127 lines
4.4 KiB
Markdown
127 lines
4.4 KiB
Markdown
|
|
# 多文件预览下拉选择器 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:** 在数据处理向导第二步中支持按文件切换原文和切片,同时保留现有双栏阅读空间。
|
|||
|
|
|
|||
|
|
**Architecture:** 为每个预览条目记录来源文件 ID;父页面按当前文件筛选原文与条目。预览组件只负责可搜索下拉选择器和当前文件双栏对照,不拼接不同文件的原文。
|
|||
|
|
|
|||
|
|
**Tech Stack:** Vue 3、TypeScript、Element Plus、SCSS、Node 回归脚本。
|
|||
|
|
|
|||
|
|
## Global Constraints
|
|||
|
|
|
|||
|
|
- 预览主区保持原文与切片的双栏比例,不新增常驻第三栏。
|
|||
|
|
- 下拉选择器必须支持 100 个文件的名称筛选。
|
|||
|
|
- 切换文件不得丢失其他文件已编辑的切片内容。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### Task 1: 锁定多文件来源映射
|
|||
|
|
|
|||
|
|
**Files:**
|
|||
|
|
- Modify: `frontend/scripts/regression-data-process-wizard.mjs`
|
|||
|
|
- Modify: `frontend/src/views/data-process/create/types.ts`
|
|||
|
|
- Modify: `frontend/src/views/data-process/create/previewModel.ts`
|
|||
|
|
|
|||
|
|
**Interfaces:**
|
|||
|
|
- Produces: `PreviewItem.sourceFileId: string`。
|
|||
|
|
- Produces: `buildPreviewItems(sourceText, processType, sourceFileId)` 为同一文件生成带文件归属的唯一条目。
|
|||
|
|
|
|||
|
|
- [ ] **Step 1: 写入失败断言**
|
|||
|
|
|
|||
|
|
```js
|
|||
|
|
assert.match(typesSource, /sourceFileId/, 'PreviewItem 缺少来源文件标识')
|
|||
|
|
assert.match(modelSource, /sourceFileId/, '切片生成没有写入来源文件标识')
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
- [ ] **Step 2: 运行失败断言**
|
|||
|
|
|
|||
|
|
Run: `npm run test:data-process-wizard`
|
|||
|
|
Expected: FAIL,提示缺少 `sourceFileId`。
|
|||
|
|
|
|||
|
|
- [ ] **Step 3: 实现文件归属**
|
|||
|
|
|
|||
|
|
```ts
|
|||
|
|
export interface PreviewItem {
|
|||
|
|
sourceFileId: string
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
export function buildPreviewItems(sourceText: string, processType: ProcessType, sourceFileId: string) {
|
|||
|
|
// 每个 item 写入 sourceFileId,并以它构造稳定 ID。
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
- [ ] **Step 4: 再次运行回归脚本**
|
|||
|
|
|
|||
|
|
Run: `npm run test:data-process-wizard`
|
|||
|
|
Expected: 新断言通过;仅保留已知的布局失败(如存在)。
|
|||
|
|
|
|||
|
|
### Task 2: 按文件驱动双栏预览
|
|||
|
|
|
|||
|
|
**Files:**
|
|||
|
|
- Modify: `frontend/src/views/data-process/DataProcessCreateView.vue`
|
|||
|
|
|
|||
|
|
**Interfaces:**
|
|||
|
|
- Consumes: `PreviewItem.sourceFileId`。
|
|||
|
|
- Produces: `activePreviewFile`、`activePreviewItems` 与当前文件选择状态。
|
|||
|
|
|
|||
|
|
- [ ] **Step 1: 为多文件下拉接线添加失败断言**
|
|||
|
|
|
|||
|
|
```js
|
|||
|
|
assert.match(viewSource, /selectedPreviewFileId/, '父页面缺少当前预览文件状态')
|
|||
|
|
assert.match(viewSource, /buildPreviewItems\(file\.content, processType\.value, String\(file\.uid\)\)/, '预览没有按文件分别生成')
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
- [ ] **Step 2: 运行失败断言**
|
|||
|
|
|
|||
|
|
Run: `npm run test:data-process-wizard`
|
|||
|
|
Expected: FAIL,提示缺少当前预览文件状态。
|
|||
|
|
|
|||
|
|
- [ ] **Step 3: 最小实现**
|
|||
|
|
|
|||
|
|
```ts
|
|||
|
|
const activePreviewFile = computed(() => uploadedFiles.value.find((file) => String(file.uid) === selectedPreviewFileId.value))
|
|||
|
|
const activePreviewItems = computed(() => previewItems.value.filter((item) => item.sourceFileId === selectedPreviewFileId.value))
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
- [ ] **Step 4: 运行回归脚本**
|
|||
|
|
|
|||
|
|
Run: `npm run test:data-process-wizard`
|
|||
|
|
Expected: 父页面多文件断言通过。
|
|||
|
|
|
|||
|
|
### Task 3: 加入可搜索文件下拉框与布局修复
|
|||
|
|
|
|||
|
|
**Files:**
|
|||
|
|
- Modify: `frontend/src/views/data-process/create/PreviewCompareStep.vue`
|
|||
|
|
- Modify: `frontend/src/views/data-process/DataProcessCreateView.vue`
|
|||
|
|
- Modify: `frontend/scripts/regression-data-process-wizard.mjs`
|
|||
|
|
|
|||
|
|
**Interfaces:**
|
|||
|
|
- Consumes: `files`、`selectedFileId`、`items`、`sourceText`。
|
|||
|
|
- Produces: `update:selectedFileId` 事件。
|
|||
|
|
|
|||
|
|
- [ ] **Step 1: 添加失败断言**
|
|||
|
|
|
|||
|
|
```js
|
|||
|
|
assert.match(previewSource, /filterable/, '文件选择器必须可搜索')
|
|||
|
|
assert.match(previewSource, /当前文件/, '预览缺少当前文件切换器')
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
- [ ] **Step 2: 运行失败断言**
|
|||
|
|
|
|||
|
|
Run: `npm run test:data-process-wizard`
|
|||
|
|
Expected: FAIL,提示缺少可搜索的文件选择器。
|
|||
|
|
|
|||
|
|
- [ ] **Step 3: 实现下拉框与响应式样式**
|
|||
|
|
|
|||
|
|
```vue
|
|||
|
|
<el-select filterable :model-value="selectedFileId" @update:model-value="emit('update:selectedFileId', $event)">
|
|||
|
|
<el-option v-for="file in files" :key="file.id" :label="file.name" :value="file.id" />
|
|||
|
|
</el-select>
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
- [ ] **Step 4: 将 `.wizard-content` 设为 `min-height: 0` 并运行验证**
|
|||
|
|
|
|||
|
|
Run: `npm run test:data-process-wizard && npm run type-check && npm run build`
|
|||
|
|
Expected: 三个命令退出码均为 0。
|