@xiaohaih/json-form-vant 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (213) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/README.md +807 -0
  3. package/TODO.md +36 -0
  4. package/components/area/index.ts +6 -0
  5. package/components/area/index.vue +120 -0
  6. package/components/area/types.ts +84 -0
  7. package/components/cascader/index.ts +6 -0
  8. package/components/cascader/index.vue +146 -0
  9. package/components/cascader/types.ts +75 -0
  10. package/components/checkbox/index.ts +6 -0
  11. package/components/checkbox/index.vue +59 -0
  12. package/components/checkbox/types.ts +54 -0
  13. package/components/checkbox-group/index.ts +6 -0
  14. package/components/checkbox-group/index.vue +67 -0
  15. package/components/checkbox-group/types.ts +63 -0
  16. package/components/component-definition/components.ts +29 -0
  17. package/components/component-definition/definition.ts +25 -0
  18. package/components/component-definition/index.ts +4 -0
  19. package/components/custom-render/index.ts +6 -0
  20. package/components/custom-render/index.vue +66 -0
  21. package/components/custom-render/types.ts +43 -0
  22. package/components/date-picker/index.ts +6 -0
  23. package/components/date-picker/index.vue +130 -0
  24. package/components/date-picker/types.ts +91 -0
  25. package/components/date-time-picker-group/index.ts +6 -0
  26. package/components/date-time-picker-group/index.vue +158 -0
  27. package/components/date-time-picker-group/types.ts +115 -0
  28. package/components/datetime-picker/index.ts +6 -0
  29. package/components/datetime-picker/index.vue +128 -0
  30. package/components/datetime-picker/types.ts +78 -0
  31. package/components/dynamic-group/index.ts +10 -0
  32. package/components/dynamic-group/index.vue +140 -0
  33. package/components/dynamic-group/types.ts +68 -0
  34. package/components/group/assist.ts +99 -0
  35. package/components/group/index.ts +7 -0
  36. package/components/group/index.vue +117 -0
  37. package/components/group/types.ts +57 -0
  38. package/components/group/virtual-group.vue +38 -0
  39. package/components/index.ts +10 -0
  40. package/components/input/index.ts +6 -0
  41. package/components/input/index.vue +83 -0
  42. package/components/input/types.ts +43 -0
  43. package/components/input-slot/index.ts +6 -0
  44. package/components/input-slot/index.vue +148 -0
  45. package/components/input-slot/types.ts +34 -0
  46. package/components/number-keyboard/index.ts +6 -0
  47. package/components/number-keyboard/index.vue +81 -0
  48. package/components/number-keyboard/types.ts +57 -0
  49. package/components/password-input/index.ts +6 -0
  50. package/components/password-input/index.vue +103 -0
  51. package/components/password-input/types.ts +64 -0
  52. package/components/picker/index.ts +6 -0
  53. package/components/picker/index.vue +136 -0
  54. package/components/picker/types.ts +94 -0
  55. package/components/radio/index.ts +6 -0
  56. package/components/radio/index.vue +68 -0
  57. package/components/radio/types.ts +58 -0
  58. package/components/radio-group/index.ts +6 -0
  59. package/components/radio-group/index.vue +74 -0
  60. package/components/radio-group/types.ts +65 -0
  61. package/components/rate/index.ts +6 -0
  62. package/components/rate/index.vue +63 -0
  63. package/components/rate/types.ts +47 -0
  64. package/components/share.ts +78 -0
  65. package/components/signature/index.ts +6 -0
  66. package/components/signature/index.vue +65 -0
  67. package/components/signature/instance.vue +161 -0
  68. package/components/signature/types.ts +79 -0
  69. package/components/slider/index.ts +6 -0
  70. package/components/slider/index.vue +63 -0
  71. package/components/slider/types.ts +53 -0
  72. package/components/stepper/index.ts +6 -0
  73. package/components/stepper/index.vue +62 -0
  74. package/components/stepper/types.ts +47 -0
  75. package/components/switch/index.ts +6 -0
  76. package/components/switch/index.vue +61 -0
  77. package/components/switch/types.ts +51 -0
  78. package/components/time-picker/index.ts +6 -0
  79. package/components/time-picker/index.vue +130 -0
  80. package/components/time-picker/types.ts +91 -0
  81. package/components/tree-select/index.ts +6 -0
  82. package/components/tree-select/index.vue +160 -0
  83. package/components/tree-select/types.ts +77 -0
  84. package/components/upload/index.ts +6 -0
  85. package/components/upload/index.vue +109 -0
  86. package/components/upload/types.ts +85 -0
  87. package/components/use.ts +45 -0
  88. package/components/utils.ts +52 -0
  89. package/components/wrapper/index.ts +6 -0
  90. package/components/wrapper/index.vue +117 -0
  91. package/components/wrapper/types.ts +94 -0
  92. package/dist/components/area/index.d.ts +5 -0
  93. package/dist/components/area/index.vue.d.ts +1843 -0
  94. package/dist/components/area/types.d.ts +1434 -0
  95. package/dist/components/cascader/index.d.ts +5 -0
  96. package/dist/components/cascader/index.vue.d.ts +2467 -0
  97. package/dist/components/cascader/types.d.ts +1419 -0
  98. package/dist/components/checkbox/index.d.ts +5 -0
  99. package/dist/components/checkbox/index.vue.d.ts +1550 -0
  100. package/dist/components/checkbox/types.d.ts +1313 -0
  101. package/dist/components/checkbox-group/index.d.ts +5 -0
  102. package/dist/components/checkbox-group/index.vue.d.ts +1643 -0
  103. package/dist/components/checkbox-group/types.d.ts +1372 -0
  104. package/dist/components/component-definition/components.d.ts +30 -0
  105. package/dist/components/component-definition/index.d.ts +4 -0
  106. package/dist/components/custom-render/index.d.ts +5 -0
  107. package/dist/components/custom-render/index.vue.d.ts +1473 -0
  108. package/dist/components/custom-render/types.d.ts +1175 -0
  109. package/dist/components/date-picker/index.d.ts +5 -0
  110. package/dist/components/date-picker/index.vue.d.ts +1888 -0
  111. package/dist/components/date-picker/types.d.ts +1458 -0
  112. package/dist/components/date-time-picker-group/index.d.ts +5 -0
  113. package/dist/components/date-time-picker-group/index.vue.d.ts +2181 -0
  114. package/dist/components/date-time-picker-group/types.d.ts +1549 -0
  115. package/dist/components/dynamic-group/index.d.ts +5 -0
  116. package/dist/components/dynamic-group/index.vue.d.ts +457 -0
  117. package/dist/components/dynamic-group/types.d.ts +403 -0
  118. package/dist/components/group/assist.d.ts +58 -0
  119. package/dist/components/group/index.d.ts +6 -0
  120. package/dist/components/group/index.vue.d.ts +139 -0
  121. package/dist/components/group/types.d.ts +189 -0
  122. package/dist/components/group/virtual-group.vue.d.ts +42 -0
  123. package/dist/components/index.d.ts +3 -0
  124. package/dist/components/input/index.d.ts +5 -0
  125. package/dist/components/input/index.vue.d.ts +2229 -0
  126. package/dist/components/input/types.d.ts +1258 -0
  127. package/dist/components/input-slot/index.d.ts +5 -0
  128. package/dist/components/input-slot/index.vue.d.ts +626 -0
  129. package/dist/components/input-slot/types.d.ts +311 -0
  130. package/dist/components/number-keyboard/index.d.ts +5 -0
  131. package/dist/components/number-keyboard/index.vue.d.ts +1643 -0
  132. package/dist/components/number-keyboard/types.d.ts +1324 -0
  133. package/dist/components/password-input/index.d.ts +5 -0
  134. package/dist/components/password-input/index.vue.d.ts +1715 -0
  135. package/dist/components/password-input/types.d.ts +1357 -0
  136. package/dist/components/picker/index.d.ts +5 -0
  137. package/dist/components/picker/index.vue.d.ts +1868 -0
  138. package/dist/components/picker/types.d.ts +1466 -0
  139. package/dist/components/radio/index.d.ts +5 -0
  140. package/dist/components/radio/index.vue.d.ts +1563 -0
  141. package/dist/components/radio/types.d.ts +1327 -0
  142. package/dist/components/radio-group/index.d.ts +5 -0
  143. package/dist/components/radio-group/index.vue.d.ts +1617 -0
  144. package/dist/components/radio-group/types.d.ts +1383 -0
  145. package/dist/components/rate/index.d.ts +5 -0
  146. package/dist/components/rate/index.vue.d.ts +1557 -0
  147. package/dist/components/rate/types.d.ts +1281 -0
  148. package/dist/components/share.d.ts +679 -0
  149. package/dist/components/signature/index.d.ts +5 -0
  150. package/dist/components/signature/index.vue.d.ts +3017 -0
  151. package/dist/components/signature/instance.vue.d.ts +1614 -0
  152. package/dist/components/signature/types.d.ts +1369 -0
  153. package/dist/components/slider/index.d.ts +5 -0
  154. package/dist/components/slider/index.vue.d.ts +1563 -0
  155. package/dist/components/slider/types.d.ts +1302 -0
  156. package/dist/components/stepper/index.d.ts +5 -0
  157. package/dist/components/stepper/index.vue.d.ts +1620 -0
  158. package/dist/components/stepper/types.d.ts +1281 -0
  159. package/dist/components/switch/index.d.ts +5 -0
  160. package/dist/components/switch/index.vue.d.ts +1529 -0
  161. package/dist/components/switch/types.d.ts +1296 -0
  162. package/dist/components/time-picker/index.d.ts +5 -0
  163. package/dist/components/time-picker/index.vue.d.ts +1936 -0
  164. package/dist/components/time-picker/types.d.ts +1458 -0
  165. package/dist/components/tree-select/index.d.ts +5 -0
  166. package/dist/components/tree-select/index.vue.d.ts +1802 -0
  167. package/dist/components/tree-select/types.d.ts +1411 -0
  168. package/dist/components/upload/index.d.ts +5 -0
  169. package/dist/components/upload/index.vue.d.ts +1697 -0
  170. package/dist/components/upload/types.d.ts +1376 -0
  171. package/dist/components/use.d.ts +53 -0
  172. package/dist/components/utils.d.ts +15 -0
  173. package/dist/components/wrapper/index.d.ts +5 -0
  174. package/dist/components/wrapper/index.vue.d.ts +1085 -0
  175. package/dist/components/wrapper/types.d.ts +541 -0
  176. package/dist/docs/.vitepress/config.d.ts +3 -0
  177. package/dist/docs/.vitepress/theme/index.d.ts +2 -0
  178. package/dist/index.cjs.js +5459 -0
  179. package/dist/index.cjs.js.map +1 -0
  180. package/dist/index.cjs.min.js +3568 -0
  181. package/dist/index.cjs.min.js.map +1 -0
  182. package/dist/index.esm.js +5264 -0
  183. package/dist/index.esm.js.map +1 -0
  184. package/dist/index.esm.min.js +3559 -0
  185. package/dist/index.esm.min.js.map +1 -0
  186. package/dist/index.umd.js +5465 -0
  187. package/dist/index.umd.js.map +1 -0
  188. package/dist/index.umd.min.js +3573 -0
  189. package/dist/index.umd.min.js.map +1 -0
  190. package/dist/src/assist.d.ts +32 -0
  191. package/dist/src/index.d.ts +5 -0
  192. package/dist/src/interface.d.ts +129 -0
  193. package/dist/src/utils.d.ts +9 -0
  194. package/dist/src/version.d.ts +2 -0
  195. package/docs/.vitepress/config.ts +99 -0
  196. package/docs/.vitepress/theme/index.ts +5 -0
  197. package/docs/README.md +20 -0
  198. package/docs/index.md +25 -0
  199. package/env.d.ts +8 -0
  200. package/package.json +71 -0
  201. package/scripts/generate-version.mjs +26 -0
  202. package/scripts/postinstall.cjs +13 -0
  203. package/scripts/utils.cjs +67 -0
  204. package/src/assist.ts +40 -0
  205. package/src/index.ts +5 -0
  206. package/src/interface.ts +293 -0
  207. package/src/utils.ts +22 -0
  208. package/src/version.ts +2 -0
  209. package/tsconfig.app.json +41 -0
  210. package/tsconfig.json +7 -0
  211. package/tsconfig.node.json +24 -0
  212. package/tsdown.config.ts +12 -0
  213. package/vite.config.ts +93 -0
@@ -0,0 +1,158 @@
1
+ <template>
2
+ <VanField
3
+ v-if="!hide"
4
+ :name="field"
5
+ :disabled="globalDisabled || disabled"
6
+ :readonly="true"
7
+ :is-link="isLink"
8
+ :model-value="showText"
9
+ v-bind="$attrs"
10
+ @click="clickHandle"
11
+ >
12
+ <template #extra>
13
+ <VanPopup v-model:show="popupInfo.visible" teleport="body" round position="bottom" v-bind="popupProps" v-on="popupOn" @close="popupInfo.close">
14
+ <VanPickerGroup
15
+ v-bind="pickerGroupProps" v-on="pickerGroupOn"
16
+ @confirm="pickerGroupHandle('confirm', $event)" @cancel="pickerGroupHandle('cancel', $event)"
17
+ >
18
+ <VanDatePicker
19
+ ref="datePickerRef"
20
+ :model-value="checkedArr[0]"
21
+ v-bind="datePickerProps" v-on="datePickerOn"
22
+ @change="changeHandle($event, 0)"
23
+ >
24
+ <template v-for="(item, slotName) of datePickerSlots" :key="slotName" #[hyphenate(slotName)]="row">
25
+ <component :is="getNode(item)" v-bind="slotProps" v-bind.prop="row" />
26
+ </template>
27
+ </VanDatePicker>
28
+ <VanTimePicker
29
+ ref="timePickerRef"
30
+ :model-value="checkedArr[1]"
31
+ v-bind="timePickerProps" v-on="timePickerOn"
32
+ @change="changeHandle($event, 1)"
33
+ >
34
+ <template v-for="(item, slotName) of timePickerSlots" :key="slotName" #[hyphenate(slotName)]="row">
35
+ <component :is="getNode(item)" v-bind="slotProps" v-bind.prop="row" />
36
+ </template>
37
+ </VanTimePicker>
38
+ <template v-for="(item, slotName) of pickerGroupSlots" :key="slotName" #[hyphenate(slotName)]="row">
39
+ <component :is="getNode(item)" v-bind="slotProps" v-bind.prop="row" />
40
+ </template>
41
+ </VanPickerGroup>
42
+ </VanPopup>
43
+ </template>
44
+ <template v-for="(item, slotName) of slots" :key="slotName" #[hyphenate(slotName)]="row">
45
+ <component :is="getNode(item)" v-bind="slotProps" v-bind.prop="row" />
46
+ </template>
47
+ </VanField>
48
+ </template>
49
+
50
+ <script lang="ts">
51
+ import { getNode, hyphenate, isArray, usePlain } from '@xiaohaih/json-form-core';
52
+ import type { DatePickerInstance, TimePickerInstance } from 'vant';
53
+ import { DatePicker as VanDatePicker, Field as VanField, PickerGroup as VanPickerGroup, Popup as VanPopup, TimePicker as VanTimePicker } from 'vant';
54
+ import type { SlotsType, VNode } from 'vue';
55
+ import { computed, defineComponent, Fragment, markRaw, nextTick, ref, watch } from 'vue';
56
+ import type { PickerOption } from '../picker/types';
57
+ import { useCommonSetup } from '../use';
58
+ import type { DateTimePickerGroupSlots } from './types';
59
+ import { dateTimePickerGroupEmitsPrivate as emits, dateTimePickerGroupPropsPrivate as props } from './types';
60
+
61
+ /**
62
+ * @file 日期时间组件
63
+ */
64
+ export default defineComponent({
65
+ name: 'HDateTimePickerGroup',
66
+ components: { VanPickerGroup, VanField, VanPopup, VanDatePicker, VanTimePicker },
67
+ inheritAttrs: false,
68
+ props,
69
+ emits,
70
+ slots: Object as SlotsType<DateTimePickerGroupSlots>,
71
+ setup(props, ctx) {
72
+ const plain = usePlain(props);
73
+ const { slotProps } = useCommonSetup(props, ctx, plain);
74
+ /** 展示在页面上的值 */
75
+ const showText = ref('');
76
+ /** 给日期组件的值 */
77
+ const checkedArr = ref<any[]>([]);
78
+ const datePickerRef = ref<DatePickerInstance>();
79
+ const timePickerRef = ref<TimePickerInstance>();
80
+ let tempValue: any;
81
+ // 监听外部值的改变, 如果改变且与临时值不一致时
82
+ // 则更新当前值, 并重置临时值
83
+ watch(
84
+ plain.checked,
85
+ (val) => {
86
+ if (val === tempValue) return tempValue = null;
87
+ tempValue = null;
88
+ checkedArr.value = val ? props.valueUnformat(val) : [];
89
+ showText.value = checkedArr.value.length ? props.format(checkedArr.value) : '';
90
+ },
91
+ { immediate: true },
92
+ );
93
+
94
+ /** 点击事件 */
95
+ function clickHandle(ev: MouseEvent) {
96
+ if (plain.globalDisabled.value || props.disabled || plain.globalReadonly.value || props.readonly) return;
97
+ props.onRowClick ? props.onRowClick(popupInfo.value, ev) : popupInfo.value.open();
98
+ }
99
+ /** 值更改事件 */
100
+ function changeHandle(value: PickerOption, idx: number) {
101
+ checkedArr.value[idx] = value.selectedValues;
102
+ pickerGroupHandle('change');
103
+ }
104
+ /**
105
+ * 日期更改事件
106
+ * @param {string} type 事件类型
107
+ * @param {PickerOption[]} [options] 确认事件会传递该选项
108
+ */
109
+ function pickerGroupHandle(type: string, options?: PickerOption[]) {
110
+ if (type !== 'change' && options) checkedArr.value = options.map((o) => o.selectedValues);
111
+ if ((props.valueTrigger === type || props.pickerGroupProps?.showToolbar === false) && checkedArr.value.length >= 2) {
112
+ plain.change(props.valueFormat(checkedArr.value));
113
+ showText.value = props.format(checkedArr.value);
114
+ tempValue = plain.checked.value;
115
+ nextTick(() => tempValue = null);
116
+ }
117
+ switch (type) {
118
+ case 'confirm':
119
+ case 'cancel':
120
+ {
121
+ popupInfo.value.close();
122
+ break;
123
+ }
124
+ default: break;
125
+ }
126
+ }
127
+
128
+ /** 弹窗显示状态 */
129
+ const popupInfo = ref({
130
+ visible: false,
131
+ open() {
132
+ popupInfo.value.visible = true;
133
+ },
134
+ close() {
135
+ popupInfo.value.visible = false;
136
+ },
137
+ });
138
+
139
+ return {
140
+ hyphenate,
141
+ getNode,
142
+ ...plain,
143
+ slotProps,
144
+ showText,
145
+ checkedArr,
146
+ datePickerRef,
147
+ timePickerRef,
148
+ clickHandle,
149
+ changeHandle,
150
+ pickerGroupHandle,
151
+ popupInfo,
152
+ };
153
+ },
154
+ });
155
+ </script>
156
+
157
+ <style lang="scss" scoped>
158
+ </style>
@@ -0,0 +1,115 @@
1
+ import type { emits2obj, PlainProps } from '@xiaohaih/json-form-core';
2
+ import { emits2props, plainProps } from '@xiaohaih/json-form-core';
3
+ import type { DatePicker as VanDatePicker, Popup as VanPopup, TimePicker as VanTimePicker } from 'vant';
4
+ import { Field as VanField, PickerGroup as VanPickerGroup } from 'vant';
5
+ import type { ExtractPublicPropTypes, PropType } from 'vue';
6
+ import type { ComponentEmit, ComponentExposed, ComponentProps } from 'vue-component-type-helpers';
7
+ import type { PickerOption } from '../picker/types';
8
+ import type { CommonProps, CommonSlots, CommonSlotsProps, ComponentType } from '../share';
9
+ import { commonProps } from '../share';
10
+
11
+ /** 组件传参 - 私有 */
12
+ export function dateTimePickerGroupPropsGeneric<Query extends Record<string, any>, OptionQuery extends Record<string, any>>() {
13
+ return {
14
+ ...commonProps as CommonProps<Query, OptionQuery>,
15
+ ...plainProps as PlainProps<Query, OptionQuery>,
16
+ /** VanPickerGroup 组件的属性 */
17
+ pickerGroupProps: { type: Object as PropType<Partial<ComponentProps<typeof VanPickerGroup>>> },
18
+ /** VanPickerGroup 组件的事件 - 兼容 vue2 版本 */
19
+ pickerGroupOn: { type: Object as PropType<Partial<ReturnType<typeof emits2obj<NonNullable<typeof VanPickerGroup.emits>>>>>, default: () => ({}) },
20
+ /** VanPickerGroup 组件的插槽 */
21
+ pickerGroupSlots: { type: Object as PropType<{
22
+ // /** 默认渲染的内容 */
23
+ // default: ComponentType<CommonSlotsProps<any, any>>;
24
+ /** 自定义整个顶部栏的内容 */
25
+ toolbar?: ComponentType<CommonSlotsProps<any, any>>;
26
+ /** 自定义标题内容 */
27
+ title?: ComponentType<CommonSlotsProps<any, any>>;
28
+ /** 自定义确认按钮内容 */
29
+ confirm?: ComponentType<CommonSlotsProps<any, any>>;
30
+ /** 自定义取消按钮内容 */
31
+ cancel?: ComponentType<CommonSlotsProps<any, any>>;
32
+ }> },
33
+ /** 是否展示右侧箭头并开启点击反馈 - Field 字段, 调整默认值 */
34
+ isLink: { type: Boolean, default: true },
35
+ /** 点击事件, 当传递了此事件时, 会忽略内部打开弹窗操作 */
36
+ onRowClick: { type: Function as PropType<(option: { open: () => void; close: () => void }, ev: MouseEvent) => void> },
37
+ /** 对值进行格式化 - 显示在页面上的值 */
38
+ format: { type: Function as PropType<(option: any) => any>, default: valueFormatDefault },
39
+ /** 对值进行格式化 - 提交值 */
40
+ valueFormat: { type: Function as PropType<(option: PickerOption | any) => any>, default: valueFormatDefault },
41
+ /** 取消值的格式化 - 给 VanPickerGroup 的值 */
42
+ valueUnformat: { type: Function as PropType<(option: any) => string[]>, default: valueUnformatDefault },
43
+ /** 值触发方式 @default confirm */
44
+ valueTrigger: { type: String as PropType<'change' | 'confirm' | 'cancel'>, default: 'confirm' },
45
+ /** VanDatePicker 组件的属性 */
46
+ datePickerProps: { type: Object as PropType<Partial<ComponentProps<typeof VanDatePicker>>> },
47
+ /** VanDatePicker 组件的事件 - 兼容 vue2 版本 */
48
+ datePickerOn: { type: Object as PropType<Partial<ReturnType<typeof emits2obj<NonNullable<typeof VanDatePicker.emits>>>>>, default: () => ({}) },
49
+ /** VanDatePicker 组件的插槽 */
50
+ datePickerSlots: { type: Object as PropType<{
51
+ /** 自定义选项内容 */
52
+ option?: ComponentType<{ option: PickerOption; index: number } & CommonSlotsProps<any, any>>;
53
+ /** 自定义选项上方内容 */
54
+ columnsTop?: ComponentType<CommonSlotsProps<any, any>>;
55
+ /** 自定义选项下方内容 */
56
+ columnsBottom?: ComponentType<CommonSlotsProps<any, any>>;
57
+ }> },
58
+ /** VanTimePicker 组件的属性 */
59
+ timePickerProps: { type: Object as PropType<Partial<ComponentProps<typeof VanTimePicker>>> },
60
+ /** VanTimePicker 组件的事件 - 兼容 vue2 版本 */
61
+ timePickerOn: { type: Object as PropType<Partial<ReturnType<typeof emits2obj<NonNullable<typeof VanTimePicker.emits>>>>>, default: () => ({}) },
62
+ /** VanTimePicker 组件的插槽 */
63
+ timePickerSlots: { type: Object as PropType<{
64
+ /** 自定义选项内容 */
65
+ option?: ComponentType<{ option: PickerOption; index: number } & CommonSlotsProps<any, any>>;
66
+ /** 自定义选项上方内容 */
67
+ columnsTop?: ComponentType<CommonSlotsProps<any, any>>;
68
+ /** 自定义选项下方内容 */
69
+ columnsBottom?: ComponentType<CommonSlotsProps<any, any>>;
70
+ }> },
71
+ /** 弹窗组件的属性 */
72
+ popupProps: { type: Object as PropType<Partial<ComponentExposed<typeof VanPopup>>> },
73
+ /** 弹窗组件的事件 - 兼容 vue2 版本 */
74
+ popupOn: { type: Object as PropType<Partial<ReturnType<typeof emits2obj<NonNullable<typeof VanPopup.emits>>>>>, default: () => ({}) },
75
+ } as const;
76
+ }
77
+ /** 组件传参 - 私有 */
78
+ export const dateTimePickerGroupPropsPrivate = dateTimePickerGroupPropsGeneric();
79
+ /** 组件传参 - 外部调用 */
80
+ export const dateTimePickerGroupProps = {
81
+ ...VanField.props as unknown as {},
82
+ ...dateTimePickerGroupPropsPrivate,
83
+ };
84
+ export type DateTimePickerGroupProps<Query extends Record<string, any>, OptionQuery extends Record<string, any>> = ExtractPublicPropTypes<ReturnType<typeof dateTimePickerGroupPropsGeneric<Query, OptionQuery>>>;
85
+
86
+ /** 组件事件 - 私有 */
87
+ export function dateTimePickerGroupEmitsGeneric<T>() {
88
+ return {};
89
+ }
90
+ /** 组件事件 - 私有 */
91
+ export const dateTimePickerGroupEmitsPrivate = dateTimePickerGroupEmitsGeneric();
92
+ /** 组件事件 - 外部调用 */
93
+ export const dateTimePickerGroupEmits = {
94
+ ...VanField.emits,
95
+ ...dateTimePickerGroupEmitsPrivate,
96
+ };
97
+
98
+ export type DateTimePickerGroupEmits<T> = ReturnType<typeof dateTimePickerGroupEmitsGeneric<T>>;
99
+
100
+ export interface DateTimePickerGroupSlots extends CommonSlots<any> {
101
+ }
102
+
103
+ /** 默认的合并函数 */
104
+ function valueFormatDefault(option: any[]) {
105
+ const result: string[] = [];
106
+ option[0] && result.push(option[0].join('-'));
107
+ option[1] && result.push(option[1].join(':'));
108
+ return result.join(' ');
109
+ }
110
+ /** 默认的取消格式化函数 */
111
+ function valueUnformatDefault(o: string) {
112
+ if (!o) return [];
113
+ const [date, time] = o.split(' ');
114
+ return [date?.split('-'), time?.split(':')].filter(Boolean);
115
+ }
@@ -0,0 +1,6 @@
1
+ import type { ComponentExposed } from 'vue-component-type-helpers';
2
+ import HDatetimePicker from './index.vue';
3
+
4
+ export { HDatetimePicker };
5
+ export type HDatetimePickerInstance = ComponentExposed<typeof HDatetimePicker>;
6
+ export * from './types';
@@ -0,0 +1,128 @@
1
+ <template>
2
+ <VanField
3
+ v-if="!hide"
4
+ :name="field"
5
+ :disabled="globalDisabled || disabled"
6
+ :readonly="true"
7
+ :is-link="isLink"
8
+ :model-value="showText"
9
+ v-bind="$attrs"
10
+ @click="clickHandle"
11
+ >
12
+ <template #extra>
13
+ <VanPopup v-model:show="popupInfo.visible" teleport="body" round position="bottom" v-bind="popupProps" v-on="popupOn" @close="popupInfo.close">
14
+ <VanDatetimePicker
15
+ :model-value="checked"
16
+ v-bind="datetimePickerProps" v-on="datetimePickerOn"
17
+ @change="changeHandle" @confirm="confirmHandle" @cancel="cancelHandle"
18
+ >
19
+ <template v-for="(item, slotName) of datetimePickerSlots" :key="slotName" #[hyphenate(slotName)]="row">
20
+ <component :is="getNode(item)" v-bind="slotProps" v-bind.prop="row" />
21
+ </template>
22
+ </VanDatetimePicker>
23
+ </VanPopup>
24
+ </template>
25
+ <template v-for="(item, slotName) of slots" :key="slotName" #[hyphenate(slotName)]="row">
26
+ <component :is="getNode(item)" v-bind="slotProps" v-bind.prop="row" />
27
+ </template>
28
+ </VanField>
29
+ </template>
30
+
31
+ <script lang="ts">
32
+ import { getNode, hyphenate, usePlain } from '@xiaohaih/json-form-core';
33
+ import { DatetimePicker as VanDatetimePicker, Field as VanField, Popup as VanPopup } from 'vant';
34
+ import type { SlotsType } from 'vue';
35
+ import { computed, defineComponent, nextTick, ref, watch } from 'vue';
36
+ import { useCommonSetup } from '../use';
37
+ import type { DatetimePickerSlots } from './types';
38
+ import { datetimePickerEmitsPrivate as emits, datetimePickerPropsPrivate as props } from './types';
39
+
40
+ /**
41
+ * @file 日期时间选择框 - vant@3.x版本
42
+ */
43
+ export default defineComponent({
44
+ name: 'HDatetimePicker',
45
+ components: { VanDatetimePicker, VanField, VanPopup },
46
+ inheritAttrs: false,
47
+ props,
48
+ emits,
49
+ slots: Object as SlotsType<DatetimePickerSlots>,
50
+ setup(props, ctx) {
51
+ const plain = usePlain(props);
52
+ const { slotProps } = useCommonSetup(props, ctx, plain);
53
+ /** 展示在页面上的值 */
54
+ const showText = ref<string | number>();
55
+ const datetimeValue = ref<Date>();
56
+ let tempValue: any;
57
+ // 监听外部值的改变, 如果改变且与临时值不一致时
58
+ // 则更新当前值, 并重置临时值
59
+ watch(
60
+ plain.checked,
61
+ (val) => {
62
+ if (val === tempValue) return tempValue = null;
63
+ tempValue = null;
64
+ datetimeValue.value = val
65
+ ? props.valueUnformat ? props.valueUnformat(val) : val
66
+ : undefined;
67
+ showText.value = datetimeValue.value ? props.format(datetimeValue.value) : '';
68
+ },
69
+ { immediate: true },
70
+ );
71
+
72
+ /** 点击事件 */
73
+ function clickHandle(ev: MouseEvent) {
74
+ if (plain.globalDisabled.value || props.disabled || plain.globalReadonly.value || props.readonly) return;
75
+ props.onRowClick ? props.onRowClick(popupInfo.value, ev) : popupInfo.value.open();
76
+ }
77
+ /**
78
+ * 日期更改事件
79
+ * @param {string} type 事件类型
80
+ * @param {string} value 日期值
81
+ */
82
+ function dateEventHandle(type: string, value: Date) {
83
+ if (props.valueTrigger === type || props.datetimePickerProps?.showToolbar === false) {
84
+ plain.change(props.valueFormat ? props.valueFormat(value) : value);
85
+ showText.value = props.format(value);
86
+ tempValue = plain.checked.value;
87
+ nextTick(() => tempValue = null);
88
+ }
89
+ switch (type) {
90
+ case 'confirm':
91
+ case 'cancel':
92
+ {
93
+ popupInfo.value.close();
94
+ break;
95
+ }
96
+ default: break;
97
+ }
98
+ }
99
+
100
+ /** 弹窗显示状态 */
101
+ const popupInfo = ref({
102
+ visible: false,
103
+ open() {
104
+ popupInfo.value.visible = true;
105
+ },
106
+ close() {
107
+ popupInfo.value.visible = false;
108
+ },
109
+ });
110
+
111
+ return {
112
+ hyphenate,
113
+ getNode,
114
+ ...plain,
115
+ slotProps,
116
+ showText,
117
+ clickHandle,
118
+ changeHandle: dateEventHandle.bind(null, 'change'),
119
+ confirmHandle: dateEventHandle.bind(null, 'confirm'),
120
+ cancelHandle: dateEventHandle.bind(null, 'cancel'),
121
+ popupInfo,
122
+ };
123
+ },
124
+ });
125
+ </script>
126
+
127
+ <style lang="scss" scoped>
128
+ </style>
@@ -0,0 +1,78 @@
1
+ import type { emits2obj, PlainProps } from '@xiaohaih/json-form-core';
2
+ import { emits2props, plainProps } from '@xiaohaih/json-form-core';
3
+ import type { Popup as VanPopup } from 'vant';
4
+ import { DatetimePicker as VanDatetimePicker, Field as VanField } from 'vant';
5
+ import type { ExtractPublicPropTypes, PropType } from 'vue';
6
+ import type { ComponentEmit, ComponentExposed, ComponentProps } from 'vue-component-type-helpers';
7
+ import type { CommonProps, CommonSlots, CommonSlotsProps, ComponentType } from '../share';
8
+ import { commonProps } from '../share';
9
+
10
+ /** 组件传参 - 私有 */
11
+ export function datetimePickerPropsGeneric<Query extends Record<string, any>, OptionQuery extends Record<string, any>>() {
12
+ return {
13
+ ...commonProps as CommonProps<Query, OptionQuery>,
14
+ ...plainProps as PlainProps<Query, OptionQuery>,
15
+ /** VanDatetimePicker 组件的属性 */
16
+ datetimePickerProps: { type: Object as PropType<Partial<ComponentProps<typeof VanDatetimePicker>>> },
17
+ /** VanDatetimePicker 组件的事件 - 兼容 vue2 版本 */
18
+ datetimePickerOn: { type: Object as PropType<Partial<ReturnType<typeof emits2obj<NonNullable<typeof VanDatetimePicker.emits>>>>>, default: () => ({}) },
19
+ /** VanDatetimePicker 组件的插槽 */
20
+ datetimePickerSlots: { type: Object as PropType<{
21
+ /** 自定义整个顶部栏的内容 */
22
+ default?: ComponentType<CommonSlotsProps<any, any>>;
23
+ /** 自定义标题内容 */
24
+ title?: ComponentType<CommonSlotsProps<any, any>>;
25
+ /** 自定义确认按钮内容 */
26
+ confirm?: ComponentType<CommonSlotsProps<any, any>>;
27
+ /** 自定义取消按钮内容 */
28
+ cancel?: ComponentType<CommonSlotsProps<any, any>>;
29
+ /** 自定义选项内容 */
30
+ option?: ComponentType<{ option: string | Record<string, any> } & CommonSlotsProps<any, any>>;
31
+ /** 自定义选项上方内容 */
32
+ columnsTop?: ComponentType<CommonSlotsProps<any, any>>;
33
+ /** 自定义选项下方内容 */
34
+ columnsBottom?: ComponentType<CommonSlotsProps<any, any>>;
35
+ }> },
36
+ /** 是否展示右侧箭头并开启点击反馈 - Field 字段, 调整默认值 */
37
+ isLink: { type: Boolean, default: true },
38
+ /** 点击事件, 当传递了此事件时, 会忽略内部打开弹窗操作 */
39
+ onRowClick: { type: Function as PropType<(option: { open: () => void; close: () => void }, ev: MouseEvent) => void> },
40
+ /** 对值进行格式化 - 显示在页面上的值 */
41
+ format: { type: Function as PropType<(value: Date) => string | number>, required: true },
42
+ /** 对值进行格式化 - 提交值 */
43
+ valueFormat: { type: Function as PropType<(value: Date) => any> },
44
+ /** 取消值的格式化 - 给 VanDatetimePicker 的值 */
45
+ valueUnformat: { type: Function as PropType<(value: any) => Date> },
46
+ /** 值触发方式 @default confirm */
47
+ valueTrigger: { type: String as PropType<'change' | 'confirm' | 'cancel'>, default: 'confirm' },
48
+ /** 弹窗组件的属性 */
49
+ popupProps: { type: Object as PropType<Partial<ComponentExposed<typeof VanPopup>>> },
50
+ /** 弹窗组件的事件 - 兼容 vue2 版本 */
51
+ popupOn: { type: Object as PropType<Partial<ReturnType<typeof emits2obj<NonNullable<typeof VanPopup.emits>>>>>, default: () => ({}) },
52
+ } as const;
53
+ }
54
+ /** 组件传参 - 私有 */
55
+ export const datetimePickerPropsPrivate = datetimePickerPropsGeneric();
56
+ /** 组件传参 - 外部调用 */
57
+ export const datetimePickerProps = {
58
+ ...VanField.props as unknown as {},
59
+ ...datetimePickerPropsPrivate,
60
+ };
61
+ export type DatetimePickerProps<Query extends Record<string, any>, OptionQuery extends Record<string, any>> = ExtractPublicPropTypes<ReturnType<typeof datetimePickerPropsGeneric<Query, OptionQuery>>>;
62
+
63
+ /** 组件事件 - 私有 */
64
+ export function datetimePickerEmitsGeneric<T>() {
65
+ return {};
66
+ }
67
+ /** 组件事件 - 私有 */
68
+ export const datetimePickerEmitsPrivate = datetimePickerEmitsGeneric();
69
+ /** 组件事件 - 外部调用 */
70
+ export const datetimePickerEmits = {
71
+ ...VanField.emits,
72
+ ...datetimePickerEmitsPrivate,
73
+ };
74
+
75
+ export type DatetimePickerEmits<T> = ReturnType<typeof datetimePickerEmitsGeneric<T>>;
76
+
77
+ export interface DatetimePickerSlots extends CommonSlots<any> {
78
+ }
@@ -0,0 +1,10 @@
1
+ import type { ComponentExposed, ComponentProps } from 'vue-component-type-helpers';
2
+ import { registerComponent } from '../group/index';
3
+ import HDynamicGroup from './index.vue';
4
+ // 为防止循环依赖(dynamic-group -> group -> assist -> dynamic-group),
5
+ // 异步注册组件
6
+ registerComponent('dynamic-group', HDynamicGroup);
7
+
8
+ export { HDynamicGroup };
9
+ export type HDynamicGroupInstance = ComponentExposed<typeof HDynamicGroup>;
10
+ export * from './types';
@@ -0,0 +1,140 @@
1
+ <template>
2
+ <VirtualGroup ref="virtualGroupRef" :tag="tag">
3
+ <template v-if="slots?.prepend || ($slots as DynamicGroupSlots).prepend">
4
+ <component :is="getNode(slots?.prepend || ($slots as DynamicGroupSlots).prepend)" :query="query" :checked="plain.checked.value" :plain="plain" />
5
+ </template>
6
+ <template v-for="(opt, idx) of finalConfig" :key="opt.uniqueValue">
7
+ <div v-bind="contentProps">
8
+ <component :is="itemSlots.prepend" :query="query" :checked="plain.checked.value" :index="idx" :plain="plain" />
9
+ <template v-for="(item) of opt.options" :key="`${field}.${idx}.${item.field || item[REWRITE_FIELD_KEY]}`">
10
+ <component :is="getComponent2(item.t)!" v-if="item" v-bind="item" :unique-value="opt.uniqueValue" :field="`${field}.${idx}.${item.field || item[REWRITE_FIELD_KEY]}`" :query="query" :parent-query="plain.checked.value[idx]" />
11
+ </template>
12
+ <component :is="itemSlots.append" :query="query" :checked="plain.checked.value" :index="idx" :plain="plain" />
13
+ </div>
14
+ </template>
15
+ <template v-if="slots?.append || ($slots as DynamicGroupSlots).append">
16
+ <component :is="getNode(slots?.append || ($slots as DynamicGroupSlots).append)" :query="query" :checked="plain.checked.value" :plain="plain" />
17
+ </template>
18
+ </VirtualGroup>
19
+ </template>
20
+
21
+ <script lang="tsx">
22
+ import type { PlainProps } from '@xiaohaih/json-form-core';
23
+ import { defineCommonMethod, get, getNode, getProvideValue, hyphenate, isPlainObject, set, usePlain } from '@xiaohaih/json-form-core';
24
+ import type { ExtractPublicPropTypes, Ref, SlotsType } from 'vue';
25
+ import { computed, defineComponent, inject, markRaw, ref, watch } from 'vue';
26
+ import { pick } from '../../src/utils';
27
+ import { getComponent, HGroup } from '../group/index';
28
+ import VirtualGroup from '../group/virtual-group.vue';
29
+ import type { DynamicGroupSlots } from './types';
30
+ import { dynamicGroupEmitsPrivate as emits, dynamicGroupPropsPrivate as props } from './types';
31
+
32
+ type Option = Omit<ExtractPublicPropTypes<PlainProps<Record<string, any>, Record<string, any>>>, 'query'> & { t: string; [REWRITE_FIELD_KEY]: string };
33
+
34
+ let globalId = 0;
35
+ /** 当 field 不存在, 但 fields 存在时, 合并 fields 到对象上的 key */
36
+ const REWRITE_FIELD_KEY = '__field__' as const;
37
+
38
+ /**
39
+ * @file 自定义组件 - 动态删减组件(对应动态表单)
40
+ */
41
+ export default defineComponent({
42
+ name: 'HDynamicGroup',
43
+ components: {
44
+ VirtualGroup,
45
+ },
46
+ props,
47
+ emits,
48
+ slots: Object as SlotsType<DynamicGroupSlots>,
49
+ setup(props, ctx) {
50
+ const virtualGroupRef = ref<Record<string, any> | undefined>();
51
+ const tagRef = computed(() => virtualGroupRef.value?.tagRef);
52
+ const plain = usePlain(props);
53
+ const checked = plain.checked as Ref<Record<string, any>[] | undefined>;
54
+
55
+ // /** watch 版本的配置项, watch 自带旧值记录, 方便做优化 */
56
+ // const finalConfig = ref<{ uniqueValue: string | number; options: Option[] }[]>([]);
57
+ // watch(
58
+ // [() => checked.value && [...checked.value], () => props.config],
59
+ // ([value, config], oldVal) => {
60
+ // if (!value?.length) return finalConfig.value = [];
61
+ // const { uniqueKey } = props;
62
+ // const isFunc = typeof config === 'function';
63
+ // const arr = !isFunc && coverObjOption2Arr<Option[]>(config);
64
+ // finalConfig.value = value.map((o, i) => ({
65
+ // uniqueValue: uniqueKey ? o[uniqueKey] : getId(o, oldVal?.[0], i),
66
+ // options: isFunc ? coverObjOption2Arr<Option[]>(config({ item: o, index: i, query: props.query })) : arr as Option[],
67
+ // }));
68
+ // },
69
+ // { immediate: true },
70
+ // );
71
+ // /**
72
+ // * 获取唯一 id, 如果与旧引用相同, 则复用唯一 id(配合 finalConfig - watch 版本使用)
73
+ // * (为动态新增的表单项做的优化, 不然可以用下方的计算属性(finalConfig))
74
+ // */
75
+ // function getId(val: Record<string, any>, oldVal: Record<string, any>[] | undefined, idx: number) {
76
+ // return oldVal?.[idx] === val ? finalConfig.value[idx].uniqueValue : ++globalId;
77
+ // }
78
+ /** 由于计算属性不似 watch 有上条数据, 因为手动记录 */
79
+ let configSnapshot = {
80
+ /** 记录每行配置项的唯一值集合 */
81
+ configUniqueValue: [] as any[],
82
+ /** 记录每行数据的值集合 */
83
+ checkedValue: [] as any[],
84
+ };
85
+ /** 计算属性版本的 config 配置项(防止生成的配置项中用了响应式变量, 不在计算属性中生成无法捕捉到) */
86
+ const finalConfig = computed(() => {
87
+ const { config } = props;
88
+ if (!config) return [];
89
+ const value = checked.value;
90
+ if (!value?.length) return [];
91
+ const isFunc = typeof config === 'function';
92
+ const arr = !isFunc && coverObjOption2Arr<Option[]>(config);
93
+ const { uniqueKey } = props;
94
+ const result = value.map((o, i) => ({ uniqueValue: uniqueKey ? o[uniqueKey] : getId(o, i), options: isFunc ? coverObjOption2Arr<Option[]>(config({ item: o, index: i, checked: value, query: props.query, plain })) : arr as Option[] }));
95
+ // eslint-disable-next-line vue/no-side-effects-in-computed-properties
96
+ configSnapshot.configUniqueValue = result.map((r) => r.uniqueValue);
97
+ // eslint-disable-next-line vue/no-side-effects-in-computed-properties
98
+ configSnapshot.checkedValue = [...value];
99
+ return result;
100
+ });
101
+ /**
102
+ * 获取唯一 id, 如果与旧引用相同, 则复用唯一 id(配合 finalConfig - computed 版本使用)
103
+ * (为动态新增的表单项做的优化, 不然可以用下方的计算属性(finalConfig))
104
+ */
105
+ function getId(val: Record<string, any>, idx: number) {
106
+ return configSnapshot.checkedValue[idx] === val ? configSnapshot.configUniqueValue[idx] : ++globalId;
107
+ }
108
+ /** 将对象形式的配置项转为数组 */
109
+ function coverObjOption2Arr<T>(opt: any): T {
110
+ if (isPlainObject(opt)) {
111
+ const r: any[] = [];
112
+ Object.entries(opt).forEach(([key, value]) => {
113
+ value.field = key;
114
+ r.push(value);
115
+ });
116
+ return r as unknown as T;
117
+ }
118
+ opt.forEach((o: any) => !o.field && o.fields && (o[REWRITE_FIELD_KEY] = o.fields.join(',')));
119
+ return opt as unknown as T;
120
+ }
121
+
122
+ function getComponent2(name: string) {
123
+ return name === 'dynamic-group' ? 'HDynamicGroup' : name === 'group' ? HGroup : getComponent(name);
124
+ }
125
+
126
+ return {
127
+ hyphenate,
128
+ getNode,
129
+ REWRITE_FIELD_KEY,
130
+ virtualGroupRef,
131
+ tagRef,
132
+ plain,
133
+ finalConfig,
134
+ getComponent2,
135
+ };
136
+ },
137
+ });
138
+ </script>
139
+
140
+ <style lang="css" scoped></style>