Files
chatroom/resources/views/chat/partials/global-dialog.blade.php
T

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" data-chat-dialog-action="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" data-chat-dialog-action="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>