feat(api-tree-select): add `api` options to tree-select
添加ApiTreeSelect组件
This commit is contained in:
parent
c1178027f0
commit
d81db890df
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
- **NoticeList** 添加分页、超长自动省略、标题点击事件、标题删除线等功能
|
||||
- **MixSider** 优化 Mix 菜单布局时 底部折叠按钮 的样式,与其它菜单布局时的风格保持一致
|
||||
- **ApiTreeSelect** 扩展`antdv`的`TreeSelect`组件,支持远程数据源,用法类似`ApiSelect`
|
||||
- 可以为不同的用户指定不同的后台首页:
|
||||
- 在`getUserInfo`接口返回的用户信息中增加`homePath`字段(可选)即可为当前用户定制首页路径
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,38 @@
|
|||
import { MockMethod } from 'vite-plugin-mock';
|
||||
import { resultSuccess } from '../_util';
|
||||
|
||||
const demoTreeList = (keyword) => {
|
||||
const result = {
|
||||
list: [] as Recordable[],
|
||||
};
|
||||
for (let index = 0; index < 5; index++) {
|
||||
const children: Recordable[] = [];
|
||||
for (let j = 0; j < 3; j++) {
|
||||
children.push({
|
||||
title: `${keyword ?? ''}选项${index}-${j}`,
|
||||
value: `${index}-${j}`,
|
||||
key: `${index}-${j}`,
|
||||
});
|
||||
}
|
||||
result.list.push({
|
||||
title: `${keyword ?? ''}选项${index}`,
|
||||
value: `${index}`,
|
||||
key: `${index}`,
|
||||
children,
|
||||
});
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
export default [
|
||||
{
|
||||
url: '/basic-api/tree/getDemoOptions',
|
||||
timeout: 1000,
|
||||
method: 'get',
|
||||
response: ({ query }) => {
|
||||
const { keyword } = query;
|
||||
console.log(keyword);
|
||||
return resultSuccess(demoTreeList(keyword));
|
||||
},
|
||||
},
|
||||
] as MockMethod[];
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
import { defHttp } from '/@/utils/http/axios';
|
||||
|
||||
enum Api {
|
||||
TREE_OPTIONS_LIST = '/tree/getDemoOptions',
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: Get sample options value
|
||||
*/
|
||||
export const treeOptionsListApi = (params?: Recordable) =>
|
||||
defHttp.get<Recordable[]>({ url: Api.TREE_OPTIONS_LIST, params });
|
||||
|
|
@ -22,6 +22,7 @@ import {
|
|||
|
||||
import RadioButtonGroup from './components/RadioButtonGroup.vue';
|
||||
import ApiSelect from './components/ApiSelect.vue';
|
||||
import ApiTreeSelect from './components/ApiTreeSelect.vue';
|
||||
import { BasicUpload } from '/@/components/Upload';
|
||||
import { StrengthMeter } from '/@/components/StrengthMeter';
|
||||
import { IconPicker } from '/@/components/Icon';
|
||||
|
|
@ -40,6 +41,7 @@ componentMap.set('AutoComplete', AutoComplete);
|
|||
componentMap.set('Select', Select);
|
||||
componentMap.set('ApiSelect', ApiSelect);
|
||||
componentMap.set('TreeSelect', TreeSelect);
|
||||
componentMap.set('ApiTreeSelect', ApiTreeSelect);
|
||||
componentMap.set('Switch', Switch);
|
||||
componentMap.set('RadioButtonGroup', RadioButtonGroup);
|
||||
componentMap.set('RadioGroup', Radio.Group);
|
||||
|
|
|
|||
|
|
@ -0,0 +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>
|
||||
|
|
@ -91,6 +91,7 @@ export type ComponentType =
|
|||
| 'Select'
|
||||
| 'ApiSelect'
|
||||
| 'TreeSelect'
|
||||
| 'ApiTreeSelect'
|
||||
| 'RadioButtonGroup'
|
||||
| 'RadioGroup'
|
||||
| 'Checkbox'
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@
|
|||
|
||||
import { optionsListApi } from '/@/api/demo/select';
|
||||
import { useDebounceFn } from '@vueuse/core';
|
||||
import { treeOptionsListApi } from '/@/api/demo/tree';
|
||||
|
||||
const provincesOptions = [
|
||||
{
|
||||
|
|
@ -347,6 +348,20 @@
|
|||
},
|
||||
defaultValue: '0',
|
||||
},
|
||||
{
|
||||
field: 'field33',
|
||||
component: 'ApiTreeSelect',
|
||||
label: '远程下拉树',
|
||||
helpMessage: ['ApiTreeSelect组件', '使用接口提供的数据生成选项'],
|
||||
required: true,
|
||||
componentProps: {
|
||||
api: treeOptionsListApi,
|
||||
resultField: 'list',
|
||||
},
|
||||
colProps: {
|
||||
span: 8,
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'field20',
|
||||
component: 'InputNumber',
|
||||
|
|
|
|||
|
|
@ -84,6 +84,9 @@
|
|||
editComponent: 'ApiSelect',
|
||||
editComponentProps: {
|
||||
api: optionsListApi,
|
||||
resultField: 'list',
|
||||
labelField: 'name',
|
||||
valueField: 'id',
|
||||
},
|
||||
width: 200,
|
||||
},
|
||||
|
|
|
|||
|
|
@ -80,6 +80,10 @@
|
|||
label: 'Option2',
|
||||
value: '2',
|
||||
},
|
||||
{
|
||||
label: 'Option3',
|
||||
value: '3',
|
||||
},
|
||||
],
|
||||
},
|
||||
width: 200,
|
||||
|
|
@ -91,6 +95,9 @@
|
|||
editComponent: 'ApiSelect',
|
||||
editComponentProps: {
|
||||
api: optionsListApi,
|
||||
resultField: 'list',
|
||||
labelField: 'name',
|
||||
valueField: 'id',
|
||||
},
|
||||
width: 200,
|
||||
},
|
||||
|
|
|
|||
Loading…
Reference in New Issue