create.vue 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. <template>
  2. <el-form :model="formData" label-width="120px" ref="form" v-loading="loading" class="pr-6">
  3. <el-form-item label="上级角色" prop="parent_id" v-if="!primary">
  4. <el-cascader
  5. :options="roles"
  6. name="parent_id"
  7. v-model="formData.parent_id"
  8. clearable
  9. check-strictly
  10. class="w-full"
  11. @change="getPermissions"
  12. :props="{ value: 'id', label: 'role_name', checkStrictly: true }"
  13. />
  14. </el-form-item>
  15. <el-form-item
  16. label="角色名称"
  17. prop="role_name"
  18. :rules="[
  19. {
  20. required: true,
  21. message: '角色名称必须填写',
  22. },
  23. ]"
  24. >
  25. <el-input v-model="formData.role_name" name="role_name" clearable />
  26. </el-form-item>
  27. <el-form-item
  28. label="角色标识"
  29. prop="identify"
  30. :rules="[
  31. {
  32. required: true,
  33. message: '角色标识必须填写',
  34. },
  35. ]"
  36. >
  37. <el-input v-model="formData.identify" name="identify" clearable />
  38. </el-form-item>
  39. <el-form-item label="角色描述" prop="description">
  40. <el-input v-model="formData.description" name="description" clearable type="textarea" />
  41. </el-form-item>
  42. <el-form-item label="数据权限" prop="data_range">
  43. <Select v-model="formData.data_range" name="data_range" clearable api="dataRange" class="w-full" />
  44. </el-form-item>
  45. <el-form-item
  46. label="自定义权限"
  47. prop="departments"
  48. v-if="showDepartments"
  49. :rules="[
  50. {
  51. required: true,
  52. message: '自定义权限必须选择',
  53. },
  54. ]"
  55. >
  56. <el-tree-select
  57. v-model="formData.departments"
  58. value-key="id"
  59. class="w-full"
  60. :data="departments"
  61. :render-after-expand="false"
  62. show-checkbox
  63. multiple
  64. :props="{ value: 'id', label: 'department_name' }"
  65. />
  66. </el-form-item>
  67. <el-form-item label="角色权限" prop="permissions">
  68. <el-tree
  69. ref="permissionTree"
  70. v-model="formData.permissions"
  71. :data="permissions"
  72. node-key="id"
  73. class="w-full"
  74. :props="{ label: 'permission_name', value: 'id' }"
  75. show-checkbox
  76. :default-expand-all="false"
  77. @check="selectPermissions"
  78. :empty-text="permissionLoadingText"
  79. />
  80. </el-form-item>
  81. <div class="flex justify-end">
  82. <el-button type="primary" @click="submitForm(form)">{{ $t('system.confirm') }}</el-button>
  83. </div>
  84. </el-form>
  85. </template>
  86. <script lang="ts" setup>
  87. import {useCreate} from '/admin/composables/curd/useCreate'
  88. import {useShow} from '/admin/composables/curd/useShow'
  89. import {nextTick, onMounted, ref, unref, watch} from 'vue'
  90. import http from '/admin/support/http'
  91. const props = defineProps({
  92. primary: String | Number,
  93. api: String,
  94. hasPermissions: Array<Object>,
  95. })
  96. const emit = defineEmits(['close'])
  97. const { formData, form, loading, submitForm, close, beforeCreate, beforeUpdate } = useCreate(props.api, props.primary)
  98. if (props.primary) {
  99. const { afterShow } = useShow(props.api, props.primary, formData)
  100. afterShow.value = formData => {
  101. const data = unref(formData)
  102. data.parent_id = data.parent_id ? [data.parent_id] : 0
  103. if (!data.data_range) {
  104. data.data_range = null
  105. }
  106. formData.value = data
  107. }
  108. }
  109. const roles = ref()
  110. const permissions = ref()
  111. // 权限树对象
  112. const permissionTree = ref()
  113. // 部门
  114. const departments = ref()
  115. const showDepartments = ref<boolean>(false)
  116. const permissionLoadingText = ref<string>('加载中...')
  117. const getPermissions = async (value: number = 0) => {
  118. if (value) {
  119. http.get('permissions/roles/' + getParent(value)).then(r => {
  120. permissions.value = r.data.data.permissions
  121. setCheckedPermissions()
  122. })
  123. } else {
  124. http.get('permissions/permissions', { from: 'role' }).then(r => {
  125. permissions.value = r.data.data
  126. setCheckedPermissions()
  127. })
  128. }
  129. }
  130. const setCheckedPermissions = () => {
  131. nextTick(() => {
  132. props.hasPermissions.forEach(p => {
  133. permissionTree.value.setChecked(p.id, true, false)
  134. })
  135. })
  136. if (!permissions.value.length) {
  137. permissionLoadingText.value = '暂无数据'
  138. }
  139. }
  140. const getRoles = () => {
  141. http.get(props.api, { id: props.primary ? props.primary : '' }).then(r => {
  142. roles.value = r.data.data
  143. })
  144. }
  145. const getDepartments = () => {
  146. http.get('permissions/departments').then(r => {
  147. departments.value = r.data.data
  148. })
  149. }
  150. onMounted(() => {
  151. getRoles()
  152. getPermissions()
  153. getDepartments()
  154. close(() => emit('close'))
  155. watch(
  156. formData,
  157. function (value) {
  158. // 如果数据权限是自定义数据
  159. showDepartments.value = value.data_range === 2
  160. },
  161. { deep: true },
  162. )
  163. })
  164. const selectPermissions = (checkedNodes, checkedKeys) => {
  165. formData.value.permissions = checkedKeys.checkedKeys.concat(checkedKeys.halfCheckedKeys).sort()
  166. }
  167. // 创建前的钩子
  168. beforeCreate.value = () => {
  169. formData.value.parent_id = getParent(formData.value.parent_id)
  170. }
  171. // 更新前的钩子
  172. beforeUpdate.value = () => {
  173. formData.value.parent_id = getParent(formData.value.parent_id)
  174. }
  175. const getParent = (parentId: any) => {
  176. return typeof parentId === 'undefined' ? 0 : parentId[parentId.length - 1]
  177. }
  178. </script>
  179. <style scoped>
  180. :deep(.el-tree .el-tree__empty-block .el-tree__empty-text) {
  181. @apply left-10 top-4;
  182. }
  183. </style>