topfans/docs/laser-card-style-pool.md
Lenticular Studio Agent 67cf3d4177 chore: 清理 laserCompositor 微服务残留
- 删除已弃用的 compositor_client.go
- 删除激光合成微服务代码
- 添加 gateway 合成控制器和测试文件
- 添加 Dify prompt 补丁脚本

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-23 22:44:03 +08:00

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):

  1. 单张稀有度:按 RARITY_WEIGHTS = { N: 50, R: 30, SR: 15, SSR: 4, UR: 1 } 加权
  2. 同档内:按 style.weight 二次加权
  3. 不重复:5 张 ID 集合 size === 5
  4. 保底:第 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 段式):

  1. 整体氛围(mood)
  2. 工艺特征(holographic/refractor/stripe/foil coverage)
  3. 色彩描述(具体颜色 + 渐变)
  4. 光线描述(single diagonal sheen sweep at 135° 与 grating_config 对齐)
  5. 负向提示(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

端到端验证

  1. 启动 dev server
  2. 进入镭射卡生成页
  3. 不输入 prompt → 点击生成
  4. 观察:5 张卡出现,每张视觉不同(不同 grating 角度/不同配色)
  5. 再次点击生成 → 又一组 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 统计