This commit is contained in:
leokun
2026-06-30 10:38:52 +08:00
commit c083be5ec2
312 changed files with 146628 additions and 0 deletions
+36
View File
@@ -0,0 +1,36 @@
import { reactive } from "vue";
export const inputModalState = reactive({
visible: false,
title: "提示",
content: "",
placeholder: "",
value: "",
_resolve: null,
});
/**
* 显示输入弹窗,返回 Promise<string|null>
* @param {Object} options - { title, content, placeholder, defaultValue }
* @returns {Promise<string|null>} - string=确定后的输入值, null=取消
*/
export function showInputModal(options = {}) {
return new Promise((resolve) => {
inputModalState.visible = true;
inputModalState.title = options.title ?? "提示";
inputModalState.content = options.content ?? "";
inputModalState.placeholder = options.placeholder ?? "";
inputModalState.value = String(options.defaultValue ?? "");
inputModalState._resolve = resolve;
});
}
export function resolveInputModal(ok) {
const value = String(inputModalState.value ?? "").trim();
inputModalState.visible = false;
inputModalState._resolve?.(ok ? value : null);
inputModalState._resolve = null;
if (!ok) {
inputModalState.value = "";
}
}
+109
View File
@@ -0,0 +1,109 @@
import { inject, provide, reactive } from "vue";
const MESSAGE_API_SYMBOL = Symbol("message-api");
const MIN_VISIBLE_MS = 300;
let messageSeed = 0;
const messageState = reactive({
current: null,
});
function clearMessageTimer(item) {
if (item?.timer) {
clearTimeout(item.timer);
item.timer = null;
}
}
function removeMessage(id, options = {}) {
if (!messageState.current || messageState.current.id !== id) {
return;
}
const current = messageState.current;
const elapsed = Date.now() - current.shownAt;
const force = options.force === true;
if (!force && elapsed < MIN_VISIBLE_MS) {
clearMessageTimer(current);
current.timer = window.setTimeout(() => {
removeMessage(id, { force: true });
}, MIN_VISIBLE_MS - elapsed);
return;
}
clearMessageTimer(current);
messageState.current = null;
}
function showMessage(options = {}) {
const type = typeof options.type === "string" ? options.type : "info";
const content = String(options.content || "").trim();
if (!content) {
return null;
}
if (messageState.current) {
clearMessageTimer(messageState.current);
}
const duration = Number.isFinite(options.duration)
? Math.max(0, options.duration)
: type === "loading"
? 0
: 2400;
const id = `message-${Date.now()}-${messageSeed += 1}`;
const item = {
id,
type,
content,
shownAt: Date.now(),
timer: null,
};
if (duration > 0) {
item.timer = window.setTimeout(() => {
removeMessage(id);
}, Math.max(duration, MIN_VISIBLE_MS));
}
messageState.current = item;
return id;
}
export function createMessageApi() {
return {
state: messageState,
show: showMessage,
success(content, options = {}) {
return showMessage({ ...options, type: "success", content });
},
error(content, options = {}) {
return showMessage({ ...options, type: "error", content });
},
info(content, options = {}) {
return showMessage({ ...options, type: "info", content });
},
loading(content, options = {}) {
return showMessage({ ...options, type: "loading", content });
},
remove: removeMessage,
clear() {
if (messageState.current) {
removeMessage(messageState.current.id, { force: true });
}
},
};
}
const defaultMessageApi = createMessageApi();
export function provideMessage() {
provide(MESSAGE_API_SYMBOL, defaultMessageApi);
return defaultMessageApi;
}
export function useMessage() {
return inject(MESSAGE_API_SYMBOL, defaultMessageApi);
}
export { messageState, showMessage, removeMessage };
+37
View File
@@ -0,0 +1,37 @@
import { reactive } from "vue";
export const modalState = reactive({
visible: false,
title: "提示",
content: "",
confirmText: "确定",
cancelText: "取消",
showCancel: true,
confirmDisabled: false,
_resolve: null,
});
/**
* 显示确认弹窗,返回 Promise<boolean>
* @param {Object} options - { title, content }
* @returns {Promise<boolean>} - true=确定, false=取消
*/
export function showModal(options = {}) {
return new Promise((resolve) => {
modalState.visible = true;
modalState.title = options.title ?? "提示";
modalState.content = options.content ?? "";
modalState.confirmText = options.confirmText ?? "确定";
modalState.cancelText = options.cancelText ?? "取消";
modalState.showCancel = options.showCancel ?? true;
modalState.confirmDisabled = options.confirmDisabled ?? false;
modalState._resolve = resolve;
});
}
export function resolveModal(ok) {
modalState.visible = false;
const resolve = modalState._resolve;
modalState._resolve = null;
resolve?.(ok);
}