From 5ac8e18d74f6e100237e4ff99a6b0e99aec525d0 Mon Sep 17 00:00:00 2001 From: iven Date: Tue, 21 Apr 2026 00:19:10 +0800 Subject: [PATCH] =?UTF-8?q?fix(web):=20=E4=BF=AE=E5=A4=8D=20visible=5Fwhen?= =?UTF-8?q?=20=E8=A1=A8=E8=BE=BE=E5=BC=8F=E8=AF=84=E4=BC=B0=E5=99=A8=20!?= =?UTF-8?q?=3D/||/&&=20=E6=94=AF=E6=8C=81=20+=20=E6=B7=BB=E5=8A=A0=20valid?= =?UTF-8?q?ation=20=E5=89=8D=E7=AB=AF=E6=A0=A1=E9=AA=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - exprEvaluator: 新增 neq 类型修复 != 操作符被当作 == 处理的 bug - exprEvaluator: 支持 || 和 && 作为 OR/AND 的别名 - PluginCRUDPage: 读取 field.validation.pattern 添加表单正则校验规则 --- apps/web/src/pages/PluginCRUDPage.tsx | 11 ++++++++--- apps/web/src/utils/exprEvaluator.ts | 20 ++++++++++++++++---- 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/apps/web/src/pages/PluginCRUDPage.tsx b/apps/web/src/pages/PluginCRUDPage.tsx index 4e79360..ec0f3f2 100644 --- a/apps/web/src/pages/PluginCRUDPage.tsx +++ b/apps/web/src/pages/PluginCRUDPage.tsx @@ -773,9 +773,14 @@ export default function PluginCRUDPage({ name={field.name} label={field.display_name || field.name} rules={ - field.required - ? [{ required: true, message: `请输入${field.display_name || field.name}` }] - : [] + [ + ...(field.required + ? [{ required: true, message: `请输入${field.display_name || field.name}` }] + : []), + ...(field.validation?.pattern + ? [{ pattern: new RegExp(field.validation.pattern), message: field.validation.message || '格式不正确' }] + : []), + ] } valuePropName={field.field_type === 'boolean' ? 'checked' : 'value'} > diff --git a/apps/web/src/utils/exprEvaluator.ts b/apps/web/src/utils/exprEvaluator.ts index 45a451d..d62b5d4 100644 --- a/apps/web/src/utils/exprEvaluator.ts +++ b/apps/web/src/utils/exprEvaluator.ts @@ -11,7 +11,7 @@ */ interface ExprNode { - type: 'eq' | 'and' | 'or' | 'not'; + type: 'eq' | 'neq' | 'and' | 'or' | 'not'; field?: string; value?: string; left?: ExprNode; @@ -49,6 +49,16 @@ function tokenize(input: string): string[] { i += 2; continue; } + if (input[i] === '&' && input[i + 1] === '&') { + tokens.push('&&'); + i += 2; + continue; + } + if (input[i] === '|' && input[i + 1] === '|') { + tokens.push('||'); + i += 2; + continue; + } let j = i; while ( j < input.length && @@ -81,12 +91,12 @@ function parseAtom(tokens: string[]): ExprNode | null { if (op !== '==' && op !== '!=') return null; const rawValue = tokens.shift() || ''; const value = rawValue.replace(/^'(.*)'$/, '$1'); - return { type: 'eq', field, value }; + return { type: op === '!=' ? 'neq' : 'eq', field, value }; } function parseAnd(tokens: string[]): ExprNode | null { let left = parseAtom(tokens); - while (tokens[0] === 'AND') { + while (tokens[0] === 'AND' || tokens[0] === '&&') { tokens.shift(); const right = parseAtom(tokens); if (left && right) { @@ -98,7 +108,7 @@ function parseAnd(tokens: string[]): ExprNode | null { function parseOr(tokens: string[]): ExprNode | null { let left = parseAnd(tokens); - while (tokens[0] === 'OR') { + while (tokens[0] === 'OR' || tokens[0] === '||') { tokens.shift(); const right = parseAnd(tokens); if (left && right) { @@ -117,6 +127,8 @@ export function evaluateExpr(node: ExprNode, values: Record): b switch (node.type) { case 'eq': return String(values[node.field!] ?? '') === node.value; + case 'neq': + return String(values[node.field!] ?? '') !== node.value; case 'and': return evaluateExpr(node.left!, values) && evaluateExpr(node.right!, values); case 'or':