# 镭射卡风格池 — 轻量抽卡设计 > 配套代码: > - [`frontend/utils/laser-card/stylePool.js`](../frontend/utils/laser-card/stylePool.js) — 45 个风格定义 > - [`frontend/utils/laser-card/gacha.js`](../frontend/utils/laser-card/gacha.js) — 加权抽卡算法 > - [`frontend/utils/laser-card/laserPresets.js`](../frontend/utils/laser-card/laserPresets.js) — 入口 > - [`frontend/composables/useLaserDifyGenerate.js`](../frontend/composables/useLaserDifyGenerate.js) — 抽卡调度 ## 设计哲学 **不要游戏化的抽卡 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 ```js { 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`](../frontend/utils/laser-card/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` 为主体: ```yaml # 修复前(硬编码压制了每张图的差异) "柔和光晕叠加层,微光粒子飘散...不要边框,不要装饰线...生成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) ```js // 抽卡分布 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 统计