@tongfun/tf-widget 0.1.7 → 0.1.8-beta

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.
@@ -0,0 +1,2 @@
1
+ # tongfun
2
+ ## 砼方微前端布局组件(内部使用), 子应用菜单、标签导航组件
@@ -0,0 +1,8 @@
1
+ import TfLayout from './src/tf-layout'
2
+
3
+ /* istanbul ignore next */
4
+ TfLayout.install = function (Vue) {
5
+ Vue.component(TfLayout.name, TfLayout)
6
+ }
7
+
8
+ export default TfLayout
@@ -0,0 +1,361 @@
1
+ <template>
2
+ <div class="tf-labelbar">
3
+ <ul ref="labelMenu">
4
+ <li
5
+ v-for="tagItem in tagList"
6
+ :key="tagItem.path"
7
+ :class="activePath === tagItem.path ? 'active-tag' : ''"
8
+ @click="routeJump(tagItem)"
9
+ @contextmenu.prevent.stop="rightClick(tagItem, $event)"
10
+ >
11
+ <span>{{ tagItem.title }}</span>
12
+ <i
13
+ v-show="!tagItem.notCloseTag"
14
+ class="el-icon-close icon"
15
+ @click.stop="closeTag(tagItem)"
16
+ />
17
+ </li>
18
+ </ul>
19
+ <div
20
+ class="image left"
21
+ @click="handleScroll('left')"
22
+ />
23
+ <el-dropdown
24
+ class="right-menu"
25
+ trigger="click"
26
+ @command="dropdownCommand"
27
+ >
28
+ <span class="el-dropdown-link">
29
+ <TfRotateBox />
30
+ </span>
31
+ <el-dropdown-menu slot="dropdown">
32
+ <el-dropdown-item
33
+ icon="el-icon-back"
34
+ command="closeLeft"
35
+ >关闭左侧</el-dropdown-item>
36
+ <el-dropdown-item
37
+ icon="el-icon-right"
38
+ command="closeRight"
39
+ >关闭右侧</el-dropdown-item>
40
+ <el-dropdown-item
41
+ icon="el-icon-circle-close"
42
+ command="closeOther"
43
+ >关闭其他</el-dropdown-item>
44
+ <el-dropdown-item
45
+ icon="el-icon-circle-close"
46
+ command="closeAll"
47
+ >关闭全部</el-dropdown-item>
48
+ </el-dropdown-menu>
49
+ </el-dropdown>
50
+ <div
51
+ class="image right"
52
+ @click="handleScroll('right')"
53
+ />
54
+ <TfRightMenu
55
+ :left="rightMenuLeft"
56
+ :top="rightMenuTop"
57
+ :show-menu="showRightMenu"
58
+ @rightMenuClick="dropdownCommand"
59
+ />
60
+ </div>
61
+ </template>
62
+
63
+ <script>
64
+ import TfRotateBox from './tf-rotate-box.vue'
65
+ import TfRightMenu from './tf-right-menu'
66
+ export default {
67
+ name: 'TfLaberBar',
68
+ components: {
69
+ TfRotateBox,
70
+ TfRightMenu
71
+ },
72
+ data () {
73
+ return {
74
+ activePath: '/',
75
+ tagList: [],
76
+ rightMenuLeft: 0,
77
+ rightMenuTop: 0,
78
+ showRightMenu: false
79
+ }
80
+ },
81
+ watch: {
82
+ $route: {
83
+ handler: function (newValue) {
84
+ if (newValue) {
85
+ const { meta, path, name, params, query } = newValue
86
+ if (!path) return
87
+ const obj = {
88
+ path,
89
+ name,
90
+ params,
91
+ query,
92
+ defaultRouter: meta.defaultRouter,
93
+ notCloseTag: meta.notCloseTag,
94
+ title: meta.title,
95
+ replace: meta.replace
96
+ }
97
+ if (!meta.noCache) {
98
+ const cacheArr = newValue.matched.map(item => item.name)
99
+ this.$emit('setCache', cacheArr)
100
+ obj.cacheArr = cacheArr
101
+ }
102
+ if (obj.defaultRouter) {
103
+ if (!this.checkMenu(obj.path)) this.tagList.unshift(obj)
104
+ } else {
105
+ if (!this.checkMenu(obj.path)) this.tagList.push(obj)
106
+ }
107
+ // todo: 增加页面缓存
108
+ this.activePath = path
109
+ }
110
+ },
111
+ deep: true,
112
+ immediate: true
113
+ }
114
+ },
115
+ created () {
116
+ window.addEventListener('click', () => {
117
+ this.showRightMenu = false
118
+ }, false)
119
+ },
120
+ methods: {
121
+ /**
122
+ * @description tag右键点击事件
123
+ */
124
+ rightClick: function (tagItem, $event) {
125
+ this.routeJump(tagItem)
126
+ this.$nextTick(() => {
127
+ this.rightMenuTop = $event.clientY
128
+ this.rightMenuLeft = $event.clientX
129
+ this.showRightMenu = true
130
+ })
131
+ },
132
+
133
+ /**
134
+ * @member
135
+ * @description 右侧操作
136
+ * @param params: 操作指令: closeLeft => 关闭左侧, closeRight => 关闭右侧, closeAll => 关闭全部,
137
+ */
138
+ dropdownCommand: function (params) {
139
+ const activeNum = this.tagList.findIndex(
140
+ (item) => item.path === this.activePath
141
+ )
142
+ const pathMap = new Map()
143
+ const deleteArr = []
144
+ const pathArr = this.tagList.map((item) => {
145
+ pathMap.set(item.path, item)
146
+ return item.path
147
+ })
148
+ switch (params) {
149
+ case 'closeLeft':
150
+ deleteArr.push(...pathArr.slice(0, activeNum))
151
+ break
152
+ case 'closeRight':
153
+ deleteArr.push(...pathArr.slice(activeNum + 1, pathArr.length))
154
+ break
155
+ case 'closeOther':
156
+ deleteArr.push(...pathArr.slice(0, activeNum))
157
+ deleteArr.push(...pathArr.slice(activeNum + 1, pathArr.length))
158
+ break
159
+ default:
160
+ deleteArr.push(...pathArr)
161
+ break
162
+ }
163
+ const deleteCacheArr = []
164
+ deleteArr.forEach((item) => {
165
+ const tagItem = pathMap.get(item)
166
+ if (tagItem && tagItem.cacheArr) deleteCacheArr.push(tagItem.cacheArr)
167
+ if (tagItem && !tagItem.notCloseTag) {
168
+ const num = this.tagList.indexOf(tagItem)
169
+ this.tagList.splice(num, 1)
170
+ }
171
+ })
172
+
173
+ this.$emit('deleteCache', deleteCacheArr)
174
+ if (params === 'closeAll') this.routeJump(this.tagList[0])
175
+ },
176
+ /**
177
+ * @description 左右滑动
178
+ * @param direction: 滑动方向
179
+ */
180
+ handleScroll (direction) {
181
+ let rollNum = 0
182
+ rollNum = direction === 'right' ? rollNum + 50 : rollNum - 50
183
+ const dom = this.$refs.labelMenu
184
+ dom.scrollLeft += rollNum
185
+ },
186
+ /**
187
+ * @description 点击tag标签
188
+ * @param path: 每项Tag
189
+ */
190
+ checkMenu (path) {
191
+ if (this.tagList.find((item) => item.path === path)) return true
192
+ return false
193
+ },
194
+ /**
195
+ * @description 路由跳转
196
+ */
197
+ routeJump: function (value) {
198
+ if (value && value.path !== this.activePath) {
199
+ const { path, query, params, replace } = value
200
+ if (replace) {
201
+ this.$router.replace({
202
+ path,
203
+ query,
204
+ params
205
+ })
206
+ } else {
207
+ this.$router.push({
208
+ path,
209
+ query,
210
+ params
211
+ })
212
+ }
213
+ }
214
+ },
215
+ /**
216
+ * 关闭tag
217
+ */
218
+ closeTag: function (tagItem) {
219
+ if (tagItem.cacheArr) this.$emit('deleteCache', [tagItem.cacheArr])
220
+ const num = this.tagList.indexOf(tagItem)
221
+ if (tagItem) {
222
+ this.tagList.splice(num, 1)
223
+ this.routeJump(this.tagList[num - 1])
224
+ }
225
+ }
226
+ }
227
+ }
228
+ </script>
229
+ <style lang="less" scoped>
230
+ .tf-labelbar {
231
+ width: 100%;
232
+ height: 40px;
233
+ position: relative;
234
+ ul {
235
+ position: absolute;
236
+ left: 35px;
237
+ top: 0;
238
+ bottom: 0;
239
+ right: 55px;
240
+ padding: 0 10px;
241
+ margin: 0;
242
+ display: flex;
243
+ align-items: flex-end;
244
+ justify-content: left;
245
+ list-style: none;
246
+ overflow-y: none;
247
+ overflow-x: auto;
248
+ &::-webkit-scrollbar {
249
+ display: none;
250
+ }
251
+
252
+ li {
253
+ margin: 0;
254
+ padding: 0;
255
+ height: 35px;
256
+ min-width: 84px;
257
+ display: flex;
258
+ justify-content: center;
259
+ align-items: center;
260
+ position: relative;
261
+ cursor: pointer;
262
+ box-sizing: border-box;
263
+ padding: 0 28px 0 15px;
264
+ white-space: nowrap;
265
+ .icon {
266
+ width: 0;
267
+ height: 12px;
268
+ position: absolute;
269
+ right: 24px;
270
+ transform: translateY(-45%);
271
+ top: 50%;
272
+ overflow: hidden;
273
+ transition: all 0.3s;
274
+ &:hover {
275
+ background: #9e9e9e;
276
+ color: white;
277
+ border-radius: 50%;
278
+ }
279
+ }
280
+ &::before {
281
+ content: "";
282
+ height: 100%;
283
+ width: 0;
284
+ mask: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFQAAAAeCAYAAACyqDnLAAAAAXNSR0IArs4c6QAAA8BJREFUaEPtmk+IFEcUxr+vZzZZe3ZDdux1JWqCCZu4CsE/EJCQUxLJSTCRXLysQnIKGAI5SA7xkpBDvAge4kUEUTxoEA+yIRIIYclBQ9gIIjGLl4DJ9I7gTo+76vQLr2Zq0zPbM9ujt+2qy0xP/WnqN1+996peET2KiHhaTTIO52WCBRyC4B0BXgbwXK++q6BuAcDfIH5ljNPlEq4qBxEpkGx0mx+7VShMHeDePXm+8Qy+AnAIwCAAUcarAFh/UyB+8mJ8Wh7ijIgUST5OGyAVjIUZ3pct8HAJxKsA4gRMo9wcFBWPzls56ZwXhTg46vNcN6UuA2phVh/Ii3GMnwG8BOARgGIulfm/alSRhaYFxP61Pi+kQU0DSpISRvIDgHdbMAdyoMYsU1TbqVCrjQLeGBvkX1aAtnMbUEs8rMkkiFMA9F9RZbrSrtQiiLOBzwNdgYqIUab2CyO5BmBXy37kxV5mFY11yo+9GDvKw7yRhLqkUPtjJZKdBK5nHT2n7ZorV3AkGOI3Sa+fBGpCgUokHxP4zi33nlKxtvRyUOLepHNaDrQmx0h85oD2BKqhlEfg97KPnWoqrclcBjSMRJ3RpAOaCehs1cfWcXIxDajZUoWRXASwzwHtCdQ6porU8croKOfTgJqtZliXHyF4G4C1Ezn1OxmAEvONGONjQ/ynDah90M9qHb8JsN2FTBmAapwe4/VgmDdtlGRsqAV6V6RUrOMWgA0O6IoL0yx7z8Nb5TX8xXp6C9Qs97m6bBQxQP3cniqtyHGpQdMkEu8HPr/vBGoc0lxddotgOvuYuW7ZDO6Jw4HP4za4two1Qf1cXT4UwXnnkDIJxZ5znAhK/CQVaCWSowS+dCFTJqA2CpoKSnyv0yl1xqAuZFqZqd0tzd73sW0zuWCcu/Xwf4o8OxLhDxDjzsOvTDPhtB/GBWxbN8jbRqVL6Y55mYCHmdb5Zz7zRpk4tjUyKzlxgl9UoMYhJQ6V3XLPDtY4JhLfrvX5uWG5dEpflzMQHHAOKTvNRDQ0HZT4pjGf2r21Q7oJYJOzn30BtaZxoeBhYmQN7xigczXZI8SUg9kXTNu4aSIFk8EQTzeBRnJSgI9cQP8UQIGLQYkf8N+arPdockgvJJL6TzRyR6fVdLvEJC+7FK3TRGa14GEXw5ocAfG1W+5PpSEbGX3BSiRXALxGYhGCAbbuLcV6Q6I9J6+K0yS/LZ4kntn8nkw5dz7bft1+T85Ix0m+q9/Z6gR1J9NPUaWl3VfScdIuhzWk9Q7qfS9iEIIb/wHQ08swGxvGXQAAAABJRU5ErkJggg==);
285
+ mask-repeat: no-repeat;
286
+ mask-size: 100% 100%;
287
+ position: absolute;
288
+ left: 0%;
289
+ right: 0;
290
+ transform: translateX(-50%);
291
+ transition: all 0.3s;
292
+ }
293
+ &:hover {
294
+ .icon {
295
+ right: 12px;
296
+ width: 12px;
297
+ }
298
+ &::before {
299
+ left: 50%;
300
+ width: 120%;
301
+ z-index: -1;
302
+ background: #eeeeee;
303
+ }
304
+ }
305
+ }
306
+ .active-tag {
307
+ color: #0c4c8e;
308
+ &::before {
309
+ left: 50%;
310
+ width: 120%;
311
+ z-index: -1;
312
+ background: #ecf5ff;
313
+ }
314
+ .icon {
315
+ right: 12px;
316
+ width: 12px;
317
+ }
318
+ &:hover {
319
+ &::before {
320
+ background: #ecf5ff !important;
321
+ }
322
+ }
323
+ }
324
+ }
325
+ .image {
326
+ cursor: pointer;
327
+ width: 13px;
328
+ height: 13px;
329
+ position: absolute;
330
+ top: 50%;
331
+ transform: translateY(-50%);
332
+ &:hover {
333
+ background: #07579a;
334
+ }
335
+ }
336
+ .left {
337
+ background: #99999a;
338
+ left: 10px;
339
+ mask: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAcCAYAAAB2+A+pAAAAAXNSR0IArs4c6QAAA9RJREFUSEuVl0tvG2UUhp/zeRIXaMFiEaEsyq1NU0oJKVBaxEVtWqCoRVzELyB2HEXiByAkAgsuldhESmJHsiIlexawoC0qioAFFWUFCJVFEWJFEBtEAh6Pv4NOPBMcx5fxSN7NO8/3nffcLKR8VFUqlcr+KIqOOOe0Vqv9MDMz81tKOaYvlUp3ZzKZw977WyStsFKp7KvVauMi8hiw6Zxby+fzP/Wjr9frx1T1GJBNBZ6fn98bBMHDwCvA08BN7/3C9PT0Whpwk/5V4KRpeoKXl5f3hGH4AHABeBk4CnwnIm8XCoXPeoFb9AYeAWpdwSaqVquHgAkRMZGFaQ9wXVXfLBaLn3cDt9E/CgRA1BEcn/Sgqp4VkbPACSBnIFX9AninWCx+2QncRR8Cf7cFJycVkVOqekFExoE7AAfUgSvAe1NTU1+3A/fQ/wv8uQtsoiiKRur1+pmWm2qcExFg3l5sB06h3wR+3wFuOulpVT0f39TCa+9tg1X1koh8mICtRkVEU+p3gufm5rLZbHbEPAWeFZHHE09bwhmJyBUR+SCfz3+VQPvQ/wP8sXXjDp4kN2210UJt2bztcZ/6BnhhYeG+gYGBIe+9NYZTzdnbIWO3PLYb53K5a+vr67kgCEZE5KmU+ga4VCq97py7x3tvyTQaZ2+7bG/2+NNMJnPROfdjFEVjqvqCQXvok3s0wEtLS4vAqKo+GRd3p9JsBn+sqh9ls9lfwjA8JyJ54Dgw2KuTAQ1wuVyuiMghVbUeanWaGhwEwa/ee6vzvKo+AmT6Ab8B3Bv7cz+wt4O4uY4/sToeHBy8EYbhcRE5r6rm8YEu+p2hLpfLo977u5xzp4FnAOtS+7qcfDu5VPVb59ydURQd7kPfCLXV4erq6q2bm5sPicgZ4BzwYBf4rnJaWVm5rQ/9/3VstzPxxsaGbReWoROAzd92Yd9qIKr6vnWupIH0od8JNrgNbOfcWCaTmVDV54EjwO2tnatTy0ypt5bZ6FzNj604YRiaZ88BFvrE81RDIoV+95BIDmBhq1arR+MJZaFv9rwuIpeTULdLwh56C/XusdgM7+C53fyqc+5dGxKdsr+L51Xgr66rT+KZc84m1ovxvhWo6jfAW8Vi8Wq3htFGPxa/X+257MWeWam9ZL+4SVyLl73LvTpVi96Wxf3WNnuC7cPlctnWHpvPrwFPAD8Dc4VCYc0WgF7wFr19p/uWmXzQanVxcTHnnDPRSRHZcM5dmpyc/D4NuFkvIidUdTDVje0As7Ozbnh4+ID33oaBF5HrhULhZhpwoh8aGjoYBMG4/YX5D8BcMmEDOwIbAAAAAElFTkSuQmCC);
340
+ mask-size: 100% 100%;
341
+ mask-repeat: no-repeat;
342
+ }
343
+ .right {
344
+ background: #99999a;
345
+ right: 35px;
346
+ mask: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABoAAAAaCAYAAACpSkzOAAAAAXNSR0IArs4c6QAAA25JREFUSEuVls9rXFUUx7/fO3mDojAhZGFwIYgbFXUj4kJqpQqtC5dxHUiYRDCL7NRSWsG/IS/PB6Vr20ijNNL0h0mlPzQNRVyIyZgWF1FrWhV1kpl59ytH3pNxmJk73uXjfu/nnXO+95zLOI7fdM7VW63WNzMzM9skhcBK0/Qx7/1z3nuWSqWvJycnb4d0jOP4KMm6pKsjIyM3x8fHGyFQkiRPSzpEskzyi0qlshHSGegagCbJz7IsO1Mqlb6vVqvNfrA4jg3yFoBHSH7aarUWQzouLCz8mh+6Lum09/7y6Ojodr8/TJLkiKQTAJ4iedV7vxjSGagOoAzgDwDXASw659YqlUqtFyxJklcBfCDpBQC/AbgR0hnINj4IIAJwj+QVScskL0va7pbGJElelvQ+gAN5NoI6A90H8FAOMsf9AuCapCXn3JXh4eHbnZEZCMBxSQcBFC7tqzPQLoCH8/SZiAB+NDdJWsmybLUotCSajfOIrEYGtNVXZxs6QYXZMgC7JM0gZ9thtqEjonaD9tT1AhXiXUlrAM63uyqO4wMkjwN4pcc1+I+uXC7fDYG8RQbgJoAl7/3y9PT0nTRNX/LeHwNg7uu2/tFJ2iD5MclaCFQcYnfNDHJqaGhopdlsPumcew/AkUAXMUevkdwcBFQU2lx1kmRKcsR7/w6AN/qACt2OpDv/B3Sf5ElJHwKoAHh3QNDPAH4YBGQ/bV3jKwCnoig612g0nnDOHZX0eiB1f+YtKpg6C9/qcwvAJwCWd3Z2tsbGxl4keUzSaz1A/+pIngUQNIN1Det/5wFcLJfLmxMTE3sD2LvQrQC44L3/qVfqzJ73LBIbA5Iu7e/vfzc7O7sfuLA9db1a0N3czhecc5eiKKpZJEULmp+fP+icswvb2YK66ooW1N5U7Ztd0C+tJpJWG41GzSIpIF0iKmzcVVfUsHNMWOGv27S13O7t7W0V6WovepcxEdS1D76/cgsvkfw8iqJvLV3dXNUx+H4vWlQ/XTGPSpJuOefOZFl2sV6v1+bm5mzydl1xHB92zp2Q9KylmeRiSGegdQCt3MIftburD+iQc+5tSY9KOkfydEhnIJv9dZumURTd6JWuAmqmSNP0Ge/9YZIPAFgdRGfPrQl7QALYmJqa2gw9BA2UJMnjkp4H4ACsV6vVrZDubzHWkATwr3pxAAAAAElFTkSuQmCC);
347
+ mask-size: 100% 100%;
348
+ mask-repeat: no-repeat;
349
+ }
350
+ .right-menu {
351
+ cursor: pointer;
352
+ width: 14px;
353
+ height: 100%;
354
+ position: absolute;
355
+ top: 0;
356
+ right: 10px;
357
+ display: flex;
358
+ align-items: center;
359
+ }
360
+ }
361
+ </style>
@@ -0,0 +1,167 @@
1
+ <template>
2
+ <div class="tf-menu" :style="{ width: isCollapse ? '64px' : '175px' }">
3
+ <el-scrollbar class="tf-menu-scroll">
4
+ <el-menu
5
+ :collapse="isCollapse"
6
+ :default-active="activePath"
7
+ class="tf-menu-content"
8
+ background-color="#001529"
9
+ text-color="#919398"
10
+ active-text-color="#ffffff"
11
+ :router="true"
12
+ :style="{ width: isCollapse ? '64px' : '175px' }"
13
+ >
14
+ <template v-for="firstMenuItem in menuInfo">
15
+ <el-submenu
16
+ v-if="firstMenuItem.childNode"
17
+ :key="firstMenuItem.path"
18
+ :index="firstMenuItem.path"
19
+ >
20
+ <template slot="title">
21
+ <svg-icon
22
+ :icon-class="firstMenuItem.icon"
23
+ style="height: 15px; width: 15px; margin-right: 10px"
24
+ />
25
+ <span>{{ firstMenuItem.moduleName }}</span>
26
+ </template>
27
+ <el-menu-item
28
+ v-for="secondMenuItem in firstMenuItem.childNode"
29
+ :key="secondMenuItem.path"
30
+ :index="secondMenuItem.path"
31
+ >
32
+ <svg-icon
33
+ :icon-class="firstMenuItem.icon"
34
+ style="height: 15px; width: 15px; margin-right: 10px"
35
+ />
36
+ <span>{{ secondMenuItem.moduleName }}</span>
37
+ </el-menu-item>
38
+ </el-submenu>
39
+ <el-menu-item
40
+ v-else
41
+ :key="firstMenuItem.path"
42
+ :index="firstMenuItem.path"
43
+ >
44
+ <svg-icon
45
+ :icon-class="firstMenuItem.icon"
46
+ style="height: 15px; width: 15px; margin-right: 10px"
47
+ />
48
+ <span slot="title">{{ firstMenuItem.moduleName }}</span>
49
+ </el-menu-item>
50
+ </template>
51
+ </el-menu>
52
+ </el-scrollbar>
53
+ <div
54
+ class="bottom-menu"
55
+ :style="{ transform: isCollapse ? 'rotate(0deg)' : 'rotate(180deg)' }"
56
+ @click="isCollapse = !isCollapse"
57
+ >
58
+ <img
59
+ src="data:image/png;base64,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"
60
+ alt=""
61
+ />
62
+ </div>
63
+ </div>
64
+ </template>
65
+
66
+ <script>
67
+ export default {
68
+ name: 'TfMenu',
69
+ props: {
70
+ menuInfo: {
71
+ type: Array,
72
+ default: function () {
73
+ return []
74
+ }
75
+ }
76
+ },
77
+ data () {
78
+ return {
79
+ isCollapse: false,
80
+ activePath: null
81
+ }
82
+ },
83
+ watch: {
84
+ '$route.path': {
85
+ handler: function (params) {
86
+ if (params) this.activePath = params
87
+ },
88
+ deep: true,
89
+ immediate: true
90
+ }
91
+ }
92
+ }
93
+ </script>
94
+
95
+ <style lang="less" scoped>
96
+ .tf-menu {
97
+ height: 100%;
98
+ background: #001529;
99
+ transition: width 0.3s ease-in-out;
100
+ /deep/.tf-menu-content {
101
+ transition: width 0.3s ease-in-out;
102
+ border-right: none !important;
103
+ .el-menu--collapse {
104
+ width: 64px !important;
105
+ .el-submenu .el-menu-item {
106
+ height: 40px;
107
+ width: 175px;
108
+ }
109
+ }
110
+ .el-submenu .el-menu-item {
111
+ transition: width 0.3s;
112
+ height: 40px;
113
+ width: 175px;
114
+ }
115
+ .el-menu-item,
116
+ .el-submenu__title {
117
+ transition: width 0.3s !important;
118
+
119
+ height: 40px;
120
+ line-height: 40px;
121
+ &:hover {
122
+ background: #0361a4 !important;
123
+ }
124
+ }
125
+ .is-active {
126
+ transition: width 0.3s !important;
127
+
128
+ background: #0361a4 !important;
129
+ }
130
+ margin-bottom: 10px;
131
+ }
132
+ .tf-menu-scroll {
133
+ height: calc(100vh - 200px);
134
+ width: 100%;
135
+ }
136
+ /deep/.el-scrollbar__wrap {
137
+ overflow-x: hidden;
138
+ }
139
+ .bottom-menu {
140
+ width: 100%;
141
+ height: 60px;
142
+ display: flex;
143
+ align-items: center;
144
+ justify-content: center;
145
+ img {
146
+ width: 20px;
147
+ height: 20px;
148
+ transition: all 0.3s;
149
+ }
150
+ }
151
+ }
152
+ </style>
153
+ <style lang="less">
154
+ .el-menu--vertical {
155
+ .el-menu--collapse .el-menu .el-submenu,
156
+ .el-menu--popup {
157
+ min-width: 175px;
158
+ .el-menu-item {
159
+ height: 40px;
160
+ line-height: 40px;
161
+ &:hover {
162
+ background: #0361a4 !important;
163
+ }
164
+ }
165
+ }
166
+ }
167
+ </style>
@@ -0,0 +1,89 @@
1
+ <template>
2
+ <div
3
+ v-show="showMenu"
4
+ class="tf-right-menu"
5
+ :style="{ top: top + 'px', left: left + 'px' }"
6
+ >
7
+ <p @click="rightMenuClick('closeLeft')">
8
+ <i class="el-icon-back" /> 关闭左侧
9
+ </p>
10
+ <p @click="rightMenuClick('closeRight')">
11
+ <i class="el-icon-right" /> 关闭右侧
12
+ </p>
13
+ <p @click="rightMenuClick('closeOther')">
14
+ <i class="el-icon-circle-close" /> 关闭其他
15
+ </p>
16
+ <p @click="rightMenuClick('closeAll')">
17
+ <i class="el-icon-circle-close" /> 全部关闭
18
+ </p>
19
+ </div>
20
+ </template>
21
+
22
+ <script>
23
+ export default {
24
+ props: {
25
+ top: {
26
+ default: 0,
27
+ type: Number
28
+ },
29
+ left: {
30
+ default: 0,
31
+ type: Number
32
+ },
33
+ showMenu: {
34
+ type: Boolean,
35
+ default: false
36
+ }
37
+ },
38
+ methods: {
39
+ /**
40
+ * @description 右键点击事件
41
+ */
42
+ rightMenuClick (params) {
43
+ this.$emit('rightMenuClick', params)
44
+ }
45
+ }
46
+ }
47
+ </script>
48
+
49
+ <style lang="less" scoped>
50
+ .tf-right-menu {
51
+ position: fixed;
52
+ z-index: 9999;
53
+ width: 120px;
54
+ height: 166px;
55
+ background: white;
56
+ box-shadow: 0 2px 12px 0 rgb(0 0 0 / 10%);
57
+ border-radius: 4px;
58
+ box-sizing: border-box;
59
+ padding: 10px 0;
60
+ p {
61
+ cursor: pointer;
62
+ height: 36px;
63
+ margin: 0;
64
+ font-size: 14px;
65
+ display: flex;
66
+ align-items: center;
67
+ justify-content: space-between;
68
+ box-sizing: border-box;
69
+ padding: 0 20px;
70
+ color: #606266;
71
+ &:hover {
72
+ background: #ecf5ff;
73
+ color: #46a6ff;
74
+ }
75
+ }
76
+ &::before {
77
+ content: "";
78
+ position: absolute;
79
+ width: 12px;
80
+ height: 6px;
81
+ top: -6px;
82
+ right: 10px;
83
+ background: white;
84
+ clip-path: polygon(50% 0px, 100% 100%, 0px 100%);
85
+ box-shadow: 0 2px 12px 0 rgb(0 0 0 / 10%);
86
+ border-radius: 1px;
87
+ }
88
+ }
89
+ </style>
@@ -0,0 +1,50 @@
1
+ <template>
2
+ <div class="tf-rotate-box">
3
+ <span class="close">
4
+ <i />
5
+ <i />
6
+ <i />
7
+ <i />
8
+ </span>
9
+ </div>
10
+ </template>
11
+
12
+ <script>
13
+ export default {}
14
+ </script>
15
+
16
+ <style lang="less" scoped>
17
+ .tf-rotate-box {
18
+ display: flex;
19
+ align-items: center;
20
+ justify-content: center;
21
+ .close {
22
+ width: 14px;
23
+ height: 14px;
24
+ display: flex;
25
+ flex-wrap: wrap;
26
+ align-items: center;
27
+ justify-content: center;
28
+ gap: 2px 2px;
29
+ transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1), border 0s,
30
+ color 0.1s, font-size 0s;
31
+ &:hover {
32
+ transform: rotate(90deg);
33
+ transform-origin: 50% 50%;
34
+ i {
35
+ background: #07579a;
36
+ &:nth-child(1) {
37
+ transform: rotate(45deg);
38
+ transform-origin: 50% 50%;
39
+ }
40
+ }
41
+ }
42
+ i {
43
+ margin: 0;
44
+ height: 6px;
45
+ width: 6px;
46
+ background: #9a9a9a;
47
+ }
48
+ }
49
+ }
50
+ </style>