Files
lgp-admin-plus/apps/web-antd/src/views/code-generation/utils/data-transformer.ts
2026-08-10 15:51:04 +08:00

266 lines
7.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 代码生成数据转换工具
* 确保三种模式输出统一的数据格式
*/
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<string, any>,
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<string>();
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 };
}