Merge branch 'feature/2.19.1.2501.01-考勤数据编辑' into custom/西部信托0401

# Conflicts:
#	pc4mobx/hrmSalary/pages/dataAcquisition/attendance/components/attendanceDataComp.js
#	pc4mobx/hrmSalary/pages/dataAcquisition/attendance/index.js
This commit is contained in:
lys 2025-06-12 17:03:15 +08:00
commit c765d95892
5 changed files with 106 additions and 50 deletions

View File

@ -73,6 +73,10 @@ export const importAttendQuoteData = (params) => {
export const viewAttendQuote = (params) => { export const viewAttendQuote = (params) => {
return postFetch("/api/bs/hrmsalary/attendQuote/view", params); return postFetch("/api/bs/hrmsalary/attendQuote/view", params);
}; };
// 批量删除考勤详情
export const batchDeleteData = (params) => {
return postFetch("/api/bs/hrmsalary/attendQuote/batchDeleteData", params);
};
// 根据所属月和账套获取周期 // 根据所属月和账套获取周期
export const getSalaryCycleAndAttendCycle = (params) => { export const getSalaryCycleAndAttendCycle = (params) => {

View File

@ -26,6 +26,7 @@ import SelectItemsWrapper from "../../../../components/selectItemsModal/selectIt
import AttendanceRefrenceDataModal from "./attendanceRefrenceDataModal"; import AttendanceRefrenceDataModal from "./attendanceRefrenceDataModal";
import AttendanceDataViewSlide from "./attendanceDataViewSlide"; import AttendanceDataViewSlide from "./attendanceDataViewSlide";
import { postFetch } from "../../../../util/request"; import { postFetch } from "../../../../util/request";
import { calcPageNo } from "../../../../util";
const getLabel = WeaLocaleProvider.getLabel; const getLabel = WeaLocaleProvider.getLabel;
@ -33,17 +34,8 @@ class AttendanceDataComp extends Component {
constructor(props) { constructor(props) {
super(props); super(props);
this.state = { this.state = {
loading: { loading: { query: false, headset: false },
query: false, dataSource: [], columns: [], pageInfo: { current: 1, pageSize: 10, total: 0 },
headset: false
},
dataSource: [],
columns: [],
pageInfo: {
current: 1,
pageSize: 10,
total: 0
},
importData: { visible: false, params: {} }, importData: { visible: false, params: {} },
importFormPayload: { importFormPayload: {
salaryYearMonth: moment().format("YYYY-MM"), salarySobList: [], salaryYearMonth: moment().format("YYYY-MM"), salarySobList: [],
@ -134,15 +126,24 @@ class AttendanceDataComp extends Component {
} }
}); });
}; };
handleDeleteAttendanceData = ({ id }) => { handleDeleteAttendanceData = (payload) => {
Modal.confirm({ Modal.confirm({
title: "信息确认", title: "信息确认",
content: "确认要删除吗?", content: "确认要删除吗?",
onOk: () => { onOk: () => {
deleteAttendance([id]).then(({ status, errormsg }) => { const { pageInfo } = this.state;
deleteAttendance(payload).then(({ status, errormsg }) => {
if (status) { if (status) {
message.success("删除成功"); message.success("删除成功");
this.getAttendanceList(); this.setState({
pageInfo: {
...this.state.pageInfo,
current: calcPageNo(pageInfo.total, pageInfo.current, 10, payload.length)
}
}, () => {
this.getAttendanceList();
this.props.onChangeSelectedRowKeys([]);
});
} else { } else {
message.error(errormsg || "删除失败"); message.error(errormsg || "删除失败");
} }
@ -288,7 +289,7 @@ class AttendanceDataComp extends Component {
dataSource, columns, pageInfo, loading, importData, importFormPayload, fieldSetPayload, dataSource, columns, pageInfo, loading, importData, importFormPayload, fieldSetPayload,
attendanceReferencePayload, attendanceViewPayload attendanceReferencePayload, attendanceViewPayload
} = this.state; } = this.state;
const { salaryYearMonth } = this.props; const { salaryYearMonth, selectedRowKeys, onChangeSelectedRowKeys } = this.props;
const pagination = { const pagination = {
...pageInfo, ...pageInfo,
showTotal: total => `${total}`, showTotal: total => `${total}`,
@ -306,6 +307,7 @@ class AttendanceDataComp extends Component {
}, () => this.getAttendanceList({ salaryYearMonth: _.compact(salaryYearMonth) })); }, () => this.getAttendanceList({ salaryYearMonth: _.compact(salaryYearMonth) }));
} }
}; };
const rowSelection = { selectedRowKeys, onChange: onChangeSelectedRowKeys };
return ( return (
<React.Fragment> <React.Fragment>
<WeaTable <WeaTable
@ -323,7 +325,7 @@ class AttendanceDataComp extends Component {
{opts.includes("admin") && {opts.includes("admin") &&
<React.Fragment> <React.Fragment>
<a href="javascript: void(0);" style={{ marginRight: 10 }} <a href="javascript: void(0);" style={{ marginRight: 10 }}
onClick={() => this.handleDeleteAttendanceData(record)}>删除</a> onClick={() => this.handleDeleteAttendanceData([record.id])}>删除</a>
<Dropdown <Dropdown
overlay={ overlay={
<Menu> <Menu>
@ -355,7 +357,7 @@ class AttendanceDataComp extends Component {
); );
} }
} }
]} ]} rowSelection={rowSelection} rowKey="id"
dataSource={dataSource} pagination={pagination} loading={loading.query}/> dataSource={dataSource} pagination={pagination} loading={loading.query}/>
{/* 考勤引用导入 */} {/* 考勤引用导入 */}
<ImportModal {...importData} importFormPayload={importFormPayload} onCancel={this.handleFinish} <ImportModal {...importData} importFormPayload={importFormPayload} onCancel={this.handleFinish}

View File

@ -6,10 +6,11 @@
*/ */
import React, { Component } from "react"; import React, { Component } from "react";
import { WeaInputSearch, WeaLocaleProvider, WeaSlideModal, WeaTop } from "ecCom"; import { WeaInputSearch, WeaLocaleProvider, WeaSlideModal, WeaTop } from "ecCom";
import { viewAttendQuote } from "../../../../apis/attendance"; import { batchDeleteData, viewAttendQuote } from "../../../../apis/attendance";
import AttendanceDataEditSlide from "./attendanceDataEditSlide"; import AttendanceDataEditSlide from "./attendanceDataEditSlide";
import { Button, Spin } from "antd"; import { Button, message, Modal, Spin } from "antd";
import "./index.less"; import "./index.less";
import { calcPageNo } from "../../../../util";
const { getLabel } = WeaLocaleProvider; const { getLabel } = WeaLocaleProvider;
@ -17,7 +18,7 @@ class AttendanceDataViewSlide extends Component {
constructor(props) { constructor(props) {
super(props); super(props);
this.state = { this.state = {
loading: { query: false }, keyword: "", dataSource: [], loading: { query: false, del: false }, keyword: "", dataSource: [], selectedRowKeys: [],
pageInfo: { current: 1, pageSize: 10, total: 0 }, attendanceSlide: { visible: false, record: {} } pageInfo: { current: 1, pageSize: 10, total: 0 }, attendanceSlide: { visible: false, record: {} }
}; };
} }
@ -40,6 +41,10 @@ class AttendanceDataViewSlide extends Component {
case "EDIT": case "EDIT":
this.setState({ attendanceSlide: { visible: true, record: params } }); this.setState({ attendanceSlide: { visible: true, record: params } });
break; break;
case "CHECKBOX":
const { selectedRowKeys } = params;
this.setState({ selectedRowKeys });
break;
default: default:
break; break;
} }
@ -52,13 +57,12 @@ class AttendanceDataViewSlide extends Component {
this.viewAttendQuote({}, nextProps); this.viewAttendQuote({}, nextProps);
} else if (nextProps.visible !== this.props.visible && !nextProps.visible) { } else if (nextProps.visible !== this.props.visible && !nextProps.visible) {
document.querySelector(".attendanceRefWrapper").classList.remove("zIndex0-attendance"); document.querySelector(".attendanceRefWrapper").classList.remove("zIndex0-attendance");
this.setState({ pageInfo: { current: 1, pageSize: 10, total: 0 } }); this.setState({ selectedRowKeys: [], pageInfo: { current: 1, pageSize: 10, total: 0 } });
} }
} }
viewAttendQuote = (extraPayload = {}, props) => { viewAttendQuote = (extraPayload = {}, props) => {
const { loading, pageInfo, keyword } = this.state; const { loading, pageInfo, keyword, selectedRowKeys } = this.state, { attendQuoteId } = props || this.props;
const { attendQuoteId } = props || this.props;
this.setState({ loading: { ...loading, query: true } }); this.setState({ loading: { ...loading, query: true } });
viewAttendQuote({ ...pageInfo, attendQuoteId, keyword, ...extraPayload }).then(({ status, data }) => { viewAttendQuote({ ...pageInfo, attendQuoteId, keyword, ...extraPayload }).then(({ status, data }) => {
this.setState({ loading: { ...loading, query: false } }); this.setState({ loading: { ...loading, query: false } });
@ -67,7 +71,8 @@ class AttendanceDataViewSlide extends Component {
this.setState({ this.setState({
pageInfo: { ...pageInfo, current, pageSize, total }, dataSource pageInfo: { ...pageInfo, current, pageSize, total }, dataSource
}, () => this.postMessageToChild({ }, () => this.postMessageToChild({
pageInfo: this.state.pageInfo, dataSource, showRowSelection: false, unitTableType: "attendanceView", pageInfo: this.state.pageInfo, dataSource, showRowSelection: true, unitTableType: "attendanceView",
selectedRowKeys,
columns: [ columns: [
..._.map(columns, (o, i) => ({ ...o, width: 150, fixed: i === 0 ? "left" : false })), ..._.map(columns, (o, i) => ({ ...o, width: 150, fixed: i === 0 ? "left" : false })),
{ {
@ -98,12 +103,38 @@ class AttendanceDataViewSlide extends Component {
} }
this.handleDebounce(); this.handleDebounce();
}; };
batchDeleteData = () => {
Modal.confirm({
title: getLabel(111, "信息确认"),
content: getLabel(111, "确认要删除吗?"),
onOk: () => {
const { selectedRowKeys, pageInfo, loading } = this.state;
this.setState({ loading: { ...loading, del: true } });
batchDeleteData({ attendQuoteDataIds: selectedRowKeys }).then(({ status, errormsg }) => {
if (status) {
message.success(getLabel(111, "操作成功!"));
this.setState({
selectedRowKeys: [], loading: { ...loading, del: false },
pageInfo: {
...pageInfo,
current: calcPageNo(pageInfo.total, pageInfo.current, 10, selectedRowKeys.length)
}
}, () => this.viewAttendQuote());
} else {
message.error(errormsg);
}
});
}
});
};
render() { render() {
const { showOperateBtn, salaryYearMonth, ...extra } = this.props; const { showOperateBtn, salaryYearMonth, ...extra } = this.props;
const { loading, keyword, attendanceSlide } = this.state; const { loading, keyword, attendanceSlide, selectedRowKeys } = this.state;
const btns = [ const btns = [
<Button type="primary" onClick={this.handleExportAttendQuote}>{getLabel(81272, "导出全部")}</Button>, <Button type="primary" onClick={this.handleExportAttendQuote}>{getLabel(81272, "导出全部")}</Button>,
<Button type="ghost" disabled={_.isEmpty(selectedRowKeys)}
onClick={this.batchDeleteData}>{getLabel(111, "批量删除")}</Button>,
<WeaInputSearch <WeaInputSearch
value={keyword} placeholder={getLabel(543380, "请输入姓名/部门/工号/手机号")} value={keyword} placeholder={getLabel(543380, "请输入姓名/部门/工号/手机号")}
onChange={keyword => this.setState({ keyword })} onChange={keyword => this.setState({ keyword })}
@ -115,7 +146,7 @@ class AttendanceDataViewSlide extends Component {
direction="right" title={ direction="right" title={
<WeaTop title={getLabel(525196, "考勤数据")} icon={<i className="icon-coms-fa"/>} <WeaTop title={getLabel(525196, "考勤数据")} icon={<i className="icon-coms-fa"/>}
iconBgcolor="#F14A2D" iconBgcolor="#F14A2D"
buttons={showOperateBtn ? btns : btns.slice(1)}/> buttons={showOperateBtn ? btns : btns.slice(2)}/>
} }
content={ content={
<div className="attendance-slide-body"> <div className="attendance-slide-body">

View File

@ -23,7 +23,7 @@ class Index extends Component {
constructor(props) { constructor(props) {
super(props); super(props);
this.state = { this.state = {
fieldName: "", selectedKey: "DATA", salaryMonth: [], fieldName: "", selectedKey: "DATA", salaryMonth: [], selectedRowKeys: [],
logDialogVisible: false, filterConditions: "[]" logDialogVisible: false, filterConditions: "[]"
}; };
} }
@ -35,25 +35,33 @@ class Index extends Component {
* Date: 2023/2/24 * Date: 2023/2/24
*/ */
getAttendanceDataScreen = () => { getAttendanceDataScreen = () => {
const { salaryMonth } = this.state; const { salaryMonth, selectedRowKeys } = this.state, { taxAgentStore: { showOperateBtn } } = this.props;
const [value1 = "", value2 = ""] = salaryMonth; const [value1 = "", value2 = ""] = salaryMonth;
return <WeaFormItem label="薪资所属月" labelCol={{ span: 2 }} wrapperCol={{ span: 22 }}> return <div className="attendDataQuery-container">
<MonthPicker <WeaFormItem label="薪资所属月" labelCol={{ span: 2 }} wrapperCol={{ span: 22 }}>
value={value1} format="YYYY-MM" <MonthPicker
disabledDate={(current) => { value={value1} format="YYYY-MM"
return current && value2 && current.getTime() > new Date(value2).getTime(); disabledDate={(current) => {
}} return current && value2 && current.getTime() > new Date(value2).getTime();
onChange={(val) => this.handleChangeSalaryMonth([val ? moment(val).format("YYYY-MM") : "", value2])} }}
/> onChange={(val) => this.handleChangeSalaryMonth([val ? moment(val).format("YYYY-MM") : "", value2])}
<span className="to"></span> />
<MonthPicker <span className="to"></span>
value={value2} format="YYYY-MM" <MonthPicker
disabledDate={(current) => { value={value2} format="YYYY-MM"
return current && value1 && current.getTime() < new Date(value1).getTime(); disabledDate={(current) => {
}} return current && value1 && current.getTime() < new Date(value1).getTime();
onChange={(val) => this.handleChangeSalaryMonth([value1, val ? moment(val).format("YYYY-MM") : ""])} }}
/> onChange={(val) => this.handleChangeSalaryMonth([value1, val ? moment(val).format("YYYY-MM") : ""])}
</WeaFormItem>; />
</WeaFormItem>
<div>{
showOperateBtn &&
<Button type="primary" disabled={_.isEmpty(selectedRowKeys)}
onClick={() => this.attendanceTableRef.handleDeleteAttendanceData(selectedRowKeys)}>{getLabel(111, "批量删除")}</Button>
}
</div>
</div>;
}; };
handleChangeSalaryMonth = (salaryMonth) => this.setState({ salaryMonth }, () => this.attendanceTableRef.getAttendanceList({ salaryYearMonth: _.compact(this.state.salaryMonth) })); handleChangeSalaryMonth = (salaryMonth) => this.setState({ salaryMonth }, () => this.attendanceTableRef.getAttendanceList({ salaryYearMonth: _.compact(this.state.salaryMonth) }));
handleAddAttendFileds = () => this.fieldMangRef.handleTriggerAttendFileds(); handleAddAttendFileds = () => this.fieldMangRef.handleTriggerAttendFileds();
@ -77,7 +85,7 @@ class Index extends Component {
}; };
render() { render() {
const { selectedKey, salaryMonth, fieldName, logDialogVisible, filterConditions } = this.state; const { selectedKey, salaryMonth, fieldName, logDialogVisible, filterConditions, selectedRowKeys } = this.state;
const { taxAgentStore: { PageAndOptAuth } } = this.props; const { taxAgentStore: { PageAndOptAuth } } = this.props;
const showOperateBtn = PageAndOptAuth.opts.includes("admin"); const showOperateBtn = PageAndOptAuth.opts.includes("admin");
const topTab = [ const topTab = [
@ -117,6 +125,8 @@ class Index extends Component {
<AttendanceDataComp <AttendanceDataComp
ref={dom => this.attendanceTableRef = dom} ref={dom => this.attendanceTableRef = dom}
salaryYearMonth={salaryMonth} salaryYearMonth={salaryMonth}
selectedRowKeys={selectedRowKeys}
onChangeSelectedRowKeys={v => this.setState({ selectedRowKeys: v })}
onFilterLog={(type, targetid) => this.onDropMenuClick(type, targetid)} onFilterLog={(type, targetid) => this.onDropMenuClick(type, targetid)}
/> : /> :
<FieldMangComp <FieldMangComp

View File

@ -3,12 +3,17 @@
display: flex; display: flex;
flex-direction: column; flex-direction: column;
.wea-new-top-req-content { .attendDataQuery-container {
& > .wea-form-item { display: flex;
align-items: center;
justify-content: space-between;
background: #FFF;
margin: 8px 16px 0 16px;
.wea-form-item {
height: 46px; height: 46px;
line-height: 46px; line-height: 46px;
background: #FFF; flex: 1;
margin: 8px 16px 0 16px;
.wea-form-item-label { .wea-form-item-label {
line-height: 46px !important; line-height: 46px !important;
@ -19,6 +24,10 @@
padding: 0 10px padding: 0 10px
} }
} }
& > div:last-child {
padding-right: 8px;
}
} }
.tableWrapper { .tableWrapper {