@lambo-design/pro-layout 1.0.0-beta.45 → 1.0.0-beta.451

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 (40) hide show
  1. package/package.json +11 -4
  2. package/src/components/pro-layout-header/index.vue +220 -0
  3. package/src/components/pro-layout-header/pro-layout-logo/index.vue +206 -0
  4. package/src/components/pro-layout-header/pro-layout-nav/components/pro-layout-nav-slide-menu.vue +399 -0
  5. package/src/components/pro-layout-header/pro-layout-nav/index-slide.vue +226 -0
  6. package/src/components/pro-layout-header/pro-layout-nav/index.vue +565 -0
  7. package/src/components/pro-layout-header/pro-layout-slogan/index.vue +40 -0
  8. package/src/components/pro-layout-header/pro-layout-tools/components/pro-layout-tools-quick-collect.vue +79 -0
  9. package/src/components/pro-layout-header/pro-layout-tools/components/pro-layout-tools-quick-document.vue +116 -0
  10. package/src/components/pro-layout-header/pro-layout-tools/components/pro-layout-tools-quick-fullscreen.vue +144 -0
  11. package/src/components/pro-layout-header/pro-layout-tools/components/pro-layout-tools-quick-icons.vue +99 -0
  12. package/src/components/pro-layout-header/pro-layout-tools/components/pro-layout-tools-quick-intl.vue +110 -0
  13. package/src/components/pro-layout-header/pro-layout-tools/components/pro-layout-tools-quick-notice.vue +133 -0
  14. package/src/components/pro-layout-header/pro-layout-tools/components/pro-layout-tools-quick-search.vue +305 -0
  15. package/src/components/pro-layout-header/pro-layout-tools/components/pro-layout-tools-quick-todo.vue +145 -0
  16. package/src/components/pro-layout-header/pro-layout-tools/components/pro-layout-tools-user.vue +64 -0
  17. package/src/components/pro-layout-header/pro-layout-tools/index.vue +38 -0
  18. package/src/components/pro-layout-header/pro-layout-trigger/index.vue +84 -0
  19. package/src/components/{pro-layout-sider-collapsed-menu.vue → pro-layout-sider/components/pro-layout-sider-collapsed-menu.vue} +30 -11
  20. package/src/components/{pro-layout-sider-icon.vue → pro-layout-sider/components/pro-layout-sider-icon.vue} +2 -2
  21. package/src/components/pro-layout-sider/components/pro-layout-sider-menu-item.vue +137 -0
  22. package/src/components/pro-layout-sider/components/pro-layout-sider-other-menu.vue +140 -0
  23. package/src/components/pro-layout-sider/components/pro-layout-sider-search.vue +345 -0
  24. package/src/components/pro-layout-sider/index.vue +477 -0
  25. package/src/components/{pro-layout-tabs.vue → pro-layout-tabs/index.vue} +118 -23
  26. package/src/index.vue +306 -40
  27. package/src/styles/color.less +267 -0
  28. package/src/styles/images/xiaoxitongzhi.png +0 -0
  29. package/src/styles/other-menu.less +63 -111
  30. package/src/utils/menuItem.js +10 -0
  31. package/src/utils/sider.js +16 -1
  32. package/src/components/pro-layout-header.vue +0 -52
  33. package/src/components/pro-layout-logo.vue +0 -79
  34. package/src/components/pro-layout-nav.vue +0 -150
  35. package/src/components/pro-layout-other-menu.vue +0 -138
  36. package/src/components/pro-layout-sider-menu-item.vue +0 -37
  37. package/src/components/pro-layout-sider.vue +0 -240
  38. package/src/components/pro-layout-tools-user.vue +0 -84
  39. package/src/components/pro-layout-tools.vue +0 -21
  40. package/src/components/pro-layout-trigger.vue +0 -48
@@ -0,0 +1,477 @@
1
+ <template>
2
+ <div ref="listenWidth" class="pro-layout-sider-wrapper"
3
+ :class="[(collapsed || systemInfo.showSearchMenu === '0') ? 'menu-has-collapsed' : '',tabsHeight != 46 ? 'custom-tabs' : '']">
4
+ <Menu v-show="!collapsed" ref="menu"
5
+ :accordion="isAccordionMode" :active-name="activeName"
6
+ :open-names="openedNames" theme="dark"
7
+ width="auto" @on-select="handleSelect"
8
+ @on-open-change="handleOpenChange">
9
+ <template v-for="(item,index) in menuList">
10
+ <template v-if="item.children && item.children.length === 1">
11
+ <ProLayoutSiderMenuItem v-if="showChildren(item)"
12
+ :key="`menu-${item.name}`"
13
+ :parent-item="item"
14
+ :collect-map="isCollected"
15
+ :system-info="systemInfo"
16
+ :nav-list="navList">
17
+ </ProLayoutSiderMenuItem>
18
+ <MenuItem v-else :key="`menu-${item.children[0].name}`"
19
+ :name="getNameOrHref(item, true)">
20
+ <Row type="flex" justify="center" align="top">
21
+ <Col :span="getSpanNum(systemInfo,'icon')">
22
+ <ProLayoutSiderIcon v-if="systemInfo.menuLogo == '1'" :icon-type="item.type == 2 ? (isCollected.hasOwnProperty(item.name) ? 'ios-star' : 'ios-star-outline') : item.meta.icon"></ProLayoutSiderIcon>
23
+ </Col>
24
+ <Col :span="getSpanNum(systemInfo,'title')">
25
+ <div :class="['menu-title-' + item.children[0].permissionId,'draggable-text']" v-draggable="dragOptions(item.children[0])">
26
+ <Tooltip style="width: 100%" v-if="systemInfo.titleShow ==='ellipsis'" placement="right" transfer :content="showTitle(item.children[0])">
27
+ <div class="menu-title-nochildren-ellipsis">{{ showTitle(item.children[0]) }}</div>
28
+ </Tooltip>
29
+ <span v-else class="menu-title-nochildren-wrap">{{ showTitle(item.children[0]) }}</span>
30
+ </div>
31
+ </Col>
32
+ </Row>
33
+ </MenuItem>
34
+ </template>
35
+ <template v-else>
36
+ <ProLayoutSiderMenuItem v-if="showChildren(item)"
37
+ :key="`menu-${item.name}`"
38
+ :parent-item="item"
39
+ :collect-map="isCollected"
40
+ :system-info="systemInfo"
41
+ :nav-list="navList">
42
+ </ProLayoutSiderMenuItem>
43
+ <MenuItem v-else :key="`menu-${item.name}`"
44
+ :name="getNameOrHref(item)">
45
+ <Row type="flex" justify="center" align="top">
46
+ <Col :span="getSpanNum(systemInfo,'icon')">
47
+ <ProLayoutSiderIcon v-if="systemInfo.menuLogo == '1'" :icon-type="item.type == 2 ? (isCollected.hasOwnProperty(item.name) ? 'ios-star' : 'ios-star-outline') : item.meta.icon"></ProLayoutSiderIcon>
48
+ </Col>
49
+ <Col :span="getSpanNum(systemInfo,'title')">
50
+ <div :class="['menu-title-' + item.permissionId,'draggable-text']" v-draggable="dragOptions(item)">
51
+ <Tooltip style="width: 100%" v-if="systemInfo.titleShow ==='ellipsis'" placement="right" transfer :content="showTitle(item)">
52
+ <div class="menu-title-nochildren-ellipsis">{{ showTitle(item) }}</div>
53
+ </Tooltip>
54
+ <span v-else class="menu-title-nochildren-wrap">{{ showTitle(item) }}</span>
55
+ </div>
56
+ </Col>
57
+ </Row>
58
+ </MenuItem>
59
+ </template>
60
+ </template>
61
+ </Menu>
62
+
63
+ <ProLayoutSiderOtherMenu v-show="systemInfo.showHistoryAndCollect !== '0'" :style="systemInfo.menuScaling === '0' ? { width: otherWidth } : {}" :collapsed="collapsed" @select-menu="selectMenu"></ProLayoutSiderOtherMenu>
64
+ <ProLayoutSiderSearch
65
+ :style="systemInfo.menuScaling === '0' ? { width: otherWidth } : {}"
66
+ v-show="!collapsed && (systemInfo.showSearchMenu !== '0')"
67
+ :searchType="0"
68
+ @select-menu="selectMenu"
69
+ ></ProLayoutSiderSearch>
70
+ <div v-show="collapsed" :list="menuList" class="menu-collapsed" >
71
+ <template v-for="item in menuList">
72
+ <ProLayoutSiderCollapsedMenu v-if="item.children && item.children.length > 0" :key="`drop-menu-${item.name}`"
73
+ :parent-item="item" theme="dark" hide-title transfer
74
+ @on-click="handleSelect" :active-item="openedNames">
75
+ </ProLayoutSiderCollapsedMenu>
76
+ <Tooltip v-else :key="`drop-menu-${item.name}`" :content="showTitle(item.children && item.children[0] ? item.children[0] : item)"
77
+ placement="right" transfer>
78
+ <template v-slot:default="{ active }">
79
+ <a :style="{textAlign: 'center'}"
80
+ :class="['drop-menu-a', item.name === selectedTopParent ? 'selected-parent' : '']"
81
+ @click="handleSelect(getNameOrHref(item, true))">
82
+ <!-- <i :class="[item.meta.icon, selectedIconType === item.meta.icon ? 'selected-icon' : '']"></i>-->
83
+ <ProLayoutSiderIcon :icon-type="item.meta.icon" icon-size="26" :class="{ 'selected-icon': item.name === selectedTopParent && collapsed }"
84
+ ></ProLayoutSiderIcon>
85
+ </a>
86
+ </template>
87
+ </Tooltip>
88
+ </template>
89
+ </div>
90
+
91
+ </div>
92
+ </template>
93
+
94
+ <script>
95
+ import Bus from "@lambo-design/shared/utils/bus";
96
+ import {deepCopy} from "@lambo-design/shared/utils/assist";
97
+ import generatorMenuList from "@lambo-design/shared/utils/menu/index";
98
+ import sider from '../../utils/sider'
99
+ import ProLayoutSiderOtherMenu from "./components/pro-layout-sider-other-menu";
100
+ import ProLayoutSiderSearch from "./components/pro-layout-sider-search";
101
+ import ProLayoutSiderMenuItem from './components/pro-layout-sider-menu-item'
102
+ import ProLayoutSiderCollapsedMenu from './components/pro-layout-sider-collapsed-menu'
103
+ import {
104
+ filterMenuName, filterMenuUri, tagExists,
105
+ isOpenBlank, buildSinglePermission,arraysEqual
106
+ } from "@lambo-design/shared/utils/platform";
107
+ import config from "@lambo-design/shared/config/config";
108
+ import {getThemeVarByKey} from "@lambo-design/shared/utils/theme";
109
+
110
+ export default {
111
+ name: "pro-layout-sider",
112
+ components: {
113
+ ProLayoutSiderMenuItem,
114
+ ProLayoutSiderCollapsedMenu,
115
+ ProLayoutSiderOtherMenu,
116
+ ProLayoutSiderSearch
117
+ },
118
+ props:{
119
+ serverContext: {
120
+ type: String,
121
+ default: () => config.upmsServerContext // 设置默认值
122
+ }
123
+ },
124
+ data(){
125
+ return {
126
+ show: false,
127
+ otherWidth:'',
128
+ originalAllMenuList: [],
129
+ navList: [],
130
+ originMenuList:[],
131
+ menuList: [],
132
+ appId: '',
133
+ collapsed: false,
134
+ activeName: '',
135
+ openedNames: [],
136
+ userExpandedMenus: [], // 记录用户手动展开的菜单(非手风琴模式下使用)
137
+ activeMenu: null,
138
+ selectedMenuParent: null,
139
+ activeMenuItem: null,
140
+ openedSubMenu: null,
141
+ currentMenuItem: null,
142
+ selectedTopParent: '',
143
+ activeIcon: null,
144
+ tagValue: '',
145
+ tagList: [],
146
+ collectMenuList: [],
147
+ isCollected: {},
148
+ systemInfo:{},
149
+ tabsHeight: 46
150
+ }
151
+ },
152
+ mixins:[sider],
153
+ computed: {
154
+ isAccordionMode() {
155
+ // 当 accordionMode 为 '0' 时关闭手风琴模式,否则开启
156
+ return this.systemInfo.accordionMode !== '0';
157
+ }
158
+ },
159
+ methods: {
160
+ initListener(){
161
+ Bus.$on('origin-all-menu-list', (data)=>{
162
+ this.initAllMenu(data);
163
+ });
164
+ Bus.$on('nav-list',(data)=>{
165
+ this.initNav(data)
166
+ });
167
+ Bus.$on('menu-list',(data)=>{
168
+ this.initMenu(data)
169
+ });
170
+ Bus.$on('trigger-change',(data)=>{
171
+ this.triggerChange(data)
172
+ });
173
+ Bus.$on('change-app', ({appId,appInfo})=> {
174
+ this.changeApp(appId,appInfo)
175
+ })
176
+ Bus.$on('tag-list',(data,current)=>{
177
+ this.initTags(data,current)
178
+ });
179
+ Bus.$on('menu-click',(current)=>{
180
+ this.menuClick(current)
181
+ });
182
+ Bus.$on('select-menu',(name,item)=>{
183
+ this.selectMenu(name,item)
184
+ });
185
+ Bus.$on('collect-menu-list',(data)=>{
186
+ this.initCollectMenu(data)
187
+ });
188
+ Bus.$on('system-info',(data)=>{
189
+ this.initSystemInfo(data)
190
+ })
191
+ },
192
+ destroyListener(){
193
+ Bus.$off('origin-all-menu-list')
194
+ Bus.$off('nav-list')
195
+ Bus.$off('menu-list')
196
+ Bus.$off('trigger-change')
197
+ Bus.$off('change-app')
198
+ Bus.$off('tag-list')
199
+ Bus.$off('menu-click')
200
+ Bus.$off('select-menu')
201
+ Bus.$off('collect-menu-list')
202
+ Bus.$off('system-info')
203
+ },
204
+ initSystemInfo(data){
205
+ this.systemInfo = deepCopy(data)
206
+ },
207
+ initAllMenu(data){
208
+ this.originalAllMenuList = data;
209
+ },
210
+ initNav(data){
211
+ if (this.navList && data && arraysEqual(this.navList,data)){
212
+ return;
213
+ }
214
+ this.navList = data;
215
+ },
216
+ initMenu(data){
217
+ if (this.originMenuList && data && arraysEqual(this.originMenuList,data)){
218
+ return;
219
+ }
220
+ if (data && data.length > 0) {
221
+ let item = data[0];
222
+ if (item.appId && item.appId !== this.appId) {
223
+ return;
224
+ }
225
+ }
226
+ this.originMenuList = deepCopy(data);
227
+ this.changeMenu()
228
+ },
229
+ initCollectMenu(data){
230
+ this.collectMenuList = data;
231
+ this.isCollected = {}
232
+ this.collectMenuList.forEach(menu => {
233
+ this.isCollected[menu.name] = true
234
+ })
235
+ },
236
+ changeApp(appId,appInfo){
237
+ this.appId = appId;
238
+ this.changeMenu()
239
+ },
240
+ changeMenu(){
241
+ let treeMenuList = generatorMenuList(this.originMenuList,this.appId,'menu');
242
+ if (treeMenuList && treeMenuList.length > 0) {
243
+ this.menuList = treeMenuList;
244
+ } else {
245
+ this.menuList = [];
246
+ }
247
+ Bus.$emit('tree-menu-list',this.menuList)
248
+ this.openedNames = this.getOpenedNamesByActiveName();
249
+ },
250
+ selectMenu(name,menu) {
251
+ if (!menu) {
252
+ let res = this.originMenuList.filter(item => item.name == name)
253
+ if (res && res.length > 0) {
254
+ menu = res[0];
255
+ }
256
+ }
257
+ if (config.mainType && config.mainType == 'singleApp') {
258
+ menu = buildSinglePermission(this.originalAllMenuList, menu);
259
+ }
260
+ if (menu.appId && menu.appId != this.appId) {
261
+ let appInfo = this.navList.filter(app => app.appId === menu.appId);
262
+ Bus.$emit('change-app', {appId:menu.appId,appInfo:appInfo[0]})
263
+ }
264
+ setTimeout(()=>{
265
+ this.handleSelect(name)
266
+ },100)
267
+ },
268
+ handleSelect(name,uri,pid){
269
+ /*if (this.activeName == name) {
270
+ return;
271
+ }*/
272
+ let menu = null;
273
+ if (name.indexOf("isTurnByHref_") > -1) {
274
+ name = name.replace("isTurnByHref_","");
275
+ menu = filterMenuUri(this.menuList,name);
276
+ } else {
277
+ menu = filterMenuName(this.menuList,name);
278
+ }
279
+ let tagList = this.tagList;
280
+ if (menu && menu.name) {
281
+ if (isOpenBlank(menu)) {
282
+ Bus.$emit('menu-click', menu.name , menu)
283
+ } else {
284
+ let tag = tagList.find(item => item.name == menu.name);
285
+ if (!tag) {
286
+ tag = {}
287
+ }
288
+ if ('home' != menu.name) {
289
+ let res = tagList.filter(item => item.name !== menu.name);
290
+ menu.cts = new Date().getTime();
291
+ tag = Object.assign(tag, menu);
292
+ res.push(tag);
293
+ tagList = deepCopy(res);
294
+ }
295
+ Bus.$emit('tag-list', tagList, menu.name)
296
+ }
297
+
298
+ /*if (!tagExists(tagList,menu.name)) {
299
+ if (!isOpenBlank(menu)) {
300
+ tagList.push(menu);
301
+ } else {
302
+ Bus.$emit('menu-click', menu.name , menu)
303
+ }
304
+ } else {
305
+ let tag = tagList.find(item => item.name == menu.name);
306
+ if ('home' != menu.name) {
307
+ let res = tagList.filter(item => item.name !== menu.name);
308
+ menu.cts = new Date().getTime();
309
+ tag = Object.assign(tag, menu);
310
+ res.push(tag);
311
+ tagList = deepCopy(res);
312
+ }
313
+ }
314
+ Bus.$emit('tag-list', tagList, menu.name)*/
315
+ }
316
+ /*if (menu.meta && Array.isArray(menu.meta.crumbs)) {
317
+ let parentMenu = menu.meta.crumbs[0]
318
+ this.$set(this, 'selectedTopParent', parentMenu.name);
319
+ } else {
320
+ // 处理没有父菜单的情况
321
+ this.$set(this, 'selectedTopParent', menu.name);
322
+ }
323
+ // 如果 uri 为空,则需要根据 pid 判断是展开父菜单还是同时展开父菜单和当前菜单
324
+ if (!uri) {
325
+ let parentName;
326
+ if (pid === 0) {
327
+ // 如果 pid 为 0,表示是最外层菜单
328
+ parentName = this.getNameOrHref(menu);
329
+ } else {
330
+ // 如果 pid 不等于 0,查找并打开对应的最外层父菜单
331
+ parentName = this.getTopParent(menu);
332
+ this.openedNames = [parentName]; // 设置最外层父菜单为展开状态
333
+ this.activeName = menu.name; // 设置当前菜单为激活状态
334
+ }
335
+ }*/
336
+ },
337
+ getTopParent(menu) {
338
+ return menu.parent ? this.getTopParent(menu.parent) : menu.name;
339
+ },
340
+ triggerChange(data){
341
+ this.collapsed = data;
342
+ },
343
+ initTags(data,name){
344
+ this.tagList = data;
345
+ this.value = name;
346
+ },
347
+ menuClick(current) {
348
+ let item = this.originMenuList.filter(menu => menu.name === current && menu.type && menu.type == '2');
349
+ if (item && item.length > 0){
350
+ if (isOpenBlank(item[0])) {
351
+ //window.location.href = window.location.href;
352
+ return;
353
+ }
354
+ let type = item[0].type;
355
+ if (type == 2) {
356
+ this.activeName = current;
357
+ } else {
358
+ let pItem = this.originMenuList.filter(menu => menu.permissionId === item[0].pid);
359
+ if (pItem && pItem.length > 0){
360
+ this.activeName = pItem[0].name;
361
+ }
362
+ }
363
+ } else {
364
+ this.activeName = current;
365
+ }
366
+ },
367
+ getOpenedNamesByActiveName(){
368
+ let res = filterMenuName(this.menuList,this.activeName);
369
+ let openNames = []
370
+ if (res) {
371
+ const crumbs = res.meta.crumbs;
372
+ if (crumbs) {
373
+ crumbs.forEach(item => {
374
+ if (item.type === 1) {
375
+ openNames.push(item.name)
376
+ }
377
+ })
378
+ }
379
+ }
380
+ return openNames
381
+ },
382
+ handleOpenChange(openNames) {
383
+ // openNames 是 Menu 组件当前的所有展开项
384
+ if (this.systemInfo.accordionMode === '0') {
385
+ // 非手风琴模式:保存用户手动展开的状态
386
+ this.userExpandedMenus = [...openNames];
387
+ }
388
+ // 注意:这里不直接修改 this.openedNames,避免循环触发
389
+ },
390
+ mergeOpenedNames(newNames) {
391
+ // 如果关闭手风琴模式,保留用户手动展开的菜单
392
+ if (this.systemInfo.accordionMode === '0') {
393
+ // 合并用户展开的菜单和新的必需展开项
394
+ const merged = [...new Set([...this.userExpandedMenus, ...newNames])];
395
+ return merged;
396
+ } else {
397
+ // 手风琴模式,只保留新的 names(路径必需的展开项)
398
+ return newNames;
399
+ }
400
+ },
401
+ handleResize() {
402
+ const targetElement = this.$refs.listenWidth; // 获取 DOM 元素的引用
403
+ this.otherWidth = targetElement.clientWidth+'px'; // 获取 div 元素的宽度
404
+ },
405
+ dragOptions(item){
406
+ if (!item) {
407
+ item = {}
408
+ }
409
+ item.navList = this.navList;
410
+ return {
411
+ trigger: '.menu-title-' + item.permissionId,
412
+ body: '.menu-title-' + item.permissionId,
413
+ recover: true,
414
+ item: item
415
+ }
416
+ },
417
+ loadingCustomStyle(){
418
+ let themeKey = localStorage.getItem("theme") ? localStorage.getItem("theme") : "default"
419
+ let tabsHeight = getThemeVarByKey(themeKey,'--layout-tabs-height');
420
+ if (tabsHeight) {
421
+ this.tabsHeight = tabsHeight;
422
+ }
423
+ }
424
+ },
425
+ watch:{
426
+ activeName(){
427
+ const newOpenNames = this.getOpenedNamesByActiveName();
428
+ this.openedNames = this.mergeOpenedNames(newOpenNames);
429
+ },
430
+ openedNames() {
431
+ this.$nextTick(() => {
432
+ this.$refs.menu.updateOpened()
433
+ this.$refs.menu.updateActiveName()
434
+ })
435
+ }
436
+ },
437
+ mounted() {
438
+ window.addEventListener('resize', this.handleResize); // 监听窗口大小变化事件
439
+ this.handleResize(); // 初始化时获取一次宽度
440
+ this.loadingCustomStyle();
441
+ },
442
+ created(){
443
+ this.initListener();
444
+ },
445
+ beforeDestroy(){
446
+ this.destroyListener();
447
+ window.removeEventListener('resize', this.handleResize); // 在组件销毁前移除事件监听器,以防止内存泄漏
448
+ }
449
+
450
+ }
451
+ </script>
452
+
453
+ <style scoped lang="less">
454
+ @import "@lambo-design/core/src/styles/default";
455
+ @import '../../styles/other-menu.less';
456
+ .pro-layout-sider-wrapper{
457
+ margin-bottom: 50px;
458
+ padding-top: 47px;
459
+ .menu-collapsed {
460
+ padding-top: 10px;
461
+ /deep/a.drop-menu-a{
462
+ display: inline-block;
463
+ padding: 6px 20px;
464
+ width: 100%;
465
+ text-align: center;
466
+ font-weight: normal;
467
+ }
468
+ overflow: hidden;
469
+ }
470
+ &.menu-has-collapsed{
471
+ padding-top: 0 !important;
472
+ }
473
+ &.custom-tabs{
474
+ padding-top: 36px;
475
+ }
476
+ }
477
+ </style>