580 lines
20 KiB
JavaScript
580 lines
20 KiB
JavaScript
import React from "react";
|
|
import { inject, observer } from "mobx-react";
|
|
import { toJS } from "mobx";
|
|
import { Button, DatePicker, message, Modal } from "antd";
|
|
import moment from "moment";
|
|
import {
|
|
WeaHelpfulTip,
|
|
WeaInputSearch,
|
|
WeaLocaleProvider,
|
|
WeaNewScroll,
|
|
WeaSelect,
|
|
WeaSlideModal,
|
|
WeaTop
|
|
} from "ecCom";
|
|
import { renderLoading } from "../../util";
|
|
import CustomTab from "../../components/customTab";
|
|
import StepSlide from "../../components/stepSlide";
|
|
import BaseInformForm from "./stepForm/baseInformForm";
|
|
import ShowSettingForm from "./stepForm/showSettingForm";
|
|
import SlideModalTitle from "../../components/slideModalTitle";
|
|
import TemplateSettingList from "./templateSettingList";
|
|
import TemplateSettingForm from "./stepForm/tmplateSettingForm";
|
|
import TemplateBaseSettings from "./templateBaseSettings";
|
|
import CopyModal from "./copyModal";
|
|
import SalarySendList from "./SalarySendList";
|
|
import { getReplenishForm } from "../../apis/payroll";
|
|
import "../dataAcquisition/cumDeduct/index.less";
|
|
|
|
const getLabel = WeaLocaleProvider.getLabel;
|
|
const { MonthPicker } = DatePicker;
|
|
|
|
@inject("payrollStore", "taxAgentStore")
|
|
@observer
|
|
export default class Payroll extends React.Component {
|
|
constructor(props) {
|
|
super(props);
|
|
this.state = {
|
|
value: "",
|
|
selectedKey: "0",
|
|
currentStep: 0,
|
|
stepSlideVisible: false,
|
|
selectedTab: 0,
|
|
editSlideVisible: false,
|
|
initSelected: false,
|
|
ledgerOptions: [],
|
|
templateSearchValue: "", // 工资单模板列表-搜索条件-名称
|
|
templateSelect: "", // 工资单模板列表-搜索条件-账套下拉选中值
|
|
templateCurrentId: "",
|
|
copyModalVisible: false,
|
|
startDate: moment(new Date()).startOf("year").format("YYYY-MM"),
|
|
endDate: moment(new Date()).startOf("month").format("YYYY-MM"),
|
|
loading: false
|
|
};
|
|
this.recordId = "";
|
|
this.salaryYearMonth = [moment(new Date()).startOf("year").format("YYYY-MM"), moment(new Date()).startOf("month").format("YYYY-MM")];
|
|
this.listPageInfo = { current: 1, pageSize: 10 };
|
|
}
|
|
|
|
// 工资单模板-新建表单变化监听
|
|
handleBaseInfoChange = (request) => {
|
|
const { payrollStore: { setTemplateBaseData } } = this.props;
|
|
setTemplateBaseData(request);
|
|
};
|
|
|
|
getReplenishForm = (isEdit = false, params = {}) => {
|
|
const { payrollStore } = this.props;
|
|
const { templateBaseData, salaryTemplateShowSet, setReplenishSalaryTemplateSalaryItemSet } = payrollStore;
|
|
if (!salaryTemplateShowSet.theme && !isEdit) {
|
|
Modal.warning({
|
|
title: "信息确认",
|
|
content: "必要信息不完整,红色*为必填项!"
|
|
});
|
|
return;
|
|
}
|
|
getReplenishForm({ salarySobId: templateBaseData.salarySob, ...params }).then(({ status, data }) => {
|
|
if (status) {
|
|
if (!isEdit) {
|
|
this.setState({ currentStep: this.state.currentStep + 1 }, () => {
|
|
setReplenishSalaryTemplateSalaryItemSet(data.replenishSalaryTemplateSalaryItemSet);
|
|
window.localStorage.setItem("salary-showset", JSON.stringify(salaryTemplateShowSet));
|
|
});
|
|
} else {
|
|
setReplenishSalaryTemplateSalaryItemSet(data.replenishSalaryTemplateSalaryItemSet);
|
|
window.localStorage.setItem("salary-showset", JSON.stringify(salaryTemplateShowSet));
|
|
}
|
|
}
|
|
});
|
|
};
|
|
// 新建保存
|
|
handleSave = () => {
|
|
const { payrollStore } = this.props;
|
|
const { fetchSavePayroll } = payrollStore;
|
|
fetchSavePayroll().then(() => {
|
|
window.localStorage.removeItem("template-basedata");
|
|
window.localStorage.removeItem("salary-showset");
|
|
this.setState({ currentStep: 0, stepSlideVisible: false });
|
|
});
|
|
};
|
|
|
|
componentWillMount() {
|
|
const { payrollStore } = this.props;
|
|
const { getPayrollTemplateLedgerList } = payrollStore;
|
|
// 获取薪资账套下拉列表
|
|
getPayrollTemplateLedgerList().then((options) => {
|
|
this.setState({
|
|
initSelected: true,
|
|
ledgerOptions: [{ key: "", showname: "" }, ...options]
|
|
});
|
|
});
|
|
}
|
|
|
|
// 模板搜索
|
|
handleTemplateSearch() {
|
|
const { templateSearchValue, templateSelect } = this.state;
|
|
let params = { name: templateSearchValue, salarySobId: templateSelect, current: 1 };
|
|
const { payrollStore: { getPayrollTemplateList } } = this.props;
|
|
getPayrollTemplateList(params);
|
|
}
|
|
|
|
// 模板选择框下拉改变事件
|
|
handleTemplateSelectChange(value) {
|
|
this.setState({ templateSelect: value }, () => {
|
|
this.handleTemplateSearch();
|
|
});
|
|
}
|
|
|
|
// 模板列表编辑
|
|
handleTemplateListEdit(record) {
|
|
const { payrollStore } = this.props;
|
|
const { getPayrollShowForm } = payrollStore;
|
|
this.recordId = record.id;
|
|
getPayrollShowForm(record.id);
|
|
this.setState({ templateCurrentId: record.id, selectedTab: 0 }, () => {
|
|
this.setState({ editSlideVisible: true });
|
|
});
|
|
}
|
|
|
|
// 模板列表复制
|
|
handleTemplateListCopy(record) {
|
|
this.setState({
|
|
templateCurrentId: record.id
|
|
}, () => {
|
|
this.setState({
|
|
copyModalVisible: true
|
|
});
|
|
});
|
|
}
|
|
|
|
// 复制模板保存事件监听
|
|
handleCopyModalSave(value) {
|
|
const { payrollStore } = this.props;
|
|
const { duplicatePayroll } = payrollStore;
|
|
duplicatePayroll(this.state.templateCurrentId, value).then(() => {
|
|
this.setState({
|
|
copyModalVisible: false
|
|
});
|
|
});
|
|
}
|
|
|
|
// 模板列表删除
|
|
handleTemplateListDelete(record) {
|
|
const { payrollStore: { deletePayroll } } = this.props;
|
|
Modal.confirm({
|
|
title: "信息确认",
|
|
content: "确认删除",
|
|
onOk: () => {
|
|
deletePayroll([record.id]);
|
|
}
|
|
});
|
|
}
|
|
|
|
|
|
handleRangePickerChange(type, value) {
|
|
const { payrollStore: { getPayrollList } } = this.props;
|
|
this.setState({
|
|
[type]: value ? moment(value).format("YYYY-MM") : moment().format("YYYY-MM")
|
|
}, () => {
|
|
const { startDate, endDate } = this.state;
|
|
this.salaryYearMonth = [startDate, endDate];
|
|
getPayrollList({ salaryYearMonth: [startDate, endDate], ...this.listPageInfo });
|
|
});
|
|
}
|
|
|
|
// 预览
|
|
handlePreview = () => {
|
|
const { payrollStore: { templateBaseData, salaryTemplateShowSet, salaryItemSet } } = this.props;
|
|
window.localStorage.setItem("template-basedata", JSON.stringify(templateBaseData));
|
|
window.localStorage.setItem("salary-showset", JSON.stringify(salaryTemplateShowSet));
|
|
window.localStorage.setItem("salaryItemSet", JSON.stringify(salaryItemSet));
|
|
window.open("/spa/hrmSalary/static/index.html#/main/hrmSalary/templatePreview");
|
|
};
|
|
|
|
// 更新保存
|
|
handleUpdateSave = () => {
|
|
const { selectedTab } = this.state;
|
|
const { payrollStore } = this.props;
|
|
const { fetchUpdatePayroll } = payrollStore;
|
|
if (selectedTab === 0) {
|
|
if (!this.validateStep1()) {
|
|
Modal.warning({
|
|
title: "信息确认",
|
|
content: "必要信息不完整,红色*为必填项!"
|
|
});
|
|
return;
|
|
}
|
|
} else if (selectedTab === 1) {
|
|
const { salaryTemplateShowSet } = payrollStore;
|
|
if (!salaryTemplateShowSet.theme) {
|
|
Modal.warning({
|
|
title: "信息确认",
|
|
content: "必要信息不完整,红色*为必填项!"
|
|
});
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
fetchUpdatePayroll(this.recordId).then(() => {
|
|
this.setState({
|
|
editSlideVisible: false,
|
|
selectedTab: 0
|
|
}, () => {
|
|
window.localStorage.removeItem("template-basedata");
|
|
window.localStorage.removeItem("salary-showset");
|
|
});
|
|
});
|
|
};
|
|
|
|
// 发放页面页码跳转
|
|
handleListDataPageChange(value, pageInfo) {
|
|
const { payrollStore: { getPayrollList } } = this.props;
|
|
this.listPageInfo = pageInfo;
|
|
getPayrollList({ salaryYearMonth: this.salaryYearMonth, ...pageInfo });
|
|
}
|
|
|
|
// 发放页面每页条数
|
|
handleListShowSizeChange(pageInfo) {
|
|
const { payrollStore: { getPayrollList } } = this.props;
|
|
this.listPageInfo = pageInfo;
|
|
getPayrollList({ salaryYearMonth: this.salaryYearMonth, ...pageInfo });
|
|
}
|
|
|
|
validateStep1 = () => {
|
|
const { payrollStore: { templateBaseData } } = this.props;
|
|
const { reissueRule = "0" } = templateBaseData;
|
|
const validList = reissueRule === "0" ? ["name", "replenishName", "salarySob"] : ["name", "replenishName", "salarySob", "replenishRule"];
|
|
if (_.every(validList, it => !!templateBaseData[it])) {
|
|
window.localStorage.setItem("template-basedata", JSON.stringify(templateBaseData));
|
|
} else {
|
|
window.localStorage.removeItem("template-basedata");
|
|
}
|
|
return _.every(validList, it => !!templateBaseData[it]);
|
|
};
|
|
|
|
render() {
|
|
const { payrollStore, taxAgentStore: { showOperateBtn } } = this.props;
|
|
const {
|
|
loading,
|
|
hasRight,
|
|
templateTableSelectedRowKeys,
|
|
setTemplateTableSelectedRowKeys,
|
|
deletePayroll,
|
|
templateBaseData,
|
|
setTemplateTablePageInfo
|
|
} = payrollStore;
|
|
const { currentStep, selectedTab, templateSearchValue, templateSelect, startDate, endDate } = this.state;
|
|
if (!hasRight && !loading) { // 无权限处理
|
|
return renderLoading();
|
|
}
|
|
const topTab = [
|
|
{
|
|
title: "工资单发放",
|
|
viewcondition: "0"
|
|
},
|
|
{
|
|
title: "工资单模板设置",
|
|
viewcondition: "1"
|
|
},
|
|
{
|
|
title: getLabel(111, "工资单模板基础设置"),
|
|
viewcondition: "2"
|
|
}
|
|
];
|
|
const renderRightOperation = () => {
|
|
if (this.state.selectedKey === "0") {
|
|
return <div style={{ display: "inline-block" }}>
|
|
<WeaHelpfulTip
|
|
width={200}
|
|
title="提示:无工资单模板无法发放工资单,请先设置一个默认使用的工资单模板"
|
|
placement="topLeft"
|
|
/>
|
|
<div style={{ display: "inline-block", marginLeft: "10px" }}>
|
|
<MonthPicker
|
|
value={startDate}
|
|
disabledDate={(current) => {
|
|
return current && endDate && current.getTime() > new Date(endDate).getTime();
|
|
}}
|
|
format="YYYY-MM"
|
|
onChange={(val) => this.handleRangePickerChange("startDate", val)}
|
|
/>
|
|
<span className="to" style={{ margin: "0 10px" }}>至</span>
|
|
<MonthPicker
|
|
value={endDate}
|
|
disabledDate={(current) => {
|
|
return current && startDate && current.getTime() < new Date(startDate).getTime();
|
|
}}
|
|
getCalendarContainer={trigger => trigger.parentNode}
|
|
format="YYYY-MM"
|
|
onChange={(val) => this.handleRangePickerChange("endDate", val)}
|
|
/>
|
|
</div>
|
|
</div>;
|
|
} else if (this.state.selectedKey === "1") {
|
|
return (
|
|
<div style={{ display: "inline-block" }}>
|
|
{
|
|
showOperateBtn &&
|
|
<Button type="primary" onClick={() => {
|
|
this.setState({ stepSlideVisible: true });
|
|
}}>新建</Button>
|
|
}
|
|
{
|
|
showOperateBtn &&
|
|
<Button
|
|
style={{ marginLeft: 10 }}
|
|
type="ghost"
|
|
onClick={() => {
|
|
const selectedRowKeys = toJS(templateTableSelectedRowKeys);
|
|
if (!selectedRowKeys.length) {
|
|
message.info("未选中任何数据!");
|
|
return;
|
|
}
|
|
Modal.confirm({
|
|
title: "信息确认",
|
|
content: `确定要将所选的工资单模板(共${selectedRowKeys.length}条数据)删除吗?`,
|
|
onOk: () => {
|
|
deletePayroll(selectedRowKeys);
|
|
}
|
|
});
|
|
}}
|
|
>批量删除工资单模板</Button>
|
|
}
|
|
{
|
|
this.state.initSelected && <WeaSelect options={this.state.ledgerOptions}
|
|
placeholder="请选择账套"
|
|
style={{ width: "200px", marginLeft: "10px", marginRight: "10px" }}
|
|
value={templateSelect} onChange={(value) => {
|
|
this.handleTemplateSelectChange(value);
|
|
}}/>
|
|
}
|
|
<WeaInputSearch style={{ marginleft: "10px" }} placeholder="请输入工资单名称" value={templateSearchValue}
|
|
onChange={(value) => {
|
|
this.setState({ templateSearchValue: value });
|
|
}}
|
|
onSearch={(value) => {
|
|
this.handleTemplateSearch(value);
|
|
}}
|
|
/>
|
|
</div>
|
|
);
|
|
} else if (this.state.selectedKey === "2") {
|
|
return <Button type="primary"
|
|
onClick={() => this.baseSetRef.salaryBillBaseSetSave()}
|
|
loading={this.state.loading}
|
|
>{getLabel(111, "保存")}</Button>;
|
|
}
|
|
};
|
|
const steps = ["基础设置", "正常核算工资单模板", "补发工资单模版"];
|
|
const nextStep = () => {
|
|
if (!this.validateStep1()) {
|
|
Modal.warning({
|
|
title: "信息确认",
|
|
content: "必要信息不完整,红色*为必填项!"
|
|
});
|
|
return;
|
|
}
|
|
if (templateBaseData.replenishName === templateBaseData.name) {
|
|
message.error("工资单模板名称和补发工资单模板名称不可相同");
|
|
return;
|
|
}
|
|
this.setState({
|
|
currentStep: this.state.currentStep + 1
|
|
});
|
|
};
|
|
// 上一步
|
|
const prevStep = () => {
|
|
this.setState({
|
|
currentStep: this.state.currentStep - 1
|
|
});
|
|
};
|
|
|
|
return (
|
|
<div className="payrollDistributionWrapper">
|
|
<WeaTop
|
|
title="工资单发放" // 文字
|
|
icon={<i className="icon-coms-fa"/>} // 左侧图标
|
|
iconBgcolor="#F14A2D" // 左侧图标背景色
|
|
showDropIcon={false} // 是否显示下拉按钮
|
|
>
|
|
<CustomTab
|
|
topTab={topTab}
|
|
searchOperationItem={renderRightOperation()}
|
|
onChange={(v) => {
|
|
this.setState({
|
|
selectedKey: v,
|
|
stepSlideVisible: false,
|
|
editSlideVisible: false
|
|
}, () => {
|
|
setTemplateTablePageInfo({ current: 1 });
|
|
setTemplateTableSelectedRowKeys([]);
|
|
});
|
|
}}
|
|
/>
|
|
<div className="tableWrapper">
|
|
<WeaNewScroll height="100%">
|
|
{
|
|
this.state.selectedKey === "0" &&
|
|
<SalarySendList
|
|
onEditTemplate={(record) => {
|
|
this.handleTemplateListEdit(record);
|
|
}}
|
|
salaryYearMonth={this.salaryYearMonth}
|
|
handleListDataPageChange={(value, pageInfo) => {
|
|
this.handleListDataPageChange(value, pageInfo);
|
|
}}
|
|
handleListShowSizeChange={(pageInfo) => {
|
|
this.handleListShowSizeChange(pageInfo);
|
|
}}
|
|
/>
|
|
}
|
|
|
|
{
|
|
this.state.selectedKey === "1" &&
|
|
<TemplateSettingList
|
|
onEdit={(record) => {
|
|
this.handleTemplateListEdit(record);
|
|
}}
|
|
onCopy={(record) => {
|
|
this.handleTemplateListCopy(record);
|
|
}}
|
|
showOperateBtn={showOperateBtn}
|
|
onDelete={(record) => this.handleTemplateListDelete(record)}
|
|
/>
|
|
}
|
|
{
|
|
this.state.selectedKey === "2" &&
|
|
<TemplateBaseSettings
|
|
ref={dom => this.baseSetRef = dom}
|
|
onChangeLoading={loading => this.setState({ loading })}
|
|
/>
|
|
}
|
|
</WeaNewScroll>
|
|
</div>
|
|
</WeaTop>
|
|
{
|
|
this.state.stepSlideVisible && <StepSlide
|
|
visible={this.state.stepSlideVisible}
|
|
currentStep={currentStep}
|
|
steps={steps}
|
|
onCancel={() => {
|
|
window.localStorage.removeItem("template-basedata");
|
|
window.localStorage.removeItem("salary-showset");
|
|
this.setState({ stepSlideVisible: false });
|
|
}}
|
|
customOperate={
|
|
currentStep === 0 ? [
|
|
<Button type="primary" onClick={() => {
|
|
nextStep();
|
|
}}>下一步</Button>
|
|
] : currentStep === 1 ? [
|
|
<Button type="default" onClick={() => {
|
|
prevStep();
|
|
}}>上一步</Button>,
|
|
<Button type="primary" onClick={() => this.getReplenishForm()}>下一步</Button>,
|
|
<Button type="default" onClick={() => {
|
|
this.handlePreview();
|
|
}}>预览</Button>
|
|
] : currentStep === 2 ? [
|
|
<Button type="default" onClick={() => {
|
|
prevStep();
|
|
}}>上一步</Button>,
|
|
<Button type="primary" onClick={this.handleSave}>保存</Button>
|
|
] :
|
|
[]
|
|
}
|
|
title="新建工资单模板"
|
|
content={
|
|
<div>
|
|
{
|
|
currentStep === 0 && <BaseInformForm onChange={(request) => this.handleBaseInfoChange(request)}/>
|
|
}
|
|
{
|
|
currentStep === 1 && <ShowSettingForm/>
|
|
}
|
|
{
|
|
currentStep === 2 && <TemplateSettingForm/>
|
|
}
|
|
</div>
|
|
}
|
|
/>
|
|
}
|
|
|
|
{
|
|
this.state.editSlideVisible &&
|
|
<WeaSlideModal
|
|
className="slideOuterWrapper"
|
|
visible={this.state.editSlideVisible}
|
|
top={0}
|
|
width={50}
|
|
height={100}
|
|
direction="right"
|
|
measure="%"
|
|
title={
|
|
<SlideModalTitle
|
|
subtitle="编辑工资单模板"
|
|
tabs={[
|
|
{ title: "基础设置", key: 0 },
|
|
{ title: "正常核算工资单模板", key: 1 },
|
|
{ title: "补发工资单模版", key: 2 }
|
|
]}
|
|
editable={false}
|
|
selectedTab={selectedTab}
|
|
showOperateBtn={showOperateBtn}
|
|
customOperate={
|
|
selectedTab === 0 ? [
|
|
<Button type="primary" onClick={() => {
|
|
this.handleUpdateSave();
|
|
}}>保存</Button>
|
|
] : selectedTab === 1 ? [
|
|
<Button type="primary" onClick={() => {
|
|
this.handleUpdateSave();
|
|
}}>保存</Button>,
|
|
<Button type="default" onClick={this.handlePreview}>预览</Button>
|
|
] : [
|
|
<Button type="primary" onClick={() => {
|
|
this.handleUpdateSave();
|
|
}}>保存</Button>
|
|
]
|
|
}
|
|
subItemChange={(selectedTab) => {
|
|
this.setState({ selectedTab: Number(selectedTab) }, () => {
|
|
if (this.state.selectedTab === 2) this.getReplenishForm(true, { id: this.state.templateCurrentId });
|
|
});
|
|
}}
|
|
/>
|
|
}
|
|
content={<div>
|
|
{
|
|
selectedTab === 0 &&
|
|
<BaseInformForm id={this.state.templateCurrentId}
|
|
onChange={(request) => this.handleBaseInfoChange(request)}/>
|
|
}
|
|
{
|
|
selectedTab === 1 && <ShowSettingForm id={this.state.templateCurrentId}/>
|
|
}
|
|
{
|
|
selectedTab === 2 && <TemplateSettingForm id={this.state.templateCurrentId}/>
|
|
}
|
|
</div>}
|
|
onClose={() => this.setState({ editSlideVisible: false }, () => {
|
|
window.localStorage.removeItem("template-basedata");
|
|
window.localStorage.removeItem("salary-showset");
|
|
this.setState({ selectedTab: 0 });
|
|
})}
|
|
/>
|
|
}
|
|
{
|
|
this.state.copyModalVisible &&
|
|
<CopyModal
|
|
onSave={(value) => this.handleCopyModalSave(value)}
|
|
visible={this.state.copyModalVisible}
|
|
onCancel={() => {
|
|
this.setState({ copyModalVisible: false });
|
|
}}/>
|
|
}
|
|
</div>
|
|
);
|
|
}
|
|
}
|