diff --git a/docs/source-analysis.html b/docs/source-analysis.html
index 2e8af27..48aaabb 100644
--- a/docs/source-analysis.html
+++ b/docs/source-analysis.html
@@ -610,7 +610,7 @@
web/app/page.tsx | 旧 React 单对话框生成台源码仍保留,便于以后回滚或抽能力;当前生产根域名已经由 web/canvas-app/ 画布产物覆盖,不再把这个 React 首页作为默认首屏。该页面里的模式也已收敛为文生图、文生视频、图生视频;图生视频只显示“上传图片”,不把“首帧/首尾帧”作为用户入口。旧 TK 复刻工作台组件仍保留在 web/components/ad-recreation-board.tsx,但不再作为默认首页渲染。 |
web/canvas-app/ | SKG 内部画布应用:从 chatfire-AI/huobao-canvas 交互逻辑改造而来。当前策略是“保留成熟画布能力,替换品牌/路由/API”:Vue Flow 节点画布、项目列表、推荐词、AI 润色、自动执行、工作流模板、首帧/尾帧/参考图节点、图片/视频/LLM 配置节点、模型配置和批量下载都保留;可见品牌收敛为 SKG logo,不展示上游注册链接或外部品牌。生产路径固定为根域名 /,内部路由用 /p/:id?;项目列表和画布 JSON 优先同步到服务端 Postgres,浏览器本地存储只是缓存/导入来源;来源说明保存在 THIRD_PARTY_NOTICES.md,不展示给终端用户。 |
web/canvas-app/src/stores/projects.js | 画布项目 Pinia store:启动时先读本地 localStorage["ai-canvas-projects"] 作为缓存,再调用 GET /canvas-projects 拉服务端项目;如果发现本地旧项目,会调用 POST /canvas-projects/import 导入到当前登录用户。新建、重命名、画布节点变更、复制和删除会同步到 /canvas-projects,本地缓存只用于快速打开和网络异常兜底。 |
- web/canvas-app/src/views/Canvas.vue | 画布主交互:恢复上游底部 prompt composer、AI 润色、自动执行、推荐词、节点菜单、工作流面板、API/模型设置入口和批量下载入口。自动执行会调用 useWorkflowOrchestrator 分析提示词,创建文生图、图转视频、故事板、多角度分镜或绘本节点组;手动模式只创建文本节点,用户自行连接节点。 |
+ web/canvas-app/src/views/Canvas.vue | 画布主交互:恢复上游底部 prompt composer、AI 润色、自动执行、推荐词、节点菜单、工作流面板、API/模型设置入口和批量下载入口。自动执行会调用 useWorkflowOrchestrator 分析提示词,创建文生图、图转视频、故事板、多角度分镜或绘本节点组;手动模式只创建文本节点,用户自行连接节点。底部推荐词为短词池,4 个一组单行展示,刷新按钮只轮换下一组,不改变输入面板高度。 |
web/canvas-app/src/config/models.js | 画布媒体模型和规格的前端白名单:图片只内置 auto、gpt-image-2、gemini-3-pro-image-preview,尺寸只内置 auto、1024x1536、1024x1024、1536x1024;视频只内置 seedance / Seedance 2.0 Fast,画幅和时长对齐后端 /health 能力边界。useModelConfig.js 和 Pinia 模型 store 会忽略浏览器本地自定义图片/视频模型,防止旧缓存把不可用模型带回生成下拉。 |
web/canvas-app/src/hooks/useApi.js | 画布到本项目后端的适配层:不再读取浏览器 API Key,而是使用当前登录会话 Cookie 调用 /api。文生图 / 图生图先创建轻量 creative job,再调用 /frames/0/generate;文生视频 / 图生视频调用 /storyboard/video 并轮询 /jobs/{id},完成后把图片或 mp4 URL 写回画布节点。useChat 已从 SKG 广告文案接口切到 /prompt/polish:AI 润色显式使用 image/video prompt 模式,LLM 节点使用通用 chat 模式,避免自动注入用户没有提到的 SKG 或营销语境;后端会判断原提示词是否有人物意图,无人物时禁止新增人物,有人物时才声明虚构 AI 角色。 |
web/scripts/sync-canvas-root.mjs | 构建桥接脚本:在 next build 静态导出完成后,把 Vite 画布产物 web/canvas-app/dist 覆盖到 web/out 根目录,使 https://marketing.skg.com 登录后直接进入画布;旧 web/scripts/sync-canvas-dist.mjs 保留但不再由生产构建调用。 |
@@ -1243,6 +1243,18 @@ ProductRefStateItem {
变更记录
这个记录不是 git log 的替代品。它记录“产品理解发生了什么变化、影响了哪些源码、你以后描述需求时该怎么说”。后续每次改功能都要补一条。
+
+
+ 2026-05-26 · 推荐词刷新改为短词轮换
+ Canvas
+ UX
+
+
+
问题:画布和首页推荐词是固定数组,旁边刷新按钮没有绑定事件;推荐词如果过长或换行,会把底部输入区撑高。
+
改动:web/canvas-app/src/views/Canvas.vue 和 Home.vue 改为 4 个一组的短推荐词池,点击刷新按钮时切换到下一组;推荐栏固定单行高度,chip 设置最大宽度和截断,按钮加 title / aria-label。
+
影响:用户可连续点刷新切换推荐词,推荐区不会因为文案长度换行或顶起 composer。
+
+
2026-05-26 · AI 润色按人物意图加安全词
diff --git a/web/canvas-app/src/views/Canvas.vue b/web/canvas-app/src/views/Canvas.vue
index cdd35a2..783495b 100644
--- a/web/canvas-app/src/views/Canvas.vue
+++ b/web/canvas-app/src/views/Canvas.vue
@@ -196,17 +196,23 @@
-
-
推荐:
+
+ 推荐:
-
@@ -437,13 +443,20 @@ const nodeTypeOptions = [
const inputPlaceholder = '你可以试着说"帮我生成一个二次元的卡通角色"'
// Quick suggestions | 快捷建议
-const suggestions = [
- '像个魔法森林',
- '三只不同的小猫',
- '生成多角度分镜',
- '夏日田野环绕漫步'
+const suggestionPage = ref(0)
+const suggestionGroups = [
+ ['魔法森林', '三只小猫', '多角度分镜', '夏日田野'],
+ ['雨夜街摊', '产品特写', '水花慢镜', '极简桌面'],
+ ['无人物街景', '夜市霓虹', '电商白底', '咖啡窗边'],
+ ['插画封面', '厨房晨光', '3D 产品', '海边慢步']
]
+const suggestions = computed(() => suggestionGroups[suggestionPage.value % suggestionGroups.length])
+
+const refreshSuggestions = () => {
+ suggestionPage.value = (suggestionPage.value + 1) % suggestionGroups.length
+}
+
// Add new node | 添加新节点
const addNewNode = async (type) => {
// Calculate viewport center position | 计算视口中心位置
diff --git a/web/canvas-app/src/views/Home.vue b/web/canvas-app/src/views/Home.vue
index 921f925..c38ee2a 100644
--- a/web/canvas-app/src/views/Home.vue
+++ b/web/canvas-app/src/views/Home.vue
@@ -54,17 +54,23 @@
-
-
推荐:
+
+ 推荐:
{{ tag }}
-
+
@@ -278,13 +284,20 @@ const renameValue = ref('')
const renameTargetId = ref(null)
// Suggestions tags | 建议标签
-const suggestions = [
- '雨中魔法森林',
- '日式街面美食摄影',
- '瀑布水流飞溅',
- '雨天富声旁边花语'
+const suggestionPage = ref(0)
+const suggestionGroups = [
+ ['魔法森林', '三只小猫', '多角度分镜', '夏日田野'],
+ ['雨夜街摊', '产品特写', '水花慢镜', '极简桌面'],
+ ['无人物街景', '夜市霓虹', '电商白底', '咖啡窗边'],
+ ['插画封面', '厨房晨光', '3D 产品', '海边慢步']
]
+const suggestions = computed(() => suggestionGroups[suggestionPage.value % suggestionGroups.length])
+
+const refreshSuggestions = () => {
+ suggestionPage.value = (suggestionPage.value + 1) % suggestionGroups.length
+}
+
// Format date | 格式化日期
const formatDate = (date) => {
if (!date) return ''