salary-management-front/pc4mobx/hrmSalary/pages/calculate/doCalc/index.js

305 lines
13 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* Author: 黎永顺
* name: 薪资核算详情
* Description:
* Date: 2023/9/13
*/
import React, { Component } from "react";
import { WeaLocaleProvider, WeaReqTop, WeaLoadingGlobal } from "ecCom";
import { Button, Dropdown, Menu, message, Modal } from "antd";
import { inject, observer } from "mobx-react";
import Layout from "./layout";
import {
acctresultAccounting,
getSalaryacctRole,
getApprovalInfoByRecordId,
getCalculateProgress,
fileSalaryAcct,
refuseSalaryacct,
approvalSalaryacct
} from "../../../apis/calculate";
import AdvanceInputBtn from "./components/advanceInputBtn";
import SalaryCalcPersonConfirm from "./components/salaryCalcPersonConfirm";
import SalaryEditCalc from "./components/salaryEditCalc";
import ProgressModal from "../../../components/progressModal";
import CustomCalcExportDialog from "./components/customCalcExportDialog";
import SalaryEditCalcImport from "./components/salaryEditCalcImport";
import { convertToUrlString } from "../../../util/url";
import "./index.less";
const getLabel = WeaLocaleProvider.getLabel;
@inject("calculateStore") @observer
class Index extends Component {
constructor(props) {
super(props);
this.state = {
selectedKey: "person",
progressVisible: false,
progress: 0,
customExpDialog: { visible: false, salaryAcctRecordId: "", checkItems: [], itemsByGroup: [] },
salaryImpDialog: { visible: false, title: "", salaryAcctRecordId: "" },
approvalInfo: {},//审批信息,
accountExceptInfo: "" //核算报错信息,
};
this.calc = null;
this.timer = null;
}
init = async () => {
const { routeParams: { salaryAcctRecordId } } = this.props;
const { data } = await getSalaryacctRole({ id: salaryAcctRecordId });
getApprovalInfoByRecordId({ salaryAcctRecordId }).then(({ status, data: approvalInfo }) => {
if (status) this.setState({ approvalInfo: { ...approvalInfo, salaryacctRole: data } });
});
};
handleMenuClick = ({ key }) => {
const { routeParams: { salaryAcctRecordId } } = this.props;
switch (key) {
case "calc_selected":
const { selectedRowKeys } = this.calc.calcTableRef.wrappedInstance.state;
if (_.isEmpty(selectedRowKeys)) {
message.warning(getLabel(543303, "请选择表格数据!"));
return;
}
this.doCacl(key, selectedRowKeys);
break;
case "zy_refuse":
WeaLoadingGlobal.start();
refuseSalaryacct({ id: salaryAcctRecordId }).then(({ status, errorMsg }) => {
WeaLoadingGlobal.destroy();
if (status) {
message.success(getLabel(111, "操作成功"));
this.calc.onAdSearch(false);
} else {
message.error(errorMsg);
}
}).catch(() => WeaLoadingGlobal.destroy());
break;
case "zy_approval":
WeaLoadingGlobal.start();
approvalSalaryacct({ id: salaryAcctRecordId }).then(({ status, errorMsg }) => {
WeaLoadingGlobal.destroy();
if (status) {
message.success(getLabel(111, "操作成功"));
this.calc.onAdSearch(false);
} else {
message.error(errorMsg);
}
}).catch(() => WeaLoadingGlobal.destroy());
break;
case "zy_file":
WeaLoadingGlobal.start();
fileSalaryAcct({ id: salaryAcctRecordId }).then(({ status, errorMsg }) => {
WeaLoadingGlobal.destroy();
if (status) {
message.success(getLabel(111, "操作成功"));
this.calc.onAdSearch(false);
} else {
message.error(errorMsg);
}
}).catch(() => WeaLoadingGlobal.destroy());
break;
default:
break;
}
};
doCacl = (key, selectedRowKeys = []) => {
Modal.confirm({
title: getLabel(131329, "信息确认"),
content: getLabel(543544, "点击核算,公式项将按照公式逻辑核算,核算结果将覆盖原数据"),
onOk: () => {
const { routeParams: { salaryAcctRecordId } } = this.props;
this.setState({ progress: 0 });
let payload = { salaryAcctRecordId };
if (key === "calc_selected") payload = _.assign(payload, { ids: selectedRowKeys });
acctresultAccounting(payload).then(() => {
this.setState({ progressVisible: true });
if (this.timer) clearInterval(this.timer);
this.timer = setInterval(() => {
getCalculateProgress(salaryAcctRecordId).then(({ data }) => {
let progress = data.progress;
if (progress === 1 && this.timer) {
clearInterval(this.timer);
this.timer = null;
this.setState({
progressVisible: false, accountExceptInfo: data.message
});
message.success(getLabel(542321, "核算完成"));
this.calc.onAdSearch(false);
} else if (!data.status) {
clearInterval(this.timer);
this.timer = null;
this.setState({
progressVisible: false, accountExceptInfo: data.message
});
message.error(data.message);
}
this.setState({ progress: Number(progress) * 100 });
});
}, 1000);
});
}
});
};
handleMoreMenuClick = ({ key }) => {
const { calculateStore: { ECSearchForm }, routeParams: { salaryAcctRecordId } } = this.props;
switch (key) {
case "exportAll":
const { consolidatedTaxation, ...extra } = ECSearchForm.getFormParams();
const payload = { ...extra, consolidatedTaxation: consolidatedTaxation === "0" ? "" : consolidatedTaxation };
const url = `/api/bs/hrmsalary/salaryacct/acctresult/export?salaryAcctRecordId=${salaryAcctRecordId}&ids=&${convertToUrlString(payload)}`;
window.open(`${window.ecologyContentPath || ""}${url}`, "_blank");
break;
case "export_custom":
getExportField({ salaryAcctRecordId }).then(({ status, data }) => {
if (status) {
const { checkItems, itemsByGroup } = data;
this.setState({
customExpDialog: {
...this.state.customExpDialog, visible: true, salaryAcctRecordId, checkItems, itemsByGroup
}
});
}
});
break;
case "import":
this.setState({
salaryImpDialog: {
...this.state.salaryImpDialog, salaryAcctRecordId, visible: true, title: getLabel(111, "薪资导入")
}
});
break;
case "offlineCompare":
window.open(`/spa/hrmSalary/static/index.html#/main/hrmSalary/calcOc/${salaryAcctRecordId}`, "_blank");
break;
case "LOCK":
case "UNLOCK":
const { selectedRowKeys } = this.calc.calcTableRef.wrappedInstance.state;
if (_.isEmpty(selectedRowKeys)) {
message.warning(getLabel(543303, "请选择表格数据!"));
return;
}
this.calc.calcTableRef.wrappedInstance.updateEmpLockStatus({ lockStatus: key, acctEmpIds: selectedRowKeys });
break;
default:
break;
}
};
renderReqBtns = () => {
const { routeParams: { salaryAcctRecordId } } = this.props;
const { selectedKey, accountExceptInfo, approvalInfo } = this.state;
const { isOpenApproval, approvalWorkflowUrl, canEdit, salaryacctRole } = approvalInfo;
let reqBtns = [];
switch (selectedKey) {
case "calc":
const menu = (<Menu onClick={this.handleMenuClick}>
<Menu.Item key="calc_selected">{getLabel(543546, "核算所选人员")}</Menu.Item>
</Menu>);
const moreMenu = (<Menu onClick={this.handleMoreMenuClick}>
{canEdit && <Menu.Item key="import">{getLabel(32935, "导入")}</Menu.Item>}
<Menu.Item key="exportAll">{getLabel(81272, "导出全部")}</Menu.Item>
<Menu.Item key="export_custom">{getLabel(544270, "自定义导出")}</Menu.Item>
<Menu.Item key="offlineCompare">{getLabel(543249, "线下对比")}</Menu.Item>
<Menu.Item key="LOCK">{getLabel(111, "批量锁定")}</Menu.Item>
<Menu.Item key="UNLOCK">{getLabel(111, "批量解锁")}</Menu.Item>
</Menu>);
reqBtns = [<Dropdown.Button onClick={() => this.doCacl("ALL")} overlay={menu} type="primary">
{getLabel(543545, "核算所有人")}
</Dropdown.Button>,
<Dropdown overlay={moreMenu}><Button type="ghost">{getLabel(17499, "更多")}</Button></Dropdown>,
<AdvanceInputBtn onOpenAdvanceSearch={() => this.calc.openAdvanceSearch()}
onAdvanceSearch={() => this.calc.onAdSearch(false)}/>];
!canEdit && reqBtns.splice(0, 1);
/*
* Author: 黎永顺
* Description:(宁波百川港通国际物流有限公司二开) 结果为“jl”显示“归档”和“退回”按钮;结果为“zy”显示“提交审批”按钮
* Params:salaryacctRole
* Date: 2026/3/25
*/
salaryacctRole === "jl" && reqBtns.unshift(<Button type="ghost"
onClick={() => this.handleMenuClick({ key: "zy_file" })}>{getLabel(111, "归档")}</Button>);
salaryacctRole === "jl" && reqBtns.unshift(<Button type="ghost"
onClick={() => this.handleMenuClick({ key: "zy_refuse" })}>{getLabel(111, "退回")}</Button>);
salaryacctRole === "zy" && reqBtns.unshift(<Button type="ghost"
onClick={() => this.handleMenuClick({ key: "zy_approval" })}>{getLabel(111, "提交审批")}</Button>);
isOpenApproval && reqBtns.unshift(<Button type="ghost" onClick={() => {
window.open(`${approvalWorkflowUrl}&salaryAcctRecordId=${salaryAcctRecordId}`, "_blank");
}}>{getLabel(111, "发起审批")}</Button>);
accountExceptInfo && reqBtns.unshift(<i className="iconfont icon-jinggao"
title={getLabel(111, "存在异常信息,点击下载!")}
onClick={() => this.downloadTxtfile(accountExceptInfo)}/>);
break;
default:
break;
}
return reqBtns;
};
downloadTxtfile = (value) => {
const element = document.createElement("a");
const file = new Blob([value], { type: "text/plain" });
element.href = URL.createObjectURL(file);
element.download = "核算异常信息.txt";
document.body.appendChild(element);
element.click();
};
renderContent = () => {
const { selectedKey, approvalInfo } = this.state;
const { canEdit } = approvalInfo;
let dom = null;
switch (selectedKey) {
case "person":
dom = <SalaryCalcPersonConfirm calcDetail={!canEdit} {...this.props}/>;
break;
case "calc":
dom = <SalaryEditCalc {...this.props} calcDetail={!canEdit} ref={dom => this.calc = dom}/>;
break;
default:
break;
}
return dom;
};
render() {
const tabs = [{ key: "person", title: getLabel(543547, "人员确认") }, {
key: "calc", title: getLabel(538011, "薪资核算")
}];
const { calculateStore: { setOtherConditions } } = this.props;
const { selectedKey, progressVisible, progress, customExpDialog, salaryImpDialog } = this.state;
return (<Layout {...this.props} init={this.init}>
<div className="salary-calculate-do-calc">
<WeaReqTop
title={getLabel(538011, "薪资核算")} tabDatas={tabs} selectedKey={selectedKey}
buttonSpace={10} icon={<i className="icon-coms-fa"/>} iconBgcolor="#F14A2D"
onChange={key => this.setState({ selectedKey: key }, () => setOtherConditions([]))}
buttons={this.renderReqBtns()}
>
<div className="salary-calculate-do-calc-content">{this.renderContent()}</div>
{progressVisible && <ProgressModal
visible={progressVisible}
onCancel={() => {
this.setState({ progressVisible: false, progress: 0 }, () => clearInterval(this.timer));
}}
progress={parseFloat(progress).toFixed(2)}
/>}
{/* 薪资核算-自定义导出*/}
<CustomCalcExportDialog {...customExpDialog} onCancel={() => {
this.setState({
customExpDialog: { ...customExpDialog, visible: false }
});
}}/>
{/* 薪资核算-导入*/}
<SalaryEditCalcImport {...salaryImpDialog} onCancel={(isFresh) => {
this.setState({
salaryImpDialog: { ...salaryImpDialog, visible: false }
}, () => isFresh && this.calc.onAdSearch(false));
}}/>
</WeaReqTop>
</div>
</Layout>);
}
}
export default Index;