| <template> | 
|   <div> | 
|     <!-- 右侧用户登录图标 --> | 
|     <div class="user-logininfo"> | 
|       <div class="logoIcon" v-if="logo"> | 
|         <div class="image"> | 
|           <img src="../../assets/logo.jpg" alt="" srcset="" /> | 
|         </div> | 
|       </div> | 
|       <div class="user-logininfo-icon" v-else> | 
|         <!-- 折叠 --> | 
|         <i @click="clickFold" class="el-icon-s-fold"></i> | 
|         <!-- 标签列表 --> | 
|         <div class="tag-list-container" @wheel.prevent="handleWheel"> | 
|           <div class="tag-list" v-for="tag in tagList" :key="tag.name"> | 
|             <div | 
|               @click="goTag(tag)" | 
|               :class="{ activeTag: tag.path === $route.path }" | 
|             > | 
|               {{ tag.meta.title }} | 
|             </div> | 
|             <i | 
|               @click="closeTag(tag)" | 
|               v-if="tagList.length > 1" | 
|               class="el-icon-close" | 
|             ></i> | 
|           </div> | 
|         </div> | 
|       </div> | 
|       <div class="user-info"> | 
|         <img src="@/assets/public/photo.png" /> | 
|         <div class="user-info-text">欢迎您,{{ userInfo.nickName }}</div> | 
|         <div class="user-info-line"></div> | 
|         <div @click="outLogin" class="user-info-out"> | 
|           <img src="@/assets/public/logOut.png" /> | 
|           <div class="user-info-out-text">退出登录</div> | 
|         </div> | 
|       </div> | 
|     </div> | 
|     <el-dialog | 
|       top="40vh" | 
|       :visible.sync="show" | 
|       :show-close="false" | 
|       :append-to-body="true" | 
|       :close-on-click-modal="false" | 
|       width="433px" | 
|     > | 
|       <div class="top-con a-center" slot="title"> | 
|         <div class="left"> | 
|           <img | 
|             src="@/assets/public/notice@2x.png" | 
|             style="width: 24px; height: 24px; margin-right: 14px" | 
|           /> | 
|           <div class="title">{{ "提示" }}</div> | 
|         </div> | 
|       </div> | 
|       <div class="lh--32 fs--20"> | 
|         {{ "当前页面可能有未保存数据,确认关闭么" }} | 
|       </div> | 
|       <span slot="footer" class="dialog-footer"> | 
|         <el-button @click="show = false">取消</el-button> | 
|         <el-button type='danger' @click="submitClose">{{ "确认" }}</el-button> | 
|       </span> | 
|     </el-dialog> | 
|   </div> | 
| </template> | 
|   | 
| <script> | 
| import { mapState } from "vuex"; | 
| export default { | 
|   data() { | 
|     return { | 
|       userInfo: "", | 
|       scrollTimer: null, | 
|       scrollAmount: 0, | 
|       show: false, | 
|       pendingCloseTag: null, | 
|     }; | 
|   }, | 
|   props: { | 
|     logo: { | 
|       type: String, | 
|       default: "", | 
|     }, | 
|   }, | 
|   computed: { | 
|     ...mapState(["tagList", "isFold"]), | 
|   }, | 
|   mounted() { | 
|     // 获取用户信息 | 
|     this.getUserInfo(); | 
|   }, | 
|   methods: { | 
|     // 点击折叠按钮 | 
|     clickFold() { | 
|       this.$store.commit("SET_ISFOLD", !this.isFold); | 
|     }, | 
|     // 获取用户信息 | 
|     getUserInfo() { | 
|       this.userInfo = JSON.parse(sessionStorage.getItem("userInfo")); | 
|     }, | 
|     // 退出登录 | 
|     outLogin() { | 
|       sessionStorage.clear(); | 
|       this.$router.replace({ path: "/" }); | 
|     }, | 
|     // 关闭标签 | 
|     closeTag(tag) { | 
|       if (tag.path && tag.path.includes('add')) { | 
|         this.pendingCloseTag = tag; | 
|         this.show = true; | 
|         return; | 
|       } | 
|       this._doCloseTag(tag); | 
|     }, | 
|     // 真正执行关闭标签的逻辑 | 
|     _doCloseTag(tag) { | 
|       this.$store.commit( | 
|         "SET_TAGLIST", | 
|         this.tagList.filter((item) => item.path !== tag.path) | 
|       ); | 
|       // 判断是否是当前标签 | 
|       if (tag.path === this.$route.path) { | 
|         this.$router.push(this.tagList[this.tagList.length - 1].path); | 
|       } | 
|     }, | 
|     submitClose() { | 
|       this.show = false; | 
|       if (this.pendingCloseTag) { | 
|         this._doCloseTag(this.pendingCloseTag); | 
|         this.pendingCloseTag = null; | 
|       } | 
|     }, | 
|     // 跳转标签 | 
|     goTag(tag) { | 
|       this.$router.push({ | 
|         path: tag.path, | 
|         query: tag.query, | 
|       }); | 
|     }, | 
|     handleWheel(e) { | 
|       if (this.scrollTimer) { | 
|         this.scrollAmount += e.deltaY; | 
|         return; | 
|       } | 
|   | 
|       const container = e.currentTarget; | 
|       this.scrollAmount = e.deltaY; | 
|   | 
|       const scroll = () => { | 
|         container.scrollLeft += this.scrollAmount * 1.2; // 增加滚动速度 | 
|         this.scrollAmount = 0; | 
|         this.scrollTimer = null; | 
|       }; | 
|   | 
|       this.scrollTimer = setTimeout(scroll, 8); // 减少延迟时间 | 
|     }, | 
|   }, | 
| }; | 
| </script> | 
|   | 
| <style lang="less" scoped> | 
| // 右侧用户头像 | 
| .user-logininfo { | 
|   height: 100%; | 
|   padding-left: 32px; | 
|   padding-right: 20px; | 
|   display: flex; | 
|   align-items: center; | 
|   justify-content: space-between; | 
|   overflow: hidden; | 
|   | 
|   .image { | 
|     // margin-top: 40px; | 
|     width: 70px; | 
|     height: 70px; | 
|   | 
|     img { | 
|       width: 100%; | 
|       height: 100%; | 
|       border-radius: 50%; | 
|     } | 
|   } | 
|   | 
|   .user-logininfo-icon { | 
|     margin-right: 30px; | 
|     flex: 1; | 
|     display: flex; | 
|     align-items: center; | 
|     min-width: 0; | 
|     overflow: hidden; | 
|   | 
|     i:first-child { | 
|       margin-right: 21px; | 
|     } | 
|   | 
|     i { | 
|       cursor: pointer; | 
|     } | 
|   | 
|     .tag-list-container { | 
|       display: flex; | 
|       align-items: center; | 
|       overflow-x: auto; | 
|       flex: 1; | 
|       min-width: 0; | 
|       scroll-behavior: auto; // 移除平滑滚动,提高性能 | 
|       -webkit-overflow-scrolling: touch; | 
|   | 
|       .tag-list { | 
|         flex-shrink: 0; | 
|         display: flex; | 
|         align-items: center; | 
|         cursor: pointer; | 
|         font-weight: 400; | 
|         font-size: 18px; | 
|         color: rgba(0, 0, 0, 0.6); | 
|         margin-right: 40px; | 
|   | 
|         div:hover { | 
|           font-weight: bold; | 
|           color: #049c9a; | 
|         } | 
|   | 
|         i { | 
|           margin-left: 10px; | 
|   | 
|           &:hover { | 
|             color: #049c9a; | 
|           } | 
|         } | 
|       } | 
|   | 
|       .activeTag { | 
|         font-weight: bold; | 
|         color: #049c9a; | 
|       } | 
|     } | 
|   } | 
|   | 
|   .user-info { | 
|     flex-shrink: 0; | 
|     display: flex; | 
|     align-items: center; | 
|   | 
|     img { | 
|       width: 26px; | 
|       height: 26px; | 
|       border-radius: 50%; | 
|     } | 
|   | 
|     .user-info-text { | 
|       margin-left: 16px; | 
|       font-size: 14px; | 
|       color: #303133; | 
|       font-weight: 400; | 
|     } | 
|   | 
|     .user-info-line { | 
|       width: 1px; | 
|       height: 12px; | 
|       background-color: #979797; | 
|       margin: 0 20px; | 
|     } | 
|   | 
|     .user-info-out { | 
|       display: flex; | 
|       align-items: center; | 
|       padding: 0 11px; | 
|       border-radius: 12px; | 
|       position: relative; | 
|       background: transparent; | 
|       cursor: pointer; | 
|   | 
|       &::before { | 
|         content: ""; | 
|         position: absolute; | 
|         top: 0; | 
|         left: 0; | 
|         right: 0; | 
|         bottom: 0; | 
|         border-radius: 12px; | 
|         padding: 1px; | 
|         background: linear-gradient( | 
|           180deg, | 
|           rgba(10, 203, 202, 1), | 
|           rgba(4, 156, 154, 1) | 
|         ); | 
|         -webkit-mask: linear-gradient(#fff 0 0) content-box, | 
|           linear-gradient(#fff 0 0); | 
|         -webkit-mask-composite: xor; | 
|         mask-composite: exclude; | 
|       } | 
|   | 
|       .user-info-out-text { | 
|         font-weight: 400; | 
|         font-size: 14px; | 
|         color: #049c9a; | 
|         line-height: 21px; | 
|         position: relative; | 
|         z-index: 1; | 
|       } | 
|   | 
|       img { | 
|         width: 14px; | 
|         height: 14px; | 
|         margin-right: 7px; | 
|         position: relative; | 
|         z-index: 1; | 
|       } | 
|     } | 
|   } | 
| } | 
| .left { | 
|     display: flex; | 
| } | 
|   | 
| ::v-deep .el-dialog { | 
|     border-radius: 12px; | 
|   | 
|     .el-dialog__header { | 
|         padding-top: 28px; | 
|         padding-right: 27px; | 
|         padding-left: 34px; | 
|         padding-bottom: 11px; | 
|     } | 
|   | 
|     .el-dialog__body { | 
|         padding: unset; | 
|         padding-left: 73px; | 
|         padding-right: 20px; | 
|     } | 
|   | 
|     .el-dialog__footer { | 
|         padding-top: 18px; | 
|         padding-right: 27px; | 
|         padding-bottom: 29px; | 
|     } | 
| } | 
|   | 
| .bgcolor1 { | 
|     background: rgba(22, 119, 255, 1); | 
| } | 
|   | 
| .top-con { | 
|     display: flex; | 
|     justify-content: space-between; | 
|   | 
|     .title { | 
|         font-family: PingFangSC, PingFang SC; | 
|         font-weight: 600; | 
|         font-size: 16px; | 
|         color: rgba(0, 0, 0, 1); | 
|         margin-bottom: 13px; | 
|     } | 
| } | 
|   | 
| .dialog-footer { | 
|     display: flex; | 
|     justify-content: end; | 
|     gap: 10px; | 
| } | 
| </style> |