# Architecture Diagram DSL Editor 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:** Replace the current generic architecture graph in the EasyCode diagram center with a DSL-driven layered architecture diagram editor. **Architecture:** Add a pure frontend utility module that generates default DSL, parses DSL, computes layered SVG layout, and builds export SVG. Update `DiagramCenterView.vue` to show a dedicated architecture editor for `activeDiagram === 'architecture'`, reusing the existing project/database load flow and `front_project_diagram` save endpoint. **Tech Stack:** Vue 3 Composition API, Vite, Element Plus, browser SVG/Canvas export, Node-based frontend utility tests. --- ## File Structure - Create `easycode-web/src/utils/architectureDiagram.js`: pure functions for default DSL generation, DSL parsing, layout, and SVG export. - Create `easycode-web/src/utils/architectureDiagram.test.mjs`: Node tests for generation, parsing, layout stats, and SVG export. - Modify `easycode-web/src/views/DiagramCenterView.vue`: render the architecture editor, bind DSL state, save/restore `architecture` diagrams, and export SVG/PNG. ## Task 1: Architecture Diagram Utility **Files:** - Create: `easycode-web/src/utils/architectureDiagram.js` - Create: `easycode-web/src/utils/architectureDiagram.test.mjs` - [ ] **Step 1: Write tests for default DSL and parsing** Create `easycode-web/src/utils/architectureDiagram.test.mjs` with tests that import: ```js import assert from 'node:assert/strict' import { buildArchitectureDiagram, buildArchitectureExportSvg, buildDefaultArchitectureDsl, parseArchitectureDsl } from './architectureDiagram.js' ``` Include a sample project: ```js const project = { projectName: '选课系统', frontFramework: 'Vue 3', backFramework: 'Spring Boot', appBlueprint: JSON.stringify({ roles: [ { name: '学生', permissions: ['选课', '查成绩'] }, { name: '教师', permissions: ['课程管理', '成绩录入'] } ], frontendMenus: [{ name: '选课大厅' }], adminMenus: [{ name: '课程管理' }, { name: '数据统计' }] }) } const database = { tables: [ { tableName: 'course', tableComment: '课程表' }, { tableName: 'student_course', tableComment: '选课记录' } ] } ``` Assert that: ```js const dsl = buildDefaultArchitectureDsl(project, database) assert.match(dsl, /用户层/) assert.match(dsl, /表现层 - Vue 3/) assert.match(dsl, /数据层/) assert.match(dsl, /2 张业务表/) const parsed = parseArchitectureDsl(dsl) assert.equal(parsed.layers[0].title, '用户层') assert.ok(parsed.layers.length >= 6) assert.ok(parsed.concerns.length >= 3) assert.ok(parsed.stats.componentCount >= 12) ``` - [ ] **Step 2: Write tests for DSL structure, layout, and SVG export** Use this DSL: ```js const customDsl = `用户层 学生 选课 / 查成绩 表现层 - Vue 3 前端 Vue 3 Composition API Vue Router 路由 接口层 - Spring MVC Controller 统一接口规范 控制器分层 横切关注点 JWT 认证 登录签发 Token 全局异常处理 统一异常响应` ``` Assert: ```js const parsed = parseArchitectureDsl(customDsl) assert.equal(parsed.layers.length, 3) assert.equal(parsed.layers[1].subtitle, 'Vue 3 前端') assert.equal(parsed.layers[1].components[0].details.length, 2) assert.equal(parsed.concerns.length, 2) const diagram = buildArchitectureDiagram(parsed) assert.equal(diagram.stats.layerCount, 3) assert.equal(diagram.stats.concernCount, 2) assert.ok(diagram.canvas.width >= 900) assert.ok(diagram.canvas.height >= 420) assert.equal(diagram.layers[0].components[0].title, '学生') const svg = buildArchitectureExportSvg(diagram) assert.match(svg, /系统架构图/) assert.match(svg, /JWT 认证/) assert.match(svg, /Vue 3/) ``` - [ ] **Step 3: Run tests and confirm they fail** Run: ```bash cd easycode-web node src/utils/architectureDiagram.test.mjs ``` Expected: module not found or missing exported functions. - [ ] **Step 4: Implement `architectureDiagram.js`** Implement exports: ```js export function buildDefaultArchitectureDsl(project = {}, database = {}) {} export function parseArchitectureDsl(dsl = '') {} export function buildArchitectureDiagram(parsed = {}, options = {}) {} export function buildArchitectureExportSvg(diagram = {}, options = {}) {} ``` The implementation must: - Parse `project.appBlueprint` safely when it is JSON text. - Produce fallback roles, services, tables, and runtime items when project data is sparse. - Split layer title/subtitle on ` - ` or `—`. - Treat `横切关注点` as `concerns`. - Return stable `stats` with `layerCount`, `componentCount`, and `concernCount`. - Escape XML text in export SVG. - [ ] **Step 5: Run utility tests and fix failures** Run: ```bash cd easycode-web node src/utils/architectureDiagram.test.mjs ``` Expected: all assertions pass with no output beyond the test runner's normal completion. ## Task 2: Diagram Center Architecture Editor **Files:** - Modify: `easycode-web/src/views/DiagramCenterView.vue` - [ ] **Step 1: Add architecture state and imports** Import these functions: ```js import { buildArchitectureDiagram, buildArchitectureExportSvg, buildDefaultArchitectureDsl, parseArchitectureDsl } from '@/utils/architectureDiagram' ``` Add refs: ```js const architectureDsl = ref('') const architectureBlackWhite = ref(false) const architectureSvgRef = ref(null) ``` Add computed values: ```js const parsedArchitecture = computed(() => parseArchitectureDsl(architectureDsl.value)) const architectureDiagram = computed(() => buildArchitectureDiagram(parsedArchitecture.value, { blackWhite: architectureBlackWhite.value, title: `${project.projectName || '项目'}系统架构图` })) ``` - [ ] **Step 2: Replace architecture branch with dedicated editor** In the template, add a branch before the existing custom graph branch: ```vue
``` The editor must include: - left DSL panel with `el-input type="textarea"` bound to `architectureDsl`; - buttons for clear, load example, refresh preview, save; - right SVG preview bound to `architectureDiagram`; - top stats for `layerCount` and `componentCount`; - checkbox bound to `architectureBlackWhite`; - export buttons using SVG and PNG handlers. - [ ] **Step 3: Add save/restore behavior** In `applySavedDrafts()`: - Find saved `diagramType === 'architecture'`. - Parse `diagramJson`. - If it contains `dsl`, set `architectureDsl`. - If no saved DSL exists, set `architectureDsl = buildDefaultArchitectureDsl(project, database.value)`. - Restore `blackWhite` from saved payload when present. In `loadSavedDiagram(diagram)`: - When `diagram.diagramType === 'architecture'`, set `activeDiagram = 'architecture'`, apply saved DSL and display mode. In `currentDiagramPayload()`: - For architecture, save: ```js { diagramType: 'architecture', title: '系统架构图', description: 'DSL 驱动的分层系统架构图', diagramJson: JSON.stringify({ dsl: architectureDsl.value, graph: architectureDiagram.value, blackWhite: architectureBlackWhite.value }) } ``` - [ ] **Step 4: Add architecture export handlers** Add: ```js function architectureSvgText() { return buildArchitectureExportSvg(architectureDiagram.value, { blackWhite: architectureBlackWhite.value }) } function downloadArchitectureSvg() {} async function downloadArchitecturePng() {} ``` PNG export should follow existing `downloadCurrentPng()` logic: create a Blob URL, load it into `Image`, draw on Canvas, save with `saveBlob`. - [ ] **Step 5: Style the editor** Add scoped SCSS for: - `.architecture-editor` - `.architecture-workbench` - `.architecture-dsl-panel` - `.architecture-preview-panel` - `.architecture-toolbar` - `.architecture-preview-scroll` - `.architecture-svg` The layout should be split-panel on desktop and single-column below 980px. Keep card radius at 8px or less and use restrained, workbench-style colors. - [ ] **Step 6: Run frontend build** Run: ```bash cd easycode-web npm run build ``` Expected: Vite production build completes successfully. ## Task 3: Manual UI Verification **Files:** - Existing frontend files only. - [ ] **Step 1: Start local dev server** Run: ```bash cd easycode-web npm run dev -- --host 0.0.0.0 ``` Expected: Vite serves the app and prints a local URL. - [ ] **Step 2: Open diagram center** Use an authenticated project URL: ```text http://localhost:/project//diagrams ``` Expected: - system architecture tab shows DSL editor and layered preview; - default DSL appears when no saved architecture diagram exists; - editing DSL and clicking generate/refresh updates the preview; - saving persists and reload restores DSL; - SVG and PNG downloads start. - [ ] **Step 3: Stop dev server** Stop the Vite session after verification so no long-running command remains. ## Self-Review - Spec coverage: default DSL, parsing, layered SVG, concerns sidebar, save/restore, export, and tests are covered. - Placeholder scan: no `TBD`, `TODO`, or vague implementation-only steps remain. - Type consistency: utility names and Vue computed/state names match across tasks.