Merge branch 'dev-tmp1' of http://47.92.113.182:3000/cq_anquan/safety-eval-service-frontend into dev-tmp1
commit
35452ae9a2
1962
pnpm-lock.yaml
1962
pnpm-lock.yaml
File diff suppressed because it is too large
Load Diff
|
|
@ -1,7 +1,8 @@
|
|||
packages: ["."]
|
||||
packages: [ "." ]
|
||||
allowBuilds:
|
||||
es5-ext: set this to true or false
|
||||
zy-react-library: set this to true or false
|
||||
core-js: false
|
||||
es5-ext: false
|
||||
zy-react-library: false
|
||||
hoist: true
|
||||
nodeLinker: hoisted
|
||||
onlyBuiltDependencies:
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import React, { useEffect, useState } from "react";
|
||||
import { Button, Form, Select, Switch, Table, Tag } from "antd";
|
||||
import { Button, Form, Select, Table, Tag } from "antd";
|
||||
import PageLayout from "@cqsjjb/jjb-react-admin-component/PageLayout";
|
||||
import SearchForm from "@cqsjjb/jjb-react-admin-component/SearchForm";
|
||||
import TableAction from "@cqsjjb/jjb-react-admin-component/TableAction";
|
||||
|
|
@ -20,7 +20,6 @@ import {
|
|||
import {
|
||||
getQualReviewMockEnabled,
|
||||
mockQueryExpertList,
|
||||
setQualReviewMockEnabled,
|
||||
} from "../mockData";
|
||||
import "../QualReview/index.less";
|
||||
|
||||
|
|
@ -36,7 +35,8 @@ const ExpertVerification = (props) => {
|
|||
const [form] = Form.useForm();
|
||||
const { qualReview, queryReviewList } = props;
|
||||
const { qualReviewList, qualReviewTotal, qualReviewLoading } = qualReview || {};
|
||||
const [mockEnabled, setMockEnabled] = useState(getQualReviewMockEnabled());
|
||||
// mock 默认关闭(真实接口);?mock=1 可临时开启演示。变更时间:2026-08-10
|
||||
const mockEnabled = getQualReviewMockEnabled();
|
||||
|
||||
const loadList = (useMock = mockEnabled) => {
|
||||
if (useMock) {
|
||||
|
|
@ -74,13 +74,6 @@ const ExpertVerification = (props) => {
|
|||
loadList();
|
||||
}, []);
|
||||
|
||||
const handleToggleMock = (v) => {
|
||||
setQualReviewMockEnabled(v);
|
||||
setMockEnabled(v);
|
||||
router.query = { ...router.query, current: 1 };
|
||||
loadList(v);
|
||||
};
|
||||
|
||||
const renderConfirmStatus = (record) => {
|
||||
const name = record.filingStatusName || record.statusName;
|
||||
if (name) {
|
||||
|
|
@ -225,14 +218,6 @@ const ExpertVerification = (props) => {
|
|||
<span className="totalText">
|
||||
共 <strong>{qualReviewTotal || 0}</strong> 条记录
|
||||
</span>
|
||||
<Tag
|
||||
className={mockEnabled ? "tag_warning" : "tag_default"}
|
||||
style={{ marginRight: 0 }}
|
||||
>
|
||||
{mockEnabled ? "Mock 演示中" : "真实接口"}
|
||||
</Tag>
|
||||
<span style={{ fontSize: "0.78rem", color: "#64748b" }}>Mock 数据</span>
|
||||
<Switch size="small" checked={mockEnabled} onChange={handleToggleMock} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,11 @@ import { Connect } from "@cqsjjb/jjb-dva-runtime";
|
|||
import { NS_QUAL_REVIEW } from "~/enumerate/namespace";
|
||||
import StaffViewModal from "~/components/StaffViewModal";
|
||||
import PreviewUrlButton from "~/components/PreviewUrlButton/index";
|
||||
import { QUALIFICATION_INDUSTRY_OPTIONS, QUALIFICATION_INDUSTRY_OPTIONS_MAP } from "~/enumerate/enterpriseOptions";
|
||||
import {
|
||||
QUALIFICATION_INDUSTRY_OPTIONS,
|
||||
QUALIFICATION_INDUSTRY_OPTIONS_MAP,
|
||||
TITLE_LEVEL_MAP,
|
||||
} from "~/enumerate/enterpriseOptions";
|
||||
import { CAPABILITY_MAP } from "~/enumerate/constant";
|
||||
import { getCalibrationTag } from "../mockData";
|
||||
|
||||
|
|
@ -32,6 +36,49 @@ function calcAge(birthDate) {
|
|||
return age >= 0 ? age : "-";
|
||||
}
|
||||
|
||||
/**
|
||||
* 职称名称:后端 QualFilingPersonnelInfoCO 返回 titleCodeArr(编码数组),
|
||||
* 转中文名称展示(高级/中级/初级)。变更时间:2026-08-10(对齐后端字段)
|
||||
*/
|
||||
function titleNames(titleCodeArr) {
|
||||
// 兼容:初审返回数组,备案变更返回字符串(可能为 "SENIOR" / "SENIOR,MIDDLE" / JSON 数组字符串)。变更时间:2026-08-10
|
||||
let list = Array.isArray(titleCodeArr) ? titleCodeArr : [];
|
||||
if (!Array.isArray(titleCodeArr) && typeof titleCodeArr === "string") {
|
||||
try {
|
||||
const parsed = JSON.parse(titleCodeArr);
|
||||
list = Array.isArray(parsed) ? parsed : [titleCodeArr];
|
||||
} catch {
|
||||
list = String(titleCodeArr)
|
||||
.split(/[,,、]/)
|
||||
.map((s) => s.trim())
|
||||
.filter(Boolean);
|
||||
}
|
||||
}
|
||||
const names = list
|
||||
.map((item) => {
|
||||
const code = typeof item === "string" ? item : item?.titleCode || item?.title;
|
||||
return item?.titleName || TITLE_LEVEL_MAP[code] || code || "";
|
||||
})
|
||||
.filter(Boolean);
|
||||
// 空数组返回空字符串,便于调用方回退 titleName 等字段
|
||||
return names.length ? names.join("、") : "";
|
||||
}
|
||||
|
||||
/**
|
||||
* 从业年限:后端返回 joinWorkDate(参加工作时间),按当前日期推算年数。
|
||||
* 变更时间:2026-08-10(对齐后端字段)
|
||||
*/
|
||||
function workYearsText(joinWorkDate) {
|
||||
if (!joinWorkDate) return "-";
|
||||
const d = new Date(String(joinWorkDate).replace(/-/g, "/"));
|
||||
if (Number.isNaN(d.getTime())) return "-";
|
||||
const now = new Date();
|
||||
let years = now.getFullYear() - d.getFullYear();
|
||||
const m = now.getMonth() - d.getMonth();
|
||||
if (m < 0 || (m === 0 && now.getDate() < d.getDate())) years--;
|
||||
return years >= 0 ? `${years}年` : "-";
|
||||
}
|
||||
|
||||
const gridStyle = {
|
||||
display: "grid",
|
||||
gridTemplateColumns: "1fr 1fr",
|
||||
|
|
@ -124,10 +171,14 @@ const FilingTabs = ({
|
|||
isReview = false,
|
||||
compliance = {},
|
||||
onComplianceChange,
|
||||
/**
|
||||
* 额外 Tab(如机构备案详情「7. 变更记录」),数组元素与 antd Tabs items 同构。
|
||||
* 不传时保持原 6 Tab,不影响初审/确认/专家核验展示。变更时间:2026-08-10
|
||||
*/
|
||||
extraTabs,
|
||||
}) => {
|
||||
const [viewId, setViewId] = useState("");
|
||||
const [equipRecord, setEquipRecord] = useState(null);
|
||||
const [previewImage, setPreviewImage] = useState("");
|
||||
|
||||
const personnelRows = useMemo(
|
||||
() =>
|
||||
|
|
@ -138,20 +189,24 @@ const FilingTabs = ({
|
|||
[detail.personnelList],
|
||||
);
|
||||
|
||||
/** 管理人员:岗位含"法定代表人/负责人";无匹配时回退展示全部人员 */
|
||||
/**
|
||||
* 管理人员判定:technicalDirectorFlag(技术负责人) 或 processControlLeaderFlag(过程控制负责人) 为 true;
|
||||
* 法定代表人/负责人按岗位名兜底归入管理人员。
|
||||
* 备案变更详情人员 CO(QualFilingPersonnelChangeInfoCO)暂未返回 flag 字段,靠岗位名兜底判断(待后端补充 flag)。
|
||||
* 变更时间:2026-08-10(按后端人员标识字段拆分)
|
||||
*/
|
||||
const isManager = (item) =>
|
||||
item.technicalDirectorFlag === true ||
|
||||
item.processControlLeaderFlag === true ||
|
||||
/法定代表人|负责人/.test(item.positionName || "");
|
||||
|
||||
const managerRows = useMemo(() => {
|
||||
const filtered = personnelRows.filter((item) =>
|
||||
/法定代表人|技术负责人|过程控制负责人|负责人/.test(item.positionName || ""),
|
||||
);
|
||||
return filtered.length ? filtered : personnelRows;
|
||||
return personnelRows.filter(isManager);
|
||||
}, [personnelRows]);
|
||||
|
||||
/** 专职安全评价师:评价师证书号存在或岗位含"评价师";无匹配时回退展示全部人员 */
|
||||
/** 专职安全评价师:非管理人员的其余人员 */
|
||||
const evaluatorRows = useMemo(() => {
|
||||
const filtered = personnelRows.filter(
|
||||
(item) => item.evaluatorCertNo || /评价师/.test(item.positionName || ""),
|
||||
);
|
||||
return filtered.length ? filtered : personnelRows;
|
||||
return personnelRows.filter((item) => !isManager(item));
|
||||
}, [personnelRows]);
|
||||
|
||||
const attachmentList = useMemo(() => {
|
||||
|
|
@ -173,16 +228,6 @@ const FilingTabs = ({
|
|||
}));
|
||||
}, [detail.businessScope]);
|
||||
|
||||
const openPreview = (file) => {
|
||||
const url = file?.url;
|
||||
if (!url) return;
|
||||
if (/\.(jpe?g|png|gif|webp|bmp)(\?|#|$)/i.test(`${file.name || ""} ${url}`.toLowerCase())) {
|
||||
setPreviewImage(url);
|
||||
} else {
|
||||
window.open(url, "_blank");
|
||||
}
|
||||
};
|
||||
|
||||
/** 人员表格列(管理/评价师共用基础) */
|
||||
const basePersonCols = (withScope) => [
|
||||
{ title: "序号", width: 60, render: (_, __, i) => i + 1 },
|
||||
|
|
@ -191,20 +236,42 @@ const FilingTabs = ({
|
|||
{
|
||||
title: "学历/专业",
|
||||
width: 160,
|
||||
// 后端字段:educationName(学历) / basicDisciplineMajorName(专业);变更时间:2026-08-10
|
||||
render: (_, r) =>
|
||||
[r.educationLevelName, r.majorName || r.educationTypeName].filter(Boolean).join(" / ") || "-",
|
||||
[r.educationName, r.basicDisciplineMajorName].filter(Boolean).join(" / ") || "-",
|
||||
},
|
||||
{
|
||||
title: "职称",
|
||||
width: 120,
|
||||
render: (_, r) => titleNames(r.titleCodeArr) || r.titleName || "-",
|
||||
},
|
||||
{ title: "职称", dataIndex: "titleName", width: 120, render: (v) => v || "-" },
|
||||
{
|
||||
title: "从业年限",
|
||||
width: 100,
|
||||
render: (_, r) => r.workYears || r.yearsOfWorking || "-",
|
||||
render: (_, r) =>
|
||||
r.workYears || r.yearsOfWorking || workYearsText(r.joinWorkDate),
|
||||
},
|
||||
{
|
||||
title: "专业能力",
|
||||
width: 180,
|
||||
render: (_, r) => {
|
||||
const codes = r.professionalCapabilityCodeList || [];
|
||||
// 能力编码:兼容 professionalCapabilityCodeList 与后端 capabilityAssessment;变更时间:2026-08-10
|
||||
// 备案变更返回 capabilityAssessment 字符串(JSON 数组),需解析后映射
|
||||
let capList = r.capabilityAssessment;
|
||||
if (typeof capList === "string") {
|
||||
try {
|
||||
const parsed = JSON.parse(capList);
|
||||
capList = Array.isArray(parsed) ? parsed : [];
|
||||
} catch {
|
||||
capList = [];
|
||||
}
|
||||
}
|
||||
const codes =
|
||||
r.professionalCapabilityCodeList ||
|
||||
(Array.isArray(capList)
|
||||
? capList.map((c) => (typeof c === "string" ? c : c?.professionalCapabilityCode)).filter(Boolean)
|
||||
: []) ||
|
||||
[];
|
||||
return codes.length
|
||||
? codes.map((code) => CAPABILITY_MAP[code] || code).join("、")
|
||||
: "-";
|
||||
|
|
@ -341,7 +408,11 @@ const FilingTabs = ({
|
|||
初次申请无需填写,已有资质备案时填写
|
||||
</span>
|
||||
</div>
|
||||
<ReadonlyField label="法定代表人 *" value={detail.legalPersonName || detail.legalPerson} />
|
||||
{/* 法定代表人:后端 CO 字段为 legalRepresentative(表 legal_representative);变更时间:2026-08-10 */}
|
||||
<ReadonlyField
|
||||
label="法定代表人 *"
|
||||
value={detail.legalRepresentative || detail.legalPersonName || detail.legalPerson}
|
||||
/>
|
||||
<ReadonlyField label="法定代表人电话 *" value={detail.legalPersonPhone} />
|
||||
<ReadonlyField label="传真 *" value={detail.fax} />
|
||||
<ReadonlyField label="联系人及电话 *" value={detail.contactPhone} />
|
||||
|
|
@ -359,12 +430,9 @@ const FilingTabs = ({
|
|||
<div style={{ display: "flex", alignItems: "center", gap: "0.5rem" }}>
|
||||
{attachmentList.length ? (
|
||||
<>
|
||||
<Button
|
||||
size="small"
|
||||
onClick={() => openPreview(attachmentList[0])}
|
||||
>
|
||||
<PreviewUrlButton url={attachmentList[0].url} size="small">
|
||||
查看营业执照
|
||||
</Button>
|
||||
</PreviewUrlButton>
|
||||
<span style={{ color: "#8b95a5", fontSize: "0.75rem" }}>
|
||||
{attachmentList[0].name || "营业执照.pdf"}
|
||||
</span>
|
||||
|
|
@ -491,17 +559,9 @@ const FilingTabs = ({
|
|||
<div style={{ display: "flex", alignItems: "center", gap: "0.5rem" }}>
|
||||
{commitment.legalRepSignatureUrl ? (
|
||||
<>
|
||||
<Button
|
||||
size="small"
|
||||
onClick={() =>
|
||||
openPreview({
|
||||
url: commitment.legalRepSignatureUrl,
|
||||
name: "机构负责人签字件",
|
||||
})
|
||||
}
|
||||
>
|
||||
<PreviewUrlButton url={commitment.legalRepSignatureUrl} size="small">
|
||||
查看签字件
|
||||
</Button>
|
||||
</PreviewUrlButton>
|
||||
<Tag color="success">已签字</Tag>
|
||||
</>
|
||||
) : (
|
||||
|
|
@ -519,6 +579,7 @@ const FilingTabs = ({
|
|||
</div>
|
||||
),
|
||||
},
|
||||
...(Array.isArray(extraTabs) ? extraTabs : []),
|
||||
];
|
||||
|
||||
return (
|
||||
|
|
@ -532,15 +593,6 @@ const FilingTabs = ({
|
|||
/>
|
||||
|
||||
<EquipViewModal record={equipRecord} onCancel={() => setEquipRecord(null)} />
|
||||
|
||||
<Image
|
||||
src={previewImage}
|
||||
preview={{
|
||||
visible: !!previewImage,
|
||||
onVisibleChange: (v) => !v && setPreviewImage(""),
|
||||
}}
|
||||
style={{ display: "none" }}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -2,23 +2,62 @@ import React, { useEffect } from "react";
|
|||
import { Button, Form, Select, Table, Tag } from "antd";
|
||||
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 TableAction from "@cqsjjb/jjb-react-admin-component/TableAction";
|
||||
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_REVIEW } from "~/enumerate/namespace";
|
||||
import { FILING_STATUS_MAP, FILING_STATUS_MAP_CHANGE } from "~/enumerate/constant";
|
||||
import { QUALIFICATION_INDUSTRY_OPTIONS_MAP } from "~/enumerate/enterpriseOptions";
|
||||
import { REVIEW_BUSINESS_SCOPE_OPTIONS, REVIEW_STATUS_CLASS } from "../reviewPageQuery";
|
||||
import {
|
||||
getQualReviewMockEnabled,
|
||||
mockQueryChangeList,
|
||||
} from "../mockData";
|
||||
import "../QualReview/index.less";
|
||||
|
||||
const { router } = tools;
|
||||
|
||||
/** 变更状态筛选(原型:停滞中/待审核/已审核;对应备案状态码 3 已打回/4 变更审核中/1 已备案) */
|
||||
const CHANGE_STATUS_OPTIONS = [
|
||||
{ label: "待审核", value: 4 },
|
||||
{ label: "停滞中", value: 3 },
|
||||
{ label: "已审核", value: 1 },
|
||||
];
|
||||
|
||||
/** 变更状态配色(对齐原型 tag-warning/danger/success) */
|
||||
function changeStatusColor(name) {
|
||||
if (/待审核|审核中|变更审核中/.test(name || "")) return "warning";
|
||||
if (/已打回|停滞|退回/.test(name || "")) return "error";
|
||||
if (/已审核|已备案|通过/.test(name || "")) return "success";
|
||||
return "default";
|
||||
}
|
||||
|
||||
/**
|
||||
* 备案变更管理(原型 mod-qual-change)
|
||||
* - 搜索:机构名称 / 备案编号 / 安全评价业务范围 / 变更状态
|
||||
* - 列:复选框、序号、机构名称、机构类型、备案编号、业务范围、变更项、变更状态、操作(查看 / 审核)
|
||||
* - 查看/审核与资质初审备案一致:查看 → FilingDetail?mode=change,审核 → QualReviewForm?mode=change
|
||||
* - 变更项:后端列表 CO 未聚合(明细在 qual_filing_change_detail.change_item_name),真实接口暂显示 "-"
|
||||
* - Mock 演示默认开启:所有行展示 查看 + 审核 按钮
|
||||
*/
|
||||
const QualChange = (props) => {
|
||||
const [form] = Form.useForm();
|
||||
const { qualReview, queryQualChangePage } = props;
|
||||
const { qualReviewList, qualReviewTotal, qualReviewLoading } = qualReview || {};
|
||||
// mock 默认关闭(真实接口);?mock=1 可临时开启演示。变更时间:2026-08-10
|
||||
const mockEnabled = getQualReviewMockEnabled();
|
||||
|
||||
const handleSearch = () => {
|
||||
const loadList = (useMock = mockEnabled) => {
|
||||
if (useMock) {
|
||||
const res = mockQueryChangeList(router.query);
|
||||
props.resetModelState(NS_QUAL_REVIEW, {
|
||||
qualReviewList: res.data,
|
||||
qualReviewTotal: res.total,
|
||||
qualReviewLoading: false,
|
||||
});
|
||||
return;
|
||||
}
|
||||
queryQualChangePage({
|
||||
...router.query,
|
||||
current: router.query.current || 1,
|
||||
|
|
@ -26,6 +65,10 @@ const QualChange = (props) => {
|
|||
});
|
||||
};
|
||||
|
||||
const handleSearch = () => {
|
||||
loadList();
|
||||
};
|
||||
|
||||
const handleReset = (values) => {
|
||||
router.query = {
|
||||
...router.query,
|
||||
|
|
@ -38,7 +81,7 @@ const QualChange = (props) => {
|
|||
|
||||
useEffect(() => {
|
||||
form.setFieldsValue(router.query);
|
||||
handleSearch();
|
||||
loadList();
|
||||
}, []);
|
||||
|
||||
const columns = [
|
||||
|
|
@ -50,22 +93,41 @@ const QualChange = (props) => {
|
|||
},
|
||||
{ title: "机构名称", dataIndex: "filingUnitName", width: 220, ellipsis: true },
|
||||
{ title: "机构类型", dataIndex: "filingUnitTypeName", width: 100 },
|
||||
{ title: "备案编号", dataIndex: "id", width: 140, ellipsis: true },
|
||||
{ title: "经营范围", dataIndex: "businessScope", width: 180, ellipsis: true,
|
||||
{ title: "备案编号", dataIndex: "filingNo", width: 140, ellipsis: true, render: (v) => v || "-" },
|
||||
{
|
||||
title: "安全评价业务范围",
|
||||
dataIndex: "businessScope",
|
||||
width: 180,
|
||||
ellipsis: true,
|
||||
render: (_, record) => {
|
||||
if(Array.isArray(record.businessScope)){
|
||||
return record.businessScope.map(item => QUALIFICATION_INDUSTRY_OPTIONS_MAP[item]).join("、");
|
||||
if (Array.isArray(record.businessScope)) {
|
||||
return record.businessScope
|
||||
.map((item) => QUALIFICATION_INDUSTRY_OPTIONS_MAP[item] || item)
|
||||
.join("、");
|
||||
}
|
||||
return record.businessScope || "-";
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "备案状态",
|
||||
title: "变更项",
|
||||
dataIndex: "changeItemNames",
|
||||
width: 160,
|
||||
ellipsis: true,
|
||||
// 后端列表 CO 未聚合变更项(明细在 qual_filing_change_detail.change_item_name),待后端补充;mock 有值
|
||||
render: (v) => v || "-",
|
||||
},
|
||||
{
|
||||
title: "变更状态",
|
||||
dataIndex: "filingStatusCode",
|
||||
width: 100,
|
||||
render: (code) => {
|
||||
const config = FILING_STATUS_MAP[code];
|
||||
return config ? <Tag color={config.color}>{config.label}</Tag> : "--";
|
||||
width: 110,
|
||||
render: (_, record) => {
|
||||
const name = record.filingStatusName || record.statusName;
|
||||
const color = changeStatusColor(name);
|
||||
return name ? (
|
||||
<Tag className={REVIEW_STATUS_CLASS[color] || "tag_default"}>{name}</Tag>
|
||||
) : (
|
||||
"--"
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
|
|
@ -73,12 +135,21 @@ const QualChange = (props) => {
|
|||
width: 140,
|
||||
fixed: "right",
|
||||
render: (_, record) => (
|
||||
<TableAction>
|
||||
<Button type="link" size="small" onClick={() => props.history.push(`FilingDetail?id=${record.id}&mode=change`)}>
|
||||
<TableAction>
|
||||
<Button
|
||||
type="link"
|
||||
size="small"
|
||||
onClick={() => props.history.push(`FilingDetail?id=${record.id}&mode=change`)}
|
||||
>
|
||||
查看
|
||||
</Button>
|
||||
{(record.filingStatusCode == 2 || record.filingStatusCode == 4) && (
|
||||
<Button type="link" size="small" onClick={() => props.history.push(`QualReviewForm?id=${record.id}&mode=change`)}>
|
||||
{/* mock 演示模式展示全部“审核”按钮;真实模式仅 审核中/变更审核中 可审核 */}
|
||||
{(mockEnabled || [2, 4].includes(Number(record.filingStatusCode))) && (
|
||||
<Button
|
||||
type="link"
|
||||
size="small"
|
||||
onClick={() => props.history.push(`QualReviewForm?id=${record.id}&mode=change`)}
|
||||
>
|
||||
审核
|
||||
</Button>
|
||||
)}
|
||||
|
|
@ -92,22 +163,34 @@ const QualChange = (props) => {
|
|||
<SearchForm
|
||||
style={{ marginBottom: 24 }}
|
||||
form={form}
|
||||
defaultExpand
|
||||
loading={qualReviewLoading}
|
||||
formLine={[
|
||||
<Form.Item key="id" name="id" normalize={(v) => (v ? v.replace(/\D/g, "").slice(0, 20) : v)}>
|
||||
<ControlWrapper.Input label="备案编号" placeholder="请输入" allowClear maxLength={20} />
|
||||
<Form.Item key="filingUnitName" name="filingUnitName">
|
||||
<ControlWrapper.Input label="机构名称" placeholder="请输入机构名称" allowClear />
|
||||
</Form.Item>,
|
||||
<Form.Item key="filingNo" name="filingNo">
|
||||
<ControlWrapper.Input label="备案编号" placeholder="请输入备案编号" allowClear />
|
||||
</Form.Item>,
|
||||
<Form.Item key="businessScope" name="businessScope">
|
||||
<ControlWrapper.Select
|
||||
label="安全评价业务范围"
|
||||
placeholder="请选择"
|
||||
allowClear
|
||||
showSearch
|
||||
optionFilterProp="label"
|
||||
style={{ width: "100%" }}
|
||||
options={REVIEW_BUSINESS_SCOPE_OPTIONS}
|
||||
/>
|
||||
</Form.Item>,
|
||||
<Form.Item key="filingStatusCode" name="filingStatusCode">
|
||||
<ControlWrapper.Select
|
||||
label="备案状态"
|
||||
label="变更状态"
|
||||
placeholder="请选择"
|
||||
allowClear
|
||||
style={{ width: "100%" }}
|
||||
>
|
||||
{Object.entries(FILING_STATUS_MAP_CHANGE).map(([code, config]) => (
|
||||
<Select.Option key={code} value={Number(code)}>{config.label}</Select.Option>
|
||||
))}
|
||||
</ControlWrapper.Select>
|
||||
options={CHANGE_STATUS_OPTIONS}
|
||||
/>
|
||||
</Form.Item>,
|
||||
]}
|
||||
onReset={handleReset}
|
||||
|
|
@ -122,11 +205,20 @@ const QualChange = (props) => {
|
|||
}}
|
||||
/>
|
||||
|
||||
<div className="toolbar">
|
||||
<div className="toolbarLeft">
|
||||
<span className="totalText">
|
||||
共 <strong>{qualReviewTotal || 0}</strong> 条记录
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Table
|
||||
rowKey="id"
|
||||
columns={columns}
|
||||
dataSource={qualReviewList}
|
||||
scroll={{ y: props.scrollY }}
|
||||
dataSource={Array.isArray(qualReviewList) ? qualReviewList : []}
|
||||
rowSelection={{}}
|
||||
scroll={{ x: 1100, y: props.scrollY }}
|
||||
loading={qualReviewLoading}
|
||||
pagination={{
|
||||
total: qualReviewTotal,
|
||||
|
|
@ -149,4 +241,4 @@ const QualChange = (props) => {
|
|||
);
|
||||
};
|
||||
|
||||
export default Connect([NS_QUAL_REVIEW], true)(AntdTableFuncControl(QualChange));
|
||||
export default Connect([NS_QUAL_REVIEW], true)(AntdTableFuncControl(QualChange));
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import React, { useEffect, useState } from "react";
|
||||
import { Button, Form, Select, Switch, Table, Tag } from "antd";
|
||||
import { Button, Form, Select, Table, Tag } from "antd";
|
||||
import PageLayout from "@cqsjjb/jjb-react-admin-component/PageLayout";
|
||||
import SearchForm from "@cqsjjb/jjb-react-admin-component/SearchForm";
|
||||
import TableAction from "@cqsjjb/jjb-react-admin-component/TableAction";
|
||||
|
|
@ -20,7 +20,6 @@ import {
|
|||
import {
|
||||
getQualReviewMockEnabled,
|
||||
mockQueryConfirmList,
|
||||
setQualReviewMockEnabled,
|
||||
} from "../mockData";
|
||||
import "../QualReview/index.less";
|
||||
|
||||
|
|
@ -37,7 +36,8 @@ const QualConfirm = (props) => {
|
|||
const [form] = Form.useForm();
|
||||
const { qualReview, queryReviewList } = props;
|
||||
const { qualReviewList, qualReviewTotal, qualReviewLoading } = qualReview || {};
|
||||
const [mockEnabled, setMockEnabled] = useState(getQualReviewMockEnabled());
|
||||
// mock 默认关闭(真实接口);?mock=1 可临时开启演示。变更时间:2026-08-10
|
||||
const mockEnabled = getQualReviewMockEnabled();
|
||||
|
||||
const loadList = (useMock = mockEnabled) => {
|
||||
if (useMock) {
|
||||
|
|
@ -75,13 +75,6 @@ const QualConfirm = (props) => {
|
|||
loadList();
|
||||
}, []);
|
||||
|
||||
const handleToggleMock = (v) => {
|
||||
setQualReviewMockEnabled(v);
|
||||
setMockEnabled(v);
|
||||
router.query = { ...router.query, current: 1 };
|
||||
loadList(v);
|
||||
};
|
||||
|
||||
const renderConfirmStatus = (record) => {
|
||||
const name = record.filingStatusName || record.statusName;
|
||||
if (name) {
|
||||
|
|
@ -224,14 +217,6 @@ const QualConfirm = (props) => {
|
|||
<span className="totalText">
|
||||
共 <strong>{qualReviewTotal || 0}</strong> 条记录
|
||||
</span>
|
||||
<Tag
|
||||
className={mockEnabled ? "tag_warning" : "tag_default"}
|
||||
style={{ marginRight: 0 }}
|
||||
>
|
||||
{mockEnabled ? "Mock 演示中" : "真实接口"}
|
||||
</Tag>
|
||||
<span style={{ fontSize: "0.78rem", color: "#64748b" }}>Mock 数据</span>
|
||||
<Switch size="small" checked={mockEnabled} onChange={handleToggleMock} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import React, { useEffect, useState } from "react";
|
||||
import { Button, Form, Select, Switch, Table, Tag } from "antd";
|
||||
import React, { useEffect } from "react";
|
||||
import { Button, Form, Select, Table, Tag } 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";
|
||||
|
|
@ -20,7 +20,6 @@ import {
|
|||
import {
|
||||
getQualReviewMockEnabled,
|
||||
mockQueryReviewList,
|
||||
setQualReviewMockEnabled,
|
||||
} from "../mockData";
|
||||
import "./index.less";
|
||||
|
||||
|
|
@ -36,7 +35,8 @@ const QualReview = (props) => {
|
|||
const [form] = Form.useForm();
|
||||
const { qualReview, queryReviewList } = props;
|
||||
const { qualReviewList, qualReviewTotal, qualReviewLoading } = qualReview || {};
|
||||
const [mockEnabled, setMockEnabled] = useState(getQualReviewMockEnabled());
|
||||
// mock 默认关闭(真实接口);?mock=1 可临时开启演示。变更时间:2026-08-10
|
||||
const mockEnabled = getQualReviewMockEnabled();
|
||||
|
||||
/**
|
||||
* 数据加载:mock 模式走本地高内聚数据(不请求后端);
|
||||
|
|
@ -78,14 +78,6 @@ const QualReview = (props) => {
|
|||
loadList();
|
||||
}, []);
|
||||
|
||||
/** 随时切换 mock/真实接口 */
|
||||
const handleToggleMock = (v) => {
|
||||
setQualReviewMockEnabled(v);
|
||||
setMockEnabled(v);
|
||||
router.query = { ...router.query, current: 1 };
|
||||
loadList(v);
|
||||
};
|
||||
|
||||
/** 审核状态渲染:优先后端文案,缺失时按状态编码推断 */
|
||||
const renderStatus = (record) => {
|
||||
const name = record.filingStatusName || record.statusName;
|
||||
|
|
@ -266,14 +258,6 @@ const QualReview = (props) => {
|
|||
<span className="totalText">
|
||||
共 <strong>{qualReviewTotal || 0}</strong> 条记录
|
||||
</span>
|
||||
<Tag
|
||||
className={mockEnabled ? "tag_warning" : "tag_default"}
|
||||
style={{ marginRight: 0 }}
|
||||
>
|
||||
{mockEnabled ? "Mock 演示中" : "真实接口"}
|
||||
</Tag>
|
||||
<span style={{ fontSize: "0.78rem", color: "#64748b" }}>Mock 数据</span>
|
||||
<Switch size="small" checked={mockEnabled} onChange={handleToggleMock} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -12,8 +12,11 @@
|
|||
* 开关优先级:URL ?mock= > localStorage(qualReviewMockEnabled) > 默认开启。
|
||||
*/
|
||||
|
||||
/** 默认是否启用 mock(true=演示模式,false=真实后端) */
|
||||
export const QUAL_REVIEW_MOCK_DEFAULT_ENABLED = true;
|
||||
/**
|
||||
* 默认是否启用 mock(true=演示模式,false=真实后端)。
|
||||
* 2026-08-10 按用户要求默认切换为真实接口;mock 代码/数据保留,仍可通过 ?mock=1 或 localStorage 临时开启演示。
|
||||
*/
|
||||
export const QUAL_REVIEW_MOCK_DEFAULT_ENABLED = false;
|
||||
|
||||
const MOCK_STORAGE_KEY = "qualReviewMockEnabled";
|
||||
|
||||
|
|
@ -240,12 +243,14 @@ export const MOCK_QUAL_FILING_DETAIL = {
|
|||
{ id: 10, materialContent: "机构内部管理制度(非受控版).pdf", materialFormat: "pdf", uploadStatusCode: 2, uploadStatusName: "已上传", attachmentUrl: "https://example.com/m10.pdf" },
|
||||
],
|
||||
personnelList: [
|
||||
{ id: 101, sourcePersonnelId: 1001, personName: "郑远平", positionName: "法定代表人", titleName: "高级工程师", educationLevelName: "本科", majorName: "安全工程", workYears: "18年", genderCode: 1 },
|
||||
{ id: 102, sourcePersonnelId: 1002, personName: "张建国", positionName: "技术负责人", titleName: "正高级工程师", educationLevelName: "本科", majorName: "化工工艺", workYears: "16年", genderCode: 1 },
|
||||
{ id: 103, sourcePersonnelId: 1003, personName: "王丽萍", positionName: "过程控制负责人", titleName: "高级工程师", educationLevelName: "本科", majorName: "安全管理", workYears: "12年", genderCode: 2 },
|
||||
{ id: 201, sourcePersonnelId: 2001, personName: "李明华", positionName: "专职安全评价师", titleName: "高级工程师", educationLevelName: "硕士", majorName: "采矿工程", workYears: "12年", evaluatorCertNo: "SJP-2020-001", professionalCapabilityCodeList: ["MINING"], appliedScope: ["METAL_NONMETAL_MINING"], genderCode: 1 },
|
||||
{ id: 202, sourcePersonnelId: 2002, personName: "陈志强", positionName: "专职安全评价师", titleName: "高级工程师", educationLevelName: "本科", majorName: "化工工艺", workYears: "10年", evaluatorCertNo: "SJP-2019-023", professionalCapabilityCodeList: ["CHEMICAL_PROCESS"], appliedScope: ["PETROCHEMICAL_CHEMICAL_PHARMACEUTICAL"], genderCode: 1 },
|
||||
{ id: 203, sourcePersonnelId: 2003, personName: "刘海", positionName: "专职安全评价师", titleName: "工程师", educationLevelName: "本科", majorName: "机械工程", workYears: "8年", evaluatorCertNo: "SJP-2021-045", professionalCapabilityCodeList: ["MECHANICAL"], appliedScope: ["METAL_SMELTING"], genderCode: 1 },
|
||||
// technicalDirectorFlag/processControlLeaderFlag:true 归管理人员(用户要求 2026-08-10)
|
||||
// 学历/专业字段:educationName / basicDisciplineMajorName(用户要求 2026-08-10)
|
||||
{ id: 101, sourcePersonnelId: 1001, personName: "郑远平", positionName: "法定代表人", titleName: "高级工程师", educationName: "本科", basicDisciplineMajorName: "安全工程", workYears: "18年", genderCode: 1, technicalDirectorFlag: false, processControlLeaderFlag: false },
|
||||
{ id: 102, sourcePersonnelId: 1002, personName: "张建国", positionName: "技术负责人", titleName: "正高级工程师", educationName: "本科", basicDisciplineMajorName: "化工工艺", workYears: "16年", genderCode: 1, technicalDirectorFlag: true, processControlLeaderFlag: false },
|
||||
{ id: 103, sourcePersonnelId: 1003, personName: "王丽萍", positionName: "过程控制负责人", titleName: "高级工程师", educationName: "本科", basicDisciplineMajorName: "安全管理", workYears: "12年", genderCode: 2, technicalDirectorFlag: false, processControlLeaderFlag: true },
|
||||
{ id: 201, sourcePersonnelId: 2001, personName: "李明华", positionName: "专职安全评价师", titleName: "高级工程师", educationName: "硕士", basicDisciplineMajorName: "采矿工程", workYears: "12年", evaluatorCertNo: "SJP-2020-001", professionalCapabilityCodeList: ["MINING"], appliedScope: ["METAL_NONMETAL_MINING"], genderCode: 1, technicalDirectorFlag: false, processControlLeaderFlag: false },
|
||||
{ id: 202, sourcePersonnelId: 2002, personName: "陈志强", positionName: "专职安全评价师", titleName: "高级工程师", educationName: "本科", basicDisciplineMajorName: "化工工艺", workYears: "10年", evaluatorCertNo: "SJP-2019-023", professionalCapabilityCodeList: ["CHEMICAL_PROCESS"], appliedScope: ["PETROCHEMICAL_CHEMICAL_PHARMACEUTICAL"], genderCode: 1, technicalDirectorFlag: false, processControlLeaderFlag: false },
|
||||
{ id: 203, sourcePersonnelId: 2003, personName: "刘海", positionName: "专职安全评价师", titleName: "工程师", educationName: "本科", basicDisciplineMajorName: "机械工程", workYears: "8年", evaluatorCertNo: "SJP-2021-045", professionalCapabilityCodeList: ["MECHANICAL"], appliedScope: ["METAL_SMELTING"], genderCode: 1, technicalDirectorFlag: false, processControlLeaderFlag: false },
|
||||
],
|
||||
equipmentList: [
|
||||
{ id: 301, deviceName: "气相色谱仪", deviceModel: "GC-2018", manufacturer: "岛津", equipmentValue: 120000, calibrationReportUrl: "https://example.com/cal1.pdf" },
|
||||
|
|
@ -346,10 +351,38 @@ export function mockQueryExpertList(params = {}) {
|
|||
return filterRowsByParams(MOCK_QUAL_EXPERT_LIST, params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 备案变更管理列表 mock(原型 mod-qual-change:4 条,与 QualFilingChangeCO 同构)。
|
||||
* 变更时间:2026-08-10
|
||||
*/
|
||||
export const MOCK_QUAL_CHANGE_LIST = [
|
||||
{ id: 301, filingId: 1, filingUnitName: "重庆安评技术研究院有限公司", filingUnitTypeName: "本地单位", filingNo: "BA-2026-001", businessScope: ["PETROCHEMICAL_CHEMICAL_PHARMACEUTICAL"], changeItemNames: "法定代表人变更", filingStatusCode: 4, filingStatusName: "变更审核中" },
|
||||
{ id: 302, filingId: 2, filingUnitName: "重庆恒安安全评价有限公司", filingUnitTypeName: "本地单位", filingNo: "BA-2025-032", businessScope: ["PETROCHEMICAL_CHEMICAL_PHARMACEUTICAL", "FIREWORKS_FIRECRACKERS"], changeItemNames: "注册地址变更", filingStatusCode: 3, filingStatusName: "已打回" },
|
||||
{ id: 303, filingId: 3, filingUnitName: "北京中安评价中心(重庆分公司)", filingUnitTypeName: "异地单位", filingNo: "BA-2026-015", businessScope: ["METAL_NONMETAL_MINING"], changeItemNames: "业务范围变更", filingStatusCode: 4, filingStatusName: "变更审核中" },
|
||||
{ id: 304, filingId: 4, filingUnitName: "重庆渝安风险评估中心", filingUnitTypeName: "本地单位", filingNo: "BA-2026-008", businessScope: ["PETROCHEMICAL_CHEMICAL_PHARMACEUTICAL"], changeItemNames: "技术负责人变更", filingStatusCode: 1, filingStatusName: "已备案" },
|
||||
];
|
||||
|
||||
/** 备案变更 mock 查询:机构名称/备案编号/业务范围/变更状态 过滤 + 分页 */
|
||||
export function mockQueryChangeList(params = {}) {
|
||||
const keyword = String(params.filingUnitName || "").trim().toLowerCase();
|
||||
const noKeyword = String(params.filingNo || "").trim().toLowerCase();
|
||||
let rows = MOCK_QUAL_CHANGE_LIST.filter((item) => {
|
||||
if (keyword && !item.filingUnitName.toLowerCase().includes(keyword)) return false;
|
||||
if (noKeyword && !String(item.filingNo || "").toLowerCase().includes(noKeyword)) return false;
|
||||
if (params.businessScope && !(item.businessScope || []).includes(params.businessScope)) return false;
|
||||
if (params.filingStatusCode !== undefined && params.filingStatusCode !== null && params.filingStatusCode !== "" && Number(item.filingStatusCode) !== Number(params.filingStatusCode)) return false;
|
||||
return true;
|
||||
});
|
||||
const current = Number(params.current || 1);
|
||||
const size = Number(params.size || 10);
|
||||
const start = (current - 1) * size;
|
||||
return { data: rows.slice(start, start + size), total: rows.length };
|
||||
}
|
||||
|
||||
/** mock 详情(按 id 返回,找不到时返回默认详情) */
|
||||
export function mockGetFilingDetail(id) {
|
||||
const row =
|
||||
[...MOCK_QUAL_REVIEW_LIST, ...MOCK_QUAL_CONFIRM_LIST, ...MOCK_QUAL_EXPERT_LIST].find(
|
||||
[...MOCK_QUAL_REVIEW_LIST, ...MOCK_QUAL_CONFIRM_LIST, ...MOCK_QUAL_EXPERT_LIST, ...MOCK_QUAL_CHANGE_LIST].find(
|
||||
(item) => String(item.id) === String(id),
|
||||
);
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -1,31 +1,24 @@
|
|||
import {
|
||||
Button,
|
||||
Image,
|
||||
Input,
|
||||
Spin,
|
||||
Table,
|
||||
Tabs,
|
||||
Tag,
|
||||
message,
|
||||
} from "antd";
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
import { Button, Spin, Table, Tag } from "antd";
|
||||
import { useEffect, useState } from "react";
|
||||
import PageLayout from "@cqsjjb/jjb-react-admin-component/PageLayout";
|
||||
import {
|
||||
fetchRegisteredOrgDetail,
|
||||
fetchRegisteredOrgPersonnelList,
|
||||
fetchRegisteredOrgQualificationGroups,
|
||||
} from "~/utils/regulatorOrgInfo";
|
||||
import { QUALIFICATION_INDUSTRY_OPTIONS_MAP } from "~/enumerate/enterpriseOptions";
|
||||
import StaffViewModal from "~/components/StaffViewModal";
|
||||
import { Get } from "@cqsjjb/jjb-common-lib/http";
|
||||
import PreviewUrlButton from "~/components/PreviewUrlButton/index";
|
||||
import FilingTabs from "~/pages/Container/QualificationReview/FilingTabs";
|
||||
|
||||
const LIST_PATH = "/container/supervision/basicInfo/registeredOrg/list";
|
||||
const { TextArea } = Input;
|
||||
|
||||
/** Mock 开关存储键(与机构备案管理列表共享,默认开启便于与原型对比) */
|
||||
const ORG_MOCK_STORAGE_KEY = "registeredOrgMockEnabled";
|
||||
|
||||
function getOrgMockEnabled() {
|
||||
try {
|
||||
// URL 参数优先(?mock=1/0),并持久化到 localStorage。变更时间:2026-08-10
|
||||
const qs = new URLSearchParams(window.location.search);
|
||||
if (qs.has("mock")) {
|
||||
const v = qs.get("mock") === "1";
|
||||
localStorage.setItem(ORG_MOCK_STORAGE_KEY, v ? "1" : "0");
|
||||
return v;
|
||||
}
|
||||
const stored = localStorage.getItem(ORG_MOCK_STORAGE_KEY);
|
||||
if (stored === "1") return true;
|
||||
if (stored === "0") return false;
|
||||
|
|
@ -35,20 +28,25 @@ function getOrgMockEnabled() {
|
|||
return true;
|
||||
}
|
||||
|
||||
/** 机构基础信息详情 mock(原型 mod-filing-detail 七项 Tab 数据) */
|
||||
/**
|
||||
* 机构基础信息详情 mock(与资质备案初审 qual-filing/detail 返回结构同构,便于复用 FilingTabs 六 Tab 展示)。
|
||||
* 变更时间:2026-08-10(参考初审详情取数方式重构)
|
||||
*/
|
||||
const ORG_DETAIL_MOCK = {
|
||||
unitName: "重庆安评技术研究院有限公司",
|
||||
creditCode: "915001072028699512",
|
||||
isLocalUnit: 1,
|
||||
id: 1,
|
||||
filingStatusCode: 1,
|
||||
filingStatusName: "已备案",
|
||||
businessScope: ["COAL_MINING", "METAL_NONMETAL_MINING", "PETROCHEMICAL_CHEMICAL_PHARMACEUTICAL", "METAL_SMELTING"],
|
||||
filingTerritoryName: "重庆市沙坪坝区",
|
||||
filingUnitName: "重庆安评技术研究院有限公司",
|
||||
filingUnitTypeName: "本地单位",
|
||||
creditCode: "915001072028699512",
|
||||
registerAddress: "重庆市沙坪坝区大学城东路20号",
|
||||
businessAddress: "重庆市沙坪坝区大学城东路20号重庆科技学院第39栋西南角实习用房三楼",
|
||||
infoDisclosureUrl: "https://cqap.example.com",
|
||||
officeAddress: "重庆市沙坪坝区大学城东路20号重庆科技学院第39栋西南角实习用房三楼",
|
||||
qualCertNo: "API-2026-001",
|
||||
infoDisclosureUrl: "https://cqap.example.com",
|
||||
legalRepresentative: "郑远平",
|
||||
legalRepresentativePhone: "023-68705577",
|
||||
legalPersonPhone: "023-68705577",
|
||||
fax: "023-68705578",
|
||||
contactPhone: "陈芳 / 139****9012",
|
||||
fixedAssetAmount: 1200,
|
||||
|
|
@ -57,36 +55,38 @@ const ORG_DETAIL_MOCK = {
|
|||
fulltimeEvaluatorCount: 25,
|
||||
registeredEngineerCount: 12,
|
||||
unitIntro: "重庆安评技术研究院成立于2015年,是一家专业从事安全评价、安全咨询、安全技术开发与转让的综合性安全技术服务机构。",
|
||||
attachmentUrl: [{ name: "营业执照副本.pdf", url: "https://example.com/license.pdf" }],
|
||||
personnel: [
|
||||
{ id: 1001, userName: "郑远平", positionName: "法定代表人", titleName: "高级工程师", educationLevelName: "本科", majorName: "安全工程", workYears: "18年" },
|
||||
{ id: 1002, userName: "张建国", positionName: "技术负责人", titleName: "正高级工程师", educationLevelName: "本科", majorName: "化工工艺", workYears: "16年" },
|
||||
{ id: 1003, userName: "王丽萍", positionName: "过程控制负责人", titleName: "高级工程师", educationLevelName: "本科", majorName: "安全管理", workYears: "12年" },
|
||||
{ id: 2001, userName: "李明华", positionName: "专职安全评价师", titleName: "高级工程师", educationLevelName: "硕士", majorName: "采矿工程", workYears: "12年", capabilityName: "非煤矿山安全评价", scopeName: "金属、非金属矿及其他矿采选业" },
|
||||
{ id: 2002, userName: "陈志强", positionName: "专职安全评价师", titleName: "高级工程师", educationLevelName: "本科", majorName: "化工工艺", workYears: "10年", capabilityName: "化工工艺安全风险评估", scopeName: "石油加工业,化学原料、化学品及医药制造业" },
|
||||
{ id: 2003, userName: "刘海", positionName: "专职安全评价师", titleName: "工程师", educationLevelName: "本科", majorName: "机械工程", workYears: "8年", capabilityName: "金属冶炼安全评价", scopeName: "金属冶炼" },
|
||||
attachmentUrl: JSON.stringify([{ name: "营业执照副本.pdf", url: "https://example.com/license.pdf" }]),
|
||||
personnelList: [
|
||||
// technicalDirectorFlag/processControlLeaderFlag:true 归管理人员(用户要求 2026-08-10)
|
||||
// 学历/专业字段:educationName / basicDisciplineMajorName(用户要求 2026-08-10)
|
||||
{ id: 1001, sourcePersonnelId: 1001, personName: "郑远平", positionName: "法定代表人", titleName: "高级工程师", educationName: "本科", basicDisciplineMajorName: "安全工程", workYears: "18年", technicalDirectorFlag: false, processControlLeaderFlag: false },
|
||||
{ id: 1002, sourcePersonnelId: 1002, personName: "张建国", positionName: "技术负责人", titleName: "正高级工程师", educationName: "本科", basicDisciplineMajorName: "化工工艺", workYears: "16年", technicalDirectorFlag: true, processControlLeaderFlag: false },
|
||||
{ id: 1003, sourcePersonnelId: 1003, personName: "王丽萍", positionName: "过程控制负责人", titleName: "高级工程师", educationName: "本科", basicDisciplineMajorName: "安全管理", workYears: "12年", technicalDirectorFlag: false, processControlLeaderFlag: true },
|
||||
{ id: 2001, sourcePersonnelId: 2001, personName: "李明华", positionName: "专职安全评价师", titleName: "高级工程师", educationName: "硕士", basicDisciplineMajorName: "采矿工程", workYears: "12年", evaluatorCertNo: "SJP-2020-001", professionalCapabilityCodeList: ["MINING"], appliedScope: ["METAL_NONMETAL_MINING"], technicalDirectorFlag: false, processControlLeaderFlag: false },
|
||||
{ id: 2002, sourcePersonnelId: 2002, personName: "陈志强", positionName: "专职安全评价师", titleName: "高级工程师", educationName: "本科", basicDisciplineMajorName: "化工工艺", workYears: "10年", evaluatorCertNo: "SJP-2019-023", professionalCapabilityCodeList: ["CHEMICAL_PROCESS"], appliedScope: ["PETROCHEMICAL_CHEMICAL_PHARMACEUTICAL"], technicalDirectorFlag: false, processControlLeaderFlag: false },
|
||||
{ id: 2003, sourcePersonnelId: 2003, personName: "刘海", positionName: "专职安全评价师", titleName: "工程师", educationName: "本科", basicDisciplineMajorName: "机械工程", workYears: "8年", evaluatorCertNo: "SJP-2021-045", professionalCapabilityCodeList: ["MECHANICAL"], appliedScope: ["METAL_SMELTING"], technicalDirectorFlag: false, processControlLeaderFlag: false },
|
||||
],
|
||||
materials: [
|
||||
{ id: 1, name: "申请材料目录.pdf", format: "pdf", url: "https://example.com/m1.pdf" },
|
||||
{ id: 2, name: "安全评价机构资质申请书及材料清单.pdf", format: "pdf", url: "https://example.com/m2.pdf" },
|
||||
{ id: 3, name: "法人证明.pdf", format: "pdf", url: "https://example.com/m3.pdf" },
|
||||
{ id: 4, name: "截至申请之日三年内无重大违法失信记录的查询证明.pdf", format: "pdf", url: "https://example.com/m4.pdf" },
|
||||
{ id: 5, name: "申请单位法定代表人承诺书.pdf", format: "pdf", url: "https://example.com/m5.pdf" },
|
||||
{ id: 6, name: "固定资产法定证明材料.pdf", format: "pdf", url: "https://example.com/m6.pdf" },
|
||||
{ id: 7, name: "工作场所及档案室面积证明材料.pdf", format: "pdf", url: "https://example.com/m7.pdf" },
|
||||
{ id: 8, name: "安全评价师专业能力证明.pdf", format: "pdf", url: "https://example.com/m8.pdf" },
|
||||
{ id: 9, name: "专职技术负责人和支撑过程控制负责人证明材料.pdf", format: "pdf", url: "https://example.com/m9.pdf" },
|
||||
{ id: 10, name: "机构内部管理制度(非受控版).pdf", format: "pdf", url: "https://example.com/m10.pdf" },
|
||||
{ id: 1, materialContent: "申请材料目录.pdf", materialFormat: "pdf", uploadStatusCode: 2, uploadStatusName: "已上传", attachmentUrl: "https://example.com/m1.pdf" },
|
||||
{ id: 2, materialContent: "安全评价机构资质申请书及材料清单.pdf", materialFormat: "pdf", uploadStatusCode: 2, uploadStatusName: "已上传", attachmentUrl: "https://example.com/m2.pdf" },
|
||||
{ id: 3, materialContent: "法人证明.pdf", materialFormat: "pdf", uploadStatusCode: 2, uploadStatusName: "已上传", attachmentUrl: "https://example.com/m3.pdf" },
|
||||
{ id: 4, materialContent: "截至申请之日三年内无重大违法失信记录的查询证明.pdf", materialFormat: "pdf", uploadStatusCode: 2, uploadStatusName: "已上传", attachmentUrl: "https://example.com/m4.pdf" },
|
||||
{ id: 5, materialContent: "申请单位法定代表人承诺书.pdf", materialFormat: "pdf", uploadStatusCode: 2, uploadStatusName: "已上传", attachmentUrl: "https://example.com/m5.pdf" },
|
||||
{ id: 6, materialContent: "固定资产法定证明材料.pdf", materialFormat: "pdf", uploadStatusCode: 2, uploadStatusName: "已上传", attachmentUrl: "https://example.com/m6.pdf" },
|
||||
{ id: 7, materialContent: "工作场所及档案室面积证明材料.pdf", materialFormat: "pdf", uploadStatusCode: 2, uploadStatusName: "已上传", attachmentUrl: "https://example.com/m7.pdf" },
|
||||
{ id: 8, materialContent: "安全评价师专业能力证明.pdf", materialFormat: "pdf", uploadStatusCode: 2, uploadStatusName: "已上传", attachmentUrl: "https://example.com/m8.pdf" },
|
||||
{ id: 9, materialContent: "专职技术负责人和支撑过程控制负责人证明材料.pdf", materialFormat: "pdf", uploadStatusCode: 2, uploadStatusName: "已上传", attachmentUrl: "https://example.com/m9.pdf" },
|
||||
{ id: 10, materialContent: "机构内部管理制度(非受控版).pdf", materialFormat: "pdf", uploadStatusCode: 2, uploadStatusName: "已上传", attachmentUrl: "https://example.com/m10.pdf" },
|
||||
],
|
||||
equipment: [
|
||||
{ id: 301, deviceName: "气相色谱仪", deviceModel: "GC-2018", manufacturer: "岛津", calibration: { label: "已检定", status: "success" } },
|
||||
{ id: 302, deviceName: "噪声计", deviceModel: "HS-6288", manufacturer: "杭州爱华", calibration: { label: "已检定", status: "success" } },
|
||||
{ id: 303, deviceName: "粉尘采样器", deviceModel: "FC-5A", manufacturer: "北京劳保所", calibration: { label: "待检定", status: "warning" } },
|
||||
equipmentList: [
|
||||
{ id: 301, deviceName: "气相色谱仪", deviceModel: "GC-2018", manufacturer: "岛津", equipmentValue: 120000, calibrationReportUrl: "https://example.com/cal1.pdf" },
|
||||
{ id: 302, deviceName: "噪声计", deviceModel: "HS-6288", manufacturer: "杭州爱华", equipmentValue: 8000, calibrationReportUrl: "https://example.com/cal2.pdf" },
|
||||
{ id: 303, deviceName: "粉尘采样器", deviceModel: "FC-5A", manufacturer: "北京劳保所", equipmentValue: 9000, calibrationReportUrl: "" },
|
||||
],
|
||||
commitment: {
|
||||
legalRepName: "郑远平",
|
||||
legalRepSignatureUrl: "https://example.com/sign.png",
|
||||
signDate: "2026-06-25 16:42",
|
||||
signWay: "APP认证签字",
|
||||
},
|
||||
changes: [
|
||||
{ id: 1, submitTime: "2026-07-18 10:24", submitType: "注册提交", changeFields: "基础信息全量提交", submitter: "机构管理员", statusName: "待审核", statusColor: "warning", url: "https://example.com/c1.pdf" },
|
||||
|
|
@ -94,120 +94,63 @@ const ORG_DETAIL_MOCK = {
|
|||
],
|
||||
};
|
||||
|
||||
const gridStyle = {
|
||||
display: "grid",
|
||||
gridTemplateColumns: "1fr 1fr",
|
||||
gap: "0.6rem 1rem",
|
||||
};
|
||||
const fieldStyle = { display: "flex", flexDirection: "column", gap: "0.3rem" };
|
||||
const labelStyle = { fontSize: "0.8rem", color: "#64748b", fontWeight: 500 };
|
||||
const inputStyle = { background: "#f8fafc" };
|
||||
const fullSpan = { gridColumn: "1 / -1" };
|
||||
|
||||
function ReadonlyField({ label, value, span }) {
|
||||
return (
|
||||
<div style={span ? { ...fieldStyle, ...span } : fieldStyle}>
|
||||
<label style={labelStyle}>{label}</label>
|
||||
<Input readOnly value={value || "-"} style={inputStyle} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function parseQueryId(location) {
|
||||
const search = location?.search || window.location.search || "";
|
||||
return new URLSearchParams(search).get("id");
|
||||
}
|
||||
|
||||
/**
|
||||
* 机构基础信息详情(原型 mod-filing-detail)
|
||||
* - 数据获取使用变更接口:按变更记录 id 调 GET /safetyEval/qual-filing-change/detail(5 表聚合),
|
||||
* 六项 Tab 直接复用 FilingTabs(基础信息/管理人员/专职评价师/申请材料/设备清单/机构负责人签字)
|
||||
* - 变更记录 Tab:GET /safetyEval/qual-filing-change/history?filingId=(filingId 取详情返回的 filingId)
|
||||
* 返回 changeTime/changeItemName/operatorName/changeCount(原型「提交类型/审核状态/查看提交件」后端未返回,待补充)
|
||||
* 变更时间:2026-08-10(按用户要求改用带 change 的详情接口)
|
||||
*/
|
||||
function RegisteredOrgDetailPage(props) {
|
||||
const id = useMemo(
|
||||
() => parseQueryId(props.location),
|
||||
[props.location?.search],
|
||||
);
|
||||
const [orgLoading, setOrgLoading] = useState(Boolean(id));
|
||||
const [extrasLoading, setExtrasLoading] = useState(Boolean(id));
|
||||
const [orgName, setOrgName] = useState("");
|
||||
const [info, setInfo] = useState({});
|
||||
const [personnel, setPersonnel] = useState([]);
|
||||
const [materials, setMaterials] = useState([]);
|
||||
const [previewImage, setPreviewImage] = useState("");
|
||||
const [viewPersonnelId, setViewPersonnelId] = useState("");
|
||||
const id = parseQueryId(props.location);
|
||||
const [detail, setDetail] = useState({});
|
||||
const [changes, setChanges] = useState([]);
|
||||
const [loading, setLoading] = useState(Boolean(id));
|
||||
const mockEnabled = getOrgMockEnabled();
|
||||
|
||||
const openPreview = (file) => {
|
||||
const url = file?.url;
|
||||
if (!url) return;
|
||||
if (/\.(jpe?g|png|gif|webp|bmp)(\?|#|$)/i.test(`${file.name || ""} ${url}`.toLowerCase())) {
|
||||
setPreviewImage(url);
|
||||
} else {
|
||||
window.open(url, "_blank");
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (!id) {
|
||||
setOrgLoading(false);
|
||||
setExtrasLoading(false);
|
||||
setLoading(false);
|
||||
return;
|
||||
}
|
||||
if (mockEnabled) {
|
||||
// Mock 演示:本地注入原型完整七项 Tab 数据
|
||||
setInfo(ORG_DETAIL_MOCK);
|
||||
setPersonnel(ORG_DETAIL_MOCK.personnel);
|
||||
setMaterials(ORG_DETAIL_MOCK.materials);
|
||||
setOrgName(ORG_DETAIL_MOCK.unitName);
|
||||
setOrgLoading(false);
|
||||
setExtrasLoading(false);
|
||||
setDetail(ORG_DETAIL_MOCK);
|
||||
setChanges(ORG_DETAIL_MOCK.changes);
|
||||
setLoading(false);
|
||||
return;
|
||||
}
|
||||
|
||||
let cancelled = false;
|
||||
setOrgLoading(true);
|
||||
setExtrasLoading(true);
|
||||
setLoading(true);
|
||||
(async () => {
|
||||
try {
|
||||
const [orgRes, groups, staffList] = await Promise.all([
|
||||
fetchRegisteredOrgDetail(id),
|
||||
fetchRegisteredOrgQualificationGroups(id).catch((err) => {
|
||||
console.warn("[RegisteredOrgDetail] qualification load failed:", err);
|
||||
return { data: {} };
|
||||
}),
|
||||
fetchRegisteredOrgPersonnelList(id).catch((err) => {
|
||||
console.warn("[RegisteredOrgDetail] personnel load failed:", err);
|
||||
return [];
|
||||
}),
|
||||
]);
|
||||
// 详情:变更聚合接口(QualFilingChangeAggregationCO:基础信息 + materials/equipmentList/commitment/personnelList)
|
||||
const detailRes = await Get(
|
||||
"/safetyEval/qual-filing-change/detail",
|
||||
{ id },
|
||||
{ token: sessionStorage.getItem("token") },
|
||||
).catch(() => ({ data: {} }));
|
||||
if (cancelled) return;
|
||||
const detail = orgRes?.data || {};
|
||||
setInfo(detail);
|
||||
setOrgName(detail.unitName || "");
|
||||
// 申请材料:资质材料组 → 扁平列表(名称/格式/附件地址)
|
||||
const flatMaterials = [];
|
||||
Object.values(groups?.data || {}).forEach((list) => {
|
||||
(Array.isArray(list) ? list : []).forEach((item, idx) => {
|
||||
const url = item.certImageUrl || item.attachmentUrl || "";
|
||||
flatMaterials.push({
|
||||
id: item.id || `${item.licenseTypeName}-${idx}`,
|
||||
name: item.certName || item.licenseTypeName || "-",
|
||||
format: /\.(png|jpe?g|gif|webp|bmp)/i.test(String(url)) ? "图片" : "pdf",
|
||||
url,
|
||||
});
|
||||
});
|
||||
});
|
||||
setMaterials(flatMaterials);
|
||||
setPersonnel(Array.isArray(staffList) ? staffList : []);
|
||||
} catch (err) {
|
||||
if (!cancelled) {
|
||||
console.warn("[RegisteredOrgDetail] load failed:", err);
|
||||
message.error("加载机构详情失败");
|
||||
}
|
||||
const filingId = detailRes?.data?.filingId || id;
|
||||
// 变更记录:history 按原备案 filingId 查询(优先取详情返回的 filingId)
|
||||
const historyRes = await Get(
|
||||
"/safetyEval/qual-filing-change/history",
|
||||
{ filingId },
|
||||
{ token: sessionStorage.getItem("token") },
|
||||
).catch(() => ({ data: {} }));
|
||||
if (cancelled) return;
|
||||
setDetail(detailRes?.data || {});
|
||||
// 变更记录:history 返回 { changeCount, records:[{id, changeItemName, changeTime, operatorName}] }
|
||||
setChanges(historyRes?.data?.records || []);
|
||||
} finally {
|
||||
if (!cancelled) {
|
||||
setOrgLoading(false);
|
||||
setExtrasLoading(false);
|
||||
}
|
||||
if (!cancelled) setLoading(false);
|
||||
}
|
||||
})();
|
||||
|
||||
return () => {
|
||||
cancelled = true;
|
||||
};
|
||||
|
|
@ -227,352 +170,50 @@ function RegisteredOrgDetailPage(props) {
|
|||
|
||||
if (!id) {
|
||||
return (
|
||||
<PageLayout
|
||||
title="机构基础信息详情"
|
||||
extra={<Button onClick={goBack}>返回</Button>}
|
||||
>
|
||||
<p style={{ margin: 0, marginBottom: 24, color: "rgba(0, 0, 0, 0.45)" }}>
|
||||
缺少机构 ID 参数
|
||||
</p>
|
||||
<PageLayout title="机构基础信息详情" extra={<Button onClick={goBack}>返回</Button>}>
|
||||
<p style={{ margin: 0, marginBottom: 24, color: "rgba(0, 0, 0, 0.45)" }}>缺少机构 ID 参数</p>
|
||||
</PageLayout>
|
||||
);
|
||||
}
|
||||
|
||||
/** 管理人员:负责人岗位优先,无匹配回退全部人员 */
|
||||
const managerRows = useMemo(() => {
|
||||
const filtered = personnel.filter((item) =>
|
||||
/法定代表人|技术负责人|过程控制负责人|负责人/.test(
|
||||
item.positionName || item.postName || item.position || "",
|
||||
),
|
||||
);
|
||||
return filtered.length ? filtered : personnel;
|
||||
}, [personnel]);
|
||||
// mock 演示下 changes 为原型完整列;真实接口仅返回 变更时间/变更项/操作人
|
||||
const changeColumns =
|
||||
mockEnabled || changes[0]?.submitTime
|
||||
? [
|
||||
{ title: "提交时间", dataIndex: "submitTime", width: 150 },
|
||||
{ title: "提交类型", dataIndex: "submitType", width: 100 },
|
||||
{ title: "变更字段", dataIndex: "changeFields", ellipsis: true },
|
||||
{ title: "提交人", dataIndex: "submitter", width: 100 },
|
||||
{ title: "审核状态", width: 100, render: (_, record) => <Tag color={record.statusColor || "default"}>{record.statusName || "-"}</Tag> },
|
||||
{
|
||||
title: "操作",
|
||||
width: 110,
|
||||
render: (_, record) => (
|
||||
<PreviewUrlButton url={record.url} size="small">
|
||||
查看提交件
|
||||
</PreviewUrlButton>
|
||||
),
|
||||
},
|
||||
]
|
||||
: [
|
||||
{ title: "变更时间", dataIndex: "changeTime", width: 160 },
|
||||
{ title: "变更项", dataIndex: "changeItemName", ellipsis: true },
|
||||
{ title: "操作人", dataIndex: "operatorName", width: 110 },
|
||||
];
|
||||
|
||||
/** 专职评价师:评价师证书/岗位匹配,无匹配回退全部人员 */
|
||||
const evaluatorRows = useMemo(() => {
|
||||
const filtered = personnel.filter((item) =>
|
||||
item.evaluatorCertNo || /评价师/.test(item.positionName || item.postName || item.position || ""),
|
||||
);
|
||||
return filtered.length ? filtered : personnel;
|
||||
}, [personnel]);
|
||||
|
||||
const businessScope = useMemo(() => {
|
||||
const list = Array.isArray(info.businessScope) ? info.businessScope : [];
|
||||
return [
|
||||
{ label: "煤炭开采业", value: "COAL_MINING" },
|
||||
{ label: "金属、非金属矿及其他矿采选业", value: "METAL_NONMETAL_MINING" },
|
||||
{ label: "陆地石油和天然气开采业", value: "ONSHORE_OIL_GAS" },
|
||||
{ label: "陆上油气管道运输业", value: "ONSHORE_OIL_GAS_PIPELINE" },
|
||||
{ label: "石油加工业,化学原料、化学品及医药制造业", value: "PETROCHEMICAL_CHEMICAL_PHARMACEUTICAL" },
|
||||
{ label: "烟花爆竹制造业", value: "FIREWORKS_FIRECRACKERS" },
|
||||
{ label: "金属冶炼", value: "METAL_SMELTING" },
|
||||
].map((opt) => ({ ...opt, checked: list.includes(opt.value) }));
|
||||
}, [info.businessScope]);
|
||||
|
||||
const equipmentList = info.equipment || [];
|
||||
const commitment = info.commitment || {};
|
||||
const changes = info.changes || [];
|
||||
|
||||
const tabItems = [
|
||||
{
|
||||
key: "info",
|
||||
label: "基础信息",
|
||||
children: (
|
||||
<Spin spinning={orgLoading}>
|
||||
<div style={gridStyle}>
|
||||
<div style={{ ...fieldStyle, ...fullSpan }}>
|
||||
<label style={labelStyle}>拟申请的法定安全评价业务范围</label>
|
||||
<div
|
||||
style={{
|
||||
display: "grid",
|
||||
gridTemplateColumns: "repeat(2, minmax(260px, 1fr))",
|
||||
gap: "0.3rem 0.75rem",
|
||||
padding: "0.75rem",
|
||||
border: "1px solid #e2e8f0",
|
||||
borderRadius: 8,
|
||||
background: "#f8fafc",
|
||||
}}
|
||||
>
|
||||
{businessScope.map((opt) => (
|
||||
<label key={opt.value} style={{ fontWeight: 400, fontSize: "0.82rem" }}>
|
||||
<input type="checkbox" checked={opt.checked} disabled /> {opt.label}
|
||||
</label>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
<ReadonlyField label="备案属地" value={info.filingTerritoryName || info.districtName} />
|
||||
<ReadonlyField label="备案单位" value={info.unitName} />
|
||||
<ReadonlyField label="备案单位类型" value={info.filingUnitTypeName || (info.isLocalUnit === 1 ? "本地单位" : "异地单位")} />
|
||||
<ReadonlyField label="统一社会信用代码" value={info.creditCode} />
|
||||
<ReadonlyField label="注册地址" value={info.registerAddress} span={fullSpan} />
|
||||
<ReadonlyField label="办公地址" value={info.businessAddress} span={fullSpan} />
|
||||
<ReadonlyField label="信息公开网址" value={info.infoDisclosureUrl} />
|
||||
<ReadonlyField label="资质证书编号" value={info.qualCertNo} />
|
||||
<ReadonlyField label="法定代表人" value={info.legalRepresentative} />
|
||||
<ReadonlyField label="法定代表人电话" value={info.legalRepresentativePhone} />
|
||||
<ReadonlyField label="传真" value={info.fax} />
|
||||
<ReadonlyField label="联系人及电话" value={info.contactPhone || info.principalPhone} />
|
||||
<ReadonlyField label="固定资产总值(万元)" value={info.fixedAssetAmount} />
|
||||
<ReadonlyField label="工作场所建筑面积(㎡)" value={info.workplaceArea} />
|
||||
<ReadonlyField label="档案室面积(㎡)" value={info.archiveRoomArea} />
|
||||
<ReadonlyField label="专职安全评价师数量" value={info.fulltimeEvaluatorCount} />
|
||||
<ReadonlyField label="注册安全工程师数量" value={info.registeredEngineerCount} />
|
||||
<div style={{ ...fieldStyle, ...fullSpan }}>
|
||||
<label style={labelStyle}>单位基本情况介绍(可附页)</label>
|
||||
<TextArea readOnly rows={4} value={info.unitIntro || ""} style={inputStyle} />
|
||||
</div>
|
||||
<div style={{ ...fieldStyle, ...fullSpan }}>
|
||||
<label style={labelStyle}>营业执照</label>
|
||||
<div style={{ display: "flex", alignItems: "center", gap: "0.5rem" }}>
|
||||
{(info.attachmentUrl || []).length ? (
|
||||
<>
|
||||
<Button
|
||||
size="small"
|
||||
onClick={() => {
|
||||
const first = (info.attachmentUrl || [])[0];
|
||||
openPreview({
|
||||
name: first.name || "营业执照",
|
||||
url: first.url || (typeof first === "string" ? first : ""),
|
||||
});
|
||||
}}
|
||||
>
|
||||
查看营业执照
|
||||
</Button>
|
||||
<Tag color="success">{(info.attachmentUrl || [])[0]?.name || "营业执照.pdf"}</Tag>
|
||||
</>
|
||||
) : (
|
||||
<span style={{ color: "#64748b", fontSize: "0.8rem" }}>—</span>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Spin>
|
||||
),
|
||||
},
|
||||
{
|
||||
key: "management",
|
||||
label: "管理人员",
|
||||
children: (
|
||||
<Table
|
||||
size="small"
|
||||
bordered
|
||||
rowKey="id"
|
||||
pagination={false}
|
||||
loading={extrasLoading}
|
||||
dataSource={managerRows}
|
||||
scroll={{ x: 900 }}
|
||||
columns={[
|
||||
{ title: "序号", width: 60, render: (_, __, i) => i + 1 },
|
||||
{ title: "姓名", dataIndex: "userName", width: 110 },
|
||||
{ title: "岗位", dataIndex: "positionName", ellipsis: true },
|
||||
{ title: "职称", dataIndex: "titleName", width: 120, render: (v) => v || "-" },
|
||||
{
|
||||
title: "学历/专业",
|
||||
width: 160,
|
||||
render: (_, r) =>
|
||||
[r.educationLevelName, r.majorName || r.educationTypeName].filter(Boolean).join(" / ") || "-",
|
||||
},
|
||||
{
|
||||
title: "从业年限",
|
||||
width: 100,
|
||||
render: (_, r) => r.workYears || r.workYear || "-",
|
||||
},
|
||||
{
|
||||
title: "操作",
|
||||
width: 80,
|
||||
fixed: "right",
|
||||
render: (_, record) => (
|
||||
<Button
|
||||
type="link"
|
||||
size="small"
|
||||
onClick={() => setViewPersonnelId(record.id || record.sourcePersonnelId)}
|
||||
>
|
||||
查看
|
||||
</Button>
|
||||
),
|
||||
},
|
||||
]}
|
||||
/>
|
||||
),
|
||||
},
|
||||
{
|
||||
key: "evaluators",
|
||||
label: "专职评价师",
|
||||
children: (
|
||||
<Table
|
||||
size="small"
|
||||
bordered
|
||||
rowKey="id"
|
||||
pagination={false}
|
||||
loading={extrasLoading}
|
||||
dataSource={evaluatorRows}
|
||||
scroll={{ x: 1100 }}
|
||||
columns={[
|
||||
{ title: "序号", width: 60, render: (_, __, i) => i + 1 },
|
||||
{ title: "人员姓名", dataIndex: "userName", width: 110 },
|
||||
{ title: "岗位类别", dataIndex: "positionName", width: 140, ellipsis: true },
|
||||
{
|
||||
title: "学历/专业",
|
||||
width: 160,
|
||||
render: (_, r) =>
|
||||
[r.educationLevelName, r.majorName || r.educationTypeName].filter(Boolean).join(" / ") || "-",
|
||||
},
|
||||
{ title: "职称", dataIndex: "titleName", width: 120, render: (v) => v || "-" },
|
||||
{
|
||||
title: "专业能力",
|
||||
width: 180,
|
||||
render: (_, r) => r.capabilityName || r.capability || QUALIFICATION_INDUSTRY_OPTIONS_MAP[r.qualScope] || r.qualScope || "-",
|
||||
},
|
||||
{
|
||||
title: "申请业务范围",
|
||||
width: 200,
|
||||
ellipsis: true,
|
||||
render: (_, r) => r.scopeName || r.appliedScopeName || QUALIFICATION_INDUSTRY_OPTIONS_MAP[r.qualScope] || r.qualScope || "-",
|
||||
},
|
||||
{
|
||||
title: "操作",
|
||||
width: 80,
|
||||
fixed: "right",
|
||||
render: (_, record) => (
|
||||
<Button
|
||||
type="link"
|
||||
size="small"
|
||||
onClick={() => setViewPersonnelId(record.id || record.sourcePersonnelId)}
|
||||
>
|
||||
查看
|
||||
</Button>
|
||||
),
|
||||
},
|
||||
]}
|
||||
/>
|
||||
),
|
||||
},
|
||||
{
|
||||
key: "materials",
|
||||
label: "申请材料",
|
||||
children: (
|
||||
<Table
|
||||
size="small"
|
||||
bordered
|
||||
rowKey="id"
|
||||
pagination={false}
|
||||
loading={extrasLoading}
|
||||
dataSource={materials}
|
||||
columns={[
|
||||
{ title: "序号", width: 60, render: (_, __, i) => i + 1 },
|
||||
{ title: "申请材料", dataIndex: "name", ellipsis: true },
|
||||
{ title: "格式", dataIndex: "format", width: 80 },
|
||||
{
|
||||
title: "操作",
|
||||
width: 80,
|
||||
render: (_, record) => (
|
||||
<Button type="link" size="small" onClick={() => openPreview(record)}>
|
||||
预览
|
||||
</Button>
|
||||
),
|
||||
},
|
||||
]}
|
||||
/>
|
||||
),
|
||||
},
|
||||
{
|
||||
key: "equipment",
|
||||
label: "设备清单",
|
||||
children: (
|
||||
<Table
|
||||
size="small"
|
||||
bordered
|
||||
rowKey="id"
|
||||
pagination={false}
|
||||
loading={extrasLoading}
|
||||
dataSource={equipmentList}
|
||||
columns={[
|
||||
{ title: "序号", width: 60, render: (_, __, i) => i + 1 },
|
||||
{ title: "设备名称", dataIndex: "deviceName", ellipsis: true },
|
||||
{ title: "规格型号", dataIndex: "deviceModel", ellipsis: true },
|
||||
{ title: "生产厂家", dataIndex: "manufacturer" },
|
||||
{
|
||||
title: "计量检定情况",
|
||||
width: 120,
|
||||
render: (_, record) => {
|
||||
const cal = record.calibration || {};
|
||||
return cal.label ? <Tag color={cal.status === "success" ? "success" : "warning"}>{cal.label}</Tag> : "-";
|
||||
},
|
||||
},
|
||||
]}
|
||||
/>
|
||||
),
|
||||
},
|
||||
{
|
||||
key: "signature",
|
||||
label: "机构负责人签字",
|
||||
children: (
|
||||
<div
|
||||
style={{
|
||||
border: "1px solid #e2e8f0",
|
||||
borderRadius: 8,
|
||||
padding: "1.25rem 1.5rem",
|
||||
background: "#fafafa",
|
||||
fontSize: "0.85rem",
|
||||
lineHeight: 1.9,
|
||||
}}
|
||||
>
|
||||
<p style={{ textAlign: "center", fontWeight: 600, fontSize: "0.95rem", marginBottom: "0.75rem" }}>
|
||||
机构负责人签字确认
|
||||
</p>
|
||||
<p>机构端已完成资质备案提交确认,承诺本次提交的基础信息、管理人员、专职安全评价师、申请材料和设备清单真实、准确、完整。</p>
|
||||
<div style={gridStyle}>
|
||||
<ReadonlyField label="签字人" value={commitment.legalRepName} />
|
||||
<ReadonlyField label="职务" value="法定代表人 / 机构负责人" />
|
||||
<ReadonlyField label="签字方式" value={commitment.signWay || "APP认证签字"} />
|
||||
<ReadonlyField label="签字时间" value={commitment.signDate} />
|
||||
<div style={{ ...fieldStyle, ...fullSpan }}>
|
||||
<label style={labelStyle}>签字文件</label>
|
||||
<div>
|
||||
{commitment.legalRepSignatureUrl ? (
|
||||
<Button size="small" onClick={() => openPreview({ name: "机构负责人签字件", url: commitment.legalRepSignatureUrl })}>
|
||||
查看签字件
|
||||
</Button>
|
||||
) : (
|
||||
<span style={{ color: "#64748b", fontSize: "0.8rem" }}>—</span>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
/** 第 7 个 Tab:变更记录(原型 mod-filing-detail 变更记录 Tab)。变更时间:2026-08-10 */
|
||||
const extraTabs = [
|
||||
{
|
||||
key: "changes",
|
||||
label: "变更记录",
|
||||
label: "7. 变更记录",
|
||||
children: (
|
||||
<Table
|
||||
size="small"
|
||||
bordered
|
||||
rowKey="id"
|
||||
pagination={false}
|
||||
loading={extrasLoading}
|
||||
dataSource={changes}
|
||||
columns={[
|
||||
{ title: "提交时间", dataIndex: "submitTime", width: 150 },
|
||||
{ title: "提交类型", dataIndex: "submitType", width: 100 },
|
||||
{ title: "变更字段", dataIndex: "changeFields", ellipsis: true },
|
||||
{ title: "提交人", dataIndex: "submitter", width: 100 },
|
||||
{
|
||||
title: "审核状态",
|
||||
width: 100,
|
||||
render: (_, record) => <Tag color={record.statusColor || "default"}>{record.statusName || "-"}</Tag>,
|
||||
},
|
||||
{
|
||||
title: "操作",
|
||||
width: 110,
|
||||
render: (_, record) => (
|
||||
<Button type="link" size="small" onClick={() => openPreview({ name: "提交件", url: record.url })}>
|
||||
查看提交件
|
||||
</Button>
|
||||
),
|
||||
},
|
||||
]}
|
||||
dataSource={Array.isArray(changes) ? changes : []}
|
||||
columns={changeColumns}
|
||||
/>
|
||||
),
|
||||
},
|
||||
|
|
@ -588,27 +229,10 @@ function RegisteredOrgDetailPage(props) {
|
|||
history={props.history}
|
||||
previous
|
||||
>
|
||||
<p style={{ margin: 0, marginBottom: 24, color: "rgba(0, 0, 0, 0.45)" }}>
|
||||
{orgName || undefined}
|
||||
</p>
|
||||
<Tabs items={tabItems} />
|
||||
|
||||
{viewPersonnelId && (
|
||||
<StaffViewModal
|
||||
open={!!viewPersonnelId}
|
||||
currentId={viewPersonnelId}
|
||||
onCancel={() => setViewPersonnelId("")}
|
||||
/>
|
||||
)}
|
||||
|
||||
<Image
|
||||
src={previewImage}
|
||||
preview={{
|
||||
visible: !!previewImage,
|
||||
onVisibleChange: (v) => !v && setPreviewImage(""),
|
||||
}}
|
||||
style={{ display: "none" }}
|
||||
/>
|
||||
<Spin spinning={loading}>
|
||||
{/* 七项 Tab:前六项复用资质备案初审详情组件(qual-filing/detail 数据),第 7 项为变更记录 */}
|
||||
<FilingTabs detail={detail || {}} extraTabs={extraTabs} />
|
||||
</Spin>
|
||||
</PageLayout>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,14 +1,13 @@
|
|||
import { Button, Form, Switch, Table, Tag } from "antd";
|
||||
import { Button, Form, Table, Tag } from "antd";
|
||||
import { AntdTableFuncControl } from "@cqsjjb/jjb-common-decorator/antd";
|
||||
import { Connect } from "@cqsjjb/jjb-dva-runtime";
|
||||
import { Get } from "@cqsjjb/jjb-common-lib/http";
|
||||
import { useEffect, useState } from "react";
|
||||
import ControlWrapper from "@cqsjjb/jjb-react-admin-component/ControlWrapper";
|
||||
import PageLayout from "@cqsjjb/jjb-react-admin-component/PageLayout";
|
||||
import SearchForm from "@cqsjjb/jjb-react-admin-component/SearchForm";
|
||||
import {
|
||||
REGISTERED_ORG_FILING_RECORD_STATUS_OPTIONS,
|
||||
REGISTERED_ORG_FILING_TYPE_SEARCH_OPTIONS,
|
||||
} from "~/enumerate/enterpriseOptions";
|
||||
import { QUALIFICATION_INDUSTRY_OPTIONS_MAP } from "~/enumerate/enterpriseOptions";
|
||||
import { QUAL_FILING_STATUS_OPTIONS } from "~/enumerate/qualFilingOptions";
|
||||
import { NS_ORG_INFO } from "~/enumerate/namespace";
|
||||
|
||||
/** 约定式路由首字母小写:registeredOrg/detail */
|
||||
|
|
@ -19,13 +18,21 @@ const ORG_MOCK_STORAGE_KEY = "registeredOrgMockEnabled";
|
|||
|
||||
function getOrgMockEnabled() {
|
||||
try {
|
||||
// URL 参数优先(?mock=1/0),并持久化到 localStorage;与资质备案模块开关行为一致。变更时间:2026-08-10
|
||||
const qs = new URLSearchParams(window.location.search);
|
||||
if (qs.has("mock")) {
|
||||
const v = qs.get("mock") === "1";
|
||||
setOrgMockEnabled(v);
|
||||
return v;
|
||||
}
|
||||
const stored = localStorage.getItem(ORG_MOCK_STORAGE_KEY);
|
||||
if (stored === "1") return true;
|
||||
if (stored === "0") return false;
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
return true;
|
||||
// 2026-08-10 按用户要求默认真实接口;mock 代码/数据保留,?mock=1 可临时开启
|
||||
return false;
|
||||
}
|
||||
|
||||
function setOrgMockEnabled(enabled) {
|
||||
|
|
@ -36,49 +43,49 @@ function setOrgMockEnabled(enabled) {
|
|||
}
|
||||
}
|
||||
|
||||
/** 机构备案管理 mock 数据(原型 mod-institution-filing:覆盖 已提交/待补正/待备案 等状态) */
|
||||
/**
|
||||
* 机构备案管理列表 mock(与后端 GET /safetyEval/qual-filing-change/page 的 QualFilingChangeCO 同构)。
|
||||
* 字段:filingUnitName/creditCode/filingUnitTypeName/businessScope/legalRepresentative/filingStatusCode/filingStatusName。
|
||||
* 变更时间:2026-08-10(列表查询切换为 /qual-filing-change/page,mock 同步对齐)
|
||||
*/
|
||||
const ORG_MOCK_LIST = [
|
||||
{ id: 1, unitName: "重庆安评技术研究院有限公司", creditCode: "915001072028699512", isLocalUnit: 1, businessScopeName: "煤炭开采业;金属、非金属矿及其他矿采选业;石油加工业,化学原料、化学品及医药制造业;金属冶炼", legalRepresentative: "郑远平", filingTypeCode: "1", filingTypeName: "审核备案", filingRecordStatusCode: 1, filingRecordStatusName: "已提交" },
|
||||
{ id: 2, unitName: "重庆恒安安全评价有限公司", creditCode: "91500103MA60H002", isLocalUnit: 1, businessScopeName: "石油加工业,化学原料、化学品及医药制造业;金属冶炼", legalRepresentative: "刘强", filingTypeCode: "1", filingTypeName: "审核备案", filingRecordStatusCode: 2, filingRecordStatusName: "待补正" },
|
||||
{ id: 3, unitName: "北京中安评价中心(重庆分公司)", creditCode: "91110108MA01XXXXX", isLocalUnit: 0, businessScopeName: "金属、非金属矿及其他矿采选业", legalRepresentative: "周海峰", filingTypeCode: "2", filingTypeName: "确认备案", filingRecordStatusCode: 3, filingRecordStatusName: "待备案" },
|
||||
{ id: 4, unitName: "重庆渝安风险评估中心", creditCode: "91500107MA5K1111", isLocalUnit: 1, businessScopeName: "化工、建筑施工", legalRepresentative: "陈明", filingTypeCode: "1", filingTypeName: "审核备案", filingRecordStatusCode: 1, filingRecordStatusName: "已提交" },
|
||||
{ id: 5, unitName: "四川天府安全评价有限公司(重庆分公司)", creditCode: "91510100MA61XXXXX", isLocalUnit: 0, businessScopeName: "烟花爆竹制造业;煤炭开采业", legalRepresentative: "李伟", filingTypeCode: "2", filingTypeName: "确认备案", filingRecordStatusCode: 3, filingRecordStatusName: "待备案" },
|
||||
{ id: 6, unitName: "重庆两江安全技术服务有限公司", creditCode: "91500000MA5UYYYYY", isLocalUnit: 1, businessScopeName: "金属冶炼;陆上油气管道运输业", legalRepresentative: "王静", filingTypeCode: "1", filingTypeName: "审核备案", filingRecordStatusCode: 2, filingRecordStatusName: "待补正" },
|
||||
{ id: 7, unitName: "云南康安评价中心", creditCode: "91530000MA6PZZZZZ", isLocalUnit: 0, businessScopeName: "煤炭开采业", legalRepresentative: "赵东升", filingTypeCode: "2", filingTypeName: "确认备案", filingRecordStatusCode: 3, filingRecordStatusName: "待备案" },
|
||||
{ id: 8, unitName: "重庆科工安全评价中心", creditCode: "91500112MA5WAAAAA", isLocalUnit: 1, businessScopeName: "陆地石油和天然气开采业", legalRepresentative: "陈海林", filingTypeCode: "1", filingTypeName: "审核备案", filingRecordStatusCode: 1, filingRecordStatusName: "已提交" },
|
||||
{ id: 9, unitName: "贵州黔安风险评估有限公司(重庆分公司)", creditCode: "91520100MA6HBBBBB", isLocalUnit: 0, businessScopeName: "石油加工业,化学原料、化学品及医药制造业", legalRepresentative: "张建国", filingTypeCode: "2", filingTypeName: "确认备案", filingRecordStatusCode: 2, filingRecordStatusName: "待补正" },
|
||||
{ id: 10, unitName: "重庆辰安检测评价有限公司", creditCode: "91500105MA5UCCCCC", isLocalUnit: 1, businessScopeName: "烟花爆竹制造业;煤炭开采业", legalRepresentative: "王丽萍", filingTypeCode: "1", filingTypeName: "审核备案", filingRecordStatusCode: 1, filingRecordStatusName: "已提交" },
|
||||
{ id: 11, unitName: "湖南湖湘安全评价中心(重庆分公司)", creditCode: "91430100MA4LDDDDD", isLocalUnit: 0, businessScopeName: "陆上油气管道运输业;金属、非金属矿及其他矿采选业", legalRepresentative: "李明华", filingTypeCode: "2", filingTypeName: "确认备案", filingRecordStatusCode: 3, filingRecordStatusName: "待备案" },
|
||||
{ id: 12, unitName: "重庆巴渝安全评价有限公司", creditCode: "91500109MA5WEEEEE", isLocalUnit: 1, businessScopeName: "石油加工业,化学原料、化学品及医药制造业;金属、非金属矿及其他矿采选业", legalRepresentative: "刘海", filingTypeCode: "1", filingTypeName: "审核备案", filingRecordStatusCode: 1, filingRecordStatusName: "已提交" },
|
||||
{ id: 1, filingId: 1, filingUnitName: "重庆安评技术研究院有限公司", creditCode: "915001072028699512", filingUnitTypeName: "本地单位", businessScope: ["COAL_MINING", "METAL_NONMETAL_MINING", "PETROCHEMICAL_CHEMICAL_PHARMACEUTICAL", "METAL_SMELTING"], legalRepresentative: "郑远平", filingStatusCode: 1, filingStatusName: "已备案" },
|
||||
{ id: 2, filingId: 2, filingUnitName: "重庆恒安安全评价有限公司", creditCode: "91500103MA60H002", filingUnitTypeName: "本地单位", businessScope: ["PETROCHEMICAL_CHEMICAL_PHARMACEUTICAL", "METAL_SMELTING"], legalRepresentative: "刘强", filingStatusCode: 2, filingStatusName: "审核中" },
|
||||
{ id: 3, filingId: 3, filingUnitName: "北京中安评价中心(重庆分公司)", creditCode: "91110108MA01XXXXX", filingUnitTypeName: "异地单位", businessScope: ["METAL_NONMETAL_MINING"], legalRepresentative: "周海峰", filingStatusCode: 3, filingStatusName: "已打回" },
|
||||
{ id: 4, filingId: 4, filingUnitName: "重庆渝安风险评估中心", creditCode: "91500107MA5K1111", filingUnitTypeName: "本地单位", businessScope: ["PETROCHEMICAL_CHEMICAL_PHARMACEUTICAL"], legalRepresentative: "陈明", filingStatusCode: 4, filingStatusName: "变更审核中" },
|
||||
{ id: 5, filingId: 5, filingUnitName: "四川天府安全评价有限公司(重庆分公司)", creditCode: "91510100MA61XXXXX", filingUnitTypeName: "异地单位", businessScope: ["FIREWORKS_FIRECRACKERS", "COAL_MINING"], legalRepresentative: "李伟", filingStatusCode: 1, filingStatusName: "已备案" },
|
||||
{ id: 6, filingId: 6, filingUnitName: "重庆两江安全技术服务有限公司", creditCode: "91500000MA5UYYYYY", filingUnitTypeName: "本地单位", businessScope: ["METAL_SMELTING", "ONSHORE_OIL_GAS_PIPELINE"], legalRepresentative: "王静", filingStatusCode: 5, filingStatusName: "暂存" },
|
||||
{ id: 7, filingId: 7, filingUnitName: "云南康安评价中心", creditCode: "91530000MA6PZZZZZ", filingUnitTypeName: "异地单位", businessScope: ["COAL_MINING"], legalRepresentative: "赵东升", filingStatusCode: 2, filingStatusName: "审核中" },
|
||||
{ id: 8, filingId: 8, filingUnitName: "重庆科工安全评价中心", creditCode: "91500112MA5WAAAAA", filingUnitTypeName: "本地单位", businessScope: ["ONSHORE_OIL_GAS"], legalRepresentative: "陈海林", filingStatusCode: 1, filingStatusName: "已备案" },
|
||||
{ id: 9, filingId: 9, filingUnitName: "贵州黔安风险评估有限公司(重庆分公司)", creditCode: "91520100MA6HBBBBB", filingUnitTypeName: "异地单位", businessScope: ["PETROCHEMICAL_CHEMICAL_PHARMACEUTICAL"], legalRepresentative: "张建国", filingStatusCode: 4, filingStatusName: "变更审核中" },
|
||||
{ id: 10, filingId: 10, filingUnitName: "重庆辰安检测评价有限公司", creditCode: "91500105MA5UCCCCC", filingUnitTypeName: "本地单位", businessScope: ["FIREWORKS_FIRECRACKERS", "COAL_MINING"], legalRepresentative: "王丽萍", filingStatusCode: 1, filingStatusName: "已备案" },
|
||||
{ id: 11, filingId: 11, filingUnitName: "湖南湖湘安全评价中心(重庆分公司)", creditCode: "91430100MA4LDDDDD", filingUnitTypeName: "异地单位", businessScope: ["ONSHORE_OIL_GAS_PIPELINE", "METAL_NONMETAL_MINING"], legalRepresentative: "李明华", filingStatusCode: 3, filingStatusName: "已打回" },
|
||||
{ id: 12, filingId: 12, filingUnitName: "重庆巴渝安全评价有限公司", creditCode: "91500109MA5WEEEEE", filingUnitTypeName: "本地单位", businessScope: ["PETROCHEMICAL_CHEMICAL_PHARMACEUTICAL", "METAL_NONMETAL_MINING"], legalRepresentative: "刘海", filingStatusCode: 1, filingStatusName: "已备案" },
|
||||
];
|
||||
|
||||
/** mock 查询:单位名称/信用代码/备案类型/状态 过滤 + 分页,返回 { success, data, totalCount } */
|
||||
/** mock 查询:单位名称/状态 过滤 + 分页,返回 { success, data, total }(与接口解包一致) */
|
||||
function mockQueryRegisteredOrgPage(params = {}) {
|
||||
const keywordOf = (v) => String(v || "").trim().toLowerCase();
|
||||
const unitName = keywordOf(params.unitName);
|
||||
const creditCode = keywordOf(params.creditCode);
|
||||
const keyword = String(params.filingUnitName || "").trim().toLowerCase();
|
||||
let rows = ORG_MOCK_LIST.filter((item) => {
|
||||
if (unitName && !item.unitName.toLowerCase().includes(unitName)) return false;
|
||||
if (creditCode && !item.creditCode.toLowerCase().includes(creditCode)) return false;
|
||||
if (params.filingTypeCode && item.filingTypeCode !== String(params.filingTypeCode)) return false;
|
||||
if (params.filingRecordStatusCode !== undefined && params.filingRecordStatusCode !== null && params.filingRecordStatusCode !== "" && Number(item.filingRecordStatusCode) !== Number(params.filingRecordStatusCode)) return false;
|
||||
if (keyword && !item.filingUnitName.toLowerCase().includes(keyword)) return false;
|
||||
if (params.filingStatusCode !== undefined && params.filingStatusCode !== null && params.filingStatusCode !== "" && Number(item.filingStatusCode) !== Number(params.filingStatusCode)) return false;
|
||||
return true;
|
||||
});
|
||||
const current = Number(params.current ?? params.pageIndex ?? 1);
|
||||
const size = Number(params.size ?? params.pageSize ?? 10);
|
||||
const current = Number(params.current ?? 1);
|
||||
const size = Number(params.size ?? 10);
|
||||
const start = (current - 1) * size;
|
||||
return {
|
||||
success: true,
|
||||
data: rows.slice(start, start + size),
|
||||
totalCount: rows.length,
|
||||
total: rows.length,
|
||||
};
|
||||
}
|
||||
|
||||
/** 提交状态配色(原型 tag-success/tag-warning/tag-info) */
|
||||
function getStatusColor(name, code) {
|
||||
if (/已提交|已备案|通过/.test(name || "")) return "success";
|
||||
if (/待补正|打回|退回/.test(name || "")) return "warning";
|
||||
if (/待备案|备案中/.test(name || "")) return code === 3 ? "warning" : "processing";
|
||||
/** 提交状态配色(对齐原型 tag-success/warning/danger/info) */
|
||||
function getStatusColor(name) {
|
||||
if (/已备案|通过/.test(name || "")) return "success";
|
||||
if (/已打回|退回/.test(name || "")) return "error";
|
||||
if (/审核中|变更审核中/.test(name || "")) return "processing";
|
||||
return "default";
|
||||
}
|
||||
|
||||
|
|
@ -89,8 +96,13 @@ function RegisteredOrgListPage(props) {
|
|||
const [loading, setLoading] = useState(false);
|
||||
const [pageIndex, setPageIndex] = useState(1);
|
||||
const [pageSize, setPageSize] = useState(10);
|
||||
const [mockEnabled, setMockEnabled] = useState(getOrgMockEnabled());
|
||||
// mock 默认关闭(真实接口);?mock=1 可临时开启演示。变更时间:2026-08-10
|
||||
const mockEnabled = getOrgMockEnabled();
|
||||
|
||||
/**
|
||||
* 列表查询:mock 模式走本地数据;真实模式调用 GET /safetyEval/qual-filing-change/page
|
||||
* (返回 QualFilingChangeCO,字段与 mock 同构)。变更时间:2026-08-10
|
||||
*/
|
||||
const fetchData = async (page = 1, size = 10, useMock = mockEnabled) => {
|
||||
setLoading(true);
|
||||
try {
|
||||
|
|
@ -98,13 +110,17 @@ function RegisteredOrgListPage(props) {
|
|||
if (useMock) {
|
||||
const res = mockQueryRegisteredOrgPage({ ...formData, current: page, size });
|
||||
setDataSource(res.data || []);
|
||||
setTotal(res.totalCount || 0);
|
||||
setTotal(res.total || 0);
|
||||
return;
|
||||
}
|
||||
const res = await props.registeredOrgList({ ...formData, current: page, size });
|
||||
const res = await Get(
|
||||
"/safetyEval/qual-filing-change/page",
|
||||
{ ...formData, current: page, size },
|
||||
{ token: sessionStorage.getItem("token") },
|
||||
);
|
||||
if (res?.success !== false) {
|
||||
setDataSource(res?.data || []);
|
||||
setTotal(res?.totalCount || 0);
|
||||
setTotal(res?.total || 0);
|
||||
}
|
||||
} catch {
|
||||
setDataSource([]);
|
||||
|
|
@ -118,17 +134,11 @@ function RegisteredOrgListPage(props) {
|
|||
fetchData();
|
||||
}, []);
|
||||
|
||||
const handleToggleMock = (v) => {
|
||||
setOrgMockEnabled(v);
|
||||
setMockEnabled(v);
|
||||
setPageIndex(1);
|
||||
fetchData(1, pageSize, v);
|
||||
};
|
||||
|
||||
const goDetail = (id) => {
|
||||
if (!id) {
|
||||
return;
|
||||
}
|
||||
const goDetail = (record) => {
|
||||
// 详情使用变更接口 GET /safetyEval/qual-filing-change/detail,参数为变更记录 id(record.id)。
|
||||
// 变更时间:2026-08-10(用户要求“查看基础信息”使用带 change 的接口)
|
||||
const id = record.id;
|
||||
if (!id) return;
|
||||
const query = `${DETAIL_PATH}?id=${encodeURIComponent(id)}`;
|
||||
if (props.history?.push) {
|
||||
props.history.push(query);
|
||||
|
|
@ -144,17 +154,16 @@ function RegisteredOrgListPage(props) {
|
|||
loading={loading}
|
||||
defaultExpand
|
||||
formLine={[
|
||||
<Form.Item key="unitName" name="unitName">
|
||||
<Form.Item key="filingUnitName" name="filingUnitName">
|
||||
<ControlWrapper.Input label="单位名称" allowClear placeholder="关键字搜索" />
|
||||
</Form.Item>,
|
||||
<Form.Item key="creditCode" name="creditCode">
|
||||
<ControlWrapper.Input label="统一社会信用代码" allowClear placeholder="关键字搜索" />
|
||||
</Form.Item>,
|
||||
<Form.Item key="filingTypeCode" name="filingTypeCode">
|
||||
<ControlWrapper.Select label="备案类型" placeholder="请选择" allowClear options={REGISTERED_ORG_FILING_TYPE_SEARCH_OPTIONS} />
|
||||
</Form.Item>,
|
||||
<Form.Item key="filingRecordStatusCode" name="filingRecordStatusCode">
|
||||
<ControlWrapper.Select label="状态" placeholder="请选择" allowClear options={REGISTERED_ORG_FILING_RECORD_STATUS_OPTIONS} />
|
||||
<Form.Item key="filingStatusCode" name="filingStatusCode">
|
||||
<ControlWrapper.Select
|
||||
label="状态"
|
||||
placeholder="请选择"
|
||||
allowClear
|
||||
options={QUAL_FILING_STATUS_OPTIONS.filter((item) => item.value !== "")}
|
||||
/>
|
||||
</Form.Item>,
|
||||
]}
|
||||
onFinish={() => {
|
||||
|
|
@ -172,11 +181,6 @@ function RegisteredOrgListPage(props) {
|
|||
<span style={{ fontSize: "0.85rem", color: "#64748b" }}>
|
||||
共 <strong style={{ color: "#2563eb" }}>{total || 0}</strong> 条记录
|
||||
</span>
|
||||
<Tag color={mockEnabled ? "warning" : "default"}>
|
||||
{mockEnabled ? "Mock 演示中" : "真实接口"}
|
||||
</Tag>
|
||||
<span style={{ fontSize: "0.78rem", color: "#64748b" }}>Mock 数据</span>
|
||||
<Switch size="small" checked={mockEnabled} onChange={handleToggleMock} />
|
||||
</div>
|
||||
|
||||
<Table
|
||||
|
|
@ -199,20 +203,31 @@ function RegisteredOrgListPage(props) {
|
|||
}}
|
||||
columns={[
|
||||
{ title: "序号", width: 60, render: (_, __, index) => index + 1 },
|
||||
{ title: "单位名称", dataIndex: "unitName", ellipsis: true },
|
||||
{ title: "单位名称", dataIndex: "filingUnitName", ellipsis: true },
|
||||
{ title: "统一社会信用代码", dataIndex: "creditCode", width: 170, ellipsis: true },
|
||||
{
|
||||
title: "是否本地单位",
|
||||
width: 100,
|
||||
// 由 filingUnitTypeName(本地单位/异地单位)判断;变更时间:2026-08-10
|
||||
render: (_, record) =>
|
||||
record.isLocalUnitName || (record.isLocalUnit === 1 ? "是" : record.isLocalUnit === 0 ? "否" : "-"),
|
||||
record.filingUnitTypeName === "本地单位"
|
||||
? "是"
|
||||
: record.filingUnitTypeName === "异地单位"
|
||||
? "否"
|
||||
: "-",
|
||||
},
|
||||
{
|
||||
title: "拟申请/具备法定安全评价业务范围",
|
||||
dataIndex: "businessScopeName",
|
||||
dataIndex: "businessScope",
|
||||
ellipsis: true,
|
||||
render: (v, record) =>
|
||||
v || record.safetyIndustryCategoryName || (Array.isArray(record.businessScope) ? record.businessScope.join(";") : "-"),
|
||||
render: (_, record) => {
|
||||
if (Array.isArray(record.businessScope)) {
|
||||
return record.businessScope
|
||||
.map((item) => QUALIFICATION_INDUSTRY_OPTIONS_MAP[item] || item)
|
||||
.join(";");
|
||||
}
|
||||
return record.businessScope || "-";
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "法定代表人",
|
||||
|
|
@ -221,10 +236,10 @@ function RegisteredOrgListPage(props) {
|
|||
},
|
||||
{
|
||||
title: "提交状态",
|
||||
width: 100,
|
||||
width: 110,
|
||||
render: (_, record) => (
|
||||
<Tag color={getStatusColor(record.filingRecordStatusName, record.filingRecordStatusCode)}>
|
||||
{record.filingRecordStatusName || "-"}
|
||||
<Tag color={getStatusColor(record.filingStatusName)}>
|
||||
{record.filingStatusName || "-"}
|
||||
</Tag>
|
||||
),
|
||||
},
|
||||
|
|
@ -233,7 +248,7 @@ function RegisteredOrgListPage(props) {
|
|||
width: 130,
|
||||
fixed: "right",
|
||||
render: (_, record) => (
|
||||
<Button type="link" onClick={() => goDetail(record.id)}>
|
||||
<Button type="link" onClick={() => goDetail(record)}>
|
||||
查看基础信息
|
||||
</Button>
|
||||
),
|
||||
|
|
|
|||
Loading…
Reference in New Issue