@infly/libs 2.0.36 → 2.0.38
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/bin/cli.js +29 -22
- package/build/build-dist/index.js +211 -46
- package/build/webpack5/webpack.base.js +10 -1
- package/build/webpack5/webpack.base.test.js +59 -0
- package/module/Permission.js +43 -36
- package/module/REST.js +109 -46
- package/module/Uts.js +90 -52
- package/module/cjs/deep-merge.cjs +38 -0
- package/module/cjs/page-config.cjs +119 -0
- package/module/cjs/request-url-rules.cjs +55 -0
- package/package.json +6 -7
- package/script/build/command.js +48 -0
- package/script/build/env.js +28 -0
- package/script/build/git.js +252 -0
- package/script/build/preview.js +75 -0
- package/script/build/webhook.js +118 -0
- package/script/git-automation/check-packages.js +11 -8
- package/script/git-automation/git-utils.js +67 -0
- package/script/git-automation/index.js +229 -104
- package/script/pts/cloud-scenes.mjs +65 -0
- package/script/pts/cloud.js +151 -0
- package/script/pts/generate-cloud-params.mjs +210 -0
- package/script/pts/generate-cloud-params.test.mjs +67 -0
- package/script/webhook/webhook.js +72 -2
- package/store/modules/user.js +63 -46
- package/tools/auto-export.js +56 -0
- package/tools/file-export.js +16 -12
- package/tools/project-preview.js +110 -97
- package/types/unused.index.d.ts +0 -71
package/module/Permission.js
CHANGED
|
@@ -9,12 +9,10 @@ import TokenService from "./TokenService";
|
|
|
9
9
|
* @param {Object} config.router 路由实例
|
|
10
10
|
* @param {Object} config.store Vuex store 实例
|
|
11
11
|
* @param {Object} config.NProgress NProgress 实例
|
|
12
|
-
* @param {Function} config.getToken 获取 token 的函数
|
|
13
12
|
* @param {Function} config.getUserInfo 获取用户信息的函数
|
|
14
13
|
* @param {Function} config.resetToken 重置 token 的函数
|
|
15
14
|
* @param {Function} config.showMessage 显示消息的函数
|
|
16
|
-
* @
|
|
17
|
-
* * @returns {void}
|
|
15
|
+
* @returns {void}
|
|
18
16
|
*/
|
|
19
17
|
export function initPermission({
|
|
20
18
|
whiteList = ["/login", "/404", "/403", "/error/401", "/error/404"],
|
|
@@ -32,14 +30,14 @@ export function initPermission({
|
|
|
32
30
|
resetToken,
|
|
33
31
|
showMessage
|
|
34
32
|
}) {
|
|
35
|
-
const { title: projectTitle
|
|
36
|
-
const { initRoutePath = "/" } = projectConfig || {};
|
|
33
|
+
const { title: projectTitle } = settings || {};
|
|
37
34
|
const { dispatch } = store || {};
|
|
35
|
+
// 转为 Set,将白名单查找从 O(n) 优化为 O(1)
|
|
36
|
+
const whiteSet = new Set(whiteList);
|
|
38
37
|
|
|
38
|
+
// afterEach 已统一调用 NProgress.done(),此处无需重复
|
|
39
39
|
const redirectToLogin = (to, next) => {
|
|
40
40
|
next(`/login?redirect=${to.path}`);
|
|
41
|
-
NProgress.done();
|
|
42
|
-
return;
|
|
43
41
|
};
|
|
44
42
|
|
|
45
43
|
const handleGetUserInfo = () => {
|
|
@@ -58,24 +56,20 @@ export function initPermission({
|
|
|
58
56
|
}
|
|
59
57
|
};
|
|
60
58
|
|
|
59
|
+
// 降级链:优先调用自定义 showMessage,其次 Message,最后 console
|
|
61
60
|
const handleShowMessage = (message, type = "error") => {
|
|
62
61
|
if (Uts.isFunction(showMessage)) {
|
|
63
62
|
showMessage(message);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
if (Uts.isFunction(Message)) {
|
|
63
|
+
} else if (Uts.isFunction(Message)) {
|
|
67
64
|
Message[type](message);
|
|
65
|
+
} else {
|
|
66
|
+
console.log(message);
|
|
68
67
|
}
|
|
69
|
-
|
|
70
|
-
console.log(message);
|
|
71
68
|
};
|
|
72
69
|
|
|
73
70
|
const handlePageTitle = (path) => {
|
|
74
71
|
const title = projectTitle || "后台管理系统";
|
|
75
|
-
|
|
76
|
-
return `${path} - ${title}`;
|
|
77
|
-
}
|
|
78
|
-
return `${title}`;
|
|
72
|
+
return path ? `${path} - ${title}` : title;
|
|
79
73
|
};
|
|
80
74
|
|
|
81
75
|
NProgress.configure({ showSpinner: false });
|
|
@@ -84,8 +78,6 @@ export function initPermission({
|
|
|
84
78
|
const handleUrlTokenParam = async (to, next, accessTokenKey, accessToken) => {
|
|
85
79
|
if (!to.query[accessTokenKey]) return false;
|
|
86
80
|
|
|
87
|
-
const newQuery = { ...to.query };
|
|
88
|
-
|
|
89
81
|
// 优先从地址栏获取token, 更新存储token值
|
|
90
82
|
if (accessToken && Uts.isFunction(dispatch)) {
|
|
91
83
|
try {
|
|
@@ -95,7 +87,8 @@ export function initPermission({
|
|
|
95
87
|
}
|
|
96
88
|
}
|
|
97
89
|
|
|
98
|
-
|
|
90
|
+
// 用解构 rest 移除 token 参数,避免修改原对象
|
|
91
|
+
const { [accessTokenKey]: _, ...newQuery } = to.query;
|
|
99
92
|
next({ path: to.path, query: newQuery, replace: true });
|
|
100
93
|
return true;
|
|
101
94
|
};
|
|
@@ -115,23 +108,38 @@ export function initPermission({
|
|
|
115
108
|
|
|
116
109
|
// 辅助函数:处理已认证用户的路由
|
|
117
110
|
const handleAuthenticatedRoute = async (to, next, permission) => {
|
|
118
|
-
//
|
|
111
|
+
// 已登录用户访问登录页
|
|
119
112
|
if (to.path === "/login") {
|
|
120
|
-
|
|
113
|
+
const { PMRedirectPath } = (await handleGetUserInfo()) || {};
|
|
114
|
+
const redirectPath = to.query.redirect;
|
|
115
|
+
|
|
116
|
+
if (redirectPath) {
|
|
117
|
+
// 查找 redirect 路由对应的权限
|
|
118
|
+
const matched = router.resolve(redirectPath)?.route;
|
|
119
|
+
const redirectPermission = matched?.meta?.permission;
|
|
120
|
+
// 无需权限 或 有权限,则走 redirect
|
|
121
|
+
if (!redirectPermission || checkPermission(redirectPermission)) {
|
|
122
|
+
return next({ path: redirectPath });
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// 否则跳到第一个有权限的页面
|
|
127
|
+
return next({ path: PMRedirectPath || "/" });
|
|
121
128
|
}
|
|
122
129
|
|
|
123
130
|
try {
|
|
124
131
|
// 获取用户信息
|
|
125
|
-
const { PMRedirectPath } = await handleGetUserInfo();
|
|
126
|
-
|
|
127
|
-
//
|
|
128
|
-
if (
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
132
|
+
const { PMRedirectPath } = (await handleGetUserInfo()) || {};
|
|
133
|
+
|
|
134
|
+
// 合并权限检查,避免重复调用 checkPermission
|
|
135
|
+
if (permission && !checkPermission(permission)) {
|
|
136
|
+
// 有兜底路径时优先跳转,否则跳 403
|
|
137
|
+
if (PMRedirectPath) {
|
|
138
|
+
return next({ path: PMRedirectPath });
|
|
139
|
+
}
|
|
140
|
+
if (!whiteSet.has(to.path)) {
|
|
141
|
+
return next({ path: "/error/403" });
|
|
142
|
+
}
|
|
135
143
|
}
|
|
136
144
|
|
|
137
145
|
next();
|
|
@@ -154,14 +162,13 @@ export function initPermission({
|
|
|
154
162
|
const Token = TokenService.getToken();
|
|
155
163
|
const accessTokenKey = TokenService.getUrlTokenKey();
|
|
156
164
|
const accessToken = TokenService.getUrlToken();
|
|
157
|
-
const {
|
|
158
|
-
const { permission } = meta || {};
|
|
165
|
+
const { permission } = to.meta || {};
|
|
159
166
|
|
|
160
167
|
// 设置页面标题
|
|
161
|
-
document.title = handlePageTitle(to.meta
|
|
168
|
+
document.title = handlePageTitle(to.meta?.title);
|
|
162
169
|
|
|
163
170
|
// 缓存页面路径(非白名单页面)
|
|
164
|
-
if (!
|
|
171
|
+
if (pagePathCacheKey && !whiteSet.has(to.path)) {
|
|
165
172
|
localStorage.setItem(pagePathCacheKey, window.location.href);
|
|
166
173
|
}
|
|
167
174
|
|
|
@@ -171,7 +178,7 @@ export function initPermission({
|
|
|
171
178
|
}
|
|
172
179
|
|
|
173
180
|
// 2. 检查白名单路径
|
|
174
|
-
if (
|
|
181
|
+
if (whiteSet.has(to.path)) {
|
|
175
182
|
return next();
|
|
176
183
|
}
|
|
177
184
|
|
package/module/REST.js
CHANGED
|
@@ -1,18 +1,71 @@
|
|
|
1
1
|
import axios from "axios";
|
|
2
2
|
import Uts from "./Uts.js";
|
|
3
3
|
import TokenService from "./TokenService.js";
|
|
4
|
+
import { resolveInternalServiceURL } from "./cjs/request-url-rules.cjs";
|
|
4
5
|
|
|
5
6
|
const baseURL = process.env.VUE_APP_BASE_API;
|
|
6
7
|
const { env } = Uts.getEnv() || {};
|
|
7
8
|
const isTestEnv = Uts.contain(["localhost", "infly-test"], env);
|
|
8
|
-
|
|
9
|
+
|
|
10
|
+
// 若接口地址是 localhost/127.0.0.1,则自动替换为当前页面访问主机。
|
|
11
|
+
// 协议、端口、路径保持不变,便于局域网联调时免改环境变量。
|
|
12
|
+
function remapLocalhostToCurrentHost(url) {
|
|
13
|
+
const normalized = Uts.normalizeEnvUrl(url);
|
|
14
|
+
if (!normalized) {
|
|
15
|
+
return normalized;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
if (typeof window === "undefined" || !window.location || !window.location.hostname) {
|
|
19
|
+
return normalized;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
try {
|
|
23
|
+
const parsed = new URL(normalized);
|
|
24
|
+
const isLocalHost = ["localhost", "127.0.0.1"].includes(parsed.hostname);
|
|
25
|
+
if (!isLocalHost) {
|
|
26
|
+
return normalized;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
parsed.hostname = window.location.hostname;
|
|
30
|
+
return parsed.toString();
|
|
31
|
+
} catch (e) {
|
|
32
|
+
return normalized;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// 解析 axios 最终使用的 baseURL。
|
|
37
|
+
// 优先级:config.baseURL > process.env.VUE_APP_BASE_API,再执行 localhost 主机替换。
|
|
38
|
+
function resolveServiceBaseURL(customBaseURL) {
|
|
39
|
+
const targetBaseURL = Uts.normalizeEnvUrl(customBaseURL || baseURL);
|
|
40
|
+
return remapLocalhostToCurrentHost(targetBaseURL);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* 对任意通知函数加去重包装
|
|
45
|
+
* @param {Function} fn - 原始通知函数,接受字符串或 { message, type, ... }
|
|
46
|
+
* @param {Number} ttl - 去重时间窗(ms),默认 500
|
|
47
|
+
* @returns {Function} 去重后的通知函数
|
|
48
|
+
*/
|
|
49
|
+
export function createNotifyDedup(fn, ttl = 500) {
|
|
50
|
+
const recentMsgs = new Set();
|
|
51
|
+
return function dedupedNotify(msgOrOptions) {
|
|
52
|
+
const message = typeof msgOrOptions === "string" ? msgOrOptions : msgOrOptions?.message;
|
|
53
|
+
if (message && recentMsgs.has(message)) return;
|
|
54
|
+
if (message) {
|
|
55
|
+
recentMsgs.add(message);
|
|
56
|
+
setTimeout(() => recentMsgs.delete(message), ttl);
|
|
57
|
+
}
|
|
58
|
+
return fn(msgOrOptions);
|
|
59
|
+
};
|
|
60
|
+
}
|
|
9
61
|
|
|
10
62
|
/**
|
|
11
63
|
* 创建封装的 axios 实例
|
|
12
64
|
* @param {Object} config 配置项
|
|
13
|
-
* @param {
|
|
65
|
+
* @param {String} config.getTokenFunc 获取 token 的 TokenService 方法名,默认 "getToken"
|
|
14
66
|
* @param {Function} config.onLogout 登出回调
|
|
15
|
-
* @param {
|
|
67
|
+
* @param {Object} config.notify Message-like 对象(如 ElementUI Message),传入后自动应用去重并构建 onNotify
|
|
68
|
+
* @param {Function} config.onNotify 自定义通知回调;若传入 Message-like 对象也可自动识别
|
|
16
69
|
* @returns {AxiosInstance}
|
|
17
70
|
*/
|
|
18
71
|
export function createService(config) {
|
|
@@ -22,10 +75,32 @@ export function createService(config) {
|
|
|
22
75
|
serviceField = defaultField,
|
|
23
76
|
logoutAction = "user/logout", // 退出登录的action方法
|
|
24
77
|
onLogout,
|
|
25
|
-
|
|
26
|
-
|
|
78
|
+
notify,
|
|
79
|
+
onNotify: rawOnNotify,
|
|
80
|
+
getTokenFunc = "getToken",
|
|
81
|
+
internalServiceURLRules = []
|
|
27
82
|
} = config || {};
|
|
28
|
-
|
|
83
|
+
// 统一在 REST 内部处理 baseURL,避免业务项目重复实现主机替换逻辑。
|
|
84
|
+
const resolvedBaseURL = resolveServiceBaseURL(customBaseURL);
|
|
85
|
+
const isProdAPI = Uts.contain(["https://api.sutpay.com"], resolvedBaseURL);
|
|
86
|
+
const service = axios.create({ baseURL: resolvedBaseURL });
|
|
87
|
+
|
|
88
|
+
// 统一处理 notify 与 onNotify:
|
|
89
|
+
// - 优先使用显式传入的 notify
|
|
90
|
+
// - 若 onNotify 是 Message-like 对象(带 .error/.success 等类型方法),也当作 notify 处理
|
|
91
|
+
// 两种写法都自动应用去重,拦截器与调用方 .catch() 共用同一个去重包装
|
|
92
|
+
const notifyTarget = notify || (rawOnNotify && typeof rawOnNotify["error"] === "function" ? rawOnNotify : null);
|
|
93
|
+
let onNotify = notifyTarget ? null : rawOnNotify;
|
|
94
|
+
|
|
95
|
+
if (notifyTarget) {
|
|
96
|
+
["success", "warning", "info", "error"].forEach((type) => {
|
|
97
|
+
if (typeof notifyTarget[type] === "function") {
|
|
98
|
+
notifyTarget[type] = createNotifyDedup(notifyTarget[type].bind(notifyTarget));
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
onNotify = ({ message, type = "error", duration }) =>
|
|
102
|
+
notifyTarget[type]?.(message) ?? notifyTarget({ message, type, duration });
|
|
103
|
+
}
|
|
29
104
|
|
|
30
105
|
/**
|
|
31
106
|
* 发送通知
|
|
@@ -61,9 +136,10 @@ export function createService(config) {
|
|
|
61
136
|
});
|
|
62
137
|
}
|
|
63
138
|
|
|
64
|
-
|
|
65
|
-
if (
|
|
66
|
-
config.url =
|
|
139
|
+
const internalServiceURL = resolveInternalServiceURL(config.url, internalServiceURLRules);
|
|
140
|
+
if (internalServiceURL) {
|
|
141
|
+
config.url = internalServiceURL.url;
|
|
142
|
+
config.baseURL = resolveServiceBaseURL(internalServiceURL.baseURL);
|
|
67
143
|
}
|
|
68
144
|
|
|
69
145
|
if (serviceField !== defaultField) {
|
|
@@ -83,54 +159,41 @@ export function createService(config) {
|
|
|
83
159
|
|
|
84
160
|
service.interceptors.response.use(
|
|
85
161
|
(response) => {
|
|
86
|
-
|
|
162
|
+
const { data } = response || {};
|
|
163
|
+
return Uts.transArrayBufferToObj(data);
|
|
87
164
|
},
|
|
88
165
|
(error) => {
|
|
89
166
|
const { response, request } = error || {};
|
|
90
167
|
const { status, data } = response || {};
|
|
168
|
+
const { error: bufferError } = Uts.transArrayBufferToObj(data) ?? {};
|
|
91
169
|
const { error: dataError, detail, message } = data || {};
|
|
170
|
+
const errorMsg = bufferError || dataError || detail || message || `请求失败(${status})`;
|
|
92
171
|
|
|
93
172
|
// 添加标识,表示错误已被拦截器处理
|
|
94
173
|
error.handledByInterceptor = true;
|
|
95
174
|
|
|
96
|
-
// HTTP
|
|
97
|
-
const
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
175
|
+
// HTTP 状态码 → 固定提示语映射(400 直接用后端返回的 errorMsg)
|
|
176
|
+
const STATUS_MESSAGES = {
|
|
177
|
+
400: errorMsg,
|
|
178
|
+
401: "登录信息已过期,请重新登录",
|
|
179
|
+
403: "您没有权限访问,请联系管理员",
|
|
180
|
+
500: errorMsg || "服务器内部错误,请联系开发人员",
|
|
181
|
+
502: "网关错误,请稍后重试或联系开发人员",
|
|
182
|
+
503: "服务暂时不可用,请稍后重试",
|
|
183
|
+
504: "网关超时,请稍后重试或联系开发人员"
|
|
104
184
|
};
|
|
105
185
|
|
|
106
|
-
//
|
|
107
|
-
const
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
handleNotify({
|
|
118
|
-
message: errorMsg,
|
|
119
|
-
type: "error"
|
|
120
|
-
});
|
|
121
|
-
} else if (request) {
|
|
122
|
-
// 请求已发送但无响应(网络问题)
|
|
123
|
-
handleNotify({
|
|
124
|
-
message: "网络请求失败,请检查网络连接",
|
|
125
|
-
type: "error"
|
|
126
|
-
});
|
|
127
|
-
} else {
|
|
128
|
-
// 请求配置错误
|
|
129
|
-
handleNotify({
|
|
130
|
-
message: error.message || "请求配置错误",
|
|
131
|
-
type: "error"
|
|
132
|
-
});
|
|
133
|
-
}
|
|
186
|
+
// 按优先级确定最终提示语,合并为一次 handleNotify 调用
|
|
187
|
+
const notifyMsg =
|
|
188
|
+
STATUS_MESSAGES[status] ??
|
|
189
|
+
(response ? errorMsg : null) ??
|
|
190
|
+
(request ? "网络请求失败,请检查网络连接" : null) ??
|
|
191
|
+
(error.message || "请求配置错误");
|
|
192
|
+
|
|
193
|
+
handleNotify({ message: notifyMsg, type: "error" });
|
|
194
|
+
|
|
195
|
+
// 401 副作用:自动登出(不受弹窗逻辑影响)
|
|
196
|
+
if (status === 401) handleLogout();
|
|
134
197
|
|
|
135
198
|
return Promise.reject(error);
|
|
136
199
|
}
|
package/module/Uts.js
CHANGED
|
@@ -7,6 +7,12 @@
|
|
|
7
7
|
// const _history = createHashHistory();
|
|
8
8
|
// console.log(_history);
|
|
9
9
|
|
|
10
|
+
const { deepMerge: deepMergeImpl } = require("./cjs/deep-merge.cjs");
|
|
11
|
+
const {
|
|
12
|
+
mergePageConfig: mergePageConfigImpl,
|
|
13
|
+
resolvePlatformPageConfig: resolvePlatformPageConfigImpl
|
|
14
|
+
} = require("./cjs/page-config.cjs");
|
|
15
|
+
|
|
10
16
|
let _getItem = Storage.prototype.getItem;
|
|
11
17
|
// import Uts from "./Uts";
|
|
12
18
|
let $state = {
|
|
@@ -81,6 +87,15 @@ let Uts = {
|
|
|
81
87
|
ce(text) {
|
|
82
88
|
global.console && global.console.error && global.console.error(text);
|
|
83
89
|
},
|
|
90
|
+
/**
|
|
91
|
+
* 规范化环境变量中的 URL 字符串
|
|
92
|
+
* 例如去除首尾空格和包裹引号:"'http://xx/'" -> "http://xx/"
|
|
93
|
+
*/
|
|
94
|
+
normalizeEnvUrl(url = "") {
|
|
95
|
+
return String(url)
|
|
96
|
+
.trim()
|
|
97
|
+
.replace(/^['"]|['"]$/g, "");
|
|
98
|
+
},
|
|
84
99
|
/**
|
|
85
100
|
* set class 动态设置类名
|
|
86
101
|
* @module condition
|
|
@@ -534,7 +549,7 @@ Filter.formatDate(1655740800000,'Y-m-d')
|
|
|
534
549
|
Uts.join()
|
|
535
550
|
''
|
|
536
551
|
*/
|
|
537
|
-
join(arr = [], symbol = "
|
|
552
|
+
join(arr = [], symbol = ",") {
|
|
538
553
|
if (Uts.notEmptyArray(arr)) {
|
|
539
554
|
return arr.join(symbol);
|
|
540
555
|
} else {
|
|
@@ -1295,11 +1310,15 @@ Uts.getEnv()
|
|
|
1295
1310
|
getEnv(string) {
|
|
1296
1311
|
let config = {};
|
|
1297
1312
|
let host = string || location.host;
|
|
1298
|
-
const
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1313
|
+
const projectName = process.env.VUE_APP_PROJECT_NAME;
|
|
1314
|
+
const projectConfigs = {
|
|
1315
|
+
"postal-benefits-platform-level": { reqModule: "management" }
|
|
1316
|
+
// 可继续添加其它项目配置
|
|
1317
|
+
};
|
|
1318
|
+
const projectConfig = {
|
|
1319
|
+
projectName,
|
|
1320
|
+
...(projectConfigs[projectName] || { reqModule: "admin" })
|
|
1321
|
+
};
|
|
1303
1322
|
|
|
1304
1323
|
config.rootDomain = (host.match(Uts.FINDDOMAINEXP) && host.match(Uts.FINDDOMAINEXP)[0]) || null;
|
|
1305
1324
|
config.env = "";
|
|
@@ -1683,35 +1702,13 @@ console.log(o1)
|
|
|
1683
1702
|
* @returns {Object} 合并后的目标对象
|
|
1684
1703
|
*/
|
|
1685
1704
|
deepMerge(target, source, overwrite = false) {
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
if (Array.isArray(sourceValue)) {
|
|
1694
|
-
// 处理数组:如果不覆盖且目标已存在,保持原数组
|
|
1695
|
-
if (!overwrite && targetValue !== undefined) {
|
|
1696
|
-
return;
|
|
1697
|
-
}
|
|
1698
|
-
target[key] = [...sourceValue];
|
|
1699
|
-
} else if (sourceValue && typeof sourceValue === "object") {
|
|
1700
|
-
// 处理对象:递归合并
|
|
1701
|
-
if (!target[key] || typeof target[key] !== "object") {
|
|
1702
|
-
target[key] = {};
|
|
1703
|
-
}
|
|
1704
|
-
Uts.deepMerge(target[key], sourceValue, overwrite);
|
|
1705
|
-
} else {
|
|
1706
|
-
// 处理基本类型:如果不覆盖且目标已存在,跳过
|
|
1707
|
-
if (!overwrite && targetValue !== undefined) {
|
|
1708
|
-
return;
|
|
1709
|
-
}
|
|
1710
|
-
target[key] = sourceValue;
|
|
1711
|
-
}
|
|
1712
|
-
});
|
|
1713
|
-
|
|
1714
|
-
return target;
|
|
1705
|
+
return deepMergeImpl(target, source, overwrite);
|
|
1706
|
+
},
|
|
1707
|
+
mergePageConfig(...sources) {
|
|
1708
|
+
return mergePageConfigImpl(...sources);
|
|
1709
|
+
},
|
|
1710
|
+
resolvePlatformPageConfig(pageConfig, platform, options) {
|
|
1711
|
+
return resolvePlatformPageConfigImpl(pageConfig, platform, options);
|
|
1715
1712
|
},
|
|
1716
1713
|
/**
|
|
1717
1714
|
* 转换字符串为小写
|
|
@@ -3917,6 +3914,21 @@ false
|
|
|
3917
3914
|
isNull(value) {
|
|
3918
3915
|
return value === null;
|
|
3919
3916
|
},
|
|
3917
|
+
/**
|
|
3918
|
+
* 判断接口字段是否有实际返回值;0 和 false 是有效值,仅排除 undefined、null、空字符串。
|
|
3919
|
+
* @module checkType
|
|
3920
|
+
* @todo Uts.isPresentValue
|
|
3921
|
+
* @param {*} value 要检查的值
|
|
3922
|
+
* @return {Boolean}
|
|
3923
|
+
* @example
|
|
3924
|
+
* Uts.isPresentValue(0)
|
|
3925
|
+
true
|
|
3926
|
+
Uts.isPresentValue('')
|
|
3927
|
+
false
|
|
3928
|
+
*/
|
|
3929
|
+
isPresentValue(value) {
|
|
3930
|
+
return value !== undefined && value !== null && value !== "";
|
|
3931
|
+
},
|
|
3920
3932
|
/**
|
|
3921
3933
|
* 检查数值是否为NaN
|
|
3922
3934
|
* @module checkType
|
|
@@ -3925,9 +3937,9 @@ false
|
|
|
3925
3937
|
* @return {Boolean}
|
|
3926
3938
|
* @example
|
|
3927
3939
|
* Uts.isNaN({})
|
|
3928
|
-
false
|
|
3929
|
-
Uts.isNaN(NaN)
|
|
3930
|
-
true
|
|
3940
|
+
false
|
|
3941
|
+
Uts.isNaN(NaN)
|
|
3942
|
+
true
|
|
3931
3943
|
*/
|
|
3932
3944
|
isNaN(value) {
|
|
3933
3945
|
return value !== value;
|
|
@@ -3940,9 +3952,9 @@ true
|
|
|
3940
3952
|
* @return {Boolean} true or false
|
|
3941
3953
|
* @example
|
|
3942
3954
|
* Uts.isString('w')
|
|
3943
|
-
true
|
|
3944
|
-
Uts.isString(1)
|
|
3945
|
-
false
|
|
3955
|
+
true
|
|
3956
|
+
Uts.isString(1)
|
|
3957
|
+
false
|
|
3946
3958
|
*/
|
|
3947
3959
|
isString(value) {
|
|
3948
3960
|
return typeof value === "string";
|
|
@@ -3955,9 +3967,9 @@ false
|
|
|
3955
3967
|
* @return {Boolean} true or false
|
|
3956
3968
|
* @example
|
|
3957
3969
|
* Uts.isDate({})
|
|
3958
|
-
false
|
|
3959
|
-
Uts.isDate(new Date())
|
|
3960
|
-
true
|
|
3970
|
+
false
|
|
3971
|
+
Uts.isDate(new Date())
|
|
3972
|
+
true
|
|
3961
3973
|
*/
|
|
3962
3974
|
isDate(value) {
|
|
3963
3975
|
return value && value.constructor === Date;
|
|
@@ -3971,9 +3983,9 @@ true
|
|
|
3971
3983
|
* @return {Boolean} true or false
|
|
3972
3984
|
* @example
|
|
3973
3985
|
* Uts.isWaitingObject({})
|
|
3974
|
-
false
|
|
3975
|
-
Uts.isWaitingObject(new Waiting())
|
|
3976
|
-
true
|
|
3986
|
+
false
|
|
3987
|
+
Uts.isWaitingObject(new Waiting())
|
|
3988
|
+
true
|
|
3977
3989
|
*/
|
|
3978
3990
|
isWaitingObject(obj) {
|
|
3979
3991
|
return obj && (obj instanceof Waiting || obj.endpoint || Uts.isFunction(obj.then));
|
|
@@ -3986,9 +3998,9 @@ true
|
|
|
3986
3998
|
* @return {Boolean}
|
|
3987
3999
|
* @example
|
|
3988
4000
|
* Uts.isError({})
|
|
3989
|
-
false
|
|
3990
|
-
Uts.isError(new Error())
|
|
3991
|
-
true
|
|
4001
|
+
false
|
|
4002
|
+
Uts.isError(new Error())
|
|
4003
|
+
true
|
|
3992
4004
|
*/
|
|
3993
4005
|
isError: function (obj) {
|
|
3994
4006
|
return obj && obj instanceof Error;
|
|
@@ -6352,10 +6364,10 @@ Uts.getParentByPath(item,treeData,{ pathFieldName: "__path", treeChildProp: "chi
|
|
|
6352
6364
|
* @returns
|
|
6353
6365
|
*/
|
|
6354
6366
|
getPMBySettings: function (code, settings) {
|
|
6355
|
-
const { permissionsCodeKey } = settings || {};
|
|
6367
|
+
const { permissionsCodeKey, notVerifyPMCodes } = settings || {};
|
|
6356
6368
|
const permissionCodes = Uts.storage.get(permissionsCodeKey) || [];
|
|
6357
6369
|
|
|
6358
|
-
return Uts.contain(permissionCodes, code);
|
|
6370
|
+
return Uts.contain(permissionCodes, code) || Uts.contain(notVerifyPMCodes, code);
|
|
6359
6371
|
},
|
|
6360
6372
|
/**
|
|
6361
6373
|
* 过滤路由权限
|
|
@@ -7227,6 +7239,32 @@ Uts.getSecondDomain('http://www.baidu.com')
|
|
|
7227
7239
|
return path.split(".").reduce(function (acc, part) {
|
|
7228
7240
|
return acc ? acc[part] : undefined;
|
|
7229
7241
|
}, obj);
|
|
7242
|
+
},
|
|
7243
|
+
transArrayBufferToObj(data) {
|
|
7244
|
+
if (!(data instanceof ArrayBuffer)) {
|
|
7245
|
+
return data;
|
|
7246
|
+
}
|
|
7247
|
+
|
|
7248
|
+
try {
|
|
7249
|
+
const jsonStr = new TextDecoder().decode(data);
|
|
7250
|
+
return JSON.parse(jsonStr);
|
|
7251
|
+
} catch {
|
|
7252
|
+
return data;
|
|
7253
|
+
}
|
|
7254
|
+
},
|
|
7255
|
+
/**
|
|
7256
|
+
* 将字符串按分隔符转换为数组
|
|
7257
|
+
* @param {String|Array} value - 输入值
|
|
7258
|
+
* @returns {Array} - 转换后的数组
|
|
7259
|
+
*/
|
|
7260
|
+
convertToArray(value) {
|
|
7261
|
+
if (Array.isArray(value)) {
|
|
7262
|
+
return value;
|
|
7263
|
+
}
|
|
7264
|
+
return String(value)
|
|
7265
|
+
.split(/[,\s\uFF0C]+/)
|
|
7266
|
+
.map((s) => s.trim())
|
|
7267
|
+
.filter(Boolean);
|
|
7230
7268
|
}
|
|
7231
7269
|
};
|
|
7232
7270
|
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 深度合并对象
|
|
3
|
+
* @param {Object} target - 目标对象
|
|
4
|
+
* @param {Object} source - 源对象
|
|
5
|
+
* @param {boolean} overwrite - 是否覆盖已存在的属性,默认 false
|
|
6
|
+
* @returns {Object} 合并后的目标对象
|
|
7
|
+
*/
|
|
8
|
+
function deepMerge(target, source, overwrite = false) {
|
|
9
|
+
if (!source || typeof source !== "object") return target;
|
|
10
|
+
if (!target || typeof target !== "object") return source;
|
|
11
|
+
|
|
12
|
+
Object.keys(source).forEach((key) => {
|
|
13
|
+
const sourceValue = source[key];
|
|
14
|
+
const targetValue = target[key];
|
|
15
|
+
|
|
16
|
+
if (Array.isArray(sourceValue)) {
|
|
17
|
+
if (!overwrite && targetValue !== undefined) {
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
target[key] = [...sourceValue];
|
|
21
|
+
} else if (sourceValue && typeof sourceValue === "object") {
|
|
22
|
+
if (!target[key] || typeof target[key] !== "object") {
|
|
23
|
+
target[key] = {};
|
|
24
|
+
}
|
|
25
|
+
deepMerge(target[key], sourceValue, overwrite);
|
|
26
|
+
} else if (!overwrite && targetValue !== undefined) {
|
|
27
|
+
return;
|
|
28
|
+
} else {
|
|
29
|
+
target[key] = sourceValue;
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
return target;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
module.exports = {
|
|
37
|
+
deepMerge
|
|
38
|
+
};
|