bug修护
parent
f3d9291fdb
commit
213224cf83
|
|
@ -10,6 +10,7 @@ import {
|
||||||
} from "~/enumerate/enterpriseOptions";
|
} from "~/enumerate/enterpriseOptions";
|
||||||
import { formSelectField } from "~/utils/enterpriseForm";
|
import { formSelectField } from "~/utils/enterpriseForm";
|
||||||
import {
|
import {
|
||||||
|
coordinatePairRule,
|
||||||
creditCodeRule,
|
creditCodeRule,
|
||||||
latitudeRule,
|
latitudeRule,
|
||||||
longitudeRule,
|
longitudeRule,
|
||||||
|
|
@ -61,7 +62,11 @@ export function buildOrgInfoFormOptions() {
|
||||||
render: FORM_ITEM_RENDER_ENUM.INPUT_NUMBER,
|
render: FORM_ITEM_RENDER_ENUM.INPUT_NUMBER,
|
||||||
useConstraints: false,
|
useConstraints: false,
|
||||||
componentProps: { ...numberFieldProps, min: -180, max: 180, precision: 6 },
|
componentProps: { ...numberFieldProps, min: -180, max: 180, precision: 6 },
|
||||||
rules: [longitudeRule(false)],
|
dependencies: ["latitude"],
|
||||||
|
rules: [
|
||||||
|
longitudeRule(false),
|
||||||
|
coordinatePairRule("latitude", "经度", "纬度"),
|
||||||
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "latitude",
|
name: "latitude",
|
||||||
|
|
@ -69,7 +74,11 @@ export function buildOrgInfoFormOptions() {
|
||||||
render: FORM_ITEM_RENDER_ENUM.INPUT_NUMBER,
|
render: FORM_ITEM_RENDER_ENUM.INPUT_NUMBER,
|
||||||
useConstraints: false,
|
useConstraints: false,
|
||||||
componentProps: { ...numberFieldProps, min: -90, max: 90, precision: 6 },
|
componentProps: { ...numberFieldProps, min: -90, max: 90, precision: 6 },
|
||||||
rules: [latitudeRule(false)],
|
dependencies: ["longitude"],
|
||||||
|
rules: [
|
||||||
|
latitudeRule(false),
|
||||||
|
coordinatePairRule("longitude", "纬度", "经度"),
|
||||||
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "registerAddress",
|
name: "registerAddress",
|
||||||
|
|
|
||||||
|
|
@ -27,10 +27,12 @@ import {
|
||||||
import { NS_ORG_INFO } from "~/enumerate/namespace";
|
import { NS_ORG_INFO } from "~/enumerate/namespace";
|
||||||
import { mockUploadFileList } from "~/utils/mockUpload";
|
import { mockUploadFileList } from "~/utils/mockUpload";
|
||||||
import {
|
import {
|
||||||
|
coordinatePairRule,
|
||||||
creditCodeRule,
|
creditCodeRule,
|
||||||
latitudeRule,
|
latitudeRule,
|
||||||
longitudeRule,
|
longitudeRule,
|
||||||
nonNegativeIntegerRule,
|
nonNegativeIntegerRule,
|
||||||
|
normalizeUrl,
|
||||||
phoneRule,
|
phoneRule,
|
||||||
positiveNumberRule,
|
positiveNumberRule,
|
||||||
urlRule,
|
urlRule,
|
||||||
|
|
@ -89,6 +91,9 @@ function OrgInfoPage(props) {
|
||||||
? dayjs(formValues.productionDate).format("YYYY-MM-DD")
|
? dayjs(formValues.productionDate).format("YYYY-MM-DD")
|
||||||
: undefined,
|
: undefined,
|
||||||
attachmentUrls: formValues.attachmentUrls? JSON.stringify(formValues.attachmentUrls) :null,
|
attachmentUrls: formValues.attachmentUrls? JSON.stringify(formValues.attachmentUrls) :null,
|
||||||
|
infoDisclosureUrl: formValues.infoDisclosureUrl
|
||||||
|
? normalizeUrl(formValues.infoDisclosureUrl)
|
||||||
|
: undefined,
|
||||||
authStatusCode: submitType === "draft" ? 0 : 1,
|
authStatusCode: submitType === "draft" ? 0 : 1,
|
||||||
authStatusName: submitType === "draft" ? "草稿" : "已提交",
|
authStatusName: submitType === "draft" ? "草稿" : "已提交",
|
||||||
};
|
};
|
||||||
|
|
@ -205,7 +210,11 @@ function OrgInfoPage(props) {
|
||||||
<Form.Item
|
<Form.Item
|
||||||
name="longitude"
|
name="longitude"
|
||||||
label="所在地坐标经度"
|
label="所在地坐标经度"
|
||||||
rules={[longitudeRule(false)]}
|
dependencies={["latitude"]}
|
||||||
|
rules={[
|
||||||
|
longitudeRule(false),
|
||||||
|
coordinatePairRule("latitude", "经度", "纬度"),
|
||||||
|
]}
|
||||||
>
|
>
|
||||||
<InputNumber
|
<InputNumber
|
||||||
style={{ width: "100%" }}
|
style={{ width: "100%" }}
|
||||||
|
|
@ -220,7 +229,11 @@ function OrgInfoPage(props) {
|
||||||
<Form.Item
|
<Form.Item
|
||||||
name="latitude"
|
name="latitude"
|
||||||
label="所在地坐标纬度"
|
label="所在地坐标纬度"
|
||||||
rules={[latitudeRule(false)]}
|
dependencies={["longitude"]}
|
||||||
|
rules={[
|
||||||
|
latitudeRule(false),
|
||||||
|
coordinatePairRule("longitude", "纬度", "经度"),
|
||||||
|
]}
|
||||||
>
|
>
|
||||||
<InputNumber
|
<InputNumber
|
||||||
style={{ width: "100%" }}
|
style={{ width: "100%" }}
|
||||||
|
|
@ -276,6 +289,7 @@ function OrgInfoPage(props) {
|
||||||
name="legalRepresentativePhone"
|
name="legalRepresentativePhone"
|
||||||
label="法定代表人联系电话"
|
label="法定代表人联系电话"
|
||||||
rules={[phoneRule("法定代表人联系电话", false)]}
|
rules={[phoneRule("法定代表人联系电话", false)]}
|
||||||
|
normalize={(value) => (typeof value === "string" ? value.trim() : value)}
|
||||||
>
|
>
|
||||||
<Input placeholder="请输入法定代表人联系电话" allowClear />
|
<Input placeholder="请输入法定代表人联系电话" allowClear />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
|
@ -294,6 +308,7 @@ function OrgInfoPage(props) {
|
||||||
name="principalPhone"
|
name="principalPhone"
|
||||||
label="主要负责人联系电话"
|
label="主要负责人联系电话"
|
||||||
rules={[phoneRule("主要负责人联系电话", true)]}
|
rules={[phoneRule("主要负责人联系电话", true)]}
|
||||||
|
normalize={(value) => (typeof value === "string" ? value.trim() : value)}
|
||||||
>
|
>
|
||||||
<Input placeholder="请输入主要负责人联系电话" allowClear />
|
<Input placeholder="请输入主要负责人联系电话" allowClear />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
|
@ -308,6 +323,7 @@ function OrgInfoPage(props) {
|
||||||
name="safetyDeptManagerPhone"
|
name="safetyDeptManagerPhone"
|
||||||
label="安全管理部门负责人联系电话"
|
label="安全管理部门负责人联系电话"
|
||||||
rules={[phoneRule("安全管理部门负责人联系电话", false)]}
|
rules={[phoneRule("安全管理部门负责人联系电话", false)]}
|
||||||
|
normalize={(value) => (typeof value === "string" ? value.trim() : value)}
|
||||||
>
|
>
|
||||||
<Input
|
<Input
|
||||||
placeholder="请输入安全管理部门负责人联系电话"
|
placeholder="请输入安全管理部门负责人联系电话"
|
||||||
|
|
@ -325,6 +341,7 @@ function OrgInfoPage(props) {
|
||||||
name="safetyDeputyPhone"
|
name="safetyDeputyPhone"
|
||||||
label="主管安全副总联系电话"
|
label="主管安全副总联系电话"
|
||||||
rules={[phoneRule("主管安全副总联系电话", false)]}
|
rules={[phoneRule("主管安全副总联系电话", false)]}
|
||||||
|
normalize={(value) => (typeof value === "string" ? value.trim() : value)}
|
||||||
>
|
>
|
||||||
<Input placeholder="请输入主管安全副总联系电话" allowClear />
|
<Input placeholder="请输入主管安全副总联系电话" allowClear />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
|
@ -347,6 +364,7 @@ function OrgInfoPage(props) {
|
||||||
name="infoDisclosureUrl"
|
name="infoDisclosureUrl"
|
||||||
label="信息公开网址"
|
label="信息公开网址"
|
||||||
rules={[urlRule("信息公开网址", false)]}
|
rules={[urlRule("信息公开网址", false)]}
|
||||||
|
normalize={(value) => (typeof value === "string" ? value.trim() : value)}
|
||||||
>
|
>
|
||||||
<Input placeholder="请输入信息公开网址" allowClear />
|
<Input placeholder="请输入信息公开网址" allowClear />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,8 @@ export const ID_CARD_PATTERN = /^\d{17}[\dX]$/i;
|
||||||
/** 手机号 */
|
/** 手机号 */
|
||||||
export const MOBILE_PHONE_PATTERN = /^1[3-9]\d{9}$/;
|
export const MOBILE_PHONE_PATTERN = /^1[3-9]\d{9}$/;
|
||||||
|
|
||||||
/** 固话或手机 */
|
/** 固话或手机(去格式符后:手机 11 位 / 固话 10~12 位) */
|
||||||
export const PHONE_PATTERN = /^(\d{3,4}-?\d{7,8}|1[3-9]\d{9})$/;
|
export const PHONE_PATTERN = /^(1[3-9]\d{9}|\d{10,12})$/;
|
||||||
|
|
||||||
/** 经度 */
|
/** 经度 */
|
||||||
export const LONGITUDE_PATTERN = /^-?((1[0-7]\d)|(\d{1,2}))(\.\d+)?$|^180(\.0+)?$/;
|
export const LONGITUDE_PATTERN = /^-?((1[0-7]\d)|(\d{1,2}))(\.\d+)?$|^180(\.0+)?$/;
|
||||||
|
|
@ -16,21 +16,48 @@ export const LONGITUDE_PATTERN = /^-?((1[0-7]\d)|(\d{1,2}))(\.\d+)?$|^180(\.0+)?
|
||||||
/** 纬度 */
|
/** 纬度 */
|
||||||
export const LATITUDE_PATTERN = /^-?([1-8]?\d(\.\d+)?|90(\.0+)?)$/;
|
export const LATITUDE_PATTERN = /^-?([1-8]?\d(\.\d+)?|90(\.0+)?)$/;
|
||||||
|
|
||||||
/** URL */
|
/** URL(需含协议或合法域名) */
|
||||||
export const URL_PATTERN = /^(https?:\/\/)[\w.-]+(?:\.[\w.-]+)+[\w\-._~:/?#[\]@!$&'()*+,;=.]*$/;
|
export const URL_PATTERN = /^(https?:\/\/)([\w-]+\.)+[\w-]+([\w\-._~:/?#[\]@!$&'()*+,;=.]*)?$/i;
|
||||||
|
|
||||||
|
const FORMAT_VALIDATE_TRIGGER = ["onBlur", "onChange"];
|
||||||
|
|
||||||
|
function isEmptyValue(value) {
|
||||||
|
return value === undefined || value === null || value === "";
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 电话去空格、括号、横线,并剥离 +86 前缀 */
|
||||||
|
export function normalizePhone(value) {
|
||||||
|
return String(value).replace(/[\s()-]/g, "").replace(/^(\+?86)/, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
/** URL 补全协议后校验 */
|
||||||
|
export function normalizeUrl(value) {
|
||||||
|
const trimmed = String(value).trim();
|
||||||
|
if (!trimmed) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
return /^https?:\/\//i.test(trimmed) ? trimmed : `https://${trimmed}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function hasTooManyDecimals(value, maxDecimals = 6) {
|
||||||
|
const str = String(value);
|
||||||
|
const dotIndex = str.indexOf(".");
|
||||||
|
if (dotIndex === -1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return str.slice(dotIndex + 1).length > maxDecimals;
|
||||||
|
}
|
||||||
|
|
||||||
export function creditCodeRule(required = true) {
|
export function creditCodeRule(required = true) {
|
||||||
return {
|
return {
|
||||||
required,
|
required,
|
||||||
message: required ? "请输入统一社会信用代码" : undefined,
|
validateTrigger: FORMAT_VALIDATE_TRIGGER,
|
||||||
pattern: CREDIT_CODE_PATTERN,
|
|
||||||
...(required ? {} : { validateTrigger: "onBlur" }),
|
|
||||||
validator: (_, value) => {
|
validator: (_, value) => {
|
||||||
if (!value) {
|
if (!value) {
|
||||||
return required ? Promise.reject(new Error("请输入统一社会信用代码")) : Promise.resolve();
|
return required ? Promise.reject(new Error("请输入统一社会信用代码")) : Promise.resolve();
|
||||||
}
|
}
|
||||||
if (!CREDIT_CODE_PATTERN.test(value.trim())) {
|
if (!CREDIT_CODE_PATTERN.test(String(value).trim().toUpperCase())) {
|
||||||
return Promise.reject(new Error("统一社会信用代码格式不正确"));
|
return Promise.reject(new Error("统一社会信用代码格式不正确(18位)"));
|
||||||
}
|
}
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
},
|
},
|
||||||
|
|
@ -56,13 +83,15 @@ export function idCardRule(required = true) {
|
||||||
export function phoneRule(label = "联系电话", required = true) {
|
export function phoneRule(label = "联系电话", required = true) {
|
||||||
return {
|
return {
|
||||||
required,
|
required,
|
||||||
|
validateTrigger: FORMAT_VALIDATE_TRIGGER,
|
||||||
|
whitespace: true,
|
||||||
validator: (_, value) => {
|
validator: (_, value) => {
|
||||||
if (!value) {
|
if (!value || !String(value).trim()) {
|
||||||
return required ? Promise.reject(new Error(`请输入${label}`)) : Promise.resolve();
|
return required ? Promise.reject(new Error(`请输入${label}`)) : Promise.resolve();
|
||||||
}
|
}
|
||||||
const str = String(value).replace(/\s+/g, "");
|
const normalized = normalizePhone(value);
|
||||||
if (!PHONE_PATTERN.test(str)) {
|
if (!PHONE_PATTERN.test(normalized)) {
|
||||||
return Promise.reject(new Error(`${label}格式不正确`));
|
return Promise.reject(new Error(`${label}格式不正确(手机11位或固话区号+号码)`));
|
||||||
}
|
}
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
},
|
},
|
||||||
|
|
@ -88,14 +117,18 @@ export function mobileRule(label = "账号", required = true) {
|
||||||
export function longitudeRule(required = false) {
|
export function longitudeRule(required = false) {
|
||||||
return {
|
return {
|
||||||
required,
|
required,
|
||||||
|
validateTrigger: FORMAT_VALIDATE_TRIGGER,
|
||||||
validator: (_, value) => {
|
validator: (_, value) => {
|
||||||
if (value === undefined || value === null || value === "") {
|
if (isEmptyValue(value)) {
|
||||||
return required ? Promise.reject(new Error("请输入经度")) : Promise.resolve();
|
return required ? Promise.reject(new Error("请输入经度")) : Promise.resolve();
|
||||||
}
|
}
|
||||||
const num = Number(value);
|
const num = Number(value);
|
||||||
if (Number.isNaN(num) || num < -180 || num > 180) {
|
if (Number.isNaN(num) || num < -180 || num > 180) {
|
||||||
return Promise.reject(new Error("经度格式不正确(-180 ~ 180)"));
|
return Promise.reject(new Error("经度格式不正确(-180 ~ 180)"));
|
||||||
}
|
}
|
||||||
|
if (hasTooManyDecimals(value)) {
|
||||||
|
return Promise.reject(new Error("经度最多保留6位小数"));
|
||||||
|
}
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
@ -104,28 +137,60 @@ export function longitudeRule(required = false) {
|
||||||
export function latitudeRule(required = false) {
|
export function latitudeRule(required = false) {
|
||||||
return {
|
return {
|
||||||
required,
|
required,
|
||||||
|
validateTrigger: FORMAT_VALIDATE_TRIGGER,
|
||||||
validator: (_, value) => {
|
validator: (_, value) => {
|
||||||
if (value === undefined || value === null || value === "") {
|
if (isEmptyValue(value)) {
|
||||||
return required ? Promise.reject(new Error("请输入纬度")) : Promise.resolve();
|
return required ? Promise.reject(new Error("请输入纬度")) : Promise.resolve();
|
||||||
}
|
}
|
||||||
const num = Number(value);
|
const num = Number(value);
|
||||||
if (Number.isNaN(num) || num < -90 || num > 90) {
|
if (Number.isNaN(num) || num < -90 || num > 90) {
|
||||||
return Promise.reject(new Error("纬度格式不正确(-90 ~ 90)"));
|
return Promise.reject(new Error("纬度格式不正确(-90 ~ 90)"));
|
||||||
}
|
}
|
||||||
|
if (hasTooManyDecimals(value)) {
|
||||||
|
return Promise.reject(new Error("纬度最多保留6位小数"));
|
||||||
|
}
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 经纬度成对填写:填了其中一个则另一个必填 */
|
||||||
|
export function coordinatePairRule(peerField, selfLabel, peerLabel) {
|
||||||
|
return ({ getFieldValue }) => ({
|
||||||
|
validateTrigger: FORMAT_VALIDATE_TRIGGER,
|
||||||
|
validator: (_, value) => {
|
||||||
|
const peerValue = getFieldValue(peerField);
|
||||||
|
const hasSelf = !isEmptyValue(value);
|
||||||
|
const hasPeer = !isEmptyValue(peerValue);
|
||||||
|
if (hasSelf && !hasPeer) {
|
||||||
|
return Promise.reject(new Error(`请同时填写${peerLabel}`));
|
||||||
|
}
|
||||||
|
if (!hasSelf && hasPeer) {
|
||||||
|
return Promise.reject(new Error(`请填写${selfLabel}`));
|
||||||
|
}
|
||||||
|
return Promise.resolve();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
export function urlRule(label = "网址", required = false) {
|
export function urlRule(label = "网址", required = false) {
|
||||||
return {
|
return {
|
||||||
required,
|
required,
|
||||||
|
validateTrigger: FORMAT_VALIDATE_TRIGGER,
|
||||||
|
whitespace: true,
|
||||||
validator: (_, value) => {
|
validator: (_, value) => {
|
||||||
if (!value) {
|
if (!value || !String(value).trim()) {
|
||||||
return required ? Promise.reject(new Error(`请输入${label}`)) : Promise.resolve();
|
return required ? Promise.reject(new Error(`请输入${label}`)) : Promise.resolve();
|
||||||
}
|
}
|
||||||
if (!URL_PATTERN.test(String(value).trim())) {
|
const normalized = normalizeUrl(value);
|
||||||
return Promise.reject(new Error(`${label}格式不正确`));
|
if (!URL_PATTERN.test(normalized)) {
|
||||||
|
return Promise.reject(new Error(`${label}格式不正确(如 https://example.com)`));
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
// eslint-disable-next-line no-new
|
||||||
|
new URL(normalized);
|
||||||
|
} catch {
|
||||||
|
return Promise.reject(new Error(`${label}格式不正确(如 https://example.com)`));
|
||||||
}
|
}
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
},
|
},
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue