columnsAside.vue 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. <template>
  2. <div class="layout-columns-aside">
  3. <el-scrollbar>
  4. <ul>
  5. <li
  6. v-for="(v, k) in columnsAsideList"
  7. :key="k"
  8. @click="onColumnsAsideMenuClick(v)"
  9. ref="columnsAsideOffsetTopRefs"
  10. :class="{ 'layout-columns-active': v.k === liIndex }"
  11. :title="$t(v.title)"
  12. >
  13. <div :class="setColumnsAsidelayout" v-if="!v.isLink || (v.isLink && v.isIframe)">
  14. <Icon :type="v.icon" />
  15. <div class="font12">
  16. {{
  17. $t(v.title) && $t(v.title).length >= 4
  18. ? $t(v.title).substr(0, setColumnsAsidelayout === 'columns-vertical' ? 4 : 3)
  19. : $t(v.title)
  20. }}
  21. </div>
  22. </div>
  23. <div :class="setColumnsAsidelayout" v-else>
  24. <a :href="v.isLink" target="_blank">
  25. <Icon :type="v.icon" />
  26. <div class="font12">
  27. {{
  28. $t(v.title) && $t(v.title).length >= 4
  29. ? $t(v.title).substr(0, setColumnsAsidelayout === 'columns-vertical' ? 4 : 3)
  30. : $t(v.title)
  31. }}
  32. </div>
  33. </a>
  34. </div>
  35. </li>
  36. <div ref="columnsAsideActiveRef" :class="setColumnsAsideStyle"></div>
  37. </ul>
  38. </el-scrollbar>
  39. </div>
  40. </template>
  41. <script>
  42. import { getMenuSider, getHeaderName } from '@/libs/system';
  43. export default {
  44. name: 'layoutColumnsAside',
  45. data() {
  46. return {
  47. columnsAsideList: [],
  48. liIndex: 0,
  49. difference: 0,
  50. routeSplit: [],
  51. activePath: '',
  52. };
  53. },
  54. computed: {
  55. // 设置分栏高亮风格
  56. setColumnsAsideStyle() {
  57. return this.$store.state.themeConfig.themeConfig.columnsAsideStyle;
  58. },
  59. // 设置分栏布局风格
  60. setColumnsAsidelayout() {
  61. console.log(this.$store.state.themeConfig.themeConfig.columnsAsideLayout, '122311');
  62. return this.$store.state.themeConfig.themeConfig.columnsAsideLayout;
  63. },
  64. Layout() {
  65. console.log(this.$store.state.themeConfig.themeConfig.Layout, '122311444');
  66. return this.$store.state.themeConfig.themeConfig.Layout;
  67. },
  68. },
  69. mounted() {
  70. this.setFilterRoutes();
  71. },
  72. methods: {
  73. // 设置菜单高亮位置移动
  74. setColumnsAsideMove(k) {
  75. if (k === undefined) return false;
  76. const els = this.$refs.columnsAsideOffsetTopRefs;
  77. this.liIndex = k;
  78. this.$refs.columnsAsideActiveRef.style.top = `${els[k].offsetTop + this.difference}px`;
  79. },
  80. // 菜单高亮点击事件
  81. onColumnsAsideMenuClick(v) {
  82. // console.log(v, 'vvvv');
  83. let { path, redirect } = v;
  84. if (path) this.$router.push(path);
  85. else this.$router.push(path);
  86. // 一个路由设置自动收起菜单
  87. if (!v.children || v.children.length <= 1) this.$store.state.themeConfig.themeConfig.isCollapse = true;
  88. else if (v.children.length > 1) this.$store.state.themeConfig.themeConfig.isCollapse = false;
  89. // this.bus.$emit('setSendColumnsChildren', getMenuSider(this.columnsAsideList, path));
  90. },
  91. // 设置高亮动态位置
  92. onColumnsAsideDown(k) {
  93. this.$nextTick(() => {
  94. this.setColumnsAsideMove(k);
  95. });
  96. },
  97. // 设置/过滤路由(非静态路由/是否显示在菜单中)
  98. setFilterRoutes() {
  99. if (this.$store.state.routesList.routesList.length <= 0) return false;
  100. this.columnsAsideList = this.filterRoutesFun(this.$store.state.routesList.routesList);
  101. // const resData = getHeaderName(this.$route.path, this.columnsAsideList);
  102. const resData = this.setSendChildren(getHeaderName(this.$route, this.columnsAsideList));
  103. if (!resData.children) {
  104. this.bus.$emit('setSendColumnsChildren', []);
  105. this.$store.state.themeConfig.themeConfig.isCollapse = true;
  106. return false;
  107. }
  108. this.onColumnsAsideDown(resData.item[0].k);
  109. // 刷新时,初始化一个路由设置自动收起菜单
  110. resData.children.length > 0
  111. ? (this.$store.state.themeConfig.themeConfig.isCollapse = false)
  112. : (this.$store.state.themeConfig.themeConfig.isCollapse = true);
  113. this.bus.$emit('setSendColumnsChildren', resData?.children || []);
  114. },
  115. // 传送当前子级数据到菜单中
  116. setSendChildren(path) {
  117. const currentPathSplit = path.split('/');
  118. let currentData = {};
  119. this.columnsAsideList.map((v, k) => {
  120. if (v.path === path) {
  121. v['k'] = k;
  122. currentData['item'] = [{ ...v }];
  123. // currentData['children'] = [{ ...v }];
  124. if (v.children) currentData['children'] = v.children;
  125. }
  126. });
  127. return currentData;
  128. },
  129. // 路由过滤递归函数
  130. filterRoutesFun(arr) {
  131. return arr
  132. .filter((item) => item.path)
  133. .map((item) => {
  134. item = Object.assign({}, item);
  135. if (item.children) item.children = this.filterRoutesFun(item.children);
  136. return item;
  137. });
  138. },
  139. // tagsView 点击时,根据路由查找下标 columnsAsideList,实现左侧菜单高亮
  140. setColumnsMenuHighlight(path) {
  141. this.routeSplit = path.split('/');
  142. this.routeSplit.shift();
  143. const routeFirst = `/${this.routeSplit[0]}`;
  144. const currentSplitRoute = this.columnsAsideList.find((v) => v.path === routeFirst);
  145. console.log(currentSplitRoute, 'currentSplitRoute');
  146. if (!currentSplitRoute) return false;
  147. // 延迟拿值,防止取不到
  148. setTimeout(() => {
  149. this.onColumnsAsideDown(currentSplitRoute.k);
  150. }, 0);
  151. },
  152. },
  153. watch: {
  154. // 监听 vuex 数据变化
  155. '$store.state': {
  156. handler(val) {
  157. console.log('变了变了');
  158. val.themeConfig.themeConfig.columnsAsideStyle === 'columnsRound'
  159. ? (this.difference = 3)
  160. : (this.difference = 0);
  161. if (val.routesList.routesList.length === this.columnsAsideList.length) return false;
  162. // this.setFilterRoutes();
  163. },
  164. deep: true,
  165. },
  166. // 监听路由的变化
  167. $route: {
  168. handler(to) {
  169. this.setColumnsMenuHighlight(to.path);
  170. // this.setColumnsAsideMove();
  171. let HeadName = getHeaderName(to, this.columnsAsideList);
  172. let asideList = getMenuSider(this.columnsAsideList, HeadName)[0]?.children;
  173. const resData = this.setSendChildren(HeadName);
  174. if (resData.length <= 0) return false;
  175. this.onColumnsAsideDown(resData.item[0].k);
  176. this.bus.$emit('setSendColumnsChildren', asideList || []);
  177. },
  178. deep: true,
  179. },
  180. },
  181. };
  182. </script>
  183. <style scoped lang="scss">
  184. .layout-columns-aside {
  185. width: 70px;
  186. height: 100%;
  187. background: var(--prev-bg-columnsMenuBar);
  188. ul {
  189. position: relative;
  190. li {
  191. color: var(--prev-bg-columnsMenuBarColor);
  192. width: 100%;
  193. height: 50px;
  194. text-align: center;
  195. display: flex;
  196. cursor: pointer;
  197. position: relative;
  198. z-index: 1;
  199. .columns-vertical {
  200. margin: auto;
  201. .columns-vertical-title {
  202. padding-top: 1px;
  203. }
  204. }
  205. .columns-horizontal {
  206. display: flex;
  207. height: 50px;
  208. width: 100%;
  209. align-items: center;
  210. justify-content: center;
  211. padding: 0 5px;
  212. i {
  213. margin-right: 3px;
  214. }
  215. a {
  216. display: flex;
  217. .columns-horizontal-title {
  218. padding-top: 1px;
  219. }
  220. }
  221. }
  222. a {
  223. text-decoration: none;
  224. color: var(--prev-bg-columnsMenuBarColor);
  225. }
  226. }
  227. .layout-columns-active,
  228. .layout-columns-active a {
  229. color: var(--prev-color-text-white);
  230. transition: 0.3s ease-in-out;
  231. }
  232. .columns-round {
  233. background: var(--prev-color-primary);
  234. color: var(--prev-color-text-white);
  235. position: absolute;
  236. left: 50%;
  237. top: 2px;
  238. height: 50px;
  239. width: 65px;
  240. transform: translateX(-50%);
  241. z-index: 0;
  242. transition: 0.3s ease-in-out;
  243. border-radius: 5px;
  244. }
  245. .columns-card {
  246. @extend .columns-round;
  247. top: 0;
  248. height: 50px;
  249. width: 100%;
  250. border-radius: 0;
  251. }
  252. }
  253. }
  254. </style>