MenuTree.vue 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. <!--------------------------------
  2. - @LastEditTime: 2024/04/01 15:51:34
  3. | https://isme.top
  4. --------------------------------->
  5. <template>
  6. <div>
  7. <n-space vertical :size="12">
  8. <h3>菜单</h3>
  9. <div class="flex">
  10. <n-input v-model:value="pattern" placeholder="搜索" clearable />
  11. <NButton class="ml-12" type="primary" @click="handleAdd()">
  12. <i class="i-material-symbols:add mr-4 text-14" />
  13. 新增
  14. </NButton>
  15. </div>
  16. <n-tree
  17. :show-irrelevant-nodes="false"
  18. :pattern="pattern"
  19. :data="treeData"
  20. :selected-keys="[currentMenu?.code]"
  21. :render-prefix="renderPrefix"
  22. :render-suffix="renderSuffix"
  23. :on-update:selected-keys="onSelect"
  24. key-field="code"
  25. label-field="name"
  26. block-line default-expand-all
  27. />
  28. </n-space>
  29. <ResAddOrEdit ref="modalRef" :menus="treeData" @refresh="(data) => emit('refresh', data)" />
  30. </div>
  31. </template>
  32. <script setup>
  33. import { NButton } from 'naive-ui'
  34. import { withModifiers } from 'vue'
  35. import api from '../api'
  36. import ResAddOrEdit from './ResAddOrEdit.vue'
  37. defineProps({
  38. treeData: {
  39. type: Array,
  40. default: () => [],
  41. },
  42. currentMenu: {
  43. type: Object,
  44. default: () => null,
  45. },
  46. })
  47. const emit = defineEmits(['refresh', 'update:currentMenu'])
  48. const pattern = ref('')
  49. const modalRef = ref(null)
  50. async function handleAdd(data = {}) {
  51. modalRef.value?.handleOpen({
  52. action: 'add',
  53. title: '新增菜单',
  54. row: { type: 'MENU', ...data },
  55. okText: '保存',
  56. })
  57. }
  58. function onSelect(keys, option, { action, node }) {
  59. emit('update:currentMenu', action === 'select' ? node : null)
  60. }
  61. function renderPrefix({ option }) {
  62. return h('i', { class: `${option.icon}?mask text-16` })
  63. }
  64. function renderSuffix({ option }) {
  65. return [
  66. h(
  67. NButton,
  68. {
  69. text: true,
  70. type: 'primary',
  71. title: '新增下级菜单',
  72. size: 'tiny',
  73. onClick: withModifiers(() => handleAdd({ parentId: option.id }), ['stop']),
  74. },
  75. { default: () => '新增' },
  76. ),
  77. h(
  78. NButton,
  79. {
  80. text: true,
  81. type: 'error',
  82. size: 'tiny',
  83. style: 'margin-left: 12px;',
  84. onClick: withModifiers(() => handleDelete(option), ['stop']),
  85. },
  86. { default: () => '删除' },
  87. ),
  88. ]
  89. }
  90. function handleDelete(item) {
  91. $dialog.confirm({
  92. content: `确认删除【${item.name}】?`,
  93. async confirm() {
  94. try {
  95. $message.loading('正在删除', { key: 'deleteMenu' })
  96. await api.deletePermission(item.id)
  97. $message.success('删除成功', { key: 'deleteMenu' })
  98. emit('refresh')
  99. emit('update:currentMenu', null)
  100. }
  101. catch (error) {
  102. console.error(error)
  103. $message.destroy('deleteMenu')
  104. }
  105. },
  106. })
  107. }
  108. </script>