columnsAside.vue 8.6 KB

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