MenuPreviewer.vue 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. <template>
  2. <div class="menu_bottom" v-for="(parent, x) of menuList" :key="x">
  3. <!-- 一级菜单 -->
  4. <div
  5. @click="menuClicked(parent, x)"
  6. class="menu_item"
  7. :class="{ active: props.activeIndex === `${x}` }"
  8. >
  9. <Icon icon="ep:fold" color="black" />{{ parent.name }}
  10. </div>
  11. <!-- 以下为二级菜单-->
  12. <div class="submenu" v-if="parentIndex === x && parent.children">
  13. <div class="subtitle menu_bottom" v-for="(child, y) in parent.children" :key="y">
  14. <div
  15. class="menu_subItem"
  16. v-if="parent.children"
  17. :class="{ active: props.activeIndex === `${x}-${y}` }"
  18. @click="subMenuClicked(child, x, y)"
  19. >
  20. {{ child.name }}
  21. </div>
  22. </div>
  23. <!-- 二级菜单加号, 当长度 小于 5 才显示二级菜单的加号 -->
  24. <div
  25. class="menu_bottom menu_addicon"
  26. v-if="!parent.children || parent.children.length < 5"
  27. @click="addSubMenu(x, parent)"
  28. >
  29. <Icon icon="ep:plus" class="plus" />
  30. </div>
  31. </div>
  32. </div>
  33. <!-- 一级菜单加号 -->
  34. <div class="menu_bottom menu_addicon" v-if="menuList.length < 3" @click="addMenu">
  35. <Icon icon="ep:plus" class="plus" />
  36. </div>
  37. </template>
  38. <script setup lang="ts">
  39. import { Menu } from './types'
  40. const props = defineProps<{
  41. modelValue: Menu[]
  42. activeIndex: string
  43. parentIndex: number
  44. accountId?: number
  45. }>()
  46. const emit = defineEmits<{
  47. (e: 'update:modelValue', v: Menu[])
  48. (e: 'menu-clicked', parent: Menu, x: number)
  49. (e: 'submenu-clicked', child: Menu, x: number, y: number)
  50. }>()
  51. const menuList = computed<Menu[]>({
  52. get: () => props.modelValue,
  53. set: (val) => emit('update:modelValue', val)
  54. })
  55. // 添加横向一级菜单
  56. const addMenu = () => {
  57. const index = menuList.value.length
  58. const menu = {
  59. name: '菜单名称',
  60. children: [],
  61. reply: {
  62. // 用于存储回复内容
  63. type: 'text',
  64. accountId: props.accountId // 保证组件里,可以使用到对应的公众号
  65. }
  66. }
  67. menuList.value[index] = menu
  68. menuClicked(menu, index - 1)
  69. }
  70. // 添加横向二级菜单;parent 表示要操作的父菜单
  71. const addSubMenu = (i: number, parent: any) => {
  72. const subMenuKeyLength = parent.children.length // 获取二级菜单key长度
  73. const addButton = {
  74. name: '子菜单名称',
  75. reply: {
  76. // 用于存储回复内容
  77. type: 'text',
  78. accountId: props.accountId // 保证组件里,可以使用到对应的公众号
  79. }
  80. }
  81. parent.children[subMenuKeyLength] = addButton
  82. subMenuClicked(parent.children[subMenuKeyLength], i, subMenuKeyLength)
  83. }
  84. const menuClicked = (parent: Menu, x: number) => {
  85. emit('menu-clicked', parent, x)
  86. }
  87. const subMenuClicked = (child: Menu, x: number, y: number) => {
  88. emit('submenu-clicked', child, x, y)
  89. }
  90. </script>
  91. <style lang="scss" scoped>
  92. .menu_bottom {
  93. position: relative;
  94. display: inline-block;
  95. float: left;
  96. width: 85.5px;
  97. text-align: center;
  98. cursor: pointer;
  99. background-color: #fff;
  100. border: 1px solid #ebedee;
  101. box-sizing: border-box;
  102. &.menu_addicon {
  103. height: 46px;
  104. line-height: 46px;
  105. .plus {
  106. color: #2bb673;
  107. }
  108. }
  109. .menu_item {
  110. display: flex;
  111. width: 100%;
  112. height: 44px;
  113. line-height: 44px;
  114. // text-align: center;
  115. box-sizing: border-box;
  116. align-items: center;
  117. justify-content: center;
  118. &.active {
  119. border: 1px solid #2bb673;
  120. }
  121. }
  122. .menu_subItem {
  123. height: 44px;
  124. line-height: 44px;
  125. text-align: center;
  126. box-sizing: border-box;
  127. &.active {
  128. border: 1px solid #2bb673;
  129. }
  130. }
  131. }
  132. /* 第二级菜单 */
  133. .submenu {
  134. position: absolute;
  135. bottom: 45px;
  136. width: 85.5px;
  137. .subtitle {
  138. background-color: #fff;
  139. box-sizing: border-box;
  140. }
  141. }
  142. </style>