topfans/frontend/utils/laser-card/laserPresets.js
Lenticular Studio Agent af7908e72e feat: 接入微达API中转站,重构镭射卡生图流程
- 替换中转站从 xbcl.link 到 weda.cc
- prompt 模板改为镭射卡全图生成(去掉 6 层合成/抠图依赖)
- 4 路并发调用 + 原图展示 = 5 张 variant
- 前端提示词中译英支持
- 全局 Vue errorHandler
- WebSocket 鉴权失败跳登录
- 删除已弃用的 laserCompositor 微服务

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

196 lines
6.5 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* 镭射卡五图预设 — 真实金属银系
* 参考实体卡Pokémon holo / BTS photocard / 国产星穹镭射票
* 5 张卡都是金属底,仅银色微调 + 色带方向/速度不同
*
* Prompt 字段:
* bgPrompt — 背景主题描述(不含前缀/后缀,由 Gateway 拼接)
* overlayPrompt — 装饰层描述(同上)
* colorHint — 主色调提示(用于用户 prompt 的配色引导)
*/
export const LASER_BATCH_EXPORT_SIZE = { w: 450, h: 600 }
/** 兼容字段:旧的 rich 模式已弃用 */
export const PRESET_VARIANTS = [
{
id: 'dream',
style: 'dream',
beam: 'prism',
backdropMode: 'grating',
backdropTone: '#A8ACB2', // 冷银
sheenBandAngle: 135,
sheenSpeed: 0.35,
sheenIntensity: 0.40,
foilCoverage: 0.75,
laserStrength: 50,
frostIntensity: 8,
flowSpeed: 0.35,
colorHint: '淡紫色 粉色 银色',
bgPrompt: 'soft dreamy holographic background, lavender and pink layered gradient, gentle bubble bokeh and soft star sparkles, single diagonal sheen sweep at 135°, dreamy celestial mood, no text, no people, no watermark',
overlayPrompt: 'thin pearl border, soft star scatter, subtle corner brackets',
},
{
id: 'classic',
style: 'classic',
beam: 'aurora',
backdropMode: 'grating',
backdropTone: '#A89E91', // 香槟银
sheenBandAngle: 120,
sheenSpeed: 0.45,
sheenIntensity: 0.38,
foilCoverage: 0.70,
laserStrength: 48,
frostIntensity: 6,
flowSpeed: 0.45,
colorHint: '香槟金 暖金色 浅米色',
bgPrompt: '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, no text, no people, no watermark',
overlayPrompt: 'warm sepia border, vintage corner motif',
},
{
id: 'holoFull',
style: 'holoFull',
beam: 'neon',
backdropMode: 'grating',
backdropTone: '#B0ACA6', // 珍珠银
sheenBandAngle: 150,
sheenSpeed: 0.30,
sheenIntensity: 0.50,
foilCoverage: 0.95,
laserStrength: 62,
frostIntensity: 10,
flowSpeed: 0.30,
colorHint: '银色 霓虹色 金属银',
bgPrompt: '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%, futuristic cyber-card mood, no text, no people, no watermark',
overlayPrompt: 'neon bevel border, sharp diagonal sheen sweep, geometric corner accents',
},
{
id: 'ice',
style: 'ice',
beam: 'white',
backdropMode: 'grating',
backdropTone: '#9C9993', // 暖银
sheenBandAngle: 110,
sheenSpeed: 0.50,
sheenIntensity: 0.36,
foilCoverage: 0.60,
laserStrength: 44,
frostIntensity: 5,
flowSpeed: 0.50,
colorHint: '浅蓝灰 冰蓝 银色',
bgPrompt: 'cool ice holographic background, pale blue-gray base with crystalline frost texture, snowflake scatter and ice-crack corner motif, fast diagonal sheen sweep at 110° (speed 0.50), crisp clean winter mood, no text, no people, no watermark',
overlayPrompt: 'thin frosted edge line, sparse ice flake scatter, light frost corner motif',
},
{
id: 'sunset',
style: 'sunset',
beam: 'sunset',
backdropMode: 'grating',
backdropTone: '#9E958A', // 玫瑰金底
sheenBandAngle: 140,
sheenSpeed: 0.40,
sheenIntensity: 0.42,
foilCoverage: 0.80,
laserStrength: 52,
frostIntensity: 7,
flowSpeed: 0.40,
colorHint: '玫瑰金 暖橙色 粉色',
bgPrompt: 'warm sunset holographic background, rose-gold base with amber and pink layered glow, soft floral corner accents, gentle diagonal sheen sweep at 140° (speed 0.40), romantic dreamy mood, no text, no people, no watermark',
overlayPrompt: 'thin rose gold border, small heart corner accents',
},
]
export const LASER_PRESET_IDS = PRESET_VARIANTS.map((p) => p.id)
export function getLaserPresetByIndex(index) {
const i = Number(index)
if (!Number.isFinite(i) || i < 0 || i >= PRESET_VARIANTS.length) {
return PRESET_VARIANTS[0]
}
return PRESET_VARIANTS[i]
}
export function getLaserPresetIndexById(presetId) {
const id = String(presetId || '').trim()
const idx = PRESET_VARIANTS.findIndex((p) => p.id === id)
return idx >= 0 ? idx : 0
}
/**
* 构建 Dify 工作流所需的 render_configs每个 variant 的完整渲染参数)
* 用于 POST /api/v1/laser/generate 请求体
* @param {string[]} [presetIds] 需要生成的 preset ID 列表默认全部5个
* @returns {Array<{preset_id: string, grating_config: object, bg_prompt: string, overlay_prompt: string}>}
*/
export function buildRenderConfigs(presetIds) {
const ids = presetIds || LASER_PRESET_IDS
return PRESET_VARIANTS
.filter((p) => ids.includes(p.id))
.map((p) => ({
preset_id: p.id,
grating_config: {
sheen_band_angle: p.sheenBandAngle,
sheen_intensity: p.sheenIntensity,
sheen_speed: p.sheenSpeed,
foil_coverage: p.foilCoverage,
backdrop_tone: p.backdropTone,
},
bg_prompt: p.bgPrompt || '',
overlay_prompt: p.overlayPrompt || '',
}))
}
export { resolveGratingConfig, DEFAULT_BACKDROP_TONE } from './laserGrating.js'
// =========================================================================
// 新增:风格池 + 抽卡(45 个风格,5 档分层)
// - 旧调用方(激光导出会、success.vue)继续用上方 export,完全兼容
// - 新调用方(抽卡、稀有度徽章)使用下方 export
// =========================================================================
// 风格池与索引(转自 stylePool.js)
export {
LASER_STYLE_POOL,
LASER_STYLE_IDS,
LASER_STYLE_INDEX,
RARITY_DISTRIBUTION,
RARITY_COLORS,
RARITY_STARS,
} from './stylePool.js'
// 抽卡算法(转自 gacha.js)
export {
drawGachaStyles,
drawGachaStyleIds,
pickRarity,
pickStyleInRarity,
findStyleById,
RARITY_WEIGHTS,
} from './gacha.js'
/**
* 兼容旧调用方:按数字索引取 style 对象
* 0-4 仍映射到原 dream/classic/holoFull/ice/sunset(与旧 PRESET_VARIANTS 顺序一致)
* 5~44 映射到新池子
* @param {number} index
*/
export function getStyleByIndex(index) {
const i = Number(index)
if (!Number.isFinite(i) || i < 0) return LASER_STYLE_POOL[0]
if (i < 5) {
const oldIds = ['dream', 'classic', 'holoFull', 'ice', 'sunset']
return LASER_STYLE_POOL.find((s) => s.id === oldIds[i]) || LASER_STYLE_POOL[0]
}
return LASER_STYLE_POOL[i] || LASER_STYLE_POOL[0]
}
/**
* 兼容旧调用方:按 style id 反查数字索引(用于 success.vue)
* @param {string} id
* @returns {number}
*/
export function getStyleIndexById(id) {
const idx = LASER_STYLE_INDEX[String(id || '')]
return Number.isFinite(idx) ? idx : 0
}