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 +91 -3
- package/dist/index-Y2_0CiYi.js +289 -0
- package/dist/mgacn-admin.js +2638 -0
- package/dist/mgacn-commonsdk.js +649 -849
- package/dist/style.css +2 -2
- package/dist/style.js +1 -0
- package/package.json +15 -8
- package/dist/mgacn-commonsdk.umd.cjs +0 -1
package/README.md
CHANGED
|
@@ -28,16 +28,104 @@ npm install mgacn-commonsdk
|
|
|
28
28
|
## 使用
|
|
29
29
|
|
|
30
30
|
```js
|
|
31
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
+
};
|