diff --git a/app/Services/DecorationService.php b/app/Services/DecorationService.php
index 7e7a3da..b736866 100644
--- a/app/Services/DecorationService.php
+++ b/app/Services/DecorationService.php
@@ -9,6 +9,7 @@
* - bubble : 消息气泡边框样式
* - name_color : 昵称颜色效果
* - avatar_frame: 头像装饰边框
+ * - text_color : 消息文字颜色特效
*
* @author ChatRoom Laravel
*
@@ -37,6 +38,7 @@ class DecorationService
'msg_bubble' => 'bubble',
'msg_name_color' => 'name_color',
'avatar_frame' => 'avatar_frame',
+ 'msg_text_color' => 'text_color',
];
/**
@@ -173,11 +175,11 @@ class DecorationService
/**
* 获取消息广播 payload 需要携带的装扮字段。
*
- * 消息广播只需要气泡样式(msg_bubble)和昵称颜色(msg_name_color),
+ * 消息广播只需要气泡样式(msg_bubble)、昵称颜色(msg_name_color)和文字颜色特效(msg_text_color),
* 头像框不需要在消息中展示。
*
* @param User $user 消息发送者
- * @return array{msg_bubble?:string, msg_name_color?:string}
+ * @return array{msg_bubble?:string, msg_name_color?:string, msg_text_color?:string}
*/
public function getDecorationsForMessage(User $user): array
{
@@ -190,6 +192,9 @@ class DecorationService
if (! empty($decorations['name_color']['style'])) {
$result['msg_name_color'] = $decorations['name_color']['style'];
}
+ if (! empty($decorations['text_color']['style'])) {
+ $result['msg_text_color'] = $decorations['text_color']['style'];
+ }
return $result;
}
diff --git a/database/migrations/2026_04_27_000002_add_msg_text_color_type_to_shop_items.php b/database/migrations/2026_04_27_000002_add_msg_text_color_type_to_shop_items.php
new file mode 100644
index 0000000..1ae8f0f
--- /dev/null
+++ b/database/migrations/2026_04_27_000002_add_msg_text_color_type_to_shop_items.php
@@ -0,0 +1,38 @@
+ '鎏金流光气泡', 'slug' => 'msg_bubble_golden', 'icon' => '🟡',
'description' => '浅金底纹、左侧金线和流光扫过,发言更醒目但不刺眼。',
- 'price' => 300, 'type' => 'msg_bubble', 'duration_days' => 1, 'sort_order' => 50],
+ 'price' => 3000, 'type' => 'msg_bubble', 'duration_days' => 1, 'sort_order' => 50],
['name' => '樱语花笺气泡', 'slug' => 'msg_bubble_sakura', 'icon' => '🌸',
'description' => '粉白信笺底色配花点纹理,适合温柔、浪漫的发言氛围。',
- 'price' => 500, 'type' => 'msg_bubble', 'duration_days' => 3, 'sort_order' => 51],
+ 'price' => 3000, 'type' => 'msg_bubble', 'duration_days' => 1, 'sort_order' => 51],
['name' => '星河微光气泡', 'slug' => 'msg_bubble_star', 'icon' => '🌌',
'description' => '淡蓝星河底纹和微光星点,保留清爽阅读感。',
- 'price' => 800, 'type' => 'msg_bubble', 'duration_days' => 7, 'sort_order' => 52],
+ 'price' => 5000, 'type' => 'msg_bubble', 'duration_days' => 1, 'sort_order' => 52],
['name' => '霓虹彩带气泡', 'slug' => 'msg_bubble_rainbow', 'icon' => '🌈',
'description' => '顶部流动彩带和浅色底框,发言有动态高光。',
- 'price' => 1500, 'type' => 'msg_bubble', 'duration_days' => 7, 'sort_order' => 53],
+ 'price' => 8000, 'type' => 'msg_bubble', 'duration_days' => 1, 'sort_order' => 53],
['name' => '皇冠礼赞气泡', 'slug' => 'msg_bubble_crown', 'icon' => '👑',
'description' => '金色礼赞底纹、皇冠角标和侧边金线,突出尊贵发言。',
- 'price' => 3000, 'type' => 'msg_bubble', 'duration_days' => 30, 'sort_order' => 54],
+ 'price' => 8000, 'type' => 'msg_bubble', 'duration_days' => 1, 'sort_order' => 54],
// ── 昵称颜色装扮 ──────────────────────────
['name' => '金色昵称', 'slug' => 'msg_name_golden', 'icon' => '🥇',
@@ -113,27 +113,44 @@ class ShopItemSeeder extends Seeder
'price' => 200, 'type' => 'msg_name_color', 'duration_days' => 1, 'sort_order' => 60],
['name' => '渐变昵称', 'slug' => 'msg_name_rainbow', 'icon' => '🎨',
'description' => '彩虹渐变色昵称,五彩斑斓。',
- 'price' => 500, 'type' => 'msg_name_color', 'duration_days' => 3, 'sort_order' => 61],
+ 'price' => 500, 'type' => 'msg_name_color', 'duration_days' => 1, 'sort_order' => 61],
['name' => '发光昵称', 'slug' => 'msg_name_glow', 'icon' => '✨',
'description' => '昵称带柔和发光效果,暗夜中最亮的星。',
- 'price' => 800, 'type' => 'msg_name_color', 'duration_days' => 7, 'sort_order' => 62],
+ 'price' => 800, 'type' => 'msg_name_color', 'duration_days' => 1, 'sort_order' => 62],
['name' => '火焰昵称', 'slug' => 'msg_name_flame', 'icon' => '🔥',
'description' => '火焰色脉动昵称,热情似火。',
- 'price' => 1500, 'type' => 'msg_name_color', 'duration_days' => 7, 'sort_order' => 63],
+ 'price' => 1500, 'type' => 'msg_name_color', 'duration_days' => 1, 'sort_order' => 63],
+
+ // ── 消息文字颜色特效装扮 ─────────────────
+ ['name' => '七彩文字', 'slug' => 'msg_text_rainbow', 'icon' => '🌈',
+ 'description' => '文字色彩在彩虹七色间平滑流动,发言自带虹光特效。',
+ 'price' => 5000, 'type' => 'msg_text_color', 'duration_days' => 1, 'sort_order' => 65],
+ ['name' => '流光文字', 'slug' => 'msg_text_shimmer', 'icon' => '💫',
+ 'description' => '一道流光从左到右扫过文字表面,如金属般闪亮。',
+ 'price' => 5000, 'type' => 'msg_text_color', 'duration_days' => 1, 'sort_order' => 66],
+ ['name' => '霓虹文字', 'slug' => 'msg_text_neon', 'icon' => '💜',
+ 'description' => '紫蓝霓虹光晕在文字周围脉动呼吸,像灯牌一样醒目。',
+ 'price' => 8000, 'type' => 'msg_text_color', 'duration_days' => 1, 'sort_order' => 67],
+ ['name' => '火焰文字', 'slug' => 'msg_text_flame', 'icon' => '🔥',
+ 'description' => '橙红烈火在文字中上下跃动,热情燃烧般的视觉冲击。',
+ 'price' => 8000, 'type' => 'msg_text_color', 'duration_days' => 1, 'sort_order' => 68],
+ ['name' => '冰蓝文字', 'slug' => 'msg_text_ice', 'icon' => '❄️',
+ 'description' => '冰蓝晶光在文字表面流转,如同冰晶折射出的冷艳光泽。',
+ 'price' => 8000, 'type' => 'msg_text_color', 'duration_days' => 1, 'sort_order' => 69],
// ── 头像框装扮 ────────────────────────────
['name' => '月银守护头像框', 'slug' => 'avatar_frame_silver', 'icon' => '🥈',
'description' => '银白金属光泽外框,低调但比普通头像更精致。',
- 'price' => 500, 'type' => 'avatar_frame', 'duration_days' => 7, 'sort_order' => 70],
+ 'price' => 5000, 'type' => 'avatar_frame', 'duration_days' => 1, 'sort_order' => 70],
['name' => '金辉勋章头像框', 'slug' => 'avatar_frame_gold', 'icon' => '🥇',
'description' => '金色勋章质感外框,带柔和光晕。',
- 'price' => 1000, 'type' => 'avatar_frame', 'duration_days' => 7, 'sort_order' => 71],
+ 'price' => 5000, 'type' => 'avatar_frame', 'duration_days' => 1, 'sort_order' => 71],
['name' => '星轨环绕头像框', 'slug' => 'avatar_frame_star', 'icon' => '⭐',
'description' => '星轨渐变环绕头像旋转,适合高调展示。',
- 'price' => 2000, 'type' => 'avatar_frame', 'duration_days' => 14, 'sort_order' => 72],
+ 'price' => 8000, 'type' => 'avatar_frame', 'duration_days' => 1, 'sort_order' => 72],
['name' => '龙焰御守头像框', 'slug' => 'avatar_frame_dragon', 'icon' => '🐉',
'description' => '红金御守质感外框,带虚线纹理和强烈光晕。',
- 'price' => 5000, 'type' => 'avatar_frame', 'duration_days' => 30, 'sort_order' => 73],
+ 'price' => 8000, 'type' => 'avatar_frame', 'duration_days' => 1, 'sort_order' => 73],
];
foreach ($items as $item) {
diff --git a/resources/js/chat-room/shop-controls.js b/resources/js/chat-room/shop-controls.js
index bf6ad75..b8e5f50 100644
--- a/resources/js/chat-room/shop-controls.js
+++ b/resources/js/chat-room/shop-controls.js
@@ -58,6 +58,11 @@ const DECORATION_GROUPS = [
desc: "同类型只保留最新购买",
type: "msg_name_color",
},
+ {
+ label: "🌈 文字颜色",
+ desc: "同类型只保留最新购买",
+ type: "msg_text_color",
+ },
{
label: "🖼️ 头像框",
desc: "同类型只保留最新购买",
@@ -68,6 +73,7 @@ const DECORATION_GROUPS = [
const DECORATION_TYPE_TO_SLOT = {
msg_bubble: "bubble",
msg_name_color: "name_color",
+ msg_text_color: "text_color",
avatar_frame: "avatar_frame",
};
diff --git a/resources/views/chat/partials/scripts.blade.php b/resources/views/chat/partials/scripts.blade.php
index 56e9bb8..75fb0a6 100644
--- a/resources/views/chat/partials/scripts.blade.php
+++ b/resources/views/chat/partials/scripts.blade.php
@@ -170,6 +170,82 @@
50% { text-shadow: 0 0 10px #fbbf24, 0 0 16px #ef4444; }
}
+ /* ========== 消息文字颜色特效 ========== */
+ .msg-text--rainbow {
+ background: linear-gradient(90deg,
+ #ef4444, #f97316, #eab308, #22c55e, #06b6d4, #3b82f6, #a855f7, #ef4444);
+ background-size: 300% 100%;
+ -webkit-background-clip: text;
+ -webkit-text-fill-color: transparent;
+ background-clip: text;
+ font-weight: 600;
+ animation: text-rainbow 3.5s linear infinite;
+ }
+ @keyframes text-rainbow {
+ 0% { background-position: 0% 50%; }
+ 100% { background-position: 300% 50%; }
+ }
+
+ .msg-text--shimmer {
+ background: linear-gradient(110deg,
+ #6b7280 0%, #9ca3af 18%, #f3f4f6 28%, #d1d5db 36%,
+ #6b7280 52%, #9ca3af 66%, #f9fafb 74%, #6b7280 100%);
+ background-size: 300% 100%;
+ -webkit-background-clip: text;
+ -webkit-text-fill-color: transparent;
+ background-clip: text;
+ font-weight: 600;
+ animation: text-shimmer 4s ease-in-out infinite;
+ }
+ @keyframes text-shimmer {
+ 0% { background-position: 100% 50%; }
+ 100% { background-position: -200% 50%; }
+ }
+
+ .msg-text--neon {
+ color: #a855f7 !important;
+ font-weight: 600;
+ text-shadow:
+ 0 0 7px #a855f7,
+ 0 0 14px #7c3aed,
+ 0 0 28px #6366f1,
+ 0 0 42px #4f46e5;
+ animation: text-neon 2s ease-in-out infinite alternate;
+ }
+ @keyframes text-neon {
+ 0% { text-shadow: 0 0 7px #a855f7, 0 0 14px #7c3aed, 0 0 28px #6366f1; }
+ 100% { text-shadow: 0 0 14px #c084fc, 0 0 28px #a855f7, 0 0 48px #7c3aed, 0 0 64px #6366f1; }
+ }
+
+ .msg-text--flame {
+ background: linear-gradient(180deg, #fef3c7 0%, #f59e0b 28%, #ea580c 60%, #dc2626 100%);
+ background-size: 100% 200%;
+ -webkit-background-clip: text;
+ -webkit-text-fill-color: transparent;
+ background-clip: text;
+ font-weight: 700;
+ animation: text-flame 1.2s ease-in-out infinite alternate;
+ }
+ @keyframes text-flame {
+ 0% { background-position: 0% 0%; }
+ 100% { background-position: 0% 100%; }
+ }
+
+ .msg-text--ice {
+ background: linear-gradient(135deg, #e0f2fe 0%, #7dd3fc 25%, #38bdf8 50%, #bae6fd 75%, #e0f2fe 100%);
+ background-size: 200% 200%;
+ -webkit-background-clip: text;
+ -webkit-text-fill-color: transparent;
+ background-clip: text;
+ font-weight: 600;
+ animation: text-ice 3s ease-in-out infinite;
+ filter: drop-shadow(0 0 4px rgba(56, 189, 248, 0.5));
+ }
+ @keyframes text-ice {
+ 0%, 100% { background-position: 0% 50%; }
+ 50% { background-position: 100% 50%; }
+ }
+
/* ========== 头像框 ========== */
.avatar-frame-wrapper {
position: relative;
@@ -1630,15 +1706,16 @@
/**
* 构建普通聊天消息的正文区域,支持缩略图与过期占位渲染。
*/
- function buildChatMessageContent(msg, fontColor) {
+ function buildChatMessageContent(msg, fontColor, textColorClass) {
const rawContent = msg.content || '';
if (msg.message_type === 'image' && !isExpiredChatImageMessage(msg)) {
const fullUrl = escapeHtml(msg.image_url || '');
const thumbUrl = escapeHtml(msg.image_thumb_url || '');
const imageName = escapeHtml(msg.image_original_name || '聊天图片');
+ const captionColorStyle = textColorClass ? '' : `color:${fontColor};`;
const captionHtml = rawContent ?
- `${rawContent}` :
+ `${rawContent}` :
'';
return `
@@ -1654,8 +1731,9 @@
}
if (msg.message_type === 'expired_image' || isExpiredChatImageMessage(msg)) {
+ const captionColorStyle = textColorClass ? '' : `color:${fontColor};`;
const captionHtml = rawContent ?
- `${rawContent}` :
+ `${rawContent}` :
'';
return `
@@ -2368,6 +2446,11 @@
nameClass = ' msg-name--' + msg.msg_name_color.replace(/^msg_name_/, '');
}
+ var textColorClass = '';
+ if (msg.msg_text_color) {
+ textColorClass = ' msg-text--' + msg.msg_text_color.replace(/^msg_text_/, '');
+ }
+
// 系统用户名列表(不可被选为聊天对象)
const systemUsers = ['钓鱼播报', '星海小博士', '系统传音', '系统公告', '送花播报', '系统', '欢迎', '系统播报', '神秘箱子'];
@@ -2464,7 +2547,7 @@
}
const headImg =
`
`;
- const messageBodyHtml = buildChatMessageContent(msg, fontColor);
+ const messageBodyHtml = buildChatMessageContent(msg, fontColor, textColorClass);
let html = '';
@@ -2559,7 +2642,7 @@
return '【' + clickableUser(uName, '#000099') + '】';
});
html =
- `${headImg}${clickableUser(msg.from_user, fontColor, nameClass)}:${parsedContent}`;
+ `${headImg}${clickableUser(msg.from_user, fontColor, nameClass)}:${parsedContent}`;
} else {
// 自动升级播报 / 赠礼通知 / 婚恋广播 等非游戏系统传音:金色左边框,轻量提示样式,不喧宾夺主
div.style.cssText =
@@ -2593,7 +2676,7 @@
});
html =
- `${headImg}${clickableUser(msg.from_user, fontColor, nameClass)}:${parsedContent}${giftHtml}`;
+ `${headImg}${clickableUser(msg.from_user, fontColor, nameClass)}:${parsedContent}${giftHtml}`;
}
} else if (msg.is_secret) {
if (msg.from_user === '系统') {
@@ -2610,7 +2693,7 @@
buildActionStr(msg.action, fromHtml, toHtml, '悄悄说') :
`${fromHtml}对${toHtml}悄悄说:`;
html =
- `${headImg}${verbStr}${messageBodyHtml}`;
+ `${headImg}${verbStr}${messageBodyHtml}`;
}
} else if (msg.to_user && msg.to_user !== '大家') {
// 对特定对象说话
@@ -2619,14 +2702,14 @@
const verbStr = msg.action ?
buildActionStr(msg.action, fromHtml, toHtml) :
`${fromHtml}对${toHtml}说:`;
- html = `${headImg}${verbStr}${messageBodyHtml}`;
+ html = `${headImg}${verbStr}${messageBodyHtml}`;
} else {
// 对大家说话
const fromHtml = clickableUser(msg.from_user, '#000099', nameClass);
const verbStr = msg.action ?
buildActionStr(msg.action, fromHtml, '大家') :
`${fromHtml}对大家说:`;
- html = `${headImg}${verbStr}${messageBodyHtml}`;
+ html = `${headImg}${verbStr}${messageBodyHtml}`;
}
if (!timeStrOverride) {