cloud-web-corejs 1.0.54-dev.767 → 1.0.54-dev.768
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 +1 -1
- package/src/components/luckysheet/view.vue +25 -3
- package/src/index.js +44 -199
- package/src/permission.js +71 -15
- package/src/store/modules/permission.js +38 -36
- package/src/store/modules/settings.js +0 -2
- package/src/store/modules/tagsView.js +1 -2
- package/src/store/modules/user.js +15 -9
- package/src/utils/externalAssets.js +62 -0
- package/src/utils/loginVab.js +68 -0
- package/src/utils/pddLog.js +18 -4
- package/src/utils/prefixGlobals.js +11 -0
- package/src/views/user/login/indexMixin.js +21 -16
package/package.json
CHANGED
|
@@ -40,6 +40,17 @@ import LuckyExcel from "luckyexcel";
|
|
|
40
40
|
//导入库export.js 这个文件是es6的,不能在普通的HTML文件直接引入js文件(虽然都是js文件,但是有区别,具体请百度es6与es5)!需要把es6转es5才可以直接引入使用!
|
|
41
41
|
import { exportExcel, generateExcelFile } from "./export";
|
|
42
42
|
import { saveAs } from "file-saver";
|
|
43
|
+
import {
|
|
44
|
+
getPublicAssetUrl,
|
|
45
|
+
loadStyles,
|
|
46
|
+
} from "@base/utils/externalAssets";
|
|
47
|
+
|
|
48
|
+
const luckysheetStyleUrls = [
|
|
49
|
+
"luckysheet/plugins/css/pluginsCss.css",
|
|
50
|
+
"luckysheet/plugins/plugins.css",
|
|
51
|
+
"luckysheet/css/luckysheet.css",
|
|
52
|
+
"luckysheet/assets/iconfont/iconfont.css",
|
|
53
|
+
].map(getPublicAssetUrl);
|
|
43
54
|
|
|
44
55
|
export default {
|
|
45
56
|
name: "luckysheet",
|
|
@@ -62,12 +73,23 @@ export default {
|
|
|
62
73
|
};
|
|
63
74
|
},
|
|
64
75
|
beforeDestroy() {
|
|
65
|
-
if (luckysheet) {
|
|
76
|
+
if (window.luckysheet) {
|
|
66
77
|
this.exitEditMode();
|
|
67
|
-
luckysheet.destroy();
|
|
78
|
+
window.luckysheet.destroy();
|
|
68
79
|
}
|
|
69
80
|
},
|
|
70
|
-
mounted() {
|
|
81
|
+
async mounted() {
|
|
82
|
+
try {
|
|
83
|
+
await loadStyles(luckysheetStyleUrls);
|
|
84
|
+
} catch (error) {
|
|
85
|
+
console.error("Luckysheet 样式加载失败", error);
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
if (this._isDestroyed) return;
|
|
89
|
+
if (!window.luckysheet) {
|
|
90
|
+
console.error("luckysheet未初始化");
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
71
93
|
// In some cases, you need to use $nextTick
|
|
72
94
|
// this.$nextTick(() => {
|
|
73
95
|
let config = this.options.config || {};
|
package/src/index.js
CHANGED
|
@@ -1,11 +1,22 @@
|
|
|
1
1
|
/**version-1.0*/
|
|
2
2
|
import "./public-path"; // qiankun publicPath 修正,必须保持第一行
|
|
3
|
-
import Vue from "vue";
|
|
4
|
-
import Cookies from "js-cookie";
|
|
5
|
-
import "normalize.css/normalize.css"; // a modern alternative to CSS resets
|
|
6
|
-
import
|
|
7
|
-
import "
|
|
8
|
-
import "
|
|
3
|
+
import Vue from "vue";
|
|
4
|
+
import Cookies from "js-cookie";
|
|
5
|
+
import "normalize.css/normalize.css"; // a modern alternative to CSS resets
|
|
6
|
+
import Button from "element-ui/lib/button";
|
|
7
|
+
import Checkbox from "element-ui/lib/checkbox";
|
|
8
|
+
import Dialog from "element-ui/lib/dialog";
|
|
9
|
+
import Form from "element-ui/lib/form";
|
|
10
|
+
import FormItem from "element-ui/lib/form-item";
|
|
11
|
+
import Input from "element-ui/lib/input";
|
|
12
|
+
import TabPane from "element-ui/lib/tab-pane";
|
|
13
|
+
import Tabs from "element-ui/lib/tabs";
|
|
14
|
+
import Tooltip from "element-ui/lib/tooltip";
|
|
15
|
+
import Loading from "element-ui/lib/loading";
|
|
16
|
+
import Message from "element-ui/lib/message";
|
|
17
|
+
import MessageBox from "element-ui/lib/message-box";
|
|
18
|
+
import "@/styles/element-variables.scss";
|
|
19
|
+
import "@/styles/index.scss"; // 登录页与业务页共用同一套全局样式
|
|
9
20
|
|
|
10
21
|
import App from "@base/App";
|
|
11
22
|
import store from "@base/store";
|
|
@@ -13,189 +24,13 @@ import router, { resetRouter } from "@base/router";
|
|
|
13
24
|
import settings from "@/settings";
|
|
14
25
|
import { setToken as setAuthToken } from "@base/utils/auth";
|
|
15
26
|
|
|
16
|
-
import "@/icons"; // icon
|
|
17
|
-
import "@base/permission"; // permission control
|
|
27
|
+
import "@/icons"; // icon
|
|
28
|
+
import "@base/permission"; // permission control
|
|
29
|
+
import "@base/resources/js/base/common.js"; // request 序列化在登录接口阶段即依赖
|
|
18
30
|
|
|
19
|
-
import
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
import BaseKeepAlive from "@base/utils/keepAlive.js";
|
|
24
|
-
|
|
25
|
-
Vue.component("BaseKeepAlive", BaseKeepAlive);
|
|
26
|
-
|
|
27
|
-
import VXETable from "vxe-table";
|
|
28
|
-
import "vxe-table/lib/style.css";
|
|
29
|
-
|
|
30
|
-
// 引入扩展插件
|
|
31
|
-
import "@base/components/table/plugins/extend-cell-area/vxe-table-extend-cell-area.es6.min.js";
|
|
32
|
-
import "@base/components/table/plugins/extend-cell-area/vxe-table-extend-cell-area.min.css";
|
|
33
|
-
|
|
34
|
-
/* // 设置授权信息
|
|
35
|
-
VXETable.setup({
|
|
36
|
-
// showAuthLog: true, // 是否在控制台显示授权信息,专业版支持关闭
|
|
37
|
-
// authId: 'gbeumewkoyt2rhf9', // 获取授权后在官网登录后进入“用户中心”查看
|
|
38
|
-
authId: 'gbeumewkoyt2rhft', // 获取授权后在官网登录后进入“用户中心”查看
|
|
39
|
-
// onAuth (e) {
|
|
40
|
-
// // 打印授权状态
|
|
41
|
-
// console.log(e)
|
|
42
|
-
// }
|
|
43
|
-
}) */
|
|
44
|
-
|
|
45
|
-
import Vab from "@base/utils/vab";
|
|
46
|
-
|
|
47
|
-
Vue.use(Vab);
|
|
48
|
-
|
|
49
|
-
Vue.use(VXETable);
|
|
50
|
-
|
|
51
|
-
/* import tablePluns from "@/mixins/table/index.js"
|
|
52
|
-
VXETable.use(tablePluns) */
|
|
53
|
-
|
|
54
|
-
import "@base/components/table/index.js";
|
|
55
|
-
|
|
56
|
-
import drag from "@base/directive/el-drag-dialog/index.js";
|
|
57
|
-
|
|
58
|
-
Vue.use(drag.install);
|
|
59
|
-
|
|
60
|
-
import elDialogCenter from "@base/directive/el-dialog-center/index.js";
|
|
61
|
-
|
|
62
|
-
Vue.use(elDialogCenter.install);
|
|
63
|
-
|
|
64
|
-
import ErroreBox from "@base/components/errorMsg/index.js";
|
|
65
|
-
|
|
66
|
-
Vue.use(ErroreBox);
|
|
67
|
-
|
|
68
|
-
import ExcelExport from "@base/components/excelExport/index.js";
|
|
69
|
-
|
|
70
|
-
Vue.use(ExcelExport);
|
|
71
|
-
|
|
72
|
-
import ExcelImport from "@base/components/excelImport/index.js";
|
|
73
|
-
|
|
74
|
-
Vue.use(ExcelImport);
|
|
75
|
-
|
|
76
|
-
import ConfirmDialog from "@base/components/confirmDialog/index.js";
|
|
77
|
-
|
|
78
|
-
Vue.use(ConfirmDialog);
|
|
79
|
-
|
|
80
|
-
import baseAlert from "@base/components/baseAlert/index.js";
|
|
81
|
-
|
|
82
|
-
Vue.use(baseAlert);
|
|
83
|
-
|
|
84
|
-
import FormDialog from "@base/components/formDialog/index.js";
|
|
85
|
-
|
|
86
|
-
Vue.use(FormDialog);
|
|
87
|
-
|
|
88
|
-
import permission from "@base/directive/permission";
|
|
89
|
-
|
|
90
|
-
Vue.use(permission);
|
|
91
|
-
|
|
92
|
-
import VabUpload from "@base/components/VabUpload/index.js";
|
|
93
|
-
|
|
94
|
-
Vue.use(VabUpload);
|
|
95
|
-
|
|
96
|
-
Vue.component("baseUpload", () =>
|
|
97
|
-
import("@base/components/VabUpload/view.vue")
|
|
98
|
-
);
|
|
99
|
-
|
|
100
|
-
import baseAttachment from "@base/components/baseAttachment/install";
|
|
101
|
-
|
|
102
|
-
Vue.use(baseAttachment);
|
|
103
|
-
Vue.component("attachmentShowList", () =>
|
|
104
|
-
import("@base/components/baseAttachment/showList")
|
|
105
|
-
);
|
|
106
|
-
|
|
107
|
-
import "@base/resources/js/base/common.js";
|
|
108
|
-
|
|
109
|
-
import vxeFilter from "@base/components/table/vxeFilter/index.js";
|
|
110
|
-
|
|
111
|
-
Vue.use(vxeFilter);
|
|
112
|
-
|
|
113
|
-
import baseTableExport from "@base/components/excelExport/button.vue";
|
|
114
|
-
|
|
115
|
-
Vue.component(baseTableExport.name, baseTableExport);
|
|
116
|
-
|
|
117
|
-
/* Vue.component('extendedProperties', () => import('@base/components/extendedProperties/view.vue')); */
|
|
118
|
-
|
|
119
|
-
import LimitNumber from "@base/directive/LimitNumber/index.js";
|
|
120
|
-
|
|
121
|
-
Vue.use(LimitNumber);
|
|
122
|
-
|
|
123
|
-
import baseInputNumber from "@base/components/baseInputNumber/index.vue";
|
|
124
|
-
|
|
125
|
-
Vue.component(baseInputNumber.name, baseInputNumber);
|
|
126
|
-
|
|
127
|
-
import elReadonly from "@base/directive/el-readonly/index.js";
|
|
128
|
-
|
|
129
|
-
Vue.use(elReadonly);
|
|
130
|
-
|
|
131
|
-
/*import cnPrint from "@base/components/cnPrint/index.js"
|
|
132
|
-
|
|
133
|
-
Vue.use(cnPrint);*/
|
|
134
|
-
|
|
135
|
-
/* Vue.component('oplogTable', () => import('@base/components/oplogTable/index.vue')); */
|
|
136
|
-
import oplogTable from "@base/components/oplogTable/index.vue";
|
|
137
|
-
|
|
138
|
-
Vue.component(oplogTable.name, oplogTable);
|
|
139
|
-
|
|
140
|
-
import baseInputBatch from "@base/components/baseInputBatch/index.vue";
|
|
141
|
-
|
|
142
|
-
Vue.component(baseInputBatch.name, baseInputBatch);
|
|
143
|
-
|
|
144
|
-
import baseArea from "@base/components/baseArea/index.vue";
|
|
145
|
-
|
|
146
|
-
Vue.component(baseArea.name, baseArea);
|
|
147
|
-
|
|
148
|
-
Vue.component("baseInputExport", () =>
|
|
149
|
-
import("@base/components/baseInputExport/index.vue")
|
|
150
|
-
);
|
|
151
|
-
|
|
152
|
-
Vue.component("advancedSearchDialog", () =>
|
|
153
|
-
import("@base/components/advancedSearchDialog/index.vue")
|
|
154
|
-
);
|
|
155
|
-
|
|
156
|
-
import baseTabs from "@base/components/baseTabs/index.vue";
|
|
157
|
-
|
|
158
|
-
Vue.component(baseTabs.name, baseTabs);
|
|
159
|
-
|
|
160
|
-
import baseTabPane from "@base/components/baseTabs/baseTabPane.vue";
|
|
161
|
-
|
|
162
|
-
Vue.component(baseTabPane.name, baseTabPane);
|
|
163
|
-
|
|
164
|
-
import vb_tabs from "@base/components/vb-tabs/index.vue";
|
|
165
|
-
import vb_tab_pane from "@base/components/vb-tabs/tab-pane.vue";
|
|
166
|
-
import xTabs from "@base/components/vb-tabs/x-tabs.vue";
|
|
167
|
-
|
|
168
|
-
Vue.component(vb_tabs.name, vb_tabs);
|
|
169
|
-
Vue.component(vb_tab_pane.name, vb_tab_pane);
|
|
170
|
-
Vue.component(xTabs.name, xTabs);
|
|
171
|
-
|
|
172
|
-
Vue.component("status-tag", () =>
|
|
173
|
-
import("@base/components/statusTag/index.vue")
|
|
174
|
-
);
|
|
175
|
-
|
|
176
|
-
Vue.component("CodeEditor", () =>
|
|
177
|
-
import("@base/components/code-editor/index.vue")
|
|
178
|
-
);
|
|
179
|
-
|
|
180
|
-
Vue.component("scriptDescriptionButton", () =>
|
|
181
|
-
import("@base/components/scriptDescription/button")
|
|
182
|
-
);
|
|
183
|
-
|
|
184
|
-
Vue.component("scriptTestButton", () =>
|
|
185
|
-
import("@base/components/scriptTest/button")
|
|
186
|
-
);
|
|
187
|
-
|
|
188
|
-
import baseTextarea from "@base/components/base-textarea/index.vue";
|
|
189
|
-
|
|
190
|
-
Vue.component(baseTextarea.name, baseTextarea);
|
|
191
|
-
|
|
192
|
-
import jsonImport from "@base/components/jsonImport/index.js";
|
|
193
|
-
|
|
194
|
-
Vue.use(jsonImport);
|
|
195
|
-
|
|
196
|
-
import langImport from "@base/components/langImport/index.js";
|
|
197
|
-
|
|
198
|
-
Vue.use(langImport);
|
|
31
|
+
import installLoginVab from "@base/utils/loginVab";
|
|
32
|
+
|
|
33
|
+
Vue.use(installLoginVab);
|
|
199
34
|
|
|
200
35
|
//vform
|
|
201
36
|
// import '@base/components/xform/utils/directive'
|
|
@@ -215,17 +50,27 @@ if (process.env.NODE_ENV === "production") {
|
|
|
215
50
|
mockXHR() */
|
|
216
51
|
}
|
|
217
52
|
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
53
|
+
[
|
|
54
|
+
Button,
|
|
55
|
+
Checkbox,
|
|
56
|
+
Dialog,
|
|
57
|
+
Form,
|
|
58
|
+
FormItem,
|
|
59
|
+
Input,
|
|
60
|
+
TabPane,
|
|
61
|
+
Tabs,
|
|
62
|
+
Tooltip,
|
|
63
|
+
].forEach((component) => Vue.use(component));
|
|
64
|
+
Vue.use(Loading.directive);
|
|
65
|
+
Vue.prototype.$ELEMENT = { size: Cookies.get("size") || "medium" };
|
|
66
|
+
Vue.prototype.$loading = Loading.service;
|
|
67
|
+
Vue.prototype.$message = Message;
|
|
68
|
+
Vue.prototype.$msgbox = MessageBox;
|
|
69
|
+
Vue.prototype.$alert = MessageBox.alert;
|
|
70
|
+
Vue.prototype.$confirm = MessageBox.confirm;
|
|
71
|
+
Vue.prototype.$prompt = MessageBox.prompt;
|
|
72
|
+
|
|
73
|
+
Vue.config.productionTip = false;
|
|
229
74
|
|
|
230
75
|
let instance = null;
|
|
231
76
|
|
package/src/permission.js
CHANGED
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
/**version-1.0*/
|
|
2
2
|
import router from "@base/router";
|
|
3
3
|
import store from "./store";
|
|
4
|
-
import
|
|
5
|
-
Message
|
|
6
|
-
} from "element-ui";
|
|
4
|
+
import Message from "element-ui/lib/message";
|
|
7
5
|
import NProgress from "nprogress"; // progress bar
|
|
8
6
|
import "nprogress/nprogress.css"; // progress bar style
|
|
9
7
|
import {
|
|
10
8
|
getToken
|
|
11
9
|
} from "./utils/auth"; // get token from cookie
|
|
12
|
-
import settingConfig from "@/settings";
|
|
10
|
+
import settingConfig from "@/settings";
|
|
11
|
+
import {
|
|
12
|
+
ensureBusinessFeatures,
|
|
13
|
+
preloadBusinessFeatures,
|
|
14
|
+
} from "@base/bootstrap/business";
|
|
13
15
|
|
|
14
16
|
import {
|
|
15
17
|
saveAccessMenuLog
|
|
@@ -20,23 +22,63 @@ NProgress.configure({
|
|
|
20
22
|
showSpinner: false,
|
|
21
23
|
}); // NProgress Configuration
|
|
22
24
|
|
|
23
|
-
const whiteList = [
|
|
25
|
+
const whiteList = [
|
|
24
26
|
"/login",
|
|
25
27
|
"/auth-redirect",
|
|
26
28
|
"/report/vform/out_render",
|
|
27
29
|
"/report/xform/out_render",
|
|
28
|
-
]; // no redirect whitelist
|
|
30
|
+
]; // no redirect whitelist
|
|
31
|
+
|
|
32
|
+
// 这些页面只依赖登录核心包;其余已登录页面和免登录业务页在进入前加载业务能力。
|
|
33
|
+
const lightweightRoutes = new Set([
|
|
34
|
+
"/login",
|
|
35
|
+
"/auth-redirect",
|
|
36
|
+
"/404",
|
|
37
|
+
]);
|
|
38
|
+
const parallelBusinessRoutes = new Set(["/", "/home"]);
|
|
39
|
+
|
|
40
|
+
function needsBusinessFeatures(to) {
|
|
41
|
+
return !lightweightRoutes.has(to.path)
|
|
42
|
+
&& (getToken() || to.meta.checkToken === false);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function handleBusinessFeatureError(error, next) {
|
|
46
|
+
console.error("[bootstrap] 业务模块加载失败", error);
|
|
47
|
+
Message.error("业务模块加载失败,请刷新后重试");
|
|
48
|
+
NProgress.done();
|
|
49
|
+
next(false);
|
|
50
|
+
}
|
|
29
51
|
|
|
30
52
|
// qiankun 保活:子应用容器被隐藏期间暂停一切路由响应(配合包入口 update 生命周期)
|
|
31
|
-
router.beforeEach((to, from, next) => {
|
|
32
|
-
if (store.state.micro && store.state.micro.routerPaused) {
|
|
53
|
+
router.beforeEach((to, from, next) => {
|
|
54
|
+
if (store.state.micro && store.state.micro.routerPaused) {
|
|
33
55
|
next(false);
|
|
34
56
|
return;
|
|
35
57
|
}
|
|
36
|
-
next();
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
router.beforeEach((to, from, next) => {
|
|
58
|
+
next();
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
router.beforeEach((to, from, next) => {
|
|
62
|
+
if (!needsBusinessFeatures(to)) {
|
|
63
|
+
next();
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
NProgress.start();
|
|
67
|
+
|
|
68
|
+
// 首页首跳先启动下载,再让鉴权守卫并行拉用户信息和菜单;最终在
|
|
69
|
+
// beforeResolve 中等待安装完成,确保组件渲染前全局能力已经就绪。
|
|
70
|
+
if (parallelBusinessRoutes.has(to.path)) {
|
|
71
|
+
preloadBusinessFeatures();
|
|
72
|
+
next();
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
ensureBusinessFeatures()
|
|
77
|
+
.then(() => next())
|
|
78
|
+
.catch((error) => handleBusinessFeatureError(error, next));
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
router.beforeEach((to, from, next) => {
|
|
40
82
|
// start progress bar
|
|
41
83
|
NProgress.start();
|
|
42
84
|
|
|
@@ -116,9 +158,23 @@ router.beforeEach((to, from, next) => {
|
|
|
116
158
|
})
|
|
117
159
|
|
|
118
160
|
|
|
119
|
-
});
|
|
120
|
-
|
|
121
|
-
router.
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
router.beforeResolve((to, from, next) => {
|
|
164
|
+
if (
|
|
165
|
+
!needsBusinessFeatures(to)
|
|
166
|
+
|| !parallelBusinessRoutes.has(to.path)
|
|
167
|
+
) {
|
|
168
|
+
next();
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
ensureBusinessFeatures()
|
|
173
|
+
.then(() => next())
|
|
174
|
+
.catch((error) => handleBusinessFeatureError(error, next));
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
router.onError((error) => {
|
|
122
178
|
// finish progress bar
|
|
123
179
|
console.error(error);
|
|
124
180
|
NProgress.done();
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import { constantRoutes } from "@base/router";
|
|
2
|
-
import { asyncRoutes, sidebarRoutes } from "@base/router/modules/system";
|
|
3
|
-
import
|
|
4
|
-
import { getRouters } from "../../api/menu";
|
|
1
|
+
import { constantRoutes } from "@base/router";
|
|
2
|
+
import { asyncRoutes, sidebarRoutes } from "@base/router/modules/system";
|
|
3
|
+
import { getRouters } from "../../api/menu";
|
|
5
4
|
import router from "@base/router";
|
|
6
5
|
import storeConfig from "../config/index";
|
|
7
6
|
import settings from "@/settings";
|
|
@@ -10,12 +9,12 @@ import {
|
|
|
10
9
|
resolveOwner,
|
|
11
10
|
dispatchMenus,
|
|
12
11
|
} from "@base/utils/menuAdapter";
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
12
|
+
|
|
13
|
+
const Layout = () => import(/* webpackChunkName: "layout" */ "@/layout");
|
|
14
|
+
const MenuFallback = () =>
|
|
15
|
+
import(
|
|
16
|
+
/* webpackChunkName: "menu-fallback" */ "@base/views/user/menuFallback/index.vue"
|
|
17
|
+
);
|
|
19
18
|
|
|
20
19
|
// qiankun 宿主态(仅 settings.microMainEnabled 的主应用登录后填充)
|
|
21
20
|
let hostRegistryApps = [];
|
|
@@ -230,34 +229,37 @@ const actions = {
|
|
|
230
229
|
},
|
|
231
230
|
// qiankun 宿主编排:拉注册表 → 按归属切分 → 注册子应用,再走常规路由生成。
|
|
232
231
|
// 非宿主(未开 microMainEnabled / 自身被 qiankun 挂载)直接透传。
|
|
233
|
-
setupHostAndRoutes({ dispatch, commit, rootState }, rows = []) {
|
|
232
|
+
setupHostAndRoutes({ dispatch, commit, rootState }, rows = []) {
|
|
234
233
|
let isHost =
|
|
235
234
|
settings.microMainEnabled === true && !window.__POWERED_BY_QIANKUN__;
|
|
236
|
-
if (!isHost) {
|
|
237
|
-
return dispatch("setSidebarRoute", rows);
|
|
238
|
-
}
|
|
239
|
-
return
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
235
|
+
if (!isHost) {
|
|
236
|
+
return dispatch("setSidebarRoute", rows);
|
|
237
|
+
}
|
|
238
|
+
return import("@base/microRouter").then(
|
|
239
|
+
({ getAppRegistry, registerSubApps, buildSubAppRoutes }) =>
|
|
240
|
+
getAppRegistry().then((apps) => {
|
|
241
|
+
// 自排除:自身也在注册表时(子应用开宿主形态互访别家应用)不装载自己,
|
|
242
|
+
// 否则会自嵌套且自身菜单被误判为"派发给子应用"而跳过本地路由
|
|
243
|
+
let ownAppCode = settings.appCode || "";
|
|
244
|
+
hostRegistryApps = (apps || []).filter(
|
|
245
|
+
(app) => app.appCode !== ownAppCode
|
|
246
|
+
);
|
|
247
|
+
commit(
|
|
248
|
+
"SET_REGISTRY_APP_CODES",
|
|
249
|
+
hostRegistryApps.map((app) => app.appCode)
|
|
250
|
+
);
|
|
251
|
+
let subAppMenus = dispatchMenus(rows, hostRegistryApps);
|
|
252
|
+
hostMicroRoutes = buildSubAppRoutes(hostRegistryApps, subAppMenus);
|
|
253
|
+
if (hostRegistryApps.length) {
|
|
254
|
+
registerSubApps(hostRegistryApps, {
|
|
255
|
+
subAppMenus,
|
|
256
|
+
userInfo: buildUserInfoSnapshot(rootState.user),
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
return dispatch("setSidebarRoute", rows);
|
|
260
|
+
})
|
|
261
|
+
);
|
|
262
|
+
},
|
|
261
263
|
// qiankun 子应用模式:主应用经 props 下发菜单,替代 getRouters 自拉
|
|
262
264
|
generateRoutesFromProps({ dispatch, rootState }, menus = []) {
|
|
263
265
|
// 调试覆盖装载时允许 URL 直达未配菜单的页面(handleMenuRoutes 追加兜底路由)
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import store from "../index.js";
|
|
2
|
-
import _ from "lodash";
|
|
3
2
|
import { isRepeatable, viewKey } from "@base/utils/repeatOpen";
|
|
4
3
|
|
|
5
4
|
let state, mutations, actions;
|
|
@@ -201,7 +200,7 @@ actions = {
|
|
|
201
200
|
let newView0 = { ...(view || window.$vueRoot.$route) };
|
|
202
201
|
delete newView0.matched;
|
|
203
202
|
newView0.meta.title = title;
|
|
204
|
-
let newView =
|
|
203
|
+
let newView = JSON.parse(JSON.stringify(newView0));
|
|
205
204
|
|
|
206
205
|
commit("UPDATE_VISITED_VIEW", newView);
|
|
207
206
|
},
|
|
@@ -10,7 +10,6 @@ import {
|
|
|
10
10
|
} from "../../api/user";
|
|
11
11
|
import { getToken, setToken, clearToken } from "../../utils/auth";
|
|
12
12
|
import router, { resetRouter } from "@base/router";
|
|
13
|
-
import { unmountAllMicroApps } from "@base/microRouter";
|
|
14
13
|
import { getDispermissions } from "../../api/menu";
|
|
15
14
|
import settingConfig from "@/settings";
|
|
16
15
|
import storeConfig from "../config/index";
|
|
@@ -330,14 +329,21 @@ actions = {
|
|
|
330
329
|
configUtil.clearToken();
|
|
331
330
|
// qiankun 宿主:登出必须真正卸载保活中的子应用,
|
|
332
331
|
// 否则换账号登录后切回子应用会复活上一个用户的实例(旧角色/旧路由/旧页面数据)
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
332
|
+
import("@base/microRouter")
|
|
333
|
+
.then(({ unmountAllMicroApps }) => unmountAllMicroApps())
|
|
334
|
+
.catch((error) => {
|
|
335
|
+
// 微前端 chunk 加载失败不能阻断本地登录态清理
|
|
336
|
+
console.error("[user] 微应用卸载模块加载失败", error);
|
|
337
|
+
})
|
|
338
|
+
.then(() => {
|
|
339
|
+
configUtil.resetRouter();
|
|
340
|
+
sessionStorage.removeItem("easyweb");
|
|
341
|
+
|
|
342
|
+
dispatch("tagsView/delAllViews", null, {
|
|
343
|
+
root: true,
|
|
344
|
+
});
|
|
345
|
+
resolve();
|
|
346
|
+
});
|
|
341
347
|
});
|
|
342
348
|
},
|
|
343
349
|
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
const assetPromises = Object.create(null);
|
|
2
|
+
|
|
3
|
+
export function getPublicAssetUrl(path) {
|
|
4
|
+
const baseUrl = (process.env.BASE_URL || "/").replace(/\/?$/, "/");
|
|
5
|
+
return baseUrl + String(path || "").replace(/^\//, "");
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
function findAsset(tagName, attribute, url) {
|
|
9
|
+
return Array.from(document.getElementsByTagName(tagName)).find(
|
|
10
|
+
(element) => element.getAttribute(attribute) === url
|
|
11
|
+
);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function loadStyle(href, attributes = {}) {
|
|
15
|
+
const key = "style:" + href;
|
|
16
|
+
if (assetPromises[key]) return assetPromises[key];
|
|
17
|
+
const existing = findAsset("link", "href", href);
|
|
18
|
+
if (existing) return Promise.resolve(existing);
|
|
19
|
+
|
|
20
|
+
assetPromises[key] = new Promise((resolve, reject) => {
|
|
21
|
+
const link = document.createElement("link");
|
|
22
|
+
link.rel = "stylesheet";
|
|
23
|
+
link.href = href;
|
|
24
|
+
Object.keys(attributes).forEach((name) => {
|
|
25
|
+
link.setAttribute(name, attributes[name]);
|
|
26
|
+
});
|
|
27
|
+
link.onload = () => resolve(link);
|
|
28
|
+
link.onerror = () => {
|
|
29
|
+
delete assetPromises[key];
|
|
30
|
+
link.remove();
|
|
31
|
+
reject(new Error("样式加载失败:" + href));
|
|
32
|
+
};
|
|
33
|
+
document.head.appendChild(link);
|
|
34
|
+
});
|
|
35
|
+
return assetPromises[key];
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function loadStyles(hrefs) {
|
|
39
|
+
return Promise.all(hrefs.map((href) => loadStyle(href)));
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function loadScript(src) {
|
|
43
|
+
const key = "script:" + src;
|
|
44
|
+
if (assetPromises[key]) return assetPromises[key];
|
|
45
|
+
const existing = findAsset("script", "src", src);
|
|
46
|
+
if (existing) return Promise.resolve(existing);
|
|
47
|
+
|
|
48
|
+
assetPromises[key] = new Promise((resolve, reject) => {
|
|
49
|
+
const script = document.createElement("script");
|
|
50
|
+
script.src = src;
|
|
51
|
+
script.async = true;
|
|
52
|
+
script.onload = () => resolve(script);
|
|
53
|
+
script.onerror = () => {
|
|
54
|
+
delete assetPromises[key];
|
|
55
|
+
script.remove();
|
|
56
|
+
reject(new Error("脚本加载失败:" + src));
|
|
57
|
+
};
|
|
58
|
+
document.head.appendChild(script);
|
|
59
|
+
});
|
|
60
|
+
return assetPromises[key];
|
|
61
|
+
}
|
|
62
|
+
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
// API 模块沿用 USER_PREFIX 等全局常量;完整 Vab 延迟加载后,登录阶段需先恢复
|
|
2
|
+
// 这项原本由 vab.js 模块初始化完成的副作用。
|
|
3
|
+
import "@base/utils/prefixGlobals";
|
|
4
|
+
import Loading from "element-ui/lib/loading";
|
|
5
|
+
import MessageBox from "element-ui/lib/message-box";
|
|
6
|
+
import request from "@base/utils/request";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* 登录阶段需要的最小 Vab 能力。完整 Vab 会连带 lodash、moment、XEUtils、
|
|
10
|
+
* 图片预览等后台依赖,改为进入业务路由后再覆盖安装。
|
|
11
|
+
*/
|
|
12
|
+
export default function installLoginVab(Vue) {
|
|
13
|
+
Vue.prototype.$baseEventBus = new Vue();
|
|
14
|
+
const $http = async function (option = {}) {
|
|
15
|
+
if (!option.loadingTarget && this.$el) {
|
|
16
|
+
option.loadingTarget = this.$el;
|
|
17
|
+
}
|
|
18
|
+
if (!option.vueTarget) {
|
|
19
|
+
option.vueTarget = this;
|
|
20
|
+
}
|
|
21
|
+
return option.sync === false ? await request(option) : request(option);
|
|
22
|
+
};
|
|
23
|
+
Object.assign($http, request);
|
|
24
|
+
$http.prototype = request.prototype;
|
|
25
|
+
Vue.prototype.$http = $http;
|
|
26
|
+
|
|
27
|
+
Vue.prototype.$baseLoading = function (option = {}) {
|
|
28
|
+
const opts = {
|
|
29
|
+
lock: true,
|
|
30
|
+
background: "hsla(0,0%,100%,.8)",
|
|
31
|
+
target: this.$el,
|
|
32
|
+
...option,
|
|
33
|
+
};
|
|
34
|
+
if (option.index) {
|
|
35
|
+
opts.spinner = "vab-loading-type" + option.index;
|
|
36
|
+
}
|
|
37
|
+
return Loading.service(opts);
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
Vue.prototype.$baseAlert = function (content, title, callback) {
|
|
41
|
+
return MessageBox.alert(content, title || "提示", {
|
|
42
|
+
confirmButtonText: "确定",
|
|
43
|
+
dangerouslyUseHTMLString: true,
|
|
44
|
+
target: this.$el,
|
|
45
|
+
confirmButtonClass: "icondui",
|
|
46
|
+
customClass: "dialog-style",
|
|
47
|
+
callback,
|
|
48
|
+
});
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
Vue.prototype.$t1 = function (path, values) {
|
|
52
|
+
const root = this.$root || window.$vueRoot;
|
|
53
|
+
if (!root || !root._i18n) return path;
|
|
54
|
+
const i18n = root.$i18n;
|
|
55
|
+
if (i18n.locale === "zh" || !i18n.te(path)) {
|
|
56
|
+
return i18n._t(path, i18n.locale, { zh: { [path]: path } }, null, values);
|
|
57
|
+
}
|
|
58
|
+
return i18n.t(path, values) || path;
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
Vue.prototype.$t2 = function (defaultValue, path, values) {
|
|
62
|
+
const root = this.$root || window.$vueRoot;
|
|
63
|
+
if (!root || !root._i18n) return defaultValue;
|
|
64
|
+
const i18n = root.$i18n;
|
|
65
|
+
const key = path || defaultValue;
|
|
66
|
+
return i18n.te(key) ? i18n.t(key, values) : defaultValue;
|
|
67
|
+
};
|
|
68
|
+
}
|
package/src/utils/pddLog.js
CHANGED
|
@@ -1,8 +1,22 @@
|
|
|
1
1
|
import settingConfig from "@/settings";
|
|
2
|
+
import { loadScript } from "@base/utils/externalAssets";
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
const PDD_LOG_SDK_URL
|
|
5
|
+
= "https://pfile.pddpic.com/galerie-go/open_sdk/pc.202102201613.js";
|
|
6
|
+
|
|
7
|
+
export async function initPddLog() {
|
|
8
|
+
if (!settingConfig.pddLogEnabled) return;
|
|
9
|
+
if (!window.PDD_OPEN_init) {
|
|
10
|
+
try {
|
|
11
|
+
await loadScript(PDD_LOG_SDK_URL);
|
|
12
|
+
} catch (error) {
|
|
13
|
+
console.warn("[pddLog] SDK 加载失败", error);
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
if (typeof window.PDD_OPEN_init === "function") {
|
|
18
|
+
pddIntfHandle();
|
|
19
|
+
}
|
|
6
20
|
}
|
|
7
21
|
|
|
8
22
|
function getPageCode(callback) {
|
|
@@ -76,7 +90,7 @@ function handleOrderLog(pati) {
|
|
|
76
90
|
async function pddIntfHandle() {
|
|
77
91
|
getPageCode(async (pageCode) => {
|
|
78
92
|
if (!pageCode) return
|
|
79
|
-
PDD_OPEN_init({
|
|
93
|
+
window.PDD_OPEN_init({
|
|
80
94
|
code: pageCode
|
|
81
95
|
// 对于获取 code 接口或未登录态,可不传 code:PDD_OPEN_init({}, function () { ... })
|
|
82
96
|
}, function () {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { encode } from "js-base64";
|
|
2
|
-
import settingConfig from "@/settings";
|
|
3
|
-
import
|
|
1
|
+
import { encode } from "js-base64";
|
|
2
|
+
import settingConfig from "@/settings";
|
|
3
|
+
import { preloadBusinessFeatures } from "@base/bootstrap/business";
|
|
4
4
|
|
|
5
5
|
function getUrlParams(url) {
|
|
6
6
|
let result = {};
|
|
@@ -234,15 +234,19 @@ export default {
|
|
|
234
234
|
reqData = { username: username, smsCode: smsCode, mode: "sms" };
|
|
235
235
|
}
|
|
236
236
|
|
|
237
|
-
if (settingConfig.i18nEnabled) {
|
|
237
|
+
if (settingConfig.i18nEnabled) {
|
|
238
238
|
//登录传语种到后台
|
|
239
239
|
let language = this.$i18n?.locale;
|
|
240
240
|
if (language && language != "zh") {
|
|
241
241
|
reqData.language = language;
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
// 登录接口、部署前缀、用户信息和菜单请求期间并行下载业务模块,
|
|
246
|
+
// 路由守卫会复用同一个 Promise,不增加登录结果等待链路。
|
|
247
|
+
preloadBusinessFeatures();
|
|
248
|
+
|
|
249
|
+
this.$store
|
|
246
250
|
.dispatch("user/login2", reqData)
|
|
247
251
|
.then((res) => {
|
|
248
252
|
if (res.type == "success") {
|
|
@@ -451,8 +455,10 @@ export default {
|
|
|
451
455
|
}
|
|
452
456
|
},
|
|
453
457
|
mobileLogin() {},
|
|
454
|
-
handleRedirectUrl(redirect) {
|
|
455
|
-
|
|
458
|
+
handleRedirectUrl(redirect) {
|
|
459
|
+
// SSO、扫码等非账号密码入口也在跳转前启动预加载。
|
|
460
|
+
preloadBusinessFeatures();
|
|
461
|
+
redirect = redirect || this.$route.query.redirect;
|
|
456
462
|
let path = null;
|
|
457
463
|
if (redirect && redirect.startsWith("/outLinkView")) {
|
|
458
464
|
path = this.addParamToUrl(redirect, "hasToken", "true");
|
|
@@ -640,12 +646,11 @@ export default {
|
|
|
640
646
|
});
|
|
641
647
|
},
|
|
642
648
|
// 生成二维码
|
|
643
|
-
createQR(content, options) {
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
});
|
|
649
|
+
async createQR(content, options) {
|
|
650
|
+
const { default: QRCode } = await import(
|
|
651
|
+
/* webpackChunkName: "login-qrcode" */ "qrcode"
|
|
652
|
+
);
|
|
653
|
+
return QRCode.toDataURL(content, options);
|
|
649
654
|
},
|
|
650
655
|
changeTab() {
|
|
651
656
|
// this.initQR();
|