feat: 完成sys模块迁移,对齐PHP/Java框架
- 重构sys模块架构,严格按admin/api/core分层 - 对齐所有sys实体与数据库表结构 - 实现完整的adminapi控制器,匹配PHP/Java契约 - 修复依赖注入问题,确保服务正确注册 - 添加自动迁移工具和契约验证 - 完善多租户支持和审计功能 - 统一命名规范,与PHP业务逻辑保持一致
This commit is contained in:
74
tools/gen-controllers.js
Normal file
74
tools/gen-controllers.js
Normal file
@@ -0,0 +1,74 @@
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const PROJECT_SRC = path.join(__dirname, '..', 'wwjcloud', 'src', 'common');
|
||||
const CONTRACT_FILE = path.join(__dirname, 'contracts', 'routes.json');
|
||||
|
||||
function toCamelCase(input) {
|
||||
return input.replace(/[-_]+([a-zA-Z0-9])/g, (_, c) => c.toUpperCase());
|
||||
}
|
||||
|
||||
function toPascalCase(input) {
|
||||
const camel = toCamelCase(input);
|
||||
return camel.charAt(0).toUpperCase() + camel.slice(1);
|
||||
}
|
||||
|
||||
function ensureDir(dir) {
|
||||
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
|
||||
}
|
||||
|
||||
function buildMethodName(method, relPath) {
|
||||
const cleaned = relPath.replace(/:\w+/g, '').replace(/\/$/, '');
|
||||
const parts = cleaned.split('/').filter(Boolean);
|
||||
const base = parts.length ? parts.join('_') : 'root';
|
||||
return method.toLowerCase() + toPascalCase(base);
|
||||
}
|
||||
|
||||
function controllerTemplate(prefix, className, routes) {
|
||||
const imports = "import { Controller, Get, Post, Put, Delete, Body, Param, Query, UseGuards } from '@nestjs/common';\n" +
|
||||
"import { ApiOperation, ApiTags } from '@nestjs/swagger';\n" +
|
||||
"import { AdminCheckTokenGuard } from '../../../../core/security/adminCheckToken.guard';\n" +
|
||||
"import { SiteScopeGuard } from '../../../../core/security/siteScopeGuard';\n\n";
|
||||
const header = `@ApiTags('${prefix}')\n@UseGuards(AdminCheckTokenGuard, SiteScopeGuard)\n@Controller('adminapi/${prefix}')\nexport class ${className} {`;
|
||||
const methods = routes.map(r => {
|
||||
const decorator = `@${r.method.charAt(0) + r.method.slice(1).toLowerCase()}('${r.rel}')`;
|
||||
const summary = `@ApiOperation({ summary: '${r.method} ${r.rel}' })`;
|
||||
const methodName = buildMethodName(r.method, r.rel);
|
||||
return ` ${decorator}\n ${summary}\n ${methodName}() {\n return { success: true };\n }`;
|
||||
}).join('\n\n');
|
||||
return imports + header + '\n' + methods + '\n}\n';
|
||||
}
|
||||
|
||||
function main() {
|
||||
const contract = JSON.parse(fs.readFileSync(CONTRACT_FILE, 'utf8'));
|
||||
// group by first segment after adminapi/
|
||||
const groups = new Map();
|
||||
for (const r of contract) {
|
||||
if (!r.path.startsWith('adminapi/')) continue;
|
||||
const rest = r.path.slice('adminapi/'.length);
|
||||
const [prefix, ...restParts] = rest.split('/');
|
||||
const rel = restParts.join('/');
|
||||
const arr = groups.get(prefix) || [];
|
||||
arr.push({ method: r.method, rel });
|
||||
groups.set(prefix, arr);
|
||||
}
|
||||
for (const [prefix, routes] of groups) {
|
||||
const moduleDir = path.join(PROJECT_SRC, prefix);
|
||||
const ctrlDir = path.join(moduleDir, 'controllers', 'adminapi');
|
||||
ensureDir(ctrlDir);
|
||||
const fileName = `${toCamelCase(prefix)}.controller.ts`;
|
||||
const filePath = path.join(ctrlDir, fileName);
|
||||
if (fs.existsSync(filePath)) {
|
||||
// do not overwrite; skip existing controllers
|
||||
continue;
|
||||
}
|
||||
const className = `${toPascalCase(prefix)}Controller`;
|
||||
const content = controllerTemplate(prefix, className, routes);
|
||||
fs.writeFileSync(filePath, content);
|
||||
console.log('Generated', filePath);
|
||||
}
|
||||
}
|
||||
|
||||
main();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user