工资单部分发放和部分撤回功能完成

This commit is contained in:
黎永顺 2022-12-03 17:23:43 +08:00
parent 29abd303af
commit 479cea2967
4 changed files with 405 additions and 154 deletions

View File

@ -1,4 +1,5 @@
import { WeaTools } from "ecCom";
import { postFetch } from "../util/request";
//工资单-工资单发放列表
export const getPayrollList = params => {
@ -313,3 +314,16 @@ export const grantProxy = params => {
body: JSON.stringify(params)
}).then(res => res.json());
};
//添加发送和撤回人员范围列表
export const sendRangeList = (params) => {
return postFetch('/api/bs/hrmsalary/salaryBill/send/range/list', params);
}
//创建范围
export const sendRangeSave = (params) => {
return postFetch('/api/bs/hrmsalary/salaryBill/send/range/save', params);
}
//刪除范围
export const sendRangeDelete = (params) => {
return postFetch('/api/bs/hrmsalary/salaryBill/send/range/delete', params);
}

View File

@ -22,7 +22,9 @@ export default class PayrollGrant extends React.Component {
selectedKey: "0",
payrollPartModalParams: {
visible: false,
title: "工资单发放"
title: "工资单发放",
grantType: "",
salarySendId: ""
}
};
this.pageInfo = { current: 1, pageSize: 10 };
@ -49,31 +51,33 @@ export default class PayrollGrant extends React.Component {
const { currentId, selectedKey } = this.state;
const { withdrawPayroll, getInfoList } = payrollStore;
withdrawPayroll({
ids: [record.id],
...record,
salarySendId: currentId
}).then(() => {
getInfoList({
salarySendId: this.state.currentId,
isGranted: selectedKey !== "0"
});
this.handleClose();
});
};
// 发放
handleGrant(record) {
handleGrant = (record) => {
const { payrollStore } = this.props;
const { currentId, selectedKey } = this.state;
const { grantPayroll, getInfoList } = payrollStore;
grantPayroll({
ids: [record.id],
...record,
salarySendId: currentId
}).then(() => {
getInfoList({
salarySendId: currentId,
isGranted: selectedKey !== "0"
});
this.handleClose();
});
}
};
/*
* Author: 黎永顺
@ -101,6 +105,8 @@ export default class PayrollGrant extends React.Component {
this.setState({
payrollPartModalParams: {
...payrollPartModalParams,
salarySendId: currentId,
grantType: "grant",
visible: true
}
});
@ -136,7 +142,9 @@ export default class PayrollGrant extends React.Component {
payrollPartModalParams: {
...payrollPartModalParams,
visible: true,
title: "工资单撤回"
title: "工资单撤回",
salarySendId: currentId,
grantType: "withdraw"
}
});
break;
@ -216,9 +224,7 @@ export default class PayrollGrant extends React.Component {
return (
<a
href="javascript:void(0);"
onClick={() => {
this.handleWithdraw(record);
}}>
onClick={() => this.handleWithdraw({ ids: [record.id] })}>
撤回
</a>
);
@ -226,9 +232,7 @@ export default class PayrollGrant extends React.Component {
return (
<a
href="javascript:void(0);"
onClick={() => {
this.handleGrant(record);
}}>
onClick={() => this.handleGrant({ ids: [record.id] })}>
发放
</a>
);
@ -355,7 +359,9 @@ export default class PayrollGrant extends React.Component {
payrollPartModalParams: {
...payrollPartModalParams,
visible: false,
title: "工资单发放"
title: "工资单发放",
grantType: "",
salarySendId: ""
}
});
};
@ -478,7 +484,12 @@ export default class PayrollGrant extends React.Component {
}}
/>
</div>
<PayrollPartTable {...payrollPartModalParams} onCancel={this.handleClose}/>
<PayrollPartTable
{...payrollPartModalParams}
onCancel={this.handleClose}
onWithdraw={this.handleWithdraw}
onGrant={this.handleGrant}
/>
</div>
);
}

View File

@ -5,114 +5,234 @@
* Date: 2022/12/2
*/
import React, { Component } from "react";
import { inject, observer } from "mobx-react";
import { WeaBrowser, WeaDialog, WeaFormItem, WeaSearchGroup, WeaSelect } from "ecCom";
import { Button, message, Modal } from "antd";
import { getTaxAgentRangeForm, taxAgentRangeSave } from "../../../apis/taxAgent";
import { SelectWithAll } from "../../socialSecurityBenefits/standingBookDetail/components/regAddEmployee";
import { commonEnumList } from "../../../apis/ruleconfig";
import { sendRangeSave } from "../../../apis/payroll";
import "./index.less";
@inject("taxAgentStore")
@observer
class PayrollPartModal extends Component {
constructor(props) {
super(props);
this.state = {
loading: false,
employeeStatus: [],
targetTypeList: [],
targetType: "EMPLOYEE",
targetTypeIds: "",
targetTypeIdsNames: "",
status: "",
statusAll: ""
personalAddItem: [
{
viewAttr: 3,
key: "include",
label: "对象",
targetType: "1",
targetTypeIds: "",
targetTypeIdsNames: ""
},
{
viewAttr: 2,
key: "exclude",
label: "对象中排除",
targetType: "1",
targetTypeIds: "",
targetTypeIdsNames: ""
}
]
};
}
componentDidMount() {
this.getTaxAgentRangeForm();
const { taxAgentStore } = this.props;
const { getTaxAgentSelectListAsAdmin } = taxAgentStore;
getTaxAgentSelectListAsAdmin();
}
getTaxAgentRangeForm = () => {
getTaxAgentRangeForm().then(({ status, data }) => {
componentWillReceiveProps(nextProps, nextContext) {
if (nextProps.visible !== this.props.visible) {
nextProps.visible && this.orderRuleEnum();
}
}
orderRuleEnum = () => {
const payload = {
enumClass: "com.engine.salary.enums.salarysend.SalarySendRangeTargetTypeEnum"
};
commonEnumList(payload).then(({ status, data }) => {
if (status) {
const { employeeStatus, targetTypeList } = data;
this.setState({
targetTypeList: _.map(targetTypeList, it => ({ key: it.id, showname: it.name })),
employeeStatus: _.map(employeeStatus, it => ({ key: it.id, showname: it.name }))
targetTypeList: _.map(data, item => {
return {
key: item.value.toString(),
showname: item.defaultLabel
};
})
});
}
});
};
taxAgentRangeSave = () => {
const { status, targetTypeIds, targetType } = this.state;
const { includeType, taxAgentId, onSuccess, onCancel } = this.props;
if (_.isEmpty(status) || _.isEmpty(targetTypeIds)) {
const { grantType, salarySendId, onCancel } = this.props;
const { personalAddItem } = this.state;
let excludeObjParams = [], includeObjParams = [];
if (
_.find(personalAddItem, item => item.viewAttr === 3).targetType !== "0" &&
_.isEmpty(_.find(personalAddItem, item => item.viewAttr === 3).targetTypeIds)
) {
Modal.warning({
title: "信息确认",
content: "必要信息不完整,红色*为必填项!"
});
return;
}
_.map(personalAddItem, it => {
const { key, targetType, targetTypeIds } = it;
if (key === "include") {
if (targetType === "0") {
includeObjParams = [{ targetType, targetId: "" }];
} else {
if (targetTypeIds) {
includeObjParams = _.map(targetTypeIds.split(","), child => ({
targetType, targetId: child
}));
}
}
} else if (key === "exclude") {
if (targetType === "0") {
excludeObjParams = [{ targetType, targetId: "" }];
} else {
if (targetTypeIds) {
excludeObjParams = _.map(targetTypeIds.split(","), child => ({
targetType, targetId: child
}));
}
}
}
});
const payload = {
employeeStatus: status.split(","),
includeType,
targetParams: _.map(targetTypeIds.split(","), it => ({ targetType, targetId: it })),
taxAgentId
grantType, salarySendId,
excludeObjParams, includeObjParams
};
this.setState({ loading: true });
taxAgentRangeSave(payload).then(({ status, errormsg }) => {
sendRangeSave(payload).then(({ status, errormsg }) => {
this.setState({ loading: false });
if (status) {
message.success("保存成功");
this.handleReset();
onSuccess();
onCancel();
} else {
message.error(errormsg || "保存失败");
}
}).catch(() => this.setState({ loading: true }));
}).catch(() => this.setState({ loading: false }));
};
renderBrowser = () => {
const { targetType, targetTypeIds, targetTypeIdsNames } = this.state;
handleChange = (type, value) => {
const { personalAddItem } = this.state;
this.setState({
personalAddItem: _.map(personalAddItem, it => {
if (it.key === type) {
return {
...it,
targetType: value,
targetTypeIds: ""
};
}
return { ...it };
})
});
};
renderBrowser = (item) => {
const { personalAddItem } = this.state;
const { taxAgentStore } = this.props;
const { targetType, targetTypeIds, targetTypeIdsNames, key, viewAttr } = item;
let browserType = {};
switch (targetType) {
case "EMPLOYEE":
browserType = { ...browserType, type: 17, title: "人员选择" };
break;
case "DEPT":
browserType = { ...browserType, type: 57, title: "部门选择" };
break;
case "SUBCOMPANY":
browserType = { ...browserType, type: 164, title: "分部选择" };
break;
case "POSITION":
browserType = { ...browserType, type: 278, title: "岗位选择" };
break;
default:
break;
if (targetType === "5") {
return <WeaSelect
multiple
viewAttr={viewAttr}
style={{ width: 200 }}
value={targetTypeIds}
options={taxAgentStore.taxAgentAdminOption}
onChange={(targetTypeIds, targetTypeIdsNames) => {
this.setState({
personalAddItem: _.map(personalAddItem, it => {
if (it.key === key) {
return {
...it,
targetTypeIds, targetTypeIdsNames
};
}
return { ...it };
})
});
}}
/>;
} else if (targetType === "0") {
return null;
} else {
switch (targetType) {
case "1":
browserType = { ...browserType, type: 17, title: "人员选择" };
break;
case "2":
browserType = { ...browserType, type: 57, title: "部门选择" };
break;
case "3":
browserType = { ...browserType, type: 164, title: "分部选择" };
break;
case "4":
browserType = { ...browserType, type: 278, title: "岗位选择" };
break;
default:
break;
}
return <WeaBrowser
{...browserType}
viewAttr={viewAttr}
isSingle={false}
value={targetTypeIds}
valueSpan={targetTypeIdsNames}
inputStyle={{ width: 200 }}
onChange={(targetTypeIds, targetTypeIdsNames) => {
this.setState({
personalAddItem: _.map(personalAddItem, it => {
if (it.key === key) {
return {
...it,
targetTypeIds, targetTypeIdsNames
};
}
return { ...it };
})
});
}}
/>;
}
return <WeaBrowser
{...browserType}
viewAttr={3}
isSingle={false}
value={targetTypeIds}
valueSpan={targetTypeIdsNames}
inputStyle={{ width: 200 }}
onChange={(targetTypeIds, targetTypeIdsNames) => {
this.setState({ targetTypeIds, targetTypeIdsNames });
}}
/>;
};
handleReset = () => {
this.setState({
targetType: "EMPLOYEE",
targetTypeIds: "",
status: "",
statusAll: ""
personalAddItem: [
{
viewAttr: 3,
key: "include",
label: "对象",
targetType: "1",
targetTypeIds: "",
targetTypeIdsNames: ""
},
{
viewAttr: 2,
key: "exclude",
label: "对象中排除",
targetType: "1",
targetTypeIds: "",
targetTypeIdsNames: ""
}
]
});
};
render() {
const { onCancel, title, visible } = this.props;
const { employeeStatus, targetTypeList, targetType, status, statusAll, loading } = this.state;
const { onCancel, visible } = this.props;
const { targetTypeList, personalAddItem, loading } = this.state;
const buttons = [
<Button type="primary" onClick={this.taxAgentRangeSave} loading={loading}>确定</Button>,
<Button type="ghost" onClick={this.handleReset}>重置</Button>
@ -121,7 +241,7 @@ class PayrollPartModal extends Component {
<WeaDialog
initLoadCss
className="payrollPartModalWrapper"
title={title}
title="添加"
visible={visible}
style={{ width: 600 }}
buttons={buttons}
@ -131,55 +251,25 @@ class PayrollPartModal extends Component {
}}
>
<WeaSearchGroup col={1} needTigger title="" showGroup center>
<WeaFormItem
label="对象类型"
labelCol={{ span: 6 }}
wrapperCol={{ span: 18 }}
>
<div style={{ display: "flex", alignItems: "center" }}>
<WeaSelect
style={{ width: 60, marginRight: 12 }}
value={targetType}
options={targetTypeList}
onChange={(targetType) => this.setState({ targetType })}
/>
{this.renderBrowser()}
</div>
</WeaFormItem>
{
SelectWithAll({
label: "选择员工状态",
options: employeeStatus,
detailtype: 2,
valueAll: statusAll,
value: status,
onChangeAll: ({ selected }) => {
if (selected) {
this.setState({
status: _.map(employeeStatus, it => it.key).join(","),
statusAll: selected
});
} else {
this.setState({
status: "",
statusAll: selected
});
}
},
onChange: ({ selected }) => {
const bool = _.every(_.map(employeeStatus, it => it.key), item => selected.split(",").includes(item));
if (bool) {
this.setState({
status: selected,
statusAll: "0"
});
} else {
this.setState({
status: selected,
statusAll: ""
});
}
}
_.map(personalAddItem, it => {
const { targetType, key, label } = it;
return <WeaFormItem
key={key}
label={label}
labelCol={{ span: 6 }}
wrapperCol={{ span: 18 }}
>
<div style={{ display: "flex", alignItems: "center" }}>
<WeaSelect
style={{ width: 60, marginRight: 12 }}
value={targetType}
options={targetTypeList}
onChange={(v) => this.handleChange(key, v)}
/>
{this.renderBrowser(it)}
</div>
</WeaFormItem>;
})
}
</WeaSearchGroup>

View File

@ -5,61 +5,197 @@
* Date: 2022/12/2
*/
import React, { Component } from "react";
import { Button } from "antd";
import { WeaButtonIcon, WeaDialog, WeaInputSearch } from "ecCom";
import { Button, message, Modal } from "antd";
import { WeaButtonIcon, WeaDialog, WeaInputSearch, WeaTable } from "ecCom";
import { sendRangeDelete, sendRangeList } from "../../../apis/payroll";
import { calcPageNo } from "../../../util";
import PayrollPartModal from "./payrollPartModal";
// import PayrollPartModal from "./payrollPartModal";
class PayrollPartTable extends Component {
constructor(props) {
super(props);
this.state = {
searchValue: "",
dialogVisible: false
dialogVisible: false,
loading: {
query: false
},
dataSource: [],
columns: [],
selectedRowKeys: [],
pageInfo: {
current: 1,
pageSize: 10,
total: 0
}
};
}
renderTitle = () => {
const { title } = this.props;
const { searchValue } = this.state;
return <div className="titleWrapper">
<div>{title}</div>
<div className="rightBtnlist">
<Button type="primary">{title.slice(-2)}</Button>
<WeaButtonIcon
buttonType="del"
type="primary"
disabled={false}
/>
<WeaButtonIcon buttonType="add" type="primary"/>
<WeaInputSearch
style={{ width: 120 }}
value={searchValue}
onChange={searchValue => this.setState({ searchValue })}
placeholder="请输入方案名称"
onSearch={() => {
}}
/>
</div>
</div>;
componentWillReceiveProps(nextProps, nextContext) {
if (nextProps.visible !== this.props.visible) {
nextProps.visible && this.sendRangeList(nextProps);
this.setState({ selectedRowKeys: [] });
}
}
sendRangeList = (props) => {
const { grantType, salarySendId, pageCurrent = {} } = props;
const { pageInfo, loading, searchValue: targetName } = this.state;
const payload = {
grantType,
salarySendId,
targetName,
...pageInfo,
...pageCurrent
};
this.setState({ loading: { ...loading, query: true } });
sendRangeList(payload).then(({ status, data }) => {
this.setState({ loading: { ...loading, query: false } });
if (status) {
const { pageNum: current, pageSize, total, columns, list: dataSource } = data;
this.setState({
pageInfo: { ...pageInfo, current, pageSize, total },
dataSource: _.map(dataSource, it => ({
...it,
includeObj: _.map(it.includeObj, child => child.targetName).join(","),
excludeObj: _.map(it.excludeObj, child => child.targetName).join(",")
})),
columns
});
}
});
};
sendRangeDelete = () => {
const { selectedRowKeys, pageInfo } = this.state;
const { grantType, salarySendId } = this.props;
Modal.confirm({
title: "信息确认",
content: "确认要删除吗?",
onOk: () => {
sendRangeDelete(selectedRowKeys).then(({ status, errormsg }) => {
if (status) {
message.success("刪除成功");
this.setState({ selectedRowKeys: [] }, () => {
this.sendRangeList({
grantType, salarySendId,
pageCurrent: {
current: calcPageNo(pageInfo.total, pageInfo.current, 10, selectedRowKeys.length)
}
});
});
} else {
message.error(errormsg || "刪除失败");
}
});
},
onCancel: () => {
}
});
};
handleOperate = () => {
const { grantType, salarySendId, onWithdraw, onGrant } = this.props;
const { selectedRowKeys } = this.state;
if (_.isEmpty(selectedRowKeys)) {
message.warning("您没有需要处理的对象!");
return;
}
Modal.confirm({
title: "信息确认",
content: `您共选择${selectedRowKeys.length}个对象,确定要${grantType === "grant" ? "发放" : "撤回"}吗?`,
onCancel: () => {
},
onOk: () => {
if (grantType === "grant") {
onGrant({ ids: [salarySendId], salarySendRangeIds: selectedRowKeys });
} else if (grantType === "withdraw") {
onWithdraw({ ids: [salarySendId], salarySendRangeIds: selectedRowKeys });
}
}
});
};
render() {
const { onCancel, visible } = this.props;
const { dataSource, columns, pageInfo, loading, selectedRowKeys, dialogVisible, searchValue } = this.state;
const { onCancel, visible, grantType, salarySendId, title } = this.props;
const pagination = {
...pageInfo,
showTotal: total => `${total}`,
showQuickJumper: true,
pageSizeOptions: ["10", "20", "50", "100"],
onChange: current => {
this.setState({
pageInfo: { ...pageInfo, current }
}, () => {
});
}
};
const rowSelection = {
selectedRowKeys,
onChange: (selectedRowKeys) => this.setState({ selectedRowKeys })
};
return (
<WeaDialog
initLoadCss
className="payrollPartTableModalWrapper"
onCancel={onCancel}
title={this.renderTitle()}
onCancel={() => this.setState({ selectedRowKeys: [] }, () => onCancel())}
title={
<RenderTitle
title={title}
selectedRowKeys={selectedRowKeys}
onAdd={() => this.setState({ dialogVisible: true })}
onDelete={this.sendRangeDelete}
onSave={this.handleOperate}
/>
}
visible={visible}
style={{ width: 700 }}
style={{ width: 700, height: 600 }}
hasScroll
>
{/*<PayrollPartModal/>*/}
<div style={{ display: "flex", justifyContent: "flex-end", margin: "10px 10px 10px 0" }}>
<WeaInputSearch
style={{ width: 220 }}
searchValue={searchValue}
onChange={(searchValue) => this.setState({ searchValue })}
onSearch={() => this.sendRangeList({ grantType, salarySendId })}
placeholder="请输入方案名称"
/>
</div>
<WeaTable
rowKey="id"
rowSelection={rowSelection}
dataSource={dataSource}
pagination={pagination}
loading={loading.query}
columns={columns}
/>
<PayrollPartModal
grantType={grantType}
salarySendId={salarySendId}
visible={dialogVisible}
onCancel={() => this.setState({ dialogVisible: false }, () => {
this.sendRangeList({ grantType, salarySendId });
})}
/>
</WeaDialog>
);
}
}
export default PayrollPartTable;
const RenderTitle = (props) => {
const { title, selectedRowKeys, onAdd, onDelete, onSave } = props;
return <div className="titleWrapper">
<div>{title}</div>
<div className="rightBtnlist">
<Button type="primary" onClick={onSave}>{title.slice(-2)}</Button>
<WeaButtonIcon
buttonType="del"
type="primary"
disabled={_.isEmpty(selectedRowKeys)}
onClick={onDelete}
/>
<WeaButtonIcon buttonType="add" type="primary" onClick={onAdd}/>
</div>
</div>;
};