From 97fe8e2058147a331442340b209eee596f6033db Mon Sep 17 00:00:00 2001 From: Jobin <425605679@qq.com> Date: Mon, 1 Nov 2021 07:59:15 +0800 Subject: [PATCH] feat(ApiCascader): add asynchronous cascader component (#1321) --- mock/demo/api-cascader.ts | 325 ++++++++++++++++++ src/api/demo/cascader.ts | 9 + src/api/demo/model/areaModel.ts | 12 + src/components/Form/index.ts | 1 + src/components/Form/src/componentMap.ts | 2 + .../Form/src/components/ApiCascader.vue | 197 +++++++++++ src/components/Form/src/types/index.ts | 1 + src/views/demo/form/UseForm.vue | 76 +++- 8 files changed, 622 insertions(+), 1 deletion(-) create mode 100644 mock/demo/api-cascader.ts create mode 100644 src/api/demo/cascader.ts create mode 100644 src/api/demo/model/areaModel.ts create mode 100644 src/components/Form/src/components/ApiCascader.vue diff --git a/mock/demo/api-cascader.ts b/mock/demo/api-cascader.ts new file mode 100644 index 00000000..6334ef5b --- /dev/null +++ b/mock/demo/api-cascader.ts @@ -0,0 +1,325 @@ +import { MockMethod } from 'vite-plugin-mock'; +import { resultSuccess } from '../_util'; + +const areaList: any[] = [ + { + id: '530825900854620160', + code: '430000', + parentCode: '100000', + levelType: 1, + name: '湖南省', + province: '湖南省', + city: null, + district: null, + town: null, + village: null, + parentPath: '430000', + createTime: '2020-11-30 15:47:31', + updateTime: '2020-11-30 16:33:42', + customized: false, + usable: true, + }, + { + id: '530825900883980288', + code: '430100', + parentCode: '430000', + levelType: 2, + name: '长沙市', + province: '湖南省', + city: '长沙市', + district: null, + town: null, + village: null, + parentPath: '430000,430100', + createTime: '2020-11-30 15:47:31', + updateTime: '2020-11-30 16:33:42', + customized: false, + usable: true, + }, + { + id: '530825900951089152', + code: '430102', + parentCode: '430100', + levelType: 3, + name: '芙蓉区', + province: '湖南省', + city: '长沙市', + district: '芙蓉区', + town: null, + village: null, + parentPath: '430000,430100,430102', + createTime: '2020-11-30 15:47:31', + updateTime: '2020-11-30 16:33:42', + customized: false, + usable: true, + }, + { + id: '530825901014003712', + code: '430104', + parentCode: '430100', + levelType: 3, + name: '岳麓区', + province: '湖南省', + city: '长沙市', + district: '岳麓区', + town: null, + village: null, + parentPath: '430000,430100,430104', + createTime: '2020-11-30 15:47:31', + updateTime: '2020-11-30 16:33:42', + customized: false, + usable: true, + }, + { + id: '530825900988837888', + code: '430103', + parentCode: '430100', + levelType: 3, + name: '天心区', + province: '湖南省', + city: '长沙市', + district: '天心区', + town: null, + village: null, + parentPath: '430000,430100,430103', + createTime: '2020-11-30 15:47:31', + updateTime: '2020-11-30 16:33:42', + customized: false, + usable: true, + }, + { + id: '530826672489115648', + code: '430103002', + parentCode: '430103', + levelType: 4, + name: '坡子街街道', + province: '湖南省', + city: '长沙市', + district: '天心区', + town: '坡子街街道', + village: null, + parentPath: '430000,430100,430103,430103002', + createTime: '2020-11-30 15:47:31', + updateTime: '2020-12-14 15:26:43', + customized: false, + usable: true, + }, + { + id: '530840241171607552', + code: '430103002001', + parentCode: '430103002', + levelType: 5, + name: '八角亭社区', + province: '湖南省', + city: '长沙市', + district: '天心区', + town: '坡子街街道', + village: '八角亭社区', + parentPath: '430000,430100,430103,430103002,430103002001', + createTime: '2020-11-30 15:47:31', + updateTime: '2021-01-20 14:07:23', + customized: false, + usable: true, + }, + { + id: '530840241200967680', + code: '430103002002', + parentCode: '430103002', + levelType: 5, + name: '西牌楼社区', + province: '湖南省', + city: '长沙市', + district: '天心区', + town: '坡子街街道', + village: '西牌楼社区', + parentPath: '430000,430100,430103,430103002,430103002002', + createTime: '2020-11-30 15:47:31', + updateTime: '2020-11-30 17:30:41', + customized: false, + usable: true, + }, + { + id: '530840241230327808', + code: '430103002003', + parentCode: '430103002', + levelType: 5, + name: '太平街社区', + province: '湖南省', + city: '长沙市', + district: '天心区', + town: '坡子街街道', + village: '太平街社区', + parentPath: '430000,430100,430103,430103002,430103002003', + createTime: '2020-11-30 15:47:31', + updateTime: '2020-11-30 17:30:41', + customized: false, + usable: true, + }, + { + id: '530840241259687936', + code: '430103002005', + parentCode: '430103002', + levelType: 5, + name: '坡子街社区', + province: '湖南省', + city: '长沙市', + district: '天心区', + town: '坡子街街道', + village: '坡子街社区', + parentPath: '430000,430100,430103,430103002,430103002005', + createTime: '2020-11-30 15:47:31', + updateTime: '2020-11-30 17:30:41', + customized: false, + usable: true, + }, + { + id: '530840241284853760', + code: '430103002006', + parentCode: '430103002', + levelType: 5, + name: '青山祠社区', + province: '湖南省', + city: '长沙市', + district: '天心区', + town: '坡子街街道', + village: '青山祠社区', + parentPath: '430000,430100,430103,430103002,430103002006', + createTime: '2020-11-30 15:47:31', + updateTime: '2020-11-30 17:30:41', + customized: false, + usable: true, + }, + { + id: '530840241310019584', + code: '430103002007', + parentCode: '430103002', + levelType: 5, + name: '沙河社区', + province: '湖南省', + city: '长沙市', + district: '天心区', + town: '坡子街街道', + village: '沙河社区', + parentPath: '430000,430100,430103,430103002,430103002007', + createTime: '2020-11-30 15:47:31', + updateTime: '2020-11-30 17:30:41', + customized: false, + usable: true, + }, + { + id: '530840241381322752', + code: '430103002008', + parentCode: '430103002', + levelType: 5, + name: '碧湘社区', + province: '湖南省', + city: '长沙市', + district: '天心区', + town: '坡子街街道', + village: '碧湘社区', + parentPath: '430000,430100,430103,430103002,430103002008', + createTime: '2020-11-30 15:47:31', + updateTime: '2020-11-30 17:30:41', + customized: false, + usable: true, + }, + { + id: '530840241410682880', + code: '430103002009', + parentCode: '430103002', + levelType: 5, + name: '创远社区', + province: '湖南省', + city: '长沙市', + district: '天心区', + town: '坡子街街道', + village: '创远社区', + parentPath: '430000,430100,430103,430103002,430103002009', + createTime: '2020-11-30 15:47:31', + updateTime: '2020-11-30 17:30:41', + customized: false, + usable: true, + }, + { + id: '530840241431654400', + code: '430103002010', + parentCode: '430103002', + levelType: 5, + name: '楚湘社区', + province: '湖南省', + city: '长沙市', + district: '天心区', + town: '坡子街街道', + village: '楚湘社区', + parentPath: '430000,430100,430103,430103002,430103002010', + createTime: '2020-11-30 15:47:31', + updateTime: '2020-11-30 17:30:41', + customized: false, + usable: true, + }, + { + id: '530840241465208832', + code: '430103002011', + parentCode: '430103002', + levelType: 5, + name: '西湖社区', + province: '湖南省', + city: '长沙市', + district: '天心区', + town: '坡子街街道', + village: '西湖社区', + parentPath: '430000,430100,430103,430103002,430103002011', + createTime: '2020-11-30 15:47:31', + updateTime: '2020-11-30 17:30:41', + customized: false, + usable: true, + }, + { + id: '530840241502957568', + code: '430103002012', + parentCode: '430103002', + levelType: 5, + name: '登仁桥社区', + province: '湖南省', + city: '长沙市', + district: '天心区', + town: '坡子街街道', + village: '登仁桥社区', + parentPath: '430000,430100,430103,430103002,430103002012', + createTime: '2020-11-30 15:47:31', + updateTime: '2020-11-30 17:30:41', + customized: false, + usable: true, + }, + { + id: '530840241553289216', + code: '430103002013', + parentCode: '430103002', + levelType: 5, + name: '文庙坪社区', + province: '湖南省', + city: '长沙市', + district: '天心区', + town: '坡子街街道', + village: '文庙坪社区', + parentPath: '430000,430100,430103,430103002,430103002013', + createTime: '2020-11-30 15:47:31', + updateTime: '2020-11-30 17:30:41', + customized: false, + usable: true, + }, +]; +export default [ + { + url: '/basic-api/cascader/getAreaRecord', + timeout: 1000, + method: 'post', + response: ({ body }) => { + const { parentCode } = body || {}; + if (!parentCode) { + return resultSuccess(areaList.filter((it) => it.code === '430000')); + } + return resultSuccess(areaList.filter((it) => it.parentCode === parentCode)); + }, + }, +] as MockMethod[]; diff --git a/src/api/demo/cascader.ts b/src/api/demo/cascader.ts new file mode 100644 index 00000000..83dcab07 --- /dev/null +++ b/src/api/demo/cascader.ts @@ -0,0 +1,9 @@ +import { defHttp } from '/@/utils/http/axios'; +import { AreaModel, AreaParams } from '/@/api/demo/model/areaModel'; + +enum Api { + AREA_RECORD = '/cascader/getAreaRecord', +} + +export const areaRecord = (data: AreaParams) => + defHttp.post({ url: Api.AREA_RECORD, data }); diff --git a/src/api/demo/model/areaModel.ts b/src/api/demo/model/areaModel.ts new file mode 100644 index 00000000..dfaa481b --- /dev/null +++ b/src/api/demo/model/areaModel.ts @@ -0,0 +1,12 @@ +export interface AreaModel { + id: string; + code: string; + parentCode: string; + name: string; + levelType: number; + [key: string]: string | number; +} + +export interface AreaParams { + parentCode: string; +} diff --git a/src/components/Form/index.ts b/src/components/Form/index.ts index 9859b29a..8bca8a36 100644 --- a/src/components/Form/index.ts +++ b/src/components/Form/index.ts @@ -10,5 +10,6 @@ export { default as ApiSelect } from './src/components/ApiSelect.vue'; export { default as RadioButtonGroup } from './src/components/RadioButtonGroup.vue'; export { default as ApiTreeSelect } from './src/components/ApiTreeSelect.vue'; export { default as ApiRadioGroup } from './src/components/ApiRadioGroup.vue'; +export { default as ApiCascader } from './src/components/ApiCascader.vue'; export { BasicForm }; diff --git a/src/components/Form/src/componentMap.ts b/src/components/Form/src/componentMap.ts index 6d0b1a6b..2f9003d5 100644 --- a/src/components/Form/src/componentMap.ts +++ b/src/components/Form/src/componentMap.ts @@ -25,6 +25,7 @@ import ApiRadioGroup from './components/ApiRadioGroup.vue'; import RadioButtonGroup from './components/RadioButtonGroup.vue'; import ApiSelect from './components/ApiSelect.vue'; import ApiTreeSelect from './components/ApiTreeSelect.vue'; +import ApiCascader from './components/ApiCascader.vue'; import { BasicUpload } from '/@/components/Upload'; import { StrengthMeter } from '/@/components/StrengthMeter'; import { IconPicker } from '/@/components/Icon'; @@ -50,6 +51,7 @@ componentMap.set('RadioButtonGroup', RadioButtonGroup); componentMap.set('RadioGroup', Radio.Group); componentMap.set('Checkbox', Checkbox); componentMap.set('CheckboxGroup', Checkbox.Group); +componentMap.set('ApiCascader', ApiCascader); componentMap.set('Cascader', Cascader); componentMap.set('Slider', Slider); componentMap.set('Rate', Rate); diff --git a/src/components/Form/src/components/ApiCascader.vue b/src/components/Form/src/components/ApiCascader.vue new file mode 100644 index 00000000..2bfd096a --- /dev/null +++ b/src/components/Form/src/components/ApiCascader.vue @@ -0,0 +1,197 @@ + + diff --git a/src/components/Form/src/types/index.ts b/src/components/Form/src/types/index.ts index c63b3408..a3e968e8 100644 --- a/src/components/Form/src/types/index.ts +++ b/src/components/Form/src/types/index.ts @@ -98,6 +98,7 @@ export type ComponentType = | 'Checkbox' | 'CheckboxGroup' | 'AutoComplete' + | 'ApiCascader' | 'Cascader' | 'DatePicker' | 'MonthPicker' diff --git a/src/views/demo/form/UseForm.vue b/src/views/demo/form/UseForm.vue index d24f3f95..95e8fb9c 100644 --- a/src/views/demo/form/UseForm.vue +++ b/src/views/demo/form/UseForm.vue @@ -52,6 +52,7 @@ > 修改查询按钮 + 联动回显 @@ -64,6 +65,7 @@ import { CollapseContainer } from '/@/components/Container/index'; import { useMessage } from '/@/hooks/web/useMessage'; import { PageWrapper } from '/@/components/Page'; + import { areaRecord } from '/@/api/demo/cascader'; const schemas: FormSchema[] = [ { @@ -166,6 +168,48 @@ ], }, }, + { + field: 'field8', + component: 'ApiCascader', + label: '联动', + colProps: { + span: 8, + }, + componentProps: { + api: areaRecord, + apiParamKey: 'parentCode', + dataField: 'data', + labelField: 'name', + valueField: 'code', + initFetchParams: { + parentCode: '', + }, + isLeaf: (record) => { + return !(record.levelType < 3); + }, + }, + }, + { + field: 'field9', + component: 'ApiCascader', + label: '联动回显', + colProps: { + span: 8, + }, + componentProps: { + api: areaRecord, + apiParamKey: 'parentCode', + dataField: 'data', + labelField: 'name', + valueField: 'code', + initFetchParams: { + parentCode: '', + }, + isLeaf: (record) => { + return !(record.levelType < 3); + }, + }, + }, ]; export default defineComponent({ @@ -173,7 +217,7 @@ setup() { const { createMessage } = useMessage(); - const [register, { setProps }] = useForm({ + const [register, { setProps, setFieldsValue, updateSchema }] = useForm({ labelWidth: 120, schemas, actionColOptions: { @@ -181,6 +225,35 @@ }, fieldMapToTime: [['fieldTime', ['startTime', 'endTime'], 'YYYY-MM']], }); + + async function handleLoad() { + const promiseFn = function () { + return new Promise((resolve) => { + setTimeout(() => { + resolve({ + field9: ['430000', '430100', '430102'], + province: '湖南省', + city: '长沙市', + district: '岳麓区', + }); + }, 1000); + }); + }; + + const item = await promiseFn(); + + const { field9, province, city, district } = item as any; + await updateSchema({ + field: 'field9', + componentProps: { + displayRenderArray: [province, city, district], + }, + }); + await setFieldsValue({ + field9, + }); + } + return { register, schemas, @@ -188,6 +261,7 @@ createMessage.success('click search,values:' + JSON.stringify(values)); }, setProps, + handleLoad, }; }, }); -- GitLab