useConditionFactory.js 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. import {ref, toValue, watch, nextTick, isRef} from 'vue';
  2. import {empty, func} from "@/uni_modules/uv-ui-tools/libs/function/test";
  3. import _ from "lodash";
  4. import {fnPlaceholder} from "@/utils/uni-helper";
  5. // 一般情况下用queryParams即可,但有可能有些全局参数不在queryParams里面,则用sharedData注入进来
  6. // 通过dependentKeys和independentKeys,获取请求必须的参数
  7. // dependentKeys是必须参数,independentKeys是非必须参数
  8. export const useConditionFactory = function (config, eventManager, queryParams, sharedData, console) {
  9. const {
  10. key, handler, autoInit, required, rule, allLabel, title, multiple,
  11. dependentKeys, independentKeys, keyName, keyValue
  12. } = config
  13. if (empty(key)) throw new Error('condition must define a key')
  14. if (!func(handler)) throw new Error('handler must be a function')
  15. const list = ref([])
  16. if (required && !rule.some(r => r.required)) {
  17. // 没有必填规则就自动创建一条
  18. const requiredRule = {required: true, message: `${title}不能为空`, transform: (v) => v + ''}
  19. config.rule = [...rule, requiredRule] // 不要直接修改rule,rule可能来自于conditionSharedConfig
  20. }
  21. const makePayload = async () => {
  22. const payload = {}
  23. const params = toValue(queryParams)
  24. // 先检查依赖项
  25. for (const key of dependentKeys) {
  26. const val = params[key]
  27. if (empty(val)) {
  28. // 只是给一个警告,reject的方式太重了,会让后续开发认为产生了不可修复问题。
  29. // 一般情况下缺必传字段,只需要等必传字段autoInit完成就会自动修复这个问题。
  30. // 当然万一运行不符合预期,这里也确实是需要着重检查的点。
  31. console.warn(`${config.key}: independent key ${key} is required, wait for next turn.`)
  32. return new Promise(fnPlaceholder).then()
  33. // return Promise.reject('some message')
  34. }
  35. payload[key] = val
  36. }
  37. for (const key of independentKeys) {
  38. payload[key] = params[key]
  39. }
  40. return {...toValue(sharedData), ...payload}
  41. }
  42. const loadData = async () => {
  43. eventManager.push('loadData calling', key)
  44. const payload = await makePayload()
  45. const results = await config.handler(payload)
  46. console.log('dataManager data loaded', key, results)
  47. const processData = function (results) {
  48. if (allLabel && !required) {
  49. const add = keyValue ? {[keyName]: allLabel, [keyValue]: ''} : allLabel
  50. list.value = [add, ...results] // 不直接修改,可能会影响缓存结果
  51. } else {
  52. list.value = results
  53. }
  54. const current = toValue(queryParams)[key]
  55. const currentInvalid = (val) => {
  56. const valSource = list.value.map(i => keyValue ? i[keyValue] : i)
  57. const diff = _.difference(valSource, [].concat(val))
  58. console.log('loadData invalid current:', val, ', diff', diff)
  59. return diff.length > 0
  60. }
  61. if (!empty(current) && currentInvalid(current)) {
  62. console.log('loadData clear invalid', key, current)
  63. queryParams.value[key] = multiple ? [] : ''
  64. }
  65. if (required && autoInit && empty(current)) {
  66. const first = _.first(list.value)
  67. const firstValue = keyValue ? first[keyValue] : first
  68. if (first) queryParams.value[key] = multiple ? [firstValue] : firstValue
  69. console.log('loadData auto init', key, firstValue)
  70. }
  71. eventManager.pop('loadData called', key)
  72. }
  73. if (isRef(results)) {
  74. const pureResults = toValue(results)
  75. if (empty(pureResults)) {
  76. // 此时没有数据,说明后续可能会更新,使用watch监听即可
  77. watch(results, (values) => processData(values))
  78. } else {
  79. processData(pureResults)
  80. }
  81. } else {
  82. processData(results)
  83. }
  84. }
  85. // 数据加载
  86. if (!dependentKeys.length) {
  87. // 无依赖项,直接调用。这里使用了nextTick做保险,万一立即进行校验,要保证uv-form渲染之后才能进行
  88. nextTick(async () => await loadData())
  89. } else {
  90. // 有依赖项,建立监听,依赖变更时重新加载数据
  91. const watches = dependentKeys.map(k => () => toValue(queryParams)[k])
  92. watch(watches, async () => await loadData(), {immediate: true})
  93. }
  94. return {list, config}
  95. }