header.vue 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. <template>
  2. <div class="trademark mr-8 flex items-center text-white">
  3. <img :src="loginLogin" class="w-10 h-10 mr-4" />
  4. <div class="text-nowrap">客户管家</div>
  5. </div>
  6. <div class=" flex flex-row justify-start items-center text-white flex-1 parentDiv" ref="parentDiv">
  7. <div v-for="(routerItem, routerItemIdex) in routerList"
  8. :class="`border-b-2 border-transparent hover:border-white p-2 mr-4 cursor-pointer multipleyHeader ${activeRouter?.path === routerItem.path ? 'border-white' : ''}`"
  9. :key="routerItem.path" ref="childDivs" v-show="visibleItems.includes(routerItemIdex)">
  10. <div v-if="routerItem.children && routerItem.children.length <= 0 && routerItem?.isMenu" @click="setCurrentRouter(routerItem)" class="text-nowrap">
  11. {{ routerItem.name }}
  12. </div>
  13. <div v-if="routerItem.children && routerItem.children.length > 0" class="flex justify-center items-center">
  14. <el-dropdown>
  15. <div class="text-white w-full h-full headerText">
  16. {{ routerItem.name }}
  17. <el-icon class="el-icon--right">
  18. <arrow-down />
  19. </el-icon>
  20. </div>
  21. <template #dropdown>
  22. <el-dropdown-menu>
  23. <el-dropdown-item v-for="child in routerItem.children" :key="child.path" @click="setCurrentRouter(child)">
  24. {{ child.name }}
  25. </el-dropdown-item>
  26. </el-dropdown-menu>
  27. </template>
  28. </el-dropdown>
  29. </div>
  30. </div>
  31. </div>
  32. <div class="flex flex-row justify-start items-center text-white header-right">
  33. <el-icon :size="26" class="ml-4 cursor-pointer">
  34. <Bell />
  35. </el-icon>
  36. <div>
  37. <img class="w-8 h-8 rounded-full ml-4 cursor-pointer" :src="defaultCover" alt="" @click="logout()">
  38. </div>
  39. <el-icon :size="26" class="ml-4 cursor-pointer">
  40. <Grid />
  41. </el-icon>
  42. </div>
  43. </template>
  44. <script lang="ts" setup>
  45. import { onMounted, ref, watchEffect, watch } from 'vue';
  46. import { RouteRecordRaw, useRouter, useRoute } from 'vue-router';
  47. import { useStore } from "../../store/index"
  48. import defaultCover from "../../assets/defaultCover.png";
  49. import loginLogin from '../../assets/login/login_logo.png'
  50. const { routers, clearStore } = useStore()
  51. const router = useRouter();
  52. const route = useRoute()
  53. // const routerList = ref<RouteRecordRaw[]>([]);
  54. const routerList = ref<any[]>([]);
  55. const activeRouter = ref<RouteRecordRaw>();
  56. const visibleItems = ref<number[]>([]);
  57. const parentDiv = ref<HTMLElement | null>(null);
  58. const updateVisibleItems = () => {
  59. const parentWidth = parentDiv.value?.offsetWidth || 10;
  60. const canvas = document.createElement('canvas');
  61. const context = canvas.getContext('2d');
  62. let textWidthList: any = [] // 所有文字的宽度
  63. let totalWidth = 0;
  64. let temporaryIndex: any = []
  65. if(context) {
  66. context.font = '16px 微软雅黑';
  67. textWidthList = routerList.value.map((item: any) => {
  68. const metrics = context.measureText(item.name);
  69. return Math.ceil(metrics.width) + 32; // 32是padding和margin的宽度
  70. })
  71. }
  72. for(let i in textWidthList) {
  73. if(totalWidth + textWidthList[i] > parentWidth) {
  74. break;
  75. }
  76. totalWidth += textWidthList[i];
  77. temporaryIndex.push(+i);
  78. }
  79. // 替换最后一个元素
  80. let lastIndex = textWidthList.length - 1;
  81. temporaryIndex.splice(temporaryIndex.length -1, 1, lastIndex)
  82. visibleItems.value = temporaryIndex;
  83. //console.log(visibleItems.value)
  84. };
  85. const setCurrentRouter = (item: RouteRecordRaw) => {
  86. activeRouter.value = item;
  87. if (item.children && item.children.length > 0) {
  88. router.push({ path: item.children[0].path });
  89. return
  90. }
  91. router.push({ path: item.path });
  92. };
  93. const logout = () => {
  94. clearStore();
  95. router.push({ path: '/login' });
  96. };
  97. onMounted(() => {
  98. routerList.value = routers;
  99. activeRouter.value = routerList.value.find((item) => item.path === router.currentRoute.value.path);
  100. window.addEventListener('resize', updateVisibleItems);
  101. setTimeout(() => {
  102. updateVisibleItems();
  103. }, 500);
  104. })
  105. watchEffect(() => {
  106. updateVisibleItems();
  107. watch(() => route.path, (newPath, _oldPath) => {
  108. activeRouter.value = routerList.value.find((item) => item.path === newPath);
  109. }, {
  110. immediate: false
  111. }
  112. );
  113. });
  114. </script>
  115. <style scoped lang="scss">
  116. .trademark {
  117. font-size: 20px;
  118. }
  119. .multipleyHeader {
  120. height: 96%;
  121. display: flex;
  122. align-items: center;
  123. text-wrap: nowrap;
  124. .headerText {
  125. font-size: 16px;
  126. }
  127. }
  128. .parentBox {
  129. // max-width: 80%;
  130. // min-width: 300px;
  131. flex: 1;
  132. overflow: hidden;
  133. }
  134. .header-right {
  135. width: 135px;
  136. }
  137. .parentDiv {
  138. width: 50%;
  139. }
  140. </style>