vue-bag-admin
Version:
Unified entry package for the Vue Bag Admin runtime ecosystem.
1,395 lines • 84.1 kB
JavaScript
import { h as k, nextTick as ke, defineComponent as ee, ref as O, watch as Ce, computed as S, openBlock as m, createElementBlock as w, createElementVNode as s, Fragment as Q, renderList as q, unref as h, withModifiers as Re, normalizeClass as V, createCommentVNode as E, toDisplayString as L, createVNode as H, inject as ft, watchEffect as gt, createBlock as U, resolveDynamicComponent as Pe, createStaticVNode as je, withCtx as R, renderSlot as de, resolveComponent as mt, Transition as vt, KeepAlive as yt, isRef as wt, normalizeStyle as ve, createTextVNode as Ke, useSlots as xt, onMounted as kt, onUnmounted as Ct } from "vue";
import { useI18n as Me, createI18n as Pt } from "vue-i18n";
import { defineStore as ue, storeToRefs as Fe } from "pinia";
import { useRoute as Ae, useRouter as $e, createRouter as Tt, createWebHashHistory as _t } from "vue-router";
import { BagUiProvider as Mt } from "../ui/index.js";
import { NDropdown as Te, NPopover as At, NTabs as $t, NTabPane as St, NEmpty as Bt, NMenu as Lt, NDrawer as Vt, NDrawerContent as Et, NSwitch as Ht, NButton as De, createDiscreteApi as Rt } from "naive-ui";
import { useLocalStorage as K, useBreakpoints as jt, breakpointsTailwind as Kt } from "@vueuse/core";
import { http as Ie } from "../request/index.js";
import { setPluginStateProvider as Dt, registerRuntimePlugins as It, isPluginEnabled as Ot } from "../core/index.js";
const Se = ue("menu", {
state: () => ({
menus: [],
// 使用 vueuse 的 useLocalStorage,自动处理持久化和响应式
collapsed: K("bag.menu.collapsed", !1),
expandedKeys: K("bag.menu.expandedKeys", []),
// 新增:用于移动端的抽屉菜单状态
mobileDrawerOpen: !1
}),
actions: {
setMenus(e) {
this.menus = e;
},
toggleCollapsed() {
this.collapsed = !this.collapsed;
},
setCollapsed(e) {
this.collapsed = e;
},
toggleMobileDrawer() {
this.mobileDrawerOpen = !this.mobileDrawerOpen;
},
setMobileDrawer(e) {
this.mobileDrawerOpen = e;
},
setExpandedKeys(e) {
this.expandedKeys = e;
}
}
}), ye = "bag.auth.token", Oe = (e) => {
var o, a, i, c, d;
const t = ((i = (a = (o = e == null ? void 0 : e.response) == null ? void 0 : o.data) == null ? void 0 : a.error) == null ? void 0 : i.message) ?? ((d = (c = e == null ? void 0 : e.response) == null ? void 0 : c.data) == null ? void 0 : d.message) ?? (e == null ? void 0 : e.message);
return t ? String(t) : "Request failed";
}, zt = (e) => {
var o, a;
const t = [];
return (o = e.role) != null && o.type && t.push(e.role.type), (a = e.role) != null && a.name && e.role.name !== e.role.type && t.push(e.role.name), t.length === 0 && t.push("authenticated"), {
username: e.username || "",
user: e,
roles: t,
permissions: Array.isArray(e.permissions) ? e.permissions : []
};
}, Ze = () => ({
async login(e) {
const t = await Ie.post("/api/auth/local", {
identifier: e.username,
password: e.password
});
return {
token: t.jwt,
profile: t.user ? {
username: String(t.user.username ?? ""),
user: t.user
} : void 0
};
},
async fetchProfile() {
const e = await Ie.get("/api/users/me", {
params: { populate: "role" }
});
return zt(e);
}
});
let Y = Ze();
const ra = (e) => {
Y = e;
}, na = () => {
Y = Ze();
}, ze = (e, t) => {
var o;
e.username = t.username || "", e.user = t.user ?? null, e.roles = (o = t.roles) != null && o.length ? t.roles : ["authenticated"], e.permissions = t.permissions ?? [], e.profileLoaded = !0;
}, he = ue("user", {
state: () => ({
token: localStorage.getItem(ye) || "",
username: "",
user: null,
roles: [],
permissions: [],
profileLoaded: !1
// 标记用户信息是否已经加载完成
}),
getters: {
// 判断用户是否已登录
isAuthenticated: (e) => !!e.token
},
actions: {
/**
* 登录逻辑 (对接 Strapi 5)
*/
async login(e) {
try {
const t = await Y.login(e);
this.token = t.token, localStorage.setItem(ye, this.token), t.profile ? ze(this, t.profile) : await this.fetchProfile();
} catch (t) {
throw new Error(Oe(t));
}
},
/**
* 退出登录
*/
logout() {
var e;
(e = Y.logout) == null || e.call(Y), this.token = "", this.username = "", this.user = null, this.roles = [], this.permissions = [], this.profileLoaded = !1, localStorage.removeItem(ye);
},
/**
* 获取用户信息(包括角色和权限点)
*/
async fetchProfile() {
try {
const e = await Y.fetchProfile({ token: this.token });
ze(this, e);
} catch (e) {
throw new Error(Oe(e));
}
},
/**
* 判断当前用户是否拥有某些角色
* @param roles 需要判断的角色数组
* @returns 只要满足其中一个角色即返回 true
*/
hasRole(e, t = "any") {
return e != null && e.length ? t === "all" ? e.every((o) => this.roles.includes(o)) : e.some((o) => this.roles.includes(o)) : !0;
},
/**
* 判断当前用户是否拥有某些权限
* @param perms 需要判断的权限点数组
* @returns 如果拥有 '*' 权限直接返回 true,否则只要满足其中一个权限即返回 true
*/
hasPermission(e, t = "any") {
return !(e != null && e.length) || this.permissions.includes("*") ? !0 : t === "all" ? e.every((o) => this.permissions.includes(o)) : e.some((o) => this.permissions.includes(o));
}
}
});
function N(e) {
return k(
"span",
{ style: { display: "inline-flex", width: "16px", height: "16px", alignItems: "center" } },
[e]
);
}
function Nt(e) {
if (e === "dashboard")
return () => N(
k("svg", { viewBox: "0 0 24 24", fill: "none", width: "16", height: "16" }, [
k("path", {
d: "M3 13h8V3H3v10Zm10 8h8V11h-8v10ZM3 21h8v-6H3v6Zm10-10h8V3h-8v8Z",
fill: "currentColor"
})
])
);
if (e === "settings")
return () => N(
k("svg", { viewBox: "0 0 24 24", fill: "none", width: "16", height: "16" }, [
k("path", {
d: "M19.14 12.94c.04-.31.06-.63.06-.94s-.02-.63-.06-.94l2.03-1.58a.5.5 0 0 0 .12-.64l-1.92-3.32a.5.5 0 0 0-.6-.22l-2.39.96a7.1 7.1 0 0 0-1.63-.94l-.36-2.54A.5.5 0 0 0 13.9 1h-3.8a.5.5 0 0 0-.49.42l-.36 2.54c-.58.23-1.12.54-1.63.94l-2.39-.96a.5.5 0 0 0-.6.22L2.71 7.48a.5.5 0 0 0 .12.64l2.03 1.58c-.04.31-.06.63-.06.94s.02.63.06.94L2.83 14.52a.5.5 0 0 0-.12.64l1.92 3.32c.13.23.4.32.64.22l2.39-.96c.5.4 1.05.71 1.63.94l.36 2.54c.04.24.25.42.49.42h3.8c.24 0 .45-.18.49-.42l.36-2.54c.58-.23 1.12-.54 1.63-.94l2.39.96c.24.1.51.01.64-.22l1.92-3.32a.5.5 0 0 0-.12-.64l-2.03-1.58ZM12 15.5A3.5 3.5 0 1 1 12 8a3.5 3.5 0 0 1 0 7.5Z",
fill: "currentColor"
})
])
);
if (e === "shop")
return () => N(
k(
"svg",
{
viewBox: "0 0 24 24",
fill: "none",
stroke: "currentColor",
"stroke-width": "2",
"stroke-linecap": "round",
"stroke-linejoin": "round",
width: "16",
height: "16"
},
[
k("path", { d: "M6 2L3 6v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V6l-3-4z" }),
k("line", { x1: "3", y1: "6", x2: "21", y2: "6" }),
k("path", { d: "M16 10a4 4 0 0 1-8 0" })
]
)
);
if (e === "order")
return () => N(
k(
"svg",
{
viewBox: "0 0 24 24",
fill: "none",
stroke: "currentColor",
"stroke-width": "2",
"stroke-linecap": "round",
"stroke-linejoin": "round",
width: "16",
height: "16"
},
[
k("path", { d: "M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" }),
k("polyline", { points: "14 2 14 8 20 8" }),
k("line", { x1: "16", y1: "13", x2: "8", y2: "13" }),
k("line", { x1: "16", y1: "17", x2: "8", y2: "17" }),
k("polyline", { points: "10 9 9 9 8 9" })
]
)
);
if (e === "user")
return () => N(
k(
"svg",
{
viewBox: "0 0 24 24",
fill: "none",
stroke: "currentColor",
"stroke-width": "2",
"stroke-linecap": "round",
"stroke-linejoin": "round",
width: "16",
height: "16"
},
[
k("path", { d: "M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2" }),
k("circle", { cx: "9", cy: "7", r: "4" }),
k("path", { d: "M23 21v-2a4 4 0 0 0-3-3.87" }),
k("path", { d: "M16 3.13a4 4 0 0 1 0 7.75" })
]
)
);
if (e === "star")
return () => N(
k(
"svg",
{
viewBox: "0 0 24 24",
fill: "none",
stroke: "currentColor",
"stroke-width": "2",
"stroke-linecap": "round",
"stroke-linejoin": "round",
width: "16",
height: "16"
},
[
k("polygon", {
points: "12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"
})
]
)
);
if (e === "chat")
return () => N(
k(
"svg",
{
viewBox: "0 0 24 24",
fill: "none",
stroke: "currentColor",
"stroke-width": "2",
"stroke-linecap": "round",
"stroke-linejoin": "round",
width: "16",
height: "16"
},
[k("path", { d: "M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z" })]
)
);
if (e === "money")
return () => N(
k(
"svg",
{
viewBox: "0 0 24 24",
fill: "none",
stroke: "currentColor",
"stroke-width": "2",
"stroke-linecap": "round",
"stroke-linejoin": "round",
width: "16",
height: "16"
},
[
k("line", { x1: "12", y1: "1", x2: "12", y2: "23" }),
k("path", { d: "M17 5H9.5a3.5 3.5 0 0 0 0 7h5a3.5 3.5 0 0 1 0 7H6" })
]
)
);
if (e === "store")
return () => N(
k(
"svg",
{
viewBox: "0 0 24 24",
fill: "none",
stroke: "currentColor",
"stroke-width": "2",
"stroke-linecap": "round",
"stroke-linejoin": "round",
width: "16",
height: "16"
},
[
k("path", { d: "M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z" }),
k("polyline", { points: "9 22 9 12 15 12 15 22" })
]
)
);
}
const Xe = {
homePath: "/dashboard",
loginPath: "/login",
profilePath: "/profile",
forbiddenPath: "/403",
notFoundPath: "/404",
redirectName: "Redirect"
};
let _e = { ...Xe };
const Ut = (e) => (_e = {
...Xe,
...e
}, _e), z = () => _e, Wt = "bag.admin.tabs", Ft = (e) => {
var t, o;
return ((t = e.meta) == null ? void 0 : t.layout) === "blank" || ((o = e.meta) == null ? void 0 : o.hideInTabBar) === !0;
}, ae = ue("tabbar", {
state: () => ({
// 标签页列表需要跨刷新和重开浏览器恢复,因此使用 localStorage 持久化。
tabs: K(Wt, []),
// 设置项可能由宿主或独立插件页修改,因此统一走 localStorage 做同步。
enableTabCache: K("bag.admin.enableTabCache", !0),
enableTabPersist: K("bag.admin.enableTabPersist", !0),
// 刷新页面时会临时把目标视图从 KeepAlive include 中移除,确保重新挂载。
refreshingViews: []
}),
getters: {
cachedViews: (e) => e.enableTabCache ? [
...new Set(
e.tabs.filter((t) => {
const o = t.cacheKey || t.name;
return !t.noCache && o && !e.refreshingViews.includes(o);
}).map((t) => t.cacheKey || t.name)
)
] : []
},
actions: {
syncRefreshingViews() {
const e = new Set(
this.tabs.map((t) => t.cacheKey || t.name).filter(Boolean)
);
this.refreshingViews = this.refreshingViews.filter((t) => e.has(t));
},
addTab(e) {
var o, a, i;
if (Ft(e) || !e.name) return;
if (!this.tabs.some((c) => c.fullPath === e.fullPath)) {
const c = (o = e.meta) == null ? void 0 : o.title, d = (a = e.meta) == null ? void 0 : a.noCache, u = (i = e.meta) == null ? void 0 : i.cacheKey;
this.tabs.push({
fullPath: e.fullPath,
path: e.path,
name: e.name,
cacheKey: u,
title: c || e.name,
noCache: !!d
});
}
},
removeTabsByPaths(e) {
if (e.length === 0) return;
const t = new Set(e);
this.tabs = this.tabs.filter((o) => !t.has(o.path)), this.syncRefreshingViews();
},
removeTab(e) {
const t = this.tabs.find((i) => i.fullPath === e), o = this.tabs.findIndex((i) => i.fullPath === e);
o !== -1 && this.tabs.splice(o, 1);
const a = (t == null ? void 0 : t.cacheKey) || (t == null ? void 0 : t.name);
a && (this.refreshingViews = this.refreshingViews.filter((i) => i !== a));
},
clearTabs() {
this.refreshingViews = [];
const { homePath: e } = z();
this.tabs = this.tabs.filter((t) => t.path === e);
},
closeOtherTabs(e) {
const { homePath: t } = z();
this.tabs = this.tabs.filter((o) => o.fullPath === e || o.path === t), this.syncRefreshingViews();
},
closeLeftTabs(e) {
const t = this.tabs.findIndex((o) => o.fullPath === e);
if (t !== -1) {
const { homePath: o } = z();
this.tabs = this.tabs.filter((a, i) => i >= t || a.path === o), this.syncRefreshingViews();
}
},
closeRightTabs(e) {
const t = this.tabs.findIndex((o) => o.fullPath === e);
if (t !== -1) {
const { homePath: o } = z();
this.tabs = this.tabs.filter((a, i) => i <= t || a.path === o), this.syncRefreshingViews();
}
},
async evictCache(e) {
const t = this.tabs.find((a) => a.fullPath === e), o = (t == null ? void 0 : t.cacheKey) || (t == null ? void 0 : t.name);
!o || t.noCache || (this.refreshingViews.includes(o) || this.refreshingViews.push(o), await ke());
},
restoreCache(e) {
const t = this.tabs.find((a) => a.fullPath === e), o = (t == null ? void 0 : t.cacheKey) || (t == null ? void 0 : t.name);
o && (this.refreshingViews = this.refreshingViews.filter((a) => a !== o));
}
}
}), Zt = { class: "tabbar-shell" }, Xt = ["onClick", "onContextmenu"], Yt = {
key: 0,
class: "tabbar-item-dot"
}, Gt = { class: "tabbar-item-title" }, Jt = ["onClick"], Qt = /* @__PURE__ */ ee({
__name: "TabBar",
setup(e) {
const t = ae(), o = Ae(), a = $e(), { locale: i, fallbackLocale: c, messages: d, t: u } = Me(), T = z(), _ = (b) => /^[A-Za-z0-9_-]+(?:\.[A-Za-z0-9_-]+)+$/.test(b), v = () => {
const b = [i.value], g = c.value;
if (typeof g == "string")
b.push(g);
else if (Array.isArray(g))
b.push(...g);
else if (g && typeof g == "object") {
const y = g[i.value];
typeof y == "string" ? b.push(y) : Array.isArray(y) && b.push(...y);
const C = g.default;
typeof C == "string" ? b.push(C) : Array.isArray(C) && b.push(...C);
}
return [...new Set(b.filter(Boolean))];
}, M = (b, g) => {
var C;
let y = (C = d.value) == null ? void 0 : C[b];
for (const X of g.split(".")) {
if (!y || typeof y != "object" || !(X in y))
return;
y = y[X];
}
return typeof y == "string" ? y : void 0;
}, A = (b) => {
for (const g of v()) {
const y = M(g, b);
if (y) return y;
}
return b;
}, j = (b) => {
const g = b.title || b.name || "Unknown";
return _(g) ? A(g) : g;
}, $ = O(null), D = () => {
$.value && $.value.scrollBy({ left: -200, behavior: "smooth" });
}, B = () => {
$.value && $.value.scrollBy({ left: 200, behavior: "smooth" });
}, Z = () => {
ke(() => {
if (!$.value) return;
const b = $.value.querySelector(".bg-gradient-to-r");
if (b) {
const g = $.value.clientWidth, y = b.offsetLeft, C = b.clientWidth, X = $.value.scrollLeft;
y < X ? $.value.scrollTo({ left: y - 20, behavior: "smooth" }) : y + C > X + g && $.value.scrollTo({
left: y + C - g + 20,
behavior: "smooth"
});
}
});
};
Ce(
() => o.fullPath,
() => {
Z();
}
);
const P = (b) => o.fullPath === b, f = (b) => {
o.fullPath !== b && a.push(b);
}, p = (b) => {
const g = t.tabs, y = g.findIndex((C) => C.fullPath === b);
if (y !== -1) {
if (P(b)) {
const C = g[y - 1] || g[y + 1];
C ? a.push(C.fullPath) : a.push(T.homePath);
}
t.removeTab(b);
}
}, I = (b) => {
p(b);
}, ne = async (b) => {
if (b) {
if (await t.evictCache(b.fullPath), b.fullPath === o.fullPath) {
await a.replace({
name: "Redirect",
query: {
target: b.fullPath
}
});
return;
}
t.restoreCache(b.fullPath), await a.push(b.fullPath);
}
}, W = O(!1), le = O(0), G = O(0), te = O(""), se = S(() => [
{ label: u("tabbar.reload", "重新加载"), key: "reload" },
{
label: u("tabbar.close", "关闭标签"),
key: "close",
disabled: te.value === T.homePath
},
{ label: u("tabbar.closeOther", "关闭其他"), key: "closeOther" },
{ label: u("tabbar.closeLeft", "关闭左侧"), key: "closeLeft" },
{ label: u("tabbar.closeRight", "关闭右侧"), key: "closeRight" },
{ label: u("tabbar.closeAll", "全部关闭"), key: "closeAll" }
]), oe = (b, g) => {
b.preventDefault(), W.value = !1, ke().then(() => {
W.value = !0, le.value = b.clientX, G.value = b.clientY, te.value = g.fullPath;
});
}, fe = () => {
W.value = !1;
}, ge = async (b) => {
W.value = !1;
const g = te.value, y = t.tabs.find((C) => C.fullPath === g);
switch (b) {
case "reload":
await ne(y);
break;
case "close":
p(g);
break;
case "closeOther":
t.closeOtherTabs(g), P(g) || a.push(g);
break;
case "closeLeft":
t.closeLeftTabs(g), t.tabs.findIndex((C) => C.fullPath === o.fullPath) === -1 && a.push(g);
break;
case "closeRight":
t.closeRightTabs(g), t.tabs.findIndex((C) => C.fullPath === o.fullPath) === -1 && a.push(g);
break;
case "closeAll":
t.clearTabs(), a.push(T.homePath);
break;
}
};
return (b, g) => (m(), w("div", Zt, [
s("div", {
class: "tabbar-nav-btn",
onClick: D
}, [...g[0] || (g[0] = [
s("svg", {
xmlns: "http://www.w3.org/2000/svg",
class: "h-4 w-4",
fill: "none",
viewBox: "0 0 24 24",
stroke: "currentColor"
}, [
s("path", {
"stroke-linecap": "round",
"stroke-linejoin": "round",
"stroke-width": "2",
d: "M15 19l-7-7 7-7"
})
], -1)
])]),
s("div", {
ref_key: "scrollContainer",
ref: $,
class: "tabbar-scroll scrollbar-hide"
}, [
(m(!0), w(Q, null, q(h(t).tabs, (y) => (m(), w("div", {
key: y.fullPath,
class: V(["tabbar-item", [P(y.fullPath) ? "is-active" : "is-inactive"]]),
onClick: (C) => f(y.fullPath),
onContextmenu: Re((C) => oe(C, y), ["prevent"])
}, [
P(y.fullPath) ? (m(), w("span", Yt)) : E("", !0),
s("span", Gt, L(j(y)), 1),
y.path !== h(T).homePath ? (m(), w("button", {
key: 1,
type: "button",
class: "tabbar-close-btn",
onClick: Re((C) => I(y.fullPath), ["stop"])
}, [...g[1] || (g[1] = [
s("svg", {
xmlns: "http://www.w3.org/2000/svg",
class: "tabbar-close-icon",
fill: "none",
viewBox: "0 0 24 24",
stroke: "currentColor"
}, [
s("path", {
"stroke-linecap": "round",
"stroke-linejoin": "round",
"stroke-width": "2",
d: "M6 18L18 6M6 6l12 12"
})
], -1)
])], 8, Jt)) : E("", !0)
], 42, Xt))), 128))
], 512),
s("div", {
class: "tabbar-nav-btn",
onClick: B
}, [...g[2] || (g[2] = [
s("svg", {
xmlns: "http://www.w3.org/2000/svg",
class: "h-4 w-4",
fill: "none",
viewBox: "0 0 24 24",
stroke: "currentColor"
}, [
s("path", {
"stroke-linecap": "round",
"stroke-linejoin": "round",
"stroke-width": "2",
d: "M9 5l7 7-7 7"
})
], -1)
])]),
H(h(Te), {
placement: "bottom-start",
trigger: "manual",
x: le.value,
y: G.value,
options: se.value,
show: W.value,
"on-clickoutside": fe,
onSelect: ge
}, null, 8, ["x", "y", "options", "show"])
]));
}
}), Be = (e, t) => {
const o = e.__vccOpts || e;
for (const [a, i] of t)
o[a] = i;
return o;
}, qt = /* @__PURE__ */ Be(Qt, [["__scopeId", "data-v-a3eb268d"]]), pe = (e, t = he()) => {
var a;
const o = {
roles: t.roles,
permissions: t.permissions,
user: t.user ?? void 0
};
return t.hasRole(e.roles, e.roleMode) && t.hasPermission(e.permissions, e.permissionMode) && (((a = e.policy) == null ? void 0 : a.call(e, o)) ?? !0);
}, la = (e) => {
const t = he();
return S(() => pe(e, t));
}, es = {
"#f97316": { hover: "#fb923c", pressed: "#ea580c", accent: "#f43f5e", accentHover: "#fb7185" },
"#3b82f6": { hover: "#60a5fa", pressed: "#2563eb", accent: "#06b6d4", accentHover: "#22d3ee" },
"#10b981": { hover: "#34d399", pressed: "#059669", accent: "#14b8a6", accentHover: "#2dd4bf" },
"#8b5cf6": { hover: "#a78bfa", pressed: "#7c3aed", accent: "#ec4899", accentHover: "#f472b6" },
"#f43f5e": { hover: "#fb7185", pressed: "#e11d48", accent: "#f97316", accentHover: "#fb923c" }
}, ts = {
headerHeight: "64px",
sidebarWidth: "256px",
sidebarCollapsedWidth: "72px",
contentMaxWidth: "1280px",
radiusSm: "8px",
radiusMd: "12px",
radiusLg: "16px",
radiusXl: "24px"
}, Ye = (e) => {
const t = e.trim().toLowerCase();
return /^#[0-9a-f]{6}$/.test(t) ? t : "#f97316";
}, Ge = (e) => {
const t = Ye(e).slice(1);
return {
r: Number.parseInt(t.slice(0, 2), 16),
g: Number.parseInt(t.slice(2, 4), 16),
b: Number.parseInt(t.slice(4, 6), 16)
};
}, ss = (e) => {
const { r: t, g: o, b: a } = Ge(e);
return `${t} ${o} ${a}`;
}, J = (e, t) => {
const { r: o, g: a, b: i } = Ge(e);
return `rgba(${o}, ${a}, ${i}, ${t})`;
}, we = (e, t) => ({
...e,
...t ?? {}
}), os = (e, t = "#f97316", o = {}) => {
const a = Ye(t), i = es[a] ?? {
hover: a,
pressed: a,
accent: a,
accentHover: a
}, c = {
primary: a,
primaryHover: i.hover,
primaryPressed: i.pressed,
primarySuppl: i.hover,
primarySoft: J(a, 0.12),
primarySofter: J(a, 0.06),
accent: i.accent,
accentHover: i.accentHover,
accentSoft: J(i.accent, 0.12),
success: "#10b981",
warning: "#f59e0b",
danger: "#f43f5e",
info: "#3b82f6"
}, d = {
...c,
bg: "#fff7ed",
bgSoft: "#fffdf8",
surface: "#ffffff",
surfaceMuted: "#f8fafc",
surfaceElevated: "rgba(255, 255, 255, 0.9)",
surfaceOverlay: "rgba(255, 255, 255, 0.78)",
border: "#e5e7eb",
borderMuted: "rgba(226, 232, 240, 0.74)",
text: "#1e293b",
textMuted: "#64748b",
textSubtle: "#94a3b8",
icon: "#64748b"
}, u = {
...c,
bg: "#050b14",
bgSoft: "#0b1220",
surface: "#0a1120",
surfaceMuted: "rgba(255, 255, 255, 0.04)",
surfaceElevated: "rgba(15, 23, 42, 0.92)",
surfaceOverlay: "rgba(255, 255, 255, 0.06)",
border: "#1f2937",
borderMuted: "rgba(30, 41, 59, 0.78)",
text: "#e2e8f0",
textMuted: "#94a3b8",
textSubtle: "#64748b",
icon: "#cbd5e1"
}, T = we(e === "dark" ? u : d, o.color), _ = we(ts, o.layout), v = we(
{
focus: `0 0 0 2px ${J(a, 0.22)}`,
header: e === "dark" ? "0 4px 20px rgba(0, 0, 0, 0.2)" : `0 4px 20px ${J(a, 0.06)}`,
sidebar: e === "dark" ? "4px 0 24px rgba(0, 0, 0, 0.2)" : "4px 0 24px rgba(15, 23, 42, 0.03)",
card: e === "dark" ? "none" : "0 14px 40px rgba(15, 23, 42, 0.06)",
menuActive: `0 4px 12px ${J(a, e === "dark" ? 0.16 : 0.25)}`
},
o.shadow
);
return { mode: e, color: T, layout: _, shadow: v };
}, as = (e) => ({
"--primary-color": e.color.primary,
"--primary-color-400": e.color.primaryHover,
"--primary-color-600": e.color.primaryPressed,
"--bag-color-primary": e.color.primary,
"--bag-color-primary-hover": e.color.primaryHover,
"--bag-color-primary-pressed": e.color.primaryPressed,
"--bag-color-primary-suppl": e.color.primarySuppl,
"--bag-color-primary-rgb": ss(e.color.primary),
"--bag-color-primary-soft": e.color.primarySoft,
"--bag-color-primary-softer": e.color.primarySofter,
"--bag-color-accent": e.color.accent,
"--bag-color-accent-hover": e.color.accentHover,
"--bag-color-accent-soft": e.color.accentSoft,
"--bag-color-success": e.color.success,
"--bag-color-warning": e.color.warning,
"--bag-color-danger": e.color.danger,
"--bag-color-info": e.color.info,
"--bag-color-bg": e.color.bg,
"--bag-color-bg-soft": e.color.bgSoft,
"--bag-color-surface": e.color.surface,
"--bag-color-surface-muted": e.color.surfaceMuted,
"--bag-color-surface-elevated": e.color.surfaceElevated,
"--bag-color-surface-overlay": e.color.surfaceOverlay,
"--bag-color-border": e.color.border,
"--bag-color-border-muted": e.color.borderMuted,
"--bag-color-text": e.color.text,
"--bag-color-text-muted": e.color.textMuted,
"--bag-color-text-subtle": e.color.textSubtle,
"--bag-color-icon": e.color.icon,
"--bag-layout-header-height": e.layout.headerHeight,
"--bag-layout-sidebar-width": e.layout.sidebarWidth,
"--bag-layout-sidebar-collapsed-width": e.layout.sidebarCollapsedWidth,
"--bag-layout-content-max-width": e.layout.contentMaxWidth,
"--bag-radius-sm": e.layout.radiusSm,
"--bag-radius-md": e.layout.radiusMd,
"--bag-radius-lg": e.layout.radiusLg,
"--bag-radius-xl": e.layout.radiusXl,
"--bag-shadow-focus": e.shadow.focus,
"--bag-shadow-header": e.shadow.header,
"--bag-shadow-sidebar": e.shadow.sidebar,
"--bag-shadow-card": e.shadow.card,
"--bag-shadow-menu-active": e.shadow.menuActive
}), rs = (e, t = document.documentElement) => {
const o = as(e);
Object.entries(o).forEach(([a, i]) => {
t.style.setProperty(a, i);
});
}, ns = [
{ name: "默认橘", value: "#f97316", colorClass: "bg-orange-500" },
{ name: "科技蓝", value: "#3b82f6", colorClass: "bg-blue-500" },
{ name: "护眼绿", value: "#10b981", colorClass: "bg-emerald-500" },
{ name: "浪漫紫", value: "#8b5cf6", colorClass: "bg-violet-500" },
{ name: "玫瑰红", value: "#f43f5e", colorClass: "bg-rose-500" }
], ls = "#f97316", ce = [
{
key: "default",
name: "默认后台",
description: "适合日常后台管理,保留完整导航与标签栏。",
theme: "light",
themeColor: "#f97316",
contentWidth: "fluid",
showTabBar: !0,
showFooter: !0,
enablePageTransition: !0,
menuCollapsed: !1,
enableTabCache: !0,
enableTabPersist: !0
},
{
key: "compact",
name: "紧凑工作台",
description: "更聚焦内容区,适合高频操作与数据录入。",
theme: "light",
themeColor: "#3b82f6",
contentWidth: "fluid",
showTabBar: !0,
showFooter: !1,
enablePageTransition: !1,
menuCollapsed: !0,
enableTabCache: !0,
enableTabPersist: !0
}
], is = (e) => ce.find((t) => t.key === e), be = ue("app-config", {
state: () => ({
presetKey: K("bag.layout.presetKey", "default"),
theme: K("bag.theme", "light"),
themeColor: K("bag.themeColor", ls),
contentWidth: K("bag.layout.contentWidth", "fluid"),
showTabBar: K("bag.layout.showTabBar", !0),
showFooter: K("bag.layout.showFooter", !0),
enablePageTransition: K("bag.layout.enablePageTransition", !0),
settingsDrawerOpen: !1
}),
getters: {
isDarkTheme: (e) => e.theme === "dark",
themeTokens: (e) => os(e.theme, e.themeColor)
},
actions: {
ensureValidPresetKey() {
if (this.presetKey === "custom") return;
ce.some((t) => t.key === this.presetKey) || (this.presetKey = "default");
},
syncPresetState() {
if (this.ensureValidPresetKey(), this.presetKey === "custom") return;
const e = is(this.presetKey);
e && (this.theme = e.theme, this.themeColor = e.themeColor, this.contentWidth = e.contentWidth, this.showTabBar = e.showTabBar, this.showFooter = e.showFooter, this.enablePageTransition = e.enablePageTransition);
},
markAsCustom() {
this.presetKey = "custom";
},
setTheme(e) {
this.markAsCustom(), this.theme = e, this.applyThemeClass(), this.applyThemeColorVariables();
},
toggleTheme() {
this.setTheme(this.theme === "light" ? "dark" : "light");
},
setThemeColor(e) {
this.markAsCustom(), this.themeColor = e, this.applyThemeColorVariables();
},
setContentWidth(e) {
this.markAsCustom(), this.contentWidth = e;
},
setShowTabBar(e) {
this.markAsCustom(), this.showTabBar = e;
},
setShowFooter(e) {
this.markAsCustom(), this.showFooter = e;
},
setEnablePageTransition(e) {
this.markAsCustom(), this.enablePageTransition = e;
},
setPresetKey(e) {
this.presetKey = e;
},
openSettingsDrawer() {
this.settingsDrawerOpen = !0;
},
closeSettingsDrawer() {
this.settingsDrawerOpen = !1;
},
resetAppearance() {
this.presetKey = "default", this.applyAppearance();
},
applyAppearance() {
this.syncPresetState(), this.applyThemeClass(), this.applyThemeColorVariables();
},
applyThemeClass() {
typeof document > "u" || (this.theme === "dark" ? document.documentElement.classList.add("dark") : document.documentElement.classList.remove("dark"));
},
applyThemeColorVariables() {
typeof document > "u" || rs(this.themeTokens);
}
}
}), cs = {
title: "Vue Bag Admin",
compactTitle: "VBA",
logoAlt: "Vue Bag Admin",
homePath: "/dashboard",
showTitle: !0
}, ds = [
{ key: "notify", label: "通知", emptyText: "暂无新通知" },
{ key: "system", label: "系统", emptyText: "暂无系统消息" },
{ key: "todo", label: "待办", emptyText: "暂无待办事项" }
], us = () => ({
notify: [
{
id: 1,
title: "有一条新的待处理通知",
time: "10分钟前",
type: "notice",
read: !1,
icon: "🔔",
color: "bg-orange-100 dark:bg-orange-500/20 text-orange-500"
},
{
id: 2,
title: "系统检测到一项配置需要确认",
time: "1小时前",
type: "warning",
read: !1,
icon: "⚠️",
color: "bg-rose-100 dark:bg-rose-500/20 text-rose-500"
},
{
id: 3,
title: "本周运行摘要已生成",
time: "昨天",
type: "success",
read: !0,
icon: "✅",
color: "bg-green-100 dark:bg-green-500/20 text-green-500"
}
],
system: [
{
id: 1,
title: "系统升级通知:今晚凌晨2点进行停机维护",
time: "2天前",
type: "system",
read: !0,
icon: "🔔",
color: "bg-blue-100 dark:bg-blue-500/20 text-blue-500"
}
],
todo: []
}), hs = () => {
const e = us();
return {
tabs: ds.map((t) => ({ ...t })),
getList: (t) => (e[t] ?? []).map((o) => ({ ...o })),
getUnreadCount: () => Object.values(e).flat().filter((t) => !t.read).length,
markAllRead: (t) => {
(e[t] ?? []).forEach((o) => {
o.read = !0;
});
}
};
}, Je = Symbol("bag-host-ui-config");
function Qe(e) {
var a;
const t = hs(), o = z();
return {
branding: {
...cs,
homePath: o.homePath,
...e == null ? void 0 : e.branding
},
messageCenter: {
...t,
...e == null ? void 0 : e.messageCenter,
tabs: (a = e == null ? void 0 : e.messageCenter) != null && a.tabs && e.messageCenter.tabs.length > 0 ? e.messageCenter.tabs : t.tabs
},
slots: {
...e == null ? void 0 : e.slots
}
};
}
function ps(e, t) {
e.provide(Je, Qe(t));
}
function bs() {
return ft(Je, Qe());
}
const fs = { class: "app-layout min-h-screen relative overflow-hidden font-sans transition-colors duration-300" }, gs = { class: "bag-app-header backdrop-blur-xl border-b flex justify-between items-center shrink-0 relative z-20 px-4 md:px-6 transition-colors duration-300" }, ms = { class: "flex items-center h-full" }, vs = { class: "bag-brand-logo" }, ys = ["src", "alt"], ws = {
key: 1,
viewBox: "0 0 24 24",
class: "h-6 w-6 text-white",
fill: "currentColor"
}, xs = {
key: 0,
class: "bag-brand-copy"
}, ks = { class: "bag-brand-title" }, Cs = {
key: 0,
class: "bag-brand-badge"
}, Ps = { class: "hidden md:flex items-center text-sm font-bold" }, Ts = { class: "bag-current-menu-pill flex items-center gap-2 px-3 py-1.5 rounded-full border transition-colors duration-300" }, _s = { class: "bag-header-actions text-slate-500 dark:text-slate-400 font-medium" }, Ms = { class: "bg-white dark:bg-[#0A1120] flex flex-col" }, As = { class: "max-h-[300px] overflow-y-auto custom-scrollbar" }, $s = {
key: 0,
class: "flex items-center justify-center py-10 text-sm text-slate-400 dark:text-slate-500"
}, Ss = {
key: 1,
class: "flex flex-col"
}, Bs = ["onClick"], Ls = {
key: 0,
class: "bag-notice-unread-dot absolute left-2 top-1/2 -translate-y-1/2 w-1.5 h-1.5 rounded-full"
}, Vs = { class: "text-lg" }, Es = { class: "flex-1 min-w-0" }, Hs = { class: "bag-notice-title text-sm line-clamp-2 leading-snug transition-colors" }, Rs = {
key: 0,
class: "text-xs text-slate-400 dark:text-slate-500 mt-1"
}, js = {
key: 2,
class: "py-10"
}, Ks = { class: "bag-header-action" }, Ds = { class: "bag-header-action-label hidden md:inline" }, Is = { class: "bag-header-action-icon" }, Os = {
key: 0,
xmlns: "http://www.w3.org/2000/svg",
class: "h-4 w-4",
viewBox: "0 0 24 24",
fill: "none",
stroke: "currentColor",
"stroke-width": "2",
"stroke-linecap": "round",
"stroke-linejoin": "round"
}, zs = {
key: 1,
xmlns: "http://www.w3.org/2000/svg",
class: "h-4 w-4",
viewBox: "0 0 24 24",
fill: "none",
stroke: "currentColor",
"stroke-width": "2",
"stroke-linecap": "round",
"stroke-linejoin": "round"
}, Ns = { class: "bag-user-entry" }, Us = { class: "font-bold text-slate-700 dark:text-slate-200" }, Ws = { class: "flex h-[calc(100vh-64px)] relative z-10" }, Fs = { class: "flex-1 overflow-y-auto custom-scrollbar p-3" }, Zs = { class: "flex-1 flex flex-col min-w-0 overflow-hidden bg-transparent" }, Xs = { class: "flex-1 overflow-auto custom-scrollbar relative flex flex-col" }, Ys = {
key: 0,
class: "bag-layout-footer py-4 text-center text-sm border-t mt-auto"
}, Gs = /* @__PURE__ */ ee({
__name: "DefaultLayout",
setup(e) {
const { locale: t, fallbackLocale: o, messages: a, t: i } = Me(), c = Se(), d = he(), u = be(), T = bs(), _ = $e(), v = Ae(), M = z(), A = O("notify"), j = O(!1), $ = O(!1), D = O(0), B = O({}), P = jt(Kt).smaller("md");
gt(() => {
P.value && c.setCollapsed(!0);
});
const f = S(() => c.collapsed), p = S(() => T.branding), I = S(() => T.messageCenter), ne = S(() => I.value.tabs), W = S(() => T.slots.brand), le = S(() => {
var r;
const n = (r = p.value.compactTitle) == null ? void 0 : r.trim();
return P.value && n ? n : p.value.title;
});
Ce(
ne,
(n) => {
var r;
n.some((l) => l.key === A.value) || (A.value = ((r = n[0]) == null ? void 0 : r.key) ?? "notify");
},
{ immediate: !0 }
), Ce(A, (n) => {
j.value && se(n);
});
const G = (n) => B.value[n] ?? [], te = (n) => n.key === "notify" && D.value > 0 ? `${n.label} (${D.value})` : n.label, se = async (n) => {
var r, l;
$.value = !0;
try {
const x = await Promise.resolve(((l = (r = I.value).getList) == null ? void 0 : l.call(r, n)) ?? []);
B.value = {
...B.value,
[n]: x ?? []
};
} catch (x) {
console.error("[bag-host] failed to load message list:", x), B.value = {
...B.value,
[n]: []
};
} finally {
$.value = !1;
}
}, oe = async () => {
var n, r;
try {
D.value = await Promise.resolve(
((r = (n = I.value).getUnreadCount) == null ? void 0 : r.call(n)) ?? Object.values(B.value).flat().filter((l) => !l.read).length
);
} catch (l) {
console.error("[bag-host] failed to load unread count:", l), D.value = 0;
}
}, fe = (n) => {
j.value = n, n && Promise.all([se(A.value), oe()]);
}, ge = (n, r) => {
const l = G(r).map(
(x) => x.id === n ? { ...x, read: !0 } : x
);
B.value = {
...B.value,
[r]: l
};
}, b = async () => {
var r, l;
const n = A.value;
await Promise.resolve((l = (r = I.value).markAllRead) == null ? void 0 : l.call(r, n)), await se(n), await oe();
}, g = async (n, r) => {
var l, x;
n.read || (ge(n.id, r), await oe()), await Promise.resolve((x = (l = I.value).onItemClick) == null ? void 0 : x.call(l, n, r));
}, y = async () => {
var n, r;
await Promise.resolve((r = (n = I.value).onViewAll) == null ? void 0 : r.call(n, A.value));
}, C = S(() => {
var r;
const n = (r = v.meta) == null ? void 0 : r.activeMenu;
return typeof n == "string" ? n : v.path;
}), X = (n) => [...n].sort((r, l) => (r.sort ?? 0) - (l.sort ?? 0)), st = (n) => n.hidden ? !1 : pe({
roles: n.roles,
permissions: n.permissions
}), Le = (n) => X(n).map((r) => {
const l = r.children ? Le(r.children) : void 0;
return { ...r, children: l };
}).filter((r) => {
var l;
return st(r) ? ((l = r.children) != null && l.length, !0) : !1;
}), Ve = [
{
path: M.homePath,
title: "menu.dashboard",
icon: "dashboard"
}
], ot = (n) => !!n && /^[A-Za-z0-9_-]+(?:\.[A-Za-z0-9_-]+)+$/.test(n), at = () => {
const n = [t.value], r = o.value;
if (typeof r == "string")
n.push(r);
else if (Array.isArray(r))
n.push(...r);
else if (r && typeof r == "object") {
const l = r[t.value];
typeof l == "string" ? n.push(l) : Array.isArray(l) && n.push(...l);
const x = r.default;
typeof x == "string" ? n.push(x) : Array.isArray(x) && n.push(...x);
}
return [...new Set(n.filter(Boolean))];
}, rt = (n, r) => {
var x;
let l = (x = a.value) == null ? void 0 : x[n];
for (const F of r.split(".")) {
if (!l || typeof l != "object" || !(F in l))
return;
l = l[F];
}
return typeof l == "string" ? l : void 0;
}, me = (n) => {
if (!n) return "";
if (!ot(n)) return n;
for (const r of at()) {
const l = rt(r, n);
if (l) return l;
}
return n;
}, nt = S(() => {
var x;
const n = [...Ve, ...c.menus], r = (F, Ee) => {
for (const ie of F) {
if (ie.path === Ee) return ie.title;
if (ie.children) {
const He = r(ie.children, Ee);
if (He) return He;
}
}
}, l = r(n, C.value);
return l ? me(l) : (x = v.meta) != null && x.title ? me(v.meta.title) : "";
}), lt = S(() => {
const n = (l) => {
var F;
const x = me(l.title);
return {
key: l.path,
label: () => k("div", { class: "bag-menu-option-label" }, [
k("span", { class: "bag-menu-option-text" }, x || l.title),
l.badge ? k(
"span",
{
class: "bag-menu-badge"
},
l.badge
) : null
]),
icon: Nt(l.icon),
children: (F = l.children) == null ? void 0 : F.map(n)
};
}, r = [...Ve, ...c.menus];
return Le(r).map(n);
}), it = [
{ label: "中文", key: "zh-CN" },
{ label: "English", key: "en" }
], ct = (n) => {
t.value = n, localStorage.setItem("lang", n);
}, dt = S(() => [
{ label: i("sysSetting.profile") || "个人中心", key: "profile" },
{ label: i("sysSetting.logout") || "退出登录", key: "logout" }
]), ut = (n) => {
n === "profile" ? _.push(M.profilePath) : n === "logout" && bt();
}, ht = (n) => {
if (n.startsWith("http://") || n.startsWith("https://")) {
window.open(n, "_blank", "noopener,noreferrer");
return;
}
_.push(n), P.value && c.setMobileDrawer(!1);
}, pt = () => {
const n = p.value.homePath;
!n || v.path === n || _.push(n);
}, bt = () => {
d.logout(), _.push(M.loginPath);
};
return (n, r) => (m(), w("div", fs, [
r[22] || (r[22] = s("div", { class: "bag-workspace-accent bag-workspace-accent--primary absolute top-0 right-0 w-96 h-96 rounded-full blur-[100px] pointer-events-none transition-colors duration-300" }, null, -1)),
r[23] || (r[23] = s("div", { class: "bag-workspace-accent bag-workspace-accent--accent absolute bottom-0 left-0 w-96 h-96 rounded-full blur-[100px] pointer-events-none transition-colors duration-300" }, null, -1)),
s("header", gs, [
s("div", ms, [
h(P) ? (m(), w("button", {
key: 0,
onClick: r[0] || (r[0] = (l) => h(c).toggleMobileDrawer()),
class: "bag-mobile-menu-btn p-2 -ml-2 mr-2 rounded-xl transition-colors md:hidden"
}, [...r[7] || (r[7] = [
s("svg", {
xmlns: "http://www.w3.org/2000/svg",
class: "h-6 w-6",
fill: "none",
viewBox: "0 0 24 24",
stroke: "currentColor"
}, [
s("path", {
"stroke-linecap": "round",
"stroke-linejoin": "round",
"stroke-width": "2",
d: "M4 6h16M4 12h16M4 18h16"
})
], -1)
])])) : E("", !0),
W.value ? (m(), U(Pe(W.value), {
key: 1,
class: "bag-brand-slot"
})) : (m(), w("button", {
key: 2,
class: V(["bag-brand group", { "is-static": !p.value.homePath }]),
type: "button",
onClick: pt
}, [
s("span", vs, [
p.value.logo ? (m(), w("img", {
key: 0,
src: p.value.logo,
alt: p.value.logoAlt || p.value.title,
class: "bag-brand-logo-image"
}, null, 8, ys)) : (m(), w("svg", ws, [...r[8] || (r[8] = [
s("path", { d: "M16 6V4a2 2 0 0 0-2-2h-4a2 2 0 0 0-2 2v2H4a2 2 0 0 0-2 2v10a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-4zm-6-2h4v2h-4V4zm10 14H4V8h16v10z" }, null, -1),
s("path", { d: "M9 10a1 1 0 0 0-1 1v2a1 1 0 0 0 2 0v-2a1 1 0 0 0-1-1zm6 0a1 1 0 0 0-1 1v2a1 1 0 0 0 2 0v-2a1 1 0 0 0-1-1z" }, null, -1)
])]))
]),
p.value.showTitle ? (m(), w("span", xs, [
s("span", ks, L(le.value), 1),
p.value.badge ? (m(), w("span", Cs, L(p.value.badge), 1)) : E("", !0)
])) : E("", !0)
], 2)),
r[9] || (r[9] = s("div", { class: "hidden md:block w-px h-6 bg-gray-200 dark:bg-gray-700 mx-6 transition-colors duration-300" }, null, -1)),
s("div", Ps, [
s("div", Ts, L(nt.value || "工作台"), 1)
])
]),
s("div", _s, [
s("div", {
class: "bag-header-action hidden sm:flex",
onClick: r[1] || (r[1] = (l) => h(_).push(h(M).homePath))
}, [...r[10] || (r[10] = [
je('<div class="bag-header-action-icon"><svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m3 9 9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"></path><polyline points="9 22 9 12 15 12 15 22"></polyline></svg></div><span class="bag-header-action-label hidden lg:inline">首页</span>', 2)
])]),
H(h(At), {
trigger: "click",
placement: "bottom-end",
width: 320,
style: { padding: "0", "border-radius": "12px", overflow: "hidden" },
"onUpdate:show": fe
}, {
trigger: R(() => [...r[11] || (r[11] = [
s("div", { class: "bag-header-action hidden sm:flex relative" }, [
s("div", { class: "bag-header-action-icon" }, [
s("svg", {
xmlns: "http://www.w3.org/2000/svg",
class: "h-4 w-4",
viewBox: "0 0 24 24",
fill: "none",
stroke: "currentColor",
"stroke-width": "2",
"stroke-linecap": "round",
"stroke-linejoin": "round"
}, [
s("path", { d: "M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9" }),
s("path", { d: "M13.73 21a2 2 0 0 1-3.46 0" })
])
]),
s("span", { class: "bag-header-action-label hidden lg:inline" }, "消息")
], -1)
])]),
default: R(() => [
s("div", Ms, [
s("div", { class: "px-4 py-3 flex justify-between items-center border-b border-gray-100 dark:border-gray-800" }, [
r[12] || (r[12] = s("span", { class: "font-bold text-slate-700 dark:text-slate-200" }, "消息通知", -1)),
s("button", {
type: "button",
class: "bag-notice-action",
onClick: b
}, " 全部已读 ")
]),
H(h($t), {
value: A.value,
"onUpdate:value": r[2] || (r[2] = (l) => A.value = l),
type: "line",
"justify-content": "space-evenly",
class: "mt-1",
"pane-style": "padding: 0;"
}, {
default: R(() => [
(m(!0), w(Q, null, q(ne.value, (l) => (m(), U(h(St), {
key: l.key,
name: l.key,
tab: te(l)
}, {
default: R(() => [
s("div", As, [
$.value ? (m(), w("div", $s, " 消息加载中... ")) : G(l.key).length > 0 ? (m(), w("div", Ss, [
(m(!0), w(Q, null, q(G(l.key), (x) => (m(), w("div", {
key: x.id,
class: V(["bag-notice-item px-4 py-3 cursor-pointer transition-colors flex gap-3 group relative", { "opacity-60": x.read }]),
onClick: (F) => g(x, l.key)
}, [
x.read ? E("", !0) : (m(), w("div", Ls)),
s("div", {
class: V(["w-10 h-10 rounded-full flex items-center justify-center shrink-0", x.color])
}, [
s("span", Vs, L(x.icon || "🔔"), 1)
], 2),
s("div", Es, [
s("p", Hs, L(x.title), 1),
x.time ? (m(), w("p", Rs, L(x.time), 1)) : E("", !0)
])
], 10, Bs))), 128))
])) : (m(), w("div", js, [
H(h(Bt), {
description: l.emptyText || `暂无${l.label}`
}, null, 8, ["description"])
]))
])
]),
_: 2
}, 1032, ["name", "tab"]))), 128))
]),
_: 1
}, 8, ["value"]),
s("div", { class: "border-t border-gray-100 dark:border-gray-800 p-2" }, [
s("button", {
type: "button",
class: "bag-notice-footer-btn",
onClick: y
}, " 查看全部消息 ")
])
])
]),
_: 1
}),
H(h(Te), {
trigger: "click",
options: it,
onSelect: ct
}, {
default: R(() => [
s("div", Ks, [
r[13] || (r[13] = s("div", { class: "bag-header-action-icon" }, [
s("svg", {
xmlns: "http://www.w3.org/2000/svg",
class: "h-4 w-4",
viewBox: "0 0 24 24",
fill: "none",
stroke: "currentColor",
"stroke-width": "2",
"stroke-linecap": "round",
"stroke-linejoin": "round"
}, [
s("circle", {
cx: "12",
cy: "12",
r: "10"
}),
s("path", { d: "M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z" }),
s("path", { d: "M2 12h20" })
])
], -1)),
s("span", Ds, L(h(t) === "en" ? "EN" : "中"), 1)
])
]),
_: 1
}),
s("div", {
class: "bag-header-action bag-header-action--icon",
onClick: r[3] || (r[3] = (l) => h(u).toggleTheme())
}, [
s("div", Is, [
h(u).theme === "light" ? (m(), w("svg", Os, [...r[14] || (r[14] = [
je('<circle cx="12" cy="12" r="5"></circle><line x1="12" y1="1" x2="12" y2="3"></l