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

766 lines
26 KiB
JavaScript
Raw Normal View History

2026-06-26 17:28:06 +08:00
import {
2026-07-13 15:31:49 +08:00
Button,
2026-08-14 17:32:18 +08:00
Checkbox,
2026-07-13 15:31:49 +08:00
DatePicker,
Descriptions,
Form,
Input,
InputNumber,
message,
Modal,
Row,
Col,
Select,
Space,
Tag,
Table,
2026-06-26 17:28:06 +08:00
} from "antd";
2026-07-07 16:20:22 +08:00
import TableAction from "@cqsjjb/jjb-react-admin-component/TableAction";
2026-07-13 15:31:49 +08:00
import { tools } from "@cqsjjb/jjb-common-lib";
2026-06-26 17:28:06 +08:00
import { Connect } from "@cqsjjb/jjb-dva-runtime";
import { useEffect, useState } from "react";
2026-06-29 16:45:58 +08:00
import PageLayout from "@cqsjjb/jjb-react-admin-component/PageLayout";
2026-08-13 10:26:12 +08:00
import SearchForm from "~/components/SearchForm";
2026-07-07 16:20:22 +08:00
import ControlWrapper from "@cqsjjb/jjb-react-admin-component/ControlWrapper";
2026-07-08 12:59:15 +08:00
import { AntdTableFuncControl } from "@cqsjjb/jjb-common-decorator/antd";
2026-08-13 12:47:39 +08:00
import { QUALIFICATION_INDUSTRY_OPTIONS } from "~/enumerate/enterpriseOptions";
2026-07-07 17:13:33 +08:00
import { isOrgAccountEnabled } from "~/utils/enterpriseInfo/adapter";
2026-06-26 17:28:06 +08:00
import {
CHONGQING_DISTRICTS,
ORG_ACCOUNT_STATE_OPTIONS,
2026-08-13 12:54:53 +08:00
QUALIFICATION_INDUSTRY_OPTIONS_MAP
2026-06-26 17:28:06 +08:00
} from "~/enumerate/enterpriseOptions";
import { NS_ORG_INFO } from "~/enumerate/namespace";
2026-08-14 17:32:18 +08:00
import AttachmentUpload from "~/components/AttachmentUpload";
2026-06-26 17:28:06 +08:00
import { safeListRequest, safeRequest } from "~/utils";
2026-08-14 17:32:18 +08:00
import {
creditCodeRule,
nonNegativeIntegerRule,
normalizeUrl,
phoneRule,
positiveNumberRule,
urlRule,
} from "~/utils/validators";
2026-06-26 17:28:06 +08:00
2026-07-13 15:31:49 +08:00
const { router } = tools;
2026-08-13 12:47:39 +08:00
const CONTACT_SEP = "/";
const mergeContactNamePhone = (name, phone) => {
if (!name && !phone) return undefined;
return [name, phone].filter(Boolean).join(CONTACT_SEP);
};
const splitContactNamePhone = (value) => {
if (!value) return { contactName: undefined, contactPhone: undefined };
const idx = String(value).indexOf(CONTACT_SEP);
if (idx >= 0) {
return {
contactName: String(value).slice(0, idx).trim(),
contactPhone: String(value).slice(idx + 1).trim(),
};
}
return { contactName: String(value).trim(), contactPhone: undefined };
};
2026-06-26 17:28:06 +08:00
function OrgAccountPage(props) {
const [searchForm] = Form.useForm();
const [editForm] = Form.useForm();
const [viewOpen, setViewOpen] = useState(false);
const [editOpen, setEditOpen] = useState(false);
const [currentId, setCurrentId] = useState(null);
const [detail, setDetail] = useState(null);
const [detailLoading, setDetailLoading] = useState(false);
const [editLoading, setEditLoading] = useState(false);
2026-07-07 16:20:22 +08:00
const [dataSource, setDataSource] = useState([]);
const [total, setTotal] = useState(0);
const [loading, setLoading] = useState(false);
2026-06-26 17:28:06 +08:00
2026-07-07 16:20:22 +08:00
const getData = async () => {
setLoading(true);
try {
2026-07-13 11:14:27 +08:00
const raw = searchForm.getFieldsValue();
const params = {
...raw,
2026-07-13 15:31:49 +08:00
current: router.query.current || 1,
pageSize: router.query.pageSize || 10,
state:
raw.state !== "" && raw.state !== undefined
? Number(raw.state)
: undefined,
...(Array.isArray(raw.openTimeRange) &&
raw.openTimeRange[0] &&
raw.openTimeRange[1]
2026-07-13 11:14:27 +08:00
? {
createTimeStart: raw.openTimeRange[0].format("YYYY-MM-DD"),
createTimeEnd: raw.openTimeRange[1].format("YYYY-MM-DD"),
}
: {}),
};
delete params.openTimeRange;
2026-07-13 15:31:49 +08:00
Object.keys(params).forEach((k) => {
if (params[k] === undefined) delete params[k];
});
2026-07-07 16:20:22 +08:00
const res = await safeListRequest(props.orgAccountList)(params);
setDataSource(res?.data || []);
2026-07-13 15:31:49 +08:00
setTotal(res?.total || 0);
2026-07-07 16:20:22 +08:00
} finally {
setLoading(false);
}
};
2026-06-26 17:28:06 +08:00
useEffect(() => {
2026-07-13 15:31:49 +08:00
getData(1, 10);
2026-06-26 17:28:06 +08:00
}, []);
const loadDetail = async (id) => {
setDetailLoading(true);
const res = await safeRequest(props.orgAccountGet, { id });
setDetail(res?.data || null);
setDetailLoading(false);
return res;
};
const openView = async (id) => {
setCurrentId(id);
setViewOpen(true);
await loadDetail(id);
};
const openEdit = async (id) => {
setCurrentId(id);
setEditOpen(true);
const res = await loadDetail(id);
if (res?.data) {
2026-08-14 17:32:18 +08:00
let attachmentUrls = res.data.attachmentUrls;
if (typeof attachmentUrls === "string" && attachmentUrls) {
try { attachmentUrls = JSON.parse(attachmentUrls); } catch {}
}
2026-08-13 12:47:39 +08:00
editForm.setFieldsValue({
...res.data,
2026-08-14 17:32:18 +08:00
attachmentUrls,
2026-08-13 12:47:39 +08:00
contactNamePhone: mergeContactNamePhone(
res.data.contactName,
res.data.contactPhone,
),
});
2026-06-26 17:28:06 +08:00
}
};
const onToggleStatus = (record) => {
const enabled = isOrgAccountEnabled(record);
Modal.confirm({
title: "确认操作",
2026-07-13 15:31:49 +08:00
content: enabled
? `确认禁用「${record.unitName}」账号?`
: `确认启用「${record.unitName}」账号?`,
2026-06-26 17:28:06 +08:00
okText: "确认",
cancelText: "取消",
onOk: async () => {
const nextState = enabled ? 1 : 0;
2026-07-13 15:31:49 +08:00
const res = await props.orgAccountUpdateState({
id: record.id,
state: nextState,
});
2026-06-26 17:28:06 +08:00
if (res?.success !== false) {
message.success("操作成功");
await getData();
}
},
});
};
const onResetPassword = (record) => {
2026-07-07 17:45:27 +08:00
console.log(record);
2026-06-26 17:28:06 +08:00
Modal.confirm({
title: "重置密码",
content: (
<div>
<p>
确认将
2026-07-13 11:14:27 +08:00
<strong>{record.unitName}</strong>
2026-06-26 17:28:06 +08:00
的密码重置为初始密码
</p>
2026-08-17 11:22:53 +08:00
<p style={{ color: "rgba(0,0,0,0.45)", fontSize: 14 }}>
2026-07-13 15:31:49 +08:00
初始密码a123456
</p>
2026-06-26 17:28:06 +08:00
</div>
),
okText: "确认重置",
cancelText: "取消",
onOk: async () => {
2026-07-07 17:45:27 +08:00
const res = await props.orgAccountResetPassword({ data: record.id });
2026-06-26 17:28:06 +08:00
if (res?.success !== false) {
message.success("密码已重置");
}
},
});
};
const onDelete = (record) => {
Modal.confirm({
title: "确认删除",
content: (
<div>
<p>
确认删除
2026-07-13 11:14:27 +08:00
<strong>{record.unitName}</strong>
2026-06-26 17:28:06 +08:00
的账号
</p>
2026-08-17 11:22:53 +08:00
<p style={{ color: "rgba(0,0,0,0.45)", fontSize: 14 }}>
2026-07-13 15:31:49 +08:00
此操作不可恢复请谨慎操作
</p>
2026-06-26 17:28:06 +08:00
</div>
),
okText: "确认删除",
okButtonProps: { danger: true },
cancelText: "取消",
onOk: async () => {
2026-07-07 17:45:27 +08:00
const res = await props.orgAccountDelete({ data: record.id });
2026-06-26 17:28:06 +08:00
if (res?.success !== false) {
message.success("删除成功");
await getData();
}
},
});
};
const onEditSubmit = async () => {
2026-08-13 12:47:39 +08:00
const formValues = await editForm.validateFields();
const split = splitContactNamePhone(formValues.contactNamePhone);
2026-08-14 17:32:18 +08:00
const contactName = split.contactName
? split.contactName.replace(/\s+/g, "")
: undefined;
const contactPhone = split.contactPhone
? split.contactPhone.replace(/\s+/g, "")
: undefined;
2026-08-13 12:47:39 +08:00
const values = {
...formValues,
2026-08-14 17:32:18 +08:00
contactName,
contactPhone,
2026-08-13 12:47:39 +08:00
contactNamePhone: undefined,
2026-08-14 17:32:18 +08:00
attachmentUrls: formValues.attachmentUrls
? JSON.stringify(formValues.attachmentUrls)
: undefined,
infoDisclosureUrl: formValues.infoDisclosureUrl
? normalizeUrl(formValues.infoDisclosureUrl)
: undefined,
2026-06-26 17:28:06 +08:00
id: currentId,
2026-08-13 12:47:39 +08:00
};
setEditLoading(true);
const res = await props.orgAccountModify(values);
2026-06-26 17:28:06 +08:00
setEditLoading(false);
if (res?.success !== false) {
message.success("保存成功");
setEditOpen(false);
setCurrentId(null);
editForm.resetFields();
await getData();
}
};
2026-07-07 16:20:22 +08:00
const columns = [
2026-08-14 17:32:18 +08:00
{ title: "单位名称", dataIndex: "unitName", ellipsis: true },
{
title: "拟申请的法定安全评价业务范围",
dataIndex: "safetyIndustryCategoryCode",
ellipsis: true,
render: (codes) =>
(Array.isArray(codes) ? codes : [])
.map((code) => QUALIFICATION_INDUSTRY_OPTIONS_MAP[code] || code)
.join("、") || "-",
},
{ title: "办公地址", dataIndex: "businessAddress", ellipsis: true },
2026-07-07 16:20:22 +08:00
{
title: "状态",
width: 80,
render: (_, record) => (
<Tag color={isOrgAccountEnabled(record) ? "success" : "error"}>
{isOrgAccountEnabled(record) ? "启用" : "禁用"}
</Tag>
),
},
2026-08-17 16:55:05 +08:00
{ title: "开户时间", dataIndex: "createTime", width: 155 },
2026-07-07 16:20:22 +08:00
{
title: "操作",
2026-07-13 11:14:27 +08:00
width: 200,
2026-07-07 16:20:22 +08:00
fixed: "right",
render: (_, record) => (
<TableAction>
2026-07-13 15:31:49 +08:00
<Button type="link" size="small" onClick={() => openView(record.id)}>
查看
</Button>
<Button type="link" size="small" onClick={() => openEdit(record.id)}>
编辑
</Button>
<Button
type="link"
size="small"
onClick={() => onResetPassword(record)}
>
重置密码
</Button>
<Button
type="link"
size="small"
danger
onClick={() => onDelete(record)}
>
删除
</Button>
<Button
type="link"
size="small"
onClick={() => onToggleStatus(record)}
>
2026-07-07 16:20:22 +08:00
{isOrgAccountEnabled(record) ? "禁用" : "启用"}
</Button>
</TableAction>
),
},
];
2026-06-26 17:28:06 +08:00
return (
2026-06-30 18:30:30 +08:00
<PageLayout
title={
<div>
2026-08-03 17:16:23 +08:00
<span>机构账号管理</span>
2026-07-13 15:31:49 +08:00
<div className="pageLayout-extra">监管端维护评价机构开户账号</div>
2026-06-30 18:30:30 +08:00
</div>
}
>
2026-07-07 16:20:22 +08:00
<SearchForm
style={{ marginBottom: 24 }}
2026-06-26 17:28:06 +08:00
form={searchForm}
2026-07-07 16:20:22 +08:00
loading={loading}
formLine={[
2026-07-13 11:14:27 +08:00
<Form.Item key="unitName" name="unitName">
2026-07-13 15:31:49 +08:00
<ControlWrapper.Input
label="机构名称"
placeholder="关键字搜索"
allowClear
/>
2026-07-07 16:20:22 +08:00
</Form.Item>,
2026-07-13 11:14:27 +08:00
<Form.Item key="districtName" name="districtName">
2026-07-13 15:31:49 +08:00
<ControlWrapper.Select
label="属地"
placeholder="请选择属地"
allowClear
>
2026-07-07 16:20:22 +08:00
{CHONGQING_DISTRICTS.map((opt) => (
2026-07-13 15:31:49 +08:00
<Select.Option key={opt.value} value={opt.value}>
{opt.label}
</Select.Option>
2026-07-07 16:20:22 +08:00
))}
</ControlWrapper.Select>
</Form.Item>,
<Form.Item key="state" name="state">
2026-07-13 15:31:49 +08:00
<ControlWrapper.Select
label="状态"
placeholder="请选择状态"
allowClear
>
2026-07-07 16:20:22 +08:00
{ORG_ACCOUNT_STATE_OPTIONS.map((opt) => (
2026-07-13 15:31:49 +08:00
<Select.Option key={opt.value} value={opt.value}>
{opt.label}
</Select.Option>
2026-07-07 16:20:22 +08:00
))}
</ControlWrapper.Select>
</Form.Item>,
<Form.Item key="openTimeRange" name="openTimeRange">
2026-07-13 15:31:49 +08:00
<ControlWrapper.DatePicker.RangePicker
label="开户时间"
allowClear
/>
2026-07-07 16:20:22 +08:00
</Form.Item>,
2026-06-26 17:28:06 +08:00
]}
2026-07-13 15:31:49 +08:00
onReset={(values) => {
2026-07-07 16:20:22 +08:00
searchForm.resetFields();
2026-07-13 15:31:49 +08:00
router.query = {
...values,
current: 1,
pageSize: 10,
};
2026-07-07 16:20:22 +08:00
getData();
}}
2026-07-13 15:31:49 +08:00
onFinish={(values) => {
router.query = {
...values,
current: 1,
pageSize: 10,
};
2026-08-13 12:47:39 +08:00
getData();
2026-07-13 15:31:49 +08:00
}}
2026-06-26 17:28:06 +08:00
/>
<Table
2026-07-07 16:20:22 +08:00
rowKey="id"
columns={columns}
dataSource={dataSource}
scroll={{ y: props.scrollY }}
loading={loading}
pagination={{
total,
showSizeChanger: true,
showQuickJumper: true,
showTotal: (t) => `${t}`,
2026-07-13 15:31:49 +08:00
current: router.query.current || 1,
pageSize: router.query.pageSize || 10,
2026-07-07 16:20:22 +08:00
onChange: (page, pageSize) => {
2026-07-13 15:31:49 +08:00
router.query = { ...router.query, current: page, pageSize };
2026-07-07 16:20:22 +08:00
getData();
2026-06-26 17:28:06 +08:00
},
2026-07-07 16:20:22 +08:00
}}
2026-06-26 17:28:06 +08:00
/>
<Modal
open={viewOpen}
2026-07-06 18:06:49 +08:00
destroyOnHidden
2026-06-26 17:28:06 +08:00
title="机构信息查看"
2026-08-17 16:55:05 +08:00
width={1000}
2026-06-26 17:28:06 +08:00
loading={detailLoading}
cancelText="关闭"
okButtonProps={{ style: { display: "none" } }}
2026-07-13 15:31:49 +08:00
onCancel={() => {
setViewOpen(false);
setDetail(null);
}}
2026-06-26 17:28:06 +08:00
>
{detail && (
2026-08-17 16:55:05 +08:00
<Descriptions bordered column={2} size="small" labelStyle={{ width: 165 }}>
2026-08-14 17:32:18 +08:00
<Descriptions.Item label="单位名称">
2026-07-13 15:31:49 +08:00
{detail.unitName}
</Descriptions.Item>
<Descriptions.Item label="统一社会信用代码">
{detail.creditCode}
</Descriptions.Item>
2026-08-14 17:32:18 +08:00
<Descriptions.Item label="营业执照" span={2}>
{(() => {
let files = [];
if (Array.isArray(detail.attachmentUrls)) {
files = detail.attachmentUrls;
} else if (typeof detail.attachmentUrls === "string" && detail.attachmentUrls) {
try { files = JSON.parse(detail.attachmentUrls); } catch {}
}
if (!files.length) return "-";
return files.map((f, i) => (
<a key={i} href={f.url} target="_blank" rel="noreferrer" style={{ marginRight: 8 }}>
{f.name || f.url}
</a>
));
})()}
2026-07-13 15:31:49 +08:00
</Descriptions.Item>
2026-08-14 17:32:18 +08:00
<Descriptions.Item label="注册地址" span={2}>
{detail.registerAddress || "-"}
2026-07-13 15:31:49 +08:00
</Descriptions.Item>
2026-08-14 17:32:18 +08:00
<Descriptions.Item label="办公地址" span={2}>
{detail.businessAddress || "-"}
2026-07-13 15:31:49 +08:00
</Descriptions.Item>
2026-08-14 17:32:18 +08:00
<Descriptions.Item label="信息公开网址">
{detail.infoDisclosureUrl || "-"}
2026-07-13 15:31:49 +08:00
</Descriptions.Item>
2026-08-14 17:32:18 +08:00
<Descriptions.Item label="资质证书编号">
{detail.qualificationCertNo || "-"}
2026-07-13 15:31:49 +08:00
</Descriptions.Item>
<Descriptions.Item label="法定代表人">
2026-08-14 17:32:18 +08:00
{detail.legalRepresentative || "-"}
</Descriptions.Item>
<Descriptions.Item label="法定代表人电话">
{detail.legalRepresentativePhone || "-"}
</Descriptions.Item>
<Descriptions.Item label="传真">
{detail.fax || "-"}
</Descriptions.Item>
<Descriptions.Item label="联系人及电话">
{mergeContactNamePhone(detail.contactName, detail.contactPhone) || "-"}
</Descriptions.Item>
<Descriptions.Item label="固定资产总值(万元)">
{detail.fixedAssetsTotal ?? "-"}
2026-07-13 15:31:49 +08:00
</Descriptions.Item>
2026-08-14 17:32:18 +08:00
<Descriptions.Item label="工作场所建筑面积(㎡)">
{detail.workplaceArea ?? "-"}
2026-07-13 15:31:49 +08:00
</Descriptions.Item>
2026-08-14 17:32:18 +08:00
<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.safetyIndustryCategoryCode || [])
.map((code) => QUALIFICATION_INDUSTRY_OPTIONS_MAP[code] || code)
.join("、") || "-"}
</Descriptions.Item>
<Descriptions.Item label="单位基本情况介绍" span={2}>
{detail.orgIntro || "-"}
2026-07-13 15:31:49 +08:00
</Descriptions.Item>
2026-06-26 17:28:06 +08:00
</Descriptions>
)}
</Modal>
<Modal
open={editOpen}
2026-07-06 18:06:49 +08:00
destroyOnHidden
2026-06-26 17:28:06 +08:00
title="编辑机构信息"
2026-08-14 17:32:18 +08:00
width={900}
2026-06-26 17:28:06 +08:00
confirmLoading={editLoading}
okText="保存"
cancelText="取消"
onCancel={() => {
setEditOpen(false);
setCurrentId(null);
editForm.resetFields();
}}
onOk={onEditSubmit}
>
2026-08-11 13:46:02 +08:00
<Form form={editForm} layout="vertical" scrollToFirstError>
2026-06-26 17:28:06 +08:00
<Row gutter={16}>
<Col span={12}>
2026-07-13 15:31:49 +08:00
<Form.Item
name="unitName"
2026-08-14 17:32:18 +08:00
label="单位名称"
rules={[{ required: true, message: "请输入单位名称" }]}
2026-07-13 15:31:49 +08:00
>
2026-08-14 17:32:18 +08:00
<Input placeholder="请输入单位名称" allowClear maxLength={200} />
2026-06-26 17:28:06 +08:00
</Form.Item>
</Col>
<Col span={12}>
2026-07-13 15:31:49 +08:00
<Form.Item
name="creditCode"
label="统一社会信用代码"
2026-08-14 17:32:18 +08:00
rules={[creditCodeRule(true)]}
2026-07-13 15:31:49 +08:00
>
2026-08-14 17:32:18 +08:00
<Input placeholder="请输入统一社会信用代码" allowClear maxLength={18} />
</Form.Item>
</Col>
<Col span={24}>
<AttachmentUpload
name="attachmentUrls"
label="营业执照"
accept=".pdf,.jpg,.jpeg,.png"
maxCount={5}
extra="支持上传营业执照扫描件限定pdf和图片最多5个。"
rules={[{ required: true, message: "请上传营业执照" }]}
/>
</Col>
<Col span={24}>
<Form.Item
name="registerAddress"
label="注册地址"
rules={[{ required: true, message: "请输入注册地址" }]}
>
<Input placeholder="请输入注册地址" maxLength={500} />
</Form.Item>
</Col>
<Col span={24}>
<Form.Item
name="businessAddress"
label="办公地址"
rules={[{ required: true, message: "请输入办公地址" }]}
>
<Input.TextArea rows={3} placeholder="请输入办公地址" maxLength={500} />
2026-06-26 17:28:06 +08:00
</Form.Item>
</Col>
<Col span={12}>
2026-08-14 17:32:18 +08:00
<Form.Item
name="infoDisclosureUrl"
label="信息公开网址"
rules={[urlRule("信息公开网址", true)]}
normalize={(value) =>
typeof value === "string" ? value.trim() : value
}
>
<Input placeholder="请输入信息公开网址" allowClear maxLength={500} />
2026-06-26 17:28:06 +08:00
</Form.Item>
</Col>
<Col span={12}>
2026-08-14 17:32:18 +08:00
<Form.Item
name="qualificationCertNo"
label="资质证书编号"
extra="非必填,初次申请无需填写"
>
<Input placeholder="初次申请无需填写" allowClear maxLength={100} />
2026-06-26 17:28:06 +08:00
</Form.Item>
</Col>
2026-08-14 17:32:18 +08:00
<Col span={12}>
<Form.Item
name="legalRepresentative"
label="法定代表人"
rules={[{ required: true, message: "请输入法定代表人" }]}
>
<Input placeholder="请输入法定代表人" allowClear maxLength={50} />
2026-06-26 17:28:06 +08:00
</Form.Item>
</Col>
2026-08-14 17:32:18 +08:00
<Col span={12}>
<Form.Item
name="legalRepresentativePhone"
label="法定代表人电话"
rules={[phoneRule("法定代表人电话", true)]}
normalize={(value) =>
typeof value === "string" ? value.trim() : value
}
>
<Input placeholder="请输入法定代表人电话" allowClear maxLength={20} />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item name="fax" label="传真" rules={[{ required: true, message: "请输入传真" }]}>
<Input placeholder="请输入传真" allowClear maxLength={20} />
2026-06-26 17:28:06 +08:00
</Form.Item>
</Col>
<Col span={12}>
2026-08-13 12:47:39 +08:00
<Form.Item
name="contactNamePhone"
label="联系人及电话"
validateFirst
rules={[
{ required: true, message: "请输入联系人及电话" },
{
validator: (_, value) => {
const { contactName, contactPhone } =
splitContactNamePhone(value);
if (!contactName) {
return Promise.reject(new Error("联系人不能为空"));
}
if (contactName.length > 50) {
return Promise.reject(new Error("联系人不能超过50字"));
}
if (!contactPhone) {
return Promise.reject(
new Error("请使用/分隔联系人和电话,并填写电话"),
);
}
if (
!/^(1[3-9]\d{9}|\d{10,12})$/.test(
String(contactPhone).replace(/\s+/g, ""),
)
) {
return Promise.reject(
new Error("电话格式不正确手机11位或固话区号+号码)"),
);
}
if (contactPhone.length > 20) {
return Promise.reject(new Error("电话不能超过20字"));
}
return Promise.resolve();
},
},
]}
extra="请使用/分隔联系人和电话,如:张三/13800138000"
>
<Input
placeholder="如:张三/13800138000"
allowClear
maxLength={73}
/>
2026-06-26 17:28:06 +08:00
</Form.Item>
</Col>
<Col span={12}>
2026-08-13 12:47:39 +08:00
<Form.Item
2026-08-14 17:32:18 +08:00
name="fixedAssetsTotal"
label="固定资产总值(万元)"
2026-08-13 12:47:39 +08:00
rules={[
2026-08-14 17:32:18 +08:00
{ required: true, message: "请输入固定资产总值" },
2026-08-13 12:47:39 +08:00
{
2026-08-14 17:32:18 +08:00
validator: (_, value) => {
if (value === undefined || value === null || value === "") {
return Promise.resolve();
}
if (Number(value) < 0) {
return Promise.reject(new Error("固定资产总值应为非负数字"));
}
return Promise.resolve();
},
2026-08-13 12:47:39 +08:00
},
]}
>
2026-08-14 17:32:18 +08:00
<InputNumber style={{ width: "100%" }} min={0} precision={4} max={99999999999} allowClear placeholder="请输入固定资产总值" />
2026-06-26 17:28:06 +08:00
</Form.Item>
</Col>
<Col span={12}>
2026-08-14 17:32:18 +08:00
<Form.Item
name="workplaceArea"
label="工作场所建筑面积(㎡)"
rules={[positiveNumberRule("工作场所建筑面积", true)]}
>
<InputNumber style={{ width: "100%" }} min={0} max={99999} precision={2} placeholder="请输入工作场所建筑面积" />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
name="archiveRoomArea"
label="档案室面积(㎡)"
rules={[positiveNumberRule("档案室面积", true)]}
>
<InputNumber style={{ width: "100%" }} min={0} max={99999} precision={2} placeholder="请输入档案室面积" />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
name="fulltimeEvaluatorCount"
label="专职安全评价师数量"
rules={[nonNegativeIntegerRule("专职安全评价师数量", true)]}
>
<InputNumber style={{ width: "100%" }} min={0} max={99999} precision={0} placeholder="请输入专职安全评价师数量" />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
name="registeredEngineerCount"
label="注册安全工程师数量"
rules={[nonNegativeIntegerRule("注册安全工程师数量", true)]}
>
<InputNumber style={{ width: "100%" }} min={0} max={99999} precision={0} placeholder="请输入注册安全工程师数量" />
</Form.Item>
</Col>
<Col span={24}>
<Form.Item
name="safetyIndustryCategoryCode"
label="拟申请的法定安全评价业务范围"
rules={[{ required: true, message: "请选择拟申请的法定安全评价业务范围" }]}
>
<Checkbox.Group
style={{
display: "grid",
gridTemplateColumns: "repeat(2, minmax(0, 1fr))",
2026-08-17 11:22:53 +08:00
gap: "9.1px 14px",
padding: "14px",
2026-08-14 17:32:18 +08:00
border: "1px solid #e2e8f0",
borderRadius: 8,
background: "#f8fafc",
}}
>
{QUALIFICATION_INDUSTRY_OPTIONS.map((opt) => (
<Checkbox key={opt.value} value={opt.value}>
{opt.label}
</Checkbox>
))}
</Checkbox.Group>
</Form.Item>
</Col>
<Col span={24}>
<Form.Item
name="orgIntro"
label="单位基本情况介绍(可附页)"
rules={[{ required: true, message: "请输入单位基本情况介绍" }]}
>
<Input.TextArea
rows={7}
placeholder="请简要介绍单位基本情况,如成立时间、人员构成、技术力量、业绩等"
maxLength={2000}
showCount
2026-07-13 15:31:49 +08:00
/>
2026-06-26 17:28:06 +08:00
</Form.Item>
</Col>
</Row>
</Form>
</Modal>
2026-06-29 16:45:58 +08:00
</PageLayout>
2026-06-26 17:28:06 +08:00
);
}
2026-07-13 15:31:49 +08:00
export default Connect(
[NS_ORG_INFO],
true,
)(AntdTableFuncControl(OrgAccountPage));