safety-eval-service-frontend/src/pages/Container/Supervision/ExperManage/index.js

369 lines
10 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 React, { useEffect, useState } from "react";
import {
Button,
Descriptions,
Form,
Input,
message,
Modal,
Select,
Table,
} from "antd";
import TableAction from "@cqsjjb/jjb-react-admin-component/TableAction";
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 { Connect } from "@cqsjjb/jjb-dva-runtime";
import { NS_QUAL_EXPERT } from "~/enumerate/namespace";
import { GENDER_OPTIONS, GENDER_MAP } from "~/enumerate/constant";
import AttachmentUpload from "~/components/AttachmentUpload";
import { idCardRule } from "~/utils/validators";
const { router } = tools;
const ExperManage = (props) => {
const [searchForm] = Form.useForm();
const [editForm] = Form.useForm();
const [detailVisible, setDetailVisible] = useState(false);
const [editVisible, setEditVisible] = useState(false);
const [editingId, setEditingId] = useState(null);
const [submiting, setSubmiting] = useState(false);
const {
qualExpert,
queryExpertPage,
getExpertDetail,
saveExpert,
modifyExpert,
deleteExpert,
} = props;
const {
qualExpertList,
qualExpertTotal,
qualExpertLoading,
qualExpertDetail,
qualExpertDetailLoading,
} = qualExpert || {};
const getData = () => {
queryExpertPage({
...router.query,
current: router.query.current || 1,
size: router.query.size || 10,
});
};
const handleReset = (values) => {
router.query = {
...router.query,
...values,
current: 1,
size: 10,
};
getData();
};
useEffect(() => {
searchForm.setFieldsValue(router.query);
getData();
}, []);
// ─── 查看详情 ───
const openDetail = async (id) => {
setDetailVisible(true);
await getExpertDetail({ id });
};
// ─── 新增 / 编辑 ───
const openAdd = () => {
editForm.resetFields();
setEditingId(null);
setEditVisible(true);
};
const openEdit = async (id) => {
setEditingId(id);
setEditVisible(true);
const res = await getExpertDetail({ id });
if (res?.success !== false) {
const params = res.data;
if (params.certificate) {
params.certificate = JSON.parse(params.certificate);
}
editForm.setFieldsValue(params);
}
};
const handleEditSubmit = async () => {
const values = await editForm.validateFields();
setSubmiting(true);
const action = editingId ? modifyExpert : saveExpert;
const params = editingId ? { ...values, id: editingId } : values;
if (values.certificate) {
params.certificate = JSON.stringify(values.certificate);
}
const res = await action(params);
setSubmiting(false);
if (res?.success !== false) {
message.success(editingId ? "修改成功" : "新增成功");
setEditVisible(false);
getData();
}
};
// ─── 删除 ───
const handleDelete = (record) => {
Modal.confirm({
title: "确认删除",
content: `确认删除专家「${record.userName}」?此操作不可恢复。`,
okText: "确认删除",
okButtonProps: { danger: true },
cancelText: "取消",
onOk: async () => {
const res = await deleteExpert({ data: record.id });
if (res?.success !== false) {
message.success("删除成功");
getData();
}
},
});
};
// ─── 表格列 ───
const columns = [
{
title: "序号",
width: 60,
fixed: "left",
render: (_, __, index) => index + 1,
},
{ title: "姓名", dataIndex: "userName", width: 100 },
{ title: "账号", dataIndex: "account", width: 140 },
{
title: "性别",
dataIndex: "genderCode",
width: 70,
render: (code) => GENDER_MAP[code] || "--",
},
{ title: "身份证号", dataIndex: "idCardNo", width: 180 },
{
title: "操作",
width: 180,
fixed: "right",
render: (_, record) => (
<TableAction>
<Button
type="link"
size="small"
onClick={() => openDetail(record.id)}
>
查看
</Button>
<Button type="link" size="small" onClick={() => openEdit(record.id)}>
编辑
</Button>
<Button
type="link"
size="small"
danger
onClick={() => handleDelete(record)}
>
删除
</Button>
</TableAction>
),
},
];
return (
<PageLayout
title="专家管理"
extra={
<Button type="primary" onClick={openAdd}>
新增专家
</Button>
}
>
<SearchForm
style={{ marginBottom: 24 }}
form={searchForm}
loading={qualExpertLoading}
formLine={[
<Form.Item key="userName" name="userName">
<ControlWrapper.Input
label="姓名"
placeholder="请输入"
allowClear
/>
</Form.Item>,
<Form.Item key="account" name="account">
<ControlWrapper.Input
label="账号"
placeholder="请输入"
allowClear
/>
</Form.Item>,
<Form.Item key="genderCode" name="genderCode">
<ControlWrapper.Select
label="性别"
placeholder="请选择"
allowClear
style={{ width: "100%" }}
>
{GENDER_OPTIONS.map((item) => (
<Select.Option key={item.value} value={item.value}>
{item.label}
</Select.Option>
))}
</ControlWrapper.Select>
</Form.Item>,
<Form.Item key="idCardNo" name="idCardNo">
<ControlWrapper.Input
label="身份证号"
placeholder="请输入"
allowClear
/>
</Form.Item>,
]}
onReset={handleReset}
onFinish={(values) => {
router.query = {
...router.query,
...values,
current: 1,
size: 10,
};
getData();
}}
/>
<Table
rowKey="id"
columns={columns}
dataSource={qualExpertList}
scroll={{ y: props.scrollY }}
loading={qualExpertLoading}
pagination={{
total: qualExpertTotal,
showSizeChanger: true,
showQuickJumper: true,
showTotal: (total) => `${total}`,
current: router.query.current || 1,
pageSize: router.query.size || 10,
onChange: (page, pageSize) => {
router.query = { ...router.query, current: page, size: pageSize };
getData();
},
}}
/>
{/* 查看详情弹窗 */}
<Modal
title="专家详情"
open={detailVisible}
onCancel={() => setDetailVisible(false)}
footer={<Button onClick={() => setDetailVisible(false)}>关闭</Button>}
width={560}
>
<Descriptions
column={2}
bordered
size="small"
loading={qualExpertDetailLoading}
>
<Descriptions.Item label="姓名">
{qualExpertDetail?.userName || "--"}
</Descriptions.Item>
<Descriptions.Item label="账号">
{qualExpertDetail?.account || "--"}
</Descriptions.Item>
<Descriptions.Item label="性别">
{GENDER_MAP[qualExpertDetail?.genderCode] || "--"}
</Descriptions.Item>
<Descriptions.Item label="身份证号">
{qualExpertDetail?.idCardNo || "--"}
</Descriptions.Item>
<Descriptions.Item label="证书" span={2}>
{(Array.isArray(qualExpertDetail?.certificate)
? qualExpertDetail?.certificate
: JSON.parse(qualExpertDetail?.certificate || "[]")
)?.map((item) => (
<a key={item.id} href={item.url} target="_blank">
{item.name}
</a>
))}
</Descriptions.Item>
</Descriptions>
</Modal>
{/* 新增/编辑弹窗 */}
<Modal
title={editingId ? "编辑专家" : "新增专家"}
open={editVisible}
onCancel={() => setEditVisible(false)}
onOk={handleEditSubmit}
confirmLoading={submiting}
width={520}
>
<Form form={editForm} layout="vertical">
<Form.Item
name="userName"
label="姓名"
rules={[
{ required: true, message: "请输入姓名" },
{ max: 32, message: "姓名最多输入32个字符" },
]}
>
<Input placeholder="请输入" allowClear maxLength={32} />
</Form.Item>
<Form.Item
name="account"
label="账号"
rules={[
{ required: true, message: "请输入账号" },
{ max: 32, message: "账号最多输入32个字符" },
]}
>
<Input placeholder="请输入" allowClear maxLength={32} />
</Form.Item>
<Form.Item name="genderCode" label="性别">
<Select placeholder="请选择" allowClear style={{ width: "100%" }}>
{GENDER_OPTIONS.map((item) => (
<Select.Option key={item.value} value={item.value}>
{item.label}
</Select.Option>
))}
</Select>
</Form.Item>
<Form.Item
name="idCardNo"
label="身份证号"
rules={[idCardRule(), { max: 20, message: "身份证号最多输入20个字符" }]}
>
<Input placeholder="请输入" allowClear maxLength={20} />
</Form.Item>
<AttachmentUpload
name="certificate"
label="证书"
maxCount={10}
accept="image/*,.pdf"
extra="支持上传图片和PDF文件最多10个"
/>
</Form>
</Modal>
</PageLayout>
);
};
export default Connect(
[NS_QUAL_EXPERT],
true,
)(AntdTableFuncControl(ExperManage));