index.vue 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. <script lang="ts" setup>
  2. import { computed, nextTick, onMounted, ref, watch } from 'vue';
  3. import { Button, Card, message, Space, Tag } from 'antdv-next';
  4. import { useVbenForm } from '#/adapter/form';
  5. const transformedValues = ref<Record<string, any>>({});
  6. const liveValues = ref<Record<string, any>>({});
  7. const [Form, formApi] = useVbenForm({
  8. commonConfig: {
  9. componentProps: {
  10. class: 'w-full',
  11. },
  12. },
  13. handleSubmit,
  14. schema: [
  15. {
  16. component: 'RangePicker',
  17. fieldName: 'reportRange',
  18. help: '通过 setValue 拆分为 startTime / endTime,并移除原字段',
  19. label: '统计时间范围',
  20. valueFormat(value, setValue) {
  21. setValue('startTime', value?.[0]?.valueOf());
  22. setValue('endTime', value?.[1]?.valueOf());
  23. },
  24. },
  25. {
  26. component: 'DatePicker',
  27. fieldName: 'deadline',
  28. help: '直接 return 时间戳,保留原字段名',
  29. label: '截止时间',
  30. valueFormat(value) {
  31. return value?.valueOf();
  32. },
  33. },
  34. {
  35. component: 'Input',
  36. componentProps: {
  37. placeholder: '请输入关键字',
  38. },
  39. fieldName: 'keyword',
  40. label: '关键字',
  41. },
  42. ],
  43. wrapperClass: 'grid-cols-1 md:grid-cols-2',
  44. });
  45. const liveValuesPreview = computed(() => formatJsonPreview(liveValues.value));
  46. const transformedValuesPreview = computed(() => {
  47. return formatJsonPreview(transformedValues.value);
  48. });
  49. function formatJsonPreview(value: Record<string, any>) {
  50. return JSON.stringify(
  51. value,
  52. (_key, currentValue) => {
  53. return isFormattableDateValue(currentValue)
  54. ? currentValue.format('YYYY-MM-DD HH:mm:ss')
  55. : currentValue;
  56. },
  57. 2,
  58. );
  59. }
  60. function isFormattableDateValue(
  61. value: unknown,
  62. ): value is { format: (template: string) => string } {
  63. return !!value && typeof value === 'object' && 'format' in value;
  64. }
  65. async function handleInspectValues() {
  66. await syncPreviewValues();
  67. message.success('已刷新 getValues 输出');
  68. }
  69. function handleSubmit(values: Record<string, any>) {
  70. transformedValues.value = values;
  71. message.success({
  72. content: `getValues output: ${JSON.stringify(values)}`,
  73. });
  74. }
  75. async function syncPreviewValues(values?: Record<string, any>) {
  76. liveValues.value = values ?? formApi.form?.values ?? {};
  77. transformedValues.value = await formApi.getValues();
  78. }
  79. onMounted(async () => {
  80. await nextTick();
  81. watch(
  82. () => formApi.form?.values,
  83. async (values) => {
  84. await syncPreviewValues(values);
  85. },
  86. {
  87. deep: true,
  88. immediate: true,
  89. },
  90. );
  91. });
  92. </script>
  93. <template>
  94. <div class="space-y-4">
  95. <div class="flex flex-wrap gap-2">
  96. <Tag color="processing">return 值:回写当前字段</Tag>
  97. <Tag color="success">setValue:拆分写入其他字段</Tag>
  98. <Tag color="warning">return undefined:保持原字段删除</Tag>
  99. </div>
  100. <Card title="valueFormat 示例">
  101. <template #extra>
  102. <Space wrap>
  103. <Button type="primary" @click="handleInspectValues">
  104. 查看 getValues 输出
  105. </Button>
  106. </Space>
  107. </template>
  108. <Form />
  109. </Card>
  110. <div class="grid gap-4 lg:grid-cols-2">
  111. <Card title="原始 form.values(组件值)">
  112. <pre class="bg-muted overflow-auto rounded-md p-4 text-sm">{{
  113. liveValuesPreview
  114. }}</pre>
  115. </Card>
  116. <Card title="getValues / submit 输出(valueFormat 后)">
  117. <pre class="bg-muted overflow-auto rounded-md p-4 text-sm">{{
  118. transformedValuesPreview
  119. }}</pre>
  120. </Card>
  121. </div>
  122. </div>
  123. </template>