基础信息修改
parent
9908a0093a
commit
36dec6aa92
|
|
@ -0,0 +1,17 @@
|
|||
E:\works\projects\safety-eval-service-frontend\node_modules\@cqsjjb\scripts\node_modules\@rspack\dev-server\dist\server.js:1658
|
||||
throw error;
|
||||
^
|
||||
|
||||
Error: listen EADDRINUSE: address already in use 0.0.0.0:8081
|
||||
at Server.setupListenHandle [as _listen2] (node:net:1941:16)
|
||||
at listenInCluster (node:net:1998:12)
|
||||
at node:net:2207:7
|
||||
at process.processTicksAndRejections (node:internal/process/task_queues:89:21) {
|
||||
code: 'EADDRINUSE',
|
||||
errno: -4091,
|
||||
syscall: 'listen',
|
||||
address: '0.0.0.0',
|
||||
port: 8081
|
||||
}
|
||||
|
||||
Node.js v22.23.1
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
|
||||
> micro-app@2.0.0 serve:development
|
||||
> cross-env NODE_ENV=development npm run serve
|
||||
|
||||
|
||||
> micro-app@2.0.0 serve
|
||||
> node node_modules/@cqsjjb/scripts/rspack.dev.server.js
|
||||
|
||||
[90m14:19:46[39m [Module] [34m[INFO][39m [90mBabel 配置文件已加载: [37mE:\works\projects\safety-eval-service-frontend//jjb.babel.js[90m[39m
|
||||
[90m14:19:46[39m [Config] [34m[INFO][39m [36m正在加载配置文件...[39m
|
||||
[90m14:19:46[39m [Config] [34m[INFO][39m [90m配置文件已加载: [37mE:\works\projects\safety-eval-service-frontend//jjb.config.js[90m[39m
|
||||
[90m14:19:46[39m [Config] [32m[SUCCESS][39m [32m配置验证通过[39m
|
||||
[90m14:19:46[39m [Config] [34m[INFO][39m [90m运行模式: [32mdevelopment[90m[39m
|
||||
[90m14:19:46[39m [DevServer] [34m[INFO][39m [90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━[39m
|
||||
[90m14:19:46[39m [DevServer] [34m[INFO][39m [90m运行模式: [32mdevelopment[90m[39m
|
||||
[90m14:19:47[39m [DevServer] [34m[INFO][39m [36m正在启动 开发服务器...[39m
|
||||
[90m14:19:47[39m [DevServer] [34m[INFO][39m [36m正在编译...[39m
|
||||
|
|
@ -1,39 +1,26 @@
|
|||
import { Connect } from "@cqsjjb/jjb-dva-runtime";
|
||||
import {
|
||||
Button,
|
||||
Checkbox,
|
||||
Col,
|
||||
DatePicker,
|
||||
Form,
|
||||
Input,
|
||||
InputNumber,
|
||||
message,
|
||||
Row,
|
||||
Select,
|
||||
Space,
|
||||
Flex,
|
||||
} from "antd";
|
||||
import AttachmentUpload from "~/components/AttachmentUpload";
|
||||
import BaiduMapPicker from "~/components/BaiduMapPicker";
|
||||
import dayjs from "dayjs";
|
||||
import { useEffect, useState } from "react";
|
||||
import PageLayout from "@cqsjjb/jjb-react-admin-component/PageLayout";
|
||||
import { NATIONAL_COUNTIES } from "~/enumerate/constant";
|
||||
|
||||
import {
|
||||
ENTERPRISE_SCALE_OPTIONS,
|
||||
ENTERPRISE_STATUS_OPTIONS,
|
||||
REGISTERED_ORG_FILING_RECORD_STATUS_OPTIONS,
|
||||
REGISTERED_ORG_FILING_TYPE_SEARCH_OPTIONS,
|
||||
QUALIFICATION_INDUSTRY_OPTIONS,
|
||||
ECONOMY_INDUSTRY_OPTIONS,
|
||||
} from "~/enumerate/enterpriseOptions";
|
||||
// 2026-08-08 变更:按原型 V1.6 institution.html 的 #mod-org-info 模块 1:1 还原机构基础信息表单。
|
||||
// 复用既有「安全生产监管行业类别」枚举作为「拟申请的法定安全评价业务范围」候选项,
|
||||
// 二者取值集合完全一致(煤矿/金属非金属矿/陆地油气/油气管道/石油化工医药/烟花爆竹/金属冶炼),无需新增枚举。
|
||||
import { QUALIFICATION_INDUSTRY_OPTIONS } from "~/enumerate/enterpriseOptions";
|
||||
import { NS_ORG_INFO } from "~/enumerate/namespace";
|
||||
|
||||
import {
|
||||
coordinatePairRule,
|
||||
creditCodeRule,
|
||||
latitudeRule,
|
||||
longitudeRule,
|
||||
nonNegativeIntegerRule,
|
||||
normalizeUrl,
|
||||
phoneRule,
|
||||
|
|
@ -41,13 +28,59 @@ import {
|
|||
urlRule,
|
||||
} from "~/utils/validators";
|
||||
|
||||
/**
|
||||
* 2026-08-08 新增:业务范围在后端为 varchar(500) 的「逗号分隔字符串」(apply_business_scope),
|
||||
* 而原型要求多选交互,故在页面出入口做数组/字符串互转。
|
||||
* 不做字段名映射,仅做同名字段的值形态转换,保持前后端字段名一致。
|
||||
*/
|
||||
const splitBusinessScope = (value) => {
|
||||
if (Array.isArray(value)) return value;
|
||||
if (!value) return undefined;
|
||||
return String(value)
|
||||
.split(",")
|
||||
.map((item) => item.trim())
|
||||
.filter(Boolean);
|
||||
};
|
||||
|
||||
const joinBusinessScope = (value) =>
|
||||
Array.isArray(value) ? value.join(",") : value || undefined;
|
||||
|
||||
/**
|
||||
* 2026-08-08 联系人及电话合并/拆分工具(交互约定见下方说明):
|
||||
* 录入:单输入框,值格式「联系人/电话」,用 / 分隔。
|
||||
* 提交前:按首个 / 拆为 contactName(/前)+ contactPhone(/后)两字段,传给后端。
|
||||
* 回显:后端 contactName/contactPhone 用 / 合并回单输入框。
|
||||
* 后端落库:contact_name varchar(50)、contact_phone varchar(20);原 contact_name_phone 列保留不删、不再写入。
|
||||
* 复用要点:其他页面如需同样交互,保持「单输入框 + / 分隔 + 提交拆分存两列 + 回显合并」即可。
|
||||
* 注意:分隔符为单斜杠「/」(无空格),与录入示例"张三/13800138000"一致。
|
||||
*/
|
||||
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 };
|
||||
};
|
||||
|
||||
function OrgInfoPage(props) {
|
||||
const [form] = Form.useForm();
|
||||
const { orgInfoLoading } = props.orgInfo;
|
||||
const [editing, setEditing] = useState(true);
|
||||
const [submitting, setSubmitting] = useState(false);
|
||||
const [detail, setDetail] = useState({});
|
||||
const [mapPickerVisible, setMapPickerVisible] = useState(false);
|
||||
/** 是否已存在机构数据(有 id 视为已入库,只能修改) */
|
||||
const [hasExistingData, setHasExistingData] = useState(false);
|
||||
|
||||
|
|
@ -58,12 +91,13 @@ function OrgInfoPage(props) {
|
|||
setDetail(res.data);
|
||||
form.setFieldsValue({
|
||||
...res.data,
|
||||
productionDate: res.data.productionDate
|
||||
? dayjs(res.data.productionDate)
|
||||
: undefined,
|
||||
attachmentUrls: res.data.attachmentUrls
|
||||
? JSON.parse(res.data.attachmentUrls)
|
||||
: null,
|
||||
// 2026-08-08 业务范围回填为数组以适配多选控件
|
||||
applyBusinessScope: splitBusinessScope(res.data.applyBusinessScope),
|
||||
// 2026-08-08 联系人及电话:后端 contactName/contactPhone 两列合并为单字段展示
|
||||
contactNamePhone: mergeContactNamePhone(
|
||||
res.data.contactName,
|
||||
res.data.contactPhone,
|
||||
),
|
||||
});
|
||||
setHasExistingData(true);
|
||||
setEditing(false);
|
||||
|
|
@ -91,14 +125,23 @@ function OrgInfoPage(props) {
|
|||
const handleSave = async (submitType) => {
|
||||
try {
|
||||
const formValues = await form.validateFields();
|
||||
// 2026-08-08 联系人及电话:单字段拆分为后端 contactName / contactPhone 两列提交
|
||||
const split = splitContactNamePhone(formValues.contactNamePhone);
|
||||
// 剔除多余字符:姓名/电话做 trim 与空白清理(校验已保证格式,此处仅兜底)
|
||||
const contactName = split.contactName
|
||||
? split.contactName.replace(/\s+/g, "")
|
||||
: undefined;
|
||||
const contactPhone = split.contactPhone
|
||||
? split.contactPhone.replace(/\s+/g, "")
|
||||
: undefined;
|
||||
const values = {
|
||||
...formValues,
|
||||
productionDate: formValues.productionDate
|
||||
? dayjs(formValues.productionDate).format("YYYY-MM-DD")
|
||||
: undefined,
|
||||
attachmentUrls: formValues.attachmentUrls
|
||||
? JSON.stringify(formValues.attachmentUrls)
|
||||
: null,
|
||||
contactName,
|
||||
contactPhone,
|
||||
// 移除仅用于展示的合并字段,避免提交冗余
|
||||
contactNamePhone: undefined,
|
||||
// 2026-08-08 多选业务范围按后端 varchar(500) 约定以逗号拼接提交
|
||||
applyBusinessScope: joinBusinessScope(formValues.applyBusinessScope),
|
||||
infoDisclosureUrl: formValues.infoDisclosureUrl
|
||||
? normalizeUrl(formValues.infoDisclosureUrl)
|
||||
: undefined,
|
||||
|
|
@ -132,18 +175,14 @@ function OrgInfoPage(props) {
|
|||
setSubmitting(false);
|
||||
}
|
||||
};
|
||||
const handleMapConfirm = ({ lng, lat }) => {
|
||||
form.setFieldsValue({ longitude: lng, latitude: lat });
|
||||
setMapPickerVisible(false);
|
||||
};
|
||||
|
||||
return (
|
||||
<PageLayout
|
||||
title={
|
||||
<div>
|
||||
{/* 2026-08-08 标题/副标题对齐原型 institution.html #mod-org-info */}
|
||||
<span>基础信息管理</span>
|
||||
<div className="pageLayout-extra">
|
||||
新成立或首次使用系统的安全评价机构,可通过系统提供的引导页面,详细填写机构的基本信息。
|
||||
机构注册认证信息,可在此持续维护并提交审核。
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
|
@ -160,19 +199,33 @@ function OrgInfoPage(props) {
|
|||
)
|
||||
}
|
||||
>
|
||||
<Form form={form} labelCol={{ span: 10 }} disabled={!editing}>
|
||||
{/*
|
||||
2026-08-08 布局对齐原型 institution.html:
|
||||
原型 .form-grid 为两列网格、label 在控件上方(纵向),gap 1rem。
|
||||
此处使用 antd Form layout="vertical" + Row/Col 两列还原,整行字段 span=24。
|
||||
2026-08-08 按原型 .info-card 增加带边框容器并整体居中(border-radius 8px、padding 1.25rem、maxWidth 960px 居中)。
|
||||
*/}
|
||||
<div
|
||||
style={{
|
||||
width: "94%",
|
||||
maxWidth: "100%",
|
||||
margin: "0 auto",
|
||||
border: "1px solid #e2e8f0",
|
||||
borderRadius: 8,
|
||||
padding: "1.25rem",
|
||||
background: "#fff",
|
||||
}}
|
||||
>
|
||||
<Form form={form} layout="vertical" disabled={!editing}>
|
||||
<Row gutter={[16, 16]}>
|
||||
{/* 2026-08-08 字段顺序严格对齐原型 institution.html 434-450 行 */}
|
||||
<Col span={12}>
|
||||
<Form.Item
|
||||
name="unitName"
|
||||
label="生产经营单位名称"
|
||||
rules={[{ required: true, message: "请输入生产经营单位名称" }]}
|
||||
label="单位名称"
|
||||
rules={[{ required: true, message: "请输入单位名称" }]}
|
||||
>
|
||||
<Input
|
||||
placeholder="请输入生产经营单位名称"
|
||||
allowClear
|
||||
maxLength={200}
|
||||
/>
|
||||
<Input placeholder="请输入单位名称" allowClear maxLength={200} />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
|
|
@ -188,180 +241,59 @@ function OrgInfoPage(props) {
|
|||
/>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<Form.Item
|
||||
name="safetyIndustryCategoryCode"
|
||||
label="安全生产监管行业类别"
|
||||
rules={[
|
||||
{ required: true, message: "请选择安全生产监管行业类别" },
|
||||
]}
|
||||
>
|
||||
<Select
|
||||
options={QUALIFICATION_INDUSTRY_OPTIONS}
|
||||
mode="multiple"
|
||||
placeholder="请选择安全生产监管行业类别"
|
||||
allowClear
|
||||
onChange={(value, option) => {
|
||||
form.setFieldValue(
|
||||
"safetyIndustryCategoryName",
|
||||
option?.map((item) => item.label).join(",") || "",
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item name="safetyIndustryCategoryName" noStyle />
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<Form.Item
|
||||
name="districtCode"
|
||||
label="属地"
|
||||
rules={[{ required: true, message: "请选择属地" }]}
|
||||
>
|
||||
<Select
|
||||
options={NATIONAL_COUNTIES}
|
||||
placeholder="请选择属地"
|
||||
allowClear
|
||||
showSearch
|
||||
optionFilterProp="label"
|
||||
onChange={(value, option) => {
|
||||
form.setFieldValue("districtName", option?.label || "");
|
||||
}}
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item name="districtName" noStyle />
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<Form.Item
|
||||
name="townStreet"
|
||||
label="所属镇、街道"
|
||||
rules={[{ required: true, message: "请输入所属镇街道" }]}
|
||||
>
|
||||
<Input
|
||||
placeholder="请输入所属镇街道"
|
||||
allowClear
|
||||
maxLength={100}
|
||||
/>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<Form.Item name="villageCommunity" label="属村(社区)">
|
||||
<Input
|
||||
placeholder="请输入属村(社区)"
|
||||
allowClear
|
||||
maxLength={100}
|
||||
/>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<Form.Item label="所在地坐标经度">
|
||||
<Flex>
|
||||
<Form.Item
|
||||
name="longitude"
|
||||
noStyle
|
||||
dependencies={["latitude"]}
|
||||
rules={[
|
||||
{
|
||||
validator(_, value) {
|
||||
const latitude = form.getFieldValue("latitude");
|
||||
if (
|
||||
value !== undefined &&
|
||||
value !== null &&
|
||||
value !== "" &&
|
||||
(latitude === undefined ||
|
||||
latitude === null ||
|
||||
latitude === "")
|
||||
) {
|
||||
return Promise.reject(
|
||||
new Error("填写经度后,纬度必填"),
|
||||
);
|
||||
}
|
||||
return Promise.resolve();
|
||||
},
|
||||
},
|
||||
]}
|
||||
>
|
||||
<InputNumber
|
||||
style={{ width: "100%" }}
|
||||
min={-180}
|
||||
max={180}
|
||||
precision={6}
|
||||
placeholder="请输入经度"
|
||||
allowClear
|
||||
/>
|
||||
</Form.Item>
|
||||
|
||||
<Button onClick={() => setMapPickerVisible(true)}>选择</Button>
|
||||
</Flex>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<Form.Item
|
||||
name="latitude"
|
||||
label="所在地坐标纬度"
|
||||
dependencies={["longitude"]}
|
||||
rules={[
|
||||
latitudeRule(false),
|
||||
coordinatePairRule("longitude", "纬度", "经度"),
|
||||
]}
|
||||
>
|
||||
<InputNumber
|
||||
style={{ width: "100%" }}
|
||||
min={-90}
|
||||
max={90}
|
||||
precision={6}
|
||||
placeholder="请输入纬度"
|
||||
/>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
{/* 原型:注册地址占整行(full) */}
|
||||
<Col span={24}>
|
||||
<Form.Item
|
||||
name="registerAddress"
|
||||
label="注册地址"
|
||||
rules={[{ required: true, message: "请输入注册地址" }]}
|
||||
>
|
||||
<Input.TextArea
|
||||
rows={3}
|
||||
placeholder="请输入注册地址"
|
||||
maxLength={200}
|
||||
/>
|
||||
<Input placeholder="请输入注册地址" maxLength={500} />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
{/* 原型:办公地址占整行(full),TextArea rows=3 */}
|
||||
<Col span={24}>
|
||||
<Form.Item
|
||||
name="businessAddress"
|
||||
label="经营地址"
|
||||
rules={[{ required: true, message: "请输入经营地址" }]}
|
||||
label="办公地址"
|
||||
rules={[{ required: true, message: "请输入办公地址" }]}
|
||||
>
|
||||
<Input.TextArea
|
||||
rows={3}
|
||||
placeholder="请输入经营地址"
|
||||
maxLength={200}
|
||||
placeholder="请输入办公地址"
|
||||
maxLength={500}
|
||||
/>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<Form.Item name="ownershipTypeName" label="归属类型">
|
||||
<Input placeholder="请输入归属类型" allowClear maxLength={50} />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<Form.Item
|
||||
name="economyIndustryCode"
|
||||
label="国民经济行业分类(GB/T4754-2017)"
|
||||
name="infoDisclosureUrl"
|
||||
label="信息公开网址"
|
||||
rules={[urlRule("信息公开网址", true)]}
|
||||
normalize={(value) =>
|
||||
typeof value === "string" ? value.trim() : value
|
||||
}
|
||||
>
|
||||
<Select
|
||||
options={ECONOMY_INDUSTRY_OPTIONS}
|
||||
placeholder="请选择国民经济行业分类"
|
||||
<Input
|
||||
placeholder="请输入信息公开网址"
|
||||
allowClear
|
||||
onChange={(value, option) => {
|
||||
form.setFieldValue(
|
||||
"economyIndustryName",
|
||||
option?.label || "",
|
||||
);
|
||||
}}
|
||||
maxLength={500}
|
||||
/>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
{/* 原型:资质证书编号非必填,带"非必填,初次申请无需填写"提示 */}
|
||||
<Col span={12}>
|
||||
<Form.Item
|
||||
name="qualificationCertNo"
|
||||
label="资质证书编号"
|
||||
extra="非必填,初次申请无需填写"
|
||||
>
|
||||
<Input
|
||||
placeholder="初次申请无需填写"
|
||||
allowClear
|
||||
maxLength={100}
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item name="economyIndustryName" noStyle />
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<Form.Item
|
||||
|
|
@ -372,127 +304,117 @@ function OrgInfoPage(props) {
|
|||
<Input placeholder="请输入法定代表人" allowClear maxLength={50} />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
{/* 2026-08-08 标签对齐原型「法定代表人电话」 */}
|
||||
<Col span={12}>
|
||||
<Form.Item
|
||||
name="legalRepresentativePhone"
|
||||
label="法定代表人联系电话"
|
||||
rules={[phoneRule("法定代表人联系电话", false)]}
|
||||
label="法定代表人电话"
|
||||
rules={[phoneRule("法定代表人电话", true)]}
|
||||
normalize={(value) =>
|
||||
typeof value === "string" ? value.trim() : value
|
||||
}
|
||||
>
|
||||
<Input
|
||||
placeholder="请输入法定代表人联系电话"
|
||||
placeholder="请输入法定代表人电话"
|
||||
allowClear
|
||||
maxLength={11}
|
||||
maxLength={20}
|
||||
/>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<Form.Item
|
||||
name="principalName"
|
||||
label="主要负责人"
|
||||
rules={[{ required: true, message: "请输入主要负责人" }]}
|
||||
>
|
||||
<Input placeholder="请输入主要负责人" allowClear maxLength={50} />
|
||||
<Form.Item name="fax" label="传真" rules={[{ required: true, message: "请输入传真" }]}>
|
||||
<Input placeholder="请输入传真" allowClear maxLength={20} />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
{/*
|
||||
2026-08-08 联系人及电话(交互约定):
|
||||
单输入框录入,格式「联系人/电话」(用 / 分隔),如:张三/13800138000;
|
||||
提交前按首个 / 拆为 contactName(/前)+ contactPhone(/后)存两列;
|
||||
回显时后端 contactName/contactPhone 用 / 合并回填。
|
||||
校验:拆分后 contactName 非空且≤50、contactPhone 非空且匹配手机/座机格式且≤20。
|
||||
*/}
|
||||
<Col span={12}>
|
||||
<Form.Item
|
||||
name="principalPhone"
|
||||
label="主要负责人联系电话"
|
||||
rules={[phoneRule("主要负责人联系电话", true)]}
|
||||
normalize={(value) =>
|
||||
typeof value === "string" ? value.trim() : value
|
||||
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("请使用/分隔联系人和电话,并填写电话"),
|
||||
);
|
||||
}
|
||||
// 复用既有 PHONE_PATTERN:手机11位 / 固话10~12位(去空白后)
|
||||
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="请输入主要负责人联系电话"
|
||||
placeholder="如:张三/13800138000"
|
||||
allowClear
|
||||
maxLength={11}
|
||||
/>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<Form.Item name="safetyDeptManager" label="安全管理部门负责人">
|
||||
<Input
|
||||
placeholder="请输入安全管理部门负责人"
|
||||
allowClear
|
||||
maxLength={50}
|
||||
maxLength={73}
|
||||
/>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<Form.Item
|
||||
name="safetyDeptManagerPhone"
|
||||
label="安全管理部门负责人联系电话"
|
||||
rules={[phoneRule("安全管理部门负责人联系电话", false)]}
|
||||
normalize={(value) =>
|
||||
typeof value === "string" ? value.trim() : value
|
||||
name="fixedAssetsTotal"
|
||||
label="固定资产总值(万元)"
|
||||
rules={[
|
||||
{ required: true, message: "请输入固定资产总值" },
|
||||
{
|
||||
validator: (_, value) => {
|
||||
if (value === undefined || value === null || value === "") {
|
||||
return Promise.resolve();
|
||||
}
|
||||
>
|
||||
<Input
|
||||
placeholder="请输入安全管理部门负责人联系电话"
|
||||
allowClear
|
||||
maxLength={11}
|
||||
/>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
|
||||
<Col span={12}>
|
||||
<Form.Item
|
||||
name="safetyDeputyPhone"
|
||||
label="主管安全副总联系电话"
|
||||
rules={[phoneRule("主管安全副总联系电话", false)]}
|
||||
normalize={(value) =>
|
||||
typeof value === "string" ? value.trim() : value
|
||||
if (Number(value) < 0) {
|
||||
return Promise.reject(
|
||||
new Error("固定资产总值应为非负数字"),
|
||||
);
|
||||
}
|
||||
return Promise.resolve();
|
||||
},
|
||||
},
|
||||
]}
|
||||
>
|
||||
<Input
|
||||
placeholder="请输入主管安全副总联系电话"
|
||||
allowClear
|
||||
maxLength={11}
|
||||
/>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<Form.Item name="productionDate" label="投产日期">
|
||||
<DatePicker
|
||||
<InputNumber
|
||||
style={{ width: "100%" }}
|
||||
placeholder="请选择投产日期"
|
||||
/>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<Form.Item name="businessStatusName" label="企业经营状态">
|
||||
<Input
|
||||
placeholder="请输入企业经营状态"
|
||||
allowClear
|
||||
maxLength={50}
|
||||
/>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<Form.Item
|
||||
name="infoDisclosureUrl"
|
||||
label="信息公开网址"
|
||||
rules={[urlRule("信息公开网址", false)]}
|
||||
normalize={(value) =>
|
||||
typeof value === "string" ? value.trim() : value
|
||||
}
|
||||
>
|
||||
<Input
|
||||
placeholder="请输入信息公开网址"
|
||||
allowClear
|
||||
maxLength={200}
|
||||
min={0}
|
||||
precision={4}
|
||||
placeholder="请输入固定资产总值"
|
||||
/>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<Form.Item
|
||||
name="workplaceArea"
|
||||
label="工作场所建筑面积"
|
||||
rules={[positiveNumberRule("工作场所建筑面积", false)]}
|
||||
label="工作场所建筑面积(㎡)"
|
||||
rules={[positiveNumberRule("工作场所建筑面积", true)]}
|
||||
>
|
||||
<InputNumber
|
||||
style={{ width: "100%" }}
|
||||
|
|
@ -506,8 +428,8 @@ function OrgInfoPage(props) {
|
|||
<Col span={12}>
|
||||
<Form.Item
|
||||
name="archiveRoomArea"
|
||||
label="档案室面积"
|
||||
rules={[positiveNumberRule("档案室面积", false)]}
|
||||
label="档案室面积(㎡)"
|
||||
rules={[positiveNumberRule("档案室面积", true)]}
|
||||
>
|
||||
<InputNumber
|
||||
style={{ width: "100%" }}
|
||||
|
|
@ -522,7 +444,7 @@ function OrgInfoPage(props) {
|
|||
<Form.Item
|
||||
name="fulltimeEvaluatorCount"
|
||||
label="专职安全评价师数量"
|
||||
rules={[nonNegativeIntegerRule("专职安全评价师数量", false)]}
|
||||
rules={[nonNegativeIntegerRule("专职安全评价师数量", true)]}
|
||||
>
|
||||
<InputNumber
|
||||
style={{ width: "100%" }}
|
||||
|
|
@ -537,7 +459,7 @@ function OrgInfoPage(props) {
|
|||
<Form.Item
|
||||
name="registeredEngineerCount"
|
||||
label="注册安全工程师数量"
|
||||
rules={[nonNegativeIntegerRule("注册安全工程师数量", false)]}
|
||||
rules={[nonNegativeIntegerRule("注册安全工程师数量", true)]}
|
||||
>
|
||||
<InputNumber
|
||||
style={{ width: "100%" }}
|
||||
|
|
@ -548,84 +470,56 @@ function OrgInfoPage(props) {
|
|||
/>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<Form.Item name="enterpriseStatusCode" label="企业状态">
|
||||
<Select
|
||||
options={ENTERPRISE_STATUS_OPTIONS}
|
||||
placeholder="请选择企业状态"
|
||||
allowClear
|
||||
onChange={(value, option) => {
|
||||
console.log(value, option);
|
||||
form.setFieldValue(
|
||||
"enterpriseStatusName",
|
||||
option?.label || "",
|
||||
);
|
||||
{/*
|
||||
2026-08-08 业务范围:
|
||||
原型为 checkbox 网格(2列、灰底 #f8fafc、边框容器),此处用 Checkbox.Group + Row/Col 还原视觉。
|
||||
*/}
|
||||
<Col span={24}>
|
||||
<Form.Item
|
||||
name="applyBusinessScope"
|
||||
label="拟申请的法定安全评价业务范围"
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: "请选择拟申请的法定安全评价业务范围",
|
||||
},
|
||||
]}
|
||||
>
|
||||
<Checkbox.Group
|
||||
style={{
|
||||
display: "grid",
|
||||
gridTemplateColumns: "repeat(2, minmax(0, 1fr))",
|
||||
gap: "0.65rem 1rem",
|
||||
padding: "1rem",
|
||||
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>
|
||||
{/* 原型:单位基本情况介绍(可附页),TextArea rows=7 */}
|
||||
<Col span={24}>
|
||||
<Form.Item
|
||||
name="orgIntro"
|
||||
label="单位基本情况介绍(可附页)"
|
||||
rules={[{ required: true, message: "请输入单位基本情况介绍" }]}
|
||||
>
|
||||
<Input.TextArea
|
||||
rows={7}
|
||||
placeholder="请简要介绍单位基本情况,如成立时间、人员构成、技术力量、业绩等"
|
||||
maxLength={2000}
|
||||
showCount
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item name="enterpriseStatusName" noStyle />
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<Form.Item name="enterpriseScaleCode" label="企业规模">
|
||||
<Select
|
||||
options={ENTERPRISE_SCALE_OPTIONS}
|
||||
placeholder="请选择企业规模"
|
||||
allowClear
|
||||
onChange={(value, option) => {
|
||||
form.setFieldValue(
|
||||
"enterpriseScaleName",
|
||||
option?.label || "",
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item name="enterpriseScaleName" noStyle />
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<Form.Item name="filingTypeCode" label="备案类型">
|
||||
<Select
|
||||
options={REGISTERED_ORG_FILING_TYPE_SEARCH_OPTIONS}
|
||||
placeholder="请选择备案类型"
|
||||
allowClear
|
||||
onChange={(value, option) => {
|
||||
form.setFieldValue("filingTypeName", option?.label);
|
||||
}}
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item name="filingTypeName" noStyle />
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<Form.Item name="filingRecordStatusCode" label="备案状态">
|
||||
<Select
|
||||
options={REGISTERED_ORG_FILING_RECORD_STATUS_OPTIONS}
|
||||
placeholder="请选择备案状态"
|
||||
allowClear
|
||||
onChange={(value, option) => {
|
||||
form.setFieldValue(
|
||||
"filingRecordStatusName",
|
||||
option?.label || "",
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item name="filingRecordStatusName" noStyle />
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<AttachmentUpload
|
||||
name="attachmentUrls"
|
||||
label="上传附件"
|
||||
extra={"最多上传10个PDF、DOC、DOCX格式文件"}
|
||||
maxCount={10}
|
||||
accept=".pdf,.doc,.docx"
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
</Form>
|
||||
<BaiduMapPicker
|
||||
visible={mapPickerVisible}
|
||||
onCancel={() => setMapPickerVisible(false)}
|
||||
onConfirm={handleMapConfirm}
|
||||
/>
|
||||
{editing && (
|
||||
<div style={{ marginTop: 24, textAlign: "center" }}>
|
||||
<Space>
|
||||
|
|
@ -645,6 +539,8 @@ function OrgInfoPage(props) {
|
|||
</Space>
|
||||
</div>
|
||||
)}
|
||||
</Form>
|
||||
</div>
|
||||
</PageLayout>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue