@axewo/fin-micro 1.0.0 → 2.0.1

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.
Files changed (103) hide show
  1. package/README.md +181 -4
  2. package/cli/index.mjs +22 -6
  3. package/dist/browser.cjs +1 -1
  4. package/dist/browser.mjs +68 -66
  5. package/dist/core.cjs +1 -1
  6. package/dist/core.mjs +459 -441
  7. package/dist/index.cjs +1 -1
  8. package/dist/index.mjs +31 -24
  9. package/dist/layout.cjs +1 -0
  10. package/dist/layout.css +1 -0
  11. package/dist/layout.mjs +719 -0
  12. package/dist/{router-view-impl-C1KG6mxu.mjs → router-view-impl-B1NzCGKV.mjs} +18 -18
  13. package/dist/router-view-impl-BvOToV_Z.cjs +1 -0
  14. package/dist/runtime.cjs +1 -1
  15. package/dist/runtime.mjs +40 -39
  16. package/dist/sdk.cjs +1 -1
  17. package/dist/sdk.mjs +92 -56
  18. package/dist/types/browser/index.d.ts +4 -0
  19. package/dist/types/core/index.d.ts +1 -1
  20. package/dist/types/index.d.ts +2 -0
  21. package/dist/types/layout/HostShell.vue.d.ts +528 -0
  22. package/dist/types/layout/ShellHeader.vue.d.ts +46 -0
  23. package/dist/types/layout/ShellMenu.vue.d.ts +12 -0
  24. package/dist/types/layout/ShellTabs.vue.d.ts +23 -0
  25. package/dist/types/layout/StandaloneMenuItem.vue.d.ts +11 -0
  26. package/dist/types/layout/StandaloneShell.vue.d.ts +40 -0
  27. package/dist/types/layout/index.d.ts +5 -0
  28. package/dist/types/layout/types.d.ts +65 -0
  29. package/dist/types/runtime/lifecycle.d.ts +1 -1
  30. package/dist/types/sdk/index.d.ts +65 -4
  31. package/dist/types/vue/index.d.ts +13 -2
  32. package/dist/types/vue/router-view-impl.d.ts +1 -1
  33. package/dist/types/watermark/FinWatermark.vue.d.ts +16 -0
  34. package/dist/types/watermark/config.d.ts +36 -0
  35. package/dist/types/watermark/index.d.ts +4 -0
  36. package/dist/vue.cjs +1 -1
  37. package/dist/vue.mjs +49 -35
  38. package/dist/watermark.cjs +2 -0
  39. package/dist/watermark.mjs +119 -0
  40. package/package.json +29 -4
  41. package/scaffold/base/index.html +2 -1
  42. package/scaffold/base/package.json.template +5 -1
  43. package/scaffold/base/pnpm-workspace.yaml +6 -0
  44. package/scaffold/base/scripts/check-runtime.mjs +43 -0
  45. package/scaffold/base/src/locales/en.ts +12 -0
  46. package/scaffold/base/src/locales/index.ts +7 -1
  47. package/scaffold/base/src/locales/zh-CN.ts +12 -0
  48. package/scaffold/base/src/main.ts +13 -5
  49. package/scaffold/base/src/router/demo.ts +6 -0
  50. package/scaffold/base/src/router/index.ts +13 -0
  51. package/scaffold/base/src/stores/demo.ts +12 -0
  52. package/scaffold/base/src/stores/index.ts +11 -0
  53. package/scaffold/base/src/utils/appConfig.ts +49 -0
  54. package/scaffold/base/src/utils/errorUtils.ts +109 -0
  55. package/scaffold/base/src/utils/requestUtils.ts +32 -11
  56. package/scaffold/base/src/utils/watermarkConfig.ts +18 -0
  57. package/scaffold/base/src/views/demo/index.vue +26 -0
  58. package/scaffold/host/.env.example +11 -3
  59. package/scaffold/host/src/App.vue +1 -13
  60. package/scaffold/host/src/bootstrap.ts +40 -8
  61. package/scaffold/host/src/hooks/usePlatformSession.ts +40 -8
  62. package/scaffold/host/src/layout/HostHeader.vue +65 -5
  63. package/scaffold/host/src/layout/HostLayout.vue +65 -21
  64. package/scaffold/host/src/layout/HostMenu.vue +11 -2
  65. package/scaffold/host/src/layout/HostTabs.vue +91 -8
  66. package/scaffold/host/src/layout/HostWorkspace.vue +29 -7
  67. package/scaffold/host/src/localPages.ts +45 -0
  68. package/scaffold/host/src/platform.ts +51 -14
  69. package/scaffold/host/src/router/guards.ts +128 -0
  70. package/scaffold/host/src/router/index.ts +25 -0
  71. package/scaffold/host/src/router/targets.ts +30 -0
  72. package/scaffold/host/src/router/workspace.ts +63 -0
  73. package/scaffold/host/src/styles/shell.css +776 -0
  74. package/scaffold/host/src/utils/request.ts +30 -3
  75. package/scaffold/host/src/views/home/index.vue +19 -0
  76. package/scaffold/host/src/views/login/components/LoginForm.vue +83 -0
  77. package/scaffold/host/src/views/login/index.vue +16 -0
  78. package/scaffold/host/src/views/not-found/index.vue +1 -0
  79. package/scaffold/host/src/views/profile/index.vue +24 -0
  80. package/scaffold/host/src/views/workspace/index.vue +11 -0
  81. package/scaffold/layouts/standard/host/src/layout/HostLayout.vue +116 -0
  82. package/scaffold/layouts/standard/host/src/styles/shell.css +168 -0
  83. package/scaffold/layouts/standard/vue/src/layout/StandaloneLayout.vue +26 -0
  84. package/scaffold/vue/src/App.vue +13 -7
  85. package/scaffold/vue/src/bootstrap.ts +25 -24
  86. package/scaffold/vue/src/bridge/auth.ts +23 -0
  87. package/scaffold/vue/src/bridge/session.ts +2 -2
  88. package/scaffold/vue/src/layout/Header.vue +15 -0
  89. package/scaffold/vue/src/layout/Sidebar.vue +21 -0
  90. package/scaffold/vue/src/layout/SidebarItem.vue +21 -0
  91. package/scaffold/vue/src/layout/StandaloneLayout.vue +34 -0
  92. package/scaffold/vue/src/main.ts +5 -2
  93. package/scaffold/vue/src/router/index.ts +9 -4
  94. package/scaffold/vue/src/router/menu.ts +38 -0
  95. package/scaffold/vue/src/views/demo/configs/table.ts +24 -0
  96. package/scaffold/vue/src/views/demo/hooks/useRecordNavigation.ts +32 -0
  97. package/scaffold/vue/src/views/demo/index.vue +17 -0
  98. package/scaffold/vue/src/views/{DetailView.vue → demo/modules/detail/index.vue} +15 -6
  99. package/scaffold/vue/src/views/demo/types.ts +5 -0
  100. package/dist/router-view-impl-CgLEalx4.cjs +0 -1
  101. package/scaffold/host/src/views/LoginView.vue +0 -38
  102. package/scaffold/vue/src/views/ListView.vue +0 -51
  103. /package/scaffold/vue/src/views/{NotFoundView.vue → not-found/index.vue} +0 -0
@@ -0,0 +1,719 @@
1
+ import { defineComponent as V, ref as K, computed as H, watch as J, openBlock as r, createElementBlock as b, Fragment as E, createCommentVNode as I, createElementVNode as l, withKeys as U, renderSlot as P, toDisplayString as k, createVNode as y, unref as g, withCtx as $, createBlock as N, resolveDynamicComponent as A, withDirectives as Z, withModifiers as _, vModelText as oe, renderList as R, createTextVNode as Y, resolveComponent as x, onMounted as ae, onBeforeUnmount as se, normalizeClass as j, normalizeStyle as ie, nextTick as q, normalizeProps as W, guardReactiveProps as D, createSlots as re, vShow as de } from "vue";
2
+ import { ElIcon as T, ElSubMenu as ee, ElMenuItem as ne, ElMenu as te } from "element-plus";
3
+ import { Expand as ue, Fold as pe, Search as ve, Bell as ce, ArrowDown as fe, User as le, SwitchButton as me, Tickets as be, Setting as ge, Menu as he, List as ye, HomeFilled as ke, Folder as G, Document as Q, ArrowLeft as $e, ArrowRight as Ce } from "@element-plus/icons-vue";
4
+ const Ie = ["inert"], we = { class: "brand" }, Se = {
5
+ class: "brand-icon",
6
+ "aria-hidden": "true"
7
+ }, Me = ["aria-label", "aria-expanded"], Ne = { class: "shell-breadcrumb" }, Oe = { class: "menu-search" }, Be = {
8
+ key: 0,
9
+ class: "shell-popover search-results"
10
+ }, Pe = ["onClick"], Ke = {
11
+ key: 0,
12
+ class: "popover-empty"
13
+ }, Le = { class: "topbar-action" }, Te = ["aria-expanded"], Fe = {
14
+ key: 0,
15
+ class: "shell-popover message-popover"
16
+ }, Ee = { class: "topbar-action" }, ze = ["aria-expanded"], Re = { class: "avatar" }, He = {
17
+ key: 0,
18
+ class: "shell-popover user-popover"
19
+ }, Ve = ["disabled"], We = ["disabled"], De = /* @__PURE__ */ V({
20
+ __name: "ShellHeader",
21
+ props: {
22
+ userName: {},
23
+ activeTitle: {},
24
+ pending: { type: Boolean },
25
+ collapsed: { type: Boolean },
26
+ apps: {},
27
+ brand: {}
28
+ },
29
+ emits: ["logout", "profile", "update:collapsed", "open", "popover-opened"],
30
+ setup(z, { expose: L, emit: O }) {
31
+ const a = z, p = O, d = K(""), u = K(null), v = H(() => {
32
+ const i = (s, w, f) => w.flatMap((S) => {
33
+ const F = `${f} / ${S.name}`;
34
+ return [...S.target ? [{ appId: s, menu: S, path: F }] : [], ...i(s, S.children ?? [], F)];
35
+ });
36
+ return a.apps.flatMap((s) => i(s.appId, s.menus ?? [], s.name));
37
+ }), m = H(() => v.value.filter((i) => i.path.toLowerCase().includes(d.value.trim().toLowerCase())));
38
+ function C() {
39
+ u.value = null;
40
+ }
41
+ function c(i) {
42
+ a.pending || (u.value = u.value === i && i !== "search" ? null : i, u.value && p("popover-opened"));
43
+ }
44
+ function B(i) {
45
+ a.pending || (C(), d.value = "", p("open", i.appId, i.menu));
46
+ }
47
+ return J(() => a.pending, (i) => {
48
+ i && C();
49
+ }), L({ closePopovers: C }), (i, s) => {
50
+ var w;
51
+ return r(), b(E, null, [
52
+ u.value ? (r(), b("button", {
53
+ key: 0,
54
+ class: "popover-backdrop",
55
+ "aria-label": "关闭弹出菜单",
56
+ tabindex: "-1",
57
+ onClick: C
58
+ })) : I("", !0),
59
+ l("header", {
60
+ class: "shell-topbar",
61
+ inert: i.pending || void 0,
62
+ onKeydown: U(C, ["esc"])
63
+ }, [
64
+ l("div", we, [
65
+ P(i.$slots, "brand", {
66
+ brand: i.brand ?? {}
67
+ }, () => {
68
+ var f, S;
69
+ return [
70
+ l("span", Se, k(((f = i.brand) == null ? void 0 : f.mark) ?? "F"), 1),
71
+ l("strong", null, k(((S = i.brand) == null ? void 0 : S.title) ?? "FIN"), 1)
72
+ ];
73
+ })
74
+ ]),
75
+ l("button", {
76
+ class: "icon-button collapse-toggle",
77
+ "aria-label": i.collapsed ? "展开侧栏" : "折叠侧栏",
78
+ "aria-expanded": !i.collapsed,
79
+ onClick: s[0] || (s[0] = (f) => !i.pending && p("update:collapsed", !i.collapsed))
80
+ }, [
81
+ y(g(T), { "aria-hidden": "true" }, {
82
+ default: $(() => [
83
+ (r(), N(A(i.collapsed ? g(ue) : g(pe))))
84
+ ]),
85
+ _: 1
86
+ })
87
+ ], 8, Me),
88
+ l("div", Ne, [
89
+ l("span", null, k(((w = i.brand) == null ? void 0 : w.workspaceTitle) ?? "工作空间"), 1),
90
+ s[8] || (s[8] = l("span", null, "/", -1)),
91
+ l("strong", null, k(a.activeTitle), 1)
92
+ ]),
93
+ s[13] || (s[13] = l("div", { class: "topbar-spacer" }, null, -1)),
94
+ l("div", Oe, [
95
+ y(g(T), { "aria-hidden": "true" }, {
96
+ default: $(() => [
97
+ y(g(ve))
98
+ ]),
99
+ _: 1
100
+ }),
101
+ Z(l("input", {
102
+ "onUpdate:modelValue": s[1] || (s[1] = (f) => d.value = f),
103
+ "aria-label": "搜索菜单",
104
+ placeholder: "搜索菜单、应用…",
105
+ onFocus: s[2] || (s[2] = (f) => c("search")),
106
+ onKeydown: s[3] || (s[3] = U(_((f) => !f.isComposing && m.value[0] && B(m.value[0]), ["prevent"]), ["enter"]))
107
+ }, null, 544), [
108
+ [oe, d.value]
109
+ ]),
110
+ u.value === "search" ? (r(), b("div", Be, [
111
+ s[9] || (s[9] = l("p", { class: "popover-label" }, "菜单搜索", -1)),
112
+ (r(!0), b(E, null, R(m.value, (f) => (r(), b("button", {
113
+ key: JSON.stringify([f.appId, f.menu.menuId]),
114
+ onClick: (S) => B(f)
115
+ }, [
116
+ l("strong", null, k(f.menu.name), 1),
117
+ l("small", null, k(f.path), 1)
118
+ ], 8, Pe))), 128)),
119
+ m.value.length ? I("", !0) : (r(), b("p", Ke, "未找到匹配的菜单"))
120
+ ])) : I("", !0)
121
+ ]),
122
+ P(i.$slots, "header-actions"),
123
+ l("div", Le, [
124
+ l("button", {
125
+ class: "icon-button",
126
+ "aria-label": "消息通知",
127
+ "aria-expanded": u.value === "messages",
128
+ onClick: s[4] || (s[4] = (f) => c("messages"))
129
+ }, [
130
+ y(g(T), { "aria-hidden": "true" }, {
131
+ default: $(() => [
132
+ y(g(ce))
133
+ ]),
134
+ _: 1
135
+ })
136
+ ], 8, Te),
137
+ u.value === "messages" ? (r(), b("div", Fe, s[10] || (s[10] = [
138
+ l("h3", null, "消息通知", -1),
139
+ l("div", { class: "empty-state" }, [
140
+ l("strong", null, "尚未接入消息服务"),
141
+ l("p", null, "接入后将在这里显示真实的通知消息。")
142
+ ], -1)
143
+ ]))) : I("", !0)
144
+ ]),
145
+ l("div", Ee, [
146
+ l("button", {
147
+ class: "user-trigger",
148
+ "aria-expanded": u.value === "user",
149
+ onClick: s[5] || (s[5] = (f) => c("user"))
150
+ }, [
151
+ l("span", Re, k(i.userName.slice(0, 1)), 1),
152
+ l("span", null, k(i.userName), 1),
153
+ y(g(T), { "aria-hidden": "true" }, {
154
+ default: $(() => [
155
+ y(g(fe))
156
+ ]),
157
+ _: 1
158
+ })
159
+ ], 8, ze),
160
+ u.value === "user" ? (r(), b("div", He, [
161
+ l("strong", null, k(i.userName), 1),
162
+ s[12] || (s[12] = l("hr", null, null, -1)),
163
+ l("button", {
164
+ disabled: i.pending,
165
+ onClick: s[6] || (s[6] = (f) => {
166
+ C(), !i.pending && p("profile");
167
+ })
168
+ }, [
169
+ y(g(T), { "aria-hidden": "true" }, {
170
+ default: $(() => [
171
+ y(g(le))
172
+ ]),
173
+ _: 1
174
+ }),
175
+ s[11] || (s[11] = Y("个人中心"))
176
+ ], 8, Ve),
177
+ l("button", {
178
+ disabled: i.pending,
179
+ onClick: s[7] || (s[7] = (f) => !i.pending && p("logout"))
180
+ }, [
181
+ y(g(T), { "aria-hidden": "true" }, {
182
+ default: $(() => [
183
+ y(g(me))
184
+ ]),
185
+ _: 1
186
+ }),
187
+ Y(k(i.pending ? "正在确认退出…" : "退出登录"), 1)
188
+ ], 8, We)
189
+ ])) : I("", !0)
190
+ ])
191
+ ], 40, Ie)
192
+ ], 64);
193
+ };
194
+ }
195
+ }), Je = /* @__PURE__ */ V({
196
+ __name: "ShellMenu",
197
+ props: {
198
+ appId: {},
199
+ menus: {}
200
+ },
201
+ emits: ["open"],
202
+ setup(z, { emit: L }) {
203
+ const O = L, a = new Map(Object.entries({ Document: Q, Folder: G, HomeFilled: ke, List: ye, Menu: he, Setting: ge, Tickets: be, User: le })), p = (d) => {
204
+ var u;
205
+ return a.get(d.icon ?? "") ?? ((u = d.children) != null && u.length ? G : Q);
206
+ };
207
+ return (d, u) => {
208
+ const v = x("ShellMenu", !0);
209
+ return r(!0), b(E, null, R(d.menus, (m) => {
210
+ var C;
211
+ return r(), b(E, {
212
+ key: JSON.stringify([d.appId, m.menuId])
213
+ }, [
214
+ (C = m.children) != null && C.length ? (r(), N(g(ee), {
215
+ key: 0,
216
+ index: JSON.stringify([d.appId, m.menuId])
217
+ }, {
218
+ title: $(() => [
219
+ y(g(T), { "aria-hidden": "true" }, {
220
+ default: $(() => [
221
+ (r(), N(A(p(m))))
222
+ ]),
223
+ _: 2
224
+ }, 1024),
225
+ l("span", null, k(m.name), 1)
226
+ ]),
227
+ default: $(() => [
228
+ y(v, {
229
+ "app-id": d.appId,
230
+ menus: m.children,
231
+ onOpen: u[0] || (u[0] = (c, B) => O("open", c, B))
232
+ }, null, 8, ["app-id", "menus"])
233
+ ]),
234
+ _: 2
235
+ }, 1032, ["index"])) : m.target ? (r(), N(g(ne), {
236
+ key: 1,
237
+ index: JSON.stringify([d.appId, m.menuId]),
238
+ onClick: (c) => O("open", d.appId, m)
239
+ }, {
240
+ default: $(() => [
241
+ y(g(T), { "aria-hidden": "true" }, {
242
+ default: $(() => [
243
+ (r(), N(A(p(m))))
244
+ ]),
245
+ _: 2
246
+ }, 1024),
247
+ l("span", null, k(m.name), 1)
248
+ ]),
249
+ _: 2
250
+ }, 1032, ["index", "onClick"])) : I("", !0)
251
+ ], 64);
252
+ }), 128);
253
+ };
254
+ }
255
+ }), Ae = ["inert"], Ue = ["disabled"], je = ["onContextmenu"], qe = ["aria-selected", "title", "onClick"], Xe = ["aria-label", "onClick"], Ye = ["disabled"], Ge = ["aria-expanded", "disabled"], Qe = { class: "popover-label" }, Ze = ["disabled"], _e = ["disabled"], xe = /* @__PURE__ */ V({
256
+ __name: "ShellTabs",
257
+ props: {
258
+ tabs: {},
259
+ activeKey: {},
260
+ pending: { type: Boolean },
261
+ isFixedTab: { type: Function }
262
+ },
263
+ emits: ["operate", "popover-opened", "error"],
264
+ setup(z, { expose: L, emit: O }) {
265
+ const a = z, p = (e) => {
266
+ var n;
267
+ return ((n = a.isFixedTab) == null ? void 0 : n.call(a, e)) ?? !1;
268
+ }, d = O, u = K(), v = K(null);
269
+ function m() {
270
+ v.value = null;
271
+ }
272
+ function C(e, n) {
273
+ a.pending || (v.value = { tab: e, ...n ? { x: Math.max(8, Math.min(n.clientX, window.innerWidth - 184)), y: Math.max(8, Math.min(n.clientY, window.innerHeight - 264)) } : {} }, d("popover-opened"));
274
+ }
275
+ function c(e) {
276
+ var h;
277
+ const n = (h = v.value) == null ? void 0 : h.tab;
278
+ if (m(), !n || a.pending || p(n) && (e === "close" || e === "refresh")) return;
279
+ const o = { tabId: n.tabId, key: n.key };
280
+ d("operate", e === "refresh" || e === "close" ? { type: e, target: o } : { type: "closeMany", scope: e, anchor: o });
281
+ }
282
+ const B = K(!1), i = K(!1), s = K(!1);
283
+ let w, f = !1;
284
+ function S() {
285
+ const e = u.value;
286
+ !e || f || (B.value = e.scrollWidth > e.clientWidth + (B.value ? 64 : 0) + 1, i.value = e.scrollLeft > 1, s.value = e.scrollLeft + e.clientWidth < e.scrollWidth - 1);
287
+ }
288
+ function F() {
289
+ var X;
290
+ const e = u.value, n = (X = e == null ? void 0 : e.querySelector('[aria-selected="true"]')) == null ? void 0 : X.parentElement;
291
+ if (!e || !n || f) return;
292
+ const o = e.getBoundingClientRect(), h = n.getBoundingClientRect();
293
+ h.left < o.left ? e.scrollLeft += h.left - o.left : h.right > o.right && (e.scrollLeft += Math.min(h.right - o.right, h.left - o.left)), S();
294
+ }
295
+ function M(e) {
296
+ var n;
297
+ a.pending || (n = u.value) == null || n.scrollBy({ left: e * Math.max(80, u.value.clientWidth * 0.8), behavior: "smooth" });
298
+ }
299
+ function t() {
300
+ q().then(() => {
301
+ if (!f)
302
+ return S(), q().then(F);
303
+ }).catch((e) => d("error", e));
304
+ }
305
+ return ae(() => {
306
+ typeof ResizeObserver < "u" && (w = new ResizeObserver(t), u.value && w.observe(u.value)), typeof window < "u" && window.addEventListener("resize", t), t();
307
+ }), se(() => {
308
+ f = !0, w == null || w.disconnect(), typeof window < "u" && window.removeEventListener("resize", t);
309
+ }), J(() => [a.activeKey, ...a.tabs.map((e) => `${e.key}:${e.title}`)], t), J(() => a.pending, (e) => {
310
+ e && m();
311
+ }), L({ closePopovers: m }), (e, n) => (r(), b("div", {
312
+ class: "shell-tabbar",
313
+ inert: e.pending || void 0,
314
+ onKeydown: U(m, ["esc"])
315
+ }, [
316
+ v.value ? (r(), b("button", {
317
+ key: 0,
318
+ class: "popover-backdrop",
319
+ "aria-label": "关闭页签菜单",
320
+ tabindex: "-1",
321
+ onClick: m
322
+ })) : I("", !0),
323
+ B.value ? (r(), b("button", {
324
+ key: 1,
325
+ class: "tab-scroll",
326
+ "aria-label": "向左查看页签",
327
+ title: "向左查看页签",
328
+ disabled: e.pending || !i.value,
329
+ onClick: n[0] || (n[0] = (o) => M(-1))
330
+ }, [
331
+ y(g($e), { "aria-hidden": "true" })
332
+ ], 8, Ue)) : I("", !0),
333
+ l("div", {
334
+ ref_key: "strip",
335
+ ref: u,
336
+ class: "tab-strip",
337
+ role: "tablist",
338
+ "aria-label": "已打开页面",
339
+ onScroll: S
340
+ }, [
341
+ (r(!0), b(E, null, R(e.tabs, (o) => (r(), b("div", {
342
+ key: o.key,
343
+ class: j(["shell-tab", { active: o.key === e.activeKey }]),
344
+ onContextmenu: _((h) => C(o, h), ["prevent"])
345
+ }, [
346
+ l("button", {
347
+ role: "tab",
348
+ "aria-selected": o.key === e.activeKey,
349
+ title: o.title,
350
+ onClick: (h) => !e.pending && d("operate", { type: "activate", target: { tabId: o.tabId, key: o.key } })
351
+ }, k(o.title), 9, qe),
352
+ p(o) ? I("", !0) : (r(), b("button", {
353
+ key: 0,
354
+ class: "tab-close",
355
+ "aria-label": `关闭 ${o.title}`,
356
+ onClick: (h) => !e.pending && d("operate", { type: "close", target: { tabId: o.tabId, key: o.key } })
357
+ }, "×", 8, Xe))
358
+ ], 42, je))), 128))
359
+ ], 544),
360
+ B.value ? (r(), b("button", {
361
+ key: 2,
362
+ class: "tab-scroll",
363
+ "aria-label": "向右查看页签",
364
+ title: "向右查看页签",
365
+ disabled: e.pending || !s.value,
366
+ onClick: n[1] || (n[1] = (o) => M(1))
367
+ }, [
368
+ y(g(Ce), { "aria-hidden": "true" })
369
+ ], 8, Ye)) : I("", !0),
370
+ l("button", {
371
+ class: "tab-more",
372
+ "aria-label": "更多页签操作",
373
+ "aria-expanded": !!v.value,
374
+ disabled: !e.tabs.length || e.pending,
375
+ onClick: n[2] || (n[2] = (o) => e.tabs.find((h) => h.key === e.activeKey) && C(e.tabs.find((h) => h.key === e.activeKey)))
376
+ }, "···", 8, Ge),
377
+ v.value ? (r(), b("div", {
378
+ key: 3,
379
+ class: j(["shell-popover tab-actions", { "context-actions": v.value.x !== void 0 }]),
380
+ style: ie(v.value.x !== void 0 ? { left: `${v.value.x}px`, top: `${v.value.y}px` } : void 0),
381
+ role: "menu",
382
+ "aria-label": "页签操作菜单"
383
+ }, [
384
+ l("p", Qe, k(v.value.tab.title), 1),
385
+ l("button", {
386
+ role: "menuitem",
387
+ disabled: p(v.value.tab),
388
+ onClick: n[3] || (n[3] = (o) => c("refresh"))
389
+ }, "刷新页面", 8, Ze),
390
+ l("button", {
391
+ role: "menuitem",
392
+ disabled: p(v.value.tab),
393
+ onClick: n[4] || (n[4] = (o) => c("close"))
394
+ }, "关闭当前", 8, _e),
395
+ n[9] || (n[9] = l("hr", null, null, -1)),
396
+ l("button", {
397
+ role: "menuitem",
398
+ onClick: n[5] || (n[5] = (o) => c("others"))
399
+ }, "关闭其他"),
400
+ l("button", {
401
+ role: "menuitem",
402
+ onClick: n[6] || (n[6] = (o) => c("left"))
403
+ }, "关闭左侧"),
404
+ l("button", {
405
+ role: "menuitem",
406
+ onClick: n[7] || (n[7] = (o) => c("right"))
407
+ }, "关闭右侧"),
408
+ l("button", {
409
+ role: "menuitem",
410
+ onClick: n[8] || (n[8] = (o) => c("all"))
411
+ }, "关闭全部业务页")
412
+ ], 6)) : I("", !0)
413
+ ], 40, Ae));
414
+ }
415
+ }), en = ["aria-busy"], nn = ["inert"], tn = ["title", "aria-label"], ln = { class: "shell-main" }, on = {
416
+ key: 0,
417
+ class: "shell-feedback",
418
+ role: "status"
419
+ }, mn = /* @__PURE__ */ V({
420
+ __name: "HostShell",
421
+ props: {
422
+ apps: {},
423
+ tabs: {},
424
+ activeKey: {},
425
+ userName: {},
426
+ pending: { type: Boolean, default: !1 },
427
+ notice: { default: "" },
428
+ brand: {},
429
+ collapsed: { type: Boolean, default: void 0 },
430
+ isFixedTab: {}
431
+ },
432
+ emits: ["open", "operate", "logout", "profile", "update:collapsed", "dismiss-notice", "error"],
433
+ setup(z, { expose: L, emit: O }) {
434
+ const a = z, p = O, d = K(!1), u = H({
435
+ get: () => a.collapsed ?? d.value,
436
+ set: (t) => {
437
+ d.value = t, p("update:collapsed", t);
438
+ }
439
+ }), v = K(), m = K(), C = K(), c = H(() => a.tabs.find((t) => t.key === a.activeKey)), B = (t, e) => JSON.stringify([t, e]), i = H(() => {
440
+ var t;
441
+ return (t = c.value) != null && t.activeMenuId ? B(c.value.appId, c.value.activeMenuId) : "";
442
+ }), s = K(!1);
443
+ function w(t, e) {
444
+ for (const n of t) {
445
+ if (n.menuId === e) return [n.menuId];
446
+ const o = w(n.children ?? [], e);
447
+ if (o.length) return [n.menuId, ...o];
448
+ }
449
+ return [];
450
+ }
451
+ const f = H(() => a.apps.flatMap((t) => {
452
+ var e;
453
+ return w(t.menus ?? [], ((e = c.value) == null ? void 0 : e.appId) === t.appId ? c.value.activeMenuId : void 0).slice(0, -1).map((n) => B(t.appId, n));
454
+ }));
455
+ J(i, () => {
456
+ var e, n;
457
+ const t = a.apps.find((o) => {
458
+ var h;
459
+ return o.appId === ((h = c.value) == null ? void 0 : h.appId);
460
+ });
461
+ if (t) for (const o of w(t.menus ?? [], (e = c.value) == null ? void 0 : e.activeMenuId).slice(0, -1)) (n = C.value) == null || n.open(B(t.appId, o));
462
+ }, { flush: "post", immediate: !0 });
463
+ async function S() {
464
+ s.value = !0, await q(), s.value = !1;
465
+ }
466
+ function F() {
467
+ var t, e;
468
+ (t = v.value) == null || t.closePopovers(), (e = m.value) == null || e.closePopovers();
469
+ }
470
+ const M = {
471
+ open: (t, e) => {
472
+ a.pending || p("open", t, e);
473
+ },
474
+ operate: (t) => {
475
+ a.pending || p("operate", t);
476
+ },
477
+ logout: () => {
478
+ a.pending || (F(), p("logout"));
479
+ },
480
+ profile: () => {
481
+ a.pending || p("profile");
482
+ },
483
+ toggleCollapsed: () => {
484
+ a.pending || (u.value = !u.value);
485
+ }
486
+ };
487
+ return J(() => a.pending, (t) => {
488
+ t && F();
489
+ }), L({ closePopovers: F }), (t, e) => (r(), b("div", {
490
+ class: j(["host-shell fin-micro-shell", { "is-collapsed": u.value }]),
491
+ "aria-busy": t.pending,
492
+ onKeydown: U(F, ["esc"])
493
+ }, [
494
+ P(t.$slots, "header", W(D({ ...M, active: c.value, collapsed: u.value, pending: t.pending })), () => {
495
+ var n;
496
+ return [
497
+ y(De, {
498
+ ref_key: "header",
499
+ ref: v,
500
+ collapsed: u.value,
501
+ "onUpdate:collapsed": e[0] || (e[0] = (o) => u.value = o),
502
+ brand: t.brand,
503
+ apps: t.apps,
504
+ "user-name": t.userName,
505
+ "active-title": ((n = c.value) == null ? void 0 : n.title) ?? "工作台",
506
+ pending: t.pending,
507
+ onLogout: M.logout,
508
+ onProfile: M.profile,
509
+ onOpen: M.open,
510
+ onPopoverOpened: e[1] || (e[1] = (o) => {
511
+ var h;
512
+ return (h = m.value) == null ? void 0 : h.closePopovers();
513
+ })
514
+ }, re({
515
+ "header-actions": $(() => [
516
+ P(t.$slots, "header-actions", W(D(M)))
517
+ ]),
518
+ _: 2
519
+ }, [
520
+ t.$slots.brand ? {
521
+ name: "brand",
522
+ fn: $((o) => [
523
+ P(t.$slots, "brand", W(D(o)))
524
+ ]),
525
+ key: "0"
526
+ } : void 0
527
+ ]), 1032, ["collapsed", "brand", "apps", "user-name", "active-title", "pending", "onLogout", "onProfile", "onOpen"])
528
+ ];
529
+ }),
530
+ l("aside", {
531
+ class: "shell-sidebar",
532
+ "aria-label": "主导航",
533
+ inert: t.pending || void 0
534
+ }, [
535
+ P(t.$slots, "sidebar", W(D({ ...M, active: c.value, collapsed: u.value, pending: t.pending })), () => [
536
+ u.value ? (r(!0), b(E, { key: 0 }, R(t.apps.filter((n) => {
537
+ var o;
538
+ return (o = n.menus) == null ? void 0 : o.length;
539
+ }), (n) => {
540
+ var o;
541
+ return r(), b("button", {
542
+ key: n.appId,
543
+ class: j(["collapsed-entry", { selected: ((o = c.value) == null ? void 0 : o.appId) === n.appId }]),
544
+ title: n.name,
545
+ "aria-label": `展开 ${n.name} 菜单`,
546
+ onClick: e[2] || (e[2] = //@ts-ignore
547
+ (...h) => M.toggleCollapsed && M.toggleCollapsed(...h))
548
+ }, k(n.name.slice(0, 1)), 11, tn);
549
+ }), 128)) : I("", !0),
550
+ Z(y(g(te), {
551
+ ref_key: "menu",
552
+ ref: C,
553
+ "collapse-transition": !1,
554
+ class: "sidebar-menu",
555
+ "default-active": s.value ? "__reset__" : i.value,
556
+ "default-openeds": f.value,
557
+ router: !1,
558
+ onSelect: S
559
+ }, {
560
+ default: $(() => [
561
+ (r(!0), b(E, null, R(t.apps, (n) => (r(), N(Je, {
562
+ key: n.appId,
563
+ "app-id": n.appId,
564
+ menus: n.menus ?? [],
565
+ onOpen: M.open
566
+ }, null, 8, ["app-id", "menus", "onOpen"]))), 128))
567
+ ]),
568
+ _: 1
569
+ }, 8, ["default-active", "default-openeds"]), [
570
+ [de, !u.value]
571
+ ]),
572
+ e[6] || (e[6] = l("div", { class: "sidebar-footer" }, [
573
+ l("span", { class: "status-dot" }),
574
+ l("span", { class: "sidebar-label" }, "工作空间已就绪")
575
+ ], -1))
576
+ ])
577
+ ], 8, nn),
578
+ l("main", ln, [
579
+ P(t.$slots, "tabs", W(D({ ...M, active: c.value, pending: t.pending })), () => [
580
+ y(xe, {
581
+ ref_key: "tabBar",
582
+ ref: m,
583
+ tabs: t.tabs,
584
+ "active-key": t.activeKey,
585
+ pending: t.pending,
586
+ "is-fixed-tab": t.isFixedTab,
587
+ onOperate: M.operate,
588
+ onError: e[3] || (e[3] = (n) => p("error", n)),
589
+ onPopoverOpened: e[4] || (e[4] = (n) => {
590
+ var o;
591
+ return (o = v.value) == null ? void 0 : o.closePopovers();
592
+ })
593
+ }, null, 8, ["tabs", "active-key", "pending", "is-fixed-tab", "onOperate"])
594
+ ]),
595
+ t.notice ? (r(), b("div", on, [
596
+ l("span", null, k(t.notice), 1),
597
+ l("button", {
598
+ "aria-label": "关闭操作提示",
599
+ onClick: e[5] || (e[5] = (n) => p("dismiss-notice"))
600
+ }, "×")
601
+ ])) : I("", !0),
602
+ P(t.$slots, "default", { active: c.value })
603
+ ])
604
+ ], 42, en));
605
+ }
606
+ }), an = /* @__PURE__ */ V({
607
+ __name: "StandaloneMenuItem",
608
+ props: {
609
+ item: {}
610
+ },
611
+ emits: ["navigate"],
612
+ setup(z, { emit: L }) {
613
+ const O = L;
614
+ return (a, p) => {
615
+ const d = x("StandaloneMenuItem", !0);
616
+ return a.item.children.length ? (r(), N(g(ee), {
617
+ key: 0,
618
+ index: a.item.path
619
+ }, {
620
+ title: $(() => [
621
+ a.item.icon ? (r(), N(g(T), { key: 0 }, {
622
+ default: $(() => [
623
+ (r(), N(A(a.item.icon)))
624
+ ]),
625
+ _: 1
626
+ })) : I("", !0),
627
+ l("span", null, k(a.item.title), 1)
628
+ ]),
629
+ default: $(() => [
630
+ (r(!0), b(E, null, R(a.item.children, (u) => (r(), N(d, {
631
+ key: u.path,
632
+ item: u,
633
+ onNavigate: p[0] || (p[0] = (v) => O("navigate", v))
634
+ }, null, 8, ["item"]))), 128))
635
+ ]),
636
+ _: 1
637
+ }, 8, ["index"])) : (r(), N(g(ne), {
638
+ key: 1,
639
+ index: a.item.path,
640
+ onClick: p[1] || (p[1] = (u) => O("navigate", a.item.path))
641
+ }, {
642
+ default: $(() => [
643
+ a.item.icon ? (r(), N(g(T), { key: 0 }, {
644
+ default: $(() => [
645
+ (r(), N(A(a.item.icon)))
646
+ ]),
647
+ _: 1
648
+ })) : I("", !0),
649
+ l("span", null, k(a.item.title), 1)
650
+ ]),
651
+ _: 1
652
+ }, 8, ["index"]));
653
+ };
654
+ }
655
+ }), sn = { class: "fin-micro-standalone" }, rn = { class: "standalone-header" }, dn = {
656
+ class: "standalone-sidebar",
657
+ "aria-label": "独立应用导航"
658
+ }, un = { class: "standalone-viewport" }, pn = { class: "standalone-content" }, bn = /* @__PURE__ */ V({
659
+ __name: "StandaloneShell",
660
+ props: {
661
+ title: {},
662
+ menus: {},
663
+ activeMenu: {},
664
+ brand: {}
665
+ },
666
+ emits: ["navigate"],
667
+ setup(z, { emit: L }) {
668
+ const O = L, a = K(!1);
669
+ async function p(d) {
670
+ O("navigate", d), a.value = !0, await q(), a.value = !1;
671
+ }
672
+ return (d, u) => (r(), b("div", sn, [
673
+ l("header", rn, [
674
+ P(d.$slots, "brand", {
675
+ brand: d.brand ?? {}
676
+ }, () => {
677
+ var v;
678
+ return [
679
+ l("strong", null, k(((v = d.brand) == null ? void 0 : v.title) ?? "业务应用"), 1)
680
+ ];
681
+ }),
682
+ l("span", null, k(d.title) + " · 独立运行", 1),
683
+ P(d.$slots, "header-actions")
684
+ ]),
685
+ l("aside", dn, [
686
+ P(d.$slots, "sidebar", {
687
+ menus: d.menus,
688
+ navigate: p
689
+ }, () => [
690
+ y(g(te), {
691
+ router: !1,
692
+ "default-active": a.value ? "__reset__" : d.activeMenu,
693
+ "collapse-transition": !1
694
+ }, {
695
+ default: $(() => [
696
+ (r(!0), b(E, null, R(d.menus, (v) => (r(), N(an, {
697
+ key: v.path,
698
+ item: v,
699
+ onNavigate: p
700
+ }, null, 8, ["item"]))), 128))
701
+ ]),
702
+ _: 1
703
+ }, 8, ["default-active"])
704
+ ])
705
+ ]),
706
+ l("div", un, [
707
+ l("main", pn, [
708
+ P(d.$slots, "default")
709
+ ]),
710
+ P(d.$slots, "workspace-overlay")
711
+ ])
712
+ ]));
713
+ }
714
+ }), gn = 1;
715
+ export {
716
+ mn as HostShell,
717
+ bn as StandaloneShell,
718
+ gn as layoutProtocol
719
+ };