@scx-js/scx-admin 0.0.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/components/crud/crud-add-button.vue +28 -0
- package/components/crud/crud-batch-delete.vue +27 -0
- package/components/crud/crud-edit-dialog.vue +36 -0
- package/components/crud/crud-edit-form.vue +28 -0
- package/components/crud/crud-form-footer.vue +28 -0
- package/components/crud/crud-pagination.vue +51 -0
- package/components/crud/crud-reset-button.vue +19 -0
- package/components/crud/crud-search-button.vue +25 -0
- package/components/crud/crud-table-delete-button.vue +31 -0
- package/components/crud/crud-table-edit-button.vue +26 -0
- package/components/crud/crud-table.vue +131 -0
- package/components/crud/index.css +46 -0
- package/components/crud/index.vue +37 -0
- package/components/easy-ckeditor/default-editor-config.js +199 -0
- package/components/easy-ckeditor/easy-ckeditor-lazy.css +17 -0
- package/components/easy-ckeditor/easy-ckeditor-lazy.vue +106 -0
- package/components/easy-ckeditor/index.css +3 -0
- package/components/easy-ckeditor/index.vue +58 -0
- package/components/easy-ckeditor/plugins/scx-upload-adapter.js +39 -0
- package/components/easy-form-item/index.vue +168 -0
- package/components/easy-image/index.css +24 -0
- package/components/easy-image/index.vue +75 -0
- package/components/easy-monaco-editor/index.css +8 -0
- package/components/easy-monaco-editor/index.vue +70 -0
- package/components/easy-monaco-editor/use-worker.js +27 -0
- package/components/easy-select/index.vue +29 -0
- package/components/easy-upload/index.vue +94 -0
- package/components/easy-upload-list/index.vue +107 -0
- package/components/index.js +69 -0
- package/components/left-tree/index.css +74 -0
- package/components/left-tree/index.vue +130 -0
- package/components/scx-container/index.css +19 -0
- package/components/scx-container/index.vue +22 -0
- package/components/user-profile/change-password-dialog.vue +100 -0
- package/components/user-profile/change-user-avatar.vue +43 -0
- package/components/user-profile/change-username-dialog.vue +82 -0
- package/components/user-profile/index.css +8 -0
- package/components/user-profile/index.vue +77 -0
- package/index.js +4 -0
- package/layout/img/default-avatar.gif +0 -0
- package/layout/index.vue +24 -0
- package/layout/scx-app.vue +110 -0
- package/layout/scx-input.vue +84 -0
- package/layout/scx-logo.vue +65 -0
- package/layout/scx-main.vue +48 -0
- package/layout/scx-menu-item.vue +47 -0
- package/layout/scx-menu-toggle.vue +69 -0
- package/layout/scx-menu.vue +122 -0
- package/layout/scx-navbar.vue +47 -0
- package/layout/scx-notice.vue +211 -0
- package/layout/scx-sidebar.vue +70 -0
- package/layout/scx-theme-switch.vue +54 -0
- package/layout/scx-user-panel.vue +193 -0
- package/package.json +30 -0
- package/routes.js +57 -0
- package/scx/ali-oss.js +87 -0
- package/scx/auth-fetch.js +68 -0
- package/scx/crud-context.js +522 -0
- package/scx/easy-option.js +131 -0
- package/scx/index.js +8 -0
- package/scx/scx-auth-info.js +48 -0
- package/scx/scx-auth.js +197 -0
- package/scx/scx-config-manager.js +105 -0
- package/scx/scx-router.js +273 -0
- package/styles/index.css +37 -0
- package/util/cities.js +350 -0
- package/util/duration-format.js +27 -0
- package/util/element-plus-helper.js +114 -0
- package/util/get-order-number.js +7 -0
- package/util/index.js +4 -0
- package/util/nations.js +16 -0
- package/util/provinces.js +41 -0
- package/views/error-page.vue +79 -0
- package/views/login/index.css +95 -0
- package/views/login/login-and-register.vue +66 -0
- package/views/login/login-bg.vue +121 -0
- package/views/login/login-form-bg.vue +61 -0
- package/views/login/login-form.vue +137 -0
- package/views/login/login-message.js +28 -0
- package/views/login/login.vue +29 -0
- package/views/login/register-form.vue +148 -0
- package/views/no-perm.vue +7 -0
- package/views/not-found.vue +7 -0
- package/views/rocket.vue +84 -0
package/scx/scx-auth.js
ADDED
@@ -0,0 +1,197 @@
|
|
1
|
+
import {JsonVOError, ResponseNotOKError, ScxReq} from "@scx-js/scx-http";
|
2
|
+
import {ScxAuthInfo} from "./scx-auth-info.js";
|
3
|
+
import {inject} from "vue";
|
4
|
+
import {ElMessage} from "element-plus";
|
5
|
+
|
6
|
+
|
7
|
+
/**
|
8
|
+
*
|
9
|
+
* @type {string}
|
10
|
+
*/
|
11
|
+
const scxAuthKey = "scx-auth";
|
12
|
+
|
13
|
+
/**
|
14
|
+
*
|
15
|
+
* @returns {ScxAuth}
|
16
|
+
*/
|
17
|
+
function useScxAuth() {
|
18
|
+
return inject(scxAuthKey);
|
19
|
+
}
|
20
|
+
|
21
|
+
|
22
|
+
class ScxAuth {
|
23
|
+
|
24
|
+
/**
|
25
|
+
* 获取 token 的标识字段
|
26
|
+
*/
|
27
|
+
TOKEN_KEY = "S-Token";
|
28
|
+
|
29
|
+
/**
|
30
|
+
* 获取 设备 的标识字段
|
31
|
+
*/
|
32
|
+
DEVICE_KEY = "S-Device";
|
33
|
+
|
34
|
+
DEVICE_TYPE = "ADMIN"; //WEBSITE 使用的是 cookie, ADMIN 使用的是 header
|
35
|
+
|
36
|
+
/**
|
37
|
+
* 用户信息
|
38
|
+
*/
|
39
|
+
userInfo;
|
40
|
+
|
41
|
+
/**
|
42
|
+
* @type ScxReq
|
43
|
+
*/
|
44
|
+
req;
|
45
|
+
|
46
|
+
/**
|
47
|
+
*
|
48
|
+
* @param {ScxAuthInfo} userInfo
|
49
|
+
* @param baseURL
|
50
|
+
*/
|
51
|
+
constructor(userInfo, baseURL) {
|
52
|
+
this.userInfo = userInfo;
|
53
|
+
this.req = new ScxReq(baseURL);
|
54
|
+
}
|
55
|
+
|
56
|
+
infoApi() {
|
57
|
+
return "api/auth/info";
|
58
|
+
}
|
59
|
+
|
60
|
+
/**
|
61
|
+
* 重置用户信息
|
62
|
+
*/
|
63
|
+
resetUserInfo() {
|
64
|
+
this.userInfo.reset();
|
65
|
+
this.userInfo.loginStatus = false;
|
66
|
+
}
|
67
|
+
|
68
|
+
/**
|
69
|
+
* 判断证书是否可用, 可用的同时会拉取用户信息
|
70
|
+
* @returns {Promise<unknown>}
|
71
|
+
*/
|
72
|
+
tokenCanUse() {
|
73
|
+
return new Promise((resolve, reject) => {
|
74
|
+
this.req.get(this.infoApi(), null, {
|
75
|
+
headers: this.AuthHeaders(), responseType: "json",
|
76
|
+
}).then(res => {
|
77
|
+
this.userInfo.fill(res);
|
78
|
+
this.userInfo.loginStatus = true;
|
79
|
+
resolve(true);
|
80
|
+
}).catch(e => {
|
81
|
+
//在两种情况下 token 不可用 一种是接口返回信息有误 一种是 后台明确 401 错误
|
82
|
+
if (e instanceof JsonVOError || (e instanceof ResponseNotOKError && e.cause.status === 401)) {
|
83
|
+
resolve(false);
|
84
|
+
} else {//这里可能是网络无法连接等 直接抛异常即可
|
85
|
+
//todo 此处因为目前只是抛出异常 所以当后台未启动时 前台也无法正确显示
|
86
|
+
//todo 这里有几种方案 第一种就是这个 tokenCanUse 状态改为3种 明确可用 明确不可用 以及未知(比如后台连接不上)
|
87
|
+
// todo 明确可用就是正常走路由 明确不可用就是跳转到登录界面 未知的情况下同样也跳转到登录界面 但是 不清空用户 token
|
88
|
+
//todo 这样下次用户刷新页面仍然可以直接进入
|
89
|
+
// reject(e);
|
90
|
+
ElMessage.error("Api 连接错误 !!!");
|
91
|
+
resolve(false);
|
92
|
+
}
|
93
|
+
});
|
94
|
+
});
|
95
|
+
}
|
96
|
+
|
97
|
+
login(username, password) {
|
98
|
+
return new Promise((resolve, reject) => {
|
99
|
+
//通知服务器退出登录
|
100
|
+
this.req.post("api/auth/login", {
|
101
|
+
username: username.trim(),
|
102
|
+
password: password,
|
103
|
+
}).then(data => {
|
104
|
+
this.setToken(data.token);
|
105
|
+
resolve(data.token);
|
106
|
+
}).catch(error => {
|
107
|
+
reject(error);
|
108
|
+
});
|
109
|
+
});
|
110
|
+
}
|
111
|
+
|
112
|
+
logout() {
|
113
|
+
return new Promise((resolve, reject) => {
|
114
|
+
//通知后台退出登录
|
115
|
+
this.req.post("api/auth/logout", null, {
|
116
|
+
headers: this.AuthHeaders(), responseType: "json",
|
117
|
+
}).then(() => {
|
118
|
+
//成功后清除 token 和 用户信息
|
119
|
+
this.removeToken();
|
120
|
+
this.resetUserInfo();
|
121
|
+
resolve();
|
122
|
+
}).catch(e => {
|
123
|
+
//在两种情况下 token 不可用 一种是接口返回信息有误 一种是 后台明确 401 错误
|
124
|
+
if (e instanceof JsonVOError || (e instanceof ResponseNotOKError && e.cause.status === 401)) {
|
125
|
+
resolve(false);
|
126
|
+
} else {//这里可能是网络无法连接等 直接抛异常即可
|
127
|
+
reject(e);
|
128
|
+
}
|
129
|
+
});
|
130
|
+
});
|
131
|
+
}
|
132
|
+
|
133
|
+
/**
|
134
|
+
* 用户是否已经登录
|
135
|
+
* @returns {boolean}
|
136
|
+
*/
|
137
|
+
alreadyLogged() {
|
138
|
+
return this.userInfo.loginStatus === true;
|
139
|
+
}
|
140
|
+
|
141
|
+
/**
|
142
|
+
* 获取 token
|
143
|
+
* @returns {string}
|
144
|
+
*/
|
145
|
+
getToken() {
|
146
|
+
try {
|
147
|
+
return localStorage.getItem(this.TOKEN_KEY);
|
148
|
+
} catch (e) {
|
149
|
+
console.error(e);
|
150
|
+
return "";
|
151
|
+
}
|
152
|
+
}
|
153
|
+
|
154
|
+
/**
|
155
|
+
* 设置 token
|
156
|
+
* @param token
|
157
|
+
*/
|
158
|
+
setToken(token) {
|
159
|
+
try {
|
160
|
+
localStorage.setItem(this.TOKEN_KEY, token);
|
161
|
+
} catch (e) {
|
162
|
+
console.error(e);
|
163
|
+
}
|
164
|
+
}
|
165
|
+
|
166
|
+
/**
|
167
|
+
* 移除 token
|
168
|
+
*/
|
169
|
+
removeToken() {
|
170
|
+
try {
|
171
|
+
localStorage.removeItem(this.TOKEN_KEY);
|
172
|
+
} catch (e) {
|
173
|
+
console.error(e);
|
174
|
+
}
|
175
|
+
}
|
176
|
+
|
177
|
+
/**
|
178
|
+
* 常用的 请求头
|
179
|
+
* @returns {{}}
|
180
|
+
*/
|
181
|
+
AuthHeaders() {
|
182
|
+
const authHeaders = {};
|
183
|
+
authHeaders[this.TOKEN_KEY] = this.getToken();
|
184
|
+
authHeaders[this.DEVICE_KEY] = this.DEVICE_TYPE;
|
185
|
+
return authHeaders;
|
186
|
+
}
|
187
|
+
|
188
|
+
install(app) {
|
189
|
+
app.provide(scxAuthKey, this);
|
190
|
+
}
|
191
|
+
|
192
|
+
}
|
193
|
+
|
194
|
+
export {
|
195
|
+
ScxAuth,
|
196
|
+
useScxAuth,
|
197
|
+
};
|
@@ -0,0 +1,105 @@
|
|
1
|
+
import {inject} from "vue";
|
2
|
+
|
3
|
+
/**
|
4
|
+
*
|
5
|
+
* @type {string}
|
6
|
+
*/
|
7
|
+
const scxSystemConfigKey = "scx-system-config";
|
8
|
+
|
9
|
+
/**
|
10
|
+
*
|
11
|
+
* @type {string}
|
12
|
+
*/
|
13
|
+
const scxUserConfigKey = "scx-user-config";
|
14
|
+
|
15
|
+
/**
|
16
|
+
* a
|
17
|
+
* @type {string}
|
18
|
+
*/
|
19
|
+
const scxConfigManagerKey = "scx-config-manager";
|
20
|
+
|
21
|
+
|
22
|
+
/**
|
23
|
+
* 配置管理器
|
24
|
+
*/
|
25
|
+
class ScxConfigManager {
|
26
|
+
|
27
|
+
req;
|
28
|
+
|
29
|
+
systemConfig;
|
30
|
+
|
31
|
+
userConfig;
|
32
|
+
|
33
|
+
/**
|
34
|
+
*
|
35
|
+
* @param req {ScxReq}
|
36
|
+
|
37
|
+
* @param systemConfig {Object}
|
38
|
+
* @param userConfig {Object}
|
39
|
+
*/
|
40
|
+
constructor(req, systemConfig, userConfig) {
|
41
|
+
this.req = req;
|
42
|
+
this.systemConfig = systemConfig;
|
43
|
+
this.userConfig = userConfig;
|
44
|
+
}
|
45
|
+
|
46
|
+
startWatch() {
|
47
|
+
return this;
|
48
|
+
}
|
49
|
+
|
50
|
+
onSystemConfigChange(event) {
|
51
|
+
return this;
|
52
|
+
}
|
53
|
+
|
54
|
+
onUserConfigChange(event) {
|
55
|
+
return this;
|
56
|
+
}
|
57
|
+
|
58
|
+
updateSystemConfig(newSystemConfig) {
|
59
|
+
return this.req.put("api/system-config", newSystemConfig);
|
60
|
+
}
|
61
|
+
|
62
|
+
updateUserConfig(newUserConfig) {
|
63
|
+
return this.req.put("api/user-config", newUserConfig);
|
64
|
+
}
|
65
|
+
|
66
|
+
install(app) {
|
67
|
+
app.provide(scxConfigManagerKey, this);
|
68
|
+
app.provide(scxSystemConfigKey, this.systemConfig);
|
69
|
+
app.provide(scxUserConfigKey, this.userConfig);
|
70
|
+
}
|
71
|
+
|
72
|
+
}
|
73
|
+
|
74
|
+
|
75
|
+
/**
|
76
|
+
*
|
77
|
+
* @returns {Object}
|
78
|
+
*/
|
79
|
+
function useScxSystemConfig() {
|
80
|
+
return inject(scxSystemConfigKey);
|
81
|
+
}
|
82
|
+
|
83
|
+
/**
|
84
|
+
*
|
85
|
+
* @returns {Object}
|
86
|
+
*/
|
87
|
+
function useScxUserConfig() {
|
88
|
+
return inject(scxUserConfigKey);
|
89
|
+
}
|
90
|
+
|
91
|
+
|
92
|
+
/**
|
93
|
+
*
|
94
|
+
* @return {ScxConfigManager}
|
95
|
+
*/
|
96
|
+
function useScxConfigManager() {
|
97
|
+
return inject(scxConfigManagerKey);
|
98
|
+
}
|
99
|
+
|
100
|
+
export {
|
101
|
+
ScxConfigManager,
|
102
|
+
useScxSystemConfig,
|
103
|
+
useScxUserConfig,
|
104
|
+
useScxConfigManager,
|
105
|
+
};
|
@@ -0,0 +1,273 @@
|
|
1
|
+
import NProgress from "nprogress";
|
2
|
+
import {createRouter, createWebHashHistory} from "vue-router";
|
3
|
+
import {inject} from "vue";
|
4
|
+
|
5
|
+
/**
|
6
|
+
* 获取路由 title
|
7
|
+
* @param route
|
8
|
+
* @returns {String}
|
9
|
+
*/
|
10
|
+
function getRouteTitle(route) {
|
11
|
+
return route.meta && route.meta.title ? route.meta.title : route.name;
|
12
|
+
}
|
13
|
+
|
14
|
+
/**
|
15
|
+
* 获取路由 排序
|
16
|
+
* @param route
|
17
|
+
* @return {Number}
|
18
|
+
*/
|
19
|
+
function getRouteOrder(route) {
|
20
|
+
return route.meta && route.meta.order ? route.meta.order : 0;
|
21
|
+
}
|
22
|
+
|
23
|
+
/**
|
24
|
+
* 是否需要登录
|
25
|
+
* @param route
|
26
|
+
* @return {boolean}
|
27
|
+
*/
|
28
|
+
function routeNoNeedLogin(route) {
|
29
|
+
return route.meta && route.meta.noNeedLogin === true;
|
30
|
+
}
|
31
|
+
|
32
|
+
/**
|
33
|
+
* 是否需要权限
|
34
|
+
* @param route
|
35
|
+
* @return {boolean}
|
36
|
+
*/
|
37
|
+
function routeNoNeedPerm(route) {
|
38
|
+
return route.meta && route.meta.noNeedPerm === true;
|
39
|
+
}
|
40
|
+
|
41
|
+
/**
|
42
|
+
* 是否可以在启动器中访问 1, 是最终节点(没有 children) 2, 没有开启 hiddenInLauncher
|
43
|
+
* @param route
|
44
|
+
* @return {boolean}
|
45
|
+
*/
|
46
|
+
function routeCanShowInLauncher(route) {
|
47
|
+
return route.children.length === 0 && !(route.meta && route.meta.hiddenInLauncher === true);
|
48
|
+
}
|
49
|
+
|
50
|
+
function routeCanShowInMenu(route) {
|
51
|
+
return !(route.meta && route.meta.hiddenInLauncher === true);
|
52
|
+
}
|
53
|
+
|
54
|
+
function sortRoutes(l) {
|
55
|
+
return l.sort((v1, v2) => getRouteOrder(v1) - getRouteOrder(v2));
|
56
|
+
}
|
57
|
+
|
58
|
+
|
59
|
+
/**
|
60
|
+
* 为路由设置 order
|
61
|
+
* @param r
|
62
|
+
*/
|
63
|
+
function setRoutesOrder(r) {
|
64
|
+
let i = 0;
|
65
|
+
|
66
|
+
function setRoutesOrder0(r0) {
|
67
|
+
for (let e of r0) {
|
68
|
+
if (!e.meta) {
|
69
|
+
e.meta = {};
|
70
|
+
}
|
71
|
+
e.meta.order = i;
|
72
|
+
i = i + 1;
|
73
|
+
if (e.children) {
|
74
|
+
setRoutesOrder0(e.children);
|
75
|
+
}
|
76
|
+
}
|
77
|
+
}
|
78
|
+
|
79
|
+
setRoutesOrder0(r);
|
80
|
+
return r;
|
81
|
+
}
|
82
|
+
|
83
|
+
class ScxRouter {
|
84
|
+
auth;
|
85
|
+
|
86
|
+
/**
|
87
|
+
* @type {Object}
|
88
|
+
*/
|
89
|
+
systemConfig;
|
90
|
+
|
91
|
+
/**
|
92
|
+
* @type {Object}
|
93
|
+
*/
|
94
|
+
userConfig;
|
95
|
+
userInfo;
|
96
|
+
vueRouter;
|
97
|
+
|
98
|
+
constructor(rawOptions = {}) {
|
99
|
+
const {
|
100
|
+
routes = [],
|
101
|
+
auth,
|
102
|
+
systemConfig,
|
103
|
+
userInfo,
|
104
|
+
userConfig,
|
105
|
+
} = rawOptions;
|
106
|
+
|
107
|
+
this.auth = auth;
|
108
|
+
this.systemConfig = systemConfig;
|
109
|
+
this.userInfo = userInfo;
|
110
|
+
this.userConfig = userConfig;
|
111
|
+
this.vueRouter = createRouter({
|
112
|
+
history: this.historyType(),
|
113
|
+
routes: setRoutesOrder(routes),
|
114
|
+
});
|
115
|
+
this.initBeforeEach(this.vueRouter);
|
116
|
+
this.initAfterEach(this.vueRouter);
|
117
|
+
}
|
118
|
+
|
119
|
+
initBeforeEach(vueRouter) {
|
120
|
+
vueRouter.beforeEach(async (to, from) => {
|
121
|
+
NProgress.start();
|
122
|
+
document.title = this.getPageTitle(to);
|
123
|
+
|
124
|
+
//先校验用户是否登录或令牌是否可用 (若用户已经登录直接放行, 如果没登陆可能是第一次进入页面, 则校验一下 token)
|
125
|
+
//此处可能会出现用户 "登录" 了但是 token 已经在后台作废 不过不用担心 因为后台数据的操作都已经做了登录校验 所以此种情况下用户只能看到空白页面而已
|
126
|
+
//至于为什么不每次都单独使用 tokenCanUse 作为判断依据而是添加了 alreadyLogged 作为辅助校验项 主要是从性能考虑
|
127
|
+
//毕竟每次切换页面都进行一次 token 是否可用的校验 (会走一次 http 请求) 对性能有很大影响
|
128
|
+
const b = this.auth.alreadyLogged() ? true : await this.auth.tokenCanUse();
|
129
|
+
|
130
|
+
if (b) {
|
131
|
+
if (to.name === "login") {//针对 login 页面做特殊处理
|
132
|
+
return this.getRedirectRouteFromLoginRoute(to);
|
133
|
+
}
|
134
|
+
//不在白名单的判断是否有权限访问 没有返回 无权限页面
|
135
|
+
if (this.canAccessThisRoute(to)) {
|
136
|
+
return true;
|
137
|
+
}
|
138
|
+
return routeNoNeedPerm(to) ? true : this.getNoPermRoute();
|
139
|
+
} else {//token 不可用移除 失效的token 并清除用户信息
|
140
|
+
//todo 因为已经失效 移不移除 应该没啥区别 this.auth.removeToken();
|
141
|
+
this.auth.resetUserInfo();
|
142
|
+
if (to.name === "login") { //针对 login 页面做特殊处理 防止无限重定向
|
143
|
+
return true;
|
144
|
+
}
|
145
|
+
return routeNoNeedLogin(to) ? true : this.getLoginRoute(to);
|
146
|
+
}
|
147
|
+
});
|
148
|
+
}
|
149
|
+
|
150
|
+
initAfterEach(vueRouter) {
|
151
|
+
vueRouter.afterEach((to, from) => {
|
152
|
+
NProgress.done();
|
153
|
+
});
|
154
|
+
}
|
155
|
+
|
156
|
+
historyType() {
|
157
|
+
return createWebHashHistory();
|
158
|
+
}
|
159
|
+
|
160
|
+
getVueRouter() {
|
161
|
+
return this.vueRouter;
|
162
|
+
}
|
163
|
+
|
164
|
+
/**
|
165
|
+
*翻译 顶部的 title
|
166
|
+
* @param route
|
167
|
+
*/
|
168
|
+
getPageTitle(route) {
|
169
|
+
return `${getRouteTitle(route)} - ${this.systemConfig.title}`;
|
170
|
+
}
|
171
|
+
|
172
|
+
/**
|
173
|
+
* 是否可以访问这个路由
|
174
|
+
* @returns {boolean}
|
175
|
+
* @param route
|
176
|
+
*/
|
177
|
+
canAccessThisRoute(route) {
|
178
|
+
//先校验是否存在于白名单中
|
179
|
+
const onWhiteList = routeNoNeedLogin(route) || routeNoNeedPerm(route);
|
180
|
+
if (onWhiteList) {
|
181
|
+
return true;
|
182
|
+
}
|
183
|
+
if (this.userInfo.user.isAdmin) {
|
184
|
+
return true;
|
185
|
+
} else {
|
186
|
+
return this.userInfo.perms.pagePerms.includes(route.name);
|
187
|
+
}
|
188
|
+
}
|
189
|
+
|
190
|
+
/**
|
191
|
+
* 根据当前路由 获取登录页面的路由 主要是对参数进行了一些特殊处理 保证可以在登陆时直接重定向到登录前的页面
|
192
|
+
*/
|
193
|
+
getLoginRoute({name, query} = {}) {
|
194
|
+
const loginQuery = {};
|
195
|
+
if (name) {
|
196
|
+
loginQuery["redirect-name"] = name;
|
197
|
+
}
|
198
|
+
if (query && Object.keys(query).length > 0) {
|
199
|
+
loginQuery["redirect-query"] = JSON.stringify(query);
|
200
|
+
}
|
201
|
+
return {name: "login", query: loginQuery};
|
202
|
+
}
|
203
|
+
|
204
|
+
getNoPermRoute() {
|
205
|
+
return {name: "no-perm"};
|
206
|
+
}
|
207
|
+
|
208
|
+
/**
|
209
|
+
* 解析 getLoginRoute 生成的 登录页面的路由 并返回应该重定向的页面
|
210
|
+
* 1, 没有重定向参数 -> 返回 home 页
|
211
|
+
* 2, 有重定向参数 但是参数有误 (无此路由) -> 返回 not-found 页
|
212
|
+
* 3, 有重定向页并且参数正确 -> 重定向到正确的页面并携带参数
|
213
|
+
* @param query
|
214
|
+
* @returns {{query: null, name: string}}
|
215
|
+
*/
|
216
|
+
getRedirectRouteFromLoginRoute({query}) {
|
217
|
+
const queryRedirectName = query["redirect-name"];
|
218
|
+
const queryRedirectQuery = query["redirect-query"];
|
219
|
+
let redirectName = "home";
|
220
|
+
let redirectQuery = null;
|
221
|
+
if (queryRedirectName) {
|
222
|
+
if (this.vueRouter.hasRoute(queryRedirectName)) {
|
223
|
+
redirectName = queryRedirectName;
|
224
|
+
if (queryRedirectQuery) {
|
225
|
+
try {
|
226
|
+
redirectQuery = JSON.parse(queryRedirectQuery);
|
227
|
+
} catch (e) {
|
228
|
+
console.warn("处理重定向参数时发生错误 : " + e);
|
229
|
+
}
|
230
|
+
}
|
231
|
+
} else {
|
232
|
+
redirectName = "not-found";
|
233
|
+
}
|
234
|
+
}
|
235
|
+
return {name: redirectName, query: redirectQuery};
|
236
|
+
}
|
237
|
+
|
238
|
+
getRoutes() {
|
239
|
+
return sortRoutes(this.vueRouter.getRoutes());
|
240
|
+
}
|
241
|
+
|
242
|
+
install(app) {
|
243
|
+
app.provide(scxRouterKey, this);
|
244
|
+
}
|
245
|
+
|
246
|
+
}
|
247
|
+
|
248
|
+
/**
|
249
|
+
*
|
250
|
+
* @type {string}
|
251
|
+
*/
|
252
|
+
const scxRouterKey = "scx-router";
|
253
|
+
|
254
|
+
/**
|
255
|
+
*
|
256
|
+
* @returns {ScxRouter}
|
257
|
+
*/
|
258
|
+
function useScxRouter() {
|
259
|
+
return inject(scxRouterKey);
|
260
|
+
}
|
261
|
+
|
262
|
+
export {
|
263
|
+
ScxRouter,
|
264
|
+
useScxRouter,
|
265
|
+
getRouteTitle,
|
266
|
+
getRouteOrder,
|
267
|
+
routeNoNeedLogin,
|
268
|
+
routeNoNeedPerm,
|
269
|
+
routeCanShowInLauncher,
|
270
|
+
routeCanShowInMenu,
|
271
|
+
sortRoutes,
|
272
|
+
setRoutesOrder,
|
273
|
+
};
|
package/styles/index.css
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
/*-------------------- 以下为一些其余的 css --------------------*/
|
2
|
+
|
3
|
+
#nprogress {
|
4
|
+
--nprogress-color: var(--scx-theme);
|
5
|
+
}
|
6
|
+
|
7
|
+
/*添加修改页面的 label 使其变粗*/
|
8
|
+
.crud .el-form-item__label {
|
9
|
+
font-weight: 700;
|
10
|
+
}
|
11
|
+
|
12
|
+
/*在 el 按钮中的图标颜色取按钮文字颜色 */
|
13
|
+
.el-button .scx-icon {
|
14
|
+
fill: currentColor;
|
15
|
+
}
|
16
|
+
|
17
|
+
/*在 el 按钮中 当 scx-icon 和 span 处在一起时 增加两者的间距*/
|
18
|
+
.el-button [class*=scx-icon] + span {
|
19
|
+
margin-left: 6px;
|
20
|
+
}
|
21
|
+
|
22
|
+
/* 定义一些其他的样式 */
|
23
|
+
.el-scrollbar__thumb {
|
24
|
+
--el-scrollbar-opacity: 1;
|
25
|
+
--el-scrollbar-bg-color: var(--scx-scrollbar-thumb-bg);
|
26
|
+
--el-scrollbar-hover-opacity: 1;
|
27
|
+
--el-scrollbar-hover-bg-color: var(--scx-scrollbar-thumb-hover-bg);
|
28
|
+
}
|
29
|
+
|
30
|
+
/*todo element plus 默认 为 span 这里特殊处理让其撑满横向宽度 */
|
31
|
+
.el-tree-node__label {
|
32
|
+
width: 100%;
|
33
|
+
}
|
34
|
+
|
35
|
+
.el-form-item__content {
|
36
|
+
min-width: 180px;
|
37
|
+
}
|