467 lines
16 KiB
JavaScript
467 lines
16 KiB
JavaScript
import React from "react";
|
||
import UserSure from "./userSure";
|
||
import { inject, observer } from "mobx-react";
|
||
import SalaryDetail from "./salaryDetail";
|
||
import { Button, Dropdown, Menu, message, Modal } from "antd";
|
||
import {
|
||
WeaBrowser,
|
||
WeaCheckbox,
|
||
WeaDropdown,
|
||
WeaFormItem,
|
||
WeaInput,
|
||
WeaLocaleProvider,
|
||
WeaSearchGroup,
|
||
WeaSelect,
|
||
WeaTab
|
||
} from "ecCom";
|
||
import { convertToUrlString, getQueryString } from "../../util/url";
|
||
import AcctResultImportModal from "./acctResult/importModal/acctResultImportModal";
|
||
import ProgressModal from "../../components/progressModal";
|
||
import { getExportField, salaryacctAcctresultCheckAuth } from "../../apis/calculate";
|
||
import CustomExportDialog from "./customExportDialog";
|
||
import Authority from "../mySalary/authority";
|
||
|
||
const getLabel = WeaLocaleProvider.getLabel;
|
||
const { ButtonSelect } = WeaDropdown;
|
||
|
||
@inject("calculateStore", "salaryFileStore", "taxAgentStore")
|
||
@observer
|
||
export default class CalculateDetail extends React.Component {
|
||
constructor(props) {
|
||
super(props);
|
||
this.state = {
|
||
showSearchAd: false,
|
||
searchItemsValue: {
|
||
employeeName: "",
|
||
workcode: "",
|
||
departmentIds: "",
|
||
positionIds: "",
|
||
subcompanyIds: "",
|
||
statuses: "",
|
||
consolidatedTaxation: "0"
|
||
},
|
||
selectedKey: "0",
|
||
fieldData: {},
|
||
acctResultImportVisiable: false,
|
||
progressVisible: false,
|
||
progress: 0,
|
||
accountIds: [],
|
||
accountExceptInfo: "",
|
||
calculateAuth: false,
|
||
customExportParams: {
|
||
visible: false, checkItems: [], itemsByGroup: []
|
||
}
|
||
};
|
||
this.id = "";
|
||
this.timer = null;
|
||
}
|
||
|
||
async componentWillMount() {
|
||
let id = getQueryString("id");
|
||
this.id = id;
|
||
const { calculateStore: { checkTaxAgent }, salaryFileStore } = this.props;
|
||
const { commonEnumList } = salaryFileStore;
|
||
this.salaryacctAcctresultCheckAuth({ salaryAcctRecordId: id });
|
||
checkTaxAgent(this.id);
|
||
let modalParam = { ...this.state.modalParam, salaryAcctRecordId: id };
|
||
this.setState({ modalParam });
|
||
commonEnumList("user", { enumClass: "com.engine.salary.enums.salarysob.SalaryEmployeeStatusEnum" });
|
||
}
|
||
|
||
salaryacctAcctresultCheckAuth = (params) => {
|
||
const { taxAgentStore: { getPermission } } = this.props;
|
||
getPermission().then(({ data }) => {
|
||
const { isOpenDevolution } = data;
|
||
if (isOpenDevolution) {
|
||
salaryacctAcctresultCheckAuth(params).then(({ status, data }) => {
|
||
this.setState({ calculateAuth: data && status });
|
||
});
|
||
} else {
|
||
this.setState({ calculateAuth: true });
|
||
}
|
||
});
|
||
};
|
||
|
||
Input = (value, key) => {
|
||
const { employeeName, workcode } = this.state.searchItemsValue;
|
||
return (
|
||
<WeaFormItem
|
||
label={value}
|
||
labelCol={{ span: 6 }}
|
||
wrapperCol={{ span: 18 }}
|
||
>
|
||
<WeaInput value={key === "employeeName" ? employeeName : workcode}
|
||
onChange={(val) => this.setState({
|
||
searchItemsValue: {
|
||
...this.state.searchItemsValue,
|
||
[key]: val
|
||
}
|
||
})}/>
|
||
</WeaFormItem>
|
||
);
|
||
};
|
||
Browser = (value, key) => {
|
||
const { positionIds, departmentIds, subcompanyIds } = this.state.searchItemsValue;
|
||
return (
|
||
<WeaFormItem
|
||
label={value}
|
||
labelCol={{ span: 6 }}
|
||
wrapperCol={{ span: 18 }}
|
||
>
|
||
<WeaBrowser
|
||
isSingle={false}
|
||
value={key === "departmentIds" ? departmentIds : key === "subcompanyIds" ? subcompanyIds : positionIds}
|
||
// tabs={key === "departmentIds" ? [
|
||
// {
|
||
// dataParams: { list: "1" },
|
||
// isSearch: true,
|
||
// key: "1",
|
||
// name: "按列表",
|
||
// selected: false,
|
||
// showOrder: 0
|
||
// }
|
||
// ] : null}
|
||
type={key === "departmentIds" ? 57 : key === "subcompanyIds" ? 164 : 278}
|
||
onChange={(val) => {
|
||
this.setState({ searchItemsValue: { ...this.state.searchItemsValue, [key]: val } });
|
||
}}/>
|
||
</WeaFormItem>
|
||
);
|
||
};
|
||
Select = (value, key) => {
|
||
const { statuses } = this.state.searchItemsValue;
|
||
return (
|
||
<WeaFormItem
|
||
label={value}
|
||
labelCol={{ span: 6 }}
|
||
wrapperCol={{ span: 18 }}
|
||
>
|
||
<WeaSelect
|
||
multiple
|
||
value={statuses}
|
||
options={[
|
||
{ key: "0", showname: "试用" }, { key: "1", showname: "正式" },
|
||
{ key: "2", showname: "临时" }, { key: "3", showname: "试用延期" },
|
||
{ key: "4", showname: "解雇" }, { key: "5", showname: "离职" },
|
||
{ key: "6", showname: "退休" }
|
||
]}
|
||
onChange={(val) => this.setState({ searchItemsValue: { ...this.state.searchItemsValue, [key]: val } })}/>
|
||
</WeaFormItem>
|
||
);
|
||
};
|
||
Checkbox = (value, key) => {
|
||
const { consolidatedTaxation } = this.state.searchItemsValue;
|
||
return (
|
||
<WeaFormItem
|
||
label={value}
|
||
labelCol={{ span: 6 }}
|
||
wrapperCol={{ span: 18 }}
|
||
>
|
||
<WeaCheckbox value={consolidatedTaxation} content="是" onChange={(val) => this.setState({
|
||
searchItemsValue: {
|
||
...this.state.searchItemsValue,
|
||
[key]: val
|
||
}
|
||
})}/>
|
||
</WeaFormItem>
|
||
);
|
||
};
|
||
|
||
// 核算点击事件
|
||
handleAccount = (key) => {
|
||
const { calculateStore } = this.props;
|
||
const { acctresultAccounting, getCalculateProgress } = calculateStore;
|
||
if (key === "SELECT" && _.isEmpty(this.state.accountIds)) {
|
||
message.warning("请先选择表格数据");
|
||
return;
|
||
}
|
||
Modal.confirm({
|
||
title: "信息确认",
|
||
content: "点击核算,公式项将按照公式逻辑核算,核算结果将覆盖原数据",
|
||
onOk: () => {
|
||
this.setState({ progress: 0 });
|
||
let payload = { salaryAcctRecordId: this.id };
|
||
if (key === "SELECT") {
|
||
payload = _.assign(payload, { ids: this.state.accountIds });
|
||
}
|
||
acctresultAccounting(payload).then(() => {
|
||
this.setState({
|
||
progressVisible: true
|
||
});
|
||
if (this.timer) {
|
||
clearInterval(this.timer);
|
||
}
|
||
this.timer = setInterval(() => {
|
||
getCalculateProgress(this.id).then(data => {
|
||
let progress = data.progress;
|
||
if (progress == 1 && this.timer) {
|
||
clearInterval(this.timer);
|
||
this.timer = null;
|
||
this.setState({
|
||
progressVisible: false,
|
||
accountIds: [],
|
||
accountExceptInfo: data.message
|
||
});
|
||
message.success("核算完成");
|
||
// acctResultList({ salaryAcctRecordId: this.id });
|
||
const childFrameObj = document.getElementById("atdTable");
|
||
const salaryAcctRecordId = getQueryString("id");
|
||
const payload = {
|
||
type: "PR",
|
||
listType: "",
|
||
url: "/api/bs/hrmsalary/salaryacct/acctresult/list",
|
||
selectedRowKeys: [],
|
||
queryParams: {
|
||
salaryAcctRecordId
|
||
}
|
||
};
|
||
childFrameObj.contentWindow.postMessage(JSON.stringify(payload), "*");
|
||
} else if (!data.status) {
|
||
clearInterval(this.timer);
|
||
this.timer = null;
|
||
this.setState({
|
||
progressVisible: false,
|
||
accountIds: [],
|
||
accountExceptInfo: data.message
|
||
});
|
||
message.error(data.message);
|
||
}
|
||
this.setState({ progress: Number(progress) * 100 });
|
||
});
|
||
}, 1000);
|
||
});
|
||
}
|
||
});
|
||
};
|
||
|
||
// 更多选项点击
|
||
handleMenuClick = e => {
|
||
if (e.key == "1") {
|
||
// 导入
|
||
this.setState({
|
||
acctResultImportVisiable: true
|
||
});
|
||
} else if (e.key == "2") {
|
||
window.open(
|
||
"/spa/hrmSalary/static/index.html#/main/hrmSalary/compareDetail?id=" +
|
||
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=&${convertToUrlString(payload)}`
|
||
);
|
||
} else if (e.key === "4") {
|
||
// 自定义导出
|
||
this.getExportField();
|
||
}
|
||
};
|
||
|
||
getExportField = () => {
|
||
getExportField({ salaryAcctRecordId: getQueryString("id") }).then(({ status, data }) => {
|
||
if (status) {
|
||
const { checkItems, itemsByGroup } = data;
|
||
this.setState({
|
||
customExportParams: {
|
||
visible: true,
|
||
checkItems, itemsByGroup
|
||
}
|
||
});
|
||
}
|
||
});
|
||
};
|
||
|
||
// 导入表单添加表头回调
|
||
handleAcctModalAdd(fieldData) {
|
||
this.setState({
|
||
fieldData
|
||
});
|
||
}
|
||
|
||
// 核算结果搜索
|
||
handleSearch(params) {
|
||
const { calculateStore: { acctResultList } } = this.props;
|
||
// acctResultList({ salaryAcctRecordId: this.id, ...params });
|
||
const childFrameObj = document.getElementById("atdTable");
|
||
const salaryAcctRecordId = getQueryString("id");
|
||
const payload = {
|
||
type: "PR",
|
||
listType: "",
|
||
url: "/api/bs/hrmsalary/salaryacct/acctresult/list",
|
||
queryParams: {
|
||
salaryAcctRecordId,
|
||
...params
|
||
}
|
||
};
|
||
childFrameObj.contentWindow.postMessage(JSON.stringify(payload), "*");
|
||
}
|
||
|
||
componentWillUnmount() {
|
||
// 清除轮询
|
||
if (this.timer) {
|
||
clearInterval(this.timer);
|
||
}
|
||
}
|
||
|
||
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();
|
||
};
|
||
|
||
render() {
|
||
const {
|
||
selectedKey,
|
||
acctResultImportVisiable,
|
||
showSearchAd,
|
||
calculateAuth,
|
||
customExportParams,
|
||
searchItemsValue
|
||
} = this.state;
|
||
const { taxAgentStore: { payrollPermission } } = this.props;
|
||
const menu = (
|
||
<Menu onClick={this.handleMenuClick.bind(this)}>
|
||
<Menu.Item key="1">导入</Menu.Item>
|
||
<Menu.Item key="2">线下对比</Menu.Item>
|
||
<Menu.Item key="3">导出全部</Menu.Item>
|
||
<Menu.Item key="4">{getLabel(111, "自定义导出")}</Menu.Item>
|
||
</Menu>
|
||
);
|
||
|
||
const renderRightOperation = () => {
|
||
const { accountExceptInfo } = this.state;
|
||
let buttons = [
|
||
<ButtonSelect
|
||
datas={[
|
||
{ key: "ALL", show: "核算所有人", selected: true },
|
||
{ key: "SELECT", show: "核算所选人员", selected: false }
|
||
]}
|
||
btnOnClick={this.handleAccount}
|
||
menuOnClick={(key) => this.handleAccount(key)}
|
||
/>,
|
||
<Dropdown.Button overlay={menu}>
|
||
更多
|
||
</Dropdown.Button>
|
||
];
|
||
accountExceptInfo && buttons.unshift(<Button type="ghost" shape="circle-outline" icon="download"
|
||
title="下载核算异常信息"
|
||
onClick={() => this.downloadTxtfile(accountExceptInfo)}/>);
|
||
return buttons;
|
||
};
|
||
const topTab = [
|
||
{ title: "人员确认", viewcondition: "0" },
|
||
{ title: "薪资核算", viewcondition: "1" }
|
||
];
|
||
const adBtn = [
|
||
// 高级搜索内部按钮
|
||
<Button type="primary" onClick={() => {
|
||
this.setState({ showSearchAd: false }, () => {
|
||
this.handleSearch(this.state.searchItemsValue);
|
||
});
|
||
}}>
|
||
搜索
|
||
</Button>,
|
||
<Button type="ghost" onClick={() => this.setState({
|
||
searchItemsValue: {
|
||
employeeName: "",
|
||
workcode: "",
|
||
departmentIds: "",
|
||
positionIds: "",
|
||
statuses: "",
|
||
consolidatedTaxation: "0"
|
||
}
|
||
})}>
|
||
重置
|
||
</Button>,
|
||
<Button type="ghost" onClick={() => this.setState({ showSearchAd: false })}>
|
||
取消
|
||
</Button>
|
||
];
|
||
|
||
const renderSearch = () => {
|
||
const searchItems = [
|
||
{ com: this.Input("姓名", "employeeName") },
|
||
{ com: this.Input("工号", "workcode") },
|
||
{ com: this.Browser("分部", "subcompanyIds") },
|
||
{ com: this.Browser("部门", "departmentIds") },
|
||
{ com: this.Browser("岗位", "positionIds") },
|
||
{ com: this.Select("状态", "statuses") },
|
||
{ com: this.Checkbox("合并计税", "consolidatedTaxation") }
|
||
];
|
||
return <WeaSearchGroup title={"基本信息"} items={searchItems} showGroup/>;
|
||
};
|
||
|
||
return (
|
||
<Authority ecId={`${this && this.props && this.props.ecId || ""}_Authority@lulowc`}
|
||
store={{ loading: false, hasRight: payrollPermission && calculateAuth }}>
|
||
<div className="calculate-layout">
|
||
<WeaTab
|
||
datas={topTab}
|
||
selectedKey={selectedKey}
|
||
keyParam="viewcondition"
|
||
onChange={v => this.setState({ selectedKey: v })}
|
||
searchType={selectedKey === "1" ? ["base", "advanced"] : []} // base:基础搜索框 advanced:显示高级搜索按钮
|
||
showSearchAd={showSearchAd} // 是否展开高级搜索面板
|
||
setShowSearchAd={(bool) => this.setState({ showSearchAd: bool })} //高级搜索面板受控
|
||
searchsAd={renderSearch()} // 高级搜索内部数据getSearchs(form, toJS(condition), 2)
|
||
buttonsAd={adBtn} // 高级搜索内部按钮
|
||
onSearch={() => this.handleSearch(this.state.searchItemsValue)} // 点搜索按钮时的回调
|
||
buttons={selectedKey === "1" ? renderRightOperation() : []}
|
||
searchsBasePlaceHolder={"请输入姓名"}
|
||
onSearchChange={(v) =>
|
||
this.setState({
|
||
searchItemsValue: {
|
||
...this.state.searchItemsValue,
|
||
employeeName: v
|
||
}
|
||
})
|
||
} // 在搜索框中输入的文字改变时的回调: 这里需要同步高级搜索和外部搜索框的值form.updateFields({ username: v })
|
||
searchsBaseValue={this.state.searchItemsValue.employeeName} // 外部input搜索值受控: 这里和高级搜索的requestname同步form.getFormParams().username
|
||
/>
|
||
{selectedKey === "0" && <UserSure/>}
|
||
{selectedKey === "1" && <SalaryDetail onChangeAccountIds={(ids) => this.setState({ accountIds: ids })}
|
||
employeeName={this.state.searchItemsValue}/>}
|
||
{acctResultImportVisiable &&
|
||
<AcctResultImportModal
|
||
visiable={acctResultImportVisiable}
|
||
fieldData={this.state.fieldData}
|
||
onAdd={fieldData => {
|
||
this.handleAcctModalAdd(fieldData);
|
||
}}
|
||
onCancel={() =>
|
||
this.setState({
|
||
acctResultImportVisiable: false,
|
||
fieldData: {}
|
||
})}
|
||
id={this.id}
|
||
/>}
|
||
{this.state.progressVisible &&
|
||
<ProgressModal
|
||
visible={this.state.progressVisible}
|
||
onCancel={() => {
|
||
this.setState({ progressVisible: false, progress: 0 });
|
||
}}
|
||
progress={this.state.progress}
|
||
/>}
|
||
<CustomExportDialog
|
||
{...customExportParams}
|
||
searchItemsValue={searchItemsValue}
|
||
onCancel={() => {
|
||
this.setState({
|
||
customExportParams: {
|
||
visible: false, checkItems: [], itemsByGroup: []
|
||
}
|
||
});
|
||
}}
|
||
/>
|
||
</div>
|
||
</Authority>
|
||
);
|
||
}
|
||
}
|