docs: 统一文档风格
This commit is contained in:
@@ -1,9 +1,5 @@
|
|||||||
# CamTalk Eino 框架与编排设计
|
# CamTalk Eino 框架与编排设计
|
||||||
|
|
||||||
> 创建日期:2026-06-19
|
|
||||||
> 状态:已实施
|
|
||||||
> 合并自:`10-Eino重构方案.md` + `11-Eino框架技术文档.md`
|
|
||||||
|
|
||||||
## 1. 概述
|
## 1. 概述
|
||||||
|
|
||||||
### 1.1 为什么选择 Eino
|
### 1.1 为什么选择 Eino
|
||||||
|
|||||||
@@ -1,9 +1,5 @@
|
|||||||
# 情景切换功能
|
# 情景切换功能
|
||||||
|
|
||||||
**状态**: ✅ 已完成
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 功能概述
|
## 功能概述
|
||||||
|
|
||||||
情景切换功能允许用户选择不同的对话场景,AI 会根据选择的情景扮演不同的角色:
|
情景切换功能允许用户选择不同的对话场景,AI 会根据选择的情景扮演不同的角色:
|
||||||
|
|||||||
@@ -1,24 +1,8 @@
|
|||||||
# 自建情景功能完整文档
|
# 自建情景功能
|
||||||
|
|
||||||
**最后更新**: 2026-06-21
|
## 概述
|
||||||
**开发者**: Claude Code + cfy
|
|
||||||
**状态**: ✅ 开发完成(80%),待测试验证
|
|
||||||
|
|
||||||
---
|
用户可以创建自己的情景,而不仅限于系统预置的 5 种情景。
|
||||||
|
|
||||||
## 📊 总体进度
|
|
||||||
|
|
||||||
**当前状态**: ✅ **Phase 1-4 已完成**
|
|
||||||
**完成度**: 🟢 **80%** (4/5 Phases)
|
|
||||||
**剩余**: Phase 5 测试验证
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 一、功能概述
|
|
||||||
|
|
||||||
### 核心功能
|
|
||||||
|
|
||||||
用户可以创建自己的情景,而不仅限于系统预置的 5 种情景:
|
|
||||||
|
|
||||||
**系统预置情景**(不可修改):
|
**系统预置情景**(不可修改):
|
||||||
- 💬 自由对话
|
- 💬 自由对话
|
||||||
@@ -34,7 +18,7 @@
|
|||||||
- 📖 历史学家
|
- 📖 历史学家
|
||||||
- ... (用户自由创建)
|
- ... (用户自由创建)
|
||||||
|
|
||||||
### 用户旅程
|
**用户旅程**:
|
||||||
|
|
||||||
```
|
```
|
||||||
1. 用户点击"创建情景"按钮
|
1. 用户点击"创建情景"按钮
|
||||||
@@ -59,29 +43,32 @@
|
|||||||
8. AI 按照用户设定的 Prompt 扮演角色
|
8. AI 按照用户设定的 Prompt 扮演角色
|
||||||
```
|
```
|
||||||
|
|
||||||
**权限隔离**: 每个用户只能看到和管理自己创建的情景,通过 `user_id` 实现数据隔离。
|
**核心特性**:完整 CRUD 操作(创建/查看/编辑/删除),通过 `user_id` 实现用户数据完全隔离,Eino Graph 管线深度集成(动态加载自建情景 Prompt),中文/英文/日文全覆盖,Modal 对话框 + 图标选择器 + Prompt 编写指南,创建后立即可用无需刷新。
|
||||||
|
|
||||||
---
|
## 技术架构
|
||||||
|
|
||||||
## 二、技术实现架构
|
### 数据流
|
||||||
|
|
||||||
### 2.1 数据流图
|
**创建情景**:
|
||||||
|
|
||||||
```
|
```
|
||||||
【创建情景】
|
|
||||||
用户填写表单 → POST /api/scenarios → Handler 验证
|
用户填写表单 → POST /api/scenarios → Handler 验证
|
||||||
→ Repository.Create → PostgreSQL 插入 → 返回情景对象
|
→ Repository.Create → PostgreSQL 插入 → 返回情景对象
|
||||||
|
```
|
||||||
|
|
||||||
【AI 对话使用自建情景】
|
**AI 对话使用自建情景**:
|
||||||
|
|
||||||
|
```
|
||||||
WebSocket 连接 → ServeWS 获取 userID
|
WebSocket 连接 → ServeWS 获取 userID
|
||||||
→ Eino Graph 初始化 → nodes_history 查询 user_scenarios
|
→ Eino Graph 初始化 → nodes_history 查询 user_scenarios
|
||||||
→ GetScenarioPrompt(customScenarios) → 构建 System Prompt
|
→ GetScenarioPrompt(customScenarios) → 构建 System Prompt
|
||||||
→ LLM 生成回复
|
→ LLM 生成回复
|
||||||
```
|
```
|
||||||
|
|
||||||
### 2.2 Eino 框架集成
|
### Eino 框架集成
|
||||||
|
|
||||||
|
**数据传递链路**:
|
||||||
|
|
||||||
**数据传递链路**:
|
|
||||||
```
|
```
|
||||||
JWT Token → userID
|
JWT Token → userID
|
||||||
↓
|
↓
|
||||||
@@ -100,19 +87,20 @@ llm.GetScenarioPrompt(scenarioID, language, customScenarios)
|
|||||||
LLM 使用自建情景 Prompt
|
LLM 使用自建情景 Prompt
|
||||||
```
|
```
|
||||||
|
|
||||||
**关键修改文件**:
|
**关键修改文件**:
|
||||||
1. `backend/internal/eino/state.go` — PipelineState 添加 `UserID`
|
|
||||||
2. `backend/internal/eino/types.go` — PipelineInput 添加 `UserID`
|
|
||||||
3. `backend/internal/eino/graph.go` — 接受 `scenarioRepo` 参数
|
|
||||||
4. `backend/internal/eino/adapter.go` — 设置 UserID
|
|
||||||
5. `backend/internal/eino/nodes_history.go` — 查询自建情景
|
|
||||||
6. `backend/internal/ws/handler.go` — 首句引导支持自建情景
|
|
||||||
|
|
||||||
---
|
| 文件 | 变更说明 |
|
||||||
|
|------|----------|
|
||||||
|
| `backend/internal/eino/state.go` | PipelineState 添加 `UserID` |
|
||||||
|
| `backend/internal/eino/types.go` | PipelineInput 添加 `UserID` |
|
||||||
|
| `backend/internal/eino/graph.go` | 接受 `scenarioRepo` 参数 |
|
||||||
|
| `backend/internal/eino/adapter.go` | 设置 UserID |
|
||||||
|
| `backend/internal/eino/nodes_history.go` | 查询自建情景 |
|
||||||
|
| `backend/internal/ws/handler.go` | 首句引导支持自建情景 |
|
||||||
|
|
||||||
## 三、数据模型设计
|
## 数据模型
|
||||||
|
|
||||||
### 3.1 数据库表结构
|
### 数据库表结构
|
||||||
|
|
||||||
**表名**: `user_scenarios`
|
**表名**: `user_scenarios`
|
||||||
|
|
||||||
@@ -128,7 +116,7 @@ CREATE TABLE user_scenarios (
|
|||||||
language VARCHAR(10) DEFAULT 'zh-CN',
|
language VARCHAR(10) DEFAULT 'zh-CN',
|
||||||
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
|
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
|
||||||
updated_at TIMESTAMP NOT NULL DEFAULT NOW(),
|
updated_at TIMESTAMP NOT NULL DEFAULT NOW(),
|
||||||
|
|
||||||
CONSTRAINT unique_user_scenario UNIQUE(user_id, name),
|
CONSTRAINT unique_user_scenario UNIQUE(user_id, name),
|
||||||
CONSTRAINT check_name_length CHECK (char_length(name) >= 2 AND char_length(name) <= 50),
|
CONSTRAINT check_name_length CHECK (char_length(name) >= 2 AND char_length(name) <= 50),
|
||||||
CONSTRAINT check_description_length CHECK (description IS NULL OR char_length(description) <= 100),
|
CONSTRAINT check_description_length CHECK (description IS NULL OR char_length(description) <= 100),
|
||||||
@@ -141,16 +129,19 @@ CREATE INDEX idx_user_scenarios_created_at ON user_scenarios(created_at DESC);
|
|||||||
```
|
```
|
||||||
|
|
||||||
**字段说明**:
|
**字段说明**:
|
||||||
- `id`: 情景唯一标识
|
|
||||||
- `user_id`: 所属用户,实现数据隔离
|
|
||||||
- `name`: 情景名称(2-50 字符)
|
|
||||||
- `icon`: Emoji 图标(默认 ✨)
|
|
||||||
- `description`: 简短描述(可选,最多 100 字符)
|
|
||||||
- `prompt`: 角色 System Prompt(10-2000 字符)
|
|
||||||
- `greeting`: 首句引导(可选,最多 500 字符)
|
|
||||||
- `language`: 默认语言(zh-CN / en-US / ja-JP)
|
|
||||||
|
|
||||||
### 3.2 后端数据模型
|
| 字段 | 说明 |
|
||||||
|
|------|------|
|
||||||
|
| `id` | 情景唯一标识 |
|
||||||
|
| `user_id` | 所属用户,实现数据隔离 |
|
||||||
|
| `name` | 情景名称(2-50 字符) |
|
||||||
|
| `icon` | Emoji 图标(默认 ✨) |
|
||||||
|
| `description` | 简短描述(可选,最多 100 字符) |
|
||||||
|
| `prompt` | 角色 System Prompt(10-2000 字符) |
|
||||||
|
| `greeting` | 首句引导(可选,最多 500 字符) |
|
||||||
|
| `language` | 默认语言(zh-CN / en-US / ja-JP) |
|
||||||
|
|
||||||
|
### 后端数据模型
|
||||||
|
|
||||||
```go
|
```go
|
||||||
// backend/internal/models/user_scenario.go
|
// backend/internal/models/user_scenario.go
|
||||||
@@ -178,7 +169,7 @@ type CreateUserScenarioRequest struct {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### 3.3 前端数据结构
|
### 前端数据结构
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
// frontend/src/lib/api/scenarios.ts
|
// frontend/src/lib/api/scenarios.ts
|
||||||
@@ -212,11 +203,9 @@ export interface ExtendedScenario {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
## REST API
|
||||||
|
|
||||||
## 四、REST API 设计
|
### API 端点
|
||||||
|
|
||||||
### 4.1 API 端点
|
|
||||||
|
|
||||||
| 方法 | 路径 | 说明 | 权限 |
|
| 方法 | 路径 | 说明 | 权限 |
|
||||||
|------|------|------|------|
|
|------|------|------|------|
|
||||||
@@ -226,9 +215,10 @@ export interface ExtendedScenario {
|
|||||||
| PATCH | `/api/scenarios/:id` | 更新情景 | 需登录 |
|
| PATCH | `/api/scenarios/:id` | 更新情景 | 需登录 |
|
||||||
| DELETE | `/api/scenarios/:id` | 删除情景 | 需登录 |
|
| DELETE | `/api/scenarios/:id` | 删除情景 | 需登录 |
|
||||||
|
|
||||||
### 4.2 API 示例
|
### API 示例
|
||||||
|
|
||||||
|
**创建情景**:
|
||||||
|
|
||||||
#### 创建情景
|
|
||||||
```http
|
```http
|
||||||
POST /api/scenarios
|
POST /api/scenarios
|
||||||
Authorization: Bearer <access_token>
|
Authorization: Bearer <access_token>
|
||||||
@@ -244,36 +234,36 @@ Content-Type: application/json
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
**响应**: 201 Created
|
响应 201 Created:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"id": "uuid-xxx",
|
"id": "uuid-xxx",
|
||||||
"user_id": "uuid-user",
|
"user_id": "uuid-user",
|
||||||
"name": "创意写作导师",
|
"name": "创意写作导师",
|
||||||
"icon": "✨",
|
"icon": "✨"
|
||||||
...
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
#### 获取列表
|
**获取列表**:
|
||||||
|
|
||||||
```http
|
```http
|
||||||
GET /api/scenarios
|
GET /api/scenarios
|
||||||
Authorization: Bearer <access_token>
|
Authorization: Bearer <access_token>
|
||||||
```
|
```
|
||||||
|
|
||||||
**响应**: 200 OK
|
响应 200 OK:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"scenarios": [...],
|
"scenarios": [],
|
||||||
"total": 3
|
"total": 3
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
## 前端实现
|
||||||
|
|
||||||
## 五、前端实现
|
### 组件结构
|
||||||
|
|
||||||
### 5.1 组件结构
|
|
||||||
|
|
||||||
```
|
```
|
||||||
frontend/src/
|
frontend/src/
|
||||||
@@ -291,21 +281,21 @@ frontend/src/
|
|||||||
└── scenarios.ts # API 调用封装
|
└── scenarios.ts # API 调用封装
|
||||||
```
|
```
|
||||||
|
|
||||||
### 5.2 核心 Hook
|
### 核心 Hook
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
// useScenarios.ts
|
// useScenarios.ts
|
||||||
|
|
||||||
export function useScenarios(token: string | null) {
|
export function useScenarios(token: string | null) {
|
||||||
const [allScenarios, setAllScenarios] = useState<ExtendedScenario[]>([]);
|
const [allScenarios, setAllScenarios] = useState<ExtendedScenario[]>([]);
|
||||||
|
|
||||||
// 合并系统预置 + 用户自建
|
// 合并系统预置 + 用户自建
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const systemScenarios = scenarios.map(s => ({...s, isCustom: false}));
|
const systemScenarios = scenarios.map(s => ({...s, isCustom: false}));
|
||||||
const customScenarios = customList.map(s => ({...s, isCustom: true}));
|
const customScenarios = customList.map(s => ({...s, isCustom: true}));
|
||||||
setAllScenarios([...systemScenarios, ...customScenarios]);
|
setAllScenarios([...systemScenarios, ...customScenarios]);
|
||||||
}, [customList]);
|
}, [customList]);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
allScenarios,
|
allScenarios,
|
||||||
createScenario,
|
createScenario,
|
||||||
@@ -315,9 +305,10 @@ export function useScenarios(token: string | null) {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### 5.3 创建情景表单
|
### 创建情景表单
|
||||||
|
|
||||||
|
**表单字段**:
|
||||||
|
|
||||||
**表单字段**:
|
|
||||||
- 名称(必填,2-50 字符)
|
- 名称(必填,2-50 字符)
|
||||||
- 图标(可选,24 个预设 emoji)
|
- 图标(可选,24 个预设 emoji)
|
||||||
- 描述(可选,最多 100 字符)
|
- 描述(可选,最多 100 字符)
|
||||||
@@ -325,175 +316,15 @@ export function useScenarios(token: string | null) {
|
|||||||
- 首句引导(可选,最多 500 字符)
|
- 首句引导(可选,最多 500 字符)
|
||||||
- 语言(可选,默认 zh-CN)
|
- 语言(可选,默认 zh-CN)
|
||||||
|
|
||||||
**表单验证**:
|
**表单验证**:
|
||||||
|
|
||||||
- 实时字符计数
|
- 实时字符计数
|
||||||
- 长度限制提示
|
- 长度限制提示
|
||||||
- 必填项高亮
|
- 必填项高亮
|
||||||
|
|
||||||
---
|
## 使用指南
|
||||||
|
|
||||||
## 六、实施进度
|
### 后端 API 测试
|
||||||
|
|
||||||
### ✅ Phase 1: 后端基础(100% 完成)
|
|
||||||
|
|
||||||
**1.1 数据库迁移** ✅
|
|
||||||
- 文件: `backend/migrations/004_user_scenarios.up.sql`
|
|
||||||
- 创建 `user_scenarios` 表
|
|
||||||
- 添加索引和约束
|
|
||||||
|
|
||||||
**1.2 数据模型** ✅
|
|
||||||
- 文件: `backend/internal/models/user_scenario.go`
|
|
||||||
- 定义 `UserScenario` 结构体
|
|
||||||
- 定义请求/响应模型
|
|
||||||
|
|
||||||
**1.3 Repository 层** ✅
|
|
||||||
- 文件: `backend/internal/store/user_scenario_repository.go`
|
|
||||||
- 实现 `UserScenarioRepository` 接口
|
|
||||||
- CRUD 操作 + 权限校验
|
|
||||||
|
|
||||||
**1.4 REST API** ✅
|
|
||||||
- 文件: `backend/internal/api/user_scenario_handler.go`
|
|
||||||
- 5 个 HTTP 端点(创建/列表/详情/更新/删除)
|
|
||||||
- 输入验证和错误处理
|
|
||||||
|
|
||||||
### ✅ Phase 2: 后端集成(100% 完成)
|
|
||||||
|
|
||||||
**2.1 Prompt 加载逻辑** ✅
|
|
||||||
- 修改: `backend/internal/ai/llm/scenarios.go`
|
|
||||||
- `GetScenarioPrompt` 支持自建情景
|
|
||||||
- `GetScenarioGreeting` 支持自建情景
|
|
||||||
|
|
||||||
**2.2 Eino 框架集成** ✅
|
|
||||||
- 修改 7 个文件,完整数据链路
|
|
||||||
- PipelineState 添加 UserID
|
|
||||||
- nodes_history 查询用户自建情景
|
|
||||||
- 动态构建 System Prompt
|
|
||||||
|
|
||||||
### ✅ Phase 3: 前端 UI(100% 完成)
|
|
||||||
|
|
||||||
**3.1 API 封装** ✅
|
|
||||||
- 文件: `frontend/src/lib/api/scenarios.ts`
|
|
||||||
- 5 个 API 调用函数
|
|
||||||
|
|
||||||
**3.2 Hook 封装** ✅
|
|
||||||
- 文件: `frontend/src/hooks/useScenarios.ts`
|
|
||||||
- `useScenarios` Hook
|
|
||||||
- 合并系统预置 + 自建情景
|
|
||||||
|
|
||||||
**3.3 组件实现** ✅
|
|
||||||
- `CreateScenarioModal` — 创建对话框
|
|
||||||
- `EditScenarioModal` — 编辑对话框
|
|
||||||
- `ConfigPanel` 改造 — 分组显示 + 编辑/删除
|
|
||||||
|
|
||||||
**3.4 i18n 支持** ✅
|
|
||||||
- 中文/英文/日文翻译(+40 条)
|
|
||||||
|
|
||||||
**3.5 样式实现** ✅
|
|
||||||
- Modal、表单、图标选择器样式
|
|
||||||
|
|
||||||
### ✅ Phase 4: 前端集成(100% 完成)
|
|
||||||
|
|
||||||
**4.1 主应用集成** ✅
|
|
||||||
- 文件: `frontend/src/App.tsx`
|
|
||||||
- 集成 `useScenarios` Hook
|
|
||||||
- 渲染 Modal 组件
|
|
||||||
- 情景选择联动
|
|
||||||
|
|
||||||
**4.2 编译验证** ✅
|
|
||||||
- 前端: 669.96 kB JS + 55.80 kB CSS
|
|
||||||
- 后端: 48MB 二进制
|
|
||||||
|
|
||||||
### ⏳ Phase 5: 测试验证(待进行)
|
|
||||||
|
|
||||||
**5.1 后端测试**
|
|
||||||
- [ ] 数据库迁移验证
|
|
||||||
- [ ] REST API CRUD 测试
|
|
||||||
- [ ] 权限隔离测试
|
|
||||||
- [ ] Eino Graph 自建情景加载测试
|
|
||||||
|
|
||||||
**5.2 前端测试**
|
|
||||||
- [ ] 创建情景表单验证
|
|
||||||
- [ ] 编辑情景数据预填充
|
|
||||||
- [ ] 删除情景二次确认
|
|
||||||
- [ ] 情景列表实时更新
|
|
||||||
|
|
||||||
**5.3 集成测试**
|
|
||||||
- [ ] 创建自建情景后立即可用
|
|
||||||
- [ ] 切换到自建情景显示首句引导
|
|
||||||
- [ ] AI 对话使用自建 Prompt
|
|
||||||
- [ ] 多用户并发隔离
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 七、已完成文件清单
|
|
||||||
|
|
||||||
### 新增文件(13 个)
|
|
||||||
|
|
||||||
**后端(5 个)**:
|
|
||||||
1. `backend/migrations/004_user_scenarios.up.sql`
|
|
||||||
2. `backend/migrations/004_user_scenarios.down.sql`
|
|
||||||
3. `backend/internal/models/user_scenario.go`
|
|
||||||
4. `backend/internal/store/user_scenario_repository.go`
|
|
||||||
5. `backend/internal/api/user_scenario_handler.go`
|
|
||||||
|
|
||||||
**前端(5 个)**:
|
|
||||||
6. `frontend/src/lib/api/scenarios.ts`
|
|
||||||
7. `frontend/src/hooks/useScenarios.ts`
|
|
||||||
8. `frontend/src/components/CreateScenarioModal/index.tsx`
|
|
||||||
9. `frontend/src/components/EditScenarioModal/index.tsx`
|
|
||||||
|
|
||||||
**文档(3 个)**:
|
|
||||||
10. `docs/自建情景功能设计方案.md`
|
|
||||||
11. `docs/自建情景功能-权限隔离说明.md`
|
|
||||||
12. `docs/自建情景功能实施进度.md`
|
|
||||||
13. `docs/自建情景功能完整文档.md` (本文件)
|
|
||||||
|
|
||||||
### 修改文件(14 个)
|
|
||||||
|
|
||||||
**后端(8 个)**:
|
|
||||||
1. `backend/cmd/server/main.go` — 注册 API 路由 + 传递 scenarioRepo
|
|
||||||
2. `backend/internal/ai/llm/scenarios.go` — Prompt/Greeting 加载支持自建
|
|
||||||
3. `backend/internal/eino/state.go` — 添加 UserID 字段
|
|
||||||
4. `backend/internal/eino/types.go` — PipelineInput 添加 UserID
|
|
||||||
5. `backend/internal/eino/graph.go` — 接受并传递 scenarioRepo
|
|
||||||
6. `backend/internal/eino/adapter.go` — 复制 UserID 到 State
|
|
||||||
7. `backend/internal/eino/nodes_history.go` — 加载自建情景
|
|
||||||
8. `backend/internal/ws/handler.go` — 首句引导支持自建情景
|
|
||||||
|
|
||||||
**前端(6 个)**:
|
|
||||||
9. `frontend/src/App.tsx` — 集成自建情景管理
|
|
||||||
10. `frontend/src/components/ConfigPanel/index.tsx` — 分组显示 + 编辑/删除
|
|
||||||
11. `frontend/src/lib/i18n/zh-CN.ts` — 新增翻译
|
|
||||||
12. `frontend/src/lib/i18n/en-US.ts` — 新增翻译
|
|
||||||
13. `frontend/src/lib/i18n/ja-JP.ts` — 新增翻译
|
|
||||||
14. `frontend/src/App.css` — 新增样式
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 八、问题解决记录
|
|
||||||
|
|
||||||
### 8.1 CORS 错误
|
|
||||||
|
|
||||||
**问题**: 前端直接访问 `http://localhost:8080` 触发 CORS
|
|
||||||
**解决**: 将 `API_BASE` 改为空字符串,使用 Vite 代理
|
|
||||||
|
|
||||||
### 8.2 验证规则不一致
|
|
||||||
|
|
||||||
**问题**: 后端要求 `description` 必填,`prompt` 最小 50 字符
|
|
||||||
**解决**: 统一为 `description` 可选,`prompt` 最小 10 字符
|
|
||||||
|
|
||||||
### 8.3 数据库约束错误
|
|
||||||
|
|
||||||
**问题**: 空字符串 `""` 不满足 `char_length >= 1` 约束
|
|
||||||
**解决**:
|
|
||||||
1. 更新约束允许 `description IS NULL`
|
|
||||||
2. Repository 使用 `NULLIF($5, '')` 将空字符串转为 NULL
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 九、测试指南
|
|
||||||
|
|
||||||
### 9.1 后端 API 测试
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# 1. 注册用户
|
# 1. 注册用户
|
||||||
@@ -528,9 +359,8 @@ curl -X DELETE http://localhost:8080/api/scenarios/<id> \
|
|||||||
-H "Authorization: Bearer $TOKEN"
|
-H "Authorization: Bearer $TOKEN"
|
||||||
```
|
```
|
||||||
|
|
||||||
### 9.2 前端功能测试
|
### 前端功能测试
|
||||||
|
|
||||||
**操作步骤**:
|
|
||||||
1. 刷新浏览器(Cmd+Shift+R)
|
1. 刷新浏览器(Cmd+Shift+R)
|
||||||
2. 登录账户
|
2. 登录账户
|
||||||
3. 打开设置面板(右上角齿轮)
|
3. 打开设置面板(右上角齿轮)
|
||||||
@@ -543,72 +373,53 @@ curl -X DELETE http://localhost:8080/api/scenarios/<id> \
|
|||||||
10. 编辑情景,验证数据预填充
|
10. 编辑情景,验证数据预填充
|
||||||
11. 删除情景,验证二次确认
|
11. 删除情景,验证二次确认
|
||||||
|
|
||||||
---
|
## 安全与限制
|
||||||
|
|
||||||
## 十、功能亮点
|
### 用户配额
|
||||||
|
|
||||||
✅ **完整的 CRUD** — 创建、查看、编辑、删除自建情景
|
|
||||||
✅ **权限隔离** — 用户数据完全隔离,无法互相访问
|
|
||||||
✅ **Eino 深度集成** — 在 Graph Pipeline 中动态加载自建情景
|
|
||||||
✅ **多语言支持** — 中文、英文、日文全覆盖
|
|
||||||
✅ **优雅的 UI** — Modal 对话框 + 图标选择器 + Prompt 编写指南
|
|
||||||
✅ **实时生效** — 创建后立即可用,无需刷新
|
|
||||||
✅ **表单验证** — 字符计数、长度限制、必填项提示
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 十一、安全与限制
|
|
||||||
|
|
||||||
### 11.1 用户配额
|
|
||||||
|
|
||||||
```go
|
```go
|
||||||
const MaxScenariosPerUser = 20 // 每个用户最多 20 个自建情景
|
const MaxScenariosPerUser = 20 // 每个用户最多 20 个自建情景
|
||||||
```
|
```
|
||||||
|
|
||||||
### 11.2 权限控制
|
### 权限控制
|
||||||
|
|
||||||
- 只能查看/编辑/删除自己的情景
|
- 只能查看/编辑/删除自己的情景
|
||||||
- 系统预置情景不可编辑/删除
|
- 系统预置情景不可编辑/删除
|
||||||
- 后端验证 `user_id` 匹配
|
- 后端验证 `user_id` 匹配
|
||||||
|
|
||||||
### 11.3 数据验证
|
### 数据验证
|
||||||
|
|
||||||
**后端**:
|
**后端**:
|
||||||
- 名称: 2-50 字符
|
|
||||||
- 描述: 可选,最多 100 字符
|
- 名称:2-50 字符
|
||||||
- Prompt: 10-2000 字符
|
- 描述:可选,最多 100 字符
|
||||||
- 首句: 可选,最多 500 字符
|
- Prompt:10-2000 字符
|
||||||
|
- 首句引导:可选,最多 500 字符
|
||||||
|
|
||||||
|
**前端**:
|
||||||
|
|
||||||
**前端**:
|
|
||||||
- 实时字符计数
|
- 实时字符计数
|
||||||
- 超长提示
|
- 超长提示
|
||||||
- 必填项高亮
|
- 必填项高亮
|
||||||
|
|
||||||
---
|
## 未来优化方向
|
||||||
|
|
||||||
## 十二、未来优化方向
|
**V1.1**:
|
||||||
|
|
||||||
### V1.1 功能(推荐)
|
|
||||||
- Prompt 模板库
|
- Prompt 模板库
|
||||||
- 实时预览效果
|
- 实时预览效果
|
||||||
- 导入导出功能
|
- 导入导出功能
|
||||||
- 情景搜索和筛选
|
- 情景搜索和筛选
|
||||||
|
|
||||||
### V2.0 功能(长期)
|
**V2.0**:
|
||||||
|
|
||||||
- 情景市场
|
- 情景市场
|
||||||
- 情景分享链接
|
- 情景分享链接
|
||||||
- AI 辅助优化 Prompt
|
- AI 辅助优化 Prompt
|
||||||
- 协作编辑(团队情景)
|
- 协作编辑(团队情景)
|
||||||
|
|
||||||
---
|
## 参考资料
|
||||||
|
|
||||||
## 十三、参考资料
|
|
||||||
|
|
||||||
- [CLAUDE.md](../CLAUDE.md) — 项目开发指南
|
- [CLAUDE.md](../CLAUDE.md) — 项目开发指南
|
||||||
- [02-接口文档.md](./02-接口文档.md) — WebSocket 和 REST API
|
- [02-接口文档.md](./02-接口文档.md) — WebSocket 和 REST API
|
||||||
- [自建情景功能-权限隔离说明.md](./自建情景功能-权限隔离说明.md) — 安全设计
|
- [自建情景功能-权限隔离说明.md](./自建情景功能-权限隔离说明.md) — 安全设计
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**开发完成日期**: 2026-06-21
|
|
||||||
**下一步行动**: 启动服务进行人工测试验证
|
|
||||||
Reference in New Issue
Block a user