@jiangood/open-admin 2.5.2 → 2.5.6
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/package.json +3 -2
- package/src/.umi-production/appData.json +78 -77
- package/src/.umi-production/core/route.tsx +6 -6
- package/src/framework/GlobalData.d.ts +8 -0
- package/src/framework/GlobalData.js +33 -0
- package/src/framework/{components/system → biz}/HasPerm.tsx +1 -1
- package/src/framework/{components/OrgTree/index.tsx → biz/OrgTree.tsx} +12 -2
- package/src/framework/{components/system/ButtonList.tsx → biz/PermActions.tsx} +6 -5
- package/src/framework/{components/RoleTree/index.tsx → biz/RoleTree.tsx} +13 -3
- package/src/framework/{components/system → biz}/index.tsx +4 -2
- package/src/framework/components/ContextMenu/index.tsx +1 -1
- package/src/framework/components/DownloadModal/index.tsx +332 -0
- package/src/framework/components/ErrorBoundary/index.tsx +18 -0
- package/src/framework/components/NamedIcon/{index.jsx → index.tsx} +8 -3
- package/src/framework/components/Page/index.tsx +2 -2
- package/src/framework/components/ProTable/index.tsx +3 -10
- package/src/framework/components/index.ts +2 -6
- package/src/framework/fields/BaseRemoteSelect/index.tsx +2 -3
- package/src/framework/fields/FieldEditor/index.tsx +35 -44
- package/src/framework/fields/FieldNumberRange/index.tsx +2 -2
- package/src/framework/fields/FieldRemoteTree/index.tsx +1 -1
- package/src/framework/fields/FieldTable/index.tsx +20 -22
- package/src/framework/fields/FieldUploadFile/index.tsx +3 -3
- package/src/framework/fields/index.ts +1 -3
- package/src/framework/index.ts +2 -0
- package/src/framework/utils/ArrayUtils.d.ts +6 -0
- package/src/framework/utils/ArrayUtils.js +30 -0
- package/src/framework/utils/DateUtils.d.ts +20 -0
- package/src/framework/utils/DateUtils.js +81 -0
- package/src/framework/utils/DeviceUtils.d.ts +3 -0
- package/src/framework/utils/DeviceUtils.js +10 -0
- package/src/framework/utils/EventBus.d.ts +6 -0
- package/src/framework/utils/EventBus.js +51 -0
- package/src/framework/utils/MessageUtils.d.ts +10 -0
- package/src/framework/utils/MessageUtils.js +43 -0
- package/src/framework/utils/ObjectUtils.d.ts +14 -0
- package/src/framework/utils/ObjectUtils.js +12 -0
- package/src/framework/utils/StorageUtils.d.ts +4 -0
- package/src/framework/utils/{StorageUtils.ts → StorageUtils.js} +7 -11
- package/src/framework/utils/StringUtils.d.ts +17 -0
- package/src/framework/utils/StringUtils.js +107 -0
- package/src/framework/utils/TreeUtils.d.ts +13 -0
- package/src/framework/utils/TreeUtils.js +63 -0
- package/src/framework/utils/UrlUtils.d.ts +6 -0
- package/src/framework/utils/UrlUtils.js +71 -0
- package/src/framework/utils/index.ts +1 -5
- package/src/framework/utils/system/DictUtils.d.ts +20 -0
- package/src/framework/utils/system/DictUtils.js +31 -0
- package/src/framework/utils/system/FormRegistry.d.ts +8 -0
- package/src/framework/utils/system/FormRegistry.js +31 -0
- package/src/framework/utils/system/HttpUtils.d.ts +14 -0
- package/src/framework/utils/system/HttpUtils.js +87 -0
- package/src/framework/utils/system/PageUtils.d.ts +14 -0
- package/src/framework/utils/system/PageUtils.js +59 -0
- package/src/framework/utils/system/PermUtils.d.ts +5 -0
- package/src/framework/utils/system/PermUtils.js +27 -0
- package/src/framework/utils/system/ThemeUtils.d.ts +6 -0
- package/src/framework/utils/system/{ThemeUtils.ts → ThemeUtils.js} +19 -19
- package/src/framework/utils/system/index.ts +1 -2
- package/src/framework/views/ViewFile/index.tsx +1 -2
- package/src/framework/views/ViewImage/index.tsx +3 -3
- package/src/framework/views/{ViewBooleanEnableDisable → ViewSwitch}/index.tsx +1 -1
- package/src/framework/views/index.ts +3 -4
- package/src/layouts/admin/HeaderRight.jsx +32 -44
- package/src/layouts/admin/index.jsx +5 -29
- package/src/layouts/index.jsx +26 -17
- package/src/pages/about.jsx +24 -4
- package/src/pages/{userCenter/ChangePassword.jsx → account/changePassword.jsx} +1 -2
- package/src/pages/{userCenter → account}/index.jsx +2 -6
- package/src/pages/forceUpdatePwd.jsx +89 -0
- package/src/pages/login.jsx +5 -5
- package/src/pages/system/dict/index.jsx +6 -6
- package/src/pages/system/file/index.jsx +4 -4
- package/src/pages/system/job/index.jsx +7 -3
- package/src/pages/system/org/index.jsx +2 -2
- package/src/pages/system/role/index.jsx +4 -4
- package/src/pages/system/role/{perm.jsx → rolePerm.jsx} +2 -2
- package/src/pages/system/user/index.jsx +4 -4
- package/src/framework/components/DownloadFileButton/index.tsx +0 -33
- package/src/framework/components/NamedIcon/index.d.ts +0 -7
- package/src/framework/components/ProTable/utils/index.ts +0 -62
- package/src/framework/fields/FieldRemoteSelectMultipleInline/index.tsx +0 -33
- package/src/framework/fields/FieldRemoteTreeSelectMultiple/index.tsx +0 -43
- package/src/framework/utils/ArrayUtils.ts +0 -186
- package/src/framework/utils/ColorsUtils.ts +0 -378
- package/src/framework/utils/DateUtils.ts +0 -187
- package/src/framework/utils/DeviceUtils.ts +0 -46
- package/src/framework/utils/DomUtils.ts +0 -50
- package/src/framework/utils/EventBusUtils.ts +0 -143
- package/src/framework/utils/Logger.ts +0 -40
- package/src/framework/utils/MessageUtils.tsx +0 -90
- package/src/framework/utils/ObjectUtils.ts +0 -118
- package/src/framework/utils/StringUtils.ts +0 -436
- package/src/framework/utils/TreeUtils.ts +0 -251
- package/src/framework/utils/UrlUtils.ts +0 -152
- package/src/framework/utils/UuidUtils.ts +0 -88
- package/src/framework/utils/ValidateUtils.ts +0 -28
- package/src/framework/utils/system/DictUtils.ts +0 -96
- package/src/framework/utils/system/FormRegistryUtils.ts +0 -76
- package/src/framework/utils/system/HttpUtils.ts +0 -251
- package/src/framework/utils/system/PageUtils.ts +0 -163
- package/src/framework/utils/system/PermUtils.ts +0 -79
- package/src/framework/utils/system/SysUtils.ts +0 -105
- package/src/framework/views/ViewProcessInstanceProgress/index.tsx +0 -98
- package/src/framework/views/ViewProcessInstanceProgressButton/index.tsx +0 -23
- package/src/pages/userCenter/message.jsx +0 -105
- /package/src/framework/{components → views}/ViewRange/index.tsx +0 -0
- /package/src/pages/system/user/{UserPerm.jsx → userPerm.jsx} +0 -0
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
export class StringUtils {
|
|
2
|
+
|
|
3
|
+
static ISO_SPLITTER = "/";
|
|
4
|
+
|
|
5
|
+
static removePrefix(str, ch) {
|
|
6
|
+
if (str != null && str.startsWith(ch)) {
|
|
7
|
+
return str.substring(ch.length);
|
|
8
|
+
}
|
|
9
|
+
return str ?? '';
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
static removeSuffix(str, ch) {
|
|
13
|
+
if (str != null && str.endsWith(ch)) {
|
|
14
|
+
return str.substring(0, str.length - ch.length);
|
|
15
|
+
}
|
|
16
|
+
return str ?? '';
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
static random(length) {
|
|
20
|
+
const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
|
|
21
|
+
let result = '';
|
|
22
|
+
for (let i = 0; i < length; i++) {
|
|
23
|
+
result += characters.charAt(Math.floor(Math.random() * characters.length));
|
|
24
|
+
}
|
|
25
|
+
return result;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
static contains(str, subStr) {
|
|
29
|
+
if (!str) return false;
|
|
30
|
+
return str.includes(subStr);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
static subAfter(source, str) {
|
|
34
|
+
if (source == null) return '';
|
|
35
|
+
const index = source.indexOf(str);
|
|
36
|
+
return index === -1 ? source : source.substring(index + str.length);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
static subAfterLast(source, str) {
|
|
40
|
+
if (source == null) return '';
|
|
41
|
+
const index = source.lastIndexOf(str);
|
|
42
|
+
return index === -1 ? source : source.substring(index + str.length);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
static subBefore(str, sub) {
|
|
46
|
+
if (str == null) return "";
|
|
47
|
+
const index = str.indexOf(sub);
|
|
48
|
+
return index === -1 ? str : str.substring(0, index);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
static pad(input, totalLen, padChar = '0') {
|
|
52
|
+
if (input == null) return padChar.repeat(totalLen);
|
|
53
|
+
let str = String(input);
|
|
54
|
+
const charsNeeded = totalLen - str.length;
|
|
55
|
+
if (charsNeeded > 0) {
|
|
56
|
+
str = padChar.repeat(charsNeeded) + str;
|
|
57
|
+
}
|
|
58
|
+
return str;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
static getWidth(str) {
|
|
62
|
+
if (str == null || str.length === 0) return 0;
|
|
63
|
+
return str.split('').reduce((pre, cur) => {
|
|
64
|
+
const charCode = cur.charCodeAt(0);
|
|
65
|
+
return pre + (charCode >= 0 && charCode <= 128 ? 1 : 2);
|
|
66
|
+
}, 0);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
static cutByWidth(str, maxWidth) {
|
|
70
|
+
let showLength = 0;
|
|
71
|
+
return str.split('').reduce((pre, cur) => {
|
|
72
|
+
const charCode = cur.charCodeAt(0);
|
|
73
|
+
const charWidth = (charCode >= 0 && charCode <= 128) ? 1 : 2;
|
|
74
|
+
if (showLength + charWidth <= maxWidth) {
|
|
75
|
+
showLength += charWidth;
|
|
76
|
+
return pre + cur;
|
|
77
|
+
}
|
|
78
|
+
return pre;
|
|
79
|
+
}, '');
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
static ellipsis(str, len, suffix = '...') {
|
|
83
|
+
if (str == null) return '';
|
|
84
|
+
if (!StringUtils.isString(str)) return '';
|
|
85
|
+
if (str.length * 2 < len) return str;
|
|
86
|
+
const fullLength = StringUtils.getWidth(str);
|
|
87
|
+
if (fullLength <= len) return str;
|
|
88
|
+
return StringUtils.cutByWidth(str, len) + suffix;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
static isString(value) {
|
|
92
|
+
return typeof value === 'string';
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
static split(str, sp) {
|
|
96
|
+
if (str == null || str.length === 0) return [];
|
|
97
|
+
if (Array.isArray(str)) return str;
|
|
98
|
+
return str.split(sp);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
static join(arr, sp) {
|
|
102
|
+
if (arr == null || !Array.isArray(arr)) {
|
|
103
|
+
return '';
|
|
104
|
+
}
|
|
105
|
+
return arr.join(sp);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export interface TreeNode<T = any> {
|
|
2
|
+
id: string | number;
|
|
3
|
+
pid: string | number | null;
|
|
4
|
+
children?: TreeNode<T>[];
|
|
5
|
+
[key: string]: any;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export class TreeUtils {
|
|
9
|
+
static walk<T extends TreeNode>(tree: T[], callback: (node: T) => void): void;
|
|
10
|
+
static findByKey<T extends TreeNode>(key: string | number, list: T[], keyName?: keyof T | 'id'): T | undefined;
|
|
11
|
+
static flattenTree<T extends TreeNode>(treeNodeList: T[]): T[];
|
|
12
|
+
static getKeyList<T extends TreeNode>(tree: T[], value: string | number): (string | number)[];
|
|
13
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
export class TreeUtils {
|
|
2
|
+
static walk(tree, callback) {
|
|
3
|
+
if (tree == null) return;
|
|
4
|
+
for (const node of tree) {
|
|
5
|
+
callback(node);
|
|
6
|
+
if (node.children && node.children.length > 0) {
|
|
7
|
+
TreeUtils.walk(node.children, callback);
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
static findByKey(key, list, keyName = 'id') {
|
|
13
|
+
for (const item of list) {
|
|
14
|
+
if (item[keyName] === key) return item;
|
|
15
|
+
if (item.children && item.children.length) {
|
|
16
|
+
const rs = TreeUtils.findByKey(key, item.children, keyName);
|
|
17
|
+
if (rs) return rs;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
return undefined;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
static _getChild(treeNode, buffer) {
|
|
24
|
+
if (treeNode.children != null && treeNode.children.length > 0) {
|
|
25
|
+
treeNode.children.forEach((c) => {
|
|
26
|
+
buffer.push(c);
|
|
27
|
+
TreeUtils._getChild(c, buffer);
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
return buffer;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
static flattenTree(treeNodeList) {
|
|
34
|
+
const buffer = [];
|
|
35
|
+
if (treeNodeList != null) {
|
|
36
|
+
treeNodeList.forEach((t) => {
|
|
37
|
+
buffer.push(t);
|
|
38
|
+
TreeUtils._getChild(t, buffer);
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
return buffer;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
static getKeyList(tree, value) {
|
|
45
|
+
const list = TreeUtils.flattenTree(tree);
|
|
46
|
+
const map = new Map();
|
|
47
|
+
list.forEach((t) => {
|
|
48
|
+
const key = t.key || t.id;
|
|
49
|
+
map.set(key, t);
|
|
50
|
+
});
|
|
51
|
+
const targetNode = map.get(value);
|
|
52
|
+
if (targetNode == null) return [];
|
|
53
|
+
const keys = [targetNode.key || targetNode.id];
|
|
54
|
+
let parentKey = targetNode.parentKey || targetNode.pid;
|
|
55
|
+
while (parentKey != null) {
|
|
56
|
+
const parent = map.get(parentKey);
|
|
57
|
+
if (parent == null) break;
|
|
58
|
+
keys.push(parent.key || parent.id);
|
|
59
|
+
parentKey = parent.parentKey || parent.pid;
|
|
60
|
+
}
|
|
61
|
+
return keys.reverse();
|
|
62
|
+
}
|
|
63
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export class UrlUtils {
|
|
2
|
+
static getParams(url?: string | null): Record<string, string>;
|
|
3
|
+
static setParam(url: string, key: string, value: string | number | boolean | null | undefined): string;
|
|
4
|
+
static getWebsocketBaseUrl(): string;
|
|
5
|
+
static contextPath(path: string): string;
|
|
6
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import {StringUtils} from './StringUtils';
|
|
2
|
+
|
|
3
|
+
export class UrlUtils {
|
|
4
|
+
static getParams(url = null) {
|
|
5
|
+
let targetUrl;
|
|
6
|
+
if (url === null || url === undefined) {
|
|
7
|
+
targetUrl = location.href;
|
|
8
|
+
} else {
|
|
9
|
+
targetUrl = url;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
if (!StringUtils.contains(targetUrl, '?')) return {};
|
|
13
|
+
const search = StringUtils.subAfter(targetUrl, '?');
|
|
14
|
+
const params = new URLSearchParams(search);
|
|
15
|
+
const result = {};
|
|
16
|
+
for (const [key, value] of params.entries()) {
|
|
17
|
+
result[key] = value;
|
|
18
|
+
}
|
|
19
|
+
return result;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
static getPathname(url) {
|
|
23
|
+
if (!url) return null;
|
|
24
|
+
return StringUtils.subBefore(url, '?');
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
static paramsToSearch(params) {
|
|
28
|
+
if (!params) return "";
|
|
29
|
+
const buffer = [];
|
|
30
|
+
for (const k in params) {
|
|
31
|
+
if (Object.prototype.hasOwnProperty.call(params, k)) {
|
|
32
|
+
const v = params[k];
|
|
33
|
+
if (v !== null && v !== undefined) {
|
|
34
|
+
buffer.push(`${k}=${v}`);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return buffer.join('&');
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
static setParam(url, key, value) {
|
|
42
|
+
const currentParams = this.getParams(url);
|
|
43
|
+
if (value === null || value === undefined) {
|
|
44
|
+
delete currentParams[key];
|
|
45
|
+
} else {
|
|
46
|
+
currentParams[key] = String(value);
|
|
47
|
+
}
|
|
48
|
+
const pathname = this.getPathname(url);
|
|
49
|
+
const newSearch = this.paramsToSearch(currentParams);
|
|
50
|
+
if (newSearch.length > 0) {
|
|
51
|
+
return `${pathname}?${newSearch}`;
|
|
52
|
+
}
|
|
53
|
+
return pathname || url;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* 根据当前页面协议和主机名构建 WebSocket 基础 URL
|
|
58
|
+
*/
|
|
59
|
+
static getWebsocketBaseUrl() {
|
|
60
|
+
const protocol = location.protocol === 'http:' ? 'ws:' : 'wss:';
|
|
61
|
+
return `${protocol}//${location.host}`;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* 为路径添加 SERVLET_CONTEXT 前缀
|
|
66
|
+
*/
|
|
67
|
+
static contextPath(path) {
|
|
68
|
+
const base = (typeof SERVLET_CONTEXT !== 'undefined' && SERVLET_CONTEXT) || '';
|
|
69
|
+
return base + path;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
@@ -2,14 +2,10 @@ export * from "./DateUtils";
|
|
|
2
2
|
export * from "./ArrayUtils";
|
|
3
3
|
export * from "./UrlUtils"
|
|
4
4
|
export * from "./StringUtils"
|
|
5
|
-
export * from "./
|
|
6
|
-
export * from "./ColorsUtils"
|
|
7
|
-
export * from "./DomUtils"
|
|
8
|
-
export * from "./UuidUtils";
|
|
5
|
+
export * from "./EventBus";
|
|
9
6
|
export * from "./TreeUtils";
|
|
10
7
|
export * from './StorageUtils'
|
|
11
8
|
export * from './DeviceUtils'
|
|
12
9
|
export * from './ObjectUtils'
|
|
13
|
-
export * from './ValidateUtils'
|
|
14
10
|
export * from './system'
|
|
15
11
|
export * from './MessageUtils'
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import {Tag} from 'antd';
|
|
3
|
+
|
|
4
|
+
export interface DictItem {
|
|
5
|
+
code: string | number;
|
|
6
|
+
label: string;
|
|
7
|
+
color?: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export interface DictOption {
|
|
11
|
+
value: string | number;
|
|
12
|
+
label: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export class DictUtils {
|
|
16
|
+
static dictList(code: string): DictItem[];
|
|
17
|
+
static dictOptions(typeCode: string): DictOption[];
|
|
18
|
+
static dictLabel(typeCode: string, code: string | number): string | undefined;
|
|
19
|
+
static dictTag(typeCode: string, code: string | number): React.ReactElement | string | null;
|
|
20
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import {GlobalData} from '../../GlobalData';
|
|
2
|
+
import {Tag} from 'antd';
|
|
3
|
+
import React from 'react';
|
|
4
|
+
|
|
5
|
+
export class DictUtils {
|
|
6
|
+
static dictList(code) {
|
|
7
|
+
const info = GlobalData.getDictInfo();
|
|
8
|
+
if (!info) return [];
|
|
9
|
+
return info.filter(e => e.typeCode === code);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
static dictOptions(typeCode) {
|
|
13
|
+
const list = DictUtils.dictList(typeCode);
|
|
14
|
+
return list.map(i => ({ value: i.code, label: i.label }));
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
static dictLabel(typeCode, code) {
|
|
18
|
+
const items = DictUtils.dictList(typeCode);
|
|
19
|
+
const item = items.find(i => i.code === code);
|
|
20
|
+
return item ? item.label : undefined;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
static dictTag(typeCode, code) {
|
|
24
|
+
if (typeCode == null || code == null) return null;
|
|
25
|
+
const item = DictUtils.dictList(typeCode).find(i => i.code === code);
|
|
26
|
+
if (item == null) return null;
|
|
27
|
+
const {label, color} = item;
|
|
28
|
+
if (color == null) return label;
|
|
29
|
+
return React.createElement(Tag, {color: color.toLowerCase()}, label);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
export class FormRegistry {
|
|
4
|
+
static register(formKey: string, formComponent: React.ComponentType<any>): void;
|
|
5
|
+
static get(formKey: string): React.ComponentType<any> | null;
|
|
6
|
+
static has(formKey: string): boolean;
|
|
7
|
+
static getAllKeys(): string[];
|
|
8
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
|
|
3
|
+
export class FormRegistry {
|
|
4
|
+
static forms = new Map();
|
|
5
|
+
|
|
6
|
+
static register(formKey, formComponent) {
|
|
7
|
+
if (!formKey || !formComponent) {
|
|
8
|
+
throw new Error("表单 Key 和组件不能为空!");
|
|
9
|
+
}
|
|
10
|
+
if (FormRegistry.forms.has(formKey)) {
|
|
11
|
+
console.warn(`表单 "${formKey}" 已存在,将被覆盖!`);
|
|
12
|
+
}
|
|
13
|
+
FormRegistry.forms.set(formKey, formComponent);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
static get(formKey) {
|
|
17
|
+
const formComponent = FormRegistry.forms.get(formKey);
|
|
18
|
+
if (!formComponent) {
|
|
19
|
+
console.warn(`表单 "${formKey}" 未注册!`);
|
|
20
|
+
}
|
|
21
|
+
return formComponent ?? null;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
static has(formKey) {
|
|
25
|
+
return FormRegistry.forms.has(formKey);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
static getAllKeys() {
|
|
29
|
+
return Array.from(FormRegistry.forms.keys());
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import {AxiosRequestConfig} from "axios";
|
|
2
|
+
|
|
3
|
+
declare const SERVLET_CONTEXT: string | undefined;
|
|
4
|
+
|
|
5
|
+
interface RequestOptions extends AxiosRequestConfig {
|
|
6
|
+
showError?: boolean;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export class HttpUtils {
|
|
10
|
+
static coreRequest<T = any>(config: RequestOptions, transformData?: boolean): Promise<T>;
|
|
11
|
+
static get<T = any>(url: string, params?: any, options?: Partial<RequestOptions>): Promise<T>;
|
|
12
|
+
static post<T = any>(url: string, data?: any, params?: any, options?: Partial<RequestOptions>): Promise<T>;
|
|
13
|
+
static postForm<T = any>(url: string, data: any, options?: Partial<RequestOptions>): Promise<T>;
|
|
14
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import axios from "axios";
|
|
2
|
+
import qs from 'qs';
|
|
3
|
+
import {PageUtils} from "./PageUtils";
|
|
4
|
+
import {MessageUtils} from "../MessageUtils";
|
|
5
|
+
|
|
6
|
+
const axiosInstance = axios.create({
|
|
7
|
+
baseURL: (typeof SERVLET_CONTEXT !== 'undefined' && SERVLET_CONTEXT) || '',
|
|
8
|
+
withCredentials: true,
|
|
9
|
+
headers: { 'Content-Type': 'application/json' },
|
|
10
|
+
paramsSerializer: (params) => qs.stringify(params, {indices: false})
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
export class HttpUtils {
|
|
14
|
+
static coreRequest(config, transformData = true) {
|
|
15
|
+
const url = config.url;
|
|
16
|
+
config.url = url.startsWith('admin') ? '/' + url : url;
|
|
17
|
+
|
|
18
|
+
return new Promise((resolve, reject) => {
|
|
19
|
+
axiosInstance(config).then((response) => {
|
|
20
|
+
const body = response.data;
|
|
21
|
+
let {success, message, data} = body;
|
|
22
|
+
if (success == undefined) {
|
|
23
|
+
resolve(response);
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
if (!success) {
|
|
27
|
+
console.error(`[HttpUtils] 请求失败: ${url}`, {code: body.code, message, data: body});
|
|
28
|
+
if (config.showError !== false) {
|
|
29
|
+
MessageUtils.error(message || '操作失败');
|
|
30
|
+
}
|
|
31
|
+
reject(message || '操作失败');
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
if (message) {
|
|
35
|
+
MessageUtils.success(message);
|
|
36
|
+
}
|
|
37
|
+
resolve(transformData ? data : response);
|
|
38
|
+
}).catch((e) => {
|
|
39
|
+
console.error(`[HttpUtils] 请求异常: ${url}`, e);
|
|
40
|
+
if (axios.isAxiosError(e) && e.response?.status === 401) {
|
|
41
|
+
MessageUtils.confirm('登录已过期,请重新登录').then(() => {
|
|
42
|
+
PageUtils.redirectToLogin();
|
|
43
|
+
});
|
|
44
|
+
reject('登录过期');
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
const msg = HttpUtils.extractErrorMessage(e);
|
|
48
|
+
if (config.showError !== false) {
|
|
49
|
+
MessageUtils.error(msg);
|
|
50
|
+
}
|
|
51
|
+
reject(msg);
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
static extractErrorMessage(e, defaultMsg = '操作失败') {
|
|
57
|
+
if (axios.isAxiosError(e)) {
|
|
58
|
+
const responseData = e.response?.data;
|
|
59
|
+
const status = e.response?.status;
|
|
60
|
+
if (status === 504) return '504 请求后端服务失败';
|
|
61
|
+
if (responseData && responseData.message) return responseData.message;
|
|
62
|
+
if (e.message) return e.message;
|
|
63
|
+
return defaultMsg;
|
|
64
|
+
}
|
|
65
|
+
if (e instanceof Error) return e.message || defaultMsg;
|
|
66
|
+
return defaultMsg;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
static get(url, params = null, options = {}) {
|
|
70
|
+
return HttpUtils.coreRequest({...options, url, method: 'GET', params});
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
static post(url, data = null, params = null, options = {}) {
|
|
74
|
+
return HttpUtils.coreRequest({...options, url, method: 'POST', data, params});
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
static postForm(url, data, options = {}) {
|
|
78
|
+
return HttpUtils.coreRequest({
|
|
79
|
+
...options,
|
|
80
|
+
url,
|
|
81
|
+
method: 'POST',
|
|
82
|
+
data: qs.stringify(data),
|
|
83
|
+
headers: {'Content-Type': 'application/x-www-form-urlencoded'}
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import {history} from "umi";
|
|
2
|
+
|
|
3
|
+
export class PageUtils {
|
|
4
|
+
static redirectToLogin(): void;
|
|
5
|
+
static currentParams(): Record<string, string | undefined>;
|
|
6
|
+
static currentPathname(): string;
|
|
7
|
+
static currentUrl(): string;
|
|
8
|
+
static currentPathnameLastPart(): string | undefined;
|
|
9
|
+
static open(path: string, label?: string): void;
|
|
10
|
+
static openNoLayout(path: string): void;
|
|
11
|
+
static currentLabel(): string | undefined;
|
|
12
|
+
static closeCurrent(): void;
|
|
13
|
+
static closeCurrentAndOpenPage(alertMessage: string, path: string, label: string): void;
|
|
14
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import {history} from "umi";
|
|
2
|
+
import {StringUtils} from "../StringUtils";
|
|
3
|
+
import {UrlUtils} from "../UrlUtils";
|
|
4
|
+
import {MessageUtils} from "../MessageUtils";
|
|
5
|
+
|
|
6
|
+
export class PageUtils {
|
|
7
|
+
static redirectToLogin() {
|
|
8
|
+
const url = PageUtils.currentUrl();
|
|
9
|
+
const encodedUrl = encodeURIComponent(url);
|
|
10
|
+
history.push(`/login?redirect=${encodedUrl}`);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
static currentParams() {
|
|
14
|
+
return UrlUtils.getParams();
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
static currentPathname() {
|
|
18
|
+
const path = window.location.hash.substring(1);
|
|
19
|
+
return StringUtils.subBefore(path, '?');
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
static currentUrl() {
|
|
23
|
+
return window.location.hash.substring(1);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
static currentPathnameLastPart() {
|
|
27
|
+
const path = this.currentPathname();
|
|
28
|
+
return StringUtils.subAfterLast(path, '/') || undefined;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
static open(path, label = '未命名') {
|
|
32
|
+
let targetPath = path;
|
|
33
|
+
if (label) {
|
|
34
|
+
targetPath = UrlUtils.setParam(targetPath, '_label', label);
|
|
35
|
+
}
|
|
36
|
+
history.push(targetPath);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
static openNoLayout(path) {
|
|
40
|
+
const targetPath = UrlUtils.setParam(path, '_noLayout', true);
|
|
41
|
+
history.push(targetPath);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
static currentLabel() {
|
|
45
|
+
return this.currentParams()['_label'];
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
static closeCurrent() {
|
|
49
|
+
const event = new CustomEvent('close-page-event', {detail: {url: PageUtils.currentUrl()}});
|
|
50
|
+
document.dispatchEvent(event);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
static closeCurrentAndOpenPage(alertMessage, path, label) {
|
|
54
|
+
MessageUtils.alert(alertMessage).then(() => {
|
|
55
|
+
this.closeCurrent();
|
|
56
|
+
this.open(path, label);
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import {GlobalData} from '../../GlobalData';
|
|
2
|
+
import {ArrayUtils} from '../ArrayUtils';
|
|
3
|
+
|
|
4
|
+
export class PermUtils {
|
|
5
|
+
static getPermissions() {
|
|
6
|
+
const info = GlobalData.getLoginInfo();
|
|
7
|
+
const { permissions } = info;
|
|
8
|
+
if (permissions == null || permissions.length === 0) return [];
|
|
9
|
+
return permissions;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
static hasPermission(perm) {
|
|
13
|
+
if (perm === null || perm === undefined || perm === '') return false;
|
|
14
|
+
const permissions = PermUtils.getPermissions();
|
|
15
|
+
if (permissions.length === 0) return false;
|
|
16
|
+
if (ArrayUtils.contains(permissions, "*")) return true;
|
|
17
|
+
return permissions.indexOf(perm) > -1;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
static isPermitted(p) {
|
|
21
|
+
return PermUtils.hasPermission(p);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
static notPermitted(p) {
|
|
25
|
+
return !PermUtils.isPermitted(p);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -1,9 +1,5 @@
|
|
|
1
|
-
import {ColorsUtils} from '../ColorsUtils';
|
|
2
|
-
|
|
3
|
-
declare const OPEN_ADMIN_THEME: Record<string, string> | undefined;
|
|
4
|
-
|
|
5
1
|
export class ThemeUtils {
|
|
6
|
-
|
|
2
|
+
static defaultTheme = {
|
|
7
3
|
"primary-color": "#1961AC",
|
|
8
4
|
"success-color": "#52c41a",
|
|
9
5
|
"warning-color": "#faad14",
|
|
@@ -13,40 +9,44 @@ export class ThemeUtils {
|
|
|
13
9
|
"primary-color-click": "#124B93"
|
|
14
10
|
};
|
|
15
11
|
|
|
16
|
-
|
|
12
|
+
static cachedTheme = null;
|
|
17
13
|
|
|
18
|
-
static get theme()
|
|
14
|
+
static get theme() {
|
|
19
15
|
if (this.cachedTheme) return this.cachedTheme;
|
|
20
16
|
this.cachedTheme = this.loadTheme();
|
|
21
17
|
return this.cachedTheme;
|
|
22
18
|
}
|
|
23
19
|
|
|
24
|
-
|
|
25
|
-
|
|
20
|
+
/** 调亮/调暗十六进制颜色 */
|
|
21
|
+
static _lightenHex(hex, percent) {
|
|
22
|
+
const num = parseInt(hex.replace('#', ''), 16);
|
|
23
|
+
const r = num >> 16 & 255, g = num >> 8 & 255, b = num & 255;
|
|
24
|
+
const t = percent < 0 ? 0 : 255;
|
|
25
|
+
const p = Math.abs(percent) / 100;
|
|
26
|
+
return '#' + (0x1000000 + (Math.round((t - r) * p) + r) * 0x10000
|
|
27
|
+
+ (Math.round((t - g) * p) + g) * 0x100 + (Math.round((t - b) * p) + b)).toString(16).slice(1);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
static loadTheme() {
|
|
31
|
+
let custom = {};
|
|
26
32
|
try {
|
|
27
33
|
if (typeof OPEN_ADMIN_THEME !== 'undefined' && OPEN_ADMIN_THEME) {
|
|
28
34
|
custom = OPEN_ADMIN_THEME;
|
|
29
35
|
}
|
|
30
|
-
} catch {}
|
|
31
|
-
|
|
36
|
+
} catch (e) {}
|
|
32
37
|
const result = {...this.defaultTheme, ...custom};
|
|
33
|
-
|
|
34
|
-
// Auto-derive hover/click from primary if not explicitly set
|
|
35
38
|
if (custom["primary-color"]) {
|
|
36
39
|
if (!custom["primary-color-hover"]) {
|
|
37
|
-
result["primary-color-hover"] =
|
|
40
|
+
result["primary-color-hover"] = ThemeUtils._lightenHex(result["primary-color"], 20);
|
|
38
41
|
}
|
|
39
42
|
if (!custom["primary-color-click"]) {
|
|
40
|
-
result["primary-color-click"] =
|
|
43
|
+
result["primary-color-click"] = ThemeUtils._lightenHex(result["primary-color"], -10);
|
|
41
44
|
}
|
|
42
45
|
}
|
|
43
|
-
|
|
44
46
|
return result;
|
|
45
47
|
}
|
|
46
48
|
|
|
47
|
-
|
|
49
|
+
static getColor(key) {
|
|
48
50
|
return ThemeUtils.theme[key];
|
|
49
51
|
}
|
|
50
52
|
}
|
|
51
|
-
|
|
52
|
-
|