Merge branch 'master' into feature/V2-公式编辑器

# Conflicts:
#	pc4mobx/hrmSalary/index.js
This commit is contained in:
黎永顺 2023-05-08 11:40:20 +08:00
commit c0b4b2eb4a
55 changed files with 3387 additions and 361 deletions

View File

@ -520,6 +520,39 @@ export const siaccountDetailCommonListSum = (params) => {
body: JSON.stringify(params)
}).then(res => res.json());
};
// 社保福利台账补缴合计接口
export const siaccountDetailSupplementaryListSum = (params) => {
return fetch("/api/bs/hrmsalary/siaccount/detail/supplementary/list/sum", {
method: "POST",
mode: "cors",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(params)
}).then(res => res.json());
};
// 社保福利台账退差合计接口
export const siaccountDetailRecessionListSum = (params) => {
return fetch("/api/bs/hrmsalary/siaccount/detail/recession/list/sum", {
method: "POST",
mode: "cors",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(params)
}).then(res => res.json());
};
// 社保福利台账补差合计接口
export const siaccountDetailBalanceListSum = (params) => {
return fetch("/api/bs/hrmsalary/siaccount/detail/balance/list/sum", {
method: "POST",
mode: "cors",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(params)
}).then(res => res.json());
};
// 导入薪资核算添加表头字段缓存
export const cacheImportField = (params) => {
return fetch("/api/bs/hrmsalary/salaryacct/acctresult/cacheImportField", {

View File

@ -43,3 +43,11 @@ export const getEncryptProgress = params => {
export const operateTaxDeclarationFunction = (params) => {
return postFetch('/api/bs/hrmsalary/sys/operateTaxDeclarationFunction', params);
}
//保存薪酬统计报表
export const reportStatisticsReportSave = (params) => {
return postFetch('/api/bs/hrmsalary/report/statistics/report/save', params);
}
//薪酬统计维度下拉列表
export const reportGetForm = params => {
return WeaTools.callApi('/api/bs/hrmsalary/report/statistics/report/getForm', 'GET', params);
}

View File

@ -0,0 +1,56 @@
import { WeaTools } from "ecCom";
import { postFetch } from "../util/request";
//薪酬统计维度下拉列表
export const dimensionGetForm = (params) => {
return WeaTools.callApi("/api/bs/hrmsalary/report/statistics/dimension/getForm", "GET", params);
};
//获取自定义统计项目表单
export const statisticsItemGetform = (params) => {
return WeaTools.callApi("/api/bs/hrmsalary/report/statistics/item/getForm", "GET", params);
};
//自定义统计项目列表
export const statisticsItemList = (params) => {
return WeaTools.callApi("/api/bs/hrmsalary/report/statistics/item/list", "GET", params);
};
// 保存薪酬统计维度
export const dimensionSave = (params) => {
return postFetch("/api/bs/hrmsalary/report/statistics/dimension/save", params);
};
// 薪酬统计维度列表
export const dimensionList = (params) => {
return postFetch("/api/bs/hrmsalary/report/statistics/dimension/list", params);
};
// 删除薪酬统计维度
export const dimensionDelete = (params) => {
return postFetch("/api/bs/hrmsalary/report/statistics/dimension/delete", params);
};
//保存薪酬统计报表
export const reportStatisticsReportList = (params) => {
return postFetch("/api/bs/hrmsalary/report/statistics/report/list", params);
};
//删除薪酬统计报表
export const reportStatisticsReportDelete = (params) => {
return postFetch("/api/bs/hrmsalary/report/statistics/report/delete", params);
};
//获取薪酬统计报表数据
export const reportStatisticsReportGetData = (params) => {
return postFetch("/api/bs/hrmsalary/report/statistics/report/getData", params);
};
//保存自定义统计项目
export const reportStatisticsItemSave = (params) => {
return postFetch("/api/bs/hrmsalary/report/statistics/item/save", params);
};
//保存数据范围及负责设置
export const reportStatisticsSaveSearchCondition = (params) => {
return postFetch("/api/bs/hrmsalary/report/statistics/report/saveSearchCondition", params);
};
//删除自定义统计项目
export const reportStatisticsItemDelete = (params) => {
return postFetch("/api/bs/hrmsalary/report/statistics/item/delete", params);
};
//获取薪酬统计报表查询条件
export const reportStatisticsGetSearchCondition = (params) => {
return WeaTools.callApi("/api/bs/hrmsalary/report/statistics/report/getSearchCondition", "GET", params);
};

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

View File

@ -32,7 +32,8 @@ import SysConfig from "./pages/sysConfig";
import RuleConfig from "./pages/ruleConfig";
import Appconfig from "./pages/appConfig";
import FieldManagement from "./pages/fieldManagement";
import EquationEditor from "./pages/equationEditor";
import AnalysisOfSalaryStatistics from "./pages/analysisOfSalaryStatistics";
import ReportView from "./pages/reportView";
import stores from "./stores";
import "./style/index";
@ -79,6 +80,8 @@ const DataAcquisition = (props) => props.children;
// sysconfig-1 规则配置
// appconfig 应用配置
// fieldManagement 字段管理
// analysisOfSalaryStatistics 薪酬统计分析
// reportView 薪酬报表查看
const Routes = (
<Route
@ -151,7 +154,8 @@ const Routes = (
<Route key="sysconfig-1" path="sysconfig-1" component={RuleConfig}/>
<Route key="appconfig" path="appconfig" component={Appconfig}/>
<Route key="fieldManagement" path="fieldManagement" component={FieldManagement}/>
<Route key="equationEditor" path="equationEditor" component={EquationEditor}/>
<Route key="analysisOfSalaryStatistics" path="analysisOfSalaryStatistics" component={AnalysisOfSalaryStatistics}/>
<Route key="reportView" path="reportView" component={ReportView}/>
</Route>
);

View File

@ -0,0 +1,101 @@
import { WeaLocaleProvider } from "ecCom";
const { getLabel } = WeaLocaleProvider;
export const condition = [
{
items: [
{
colSpan: 1,
checkbox: false,
checkboxValue: false,
conditionType: "SELECT",
domkey: ["dimType"],
fieldcol: 14,
label: getLabel(111, "维度类型"),
labelcol: 6,
options: [],
detailtype: 3,
rules: "required|string",
viewAttr: 3
},
{
colSpan: 1,
conditionType: "SELECT",
domkey: ["setting4Qualitative"],
fieldcol: 14,
label: getLabel(111, "统计维度"),
labelcol: 6,
options: [],
rules: "required|string",
viewAttr: 3
},
{
colSpan: 1,
conditionType: "INPUT",
domkey: ["dimName"],
fieldcol: 14,
label: getLabel(111, "统计维度名称"),
labelcol: 6,
value: "",
rules: "required|string",
viewAttr: 3
},
{
colSpan: 1,
conditionType: "SELECT",
domkey: ["dimCode"],
fieldcol: 14,
label: getLabel(111, "分组所属字段"),
labelcol: 6,
options: [],
viewAttr: 2,
helpfulTip: "",
hide: true
},
{
colSpan: 1,
conditionType: "TEXTAREA",
domkey: ["remark"],
fieldcol: 14,
label: getLabel(111, "描述"),
labelcol: 6,
value: "",
viewAttr: 2
}
],
title: getLabel(111, "基础设置"),
defaultshow: true
}
];
export const reportCondition = [
{
items: [
{
colSpan: 1,
conditionType: "INPUT",
domkey: ["reportName"],
fieldcol: 14,
label: getLabel(111, "报表名称"),
labelcol: 6,
value: "",
rules: "required|string",
viewAttr: 3
},
{
colSpan: 1,
conditionType: "SELECT",
domkey: ["dimensionIds"],
fieldcol: 14,
label: getLabel(111, "统计维度"),
labelcol: 6,
options: [],
rules: "required|string",
viewAttr: 3,
helpfulTip: "",
hide: true
}
],
title: "",
defaultshow: true
}
];

View File

@ -0,0 +1,205 @@
/*
* Author: 黎永顺
* name: 新增统计维度弹框
* Description:
* Date: 2023/4/11
*/
import React, { Component } from "react";
import { WeaDialog, WeaLocaleProvider, WeaSearchGroup } from "ecCom";
import { Button, message, Modal } from "antd";
import { dimensionGetForm, dimensionSave } from "../../../apis/statistics";
import { getSearchs } from "../../../util";
import GroupSpacingEditTable from "./groupSpacingEditTable";
import GroupIndividualEditTable from "./groupIndividualEditTable";
import "../index.less";
const { getLabel } = WeaLocaleProvider;
const keyObj = {
"RATION_GROUP_SPACING": "setting4RationGroupSpacing",
"RATION_GROUP_INDIVIDUAL": "setting4RationGroupIndividual"
};
class DimensionSlide extends Component {
constructor(props) {
super(props);
this.state = {
loading: false,
dimType: "QUALITATIVE",
setting4RationGroupSpacing: [],
setting4RationGroupIndividual: []
};
}
componentDidMount() {
this.props.initCondition();
}
componentWillReceiveProps(nextProps, nextContext) {
if (nextProps.visible !== this.props.visible && nextProps.formId) this.dimensionGetForm({ id: nextProps.formId });
if (nextProps.visible !== this.props.visible && !nextProps.formId) {
nextProps.form.updateFields({
dimType: "QUALITATIVE"
});
nextProps.onChangeCondition("QUALITATIVE");
}
if (nextProps.visible !== this.props.visible && !nextProps.visible) {
this.setState({
loading: false,
dimType: "QUALITATIVE",
setting4RationGroupSpacing: [],
setting4RationGroupIndividual: []
});
}
}
dimensionGetForm = (payload) => {
dimensionGetForm(payload).then(({ status, data }) => {
if (status) {
const { baseForm: { data: formData } } = data;
const setting = formData.setting ? JSON.parse(formData.setting) : {};
this.props.onChangeCondition(formData["dimType"], 1);
this.setState({
dimType: formData.dimType,
[keyObj[formData["dimType"]]]: setting
}, () => {
const fields = _.map(this.props.condition[0].items, it => {
return it.domkey[0];
});
fields.map(item => {
if (item !== "setting4Qualitative") {
this.props.form.updateFields({
[item]: formData[item] || ""
});
} else if (item === "setting4Qualitative" && formData.statsDim) {
this.props.form.updateFields({
setting4Qualitative: formData.statsDim
});
}
});
});
}
});
};
handleSave = () => {
const { dimType } = this.state;
const { condition, onCancel, formId } = this.props;
const { setting4Qualitative, dimCode, ...extraParams } = this.props.form.getFormParams();
let payload = { id: formId, ...extraParams };
if (dimType === "QUALITATIVE") {
if (!setting4Qualitative || !extraParams.dimName) {
Modal.warning({
title: getLabel(111, "信息确认"),
content: getLabel(111, "必要信息不完整,红色*为必填项!")
});
return;
}
const tjOptions = _.find(condition[0].items, item => item.domkey[0] === "setting4Qualitative").options;
const tjObj = _.find(tjOptions, item => item.key === setting4Qualitative);
payload = { ...payload, setting4Qualitative: { id: tjObj.key, name: tjObj.showname } };
} else {
if (!extraParams.dimName) {
Modal.warning({
title: getLabel(111, "信息确认"),
content: getLabel(111, "必要信息不完整,红色*为必填项!")
});
return;
}
if (dimType === "RATION_GROUP_SPACING") {
const { setting4RationGroupSpacing } = this.state;
const bool = _.every(setting4RationGroupSpacing, it => it.startValue !== "" && it.endValue !== "" && it.startValue <= it.endValue);
if (_.isEmpty(setting4RationGroupSpacing) || !bool) {
message.warning(getLabel(111, "请完善分组设置相关数据!分组设置不能为空,起始值结束值必填,且起始值需小于结束值!"));
return;
} else {
payload = {
...payload, dimCode,
setting4RationGroupSpacing: _.map(setting4RationGroupSpacing, (it, index) => ({
id: index + 1,
endValue: it.endValue,
startValue: it.startValue,
includeEnd: it.includeEnd === "1",
includeStart: it.includeStart === "1"
}))
};
}
} else if (dimType === "RATION_GROUP_INDIVIDUAL") {
const { setting4RationGroupIndividual } = this.state;
const bool = _.every(setting4RationGroupIndividual, it => it.value !== "");
if (_.isEmpty(setting4RationGroupIndividual) || !bool) {
message.warning(getLabel(111, "请完善分组设置相关数据!分组设置不能为空,且数值必填"));
return;
} else {
payload = {
...payload, dimCode,
setting4RationGroupIndividual: _.map(setting4RationGroupIndividual, (it, index) => ({ id: index + 1, ...it }))
};
}
}
}
this.setState({ loading: true });
dimensionSave(payload).then(({ status, errormsg }) => {
this.setState({ loading: false });
if (status) {
message.success(getLabel(111, "保存成功"));
onCancel(true);
this.props.form.resetForm();
} else {
message.error(errormsg || getLabel(111, "保存失败"));
}
}).catch(() => this.setState({ loading: false }));
};
formItemChange = (formObj) => {
const { onChangeCondition } = this.props;
const filedKey = _.keys(formObj)[0];
if (filedKey === "dimType") {
this.setState({
dimType: formObj[filedKey].value,
setting4RationGroupSpacing: [],
setting4RationGroupIndividual: []
}, () => onChangeCondition(formObj[filedKey].value));
}
};
handleConvertGroupDatasource = (data) => {
const { dimType } = this.state;
this.setState({ [keyObj[dimType]]: data });
};
render() {
const { loading, dimType, setting4RationGroupSpacing, setting4RationGroupIndividual } = this.state;
const { form, condition, formId } = this.props;
return (
<WeaDialog
{...this.props}
initLoadCss hasScroll
style={{ width: 900, height: 450 }}
className="dimensionSlideWrapper"
title={
<div className="dimensionTitle">
<span>{formId ? getLabel(111, "编辑统计维度") : getLabel(111, "新建统计维度")}</span>
<Button type="primary" onClick={this.handleSave} loading={loading}>{getLabel(111, "保存")}</Button>
</div>
}
>
{getSearchs(form, condition, 1, false, this.formItemChange)}
{
dimType !== "QUALITATIVE" &&
<WeaSearchGroup title={getLabel(111, "分组设置")} showGroup>
{
dimType === "RATION_GROUP_SPACING" &&
<GroupSpacingEditTable onChange={this.handleConvertGroupDatasource}
setting4RationGroupSpacing={setting4RationGroupSpacing}/>
}
{
dimType === "RATION_GROUP_INDIVIDUAL" &&
<GroupIndividualEditTable onChange={this.handleConvertGroupDatasource}
setting4RationGroupIndividual={setting4RationGroupIndividual}/>
}
</WeaSearchGroup>
}
</WeaDialog>
);
}
}
export default DimensionSlide;

View File

@ -0,0 +1,115 @@
/*
* Author: 黎永顺
* name: 统计维度管理列表
* Description:
* Date: 2023/4/11
*/
import React, { Component } from "react";
import { WeaLocaleProvider, WeaTable } from "ecCom";
import { message, Modal } from "antd";
import { dimensionDelete, dimensionList } from "../../../apis/statistics";
import "../index.less";
const { getLabel } = WeaLocaleProvider;
class DimensionTable extends Component {
constructor(props) {
super(props);
this.state = {
loading: false,
dataSource: [],
pageInfo: {
current: 1, pageSize: 10, total: 0
}
};
}
componentDidMount() {
this.dimensionList();
}
dimensionList = (extra = {}) => {
const { pageInfo } = this.state;
this.setState({ loading: true });
dimensionList({ ...pageInfo, ...extra }).then(({ status, data }) => {
this.setState({ loading: false });
if (status) {
const { pageNum: current, pageSize, total, list: dataSource } = data;
this.setState({
dataSource,
pageInfo: {
...pageInfo,
current, pageSize, total
}
});
}
}).catch(() => this.setState({ loading: false }));
};
dimensionDelete = (payload) => {
Modal.confirm({
title: getLabel(111, "信息确认"),
content: getLabel(111, "确认要删除吗?"),
onOk: () => {
dimensionDelete(payload).then(({ status, errormsg }) => {
if (status) {
message.success(getLabel(111, "删除成功"));
this.dimensionList();
} else {
message.error(errormsg || getLabel(111, "删除失败"));
}
});
}
});
};
render() {
const { dataSource, loading, pageInfo } = this.state;
const { onEdit } = this.props;
const pagination = {
...pageInfo,
showTotal: total => `${getLabel(111, "共")} ${total} ${getLabel(111, "条")}`,
showQuickJumper: true,
showSizeChanger: true,
pageSizeOptions: ["10", "20", "50", "100"],
onShowSizeChange: (current, pageSize) => {
this.setState({
pageInfo: { ...pageInfo, current, pageSize }
}, () => this.dimensionList());
},
onChange: current => {
this.setState({
pageInfo: { ...pageInfo, current }
}, () => this.dimensionList());
}
};
const columns = [
{ dataIndex: "dimName", title: getLabel(111, "统计维度") },
{ dataIndex: "remark", title: getLabel(111, "描述") },
{ dataIndex: "dimType", title: getLabel(111, "维度类型") },
{
dataIndex: "operate", title: getLabel(111, "操作"),
render: (_, record) => {
return (
<span className="space10">
<a href="javascript: void(0);" onClick={() => onEdit(record.id)}>{getLabel(111, "编辑")}</a>
<a href="javascript: void(0);"
onClick={() => this.dimensionDelete([record.id])}>{getLabel(111, "删除")}</a>
</span>
);
}
}
];
return (
<WeaTable
rowKey="id"
className="dimensionTableWrapper"
dataSource={dataSource}
pagination={pagination}
loading={loading}
columns={columns}
/>
);
}
}
export default DimensionTable;

View File

@ -0,0 +1,52 @@
/*
* Author: 黎永顺
* name: 分组设置-定量-单项式分组编辑表格
* Description:
* Date: 2023/4/12
*/
import React, { Component } from "react";
import { WeaLocaleProvider, WeaTableEdit } from "ecCom";
const { getLabel } = WeaLocaleProvider;
class GroupIndividualEditTable extends Component {
constructor(props) {
super(props);
this.state = {
dataSource: []
};
}
componentDidMount() {
const { setting4RationGroupIndividual } = this.props;
this.setState({
dataSource: setting4RationGroupIndividual
});
}
handleChangeTableData = (dataSource) => {
const { onChange } = this.props;
this.setState({ dataSource }, () => onChange(this.state.dataSource));
};
render() {
const { dataSource } = this.state;
const columns = [
{
title: getLabel(111, "分组设置值"),
dataIndex: "value",
key: "value",
com: [
{ label: "", key: "value", type: "INPUTNUMBER" }
]
}
];
return (
<WeaTableEdit
draggable={true} columns={columns} datas={dataSource}
showCopy={false} deleteConfirm onChange={this.handleChangeTableData}
/>
);
}
}
export default GroupIndividualEditTable;

View File

@ -0,0 +1,100 @@
/*
* Author: 黎永顺
* name: 分组设置-定量-组距式分组编辑表格
* Description:
* Date: 2023/4/12
*/
import React, { Component } from "react";
import { WeaLocaleProvider, WeaTableEdit } from "ecCom";
const { getLabel } = WeaLocaleProvider;
class GroupSpacingEditTable extends Component {
constructor(props) {
super(props);
this.state = {
dataSource: []
};
}
componentDidMount() {
const { setting4RationGroupSpacing } = this.props;
this.setState({
dataSource: _.map(setting4RationGroupSpacing, item => {
return {
...item,
includeStart: item.includeStart ? "1" : "0",
includeEnd: item.includeEnd ? "1" : "0"
};
})
});
}
handleChangeTableData = (dataSource) => {
const { onChange } = this.props;
this.setState({ dataSource }, () => onChange(this.state.dataSource));
};
render() {
const { dataSource } = this.state;
const columns = [
{
title: getLabel(111, "起始值"),
dataIndex: "startValue",
key: "startValue",
com: [
{ label: "", key: "startValue", type: "INPUTNUMBER" }
]
},
{
title: getLabel(111, "含"),
dataIndex: "includeStart",
key: "includeStart",
com: [
{
type: "CHECKBOX",
key: "includeStart",
otherParams: { content: getLabel(111, "含") }
}
]
},
{
title: getLabel(111, "至"),
dataIndex: "to",
key: "to",
com: [
{ label: "", type: "TEXT" }
]
},
{
title: getLabel(111, "结束值"),
dataIndex: "endValue",
key: "endValue",
com: [
{ label: "", key: "endValue", type: "INPUTNUMBER" }
]
},
{
title: getLabel(111, "含"),
dataIndex: "includeEnd",
key: "includeEnd",
com: [
{
type: "CHECKBOX",
key: "includeEnd",
otherParams: { content: getLabel(111, "含") }
}
]
}
];
return (
<WeaTableEdit
draggable={true} deleteConfirm columns={columns}
datas={_.map(dataSource, item => ({ ...item, to: getLabel(111, "至") }))}
showCopy={false} onChange={this.handleChangeTableData}
/>
);
}
}
export default GroupSpacingEditTable;

View File

@ -0,0 +1,19 @@
/*
* Author: 黎永顺
* name: 报表表单
* Description:
* Date: 2023/4/17
*/
import React, { Component } from "react";
import { getSearchs } from "../../../util";
class ReportForm extends Component {
render() {
const { form, condition } = this.props;
return (
<React.Fragment>{getSearchs(form, condition, 1, false)}</React.Fragment>
);
}
}
export default ReportForm;

View File

@ -0,0 +1,106 @@
/*
* Author: 黎永顺
* name: 统计表
* Description:
* Date: 2023/4/17
*/
import React, { Component } from "react";
import { WeaLocaleProvider } from "ecCom";
import { Button, Col, Dropdown, Menu, message, Modal, Row } from "antd";
import { reportStatisticsReportDelete, reportStatisticsReportList } from "../../../apis/statistics";
import "../index.less";
const SubMenu = Menu.SubMenu;
const { getLabel } = WeaLocaleProvider;
class ReportList extends Component {
constructor(props) {
super(props);
this.state = {
dataSource: []
};
}
componentDidMount() {
this.reportStatisticsReportList();
}
handleOptsClick = ({ key }, id, dimensionId) => {
if (key === "delete") {
this.reportStatisticsReportDelete(id.split(","));
} else if (key === "edit") {
this.props.onEdit("addReport", id);
}
};
reportStatisticsReportDelete = (payload) => {
Modal.confirm({
title: getLabel(111, "信息确认"),
content: getLabel(111, "确认删除本条数据吗?"),
onOk: () => {
const { reportName = "" } = this.props;
reportStatisticsReportDelete(payload).then(({ status, errormsg }) => {
if (status) {
message.success(getLabel(111, "删除成功"));
this.reportStatisticsReportList({ reportName });
} else {
message.error(errormsg || getLabel(111, "删除失败"));
}
});
}
});
};
reportStatisticsReportList = (payload = {}) => {
reportStatisticsReportList(payload).then(({ status, data: dataSource }) => {
if (status) {
this.setState({ dataSource });
}
});
};
/*
* Author: 黎永顺
* Description: 报表查看
* Params:
* Date: 2023/4/20
*/
handleGoReportView = (id) => {
window.open(`${window.location.origin}/spa/hrmSalary/static/index.html#/main/hrmSalary/reportView?id=${id}`);
};
render() {
const { dataSource } = this.state;
return (
<Row gutter={16} className="reportRow">
{
_.isEmpty(dataSource) ? <div className="empty">{getLabel(111, "暂无数据")}</div> :
_.map(dataSource, it => {
const { reportName, dimension, id, dimensionId } = it;
return <Col className="gutter-row" span={6} onClick={() => this.handleGoReportView(id)}>
<div className="card-item">
<div className="cardLeft"><i className="icon-coms-fa"/></div>
<div className="cardCenter">
<span className="reportName">{reportName}</span>
<div className="dimension">
<div className="label">{getLabel(111, "统计维度")}</div>
<div className="value">{dimension}</div>
</div>
</div>
<div className="cardRight">
<Dropdown overlay={
<Menu onClick={e => this.handleOptsClick(e, id, dimensionId)}>
<Menu.Item key="edit">{getLabel(111, "编辑")}</Menu.Item>
<Menu.Item key="delete">{getLabel(111, "删除")}</Menu.Item>
</Menu>
}>
<Button type="ghost"><i className="icon-coms-more"/></Button>
</Dropdown>
</div>
</div>
</Col>;
})
}
</Row>
);
}
}
export default ReportList;

View File

@ -0,0 +1,70 @@
/*
* Author: 黎永顺
* name: 统计弹框
* Description:
* Date: 2023/4/10
*/
import React, { Component } from "react";
import { Button, message, Modal } from "antd";
import { WeaDialog, WeaLocaleProvider } from "ecCom";
import { reportStatisticsReportSave } from "../../../apis/ruleconfig";
import "../index.less";
const { getLabel } = WeaLocaleProvider;
class StatisticsModal extends Component {
constructor(props) {
super(props);
this.state = {
loading: false
};
}
handleSaveReportList = () => {
const { form, id, onCancel } = this.props;
form.validateForm().then(f => {
if (f.isValid) {
const { dimensionIds, reportName } = form.getFormParams();
const payload = { id, reportName, dimensionIds: dimensionIds.split(",") };
this.setState({ loading: true });
reportStatisticsReportSave(payload).then(({ status, errormsg }) => {
this.setState({ loading: false });
if (status) {
onCancel(true);
message.success(getLabel(111, "保存成功"));
form.resetForm();
} else {
message.error(errormsg || getLabel(111, "保存失败"));
}
}).catch(() => this.setState({ loading: false }));
} else {
Modal.warning({
title: getLabel(111, "信息确认"),
content: getLabel(111, "必要信息不完整,红色*为必填项!")
});
}
});
};
render() {
const { loading } = this.state;
const { typeKey, onCancel } = this.props;
const buttons = typeKey === "addReport" ? [
<Button type="primary" onClick={this.handleSaveReportList} loading={loading}>{getLabel(111, "保存")}</Button>
] : [];
return (
<WeaDialog
{...this.props} hasScroll
style={typeKey === "addReport" ? { width: 600 } : { width: 640, height: 540 }}
buttons={buttons}
onCancel={onCancel}
initLoadCss
className="dimensionModalWrapper"
>
{this.props.children}
</WeaDialog>
);
}
}
export default StatisticsModal;

View File

@ -0,0 +1,296 @@
/*
* Author: 黎永顺
* name: 薪酬统计分析
* Description:
* Date: 2023/4/10
*/
import React, { Component } from "react";
import { inject, observer } from "mobx-react";
import { WeaInputSearch, WeaLocaleProvider, WeaReqTop } from "ecCom";
import { Button } from "antd";
import { condition, reportCondition } from "./components/conditions";
import { commonEnumList, reportGetForm } from "../../apis/ruleconfig";
import { dimensionGetForm } from "../../apis/statistics";
import StatisticsModal from "./components/statisticsModal";
import DimensionSlide from "./components/dimensionSlide";
import DimensionTable from "./components/dimensionTable";
import ReportList from "./components/reportList";
import ReportForm from "./components/reportForm";
import "./index.less";
const { getLabel } = WeaLocaleProvider;
@inject("taxAgentStore", "attendanceStore")
@observer
class Index extends Component {
constructor(props) {
super(props);
this.state = {
conditions: [],
convertConditions: [],
reportConditions: [],
selectedKey: "statistics",
reportName: "",
slideReq: {
visible: false, formId: ""
},
modalReq: {
title: "", visible: false,
typeKey: "", id: ""
}
};
}
componentDidMount() {
this.initReportFormCondition();
}
initReportFormCondition = (payload = {}) => {
const { attendanceStore: { reportForm } } = this.props;
reportGetForm(payload).then(({ status, data }) => {
if (status) {
const { statsDimOptions, data: detailData } = data;
if (_.isEmpty(payload)) {
this.setState({
reportConditions: _.map(reportCondition, item => {
return {
...item,
items: _.map(item.items, child => {
if (child.domkey[0] === "dimensionIds") {
return {
...child,
options: _.map(statsDimOptions, dimTypeItem => ({
key: dimTypeItem.id,
showname: dimTypeItem.content
}))
};
}
return { ...child };
})
};
})
}, () => {
reportForm.initFormFields(this.state.reportConditions);
});
} else {
reportForm.updateFields({
reportName: detailData.reportName,
dimensionIds: detailData.dimension.join(",")
});
}
}
});
};
initCondition = async () => {
const { attendanceStore: { statisticsForm } } = this.props;
const [dimTypeEnum, dimCodeList] = await Promise.all([this.commonEnumList(), this.dimensionGetForm()]);
const { data: dimTypeData } = dimTypeEnum, { data: dimCodeData } = dimCodeList;
const { baseForm: { statsDimOptions, groupDimOptions, data: dimTypeValue } } = dimCodeData;
this.setState({
conditions: _.map(condition, item => {
return {
...item,
items: _.map(item.items, child => {
if (child.domkey[0] === "dimType") {
return {
...child,
value: dimTypeValue.dimType,
options: _.map(dimTypeData, dimTypeItem => ({
key: dimTypeItem.value,
showname: dimTypeItem.defaultLabel
}))
};
}
if (child.domkey[0] === "setting4Qualitative") {
return {
...child,
options: _.map(statsDimOptions, dimCodeItem => ({
key: dimCodeItem.id,
showname: dimCodeItem.content
}))
};
}
if (child.domkey[0] === "dimCode") {
return {
...child,
options: _.map(groupDimOptions, dimCodeItem => ({
key: dimCodeItem.id,
showname: dimCodeItem.content
}))
};
}
return { ...child };
})
};
})
}, () => {
this.setState({ convertConditions: this.state.conditions });
statisticsForm.initFormFields(this.state.conditions);
});
};
commonEnumList = () => {
const payload = {
enumClass: "com.engine.salary.report.enums.SalaryStatisticsDimensionTypeEnum"
};
return commonEnumList(payload);
};
dimensionGetForm = () => {
return dimensionGetForm();
};
handleChangeCondition = (val, viewAttr) => {
const { attendanceStore: { statisticsForm } } = this.props;
const helpfulTitle = val === "RATION_GROUP_SPACING" ?
"例:\n" +
" 若所属字段为【工龄】分组设置为【0-5】【5-10】统计项为【税前薪资】对应的统计规则为【求和】 则统计结果为【工龄】为【0-5】的所有人的【税前薪资】求和【工龄】为【5-10】的所有人的【税前薪资】求和\n" +
"若未选择所属字段分组设置为【0-10,000.00】【10,000.00-20,000.00】;若统计项为【税前薪资】,对应的统计规则为【计数】; 则统计结果为【税前薪资】为【0-10,000.00】有多少人【税前薪资】为【10,000.00-20,000.00】有多少人;" :
val === "RATION_GROUP_INDIVIDUAL" ?
"例:\n" +
" 若所属字段为【职级】分组设置为【1】【2】【3】统计项为【税前薪资】对应的统计规则为【平均值】 则统计结果为【职级】为【1】的所有人的【税前薪资】的平均值【职级】为【2】的所有人的【税前薪资】的平均值【职级】为【3】的所有人的【税前薪资】的平均值\n" +
"若未选择所属字段分组设置为【1】【2】【3】若统计项为【绩效】对应的统计规则为【计数】 则统计结果为【绩效】为【1】有多少人绩效为【2】有多少人绩效为【3】有多少人" : "";
if (val === "QUALITATIVE") {
this.setState({
conditions: _.map(this.state.convertConditions, item => {
return {
...item,
items: _.map(_.filter(item.items, child => child.domkey[0] !== "dimCode"), it => {
if (it.domkey[0] === "dimType") {
return { ...it, value: val, viewAttr: viewAttr ? viewAttr : it.viewAttr };
}
return { ...it };
})
};
})
}, () => {
statisticsForm.setCondition(this.state.conditions);
});
} else {
this.setState({
conditions: _.map(this.state.convertConditions, item => {
return {
...item,
items: _.map(_.filter(item.items, child => child.domkey[0] !== "setting4Qualitative"), it => {
if (it.domkey[0] === "dimType") {
return { ...it, value: val, viewAttr: viewAttr ? viewAttr : it.viewAttr };
} else if (it.domkey[0] === "dimCode") {
return { ...it, helpfulTitle };
}
return { ...it };
})
};
})
}, () => {
statisticsForm.setCondition(this.state.conditions);
});
}
};
handleReqBtnsClick = (key, id = "") => {
if (key === "search") {
const { reportName } = this.state;
this.reportListRef.reportStatisticsReportList({ reportName });
} else {
const { modalReq } = this.state;
const title = key === "dimension" ?
<div className="dimensionTitle">
<span>{getLabel(111, "统计维度管理")}</span>
<Button type="primary" onClick={() => this.handleAddDimension()}>{getLabel(111, "新建统计维度")}</Button>
</div>
: getLabel(111, id ? "编辑报表" : "新建报表");
this.setState({
modalReq: {
...modalReq, id, title,
visible: true, typeKey: key
}
}, () => id && this.initReportFormCondition({ id }));
}
};
handleCancel = (refresh = false) => {
const { attendanceStore: { reportForm } } = this.props;
const { modalReq } = this.state;
this.setState({
modalReq: {
...modalReq, visible: false, id: ""
}
}, () => {
const { selectedKey, reportName } = this.state;
selectedKey === "statistics" && reportForm.resetForm();
refresh && selectedKey === "statistics" && this.reportListRef.reportStatisticsReportList({ reportName });
});
};
handleAddDimension = (formId = "") => {
const { slideReq } = this.state;
this.setState({
slideReq: {
...slideReq, visible: true,
formId
}
});
};
handleClose = (initTable = false) => {
const { attendanceStore: { statisticsForm } } = this.props;
const { slideReq } = this.state;
this.setState({
slideReq: {
...slideReq, visible: false, formId: ""
}
}, () => {
statisticsForm.resetForm();
initTable && this.dimensionTableRef.dimensionList();
});
};
render() {
const { taxAgentStore: { statisticsReportBtn }, attendanceStore: { statisticsForm, reportForm } } = this.props;
const { selectedKey, modalReq, slideReq, conditions, reportConditions, reportName } = this.state;
const buttons = [
<Button type="primary" onClick={() => this.handleReqBtnsClick("addReport")}>{getLabel(111, "新建报表")}</Button>,
<Button type="ghost"
onClick={() => this.handleReqBtnsClick("dimension")}>{getLabel(111, "维度统计管理")}</Button>,
<WeaInputSearch placeholder={getLabel(111, "请输入报表名称")} className="search"
value={reportName}
onChange={reportName => this.setState({ reportName })}
onSearch={() => this.handleReqBtnsClick("search")}/>
];
const tabs = [
{ key: "statistics", title: getLabel(111, "统计表") }
// { key: "detail", title: getLabel(111, "员工明细") }
];
return (
<WeaReqTop
title={getLabel(111, "薪酬统计报表")} icon={<i className="icon-coms-fa"/>}
iconBgcolor="#F14A2D" buttons={!statisticsReportBtn ? buttons.slice(-1) : buttons} buttonSpace={10}
showDropIcon={false} tabDatas={tabs} className="xc_tj_fx_wrapper"
selectedKey={selectedKey}
onChange={selectedKey => this.setState({ selectedKey }, () => this.state.selectedKey === "statistics" && this.initReportFormCondition())}
>
{
this.state.selectedKey === "statistics" &&
<ReportList
ref={dom => this.reportListRef = dom}
reportName={reportName}
onEdit={this.handleReqBtnsClick}
/>
}
<StatisticsModal {...modalReq} onCancel={this.handleCancel} form={reportForm}>
{
modalReq.typeKey === "dimension" &&
<DimensionTable ref={dom => this.dimensionTableRef = dom}
onEdit={id => this.handleAddDimension(id)}
/>
}
{
modalReq.typeKey === "addReport" &&
<ReportForm form={reportForm} condition={reportConditions}/>
}
</StatisticsModal>
<DimensionSlide
{...slideReq} onCancel={this.handleClose}
form={statisticsForm} condition={conditions}
initCondition={this.initCondition} onChangeCondition={this.handleChangeCondition}
/>
</WeaReqTop>
);
}
}
export default Index;

View File

@ -0,0 +1,141 @@
.xc_tj_fx_wrapper {
.search {
top: -3px;
margin-right: 10px;
width: 220px;
}
.wea-new-top-req-content {
background: #FFF;
.reportRow {
padding: 16px;
.gutter-row {
margin-bottom: 16px;
border-radius: 6px;
.card-item {
border-radius: 6px;
display: flex;
height: 90px;
justify-content: space-between;
padding: 22px 0 22px 16px;
border: 1px solid #e5e5e5;
.cardLeft {
display: flex;
align-items: center;
justify-content: center;
i {
padding: 10px;
color: #FFF;
font-size: 20px;
border-radius: 50%;
background-color: #ff666a;
}
}
.cardCenter {
display: flex;
flex: 1;
flex-direction: column;
justify-content: space-between;
margin-left: 10px;
.reportName {
font-size: 14px;
color: #111;
font-weight: 600;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.dimension {
display: flex;
.label {
height: 12px;
font-size: 12px;
color: #999;
line-height: 12px;
font-weight: 400;
}
.value {
height: 12px;
font-size: 12px;
color: #111;
line-height: 12px;
font-weight: 400;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}
}
.cardRight {
display: flex;
align-items: center;
justify-content: center;
.ant-btn-ghost {
color: #999;
border: 1px solid transparent;
}
.ant-btn-ghost:focus, .ant-btn-ghost:hover,
.ant-btn-ghost.active, .ant-btn-ghost:active {
color: #2baee9;
background-color: #FFF;
border: 1px solid #e5e5e5;
}
}
}
}
.card-item:hover {
cursor: pointer;
box-shadow: 0 3px 12px 0 rgba(0, 0, 0, .12);
}
}
.empty {
font-size: 16px;
width: 100%;
text-align: center;
margin-top: 26px;
}
}
}
//统计维度弹框
.dimensionModalWrapper, .dimensionSlideWrapper {
.dimensionTitle {
width: 100%;
display: flex;
align-items: center;
justify-content: space-between;
}
.dimensionTableWrapper {
.space10 {
a:first-child {
margin-right: 10px;
}
}
}
}
.dimensionSlideWrapper, .dimensionModalWrapper {
.wea-search-group {
.wea-select, .ant-select, .ant-select-selection {
width: 100%;
}
}
}

View File

@ -109,7 +109,10 @@ export default class SelectFieldModal extends React.Component {
// 添加按钮点击回调
handleAddClick = async () => {
const { status } = await this.cacheImportField();
//薪资核算详情页面的导入表单字段缓存功能
if (window.location.hash.indexOf("calculateDetail") !== -1) {
const { status } = await this.cacheImportField();
}
this.props.onAdd(this.fieldData);
this.props.onCancel();
};

View File

@ -1,7 +1,7 @@
import React from "react";
import ImportModal from "../../components/importModal";
import { inject, observer } from "mobx-react";
import { getQueryString } from "../../util/url";
import { convertToUrlString, getQueryString } from "../../util/url";
@inject("calculateStore", "standingBookStore")
@observer
@ -35,7 +35,12 @@ export default class CompareDetailImportModal extends React.Component {
if (this.props.id) {
url = "/api/bs/hrmsalary/salaryacct/comparisonresult/importtemplate/export?salaryAcctRecordId=" + this.props.id;
} else {
url = `/api/bs/hrmsalary/siaccount/comparisonwelfare/importtemplate/export`;
const payload = {
billMonth: getQueryString("billMonth"),
paymentOrganization: getQueryString("paymentOrganization"),
paymentStatus: 0
};
url = `/api/bs/hrmsalary/siaccount/comparisonwelfare/importtemplate/export?${convertToUrlString(payload)}`;
}
window.open(url);
}

View File

@ -4,7 +4,7 @@ import { inject, observer } from "mobx-react";
import SalaryDetail from "./salaryDetail";
import { Button, Dropdown, Menu, message, Modal } from "antd";
import { WeaBrowser, WeaCheckbox, WeaDropdown, WeaFormItem, WeaInput, WeaSearchGroup, WeaSelect, WeaTab } from "ecCom";
import { getQueryString } from "../../util/url";
import { convertToUrlString, getQueryString } from "../../util/url";
import AcctResultImportModal from "./acctResult/importModal/acctResultImportModal";
import ProgressModal from "../../components/progressModal";
@ -172,7 +172,7 @@ export default class CalculateDetail extends React.Component {
url: "/api/bs/hrmsalary/salaryacct/acctresult/list",
selectedRowKeys: [],
queryParams: {
salaryAcctRecordId,
salaryAcctRecordId
}
};
childFrameObj.contentWindow.postMessage(JSON.stringify(payload), "*");
@ -208,8 +208,11 @@ export default class CalculateDetail extends React.Component {
this.id
);
} else if (e.key == "3") {
const { searchItemsValue } = this.state;
const { consolidatedTaxation, ...extra } = searchItemsValue;
const payload = { ...extra, consolidatedTaxation: consolidatedTaxation === "0" ? "" : consolidatedTaxation };
window.open(
"/api/bs/hrmsalary/salaryacct/acctresult/export?salaryAcctRecordId=" + this.id + "&ids="
`/api/bs/hrmsalary/salaryacct/acctresult/export?salaryAcctRecordId=${this.id}&ids=&${convertToUrlString(payload)}`
);
}
};

View File

@ -56,17 +56,17 @@ class Index extends Component {
};
handleChangeSalaryMonth = (salaryMonth) => this.setState({ salaryMonth }, () => this.attendanceTableRef.getAttendanceList({ salaryYearMonth: _.compact(this.state.salaryMonth) }));
handleAddAttendFileds = () => this.fieldMangRef.handleTriggerAttendFileds();
handleImportAttendanceData= ()=>{
handleImportAttendanceData = () => {
this.attendanceTableRef.handleImportAttendanceData({
visiable: true, params: {}, step: 0,
columns: [], slideDataSource: [], importResult: []
});
}
handleQuoteAttendanceData= ()=>{
};
handleQuoteAttendanceData = () => {
this.attendanceTableRef.handleQuoteAttendanceData({
visible: true, title: "引用考勤数据"
});
}
};
render() {
const { selectedKey, salaryMonth, fieldName } = this.state;
@ -82,7 +82,7 @@ class Index extends Component {
return (
<div className="attendanceRefWrapper">
<WeaTab
datas={topTab} keyParam="viewcondition" selectedKey={selectedKey} buttons={buttons}
datas={topTab} keyParam="viewcondition" selectedKey={selectedKey} buttons={showOperateBtn ? buttons : []}
searchType={selectedKey === "FIELD" ? ["base"] : []} searchsBasePlaceHolder="请输入字段名称"
onChange={v => this.setState({ selectedKey: v })}
searchsBaseValue={fieldName} onSearchChange={fieldName => this.setState({ fieldName })}

View File

@ -19,6 +19,7 @@ import ImportFormCom from "./components/importFormCom";
import TableRecord from "../components/tableRecord";
import { dataCollectCondition, modalColumns } from "./columns";
import { removePropertyCondition } from "../../../util/response";
import { convertToUrlString } from "../../../util/url";
import Layout from "../layout";
import moment from "moment";
@ -52,6 +53,7 @@ class Index extends Component {
slideDataSource: []
},
exportPayloadUrl: "",
exportPayloadType: false,
advanceCondition: null
};
this.tableRef = null;
@ -160,9 +162,11 @@ class Index extends Component {
* Date: 2023/2/20
*/
handleExportAll = () => {
const { declareMonth, taxAgentId } = this.state;
const { cumDeductStore: { form } } = this.props;
const { declareMonth, taxAgentId, exportPayloadType } = this.state;
this.setState({
exportPayloadUrl: `${window.location.origin}/api/bs/hrmsalary/addUpDeduction/export?ids=&declareMonth=${declareMonth}&taxAgentId=${taxAgentId}`
exportPayloadType: !exportPayloadType,
exportPayloadUrl: `${window.location.origin}/api/bs/hrmsalary/addUpDeduction/export?ids=&declareMonth=${declareMonth}&taxAgentId=${taxAgentId}&${convertToUrlString(form.getFormParams())}`
});
};
/*
@ -173,12 +177,13 @@ class Index extends Component {
*/
handleExportSelect = () => {
const { selectedRowKeys: ids } = this.tableRef.state;
const { declareMonth, taxAgentId } = this.state;
const { declareMonth, taxAgentId, exportPayloadType } = this.state;
if (ids.length === 0) {
message.warning("请选择需要导出的数据");
return;
}
this.setState({
exportPayloadType: !exportPayloadType,
exportPayloadUrl: `${window.location.origin}/api/bs/hrmsalary/addUpDeduction/export?ids=${ids.join(",")}&declareMonth=${declareMonth}&taxAgentId=${taxAgentId}`
});
};
@ -497,7 +502,7 @@ class Index extends Component {
const { taxAgentStore: { showOperateBtn }, cumDeductStore: { form } } = this.props;
const {
declareMonth, taxAgentId, slidePayload, saveLoading, exportPayloadUrl, advanceCondition,
importPayload
importPayload, exportPayloadType
} = this.state;
const tablePayload = { declareMonth: [declareMonth], taxAgentId };
return (
@ -505,6 +510,7 @@ class Index extends Component {
onResizeWindowInnerWidth={this.handleResize} slidePayload={slidePayload}
onClose={this.handleCloseSlide} onSave={this.handleSaveData}
slideLoading={saveLoading} exportPayloadUrl={exportPayloadUrl}
exportPayloadType={exportPayloadType}
form={form} condition={advanceCondition} onAdSearch={this.handleAdSearch}
onImportSetStep={this.handleImportSetStep} onCancel={this.handleCloseImport}
importPayload={importPayload} onImportFile={this.handleImportFile}

View File

@ -28,6 +28,7 @@ import { dataCollectCondition, taxOptions } from "./columns";
import AddItems from "../addItems";
import TableRecord from "../components/tableRecord";
import { situationModalColumns } from "../cumDeduct/columns";
import { convertToUrlString } from "../../../util/url";
@inject("taxAgentStore", "cumSituationStore")
@observer
@ -59,6 +60,7 @@ class Index extends Component {
slideDataSource: []
},
exportPayloadUrl: "",
exportPayloadType: false,
advanceCondition: null
};
this.tableRef = null;
@ -277,9 +279,11 @@ class Index extends Component {
* Date: 2023/2/20
*/
handleExportAll = () => {
const { declareMonth, taxAgentId, year } = this.state;
const { cumSituationStore: { form } } = this.props;
const { declareMonth, taxAgentId, year, exportPayloadType } = this.state;
this.setState({
exportPayloadUrl: `${window.location.origin}/api/bs/hrmsalary/addUpSituation/export?ids=&year=${year}&taxYearMonth=${year}-${declareMonth}&taxAgentId=${taxAgentId}`
exportPayloadType: !exportPayloadType,
exportPayloadUrl: `${window.location.origin}/api/bs/hrmsalary/addUpSituation/export?ids=&year=${year}&taxYearMonth=${year}-${declareMonth}&taxAgentId=${taxAgentId}&${convertToUrlString(form.getFormParams())}`
});
};
/*
@ -290,12 +294,13 @@ class Index extends Component {
*/
handleExportSelect = () => {
const { selectedRowKeys: ids } = this.tableRef.state;
const { declareMonth, taxAgentId, year } = this.state;
const { declareMonth, taxAgentId, year, exportPayloadType } = this.state;
if (ids.length === 0) {
message.warning("请选择需要导出的数据");
return;
}
this.setState({
exportPayloadType: !exportPayloadType,
exportPayloadUrl: `${window.location.origin}/api/bs/hrmsalary/addUpSituation/export?ids=${ids.join(",")}&year=${year}&taxYearMonth=${year}-${declareMonth}&taxAgentId=${taxAgentId}`
});
};
@ -511,7 +516,7 @@ class Index extends Component {
const { taxAgentStore: { showOperateBtn }, cumSituationStore: { form } } = this.props;
const {
declareMonth, taxAgentId, slidePayload, saveLoading, exportPayloadUrl, advanceCondition,
importPayload, year
importPayload, year, exportPayloadType
} = this.state;
const tablePayload = { taxYearMonth: `${year}-${declareMonth}`, year, taxAgentId };
return (
@ -519,6 +524,7 @@ class Index extends Component {
onResizeWindowInnerWidth={this.handleResize} slidePayload={slidePayload}
onClose={this.handleCloseSlide} onSave={this.handleSaveData}
slideLoading={saveLoading} exportPayloadUrl={exportPayloadUrl}
exportPayloadType={exportPayloadType}
form={form} condition={advanceCondition} onAdSearch={this.handleAdSearch}
onImportSetStep={this.handleImportSetStep} onCancel={this.handleCloseImport}
importPayload={{ ...importPayload, importOpts: { taxYearMonth: importPayload.importOpts.declareMonth } }}

View File

@ -154,7 +154,7 @@ class DataTables extends Component {
dataSource={dataSource}
pagination={pagination}
loading={loading.query}
xWidth={getColumns.length * 120}
xWidth={getColumns.length * 150}
/>;
}
}

View File

@ -30,7 +30,7 @@ class Layout extends Component {
}
componentWillReceiveProps(nextProps, nextContext) {
if (nextProps.exportPayloadUrl !== this.props.exportPayloadUrl) {
if (nextProps.exportPayloadType !== this.props.exportPayloadType) {
/*
* Author: 黎永顺
* Description:导出数据采集数据

View File

@ -103,6 +103,15 @@ export const dataCollectCondition = [
labelcol: 8,
value: "",
viewAttr: 2
},
{
conditionType: "INPUT",
domkey: ["privatePension"],
fieldcol: 14,
label: "个人养老金",
labelcol: 8,
value: "",
viewAttr: 2
}
],
title: "数据采集",

View File

@ -29,6 +29,7 @@ import { dataCollectCondition } from "./columns";
import AddItems from "../addItems";
import TableRecord from "../components/tableRecord";
import { otherModalColumns } from "../cumDeduct/columns";
import { convertToUrlString } from "../../../util/url";
@inject("taxAgentStore", "otherDeductStore")
@observer
@ -59,6 +60,7 @@ class Index extends Component {
slideDataSource: []
},
exportPayloadUrl: "",
exportPayloadType: false,
advanceCondition: null
};
this.tableRef = null;
@ -250,9 +252,11 @@ class Index extends Component {
* Date: 2023/2/20
*/
handleExportAll = () => {
const { declareMonth, taxAgentId } = this.state;
const { otherDeductStore: { form } } = this.props;
const { declareMonth, taxAgentId, exportPayloadType } = this.state;
this.setState({
exportPayloadUrl: `${window.location.origin}/api/bs/hrmsalary/otherDeduction/export?ids=&declareMonth=${declareMonth}&taxAgentId=${taxAgentId}`
exportPayloadType: !exportPayloadType,
exportPayloadUrl: `${window.location.origin}/api/bs/hrmsalary/otherDeduction/export?ids=&declareMonth=${declareMonth}&taxAgentId=${taxAgentId}&${convertToUrlString(form.getFormParams())}`
});
};
/*
@ -263,12 +267,13 @@ class Index extends Component {
*/
handleExportSelect = () => {
const { selectedRowKeys: ids } = this.tableRef.state;
const { declareMonth, taxAgentId } = this.state;
const { declareMonth, taxAgentId, exportPayloadType } = this.state;
if (ids.length === 0) {
message.warning("请选择需要导出的数据");
return;
}
this.setState({
exportPayloadType: !exportPayloadType,
exportPayloadUrl: `${window.location.origin}/api/bs/hrmsalary/otherDeduction/export?ids=${ids.join(",")}&declareMonth=${declareMonth}&taxAgentId=${taxAgentId}`
});
};
@ -504,7 +509,7 @@ class Index extends Component {
const { taxAgentStore: { showOperateBtn }, otherDeductStore: { form } } = this.props;
const {
declareMonth, taxAgentId, slidePayload, saveLoading, exportPayloadUrl, advanceCondition,
importPayload
importPayload, exportPayloadType
} = this.state;
const tablePayload = { declareMonth: [declareMonth], taxAgentId };
return (
@ -512,6 +517,7 @@ class Index extends Component {
onResizeWindowInnerWidth={this.handleResize} slidePayload={slidePayload}
onClose={this.handleCloseSlide} onSave={this.handleSaveData}
slideLoading={saveLoading} exportPayloadUrl={exportPayloadUrl}
exportPayloadType={exportPayloadType}
form={form} condition={advanceCondition} onAdSearch={this.handleAdSearch}
onImportSetStep={this.handleImportSetStep} onCancel={this.handleCloseImport}
importPayload={importPayload} onImportFile={this.handleImportFile}

View File

@ -21,6 +21,7 @@ import { condition } from "./components/condition";
import AddItems from "../addItems";
import TableRecord from "../components/tableRecord";
import { specialModalColumns } from "../cumDeduct/columns";
import { convertToUrlString } from "../../../util/url";
@inject("taxAgentStore", "specialAddStore")
@observer
@ -49,6 +50,7 @@ class Index extends Component {
slideDataSource: []
},
exportPayloadUrl: "",
exportPayloadType: false,
advanceCondition: null
};
this.tableRef = null;
@ -207,9 +209,11 @@ class Index extends Component {
* Date: 2023/2/20
*/
handleExportAll = () => {
const { taxAgentId } = this.state;
const { specialAddStore: { advanceForm } } = this.props;
const { taxAgentId, exportPayloadType } = this.state;
this.setState({
exportPayloadUrl: `${window.location.origin}/api/bs/hrmsalary/specialAddDeduction/export?ids=&taxAgentId=${taxAgentId}`
exportPayloadType: !exportPayloadType,
exportPayloadUrl: `${window.location.origin}/api/bs/hrmsalary/specialAddDeduction/export?ids=&taxAgentId=${taxAgentId}&${convertToUrlString(advanceForm.getFormParams())}`
});
};
/*
@ -220,12 +224,13 @@ class Index extends Component {
*/
handleExportSelect = () => {
const { selectedRowKeys: ids } = this.tableRef.state;
const { taxAgentId } = this.state;
const { taxAgentId, exportPayloadType } = this.state;
if (ids.length === 0) {
message.warning("请选择需要导出的数据");
return;
}
this.setState({
exportPayloadType: !exportPayloadType,
exportPayloadUrl: `${window.location.origin}/api/bs/hrmsalary/specialAddDeduction/export?ids=${ids.join(",")}&taxAgentId=${taxAgentId}`
});
};
@ -414,7 +419,8 @@ class Index extends Component {
render() {
const { taxAgentStore: { showOperateBtn }, specialAddStore: { advanceForm } } = this.props;
const {
taxAgentId, slidePayload, saveLoading, exportPayloadUrl, advanceCondition, importPayload
taxAgentId, slidePayload, saveLoading, exportPayloadUrl, advanceCondition, importPayload,
exportPayloadType
} = this.state;
const tablePayload = { taxAgentId };
return (
@ -422,6 +428,7 @@ class Index extends Component {
onResizeWindowInnerWidth={this.handleResize} slidePayload={slidePayload}
onClose={this.handleCloseSlide} onSave={this.handleSaveData}
slideLoading={saveLoading} exportPayloadUrl={exportPayloadUrl}
exportPayloadType={exportPayloadType}
form={advanceForm} condition={advanceCondition} onAdSearch={this.handleAdSearch}
onImportSetStep={this.handleImportSetStep} onCancel={this.handleCloseImport}
importPayload={importPayload} onImportFile={this.handleImportFile}

View File

@ -232,17 +232,17 @@ class FieldSlide extends Component {
{/* />*/}
{/* </WeaFormItem>*/}
{/*}*/}
<WeaFormItem label="默认使用" labelCol={{ span: 6 }} wrapperCol={{ span: 12 }}>
<WeaCheckbox
value={useDefault}
display="switch"
onChange={value => this.handleChangeFields("useDefault", value)}
/>
<WeaHelpfulTip style={{ marginLeft: "10px" }}
title="提示:开启后,每个薪资方案都有该薪资项目,可在具体薪资方案中删除"
placement="topLeft"
/>
</WeaFormItem>
{/*<WeaFormItem label="默认使用" labelCol={{ span: 6 }} wrapperCol={{ span: 12 }}>*/}
{/* <WeaCheckbox*/}
{/* value={useDefault}*/}
{/* display="switch"*/}
{/* onChange={value => this.handleChangeFields("useDefault", value)}*/}
{/* />*/}
{/* <WeaHelpfulTip style={{ marginLeft: "10px" }}*/}
{/* title="提示:开启后,每个薪资方案都有该薪资项目,可在具体薪资方案中删除"*/}
{/* placement="topLeft"*/}
{/* />*/}
{/*</WeaFormItem>*/}
<WeaFormItem label="可见性" labelCol={{ span: 6 }} wrapperCol={{ span: 12 }}>
<WeaSelect
value={sharedType}

View File

@ -8,10 +8,16 @@ import React, { Component } from "react";
import { WeaCheckbox, WeaFormItem, WeaHelpfulTip, WeaInput, WeaSelect, WeaTextarea } from "ecCom";
import { Col, Row } from "antd";
import { inject, observer } from "mobx-react";
import {toJS} from 'mobx';
import { baseSettingFormItem } from "../config";
import { getLedgerBasicForm } from "../../../apis/ledger";
import { getAddMonthYearMonth, getCurrentYearMonth, getSubtractMonthYearMonth } from "../../../util/date";
import {
generateBasicInfo,
getAddMonthYearMonth,
getCurrentYearMonth,
getMonthDays,
getSubtractMonthYearMonth,
prefixAddZero
} from "../../../util/date";
import { commonEnumList } from "../../../apis/ruleconfig";
import moment from "moment";
import "./index.less";
@ -206,9 +212,8 @@ export default LedgerBaseSetting;
const CustomSelect = (props) => {
const { list, baseInfo, onChange, inputStr } = props;
const { salaryCycleType, salaryCycleFromDay, attendCycleType, attendCycleFromDay, canEdit } = baseInfo;
const salaryCycleStrObj = initPeriodStr("inputStr", salaryCycleType, salaryCycleFromDay);
const attendCycleStrObj = initPeriodStr("inputStr", attendCycleType, attendCycleFromDay);
const { canEdit } = baseInfo;
const selectInfo = buildEditBasicInfo(baseInfo);
return <Row gutter={10} key={inputStr}>
{
_.map(list, item => {
@ -221,20 +226,12 @@ const CustomSelect = (props) => {
})
}
<Col span={12}
className="desc">{inputStr === "salaryCycleStrObj" ? salaryCycleStrObj.inputStr : attendCycleStrObj.inputStr}</Col>
className="desc">{inputStr === "salaryCycleStrObj" ? selectInfo.salaryCycleInfo.salaryPeriodTip : selectInfo.attendCycleInfo.attendancePeriodTip}</Col>
</Row>;
};
const MonthCycleDesc = (props) => {
const {
taxCycleType,
socialSecurityCycleType,
salaryCycleFromDay,
salaryCycleType,
attendCycleType,
attendCycleFromDay
} = props;
const salaryCycleStrObj = initPeriodStr("salaryCycleStr", salaryCycleType, salaryCycleFromDay);
const attendCycleStrObj = initPeriodStr("attendCycleStr", attendCycleType, attendCycleFromDay);
const { taxCycleType, socialSecurityCycleType } = props;
const selectInfo = buildEditBasicInfo({ ...props });
return <div className="baseSettingRight">
<div className="title">月份周期说明</div>
<div className="descContent">
@ -245,28 +242,131 @@ const MonthCycleDesc = (props) => {
<div>根据您当前的选择相应的周期为</div>
<div className="descTitle">薪资周期</div>
<div>
<span className="notice">{getStartDate(salaryCycleType, salaryCycleFromDay)}</span>
<span className="notice">{salaryCycleStrObj.date}</span>
<span className="notice">{selectInfo.salaryCycleInfo.salaryPeriodStart}</span>
<span className="notice">{selectInfo.salaryCycleInfo.salaryPeriodEnd}</span>
</div>
<div className="descTitle">税款所属期</div>
<div className="notice">{getMonth(taxCycleType)}</div>
<div className="descTitle">考勤取值周期</div>
<div>
<span className="notice">{getStartDate(attendCycleType, attendCycleFromDay)}</span>
<span className="notice">{attendCycleStrObj.date}</span>
<span className="notice">{selectInfo.attendCycleInfo.attendancePeriodStart}</span>
<span className="notice">{selectInfo.attendCycleInfo.attendancePeriodEnd}</span>
</div>
<div className="descTitle">福利台账月份</div>
<div>引用<span className="notice">{getMonth(socialSecurityCycleType)}</span></div>
</div>
</div>;
};
// 获取开始日期
const getStartDate = (salaryCycleType, day) => {
day = Number(day);
return getMonth(salaryCycleType) + "-" + (day < 10 ? "0" + day : day);
const buildEditBasicInfo = (editBasicInfo) => {
const { attendCycleType, salaryCycleType } = editBasicInfo;
const now = new Date();
let nowYear = now.getFullYear();
let nowMonth = now.getMonth() + 1;
let tmpV = {};
// 薪资联动
switch (salaryCycleType) {
case "1" :
tmpV["salaryCycleInfo"] = buildSalaryInfo(editBasicInfo, -2, nowYear, nowMonth);
break;
case "2" :
tmpV["salaryCycleInfo"] = buildSalaryInfo(editBasicInfo, -1, nowYear, nowMonth);
break;
case "3" :
tmpV["salaryCycleInfo"] = buildSalaryInfo(editBasicInfo, 0, nowYear, nowMonth);
break;
case "4" :
tmpV["salaryCycleInfo"] = buildSalaryInfo(editBasicInfo, 1, nowYear, nowMonth);
break;
}
// 考勤联动
switch (attendCycleType) {
case "1" :
tmpV["attendCycleInfo"] = buildAttendanceInfo(editBasicInfo, -2, nowYear, nowMonth);
break;
case "2" :
tmpV["attendCycleInfo"] = buildAttendanceInfo(editBasicInfo, -1, nowYear, nowMonth);
break;
case "3" :
tmpV["attendCycleInfo"] = buildAttendanceInfo(editBasicInfo, 0, nowYear, nowMonth);
break;
case "4" :
tmpV["attendCycleInfo"] = buildAttendanceInfo(editBasicInfo, 1, nowYear, nowMonth);
break;
}
return tmpV;
};
/*
* Author: 黎永顺
* Description:构建薪资周期联动信息
* Params:
* Date: 2023/4/17
*/
const buildSalaryInfo = (editBasicInfo, monthCal, nowYear, nowMonth) => {
const { salaryCycleFromDay } = editBasicInfo;
let salaryCycleFromDayNum = Number(salaryCycleFromDay), customInfo = {};
const basicInfo = generateBasicInfo(monthCal, nowYear, nowMonth);
const { nowMonthStr, nextMonthStr, year, month } = basicInfo;
customInfo.salaryYear = year;
customInfo.salaryMonth = month;
if (salaryCycleFromDayNum === 1) {
customInfo.salaryPeriodTip = "至" + nowMonthStr + "最后一天";
customInfo.salaryPeriodStart = customInfo.salaryYear + "-"
+ prefixAddZero(customInfo.salaryMonth, 2) + "-01";
customInfo.salaryPeriodEnd = customInfo.salaryYear + "-"
+ prefixAddZero(customInfo.salaryMonth, 2) + "-"
+ prefixAddZero(getMonthDays(customInfo.salaryYear, customInfo.salaryMonth), 2);
} else {
customInfo.salaryPeriodTip = "至" + nextMonthStr + (salaryCycleFromDayNum - 1) + "号";
customInfo.salaryPeriodStart = customInfo.salaryYear + "-"
+ prefixAddZero(customInfo.salaryMonth, 2) + "-" + prefixAddZero(salaryCycleFromDayNum, 2);
let year = customInfo.salaryYear;
let month = customInfo.salaryMonth;
if (month === "12") {
year = Number(year) + 1;
month = 1;
} else {
month = Number(month) + 1;
}
customInfo.salaryPeriodEnd = year + "-"
+ prefixAddZero(month, 2) + "-"
+ prefixAddZero(salaryCycleFromDayNum - 1, 2);
}
return customInfo;
};
const buildAttendanceInfo = (editBasicInfo, monthCal, nowYear, nowMonth) => {
const { attendCycleFromDay } = editBasicInfo;
let attendCycleFromDayNum = Number(attendCycleFromDay), customInfo = {};
const basicInfo = generateBasicInfo(monthCal, nowYear, nowMonth);
const { nowMonthStr, nextMonthStr } = basicInfo;
let year = basicInfo.year;
let month = basicInfo.month;
if (attendCycleFromDayNum === 1) {
customInfo.attendancePeriodTip = "至" + nowMonthStr + "最后一天";
customInfo.attendancePeriodStart = year + "-"
+ prefixAddZero(month, 2) + "-01";
customInfo.attendancePeriodEnd = year + "-"
+ prefixAddZero(month, 2) + "-"
+ prefixAddZero(getMonthDays(year, month), 2);
} else {
customInfo.attendancePeriodTip = "至" + nextMonthStr + (attendCycleFromDayNum - 1) + "号";
customInfo.attendancePeriodStart = year + "-"
+ prefixAddZero(month, 2) + "-" + prefixAddZero(attendCycleFromDayNum, 2);
if (month === "12") {
year = (Number(year) + 1).toString();
month = "1";
} else {
month = (Number(month) + 1).toString();
}
customInfo.attendancePeriodEnd = year + "-"
+ prefixAddZero(month, 2) + "-"
+ prefixAddZero(attendCycleFromDayNum - 1, 2);
}
return customInfo;
};
const getMonth = (salaryCycleType) => {
switch (salaryCycleType) {
case "1": // 上上月
@ -279,62 +379,3 @@ const getMonth = (salaryCycleType) => {
return getAddMonthYearMonth(1);
}
};
const initPeriodStr = (periodStrType, types, fromDay) => {
let str = "", tmpDate = null;
switch (types) {
case "1":
tmpDate = moment().subtract(2, "month");
const is_31H = moment(tmpDate, "YYYY-MM").daysInMonth() === 31;
if (fromDay == 1) {
tmpDate = moment().subtract(2, "month").endOf("month");
str = `至上上月最后一天`;
} else {
tmpDate = moment(new Date(`${moment(tmpDate).format("YYYY-MM")}-0${fromDay}`))
.add(is_31H ? 30 : 27, "days");
str = `至上月${moment(tmpDate).date()}`;
}
break;
case "2":
tmpDate = moment().subtract(1, "month");
const is_31 = moment(tmpDate, "YYYY-MM").daysInMonth() === 31;
if (fromDay == 1) {
tmpDate = moment().subtract(1, "month").endOf("month");
str = `至上月最后一天`;
} else {
tmpDate = moment(new Date(`${moment(tmpDate).format("YYYY-MM")}-0${fromDay}`))
.add(is_31 ? 30 : 27, "days");
str = `至本月${moment(tmpDate).date()}`;
}
break;
case "3":
tmpDate = moment().add(0, "month");
const is_31K = moment(tmpDate, "YYYY-MM").daysInMonth() === 31;
if (fromDay == 1) {
tmpDate = moment().endOf("month");
str = `至本月最后一天`;
} else {
tmpDate = moment(new Date(`${moment(tmpDate).format("YYYY-MM")}-0${fromDay}`))
.add(is_31K ? 30 : 27, "days");
str = `至下月${moment(tmpDate).date()}`;
}
break;
case "4":
tmpDate = moment().add(1, "month");
const is_31L = moment(tmpDate, "YYYY-MM").daysInMonth() === 31;
if (fromDay == 1) {
tmpDate = moment().add(1, "month").endOf("month");
str = `至下月最后一天`;
} else {
tmpDate = moment(new Date(`${moment(tmpDate).format("YYYY-MM")}-0${fromDay}`))
.add(is_31L ? 30 : 29, "days");
str = `至下下月${moment(tmpDate).date()}`;
}
break;
default:
break;
}
return {
[periodStrType]: str,
date: moment(tmpDate).format("YYYY-MM-DD")
};
};

View File

@ -301,10 +301,10 @@ class LedgerSalaryItem extends Component {
* Params:
* Date: 2023/3/8
*/
handleMoveSalaryItem = (moveToItemId, items) => {
handleMoveSalaryItem = (moveToItemId, items, titleName) => {
const { itemGroups } = this.state;
const { salaryItemGroupId: deleteItemId, id, key } = items;
if (moveToItemId === deleteItemId) return;
if (moveToItemId === deleteItemId || (deleteItemId === "0" && titleName === "未分类")) return;
this.setState({
itemGroups: _.map(itemGroups, it => {
if (moveToItemId === it.uuid) {

View File

@ -13,6 +13,7 @@ export default class LedgerSalaryItemAddModal extends React.Component {
name: "",
selectedRowKeys: [],
dataSource: [],
dataSourceCopy: [],
columns: [],
pageInfo: {
current: 1,
@ -24,7 +25,7 @@ export default class LedgerSalaryItemAddModal extends React.Component {
componentWillReceiveProps(nextProps, nextContext) {
if (nextProps.visible !== this.props.visivle && nextProps.visible) {
this.setState({ selectedRowKeys: [] }, () => {
this.setState({ selectedRowKeys: [], dataSourceCopy: [] }, () => {
this.listSalaryItem();
});
}
@ -32,7 +33,7 @@ export default class LedgerSalaryItemAddModal extends React.Component {
listSalaryItem = () => {
const { itemGroups } = this.props;
const { name, pageInfo, loading } = this.state;
const { name, pageInfo, loading, dataSourceCopy } = this.state;
let excludeIds = [];
itemGroups.map(item => {
item.items && item.items.map(i => {
@ -50,6 +51,7 @@ export default class LedgerSalaryItemAddModal extends React.Component {
if (status) {
const { pageNum: current, pageSize, total, columns, list: dataSource } = data;
this.setState({
dataSourceCopy: [...dataSourceCopy, ...dataSource],
pageInfo: { ...pageInfo, current, pageSize, total },
dataSource,
columns
@ -80,11 +82,11 @@ export default class LedgerSalaryItemAddModal extends React.Component {
};
handleAdd = () => {
const { dataSource, selectedRowKeys } = this.state;
const { dataSourceCopy, selectedRowKeys } = this.state;
const { onAddSalaryItems, id, onCancel, itemGroups } = this.props;
const arrItems = _.find(itemGroups, it => it.uuid === id).items || [];
let selectItems = [];
dataSource.map((item) => {
dataSourceCopy.map((item) => {
item = { ...item };
selectedRowKeys.map((key, keyIdx) => {
if (item.id === key) {

View File

@ -175,11 +175,11 @@ class LedgerSalaryItemNormal extends Component {
});
};
handleSubmitMoveTo = () => {
const { onMoveSalaryItem } = this.props;
const { onMoveSalaryItem, dataSource } = this.props;
const { moveModalPayload } = this.state;
const { record, value } = moveModalPayload;
this.handleCancelMove();
onMoveSalaryItem(value, record);
onMoveSalaryItem(value, record, _.find(dataSource, it => (it.id === value || it.uuid === value)).name);
};
render() {

View File

@ -25,7 +25,7 @@ class LedgerSalaryItemTable extends Component {
const { dataSource, onHandleItemhide } = this.props;
onHandleItemhide(
_.map([...dataSource], item => {
if (id === item.id) {
if (id === item.id || id === item.key) {
return {
...item,
itemHide: String(value)
@ -48,7 +48,14 @@ class LedgerSalaryItemTable extends Component {
};
render() {
const { dataSource, onDropCategoryItem, onChangeSelectedRowKeys, onEditFormnul, selectedRowKeys, onMoveTo } = this.props;
const {
dataSource,
onDropCategoryItem,
onChangeSelectedRowKeys,
onEditFormnul,
selectedRowKeys,
onMoveTo
} = this.props;
const rowSelection = {
selectedRowKeys,
onChange: (selectedRowKeys) => this.setState({ selectedRowKeys }, () => {
@ -58,7 +65,7 @@ class LedgerSalaryItemTable extends Component {
disabled: !record.canDelete
})
};
const checkValue = _.every(dataSource, it => it.itemHide && it.itemHide === "1") ? "1" : "0";
const checkValue = (!_.isEmpty(dataSource) && _.every(dataSource, it => it.itemHide && it.itemHide === "1")) ? "1" : "0";
const columns = [
{
title: "名称",
@ -102,7 +109,7 @@ class LedgerSalaryItemTable extends Component {
width: 80,
render: (text, record) => <WeaCheckbox
value={text ? String(text) : !text ? "0" : "1"}
onChange={value => this.handleChangeItem(value, record.id)}
onChange={value => this.handleChangeItem(value, record.id || record.key)}
/>
},
{

View File

@ -24,7 +24,8 @@ export default class MobilePayroll extends React.Component {
const type = getQueryString("type");
this.id = getQueryString("id");
const { mySalaryStore: { init } } = this.props;
type !== "phone" && init(false);
// type !== "phone" && init(false);
init(false);
this.getMySalaryBill(this.id);
}

View File

@ -5,8 +5,7 @@ import { Button, Spin } from "antd";
import { getQueryString } from "../../../util/url";
import { removePropertyCondition } from "../../../util/response";
import { getSearchs } from "../../../util";
import { getPayrollDetailList, getPayrollDetailSa, getPayrollInfo, salaryBillSendSum } from "../../../apis/payroll";
import { sysConfCodeRule } from "../../../apis/ruleconfig";
import { getPayrollDetailList, getPayrollDetailSa, getPayrollInfo } from "../../../apis/payroll";
import "./index.less";
@inject("payrollStore")
@ -17,8 +16,7 @@ export default class PayrollDetail extends React.Component {
this.state = {
salarySendDetailBaseInfo: {}, loading: false,
condition: [], dataSource: [], columns: [],
pageInfo: { current: 1, pageSize: 10, total: 0 },
salaryBillSendSum: {}, showSum: false
pageInfo: { current: 1, pageSize: 10, total: 0 }
};
}
@ -54,16 +52,11 @@ export default class PayrollDetail extends React.Component {
}
}
if (type === "init") {
const { status, data: sysData } = await this.sysConfCodeRule();
const { data: { sumRow } } = await this.salaryBillSendSum();
const salaryBillSendSum = _.reduce(_.keys(sumRow), (pre, cur) => (_.assign(pre, { [`${cur}_salaryItem`]: sumRow[cur] })), {});
this.setState({ showSum: status && sysData === "1", salaryBillSendSum });
childFrameObj.contentWindow.postMessage(JSON.stringify({
dataSource,
columns,
pageInfo,
showSum: status && sysData === "1",
salaryBillSendSum
sumpayload: { salarySendId: getQueryString("id") }
}), "*");
this.getPayrollDetailList({ child: type });
}
@ -110,25 +103,18 @@ export default class PayrollDetail extends React.Component {
})),
pageInfo: { ...pageInfo, current, pageSize, total }
}, () => {
const { pageInfo, dataSource, columns, salaryBillSendSum, showSum } = this.state;
const { pageInfo, dataSource, columns } = this.state;
(child === "PAGEINFO" || child === "init") &&
childFrameObj.contentWindow.postMessage(JSON.stringify({
dataSource,
columns,
pageInfo, showSum,
salaryBillSendSum
pageInfo,
sumpayload: { salarySendId: getQueryString("id") }
}), "*");
});
}
}).catch(() => this.setState({ loading: false }));
};
salaryBillSendSum = () => {
const salarySendId = getQueryString("id");
return salaryBillSendSum({ salarySendId });
};
sysConfCodeRule = () => {
return sysConfCodeRule({ code: "OPEN_ACCT_RESULT_SUM" });
};
handleExportAll = () => {
const salarySendId = getQueryString("id");
const url = `${window.location.origin}/api/bs/hrmsalary/salaryBill/send/exportDetailList?salarySendId=${salarySendId}`;

View File

@ -0,0 +1,153 @@
import { WeaLocaleProvider } from "ecCom";
const { getLabel } = WeaLocaleProvider;
export const condition = [
{
items: [
{
colSpan: 2,
checkbox: false,
checkboxValue: false,
conditionType: "SELECT",
domkey: ["taxAgent"],
fieldcol: 18,
label: getLabel(111, "个税扣缴义务人"),
labelcol: 6,
options: [],
multiple: true,
viewAttr: 2
},
{
browserConditionParam: {
completeParams: {},
conditionDataParams: {},
dataParams: {},
destDataParams: {},
hasAddBtn: false,
hasAdvanceSerach: true,
idSeparator: ",",
isAutoComplete: 1,
isDetail: 0,
isMultCheckbox: false,
isSingle: false,
linkUrl: "",
pageSize: 10,
quickSearchName: "",
replaceDatas: [],
title: getLabel(111, "分部"),
type: "164",
viewAttr: 2
},
colSpan: 2,
conditionType: "BROWSER",
domkey: ["subCompany"],
fieldcol: 18,
isQuickSearch: false,
label: getLabel(111, "分部"),
labelcol: 6,
viewAttr: 2
},
{
browserConditionParam: {
completeParams: {},
conditionDataParams: {},
dataParams: {},
destDataParams: {},
hasAddBtn: false,
hasAdvanceSerach: true,
idSeparator: ",",
isAutoComplete: 1,
isDetail: 0,
isMultCheckbox: false,
isSingle: false,
linkUrl: "",
pageSize: 10,
quickSearchName: "",
replaceDatas: [],
title: getLabel(111, "部门"),
type: "57",
viewAttr: 2
},
colSpan: 2,
conditionType: "BROWSER",
domkey: ["department"],
fieldcol: 18,
isQuickSearch: false,
label: getLabel(111, "部门"),
labelcol: 6,
viewAttr: 2
},
// {
// browserConditionParam: {
// completeParams: {},
// conditionDataParams: {},
// dataParams: {},
// destDataParams: {},
// hasAddBtn: false,
// hasAdvanceSerach: true,
// idSeparator: ",",
// isAutoComplete: 1,
// isDetail: 0,
// isMultCheckbox: false,
// isSingle: false,
// linkUrl: "",
// pageSize: 10,
// quickSearchName: "",
// replaceDatas: [],
// title: getLabel(111, "岗位"),
// type: "278",
// viewAttr: 2
// },
// colSpan: 2,
// conditionType: "BROWSER",
// domkey: ["position"],
// fieldcol: 18,
// isQuickSearch: false,
// label: getLabel(111, "岗位"),
// labelcol: 6,
// viewAttr: 2
// },
{
browserConditionParam: {
completeParams: {},
conditionDataParams: {},
dataParams: {},
destDataParams: {},
hasAddBtn: false,
hasAdvanceSerach: true,
idSeparator: ",",
isAutoComplete: 1,
isDetail: 0,
isMultCheckbox: false,
isSingle: false,
linkUrl: "",
pageSize: 10,
quickSearchName: "",
replaceDatas: [],
title: getLabel(111, "人员"),
type: "17",
viewAttr: 2
},
colSpan: 2,
conditionType: "BROWSER",
domkey: ["employee"],
fieldcol: 18,
isQuickSearch: false,
label: getLabel(111, "人员"),
labelcol: 6,
viewAttr: 2
},
{
colSpan: 2,
conditionType: "RANGEPICKER",
domkey: ["hiredate1", "hiredate2"],
fieldcol: 18,
label: getLabel(111, "入职日期"),
labelcol: 6,
viewAttr: 2
}
],
title: "",
defaultshow: true
}
];

View File

@ -0,0 +1,416 @@
/*
* Author: 黎永顺
* name: 新建自定义统计项目弹框
* Description:
* Date: 2023/4/10
*/
import React, { Component } from "react";
import { Button, message, Modal } from "antd";
import {
WeaBrowser,
WeaCheckbox,
WeaDialog,
WeaError,
WeaFormItem,
WeaHelpfulTip,
WeaInput,
WeaInputNumber,
WeaLocaleProvider,
WeaTable
} from "ecCom";
import { reportStatisticsItemSave, statisticsItemGetform } from "../../../apis/statistics";
import "../index.less";
const { getLabel } = WeaLocaleProvider;
class CustomStatisticsItemsModal extends Component {
constructor(props) {
super(props);
this.state = {
loading: false,
columns: [],
dataSource: [],
formData: {
itemValue: "", itemValueSpan: "",
itemName: ""
}
};
}
componentWillReceiveProps(nextProps, nextContext) {
if (nextProps.visible !== this.props.visible && nextProps.visible) {
this.statisticsItemGetform({ id: nextProps.statisticsItemId });
} else {
this.setState({
columns: [],
dataSource: [],
formData: {
itemValue: "", itemValueSpan: "",
itemName: ""
}
});
}
}
handleSaveStatisticalItems = () => {
const { dataSource, formData } = this.state;
const { id: statReportId, statisticsItemId } = this.props;
const { itemValue, itemName } = formData;
const isNoRules = _.some(dataSource, it => !!it.m2mValue || !!it.ratioValue || !!it.totalValue || !!it.y2yValue);
const isChainRequired = _.some(dataSource, it => !!it.m2mValue && (!it.m2mLowerLimit || !it.m2mUpperLimit));
const isChainValRight = _.some(dataSource, it => !!it.m2mValue && it.m2mLowerLimit !== 0 && it.m2mUpperLimit !== 0 && (Number(it.m2mLowerLimit) > Number(it.m2mUpperLimit)));
const isYoyRequired = _.some(dataSource, it => !!it.y2yValue && (!it.y2yLowerLimit || !it.y2yUpperLimit));
const isYoyValRight = _.some(dataSource, it => !!it.y2yValue && it.y2yLowerLimit !== 0 && it.y2yUpperLimit !== 0 && (Number(it.y2yLowerLimit) > Number(it.y2yUpperLimit)));
if (!itemValue && !itemName) {
this.refs.proError.showError();
this.refs.nameError.showError();
return;
}
if (!itemValue) {
this.refs.proError.showError();
return;
}
if (!itemName) {
this.refs.nameError.showError();
return;
}
if (!isNoRules) {
message.warning(getLabel(111, "请至少设置一个统计规则"));
return;
}
if (isChainRequired) {
message.warning(getLabel(111, "请完善环比增幅正常区间设置上下限"));
return;
}
if (isChainValRight) {
message.warning(getLabel(111, "环比增幅上下限设置错误"));
return;
}
if (isYoyRequired) {
message.warning(getLabel(111, "请完善同比增幅正常区间设置上下限"));
return;
}
if (isYoyValRight) {
message.warning(getLabel(111, "同比增幅上下限设置错误"));
return;
}
let payload = { statReportId, itemValue: itemValue.split(","), itemName };
payload = {
id: statisticsItemId,
...payload,
..._.reduce(dataSource, (pre, cur) => {
if (!!cur.m2mValue || !!cur.ratioValue || !!cur.totalValue || !!cur.y2yValue) {
const { y2yLowerLimit, y2yUpperLimit, m2mLowerLimit, m2mUpperLimit } = cur;
if (!!cur.m2mValue) {
return {
...pre,
[`${cur["id"]}Rule`]: {
m2mValue: cur.m2mValue.toString(),
ratioValue: cur.ratioValue.toString(),
totalValue: cur.totalValue.toString(),
y2yValue: cur.y2yValue.toString(),
m2mLowerLimit: m2mLowerLimit.toString(),
m2mUpperLimit: m2mUpperLimit.toString()
}
};
}
if (!!cur.m2mValue) {
return {
...pre,
[`${cur["id"]}Rule`]: {
m2mValue: cur.m2mValue.toString(),
ratioValue: cur.ratioValue.toString(),
totalValue: cur.totalValue.toString(),
y2yValue: cur.y2yValue.toString(),
y2yLowerLimit: y2yLowerLimit.toString(),
y2yUpperLimit: y2yUpperLimit.toString()
}
};
}
if (!!cur.y2yValue && !!cur.y2yValue) {
return {
...pre,
[`${cur["id"]}Rule`]: {
m2mValue: cur.m2mValue.toString(),
ratioValue: cur.ratioValue.toString(),
totalValue: cur.totalValue.toString(),
y2yValue: cur.y2yValue.toString(),
m2mLowerLimit: m2mLowerLimit.toString(),
m2mUpperLimit: m2mUpperLimit.toString(),
y2yLowerLimit: y2yLowerLimit.toString(),
y2yUpperLimit: y2yUpperLimit.toString()
}
};
}
return {
...pre,
[`${cur["id"]}Rule`]: {
m2mValue: cur.m2mValue.toString(),
ratioValue: cur.ratioValue.toString(),
totalValue: cur.totalValue.toString(),
y2yValue: cur.y2yValue.toString()
}
};
}
return { ...pre };
}, {})
};
if (statisticsItemId) {
Modal.confirm({
title: getLabel(111, "信息确认"),
content: getLabel(111, `确定要编辑统计项吗?编辑后,可能需要重新设置分析图设置。`),
onOk: () => this.reportStatisticsItemSave(payload)
});
} else {
this.reportStatisticsItemSave(payload);
}
};
reportStatisticsItemSave = (payload) => {
this.setState({ loading: true });
reportStatisticsItemSave(payload).then(({ status, errormsg }) => {
this.setState({ loading: false });
if (status) {
this.setState({
formData: {
itemValue: "", itemName: ""
}
}, () => this.props.onCancel(true));
} else {
message.error(errormsg);
}
}).catch(() => this.setState({ loading: false }));
};
statisticsItemGetform = (payload) => {
statisticsItemGetform(payload).then(({ status, data }) => {
if (status) {
const { formData } = this.state;
const { ruleData, baseForm } = data;
const { data: dataDetail } = baseForm;
const { columns, data: dataSource } = ruleData;
this.setState({
columns, dataSource,
formData: {
...formData,
itemName: dataDetail ? dataDetail.itemName : "",
itemValue: dataDetail ? _.map(dataDetail.itemValue, it => it.id).join() : "",
itemValueSpan: dataDetail ? _.map(dataDetail.itemValue, it => it.name).join() : ""
}
});
}
});
};
handleChangeColumnCheckBox = (key, value, id) => {
const { dataSource } = this.state;
this.setState({
dataSource: _.map(dataSource, it => {
if (it.id === id) {
if (key !== "totalValue" && !!value && value !== "0") {
return {
...it,
totalValue: Number(value),
[key]: Number(value)
};
}
return {
...it,
[key]: Number(value)
};
}
return { ...it };
})
});
};
handleChangeColumnAllChecked = (key, val) => {
const { dataSource } = this.state;
this.setState({
dataSource: _.map(dataSource, it => {
if (key !== "totalValue" && !!val && val !== "0") {
return {
...it,
totalValue: Number(val),
[key]: Number(val)
};
}
return {
...it,
[key]: Number(val)
};
})
});
};
handleChangeColumnM2MValue = (key, value, id) => {
const { dataSource } = this.state;
this.setState({
dataSource: _.map(dataSource, it => {
if (it.id === id) {
return {
...it,
[key]: value
};
}
return { ...it };
})
});
};
handleChangeStatisticalItems = (itemValue, _names, datas) => {
const { formData } = this.state;
this.setState({
formData: {
...formData,
itemValue,
itemValueSpan: _.map(datas, it => it.name).join(","),
itemName: datas.length === 1 ? _.map(datas, it => it.names).join(",") : ""
}
});
};
render() {
const { loading, columns, dataSource, formData } = this.state;
const { itemName, itemValue, itemValueSpan } = formData;
const { statisticsItemId } = this.props;
const cols = _.map(columns, it => {
const { text, column } = it;
if (column === "ruleName" || column === "ratio" || column === "m2m" || column === "y2y") {
const key = column === "ruleName" ? "total" : column;
return {
...it,
title: <span>
<WeaCheckbox
value={_.every(dataSource, child => !!child[`${key}Value`])}
onChange={val => this.handleChangeColumnAllChecked(`${key}Value`, val)}
/>
<span style={{ marginLeft: 8 }}>{text}</span>
</span>,
render: (txt, record) => {
return <span>
<WeaCheckbox
value={record[`${key}Value`].toString()}
onChange={val => this.handleChangeColumnCheckBox(`${key}Value`, val, record.id)}
/>
<span style={{ marginLeft: 8 }}>
{column === "ruleName" ? record["ruleName"] : text}
</span>
</span>;
}
};
} else if (column === "m2mLimit") {
return {
...it,
title: <span>
<span style={{ marginRight: 8 }}>{text}</span>
<WeaHelpfulTip title={getLabel(111, "如:增幅>10%,差值和增幅标记为红色,增幅<-10%标记为绿色")}
placement="top" width={200}/>
</span>,
render: (txt, record) => {
return !!record["m2mValue"] && <IntervalSettingsComp
LowerLimit={record[`${column.replace("Limit", "")}LowerLimit`]}
UpperLimit={record[`${column.replace("Limit", "")}UpperLimit`]}
onChange={(type, val) => this.handleChangeColumnM2MValue(`${column.replace("Limit", "")}${type === "min" ? "LowerLimit" : "UpperLimit"}`, val, record.id)}
/>;
}
};
} else if (column === "y2yLimit") {
return {
...it,
title: <span>
<span style={{ marginRight: 8 }}>{text}</span>
<WeaHelpfulTip title={getLabel(111, "如:增幅>10%,差值和增幅标记为红色,增幅<-10%标记为绿色")}
placement="top" width={200}/>
</span>,
render: (txt, record) => {
return !!record["y2yValue"] && <IntervalSettingsComp
LowerLimit={record[`${column.replace("Limit", "")}LowerLimit`]}
UpperLimit={record[`${column.replace("Limit", "")}UpperLimit`]}
onChange={(type, val) => this.handleChangeColumnM2MValue(`${column.replace("Limit", "")}${type === "min" ? "LowerLimit" : "UpperLimit"}`, val, record.id)}
/>;
}
};
}
});
return (
<WeaDialog
{...this.props} hasScroll buttons={[]} initLoadCss
title={
<div className="itemsTitle">
<span>{statisticsItemId ? getLabel(111, "编辑自定义统计项目") : getLabel(111, "新建自定义统计项目")}</span>
<Button type="primary" loading={loading}
onClick={this.handleSaveStatisticalItems}>{getLabel(111, "保存")}</Button>
</div>
}
style={{ width: 900, height: 450 }}
className="statisticItemsWrapper"
>
<div className="statisticItemsBox">
<WeaFormItem label={getLabel(111, "统计项目")} labelCol={{ span: 6 }} wrapperCol={{ span: 18 }}>
<WeaError tipPosition="bottom" ref="proError" error={getLabel(111, "此项必填")}>
<WeaBrowser
title={getLabel(111, "统计项目")}
type={162}
viewAttr={3}
isSingle={false}
value={itemValue}
replaceDatas={itemValue ? _.map(itemValue.split(","), (it, idx) => ({
id: it,
name: itemValueSpan.split(",")[idx]
})) : []}
completeParams={{
type: 162,
fielddbtype: "browser.salaryItemBrowser",
f_weaver_belongto_usertype: "0"
}}
conditionDataParams={{
type: "browser.salaryItemBrowser",
fielddbtype: "browser.salaryItemBrowser",
f_weaver_belongto_usertype: "0"
}}
dataParams={{
type: "browser.salaryItemBrowser",
f_weaver_belongto_usertype: "0"
}}
destDataParams={{
type: "browser.salaryItemBrowser",
f_weaver_belongto_usertype: "0"
}}
isMultCheckbox
inputStyle={{ width: "100%" }}
onChange={this.handleChangeStatisticalItems}
/>
</WeaError>
</WeaFormItem>
<WeaFormItem label={getLabel(111, "统计项名称")} labelCol={{ span: 6 }} wrapperCol={{ span: 18 }}>
<WeaError tipPosition="bottom" ref="nameError" error={getLabel(111, "此项必填")}>
<WeaInput value={itemName} viewAttr={3}
onChange={itemName => this.setState({ formData: { ...formData, itemName } })}/>
</WeaError>
</WeaFormItem>
<div className="customRuleTableWrapper">
<WeaTable
dataSource={dataSource}
columns={cols}
pagination={false}
/>
</div>
</div>
</WeaDialog>
);
}
}
export default CustomStatisticsItemsModal;
/*
* Author: 黎永顺
* Description: 区间设置
* Params:
* Date: 2023/4/23
*/
const IntervalSettingsComp = (props) => {
const { LowerLimit, UpperLimit, onChange } = props;
return <div className="intervalSettingsCompWrapper">
<WeaInputNumber value={LowerLimit} precision={2} onChange={val => onChange("min", val)}/>
<span className="increaseTitle">{`% <${getLabel(111, "增幅")}<`}</span>
<WeaInputNumber value={UpperLimit} precision={2} onChange={val => onChange("max", val)}/>
<span className="pecentTitle">%</span>
</div>;
};

View File

@ -0,0 +1,83 @@
/*
* Author: 黎永顺
* name: 报表查看-左侧tab标题
* Description:
* Date: 2023/4/20
*/
import React, { Component } from "react";
import { WeaInputSearch, WeaLocaleProvider } from "ecCom";
import { reportStatisticsReportList } from "../../../apis/statistics";
import { Menu } from "antd";
import { getQueryString } from "../../../util/url";
import "../index.less";
const { getLabel } = WeaLocaleProvider;
class LeftTab extends Component {
constructor(props) {
super(props);
this.state = {
reportName: "",
selectedKeys: getQueryString("id").split(","),
reportList: []
};
}
componentDidMount() {
this.reportStatisticsReportList();
}
reportStatisticsReportList = () => {
const { reportName, selectedKeys } = this.state;
const { onChangeTab } = this.props;
reportStatisticsReportList({ reportName }).then(({ status, data: reportList }) => {
if (status) this.setState({ reportList }, () => {
onChangeTab(_.find(this.state.reportList, it => it.id === selectedKeys[0]));
});
});
};
updateReportList = (report) => {
const { reportList } = this.state;
this.setState({
reportList: _.reduce(reportList, (pre, cur) => {
if (report.id === cur.id) {
return [...pre, report];
}
return [...pre, cur];
}, [])
});
};
render() {
const { reportName, selectedKeys, reportList } = this.state;
const { onChangeTab } = this.props;
return (
<div className="leftTabWrapper">
<div className="searchArea">
<WeaInputSearch
value={reportName} onChange={reportName => this.setState({ reportName })}
placeholder={getLabel(111, "请输入报表名称")} onSearch={this.reportStatisticsReportList}
/>
</div>
<Menu
mode="inline" selectedKeys={selectedKeys}
onClick={({ key }) => {
this.setState({ selectedKeys: key.split(",") }, () => {
onChangeTab(_.find(reportList, it => it.id === key));
});
}}
>
{
_.map(reportList, item => {
const { reportName, id } = item;
return <Menu.Item key={id}>{reportName}</Menu.Item>;
})
}
</Menu>
</div>
);
}
}
export default LeftTab;

View File

@ -0,0 +1,109 @@
/*
* Author: 黎永顺
* name: 报表内容区
* Description:
* Date: 2023/4/21
*/
import React, { Component } from "react";
import { Spin } from "antd";
import RightOptions from "./rightOptions";
import { reportStatisticsReportGetData } from "../../../apis/statistics";
import "../index.less";
class ReportContent extends Component {
constructor(props) {
super(props);
this.state = {
columns: [],
dataSource: [],
countResult: {},
loading: false
};
}
componentDidMount() {
window.addEventListener("message", this.handleReceive, false);
}
componentWillReceiveProps(nextProps, nextContext) {
if (nextProps.report !== this.props.report && nextProps.report.dimensionId) {
this.reportStatisticsReportGetData(nextProps.report.id, nextProps.report.dimensionId);
}
}
componentWillUnmount() {
window.removeEventListener("message", this.handleReceive, false);
}
handleReceive = ({ data }) => {
const { type } = data;
if (type === "init") {
const { columns, countResult, dataSource } = this.state;
this.postMessageToChild({
columns, countResult, dataSource,
showSum: !_.isEmpty(countResult)
});
} else if (type === "turn") {
}
};
postMessageToChild = (payload) => {
const childFrameObj = document.getElementById("atdTable");
const { dataSource, columns, showSum, countResult } = payload;
childFrameObj.contentWindow.postMessage(JSON.stringify({
dataSource, columns, showSum, countResult
}), "*");
};
reportStatisticsReportGetData = (id, dimensionId) => {
const payload = { id, dimensionId };
this.setState({ loading: true });
reportStatisticsReportGetData(payload).then(({ status, data }) => {
this.setState({ loading: false });
if (status) {
const { countResult, columns, pageInfo: { list } } = data;
this.setState({
countResult,
columns: _.map(columns, it => ({
...it,
dataIndex: it.column, width: 150,
title: it.text, align: "center",
children: !_.isNil(it.children) ? _.map(it.children, child => ({
...child,
dataIndex: child.column, width: 150,
title: child.text, align: "center"
})) : []
})),
dataSource: list || []
}, () => {
this.postMessageToChild({
columns: this.state.columns, countResult: this.state.countResult,
dataSource: this.state.dataSource,
showSum: !_.isEmpty(this.state.countResult)
});
});
}
}).catch(() => this.setState({ loading: false }));
};
render() {
const { loading } = this.state;
return (
<div className="layoutContent">
<div className="layoutBox">
<Spin spinning={loading}>
<iframe
style={{ border: 0, width: "100%", height: "100%" }}
// src="http://localhost:7607/#/reportTable"
src="/spa/hrmSalary/hrmSalaryCalculateDetail/index.html#/reportTable"
id="atdTable"
/>
</Spin>
</div>
{/*侧边栏*/}
{/*<RightOptions/>*/}
</div>
);
}
}
export default ReportContent;

View File

@ -0,0 +1,48 @@
/*
* Author: 黎永顺
* name: 内容操作按钮区
* Description:
* Date: 2023/4/21
*/
import React, { Component } from "react";
import { WeaLocaleProvider } from "ecCom";
import "../index.less";
const { getLabel } = WeaLocaleProvider;
class RightOptions extends Component {
constructor(props) {
super(props);
this.state = {
show: true
};
}
render() {
const { show } = this.state;
return (
<div className="layoutSide" style={{ width: show ? "30px" : 0 }}>
<div className="sideBox">
<div className="sideMain">
<div className="toll-bar-container" style={{ alignItems: show && "center" }}>
<i className="icon-coms-background" title={getLabel(111, "数据视图")}/>
<i className="icon-portal-reportform-o" title={getLabel(111, "柱状图")}/>
<i className="icon-coms-Line" title={getLabel(111, "折线图")}/>
<i className="icon-coms-Pie" title={getLabel(111, "饼图")}/>
<i className="icon-coms-Flow-setting" title={getLabel(111, "设置")}/>
</div>
</div>
<span className="show-btn-right"
onClick={() => this.setState({ show: !show })}>
{
show ? <img src={require("../../../common/leftTree-show.png")} alt=""/> :
<img src={require("../../../common/leftTree-hide.png")} alt=""/>
}
</span>
</div>
</div>
);
}
}
export default RightOptions;

View File

@ -0,0 +1,348 @@
/*
* Author: 黎永顺
* name: 统计数据范围及规则设置
* Description:
* Date: 2023/4/21
*/
import React, { Component } from "react";
import { toJS } from "mobx";
import {
WeaButtonIcon,
WeaDatePicker,
WeaError,
WeaFormItem,
WeaHelpfulTip,
WeaLocaleProvider,
WeaSearchGroup,
WeaSelect,
WeaSlideModal,
WeaTable
} from "ecCom";
import CustomStatisticsItemsModal from "./customStatisticsItemsModal";
import moment from "moment";
import { Button, message, Modal } from "antd";
import { condition } from "./condition";
import { getSearchs } from "../../../util";
import {
reportStatisticsGetSearchCondition,
reportStatisticsItemDelete,
reportStatisticsSaveSearchCondition,
statisticsItemList
} from "../../../apis/statistics";
import { commonEnumList } from "../../../apis/ruleconfig";
import "../index.less";
const { getLabel } = WeaLocaleProvider;
class StatisticalMicroSettingsSlide extends Component {
constructor(props) {
super(props);
this.state = {
loading: false,
selectedRowKeys: [],
conditions: [],
dataSource: [],
unitTypeList: [],
salaryMonth: [],
statisticalItemPayload: {
visible: false, id: "", dimension: "",
statisticsItemId: ""
}
};
}
componentWillReceiveProps(nextProps, nextContext) {
if (nextProps.taxAgentAdminOption !== this.props.taxAgentAdminOption && !_.isEmpty(nextProps.taxAgentAdminOption)) {
const conditions = _.map(condition, item => {
return {
...item,
items: _.map(item.items, child => {
if (child.domkey[0] === "taxAgent") {
return {
...child,
options: toJS(nextProps.taxAgentAdminOption)
};
}
return { ...child };
})
};
});
this.setState({ conditions });
nextProps.form.initFormFields(condition);
}
if (nextProps.id !== this.props.id && !_.isEmpty(nextProps.id)) {
this.reportStatisticsGetSearchCondition(nextProps.id);
this.statisticsItemList(nextProps.id).then(r => {
});
}
if (nextProps.visible !== this.props.visible && !nextProps.visible) {
nextProps.form.resetForm();
this.setState({ selectedRowKeys: [] });
}
}
reportStatisticsGetSearchCondition = (id) => {
const { conditions } = this.state;
const { form } = this.props;
reportStatisticsGetSearchCondition({ id }).then(({ status, data }) => {
if (status && !_.isEmpty(data)) {
const { salaryEndMonth, salaryStartMonth, ...formData } = data.data;
this.setState({
salaryMonth: [salaryStartMonth || moment().startOf("year").format("YYYY-MM"), salaryEndMonth || moment().format("YYYY-MM")]
});
const fields = _.map(conditions[0].items, it => it.domkey[0]);
fields.map(item => {
const value = item.indexOf("hiredate") !== -1 ? {
value: formData["hiredate"] || []
} : {
value: !_.isNil(formData[item]) ? _.map(formData[item], val => val.id).join(",") : "",
valueSpan: !_.isNil(formData[item]) ? _.map(formData[item], val => val.name).join(",") : "",
valueObj: !_.isNil(formData[item]) ? formData[item] : []
};
const key = item.indexOf("hiredate") !== -1 ? "hiredate1__hiredate2" : item;
form.updateFields({
[key]: value
});
});
}
});
};
reportStatisticsSaveSearchCondition = () => {
const { salaryMonth, dataSource } = this.state;
const { form, id, dimension, onClose } = this.props;
const [salaryStartMonth, salaryEndMonth] = salaryMonth;
const { department, employee, position, subCompany, taxAgent, ...extra } = form.getFormDatas();
const { value, valueSpan } = taxAgent;
if (!salaryEndMonth || !salaryStartMonth) {
this.refs.weaError.showError();
return;
}
const payload = {
dimension, id,
hiredate: extra["hiredate1__hiredate2"].value || [],
department: _.map(department.valueObj, it => ({ id: it.id, name: it.name })),
employee: _.map(employee.valueObj, it => ({ id: it.id, name: it.name })),
// position: _.map(position.valueObj, it => ({ id: it.id, name: it.name })),
subCompany: _.map(subCompany.valueObj, it => ({ id: it.id, name: it.name })),
taxAgent: value ? _.map(value.split(","), (it, idx) => ({ id: it, name: valueSpan.split(",")[idx] })) : [],
items: dataSource,
salaryEndMonth: salaryEndMonth + "-01",
salaryStartMonth: salaryStartMonth + "-01"
};
this.setState({ loading: true });
reportStatisticsSaveSearchCondition(payload).then(({ status, errormsg }) => {
this.setState({ loading: false });
if (status) {
onClose(true);
message.success(getLabel(111, "保存成功"));
} else {
message.error(errormsg);
}
}).catch(() => this.setState({ loading: false }));
};
reportStatisticsItemDelete = () => {
Modal.confirm({
title: getLabel(111, "信息确认"),
content: getLabel(111, "确认要删除吗?"),
onOk: () => {
const { selectedRowKeys } = this.state;
reportStatisticsItemDelete(selectedRowKeys).then(({ status, errormsg }) => {
if (status) {
message.success(getLabel(111, "删除成功"));
this.setState({
selectedRowKeys: []
}, () => {
this.statisticsItemList(this.props.id).then(r => {
});
});
} else {
message.error(errormsg || getLabel(111, "删除失败"));
}
});
}
});
};
statisticsItemList = async (statisticsReportId = "") => {
const { data: unitTypeList } = await this.commonEnumList();
statisticsItemList({ statisticsReportId }).then(({ status, data }) => {
if (status) {
this.setState({
dataSource: data,
unitTypeList: _.map(unitTypeList, it => ({ key: it.value.toString(), showname: it.defaultLabel }))
});
}
});
};
commonEnumList = () => {
const payload = {
enumClass: "com.engine.salary.report.enums.UnitTypeEnum"
};
return commonEnumList(payload);
};
renderGroupTitle = () => {
return <div className="groupTitleWrapper">
<span>{getLabel(111, "统计数据范围")}</span>
<span>{getLabel(111, "统计满足以下所有条件的人员薪资核算数据,不选则默认为选择全部")}</span>
</div>;
};
renderProjectTitle = () => {
const { selectedRowKeys } = this.state;
const { id, dimension } = this.props;
return <div className="groupPorjectTitleWrapper">
<div>
<span>{getLabel(111, "统计项目")}</span>
<WeaHelpfulTip width={200} placement="topLeft"
title={getLabel(111, "统计列表的统计项排序与本列表统计项的顺序一致")}
/>
</div>
<div>
<WeaButtonIcon
buttonType="del" type="primary" disabled={_.isEmpty(selectedRowKeys)}
onClick={this.reportStatisticsItemDelete}
/>
<WeaButtonIcon
buttonType="add" type="primary"
onClick={() => this.setState({
statisticalItemPayload: {
visible: true, id, dimension,
statisticsItemId: ""
}
})}
/>
</div>
</div>;
};
render() {
const {
salaryMonth, conditions, selectedRowKeys, loading,
statisticalItemPayload, dataSource, unitTypeList
} = this.state;
const { id, dimension } = this.props;
const columns = [
{
title: "统计项名称",
dataIndex: "itemName",
render: (txt, record) => {
return (
<a href="javascript: void(0);" onClick={() => this.setState({
statisticalItemPayload: { visible: true, id, dimension, statisticsItemId: record.id }
})}>{txt}</a>
);
}
},
{
title: "统计单位",
dataIndex: "unitType",
render: (txt, record) => {
return <WeaSelect
value={!_.isNil(txt) ? txt.toString() : ""} options={unitTypeList} style={{ width: 150 }}
onChange={unitType => this.customStatisticsItemsRef.reportStatisticsItemSave({ id: record.id, unitType })}
/>;
}
}
];
const rowSelection = {
selectedRowKeys,
onChange: (selectedRowKeys) => {
this.setState({ selectedRowKeys });
}
};
return (
<WeaSlideModal
className="microSlideWrapper"
{...this.props}
onClose={() => this.props.onClose()}
top={0}
measureT="%"
width={800}
measureX="px"
height={100}
measureY="%"
direction={"right"}
title={<TitleDialog loading={loading} onSave={this.reportStatisticsSaveSearchCondition}/>}
content={
<React.Fragment>
<WeaSearchGroup title={getLabel(111, "统计时间范围")} col={2} showGroup needTigger>
<WeaFormItem label={getLabel(111, "薪资所属月")} labelCol={{ span: 8 }} wrapperCol={{ span: 16 }}>
<WeaError tipPosition="bottom" ref="weaError" error={getLabel(111, "此项必填")}>
<MonthRangePicker viewAttr={3} dateRange={salaryMonth}
onChange={v => this.setState({ salaryMonth: v })}/>
</WeaError>
</WeaFormItem>
</WeaSearchGroup>
{
getSearchs(this.props.form, conditions, 2, false, () => {
}, this.renderGroupTitle())
}
<WeaSearchGroup title={this.renderProjectTitle()} showGroup needTigger>
<WeaTable
rowKey="id"
columns={columns}
dataSource={dataSource}
draggable={true}
onDrop={datas => this.setState({
dataSource: _.map(datas, (it, idx) => ({ ...it, indexValue: idx.toString() }))
})}
pagination={false}
rowSelection={rowSelection}
/>
<CustomStatisticsItemsModal
ref={dom => this.customStatisticsItemsRef = dom}
{...statisticalItemPayload}
onCancel={(isRefresh) => this.setState({
statisticalItemPayload: {
visible: false,
id: "",
dimension: "",
statisticsItemId: ""
}
}, () => isRefresh && this.statisticsItemList(this.props.id))}
/>
</WeaSearchGroup>
</React.Fragment>
}
/>
);
}
}
export default StatisticalMicroSettingsSlide;
const TitleDialog = (props) => {
return <div className="titleDialog">
<div className="titleCol">
<div className="titleLeftBox">
<div className="titleIcon"><i className="icon-coms-fa"/></div>
<div className="title">{getLabel(111, "统计数据范围及规则设置")}</div>
</div>
</div>
<div className="titleCol titleRightBox">
<Button type="primary" loading={props.loading} onClick={props.onSave}>{getLabel(111, "保存")}</Button>
</div>
</div>;
};
const MonthRangePicker = (props) => {
const { dateRange, onChange, viewAttr } = props;
const [startDate, endDate] = dateRange || [];
return <div className="rangePickerBox">
<WeaDatePicker
value={startDate}
disabledDate={(current) => {
return current && endDate && current.getTime() > new Date(endDate).getTime();
}}
format="YYYY-MM"
onChange={(val) => onChange([val, endDate])}
viewAttr={viewAttr}
/>
<span className="to" style={{ margin: "0 10px" }}></span>
<WeaDatePicker
value={endDate}
disabledDate={(current) => {
return current && startDate && current.getTime() < new Date(startDate).getTime();
}}
format="YYYY-MM"
viewAttr={viewAttr}
onChange={(val) => onChange([startDate, val])}
/>
</div>;
};

View File

@ -0,0 +1,165 @@
/*
* Author: 黎永顺
* name: 薪酬报表查看
* Description:
* Date: 2023/4/20
*/
import React, { Component } from "react";
import { inject, observer } from "mobx-react";
import { WeaLeftRightLayout, WeaLocaleProvider, WeaSelect, WeaTop } from "ecCom";
import { message, Modal } from "antd";
import LeftTab from "./components/leftTab";
import ReportContent from "./components/reportContent";
import StatisticalMicroSettingsSlide from "./components/statisticalMicroSettingsSlide";
import { reportGetForm, reportStatisticsReportSave } from "../../apis/ruleconfig";
import "./index.less";
const { getLabel } = WeaLocaleProvider;
@inject("taxAgentStore", "attendanceStore")
@observer
class Index extends Component {
constructor(props) {
super(props);
this.state = {
report: {},
dimensionList: [],
statisticalPayload: {
visible: false, id: "", dimension: ""
}
};
}
componentDidMount() {
const { taxAgentStore: { getTaxAgentSelectListAsAdmin } } = this.props;
this.reportGetForm();
getTaxAgentSelectListAsAdmin();
}
reportGetForm = () => {
reportGetForm().then(({ status, data }) => {
if (status) {
const { statsDimOptions } = data;
this.setState({
dimensionList: _.map(statsDimOptions, it => ({ key: it.id, showname: it.content }))
});
}
});
};
/*
* Author: 黎永顺
* Description: 统计维度切换
* Params:
* Date: 2023/4/20
*/
handleChangeDimension = (dimensionId, dimension) => {
const { report } = this.state;
Modal.confirm({
title: getLabel(111, "信息确认"),
content: getLabel(111, "确认要更改统计维度吗?"),
onOk: () => {
const payload = {
id: report.id,
reportName: report.reportName,
dimensionIds: dimensionId.split(",")
};
reportStatisticsReportSave(payload).then(({ status, errormsg }) => {
this.setState({ loading: false });
if (status) {
message.success(getLabel(111, "切换成功"));
this.setState({
report: {
...report, dimensionId,
dimension
}
}, () => this.leftTabRef.updateReportList(this.state.report));
} else {
message.error(errormsg || getLabel(111, "切换失败"));
this.setState({ report: { ...report } });
}
});
},
onCancel: () => {
this.setState({ report: { ...report } });
}
});
};
/*
* Author: 黎永顺
* Description: 导出报表数据
* Params:
* Date: 2023/4/24
*/
exportData = () => {
const { report } = this.state;
const { id, dimensionId } = report;
window.open(`${window.location.origin}/api/bs/hrmsalary/report/statistics/report/exportData?id=${id}&dimensionId=${dimensionId}`, "_self");
};
render() {
const { report, dimensionList, statisticalPayload } = this.state;
const { attendanceStore: { settingForm }, taxAgentStore: { taxAgentAdminOption } } = this.props;
return (
<WeaTop
title={getLabel(111, "报表查看")}
icon={<i className="icon-coms-fa"/>}
iconBgcolor="#F14A2D"
showDropIcon={false}
className="reportViewWrapper"
>
<WeaLeftRightLayout
leftWidth={210}
leftCom={
<LeftTab
ref={dom => this.leftTabRef = dom}
onChangeTab={report =>
this.setState({
report,
statisticalPayload: { visible: false, id: "", dimension: "" }
})}
/>
}
>
<div className="rightLayout">
<div className="layoutHeader">
<div className="layoutRow">
<div className="layoutCol"><span className="leftColTitle">{report.reportName}</span></div>
<div className="layoutCol layoutColRight">
<div className="rightColTitle">
<div className="dimension">
<span>{getLabel(111, "统计维度")}</span>
<WeaSelect value={report.dimensionId} options={dimensionList}
onChange={(key, showname) => this.handleChangeDimension(key, showname)}/>
</div>
<div className="iconWrapper">
<i
className="icon-coms02-currency"
title={getLabel(111, "统计数据范围及规则设置")}
onClick={() => this.setState({
statisticalPayload: { visible: true, id: report.id, dimension: report.dimensionId }
})}
/>
<i className="icon-coms-export" onClick={this.exportData} title={getLabel(111, "导出")}/>
</div>
{/*统计数据范围及规则设置弹框*/}
<StatisticalMicroSettingsSlide
{...statisticalPayload} form={settingForm}
taxAgentAdminOption={taxAgentAdminOption}
onClose={(isRefresh) => this.setState({
statisticalPayload: { visible: false, id: "", dimension: "" }
}, () => isRefresh && this.reportRef.reportStatisticsReportGetData(report.id, report.dimensionId))}
/>
</div>
</div>
</div>
</div>
{/* 内容区 */}
<ReportContent ref={dom => this.reportRef = dom} report={report}/>
</div>
</WeaLeftRightLayout>
</WeaTop>
);
}
}
export default Index;

View File

@ -0,0 +1,304 @@
.reportViewWrapper {
height: 100%;
display: flex;
flex-direction: column;
.wea-new-top-content {
flex: 1;
.leftTabWrapper {
background: #FFF;
height: 100%;
overflow-y: auto;
.searchArea {
width: 100%;
height: 49px;
line-height: 49px;
padding: 0 6px;
.wea-input-focus {
width: 100%;
}
}
.ant-menu {
border-right-color: transparent !important;
.ant-menu-item, .ant-menu-item {
border-left: 4px solid transparent;
border-right: none;
}
.ant-menu-item-selected, .ant-menu-selected {
border-left: 4px solid #2db7f5;
background: #f5f5f5;
border-right: none;
}
.ant-menu-item-active, .ant-menu-item:hover, .ant-menu-submenu-active, .ant-menu-submenu-title:hover {
background: #f5f5f5;
}
}
}
.rightLayout {
display: flex;
flex-direction: column;
height: 100%;
.layoutHeader {
height: 50px;
.layoutRow {
height: 100%;
display: flex;
align-content: center;
padding: 8px 16px;
background-color: #f9f9f9;
border-bottom: 1px solid #e5e5e5;
.layoutCol {
flex: 1;
height: 100%;
display: flex;
align-items: center;
.rightColTitle {
height: 100%;
display: flex;
align-items: center;
white-space: nowrap;
i.icon-coms02-currency, i.icon-coms-export {
font-size: 16px;
color: #2db7f5;
cursor: pointer;
}
i.icon-coms02-currency {
margin: 0 10px;
}
.dimension {
display: flex;
align-items: center;
.wea-select {
width: 150px;
margin-left: 10px;
}
}
.iconWrapper {
display: flex;
align-items: center;
}
}
}
.layoutColRight {
justify-content: flex-end;
}
}
}
.layoutContent {
flex: 1;
display: flex;
justify-content: space-between;
width: 100%;
height: 100%;
.layoutBox {
flex: 1;
padding: 16px;
.ant-spin-nested-loading, .ant-spin-container {
height: 100%;
}
}
.layoutSide {
position: relative;
transition: width .3s cubic-bezier(.645, .045, .355, 1), height .3s cubic-bezier(.645, .045, .355, 1);
min-height: 1px;
.sideBox {
position: relative;
height: 100%;
width: 100%;
.sideMain {
width: 100%;
.toll-bar-container {
margin-top: 16px;
background-color: #fff;
border: 1px solid #e5e5e5;
height: 180px;
display: flex;
flex-direction: column;
justify-content: space-around;
i {
font-size: 16px;
color: #2db7f5 !important;
cursor: pointer;
}
}
}
.show-btn-right {
position: absolute;
cursor: pointer;
z-index: 100;
top: 60px;
left: -17px;
transform: rotate(180deg);
}
}
}
}
}
}
}
//统计数据范围及规则设置
.microSlideWrapper {
z-index: 999;
.wea-slide-modal-title {
height: auto !important;
line-height: normal !important;
}
.titleDialog {
display: flex;
padding: 10px 16px 10px 0;
position: relative;
background-color: #f6f6f6;
border-bottom: 1px solid #e5e5e5;
.titleCol {
flex: 1;
.titleLeftBox {
display: flex;
height: 100%;
align-items: center;
padding-left: 16px;
.titleIcon {
color: #fff;
margin: 0;
width: 40px;
height: 40px;
line-height: 40px;
font-size: 22px;
display: flex;
align-items: center;
justify-content: center;
background: #F14A2D;
border-radius: 50%;
}
.title {
font-size: 14px;
color: #333;
padding-left: 6px;
}
}
}
.titleRightBox {
display: flex;
justify-content: flex-end;
align-items: center;
padding-right: 30px;
}
}
.groupTitleWrapper {
display: flex;
justify-content: space-between;
& > span:last-child {
color: #666
}
}
.groupPorjectTitleWrapper {
display: flex;
justify-content: space-between;
align-items: center;
& > div:first-child {
display: flex;
align-items: center;
& > span:first-child {
padding-right: 8px;
}
}
& > div:last-child {
display: flex;
align-items: center;
.wea-button-icon:first-child {
margin-right: 10px;
}
}
}
.rangePickerBox {
display: flex;
align-items: center;
}
}
//新建自定义统计项目
.statisticItemsWrapper {
.itemsTitle {
display: flex;
align-items: center;
justify-content: space-between;
}
.statisticItemsBox {
padding: 16px;
.wea-error {
width: 100%;
}
.wea-form-item {
padding: 5px 16px;
border: 1px solid #e5e5e5;
}
.wea-form-item:first-child {
border-bottom: none;
}
}
.customRuleTableWrapper {
margin-top: 16px;
.intervalSettingsCompWrapper {
display: flex;
align-items: center;
span.increaseTitle {
padding: 0 8px;
display: inline-block;
width: 230px;
}
span.pecentTitle {
padding-left: 8px;
}
}
}
}

View File

@ -491,7 +491,8 @@ export default class Archives extends React.Component {
break;
case "suspend":
dom = <div>
<div>1数据进入待减员规则①员工的人事状态属性从在职变成非在职且在在缴员工在缴员工里档案维护了缴纳终止月且小于等于当前月③个税扣缴义务人发生调整④某员工分权时在原个税扣缴义务人下处于在缴员工里但又将该员工添加到其他的个税扣缴义务人下的情况</div>
{/*④某员工分权时在原个税扣缴义务人下处于【在缴员工】里但又将该员工添加到其他的个税扣缴义务人下的情况;*/}
<div>1数据进入待减员规则①员工的人事状态属性从在职变成非在职且在在缴员工在缴员工里档案维护了缴纳终止月且小于等于当前月③个税扣缴义务人发生调整</div>
<div>2待减员为是否不再缴纳的待办状态数据是从在缴员工中复制的若不处理列表中的待办数据也不影响社保福利核算待减员维护的数据和在缴员工数据是同步的</div>
<div>3点击减员前先维护最后缴纳月所有有起始缴纳月的福利项的最后缴纳月都小于等于当前月且无未归档的核算数据的档案才能减员成功减员成功后数据进入停缴员工</div>
{/*<div>4、数据进入【待减员】规则的第四种情况下若还需要在当前个税扣缴义务人下进行缴纳的话当前该员工的【待减员】数据进行【删除待办】操作即可若不在该个税扣缴义务人下继续缴纳维护好最后缴纳月后进行【减员】操作员工进入【停缴员工】</div>*/}
@ -500,7 +501,7 @@ export default class Archives extends React.Component {
default:
dom = <div>
<div>1不需要缴纳社保福利的员工保存在停缴员工</div>
<div>2停缴员工点击取消停缴数据会回退到上次的位置待减员减员到停缴员工的点击停缴返回到在缴员工不返回到待减员</div>
{/*<div>2、【停缴员工】点击取消停缴数据会回退到上次的位置从【待减员】减员到停缴员工的点击停缴返回到【在缴员工】不返回到【待减员】</div>*/}
{/*<div>3、若员工的社保福利从一个个税扣缴义务人下转到另一个个税扣缴义务人下去缴纳则在转后的个税扣缴义务人的【待增员】中进行增员操作成功后员工进入待【在缴员工】而在原个税扣缴义务人下的【停缴员工】中该员工数据将会被删除是否开启分权员工的档案数据都只保存一份</div>*/}
</div>;
break;

View File

@ -77,6 +77,9 @@
.tableWrapper {
flex: 1;
overflow: hidden;
.ant-spin-nested-loading, .ant-spin-container {
height: 100%;
}
}
.tdEllipsis {

View File

@ -13,8 +13,7 @@ import { getQueryString } from "../../../../util/url";
import ProgressModal from "../../../../components/progressModal";
import AcctResultImportModal from "../../../calculateDetail/acctResult/importModal/acctResultImportModal";
import AdjustmentSlide from "./adjustmentSlide";
import { getCalculateProgress, siaccountDetailCommonListSum } from "../../../../apis/calculate";
import { sysConfCodeRule } from "../../../../apis/ruleconfig";
import { getCalculateProgress } from "../../../../apis/calculate";
import RegEditDetial from "./regEditDetial";
import SupplementarySlide from "./supplementarySlide";
import _ from "lodash";
@ -76,13 +75,7 @@ export default class NormalIndex extends Component {
handleReceive = async ({ data }) => {
const { type, payload: { id, params } = {} } = data;
if (type === "init") {
const { selectedKey } = this.props;
const { status, data: sysData } = await this.sysConfCodeRule();
const { data: { sumRow: siaccountSum } } = await this.siaccountDetailCommonListSum();
this.setState({
showSum: selectedKey === "1" && status && sysData === "1",
siaccountSum
}, () => this.postMessageToChild());
this.postMessageToChild();
} else if (type === "turn") {
if (id === "PAGEINFO") {
const { pageNum: current, size: pageSize } = params;
@ -105,13 +98,6 @@ export default class NormalIndex extends Component {
}
}
};
sysConfCodeRule = () => {
return sysConfCodeRule({ code: "OPEN_ACCT_RESULT_SUM" });
};
siaccountDetailCommonListSum = () => {
const { billMonth, paymentOrganization } = this.props;
return siaccountDetailCommonListSum({ billMonth, paymentOrganization });
};
componentWillUnmount() {
if (this.timer) {
@ -138,20 +124,22 @@ export default class NormalIndex extends Component {
}
postMessageToChild = () => {
const billMonth = getQueryString("billMonth");
const paymentOrganization = getQueryString("paymentOrganization");
const childFrameObj = document.getElementById("atdTable");
const { current, pageSize, tableData, selectedRowKeys, showSum, siaccountSum } = this.state;
const { current, pageSize, tableData, selectedRowKeys, showSum, siaccountSum, searchValue: userName } = this.state;
const { list: dataSource, total, columns } = tableData;
const pageInfo = { current, pageSize, total };
childFrameObj.contentWindow.postMessage(JSON.stringify({
dataSource, columns, pageInfo,
selectedRowKeys, showSum, siaccountSum,
selectedRowKeys, selectedKey: this.props.selectedKey,
sumpayload: { billMonth, paymentOrganization, userName },
showOperates: !getQueryString("type")
}), "*");
};
handleSearch(value) {
const { billMonth, selectedKey, paymentOrganization } = this.props;
const { current } = this.state;
selectedKey === "1"
? this.getNormalList({
billMonth,
@ -242,27 +230,19 @@ export default class NormalIndex extends Component {
}
};
getNormalList = async (payload = {}) => {
const { status, data: sysData } = await this.sysConfCodeRule();
const { data: { sumRow: siaccountSum } } = await this.siaccountDetailCommonListSum();
const { getNormalList } = this.props.standingBookStore;
getNormalList({ ...payload }).then(({ list, columns = [], total }) => {
this.setState({
showSum: this.props.selectedKey === "1" && status && sysData === "1",
siaccountSum,
tableData: { list, total, columns }
}, () => this.postMessageToChild());
});
};
getSupplementaryList = async (payload = {}) => {
const { status, data: sysData } = await this.sysConfCodeRule();
const { data: { sumRow: siaccountSum } } = await this.siaccountDetailCommonListSum();
const { getSupplementaryList } = this.props.standingBookStore;
getSupplementaryList({
...payload
}).then(({ list, columns = [], total }) => {
this.setState({
showSum: this.props.selectedKey === "1" && status && sysData === "1",
siaccountSum,
tableData: { list, columns, total }
}, () => this.postMessageToChild());
});

View File

@ -270,7 +270,7 @@ class RegEditDetial extends Component {
}
</div>
}
onClose={onCancel}
onClose={() => onCancel()}
showMask={true}
/>
);

View File

@ -5,7 +5,7 @@
* Date: 2022/11/23
*/
import React, { Component } from "react";
import { WeaTable } from "ecCom";
import { Spin } from "antd";
import { getQueryString } from "../../../../util/url";
import * as API from "../../../../apis/standingBook";
import "./index.less";
@ -25,6 +25,7 @@ class RegList extends Component {
loading: {
query: false
},
datalistPayload: {},
pageInfo: {
current: 1,
pageSize: 10,
@ -35,14 +36,52 @@ class RegList extends Component {
componentDidMount() {
this.recessionList();
window.addEventListener("message", this.handleReceive, false);
}
handleReceive = async ({ data }) => {
const { onEdit, onChangeRowkey } = this.props;
const { type, payload: { id, params } = {} } = data;
if (type === "init") {
this.postMessageToChild();
} else if (type === "turn") {
if (id === "PAGEINFO") {
const { pageNum: current, size: pageSize } = params;
this.setState({ pageInfo: { ...this.state.pageInfo, current, pageSize } }, () => this.recessionList());
} else if (id === "ROWSELECT") {
const { selectedRowKeys } = params;
this.setState({ selectedRowKeys });
onChangeRowkey(selectedRowKeys);
} else if (id === "EDIT") {
onEdit(params);
}
}
};
postMessageToChild = () => {
const paymentStatus = this.props.type === "difference" ? "4" : "3";
const creator = Number(getQueryString("creator"));
const billMonth = getQueryString("billMonth");
const paymentOrganization = getQueryString("paymentOrganization");
const childFrameObj = document.getElementById("atdTable");
const { pageInfo, dataSource, columns, selectedRowKeys, datalistPayload } = this.state;
childFrameObj.contentWindow.postMessage(JSON.stringify({
dataSource, columns, pageInfo,
selectedRowKeys, selectedKey: this.props.type,
sumpayload: { billMonth, paymentOrganization, creator, paymentStatus, ...datalistPayload },
showOperates: !getQueryString("type")
}), "*");
};
componentWillReceiveProps(nextProps, nextContext) {
if (nextProps.visible !== this.props.visible) {
this.recessionList();
}
}
componentWillUnmount() {
window.removeEventListener("message", this.handleReceive, false);
}
handleResetSelectRowKeys = (selectedRowKeys) => {
this.setState({ selectedRowKeys });
};
@ -52,7 +91,7 @@ class RegList extends Component {
const billMonth = getQueryString("billMonth");
const paymentOrganization = getQueryString("paymentOrganization");
const creator = Number(getQueryString("creator"));
const paymentStatus = "3";
const paymentStatus = type === "difference" ? "4" : "3";
const payload = {
billMonth, paymentStatus,
creator, paymentOrganization,
@ -68,105 +107,26 @@ class RegList extends Component {
this.setState({
pageInfo: { ...pageInfo, current, pageSize, total },
dataSource,
columns: _.map(_.filter(columns, it => it.dataIndex !== "id"), items => {
if (items.dataIndex === "employeeId") {
return {
...items,
width: 110,
title: "姓名",
render: (text, r) => {
const { userName } = r;
return (
<span>{userName}</span>
);
}
};
} else if (items.dataIndex === "costCenter") {
return {
...items,
width: 110,
render: (text, r) => {
const { costCenter } = r;
return (
<a href={costCenter.url} className="tdEllipsis">{costCenter.name || ""}</a>
);
}
};
}
return {
...items,
title: <span dangerouslySetInnerHTML={{ __html: items.title }}/>,
width: 120,
render: (text) => {
return <span className="tdEllipsis" title={text}>{text}</span>;
}
};
})
});
columns,
datalistPayload: module
}, () => this.postMessageToChild());
}
}).catch(() => {
this.setState({ loading: { ...loading, query: false } });
});
};
handleChangeRow = (selectedRowKeys) => {
const { onChangeRowkey } = this.props;
this.setState({ selectedRowKeys });
onChangeRowkey(selectedRowKeys);
};
render() {
const { loading, pageInfo, selectedRowKeys, dataSource, columns } = this.state;
const { onEdit } = this.props;
const pagination = {
...pageInfo,
showTotal: total => `${total}`,
showQuickJumper: true,
showSizeChanger: true,
pageSizeOptions: ["10", "20", "50", "100"],
onShowSizeChange: (current, pageSize) => {
this.setState({ pageInfo: { ...pageInfo, current, pageSize } }, () => {
this.recessionList();
});
},
onChange: (current) => {
this.setState({ pageInfo: { ...pageInfo, current } }, () => {
this.recessionList();
});
}
};
const rowSelection = {
selectedRowKeys,
onChange: this.handleChangeRow
};
const { loading } = this.state;
return (
<WeaTable
rowKey="id"
columns={!getQueryString("type") ? [
...columns,
{
title: "操作",
dataIndex: "operate",
fixed: "right",
width: "120px",
render: (text, record) => {
return (
<div className="optWrapper">
<a
href="javascript:void(0);"
className="mr10"
onClick={() => onEdit(record)}
>编辑</a>
</div>
);
}
}
] : [...columns]}
dataSource={dataSource}
loading={loading.query}
pagination={pagination}
rowSelection={rowSelection}
scroll={{ x: 900 }}
/>
<Spin spinning={loading.query}>
<iframe
style={{ border: 0, width: "100%", height: "100%" }}
// src="http://localhost:7607/#/standingbookTable"
src="/spa/hrmSalary/hrmSalaryCalculateDetail/index.html#/standingbookTable"
id="atdTable"
/>
</Spin>
);
}
}

View File

@ -134,7 +134,7 @@ class Regression extends Component {
selectKey={selectKey}
/>
<div className="tableWrapper">
<WeaNewScroll height="100%">
{/*<WeaNewScroll height="100%">*/}
<RegList
type="regression"
ref={dom => this.regListRef = dom}
@ -152,7 +152,7 @@ class Regression extends Component {
onCancel={this.handleCloseModal}
onSave={this.handleSave}
/>
</WeaNewScroll>
{/*</WeaNewScroll>*/}
</div>
</div>
);

View File

@ -1,6 +1,6 @@
import React from "react";
import { inject, observer } from "mobx-react";
import { Button, Col, message, Modal, Row, Switch, Dropdown, Menu } from "antd";
import { Button, Col, Dropdown, Menu, message, Modal, Row, Switch } from "antd";
import { WeaFormItem, WeaInputSearch, WeaSearchGroup, WeaTable, WeaTop } from "ecCom";
import { renderNoright } from "../../util"; // 渲染form数据的方法因为多个页面都会使用所以抽的公共方法在util中
import EditModal from "./editModal";
@ -303,7 +303,8 @@ export default class TaxAgent extends React.Component {
columns,
doInit,
hasRight,
getTaxAgentList
getTaxAgentList,
showOperateBtn
} = taxAgentStore;
if (!hasRight && !loading) {
@ -369,7 +370,7 @@ export default class TaxAgent extends React.Component {
</Menu>
}>
<a className="ant-dropdown-link" href="javaScript:void(0);">
<i className="icon-coms-more" />
<i className="icon-coms-more"/>
</a>
</Dropdown>
</div>
@ -403,7 +404,7 @@ export default class TaxAgent extends React.Component {
title="个税扣缴义务人" // 文字
icon={<i className="icon-coms-fa"/>} // 左侧图标
iconBgcolor="#F14A2D" // 左侧图标背景色
buttons={btns}
buttons={showOperateBtn ? btns : btns.slice(1)}
showDropIcon={true}>
<Row
gutter={16}

View File

@ -5,4 +5,9 @@ import { WeaForm } from "comsMobx";
export class AttendanceStore {
@observable form = new WeaForm();
@observable refenceform = new WeaForm();
//薪酬统计 新增form
@observable statisticsForm = new WeaForm();
@observable reportForm = new WeaForm();
//报表查看 统计数据范围及规则设置form
@observable settingForm = new WeaForm();
}

View File

@ -16,6 +16,7 @@ export class TaxAgentStore {
@observable showSearchAd = false; // 高级搜索面板显示
@observable showOperateBtn = false; // 页面操作按钮显示权限
@observable showSalaryItemBtn = false; // 薪资项目管理页面操作按钮显示权限
@observable statisticsReportBtn = false; // 薪酬统计报表页面操作按钮显示权限
@observable loading = false; // 数据加载状态
@observable modalVisiable = false; // EditModal 模态框
@observable columns = [];
@ -37,6 +38,7 @@ export class TaxAgentStore {
@action setShowOperateBtn = bool => (this.showOperateBtn = bool);
@action setSalaryItemBtn = bool => (this.showSalaryItemBtn = bool);//薪资项目权限
@action setStatisticsReportBtn = bool => (this.statisticsReportBtn = bool);//薪酬统计报表权限
// 初始化操作
@action
@ -141,6 +143,8 @@ export class TaxAgentStore {
!isOpenDevolution ? true : isAdminEnable ? true : false
);
this.setSalaryItemBtn((isOpenDevolution && (isChief || isAdminEnable)));
//薪酬统计报表权限
this.setStatisticsReportBtn(!isOpenDevolution ? true : !!(isAdminEnable || isChief));
resolve({ status, data });
} else {
reject();

View File

@ -1,21 +1,89 @@
import moment from 'moment'
import moment from "moment";
import { WeaLocaleProvider } from "ecCom";
const getLabel = WeaLocaleProvider.getLabel;
// 获取当前年月
export const getCurrentYearMonth = () => {
return moment(new Date()).format("YYYY-MM")
}
return moment(new Date()).format("YYYY-MM");
};
// 获取当前月份
export const getCurrentMonth = () => {
return (new Date()).getMonth() + 1
}
return (new Date()).getMonth() + 1;
};
// 获取前几个月的年月
export const getSubtractMonthYearMonth = (subtract = 1) => {
return moment(new Date()).subtract(subtract,'months').startOf('month').format('YYYY-MM')
}
return moment(new Date()).subtract(subtract, "months").startOf("month").format("YYYY-MM");
};
// 获取后几个月的年月
export const getAddMonthYearMonth = (add = 1) => {
return moment(new Date()).add(add,'months').startOf('month').format('YYYY-MM')
}
return moment(new Date()).add(add, "months").startOf("month").format("YYYY-MM");
};
/**
* 数字前面补零
* @param num
* @param length
*/
export const prefixAddZero = (num, length) => {
return (Array(length).join("0") + num).slice(-length);
};
/**
* 获取月份天数
* @param year
* @param month
*/
export const getMonthDays = (year, month) => {
const d = new Date(Number(year), Number(month), 0);
return d.getDate();
};
export const generateBasicInfo = (monthCal, nowYear, nowMonth) => {
let nowMonthStr = "", nextMonthStr = "";
switch (monthCal) {
case -2:
nowMonthStr = getLabel(111, "上上月");
nextMonthStr = getLabel(111, "上月");
break;
case -1:
nowMonthStr = getLabel(111, "上月");
nextMonthStr = getLabel(111, "本月");
break;
case 0:
nowMonthStr = getLabel(111, "本月");
nextMonthStr = getLabel(111, "下月");
break;
case 1:
nowMonthStr = getLabel(111, "下月");
nextMonthStr = getLabel(111, "下下月");
break;
}
let year, month;
if (monthCal < 0) {
let monthCalAbs = Math.abs(monthCal);
if (nowMonth <= monthCalAbs) {
// 跨年
year = (nowYear - 1).toString();
month = (12 - (monthCalAbs - nowMonth)).toString();
} else {
// 未跨年
year = nowYear.toString();
month = (nowMonth - monthCalAbs).toString();
}
} else if (monthCal === 0) {
year = nowYear.toString();
month = nowMonth.toString();
} else {
if (nowMonth + monthCal > 12) {
year = (nowYear + 1).toString();
month = (nowMonth + monthCal - 12).toString();
} else {
year = nowYear.toString();
month = (nowMonth + monthCal).toString();
}
}
return { year, month, nowMonthStr, nextMonthStr };
};

View File

@ -1,65 +1,35 @@
import { Spin } from 'antd';
import { WeaSwitch } from 'comsMobx';
import { WeaLocaleProvider, WeaAlertPage, WeaSearchGroup, WeaFormItem } from 'ecCom';
import { Spin } from "antd";
import { WeaSwitch } from "comsMobx";
import { WeaAlertPage, WeaFormItem, WeaHelpfulTip, WeaLocaleProvider, WeaSearchGroup } from "ecCom";
const getLabel = WeaLocaleProvider.getLabel;
// 渲染form表单: 一般对form的渲染都统一使用该方法
export const getCustomSearchs = (form, condition, col, isCenter) => {
const { isFormInit } = form;
const formParams = form.getFormParams();
let items = [];
let group = [];
isFormInit && condition &&
condition.map(c =>{
c.items.map(fields => {
items.push({
com:(
<WeaFormItem
label={`${fields.label}`} // label 标签的文本
labelCol={{span: `${fields.labelcol}`}} // label标签占一行比例
wrapperCol={{span: `${fields.fieldcol}`}} // 右侧控件占一行比例
error={form.getError(fields)} // 错误提示: 处理表单中有必填项,保存的校验
tipPosition="bottom" // 错误提示的显示位置: top/bottom
>
<WeaSwitch
fieldConfig={fields}
form={form}
formParams={formParams}
/>
</WeaFormItem>),
colSpan:1,
})
});
// 获取condition的domKey值
export const getConditionDomkeys = (condition) => {
let domkeyList = [];
_.forEach(condition, item => {
const tmpV = _.reduce(item.items, (pre, cur) => {
return [...pre, cur["domkey"][0]];
}, []);
domkeyList = domkeyList.concat(tmpV);
});
if(items.length > 0) {
group.push(
<WeaSearchGroup
col={col || 1} // 高级搜索列布局列数
needTigger={true} // 是否开启收缩
title={''} // 高级搜索标题
showGroup={true} // 是否开启面板
items={items} // 条目数组数据
center={isCenter || false} // 内容是否居中:一般弹框需要
/>)
return group;
}
}
return domkeyList;
};
// 渲染form表单: 一般对form的渲染都统一使用该方法
export const getSearchs = (form, condition, col, isCenter) => {
export const getSearchs = (form, condition, col, isCenter, onChange = () => void (0), title) => {
const { isFormInit } = form;
const formParams = form.getFormParams();
let group = [];
isFormInit && condition && condition.map(c =>{
isFormInit && condition && condition.map(c => {
let items = [];
c.items.map(fields => {
items.push({
com:(
com: (
<WeaFormItem
label={`${fields.label}`} // label 标签的文本
labelCol={{span: `${fields.labelcol}`}} // label标签占一行比例
wrapperCol={{span: `${fields.fieldcol}`}} // 右侧控件占一行比例
labelCol={{ span: `${fields.labelcol}` }} // label标签占一行比例
wrapperCol={{ span: `${fields.fieldcol}` }} // 右侧控件占一行比例
error={form.getError(fields)} // 错误提示: 处理表单中有必填项,保存的校验
tipPosition="bottom" // 错误提示的显示位置: top/bottom
>
@ -67,39 +37,44 @@ export const getSearchs = (form, condition, col, isCenter) => {
fieldConfig={fields}
form={form}
formParams={formParams}
onChange={onChange}
/>
{
fields.helpfulTitle &&
<WeaHelpfulTip title={fields.helpfulTitle} style={{ position: "absolute", right: "-20px", top: "25%" }}/>
}
</WeaFormItem>),
colSpan:1,
})
colSpan: 1
});
});
group.push(
<WeaSearchGroup
col={col || 1} // 高级搜索列布局列数
needTigger={true} // 是否开启收缩
title={c.title || ''} // 高级搜索标题
title={c.title || title} // 高级搜索标题
showGroup={c.defaultshow} // 是否开启面板
items={items} // 条目数组数据
center={isCenter || false} // 内容是否居中:一般弹框需要
/>)
/>);
});
return group;
}
};
// 页面加载中效果处理
export const renderLoading = (loading) => (
<div className="wea-demo-loading">
<Spin spinning={loading} />
<Spin spinning={loading}/>
</div>
)
);
// 无权限处理
export const renderNoright = () => (
<WeaAlertPage>
<div>
{getLabel(2012,'对不起,您暂时没有权限!')}
{getLabel(2012, "对不起,您暂时没有权限!")}
</div>
</WeaAlertPage>
)
);
// 暂无数据处理
export const renderNoData = () => (
@ -108,13 +83,13 @@ export const renderNoData = () => (
暂无数据
</div>
</WeaAlertPage>
)
);
//分页计算
export function calcPageNo (total, pageNo = 1, pageSize = 10, selectDelDataLen = 1) {
const totalPage = Math.ceil((total - selectDelDataLen) / pageSize) // 总页数
pageNo = pageNo > totalPage ? totalPage : pageNo
pageNo = pageNo < 1 ? 1 : pageNo
return pageNo
export function calcPageNo(total, pageNo = 1, pageSize = 10, selectDelDataLen = 1) {
const totalPage = Math.ceil((total - selectDelDataLen) / pageSize); // 总页数
pageNo = pageNo > totalPage ? totalPage : pageNo;
pageNo = pageNo < 1 ? 1 : pageNo;
return pageNo;
}

View File

@ -22,3 +22,18 @@ export const getQueryString = (variable) => {
}
return null;
};
export const convertToUrlString = (data) => {
const _result = [];
for (const key in data) {
const value = data[key];
if (value.constructor === Array) {
value.forEach(function (_value) {
_result.push(key + "=" + _value);
});
} else {
_result.push(key + "=" + value);
}
}
return _result.join("&");
};