1
This commit is contained in:
parent
cec0962afd
commit
e7b914a2ae
@ -68,7 +68,7 @@ const WorkflowDesignInner: React.FC = () => {
|
||||
if (data) {
|
||||
setNodes(data.nodes);
|
||||
setEdges(data.edges);
|
||||
setWorkflowTitle(data.definition.name);
|
||||
setWorkflowTitle(data.definition?.name || '未命名工作流');
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -419,11 +419,16 @@ const WorkflowDesignInner: React.FC = () => {
|
||||
tagName === 'TEXTAREA' ||
|
||||
target.isContentEditable ||
|
||||
target.getAttribute('contenteditable') === 'true';
|
||||
const isInDrawer = target.closest('.ant-drawer-body') !== null;
|
||||
const isInModal = target.closest('.ant-modal') !== null;
|
||||
|
||||
// 在抽屉或模态框内,且在输入元素中时,允许原生行为
|
||||
const shouldSkipShortcut = isInputElement || isInDrawer || isInModal;
|
||||
// 检查是否在 shadcn/ui Sheet、Dialog 或其他模态框内
|
||||
const isInSheet = target.closest('[role="dialog"]') !== null;
|
||||
const isInModal = target.closest('[role="alertdialog"]') !== null;
|
||||
const isInPopover = target.closest('[role="menu"]') !== null ||
|
||||
target.closest('[role="listbox"]') !== null ||
|
||||
target.closest('[data-radix-popper-content-wrapper]') !== null;
|
||||
|
||||
// 在模态框或弹窗内,或者在输入元素中时,允许原生行为
|
||||
const shouldSkipShortcut = isInputElement || isInSheet || isInModal || isInPopover;
|
||||
|
||||
const isMac = navigator.platform.toUpperCase().indexOf('MAC') >= 0;
|
||||
const ctrlKey = isMac ? e.metaKey : e.ctrlKey;
|
||||
|
||||
@ -83,7 +83,7 @@ export const NotificationNodeDefinition: ConfigurableNodeDefinition = {
|
||||
default: ""
|
||||
}
|
||||
},
|
||||
required: ["nodeName", "nodeCode", "notificationType", "title", "content", "recipients"]
|
||||
required: ["nodeName", "nodeCode", "notificationType", "title", "content"]
|
||||
},
|
||||
outputs: [{
|
||||
name: "status",
|
||||
@ -91,8 +91,7 @@ export const NotificationNodeDefinition: ConfigurableNodeDefinition = {
|
||||
type: "string",
|
||||
enum: ["SUCCESS", "FAILURE"],
|
||||
description: "执行的结果状态",
|
||||
example: "SUCCESS",
|
||||
required: true
|
||||
example: "SUCCESS"
|
||||
}]
|
||||
};
|
||||
|
||||
|
||||
@ -9,6 +9,7 @@ export enum NodeType {
|
||||
SCRIPT_TASK = 'SCRIPT_TASK',
|
||||
DEPLOY_NODE = 'DEPLOY_NODE',
|
||||
JENKINS_BUILD = 'JENKINS_BUILD',
|
||||
NOTIFICATION = 'NOTIFICATION',
|
||||
GATEWAY_NODE = 'GATEWAY_NODE',
|
||||
SUB_PROCESS = 'SUB_PROCESS',
|
||||
CALL_ACTIVITY = 'CALL_ACTIVITY'
|
||||
|
||||
@ -15,77 +15,94 @@ export const convertJsonSchemaToZod = (jsonSchema: JSONSchema): z.ZodObject<any>
|
||||
|
||||
Object.entries(jsonSchema.properties).forEach(([key, prop]: [string, any]) => {
|
||||
let fieldSchema: z.ZodTypeAny;
|
||||
const isRequired = Array.isArray(jsonSchema.required) && jsonSchema.required.includes(key);
|
||||
|
||||
// 根据类型创建 Zod Schema
|
||||
switch (prop.type) {
|
||||
case 'string':
|
||||
fieldSchema = z.string();
|
||||
if (prop.format === 'email') {
|
||||
fieldSchema = (fieldSchema as z.ZodString).email(prop.title ? `${prop.title}格式不正确` : '邮箱格式不正确');
|
||||
} else if (prop.format === 'url') {
|
||||
fieldSchema = (fieldSchema as z.ZodString).url(prop.title ? `${prop.title}格式不正确` : 'URL格式不正确');
|
||||
}
|
||||
if (prop.minLength) {
|
||||
fieldSchema = (fieldSchema as z.ZodString).min(prop.minLength, `${prop.title || key}至少需要${prop.minLength}个字符`);
|
||||
}
|
||||
if (prop.maxLength) {
|
||||
fieldSchema = (fieldSchema as z.ZodString).max(prop.maxLength, `${prop.title || key}最多${prop.maxLength}个字符`);
|
||||
}
|
||||
if (prop.pattern) {
|
||||
fieldSchema = (fieldSchema as z.ZodString).regex(new RegExp(prop.pattern), `${prop.title || key}格式不正确`);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'number':
|
||||
case 'integer':
|
||||
fieldSchema = prop.type === 'integer' ? z.number().int() : z.number();
|
||||
if (prop.minimum !== undefined) {
|
||||
fieldSchema = (fieldSchema as z.ZodNumber).min(prop.minimum, `${prop.title || key}不能小于${prop.minimum}`);
|
||||
}
|
||||
if (prop.maximum !== undefined) {
|
||||
fieldSchema = (fieldSchema as z.ZodNumber).max(prop.maximum, `${prop.title || key}不能大于${prop.maximum}`);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'boolean':
|
||||
fieldSchema = z.boolean();
|
||||
break;
|
||||
|
||||
case 'array':
|
||||
fieldSchema = z.array(z.any());
|
||||
if (prop.minItems !== undefined) {
|
||||
fieldSchema = (fieldSchema as z.ZodArray<any>).min(prop.minItems, `${prop.title || key}至少需要${prop.minItems}项`);
|
||||
}
|
||||
if (prop.maxItems !== undefined) {
|
||||
fieldSchema = (fieldSchema as z.ZodArray<any>).max(prop.maxItems, `${prop.title || key}最多${prop.maxItems}项`);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'object':
|
||||
fieldSchema = z.record(z.any());
|
||||
break;
|
||||
|
||||
default:
|
||||
fieldSchema = z.any();
|
||||
}
|
||||
|
||||
// 处理默认值
|
||||
if (prop.default !== undefined) {
|
||||
fieldSchema = fieldSchema.default(prop.default);
|
||||
}
|
||||
|
||||
// 处理枚举
|
||||
// 如果有枚举,直接使用枚举(枚举会覆盖其他类型)
|
||||
if (prop.enum && Array.isArray(prop.enum)) {
|
||||
const enumValues = prop.enum.map((v: any) => (typeof v === 'object' ? v.value : v));
|
||||
fieldSchema = z.enum(enumValues as [string, ...string[]]);
|
||||
}
|
||||
|
||||
// 处理必填字段
|
||||
if (Array.isArray(jsonSchema.required) && jsonSchema.required.includes(key)) {
|
||||
// 已经是必填的,不需要额外处理
|
||||
|
||||
// 处理默认值
|
||||
if (prop.default !== undefined) {
|
||||
fieldSchema = fieldSchema.default(prop.default);
|
||||
}
|
||||
|
||||
// 处理必填/可选
|
||||
if (!isRequired) {
|
||||
fieldSchema = fieldSchema.optional();
|
||||
}
|
||||
} else {
|
||||
// 非必填字段设为 optional
|
||||
fieldSchema = fieldSchema.optional();
|
||||
// 根据类型创建 Zod Schema
|
||||
switch (prop.type) {
|
||||
case 'string': {
|
||||
let stringSchema = z.string();
|
||||
|
||||
// 必填字段需要非空验证
|
||||
if (isRequired) {
|
||||
stringSchema = stringSchema.min(1, `${prop.title || key}不能为空`);
|
||||
}
|
||||
|
||||
if (prop.format === 'email') {
|
||||
stringSchema = stringSchema.email(prop.title ? `${prop.title}格式不正确` : '邮箱格式不正确');
|
||||
} else if (prop.format === 'url') {
|
||||
stringSchema = stringSchema.url(prop.title ? `${prop.title}格式不正确` : 'URL格式不正确');
|
||||
}
|
||||
if (prop.minLength) {
|
||||
stringSchema = stringSchema.min(prop.minLength, `${prop.title || key}至少需要${prop.minLength}个字符`);
|
||||
}
|
||||
if (prop.maxLength) {
|
||||
stringSchema = stringSchema.max(prop.maxLength, `${prop.title || key}最多${prop.maxLength}个字符`);
|
||||
}
|
||||
if (prop.pattern) {
|
||||
stringSchema = stringSchema.regex(new RegExp(prop.pattern), `${prop.title || key}格式不正确`);
|
||||
}
|
||||
|
||||
fieldSchema = stringSchema;
|
||||
break;
|
||||
}
|
||||
|
||||
case 'number':
|
||||
case 'integer':
|
||||
fieldSchema = prop.type === 'integer' ? z.number().int() : z.number();
|
||||
if (prop.minimum !== undefined) {
|
||||
fieldSchema = (fieldSchema as z.ZodNumber).min(prop.minimum, `${prop.title || key}不能小于${prop.minimum}`);
|
||||
}
|
||||
if (prop.maximum !== undefined) {
|
||||
fieldSchema = (fieldSchema as z.ZodNumber).max(prop.maximum, `${prop.title || key}不能大于${prop.maximum}`);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'boolean':
|
||||
fieldSchema = z.boolean();
|
||||
break;
|
||||
|
||||
case 'array':
|
||||
fieldSchema = z.array(z.any());
|
||||
if (prop.minItems !== undefined) {
|
||||
fieldSchema = (fieldSchema as z.ZodArray<any>).min(prop.minItems, `${prop.title || key}至少需要${prop.minItems}项`);
|
||||
}
|
||||
if (prop.maxItems !== undefined) {
|
||||
fieldSchema = (fieldSchema as z.ZodArray<any>).max(prop.maxItems, `${prop.title || key}最多${prop.maxItems}项`);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'object':
|
||||
fieldSchema = z.record(z.any());
|
||||
break;
|
||||
|
||||
default:
|
||||
fieldSchema = z.any();
|
||||
}
|
||||
|
||||
// 处理默认值
|
||||
if (prop.default !== undefined) {
|
||||
fieldSchema = fieldSchema.default(prop.default);
|
||||
}
|
||||
|
||||
// 处理可选字段
|
||||
if (!isRequired) {
|
||||
fieldSchema = fieldSchema.optional();
|
||||
}
|
||||
}
|
||||
|
||||
shape[key] = fieldSchema;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user