usePage增加许多配置项,另外增加一些回调函数、插槽等等,修改逻辑增强配置灵活性
zk authored at 2023-11-21 17:42:23
3.07 KiB
NewLife.QuickVue
<template>
  <el-cascader class="w-full" :props="caProps" v-model="caValue" />
</template>

<script setup lang="ts" name="cascader">
import { useVModel } from '@vueuse/core';
import type { CascaderProps } from 'element-plus'
import { computed, ref, useAttrs, watch } from 'vue';
import { usePageApi } from '/@/api/page';
import { deepMerge } from '/@/utils/other';
type PropApi = (...arr: any) => Promise<Array<EmptyObjectType>>
interface Props {
  // 读取store缓存
  storeKey?: string;
  // 值字段名
  valueKey?: string;
  // 名称字段名
  labelKey?: string;
  // 子集字段名
  childrenKey?: string;
  // 请求返回值字段名
  resultKey?: string;
  // 父级地段名
  parentKey?: string;
  // 用与将数组拆分赋值给多个字段
  modelKeys?: string[];
  // 绑定的值,可绑定表单对象或者属性值,当绑定表单对象时,需要搭配modelKeys一起使用
  modelValue?: any;
  // 请求方法
  api?: PropApi | Array<PropApi>
  // 请求地址
  url?: string | Array<string>
  // 总层级
  level?: number;
  // 最后以及标识字段
  leafKey?: string;
  // 请求携带的参数
  requestProps?: EmptyObjectType;
}
interface Emits {
  (e: 'update:model-value', val: any): void;
  (e: 'optionRequestAfter', val: EmptyArrayType, level: number): void;
}
const props = withDefaults(defineProps<Props>(), {
  valueKey: 'id',
  labelKey: 'name',
  resultKey: 'data',
  childrenKey: 'children',
  parentKey: 'parentId'
})
const emits = defineEmits<Emits>()

const vModel = useVModel(props, 'modelValue', emits)

const caValue = computed({
  get () {
    if (props.modelKeys) {
      let val = props.modelKeys.map(key => props.modelValue[key])
      for (let i = val.length - 1; i >= 0; i--) {
        if (!val[i]) val.splice(i, 1)
        else break;
      }
      return val
    }
    return props.modelValue
  },
  set (val: Array<string | number>) {
    let value = val || []
    if (props.modelKeys) {
      props.modelKeys.forEach((key, i) => {
        vModel.value[key] = value[i]
      })
    } else {
      vModel.value = value
    }
  }
})

const attrs = useAttrs();
const caProps = (attrs.props || {}) as CascaderProps;
if (props.api || props.url) {
  caProps.lazy = true;
  caProps.value = props.valueKey!;
  caProps.label = props.labelKey!;
  caProps.children = props.childrenKey!;
  const { getTableData } = usePageApi()
  caProps.lazyLoad = async (node, resolve) => {
    const { level, value } = node
    let res
    const requestProps = deepMerge(props.requestProps, level ? {[props.parentKey]: value} : {})
    if (props.api) {
      res = await Array.isArray(props.api) ? props.api[level](requestProps) : (props.api as PropApi)(requestProps)
    } else {
      res = await getTableData(Array.isArray(props.url) ? props.url[level] : props.url!, requestProps)
    }
    emits('optionRequestAfter', res[props.resultKey], level)
    const nodes = res[props.resultKey].map((item: EmptyObjectType) => ({
      ...item,
      leaf: props.leafKey ? item[props.leafKey] : props.level ? level >= props.level : true
    }))
    resolve(nodes)
  }
}
</script>

<style scoped>

</style>