CascaderField.vue 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. <template>
  2. <Popup
  3. :show="popupShow"
  4. @close="onCancel"
  5. :closeIcon="false"
  6. position="bottom"
  7. closeable
  8. >
  9. <PopupTitle
  10. relative
  11. :title="title"
  12. :closeable="true"
  13. @close="onCancel"
  14. />
  15. <Cascader
  16. v-if="popupShow"
  17. v-bind="props"
  18. v-model="tempValue"
  19. @selectTextChange="onSelectTextChange"
  20. @pickEnd="onPickEnd"
  21. />
  22. <slot name="footer">
  23. <Height :size="20" />
  24. </slot>
  25. </Popup>
  26. <Text
  27. v-if="showSelectText"
  28. :size="30"
  29. color="text.second"
  30. :text="selectText || placeholder"
  31. :maxWidth="300"
  32. v-bind="textProps"
  33. />
  34. </template>
  35. <script setup lang="ts">
  36. import { ref, toRef } from 'vue';
  37. import { useFieldChildValueInjector } from './FormContext';
  38. import { usePickerFieldTempStorageData } from './PickerUtils';
  39. import type { CascaderProps } from './Cascader.vue';
  40. import Popup from '../dialog/Popup.vue';
  41. import Cascader from './Cascader.vue';
  42. import Height from '../layout/space/Height.vue';
  43. import Text, { type TextProps } from '../basic/Text.vue';
  44. import PopupTitle from '../dialog/PopupTitle.vue';
  45. export interface CascaderFieldProps extends Omit<CascaderProps, 'modelValue'> {
  46. modelValue?: (string|number)[];
  47. /**
  48. * 标题
  49. */
  50. title?: string,
  51. /**
  52. * 是否显示选择的文本。
  53. * @default true
  54. */
  55. showSelectText?: boolean,
  56. /**
  57. * 占位符
  58. */
  59. placeholder?: string,
  60. /**
  61. * 初始值
  62. */
  63. initalValue?: string[],
  64. /**
  65. * 是否在选择完成后立即更新值。
  66. * @default false
  67. */
  68. shouldUpdateValueImmediately?: boolean,
  69. /**
  70. * 显示的文本属性
  71. */
  72. textProps?: TextProps,
  73. /**
  74. * 确认前的回调
  75. * @param value 选中的值
  76. * @returns 返回true可以阻止关闭弹窗
  77. */
  78. beforeConfirm?: (value: (string|number)[]|undefined) => Promise<boolean>,
  79. }
  80. const emit = defineEmits([ 'update:modelValue', 'cancel', 'confirm', 'selectTextChange', 'tempValueChange' ]);
  81. const props = withDefaults(defineProps<CascaderFieldProps>(), {
  82. modelValue: () => [],
  83. title: '请选择',
  84. placeholder: '请选择',
  85. titleProps: () => ({
  86. cancelText: '取消',
  87. confirmText: '确定',
  88. }),
  89. showSelectText: true,
  90. autoConfirm: true,
  91. });
  92. const popupShow = ref(false);
  93. const {
  94. value,
  95. updateValue,
  96. } = useFieldChildValueInjector(
  97. toRef(props, 'modelValue'),
  98. (v) => emit('update:modelValue', v),
  99. undefined,
  100. () => {
  101. popupShow.value = true;
  102. },
  103. props.initalValue,
  104. );
  105. const {
  106. onSelectTextChange,
  107. onCancel,
  108. onConfirm,
  109. selectText,
  110. tempValue,
  111. } = usePickerFieldTempStorageData(
  112. value,
  113. updateValue,
  114. () => popupShow.value = false,
  115. emit as any,
  116. [],
  117. props.shouldUpdateValueImmediately,
  118. props.beforeConfirm,
  119. );
  120. function onPickEnd() {
  121. if (props.autoConfirm)
  122. onConfirm();
  123. }
  124. defineOptions({
  125. options: {
  126. styleIsolation: "shared",
  127. virtualHost: true,
  128. }
  129. })
  130. </script>