useTaskSelectHandlers.ts 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347
  1. import type { Ref } from 'vue'
  2. import type { PharmacyItem } from '@/services/modules/task/entitySelector/type'
  3. import { getListDrugTableApi } from '@/services/modules/task/taskFrom/index'
  4. import type {
  5. DynamicFormFieldValue,
  6. DynamicFormState,
  7. FieldValue,
  8. TaskFieldConfigViewItem,
  9. TaskFieldOption,
  10. } from './useTaskForm'
  11. export interface SingleSelectChangeEvent {
  12. previousValue: FieldValue
  13. value: string
  14. label: string
  15. selectedItem: TaskFieldOption
  16. }
  17. interface UseTaskSelectHandlersOptions {
  18. taskTypeId: Ref<string>
  19. form: Ref<DynamicFormState>
  20. taskFieldConfigList: Ref<TaskFieldConfigViewItem[]>
  21. }
  22. /**
  23. * 动态表单选择器业务处理。
  24. *
  25. * 统一处理:
  26. * 1. 单选打开前逻辑
  27. * 2. 单选值变化逻辑
  28. * 3. 多选打开前逻辑
  29. * 4. 字段查找
  30. * 5. 表单值读取和修改
  31. * 6. 字段 options 修改
  32. */
  33. export const useTaskSelectHandlers = ({
  34. taskTypeId,
  35. form,
  36. taskFieldConfigList,
  37. }: UseTaskSelectHandlersOptions) => {
  38. /**
  39. * 根据 alias 查找字段配置。
  40. */
  41. const findFieldByAlias = (alias: string): TaskFieldConfigViewItem | undefined => {
  42. return taskFieldConfigList.value.find((item) => item.alias === alias)
  43. }
  44. /**
  45. * 根据字段配置获取对应表单值。
  46. */
  47. const getFieldFormValue = (field: TaskFieldConfigViewItem): DynamicFormFieldValue | undefined => {
  48. return form.value.value[field.id]
  49. }
  50. /**
  51. * 根据 alias 获取对应表单值。
  52. */
  53. const getFieldFormValueByAlias = (alias: string): DynamicFormFieldValue | undefined => {
  54. const field = findFieldByAlias(alias)
  55. if (!field) {
  56. return undefined
  57. }
  58. return getFieldFormValue(field)
  59. }
  60. /**
  61. * 根据 alias 获取字段实际 value。
  62. */
  63. const getFieldValueByAlias = (alias: string): FieldValue => {
  64. return getFieldFormValueByAlias(alias)?.value
  65. }
  66. /**
  67. * 更新指定字段的表单值。
  68. */
  69. const setFieldFormValue = (
  70. field: TaskFieldConfigViewItem,
  71. fieldValue: Partial<DynamicFormFieldValue>
  72. ) => {
  73. const currentValue = getFieldFormValue(field)
  74. if (!currentValue) {
  75. return
  76. }
  77. if (fieldValue.label !== undefined) {
  78. currentValue.label = fieldValue.label
  79. }
  80. if (fieldValue.value !== undefined) {
  81. currentValue.value = fieldValue.value
  82. }
  83. }
  84. /**
  85. * 根据 alias 更新字段表单值。
  86. */
  87. const setFieldFormValueByAlias = (alias: string, fieldValue: Partial<DynamicFormFieldValue>) => {
  88. const field = findFieldByAlias(alias)
  89. if (!field) {
  90. return
  91. }
  92. setFieldFormValue(field, fieldValue)
  93. }
  94. /**
  95. * 清空字段值。
  96. */
  97. const clearFieldValue = (field: TaskFieldConfigViewItem) => {
  98. const currentValue = getFieldFormValue(field)
  99. if (!currentValue) {
  100. return
  101. }
  102. currentValue.label = ''
  103. currentValue.value = ''
  104. }
  105. /**
  106. * 根据 alias 清空字段值。
  107. */
  108. const clearFieldValueByAlias = (alias: string) => {
  109. const field = findFieldByAlias(alias)
  110. if (!field) {
  111. return
  112. }
  113. clearFieldValue(field)
  114. }
  115. /**
  116. * 更新字段选项。
  117. *
  118. * 没有选项时统一设置为 null。
  119. */
  120. const setFieldOptions = (field: TaskFieldConfigViewItem, options: TaskFieldOption[]) => {
  121. field.options = options.length ? options : null
  122. }
  123. /**
  124. * 根据 alias 更新字段选项。
  125. */
  126. const setFieldOptionsByAlias = (alias: string, options: TaskFieldOption[]) => {
  127. const field = findFieldByAlias(alias)
  128. if (!field) {
  129. return
  130. }
  131. setFieldOptions(field, options)
  132. }
  133. /**
  134. * 单选打开前处理。
  135. *
  136. * 特殊接口请求和业务校验写在这里。
  137. */
  138. const handleSingleSelectBeforeOpen = async (field: TaskFieldConfigViewItem): Promise<boolean> => {
  139. console.log('field', field)
  140. if (field.taskTypeId === '18' && field.alias === 'pharmacyName') {
  141. uni.navigateTo({
  142. url: `/pages-common/entity-selector/index?alias=pharmacyName`,
  143. events: {
  144. pharmacyNameSelect: (selectedPharmacyItem: PharmacyItem | string) => {
  145. setPharmacyNameSelectEvent(selectedPharmacyItem)
  146. },
  147. },
  148. })
  149. return false
  150. }
  151. if (taskTypeId.value === '47') {
  152. /**
  153. * OTC 推广任务示例。
  154. */
  155. const scorePackageValue = getFieldFormValueByAlias('scorePackage')
  156. console.log('scorePackageValue', scorePackageValue)
  157. if (field.taskFiledValue === '产品') {
  158. if (!scorePackageValue?.value) {
  159. uni.showToast({
  160. title: '请先选择积分包',
  161. icon: 'none',
  162. })
  163. return false
  164. } else {
  165. const arr = await getListDrugTable(String(scorePackageValue.value))
  166. field.options = arr
  167. return true
  168. }
  169. }
  170. if (field.alias === 'realTaskTypeId') {
  171. return true
  172. }
  173. }
  174. return true
  175. }
  176. const getListDrugTable = async (packageId: string) => {
  177. try {
  178. const res = await getListDrugTableApi(packageId)
  179. const arr = res.data.map((item: string) => {
  180. return {
  181. label: item,
  182. value: item,
  183. }
  184. })
  185. return arr
  186. } catch (error) {
  187. console.error('获取药品列表失败:', error)
  188. return []
  189. }
  190. }
  191. /**
  192. * 单选值发生变化。
  193. *
  194. * SingleSelect 内部已经保证新值与原值不同时
  195. * 才会触发此方法。
  196. */
  197. const handleSingleSelectChange = (
  198. field: TaskFieldConfigViewItem,
  199. event: SingleSelectChangeEvent
  200. ) => {
  201. console.log('单选字段:', field)
  202. console.log('单选变化:', event)
  203. /**
  204. * OTC 推广任务的字段联动示例。
  205. */
  206. if (taskTypeId.value === '47') {
  207. if (field.alias === 'scorePackage') {
  208. clearFieldValueByAlias('realTaskTypeId')
  209. }
  210. }
  211. }
  212. /**
  213. * 多选打开前处理。
  214. */
  215. const handleMultipleSelectBeforeOpen = async (
  216. field: TaskFieldConfigViewItem
  217. ): Promise<boolean> => {
  218. const currentFormValue = getFieldFormValue(field)
  219. if (!currentFormValue) {
  220. console.warn(`未找到字段对应的表单值:${field.id}`)
  221. return false
  222. }
  223. /**
  224. * 特殊多选接口请求写在这里。
  225. *
  226. * 示例:
  227. *
  228. * if (
  229. * taskTypeId.value === '47' &&
  230. * field.alias === 'targetUsers'
  231. * ) {
  232. * const packageValue =
  233. * getFieldValueByAlias('scorePackage')
  234. *
  235. * if (!packageValue) {
  236. * uni.showToast({
  237. * title: '请先选择分数包',
  238. * icon: 'none',
  239. * })
  240. *
  241. * return false
  242. * }
  243. *
  244. * const res = await getTargetUserListApi({
  245. * packageId: String(packageValue),
  246. * })
  247. *
  248. * setFieldOptions(
  249. * field,
  250. * res.data.map((item) => ({
  251. * label: String(item.name),
  252. * value: String(item.id),
  253. * }))
  254. * )
  255. * }
  256. */
  257. return true
  258. }
  259. const setPharmacyNameSelectEvent = (selectedPharmacyItem: PharmacyItem | string) => {
  260. if (typeof selectedPharmacyItem === 'string') {
  261. setFieldFormValueByAlias('pharmacyName', {
  262. label: selectedPharmacyItem,
  263. value: selectedPharmacyItem,
  264. })
  265. return
  266. }
  267. setFieldFormValueByAlias('pharmacyName', {
  268. label: selectedPharmacyItem.pharmacyName,
  269. value: selectedPharmacyItem.pharmacyName,
  270. })
  271. setFieldFormValueByAlias('pharmacyType', {
  272. label: undefined,
  273. value: selectedPharmacyItem.pharmacyType,
  274. })
  275. setFieldFormValueByAlias('address', {
  276. label: selectedPharmacyItem.address,
  277. value: selectedPharmacyItem.address,
  278. })
  279. const address = `${selectedPharmacyItem.province}-${selectedPharmacyItem.city}-${selectedPharmacyItem.area}`
  280. setFieldFormValueByAlias('shengshiqu', {
  281. label: address,
  282. value: address,
  283. })
  284. }
  285. return {
  286. handleSingleSelectBeforeOpen,
  287. handleSingleSelectChange,
  288. handleMultipleSelectBeforeOpen,
  289. /**
  290. * 以下方法可按需在页面或其他业务逻辑中使用。
  291. */
  292. findFieldByAlias,
  293. getFieldFormValue,
  294. getFieldFormValueByAlias,
  295. getFieldValueByAlias,
  296. setFieldFormValue,
  297. setFieldFormValueByAlias,
  298. clearFieldValue,
  299. clearFieldValueByAlias,
  300. setFieldOptions,
  301. setFieldOptionsByAlias,
  302. }
  303. }