重构:全局自定义弹窗系统 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
This commit is contained in:
2026-03-01 00:34:11 +08:00
parent e2ae4b34b3
commit 7ec0904c5c
4 changed files with 209 additions and 47 deletions
@@ -0,0 +1,178 @@
{{--
文件功能:全局自定义弹窗组件(替代原生 alert / confirm
提供全局 JS API
- window.chatDialog.alert(message, title?, color?) Promise<void>
- window.chatDialog.confirm(message, title?, color?) Promise<boolean>
任何 JS 代码(Alpine.js 组件、toolbar、scripts 等)均可直接调用,
无需使用浏览器原生弹窗,避免 Chrome/Edge 兼容性问题。
@author ChatRoom Laravel
@version 1.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 14px; font-size:13px; color:#374151;
line-height:1.6; word-break:break-word;">
</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);
}
}
#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;
const $ = id => document.getElementById(id);
/** 打开弹窗内部方法 */
function _open({
message,
title,
color,
type
}) {
$('global-dialog-header').textContent = title;
$('global-dialog-header').style.background = color;
$('global-dialog-message').textContent = message;
$('global-dialog-confirm-btn').style.background = color;
// 撤销/alert 模式隐藏取消按钮
const cancelBtn = $('global-dialog-cancel-btn');
cancelBtn.style.display = type === 'confirm' ? '' : 'none';
// 调整确认按钮宽度
$('global-dialog-confirm-btn').style.flex = type === 'confirm' ? '1' : '1 1 100%';
$('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'
});
});
},
/** 点确定按钮 */
_confirm() {
_resolve?.(true);
this._hide();
},
/** 点取消按钮 */
_cancel() {
_resolve?.(false);
this._hide();
},
/** 关闭弹窗 */
_hide() {
$('global-dialog-modal').style.display = 'none';
_resolve = null;
},
};
})();
// 点击遮罩层关闭(等同点取消)
document.getElementById('global-dialog-modal').addEventListener('click', function(e) {
if (e.target === this) {
window.chatDialog._cancel();
}
});
</script>