@lambo-design/pro-layout 1.0.0-beta.40 → 1.0.0-beta.401

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 (37) hide show
  1. package/package.json +11 -4
  2. package/src/components/pro-layout-header/index.vue +203 -0
  3. package/src/components/pro-layout-header/pro-layout-logo/index.vue +150 -0
  4. package/src/components/pro-layout-header/pro-layout-nav/components/pro-layout-nav-slide-menu.vue +327 -0
  5. package/src/components/pro-layout-header/pro-layout-nav/index-slide.vue +220 -0
  6. package/src/components/pro-layout-header/pro-layout-nav/index.vue +494 -0
  7. package/src/components/pro-layout-header/pro-layout-tools/components/pro-layout-tools-quick-collect.vue +79 -0
  8. package/src/components/pro-layout-header/pro-layout-tools/components/pro-layout-tools-quick-document.vue +20 -0
  9. package/src/components/pro-layout-header/pro-layout-tools/components/pro-layout-tools-quick-fullscreen.vue +142 -0
  10. package/src/components/pro-layout-header/pro-layout-tools/components/pro-layout-tools-quick-icons.vue +84 -0
  11. package/src/components/pro-layout-header/pro-layout-tools/components/pro-layout-tools-quick-intl.vue +91 -0
  12. package/src/components/pro-layout-header/pro-layout-tools/components/pro-layout-tools-quick-notice.vue +133 -0
  13. package/src/components/pro-layout-header/pro-layout-tools/components/pro-layout-tools-quick-search.vue +300 -0
  14. package/src/components/pro-layout-header/pro-layout-tools/components/pro-layout-tools-quick-todo.vue +142 -0
  15. package/src/components/pro-layout-header/pro-layout-tools/components/pro-layout-tools-user.vue +64 -0
  16. package/src/components/pro-layout-header/pro-layout-tools/index.vue +28 -0
  17. package/src/components/{pro-layout-trigger.vue → pro-layout-header/pro-layout-trigger/index.vue} +26 -3
  18. package/src/components/{pro-layout-sider-collapsed-menu.vue → pro-layout-sider/components/pro-layout-sider-collapsed-menu.vue} +30 -11
  19. package/src/components/{pro-layout-sider-icon.vue → pro-layout-sider/components/pro-layout-sider-icon.vue} +2 -2
  20. package/src/components/pro-layout-sider/components/pro-layout-sider-menu-item.vue +137 -0
  21. package/src/components/pro-layout-sider/components/pro-layout-sider-other-menu.vue +140 -0
  22. package/src/components/pro-layout-sider/components/pro-layout-sider-search.vue +345 -0
  23. package/src/components/pro-layout-sider/index.vue +450 -0
  24. package/src/components/{pro-layout-tabs.vue → pro-layout-tabs/index.vue} +77 -8
  25. package/src/index.vue +194 -37
  26. package/src/styles/color.less +260 -0
  27. package/src/styles/images/xiaoxitongzhi.png +0 -0
  28. package/src/styles/other-menu.less +111 -0
  29. package/src/utils/menuItem.js +10 -0
  30. package/src/utils/sider.js +16 -1
  31. package/src/components/pro-layout-header.vue +0 -52
  32. package/src/components/pro-layout-logo.vue +0 -79
  33. package/src/components/pro-layout-nav.vue +0 -150
  34. package/src/components/pro-layout-sider-menu-item.vue +0 -37
  35. package/src/components/pro-layout-sider.vue +0 -240
  36. package/src/components/pro-layout-tools-user.vue +0 -84
  37. package/src/components/pro-layout-tools.vue +0 -21
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lambo-design/pro-layout",
3
- "version": "1.0.0-beta.40",
3
+ "version": "1.0.0-beta.401",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "author": "lambo",
@@ -10,8 +10,15 @@
10
10
  "registry": "https://registry.npmjs.org/"
11
11
  },
12
12
  "devDependencies": {
13
- "@lambo-design/core": "^4.7.1-beta.54",
14
- "@lambo-design/shared": "^1.0.0-beta.39"
13
+ "@lambo-design/core": "^4.7.1-beta.167",
14
+ "@lambo-design/shared": "^1.0.0-beta.286"
15
15
  },
16
- "scripts": {}
16
+ "scripts": {
17
+ "release-pro-layout": "pnpm release-beta && git push --follow-tags && pnpm re-publish",
18
+ "release-major": "standard-version --release-as major",
19
+ "release-minor": "standard-version --release-as minor",
20
+ "release-patch": "standard-version --release-as patch",
21
+ "release-beta": "standard-version --prerelease beta",
22
+ "re-publish": "pnpm publish --access public --no-git-checks"
23
+ }
17
24
  }
@@ -0,0 +1,203 @@
1
+ <template>
2
+ <div class="pro-layout-header-wrapper">
3
+ <div class="trigger-box" :style="menuScalingStyle">
4
+ <slot name="pro-layout-trigger">
5
+ <LamboProTrigger v-if="systemInfo.menuScaling === '1'" :menu-scaling-status="systemInfo.menuScalingStatus" :hide-menu-logo="hideMenuLogo"></LamboProTrigger>
6
+ </slot>
7
+ </div>
8
+ <div class="logo-box">
9
+ <slot name="pro-layout-logo">
10
+ <LamboProLogo></LamboProLogo>
11
+ </slot>
12
+ </div>
13
+ <div class="nav-box" v-show="!systemInfo || !systemInfo.navType || systemInfo.navType == 'dropdown'">
14
+ <slot name="pro-layout-nav">
15
+ <LamboProNav
16
+ :available-width="availableWidth"
17
+ ></LamboProNav>
18
+ </slot>
19
+ </div>
20
+ <div class="tools-box">
21
+ <LamboProTools>
22
+ <template slot = "pro-layout-icons">
23
+ <slot name="pro-layout-icons"></slot>
24
+ </template>
25
+ <template slot = "pro-layout-user">
26
+ <slot name="pro-layout-user"></slot>
27
+ </template>
28
+ </LamboProTools>
29
+ </div>
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>
35
+ </div>
36
+ </div>
37
+ </template>
38
+
39
+ <script>
40
+ import LamboProTrigger from './pro-layout-trigger'
41
+ import LamboProLogo from './pro-layout-logo'
42
+ import LamboProNav from './pro-layout-nav'
43
+ import LamboProNavSilde from './pro-layout-nav/index-slide'
44
+ import LamboProTools from './pro-layout-tools'
45
+ import Bus from "@lambo-design/shared/utils/bus";
46
+
47
+ export default {
48
+ name: "pro-layout-header",
49
+ props:{
50
+ acceptAppId: {
51
+ type: String,
52
+ default:''
53
+ },
54
+ hideMenuLogo: {
55
+ type: Boolean,
56
+ default:true
57
+ }
58
+ },
59
+ data(){
60
+ return {
61
+ systemInfo: {},
62
+ availableWidth: 0,
63
+ resizeTimer: null,
64
+ }
65
+ },
66
+ components: {
67
+ LamboProTrigger,
68
+ LamboProLogo,
69
+ LamboProNav,
70
+ LamboProNavSilde,
71
+ LamboProTools
72
+ },
73
+ computed:{
74
+ menuScalingStyle(){
75
+ return this.systemInfo.menuScaling === '1' ? '' : {marginLeft:'25px'}
76
+ }
77
+ },
78
+ methods:{
79
+ initListener(){
80
+ Bus.$on('system-info',(data)=>{
81
+ this.initSystem(data)
82
+ });
83
+
84
+ // 监听窗口大小变化
85
+ window.addEventListener('resize', this.handleResize);
86
+ },
87
+ destroyListener(){
88
+ Bus.$off('system-info');
89
+ window.removeEventListener('resize', this.handleResize);
90
+ },
91
+ initSystem(data){
92
+ if (data) {
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")?.getBoundingClientRect().width || window.innerWidth;
109
+ // 获取各个组件的宽度
110
+ const triggerBoxWidth = this.getTriggerBoxWidth();
111
+ const logoBoxWidth = this.getLogoBoxWidth();
112
+ const toolsBoxWidth = this.getToolsBoxWidth();
113
+
114
+ let reservedWidth = 1;
115
+ // 预留一些空间给箭头按钮和边距
116
+ if(this.systemInfo.navType == 'slide'){
117
+ reservedWidth = 150;
118
+ }
119
+
120
+ // 计算可用宽度
121
+ this.availableWidth = docWidth - triggerBoxWidth - logoBoxWidth - toolsBoxWidth - reservedWidth;
122
+
123
+ // 确保最小宽度
124
+ this.availableWidth = Math.max(this.availableWidth, 200);
125
+
126
+ } catch (error) {
127
+ console.warn('Error calculating available width:', error);
128
+ this.availableWidth = 800; // 默认值
129
+ }
130
+ },
131
+
132
+ // 获取trigger组件宽度
133
+ getTriggerBoxWidth() {
134
+ const triggerBox = document.querySelector('.trigger-box');
135
+ return triggerBox ? triggerBox.getBoundingClientRect().width : 0;
136
+ },
137
+
138
+ // 获取logo组件宽度
139
+ getLogoBoxWidth() {
140
+ const logoBox = document.querySelector('.logo-box');
141
+ return logoBox ? logoBox.getBoundingClientRect().width : 0;
142
+ },
143
+
144
+ // 获取tools组件宽度
145
+ getToolsBoxWidth() {
146
+ const toolsBox = document.querySelector('.tools-box');
147
+ return toolsBox ? toolsBox.getBoundingClientRect().width : 0;
148
+ },
149
+
150
+ // 处理窗口大小变化
151
+ handleResize() {
152
+ // 防抖处理
153
+ clearTimeout(this.resizeTimer);
154
+ this.resizeTimer = setTimeout(() => {
155
+ this.calculateAvailableWidth();
156
+ }, 150);
157
+ },
158
+
159
+ // 处理slide组件宽度变化
160
+ handleSlideWidthChange(data) {
161
+ // console.log('Slide width change:', data);
162
+ // 可以在这里处理slide组件宽度变化的逻辑
163
+ }
164
+ },
165
+ mounted() {
166
+ // 组件挂载后计算一次宽度
167
+ this.$nextTick(() => {
168
+ this.calculateAvailableWidth();
169
+ });
170
+ },
171
+ created(){
172
+ this.initListener();
173
+ },
174
+ beforeDestroy(){
175
+ this.destroyListener();
176
+ }
177
+ }
178
+ </script>
179
+
180
+ <style scoped lang="less">
181
+ .pro-layout-header-wrapper{
182
+ width: auto;
183
+ height: 64px;
184
+ .trigger-box{
185
+ float: left;
186
+ height: inherit;
187
+ }
188
+ .logo-box{
189
+ float: left;
190
+ }
191
+ .nav-box{
192
+ float: left;
193
+ }
194
+ .nav-slide-container{
195
+ float: left;
196
+ flex: 1;
197
+ overflow: hidden;
198
+ }
199
+ .tools-box{
200
+ float: right;
201
+ }
202
+ }
203
+ </style>
@@ -0,0 +1,150 @@
1
+ <template>
2
+ <div @click="handleClick">
3
+ <Row class="pro-layout-logo-wrapper" :style="systemInfo.layoutSize === 'default' ? {height:'64px'} :{height:'50px'} " type="flex" align="middle">
4
+ <Col>
5
+ <div class="logo" v-if="systemInfo.systemLogo" :style="logoStyle"></div>
6
+ </Col>
7
+ <Col>
8
+ <div class="divider" v-if="systemInfo.systemLogo"></div>
9
+ </Col>
10
+ <Col>
11
+ <div class="system-name" :style="nameStyle">{{systemName}}</div>
12
+ </Col>
13
+ </Row>
14
+ </div>
15
+ </template>
16
+
17
+ <script>
18
+ import Bus from '@lambo-design/shared/utils/bus'
19
+ import Locale from '@lambo-design/core/src/mixins/locale';
20
+
21
+ export default {
22
+ name: "pro-layout-logo",
23
+ mixins: [Locale],
24
+ props:{
25
+ routeName:String,
26
+ default:''
27
+ },
28
+ data(){
29
+ return {
30
+ systemInfo: {},
31
+ systemName: this.t('pro-layout.common.systemName'),
32
+ isHovered: false,
33
+ src:''
34
+ }
35
+ },
36
+ computed:{
37
+ logoStyle() {
38
+ let style = '';
39
+ if (this.systemInfo && this.systemInfo.systemLogo) {
40
+ style += `background: url("${this.systemInfo.systemLogo}") no-repeat; background-size: 100% 100%;background-position:center;`;
41
+ // 如果 systemInfo.logoWidth 存在且不为空,则添加到样式
42
+ if (this.systemInfo.logoWidth && this.systemInfo.logoWidth !== '') {
43
+ style += `width: ${this.systemInfo.logoWidth}px;`;
44
+ }
45
+ // 如果 systemInfo.logoTop 存在且不为空,则添加到样式
46
+ // if (this.systemInfo.logoTop && this.systemInfo.logoTop !== '') {
47
+ // style += `margin-top: ${this.systemInfo.logoTop}px;`;
48
+ // }
49
+ style += `text-align-last: justify;`
50
+ }
51
+ return style;
52
+ },
53
+
54
+
55
+ nameStyle() {
56
+ let style = '';
57
+ if (this.systemInfo && this.systemInfo.nameSize) {
58
+ const lines = this.systemInfo.nameSize; // 行数
59
+ const maxHeight = lineHeight * lines; // 计算最大高度
60
+
61
+ // 根据nameSize设置margin-top
62
+ // if (lines == 1) {
63
+ // style += `margin-top: 12px;`;
64
+ // } else if (lines == 2) {
65
+ // style += `margin-top: 5px; `;
66
+ // }
67
+
68
+ // 动态计算字体大小
69
+ const fontSize = Math.max(20 - (lines - 1) * 4, 15); // 字体大小递减
70
+ const lineHeight = fontSize + 5; // 固定行高
71
+ const width = (this.systemName.length / lines) * fontSize + 20;
72
+
73
+ // 组装样式字符串
74
+ style += `line-height: ${lineHeight}px;`;
75
+ style += `font-size: ${fontSize}px;`;
76
+ style += `max-height: ${maxHeight}px;`; // 设置最大高度限制行数
77
+ if (this.$cookies.get("lambo_lang_code") && this.$cookies.get("lambo_lang_code") == 'zh') {
78
+ style += `width: ${width}px;`; // 设置宽度
79
+ }
80
+ style += `overflow: hidden;`; // 超出部分隐藏
81
+ style += `word-wrap: break-word;`; // 允许单词内换行
82
+ style += `white-space: normal;`; // 默认的换行方式
83
+ style += `text-align-last: justify;`;
84
+ style += `text-align: justify;`;
85
+ }
86
+ return style;
87
+ }
88
+
89
+ },
90
+ methods: {
91
+ handleClick(){
92
+ Bus.$emit('click-logo')
93
+ },
94
+ initListener(){
95
+ Bus.$on('system-info',(data)=>{
96
+ this.initSystem(data)
97
+ });
98
+ },
99
+ destroyListener(){
100
+ Bus.$off('system-info')
101
+ },
102
+ initSystem(data){
103
+ if (data) {
104
+ this.systemInfo = data;
105
+ if (data.systemName) {
106
+ this.systemName = data.systemName;
107
+ }
108
+ }
109
+ },
110
+
111
+ },
112
+ created(){
113
+ this.initListener();
114
+ },
115
+ beforeDestroy(){
116
+ this.destroyListener();
117
+ }
118
+ }
119
+ </script>
120
+
121
+ <style scoped lang="less">
122
+ @import "@lambo-design/core/src/styles/default";
123
+ .pro-layout-logo-wrapper{
124
+ overflow: hidden;
125
+ cursor:pointer;
126
+ .logo{
127
+ width: 210px;
128
+ height: 40px;
129
+ background: url("../../../styles/images/inspur.png") no-repeat;
130
+ background-size: 100% 100%;
131
+ background-position: center; /* 图片在背景区域内居中显示 */
132
+ //float: left;
133
+ //margin-top: 20px;
134
+ }
135
+ .divider{
136
+ height: 33px;
137
+ width: 2px;
138
+ border-right: 2px dashed fade(@_black,30%);
139
+ //float: left;
140
+ margin: 0 12px 0 14px;
141
+ }
142
+ .system-name{
143
+ //float: left;
144
+ font-weight: bold;
145
+ font-size: 20px;
146
+ margin-right: 15px;
147
+
148
+ }
149
+ }
150
+ </style>
@@ -0,0 +1,327 @@
1
+ <template>
2
+ <div class="menu-list" ref="menuList">
3
+ <ul class="top-menu" :style="layoutSize === 'default' ? {height: '64px'} : {height: '50px'}" ref="topNav">
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>
15
+ </ul>
16
+ </div>
17
+ </template>
18
+
19
+ <script>
20
+ import Bus from '@lambo-design/shared/utils/bus'
21
+ import { deepCopy } from '@lambo-design/shared/utils/assist'
22
+
23
+ export default {
24
+ props: {
25
+ acceptInt: {
26
+ type: Number,
27
+ default: 0
28
+ },
29
+ topMenListNum: {
30
+ type: Number,
31
+ default: 0
32
+ },
33
+ availableWidth: {
34
+ type: Number,
35
+ default: 800
36
+ }
37
+ },
38
+ data() {
39
+ return {
40
+ systemInfo:{},
41
+ pointer:0,
42
+ arrowFlag: true,
43
+ acceptAppId: '',
44
+ navList: [],
45
+ topMenList: [],
46
+ topTqmMenList:[],
47
+ otherList: [],
48
+ activeName: '',
49
+ topMenuNum: 7,
50
+ displayMenuNum: 7, // 实际显示的菜单数量
51
+ lastTopMenuNum:-1,
52
+ originMenuList: [],
53
+ layoutSize:"default",
54
+ // menuItemWidths: [], // 存储每个菜单项的宽度
55
+ resizeObserver: null,
56
+ }
57
+ },
58
+ methods: {
59
+ initListener() {
60
+ Bus.$on('system-info',(data) => {
61
+ this.initSystemInfo(data);
62
+ })
63
+ Bus.$on('nav-list', (data) => {
64
+ this.initNav(data)
65
+ })
66
+ Bus.$on('change-app', ({ appId, appInfo }) => {
67
+ this.changeApp(appId, appInfo)
68
+ })
69
+ },
70
+ destroyListener() {
71
+ Bus.$off('system-info')
72
+ Bus.$off('nav-list')
73
+ Bus.$off('change-app')
74
+ },
75
+ initSystemInfo(data) {
76
+ if (data) {
77
+ this.systemInfo = data
78
+ this.layoutSize = data.layoutSize ? data.layoutSize : 'default';
79
+ this.topMenuNum = data.topMenu ? data.topMenu : 4;
80
+ this.acceptAppId = data.acceptAppId ? data.acceptAppId : '';
81
+ if (!this.activeName) {
82
+ this.activeName = this.acceptAppId
83
+ }
84
+ this.initNav(this.navList)
85
+ }
86
+ },
87
+ initNav(data) {
88
+ if (data.toString() === this.navList.toString() && this.topMenuNum === this.lastTopMenuNum) {
89
+ return
90
+ }
91
+ this.navList = data
92
+ this.lastTopMenuNum = this.topMenuNum
93
+
94
+ this.topMenList = data
95
+ this.$emit('topMen-list', this.topMenList);
96
+
97
+ // 计算可以显示的菜单数量
98
+ this.calculateDisplayMenuNum();
99
+
100
+ if (this.topMenList.length > 0) {
101
+ let appId = this.topMenList[0].appId
102
+ for (let i = 0; i < this.topMenList.length; i++) {
103
+ if (this.topMenList[i].selected == true) {
104
+ appId = this.topMenList[i].appId
105
+ }
106
+ }
107
+ if (this.activeName) {
108
+ appId = this.activeName
109
+ }
110
+ this.selectApp(appId)
111
+ }
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
+
201
+ selectApp(appId) {
202
+ if (appId) {
203
+ this.activeName = appId
204
+ let res = this.navList.filter(app => app.appId == appId)
205
+ Bus.$emit('change-app', { appId, appInfo: res[0] })
206
+ }
207
+ },
208
+ changeApp(appId, appInfo){
209
+ if (appId) {
210
+ this.activeName = appId
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
+ });
236
+ }
237
+ },
238
+ watch: {
239
+ acceptInt(val){
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();
250
+ }
251
+ },
252
+ mounted() {
253
+ this.calculateDisplayMenuNum();
254
+ this.$nextTick(() => {
255
+ this.observeResize();
256
+ });
257
+ },
258
+ created() {
259
+ this.initListener()
260
+ },
261
+ beforeDestroy() {
262
+ this.destroyListener();
263
+ if (this.resizeObserver) {
264
+ this.resizeObserver.disconnect();
265
+ }
266
+ }
267
+ }
268
+ </script>
269
+
270
+ <style scoped lang="less">
271
+ @import '@lambo-design/core/src/styles/default.less';
272
+ .menu-list {
273
+ height: 100%;
274
+ line-height: 24px;
275
+ cursor: pointer;
276
+ font-size: 16px;
277
+ margin-left: 15px;
278
+ overflow: hidden;
279
+
280
+ .top-menu {
281
+ overflow: hidden;
282
+ white-space: nowrap;
283
+
284
+ .top-menu-item {
285
+ padding-left: 15px;
286
+ padding-right: 15px;
287
+ position: relative;
288
+ height: 100%;
289
+ list-style: none;
290
+ float: left;
291
+ transition: all 0.3s ease;
292
+
293
+ &:hover {
294
+ .menu-item {
295
+ // hover styles
296
+ }
297
+ }
298
+ &.active {
299
+ .menu-item {
300
+ // active styles
301
+ }
302
+ }
303
+ .menu-item {
304
+ display: flex;
305
+ margin-top: 10px;
306
+ text-align: center;
307
+ }
308
+ .menu-icon {
309
+ height: 20px;
310
+ line-height: 20px;
311
+ text-align: center;
312
+ margin-right: 10px;
313
+ margin-top: 3px;
314
+ }
315
+ .menu-txt {
316
+ text-align: center;
317
+ font-size: 14px;
318
+ line-height: 2;
319
+ white-space: nowrap;
320
+ overflow: hidden;
321
+ text-overflow: ellipsis;
322
+ max-width: 120px; // 限制最大宽度
323
+ }
324
+ }
325
+ }
326
+ }
327
+ </style>