305 lines
9.6 KiB
JavaScript
305 lines
9.6 KiB
JavaScript
import { Connect } from "@cqsjjb/jjb-dva-runtime";
|
||
import { Button, DatePicker, Descriptions, Form, Input, message, Modal, Select } from "antd";
|
||
import { useEffect, useState } from "react";
|
||
import AddIcon from "zy-react-library/components/Icon/AddIcon";
|
||
import PageLayout from "@cqsjjb/jjb-react-admin-component/PageLayout";
|
||
import Search from "zy-react-library/components/Search";
|
||
import Table from "zy-react-library/components/Table";
|
||
import Upload from "zy-react-library/components/Upload";
|
||
import useTable from "zy-react-library/hooks/useTable";
|
||
import { asId } from "~/api/enterpriseInfo/idUtil";
|
||
import { NS_STAFF_INFO, NS_STAFF_RESIGNATION_APPLY } from "~/enumerate/namespace";
|
||
import { safeListRequest, safeRequest } from "~/utils";
|
||
import { formSelectField, getResignAuditStatusLabel } from "~/utils/enterpriseForm";
|
||
import { DEFAULT_UPLOAD_FILE_URL, mockUploadFileList, resolveUploadFileId } from "~/utils/mockUpload";
|
||
|
||
|
||
const RESIGN_AUDIT_STATUS = { 0: "未审核", 1: "已审核", 2: "已退回" };
|
||
|
||
function ResignationApplyPage(props) {
|
||
const [addModalOpen, setAddModalOpen] = useState(false);
|
||
const [viewModalOpen, setViewModalOpen] = useState(false);
|
||
const [currentId, setCurrentId] = useState("");
|
||
const [staffOptions, setStaffOptions] = useState([]);
|
||
const [searchForm] = Form.useForm();
|
||
|
||
const { tableProps, getData } = useTable(safeListRequest(props.staffResignationApplyList), { form: searchForm });
|
||
|
||
useEffect(() => {
|
||
getData();
|
||
}, []);
|
||
|
||
useEffect(() => {
|
||
let cancelled = false;
|
||
props.staffInfoList?.({ pageIndex: 1, pageSize: 500 }).then((res) => {
|
||
if (!cancelled) {
|
||
setStaffOptions((res?.data || []).map((s) => ({
|
||
label: `${s.staffName}(${s.account})`,
|
||
value: asId(s.id),
|
||
staffName: s.staffName,
|
||
account: s.account,
|
||
})));
|
||
}
|
||
}).catch((err) => {
|
||
console.warn("[ResignationApply] load staff options failed:", err);
|
||
});
|
||
return () => {
|
||
cancelled = true;
|
||
};
|
||
}, []);
|
||
|
||
return (
|
||
<PageLayout
|
||
title={
|
||
<div>
|
||
<span>离职申请管理</span>
|
||
<div className="pageLayout-extra">
|
||
机构管理员在人员信息管理页面进行相应的修改操作
|
||
</div>
|
||
</div>
|
||
}
|
||
>
|
||
<Search
|
||
form={searchForm}
|
||
options={[
|
||
{ name: "likeStaffName", label: "姓名", placeholder: "请输入姓名", colProps: { xs: 24, sm: 12, md: 8, lg: 6 } },
|
||
formSelectField(
|
||
"auditStatus",
|
||
"离职申请审核状态",
|
||
Object.entries(RESIGN_AUDIT_STATUS).map(([value, label]) => ({ label, value: Number(value) })),
|
||
{ colProps: { xs: 24, sm: 12, md: 8, lg: 8 }, placeholder: "请选择审核状态" },
|
||
),
|
||
]}
|
||
onFinish={getData}
|
||
/>
|
||
<Table
|
||
toolBarRender={() => (
|
||
<Button
|
||
type="primary"
|
||
icon={<AddIcon />}
|
||
onClick={() => {
|
||
setCurrentId("");
|
||
setAddModalOpen(true);
|
||
}}
|
||
>
|
||
新增离职申请
|
||
</Button>
|
||
)}
|
||
columns={[
|
||
{ title: "账户", dataIndex: "account" },
|
||
{ title: "姓名", dataIndex: "applicantName" },
|
||
{ title: "部门", dataIndex: "deptName" },
|
||
{ title: "申请时间", dataIndex: "applyTime" },
|
||
{
|
||
title: "离职申请审核状态",
|
||
dataIndex: "auditStatus",
|
||
render: (_, record) => getResignAuditStatusLabel(record),
|
||
},
|
||
{
|
||
title: "操作",
|
||
width: 100,
|
||
render: (_, record) => (
|
||
<Button
|
||
type="link"
|
||
onClick={() => {
|
||
setCurrentId(asId(record.id));
|
||
setViewModalOpen(true);
|
||
}}
|
||
>
|
||
查看
|
||
</Button>
|
||
),
|
||
},
|
||
]}
|
||
{...tableProps}
|
||
/>
|
||
|
||
{addModalOpen && (
|
||
<AddModal
|
||
open={addModalOpen}
|
||
staffOptions={staffOptions}
|
||
requestAdd={props.staffResignationApplyAdd}
|
||
onCancel={() => setAddModalOpen(false)}
|
||
onSuccess={getData}
|
||
/>
|
||
)}
|
||
{viewModalOpen && (
|
||
<ViewModal
|
||
open={viewModalOpen}
|
||
currentId={currentId}
|
||
requestDetails={props.staffResignationApplyInfo}
|
||
onCancel={() => {
|
||
setViewModalOpen(false);
|
||
setCurrentId("");
|
||
}}
|
||
/>
|
||
)}
|
||
</PageLayout>
|
||
);
|
||
}
|
||
|
||
function AddModal({ open, staffOptions, requestAdd, onCancel, onSuccess }) {
|
||
const [form] = Form.useForm();
|
||
const [submitting, setSubmitting] = useState(false);
|
||
|
||
const handleCancel = () => {
|
||
form.resetFields();
|
||
onCancel();
|
||
};
|
||
|
||
const onApplicantChange = (personnelId) => {
|
||
const staff = staffOptions.find((s) => String(s.value) === String(personnelId));
|
||
form.setFieldsValue({
|
||
applicantName: staff?.staffName || "",
|
||
});
|
||
};
|
||
|
||
const handleSubmit = async (values) => {
|
||
try {
|
||
setSubmitting(true);
|
||
const staff = staffOptions.find((s) => String(s.value) === String(values.personnelId));
|
||
values.applicantName = staff?.staffName || values.applicantName;
|
||
values.attachmentId = resolveUploadFileId(values.resignReport);
|
||
const res = await requestAdd(values);
|
||
if (res?.success !== false) {
|
||
message.success("提交成功");
|
||
handleCancel();
|
||
onSuccess();
|
||
}
|
||
else {
|
||
message.error(res?.message || "提交失败");
|
||
}
|
||
}
|
||
finally {
|
||
setSubmitting(false);
|
||
}
|
||
};
|
||
|
||
return (
|
||
<Modal
|
||
open={open}
|
||
destroyOnClose
|
||
title="添加离职申请"
|
||
width={720}
|
||
confirmLoading={submitting}
|
||
onCancel={handleCancel}
|
||
onOk={form.submit}
|
||
>
|
||
<Form form={form} layout="vertical" onFinish={handleSubmit}>
|
||
<Form.Item
|
||
name="personnelId"
|
||
label="申请人"
|
||
rules={[{ required: true, message: "请选择申请人" }]}
|
||
>
|
||
<Select
|
||
showSearch
|
||
placeholder="请选择申请人"
|
||
options={staffOptions}
|
||
optionFilterProp="label"
|
||
onChange={onApplicantChange}
|
||
/>
|
||
</Form.Item>
|
||
<Form.Item name="applicantName" hidden>
|
||
<Input />
|
||
</Form.Item>
|
||
<Form.Item
|
||
name="applyTime"
|
||
label="申请时间"
|
||
rules={[{ required: true, message: "请选择申请时间" }]}
|
||
>
|
||
<DatePicker showTime style={{ width: "100%" }} />
|
||
</Form.Item>
|
||
<Form.Item
|
||
name="expectedLeaveDate"
|
||
label="预计离职日期"
|
||
rules={[{ required: true, message: "请选择预计离职日期" }]}
|
||
>
|
||
<DatePicker style={{ width: "100%" }} />
|
||
</Form.Item>
|
||
<Form.Item
|
||
name="leaveReason"
|
||
label="离职原因"
|
||
rules={[{ required: true, message: "请输入离职原因" }]}
|
||
>
|
||
<Input.TextArea rows={3} placeholder="请输入离职原因" />
|
||
</Form.Item>
|
||
<Form.Item name="remark" label="备注">
|
||
<Input.TextArea rows={2} placeholder="请输入备注" />
|
||
</Form.Item>
|
||
<Form.Item
|
||
name="resignReport"
|
||
label="离职通知报告"
|
||
rules={[{ required: true, message: "请上传离职通知报告" }]}
|
||
valuePropName="fileList"
|
||
getValueFromEvent={(e) => e?.fileList}
|
||
initialValue={mockUploadFileList("离职通知报告.pdf")}
|
||
>
|
||
<Upload
|
||
accept=".pdf"
|
||
maxCount={1}
|
||
tip="联调阶段默认通过,使用固定文件地址"
|
||
/>
|
||
</Form.Item>
|
||
</Form>
|
||
</Modal>
|
||
);
|
||
}
|
||
|
||
function ViewModal({ open, currentId, requestDetails, onCancel }) {
|
||
const [info, setInfo] = useState({});
|
||
const [detailLoading, setDetailLoading] = useState(false);
|
||
|
||
useEffect(() => {
|
||
if (!open || !currentId) {
|
||
setInfo({});
|
||
return;
|
||
}
|
||
let cancelled = false;
|
||
setDetailLoading(true);
|
||
safeRequest(requestDetails, { id: currentId }).then((res) => {
|
||
if (!cancelled) {
|
||
const data = res?.data || {};
|
||
setInfo({
|
||
...data,
|
||
resignReport: data.attachmentId
|
||
? [{ name: "离职通知报告.pdf", fileName: "离职通知报告.pdf", url: data.attachmentId || DEFAULT_UPLOAD_FILE_URL }]
|
||
: [],
|
||
});
|
||
}
|
||
}).finally(() => {
|
||
if (!cancelled) {
|
||
setDetailLoading(false);
|
||
}
|
||
});
|
||
return () => {
|
||
cancelled = true;
|
||
};
|
||
}, [open, currentId]);
|
||
|
||
return (
|
||
<Modal
|
||
open={open}
|
||
destroyOnClose
|
||
title="查看离职申请"
|
||
width={720}
|
||
loading={detailLoading}
|
||
cancelText="返回"
|
||
okButtonProps={{ style: { display: "none" } }}
|
||
onCancel={onCancel}
|
||
>
|
||
<Descriptions bordered column={1} labelStyle={{ width: 120 }}>
|
||
<Descriptions.Item label="申请人">{info.applicantName}</Descriptions.Item>
|
||
<Descriptions.Item label="申请时间">{info.applyTime}</Descriptions.Item>
|
||
<Descriptions.Item label="预计离职日期">{info.expectedLeaveDate}</Descriptions.Item>
|
||
<Descriptions.Item label="离职原因">{info.leaveReason}</Descriptions.Item>
|
||
<Descriptions.Item label="备注">{info.remark}</Descriptions.Item>
|
||
<Descriptions.Item label="离职通知报告">
|
||
{info.resignReport?.[0]?.fileName || info.resignReport?.[0]?.name || "-"}
|
||
</Descriptions.Item>
|
||
</Descriptions>
|
||
</Modal>
|
||
);
|
||
}
|
||
|
||
export default Connect([NS_STAFF_RESIGNATION_APPLY, NS_STAFF_INFO], true)(ResignationApplyPage);
|