safety-eval-service-frontend/src/pages/Container/Supervision/BasicInfo/RegisteredOrg/Detail/index.js

297 lines
8.7 KiB
JavaScript
Raw Normal View History

2026-06-26 17:28:06 +08:00
import { Button, Card, Form, Spin, Table, Tabs, Tag, message } from "antd";
import { useEffect, useMemo, useState } from "react";
import FormBuilder from "zy-react-library/components/FormBuilder";
2026-06-29 16:45:58 +08:00
import PageLayout from "@cqsjjb/jjb-react-admin-component/PageLayout";
2026-06-26 17:28:06 +08:00
import FilePreviewModal from "~/components/FilePreviewModal";
import {
fetchRegisteredOrgDetail,
fetchRegisteredOrgPersonnelCertDetail,
fetchRegisteredOrgPersonnelCertList,
fetchRegisteredOrgPersonnelDetail,
fetchRegisteredOrgPersonnelList,
fetchRegisteredOrgQualificationGroups,
} from "~/api/regulatorOrgInfo";
import { buildOrgInfoFormOptions } from "../../../../EnterpriseInfo/OrgInfo/formOptions";
import StaffViewModal from "../../../../EnterpriseInfo/PersonnelInfo/StaffViewModal";
const LIST_PATH = "/container/supervision/basicInfo/registeredOrg/list";
const ORG_INFO_FORM_OPTIONS = buildOrgInfoFormOptions();
function parseQueryId(location) {
const search = location?.search || window.location.search || "";
return new URLSearchParams(search).get("id");
}
2026-07-07 15:58:05 +08:00
function resolvePreviewUrl(raw) {
if (!raw) return "";
const u = String(raw);
if (/^https?:\/\//i.test(u)) return u;
const base = window.fileUrl || "";
return base ? `${base}${u}` : u;
}
function isImageUrl(url) {
return /\.(jpe?g|png|gif|webp|bmp)(\?|#|$)/i.test(String(url || "").toLowerCase());
}
2026-06-26 17:28:06 +08:00
function MaterialsTab({ materialGroups, loading, onPreview }) {
if (loading) {
return <Spin />;
}
return (
<div>
<div style={{ marginBottom: 12, color: "rgba(0,0,0,0.45)" }}>
该机构共申请
<strong>{materialGroups.length}</strong>
个业务范围资质以下为各范围对应的申请材料清单
</div>
{materialGroups.map((group) => (
<Card
key={group.id}
size="small"
style={{ marginBottom: 16 }}
title={`业务范围:${group.scopeName}`}
extra={(
<span style={{ fontSize: 12 }}>
证书有效期
<span style={{ color: group.expireWarning ? "#faad14" : "#52c41a", fontWeight: 500 }}>
{group.expireDate}
{group.expireWarning ? "(即将到期)" : ""}
</span>
</span>
)}
>
<Table
size="small"
bordered
rowKey="id"
pagination={false}
dataSource={group.materials}
columns={[
{ title: "材料名称", dataIndex: "name" },
{
title: "操作",
width: 80,
render: (_, record) => (
<Button type="link" size="small" onClick={() => onPreview(record)}>预览</Button>
),
},
]}
/>
</Card>
))}
</div>
);
}
function PersonnelTab({ personnel, loading, onView }) {
if (loading) {
return <Spin />;
}
return (
<Table
size="small"
bordered
rowKey="id"
pagination={false}
dataSource={personnel}
columns={[
{ title: "序号", width: 60, render: (_, __, index) => index + 1 },
{ title: "姓名", dataIndex: "name", width: 90 },
{ title: "性别", dataIndex: "gender", width: 60 },
{ title: "岗位", dataIndex: "position", width: 110 },
{ title: "资质范围", dataIndex: "qualScope", width: 90 },
{ title: "学历", dataIndex: "education", width: 80 },
{
title: "注册安全工程师",
width: 120,
render: (_, record) => (
<Tag color={record.registerEngineer === 1 ? "success" : "error"}>
{record.registerEngineer === 1 ? "是" : "否"}
</Tag>
),
},
{
title: "操作",
width: 80,
render: (_, record) => (
<Button type="link" size="small" onClick={() => onView(record)}>查看</Button>
),
},
]}
/>
);
}
function RegisteredOrgDetailPage(props) {
const id = useMemo(() => parseQueryId(props.location), [props.location?.search]);
const [form] = Form.useForm();
const [orgLoading, setOrgLoading] = useState(Boolean(parseQueryId(props.location)));
const [extrasLoading, setExtrasLoading] = useState(Boolean(parseQueryId(props.location)));
const [orgName, setOrgName] = useState("");
const [materialGroups, setMaterialGroups] = useState([]);
const [personnel, setPersonnel] = useState([]);
const [filePreview, setFilePreview] = useState(null);
const [viewPersonnelId, setViewPersonnelId] = useState("");
useEffect(() => {
if (!id) {
setOrgLoading(false);
setExtrasLoading(false);
return;
}
let cancelled = false;
setOrgLoading(true);
setExtrasLoading(true);
(async () => {
try {
const [orgRes, groups, staffList] = await Promise.all([
fetchRegisteredOrgDetail(id),
fetchRegisteredOrgQualificationGroups(id).catch((err) => {
console.warn("[RegisteredOrgDetail] qualification load failed:", err);
message.error(err?.message || "加载申请材料失败");
return [];
}),
fetchRegisteredOrgPersonnelList(id).catch((err) => {
console.warn("[RegisteredOrgDetail] personnel load failed:", err);
message.error(err?.message || "加载人员信息失败");
return [];
}),
]);
if (cancelled) {
return;
}
if (orgRes?.data) {
form.setFieldsValue(orgRes.data);
setOrgName(orgRes.data.orgName || "");
}
setMaterialGroups(groups || []);
setPersonnel(staffList || []);
}
catch (err) {
if (!cancelled) {
console.warn("[RegisteredOrgDetail] load failed:", err);
message.error("加载机构详情失败");
}
}
finally {
if (!cancelled) {
setOrgLoading(false);
setExtrasLoading(false);
}
}
})();
return () => {
cancelled = true;
};
}, [id]);
const goBack = () => {
if (props.history?.goBack && props.history.length > 1) {
props.history.goBack();
return;
}
if (props.history?.push) {
props.history.push(LIST_PATH);
return;
}
window.location.href = `/certificate${LIST_PATH}`;
};
if (!id) {
return (
2026-06-29 16:45:58 +08:00
<PageLayout title="备案信息详情" extra={<Button onClick={goBack}>返回</Button>}>
<p style={{ margin: 0, marginBottom: 24, color: "rgba(0, 0, 0, 0.45)" }}>
缺少机构 ID 参数
</p>
</PageLayout>
2026-06-26 17:28:06 +08:00
);
}
const tabItems = [
{
key: "info",
label: "备案信息",
children: (
<Spin spinning={orgLoading}>
<FormBuilder
form={form}
span={12}
disabled
useAutoGenerateRequired={false}
options={ORG_INFO_FORM_OPTIONS}
labelCol={{ span: 10 }}
showActionButtons={false}
/>
</Spin>
),
},
{
key: "materials",
label: "申请清单材料",
children: (
<MaterialsTab
materialGroups={materialGroups}
loading={extrasLoading}
2026-07-07 15:58:05 +08:00
onPreview={(record) => {
const url = resolvePreviewUrl(record?.previewUrl);
if (!url) {
message.warning("该材料暂无可预览的附件");
return;
}
if (isImageUrl(url)) {
setFilePreview(record);
} else {
window.open(url, "_blank");
}
}}
2026-06-26 17:28:06 +08:00
/>
),
},
{
key: "personnel",
label: "人员信息",
children: (
<PersonnelTab
personnel={personnel}
loading={extrasLoading}
onView={(record) => setViewPersonnelId(record.id)}
/>
),
},
];
return (
2026-06-29 16:45:58 +08:00
<PageLayout title="备案信息详情" extra={<Button onClick={goBack}> 返回</Button>}>
<p style={{ margin: 0, marginBottom: 24, color: "rgba(0, 0, 0, 0.45)" }}>
{orgName || undefined}
</p>
2026-06-26 17:28:06 +08:00
<Tabs items={tabItems} />
<FilePreviewModal
open={!!filePreview}
title="文件预览"
fileName={filePreview?.name}
2026-07-07 15:58:05 +08:00
url={resolvePreviewUrl(filePreview?.previewUrl)}
2026-06-26 17:28:06 +08:00
onCancel={() => setFilePreview(null)}
/>
{viewPersonnelId && (
<StaffViewModal
open={!!viewPersonnelId}
currentId={viewPersonnelId}
requestDetails={fetchRegisteredOrgPersonnelDetail}
requestCertList={fetchRegisteredOrgPersonnelCertList}
requestCertDetails={fetchRegisteredOrgPersonnelCertDetail}
onCancel={() => setViewPersonnelId("")}
/>
)}
2026-06-29 16:45:58 +08:00
</PageLayout>
2026-06-26 17:28:06 +08:00
);
}
export default RegisteredOrgDetailPage;