docs: add project code analysis plan
This commit is contained in:
@@ -0,0 +1,581 @@
|
||||
# Project Code Analysis Implementation Plan
|
||||
|
||||
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
||||
|
||||
**Goal:** Add project-bound code analysis that reads the current generated project source, calls the existing AI task service, saves history, and supports continue generation.
|
||||
|
||||
**Architecture:** Reuse the existing EasyCode front workbench, preview source service, AI async task table, and generation history table. Add a small backend code-analysis layer that builds a safe source summary from preview output and exposes semantic endpoints; add a Vue page that starts tasks, polls status, shows history, and renders/export reports.
|
||||
|
||||
**Tech Stack:** Spring Boot, MyBatis XML, existing DeepSeek AI service integration, Vue 3, Element Plus, node:test source assertions.
|
||||
|
||||
---
|
||||
|
||||
## File Map
|
||||
|
||||
- `ruoyi-generator/src/main/java/com/ruoyi/generator/domain/front/dto/GenerateCodeAnalysisRequest.java`: request fields for fresh and continue generation.
|
||||
- `ruoyi-generator/src/main/java/com/ruoyi/generator/domain/front/dto/CodeAnalysisResponse.java`: AI result payload and source snapshot metadata.
|
||||
- `ruoyi-generator/src/main/java/com/ruoyi/generator/domain/front/dto/CodeAnalysisSourceSummary.java`: safe code snapshot summary used by UI and prompt.
|
||||
- `ruoyi-generator/src/main/java/com/ruoyi/generator/domain/front/dto/CodeAnalysisHistoryResponse.java`: history item wrapper with parsed response.
|
||||
- `ruoyi-generator/src/main/java/com/ruoyi/generator/service/front/ProjectCodeAnalysisService.java`: collect preview source, filter files, build prompt context, list and load history.
|
||||
- `ruoyi-generator/src/main/java/com/ruoyi/generator/service/front/IAiGenerateService.java`: add `generateCodeAnalysis`.
|
||||
- `ruoyi-generator/src/main/java/com/ruoyi/generator/service/front/AiGenerateServiceImpl.java`: build code-analysis prompt and parse AI response.
|
||||
- `ruoyi-generator/src/main/java/com/ruoyi/generator/service/front/AiGenerationTaskServiceImpl.java`: allow `code_analysis`.
|
||||
- `ruoyi-generator/src/main/java/com/ruoyi/generator/service/front/AiGenerationTaskWorker.java`: execute `code_analysis` tasks.
|
||||
- `ruoyi-generator/src/main/resources/mapper/front/FrontProjectGenerationMapper.xml`: add user/project scoped generation lookup.
|
||||
- `ruoyi-generator/src/main/java/com/ruoyi/generator/mapper/front/FrontProjectGenerationMapper.java`: expose lookup method.
|
||||
- `ruoyi-admin/src/main/java/com/ruoyi/web/controller/front/FrontProjectController.java`: add code-analysis semantic endpoints.
|
||||
- `easycode-web/src/api/project.js`: add code-analysis API wrappers.
|
||||
- `easycode-web/src/router/index.js`: add `/project/:projectId/code-analysis`.
|
||||
- `easycode-web/src/views/CodeAnalysisView.vue`: page UI, history, task polling, continue generation, report export.
|
||||
- `easycode-web/src/views/codeAnalysisView.test.mjs`: front-end source assertions.
|
||||
- `easycode-web/src/views/ProjectListView.vue`, `PreviewView.vue`, `GenerateView.vue`: add project-level entry buttons.
|
||||
- Relevant backend tests under `ruoyi-generator/src/test/java/com/ruoyi/generator/service/front/` and `ruoyi-admin/src/test/java/com/ruoyi/web/controller/front/`.
|
||||
|
||||
---
|
||||
|
||||
### Task 1: Backend DTOs and Source Summary Service
|
||||
|
||||
**Files:**
|
||||
- Create: `ruoyi-generator/src/main/java/com/ruoyi/generator/domain/front/dto/GenerateCodeAnalysisRequest.java`
|
||||
- Create: `ruoyi-generator/src/main/java/com/ruoyi/generator/domain/front/dto/CodeAnalysisResponse.java`
|
||||
- Create: `ruoyi-generator/src/main/java/com/ruoyi/generator/domain/front/dto/CodeAnalysisSourceSummary.java`
|
||||
- Create: `ruoyi-generator/src/main/java/com/ruoyi/generator/service/front/ProjectCodeAnalysisService.java`
|
||||
- Test: `ruoyi-generator/src/test/java/com/ruoyi/generator/service/front/ProjectCodeAnalysisServiceTest.java`
|
||||
|
||||
- [ ] **Step 1: Write failing source summary tests**
|
||||
|
||||
Create `ProjectCodeAnalysisServiceTest.java` with tests that use a fake `IFrontProjectPreviewService` returning nested nodes and file contents. Include these behaviors:
|
||||
|
||||
```java
|
||||
@Test
|
||||
public void shouldCollectAllowedPreviewFilesAndSkipBuildArtifacts() {
|
||||
ProjectCodeAnalysisService service = newServiceWithPreview(
|
||||
node("backend:src/main/java/com/example/UserController.java", "UserController.java", "file"),
|
||||
node("backend:target/classes/App.class", "App.class", "file"),
|
||||
node("frontend:node_modules/vue/index.js", "index.js", "file"));
|
||||
|
||||
CodeAnalysisSourceSummary summary = service.buildSourceSummary(1L, 10L);
|
||||
|
||||
assertEquals(1, summary.getAnalyzedFileCount());
|
||||
assertTrue(summary.getIncludedFiles().get(0).getPath().contains("UserController.java"));
|
||||
assertTrue(summary.getSkippedFiles().stream().anyMatch(file -> file.getReason().contains("构建产物")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldTrimLargeFilesAndKeepSummaryUsable() {
|
||||
String large = repeat("public void method() {}\n", 7000);
|
||||
ProjectCodeAnalysisService service = newServiceWithContent("backend:src/main/java/App.java", large);
|
||||
|
||||
CodeAnalysisSourceSummary summary = service.buildSourceSummary(1L, 10L);
|
||||
|
||||
assertEquals(1, summary.getAnalyzedFileCount());
|
||||
assertTrue(summary.getIncludedFiles().get(0).getContent().length() < large.length());
|
||||
assertTrue(summary.getWarnings().stream().anyMatch(value -> value.contains("超过 100KB")));
|
||||
}
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Run tests and verify RED**
|
||||
|
||||
Run: `mvn -pl ruoyi-generator -Dtest=ProjectCodeAnalysisServiceTest test`
|
||||
|
||||
Expected: compile fails because `ProjectCodeAnalysisService` and DTO classes do not exist.
|
||||
|
||||
- [ ] **Step 3: Add DTOs**
|
||||
|
||||
Implement DTOs with JavaBean getters/setters:
|
||||
|
||||
```java
|
||||
public class GenerateCodeAnalysisRequest {
|
||||
private String mode;
|
||||
private Long previousGenerationId;
|
||||
private String previousMarkdown;
|
||||
private String extraRequirements;
|
||||
// getters and setters
|
||||
}
|
||||
```
|
||||
|
||||
`CodeAnalysisResponse` fields: `title`, `markdown`, `sections`, `sourceSnapshot`, `warnings`.
|
||||
|
||||
`CodeAnalysisSourceSummary` fields: `projectId`, `fileCount`, `analyzedFileCount`, `skippedFileCount`, `charCount`, `estimatedTokens`, `includedFiles`, `skippedFiles`, `warnings`, `promptContext`. Add nested static classes `SourceFile` and `SkippedFile`.
|
||||
|
||||
- [ ] **Step 4: Implement minimal source summary service**
|
||||
|
||||
`ProjectCodeAnalysisService.buildSourceSummary(userId, projectId)` should:
|
||||
|
||||
- call `frontProjectPreviewService.getStructure` for `backend`, `frontend`, `admin_frontend`, `sql`;
|
||||
- walk `children`;
|
||||
- include only configured code extensions;
|
||||
- skip `node_modules`, `target`, `dist`, `.git`, `.idea`;
|
||||
- create `PreviewFileRequest` with `templateType`, `nodeId`, `tableId`, `category`;
|
||||
- read `content` from `frontProjectPreviewService.getFileContent`;
|
||||
- trim content above `100 * 1024` characters;
|
||||
- build `promptContext` from file path headings and content.
|
||||
|
||||
- [ ] **Step 5: Run tests and verify GREEN**
|
||||
|
||||
Run: `mvn -pl ruoyi-generator -Dtest=ProjectCodeAnalysisServiceTest test`
|
||||
|
||||
Expected: tests pass.
|
||||
|
||||
- [ ] **Step 6: Commit**
|
||||
|
||||
```bash
|
||||
git add ruoyi-generator/src/main/java/com/ruoyi/generator/domain/front/dto/GenerateCodeAnalysisRequest.java \
|
||||
ruoyi-generator/src/main/java/com/ruoyi/generator/domain/front/dto/CodeAnalysisResponse.java \
|
||||
ruoyi-generator/src/main/java/com/ruoyi/generator/domain/front/dto/CodeAnalysisSourceSummary.java \
|
||||
ruoyi-generator/src/main/java/com/ruoyi/generator/service/front/ProjectCodeAnalysisService.java \
|
||||
ruoyi-generator/src/test/java/com/ruoyi/generator/service/front/ProjectCodeAnalysisServiceTest.java
|
||||
git commit -m "feat: collect project source for code analysis"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Task 2: AI Task Type and Generation
|
||||
|
||||
**Files:**
|
||||
- Modify: `ruoyi-generator/src/main/java/com/ruoyi/generator/service/front/IAiGenerateService.java`
|
||||
- Modify: `ruoyi-generator/src/main/java/com/ruoyi/generator/service/front/AiGenerateServiceImpl.java`
|
||||
- Modify: `ruoyi-generator/src/main/java/com/ruoyi/generator/service/front/AiGenerationTaskServiceImpl.java`
|
||||
- Modify: `ruoyi-generator/src/main/java/com/ruoyi/generator/service/front/AiGenerationTaskWorker.java`
|
||||
- Test: `ruoyi-generator/src/test/java/com/ruoyi/generator/service/front/AiGenerationTaskServiceImplTest.java`
|
||||
- Test: `ruoyi-generator/src/test/java/com/ruoyi/generator/service/front/AiGenerationTaskWorkerTest.java`
|
||||
- Test: `ruoyi-generator/src/test/java/com/ruoyi/generator/service/front/AiGenerateServiceImplTest.java`
|
||||
|
||||
- [ ] **Step 1: Write failing task acceptance tests**
|
||||
|
||||
Add assertions that `code_analysis` is accepted:
|
||||
|
||||
```java
|
||||
@Test
|
||||
public void createTaskShouldAcceptCodeAnalysisType() {
|
||||
AiGenerationTaskCreateRequest request = new AiGenerationTaskCreateRequest();
|
||||
request.setGenerateType("code_analysis");
|
||||
|
||||
AiGenerationTaskStatusResponse response = service.createTask(1L, 100L, request);
|
||||
|
||||
assertEquals("code_analysis", response.getGenerateType());
|
||||
assertEquals("QUEUED", response.getStatus());
|
||||
}
|
||||
```
|
||||
|
||||
Add worker test verifying dispatch calls `generateCodeAnalysis`:
|
||||
|
||||
```java
|
||||
@Test
|
||||
public void workerShouldExecuteCodeAnalysisTask() {
|
||||
AiGenerationTask task = queuedTask("code_analysis");
|
||||
mapper.insertAiGenerationTask(task);
|
||||
|
||||
worker.processTask(task.getTaskId());
|
||||
|
||||
assertTrue(aiGenerateService.codeAnalysisCalled);
|
||||
assertEquals("SUCCEEDED", mapper.selectAiGenerationTaskById(task.getTaskId()).getStatus());
|
||||
}
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Run tests and verify RED**
|
||||
|
||||
Run: `mvn -pl ruoyi-generator -Dtest=AiGenerationTaskServiceImplTest,AiGenerationTaskWorkerTest test`
|
||||
|
||||
Expected: unsupported generate type or missing interface method.
|
||||
|
||||
- [ ] **Step 3: Add interface and task dispatch**
|
||||
|
||||
Add to `IAiGenerateService`:
|
||||
|
||||
```java
|
||||
CodeAnalysisResponse generateCodeAnalysis(Long userId, Long projectId, GenerateCodeAnalysisRequest request);
|
||||
```
|
||||
|
||||
Allow `code_analysis` in `AiGenerationTaskServiceImpl.validateRequest()`.
|
||||
|
||||
In `AiGenerationTaskWorker.execute()` add:
|
||||
|
||||
```java
|
||||
if ("code_analysis".equals(task.getGenerateType())) {
|
||||
return aiGenerateService.generateCodeAnalysis(task.getUserId(), task.getProjectId(), toCodeAnalysisRequest(request));
|
||||
}
|
||||
```
|
||||
|
||||
Add `toCodeAnalysisRequest()` mapping `mode`, `previousGenerationId`, `previousMarkdown`, `extraRequirements`.
|
||||
|
||||
- [ ] **Step 4: Add prompt generation test**
|
||||
|
||||
In `AiGenerateServiceImplTest`, assert prompt contains fixed sections and source context:
|
||||
|
||||
```java
|
||||
@Test
|
||||
public void codeAnalysisPromptShouldRequireFixedSectionsAndUseSourceSummary() {
|
||||
CodeAnalysisResponse response = service.generateCodeAnalysis(1L, 100L, new GenerateCodeAnalysisRequest());
|
||||
|
||||
String prompt = deepSeekClient.lastPrompt();
|
||||
assertTrue(prompt.contains("项目概述与技术栈"));
|
||||
assertTrue(prompt.contains("系统架构与核心模块"));
|
||||
assertTrue(prompt.contains("核心业务流程"));
|
||||
assertTrue(prompt.contains("数据库设计"));
|
||||
assertTrue(prompt.contains("答辩准备"));
|
||||
assertTrue(prompt.contains("不要编造未出现的模块"));
|
||||
}
|
||||
```
|
||||
|
||||
- [ ] **Step 5: Implement AI generation method**
|
||||
|
||||
In `AiGenerateServiceImpl.generateCodeAnalysis()`:
|
||||
|
||||
- call `projectCodeAnalysisService.buildSourceSummary(userId, projectId)`;
|
||||
- throw `ServiceException("请先生成源码预览后再进行代码解读")` if no analyzed files;
|
||||
- build prompt with fixed sections and `summary.getPromptContext()`;
|
||||
- include previous markdown when `mode = continue`;
|
||||
- parse AI markdown into `CodeAnalysisResponse`;
|
||||
- attach `sourceSnapshot` and warnings.
|
||||
|
||||
- [ ] **Step 6: Run tests and verify GREEN**
|
||||
|
||||
Run: `mvn -pl ruoyi-generator -Dtest=AiGenerationTaskServiceImplTest,AiGenerationTaskWorkerTest,AiGenerateServiceImplTest test`
|
||||
|
||||
Expected: tests pass.
|
||||
|
||||
- [ ] **Step 7: Commit**
|
||||
|
||||
```bash
|
||||
git add ruoyi-generator/src/main/java/com/ruoyi/generator/service/front/IAiGenerateService.java \
|
||||
ruoyi-generator/src/main/java/com/ruoyi/generator/service/front/AiGenerateServiceImpl.java \
|
||||
ruoyi-generator/src/main/java/com/ruoyi/generator/service/front/AiGenerationTaskServiceImpl.java \
|
||||
ruoyi-generator/src/main/java/com/ruoyi/generator/service/front/AiGenerationTaskWorker.java \
|
||||
ruoyi-generator/src/test/java/com/ruoyi/generator/service/front/AiGenerationTaskServiceImplTest.java \
|
||||
ruoyi-generator/src/test/java/com/ruoyi/generator/service/front/AiGenerationTaskWorkerTest.java \
|
||||
ruoyi-generator/src/test/java/com/ruoyi/generator/service/front/AiGenerateServiceImplTest.java
|
||||
git commit -m "feat: run code analysis through ai tasks"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Task 3: History and Controller Endpoints
|
||||
|
||||
**Files:**
|
||||
- Create: `ruoyi-generator/src/main/java/com/ruoyi/generator/domain/front/dto/CodeAnalysisHistoryResponse.java`
|
||||
- Modify: `ruoyi-generator/src/main/java/com/ruoyi/generator/mapper/front/FrontProjectGenerationMapper.java`
|
||||
- Modify: `ruoyi-generator/src/main/resources/mapper/front/FrontProjectGenerationMapper.xml`
|
||||
- Modify: `ruoyi-generator/src/main/java/com/ruoyi/generator/service/front/ProjectCodeAnalysisService.java`
|
||||
- Modify: `ruoyi-admin/src/main/java/com/ruoyi/web/controller/front/FrontProjectController.java`
|
||||
- Test: `ruoyi-generator/src/test/java/com/ruoyi/generator/service/front/ProjectCodeAnalysisServiceTest.java`
|
||||
|
||||
- [ ] **Step 1: Write failing history tests**
|
||||
|
||||
Add tests:
|
||||
|
||||
```java
|
||||
@Test
|
||||
public void historyShouldOnlyReturnCodeAnalysisRecordsForOwnedProject() {
|
||||
List<CodeAnalysisHistoryResponse> history = service.listHistory(1L, 100L);
|
||||
|
||||
assertTrue(history.stream().allMatch(item -> "code_analysis".equals(item.getGenerateType())));
|
||||
assertTrue(history.stream().allMatch(item -> Long.valueOf(100L).equals(item.getProjectId())));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getHistoryDetailShouldRejectOtherProjectRecord() {
|
||||
assertThrows(ServiceException.class, () -> service.getHistoryDetail(1L, 100L, 999L));
|
||||
}
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Run tests and verify RED**
|
||||
|
||||
Run: `mvn -pl ruoyi-generator -Dtest=ProjectCodeAnalysisServiceTest test`
|
||||
|
||||
Expected: missing history DTO/service methods.
|
||||
|
||||
- [ ] **Step 3: Add mapper lookup**
|
||||
|
||||
Add mapper method:
|
||||
|
||||
```java
|
||||
FrontProjectGeneration selectGenerationForUser(@Param("userId") Long userId,
|
||||
@Param("projectId") Long projectId, @Param("generationId") Long generationId);
|
||||
```
|
||||
|
||||
Add XML select:
|
||||
|
||||
```xml
|
||||
<select id="selectGenerationForUser" resultMap="FrontProjectGenerationResult">
|
||||
<include refid="selectFrontProjectGenerationVo"/>
|
||||
where user_id = #{userId}
|
||||
and project_id = #{projectId}
|
||||
and generation_id = #{generationId}
|
||||
</select>
|
||||
```
|
||||
|
||||
- [ ] **Step 4: Implement history service methods**
|
||||
|
||||
Add `listHistory(userId, projectId)`, `getHistoryDetail(userId, projectId, generationId)`, `createTaskRequest(...)`, and `createContinueTaskRequest(...)` to `ProjectCodeAnalysisService`. Filter list results in Java to `generateType = code_analysis` if reusing `selectGenerationsByProjectId`.
|
||||
|
||||
- [ ] **Step 5: Add controller endpoints**
|
||||
|
||||
In `FrontProjectController` add:
|
||||
|
||||
```java
|
||||
@GetMapping("/{projectId}/code-analysis/source-summary")
|
||||
public AjaxResult codeAnalysisSourceSummary(@PathVariable Long projectId) {
|
||||
Long userId = SecurityUtils.getUserId();
|
||||
return success(projectCodeAnalysisService.buildSourceSummary(userId, projectId));
|
||||
}
|
||||
```
|
||||
|
||||
Add history/detail/task/continue endpoints. Task endpoints call `aiGenerationTaskService.createTask(userId, projectId, requestFromService)`.
|
||||
|
||||
- [ ] **Step 6: Run tests and verify GREEN**
|
||||
|
||||
Run: `mvn -pl ruoyi-generator -Dtest=ProjectCodeAnalysisServiceTest test`
|
||||
|
||||
Expected: tests pass.
|
||||
|
||||
- [ ] **Step 7: Commit**
|
||||
|
||||
```bash
|
||||
git add ruoyi-generator/src/main/java/com/ruoyi/generator/domain/front/dto/CodeAnalysisHistoryResponse.java \
|
||||
ruoyi-generator/src/main/java/com/ruoyi/generator/mapper/front/FrontProjectGenerationMapper.java \
|
||||
ruoyi-generator/src/main/resources/mapper/front/FrontProjectGenerationMapper.xml \
|
||||
ruoyi-generator/src/main/java/com/ruoyi/generator/service/front/ProjectCodeAnalysisService.java \
|
||||
ruoyi-admin/src/main/java/com/ruoyi/web/controller/front/FrontProjectController.java \
|
||||
ruoyi-generator/src/test/java/com/ruoyi/generator/service/front/ProjectCodeAnalysisServiceTest.java
|
||||
git commit -m "feat: expose project code analysis history"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Task 4: Frontend API, Routing, and Page Skeleton
|
||||
|
||||
**Files:**
|
||||
- Modify: `easycode-web/src/api/project.js`
|
||||
- Modify: `easycode-web/src/router/index.js`
|
||||
- Create: `easycode-web/src/views/CodeAnalysisView.vue`
|
||||
- Create: `easycode-web/src/views/codeAnalysisView.test.mjs`
|
||||
|
||||
- [ ] **Step 1: Write failing frontend source tests**
|
||||
|
||||
Create `codeAnalysisView.test.mjs`:
|
||||
|
||||
```js
|
||||
test('code analysis route and page expose core controls', () => {
|
||||
const router = readSource('../router/index.js')
|
||||
const view = readSource('CodeAnalysisView.vue')
|
||||
const api = readSource('../api/project.js')
|
||||
|
||||
assert.equal(router.includes("path: '/project/:projectId/code-analysis'"), true)
|
||||
assert.equal(router.includes("name: 'code-analysis'"), true)
|
||||
assert.equal(view.includes('章节导航'), true)
|
||||
assert.equal(view.includes('开始 AI 解读'), true)
|
||||
assert.equal(view.includes('继续生成'), true)
|
||||
assert.equal(view.includes('历史'), true)
|
||||
assert.equal(api.includes('getCodeAnalysisSourceSummary'), true)
|
||||
})
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Run test and verify RED**
|
||||
|
||||
Run: `node --test easycode-web/src/views/codeAnalysisView.test.mjs`
|
||||
|
||||
Expected: file missing or assertions fail.
|
||||
|
||||
- [ ] **Step 3: Add API wrappers**
|
||||
|
||||
Add to `project.js`:
|
||||
|
||||
```js
|
||||
export function getCodeAnalysisSourceSummary(projectId) { ... }
|
||||
export function listCodeAnalysisHistory(projectId) { ... }
|
||||
export function getCodeAnalysisHistory(projectId, generationId) { ... }
|
||||
export function createCodeAnalysisTask(projectId, data) { ... }
|
||||
export function continueCodeAnalysisTask(projectId, data) { ... }
|
||||
```
|
||||
|
||||
- [ ] **Step 4: Add route**
|
||||
|
||||
Import `CodeAnalysisView` and add route with `requiresAuth: true`.
|
||||
|
||||
- [ ] **Step 5: Add page skeleton**
|
||||
|
||||
Create page with:
|
||||
|
||||
- `projectId` from route;
|
||||
- `project`, `sourceSummary`, `history`, `activeTask`, `reportMarkdown`;
|
||||
- buttons for start, continue, refresh, history;
|
||||
- empty state when no report;
|
||||
- tabs for preview/edit;
|
||||
- history drawer placeholder.
|
||||
|
||||
- [ ] **Step 6: Run frontend test and verify GREEN**
|
||||
|
||||
Run: `node --test easycode-web/src/views/codeAnalysisView.test.mjs`
|
||||
|
||||
Expected: tests pass.
|
||||
|
||||
- [ ] **Step 7: Commit**
|
||||
|
||||
```bash
|
||||
git add easycode-web/src/api/project.js easycode-web/src/router/index.js \
|
||||
easycode-web/src/views/CodeAnalysisView.vue easycode-web/src/views/codeAnalysisView.test.mjs
|
||||
git commit -m "feat: add code analysis page shell"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Task 5: Frontend Task Polling, History, Continue, and Export
|
||||
|
||||
**Files:**
|
||||
- Modify: `easycode-web/src/views/CodeAnalysisView.vue`
|
||||
- Test: `easycode-web/src/views/codeAnalysisView.test.mjs`
|
||||
|
||||
- [ ] **Step 1: Add failing tests for behavior markers**
|
||||
|
||||
Extend source test:
|
||||
|
||||
```js
|
||||
assert.equal(view.includes('function waitForCodeAnalysisTask'), true)
|
||||
assert.equal(view.includes('continueCodeAnalysisTask'), true)
|
||||
assert.equal(view.includes('listCodeAnalysisHistory'), true)
|
||||
assert.equal(view.includes('downloadMarkdown'), true)
|
||||
assert.equal(view.includes('downloadWordDoc'), true)
|
||||
assert.equal(view.includes('renderMarkdown'), true)
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Run test and verify RED**
|
||||
|
||||
Run: `node --test easycode-web/src/views/codeAnalysisView.test.mjs`
|
||||
|
||||
Expected: missing function markers.
|
||||
|
||||
- [ ] **Step 3: Implement task polling**
|
||||
|
||||
Use existing `getAiTask(projectId, taskId)` with interval or async loop. On success parse `resultPayload` JSON and set report/history. On failed show error.
|
||||
|
||||
- [ ] **Step 4: Implement history loading**
|
||||
|
||||
Load history on mount, pick first successful item with parsed `response.markdown`, and allow drawer selection.
|
||||
|
||||
- [ ] **Step 5: Implement continue generation**
|
||||
|
||||
When continuing:
|
||||
|
||||
- use current edited markdown if present;
|
||||
- fallback to latest successful history markdown;
|
||||
- call `continueCodeAnalysisTask(projectId, { previousGenerationId, previousMarkdown })`;
|
||||
- poll resulting task.
|
||||
|
||||
- [ ] **Step 6: Implement exports**
|
||||
|
||||
Reuse `saveBlob` and `renderMarkdown`. Markdown filename: `${projectName || 'code-analysis'}-代码解读报告.md`. Word compatible filename: `.doc`.
|
||||
|
||||
- [ ] **Step 7: Run test and verify GREEN**
|
||||
|
||||
Run: `node --test easycode-web/src/views/codeAnalysisView.test.mjs`
|
||||
|
||||
Expected: tests pass.
|
||||
|
||||
- [ ] **Step 8: Commit**
|
||||
|
||||
```bash
|
||||
git add easycode-web/src/views/CodeAnalysisView.vue easycode-web/src/views/codeAnalysisView.test.mjs
|
||||
git commit -m "feat: complete code analysis report workflow"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Task 6: Project Entry Points and Verification
|
||||
|
||||
**Files:**
|
||||
- Modify: `easycode-web/src/views/ProjectListView.vue`
|
||||
- Modify: `easycode-web/src/views/projectListView.test.mjs`
|
||||
- Modify: `easycode-web/src/views/PreviewView.vue`
|
||||
- Modify: `easycode-web/src/views/previewView.test.mjs`
|
||||
- Modify: `easycode-web/src/views/GenerateView.vue`
|
||||
- Modify: `easycode-web/src/views/generateView.test.mjs`
|
||||
|
||||
- [ ] **Step 1: Add failing entry tests**
|
||||
|
||||
Project list test:
|
||||
|
||||
```js
|
||||
assert.equal(source.includes('el-tooltip content="代码解读"'), true)
|
||||
assert.equal(source.includes('aria-label="代码解读"'), true)
|
||||
assert.equal(source.includes('openCodeAnalysis'), true)
|
||||
```
|
||||
|
||||
Preview test:
|
||||
|
||||
```js
|
||||
assert.equal(source.includes('代码解读'), true)
|
||||
assert.equal(source.includes('openCodeAnalysis'), true)
|
||||
assert.equal(source.includes('`/project/${projectId.value}/code-analysis`'), true)
|
||||
```
|
||||
|
||||
Generate test:
|
||||
|
||||
```js
|
||||
assert.equal(source.includes('打开代码解读'), true)
|
||||
assert.equal(source.includes('/code-analysis'), true)
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Run tests and verify RED**
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
node --test easycode-web/src/views/projectListView.test.mjs
|
||||
node --test easycode-web/src/views/previewView.test.mjs
|
||||
node --test easycode-web/src/views/generateView.test.mjs
|
||||
```
|
||||
|
||||
Expected: assertions fail.
|
||||
|
||||
- [ ] **Step 3: Add entry buttons**
|
||||
|
||||
Project list: import `Reading` or another Element Plus icon and add compact icon button that routes to `/project/${projectId}/code-analysis`.
|
||||
|
||||
Preview: add toolbar button near download.
|
||||
|
||||
Generate: add generated result action after preview/download where a project id is available.
|
||||
|
||||
- [ ] **Step 4: Run tests and verify GREEN**
|
||||
|
||||
Run the three node tests again.
|
||||
|
||||
Expected: tests pass.
|
||||
|
||||
- [ ] **Step 5: Run targeted backend tests**
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
mvn -pl ruoyi-generator -Dtest=ProjectCodeAnalysisServiceTest,AiGenerationTaskServiceImplTest,AiGenerationTaskWorkerTest,AiGenerateServiceImplTest test
|
||||
```
|
||||
|
||||
Expected: tests pass.
|
||||
|
||||
- [ ] **Step 6: Run frontend build check**
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
cd easycode-web
|
||||
npm run build
|
||||
```
|
||||
|
||||
Expected: Vite build succeeds.
|
||||
|
||||
- [ ] **Step 7: Commit**
|
||||
|
||||
```bash
|
||||
git add easycode-web/src/views/ProjectListView.vue easycode-web/src/views/projectListView.test.mjs \
|
||||
easycode-web/src/views/PreviewView.vue easycode-web/src/views/previewView.test.mjs \
|
||||
easycode-web/src/views/GenerateView.vue easycode-web/src/views/generateView.test.mjs
|
||||
git commit -m "feat: add project code analysis entry points"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Self-Review
|
||||
|
||||
- Spec coverage: the plan covers no ZIP upload, project-bound source preview collection, AI task integration, history, continue generation, report UI, project entry points, and verification.
|
||||
- No placeholders: task steps include concrete files, method names, commands, and expected outputs.
|
||||
- Type consistency: `GenerateCodeAnalysisRequest`, `CodeAnalysisResponse`, `CodeAnalysisSourceSummary`, and `code_analysis` are introduced before later tasks reference them.
|
||||
Reference in New Issue
Block a user