yh-pub 1.0.0 → 1.0.2

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.
Files changed (55) hide show
  1. package/README.MD +19 -19
  2. package/layout/admin/adminIndex.vue +104 -104
  3. package/layout/admin/api/loginApi.js +24 -24
  4. package/layout/admin/api/routers.js +93 -93
  5. package/layout/admin/api/tenantApi.js +123 -123
  6. package/layout/admin/home/homeIndex.vue +25 -25
  7. package/layout/admin/login/login.vue +161 -161
  8. package/layout/admin/menu/MenuIndex.vue +648 -648
  9. package/layout/admin/menu/icon.vue +108 -108
  10. package/layout/admin/menu/iconList.js +934 -934
  11. package/layout/admin/saTenant/saTenant.vue +173 -173
  12. package/layout/admin/saTenant/saTenantForm.js +80 -80
  13. package/layout/admin/saTenant/saTenantForm.vue +61 -61
  14. package/layout/admin/saTenant/saTenantRoleManage.js +417 -417
  15. package/layout/admin/saTenant/saTenantRoleManage.vue +99 -99
  16. package/layout/admin/user/saUser.less +6 -6
  17. package/layout/admin/user/saUser.vue +72 -72
  18. package/layout/main/components/console/console.vue +205 -205
  19. package/layout/main/components/error-store/error-store.vue +72 -72
  20. package/layout/main/components/error-store/index.js +2 -2
  21. package/layout/main/components/fullscreen/fullscreen.vue +57 -57
  22. package/layout/main/components/fullscreen/index.js +2 -2
  23. package/layout/main/components/language/language.vue +71 -71
  24. package/layout/main/components/side-menu/side-menu.less +73 -73
  25. package/layout/main/components/side-menu/side-menu.vue +75 -75
  26. package/layout/main/components/tags-nav/tags-nav.less +44 -44
  27. package/layout/main/components/tags-nav/tags-nav.vue +144 -144
  28. package/layout/main/components/user/user.less +12 -12
  29. package/layout/main/components/user/user.vue +185 -185
  30. package/layout/main/home/home.vue +480 -480
  31. package/layout/main/home/index.js +2 -2
  32. package/layout/main/home/toDoList.vue +32 -32
  33. package/layout/main/login/login.less +93 -93
  34. package/layout/main/login/login.vue +151 -151
  35. package/layout/main/main.less +81 -81
  36. package/layout/main/main.vue +254 -202
  37. package/layout/main/system/dict.vue +64 -64
  38. package/layout/main/system/orgManage.vue +473 -473
  39. package/layout/main/system/roleManage.js +807 -755
  40. package/layout/main/system/roleManage.vue +424 -399
  41. package/package.json +11 -11
  42. package/view/basic/error-logger.vue +74 -74
  43. package/view/basic/error-page/401.vue +22 -22
  44. package/view/basic/error-page/404.vue +22 -22
  45. package/view/basic/error-page/500.vue +22 -22
  46. package/view/basic/error-page/back-btn-group.vue +48 -48
  47. package/view/basic/error-page/error-content.vue +28 -28
  48. package/view/basic/error-page/error.less +46 -46
  49. package/view/config/component/confFormItem.vue +49 -49
  50. package/view/config/config.scss +45 -45
  51. package/view/config/configIndex.vue +150 -150
  52. package/view/config/subPage/router-config.vue +4 -4
  53. package/view/config/subPage/sys-config.vue +249 -249
  54. package/view/window/IframeFReportView.vue +27 -27
  55. package/view/window/windowIndex.vue +22 -22
@@ -1,81 +1,81 @@
1
- .main{
2
- height: 100%;
3
- display: flex;
4
- .logo-con{
5
- display: flex;
6
- justify-content: center;
7
- align-items: center;
8
- height: 50px;
9
- box-sizing: border-box;
10
- background-color: #0051C1;
11
- .max-logo{
12
- height: 44px;
13
- width: auto;
14
- display: block;
15
- margin: 0 auto;
16
- }
17
- .mini-logo{
18
- width: 44px;
19
- height: auto;
20
- display: block;
21
- margin: 0 auto;
22
- }
23
- }
24
- .header-con{
25
- --header-size: 50px;
26
- background: linear-gradient(90deg, #0051C1 0%, #3E93FE 100%);
27
- width: 100%;
28
- height: var(--header-size);
29
- line-height: var(--header-size);
30
- padding: 0 12px;
31
- box-sizing: border-box;
32
- display: flex;
33
- justify-content: flex-end;
34
- align-items: center;
35
- position: relative;
36
- .class-collapsed{
37
- position: absolute;
38
- left: 0;
39
- top: 9px;
40
- width: 32px;
41
- height: 32px;
42
- line-height: 32px;
43
- text-align: center;
44
- margin-right: 12px;
45
- color: var(--el-color-white);
46
- font-size: 26px;
47
- cursor: pointer;
48
- }
49
- }
50
- .main-layout-con{
51
- flex: 1;
52
- overflow: hidden;
53
- background-color:#F3F5FA;
54
- display: flex;
55
- flex-direction: column;
56
- }
57
- .main-container{
58
- flex: 1;
59
- overflow: auto;
60
- background-color: #fff;
61
- padding: 0 10px 10px 10px;
62
- box-sizing: border-box;
63
- }
64
- .left-sider{
65
- width: 220px;
66
- background-color: #21304C;
67
- --el-menu-bg-color: #21304C;
68
- --el-menu-text-color: var(--el-color-white);
69
- --el-menu-active-color: var(--el-color-white);
70
- --el-menu-hover-bg-color: transparent;
71
- &.is-collapse {
72
- width: 64px;
73
- }
74
- }
75
- .right-container {
76
- overflow: hidden;
77
- flex: 1;
78
- display: flex;
79
- flex-direction: column;
80
- }
81
- }
1
+ .main{
2
+ height: 100%;
3
+ display: flex;
4
+ .logo-con{
5
+ display: flex;
6
+ justify-content: center;
7
+ align-items: center;
8
+ height: 50px;
9
+ box-sizing: border-box;
10
+ background-color: #0051C1;
11
+ .max-logo{
12
+ height: 44px;
13
+ width: auto;
14
+ display: block;
15
+ margin: 0 auto;
16
+ }
17
+ .mini-logo{
18
+ width: 44px;
19
+ height: auto;
20
+ display: block;
21
+ margin: 0 auto;
22
+ }
23
+ }
24
+ .header-con{
25
+ --header-size: 50px;
26
+ background: linear-gradient(90deg, #0051C1 0%, #3E93FE 100%);
27
+ width: 100%;
28
+ height: var(--header-size);
29
+ line-height: var(--header-size);
30
+ padding: 0 12px;
31
+ box-sizing: border-box;
32
+ display: flex;
33
+ justify-content: flex-end;
34
+ align-items: center;
35
+ position: relative;
36
+ .class-collapsed{
37
+ position: absolute;
38
+ left: 0;
39
+ top: 9px;
40
+ width: 32px;
41
+ height: 32px;
42
+ line-height: 32px;
43
+ text-align: center;
44
+ margin-right: 12px;
45
+ color: var(--el-color-white);
46
+ font-size: 26px;
47
+ cursor: pointer;
48
+ }
49
+ }
50
+ .main-layout-con{
51
+ flex: 1;
52
+ overflow: hidden;
53
+ background-color:#F3F5FA;
54
+ display: flex;
55
+ flex-direction: column;
56
+ }
57
+ .main-container{
58
+ flex: 1;
59
+ overflow: auto;
60
+ background-color: #fff;
61
+ padding: 0 10px 10px 10px;
62
+ box-sizing: border-box;
63
+ }
64
+ .left-sider{
65
+ width: 220px;
66
+ background-color: #21304C;
67
+ --el-menu-bg-color: #21304C;
68
+ --el-menu-text-color: var(--el-color-white);
69
+ --el-menu-active-color: var(--el-color-white);
70
+ --el-menu-hover-bg-color: transparent;
71
+ &.is-collapse {
72
+ width: 64px;
73
+ }
74
+ }
75
+ .right-container {
76
+ overflow: hidden;
77
+ flex: 1;
78
+ display: flex;
79
+ flex-direction: column;
80
+ }
81
+ }
@@ -1,202 +1,254 @@
1
- <template>
2
- <section class="main">
3
- <aside
4
- class="left-sider"
5
- :class="{ 'is-collapse': collapse }">
6
- <!-- 需要放在菜单上面的内容,如Logo,写在side-menu标签内部,如下 -->
7
- <div class="logo-con">
8
- <template v-if="hasCustomLogo">
9
- <img
10
- v-show="!collapse"
11
- class="max-logo"
12
- :src="logo"
13
- key="max-logo" />
14
- <img
15
- v-show="collapse"
16
- class="mini-logo"
17
- :src="minLogo"
18
- key="min-logo" />
19
- </template>
20
- <template v-else>
21
- <img
22
- v-show="!collapse"
23
- class="max-logo"
24
- src="@/assets/images/logo.png"
25
- key="max-logo" />
26
- <img
27
- v-show="collapse"
28
- class="mini-logo"
29
- src="@/assets/images/logo-min.png"
30
- key="min-logo" />
31
- </template>
32
- </div>
33
- <side-menu
34
- :active-name="route?.name"
35
- :collapse="collapse"
36
- :menu-list="menuList"></side-menu>
37
- </aside>
38
- <section
39
- class="right-container"
40
- :class="{ 'is-collapse': collapse }">
41
- <header class="header-con">
42
- <i
43
- :class="`iconfont class-collapsed ${collapse ? 'icon-indent' : 'icon-outdent'}`"
44
- @click="handleCollapsedChange"></i>
45
- <user
46
- :message-unread-count="unreadCount"
47
- :user-name="userName" />
48
- <language v-if="config.useI18n" />
49
- <!-- <error-store
50
- v-if="config.plugin?.errorStore?.showInHeader"
51
- :count="errorCount"></error-store>
52
- <LogConsole></LogConsole> -->
53
- <fullscreen v-model="isFullScreen" />
54
- </header>
55
- <main class="main-layout-con">
56
- <tags-nav />
57
- <section class="main-container">
58
- <router-view v-slot="{ Component }">
59
- <KeepAlive
60
- :max="10"
61
- ref="kpAliveRef">
62
- <component
63
- :is="Component"
64
- :key="route.path" />
65
- </KeepAlive>
66
- </router-view>
67
- </section>
68
- </main>
69
- </section>
70
- </section>
71
- </template>
72
-
73
- <script setup>
74
- import "./main.less";
75
- import { ref, onMounted, onUnmounted, computed } from "vue";
76
- import { storeToRefs } from "pinia";
77
- import { ElNotification } from "element-plus";
78
- import { getToken, getStorage } from "@/libs/util";
79
- import { markRead } from "@/api/user";
80
- import { useRouter, useRoute } from "vue-router";
81
-
82
- import config from "@/config";
83
- import { useAppStore } from "@/store/app.js";
84
- import { useUserStore } from "@/store/user.js";
85
- import SideMenu from "./components/side-menu/side-menu.vue";
86
- import TagsNav from "./components/tags-nav/tags-nav.vue";
87
- import User from "./components/user/user.vue";
88
- import Fullscreen from "./components/fullscreen/fullscreen.vue";
89
- import { Language } from "yh-i18n";
90
-
91
- const baseUrl = process.env.NODE_ENV === "development" ? config.baseUrl.dev : config.baseUrl.pro;
92
-
93
- const userStore = useUserStore();
94
- const appStore = useAppStore();
95
- const router = useRouter();
96
- const route = useRoute();
97
- const kpAliveRef = ref();
98
-
99
- const { menuList, errorCount, tagNavList } = storeToRefs(appStore);
100
- const { unreadCount } = storeToRefs(userStore);
101
-
102
- const hasCustomLogo = computed(() => {
103
- return !!config.logo;
104
- });
105
-
106
- const logo = computed(() => {
107
- return config.logo;
108
- });
109
-
110
- const minLogo = computed(() => {
111
- return config.minLogo;
112
- });
113
-
114
- const userName = ref("");
115
- const collapse = ref(false);
116
- const unReadMessageMap = ref({});
117
- const websocketPath = baseUrl.replace("http", "ws") + "/webSocket";
118
- const isFullScreen = ref(false);
119
- let websocket = null;
120
-
121
- function handleCollapsedChange() {
122
- collapse.value = !collapse.value;
123
- }
124
-
125
- function initWebsocket() {
126
- let token = getToken();
127
- if (typeof WebSocket === "undefined") {
128
- ElMessage.info("您的浏览器不支持WebSocket");
129
- } else if (token) {
130
- try {
131
- // 实例化websocket
132
- websocket = new WebSocket(websocketPath + "?$_TOKEN=" + token);
133
- // 监听websocket的连接
134
- websocket.onopen = () => {
135
- console.log("(" + websocketPath + ") websocket连接成功");
136
- };
137
- // 监听websocket的错误信息
138
- websocket.onerror = () => {
139
- console.log("(" + websocketPath + ") websocket连接错误");
140
- };
141
- // 监听websocket的消息
142
- websocket.onmessage = (msg) => {
143
- websocketGetMessage(msg);
144
- };
145
- // 监听websocket关闭
146
- websocket.onclose = () => {
147
- websocketClose();
148
- };
149
- } catch (e) {}
150
- }
151
- }
152
-
153
- function websocketGetMessage(msg) {
154
- let msgData = eval(msg.data);
155
- if (msgData && msgData.length > 0) {
156
- msgData.forEach((msg) => {
157
- if (!unReadMessageMap.value[msg.ID]) {
158
- unReadMessageMap.value[msg.ID] = msg;
159
- }
160
- });
161
- Object.keys(unReadMessageMap.value).forEach((key) => {
162
- let msg = unReadMessageMap.value[key];
163
- if (!msg.hasOwnProperty("show")) {
164
- ElNotification.open({
165
- title: msg.TITLE,
166
- desc: msg.TEXT,
167
- duration: 0,
168
- name: msg.ID,
169
- onClose: () => {
170
- delete unReadMessageMap.value[msg.ID];
171
- markRead(msg.ID);
172
- },
173
- });
174
- msg["show"] = true;
175
- }
176
- });
177
- }
178
- }
179
-
180
- function websocketSendMessage(msg) {
181
- websocket.send(msg);
182
- }
183
-
184
- function websocketClose() {
185
- let that = this;
186
- console.log("websocket关闭,尝试重新连接websocket");
187
- window.setTimeout(() => {
188
- that.initWebsocket();
189
- }, 1000);
190
- }
191
-
192
- onMounted(async () => {
193
- try {
194
- userName.value = getStorage("userName");
195
- } catch (error) {
196
- console.error("菜单加载异常:", error);
197
- }
198
- });
199
- onUnmounted(() => {
200
- ElNotification.closeAll();
201
- });
202
- </script>
1
+ <template>
2
+ <section class="main">
3
+ <aside
4
+ class="left-sider"
5
+ :class="{'is-collapse': collapse}">
6
+ <!-- 需要放在菜单上面的内容,如Logo,写在side-menu标签内部,如下 -->
7
+ <div class="logo-con">
8
+ <template v-if="hasCustomLogo">
9
+ <img
10
+ v-show="!collapse"
11
+ class="max-logo"
12
+ :src="logo"
13
+ key="max-logo" />
14
+ <img
15
+ v-show="collapse"
16
+ class="mini-logo"
17
+ :src="minLogo"
18
+ key="min-logo" />
19
+ </template>
20
+ <template v-else>
21
+ <img
22
+ v-show="!collapse"
23
+ class="max-logo"
24
+ src="@/assets/images/logo.png"
25
+ key="max-logo" />
26
+ <img
27
+ v-show="collapse"
28
+ class="mini-logo"
29
+ src="@/assets/images/logo-min.png"
30
+ key="min-logo" />
31
+ </template>
32
+ </div>
33
+ <side-menu
34
+ :active-name="route?.name"
35
+ :collapse="collapse"
36
+ :menu-list="menuList"></side-menu>
37
+ </aside>
38
+ <section
39
+ class="right-container"
40
+ :class="{'is-collapse': collapse}">
41
+ <header class="header-con">
42
+ <i
43
+ :class="`iconfont class-collapsed ${collapse ? 'icon-indent' : 'icon-outdent'}`"
44
+ @click="handleCollapsedChange"></i>
45
+ <user
46
+ :message-unread-count="unreadCount"
47
+ :user-name="userName" />
48
+ <language v-if="config.useI18n" />
49
+ <!-- <error-store
50
+ v-if="config.plugin?.errorStore?.showInHeader"
51
+ :count="errorCount"></error-store>
52
+ <LogConsole></LogConsole> -->
53
+ <fullscreen v-model="isFullScreen" />
54
+ </header>
55
+ <main class="main-layout-con">
56
+ <tags-nav />
57
+ <section
58
+ class="main-container"
59
+ :class="{'is-iframe': isIframe}">
60
+ <router-view v-slot="{Component}">
61
+ <KeepAlive
62
+ :max="10"
63
+ ref="kpAliveRef">
64
+ <component
65
+ v-show="!isIframe"
66
+ :is="Component"
67
+ :key="route.path" />
68
+ </KeepAlive>
69
+ <iframe
70
+ v-show="item === route.params.url"
71
+ v-for="item in iframeList"
72
+ :src="item"
73
+ :key="item"
74
+ frameborder="0"
75
+ scrolling="auto"
76
+ style="background-color: #fff"></iframe>
77
+ </router-view>
78
+ </section>
79
+ </main>
80
+ </section>
81
+ </section>
82
+ </template>
83
+
84
+ <script setup>
85
+ import './main.less';
86
+ import {ref, onMounted, onUnmounted, computed, watch} from 'vue';
87
+ import {storeToRefs} from 'pinia';
88
+ import {ElNotification} from 'element-plus';
89
+ import {getToken, getStorage} from '@/libs/util';
90
+ import {markRead} from '@/api/user';
91
+ import {useRouter, useRoute, onBeforeRouteUpdate} from 'vue-router';
92
+
93
+ import config from '@/config';
94
+ import {useAppStore} from '@/store/app.js';
95
+ import {useUserStore} from '@/store/user.js';
96
+ import SideMenu from './components/side-menu/side-menu.vue';
97
+ import TagsNav from './components/tags-nav/tags-nav.vue';
98
+ import User from './components/user/user.vue';
99
+ import Fullscreen from './components/fullscreen/fullscreen.vue';
100
+ import {Language} from 'yh-i18n';
101
+
102
+ const baseUrl = process.env.NODE_ENV === 'development' ? config.baseUrl.dev : config.baseUrl.pro;
103
+
104
+ const userStore = useUserStore();
105
+ const appStore = useAppStore();
106
+ const router = useRouter();
107
+ const route = useRoute();
108
+ const kpAliveRef = ref();
109
+
110
+ const {menuList, errorCount, tagPaths} = storeToRefs(appStore);
111
+ const {unreadCount} = storeToRefs(userStore);
112
+
113
+ const hasCustomLogo = computed(() => {
114
+ return !!config.logo;
115
+ });
116
+
117
+ const logo = computed(() => {
118
+ return config.logo;
119
+ });
120
+
121
+ const minLogo = computed(() => {
122
+ return config.minLogo;
123
+ });
124
+
125
+ const isIframe = computed(() => {
126
+ return route.meta.isIframe;
127
+ });
128
+
129
+ const iframeList = ref([]);
130
+ function pushIframe(url) {
131
+ if (!iframeList.value.includes(url)) {
132
+ iframeList.value.push(url);
133
+ }
134
+ }
135
+ onBeforeRouteUpdate((to, form, next) => {
136
+ if (to.meta.isIframe) {
137
+ pushIframe(to.params.url);
138
+ }
139
+ next();
140
+ });
141
+ watch(
142
+ () => tagPaths.value,
143
+ (newVal, oldVal) => {
144
+ let delPath = oldVal.filter((path) => !newVal.includes(path));
145
+ delPath.forEach((path) => {
146
+ iframeList.value = iframeList.value.filter((item) => item !== path);
147
+ });
148
+ }
149
+ );
150
+
151
+ const userName = ref('');
152
+ const collapse = ref(false);
153
+ const unReadMessageMap = ref({});
154
+ const websocketPath = baseUrl.replace('http', 'ws') + '/webSocket';
155
+ const isFullScreen = ref(false);
156
+ let websocket = null;
157
+
158
+ function handleCollapsedChange() {
159
+ collapse.value = !collapse.value;
160
+ }
161
+
162
+ function initWebsocket() {
163
+ let token = getToken();
164
+ if (typeof WebSocket === 'undefined') {
165
+ ElMessage.info('您的浏览器不支持WebSocket');
166
+ } else if (token) {
167
+ try {
168
+ // 实例化websocket
169
+ websocket = new WebSocket(websocketPath + '?$_TOKEN=' + token);
170
+ // 监听websocket的连接
171
+ websocket.onopen = () => {
172
+ console.log('(' + websocketPath + ') websocket连接成功');
173
+ };
174
+ // 监听websocket的错误信息
175
+ websocket.onerror = () => {
176
+ console.log('(' + websocketPath + ') websocket连接错误');
177
+ };
178
+ // 监听websocket的消息
179
+ websocket.onmessage = (msg) => {
180
+ websocketGetMessage(msg);
181
+ };
182
+ // 监听websocket关闭
183
+ websocket.onclose = () => {
184
+ websocketClose();
185
+ };
186
+ } catch (e) {}
187
+ }
188
+ }
189
+
190
+ function websocketGetMessage(msg) {
191
+ let msgData = eval(msg.data);
192
+ if (msgData && msgData.length > 0) {
193
+ msgData.forEach((msg) => {
194
+ if (!unReadMessageMap.value[msg.ID]) {
195
+ unReadMessageMap.value[msg.ID] = msg;
196
+ }
197
+ });
198
+ Object.keys(unReadMessageMap.value).forEach((key) => {
199
+ let msg = unReadMessageMap.value[key];
200
+ if (!msg.hasOwnProperty('show')) {
201
+ ElNotification.open({
202
+ title: msg.TITLE,
203
+ desc: msg.TEXT,
204
+ duration: 0,
205
+ name: msg.ID,
206
+ onClose: () => {
207
+ delete unReadMessageMap.value[msg.ID];
208
+ markRead(msg.ID);
209
+ },
210
+ });
211
+ msg['show'] = true;
212
+ }
213
+ });
214
+ }
215
+ }
216
+
217
+ function websocketSendMessage(msg) {
218
+ websocket.send(msg);
219
+ }
220
+
221
+ function websocketClose() {
222
+ let that = this;
223
+ console.log('websocket关闭,尝试重新连接websocket');
224
+ window.setTimeout(() => {
225
+ that.initWebsocket();
226
+ }, 1000);
227
+ }
228
+
229
+ onMounted(async () => {
230
+ try {
231
+ userName.value = getStorage('userName');
232
+ if (route.meta.isIframe) {
233
+ pushIframe(route.params.url);
234
+ }
235
+ } catch (error) {
236
+ console.error('菜单加载异常:', error);
237
+ }
238
+ });
239
+ onUnmounted(() => {
240
+ ElNotification.closeAll();
241
+ });
242
+ </script>
243
+
244
+ <style lang="scss">
245
+ .main-container.is-iframe {
246
+ padding: 0 !important;
247
+ box-sizing: border-box;
248
+ overflow: hidden;
249
+ > iframe {
250
+ width: 100%;
251
+ height: 100%;
252
+ }
253
+ }
254
+ </style>