CascaderFormItem.vue 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. <template>
  2. <a-cascader
  3. :value="value"
  4. :options="options"
  5. :load-data="doLoadData"
  6. :placeholder="placeholder"
  7. @update:value="onUpdateValue"
  8. change-on-select
  9. v-bind="(customProps as any)"
  10. />
  11. </template>
  12. <script lang="ts">
  13. import { defineComponent, onMounted, type PropType, ref, toRefs, watch } from "vue";
  14. import type { CascaderProps } from "ant-design-vue";
  15. import type { LoadDataFun, OnChooseFun } from "./CascaderFormItem";
  16. export default defineComponent({
  17. props: {
  18. loadData: {
  19. type: Function as PropType<LoadDataFun>,
  20. default: null,
  21. },
  22. placeholder: {
  23. type: String,
  24. default: '请选择地址',
  25. },
  26. loadAtStart: {
  27. type: Boolean,
  28. default: true,
  29. },
  30. loadCascaderToCurrentValueAtStart: {
  31. type: Boolean,
  32. default: true,
  33. },
  34. value: {},
  35. /**
  36. * 选择后回调
  37. */
  38. onSelect: {
  39. type: Function as PropType<OnChooseFun>,
  40. default: null,
  41. },
  42. onSelectFindIdKey: {
  43. type: String,
  44. default: 'id',
  45. },
  46. /**
  47. * a-cascader 其他自定义参数
  48. */
  49. customProps: {
  50. //type: Object as PropType<CascaderProps>,
  51. default: null,
  52. },
  53. },
  54. emits: [
  55. 'update:value'
  56. ],
  57. setup(props, context) {
  58. const { loadAtStart, loadCascaderToCurrentValueAtStart, value, loadData, onSelect } = toRefs(props);
  59. const options = ref<CascaderProps['options']>([]);
  60. const doLoadData = ((selectedOptions) => {
  61. const parent = selectedOptions && selectedOptions.length > 0 ? selectedOptions[selectedOptions.length - 1] : null;
  62. loadData.value(parent?.value as number, selectedOptions ? selectedOptions.length : 0, parent)
  63. .then((d) => {
  64. if (!d)
  65. throw new Error("loadData return invalid data!");
  66. if (parent) {
  67. //添加数据至指定层级下方
  68. if (!parent.children)
  69. parent.children = d;
  70. else
  71. parent.children = parent.children.concat(d);
  72. } else {
  73. //添加数据
  74. options.value = d;
  75. //这个时候加载一下默认选择项目
  76. if (loadCascaderToCurrentValueAtStart.value)
  77. doLoadDataToCurrentValue();
  78. }
  79. }).catch((e) => {
  80. console.error(e);
  81. });
  82. }) as CascaderProps['loadData'];
  83. function onUpdateValue(v: number[]) {
  84. context.emit('update:value', v);
  85. //选中后回调
  86. if (typeof onSelect.value === 'function') {
  87. const objArr = [] as unknown[];
  88. const valueArrNow = v.concat();
  89. //通过ID查找指定的对象
  90. let optionsCurrent = options.value as CascaderProps['options'];
  91. for (let i = 0; i < v.length; i++) {
  92. if (!optionsCurrent)
  93. break;
  94. const item = optionsCurrent.find(k => k.value === valueArrNow[i]);
  95. if (item) {
  96. objArr.push(item);
  97. optionsCurrent = item.children;//下一级
  98. } else {
  99. break;
  100. }
  101. }
  102. //回调
  103. onSelect.value(v, objArr);
  104. }
  105. }
  106. //加载树形数据至当前选中层级
  107. function doLoadDataToCurrentValue() {
  108. const valueArrNow = (value.value as number[]).concat();
  109. function findChildren(index: number, optionsCurrent: CascaderProps['options']) {
  110. if (!optionsCurrent)
  111. return;
  112. //当前级数据,查找是否存在,
  113. const option = optionsCurrent.find(k => k.value === valueArrNow[index]);
  114. if (option && (!option.children || option.children.length === 0)) {
  115. //存在,尝试加载下一级数据
  116. loadData.value(valueArrNow[index], index, option)
  117. .then((d) => {
  118. if (!d)
  119. throw new Error("loadData return invalid data!");
  120. if (parent) {
  121. if (!option.children)
  122. option.children = d;
  123. else
  124. option.children = option.children.concat(d);
  125. //如果还没有达到输入选择的层级,则进行下一次加载
  126. if (index < valueArrNow.length - 1) {
  127. findChildren(index + 1, option.children);
  128. }
  129. }
  130. }).catch((e) => {
  131. console.error(e);
  132. });
  133. }
  134. }
  135. findChildren(0, options.value);
  136. }
  137. onMounted(() => {
  138. if (loadAtStart.value && typeof doLoadData === 'function')
  139. doLoadData([]);
  140. });
  141. watch(value, () => {
  142. doLoadDataToCurrentValue();
  143. });
  144. return {
  145. doLoadData,
  146. doLoadDataToCurrentValue,
  147. onUpdateValue,
  148. options,
  149. };
  150. },
  151. });
  152. </script>