mooho-base-admin-plus 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env +5 -0
- package/.env.development +0 -0
- package/.env.production +0 -0
- package/.eslintignore +11 -0
- package/.eslintrc.js +47 -0
- package/.prettierrc +15 -0
- package/README.md +18 -0
- package/dist/favicon.ico +0 -0
- package/dist/mooho-base-admin-plus.min.esm.js +131746 -0
- package/dist/mooho-base-admin-plus.min.js +279 -0
- package/dist/setting.js +31 -0
- package/dist/static/images/app-barcode.png +0 -0
- package/dist/static/images/login/bg.png +0 -0
- package/dist/static/images/login/logo.png +0 -0
- package/dist/static/images/login/password-active.png +0 -0
- package/dist/static/images/login/password-default.png +0 -0
- package/dist/static/images/login/signIn-img.png +0 -0
- package/dist/static/images/login/user-active.png +0 -0
- package/dist/static/images/login/user-default.png +0 -0
- package/dist/static/images/logo-dark.png +0 -0
- package/dist/static/images/logo-small.png +0 -0
- package/dist/static/images/logo.png +0 -0
- package/dist/static/images/logo.svg +510 -0
- package/dist/static/images/no-image.png +0 -0
- package/dist/style.css +4 -0
- package/index.html +18 -0
- package/other/pda.vue +28 -0
- package/package.json +59 -0
- package/public/favicon.ico +0 -0
- package/public/setting.js +31 -0
- package/public/static/images/app-barcode.png +0 -0
- package/public/static/images/login/bg.png +0 -0
- package/public/static/images/login/logo.png +0 -0
- package/public/static/images/login/password-active.png +0 -0
- package/public/static/images/login/password-default.png +0 -0
- package/public/static/images/login/signIn-img.png +0 -0
- package/public/static/images/login/user-active.png +0 -0
- package/public/static/images/login/user-default.png +0 -0
- package/public/static/images/logo-dark.png +0 -0
- package/public/static/images/logo-small.png +0 -0
- package/public/static/images/logo.png +0 -0
- package/public/static/images/logo.svg +510 -0
- package/public/static/images/no-image.png +0 -0
- package/src/App.vue +60 -0
- package/src/api/application.js +35 -0
- package/src/api/customModel.js +187 -0
- package/src/api/customPage.js +15 -0
- package/src/api/customTable.js +24 -0
- package/src/api/dataSource.js +93 -0
- package/src/api/dataView.js +199 -0
- package/src/api/dictType.js +23 -0
- package/src/api/entityView.js +13 -0
- package/src/api/enum.js +15 -0
- package/src/api/filterColumn.js +16 -0
- package/src/api/model.js +244 -0
- package/src/api/movePlan.js +29 -0
- package/src/api/notification.js +28 -0
- package/src/api/openApiPermission.js +25 -0
- package/src/api/permission.js +51 -0
- package/src/api/planJob.js +15 -0
- package/src/api/process.js +23 -0
- package/src/api/processDef.js +36 -0
- package/src/api/processInst.js +16 -0
- package/src/api/rolePermission.js +17 -0
- package/src/api/roleProperty.js +36 -0
- package/src/api/shortcut.js +20 -0
- package/src/api/system.js +23 -0
- package/src/api/task.js +56 -0
- package/src/api/taskQueue.js +24 -0
- package/src/api/user.js +45 -0
- package/src/api/viewColumn.js +16 -0
- package/src/assets/svg/body.svg +17 -0
- package/src/assets/svg/header-theme-dark.svg +40 -0
- package/src/assets/svg/header-theme-primary.svg +40 -0
- package/src/assets/svg/header-top.svg +40 -0
- package/src/assets/svg/icon-happy.svg +1 -0
- package/src/assets/svg/icon-sad.svg +1 -0
- package/src/assets/svg/icon-social-bilibili.svg +1 -0
- package/src/assets/svg/icon-social-dingding.svg +1 -0
- package/src/assets/svg/icon-social-facebook.svg +1 -0
- package/src/assets/svg/icon-social-juejin.svg +1 -0
- package/src/assets/svg/icon-social-qq.svg +1 -0
- package/src/assets/svg/icon-social-twitter.svg +1 -0
- package/src/assets/svg/icon-social-wechat.svg +1 -0
- package/src/assets/svg/icon-social-weibo.svg +1 -0
- package/src/assets/svg/icon-social-zhihu.svg +1 -0
- package/src/assets/svg/nav-theme-dark.svg +40 -0
- package/src/assets/svg/nav-theme-light.svg +40 -0
- package/src/components/copyright/index.vue +28 -0
- package/src/components/home/notice-list.vue +62 -0
- package/src/components/home/shortcut.vue +125 -0
- package/src/components/input/dialog-select.vue +301 -0
- package/src/components/input/item-select.vue +195 -0
- package/src/components/link/index.vue +54 -0
- package/src/components/richEditor/index.vue +86 -0
- package/src/components/upload/file-upload.vue +84 -0
- package/src/components/upload/upload-attachment.vue +119 -0
- package/src/components/upload/upload-image.vue +212 -0
- package/src/components/view/column-check.vue +223 -0
- package/src/components/view/column-edit.vue +850 -0
- package/src/components/view/column-select.vue +206 -0
- package/src/components/view/condition-edit.vue +164 -0
- package/src/components/view/filter-edit.vue +633 -0
- package/src/components/view/filter-setting.vue +126 -0
- package/src/components/view/form-setting-layout.vue +375 -0
- package/src/components/view/form-setting.vue +247 -0
- package/src/components/view/group-column.vue +104 -0
- package/src/components/view/group-method.vue +104 -0
- package/src/components/view/mixin.js +72 -0
- package/src/components/view/modal-form-filter.vue +319 -0
- package/src/components/view/modal-form-sort.vue +248 -0
- package/src/components/view/modal-form.vue +453 -0
- package/src/components/view/modal-table.vue +471 -0
- package/src/components/view/table-filter.vue +702 -0
- package/src/components/view/table-setting.vue +533 -0
- package/src/components/view/view-chart.vue +423 -0
- package/src/components/view/view-form-draggable.vue +837 -0
- package/src/components/view/view-form.vue +1444 -0
- package/src/components/view/view-table.vue +2261 -0
- package/src/components/workflow/flow-chart.vue +846 -0
- package/src/directive/focus.js +10 -0
- package/src/directive/tabHide.js +9 -0
- package/src/i18n/index.js +15 -0
- package/src/i18n/locale/en-US.js +1 -0
- package/src/i18n/locale/lang.js +1 -0
- package/src/i18n/locale/zh-CN.js +1 -0
- package/src/i18n/locale.js +102 -0
- package/src/index.js +222 -0
- package/src/layouts/basic-layout/header-breadcrumb/index.vue +122 -0
- package/src/layouts/basic-layout/header-collapse/index.vue +44 -0
- package/src/layouts/basic-layout/header-fullscreen/index.vue +19 -0
- package/src/layouts/basic-layout/header-i18n/index.vue +45 -0
- package/src/layouts/basic-layout/header-log/index.vue +41 -0
- package/src/layouts/basic-layout/header-logo/index.vue +23 -0
- package/src/layouts/basic-layout/header-notice/index.vue +218 -0
- package/src/layouts/basic-layout/header-reload/index.vue +21 -0
- package/src/layouts/basic-layout/header-search/index.vue +37 -0
- package/src/layouts/basic-layout/header-setting/index.vue +219 -0
- package/src/layouts/basic-layout/header-user/index.vue +175 -0
- package/src/layouts/basic-layout/i18n.js +50 -0
- package/src/layouts/basic-layout/index.vue +280 -0
- package/src/layouts/basic-layout/menu-head/index.vue +120 -0
- package/src/layouts/basic-layout/menu-head/title.vue +48 -0
- package/src/layouts/basic-layout/menu-side/index.vue +113 -0
- package/src/layouts/basic-layout/menu-side/menu-collapse.vue +76 -0
- package/src/layouts/basic-layout/menu-side/menu-item.vue +31 -0
- package/src/layouts/basic-layout/menu-side/menu-title.vue +56 -0
- package/src/layouts/basic-layout/menu-side/submenu.vue +31 -0
- package/src/layouts/basic-layout/mixins/click-item.js +21 -0
- package/src/layouts/basic-layout/mixins/sider-menu-badge.js +13 -0
- package/src/layouts/basic-layout/mixins/translate-title.js +11 -0
- package/src/layouts/basic-layout/tabs/index.vue +192 -0
- package/src/layouts/basic-layout/water-mark/index.vue +29 -0
- package/src/libs/lodop/index.js +145 -0
- package/src/libs/random_str.js +10 -0
- package/src/libs/request/index.js +158 -0
- package/src/libs/system/index.js +234 -0
- package/src/libs/util.cookies.js +44 -0
- package/src/libs/util.db.js +13 -0
- package/src/libs/util.js +55 -0
- package/src/libs/util.log.js +88 -0
- package/src/libs/water-mark.js +44 -0
- package/src/menu/header.js +20 -0
- package/src/menu/modules/dashboard.js +23 -0
- package/src/menu/sider.js +12 -0
- package/src/mixins/app.js +9 -0
- package/src/mixins/page.js +643 -0
- package/src/pages/account/login.vue +101 -0
- package/src/pages/common/home.vue +169 -0
- package/src/pages/common/task-form.vue +350 -0
- package/src/pages/common/todo.vue +31 -0
- package/src/pages/system/apiLog.vue +79 -0
- package/src/pages/system/applicationType.vue +182 -0
- package/src/pages/system/customPage.vue +62 -0
- package/src/pages/system/customTable.vue +98 -0
- package/src/pages/system/dict.vue +36 -0
- package/src/pages/system/dictType.vue +58 -0
- package/src/pages/system/entityView.vue +38 -0
- package/src/pages/system/error/404.vue +6 -0
- package/src/pages/system/extendColumn.vue +99 -0
- package/src/pages/system/formView.vue +136 -0
- package/src/pages/system/log.vue +55 -0
- package/src/pages/system/notice.vue +26 -0
- package/src/pages/system/openApi.vue +26 -0
- package/src/pages/system/openUser.vue +66 -0
- package/src/pages/system/organization.vue +98 -0
- package/src/pages/system/organizationType.vue +26 -0
- package/src/pages/system/permission.vue +175 -0
- package/src/pages/system/planJob.vue +40 -0
- package/src/pages/system/printTemplate.vue +48 -0
- package/src/pages/system/process.vue +79 -0
- package/src/pages/system/processType.vue +26 -0
- package/src/pages/system/role.vue +395 -0
- package/src/pages/system/rolePropertyEdit.vue +480 -0
- package/src/pages/system/sequenceSetting.vue +26 -0
- package/src/pages/system/systemData.vue +52 -0
- package/src/pages/system/tableView.vue +386 -0
- package/src/pages/system/taskQueue.vue +48 -0
- package/src/pages/system/user.vue +250 -0
- package/src/pages/template/processPage.vue +243 -0
- package/src/pages/template/reportPage.vue +66 -0
- package/src/pages/template/viewPage.vue +139 -0
- package/src/plugins/auth/index.js +21 -0
- package/src/plugins/error/index.js +31 -0
- package/src/plugins/index.js +24 -0
- package/src/plugins/sweetalert2/index.js +20 -0
- package/src/router/dynamic.js +183 -0
- package/src/router/index.js +84 -0
- package/src/setting.js +202 -0
- package/src/store/index.js +9 -0
- package/src/store/modules/admin/index.js +16 -0
- package/src/store/modules/admin/modules/account.js +103 -0
- package/src/store/modules/admin/modules/cache.js +119 -0
- package/src/store/modules/admin/modules/dataView.js +112 -0
- package/src/store/modules/admin/modules/db.js +231 -0
- package/src/store/modules/admin/modules/i18n.js +87 -0
- package/src/store/modules/admin/modules/layout.js +115 -0
- package/src/store/modules/admin/modules/loader.js +44 -0
- package/src/store/modules/admin/modules/log.js +77 -0
- package/src/store/modules/admin/modules/menu.js +338 -0
- package/src/store/modules/admin/modules/page.js +466 -0
- package/src/store/modules/admin/modules/user.js +96 -0
- package/src/store/modules/admin/modules/viewPage.js +34 -0
- package/src/styles/common.less +47 -0
- package/src/styles/css/default.css +510 -0
- package/src/styles/css/login.css +1217 -0
- package/src/styles/default/index.less +6 -0
- package/src/styles/font/demo.css +539 -0
- package/src/styles/font/demo_index.html +372 -0
- package/src/styles/font/icon-demo/demo.css +539 -0
- package/src/styles/font/icon-demo/demo_index.html +423 -0
- package/src/styles/font/icon-demo/iconfont.css +61 -0
- package/src/styles/font/icon-demo/iconfont.eot +0 -0
- package/src/styles/font/icon-demo/iconfont.js +1 -0
- package/src/styles/font/icon-demo/iconfont.svg +59 -0
- package/src/styles/font/icon-demo/iconfont.ttf +0 -0
- package/src/styles/font/icon-demo/iconfont.woff +0 -0
- package/src/styles/font/icon-demo/iconfont.woff2 +0 -0
- package/src/styles/font/iconfont.css +47 -0
- package/src/styles/font/iconfont.js +1 -0
- package/src/styles/font/iconfont.json +65 -0
- package/src/styles/font/iconfont.ttf +0 -0
- package/src/styles/font/iconfont.woff +0 -0
- package/src/styles/font/iconfont.woff2 +0 -0
- package/src/styles/font/ionicons.svg +870 -0
- package/src/styles/font/ionicons.ttf +0 -0
- package/src/styles/font/ionicons.woff +0 -0
- package/src/styles/font/ionicons.woff2 +0 -0
- package/src/styles/index.less +7 -0
- package/src/styles/layout/basic-layout/layout.less +527 -0
- package/src/styles/layout/basic-layout/menu.less +274 -0
- package/src/styles/layout/index.less +2 -0
- package/src/styles/setting.less +6 -0
- package/styleguide.config.js +22 -0
- package/test/api/barcode.js +50 -0
- package/test/api/inbound.js +47 -0
- package/test/api/interfaceLog.js +15 -0
- package/test/api/interfaceQueue.js +15 -0
- package/test/api/interfaceServer.js +29 -0
- package/test/api/movePlan.js +50 -0
- package/test/api/movePlanItem.js +13 -0
- package/test/api/moveType.js +22 -0
- package/test/api/openApiPermission.js +25 -0
- package/test/api/outbound.js +40 -0
- package/test/api/permission.js +34 -0
- package/test/api/rolePermission.js +17 -0
- package/test/api/user.js +40 -0
- package/test/api/viewColumn.js +16 -0
- package/test/api/warehouse.js +13 -0
- package/test/api/warehouseMoveType.js +18 -0
- package/test/main.js +55 -0
- package/test/package.js +33 -0
- package/test/pages/home/index.vue +22 -0
- package/test/pages/task/test.vue +28 -0
- package/test/pages/test/dataViewTest.vue +28 -0
- package/test/pages/test/logReport.vue +25 -0
- package/test/pages/test/testPage.vue +38 -0
- package/test/router/routes.js +88 -0
- package/test/setting.env.js +22 -0
- package/test/styles/css/custom.css +0 -0
- package/test/styles/css/login.css +1217 -0
- package/vite.config.js +72 -0
- package/vue.config.js +20 -0
|
@@ -0,0 +1,466 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 多标签页
|
|
3
|
+
* */
|
|
4
|
+
import { get, cloneDeep } from 'lodash';
|
|
5
|
+
import router from '../../../../router';
|
|
6
|
+
import Setting from '../../../../setting';
|
|
7
|
+
import menuSider from '../../../../menu/sider';
|
|
8
|
+
import { getAllSiderMenu, includeArray } from '../../../../libs/system';
|
|
9
|
+
|
|
10
|
+
// 判定是否需要缓存
|
|
11
|
+
const isKeepAlive = data => get(data, 'meta.cache', false);
|
|
12
|
+
|
|
13
|
+
export default {
|
|
14
|
+
namespaced: true,
|
|
15
|
+
state: {
|
|
16
|
+
// 可以在多页 tab 模式下显示的页面
|
|
17
|
+
pool: [],
|
|
18
|
+
// 当前显示的多页面列表
|
|
19
|
+
opened: Setting.page.opened,
|
|
20
|
+
// 当前页面
|
|
21
|
+
current: '',
|
|
22
|
+
// 需要缓存的页面 name
|
|
23
|
+
keepAlive: []
|
|
24
|
+
},
|
|
25
|
+
actions: {
|
|
26
|
+
/**
|
|
27
|
+
* @description 从持久化数据载入分页列表
|
|
28
|
+
*/
|
|
29
|
+
openedLoad({ state, commit, dispatch, rootState }, { loadOpenedTabs = true }) {
|
|
30
|
+
return new Promise(async resolve => {
|
|
31
|
+
// store 赋值
|
|
32
|
+
let value = await dispatch(
|
|
33
|
+
'admin/db/get',
|
|
34
|
+
{
|
|
35
|
+
dbName: 'sys',
|
|
36
|
+
path: 'page.opened',
|
|
37
|
+
defaultValue: Setting.page.opened,
|
|
38
|
+
user: true
|
|
39
|
+
},
|
|
40
|
+
{ root: true }
|
|
41
|
+
);
|
|
42
|
+
if (!loadOpenedTabs) value = [];
|
|
43
|
+
// 在处理函数中进行数据优化 过滤掉现在已经失效的页签或者已经改变了信息的页签
|
|
44
|
+
// 以 fullPath 字段为准
|
|
45
|
+
// 如果页面过多的话可能需要优化算法
|
|
46
|
+
// valid 有效列表 1, 1, 0, 1 => 有效, 有效, 失效, 有效
|
|
47
|
+
const valid = [];
|
|
48
|
+
// 处理数据
|
|
49
|
+
state.opened = value
|
|
50
|
+
.map(opened => {
|
|
51
|
+
// 忽略首页
|
|
52
|
+
if (opened.fullPath === '/index') {
|
|
53
|
+
valid.push(1);
|
|
54
|
+
return opened;
|
|
55
|
+
}
|
|
56
|
+
// 尝试在所有的支持多标签页的页面里找到 name 匹配的页面
|
|
57
|
+
const find = state.pool.find(item => item.name === opened.name);
|
|
58
|
+
// 如果 value 项有 keepMeta 字段,则保留 meta
|
|
59
|
+
if (opened.keepMeta) {
|
|
60
|
+
find.meta = Object.assign({}, opened.meta);
|
|
61
|
+
}
|
|
62
|
+
// 记录有效或无效信息
|
|
63
|
+
valid.push(find ? 1 : 0);
|
|
64
|
+
// 返回合并后的数据 新的覆盖旧的
|
|
65
|
+
// 新的数据中一般不会携带 params 和 query, 所以旧的参数会留存
|
|
66
|
+
return Object.assign({}, opened, find);
|
|
67
|
+
})
|
|
68
|
+
.filter((opened, index) => valid[index] === 1)
|
|
69
|
+
// 对 menu 鉴权过滤
|
|
70
|
+
.filter(opened => {
|
|
71
|
+
const allSiderMenu = getAllSiderMenu(menuSider);
|
|
72
|
+
const find = allSiderMenu.find(item => item.path === opened.fullPath);
|
|
73
|
+
|
|
74
|
+
let state = true;
|
|
75
|
+
if (find && find.auth) {
|
|
76
|
+
const userInfo = rootState.admin.user.info;
|
|
77
|
+
// @权限
|
|
78
|
+
const access = cloneDeep(userInfo.access);
|
|
79
|
+
// 给 access 强制加一个 hidden 的权限,否则菜单隐藏后,Tabs 页签会不显示该页签
|
|
80
|
+
access.push('hidden');
|
|
81
|
+
// 如果用户当前的权限,不是该 menu 对应的 权限,则过滤这个 Tab
|
|
82
|
+
if (access && !includeArray(find.auth, access)) state = false;
|
|
83
|
+
}
|
|
84
|
+
return state;
|
|
85
|
+
});
|
|
86
|
+
// 根据 opened 数据生成缓存设置
|
|
87
|
+
commit('keepAliveRefresh');
|
|
88
|
+
// end
|
|
89
|
+
resolve();
|
|
90
|
+
});
|
|
91
|
+
},
|
|
92
|
+
/**
|
|
93
|
+
* 将 opened 属性赋值并持久化 在这之前请先确保已经更新了 state.opened
|
|
94
|
+
*/
|
|
95
|
+
opened2db({ state, dispatch }) {
|
|
96
|
+
return new Promise(async resolve => {
|
|
97
|
+
// 设置数据
|
|
98
|
+
dispatch(
|
|
99
|
+
'admin/db/set',
|
|
100
|
+
{
|
|
101
|
+
dbName: 'sys',
|
|
102
|
+
path: 'page.opened',
|
|
103
|
+
value: state.opened,
|
|
104
|
+
user: true
|
|
105
|
+
},
|
|
106
|
+
{ root: true }
|
|
107
|
+
);
|
|
108
|
+
// end
|
|
109
|
+
resolve();
|
|
110
|
+
});
|
|
111
|
+
},
|
|
112
|
+
/**
|
|
113
|
+
* @description 更新页面列表上的某一项
|
|
114
|
+
* @param {Object} param { index, params, query, fullPath } 路由信息
|
|
115
|
+
*/
|
|
116
|
+
openedUpdate({ state, dispatch }, { index, params, query, fullPath, meta, keepMeta = false }) {
|
|
117
|
+
return new Promise(async resolve => {
|
|
118
|
+
// 更新页面列表某一项
|
|
119
|
+
let page = state.opened[index];
|
|
120
|
+
page.params = params || page.params;
|
|
121
|
+
page.query = query || page.query;
|
|
122
|
+
page.fullPath = fullPath || page.fullPath;
|
|
123
|
+
page.meta = meta || page.meta;
|
|
124
|
+
page.keepMeta = keepMeta;
|
|
125
|
+
state.opened.splice(index, 1, page);
|
|
126
|
+
// 持久化
|
|
127
|
+
await dispatch('opened2db');
|
|
128
|
+
// end
|
|
129
|
+
resolve();
|
|
130
|
+
});
|
|
131
|
+
},
|
|
132
|
+
/**
|
|
133
|
+
* @description 更新页面当前项
|
|
134
|
+
* @param {Object} param { params, query, fullPath } 路由信息
|
|
135
|
+
*/
|
|
136
|
+
currentUpdate({ state, dispatch }, { params, query, fullPath, meta, keepMeta = false }) {
|
|
137
|
+
return new Promise(async resolve => {
|
|
138
|
+
setTimeout(async () => {
|
|
139
|
+
// 更新当前项
|
|
140
|
+
const index = state.opened.findIndex(item => item.fullPath === state.current);
|
|
141
|
+
let page = state.opened[index];
|
|
142
|
+
page.params = params || page.params;
|
|
143
|
+
page.query = query || page.query;
|
|
144
|
+
page.fullPath = fullPath || page.fullPath;
|
|
145
|
+
page.meta = meta || page.meta;
|
|
146
|
+
page.keepMeta = keepMeta;
|
|
147
|
+
state.opened.splice(index, 1, page);
|
|
148
|
+
// 持久化
|
|
149
|
+
await dispatch('opened2db');
|
|
150
|
+
// end
|
|
151
|
+
resolve();
|
|
152
|
+
}, 0);
|
|
153
|
+
});
|
|
154
|
+
},
|
|
155
|
+
/**
|
|
156
|
+
* @description 新增一个 tag (打开一个页面)
|
|
157
|
+
* @param {Object} param new tag info
|
|
158
|
+
*/
|
|
159
|
+
add({ state, commit, dispatch }, { tag, params, query, fullPath }) {
|
|
160
|
+
return new Promise(async resolve => {
|
|
161
|
+
// 设置新的 tag 在新打开一个以前没打开过的页面时使用
|
|
162
|
+
let newTag = tag;
|
|
163
|
+
newTag.params = params || newTag.params;
|
|
164
|
+
newTag.query = query || newTag.query;
|
|
165
|
+
newTag.fullPath = fullPath || newTag.fullPath;
|
|
166
|
+
// 添加进当前显示的页面数组
|
|
167
|
+
state.opened.push(newTag);
|
|
168
|
+
// 如果这个页面需要缓存 将其添加到缓存设置
|
|
169
|
+
if (isKeepAlive(newTag)) {
|
|
170
|
+
commit('keepAlivePush', tag.name);
|
|
171
|
+
}
|
|
172
|
+
// 持久化
|
|
173
|
+
await dispatch('opened2db');
|
|
174
|
+
// end
|
|
175
|
+
resolve();
|
|
176
|
+
});
|
|
177
|
+
},
|
|
178
|
+
/**
|
|
179
|
+
* @description 打开一个新的页面
|
|
180
|
+
* @param {Object} param 从路由钩子的 to 对象上获取 { name, params, query, fullPath } 路由信息
|
|
181
|
+
*/
|
|
182
|
+
open({ state, commit, dispatch }, { name, params, query, fullPath }) {
|
|
183
|
+
return new Promise(async resolve => {
|
|
184
|
+
// 已经打开的页面
|
|
185
|
+
let opened = state.opened;
|
|
186
|
+
// 判断此页面是否已经打开 并且记录位置
|
|
187
|
+
let pageOpenedIndex = 0;
|
|
188
|
+
const pageOpened = opened.find((page, index) => {
|
|
189
|
+
const same = page.fullPath === fullPath;
|
|
190
|
+
pageOpenedIndex = same ? index : pageOpenedIndex;
|
|
191
|
+
return same;
|
|
192
|
+
});
|
|
193
|
+
if (pageOpened) {
|
|
194
|
+
// 页面以前打开过
|
|
195
|
+
await dispatch('openedUpdate', {
|
|
196
|
+
index: pageOpenedIndex,
|
|
197
|
+
params,
|
|
198
|
+
query,
|
|
199
|
+
fullPath
|
|
200
|
+
});
|
|
201
|
+
} else {
|
|
202
|
+
// 页面以前没有打开过
|
|
203
|
+
let page = state.pool.find(t => t.name === name);
|
|
204
|
+
// 如果这里没有找到 page 代表这个路由虽然在框架内 但是不参与标签页显示
|
|
205
|
+
if (page) {
|
|
206
|
+
await dispatch('add', {
|
|
207
|
+
tag: Object.assign({}, page),
|
|
208
|
+
params,
|
|
209
|
+
query,
|
|
210
|
+
fullPath
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
commit('currentSet', fullPath);
|
|
215
|
+
// end
|
|
216
|
+
resolve();
|
|
217
|
+
});
|
|
218
|
+
},
|
|
219
|
+
/**
|
|
220
|
+
* @description 关闭一个 tag (关闭一个页面)
|
|
221
|
+
* @param {Object} param { tagName: 要关闭的标签名字 }
|
|
222
|
+
*/
|
|
223
|
+
close({ state, commit, dispatch }, { tagName }) {
|
|
224
|
+
return new Promise(async resolve => {
|
|
225
|
+
// 下个新的页面
|
|
226
|
+
let newPage = state.opened[0];
|
|
227
|
+
const isCurrent = state.current === tagName;
|
|
228
|
+
// 如果关闭的页面就是当前显示的页面
|
|
229
|
+
if (isCurrent) {
|
|
230
|
+
// 去找一个新的页面
|
|
231
|
+
let len = state.opened.length;
|
|
232
|
+
for (let i = 0; i < len; i++) {
|
|
233
|
+
if (state.opened[i].fullPath === tagName) {
|
|
234
|
+
// 是否只剩最后一个,是则跳首页
|
|
235
|
+
if (len > 1) {
|
|
236
|
+
// 如果是最后一个,则向前一个跳,否则向下一个跳
|
|
237
|
+
if (i === len - 1) {
|
|
238
|
+
newPage = state.opened[i - 1];
|
|
239
|
+
} else {
|
|
240
|
+
newPage = state.opened[i + 1];
|
|
241
|
+
}
|
|
242
|
+
} else {
|
|
243
|
+
newPage = {};
|
|
244
|
+
}
|
|
245
|
+
break;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
// 找到这个页面在已经打开的数据里是第几个
|
|
250
|
+
const index = state.opened.findIndex(page => page.fullPath === tagName);
|
|
251
|
+
if (index >= 0) {
|
|
252
|
+
// 如果这个页面是缓存的页面 将其在缓存设置中删除
|
|
253
|
+
commit('keepAliveRemove', state.opened[index].name);
|
|
254
|
+
// 更新数据 删除关闭的页面
|
|
255
|
+
state.opened.splice(index, 1);
|
|
256
|
+
}
|
|
257
|
+
// 持久化
|
|
258
|
+
await dispatch('opened2db');
|
|
259
|
+
// 最后需要判断是否需要跳到首页
|
|
260
|
+
if (isCurrent) {
|
|
261
|
+
const { name = 'index', params = {}, query = {} } = newPage;
|
|
262
|
+
let routerObj = {
|
|
263
|
+
name,
|
|
264
|
+
params,
|
|
265
|
+
query
|
|
266
|
+
};
|
|
267
|
+
router.push(routerObj, () => {});
|
|
268
|
+
}
|
|
269
|
+
// end
|
|
270
|
+
resolve();
|
|
271
|
+
});
|
|
272
|
+
},
|
|
273
|
+
/**
|
|
274
|
+
* @description 关闭当前标签左边的标签
|
|
275
|
+
* @param {Object} param { pageSelect: 当前选中的tagName }
|
|
276
|
+
*/
|
|
277
|
+
closeLeft({ state, commit, dispatch }, { pageSelect } = {}) {
|
|
278
|
+
return new Promise(async resolve => {
|
|
279
|
+
const pageAim = pageSelect || state.current;
|
|
280
|
+
let currentIndex = 0;
|
|
281
|
+
state.opened.forEach((page, index) => {
|
|
282
|
+
if (page.fullPath === pageAim) {
|
|
283
|
+
currentIndex = index;
|
|
284
|
+
}
|
|
285
|
+
});
|
|
286
|
+
if (currentIndex > 0) {
|
|
287
|
+
// 删除打开的页面 并在缓存设置中删除
|
|
288
|
+
state.opened.splice(1, currentIndex - 1).forEach(({ name }) => commit('keepAliveRemove', name));
|
|
289
|
+
}
|
|
290
|
+
state.current = pageAim;
|
|
291
|
+
if (router.currentRoute.value.fullPath !== pageAim) {
|
|
292
|
+
router.push(pageAim);
|
|
293
|
+
}
|
|
294
|
+
// 持久化
|
|
295
|
+
await dispatch('opened2db');
|
|
296
|
+
// end
|
|
297
|
+
resolve();
|
|
298
|
+
});
|
|
299
|
+
},
|
|
300
|
+
/**
|
|
301
|
+
* @description 关闭当前标签右边的标签
|
|
302
|
+
* @param {Object} param { pageSelect: 当前选中的tagName }
|
|
303
|
+
*/
|
|
304
|
+
closeRight({ state, commit, dispatch }, { pageSelect } = {}) {
|
|
305
|
+
return new Promise(async resolve => {
|
|
306
|
+
const pageAim = pageSelect || state.current;
|
|
307
|
+
let currentIndex = 0;
|
|
308
|
+
state.opened.forEach((page, index) => {
|
|
309
|
+
if (page.fullPath === pageAim) {
|
|
310
|
+
currentIndex = index;
|
|
311
|
+
}
|
|
312
|
+
});
|
|
313
|
+
// 删除打开的页面 并在缓存设置中删除
|
|
314
|
+
state.opened.splice(currentIndex + 1).forEach(({ name }) => commit('keepAliveRemove', name));
|
|
315
|
+
// 设置当前的页面
|
|
316
|
+
state.current = pageAim;
|
|
317
|
+
if (router.currentRoute.value.fullPath !== pageAim) {
|
|
318
|
+
router.push(pageAim);
|
|
319
|
+
}
|
|
320
|
+
// 持久化
|
|
321
|
+
await dispatch('opened2db');
|
|
322
|
+
// end
|
|
323
|
+
resolve();
|
|
324
|
+
});
|
|
325
|
+
},
|
|
326
|
+
/**
|
|
327
|
+
* @description 关闭当前激活之外的 tag
|
|
328
|
+
* @param {Object} param { pageSelect: 当前选中的tagName }
|
|
329
|
+
*/
|
|
330
|
+
closeOther({ state, commit, dispatch }, { pageSelect } = {}) {
|
|
331
|
+
return new Promise(async resolve => {
|
|
332
|
+
const pageAim = pageSelect || state.current;
|
|
333
|
+
let currentIndex = 0;
|
|
334
|
+
state.opened.forEach((page, index) => {
|
|
335
|
+
if (page.fullPath === pageAim) {
|
|
336
|
+
currentIndex = index;
|
|
337
|
+
}
|
|
338
|
+
});
|
|
339
|
+
// 删除打开的页面数据 并更新缓存设置
|
|
340
|
+
if (currentIndex === 0) {
|
|
341
|
+
state.opened.splice(1).forEach(({ name }) => commit('keepAliveRemove', name));
|
|
342
|
+
} else {
|
|
343
|
+
state.opened.splice(currentIndex + 1).forEach(({ name }) => commit('keepAliveRemove', name));
|
|
344
|
+
state.opened.splice(1, currentIndex - 1).forEach(({ name }) => commit('keepAliveRemove', name));
|
|
345
|
+
}
|
|
346
|
+
// 设置新的页面
|
|
347
|
+
state.current = pageAim;
|
|
348
|
+
if (router.currentRoute.value.fullPath !== pageAim) {
|
|
349
|
+
router.push(pageAim);
|
|
350
|
+
}
|
|
351
|
+
// 持久化
|
|
352
|
+
await dispatch('opened2db');
|
|
353
|
+
// end
|
|
354
|
+
resolve();
|
|
355
|
+
});
|
|
356
|
+
},
|
|
357
|
+
/**
|
|
358
|
+
* @description 关闭所有 tag
|
|
359
|
+
* @param {Object} state vuex state
|
|
360
|
+
*/
|
|
361
|
+
closeAll({ state, commit, dispatch }) {
|
|
362
|
+
return new Promise(async resolve => {
|
|
363
|
+
// 删除打开的页面 并在缓存设置中删除
|
|
364
|
+
state.opened.splice(1).forEach(({ name }) => commit('keepAliveRemove', name));
|
|
365
|
+
// 持久化
|
|
366
|
+
await dispatch('opened2db');
|
|
367
|
+
// 关闭所有的标签页后需要判断一次现在是不是在首页
|
|
368
|
+
if (router.currentRoute.value.name !== 'index') {
|
|
369
|
+
router.push(
|
|
370
|
+
{
|
|
371
|
+
name: 'index'
|
|
372
|
+
},
|
|
373
|
+
() => {}
|
|
374
|
+
);
|
|
375
|
+
}
|
|
376
|
+
// end
|
|
377
|
+
resolve();
|
|
378
|
+
});
|
|
379
|
+
},
|
|
380
|
+
/**
|
|
381
|
+
* @description 直接更新 opened,用于拖拽调整页签顺序
|
|
382
|
+
* */
|
|
383
|
+
updateOpened({ state, dispatch }, { opened }) {
|
|
384
|
+
return new Promise(async resolve => {
|
|
385
|
+
state.opened = opened;
|
|
386
|
+
// 持久化
|
|
387
|
+
await dispatch('opened2db');
|
|
388
|
+
// end
|
|
389
|
+
resolve();
|
|
390
|
+
});
|
|
391
|
+
}
|
|
392
|
+
},
|
|
393
|
+
mutations: {
|
|
394
|
+
/**
|
|
395
|
+
* @class keepAlive
|
|
396
|
+
* @description 从已经打开的页面记录中更新需要缓存的页面记录
|
|
397
|
+
* @param {Object} state vuex state
|
|
398
|
+
*/
|
|
399
|
+
keepAliveRefresh(state) {
|
|
400
|
+
state.keepAlive = state.opened.filter(item => isKeepAlive(item)).map(e => e.name);
|
|
401
|
+
},
|
|
402
|
+
/**
|
|
403
|
+
* @description 删除一个页面的缓存设置
|
|
404
|
+
* @param {Object} state vuex state
|
|
405
|
+
* @param {String} name name
|
|
406
|
+
*/
|
|
407
|
+
keepAliveRemove(state, name) {
|
|
408
|
+
const list = [...state.keepAlive];
|
|
409
|
+
const index = list.findIndex(item => item === name);
|
|
410
|
+
|
|
411
|
+
if (index !== -1) {
|
|
412
|
+
list.splice(index, 1);
|
|
413
|
+
state.keepAlive = list;
|
|
414
|
+
}
|
|
415
|
+
},
|
|
416
|
+
/**
|
|
417
|
+
* @description 增加一个页面的缓存设置
|
|
418
|
+
* @param {Object} state vuex state
|
|
419
|
+
* @param {String} name name
|
|
420
|
+
*/
|
|
421
|
+
keepAlivePush(state, name) {
|
|
422
|
+
const keep = [...state.keepAlive];
|
|
423
|
+
keep.push(name);
|
|
424
|
+
state.keepAlive = keep;
|
|
425
|
+
},
|
|
426
|
+
/**
|
|
427
|
+
* @description 清空页面缓存设置
|
|
428
|
+
* @param {Object} state vuex state
|
|
429
|
+
*/
|
|
430
|
+
keepAliveClean(state) {
|
|
431
|
+
state.keepAlive = [];
|
|
432
|
+
},
|
|
433
|
+
/**
|
|
434
|
+
* @class current
|
|
435
|
+
* @description 设置当前激活的页面 fullPath
|
|
436
|
+
* @param {Object} state vuex state
|
|
437
|
+
* @param {String} fullPath new fullPath
|
|
438
|
+
*/
|
|
439
|
+
currentSet(state, fullPath) {
|
|
440
|
+
state.current = fullPath;
|
|
441
|
+
},
|
|
442
|
+
/**
|
|
443
|
+
* @class pool
|
|
444
|
+
* @description 保存 pool (候选池)
|
|
445
|
+
* @param {Object} state vuex state
|
|
446
|
+
* @param {Array} routes routes
|
|
447
|
+
*/
|
|
448
|
+
init(state, routes) {
|
|
449
|
+
const pool = [];
|
|
450
|
+
const push = function (routes) {
|
|
451
|
+
routes.forEach(route => {
|
|
452
|
+
if (route.children) {
|
|
453
|
+
push(route.children);
|
|
454
|
+
} else {
|
|
455
|
+
if (!route.hidden) {
|
|
456
|
+
const { meta, name, path } = route;
|
|
457
|
+
pool.push({ meta, name, path });
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
});
|
|
461
|
+
};
|
|
462
|
+
push(routes);
|
|
463
|
+
state.pool = pool;
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
};
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 用户信息
|
|
3
|
+
* */
|
|
4
|
+
export default {
|
|
5
|
+
namespaced: true,
|
|
6
|
+
state: {
|
|
7
|
+
// 用户信息
|
|
8
|
+
info: {},
|
|
9
|
+
// 附加数据
|
|
10
|
+
data: {}
|
|
11
|
+
},
|
|
12
|
+
actions: {
|
|
13
|
+
/**
|
|
14
|
+
* @description 设置用户数据
|
|
15
|
+
* @param {Object} state vuex state
|
|
16
|
+
* @param {Object} dispatch vuex dispatch
|
|
17
|
+
* @param {*} info info
|
|
18
|
+
*/
|
|
19
|
+
set({ state, dispatch }, info) {
|
|
20
|
+
return new Promise(async resolve => {
|
|
21
|
+
// store 赋值
|
|
22
|
+
state.info = info;
|
|
23
|
+
// 持久化
|
|
24
|
+
await dispatch(
|
|
25
|
+
'admin/db/set',
|
|
26
|
+
{
|
|
27
|
+
dbName: 'sys',
|
|
28
|
+
path: 'user.info',
|
|
29
|
+
value: info,
|
|
30
|
+
user: true
|
|
31
|
+
},
|
|
32
|
+
{ root: true }
|
|
33
|
+
);
|
|
34
|
+
// end
|
|
35
|
+
resolve();
|
|
36
|
+
});
|
|
37
|
+
},
|
|
38
|
+
/**
|
|
39
|
+
* @description 设置用户附加数据
|
|
40
|
+
* @param {Object} state vuex state
|
|
41
|
+
* @param {Object} dispatch vuex dispatch
|
|
42
|
+
* @param {*} data data
|
|
43
|
+
*/
|
|
44
|
+
setData({ state, dispatch }, data) {
|
|
45
|
+
return new Promise(async resolve => {
|
|
46
|
+
// store 赋值
|
|
47
|
+
state.data = data;
|
|
48
|
+
// 持久化
|
|
49
|
+
await dispatch(
|
|
50
|
+
'admin/db/set',
|
|
51
|
+
{
|
|
52
|
+
dbName: 'sys',
|
|
53
|
+
path: 'user.data',
|
|
54
|
+
value: data,
|
|
55
|
+
user: true
|
|
56
|
+
},
|
|
57
|
+
{ root: true }
|
|
58
|
+
);
|
|
59
|
+
// end
|
|
60
|
+
resolve();
|
|
61
|
+
});
|
|
62
|
+
},
|
|
63
|
+
/**
|
|
64
|
+
* @description 从数据库取用户数据
|
|
65
|
+
* @param {Object} state vuex state
|
|
66
|
+
* @param {Object} dispatch vuex dispatch
|
|
67
|
+
*/
|
|
68
|
+
load({ state, dispatch }) {
|
|
69
|
+
return new Promise(async resolve => {
|
|
70
|
+
// store 赋值
|
|
71
|
+
state.info = await dispatch(
|
|
72
|
+
'admin/db/get',
|
|
73
|
+
{
|
|
74
|
+
dbName: 'sys',
|
|
75
|
+
path: 'user.info',
|
|
76
|
+
defaultValue: {},
|
|
77
|
+
user: true
|
|
78
|
+
},
|
|
79
|
+
{ root: true }
|
|
80
|
+
);
|
|
81
|
+
state.data = await dispatch(
|
|
82
|
+
'admin/db/get',
|
|
83
|
+
{
|
|
84
|
+
dbName: 'sys',
|
|
85
|
+
path: 'user.data',
|
|
86
|
+
defaultValue: {},
|
|
87
|
+
user: true
|
|
88
|
+
},
|
|
89
|
+
{ root: true }
|
|
90
|
+
);
|
|
91
|
+
// end
|
|
92
|
+
resolve();
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import customPageApi from '../../../../api/customPage';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* 缓存信息
|
|
5
|
+
* */
|
|
6
|
+
export default {
|
|
7
|
+
namespaced: true,
|
|
8
|
+
state: {
|
|
9
|
+
// 自定义页面
|
|
10
|
+
pages: {}
|
|
11
|
+
},
|
|
12
|
+
getters: {
|
|
13
|
+
get: state => id => {
|
|
14
|
+
return state.pages[id];
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
actions: {
|
|
18
|
+
/**
|
|
19
|
+
* @description 加载数据视图
|
|
20
|
+
* @param {Object} state vuex state
|
|
21
|
+
* @param {*} id 代码
|
|
22
|
+
*/
|
|
23
|
+
async load({ state }, id) {
|
|
24
|
+
if (!(id in state.pages)) {
|
|
25
|
+
let res = await customPageApi.get(id);
|
|
26
|
+
state.pages[id] = res;
|
|
27
|
+
|
|
28
|
+
return res;
|
|
29
|
+
} else {
|
|
30
|
+
return state.pages[id];
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
};
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
#app, body, html{
|
|
2
|
+
height: 100%;
|
|
3
|
+
}
|
|
4
|
+
body{
|
|
5
|
+
background-color: @background-color-base;
|
|
6
|
+
font-size: 14px;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
// 隐藏滚动条样式
|
|
10
|
+
.i-scrollbar-hide{
|
|
11
|
+
&::-webkit-scrollbar{
|
|
12
|
+
width: 0;
|
|
13
|
+
}
|
|
14
|
+
&::-webkit-scrollbar-track{
|
|
15
|
+
background-color: transparent;
|
|
16
|
+
}
|
|
17
|
+
&::-webkit-scrollbar-thumb{
|
|
18
|
+
background: #e8eaec;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// 极简滚动条样式
|
|
23
|
+
.i-scrollbar{
|
|
24
|
+
&::-webkit-scrollbar{
|
|
25
|
+
width: 6px;
|
|
26
|
+
}
|
|
27
|
+
&::-webkit-scrollbar-track{
|
|
28
|
+
background-color: transparent;
|
|
29
|
+
}
|
|
30
|
+
&::-webkit-scrollbar-thumb{
|
|
31
|
+
background: #808695;
|
|
32
|
+
border-radius: 4px;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// 去除 Table 的左右边框,更精简
|
|
37
|
+
.i-table-no-border{
|
|
38
|
+
.ivu-table th{
|
|
39
|
+
background-color: #fff;
|
|
40
|
+
}
|
|
41
|
+
.ivu-table-wrapper, .ivu-table tr:last-child td{
|
|
42
|
+
border: none;
|
|
43
|
+
}
|
|
44
|
+
.ivu-table:before, .ivu-table:after{
|
|
45
|
+
display: none;
|
|
46
|
+
}
|
|
47
|
+
}
|