f17f171f4b
迁移收尾修复:
- heartbeat.js: 移除 export { } 中重复的 startHeartbeat/stopHeartbeat(已通过 export function 导出)
- scripts.blade.php: 移除 JS 注释中的 {{ }} 避免 Blade 编译为 e() 导致 PHP 解析错误
- preferences-status.js: 补全 6 个缺失的 window.* 赋值(toggleBlockMenu/toggleFeatureMenu 等),
实现迁移中丢失的 updateDailyStatus/clearDailyStatus,修复 handleFeatureLocalClear 清屏回调
- toolbar.js: 补全 window.runFeatureShortcut 赋值
头像框样式修复(chat-decorations.css):
- z-index 互换:头像降至 1,框升至 3,使框边缘可遮挡头像外围
- 使用 CSS mask(radial-gradient)挖环形替代旧 ::before 实心圆遮挡方案
- clip-path: circle(50%) 硬裁剪确保圆形,不受 chat.css border-radius: 2px 覆盖
- 特异性提升至 .user-item .avatar-frame-wrapper .user-head
新 Vite 模块(从 Blade 迁移):
- chat-state.js / message-renderer.js / user-list.js / chat-events.js
- composer.js(重写)/ heartbeat.js / admin-commands.js
- vip-presence.js / chat-decorations.css
105 lines
3.5 KiB
JavaScript
105 lines
3.5 KiB
JavaScript
// 会员进退场豪华横幅模块,从 Blade 内联脚本迁移至 Vite 管理。
|
|
|
|
import { escapeHtml } from "./html.js";
|
|
|
|
/**
|
|
* 转义会员横幅文本,避免横幅层被注入 HTML。
|
|
*/
|
|
function escapePresenceText(text) {
|
|
return escapeHtml(String(text ?? "")).replace(/\n/g, "<br>");
|
|
}
|
|
|
|
/**
|
|
* 根据不同的会员横幅风格返回渐变与光影配置。
|
|
*/
|
|
function getVipPresenceStyleConfig(style, color) {
|
|
const fallback = color || "#f59e0b";
|
|
|
|
const map = {
|
|
aurora: {
|
|
gradient: `linear-gradient(135deg, #f59e0b, #fbbf24, #fef3c7)`,
|
|
glow: `rgba(251, 191, 36, 0.4)`,
|
|
accent: "#78350f",
|
|
},
|
|
storm: {
|
|
gradient: `linear-gradient(135deg, #0ea5e9, #7dd3fc, #f0f9ff)`,
|
|
glow: `rgba(125, 211, 252, 0.4)`,
|
|
accent: "#0369a1",
|
|
},
|
|
royal: {
|
|
gradient: `linear-gradient(135deg, #d97706, #fcd34d, #fffbeb)`,
|
|
glow: `rgba(252, 211, 77, 0.4)`,
|
|
accent: "#92400e",
|
|
},
|
|
cosmic: {
|
|
gradient: `linear-gradient(135deg, #db2777, #f472b6, #fdf2f8)`,
|
|
glow: `rgba(244, 114, 182, 0.4)`,
|
|
accent: "#9d174d",
|
|
},
|
|
farewell: {
|
|
gradient: `linear-gradient(135deg, #ea580c, #fb923c, #fff7ed)`,
|
|
glow: `rgba(251, 146, 60, 0.4)`,
|
|
accent: "#9a3412",
|
|
},
|
|
};
|
|
|
|
return map[style] || map.aurora;
|
|
}
|
|
|
|
/**
|
|
* 显示会员进退场豪华横幅。
|
|
*
|
|
* @param {Record<string, any>} payload 携带 presence_text / presence_type / presence_icon 等字段的消息载荷
|
|
* @returns {void}
|
|
*/
|
|
function showVipPresenceBanner(payload) {
|
|
if (!payload || !payload.presence_text) {
|
|
return;
|
|
}
|
|
|
|
const existing = document.getElementById("vip-presence-banner");
|
|
if (existing) {
|
|
existing.remove();
|
|
}
|
|
|
|
const styleConfig = getVipPresenceStyleConfig(
|
|
payload.presence_banner_style,
|
|
payload.presence_color,
|
|
);
|
|
const bannerTypeLabel =
|
|
payload.presence_type === "leave"
|
|
? "离场提示"
|
|
: payload.presence_type === "purchase"
|
|
? "开通喜报"
|
|
: "闪耀登场";
|
|
|
|
const banner = document.createElement("div");
|
|
banner.id = "vip-presence-banner";
|
|
banner.className = "vip-presence-banner";
|
|
banner.innerHTML = `
|
|
<div class="vip-presence-banner__glow" style="background:${styleConfig.glow};"></div>
|
|
<div class="vip-presence-banner__card" style="background:${styleConfig.gradient}; border-color:${payload.presence_color || "#fff"};">
|
|
<div class="vip-presence-banner__meta">
|
|
<span class="vip-presence-banner__icon">${escapeHtml(payload.presence_icon || "👑")}</span>
|
|
<span class="vip-presence-banner__level">${escapeHtml(payload.presence_level_name || "尊贵会员")}</span>
|
|
<span class="vip-presence-banner__type">${bannerTypeLabel}</span>
|
|
</div>
|
|
<div class="vip-presence-banner__text" style="color:${styleConfig.accent};">
|
|
${escapePresenceText(payload.presence_text)}
|
|
</div>
|
|
</div>
|
|
`;
|
|
|
|
document.body.appendChild(banner);
|
|
|
|
setTimeout(() => {
|
|
banner.classList.add("is-leaving");
|
|
setTimeout(() => banner.remove(), 700);
|
|
}, 4200);
|
|
}
|
|
|
|
// 挂载到 window 供 Blade 脚本及其他模块使用。
|
|
window.showVipPresenceBanner = showVipPresenceBanner;
|
|
|
|
export { showVipPresenceBanner, getVipPresenceStyleConfig, escapePresenceText };
|