Commit 1d45617e4a311e339eb008a629cd342cd673ecf1

Authored by vben
1 parent 3f78b5aa

refactor(form): enhanced form customization and dynamic capabilities

CHANGELOG.zh_CN.md
... ... @@ -4,6 +4,7 @@
4 4  
5 5 - 重构 hook,引入 `@vueuse`,删除其中已有的`hook`,优化现有的 hook
6 6 - `useEvent` 更名->`useEventListener`
  7 +- 表单`ComponentType`删除 `SelectOptGroup`,`SelectOption`,`Transfer`,`Radio`,四个类型。修改`RadioButtonGroup`组件
7 8  
8 9 ### ✨ Features
9 10  
... ... @@ -12,10 +13,15 @@
12 13 - 新增菜单及顶栏颜色选择配色
13 14 - 增加示例结果页
14 15  
  16 +### ⚡ Wip
  17 +
  18 +- 上传组件(未完成,测试中...)
  19 +
15 20 ### ⚡ Performance Improvements
16 21  
17 22 - 优化 settingDrawer 代码
18 23 - 优化多标签页切换速度
  24 +- 增加表单自定义及动态能力
19 25  
20 26 ### 🐛 Bug Fixes
21 27  
... ... @@ -23,6 +29,7 @@
23 29 - 修复登录过期后重新登录未跳转原来页面的
24 30 - 修复 window 系统动态引入错误
25 31 - 修复页面类型错误
  32 +- 修复表单 switch 和 checkBox 单独使用报错
26 33  
27 34 ## 2.0.0-rc.9 (2020-11-9)
28 35  
... ...
src/components/Form/src/BasicForm.vue
... ... @@ -5,6 +5,7 @@
5 5 <template v-for="schema in getSchema" :key="schema.field">
6 6 <FormItem
7 7 :tableAction="tableAction"
  8 + :formActionType="formActionType"
8 9 :schema="schema"
9 10 :formProps="getProps"
10 11 :allDefaultValues="defaultValueRef"
... ... @@ -164,7 +165,7 @@
164 165 propsRef.value = mergeProps;
165 166 }
166 167  
167   - const methods: Partial<FormActionType> = {
  168 + const formActionType: Partial<FormActionType> = {
168 169 getFieldsValue,
169 170 setFieldsValue,
170 171 resetFields,
... ... @@ -179,7 +180,7 @@
179 180  
180 181 onMounted(() => {
181 182 initDefault();
182   - emit('register', methods);
  183 + emit('register', formActionType);
183 184 });
184 185  
185 186 return {
... ... @@ -191,7 +192,8 @@
191 192 getProps,
192 193 formElRef,
193 194 getSchema,
194   - ...methods,
  195 + formActionType,
  196 + ...formActionType,
195 197 };
196 198 },
197 199 });
... ...
src/components/Form/src/FormItem.tsx
1 1 import type { PropType } from 'vue';
2   -import type { FormProps } from './types/form';
  2 +import type { FormActionType, FormProps } from './types/form';
3 3 import type { FormSchema } from './types/form';
4 4 import type { ValidationRule } from 'ant-design-vue/lib/form/Form';
5 5 import type { TableActionType } from '/@/components/Table';
... ... @@ -41,6 +41,9 @@ export default defineComponent({
41 41 tableAction: {
42 42 type: Object as PropType<TableActionType>,
43 43 },
  44 + formActionType: {
  45 + type: Object as PropType<FormActionType>,
  46 + },
44 47 },
45 48 setup(props, { slots }) {
46 49 const itemLabelWidthRef = useItemLabelWidth(toRef(props, 'schema'), toRef(props, 'formProps'));
... ... @@ -61,12 +64,12 @@ export default defineComponent({
61 64 });
62 65  
63 66 const getComponentsPropsRef = computed(() => {
64   - const { schema, tableAction, formModel } = props;
  67 + const { schema, tableAction, formModel, formActionType } = props;
65 68 const { componentProps = {} } = schema;
66 69 if (!isFunction(componentProps)) {
67 70 return componentProps;
68 71 }
69   - return componentProps({ schema, tableAction, formModel }) || {};
  72 + return componentProps({ schema, tableAction, formModel, formActionType }) || {};
70 73 });
71 74  
72 75 const getDisableRef = computed(() => {
... ... @@ -179,17 +182,27 @@ export default defineComponent({
179 182 }
180 183  
181 184 function renderComponent() {
182   - const { renderComponentContent, component, field, changeEvent = 'change' } = props.schema;
  185 + const {
  186 + renderComponentContent,
  187 + component,
  188 + field,
  189 + changeEvent = 'change',
  190 + valueField,
  191 + } = props.schema;
183 192  
184   - const isCheck = component && ['Switch'].includes(component);
  193 + const isCheck = component && ['Switch', 'Checkbox'].includes(component);
185 194  
186 195 const eventKey = `on${upperFirst(changeEvent)}`;
  196 +
187 197 const on = {
188 198 [eventKey]: (e: any) => {
189 199 if (propsData[eventKey]) {
190 200 propsData[eventKey](e);
191 201 }
192   - (props.formModel as any)[field] = e && e.target ? e.target.value : e;
  202 +
  203 + const target = e ? e.target : null;
  204 + const value = target ? (isCheck ? target.checked : target.value) : e;
  205 + (props.formModel as any)[field] = value;
193 206 },
194 207 };
195 208 const Comp = componentMap.get(component);
... ... @@ -215,17 +228,20 @@ export default defineComponent({
215 228 propsData.codeField = field;
216 229 propsData.formValues = unref(getValuesRef);
217 230 const bindValue = {
218   - [isCheck ? 'checked' : 'value']: handleValue(component, field),
  231 + [valueField || (isCheck ? 'checked' : 'value')]: handleValue(component, field),
219 232 };
220 233 if (!renderComponentContent) {
221 234 return <Comp {...propsData} {...on} {...bindValue} />;
222 235 }
  236 + const compSlot = isFunction(renderComponentContent)
  237 + ? { ...renderComponentContent(unref(getValuesRef)) }
  238 + : {
  239 + default: () => renderComponentContent,
  240 + };
223 241  
224 242 return (
225 243 <Comp {...propsData} {...on} {...bindValue}>
226   - {{
227   - ...renderComponentContent(unref(getValuesRef)),
228   - }}
  244 + {compSlot}
229 245 </Comp>
230 246 );
231 247 }
... ... @@ -249,7 +265,7 @@ export default defineComponent({
249 265 const { colon } = props.formProps;
250 266 const getContent = () => {
251 267 return slot
252   - ? getSlot(slots, slot)
  268 + ? getSlot(slots, slot, unref(getValuesRef))
253 269 : render
254 270 ? render(unref(getValuesRef))
255 271 : renderComponent();
... ... @@ -276,7 +292,7 @@ export default defineComponent({
276 292 const { isIfShow, isShow } = getShow();
277 293 const getContent = () => {
278 294 return colSlot
279   - ? getSlot(slots, colSlot)
  295 + ? getSlot(slots, colSlot, unref(getValuesRef))
280 296 : renderColContent
281 297 ? renderColContent(unref(getValuesRef))
282 298 : renderItem();
... ...
src/components/Form/src/componentMap.ts
... ... @@ -14,8 +14,8 @@ import {
14 14 Switch,
15 15 TimePicker,
16 16 TreeSelect,
17   - Transfer,
18 17 } from 'ant-design-vue';
  18 +import RadioButtonGroup from './components/RadioButtonGroup.vue';
19 19  
20 20 import { ComponentType } from './types/index';
21 21  
... ... @@ -30,13 +30,13 @@ componentMap.set(&#39;InputNumber&#39;, InputNumber);
30 30 componentMap.set('AutoComplete', AutoComplete);
31 31  
32 32 componentMap.set('Select', Select);
33   -componentMap.set('SelectOptGroup', Select.OptGroup);
34   -componentMap.set('SelectOption', Select.Option);
  33 +// componentMap.set('SelectOptGroup', Select.OptGroup);
  34 +// componentMap.set('SelectOption', Select.Option);
35 35 componentMap.set('TreeSelect', TreeSelect);
36   -componentMap.set('Transfer', Transfer);
37   -componentMap.set('Radio', Radio);
  36 +// componentMap.set('Transfer', Transfer);
  37 +// componentMap.set('Radio', Radio);
38 38 componentMap.set('Switch', Switch);
39   -componentMap.set('RadioButton', Radio.Button);
  39 +componentMap.set('RadioButtonGroup', RadioButtonGroup);
40 40 componentMap.set('RadioGroup', Radio.Group);
41 41 componentMap.set('Checkbox', Checkbox);
42 42 componentMap.set('CheckboxGroup', Checkbox.Group);
... ...
src/components/Form/src/components/RadioButtonGroup.vue 0 → 100644
  1 +<template>
  2 + <RadioGroup v-bind="$attrs" v-model:value="valueRef" button-style="solid">
  3 + <template v-for="item in getOptions" :key="`${item.value}`">
  4 + <RadioButton :value="item.value"> {{ item.label }} </RadioButton>
  5 + </template>
  6 + </RadioGroup>
  7 +</template>
  8 +<script lang="ts">
  9 + import { defineComponent, ref, PropType, watch, unref, computed } from 'vue';
  10 + import { Radio } from 'ant-design-vue';
  11 + import {} from 'ant-design-vue/es/radio/Group';
  12 + import { isString } from '/@/utils/is';
  13 +
  14 + type OptionsItem = { label: string; value: string; disabled?: boolean };
  15 + type RadioItem = string | OptionsItem;
  16 + export default defineComponent({
  17 + name: 'RadioButtonGroup',
  18 + components: {
  19 + RadioGroup: Radio.Group,
  20 + RadioButton: Radio.Button,
  21 + },
  22 + props: {
  23 + value: {
  24 + type: String as PropType<string>,
  25 + },
  26 + options: {
  27 + type: Array as PropType<RadioItem[]>,
  28 + default: () => [],
  29 + },
  30 + },
  31 + setup(props, { emit }) {
  32 + const valueRef = ref('');
  33 +
  34 + watch(
  35 + () => props.value,
  36 + (v = '') => {
  37 + valueRef.value = v;
  38 + },
  39 + { immediate: true }
  40 + );
  41 +
  42 + watch(
  43 + () => unref(valueRef),
  44 + () => {
  45 + emit('change', valueRef.value);
  46 + },
  47 + { immediate: true }
  48 + );
  49 +
  50 + const getOptions = computed((): OptionsItem[] => {
  51 + const { options } = props;
  52 + if (!options || options.length === 0) return [];
  53 + const isStringArr = options.some((item) => isString(item));
  54 + if (!isStringArr) return options as OptionsItem[];
  55 + return options.map((item) => ({ label: item, value: item })) as OptionsItem[];
  56 + });
  57 +
  58 + return { valueRef, getOptions };
  59 + },
  60 + });
  61 +</script>
... ...
src/components/Form/src/types/form.ts
... ... @@ -7,6 +7,10 @@ import { TableActionType } from &#39;../../../Table/src/types/table&#39;;
7 7  
8 8 export type FieldMapToTime = [string, [string, string], string?][];
9 9  
  10 +export type Rule = RuleObject & {
  11 + trigger?: 'blur' | 'change' | ['change', 'blur'];
  12 +};
  13 +
10 14 export interface RenderCallbackParams {
11 15 schema: FormSchema;
12 16 values: any;
... ... @@ -98,7 +102,10 @@ export interface FormProps {
98 102 export interface FormSchema {
99 103 // 字段名
100 104 field: string;
  105 + // 内部值更改触发的事件名,默认 change
101 106 changeEvent?: string;
  107 + // v-model绑定的变量名 默认 value
  108 + valueField?: string;
102 109 // 标签名
103 110 label: string;
104 111 // 文本右侧帮助文本
... ... @@ -113,13 +120,18 @@ export interface FormSchema {
113 120 component: ComponentType;
114 121 // 组件参数
115 122 componentProps?:
116   - | ((opt: { schema: FormSchema; tableAction: TableActionType; formModel: any }) => any)
  123 + | ((opt: {
  124 + schema: FormSchema;
  125 + tableAction: TableActionType;
  126 + formActionType: FormActionType;
  127 + formModel: any;
  128 + }) => any)
117 129 | object;
118 130 // 必填
119 131 required?: boolean;
120 132  
121 133 // 校验规则
122   - rules?: RuleObject[];
  134 + rules?: Rule[];
123 135 // 校验信息是否加入label
124 136 rulesMessageJoinLabel?: boolean;
125 137  
... ... @@ -146,7 +158,11 @@ export interface FormSchema {
146 158 // 渲染 col内容,需要外层包裹 form-item
147 159 renderColContent?: (renderCallbackParams: RenderCallbackParams) => VNode | VNode[] | string;
148 160  
149   - renderComponentContent?: (renderCallbackParams: RenderCallbackParams) => any;
  161 + renderComponentContent?:
  162 + | ((renderCallbackParams: RenderCallbackParams) => any)
  163 + | VNode
  164 + | VNode[]
  165 + | string;
150 166  
151 167 // 自定义slot, 在 from-item内
152 168 slot?: string;
... ... @@ -156,7 +172,7 @@ export interface FormSchema {
156 172  
157 173 dynamicDisabled?: boolean | ((renderCallbackParams: RenderCallbackParams) => boolean);
158 174  
159   - dynamicRules?: (renderCallbackParams: RenderCallbackParams) => RuleObject[];
  175 + dynamicRules?: (renderCallbackParams: RenderCallbackParams) => Rule[];
160 176 }
161 177 export interface HelpComponentProps {
162 178 maxWidth: string;
... ...
src/components/Form/src/types/index.ts
... ... @@ -93,8 +93,8 @@ export type ComponentType =
93 93 | 'SelectOption'
94 94 | 'TreeSelect'
95 95 | 'Transfer'
96   - | 'Radio'
97   - | 'RadioButton'
  96 + // | 'Radio'
  97 + | 'RadioButtonGroup'
98 98 | 'RadioGroup'
99 99 | 'Checkbox'
100 100 | 'CheckboxGroup'
... ...
src/components/Table/src/types/table.ts
... ... @@ -87,7 +87,7 @@ export interface GetColumnsParams {
87 87 export type SizeType = 'default' | 'middle' | 'small' | 'large';
88 88  
89 89 export interface TableActionType {
90   - reload: (opt?: FetchParams) => Promise<void>;
  90 + // reload: (opt?: FetchParams) => Promise<void>;
91 91 getSelectRows: () => any[];
92 92 clearSelectedRowKeys: () => void;
93 93 getSelectRowKeys: () => string[];
... ...
src/router/menus/modules/demo/comp.ts
... ... @@ -38,10 +38,10 @@ const menu: MenuModule = {
38 38 path: 'strength-meter',
39 39 name: '密码强度组件',
40 40 },
41   - {
42   - path: 'upload',
43   - name: '上传组件',
44   - },
  41 + // {
  42 + // path: 'upload',
  43 + // name: '上传组件',
  44 + // },
45 45 {
46 46 path: 'scroll',
47 47 name: '滚动组件',
... ...
src/router/menus/modules/demo/form.ts
... ... @@ -4,10 +4,18 @@ const menu: MenuModule = {
4 4 menu: {
5 5 path: '/form',
6 6 name: 'Form',
  7 + tag: {
  8 + type: 'warn',
  9 + dot: true,
  10 + },
7 11 children: [
8 12 {
9 13 path: 'basic',
10 14 name: '基础表单',
  15 + tag: {
  16 + type: 'warn',
  17 + content: 'updated',
  18 + },
11 19 },
12 20 {
13 21 path: 'useForm',
... ... @@ -24,14 +32,26 @@ const menu: MenuModule = {
24 32 {
25 33 path: 'ruleForm',
26 34 name: '表单校验',
  35 + tag: {
  36 + type: 'warn',
  37 + content: 'updated',
  38 + },
27 39 },
28 40 {
29 41 path: 'dynamicForm',
30 42 name: '动态表单',
  43 + tag: {
  44 + type: 'warn',
  45 + content: 'updated',
  46 + },
31 47 },
32 48 {
33 49 path: 'customerForm',
34 50 name: '自定义组件',
  51 + tag: {
  52 + type: 'warn',
  53 + content: 'updated',
  54 + },
35 55 },
36 56 ],
37 57 },
... ...
src/views/demo/form/CustomerForm.vue
1 1 <template>
2 2 <div class="m-4">
3 3 <CollapseContainer title="自定义表单">
4   - <BasicForm @register="register" @submit="handleSubmit" />
  4 + <BasicForm @register="register" @submit="handleSubmit">
  5 + <template #f3="{ model, field }">
  6 + <a-input v-model:value="model[field]" placeholder="自定义slot" />
  7 + </template>
  8 + </BasicForm>
5 9 </CollapseContainer>
6 10 </div>
7 11 </template>
... ... @@ -15,7 +19,7 @@
15 19 {
16 20 field: 'field1',
17 21 component: 'Input',
18   - label: '字段1',
  22 + label: 'render方式',
19 23 colProps: {
20 24 span: 8,
21 25 },
... ... @@ -33,7 +37,7 @@
33 37 {
34 38 field: 'field2',
35 39 component: 'Input',
36   - label: '字段2',
  40 + label: 'render组件slot',
37 41 colProps: {
38 42 span: 8,
39 43 },
... ... @@ -44,6 +48,16 @@
44 48 };
45 49 },
46 50 },
  51 + {
  52 + field: 'field3',
  53 + component: 'Input',
  54 + label: '自定义Slot',
  55 + slot: 'f3',
  56 + colProps: {
  57 + span: 8,
  58 + },
  59 + rules: [{ required: true }],
  60 + },
47 61 ];
48 62 export default defineComponent({
49 63 components: { BasicForm, CollapseContainer },
... ...
src/views/demo/form/DynamicForm.vue
... ... @@ -9,6 +9,10 @@
9 9 <CollapseContainer title="动态表单示例,动态根据表单内其他值改变">
10 10 <BasicForm @register="register" />
11 11 </CollapseContainer>
  12 +
  13 + <CollapseContainer class="mt-5" title="componentProps动态改变">
  14 + <BasicForm @register="register1" />
  15 + </CollapseContainer>
12 16 </div>
13 17 </template>
14 18 <script lang="ts">
... ... @@ -120,6 +124,58 @@
120 124 },
121 125 ];
122 126  
  127 + const schemas1: FormSchema[] = [
  128 + {
  129 + field: 'f1',
  130 + component: 'Input',
  131 + label: 'F1',
  132 + colProps: {
  133 + span: 12,
  134 + },
  135 + labelWidth: 200,
  136 + componentProps: ({ formModel }) => {
  137 + return {
  138 + placeholder: '同步f2的值为f1',
  139 + onChange: (e: ChangeEvent) => {
  140 + formModel.f2 = e.target.value;
  141 + },
  142 + };
  143 + },
  144 + },
  145 + {
  146 + field: 'f2',
  147 + component: 'Input',
  148 + label: 'F2',
  149 + colProps: {
  150 + span: 12,
  151 + },
  152 + labelWidth: 200,
  153 + componentProps: { disabled: true },
  154 + },
  155 + {
  156 + field: 'f3',
  157 + component: 'Input',
  158 + label: 'F3',
  159 + colProps: {
  160 + span: 12,
  161 + },
  162 + labelWidth: 200,
  163 + // @ts-ignore
  164 + componentProps: ({ formActionType, tableAction }) => {
  165 + return {
  166 + placeholder: '值改变时执行查询,查看控制台',
  167 + onChange: async () => {
  168 + const { validate } = formActionType;
  169 + // tableAction只适用于在表格内开启表单的例子
  170 + // const { reload } = tableAction;
  171 + const res = await validate();
  172 + console.log(res);
  173 + },
  174 + };
  175 + },
  176 + },
  177 + ];
  178 +
123 179 export default defineComponent({
124 180 components: { BasicForm, CollapseContainer },
125 181 setup() {
... ... @@ -133,6 +189,13 @@
133 189 span: 24,
134 190 },
135 191 });
  192 + const [register1] = useForm({
  193 + labelWidth: 120,
  194 + schemas: schemas1,
  195 + actionColOptions: {
  196 + span: 24,
  197 + },
  198 + });
136 199 function changeLabel3() {
137 200 updateSchema({
138 201 field: 'field3',
... ... @@ -170,6 +233,7 @@
170 233 }
171 234 return {
172 235 register,
  236 + register1,
173 237 schemas,
174 238 setProps,
175 239 changeLabel3,
... ...
src/views/demo/form/RuleForm.vue
... ... @@ -65,7 +65,33 @@
65 65 },
66 66 ],
67 67 },
68   - rules: [{ required: true, message: '请输入aa' }],
  68 + rules: [
  69 + {
  70 + required: true,
  71 + message: '请输入aa',
  72 + },
  73 + ],
  74 + },
  75 + {
  76 + field: 'field44',
  77 + component: 'Input',
  78 + label: '自定义校验',
  79 + colProps: {
  80 + span: 8,
  81 + },
  82 + rules: [
  83 + {
  84 + required: true,
  85 + // @ts-ignore
  86 + validator: async (rule, value) => {
  87 + if (value === '1') {
  88 + return Promise.reject('值不能为1');
  89 + }
  90 + return Promise.resolve();
  91 + },
  92 + trigger: 'blur',
  93 + },
  94 + ],
69 95 },
70 96 {
71 97 field: 'field5',
... ...
src/views/demo/form/index.vue
... ... @@ -11,10 +11,11 @@
11 11 </div>
12 12 </template>
13 13 <script lang="ts">
14   - import { defineComponent } from 'vue';
  14 + import { defineComponent, ref } from 'vue';
15 15 import { BasicForm, FormSchema } from '/@/components/Form/index';
16 16 import { CollapseContainer } from '/@/components/Container/index';
17 17 import { useMessage } from '/@/hooks/web/useMessage';
  18 +
18 19 const schemas: FormSchema[] = [
19 20 {
20 21 field: 'field1',
... ... @@ -23,8 +24,11 @@
23 24 colProps: {
24 25 span: 8,
25 26 },
26   - defaultValue: '111',
27   - componentProps: () => {
  27 + // componentProps:{},
  28 + // can func
  29 + componentProps: ({ schema, formModel }) => {
  30 + console.log('form:', schema);
  31 + console.log('formModel:', formModel);
28 32 return {
29 33 placeholder: '自定义placeholder',
30 34 onChange: (e: any) => {
... ... @@ -32,14 +36,26 @@
32 36 },
33 37 };
34 38 },
  39 + renderComponentContent: () => {
  40 + return {
  41 + prefix: () => 'pSlot',
  42 + suffix: () => 'sSlot',
  43 + };
  44 + },
35 45 },
36 46 {
37 47 field: 'field2',
38 48 component: 'Input',
39 49 label: '字段2',
  50 + defaultValue: '111',
40 51 colProps: {
41 52 span: 8,
42 53 },
  54 + componentProps: {
  55 + onChange: (e: any) => {
  56 + console.log(e);
  57 + },
  58 + },
43 59 },
44 60 {
45 61 field: 'field3',
... ... @@ -111,17 +127,100 @@
111 127 ],
112 128 },
113 129 },
  130 + {
  131 + field: 'field8',
  132 + component: 'Checkbox',
  133 + label: '字段8',
  134 + colProps: {
  135 + span: 8,
  136 + },
  137 + renderComponentContent: 'Check',
  138 + },
  139 + {
  140 + field: 'field9',
  141 + component: 'Switch',
  142 + label: '字段9',
  143 + colProps: {
  144 + span: 8,
  145 + },
  146 + },
  147 + {
  148 + field: 'field10',
  149 + component: 'RadioButtonGroup',
  150 + label: '字段10',
  151 + colProps: {
  152 + span: 8,
  153 + },
  154 + componentProps: {
  155 + options: [
  156 + {
  157 + label: '选项1',
  158 + value: '1',
  159 + },
  160 + {
  161 + label: '选项2',
  162 + value: '2',
  163 + },
  164 + ],
  165 + },
  166 + },
  167 + {
  168 + field: 'field11',
  169 + component: 'Cascader',
  170 + label: '字段11',
  171 + colProps: {
  172 + span: 8,
  173 + },
  174 + componentProps: {
  175 + options: [
  176 + {
  177 + value: 'zhejiang',
  178 + label: 'Zhejiang',
  179 + children: [
  180 + {
  181 + value: 'hangzhou',
  182 + label: 'Hangzhou',
  183 + children: [
  184 + {
  185 + value: 'xihu',
  186 + label: 'West Lake',
  187 + },
  188 + ],
  189 + },
  190 + ],
  191 + },
  192 + {
  193 + value: 'jiangsu',
  194 + label: 'Jiangsu',
  195 + children: [
  196 + {
  197 + value: 'nanjing',
  198 + label: 'Nanjing',
  199 + children: [
  200 + {
  201 + value: 'zhonghuamen',
  202 + label: 'Zhong Hua Men',
  203 + },
  204 + ],
  205 + },
  206 + ],
  207 + },
  208 + ],
  209 + },
  210 + },
114 211 ];
115 212  
116 213 export default defineComponent({
117 214 components: { BasicForm, CollapseContainer },
118 215 setup() {
  216 + const check = ref(null);
119 217 const { createMessage } = useMessage();
120 218 return {
121 219 schemas,
122 220 handleSubmit: (values: any) => {
123 221 createMessage.success('click search,values:' + JSON.stringify(values));
124 222 },
  223 + check,
125 224 };
126 225 },
127 226 });
... ...