356 lines
10 KiB
JavaScript
356 lines
10 KiB
JavaScript
import { Connect } from "@cqsjjb/jjb-dva-runtime";
|
||
import {
|
||
Button,
|
||
DatePicker,
|
||
Descriptions,
|
||
Form,
|
||
Input,
|
||
message,
|
||
Modal,
|
||
Select,
|
||
Table,
|
||
Tag,
|
||
} from "antd";
|
||
import TableAction from "@cqsjjb/jjb-react-admin-component/TableAction";
|
||
import AttachmentUpload from "~/components/AttachmentUpload";
|
||
import { useEffect, useState } from "react";
|
||
import PageLayout from "@cqsjjb/jjb-react-admin-component/PageLayout";
|
||
import SearchForm from "@cqsjjb/jjb-react-admin-component/SearchForm";
|
||
import ControlWrapper from "@cqsjjb/jjb-react-admin-component/ControlWrapper";
|
||
import { AntdTableFuncControl } from "@cqsjjb/jjb-common-decorator/antd";
|
||
import { tools } from "@cqsjjb/jjb-common-lib";
|
||
import {
|
||
NS_STAFF_INFO,
|
||
NS_STAFF_RESIGNATION_APPLY,
|
||
} from "~/enumerate/namespace";
|
||
import {
|
||
RESIGN_AUDIT_STATUS_LABEL,
|
||
AUDIT_STATUS_COLOR,
|
||
} from "~/utils/enterpriseForm";
|
||
|
||
const { router } = tools;
|
||
|
||
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 { staffResignationApply } = props;
|
||
const {
|
||
staffResignationApplyList: dataSource,
|
||
staffResignationApplyTotal: total,
|
||
staffResignationApplyLoading: loading,
|
||
} = staffResignationApply || {};
|
||
|
||
const handleSearch = () => {
|
||
props.staffResignationApplyList({ ...router.query });
|
||
};
|
||
|
||
useEffect(() => {
|
||
searchForm.setFieldsValue(router.query);
|
||
handleSearch();
|
||
}, []);
|
||
|
||
useEffect(() => {
|
||
let cancelled = false;
|
||
props
|
||
.staffInfoList?.({ current: 1, size: 500 })
|
||
.then((res) => {
|
||
if (!cancelled) {
|
||
setStaffOptions(
|
||
(res?.data || []).map((s) => ({
|
||
label: `${s.userName ?? s.staffName}(${s.account})`,
|
||
value: s.id,
|
||
staffName: s.userName ?? s.staffName,
|
||
account: s.account,
|
||
})),
|
||
);
|
||
}
|
||
})
|
||
.catch(() => {});
|
||
return () => {
|
||
cancelled = true;
|
||
};
|
||
}, []);
|
||
|
||
return (
|
||
<PageLayout
|
||
title={
|
||
<div>
|
||
<span>离职申请管理</span>
|
||
<div className="pageLayout-extra">
|
||
机构管理员在人员信息管理页面进行相应的修改操作
|
||
</div>
|
||
</div>
|
||
}
|
||
extra={
|
||
<Button
|
||
type="primary"
|
||
style={{ marginTop: 16 }}
|
||
onClick={() => {
|
||
setCurrentId("");
|
||
setAddModalOpen(true);
|
||
}}
|
||
>
|
||
新增离职申请
|
||
</Button>
|
||
}
|
||
>
|
||
<SearchForm
|
||
style={{ marginBottom: 24 }}
|
||
form={searchForm}
|
||
loading={loading}
|
||
formLine={[
|
||
<Form.Item key="applicantName" name="applicantName">
|
||
<ControlWrapper.Input
|
||
label="姓名"
|
||
placeholder="请输入"
|
||
allowClear
|
||
/>
|
||
</Form.Item>,
|
||
<Form.Item key="auditStatusCode" name="auditStatusCode">
|
||
<ControlWrapper.Select
|
||
label="离职申请审核状态"
|
||
placeholder="请选择"
|
||
allowClear
|
||
style={{ width: "100%" }}
|
||
>
|
||
{Object.entries(RESIGN_AUDIT_STATUS_LABEL).map(
|
||
([value, label]) => (
|
||
<Select.Option key={value} value={Number(value)}>
|
||
{label}
|
||
</Select.Option>
|
||
),
|
||
)}
|
||
</ControlWrapper.Select>
|
||
</Form.Item>,
|
||
]}
|
||
onReset={(value) => {
|
||
router.query = { ...value, current: 1, size: 10 };
|
||
handleSearch();
|
||
}}
|
||
onFinish={(value) => {
|
||
router.query = { ...value, current: 1, size: 10 };
|
||
handleSearch();
|
||
}}
|
||
/>
|
||
<Table
|
||
rowKey="id"
|
||
columns={[
|
||
{ title: "账户", dataIndex: "account", width: 140 },
|
||
{ title: "姓名", dataIndex: "applicantName", width: 100 },
|
||
{ title: "部门", dataIndex: "deptName", width: 160 },
|
||
{ title: "申请时间", dataIndex: "applyTime", width: 160 },
|
||
{
|
||
title: "离职申请审核状态",
|
||
dataIndex: "auditStatusCode",
|
||
width: 140,
|
||
render: (_, record) => {
|
||
const code = record.auditStatusCode ?? record.auditStatus;
|
||
const label = RESIGN_AUDIT_STATUS_LABEL[code] ?? "-";
|
||
return <Tag color={AUDIT_STATUS_COLOR[code]}>{label}</Tag>;
|
||
},
|
||
},
|
||
{
|
||
title: "操作",
|
||
width: 80,
|
||
render: (_, record) => (
|
||
<TableAction>
|
||
<Button
|
||
type="link"
|
||
size="small"
|
||
onClick={() => {
|
||
setCurrentId(record.id);
|
||
setViewModalOpen(true);
|
||
}}
|
||
>
|
||
查看
|
||
</Button>
|
||
</TableAction>
|
||
),
|
||
},
|
||
]}
|
||
dataSource={dataSource}
|
||
scroll={{ y: props.scrollY }}
|
||
loading={loading}
|
||
pagination={{
|
||
total,
|
||
showSizeChanger: true,
|
||
showQuickJumper: true,
|
||
showTotal: (t) => `共 ${t} 条`,
|
||
current: router.query.current || 1,
|
||
pageSize: router.query.size || 10,
|
||
onChange: (page, pageSize) => {
|
||
router.query = { ...router.query, current: page, size: pageSize };
|
||
handleSearch();
|
||
},
|
||
}}
|
||
/>
|
||
|
||
<AddModal
|
||
open={addModalOpen}
|
||
staffOptions={staffOptions}
|
||
requestAdd={props.staffResignationApplyAdd}
|
||
onCancel={() => setAddModalOpen(false)}
|
||
onSuccess={handleSearch}
|
||
/>
|
||
<ViewModal
|
||
open={viewModalOpen}
|
||
currentId={currentId}
|
||
requestDetail={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 handleSubmit = async () => {
|
||
try {
|
||
const values = await form.validateFields();
|
||
setSubmitting(true);
|
||
values.applyTime =
|
||
values.applyTime?.format?.("YYYY-MM-DD HH:mm:ss") || values.applyTime;
|
||
values.expectedResignDate =
|
||
values.expectedResignDate?.format?.("YYYY-MM-DD") ||
|
||
values.expectedResignDate;
|
||
values.reportFileUrl = values.reportFileUrl?.map?.((f) => f.url).filter(Boolean).join(",") || undefined;
|
||
const res = await requestAdd(values);
|
||
if (res?.success !== false) {
|
||
message.success("提交成功");
|
||
handleCancel();
|
||
onSuccess();
|
||
} else {
|
||
message.error(res?.message || "提交失败");
|
||
}
|
||
} catch {
|
||
// validation error
|
||
} finally {
|
||
setSubmitting(false);
|
||
}
|
||
};
|
||
|
||
return (
|
||
<Modal
|
||
open={open}
|
||
destroyOnHidden
|
||
title="添加离职申请"
|
||
width={720}
|
||
confirmLoading={submitting}
|
||
onCancel={handleCancel}
|
||
onOk={handleSubmit}
|
||
>
|
||
<Form form={form} layout="vertical">
|
||
<Form.Item
|
||
name="personnelId"
|
||
label="申请人"
|
||
rules={[{ required: true, message: "请选择申请人" }]}
|
||
>
|
||
<Select
|
||
showSearch
|
||
placeholder="请选择申请人"
|
||
options={staffOptions}
|
||
optionFilterProp="label"
|
||
/>
|
||
</Form.Item>
|
||
<Form.Item
|
||
name="applyTime"
|
||
label="申请时间"
|
||
rules={[{ required: true, message: "请选择申请时间" }]}
|
||
>
|
||
<DatePicker showTime style={{ width: "100%" }} />
|
||
</Form.Item>
|
||
<Form.Item
|
||
name="expectedResignDate"
|
||
label="预计离职日期"
|
||
rules={[{ required: true, message: "请选择预计离职日期" }]}
|
||
>
|
||
<DatePicker style={{ width: "100%" }} />
|
||
</Form.Item>
|
||
<Form.Item
|
||
name="resignReason"
|
||
label="离职原因"
|
||
rules={[{ required: true, message: "请输入离职原因" }]}
|
||
>
|
||
<Input.TextArea rows={3} placeholder="请输入离职原因" />
|
||
</Form.Item>
|
||
<Form.Item name="remark" label="备注">
|
||
<Input.TextArea rows={2} placeholder="请输入备注" />
|
||
</Form.Item>
|
||
<AttachmentUpload name="reportFileUrl" label="离职通知报告" maxCount={1} accept=".pdf" />
|
||
</Form>
|
||
</Modal>
|
||
);
|
||
}
|
||
|
||
function ViewModal({ open, currentId, requestDetail, onCancel }) {
|
||
const [info, setInfo] = useState({});
|
||
const [detailLoading, setDetailLoading] = useState(false);
|
||
|
||
useEffect(() => {
|
||
if (!open || !currentId) {
|
||
setInfo({});
|
||
return;
|
||
}
|
||
let cancelled = false;
|
||
setDetailLoading(true);
|
||
requestDetail({ id: currentId })
|
||
.then((res) => {
|
||
if (!cancelled) setInfo(res?.data || {});
|
||
})
|
||
.finally(() => {
|
||
if (!cancelled) setDetailLoading(false);
|
||
});
|
||
return () => {
|
||
cancelled = true;
|
||
};
|
||
}, [open, currentId]);
|
||
|
||
return (
|
||
<Modal
|
||
open={open}
|
||
destroyOnHidden
|
||
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.expectedResignDate}
|
||
</Descriptions.Item>
|
||
<Descriptions.Item label="离职原因">
|
||
{info.resignReason}
|
||
</Descriptions.Item>
|
||
<Descriptions.Item label="备注">{info.remark}</Descriptions.Item>
|
||
<Descriptions.Item label="离职通知报告">
|
||
{info.reportFileUrl || "-"}
|
||
</Descriptions.Item>
|
||
</Descriptions>
|
||
</Modal>
|
||
);
|
||
}
|
||
|
||
export default Connect(
|
||
[NS_STAFF_RESIGNATION_APPLY, NS_STAFF_INFO],
|
||
true,
|
||
)(AntdTableFuncControl(ResignationApplyPage));
|