# 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.