RoleDrawer.vue 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. <template>
  2. <el-drawer :title="title" v-model="drawerOpened" @close="reset">
  3. <el-form
  4. label-position="left"
  5. label-width="80px"
  6. :model="formData"
  7. :rules="formRules"
  8. ref="formInstance"
  9. >
  10. <el-form-item label="角色名称" prop="roleName">
  11. <el-input placeholder="角色名称" v-model="formData.roleName" />
  12. </el-form-item>
  13. <el-form-item label="角色权限">
  14. <PermissioTreenCard title="相机权限" :tree-data="cameraPermTreeData" ref="cameraCardInstance" />
  15. <PermissioTreenCard title="菜单权限" :tree-data="menuPermTreeData" ref="menuCardInstance" />
  16. <PermissioTreenCard title="功能权限" :tree-data="funcPermTreeData" ref="funcCardInstance" />
  17. </el-form-item>
  18. <el-form-item label="备注" prop="remark">
  19. <el-input type="textarea" placeholder="备注" v-model="formData.remark" />
  20. </el-form-item>
  21. </el-form>
  22. <template #footer>
  23. <el-button @click="reset">重置</el-button>
  24. <el-button type="primary" @click="submit">提交</el-button>
  25. </template>
  26. </el-drawer>
  27. </template>
  28. <script setup lang="ts">
  29. import { reactive, ref, computed, toRaw } from 'vue';
  30. import PermissioTreenCard from './PermissionTreeCard.vue';
  31. import { RoleForm, Role, AssignedPermissions } from '@/types/role/type';
  32. import { FormRules, FormInstance, ElMessage } from 'element-plus';
  33. import useMenuPermTree from '../hooks/useMenuPermissionTree';
  34. import useFuncPermTree from '../hooks/useFunctionPermissionTree';
  35. import useCameraPermTree from '../hooks/useCameraPermissionTree';
  36. import { createRole, editRole, getAssignedPerms } from '@/api/system/role';
  37. import { PermissionTreeKey } from '@/types/permission/type';
  38. defineProps<{
  39. title: string;
  40. }>();
  41. const emits = defineEmits<{
  42. (e: 'submitted'): void; // 提交之后触发的事件
  43. }>();
  44. const { cameraPermTreeData } = useCameraPermTree();
  45. const { menuPermTreeData } = useMenuPermTree();
  46. const { funcPermTreeData} = useFuncPermTree();
  47. const drawerOpened = ref(false);
  48. const cameraCardInstance = ref<InstanceType<typeof PermissioTreenCard>>();
  49. const menuCardInstance = ref<InstanceType<typeof PermissioTreenCard>>();
  50. const funcCardInstance = ref<InstanceType<typeof PermissioTreenCard>>();
  51. // 表单相关
  52. const defaultFormData = (): RoleForm => ({
  53. id: null,
  54. roleName: '',
  55. remark: '',
  56. cameraIds: [],
  57. menuIds: [],
  58. permIds: [],
  59. });
  60. const formData = reactive<RoleForm>(defaultFormData());
  61. const formRules: FormRules = {
  62. roleName: { required: true, trigger: 'blur', message: '请填写角色名称' },
  63. remark: {},
  64. };
  65. const formInstance = ref<FormInstance>();
  66. const isEditing = computed(() => formData.id != null);
  67. /**
  68. * 打开 drawer。如果未传递 roleId,表示创建角色;反之,表示编辑角色
  69. * @param roleId 可选
  70. */
  71. const open = (role?: Role) => {
  72. if (role) {
  73. formData.id = role.id;
  74. formData.roleName = role.roleName;
  75. formData.remark = role.remark;
  76. getAssignedPermissions(role.id);
  77. // TODO: 获取已拥有的权限
  78. }
  79. drawerOpened.value = true;
  80. };
  81. /**
  82. * 获取当前角色已分配的权限数据,并更新相应的权限数
  83. */
  84. const getAssignedPermissions = async (roleId: number) => {
  85. try {
  86. const result = await getAssignedPerms(roleId);
  87. displayAssignedPermissions(result);
  88. } catch (e) {
  89. console.error(e);
  90. }
  91. }
  92. const displayAssignedPermissions = (result: AssignedPermissions) => {
  93. // 相机树很有可能会有 id 重复的情况,比如说 一个camera id 和 一个 workspace id 相同,这样会导致 tree 节点 value 不唯一,因此需要给个前缀
  94. cameraCardInstance.value?.setAssignedPermissions(result.cameraIds ?? [], 'camera');
  95. menuCardInstance.value?.setAssignedPermissions(result.menuIds ?? []);
  96. funcCardInstance.value?.setAssignedPermissions(result.permIds ?? []);
  97. }
  98. /**
  99. * 重置表单
  100. */
  101. const reset = () => {
  102. formInstance.value?.resetFields();
  103. Object.assign(formData, defaultFormData());
  104. cameraCardInstance.value?.reset();
  105. menuCardInstance.value?.reset();
  106. funcCardInstance.value?.reset();
  107. };
  108. /**
  109. * 提交。创建和编辑统一
  110. */
  111. const submit = async () => {
  112. formData.cameraIds = cleanCameraPermissions(cameraCardInstance.value!.getSelectedPermissions());
  113. formData.menuIds = menuCardInstance.value!.getSelectedPermissions();
  114. formData.permIds = funcCardInstance.value!.getSelectedPermissions();
  115. const api = isEditing.value ? editRole : createRole;
  116. try {
  117. await api(toRaw(formData));
  118. drawerOpened.value = false;
  119. ElMessage.success('提交成功');
  120. // 让父组件更新列表
  121. emits('submitted');
  122. } catch (e) {
  123. console.error(e);
  124. }
  125. }
  126. /**
  127. * 获取到的相机的权限码是 camera-xxx, 例如 camera-11, 提交后端转换成数字 11
  128. */
  129. const cleanCameraPermissions = (perms: PermissionTreeKey[]) => {
  130. return perms.map(perm => {
  131. if (typeof perm === 'string' && perm.includes('-')) {
  132. const splits = perm.split('-');
  133. return +splits[1];
  134. }
  135. // 否则正常返回
  136. return perm;
  137. });
  138. }
  139. defineExpose({ open });
  140. </script>