{"version":3,"file":"use-form-model.mjs","sources":["../../../../../packages/components/form/src/use-form-model.ts"],"sourcesContent":["import { omit } from 'lodash'\nimport { isReactive, shallowReactive } from 'vue'\nimport type { FormModel, FormModelItem } from './form'\nimport { isObject } from '@element-ultra/utils'\n\ntype GetModel<T extends Record<string, any>> = {\n  [key in keyof T]: T[key] extends { [k: string]: any; children: any }\n    ? GetModel<T[key]['children']>\n    : T[key]['value']\n}\n\nfunction proxyHelper() {\n  // 副作用收集\n  const keyEffects = new Map<string, Set<() => void>>()\n  // 依赖收集\n  const keyDeps = new Map<string, Set<string>>()\n\n  const getEffects = (key: string) => {\n    let effects = keyEffects.get(key)\n    // 不能有相互依赖\n    if (!effects) {\n      effects = new Set()\n      keyEffects.set(key, effects)\n    }\n    return effects\n  }\n\n  // 当前激活的副作用\n  let activeEffect: (() => void) | null\n  // 当前激活的key\n  let activeKey: string | null\n\n  /**\n   * 依赖追踪\n   */\n  const track = (key: string) => {\n    if (activeKey) {\n      let trackKeyDeps = keyDeps.get(key)\n\n      if (trackKeyDeps?.has(activeKey)) {\n        return console.error(\n          `无法被追踪, 存在循环依赖: [${key}]  <=> [${activeKey}]`\n        )\n      }\n\n      let deps = keyDeps.get(activeKey)\n      deps?.add(key)\n    }\n\n    if (activeEffect) {\n      let effects = getEffects(key)\n      effects.add(activeEffect)\n    }\n  }\n\n  const trigger = (key: string) => {\n    if (keyEffects.get(key)) {\n      let effects = getEffects(key)\n      effects.forEach(effect => effect())\n    }\n  }\n\n  const watchGetter = (\n    getters: Record<string, undefined | ((...args: any[]) => any)>,\n    model: Record<string, any>\n  ) => {\n    Object.keys(getters).forEach(key => {\n      let getter = getters[key]\n      if (!getter) return\n\n      keyDeps.set(key, new Set())\n      activeKey = key\n\n      activeEffect = () => {\n        model[key] = getter!(model)\n      }\n\n      // 触发副作用收集\n      let v = getter(model)\n\n      activeKey = null\n      activeEffect = null\n\n      // 因为赋值会立马执行副作用, 并触发新的getter\n      // 因此, 清空全局变量之后再赋值, 避免无限触发getter(循环引用时)\n      model[key] = v\n    })\n  }\n\n  const proxy = <T extends { [key: string]: any }>(o: T): T => {\n    return new Proxy<T>(o, {\n      get(t, p: string) {\n        track(p)\n        return t[p]\n      },\n      set(t: { [key: string]: any }, p: string, val) {\n        t[p] = val\n        trigger(p)\n        return true\n      }\n    })\n  }\n\n  return {\n    proxy,\n    watchGetter\n  }\n}\n\n/**\n * 使用表单数据模型\n * @param model 表单数据模型\n */\nexport default function useFormModel<\n  M extends FormModel,\n  K extends keyof M,\n  Model extends GetModel<M> = GetModel<M>\n>(\n  model: M,\n  valueGetter?: {\n    [key in K]?: (model: Model) => any\n  }\n) {\n  const rawModel = {} as Model\n\n  const reduceRawModel = (model: FormModel, rawModel: Record<string, any>) => {\n    const modelKeys = Object.keys(model)\n    modelKeys.forEach(key => {\n      const modelItem = model[key]\n      rawModel[key] = modelItem.value\n      if (modelItem.children) {\n        let value = rawModel[key]\n        if (!value || !isObject(value)) {\n          throw new Error(`请为${key}字段指定一个对象值`)\n        }\n        // 非响应的对象要使其响应\n        if (!isReactive(value)) {\n          rawModel[key] = shallowReactive(value)\n        }\n        reduceRawModel(modelItem.children, rawModel[key])\n      }\n    })\n  }\n\n  reduceRawModel(model, rawModel)\n\n  const rules: Record<string, Omit<FormModelItem, 'value'>> = {}\n\n  // 递归合并子级规则, 以便校验.\n  // test: { children: { test1: { required: true } } } -> 'test.test1': { required: true }\n  const getRules = (model: FormModel, pre = '') => {\n    const modelKeys = Object.keys(model)\n    modelKeys.forEach(key => {\n      const modelItem = model[key]\n      if (modelItem.children) {\n        getRules(modelItem.children, pre + key + '.')\n      } else {\n        rules[pre + key] = omit(modelItem, ['value'])\n      }\n    })\n  }\n  getRules(model)\n\n  const form = shallowReactive(rawModel)\n\n  // 设置一个代理层\n  if (valueGetter) {\n    const { proxy, watchGetter } = proxyHelper()\n    let proxyForm = proxy<Model>(form)\n    // 访问proxyForm的属性来触发依赖收集\n    watchGetter(valueGetter, proxyForm)\n\n    return [proxyForm, rules] as const\n  }\n\n  return [form, rules] as const\n}"],"names":["model","rawModel"],"mappings":"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"}