Commit Graph

118 Commits

Author SHA1 Message Date
dac7750fe1 功能:特效音效三项优化 + 禁音开关
音效改进(effect-sounds.js):
1. 雷电 - 三层合成更贴近真实:
   ①放电啪声(带通噪声 ~50ms)
   ②低频轰鸣(120→38Hz 扫频,快冲击 2s 衰减)
   ③极低频滚动余韵(55→22Hz,缓慢堆积 3.6s 长衰减)
2. 下雨 - 音量 0.40→0.15,时长与视觉效果统一(8000ms)
3. 下雪 - 移除风声,只保留五声音阶铃音(C/E/G/C)
   铃音加第二泛音(×2.76倍频)模拟真实铃铛共鸣感
   8次随机铃声分布在 10 秒内

禁音开关:
- input-bar.blade.php:悄悄话旁新增「🔇 禁音」复选框
- scripts.blade.php:toggleSoundMute() 函数,
  localStorage chat_sound_muted 持久化,
  DOMContentLoaded 恢复复选框状态
- effect-sounds.js:play() 先检查 chat_sound_muted 标志
2026-03-01 13:19:24 +08:00
1d7aa636a0 功能:4种全屏特效增加 Web Audio API 实时合成音效
新建 public/js/effects/effect-sounds.js:
- 雷电:低频白噪声爆裂 + 雷鸣渐衰(10次,与视觉同步)
- 烟花:发射滑音(200→700Hz)+ 带通噪声爆炸(9轮)
- 下雨:双层带通白噪声(1200Hz+3500Hz)持续淡入淡出
- 下雪:4000Hz+高频风声 + 五声音阶轻柔铃音(5次随机)
- 所有音效纯 Web Audio API 合成,无外部音频文件
- 旧 AudioContext 若被 suspended 自动 resume

effect-manager.js:
- play() 调用 EffectSounds.play(type) 同步触发音效
- _cleanup() 调用 EffectSounds.stop() 兜底停止

frame.blade.php:effect-sounds.js 在 effect-manager 前引入
2026-03-01 13:07:36 +08:00
3d7b86f06d 功能:奖励发放聊天室公告 + 右下角 Toast 通知卡片
后端(AdminCommandController::reward):
- 新增聊天室公开公告消息(系统公告,所有在场用户可见)
- 接收者私信附带 toast_notification 字段触发前端小卡片
- 公告文案:「🪙 [职务人] 向 [目标] 发放了 [N] 枚奖励金币!」

前端:
- 新建 chat/partials/toast-notification.blade.php:
  全局右下角 Toast 组件,window.chatToast.show() API
  支持 title/message/icon/color/duration/action 配置
  多条 Toast 从右下角向上堆叠,独立计时、独立关闭
- chat:message 事件监听中检测 toast_notification 字段,
  自动弹出右下角通知卡片(仅接收方可见)
- showFriendToast 迁移至 window.chatToast.show(),
  删除 80 行旧实现,代码量净减
- frame.blade.php 引入新 partial

DEVELOPMENT.md:
- 新增 §7.9 chatToast 完整文档(API、使用场景、迁移说明)
- 原 chatBanner 章节编号改为 §7.10
2026-03-01 12:15:18 +08:00
2ae3d83349 优化:确认发放按钮圆角 6px→20px,视觉更圆润 2026-03-01 12:08:05 +08:00
9da0d83914 优化:确认发放按钮风格改为与全局弹窗一致
- 输入框+按钮回到同一行(align-items:stretch)
- 按钮完全复刻 global-dialog 确认按钮样式:
  padding:9px, border-radius:6px, font-size:13px, font-weight:bold
- 背景色 #f59e0b(与弹窗标题栏橙色对应)
- :style 仅控制 opacity,background 两分支都明确写入
2026-03-01 12:07:12 +08:00
5180526821 优化:确认发放按钮改为全宽独立一行,风格同弹窗按钮
输入框独占一行,按钮在输入框下方全宽显示:
- 宽度 100%,高度 48px,字号 16px,字间距 2px
- 琥珀橙色 #f59e0b,与弹窗头部色调呼应
- 禁用时 opacity:0.45,启用时 box-shadow 投影
- 符合截图中弹窗确定按钮的视觉风格
2026-03-01 12:04:05 +08:00
0d693eef5f 优化:输入框与确认按钮等高(align-items:stretch)
flex 容器改为 align-items:stretch,按钮去掉固定 height
改为 align-self:stretch,自动撑满与输入框相同高度,
视觉上两者完全对齐。
2026-03-01 12:01:53 +08:00
4207528043 修复:确认发放按钮背景色始终通过 :style 注入
将 background 从 static style 移入 :style 绑定,
两种状态(启用/禁用)均显式包含 background,
彻底避免 Alpine :style 动态绑定覆盖静态 style background 的问题。

按钮颜色:橙红渐变 #ea580c→#dc2626
- 启用:opacity:1 + box-shadow 投影
- 禁用:opacity:0.4 + no-shadow(未输入金额时)
2026-03-01 12:00:03 +08:00
96c472bfb9 修复:弹窗额度4列布局+确认按钮背景色
1. 4列布局:x-show 与 display:grid 分离到两层 div,
   避免 Alpine x-show 显示时把 display:grid 覆盖为 block

2. 确认按钮::style 改为始终返回 opacity 值而非空字符串,
   避免 Alpine :style 绑定空值时清除静态 style 的 background,
   按钮现为橙红渐变(#ea580c→#dc2626)+红色投影,
   禁用状态 opacity:0.45 降亮+cursor:not-allowed
2026-03-01 11:58:08 +08:00
4ba5a88fc2 优化:奖励弹窗加宽+4列额度+最近10条记录+确认按钮醒目
- 弹窗宽度 320→520px(max-width:95vw 自适应)
- 额度四格改为一行4列(单次上限/单日上限/今日已发/剩余额度)
- 确认按钮改为橙红渐变+投影,视觉更突出
- 输入框下方显示最近10条发放记录(目标/金额/时间)
- 发放成功后实时在历史列表头部插入新纪录
- rewardQuota 接口统一返回 recent_rewards(最近10条)
2026-03-01 11:55:29 +08:00
21cabb08c9 功能:奖励金币改为独立弹窗(展示额度信息)
- 点击「送金币」按钮打开独立弹窗,不再内联在用户名片中
- 弹窗展示 4 格额度信息:单次上限、单日上限、今日已发、剩余额度
- 新增 GET /command/reward-quota 接口(rewardQuota 方法)
  返回当前操作人实时额度,超管返回全部不限
- 发放成功后页面内实时更新今日已发/剩余额度,无需刷新
- 移除原内联奖励面板,action 改为调用全局 openRewardModal()
2026-03-01 11:50:12 +08:00
3d30d7e811 功能:id=1 超管无需职务即可发放奖励金币
前端(frame.blade.php):
- Auth::id()===1 时 myMaxReward=-1(不限),送金币按钮始终显示

后端(AdminCommandController::reward):
- isSuperAdmin=true 时跳过职务检查和①②③④限额校验
- 全局接收次数⑤对超管同样生效(防止刷奖励)
- 履职记录 user_position_id 允许 null(超管无职务时)
- 发放备注改用 positionName 变量(超管显示「超级管理员」)

顺带修复:②操作人单日累计统计之前误查 target_user_id,
已改为正确的 user_id(操作人自己今日已发总额)
2026-03-01 11:43:51 +08:00
cc1278ffcb 修复:openUserCard 剥除消息中的装饰括号避免 404
问题:部分自动动作/系统消息用「【username】」格式显示用户名,
      双击时把「【」前缀一并传给 openUserCard,导致:
      GET /user/【lkddi → 404

修复:在 openUserCard 入口统一用正则清洗 【】[]
      等装饰字符,再传给 fetchUser 查询。
2026-03-01 11:42:13 +08:00
8dcf23d7e4 修复:单次上限三态逻辑(null=不限/-1=不限/0=禁止/正整数=有上限)
frame.blade.php:
- max_reward=null → myMaxReward=-1(不限,有权限)
- max_reward=0   → myMaxReward=0(禁止发放)
- max_reward=N   → myMaxReward=N(有具体上限)

user-actions.blade.php:
- 按钮显示条件:myMaxReward !== 0(-1 和正整数都显示)
- 面板上限文字:-1 显示「不限」,正整数显示具体数值
- sendReward 校验:0=禁止阻断,-1=不限跳过上限校验,N=有上限
- 输入框 :max:-1 时上限 999999(实际不限),N 时上限 N
2026-03-01 11:39:28 +08:00
ff57afe388 功能:职务奖励金币发放系统
数据库:
- positions 新增 daily_reward_limit(单日累计上限)
- positions 新增 recipient_daily_limit(同一接收者每日次数上限)

后端:
- CurrencySource::POSITION_REWARD 新枚举值
- AdminCommandController::reward() 三层限额校验
  ① 单次上限 ② 单日累计上限 ③ 同一接收者每日次数
  写履职记录(PositionAuthorityLog)+ UserCurrencyService
  聊天室悄悄话通知接收者
- POST /command/reward 路由注册

前端(user-actions.blade.php):
- 名片按钮行 2+1 布局(加好友/送礼物/送金币)
- 送金币仅在 myMaxReward>0 时显示(职务持有者)
- 内联奖励金币面板:金额输入 + 确认发放 + 说明文字
- sendReward() 前端校验 + API 调用 + chatDialog 反馈

后台(positions/index):
- 编辑表单新增两个奖励限额字段
- PositionController 验证规则同步更新
2026-03-01 11:09:29 +08:00
5a7d1565e5 修复:channels.php 移除 int 类型提示,改用强转比较防兼容性问题
int $id 类型提示在某些 PHP 版本下对字符串参数可能失败,
统一改为 (int) 强转比较,与 App.Models.User.{id} 写法一致。
2026-03-01 01:54:19 +08:00
7bae5e56ff 修复:私有频道改用数字 ID,解决中文用户名导致 Pusher 频道名非法
错误原因:Pusher 频道名只允许 [a-zA-Z0-9_\-=@,.],
中文用户名(如「超级舞魅」)用于 private-user.{username} 导致
PusherException: Invalid channel name。

修复方案(改用数字 ID):
- FriendAdded/FriendRemoved 构造加 toUserId 参数
- broadcastOn() 改为 PrivateChannel('user.' . $toUserId)
- FriendController 传入 $target->id / $targetUser->id
- channels.php 鉴权改为 'user.{id}',核对 $user->id 数字相等
- frame.blade.php chatContext 加 userId
- scripts.blade.php Echo.private 改用 userId 订阅
2026-03-01 01:41:04 +08:00
a44a9ce242 修复:回加好友成功后大卡片自动关闭
quickFriendAction 是 async 函数,await 完成后
检查按钮文字是否为 '',1.5 秒后调用 close() 关闭 banner。
2026-03-01 01:33:41 +08:00
f951ec428d 重构:聊天室所有 alert() 改为 window.chatDialog.alert()
scripts.blade.php 全部 21 处原生 alert() 替换:
- 成功类 → chatDialog.alert(..., '提示', '#16a34a')
- 失败/错误类 → chatDialog.alert(..., '操作失败', '#cc4444')
- 网络异常类 → chatDialog.alert(..., '网络异常', '#cc4444')
- 连接断开/踢出 → chatDialog.alert(..., '连接警告', '#b45309')
- 一般提示 → chatDialog.alert(..., '提示', '#336699')

DEVELOPMENT.md 新增 §7.9 window.chatBanner 使用文档
2026-03-01 01:32:20 +08:00
5c53b8cf2f 功能:window.chatBanner 全局大卡片公共组件
前端:
- window.chatBanner.show(options) 全局 API,完全自定义:
  icon/title/name/body/sub/gradient/titleColor/autoClose/buttons
- window.chatBanner.close(id) 关闭指定 banner
- showFriendBanner / showAppointmentBanner 均改用 chatBanner 实现
- setupBannerNotification() 监听私有+房间频道的 BannerNotification 事件

后端:
- BannerNotification 事件(ShouldBroadcastNow),支持 user/room 双目标
- BannerBroadcastController(仅超级管理员路由,三层中间件保护)
- 内容字段 strip_tags 净化防 XSS,按钮 action 白名单校验

安全:
- window.chatBanner.show() 被人控制台调用只影响自己,无法推给他人
- HTTP 入口 POST /admin/banner/broadcast 仅超管可访问
2026-03-01 01:28:23 +08:00
779179af01 功能:好友添加通知改为居中大卡弹窗(同任命公告风格)
FriendAdded:
- 互相好友 → 绿色渐变大卡 + '你们现在互为好友 🎊',5秒自动消失
- 单向添加 → 蓝绿渐变大卡 + [ 回加好友] + [稍后再说] 按钮,手动关闭

FriendRemoved:保留右下角 Toast 通知

效果复用 appoint-pop 弹出动画关键帧
2026-03-01 01:09:37 +08:00
212f7a0096 功能:好友悄悄话内嵌快捷操作链接
后端:
- notifyOnlineUser 生成带内联 <a> 标签的内容
- added 未互相 → 嵌入 ' 回加好友' 链接
- removed 互相  → 嵌入 '🗑️ 同步移除' 链接
- 链接调用全局 quickFriendAction(act, username, el)

前端:
- 新增 window.quickFriendAction() 全局函数
- 防重复点击(dataset.done 标记)
- 成功后更新链接文字 ' 已回加' / ' 已移除',不刷新页面
2026-03-01 01:03:10 +08:00
3c2038e8fe 优化:好友通知弹窗根据互相状态显示不同内容
FriendAdded 事件:
- 新增 hasAddedBack 字段(B 是否已回加 A)
- Toast:已互相好友 → '你们现在互为好友 🎉'
- Toast:未回加 → '但你还没有添加对方为好友' + [ 回加] 一键操作按钮

FriendRemoved 事件:
- 新增 hadAddedBack 字段(之前是否互相好友)
- Toast:之前互相好友 → 提示 + [🗑️ 同步移除] 一键操作按钮
- Toast:单向好友 → 简单通知,无操作按钮

Toast 改进:
- 右上角 × 关闭按钮
- 快捷操作按钮支持 fetch 直接请求
- 完成后显示结果并自动关闭,延时改为 8 秒
2026-03-01 00:54:10 +08:00
700ab9def4 feat: 好友系统全实现
后端:
- FriendController:add/remove/status/index 四个接口
- FriendAdded / FriendRemoved 广播事件(私有频道)
- channels.php 注册 user.{username} 私有频道鉴权
- routes/web.php 注册好友路由
- ChatController::init() 修复 DutyLog 在 return 后执行的 bug
- ChatController::notifyFriendsOnline() 上线时悄悄话通知好友

前端:
- user-actions:写私信 → 加好友/删好友按钮(动态状态)
- toggleFriend() 方法 + fetchUser 后加载好友状态
- scripts:监听私有频道 FriendAdded/FriendRemoved
- showFriendToast() 右下角浮窗通知(5秒自动消失)
- global-dialog 加 fdSlideIn 动画
2026-03-01 00:48:51 +08:00
7ec0904c5c 重构:全局自定义弹窗系统 window.chatDialog
- 新增 chat/partials/global-dialog.blade.php(全局弹窗 HTML + JS)
- 提供 chatDialog.alert() 和 chatDialog.confirm() 两个异步 API
- Alpine.js userCardComponent 的 $alert/$confirm 代理到全局 API
- toolbar 离开按钮统一改用 chatDialog.confirm(),移除独立 leave-confirm-modal
- 支持动态标题颜色、淡入动画,兼容 Chrome/Edge/Firefox
2026-03-01 00:34:11 +08:00
e2ae4b34b3 修复:Chrome 离开按钮 confirm 弹窗闪烁 → 自定义 HTML 弹窗
- 移除原生 confirm(),改为自定义 #leave-confirm-modal 弹窗
- 红色渐变标题栏,取消/确定离开两个按钮
- 点击遮罩可关闭,不触发任何浏览器原生对话框机制
2026-03-01 00:29:00 +08:00
f0cbcfa949 修复:Alpine.js userInfo.position_history 初始 undefined 导致 length 报错
- userInfo 初始值加 position_history: [],防止挂载时 undefined.length
- x-text 和 x-if 里加可选链 ?.length ?? 0 双重兜底
2026-03-01 00:23:08 +08:00
91b569ffd3 修复:离开按钮 confirm 弹窗在 Chrome 闪烁消失
将 beforeunload 改为 pagehide 事件:
- pagehide 在页面关闭/刷新时触发,但不会弹原生「离开网站」确认框
- 与原生 confirm() 不产生冲突,Chrome/Edge 行为一致
- leaveRoom() 设 _manualLeave 标记,pagehide 里不重复发 beacon
2026-03-01 00:18:46 +08:00
0f5b8a4f52 修复:Chrome 点击离开时出现原生"离开网站"弹窗闪烁
主动调用 remove 移除 beforeunload 监听后再导航,
Chrome 不再触发原生确认框,Edge 行为不变
2026-03-01 00:16:34 +08:00
1caaec5601 修复:关闭浏览器时 leave 不触发导致勤务日志不结算
- 新增 sendLeaveBeacon(),使用 navigator.sendBeacon 发送 leave 请求
- beforeunload 事件:关闭标签/浏览器/刷新均自动结算
- visibilitychange 事件:切到后台 30 秒后自动结算,切回来取消
- sendBeacon 比 fetch 更可靠,浏览器关闭时也能确保请求发出
2026-03-01 00:12:47 +08:00
5f30220609 feat: 任命/撤销通知系统 + 用户名片UI优化
- 任命/撤销事件增加 type 字段区分类型
- 任命:全屏礼花 + 紫色弹窗 + 紫色系统消息
- 撤销:灰色弹窗 + 灰色系统消息,无礼花
- 消息分发:操作者/被操作者显示在私聊面板,其他人显示在公屏
- 系统消息加随机鼓励语(各5条轮换)
- ChatStateService 修复 Redis key 前缀扫描问题(getAllActiveRoomIds)
- 用户名片折叠优化:管理员视野、职务履历均可折叠
- 管理操作 + 职务操作合并为「🔧 管理操作」折叠区
- 悄悄话改为「🎁 送礼物」按钮,礼物面板内联展开
2026-02-28 23:44:38 +08:00
3f5d0e9539 功能:自动存点通知实现滚动替换,新消息到来时自动删除旧的通知,保持包厢窗口整洁 2026-02-28 11:56:42 +08:00
0ff64d2737 修复:增强 scripts.blade.php 的 JS 健壮性,解决因 DOM 元素缺失导致的执行中断及变量未初始化问题 2026-02-28 11:22:18 +08:00
28d402d204 修复:重写本地清屏逻辑,使用 localStorage 记录拉取游标,避免进房带历史功能导致清屏失效 2026-02-28 11:20:34 +08:00
9a98bdfbe6 修复:聊天室初次加载时附带历史消息,解决因网络延迟错失入场欢迎语的问题 2026-02-28 11:17:09 +08:00
cb2e962116 优化:与AI聊天不再阻塞全局发言锁,允许在AI思考期间继续在公屏聊天 2026-02-28 11:12:51 +08:00
e7436e7898 修复:与AI聊天或其他特定错误拦截后,发送消息按钮永久失灵的问题 2026-02-27 17:45:18 +08:00
4ef95eaa27 新增:新人首次入住聊天室大礼包自动发放功能(6666金币 + 满场烟花 + 公屏欢迎) 2026-02-27 17:21:33 +08:00
efc4dfd752 修复:聊天室界面的送鱼按钮 Alpine.js 语法错误导致发言被卡住的问题 2026-02-27 17:04:12 +08:00
4fe3c1eed9 修复:商店购买单次特效卡并指定给别人时,购买者自己也必须能看到特效播放 2026-02-27 16:56:57 +08:00
f37530fa0e UI:聊天消息移除硬编码 font-size,统一继承用户设置的字体大小 2026-02-27 16:33:40 +08:00
157aee3812 修复:confirmGift null错误(先保存item再关弹框);MessageSent改为ShouldBroadcastNow立即广播;修复route()引号冲突 2026-02-27 16:26:16 +08:00
6a8ba4fbc8 功能:单次特效卡支持赠送——送礼弹框、广播给指定用户/全员、公屏系统消息、购买后关闭商店展示特效 2026-02-27 16:19:21 +08:00
1e2c304754 UI: 商店弹窗改为蓝白风格,与现有设置弹窗保持一致 2026-02-27 16:09:10 +08:00
8ac540c65b 重构:商店从右侧 Tab 移至工具栏按钮弹窗,新增 2 列网格卡片布局 2026-02-27 16:06:15 +08:00
9c8f7b1a95 UI: 商店面板重新设计——紧凑卡片、渐变配色、悬浮特效、绝对定位适配窄侧边栏 2026-02-27 16:02:22 +08:00
7fb86bfe21 Feat: 商店功能完整实现(单次特效卡888/周卡8888/改名卡5000,含购买、周卡覆盖、改名黑名单) 2026-02-27 15:57:12 +08:00
094181b826 Fix: 防止Enter重复发送(IME输入法防穿透+_isSending防重入锁) 2026-02-27 14:53:45 +08:00
a3d0d6cec5 Feat: 输入栏增加字号选择器,自动应用到聊天窗口并持久化到localStorage 2026-02-27 14:46:49 +08:00
4668c163aa Feat: 管理员进入聊天室自动触发烟花+公屏欢迎公告 2026-02-27 14:34:04 +08:00