index.vue 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  1. <template>
  2. <div class="aside-menu--group">
  3. <div class="aside-menu--abbr-group">
  4. <div class="aside-menu--first-group">
  5. <div
  6. class="aside-menu--first-item"
  7. :class="{
  8. 'active': String(active.apex) === first._compute._key
  9. }"
  10. v-for="first in filterMenus"
  11. :key="first._compute._key"
  12. @click="onSelectApexMenu(first)"
  13. >
  14. <JyIcon :name="first.icon" classPrefix=""></JyIcon>
  15. <span>{{ first.label }}</span>
  16. </div>
  17. </div>
  18. <div class="aside-menu--toggle-group">
  19. <div
  20. class="aside-menu--toggle-item"
  21. :class="{
  22. active: item.key === type
  23. }"
  24. v-for="(item, i) in menuTypes"
  25. :key="i"
  26. @click="onSwitchMenuType(item)"
  27. >
  28. {{item.label}}
  29. </div>
  30. </div>
  31. </div>
  32. <div class="aside-menu--open-group" v-show="filterSubMenus.length">
  33. <el-menu
  34. :default-openeds="defaultOpenSubMenus"
  35. >
  36. <el-submenu
  37. v-for="group in filterSubMenus"
  38. :key="group._compute._uniqueIndexes[1]"
  39. :index="group._compute._uniqueIndexes[0] + '-' + group._compute._uniqueIndexes[1]"
  40. >
  41. <template slot="title">
  42. <JyIcon :name="group.icon" classPrefix=""></JyIcon>
  43. <span class="group-title ellipsis">{{group.label}}</span>
  44. </template>
  45. <el-menu-item-group v-if="group.children">
  46. <template slot="title"></template>
  47. <el-menu-item
  48. v-for="menu in group.children"
  49. :class="{
  50. active: activeMenu._compute._key === menu._compute._key
  51. }"
  52. :key="menu._compute._key"
  53. :index="menu._compute._key"
  54. @click="onSelectSubMenu(menu)"
  55. >
  56. {{ menu.label }}
  57. </el-menu-item>
  58. </el-menu-item-group>
  59. </el-submenu>
  60. </el-menu>
  61. </div>
  62. </div>
  63. </template>
  64. <script>
  65. import { mapActions, mapGetters, mapMutations, mapState } from 'vuex'
  66. export default {
  67. name: 'aside-menu',
  68. props: {
  69. beforeSelect: {
  70. type: Function,
  71. default: () => true
  72. }
  73. },
  74. computed: {
  75. ...mapState('work-bench/menu', [
  76. 'type',
  77. 'active'
  78. ]),
  79. ...mapGetters('work-bench/menu', [
  80. 'filterMenus',
  81. 'menuTypes',
  82. 'filterSubMenus',
  83. 'defaultOpenSubMenus',
  84. 'activeMenu'
  85. ]),
  86. },
  87. created () {},
  88. methods: {
  89. ...mapMutations('work-bench/menu', [
  90. 'setActiveOfType'
  91. ]),
  92. ...mapActions('work-bench/menu', [
  93. 'setMenuType'
  94. ]),
  95. /**
  96. * 附属菜单选中事件回调
  97. * @param menu
  98. * @param sIndex - 附属菜单索引
  99. * @param gIndex - 分组索引
  100. */
  101. async onSelectSubMenu (menu) {
  102. const canNext = await this.beforeSelect(menu)
  103. if (!canNext) {
  104. return
  105. }
  106. if (!menu?._compute) {
  107. menu._compute = {
  108. _uniqueIndexes: [this.activeMenu._compute._uniqueIndexes[0], 0, 0]
  109. }
  110. }
  111. this.setActiveOfType({
  112. type: 'group',
  113. index: menu._compute._uniqueIndexes[1]
  114. })
  115. this.setActiveOfType({
  116. type: 'sub',
  117. index: menu._compute._uniqueIndexes[2]
  118. })
  119. this.openMenuLink()
  120. },
  121. /**
  122. * 顶级菜单选中事件回调
  123. * @param menu - 菜单
  124. * @param i - 索引
  125. */
  126. async onSelectApexMenu (menu) {
  127. const canNext = await this.beforeSelect(menu)
  128. if (!canNext) {
  129. return
  130. }
  131. // 记录当前一级菜单索引
  132. this.setActiveOfType({
  133. type: 'apex',
  134. index: menu._compute._uniqueIndexes[0]
  135. })
  136. // 判断是否需要打开二级菜单
  137. if (menu?.children?.length) {
  138. this.onSelectSubMenu(menu.children[0].children[0])
  139. } else {
  140. this.openMenuLink()
  141. }
  142. },
  143. /**
  144. * 切换 全部/可用 服务状态
  145. * @param item
  146. */
  147. onSwitchMenuType (item) {
  148. this.setMenuType(item)
  149. },
  150. /**
  151. * 打开菜单链接
  152. * @param menu
  153. */
  154. openMenuLink () {
  155. const menu = this.activeMenu
  156. this.$emit('open', menu)
  157. }
  158. }
  159. }
  160. </script>
  161. <style scoped lang="scss">
  162. $aside-menu--color: #ffffff;
  163. $aside-menu--color-main: #2CB7CA;
  164. $aside-menu--color-secondary: #25A3B5;
  165. $aside-menu--color-gray: rgba(255,255,255,0.7000);
  166. $aside-menu--color-black: #2C2E33;
  167. $aside-menu--text-color: #1D1D1D;
  168. $aside-menu--text-secondary-color: #686868;
  169. $aside-menu--apex-width: 60px;
  170. $aside-menu--apex-bg: $aside-menu--color-black;
  171. .aside-menu--{
  172. &group {
  173. height: 100%;
  174. display: flex;
  175. flex-direction: row;
  176. }
  177. &abbr- {
  178. &group {
  179. display: flex;
  180. flex-direction: column;
  181. align-items: center;
  182. justify-content: space-between;
  183. width: $aside-menu--apex-width;
  184. padding: 8px 0;
  185. box-sizing: border-box;
  186. background: $aside-menu--apex-bg;
  187. font-size: 14px;
  188. font-weight: 400;
  189. }
  190. &item {
  191. display: flex;
  192. flex-direction: column;
  193. align-items: center;
  194. justify-content: center;
  195. }
  196. }
  197. &toggle- {
  198. &group {
  199. color: $aside-menu--color-gray;
  200. line-height: 16px;
  201. margin-bottom: 16px;
  202. }
  203. &item {
  204. padding: 8px 14px;
  205. text-align: center;
  206. cursor: pointer;
  207. &.active {
  208. color: $aside-menu--color-main;
  209. }
  210. }
  211. }
  212. &first- {
  213. &group {
  214. width: 100%;
  215. color: $aside-menu--color-gray;
  216. line-height: 22px;
  217. .iconfont {
  218. font-size: 18px;
  219. }
  220. }
  221. &item {
  222. min-height: 60px;
  223. display: flex;
  224. flex-direction: column;
  225. align-items: center;
  226. justify-content: center;
  227. cursor: pointer;
  228. &.active, &:hover {
  229. background: $aside-menu--color-secondary;
  230. color: $aside-menu--color;
  231. }
  232. }
  233. }
  234. &open- {
  235. &group {
  236. width: 152px;
  237. height: 100%;
  238. background-color: $aside-menu--color;
  239. .iconfont {
  240. font-size: 16px;
  241. margin-right: 8px;
  242. color: $aside-menu--text-color;
  243. }
  244. .group-title {
  245. display: inline-block;
  246. max-width: 6em;
  247. }
  248. ::v-deep {
  249. .el-menu {
  250. border: none;
  251. padding: 8px;
  252. box-sizing: border-box;
  253. background-color: inherit;
  254. &.el-menu--inline {
  255. padding: unset;
  256. }
  257. }
  258. .el-submenu__title {
  259. height: auto;
  260. font-size: 14px;
  261. font-weight: 400;
  262. color: $aside-menu--text-color;
  263. line-height: 22px;
  264. margin-top: 4px;
  265. padding: 8px;
  266. padding-left: 8px !important;
  267. }
  268. .el-menu-item {
  269. min-width: unset;
  270. height: auto;
  271. font-size: 12px;
  272. font-weight: 400;
  273. color: $aside-menu--text-secondary-color;
  274. line-height: 18px;
  275. padding: 8px;
  276. padding-left: 32px !important;
  277. white-space: normal;
  278. transition: unset;
  279. &.active,
  280. &:hover {
  281. color: $aside-menu--color-main;
  282. }
  283. }
  284. .el-submenu__title:focus,
  285. .el-menu-item:focus {
  286. background-color: inherit;
  287. }
  288. .el-submenu__title:hover,
  289. .el-submenu__title.active,
  290. .el-menu-item.active,
  291. .el-menu-item:hover {
  292. background: #EAF8FA;
  293. border-radius: 4px;
  294. }
  295. .el-submenu__title .el-submenu__icon-arrow {
  296. margin-top: -8px;
  297. right: 8px;
  298. font-family: "iconfont" !important;
  299. font-size: 16px;
  300. color: #8F9399;
  301. &::before {
  302. content: "\e656";
  303. }
  304. }
  305. .el-menu-item-group__title {
  306. display: none;
  307. }
  308. }
  309. }
  310. }
  311. }
  312. </style>