305 lines
13 KiB
JavaScript
305 lines
13 KiB
JavaScript
/*
|
||
* 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;
|