DeptConfigModal.vue 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. <template>
  2. <a-modal width="50%" v-model:visible="visible" title="部门配置" @cancel="handleCancel" @ok="editDeptHandleOk">
  3. <div :style="{ display: 'flex' }">
  4. <a-card class="card-body" title="机构" hoverable>
  5. <a-tree :data="dept_list" v-model:checked-keys="checked_keys" v-model:expanded-keys="expand_keys"
  6. :checkable="true" :show-line="true" @check="onCheck" :fieldNames="{
  7. key: 'deptId',
  8. title: 'deptName',
  9. children: 'children',
  10. }">
  11. </a-tree>
  12. </a-card>
  13. <a-card class="card-body" title="角色所属部门">
  14. <a-space wrap>
  15. <a-tag v-for="item of check_strictly" :key="item.deptId">
  16. {{ item.deptName }}
  17. </a-tag>
  18. </a-space>
  19. </a-card>
  20. </div>
  21. </a-modal>
  22. </template>
  23. <script setup>
  24. import { ref, toRefs, watch } from 'vue';
  25. // 定义组件的 props 和 emits
  26. const props = defineProps({
  27. visible: Boolean,
  28. dept_list: {
  29. type: Array,
  30. default: () => []
  31. },
  32. record: {
  33. type: Object,
  34. default: false
  35. }
  36. });
  37. const { visible, dept_list, record } = toRefs(props);
  38. const emit = defineEmits(['close', 'ok']);
  39. // 组件内部状态
  40. const checked_keys = ref([]);
  41. // 默认展开第一节
  42. const expand_keys = ref(['0']);
  43. const check_strictly = ref([]);
  44. // 递归取消所有子节点的选择
  45. const cancelChildSelection = (node, selected_nodes) => {
  46. if (node.children && node.children.length > 0) {
  47. node.children.forEach(child => {
  48. const child_index = selected_nodes.findIndex(val => val.deptId === child.deptId);
  49. if (child_index !== -1) {
  50. // 取消子节点的选择
  51. selected_nodes.splice(child_index, 1);
  52. // 递归取消子节点的选择
  53. cancelChildSelection(child, selected_nodes);
  54. }
  55. });
  56. }
  57. }
  58. // 处理树形组件的勾选变化
  59. const onCheck = (new_checked_keys, event) => {
  60. const o = { deptId: event.node.deptId, deptName: event.node.deptName };
  61. if (event.checked) {
  62. // 添加部门
  63. check_strictly.value.push(o);
  64. } else {
  65. // 移除部门
  66. const dept_index = check_strictly.value.findIndex((val) => val.deptId === event.node.deptId);
  67. check_strictly.value.splice(dept_index, 1);
  68. // 递归取消所有子节点的选择
  69. cancelChildSelection(event.node, check_strictly.value);
  70. }
  71. };
  72. // 处理取消事件
  73. const handleCancel = () => {
  74. visible.value = false;
  75. emit('close');
  76. };
  77. // 处理确认事件
  78. const editDeptHandleOk = () => {
  79. emit('ok', checked_keys.value);
  80. };
  81. watch(() => props.record, (newVal) => {
  82. if (newVal?.dept) {
  83. newVal.dept.forEach((val) => {
  84. check_strictly.value.push({
  85. deptId: val.deptId,
  86. deptName: val.deptName
  87. });
  88. checked_keys.value.push(val.deptId);
  89. expand_keys.value.push(val.deptId);
  90. });
  91. }
  92. });
  93. </script>
  94. <style lang="css" scoped>
  95. .card-body {
  96. width: 460px;
  97. height: 500px;
  98. overflow-y: auto;
  99. }
  100. .card-body:first-child {
  101. margin-right: 16px;
  102. }
  103. </style>