Files
delivery-desk/docs/architecture.md

85 lines
5.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 架构与数据模型
## 系统边界
Delivery Desk 是 React + Express 单体应用,前后端共享 `shared/types.ts`。开发环境使用 SQLite 和本地上传目录,正式环境使用 PostgreSQL 和腾讯云 COS。
```mermaid
flowchart LR
browser["工作台 / 客户浏览器"] --> app["Express + React"]
api["外部 API 客户端"] --> app
app --> db["SQLite / PostgreSQL"]
app --> storage["本地 uploads / 腾讯云 COS"]
```
## 产品层级
```text
运营组
└── 项目
└── 作品
└── 验收轮次(每轮一个方案)
```
- 客户会话绑定项目,不能跨项目访问。
- 项目级 API Key 只能访问绑定项目;平台级 Key 可跨组管理项目。
- 历史作品交付集不再是产品层级。`collections` 表仅作为旧数据和旧 URL 的迁移兼容容器。
- `work_versions` 继续保存每轮内容快照,但与 `review_rounds` 强制一对一。
- 升级时如检测到旧的一轮多方案数据,会把额外方案拆成只读的独立历史轮次,保留图片、批注、验收事件和当前活动方案,再建立一轮一方案唯一约束。
## 主要数据表
| 表 | 用途 |
|---|---|
| `operation_groups` | 运营组及状态 |
| `users` / `sessions` | 工作台账号、角色和会话 |
| `customer_sessions` | 项目级客户会话 |
| `projects` | 项目、客户访问配置和自动验收状态 |
| `collections` | 迁移期内部兼容容器,不属于产品层级 |
| `notes` | 作品当前状态、活动轮次和项目归属 |
| `review_rounds` | 验收轮次与完成原因 |
| `work_versions` | 单轮内容快照;每轮恰好一条 |
| `images` | 轮次图片、顺序和存储信息 |
| `annotations` | 图片坐标批注 |
| `text_annotations` | 标题、正文和 Tag 选区批注与文本上下文 |
| `work_comments` | 作品总体反馈 |
| `review_events` | 提交、退修、通过和重新打开记录 |
| `api_keys` | 平台级/项目级 API Key 哈希 |
| `storage_configs` | 加密后的 COS 配置 |
| `audit_logs` | 管理与业务审计 |
## 状态计算
作品状态为 `draft``pending``changes_requested``approved`。只有活动轮次可新增批注和作出验收决定;新轮次会锁定旧轮次。客户通过活动轮次后作品为已通过,退修后运营通过新轮次提交修改。
项目验收状态自动计算:
- 没有非草稿作品:`draft`
- 存在未通过作品:`reviewing`
- 所有非草稿作品通过:`completed`
- 人工归档:`archived`
完成项目为只读。新增作品、创建新轮次或由管理员重新打开作品时,项目恢复为验收中;已关闭或归档项目始终只读。开放反馈不会阻止通过;通过时仍为开放的反馈会标记为随该轮验收关闭,历史内容保留。
## 批注模型
- 作品缩略图只展示现有坐标标记,不能新增坐标批注;点击标记会联动打开验收协作面板中的对应反馈。
- 点击图片打开悬浮图片窗格;只有该窗格可以新增坐标批注,并支持原图查看、缩放和前后切换。点击窗格外会同时关闭图片窗格和验收协作面板。
- 标题、正文和 Tag 批注保存 `start_offset``end_offset``selected_text` 及前后文,提交时校验选区仍与轮次快照一致。
- `GET /api/works/:workId/annotations` 按轮次返回图片批注、文字批注、总体反馈和验收事件。
- `GET /api/works/:workId/optimization-context?round=N` 聚合指定轮次的内容、图片和可执行反馈,默认排除已关闭或撤回记录,供外部内容优化流程只读使用。
## Agent 安全上传
内置 Agent Skill 固定连接 `http://192.168.30.90:3010`,采用“发现目标 → 操作者确认运营组和项目 → 生成计划 → 操作者确认内容与确认码 → 单次写入 → 读取核验”的两阶段确认流程。计划文件只保存目标 ID、待写内容和确认摘要不保存 API Key并写入已被 Git 忽略的 `tmp/` 目录。
新建作品以 `externalId` 保证幂等;新增验收轮次没有幂等键。轮次写入超时或响应不明确时,必须先重新读取作品状态,不能直接重试,以免重复创建轮次。
## 存储
平台管理员可在管理页保存和测试 COS 配置。SecretId/SecretKey 使用 `COS_CONFIG_ENCRYPTION_KEY` 派生的 AES-256-GCM 密钥加密,读取接口不返回明文。连接测试会上传、读取并删除临时对象。
外部 API 图片统一归一到当前活动 COS所有 URL 会先拒绝本机、私有网段、局域网和保留地址;与配置的 COS 公开域名或 CDN 域名同源时直接保存,其他公开 URL 经 DNS SSRF 防护、图片类型和 20 MB 大小校验后下载,并按内容哈希转存到 COS。没有活动 COS 配置时拒绝 URL 导入;全部图片准备成功后才创建作品或新验收轮次。该规则不自动追溯迁移历史图片内容。
外部 Agent 只有本地图片时使用现有 multipart 通道,不使用 Base64。Skill 计划只保存文件路径、大小和 SHA-256执行时重新校验后流式上传服务端以 Sharp 验证真实图片内容,再从临时文件写入活动 COS。