intention-coding 0.6.4 → 0.6.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/db/tech-spec-storage.d.ts +139 -0
- package/dist/db/tech-spec-storage.d.ts.map +1 -0
- package/dist/index.cjs +2432 -55
- package/dist/services/tech-spec-generator/chapter-processor.d.ts +144 -0
- package/dist/services/tech-spec-generator/chapter-processor.d.ts.map +1 -0
- package/dist/services/tech-spec-generator/code-analyzer.d.ts +19 -0
- package/dist/services/tech-spec-generator/code-analyzer.d.ts.map +1 -0
- package/dist/services/tech-spec-generator/document-merger.d.ts +50 -0
- package/dist/services/tech-spec-generator/document-merger.d.ts.map +1 -0
- package/dist/services/tech-spec-generator/index.d.ts +221 -22
- package/dist/services/tech-spec-generator/index.d.ts.map +1 -1
- package/dist/services/tech-spec-generator/project-analyzer.d.ts +58 -0
- package/dist/services/tech-spec-generator/project-analyzer.d.ts.map +1 -0
- package/dist/services/tech-spec-generator/types.d.ts +68 -0
- package/dist/services/tech-spec-generator/types.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -11116,6 +11116,1836 @@ ${requirement_description}
|
|
|
11116
11116
|
function getTechSpecOutputDir(projectPath) {
|
|
11117
11117
|
return `${projectPath}/${TECH_SPEC_OUTPUT_DIR}`;
|
|
11118
11118
|
}
|
|
11119
|
+
const FILE_TYPE_PATTERNS = {
|
|
11120
|
+
controller: [
|
|
11121
|
+
/Controller\.(ts|js|java)$/i,
|
|
11122
|
+
/controller\.(ts|js|java)$/i,
|
|
11123
|
+
/@Controller/,
|
|
11124
|
+
/@RestController/
|
|
11125
|
+
],
|
|
11126
|
+
service: [
|
|
11127
|
+
/Service\.(ts|js|java)$/i,
|
|
11128
|
+
/service\.(ts|js|java)$/i,
|
|
11129
|
+
/@Service/,
|
|
11130
|
+
/ServiceImpl\.(ts|js|java)$/i
|
|
11131
|
+
],
|
|
11132
|
+
entity: [
|
|
11133
|
+
/Entity\.(ts|js|java)$/i,
|
|
11134
|
+
/entity\.(ts|js|java)$/i,
|
|
11135
|
+
/Model\.(ts|js|java)$/i,
|
|
11136
|
+
/model\.(ts|js|java)$/i,
|
|
11137
|
+
/@Entity/,
|
|
11138
|
+
/@Table/
|
|
11139
|
+
],
|
|
11140
|
+
dto: [
|
|
11141
|
+
/DTO\.(ts|js|java)$/i,
|
|
11142
|
+
/dto\.(ts|js|java)$/i,
|
|
11143
|
+
/Vo\.(ts|js|java)$/i,
|
|
11144
|
+
/vo\.(ts|js|java)$/i,
|
|
11145
|
+
/Bo\.(ts|js|java)$/i,
|
|
11146
|
+
/bo\.(ts|js|java)$/i,
|
|
11147
|
+
/Request\.(ts|js|java)$/i,
|
|
11148
|
+
/Response\.(ts|js|java)$/i,
|
|
11149
|
+
/Query\.(ts|js|java)$/i,
|
|
11150
|
+
/Form\.(ts|js|java)$/i
|
|
11151
|
+
],
|
|
11152
|
+
config: [
|
|
11153
|
+
/Config\.(ts|js|java)$/i,
|
|
11154
|
+
/config\.(ts|js|java)$/i,
|
|
11155
|
+
/Configuration\.(ts|js|java)$/i,
|
|
11156
|
+
/@Configuration/
|
|
11157
|
+
]
|
|
11158
|
+
};
|
|
11159
|
+
const IGNORE_PATTERNS = [
|
|
11160
|
+
"node_modules",
|
|
11161
|
+
".git",
|
|
11162
|
+
".svn",
|
|
11163
|
+
"target",
|
|
11164
|
+
"build",
|
|
11165
|
+
"dist",
|
|
11166
|
+
".idea",
|
|
11167
|
+
".vscode",
|
|
11168
|
+
"logs",
|
|
11169
|
+
"temp",
|
|
11170
|
+
"tmp",
|
|
11171
|
+
".DS_Store",
|
|
11172
|
+
"Thumbs.db",
|
|
11173
|
+
"*.log",
|
|
11174
|
+
"*.tmp",
|
|
11175
|
+
"*.bak"
|
|
11176
|
+
];
|
|
11177
|
+
function shouldIgnore(filePath) {
|
|
11178
|
+
const fileName = external_path_namespaceObject.basename(filePath);
|
|
11179
|
+
const dirName = external_path_namespaceObject.dirname(filePath);
|
|
11180
|
+
return IGNORE_PATTERNS.some((pattern)=>{
|
|
11181
|
+
if (pattern.includes("*")) {
|
|
11182
|
+
const regex = new RegExp(pattern.replace(/\*/g, ".*"));
|
|
11183
|
+
return regex.test(fileName);
|
|
11184
|
+
}
|
|
11185
|
+
return fileName === pattern || dirName.includes(pattern) || filePath.includes(pattern);
|
|
11186
|
+
});
|
|
11187
|
+
}
|
|
11188
|
+
async function identifyFileType(filePath) {
|
|
11189
|
+
const fileName = external_path_namespaceObject.basename(filePath);
|
|
11190
|
+
for (const [type, patterns] of Object.entries(FILE_TYPE_PATTERNS))for (const pattern of patterns)if (pattern instanceof RegExp) {
|
|
11191
|
+
if (pattern.test(fileName)) return type;
|
|
11192
|
+
}
|
|
11193
|
+
try {
|
|
11194
|
+
const stats = await promises_namespaceObject.stat(filePath);
|
|
11195
|
+
if (stats.size < 51200) {
|
|
11196
|
+
const content = await promises_namespaceObject.readFile(filePath, "utf-8");
|
|
11197
|
+
for (const [type, patterns] of Object.entries(FILE_TYPE_PATTERNS))for (const pattern of patterns)if (pattern instanceof RegExp && pattern.test(content)) return type;
|
|
11198
|
+
}
|
|
11199
|
+
} catch (error) {}
|
|
11200
|
+
return "other";
|
|
11201
|
+
}
|
|
11202
|
+
async function scanDirectory(dirPath, projectPath, currentModule) {
|
|
11203
|
+
const files = [];
|
|
11204
|
+
try {
|
|
11205
|
+
const entries = await promises_namespaceObject.readdir(dirPath, {
|
|
11206
|
+
withFileTypes: true
|
|
11207
|
+
});
|
|
11208
|
+
for (const entry of entries){
|
|
11209
|
+
const fullPath = external_path_namespaceObject.join(dirPath, entry.name);
|
|
11210
|
+
const relativePath = external_path_namespaceObject.relative(projectPath, fullPath);
|
|
11211
|
+
if (!shouldIgnore(fullPath)) {
|
|
11212
|
+
if (entry.isDirectory()) {
|
|
11213
|
+
const subFiles = await scanDirectory(fullPath, projectPath, currentModule);
|
|
11214
|
+
files.push(...subFiles);
|
|
11215
|
+
} else if (entry.isFile()) {
|
|
11216
|
+
const ext = external_path_namespaceObject.extname(entry.name).toLowerCase();
|
|
11217
|
+
if ([
|
|
11218
|
+
".ts",
|
|
11219
|
+
".js",
|
|
11220
|
+
".java",
|
|
11221
|
+
".kt",
|
|
11222
|
+
".py",
|
|
11223
|
+
".go",
|
|
11224
|
+
".cs"
|
|
11225
|
+
].includes(ext)) {
|
|
11226
|
+
const fileType = await identifyFileType(fullPath);
|
|
11227
|
+
files.push({
|
|
11228
|
+
path: fullPath,
|
|
11229
|
+
name: entry.name,
|
|
11230
|
+
type: fileType,
|
|
11231
|
+
relativePath,
|
|
11232
|
+
module: currentModule
|
|
11233
|
+
});
|
|
11234
|
+
}
|
|
11235
|
+
}
|
|
11236
|
+
}
|
|
11237
|
+
}
|
|
11238
|
+
} catch (error) {
|
|
11239
|
+
logger.warn(`\u{626B}\u{63CF}\u{76EE}\u{5F55}\u{5931}\u{8D25}: ${dirPath}`, {
|
|
11240
|
+
error
|
|
11241
|
+
});
|
|
11242
|
+
}
|
|
11243
|
+
return files;
|
|
11244
|
+
}
|
|
11245
|
+
function identifyModules(files, projectPath) {
|
|
11246
|
+
const moduleMap = new Map();
|
|
11247
|
+
for (const file of files){
|
|
11248
|
+
const pathParts = file.relativePath.split(external_path_namespaceObject.sep);
|
|
11249
|
+
let moduleName = "default";
|
|
11250
|
+
if (pathParts.includes("src") && pathParts.includes("main") && pathParts.includes("java")) {
|
|
11251
|
+
const javaIndex = pathParts.indexOf("java");
|
|
11252
|
+
if (javaIndex + 3 < pathParts.length) moduleName = pathParts[javaIndex + 3];
|
|
11253
|
+
} else if (pathParts.includes("modules") || pathParts.includes("packages")) {
|
|
11254
|
+
const moduleIndex = pathParts.findIndex((p)=>"modules" === p || "packages" === p);
|
|
11255
|
+
if (moduleIndex + 1 < pathParts.length) moduleName = pathParts[moduleIndex + 1];
|
|
11256
|
+
} else if (pathParts.length > 1) moduleName = pathParts[0];
|
|
11257
|
+
if (!moduleMap.has(moduleName)) moduleMap.set(moduleName, []);
|
|
11258
|
+
moduleMap.get(moduleName).push({
|
|
11259
|
+
...file,
|
|
11260
|
+
module: moduleName
|
|
11261
|
+
});
|
|
11262
|
+
}
|
|
11263
|
+
const modules = [];
|
|
11264
|
+
for (const [moduleName, moduleFiles] of moduleMap.entries()){
|
|
11265
|
+
if (0 === moduleFiles.length) continue;
|
|
11266
|
+
const modulePaths = moduleFiles.map((f)=>external_path_namespaceObject.dirname(f.path));
|
|
11267
|
+
const commonPath = findCommonPath(modulePaths);
|
|
11268
|
+
modules.push({
|
|
11269
|
+
name: moduleName,
|
|
11270
|
+
path: commonPath,
|
|
11271
|
+
relativePath: external_path_namespaceObject.relative(projectPath, commonPath),
|
|
11272
|
+
files: moduleFiles,
|
|
11273
|
+
subModules: []
|
|
11274
|
+
});
|
|
11275
|
+
}
|
|
11276
|
+
return modules;
|
|
11277
|
+
}
|
|
11278
|
+
function findCommonPath(paths) {
|
|
11279
|
+
if (0 === paths.length) return "";
|
|
11280
|
+
if (1 === paths.length) return external_path_namespaceObject.dirname(paths[0]);
|
|
11281
|
+
const parts = paths[0].split(external_path_namespaceObject.sep);
|
|
11282
|
+
let commonLength = parts.length;
|
|
11283
|
+
for(let i = 1; i < paths.length; i++){
|
|
11284
|
+
const currentParts = paths[i].split(external_path_namespaceObject.sep);
|
|
11285
|
+
commonLength = Math.min(commonLength, currentParts.length);
|
|
11286
|
+
for(let j = 0; j < commonLength; j++)if (parts[j] !== currentParts[j]) {
|
|
11287
|
+
commonLength = j;
|
|
11288
|
+
break;
|
|
11289
|
+
}
|
|
11290
|
+
}
|
|
11291
|
+
return parts.slice(0, commonLength).join(external_path_namespaceObject.sep);
|
|
11292
|
+
}
|
|
11293
|
+
async function analyzeProject(projectPath) {
|
|
11294
|
+
logger.info(`\u{5F00}\u{59CB}\u{5206}\u{6790}\u{9879}\u{76EE}: ${projectPath}`);
|
|
11295
|
+
try {
|
|
11296
|
+
const stats = await promises_namespaceObject.stat(projectPath);
|
|
11297
|
+
if (!stats.isDirectory()) throw new Error(`\u{9879}\u{76EE}\u{8DEF}\u{5F84}\u{4E0D}\u{662F}\u{76EE}\u{5F55}: ${projectPath}`);
|
|
11298
|
+
const allFiles = await scanDirectory(projectPath, projectPath);
|
|
11299
|
+
const modules = identifyModules(allFiles, projectPath);
|
|
11300
|
+
const statistics = {
|
|
11301
|
+
totalFiles: allFiles.length,
|
|
11302
|
+
controllerFiles: allFiles.filter((f)=>"controller" === f.type).length,
|
|
11303
|
+
serviceFiles: allFiles.filter((f)=>"service" === f.type).length,
|
|
11304
|
+
entityFiles: allFiles.filter((f)=>"entity" === f.type).length,
|
|
11305
|
+
dtoFiles: allFiles.filter((f)=>"dto" === f.type).length,
|
|
11306
|
+
moduleCount: modules.length
|
|
11307
|
+
};
|
|
11308
|
+
const projectName = external_path_namespaceObject.basename(projectPath);
|
|
11309
|
+
const result = {
|
|
11310
|
+
projectName,
|
|
11311
|
+
projectPath,
|
|
11312
|
+
modules,
|
|
11313
|
+
allFiles,
|
|
11314
|
+
statistics
|
|
11315
|
+
};
|
|
11316
|
+
logger.info(`\u{9879}\u{76EE}\u{5206}\u{6790}\u{5B8C}\u{6210}`, {
|
|
11317
|
+
projectName,
|
|
11318
|
+
moduleCount: modules.length,
|
|
11319
|
+
totalFiles: allFiles.length
|
|
11320
|
+
});
|
|
11321
|
+
return result;
|
|
11322
|
+
} catch (error) {
|
|
11323
|
+
logger.error(`\u{9879}\u{76EE}\u{5206}\u{6790}\u{5931}\u{8D25}: ${projectPath}`, {
|
|
11324
|
+
error: error.message
|
|
11325
|
+
});
|
|
11326
|
+
throw error;
|
|
11327
|
+
}
|
|
11328
|
+
}
|
|
11329
|
+
function getModuleNames(analysis) {
|
|
11330
|
+
return analysis.modules.map((m)=>m.name);
|
|
11331
|
+
}
|
|
11332
|
+
function extractComments(content) {
|
|
11333
|
+
const comments = new Map();
|
|
11334
|
+
const lines = content.split("\n");
|
|
11335
|
+
let currentComment = "";
|
|
11336
|
+
let commentStartLine = -1;
|
|
11337
|
+
for(let i = 0; i < lines.length; i++){
|
|
11338
|
+
const line = lines[i].trim();
|
|
11339
|
+
if (line.startsWith("/**")) {
|
|
11340
|
+
currentComment = "";
|
|
11341
|
+
commentStartLine = i;
|
|
11342
|
+
} else if (line.startsWith("*") && commentStartLine >= 0) {
|
|
11343
|
+
const commentText = line.replace(/^\*\s?/, "");
|
|
11344
|
+
if (commentText && !commentText.startsWith("@")) currentComment += (currentComment ? " " : "") + commentText;
|
|
11345
|
+
} else if (line.startsWith("*/") && commentStartLine >= 0) {
|
|
11346
|
+
if (currentComment) comments.set(i + 1, currentComment);
|
|
11347
|
+
currentComment = "";
|
|
11348
|
+
commentStartLine = -1;
|
|
11349
|
+
} else if (line.startsWith("//")) {
|
|
11350
|
+
const commentText = line.replace(/^\/\/\s?/, "");
|
|
11351
|
+
if (commentText) comments.set(i + 1, commentText);
|
|
11352
|
+
}
|
|
11353
|
+
}
|
|
11354
|
+
return comments;
|
|
11355
|
+
}
|
|
11356
|
+
function extractAnnotations(content, lineNumber) {
|
|
11357
|
+
const lines = content.split("\n");
|
|
11358
|
+
const annotations = [];
|
|
11359
|
+
for(let i = Math.max(0, lineNumber - 10); i < lineNumber; i++){
|
|
11360
|
+
const line = lines[i]?.trim();
|
|
11361
|
+
if (line && line.startsWith("@")) annotations.push(line);
|
|
11362
|
+
}
|
|
11363
|
+
return annotations;
|
|
11364
|
+
}
|
|
11365
|
+
async function analyzeJavaController(file) {
|
|
11366
|
+
try {
|
|
11367
|
+
const content = await promises_namespaceObject.readFile(file.path, "utf-8");
|
|
11368
|
+
const comments = extractComments(content);
|
|
11369
|
+
const lines = content.split("\n");
|
|
11370
|
+
let className = "";
|
|
11371
|
+
let classDescription = "";
|
|
11372
|
+
let classLineNumber = -1;
|
|
11373
|
+
for(let i = 0; i < lines.length; i++){
|
|
11374
|
+
const line = lines[i].trim();
|
|
11375
|
+
if (line.includes("class ") && (line.includes("Controller") || line.includes("@RestController") || line.includes("@Controller"))) {
|
|
11376
|
+
const match = line.match(/class\s+(\w+)/);
|
|
11377
|
+
if (match) {
|
|
11378
|
+
className = match[1];
|
|
11379
|
+
classLineNumber = i;
|
|
11380
|
+
classDescription = comments.get(i) || className;
|
|
11381
|
+
break;
|
|
11382
|
+
}
|
|
11383
|
+
}
|
|
11384
|
+
}
|
|
11385
|
+
if (!className) return null;
|
|
11386
|
+
const methods = [];
|
|
11387
|
+
for(let i = 0; i < lines.length; i++){
|
|
11388
|
+
const line = lines[i].trim();
|
|
11389
|
+
const methodMatch = line.match(/public\s+(\w+(?:<[^>]+>)?)\s+(\w+)\s*\([^)]*\)/);
|
|
11390
|
+
if (methodMatch) {
|
|
11391
|
+
const returnType = methodMatch[1];
|
|
11392
|
+
const methodName = methodMatch[2];
|
|
11393
|
+
const methodDescription = comments.get(i) || methodName;
|
|
11394
|
+
const annotations = extractAnnotations(content, i);
|
|
11395
|
+
let httpMethod = "";
|
|
11396
|
+
let path = "";
|
|
11397
|
+
for (const annotation of annotations){
|
|
11398
|
+
if (annotation.includes("@GetMapping") || annotation.includes("@RequestMapping") && annotation.includes("GET")) httpMethod = "GET";
|
|
11399
|
+
else if (annotation.includes("@PostMapping") || annotation.includes("@RequestMapping") && annotation.includes("POST")) httpMethod = "POST";
|
|
11400
|
+
else if (annotation.includes("@PutMapping")) httpMethod = "PUT";
|
|
11401
|
+
else if (annotation.includes("@DeleteMapping")) httpMethod = "DELETE";
|
|
11402
|
+
const pathMatch = annotation.match(/["\']([^"']+)["\']/);
|
|
11403
|
+
if (pathMatch) path = pathMatch[1];
|
|
11404
|
+
}
|
|
11405
|
+
const parameters = [];
|
|
11406
|
+
const paramMatch = line.match(/\(([^)]+)\)/);
|
|
11407
|
+
if (paramMatch) {
|
|
11408
|
+
const paramStr = paramMatch[1];
|
|
11409
|
+
const params = paramStr.split(",").map((p)=>p.trim()).filter((p)=>p);
|
|
11410
|
+
params.forEach((param, index)=>{
|
|
11411
|
+
const parts = param.split(/\s+/);
|
|
11412
|
+
if (parts.length >= 2) {
|
|
11413
|
+
const type = parts[parts.length - 2];
|
|
11414
|
+
const name = parts[parts.length - 1];
|
|
11415
|
+
parameters.push({
|
|
11416
|
+
id: String(index + 1),
|
|
11417
|
+
propertyType: type,
|
|
11418
|
+
propertyName: name,
|
|
11419
|
+
required: "\u662F",
|
|
11420
|
+
propertyDesc: `${name}\u{53C2}\u{6570}`
|
|
11421
|
+
});
|
|
11422
|
+
}
|
|
11423
|
+
});
|
|
11424
|
+
}
|
|
11425
|
+
methods.push({
|
|
11426
|
+
name: methodName,
|
|
11427
|
+
description: methodDescription,
|
|
11428
|
+
parameters,
|
|
11429
|
+
returnType,
|
|
11430
|
+
returnDescription: `${methodName}\u{8FD4}\u{56DE}\u{7ED3}\u{679C}`,
|
|
11431
|
+
httpMethod,
|
|
11432
|
+
path
|
|
11433
|
+
});
|
|
11434
|
+
}
|
|
11435
|
+
}
|
|
11436
|
+
return {
|
|
11437
|
+
name: className,
|
|
11438
|
+
description: classDescription,
|
|
11439
|
+
type: "controller",
|
|
11440
|
+
methods,
|
|
11441
|
+
fields: [],
|
|
11442
|
+
annotations: extractAnnotations(content, classLineNumber)
|
|
11443
|
+
};
|
|
11444
|
+
} catch (error) {
|
|
11445
|
+
logger.warn(`\u{5206}\u{6790}Controller\u{6587}\u{4EF6}\u{5931}\u{8D25}: ${file.path}`, {
|
|
11446
|
+
error
|
|
11447
|
+
});
|
|
11448
|
+
return null;
|
|
11449
|
+
}
|
|
11450
|
+
}
|
|
11451
|
+
async function analyzeJavaService(file) {
|
|
11452
|
+
try {
|
|
11453
|
+
const content = await promises_namespaceObject.readFile(file.path, "utf-8");
|
|
11454
|
+
const comments = extractComments(content);
|
|
11455
|
+
const lines = content.split("\n");
|
|
11456
|
+
let className = "";
|
|
11457
|
+
let classDescription = "";
|
|
11458
|
+
for(let i = 0; i < lines.length; i++){
|
|
11459
|
+
const line = lines[i].trim();
|
|
11460
|
+
if (line.includes("class ") && (line.includes("Service") || line.includes("ServiceImpl"))) {
|
|
11461
|
+
const match = line.match(/class\s+(\w+)/);
|
|
11462
|
+
if (match) {
|
|
11463
|
+
className = match[1];
|
|
11464
|
+
classDescription = comments.get(i) || className;
|
|
11465
|
+
break;
|
|
11466
|
+
}
|
|
11467
|
+
}
|
|
11468
|
+
}
|
|
11469
|
+
if (!className) return null;
|
|
11470
|
+
const methods = [];
|
|
11471
|
+
for(let i = 0; i < lines.length; i++){
|
|
11472
|
+
const line = lines[i].trim();
|
|
11473
|
+
const methodMatch = line.match(/public\s+(\w+(?:<[^>]+>)?)\s+(\w+)\s*\([^)]*\)/);
|
|
11474
|
+
if (methodMatch) {
|
|
11475
|
+
const returnType = methodMatch[1];
|
|
11476
|
+
const methodName = methodMatch[2];
|
|
11477
|
+
const methodDescription = comments.get(i) || methodName;
|
|
11478
|
+
methods.push({
|
|
11479
|
+
name: methodName,
|
|
11480
|
+
description: methodDescription,
|
|
11481
|
+
parameters: [],
|
|
11482
|
+
returnType,
|
|
11483
|
+
returnDescription: `${methodName}\u{8FD4}\u{56DE}\u{7ED3}\u{679C}`
|
|
11484
|
+
});
|
|
11485
|
+
}
|
|
11486
|
+
}
|
|
11487
|
+
return {
|
|
11488
|
+
name: className,
|
|
11489
|
+
description: classDescription,
|
|
11490
|
+
type: "service",
|
|
11491
|
+
methods,
|
|
11492
|
+
fields: [],
|
|
11493
|
+
annotations: []
|
|
11494
|
+
};
|
|
11495
|
+
} catch (error) {
|
|
11496
|
+
logger.warn(`\u{5206}\u{6790}Service\u{6587}\u{4EF6}\u{5931}\u{8D25}: ${file.path}`, {
|
|
11497
|
+
error
|
|
11498
|
+
});
|
|
11499
|
+
return null;
|
|
11500
|
+
}
|
|
11501
|
+
}
|
|
11502
|
+
async function analyzeJavaEntity(file) {
|
|
11503
|
+
try {
|
|
11504
|
+
const content = await promises_namespaceObject.readFile(file.path, "utf-8");
|
|
11505
|
+
const comments = extractComments(content);
|
|
11506
|
+
const lines = content.split("\n");
|
|
11507
|
+
let className = "";
|
|
11508
|
+
let classDescription = "";
|
|
11509
|
+
for(let i = 0; i < lines.length; i++){
|
|
11510
|
+
const line = lines[i].trim();
|
|
11511
|
+
if (line.includes("@Table")) {
|
|
11512
|
+
const tableMatch = line.match(/name\s*=\s*["\']([^"']+)["\']/);
|
|
11513
|
+
if (tableMatch) tableMatch[1];
|
|
11514
|
+
}
|
|
11515
|
+
if (line.includes("class ") && (line.includes("Entity") || content.includes("@Entity"))) {
|
|
11516
|
+
const match = line.match(/class\s+(\w+)/);
|
|
11517
|
+
if (match) {
|
|
11518
|
+
className = match[1];
|
|
11519
|
+
classDescription = comments.get(i) || className;
|
|
11520
|
+
break;
|
|
11521
|
+
}
|
|
11522
|
+
}
|
|
11523
|
+
}
|
|
11524
|
+
if (!className) return null;
|
|
11525
|
+
const fields = [];
|
|
11526
|
+
for(let i = 0; i < lines.length; i++){
|
|
11527
|
+
const line = lines[i].trim();
|
|
11528
|
+
const fieldMatch = line.match(/private\s+(\w+(?:<[^>]+>)?)\s+(\w+);?/);
|
|
11529
|
+
if (fieldMatch) {
|
|
11530
|
+
const fieldType = fieldMatch[1];
|
|
11531
|
+
const fieldName = fieldMatch[2];
|
|
11532
|
+
const fieldDescription = comments.get(i) || fieldName;
|
|
11533
|
+
const annotations = extractAnnotations(content, i);
|
|
11534
|
+
fields.push({
|
|
11535
|
+
name: fieldName,
|
|
11536
|
+
type: fieldType,
|
|
11537
|
+
description: fieldDescription,
|
|
11538
|
+
annotations
|
|
11539
|
+
});
|
|
11540
|
+
}
|
|
11541
|
+
}
|
|
11542
|
+
return {
|
|
11543
|
+
name: className,
|
|
11544
|
+
description: classDescription,
|
|
11545
|
+
type: "entity",
|
|
11546
|
+
methods: [],
|
|
11547
|
+
fields,
|
|
11548
|
+
annotations: []
|
|
11549
|
+
};
|
|
11550
|
+
} catch (error) {
|
|
11551
|
+
logger.warn(`\u{5206}\u{6790}Entity\u{6587}\u{4EF6}\u{5931}\u{8D25}: ${file.path}`, {
|
|
11552
|
+
error
|
|
11553
|
+
});
|
|
11554
|
+
return null;
|
|
11555
|
+
}
|
|
11556
|
+
}
|
|
11557
|
+
async function analyzeTypeScriptFile(file) {
|
|
11558
|
+
try {
|
|
11559
|
+
const content = await promises_namespaceObject.readFile(file.path, "utf-8");
|
|
11560
|
+
const comments = extractComments(content);
|
|
11561
|
+
const lines = content.split("\n");
|
|
11562
|
+
let className = "";
|
|
11563
|
+
let classDescription = "";
|
|
11564
|
+
for(let i = 0; i < lines.length; i++){
|
|
11565
|
+
const line = lines[i].trim();
|
|
11566
|
+
const classMatch = line.match(/(?:export\s+)?(?:class|interface)\s+(\w+)/);
|
|
11567
|
+
if (classMatch) {
|
|
11568
|
+
className = classMatch[1];
|
|
11569
|
+
classDescription = comments.get(i) || className;
|
|
11570
|
+
break;
|
|
11571
|
+
}
|
|
11572
|
+
}
|
|
11573
|
+
if (!className) return null;
|
|
11574
|
+
return {
|
|
11575
|
+
name: className,
|
|
11576
|
+
description: classDescription,
|
|
11577
|
+
type: file.type,
|
|
11578
|
+
methods: [],
|
|
11579
|
+
fields: [],
|
|
11580
|
+
annotations: []
|
|
11581
|
+
};
|
|
11582
|
+
} catch (error) {
|
|
11583
|
+
logger.warn(`\u{5206}\u{6790}TypeScript\u{6587}\u{4EF6}\u{5931}\u{8D25}: ${file.path}`, {
|
|
11584
|
+
error
|
|
11585
|
+
});
|
|
11586
|
+
return null;
|
|
11587
|
+
}
|
|
11588
|
+
}
|
|
11589
|
+
async function analyzeCodeFile(file) {
|
|
11590
|
+
const supportedTypes = [
|
|
11591
|
+
"controller",
|
|
11592
|
+
"service",
|
|
11593
|
+
"entity",
|
|
11594
|
+
"dto"
|
|
11595
|
+
];
|
|
11596
|
+
if (!supportedTypes.includes(file.type)) return null;
|
|
11597
|
+
const ext = external_path_namespaceObject.extname(file.path).toLowerCase();
|
|
11598
|
+
switch(ext){
|
|
11599
|
+
case ".java":
|
|
11600
|
+
if ("controller" === file.type) return analyzeJavaController(file);
|
|
11601
|
+
if ("service" === file.type) return analyzeJavaService(file);
|
|
11602
|
+
if ("entity" === file.type) return analyzeJavaEntity(file);
|
|
11603
|
+
break;
|
|
11604
|
+
case ".ts":
|
|
11605
|
+
case ".js":
|
|
11606
|
+
return analyzeTypeScriptFile(file);
|
|
11607
|
+
default:
|
|
11608
|
+
break;
|
|
11609
|
+
}
|
|
11610
|
+
return null;
|
|
11611
|
+
}
|
|
11612
|
+
function classInfoToServiceInterface(classInfo, index) {
|
|
11613
|
+
const interfaceDetailList = classInfo.methods.map((method, methodIndex)=>({
|
|
11614
|
+
id: String(methodIndex + 1),
|
|
11615
|
+
functionDescription: method.description,
|
|
11616
|
+
serviceName: classInfo.name,
|
|
11617
|
+
methodName: method.name
|
|
11618
|
+
}));
|
|
11619
|
+
return {
|
|
11620
|
+
id: String(index + 1),
|
|
11621
|
+
serviceType: "controller" === classInfo.type ? "REST" : "Service",
|
|
11622
|
+
serviceEnglishName: classInfo.name,
|
|
11623
|
+
serviceChineseName: classInfo.description,
|
|
11624
|
+
serviceDescription: classInfo.description,
|
|
11625
|
+
interfaceDetailList
|
|
11626
|
+
};
|
|
11627
|
+
}
|
|
11628
|
+
function classInfoToDesignDetail(classInfo) {
|
|
11629
|
+
const interfaceDesignDetailList = classInfo.methods.map((method)=>({
|
|
11630
|
+
functionName: method.name,
|
|
11631
|
+
interfaceDesc: method.description,
|
|
11632
|
+
className: classInfo.name,
|
|
11633
|
+
methodName: method.name,
|
|
11634
|
+
parameterList: method.parameters,
|
|
11635
|
+
returnResultList: [
|
|
11636
|
+
{
|
|
11637
|
+
id: "1",
|
|
11638
|
+
propertyType: method.returnType,
|
|
11639
|
+
propertyName: "result",
|
|
11640
|
+
propertyDesc: method.returnDescription
|
|
11641
|
+
}
|
|
11642
|
+
],
|
|
11643
|
+
implementLogic: `${method.description}\u{7684}\u{5177}\u{4F53}\u{5B9E}\u{73B0}\u{903B}\u{8F91}`
|
|
11644
|
+
}));
|
|
11645
|
+
return {
|
|
11646
|
+
serviceName: classInfo.name,
|
|
11647
|
+
serviceDesc: classInfo.description,
|
|
11648
|
+
interfaceDesignDetailList
|
|
11649
|
+
};
|
|
11650
|
+
}
|
|
11651
|
+
function classInfoToTableInfo(classInfo, index) {
|
|
11652
|
+
const tableDetailList = classInfo.fields.map((field, fieldIndex)=>({
|
|
11653
|
+
id: String(fieldIndex + 1),
|
|
11654
|
+
fieldName: field.name,
|
|
11655
|
+
fieldType: field.type,
|
|
11656
|
+
fieldDescription: field.description,
|
|
11657
|
+
fieldLength: getFieldLength(field.type)
|
|
11658
|
+
}));
|
|
11659
|
+
return {
|
|
11660
|
+
id: String(index + 1),
|
|
11661
|
+
tableName: camelToSnakeCase(classInfo.name),
|
|
11662
|
+
entityName: classInfo.name,
|
|
11663
|
+
tableDescription: classInfo.description,
|
|
11664
|
+
tableDetailList
|
|
11665
|
+
};
|
|
11666
|
+
}
|
|
11667
|
+
function getFieldLength(fieldType) {
|
|
11668
|
+
const type = fieldType.toLowerCase();
|
|
11669
|
+
if (type.includes("string") || type.includes("varchar")) return "255";
|
|
11670
|
+
if (type.includes("text")) return "65535";
|
|
11671
|
+
if (type.includes("int") || type.includes("integer")) return "11";
|
|
11672
|
+
if (type.includes("long")) return "20";
|
|
11673
|
+
if (type.includes("decimal") || type.includes("double")) return "10,2";
|
|
11674
|
+
else if (type.includes("date") || type.includes("time")) return "-";
|
|
11675
|
+
else return "255";
|
|
11676
|
+
}
|
|
11677
|
+
function camelToSnakeCase(str) {
|
|
11678
|
+
return str.replace(/([A-Z])/g, "_$1").toLowerCase().replace(/^_/, "");
|
|
11679
|
+
}
|
|
11680
|
+
async function analyzeProjectCode(analysis, options = {}) {
|
|
11681
|
+
logger.info(`\u{5F00}\u{59CB}\u{5206}\u{6790}\u{9879}\u{76EE}\u{4EE3}\u{7801}: ${analysis.projectName}`);
|
|
11682
|
+
let filesToAnalyze = analysis.allFiles;
|
|
11683
|
+
if (options.includeModules && options.includeModules.length > 0) filesToAnalyze = filesToAnalyze.filter((f)=>f.module && options.includeModules.includes(f.module));
|
|
11684
|
+
if (options.excludeModules && options.excludeModules.length > 0) filesToAnalyze = filesToAnalyze.filter((f)=>!f.module || !options.excludeModules.includes(f.module));
|
|
11685
|
+
if (options.includeFileTypes && options.includeFileTypes.length > 0) filesToAnalyze = filesToAnalyze.filter((f)=>options.includeFileTypes.includes(f.type));
|
|
11686
|
+
logger.info(`\u{9700}\u{8981}\u{5206}\u{6790}\u{7684}\u{6587}\u{4EF6}\u{6570}\u{91CF}: ${filesToAnalyze.length}`);
|
|
11687
|
+
const classInfoList = [];
|
|
11688
|
+
for (const file of filesToAnalyze)try {
|
|
11689
|
+
const classInfo = await analyzeCodeFile(file);
|
|
11690
|
+
if (classInfo) classInfoList.push(classInfo);
|
|
11691
|
+
} catch (error) {
|
|
11692
|
+
logger.warn(`\u{5206}\u{6790}\u{6587}\u{4EF6}\u{5931}\u{8D25}: ${file.path}`, {
|
|
11693
|
+
error
|
|
11694
|
+
});
|
|
11695
|
+
}
|
|
11696
|
+
logger.info(`\u{6210}\u{529F}\u{5206}\u{6790}\u{7684}\u{7C7B}\u{6570}\u{91CF}: ${classInfoList.length}`);
|
|
11697
|
+
const serviceInterfaceList = [];
|
|
11698
|
+
const designDetailList = [];
|
|
11699
|
+
const tableInfoList = [];
|
|
11700
|
+
let serviceIndex = 0;
|
|
11701
|
+
let tableIndex = 0;
|
|
11702
|
+
for (const classInfo of classInfoList)if ("controller" === classInfo.type || "service" === classInfo.type) {
|
|
11703
|
+
serviceInterfaceList.push(classInfoToServiceInterface(classInfo, serviceIndex++));
|
|
11704
|
+
designDetailList.push(classInfoToDesignDetail(classInfo));
|
|
11705
|
+
} else if ("entity" === classInfo.type) tableInfoList.push(classInfoToTableInfo(classInfo, tableIndex++));
|
|
11706
|
+
logger.info(`\u{4EE3}\u{7801}\u{5206}\u{6790}\u{5B8C}\u{6210}`, {
|
|
11707
|
+
serviceCount: serviceInterfaceList.length,
|
|
11708
|
+
designCount: designDetailList.length,
|
|
11709
|
+
tableCount: tableInfoList.length
|
|
11710
|
+
});
|
|
11711
|
+
return {
|
|
11712
|
+
serviceInterfaceList,
|
|
11713
|
+
designDetailList,
|
|
11714
|
+
tableInfoList
|
|
11715
|
+
};
|
|
11716
|
+
}
|
|
11717
|
+
class TechSpecStorage {
|
|
11718
|
+
dataDir;
|
|
11719
|
+
projectsFile;
|
|
11720
|
+
chaptersFile;
|
|
11721
|
+
modulesFile;
|
|
11722
|
+
filesFile;
|
|
11723
|
+
constructor(){
|
|
11724
|
+
try {
|
|
11725
|
+
const storageDir = getStorageDir();
|
|
11726
|
+
this.dataDir = external_path_namespaceObject.join(storageDir, "tech-spec");
|
|
11727
|
+
this.projectsFile = external_path_namespaceObject.join(this.dataDir, "projects.json");
|
|
11728
|
+
this.chaptersFile = external_path_namespaceObject.join(this.dataDir, "chapters.json");
|
|
11729
|
+
this.modulesFile = external_path_namespaceObject.join(this.dataDir, "modules.json");
|
|
11730
|
+
this.filesFile = external_path_namespaceObject.join(this.dataDir, "files.json");
|
|
11731
|
+
this.ensureDataDir();
|
|
11732
|
+
} catch (error) {
|
|
11733
|
+
console.warn("TechSpecStorage\u521D\u59CB\u5316\u5931\u8D25\uFF0C\u4F7F\u7528\u9ED8\u8BA4\u8DEF\u5F84:", error);
|
|
11734
|
+
const defaultDir = external_path_namespaceObject.join(process.cwd(), ".aico");
|
|
11735
|
+
this.dataDir = external_path_namespaceObject.join(defaultDir, "tech-spec");
|
|
11736
|
+
this.projectsFile = external_path_namespaceObject.join(this.dataDir, "projects.json");
|
|
11737
|
+
this.chaptersFile = external_path_namespaceObject.join(this.dataDir, "chapters.json");
|
|
11738
|
+
this.modulesFile = external_path_namespaceObject.join(this.dataDir, "modules.json");
|
|
11739
|
+
this.filesFile = external_path_namespaceObject.join(this.dataDir, "files.json");
|
|
11740
|
+
this.ensureDataDir();
|
|
11741
|
+
}
|
|
11742
|
+
}
|
|
11743
|
+
ensureDataDir() {
|
|
11744
|
+
if (!external_fs_namespaceObject.existsSync(this.dataDir)) external_fs_namespaceObject.mkdirSync(this.dataDir, {
|
|
11745
|
+
recursive: true
|
|
11746
|
+
});
|
|
11747
|
+
if (!external_fs_namespaceObject.existsSync(this.projectsFile)) external_fs_namespaceObject.writeFileSync(this.projectsFile, "[]", "utf8");
|
|
11748
|
+
if (!external_fs_namespaceObject.existsSync(this.chaptersFile)) external_fs_namespaceObject.writeFileSync(this.chaptersFile, "[]", "utf8");
|
|
11749
|
+
if (!external_fs_namespaceObject.existsSync(this.modulesFile)) external_fs_namespaceObject.writeFileSync(this.modulesFile, "[]", "utf8");
|
|
11750
|
+
if (!external_fs_namespaceObject.existsSync(this.filesFile)) external_fs_namespaceObject.writeFileSync(this.filesFile, "[]", "utf8");
|
|
11751
|
+
}
|
|
11752
|
+
getNextId(items) {
|
|
11753
|
+
return items.length > 0 ? Math.max(...items.map((i)=>i.id)) + 1 : 1;
|
|
11754
|
+
}
|
|
11755
|
+
readProjects() {
|
|
11756
|
+
try {
|
|
11757
|
+
const data = external_fs_namespaceObject.readFileSync(this.projectsFile, "utf8");
|
|
11758
|
+
return JSON.parse(data).map((p)=>({
|
|
11759
|
+
...p,
|
|
11760
|
+
createdAt: new Date(p.createdAt),
|
|
11761
|
+
updatedAt: new Date(p.updatedAt),
|
|
11762
|
+
completedAt: p.completedAt ? new Date(p.completedAt) : void 0
|
|
11763
|
+
}));
|
|
11764
|
+
} catch (error) {
|
|
11765
|
+
logger.error("Error reading tech spec projects file", error);
|
|
11766
|
+
return [];
|
|
11767
|
+
}
|
|
11768
|
+
}
|
|
11769
|
+
writeProjects(projects) {
|
|
11770
|
+
external_fs_namespaceObject.writeFileSync(this.projectsFile, JSON.stringify(projects, null, 2), "utf8");
|
|
11771
|
+
}
|
|
11772
|
+
async createTechSpecProject(data) {
|
|
11773
|
+
const projects = this.readProjects();
|
|
11774
|
+
const newProject = {
|
|
11775
|
+
id: this.getNextId(projects),
|
|
11776
|
+
uuid: data.uuid,
|
|
11777
|
+
projectName: data.projectName,
|
|
11778
|
+
moduleName: data.moduleName,
|
|
11779
|
+
projectPath: data.projectPath,
|
|
11780
|
+
status: "analyzing",
|
|
11781
|
+
totalModules: data.totalModules,
|
|
11782
|
+
processedModules: 0,
|
|
11783
|
+
totalFiles: data.totalFiles,
|
|
11784
|
+
processedFiles: 0,
|
|
11785
|
+
createdAt: new Date(),
|
|
11786
|
+
updatedAt: new Date()
|
|
11787
|
+
};
|
|
11788
|
+
projects.push(newProject);
|
|
11789
|
+
this.writeProjects(projects);
|
|
11790
|
+
return newProject;
|
|
11791
|
+
}
|
|
11792
|
+
async getTechSpecProject(uuid) {
|
|
11793
|
+
const projects = this.readProjects();
|
|
11794
|
+
return projects.find((p)=>p.uuid === uuid) || null;
|
|
11795
|
+
}
|
|
11796
|
+
async getAllTechSpecProjects() {
|
|
11797
|
+
return this.readProjects();
|
|
11798
|
+
}
|
|
11799
|
+
async updateTechSpecProject(uuid, data) {
|
|
11800
|
+
const projects = this.readProjects();
|
|
11801
|
+
const projectIndex = projects.findIndex((p)=>p.uuid === uuid);
|
|
11802
|
+
if (projectIndex >= 0) {
|
|
11803
|
+
projects[projectIndex] = {
|
|
11804
|
+
...projects[projectIndex],
|
|
11805
|
+
...data,
|
|
11806
|
+
updatedAt: new Date()
|
|
11807
|
+
};
|
|
11808
|
+
this.writeProjects(projects);
|
|
11809
|
+
}
|
|
11810
|
+
}
|
|
11811
|
+
readChapters() {
|
|
11812
|
+
try {
|
|
11813
|
+
const data = external_fs_namespaceObject.readFileSync(this.chaptersFile, "utf8");
|
|
11814
|
+
return JSON.parse(data).map((c)=>({
|
|
11815
|
+
...c,
|
|
11816
|
+
createdAt: new Date(c.createdAt),
|
|
11817
|
+
updatedAt: new Date(c.updatedAt)
|
|
11818
|
+
}));
|
|
11819
|
+
} catch (error) {
|
|
11820
|
+
logger.error("Error reading tech spec chapters file", error);
|
|
11821
|
+
return [];
|
|
11822
|
+
}
|
|
11823
|
+
}
|
|
11824
|
+
writeChapters(chapters) {
|
|
11825
|
+
external_fs_namespaceObject.writeFileSync(this.chaptersFile, JSON.stringify(chapters, null, 2), "utf8");
|
|
11826
|
+
}
|
|
11827
|
+
async createTechSpecChapter(data) {
|
|
11828
|
+
const chapters = this.readChapters();
|
|
11829
|
+
const newChapter = {
|
|
11830
|
+
id: this.getNextId(chapters),
|
|
11831
|
+
uuid: data.uuid,
|
|
11832
|
+
projectUuid: data.projectUuid,
|
|
11833
|
+
chapterType: data.chapterType,
|
|
11834
|
+
chapterTitle: data.chapterTitle,
|
|
11835
|
+
chapterOrder: data.chapterOrder,
|
|
11836
|
+
content: data.content,
|
|
11837
|
+
moduleSource: data.moduleSource,
|
|
11838
|
+
fileCount: data.fileCount,
|
|
11839
|
+
status: "completed",
|
|
11840
|
+
createdAt: new Date(),
|
|
11841
|
+
updatedAt: new Date()
|
|
11842
|
+
};
|
|
11843
|
+
chapters.push(newChapter);
|
|
11844
|
+
this.writeChapters(chapters);
|
|
11845
|
+
return newChapter;
|
|
11846
|
+
}
|
|
11847
|
+
async getTechSpecChapters(projectUuid) {
|
|
11848
|
+
const chapters = this.readChapters();
|
|
11849
|
+
return chapters.filter((c)=>c.projectUuid === projectUuid).sort((a, b)=>a.chapterOrder - b.chapterOrder);
|
|
11850
|
+
}
|
|
11851
|
+
async getTechSpecChaptersByType(projectUuid, chapterType) {
|
|
11852
|
+
const chapters = this.readChapters();
|
|
11853
|
+
return chapters.filter((c)=>c.projectUuid === projectUuid && c.chapterType === chapterType).sort((a, b)=>a.chapterOrder - b.chapterOrder);
|
|
11854
|
+
}
|
|
11855
|
+
async updateTechSpecChapter(uuid, data) {
|
|
11856
|
+
const chapters = this.readChapters();
|
|
11857
|
+
const chapterIndex = chapters.findIndex((c)=>c.uuid === uuid);
|
|
11858
|
+
if (chapterIndex >= 0) {
|
|
11859
|
+
chapters[chapterIndex] = {
|
|
11860
|
+
...chapters[chapterIndex],
|
|
11861
|
+
...data,
|
|
11862
|
+
updatedAt: new Date()
|
|
11863
|
+
};
|
|
11864
|
+
this.writeChapters(chapters);
|
|
11865
|
+
}
|
|
11866
|
+
}
|
|
11867
|
+
readModules() {
|
|
11868
|
+
try {
|
|
11869
|
+
const data = external_fs_namespaceObject.readFileSync(this.modulesFile, "utf8");
|
|
11870
|
+
return JSON.parse(data).map((m)=>({
|
|
11871
|
+
...m,
|
|
11872
|
+
createdAt: new Date(m.createdAt),
|
|
11873
|
+
updatedAt: new Date(m.updatedAt),
|
|
11874
|
+
startedAt: m.startedAt ? new Date(m.startedAt) : void 0,
|
|
11875
|
+
completedAt: m.completedAt ? new Date(m.completedAt) : void 0
|
|
11876
|
+
}));
|
|
11877
|
+
} catch (error) {
|
|
11878
|
+
logger.error("Error reading tech spec modules file", error);
|
|
11879
|
+
return [];
|
|
11880
|
+
}
|
|
11881
|
+
}
|
|
11882
|
+
writeModules(modules) {
|
|
11883
|
+
external_fs_namespaceObject.writeFileSync(this.modulesFile, JSON.stringify(modules, null, 2), "utf8");
|
|
11884
|
+
}
|
|
11885
|
+
async createModuleProcessStatus(data) {
|
|
11886
|
+
const modules = this.readModules();
|
|
11887
|
+
const newModule = {
|
|
11888
|
+
id: this.getNextId(modules),
|
|
11889
|
+
uuid: data.uuid,
|
|
11890
|
+
projectUuid: data.projectUuid,
|
|
11891
|
+
moduleName: data.moduleName,
|
|
11892
|
+
moduleType: data.moduleType,
|
|
11893
|
+
totalFiles: data.totalFiles,
|
|
11894
|
+
processedFiles: 0,
|
|
11895
|
+
status: "pending",
|
|
11896
|
+
createdAt: new Date(),
|
|
11897
|
+
updatedAt: new Date()
|
|
11898
|
+
};
|
|
11899
|
+
modules.push(newModule);
|
|
11900
|
+
this.writeModules(modules);
|
|
11901
|
+
return newModule;
|
|
11902
|
+
}
|
|
11903
|
+
async getModuleProcessStatuses(projectUuid) {
|
|
11904
|
+
const modules = this.readModules();
|
|
11905
|
+
return modules.filter((m)=>m.projectUuid === projectUuid);
|
|
11906
|
+
}
|
|
11907
|
+
async updateModuleProcessStatus(uuid, data) {
|
|
11908
|
+
const modules = this.readModules();
|
|
11909
|
+
const moduleIndex = modules.findIndex((m)=>m.uuid === uuid);
|
|
11910
|
+
if (moduleIndex >= 0) {
|
|
11911
|
+
modules[moduleIndex] = {
|
|
11912
|
+
...modules[moduleIndex],
|
|
11913
|
+
...data,
|
|
11914
|
+
updatedAt: new Date()
|
|
11915
|
+
};
|
|
11916
|
+
this.writeModules(modules);
|
|
11917
|
+
}
|
|
11918
|
+
}
|
|
11919
|
+
readFiles() {
|
|
11920
|
+
try {
|
|
11921
|
+
const data = external_fs_namespaceObject.readFileSync(this.filesFile, "utf8");
|
|
11922
|
+
return JSON.parse(data).map((f)=>({
|
|
11923
|
+
...f,
|
|
11924
|
+
createdAt: new Date(f.createdAt),
|
|
11925
|
+
updatedAt: new Date(f.updatedAt)
|
|
11926
|
+
}));
|
|
11927
|
+
} catch (error) {
|
|
11928
|
+
logger.error("Error reading tech spec files file", error);
|
|
11929
|
+
return [];
|
|
11930
|
+
}
|
|
11931
|
+
}
|
|
11932
|
+
writeFiles(files) {
|
|
11933
|
+
external_fs_namespaceObject.writeFileSync(this.filesFile, JSON.stringify(files, null, 2), "utf8");
|
|
11934
|
+
}
|
|
11935
|
+
async createFileProcessRecord(data) {
|
|
11936
|
+
const files = this.readFiles();
|
|
11937
|
+
const newFile = {
|
|
11938
|
+
id: this.getNextId(files),
|
|
11939
|
+
uuid: data.uuid,
|
|
11940
|
+
projectUuid: data.projectUuid,
|
|
11941
|
+
moduleUuid: data.moduleUuid,
|
|
11942
|
+
filePath: data.filePath,
|
|
11943
|
+
fileName: data.fileName,
|
|
11944
|
+
fileType: data.fileType,
|
|
11945
|
+
extractedData: data.extractedData,
|
|
11946
|
+
status: "completed",
|
|
11947
|
+
processingTime: data.processingTime,
|
|
11948
|
+
createdAt: new Date(),
|
|
11949
|
+
updatedAt: new Date()
|
|
11950
|
+
};
|
|
11951
|
+
files.push(newFile);
|
|
11952
|
+
this.writeFiles(files);
|
|
11953
|
+
return newFile;
|
|
11954
|
+
}
|
|
11955
|
+
async getFileProcessRecords(projectUuid) {
|
|
11956
|
+
const files = this.readFiles();
|
|
11957
|
+
return files.filter((f)=>f.projectUuid === projectUuid);
|
|
11958
|
+
}
|
|
11959
|
+
async getFileProcessRecordsByModule(moduleUuid) {
|
|
11960
|
+
const files = this.readFiles();
|
|
11961
|
+
return files.filter((f)=>f.moduleUuid === moduleUuid);
|
|
11962
|
+
}
|
|
11963
|
+
async mergeChaptersByType(projectUuid, chapterType) {
|
|
11964
|
+
const chapters = await this.getTechSpecChaptersByType(projectUuid, chapterType);
|
|
11965
|
+
if (0 === chapters.length) return null;
|
|
11966
|
+
switch(chapterType){
|
|
11967
|
+
case "service_interface_list":
|
|
11968
|
+
return this.mergeServiceInterfaceChapters(chapters);
|
|
11969
|
+
case "interface_design":
|
|
11970
|
+
return this.mergeInterfaceDesignChapters(chapters);
|
|
11971
|
+
case "database_design":
|
|
11972
|
+
return this.mergeDatabaseDesignChapters(chapters);
|
|
11973
|
+
case "tech_solution":
|
|
11974
|
+
return this.mergeTechSolutionChapters(chapters);
|
|
11975
|
+
case "business_exception":
|
|
11976
|
+
return this.mergeBusinessExceptionChapters(chapters);
|
|
11977
|
+
case "appendix":
|
|
11978
|
+
return this.mergeAppendixChapters(chapters);
|
|
11979
|
+
default:
|
|
11980
|
+
return {
|
|
11981
|
+
content: chapters.map((c)=>JSON.parse(c.content)).join("\n\n"),
|
|
11982
|
+
totalModules: chapters.length,
|
|
11983
|
+
totalFiles: chapters.reduce((sum, c)=>sum + c.fileCount, 0)
|
|
11984
|
+
};
|
|
11985
|
+
}
|
|
11986
|
+
}
|
|
11987
|
+
mergeServiceInterfaceChapters(chapters) {
|
|
11988
|
+
const allInterfaces = [];
|
|
11989
|
+
let idCounter = 1;
|
|
11990
|
+
for (const chapter of chapters)try {
|
|
11991
|
+
const chapterData = JSON.parse(chapter.content);
|
|
11992
|
+
if (Array.isArray(chapterData)) {
|
|
11993
|
+
const interfaces = chapterData.map((item)=>({
|
|
11994
|
+
...item,
|
|
11995
|
+
id: String(idCounter++),
|
|
11996
|
+
moduleSource: chapter.moduleSource
|
|
11997
|
+
}));
|
|
11998
|
+
allInterfaces.push(...interfaces);
|
|
11999
|
+
}
|
|
12000
|
+
} catch (error) {
|
|
12001
|
+
logger.warn(`\u{89E3}\u{6790}\u{7AE0}\u{8282}\u{5185}\u{5BB9}\u{5931}\u{8D25}: ${chapter.uuid}`, error);
|
|
12002
|
+
}
|
|
12003
|
+
return allInterfaces;
|
|
12004
|
+
}
|
|
12005
|
+
mergeInterfaceDesignChapters(chapters) {
|
|
12006
|
+
const allDesigns = [];
|
|
12007
|
+
for (const chapter of chapters)try {
|
|
12008
|
+
const chapterData = JSON.parse(chapter.content);
|
|
12009
|
+
if (Array.isArray(chapterData)) {
|
|
12010
|
+
const designs = chapterData.map((item)=>({
|
|
12011
|
+
...item,
|
|
12012
|
+
moduleSource: chapter.moduleSource
|
|
12013
|
+
}));
|
|
12014
|
+
allDesigns.push(...designs);
|
|
12015
|
+
}
|
|
12016
|
+
} catch (error) {
|
|
12017
|
+
logger.warn(`\u{89E3}\u{6790}\u{7AE0}\u{8282}\u{5185}\u{5BB9}\u{5931}\u{8D25}: ${chapter.uuid}`, error);
|
|
12018
|
+
}
|
|
12019
|
+
return allDesigns;
|
|
12020
|
+
}
|
|
12021
|
+
mergeDatabaseDesignChapters(chapters) {
|
|
12022
|
+
const allTables = [];
|
|
12023
|
+
let idCounter = 1;
|
|
12024
|
+
for (const chapter of chapters)try {
|
|
12025
|
+
const chapterData = JSON.parse(chapter.content);
|
|
12026
|
+
if (Array.isArray(chapterData)) {
|
|
12027
|
+
const tables = chapterData.map((item)=>({
|
|
12028
|
+
...item,
|
|
12029
|
+
id: String(idCounter++),
|
|
12030
|
+
moduleSource: chapter.moduleSource
|
|
12031
|
+
}));
|
|
12032
|
+
allTables.push(...tables);
|
|
12033
|
+
}
|
|
12034
|
+
} catch (error) {
|
|
12035
|
+
logger.warn(`\u{89E3}\u{6790}\u{7AE0}\u{8282}\u{5185}\u{5BB9}\u{5931}\u{8D25}: ${chapter.uuid}`, error);
|
|
12036
|
+
}
|
|
12037
|
+
return allTables;
|
|
12038
|
+
}
|
|
12039
|
+
mergeTechSolutionChapters(chapters) {
|
|
12040
|
+
const contents = [];
|
|
12041
|
+
for (const chapter of chapters)try {
|
|
12042
|
+
const chapterData = JSON.parse(chapter.content);
|
|
12043
|
+
if (chapterData.content) contents.push(`## ${chapter.moduleSource || "\u6A21\u5757"}\n${chapterData.content}`);
|
|
12044
|
+
} catch (error) {
|
|
12045
|
+
logger.warn(`\u{89E3}\u{6790}\u{7AE0}\u{8282}\u{5185}\u{5BB9}\u{5931}\u{8D25}: ${chapter.uuid}`, error);
|
|
12046
|
+
}
|
|
12047
|
+
return {
|
|
12048
|
+
content: contents.join("\n\n")
|
|
12049
|
+
};
|
|
12050
|
+
}
|
|
12051
|
+
mergeBusinessExceptionChapters(chapters) {
|
|
12052
|
+
const contents = [];
|
|
12053
|
+
for (const chapter of chapters)try {
|
|
12054
|
+
const chapterData = JSON.parse(chapter.content);
|
|
12055
|
+
if (chapterData.content) contents.push(`## ${chapter.moduleSource || "\u6A21\u5757"}\n${chapterData.content}`);
|
|
12056
|
+
} catch (error) {
|
|
12057
|
+
logger.warn(`\u{89E3}\u{6790}\u{7AE0}\u{8282}\u{5185}\u{5BB9}\u{5931}\u{8D25}: ${chapter.uuid}`, error);
|
|
12058
|
+
}
|
|
12059
|
+
return {
|
|
12060
|
+
content: contents.join("\n\n")
|
|
12061
|
+
};
|
|
12062
|
+
}
|
|
12063
|
+
mergeAppendixChapters(chapters) {
|
|
12064
|
+
const allExceptionCodes = [];
|
|
12065
|
+
const allCodeValues = [];
|
|
12066
|
+
let idCounter = 1;
|
|
12067
|
+
for (const chapter of chapters)try {
|
|
12068
|
+
const chapterData = JSON.parse(chapter.content);
|
|
12069
|
+
if (chapterData.exceptionCodeList && Array.isArray(chapterData.exceptionCodeList)) {
|
|
12070
|
+
const codes = chapterData.exceptionCodeList.map((item)=>({
|
|
12071
|
+
...item,
|
|
12072
|
+
id: String(idCounter++),
|
|
12073
|
+
moduleSource: chapter.moduleSource
|
|
12074
|
+
}));
|
|
12075
|
+
allExceptionCodes.push(...codes);
|
|
12076
|
+
}
|
|
12077
|
+
if (chapterData.codeValueList && Array.isArray(chapterData.codeValueList)) {
|
|
12078
|
+
const values = chapterData.codeValueList.map((item)=>({
|
|
12079
|
+
...item,
|
|
12080
|
+
id: String(idCounter++),
|
|
12081
|
+
moduleSource: chapter.moduleSource
|
|
12082
|
+
}));
|
|
12083
|
+
allCodeValues.push(...values);
|
|
12084
|
+
}
|
|
12085
|
+
} catch (error) {
|
|
12086
|
+
logger.warn(`\u{89E3}\u{6790}\u{7AE0}\u{8282}\u{5185}\u{5BB9}\u{5931}\u{8D25}: ${chapter.uuid}`, error);
|
|
12087
|
+
}
|
|
12088
|
+
return {
|
|
12089
|
+
exceptionCodeList: allExceptionCodes,
|
|
12090
|
+
codeValueList: allCodeValues
|
|
12091
|
+
};
|
|
12092
|
+
}
|
|
12093
|
+
async cleanupProject(projectUuid) {
|
|
12094
|
+
const chapters = this.readChapters();
|
|
12095
|
+
const filteredChapters = chapters.filter((c)=>c.projectUuid !== projectUuid);
|
|
12096
|
+
this.writeChapters(filteredChapters);
|
|
12097
|
+
const modules = this.readModules();
|
|
12098
|
+
const filteredModules = modules.filter((m)=>m.projectUuid !== projectUuid);
|
|
12099
|
+
this.writeModules(filteredModules);
|
|
12100
|
+
const files = this.readFiles();
|
|
12101
|
+
const filteredFiles = files.filter((f)=>f.projectUuid !== projectUuid);
|
|
12102
|
+
this.writeFiles(filteredFiles);
|
|
12103
|
+
logger.info(`\u{5DF2}\u{6E05}\u{7406}\u{9879}\u{76EE} ${projectUuid} \u{7684}\u{6240}\u{6709}\u{76F8}\u{5173}\u{6570}\u{636E}`);
|
|
12104
|
+
}
|
|
12105
|
+
async getProjectStatistics(projectUuid) {
|
|
12106
|
+
const chapters = await this.getTechSpecChapters(projectUuid);
|
|
12107
|
+
const modules = await this.getModuleProcessStatuses(projectUuid);
|
|
12108
|
+
const files = await this.getFileProcessRecords(projectUuid);
|
|
12109
|
+
const chaptersByType = {
|
|
12110
|
+
project_overview: 0,
|
|
12111
|
+
service_interface_list: 0,
|
|
12112
|
+
interface_design: 0,
|
|
12113
|
+
database_design: 0,
|
|
12114
|
+
tech_solution: 0,
|
|
12115
|
+
business_exception: 0,
|
|
12116
|
+
appendix: 0
|
|
12117
|
+
};
|
|
12118
|
+
chapters.forEach((chapter)=>{
|
|
12119
|
+
chaptersByType[chapter.chapterType]++;
|
|
12120
|
+
});
|
|
12121
|
+
return {
|
|
12122
|
+
totalChapters: chapters.length,
|
|
12123
|
+
completedChapters: chapters.filter((c)=>"completed" === c.status).length,
|
|
12124
|
+
totalModules: modules.length,
|
|
12125
|
+
completedModules: modules.filter((m)=>"completed" === m.status).length,
|
|
12126
|
+
totalFiles: files.length,
|
|
12127
|
+
completedFiles: files.filter((f)=>"completed" === f.status).length,
|
|
12128
|
+
chaptersByType
|
|
12129
|
+
};
|
|
12130
|
+
}
|
|
12131
|
+
}
|
|
12132
|
+
const techSpecStorage = new TechSpecStorage();
|
|
12133
|
+
const techSpecDbOperations = {
|
|
12134
|
+
createTechSpecProject: techSpecStorage.createTechSpecProject.bind(techSpecStorage),
|
|
12135
|
+
getTechSpecProject: techSpecStorage.getTechSpecProject.bind(techSpecStorage),
|
|
12136
|
+
getAllTechSpecProjects: techSpecStorage.getAllTechSpecProjects.bind(techSpecStorage),
|
|
12137
|
+
updateTechSpecProject: techSpecStorage.updateTechSpecProject.bind(techSpecStorage),
|
|
12138
|
+
createTechSpecChapter: techSpecStorage.createTechSpecChapter.bind(techSpecStorage),
|
|
12139
|
+
getTechSpecChapters: techSpecStorage.getTechSpecChapters.bind(techSpecStorage),
|
|
12140
|
+
getTechSpecChaptersByType: techSpecStorage.getTechSpecChaptersByType.bind(techSpecStorage),
|
|
12141
|
+
updateTechSpecChapter: techSpecStorage.updateTechSpecChapter.bind(techSpecStorage),
|
|
12142
|
+
createModuleProcessStatus: techSpecStorage.createModuleProcessStatus.bind(techSpecStorage),
|
|
12143
|
+
getModuleProcessStatuses: techSpecStorage.getModuleProcessStatuses.bind(techSpecStorage),
|
|
12144
|
+
updateModuleProcessStatus: techSpecStorage.updateModuleProcessStatus.bind(techSpecStorage),
|
|
12145
|
+
createFileProcessRecord: techSpecStorage.createFileProcessRecord.bind(techSpecStorage),
|
|
12146
|
+
getFileProcessRecords: techSpecStorage.getFileProcessRecords.bind(techSpecStorage),
|
|
12147
|
+
getFileProcessRecordsByModule: techSpecStorage.getFileProcessRecordsByModule.bind(techSpecStorage),
|
|
12148
|
+
mergeChaptersByType: techSpecStorage.mergeChaptersByType.bind(techSpecStorage),
|
|
12149
|
+
cleanupProject: techSpecStorage.cleanupProject.bind(techSpecStorage),
|
|
12150
|
+
getProjectStatistics: techSpecStorage.getProjectStatistics.bind(techSpecStorage)
|
|
12151
|
+
};
|
|
12152
|
+
const DEFAULT_CONFIG = {
|
|
12153
|
+
maxFilesPerBatch: 50,
|
|
12154
|
+
maxModulesPerChapter: 10,
|
|
12155
|
+
enableParallelProcessing: true,
|
|
12156
|
+
skipEmptyModules: true
|
|
12157
|
+
};
|
|
12158
|
+
class ChapterProcessor {
|
|
12159
|
+
config;
|
|
12160
|
+
constructor(config = {}){
|
|
12161
|
+
this.config = {
|
|
12162
|
+
...DEFAULT_CONFIG,
|
|
12163
|
+
...config
|
|
12164
|
+
};
|
|
12165
|
+
}
|
|
12166
|
+
async processFullProject(projectAnalysis, options = {}) {
|
|
12167
|
+
const startTime = Date.now();
|
|
12168
|
+
const projectUuid = (0, external_crypto_namespaceObject.randomUUID)();
|
|
12169
|
+
try {
|
|
12170
|
+
logger.info(`\u{5F00}\u{59CB}\u{5206}\u{7AE0}\u{8282}\u{5904}\u{7406}\u{9879}\u{76EE}: ${projectAnalysis.projectName}`, {
|
|
12171
|
+
projectUuid
|
|
12172
|
+
});
|
|
12173
|
+
const techSpecProject = await this.createProjectRecord(projectUuid, projectAnalysis, options);
|
|
12174
|
+
const filteredModules = this.filterModules(projectAnalysis.modules, options);
|
|
12175
|
+
if (0 === filteredModules.length) throw new Error("\u6CA1\u6709\u627E\u5230\u7B26\u5408\u6761\u4EF6\u7684\u6A21\u5757");
|
|
12176
|
+
const batches = this.createModuleBatches(filteredModules);
|
|
12177
|
+
logger.info(`\u{9879}\u{76EE}\u{5206}\u{4E3A} ${batches.length} \u{4E2A}\u{6279}\u{6B21}\u{5904}\u{7406}`, {
|
|
12178
|
+
projectUuid,
|
|
12179
|
+
totalModules: filteredModules.length,
|
|
12180
|
+
totalBatches: batches.length
|
|
12181
|
+
});
|
|
12182
|
+
let totalProcessedFiles = 0;
|
|
12183
|
+
let totalServiceInterfaces = 0;
|
|
12184
|
+
let totalDesignDetails = 0;
|
|
12185
|
+
let totalTableInfo = 0;
|
|
12186
|
+
for(let i = 0; i < batches.length; i++){
|
|
12187
|
+
const batch = batches[i];
|
|
12188
|
+
logger.info(`\u{5904}\u{7406}\u{6279}\u{6B21} ${i + 1}/${batches.length}`, {
|
|
12189
|
+
projectUuid,
|
|
12190
|
+
batchId: batch.batchId,
|
|
12191
|
+
moduleCount: batch.modules.length,
|
|
12192
|
+
fileCount: batch.totalFiles
|
|
12193
|
+
});
|
|
12194
|
+
try {
|
|
12195
|
+
const batchResult = await this.processBatch(projectUuid, batch);
|
|
12196
|
+
totalProcessedFiles += batchResult.processedFiles;
|
|
12197
|
+
totalServiceInterfaces += batchResult.serviceInterfaceCount;
|
|
12198
|
+
totalDesignDetails += batchResult.designDetailCount;
|
|
12199
|
+
totalTableInfo += batchResult.tableInfoCount;
|
|
12200
|
+
await techSpecDbOperations.updateTechSpecProject(projectUuid, {
|
|
12201
|
+
processedModules: (i + 1) * this.config.maxModulesPerChapter,
|
|
12202
|
+
processedFiles: totalProcessedFiles,
|
|
12203
|
+
status: "generating"
|
|
12204
|
+
});
|
|
12205
|
+
} catch (error) {
|
|
12206
|
+
logger.error(`\u{6279}\u{6B21}\u{5904}\u{7406}\u{5931}\u{8D25}: ${batch.batchId}`, {
|
|
12207
|
+
error: error.message
|
|
12208
|
+
});
|
|
12209
|
+
}
|
|
12210
|
+
}
|
|
12211
|
+
await this.generateProjectOverviewChapter(projectUuid, techSpecProject, projectAnalysis);
|
|
12212
|
+
await techSpecDbOperations.updateTechSpecProject(projectUuid, {
|
|
12213
|
+
status: "completed",
|
|
12214
|
+
completedAt: new Date(),
|
|
12215
|
+
processedModules: filteredModules.length,
|
|
12216
|
+
processedFiles: totalProcessedFiles
|
|
12217
|
+
});
|
|
12218
|
+
const processingTime = Date.now() - startTime;
|
|
12219
|
+
logger.info(`\u{9879}\u{76EE}\u{5904}\u{7406}\u{5B8C}\u{6210}`, {
|
|
12220
|
+
projectUuid,
|
|
12221
|
+
processingTime,
|
|
12222
|
+
totalModules: filteredModules.length,
|
|
12223
|
+
totalFiles: totalProcessedFiles
|
|
12224
|
+
});
|
|
12225
|
+
return {
|
|
12226
|
+
success: true,
|
|
12227
|
+
projectUuid,
|
|
12228
|
+
totalChapters: batches.length + 1,
|
|
12229
|
+
processedChapters: batches.length + 1,
|
|
12230
|
+
totalModules: filteredModules.length,
|
|
12231
|
+
processedModules: filteredModules.length,
|
|
12232
|
+
totalFiles: projectAnalysis.allFiles.length,
|
|
12233
|
+
processedFiles: totalProcessedFiles,
|
|
12234
|
+
statistics: {
|
|
12235
|
+
serviceInterfaceCount: totalServiceInterfaces,
|
|
12236
|
+
designDetailCount: totalDesignDetails,
|
|
12237
|
+
tableInfoCount: totalTableInfo,
|
|
12238
|
+
processingTime
|
|
12239
|
+
}
|
|
12240
|
+
};
|
|
12241
|
+
} catch (error) {
|
|
12242
|
+
logger.error(`\u{9879}\u{76EE}\u{5904}\u{7406}\u{5931}\u{8D25}: ${projectAnalysis.projectName}`, {
|
|
12243
|
+
error: error.message,
|
|
12244
|
+
projectUuid
|
|
12245
|
+
});
|
|
12246
|
+
await techSpecDbOperations.updateTechSpecProject(projectUuid, {
|
|
12247
|
+
status: "failed"
|
|
12248
|
+
});
|
|
12249
|
+
return {
|
|
12250
|
+
success: false,
|
|
12251
|
+
projectUuid,
|
|
12252
|
+
totalChapters: 0,
|
|
12253
|
+
processedChapters: 0,
|
|
12254
|
+
totalModules: 0,
|
|
12255
|
+
processedModules: 0,
|
|
12256
|
+
totalFiles: 0,
|
|
12257
|
+
processedFiles: 0,
|
|
12258
|
+
errorMessage: error.message,
|
|
12259
|
+
statistics: {
|
|
12260
|
+
serviceInterfaceCount: 0,
|
|
12261
|
+
designDetailCount: 0,
|
|
12262
|
+
tableInfoCount: 0,
|
|
12263
|
+
processingTime: Date.now() - startTime
|
|
12264
|
+
}
|
|
12265
|
+
};
|
|
12266
|
+
}
|
|
12267
|
+
}
|
|
12268
|
+
async createProjectRecord(projectUuid, projectAnalysis, options) {
|
|
12269
|
+
const projectName = options.projectName || projectAnalysis.projectName;
|
|
12270
|
+
const moduleName = options.moduleName || projectName;
|
|
12271
|
+
return await techSpecDbOperations.createTechSpecProject({
|
|
12272
|
+
uuid: projectUuid,
|
|
12273
|
+
projectName,
|
|
12274
|
+
moduleName,
|
|
12275
|
+
projectPath: projectAnalysis.projectPath,
|
|
12276
|
+
totalModules: projectAnalysis.modules.length,
|
|
12277
|
+
totalFiles: projectAnalysis.allFiles.length
|
|
12278
|
+
});
|
|
12279
|
+
}
|
|
12280
|
+
filterModules(modules, options) {
|
|
12281
|
+
let filteredModules = [
|
|
12282
|
+
...modules
|
|
12283
|
+
];
|
|
12284
|
+
if (options.includeModules && options.includeModules.length > 0) filteredModules = filteredModules.filter((m)=>options.includeModules.includes(m.name));
|
|
12285
|
+
if (options.excludeModules && options.excludeModules.length > 0) filteredModules = filteredModules.filter((m)=>!options.excludeModules.includes(m.name));
|
|
12286
|
+
if (this.config.skipEmptyModules) filteredModules = filteredModules.filter((m)=>m.files.length > 0);
|
|
12287
|
+
return filteredModules;
|
|
12288
|
+
}
|
|
12289
|
+
createModuleBatches(modules) {
|
|
12290
|
+
const batches = [];
|
|
12291
|
+
let currentBatch = [];
|
|
12292
|
+
let currentFileCount = 0;
|
|
12293
|
+
for (const module of modules){
|
|
12294
|
+
if (currentBatch.length >= this.config.maxModulesPerChapter || currentFileCount + module.files.length > this.config.maxFilesPerBatch) {
|
|
12295
|
+
if (currentBatch.length > 0) batches.push({
|
|
12296
|
+
batchId: (0, external_crypto_namespaceObject.randomUUID)(),
|
|
12297
|
+
modules: [
|
|
12298
|
+
...currentBatch
|
|
12299
|
+
],
|
|
12300
|
+
totalFiles: currentFileCount,
|
|
12301
|
+
chapterType: this.determineChapterType(currentBatch)
|
|
12302
|
+
});
|
|
12303
|
+
currentBatch = [];
|
|
12304
|
+
currentFileCount = 0;
|
|
12305
|
+
}
|
|
12306
|
+
currentBatch.push(module);
|
|
12307
|
+
currentFileCount += module.files.length;
|
|
12308
|
+
}
|
|
12309
|
+
if (currentBatch.length > 0) batches.push({
|
|
12310
|
+
batchId: (0, external_crypto_namespaceObject.randomUUID)(),
|
|
12311
|
+
modules: currentBatch,
|
|
12312
|
+
totalFiles: currentFileCount,
|
|
12313
|
+
chapterType: this.determineChapterType(currentBatch)
|
|
12314
|
+
});
|
|
12315
|
+
return batches;
|
|
12316
|
+
}
|
|
12317
|
+
determineChapterType(modules) {
|
|
12318
|
+
const fileTypes = modules.flatMap((m)=>m.files.map((f)=>f.type));
|
|
12319
|
+
if (fileTypes.includes("controller") || fileTypes.includes("service")) return "service_interface_list";
|
|
12320
|
+
if (fileTypes.includes("entity")) return "database_design";
|
|
12321
|
+
return "interface_design";
|
|
12322
|
+
}
|
|
12323
|
+
async processBatch(projectUuid, batch) {
|
|
12324
|
+
logger.info(`\u{5F00}\u{59CB}\u{5904}\u{7406}\u{6279}\u{6B21}: ${batch.batchId}`, {
|
|
12325
|
+
moduleCount: batch.modules.length,
|
|
12326
|
+
fileCount: batch.totalFiles
|
|
12327
|
+
});
|
|
12328
|
+
const moduleStatuses = [];
|
|
12329
|
+
for (const module of batch.modules){
|
|
12330
|
+
const moduleUuid = (0, external_crypto_namespaceObject.randomUUID)();
|
|
12331
|
+
const moduleStatus = await techSpecDbOperations.createModuleProcessStatus({
|
|
12332
|
+
uuid: moduleUuid,
|
|
12333
|
+
projectUuid,
|
|
12334
|
+
moduleName: module.name,
|
|
12335
|
+
moduleType: this.detectModuleType(module),
|
|
12336
|
+
totalFiles: module.files.length
|
|
12337
|
+
});
|
|
12338
|
+
moduleStatuses.push(moduleStatus);
|
|
12339
|
+
}
|
|
12340
|
+
const batchAnalysis = {
|
|
12341
|
+
projectName: `batch-${batch.batchId}`,
|
|
12342
|
+
projectPath: "",
|
|
12343
|
+
modules: batch.modules,
|
|
12344
|
+
allFiles: batch.modules.flatMap((m)=>m.files),
|
|
12345
|
+
statistics: {
|
|
12346
|
+
totalFiles: batch.totalFiles,
|
|
12347
|
+
controllerFiles: 0,
|
|
12348
|
+
serviceFiles: 0,
|
|
12349
|
+
entityFiles: 0,
|
|
12350
|
+
dtoFiles: 0,
|
|
12351
|
+
moduleCount: batch.modules.length
|
|
12352
|
+
}
|
|
12353
|
+
};
|
|
12354
|
+
const codeAnalysis = await analyzeProjectCode(batchAnalysis, {
|
|
12355
|
+
includeFileTypes: [
|
|
12356
|
+
"controller",
|
|
12357
|
+
"service",
|
|
12358
|
+
"entity",
|
|
12359
|
+
"dto"
|
|
12360
|
+
]
|
|
12361
|
+
});
|
|
12362
|
+
await this.storeChapterContent(projectUuid, batch, codeAnalysis);
|
|
12363
|
+
for (const moduleStatus of moduleStatuses)await techSpecDbOperations.updateModuleProcessStatus(moduleStatus.uuid, {
|
|
12364
|
+
status: "completed",
|
|
12365
|
+
processedFiles: moduleStatus.totalFiles,
|
|
12366
|
+
completedAt: new Date()
|
|
12367
|
+
});
|
|
12368
|
+
return {
|
|
12369
|
+
processedFiles: batch.totalFiles,
|
|
12370
|
+
serviceInterfaceCount: codeAnalysis.serviceInterfaceList.length,
|
|
12371
|
+
designDetailCount: codeAnalysis.designDetailList.length,
|
|
12372
|
+
tableInfoCount: codeAnalysis.tableInfoList.length
|
|
12373
|
+
};
|
|
12374
|
+
}
|
|
12375
|
+
detectModuleType(module) {
|
|
12376
|
+
const javaFiles = module.files.filter((f)=>f.path.endsWith(".java"));
|
|
12377
|
+
const tsFiles = module.files.filter((f)=>f.path.endsWith(".ts") || f.path.endsWith(".js"));
|
|
12378
|
+
if (javaFiles.length > tsFiles.length) return "java";
|
|
12379
|
+
if (tsFiles.length > 0) return "typescript";
|
|
12380
|
+
return "other";
|
|
12381
|
+
}
|
|
12382
|
+
async storeChapterContent(projectUuid, batch, codeAnalysis) {
|
|
12383
|
+
const moduleNames = batch.modules.map((m)=>m.name).join(", ");
|
|
12384
|
+
if (codeAnalysis.serviceInterfaceList.length > 0) await techSpecDbOperations.createTechSpecChapter({
|
|
12385
|
+
uuid: (0, external_crypto_namespaceObject.randomUUID)(),
|
|
12386
|
+
projectUuid,
|
|
12387
|
+
chapterType: "service_interface_list",
|
|
12388
|
+
chapterTitle: `\u{670D}\u{52A1}\u{63A5}\u{53E3}\u{6E05}\u{5355} - ${moduleNames}`,
|
|
12389
|
+
chapterOrder: this.getChapterOrder("service_interface_list"),
|
|
12390
|
+
content: JSON.stringify(codeAnalysis.serviceInterfaceList),
|
|
12391
|
+
moduleSource: moduleNames,
|
|
12392
|
+
fileCount: batch.totalFiles
|
|
12393
|
+
});
|
|
12394
|
+
if (codeAnalysis.designDetailList.length > 0) await techSpecDbOperations.createTechSpecChapter({
|
|
12395
|
+
uuid: (0, external_crypto_namespaceObject.randomUUID)(),
|
|
12396
|
+
projectUuid,
|
|
12397
|
+
chapterType: "interface_design",
|
|
12398
|
+
chapterTitle: `\u{63A5}\u{53E3}\u{8BBE}\u{8BA1}\u{8BE6}\u{60C5} - ${moduleNames}`,
|
|
12399
|
+
chapterOrder: this.getChapterOrder("interface_design"),
|
|
12400
|
+
content: JSON.stringify(codeAnalysis.designDetailList),
|
|
12401
|
+
moduleSource: moduleNames,
|
|
12402
|
+
fileCount: batch.totalFiles
|
|
12403
|
+
});
|
|
12404
|
+
if (codeAnalysis.tableInfoList.length > 0) await techSpecDbOperations.createTechSpecChapter({
|
|
12405
|
+
uuid: (0, external_crypto_namespaceObject.randomUUID)(),
|
|
12406
|
+
projectUuid,
|
|
12407
|
+
chapterType: "database_design",
|
|
12408
|
+
chapterTitle: `\u{6570}\u{636E}\u{5E93}\u{8BBE}\u{8BA1} - ${moduleNames}`,
|
|
12409
|
+
chapterOrder: this.getChapterOrder("database_design"),
|
|
12410
|
+
content: JSON.stringify(codeAnalysis.tableInfoList),
|
|
12411
|
+
moduleSource: moduleNames,
|
|
12412
|
+
fileCount: batch.totalFiles
|
|
12413
|
+
});
|
|
12414
|
+
const techSolutionContent = this.generateTechSolutionContent(batch, codeAnalysis);
|
|
12415
|
+
if (techSolutionContent) await techSpecDbOperations.createTechSpecChapter({
|
|
12416
|
+
uuid: (0, external_crypto_namespaceObject.randomUUID)(),
|
|
12417
|
+
projectUuid,
|
|
12418
|
+
chapterType: "tech_solution",
|
|
12419
|
+
chapterTitle: `\u{6280}\u{672F}\u{65B9}\u{6848} - ${moduleNames}`,
|
|
12420
|
+
chapterOrder: this.getChapterOrder("tech_solution"),
|
|
12421
|
+
content: JSON.stringify(techSolutionContent),
|
|
12422
|
+
moduleSource: moduleNames,
|
|
12423
|
+
fileCount: batch.totalFiles
|
|
12424
|
+
});
|
|
12425
|
+
const businessExceptionContent = this.generateBusinessExceptionContent(batch, codeAnalysis);
|
|
12426
|
+
if (businessExceptionContent) await techSpecDbOperations.createTechSpecChapter({
|
|
12427
|
+
uuid: (0, external_crypto_namespaceObject.randomUUID)(),
|
|
12428
|
+
projectUuid,
|
|
12429
|
+
chapterType: "business_exception",
|
|
12430
|
+
chapterTitle: `\u{4E1A}\u{52A1}\u{5F02}\u{5E38}\u{5904}\u{7406} - ${moduleNames}`,
|
|
12431
|
+
chapterOrder: this.getChapterOrder("business_exception"),
|
|
12432
|
+
content: JSON.stringify(businessExceptionContent),
|
|
12433
|
+
moduleSource: moduleNames,
|
|
12434
|
+
fileCount: batch.totalFiles
|
|
12435
|
+
});
|
|
12436
|
+
}
|
|
12437
|
+
getChapterOrder(chapterType) {
|
|
12438
|
+
const orderMap = {
|
|
12439
|
+
project_overview: 1,
|
|
12440
|
+
service_interface_list: 2,
|
|
12441
|
+
interface_design: 3,
|
|
12442
|
+
database_design: 4,
|
|
12443
|
+
tech_solution: 5,
|
|
12444
|
+
business_exception: 6,
|
|
12445
|
+
appendix: 7
|
|
12446
|
+
};
|
|
12447
|
+
return orderMap[chapterType] || 99;
|
|
12448
|
+
}
|
|
12449
|
+
generateTechSolutionContent(batch, codeAnalysis) {
|
|
12450
|
+
const moduleNames = batch.modules.map((m)=>m.name).join(", ");
|
|
12451
|
+
return {
|
|
12452
|
+
content: `
|
|
12453
|
+
## ${moduleNames} \u{6A21}\u{5757}\u{6280}\u{672F}\u{65B9}\u{6848}
|
|
12454
|
+
|
|
12455
|
+
### \u{6D41}\u{91CF}\u{4F30}\u{7B97}
|
|
12456
|
+
\u{6839}\u{636E} ${moduleNames} \u{6A21}\u{5757}\u{7684} ${codeAnalysis.serviceInterfaceList.length} \u{4E2A}\u{670D}\u{52A1}\u{63A5}\u{53E3}\u{FF0C}\u{9884}\u{4F30}\u{65E5}\u{5747}\u{8BF7}\u{6C42}\u{91CF}\u{3002}
|
|
12457
|
+
|
|
12458
|
+
### \u{6280}\u{672F}\u{67B6}\u{6784}
|
|
12459
|
+
\u{6A21}\u{5757}\u{5305}\u{542B} ${codeAnalysis.tableInfoList.length} \u{4E2A}\u{6570}\u{636E}\u{8868}\u{FF0C}${codeAnalysis.designDetailList.length} \u{4E2A}\u{63A5}\u{53E3}\u{8BBE}\u{8BA1}\u{3002}
|
|
12460
|
+
|
|
12461
|
+
### \u{4E2D}\u{95F4}\u{4EF6}\u{9009}\u{578B}
|
|
12462
|
+
\u{57FA}\u{4E8E}\u{6A21}\u{5757}\u{7279}\u{70B9}\u{FF0C}\u{5EFA}\u{8BAE}\u{4F7F}\u{7528}\u{76F8}\u{5E94}\u{7684}\u{4E2D}\u{95F4}\u{4EF6}\u{8FDB}\u{884C}\u{652F}\u{6491}\u{3002}
|
|
12463
|
+
`.trim()
|
|
12464
|
+
};
|
|
12465
|
+
}
|
|
12466
|
+
generateBusinessExceptionContent(batch, codeAnalysis) {
|
|
12467
|
+
const moduleNames = batch.modules.map((m)=>m.name).join(", ");
|
|
12468
|
+
return {
|
|
12469
|
+
content: `
|
|
12470
|
+
## ${moduleNames} \u{6A21}\u{5757}\u{4E1A}\u{52A1}\u{5F02}\u{5E38}\u{5904}\u{7406}
|
|
12471
|
+
|
|
12472
|
+
### \u{5F02}\u{5E38}\u{5206}\u{7C7B}
|
|
12473
|
+
\u{6A21}\u{5757}\u{4E2D}\u{7684}\u{4E1A}\u{52A1}\u{5F02}\u{5E38}\u{6309}\u{7167}\u{7EDF}\u{4E00}\u{7684}\u{5206}\u{7C7B}\u{6807}\u{51C6}\u{8FDB}\u{884C}\u{5904}\u{7406}\u{3002}
|
|
12474
|
+
|
|
12475
|
+
### \u{5F02}\u{5E38}\u{5904}\u{7406}\u{7B56}\u{7565}
|
|
12476
|
+
\u{9488}\u{5BF9} ${codeAnalysis.serviceInterfaceList.length} \u{4E2A}\u{670D}\u{52A1}\u{63A5}\u{53E3}\u{7684}\u{5F02}\u{5E38}\u{5904}\u{7406}\u{7B56}\u{7565}\u{3002}
|
|
12477
|
+
|
|
12478
|
+
### \u{5F02}\u{5E38}\u{7801}\u{5B9A}\u{4E49}
|
|
12479
|
+
\u{6A21}\u{5757}\u{76F8}\u{5173}\u{7684}\u{5F02}\u{5E38}\u{7801}\u{5B9A}\u{4E49}\u{548C}\u{5904}\u{7406}\u{89C4}\u{8303}\u{3002}
|
|
12480
|
+
`.trim()
|
|
12481
|
+
};
|
|
12482
|
+
}
|
|
12483
|
+
async generateProjectOverviewChapter(projectUuid, project, projectAnalysis) {
|
|
12484
|
+
const statistics = await techSpecDbOperations.getProjectStatistics(projectUuid);
|
|
12485
|
+
const overviewContent = {
|
|
12486
|
+
projectName: project.projectName,
|
|
12487
|
+
moduleName: project.moduleName,
|
|
12488
|
+
projectPath: project.projectPath,
|
|
12489
|
+
totalModules: statistics.totalModules,
|
|
12490
|
+
totalFiles: statistics.totalFiles,
|
|
12491
|
+
summary: `
|
|
12492
|
+
\u{9879}\u{76EE} ${project.projectName} \u{5305}\u{542B} ${statistics.totalModules} \u{4E2A}\u{4E1A}\u{52A1}\u{6A21}\u{5757}\u{FF0C}
|
|
12493
|
+
\u{5171}\u{8BA1} ${statistics.totalFiles} \u{4E2A}\u{4EE3}\u{7801}\u{6587}\u{4EF6}\u{3002}
|
|
12494
|
+
|
|
12495
|
+
\u{901A}\u{8FC7}\u{81EA}\u{52A8}\u{5316}\u{5206}\u{6790}\u{FF0C}\u{751F}\u{6210}\u{4E86} ${statistics.totalChapters} \u{4E2A}\u{6280}\u{672F}\u{89C4}\u{683C}\u{7AE0}\u{8282}\u{FF0C}
|
|
12496
|
+
\u{5305}\u{62EC}\u{670D}\u{52A1}\u{63A5}\u{53E3}\u{6E05}\u{5355}\u{3001}\u{63A5}\u{53E3}\u{8BBE}\u{8BA1}\u{8BE6}\u{60C5}\u{3001}\u{6570}\u{636E}\u{5E93}\u{8BBE}\u{8BA1}\u{7B49}\u{5B8C}\u{6574}\u{5185}\u{5BB9}\u{3002}
|
|
12497
|
+
`.trim(),
|
|
12498
|
+
moduleList: projectAnalysis.modules.map((m)=>({
|
|
12499
|
+
name: m.name,
|
|
12500
|
+
path: m.relativePath,
|
|
12501
|
+
fileCount: m.files.length
|
|
12502
|
+
}))
|
|
12503
|
+
};
|
|
12504
|
+
await techSpecDbOperations.createTechSpecChapter({
|
|
12505
|
+
uuid: (0, external_crypto_namespaceObject.randomUUID)(),
|
|
12506
|
+
projectUuid,
|
|
12507
|
+
chapterType: "project_overview",
|
|
12508
|
+
chapterTitle: "\u9879\u76EE\u6982\u8FF0",
|
|
12509
|
+
chapterOrder: this.getChapterOrder("project_overview"),
|
|
12510
|
+
content: JSON.stringify(overviewContent),
|
|
12511
|
+
moduleSource: "all",
|
|
12512
|
+
fileCount: projectAnalysis.allFiles.length
|
|
12513
|
+
});
|
|
12514
|
+
}
|
|
12515
|
+
async processMultiProjects(config) {
|
|
12516
|
+
const startTime = Date.now();
|
|
12517
|
+
const projectUuid = (0, external_crypto_namespaceObject.randomUUID)();
|
|
12518
|
+
logger.info(`\u{5F00}\u{59CB}\u{5904}\u{7406}\u{591A}\u{9879}\u{76EE}\u{5408}\u{5E76}: ${config.mergedProjectName}`, {
|
|
12519
|
+
projectUuid,
|
|
12520
|
+
projectCount: config.projectPaths.length,
|
|
12521
|
+
projectPaths: config.projectPaths
|
|
12522
|
+
});
|
|
12523
|
+
const projectResults = [];
|
|
12524
|
+
let totalServiceInterfaces = 0;
|
|
12525
|
+
let totalDesignDetails = 0;
|
|
12526
|
+
let totalTables = 0;
|
|
12527
|
+
let totalFiles = 0;
|
|
12528
|
+
let processedProjects = 0;
|
|
12529
|
+
try {
|
|
12530
|
+
await techSpecDbOperations.createTechSpecProject({
|
|
12531
|
+
uuid: projectUuid,
|
|
12532
|
+
projectName: config.mergedProjectName,
|
|
12533
|
+
moduleName: config.mergedModuleName || config.mergedProjectName,
|
|
12534
|
+
projectPath: config.projectPaths.join(";"),
|
|
12535
|
+
totalModules: config.projectPaths.length,
|
|
12536
|
+
totalFiles: 0
|
|
12537
|
+
});
|
|
12538
|
+
for(let i = 0; i < config.projectPaths.length; i++){
|
|
12539
|
+
const projectPath = config.projectPaths[i];
|
|
12540
|
+
const projectAlias = config.projectAliases?.[projectPath];
|
|
12541
|
+
logger.info(`\u{5206}\u{6790}\u{5FAE}\u{670D}\u{52A1}\u{9879}\u{76EE} ${i + 1}/${config.projectPaths.length}: ${projectPath}`);
|
|
12542
|
+
try {
|
|
12543
|
+
const projectAnalysis = await analyzeProject(projectPath);
|
|
12544
|
+
const projectName = projectAlias || projectAnalysis.projectName;
|
|
12545
|
+
const codeAnalysis = await analyzeProjectCode(projectAnalysis, {
|
|
12546
|
+
includeFileTypes: [
|
|
12547
|
+
"controller",
|
|
12548
|
+
"service",
|
|
12549
|
+
"entity",
|
|
12550
|
+
"dto"
|
|
12551
|
+
]
|
|
12552
|
+
});
|
|
12553
|
+
const prefixedData = this.addProjectPrefix(codeAnalysis, projectName, false !== config.addProjectPrefix);
|
|
12554
|
+
await this.storeMultiProjectChapterContent(projectUuid, projectName, prefixedData, projectAnalysis.allFiles.length);
|
|
12555
|
+
totalServiceInterfaces += prefixedData.serviceInterfaceList.length;
|
|
12556
|
+
totalDesignDetails += prefixedData.designDetailList.length;
|
|
12557
|
+
totalTables += prefixedData.tableInfoList.length;
|
|
12558
|
+
totalFiles += projectAnalysis.allFiles.length;
|
|
12559
|
+
processedProjects++;
|
|
12560
|
+
projectResults.push({
|
|
12561
|
+
projectPath,
|
|
12562
|
+
projectName,
|
|
12563
|
+
success: true,
|
|
12564
|
+
statistics: {
|
|
12565
|
+
serviceInterfaceCount: prefixedData.serviceInterfaceList.length,
|
|
12566
|
+
designDetailCount: prefixedData.designDetailList.length,
|
|
12567
|
+
tableInfoCount: prefixedData.tableInfoList.length
|
|
12568
|
+
}
|
|
12569
|
+
});
|
|
12570
|
+
logger.info(`\u{5FAE}\u{670D}\u{52A1}\u{9879}\u{76EE}\u{5206}\u{6790}\u{5B8C}\u{6210}: ${projectName}`, {
|
|
12571
|
+
serviceInterfaces: prefixedData.serviceInterfaceList.length,
|
|
12572
|
+
designDetails: prefixedData.designDetailList.length,
|
|
12573
|
+
tables: prefixedData.tableInfoList.length
|
|
12574
|
+
});
|
|
12575
|
+
} catch (error) {
|
|
12576
|
+
logger.error(`\u{5FAE}\u{670D}\u{52A1}\u{9879}\u{76EE}\u{5206}\u{6790}\u{5931}\u{8D25}: ${projectPath}`, {
|
|
12577
|
+
error: error.message
|
|
12578
|
+
});
|
|
12579
|
+
projectResults.push({
|
|
12580
|
+
projectPath,
|
|
12581
|
+
projectName: projectAlias || projectPath.split("/").pop() || projectPath,
|
|
12582
|
+
success: false,
|
|
12583
|
+
errorMessage: error.message,
|
|
12584
|
+
statistics: {
|
|
12585
|
+
serviceInterfaceCount: 0,
|
|
12586
|
+
designDetailCount: 0,
|
|
12587
|
+
tableInfoCount: 0
|
|
12588
|
+
}
|
|
12589
|
+
});
|
|
12590
|
+
}
|
|
12591
|
+
}
|
|
12592
|
+
await this.generateMultiProjectOverviewChapter(projectUuid, config, projectResults, {
|
|
12593
|
+
totalServiceInterfaces,
|
|
12594
|
+
totalDesignDetails,
|
|
12595
|
+
totalTables,
|
|
12596
|
+
totalFiles
|
|
12597
|
+
});
|
|
12598
|
+
await techSpecDbOperations.updateTechSpecProject(projectUuid, {
|
|
12599
|
+
status: "completed",
|
|
12600
|
+
completedAt: new Date(),
|
|
12601
|
+
totalFiles,
|
|
12602
|
+
processedFiles: totalFiles,
|
|
12603
|
+
processedModules: processedProjects
|
|
12604
|
+
});
|
|
12605
|
+
const processingTime = Date.now() - startTime;
|
|
12606
|
+
logger.info(`\u{591A}\u{9879}\u{76EE}\u{5408}\u{5E76}\u{5904}\u{7406}\u{5B8C}\u{6210}`, {
|
|
12607
|
+
projectUuid,
|
|
12608
|
+
processingTime,
|
|
12609
|
+
totalProjects: config.projectPaths.length,
|
|
12610
|
+
processedProjects,
|
|
12611
|
+
totalServiceInterfaces,
|
|
12612
|
+
totalDesignDetails,
|
|
12613
|
+
totalTables
|
|
12614
|
+
});
|
|
12615
|
+
return {
|
|
12616
|
+
success: true,
|
|
12617
|
+
projectUuid,
|
|
12618
|
+
mergedProjectName: config.mergedProjectName,
|
|
12619
|
+
totalProjects: config.projectPaths.length,
|
|
12620
|
+
processedProjects,
|
|
12621
|
+
projectResults,
|
|
12622
|
+
mergedStatistics: {
|
|
12623
|
+
totalServiceInterfaces,
|
|
12624
|
+
totalDesignDetails,
|
|
12625
|
+
totalTables,
|
|
12626
|
+
totalFiles,
|
|
12627
|
+
processingTime
|
|
12628
|
+
}
|
|
12629
|
+
};
|
|
12630
|
+
} catch (error) {
|
|
12631
|
+
logger.error(`\u{591A}\u{9879}\u{76EE}\u{5408}\u{5E76}\u{5904}\u{7406}\u{5931}\u{8D25}`, {
|
|
12632
|
+
error: error.message,
|
|
12633
|
+
projectUuid
|
|
12634
|
+
});
|
|
12635
|
+
await techSpecDbOperations.updateTechSpecProject(projectUuid, {
|
|
12636
|
+
status: "failed"
|
|
12637
|
+
});
|
|
12638
|
+
return {
|
|
12639
|
+
success: false,
|
|
12640
|
+
projectUuid,
|
|
12641
|
+
mergedProjectName: config.mergedProjectName,
|
|
12642
|
+
totalProjects: config.projectPaths.length,
|
|
12643
|
+
processedProjects,
|
|
12644
|
+
projectResults,
|
|
12645
|
+
mergedStatistics: {
|
|
12646
|
+
totalServiceInterfaces,
|
|
12647
|
+
totalDesignDetails,
|
|
12648
|
+
totalTables,
|
|
12649
|
+
totalFiles,
|
|
12650
|
+
processingTime: Date.now() - startTime
|
|
12651
|
+
},
|
|
12652
|
+
errorMessage: error.message
|
|
12653
|
+
};
|
|
12654
|
+
}
|
|
12655
|
+
}
|
|
12656
|
+
addProjectPrefix(codeAnalysis, projectName, addPrefix) {
|
|
12657
|
+
if (!addPrefix) return codeAnalysis;
|
|
12658
|
+
const prefix = `[${projectName}]`;
|
|
12659
|
+
return {
|
|
12660
|
+
serviceInterfaceList: codeAnalysis.serviceInterfaceList.map((item)=>({
|
|
12661
|
+
...item,
|
|
12662
|
+
serviceChineseName: `${prefix} ${item.serviceChineseName || item.serviceEnglishName}`,
|
|
12663
|
+
serviceDescription: `${prefix} ${item.serviceDescription || ""}`,
|
|
12664
|
+
_sourceProject: projectName
|
|
12665
|
+
})),
|
|
12666
|
+
designDetailList: codeAnalysis.designDetailList.map((item)=>({
|
|
12667
|
+
...item,
|
|
12668
|
+
serviceName: `${prefix} ${item.serviceName}`,
|
|
12669
|
+
serviceDesc: `${prefix} ${item.serviceDesc || ""}`,
|
|
12670
|
+
_sourceProject: projectName
|
|
12671
|
+
})),
|
|
12672
|
+
tableInfoList: codeAnalysis.tableInfoList.map((item)=>({
|
|
12673
|
+
...item,
|
|
12674
|
+
tableDescription: `${prefix} ${item.tableDescription || item.tableName}`,
|
|
12675
|
+
_sourceProject: projectName
|
|
12676
|
+
}))
|
|
12677
|
+
};
|
|
12678
|
+
}
|
|
12679
|
+
async storeMultiProjectChapterContent(projectUuid, projectName, codeAnalysis, fileCount) {
|
|
12680
|
+
if (codeAnalysis.serviceInterfaceList.length > 0) await techSpecDbOperations.createTechSpecChapter({
|
|
12681
|
+
uuid: (0, external_crypto_namespaceObject.randomUUID)(),
|
|
12682
|
+
projectUuid,
|
|
12683
|
+
chapterType: "service_interface_list",
|
|
12684
|
+
chapterTitle: `\u{670D}\u{52A1}\u{63A5}\u{53E3}\u{6E05}\u{5355} - ${projectName}`,
|
|
12685
|
+
chapterOrder: this.getChapterOrder("service_interface_list"),
|
|
12686
|
+
content: JSON.stringify(codeAnalysis.serviceInterfaceList),
|
|
12687
|
+
moduleSource: projectName,
|
|
12688
|
+
fileCount
|
|
12689
|
+
});
|
|
12690
|
+
if (codeAnalysis.designDetailList.length > 0) await techSpecDbOperations.createTechSpecChapter({
|
|
12691
|
+
uuid: (0, external_crypto_namespaceObject.randomUUID)(),
|
|
12692
|
+
projectUuid,
|
|
12693
|
+
chapterType: "interface_design",
|
|
12694
|
+
chapterTitle: `\u{63A5}\u{53E3}\u{8BBE}\u{8BA1}\u{8BE6}\u{60C5} - ${projectName}`,
|
|
12695
|
+
chapterOrder: this.getChapterOrder("interface_design"),
|
|
12696
|
+
content: JSON.stringify(codeAnalysis.designDetailList),
|
|
12697
|
+
moduleSource: projectName,
|
|
12698
|
+
fileCount
|
|
12699
|
+
});
|
|
12700
|
+
if (codeAnalysis.tableInfoList.length > 0) await techSpecDbOperations.createTechSpecChapter({
|
|
12701
|
+
uuid: (0, external_crypto_namespaceObject.randomUUID)(),
|
|
12702
|
+
projectUuid,
|
|
12703
|
+
chapterType: "database_design",
|
|
12704
|
+
chapterTitle: `\u{6570}\u{636E}\u{5E93}\u{8BBE}\u{8BA1} - ${projectName}`,
|
|
12705
|
+
chapterOrder: this.getChapterOrder("database_design"),
|
|
12706
|
+
content: JSON.stringify(codeAnalysis.tableInfoList),
|
|
12707
|
+
moduleSource: projectName,
|
|
12708
|
+
fileCount
|
|
12709
|
+
});
|
|
12710
|
+
const techSolutionContent = {
|
|
12711
|
+
content: `
|
|
12712
|
+
## ${projectName} \u{5FAE}\u{670D}\u{52A1}\u{6280}\u{672F}\u{65B9}\u{6848}
|
|
12713
|
+
|
|
12714
|
+
### \u{670D}\u{52A1}\u{6982}\u{8FF0}
|
|
12715
|
+
${projectName} \u{5FAE}\u{670D}\u{52A1}\u{5305}\u{542B} ${codeAnalysis.serviceInterfaceList.length} \u{4E2A}\u{670D}\u{52A1}\u{63A5}\u{53E3}\u{FF0C}${codeAnalysis.tableInfoList.length} \u{4E2A}\u{6570}\u{636E}\u{8868}\u{3002}
|
|
12716
|
+
|
|
12717
|
+
### \u{6280}\u{672F}\u{67B6}\u{6784}
|
|
12718
|
+
\u{57FA}\u{4E8E}\u{5FAE}\u{670D}\u{52A1}\u{67B6}\u{6784}\u{8BBE}\u{8BA1}\u{FF0C}\u{63D0}\u{4F9B}\u{72EC}\u{7ACB}\u{7684}\u{4E1A}\u{52A1}\u{529F}\u{80FD}\u{6A21}\u{5757}\u{3002}
|
|
12719
|
+
|
|
12720
|
+
### \u{63A5}\u{53E3}\u{8BBE}\u{8BA1}
|
|
12721
|
+
\u{5171}\u{8BBE}\u{8BA1} ${codeAnalysis.designDetailList.length} \u{4E2A}\u{63A5}\u{53E3}\u{FF0C}\u{652F}\u{6301}\u{670D}\u{52A1}\u{95F4}\u{8C03}\u{7528}\u{548C}\u{5916}\u{90E8}\u{8BBF}\u{95EE}\u{3002}
|
|
12722
|
+
`.trim()
|
|
12723
|
+
};
|
|
12724
|
+
await techSpecDbOperations.createTechSpecChapter({
|
|
12725
|
+
uuid: (0, external_crypto_namespaceObject.randomUUID)(),
|
|
12726
|
+
projectUuid,
|
|
12727
|
+
chapterType: "tech_solution",
|
|
12728
|
+
chapterTitle: `\u{6280}\u{672F}\u{65B9}\u{6848} - ${projectName}`,
|
|
12729
|
+
chapterOrder: this.getChapterOrder("tech_solution"),
|
|
12730
|
+
content: JSON.stringify(techSolutionContent),
|
|
12731
|
+
moduleSource: projectName,
|
|
12732
|
+
fileCount
|
|
12733
|
+
});
|
|
12734
|
+
}
|
|
12735
|
+
async generateMultiProjectOverviewChapter(projectUuid, config, projectResults, statistics) {
|
|
12736
|
+
const successfulProjects = projectResults.filter((p)=>p.success);
|
|
12737
|
+
const failedProjects = projectResults.filter((p)=>!p.success);
|
|
12738
|
+
const overviewContent = {
|
|
12739
|
+
projectName: config.mergedProjectName,
|
|
12740
|
+
moduleName: config.mergedModuleName || config.mergedProjectName,
|
|
12741
|
+
isMultiProject: true,
|
|
12742
|
+
totalProjects: config.projectPaths.length,
|
|
12743
|
+
successfulProjects: successfulProjects.length,
|
|
12744
|
+
failedProjects: failedProjects.length,
|
|
12745
|
+
summary: `
|
|
12746
|
+
\u{672C}\u{6280}\u{672F}\u{89C4}\u{683C}\u{8BF4}\u{660E}\u{4E66}\u{6DB5}\u{76D6} ${config.mergedProjectName} \u{9879}\u{76EE}\u{7FA4}\u{FF0C}\u{5305}\u{542B} ${successfulProjects.length} \u{4E2A}\u{5FAE}\u{670D}\u{52A1}\u{9879}\u{76EE}\u{3002}
|
|
12747
|
+
|
|
12748
|
+
### \u{9879}\u{76EE}\u{6982}\u{89C8}
|
|
12749
|
+
- \u{5FAE}\u{670D}\u{52A1}\u{6570}\u{91CF}\u{FF1A}${successfulProjects.length} \u{4E2A}
|
|
12750
|
+
- \u{670D}\u{52A1}\u{63A5}\u{53E3}\u{603B}\u{6570}\u{FF1A}${statistics.totalServiceInterfaces} \u{4E2A}
|
|
12751
|
+
- \u{63A5}\u{53E3}\u{8BBE}\u{8BA1}\u{603B}\u{6570}\u{FF1A}${statistics.totalDesignDetails} \u{4E2A}
|
|
12752
|
+
- \u{6570}\u{636E}\u{8868}\u{603B}\u{6570}\u{FF1A}${statistics.totalTables} \u{4E2A}
|
|
12753
|
+
- \u{4EE3}\u{7801}\u{6587}\u{4EF6}\u{603B}\u{6570}\u{FF1A}${statistics.totalFiles} \u{4E2A}
|
|
12754
|
+
|
|
12755
|
+
### \u{5FAE}\u{670D}\u{52A1}\u{5217}\u{8868}
|
|
12756
|
+
${successfulProjects.map((p, i)=>`${i + 1}. **${p.projectName}**
|
|
12757
|
+
- \u{670D}\u{52A1}\u{63A5}\u{53E3}\u{FF1A}${p.statistics.serviceInterfaceCount} \u{4E2A}
|
|
12758
|
+
- \u{63A5}\u{53E3}\u{8BBE}\u{8BA1}\u{FF1A}${p.statistics.designDetailCount} \u{4E2A}
|
|
12759
|
+
- \u{6570}\u{636E}\u{8868}\u{FF1A}${p.statistics.tableInfoCount} \u{4E2A}`).join("\n")}
|
|
12760
|
+
|
|
12761
|
+
${failedProjects.length > 0 ? `
|
|
12762
|
+
### \u{5206}\u{6790}\u{5931}\u{8D25}\u{7684}\u{9879}\u{76EE}
|
|
12763
|
+
${failedProjects.map((p)=>`- ${p.projectName}: ${p.errorMessage}`).join("\n")}
|
|
12764
|
+
` : ""}
|
|
12765
|
+
`.trim(),
|
|
12766
|
+
projectList: projectResults.map((p)=>({
|
|
12767
|
+
projectPath: p.projectPath,
|
|
12768
|
+
projectName: p.projectName,
|
|
12769
|
+
success: p.success,
|
|
12770
|
+
errorMessage: p.errorMessage,
|
|
12771
|
+
statistics: p.statistics
|
|
12772
|
+
})),
|
|
12773
|
+
mergedStatistics: statistics
|
|
12774
|
+
};
|
|
12775
|
+
await techSpecDbOperations.createTechSpecChapter({
|
|
12776
|
+
uuid: (0, external_crypto_namespaceObject.randomUUID)(),
|
|
12777
|
+
projectUuid,
|
|
12778
|
+
chapterType: "project_overview",
|
|
12779
|
+
chapterTitle: "\u9879\u76EE\u6982\u8FF0",
|
|
12780
|
+
chapterOrder: this.getChapterOrder("project_overview"),
|
|
12781
|
+
content: JSON.stringify(overviewContent),
|
|
12782
|
+
moduleSource: "all",
|
|
12783
|
+
fileCount: statistics.totalFiles
|
|
12784
|
+
});
|
|
12785
|
+
}
|
|
12786
|
+
}
|
|
12787
|
+
const DEFAULT_MERGE_CONFIG = {
|
|
12788
|
+
includeEmptyChapters: false,
|
|
12789
|
+
generateDefaultContent: true,
|
|
12790
|
+
maxItemsPerChapter: 1000,
|
|
12791
|
+
enableChapterSummary: true
|
|
12792
|
+
};
|
|
12793
|
+
class DocumentMerger {
|
|
12794
|
+
config;
|
|
12795
|
+
constructor(config = {}){
|
|
12796
|
+
this.config = {
|
|
12797
|
+
...DEFAULT_MERGE_CONFIG,
|
|
12798
|
+
...config
|
|
12799
|
+
};
|
|
12800
|
+
}
|
|
12801
|
+
async mergeAndRenderDocument(projectUuid, outputDir) {
|
|
12802
|
+
const startTime = Date.now();
|
|
12803
|
+
try {
|
|
12804
|
+
const project = await techSpecDbOperations.getTechSpecProject(projectUuid);
|
|
12805
|
+
if (!project) throw new Error(`\u{9879}\u{76EE}\u{4E0D}\u{5B58}\u{5728}: ${projectUuid}`);
|
|
12806
|
+
const statistics = await techSpecDbOperations.getProjectStatistics(projectUuid);
|
|
12807
|
+
const techSpecData = await this.mergeAllChapters(projectUuid, project);
|
|
12808
|
+
let finalOutputDir = outputDir;
|
|
12809
|
+
if (!finalOutputDir) {
|
|
12810
|
+
const projectPath = project.projectPath;
|
|
12811
|
+
const firstProjectPath = projectPath.includes(";") ? projectPath.split(";")[0].trim() : projectPath;
|
|
12812
|
+
finalOutputDir = getTechSpecOutputDir(firstProjectPath);
|
|
12813
|
+
}
|
|
12814
|
+
const renderResult = await renderTechSpecDoc(techSpecData, finalOutputDir);
|
|
12815
|
+
if (!renderResult.success) throw new Error(renderResult.error || "\u6587\u6863\u6E32\u67D3\u5931\u8D25");
|
|
12816
|
+
await techSpecDbOperations.updateTechSpecProject(projectUuid, {
|
|
12817
|
+
status: "completed",
|
|
12818
|
+
completedAt: new Date()
|
|
12819
|
+
});
|
|
12820
|
+
return {
|
|
12821
|
+
success: true,
|
|
12822
|
+
outputPath: renderResult.outputPath,
|
|
12823
|
+
techSpecData,
|
|
12824
|
+
statistics: {
|
|
12825
|
+
totalChapters: statistics.totalChapters,
|
|
12826
|
+
mergedChapters: statistics.completedChapters,
|
|
12827
|
+
totalServiceInterfaces: techSpecData.serviceInterfaceList.length,
|
|
12828
|
+
totalDesignDetails: techSpecData.designDetailList.length,
|
|
12829
|
+
totalTables: techSpecData.tableInfoList.length,
|
|
12830
|
+
processingTime: Date.now() - startTime
|
|
12831
|
+
}
|
|
12832
|
+
};
|
|
12833
|
+
} catch (error) {
|
|
12834
|
+
await techSpecDbOperations.updateTechSpecProject(projectUuid, {
|
|
12835
|
+
status: "failed"
|
|
12836
|
+
});
|
|
12837
|
+
return {
|
|
12838
|
+
success: false,
|
|
12839
|
+
statistics: {
|
|
12840
|
+
totalChapters: 0,
|
|
12841
|
+
mergedChapters: 0,
|
|
12842
|
+
totalServiceInterfaces: 0,
|
|
12843
|
+
totalDesignDetails: 0,
|
|
12844
|
+
totalTables: 0,
|
|
12845
|
+
processingTime: Date.now() - startTime
|
|
12846
|
+
},
|
|
12847
|
+
errorMessage: error.message
|
|
12848
|
+
};
|
|
12849
|
+
}
|
|
12850
|
+
}
|
|
12851
|
+
async mergeAllChapters(projectUuid, project) {
|
|
12852
|
+
const now = new Date();
|
|
12853
|
+
const isMultiProject = project.projectPath?.includes(";");
|
|
12854
|
+
const techSpecData = {
|
|
12855
|
+
projectName: project.projectName,
|
|
12856
|
+
moduleName: project.moduleName,
|
|
12857
|
+
year: String(now.getFullYear()),
|
|
12858
|
+
month: String(now.getMonth() + 1).padStart(2, "0"),
|
|
12859
|
+
referDoc: isMultiProject ? "\u591A\u5FAE\u670D\u52A1\u9879\u76EE\u4EE3\u7801\u81EA\u52A8\u5206\u6790\u751F\u6210" : "\u9879\u76EE\u4EE3\u7801\u81EA\u52A8\u5206\u6790\u751F\u6210",
|
|
12860
|
+
serviceInterfaceList: [],
|
|
12861
|
+
designDetailList: [],
|
|
12862
|
+
tableInfoList: []
|
|
12863
|
+
};
|
|
12864
|
+
const serviceInterfaces = await techSpecDbOperations.mergeChaptersByType(projectUuid, "service_interface_list");
|
|
12865
|
+
if (serviceInterfaces && Array.isArray(serviceInterfaces)) techSpecData.serviceInterfaceList = this.limitAndReindex(serviceInterfaces, this.config.maxItemsPerChapter);
|
|
12866
|
+
const designDetails = await techSpecDbOperations.mergeChaptersByType(projectUuid, "interface_design");
|
|
12867
|
+
if (designDetails && Array.isArray(designDetails)) techSpecData.designDetailList = designDetails.slice(0, this.config.maxItemsPerChapter);
|
|
12868
|
+
const tableInfos = await techSpecDbOperations.mergeChaptersByType(projectUuid, "database_design");
|
|
12869
|
+
if (tableInfos && Array.isArray(tableInfos)) techSpecData.tableInfoList = this.limitAndReindex(tableInfos, this.config.maxItemsPerChapter);
|
|
12870
|
+
const techSolution = await techSpecDbOperations.mergeChaptersByType(projectUuid, "tech_solution");
|
|
12871
|
+
if (techSolution && techSolution.content) techSpecData.techSolution = {
|
|
12872
|
+
content: techSolution.content
|
|
12873
|
+
};
|
|
12874
|
+
else if (this.config.generateDefaultContent) techSpecData.techSolution = this.generateDefaultTechSolution(techSpecData);
|
|
12875
|
+
const businessException = await techSpecDbOperations.mergeChaptersByType(projectUuid, "business_exception");
|
|
12876
|
+
if (businessException && businessException.content) techSpecData.businessException = {
|
|
12877
|
+
content: businessException.content
|
|
12878
|
+
};
|
|
12879
|
+
else if (this.config.generateDefaultContent) techSpecData.businessException = this.generateDefaultBusinessException();
|
|
12880
|
+
const appendix = await techSpecDbOperations.mergeChaptersByType(projectUuid, "appendix");
|
|
12881
|
+
if (appendix) techSpecData.appendix = {
|
|
12882
|
+
exceptionCodeList: appendix.exceptionCodeList || [],
|
|
12883
|
+
codeValueList: appendix.codeValueList || []
|
|
12884
|
+
};
|
|
12885
|
+
else if (this.config.generateDefaultContent) techSpecData.appendix = this.generateDefaultAppendix();
|
|
12886
|
+
return techSpecData;
|
|
12887
|
+
}
|
|
12888
|
+
limitAndReindex(items, maxItems) {
|
|
12889
|
+
const limitedItems = items.slice(0, maxItems);
|
|
12890
|
+
return limitedItems.map((item, index)=>({
|
|
12891
|
+
...item,
|
|
12892
|
+
id: String(index + 1)
|
|
12893
|
+
}));
|
|
12894
|
+
}
|
|
12895
|
+
generateDefaultTechSolution(techSpecData) {
|
|
12896
|
+
const serviceCount = techSpecData.serviceInterfaceList.length;
|
|
12897
|
+
const tableCount = techSpecData.tableInfoList.length;
|
|
12898
|
+
return {
|
|
12899
|
+
content: `\u{6839}\u{636E}\u{9879}\u{76EE}\u{89C4}\u{6A21}\u{5206}\u{6790}\u{FF0C}\u{7CFB}\u{7EDF}\u{5305}\u{542B} ${serviceCount} \u{4E2A}\u{670D}\u{52A1}\u{63A5}\u{53E3}\u{FF0C}${tableCount} \u{4E2A}\u{6570}\u{636E}\u{8868}\u{3002}\u{5EFA}\u{8BAE}\u{91C7}\u{7528}\u{5FAE}\u{670D}\u{52A1}\u{67B6}\u{6784}\u{3002}`
|
|
12900
|
+
};
|
|
12901
|
+
}
|
|
12902
|
+
generateDefaultBusinessException() {
|
|
12903
|
+
return {
|
|
12904
|
+
content: `\u{9879}\u{76EE}\u{91C7}\u{7528}\u{7EDF}\u{4E00}\u{5F02}\u{5E38}\u{5904}\u{7406}\u{673A}\u{5236}\u{FF0C}\u{5305}\u{62EC}\u{7CFB}\u{7EDF}\u{5F02}\u{5E38}\u{548C}\u{4E1A}\u{52A1}\u{5F02}\u{5E38}\u{4E24}\u{5927}\u{7C7B}\u{3002}`
|
|
12905
|
+
};
|
|
12906
|
+
}
|
|
12907
|
+
generateDefaultAppendix() {
|
|
12908
|
+
return {
|
|
12909
|
+
exceptionCodeList: [
|
|
12910
|
+
{
|
|
12911
|
+
id: "1",
|
|
12912
|
+
exceptionCode: "SYS0001",
|
|
12913
|
+
exceptionDescription: "\u7CFB\u7EDF\u5185\u90E8\u9519\u8BEF"
|
|
12914
|
+
}
|
|
12915
|
+
],
|
|
12916
|
+
codeValueList: [
|
|
12917
|
+
{
|
|
12918
|
+
id: "1",
|
|
12919
|
+
propertyName: "\u7528\u6237\u72B6\u6001",
|
|
12920
|
+
codeValue: "1-\u6B63\u5E38\uFF0C0-\u7981\u7528"
|
|
12921
|
+
}
|
|
12922
|
+
]
|
|
12923
|
+
};
|
|
12924
|
+
}
|
|
12925
|
+
async getProjectProgress(projectUuid) {
|
|
12926
|
+
const project = await techSpecDbOperations.getTechSpecProject(projectUuid);
|
|
12927
|
+
const statistics = await techSpecDbOperations.getProjectStatistics(projectUuid);
|
|
12928
|
+
if (!project) throw new Error(`\u{9879}\u{76EE}\u{4E0D}\u{5B58}\u{5728}: ${projectUuid}`);
|
|
12929
|
+
const totalSteps = 7;
|
|
12930
|
+
const completedSteps = statistics.completedChapters;
|
|
12931
|
+
const percentage = Math.round(completedSteps / totalSteps * 100);
|
|
12932
|
+
let currentStep = "\u51C6\u5907\u4E2D";
|
|
12933
|
+
if ("analyzing" === project.status) currentStep = "\u5206\u6790\u9879\u76EE\u7ED3\u6784";
|
|
12934
|
+
else if ("generating" === project.status) currentStep = `\u{751F}\u{6210}\u{7AE0}\u{8282}\u{5185}\u{5BB9} (${completedSteps}/${totalSteps})`;
|
|
12935
|
+
else if ("completed" === project.status) currentStep = "\u5DF2\u5B8C\u6210";
|
|
12936
|
+
else if ("failed" === project.status) currentStep = "\u5904\u7406\u5931\u8D25";
|
|
12937
|
+
return {
|
|
12938
|
+
project,
|
|
12939
|
+
statistics,
|
|
12940
|
+
progress: {
|
|
12941
|
+
totalSteps,
|
|
12942
|
+
completedSteps,
|
|
12943
|
+
currentStep,
|
|
12944
|
+
percentage
|
|
12945
|
+
}
|
|
12946
|
+
};
|
|
12947
|
+
}
|
|
12948
|
+
}
|
|
11119
12949
|
const TableFieldDetailSchema = objectType({
|
|
11120
12950
|
id: stringType().describe("\u5E8F\u53F7"),
|
|
11121
12951
|
fieldName: stringType().describe("\u5B57\u6BB5\u540D"),
|
|
@@ -11614,65 +13444,392 @@ ${requirement_description}
|
|
|
11614
13444
|
]
|
|
11615
13445
|
})
|
|
11616
13446
|
};
|
|
11617
|
-
const generateFinalDocumentTool = {
|
|
11618
|
-
name: "generate_final_document",
|
|
11619
|
-
description: "\u6574\u5408\u6240\u6709\u6536\u96C6\u7684\u4FE1\u606F\uFF0C\u751F\u6210\u5B8C\u6574\u7684\u6280\u672F\u89C4\u683C\u8BF4\u660E\u4E66",
|
|
13447
|
+
const generateFinalDocumentTool = {
|
|
13448
|
+
name: "generate_final_document",
|
|
13449
|
+
description: "\u6574\u5408\u6240\u6709\u6536\u96C6\u7684\u4FE1\u606F\uFF0C\u751F\u6210\u5B8C\u6574\u7684\u6280\u672F\u89C4\u683C\u8BF4\u660E\u4E66",
|
|
13450
|
+
inputSchema: {
|
|
13451
|
+
projectPath: stringType().min(1).describe(PROJECT_PATH_DESCRIPTION),
|
|
13452
|
+
techSpecData: objectType({
|
|
13453
|
+
projectName: stringType().describe("\u9879\u76EE\u540D\u79F0"),
|
|
13454
|
+
moduleName: stringType().describe("\u6A21\u5757\u540D\u79F0"),
|
|
13455
|
+
year: stringType().optional().describe("\u5E74\u4EFD\uFF0C\u9ED8\u8BA4\u5F53\u524D\u5E74\u4EFD"),
|
|
13456
|
+
month: stringType().optional().describe("\u6708\u4EFD\uFF0C\u9ED8\u8BA4\u5F53\u524D\u6708\u4EFD"),
|
|
13457
|
+
referDoc: stringType().optional().describe("\u53C2\u8003\u6587\u6863"),
|
|
13458
|
+
serviceInterfaceList: arrayType(ServiceInterfaceSchema).default([]).describe("\u670D\u52A1\u63A5\u53E3\u6E05\u5355"),
|
|
13459
|
+
designDetailList: arrayType(DesignDetailSchema).default([]).describe("\u670D\u52A1\u63A5\u53E3\u8BBE\u8BA1\u8BE6\u60C5"),
|
|
13460
|
+
tableInfoList: arrayType(TableInfoSchema).default([]).describe("\u6570\u636E\u5E93\u8868\u4FE1\u606F\u5217\u8868"),
|
|
13461
|
+
techSolution: TechSolutionSchema.optional().describe("\u6280\u672F\u65B9\u6848"),
|
|
13462
|
+
businessException: BusinessExceptionSchema.optional().describe("\u4E1A\u52A1\u5F02\u5E38\u5904\u7406"),
|
|
13463
|
+
appendix: AppendixSchema.optional().describe("\u9644\u5F55"),
|
|
13464
|
+
dtoDefinitions: recordType(stringType(), arrayType(objectType({
|
|
13465
|
+
name: stringType().optional().describe("\u5B57\u6BB5\u540D"),
|
|
13466
|
+
type: stringType().optional().describe("\u5B57\u6BB5\u7C7B\u578B"),
|
|
13467
|
+
required: stringType().optional().describe("\u662F\u5426\u5FC5\u586B"),
|
|
13468
|
+
description: stringType().optional().describe("\u5B57\u6BB5\u63CF\u8FF0")
|
|
13469
|
+
}))).optional().describe("DTO\u5B9A\u4E49\u6620\u5C04\uFF0C\u7528\u4E8E\u5C55\u5F00\u63A5\u53E3\u53C2\u6570\u4E2D\u7684DTO\u4E3A\u5177\u4F53\u5B57\u6BB5")
|
|
13470
|
+
}).describe("\u5B8C\u6574\u7684\u6280\u672F\u89C4\u683C\u6570\u636E")
|
|
13471
|
+
},
|
|
13472
|
+
handler: async (args)=>{
|
|
13473
|
+
try {
|
|
13474
|
+
const { projectPath } = args;
|
|
13475
|
+
let { techSpecData } = args;
|
|
13476
|
+
if (!projectPath || !techSpecData) return {
|
|
13477
|
+
content: [
|
|
13478
|
+
{
|
|
13479
|
+
type: "text",
|
|
13480
|
+
text: JSON.stringify({
|
|
13481
|
+
success: false,
|
|
13482
|
+
message: "\u7F3A\u5C11\u5FC5\u586B\u53C2\u6570"
|
|
13483
|
+
})
|
|
13484
|
+
}
|
|
13485
|
+
],
|
|
13486
|
+
isError: true
|
|
13487
|
+
};
|
|
13488
|
+
if ("string" == typeof techSpecData) techSpecData = JSON.parse(techSpecData);
|
|
13489
|
+
const now = new Date();
|
|
13490
|
+
const normalizedData = normalizeInputData(techSpecData);
|
|
13491
|
+
const data = {
|
|
13492
|
+
projectName: normalizedData.projectName || "\u672A\u547D\u540D\u9879\u76EE",
|
|
13493
|
+
moduleName: normalizedData.moduleName || "\u672A\u547D\u540D\u6A21\u5757",
|
|
13494
|
+
year: normalizedData.year || String(now.getFullYear()),
|
|
13495
|
+
month: normalizedData.month || String(now.getMonth() + 1).padStart(2, "0"),
|
|
13496
|
+
referDoc: normalizedData.referDoc || "\u65E0",
|
|
13497
|
+
serviceInterfaceList: normalizedData.serviceInterfaceList || [],
|
|
13498
|
+
designDetailList: normalizedData.designDetailList || [],
|
|
13499
|
+
tableInfoList: normalizedData.tableInfoList || [],
|
|
13500
|
+
techSolution: normalizedData.techSolution || void 0,
|
|
13501
|
+
businessException: normalizedData.businessException || void 0,
|
|
13502
|
+
appendix: normalizedData.appendix || void 0
|
|
13503
|
+
};
|
|
13504
|
+
const outputDir = getTechSpecOutputDir(projectPath);
|
|
13505
|
+
const result = await renderTechSpecDoc(data, outputDir);
|
|
13506
|
+
if (result.success) return {
|
|
13507
|
+
content: [
|
|
13508
|
+
{
|
|
13509
|
+
type: "text",
|
|
13510
|
+
text: JSON.stringify({
|
|
13511
|
+
success: true,
|
|
13512
|
+
message: "\u6280\u672F\u89C4\u683C\u8BF4\u660E\u4E66\u751F\u6210\u6210\u529F",
|
|
13513
|
+
data: {
|
|
13514
|
+
outputPath: result.outputPath,
|
|
13515
|
+
projectName: data.projectName,
|
|
13516
|
+
moduleName: data.moduleName,
|
|
13517
|
+
statistics: {
|
|
13518
|
+
tableCount: data.tableInfoList.length,
|
|
13519
|
+
serviceCount: data.serviceInterfaceList.length,
|
|
13520
|
+
designCount: data.designDetailList.length,
|
|
13521
|
+
hasTechSolution: !!data.techSolution,
|
|
13522
|
+
hasBusinessException: !!data.businessException,
|
|
13523
|
+
hasAppendix: !!data.appendix
|
|
13524
|
+
}
|
|
13525
|
+
}
|
|
13526
|
+
})
|
|
13527
|
+
}
|
|
13528
|
+
]
|
|
13529
|
+
};
|
|
13530
|
+
return {
|
|
13531
|
+
content: [
|
|
13532
|
+
{
|
|
13533
|
+
type: "text",
|
|
13534
|
+
text: JSON.stringify({
|
|
13535
|
+
success: false,
|
|
13536
|
+
message: result.error || "\u6587\u6863\u751F\u6210\u5931\u8D25"
|
|
13537
|
+
})
|
|
13538
|
+
}
|
|
13539
|
+
],
|
|
13540
|
+
isError: true
|
|
13541
|
+
};
|
|
13542
|
+
} catch (error) {
|
|
13543
|
+
return {
|
|
13544
|
+
content: [
|
|
13545
|
+
{
|
|
13546
|
+
type: "text",
|
|
13547
|
+
text: JSON.stringify({
|
|
13548
|
+
success: false,
|
|
13549
|
+
message: error.message || "\u751F\u6210\u8FC7\u7A0B\u4E2D\u53D1\u751F\u9519\u8BEF"
|
|
13550
|
+
})
|
|
13551
|
+
}
|
|
13552
|
+
],
|
|
13553
|
+
isError: true
|
|
13554
|
+
};
|
|
13555
|
+
}
|
|
13556
|
+
}
|
|
13557
|
+
};
|
|
13558
|
+
const analyzeLargeProjectTool = {
|
|
13559
|
+
name: "analyze_large_project",
|
|
13560
|
+
description: "\u5206\u6790\u5927\u578B\u9879\u76EE\u5E76\u5206\u7AE0\u8282\u5B58\u50A8\u5230\u6570\u636E\u5E93\uFF0C\u652F\u6301\u5904\u7406\u5305\u542B\u6570\u767E\u4E2A\u6587\u4EF6\u7684\u5927\u578B\u9879\u76EE\u3002\u9002\u7528\u4E8E\u4F01\u4E1A\u7EA7\u9879\u76EE\u7684\u5B8C\u6574\u6280\u672F\u89C4\u683C\u8BF4\u660E\u4E66\u751F\u6210\u3002",
|
|
13561
|
+
inputSchema: {
|
|
13562
|
+
projectPath: stringType().min(1).describe(PROJECT_PATH_DESCRIPTION),
|
|
13563
|
+
projectName: stringType().optional().describe("\u9879\u76EE\u540D\u79F0\uFF0C\u5982\u4E0D\u63D0\u4F9B\u5219\u4F7F\u7528\u76EE\u5F55\u540D"),
|
|
13564
|
+
moduleName: stringType().optional().describe("\u6A21\u5757\u540D\u79F0\uFF0C\u5982\u4E0D\u63D0\u4F9B\u5219\u4F7F\u7528\u9879\u76EE\u540D"),
|
|
13565
|
+
includeModules: arrayType(stringType()).optional().describe("\u8981\u5305\u542B\u7684\u6A21\u5757\u5217\u8868\uFF0C\u5982\u4E0D\u63D0\u4F9B\u5219\u5305\u542B\u6240\u6709\u6A21\u5757"),
|
|
13566
|
+
excludeModules: arrayType(stringType()).optional().describe("\u8981\u6392\u9664\u7684\u6A21\u5757\u5217\u8868"),
|
|
13567
|
+
maxFilesPerBatch: numberType().optional().default(50).describe("\u6BCF\u6279\u5904\u7406\u7684\u6700\u5927\u6587\u4EF6\u6570"),
|
|
13568
|
+
maxModulesPerChapter: numberType().optional().default(10).describe("\u6BCF\u7AE0\u8282\u7684\u6700\u5927\u6A21\u5757\u6570")
|
|
13569
|
+
},
|
|
13570
|
+
handler: async (args)=>{
|
|
13571
|
+
try {
|
|
13572
|
+
const { projectPath, projectName, moduleName, includeModules, excludeModules, maxFilesPerBatch = 50, maxModulesPerChapter = 10 } = args;
|
|
13573
|
+
if (!projectPath) return {
|
|
13574
|
+
content: [
|
|
13575
|
+
{
|
|
13576
|
+
type: "text",
|
|
13577
|
+
text: JSON.stringify({
|
|
13578
|
+
success: false,
|
|
13579
|
+
message: "\u7F3A\u5C11\u5FC5\u586B\u53C2\u6570\uFF1AprojectPath"
|
|
13580
|
+
})
|
|
13581
|
+
}
|
|
13582
|
+
],
|
|
13583
|
+
isError: true
|
|
13584
|
+
};
|
|
13585
|
+
logger.info(`\u{5F00}\u{59CB}\u{5206}\u{6790}\u{5927}\u{578B}\u{9879}\u{76EE}: ${projectPath}`);
|
|
13586
|
+
const projectAnalysis = await analyzeProject(projectPath);
|
|
13587
|
+
const chapterProcessor = new ChapterProcessor({
|
|
13588
|
+
maxFilesPerBatch,
|
|
13589
|
+
maxModulesPerChapter,
|
|
13590
|
+
enableParallelProcessing: true,
|
|
13591
|
+
skipEmptyModules: true
|
|
13592
|
+
});
|
|
13593
|
+
const result = await chapterProcessor.processFullProject(projectAnalysis, {
|
|
13594
|
+
projectName,
|
|
13595
|
+
moduleName,
|
|
13596
|
+
includeModules,
|
|
13597
|
+
excludeModules
|
|
13598
|
+
});
|
|
13599
|
+
if (result.success) return {
|
|
13600
|
+
content: [
|
|
13601
|
+
{
|
|
13602
|
+
type: "text",
|
|
13603
|
+
text: JSON.stringify({
|
|
13604
|
+
success: true,
|
|
13605
|
+
message: "\u5927\u578B\u9879\u76EE\u5206\u6790\u5B8C\u6210\uFF0C\u7AE0\u8282\u5DF2\u5B58\u50A8\u5230\u6570\u636E\u5E93",
|
|
13606
|
+
data: {
|
|
13607
|
+
projectUuid: result.projectUuid,
|
|
13608
|
+
projectAnalysis: {
|
|
13609
|
+
projectName: projectAnalysis.projectName,
|
|
13610
|
+
moduleCount: projectAnalysis.modules.length,
|
|
13611
|
+
totalFiles: projectAnalysis.statistics.totalFiles,
|
|
13612
|
+
modules: getModuleNames(projectAnalysis)
|
|
13613
|
+
},
|
|
13614
|
+
processingResult: {
|
|
13615
|
+
totalChapters: result.totalChapters,
|
|
13616
|
+
processedChapters: result.processedChapters,
|
|
13617
|
+
totalModules: result.totalModules,
|
|
13618
|
+
processedModules: result.processedModules,
|
|
13619
|
+
totalFiles: result.totalFiles,
|
|
13620
|
+
processedFiles: result.processedFiles
|
|
13621
|
+
},
|
|
13622
|
+
statistics: result.statistics,
|
|
13623
|
+
nextStep: `\u{8C03}\u{7528} render_final_document \u{5DE5}\u{5177}\u{FF0C}\u{4F7F}\u{7528} projectUuid: ${result.projectUuid} \u{751F}\u{6210}\u{6700}\u{7EC8}\u{6587}\u{6863}`
|
|
13624
|
+
}
|
|
13625
|
+
})
|
|
13626
|
+
}
|
|
13627
|
+
]
|
|
13628
|
+
};
|
|
13629
|
+
return {
|
|
13630
|
+
content: [
|
|
13631
|
+
{
|
|
13632
|
+
type: "text",
|
|
13633
|
+
text: JSON.stringify({
|
|
13634
|
+
success: false,
|
|
13635
|
+
message: result.errorMessage || "\u5927\u578B\u9879\u76EE\u5206\u6790\u5931\u8D25",
|
|
13636
|
+
data: {
|
|
13637
|
+
projectUuid: result.projectUuid,
|
|
13638
|
+
statistics: result.statistics
|
|
13639
|
+
}
|
|
13640
|
+
})
|
|
13641
|
+
}
|
|
13642
|
+
],
|
|
13643
|
+
isError: true
|
|
13644
|
+
};
|
|
13645
|
+
} catch (error) {
|
|
13646
|
+
logger.error("\u5927\u578B\u9879\u76EE\u5206\u6790\u5931\u8D25", {
|
|
13647
|
+
error: error.message
|
|
13648
|
+
});
|
|
13649
|
+
return {
|
|
13650
|
+
content: [
|
|
13651
|
+
{
|
|
13652
|
+
type: "text",
|
|
13653
|
+
text: JSON.stringify({
|
|
13654
|
+
success: false,
|
|
13655
|
+
message: error.message || "\u5206\u6790\u8FC7\u7A0B\u4E2D\u53D1\u751F\u9519\u8BEF"
|
|
13656
|
+
})
|
|
13657
|
+
}
|
|
13658
|
+
],
|
|
13659
|
+
isError: true
|
|
13660
|
+
};
|
|
13661
|
+
}
|
|
13662
|
+
}
|
|
13663
|
+
};
|
|
13664
|
+
const analyzeMultiProjectsTool = {
|
|
13665
|
+
name: "analyze_multi_projects",
|
|
13666
|
+
description: "\u5206\u6790\u591A\u4E2A\u5FAE\u670D\u52A1\u9879\u76EE\u5E76\u5408\u5E76\u751F\u6210\u4E00\u4E2A\u6280\u672F\u89C4\u683C\u8BF4\u660E\u4E66\u3002\u9002\u7528\u4E8E\u62C6\u5206\u4E3A\u591A\u4E2A\u5FAE\u670D\u52A1\u7684\u5927\u578B\u9879\u76EE\uFF0C\u5C06\u6240\u6709\u5FAE\u670D\u52A1\u7684\u529F\u80FD\u7EDF\u4E00\u6574\u5408\u5230\u4E00\u4EFD\u6587\u6863\u4E2D\u3002",
|
|
13667
|
+
inputSchema: {
|
|
13668
|
+
projectPaths: arrayType(stringType().min(1)).min(1).describe("\u5FAE\u670D\u52A1\u9879\u76EE\u8DEF\u5F84\u5217\u8868\uFF0C\u6BCF\u4E2A\u8DEF\u5F84\u6307\u5411\u4E00\u4E2A\u72EC\u7ACB\u7684\u5FAE\u670D\u52A1\u9879\u76EE"),
|
|
13669
|
+
mergedProjectName: stringType().min(1).describe("\u5408\u5E76\u540E\u7684\u9879\u76EE\u540D\u79F0\uFF0C\u5C06\u663E\u793A\u5728\u6280\u672F\u89C4\u683C\u8BF4\u660E\u4E66\u7684\u6807\u9898\u4E2D"),
|
|
13670
|
+
mergedModuleName: stringType().optional().describe("\u5408\u5E76\u540E\u7684\u6A21\u5757\u540D\u79F0\uFF0C\u5982\u4E0D\u63D0\u4F9B\u5219\u4F7F\u7528\u9879\u76EE\u540D\u79F0"),
|
|
13671
|
+
outputDir: stringType().optional().describe("\u8F93\u51FA\u76EE\u5F55\uFF0C\u5982\u4E0D\u63D0\u4F9B\u5219\u4F7F\u7528\u7B2C\u4E00\u4E2A\u9879\u76EE\u7684\u9ED8\u8BA4\u76EE\u5F55"),
|
|
13672
|
+
addProjectPrefix: booleanType().optional().default(true).describe("\u662F\u5426\u4E3A\u6BCF\u4E2A\u5FAE\u670D\u52A1\u7684\u5185\u5BB9\u6DFB\u52A0\u9879\u76EE\u524D\u7F00\u6807\u8BC6\uFF0C\u4FBF\u4E8E\u533A\u5206\u6765\u6E90"),
|
|
13673
|
+
projectAliases: recordType(stringType(), stringType()).optional().describe("\u9879\u76EE\u522B\u540D\u6620\u5C04\uFF0Ckey\u4E3A\u9879\u76EE\u8DEF\u5F84\uFF0Cvalue\u4E3A\u663E\u793A\u540D\u79F0\u3002\u7528\u4E8E\u81EA\u5B9A\u4E49\u5FAE\u670D\u52A1\u7684\u663E\u793A\u540D\u79F0")
|
|
13674
|
+
},
|
|
13675
|
+
handler: async (args)=>{
|
|
13676
|
+
try {
|
|
13677
|
+
const { projectPaths, mergedProjectName, mergedModuleName, outputDir, addProjectPrefix = true, projectAliases } = args;
|
|
13678
|
+
if (!projectPaths || 0 === projectPaths.length) return {
|
|
13679
|
+
content: [
|
|
13680
|
+
{
|
|
13681
|
+
type: "text",
|
|
13682
|
+
text: JSON.stringify({
|
|
13683
|
+
success: false,
|
|
13684
|
+
message: "\u7F3A\u5C11\u5FC5\u586B\u53C2\u6570\uFF1AprojectPaths\uFF08\u81F3\u5C11\u9700\u8981\u4E00\u4E2A\u9879\u76EE\u8DEF\u5F84\uFF09"
|
|
13685
|
+
})
|
|
13686
|
+
}
|
|
13687
|
+
],
|
|
13688
|
+
isError: true
|
|
13689
|
+
};
|
|
13690
|
+
if (!mergedProjectName) return {
|
|
13691
|
+
content: [
|
|
13692
|
+
{
|
|
13693
|
+
type: "text",
|
|
13694
|
+
text: JSON.stringify({
|
|
13695
|
+
success: false,
|
|
13696
|
+
message: "\u7F3A\u5C11\u5FC5\u586B\u53C2\u6570\uFF1AmergedProjectName"
|
|
13697
|
+
})
|
|
13698
|
+
}
|
|
13699
|
+
],
|
|
13700
|
+
isError: true
|
|
13701
|
+
};
|
|
13702
|
+
logger.info(`\u{5F00}\u{59CB}\u{5206}\u{6790}\u{591A}\u{4E2A}\u{5FAE}\u{670D}\u{52A1}\u{9879}\u{76EE}`, {
|
|
13703
|
+
projectCount: projectPaths.length,
|
|
13704
|
+
mergedProjectName,
|
|
13705
|
+
projectPaths
|
|
13706
|
+
});
|
|
13707
|
+
const chapterProcessor = new ChapterProcessor({
|
|
13708
|
+
maxFilesPerBatch: 50,
|
|
13709
|
+
maxModulesPerChapter: 10,
|
|
13710
|
+
enableParallelProcessing: true,
|
|
13711
|
+
skipEmptyModules: true
|
|
13712
|
+
});
|
|
13713
|
+
const result = await chapterProcessor.processMultiProjects({
|
|
13714
|
+
projectPaths,
|
|
13715
|
+
mergedProjectName,
|
|
13716
|
+
mergedModuleName,
|
|
13717
|
+
outputDir,
|
|
13718
|
+
addProjectPrefix,
|
|
13719
|
+
projectAliases
|
|
13720
|
+
});
|
|
13721
|
+
if (result.success) return {
|
|
13722
|
+
content: [
|
|
13723
|
+
{
|
|
13724
|
+
type: "text",
|
|
13725
|
+
text: JSON.stringify({
|
|
13726
|
+
success: true,
|
|
13727
|
+
message: "\u591A\u5FAE\u670D\u52A1\u9879\u76EE\u5206\u6790\u5B8C\u6210\uFF0C\u7AE0\u8282\u5DF2\u5B58\u50A8\u5230\u6570\u636E\u5E93",
|
|
13728
|
+
data: {
|
|
13729
|
+
projectUuid: result.projectUuid,
|
|
13730
|
+
mergedProjectName: result.mergedProjectName,
|
|
13731
|
+
summary: {
|
|
13732
|
+
totalProjects: result.totalProjects,
|
|
13733
|
+
processedProjects: result.processedProjects,
|
|
13734
|
+
successfulProjects: result.projectResults.filter((p)=>p.success).length,
|
|
13735
|
+
failedProjects: result.projectResults.filter((p)=>!p.success).length
|
|
13736
|
+
},
|
|
13737
|
+
projectResults: result.projectResults.map((p)=>({
|
|
13738
|
+
projectPath: p.projectPath,
|
|
13739
|
+
projectName: p.projectName,
|
|
13740
|
+
success: p.success,
|
|
13741
|
+
errorMessage: p.errorMessage,
|
|
13742
|
+
statistics: p.statistics
|
|
13743
|
+
})),
|
|
13744
|
+
mergedStatistics: result.mergedStatistics,
|
|
13745
|
+
nextStep: `\u{8C03}\u{7528} render_final_document \u{5DE5}\u{5177}\u{FF0C}\u{4F7F}\u{7528} projectUuid: ${result.projectUuid} \u{751F}\u{6210}\u{6700}\u{7EC8}\u{7684}\u{5408}\u{5E76}\u{6587}\u{6863}`
|
|
13746
|
+
}
|
|
13747
|
+
})
|
|
13748
|
+
}
|
|
13749
|
+
]
|
|
13750
|
+
};
|
|
13751
|
+
return {
|
|
13752
|
+
content: [
|
|
13753
|
+
{
|
|
13754
|
+
type: "text",
|
|
13755
|
+
text: JSON.stringify({
|
|
13756
|
+
success: false,
|
|
13757
|
+
message: result.errorMessage || "\u591A\u9879\u76EE\u5206\u6790\u5931\u8D25",
|
|
13758
|
+
data: {
|
|
13759
|
+
projectUuid: result.projectUuid,
|
|
13760
|
+
projectResults: result.projectResults,
|
|
13761
|
+
mergedStatistics: result.mergedStatistics
|
|
13762
|
+
}
|
|
13763
|
+
})
|
|
13764
|
+
}
|
|
13765
|
+
],
|
|
13766
|
+
isError: true
|
|
13767
|
+
};
|
|
13768
|
+
} catch (error) {
|
|
13769
|
+
logger.error("\u591A\u9879\u76EE\u5206\u6790\u5931\u8D25", {
|
|
13770
|
+
error: error.message
|
|
13771
|
+
});
|
|
13772
|
+
return {
|
|
13773
|
+
content: [
|
|
13774
|
+
{
|
|
13775
|
+
type: "text",
|
|
13776
|
+
text: JSON.stringify({
|
|
13777
|
+
success: false,
|
|
13778
|
+
message: error.message || "\u5206\u6790\u8FC7\u7A0B\u4E2D\u53D1\u751F\u9519\u8BEF"
|
|
13779
|
+
})
|
|
13780
|
+
}
|
|
13781
|
+
],
|
|
13782
|
+
isError: true
|
|
13783
|
+
};
|
|
13784
|
+
}
|
|
13785
|
+
}
|
|
13786
|
+
};
|
|
13787
|
+
const renderFinalDocumentTool = {
|
|
13788
|
+
name: "render_final_document",
|
|
13789
|
+
description: "\u5C06\u6570\u636E\u5E93\u4E2D\u5B58\u50A8\u7684\u7AE0\u8282\u5408\u5E76\u5E76\u6E32\u67D3\u4E3A\u6700\u7EC8\u7684\u6280\u672F\u89C4\u683C\u8BF4\u660E\u4E66Word\u6587\u6863\u3002\u7528\u4E8E\u5927\u578B\u9879\u76EE\u7684\u6700\u7EC8\u6587\u6863\u751F\u6210\u3002",
|
|
11620
13790
|
inputSchema: {
|
|
11621
|
-
|
|
11622
|
-
|
|
11623
|
-
|
|
11624
|
-
|
|
11625
|
-
|
|
11626
|
-
month: stringType().optional().describe("\u6708\u4EFD\uFF0C\u9ED8\u8BA4\u5F53\u524D\u6708\u4EFD"),
|
|
11627
|
-
referDoc: stringType().optional().describe("\u53C2\u8003\u6587\u6863"),
|
|
11628
|
-
serviceInterfaceList: arrayType(ServiceInterfaceSchema).default([]).describe("\u670D\u52A1\u63A5\u53E3\u6E05\u5355"),
|
|
11629
|
-
designDetailList: arrayType(DesignDetailSchema).default([]).describe("\u670D\u52A1\u63A5\u53E3\u8BBE\u8BA1\u8BE6\u60C5"),
|
|
11630
|
-
tableInfoList: arrayType(TableInfoSchema).default([]).describe("\u6570\u636E\u5E93\u8868\u4FE1\u606F\u5217\u8868"),
|
|
11631
|
-
techSolution: TechSolutionSchema.optional().describe("\u6280\u672F\u65B9\u6848"),
|
|
11632
|
-
businessException: BusinessExceptionSchema.optional().describe("\u4E1A\u52A1\u5F02\u5E38\u5904\u7406"),
|
|
11633
|
-
appendix: AppendixSchema.optional().describe("\u9644\u5F55"),
|
|
11634
|
-
dtoDefinitions: recordType(stringType(), arrayType(objectType({
|
|
11635
|
-
name: stringType().optional().describe("\u5B57\u6BB5\u540D"),
|
|
11636
|
-
type: stringType().optional().describe("\u5B57\u6BB5\u7C7B\u578B"),
|
|
11637
|
-
required: stringType().optional().describe("\u662F\u5426\u5FC5\u586B"),
|
|
11638
|
-
description: stringType().optional().describe("\u5B57\u6BB5\u63CF\u8FF0")
|
|
11639
|
-
}))).optional().describe("DTO\u5B9A\u4E49\u6620\u5C04\uFF0C\u7528\u4E8E\u5C55\u5F00\u63A5\u53E3\u53C2\u6570\u4E2D\u7684DTO\u4E3A\u5177\u4F53\u5B57\u6BB5")
|
|
11640
|
-
}).describe("\u5B8C\u6574\u7684\u6280\u672F\u89C4\u683C\u6570\u636E")
|
|
13791
|
+
projectUuid: stringType().min(1).describe("\u9879\u76EEUUID\uFF0C\u7531 analyze_large_project \u5DE5\u5177\u8FD4\u56DE"),
|
|
13792
|
+
outputDir: stringType().optional().describe("\u8F93\u51FA\u76EE\u5F55\uFF0C\u5982\u4E0D\u63D0\u4F9B\u5219\u4F7F\u7528\u9879\u76EE\u9ED8\u8BA4\u76EE\u5F55"),
|
|
13793
|
+
includeEmptyChapters: booleanType().optional().default(false).describe("\u662F\u5426\u5305\u542B\u7A7A\u7AE0\u8282"),
|
|
13794
|
+
generateDefaultContent: booleanType().optional().default(true).describe("\u662F\u5426\u4E3A\u7A7A\u7AE0\u8282\u751F\u6210\u9ED8\u8BA4\u5185\u5BB9"),
|
|
13795
|
+
maxItemsPerChapter: numberType().optional().default(1000).describe("\u6BCF\u7AE0\u8282\u6700\u5927\u6761\u76EE\u6570")
|
|
11641
13796
|
},
|
|
11642
13797
|
handler: async (args)=>{
|
|
11643
13798
|
try {
|
|
11644
|
-
const {
|
|
11645
|
-
|
|
11646
|
-
if (!projectPath || !techSpecData) return {
|
|
13799
|
+
const { projectUuid, outputDir, includeEmptyChapters = false, generateDefaultContent = true, maxItemsPerChapter = 1000 } = args;
|
|
13800
|
+
if (!projectUuid) return {
|
|
11647
13801
|
content: [
|
|
11648
13802
|
{
|
|
11649
13803
|
type: "text",
|
|
11650
13804
|
text: JSON.stringify({
|
|
11651
13805
|
success: false,
|
|
11652
|
-
message: "\u7F3A\u5C11\u5FC5\u586B\u53C2\u6570"
|
|
13806
|
+
message: "\u7F3A\u5C11\u5FC5\u586B\u53C2\u6570\uFF1AprojectUuid"
|
|
11653
13807
|
})
|
|
11654
13808
|
}
|
|
11655
13809
|
],
|
|
11656
13810
|
isError: true
|
|
11657
13811
|
};
|
|
11658
|
-
|
|
11659
|
-
const
|
|
11660
|
-
|
|
11661
|
-
|
|
11662
|
-
|
|
11663
|
-
|
|
11664
|
-
|
|
11665
|
-
|
|
11666
|
-
|
|
11667
|
-
|
|
11668
|
-
|
|
11669
|
-
|
|
11670
|
-
|
|
11671
|
-
businessException: normalizedData.businessException || void 0,
|
|
11672
|
-
appendix: normalizedData.appendix || void 0
|
|
13812
|
+
logger.info(`\u{5F00}\u{59CB}\u{6E32}\u{67D3}\u{6700}\u{7EC8}\u{6587}\u{6863}: ${projectUuid}`);
|
|
13813
|
+
const project = await techSpecDbOperations.getTechSpecProject(projectUuid);
|
|
13814
|
+
if (!project) return {
|
|
13815
|
+
content: [
|
|
13816
|
+
{
|
|
13817
|
+
type: "text",
|
|
13818
|
+
text: JSON.stringify({
|
|
13819
|
+
success: false,
|
|
13820
|
+
message: `\u{9879}\u{76EE}\u{4E0D}\u{5B58}\u{5728}: ${projectUuid}`
|
|
13821
|
+
})
|
|
13822
|
+
}
|
|
13823
|
+
],
|
|
13824
|
+
isError: true
|
|
11673
13825
|
};
|
|
11674
|
-
const
|
|
11675
|
-
|
|
13826
|
+
const documentMerger = new DocumentMerger({
|
|
13827
|
+
includeEmptyChapters,
|
|
13828
|
+
generateDefaultContent,
|
|
13829
|
+
maxItemsPerChapter,
|
|
13830
|
+
enableChapterSummary: true
|
|
13831
|
+
});
|
|
13832
|
+
const result = await documentMerger.mergeAndRenderDocument(projectUuid, outputDir);
|
|
11676
13833
|
if (result.success) return {
|
|
11677
13834
|
content: [
|
|
11678
13835
|
{
|
|
@@ -11681,16 +13838,19 @@ ${requirement_description}
|
|
|
11681
13838
|
success: true,
|
|
11682
13839
|
message: "\u6280\u672F\u89C4\u683C\u8BF4\u660E\u4E66\u751F\u6210\u6210\u529F",
|
|
11683
13840
|
data: {
|
|
13841
|
+
projectUuid,
|
|
11684
13842
|
outputPath: result.outputPath,
|
|
11685
|
-
|
|
11686
|
-
|
|
11687
|
-
|
|
11688
|
-
|
|
11689
|
-
|
|
11690
|
-
|
|
11691
|
-
|
|
11692
|
-
|
|
11693
|
-
|
|
13843
|
+
projectInfo: {
|
|
13844
|
+
projectName: project.projectName,
|
|
13845
|
+
moduleName: project.moduleName,
|
|
13846
|
+
projectPath: project.projectPath
|
|
13847
|
+
},
|
|
13848
|
+
statistics: result.statistics,
|
|
13849
|
+
techSpecSummary: {
|
|
13850
|
+
serviceInterfaceCount: result.statistics.totalServiceInterfaces,
|
|
13851
|
+
designDetailCount: result.statistics.totalDesignDetails,
|
|
13852
|
+
tableCount: result.statistics.totalTables,
|
|
13853
|
+
chapterCount: result.statistics.totalChapters
|
|
11694
13854
|
}
|
|
11695
13855
|
}
|
|
11696
13856
|
})
|
|
@@ -11703,20 +13863,231 @@ ${requirement_description}
|
|
|
11703
13863
|
type: "text",
|
|
11704
13864
|
text: JSON.stringify({
|
|
11705
13865
|
success: false,
|
|
11706
|
-
message: result.
|
|
13866
|
+
message: result.errorMessage || "\u6587\u6863\u6E32\u67D3\u5931\u8D25",
|
|
13867
|
+
data: {
|
|
13868
|
+
projectUuid,
|
|
13869
|
+
statistics: result.statistics
|
|
13870
|
+
}
|
|
11707
13871
|
})
|
|
11708
13872
|
}
|
|
11709
13873
|
],
|
|
11710
13874
|
isError: true
|
|
11711
13875
|
};
|
|
11712
13876
|
} catch (error) {
|
|
13877
|
+
logger.error("\u6587\u6863\u6E32\u67D3\u5931\u8D25", {
|
|
13878
|
+
error: error.message
|
|
13879
|
+
});
|
|
11713
13880
|
return {
|
|
11714
13881
|
content: [
|
|
11715
13882
|
{
|
|
11716
13883
|
type: "text",
|
|
11717
13884
|
text: JSON.stringify({
|
|
11718
13885
|
success: false,
|
|
11719
|
-
message: error.message || "\
|
|
13886
|
+
message: error.message || "\u6E32\u67D3\u8FC7\u7A0B\u4E2D\u53D1\u751F\u9519\u8BEF"
|
|
13887
|
+
})
|
|
13888
|
+
}
|
|
13889
|
+
],
|
|
13890
|
+
isError: true
|
|
13891
|
+
};
|
|
13892
|
+
}
|
|
13893
|
+
}
|
|
13894
|
+
};
|
|
13895
|
+
const getProjectProgressTool = {
|
|
13896
|
+
name: "get_project_progress",
|
|
13897
|
+
description: "\u83B7\u53D6\u5927\u578B\u9879\u76EE\u5904\u7406\u8FDB\u5EA6\u548C\u72B6\u6001\u4FE1\u606F\u3002\u7528\u4E8E\u76D1\u63A7\u9879\u76EE\u5206\u6790\u548C\u6587\u6863\u751F\u6210\u7684\u8FDB\u5EA6\u3002",
|
|
13898
|
+
inputSchema: {
|
|
13899
|
+
projectUuid: stringType().min(1).describe("\u9879\u76EEUUID")
|
|
13900
|
+
},
|
|
13901
|
+
handler: async (args)=>{
|
|
13902
|
+
try {
|
|
13903
|
+
const { projectUuid } = args;
|
|
13904
|
+
if (!projectUuid) return {
|
|
13905
|
+
content: [
|
|
13906
|
+
{
|
|
13907
|
+
type: "text",
|
|
13908
|
+
text: JSON.stringify({
|
|
13909
|
+
success: false,
|
|
13910
|
+
message: "\u7F3A\u5C11\u5FC5\u586B\u53C2\u6570\uFF1AprojectUuid"
|
|
13911
|
+
})
|
|
13912
|
+
}
|
|
13913
|
+
],
|
|
13914
|
+
isError: true
|
|
13915
|
+
};
|
|
13916
|
+
const documentMerger = new DocumentMerger();
|
|
13917
|
+
const progressInfo = await documentMerger.getProjectProgress(projectUuid);
|
|
13918
|
+
return {
|
|
13919
|
+
content: [
|
|
13920
|
+
{
|
|
13921
|
+
type: "text",
|
|
13922
|
+
text: JSON.stringify({
|
|
13923
|
+
success: true,
|
|
13924
|
+
message: "\u9879\u76EE\u8FDB\u5EA6\u83B7\u53D6\u6210\u529F",
|
|
13925
|
+
data: {
|
|
13926
|
+
projectUuid,
|
|
13927
|
+
project: {
|
|
13928
|
+
projectName: progressInfo.project.projectName,
|
|
13929
|
+
moduleName: progressInfo.project.moduleName,
|
|
13930
|
+
status: progressInfo.project.status,
|
|
13931
|
+
createdAt: progressInfo.project.createdAt,
|
|
13932
|
+
updatedAt: progressInfo.project.updatedAt,
|
|
13933
|
+
completedAt: progressInfo.project.completedAt
|
|
13934
|
+
},
|
|
13935
|
+
progress: progressInfo.progress,
|
|
13936
|
+
statistics: progressInfo.statistics,
|
|
13937
|
+
isCompleted: "completed" === progressInfo.project.status,
|
|
13938
|
+
canRender: progressInfo.statistics.completedChapters > 0
|
|
13939
|
+
}
|
|
13940
|
+
})
|
|
13941
|
+
}
|
|
13942
|
+
]
|
|
13943
|
+
};
|
|
13944
|
+
} catch (error) {
|
|
13945
|
+
return {
|
|
13946
|
+
content: [
|
|
13947
|
+
{
|
|
13948
|
+
type: "text",
|
|
13949
|
+
text: JSON.stringify({
|
|
13950
|
+
success: false,
|
|
13951
|
+
message: error.message || "\u83B7\u53D6\u8FDB\u5EA6\u5931\u8D25"
|
|
13952
|
+
})
|
|
13953
|
+
}
|
|
13954
|
+
],
|
|
13955
|
+
isError: true
|
|
13956
|
+
};
|
|
13957
|
+
}
|
|
13958
|
+
}
|
|
13959
|
+
};
|
|
13960
|
+
const listTechSpecProjectsTool = {
|
|
13961
|
+
name: "list_tech_spec_projects",
|
|
13962
|
+
description: "\u5217\u51FA\u6240\u6709\u6280\u672F\u89C4\u683C\u8BF4\u660E\u4E66\u9879\u76EE\u53CA\u5176\u72B6\u6001\u3002\u7528\u4E8E\u67E5\u770B\u5386\u53F2\u9879\u76EE\u548C\u7BA1\u7406\u9879\u76EE\u3002",
|
|
13963
|
+
inputSchema: {
|
|
13964
|
+
status: stringType().optional().describe("\u8FC7\u6EE4\u72B6\u6001\uFF1Aanalyzing, generating, completed, failed"),
|
|
13965
|
+
limit: numberType().optional().default(20).describe("\u8FD4\u56DE\u6570\u91CF\u9650\u5236")
|
|
13966
|
+
},
|
|
13967
|
+
handler: async (args)=>{
|
|
13968
|
+
try {
|
|
13969
|
+
const { status, limit = 20 } = args;
|
|
13970
|
+
let projects = await techSpecDbOperations.getAllTechSpecProjects();
|
|
13971
|
+
if (status) projects = projects.filter((p)=>p.status === status);
|
|
13972
|
+
projects.sort((a, b)=>b.createdAt.getTime() - a.createdAt.getTime());
|
|
13973
|
+
projects = projects.slice(0, limit);
|
|
13974
|
+
const projectsWithStats = await Promise.all(projects.map(async (project)=>{
|
|
13975
|
+
try {
|
|
13976
|
+
const statistics = await techSpecDbOperations.getProjectStatistics(project.uuid);
|
|
13977
|
+
return {
|
|
13978
|
+
...project,
|
|
13979
|
+
statistics
|
|
13980
|
+
};
|
|
13981
|
+
} catch (error) {
|
|
13982
|
+
return {
|
|
13983
|
+
...project,
|
|
13984
|
+
statistics: null
|
|
13985
|
+
};
|
|
13986
|
+
}
|
|
13987
|
+
}));
|
|
13988
|
+
return {
|
|
13989
|
+
content: [
|
|
13990
|
+
{
|
|
13991
|
+
type: "text",
|
|
13992
|
+
text: JSON.stringify({
|
|
13993
|
+
success: true,
|
|
13994
|
+
message: `\u{627E}\u{5230} ${projectsWithStats.length} \u{4E2A}\u{9879}\u{76EE}`,
|
|
13995
|
+
data: {
|
|
13996
|
+
projects: projectsWithStats.map((p)=>({
|
|
13997
|
+
uuid: p.uuid,
|
|
13998
|
+
projectName: p.projectName,
|
|
13999
|
+
moduleName: p.moduleName,
|
|
14000
|
+
status: p.status,
|
|
14001
|
+
totalModules: p.totalModules,
|
|
14002
|
+
processedModules: p.processedModules,
|
|
14003
|
+
totalFiles: p.totalFiles,
|
|
14004
|
+
processedFiles: p.processedFiles,
|
|
14005
|
+
createdAt: p.createdAt,
|
|
14006
|
+
updatedAt: p.updatedAt,
|
|
14007
|
+
completedAt: p.completedAt,
|
|
14008
|
+
statistics: p.statistics
|
|
14009
|
+
})),
|
|
14010
|
+
totalCount: projectsWithStats.length
|
|
14011
|
+
}
|
|
14012
|
+
})
|
|
14013
|
+
}
|
|
14014
|
+
]
|
|
14015
|
+
};
|
|
14016
|
+
} catch (error) {
|
|
14017
|
+
return {
|
|
14018
|
+
content: [
|
|
14019
|
+
{
|
|
14020
|
+
type: "text",
|
|
14021
|
+
text: JSON.stringify({
|
|
14022
|
+
success: false,
|
|
14023
|
+
message: error.message || "\u83B7\u53D6\u9879\u76EE\u5217\u8868\u5931\u8D25"
|
|
14024
|
+
})
|
|
14025
|
+
}
|
|
14026
|
+
],
|
|
14027
|
+
isError: true
|
|
14028
|
+
};
|
|
14029
|
+
}
|
|
14030
|
+
}
|
|
14031
|
+
};
|
|
14032
|
+
const analyzeProjectStructureTool = {
|
|
14033
|
+
name: "analyze_project_structure",
|
|
14034
|
+
description: "\u4EC5\u5206\u6790\u9879\u76EE\u7ED3\u6784\uFF0C\u4E0D\u751F\u6210\u6587\u6863\u3002\u7528\u4E8E\u4E86\u89E3\u9879\u76EE\u7684\u6A21\u5757\u548C\u6587\u4EF6\u7EC4\u7EC7\u60C5\u51B5\u3002",
|
|
14035
|
+
inputSchema: {
|
|
14036
|
+
projectPath: stringType().min(1).describe(PROJECT_PATH_DESCRIPTION)
|
|
14037
|
+
},
|
|
14038
|
+
handler: async (args)=>{
|
|
14039
|
+
try {
|
|
14040
|
+
const { projectPath } = args;
|
|
14041
|
+
if (!projectPath) return {
|
|
14042
|
+
content: [
|
|
14043
|
+
{
|
|
14044
|
+
type: "text",
|
|
14045
|
+
text: JSON.stringify({
|
|
14046
|
+
success: false,
|
|
14047
|
+
message: "\u7F3A\u5C11\u5FC5\u586B\u53C2\u6570\uFF1AprojectPath"
|
|
14048
|
+
})
|
|
14049
|
+
}
|
|
14050
|
+
],
|
|
14051
|
+
isError: true
|
|
14052
|
+
};
|
|
14053
|
+
const analysis = await analyzeProject(projectPath);
|
|
14054
|
+
return {
|
|
14055
|
+
content: [
|
|
14056
|
+
{
|
|
14057
|
+
type: "text",
|
|
14058
|
+
text: JSON.stringify({
|
|
14059
|
+
success: true,
|
|
14060
|
+
message: "\u9879\u76EE\u7ED3\u6784\u5206\u6790\u5B8C\u6210",
|
|
14061
|
+
data: {
|
|
14062
|
+
projectName: analysis.projectName,
|
|
14063
|
+
projectPath: analysis.projectPath,
|
|
14064
|
+
statistics: analysis.statistics,
|
|
14065
|
+
modules: analysis.modules.map((m)=>({
|
|
14066
|
+
name: m.name,
|
|
14067
|
+
relativePath: m.relativePath,
|
|
14068
|
+
fileCount: m.files.length,
|
|
14069
|
+
fileTypes: {
|
|
14070
|
+
controller: m.files.filter((f)=>"controller" === f.type).length,
|
|
14071
|
+
service: m.files.filter((f)=>"service" === f.type).length,
|
|
14072
|
+
entity: m.files.filter((f)=>"entity" === f.type).length,
|
|
14073
|
+
dto: m.files.filter((f)=>"dto" === f.type).length,
|
|
14074
|
+
other: m.files.filter((f)=>"other" === f.type).length
|
|
14075
|
+
}
|
|
14076
|
+
})),
|
|
14077
|
+
availableModules: getModuleNames(analysis)
|
|
14078
|
+
}
|
|
14079
|
+
})
|
|
14080
|
+
}
|
|
14081
|
+
]
|
|
14082
|
+
};
|
|
14083
|
+
} catch (error) {
|
|
14084
|
+
return {
|
|
14085
|
+
content: [
|
|
14086
|
+
{
|
|
14087
|
+
type: "text",
|
|
14088
|
+
text: JSON.stringify({
|
|
14089
|
+
success: false,
|
|
14090
|
+
message: error.message || "\u9879\u76EE\u7ED3\u6784\u5206\u6790\u5931\u8D25"
|
|
11720
14091
|
})
|
|
11721
14092
|
}
|
|
11722
14093
|
],
|
|
@@ -11726,6 +14097,12 @@ ${requirement_description}
|
|
|
11726
14097
|
}
|
|
11727
14098
|
};
|
|
11728
14099
|
const techSpecGeneratorTools = [
|
|
14100
|
+
analyzeLargeProjectTool,
|
|
14101
|
+
analyzeMultiProjectsTool,
|
|
14102
|
+
renderFinalDocumentTool,
|
|
14103
|
+
getProjectProgressTool,
|
|
14104
|
+
listTechSpecProjectsTool,
|
|
14105
|
+
analyzeProjectStructureTool,
|
|
11729
14106
|
analyzeProjectContextTool,
|
|
11730
14107
|
collectServiceInterfacesTool,
|
|
11731
14108
|
generateInterfaceDesignsTool,
|