- 删除已弃用的 compositor_client.go - 删除激光合成微服务代码 - 添加 gateway 合成控制器和测试文件 - 添加 Dify prompt 补丁脚本 Co-Authored-By: Claude <noreply@anthropic.com>
9.9 KiB
镭射卡风格池 — 轻量抽卡设计
配套代码:
设计哲学
不要游戏化的抽卡 UI,要"概念上的抽卡" —— 每次点击生成,5 张卡都是不同的镭射风格,带来视觉上的惊喜感。
- ✅ 算法按稀有度加权随机(常见款多,稀有款少)
- ✅ 每次生成内容都不一样(grating_config + bg_prompt 全部按抽卡结果)
- ❌ 不在 UI 显示稀有度徽章、星级、配色(避免游戏化)
风格池规模与分层
| 档位 | 数量 | 单抽概率 | 视觉特征 |
|---|---|---|---|
| N (Normal) | 10 | 50% | 银底基础款,常见 |
| R (Rare) | 10 | 30% | Refractor 类,有色彩倾向 |
| SR (Super Rare) | 10 | 15% | Mosaic/Atomic/横纹限量 |
| SSR | 9 | 4% | Full Art/Rainbow/Gold |
| UR (Ultra Rare) | 6 | 1% | Secret/Star/Prismatic |
合计 45 个,保底:第 5 张若前 4 张全是 N,强制抽 R+。
风格分类(完整列表)
N(10)—— 基础银底
classic_silver / moonlight_silver / pearl_basic / frost_silver / warm_silver / graphite_silver / rosegold_base / sky_silver / cream_silver / steel_silver
R(10)—— Refractor 类
prizm_blue / prizm_red / prizm_green / prizm_orange / prizm_purple / prizm_pink / topps_refractor / reverse_holo / bowman_chrome / wave_blue
SR(10)—— 限量工艺
mosaic / shimmer / neon_molectric / disco / topps_atomic / hyper_prizm / cracked_ice / yugioh_super / yugioh_ultra / ws_sr
SSR(9)—— 稀有工艺
rainbow_rare / prizm_gold / prizm_black / cosmic_prizm / prizm_shattered / topps_sepia / pokemon_fullart / yugioh_secret / gold_secret
UR(6)—— 终极稀有
pokemon_star / superfractor / yugioh_starlight / yugioh_platinum / yugioh_prismatic / ws_ssp
用户提示词的处理方式
核心原则:用户描述为主轴,holographic 作为载体/底材
当用户输入 prompt 时,前端 wrapUserPrompt() 会构造如下结构的 prompt:
[用户原始描述,例如 "海报文字风"],
on a [color_hint] holographic metallic card substrate,
single diagonal sheen sweep at [angle]°,
soft pearlescent foil coverage [coverage]%,
subtle rainbow diffraction with intensity [intensity]%,
refined laser card design,
no text, no people, no watermark
关键设计:
- ✅ 用户描述放最前(主轴 → AI 优先遵循)
- ✅ Holographic 描述在主体之后(底材约束 → 保持激光卡美学)
- ✅ 抽卡仍生效(5 张图 grating_config / overlay 各不同,共享同一 user 主题)
- ✅ 后端 controller 不再二次拼接(前端 user_prompt 字段传空)
示例:
| 用户输入 | 包装后 prompt(节选) |
|---|---|
海报文字风 |
海报文字风, on a silver holographic metallic card substrate, single diagonal sheen sweep at 135°, soft pearlescent foil coverage 75%, ..., no text, no people, no watermark |
赛博朋克霓虹 |
赛博朋克霓虹, on a warm silver holographic metallic card substrate, single diagonal sheen sweep at 120°, soft pearlescent foil coverage 85%, ... |
可爱卡哇伊 |
可爱卡哇伊, on a silver holographic metallic card substrate, single diagonal sheen sweep at 130°, soft pearlescent foil coverage 58%, ... |
5 张抽卡结果会共享同一个 user 主题,但每张图的金属底材(角度/覆盖率/强度)不同 → 用户在固定风格下获得多样性。
Style Schema
{
id: 'prizm_blue',
rarity: 'R',
display_name_zh: '蓝棱镜',
display_name_en: 'Prizm Blue',
weight: 7, // 同档位内相对权重
family: 'panini_prizm',
reference: { series, year, note }, // 真实卡牌系列溯源
grating_config: {
sheen_band_angle: 120,
sheen_speed: 0.42,
sheen_intensity: 0.38,
foil_coverage: 0.70,
backdrop_tone: '#A8ACB2'
},
color_hint: '电光蓝 宝石蓝',
bg_prompt: '...', // 英文全量 prompt(锚定工艺 + sheen 角度 + negative)
overlay_prompt: '...',
tags: 'blue,sport,prizm'
}
抽卡算法
gacha.js 主入口 drawGachaStyles(count = 5):
- 单张稀有度:按
RARITY_WEIGHTS = { N: 50, R: 30, SR: 15, SSR: 4, UR: 1 }加权 - 同档内:按 style.weight 二次加权
- 不重复:5 张 ID 集合 size === 5
- 保底:第 5 张时若前 4 张全是 N,强制抽 R+
纯 JS,~80 行,无第三方依赖。
集成模式:虚拟 ID + 实际 prompt
Dify workflow 仅识别旧 5 个 preset_id,但 pool 中有 45 个风格。采用虚拟 ID 模式让 pool 内容真正生效:
抽卡选中: cosmic_prizm (SSR)
↓
preset_id 字段: 'dream'/'classic'/'holoFull'/'ice'/'sunset' 之一(循环取,保 Dify 兼容)
grating_config: cosmic_prizm 的 grating_config(深空紫)
bg_prompt: cosmic_prizm 的 bg_prompt(深空紫渐变 + 星点)
overlay_prompt: cosmic_prizm 的 overlay_prompt
↓
Dify 收到 prompt + grating_config → 生成对应风格的图
↓
前端收到 5 张图,用户感受到"这次是宇宙主题,下次是蓝棱镜"的惊喜
优势:
- ✅ Dify workflow 不重发布
- ✅ 后端零改动
- ✅ 数据库零迁移
- ✅ 用户实际感受到 45 种风格的不同
装饰层(overlay)与背景层(bg)对齐
Dify yml 中装饰层 prompt 模板与背景层采用相同结构 —— 简短引导 + overlay_prompts_all 为主体:
# 修复前(硬编码压制了每张图的差异)
"柔和光晕叠加层,微光粒子飘散...不要边框,不要装饰线...生成5种不同效果: {{overlay_prompts_all}}"
# 修复后(简短引导 + 每张图的 overlay_prompt 主导)
"镭射卡装饰叠加层,透明背景,软光晕与微光粒子飘散...生成5种不同风格的装饰变体: {{overlay_prompts_all}}"
修复后,pool 中 45 个 style 各自的 overlay_prompt(如"star scatter corner"、"floral corner accents"、"geometric mosaic border"等)能真正生效,5 张装饰图会按风格变化。
现有 5 个 Preset 的提示词优化
模板结构(5 段式):
- 整体氛围(mood)
- 工艺特征(holographic/refractor/stripe/foil coverage)
- 色彩描述(具体颜色 + 渐变)
- 光线描述(
single diagonal sheen sweep at 135°与 grating_config 对齐) - 负向提示(
no text, no people, no watermark)
| Preset | 优化后 prompt(摘要) |
|---|---|
| dream | soft dreamy holographic background, lavender and pink layered gradient, ..., single diagonal sheen sweep at 135°, dreamy celestial mood, no text, no people, no watermark |
| classic | classic vintage refractor holographic surface, warm champagne and pale gold gradient, ..., single diagonal sheen sweep at 120°, soft film grain texture, refined retro cardstock mood, ... |
| holoFull | full holographic tech background, silver metallic base with pearl glow, geometric neon circuit lines and star sparks, ..., vivid diagonal sheen sweep at 150°, high foil coverage 95%, ... |
| ice | cool ice holographic background, pale blue-gray base with crystalline frost texture, ..., fast diagonal sheen sweep at 110° (speed 0.50), crisp clean winter mood, ... |
| sunset | warm sunset holographic background, rose-gold base with amber and pink layered glow, ..., gentle diagonal sheen sweep at 140° (speed 0.40), romantic dreamy mood, ... |
为什么优化后更稳定:AI 对抽象形容词理解漂移大,对"holographic + 量化角度"响应稳定。优化后 prompt 与 grating_config 字段对账,避免"参数是冷银但生图是紫色"的不一致。
兼容性矩阵
| 既有调用方 | 改动前行为 | 改动后行为 | 风险 |
|---|---|---|---|
success.vue getLaserPresetByIndex(0) |
返回 dream |
完全一致(PRESET_VARIANTS 未动) |
零 |
useLaserMint 接口 |
不变 | 不变 | 零 |
useLaserBatchGenerate.run() |
presetIds=null → 默认 5 个 | presetIds=null → submit 内部按 userPrompt 抽卡 | 零 |
laserBatchExport.js |
旧 5 个 | 保留不变 | 零 |
| 后端 Gateway | 接收 render_configs | 零改动 | 零 |
| Dify workflow | 接收 5 个 preset_id | 零改动 | 零 |
| 数据库 | 存 preset_id 字符串 | 零改动 | 零 |
验收方法
单元测试(浏览器 console)
// 抽卡分布
const gacha = await import('/utils/laser-card/gacha.js')
const dist = { N: 0, R: 0, SR: 0, SSR: 0, UR: 0 }
for (let i = 0; i < 1000; i++) {
gacha.drawGachaStyles(5).forEach(s => dist[s.rarity]++)
}
console.log(dist) // 应大致 N:2500 R:1500 SR:750 SSR:200 UR:50
// 保底
const noRplus = Array(100).fill(0).filter(() =>
gacha.drawGachaStyles(5).every(s => s.rarity === 'N')
).length
console.log('保底失败次数:', noRplus) // 应为 0
端到端验证
- 启动 dev server
- 进入镭射卡生成页
- 不输入 prompt → 点击生成
- 观察:5 张卡出现,每张视觉不同(不同 grating 角度/不同配色)
- 再次点击生成 → 又一组 5 张,与上次不同
惊喜感验证:连续生成 5 次,每次 5 张卡,应该看到:
- 至少 1-2 张明显色彩倾向(R+ 卡)
- 偶有 1 张视觉特别"满"(SR+ 高 foil_coverage)
- 极少数会"出彩"(UR 的全光谱彩虹)
DevTools Network 验证:
preset_codes=["dream","classic","holoFull","ice","sunset"](虚拟 ID)render_configs[].bg_prompt= 每次都不同(抽卡选出的)- 无
_meta/rarity等额外字段污染后端
不在 Phase 1 范围内
- ❌ Dify workflow 真实派发 45 个 preset_id(需重发)
- ❌ "重抽一次"按钮(当前每次生成都是新抽卡)
- ❌ 抽卡动画(目前直接展示)
- ❌ 收藏册(用户历史)
- ❌ 后端 rarity 统计