fix(web): 修复 visible_when 表达式评估器 !=/||/&& 支持 + 添加 validation 前端校验
- exprEvaluator: 新增 neq 类型修复 != 操作符被当作 == 处理的 bug - exprEvaluator: 支持 || 和 && 作为 OR/AND 的别名 - PluginCRUDPage: 读取 field.validation.pattern 添加表单正则校验规则
This commit is contained in:
@@ -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'}
|
||||
>
|
||||
|
||||
@@ -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<string, unknown>): 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':
|
||||
|
||||
Reference in New Issue
Block a user