/** * 代码生成数据转换工具 * 确保三种模式输出统一的数据格式 */ export interface FieldType { name: string; type: string; type_length: string; default: string; comment: string; not_null: boolean; formShow: boolean; tableShow: boolean; formType: string; search: boolean; searchValue: string; } export interface CodeGenData { class_name: string; class_comment: string; icon: string; sort: number; pid: number; field: FieldType[]; } /** * 默认字段结构 */ const createDefaultField = (): FieldType => ({ name: '', type: 'varchar', type_length: '', default: '', comment: '', not_null: true, formShow: true, tableShow: true, formType: 'VbenInput', search: true, searchValue: '=', }); /** * JSON模式数据转换 * 支持单个对象或对象数组(批量生成) */ export function transformJsonToStandard(json: any): CodeGenData | CodeGenData[] { // 如果输入是数组(批量生成多个模块) if (Array.isArray(json) && json.length > 0) { // 检查第一个元素是否是完整的模块配置 if (json[0] && json[0].class_name && json[0].field) { // 数组中的每个元素都是完整的模块配置 return json.map((item: any) => ({ class_name: item.class_name || '', class_comment: item.class_comment || '', icon: item.icon || '', sort: item.sort ?? 9999, pid: item.pid ?? 0, field: Array.isArray(item.field) ? item.field.map((f: any) => ({ name: f.name || '', type: f.type || 'varchar', type_length: f.type_length || '', default: f.default || '', comment: f.comment || '', not_null: f.not_null !== undefined ? f.not_null : true, formShow: f.formShow !== undefined ? f.formShow : true, tableShow: f.tableShow !== undefined ? f.tableShow : true, formType: f.formType || 'VbenInput', search: f.search !== undefined ? f.search : true, searchValue: f.searchValue || '=', })) : [], })); } else { // 数组中的元素只是字段数组,需要用户补充基础信息 return { class_name: '', class_comment: '', icon: '', sort: 9999, pid: 0, field: json.map((f: any) => ({ name: f.name || '', type: f.type || 'varchar', type_length: f.type_length || '', default: f.default || '', comment: f.comment || '', not_null: f.not_null !== undefined ? f.not_null : true, formShow: f.formShow !== undefined ? f.formShow : true, tableShow: f.tableShow !== undefined ? f.tableShow : true, formType: f.formType || 'VbenInput', search: f.search !== undefined ? f.search : true, searchValue: f.searchValue || '=', })), }; } } // 如果JSON包含完整结构,直接使用(单个模块) if (json.class_name && json.field) { return { class_name: json.class_name || '', class_comment: json.class_comment || '', icon: json.icon || '', sort: json.sort ?? 9999, pid: json.pid ?? 0, field: Array.isArray(json.field) ? json.field.map((f: any) => ({ name: f.name || '', type: f.type || 'varchar', type_length: f.type_length || '', default: f.default || '', comment: f.comment || '', not_null: f.not_null !== undefined ? f.not_null : true, formShow: f.formShow !== undefined ? f.formShow : true, tableShow: f.tableShow !== undefined ? f.tableShow : true, formType: f.formType || 'VbenInput', search: f.search !== undefined ? f.search : true, searchValue: f.searchValue || '=', })) : [], }; } // 默认返回空结构 return { class_name: '', class_comment: '', icon: '', sort: 9999, pid: 0, field: [createDefaultField()], }; } /** * 手动模式数据转换 */ export function transformManualToStandard( formData: Record, fields: FieldType[], ): CodeGenData { return { class_name: formData.class_name || '', class_comment: formData.class_comment || '', icon: formData.icon || '', sort: formData.sort ?? 9999, pid: formData.pid ?? 0, field: Array.isArray(fields) ? fields : [], }; } /** * AI模式数据转换 */ export function transformAiToStandard(aiData: any): CodeGenData { // AI返回完整表单数据 if (aiData && aiData.class_name) { return { class_name: aiData.class_name || '', class_comment: aiData.class_comment || '', icon: aiData.icon || '', sort: aiData.sort ?? 9999, pid: aiData.pid ?? 0, field: Array.isArray(aiData.field) ? aiData.field.map((f: any) => ({ name: f.name || '', type: f.type || 'varchar', type_length: f.type_length || '', default: f.default || '', comment: f.comment || '', not_null: f.not_null !== undefined ? f.not_null : true, formShow: f.formShow !== undefined ? f.formShow : true, tableShow: f.tableShow !== undefined ? f.tableShow : true, formType: f.formType || 'VbenInput', search: f.search !== undefined ? f.search : true, searchValue: f.searchValue || '=', })) : [], }; } // 默认返回空结构 return { class_name: '', class_comment: '', icon: '', sort: 9999, pid: 0, field: [createDefaultField()], }; } /** 系统自动维护字段,禁止出现在业务 field 里 */ const RESERVED_FIELD_NAMES = new Set([ 'id', 'status', 'created_at', 'updated_at', 'deleted_at', ]); /** * 数据验证(导入前兜底,避免脏 class_name / 字段名进建表 SQL) */ export function validateData(data: CodeGenData): { valid: boolean; message?: string; } { if (!data.class_name || !data.class_name.trim()) { return { valid: false, message: '类名不能为空' }; } if (!/^[A-Z][A-Za-z0-9]{0,63}$/.test(data.class_name.trim())) { return { valid: false, message: '类名须为英文 PascalCase(如 VipMember),不能含中文或下划线', }; } if (!data.class_comment || !data.class_comment.trim()) { return { valid: false, message: '中文名称不能为空' }; } if (!data.icon || !data.icon.trim()) { return { valid: false, message: '菜单图标不能为空' }; } if (!Array.isArray(data.field) || data.field.length === 0) { return { valid: false, message: '至少需要一个字段' }; } const seen = new Set(); for (const field of data.field) { const name = (field.name || '').trim(); if (!name) { return { valid: false, message: '字段名不能为空' }; } if (name.length > 64 || /[\s,。::|()()]/.test(name)) { return { valid: false, message: `字段名非法「${name}」,须为短小写 snake_case`, }; } if (!/^[a-z][a-z0-9_]{0,63}$/.test(name)) { return { valid: false, message: `字段名非法「${name}」,须为小写 snake_case(如 user_name)`, }; } if (RESERVED_FIELD_NAMES.has(name)) { return { valid: false, message: `字段「${name}」为系统保留字段` }; } if (seen.has(name)) { return { valid: false, message: `字段名重复「${name}」` }; } seen.add(name); } return { valid: true }; }