Skip to content

Commit d81db89

Browse files
committed
feat(api-tree-select): add api options to tree-select
添加ApiTreeSelect组件
1 parent c117802 commit d81db89

File tree

9 files changed

+79
-0
lines changed

9 files changed

+79
-0
lines changed

CHANGELOG.zh_CN.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
- **NoticeList** 添加分页、超长自动省略、标题点击事件、标题删除线等功能
44
- **MixSider** 优化 Mix 菜单布局时 底部折叠按钮 的样式,与其它菜单布局时的风格保持一致
5+
- **ApiTreeSelect** 扩展`antdv``TreeSelect`组件,支持远程数据源,用法类似`ApiSelect`
56
- 可以为不同的用户指定不同的后台首页:
67
-`getUserInfo`接口返回的用户信息中增加`homePath`字段(可选)即可为当前用户定制首页路径
78

mock/demo/tree-demo.ts

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import { MockMethod } from 'vite-plugin-mock';
2+
import { resultSuccess } from '../_util';
3+
4+
const demoTreeList = (keyword) => {
5+
const result = {
6+
list: [] as Recordable[],
7+
};
8+
for (let index = 0; index < 5; index++) {
9+
const children: Recordable[] = [];
10+
for (let j = 0; j < 3; j++) {
11+
children.push({
12+
title: `${keyword ?? ''}选项${index}-${j}`,
13+
value: `${index}-${j}`,
14+
key: `${index}-${j}`,
15+
});
16+
}
17+
result.list.push({
18+
title: `${keyword ?? ''}选项${index}`,
19+
value: `${index}`,
20+
key: `${index}`,
21+
children,
22+
});
23+
}
24+
return result;
25+
};
26+
27+
export default [
28+
{
29+
url: '/basic-api/tree/getDemoOptions',
30+
timeout: 1000,
31+
method: 'get',
32+
response: ({ query }) => {
33+
const { keyword } = query;
34+
console.log(keyword);
35+
return resultSuccess(demoTreeList(keyword));
36+
},
37+
},
38+
] as MockMethod[];

src/api/demo/tree.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { defHttp } from '/@/utils/http/axios';
2+
3+
enum Api {
4+
TREE_OPTIONS_LIST = '/tree/getDemoOptions',
5+
}
6+
7+
/**
8+
* @description: Get sample options value
9+
*/
10+
export const treeOptionsListApi = (params?: Recordable) =>
11+
defHttp.get<Recordable[]>({ url: Api.TREE_OPTIONS_LIST, params });

src/components/Form/src/componentMap.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import {
2222

2323
import RadioButtonGroup from './components/RadioButtonGroup.vue';
2424
import ApiSelect from './components/ApiSelect.vue';
25+
import ApiTreeSelect from './components/ApiTreeSelect.vue';
2526
import { BasicUpload } from '/@/components/Upload';
2627
import { StrengthMeter } from '/@/components/StrengthMeter';
2728
import { IconPicker } from '/@/components/Icon';
@@ -40,6 +41,7 @@ componentMap.set('AutoComplete', AutoComplete);
4041
componentMap.set('Select', Select);
4142
componentMap.set('ApiSelect', ApiSelect);
4243
componentMap.set('TreeSelect', TreeSelect);
44+
componentMap.set('ApiTreeSelect', ApiTreeSelect);
4345
componentMap.set('Switch', Switch);
4446
componentMap.set('RadioButtonGroup', RadioButtonGroup);
4547
componentMap.set('RadioGroup', Radio.Group);

src/components/Form/src/components/ApiTreeSelect.vue

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<template> <a-tree-select v-bind="getAttrs"> <template #[item]="data" v-for="item in Object.keys($slots)"> <slot :name="item" v-bind="data"></slot> </template> <template #suffixIcon v-if="loading"> <LoadingOutlined spin /> </template> </a-tree-select></template><script lang="ts"> import { computed, defineComponent, watch, ref, onMounted, unref } from 'vue'; import { TreeSelect } from 'ant-design-vue'; import { isArray, isFunction } from '/@/utils/is'; import { get } from 'lodash-es'; import { propTypes } from '/@/utils/propTypes'; import { LoadingOutlined } from '@ant-design/icons-vue'; export default defineComponent({ name: 'ApiTreeSelect', components: { ATreeSelect: TreeSelect, LoadingOutlined }, props: { api: { type: Function as PropType<(arg?: Recordable) => Promise<Recordable>> }, params: { type: Object }, immediate: { type: Boolean, default: true }, resultField: propTypes.string.def(''), }, emits: ['options-change'], setup(props, { attrs, emit }) { const treeData = ref<Recordable[]>([]); const isFirstLoaded = ref<Boolean>(false); const loading = ref(false); const getAttrs = computed(() => { return { ...(props.api ? { treeData: unref(treeData) } : {}), ...attrs, }; }); watch([() => props.params, () => props.immediate], () => { isFirstLoaded.value && fetch(); }); onMounted(() => { props.immediate && fetch(); }); async function fetch() { const { api } = props; if (!api || !isFunction(api)) return; loading.value = true; treeData.value = []; let result; try { result = await api(props.params); } catch (e) { console.error(e); } loading.value = false; if (!result) return; if (!isArray(result)) { result = get(result, props.resultField); } treeData.value = (result as Recordable[]) || []; isFirstLoaded.value = true; emit('options-change', treeData.value); } return { getAttrs, loading }; }, });</script>

src/components/Form/src/types/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ export type ComponentType =
9191
| 'Select'
9292
| 'ApiSelect'
9393
| 'TreeSelect'
94+
| 'ApiTreeSelect'
9495
| 'RadioButtonGroup'
9596
| 'RadioGroup'
9697
| 'Checkbox'

src/views/demo/form/index.vue

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
4747
import { optionsListApi } from '/@/api/demo/select';
4848
import { useDebounceFn } from '@vueuse/core';
49+
import { treeOptionsListApi } from '/@/api/demo/tree';
4950
5051
const provincesOptions = [
5152
{
@@ -347,6 +348,20 @@
347348
},
348349
defaultValue: '0',
349350
},
351+
{
352+
field: 'field33',
353+
component: 'ApiTreeSelect',
354+
label: '远程下拉树',
355+
helpMessage: ['ApiTreeSelect组件', '使用接口提供的数据生成选项'],
356+
required: true,
357+
componentProps: {
358+
api: treeOptionsListApi,
359+
resultField: 'list',
360+
},
361+
colProps: {
362+
span: 8,
363+
},
364+
},
350365
{
351366
field: 'field20',
352367
component: 'InputNumber',

src/views/demo/table/EditCellTable.vue

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,9 @@
8484
editComponent: 'ApiSelect',
8585
editComponentProps: {
8686
api: optionsListApi,
87+
resultField: 'list',
88+
labelField: 'name',
89+
valueField: 'id',
8790
},
8891
width: 200,
8992
},

src/views/demo/table/EditRowTable.vue

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,10 @@
8080
label: 'Option2',
8181
value: '2',
8282
},
83+
{
84+
label: 'Option3',
85+
value: '3',
86+
},
8387
],
8488
},
8589
width: 200,
@@ -91,6 +95,9 @@
9195
editComponent: 'ApiSelect',
9296
editComponentProps: {
9397
api: optionsListApi,
98+
resultField: 'list',
99+
labelField: 'name',
100+
valueField: 'id',
94101
},
95102
width: 200,
96103
},

0 commit comments

Comments
 (0)