CustomerLimitConfigForm.vue 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. <template>
  2. <Dialog :title="dialogTitle" v-model="dialogVisible">
  3. <el-form
  4. ref="formRef"
  5. :model="formData"
  6. :rules="formRules"
  7. label-width="200px"
  8. v-loading="formLoading"
  9. >
  10. <el-form-item label="规则适用人群" prop="userIds">
  11. <el-tree-select
  12. v-model="formData.userIds"
  13. :data="userTree"
  14. :props="defaultProps"
  15. multiple
  16. filterable
  17. check-on-click-node
  18. node-key="id"
  19. placeholder="请选择规则适用人群"
  20. />
  21. </el-form-item>
  22. <el-form-item label="规则适用部门" prop="deptIds">
  23. <el-tree-select
  24. v-model="formData.deptIds"
  25. :data="deptTree"
  26. :props="defaultProps"
  27. multiple
  28. filterable
  29. check-strictly
  30. node-key="id"
  31. placeholder="请选择规则适用部门"
  32. />
  33. </el-form-item>
  34. <el-form-item
  35. :label="
  36. formData.type === LimitConfType.CUSTOMER_QUANTITY_LIMIT
  37. ? '拥有客户数上限'
  38. : '锁定客户数上限'
  39. "
  40. prop="maxCount"
  41. >
  42. <el-input-number v-model="formData.maxCount" placeholder="请输入数量上限" />
  43. </el-form-item>
  44. <el-form-item
  45. label="成交客户是否占用拥有客户数"
  46. v-if="formData.type === LimitConfType.CUSTOMER_QUANTITY_LIMIT"
  47. prop="dealCountEnabled"
  48. >
  49. <el-switch v-model="formData.dealCountEnabled" />
  50. </el-form-item>
  51. </el-form>
  52. <template #footer>
  53. <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
  54. <el-button @click="dialogVisible = false">取 消</el-button>
  55. </template>
  56. </Dialog>
  57. </template>
  58. <script setup lang="ts">
  59. import * as CustomerLimitConfigApi from '@/api/crm/customer/limitConfig'
  60. import * as DeptApi from '@/api/system/dept'
  61. import { defaultProps, handleTree } from '@/utils/tree'
  62. import * as UserApi from '@/api/system/user'
  63. import { cloneDeep } from 'lodash-es'
  64. import { LimitConfType } from '@/api/crm/customer/limitConfig'
  65. const { t } = useI18n() // 国际化
  66. const message = useMessage() // 消息弹窗
  67. const dialogVisible = ref(false) // 弹窗的是否展示
  68. const dialogTitle = ref('') // 弹窗的标题
  69. const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
  70. const formType = ref('') // 表单的类型:create - 新增;update - 修改
  71. const formData = ref({
  72. id: undefined,
  73. type: LimitConfType.CUSTOMER_LOCK_LIMIT, // 给个默认值,避免 IDE 报错
  74. userIds: undefined,
  75. deptIds: undefined,
  76. maxCount: undefined,
  77. dealCountEnabled: false
  78. })
  79. const formRules = reactive({
  80. type: [{ required: true, message: '规则类型不能为空', trigger: 'change' }],
  81. maxCount: [{ required: true, message: '数量上限不能为空', trigger: 'blur' }]
  82. })
  83. const formRef = ref() // 表单 Ref
  84. // TODO @非繁人:看看怎么搞个部门选择组件
  85. const deptTree = ref() // 部门树形结构
  86. const userTree = ref() // 用户树形结构
  87. /** 打开弹窗 */
  88. const open = async (type: string, limitConfType: LimitConfType, id?: number) => {
  89. dialogVisible.value = true
  90. dialogTitle.value = t('action.' + type)
  91. formType.value = type
  92. resetForm()
  93. // 修改时,设置数据
  94. if (id) {
  95. formLoading.value = true
  96. try {
  97. formData.value = await CustomerLimitConfigApi.getCustomerLimitConfig(id)
  98. } finally {
  99. formLoading.value = false
  100. }
  101. } else {
  102. formData.value.type = limitConfType
  103. }
  104. // 获得部门树
  105. await getDeptTree()
  106. // 获得用户
  107. await getUserTree()
  108. }
  109. defineExpose({ open }) // 提供 open 方法,用于打开弹窗
  110. /** 提交表单 */
  111. const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
  112. const submitForm = async () => {
  113. // 校验表单
  114. if (!formRef) return
  115. const valid = await formRef.value.validate()
  116. if (!valid) return
  117. // 提交请求
  118. formLoading.value = true
  119. try {
  120. const data = formData.value as unknown as CustomerLimitConfigApi.CustomerLimitConfigVO
  121. if (formType.value === 'create') {
  122. await CustomerLimitConfigApi.createCustomerLimitConfig(data)
  123. message.success(t('common.createSuccess'))
  124. } else {
  125. await CustomerLimitConfigApi.updateCustomerLimitConfig(data)
  126. message.success(t('common.updateSuccess'))
  127. }
  128. dialogVisible.value = false
  129. // 发送操作成功的事件
  130. emit('success')
  131. } finally {
  132. formLoading.value = false
  133. }
  134. }
  135. /** 重置表单 */
  136. const resetForm = () => {
  137. formData.value = {
  138. id: undefined,
  139. type: LimitConfType.CUSTOMER_LOCK_LIMIT,
  140. userIds: undefined,
  141. deptIds: undefined,
  142. maxCount: undefined,
  143. dealCountEnabled: false
  144. }
  145. formRef.value?.resetFields()
  146. }
  147. /**
  148. * 获取部门树
  149. */
  150. const getDeptTree = async () => {
  151. const res = await DeptApi.getSimpleDeptList()
  152. deptTree.value = []
  153. deptTree.value.push(...handleTree(res))
  154. }
  155. /**
  156. * 获取用户树
  157. */
  158. const getUserTree = async () => {
  159. const res = await UserApi.getAllUser()
  160. userTree.value = []
  161. userTree.value = cloneDeep(unref(deptTree))
  162. const deptUserMap = {}
  163. res.forEach((user) => {
  164. if (user.dept) {
  165. if (!deptUserMap[user.deptId]) {
  166. deptUserMap[user.deptId] = []
  167. }
  168. deptUserMap[user.deptId].push(user)
  169. }
  170. })
  171. handleUserData(userTree.value, deptUserMap)
  172. }
  173. // TODO @非繁人:看看怎么搞个用户选择的组件
  174. /**
  175. * 处理用户树
  176. *
  177. * @param deptTree
  178. * @param deptUserMap
  179. */
  180. const handleUserData = (deptTree, deptUserMap) => {
  181. for (let i = 0; i < deptTree.length; i++) {
  182. // 如果是用户,就不用继续找部门下的用户
  183. if (deptTree[i].isUser) {
  184. continue
  185. }
  186. const users = deptUserMap[deptTree[i].id]
  187. if (users) {
  188. if (!deptTree[i].children) {
  189. deptTree[i].children = []
  190. }
  191. deptTree[i].children.push(
  192. ...users.map((user) => {
  193. return {
  194. id: user.id,
  195. name: user.username + '-' + user.nickname,
  196. isUser: true,
  197. // 用户状态为关闭
  198. disabled: user.status === 1
  199. }
  200. })
  201. )
  202. }
  203. if (deptTree[i].children && deptTree[i].children.length !== 0) {
  204. handleUserData(deptTree[i].children, deptUserMap)
  205. }
  206. // 非人员选项禁用
  207. deptTree[i].disabled = true
  208. // 将非人员的 id 置为空
  209. deptTree[i].id = 'null'
  210. }
  211. }
  212. </script>