数据采集-考勤引用页面重构

This commit is contained in:
黎永顺 2023-03-07 14:47:47 +08:00
parent 1fc70a9978
commit 6d5258daa5
10 changed files with 482 additions and 124 deletions

View File

@ -273,14 +273,14 @@ export const importAttendQuoteData = (params) => {
}; };
// 查看考勤详情 // 查看考勤详情
export const viewAttendQuote = (ids) => { export const viewAttendQuote = (params) => {
return fetch("/api/bs/hrmsalary/attendQuote/view", { return fetch("/api/bs/hrmsalary/attendQuote/view", {
method: "POST", method: "POST",
mode: "cors", mode: "cors",
headers: { headers: {
"Content-Type": "application/json", "Content-Type": "application/json",
}, },
body: JSON.stringify(ids), body: JSON.stringify(params),
}).then((res) => res.json()); }).then((res) => res.json());
}; };

View File

@ -27,7 +27,7 @@ export default class SelectItemModal extends React.Component {
render() { render() {
const { searchValue } = this.state; const { searchValue } = this.state;
const { title, onSearchItemSet, onShowOnlyChecked, comp: children, ...extra } = this.props; const { title, onSearchItemSet, onShowOnlyChecked, children, ...extra } = this.props;
const btns = [<Button type="primary">保存</Button>]; const btns = [<Button type="primary">保存</Button>];
const moreBtn = { const moreBtn = {
datas: [ datas: [

View File

@ -8,6 +8,81 @@ import React, { Component } from "react";
import { WeaCheckbox, WeaSearchGroup } from "ecCom"; import { WeaCheckbox, WeaSearchGroup } from "ecCom";
class SelectItemsWrapper extends Component { class SelectItemsWrapper extends Component {
constructor(props) {
super(props);
this.state = {
list: [],
filterList: []
};
}
componentDidMount() {
this.setState({
list: this.props.dataSource
});
}
handleSearchItemSet = (val) => {
const { dataSource } = this.props;
this.setState({
filterList: _.map(dataSource, item => {
return {
...item,
items: _.filter(item.items || [], child => child.name.indexOf(val) !== -1)
};
})
});
};
handleShowOnlyChecked = (checked) => {
const { dataSource } = this.props;
const { list } = this.state;
if (!!Number(checked)) {
this.setState({
list: _.map(list, item => {
return {
...item,
items: _.filter(item.items || [], child => !!child.checked)
};
})
});
} else {
this.setState({ list: dataSource });
}
};
handleSelectGroupAll = (groupId, checked) => {
const { list, filterList } = this.state;
const key = !_.isEmpty(filterList) ? "filterList" : "list";
this.setState({
[key]: _.map(!_.isEmpty(filterList) ? filterList : list, item => {
if (groupId === item.groupId) {
return {
...item,
items: _.map(item.items || [], child => {
return { ...child, checked: !!Number(checked) };
})
};
}
return { ...item };
})
});
};
handleSelectItem = (id, checked) => {
const { list, filterList } = this.state;
const key = !_.isEmpty(filterList) ? "filterList" : "list";
this.setState({
[key]: _.map(!_.isEmpty(filterList) ? filterList : list, item => {
return {
...item,
items: _.map(item.items || [], child => {
if (id === child.id) {
return { ...child, checked: !!Number(checked) };
}
return { ...child };
})
};
})
});
};
renderTitle = (item) => { renderTitle = (item) => {
const { onSelectGroupAll } = this.props; const { onSelectGroupAll } = this.props;
const { groupName, groupId } = item; const { groupName, groupId } = item;
@ -18,11 +93,13 @@ class SelectItemsWrapper extends Component {
}; };
render() { render() {
const { dataSource, onSelectItem } = this.props; const { list, filterList } = this.state;
const { onSelectItem } = this.props;
console.log("filterList", filterList);
return ( return (
<React.Fragment> <React.Fragment>
{ {
_.map(dataSource, item => { _.map(!_.isEmpty(filterList) ? filterList : list, item => {
const { items } = item; const { items } = item;
return <WeaSearchGroup title={this.renderTitle(item)} showGroup> return <WeaSearchGroup title={this.renderTitle(item)} showGroup>
<div className="itemsWrapper"> <div className="itemsWrapper">

View File

@ -141,6 +141,7 @@ export const conditions = [
showname: "文本" showname: "文本"
} }
], ],
rules: "required|string",
viewAttr: 3 viewAttr: 3
}, },
{ {
@ -167,5 +168,46 @@ export const conditions = [
defaultshow: true defaultshow: true
} }
]; ];
export const reFrenceConditions = [
{
items: [
{
colSpan: 1,
conditionType: "MONTHPICKER",
domkey: ["salaryYearMonth"],
fieldcol: 18,
rules: "required|string",
label: "薪资所属月",
labelcol: 6,
value: "",
viewAttr: 3
},
{
colSpan: 1,
conditionType: "SELECT",
domkey: ["salarySobId"],
fieldcol: 18,
isQuickSearch: false,
label: "薪资账套",
labelcol: 6,
valueList:[],
options: [],
rules: "required|string",
viewAttr: 3
},
{
colSpan: 1,
conditionType: "INPUT",
domkey: ["description"],
fieldcol: 18,
label: "备注",
labelcol: 6,
value: "",
viewAttr: 2
}
],
defaultshow: true
}
];

View File

@ -22,6 +22,8 @@ import ImportFormOptions from "./importFormOptions";
import SelectItemModal from "../../../../components/selectItemsModal"; import SelectItemModal from "../../../../components/selectItemsModal";
import moment from "moment"; import moment from "moment";
import SelectItemsWrapper from "../../../../components/selectItemsModal/selectItemsWrapper"; import SelectItemsWrapper from "../../../../components/selectItemsModal/selectItemsWrapper";
import AttendanceRefrenceDataModal from "./attendanceRefrenceDataModal";
import AttendanceDataViewSlide from "./attendanceDataViewSlide";
class AttendanceDataComp extends Component { class AttendanceDataComp extends Component {
constructor(props) { constructor(props) {
@ -33,7 +35,6 @@ class AttendanceDataComp extends Component {
}, },
dataSource: [], dataSource: [],
columns: [], columns: [],
fieldSetList: [],
pageInfo: { pageInfo: {
current: 1, current: 1,
pageSize: 10, pageSize: 10,
@ -47,7 +48,9 @@ class AttendanceDataComp extends Component {
salaryYearMonth: moment().format("YYYY-MM"), salarySobList: [], salaryYearMonth: moment().format("YYYY-MM"), salarySobList: [],
salarySobId: "", salaryCycle: "", attendCycle: "" salarySobId: "", salaryCycle: "", attendCycle: ""
}, },
fieldSetPayload: { visible: false, title: "", data: [] } fieldSetPayload: { visible: false, title: "", children: null },
attendanceReferencePayload: { visible: false, title: "" },
attendanceViewPayload: { visible: false, attendQuoteId: "", salaryYearMonth: "" }
}; };
} }
@ -136,6 +139,16 @@ class AttendanceDataComp extends Component {
} }
}); });
}; };
handleViewAttendanceData = ({ id, salaryCycle }) => {
const { attendanceViewPayload } = this.state;
this.setState({
attendanceViewPayload: {
...attendanceViewPayload,
visible: true, attendQuoteId: id,
salaryYearMonth: salaryCycle
}
});
};
handleImportAttendanceData = (importData) => { handleImportAttendanceData = (importData) => {
const { importFormPayload } = this.state; const { importFormPayload } = this.state;
const { salaryYearMonth, salarySobId } = importFormPayload; const { salaryYearMonth, salarySobId } = importFormPayload;
@ -208,10 +221,15 @@ class AttendanceDataComp extends Component {
this.setState({ loading: { ...loading, headset: false } }); this.setState({ loading: { ...loading, headset: false } });
if (status) { if (status) {
this.setState({ this.setState({
fieldSetList: data,
fieldSetPayload: { fieldSetPayload: {
...fieldSetPayload, ...fieldSetPayload,
visible: true, title: "导入字段设置", data visible: true, title: "导入字段设置",
children: <SelectItemsWrapper
ref={dom => this.setItemRef = dom}
dataSource={data}
onSelectGroupAll={this.handleSelectGroupAll}
onSelectItem={this.handleSelectItem}
/>
} }
}); });
} }
@ -222,121 +240,35 @@ class AttendanceDataComp extends Component {
this.setState({ this.setState({
fieldSetPayload: { fieldSetPayload: {
...fieldSetPayload, ...fieldSetPayload,
visible: false, title: "", data: [] visible: false, title: "", children: null
} }
}); });
}; };
handleSearchItemSet = (val) => { handleSearchItemSet = (val) => this.setItemRef.handleSearchItemSet(val);
const { fieldSetPayload, fieldSetList } = this.state; handleShowOnlyChecked = (checked) => this.setItemRef.handleShowOnlyChecked(checked);
this.setState({ handleSelectGroupAll = (groupId, checked) => this.setItemRef.handleSelectGroupAll(groupId, checked);
fieldSetList: _.map(_.cloneDeep(fieldSetList), item => { handleSelectItem = (id, checked) => this.setItemRef.handleSelectItem(id, checked);
return { /*
...item, * Author: 黎永顺
items: _.filter(item.items || [], child => { * Description: 考勤数据引用
return child.name.indexOf(val) !== -1; * Params:
}) * Date: 2023/3/7
}; */
}), handleQuoteAttendanceData = (payload) => {
fieldSetPayload: { const { attendanceReferencePayload } = this.state;
...fieldSetPayload, this.setState({ attendanceReferencePayload: { ...attendanceReferencePayload, ...payload } });
data: _.map(_.cloneDeep(fieldSetList), item => {
return {
...item,
items: _.filter(item.items || [], child => {
return child.name.indexOf(val) !== -1;
})
};
})
}
});
}; };
handleShowOnlyChecked = (checked) => { handleCloseQuoteModal = (isRefresh) => {
const { fieldSetPayload, fieldSetList } = this.state; const { attendanceReferencePayload } = this.state;
if (!!Number(checked)) { this.setState({ attendanceReferencePayload: { ...attendanceReferencePayload, visible: false } }, () => {
this.setState({ isRefresh && this.getAttendanceList();
fieldSetPayload: {
...fieldSetPayload,
data: _.map(_.cloneDeep(fieldSetList), item => {
return {
...item,
items: _.filter(item.items || [], child => !!child.checked)
};
})
}
});
} else {
this.setState({
fieldSetPayload: {
...fieldSetPayload,
data: _.cloneDeep(fieldSetList)
}
});
}
};
handleSelectGroupAll = (groupId, checked) => {
const { fieldSetPayload, fieldSetList } = this.state;
this.setState({
fieldSetList: _.map(_.cloneDeep(fieldSetList), item => {
if (groupId === item.groupId) {
return {
...item,
items: _.map(item.items || [], child => {
return { ...child, checked: !!Number(checked) };
})
};
}
return { ...item };
}),
fieldSetPayload: {
...fieldSetPayload,
data: _.map(_.cloneDeep(fieldSetList), item => {
if (groupId === item.groupId) {
return {
...item,
items: _.map(item.items || [], child => {
return { ...child, checked: !!Number(checked) };
})
};
}
return { ...item };
})
}
});
};
handleSelectItem = (id, checked) => {
const { fieldSetPayload, fieldSetList } = this.state;
this.setState({
fieldSetList: _.map(_.cloneDeep(fieldSetList), item => {
return {
...item,
items: _.map(item.items || [], child => {
if (id === child.id) {
return { ...child, checked: !!Number(checked) };
}
return { ...child };
})
};
}),
fieldSetPayload: {
...fieldSetPayload,
data: _.map(_.cloneDeep(fieldSetList), item => {
return {
...item,
items: _.map(item.items || [], child => {
if (id === child.id) {
return { ...child, checked: !!Number(checked) };
}
return { ...child };
})
};
})
}
}); });
}; };
render() { render() {
const { const {
dataSource, columns, pageInfo, loading, importData, importFormPayload, fieldSetPayload dataSource, columns, pageInfo, loading, importData, importFormPayload, fieldSetPayload,
attendanceReferencePayload, attendanceViewPayload
} = this.state; } = this.state;
const { showOperateBtn, salaryYearMonth } = this.props; const { showOperateBtn, salaryYearMonth } = this.props;
const pagination = { const pagination = {
@ -368,7 +300,7 @@ class AttendanceDataComp extends Component {
render: (_, record) => { render: (_, record) => {
return ( return (
<div className="linkWapper"> <div className="linkWapper">
<a href="javascript: void(0);">查看</a> <a href="javascript: void(0);" onClick={() => this.handleViewAttendanceData(record)}>查看</a>
{showOperateBtn && {showOperateBtn &&
<a href="javascript: void(0);" onClick={() => this.handleDeleteAttendanceData(record)}>删除</a> <a href="javascript: void(0);" onClick={() => this.handleDeleteAttendanceData(record)}>删除</a>
} }
@ -395,17 +327,27 @@ class AttendanceDataComp extends Component {
/> />
{/* 表头设置 */} {/* 表头设置 */}
<SelectItemModal {...fieldSetPayload} <SelectItemModal {...fieldSetPayload}
comp={
<SelectItemsWrapper
dataSource={fieldSetPayload.data}
onSelectGroupAll={this.handleSelectGroupAll}
onSelectItem={this.handleSelectItem}
/>
}
onCancel={this.handleCloseSettings} onCancel={this.handleCloseSettings}
onSearchItemSet={this.handleSearchItemSet} onSearchItemSet={this.handleSearchItemSet}
onShowOnlyChecked={this.handleShowOnlyChecked} onShowOnlyChecked={this.handleShowOnlyChecked}
/> />
{/* 考勤数据引用 */}
<AttendanceRefrenceDataModal
{...attendanceReferencePayload}
onCancel={this.handleCloseQuoteModal}
/>
{/* 考勤数据查看 */}
<AttendanceDataViewSlide
{...attendanceViewPayload}
showOperateBtn={showOperateBtn}
onClose={() => this.setState({
attendanceViewPayload: {
...attendanceViewPayload,
visible: false,
attendQuoteId: ""
}
})}
/>
</React.Fragment> </React.Fragment>
); );
} }

View File

@ -0,0 +1,143 @@
/*
* Author: 黎永顺
* name: 考勤引用数据查看
* Description:
* Date: 2023/3/7
*/
import React, { Component } from "react";
import { WeaFormItem, WeaInput, WeaInputSearch, WeaSlideModal } from "ecCom";
import { Button } from "antd";
import SlideModalTitle from "../../../../components/slideModalTitle";
import { viewAttendQuote } from "../../../../apis/attendance";
import UnifiedTable from "../../../../components/UnifiedTable";
import "./index.less";
class AttendanceDataViewSlide extends Component {
constructor(props) {
super(props);
this.state = {
loading: {
query: false
},
keyword: "",
dataSource: [],
columns: [],
pageInfo: {
current: 1, pageSize: 10, total: 0
}
};
}
componentWillReceiveProps(nextProps, nextContext) {
if (nextProps.visible !== this.props.visible && nextProps.visible) this.viewAttendQuote({}, nextProps);
}
viewAttendQuote = (extraPayload = {}, props) => {
const { loading, pageInfo, keyword } = this.state;
const { attendQuoteId } = props;
this.setState({ loading: { ...loading, query: true } });
viewAttendQuote({ ...pageInfo, attendQuoteId, keyword, ...extraPayload }).then(({ status, data }) => {
this.setState({ loading: { ...loading, query: false } });
if (status) {
const { columns, list: dataSource, pageNum: current, pageSize, total } = data.pageInfo;
this.setState({
pageInfo: { ...pageInfo, current, pageSize, total },
dataSource,
columns
});
}
}).catch(() => this.setState({ loading: { ...loading, query: false } }));
};
renderCustomOperate = () => {
const { keyword } = this.state;
const { showOperateBtn } = this.props;
return ([
<div style={{ display: "inline-block" }}>
{showOperateBtn && <Button type="primary" onClick={this.handleExportAttendQuote}>导出全部</Button>}
<WeaInputSearch
value={keyword}
style={{ marginLeft: 10 }}
placeholder="请输入姓名/部门/工号/手机号"
onChange={keyword => this.setState({ keyword })}
onSearch={() => this.viewAttendQuote({ current: 1 }, this.props)}
/>
</div>
]);
};
handleExportAttendQuote = () => {
if (!this.handleDebounce) {
this.handleDebounce = _.debounce(() => {
const { attendQuoteId } = this.props;
const url = `${window.location.origin}/api/bs/hrmsalary/attendQuote/export?attendQuoteId=${attendQuoteId}`;
window.open(url, "_self");
this.handleDebounce = null;
}, 500);
}
this.handleDebounce();
};
render() {
const { showOperateBtn, salaryYearMonth, ...extra } = this.props;
const { columns, dataSource, loading, pageInfo } = this.state;
const pagination = {
...pageInfo,
showTotal: (total) => `${total}`,
pageSizeOptions: ["10", "20", "50", "100"],
showSizeChanger: true,
showQuickJumper: true,
onShowSizeChange: (current, pageSize) => {
this.setState({
pageInfo: { ...pageInfo, current, pageSize }
}, () => this.viewAttendQuote({}, this.props));
},
onChange: (current) => {
this.setState({
pageInfo: { ...pageInfo, current }
}, () => this.viewAttendQuote({}, this.props));
}
};
return (
<WeaSlideModal
{...extra}
className="attendanceSlideWrapper"
top={0}
measureT="%"
width={800}
measureX="px"
height={100}
measureY="%"
direction="right"
title={
<SlideModalTitle
subtitle="考勤数据"
editable={false}
showOperateBtn={showOperateBtn}
customOperate={this.renderCustomOperate()}
/>
}
content={
<div>
<WeaFormItem label="考勤周期" labelCol={{ span: 4 }} wrapperCol={{ span: 20 }} underline>
<WeaInput value={salaryYearMonth} viewAttr={1}/>
</WeaFormItem>
<UnifiedTable
rowKey="id"
columns={_.map(columns, item => ({
...item,
render: (text) => {
return <span className="ellipsis" title={text}> {text} </span>;
}
}))}
dataSource={dataSource}
pagination={pagination}
loading={loading.query}
xWidth={columns.length * 120}
/>
</div>
}
/>
);
}
}
export default AttendanceDataViewSlide;

View File

@ -0,0 +1,114 @@
/*
* Author: 黎永顺
* name: 考勤数据引用
* Description:
* Date: 2023/3/1
*/
import React, { Component } from "react";
import { inject, observer } from "mobx-react";
import { WeaDialog } from "ecCom";
import { Button, message } from "antd";
import { reFrenceConditions } from "../columns";
import { getSearchs } from "../../../../util";
import { checkOperation, getLedgerList, syncAttendanceRefer } from "../../../../apis/attendance";
import "./index.less";
@inject("attendanceStore")
@observer
class AttendanceRefrenceDataModal extends Component {
constructor(props) {
super(props);
this.state = {
loading: false,
condition: []
};
}
componentDidMount() {
this.getLedgerList();
}
componentWillReceiveProps(nextProps, nextContext) {
if (nextProps.visible !== this.props.visible && nextProps.visible) this.handleResetForm();
}
getLedgerList = () => {
const { attendanceStore: { refenceform } } = this.props;
getLedgerList().then(({ status, data }) => {
if (status) {
this.setState({
condition: _.map(reFrenceConditions, (item) => {
const { items } = item;
return {
...item,
items: _.map(items, child => {
const { domkey } = child;
if (domkey[0] === "salarySobId") {
return { ...child, options: _.map(data, it => ({ key: it.id, showname: it.content })) };
}
return { ...child };
})
};
})
}, () => refenceform.initFormFields(this.state.condition));
}
});
};
/*
* Author: 黎永顺
* Description: 同步考勤数据
* Params:
* Date: 2023/3/1
*/
handleSubmitFields = () => {
const { attendanceStore: { refenceform }, onCancel } = this.props;
refenceform.validateForm().then(f => {
if (f.isValid) {
const payload = refenceform.getFormParams();
const checkPayload = { salaryYearMonthStr: payload.salaryYearMonth, salarySobId: payload.salarySobId };
this.setState({ loading: true });
checkOperation(checkPayload).then(({ status, errormsg: errormessage }) => {
if (status) {
syncAttendanceRefer(payload).then(({ status, errormsg }) => {
this.setState({ loading: false });
if (status) {
message.success("同步成功");
onCancel(true);
} else {
message.error(errormsg || "同步失败");
}
}).catch(() => this.setState({ loading: false }));
} else {
this.setState({ loading: false });
message.error(errormessage);
}
}).catch(() => this.setState({ loading: false }));
} else {
f.showErrors();
}
});
};
handleResetForm = () => {
const { attendanceStore: { refenceform } } = this.props;
refenceform.resetForm();
};
render() {
const { condition, loading } = this.state;
const { attendanceStore: { refenceform } } = this.props;
const buttons = [
<Button type="primary" onClick={this.handleSubmitFields} loading={loading}>同步</Button>
];
return (
<WeaDialog
{...this.props} style={{ width: 440, height: 156 }}
buttons={buttons} hasScroll initLoadCss
className="modalWrapper"
>
{getSearchs(refenceform, condition, 1)}
</WeaDialog>
);
}
}
export default AttendanceRefrenceDataModal;

View File

@ -3,6 +3,10 @@
width: 100%; width: 100%;
} }
.wea-date-picker {
width: 100%;
}
.wea-select { .wea-select {
display: inline-block; display: inline-block;
position: relative; position: relative;
@ -17,3 +21,33 @@
.attendanceFormWrapper { .attendanceFormWrapper {
padding: 0; padding: 0;
} }
.attendanceSlideWrapper {
.wea-slide-modal-title {
height: initial;
line-height: initial;
text-align: left;
}
.rodal-close {
z-index: 99;
top: 10px !important;
}
}
@media (min-width: 1260px) {
.attendanceSlideWrapper {
.reqTopWrapper .wea-new-top-req-title > div:first-child > div {
max-width: 100% !important;
}
}
}
@media screen and (min-width: 1060px) and (max-width: 1260px) {
.attendanceSlideWrapper {
.reqTopWrapper .wea-new-top-req-title > div:first-child > div {
max-width: calc(100% - 96px) !important;
}
}
}

View File

@ -62,6 +62,11 @@ class Index extends Component {
columns: [], slideDataSource: [], importResult: [] columns: [], slideDataSource: [], importResult: []
}); });
} }
handleQuoteAttendanceData= ()=>{
this.attendanceTableRef.handleQuoteAttendanceData({
visible: true, title: "引用考勤数据"
});
}
render() { render() {
const { selectedKey, salaryMonth, fieldName } = this.state; const { selectedKey, salaryMonth, fieldName } = this.state;
@ -71,7 +76,7 @@ class Index extends Component {
{ title: "字段管理", viewcondition: "FIELD" } { title: "字段管理", viewcondition: "FIELD" }
]; ];
const buttons = selectedKey === "DATA" ? [ const buttons = selectedKey === "DATA" ? [
<Button type="primary">引用</Button>, <Button type="primary" onClick={this.handleQuoteAttendanceData}>引用</Button>,
<Button type="ghost" onClick={this.handleImportAttendanceData}>导入</Button> <Button type="ghost" onClick={this.handleImportAttendanceData}>导入</Button>
] : [<Button type="primary" onClick={this.handleAddAttendFileds}>新建</Button>]; ] : [<Button type="primary" onClick={this.handleAddAttendFileds}>新建</Button>];
return ( return (

View File

@ -4,4 +4,5 @@ import { WeaForm } from "comsMobx";
export class AttendanceStore { export class AttendanceStore {
@observable form = new WeaForm(); @observable form = new WeaForm();
@observable refenceform = new WeaForm();
} }