/** * 配置值校验工具 * 根据配置类型校验值的格式,编辑模式下额外校验值范围 */ /** * 支持的值类型列表 */ const VALID_TYPES = ["string", "number", "boolean", "json"]; /** * 校验配置值是否符合指定的类型 * @param {any} value - 配置值 * @param {string} type - 配置类型(string/number/boolean/json) * @returns {{ valid: boolean, message: string }} 校验结果 */ function validateByType(value, type) { if (!VALID_TYPES.includes(type)) { return { valid: false, message: `不支持的类型: ${type},支持的类型: ${VALID_TYPES.join(", ")}` }; } switch (type) { case "string": if (typeof value !== "string") { return { valid: false, message: "值必须是字符串类型" }; } break; case "number": { if (value === null || value === undefined || String(value).trim() === "") { return { valid: false, message: "值必须是有效的数字" }; } const num = Number(value); if (isNaN(num)) { return { valid: false, message: "值必须是有效的数字" }; } break; } case "boolean": if (typeof value !== "boolean" && value !== "true" && value !== "false") { return { valid: false, message: "值必须是布尔类型(true 或 false)" }; } break; case "json": try { JSON.parse(typeof value === "string" ? value : JSON.stringify(value)); } catch { return { valid: false, message: "值必须是有效的 JSON 格式" }; } break; } return { valid: true, message: "" }; } /** * 校验值范围约束(仅在编辑模式下生效) * 支持: * - 正则约束(string 类型常用):"/正则/flags",如 /^1[3-9]\d{9}$/(手机号) * - 区间范围:"1-100" 或 "0.0-1.0" * - 枚举范围:"枚举: A,B,C" * - 描述性范围(如 "合法 IPv4 地址")仅作提示,不做强制校验 * @param {any} value - 配置值 * @param {string} valueRange - 值范围描述 * @returns {{ valid: boolean, message: string }} 校验结果 */ function validateRange(value, valueRange) { if (!valueRange || valueRange.trim() === "") { return { valid: true, message: "" }; } const range = valueRange.trim(); // 正则约束: "/pattern/flags",如 /^1[3-9]\d{9}$/(手机号) if (range.startsWith("/")) { // pattern 中未转义的 / 不允许(与 JS 正则字面量一致);flags 仅允许字母 const regexMatch = range.match(/^\/((?:\\.|[^\\/])*)\/([a-z]*)$/); if (!regexMatch) { return { valid: false, message: `正则格式无效: ${range},正确格式为 /pattern/flags` }; } const pattern = regexMatch[1]; const flags = regexMatch[2] || ""; let re; try { re = new RegExp(pattern, flags); } catch (e) { return { valid: false, message: `正则表达式无效: /${pattern}/` }; } // 保留 g/y 标志语义:test 前重置 lastIndex,避免状态残留 re.lastIndex = 0; if (!re.test(String(value))) { return { valid: false, message: `值不符合格式要求: /${pattern}/` }; } return { valid: true, message: "" }; } // 区间范围: "1-100" 或 "0.0-1.0" const rangeMatch = range.match(/^(-?\d+(\.\d+)?)\s*-\s*(-?\d+(\.\d+)?)$/); if (rangeMatch) { const min = Number(rangeMatch[1]); const max = Number(rangeMatch[3]); if (min > max) { return { valid: false, message: `范围下限 ${min} 大于上限 ${max}` }; } const num = Number(value); if (isNaN(num) || num < min || num > max) { return { valid: false, message: `值必须在 ${min} 到 ${max} 之间` }; } return { valid: true, message: "" }; } // 枚举范围: "枚举: A,B,C" const enumMatch = range.match(/^枚举[::]\s*(.+)$/); if (enumMatch) { const options = enumMatch[1].split(/[,,]/).map((s) => s.trim()); if (!options.includes(String(value).trim())) { return { valid: false, message: `值必须是以下选项之一: ${options.join(", ")}` }; } return { valid: true, message: "" }; } // 其他描述性范围(如 "合法 IPv4 地址")目前不做强制校验,仅作提示 return { valid: true, message: "" }; } module.exports = { VALID_TYPES, validateByType, validateRange };