Files
chatroom/resources/views/chat/partials/global-dialog.blade.php
lkddi bfb1a3bca4 重构(chat): 聊天室 Partials 第二阶段分类拆分及修复红包弹窗隐藏 Bug
- 完成对 scripts.blade.php 中非核心业务逻辑(钓鱼游戏、AI机器人、系统全局公告)的深度抽象隔离
- 修复抢红包逻辑中 setInterval 缺失时间参数(1000)引发浏览器前端主线程挂起的重度阻塞问题
- 修复 lottery-panel 组件结尾漏写 </div> 导致的连锁级渲染树崩溃(该崩溃导致红包节点被意外当作隐藏后代节点渲染,造成彻底不可见)
- 对相关模板规范代码结构,执行 Laravel Pint 格式化并提交
2026-03-09 11:30:11 +08:00

235 lines
8.7 KiB
PHP
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.
{{--
文件功能:全局自定义弹窗组件(替代原生 alert / confirm / prompt
提供全局 JS API
- window.chatDialog.alert(message, title?, color?) Promise<void>
- window.chatDialog.confirm(message, title?, color?) Promise<boolean>
- window.chatDialog.prompt(message, defaultVal?, title?, color?) Promise<string|null>
任何 JS 代码Alpine.js 组件、toolbar、scripts 等)均可直接调用,
无需使用浏览器原生弹窗,避免 Chrome/Edge 兼容性问题。
@author ChatRoom Laravel
@version 2.0.0
--}}
{{-- ─── 全局弹窗遮罩 ─── --}}
<div id="global-dialog-modal"
style="display:none; position:fixed; inset:0; background:rgba(0,0,0,.5);
z-index:999999; justify-content:center; align-items:center;">
<div id="global-dialog-box"
style="background:#fff; border-radius:10px; width:320px; max-width:90vw;
box-shadow:0 12px 40px rgba(0,0,0,.35); overflow:hidden;
animation:gdSlideIn .18s ease;">
{{-- 标题栏(颜色由 JS 动态设置) --}}
<div id="global-dialog-header" style="padding:13px 18px; font-size:14px; font-weight:bold; color:#fff;">
</div>
{{-- 内容区 --}}
<div id="global-dialog-message"
style="padding:18px 18px 8px; font-size:13px; color:#374151; white-space:pre-wrap;
line-height:1.6; word-break:break-word;">
</div>
{{-- 输入框prompt 模式专用) --}}
<div id="global-dialog-input-wrap" style="display:none; padding:0 18px 12px;">
<textarea id="global-dialog-input"
style="width:100%; box-sizing:border-box; border:1px solid #d1d5db; border-radius:6px;
padding:8px 10px; font-size:13px; color:#374151; resize:vertical;
min-height:72px; line-height:1.5; outline:none; font-family:inherit;
transition:border-color .15s;"
placeholder="请输入内容…"></textarea>
</div>
{{-- 按钮区 --}}
<div style="display:flex; gap:10px; padding:0 18px 16px;">
<button id="global-dialog-cancel-btn" onclick="window.chatDialog._cancel()"
style="flex:1; padding:9px; background:#f3f4f6; color:#555;
border:1px solid #d1d5db; border-radius:6px;
font-size:13px; cursor:pointer; transition:background .15s;">
取消
</button>
<button id="global-dialog-confirm-btn" onclick="window.chatDialog._confirm()"
style="flex:1; padding:9px; color:#fff; border:none;
border-radius:6px; font-size:13px; font-weight:bold;
cursor:pointer; transition:opacity .15s;">
确定
</button>
</div>
</div>
</div>
<style>
@keyframes gdSlideIn {
from {
opacity: 0;
transform: scale(.92) translateY(-8px);
}
to {
opacity: 1;
transform: scale(1) translateY(0);
}
}
@keyframes fdSlideIn {
from {
opacity: 0;
transform: translateY(16px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
#global-dialog-cancel-btn:hover {
background: #e5e7eb !important;
}
#global-dialog-confirm-btn:hover {
opacity: .88;
}
</style>
<script>
/**
* 全局弹窗工具,提供 alert / confirm 两种模式。
* 替代浏览器原生弹窗,兼容 Chrome/Edge/Safari。
*
* 用法:
* await window.chatDialog.alert('操作成功!', '提示', '#16a34a');
* const yes = await window.chatDialog.confirm('确定要删除吗?', '请确认');
* if (yes) { ... }
*/
window.chatDialog = (function() {
let _resolve = null;
let _currentType = 'alert';
const $ = id => document.getElementById(id);
/** 打开弹窗内部方法 */
function _open({ message, title, color, type, defaultVal }) {
_currentType = type;
$('global-dialog-header').textContent = title;
$('global-dialog-header').style.background = color;
$('global-dialog-message').textContent = message;
$('global-dialog-confirm-btn').style.background = color;
// prompt 模式显示输入框,并填入默认值
const inputWrap = $('global-dialog-input-wrap');
const inputEl = $('global-dialog-input');
if (type === 'prompt') {
inputEl.value = defaultVal ?? '';
inputWrap.style.display = '';
// 弹出后自动聚焦
setTimeout(() => { inputEl.focus(); inputEl.select(); }, 80);
} else {
inputWrap.style.display = 'none';
inputEl.value = '';
}
// alert 模式隐藏取消按钮
const cancelBtn = $('global-dialog-cancel-btn');
cancelBtn.style.display = (type === 'confirm' || type === 'prompt') ? '' : 'none';
// alert 模式确认按钮撑满
$('global-dialog-confirm-btn').style.flex = type === 'alert' ? '1 1 100%' : '1';
$('global-dialog-modal').style.display = 'flex';
}
return {
/**
* 显示提示弹窗(替代 alert
*
* @param {string} message 提示内容
* @param {string} title 标题(默认:提示)
* @param {string} color 标题栏颜色(默认蓝色)
* @return {Promise<void>}
*/
alert(message, title = '提示', color = '#336699') {
return new Promise(resolve => {
_resolve = resolve;
_open({ message, title, color, type: 'alert' });
});
},
/**
* 显示确认弹窗(替代 confirm
*
* @param {string} message 确认内容
* @param {string} title 标题(默认:请确认)
* @param {string} color 标题栏颜色(默认红色)
* @return {Promise<boolean>} 用户点确定返回 true取消返回 false
*/
confirm(message, title = '请确认', color = '#cc4444') {
return new Promise(resolve => {
_resolve = resolve;
_open({ message, title, color, type: 'confirm' });
});
},
/**
* 显示文本输入弹窗(替代 prompt
*
* @param {string} message 提示文字
* @param {string} defaultVal 输入框默认值
* @param {string} title 标题(默认:请输入)
* @param {string} color 标题栏颜色(默认蓝色)
* @return {Promise<string|null>} 确定返回输入内容,取消返回 null
*/
prompt(message, defaultVal = '', title = '请输入', color = '#336699') {
return new Promise(resolve => {
_resolve = resolve;
_open({ message, title, color, type: 'prompt', defaultVal });
});
},
/** 点确定按钮 */
_confirm() {
if (_currentType === 'prompt') {
// prompt 模式:返回输入框内容
_resolve?.($('global-dialog-input').value);
} else if (_currentType === 'confirm') {
_resolve?.(true);
} else {
_resolve?.();
}
this._hide();
},
/** 点取消按钮 */
_cancel() {
if (_currentType === 'prompt') {
_resolve?.(null);
} else {
_resolve?.(false);
}
this._hide();
},
/** 关闭弹窗 */
_hide() {
$('global-dialog-modal').style.display = 'none';
_resolve = null;
_currentType = 'alert';
},
};
})();
// prompt 模式支持按 Enter 确认、Esc 取消
document.getElementById('global-dialog-input').addEventListener('keydown', function(e) {
if (e.key === 'Enter' && !e.shiftKey) {
e.preventDefault();
window.chatDialog._confirm();
} else if (e.key === 'Escape') {
e.preventDefault();
window.chatDialog._cancel();
}
});
</script>