mgacn-commonsdk 1.0.4 → 1.1.0

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
@@ -28,16 +28,104 @@ npm install mgacn-commonsdk
28
28
  ## 使用
29
29
 
30
30
  ```js
31
- import MgacnCommonSdk from 'mgacn-commonsdk';
31
+ // 顺序不能乱:先 EP 默认,再品牌主题(主题不要被 JS 副作用提前加载)
32
+ import 'element-plus/dist/index.css';
32
33
  import 'mgacn-commonsdk/style.css';
34
+ import MgacnCommonSdk from 'mgacn-commonsdk';
33
35
 
34
36
  app.use(MgacnCommonSdk, {
35
37
  tokenKey: 'your_token_key',
36
38
  baseURL: import.meta.env.VITE_API_BASE_URL,
37
- systemIdKey: 'mgacn_systemid', // 可选,有的系统需要
39
+ systemId: '', // 可选;子应用也可接口拿到后 setSystemId
40
+ });
41
+ ```
42
+
43
+ `style.css` 已包含门户与子系统共用的主题样式(**必须**放在 `element-plus` 样式之后;SDK 的 JS 入口不再副作用引入主题,避免被 Vite CSS 去重后排到 EP 前面):
44
+
45
+ - `element-variables.scss` — 品牌色与 EP 变量
46
+ - `common.scss` — 通用工具类
47
+ - `reset-element.scss` — Element Plus 样式重置
48
+
49
+ 子应用从接口获取 `systemId` 后(接口待定):
50
+
51
+ ```js
52
+ import { setSystemId } from 'mgacn-commonsdk';
53
+
54
+ setSystemId(systemId); // 之后请求头会带 systemId
55
+ ```
56
+
57
+ ### 按钮权限
58
+
59
+ `app.use` 时传入权限列表读取函数(通常来自菜单 store 的 `permissions`),SDK 会注册指令并提供 `hasPermission`:
60
+
61
+ ```js
62
+ import { useMenuStore } from '@/store/menuStore';
63
+
64
+ app.use(MgacnCommonSdk, {
65
+ tokenKey: 'mgacn_token',
66
+ getPermissions: () => useMenuStore().permissions,
67
+ });
68
+ ```
69
+
70
+ 也可事后设置:
71
+
72
+ ```js
73
+ import { setPermissionGetter, hasPermission, checkPermission } from 'mgacn-commonsdk';
74
+
75
+ setPermissionGetter(() => useMenuStore().permissions);
76
+
77
+ hasPermission('menu:add');
78
+ hasPermission(['menu:add', 'menu:edit']); // 且
79
+ hasPermission(['menu:add', 'menu:edit'], 'or'); // 或
80
+ checkPermission(['menu:add'], 'menu:add'); // 纯函数,不依赖 getter
81
+ ```
82
+
83
+ 模板指令(`install` 时自动注册):
84
+
85
+ ```vue
86
+ <el-button v-hasPermission="'menu:add'">新增</el-button>
87
+ <el-button v-hasAnyPermission="'menu:add,menu:edit'">编辑类</el-button>
88
+ <span v-hasNoPermission="'menu:add'">无新增权限时可见</span>
89
+ ```
90
+
91
+ 未传入 `getPermissions` / `setPermissionGetter` 时,`hasPermission` 不拦截(恒为 `true`)。
92
+
93
+ ### 子系统壳层(`mgacn-commonsdk/admin`)
94
+
95
+ 门户**不要**引入;仅各业务子系统使用。仍是**同一个 npm 包**,通过子路径导出,无需发第二个包。
96
+
97
+ 包含:顶栏、侧栏、布局、user/system/menu store、动态路由、菜单管理、角色管理。
98
+
99
+ ```js
100
+ import { bootstrapAdminApp } from 'mgacn-commonsdk/admin';
101
+ import 'element-plus/dist/index.css';
102
+ import 'mgacn-commonsdk/style.css';
103
+ import App from './App.vue';
104
+ import Homepage from './views/homepage/index.vue';
105
+
106
+ bootstrapAdminApp({
107
+ App,
108
+ homepageComponent: Homepage,
109
+ deployKey: 'account_cms', // 部署目录名,匹配当前系统
110
+ appTitle: '芒果ACN账号库',
111
+ portalUrl: import.meta.env.VITE_PORTAL_URL, // 如 /portal_cms#
112
+ ossDomain: import.meta.env.VITE_OSS_URL,
113
+ viewModules: import.meta.glob('./views/**/*.vue'),
114
+ isDev: import.meta.env.DEV,
115
+ setupIcons: (app) => { /* 注册图标 */ },
38
116
  });
39
117
  ```
40
118
 
119
+ 菜单 `pathComponent` 为 `system/menu`、`system/role` 时走壳内页面;其它业务页由宿主 `viewModules` 解析。
120
+
121
+ 本地 monorepo 可在 Vite 中 alias:
122
+
123
+ ```js
124
+ 'mgacn-commonsdk/admin' → '../mgacn-commonsdk/src/admin/index.js'
125
+ ```
126
+
127
+ peer 依赖需宿主已安装:`vue`、`vue-router`、`pinia`、`element-plus`、`@element-plus/icons-vue`。
128
+
41
129
  ### 网络请求(宿主使用 .GET / .POST)
42
130
 
43
131
  先 `app.use` 后,页面里这样调:
@@ -241,7 +329,7 @@ import { createRequest, createApi } from 'mgacn-commonsdk';
241
329
  const request = createRequest({
242
330
  tokenKey: 'your_token_key',
243
331
  baseURL: '/api',
244
- systemIdKey: 'mgacn_systemid', // 可选
332
+ systemId: '', // 可选;也可事后 setSystemId
245
333
  });
246
334
  const api = createApi(request);
247
335
  ```
@@ -0,0 +1,289 @@
1
+ import T from "axios";
2
+ function I(t) {
3
+ if (!t)
4
+ throw new Error("[mgacn-commonsdk] createApi 需要传入 request 实例");
5
+ return {
6
+ // ---------- 注销登录 ----------
7
+ logout(n) {
8
+ return t.GET(`/yhAdmin/login/exit/${n}`);
9
+ },
10
+ // ---------- 用户 ----------
11
+ getUserInfo(n) {
12
+ return t.GET(`/yhAdmin/user/queryUser/${n}`);
13
+ },
14
+ // ---------- OSS ----------
15
+ getOssSts(n) {
16
+ return t.GET("/yhAdmin/oss/getStsToken", { params: { dir: n } });
17
+ }
18
+ };
19
+ }
20
+ const y = "__MGACN_COMMONSDK_API__";
21
+ function G(t) {
22
+ globalThis[y] = t;
23
+ }
24
+ function K() {
25
+ const t = globalThis[y];
26
+ if (!t)
27
+ throw new Error("[mgacn-commonsdk] 请先 app.use(MgacnCommonSdk, { tokenKey, baseURL })");
28
+ return t;
29
+ }
30
+ const b = "__MGACN_COMMONSDK_SYSTEM_ID__";
31
+ function E(t) {
32
+ globalThis[b] = t == null ? "" : String(t);
33
+ }
34
+ function M() {
35
+ return globalThis[b] || "";
36
+ }
37
+ function Y(t = {}) {
38
+ const {
39
+ baseURL: n = "",
40
+ timeout: e = 6e4,
41
+ tokenKey: r,
42
+ systemId: s,
43
+ loginUrl: o = "/login"
44
+ } = t;
45
+ s != null && s !== "" && E(s);
46
+ const c = T.create({ baseURL: n, timeout: e });
47
+ let a = !1;
48
+ function f() {
49
+ typeof localStorage < "u" && localStorage.clear(), !a && (a = !0, setTimeout(() => {
50
+ typeof window < "u" && window.location.replace(o);
51
+ }, 1500));
52
+ }
53
+ return c.interceptors.request.use(
54
+ (i) => {
55
+ if (i.headers["Content-Type"] = "application/json;charset=UTF-8", typeof localStorage < "u" && r) {
56
+ const m = localStorage.getItem(r);
57
+ m && (i.headers.Authorization = m);
58
+ }
59
+ const u = M();
60
+ return u && (i.headers.systemId = u), i;
61
+ },
62
+ (i) => Promise.reject(i)
63
+ ), c.interceptors.response.use(
64
+ (i) => {
65
+ if (i.status !== 200)
66
+ return Promise.reject(new Error(`请求发生错误,状态码 ${i.status}`));
67
+ const { data: u, config: m } = i;
68
+ if (m.responseType === "arraybuffer") return u;
69
+ if (u && u.code === 0) return u.data;
70
+ const l = Number(u == null ? void 0 : u.code);
71
+ if (l === 401 || l === 403)
72
+ return f(), Promise.reject(new Error("登录失效,请重新登录"));
73
+ const g = S(u) || "请求失败";
74
+ return Promise.reject(new Error(g));
75
+ },
76
+ (i) => {
77
+ var g, h;
78
+ const u = (g = i == null ? void 0 : i.response) == null ? void 0 : g.status;
79
+ if (u === 401 || u === 403)
80
+ return f(), Promise.reject(new Error("登录失效,请重新登录"));
81
+ const m = (h = i == null ? void 0 : i.response) == null ? void 0 : h.data, l = S(m) || (i == null ? void 0 : i.message) || "请求失败";
82
+ return Promise.reject(new Error(String(l)));
83
+ }
84
+ ), c;
85
+ }
86
+ function S(t) {
87
+ if (t == null) return "";
88
+ if (typeof t == "string") {
89
+ const e = t.trim();
90
+ return e ? /^<!DOCTYPE html>/i.test(e) || /^<html[\s>]/i.test(e) ? "接口地址无效或未配置代理" : e.length > 200 ? `${e.slice(0, 200)}…` : e : "";
91
+ }
92
+ if (typeof t != "object") return String(t);
93
+ const n = [t.message, t.msg, t.data, t.error];
94
+ for (const e of n)
95
+ if (!(e == null || e === "") && (typeof e == "string" || typeof e == "number")) {
96
+ const r = String(e).trim();
97
+ return /^<!DOCTYPE html>/i.test(r) || /^<html[\s>]/i.test(r) ? "接口地址无效或未配置代理" : r.length > 200 ? `${r.slice(0, 200)}…` : r;
98
+ }
99
+ return "";
100
+ }
101
+ function x(t = {}) {
102
+ const n = Y(t);
103
+ return {
104
+ GET(e, r = {}) {
105
+ return n({ method: "get", url: e, ...r });
106
+ },
107
+ POST(e, r, s = {}) {
108
+ return n({ method: "post", url: e, data: r, ...s });
109
+ },
110
+ DELETE(e, r = {}) {
111
+ return n({ method: "delete", url: e, ...r });
112
+ }
113
+ };
114
+ }
115
+ const N = "__MGACN_COMMONSDK_REQUEST__";
116
+ function U(t) {
117
+ globalThis[N] = t;
118
+ }
119
+ function q() {
120
+ const t = globalThis[N];
121
+ if (!t)
122
+ throw new Error("[mgacn-commonsdk] 请先 app.use(MgacnCommonSdk, { tokenKey, baseURL })");
123
+ return t;
124
+ }
125
+ const _ = "__MGACN_COMMONSDK_PERMISSION_GETTER__";
126
+ function L(t) {
127
+ globalThis[_] = typeof t == "function" ? t : null;
128
+ }
129
+ function w() {
130
+ return globalThis[_] || null;
131
+ }
132
+ function A(t, n, e = "and") {
133
+ const r = (Array.isArray(n) ? n : [n]).map((o) => String(o ?? "").trim()).filter(Boolean);
134
+ if (!r.length) return !0;
135
+ const s = new Set((t || []).map(String));
136
+ return e === "or" ? r.some((o) => s.has(o)) : r.every((o) => s.has(o));
137
+ }
138
+ function z(t, n = "and") {
139
+ const e = w();
140
+ return typeof e != "function" ? !0 : A(e(), t, n);
141
+ }
142
+ const F = (t, n) => {
143
+ const e = t.__vccOpts || t;
144
+ for (const [r, s] of n)
145
+ e[r] = s;
146
+ return e;
147
+ };
148
+ function O(t) {
149
+ return !!(t == null || typeof t == "string" && t.trim() === "" || Array.isArray(t) && t.length === 0 || typeof t == "object" && !Array.isArray(t) && Object.keys(t).length === 0);
150
+ }
151
+ function d(t) {
152
+ if (t === null || typeof t != "object") return t;
153
+ if (t instanceof Date) return new Date(t.getTime());
154
+ if (Array.isArray(t)) return t.map((e) => d(e));
155
+ const n = {};
156
+ return Object.keys(t).forEach((e) => {
157
+ n[e] = d(t[e]);
158
+ }), n;
159
+ }
160
+ function P(t, n = 300) {
161
+ let e = null;
162
+ return function(...s) {
163
+ e && clearTimeout(e), e = setTimeout(() => {
164
+ t.apply(this, s);
165
+ }, n);
166
+ };
167
+ }
168
+ function j(t, n = 300) {
169
+ let e = 0;
170
+ return function(...s) {
171
+ const o = Date.now();
172
+ o - e >= n && (e = o, t.apply(this, s));
173
+ };
174
+ }
175
+ function D(t) {
176
+ if (t == null || t === "") return null;
177
+ if (t instanceof Date)
178
+ return Number.isNaN(t.getTime()) ? null : t;
179
+ if (typeof t == "number") {
180
+ const s = new Date(t);
181
+ return Number.isNaN(s.getTime()) ? null : s;
182
+ }
183
+ const n = String(t).trim();
184
+ if (!n) return null;
185
+ if (/^\d{10,13}$/.test(n)) {
186
+ const s = n.length === 10 ? Number(n) * 1e3 : Number(n), o = new Date(s);
187
+ return Number.isNaN(o.getTime()) ? null : o;
188
+ }
189
+ if (/[Zz]$|[+-]\d{2}:?\d{2}$/.test(n)) {
190
+ const s = new Date(n);
191
+ return Number.isNaN(s.getTime()) ? null : s;
192
+ }
193
+ const e = n.match(
194
+ /^(\d{4})[-/.年](\d{1,2})[-/.月](\d{1,2})日?(?:[\sT]+(\d{1,2}):(\d{1,2})(?::(\d{1,2}))?(?:\.(\d{1,3}))?)?/
195
+ );
196
+ if (e) {
197
+ const [, s, o, c, a = "0", f = "0", i = "0", u = "0"] = e, m = new Date(
198
+ Number(s),
199
+ Number(o) - 1,
200
+ Number(c),
201
+ Number(a),
202
+ Number(f),
203
+ Number(i),
204
+ Number(String(u).padEnd(3, "0"))
205
+ );
206
+ return Number.isNaN(m.getTime()) ? null : m;
207
+ }
208
+ const r = new Date(n);
209
+ return Number.isNaN(r.getTime()) ? null : r;
210
+ }
211
+ function p(t, n = "YYYY-MM-DD HH:mm:ss") {
212
+ const e = D(t);
213
+ if (!e) return "";
214
+ const r = e.getFullYear(), s = e.getMonth() + 1, o = e.getDate(), c = e.getHours(), a = e.getMinutes(), f = e.getSeconds(), i = {
215
+ YYYY: String(r),
216
+ MM: String(s).padStart(2, "0"),
217
+ DD: String(o).padStart(2, "0"),
218
+ HH: String(c).padStart(2, "0"),
219
+ mm: String(a).padStart(2, "0"),
220
+ ss: String(f).padStart(2, "0"),
221
+ M: String(s),
222
+ D: String(o),
223
+ H: String(c),
224
+ m: String(a),
225
+ s: String(f)
226
+ };
227
+ return n.replace(/YYYY|MM|DD|HH|mm|ss|M|D|H|m|s/g, (u) => i[u]);
228
+ }
229
+ function C() {
230
+ const t = /* @__PURE__ */ new Date();
231
+ t.setHours(23, 59, 59, 0);
232
+ const n = /* @__PURE__ */ new Date();
233
+ return n.setDate(n.getDate() - 30), n.setHours(0, 0, 0, 0), {
234
+ start: p(n, "YYYY-MM-DD HH:mm:ss"),
235
+ end: p(t, "YYYY-MM-DD HH:mm:ss")
236
+ };
237
+ }
238
+ function k(t) {
239
+ const n = {};
240
+ return Object.keys(t || {}).forEach((e) => {
241
+ const r = t[e];
242
+ r == null || r === "" || Array.isArray(r) && r.length === 0 || (n[e] = r);
243
+ }), n;
244
+ }
245
+ function H(t, n = 2) {
246
+ if (t == null || t === "") return t;
247
+ const e = Number(t);
248
+ if (Number.isNaN(e)) return t;
249
+ const r = e.toFixed(n), [s, o] = r.split("."), c = s.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
250
+ if (o == null) return c;
251
+ const a = o.replace(/0+$/, "");
252
+ return a ? `${c}.${a}` : c;
253
+ }
254
+ function R(t = "id") {
255
+ return `${t}_${Date.now()}_${Math.random().toString(36).slice(2, 9)}`;
256
+ }
257
+ const B = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
258
+ __proto__: null,
259
+ cleanParams: k,
260
+ debounce: P,
261
+ deepClone: d,
262
+ formatDate: p,
263
+ formatNum: H,
264
+ getRecentMonthRange: C,
265
+ isEmpty: O,
266
+ parseDate: D,
267
+ throttle: j,
268
+ uniqueId: R
269
+ }, Symbol.toStringTag, { value: "Module" }));
270
+ export {
271
+ F as _,
272
+ q as a,
273
+ k as b,
274
+ A as c,
275
+ d,
276
+ P as e,
277
+ L as f,
278
+ K as g,
279
+ z as h,
280
+ x as i,
281
+ I as j,
282
+ U as k,
283
+ G as l,
284
+ Y as m,
285
+ w as n,
286
+ M as o,
287
+ B as p,
288
+ E as s
289
+ };