@lambo-design/pro-layout 1.0.0-beta.384 → 1.0.0-beta.388
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 +3 -3
- package/src/components/pro-layout-header/index.vue +93 -4
- package/src/components/pro-layout-header/pro-layout-nav/components/pro-layout-nav-slide-menu.vue +167 -35
- package/src/components/pro-layout-header/pro-layout-nav/index-slide.vue +153 -22
- package/src/components/pro-layout-header/pro-layout-nav/index.vue +235 -72
- package/src/components/pro-layout-header/pro-layout-tools/components/pro-layout-tools-quick-icons.vue +0 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lambo-design/pro-layout",
|
|
3
|
-
"version": "1.0.0-beta.
|
|
3
|
+
"version": "1.0.0-beta.388",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"author": "lambo",
|
|
@@ -10,8 +10,8 @@
|
|
|
10
10
|
"registry": "https://registry.npmjs.org/"
|
|
11
11
|
},
|
|
12
12
|
"devDependencies": {
|
|
13
|
-
"@lambo-design/core": "^4.7.1-beta.
|
|
14
|
-
"@lambo-design/shared": "^1.0.0-beta.
|
|
13
|
+
"@lambo-design/core": "^4.7.1-beta.167",
|
|
14
|
+
"@lambo-design/shared": "^1.0.0-beta.280"
|
|
15
15
|
},
|
|
16
16
|
"scripts": {
|
|
17
17
|
"release-pro-layout": "pnpm release-beta && git push --follow-tags && pnpm re-publish",
|
|
@@ -12,7 +12,9 @@
|
|
|
12
12
|
</div>
|
|
13
13
|
<div class="nav-box" v-show="!systemInfo || !systemInfo.navType || systemInfo.navType == 'dropdown'">
|
|
14
14
|
<slot name="pro-layout-nav">
|
|
15
|
-
<LamboProNav
|
|
15
|
+
<LamboProNav
|
|
16
|
+
:available-width="availableWidth"
|
|
17
|
+
></LamboProNav>
|
|
16
18
|
</slot>
|
|
17
19
|
</div>
|
|
18
20
|
<div class="tools-box">
|
|
@@ -25,8 +27,11 @@
|
|
|
25
27
|
</template>
|
|
26
28
|
</LamboProTools>
|
|
27
29
|
</div>
|
|
28
|
-
<div v-show="systemInfo && systemInfo.navType && systemInfo.navType == 'slide'">
|
|
29
|
-
<LamboProNavSilde
|
|
30
|
+
<div class="nav-slide-container" v-show="systemInfo && systemInfo.navType && systemInfo.navType == 'slide'" ref="slideContainer">
|
|
31
|
+
<LamboProNavSilde
|
|
32
|
+
:available-width="availableWidth"
|
|
33
|
+
@width-change="handleSlideWidthChange"
|
|
34
|
+
></LamboProNavSilde>
|
|
30
35
|
</div>
|
|
31
36
|
</div>
|
|
32
37
|
</template>
|
|
@@ -38,6 +43,7 @@ import LamboProNav from './pro-layout-nav'
|
|
|
38
43
|
import LamboProNavSilde from './pro-layout-nav/index-slide'
|
|
39
44
|
import LamboProTools from './pro-layout-tools'
|
|
40
45
|
import Bus from "@lambo-design/shared/utils/bus";
|
|
46
|
+
|
|
41
47
|
export default {
|
|
42
48
|
name: "pro-layout-header",
|
|
43
49
|
props:{
|
|
@@ -53,6 +59,8 @@ export default {
|
|
|
53
59
|
data(){
|
|
54
60
|
return {
|
|
55
61
|
systemInfo: {},
|
|
62
|
+
availableWidth: 0,
|
|
63
|
+
resizeTimer: null,
|
|
56
64
|
}
|
|
57
65
|
},
|
|
58
66
|
components: {
|
|
@@ -72,16 +80,92 @@ export default {
|
|
|
72
80
|
Bus.$on('system-info',(data)=>{
|
|
73
81
|
this.initSystem(data)
|
|
74
82
|
});
|
|
83
|
+
|
|
84
|
+
// 监听窗口大小变化
|
|
85
|
+
window.addEventListener('resize', this.handleResize);
|
|
75
86
|
},
|
|
76
87
|
destroyListener(){
|
|
77
|
-
Bus.$off('system-info')
|
|
88
|
+
Bus.$off('system-info');
|
|
89
|
+
window.removeEventListener('resize', this.handleResize);
|
|
78
90
|
},
|
|
79
91
|
initSystem(data){
|
|
80
92
|
if (data) {
|
|
81
93
|
this.systemInfo = data;
|
|
94
|
+
// 当系统信息加载完成后,如果是slide模式,计算可用宽度
|
|
95
|
+
this.$nextTick(() => {
|
|
96
|
+
this.calculateAvailableWidth();
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
},
|
|
100
|
+
// 计算slide导航可用宽度
|
|
101
|
+
calculateAvailableWidth() {
|
|
102
|
+
if (!this.systemInfo) {
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
try {
|
|
107
|
+
// 获取页面总宽度
|
|
108
|
+
const docWidth = document.getElementById("app")?.clientWidth || window.innerWidth;
|
|
109
|
+
|
|
110
|
+
// 获取各个组件的宽度
|
|
111
|
+
const triggerBoxWidth = this.getTriggerBoxWidth();
|
|
112
|
+
const logoBoxWidth = this.getLogoBoxWidth();
|
|
113
|
+
const toolsBoxWidth = this.getToolsBoxWidth();
|
|
114
|
+
|
|
115
|
+
// 预留一些空间给箭头按钮和边距
|
|
116
|
+
const reservedWidth = 150;
|
|
117
|
+
|
|
118
|
+
// 计算可用宽度
|
|
119
|
+
this.availableWidth = docWidth - triggerBoxWidth - logoBoxWidth - toolsBoxWidth - reservedWidth;
|
|
120
|
+
|
|
121
|
+
// 确保最小宽度
|
|
122
|
+
this.availableWidth = Math.max(this.availableWidth, 200);
|
|
123
|
+
|
|
124
|
+
} catch (error) {
|
|
125
|
+
console.warn('Error calculating available width:', error);
|
|
126
|
+
this.availableWidth = 800; // 默认值
|
|
82
127
|
}
|
|
128
|
+
},
|
|
129
|
+
|
|
130
|
+
// 获取trigger组件宽度
|
|
131
|
+
getTriggerBoxWidth() {
|
|
132
|
+
const triggerBox = document.querySelector('.trigger-box');
|
|
133
|
+
return triggerBox ? triggerBox.clientWidth : 0;
|
|
134
|
+
},
|
|
135
|
+
|
|
136
|
+
// 获取logo组件宽度
|
|
137
|
+
getLogoBoxWidth() {
|
|
138
|
+
const logoBox = document.querySelector('.logo-box');
|
|
139
|
+
return logoBox ? logoBox.clientWidth : 0;
|
|
140
|
+
},
|
|
141
|
+
|
|
142
|
+
// 获取tools组件宽度
|
|
143
|
+
getToolsBoxWidth() {
|
|
144
|
+
const toolsBox = document.querySelector('.tools-box');
|
|
145
|
+
return toolsBox ? toolsBox.clientWidth : 0;
|
|
146
|
+
},
|
|
147
|
+
|
|
148
|
+
// 处理窗口大小变化
|
|
149
|
+
handleResize() {
|
|
150
|
+
// 防抖处理
|
|
151
|
+
clearTimeout(this.resizeTimer);
|
|
152
|
+
this.resizeTimer = setTimeout(() => {
|
|
153
|
+
this.calculateAvailableWidth();
|
|
154
|
+
}, 150);
|
|
155
|
+
},
|
|
156
|
+
|
|
157
|
+
// 处理slide组件宽度变化
|
|
158
|
+
handleSlideWidthChange(data) {
|
|
159
|
+
// console.log('Slide width change:', data);
|
|
160
|
+
// 可以在这里处理slide组件宽度变化的逻辑
|
|
83
161
|
}
|
|
84
162
|
},
|
|
163
|
+
mounted() {
|
|
164
|
+
// 组件挂载后计算一次宽度
|
|
165
|
+
this.$nextTick(() => {
|
|
166
|
+
this.calculateAvailableWidth();
|
|
167
|
+
});
|
|
168
|
+
},
|
|
85
169
|
created(){
|
|
86
170
|
this.initListener();
|
|
87
171
|
},
|
|
@@ -105,6 +189,11 @@ export default {
|
|
|
105
189
|
.nav-box{
|
|
106
190
|
float: left;
|
|
107
191
|
}
|
|
192
|
+
.nav-slide-container{
|
|
193
|
+
float: left;
|
|
194
|
+
flex: 1;
|
|
195
|
+
overflow: hidden;
|
|
196
|
+
}
|
|
108
197
|
.tools-box{
|
|
109
198
|
float: right;
|
|
110
199
|
}
|
package/src/components/pro-layout-header/pro-layout-nav/components/pro-layout-nav-slide-menu.vue
CHANGED
|
@@ -1,12 +1,17 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div class="menu-list" >
|
|
2
|
+
<div class="menu-list" ref="menuList">
|
|
3
3
|
<ul class="top-menu" :style="layoutSize === 'default' ? {height: '64px'} : {height: '50px'}" ref="topNav">
|
|
4
|
-
<
|
|
5
|
-
<
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
4
|
+
<template v-for="(item,index) in topMenList" >
|
|
5
|
+
<li class="top-menu-item"
|
|
6
|
+
:class="{ 'active': activeName === item.appId }"
|
|
7
|
+
:key="item.appId"
|
|
8
|
+
@click="selectApp(item.appId)">
|
|
9
|
+
<div class="menu-item" :style="layoutSize === 'default' ? {paddingTop: '10px'} : {paddingTop: '2px'}">
|
|
10
|
+
<p class="menu-icon" v-show="systemInfo.navLogo==='1'"><Icon :type="item.icon" :size="20"></Icon></p>
|
|
11
|
+
<p class="menu-txt" :title="item.name">{{ item.name }}</p>
|
|
12
|
+
</div>
|
|
13
|
+
</li>
|
|
14
|
+
</template>
|
|
10
15
|
</ul>
|
|
11
16
|
</div>
|
|
12
17
|
</template>
|
|
@@ -24,13 +29,16 @@ export default {
|
|
|
24
29
|
topMenListNum: {
|
|
25
30
|
type: Number,
|
|
26
31
|
default: 0
|
|
32
|
+
},
|
|
33
|
+
availableWidth: {
|
|
34
|
+
type: Number,
|
|
35
|
+
default: 800
|
|
27
36
|
}
|
|
28
37
|
},
|
|
29
38
|
data() {
|
|
30
39
|
return {
|
|
31
40
|
systemInfo:{},
|
|
32
41
|
pointer:0,
|
|
33
|
-
flag:true,
|
|
34
42
|
arrowFlag: true,
|
|
35
43
|
acceptAppId: '',
|
|
36
44
|
navList: [],
|
|
@@ -39,9 +47,12 @@ export default {
|
|
|
39
47
|
otherList: [],
|
|
40
48
|
activeName: '',
|
|
41
49
|
topMenuNum: 7,
|
|
50
|
+
displayMenuNum: 7, // 实际显示的菜单数量
|
|
42
51
|
lastTopMenuNum:-1,
|
|
43
52
|
originMenuList: [],
|
|
44
|
-
layoutSize:"default"
|
|
53
|
+
layoutSize:"default",
|
|
54
|
+
// menuItemWidths: [], // 存储每个菜单项的宽度
|
|
55
|
+
resizeObserver: null,
|
|
45
56
|
}
|
|
46
57
|
},
|
|
47
58
|
methods: {
|
|
@@ -79,18 +90,13 @@ export default {
|
|
|
79
90
|
}
|
|
80
91
|
this.navList = data
|
|
81
92
|
this.lastTopMenuNum = this.topMenuNum
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
// this.otherList = navList
|
|
90
|
-
} else {
|
|
91
|
-
this.topMenList = this.navList
|
|
92
|
-
this.$emit('topMen-true', false);
|
|
93
|
-
}
|
|
93
|
+
|
|
94
|
+
this.topMenList = data
|
|
95
|
+
this.$emit('topMen-list', this.topMenList);
|
|
96
|
+
|
|
97
|
+
// 计算可以显示的菜单数量
|
|
98
|
+
this.calculateDisplayMenuNum();
|
|
99
|
+
|
|
94
100
|
if (this.topMenList.length > 0) {
|
|
95
101
|
let appId = this.topMenList[0].appId
|
|
96
102
|
for (let i = 0; i < this.topMenList.length; i++) {
|
|
@@ -104,6 +110,94 @@ export default {
|
|
|
104
110
|
this.selectApp(appId)
|
|
105
111
|
}
|
|
106
112
|
},
|
|
113
|
+
// 计算可以显示的菜单数量
|
|
114
|
+
calculateDisplayMenuNum() {
|
|
115
|
+
this.$nextTick(() => {
|
|
116
|
+
if (!this.$refs.menuList) return;
|
|
117
|
+
|
|
118
|
+
// 获取单个菜单项的平均宽度
|
|
119
|
+
// const menuItems = this.$refs.menuList.querySelectorAll('.top-menu-item');
|
|
120
|
+
// if (menuItems.length === 0) return;
|
|
121
|
+
|
|
122
|
+
let totalWidth = 0;
|
|
123
|
+
let itemWidths = [];
|
|
124
|
+
|
|
125
|
+
// 临时显示所有菜单项以测量宽度
|
|
126
|
+
// menuItems.forEach((item, index) => {
|
|
127
|
+
// item.style.display = 'block';
|
|
128
|
+
// const width = item.offsetWidth;
|
|
129
|
+
// itemWidths.push(width);
|
|
130
|
+
// totalWidth += width;
|
|
131
|
+
// });
|
|
132
|
+
|
|
133
|
+
// this.menuItemWidths = itemWidths;
|
|
134
|
+
|
|
135
|
+
// 计算可以显示的菜单数量
|
|
136
|
+
let displayCount = 0;
|
|
137
|
+
let accumulatedWidth = 0;
|
|
138
|
+
const reservedWidth = 40; // 预留一些边距
|
|
139
|
+
|
|
140
|
+
this.navList.forEach((item, index) => {
|
|
141
|
+
const estimatedWidth = this.estimateMenuItemWidth(item);
|
|
142
|
+
if (accumulatedWidth + estimatedWidth <= this.availableWidth - reservedWidth) {
|
|
143
|
+
accumulatedWidth += estimatedWidth;
|
|
144
|
+
displayCount++;
|
|
145
|
+
}
|
|
146
|
+
})
|
|
147
|
+
//
|
|
148
|
+
// for (let i = 0; i < itemWidths.length; i++) {
|
|
149
|
+
// if (accumulatedWidth + itemWidths[i] <= this.availableWidth - reservedWidth) {
|
|
150
|
+
// accumulatedWidth += itemWidths[i];
|
|
151
|
+
// displayCount++;
|
|
152
|
+
// } else {
|
|
153
|
+
// break;
|
|
154
|
+
// }
|
|
155
|
+
// }
|
|
156
|
+
|
|
157
|
+
// 确保至少显示一个菜单项
|
|
158
|
+
let displayMenuNum = Math.max(1, displayCount);
|
|
159
|
+
|
|
160
|
+
// 如果配置的数量更小则依赖配置
|
|
161
|
+
if(this.topMenuNum < displayMenuNum){
|
|
162
|
+
this.displayMenuNum = this.topMenuNum
|
|
163
|
+
}else{
|
|
164
|
+
this.displayMenuNum = displayMenuNum
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// this.displayMenuNum = Math.max(1, displayCount);
|
|
168
|
+
// 判断是否需要显示箭头
|
|
169
|
+
const needArrows = this.topMenList.length > this.displayMenuNum;
|
|
170
|
+
this.$emit('topMen-num', this.displayMenuNum);
|
|
171
|
+
this.$emit('topMen-true', needArrows);
|
|
172
|
+
|
|
173
|
+
// 向父组件报告实际宽度
|
|
174
|
+
this.$emit('menu-width-change', totalWidth);
|
|
175
|
+
|
|
176
|
+
//重新调整样式
|
|
177
|
+
menuItems.forEach((item, index) => {
|
|
178
|
+
if(!(this.pointer <= index && index < (this.pointer + this.displayMenuNum))){
|
|
179
|
+
item.style.display = 'none';
|
|
180
|
+
}else{
|
|
181
|
+
item.style.display = 'block'
|
|
182
|
+
}
|
|
183
|
+
});
|
|
184
|
+
});
|
|
185
|
+
},
|
|
186
|
+
estimateMenuItemWidth(item) {
|
|
187
|
+
// 基础宽度:内边距 + 边框
|
|
188
|
+
let baseWidth = 30;
|
|
189
|
+
|
|
190
|
+
// 图标宽度
|
|
191
|
+
if (item.icon && this.systemInfo.navLogo === '1') {
|
|
192
|
+
baseWidth += 30;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// 文字宽度估算(每个字符约14px)
|
|
196
|
+
|
|
197
|
+
const textWidth = (item.name || '').length * 14;
|
|
198
|
+
return baseWidth + textWidth;
|
|
199
|
+
},
|
|
200
|
+
|
|
107
201
|
selectApp(appId) {
|
|
108
202
|
if (appId) {
|
|
109
203
|
this.activeName = appId
|
|
@@ -115,18 +209,60 @@ export default {
|
|
|
115
209
|
if (appId) {
|
|
116
210
|
this.activeName = appId
|
|
117
211
|
}
|
|
212
|
+
},
|
|
213
|
+
// 监听菜单容器大小变化
|
|
214
|
+
observeResize() {
|
|
215
|
+
if (window.ResizeObserver) {
|
|
216
|
+
this.resizeObserver = new ResizeObserver(() => {
|
|
217
|
+
this.calculateDisplayMenuNum();
|
|
218
|
+
this.controlVisable()
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
if (this.$refs.menuList) {
|
|
222
|
+
this.resizeObserver.observe(this.$refs.menuList);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
},
|
|
226
|
+
controlVisable(){
|
|
227
|
+
//重新调整样式
|
|
228
|
+
const menuItems = this.$refs.menuList.querySelectorAll('.top-menu-item');
|
|
229
|
+
menuItems.forEach((item, index) => {
|
|
230
|
+
if(!(this.pointer <= index && index < (this.pointer + this.displayMenuNum))){
|
|
231
|
+
item.style.display = 'none';
|
|
232
|
+
}else{
|
|
233
|
+
item.style.display = 'block';
|
|
234
|
+
}
|
|
235
|
+
});
|
|
118
236
|
}
|
|
119
237
|
},
|
|
120
238
|
watch: {
|
|
121
239
|
acceptInt(val){
|
|
122
240
|
this.pointer = val;
|
|
241
|
+
this.controlVisable()
|
|
242
|
+
},
|
|
243
|
+
availableWidth(newVal, oldVal) {
|
|
244
|
+
if (newVal !== oldVal) {
|
|
245
|
+
this.calculateDisplayMenuNum();
|
|
246
|
+
}
|
|
247
|
+
},
|
|
248
|
+
topMenList() {
|
|
249
|
+
this.calculateDisplayMenuNum();
|
|
123
250
|
}
|
|
124
251
|
},
|
|
252
|
+
mounted() {
|
|
253
|
+
this.calculateDisplayMenuNum();
|
|
254
|
+
this.$nextTick(() => {
|
|
255
|
+
this.observeResize();
|
|
256
|
+
});
|
|
257
|
+
},
|
|
125
258
|
created() {
|
|
126
259
|
this.initListener()
|
|
127
260
|
},
|
|
128
261
|
beforeDestroy() {
|
|
129
|
-
this.destroyListener()
|
|
262
|
+
this.destroyListener();
|
|
263
|
+
if (this.resizeObserver) {
|
|
264
|
+
this.resizeObserver.disconnect();
|
|
265
|
+
}
|
|
130
266
|
}
|
|
131
267
|
}
|
|
132
268
|
</script>
|
|
@@ -136,58 +272,54 @@ export default {
|
|
|
136
272
|
.menu-list {
|
|
137
273
|
height: 100%;
|
|
138
274
|
line-height: 24px;
|
|
139
|
-
//color: #ffffff;
|
|
140
275
|
cursor: pointer;
|
|
141
276
|
font-size: 16px;
|
|
142
277
|
margin-left: 15px;
|
|
278
|
+
overflow: hidden;
|
|
279
|
+
|
|
143
280
|
.top-menu {
|
|
144
281
|
overflow: hidden;
|
|
282
|
+
white-space: nowrap;
|
|
283
|
+
|
|
145
284
|
.top-menu-item {
|
|
146
285
|
padding-left: 15px;
|
|
147
286
|
padding-right: 15px;
|
|
148
287
|
position: relative;
|
|
149
288
|
height: 100%;
|
|
150
|
-
//color: #FFFFFF;
|
|
151
289
|
list-style: none;
|
|
152
290
|
float: left;
|
|
291
|
+
transition: all 0.3s ease;
|
|
292
|
+
|
|
153
293
|
&:hover {
|
|
154
|
-
//background: transparent;
|
|
155
294
|
.menu-item {
|
|
156
|
-
//
|
|
295
|
+
// hover styles
|
|
157
296
|
}
|
|
158
297
|
}
|
|
159
298
|
&.active {
|
|
160
|
-
//background-image: linear-gradient(to bottom, rgba(255, 255, 255, 0.5), rgba(255, 255, 255, 0)) !important;
|
|
161
|
-
//border-bottom: 2px solid var(--primary-color-tint-5, @_primary-color-tint-5);
|
|
162
299
|
.menu-item {
|
|
163
|
-
//
|
|
164
|
-
//width: 135px;
|
|
300
|
+
// active styles
|
|
165
301
|
}
|
|
166
302
|
}
|
|
167
303
|
.menu-item {
|
|
168
304
|
display: flex;
|
|
169
305
|
margin-top: 10px;
|
|
170
306
|
text-align: center;
|
|
171
|
-
//padding-right: 10px;
|
|
172
|
-
//width: 135px;
|
|
173
|
-
|
|
174
307
|
}
|
|
175
308
|
.menu-icon {
|
|
176
309
|
height: 20px;
|
|
177
310
|
line-height: 20px;
|
|
178
311
|
text-align: center;
|
|
179
312
|
margin-right: 10px;
|
|
180
|
-
//margin-left: 10px;
|
|
181
313
|
margin-top: 3px;
|
|
182
314
|
}
|
|
183
315
|
.menu-txt {
|
|
184
316
|
text-align: center;
|
|
185
317
|
font-size: 14px;
|
|
186
318
|
line-height: 2;
|
|
187
|
-
//width: 135px;
|
|
188
319
|
white-space: nowrap;
|
|
189
320
|
overflow: hidden;
|
|
190
321
|
text-overflow: ellipsis;
|
|
322
|
+
max-width: 120px; // 限制最大宽度
|
|
191
323
|
}
|
|
192
324
|
}
|
|
193
325
|
}
|
|
@@ -1,10 +1,17 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div class="pro-layout-nav-slide-wrapper">
|
|
3
|
-
<div class="nav-box-slide">
|
|
4
|
-
<LamboProNavSlideMenu
|
|
2
|
+
<div class="pro-layout-nav-slide-wrapper" ref="slideWrapper">
|
|
3
|
+
<div class="nav-box-slide" ref="navBox" :style="{ width: availableWidth + 'px' }">
|
|
4
|
+
<LamboProNavSlideMenu
|
|
5
|
+
:accept-int="pointer"
|
|
6
|
+
:available-width="availableWidth"
|
|
7
|
+
@topMen-list="handleCustomEvent"
|
|
8
|
+
@topMen-num="topMen"
|
|
9
|
+
@topMen-true="topMenTrue"
|
|
10
|
+
@menu-width-change="handleMenuWidthChange"
|
|
11
|
+
></LamboProNavSlideMenu>
|
|
5
12
|
</div>
|
|
6
13
|
<!--slide按钮-->
|
|
7
|
-
<div class="tools-box-slide">
|
|
14
|
+
<div class="tools-box-slide" v-if="shouldShowArrows">
|
|
8
15
|
<div style="margin-right: 50px;">
|
|
9
16
|
<Icon
|
|
10
17
|
class="more-menu"
|
|
@@ -12,12 +19,14 @@
|
|
|
12
19
|
type="md-arrow-dropleft-circle"
|
|
13
20
|
v-if="arrowFlag"
|
|
14
21
|
@click="moveMenu('left')"
|
|
22
|
+
:style="{ opacity: canMoveLeft ? 1 : 0.3 }"
|
|
15
23
|
/>
|
|
16
24
|
<Icon
|
|
17
25
|
type="md-arrow-dropright-circle"
|
|
18
26
|
class="more-menu"
|
|
19
27
|
v-if="arrowFlag"
|
|
20
28
|
@click="moveMenu('right')"
|
|
29
|
+
:style="{ opacity: canMoveRight ? 1 : 0.3 }"
|
|
21
30
|
/>
|
|
22
31
|
</div>
|
|
23
32
|
</div>
|
|
@@ -26,13 +35,29 @@
|
|
|
26
35
|
|
|
27
36
|
<script>
|
|
28
37
|
import LamboProNavSlideMenu from './components/pro-layout-nav-slide-menu'
|
|
38
|
+
|
|
29
39
|
export default {
|
|
40
|
+
props: {
|
|
41
|
+
availableWidth: {
|
|
42
|
+
type: Number,
|
|
43
|
+
default: 800
|
|
44
|
+
},
|
|
45
|
+
autoCalculateWidth: {
|
|
46
|
+
type: Boolean,
|
|
47
|
+
default: true
|
|
48
|
+
}
|
|
49
|
+
},
|
|
30
50
|
data(){
|
|
31
51
|
return {
|
|
32
|
-
pointer:0,
|
|
33
|
-
topList:[],
|
|
34
|
-
topNum:0,
|
|
35
|
-
arrowFlag:
|
|
52
|
+
pointer: 0,
|
|
53
|
+
topList: [],
|
|
54
|
+
topNum: 0,
|
|
55
|
+
arrowFlag: false,
|
|
56
|
+
menuActualWidth: 0,
|
|
57
|
+
shouldShowArrows: false,
|
|
58
|
+
canMoveLeft: false,
|
|
59
|
+
canMoveRight: false,
|
|
60
|
+
resizeObserver: null,
|
|
36
61
|
}
|
|
37
62
|
},
|
|
38
63
|
components: {
|
|
@@ -42,48 +67,154 @@ export default {
|
|
|
42
67
|
handleCustomEvent(data) {
|
|
43
68
|
// 接收子组件传递的数据
|
|
44
69
|
this.topList = data;
|
|
70
|
+
this.checkWidthAndArrows();
|
|
45
71
|
},
|
|
46
72
|
topMen(data){
|
|
47
73
|
this.topNum = data;
|
|
74
|
+
this.checkWidthAndArrows();
|
|
48
75
|
},
|
|
49
76
|
topMenTrue(data){
|
|
50
|
-
this.arrowFlag = data
|
|
77
|
+
this.arrowFlag = data;
|
|
78
|
+
this.checkWidthAndArrows();
|
|
79
|
+
},
|
|
80
|
+
// 处理菜单宽度变化
|
|
81
|
+
handleMenuWidthChange(width) {
|
|
82
|
+
this.menuActualWidth = width;
|
|
83
|
+
this.checkWidthAndArrows();
|
|
84
|
+
},
|
|
85
|
+
// 检查宽度并决定是否显示箭头
|
|
86
|
+
checkWidthAndArrows() {
|
|
87
|
+
this.$nextTick(() => {
|
|
88
|
+
if (!this.autoCalculateWidth) {
|
|
89
|
+
this.shouldShowArrows = this.arrowFlag;
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// 计算实际菜单宽度
|
|
94
|
+
const navBox = this.$refs.navBox;
|
|
95
|
+
if (navBox) {
|
|
96
|
+
const menuContainer = navBox.querySelector('.menu-list');
|
|
97
|
+
if (menuContainer) {
|
|
98
|
+
this.menuActualWidth = menuContainer.scrollWidth;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// 预留箭头按钮空间
|
|
103
|
+
const arrowSpace = 80;
|
|
104
|
+
const effectiveWidth = this.availableWidth - arrowSpace;
|
|
105
|
+
|
|
106
|
+
// 判断是否需要显示箭头
|
|
107
|
+
this.shouldShowArrows = this.menuActualWidth > effectiveWidth;
|
|
108
|
+
|
|
109
|
+
if (this.shouldShowArrows) {
|
|
110
|
+
this.updateArrowStates();
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// 触发宽度变化事件
|
|
114
|
+
this.$emit('width-change', {
|
|
115
|
+
available: this.availableWidth,
|
|
116
|
+
actual: this.menuActualWidth,
|
|
117
|
+
needArrows: this.shouldShowArrows
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
});
|
|
121
|
+
},
|
|
122
|
+
// 更新箭头状态
|
|
123
|
+
updateArrowStates() {
|
|
124
|
+
if (!this.shouldShowArrows) {
|
|
125
|
+
this.canMoveLeft = false;
|
|
126
|
+
this.canMoveRight = false;
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// 计算最大可移动位置
|
|
131
|
+
const maxPointer = Math.max(0, this.topList.length - this.topNum);
|
|
132
|
+
|
|
133
|
+
this.canMoveLeft = this.pointer > 0;
|
|
134
|
+
this.canMoveRight = this.pointer < maxPointer;
|
|
51
135
|
},
|
|
52
136
|
moveMenu: function (direction) {
|
|
137
|
+
if (!this.shouldShowArrows) return;
|
|
138
|
+
|
|
139
|
+
const maxPointer = Math.max(0, this.topList.length - this.topNum);
|
|
140
|
+
|
|
53
141
|
if (direction === "right") {
|
|
54
|
-
if (this.pointer
|
|
55
|
-
|
|
142
|
+
if (this.pointer < maxPointer) {
|
|
143
|
+
this.pointer++;
|
|
56
144
|
}
|
|
57
|
-
this.pointer++;
|
|
58
145
|
} else {
|
|
59
|
-
if (this.pointer
|
|
60
|
-
|
|
146
|
+
if (this.pointer > 0) {
|
|
147
|
+
this.pointer--;
|
|
61
148
|
}
|
|
62
|
-
this.pointer--;
|
|
63
149
|
}
|
|
150
|
+
|
|
151
|
+
this.updateArrowStates();
|
|
152
|
+
|
|
64
153
|
this.flag = false;
|
|
65
154
|
let self = this;
|
|
66
155
|
setTimeout(() => {
|
|
67
156
|
self.flag = true;
|
|
68
157
|
}, 0);
|
|
69
158
|
},
|
|
159
|
+
// 监听容器大小变化
|
|
160
|
+
observeResize() {
|
|
161
|
+
if (window.ResizeObserver) {
|
|
162
|
+
this.resizeObserver = new ResizeObserver(() => {
|
|
163
|
+
this.checkWidthAndArrows();
|
|
164
|
+
});
|
|
70
165
|
|
|
166
|
+
if (this.$refs.slideWrapper) {
|
|
167
|
+
this.resizeObserver.observe(this.$refs.slideWrapper);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
},
|
|
71
171
|
},
|
|
172
|
+
watch: {
|
|
173
|
+
availableWidth(newVal) {
|
|
174
|
+
this.checkWidthAndArrows();
|
|
175
|
+
},
|
|
176
|
+
pointer() {
|
|
177
|
+
this.updateArrowStates();
|
|
178
|
+
}
|
|
179
|
+
},
|
|
180
|
+
mounted() {
|
|
181
|
+
this.$nextTick(() => {
|
|
182
|
+
this.checkWidthAndArrows();
|
|
183
|
+
this.observeResize();
|
|
184
|
+
});
|
|
185
|
+
},
|
|
186
|
+
beforeDestroy() {
|
|
187
|
+
if (this.resizeObserver) {
|
|
188
|
+
this.resizeObserver.disconnect();
|
|
189
|
+
}
|
|
190
|
+
}
|
|
72
191
|
}
|
|
73
192
|
</script>
|
|
74
193
|
|
|
75
194
|
<style scoped lang="less">
|
|
195
|
+
.pro-layout-nav-slide-wrapper {
|
|
196
|
+
display: flex;
|
|
197
|
+
align-items: center;
|
|
198
|
+
height: 100%;
|
|
199
|
+
width: 100%;
|
|
200
|
+
|
|
201
|
+
.nav-box-slide{
|
|
202
|
+
overflow: hidden;
|
|
203
|
+
flex: 1;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
.tools-box-slide{
|
|
207
|
+
flex-shrink: 0;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
76
210
|
|
|
77
211
|
.more-menu {
|
|
78
|
-
//color: #d9eeec;
|
|
79
212
|
font-size: 22px;
|
|
80
213
|
cursor: pointer;
|
|
81
|
-
|
|
214
|
+
transition: opacity 0.3s ease;
|
|
82
215
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
}
|
|
86
|
-
.tools-box-slide{
|
|
87
|
-
float: right;
|
|
216
|
+
&:hover {
|
|
217
|
+
opacity: 0.8 !important;
|
|
218
|
+
}
|
|
88
219
|
}
|
|
89
220
|
</style>
|
|
@@ -1,55 +1,55 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div class="pro-layout-nav-wrapper">
|
|
3
3
|
<Menu
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
4
|
+
ref="topNav"
|
|
5
|
+
mode="horizontal"
|
|
6
|
+
theme="dark"
|
|
7
|
+
:active-name="activeName"
|
|
8
|
+
@on-select="selectApp"
|
|
9
9
|
>
|
|
10
10
|
<template v-for="item in topMenList">
|
|
11
11
|
<MenuItem v-if="!item.children" :key="item.appId" :name="item.appId">
|
|
12
12
|
<Icon
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
v-bind="getIcon(item)"
|
|
14
|
+
:size="20"
|
|
15
|
+
v-show="systemInfo.navLogo === '1'"
|
|
16
16
|
></Icon
|
|
17
17
|
>{{ item.name }}
|
|
18
18
|
<div class="line"></div>
|
|
19
19
|
</MenuItem>
|
|
20
20
|
<Submenu
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
21
|
+
class="ibp-nav-sub-menu"
|
|
22
|
+
v-else
|
|
23
|
+
:name="item.name"
|
|
24
|
+
:key="item.name"
|
|
25
25
|
>
|
|
26
26
|
<template slot="title">
|
|
27
27
|
{{ item.name }}
|
|
28
28
|
</template>
|
|
29
29
|
<MenuItem
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
30
|
+
v-for="itemL2 in item.children"
|
|
31
|
+
:key="itemL2.appId"
|
|
32
|
+
:name="itemL2.appId"
|
|
33
|
+
><Icon
|
|
34
34
|
:type="itemL2.icon"
|
|
35
35
|
:size="20"
|
|
36
36
|
v-show="systemInfo.navLogo === '1'"
|
|
37
|
-
|
|
38
|
-
|
|
37
|
+
></Icon
|
|
38
|
+
>{{ itemL2.name }}</MenuItem
|
|
39
39
|
>
|
|
40
40
|
</Submenu>
|
|
41
41
|
</template>
|
|
42
42
|
<Submenu name="other" v-if="otherList.length > 0">
|
|
43
43
|
<template slot="title"> ... </template>
|
|
44
44
|
<MenuItem
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
45
|
+
:name="item.appId"
|
|
46
|
+
v-for="item in otherList"
|
|
47
|
+
:key="item.appId"
|
|
48
48
|
>
|
|
49
49
|
<Icon
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
50
|
+
v-bind="getIcon(item)"
|
|
51
|
+
:size="20"
|
|
52
|
+
v-show="systemInfo.navLogo === '1'"
|
|
53
53
|
></Icon
|
|
54
54
|
>{{ item.name }}
|
|
55
55
|
</MenuItem>
|
|
@@ -66,7 +66,12 @@ import _ from "lodash";
|
|
|
66
66
|
|
|
67
67
|
export default {
|
|
68
68
|
name: "pro-layout-nav",
|
|
69
|
-
props: {
|
|
69
|
+
props: {
|
|
70
|
+
availableWidth: {
|
|
71
|
+
type: Number,
|
|
72
|
+
default: 800
|
|
73
|
+
}
|
|
74
|
+
},
|
|
70
75
|
data() {
|
|
71
76
|
return {
|
|
72
77
|
systemInfo: {},
|
|
@@ -79,6 +84,11 @@ export default {
|
|
|
79
84
|
lastTopMenuNum: -1,
|
|
80
85
|
acceptAppId: "",
|
|
81
86
|
originMenuList: [],
|
|
87
|
+
// 新增响应式相关状态
|
|
88
|
+
resizeObserver: null,
|
|
89
|
+
menuActualWidth: 0,
|
|
90
|
+
shouldShowMore: false,
|
|
91
|
+
autoCalculateWidth: true,
|
|
82
92
|
};
|
|
83
93
|
},
|
|
84
94
|
methods: {
|
|
@@ -95,12 +105,19 @@ export default {
|
|
|
95
105
|
Bus.$on("menu-list", (data) => {
|
|
96
106
|
this.initMenu(data);
|
|
97
107
|
});
|
|
108
|
+
// 初始化响应式监听
|
|
109
|
+
this.initResizeObserver();
|
|
98
110
|
},
|
|
99
111
|
destroyListener() {
|
|
100
112
|
Bus.$off("system-info");
|
|
101
113
|
Bus.$off("nav-list");
|
|
102
114
|
Bus.$off("menu-list");
|
|
103
115
|
Bus.$off("change-app");
|
|
116
|
+
// 清理 ResizeObserver
|
|
117
|
+
if (this.resizeObserver) {
|
|
118
|
+
this.resizeObserver.disconnect();
|
|
119
|
+
this.resizeObserver = null;
|
|
120
|
+
}
|
|
104
121
|
},
|
|
105
122
|
initSystemInfo(data) {
|
|
106
123
|
if (data) {
|
|
@@ -115,9 +132,9 @@ export default {
|
|
|
115
132
|
},
|
|
116
133
|
initNav(data) {
|
|
117
134
|
if (
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
135
|
+
_.some(data, (app) => app.children?.length) || // 分组以后会死循环调用,中断一下
|
|
136
|
+
(arraysEqual(this.originNavList, data) &&
|
|
137
|
+
this.topMenuNum === this.lastTopMenuNum)
|
|
121
138
|
) {
|
|
122
139
|
return;
|
|
123
140
|
}
|
|
@@ -137,25 +154,25 @@ export default {
|
|
|
137
154
|
// 如果组织了二级菜单展现,则对菜单进行分组
|
|
138
155
|
if (!_.isEmpty(parentNameEnum)) {
|
|
139
156
|
let rlt = _.reduce(
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
157
|
+
dataClone,
|
|
158
|
+
(acc, cur) => {
|
|
159
|
+
let parentName = parentNameEnum[cur.appId];
|
|
160
|
+
if (parentName) {
|
|
161
|
+
let curApp = _.find(acc, { name: parentName });
|
|
162
|
+
if (curApp) {
|
|
163
|
+
curApp.children.push(cur);
|
|
164
|
+
} else {
|
|
165
|
+
acc.push({
|
|
166
|
+
name: parentName,
|
|
167
|
+
children: [cur],
|
|
168
|
+
});
|
|
169
|
+
}
|
|
147
170
|
} else {
|
|
148
|
-
acc.push(
|
|
149
|
-
name: parentName,
|
|
150
|
-
children: [cur],
|
|
151
|
-
});
|
|
171
|
+
acc.push(cur);
|
|
152
172
|
}
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
return acc;
|
|
157
|
-
},
|
|
158
|
-
[]
|
|
173
|
+
return acc;
|
|
174
|
+
},
|
|
175
|
+
[]
|
|
159
176
|
);
|
|
160
177
|
this.navList = rlt;
|
|
161
178
|
} else {
|
|
@@ -208,39 +225,166 @@ export default {
|
|
|
208
225
|
},
|
|
209
226
|
// 顶部导航的导航配置多的话,分辨率低的场景下,需要计算一下剩余空间能展示多少,动态计算topMenuNum
|
|
210
227
|
calcTopMenus() {
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
228
|
+
// this.$nextTick(() => {
|
|
229
|
+
if (!this.autoCalculateWidth) {
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
// 计算可用宽度
|
|
234
|
+
// this.calculateAvailableWidth();
|
|
235
|
+
|
|
236
|
+
// 计算实际菜单宽度
|
|
237
|
+
this.calculateMenuActualWidth();
|
|
238
|
+
|
|
239
|
+
// 预留"更多"按钮空间
|
|
240
|
+
const moreButtonSpace = 80;
|
|
241
|
+
const effectiveWidth = this.availableWidth - moreButtonSpace;
|
|
242
|
+
|
|
243
|
+
// 判断是否需要显示"更多"按钮
|
|
244
|
+
this.shouldShowMore = this.menuActualWidth > effectiveWidth;
|
|
245
|
+
|
|
246
|
+
// 根据可用宽度计算能显示的菜单数量
|
|
247
|
+
this.calculateTopMenuNum();
|
|
248
|
+
|
|
249
|
+
// 更新显示列表
|
|
250
|
+
this.updateMenuLists();
|
|
251
|
+
|
|
252
|
+
// 触发宽度变化事件
|
|
253
|
+
this.$emit('width-change', {
|
|
254
|
+
available: this.availableWidth,
|
|
255
|
+
actual: this.menuActualWidth,
|
|
256
|
+
needMore: this.shouldShowMore
|
|
257
|
+
});
|
|
258
|
+
// });
|
|
259
|
+
},
|
|
260
|
+
|
|
261
|
+
// 计算可用宽度
|
|
262
|
+
// calculateAvailableWidth() {
|
|
263
|
+
// const appElement = document.getElementById("app");
|
|
264
|
+
// if (!appElement) return;
|
|
265
|
+
//
|
|
266
|
+
// const docWidth = appElement.clientWidth;
|
|
267
|
+
// const triggerBoxWidth = this.getElementWidth("trigger-box");
|
|
268
|
+
// const logoBoxWidth = this.getElementWidth("logo-box");
|
|
269
|
+
// const toolsBoxWidth = this.getElementWidth("tools-box");
|
|
270
|
+
// const othersWidth = 80; // 其他按钮的宽度
|
|
271
|
+
//
|
|
272
|
+
// this.availableWidth = docWidth - triggerBoxWidth - logoBoxWidth - toolsBoxWidth - othersWidth;
|
|
273
|
+
// },
|
|
274
|
+
|
|
275
|
+
// 计算实际菜单宽度
|
|
276
|
+
calculateMenuActualWidth() {
|
|
277
|
+
const navWrapper = this.$el;
|
|
278
|
+
if (!navWrapper) return;
|
|
279
|
+
|
|
280
|
+
const menuContainer = navWrapper.querySelector('.ivu-menu');
|
|
281
|
+
if (menuContainer) {
|
|
282
|
+
// 计算所有菜单项的实际宽度
|
|
283
|
+
let totalWidth = 0;
|
|
284
|
+
const menuItems = menuContainer.querySelectorAll('li');
|
|
285
|
+
menuItems.forEach(item => {
|
|
286
|
+
totalWidth += item.offsetWidth;
|
|
287
|
+
});
|
|
288
|
+
this.menuActualWidth = totalWidth;
|
|
289
|
+
}
|
|
290
|
+
},
|
|
291
|
+
|
|
292
|
+
// 计算顶部菜单数量
|
|
293
|
+
calculateTopMenuNum() {
|
|
294
|
+
if (!this.navList || this.navList.length === 0) return;
|
|
295
|
+
|
|
296
|
+
let topMenuNum = 0;
|
|
297
|
+
let sumWidth = 0;
|
|
298
|
+
|
|
299
|
+
// 模拟计算每个菜单项的宽度
|
|
300
|
+
this.navList.forEach((item, index) => {
|
|
301
|
+
// 估算每个菜单项的宽度(包括图标、文字、边距等)
|
|
302
|
+
const estimatedWidth = this.estimateMenuItemWidth(item);
|
|
303
|
+
|
|
304
|
+
if (sumWidth + estimatedWidth < this.availableWidth) {
|
|
305
|
+
topMenuNum++;
|
|
306
|
+
sumWidth += estimatedWidth;
|
|
229
307
|
}
|
|
230
|
-
})
|
|
308
|
+
});
|
|
309
|
+
|
|
231
310
|
// 如果计算值为0,就不要触发事件,如果系统配置要展示少量,也不要触发事件
|
|
232
|
-
if (topMenuNum && this.systemInfo?.topMenu > topMenuNum) {
|
|
311
|
+
if (topMenuNum && (!this.systemInfo?.topMenu || this.systemInfo?.topMenu > topMenuNum)) {
|
|
233
312
|
this.topMenuNum = topMenuNum;
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
313
|
+
}else{
|
|
314
|
+
this.topMenuNum = this.systemInfo.topMenu;
|
|
315
|
+
}
|
|
316
|
+
},
|
|
317
|
+
|
|
318
|
+
// 估算菜单项宽度
|
|
319
|
+
estimateMenuItemWidth(item) {
|
|
320
|
+
// 基础宽度:内边距 + 边框
|
|
321
|
+
let baseWidth = 40;
|
|
322
|
+
|
|
323
|
+
// 图标宽度
|
|
324
|
+
if (item.icon && this.systemInfo.navLogo === '1') {
|
|
325
|
+
baseWidth += 26;
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
// 文字宽度估算(每个字符约14px)
|
|
329
|
+
// const fontSize = parseInt(window.getComputedStyle(document.querySelector('#customVars')).getPropertyValue('--font-size-base').replace("px",""))
|
|
330
|
+
var customVars=window.getComputedStyle(document.querySelector('#customVars'));
|
|
331
|
+
var fontSizeVar=customVars.getPropertyValue('--font-size-base');
|
|
332
|
+
var fontSize=parseInt(fontSizeVar.replace("px",""));
|
|
333
|
+
|
|
334
|
+
const textWidth = (item.name || '').length * fontSize;
|
|
335
|
+
|
|
336
|
+
return baseWidth + textWidth;
|
|
337
|
+
},
|
|
338
|
+
|
|
339
|
+
// 更新菜单列表
|
|
340
|
+
updateMenuLists() {
|
|
341
|
+
if (this.navList.length > this.topMenuNum) {
|
|
342
|
+
const navList = deepCopy(this.navList);
|
|
343
|
+
this.topMenList = navList.splice(0, this.topMenuNum);
|
|
344
|
+
this.otherList = navList;
|
|
345
|
+
} else {
|
|
346
|
+
this.topMenList = this.navList;
|
|
347
|
+
this.otherList = [];
|
|
348
|
+
}
|
|
349
|
+
console.log("topMenList",this.topMenList.length)
|
|
350
|
+
console.log("otherList",this.otherList.length)
|
|
351
|
+
},
|
|
352
|
+
|
|
353
|
+
// 获取元素宽度的辅助方法
|
|
354
|
+
getElementWidth(className) {
|
|
355
|
+
const element = document.getElementsByClassName(className)[0];
|
|
356
|
+
return element ? element.clientWidth : 0;
|
|
357
|
+
},
|
|
358
|
+
|
|
359
|
+
// 初始化 ResizeObserver
|
|
360
|
+
initResizeObserver() {
|
|
361
|
+
if (window.ResizeObserver) {
|
|
362
|
+
this.resizeObserver = new ResizeObserver(() => {
|
|
363
|
+
this.calcTopMenus();
|
|
364
|
+
});
|
|
365
|
+
}
|
|
366
|
+
},
|
|
367
|
+
|
|
368
|
+
// 开始监听容器大小变化
|
|
369
|
+
startResizeObserving() {
|
|
370
|
+
if (this.resizeObserver && this.$el) {
|
|
371
|
+
this.resizeObserver.observe(this.$el);
|
|
372
|
+
|
|
373
|
+
// 同时监听父容器
|
|
374
|
+
const appElement = document.getElementById("app");
|
|
375
|
+
if (appElement) {
|
|
376
|
+
this.resizeObserver.observe(appElement);
|
|
241
377
|
}
|
|
242
378
|
}
|
|
243
379
|
},
|
|
380
|
+
|
|
381
|
+
// 停止监听容器大小变化
|
|
382
|
+
stopResizeObserving() {
|
|
383
|
+
if (this.resizeObserver) {
|
|
384
|
+
this.resizeObserver.disconnect();
|
|
385
|
+
}
|
|
386
|
+
},
|
|
387
|
+
|
|
244
388
|
//获取icon图标
|
|
245
389
|
getIcon(item){
|
|
246
390
|
const icon = item.icon
|
|
@@ -261,12 +405,31 @@ export default {
|
|
|
261
405
|
this.$refs.topNav.updateActiveName();
|
|
262
406
|
});
|
|
263
407
|
},
|
|
408
|
+
// 监听可用宽度变化
|
|
409
|
+
availableWidth(newVal) {
|
|
410
|
+
console.log("availableWidth",newVal)
|
|
411
|
+
this.calcTopMenus();
|
|
412
|
+
},
|
|
413
|
+
// 监听系统信息变化
|
|
414
|
+
systemInfo: {
|
|
415
|
+
handler() {
|
|
416
|
+
this.calcTopMenus();
|
|
417
|
+
},
|
|
418
|
+
deep: true
|
|
419
|
+
}
|
|
264
420
|
},
|
|
265
421
|
created() {
|
|
266
422
|
this.initListener();
|
|
267
423
|
},
|
|
424
|
+
mounted() {
|
|
425
|
+
this.$nextTick(() => {
|
|
426
|
+
this.calcTopMenus();
|
|
427
|
+
this.startResizeObserving();
|
|
428
|
+
});
|
|
429
|
+
},
|
|
268
430
|
beforeDestroy() {
|
|
269
431
|
this.destroyListener();
|
|
432
|
+
this.stopResizeObserving();
|
|
270
433
|
},
|
|
271
434
|
};
|
|
272
435
|
</script>
|
|
@@ -53,7 +53,6 @@ export default {
|
|
|
53
53
|
},
|
|
54
54
|
methods: {
|
|
55
55
|
initListener() {
|
|
56
|
-
debugger
|
|
57
56
|
Bus.$on('system-info',(data) => {
|
|
58
57
|
this.initSystemInfo(data);
|
|
59
58
|
})
|
|
@@ -62,7 +61,6 @@ export default {
|
|
|
62
61
|
Bus.$off('system-info')
|
|
63
62
|
},
|
|
64
63
|
initSystemInfo(data){
|
|
65
|
-
debugger
|
|
66
64
|
if (data && data.rightTopOptButtonList) {
|
|
67
65
|
this.rightTopOptButtonList = deepCopy(data.rightTopOptButtonList)
|
|
68
66
|
}
|