feat: 实现自建情景功能

## 功能概述
- 用户可创建、编辑、删除自定义情景
- 支持自定义情景名称、图标、描述、Prompt、首句引导
- 完整的权限隔离,用户只能管理自己的情景
- 深度集成 Eino 框架,动态加载自建情景 Prompt

## 后端实现
### 数据库
- 新增 user_scenarios 表
- 支持用户配额(最多 20 个)
- 字段验证:description 可选,prompt 最小 10 字符

### API
- GET /api/scenarios - 获取用户情景列表
- POST /api/scenarios - 创建情景
- GET /api/scenarios/:id - 获取详情
- PATCH /api/scenarios/:id - 更新情景
- DELETE /api/scenarios/:id - 删除情景

### Eino 集成
- PipelineState 添加 UserID 字段
- nodes_history 动态加载用户自建情景
- GetScenarioPrompt 支持自建情景优先级

## 前端实现
### 组件
- CreateScenarioModal - 创建情景对话框
- EditScenarioModal - 编辑情景对话框
- ConfigPanel 改造 - 分组显示系统预置和自建情景

### Hook
- useScenarios - 合并系统和自建情景,提供 CRUD 接口

### 国际化
- 中文、英文、日文翻译支持

## 问题修复
- 修复 CORS 问题:使用 Vite 代理
- 统一验证规则:description 可选,prompt 最小 10 字符
- 修复数据库约束:使用 NULLIF 处理空字符串

## 文件变更
新增文件: 13 个
修改文件: 14 个

详见文档: docs/自建情景功能完整文档.md
This commit is contained in:
2026-06-21 15:38:28 +08:00
parent 9ad486d117
commit 1079e22699
24 changed files with 2779 additions and 62 deletions

View File

@@ -0,0 +1,6 @@
-- 004_user_scenarios.down.sql
-- 回滚用户自建情景表
DROP INDEX IF EXISTS idx_user_scenarios_created_at;
DROP INDEX IF EXISTS idx_user_scenarios_user_id;
DROP TABLE IF EXISTS user_scenarios;

View File

@@ -0,0 +1,36 @@
-- 004_user_scenarios.up.sql
-- 用户自建情景表
CREATE TABLE user_scenarios (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
name VARCHAR(50) NOT NULL,
icon VARCHAR(10) DEFAULT '',
description VARCHAR(100) NOT NULL,
prompt TEXT NOT NULL,
greeting VARCHAR(200),
language VARCHAR(10) DEFAULT 'zh-CN',
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
updated_at TIMESTAMP NOT NULL DEFAULT NOW(),
CONSTRAINT unique_user_scenario UNIQUE(user_id, name),
CONSTRAINT check_name_length CHECK (char_length(name) >= 2 AND char_length(name) <= 50),
CONSTRAINT check_description_length CHECK (char_length(description) >= 5 AND char_length(description) <= 100),
CONSTRAINT check_prompt_length CHECK (char_length(prompt) >= 50 AND char_length(prompt) <= 2000)
);
-- 为用户 ID 创建索引,加速查询
CREATE INDEX idx_user_scenarios_user_id ON user_scenarios(user_id);
-- 为创建时间创建索引,用于排序
CREATE INDEX idx_user_scenarios_created_at ON user_scenarios(created_at DESC);
COMMENT ON TABLE user_scenarios IS '用户自建情景表';
COMMENT ON COLUMN user_scenarios.id IS '情景唯一标识';
COMMENT ON COLUMN user_scenarios.user_id IS '所属用户 ID外键关联 users 表';
COMMENT ON COLUMN user_scenarios.name IS '情景名称,如"创意写作导师"';
COMMENT ON COLUMN user_scenarios.icon IS 'Emoji 图标,如"🎨"';
COMMENT ON COLUMN user_scenarios.description IS '简短描述,显示在情景卡片上';
COMMENT ON COLUMN user_scenarios.prompt IS '角色 System Prompt定义 AI 行为';
COMMENT ON COLUMN user_scenarios.greeting IS '首句引导,可选';
COMMENT ON COLUMN user_scenarios.language IS '默认语言,如 zh-CN、en-US';