labull-framework 0.1.1 → 0.1.3

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/README.md CHANGED
@@ -36,20 +36,46 @@ app.mount('#app')
36
36
 
37
37
  ```vue
38
38
  <script setup lang="ts">
39
+ import { ref } from 'vue'
39
40
  import { useAuth } from 'labull-framework/auth'
40
- import { MagicBlockHost } from 'labull-framework/magic-block'
41
+ import { openTab } from 'labull-framework/ui'
42
+ import type { SideItem } from 'labull-framework/ui'
41
43
 
42
44
  const { user, isStaff, logout } = useAuth()
45
+ const notice = ref('')
46
+
47
+ /** 一级 = 模块(点它滑出二级菜单),二级 = 页面;点一项干什么写在它自己的 onClick 里。 */
48
+ const menu: SideItem[] = [
49
+ { path: 'sales', title: '销售管理', icon: 'pi pi-shopping-cart', children: [
50
+ { path: '/orders', title: '订单', icon: 'pi pi-list', onClick: () => openTab('/orders') },
51
+ { path: '/orders/42', title: '订单 SO-1', icon: 'pi pi-file', onClick: () => openTab('/orders/42?orderId=7') },
52
+ { title: '设置', icon: 'pi pi-cog', onClick: () => { notice.value = '这一项不开标签' } }, // 不写 onClick 时默认"有 path 就开那个标签"
53
+ ]},
54
+ ]
43
55
  </script>
44
56
 
45
57
  <template>
46
- <ProductShell>
47
- <template #appbar><b>订单系统</b></template>
48
- <MagicBlockHost uuid="6f1c…" />
58
+ <ProductShell :side="menu" caption="订单系统">
59
+ <template #appbar><b>{{ user?.name }}</b></template>
60
+ <RouterView /> <!-- 页面(= 标签内容)由路由给 -->
49
61
  </ProductShell>
50
62
  </template>
51
63
  ```
52
64
 
65
+ magic block:**一条路由 = 一个块** —— **块外面不放任何东西**(标题 / 按钮 / 参数展示都写进块自己的
66
+ `index.open.html`),块占满这条标签页:
67
+
68
+ ```ts
69
+ // main.ts:这一条路由就是这个块(没有页面文件)
70
+ { path: '/orders', component: MagicBlockPage, props: { uuid: '6f1c…' },
71
+ meta: { title: '订单', icon: 'pi pi-list' } }
72
+ ```
73
+ ```js
74
+ // 块自己的 index.open.html 里:要什么问宿主
75
+ const tab = await magicBlock.context() // { path, params, query }
76
+ await magicBlock.setTabTitle('订单 SO-42', 'pi pi-file') // 给所属那条标签起名
77
+ ```
78
+
53
79
  后端地址走 `VITE_API_BASE`(默认 `http://localhost:3000`)。
54
80
 
55
81
  ## subpath 对照表(原包 → 现在怎么 import)
@@ -58,8 +84,8 @@ const { user, isStaff, logout } = useAuth()
58
84
  |---|---|---|
59
85
  | `@labull/theme` | `labull-framework/style.css`(或 `labull-framework/theme`) | `--sp-*` token + 完整主题层 + 结构类 + primeicons |
60
86
  | `@labull/auth` | `labull-framework/auth` | `useAuth()` / `apiFetch()` / `ensureAuthenticated()` / `createAuthGate()` / `API_BASE` |
61
- | `@labull/ui` | `labull-framework/ui` | `ProductShell` / `ProductSide` / `ProductTabs` / `AppSearch` / `UserMenu` / `labull` 插件 |
62
- | `@labull/magic-block` | `labull-framework/magic-block` | `MagicBlockHost` / `MagicBlockConsole` / 清单校验 / bridge |
87
+ | `@labull/ui` | `labull-framework/ui` | `ProductShell` / `ProductSide` / `ProductTabs` / `TabPage` / `AppSearch` / `UserMenu` / `labull` 插件,以及标签那一套:`openTab` / `activateTab` / `closeTab` / `useTabs` / `useTabContext` |
88
+ | `@labull/magic-block` | `labull-framework/magic-block` | `MagicBlockPage`(一条路由 = 一个块,**唯一入口**) / `MagicBlockConsole` / 清单校验 / bridge |
63
89
 
64
90
  根入口 `labull-framework` = `auth` + `ui`(最常用的两层)。
65
91
 
@@ -0,0 +1,132 @@
1
+ import { reactive as h, computed as p, ref as y, provide as T, inject as g } from "vue";
2
+ import { useRouter as w } from "vue-router";
3
+ const c = h({ tabs: [], active: "" });
4
+ let r = null;
5
+ function L(t) {
6
+ r = t;
7
+ }
8
+ function s(t) {
9
+ return typeof t == "string" && t.trim() ? t.trim() : "";
10
+ }
11
+ function x(t) {
12
+ const o = t.split("/").filter(Boolean).pop();
13
+ return { title: o ? decodeURIComponent(o) : "首页", icon: "pi pi-file" };
14
+ }
15
+ function v(t) {
16
+ return c.tabs.find((o) => o.key === t);
17
+ }
18
+ function b(t, o, e) {
19
+ const n = v(t);
20
+ if (n) {
21
+ const l = s(e?.title);
22
+ l && (n.title = l);
23
+ const d = s(e?.icon);
24
+ return d && (n.icon = d), c.active = n.key, n.key;
25
+ }
26
+ const i = x(o), a = {
27
+ key: t,
28
+ path: o,
29
+ title: s(e?.title) || i.title,
30
+ icon: s(e?.icon) || i.icon
31
+ };
32
+ return c.tabs.push(a), c.active = a.key, a.key;
33
+ }
34
+ function O(t, o) {
35
+ const e = r ? r.resolve(t) : { fullPath: t, path: t.split("?")[0] ?? t, matched: !0 };
36
+ if (!e.matched)
37
+ return console.warn(`[labull] 这个应用里没有页面 ${t}:先把它加进路由表,再开标签。`), "";
38
+ const n = b(e.fullPath, e.path, o);
39
+ return r && r.current() !== n && r.go(n), n;
40
+ }
41
+ function _(t) {
42
+ v(t) && (c.active = t, r && r.current() !== t && r.go(t));
43
+ }
44
+ function R(t, o, e) {
45
+ return b(t, o, e);
46
+ }
47
+ function q(t) {
48
+ const o = c.tabs.findIndex((i) => i.key === t);
49
+ if (o < 0) return "";
50
+ const e = c.tabs.filter((i) => i.key !== t);
51
+ if (c.tabs = e, c.active !== t) return "";
52
+ const n = e[o] ?? e[o - 1] ?? e[e.length - 1];
53
+ return n ? (c.active = n.key, r && r.current() !== n.key && r.go(n.key), n.key) : (c.active = "", "");
54
+ }
55
+ function C(t, o, e) {
56
+ const n = v(t);
57
+ if (!n) return;
58
+ const i = s(o);
59
+ i && (n.title = i);
60
+ const a = s(e);
61
+ a && (n.icon = a);
62
+ }
63
+ function N() {
64
+ return {
65
+ tabs: p(() => c.tabs),
66
+ active: p(() => c.active),
67
+ openTab: O,
68
+ activateTab: _,
69
+ closeTab: q
70
+ };
71
+ }
72
+ const f = typeof window > "u" ? null : window.matchMedia("(orientation: portrait)"), k = y(f ? f.matches : !1), u = y(!1);
73
+ function j() {
74
+ u.value = !u.value;
75
+ }
76
+ function E() {
77
+ u.value = !1;
78
+ }
79
+ f && f.addEventListener("change", (t) => {
80
+ k.value = t.matches, t.matches || (u.value = !1);
81
+ });
82
+ function U() {
83
+ return { portrait: k, navOpen: u, toggleNav: j, closeNav: E };
84
+ }
85
+ const A = (t, o) => {
86
+ const e = t.__vccOpts || t;
87
+ for (const [n, i] of o)
88
+ e[n] = i;
89
+ return e;
90
+ }, m = "labull:tab";
91
+ function M(t) {
92
+ const o = w(), { active: e } = N(), n = () => o.resolve(t.key), i = {
93
+ key: t.key,
94
+ path: t.path,
95
+ get params() {
96
+ return n().params;
97
+ },
98
+ get query() {
99
+ return n().query;
100
+ },
101
+ active: p(() => e.value === t.key),
102
+ setTitle(a, l) {
103
+ C(t.key, a, l);
104
+ }
105
+ };
106
+ return T(m, i), i;
107
+ }
108
+ function P() {
109
+ const t = g(m, null);
110
+ if (!t) throw new Error("[labull] 这里不在标签页里:页面与 magic block 必须放在外壳的标签内容区(标签页)里。");
111
+ return t;
112
+ }
113
+ function V(t, o) {
114
+ if (!o || typeof o.resolve != "function") return !1;
115
+ const e = o.resolve(t), n = e?.params ?? {}, i = e?.query ?? {};
116
+ return Object.keys(n).length > 0 || Object.keys(i).length > 0;
117
+ }
118
+ export {
119
+ m as T,
120
+ A as _,
121
+ _ as a,
122
+ V as b,
123
+ q as c,
124
+ N as d,
125
+ U as e,
126
+ R as f,
127
+ L as i,
128
+ O as o,
129
+ M as p,
130
+ C as s,
131
+ P as u
132
+ };