@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.
- package/CHANGELOG.md +9 -0
- package/README.md +807 -0
- package/TODO.md +36 -0
- package/components/area/index.ts +6 -0
- package/components/area/index.vue +120 -0
- package/components/area/types.ts +84 -0
- package/components/cascader/index.ts +6 -0
- package/components/cascader/index.vue +146 -0
- package/components/cascader/types.ts +75 -0
- package/components/checkbox/index.ts +6 -0
- package/components/checkbox/index.vue +59 -0
- package/components/checkbox/types.ts +54 -0
- package/components/checkbox-group/index.ts +6 -0
- package/components/checkbox-group/index.vue +67 -0
- package/components/checkbox-group/types.ts +63 -0
- package/components/component-definition/components.ts +29 -0
- package/components/component-definition/definition.ts +25 -0
- package/components/component-definition/index.ts +4 -0
- package/components/custom-render/index.ts +6 -0
- package/components/custom-render/index.vue +66 -0
- package/components/custom-render/types.ts +43 -0
- package/components/date-picker/index.ts +6 -0
- package/components/date-picker/index.vue +130 -0
- package/components/date-picker/types.ts +91 -0
- package/components/date-time-picker-group/index.ts +6 -0
- package/components/date-time-picker-group/index.vue +158 -0
- package/components/date-time-picker-group/types.ts +115 -0
- package/components/datetime-picker/index.ts +6 -0
- package/components/datetime-picker/index.vue +128 -0
- package/components/datetime-picker/types.ts +78 -0
- package/components/dynamic-group/index.ts +10 -0
- package/components/dynamic-group/index.vue +140 -0
- package/components/dynamic-group/types.ts +68 -0
- package/components/group/assist.ts +99 -0
- package/components/group/index.ts +7 -0
- package/components/group/index.vue +117 -0
- package/components/group/types.ts +57 -0
- package/components/group/virtual-group.vue +38 -0
- package/components/index.ts +10 -0
- package/components/input/index.ts +6 -0
- package/components/input/index.vue +83 -0
- package/components/input/types.ts +43 -0
- package/components/input-slot/index.ts +6 -0
- package/components/input-slot/index.vue +148 -0
- package/components/input-slot/types.ts +34 -0
- package/components/number-keyboard/index.ts +6 -0
- package/components/number-keyboard/index.vue +81 -0
- package/components/number-keyboard/types.ts +57 -0
- package/components/password-input/index.ts +6 -0
- package/components/password-input/index.vue +103 -0
- package/components/password-input/types.ts +64 -0
- package/components/picker/index.ts +6 -0
- package/components/picker/index.vue +136 -0
- package/components/picker/types.ts +94 -0
- package/components/radio/index.ts +6 -0
- package/components/radio/index.vue +68 -0
- package/components/radio/types.ts +58 -0
- package/components/radio-group/index.ts +6 -0
- package/components/radio-group/index.vue +74 -0
- package/components/radio-group/types.ts +65 -0
- package/components/rate/index.ts +6 -0
- package/components/rate/index.vue +63 -0
- package/components/rate/types.ts +47 -0
- package/components/share.ts +78 -0
- package/components/signature/index.ts +6 -0
- package/components/signature/index.vue +65 -0
- package/components/signature/instance.vue +161 -0
- package/components/signature/types.ts +79 -0
- package/components/slider/index.ts +6 -0
- package/components/slider/index.vue +63 -0
- package/components/slider/types.ts +53 -0
- package/components/stepper/index.ts +6 -0
- package/components/stepper/index.vue +62 -0
- package/components/stepper/types.ts +47 -0
- package/components/switch/index.ts +6 -0
- package/components/switch/index.vue +61 -0
- package/components/switch/types.ts +51 -0
- package/components/time-picker/index.ts +6 -0
- package/components/time-picker/index.vue +130 -0
- package/components/time-picker/types.ts +91 -0
- package/components/tree-select/index.ts +6 -0
- package/components/tree-select/index.vue +160 -0
- package/components/tree-select/types.ts +77 -0
- package/components/upload/index.ts +6 -0
- package/components/upload/index.vue +109 -0
- package/components/upload/types.ts +85 -0
- package/components/use.ts +45 -0
- package/components/utils.ts +52 -0
- package/components/wrapper/index.ts +6 -0
- package/components/wrapper/index.vue +117 -0
- package/components/wrapper/types.ts +94 -0
- package/dist/components/area/index.d.ts +5 -0
- package/dist/components/area/index.vue.d.ts +1843 -0
- package/dist/components/area/types.d.ts +1434 -0
- package/dist/components/cascader/index.d.ts +5 -0
- package/dist/components/cascader/index.vue.d.ts +2467 -0
- package/dist/components/cascader/types.d.ts +1419 -0
- package/dist/components/checkbox/index.d.ts +5 -0
- package/dist/components/checkbox/index.vue.d.ts +1550 -0
- package/dist/components/checkbox/types.d.ts +1313 -0
- package/dist/components/checkbox-group/index.d.ts +5 -0
- package/dist/components/checkbox-group/index.vue.d.ts +1643 -0
- package/dist/components/checkbox-group/types.d.ts +1372 -0
- package/dist/components/component-definition/components.d.ts +30 -0
- package/dist/components/component-definition/index.d.ts +4 -0
- package/dist/components/custom-render/index.d.ts +5 -0
- package/dist/components/custom-render/index.vue.d.ts +1473 -0
- package/dist/components/custom-render/types.d.ts +1175 -0
- package/dist/components/date-picker/index.d.ts +5 -0
- package/dist/components/date-picker/index.vue.d.ts +1888 -0
- package/dist/components/date-picker/types.d.ts +1458 -0
- package/dist/components/date-time-picker-group/index.d.ts +5 -0
- package/dist/components/date-time-picker-group/index.vue.d.ts +2181 -0
- package/dist/components/date-time-picker-group/types.d.ts +1549 -0
- package/dist/components/dynamic-group/index.d.ts +5 -0
- package/dist/components/dynamic-group/index.vue.d.ts +457 -0
- package/dist/components/dynamic-group/types.d.ts +403 -0
- package/dist/components/group/assist.d.ts +58 -0
- package/dist/components/group/index.d.ts +6 -0
- package/dist/components/group/index.vue.d.ts +139 -0
- package/dist/components/group/types.d.ts +189 -0
- package/dist/components/group/virtual-group.vue.d.ts +42 -0
- package/dist/components/index.d.ts +3 -0
- package/dist/components/input/index.d.ts +5 -0
- package/dist/components/input/index.vue.d.ts +2229 -0
- package/dist/components/input/types.d.ts +1258 -0
- package/dist/components/input-slot/index.d.ts +5 -0
- package/dist/components/input-slot/index.vue.d.ts +626 -0
- package/dist/components/input-slot/types.d.ts +311 -0
- package/dist/components/number-keyboard/index.d.ts +5 -0
- package/dist/components/number-keyboard/index.vue.d.ts +1643 -0
- package/dist/components/number-keyboard/types.d.ts +1324 -0
- package/dist/components/password-input/index.d.ts +5 -0
- package/dist/components/password-input/index.vue.d.ts +1715 -0
- package/dist/components/password-input/types.d.ts +1357 -0
- package/dist/components/picker/index.d.ts +5 -0
- package/dist/components/picker/index.vue.d.ts +1868 -0
- package/dist/components/picker/types.d.ts +1466 -0
- package/dist/components/radio/index.d.ts +5 -0
- package/dist/components/radio/index.vue.d.ts +1563 -0
- package/dist/components/radio/types.d.ts +1327 -0
- package/dist/components/radio-group/index.d.ts +5 -0
- package/dist/components/radio-group/index.vue.d.ts +1617 -0
- package/dist/components/radio-group/types.d.ts +1383 -0
- package/dist/components/rate/index.d.ts +5 -0
- package/dist/components/rate/index.vue.d.ts +1557 -0
- package/dist/components/rate/types.d.ts +1281 -0
- package/dist/components/share.d.ts +679 -0
- package/dist/components/signature/index.d.ts +5 -0
- package/dist/components/signature/index.vue.d.ts +3017 -0
- package/dist/components/signature/instance.vue.d.ts +1614 -0
- package/dist/components/signature/types.d.ts +1369 -0
- package/dist/components/slider/index.d.ts +5 -0
- package/dist/components/slider/index.vue.d.ts +1563 -0
- package/dist/components/slider/types.d.ts +1302 -0
- package/dist/components/stepper/index.d.ts +5 -0
- package/dist/components/stepper/index.vue.d.ts +1620 -0
- package/dist/components/stepper/types.d.ts +1281 -0
- package/dist/components/switch/index.d.ts +5 -0
- package/dist/components/switch/index.vue.d.ts +1529 -0
- package/dist/components/switch/types.d.ts +1296 -0
- package/dist/components/time-picker/index.d.ts +5 -0
- package/dist/components/time-picker/index.vue.d.ts +1936 -0
- package/dist/components/time-picker/types.d.ts +1458 -0
- package/dist/components/tree-select/index.d.ts +5 -0
- package/dist/components/tree-select/index.vue.d.ts +1802 -0
- package/dist/components/tree-select/types.d.ts +1411 -0
- package/dist/components/upload/index.d.ts +5 -0
- package/dist/components/upload/index.vue.d.ts +1697 -0
- package/dist/components/upload/types.d.ts +1376 -0
- package/dist/components/use.d.ts +53 -0
- package/dist/components/utils.d.ts +15 -0
- package/dist/components/wrapper/index.d.ts +5 -0
- package/dist/components/wrapper/index.vue.d.ts +1085 -0
- package/dist/components/wrapper/types.d.ts +541 -0
- package/dist/docs/.vitepress/config.d.ts +3 -0
- package/dist/docs/.vitepress/theme/index.d.ts +2 -0
- package/dist/index.cjs.js +5459 -0
- package/dist/index.cjs.js.map +1 -0
- package/dist/index.cjs.min.js +3568 -0
- package/dist/index.cjs.min.js.map +1 -0
- package/dist/index.esm.js +5264 -0
- package/dist/index.esm.js.map +1 -0
- package/dist/index.esm.min.js +3559 -0
- package/dist/index.esm.min.js.map +1 -0
- package/dist/index.umd.js +5465 -0
- package/dist/index.umd.js.map +1 -0
- package/dist/index.umd.min.js +3573 -0
- package/dist/index.umd.min.js.map +1 -0
- package/dist/src/assist.d.ts +32 -0
- package/dist/src/index.d.ts +5 -0
- package/dist/src/interface.d.ts +129 -0
- package/dist/src/utils.d.ts +9 -0
- package/dist/src/version.d.ts +2 -0
- package/docs/.vitepress/config.ts +99 -0
- package/docs/.vitepress/theme/index.ts +5 -0
- package/docs/README.md +20 -0
- package/docs/index.md +25 -0
- package/env.d.ts +8 -0
- package/package.json +71 -0
- package/scripts/generate-version.mjs +26 -0
- package/scripts/postinstall.cjs +13 -0
- package/scripts/utils.cjs +67 -0
- package/src/assist.ts +40 -0
- package/src/index.ts +5 -0
- package/src/interface.ts +293 -0
- package/src/utils.ts +22 -0
- package/src/version.ts +2 -0
- package/tsconfig.app.json +41 -0
- package/tsconfig.json +7 -0
- package/tsconfig.node.json +24 -0
- package/tsdown.config.ts +12 -0
- package/vite.config.ts +93 -0
package/TODO.md
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# 组件改造任务清单
|
|
2
|
+
|
|
3
|
+
## 每个组件需要满足的两个条件:
|
|
4
|
+
1. **slotProps**: `const { slotProps } = useCommonSetup(props, ctx, plain);` 并在 setup 返回 slotProps
|
|
5
|
+
2. **Slots声明+渲染**: types.ts 中声明插槽类型 + index.vue 中 v-for 遍历渲染插槽
|
|
6
|
+
|
|
7
|
+
## 各组件状态一览
|
|
8
|
+
|
|
9
|
+
### ✅ 已完成(不需要修改)
|
|
10
|
+
- cascader - ✅ slotProps + slots渲染
|
|
11
|
+
- checkbox - ✅ slotProps + slots渲染
|
|
12
|
+
- input - ✅ slotProps + slots渲染
|
|
13
|
+
- radio - ✅ slotProps + slots渲染
|
|
14
|
+
|
|
15
|
+
### ❌ 缺少 useCommonSetup + slotProps (但Slots已声明)
|
|
16
|
+
- datepicker - ❌ 无useCommonSetup/slotProps,无slots渲染
|
|
17
|
+
- number-keyboard - ❌ 无useCommonSetup/slotProps,无slots渲染
|
|
18
|
+
- rate - ❌ 无useCommonSetup/slotProps,无slots渲染
|
|
19
|
+
- signature - ❌ 无useCommonSetup/slotProps,无slots渲染
|
|
20
|
+
- slider - ❌ 无useCommonSetup/slotProps,无slots渲染
|
|
21
|
+
- stepper - ❌ 无useCommonSetup/slotProps,无slots渲染
|
|
22
|
+
- switch - ❌ 无useCommonSetup/slotProps,无slots渲染
|
|
23
|
+
- timepicker - ❌ 无useCommonSetup/slotProps,无slots渲染
|
|
24
|
+
- upload - ❌ 无useCommonSetup/slotProps,无slots渲染
|
|
25
|
+
|
|
26
|
+
### ❌ 缺少 slotProps 渲染 + types.ts 中Slots需要修复
|
|
27
|
+
- password-input - ❌ 无slots声明,无useCommonSetup/slotProps,无slots渲染,PasswordInputSlots为空
|
|
28
|
+
|
|
29
|
+
### ❌ 已有slotProps但模板缺少slots渲染
|
|
30
|
+
- checkbox-group - ✅ slotProps,但模板缺少slots渲染
|
|
31
|
+
- radio-group - ✅ slotProps,但模板缺少slots渲染
|
|
32
|
+
|
|
33
|
+
### ⬜ 不适用(非标准表单组件)
|
|
34
|
+
- group - 不适用
|
|
35
|
+
- input-slot - 不适用
|
|
36
|
+
- wrapper - 不适用
|
|
@@ -0,0 +1,120 @@
|
|
|
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
|
+
<VanArea
|
|
15
|
+
:model-value="checked"
|
|
16
|
+
:area-list="finalOption"
|
|
17
|
+
v-bind="areaProps" v-on="areaOn"
|
|
18
|
+
@change="changeHandle" @confirm="confirmHandle" @cancel="cancelHandle"
|
|
19
|
+
>
|
|
20
|
+
<template v-for="(item, slotName) of areaSlots" :key="slotName" #[hyphenate(slotName)]="row">
|
|
21
|
+
<component :is="getNode(item)" v-bind="slotProps" v-bind.prop="row" />
|
|
22
|
+
</template>
|
|
23
|
+
</VanArea>
|
|
24
|
+
</VanPopup>
|
|
25
|
+
</template>
|
|
26
|
+
<template v-for="(item, slotName) of slots" :key="slotName" #[hyphenate(slotName)]="row">
|
|
27
|
+
<component :is="getNode(item)" v-bind="slotProps" v-bind.prop="row" />
|
|
28
|
+
</template>
|
|
29
|
+
</VanField>
|
|
30
|
+
</template>
|
|
31
|
+
|
|
32
|
+
<script lang="ts">
|
|
33
|
+
import { getNode, hyphenate, usePlain } from '@xiaohaih/json-form-core';
|
|
34
|
+
import { Area as VanArea, Field as VanField, Popup as VanPopup } from 'vant';
|
|
35
|
+
import type { SlotsType } from 'vue';
|
|
36
|
+
import { computed, defineComponent, ref } from 'vue';
|
|
37
|
+
import type { PickerOption } from '../picker/types';
|
|
38
|
+
import { useCommonSetup } from '../use';
|
|
39
|
+
import type { AreaSlots } from './types';
|
|
40
|
+
import { areaEmitsPrivate as emits, areaPropsPrivate as props } from './types';
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* @file 区域选择框
|
|
44
|
+
*/
|
|
45
|
+
export default defineComponent({
|
|
46
|
+
name: 'HArea',
|
|
47
|
+
components: { VanArea, VanField, VanPopup },
|
|
48
|
+
inheritAttrs: false,
|
|
49
|
+
props,
|
|
50
|
+
emits,
|
|
51
|
+
slots: Object as SlotsType<AreaSlots>,
|
|
52
|
+
setup(props, ctx) {
|
|
53
|
+
const plain = usePlain(props);
|
|
54
|
+
const { slotProps } = useCommonSetup(props, ctx, plain);
|
|
55
|
+
/** 展示在页面上的值 */
|
|
56
|
+
const showText = computed(() => {
|
|
57
|
+
const value = plain.checked.value as string;
|
|
58
|
+
if (!value) return '';
|
|
59
|
+
const { format, showAllLevels, separator } = props;
|
|
60
|
+
const source = (props.areaProps?.areaList || plain.finalOption.value) as Record<string, any>;
|
|
61
|
+
if (format) return format({ source, value, showAllLevels, separator });
|
|
62
|
+
const result: string[] = [];
|
|
63
|
+
source.province_list && result.push(source.province_list[`${value.slice(0, 2)}0000`]);
|
|
64
|
+
value.length >= 4 && source.city_list && result.push(source.city_list[`${value.slice(0, 4)}00`]);
|
|
65
|
+
value.length >= 6 && source.county_list && result.push(source.county_list[value]);
|
|
66
|
+
return result.filter(Boolean).join(separator);
|
|
67
|
+
});
|
|
68
|
+
/** 点击事件 */
|
|
69
|
+
function clickHandle(ev: MouseEvent) {
|
|
70
|
+
if (plain.globalDisabled.value || props.disabled || plain.globalReadonly.value || props.readonly) return;
|
|
71
|
+
props.onRowClick ? props.onRowClick(popupInfo.value, ev) : popupInfo.value.open();
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* 更改事件
|
|
75
|
+
* @param {string} type 事件类型
|
|
76
|
+
* @param {string} value 日期值
|
|
77
|
+
*/
|
|
78
|
+
function dateEventHandle(type: string, value: PickerOption) {
|
|
79
|
+
// @ts-expect-error 忽视 showToolbar 声明报错
|
|
80
|
+
(props.valueTrigger === type || props.areaProps?.showToolbar === false) && plain.change(value.selectedValues.slice(-1)[0]);
|
|
81
|
+
switch (type) {
|
|
82
|
+
case 'confirm':
|
|
83
|
+
case 'cancel':
|
|
84
|
+
{
|
|
85
|
+
popupInfo.value.close();
|
|
86
|
+
break;
|
|
87
|
+
}
|
|
88
|
+
default: break;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/** 弹窗显示状态 */
|
|
93
|
+
const popupInfo = ref({
|
|
94
|
+
visible: false,
|
|
95
|
+
open() {
|
|
96
|
+
popupInfo.value.visible = true;
|
|
97
|
+
},
|
|
98
|
+
close() {
|
|
99
|
+
popupInfo.value.visible = false;
|
|
100
|
+
},
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
return {
|
|
104
|
+
hyphenate,
|
|
105
|
+
getNode,
|
|
106
|
+
...plain,
|
|
107
|
+
slotProps,
|
|
108
|
+
showText,
|
|
109
|
+
clickHandle,
|
|
110
|
+
changeHandle: dateEventHandle.bind(null, 'change'),
|
|
111
|
+
confirmHandle: dateEventHandle.bind(null, 'confirm'),
|
|
112
|
+
cancelHandle: dateEventHandle.bind(null, 'cancel'),
|
|
113
|
+
popupInfo,
|
|
114
|
+
};
|
|
115
|
+
},
|
|
116
|
+
});
|
|
117
|
+
</script>
|
|
118
|
+
|
|
119
|
+
<style lang="scss" scoped>
|
|
120
|
+
</style>
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import type { emits2obj, PlainProps } from '@xiaohaih/json-form-core';
|
|
2
|
+
import { emits2props, plainProps } from '@xiaohaih/json-form-core';
|
|
3
|
+
import type { Area as VanArea, Popup as VanPopup } from 'vant';
|
|
4
|
+
import { 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 { PickerOption } from '../picker/types';
|
|
8
|
+
import type { CommonProps, CommonSlots, CommonSlotsProps, ComponentType } from '../share';
|
|
9
|
+
import { commonProps } from '../share';
|
|
10
|
+
|
|
11
|
+
/** 组件传参 - 私有 */
|
|
12
|
+
export function areaPropsGeneric<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
|
+
/** 重写 option 属性, 增加支持的类型 */
|
|
17
|
+
options: { type: [Object, Array] as PropType<any> },
|
|
18
|
+
/** VanArea 组件的属性 */
|
|
19
|
+
areaProps: { type: Object as PropType<Partial<ComponentProps<typeof VanArea>>> },
|
|
20
|
+
/** VanArea 组件的事件 - 兼容 vue2 版本 */
|
|
21
|
+
areaOn: { type: Object as PropType<Partial<ReturnType<typeof emits2obj<NonNullable<typeof VanArea.emits>>>>>, default: () => ({}) },
|
|
22
|
+
/** VanArea 组件的插槽 */
|
|
23
|
+
areaSlots: { type: Object as PropType<{
|
|
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
|
+
columnsTop?: ComponentType<CommonSlotsProps<any, any>>;
|
|
34
|
+
/** 自定义选项下方内容 */
|
|
35
|
+
columnsBottom?: ComponentType<CommonSlotsProps<any, any>>;
|
|
36
|
+
}> },
|
|
37
|
+
/** 是否展示右侧箭头并开启点击反馈 - Field 字段, 调整默认值 */
|
|
38
|
+
isLink: { type: Boolean, default: true },
|
|
39
|
+
/** 点击事件, 当传递了此事件时, 会忽略内部打开弹窗操作 */
|
|
40
|
+
onRowClick: { type: Function as PropType<(option: { open: () => void; close: () => void }, ev: MouseEvent) => void> },
|
|
41
|
+
/** 显示文本的分隔符 @default / */
|
|
42
|
+
separator: { type: String, default: '/' },
|
|
43
|
+
/** 是否显示全路径 */
|
|
44
|
+
showAllLevels: { type: Boolean, default: true },
|
|
45
|
+
/** 对值进行格式化 - 显示在页面上的值 */
|
|
46
|
+
format: { type: Function as PropType<(option: {
|
|
47
|
+
source: Record<'province_list' | 'city_list' | 'county_list', Record<string, any>>;
|
|
48
|
+
value: string | undefined;
|
|
49
|
+
showAllLevels: boolean;
|
|
50
|
+
separator: string;
|
|
51
|
+
}) => any> },
|
|
52
|
+
/** 值触发方式 @default confirm */
|
|
53
|
+
valueTrigger: { type: String as PropType<'change' | 'confirm' | 'cancel'>, default: 'confirm' },
|
|
54
|
+
/** 弹窗组件的属性 */
|
|
55
|
+
popupProps: { type: Object as PropType<Partial<ComponentExposed<typeof VanPopup>>> },
|
|
56
|
+
/** 弹窗组件的事件 - 兼容 vue2 版本 */
|
|
57
|
+
popupOn: { type: Object as PropType<Partial<ReturnType<typeof emits2obj<NonNullable<typeof VanPopup.emits>>>>>, default: () => ({}) },
|
|
58
|
+
} as const;
|
|
59
|
+
}
|
|
60
|
+
/** 组件传参 - 私有 */
|
|
61
|
+
export const areaPropsPrivate = areaPropsGeneric();
|
|
62
|
+
/** 组件传参 - 外部调用 */
|
|
63
|
+
export const areaProps = {
|
|
64
|
+
...VanField.props as unknown as {},
|
|
65
|
+
...areaPropsPrivate,
|
|
66
|
+
};
|
|
67
|
+
export type AreaProps<Query extends Record<string, any>, OptionQuery extends Record<string, any>> = ExtractPublicPropTypes<ReturnType<typeof areaPropsGeneric<Query, OptionQuery>>>;
|
|
68
|
+
|
|
69
|
+
/** 组件事件 - 私有 */
|
|
70
|
+
export function areaEmitsGeneric<T>() {
|
|
71
|
+
return {};
|
|
72
|
+
}
|
|
73
|
+
/** 组件事件 - 私有 */
|
|
74
|
+
export const areaEmitsPrivate = areaEmitsGeneric();
|
|
75
|
+
/** 组件事件 - 外部调用 */
|
|
76
|
+
export const areaEmits = {
|
|
77
|
+
...VanField.emits,
|
|
78
|
+
...areaEmitsPrivate,
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
export type AreaEmits<T> = ReturnType<typeof areaEmitsGeneric<T>>;
|
|
82
|
+
|
|
83
|
+
export interface AreaSlots extends CommonSlots<any> {
|
|
84
|
+
}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<VanField
|
|
3
|
+
v-if="!hide"
|
|
4
|
+
:name="field" :label="label"
|
|
5
|
+
:disabled="globalDisabled || disabled"
|
|
6
|
+
:readonly="true"
|
|
7
|
+
:placeholder="placeholder"
|
|
8
|
+
:model-value="lastCheckedValue" :is-link="isLink"
|
|
9
|
+
v-bind="$attrs"
|
|
10
|
+
@click="clickHandle"
|
|
11
|
+
>
|
|
12
|
+
<template #input>
|
|
13
|
+
<HInputSlot
|
|
14
|
+
:value="showText" :placeholder="placeholder"
|
|
15
|
+
:disabled="globalDisabled || disabled" :readonly="globalReadonly || readonly"
|
|
16
|
+
v-bind="$attrs"
|
|
17
|
+
/>
|
|
18
|
+
</template>
|
|
19
|
+
<template #extra>
|
|
20
|
+
<VanPopup v-model:show="popupInfo.visible" teleport="body" round position="bottom" v-bind="popupProps" v-on="popupOn" @close="popupInfo.close">
|
|
21
|
+
<VanCascader
|
|
22
|
+
:title="cascaderProps.title || label" :placeholder="cascaderProps.placeholder || placeholder"
|
|
23
|
+
:model-value="lastCheckedValue" :options="finalOption"
|
|
24
|
+
v-bind="cascaderProps" v-on="cascaderOn"
|
|
25
|
+
@change="change" @finish="finish" @close="popupInfo.close"
|
|
26
|
+
>
|
|
27
|
+
<template v-for="(item, slotName) of cascaderSlots" :key="slotName" #[hyphenate(slotName)]="row">
|
|
28
|
+
<component :is="getNode(item)" v-bind="slotProps" v-bind.prop="row" />
|
|
29
|
+
</template>
|
|
30
|
+
</VanCascader>
|
|
31
|
+
</VanPopup>
|
|
32
|
+
</template>
|
|
33
|
+
<template v-for="(item, slotName) of slots" :key="slotName" #[hyphenate(slotName)]="row">
|
|
34
|
+
<component :is="getNode(item)" v-bind="slotProps" v-bind.prop="row" />
|
|
35
|
+
</template>
|
|
36
|
+
</VanField>
|
|
37
|
+
</template>
|
|
38
|
+
|
|
39
|
+
<script lang="ts">
|
|
40
|
+
import { getNode, hyphenate, usePlain } from '@xiaohaih/json-form-core';
|
|
41
|
+
import type { CascaderOption } from 'vant';
|
|
42
|
+
import { Cascader as VanCascader, Field as VanField, Popup as VanPopup } from 'vant';
|
|
43
|
+
import type { SlotsType } from 'vue';
|
|
44
|
+
import { computed, defineComponent, ref, watch } from 'vue';
|
|
45
|
+
import { pick } from '../../src/utils';
|
|
46
|
+
import { HInputSlot } from '../input-slot/index';
|
|
47
|
+
import { useCommonSetup, useTempChecked } from '../use';
|
|
48
|
+
import { getChained } from '../utils';
|
|
49
|
+
import type { CascaderSlots } from './types';
|
|
50
|
+
import { cascaderEmitsPrivate as emits, cascaderPropsPrivate as props } from './types';
|
|
51
|
+
|
|
52
|
+
interface Datum {
|
|
53
|
+
/** 当前选中项 */
|
|
54
|
+
value: string | number;
|
|
55
|
+
/** 选中项的所有值 */
|
|
56
|
+
selectedOptions: CascaderOption[];
|
|
57
|
+
/** 选中项下标 */
|
|
58
|
+
tabIndex: number;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* @file 级联框
|
|
63
|
+
*/
|
|
64
|
+
export default defineComponent({
|
|
65
|
+
name: 'HCascader',
|
|
66
|
+
components: { VanCascader, VanField, VanPopup, HInputSlot },
|
|
67
|
+
inheritAttrs: false,
|
|
68
|
+
props,
|
|
69
|
+
emits,
|
|
70
|
+
slots: Object as SlotsType<CascaderSlots>,
|
|
71
|
+
setup(props, ctx) {
|
|
72
|
+
const plain = usePlain(props);
|
|
73
|
+
/** 选中值的最后一位 */
|
|
74
|
+
const lastCheckedValue = computed(() => {
|
|
75
|
+
const val = plain.checked.value;
|
|
76
|
+
return (Array.isArray(val) ? val[val.length - 1] : val) as string;
|
|
77
|
+
});
|
|
78
|
+
/** 展示的文字 */
|
|
79
|
+
const showText = computed(() => {
|
|
80
|
+
const val = lastCheckedValue.value;
|
|
81
|
+
const options = plain.finalOption.value;
|
|
82
|
+
if (!val || !options.length) return '';
|
|
83
|
+
const { labelKey, valueKey, children } = fieldInfo.value;
|
|
84
|
+
const result = getChained(options, { [valueKey]: val }, children);
|
|
85
|
+
if (!result.length) return '';
|
|
86
|
+
return props.showAllLevels ? result.map((v) => v[labelKey]).join('/') : result[result.length - 1]![labelKey];
|
|
87
|
+
});
|
|
88
|
+
const { slotProps } = useCommonSetup(props, ctx, plain);
|
|
89
|
+
/** 级联下拉框的字段信息 */
|
|
90
|
+
const fieldInfo = computed(() => {
|
|
91
|
+
const fieldNames = props.cascaderProps?.fieldNames || {};
|
|
92
|
+
return {
|
|
93
|
+
labelKey: fieldNames.text || 'text',
|
|
94
|
+
valueKey: fieldNames.value || 'value',
|
|
95
|
+
children: fieldNames.children || 'children',
|
|
96
|
+
};
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
/** 点击事件 */
|
|
100
|
+
function clickHandle(ev: MouseEvent) {
|
|
101
|
+
if (plain.globalDisabled.value || props.disabled || plain.globalReadonly.value || props.readonly) return;
|
|
102
|
+
props.onRowClick ? props.onRowClick(popupInfo.value, ev) : popupInfo.value.open();
|
|
103
|
+
}
|
|
104
|
+
/** 级联选择值更改事件 */
|
|
105
|
+
function change(option: Datum) {
|
|
106
|
+
props.checkStrictly && setValue(option);
|
|
107
|
+
}
|
|
108
|
+
/** 级联选择完成事件 */
|
|
109
|
+
function finish(option: Datum) {
|
|
110
|
+
props.checkStrictly || setValue(option);
|
|
111
|
+
}
|
|
112
|
+
/** 设置文本框显示的值 */
|
|
113
|
+
function setValue(option: Datum) {
|
|
114
|
+
const { valueKey } = fieldInfo.value;
|
|
115
|
+
props.emitPath ? plain.change(option.selectedOptions.map((v) => v[valueKey])) : plain.change(option.value);
|
|
116
|
+
}
|
|
117
|
+
/** 弹窗显示状态 */
|
|
118
|
+
const popupInfo = ref({
|
|
119
|
+
visible: false,
|
|
120
|
+
open() {
|
|
121
|
+
popupInfo.value.visible = true;
|
|
122
|
+
},
|
|
123
|
+
close() {
|
|
124
|
+
popupInfo.value.visible = false;
|
|
125
|
+
},
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
return {
|
|
129
|
+
hyphenate,
|
|
130
|
+
getNode,
|
|
131
|
+
...plain,
|
|
132
|
+
slotProps,
|
|
133
|
+
fieldInfo,
|
|
134
|
+
lastCheckedValue,
|
|
135
|
+
showText,
|
|
136
|
+
clickHandle,
|
|
137
|
+
change,
|
|
138
|
+
finish,
|
|
139
|
+
setValue,
|
|
140
|
+
popupInfo,
|
|
141
|
+
};
|
|
142
|
+
},
|
|
143
|
+
});
|
|
144
|
+
</script>
|
|
145
|
+
|
|
146
|
+
<style lang="scss" scoped></style>
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import type { emits2obj, PlainProps } from '@xiaohaih/json-form-core';
|
|
2
|
+
import { emits2props, plainProps } from '@xiaohaih/json-form-core';
|
|
3
|
+
import type { CascaderOption, Cascader as VanCascader, Popup as VanPopup } from 'vant';
|
|
4
|
+
import { Field as VanField } from 'vant';
|
|
5
|
+
import type { ExtractPublicPropTypes, PropType } from 'vue';
|
|
6
|
+
import { camelize } from 'vue';
|
|
7
|
+
import type { ComponentEmit, ComponentExposed, ComponentProps } from 'vue-component-type-helpers';
|
|
8
|
+
import type { CommonProps, CommonSlots, CommonSlotsProps, ComponentType } from '../share';
|
|
9
|
+
import { commonProps } from '../share';
|
|
10
|
+
|
|
11
|
+
/** 组件传参 - 私有 */
|
|
12
|
+
export function cascaderPropsGeneric<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
|
+
/** 输入框左侧文本 */
|
|
17
|
+
label: { type: String },
|
|
18
|
+
/** 输入框的提示文字 */
|
|
19
|
+
placeholder: { type: String },
|
|
20
|
+
/** 是否展示右侧箭头并开启点击反馈 */
|
|
21
|
+
isLink: { type: Boolean, default: true },
|
|
22
|
+
/** 是否严格的遵守父子节点不互相关联(可选任意级) */
|
|
23
|
+
checkStrictly: { type: Boolean, default: undefined },
|
|
24
|
+
/** 是否显示全路径 */
|
|
25
|
+
showAllLevels: { type: Boolean, default: undefined },
|
|
26
|
+
/** 节点关联的情况下, 是否返回所有路径(即返回数组) */
|
|
27
|
+
emitPath: { type: Boolean, default: undefined },
|
|
28
|
+
/** 点击事件, 当传递了此事件时, 会忽略内部打开弹窗操作 */
|
|
29
|
+
onRowClick: { type: Function as PropType<(option: { open: () => void; close: () => void }, ev: MouseEvent) => void> },
|
|
30
|
+
/** VanCascader 组件的属性 */
|
|
31
|
+
cascaderProps: { type: Object as PropType<Partial<ComponentProps<typeof VanCascader>>>, default: () => ({}) },
|
|
32
|
+
/** VanCascader 组件的事件 - 兼容 vue2 版本 */
|
|
33
|
+
cascaderOn: { type: Object as PropType<Partial<ReturnType<typeof emits2obj<NonNullable<typeof VanCascader.emits>>>>>, default: () => ({}) },
|
|
34
|
+
/** VanCascader 组件的插槽 */
|
|
35
|
+
cascaderSlots: { type: Object as PropType<{
|
|
36
|
+
/** 自定义顶部标题 */
|
|
37
|
+
title?: ComponentType<CommonSlotsProps<any, any>>;
|
|
38
|
+
/** 自定义选项文字 */
|
|
39
|
+
option?: ComponentType<{ option: CascaderOption; selected: boolean } & CommonSlotsProps<any, any>>;
|
|
40
|
+
/** 自定义选项上方的内容 */
|
|
41
|
+
optionsTop?: ComponentType<{ tabIndex: number } & CommonSlotsProps<any, any>>;
|
|
42
|
+
/** 自定义选项下方的内容 */
|
|
43
|
+
optionsBottom?: ComponentType<{ tabIndex: number } & CommonSlotsProps<any, any>>;
|
|
44
|
+
}> },
|
|
45
|
+
/** 弹窗组件的属性 */
|
|
46
|
+
popupProps: { type: Object as PropType<Partial<ComponentExposed<typeof VanPopup>>> },
|
|
47
|
+
/** 弹窗组件的事件 - 兼容 vue2 版本 */
|
|
48
|
+
popupOn: { type: Object as PropType<Partial<ReturnType<typeof emits2obj<NonNullable<typeof VanPopup.emits>>>>>, default: () => ({}) },
|
|
49
|
+
} as const;
|
|
50
|
+
}
|
|
51
|
+
/** 组件传参 - 私有 */
|
|
52
|
+
export const cascaderPropsPrivate = cascaderPropsGeneric();
|
|
53
|
+
/** 组件传参 - 外部调用 */
|
|
54
|
+
export const cascaderProps = {
|
|
55
|
+
...VanField.props as unknown as {},
|
|
56
|
+
...cascaderPropsPrivate,
|
|
57
|
+
};
|
|
58
|
+
export type CascaderProps<Query extends Record<string, any>, OptionQuery extends Record<string, any>> = ExtractPublicPropTypes<ReturnType<typeof cascaderPropsGeneric<Query, OptionQuery>>>;
|
|
59
|
+
|
|
60
|
+
/** 组件事件 - 私有 */
|
|
61
|
+
export function cascaderEmitsGeneric<T>() {
|
|
62
|
+
return {};
|
|
63
|
+
}
|
|
64
|
+
/** 组件事件 - 私有 */
|
|
65
|
+
export const cascaderEmitsPrivate = cascaderEmitsGeneric();
|
|
66
|
+
/** 组件事件 - 外部调用 */
|
|
67
|
+
export const cascaderEmits = {
|
|
68
|
+
...VanField.emits,
|
|
69
|
+
...cascaderEmitsPrivate,
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
export type CascaderEmits<T> = ReturnType<typeof cascaderEmitsGeneric<T>>;
|
|
73
|
+
|
|
74
|
+
export interface CascaderSlots extends CommonSlots<any> {
|
|
75
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<VanField
|
|
3
|
+
v-if="!hide"
|
|
4
|
+
:name="field" :label="label"
|
|
5
|
+
:disabled="globalDisabled || disabled"
|
|
6
|
+
:readonly="globalReadonly || readonly"
|
|
7
|
+
v-bind="$attrs"
|
|
8
|
+
>
|
|
9
|
+
<template #input>
|
|
10
|
+
<VanCheckbox
|
|
11
|
+
:name="field" :model-value="checked"
|
|
12
|
+
:disabled="globalDisabled || disabled || globalReadonly || readonly"
|
|
13
|
+
v-bind="checkboxProps" v-on="checkboxOn"
|
|
14
|
+
@update:model-value="change"
|
|
15
|
+
>
|
|
16
|
+
<template v-for="(item, slotName) of checkboxSlots" :key="slotName" #[hyphenate(slotName)]="row">
|
|
17
|
+
<component :is="getNode(item)" v-bind="slotProps" v-bind.prop="row" />
|
|
18
|
+
</template>
|
|
19
|
+
</VanCheckbox>
|
|
20
|
+
</template>
|
|
21
|
+
</VanField>
|
|
22
|
+
</template>
|
|
23
|
+
|
|
24
|
+
<script lang="ts">
|
|
25
|
+
import { getNode, hyphenate, usePlain } from '@xiaohaih/json-form-core';
|
|
26
|
+
import { Checkbox as VanCheckbox, Field as VanField } from 'vant';
|
|
27
|
+
import type { SlotsType } from 'vue';
|
|
28
|
+
import { computed, defineComponent } from 'vue';
|
|
29
|
+
import { pick } from '../../src/utils';
|
|
30
|
+
import { useCommonSetup, useTempChecked } from '../use';
|
|
31
|
+
import type { CheckboxSlots } from './types';
|
|
32
|
+
import { checkboxEmitsPrivate as emits, checkboxPropsPrivate as props } from './types';
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* @file 多选框
|
|
36
|
+
*/
|
|
37
|
+
export default defineComponent({
|
|
38
|
+
name: 'HCheckbox',
|
|
39
|
+
components: { VanCheckbox, VanField },
|
|
40
|
+
inheritAttrs: false,
|
|
41
|
+
props,
|
|
42
|
+
emits,
|
|
43
|
+
slots: Object as SlotsType<CheckboxSlots>,
|
|
44
|
+
setup(props, ctx) {
|
|
45
|
+
const plain = usePlain(props);
|
|
46
|
+
const { slotProps } = useCommonSetup(props, ctx, plain);
|
|
47
|
+
|
|
48
|
+
return {
|
|
49
|
+
hyphenate,
|
|
50
|
+
getNode,
|
|
51
|
+
...plain,
|
|
52
|
+
slotProps,
|
|
53
|
+
};
|
|
54
|
+
},
|
|
55
|
+
});
|
|
56
|
+
</script>
|
|
57
|
+
|
|
58
|
+
<style lang="scss" scoped>
|
|
59
|
+
</style>
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import type { emits2obj, PlainProps } from '@xiaohaih/json-form-core';
|
|
2
|
+
import { emits2props, plainProps } from '@xiaohaih/json-form-core';
|
|
3
|
+
import { Checkbox as VanCheckbox, Field as VanField } from 'vant';
|
|
4
|
+
import type { ExtractPublicPropTypes, PropType } from 'vue';
|
|
5
|
+
import { camelize } 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 checkboxPropsGeneric<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
|
+
/** 输入框左侧文本 */
|
|
16
|
+
label: { type: String },
|
|
17
|
+
/** VanCheckbox 组件的属性 */
|
|
18
|
+
checkboxProps: { type: Object as PropType<Partial<ComponentProps<typeof VanCheckbox>>> },
|
|
19
|
+
/** VanCheckbox 组件的事件 - 兼容 vue2 版本 */
|
|
20
|
+
checkboxOn: { type: Object as PropType<Partial<ReturnType<typeof emits2obj<NonNullable<typeof VanCheckbox.emits>>>>>, default: () => ({}) },
|
|
21
|
+
/** VanCheckbox 组件的插槽 */
|
|
22
|
+
checkboxSlots: { type: Object as PropType<{
|
|
23
|
+
/** 自定义文本 */
|
|
24
|
+
default?: ComponentType<{ checked: boolean; disabled: boolean } & CommonSlotsProps<any, any>>;
|
|
25
|
+
/** 自定义图标 */
|
|
26
|
+
icon?: ComponentType<{ checked: boolean; disabled: boolean } & CommonSlotsProps<any, any>>;
|
|
27
|
+
}> },
|
|
28
|
+
} as const;
|
|
29
|
+
}
|
|
30
|
+
/** 组件传参 - 私有 */
|
|
31
|
+
export const checkboxPropsPrivate = checkboxPropsGeneric();
|
|
32
|
+
/** 组件传参 - 外部调用 */
|
|
33
|
+
export const checkboxProps = {
|
|
34
|
+
...VanField.props as unknown as {},
|
|
35
|
+
...checkboxPropsPrivate,
|
|
36
|
+
};
|
|
37
|
+
export type CheckboxProps<Query extends Record<string, any>, OptionQuery extends Record<string, any>> = ExtractPublicPropTypes<ReturnType<typeof checkboxPropsGeneric<Query, OptionQuery>>>;
|
|
38
|
+
|
|
39
|
+
/** 组件事件 - 私有 */
|
|
40
|
+
export function checkboxEmitsGeneric<T>() {
|
|
41
|
+
return {};
|
|
42
|
+
}
|
|
43
|
+
/** 组件事件 - 私有 */
|
|
44
|
+
export const checkboxEmitsPrivate = checkboxEmitsGeneric();
|
|
45
|
+
/** 组件事件 - 外部调用 */
|
|
46
|
+
export const checkboxEmits = {
|
|
47
|
+
...VanField.emits,
|
|
48
|
+
...checkboxEmitsPrivate,
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
export type CheckboxEmits<T> = ReturnType<typeof checkboxEmitsGeneric<T>>;
|
|
52
|
+
|
|
53
|
+
export interface CheckboxSlots extends CommonSlots<any> {
|
|
54
|
+
}
|