新增多种生成方式
This commit is contained in:
@@ -0,0 +1,201 @@
|
||||
/**
|
||||
* 代码生成数据转换工具
|
||||
* 确保三种模式输出统一的数据格式
|
||||
*/
|
||||
|
||||
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 {
|
||||
// 如果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 || '=',
|
||||
}))
|
||||
: [],
|
||||
};
|
||||
}
|
||||
|
||||
// 如果只有字段数组,需要用户补充基础信息
|
||||
if (Array.isArray(json)) {
|
||||
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 || '=',
|
||||
})),
|
||||
};
|
||||
}
|
||||
|
||||
// 默认返回空结构
|
||||
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()],
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 数据验证
|
||||
*/
|
||||
export function validateData(data: CodeGenData): {
|
||||
valid: boolean;
|
||||
message?: string;
|
||||
} {
|
||||
if (!data.class_name || !data.class_name.trim()) {
|
||||
return { valid: false, message: '类名不能为空' };
|
||||
}
|
||||
|
||||
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: '至少需要一个字段' };
|
||||
}
|
||||
|
||||
// 验证字段
|
||||
for (const field of data.field) {
|
||||
if (!field.name || !field.name.trim()) {
|
||||
return { valid: false, message: '字段名不能为空' };
|
||||
}
|
||||
}
|
||||
|
||||
return { valid: true };
|
||||
}
|
||||
|
||||
254
apps/web-antd/src/views/code-generation/utils/draft-manager.ts
Normal file
254
apps/web-antd/src/views/code-generation/utils/draft-manager.ts
Normal file
@@ -0,0 +1,254 @@
|
||||
/**
|
||||
* 草稿管理工具
|
||||
* 使用 localStorage 存储草稿,每种模式独立存储
|
||||
*/
|
||||
|
||||
export type GenerationMode = 'json' | 'manual' | 'ai';
|
||||
|
||||
export interface DraftItem {
|
||||
id: string;
|
||||
name: string;
|
||||
mode: GenerationMode;
|
||||
data: any;
|
||||
createdAt: number;
|
||||
updatedAt: number;
|
||||
}
|
||||
|
||||
const STORAGE_PREFIX = 'code-gen-draft';
|
||||
const MAX_DRAFTS_PER_MODE = 10; // 每种模式最多保存10个草稿
|
||||
|
||||
/**
|
||||
* 获取存储key
|
||||
*/
|
||||
function getStorageKey(mode: GenerationMode, id?: string): string {
|
||||
if (id) {
|
||||
return `${STORAGE_PREFIX}-${mode}-${id}`;
|
||||
}
|
||||
return `${STORAGE_PREFIX}-${mode}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有草稿的索引key
|
||||
*/
|
||||
function getIndexKey(mode: GenerationMode): string {
|
||||
return `${STORAGE_PREFIX}-index-${mode}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成草稿ID
|
||||
*/
|
||||
function generateDraftId(): string {
|
||||
return `draft-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取草稿索引列表
|
||||
*/
|
||||
function getDraftIndex(mode: GenerationMode): string[] {
|
||||
try {
|
||||
const key = getIndexKey(mode);
|
||||
const indexStr = localStorage.getItem(key);
|
||||
if (indexStr) {
|
||||
return JSON.parse(indexStr);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取草稿索引失败:', error);
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存草稿索引
|
||||
*/
|
||||
function saveDraftIndex(mode: GenerationMode, ids: string[]): void {
|
||||
try {
|
||||
const key = getIndexKey(mode);
|
||||
localStorage.setItem(key, JSON.stringify(ids));
|
||||
} catch (error) {
|
||||
console.error('保存草稿索引失败:', error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取默认草稿名称
|
||||
*/
|
||||
function getDefaultDraftName(mode: GenerationMode, index: number): string {
|
||||
const modeNames = {
|
||||
json: 'JSON导入',
|
||||
manual: '手动填写',
|
||||
ai: 'AI提示词',
|
||||
};
|
||||
const numbers = ['一', '二', '三', '四', '五', '六', '七', '八', '九', '十'];
|
||||
const number = numbers[index] || `${index + 1}`;
|
||||
return `${modeNames[mode]} - 草稿${number}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存草稿
|
||||
*/
|
||||
export function saveDraft(
|
||||
mode: GenerationMode,
|
||||
data: any,
|
||||
name?: string,
|
||||
draftId?: string,
|
||||
): string {
|
||||
try {
|
||||
const id = draftId || generateDraftId();
|
||||
const now = Date.now();
|
||||
const index = getDraftIndex(mode);
|
||||
|
||||
// 如果指定了draftId,更新现有草稿
|
||||
if (draftId && index.includes(draftId)) {
|
||||
const existingDraft = loadDraft(mode, draftId);
|
||||
const draftName = name || existingDraft?.name || getDefaultDraftName(mode, 0);
|
||||
const draft: DraftItem = {
|
||||
id,
|
||||
name: draftName,
|
||||
mode,
|
||||
data,
|
||||
createdAt: existingDraft?.createdAt || now,
|
||||
updatedAt: now,
|
||||
};
|
||||
|
||||
const key = getStorageKey(mode, id);
|
||||
localStorage.setItem(key, JSON.stringify(draft));
|
||||
return id;
|
||||
}
|
||||
|
||||
// 创建新草稿
|
||||
const draftName =
|
||||
name || getDefaultDraftName(mode, index.length);
|
||||
const draft: DraftItem = {
|
||||
id,
|
||||
name: draftName,
|
||||
mode,
|
||||
data,
|
||||
createdAt: now,
|
||||
updatedAt: now,
|
||||
};
|
||||
|
||||
// 保存草稿
|
||||
const key = getStorageKey(mode, id);
|
||||
localStorage.setItem(key, JSON.stringify(draft));
|
||||
|
||||
// 更新索引(限制数量)
|
||||
const newIndex = [id, ...index].slice(0, MAX_DRAFTS_PER_MODE);
|
||||
saveDraftIndex(mode, newIndex);
|
||||
|
||||
// 如果超出限制,删除最旧的草稿
|
||||
if (index.length >= MAX_DRAFTS_PER_MODE) {
|
||||
const oldIds = index.slice(MAX_DRAFTS_PER_MODE - 1);
|
||||
oldIds.forEach((oldId) => {
|
||||
try {
|
||||
localStorage.removeItem(getStorageKey(mode, oldId));
|
||||
} catch (error) {
|
||||
console.error('删除旧草稿失败:', error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return id;
|
||||
} catch (error) {
|
||||
console.error('保存草稿失败:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载草稿
|
||||
*/
|
||||
export function loadDraft(
|
||||
mode: GenerationMode,
|
||||
id: string,
|
||||
): DraftItem | null {
|
||||
try {
|
||||
const key = getStorageKey(mode, id);
|
||||
const draftStr = localStorage.getItem(key);
|
||||
if (draftStr) {
|
||||
const draft = JSON.parse(draftStr) as DraftItem;
|
||||
// 验证模式是否匹配
|
||||
if (draft.mode === mode) {
|
||||
return draft;
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('加载草稿失败:', error);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 列出所有草稿
|
||||
*/
|
||||
export function listDrafts(mode: GenerationMode): DraftItem[] {
|
||||
try {
|
||||
const index = getDraftIndex(mode);
|
||||
const drafts: DraftItem[] = [];
|
||||
|
||||
for (const id of index) {
|
||||
const draft = loadDraft(mode, id);
|
||||
if (draft) {
|
||||
drafts.push(draft);
|
||||
}
|
||||
}
|
||||
|
||||
// 按更新时间倒序排列
|
||||
return drafts.sort((a, b) => b.updatedAt - a.updatedAt);
|
||||
} catch (error) {
|
||||
console.error('列出草稿失败:', error);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除草稿
|
||||
*/
|
||||
export function deleteDraft(mode: GenerationMode, id: string): boolean {
|
||||
try {
|
||||
const key = getStorageKey(mode, id);
|
||||
localStorage.removeItem(key);
|
||||
|
||||
// 更新索引
|
||||
const index = getDraftIndex(mode);
|
||||
const newIndex = index.filter((draftId) => draftId !== id);
|
||||
saveDraftIndex(mode, newIndex);
|
||||
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error('删除草稿失败:', error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取草稿名称
|
||||
*/
|
||||
export function getDraftName(mode: GenerationMode, id: string): string {
|
||||
const draft = loadDraft(mode, id);
|
||||
return draft?.name || getDefaultDraftName(mode, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* 清空所有草稿(用于测试或重置)
|
||||
*/
|
||||
export function clearAllDrafts(mode?: GenerationMode): void {
|
||||
try {
|
||||
if (mode) {
|
||||
// 清空指定模式的草稿
|
||||
const index = getDraftIndex(mode);
|
||||
index.forEach((id) => {
|
||||
localStorage.removeItem(getStorageKey(mode, id));
|
||||
});
|
||||
localStorage.removeItem(getIndexKey(mode));
|
||||
} else {
|
||||
// 清空所有模式的草稿
|
||||
const modes: GenerationMode[] = ['json', 'manual', 'ai'];
|
||||
modes.forEach((m) => {
|
||||
clearAllDrafts(m);
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('清空草稿失败:', error);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user