import {ref, toValue, watch, nextTick, isRef} from 'vue'; import {empty, func} from "@/uni_modules/uv-ui-tools/libs/function/test"; import _ from "lodash"; import {fnPlaceholder} from "@/utils/uni-helper"; // 一般情况下用queryParams即可,但有可能有些全局参数不在queryParams里面,则用sharedData注入进来 // 通过dependentKeys和independentKeys,获取请求必须的参数 // dependentKeys是必须参数,independentKeys是非必须参数 export const useConditionFactory = function (config, eventManager, queryParams, sharedData, console) { const { key, handler, autoInit, required, rule, allLabel, title, multiple, dependentKeys, independentKeys, keyName, keyValue } = config if (empty(key)) throw new Error('condition must define a key') if (!func(handler)) throw new Error('handler must be a function') const list = ref([]) if (required && !rule.some(r => r.required)) { // 没有必填规则就自动创建一条 const requiredRule = {required: true, message: `${title}不能为空`, transform: (v) => v + ''} config.rule = [...rule, requiredRule] // 不要直接修改rule,rule可能来自于conditionSharedConfig } const makePayload = async () => { const payload = {} const params = toValue(queryParams) // 先检查依赖项 for (const key of dependentKeys) { const val = params[key] if (empty(val)) { // 只是给一个警告,reject的方式太重了,会让后续开发认为产生了不可修复问题。 // 一般情况下缺必传字段,只需要等必传字段autoInit完成就会自动修复这个问题。 // 当然万一运行不符合预期,这里也确实是需要着重检查的点。 console.warn(`${config.key}: independent key ${key} is required, wait for next turn.`) return new Promise(fnPlaceholder).then() // return Promise.reject('some message') } payload[key] = val } for (const key of independentKeys) { payload[key] = params[key] } return {...toValue(sharedData), ...payload} } const loadData = async () => { eventManager.push('loadData calling', key) const payload = await makePayload() const results = await config.handler(payload) console.log('dataManager data loaded', key, results) const processData = function (results) { if (allLabel && !required) { const add = keyValue ? {[keyName]: allLabel, [keyValue]: ''} : allLabel list.value = [add, ...results] // 不直接修改,可能会影响缓存结果 } else { list.value = results } const current = toValue(queryParams)[key] const currentInvalid = (val) => { const valSource = list.value.map(i => keyValue ? i[keyValue] : i) const diff = _.difference(valSource, [].concat(val)) console.log('loadData invalid current:', val, ', diff', diff) return diff.length > 0 } if (!empty(current) && currentInvalid(current)) { console.log('loadData clear invalid', key, current) queryParams.value[key] = multiple ? [] : '' } if (required && autoInit && empty(current)) { const first = _.first(list.value) const firstValue = keyValue ? first[keyValue] : first if (first) queryParams.value[key] = multiple ? [firstValue] : firstValue console.log('loadData auto init', key, firstValue) } eventManager.pop('loadData called', key) } if (isRef(results)) { const pureResults = toValue(results) if (empty(pureResults)) { // 此时没有数据,说明后续可能会更新,使用watch监听即可 watch(results, (values) => processData(values)) } else { processData(pureResults) } } else { processData(results) } } // 数据加载 if (!dependentKeys.length) { // 无依赖项,直接调用。这里使用了nextTick做保险,万一立即进行校验,要保证uv-form渲染之后才能进行 nextTick(async () => await loadData()) } else { // 有依赖项,建立监听,依赖变更时重新加载数据 const watches = dependentKeys.map(k => () => toValue(queryParams)[k]) watch(watches, async () => await loadData(), {immediate: true}) } return {list, config} }