smart-admin-web 10.12.1 → 10.12.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api/index.d.ts +13 -1
- package/dist/api/index.js +25 -13
- package/dist/api/index.js.map +1 -1
- package/dist/api/schema.d.ts +360 -3
- package/dist/assets/icons/ph-subset.json.js +1 -1
- package/dist/lib/runtime.js +1 -1
- package/dist/locales/en-US.d.ts +12 -1
- package/dist/locales/en-US.js +13 -2
- package/dist/locales/en-US.js.map +1 -1
- package/dist/locales/zh-CN.d.ts +12 -1
- package/dist/locales/zh-CN.js +13 -2
- package/dist/locales/zh-CN.js.map +1 -1
- package/dist/router/index.js +18 -13
- package/dist/router/index.js.map +1 -1
- package/dist/router/viewRegistry.js +1 -1
- package/dist/router/viewRegistry.js.map +1 -1
- package/dist/style.css +1 -1
- package/dist/types/api.d.ts +26 -0
- package/dist/types/api.js.map +1 -1
- package/dist/views/dashboard/ShortcutPicker.vue.d.ts +16 -0
- package/dist/views/dashboard/ShortcutPicker.vue.js +8 -0
- package/dist/views/dashboard/ShortcutPicker.vue.js.map +1 -0
- package/dist/views/dashboard/ShortcutPicker2.vue.js +86 -0
- package/dist/views/dashboard/ShortcutPicker2.vue.js.map +1 -0
- package/dist/views/dashboard/biz.vue.js +2 -2
- package/dist/views/dashboard/biz2.vue.js +265 -93
- package/dist/views/dashboard/biz2.vue.js.map +1 -1
- package/dist/views/dashboard/onlineDuration.d.ts +5 -0
- package/dist/views/dashboard/onlineDuration.js +8 -0
- package/dist/views/dashboard/onlineDuration.js.map +1 -0
- package/dist/views/dashboard/shortcutGroups.d.ts +18 -0
- package/dist/views/dashboard/shortcutGroups.js +19 -0
- package/dist/views/dashboard/shortcutGroups.js.map +1 -0
- package/dist/views/system/user/index.vue.js +2 -2
- package/dist/views/system/user/index2.vue.js +281 -211
- package/dist/views/system/user/index2.vue.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
type __VLS_Props = {
|
|
2
|
+
excludePaths: string[];
|
|
3
|
+
};
|
|
4
|
+
type __VLS_ModelProps = {
|
|
5
|
+
'show'?: boolean;
|
|
6
|
+
};
|
|
7
|
+
type __VLS_PublicProps = __VLS_Props & __VLS_ModelProps;
|
|
8
|
+
declare const __VLS_export: import('vue').DefineComponent<__VLS_PublicProps, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
|
|
9
|
+
pick: (path: string) => any;
|
|
10
|
+
"update:show": (value: boolean) => any;
|
|
11
|
+
}, string, import('vue').PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
|
|
12
|
+
onPick?: ((path: string) => any) | undefined;
|
|
13
|
+
"onUpdate:show"?: ((value: boolean) => any) | undefined;
|
|
14
|
+
}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
|
|
15
|
+
declare const _default: typeof __VLS_export;
|
|
16
|
+
export default _default;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import o from "./ShortcutPicker2.vue.js";
|
|
2
|
+
/* empty css */
|
|
3
|
+
import t from "../../_virtual/_plugin-vue_export-helper.js";
|
|
4
|
+
const m = /* @__PURE__ */ t(o, [["__scopeId", "data-v-1ba501cb"]]);
|
|
5
|
+
export {
|
|
6
|
+
m as default
|
|
7
|
+
};
|
|
8
|
+
//# sourceMappingURL=ShortcutPicker.vue.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ShortcutPicker.vue.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { defineComponent as _, useModel as g, ref as m, watch as M, nextTick as b, computed as B, openBlock as n, createBlock as f, unref as l, withCtx as i, createVNode as s, createCommentVNode as S, createElementBlock as h, Fragment as z, renderList as E, createElementVNode as L, toDisplayString as P, mergeModels as v } from "vue";
|
|
2
|
+
import { NModal as V, NCard as q, NInput as F, NScrollbar as I, NEmpty as R } from "naive-ui";
|
|
3
|
+
import { useI18n as T } from "vue-i18n";
|
|
4
|
+
import { useMenuFlat as U } from "../../composables/useMenuFlat.js";
|
|
5
|
+
import { translateMenuTitle as $ } from "../../locales/menuTitle.js";
|
|
6
|
+
import A from "../../components/AppIcon.vue.js";
|
|
7
|
+
const D = ["onClick"], W = /* @__PURE__ */ _({
|
|
8
|
+
__name: "ShortcutPicker",
|
|
9
|
+
props: /* @__PURE__ */ v({
|
|
10
|
+
excludePaths: {}
|
|
11
|
+
}, {
|
|
12
|
+
show: { type: Boolean, default: !1 },
|
|
13
|
+
showModifiers: {}
|
|
14
|
+
}),
|
|
15
|
+
emits: /* @__PURE__ */ v(["pick"], ["update:show"]),
|
|
16
|
+
setup(u, { emit: w }) {
|
|
17
|
+
const k = u, y = w, a = g(u, "show"), { t: c } = T(), x = U(), r = m(""), p = m();
|
|
18
|
+
M(a, (o) => {
|
|
19
|
+
o && (r.value = "", b(() => {
|
|
20
|
+
var t;
|
|
21
|
+
return (t = p.value) == null ? void 0 : t.focus();
|
|
22
|
+
}));
|
|
23
|
+
});
|
|
24
|
+
function C(o) {
|
|
25
|
+
return $(o.title);
|
|
26
|
+
}
|
|
27
|
+
const d = B(() => {
|
|
28
|
+
const o = new Set(k.excludePaths), t = r.value.trim().toLowerCase();
|
|
29
|
+
return x.value.filter((e) => !o.has(e.path)).map((e) => ({ ...e, display: C(e) })).filter((e) => !t || e.display.toLowerCase().includes(t));
|
|
30
|
+
});
|
|
31
|
+
function N(o) {
|
|
32
|
+
y("pick", o), a.value = !1;
|
|
33
|
+
}
|
|
34
|
+
return (o, t) => (n(), f(l(V), {
|
|
35
|
+
show: a.value,
|
|
36
|
+
"onUpdate:show": t[1] || (t[1] = (e) => a.value = e)
|
|
37
|
+
}, {
|
|
38
|
+
default: i(() => [
|
|
39
|
+
s(l(q), {
|
|
40
|
+
style: { width: "420px" },
|
|
41
|
+
title: l(c)("biz.quickAdd"),
|
|
42
|
+
bordered: !1,
|
|
43
|
+
size: "small",
|
|
44
|
+
role: "dialog"
|
|
45
|
+
}, {
|
|
46
|
+
default: i(() => [
|
|
47
|
+
s(l(F), {
|
|
48
|
+
ref_key: "inputRef",
|
|
49
|
+
ref: p,
|
|
50
|
+
value: r.value,
|
|
51
|
+
"onUpdate:value": t[0] || (t[0] = (e) => r.value = e),
|
|
52
|
+
placeholder: l(c)("common.search"),
|
|
53
|
+
clearable: ""
|
|
54
|
+
}, null, 8, ["value", "placeholder"]),
|
|
55
|
+
s(l(I), { style: { "max-height": "320px", "margin-top": "12px" } }, {
|
|
56
|
+
default: i(() => [
|
|
57
|
+
d.value.length ? S("", !0) : (n(), f(l(R), {
|
|
58
|
+
key: 0,
|
|
59
|
+
class: "empty"
|
|
60
|
+
})),
|
|
61
|
+
(n(!0), h(z, null, E(d.value, (e) => (n(), h("div", {
|
|
62
|
+
key: e.path,
|
|
63
|
+
class: "row",
|
|
64
|
+
onClick: (j) => N(e.path)
|
|
65
|
+
}, [
|
|
66
|
+
s(A, {
|
|
67
|
+
icon: e.icon || "ph:squares-four",
|
|
68
|
+
size: 16
|
|
69
|
+
}, null, 8, ["icon"]),
|
|
70
|
+
L("span", null, P(e.display), 1)
|
|
71
|
+
], 8, D))), 128))
|
|
72
|
+
]),
|
|
73
|
+
_: 1
|
|
74
|
+
})
|
|
75
|
+
]),
|
|
76
|
+
_: 1
|
|
77
|
+
}, 8, ["title"])
|
|
78
|
+
]),
|
|
79
|
+
_: 1
|
|
80
|
+
}, 8, ["show"]));
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
export {
|
|
84
|
+
W as default
|
|
85
|
+
};
|
|
86
|
+
//# sourceMappingURL=ShortcutPicker2.vue.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ShortcutPicker2.vue.js","sources":["../../../src/views/dashboard/ShortcutPicker.vue"],"sourcesContent":["<script setup lang=\"ts\">\n// 复用 MenuSearch.vue 的\"搜索+标题翻译+高亮候选\"思路,但不是同一个组件——MenuSearch 是全局命令面板,\n// 点了就跳转;这里点了是回调 pick(仅置顶,不导航),排除列表也不一样(排除已置顶,不是排除当前页)。\nimport { computed, nextTick, ref, watch } from 'vue'\nimport { NModal, NCard, NInput, NEmpty, NScrollbar } from 'naive-ui'\nimport { useI18n } from 'vue-i18n'\nimport { useMenuFlat, type MenuLeaf } from '#/composables/useMenuFlat'\nimport { translateMenuTitle } from '#/locales/menuTitle'\nimport AppIcon from '#/components/AppIcon.vue'\n\nconst props = defineProps<{ excludePaths: string[] }>()\nconst emit = defineEmits<{ pick: [path: string] }>()\nconst show = defineModel<boolean>('show', { default: false })\n\nconst { t } = useI18n()\nconst leaves = useMenuFlat()\nconst keyword = ref('')\nconst inputRef = ref<InstanceType<typeof NInput>>()\n\nwatch(show, v => {\n if (v) {\n keyword.value = ''\n nextTick(() => inputRef.value?.focus())\n }\n})\n\nfunction label(item: MenuLeaf) {\n return translateMenuTitle(item.title)\n}\n\nconst candidates = computed(() => {\n const excluded = new Set(props.excludePaths)\n const kw = keyword.value.trim().toLowerCase()\n return leaves.value\n .filter(l => !excluded.has(l.path))\n .map(l => ({ ...l, display: label(l) }))\n .filter(l => !kw || l.display.toLowerCase().includes(kw))\n})\n\nfunction pick(path: string) {\n emit('pick', path)\n show.value = false\n}\n</script>\n\n<template>\n <n-modal v-model:show=\"show\">\n <n-card\n style=\"width: 420px\"\n :title=\"t('biz.quickAdd')\"\n :bordered=\"false\"\n size=\"small\"\n role=\"dialog\"\n >\n <n-input ref=\"inputRef\" v-model:value=\"keyword\" :placeholder=\"t('common.search')\" clearable />\n <n-scrollbar style=\"max-height: 320px; margin-top: 12px\">\n <n-empty v-if=\"!candidates.length\" class=\"empty\" />\n <div v-for=\"c in candidates\" :key=\"c.path\" class=\"row\" @click=\"pick(c.path)\">\n <AppIcon :icon=\"c.icon || 'ph:squares-four'\" :size=\"16\" />\n <span>{{ c.display }}</span>\n </div>\n </n-scrollbar>\n </n-card>\n </n-modal>\n</template>\n\n<style scoped>\n.row {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 10px;\n border-radius: var(--radius-md);\n cursor: pointer;\n}\n.row:hover {\n background: var(--color-fill-hover);\n}\n.empty {\n padding: 24px 0;\n}\n</style>\n"],"names":["props","__props","emit","__emit","show","_useModel","t","useI18n","leaves","useMenuFlat","keyword","ref","inputRef","watch","v","nextTick","_a","label","item","translateMenuTitle","candidates","computed","excluded","kw","l","pick","path","_createBlock","_unref","NModal","$event","_createVNode","NCard","NInput","NScrollbar","NEmpty","_createElementBlock","_Fragment","_renderList","c","AppIcon","_createElementVNode","_toDisplayString"],"mappings":";;;;;;;;;;;;;;;;AAUA,UAAMA,IAAQC,GACRC,IAAOC,GACPC,IAAOC,EAAoBJ,GAAC,MAA0B,GAEtD,EAAE,GAAAK,EAAA,IAAMC,EAAA,GACRC,IAASC,EAAA,GACTC,IAAUC,EAAI,EAAE,GAChBC,IAAWD,EAAA;AAEjB,IAAAE,EAAMT,GAAM,CAAAU,MAAK;AACf,MAAIA,MACFJ,EAAQ,QAAQ,IAChBK,EAAS,MAAA;;AAAM,gBAAAC,IAAAJ,EAAS,UAAT,gBAAAI,EAAgB;AAAA,OAAO;AAAA,IAE1C,CAAC;AAED,aAASC,EAAMC,GAAgB;AAC7B,aAAOC,EAAmBD,EAAK,KAAK;AAAA,IACtC;AAEA,UAAME,IAAaC,EAAS,MAAM;AAChC,YAAMC,IAAW,IAAI,IAAItB,EAAM,YAAY,GACrCuB,IAAKb,EAAQ,MAAM,KAAA,EAAO,YAAA;AAChC,aAAOF,EAAO,MACX,OAAO,CAAAgB,MAAK,CAACF,EAAS,IAAIE,EAAE,IAAI,CAAC,EACjC,IAAI,CAAAA,OAAM,EAAE,GAAGA,GAAG,SAASP,EAAMO,CAAC,EAAA,EAAI,EACtC,OAAO,CAAAA,MAAK,CAACD,KAAMC,EAAE,QAAQ,YAAA,EAAc,SAASD,CAAE,CAAC;AAAA,IAC5D,CAAC;AAED,aAASE,EAAKC,GAAc;AAC1B,MAAAxB,EAAK,QAAQwB,CAAI,GACjBtB,EAAK,QAAQ;AAAA,IACf;2BAIEuB,EAiBUC,EAAAC,CAAA,GAAA;AAAA,MAjBO,MAAMzB,EAAA;AAAA,8CAAAA,EAAI,QAAA0B;AAAA,IAAA;iBACzB,MAeS;AAAA,QAfTC,EAeSH,EAAAI,CAAA,GAAA;AAAA,UAdP,OAAA,EAAA,OAAA,QAAA;AAAA,UACC,OAAOJ,EAAAtB,CAAA,EAAC,cAAA;AAAA,UACR,UAAU;AAAA,UACX,MAAK;AAAA,UACL,MAAK;AAAA,QAAA;qBAEL,MAA8F;AAAA,YAA9FyB,EAA8FH,EAAAK,CAAA,GAAA;AAAA,uBAAjF;AAAA,cAAJ,KAAIrB;AAAA,cAAmB,OAAOF,EAAA;AAAA,uDAAAA,EAAO,QAAAoB;AAAA,cAAG,aAAaF,EAAAtB,CAAA,EAAC,eAAA;AAAA,cAAmB,WAAA;AAAA,YAAA;YAClFyB,EAMcH,EAAAM,CAAA,GAAA,EAND,OAAA,EAAA,cAAA,SAAA,cAAA,OAAA,KAA2C;AAAA,yBACtD,MAAmD;AAAA,gBAAnCd,EAAA,MAAW,2BAA3BO,EAAmDC,EAAAO,CAAA,GAAA;AAAA;kBAAhB,OAAM;AAAA,gBAAA;wBACzCC,EAGMC,GAAA,MAAAC,EAHWlB,EAAA,OAAU,CAAfmB,YAAZH,EAGM,OAAA;AAAA,kBAHwB,KAAKG,EAAE;AAAA,kBAAM,OAAM;AAAA,kBAAO,SAAK,CAAAT,MAAEL,EAAKc,EAAE,IAAI;AAAA,gBAAA;kBACxER,EAA0DS,GAAA;AAAA,oBAAhD,MAAMD,EAAE,QAAI;AAAA,oBAAwB,MAAM;AAAA,kBAAA;kBACpDE,EAA4B,QAAA,MAAAC,EAAnBH,EAAE,OAAO,GAAA,CAAA;AAAA,gBAAA;;;;;;;;;;;;"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import o from "./biz2.vue.js";
|
|
2
2
|
/* empty css */
|
|
3
3
|
import t from "../../_virtual/_plugin-vue_export-helper.js";
|
|
4
|
-
const
|
|
4
|
+
const p = /* @__PURE__ */ t(o, [["__scopeId", "data-v-4a6a23e0"]]);
|
|
5
5
|
export {
|
|
6
|
-
|
|
6
|
+
p as default
|
|
7
7
|
};
|
|
8
8
|
//# sourceMappingURL=biz.vue.js.map
|
|
@@ -1,136 +1,308 @@
|
|
|
1
|
-
import { defineComponent as
|
|
2
|
-
import { NCard as
|
|
3
|
-
import { Icon as
|
|
4
|
-
import { useI18n as
|
|
5
|
-
import { useRoute as
|
|
6
|
-
import { useUserStore as
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import
|
|
12
|
-
import {
|
|
13
|
-
|
|
1
|
+
import { defineComponent as W, computed as b, ref as h, onMounted as X, onUnmounted as Y, openBlock as o, createElementBlock as s, createElementVNode as n, normalizeStyle as Z, createVNode as c, unref as t, toDisplayString as l, createCommentVNode as r, createSlots as tt, withCtx as d, Fragment as C, renderList as q, createBlock as y, createTextVNode as R, withModifiers as F } from "vue";
|
|
2
|
+
import { NCard as D, NEmpty as I, NTag as et, NButton as ot, NList as it, NListItem as st } from "naive-ui";
|
|
3
|
+
import { Icon as S } from "@iconify/vue";
|
|
4
|
+
import { useI18n as nt } from "vue-i18n";
|
|
5
|
+
import { useRoute as at, useRouter as lt } from "vue-router";
|
|
6
|
+
import { useUserStore as ut } from "../../stores/user.js";
|
|
7
|
+
import { useAppStore as ct } from "../../stores/app.js";
|
|
8
|
+
import { btnGrad as rt } from "../../theme/mix.js";
|
|
9
|
+
import { personalApi as _, noticeApi as dt } from "../../api/index.js";
|
|
10
|
+
import { useMenuFlat as pt } from "../../composables/useMenuFlat.js";
|
|
11
|
+
import { translateMenuTitle as G } from "../../locales/menuTitle.js";
|
|
12
|
+
import { onlineDurationParts as vt } from "./onlineDuration.js";
|
|
13
|
+
import { buildShortcutGroups as mt } from "./shortcutGroups.js";
|
|
14
|
+
import ht from "./ShortcutPicker.vue.js";
|
|
15
|
+
import j from "../../components/AppIcon.vue.js";
|
|
16
|
+
import { fmtDateTime as E } from "../../utils/format.js";
|
|
17
|
+
import { uaSummary as _t } from "../../utils/ua.js";
|
|
18
|
+
const kt = { class: "view" }, ft = { class: "banner" }, bt = { class: "banner-body" }, yt = { class: "hi" }, gt = { class: "tip" }, wt = {
|
|
14
19
|
key: 0,
|
|
15
|
-
class: "
|
|
16
|
-
},
|
|
20
|
+
class: "meta-row"
|
|
21
|
+
}, zt = { key: 0 }, Ct = {
|
|
22
|
+
key: 1,
|
|
23
|
+
class: "meta-dot"
|
|
24
|
+
}, qt = { class: "row" }, St = {
|
|
25
|
+
key: 0,
|
|
26
|
+
class: "todo-list"
|
|
27
|
+
}, $t = ["onClick"], Tt = { class: "todo-main" }, xt = { class: "todo-title" }, Nt = {
|
|
28
|
+
key: 0,
|
|
29
|
+
class: "todo-sub"
|
|
30
|
+
}, Lt = { class: "todo-time" }, Pt = { key: 0 }, Dt = {
|
|
31
|
+
key: 0,
|
|
32
|
+
class: "quick-group-label"
|
|
33
|
+
}, It = {
|
|
34
|
+
key: 1,
|
|
35
|
+
class: "quick-grid"
|
|
36
|
+
}, Et = ["aria-label", "onClick"], Mt = ["onClick"], At = { class: "quick-name" }, Bt = {
|
|
37
|
+
key: 2,
|
|
38
|
+
class: "quick-group-label"
|
|
39
|
+
}, Ut = {
|
|
40
|
+
key: 3,
|
|
41
|
+
class: "quick-grid"
|
|
42
|
+
}, Vt = ["aria-label", "onClick"], Rt = ["onClick"], Ft = { class: "quick-name" }, Gt = { class: "notice-title" }, jt = {
|
|
17
43
|
key: 0,
|
|
18
44
|
class: "dot"
|
|
19
|
-
},
|
|
45
|
+
}, Ht = { class: "notice-time" }, re = /* @__PURE__ */ W({
|
|
20
46
|
__name: "biz",
|
|
21
|
-
setup(
|
|
22
|
-
const { t:
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
47
|
+
setup(Jt) {
|
|
48
|
+
const { t: a } = nt(), M = ut(), H = ct(), A = at(), g = lt(), J = pt(), K = b(() => ({ background: rt(H.accent) })), $ = h(null), m = h(null), B = h(/* @__PURE__ */ new Date());
|
|
49
|
+
let T;
|
|
50
|
+
const w = b(() => {
|
|
51
|
+
if (!$.value) return "";
|
|
52
|
+
const { hours: i, minutes: u } = vt($.value, B.value);
|
|
53
|
+
return i > 0 ? a("biz.onlineDuration", { hours: i, minutes: u }) : a("biz.onlineDurationShort", { minutes: u });
|
|
54
|
+
}), x = b(() => {
|
|
55
|
+
if (!m.value) return a("biz.firstLogin");
|
|
56
|
+
const i = _t(m.value.userAgent), u = m.value.ip ? ` · ${m.value.ip}` : "";
|
|
57
|
+
return `${a("biz.lastLogin", { time: E(m.value.time, { seconds: !1 }) })}${u}${i ? ` · ${i}` : ""}`;
|
|
58
|
+
}), p = h(null), z = h([]), N = h(!1), v = b(
|
|
59
|
+
() => mt(
|
|
60
|
+
z.value.filter((i) => i.menuPath !== A.path),
|
|
61
|
+
J.value
|
|
62
|
+
)
|
|
63
|
+
), O = b(() => z.value.filter((i) => i.pinned).map((i) => i.menuPath));
|
|
64
|
+
async function L() {
|
|
65
|
+
try {
|
|
66
|
+
z.value = await _.shortcuts();
|
|
67
|
+
} catch {
|
|
68
|
+
z.value = [];
|
|
69
|
+
}
|
|
29
70
|
}
|
|
30
|
-
|
|
31
|
-
|
|
71
|
+
async function U(i) {
|
|
72
|
+
await _.pinShortcut(i), await L();
|
|
73
|
+
}
|
|
74
|
+
async function Q(i) {
|
|
75
|
+
await _.unpinShortcut(i), await L();
|
|
76
|
+
}
|
|
77
|
+
const P = h([]);
|
|
78
|
+
return X(async () => {
|
|
79
|
+
var i;
|
|
80
|
+
T = setInterval(() => {
|
|
81
|
+
B.value = /* @__PURE__ */ new Date();
|
|
82
|
+
}, 6e4);
|
|
83
|
+
try {
|
|
84
|
+
const u = await _.sessions();
|
|
85
|
+
$.value = ((i = u.find((k) => k.isCurrent)) == null ? void 0 : i.loginTime) ?? null;
|
|
86
|
+
} catch {
|
|
87
|
+
}
|
|
32
88
|
try {
|
|
33
|
-
|
|
89
|
+
m.value = await _.lastLogin();
|
|
34
90
|
} catch {
|
|
91
|
+
m.value = null;
|
|
35
92
|
}
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
93
|
+
try {
|
|
94
|
+
p.value = await _.workbenchTodo();
|
|
95
|
+
} catch {
|
|
96
|
+
p.value = null;
|
|
97
|
+
}
|
|
98
|
+
await L();
|
|
99
|
+
try {
|
|
100
|
+
P.value = (await dt.mine({ page: 1, pageSize: 5 })).items;
|
|
101
|
+
} catch {
|
|
102
|
+
}
|
|
103
|
+
}), Y(() => {
|
|
104
|
+
T && clearInterval(T);
|
|
105
|
+
}), (i, u) => {
|
|
106
|
+
var k, V;
|
|
107
|
+
return o(), s("div", kt, [
|
|
108
|
+
n("div", ft, [
|
|
109
|
+
n("div", {
|
|
41
110
|
class: "avatar",
|
|
42
|
-
style:
|
|
111
|
+
style: Z(K.value)
|
|
43
112
|
}, [
|
|
44
|
-
|
|
113
|
+
c(t(S), {
|
|
45
114
|
icon: "ph:user",
|
|
46
115
|
width: 26,
|
|
47
116
|
color: "#fff"
|
|
48
117
|
})
|
|
49
118
|
], 4),
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
119
|
+
n("div", bt, [
|
|
120
|
+
n("div", yt, l(t(a)("biz.welcome", { name: ((k = t(M).userInfo) == null ? void 0 : k.name) ?? ((V = t(M).userInfo) == null ? void 0 : V.account) ?? "" })), 1),
|
|
121
|
+
n("div", gt, l(t(a)("biz.subtitle")), 1),
|
|
122
|
+
w.value || x.value ? (o(), s("div", wt, [
|
|
123
|
+
w.value ? (o(), s("span", zt, l(w.value), 1)) : r("", !0),
|
|
124
|
+
w.value && x.value ? (o(), s("span", Ct)) : r("", !0),
|
|
125
|
+
n("span", null, l(x.value), 1)
|
|
126
|
+
])) : r("", !0)
|
|
53
127
|
])
|
|
54
128
|
]),
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
129
|
+
n("div", qt, [
|
|
130
|
+
c(t(D), {
|
|
131
|
+
title: t(a)("biz.todo"),
|
|
132
|
+
bordered: !0
|
|
133
|
+
}, tt({
|
|
134
|
+
default: d(() => [
|
|
135
|
+
p.value && p.value.items.length ? (o(), s("div", St, [
|
|
136
|
+
(o(!0), s(C, null, q(p.value.items, (e) => (o(), s("div", {
|
|
137
|
+
key: e.id,
|
|
138
|
+
class: "todo-row",
|
|
139
|
+
onClick: (f) => e.url && t(g).push(e.url)
|
|
140
|
+
}, [
|
|
141
|
+
n("div", Tt, [
|
|
142
|
+
n("div", xt, l(e.title), 1),
|
|
143
|
+
e.description ? (o(), s("div", Nt, l(e.description), 1)) : r("", !0)
|
|
144
|
+
]),
|
|
145
|
+
n("span", Lt, l(t(E)(e.createTime, { seconds: !1 })), 1)
|
|
146
|
+
], 8, $t))), 128))
|
|
147
|
+
])) : (o(), y(t(I), {
|
|
148
|
+
key: 1,
|
|
149
|
+
description: t(a)("biz.todoEmpty")
|
|
150
|
+
}, null, 8, ["description"]))
|
|
151
|
+
]),
|
|
152
|
+
_: 2
|
|
153
|
+
}, [
|
|
154
|
+
p.value && p.value.totalCount > 0 ? {
|
|
155
|
+
name: "header-extra",
|
|
156
|
+
fn: d(() => [
|
|
157
|
+
c(t(et), {
|
|
158
|
+
type: "error",
|
|
159
|
+
round: "",
|
|
160
|
+
size: "small"
|
|
161
|
+
}, {
|
|
162
|
+
default: d(() => [
|
|
163
|
+
R(l(p.value.totalCount), 1)
|
|
164
|
+
]),
|
|
165
|
+
_: 1
|
|
166
|
+
})
|
|
167
|
+
]),
|
|
168
|
+
key: "0"
|
|
169
|
+
} : void 0
|
|
170
|
+
]), 1032, ["title"]),
|
|
171
|
+
c(t(D), {
|
|
172
|
+
title: t(a)("biz.quick"),
|
|
173
|
+
bordered: !0
|
|
174
|
+
}, {
|
|
175
|
+
"header-extra": d(() => [
|
|
176
|
+
c(t(ot), {
|
|
177
|
+
size: "small",
|
|
178
|
+
quaternary: "",
|
|
179
|
+
circle: "",
|
|
180
|
+
onClick: u[0] || (u[0] = (e) => N.value = !0)
|
|
65
181
|
}, {
|
|
66
|
-
icon:
|
|
67
|
-
|
|
68
|
-
icon:
|
|
69
|
-
|
|
70
|
-
}
|
|
71
|
-
]),
|
|
72
|
-
default: r(() => [
|
|
73
|
-
_(" " + a(t.title), 1)
|
|
182
|
+
icon: d(() => [
|
|
183
|
+
c(t(S), {
|
|
184
|
+
icon: "ph:plus",
|
|
185
|
+
width: 16
|
|
186
|
+
})
|
|
74
187
|
]),
|
|
75
|
-
_:
|
|
76
|
-
}
|
|
77
|
-
])
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
188
|
+
_: 1
|
|
189
|
+
})
|
|
190
|
+
]),
|
|
191
|
+
default: d(() => [
|
|
192
|
+
v.value.pinned.length || v.value.suggested.length ? (o(), s("div", Pt, [
|
|
193
|
+
v.value.pinned.length ? (o(), s("div", Dt, l(t(a)("biz.quickPinned")), 1)) : r("", !0),
|
|
194
|
+
v.value.pinned.length ? (o(), s("div", It, [
|
|
195
|
+
(o(!0), s(C, null, q(v.value.pinned, (e) => (o(), s("div", {
|
|
196
|
+
key: e.path,
|
|
197
|
+
class: "quick-item"
|
|
198
|
+
}, [
|
|
199
|
+
n("button", {
|
|
200
|
+
class: "quick-star active",
|
|
201
|
+
type: "button",
|
|
202
|
+
"aria-label": t(a)("biz.quickUnpin"),
|
|
203
|
+
onClick: F((f) => Q(e.path), ["stop"])
|
|
204
|
+
}, [
|
|
205
|
+
c(t(S), {
|
|
206
|
+
icon: "ph:star-fill",
|
|
207
|
+
width: 12
|
|
208
|
+
})
|
|
209
|
+
], 8, Et),
|
|
210
|
+
n("div", {
|
|
211
|
+
class: "quick-body",
|
|
212
|
+
onClick: (f) => t(g).push(e.path)
|
|
213
|
+
}, [
|
|
214
|
+
c(j, {
|
|
215
|
+
icon: e.icon,
|
|
216
|
+
size: 17
|
|
217
|
+
}, null, 8, ["icon"]),
|
|
218
|
+
n("span", At, l(t(G)(e.title)), 1)
|
|
219
|
+
], 8, Mt)
|
|
220
|
+
]))), 128))
|
|
221
|
+
])) : r("", !0),
|
|
222
|
+
v.value.suggested.length ? (o(), s("div", Bt, l(t(a)("biz.quickSuggested")), 1)) : r("", !0),
|
|
223
|
+
v.value.suggested.length ? (o(), s("div", Ut, [
|
|
224
|
+
(o(!0), s(C, null, q(v.value.suggested, (e) => (o(), s("div", {
|
|
225
|
+
key: e.path,
|
|
226
|
+
class: "quick-item suggested"
|
|
227
|
+
}, [
|
|
228
|
+
n("button", {
|
|
229
|
+
class: "quick-star",
|
|
230
|
+
type: "button",
|
|
231
|
+
"aria-label": t(a)("biz.quickPin"),
|
|
232
|
+
onClick: F((f) => U(e.path), ["stop"])
|
|
233
|
+
}, [
|
|
234
|
+
c(t(S), {
|
|
235
|
+
icon: "ph:star",
|
|
236
|
+
width: 12
|
|
237
|
+
})
|
|
238
|
+
], 8, Vt),
|
|
239
|
+
n("div", {
|
|
240
|
+
class: "quick-body",
|
|
241
|
+
onClick: (f) => t(g).push(e.path)
|
|
242
|
+
}, [
|
|
243
|
+
c(j, {
|
|
244
|
+
icon: e.icon,
|
|
245
|
+
size: 17
|
|
246
|
+
}, null, 8, ["icon"]),
|
|
247
|
+
n("span", Ft, l(t(G)(e.title)), 1)
|
|
248
|
+
], 8, Rt)
|
|
249
|
+
]))), 128))
|
|
250
|
+
])) : r("", !0)
|
|
251
|
+
])) : (o(), y(t(I), {
|
|
252
|
+
key: 1,
|
|
253
|
+
description: t(a)("biz.noMenus")
|
|
254
|
+
}, null, 8, ["description"]))
|
|
255
|
+
]),
|
|
256
|
+
_: 1
|
|
257
|
+
}, 8, ["title"])
|
|
258
|
+
]),
|
|
259
|
+
c(t(D), {
|
|
260
|
+
title: t(a)("biz.notices"),
|
|
86
261
|
bordered: !0
|
|
87
262
|
}, {
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
text: "",
|
|
91
|
-
type: "primary",
|
|
92
|
-
onClick: i[0] || (i[0] = (t) => e(f).push("/personal/notice"))
|
|
93
|
-
}, {
|
|
94
|
-
default: r(() => [
|
|
95
|
-
_(a(e(c)("biz.viewAll")), 1)
|
|
96
|
-
]),
|
|
97
|
-
_: 1
|
|
98
|
-
})
|
|
99
|
-
]),
|
|
100
|
-
default: r(() => [
|
|
101
|
-
h.value.length ? (o(), p(e(L), {
|
|
263
|
+
default: d(() => [
|
|
264
|
+
P.value.length ? (o(), y(t(it), {
|
|
102
265
|
key: 0,
|
|
103
266
|
"show-divider": !1
|
|
104
267
|
}, {
|
|
105
|
-
default:
|
|
106
|
-
(o(!0),
|
|
107
|
-
key:
|
|
268
|
+
default: d(() => [
|
|
269
|
+
(o(!0), s(C, null, q(P.value, (e) => (o(), y(t(st), {
|
|
270
|
+
key: e.id
|
|
108
271
|
}, {
|
|
109
|
-
default:
|
|
110
|
-
|
|
272
|
+
default: d(() => [
|
|
273
|
+
n("div", {
|
|
111
274
|
class: "notice-row",
|
|
112
|
-
onClick:
|
|
275
|
+
onClick: u[1] || (u[1] = (f) => t(g).push("/personal/notice"))
|
|
113
276
|
}, [
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
277
|
+
n("span", Gt, [
|
|
278
|
+
e.isRead ? r("", !0) : (o(), s("span", jt)),
|
|
279
|
+
R(" " + l(e.title), 1)
|
|
117
280
|
]),
|
|
118
|
-
|
|
281
|
+
n("span", Ht, l(t(E)(e.publishTime, { seconds: !1 })), 1)
|
|
119
282
|
])
|
|
120
283
|
]),
|
|
121
284
|
_: 2
|
|
122
285
|
}, 1024))), 128))
|
|
123
286
|
]),
|
|
124
287
|
_: 1
|
|
125
|
-
})) : (o(),
|
|
288
|
+
})) : (o(), y(t(I), {
|
|
289
|
+
key: 1,
|
|
290
|
+
description: t(a)("biz.noticesEmpty")
|
|
291
|
+
}, null, 8, ["description"]))
|
|
126
292
|
]),
|
|
127
293
|
_: 1
|
|
128
|
-
}, 8, ["title"])
|
|
294
|
+
}, 8, ["title"]),
|
|
295
|
+
c(ht, {
|
|
296
|
+
show: N.value,
|
|
297
|
+
"onUpdate:show": u[2] || (u[2] = (e) => N.value = e),
|
|
298
|
+
"exclude-paths": [...O.value, t(A).path],
|
|
299
|
+
onPick: U
|
|
300
|
+
}, null, 8, ["show", "exclude-paths"])
|
|
129
301
|
]);
|
|
130
302
|
};
|
|
131
303
|
}
|
|
132
304
|
});
|
|
133
305
|
export {
|
|
134
|
-
|
|
306
|
+
re as default
|
|
135
307
|
};
|
|
136
308
|
//# sourceMappingURL=biz2.vue.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"biz2.vue.js","sources":["../../../src/views/dashboard/biz.vue"],"sourcesContent":["<script setup lang=\"ts\">\n// 业务系统的工作台。每个应用一个首页组件——这里和 dashboard/workbench.vue 是两个独立页面,\n// 由各自应用的「工作台」菜单(component 字段)指向,切应用即换首页。\n// 全部真数据拼装:欢迎卡(user store)+ 快捷入口(当前应用菜单树的可见叶子)+ 我的通知(notice/mine)。\n// 应用要换成自己的业务统计,在自己的 views/ 下放同 key(dashboard/biz)的页面覆盖本页;别造写死的假数字。\nimport { computed, onMounted, ref } from 'vue'\nimport { NCard, NButton, NList, NListItem, NEmpty } from 'naive-ui'\nimport { Icon } from '@iconify/vue'\nimport { useI18n } from 'vue-i18n'\nimport { useRoute, useRouter } from 'vue-router'\nimport { useUserStore } from '#/stores/user'\nimport { useAuthStore } from '#/stores/auth'\nimport { useAppStore } from '#/stores/app'\nimport { btnGrad } from '#/theme/mix'\nimport { noticeApi } from '#/api'\nimport type { NoticeMineItem } from '#/types/api'\nimport type { MenuNode } from '#/types/menu'\nimport AppIcon from '#/components/AppIcon.vue'\nimport { fmtDateTime } from '#/utils/format'\n\nconst { t } = useI18n()\nconst user = useUserStore()\nconst auth = useAuthStore()\nconst app = useAppStore()\nconst route = useRoute()\nconst router = useRouter()\n\nconst avatarStyle = computed(() => ({ background: btnGrad(app.accent) }))\n\n/** 当前应用菜单树的可见叶子(带 path)= 快捷入口;排除本页自身。 */\nfunction leaves(tree: MenuNode[]): MenuNode[] {\n const out: MenuNode[] = []\n for (const n of tree) {\n if (!n.visible) continue\n if (n.children?.length) out.push(...leaves(n.children))\n else if (n.path) out.push(n)\n }\n return out\n}\nconst quick = computed(() => leaves(auth.menuTree).filter(n => n.path !== route.path))\n\nconst notices = ref<NoticeMineItem[]>([])\nonMounted(async () => {\n try {\n notices.value = (await noticeApi.mine({ page: 1, pageSize: 5 })).items\n } catch {\n // 首页不因一张卡挂了糊用户一脸红(同 workbench):通知取不到就空态,其余照常可用。\n }\n})\n</script>\n\n<template>\n <div class=\"view\">\n <!-- 欢迎横幅(与 workbench 同语法:btnGrad 头像 + 主副标题) -->\n <div class=\"banner\">\n <div class=\"avatar\" :style=\"avatarStyle\">\n <Icon icon=\"ph:user\" :width=\"26\" color=\"#fff\" />\n </div>\n <div>\n <div class=\"hi\">\n {{ t('biz.welcome', { name: user.userInfo?.name ?? user.userInfo?.account ?? '' }) }}\n </div>\n <div class=\"tip\">{{ t('biz.subtitle') }}</div>\n </div>\n </div>\n\n <n-card :title=\"t('biz.quick')\" :bordered=\"true\">\n <div v-if=\"quick.length\" class=\"quick\">\n <n-button v-for=\"m in quick\" :key=\"m.id\" secondary @click=\"router.push(m.path!)\">\n <template #icon><AppIcon :icon=\"m.icon || 'ph:squares-four'\" :size=\"16\" /></template>\n {{ m.title }}\n </n-button>\n </div>\n <n-empty v-else :description=\"t('biz.noMenus')\" />\n </n-card>\n\n <n-card :title=\"t('biz.notices')\" :bordered=\"true\">\n <template #header-extra>\n <n-button text type=\"primary\" @click=\"router.push('/personal/notice')\">\n {{ t('biz.viewAll') }}\n </n-button>\n </template>\n <n-list v-if=\"notices.length\" :show-divider=\"false\">\n <n-list-item v-for=\"n in notices\" :key=\"n.id\">\n <div class=\"notice-row\" @click=\"router.push('/personal/notice')\">\n <span class=\"notice-title\">\n <span v-if=\"!n.isRead\" class=\"dot\" />\n {{ n.title }}\n </span>\n <span class=\"notice-time\">{{ fmtDateTime(n.publishTime, { seconds: false }) }}</span>\n </div>\n </n-list-item>\n </n-list>\n <n-empty v-else />\n </n-card>\n </div>\n</template>\n\n<style scoped>\n.view {\n display: flex;\n flex-direction: column;\n gap: var(--gap-card);\n}\n.banner {\n display: flex;\n align-items: center;\n gap: 16px;\n padding: 24px;\n border-radius: var(--radius-lg);\n background: var(--color-primary-light);\n}\n.avatar {\n width: 52px;\n height: 52px;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n.hi {\n font-size: var(--font-size-lg);\n font-weight: 600;\n color: var(--color-text-primary);\n}\n.tip {\n color: var(--color-text-secondary);\n margin-top: 4px;\n}\n.quick {\n display: flex;\n flex-wrap: wrap;\n gap: 12px;\n}\n.notice-row {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n cursor: pointer;\n}\n.notice-title {\n display: flex;\n align-items: center;\n gap: 8px;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n color: var(--color-text-primary);\n}\n.dot {\n flex-shrink: 0;\n width: 6px;\n height: 6px;\n border-radius: 50%;\n background: var(--color-primary);\n}\n.notice-time {\n flex-shrink: 0;\n color: var(--color-text-secondary);\n font-size: 12px;\n}\n</style>\n"],"names":["t","useI18n","user","useUserStore","auth","useAuthStore","app","useAppStore","route","useRoute","router","useRouter","avatarStyle","computed","btnGrad","leaves","tree","out","_a","quick","n","notices","ref","onMounted","noticeApi","_openBlock","_createElementBlock","_hoisted_1","_createElementVNode","_hoisted_2","_createVNode","_unref","Icon","_hoisted_3","_toDisplayString","_hoisted_4","NCard","_hoisted_5","_Fragment","_renderList","m","_createBlock","NButton","AppIcon","NEmpty","_cache","$event","NList","NListItem","_hoisted_6","_hoisted_7","_hoisted_8"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"biz2.vue.js","sources":["../../../src/views/dashboard/biz.vue"],"sourcesContent":["<script setup lang=\"ts\">\n// 业务系统的工作台。每个应用一个首页组件——这里和 dashboard/workbench.vue 是两个独立页面,\n// 由各自应用的「工作台」菜单(component 字段)指向,切应用即换首页。\n// 全部真数据拼装:欢迎横幅(user store + sessions + last-login)+ 待办事项(工作台待办扩展点,\n// 内核默认空)+ 快捷方式(手动置顶 + 高频自动补位)+ 我的通知(notice/mine)。\n// 应用要换成自己的业务统计,在自己的 views/ 下放同 key(dashboard/biz)的页面覆盖本页;别造写死的假数字。\nimport { computed, onMounted, onUnmounted, ref } from 'vue'\nimport { NCard, NButton, NList, NListItem, NEmpty, NTag } from 'naive-ui'\nimport { Icon } from '@iconify/vue'\nimport { useI18n } from 'vue-i18n'\nimport { useRoute, useRouter } from 'vue-router'\nimport { useUserStore } from '#/stores/user'\nimport { useAppStore } from '#/stores/app'\nimport { btnGrad } from '#/theme/mix'\nimport { noticeApi, personalApi } from '#/api'\nimport type {\n NoticeMineItem,\n LastLoginInfo,\n WorkbenchTodoSummary,\n UserShortcutItem,\n} from '#/types/api'\nimport { useMenuFlat } from '#/composables/useMenuFlat'\nimport { translateMenuTitle } from '#/locales/menuTitle'\nimport { onlineDurationParts } from './onlineDuration'\nimport { buildShortcutGroups } from './shortcutGroups'\nimport ShortcutPicker from './ShortcutPicker.vue'\nimport AppIcon from '#/components/AppIcon.vue'\nimport { fmtDateTime } from '#/utils/format'\nimport { uaSummary } from '#/utils/ua'\n\nconst { t } = useI18n()\nconst user = useUserStore()\nconst app = useAppStore()\nconst route = useRoute()\nconst router = useRouter()\nconst leaves = useMenuFlat()\n\nconst avatarStyle = computed(() => ({ background: btnGrad(app.accent) }))\n\n// ── 在线时长 + 上次登录 ─────────────────────────────────────\nconst currentLoginTime = ref<string | null>(null)\nconst lastLogin = ref<LastLoginInfo | null>(null)\nconst now = ref(new Date())\nlet tickTimer: ReturnType<typeof setInterval> | undefined\n\nconst onlineText = computed(() => {\n if (!currentLoginTime.value) return ''\n const { hours, minutes } = onlineDurationParts(currentLoginTime.value, now.value)\n return hours > 0\n ? t('biz.onlineDuration', { hours, minutes })\n : t('biz.onlineDurationShort', { minutes })\n})\nconst lastLoginText = computed(() => {\n if (!lastLogin.value) return t('biz.firstLogin')\n const device = uaSummary(lastLogin.value.userAgent)\n const ip = lastLogin.value.ip ? ` · ${lastLogin.value.ip}` : ''\n const base = t('biz.lastLogin', { time: fmtDateTime(lastLogin.value.time, { seconds: false }) })\n return `${base}${ip}${device ? ` · ${device}` : ''}`\n})\n\n// ── 待办事项:内核默认空,消费方接入真实审批/工单系统后有内容 ──────────\nconst todo = ref<WorkbenchTodoSummary | null>(null)\n\n// ── 快捷方式 ─────────────────────────────────────────────\nconst shortcuts = ref<UserShortcutItem[]>([])\nconst pickerShow = ref(false)\n// 排除本页自身:工作台自己也是菜单树里的一条,不该出现在\"去哪儿\"的快捷方式里\nconst groups = computed(() =>\n buildShortcutGroups(\n shortcuts.value.filter(s => s.menuPath !== route.path),\n leaves.value,\n ),\n)\nconst pinnedPaths = computed(() => shortcuts.value.filter(s => s.pinned).map(s => s.menuPath))\n\nasync function loadShortcuts() {\n try {\n shortcuts.value = await personalApi.shortcuts()\n } catch {\n shortcuts.value = []\n }\n}\nasync function pin(path: string) {\n await personalApi.pinShortcut(path)\n await loadShortcuts()\n}\nasync function unpin(path: string) {\n await personalApi.unpinShortcut(path)\n await loadShortcuts()\n}\n\n// ── 通知 ────────────────────────────────────────────────\nconst notices = ref<NoticeMineItem[]>([])\n\nonMounted(async () => {\n tickTimer = setInterval(() => {\n now.value = new Date()\n }, 60_000)\n\n try {\n const sessions = await personalApi.sessions()\n currentLoginTime.value = sessions.find(s => s.isCurrent)?.loginTime ?? null\n } catch {\n // 在线时长拿不到就不显示这一段,不影响页面其余部分\n }\n try {\n lastLogin.value = await personalApi.lastLogin()\n } catch {\n lastLogin.value = null\n }\n try {\n todo.value = await personalApi.workbenchTodo()\n } catch {\n todo.value = null\n }\n await loadShortcuts()\n try {\n notices.value = (await noticeApi.mine({ page: 1, pageSize: 5 })).items\n } catch {\n // 首页不因一张卡挂了糊用户一脸红:通知取不到就空态,其余照常可用。\n }\n})\nonUnmounted(() => {\n if (tickTimer) clearInterval(tickTimer)\n})\n</script>\n\n<template>\n <div class=\"view\">\n <!-- 欢迎横幅:身份 + 在线状态,一行说完 -->\n <div class=\"banner\">\n <div class=\"avatar\" :style=\"avatarStyle\">\n <Icon icon=\"ph:user\" :width=\"26\" color=\"#fff\" />\n </div>\n <div class=\"banner-body\">\n <div class=\"hi\">\n {{ t('biz.welcome', { name: user.userInfo?.name ?? user.userInfo?.account ?? '' }) }}\n </div>\n <div class=\"tip\">{{ t('biz.subtitle') }}</div>\n <div v-if=\"onlineText || lastLoginText\" class=\"meta-row\">\n <span v-if=\"onlineText\">{{ onlineText }}</span>\n <span v-if=\"onlineText && lastLoginText\" class=\"meta-dot\" />\n <span>{{ lastLoginText }}</span>\n </div>\n </div>\n </div>\n\n <div class=\"row\">\n <!-- 待办事项:内核默认空,消费方接入真实审批/工单系统后有内容 -->\n <n-card :title=\"t('biz.todo')\" :bordered=\"true\">\n <template v-if=\"todo && todo.totalCount > 0\" #header-extra>\n <n-tag type=\"error\" round size=\"small\">{{ todo.totalCount }}</n-tag>\n </template>\n <div v-if=\"todo && todo.items.length\" class=\"todo-list\">\n <div\n v-for=\"i in todo.items\"\n :key=\"i.id\"\n class=\"todo-row\"\n @click=\"i.url && router.push(i.url)\"\n >\n <div class=\"todo-main\">\n <div class=\"todo-title\">{{ i.title }}</div>\n <div v-if=\"i.description\" class=\"todo-sub\">{{ i.description }}</div>\n </div>\n <span class=\"todo-time\">{{ fmtDateTime(i.createTime, { seconds: false }) }}</span>\n </div>\n </div>\n <n-empty v-else :description=\"t('biz.todoEmpty')\" />\n </n-card>\n\n <!-- 快捷方式:实心星=手动置顶(可移除),虚线框+空心星=高频访问自动推荐(点固定即置顶) -->\n <n-card :title=\"t('biz.quick')\" :bordered=\"true\">\n <template #header-extra>\n <n-button size=\"small\" quaternary circle @click=\"pickerShow = true\">\n <template #icon><Icon icon=\"ph:plus\" :width=\"16\" /></template>\n </n-button>\n </template>\n <div v-if=\"groups.pinned.length || groups.suggested.length\">\n <div v-if=\"groups.pinned.length\" class=\"quick-group-label\">\n {{ t('biz.quickPinned') }}\n </div>\n <div v-if=\"groups.pinned.length\" class=\"quick-grid\">\n <div v-for=\"s in groups.pinned\" :key=\"s.path\" class=\"quick-item\">\n <button\n class=\"quick-star active\"\n type=\"button\"\n :aria-label=\"t('biz.quickUnpin')\"\n @click.stop=\"unpin(s.path)\"\n >\n <Icon icon=\"ph:star-fill\" :width=\"12\" />\n </button>\n <div class=\"quick-body\" @click=\"router.push(s.path)\">\n <AppIcon :icon=\"s.icon\" :size=\"17\" />\n <span class=\"quick-name\">{{ translateMenuTitle(s.title) }}</span>\n </div>\n </div>\n </div>\n <div v-if=\"groups.suggested.length\" class=\"quick-group-label\">\n {{ t('biz.quickSuggested') }}\n </div>\n <div v-if=\"groups.suggested.length\" class=\"quick-grid\">\n <div v-for=\"s in groups.suggested\" :key=\"s.path\" class=\"quick-item suggested\">\n <button\n class=\"quick-star\"\n type=\"button\"\n :aria-label=\"t('biz.quickPin')\"\n @click.stop=\"pin(s.path)\"\n >\n <Icon icon=\"ph:star\" :width=\"12\" />\n </button>\n <div class=\"quick-body\" @click=\"router.push(s.path)\">\n <AppIcon :icon=\"s.icon\" :size=\"17\" />\n <span class=\"quick-name\">{{ translateMenuTitle(s.title) }}</span>\n </div>\n </div>\n </div>\n </div>\n <n-empty v-else :description=\"t('biz.noMenus')\" />\n </n-card>\n </div>\n\n <!-- 通知:没有\"查看全部\"——卡片本身就是完整内容 -->\n <n-card :title=\"t('biz.notices')\" :bordered=\"true\">\n <n-list v-if=\"notices.length\" :show-divider=\"false\">\n <n-list-item v-for=\"n in notices\" :key=\"n.id\">\n <div class=\"notice-row\" @click=\"router.push('/personal/notice')\">\n <span class=\"notice-title\">\n <span v-if=\"!n.isRead\" class=\"dot\" />\n {{ n.title }}\n </span>\n <span class=\"notice-time\">{{ fmtDateTime(n.publishTime, { seconds: false }) }}</span>\n </div>\n </n-list-item>\n </n-list>\n <n-empty v-else :description=\"t('biz.noticesEmpty')\" />\n </n-card>\n\n <ShortcutPicker\n v-model:show=\"pickerShow\"\n :exclude-paths=\"[...pinnedPaths, route.path]\"\n @pick=\"pin\"\n />\n </div>\n</template>\n\n<style scoped>\n.view {\n display: flex;\n flex-direction: column;\n gap: var(--gap-card);\n}\n.banner {\n display: flex;\n align-items: center;\n gap: 16px;\n padding: 24px;\n border-radius: var(--radius-lg);\n background: var(--color-primary-light);\n}\n.avatar {\n flex-shrink: 0;\n width: 52px;\n height: 52px;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n.banner-body {\n min-width: 0;\n}\n.hi {\n font-size: var(--font-size-lg);\n font-weight: 600;\n color: var(--color-text-primary);\n}\n.tip {\n color: var(--color-text-secondary);\n margin-top: 4px;\n}\n.meta-row {\n margin-top: 8px;\n display: flex;\n align-items: center;\n gap: 10px;\n font-size: 13px;\n color: var(--color-text-tertiary);\n font-variant-numeric: tabular-nums;\n}\n.meta-dot {\n width: 3px;\n height: 3px;\n border-radius: 50%;\n background: var(--color-text-disabled);\n flex-shrink: 0;\n}\n.row {\n display: grid;\n grid-template-columns: 1.35fr 1fr;\n gap: var(--gap-card);\n align-items: start;\n}\n@media (max-width: 760px) {\n .row {\n grid-template-columns: 1fr;\n }\n}\n.todo-list {\n display: flex;\n flex-direction: column;\n}\n.todo-row {\n display: flex;\n align-items: flex-start;\n justify-content: space-between;\n gap: 12px;\n padding: 10px 0;\n border-bottom: 1px solid var(--color-border);\n cursor: pointer;\n}\n.todo-row:last-child {\n border-bottom: none;\n}\n.todo-title {\n color: var(--color-text-primary);\n font-weight: 500;\n}\n.todo-sub {\n margin-top: 2px;\n font-size: 12px;\n color: var(--color-text-tertiary);\n}\n.todo-time {\n flex-shrink: 0;\n font-size: 12px;\n color: var(--color-text-tertiary);\n}\n.quick-group-label {\n font-size: 12px;\n color: var(--color-text-tertiary);\n margin: 4px 0 8px;\n}\n.quick-grid {\n display: flex;\n flex-wrap: wrap;\n gap: 10px;\n margin-bottom: 4px;\n}\n.quick-item {\n position: relative;\n border: 1px solid var(--color-border);\n border-radius: var(--radius-md);\n}\n.quick-item.suggested {\n border-style: dashed;\n}\n.quick-body {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 14px 8px 10px;\n cursor: pointer;\n}\n.quick-name {\n font-size: 13px;\n color: var(--color-text-secondary);\n}\n.quick-star {\n position: absolute;\n top: -6px;\n right: -6px;\n width: 18px;\n height: 18px;\n border-radius: 50%;\n border: 1px solid var(--color-border);\n background: var(--color-bg-elevated);\n color: var(--color-text-disabled);\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n}\n.quick-star.active {\n color: var(--color-warning);\n}\n.notice-row {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n cursor: pointer;\n}\n.notice-title {\n display: flex;\n align-items: center;\n gap: 8px;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n color: var(--color-text-primary);\n}\n.dot {\n flex-shrink: 0;\n width: 6px;\n height: 6px;\n border-radius: 50%;\n background: var(--color-primary);\n}\n.notice-time {\n flex-shrink: 0;\n color: var(--color-text-secondary);\n font-size: 12px;\n}\n</style>\n"],"names":["t","useI18n","user","useUserStore","app","useAppStore","route","useRoute","router","useRouter","leaves","useMenuFlat","avatarStyle","computed","btnGrad","currentLoginTime","ref","lastLogin","now","tickTimer","onlineText","hours","minutes","onlineDurationParts","lastLoginText","device","uaSummary","ip","fmtDateTime","todo","shortcuts","pickerShow","groups","buildShortcutGroups","s","pinnedPaths","loadShortcuts","personalApi","pin","path","unpin","notices","onMounted","sessions","_a","noticeApi","onUnmounted","_openBlock","_createElementBlock","_hoisted_1","_createElementVNode","_hoisted_2","_createVNode","_unref","Icon","_hoisted_3","_hoisted_4","_toDisplayString","_hoisted_5","_hoisted_6","_hoisted_8","_hoisted_9","NCard","_hoisted_10","_Fragment","_renderList","i","$event","_hoisted_12","_hoisted_13","_hoisted_14","_hoisted_15","_createBlock","NEmpty","NTag","_createTextVNode","NButton","_hoisted_16","_hoisted_17","_hoisted_18","_withModifiers","AppIcon","_hoisted_21","_hoisted_22","_hoisted_23","_hoisted_26","NList","n","NListItem","_cache","_hoisted_27","_hoisted_28","_hoisted_29","ShortcutPicker"],"mappings":"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"}
|