From 393a170d3acf5bba56381cb75e3c736c41d9b752 Mon Sep 17 00:00:00 2001 From: zwt13703 Date: Wed, 1 Jul 2026 20:13:23 +0800 Subject: [PATCH] =?UTF-8?q?docs:=E6=9B=B4=E6=96=B0=E6=8F=90=E7=A4=BA?= =?UTF-8?q?=E8=AF=8D=E3=80=81=E4=BB=BB=E5=8A=A1=E6=B8=85=E5=8D=95=E3=80=81?= =?UTF-8?q?=E5=8E=9F=E5=9E=8B=E5=9B=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AGENTS.md | 2 +- README.md | 6 +- SKILL.md | 2 +- .../AI文档模板系统-像素级任务清单-20260701.md | 1338 +++++++++++++++++ ...文档模板系统-完整原型-20260701-115332.html | 618 ++++++++ 5 files changed, 1961 insertions(+), 5 deletions(-) create mode 100644 docs/AI文档模板系统-像素级任务清单-20260701.md create mode 100644 docs/AI文档模板系统-完整原型-20260701-115332.html diff --git a/AGENTS.md b/AGENTS.md index 2615cf5..72b173d 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -14,7 +14,7 @@ AI 文档模板生成系统(第一阶段 MVP),定位是一个 **Word 模 ## 技术栈 -- **前端**:Vue 3 + TypeScript + Vite + Element Plus + Pinia + Vue Router 4 +- **前端**:Vue 3 + TypeScript + Vite + Ant Design Vue + Pinia + Vue Router 4 - **后端**:Python 3.11+ + FastAPI + SQLAlchemy + Alembic + MySQL 8.0 - **存储**:MinIO(文件)/ MySQL(结构化数据) - **关键词**:block_id, template, region_type, upsert diff --git a/README.md b/README.md index e588680..03e9c98 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ |---|------|---------| | 前端框架 | Vue 3 | ^3.4 | | 构建工具 | Vite | ^5.x | -| UI 组件库 | Element Plus | ^2.8 | +| UI 组件库 | Ant Design Vue | ^4.x | | 状态管理 | Pinia | ^2.x | | 路由 | Vue Router 4 | ^4.x | | 后端框架 | Python FastAPI | ^0.110 | @@ -135,8 +135,8 @@ uvicorn app.main:app --reload --port 8000 ```bash cd frontend -pnpm install -pnpm run dev +npm install +npm run dev ``` ### 访问 diff --git a/SKILL.md b/SKILL.md index 943b328..f5fe512 100644 --- a/SKILL.md +++ b/SKILL.md @@ -30,7 +30,7 @@ metadata: | 层 | 选型 | 说明 | |---|------|------| -| 前端 | Vue3 + Vite + Element Plus + Pinia | 组件化单页应用 | +| 前端 | Vue3 + Vite + Ant Design Vue + Pinia | 组件化单页应用 | | 后端 | Python FastAPI | RESTful API | | 数据库 | MySQL 8.0 + SQLAlchemy + Alembic | 关系型数据 | | 文件存储 | MinIO / 本地文件系统 | 模板和资料文件 | diff --git a/docs/AI文档模板系统-像素级任务清单-20260701.md b/docs/AI文档模板系统-像素级任务清单-20260701.md new file mode 100644 index 0000000..695dfc1 --- /dev/null +++ b/docs/AI文档模板系统-像素级任务清单-20260701.md @@ -0,0 +1,1338 @@ +# AI 文档模板系统 — 像素级任务清单 + +> 每个任务 ~0.25–0.5 天,可独立分配,验收精确到文件/函数/交互效果。 +> 聚焦:模板标注配置页(第一阶段 MVP)。 +> UI 库:Ant Design Vue + +--- + +## 第一阶段:MVP 任务总表(73 个) + +| # | 任务名 | 端 | 预估 | +|---|--------|:--:|:----:| +| | **环境搭建** | | | +| 001 | 初始化 FastAPI 项目 + main.py + health 接口 | 后端 | 0.25d | +| 002 | 配置 MySQL 连接 + SQLAlchemy session | 后端 | 0.25d | +| 003 | 配置 MinIO 客户端 | 后端 | 0.25d | +| 004 | Alembic 初始化 + 第一个迁移脚本 | 后端 | 0.25d | +| 005 | Docker Compose 编排(MySQL + MinIO) | 后端 | 0.25d | +| 006 | 初始化 Vue3 + Vite 项目 | 前端 | 0.25d | +| 007 | 安装 Ant Design Vue + 全局注册 | 前端 | 0.25d | +| 008 | 安装 Vue Router + 配置路由结构 | 前端 | 0.25d | +| 009 | 安装 Pinia + 创建根 store | 前端 | 0.25d | +| 010 | 安装 Axios + 创建 API 客户端 base.ts | 前端 | 0.25d | +| 011 | 定义全局 CSS 变量 | 前端 | 0.25d | +| | **数据库建表(3 个)** | | | +| 012 | 创建 template 表 + SQLAlchemy Model | 后端 | 0.25d | +| 013 | 创建 template_block 表 + SQLAlchemy Model | 后端 | 0.25d | +| 014 | 创建 block_config 表 + SQLAlchemy Model(含 unique 约束) | 后端 | 0.25d | +| | **模板上传** | | | +| 015 | 实现文件接收 + .docx 格式校验 + 大小校验 | 后端 | 0.25d | +| 016 | 实现文件存储到 MinIO | 后端 | 0.25d | +| 017 | 实现 template 表 insert | 后端 | 0.25d | +| 018 | 组装上传接口 `POST /api/templates/upload` | 后端 | 0.25d | +| | **Word 解析** | | | +| 019 | 实现 docx 文件打开 + 逐段落遍历 | 后端 | 0.25d | +| 020 | 实现标题识别(Heading 1-6)→ type=heading | 后端 | 0.25d | +| 021 | 实现段落识别 → type=paragraph | 后端 | 0.25d | +| 022 | 实现表格识别 + 行数列数提取 → type=table | 后端 | 0.25d | +| 023 | 实现 block_id 生成器(顺序编号) | 后端 | 0.25d | +| 024 | 实现层级构建(parent_block_id)+ 结构树 tree 输出 | 后端 | 0.25d | +| 025 | 将解析结果批量写入 template_block 表 | 后端 | 0.25d | +| | **HTML 预览生成** | | | +| 026 | 标题 → `

` 转换 + 居中加粗样式 | 后端 | 0.25d | +| 027 | 段落 → `

` 转换 + 首行缩进样式 | 后端 | 0.25d | +| 028 | 表格 → `` 转换 + 边框样式 | 后端 | 0.25d | +| 029 | 拼接完整 HTML 字符串(带内联 CSS) | 后端 | 0.25d | +| | **查询 + 配置接口** | | | +| 030 | 实现 `GET /api/templates/{id}` 组装全部数据 | 后端 | 0.5d | +| 031 | 实现 `POST /api/templates/{id}/blocks/{blockId}/config` upsert | 后端 | 0.25d | +| 032 | 实现 `GET /api/data-sources` 返回预设列表 | 后端 | 0.25d | +| 033 | 实现 `POST /api/data-sources` 新增数据源 | 后端 | 0.25d | +| | **四栏布局** | | | +| 034 | 实现四栏 CSS Grid 布局 | 前端 | 0.5d | +| 035 | 实现左侧菜单 shell 组件 | 前端 | 0.25d | +| 036 | 实现顶部工具栏 shell 组件 | 前端 | 0.25d | +| 037 | 实现配置面板 shell 组件 | 前端 | 0.25d | +| 038 | 实现预览区 shell 组件(A4 纸效果) | 前端 | 0.25d | +| 039 | 实现结构树 shell 组件 | 前端 | 0.25d | +| | **左侧菜单** | | | +| 040 | 菜单数据模型(JSON)+ 子菜单配置 | 前端 | 0.25d | +| 041 | 菜单展开/收起交互 + 箭头旋转动画 | 前端 | 0.25d | +| 042 | 菜单选中高亮(蓝色左侧竖条) | 前端 | 0.25d | +| | **顶部工具栏** | | | +| 043 | 面包屑导航渲染 | 前端 | 0.25d | +| 044 | 模板名称 + 版本号标签展示 | 前端 | 0.25d | +| 045 | 保存状态指示器(已保存/未保存 圆点切换) | 前端 | 0.25d | +| 046 | 操作按钮区(预览/保存/生成测试/导出模板/全屏) | 前端 | 0.25d | +| | **Word 预览区** | | | +| 047 | v-html 渲染后端 HTML + 为 [data-block-id] 添加 doc-block class | 前端 | 0.25d | +| 048 | 点击事件委托 + block_id 提取 | 前端 | 0.25d | +| 049 | 选中高亮(蓝色虚线 outline + 浅蓝背景) | 前端 | 0.25d | +| 050 | 区域类型颜色映射(蓝/黄/绿/紫/灰)+ 保存后更新 | 前端 | 0.5d | +| 051 | block_id 标签 absolute 定位 + hover 显示 | 前端 | 0.25d | +| 052 | 显示/隐藏标签 toggle 开关 | 前端 | 0.25d | +| 053 | 缩放控制(70%/100%/150% scale 切换) | 前端 | 0.25d | +| | **结构树** | | | +| 054 | 递归树组件 + 数据绑定 | 前端 | 0.5d | +| 055 | 展开/折叠交互 + 图标 | 前端 | 0.25d | +| 056 | 状态圆点(已配置绿/待审核黄/已禁用红/未配置灰) | 前端 | 0.25d | +| 057 | 点击树节点 → 预览区 scrollIntoView + 闪烁高亮 | 前端 | 0.5d | +| | **配置面板** | | | +| 058 | 区域名称 input(默认取 text_preview) | 前端 | 0.25d | +| 059 | 区域类型 select | 前端 | 0.25d | +| 060 | 数据来源 tag chips 多选组件 | 前端 | 0.5d | +| 061 | 提示词 textarea + 字数统计 | 前端 | 0.5d | +| 062 | 输出格式 select | 前端 | 0.25d | +| 063 | 是否需要审核 radio | 前端 | 0.25d | +| 064 | 备注 textarea + 字数统计 | 前端 | 0.25d | +| 065 | 保存按钮 + loading 状态 + 成功/失败提示 | 前端 | 0.25d | +| 066 | 未选中区域时的空状态占位提示 | 前端 | 0.25d | +| | **Pinia Store** | | | +| 067 | templateStore | 前端 | 0.5d | +| 068 | selectionStore | 前端 | 0.25d | +| 069 | uiStore | 前端 | 0.25d | +| | **三区联动** | | | +| 070 | watch selectedBlockId → 配置面板加载 | 前端 | 0.5d | +| 071 | watch selectedBlockId → 结构树节点高亮 | 前端 | 0.25d | +| 072 | 页面初始化 loading(全页遮罩 + a-spin) | 前端 | 0.25d | +| 073 | 加载失败错误页 + 重新加载按钮 | 前端 | 0.25d | +| | **总计** | | **~18.25d** | + +--- + +## 第一阶段 MVP 任务卡(逐个) + +--- + +### 环境搭建(001–011) + +--- + +#### 001 · 初始化 FastAPI 项目 + main.py + health 接口 + +**端**:后端 **预估**:0.25d **产出**:`app/main.py` + +**做什么** +- 创建 `app/` 目录,创建 `app/main.py` +- 创建 FastAPI 实例,添加 `GET /health` 返回 `{"status": "ok"}` +- 添加 CORS 中间件(允许前端 localhost 访问) +- 创建目录结构:`api/`, `models/`, `services/`, `schemas/` + +**验收** +- `uvicorn app.main:app --reload` 启动成功 +- 访问 `/docs` 显示 Swagger 页面 +- 访问 `/health` 返回 200 + +--- + +#### 002 · 配置 MySQL 连接 + SQLAlchemy session + +**端**:后端 **预估**:0.25d **产出**:`app/database.py` + +**做什么** +- 创建 `app/database.py` +- 配置 SQLAlchemy engine(读取环境变量 `DB_HOST/DB_PORT/DB_USER/DB_PASS/DB_NAME`) +- 创建 `SessionLocal` 工厂 +- 创建 `Base` 基类 +- 创建 `get_db` 依赖注入函数 + +**验收** +- 应用启动时不会报数据库连接错误 + +--- + +#### 003 · 配置 MinIO 客户端 + +**端**:后端 **预估**:0.25d **产出**:`app/services/storage.py` + +**做什么** +- 创建 `app/services/storage.py` +- 初始化 `minio.Minio` 客户端 +- 实现 `upload_file(bucket, file_path, content)` 函数 +- 实现 `download_file(bucket, file_path)` 函数 +- 实现 `ensure_bucket(bucket_name)` 自动创建 bucket + +**验收** +- MinIO 未启动时降级为本地文件存储 + +--- + +#### 004 · Alembic 初始化 + 第一个迁移脚本 + +**端**:后端 **预估**:0.25d **产出**:`alembic.ini`, `migrations/` + +**做什么** +- 运行 `alembic init alembic` +- 配置 `alembic.ini` 中的数据库连接 +- 配置 `env.py` 导入 `Base` +- 生成第一个空迁移 + +**验收** +- `alembic upgrade head` 成功执行 +- `alembic history` 显示初始迁移 + +--- + +#### 005 · Docker Compose 编排 + +**端**:后端 **预估**:0.25d **产出**:`docker-compose.yml` + +**做什么** +- 创建 `docker-compose.yml` +- MySQL 8.0 服务(端口 3306,初始化数据库 `ai_doc_template`) +- MinIO 服务(端口 9000 + 9001 console) +- 网络配置,服务间可通信 + +**验收** +- `docker-compose up -d` 启动成功 + +--- + +#### 006 · 初始化 Vue3 + Vite 项目 + +**端**:前端 **预估**:0.25d **产出**:前端项目根目录 + +**做什么** +- 运行 `npm create vite@latest`(Vue3 + TypeScript) +- 安装依赖 `npm install` +- 确认 `npm run dev` 可启动 +- 清理默认 App.vue 内容,保留 Hello World + +**验收** +- `npm run dev` 启动成功 + +--- + +#### 007 · 安装 Ant Design Vue + 全局注册 + +**端**:前端 **预估**:0.25d **产出**:`src/main.ts` + +**做什么** +- 运行 `npm install ant-design-vue` +- 在 `main.ts` 中 `import Antd from 'ant-design-vue'` + `app.use(Antd)` +- 全局导入样式:`import 'ant-design-vue/dist/reset.css'` +- 验证:在 App.vue 中使用一个 `` 看能否渲染 + +**验收** +- Ant Design Vue 按钮可正常显示 +- 无控制台报错 + +--- + +#### 008 · 安装 Vue Router + 配置路由结构 + +**端**:前端 **预估**:0.25d **产出**:`src/router/index.ts` + +**做什么** +- 运行 `npm install vue-router@4` +- 创建 `src/router/index.ts` +- 配置路由:`/` → TemplateCenter, `/template/:id` → TemplateEdit +- 在 `main.ts` 中 `app.use(router)` +- 添加 `router-view` 到 App.vue + +**验收** +- 访问 `/` 显示模板中心页 +- 访问 `/template/1` 显示模板编辑页 + +--- + +#### 009 · 安装 Pinia + 创建根 store + +**端**:前端 **预估**:0.25d **产出**:`src/stores/index.ts` + +**做什么** +- 运行 `npm install pinia` +- 在 `main.ts` 中 `app.use(createPinia())` +- 创建一个简单的 counter store 验证可用 + +**验收** +- Pinia 正常注册,无控制台报错 + +--- + +#### 010 · 安装 Axios + 创建 API 客户端 + +**端**:前端 **预估**:0.25d **产出**:`src/api/base.ts` + +**做什么** +- 运行 `npm install axios` +- 创建 `src/api/base.ts` +- 创建 axios 实例,baseURL 设为 `/api` +- 添加请求/响应拦截器 + +**验收** +- 调用 `api.get('/health')` 能收到后端响应 + +--- + +#### 011 · 定义全局 CSS 变量 + +**端**:前端 **预估**:0.25d **产出**:`src/styles/variables.css` + +**做什么** +- 创建 `src/styles/variables.css` +- 定义 `:root` 变量: + +```css +:root { + --primary: #5b5bd6; + --primary-hover: #4a4ac0; + --primary-soft: #eeeefb; + --text: #1a1d24; + --text-2: #5b626e; + --text-3: #9aa1ad; + --border: #e0e2e6; + --border-light: #eaecef; + --bg: #f5f6f8; + --bg-card: #fff; + --bg-soft: #f0f1f3; + --success: #1a8c4a; + --warn: #d48a00; + --danger: #d33; + --font: -apple-system, "PingFang SC", "Microsoft YaHei", sans-serif; + --fs-body: 13px; + --fs-sm: 12px; + --radius: 6px; + --sidebar-w: 220px; + --config-panel-w: 380px; + --tree-panel-w: 240px; + --toolbar-h: 48px; +} +``` + +- 在 `main.ts` 中 import + +**验收** +- 全局样式变量可在任意组件中使用 `var(--primary)` + +--- + +### 数据库建表(012–014) + +--- + +#### 012 · 创建 template 表 + Model + +**端**:后端 **预估**:0.25d **产出**:`app/models/template.py` + +**做什么** +- 定义 `Template` Model(字段见附录) +- 生成 Alembic 迁移并执行 + +**验收** +- 表创建成功,可通过 Model 插入一条记录 + +--- + +#### 013 · 创建 template_block 表 + Model + +**端**:后端 **预估**:0.25d **产出**:`app/models/template_block.py` + +**做什么** +- 定义 `TemplateBlock` Model +- 外键关联到 `template.id` +- 生成迁移并执行 + +**验收** +- 插入数据时外键约束生效 + +--- + +#### 014 · 创建 block_config 表 + Model + +**端**:后端 **预估**:0.25d **产出**:`app/models/block_config.py` + +**做什么** +- 定义 `BlockConfig` Model +- 添加唯一约束 `(template_id, block_id)` +- 生成迁移并执行 + +**验收** +- 重复 `(template_id, block_id)` 插入时更新而非报错 + +--- + +### 模板上传(015–018) + +--- + +#### 015 · 文件接收 + 格式校验 + 大小校验 + +**端**:后端 **预估**:0.25d **产出**:`app/services/template_service.py` 中的 `validate_file()` + +**做什么** +- 校验扩展名为 `.docx` +- 校验 Content-Type +- 校验文件大小 ≤ 50MB + +**验收** +- 上传 `.txt` 返回 400 +- 上传 >50MB 返回 413 + +--- + +#### 016 · 文件存储到 MinIO + +**端**:后端 **预估**:0.25d **产出**:`app/services/template_service.py` 中的 `save_file()` + +**做什么** +- 调用 storage 服务的 upload_file +- 路径格式:`/templates/{template_id}/{filename}` +- MinIO 不可用时降级本地存储 + +**验收** +- 文件保存到指定路径 + +--- + +#### 017 · template 表 insert + +**端**:后端 **预估**:0.25d **产出**:`app/services/template_service.py` 中的 `create_template_record()` + +**做什么** +- 写入 template 表 +- 返回创建的 template 对象 + +**验收** +- 数据库有正确记录 + +--- + +#### 018 · 组装上传接口 + +**端**:后端 **预估**:0.25d **产出**:`app/api/templates.py` 中的 upload 路由 + +**做什么** +- 创建 `app/api/templates.py` +- 实现 `POST /api/templates/upload` 路由 +- 调用 015→016→017 三个步骤 + +**验收** +- Postman 上传成功,返回 `{"template_id": 1, "name": "...", "status": "uploaded"}` + +--- + +### Word 解析(019–025) + +--- + +#### 019 · docx 文件打开 + 逐段落遍历 + +**端**:后端 **预估**:0.25d **产出**:`app/services/doc_parser.py` 中的 `parse_document()` + +**做什么** +- 使用 python-docx 打开文件 +- 遍历 `document.paragraphs` + +**验收** +- 返回段落列表 + +--- + +#### 020 · 标题识别(Heading 1-6) + +**端**:后端 **预估**:0.25d **产出**:`app/services/doc_parser.py` 中的 `classify_paragraph()` + +**做什么** +- 判断 `paragraph.style.name` 是否以 "Heading" 开头 +- 提取标题级别和文本 + +**验收** +- Heading 1 → level 1 +- Heading 2 → level 2 + +--- + +#### 021 · 段落识别 + +**端**:后端 **预估**:0.25d **产出**:`app/services/doc_parser.py` + +**做什么** +- 非标题段落 → type="paragraph" +- 提取文本和样式名称 + +**验收** +- 正文段落 type=paragraph + +--- + +#### 022 · 表格识别 + 行数列数提取 + +**端**:后端 **预估**:0.25d **产出**:`app/services/doc_parser.py` 中的 `parse_tables()` + +**做什么** +- 遍历 `document.tables` +- 提取行数、列数、表头 + +**验收** +- 表格行数列数正确 + +--- + +#### 023 · block_id 生成器 + +**端**:后端 **预估**:0.25d **产出**:`app/services/doc_parser.py` 中的 `generate_block_id()` + +**做什么** +- 格式:`block_001`, `block_002`, ... 递增 + +**验收** +- 输入 1 → `block_001` +- 输入 12 → `block_012` + +--- + +#### 024 · 层级构建 + 结构树输出 + +**端**:后端 **预估**:0.25d **产出**:`app/services/doc_parser.py` 中的 `build_tree()` + +**做什么** +- 根据 heading level 确定父子关系 +- 填充 `parent_block_id` +- 输出嵌套 tree 结构 + +**验收** +- 三级标题层级正确 +- 表格归属于正确的父章节 + +--- + +#### 025 · 解析结果批量写入 template_block 表 + +**端**:后端 **预估**:0.25d **产出**:`app/services/doc_parser.py` 中的 `save_blocks()` + +**做什么** +- 批量 insert 到 template_block 表 +- 先删除旧记录(重解析场景) + +**验收** +- 数据库有对应的 block 记录 + +--- + +### HTML 预览生成(026–029) + +--- + +#### 026 · 标题 → `

` 转换 + +**端**:后端 **预估**:0.25d **产出**:`app/services/html_generator.py` 中的 `render_heading()` + +**做什么** +- 输出 `

标题内容

` + +**验收** +- 标签带 data-block-id,样式居中加粗 + +--- + +#### 027 · 段落 → `

` 转换 + +**端**:后端 **预估**:0.25d **产出**:`app/services/html_generator.py` 中的 `render_paragraph()` + +**做什么** +- 输出 `

段落内容

` + +**验收** +- 首行缩进,行高 1.8 + +--- + +#### 028 · 表格 → `
` 转换 + +**端**:后端 **预估**:0.25d **产出**:`app/services/html_generator.py` 中的 `render_table()` + +**做什么** +- 输出完整 HTML `
` 带 data-block-id + +**验收** +- 表格正确渲染,边框可见 + +--- + +#### 029 · 拼接完整 HTML 字符串 + +**端**:后端 **预估**:0.25d **产出**:`app/services/html_generator.py` 中的 `generate_preview_html()` + +**做什么** +- 按 sort_order 排序 +- 遍历 blocks 调用对应的 render 函数 +- 拼接为完整 HTML + +**验收** +- 返回字符串可被前端 v-html 渲染 + +--- + +### 查询 + 配置接口(030–033) + +--- + +#### 030 · 模板详情查询接口 + +**端**:后端 **预估**:0.5d **产出**:`app/api/templates.py` 中的 GET 路由 + +**做什么** +- 实现 `GET /api/templates/{template_id}` +- 查询 template 表 + template_block 表 + block_config 表 +- 调用 html_generator 生成 preview_html +- 返回完整 JSON + +**验收** +- 返回数据包含 template, preview_html, blocks, tree, configs + +--- + +#### 031 · 保存区域配置接口 + +**端**:后端 **预估**:0.25d **产出**:`app/api/blocks.py` 中的 POST 路由 + +**做什么** +- 实现 `POST /api/templates/{template_id}/blocks/{block_id}/config` +- upsert 语义 + +**验收** +- 保存后数据库记录正确 +- 重复调用更新记录 + +--- + +#### 032 · 获取数据源列表 + +**端**:后端 **预估**:0.25d **产出**:`app/api/data_sources.py` 中的 GET 路由 + +**做什么** +- 返回预设列表:财务部、运行部、生技部、安全监察部等 + +**验收** +- 返回 JSON 数组 + +--- + +#### 033 · 新增数据源 + +**端**:后端 **预估**:0.25d **产出**:`app/api/data_sources.py` 中的 POST 路由 + +**做什么** +- 接收 `{name, category}` 并存储 + +**验收** +- 新增后 GET 列表包含新数据源 + +--- + +### 四栏布局(034–039) + +--- + +#### 034 · 四栏 CSS Grid 布局 + +**端**:前端 **预估**:0.5d **产出**:`src/views/TemplateEdit.vue` + +**做什么** +```css +.layout { + display: grid; + grid-template-columns: var(--sidebar-w) var(--config-panel-w) 1fr var(--tree-panel-w); + grid-template-rows: var(--toolbar-h) 1fr; + height: 100vh; +} +``` + +- 工具栏 grid-column: 1 / -1 +- 左侧菜单 grid-column: 1 +- 配置面板 grid-column: 2 +- 预览区 grid-column: 3 +- 结构树 grid-column: 4 + +**验收** +- 页面渲染为四栏布局 +- 各区域宽度正确 + +--- + +#### 035 · 左侧菜单 shell + +**端**:前端 **预估**:0.25d **产出**:`src/components/TemplateEdit/LeftMenu.vue` + +**做什么** +- 固定宽度 220px +- overflow-y: auto, border-right, 白色背景 + +**验收** +- 渲染在正确位置 + +--- + +#### 036 · 顶部工具栏 shell + +**端**:前端 **预估**:0.25d **产出**:`src/components/TemplateEdit/TopToolbar.vue` + +**做什么** +- 固定高度 48px, flex 布局, border-bottom + +**验收** +- 渲染在顶部 + +--- + +#### 037 · 配置面板 shell + +**端**:前端 **预估**:0.25d **产出**:`src/components/TemplateEdit/ConfigPanel.vue` + +**做什么** +- 固定宽度 380px, overflow-y: auto +- border-right: 1px solid + +**验收** +- 渲染在正确位置 + +--- + +#### 038 · 预览区 shell + +**端**:前端 **预估**:0.25d **产出**:`src/components/TemplateEdit/WordPreview.vue` + +**做什么** +- flex: 1, overflow-y: auto, 背景色 `#f0f1f3` +- 内部 A4 纸容器:794px 宽, 白色背景, box-shadow + +**验收** +- A4 纸效果可见 + +--- + +#### 039 · 结构树 shell + +**端**:前端 **预估**:0.25d **产出**:`src/components/TemplateEdit/StructureTree.vue` + +**做什么** +- 固定宽度 240px, overflow-y: auto +- border-left: 1px solid + +**验收** +- 渲染在右侧 + +--- + +### 左侧菜单(040–042) + +--- + +#### 040 · 菜单数据模型 + +**端**:前端 **预估**:0.25d **产出**:`src/components/TemplateEdit/menu-data.ts` + +**做什么** +```ts +interface MenuItem { + label: string + icon: string + children?: MenuItem[] + route?: string +} +``` +- 完整菜单数据(模板中心/生成文档/历史记录/系统配置 及子菜单) + +**验收** +- 数据结构可被菜单组件消费 + +--- + +#### 041 · 菜单展开/收起 + 箭头动画 + +**端**:前端 **预估**:0.25d **产出**:`LeftMenu.vue` + +**做什么** +- 渲染菜单树 +- 有子菜单的项显示箭头图标 +- 点击切换展开/收起,箭头旋转动画 + +**验收** +- 点击展开子菜单,箭头旋转 90°,动画流畅 + +--- + +#### 042 · 菜单选中高亮 + +**端**:前端 **预估**:0.25d **产出**:`LeftMenu.vue` + +**做什么** +- 当前选中菜单添加 `active` class +- 高亮样式:`background: #eeeefb; color: #5b5bd6;` +- 左侧竖条 3px:`border-left: 3px solid #5b5bd6;` + +**验收** +- 点击菜单项高亮,切换时旧高亮移除 + +--- + +### 顶部工具栏(043–046) + +--- + +#### 043 · 面包屑导航 + +**端**:前端 **预估**:0.25d **产出**:`TopToolbar.vue` + +**做什么** +- 显示面包屑:`模板中心 / 模板名称 / 区域配置` +- 每段用 `/` 分隔,最后一段加粗 + +**验收** +- 面包屑渲染正确 + +--- + +#### 044 · 模板名称 + 版本号 + +**端**:前端 **预估**:0.25d **产出**:`TopToolbar.vue` + +**做什么** +- 从 Pinia store 读取模板名称显示 +- 版本号显示为灰色小标签 + +**验收** +- 模板名称正确读取 + +--- + +#### 045 · 保存状态指示器 + +**端**:前端 **预估**:0.25d **产出**:`TopToolbar.vue` + +**做什么** +- 小圆点 + 文字:绿色"已保存" / 黄色"未保存" +- 从 uiStore 读取 saveStatus + +**验收** +- 初始"未保存",保存成功后变"已保存" + +--- + +#### 046 · 操作按钮区 + +**端**:前端 **预估**:0.25d **产出**:`TopToolbar.vue` + +**做什么** +- 使用 Ant Design Vue `` +- 按钮:预览、保存(primary)、生成测试、导出模板、全屏 +- 按钮间距 8px + +**验收** +- 5 个按钮分布整齐,保存按钮高亮 + +--- + +### Word 预览区(047–053) + +--- + +#### 047 · v-html 渲染后端 HTML + +**端**:前端 **预估**:0.25d **产出**:`WordPreview.vue` + +**做什么** +- `
` +- 在 mounted 中为所有 `[data-block-id]` 元素添加 class `doc-block` + +**验收** +- HTML 内容渲染正确 + +--- + +#### 048 · 点击事件委托 + block_id 提取 + +**端**:前端 **预估**:0.25d **产出**:`WordPreview.vue` handleClick + +**做什么** +```ts +function handleClick(event: MouseEvent) { + const target = (event.target as HTMLElement).closest('[data-block-id]') + if (!target) { selectionStore.cancelSelection(); return } + const blockId = target.getAttribute('data-block-id') + selectionStore.selectBlock(blockId) +} +``` + +**验收** +- 点击段落提取到正确的 block_id +- 点击空白区域取消选中 + +--- + +#### 049 · 选中高亮 + +**端**:前端 **预估**:0.25d **产出**:`WordPreview.vue` + +**做什么** +- 选中 block 添加 class `active-region` +- CSS:`outline: 2px solid #5b5bd6; outline-offset: -2px; background: #f0f0ff;` + +**验收** +- 选中后蓝色虚线边框可见 + +--- + +#### 050 · 区域类型颜色映射 + +**端**:前端 **预估**:0.5d **产出**:`WordPreview.vue` + +**做什么** +- 根据 region_type 添加颜色 class: + - `ai_generate` → 浅蓝 `#e8f0fe` + 蓝色左边框 + - `manual` → 浅黄 `#fef7e0` + 黄色左边框 + - `fixed` → 浅绿 `#e6f4ea` + 绿色左边框 + - `table` → 浅紫 `#f3e8ff` + 紫色左边框 +- 保存配置后立即更新 + +**验收** +- 保存后预览区颜色变化正确 + +--- + +#### 051 · block_id 标签 + +**端**:前端 **预估**:0.25d **产出**:`WordPreview.vue` + +**做什么** +- 每个 block 左下角显示标签 `block_003` +- 标签样式:`position: absolute; left: -80px; font-size: 11px;` +- hover 时透明度 0→1(CSS transition) + +**验收** +- 鼠标移入时标签可见 + +--- + +#### 052 · 显示/隐藏标签 toggle + +**端**:前端 **预估**:0.25d **产出**:`TopToolbar.vue` + `WordPreview.vue` + +**做什么** +- 工具栏添加 Ant Design Vue `` +- 标签:`显示区域标识` +- 切换时更新 uiStore.showLabels + +**验收** +- 关闭后所有标签隐藏 + +--- + +#### 053 · 缩放控制 + +**端**:前端 **预估**:0.25d **产出**:`WordPreview.vue` + +**做什么** +- 工具栏缩放控制:`- 100% +` +- 级别:70% / 100% / 150% +- 对 `.doc-content` 应用 `transform: scale(N)` + +**验收** +- 缩放后内容清晰,交互正常 + +--- + +### 结构树(054–057) + +--- + +#### 054 · 递归树组件 + 数据绑定 + +**端**:前端 **预估**:0.5d **产出**:`StructureTree.vue` + +**做什么** +- 递归组件,接收 tree 数据 +- 渲染文档章节层级 + +**验收** +- 树结构与解析结果一致,递归渲染无报错 + +--- + +#### 055 · 展开/折叠 + 图标 + +**端**:前端 **预估**:0.25d **产出**:`StructureTree.vue` + +**做什么** +- 箭头旋转 90° 表示展开 +- 图标:heading→📄, paragraph→📝, table→📊 + +**验收** +- 点击箭头展开/折叠,图标正确 + +--- + +#### 056 · 状态圆点 + +**端**:前端 **预估**:0.25d **产出**:`StructureTree.vue` + +**做什么** +- 从 Pinia store 的 configs 读取配置 +- 圆点:已配置=绿色 / 待审核=黄色 / 已禁用=红色 / 未配置=灰色 +- 圆点样式:`width: 8px; height: 8px; border-radius: 50%;` + +**验收** +- 保存后圆点变为绿色 + +--- + +#### 057 · 树节点 → 预览区滚动定位 + +**端**:前端 **预估**:0.5d **产出**:`StructureTree.vue` + `WordPreview.vue` + +**做什么** +- 点击树节点: + 1. `selectionStore.selectBlock(blockId)` + 2. `document.querySelector([data-block-id="${blockId}"])?.scrollIntoView({ behavior: 'smooth', block: 'center' })` +- 闪烁效果:添加 class `flash`,0.3s 后移除 + +**验收** +- 点击树节点后预览区滚动到正确位置 + +--- + +### 配置面板(058–066) + +--- + +#### 058 · 区域名称 input + +**端**:前端 **预估**:0.25d **产出**:`ConfigPanel.vue` + +**做什么** +- `` +- 选中 block 时默认填充 text_preview + +**验收** +- 选中后显示 block 名称,可编辑 + +--- + +#### 059 · 区域类型 select + +**端**:前端 **预估**:0.25d **产出**:`ConfigPanel.vue` + +**做什么** +- `` +- 选项:AI 生成区域 / 人工填写区域 / 固定区域 / 表格生成区域 + +**验收** +- 切换选项值变化 + +--- + +#### 060 · 数据来源 tag chips + +**端**:前端 **预估**:0.5d **产出**:`ConfigPanel.vue` + +**做什么** +- 已选项显示为 `财务部` +- 末尾" + 添加"按钮,点击弹出 `` 下拉 +- 已选的不可重复添加 + +**验收** +- 标签显示正确,可删除可添加 + +--- + +#### 061 · 提示词 textarea + 字数统计 + +**端**:前端 **预估**:0.5d **产出**:`ConfigPanel.vue` + +**做什么** +- `` +- 超过 850 字时数字变橙色,超过 1000 变红 + +**验收** +- 输入字数实时统计 + +--- + +#### 062 · 输出格式 select + +**端**:前端 **预估**:0.25d **产出**:`ConfigPanel.vue` + +**做什么** +- `` +- 选项:正式报告段落 / 分条说明 / 表格数据 / JSON 数据 / 标题文本 + +**验收** +- 选项切换正常 + +--- + +#### 063 · 是否需要审核 radio + +**端**:前端 **预估**:0.25d **产出**:`ConfigPanel.vue` + +**做什么** +- `` +- `` +- `` + +**验收** +- 切换值变化 + +--- + +#### 064 · 备注 textarea + +**端**:前端 **预估**:0.25d **产出**:`ConfigPanel.vue` + +**做什么** +- `` + +**验收** +- 输入正常,字数统计正确 + +--- + +#### 065 · 保存按钮 + 流程 + +**端**:前端 **预估**:0.25d **产出**:`ConfigPanel.vue` + +**做什么** +- `保存该区域配置` +- 点击后: + 1. `saving = true` + 2. 调用 POST 接口 + 3. 成功 → `saving = false` + `message.success('保存成功')` + 4. 失败 → `saving = false` + `message.error('保存失败')` + +**验收** +- 保存成功/失败有对应提示 + +--- + +#### 066 · 未选中空状态 + +**端**:前端 **预估**:0.25d **产出**:`ConfigPanel.vue` + +**做什么** +- `selectedBlockId === null` 时显示: +- 居中图标 + "点击文档中的区域开始配置" +- 隐藏所有表单字段 + +**验收** +- 初始显示空状态,选中后显示表单 + +--- + +### Pinia Store(067–069) + +--- + +#### 067 · templateStore + +**端**:前端 **预估**:0.5d **产出**:`src/stores/templateStore.ts` + +**做什么** +- state: `template`, `previewHtml`, `blocks`, `tree`, `configs`, `dataSources` +- actions: `fetchTemplate(id)`, `updateConfig(blockId, config)` +- getters: `getBlockById(blockId)`, `getConfigByBlockId(blockId)` + +**验收** +- 调用 fetchTemplate 后所有数据填充 + +--- + +#### 068 · selectionStore + +**端**:前端 **预估**:0.25d **产出**:`src/stores/selectionStore.ts` + +**做什么** +- state: `selectedBlockId: string | null` +- actions: `selectBlock(id)`, `cancelSelection()` + +**验收** +- selectBlock 后 selectedBlockId 更新 + +--- + +#### 069 · uiStore + +**端**:前端 **预估**:0.25d **产出**:`src/stores/uiStore.ts` + +**做什么** +- state: `zoomLevel: 100`, `showLabels: true`, `saveStatus: 'saved' | 'unsaved' | 'saving'` +- actions: `setZoom(level)`, `toggleLabels()`, `setSaveStatus(status)` + +**验收** +- 状态可读可写,所有组件响应变化 + +--- + +### 三区联动(070–073) + +--- + +#### 070 · watch selectedBlockId → 配置加载 + +**端**:前端 **预估**:0.5d **产出**:`ConfigPanel.vue` + +**做什么** +```ts +watch(() => selectionStore.selectedBlockId, (blockId) => { + if (!blockId) { form.value = {}; return } + const config = templateStore.configs[blockId] + if (config) { + form.value = { ...config } + } else { + const block = templateStore.getBlockById(blockId) + form.value = { + regionName: block?.text_preview || '', + regionType: 'ai_generate', + dataSources: [], + prompt: '', + outputFormat: 'formal_paragraph', + needReview: true, + remark: '', + enabled: true + } + } +}) +``` + +**验收** +- 已配置的 block 加载已有配置 +- 未配置的 block 显示默认值 + +--- + +#### 071 · watch selectedBlockId → 树节点高亮 + +**端**:前端 **预估**:0.25d **产出**:`StructureTree.vue` + +**做什么** +```ts +watch(() => selectionStore.selectedBlockId, (blockId) => { + highlightNode(blockId) + if (blockId) expandParents(blockId) +}) +``` + +**验收** +- 选中后树节点高亮,父级自动展开 + +--- + +#### 072 · 页面初始化 loading + +**端**:前端 **预估**:0.25d **产出**:`TemplateEdit.vue` + +**做什么** +- 页面 mounted 时: + 1. `loading = true` + 2. 调用 `templateStore.fetchTemplate(id)` + 3. 成功 → `loading = false` +- loading 状态:全屏半透明遮罩 + `` 加载动画 + +**验收** +- 加载时显示 loading,完成后内容出现 + +--- + +#### 073 · 加载失败错误页 + +**端**:前端 **预估**:0.25d **产出**:`TemplateEdit.vue` + +**做什么** +- 加载失败时显示:错误图标 + "加载失败" + 错误信息 + 重新加载按钮 +- 点击重新加载重试 fetchTemplate + +**验收** +- 模拟网络断开时显示错误页 + +--- + +## 附录:数据库表结构 + +### template 表 + +```sql +CREATE TABLE template ( + id INT AUTO_INCREMENT PRIMARY KEY, + name VARCHAR(200) NOT NULL, + type VARCHAR(50) DEFAULT 'report', + version VARCHAR(20) DEFAULT 'v1.0.0', + original_file_path VARCHAR(500) NOT NULL, + status TINYINT DEFAULT 1, + created_by VARCHAR(50), + created_at DATETIME DEFAULT CURRENT_TIMESTAMP, + updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP +); +``` + +### template_block 表 + +```sql +CREATE TABLE template_block ( + id INT AUTO_INCREMENT PRIMARY KEY, + template_id INT NOT NULL, + block_id VARCHAR(50) NOT NULL, + parent_block_id VARCHAR(50), + block_type VARCHAR(20) NOT NULL, + block_name VARCHAR(200), + text_preview VARCHAR(500), + level INT DEFAULT 0, + sort_order INT DEFAULT 0, + table_rows INT, + table_cols INT, + created_at DATETIME DEFAULT CURRENT_TIMESTAMP, + FOREIGN KEY (template_id) REFERENCES template(id) ON DELETE CASCADE, + INDEX idx_template_id (template_id) +); +``` + +### block_config 表 + +```sql +CREATE TABLE block_config ( + id INT AUTO_INCREMENT PRIMARY KEY, + template_id INT NOT NULL, + block_id VARCHAR(50) NOT NULL, + region_name VARCHAR(200), + region_type VARCHAR(30) DEFAULT 'ai_generate', + data_sources TEXT, + prompt TEXT, + output_format VARCHAR(30) DEFAULT 'formal_paragraph', + need_review TINYINT DEFAULT 1, + remark TEXT, + enabled TINYINT DEFAULT 1, + created_at DATETIME DEFAULT CURRENT_TIMESTAMP, + updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + FOREIGN KEY (template_id) REFERENCES template(id) ON DELETE CASCADE, + UNIQUE KEY uk_template_block (template_id, block_id) +); +``` + +--- + +## 附录:第一阶段接口清单 + +| 方法 | 路径 | 任务 | +|------|------|:----:| +| GET | `/health` | 001 | +| POST | `/api/templates/upload` | 018 | +| GET | `/api/templates/{template_id}` | 030 | +| POST | `/api/templates/{template_id}/blocks/{block_id}/config` | 031 | +| GET | `/api/data-sources` | 032 | +| POST | `/api/data-sources` | 033 | + +--- + +## 附录:Ant Design Vue 组件对照 + +| 用途 | Ant Design Vue 组件 | +|------|-------------------| +| 按钮 | `` | +| 文本输入 | `` | +| 下拉选择 | `` | +| 多行文本 | ``(自带 `show-count` 字数统计) | +| 标签 | `` | +| 单选框 | ` ` | +| 开关 | `` | +| 加载动画 | `` | +| 消息提示 | `message.success()` / `message.error()`(从 `ant-design-vue` import) | diff --git a/docs/AI文档模板系统-完整原型-20260701-115332.html b/docs/AI文档模板系统-完整原型-20260701-115332.html new file mode 100644 index 0000000..6bfdea6 --- /dev/null +++ b/docs/AI文档模板系统-完整原型-20260701-115332.html @@ -0,0 +1,618 @@ + + + + + +AI 文档模板系统 · 原型 + + + + +
+ + + + +
+ + +
+ +
+
8
模板总数
+
5
已启用
+
3
本周使用
+
12
累计生成
+
+
+
+
+ + +
+
+
+ + + + + + + + + + + +
模板名称类型版本区域数状态更新时间操作
季度经济活动分析报告报告类v1.28已启用2026-06-28
工作总结报告模板报告类v1.06已启用2026-06-25
述职报告模板报告类v1.05已停用2026-06-20
项目申报书报告类v2.110已启用2026-06-18
会议纪要模板公文类v1.04已启用2026-06-15
合同模板(技术服务)合同类v1.012已启用2026-06-10
整改报告模板报告类v1.05已停用2026-06-05
人才培养方案公文类v1.07已启用2026-05-28
+ +

共 8 条
+ + + + +
+ +
+
+ + v1.0.0 + 已保存 +
+
阅读视图
+
页面视图
+
+
+
100%
+
+ +
+
显示区域标识
+
+ + +
+
+ + +
+ +
+
+
区域配置
+
提示词历史 3
+
+
+ +
+
+
基本信息
+
+
+
+
+ 财务部 + 运行部 + 生技部 + + 添加部门 +
+
+
+ +
73 / 1000
+
+
+
+
0 / 200
+
+ +
+ +
+
+
版本历史
+
v3
请根据上传资料生成本章节内容,要求包括主要指标完成情况、同比变化、原因分析和存在风险。语言要求正式、客观、逻辑清晰。
当前使用 · 周文涛 · 2026-06-28
+
v2
请根据上传资料生成本章节内容,要求包括主要指标完成情况、同比变化和原因分析。
2026-06-20 · 周文涛
+
v1
请根据上传资料生成"主要经营指标完成情况"章节内容。
2026-06-15 · 初始版本
+
+
+
+
+ + +
+
+
2025年第一季度经济活动分析报告
+
某某集团有限公司
+ +
+ block_001 · AI +
一、主要经营指标完成情况 AI 区域
+
+ +
+ block_002 · AI +

本季度公司经营整体保持平稳,各项主要经营指标完成情况良好。营业收入完成12.35亿元,同比上升8.7%;利润总额完成1.25亿元,同比上升5.3%;净利润完成1.02亿元,同比上升4.8%。主要原因是电量增长、成本控制有效以及市场销售情况改善。部分指标虽然完成目标,但也存在一定风险和压力,需要在下一步工作中持续关注和改进。

+
+ +
+ block_003 · 表格 +
二、主要经营指标完成情况表 表格区域
+ + + + + + + + + +
指标名称本期完成值同比增减完成率责任部门原因分析
营业收入(亿元)12.35+8.7%102.3%营销部市场需求增长
利润总额(亿元)1.25+5.3%100.8%财务部成本控制有效
净利润(亿元)1.02+4.8%100.5%财务部综合因素影响
发电量(亿度)45.67+6.2%101.2%运行部设备运行稳定
供电煤耗(克/度)301.5-1.2%99.5%生技部机组负荷率偏低
+
+ +
+ block_004 · AI +
三、存在的主要问题 AI 区域
+
1. 部分指标完成质量不高,存在一定的虚增因素;
+
2. 成本控制压力仍然较大,燃料成本同比上升明显;
+
3. 设备老化问题突出,非计划停运次数较去年同期增加2次;
+
4. 安全风险管控仍需加强,现场违章作业问题时有发生。
+
+ +
+ block_005 · AI +
四、下一步工作措施 AI 区域
+

下一步,公司将重点做好以下工作:一是加强成本管控,深入推进降本增效专项行动,确保完成年度利润目标;二是强化设备管理,加大设备检修维护力度,提高设备可靠性;三是严格落实安全生产责任制,深入开展安全隐患排查治理,坚决杜绝较大及以上安全事故。

+
+ +
+ block_006 · 变量 +
报告单位:某某集团有限公司报告日期:2025年4月15日
+
+
+
+ + +
+
文档结构8 个区域
+
+
+
    +
  • +
    📄全文
    +
      +
    • 📄封面信息
    • +
    • +
      📄一、经营指标完成情况
      +
        +
      • 📝正文
      • +
      • 📊指标完成情况表
      • +
      +
    • +
    • 📄三、存在的主要问题
    • +
    • 📄四、下一步工作措施
    • +
    • 🔒页脚
    • +
    +
  • +
+
+
+
+
+ + +
+ +
+
+
+ + +
+
+ + + + + + + + + + +
任务名称使用模板资料数生成时间状态审核操作
2026Q2 经济活动分析报告季度经济活动分析报告42026-06-30 14:23已完成待审核
上半年工作总结工作总结报告模板32026-06-28 09:15已完成已通过
项目申报书(智慧港口)项目申报书62026-06-25 16:40已完成已通过
5月安全生产整改报告整改报告模板22026-06-20 11:00失败
Q2 会议纪要(月度)会议纪要模板12026-06-18 08:30已完成已驳回
2026Q1 经济活动分析报告季度经济活动分析报告42026-04-05 10:00已完成已通过
+
+
共 6 条
+
+
+ + +
+ +
+
+
提示词模板
+
默认提示词
+
+
+
+
+ +
+
+ + + + + + + + +
模板名称适用场景字数版本更新时间操作
经济活动分析报告 · 总提示词季度/年度经济分析186v32026-06-28
工作总结 · 章节生成工作总结各章节152v22026-06-25
会议纪要 · 要点提取会议记录摘要98v12026-06-20
数据提取 · 表格填充从资料提取数据填表210v12026-06-15
+
+
+
+
+
+ +
+
+
+ + + + + + + \ No newline at end of file