mirror of
https://github.com/RhenCloud/Cloud-Index.git
synced 2025-12-06 07:06:41 +08:00
- 移除 main.js 并替换为8个 JS 模块 - 移除 main.css 并替换为7个 CSS 模块 - 更新 base.html 以加载模块化文件 - 通过 index.css 保持完全向后兼容 - 改进代码组织、可维护性和可复用性
236 lines
6.9 KiB
JavaScript
236 lines
6.9 KiB
JavaScript
/**
|
||
* 对话框(Dialog)相关功能
|
||
* 包括确认、输入、提示等对话框
|
||
*/
|
||
|
||
const dialogState = {
|
||
container: null,
|
||
title: null,
|
||
message: null,
|
||
inputWrapper: null,
|
||
input: null,
|
||
confirmBtn: null,
|
||
cancelBtn: null,
|
||
resolve: null,
|
||
options: null,
|
||
previousActiveElement: null,
|
||
};
|
||
|
||
/**
|
||
* 检查对话框是否打开
|
||
* @returns {boolean}
|
||
*/
|
||
function isDialogOpen() {
|
||
return Boolean(dialogState.container && !dialogState.container.hasAttribute("hidden"));
|
||
}
|
||
|
||
/**
|
||
* 关闭对话框
|
||
* @param {boolean} confirmed - 是否确认
|
||
*/
|
||
function closeDialog(confirmed) {
|
||
if (!dialogState.resolve || !dialogState.container) {
|
||
return;
|
||
}
|
||
|
||
const showInput = dialogState.options?.showInput;
|
||
const value = confirmed && showInput && dialogState.input ? dialogState.input.value : undefined;
|
||
|
||
dialogState.container.classList.remove("is-visible");
|
||
dialogState.container.setAttribute("aria-hidden", "true");
|
||
|
||
window.setTimeout(() => {
|
||
if (!dialogState.container.classList.contains("is-visible")) {
|
||
dialogState.container.setAttribute("hidden", "");
|
||
}
|
||
}, 200);
|
||
|
||
if (dialogState.inputWrapper) {
|
||
dialogState.inputWrapper.hidden = true;
|
||
}
|
||
|
||
const resolve = dialogState.resolve;
|
||
dialogState.resolve = null;
|
||
const options = dialogState.options || {};
|
||
dialogState.options = null;
|
||
|
||
if (dialogState.previousActiveElement && typeof dialogState.previousActiveElement.focus === "function") {
|
||
dialogState.previousActiveElement.focus({ preventScroll: true });
|
||
}
|
||
dialogState.previousActiveElement = null;
|
||
|
||
resolve({
|
||
confirmed,
|
||
value: value !== undefined ? value : undefined,
|
||
options,
|
||
});
|
||
}
|
||
|
||
/**
|
||
* 打开对话框
|
||
* @param {object} options - 对话框选项
|
||
* @returns {Promise}
|
||
*/
|
||
function openDialog(options) {
|
||
if (!dialogState.container) {
|
||
return Promise.resolve({ confirmed: false });
|
||
}
|
||
|
||
return new Promise((resolve) => {
|
||
dialogState.resolve = resolve;
|
||
dialogState.options = options;
|
||
dialogState.previousActiveElement =
|
||
document.activeElement instanceof HTMLElement ? document.activeElement : null;
|
||
|
||
dialogState.container.removeAttribute("hidden");
|
||
dialogState.container.setAttribute("aria-hidden", "false");
|
||
|
||
if (dialogState.title) {
|
||
dialogState.title.textContent = options.title || "";
|
||
dialogState.title.hidden = !options.title;
|
||
}
|
||
|
||
if (dialogState.message) {
|
||
dialogState.message.textContent = options.message || "";
|
||
}
|
||
|
||
if (dialogState.inputWrapper && dialogState.input) {
|
||
dialogState.inputWrapper.hidden = !options.showInput;
|
||
dialogState.input.value = options.defaultValue || "";
|
||
dialogState.input.placeholder = options.placeholder || "";
|
||
}
|
||
|
||
if (dialogState.confirmBtn) {
|
||
dialogState.confirmBtn.textContent = options.confirmLabel || "确定";
|
||
}
|
||
|
||
if (dialogState.cancelBtn) {
|
||
dialogState.cancelBtn.textContent = options.cancelLabel || "取消";
|
||
dialogState.cancelBtn.hidden = options.hideCancel || false;
|
||
}
|
||
|
||
window.requestAnimationFrame(() => {
|
||
if (!dialogState.container) {
|
||
return;
|
||
}
|
||
dialogState.container.classList.add("is-visible");
|
||
|
||
if (options.showInput && dialogState.input) {
|
||
dialogState.input.focus();
|
||
dialogState.input.select();
|
||
} else if (dialogState.confirmBtn) {
|
||
dialogState.confirmBtn.focus();
|
||
}
|
||
});
|
||
});
|
||
}
|
||
|
||
/**
|
||
* 初始化对话框
|
||
*/
|
||
function initDialog() {
|
||
const container = document.getElementById("appDialog");
|
||
if (!container || container.dataset.initialized === "true") {
|
||
return;
|
||
}
|
||
|
||
container.dataset.initialized = "true";
|
||
dialogState.container = container;
|
||
dialogState.title = document.getElementById("appDialogTitle");
|
||
dialogState.message = document.getElementById("appDialogMessage");
|
||
dialogState.inputWrapper = document.getElementById("appDialogInputWrapper");
|
||
dialogState.input = document.getElementById("appDialogInput");
|
||
dialogState.confirmBtn = document.getElementById("appDialogConfirm");
|
||
dialogState.cancelBtn = document.getElementById("appDialogCancel");
|
||
|
||
if (dialogState.confirmBtn) {
|
||
dialogState.confirmBtn.addEventListener("click", () => closeDialog(true));
|
||
}
|
||
|
||
if (dialogState.cancelBtn) {
|
||
dialogState.cancelBtn.addEventListener("click", () => closeDialog(false));
|
||
}
|
||
|
||
container.addEventListener("click", (event) => {
|
||
if (
|
||
event.target === container ||
|
||
(event.target instanceof HTMLElement && event.target.dataset.dialogDismiss === "true")
|
||
) {
|
||
closeDialog(false);
|
||
}
|
||
});
|
||
|
||
document.addEventListener("keydown", (event) => {
|
||
if (!isDialogOpen()) {
|
||
return;
|
||
}
|
||
|
||
if (event.key === "Escape") {
|
||
event.preventDefault();
|
||
closeDialog(false);
|
||
return;
|
||
}
|
||
|
||
if (event.key === "Enter" && dialogState.options?.showInput) {
|
||
const active = document.activeElement;
|
||
if (active === dialogState.input) {
|
||
event.preventDefault();
|
||
closeDialog(true);
|
||
}
|
||
}
|
||
});
|
||
}
|
||
|
||
/**
|
||
* 显示确认对话框
|
||
* @param {string} message - 消息
|
||
* @param {object} options - 选项
|
||
* @returns {Promise<boolean>}
|
||
*/
|
||
function showConfirm(message, options = {}) {
|
||
return openDialog({
|
||
title: options.title || "确认操作",
|
||
message,
|
||
confirmLabel: options.confirmLabel || "确定",
|
||
cancelLabel: options.cancelLabel || "取消",
|
||
hideCancel: options.hideCancel || false,
|
||
}).then((result) => Boolean(result.confirmed));
|
||
}
|
||
|
||
/**
|
||
* 显示输入对话框
|
||
* @param {string} message - 消息
|
||
* @param {object} options - 选项
|
||
* @returns {Promise<string|null>}
|
||
*/
|
||
async function showPrompt(message, options = {}) {
|
||
const result = await openDialog({
|
||
title: options.title || "请输入内容",
|
||
message,
|
||
confirmLabel: options.confirmLabel || "确定",
|
||
cancelLabel: options.cancelLabel || "取消",
|
||
showInput: true,
|
||
defaultValue: options.defaultValue || "",
|
||
placeholder: options.placeholder || "",
|
||
});
|
||
|
||
if (!result.confirmed) {
|
||
return null;
|
||
}
|
||
|
||
const value = typeof result.value === "string" ? result.value.trim() : "";
|
||
return value === "" ? null : value;
|
||
}
|
||
|
||
/**
|
||
* 导出到全局作用域
|
||
*/
|
||
window.DialogUtils = {
|
||
isDialogOpen,
|
||
closeDialog,
|
||
openDialog,
|
||
initDialog,
|
||
showConfirm,
|
||
showPrompt,
|
||
};
|