feature/2.15.1.2407.01-浮动薪酬

This commit is contained in:
黎永顺 2024-08-12 09:24:11 +08:00
parent 86de787ed4
commit 9d99557f4b
7 changed files with 288 additions and 73 deletions

View File

@ -29,3 +29,16 @@ export const createVariableSalary = params => {
export const getVariableSalaryList = params => {
return postFetch("/api/bs/hrmsalary/variableSalary/list", params);
};
//导入浮动薪酬档案
export const importVariableSalary = params => {
return postFetch("/api/bs/hrmsalary/variableSalary/importData", params);
};
//删除浮动薪酬档案
export const deleteVariableSalary = params => {
return postFetch("/api/bs/hrmsalary/variableSalary/deleteSelectData", params);
};
//获取浮动薪酬档案明细
export const getVariableSalaryDetail = params => {
return postFetch("/api/bs/hrmsalary/variableSalary/getDetail", params);
};

View File

@ -39,13 +39,16 @@ class Index extends Component {
}
initForm = (props) => {
const { baseTableStore: { VSSalaryFileForm } } = props;
const { baseTableStore: { VSSalaryFileForm }, detail } = props;
API.getCreateForm().then(({ status, data }) => {
this.setState({
conditions: [
..._.map(salaryFileConditions, item => ({
...item,
items: _.map(item.items, o => ({ ...o, label: getLabel(o.lanId, o.label) }))
items: _.map(item.items, o => ({
...o, viewAttr: !_.isEmpty(detail) ? 1 : 2, label: getLabel(o.lanId, o.label),
value: detail[getKey(o)] || ""
}))
})),
{
items: _.map(data, o => ({
@ -54,14 +57,25 @@ class Index extends Component {
fieldcol: 14,
label: o.name,
labelcol: 6,
value: "",
viewAttr: 2
value: detail[`${String(o.id)}_variableItem`] || "",
viewAttr: !_.isEmpty(detail) ? 1 : 2
})),
title: "", col: 2,
defaultshow: true
}
]
}, () => VSSalaryFileForm.initFormFields(this.state.conditions));
}, () => {
VSSalaryFileForm.initFormFields(this.state.conditions);
if (!_.isEmpty(detail)) {
VSSalaryFileForm.updateFields({
employeeId: {
value: detail["employeeId"],
valueSpan: detail["username"],
valueObj: [{ id: detail["employeeId"], name: detail["username"] }]
}
});
}
});
});
};
convertPayload = (payload) => {
@ -96,14 +110,17 @@ class Index extends Component {
});
};
renderTitle = () => {
const { loading } = this.state, { title } = this.props;
const { loading } = this.state, { title, detail } = this.props;
return <div className="titleDialog">
<div className="titleCol titleLeftBox">
<div className="titleIcon"><i className="icon-coms-fa"/></div>
<div className="title">{title}</div>
</div>
<div className="titleCol titleRightBox">
<Button type="primary" loading={loading} onClick={this.save}>{getLabel(537558, "保存")}</Button>
{
_.isEmpty(detail) &&
<Button type="primary" loading={loading} onClick={this.save}>{getLabel(537558, "保存")}</Button>
}
</div>
</div>;
};

View File

@ -0,0 +1,94 @@
/*
* 浮动薪酬
* 薪资档案导入
* @Author: 黎永顺
* @Date: 2024/8/8
* @Wechat:
* @Email: 971387674@qq.com
* @description:
*/
import React, { Component } from "react";
import { WeaCheckbox, WeaLocaleProvider } from "ecCom";
import ImportDialog from "../../../../components/importDialog";
import * as API from "../../../../apis/variableSalary";
import { convertToUrlString } from "../../../../util/url";
const getLabel = WeaLocaleProvider.getLabel;
class Index extends Component {
constructor(props) {
super(props);
this.state = {
importDialog: {
nextloading: false, link: "/api/bs/hrmsalary/variableSalary/downloadTemplate",
importResult: {}, imageId: "", hasData: false,
previewUrl: "/api/bs/hrmsalary/variableSalary/preview"
}
};
}
componentWillReceiveProps(nextProps, nextContext) {
const { importDialog } = this.state;
if (nextProps.visible !== this.props.visible && nextProps.visible) {
const { baseTableStore: { VSalryForm }, salaryMonth } = nextProps;
const payload = {
salaryMonth, ...VSalryForm.getFormParams(), hasData: importDialog.hasData
};
this.setState({ importDialog: { ...importDialog, link: `${importDialog.link}?${convertToUrlString(payload)}` } });
} else {
this.setState({
importDialog: {
nextloading: false, link: "/api/bs/hrmsalary/variableSalary/downloadTemplate", hasData: false,
importResult: {}, imageId: "", previewUrl: "/api/bs/hrmsalary/variableSalary/preview"
}
});
}
}
handleImport = (payload) => {
const { salaryMonth } = this.props;
const { importDialog } = this.state;
this.setState({ importDialog: { ...importDialog, nextloading: true } });
API.importVariableSalary({ ...payload, salaryMonth }).then(({ data, status }) => {
this.setState({ importDialog: { ...importDialog, nextloading: false } });
if (status) {
this.setState({
importDialog: { ...importDialog, ...payload, importResult: data }
});
}
}).catch(() => this.setState({ importDialog: { ...importDialog, nextloading: false } }));
};
render() {
const { importDialog } = this.state;
return (
<ImportDialog
{...this.props} {...importDialog}
onResetImportResult={() => this.setState({
importDialog: { ...importDialog, importResult: {}, imageId: "", link: null }
})}
exportDataDom={
<WeaCheckbox
value={importDialog.hasData ? "1" : "0"}
content={getLabel(543208, "导出现有数据")}
helpfulTip={getLabel(111, "提示:建议先导出现有最新数据,修改后再导入")}
onChange={val => {
const { baseTableStore: { VSalryForm }, salaryMonth } = this.props;
const payload = { salaryMonth, ...VSalryForm.getFormParams(), hasData: val === "1" };
this.setState({
importDialog: {
...importDialog, hasData: val === "1",
link: `/api/bs/hrmsalary/variableSalary/downloadTemplate?${convertToUrlString(payload)}`
}
});
}}
/>
}
nextCallback={imageId => this.setState({ importDialog: { ...importDialog, imageId } })}
nextUplaodCallback={imageId => this.handleImport({ imageId })}
/>
);
}
}
export default Index;

View File

@ -8,10 +8,13 @@
* @description:
*/
import React, { Component } from "react";
import { WeaLocaleProvider, WeaTable } from "ecCom";
import { message, Modal } from "antd";
import { WeaLocaleProvider } from "ecCom";
import { WeaTableNew } from "comsMobx";
import { message, Modal, Spin } from "antd";
import * as API from "../../../../apis/variableSalary";
import { toJS } from "mobx";
const WeaTableComx = WeaTableNew.WeaTable;
const getLabel = WeaLocaleProvider.getLabel;
class Index extends Component {
@ -23,64 +26,78 @@ class Index extends Component {
}
componentDidMount() {
window.addEventListener("message", this.handleReceive, false);
window.addEventListener("resize", this.handleResize, false);
this.getVariableSalaryList();
}
componentWillUnmount() {
window.removeEventListener("message", this.handleReceive, false);
window.removeEventListener("resize", this.handleResize, false);
}
componentWillReceiveProps(nextProps, nextContext) {
if (nextProps.isQuery !== this.props.isQuery) this.setState({
pageInfo: { ...this.state.pageInfo, current: 1 }
}, () => this.getVariableSalaryList());
}
handleReceive = async ({ data }) => {
const { type, payload: { id, params } = {} } = data;
if (type === "init") {
this.getColumns();
} else if (type === "turn") {
switch (id) {
case "PAGEINFO":
this.setState({
pageInfo: { ...this.state.pageInfo, ...params }
}, () => this.getVariableSalaryList());
break;
case "DEL":
this.handleDelete([params.id]);
break;
case "VIEW":
this.handleView(params.id);
break;
default:
break;
}
}
};
getVariableSalaryList = () => {
const { baseTableStore: { VSalryForm }, salaryMonth } = this.props;
const { baseTableStore: { VSalryForm, getVariableSalaryList }, salaryMonth } = this.props;
const { pageInfo } = this.state;
const { departmentIds } = VSalryForm.getFormParams();
console.log(VSalryForm.getFormParams());
this.setState({ loading: true });
API.getVariableSalaryList({
getVariableSalaryList({
...pageInfo, salaryMonth, ...VSalryForm.getFormParams(),
departmentIds: !_.isEmpty(departmentIds) ? departmentIds.split(",") : []
})
.then(({ status, data }) => {
this.setState({ loading: false });
if (status) {
const { list: dataSource, columns, pageNum: current, pageSize, total } = data;
this.setState({
pageInfo: { ...pageInfo, current, pageSize, total }, dataSource,
columns: [
..._.filter(columns, o => o.dataIndex !== "id"),
{
title: getLabel(111, "操作"), dataIndex: "oprate",
render: (__, record) => (<React.Fragment>
<a href="javascript: void(0)" style={{ marginRight: 10 }}
onClick={() => this.handleEdit(record.id)}>{getLabel(111, "编辑")}</a>
{
record.canDelete && <a href="javascript: void(0)"
onClick={() => this.handleDelete([record.id])}>{getLabel(111, "删除")}</a>
}
</React.Fragment>)
}
]
}
);
}
});
};
handleEdit = (id) => {
API.getVariableSalaryItemDetail({ id }).then(({ status, data }) => {
if (status) this.props.onEditSalaryItem(data);
}).then(({ status, data }) => {
this.setState({ loading: false });
if (status) {
const { pageInfo: result } = data;
const { list: dataSource, pageNum: current, pageSize, total } = result;
this.setState({
pageInfo: { ...pageInfo, current, pageSize, total }, dataSource
}
);
}
});
};
handleDelete = (itemIds) => {
handleView = (id) => {
API.getVariableSalaryDetail({ id }).then(({ status, data }) => {
if (status) this.props.onViewSalaryFile(data.data);
});
};
handleDelete = (ids) => {
Modal.confirm({
title: getLabel(111, "信息确认"),
content: getLabel(111, "确认删除吗?"),
onOk: () => {
API.deleteVariableSalaryItem({ itemIds }).then(({ status, errormsg }) => {
API.deleteVariableSalary({ ids }).then(({ status, errormsg }) => {
if (status) {
message.success(getLabel(111, "删除成功"));
this.getVariableSalaryItemList();
this.getVariableSalaryList();
} else {
message.error(errormsg);
}
@ -88,29 +105,57 @@ class Index extends Component {
}
});
};
getColumns = () => {
const { baseTableStore: { SFTableStore }, showOperateBtn } = this.props;
const columns = _.map(_.filter(toJS(SFTableStore.columns), (item) => item.display === "true"), (it, idx) => ({
dataIndex: it.dataIndex, title: it.title, align: "left",
width: 150, ellipsis: true
}));
if (!_.isEmpty(columns)) {
this.postMessageToChild({
columns, showOperateBtn, dataSource: this.state.dataSource, scrollHeight: 100,
pageInfo: this.state.pageInfo, unitTableType: "variableSalary"
});
}
return columns;
};
postMessageToChild = (payload = {}) => {
const i18n = {
"操作": getLabel(30585, "操作"), "查看详情": getLabel(111, "查看详情"),
"共": getLabel(18609, "共"), "条": getLabel(18256, "条"),
"删除": getLabel(111, "删除")
};
const childFrameObj = document.getElementById("unitTable");
childFrameObj && childFrameObj.contentWindow.postMessage(JSON.stringify({ ...payload, i18n }), "*");
};
render() {
const { columns, dataSource, loading, pageInfo } = this.state;
const pagination = {
...pageInfo,
showTotal: total => `${getLabel(18609, "共")} ${total} ${getLabel(18256, "条")}`,
showQuickJumper: true,
showSizeChanger: true,
pageSizeOptions: ["10", "20", "50", "100"],
onShowSizeChange: (current, pageSize) => {
this.setState({
pageInfo: { ...pageInfo, current, pageSize }
}, () => this.getVariableSalaryList());
},
onChange: current => {
this.setState({
pageInfo: { ...pageInfo, current }
}, () => this.getVariableSalaryList());
}
};
const { loading, dataSource } = this.state;
const { baseTableStore: { SFTableStore } } = this.props;
const dom = document.querySelector(".wea-new-top-req-content");
let height = 280;
if (dom && dataSource.length > 0) {
height = (parseFloat(dom.style.height) > 620 && dataSource.length === 10) ? dataSource.length * 39 + 113 : dataSource.length < 10 ? dataSource.length * 39 + 113 : parseFloat(dom.style.height) - 16;
}
return (
<WeaTable columns={columns} dataSource={dataSource} loading={loading} bordered
pagination={pagination} scroll={{ y: `calc(100vh - 202px)` }}/>
<React.Fragment>
<div style={{ height: height + "px" }}>
<Spin spinning={loading}>
<iframe
style={{ border: 0, width: "100%", height: "100%" }}
// src="http://localhost:7607/#/unitTable"
src="/spa/hrmSalary/hrmSalaryCalculateDetail/index.html#/unitTable"
id="unitTable"
/>
</Spin>
</div>
<WeaTableComx
style={{ display: "none" }}
comsWeaTableStore={SFTableStore}
needScroll={true}
columns={this.getColumns()}
/>
</React.Fragment>
);
}
}

View File

@ -16,6 +16,8 @@ import SalaryItemDialog from "./components/salaryItemDialog";
import SalaryFileDialog from "./components/salaryFileDialog";
import SalaryItemList from "./components/salaryItemList";
import SalaryFileList from "./components/salaryFileList";
import SalaryFileImportDialog from "./components/salaryFileImportDialog";
import { convertToUrlString } from "../../util/url";
import moment from "moment";
import { Button } from "antd";
import cs from "classnames";
@ -32,35 +34,49 @@ class Index extends Component {
selectedKey: "salaryFile", isQuery: false, showSearchAd: false,
salaryMonth: moment(new Date()).format("YYYY-MM"),
SIDialog: { visible: false, title: "", id: "" }, //薪资项目薪资编辑弹框
SFDialog: { visible: false, title: "", id: "" } //薪资档案编辑弹框
SFDialog: { visible: false, title: "", detail: {} }, //薪资档案编辑弹框
SFImpDialog: { visible: false, title: getLabel(24023, "数据导入") }//薪资档案导入
};
}
handleAdvanceSearch = () => this.setState({ isQuery: !this.state.isQuery });
openAdvanceSearch = () => this.setState({ showSearchAd: !this.state.showSearchAd });
handleOperate = (type) => {
handleOperate = (type, detail = {}) => {
switch (type) {
case "create":
this.setState({
SFDialog: { visible: true, id: "", title: getLabel(111, "新增薪资档案") }
SFDialog: {
visible: true, detail,
title: _.isEmpty(detail) ? getLabel(111, "新增薪资档案") : getLabel(111, "查看薪资档案")
}
});
break;
case "import":
this.setState({ SFImpDialog: { ...this.state.SFImpDialog, visible: true } });
break;
case "export":
const { baseTableStore: { VSalryForm } } = this.props;
const { salaryMonth } = this.state;
const payload = { salaryMonth, ...VSalryForm.getFormParams() };
window.open(`/api/bs/hrmsalary/variableSalary/export?${convertToUrlString(payload)}`, "_blank");
break;
default:
break;
}
};
render() {
const { selectedKey, SIDialog, SFDialog, showSearchAd, isQuery, salaryMonth } = this.state;
const { selectedKey, SIDialog, SFDialog, SFImpDialog, showSearchAd, isQuery, salaryMonth } = this.state;
const { taxAgentStore: { showOperateBtn }, baseTableStore: { VSSalaryItemForm } } = this.props;
const tabs = [
{
title: getLabel(111, "薪资档案"), key: "salaryFile",
buttons: showOperateBtn ? [
<Button type="primary" onClick={() => this.handleOperate("create")}>{getLabel(111, "新建")}</Button>,
// <Button type="primary" onClick={() => this.handleOperate("create")}>{getLabel(111, "新建")}</Button>,
<Button type="ghost" onClick={() => this.handleOperate("import")}>{getLabel(111, "导入")}</Button>,
<Button type="primary" onClick={() => this.handleOperate("export")}>{getLabel(111, "导出")}</Button>,
<WeaDatePicker format="YYYY-MM" value={salaryMonth} onChange={val => this.setState({ salaryMonth: val })}/>,
<WeaDatePicker format="YYYY-MM" value={salaryMonth}
onChange={val => this.setState({ salaryMonth: val }, () => this.handleAdvanceSearch())}/>,
<AdvanceInputBtn searchType="advance" onOpenAdvanceSearch={() => this.openAdvanceSearch()}
onAdvanceSearch={this.handleAdvanceSearch}/>
] : [
@ -68,7 +84,8 @@ class Index extends Component {
<AdvanceInputBtn searchType="advance" onOpenAdvanceSearch={() => this.openAdvanceSearch()}
onAdvanceSearch={this.handleAdvanceSearch}/>
],
children: <SalaryFileList {...this.props} salaryMonth={salaryMonth} isQuery={isQuery}/>
children: <SalaryFileList {...this.props} salaryMonth={salaryMonth} isQuery={isQuery}
onViewSalaryFile={(data) => this.handleOperate("create", data)}/>
},
{
title: getLabel(111, "薪资项目"), key: "salaryItem",
@ -90,11 +107,11 @@ class Index extends Component {
title={getLabel(111, "浮动薪酬")} icon={<i className="icon-coms-fa"/>} selectedKey={selectedKey}
iconBgcolor="#F14A2D" tabDatas={tabs} className="variable_salary_wrapper"
buttons={_.find(tabs, o => selectedKey === o.key).buttons} buttonSpace={10}
onChange={selectedKey => this.setState({ selectedKey })}
onChange={selectedKey => this.setState({ selectedKey, SFDialog: { ...SFDialog, visible: false } })}
showDropIcon={false}
>
<div className={cs("searchAdvanced-condition-container", { "searchAdvanced-condition-hide": !showSearchAd })}>
<SearchPannel onCancel={() => this.setState({ showSearchAd: false })} onAdSearch={this.onAdSearch}/>
<SearchPannel onCancel={() => this.setState({ showSearchAd: false })} onAdSearch={this.handleAdvanceSearch}/>
</div>
{_.find(tabs, o => selectedKey === o.key).children}
{/*薪资项目*/}
@ -105,6 +122,11 @@ class Index extends Component {
<SalaryFileDialog {...SFDialog} onSearch={this.handleAdvanceSearch} onClose={callback => this.setState({
SFDialog: { ...SFDialog, visible: false }
}, () => callback && callback())}/>
{/* 薪资档案导入*/}
<SalaryFileImportDialog {...this.props} {...SFImpDialog} salaryMonth={salaryMonth} onCancel={callback => {
this.setState({ SFImpDialog: { ...SFImpDialog, visible: false } },
() => callback && this.handleAdvanceSearch());
}}/>
</WeaReqTop>
);
}

View File

@ -10,6 +10,10 @@
background: #FFF;
}
.ant-spin-nested-loading, .ant-spin-container {
height: 100% !important;
}
}
.searchAdvanced-condition-hide {

View File

@ -3,6 +3,7 @@ import { message } from "antd";
import { WeaForm, WeaTableNew } from "comsMobx";
import * as API from "../apis"; // 引入API接口文件
import { getVariableSalaryList } from "../apis/variableSalary"; //浮动薪酬-薪资档案列表查询
const { TableStore } = WeaTableNew;
@ -20,6 +21,25 @@ export class BaseTableStore {
@action initVSSalaryItemForm = () => this.VSSalaryItemForm = new WeaForm();
@observable VSSalaryFileForm = new WeaForm(); // 新增编辑薪资档案form
@action initVSSalaryFileForm = () => this.VSSalaryFileForm = new WeaForm();
@observable SFTableStore = new TableStore(); // 浮动薪酬-薪资档案table
@action("浮动薪酬-薪资档案列表查询")
getVariableSalaryList = (payload) => {
return new Promise((resolve, reject) => {
getVariableSalaryList(payload).then(res => {
const { data, status } = res;
if (status) {
const { dataKey } = data;
const { datas } = dataKey;
this.SFTableStore.getDatas(datas);
}
resolve(res);
}).catch(() => {
reject();
});
});
};
// 初始化操作
@action