index.vue 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. <template>
  2. <work-bench-layout>
  3. <template v-slot:nav>
  4. <router-view name="nav">
  5. <template v-slot:nav-user-info="{ info }">
  6. <slot name="nav-user-info" v-bind:info="info"></slot>
  7. </template>
  8. </router-view>
  9. </template>
  10. <template v-slot:menu>
  11. <router-view v-show="showMenu" name="menu" :before-select="onBeforeSelect"
  12. @open="onOpenMenu"></router-view>
  13. </template>
  14. <router-view id="work-bench-container"></router-view>
  15. </work-bench-layout>
  16. </template>
  17. <script>
  18. import WorkBenchLayout from './layout'
  19. import { mapActions, mapGetters } from 'vuex'
  20. import { checkCanNextMenu } from '../../utils/menu'
  21. export default {
  22. name: 'work-bench',
  23. components: {
  24. [WorkBenchLayout.name]: WorkBenchLayout
  25. },
  26. data () {
  27. return {
  28. nowTryMenuStatus: true
  29. }
  30. },
  31. computed: {
  32. ...mapGetters('work-bench/dialog', [
  33. 'dialogOptions'
  34. ]),
  35. showMenu () {
  36. return this.nowTryMenuStatus && this.$route.query.aside !== '0'
  37. }
  38. },
  39. async beforeRouteEnter (to, from, next) {
  40. next(async (vm) => {
  41. await vm.getMenus()
  42. await vm.checkNextMenu(to)
  43. })
  44. },
  45. async beforeRouteUpdate (to, from, next) {
  46. await this.checkNextMenu(to)
  47. next()
  48. },
  49. methods: {
  50. ...mapActions('work-bench', [
  51. 'getMenus'
  52. ]),
  53. ...mapActions('work-bench/menu', [
  54. 'tryMatchMenu',
  55. 'tryFindMenu'
  56. ]),
  57. ...mapActions('work-bench/dialog', [
  58. 'openDialog'
  59. ]),
  60. /**
  61. * 更新路由时检验菜单
  62. * @param to
  63. * @returns {Promise<void>}
  64. */
  65. async checkNextMenu (to) {
  66. const findMenuInfo = await this.tryFindMenu({
  67. link: to.query.link || to.fullPath
  68. })
  69. // 没有找到匹配的菜单时,用于隐藏侧边菜单
  70. this.nowTryMenuStatus = Boolean(findMenuInfo.findMenu)
  71. // 仅在有内容时进行菜单选中的尝试
  72. if (this.nowTryMenuStatus) {
  73. const canNext = checkCanNextMenu.apply(this, [findMenuInfo.findMenu])
  74. if (canNext) {
  75. this.tryMatchMenu({
  76. link: to.query.link || to.fullPath,
  77. find: findMenuInfo
  78. })
  79. }
  80. }
  81. },
  82. /**
  83. * 默认前置校验
  84. * @param menu
  85. * @returns {boolean}
  86. */
  87. beforeSelect (menu) {
  88. return checkCanNextMenu.apply(this, [menu])
  89. },
  90. /**
  91. * 打开菜单前置校验钩子
  92. * @param menu
  93. * @returns {Promise<boolean>}
  94. */
  95. async onBeforeSelect (menu) {
  96. let canNext = true
  97. const spareFn = this.beforeSelect.bind(this)
  98. canNext = await new Promise((resolve) => {
  99. const next = (result) => {
  100. resolve(Boolean(result))
  101. }
  102. this.$BRACE.$emit({
  103. fKey: 'onBeforeSelect',
  104. spareFn: (menu, next) => {
  105. next(spareFn(menu))
  106. }
  107. }, menu, next)
  108. })
  109. return canNext
  110. },
  111. /**
  112. * 调用公共函数打开页面
  113. * @param menu
  114. */
  115. openMenu (menu) {
  116. this.$BRACE.methods.open({
  117. route: menu
  118. })
  119. },
  120. /**
  121. * 打开菜单事件发布
  122. * @param menu
  123. */
  124. onOpenMenu (menu) {
  125. this.$BRACE.$emit({
  126. fKey: 'onOpenMenu',
  127. spareFn: (menu, next) => {
  128. next(menu)
  129. }
  130. }, menu, this.openMenu.bind(this))
  131. }
  132. }
  133. }
  134. </script>
  135. <style lang="scss">
  136. @import "../../style/index";
  137. .content-shadow {
  138. background: #FFFFFF;
  139. box-shadow: 0px 4px 8px 0px rgba(0, 0, 0, 0.0800);
  140. border-radius: 5px 5px 5px 5px;
  141. }
  142. .abnormal-tip {
  143. margin: $padding-lg;
  144. padding: $padding-xl;
  145. @extend .content-shadow;
  146. }
  147. .custom-message-box,
  148. .custom-alert-box {
  149. width: 380px !important;
  150. border-radius: 8px;
  151. .custom-confirm-btn {
  152. margin-top: 12px;
  153. width: 132px;
  154. height: 36px;
  155. background: #2cb7ca;
  156. border-radius: 6px;
  157. border: 0;
  158. font-size: 16px;
  159. }
  160. .el-message-box__message {
  161. font-size: 14px;
  162. color: #686868;
  163. }
  164. .el-message-box__headerbtn .el-message-box__close{
  165. display: inline-block;
  166. width: 20px;
  167. height: 20px;
  168. background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAACXBIWXMAABYlAAAWJQFJUiTwAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAFZSURBVHgB7ZfLjYMwEIaH151OkhJSA0KC26a0zQ0kRA2UsOkkd17rQUJCq2Bs/8Pm4u+EEP75NBbjgcjj8Xg+T9u2l7quv0gIzqqq6mLybHj0AMsNw9AFQfAtIckZnBWGYWciGZCBnLpM13vzPN+LongQILe59Zqm6VaW5XNvjbaCfd9ft3KMayXfyDFpHMdX3TptBTXBVpXcy1DbfM/z/AEJopKInLGgqyQqZyVoKykhZy1oKikl5yR4JLmECsktWeTInuQ7XOUYZ0HGRBKRYyBBRieJyi0ZdCLjOBLK6VuMnN3Mv3wkiKTTFuv63NpqtiCjmlij3n4QEgOGk6DNCSElCQ8LulYiIQmNWyZ9DpV0HlhtmjAiGZwth0pq20ySJD8q9EWgHMMSf1sQZ/M7dOsOt5j/7NSR1anwVOJsXSvJclEU3bIsexIKSzZNI/rjzpnk8Xg8n+cXjfMeGT1wE4IAAAAASUVORK5CYII=) no-repeat center;
  169. background-size: contain;
  170. }
  171. .el-icon-close:before{
  172. content: '';
  173. }
  174. }
  175. .custom-alert-box {
  176. padding-bottom: 32px!important;
  177. .el-message-box__header{
  178. padding-top: 32px!important;
  179. }
  180. .el-message-box__title{
  181. line-height: 28px;
  182. }
  183. .el-message-box__btns{
  184. display: flex;
  185. align-items: center;
  186. flex-direction: row-reverse;
  187. justify-content: space-between;
  188. padding: 0 32px;
  189. }
  190. .custom-confirm-btn{
  191. margin-left: 0!important;
  192. }
  193. .custom-default-btn,
  194. .custom-default-btn:hover,
  195. .custom-default-btn:focus{
  196. width: 132px;
  197. height: 36px;
  198. margin-top: 12px;
  199. border-radius: 6px;
  200. background-color: #fff;
  201. border: 1px solid #DCDFE6;
  202. color: #686868;
  203. font-size: 16px;
  204. }
  205. }
  206. </style>