Merge branch 'develop' into release

This commit is contained in:
黎永顺 2022-12-21 15:29:45 +08:00
commit 3170ed0ea9
66 changed files with 5748 additions and 417 deletions

View File

@ -333,6 +333,17 @@ export const fileSalaryAcct = (params) => {
}
}).then(res => res.json());
};
// 薪资记录-回算
export const backCalculate = (params) => {
return fetch("/api/bs/hrmsalary/salaryacct/backCalculate", {
method: "POST",
mode: "cors",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(params)
}).then(res => res.json());
};
// 薪资记录-重新核算
export const reAccounting = (params) => {

View File

@ -268,3 +268,17 @@ export const listAdjustmentRule = params => {
body: JSON.stringify(params)
}).then(res => res.json());
};
//获取回算薪资项目
export const getAggregate = params => {
return WeaTools.callApi("/api/bs/hrmsalary/salarysob/backitem/getAggregate", "GET", params);
};
//编辑回算薪资项目详情
export const getBackitemForm = params => {
return WeaTools.callApi("/api/bs/hrmsalary/salarysob/backitem/getForm", "GET", params);
};
//保存回算薪资项目详情
export const salarysobBackitemSave = params => {
return postFetch("/api/bs/hrmsalary/salarysob/backitem/save", params);
};

View File

@ -315,6 +315,29 @@ export const grantProxy = params => {
}).then(res => res.json());
};
// 工资单发放-新建时获取补发工资单模板薪资项目设置
export const getReplenishForm = params => {
return fetch("/api/bs/hrmsalary/salaryBill/template/getReplenishForm", {
method: "POST",
mode: "cors",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(params)
}).then(res => res.json());
};
// 工资单发放-获取规则设置下拉框
export const getReplenishRuleSetOptions = ({ salarySobId }) => {
return fetch(`/api/bs/hrmsalary/salaryBill/template/getReplenishRuleSetOptions?salarySobId=${salarySobId}`, {
method: "GET",
mode: "cors",
headers: {
"Content-Type": "application/json"
}
}).then(res => res.json());
};
//添加发送和撤回人员范围列表
export const sendRangeList = (params) => {
return postFetch('/api/bs/hrmsalary/salaryBill/send/range/list', params);

View File

@ -202,6 +202,14 @@ export const getWelfareList = () => {
{}
);
};
// 补差表单字段对应的接口
export const getBalanceWelfareList = () => {
return WeaTools.callApi(
"/api/bs/hrmsalary/siaccount/getBalanceWelfareList",
"get",
{}
);
};
// 社保福利台账-导入预览
export const welfarePreview = (params) => {
@ -226,6 +234,17 @@ export const importInsuranceAcctDetail = (params) => {
body: JSON.stringify(params)
}).then((res) => res.json());
};
// 社保福利台账-补差数据导入
export const importBalanceInsuranceDetail = (params) => {
return fetch("/api/bs/hrmsalary/siaccount/welfare/importBalanceInsuranceDetail", {
method: "post",
mode: "cors",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(params)
}).then((res) => res.json());
};
// 社保福利台账-线下对比数据导入
export const importExcelInsuranceDetail = (params) => {
@ -251,10 +270,18 @@ export const saveRecession = (params) => {
export const recessionList = (params) => {
return postFetch("/api/bs/hrmsalary/siaccount/detail/recession/list", params);
};
//查询补差列表
export const balanceList = (params) => {
return postFetch("/api/bs/hrmsalary/siaccount/detail/balance/list", params);
};
//删除退差数据
export const delRecession = (params) => {
return postFetch("/api/bs/hrmsalary/siaccount/delRecession", params);
};
//删除补差数据
export const delBalance = (params) => {
return postFetch("/api/bs/hrmsalary/siaccount/delBalance", params);
};
//编辑社保福利缴纳数据
export const editAccount = (params) => {
return postFetch("/api/bs/hrmsalary/siaccount/editAccount", params);

View File

@ -17,10 +17,14 @@ export const queryList = (params) => {
export const queryInsuranceTabTotal = (params) => {
return WeaTools.callApi('/api/bs/hrmsalary/archives/queryInsuranceTabTotal', params);
};
//删除待办
//删除待办-待增员
export const updateRunStatus = (params) => {
return postFetch('/api/bs/hrmsalary/archives/updateRunStatus', params);
};
//删除待办-待减员
export const cancelStayDel = (params) => {
return postFetch('/api/bs/hrmsalary/archives/cancelStayDel', params);
};
//全量增员
export const allStayAddToPay = (params) => {
return WeaTools.callApi('/api/bs/hrmsalary/archives/allStayAddToPay', 'GET', params);

View File

@ -0,0 +1,227 @@
/*
* Author: 黎永顺
* name: 新增人员范围弹框
* Description:
* Date: 2022/11/30
*/
import React, { Component } from "react";
import { WeaBrowser, WeaDialog, WeaFormItem, WeaSearchGroup, WeaSelect } from "ecCom";
import { Button, message, Modal } from "antd";
import { getTaxAgentRangeForm } from "../../apis/taxAgent";
import { SelectWithAll } from "../../pages/socialSecurityBenefits/standingBookDetail/components/regAddEmployee";
import "./index.less";
class PersonalScopeModal extends Component {
constructor(props) {
super(props);
this.state = {
loading: false,
employeeStatus: [],
targetTypeList: [],
targetType: "EMPLOYEE",
targetTypeIds: "",
targetTypeIdsNames: "",
status: "",
statusAll: ""
};
}
componentDidMount() {
const { isTaxgent = true } = this.props;
if (isTaxgent) {
this.getTaxAgentRangeForm();
} else {
const employeeStatus = [
{ key: "TRIAL", showname: "试用" },
{ key: "FORMAL", showname: "正式" },
{ key: "TEMPORARY", showname: "临时" },
{ key: "DELAY", showname: "试用延期" },
{ key: "FIRE", showname: "解雇" },
{ key: "DEPARTURE", showname: "离职" },
{ key: "RETIRED", showname: "退休" }
];
const targetTypeList = [
{
key: "EMPLOYEE",
showname: "人员",
selected: false
},
{
key: "SUBCOMPANY",
showname: "分部",
selected: false
},
{
key: "DEPT",
showname: "部门",
selected: false
},
{
key: "POSITION",
showname: "岗位",
selected: false
}
];
this.setState({ targetTypeList, employeeStatus });
}
}
getTaxAgentRangeForm = () => {
getTaxAgentRangeForm().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 }))
});
}
});
};
handleSubmit = () => {
const { status, targetTypeIds, targetType } = this.state;
const { includeType, saveKeyVal, onSuccess, onCancel, APISaveFox } = this.props;
if (_.isEmpty(status) || _.isEmpty(targetTypeIds)) {
Modal.warning({
title: "信息确认",
content: "必要信息不完整,红色*为必填项!"
});
return;
}
const payload = {
employeeStatus: status.split(","),
includeType,
targetParams: _.map(targetTypeIds.split(","), it => ({ targetType, targetId: it })),
[saveKeyVal["key"]]: saveKeyVal["value"],
};
this.setState({ loading: true });
APISaveFox["save"](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 }));
};
renderBrowser = () => {
const { targetType, targetTypeIds, targetTypeIdsNames } = this.state;
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;
}
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: ""
});
};
render() {
const { onCancel, title, visible } = this.props;
const { employeeStatus, targetTypeList, targetType, status, statusAll, loading } = this.state;
const buttons = [
<Button type="primary" onClick={this.handleSubmit} loading={loading}>确定</Button>,
<Button type="ghost" onClick={this.handleReset}>重置</Button>
];
return (
<WeaDialog
initLoadCss
className="personalScopeModalWrapper"
title={title}
visible={visible}
style={{ width: 600 }}
buttons={buttons}
onCancel={() => {
this.handleReset();
onCancel();
}}
>
<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: ""
});
}
}
})
}
</WeaSearchGroup>
</WeaDialog>
);
}
}
export default PersonalScopeModal;

View File

@ -0,0 +1,14 @@
//添加关联人员弹框中的下拉框样式
.personalScopeModalWrapper{
.wea-select,.ant-select-selection,.ant-select{
width: 100%;
}
.wea-select{
display: inline-block;
position: relative;
}
.ant-select-selection{
height: 30px;
border-radius: 0;
}
}

View File

@ -0,0 +1,130 @@
/*
* Author: 黎永顺
* name: 人员范围列表数据
* Description:
* Date: 2022/11/30
*/
import React, { Component } from "react";
import { WeaTable } from "ecCom";
import { calcPageNo } from "../../util";
import "./index.less";
class PersonalScopeTable extends Component {
constructor(props) {
super(props);
this.state = {
loading: {
query: false
},
dataSource: [],
columns: [],
selectedRowKeys: [],
pageInfo: {
current: 1,
pageSize: 10,
total: 0
}
};
}
componentDidMount() {
this.getPersonalScopeList();
}
componentWillReceiveProps(nextProps, nextContext) {
if (nextProps.tabActive !== this.props.tabActive) {
this.setState({ selectedRowKeys: [] }, () => {
this.getPersonalScopeList(nextProps.tabActive);
nextProps.onChangeSelectKey([]);
});
}
}
getPersonalScopeList = (tabActive = this.props.tabActive) => {
const { searchValue, searchKeyVal, APIFox } = this.props;
const { pageInfo, loading } = this.state;
const payload = {
[searchKeyVal["key"]]: searchKeyVal["value"],
targetName: searchValue,
...pageInfo
};
this.setState({ loading: { ...loading, query: true } });
APIFox[tabActive](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,
columns: _.map(columns, item => {
return {
...item,
render: (text) => {
return <span className="tdEllipsis" title={text}>{text}</span>;
}
};
})
});
}
}).catch(() => {
this.setState({ loading: { ...loading, query: false } });
});
};
/*
* Author: 黎永顺
* Description: 清空选中项
* Params:
* Date: 2022/11/30
*/
clearRowkeys = () => {
const { pageInfo, selectedRowKeys } = this.state;
this.setState({
selectedRowKeys: [],
pageInfo: {
...pageInfo,
current: calcPageNo(pageInfo.total, pageInfo.current, 10, selectedRowKeys.length)
}
}, () => {
this.getPersonalScopeList();
});
};
render() {
const { dataSource, columns, pageInfo, loading, selectedRowKeys } = this.state;
const { onChangeSelectKey } = this.props;
const pagination = {
...pageInfo,
showTotal: total => `${total}`,
showQuickJumper: true,
pageSizeOptions: ["10", "20", "50", "100"],
onChange: current => {
this.setState({
pageInfo: { ...pageInfo, current }
}, () => {
this.getPersonalScopeList();
});
}
};
const rowSelection = {
selectedRowKeys,
onChange: (selectedRowKeys) => {
this.setState({ selectedRowKeys }, () => {
onChangeSelectKey(this.state.selectedRowKeys);
});
}
};
return (
<WeaTable
rowKey="id"
rowSelection={rowSelection}
dataSource={dataSource}
pagination={pagination}
loading={loading.query}
columns={columns}
/>
);
}
}
export default PersonalScopeTable;

View File

@ -0,0 +1,11 @@
.ledgerWrapper {
height: 100%;
.tdEllipsis {
display: inline-block;
width: 100%;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}

View File

@ -1,28 +1,29 @@
import React from 'react';
import { WeaSteps } from 'ecCom'
import React from "react";
import { WeaSteps } from "ecCom";
import "./index.less";
const Step = WeaSteps.Step;
import "./index.less"
export default class StepSlideHeader extends React.Component {
render() {
return (
<div className="stepSlideHeader">
<div className="headerWrapper">
<WeaSteps current={this.props.current}>
{
this.props.steps && this.props.steps.map(item =>
(
<Step description={item} />
)
)
}
</WeaSteps>
</div>
<div className="contentWrapper">
{this.props.children}
</div>
</div>
)
}
}
render() {
return (
<div className="stepSlideHeader">
<div className="headerWrapper">
<WeaSteps current={this.props.current}>
{
this.props.steps && this.props.steps.map(item =>
(
<Step description={item}/>
)
)
}
</WeaSteps>
</div>
<div className="contentWrapper">
{this.props.children}
</div>
</div>
);
}
}

View File

@ -14,7 +14,7 @@ import OtherDeduct from "./pages/dataAcquisition/otherDeduct";
import CumSituation from "./pages/dataAcquisition/cumSituation";
import Attendance from "./pages/dataAcquisition/attendance";
import SpecialAddDeduction from "./pages/dataAcquisition/specialAddDeduction";
import Ledger from "./pages/ledger";
import Ledger from "./pages/ledgerPage";
import Calculate from "./pages/calculate";
import Payroll from "./pages/payroll";
import PayrollGrant from "./pages/payroll/payrollGrant";

View File

@ -1,15 +1,15 @@
import React from "react";
import { inject, observer } from "mobx-react";
import { Button, DatePicker, Dropdown, Menu, message, Modal } from "antd";
import { Button, DatePicker, Dropdown, Menu, message, Modal, Tag } from "antd";
import { WeaInputSearch, WeaTop } from "ecCom";
import { renderNoright } from "../../util"; // 渲染form数据的方法因为多个页面都会使用所以抽的公共方法在util中
import CustomTab from "../../components/customTab";
import { columns } from "./columns";
import moment from "moment";
import BaseFormModal from "./baseFormModal";
import CustomPaginationTable from "../../components/customPaginationTable";
import ProgressModal from "../../components/progressModal";
import "./index.less";
import { deleteLedgerPersonRange } from "../../apis/ledger";
const MonthPicker = DatePicker.MonthPicker;
@ -26,25 +26,7 @@ export default class Calculate extends React.Component {
searchValue: "",
startDate: moment(new Date()).startOf("year").format("YYYY-MM"),
endDate: moment(new Date()).startOf("month").format("YYYY-MM"),
current: 1,
columns: columns.map(item => {
if (item.dataIndex == "cz") {
item.render = () =>
<div>
<a style={{ marginRight: "10px" }}>核算</a>
<a style={{ marginRight: "10px" }}>归档</a>
<a
style={{ marginRight: "10px" }}
onClick={() =>
window.open(
"/spa/hrmSalary/static/index.html#/main/hrmSalary/placeOnFileDetail"
)}>
查看
</a>
<a>删除</a>
</div>;
}
})
current: 1
};
this.pageInfo = { current: 1, pageSize: 10 };
}
@ -141,6 +123,12 @@ export default class Calculate extends React.Component {
message.success("归档成功");
this.handleSearch(this.state.searchValue);
});
}).catch(() => {
clearInterval(this.timer);
this.setState({
progressVisible: false,
progress: 0
});
});
}
@ -152,6 +140,20 @@ export default class Calculate extends React.Component {
});
}
// 回算
handleBackCalculate = (record) => {
Modal.confirm({
title: "信息确认",
content: "确定回算吗?\n 回算后,正常核算的数据会被覆盖,正常核算的工资单不能继续发放或撤回!",
onOk: () => {
const { calculateStore: { backCalculate } } = this.props;
backCalculate(record.id).then(() => {
this.handleSearch(this.state.searchValue);
});
}
});
};
// 查看详情回调
handleDetail(record) {
window.open(
@ -161,13 +163,28 @@ export default class Calculate extends React.Component {
}
// 获取列表
getColumns() {
getColumns = () => {
const {
calculateStore: { salaryListColumns },
taxAgentStore: { showOperateBtn }
} = this.props;
let columns = [...salaryListColumns];
let columns = [...salaryListColumns].filter(item => item.dataIndex !== "backCalcStatus" && item.dataIndex !== "acctTimes");
columns.map(item => {
if (item.dataIndex === "salarySobName") {
item.width = 300;
item.render = (text, record) => {
return <div className="salarySobNameWrapper">
<span>{text}</span>
<div className="salarySobNameTagWrapper">
{
record.backCalcStatus === 1 &&
<i className="icon-coms-Refresh" title="回算"/>
}
<Tag color="blue">{`${record.acctTimes}`}</Tag>
</div>
</div>;
};
}
if (item.title == "操作" && showOperateBtn) {
item.render = (text, record) => {
const accountBtn = _.filter(
@ -222,6 +239,8 @@ export default class Calculate extends React.Component {
this.handleReaccount(record);
} else if (cz.text == "查看") {
this.handleDetail(record);
} else if (cz.text == "回算") {
this.handleBackCalculate(record);
}
}}>
{cz.text}
@ -242,7 +261,7 @@ export default class Calculate extends React.Component {
}
});
return showOperateBtn ? columns : _.filter(columns, it => it.title != "操作");
}
};
// 分页
handleDataPageChange(value) {

View File

@ -13,3 +13,19 @@
}
}
}
.salarySobNameWrapper{
display: flex;
align-items: center;
justify-content: space-between;
width: 100%;
.salarySobNameTagWrapper{
display: flex;
align-items: center;
i{
color: #5d9cec;
margin-right: 10px;
cursor: pointer;
}
}
}

View File

@ -37,7 +37,7 @@ export default class AcctResultImportModal extends React.Component {
// 获取模板
handleAccResultTemplateLink() {
const { isStandingBook, standingBookTabKey } = this.props;
const { isStandingBook, standingBookTabKey, standingBookType } = this.props;
let url = "";
if (_.isEmpty(this.state.modalParam.salaryItemIds)) {
message.warning("请选择表单字段");
@ -52,6 +52,8 @@ export default class AcctResultImportModal extends React.Component {
url = `${window.location.origin}/api/bs/hrmsalary/siaccount/welfare/importtemplate/export?welfareNames=${this.state.modalParam.salaryItemIds}&billMonth=${billMonth}&paymentOrganization=${paymentOrganization}`;
} else if (standingBookTabKey === "3") {
url = `${window.location.origin}/api/bs/hrmsalary/siaccount/welfare/supplyimporttemplate/export?welfareNames=${this.state.modalParam.salaryItemIds}&billMonth=${billMonth}&paymentOrganization=${paymentOrganization}`;
} else if (standingBookType === "difference") {
url = `${window.location.origin}/api/bs/hrmsalary/siaccount/welfare/balanceimporttemplate/export?welfareNames=${this.state.modalParam.salaryItemIds}&billMonth=${billMonth}&paymentOrganization=${paymentOrganization}`;
}
}
window.open(url, "_self");
@ -162,8 +164,10 @@ export default class AcctResultImportModal extends React.Component {
}
render() {
const billMonth = getQueryString("billMonth");
//isStandingBook: 是否是社保福利台账核算的导入标识
const { calculateStore, standingBookStore, isStandingBook, visiable } = this.props;
//standingBookType: 是否是补差的导入标识
const { calculateStore, standingBookStore, isStandingBook, visiable, standingBookType } = this.props;
const {
fetchPreviewAcctResult,
previewAcctResultColumns,
@ -176,7 +180,8 @@ export default class AcctResultImportModal extends React.Component {
previewStandingBookAcctResultColumns,
previewStandingBookAcctResultDataSource,
importStandingBookAcctResult,
importInsuranceAcctDetail
importInsuranceAcctDetail,
importBalanceInsuranceDetail
} = standingBookStore;
const { step, selectFieldVisible, modalParam } = this.state;
return (
@ -184,6 +189,7 @@ export default class AcctResultImportModal extends React.Component {
{
visiable && <ImportModal
isStandingBook={isStandingBook}
standingBookType={standingBookType}
init={() => {
this.handleImportModalInit();
}}
@ -200,7 +206,11 @@ export default class AcctResultImportModal extends React.Component {
!isStandingBook ? fetchPreviewAcctResult(params) : welfarePreview(params);
}}
importFile={(params) => {
!isStandingBook ? fetchImportAcctResult(params) : importInsuranceAcctDetail(params);
!isStandingBook ?
fetchImportAcctResult(params) :
standingBookType === "difference" ?
importBalanceInsuranceDetail({...params, billMonth}) :
importInsuranceAcctDetail(params);
}}
templateLink={() => {
this.handleAccResultTemplateLink();
@ -215,6 +225,7 @@ export default class AcctResultImportModal extends React.Component {
{
selectFieldVisible && <SelectFieldModal
isStandingBook={isStandingBook}
standingBookType={standingBookType}
id={this.props.id}
visible={selectFieldVisible}
fieldData={this.props.fieldData}

View File

@ -3,6 +3,8 @@ import { Button, Col, Row } from "antd";
import { inject, observer } from "mobx-react";
import { WeaCheckbox, WeaDialog } from "ecCom";
const APIFox = {};
@inject("calculateStore", "standingBookStore")
@observer
export default class SelectFieldModal extends React.Component {
@ -14,7 +16,11 @@ export default class SelectFieldModal extends React.Component {
}
componentWillMount() {
const { calculateStore: { getImportField }, standingBookStore: { getWelfareList }, isStandingBook } = this.props;
const {
calculateStore: { getImportField },
standingBookStore: { getWelfareList, getBalanceWelfareList },
isStandingBook, standingBookType
} = this.props;
if (!isStandingBook) {
getImportField(this.props.id).then(data => {
let fieldData = {};
@ -43,7 +49,8 @@ export default class SelectFieldModal extends React.Component {
this.fieldData = fieldData;
});
} else {
getWelfareList().then(result => {
const APIFox = standingBookType === "difference" ? getBalanceWelfareList : getWelfareList;
APIFox().then(result => {
let fieldData = {};
let formulaItems = [];
formulaItems = _.map(result, it => ({ ...it, salaryItemId: it.salaryItemName }));
@ -146,9 +153,9 @@ export default class SelectFieldModal extends React.Component {
const { isStandingBook } = this.props;
return (
<WeaDialog
title='添加表头字段'
title="添加表头字段"
visible={this.props.visible}
style={{width:800}}
style={{ width: 800 }}
onCancel={() => {
this.props.onCancel();
}}
@ -161,7 +168,7 @@ export default class SelectFieldModal extends React.Component {
<div style={{ minHeight: "20vh", maxHeight: "50vh", overflow: "hidden auto", padding: "16px 20px" }}>
{
!_.isEmpty(fieldData.formulaItems) &&
<div >
<div>
<div style={{ height: "40px", lineHeight: "40px" }}>
<WeaCheckbox content={!isStandingBook ? "公式项" : "全选"} onChange={(value) => {
this.handleTitleCheckboxChange(value, "formula");

View File

@ -1,40 +1,58 @@
import React from "react";
import { WeaHelpfulTip, WeaInput } from "ecCom";
import { WeaHelpfulTip, WeaInput, WeaTab } from "ecCom";
import IssuedAndReissueTable from "./issuedAndReissueTable";
import { Col, Row } from "antd";
import { inject, observer } from "mobx-react";
import { toJS } from "mobx";
import cs from "classnames";
import "./index.less";
@inject("calculateStore")
@observer
export default class EditSalaryDetail extends React.Component {
constructor(props) {
super(props);
this.state = {
selectedKey: "0"
};
}
componentWillMount() {
const { calculateStore: { acctresultDetail } } = this.props;
acctresultDetail(this.props.id);
}
handleItemValueChange(field, value, isInput) {
handleItemValueChange = (field, value, isInput) => {
console.log(field, value, isInput);
const { calculateStore: { acctresultDetailForm, setAcctresultDetailForm } } = this.props;
let form = { ...acctresultDetailForm };
if (isInput) {
if (isInput === "inputItems") {
form.inputItems = acctresultDetailForm.inputItems.map(item => {
item = { ...item };
if (item.salaryItemName == field) {
if (item.salaryItemName === field) {
item.resultValue = value;
}
return item;
});
} else {
} else if (isInput === "formulaItems") {
form.formulaItems = acctresultDetailForm.formulaItems.map(item => {
item = { ...item };
if (item.salaryItemName == field) {
if (item.salaryItemName === field) {
item.resultValue = value;
}
return item;
});
} else if (isInput === "issuedAndReissueItems") {
form.issuedAndReissueItems = acctresultDetailForm.issuedAndReissueItems.map(item => {
item = { ...item };
if (item.salaryItemName === field) {
item.resultValue = value;
}
return item;
});
}
setAcctresultDetailForm(form);
}
};
renderTableTr = (data, isInput) => {
const tables = [];
@ -62,6 +80,17 @@ export default class EditSalaryDetail extends React.Component {
render() {
const { calculateStore: { acctresultDetailForm } } = this.props;
const { selectedKey } = this.state;
const topTab = [
{
title: "正常工资薪金所得",
viewcondition: "0"
},
{
title: "已发补发",
viewcondition: "1"
}
];
return (
<div className="editSalaryDetail">
<div className="detailItemWrapper">
@ -84,39 +113,45 @@ export default class EditSalaryDetail extends React.Component {
}
</div>
</div>
<div>
<div className="detailItemWrapper">
<span className="itemTitle">输入项</span>
<div className="itemContent">
<Row>
{
acctresultDetailForm.inputItems && acctresultDetailForm.inputItems.map((item, index) => {
const len = acctresultDetailForm.inputItems.length;
return (
<Col span={8}>
<Row>
<Col span={12}
className={cs("itemLabel", { "borderB-none": Math.ceil((index + 1) / 3) === len / 3 })}>{item.salaryItemName}</Col>
<Col span={12} className={cs("itemValue", {
"borderB-none": Math.ceil((index + 1) / 3) === len / 3,
"borderR-none": (index + 1) % 3 === 0
})}><WeaInput value={item.resultValue} disabled={!item.canEdit} onChange={(value) => {
this.handleItemValueChange(item.salaryItemName, value, true);
}}/></Col>
</Row>
</Col>
);
})
}
</Row>
{
!_.isEmpty(toJS(acctresultDetailForm.issuedAndReissueItems)) &&
<WeaTab
datas={topTab}
keyParam="viewcondition"
selectedKey={selectedKey}
onChange={v => this.setState({ selectedKey: v })}
/>
}
{
selectedKey === "0" &&
<div>
<div className="detailItemWrapper">
<span className="itemTitle">输入项</span>
<div className="itemContent">
<Row>
{
acctresultDetailForm.inputItems && acctresultDetailForm.inputItems.map((item, index) => {
const len = acctresultDetailForm.inputItems.length;
return (
<Col span={8}>
<Row>
<Col span={12}
className={cs("itemLabel", { "borderB-none": Math.ceil((index + 1) / 3) === len / 3 })}>{item.salaryItemName}</Col>
<Col span={12} className={cs("itemValue", {
"borderB-none": Math.ceil((index + 1) / 3) === len / 3,
"borderR-none": (index + 1) % 3 === 0
})}><WeaInput value={item.resultValue} disabled={!item.canEdit} onChange={(value) => {
this.handleItemValueChange(item.salaryItemName, value, "inputItems");
}}/></Col>
</Row>
</Col>
);
})
}
</Row>
</div>
</div>
</div>
</div>
<div>
<div className="detailItemWrapper">
<div className="detailItemWrapper">
<span className="itemTitle">
<span>公式项</span>
<WeaHelpfulTip
@ -126,31 +161,39 @@ export default class EditSalaryDetail extends React.Component {
placement="topLeft"
/>
</span>
<div className="itemContent">
<Row>
{
acctresultDetailForm.formulaItems && acctresultDetailForm.formulaItems.map((item, index) => {
const len = acctresultDetailForm.formulaItems.length;
return (
<Col span={8}>
<Row>
<Col span={12}
className={cs("itemLabel", { "borderB-none": Math.ceil((index + 1) / 3) === len / 3 })}>{item.salaryItemName}</Col>
<Col span={12} className={cs("itemValue", {
"borderB-none": Math.ceil((index + 1) / 3) === len / 3,
"borderR-none": (index + 1) % 3 === 0
})}><WeaInput value={item.resultValue} disabled={!item.canEdit} onChange={(value) => {
this.handleItemValueChange(item.salaryItemName, value, false);
}}/></Col>
</Row>
</Col>
);
})
}
</Row>
<div className="itemContent">
<Row>
{
acctresultDetailForm.formulaItems && acctresultDetailForm.formulaItems.map((item, index) => {
const len = acctresultDetailForm.formulaItems.length;
return (
<Col span={8}>
<Row>
<Col span={12}
className={cs("itemLabel", { "borderB-none": Math.ceil((index + 1) / 3) === len / 3 })}>{item.salaryItemName}</Col>
<Col span={12} className={cs("itemValue", {
"borderB-none": Math.ceil((index + 1) / 3) === len / 3,
"borderR-none": (index + 1) % 3 === 0
})}><WeaInput value={item.resultValue} disabled={!item.canEdit} onChange={(value) => {
this.handleItemValueChange(item.salaryItemName, value, "formulaItems");
}}/></Col>
</Row>
</Col>
);
})
}
</Row>
</div>
</div>
</div>
</div>
}
{
selectedKey === "1" &&
<IssuedAndReissueTable
dataSource={toJS(acctresultDetailForm.issuedAndReissueItems)}
onChangeIssueReissueValue={this.handleItemValueChange}
/>
}
</div>
);
}

View File

@ -0,0 +1,68 @@
/*
* Author: 黎永顺
* name: 已发补发列表
* Description:
* Date: 2022/12/14
*/
import React, { Component } from "react";
import { WeaHelpfulTip, WeaInputNumber, WeaTable } from "ecCom";
class IssuedAndReissueTable extends Component {
render() {
const { dataSource, onChangeIssueReissueValue } = this.props;
const columns = [
{
dataIndex: "salaryItemName",
title: "薪资项目",
render: (text) => {
return <span className="tdEllipsis" title={text}>{text}</span>;
}
},
{
dataIndex: "resultValue",
title: <span>
<span style={{ marginRight: 8 }}>项目值</span>
<WeaHelpfulTip
title="若薪资项目有公式,手动编辑项目值后,需点击锁定图标输入值才生效;点击锁定图标,解锁手动编辑的项目值,公式生效,点击保存按照公式重新核算;重新核算后,不显示解锁图标。"
placement="bottom"
width={200}
/>
</span>,
render: (text, record) => {
const { canEdit } = record;
return <WeaInputNumber
disabled={!canEdit}
min={0}
precision={2}
value={text || 0}
onChange={(value) => onChangeIssueReissueValue(record.salaryItemName, value, "issuedAndReissueItems")}
/>;
}
},
{
dataIndex: "salaryBackItemFormula",
title: <span>
<span style={{ marginRight: 8 }}>核算公式</span>
<WeaHelpfulTip
title="若薪资项目有公式,且项目值手动编辑修改过并点击锁定图标,则公式失效;若解除锁定,则项目公式重新生效;"
placement="bottom"
width={200}
/>
</span>,
render: (text, record) => {
return <span className="tdEllipsis" title={text}>{_.isNil(text) ? "输入" : text}</span>;
}
}
];
return (
<WeaTable
rowKey="id"
dataSource={dataSource}
columns={columns}
pagination={false}
/>
);
}
}
export default IssuedAndReissueTable;

View File

@ -52,6 +52,8 @@ export default class SalaryDetail extends React.Component {
if (type === "PR") {
if (id === "EDIT") {
this.handleEdit(record);
} else if (id === "COSTCENTER") {
window.open(record ? record.url : "", "_blank");
} else if (id === "COLUMNINDEX") {
if (!extraId) {
this.setState({ columnIndex: record });
@ -266,7 +268,7 @@ export default class SalaryDetail extends React.Component {
measure={"%"}
title={
<SlideModalTitle
subtitle={"编辑薪资"}
subtitle="编辑薪资"
editable={true}
showOperateBtn={showOperateBtn}
onSave={() => this.handleEditSlideSave()}

View File

@ -4,7 +4,6 @@ import { WeaBrowser, WeaFormItem, WeaHelpfulTip, WeaInput, WeaSearchGroup, WeaSe
import { inject, observer } from "mobx-react";
import "./index.less";
import { getQueryString } from "../../util/url";
import { calcPageNo } from "../../util";
@inject("calculateStore", "salaryFileStore")
@observer
@ -87,8 +86,8 @@ export default class UserSure extends React.Component {
<WeaSelect
value={String(status)}
options={[
{ key: "", showname: "" }, {key: "ALL", showname: "全部"},
{ key: "NORMAL", showname: "在职" }, {key: "UNAVAILABLE", showname: "离职"}
{ key: "", showname: "" }, { key: "ALL", showname: "全部" },
{ key: "NORMAL", showname: "在职" }, { key: "UNAVAILABLE", showname: "离职" }
]}
onChange={(val) => this.setState({ searchItemsValue: { ...this.state.searchItemsValue, [key]: val } })}/>
</WeaFormItem>
@ -122,6 +121,8 @@ export default class UserSure extends React.Component {
childFrameObj.contentWindow.postMessage(JSON.stringify(payload), "*"); //window.postMessage
} else if (id === "DELETE") {
this.handleDeleteItem(record);
} else if (id === "COSTCENTER") {
window.open(record.url, "_blank");
} else if (id === "BATCHDELETE") {
this.onSelectChange(record);
} else if (id === "PAGEINFO") {
@ -144,7 +145,7 @@ export default class UserSure extends React.Component {
const payload = {
type: "PC",
listType: "MA",
url: this.state.selectedKey === '1'?"/api/bs/hrmsalary/salaryacct/reducedemployee/list":"/api/bs/hrmsalary/salaryacct/addedemployee/list",
url: this.state.selectedKey === "1" ? "/api/bs/hrmsalary/salaryacct/reducedemployee/list" : "/api/bs/hrmsalary/salaryacct/addedemployee/list",
queryParams: {
salaryAcctRecordId,
employeeName: this.state.userListSearchValue,
@ -223,7 +224,7 @@ export default class UserSure extends React.Component {
salaryAcctRecordId,
employeeName: this.state.userListSearchValue,
...this.pageInfo,
current: 1,
current: 1
}
};
childFrameObj.contentWindow.postMessage(JSON.stringify(payload), "*");
@ -253,7 +254,7 @@ export default class UserSure extends React.Component {
queryParams: {
salaryAcctRecordId,
employeeName: this.state.userListSearchValue,
...this.pageInfo,
...this.pageInfo
}
};
childFrameObj.contentWindow.postMessage(JSON.stringify(payload), "*");
@ -570,6 +571,7 @@ export default class UserSure extends React.Component {
<div style={{ width: "100%", height: "calc(100vh - 261px)" }}>
<iframe
style={{ border: 0, width: "100%", height: "100%" }}
// src="http://localhost:7607/#/atdTable"
src="/spa/hrmSalary/hrmSalaryCalculateDetail/index.html#/atdTable"
id="atdTable"
/>

View File

@ -0,0 +1,106 @@
/*
* Author: 黎永顺
* name: 回算薪资项目表格数据
* Description:
* Date: 2022/12/13
*/
import React, { Component } from "react";
import { WeaTable } from "ecCom";
import { inject, observer } from "mobx-react";
import LedgerBackCalcEditSlide from "./ledgerBackCalcEditSlide";
@inject("taxAgentStore")
@observer
class LedgerBackCalculatedSalaryItemTable extends Component {
constructor(props) {
super(props);
this.state = {
backCalcEditSlide: {
visible: false,
title: "编辑薪资项目",
id: "",
salaryItemId: "",
backCalcType: ""
}
};
}
handleEditBackCalc = (record) => {
const { id, salaryItemId, backCalcType } = record;
const { backCalcEditSlide } = this.state;
this.setState({
backCalcEditSlide: {
...backCalcEditSlide,
visible: true,
id,
salaryItemId,
backCalcType
}
});
};
handleClose = (isRefresh = false) => {
const { backCalcEditSlide } = this.state;
const { onRefresh } = this.props;
this.setState({
backCalcEditSlide: {
...backCalcEditSlide,
visible: false,
id: "",
salaryItemId: "",
backCalcType: ""
}
}, () => {
isRefresh && onRefresh();
});
};
render() {
const { backCalcEditSlide } = this.state;
const { taxAgentStore: { showOperateBtn }, dataSource, editId, saveSalarySobId, key } = this.props;
const columns = [
{
dataIndex: "name",
title: "薪资项目",
render: (text) => {
return <span className="tdEllipsis" title={text}>{text}</span>;
}
},
{
dataIndex: "formulaContent",
title: "核算公式",
render: (text, record) => {
return <span className="tdEllipsis" title={text}>{text}</span>;
}
},
{
dataIndex: "",
title: "操作",
width: 80,
render: (text, record, index) => {
const { canEdit } = record;
return (showOperateBtn && canEdit) ?
<a href="javascript: void(0);" onClick={() => this.handleEditBackCalc(record)}>编辑</a> :
<span></span>;
}
}
];
return (
<div>
<WeaTable
rowKey="id"
dataSource={dataSource}
columns={columns}
pagination={false}
/>
<LedgerBackCalcEditSlide
{...backCalcEditSlide}
editId={editId || saveSalarySobId}
showOperateBtn={showOperateBtn}
onCancle={this.handleClose}
/>
</div>
);
}
}
export default LedgerBackCalculatedSalaryItemTable;

View File

@ -0,0 +1,79 @@
/*
* Author: 黎永顺
* name: 复制账套
* Description:
* Date: 2022/12/8
*/
import React, { Component } from "react";
import { inject, observer } from "mobx-react";
import { categoryConditions } from "../config";
import { WeaDialog } from "ecCom";
import { Button } from "antd";
import { getSearchs } from "../../../util";
@inject("ledgerStore")
@observer
class CategoryAddModal extends Component {
constructor(props) {
super(props);
this.state = {
loading: false
};
}
componentDidMount() {
this.getFormFields();
}
componentWillReceiveProps(nextProps, nextContext) {
if (nextProps.visible !== this.props.visible && nextProps.visible) {
const { ledgerStore, name = "" } = nextProps;
const { categoryForm: form } = ledgerStore;
form.updateFields({
name: { value: name }
});
}
}
getFormFields = () => {
const { ledgerStore } = this.props;
const { categoryForm: form } = ledgerStore;
form.initFormFields(categoryConditions);
};
handleSubmit = () => {
const { ledgerStore, id, onSaveCategory, onCancel } = this.props;
const { categoryForm: form } = ledgerStore;
form.validateForm().then(f => {
if (f.isValid) {
const payload = form.getFormParams();
onSaveCategory({ ...payload, id });
onCancel();
} else {
f.showErrors();
}
});
};
render() {
const { onCancel, ledgerStore, ...extra } = this.props;
const { loading } = this.state;
const { categoryForm: form } = ledgerStore;
const buttons = [
<Button type="primary" onClick={this.handleSubmit} loading={loading}>保存</Button>,
<Button type="ghost" onClick={onCancel}> 取消 </Button>
];
return (
<WeaDialog
{...extra}
style={{ width: 600 }}
buttons={buttons}
onCancel={onCancel}
>
{getSearchs(form, categoryConditions, 1)}
</WeaDialog>
);
}
}
export default CategoryAddModal;

View File

@ -0,0 +1,111 @@
/*
* Author: 黎永顺
* name: 复制账套
* Description:
* Date: 2022/12/8
*/
import React, { Component } from "react";
import { inject, observer } from "mobx-react";
import { copyConditions } from "../config";
import { duplicateLedger } from "../../../apis/ledger";
import { WeaDialog } from "ecCom";
import { Button, message } from "antd";
import { getSearchs } from "../../../util";
import "./index.less";
@inject("ledgerStore", "taxAgentStore")
@observer
class CopyLedgerModal extends Component {
constructor(props) {
super(props);
this.state = {
loading: false
};
}
componentDidMount() {
this.getTaxAgentSelectListAsAdmin();
}
componentWillReceiveProps(nextProps, nextContext) {
if (nextProps.visible !== this.props.visible && nextProps.visible) {
const { ledgerStore, name, taxAgentId } = nextProps;
const { copyForm: form } = ledgerStore;
form.updateFields({
name: { value: name },
taxAgentId: { value: taxAgentId.toString() }
});
}
}
getTaxAgentSelectListAsAdmin = () => {
const { taxAgentStore, ledgerStore } = this.props;
const { copyForm: form } = ledgerStore;
const { getTaxAgentSelectListAsAdmin } = taxAgentStore;
getTaxAgentSelectListAsAdmin().then(({ status, data }) => {
if (status) {
const conditions = _.map(copyConditions, it => {
it.items = _.map(it.items, child => {
if (child.domkey[0] === "taxAgentId") {
return {
...child,
options: _.map(data, it => ({ key: it.id, showname: it.content }))
};
} else {
return { ...child };
}
});
return { ...it };
});
form.initFormFields(conditions);
}
});
};
handleSubmit = () => {
const { ledgerStore, id, onRefreshList, onCancel } = this.props;
const { copyForm: form } = ledgerStore;
form.validateForm().then(f => {
if (f.isValid) {
const payload = { id, ...form.getFormParams() };
this.setState({ loading: true });
duplicateLedger(payload).then(({ status, errormsg }) => {
this.setState({ loading: false });
if (status) {
message.success(errormsg || "复制成功");
onRefreshList();
onCancel();
} else {
message.error(errormsg || "复制失败");
}
});
} else {
f.showErrors();
}
});
};
render() {
const { onCancel, ledgerStore, ...extra } = this.props;
const { loading } = this.state;
const { copyForm: form } = ledgerStore;
const buttons = [
<Button type="primary" onClick={this.handleSubmit} loading={loading}>保存</Button>,
<Button type="ghost" onClick={onCancel}> 取消 </Button>
];
return (
<WeaDialog
{...extra}
initLoadCss
className="copyWrapper"
style={{ width: 600 }}
buttons={buttons}
onCancel={onCancel}
>
{getSearchs(form, copyConditions, 1)}
</WeaDialog>
);
}
}
export default CopyLedgerModal;

View File

@ -0,0 +1,210 @@
.ledgerWrapper {
.optWrapper {
display: flex;
align-items: center;
i {
cursor: pointer;
}
}
}
.ledgerSlideContent {
}
.copyWrapper {
.wea-select {
.ant-select {
width: 100% !important;
.ant-select-selection {
border-radius: 0 !important;
height: 30px !important;
}
}
}
}
//薪资账套基本设置信息
.baseSettingWrapper {
padding: 12px 12px 12px 20px;
.baseSettingLeft {
border: 1px solid #ebedf0;
padding: 0 !important;
border-bottom: none;
.wea-form-item {
padding: 4px 10px;
border-bottom: 1px solid #ebedf0;
.desc {
line-height: 32px;
}
}
}
.baseSettingRight {
width: 100%;
background: #fff;
border: 1px solid #ebedf0;
.title {
border-bottom: 1px solid #ebedf0;
background: #f7fbfe;
width: 100%;
padding: 0 12px;
line-height: 40px;
font-size: 14px;
}
.descContent {
color: #999;
width: 100%;
padding: 0 12px;
line-height: 24px;
.descTitle {
font-size: 14px;
color: #333;
line-height: 26px;
}
}
.notice {
color: #ff4d4f;
}
}
}
//调薪计薪规则弹框
.adjustRuleModalWrapper {
.titleTipWrapper {
display: flex;
align-items: center;
.title {
margin-right: 4px;
}
}
.adjustRuleDetailWrapper {
display: flex;
flex-direction: column;
.adjustSalaryFlex {
display: flex;
align-items: center;
margin-bottom: 10px;
}
}
.wea-select, .ant-select-selection, .ant-select {
width: 100%;
}
.wea-select {
display: inline-block;
position: relative;
}
.ant-select-selection {
height: 30px;
border-radius: 0;
}
}
// 回算薪资项目
.ledgerBackCalculatedSalaryItemWrapper {
.titleWrapper {
display: flex;
align-items: center;
& > span {
margin-right: 8px;
}
}
}
//回算薪资项目编辑弹框
.backCalcSlideWrapper {
.backCalcSlideCol {
border: 1px solid #ebedf0;
border-bottom: none;
margin: 10px;
.wea-form-item {
padding: 4px 10px;
border-bottom: 1px solid #ebedf0;
}
}
.textareaBox {
position: relative;
z-index: 1;
& > .wea-textarea-normal {
z-index: -11;
}
}
}
//薪资项目
.ledgerSalaryItemWrapper {
.userInfoWrapper {
margin-top: 10px;
margin-bottom: 10px;
padding: 10px;
border: 1px solid #ebedf0;
border-radius: 5px;
display: flex;
align-items: center;
.wea-sortable-grid-item {
display: inline-block;
border: none;
padding: 0;
}
}
.categroyListWrapper {
.titleNormalWrapper {
display: flex;
justify-content: space-between;
align-items: center;
.titleWrapper, .titleBtnWrapper{
display: flex;
align-items: center;
width: inherit;
}
.titleWrapper{
i{
font-size: 16px;
color: #333;
margin-left: 8px;
}
}
.titleBtnWrapper{
.wea-button-icon{
margin-left: 12px;
}
}
}
}
.titleWrapper {
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
.titleLeft {
display: flex;
align-items: center;
& > span {
margin-right: 8px;
}
}
}
}

View File

@ -0,0 +1,183 @@
/*
* Author: 黎永顺
* name: 新增调薪计薪规
* Description:
* Date: 2022/12/12
*/
import React, { Component } from "react";
import { WeaDialog, WeaFormItem, WeaHelpfulTip, WeaSearchGroup, WeaSelect } from "ecCom";
import { Button, Modal, Radio } from "antd";
import { monthDays } from "../config";
import { listSalarySobItem } from "../../../apis/ledger";
import "./index.less";
class LedgerAdjustRuleAddModal extends Component {
constructor(props) {
super(props);
this.state = {
beforeAdjustmentType: 2,
afterAdjustmentType: 1,
salaryItemId: "",
salaryItemName: "",
dayOfMonth: "1",
salaryItemOptions: []
};
}
componentWillReceiveProps(nextProps, nextContext) {
if (nextProps.visible !== this.props.visible && nextProps.salarySobId) this.listSalarySobItem(nextProps.salarySobId);
}
listSalarySobItem = (salarySobId) => {
const { salaryRuleItemsList } = this.props;
const payload = {
excludeSalaryItemIds: _.map(salaryRuleItemsList, item => item.salaryItemId),
salarySobId
};
listSalarySobItem(payload).then(({ status, data }) => {
if (status) {
this.setState({
salaryItemOptions: _.map(data, it => ({ key: it.salaryItemId.toString(), showname: it.salaryItemName }))
});
}
});
};
handleSave = () => {
const { salaryRuleItemsList, onSave } = this.props;
const { salaryItemOptions, ...extraItems } = this.state;
if (_.isEmpty(extraItems.salaryItemId)) {
Modal.warning({
title: "信息确认",
content: "必要信息不完整,红色*为必填项!"
});
return;
}
const items = {
...extraItems,
salaryItemName: this.state.salaryItemName
};
this.handleReset();
onSave([...salaryRuleItemsList, items]);
};
handleReset = () => {
this.setState({
beforeAdjustmentType: 2,
afterAdjustmentType: 1,
salaryItemId: "",
salaryItemName: "",
dayOfMonth: "1",
salaryItemOptions: []
}, () => {
const { onCancel } = this.props;
onCancel();
});
};
render() {
const {
salaryItemId,
salaryItemOptions,
dayOfMonth,
beforeAdjustmentType,
afterAdjustmentType
} = this.state;
const { title, visible } = this.props;
const buttons = [<Button type="primary" onClick={this.handleSave}>保存</Button>];
return (
<WeaDialog
initLoadCss
className="adjustRuleModalWrapper"
title={title}
visible={visible}
style={{ width: 750 }}
buttons={buttons}
onCancel={this.handleReset}
>
<WeaSearchGroup col={1} needTigger title="" showGroup center>
<WeaFormItem label="薪资项目" labelCol={{ span: 4 }} wrapperCol={{ span: 20 }}
style={{ tableLayout: "fixed" }}>
<WeaSelect
multiple
viewAttr={3}
style={{ width: "100%" }}
options={salaryItemOptions}
value={salaryItemId}
onChange={(salaryItemId, salaryItemName) => this.setState({ salaryItemId, salaryItemName })}
/>
</WeaFormItem>
<WeaFormItem label={<AdjustTitle/>} labelCol={{ span: 4 }} wrapperCol={{ span: 20 }} colon={false}>
<div className="adjustRuleDetailWrapper">
<div className="adjustSalaryFlex">
<span>如果调薪生效日期在</span>
<WeaSelect
viewAttr={3}
style={{ width: 60, margin: "0 6px" }}
value={dayOfMonth}
options={monthDays}
onChange={(dayOfMonth) => this.setState({ dayOfMonth })}
/>
<span>之前</span>
</div>
<div className="adjustSalaryFlex">
<span>计薪规则为</span>
<Radio.Group onChange={(e) => this.setState({ beforeAdjustmentType: e.target.value })}
value={beforeAdjustmentType}>
<Radio value={2}>取调整后薪资</Radio>
<Radio value={4}>分段计薪<WeaHelpfulTip
style={{ marginLeft: "10px" }}
width={200}
title="=调整前薪资/当月自然日天数*调整前自然日天数+调整后薪资/当月自然日天数*调整后自然日天数"
placement="topLeft"
/></Radio>
<Radio value={3}>取平均<WeaHelpfulTip
style={{ marginLeft: "10px" }}
width={200}
title="=(调整前薪资+调整后薪资)/2"
placement="topLeft"
/>
</Radio>
</Radio.Group>
</div>
<div style={{ marginBottom: 10 }}>否则调薪生效日期在{dayOfMonth}号之后</div>
<div className="adjustSalaryFlex">
<span>计薪规则为</span>
<Radio.Group onChange={(e) => this.setState({ afterAdjustmentType: e.target.value })}
value={afterAdjustmentType}>
<Radio value={1}>取调整前薪资</Radio>
<Radio value={4}>分段计薪<WeaHelpfulTip
style={{ marginLeft: "10px" }}
width={200}
title="=调整前薪资/当月自然日天数*调整前自然日天数+调整后薪资/当月自然日天数*调整后自然日天数"
placement="topLeft"
/></Radio>
<Radio value={3}>取平均<WeaHelpfulTip
style={{ marginLeft: "10px" }}
width={200}
title="=(调整前薪资+调整后薪资)/2"
placement="topLeft"
/>
</Radio>
</Radio.Group>
</div>
</div>
</WeaFormItem>
</WeaSearchGroup>
</WeaDialog>
);
}
}
export default LedgerAdjustRuleAddModal;
const AdjustTitle = () => {
return <div className="titleTipWrapper">
<span className="title">计薪规则</span>
<WeaHelpfulTip
width={200}
title="该规则适用于一个薪资核算周期内只调整一次薪资或个税扣缴义务人的情况,其他情况默认按照分段计薪规则核算"
placement="topLeft"
/>
<span className="title">:</span>
</div>;
};

View File

@ -0,0 +1,160 @@
/*
* Author: 黎永顺
* name: 薪资账套关联人员
* Description:
* Date: 2022/12/12
*/
import React, { Component } from "react";
import { inject, observer } from "mobx-react";
import { message, Modal } from "antd";
import { WeaButtonIcon, WeaInputSearch, WeaTab } from "ecCom";
import PersonalScopeTable from "../../../components/PersonalScopeTable";
import PersonalScopeModal from "../../../components/PersonalScopeModal";
import {
deleteLedgerPersonRange,
getLedgerPersonRangeExclude,
getLedgerPersonRangeInclude,
saveLedgerPersonRange
} from "../../../apis/ledger";
const APIFox = {
listInclude: getLedgerPersonRangeInclude,
listExclude: getLedgerPersonRangeExclude
};
const APISaveFox = {
save: saveLedgerPersonRange
};
@inject("taxAgentStore")
@observer
class LedgerAssociatedPersonnel extends Component {
constructor(props) {
super(props);
this.state = {
searchValue: "",
selectedKey: "listInclude",
rowKeys: [],
personalAddModal: {
visible: false,
title: "关联人员",
includeType: ""
}
};
}
/*
* Author: 黎永顺
* Description: 删除人员范围
* Params:
* Date: 2022/11/30
*/
taxAgentRangeDelete = () => {
Modal.confirm({
title: "信息确认",
content: "确认要删除吗?",
onOk: () => {
deleteLedgerPersonRange(this.state.rowKeys).then(({ status, errormsg }) => {
if (status) {
message.success("删除成功");
this.setState({ rowKeys: [] }, () => {
this.personalScopeTableRef.clearRowkeys();
});
} else {
message.error(errormsg || "删除失败");
}
});
}
});
};
/*
* Author: 黎永顺
* Description:新增人员范围
* Params:
* Date: 2022/11/30
*/
handleAddPersonal = () => {
const { personalAddModal, selectedKey } = this.state;
this.setState({
personalAddModal: {
...personalAddModal,
visible: true,
includeType: selectedKey === "listInclude" ? 1 : 0
}
});
};
render() {
const { selectedKey, searchValue, rowKeys, personalAddModal } = this.state;
const { taxAgentStore: { showOperateBtn }, editId, saveSalarySobId } = this.props;
const topTab = [
{
title: "关联人员范围",
viewcondition: "listInclude"
},
{
title: "从范围中排除",
viewcondition: "listExclude"
}
];
const btns = showOperateBtn ? [
<WeaButtonIcon
buttonType="del"
type="primary"
disabled={_.isEmpty(rowKeys)}
onClick={this.taxAgentRangeDelete}
/>,
<WeaButtonIcon buttonType="add" type="primary" onClick={this.handleAddPersonal}/>,
<WeaInputSearch
style={{ width: 220 }}
value={searchValue}
onChange={searchValue => this.setState({ searchValue })}
placeholder="请输入对象"
onSearch={() => this.personalScopeTableRef.getPersonalScopeList()}
/>
] : [<WeaInputSearch
style={{ width: 220 }}
value={searchValue}
onChange={searchValue => this.setState({ searchValue })}
placeholder="请输入对象"
onSearch={() => this.personalScopeTableRef.getPersonalScopeList()}
/>];
return (
<div>
<WeaTab
datas={topTab}
keyParam="viewcondition" //主键
selectedKey={selectedKey}
buttons={btns}
onChange={selectedKey => this.setState({ selectedKey })}
/>
<PersonalScopeTable
ref={dom => this.personalScopeTableRef = dom}
searchKeyVal={{ key: "salarySobId", value: editId || saveSalarySobId }}
APIFox={APIFox}
tabActive={selectedKey}
searchValue={searchValue}
onChangeSelectKey={rowKeys => this.setState({ rowKeys })}
/>
{/*新增人员范围*/}
<PersonalScopeModal
{...personalAddModal}
APISaveFox={APISaveFox}
isTaxgent={false}
saveKeyVal={{ key: "salarySobId", value: editId || saveSalarySobId }}
onSuccess={() => this.personalScopeTableRef.getPersonalScopeList()}
onCancel={() =>
this.setState({
personalAddModal: {
...personalAddModal,
visible: false,
includeType: ""
}
})
}
/>
</div>
);
}
}
export default LedgerAssociatedPersonnel;

View File

@ -0,0 +1,204 @@
/*
* Author: 黎永顺
* name: 编辑回算薪资项目
* Description:
* Date: 2022/12/13
*/
import React, { Component } from "react";
import { WeaFormItem, WeaInput, WeaSelect, WeaSlideModal, WeaTextarea } from "ecCom";
import { Col, message, Modal, Row } from "antd";
import SlideModalTitle from "../../../components/slideModalTitle";
import { getBackitemForm, salarysobBackitemSave } from "../../../apis/ledger";
import { fieldType, keepDecimalPlaces, roundingRules, valueTaking } from "../config";
import FormalFormModal from "../../salaryItem/formalFormModal";
import "./index.less";
class LedgerBackCalcEditSlide extends Component {
constructor(props) {
super(props);
this.state = {
loading: false,
dataType: "",
formulaContent: "",
pattern: "",
roundingMode: "",
valueType: "",
salaryItem: [],
formulaId: "",
backCalcEditFormulModal: {
visible: false,
valueType: "",
dataType: "",
backCalcType: "",
formulaId: ""
}
};
}
componentWillReceiveProps(nextProps, nextContext) {
if (nextProps.visible !== this.props.visible && nextProps.id) this.getBackitemForm(nextProps.id);
}
getBackitemForm = (id) => {
getBackitemForm({ id }).then(({ status, data }) => {
if (status) {
this.setState({ ...data });
}
});
};
handleChange = (type, value) => {
this.setState({
...this.state,
[type]: value
});
};
handleSaveBackCalcItems = () => {
const { salaryItem, loading, backCalcEditFormulModal, ...extra } = this.state;
const { salaryItemId, editId: salarySobId, onCancle } = this.props;
if (extra.valueType === "FORMULA" && _.isEmpty(extra.formulaContent)) {
Modal.warning({
title: "信息确认",
content: "必要信息不完整,红色*为必填项!"
});
return;
}
const payload = { ...extra, salarySobId, salaryItemId };
this.setState({ loading: true });
salarysobBackitemSave(payload).then(({ status, errormsg }) => {
this.setState({ loading: false });
if (status) {
message.success("保存成功");
onCancle(true);
} else {
message.error(errormsg || "保存失败");
}
}).catch(() => this.setState({ loading: false }));
};
handleEditFormnul = () => {
const { backCalcType } = this.props;
const { backCalcEditFormulModal, valueType, dataType, formulaId } = this.state;
this.setState({
backCalcEditFormulModal: {
...backCalcEditFormulModal,
visible: true,
valueType,
dataType: _.lowerCase(dataType),
backCalcType,
formulaId
}
});
};
handleCloseEditFormnul = () => {
const { backCalcEditFormulModal } = this.state;
this.setState({
backCalcEditFormulModal: {
...backCalcEditFormulModal,
visible: false,
valueType: "",
dataType: "",
backCalcType: "",
formulaId: ""
}
});
};
render() {
const { title, visible, showOperateBtn, onCancle } = this.props;
const {
valueType,
dataType,
roundingMode,
pattern,
salaryItem = [],
loading,
formulaContent,
backCalcEditFormulModal
} = this.state;
const salaryItemName = salaryItem[0] ? salaryItem[0].name : "";
return (
<WeaSlideModal
className="backCalcSlideWrapper"
visible={visible}
top={0}
width={100}
height={100}
direction="right"
measure="%"
title={
<SlideModalTitle
subtitle={title}
tabs={[]}
loading={loading}
showOperateBtn={showOperateBtn}
editable={true}
onSave={this.handleSaveBackCalcItems}
/>
}
content={
<div className="backCalcSlideContent">
<Row>
<Col span={16} className="backCalcSlideCol">
<WeaFormItem label="薪资项目" labelCol={{ span: 3 }} wrapperCol={{ span: 12 }}>
<WeaInput value={salaryItemName} viewAttr={1}/>
</WeaFormItem>
<WeaFormItem label="字段类型" labelCol={{ span: 3 }} wrapperCol={{ span: 12 }}>
<WeaSelect options={fieldType} value={dataType} viewAttr={1}/>
</WeaFormItem>
<Row gutter={20}>
<Col span={12}>
<WeaFormItem label="舍入规则" labelCol={{ span: 6 }} wrapperCol={{ span: 12 }}>
<WeaSelect
options={roundingRules} value={roundingMode} viewAttr={3}
onChange={(v) => this.handleChange("roundingMode", v)}
/>
</WeaFormItem>
</Col>
<Col span={12}>
<WeaFormItem label="保留小数位" labelCol={{ span: 6 }} wrapperCol={{ span: 12 }}>
<WeaSelect
options={keepDecimalPlaces} value={pattern} viewAttr={3}
onChange={(v) => this.handleChange("pattern", v)}
/>
</WeaFormItem>
</Col>
</Row>
<WeaFormItem label="取值方式" labelCol={{ span: 3 }} wrapperCol={{ span: 12 }}>
<WeaSelect
options={valueTaking} value={valueType} detailtype={3}
viewAttr={3}
onChange={(v) => this.handleChange("valueType", v)}
/>
</WeaFormItem>
{
valueType === "FORMULA" &&
<WeaFormItem label="公式内容" labelCol={{ span: 3 }} wrapperCol={{ span: 12 }}>
<div className="textareaBox" onClick={this.handleEditFormnul}>
<WeaTextarea viewAttr={3} value={formulaContent}/>
</div>
{/*公式弹框*/}
{
backCalcEditFormulModal.visible &&
<FormalFormModal
{...backCalcEditFormulModal}
formulaContent={formulaContent}
onSaveFormal={data => this.setState({
...this.state,
formulaId: data.id,
formulaContent: data.formula
})}
onCancel={this.handleCloseEditFormnul}
/>
}
</WeaFormItem>
}
</Col>
</Row>
</div>
}
onClose={onCancle}
/>
);
}
}
export default LedgerBackCalcEditSlide;

View File

@ -0,0 +1,104 @@
/*
* Author: 黎永顺
* name: 回算薪资项目
* Description:
* Date: 2022/12/13
*/
import React, { Component } from "react";
import { WeaHelpfulTip, WeaSearchGroup } from "ecCom";
import LedgerBackCalculatedSalaryItemTable from "./LedgerBackCalculatedSalaryItemTable";
import { getAggregate } from "../../../apis/ledger";
import "./index.less";
class LedgerBackCalculatedSalaryItem extends Component {
constructor(props) {
super(props);
this.state = {
backCalcItems: [
{
key: "issuedItems",
label: "已发项目设置",
dataSource: [],
helpContent: [
"核算时,已发项目的公式中各项目值均取该项目在该账套核算中的最后一次核算值;",
"已发项目的公式设置,只可在【取最后一次核算值的项目】中选择;"
]
},
{
key: "reissueItems",
label: "补发项目设置",
dataSource: [],
helpContent: [
"系统内置补发项目【补发薪资合计】,可新增其他的项目,如【补发备注】等;",
"公式取值为当次回算的核算值。"
]
}
]
};
}
componentDidMount() {
this.getAggregate();
}
getAggregate = () => {
const { editId: salarySobId, saveSalarySobId } = this.props;
const { backCalcItems } = this.state;
getAggregate({ salarySobId: salarySobId || saveSalarySobId }).then(({ status, data }) => {
if (status) {
this.setState({
backCalcItems: _.map(backCalcItems, item => {
const { key } = item;
return {
...item,
dataSource: data[key]
};
})
});
}
});
};
render() {
const { backCalcItems } = this.state;
return (
<div className="ledgerBackCalculatedSalaryItemWrapper">
{
_.map(backCalcItems, item => {
const { key, label, helpContent, dataSource } = item;
return (
<WeaSearchGroup
key={key}
needTigger
title={
<TitleComp title={label} helpContent={helpContent}/>
}
showGroup
>
<LedgerBackCalculatedSalaryItemTable
{...this.props} dataSource={dataSource}
key={key} onRefresh={this.getAggregate}
/>
</WeaSearchGroup>);
})
}
</div>
);
}
}
export default LedgerBackCalculatedSalaryItem;
const TitleComp = (props) => {
const helpContent = _.map(props.helpContent, (it, idx) => {
return <div>{`${idx + 1}${it}`}</div>;
});
return <div className="titleWrapper">
<span>{props.title}</span>
<WeaHelpfulTip
width={300}
title={helpContent}
placement="topLeft"
/>
</div>;
};

View File

@ -0,0 +1,312 @@
/*
* Author: 黎永顺
* name: 薪资账套基本设置
* Description:
* Date: 2022/12/9
*/
import React, { Component } from "react";
import { WeaCheckbox, WeaFormItem, WeaHelpfulTip, WeaInput, WeaSelect, WeaTextarea } from "ecCom";
import { Col, Row } from "antd";
import { inject, observer } from "mobx-react";
import { baseSettingFormItem } from "../config";
import { getLedgerBasicForm } from "../../../apis/ledger";
import { getAddMonthYearMonth, getCurrentYearMonth, getSubtractMonthYearMonth } from "../../../util/date";
import moment from "moment";
import "./index.less";
@inject("taxAgentStore")
@observer
class LedgerBaseSetting extends Component {
constructor(props) {
super(props);
this.state = {
baseForm: baseSettingFormItem,
settingBaseInfo: {
name: "",
taxAgentId: "",
taxableItems: "1",
salaryCycleType: "3",
salaryCycleFromDay: "1",
taxCycleType: "3",
attendCycleType: "3",
attendCycleFromDay: "1",
socialSecurityCycleType: "3",
description: "",
canEdit: false
}
};
}
componentDidMount() {
this.getTaxAgentSelectListAsAdmin();
if (this.props.visible && this.props.editId) {
this.getLedgerBasicForm(this.props.editId);
}
}
componentWillReceiveProps(nextProps, nextContext) {
if (nextProps.visible !== this.props.visible && nextProps.editId) {
this.getLedgerBasicForm(nextProps.editId);
}
if (nextProps.visible !== this.props.visible && !nextProps.editId) {
this.handleResetBaseInfo();
}
}
handleResetBaseInfo = () => {
this.setState({
settingBaseInfo: {
name: "",
taxAgentId: "",
taxableItems: "1",
salaryCycleType: "3",
salaryCycleFromDay: "1",
taxCycleType: "3",
attendCycleType: "3",
attendCycleFromDay: "1",
socialSecurityCycleType: "3",
description: "",
canEdit: "true"
}
});
};
getLedgerBasicForm = (id) => {
getLedgerBasicForm({ id }).then(({ status, data }) => {
if (status) {
const { basicForm } = data;
const { settingBaseInfo } = this.state;
let tmpV = {};
_.map(Object.keys(settingBaseInfo), key => {
tmpV[key] = !_.isNil(basicForm[key]) ? basicForm[key].toString() : "";
});
this.setState({
settingBaseInfo: {
...settingBaseInfo,
...tmpV
}
}, () => {
this.props.onSaveParams(this.state.settingBaseInfo);
});
}
});
};
getTaxAgentSelectListAsAdmin = () => {
const { taxAgentStore } = this.props;
const { getTaxAgentSelectListAsAdmin } = taxAgentStore;
getTaxAgentSelectListAsAdmin().then(({ status, data }) => {
if (status) {
const { baseForm } = this.state;
this.setState({
baseForm: _.map(baseForm, it => {
if (it.key === "taxAgentId") {
return {
...it,
options: _.map(data, it => ({ key: it.id, showname: it.content }))
};
}
return { ...it };
})
});
}
});
};
handleChangeField = (key, value) => {
const { onSaveParams } = this.props;
const { settingBaseInfo } = this.state;
this.setState({
settingBaseInfo: {
...settingBaseInfo,
[key]: value
}
}, () => {
onSaveParams(this.state.settingBaseInfo);
});
};
render() {
const { editId } = this.props;
const { baseForm, settingBaseInfo } = this.state;
const { canEdit, taxAgentId } = settingBaseInfo;
let taxAgentIdDisabled = false, taxableItemsDisabled = false;
return (
<div className="baseSettingWrapper">
<Row gutter={20}>
<Col span={18} className="baseSettingLeft">
{
_.map(baseForm, item => {
const { key, label, type, options = [], children = [] } = item;
taxAgentIdDisabled = key === "taxAgentId" && taxAgentId;
taxableItemsDisabled = key === "taxableItems" && editId;
return <WeaFormItem
key={key} label={label}
labelCol={{ span: 6 }} wrapperCol={{ span: 12 }}
>
{
type === "INPUT" ?
<WeaInput value={settingBaseInfo[key]} viewAttr={3} disabled={canEdit !== "true"}
onChange={(v) => this.handleChangeField(key, v)}/> :
type === "TEXTAREA" ?
<WeaTextarea value={settingBaseInfo[key]} disabled={canEdit !== "true"}
onChange={(v) => this.handleChangeField(key, v)}/> :
type === "CHECKBOX" ?
<React.Fragment>
<WeaCheckbox value={true} viewAttr={1}
content="【入职日期≤薪资周期止】且【离职日期≥薪资周期起】"/>
<WeaHelpfulTip width={200} title="提示:最后发薪日期为空,默认为无穷大" placement="topLeft"/>
</React.Fragment> :
type === "SELECT" ?
<WeaSelect value={settingBaseInfo[key]} options={options} viewAttr={3}
disabled={canEdit !== "true" || taxAgentIdDisabled || taxableItemsDisabled}
onChange={(v) => this.handleChangeField(key, v)}/> :
type === "CUSTOM" ?
<CustomSelect list={children} baseInfo={settingBaseInfo} inputStr={key}
onChange={(key, v) => this.handleChangeField(key, v)}/> : null
}
</WeaFormItem>;
})
}
</Col>
<Col span={6}><MonthCycleDesc {...settingBaseInfo}/></Col>
</Row>
</div>
);
}
}
export default LedgerBaseSetting;
const CustomSelect = (props) => {
const { list, baseInfo, onChange, inputStr } = props;
const { salaryCycleType, salaryCycleFromDay, attendCycleType, attendCycleFromDay, canEdit } = baseInfo;
const salaryCycleStrObj = initPeriodStr("inputStr", salaryCycleType, salaryCycleFromDay);
const attendCycleStrObj = initPeriodStr("inputStr", attendCycleType, attendCycleFromDay);
return <Row gutter={10} key={key}>
{
_.map(list, item => {
const { key, options = [] } = item;
return <Col span={6}>
<WeaSelect value={baseInfo[key]} options={options} viewAttr={3}
disabled={canEdit !== "true"}
onChange={(v) => onChange(key, v)}/>
</Col>;
})
}
<Col span={12}
className="desc">{inputStr === "salaryCycleStrObj" ? salaryCycleStrObj.inputStr : attendCycleStrObj.inputStr}</Col>
</Row>;
};
const MonthCycleDesc = (props) => {
const {
taxCycleType,
socialSecurityCycleType,
salaryCycleFromDay,
salaryCycleType,
attendCycleType,
attendCycleFromDay
} = props;
const salaryCycleStrObj = initPeriodStr("salaryCycleStr", salaryCycleType, salaryCycleFromDay);
const attendCycleStrObj = initPeriodStr("attendCycleStr", attendCycleType, attendCycleFromDay);
return <div className="baseSettingRight">
<div className="title">月份周期说明</div>
<div className="descContent">
<div>
薪资所属月是<span className="notice">{moment().format("YYYY-MM")}</span><span
className="notice">{moment().format("MM")}</span>
</div>
<div>根据您当前的选择相应的周期为</div>
<div className="descTitle">薪资周期</div>
<div>
<span className="notice">{getStartDate(salaryCycleType, salaryCycleFromDay)}</span>
<span className="notice">{salaryCycleStrObj.date}</span>
</div>
<div className="descTitle">税款所属期</div>
<div className="notice">{getMonth(taxCycleType)}</div>
<div className="descTitle">考勤取值周期</div>
<div>
<span className="notice">{getStartDate(attendCycleType, attendCycleFromDay)}</span>
<span className="notice">{attendCycleStrObj.date}</span>
</div>
<div className="descTitle">福利台账月份</div>
<div>引用<span className="notice">{getMonth(socialSecurityCycleType)}</span></div>
</div>
</div>;
};
// 获取开始日期
const getStartDate = (salaryCycleType, day) => {
day = Number(day);
return getMonth(salaryCycleType) + "-" + (day < 10 ? "0" + day : day);
};
const getMonth = (salaryCycleType) => {
switch (salaryCycleType) {
case "1": // 上上月
return getSubtractMonthYearMonth(2);
case "2": // 上月
return getSubtractMonthYearMonth(1);
case "3": // 本月
return getCurrentYearMonth();
case "4": // 下月
return getAddMonthYearMonth(1);
}
};
const initPeriodStr = (periodStrType, types, fromDay) => {
let str = "", tmpDate = null;
switch (types) {
case "1":
tmpDate = moment().subtract(2, "month");
const is_31H = moment(tmpDate, "YYYY-MM").daysInMonth() === 31;
if (fromDay == 1) {
tmpDate = moment().subtract(2, "month").endOf("month");
str = `至上上月最后一天`;
} else {
tmpDate = moment(new Date(`${moment(tmpDate).format("YYYY-MM")}-0${fromDay}`))
.add(is_31H ? 30 : 29, "days");
str = `至上月${moment(tmpDate).date()}`;
}
break;
case "2":
tmpDate = moment().subtract(1, "month");
const is_31 = moment(tmpDate, "YYYY-MM").daysInMonth() === 31;
if (fromDay == 1) {
tmpDate = moment().subtract(1, "month").endOf("month");
str = `至上月最后一天`;
} else {
tmpDate = moment(new Date(`${moment(tmpDate).format("YYYY-MM")}-0${fromDay}`))
.add(is_31 ? 30 : 29, "days");
str = `至本月${moment(tmpDate).date()}`;
}
break;
case "3":
tmpDate = moment().add(0, "month");
const is_31K = moment(tmpDate, "YYYY-MM").daysInMonth() === 31;
if (fromDay == 1) {
tmpDate = moment().endOf("month");
str = `至本月最后一天`;
} else {
tmpDate = moment(new Date(`${moment(tmpDate).format("YYYY-MM")}-0${fromDay}`))
.add(is_31K ? 30 : 29, "days");
str = `至下月${moment(tmpDate).date()}`;
}
break;
case "4":
tmpDate = moment().add(1, "month");
const is_31L = moment(tmpDate, "YYYY-MM").daysInMonth() === 31;
if (fromDay == 1) {
tmpDate = moment().add(1, "month").endOf("month");
str = `至下月最后一天`;
} else {
tmpDate = moment(new Date(`${moment(tmpDate).format("YYYY-MM")}-0${fromDay}`))
.add(is_31L ? 30 : 29, "days");
str = `至下下月${moment(tmpDate).date()}`;
}
break;
default:
break;
}
return {
[periodStrType]: str,
date: moment(tmpDate).format("YYYY-MM-DD")
};
};

View File

@ -0,0 +1,164 @@
/*
* Author: 黎永顺
* name: 调薪计薪规则
* Description:
* Date: 2022/12/12
*/
import React, { Component } from "react";
import { inject, observer } from "mobx-react";
import { WeaButtonIcon, WeaTab, WeaTable } from "ecCom";
import { Modal } from "antd";
import LedgerAdjustRuleAddModal from "./ledgerAdjustRuleAddModal";
import { listAdjustmentRule } from "../../../apis/ledger";
@inject("taxAgentStore")
@observer
class LedgerSalaryAdjustmentRules extends Component {
constructor(props) {
super(props);
this.state = {
dataSource: [],
adjustRuleAddModal: {
visible: false,
title: "调薪计薪规则项",
salarySobId: ""
}
};
}
componentDidMount() {
this.listAdjustmentRule();
}
listAdjustmentRule = () => {
const { editId: salarySobId, saveSalarySobId } = this.props;
listAdjustmentRule({ salarySobId: salarySobId || saveSalarySobId }).then(({ status, data }) => {
if (status) {
this.setState({
dataSource: data
}, () => {
const { onSaveParams } = this.props;
const { dataSource } = this.state;
onSaveParams(dataSource);
});
}
});
};
handleAddAdjustRule = () => {
const { adjustRuleAddModal } = this.state;
const { editId, saveSalarySobId } = this.props;
this.setState({
adjustRuleAddModal: {
...adjustRuleAddModal,
visible: true,
salarySobId: editId || saveSalarySobId
}
});
};
handleCloseModal = () => {
const { adjustRuleAddModal } = this.state;
this.setState({
adjustRuleAddModal: {
...adjustRuleAddModal,
visible: false,
salarySobId: ""
}
});
};
handleDelete = (index) => {
const { dataSource } = this.state;
Modal.confirm({
title: "信息确认",
content: "确认要删除吗?",
onOk: () => {
this.setState({
dataSource: _.filter(dataSource, (it, idx) => idx !== index)
}, () => {
const { onSaveParams } = this.props;
const { dataSource } = this.state;
onSaveParams(dataSource);
});
}
});
};
convertAdjustmentType = (index) => {
const nameList = {
1: "取调薪前薪资",
2: "取调薪后薪资",
3: "平均值",
4: "分段计薪"
};
return nameList[Number(index)];
};
render() {
const { taxAgentStore: { showOperateBtn }, editId, onSaveParams } = this.props;
const { adjustRuleAddModal } = this.state;
const { dataSource } = this.state;
const btns = showOperateBtn ? [
<WeaButtonIcon buttonType="add" type="primary" onClick={this.handleAddAdjustRule}/>
] : [];
const columns = [
{
title: "序号",
dataIndex: "index",
width: 60,
render: (text, record, index) => {
return index + 1;
}
},
{
dataIndex: "salaryItemName",
title: "薪资项目",
render: (text) => {
return <span className="tdEllipsis" title={text}>{text}</span>;
}
},
{
dataIndex: "salaryCalculationRules",
title: "计薪规则",
render: (text, record) => {
const salaryCalculationRules = `${record.dayOfMonth}号(含)之前调薪,${this.convertAdjustmentType(record.beforeAdjustmentType)}${record.dayOfMonth}号之后调薪,${this.convertAdjustmentType(record.afterAdjustmentType)}`;
return <span className="tdEllipsis" title={salaryCalculationRules}>{salaryCalculationRules}</span>;
}
},
{
dataIndex: "",
title: "操作",
width: 80,
render: (text, record, index) => {
return showOperateBtn ?
<a href="javascript: void(0);" onClick={() => this.handleDelete(index)}>删除</a> : <span></span>;
}
}
];
return (
<div>
<WeaTab datas={[]} keyParam="viewcondition" buttons={btns}/>
<WeaTable
rowKey="id"
dataSource={dataSource}
columns={columns}
pagination={false}
/>
<LedgerAdjustRuleAddModal
{...adjustRuleAddModal}
salaryRuleItemsList={dataSource}
onCancel={this.handleCloseModal}
onSave={(dataSource) => {
this.setState({ dataSource }, () => {
const { dataSource } = this.state;
const ruleParams = _.map(dataSource, it => {
const { salaryCalculationRules, ...params } = it;
return { ...params };
});
onSaveParams(ruleParams);
});
}}
/>
</div>
);
}
}
export default LedgerSalaryAdjustmentRules;

View File

@ -0,0 +1,328 @@
/*
* Author: 黎永顺
* name: 薪资项目
* Description:
* Date: 2022/12/13
*/
import React, { Component } from "react";
import LedgerSalaryItemBaseInfo from "./ledgerSalaryItemBaseInfo";
import LedgerSalaryItemNormal from "./ledgerSalaryItemNormal";
import LedgerSalaryItemPreviewModal from "./ledgerSalaryItemPreviewModal";
import { getLedgerItemForm } from "../../../apis/ledger";
import "./index.less";
class LedgerSalaryItem extends Component {
constructor(props) {
super(props);
this.state = {
previewVisible: false, //预览标识
empFields: [], //员工基本信息
itemGroups: [] //正常工资薪金所得项
};
}
componentDidMount() {
this.getLedgerItemForm();
}
/*
* Author: 黎永顺
* Description: 薪资项目以及员工基本信息查询
* Params:
* Date: 2022/12/14
*/
getLedgerItemForm = () => {
const { editId: salarySobId, saveSalarySobId } = this.props;
getLedgerItemForm({ salarySobId: salarySobId || saveSalarySobId }).then(({ status, data }) => {
if (status) {
const { empFields, itemGroups, items } = data;
const obj = {
id: itemGroups.length,
itemHide: null,
items,
name: "未分类",
salarySobId,
sortedIndex: itemGroups.length
};
this.setState({ empFields, itemGroups: [...itemGroups, obj] }, () => {
const { empFields, itemGroups } = this.state;
const { onSaveSalaryItem } = this.props;
onSaveSalaryItem(empFields, itemGroups);
});
}
});
};
/*
* Author: 黎永顺
* Description: 员工基本信息排序
* Params:
* Date: 2022/12/14
*/
handleChangeSortableList = (empFields) => {
this.setState({ empFields }, () => {
const { empFields, itemGroups } = this.state;
const { onSaveSalaryItem } = this.props;
onSaveSalaryItem(empFields, itemGroups);
});
};
/*
* Author: 黎永顺
* Description:编辑保存性子项目分类
* Params:
* Date: 2022/12/13
*/
handleSaveCateGory = (payload) => {
const { itemGroups } = this.state;
if (payload.id) {
this.setState({
itemGroups: _.map(itemGroups, it => {
if (it.id === payload.id) {
return { ...it, name: payload.name };
}
return { ...it };
})
});
} else {
const obj = {
id: itemGroups.length,
itemHide: null,
items: [],
name: payload.name
};
this.setState({
itemGroups: _.map([obj, ...itemGroups], (it, idx) => ({ ...it, sortedIndex: idx }))
}, () => {
const { empFields, itemGroups } = this.state;
const { onSaveSalaryItem } = this.props;
onSaveSalaryItem(empFields, itemGroups);
});
}
};
/*
* Author: 黎永顺
* Description: 删除分类
* Params:
* Date: 2022/12/14
*/
handleDeleteCategroy = (id) => {
const { itemGroups } = this.state;
this.setState({
itemGroups: _.filter(itemGroups, it => it.id !== id)
}, () => {
const { empFields, itemGroups } = this.state;
const { onSaveSalaryItem } = this.props;
onSaveSalaryItem(empFields, itemGroups);
});
};
/*
* Author: 黎永顺
* Description: 删除分类项下的列表数据
* Params:
* Date: 2022/12/14
*/
handleDeleteCategroyItems = (id, selectedRowKeys) => {
const { itemGroups } = this.state;
this.setState({
itemGroups: _.map(itemGroups, item => {
if (item.id === id) {
return {
...item,
items: _.filter(item.items, it => !selectedRowKeys.includes(it.id)),
selectedRowKeys: []
};
}
return { ...item };
})
}, () => {
const { empFields, itemGroups } = this.state;
const { onSaveSalaryItem } = this.props;
onSaveSalaryItem(empFields, itemGroups);
});
};
/*
* Author: 黎永顺
* Description: 修改信息项目分类的顺序-向上移动
* Params:
* Date: 2022/12/14
*/
handleUpgo = (index) => {
const { itemGroups } = this.state;
let newItemGroups = [...itemGroups];
if (index !== 0) {
newItemGroups[index] = newItemGroups.splice(index - 1, 1, newItemGroups[index])[0];
} else {
newItemGroups.push(newItemGroups.shift());
}
this.setState({
itemGroups: _.map(newItemGroups, (it, idx) => ({
...it,
sortedIndex: idx
}))
}, () => {
const { empFields, itemGroups } = this.state;
const { onSaveSalaryItem } = this.props;
onSaveSalaryItem(empFields, itemGroups);
});
};
/*
* Author: 黎永顺
* Description: 修改信息项目分类的顺序-向下移动
* Params:
* Date: 2022/12/14
*/
handleDowngo = (index) => {
const { itemGroups } = this.state;
let newItemGroups = [...itemGroups];
if (index !== newItemGroups.length - 1) {
newItemGroups[index] = newItemGroups.splice(index + 1, 1, newItemGroups[index])[0];
} else {
newItemGroups.unshift(newItemGroups.splice(index, 1)[0]);
}
this.setState({
itemGroups: _.map(newItemGroups, (it, idx) => ({
...it,
sortedIndex: idx
}))
}, () => {
const { empFields, itemGroups } = this.state;
const { onSaveSalaryItem } = this.props;
onSaveSalaryItem(empFields, itemGroups);
});
};
/*
* Author: 黎永顺
* Description: 移動分类下的列表数据\切换薪资分类-隐藏复选框
* Params:
* Date: 2022/12/14
*/
handleDropCategroyItem = (filed, data) => {
const { itemGroups } = this.state;
this.setState({
itemGroups: _.map(itemGroups, it => {
if (filed.id === it.id) {
return {
...it,
items: _.map(data, (child, childIndex) => {
return {
...child,
sortedIndex: childIndex
};
})
};
}
return { ...it };
})
}, () => {
const { empFields, itemGroups } = this.state;
const { onSaveSalaryItem } = this.props;
onSaveSalaryItem(empFields, itemGroups);
});
};
/*
* Author: 黎永顺
* Description: 薪资分类选中复选框
* Params:
* Date: 2022/12/14
*/
handleChangeSelectedRowKeys = (filed, data) => {
const { itemGroups } = this.state;
this.setState({
itemGroups: _.map(itemGroups, it => {
if (filed.id === it.id) {
return { ...it, selectedRowKeys: data };
}
return { ...it };
})
}, () => {
const { empFields, itemGroups } = this.state;
const { onSaveSalaryItem } = this.props;
onSaveSalaryItem(empFields, itemGroups);
});
};
/*
* Author: 黎永顺
* Description: 薪资项目-新增项
* Params:
* Date: 2022/12/14
*/
handleAddSalaryItems = (id, items) => {
const { itemGroups } = this.state;
this.setState({
itemGroups: _.map(itemGroups, it => {
if (id === it.id) {
return { ...it, items: [...it.items, ...items] };
}
return { ...it };
})
}, () => {
const { empFields, itemGroups } = this.state;
const { onSaveSalaryItem } = this.props;
onSaveSalaryItem(empFields, itemGroups);
});
};
/*
* Author: 黎永顺
* Description: 保存薪资项目公式
* Params:
* Date: 2022/12/14
*/
handleSaveFormnul = (id, items) => {
const { itemGroups } = this.state;
this.setState({
itemGroups: _.map(itemGroups, it => {
if (id === it.id) {
return { ...it, items };
}
return { ...it };
})
}, () => {
const { empFields, itemGroups } = this.state;
const { onSaveSalaryItem } = this.props;
onSaveSalaryItem(empFields, itemGroups);
});
};
/*
* Author: 黎永顺
* Description: 员工基本信息-预览
* Params:
* Date: 2022/12/14
*/
handlePreview = () => {
this.setState({ previewVisible: true });
};
render() {
const { empFields, itemGroups, previewVisible } = this.state;
return (
<div className="ledgerSalaryItemWrapper">
<LedgerSalaryItemBaseInfo
{...this.props} dataSource={empFields}
onChangeSortableList={this.handleChangeSortableList}
onPreview={this.handlePreview}
/>
<LedgerSalaryItemPreviewModal
visible={previewVisible}
empFields={empFields} itemGroups={itemGroups}
onCancel={() => this.setState({ previewVisible: false })}
/>
<LedgerSalaryItemNormal
ref={dom => this.ledgerSalaryItemNormalRef = dom}
{...this.props} dataSource={itemGroups}
onSaveCategory={this.handleSaveCateGory}
onDeleteCategroy={this.handleDeleteCategroy}
onDeleteCategroyItems={this.handleDeleteCategroyItems}
onUpgo={this.handleUpgo}
onDowngo={this.handleDowngo}
onDropCategoryItem={this.handleDropCategroyItem}
onHandleItemhide={this.handleDropCategroyItem}
onChangeSelectedRowKeys={this.handleChangeSelectedRowKeys}
onAddSalaryItems={this.handleAddSalaryItems}
onSaveFormnul={this.handleSaveFormnul}
/>
</div>
);
}
}
export default LedgerSalaryItem;

View File

@ -0,0 +1,151 @@
import React from "react";
import { Button, Switch } from "antd";
import { WeaDialog, WeaInputSearch, WeaTable } from "ecCom";
import { listSalaryItem } from "../../../apis/ledger";
export default class LedgerSalaryItemAddModal extends React.Component {
constructor(props) {
super(props);
this.state = {
loading: {
query: false
},
name: "",
selectedRowKeys: [],
dataSource: [],
columns: [],
pageInfo: {
current: 1,
pageSize: 10,
total: 0
}
};
}
componentWillReceiveProps(nextProps, nextContext) {
if (nextProps.visible !== this.props.visivle && nextProps.visible) {
this.setState({ selectedRowKeys: [] }, () => {
this.listSalaryItem();
});
}
}
listSalaryItem = () => {
const { itemGroups } = this.props;
const { name, pageInfo, loading } = this.state;
let excludeIds = [];
itemGroups.map(item => {
item.items && item.items.map(i => {
excludeIds.push(i.salaryItemId);
});
});
const payload = {
excludeIds,
name,
...pageInfo
};
this.setState({ loading: { ...loading, query: true } });
listSalaryItem(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,
columns
});
}
}).catch(() => {
this.setState({ loading: { ...loading, query: false } });
});
};
getSalaryItemAddColumns = () => {
const { columns } = this.state;
let newColumns = [];
newColumns = columns.map(column => {
let newColumn = column;
newColumn.render = (text, record, index) => { //前端元素转义
let valueSpan = record[newColumn.dataIndex + "span"] !== undefined ? record[newColumn.dataIndex + "span"] : record[newColumn.dataIndex];
switch (newColumn.dataIndex) {
case "useDefault":
case "useInEmployeeSalary":
return <Switch checked={text == 1}/>;
default:
return <div dangerouslySetInnerHTML={{ __html: valueSpan }}/>;
}
};
return newColumn;
});
return newColumns;
};
handleAdd = () => {
const { dataSource, selectedRowKeys } = this.state;
const { onAddSalaryItems, id, onCancel } = this.props;
let selectItems = [];
dataSource.map((item, index) => {
item = { ...item };
selectedRowKeys.map(key => {
if (item.id === key) {
item.salaryItemId = item.id;
item.key = item.id;
item.sortedIndex = index;
selectItems.push(item);
}
});
});
onCancel();
onAddSalaryItems(id, selectItems);
};
render() {
const { onCancel, visible } = this.props;
const { name, selectedRowKeys, pageInfo, dataSource, loading } = this.state;
const pagination = {
...pageInfo,
showTotal: total => `${total}`,
showQuickJumper: true,
pageSizeOptions: ["10", "20", "50", "100"],
onChange: current => {
this.setState({
pageInfo: { ...pageInfo, current }
}, () => {
this.listSalaryItem();
});
}
};
const rowSelection = {
selectedRowKeys,
onChange: (selectedRowKeys) => {
this.setState({ selectedRowKeys }, () => {
});
}
};
return (
<WeaDialog
visible={visible}
onCancel={onCancel}
title="添加薪资项目"
style={{ width: "80vw", height: 600 }}
buttons={[<Button type="primary" onClick={this.handleAdd} disabled={_.isEmpty(selectedRowKeys)}>添加</Button>]}
>
<div style={{ display: "flex", justifyContent: "flex-end", alignItems: "center", padding: 20 }}>
<WeaInputSearch
placeholder="请输入薪资项目名称"
value={name}
onChange={(name) => this.setState({ name })}
onSearch={() => this.listSalaryItem()}
/>
</div>
<WeaTable
rowKey="id"
rowSelection={rowSelection}
dataSource={dataSource}
pagination={pagination}
loading={loading.query}
columns={this.getSalaryItemAddColumns()}
/>
</WeaDialog>
);
}
}

View File

@ -0,0 +1,104 @@
/*
* Author: 黎永顺
* name: 薪资项目-员工基本信息
* Description:
* Date: 2022/12/13
*/
import React, { Component } from "react";
import { WeaHelpfulTip, WeaSearchGroup, WeaSelect, WeaSortable } from "ecCom";
import { Button, Icon } from "antd";
import { empFieldList } from "../../../apis/ledger";
class LedgerSalaryItemBaseInfo extends Component {
constructor(props) {
super(props);
this.state = {
empFieldListOptions: []
};
}
componentDidMount() {
this.empFieldList();
}
empFieldList = () => {
empFieldList().then(({ status, data }) => {
if (status) {
const dataFilter = _.filter(data, it => !["taxAgentName", "username", "departmentName"].includes(it.id));
this.setState({
empFieldListOptions: _.map(dataFilter, it => ({ key: it.id, showname: it.name }))
});
}
});
};
handleAddEmpList = (key, showname) => {
const { dataSource, onChangeSortableList } = this.props;
const obj = {
canDelete: true,
fieldId: key,
fieldName: showname,
id: dataSource.length,
salarySobId: "",
sortedIndex: dataSource.length
};
onChangeSortableList([...dataSource, obj]);
};
handleDeleteEmplist = (item) => {
const { dataSource, onChangeSortableList } = this.props;
onChangeSortableList(_.xorWith(dataSource, [item], _.isEqual));
};
render() {
const { dataSource, onChangeSortableList, onPreview } = this.props;
const { empFieldListOptions } = this.state;
return (
<WeaSearchGroup needTigger={false} showGroup title={<TitleComp onPreview={onPreview}/>}>
<div className="userInfoWrapper">
<WeaSortable
datas={dataSource}
draggableType="icon"
onChange={onChangeSortableList}
renderNodeItem={(item) => {
const { fieldName, canDelete } = item;
return <div style={{ display: "inline-block", paddingLeft: "10px", paddingRight: "10px" }}>
<span className="selectedItem" onBlur>{fieldName}</span>
{
canDelete &&
<Icon
style={{ cursor: "pointer", marginLeft: "5px", fontWeight: "600" }}
type="cross"
onClick={() => this.handleDeleteEmplist(item)}
/>
}
</div>;
}}
className="wea-sortable-grid-item"
/>
<WeaSelect
showSearch
options={empFieldListOptions}
style={{ width: 150 }}
onChange={this.handleAddEmpList}
/>
</div>
</WeaSearchGroup>
);
}
}
export default LedgerSalaryItemBaseInfo;
const TitleComp = (props) => {
const { onPreview } = props;
return <div className="titleWrapper">
<div className="titleLeft">
<span>员工基本信息</span>
<WeaHelpfulTip
width={300}
title="姓名、部门、个税扣缴义务人为必须项,不可删除"
placement="topLeft"
/>
</div>
<Button type="ghost" onClick={onPreview}>预览</Button>
</div>;
};

View File

@ -0,0 +1,252 @@
/*
* Author: 黎永顺
* name: 薪资项目-正常薪资所得
* Description:
* Date: 2022/12/13
*/
import React, { Component } from "react";
import { inject, observer } from "mobx-react";
import { WeaButtonIcon, WeaSearchGroup } from "ecCom";
import { Button, Modal } from "antd";
import CategoryAddModal from "./categoryAddModal";
import LedgerSalaryItemAddModal from "./ledgerSalaryItemAddModal";
import LedgerSalaryItemTable from "./ledgerSalaryItemTable";
import "./index.less";
import FormalFormModal from "../../salaryItem/formalFormModal";
@inject("ledgerStore")
@observer
class LedgerSalaryItemNormal extends Component {
constructor(props) {
super(props);
this.state = {
addCategoryItemsVisible: false,
categoryModal: {
visible: false,
title: "新增分类",
name: "",
id: ""
},
editFormulModal: {
visible: false,
formulaId: "",
valueType: "",
dataType: ""
},
//公式保存数据
formnulField: {},
formnulId: ""
};
}
componentWillUnmount() {
this.handleResetFormnul();
}
handleEditFormnul = (field, record) => {
const { valueType, formulaId, dateType: dataType, id } = record;
const { editFormulModal } = this.state;
this.setState({
editFormulModal: {
...editFormulModal,
visible: true,
valueType, formulaId, dataType
},
formnulField: field,
formnulId: id
});
};
handleSaveFormnul = (data) => {
const { onSaveFormnul } = this.props;
const { formnulField, formnulId } = this.state;
const tmpV = _.cloneDeep(formnulField.items);
const formnulData = _.map(tmpV, it => {
if (it.id === formnulId) {
return { ...it, formulaId: data.id, formulaContent: data.formula };
}
return { ...it };
});
onSaveFormnul(formnulField.id, formnulData);
};
handleAddCategory = (name = "", id = "") => {
const { categoryModal } = this.state;
this.setState({
categoryModal: {
...categoryModal,
visible: true,
name,
title: name ? "编辑分类" : "新增分类",
id
}
});
};
handleDeleteCategory = (id) => {
const { onDeleteCategroy } = this.props;
Modal.confirm({
title: "信息确认",
content: "确认要删除吗?",
onOk: () => {
onDeleteCategroy(id);
}
});
};
handleDeleteCategoryItems = (id, selectedRowKeys) => {
const { onDeleteCategroyItems } = this.props;
Modal.confirm({
title: "信息确认",
content: "确认删除所选薪资项目吗?删除后此项目下的进位规则/保留小数位/公式内容会一起被清除!",
onOk: () => {
onDeleteCategroyItems(id, selectedRowKeys);
}
});
};
handleUpgo = (sortedIndex) => {
const { onUpgo } = this.props;
onUpgo(sortedIndex);
};
handleDowngo = (sortedIndex) => {
const { onDowngo } = this.props;
onDowngo(sortedIndex);
};
handleClose = () => {
const { ledgerStore } = this.props;
const { categoryForm: form } = ledgerStore;
const { categoryModal } = this.state;
this.setState({
categoryModal: {
...categoryModal,
visible: false,
title: "新增分类",
name: "",
id: ""
}
}, () => form.resetForm());
};
handleCloseFormnul = () => {
const { editFormulModal } = this.state;
this.setState({
editFormulModal: {
...editFormulModal,
visible: false,
formulaId: "",
valueType: "", dataType: ""
}
});
};
handleResetFormnul = () => {
this.setState({
formnulField: {},
formnulId: ""
});
};
render() {
const {
dataSource,
onSaveCategory,
onDropCategoryItem,
onHandleItemhide,
onChangeSelectedRowKeys,
onAddSalaryItems
} = this.props;
const { categoryModal, addCategoryItemsVisible, editFormulModal } = this.state;
return (
<WeaSearchGroup needTigger={false} showGroup title={<TitleComp onAddCategory={this.handleAddCategory}/>}>
<div className="categroyListWrapper">
{
_.map(dataSource, field => {
const { items } = field;
return <WeaSearchGroup
needTigger showGroup
title={
<TitleNormalComp
{...field}
dataSourceLen={dataSource.length}
onEditCategory={this.handleAddCategory}
onDeleteCategory={this.handleDeleteCategory}
onDeleteCategoryItems={this.handleDeleteCategoryItems}
onAddCategoryItems={(id) => this.setState({ addCategoryItemsVisible: { visible: true, id } })}
onUpgo={this.handleUpgo}
onDowngo={this.handleDowngo}
/>
}
>
<LedgerSalaryItemTable
dataSource={items}
onDropCategoryItem={(data) => onDropCategoryItem(field, data)}
onHandleItemhide={(data) => onHandleItemhide(field, data)}
onChangeSelectedRowKeys={(data) => onChangeSelectedRowKeys(field, data)}
onEditFormnul={(data) => this.handleEditFormnul(field, data)}
/>
</WeaSearchGroup>;
})
}
<LedgerSalaryItemAddModal
{...addCategoryItemsVisible}
itemGroups={dataSource}
onCancel={() => this.setState({ addCategoryItemsVisible: { visible: false, id: "" } })}
onAddSalaryItems={onAddSalaryItems}
/>
<CategoryAddModal
{...categoryModal}
onSaveCategory={onSaveCategory}
onCancel={this.handleClose}
/>
{/*公式编辑*/}
{
editFormulModal.visible &&
<FormalFormModal
{...editFormulModal}
onSaveFormal={this.handleSaveFormnul}
onCancel={this.handleCloseFormnul}
/>
}
</div>
</WeaSearchGroup>
);
}
}
export default LedgerSalaryItemNormal;
const TitleNormalComp = (props) => {
const {
name, onEditCategory, onDeleteCategory,
sortedIndex, dataSourceLen, id, onUpgo,
onDowngo, selectedRowKeys = [], onDeleteCategoryItems,
onAddCategoryItems
} = props;
return <div className="titleNormalWrapper">
<div className="titleWrapper">
<span>{name}</span>
{
name !== "未分类" &&
<i className="icon-coms-edit" title="编辑" onClick={() => onEditCategory(name, id)}/>
}
{
name !== "未分类" &&
<i className="icon-coms-Delete" title="删除" onClick={() => onDeleteCategory(id)}/>
}
{
sortedIndex !== 0 &&
<i className="icon-coms-Reverse" title="向上移动" onClick={() => onUpgo(sortedIndex)}/>
}
{
sortedIndex !== dataSourceLen - 1 &&
<i className="icon-coms-positive-sequence" title="向下移动" onClick={() => onDowngo(sortedIndex)}/>
}
</div>
<div className="titleBtnWrapper">
<WeaButtonIcon buttonType="del" type="primary" disabled={_.isEmpty(selectedRowKeys)}
onClick={() => onDeleteCategoryItems(id, selectedRowKeys)}/>
<WeaButtonIcon buttonType="add" type="primary" onClick={() => onAddCategoryItems(id)}/>
</div>
</div>;
};
const TitleComp = (props) => {
const { onAddCategory } = props;
return <div className="titleWrapper">
<span>正常工资薪金所得</span>
<Button type="ghost" onClick={() => onAddCategory()}>新增分类</Button>
</div>;
};

View File

@ -0,0 +1,63 @@
import React from "react";
import { WeaDialog, WeaTable } from "ecCom";
export default class LedgerSalaryItemPreviewModal extends React.Component {
getColumns = () => {
const { empFields, itemGroups } = this.props;
let columns = [];
let length = 0;
empFields.map(item => {
columns.push({
title: item.fieldName,
key: item.fieldId,
width: 150
});
length++;
});
itemGroups.map(item => {
if (item.id !== "default") {
let columnItem = {
title: item.name,
children: item.items.map(i => {
return {
title: i.name,
key: i.id,
width: 150
};
length++;
})
};
columns.push(columnItem);
}
});
itemGroups.map(item => {
if (item.id === "default") {
item.items.map(i => {
columns.push({
title: i.name,
key: i.id,
width: 150
});
length++;
});
}
});
return { columns, length };
};
render() {
const { onCancel, visible } = this.props;
return (
<WeaDialog
visible={visible}
title="预览"
style={{ width: "80vw", height: 200 }}
onCancel={onCancel}
>
<WeaTable columns={this.getColumns().columns} dataSource={[]} scroll={{ x: this.getColumns().length * 150 }}/>
</WeaDialog>
);
}
}

View File

@ -0,0 +1,135 @@
/*
* Author: 黎永顺
* name: 薪资项目-列表数据
* Description:
* Date: 2022/12/13
*/
import React, { Component } from "react";
import { WeaCheckbox, WeaHelpfulTip, WeaTable } from "ecCom";
class LedgerSalaryItemTable extends Component {
constructor(props) {
super(props);
this.state = {
selectedRowKeys: []
};
}
/*
* Author: 黎永顺
* Description: 列表操作隐藏复选框
* Params:
* Date: 2022/12/14
*/
handleChangeItem = (value, id) => {
const { dataSource, onHandleItemhide } = this.props;
onHandleItemhide(
_.map([...dataSource], item => {
if (id === item.id) {
return {
...item,
itemHide: String(value)
};
}
return { ...item };
})
);
};
handleChangeAllItem = (value) => {
const { dataSource, onHandleItemhide } = this.props;
onHandleItemhide(
_.map([...dataSource], item => {
return {
...item,
itemHide: String(value)
};
})
);
};
render() {
const { dataSource, onDropCategoryItem, onChangeSelectedRowKeys, onEditFormnul } = this.props;
const { selectedRowKeys } = this.state;
const rowSelection = {
selectedRowKeys,
onChange: (selectedRowKeys) => this.setState({ selectedRowKeys }, () => {
onChangeSelectedRowKeys(this.state.selectedRowKeys);
}),
getCheckboxProps: record => ({
disabled: !record.canDelete
})
};
const checkValue = _.every(dataSource, it => it.itemHide && it.itemHide === "1") ? "1" : "0";
const columns = [
{
title: "名称",
dataIndex: "name",
key: "name"
},
{
title: <span>
<span style={{ marginRight: 8 }}>核算公式</span>
<WeaHelpfulTip title={<HelpContent/>} placement="bottom" width={200}/>
</span>,
dataIndex: "formulaContent",
key: "formulaContent",
render: (text, record) => {
if (record.canEdit) {
return (
<span className="linkWapper">
<a href="javascript: void(0);" onClick={() => onEditFormnul(record)}> {text} </a>
</span>
);
} else {
return <span> {text} </span>;
}
}
},
{
title: "个税申请表对应字段",
dataIndex: "taxDeclarationColumn",
key: "taxDeclarationColumn"
},
{
title: <span>
<WeaCheckbox
value={checkValue}
onChange={value => this.handleChangeAllItem(value)}
/>
<span style={{ marginLeft: 8 }}>隐藏</span>
</span>,
dataIndex: "itemHide",
key: "itemHide",
render: (text, record) => <WeaCheckbox
value={text ? String(text) : !text ? "0" : "1"}
onChange={value => this.handleChangeItem(value, record.id)}
/>
}
];
return (
<WeaTable
rowKey="id"
rowSelection={rowSelection}
dataSource={dataSource}
columns={columns}
onRow={(record, index) => ({
index,
moveRow: record
})}
pagination={false}
onDrop={onDropCategoryItem}
draggable={true}
/>
);
}
}
export default LedgerSalaryItemTable;
const HelpContent = () => {
return <span>
<span>1新建薪资账套时核算公式与薪资项目管理菜单一致</span><br/>
<span>2取值方式为公式的薪资项目核算公式显示为具体公式点击公式可编辑公式核算时按照当前薪资项目的公式进行核算</span><br/>
<span>3薪资账套内的薪资项目的公式或SQL的修改或公式的修改都不影响薪资项目管理菜单的薪资项目取值方式或公式只对当前账套生效</span><br/>
</span>;
};

View File

@ -0,0 +1,295 @@
/*
* Author: 黎永顺
* name: 新增编辑薪资账套
* Description:
* Date: 2022/12/8
*/
import React, { Component } from "react";
import { inject, observer } from "mobx-react";
import { WeaSlideModal, WeaSteps } from "ecCom";
import { Button, message, Modal } from "antd";
import SlideModalTitle from "../../../components/slideModalTitle";
import LedgerBaseSetting from "./ledgerBaseSetting";
import LedgerAssociatedPersonnel from "./ledgerAssociatedPersonnel";
import LedgerSalaryAdjustmentRules from "./ledgerSalaryAdjustmentRules";
import LedgerBackCalculatedSalaryItem from "./ledgerBackCalculatedSalaryItem";
import LedgerSalaryItem from "./ledgerSalaryItem";
import { saveAdjustmentRule, saveLedgerBasic, saveLedgerItem } from "../../../apis/ledger";
import "./index.less";
const Step = WeaSteps.Step;
const tabs = [
{ key: 0, title: "基础设置" },
{ key: 1, title: "关联人员" },
{ key: 2, title: "薪资项目" },
{ key: 3, title: "回算薪资项目" },
{ key: 4, title: "调薪计薪规则" }
];
@inject("taxAgentStore")
@observer
class LedgerSlide extends Component {
constructor(props) {
super(props);
this.state = {
current: 0,
loading: false,
baseSettingInfo: {},
adjustRules: [],
empFields: [], itemGroups: [],
saveSalarySobId: ""
};
}
componentWillUnmount() {
this.setState({
saveSalarySobId: ""
});
}
/*
* Author: 黎永顺
* Description: 保存基本信息
* Params:
* Date: 2022/12/12
*/
saveLedgerBasic = () => {
const { baseSettingInfo, current } = this.state;
const { editId } = this.props;
const { description, canEdit, ...extra } = baseSettingInfo;
const bool = _.every(Object.keys(extra), key => !!extra[key]);
if (!bool || _.isEmpty(baseSettingInfo)) {
Modal.warning({
title: "信息确认",
content: "必要信息不完整,红色*为必填项!"
});
return false;
}
this.setState({ loading: true });
saveLedgerBasic({ ...extra, description, id: editId }).then(({ status, data, errormsg }) => {
this.setState({ loading: false });
if (status) {
const { onRefreshList } = this.props;
message.success("保存成功");
onRefreshList();
!editId && this.setState({ current: current + 1, saveSalarySobId: data });
} else {
message.error(errormsg || "保存失败");
}
}).catch(() => this.setState({ loading: false }));
};
/*
* Author: 黎永顺
* Description: 保存调薪计薪规则
* Params:
* Date: 2022/12/12
*/
saveLedgerAdjustRule = () => {
const { adjustRules, saveSalarySobId } = this.state;
const payload = {
salarySobId: this.props.editId || saveSalarySobId,
ruleParams: adjustRules
};
this.setState({ loading: true });
saveAdjustmentRule(payload).then(({ status, errormsg }) => {
this.setState({ loading: false });
if (status) {
message.success("保存成功");
this.handleClose();
} else {
message.success(errormsg || "保存失败");
}
}).catch(() => this.setState({ loading: false }));
};
/*
* Author: 黎永顺
* Description: 薪资项目保存
* Params:
* Date: 2022/12/14
*/
saveLedgerItem = () => {
const { empFields, itemGroups, saveSalarySobId } = this.state;
const { editId: salarySobId } = this.props;
const payload = {
empFields,
itemGroups: _.filter(itemGroups, it => it.name !== "未分类"),
items: _.find(itemGroups, it => it.name === "未分类").items || [],
salarySobId: salarySobId || saveSalarySobId
};
this.setState({ loading: true });
saveLedgerItem(payload).then(({ status, errormsg }) => {
this.setState({ loading: false });
if (status) {
message.success("保存成功");
} else {
message.error(errormsg || "保存失败");
}
}).catch(() => this.setState({ loading: false }));
};
handleChangeSlideTab = (current) => {
this.setState({ current: Number(current) });
};
handleClose = () => {
this.setState({ current: 0 }, () => this.props.onCancel());
};
/*
* Author: 黎永顺
* Description: 基础信息字段切换
* Params:
* Date: 2022/12/9
*/
handleChangeSaveParams = (baseSettingInfo) => {
this.setState({ baseSettingInfo });
};
/*
* Author: 黎永顺
* Description: 薪资项目保存数据
* Params:
* Date: 2022/12/14
*/
handleSaveSalaryItemParams = (empFields, itemGroups) => {
this.setState({ empFields, itemGroups });
};
renderChildren = () => {
const { current, saveSalarySobId } = this.state;
let CurrentDom = null;
switch (current) {
case 0:
CurrentDom = <LedgerBaseSetting {...this.props} onSaveParams={this.handleChangeSaveParams}/>;
break;
case 1:
CurrentDom = <LedgerAssociatedPersonnel {...this.props} saveSalarySobId={saveSalarySobId}/>;
break;
case 2:
CurrentDom = <LedgerSalaryItem {...this.props} saveSalarySobId={saveSalarySobId}
onSaveSalaryItem={this.handleSaveSalaryItemParams}/>;
break;
case 3:
CurrentDom = <LedgerBackCalculatedSalaryItem {...this.props} saveSalarySobId={saveSalarySobId}/>;
break;
case 4:
CurrentDom =
<LedgerSalaryAdjustmentRules {...this.props} saveSalarySobId={saveSalarySobId}
onSaveParams={(adjustRules) => this.setState({ adjustRules })}/>;
break;
default:
CurrentDom = null;
break;
}
return CurrentDom;
};
renderCustomOperate = () => {
const { taxAgentStore: { showOperateBtn }, editId } = this.props;
const { current, loading } = this.state;
let CurrentDom = [];
//管理员操作权限
if (showOperateBtn) {
switch (current) {
case 0:
CurrentDom = [
<Button
type="primary"
loading={loading}
onClick={this.saveLedgerBasic}
>{editId ? "保存" : "保存并进入下一步"}</Button>
];
break;
case 1:
CurrentDom = !editId ? [
<Button type="ghost" onClick={this.handleClose}>完成跳过所有步骤</Button>,
<Button type="primary" onClick={() => this.setState({ current: current + 1 })}>下一步</Button>
] : [];
break;
case 2:
CurrentDom = !editId ?
[
<Button type="ghost" onClick={this.handleClose}>完成跳过所有步骤</Button>,
<Button type="ghost" onClick={() => this.setState({ current: current - 1 })}>上一步</Button>,
<Button
type="primary"
loading={loading}
onClick={() => {
this.setState({ current: current + 1 }, () => {
this.saveLedgerItem();
});
}}
>保存并进入下一步</Button>
] : [
<Button type="primary" loading={loading} onClick={this.saveLedgerItem}>保存</Button>
];
break;
case 3:
CurrentDom = !editId ?
[
<Button type="ghost" onClick={this.handleClose}>完成跳过所有步骤</Button>,
<Button type="ghost" onClick={() => this.setState({ current: current - 1 })}>上一步</Button>,
<Button type="primary" onClick={() => this.setState({ current: current + 1 })}>下一步</Button>
] : [];
break;
case 4:
CurrentDom = !editId ?
[
<Button type="ghost" onClick={() => this.setState({ current: current - 1 })}>上一步</Button>,
<Button type="primary" loading={loading} onClick={this.saveLedgerAdjustRule}>完成</Button>
] : [
<Button type="primary" loading={loading} onClick={this.saveLedgerAdjustRule}>保存</Button>
];
break;
default:
break;
}
}
return CurrentDom;
};
render() {
const { title, visible, editId, taxAgentStore: { showOperateBtn } } = this.props;
const { current } = this.state;
return (
<WeaSlideModal
className="slideOuterWrapper"
visible={visible}
top={0}
width={65}
height={100}
direction="right"
measure="%"
title={
<SlideModalTitle
subtitle={title}
tabs={editId ? tabs : []}
loading={false}
showOperateBtn={showOperateBtn}
editable={false}
onSave={() => {
}}
selectedTab={current}
customOperate={this.renderCustomOperate()}
subItemChange={this.handleChangeSlideTab}
/>
}
content={
<div className="ledgerSlideContent">
{
!editId &&
<WeaSteps current={current} style={{ margin: "20px 0" }}>
{
_.map(tabs, item => {
const { key, title } = item;
return <Step description={title} key={key}/>;
})
}
</WeaSteps>
}
{
this.renderChildren()
}
</div>
}
onClose={this.handleClose}
/>
);
}
}
export default LedgerSlide;

View File

@ -0,0 +1,204 @@
/*
* Author: 黎永顺
* name: 薪资账套列表
* Description:
* Date: 2022/12/7
*/
import React, { Component } from "react";
import { WeaCheckbox, WeaTable } from "ecCom";
import { inject, observer } from "mobx-react";
import { Menu, message, Modal, Popover } from "antd";
import { changeLedgerStatus, deleteLedger, getLedgerList } from "../../../apis/ledger";
import CopyLedgerModal from "./copyLedgerModal";
import "./index.less";
@inject("taxAgentStore")
@observer
class LedgerTable extends Component {
constructor(props) {
super(props);
this.state = {
loading: false,
dataSource: [],
columns: [],
pageInfo: {
current: 1,
pageSize: 10,
total: 0
},
copyLedgerModal: {
visible: false,
title: "复制账套", id: "", name: "", taxAgenyId: ""
}
};
}
componentDidMount() {
this.getLedgerList();
}
componentWillReceiveProps(nextProps, nextContext) {
if (nextProps.doSearch !== this.props.doSearch) this.getLedgerList();
}
getLedgerList = () => {
const { name } = this.props;
const { pageInfo } = this.state;
const payload = { name, ...pageInfo };
this.setState({ loading: true });
getLedgerList(payload).then(({ status, data }) => {
this.setState({ loading: false });
if (status) {
const { pageNum: current, pageSize, total, columns, list: dataSource } = data;
this.setState({
pageInfo: { ...pageInfo, current, pageSize, total },
dataSource,
columns
});
}
});
};
getColumns = () => {
const { columns } = this.state;
const { taxAgentStore, onEditLedger } = this.props;
const { showOperateBtn } = taxAgentStore;
return _.map(columns, item => {
const { dataIndex } = item;
if (dataIndex === "disable") {
item.render = (text, record) => {
return <WeaCheckbox
value={text === 0 ? "1" : "0"}
display="switch"
disabled={!showOperateBtn}
onChange={(disable) => this.changeLedgerStatus({ id: record.id, disable: disable === "0" ? 1 : 0 })}
/>;
};
} else if (dataIndex === "operate") {
item.width = 120;
item.render = (text, record) => {
return <div className="optWrapper">
<a href="javascript:void(0);" className="mr10" onClick={()=> onEditLedger(record)}>{showOperateBtn ? "编辑" : "查看"}</a>
{
showOperateBtn &&
<Popover
overlayClassName="moreIconWrapper"
placement="bottomRight"
content={<Menu onClick={(e) => this.handleMenuClick(e, record)}>
<Menu.Item key="copy">复制</Menu.Item>
<Menu.Item key="delete">删除</Menu.Item>
</Menu>} title="">
<i className="icon-coms-more"/>
</Popover>
}
</div>;
};
} else {
item.render = (text) => {
return <span className="tdEllipsis" title={text}>{text}</span>;
};
}
return { ...item };
});
};
/*
* Author: 黎永顺
* Description: 刪除薪资账套
* Params:
* Date: 2022/12/8
*/
deleteLedger = (payload) => {
deleteLedger(payload).then(({ status, errormsg }) => {
if (status) {
message.success("删除成功");
this.getLedgerList();
} else {
message.error(errormsg || "删除失败");
}
});
};
/*
* Author: 黎永顺
* Description: 启用/关闭账套
* Params:
* Date: 2022/12/8
*/
changeLedgerStatus = (payload) => {
changeLedgerStatus(payload).then(({ status, errormsg }) => {
if (status) {
message.success("操作成功");
this.getLedgerList();
} else {
message.error(errormsg || "操作成功");
}
});
};
handleResetCopy = () => {
const { copyLedgerModal } = this.state;
this.setState({
copyLedgerModal: { ...copyLedgerModal, visible: false, id: "", name: "", taxAgenyId: "" }
});
};
handleMenuClick = ({ key }, record) => {
const { copyLedgerModal } = this.state;
const { id, name, taxAgentId } = record;
switch (key) {
case "copy":
this.setState({
copyLedgerModal: { ...copyLedgerModal, visible: true, id, name, taxAgentId }
});
break;
case "delete":
Modal.confirm({
title: "信息确认",
content: "确认要删除吗?",
onOk: () => {
this.deleteLedger([id]);
}
});
break;
default:
break;
}
};
render() {
const { dataSource, columns, pageInfo, loading, copyLedgerModal } = this.state;
const pagination = {
...pageInfo,
showTotal: total => `${total}`,
showQuickJumper: true,
showSizeChanger: true,
pageSizeOptions: ["10", "20", "50", "100"],
onShowSizeChange: (current, pageSize) => {
this.setState({ pageInfo: { ...pageInfo, current, pageSize } }, () => {
this.getLedgerList();
});
},
onChange: current => {
this.setState({
pageInfo: { ...pageInfo, current }
}, () => {
this.getLedgerList();
});
}
};
return (
<React.Fragment>
<WeaTable
rowKey="id"
dataSource={dataSource}
pagination={pagination}
loading={loading}
columns={this.getColumns()}
/>
<CopyLedgerModal
{...copyLedgerModal}
onCancel={this.handleResetCopy}
onRefreshList={this.getLedgerList}
/>
</React.Fragment>
);
}
}
export default LedgerTable;

View File

@ -0,0 +1,774 @@
export const copyConditions = [
{
items: [
{
colSpan: 1,
conditionType: "INPUT",
domkey: ["name"],
fieldcol: 14,
rules: "required|string",
label: "账套名称",
labelcol: 6,
value: "",
viewAttr: 3
},
{
colSpan: 1,
conditionType: "SELECT",
domkey: ["taxAgentId"],
fieldcol: 14,
rules: "required|string",
label: "个税扣缴义务人",
labelcol: 6,
value: "",
viewAttr: 3
}
],
defaultshow: true
}
];
export const categoryConditions = [
{
items: [
{
colSpan: 1,
conditionType: "INPUT",
domkey: ["name"],
fieldcol: 14,
rules: "required|string",
label: "名称",
labelcol: 6,
value: "",
viewAttr: 3
}
],
defaultshow: true
}
];
export const baseSettingFormItem = [
{
key: "name",
label: "账套名称",
type: "INPUT"
},
{
key: "taxAgentId",
label: "个税扣缴义务人",
type: "SELECT",
options: []
},
{
key: "taxableItems",
label: "薪资类型",
type: "SELECT",
options: [
{
key: "1",
selected: true,
showname: "正常工资薪金所得"
},
{
key: "4",
selected: false,
showname: "劳务报酬所得"
}
]
},
{
key: "salaryCycleStrObj",
label: "薪资周期",
type: "CUSTOM",
children: [
{
key: "salaryCycleType",
type: "SELECT",
options: [
{
key: "1",
selected: false,
showname: "上上月"
},
{
key: "2",
selected: false,
showname: "上月"
},
{
key: "3",
selected: true,
showname: "本月"
},
{
key: "4",
selected: false,
showname: "下月"
}
]
},
{
key: "salaryCycleFromDay",
type: "SELECT",
options: [
{
key: "1",
selected: true,
showname: "1号"
},
{
key: "2",
selected: false,
showname: "2号"
},
{
key: "3",
selected: false,
showname: "3号"
},
{
key: "4",
selected: false,
showname: "4号"
},
{
key: "5",
selected: false,
showname: "5号"
},
{
key: "6",
selected: false,
showname: "6号"
},
{
key: "7",
selected: false,
showname: "7号"
},
{
key: "8",
selected: false,
showname: "8号"
},
{
key: "9",
selected: false,
showname: "9号"
},
{
key: "10",
selected: false,
showname: "10号"
},
{
key: "11",
selected: false,
showname: "11号"
},
{
key: "12",
selected: false,
showname: "12号"
},
{
key: "13",
selected: false,
showname: "13号"
},
{
key: "14",
selected: false,
showname: "14号"
},
{
key: "15",
selected: false,
showname: "15号"
},
{
key: "16",
selected: false,
showname: "16号"
},
{
key: "17",
selected: false,
showname: "17号"
},
{
key: "18",
selected: false,
showname: "18号"
},
{
key: "19",
selected: false,
showname: "19号"
},
{
key: "20",
selected: false,
showname: "20号"
},
{
key: "21",
selected: false,
showname: "21号"
},
{
key: "22",
selected: false,
showname: "22号"
},
{
key: "23",
selected: false,
showname: "23号"
},
{
key: "24",
selected: false,
showname: "24号"
},
{
key: "25",
selected: false,
showname: "25号"
},
{
key: "26",
selected: false,
showname: "26号"
},
{
key: "27",
selected: false,
showname: "27号"
},
{
key: "28",
selected: false,
showname: "28号"
},
{
key: "29",
selected: false,
showname: "29号"
},
{
key: "30",
selected: false,
showname: "30号"
},
{
key: "31",
selected: false,
showname: "31号"
}
]
}
]
},
{
key: "taxCycleType",
label: "税款所属期",
type: "SELECT",
options: [
{
key: "1",
selected: false,
showname: "上上月"
},
{
key: "2",
selected: false,
showname: "上月"
},
{
key: "3",
selected: true,
showname: "本月"
},
{
key: "4",
selected: false,
showname: "下月"
}
]
},
{
key: "attendCycleStrObj",
label: "考勤周期",
type: "CUSTOM",
children: [
{
key: "attendCycleType",
type: "SELECT",
options: [
{
key: "1",
selected: false,
showname: "上上月"
},
{
key: "2",
selected: false,
showname: "上月"
},
{
key: "3",
selected: true,
showname: "本月"
},
{
key: "4",
selected: false,
showname: "下月"
}
]
},
{
key: "attendCycleFromDay",
type: "SELECT",
options: [
{
key: "1",
selected: true,
showname: "1号"
},
{
key: "2",
selected: false,
showname: "2号"
},
{
key: "3",
selected: false,
showname: "3号"
},
{
key: "4",
selected: false,
showname: "4号"
},
{
key: "5",
selected: false,
showname: "5号"
},
{
key: "6",
selected: false,
showname: "6号"
},
{
key: "7",
selected: false,
showname: "7号"
},
{
key: "8",
selected: false,
showname: "8号"
},
{
key: "9",
selected: false,
showname: "9号"
},
{
key: "10",
selected: false,
showname: "10号"
},
{
key: "11",
selected: false,
showname: "11号"
},
{
key: "12",
selected: false,
showname: "12号"
},
{
key: "13",
selected: false,
showname: "13号"
},
{
key: "14",
selected: false,
showname: "14号"
},
{
key: "15",
selected: false,
showname: "15号"
},
{
key: "16",
selected: false,
showname: "16号"
},
{
key: "17",
selected: false,
showname: "17号"
},
{
key: "18",
selected: false,
showname: "18号"
},
{
key: "19",
selected: false,
showname: "19号"
},
{
key: "20",
selected: false,
showname: "20号"
},
{
key: "21",
selected: false,
showname: "21号"
},
{
key: "22",
selected: false,
showname: "22号"
},
{
key: "23",
selected: false,
showname: "23号"
},
{
key: "24",
selected: false,
showname: "24号"
},
{
key: "25",
selected: false,
showname: "25号"
},
{
key: "26",
selected: false,
showname: "26号"
},
{
key: "27",
selected: false,
showname: "27号"
},
{
key: "28",
selected: false,
showname: "28号"
},
{
key: "29",
selected: false,
showname: "29号"
},
{
key: "30",
selected: false,
showname: "30号"
},
{
key: "31",
selected: false,
showname: "31号"
}
]
}
]
},
{
key: "socialSecurityCycleType",
label: "福利台账月份",
type: "SELECT",
options: [
{
key: "1",
selected: false,
showname: "上上月"
},
{
key: "2",
selected: false,
showname: "上月"
},
{
key: "3",
selected: true,
showname: "本月"
},
{
key: "4",
selected: false,
showname: "下月"
}
]
},
{
key: "namescpoe",
label: "核算人员范围",
type: "CHECKBOX"
},
{
key: "description",
label: "备注",
type: "TEXTAREA"
}
];
export const monthDays = [
{
key: "1",
selected: true,
showname: "1号"
},
{
key: "2",
selected: false,
showname: "2号"
},
{
key: "3",
selected: false,
showname: "3号"
},
{
key: "4",
selected: false,
showname: "4号"
},
{
key: "5",
selected: false,
showname: "5号"
},
{
key: "6",
selected: false,
showname: "6号"
},
{
key: "7",
selected: false,
showname: "7号"
},
{
key: "8",
selected: false,
showname: "8号"
},
{
key: "9",
selected: false,
showname: "9号"
},
{
key: "10",
selected: false,
showname: "10号"
},
{
key: "11",
selected: false,
showname: "11号"
},
{
key: "12",
selected: false,
showname: "12号"
},
{
key: "13",
selected: false,
showname: "13号"
},
{
key: "14",
selected: false,
showname: "14号"
},
{
key: "15",
selected: false,
showname: "15号"
},
{
key: "16",
selected: false,
showname: "16号"
},
{
key: "17",
selected: false,
showname: "17号"
},
{
key: "18",
selected: false,
showname: "18号"
},
{
key: "19",
selected: false,
showname: "19号"
},
{
key: "20",
selected: false,
showname: "20号"
},
{
key: "21",
selected: false,
showname: "21号"
},
{
key: "22",
selected: false,
showname: "22号"
},
{
key: "23",
selected: false,
showname: "23号"
},
{
key: "24",
selected: false,
showname: "24号"
},
{
key: "25",
selected: false,
showname: "25号"
},
{
key: "26",
selected: false,
showname: "26号"
},
{
key: "27",
selected: false,
showname: "27号"
},
{
key: "28",
selected: false,
showname: "28号"
},
{
key: "29",
selected: false,
showname: "29号"
},
{
key: "30",
selected: false,
showname: "30号"
},
{
key: "31",
selected: false,
showname: "31号"
}
];
export const fieldType = [
{
key: "STRING",
selected: false,
showname: "字符"
},
{
key: "NUMBER",
selected: false,
showname: "数值"
}
];
export const valueTaking = [
{
key: "INPUT",
selected: false,
showname: "输入"
},
{
key: "FORMULA",
selected: false,
showname: "公式"
}
];
export const roundingRules = [
{
key: "RAW_DATA",
selected: false,
showname: "原始数据"
},
{
key: "ROUNDING",
selected: false,
showname: "四舍五入"
},
{
key: "ROUND_UP",
selected: false,
showname: "向上舍入"
},
{
key: "ROUND_DOWN",
selected: false,
showname: "向下舍入"
},
{
key: "CEILING",
selected: false,
showname: "见分进角"
},
{
key: "UP_EVEN",
selected: false,
showname: "向上求偶"
}
];
export const keepDecimalPlaces = [
{
key: "0",
selected: false,
showname: "0"
},
{
key: "1",
selected: false,
showname: "1"
},
{
key: "2",
selected: false,
showname: "2"
},
{
key: "3",
selected: false,
showname: "3"
},
{
key: "4",
selected: false,
showname: "4"
},
{
key: "5",
selected: false,
showname: "5"
}
];

View File

@ -0,0 +1,83 @@
/*
* Author: 黎永顺
* name: 薪资账套
* Description:
* Date: 2022/12/6
*/
import React, { Component } from "react";
import { inject, observer } from "mobx-react";
import { WeaInputSearch, WeaTop } from "ecCom";
import { Button } from "antd";
import LedgerTable from "./components/ledgerTable";
import LedgerSlide from "./components/ledgerSlide";
@inject("taxAgentStore")
@observer
class Index extends Component {
constructor(props) {
super(props);
this.state = {
searchVal: "",
doSearch: false,
slideparams: {
visible: false,
title: "新建账套",
editId: ""
}
};
}
handleEditLedger = (record) => {
const { slideparams } = this.state;
const { id } = record;
this.setState({ slideparams: { ...slideparams, visible: true, title: "编辑账套", editId: id } });
};
handleResetLedger = () => {
const { slideparams } = this.state;
this.setState({
slideparams: {
...slideparams,
visible: false,
title: "新建账套",
editId: ""
}
});
};
render() {
const { searchVal, doSearch, slideparams } = this.state;
const { taxAgentStore } = this.props;
const { showOperateBtn } = taxAgentStore;
const btns = [
<Button
type="primary"
onClick={() => this.setState({ slideparams: { ...slideparams, visible: true } })}
>新建</Button>,
<WeaInputSearch
value={searchVal} placeholder="请输入薪资账套名称"
onChange={searchVal => this.setState({ searchVal })}
onSearch={() => this.setState({ doSearch: !doSearch })}
/>
];
return (
<WeaTop
title="薪资账套"
icon={<i className="icon-coms-fa"/>}
iconBgcolor="#F14A2D"
showDropIcon={false}
buttons={showOperateBtn ? btns : btns.slice(-1)}
>
<div className="ledgerWrapper">
<LedgerTable name={searchVal} doSearch={doSearch} onEditLedger={this.handleEditLedger}/>
<LedgerSlide
{...slideparams}
onCancel={this.handleResetLedger}
onRefreshList={() => this.setState({ doSearch: !doSearch })}
/>
</div>
</WeaTop>
);
}
}
export default Index;

View File

@ -0,0 +1,11 @@
.ledgerWrapper {
height: 100%;
.tdEllipsis {
display: inline-block;
width: 100%;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}

View File

@ -1,8 +1,9 @@
import React from "react";
import { inject, observer } from "mobx-react";
import { message } from "antd";
import { message, Tag } from "antd";
import moment from "moment";
import CustomPaginationTable from "../../components/customPaginationTable";
import "../calculate/index.less";
@inject("payrollStore", "taxAgentStore")
@observer
@ -49,10 +50,8 @@ export default class SalarySendList extends React.Component {
getColumns = () => {
const { payrollStore: { salarySendTableStore }, taxAgentStore: { showOperateBtn } } = this.props;
const { columns } = salarySendTableStore;
if (!columns) {
return [];
}
let result = columns.filter(item => item.hide === "false");
if (!columns) return [];
let result = columns.filter(item => (item.hide === "false" && item.dataIndex !== "acctTimes"));
result.map(item => {
if (item.dataIndex === "salaryYearMonth") {
item.render = (text, record) => {
@ -70,6 +69,20 @@ export default class SalarySendList extends React.Component {
</span>
);
};
} else if (item.dataIndex === "salarySob") {
item.width = 300;
item.render = (text, record) => {
return <div className="salarySobNameWrapper">
<span>{text}</span>
<div className="salarySobNameTagWrapper">
{
record.salaryAcctType === 1 &&
<Tag color="yellow">补发</Tag>
}
<Tag color="blue">{`${record.acctTimes}`}</Tag>
</div>
</div>;
};
}
});
showOperateBtn
@ -79,15 +92,20 @@ export default class SalarySendList extends React.Component {
title: "操作",
key: "operate",
render: (text, record) => {
const { sendNum, sendTotal } = record;
const { sendNum, sendTotal, salaryAcctType, haveBackCalc } = record;
//显示发放
const showGrant = haveBackCalc === 1 && salaryAcctType === 0;
return (
<React.Fragment>
<a href="javascript:void(0);" onClick={() => this.handleGrant(record)}
style={{ marginRight: 10 }}>发放</a>
<a href="javascript:void(0);" onClick={() => this.handleShowDetail(record)}
style={{ marginRight: 10 }}>查看详情</a>
{
sendNum !== sendTotal &&
!showGrant &&
<a href="javascript:void(0);" onClick={() => this.handleShowDetail(record)}
style={{ marginRight: 10 }}>查看详情</a>
}
{
sendNum !== sendTotal && !showGrant &&
<a href="javascript:void(0);" onClick={() => this.handleUpdateTemplate(record)}>更新模板</a>
}
</React.Fragment>
@ -101,8 +119,14 @@ export default class SalarySendList extends React.Component {
title: "操作",
key: "operate",
render: (text, record) => {
const { salaryAcctType } = record;
return (
<a href="javascript:void(0);" onClick={() => this.handleShowDetail(record)}>查看详情</a>
<span>
{
salaryAcctType === 0 &&
<a href="javascript:void(0);" onClick={() => this.handleShowDetail(record)}>查看详情</a>
}
</span>
);
}
}

View File

@ -6,14 +6,17 @@ import moment from "moment";
import { WeaHelpfulTip, WeaInputSearch, WeaSelect, WeaSlideModal, WeaTop } from "ecCom";
import { renderLoading } from "../../util"; // 渲染form数据的方法因为多个页面都会使用所以抽的公共方法在util中
import CustomTab from "../../components/customTab";
import { columns, tempateColumns } from "./columns";
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 { notNull } from "../../util/validate";
import TemplateSettingForm from "./stepForm/tmplateSettingForm";
import CopyModal from "./copyModal";
import SalarySendList from "./SalarySendList";
import { getReplenishForm } from "../../apis/payroll";
import "../dataAcquisition/cumDeduct/index.less";
const { MonthPicker } = DatePicker;
@ -28,7 +31,7 @@ export default class Payroll extends React.Component {
selectedKey: "0",
currentStep: 0,
stepSlideVisible: false,
selectedTab: "0",
selectedTab: 0,
editSlideVisible: false,
initSelected: false,
ledgerOptions: [],
@ -60,11 +63,37 @@ export default class Payroll extends React.Component {
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("salaryTemplateShowSet", JSON.stringify(salaryTemplateShowSet));
});
} else {
setReplenishSalaryTemplateSalaryItemSet(data.replenishSalaryTemplateSalaryItemSet);
window.localStorage.setItem("salaryTemplateShowSet", JSON.stringify(salaryTemplateShowSet));
}
}
});
};
// 新建保存
handleSave = () => {
const { payrollStore } = this.props;
const { fetchSavePayroll } = payrollStore;
fetchSavePayroll().then(() => {
window.localStorage.removeItem("templateBaseData");
window.localStorage.removeItem("salaryTemplateShowSet");
this.setState({ currentStep: 0, stepSlideVisible: false });
});
};
@ -102,7 +131,7 @@ export default class Payroll extends React.Component {
const { getPayrollShowForm } = payrollStore;
this.recordId = record.id;
getPayrollShowForm(record.id);
this.setState({ templateCurrentId: record.id, selectedTab: "0" }, () => {
this.setState({ templateCurrentId: record.id, selectedTab: 0 }, () => {
this.setState({ editSlideVisible: true });
});
}
@ -137,9 +166,6 @@ export default class Payroll extends React.Component {
content: "确认删除",
onOk: () => {
deletePayroll([record.id]);
},
onCancel: () => {
}
});
}
@ -167,8 +193,29 @@ export default class Payroll extends React.Component {
// 更新保存
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,
@ -191,6 +238,18 @@ export default class Payroll extends React.Component {
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("templateBaseData", JSON.stringify(templateBaseData));
} else {
window.localStorage.removeItem("templateBaseData");
}
return _.every(validList, it => !!templateBaseData[it]);
};
render() {
const { payrollStore, taxAgentStore: { showOperateBtn } } = this.props;
const { loading, hasRight, templateStore, deletePayroll } = payrollStore;
@ -285,20 +344,15 @@ export default class Payroll extends React.Component {
);
}
};
const steps = ["基础设置", "显示设置"];
const validateStep1 = () => {
const { payrollStore: { templateBaseData } } = this.props;
if (!notNull(templateBaseData.name) || !notNull(templateBaseData.salarySob)) {
const steps = ["基础设置", "正常核算工资单模板", "补发工资单模版"];
const nextStep = () => {
if (!this.validateStep1()) {
Modal.warning({
title: "信息确认",
content: "必要信息不完整,红色*为必填项!"
});
return false;
return;
}
return true;
};
const nextStep = () => {
if (!validateStep1()) return;
this.setState({
currentStep: this.state.currentStep + 1
});
@ -359,6 +413,8 @@ export default class Payroll extends React.Component {
currentStep={currentStep}
steps={steps}
onCancel={() => {
window.localStorage.removeItem("templateBaseData");
window.localStorage.removeItem("salaryTemplateShowSet");
this.setState({ stepSlideVisible: false });
}}
customOperate={
@ -367,23 +423,33 @@ export default class Payroll extends React.Component {
nextStep();
}}>下一步</Button>
] : currentStep === 1 ? [
<Button type="default" style={{ marginRight: 10 }} onClick={() => {
<Button type="default" onClick={() => {
prevStep();
}}>上一步</Button>,
<Button type="primary" onClick={this.handleSave}>保存</Button>,
<Button type="default" style={{ marginLeft: 10 }} onClick={this.handlePreview}>预览</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={this.handleBaseInfoChange}/>
currentStep === 0 && <BaseInformForm onChange={(request) => this.handleBaseInfoChange(request)}/>
}
{
currentStep === 1 && <ShowSettingForm/>
}
{
currentStep === 2 && <TemplateSettingForm/>
}
</div>
}
/>
@ -397,42 +463,61 @@ export default class Payroll extends React.Component {
top={0}
width={50}
height={100}
direction={"right"}
measure={"%"}
direction="right"
measure="%"
title={
<SlideModalTitle
subtitle="编辑工资单模板"
tabs={[{ title: "基础设置", key: "0" }, { title: "显示设置", key: "1" }]}
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} style={{ marginRight: 10 }}>保存</Button>,
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>
] : []
}
subItemChange={
(selectedTab) => {
this.setState({ selectedTab });
}
] : [
<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={this.handleBaseInfoChange}/>
selectedTab === 0 &&
<BaseInformForm id={this.state.templateCurrentId}
onChange={(request) => this.handleBaseInfoChange(request)}/>
}
{
selectedTab === "1" && <ShowSettingForm id={this.state.templateCurrentId}/>
selectedTab === 1 && <ShowSettingForm id={this.state.templateCurrentId}/>
}
{
selectedTab === 2 && <TemplateSettingForm id={this.state.templateCurrentId}/>
}
</div>}
onClose={() => this.setState({ editSlideVisible: false }, () => this.setState({ selectedTab: 0 }))}
showMask={true}
closeMaskOnClick={() => this.setState({ editSlideVisible: false }, () => this.setState({ selectedTab: 0 }))}/>
onClose={() => this.setState({ editSlideVisible: false }, () => {
window.localStorage.removeItem("templateBaseData");
window.localStorage.removeItem("salaryTemplateShowSet");
this.setState({ selectedTab: 0 });
})}
/>
}
{
this.state.copyModalVisible &&

View File

@ -216,7 +216,8 @@ export default class PayrollGrant extends React.Component {
getColumns = () => {
const { payrollStore } = this.props;
const { salaryGrantTableStore: columns } = payrollStore;
const { salaryGrantTableStore: columns,salarySendDetailBaseInfo } = payrollStore;
const notShowGrantOrWithdraw = salarySendDetailBaseInfo.haveBackCalc === 1 && salarySendDetailBaseInfo.salaryAcctType === "0";
return [
...toJS(columns),
{
@ -225,7 +226,7 @@ export default class PayrollGrant extends React.Component {
dataIndex: "",
display: true,
render: (text, record) => {
if (record.sendStatus === "已发放") {
if (record.sendStatus === "已发放" && !notShowGrantOrWithdraw) {
return (
<a
href="javascript:void(0);"
@ -233,7 +234,7 @@ export default class PayrollGrant extends React.Component {
撤回
</a>
);
} else {
} else if(!notShowGrantOrWithdraw) {
return (
<a
href="javascript:void(0);"
@ -248,6 +249,9 @@ export default class PayrollGrant extends React.Component {
};
getSearchsAdQuick() {
const { payrollStore } = this.props;
const { salarySendDetailBaseInfo } = payrollStore;
const notShowGrantOrWithdraw = salarySendDetailBaseInfo.haveBackCalc === 1 && salarySendDetailBaseInfo.salaryAcctType === "0";
const { selectedKey } = this.state;
const handleMenuClick = e => {
switch (e.key) {
@ -272,7 +276,7 @@ export default class PayrollGrant extends React.Component {
更多
</Dropdown.Button>
];
if (selectedKey === "0") {
if (selectedKey === "0" && !notShowGrantOrWithdraw) {
btnDom = [
<ButtonSelect
datas={[
@ -285,7 +289,7 @@ export default class PayrollGrant extends React.Component {
/>,
...btnDom
];
} else {
} else if(selectedKey === "1" && !notShowGrantOrWithdraw) {
btnDom = [
<ButtonSelect
datas={[

View File

@ -1,6 +1,7 @@
import React from "react";
import { WeaFormItem, WeaInput, WeaSearchGroup, WeaSelect } from "ecCom";
import { inject, observer } from "mobx-react";
import { getReplenishRuleSetOptions } from "../../../apis/payroll";
import { toJS } from "mobx";
@inject("payrollStore")
@ -11,6 +12,7 @@ export default class BaseInformForm extends React.Component {
this.state = {
inited: false,
options: [],
replenishRuleOptions: [],
request: {}
};
}
@ -18,37 +20,60 @@ export default class BaseInformForm extends React.Component {
componentWillMount() {
const { payrollStore } = this.props;
const { getPayrollBaseForm } = payrollStore;
const templateBaseData = window.localStorage.getItem("templateBaseData") || "{}";
getPayrollBaseForm(this.props.id).then(data => {
this.setState(
{
replenishRuleOptions: _.map(data.replenishRuleSetOption, it => ({ key: it.id, showname: it.content })),
options: _.isEmpty(toJS(data.salarySobOptions)) ? [{ key: "", showname: "" }] : [{
key: "",
showname: ""
}, ...toJS(data.salarySobOptions)],
request: data.templateBaseData
},
() => {
request: {
...data.templateBaseData,
reissueRule: data.templateBaseData.replenishRule ? "1" : "0",
...JSON.parse(templateBaseData)
}
}, () => {
this.props.onChange && this.props.onChange(this.state.request);
this.setState({
inited: true
});
}
);
});
JSON.parse(templateBaseData).salarySob && this.getReplenishRuleSetOptions({ salarySobId: JSON.parse(templateBaseData).salarySob });
}
hanldeChange(params) {
hanldeChange = (params) => {
let request = { ...this.state.request, ...params };
this.setState({
request
}, () => {
if (this.state.request.reissueRule === "1" && this.state.request.salarySob) {
// TODO获取规则设置枚举项
this.getReplenishRuleSetOptions();
}
});
this.props.onChange && this.props.onChange(request);
}
};
getReplenishRuleSetOptions = (params = {}) => {
const { request } = this.state;
getReplenishRuleSetOptions({ salarySobId: request.salarySob, ...params }).then(({ status, data }) => {
if (status && !_.isEmpty(data)) {
this.setState({
replenishRuleOptions: _.map(data, it => ({ key: it.id, showname: it.content }))
});
}
});
};
render() {
const { request, options } = this.state;
const { salarySob, name, description } = request;
const { request, options, replenishRuleOptions } = this.state;
const { salarySob, name, description, replenishName, replenishRule, reissueRule } = request;
return (
<WeaSearchGroup title="基础信息" items={[]} needTigger showGroup center>
<WeaSearchGroup title="基础信息" items={[]} needTigger showGroup col={1}>
<WeaFormItem
label="薪资账套"
labelCol={{ span: 6 }}
@ -75,6 +100,45 @@ export default class BaseInformForm extends React.Component {
onChange={value => this.hanldeChange({ name: value })}
/>
</WeaFormItem>
<WeaFormItem
label="补发工资单模板名称"
labelCol={{ span: 6 }}
wrapperCol={{ span: 18 }}
>
<WeaInput
value={replenishName}
viewAttr={3}
onChange={value => this.hanldeChange({ replenishName: value })}
/>
</WeaFormItem>
<WeaFormItem
label="补发工资单名单生成规则"
labelCol={{ span: 6 }}
wrapperCol={{ span: 18 }}
>
<WeaSelect
options={[{ key: "0", showname: "全部" }, { key: "1", showname: "按规则" }]}
value={reissueRule}
detailtype={3}
viewAttr={3}
onChange={value => this.hanldeChange({ reissueRule: value })}
/>
</WeaFormItem>
{
reissueRule !== "0" &&
<WeaFormItem
label="规则设置"
labelCol={{ span: 6 }}
wrapperCol={{ span: 18 }}
>
<WeaSelect
options={replenishRuleOptions}
value={replenishRule}
viewAttr={3}
onChange={value => this.hanldeChange({ replenishRule: value })}
/>
</WeaFormItem>
}
<WeaFormItem
label="备注"
labelCol={{ span: 6 }}

View File

@ -23,7 +23,6 @@
}
.showSettingForm {
padding: 10px 20px;
.settingItemWrapper {
.itemTitle {

View File

@ -3,7 +3,7 @@ import { Icon, Modal, Radio, Switch } from "antd";
import { WeaFormItem, WeaInput, WeaSearchGroup } from "ecCom";
import { inject, observer } from "mobx-react";
import BackgroundUpload from "../components/backgroundUpload";
import './index.less';
import "./index.less";
@inject("payrollStore")
@ -17,22 +17,22 @@ export default class ShowSettingForm extends React.Component {
}
// form 字段变化时的回调
handleChange(params) {
handleChange = (params) => {
const { payrollStore: { salaryTemplateShowSet, setSalaryTemplateShowSet } } = this.props;
let request = { ...salaryTemplateShowSet, ...params };
setSalaryTemplateShowSet(request);
}
};
// 工资单主题 插入变量
handleThemeNameCllck(param) {
handleThemeNameCllck = (param) => {
const { payrollStore } = this.props;
const { salaryTemplateShowSet, setSalaryTemplateShowSet } = payrollStore;
let request = { ...salaryTemplateShowSet };
request.theme = (request.theme ? request.theme : "") + param;
setSalaryTemplateShowSet(request);
}
};
handleDownClick(index) {
handleDownClick = (index) => {
const { payrollStore: { salaryItemSet, setSalaryItemSet } } = this.props;
let downItem = salaryItemSet[index + 1];
let thisItem = salaryItemSet[index];
@ -40,9 +40,9 @@ export default class ShowSettingForm extends React.Component {
resultSet[index] = downItem;
resultSet[index + 1] = thisItem;
setSalaryItemSet(resultSet);
}
};
handleUpClick(index) {
handleUpClick = (index) => {
const { payrollStore: { salaryItemSet, setSalaryItemSet } } = this.props;
let upItem = salaryItemSet[index - 1];
let thisItem = salaryItemSet[index];
@ -50,11 +50,10 @@ export default class ShowSettingForm extends React.Component {
resultSet[index] = upItem;
resultSet[index - 1] = thisItem;
setSalaryItemSet(resultSet);
}
};
handleDeleteItem(group, item) {
handleDeleteItem = (group, item) => {
const { payrollStore: { salaryItemSet, setSalaryItemSet } } = this.props;
console.log("item:", item);
let resultSalaryItemSet = [...salaryItemSet];
resultSalaryItemSet.map(sourceGroup => {
if (sourceGroup.id == group.id) {
@ -66,9 +65,9 @@ export default class ShowSettingForm extends React.Component {
}
});
setSalaryItemSet(resultSalaryItemSet);
}
};
handleDeleteClick(index) {
handleDeleteClick = (index) => {
Modal.confirm({
title: "信息确认",
content: "确认删除",
@ -77,14 +76,13 @@ export default class ShowSettingForm extends React.Component {
let resultSalaryItemSet = [...salaryItemSet];
resultSalaryItemSet.splice(index, 1);
setSalaryItemSet(resultSalaryItemSet);
},
onCancel: () => {
}
});
}
};
render() {
const { payrollStore } = this.props;
const { payrollStore, id } = this.props;
const salaryTemplateShowSetStorage = id ? "{}" : window.localStorage.getItem("salaryTemplateShowSet") || "{}";
const { salaryTemplateShowSet } = payrollStore;
const { salaryItemSet } = payrollStore;
const {
@ -94,7 +92,7 @@ export default class ShowSettingForm extends React.Component {
textContentPosition,
salaryItemNullStatus,
salaryItemZeroStatus
} = salaryTemplateShowSet;
} = { ...salaryTemplateShowSet, ...JSON.parse(salaryTemplateShowSetStorage) };
return (
<div className="showSettingForm">
<WeaSearchGroup title="主题及其他设置" items={[]} needTigger showGroup center>

View File

@ -0,0 +1,121 @@
import React from "react";
import { Icon, Modal } from "antd";
import { WeaSearchGroup } from "ecCom";
import { inject, observer } from "mobx-react";
import { toJS } from "mobx";
import "./index.less";
@inject("payrollStore")
@observer
export default class TemplateSettingForm extends React.Component {
handleDownClick = (index) => {
const { payrollStore: { replenishSalaryTemplateSalaryItemSet, setReplenishSalaryTemplateSalaryItemSet } } = this.props;
let downItem = replenishSalaryTemplateSalaryItemSet[index + 1];
let thisItem = replenishSalaryTemplateSalaryItemSet[index];
let resultSet = [...replenishSalaryTemplateSalaryItemSet];
resultSet[index] = downItem;
resultSet[index + 1] = thisItem;
setReplenishSalaryTemplateSalaryItemSet(resultSet);
};
handleUpClick = (index) => {
const { payrollStore: { replenishSalaryTemplateSalaryItemSet, setReplenishSalaryTemplateSalaryItemSet } } = this.props;
let upItem = replenishSalaryTemplateSalaryItemSet[index - 1];
let thisItem = replenishSalaryTemplateSalaryItemSet[index];
let resultSet = [...replenishSalaryTemplateSalaryItemSet];
resultSet[index] = upItem;
resultSet[index - 1] = thisItem;
setReplenishSalaryTemplateSalaryItemSet(resultSet);
};
handleDeleteItem = (group, item) => {
const { payrollStore: { replenishSalaryTemplateSalaryItemSet, setReplenishSalaryTemplateSalaryItemSet } } = this.props;
let resultSalaryItemSet = [...replenishSalaryTemplateSalaryItemSet];
resultSalaryItemSet.map(sourceGroup => {
if (sourceGroup.id === group.id) {
sourceGroup.items.map((sourceItem, index) => {
if (sourceItem.id === item.id) {
sourceGroup.items.splice(index, 1);
}
});
}
});
setReplenishSalaryTemplateSalaryItemSet(resultSalaryItemSet);
};
handleDeleteClick = (index) => {
Modal.confirm({
title: "信息确认",
content: "确认删除",
onOk: () => {
const { payrollStore: { replenishSalaryTemplateSalaryItemSet, setReplenishSalaryTemplateSalaryItemSet } } = this.props;
let resultSalaryItemSet = [...replenishSalaryTemplateSalaryItemSet];
resultSalaryItemSet.splice(index, 1);
setReplenishSalaryTemplateSalaryItemSet(resultSalaryItemSet);
},
onCancel: () => {
}
});
};
render() {
const { payrollStore } = this.props;
const { replenishSalaryTemplateSalaryItemSet } = payrollStore;
return (
<div className="showSettingForm">
<WeaSearchGroup title="薪资项目设置" items={[]} needTigger showGroup>
{
!_.isEmpty(toJS(replenishSalaryTemplateSalaryItemSet)) &&
replenishSalaryTemplateSalaryItemSet.map((group, index) => (
<div className="configItemWrapper">
<div className="configTitle">{group.groupName}
{
index < replenishSalaryTemplateSalaryItemSet.length - 1 &&
<Icon
type="caret-down"
style={{ marginLeft: "10px", cursor: "pointer", color: "#666" }}
onClick={() => {
this.handleDownClick(index);
}}
/>
}
{
index > 0 &&
<Icon
type="caret-up"
style={{ marginLeft: "10px", cursor: "pointer", color: "#666" }}
onClick={() => {
this.handleUpClick(index);
}}
/>
}
<i
className="icon-coms-Delete"
style={{ cursor: "pointer", color: "#666", marginLeft: "10px" }}
onClick={() => {
this.handleDeleteClick(index);
}}
/>
</div>
<div className="configContent">
{group.items.map(item => (
<span className="editItem">{item.name}
<Icon
type="cross" style={{ cursor: "pointer" }}
onClick={() => {
this.handleDeleteItem(group, item);
}}
/>
</span>
))}
</div>
</div>
))
}
</WeaSearchGroup>
</div>
);
}
}

View File

@ -14,13 +14,13 @@ import {
WeaFormItem,
WeaHelpfulTip,
WeaInput,
WeaPopoverHrm,
WeaSearchGroup,
WeaSelect,
WeaSlideModal,
WeaTab,
WeaTable,
WeaTop,
WeaPopoverHrm
WeaTop
} from "ecCom";
import { WeaTableNew } from "comsMobx";
import { Button, Dropdown, Menu, message, Modal, Popover } from "antd";
@ -148,8 +148,8 @@ class Index extends Component {
const { taxAgentStore } = this.props;
const { getTaxAgentSelectListAsAdmin } = taxAgentStore;
getTaxAgentSelectListAsAdmin();
const init = this.init();
this.queryList("/api/bs/hrmsalary/salaryArchive/pendingList");
const init = this.init();
}
init = async () => {
@ -192,7 +192,16 @@ class Index extends Component {
const { loading, pageInfo, searchItemsValue } = this.state;
const { payrollFilesStore: { tableStore, queryList } } = this.props;
const payload = { ...pageInfo };
this.setState({ loading: { ...loading, query: true } });
this.setState({
loading: { ...loading, query: true },
dataSource: [],
tabCount: {
SUSPEND: 0,
STOP: 0,
FIXED: 0,
PENDING: 0
}
});
queryList(payload, searchItemsValue, url).then(({ data, status }) => {
this.setState({ loading: { ...loading, query: false } });
if (status) {
@ -230,8 +239,6 @@ class Index extends Component {
} else {
message.error(errormsg || "操作失败!");
}
}).catch(err => {
console.log(err);
});
}
});
@ -289,6 +296,33 @@ class Index extends Component {
}
});
};
handleClick = ({ key }) => {
const { selectedRowKeys } = this.state;
if (selectedRowKeys.length === 0) {
message.warning("请选择表格数据");
return;
}
if (key === "batchDelete") {
this.deletePendingTodo(selectedRowKeys);
} else {
API.gotoFixed(selectedRowKeys).then(({ status, data, errormsg }) => {
if (status) {
if (data.type === "success") {
message.success("操作成功!");
this.setState({
selectedRowKeys: []
}, () => {
this.query();
});
} else {
message.info(data.msg);
}
} else {
message.error(errormsg || "操作失败!");
}
});
}
};
getRightOptionBtns = () => {
const { selectedKey, importType, selectedRowKeys, searchItemsValue, pageInfo } = this.state;
const { taxAgentStore: { showOperateBtn } } = this.props;
@ -304,7 +338,20 @@ class Index extends Component {
verticalAlign: "middle"
}}/></Button>
</Dropdown>,
<Button type="ghost" onClick={this.allGotoFixed}>全部设为发薪人员</Button>
<Button type="ghost" onClick={this.allGotoFixed}>全部设为发薪人员</Button>,
<Dropdown
overlay={
<Menu className="dropdownMenuWrapper" onClick={this.handleClick}>
<Menu.Item key="batchSet">批量设为发薪员工</Menu.Item>
<Menu.Item key="batchDelete">批量删除待办</Menu.Item>
</Menu>
}
>
<Button type="primary">更多<i className="icon-coms-down2" style={{
marginLeft: 8,
verticalAlign: "middle"
}}/></Button>
</Dropdown>
];
} else if (selectedKey === "fixed" && showOperateBtn) {
return [
@ -427,7 +474,7 @@ class Index extends Component {
</a>;
}
};
}else if (item.dataIndex === "operate") {
} else if (item.dataIndex === "operate") {
return {
...item,
fixed: "right",
@ -564,7 +611,13 @@ class Index extends Component {
current: 1,
pageSize: 10
}
}, () => this.query());
});
if (!this.handleChangeDebounce) {
this.handleChangeDebounce = _.debounce(() => {
this.query()
}, 500);
}
this.handleChangeDebounce();
};
//编辑保存
handleSave = () => {

View File

@ -10,6 +10,8 @@ export default class FormalFormModal extends React.Component {
constructor(props) {
super(props);
this.state = {
validateType: "",
returnType: "",
value: "",
extendParam: {
sqlReturnKey: "",
@ -35,7 +37,9 @@ export default class FormalFormModal extends React.Component {
if (this.props.formulaId) {
detailFormual(this.props.formulaId).then(data => {
this.setState({
value: data.formula
value: data.formula,
returnType: data.returnType,
validateType: data.validateType
});
this.parameters = data.parameters;
this.referenceType = data.referenceType;
@ -60,6 +64,8 @@ export default class FormalFormModal extends React.Component {
let groupParams = {};
if (this.referenceType == "sql") {
groupParams = { "referenceType": "sql" };
}else{
groupParams = this.props.backCalcType === "issuedItems" ? { "referenceType": "backCalc" } : {};
}
salaryAcctImportTemplateParam(groupParams);
});
@ -67,6 +73,12 @@ export default class FormalFormModal extends React.Component {
let groupParams = {};
if (this.props.valueType == "3") {
groupParams = { "referenceType": "sql" };
} else if (this.props.valueType === "FORMULA") {
groupParams = this.props.backCalcType === "issuedItems" ? { "referenceType": "backCalc" } : {};
this.referenceType = "formula";
this.setState({
value: this.props.formulaContent
});
}
salaryAcctImportTemplateParam(groupParams);
}
@ -185,8 +197,8 @@ export default class FormalFormModal extends React.Component {
description: "备注",
module: "salary",
useFor: "salaryitem",
returnType: this.props.dataType,
validateType: this.props.dataType,
returnType: this.props.dataType || this.state.returnType,
validateType: this.props.dataType || this.state.returnType,
extendParam: JSON.stringify(this.state.extendParam),
formula: this.state.value,
parameters: this.parameters,
@ -247,7 +259,7 @@ export default class FormalFormModal extends React.Component {
const { value, formulaDatasourceList, extendParam } = this.state;
return (
<WeaDialog
title={`${this.props.valueType == 2 ? "函数" : "SQL"}公式`}
title={`${(this.props.valueType == 2 || this.props.valueType === "FORMULA") ? "函数" : "SQL"}公式`}
visible={this.props.visible}
style={{ width: 800 }}
buttons={[

View File

@ -174,17 +174,17 @@ export default class Archives extends React.Component {
placement="bottomRight"
content={<Menu onClick={({ key }) => {
if (key === "stopSalary") {
Modal.warning({
Modal.confirm({
title: "信息确认",
content: `确定要删除该条待办人员吗?`,
onOk: () => this.deleteTodoList({ runStatus: "5", ids: [record.baseInfo] })
onOk: () => this.cancelStayDel({ runStatus: "3", ids: [record.baseInfo] })
});
} else {
this.stayDelToStop([record.baseInfo]);
}
}}>
<Menu.Item key="stayDelToStop">减员</Menu.Item>
{/*<Menu.Item key="stopSalary">删除待办</Menu.Item>*/}
<Menu.Item key="stopSalary">删除待办</Menu.Item>
</Menu>} title="">
<i className="icon-coms-more"/>
</Popover>
@ -401,6 +401,8 @@ export default class Archives extends React.Component {
case "suspend":
if (key === "1") {
this.stayDelToStop(selectedRowKeys);
} else if (key === "2") {
this.cancelStayDel({ runStatus: "3", ids: selectedRowKeys });
}
break;
default:
@ -454,7 +456,7 @@ export default class Archives extends React.Component {
}
});
};
//删除待办
//删除待办-待增员
deleteTodoList = (payload) => {
API.updateRunStatus(payload).then(({ status, errormsg }) => {
if (status) {
@ -466,6 +468,18 @@ export default class Archives extends React.Component {
}
});
};
//删除待办-待减员
cancelStayDel = (payload) => {
API.cancelStayDel(payload).then(({ status, errormsg }) => {
if (status) {
message.success("操作成功");
this.query();
this.onSelectChange([]);
} else {
message.error(errormsg || "操作失败");
}
});
};
getTipChildren = () => {
const { selectedKey } = this.state;
@ -649,6 +663,7 @@ export default class Archives extends React.Component {
overlay={
<Menu onClick={this.handleMenuItemClick}>
<Menu.Item key="1">批量减员</Menu.Item>
<Menu.Item key="2">批量删除待办</Menu.Item>
</Menu>
}
type="primary"

View File

@ -9,6 +9,7 @@ import CustomPaginationTable from "../../../components/customPaginationTable";
import moment from "moment";
import _ from "lodash";
import ProgressModal from "../../../components/progressModal";
import { getCalculateProgress } from "../../../apis/calculate";
import "./index.less";
const MonthPicker = DatePicker.MonthPicker;
@ -318,39 +319,54 @@ export default class StandingBook extends React.Component {
break;
}
};
handleOk = (formVal) => {
handleOk = async (formVal) => {
const { save } = this.props.standingBookStore;
const { billMonth, ...extra } = formVal;
const payload = {
billMonth: moment(billMonth).format("YYYY-MM"),
...extra
};
save(payload).then(({ data }) => {
this.setState({
progressVisible: true
}, () => {
this.timer = setInterval(() => {
if (this.state.progress !== 100) {
this.setState({
progress: this.state.progress + 10
});
const { data: saveData } = await save(payload);
this.setState({
progressVisible: true
}, () => {
this.timer = setInterval(() => {
getCalculateProgress(moment(billMonth).format("YYYY-MM")).then(({ status, data }) => {
if (status) {
if (this.state.progress !== 100) {
this.setState({
progress: (Number(data.progress).toFixed(2)) * 100
});
} else {
clearInterval(this.timer);
this.setState({
progressVisible: false,
progress: 0
}, () => {
message.success("核算成功");
this.handleClose();
this.getCommonList({
...this.state.tableParams,
current: this.state.current
});
this.handleGoDetail(moment(billMonth).format("YYYY-MM"), "", extra.paymentOrganization ? extra.paymentOrganization : "", saveData);
});
}
} else {
clearInterval(this.timer);
this.setState({
progressVisible: false,
progress: 0
}, () => {
message.success("核算成功");
this.handleClose();
this.getCommonList({
...this.state.tableParams,
current: this.state.current
});
this.handleGoDetail(moment(billMonth).format("YYYY-MM"), "", extra.paymentOrganization ? extra.paymentOrganization : "", data);
});
}
}, 1000);
});
}).catch(() => {
clearInterval(this.timer);
this.setState({
progressVisible: false,
progress: 0
});
});
}, 600);
});
};

View File

@ -68,6 +68,7 @@ class AdjustmentSlide extends Component {
const { data: dataMsg, errorMessage = [] } = data;
const msg = dataMsg + errorMessage.join(",");
!_.isEmpty(errorMessage) ? message.error(msg) : message.success(msg || "保存成功");
_.isEmpty(errorMessage) &&
this.adjustTableRef.getCompensationList().then(r => {
});
} else {

View File

@ -37,10 +37,18 @@
margin-right: 0px;
}
}
.tdEllipsis {
display: inline-block;
width: 100%;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}
//退差
.regressionWrapper {
//退差;补差
.regressionWrapper, .differenceWrapper {
height: calc(100vh - 47px);
overflow: auto;

View File

@ -0,0 +1,140 @@
/*
* Author: 黎永顺
* name: 补差
* Description:
* Date: 2022/12/16
*/
import React, { Component } from "react";
import RegTop from "./regTop";
import { message, Modal } from "antd";
import { getQueryString } from "../../../../util/url";
import RegList from "./regList";
import AcctResultImportModal from "../../../calculateDetail/acctResult/importModal/acctResultImportModal";
import * as API from "../../../../apis/standingBook";
import "./index.less";
import RegEditDetial from "./regEditDetial";
import { calcPageNo } from "../../../../util";
class MakeupDifference extends Component {
constructor(props) {
super(props);
this.state = {
selectKey: [],
fieldData: {},
returnEditPersonSlide: {
title: "",
editId: "",
visible: false
},
importDiffModal: {
visible: false
},
loading: { save: false }
};
this.diffListRef = null;
this.regTopRef = null;
}
delBalance = () => {
const { selectKey: ids } = this.state;
const billMonth = getQueryString("billMonth");
const paymentOrganization = getQueryString("paymentOrganization");
const payload = { ids, billMonth, paymentOrganization };
API.delBalance(payload).then(({ status, errormsg }) => {
if (status) {
message.success("删除成功");
const current = calcPageNo(this.diffListRef.state.pageInfo.total, this.diffListRef.state.pageInfo.current, 10, ids.length);
this.diffListRef.recessionList({ current });
this.diffListRef.handleResetSelectRowKeys([]);
this.setState({ selectKey: [] });
} else {
message.error(errormsg || "删除失败");
}
});
};
handleChangeOpt = (key) => {
const { importDiffModal } = this.state;
const name = this.regTopRef.state.name;
const billMonth = getQueryString("billMonth");
const paymentOrganization = getQueryString("paymentOrganization");
switch (key) {
case "delete":
Modal.confirm({
title: "信息确认",
content: "确定删除数据吗?",
onOk: () => this.delBalance()
});
break;
case "import":
this.setState({ importDiffModal: { ...importDiffModal, visible: true } });
break;
case "export":
const url = `${window.location.origin}/api/bs/hrmsalary/welfare/balance/export?billMonth=${billMonth}&paymentOrganization=${paymentOrganization}`;
window.open(url, "_self");
break;
case "search":
this.diffListRef.recessionList({ userName: name });
break;
default:
break;
}
};
handleEdit = (record) => {
const { userName, id: editId } = record;
const { returnEditPersonSlide } = this.state;
this.setState({
returnEditPersonSlide: { ...returnEditPersonSlide, visible: true, title: userName, editId }
});
};
handleCloseModal = (refreshList = false) => {
const { returnEditPersonSlide } = this.state;
this.setState({
returnEditPersonSlide: { ...returnEditPersonSlide, visible: false, title: "", editId: "" }
}, () => {
refreshList && this.diffListRef.recessionList();
});
};
render() {
const billMonth = getQueryString("billMonth");
const { selectKey, importDiffModal, fieldData, returnEditPersonSlide } = this.state;
return (
<div className="differenceWrapper">
<RegTop
type="difference"
ref={dom => this.regTopRef = dom}
billMonth={billMonth}
onChange={this.handleChangeOpt}
selectKey={selectKey}
/>
<RegList
type="difference"
ref={dom => this.diffListRef = dom}
onChangeRowkey={(selectKey) => this.setState({ selectKey })}
onEdit={this.handleEdit}
/>
{/*编辑弹框*/}
<RegEditDetial {...returnEditPersonSlide} onCancel={this.handleCloseModal}/>
{/*导入补差*/}
{
importDiffModal.visible &&
<AcctResultImportModal
visiable={importDiffModal.visible}
fieldData={fieldData}
onAdd={fieldData => this.setState({ fieldData })}
onCancel={() => {
this.setState({ importDiffModal: { ...importDiffModal, visible: false }, fieldData: {} }, () => {
const name = this.regTopRef.state.name;
this.diffListRef.recessionList({ userName: name });
});
}}
isStandingBook
standingBookType="difference"
/>
}
</div>
);
}
}
export default MakeupDifference;

View File

@ -14,8 +14,10 @@ import { getQueryString } from "../../../../util/url";
import ProgressModal from "../../../../components/progressModal";
import AcctResultImportModal from "../../../calculateDetail/acctResult/importModal/acctResultImportModal";
import AdjustmentSlide from "./adjustmentSlide";
import { getCalculateProgress } from "../../../../apis/calculate";
import _ from "lodash";
import "./index.less";
import RegEditDetial from "./regEditDetial";
@inject("standingBookStore")
@observer
@ -46,6 +48,11 @@ export default class NormalIndex extends Component {
fieldData: {}, //选中的表单头信息
importParams: { //导入信息的弹框表示
visible: false
},
returnEditPersonSlide: {
title: "",
editId: "",
visible: false
}
};
this.timer = null;
@ -192,7 +199,6 @@ export default class NormalIndex extends Component {
...it,
width: 150,
fixed: "left",
render: (text, r) => {
const { userName, employeeId } = r;
return (
@ -362,40 +368,52 @@ export default class NormalIndex extends Component {
handleCommonAccountClick() {
const { billMonth, selectedKey, paymentOrganization } = this.props;
const { commonAccount } = this.props.standingBookStore;
commonAccount({
billMonth,
paymentOrganization,
includes: []
}).then(() => {
this.setState({
progressVisible: true
}, () => {
this.timer = setInterval(() => {
if (this.state.progress !== 100) {
this.setState({
progress: this.state.progress + 10
});
commonAccount({ billMonth, paymentOrganization, includes: [] });
this.setState({
progressVisible: true
}, () => {
this.timer = setInterval(() => {
getCalculateProgress(billMonth).then(({ status, data }) => {
if (status) {
if (this.state.progress !== 100) {
this.setState({
progress: (Number(data.progress).toFixed(2)) * 100
});
} else {
clearInterval(this.timer);
this.setState({
progressVisible: false,
progress: 0
}, () => {
message.success("核算成功");
selectedKey === "1"
? this.getNormalList({
billMonth,
paymentOrganization,
current: this.state.current
})
: this.getSupplementaryList({
billMonth,
paymentOrganization,
current: this.state.current
});
});
}
} else {
clearInterval(this.timer);
message.success("核算成功");
this.setState({
progressVisible: false,
progress: 0
});
selectedKey === "1"
? this.getNormalList({
billMonth,
paymentOrganization,
current: this.state.current
})
: this.getSupplementaryList({
billMonth,
paymentOrganization,
current: this.state.current
});
}
}, 1000);
});
}).catch(() => {
clearInterval(this.timer);
this.setState({
progressVisible: false,
progress: 0
});
});
}, 600);
});
}
@ -410,15 +428,26 @@ export default class NormalIndex extends Component {
window.open(url, "_self");
};
handleEditNormalStandingBook = (record) => {
const { userName, id: editId } = record;
const { returnEditPersonSlide } = this.state;
this.setState({
returnEditPersonSlide: { ...returnEditPersonSlide, visible: true, title: userName, editId }
});
};
handleCloseNormalStandingBookModal = (refreshList = false) => {
const { returnEditPersonSlide } = this.state;
this.setState({
returnEditPersonSlide: { ...returnEditPersonSlide, visible: false, title: "", editId: "" }
}, () => {
refreshList && this.getNormalList();
});
};
render() {
const { remarks, billMonth, selectedKey, paymentOrganization } = this.props;
const { selectedRowKeys, addProps, adjustSlide, importParams } = this.state;
const {
loading,
form,
condition,
saveLoading
} = this.props.standingBookStore;
const { selectedRowKeys, addProps, adjustSlide, importParams, returnEditPersonSlide } = this.state;
const { loading, form, condition, saveLoading } = this.props.standingBookStore;
let { list, columns, total } = this.state.tableData;
const rowSelection = {
selectedRowKeys,
@ -457,9 +486,52 @@ export default class NormalIndex extends Component {
});
}
};
columns = _.map(toJS(columns), item => {
if (item.dataIndex === "employeeId") {
return { ...item };
} else if (item.dataIndex === "costCenter") {
return {
...item,
render: (text, record) => {
const { costCenter } = record;
return <a href={costCenter.url} className="tdEllipsis">{costCenter.name || ""}</a>;
}
};
}
return {
...item,
render: (text) => {
return <span className="tdEllipsis" title={text}>{text}</span>;
}
};
});
columns = [
...columns,
{
title: "操作",
dataIndex: "operate",
fixed: "right",
width: "120px",
render: (text, record) => {
return (
<div className="optWrapper">
{
selectedKey === "3" &&
<a
href="javascript:void(0);"
className="mr10"
onClick={() => this.handleEditNormalStandingBook(record)}
>编辑</a>
}
</div>
);
}
}
];
return (
<div className="normalWapper">
{selectedKey === "1" &&
{
selectedKey === "1" &&
<div className="topContent">
<div className="month">
<span>
@ -478,7 +550,8 @@ export default class NormalIndex extends Component {
{remarks}
</span>
</div>
</div>}
</div>
}
<div className="tabOption">
{this.props.type !== "detail" && this.props.selectedKey == "3"
? <span style={{ display: "flex", alignItems: "center" }}>
@ -624,6 +697,8 @@ export default class NormalIndex extends Component {
scroll={{ x: 1200, y: "calc(100vh - 233px)" }}
/>
</Spin>
{/*编辑弹框*/}
<RegEditDetial {...returnEditPersonSlide} onCancel={this.handleCloseNormalStandingBookModal}/>
<AdjustmentSlide
{...adjustSlide}
onCancel={() => {

View File

@ -30,33 +30,6 @@ class RegAddEmployee extends Component {
};
}
componentDidMount() {
this.getEmployeeListByTaxAgent();
}
getEmployeeListByTaxAgent = () => {
const { returnPersonInfo, selectPersonInfo } = this.state;
const payload = {
pageNum: 1,
pageSize: 10000,
name: null
};
API.getEmployeeListByTaxAgent(payload).then(({ status, data }) => {
if (status) {
const { list } = data;
this.setState({
returnPersonInfo: {
...returnPersonInfo,
employeeOptions: _.map(list || [], it => ({ key: String(it.employeeId), showname: it.username }))
},
selectPersonInfo: {
...selectPersonInfo,
employeeOptions: _.map(list || [], it => ({ key: String(it.employeeId), showname: it.username }))
}
});
}
});
};
handleReset = () => {
this.setState({
baseInfo: {

View File

@ -28,6 +28,7 @@ class RegEditDetial extends Component {
render: (text, record) => {
return (
<WeaInputNumber
disabled={_.isNil(text)}
precision={2}
value={text}
onChange={v => this.handleChange("social", item.dataIndex, v, record)}
@ -50,6 +51,7 @@ class RegEditDetial extends Component {
render: (text, record) => {
return (
<WeaInputNumber
disabled={_.isNil(text)}
precision={2}
value={text}
onChange={v => this.handleChange("fund", item.dataIndex, v, record)}
@ -73,6 +75,7 @@ class RegEditDetial extends Component {
return (
<WeaInputNumber
precision={2}
disabled={_.isNil(text)}
value={text}
onChange={v => this.handleChange("other", item.dataIndex, v, record)}
/>
@ -107,16 +110,28 @@ class RegEditDetial extends Component {
otherComJson: {}
};
_.forEach(socialData.dataSource, item => {
payload["socialPerJson"][item["insuranceId"]] = item.personalPaymentAmount || "0";
payload["socialComJson"][item["insuranceId"]] = item.companyPaymentAmount || "0";
if (item.personalPaymentAmount) {
payload["socialPerJson"][item["insuranceId"]] = item.personalPaymentAmount;
}
if (item.companyPaymentAmount) {
payload["socialComJson"][item["insuranceId"]] = item.companyPaymentAmount;
}
});
_.forEach(foundData.dataSource, item => {
payload["fundPerJson"][item["insuranceId"]] = item.personalPaymentAmount || "0";
payload["fundComJson"][item["insuranceId"]] = item.companyPaymentAmount || "0";
if (item.personalPaymentAmount) {
payload["fundPerJson"][item["insuranceId"]] = item.personalPaymentAmount;
}
if (item.companyPaymentAmount) {
payload["fundComJson"][item["insuranceId"]] = item.companyPaymentAmount;
}
});
_.forEach(otherData.dataSource, item => {
payload["otherPerJson"][item["insuranceId"]] = item.personalPaymentAmount || "0";
payload["otherComJson"][item["insuranceId"]] = item.companyPaymentAmount || "0";
if (item.personalPaymentAmount) {
payload["otherPerJson"][item["insuranceId"]] = item.personalPaymentAmount;
}
if (item.companyPaymentAmount) {
payload["otherComJson"][item["insuranceId"]] = item.companyPaymentAmount;
}
});
_.forEach(Object.keys(payload), item => {
payload[item] = JSON.stringify(payload[item]);
@ -126,7 +141,7 @@ class RegEditDetial extends Component {
this.setState({ loading: false });
if (status) {
message.success("保存成功");
onCancel();
onCancel(true);
} else {
message.error(errormsg || "保存成功");
}
@ -139,7 +154,7 @@ class RegEditDetial extends Component {
case "social":
const sociallist = _.map(socialData.dataSource, item => {
if (item.insuranceId === record.insuranceId) {
return { ...item, [dataIndex]: !_.isNil(value) ? String(value): "0" };
return { ...item, [dataIndex]: !_.isNil(value) ? String(value) : "0" };
}
return { ...item };
});
@ -150,7 +165,7 @@ class RegEditDetial extends Component {
case "fund":
const fundlist = _.map(foundData.dataSource, item => {
if (item.insuranceId === record.insuranceId) {
return { ...item, [dataIndex]: !_.isNil(value) ? String(value): "0" };
return { ...item, [dataIndex]: !_.isNil(value) ? String(value) : "0" };
}
return { ...item };
});
@ -161,7 +176,7 @@ class RegEditDetial extends Component {
case "other":
const otherlist = _.map(otherData.dataSource, item => {
if (item.insuranceId === record.insuranceId) {
return { ...item, [dataIndex]: !_.isNil(value) ? String(value): "0" };
return { ...item, [dataIndex]: !_.isNil(value) ? String(value) : "0" };
}
return { ...item };
});

View File

@ -10,6 +10,11 @@ import { getQueryString } from "../../../../util/url";
import * as API from "../../../../apis/standingBook";
import "./index.less";
const APIFox = {
"regression": API.recessionList,
"difference": API.balanceList
};
class RegList extends Component {
constructor(props) {
super(props);
@ -41,7 +46,8 @@ class RegList extends Component {
handleResetSelectRowKeys = (selectedRowKeys) => {
this.setState({ selectedRowKeys });
};
recessionList = (module = {}) => {
recessionList = (module) => {
const { type } = this.props;
const { loading, pageInfo } = this.state;
const billMonth = getQueryString("billMonth");
const paymentOrganization = getQueryString("paymentOrganization");
@ -54,7 +60,7 @@ class RegList extends Component {
...module
};
this.setState({ loading: { ...loading, query: true } });
API.recessionList(payload).then(({ status, data }) => {
APIFox[type](payload).then(({ status, data }) => {
this.setState({ loading: { ...loading, query: false } });
if (status) {
const { pageInfo: list } = data;
@ -68,7 +74,6 @@ class RegList extends Component {
...items,
width: 110,
title: "姓名",
fixed: "left",
render: (text, r) => {
const { userName } = r;
return (
@ -76,6 +81,17 @@ class RegList extends Component {
);
}
};
} else if (items.dataIndex === "costCenter") {
return {
...items,
width: 110,
render: (text, r) => {
const { costCenter } = r;
return (
<a href={costCenter.url} className="tdEllipsis">{costCenter.name || ""}</a>
);
}
};
}
return {
...items,

View File

@ -13,7 +13,7 @@ class RegTop extends Component {
renderTopBtns = () => {
const { name } = this.state;
const { onChange, selectKey } = this.props;
const { onChange, selectKey, type: regtopType } = this.props;
const type = getQueryString("type");
let dom = [
<WeaHelpfulTip
@ -44,15 +44,18 @@ class RegTop extends Component {
];
if (!type) {
const [dom1, ...extra] = dom;
const domBtn = regtopType === "regression" ?
<Button type="primary" size="small" onClick={() => onChange("add")}>
<span className="icon-coms-Add-to-hot" title="添加"></span>
</Button> :
<Button type="primary" size="small" onClick={() => onChange("import")}>
<span className="icon-coms02-Import" title="导入"></span>
</Button>;
dom = [
dom1,
<Button type="primary" size="small" disabled={_.isEmpty(selectKey)} onClick={() => onChange("delete")}>
<span className="icon-coms-form-delete-hot" title="删除"></span>
</Button>,
<Button type="primary" size="small" onClick={() => onChange("add")}>
<span className="icon-coms-Add-to-hot" title="添加"></span>
</Button>,
...extra
</Button>, domBtn, ...extra
];
}
return dom;

View File

@ -102,13 +102,14 @@ class Regression extends Component {
break;
}
};
handleCloseModal = () => {
handleCloseModal = (refreshList = false) => {
const { returnPersonModal, returnEditPersonSlide } = this.state;
this.setState({
returnPersonModal: { ...returnPersonModal, visible: false, title: "添加退差人员" },
returnEditPersonSlide: { ...returnEditPersonSlide, visible: false, title: "", editId: "" }
}, () => {
this.regEmmployeeRef.handleReset();
refreshList && this.regListRef.recessionList();
});
};
handleEdit = (record) => {
@ -125,12 +126,14 @@ class Regression extends Component {
return (
<div className="regressionWrapper">
<RegTop
type="regression"
ref={dom => this.regTopRef = dom}
billMonth={billMonth}
onChange={this.handleChangeOpt}
selectKey={selectKey}
/>
<RegList
type="regression"
ref={dom => this.regListRef = dom}
visible={returnPersonModal.visible}
onChangeRowkey={(selectKey) => this.setState({ selectKey })}

View File

@ -11,6 +11,7 @@ import NormalIndex from "./components/normal";
import OverViewIndex from "./components/overView";
import AbnormalListIndex from "./components/abnormalList";
import Regression from "./components/regression";
import MakeupDifference from "./components/makeupDifference";
@inject("standingBookStore")
@observer
@ -39,7 +40,7 @@ class StandingBookDetail extends Component {
getTabList({ billMonth, paymentOrganization: this.paymentOrganization }).then(({ data }) => {
const { tabList, remarks, billMonth } = data;
let newTabList = tabList.filter(item => item.id != "2");
newTabList[newTabList.length - 2] = newTabList.splice(newTabList.length - 1, 1, newTabList[newTabList.length - 2])[0]
newTabList.push(newTabList.splice(_.findIndex(newTabList, it => it.id === "4"), 1)[0]);
this.setState({
selectedKey: newTabList[0].id,
tabList: _.map(newTabList, it => ({ title: it.content, viewcondition: it.id })),
@ -74,7 +75,10 @@ class StandingBookDetail extends Component {
<OverViewIndex billMonth={billMonth} type={this.type} paymentOrganization={this.paymentOrganization}/>
}
{
selectedKey === "5" && <Regression />
selectedKey === "5" && <Regression/>
}
{
selectedKey === "6" && <MakeupDifference/>
}
</div>
);

View File

@ -1,26 +1,26 @@
import React from 'react';
import ReactDOM from 'react-dom';
import React from "react";
import ReactDOM from "react-dom";
import { createHashHistory } from 'History';
import { createHashHistory } from "History";
import { Router, Route, useRouterHistory, IndexRedirect } from 'react-router';
import { IndexRedirect, Route, Router, useRouterHistory } from "react-router";
import { syncHistoryWithStore, RouterStore } from 'mobx-react-router';
import { RouterStore, syncHistoryWithStore } from "mobx-react-router";
import { Provider } from 'mobx-react';
import { Provider } from "mobx-react";
import Module from 'weaHrmSalary';
import Module from "weaHrmSalary";
const routing = new RouterStore();
const allStore = {
routing,
...Module.store,
...Module.store
};
const browserHistory = useRouterHistory(createHashHistory)({
queryKey: '_key',
basename: '/',
queryKey: "_key",
basename: "/"
});
const history = syncHistoryWithStore(browserHistory, allStore.routing);
@ -31,21 +31,24 @@ class Root extends React.Component {
componentWillMount() {
top.$(".ant-message").remove();
allStore.taxAgentStore.getPermission();
window.localStorage.removeItem("templateBaseData");
window.localStorage.removeItem("salaryTemplateShowSet");
}
render() {
return (
<Provider {...allStore}>
<Router history={history}>
<Route name='root' breadcrumbName='根路由' path='/' component={Home}>
<IndexRedirect to='main/hrmSalary/index' />
<Route name='main' breadcrumbName='入口' path='/main' component={Home}>
{ Module.Route }
<Route name="root" breadcrumbName="根路由" path="/" component={Home}>
<IndexRedirect to="main/hrmSalary/index"/>
<Route name="main" breadcrumbName="入口" path="/main" component={Home}>
{Module.Route}
</Route>
</Route>
</Router>
</Provider>
)
);
}
}
ReactDOM.render(<Root />, document.getElementById('container'));
ReactDOM.render(<Root/>, document.getElementById("container"));

View File

@ -1,11 +1,8 @@
import { observable, action, toJS } from "mobx";
import { action, observable } from "mobx";
import { message } from "antd";
import { WeaForm, WeaTableNew } from "comsMobx";
import { removePropertyCondition } from "../util/response";
import _ from "lodash";
import * as API from "../apis/standingBook";
import { importExcelInsuranceDetail } from "../apis/standingBook";
const { TableStore } = WeaTableNew;
@ -44,7 +41,7 @@ export class StandingBookStore {
if (status) {
// 接口请求成功/失败处理
const {
pageInfo: { list, columns, total, pageNum },
pageInfo: { list, columns, total, pageNum }
} = data;
resolve({ list, columns, total, pageNum });
} else {
@ -66,7 +63,7 @@ export class StandingBookStore {
if (status) {
// 接口请求成功/失败处理
const {
pageInfo: { list, columns, total },
pageInfo: { list, columns, total }
} = data;
resolve({ list, columns, total });
} else {
@ -88,7 +85,7 @@ export class StandingBookStore {
if (status) {
// 接口请求成功/失败处理
const {
pageInfo: { list, columns, total },
pageInfo: { list, columns, total }
} = data;
resolve({ list, columns, total });
} else {
@ -131,7 +128,7 @@ export class StandingBookStore {
// 接口请求成功/失败处理
const {
dataKey: { datas },
pageInfo: { list, total },
pageInfo: { list, total }
} = data;
this.tableStore.getDatas(datas);
resolve({ list, total });
@ -229,7 +226,7 @@ export class StandingBookStore {
// 接口请求成功/失败处理
const {
dataKey: { datas },
pageInfo: { list, total },
pageInfo: { list, total }
} = data;
this.tableStore.getDatas(datas);
resolve({ list, total });
@ -302,7 +299,7 @@ export class StandingBookStore {
action((res) => {
if (res.status) {
// 接口请求成功/失败处理
let condition = removePropertyCondition(res.data.condition)
let condition = removePropertyCondition(res.data.condition);
this.condition = condition;
this.form.initFormFields(condition); // 渲染高级搜索form表单
} else {
@ -318,7 +315,7 @@ export class StandingBookStore {
action((res) => {
if (res.status) {
// 接口请求成功/失败处理
let condition = removePropertyCondition(res.data.condition)
let condition = removePropertyCondition(res.data.condition);
this.condition = condition;
this.form.initFormFields(condition); // 渲染高级搜索form表单
} else {
@ -361,57 +358,70 @@ export class StandingBookStore {
commonAccount = (params) => {
return new Promise((resolve, reject) => {
API.commonAccount(params).then(res => {
if(res.status) {
if (res.status) {
resolve();
} else {
message.error(res.errormsg || "接口调用失败!")
message.error(res.errormsg || "接口调用失败!");
reject();
}
})
})
}
});
});
};
@action("社保福利台账重新核算")
socialSecurityBenefitsRecalculate = (params) => {
return new Promise((resolve, reject) => {
API.socialSecurityBenefitsRecalculate(params).then(res => {
if(res.status) {
if (res.status) {
resolve();
} else {
reject(res.errormsg || "接口调用失败!");
}
})
})
}
});
});
};
// 获取当前管理员下的所有个税扣缴义务人
@action
getAdminTaxAgentList = () => {
return new Promise((resolve, reject) => {
API.getAdminTaxAgentList().then(res => {
if(res.status) {
if (res.status) {
resolve(res.data);
} else {
message.error(res.errormsg || "接口调用失败!")
message.error(res.errormsg || "接口调用失败!");
reject();
}
})
})
}
});
});
};
@action("社保福利台账核算导入信息表头信息列表")
getWelfareList = () => {
return new Promise((resolve, reject) => {
API.getWelfareList().then(res => {
if(res.status) {
if (res.status) {
resolve(res.data);
} else {
message.error(res.errormsg || "接口调用失败!")
message.error(res.errormsg || "接口调用失败!");
reject();
}
})
})
}
});
});
};
@action("社保福利台账补差导入信息表头信息列表")
getBalanceWelfareList = () => {
return new Promise((resolve, reject) => {
API.getBalanceWelfareList().then(res => {
if (res.status) {
resolve(res.data);
} else {
message.error(res.errormsg || "接口调用失败!");
reject();
}
});
});
};
@action
setPreviewStandingBookAcctResultDataSource = previewAcctResultDataSource => {
@ -452,6 +462,16 @@ export class StandingBookStore {
});
};
@action("社保福利台账-补差数据导入")
importBalanceInsuranceDetail = (params) => {
API.importBalanceInsuranceDetail(params).then(res => {
if (res.status) {
this.importStandingBookAcctResult = res.data;
} else {
message.error(res.errormsg || "导入失败");
}
});
};
@action("社保福利台账-核算数据导入")
importInsuranceAcctDetail = (params) => {
API.importInsuranceAcctDetail(params).then(res => {

View File

@ -3,6 +3,7 @@ import { message } from "antd";
import { WeaForm, WeaTableNew } from "comsMobx";
import * as API from "../apis/calculate";
import { backCalculate } from "../apis/calculate";
const { TableStore } = WeaTableNew;
@ -466,7 +467,21 @@ export class calculateStore {
}
});
});
};
// 薪资记录-回算
@action
backCalculate = (salaryAcctRecordId) => {
return new Promise((resolve, reject) => {
API.backCalculate({ salaryAcctRecordId }).then(res => {
if (res.status) {
message.success("回算成功");
resolve();
} else {
message.error(res.errormsg || "回算失败");
reject();
}
});
});
};
// 薪资结果-编辑表单保存
@ -486,7 +501,14 @@ export class calculateStore {
return record;
});
let items = inputItems.concat(formulaItems);
let issuedAndReissueItems = this.acctresultDetailForm.issuedAndReissueItems.map(item => {
let record = {};
record.salaryItemId = item.salaryItemId;
record.resultValue = item.resultValue;
return record;
});
let items = inputItems.concat(formulaItems).concat(issuedAndReissueItems);
let params = {
salaryAcctEmpId: recordId,
items

View File

@ -3,12 +3,18 @@ import { message } from "antd";
import { WeaForm, WeaTableNew } from "comsMobx";
import * as API from "../apis/ledger"; // 引入API接口文件
import { tempateColumns } from "../pages/payroll/columns";
import { notNull } from "../util/validate";
import { categoryConditions } from "../pages/ledgerPage/config";
const { TableStore } = WeaTableNew;
export class LedgerStore {
//重构薪资账套
@observable copyForm = new WeaForm(); // 复制form
@observable categoryForm = new WeaForm(); // 新增分类form
/*******************************************************/
@observable tableStore = new TableStore(); // new table
@observable form = new WeaForm(); // nrew 一个form
@observable condition = []; // 存储后台得到的form数据

View File

@ -1,9 +1,8 @@
import { action, observable } from "mobx";
import { action, observable, toJS } from "mobx";
import { message } from "antd";
import { WeaForm, WeaTableNew } from "comsMobx";
import * as API from "../apis/payroll"; // 引入API接口文件
import { notNull } from "../util/validate";
import { removePropertyCondition } from "../util/response";
const { TableStore } = WeaTableNew;
@ -23,6 +22,7 @@ export class payrollStore {
@observable salarySobOptions = []; // 账套列表
// 显示设置表单
@observable salaryTemplateShowSet = {}; // 显示设置基础表单
@observable replenishSalaryTemplateSalaryItemSet = []; // 补发工资单模版基础表单
@observable salaryItemSet = []; // 显示设置薪资项
// **** 工资单页面 ****
@ -53,6 +53,10 @@ export class payrollStore {
@observable canWidthdrawColumns = []; // 可以撤回的列表列名
@observable canWithdrawPageInfo = {}; // 可以撤回列表分页对象
@action
setReplenishSalaryTemplateSalaryItemSet = replenishSalaryTemplateSalaryItemSet =>
(this.replenishSalaryTemplateSalaryItemSet = replenishSalaryTemplateSalaryItemSet);
@action
setGrantListShowSearchAd = grantListShowSearchAd =>
(this.grantListShowSearchAd = grantListShowSearchAd);
@ -64,8 +68,7 @@ export class payrollStore {
// 基础信息表单数据
@action
setTemplateBaseData = templateBaseData =>
(this.templateBaseData = templateBaseData);
setTemplateBaseData = templateBaseData => (this.templateBaseData = templateBaseData);
// 显示设置基础表单
@action
@ -168,6 +171,7 @@ export class payrollStore {
})
: [];
resolve({
replenishRuleSetOption: res.data.replenishRuleSetOption,
templateBaseData: this.templateBaseData,
salarySobOptions: this.salarySobOptions
});
@ -182,15 +186,14 @@ export class payrollStore {
// 工资单模板-获取工资单模板显示设置表单
@action
getPayrollShowForm = (id = "") => {
let params = {
id
};
const params = { id };
const salaryTemplateShowSetStorage = window.localStorage.getItem("salaryTemplateShowSet") || "{}";
API.getPayrollShowForm(params).then(res => {
if (res.status) {
if (id !== "") {
this.salaryItemSet = res.data.salaryTemplateSalaryItemSet;
}
this.salaryTemplateShowSet = res.data.salaryTemplateShowSet.data;
this.salaryTemplateShowSet = { ...res.data.salaryTemplateShowSet.data, ...JSON.parse(salaryTemplateShowSetStorage) };
} else {
message.error(res.errormsg || "获取失败");
}
@ -216,23 +219,15 @@ export class payrollStore {
@action
initShowSettingForm = (id = "") => {
this.getPayrollShowForm(id);
if (id == "") {
if (id === "") {
this.getPayrollItemList(this.templateBaseData.salarySob);
}
};
// 校验显示设置表单
validateSalaryTemplateShowSet = () => {
if (!notNull(this.salaryTemplateShowSet.theme)) {
message.warning("工资单主题不能为空");
return false;
}
return true;
};
// 拼装保存参数
convertParams = () => {
let params = { ...this.templateBaseData, ...this.salaryTemplateShowSet };
params.replenishRule = (!params.replenishRule || params.reissueRule === "0") ? "ALL" : params.replenishRule;
params.salarySobId = params.salarySob;
params.emailStatus = params.emailStatus ? params.emailStatus : false;
params.msgStatus = params.msgStatus ? params.msgStatus : false;
@ -242,19 +237,16 @@ export class payrollStore {
params.salaryItemZeroStatus = params.salaryItemZeroStatus
? params.salaryItemZeroStatus
: false;
params.salaryItemSetting = this.salaryItemSet;
params.salaryItemSetting = toJS(this.salaryItemSet);
params.replenishSalaryItemSetting = toJS(this.replenishSalaryTemplateSalaryItemSet);
return params;
};
// 工资单模板-新建工资单模板
@action
fetchSavePayroll = () => {
let params = this.convertParams();
return new Promise((resolve, reject) => {
if (!this.validateSalaryTemplateShowSet()) {
reject();
return false;
}
const params = this.convertParams();
API.savePayroll(params).then(res => {
if (res.status) {
message.success("保存成功");
@ -264,20 +256,16 @@ export class payrollStore {
message.error(res.errormsg || "保存失败");
reject();
}
});
}).catch(() => reject());
});
};
// 工资单模板-更新工资单模板
@action
fetchUpdatePayroll = id => {
let params = this.convertParams();
params.id = id;
return new Promise((resolve, reject) => {
if (!this.validateSalaryTemplateShowSet()) {
reject();
return false;
}
let params = this.convertParams();
params.id = id;
API.updatePayroll(params).then(res => {
if (res.status) {
message.success("保存成功");