271 lines
6.5 KiB
JavaScript
271 lines
6.5 KiB
JavaScript
|
|
#!/usr/bin/env node
|
|||
|
|
|
|||
|
|
const fs = require('fs');
|
|||
|
|
const path = require('path');
|
|||
|
|
const BaseGenerator = require('./base-generator');
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 📚 字典生成器
|
|||
|
|
* 专门负责生成NestJS字典/枚举文件
|
|||
|
|
*/
|
|||
|
|
class DictGenerator extends BaseGenerator {
|
|||
|
|
constructor() {
|
|||
|
|
super('DictGenerator');
|
|||
|
|
|
|||
|
|
this.config = {
|
|||
|
|
phpBasePath: '/Users/wanwu/Documents/wwjcloud/wwjcloud-nsetjs/niucloud-php/niucloud',
|
|||
|
|
nestjsBasePath: '/Users/wanwu/Documents/wwjcloud/wwjcloud-nsetjs/wwjcloud-nest/src/core',
|
|||
|
|
discoveryResultPath: '/Users/wanwu/Documents/wwjcloud/wwjcloud-nsetjs/tools/php-discovery-result.json'
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
this.discoveryData = null;
|
|||
|
|
this.dictStats = {
|
|||
|
|
dictsCreated: 0,
|
|||
|
|
dictsSkipped: 0
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 运行字典生成
|
|||
|
|
*/
|
|||
|
|
async run() {
|
|||
|
|
try {
|
|||
|
|
console.log('📚 启动字典生成器...');
|
|||
|
|
console.log('目标:生成NestJS字典/枚举文件\n');
|
|||
|
|
|
|||
|
|
// 加载PHP文件发现结果
|
|||
|
|
await this.loadDiscoveryData();
|
|||
|
|
|
|||
|
|
// 生成字典
|
|||
|
|
await this.generateDicts();
|
|||
|
|
|
|||
|
|
// 输出统计报告
|
|||
|
|
this.printStats();
|
|||
|
|
|
|||
|
|
} catch (error) {
|
|||
|
|
console.error('❌ 字典生成失败:', error);
|
|||
|
|
this.stats.errors++;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 加载PHP文件发现结果
|
|||
|
|
*/
|
|||
|
|
async loadDiscoveryData() {
|
|||
|
|
try {
|
|||
|
|
const data = fs.readFileSync(this.config.discoveryResultPath, 'utf8');
|
|||
|
|
this.discoveryData = JSON.parse(data);
|
|||
|
|
console.log(' ✅ 成功加载PHP文件发现结果');
|
|||
|
|
} catch (error) {
|
|||
|
|
console.error('❌ 加载发现结果失败:', error);
|
|||
|
|
throw error;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 生成字典
|
|||
|
|
*/
|
|||
|
|
async generateDicts() {
|
|||
|
|
console.log(' 🔨 生成字典...');
|
|||
|
|
|
|||
|
|
for (const [moduleName, dicts] of Object.entries(this.discoveryData.dicts)) {
|
|||
|
|
for (const [dictName, dictInfo] of Object.entries(dicts)) {
|
|||
|
|
await this.createDict(moduleName, dictName, dictInfo);
|
|||
|
|
this.stats.dictsCreated++;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
console.log(` ✅ 生成了 ${this.stats.dictsCreated} 个字典`);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 创建字典
|
|||
|
|
*/
|
|||
|
|
async createDict(moduleName, dictName, dictInfo) {
|
|||
|
|
// 使用 kebab-case 文件名,避免重叠名问题
|
|||
|
|
// 例如: dict → dict.enum.ts (而不是 DictDict.ts)
|
|||
|
|
const kebabName = this.toKebabCase(dictName);
|
|||
|
|
const dictPath = path.join(
|
|||
|
|
this.config.nestjsBasePath,
|
|||
|
|
moduleName,
|
|||
|
|
'enums',
|
|||
|
|
`${kebabName}.enum.ts` // ✅ kebab-case + .enum.ts 后缀
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
const content = this.generateDictContent(moduleName, dictName);
|
|||
|
|
const success = this.writeFile(dictPath, content, `Enum for ${moduleName}/${dictName}`);
|
|||
|
|
|
|||
|
|
if (success) {
|
|||
|
|
this.dictStats.dictsCreated++;
|
|||
|
|
} else {
|
|||
|
|
this.dictStats.dictsSkipped++;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 生成字典内容
|
|||
|
|
*/
|
|||
|
|
generateDictContent(moduleName, dictName) {
|
|||
|
|
// 避免重叠名: Dict → DictEnum (而不是 DictDict)
|
|||
|
|
const pascalName = this.toPascalCase(dictName);
|
|||
|
|
const className = `${pascalName}Enum`; // ✅ 例如: DictEnum, MemberEnum
|
|||
|
|
const dictVarName = `${this.toCamelCase(dictName)}Dict`; // ✅ 例如: dictDict, memberDict
|
|||
|
|
|
|||
|
|
const content = `/**
|
|||
|
|
* ${dictName} 枚举
|
|||
|
|
* 定义相关的常量值
|
|||
|
|
*/
|
|||
|
|
|
|||
|
|
export enum ${className} {
|
|||
|
|
// 状态枚举
|
|||
|
|
STATUS_ACTIVE = 'active',
|
|||
|
|
STATUS_INACTIVE = 'inactive',
|
|||
|
|
STATUS_PENDING = 'pending',
|
|||
|
|
STATUS_DELETED = 'deleted',
|
|||
|
|
|
|||
|
|
// 类型枚举
|
|||
|
|
TYPE_NORMAL = 'normal',
|
|||
|
|
TYPE_PREMIUM = 'premium',
|
|||
|
|
TYPE_VIP = 'vip',
|
|||
|
|
|
|||
|
|
// 级别枚举
|
|||
|
|
LEVEL_LOW = 1,
|
|||
|
|
LEVEL_MEDIUM = 2,
|
|||
|
|
LEVEL_HIGH = 3,
|
|||
|
|
LEVEL_CRITICAL = 4,
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* ${dictName} 字典映射
|
|||
|
|
*/
|
|||
|
|
export const ${dictVarName} = {
|
|||
|
|
// 状态映射
|
|||
|
|
status: {
|
|||
|
|
[${className}.STATUS_ACTIVE]: '激活',
|
|||
|
|
[${className}.STATUS_INACTIVE]: '未激活',
|
|||
|
|
[${className}.STATUS_PENDING]: '待处理',
|
|||
|
|
[${className}.STATUS_DELETED]: '已删除',
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
// 类型映射
|
|||
|
|
type: {
|
|||
|
|
[${className}.TYPE_NORMAL]: '普通',
|
|||
|
|
[${className}.TYPE_PREMIUM]: '高级',
|
|||
|
|
[${className}.TYPE_VIP]: 'VIP',
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
// 级别映射
|
|||
|
|
level: {
|
|||
|
|
[${className}.LEVEL_LOW]: '低',
|
|||
|
|
[${className}.LEVEL_MEDIUM]: '中',
|
|||
|
|
[${className}.LEVEL_HIGH]: '高',
|
|||
|
|
[${className}.LEVEL_CRITICAL]: '紧急',
|
|||
|
|
},
|
|||
|
|
} as const;
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* ${dictName} 工具类
|
|||
|
|
*/
|
|||
|
|
export class ${className}Util {
|
|||
|
|
/**
|
|||
|
|
* 获取状态文本
|
|||
|
|
*/
|
|||
|
|
static getStatusText(status: ${className}): string {
|
|||
|
|
return (${dictVarName}.status as any)[status] || '未知';
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 获取类型文本
|
|||
|
|
*/
|
|||
|
|
static getTypeText(type: ${className}): string {
|
|||
|
|
return (${dictVarName}.type as any)[type] || '未知';
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 获取级别文本
|
|||
|
|
*/
|
|||
|
|
static getLevelText(level: ${className}): string {
|
|||
|
|
return (${dictVarName}.level as any)[level] || '未知';
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 获取所有状态选项
|
|||
|
|
*/
|
|||
|
|
static getStatusOptions(): Array<{ value: string; label: string }> {
|
|||
|
|
return Object.entries(${dictVarName}.status).map(([value, label]) => ({
|
|||
|
|
value,
|
|||
|
|
label: label as string,
|
|||
|
|
}));
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 获取所有类型选项
|
|||
|
|
*/
|
|||
|
|
static getTypeOptions(): Array<{ value: string; label: string }> {
|
|||
|
|
return Object.entries(${dictVarName}.type).map(([value, label]) => ({
|
|||
|
|
value,
|
|||
|
|
label: label as string,
|
|||
|
|
}));
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 获取所有级别选项
|
|||
|
|
*/
|
|||
|
|
static getLevelOptions(): Array<{ value: number; label: string }> {
|
|||
|
|
return Object.entries(${dictVarName}.level).map(([value, label]) => ({
|
|||
|
|
value: Number(value),
|
|||
|
|
label: label as string,
|
|||
|
|
}));
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 验证状态值
|
|||
|
|
*/
|
|||
|
|
static isValidStatus(status: string): boolean {
|
|||
|
|
return Object.values(${className}).includes(status as ${className});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 验证类型值
|
|||
|
|
*/
|
|||
|
|
static isValidType(type: string): boolean {
|
|||
|
|
return Object.values(${className}).includes(type as ${className});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 验证级别值
|
|||
|
|
*/
|
|||
|
|
static isValidLevel(level: number): boolean {
|
|||
|
|
return Object.values(${className}).includes(level as ${className});
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* ${dictName} 类型定义
|
|||
|
|
*/
|
|||
|
|
export type ${className}Status = keyof typeof ${dictVarName}.status;
|
|||
|
|
export type ${className}Type = keyof typeof ${dictVarName}.type;
|
|||
|
|
export type ${className}Level = keyof typeof ${dictVarName}.level;`;
|
|||
|
|
|
|||
|
|
return content;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 输出统计报告
|
|||
|
|
*/
|
|||
|
|
printStats() {
|
|||
|
|
super.printStats({
|
|||
|
|
'Dicts Created': this.dictStats.dictsCreated,
|
|||
|
|
'Dicts Skipped': this.dictStats.dictsSkipped
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 如果直接运行此文件
|
|||
|
|
if (require.main === module) {
|
|||
|
|
const generator = new DictGenerator();
|
|||
|
|
generator.run().catch(console.error);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
module.exports = DictGenerator;
|