safety-eval-service-frontend/src/pages/Container/EnterpriseInfo/ResignationApply/index.js

305 lines
9.6 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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);