feat: 拆解单文件 Demo 为 Vite + React 前端工程

- 保留根目录 index.html 作为 v1 单文件原型(不参与构建)
- app/ 下新建 Vite + React 工程(vite.config root 指向 app/,两版互不干扰)
- 状态收敛到 useAppStore(表单/消息/串行确认/一键发品 + 4 条异步编排流)
- 生成卡片重构为结构化数据驱动渲染,按钮为真实 React 事件
- 6 大表单模块卡片化;Agent 意图解析与偏好学习抽为独立 lib
- 功能与视觉与 v1 完全一致,浏览器端全流程回归通过
This commit is contained in:
2026-09-16 13:37:58 +08:00
parent 609e0afb29
commit 01dcd83987
29 changed files with 3872 additions and 19 deletions
+245
View File
@@ -0,0 +1,245 @@
/* ============================================================
* 工具(Tool)定义:Agent 可调用的 8 个生成工具
* buildGen(type, ctx) 返回结构化结果:
* pre —— 助手开场白(应用内静态 HTML,非用户输入)
* card —— 生成卡片结构(head / lines / foot / tips),由 GenCardView 渲染
* data —— 填入表单的结构化数据
* ============================================================ */
/** 自主发品 Agent 的 8 步任务清单 */
export const agentSteps = [
{ label: '商品标题', type: 'title', note: '3 方案·已选高转化款填入' },
{ label: '详细介绍', type: 'intro', note: '四段式卖点已填入' },
{ label: '商品详情', type: 'detail', note: '图文结构已写入编辑器' },
{ label: '商品图片', type: 'image', note: '6 张配图清单已添加' },
{ label: '行程编辑', type: 'itinerary', note: '逐日行程已填入' },
{ label: '价格库存', type: 'price', note: '5 个团期 + 定价已填入' },
{ label: 'SEO 关键词', type: 'seo', note: '6 个高流量词已提取' },
{ label: '合规检查', type: 'check', note: '扫描完成·0 极限词风险' }
]
/** 一键发品的 6 步流程 */
export const ocStepsDef = [
{ label: '商品标题', type: 'title', note: '已选高转化方案' },
{ label: '详细介绍', type: 'intro', note: '四段式卖点' },
{ label: '商品详情', type: 'detail', note: '图文结构就绪' },
{ label: '商品图片', type: 'image', note: '配图清单 6 张' },
{ label: '行程编辑', type: 'itinerary', note: '逐日框架就绪' },
{ label: '价格库存', type: 'price', note: '团期+定价就绪' }
]
/** 各工具的动作名称(对话中展示用) */
export const actionLabel = {
title: '生成商品标题', intro: '生成详细介绍', detail: '生成商品详情', image: '配图建议',
itinerary: '规划行程', price: '价格库存方案', seo: 'SEO 关键词', check: '合规检查'
}
/** 图片占位调色板 */
export const imgPalette = [
{ g: 'linear-gradient(135deg,#ffb300,#ff7a1a)', em: '🚤' },
{ g: 'linear-gradient(135deg,#f59e0b,#ef4444)', em: '🏮' },
{ g: 'linear-gradient(135deg,#8b5cf6,#ec4899)', em: '🏔️' },
{ g: 'linear-gradient(135deg,#22c55e,#ffb300)', em: '🏨' },
{ g: 'linear-gradient(135deg,#f97316,#facc15)', em: '🍲' },
{ g: 'linear-gradient(135deg,#6366f1,#ffb300)', em: '🌅' }
]
/** 表单模块 → 卡片锚点(滚动定位用) */
export const cardMap = {
title: 'card-title', intro: 'card-intro', detail: 'card-detail',
image: 'card-img', itinerary: 'card-itinerary', price: 'card-price'
}
/** 生成 8 类工具的结构化结果(ctx 为当前表单上下文) */
export function buildGen(type, ctx) {
const { dest, days, type: pType, theme } = ctx
const isYn = dest === '云南'
switch (type) {
case 'title': {
const t = [
`【纯玩无购物】${dest}${days}精品${pType}·5A景区全含·${theme}首选`,
`${dest}${days}深度${pType}|一价全含0自费·住${isYn ? '海景' : '景区'}酒店`,
`【${theme}必选】${dest}${days}${pType}·随走随停·金牌向导·赠${isYn ? '洱海游船' : '旅拍'}体验`
]
return {
pre: `结合 <span class="hl">${dest}·${days}·${pType}·${theme}</span> 生成 3 个高点击标题(可多次点击填入切换方案):`,
card: {
head: '✨ 标题方案(三选一)',
lines: t.map((x, i) => `<b>${i + 1}.</b> ${x}`),
foot: { apply: 'title', label: '⚡ 一键填入「商品标题」', regen: true },
tips: [
{ cls: 'ok-pill', text: '含目的地+天数+类型,利于搜索' },
{ cls: '', text: '「无购物」为平台高转化词' }
]
},
data: t
}
}
case 'intro': {
const d = `【${dest}${days}${pType}·${theme}优选】全程 0 购物 0 自费,景区门票一价全含,金牌持证导游全程讲解。\n精选 ${days === '3天2晚' ? '2' : '4'} 晚高分酒店,${isYn ? '大理海景房 + 丽江古城客栈' : '近景区步行可达'},住的舒心才是真度假。\n特色体验:${isYn ? '白族扎染 + 洱海游船 + 野生菌火锅' : '深度环线,不赶路'},孩子玩得开心、大人拍得尽兴。\n服务承诺:行程透明无隐形消费,24h 专属管家,未成团提前 3 天全额退款。`
return {
pre: `围绕「${theme}」人群痛点,按「亮点—住宿—体验—承诺」四段式生成详细介绍:`,
card: {
head: '✨ 详细介绍(列表页卖点摘要)',
lines: d.split('\n'),
foot: { apply: 'intro', label: '⚡ 一键填入「详细介绍」', regen: true },
tips: [
{ cls: 'ok-pill', text: '约 200 字,符合最佳展示长度' },
{ cls: '', text: '含服务承诺,降低决策门槛' }
]
},
data: d
}
}
case 'detail': {
return {
pre: '已生成结构化商品详情(亮点/住宿/餐饮/保障 + 配图占位),可直接在编辑器中继续润色:',
card: {
head: '✨ 商品详情(图文结构)',
lines: [
`<b>行程亮点</b> · 0购物0自费 / 经典IP全含 / ${theme}节奏`,
`<b>住宿安排</b> · ${isYn ? '海景房+古城客栈' : '高分酒店'}`,
`<b>舌尖体验</b> · ${isYn ? '野生菌火锅+风味餐' : '特色餐 3 次'}`,
`<b>服务保障</b> · 金牌导游 / 24h管家 / 全额退款承诺`,
`<b>配图占位</b> · 行程地图 / 酒店实拍 / 餐饮实拍`
],
foot: { apply: 'detail', label: '⚡ 写入「商品详情」编辑器', regen: true },
tips: []
},
data: `<h3>🌟 行程亮点</h3>
<ul>
<li>全程 <b>0 购物 0 自费</b>,行程透明,把时间还给风景</li>
<li>${dest}经典 IP 全含:${isYn ? '石林、洱海、玉龙雪山、丽江古城' : '核心景区深度游览'}</li>
<li>${theme}专属节奏:每日行车 ≤ 3.5 小时,不赶路不早起(可睡到自然醒)</li>
</ul>
<h3>🏨 住宿安排</h3>
<ul>
<li>${isYn ? '大理 1 晚海景房 + 丽江 2 晚古城客栈' : '全程高分舒适型酒店'}</li>
<li>提前公布酒店名单,拒绝到店换酒店</li>
</ul>
<h3>🍜 舌尖体验</h3>
<ul>
<li>${isYn ? '野生菌火锅 + 白族风味餐 + 过桥米线' : '当地特色风味餐 3 次'}</li>
</ul>
<h3>🛡️ 服务保障</h3>
<ul>
<li>持证金牌导游 + 24h 专属管家</li>
<li>未成团提前 3 天全额退款,出行无忧</li>
</ul>
<div class="img-slot">🖼️ 此处建议插入:行程地图 / 实拍酒店 / 餐饮实拍(见「配图建议」)</div>`
}
}
case 'image': {
const list = [
{ label: `${dest}全景主图(横版大图)`, use: '主图' },
{ label: '酒店实拍·房间内饰', use: '详情' },
{ label: '核心景区打卡机位', use: '详情' },
{ label: '特色餐食实拍', use: '详情' },
{ label: `${theme}互动瞬间抓拍`, use: '详情' },
{ label: '行程地图示意', use: '详情' }
]
return {
pre: '根据行程内容生成 <b>6 张配图拍摄脚本</b>(含用途与构图建议):',
card: {
head: '✨ 配图清单(转化率优选顺序)',
lines: list.map((im, i) => `<b>${i + 1}.</b> ${im.label} <span style="color:#86909c;font-size:11px">[${im.use}]</span>`),
foot: { apply: 'image', label: '⚡ 按清单添加到「商品图片」', regen: true },
tips: [
{ cls: 'ok-pill', text: '主图含地标,点击率 +18%' },
{ cls: '', text: '实拍图 > 精修图,差评更少' }
]
},
data: list.map(x => ({ label: x.use === '主图' ? x.label : x.label.replace(/(.*)/, '') }))
}
}
case 'itinerary': {
const dayList = [
{ title: isYn ? '抵达昆明·专车接站' : `抵达${dest}·专车接站`, desc: '落地即接,24h 接站服务,入住酒店后自由活动,推荐逛逛翠湖公园。' },
{ title: isYn ? '石林风景区 → 楚雄' : '核心景区深度游', desc: '上午游览 5A 石林,午后赴楚雄,晚观彝族歌舞表演。' },
{ title: isYn ? '大理古城 → 洱海游船 → 双廊' : '慢节奏主题日', desc: '上午漫步大理古城,午后洱海游船,双廊海边下午茶,看日落。' },
{ title: isYn ? '丽江古城 → 玉龙雪山 → 蓝月谷' : '自由活动日', desc: '索道登玉龙雪山4506m,蓝月谷拍照,晚逛丽江四方街。' },
{ title: isYn ? '束河古镇 → 返回昆明' : '自由活动·休整', desc: '睡到自然醒,逛束河古镇,午后大巴返回昆明。' },
{ title: '返程日·专车送站', desc: '根据航班时间安排送站,行程圆满结束。' }
].slice(0, parseInt(days) || 6)
return {
pre: `按 <span class="hl">${days}·${pType}·${theme}</span> 节奏规划每日行程,张弛有度:`,
card: {
head: '✨ 行程框架(每日含主题与安排)',
lines: dayList.map((d, i) => `<b>D${i + 1}</b> ${d.title}`),
foot: { apply: 'itinerary', label: '⚡ 填入「行程编辑」', regen: true },
tips: [
{ cls: 'ok-pill', text: `每日行车 ≤ 3.5h,适合${theme}` },
{ cls: '', text: 'D1/D6 只做接驳,差评率更低' }
]
},
data: dayList
}
}
case 'price': {
const rows = [
{ date: '2026-09-12', adult: 3299, child: 2299, stock: 18, on: true },
{ date: '2026-09-26', adult: 3499, child: 2399, stock: 12, on: true },
{ date: '2026-10-01', adult: 4199, child: 2899, stock: 25, on: true },
{ date: '2026-10-03', adult: 4199, child: 2899, stock: 5, on: true },
{ date: '2026-10-17', adult: 3399, child: 2349, stock: 20, on: true }
]
return {
pre: `基于近 30 天 <span class="hl">${dest}·${days}·${pType}</span> 成交数据,生成 5 个团期排期与定价(含国庆档):`,
card: {
head: '✨ 价格库存方案',
lines: [
`📊 市场区间:<b>¥2,899-¥4,199</b>(${theme}均价 ¥3,480)`,
`🎯 平季定价:<b>¥3,299</b>(低于均价 5%,点击率预估 +23%)`,
`📈 国庆档:<b>¥4,199</b>·库存充足(预计售罄率 85%)`,
`💡 策略:首月立减 ¥300 冲新品榜,稳定后回调`
],
foot: { apply: 'price', label: '⚡ 填入「价格库存」表', regen: true },
tips: [
{ cls: 'ok-pill', text: '低于均价 5%,排序更优' },
{ cls: 'warn-pill', text: '10-03 团期库存偏低,建议 +10' }
]
},
data: rows
}
}
case 'seo': {
const kw = `${dest}旅游,${dest}${days},${pType},${theme}旅游,${dest}纯玩无购物,${dest}自由行攻略`
const heat = [8200, 6500, 5400, 3900, 2800, 1900]
return {
pre: '提取 <b>6 个高流量关键词</b>,按搜索热度排序:',
card: {
head: '✨ SEO 关键词(月均搜索指数)',
lines: kw.split(',').map((k, i) => `<b>${i + 1}.</b> ${k} <span style="color:#86909c;font-size:11px">热度 ${heat[i]}</span>`),
foot: { apply: null, label: '📋 复制关键词', regen: true },
tips: []
},
data: kw
}
}
case 'check': {
return {
pre: '已对 6 大模块进行 <b>广告法 + 平台规则</b> 双重合规扫描:',
card: {
head: '🛡️ 合规检查报告',
lines: [
'✅ 标题:无「最」「第一」等极限词',
'✅ 详细介绍:无「国家级」「顶级」违禁表述',
'⚠️ 建议:「金牌导游」表述需补充资质证明材料',
'⚠️ 建议:「全额退款」承诺需与退改政策页一致',
'ℹ️ 提示:主图 800×600 以上,避免文字遮挡地标'
],
foot: null,
tips: [
{ cls: 'ok-pill', text: '极限词 0 风险' },
{ cls: 'warn-pill', text: '2 项待补充' },
{ cls: '', text: '审核通过率预估 96%' }
]
},
data: null
}
}
default:
throw new Error('unknown tool type: ' + type)
}
}