Merge branch 'main' of https://github.com/vbenjs/vue-vben-admin
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
<script lang="ts" setup>
|
||||
import type { AnyPromiseFunction } from '@vben/types';
|
||||
|
||||
import { computed, ref, unref, useAttrs, type VNode, watch } from 'vue';
|
||||
import { type Component, computed, ref, unref, useAttrs, watch } from 'vue';
|
||||
|
||||
import { LoaderCircle } from '@vben/icons';
|
||||
import { get, isEqual, isFunction } from '@vben-core/shared/utils';
|
||||
@@ -10,37 +10,56 @@ import { objectOmit } from '@vueuse/core';
|
||||
|
||||
type OptionsItem = {
|
||||
[name: string]: any;
|
||||
children?: OptionsItem[];
|
||||
disabled?: boolean;
|
||||
label?: string;
|
||||
value?: string;
|
||||
};
|
||||
|
||||
interface Props {
|
||||
// 组件
|
||||
component: VNode;
|
||||
/** 组件 */
|
||||
component: Component;
|
||||
/** 是否将value从数字转为string */
|
||||
numberToString?: boolean;
|
||||
/** 获取options数据的函数 */
|
||||
api?: (arg?: any) => Promise<OptionsItem[] | Record<string, any>>;
|
||||
/** 传递给api的参数 */
|
||||
params?: Record<string, any>;
|
||||
/** 从api返回的结果中提取options数组的字段名 */
|
||||
resultField?: string;
|
||||
/** label字段名 */
|
||||
labelField?: string;
|
||||
/** children字段名,需要层级数据的组件可用 */
|
||||
childrenField?: string;
|
||||
/** value字段名 */
|
||||
valueField?: string;
|
||||
/** 组件接收options数据的属性名 */
|
||||
optionsPropName?: string;
|
||||
/** 是否立即调用api */
|
||||
immediate?: boolean;
|
||||
/** 每次`visibleEvent`事件发生时都重新请求数据 */
|
||||
alwaysLoad?: boolean;
|
||||
/** 在api请求之前的回调函数 */
|
||||
beforeFetch?: AnyPromiseFunction<any, any>;
|
||||
/** 在api请求之后的回调函数 */
|
||||
afterFetch?: AnyPromiseFunction<any, any>;
|
||||
/** 直接传入选项数据,也作为api返回空数据时的后备数据 */
|
||||
options?: OptionsItem[];
|
||||
// 尾部插槽
|
||||
/** 组件的插槽名称,用来显示一个"加载中"的图标 */
|
||||
loadingSlot?: string;
|
||||
// 可见时触发的事件名
|
||||
/** 触发api请求的事件名 */
|
||||
visibleEvent?: string;
|
||||
modelField?: string;
|
||||
/** 组件的v-model属性名,默认为modelValue。部分组件可能为value */
|
||||
modelPropName?: string;
|
||||
}
|
||||
|
||||
defineOptions({ name: 'ApiSelect', inheritAttrs: false });
|
||||
defineOptions({ name: 'ApiComponent', inheritAttrs: false });
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
labelField: 'label',
|
||||
valueField: 'value',
|
||||
childrenField: '',
|
||||
optionsPropName: 'options',
|
||||
resultField: '',
|
||||
visibleEvent: '',
|
||||
numberToString: false,
|
||||
@@ -50,7 +69,7 @@ const props = withDefaults(defineProps<Props>(), {
|
||||
loadingSlot: '',
|
||||
beforeFetch: undefined,
|
||||
afterFetch: undefined,
|
||||
modelField: 'modelValue',
|
||||
modelPropName: 'modelValue',
|
||||
api: undefined,
|
||||
options: () => [],
|
||||
});
|
||||
@@ -69,29 +88,34 @@ const loading = ref(false);
|
||||
const isFirstLoaded = ref(false);
|
||||
|
||||
const getOptions = computed(() => {
|
||||
const { labelField, valueField, numberToString } = props;
|
||||
const { labelField, valueField, childrenField, numberToString } = props;
|
||||
|
||||
const data: OptionsItem[] = [];
|
||||
const refOptionsData = unref(refOptions);
|
||||
|
||||
for (const next of refOptionsData) {
|
||||
if (next) {
|
||||
const value = get(next, valueField);
|
||||
data.push({
|
||||
...objectOmit(next, [labelField, valueField]),
|
||||
label: get(next, labelField),
|
||||
function transformData(data: OptionsItem[]): OptionsItem[] {
|
||||
return data.map((item) => {
|
||||
const value = get(item, valueField);
|
||||
return {
|
||||
...objectOmit(item, [labelField, valueField, childrenField]),
|
||||
label: get(item, labelField),
|
||||
value: numberToString ? `${value}` : value,
|
||||
});
|
||||
}
|
||||
...(childrenField && item[childrenField]
|
||||
? { children: transformData(item[childrenField]) }
|
||||
: {}),
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
const data: OptionsItem[] = transformData(refOptionsData);
|
||||
|
||||
return data.length > 0 ? data : props.options;
|
||||
});
|
||||
|
||||
const bindProps = computed(() => {
|
||||
return {
|
||||
[props.modelField]: unref(modelValue),
|
||||
[`onUpdate:${props.modelField}`]: (val: string) => {
|
||||
[props.modelPropName]: unref(modelValue),
|
||||
[props.optionsPropName]: unref(getOptions),
|
||||
[`onUpdate:${props.modelPropName}`]: (val: string) => {
|
||||
modelValue.value = val;
|
||||
},
|
||||
...objectOmit(attrs, ['onUpdate:value']),
|
||||
@@ -168,7 +192,6 @@ function emitChange() {
|
||||
<component
|
||||
:is="component"
|
||||
v-bind="bindProps"
|
||||
:options="getOptions"
|
||||
:placeholder="$attrs.placeholder"
|
||||
>
|
||||
<template v-for="item in Object.keys($slots)" #[item]="data">
|
@@ -0,0 +1 @@
|
||||
export { default as ApiComponent } from './api-component.vue';
|
@@ -1 +0,0 @@
|
||||
export { default as ApiSelect } from './api-select.vue';
|
@@ -1,4 +1,4 @@
|
||||
export * from './api-select';
|
||||
export * from './api-component';
|
||||
export * from './captcha';
|
||||
export * from './code-mirror';
|
||||
export * from './ellipsis-text';
|
||||
|
@@ -1,5 +1,12 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, nextTick, onMounted, ref, useTemplateRef } from 'vue';
|
||||
import {
|
||||
computed,
|
||||
nextTick,
|
||||
onMounted,
|
||||
ref,
|
||||
type StyleValue,
|
||||
useTemplateRef,
|
||||
} from 'vue';
|
||||
|
||||
import { CSS_VARIABLE_LAYOUT_CONTENT_HEIGHT } from '@vben-core/shared/constants';
|
||||
import { cn } from '@vben-core/shared/utils';
|
||||
@@ -29,13 +36,11 @@ const shouldAutoHeight = ref(false);
|
||||
const headerRef = useTemplateRef<HTMLDivElement>('headerRef');
|
||||
const footerRef = useTemplateRef<HTMLDivElement>('footerRef');
|
||||
|
||||
const contentStyle = computed(() => {
|
||||
const contentStyle = computed<StyleValue>(() => {
|
||||
if (autoContentHeight) {
|
||||
return {
|
||||
height: shouldAutoHeight.value
|
||||
? `calc(var(${CSS_VARIABLE_LAYOUT_CONTENT_HEIGHT}) - ${headerHeight.value}px)`
|
||||
: '0',
|
||||
// 'overflow-y': shouldAutoHeight.value?'auto':'unset',
|
||||
height: `calc(var(${CSS_VARIABLE_LAYOUT_CONTENT_HEIGHT}) - ${headerHeight.value}px)`,
|
||||
overflowY: shouldAutoHeight.value ? 'auto' : 'unset',
|
||||
};
|
||||
}
|
||||
return {};
|
||||
|
@@ -16,6 +16,7 @@ import {
|
||||
VxeInput,
|
||||
VxeLoading,
|
||||
VxeModal,
|
||||
VxeNumberInput,
|
||||
VxePager,
|
||||
// VxeList,
|
||||
// VxeModal,
|
||||
@@ -82,6 +83,7 @@ export function initVxeTable() {
|
||||
// VxeUI.component(VxeList);
|
||||
VxeUI.component(VxeLoading);
|
||||
VxeUI.component(VxeModal);
|
||||
VxeUI.component(VxeNumberInput);
|
||||
// VxeUI.component(VxeOptgroup);
|
||||
// VxeUI.component(VxeOption);
|
||||
VxeUI.component(VxePager);
|
||||
|
Reference in New Issue
Block a user