diff --git a/.gitignore b/.gitignore index 87297f6..4e7cc2f 100644 --- a/.gitignore +++ b/.gitignore @@ -23,7 +23,7 @@ dist-ssr *.sln *.sw? uploads -docs +#docs #.claude plugs sillytavern diff --git a/docs/Clannad_v3.1.png b/docs/Clannad_v3.1.png new file mode 100644 index 0000000..3d944a8 Binary files /dev/null and b/docs/Clannad_v3.1.png differ diff --git a/docs/Clannad_v3.1_analysis.md b/docs/Clannad_v3.1_analysis.md new file mode 100644 index 0000000..11ea7c7 --- /dev/null +++ b/docs/Clannad_v3.1_analysis.md @@ -0,0 +1,357 @@ +# Clannad_v3.1.png 案例分析与落地要点 + +## 目标角色卡概览 + +- **图像**:@docs/Clannad_v3.1.png(图片来源、版权信息见下方字段) +- **风格**:Clannad 系列日系校园少女题材,具有较强的情感表达与背景设定需求 +- **已知需求**:在云酒馆系统中以“前端卡”方式呈现,并能注入背景信息、变量、互动 UI + +--- + +## 10.1 数据字段与数据模型需求 + +| 字段名 | 说明 | 备注 | +|--------|------|------| +| portrait_url | 图片主地址 | 建议使用 CDN 托管,支持 webp/AVIF 高效格式 | +| portrait_alt | 无障碍文本描述 | 供屏幕阅读器使用,描述角色外观特征 | +| thumbnail_url | 缩略图地址 | 列表页展示使用,建议 200x200 以内 | +| portrait_caption | 图片简短说明 | 显示在图片下方的简短描述 | +| image_source | 版权信息/出处 | 记录图片来源、授权信息 | +| worldbook_id | 关联的 Worldbook | 用于注入背景设定 | +| worldbook_entries | 世界书条目集合 | 用于背景信息注入 | +| name | 角色名称 | 现有字段 | +| description | 角色描述 | 现有字段 | +| personality | 性格设定 | 现有字段 | +| scenario | 场景设定 | 现有字段 | +| first_mes | 开场白 | 现有字段 | +| mes_example | 对话示例 | 现有字段 | +| system_prompt | 系统提示词 | 现有字段 | +| extensions | 扩展数据 | MVU 相关字段 | +| variables | 变量定义 | MVU 相关字段 | + +--- + +## 10.2 后端改动要点 + +### 10.2.1 数据模型扩展 + +在 `model/app/ai_character.go` 中新增以下字段: + +```go +type AICharacter struct { + // ... 现有字段 ... + + // 图片相关字段 + PortraitURL string `json:"portraitUrl" gorm:"type:varchar(500)"` + PortraitAlt string `json:"portraitAlt" gorm:"type:varchar(200)"` + ThumbnailURL string `json:"thumbnailUrl" gorm:"type:varchar(500)"` + PortraitCaption string `json:"portraitCaption" gorm:"type:varchar(200)"` + ImageSource string `json:"imageSource" gorm:"type:varchar(500)"` // 版权信息 + + // Worldbook 关联 + WorldbookID *uint `json:"worldbookId"` +} +``` + +### 10.2.2 API 接口 + +- **上传图片**:`POST /api/v1/app/character/:id/portrait` + - 鉴权:需要用户登录 + - 校验:文件大小(建议最大 5MB)、格式(支持 jpg/png/webp/gif) + - 返回:portrait_url、thumbnail_url + +- **获取角色图片信息**:`GET /api/v1/app/character/:id` + - 返回字段包含 portrait_url、portrait_alt、thumbnail_url、portrait_caption、image_source + +### 10.2.3 Worldbook 关联增强 + +在 `conversation.go` 的 system prompt 构建流程中,增加对角色关联 Worldbook 的背景注入: + +- 读取 `character.WorldbookID` +- 通过 WorldbookEngine 查询对应的启用条目 +- 将背景信息注入到 system_prompt 中(需控制 token budget) + +### 10.2.4 数据迁移 + +为现有角色卡补充默认字段值: + +```sql +ALTER TABLE ai_characters +ADD COLUMN IF NOT EXISTS portrait_url VARCHAR(500), +ADD COLUMN IF NOT EXISTS portrait_alt VARCHAR(200), +ADD COLUMN IF NOT EXISTS thumbnail_url VARCHAR(500), +ADD COLUMN IF NOT EXISTS portrait_caption VARCHAR(200), +ADD COLUMN IF NOT EXISTS image_source VARCHAR(500), +ADD COLUMN IF NOT EXISTS worldbook_id UINT REFERENCES worldbooks(id); +``` + +--- + +## 10.3 前端实现要点 + +### 10.3.1 角色卡片组件 + +在 `web-app/src/components/` 中新增或扩展角色卡片组件: + +```tsx +interface CharacterCardProps { + portraitUrl?: string; + portraitAlt?: string; + thumbnailUrl?: string; + portraitCaption?: string; + // ... 其他字段 +} + +const CharacterPortrait: React.FC = ({ + portraitUrl, + portraitAlt, + thumbnailUrl, + portraitCaption +}) => { + if (!portraitUrl) return null; + + return ( +
+ {portraitAlt + {portraitCaption && ( +

{portraitCaption}

+ )} +
+ ); +}; +``` + +### 10.3.2 样式隔离 + +使用 CSS Modules 或在组件级别定义样式: + +```css +/* CharacterPortrait.module.css */ +.character-portrait { + display: flex; + flex-direction: column; + align-items: center; +} + +.portrait-image { + max-width: 300px; + border-radius: 8px; +} + +.portrait-caption { + font-size: 14px; + color: #666; + margin-top: 8px; +} +``` + +### 10.3.3 沙箱渲染 + +对于需要执行脚本的前端卡,使用 iframe 沙箱: + +```tsx +const FrontendCardSandbox: React.FC<{ htmlContent: string }> = ({ htmlContent }) => { + return ( +