safety-eval-service-frontend/src/pages/Container/QualificationReview/FilingTabs/index.js

222 lines
10 KiB
JavaScript
Raw Normal View History

2026-07-09 17:00:19 +08:00
import React, { useState, useEffect, useMemo } from "react";
2026-07-02 16:58:07 +08:00
import { Button, Descriptions, Table, Tag, Tabs, Select, Modal, Space, Image } from "antd";
import { Connect } from "@cqsjjb/jjb-dva-runtime";
import { NS_QUAL_REVIEW } from "~/enumerate/namespace";
2026-07-09 09:23:22 +08:00
import StaffViewModal from "~/components/StaffViewModal";
2026-07-02 16:58:07 +08:00
import PreviewUrlButton from "~/components/PreviewUrlButton/index";
2026-06-30 15:59:15 +08:00
/**
* 共享组件资质备案 5 个标签页详情 / 审核共用
* @param {Object} props
* @param {Object} props.detail - 备案详情数据
* @param {boolean} [props.isReview=false] - 审核模式开启后材料上传显示"上传附件"+"符合性"
* @param {Object} [props.compliance={}] - 审核模式下的符合性状态
* @param {Function} [props.onComplianceChange] - 符合性变动回调
* @param {Function} [props.onPersonnelView] - 查看人员详情回调覆盖默认弹窗
* @param {Function} [props.onEquipView] - 查看设备详情回调 (record) => void覆盖默认弹窗
*/
const FilingTabs = ({
detail,
isReview = false,
compliance = {},
onComplianceChange,
2026-07-06 16:22:51 +08:00
2026-06-30 15:59:15 +08:00
}) => {
2026-07-02 16:58:07 +08:00
const [viewId, setViewId] = useState("");
2026-07-09 17:00:19 +08:00
const attachmentList = useMemo(() => {
const v = detail.attachmentUrl;
if (!v) return [];
try {
const p = JSON.parse(v);
return Array.isArray(p) ? p : [];
} catch {
return [];
}
}, [detail.attachmentUrl]);
2026-07-02 16:58:07 +08:00
2026-06-30 15:59:15 +08:00
const baseCols = [
{ title: "序号", width: 60, render: (_, __, i) => i + 1 },
2026-07-02 16:58:07 +08:00
{ title: "材料名称", dataIndex: "materialContent" },
2026-06-30 15:59:15 +08:00
];
const materialCols = isReview
? [
...baseCols,
2026-07-02 16:58:07 +08:00
{ title: "上传附件", dataIndex: "attachmentDesc", width: 120 },
{ title: "格式", dataIndex: "materialFormat", width: 80 },
{ title: "状态", width: 100, render: (_, record) => record.uploadStatusCode === 2 ? <Tag color="success">{record.uploadStatusName || "已上传"}</Tag> : <Tag color="warning">{record.uploadStatusName || ""}</Tag> },
2026-06-30 15:59:15 +08:00
{ title: "符合性", width: 100,
render: (_, record) => (
<Select
style={{ width: "100%", fontSize: "0.75rem" }}
size="small"
placeholder="请选择"
value={compliance[record.id]}
2026-07-08 16:20:43 +08:00
allowClear
defaultValue={'pass'}
2026-06-30 15:59:15 +08:00
onChange={(v) => onComplianceChange?.(record.id, v)}
>
<Select.Option value="pass">符合</Select.Option>
<Select.Option value="fail">不符合</Select.Option>
</Select>
),
},
]
: [
...baseCols,
2026-07-02 16:58:07 +08:00
{ title: "格式", dataIndex: "materialFormat", width: 80 },
{ title: "状态", width: 100, render: (_, record) => record.uploadStatusCode === 2 ? <Tag color="success">{record.uploadStatusName || "已上传"}</Tag> : <Tag color="warning">{record.uploadStatusName || ""}</Tag> },
{ title: "操作", width: 80, render: (_, record) => <PreviewUrlButton url={record.attachmentUrl}>预览</PreviewUrlButton> },
2026-06-30 15:59:15 +08:00
];
2026-07-09 17:00:19 +08:00
const commitment= detail.commitment || {};
2026-07-02 16:58:07 +08:00
2026-06-30 15:59:15 +08:00
const items = [
{
key: "info",
label: "1.备案基本信息",
children: (
<Descriptions column={2} bordered size="small" style={{ background: "#fff" }}>
2026-07-02 16:58:07 +08:00
<Descriptions.Item label="申请的业务范围" span={2}>{detail.businessScope}</Descriptions.Item>
<Descriptions.Item label="备案属地">{detail.filingTerritoryName}</Descriptions.Item>
<Descriptions.Item label="备案单位">{detail.filingUnitName}</Descriptions.Item>
<Descriptions.Item label="备案单位类型">{detail.filingUnitTypeName}</Descriptions.Item>
2026-06-30 15:59:15 +08:00
<Descriptions.Item label="统一社会信用代码">{detail.creditCode}</Descriptions.Item>
<Descriptions.Item label="办公地址" span={2}>{detail.officeAddress}</Descriptions.Item>
<Descriptions.Item label="注册地址" span={2}>{detail.registerAddress}</Descriptions.Item>
2026-07-02 16:58:07 +08:00
<Descriptions.Item label="资质证书编号">{detail.qualCertNo}</Descriptions.Item>
<Descriptions.Item label="信息公开网址">{detail.infoDisclosureUrl}</Descriptions.Item>
<Descriptions.Item label="法人代表及电话">{detail.legalPersonPhone}</Descriptions.Item>
<Descriptions.Item label="联系人及电话">{detail.contactPhone}</Descriptions.Item>
<Descriptions.Item label="固定资产总值(万元)">{detail.fixedAssetAmount}</Descriptions.Item>
<Descriptions.Item label="工作场所建筑面积">{detail.workplaceArea}</Descriptions.Item>
<Descriptions.Item label="档案室面积">{detail.archiveRoomArea}</Descriptions.Item>
<Descriptions.Item label="专职安全评价师数量">{detail.fulltimeEvaluatorCount}</Descriptions.Item>
<Descriptions.Item label="注册安全工程师数量">{detail.registeredEngineerCount}</Descriptions.Item>
<Descriptions.Item label="单位基本情况介绍" span={2}>{detail.unitIntro}</Descriptions.Item>
2026-07-09 17:00:19 +08:00
<Descriptions.Item label="附件" span={2}>
{attachmentList.length
? attachmentList.map((item, i) => {
const isImg = /\.(png|jpe?g|gif|bmp|webp|svg)(\?.*)?$/i.test(item.url || "");
return isImg ? (
<Image key={item.url || i} src={item.url} style={{ width: 100, height: 100, objectFit: "cover", marginRight: 8 }} />
) : (
<PreviewUrlButton key={item.url || i} url={item.url}>
{item.name || `附件${i + 1}`}
</PreviewUrlButton>
);
})
: "-"}
</Descriptions.Item>
2026-06-30 15:59:15 +08:00
</Descriptions>
),
},
{
key: "materials",
label: "2.备案材料上传",
children: (
2026-07-02 16:58:07 +08:00
<Table size="small" bordered rowKey="id" pagination={false} dataSource={detail?.materials || []} columns={materialCols} />
2026-06-30 15:59:15 +08:00
),
},
{
key: "promise",
label: "3.法定代表人承诺书",
children: (
<div style={{ border: "1px solid #d9d9d9", borderRadius: 6, 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>
2026-07-02 16:58:07 +08:00
<p>本人{commitment.legalRepName}{detail.filingUnitName}法定代表人现代表我单位承诺如下</p>
2026-06-30 15:59:15 +08:00
<p>我单位自愿申请安全评价机构资质本人已经认真学习了解并掌握安全生产法行政许可法行政处罚法安全评价检测检验机构管理办法等法律法规的相关规定知悉开展安全评价工作的法律责任义务权力和风险</p>
<p>本人承诺本单位满足安全评价检测检验机构管理办法所规定的资质条件要求本人及单位三年内无重大违法失信行为申请资质所提交的有关材料真实合法有效并对其真实性合法性承担相应法律责任接受并配合有关部门对本单位开展的专业能力审查</p>
<p>如能获准资质本单位将严格按照法律法规规章标准的要求开展安全评价活动遵守执业准则和职业道德并对作出的安全评价报告结果承担法律责任自觉接受应急管理部门煤矿安全监督管理部门等行政执法部门的监督检查</p>
2026-07-02 16:58:07 +08:00
<p style={{ marginTop: "0.75rem" }}>法定代表人{commitment.legalRepName}已签名</p>
<Space>
2026-07-03 10:43:29 +08:00
{commitment.legalRepSignatureUrl&&<Image src={commitment.legalRepSignatureUrl} style={{ width: 100, height: 100 }} />}
2026-07-02 16:58:07 +08:00
<p>单位盖章</p>
</Space>
<p style={{ textAlign: "right" }}>{commitment.signDate}</p>
2026-06-30 15:59:15 +08:00
</div>
),
},
{
key: "personnel",
label: "4.备案人员管理",
children: (
2026-07-02 16:58:07 +08:00
<Table size="small" bordered rowKey="id" pagination={false} dataSource={detail?.personnelList || []}
2026-06-30 15:59:15 +08:00
columns={[
{ title: "序号", width: 60, render: (_, __, i) => i + 1 },
2026-07-02 16:58:07 +08:00
{ title: "人员姓名", dataIndex: "personName", width: 100 },
{ title: "类型", dataIndex: "personTypeName", width: 100 },
2026-07-07 15:27:25 +08:00
2026-07-02 16:58:07 +08:00
{ title: "职称", dataIndex: "titleName", width: 100 },
2026-06-30 15:59:15 +08:00
{ title: "操作", width: 80,
2026-07-02 16:58:07 +08:00
render: (_, record) => (
<Button type="link" size="small" onClick={() => setViewId(record.sourcePersonnelId)}>
2026-06-30 15:59:15 +08:00
查看
</Button>
),
},
]}
/>
),
},
{
key: "equipment",
label: "5.装备清单",
children: (
2026-07-02 16:58:07 +08:00
<Table size="small" bordered rowKey="id" pagination={false} dataSource={detail?.equipmentList || []}
2026-06-30 15:59:15 +08:00
columns={[
{ title: "序号", width: 60, render: (_, __, i) => i + 1 },
2026-07-02 16:58:07 +08:00
{ title: "装备名称", dataIndex: "deviceName", width: 140 },
{ title: "规格型号", dataIndex: "deviceModel", width: 120 },
2026-06-30 15:59:15 +08:00
{ title: "生产厂家", dataIndex: "manufacturer", width: 140 },
2026-07-02 16:58:07 +08:00
{ title: "计量检定情况", width: 120,
render: (_, record) => {
if (record.calibrationReportUrl) {
return <Tag color="success">已上传</Tag>;
}
return <Tag color="warning">待上传</Tag>;
2026-06-30 15:59:15 +08:00
},
},
{ title: "操作", width: 80,
render: (_, record) => (
2026-07-02 16:58:07 +08:00
<PreviewUrlButton url={record.calibrationReportUrl}>
2026-06-30 15:59:15 +08:00
查看
2026-07-02 16:58:07 +08:00
</PreviewUrlButton>
2026-06-30 15:59:15 +08:00
),
},
]}
/>
),
},
];
return (
<>
<Tabs items={items} />
{/* 人员详细信息弹窗 */}
2026-07-02 16:58:07 +08:00
<StaffViewModal
open={!!viewId}
currentId={viewId}
onCancel={() => setViewId("")}
/>
2026-06-30 15:59:15 +08:00
2026-07-06 16:22:51 +08:00
2026-07-02 16:58:07 +08:00
</>
2026-06-30 15:59:15 +08:00
);
};
2026-07-02 16:58:07 +08:00
export default Connect(
[NS_QUAL_REVIEW],
true,
)(FilingTabs);