feat: improve vbenCheckButtonGroup (#6329)
* 按钮组支持单选清除和多选限制最大选项数 * 按钮组支持icon插槽来定制图标
This commit is contained in:
parent
ea776aa710
commit
4102cc2211
@ -29,14 +29,25 @@ export type ValueType = boolean | number | string;
|
||||
|
||||
export interface VbenButtonGroupProps
|
||||
extends Pick<VbenButtonProps, 'disabled'> {
|
||||
/** 单选模式下允许清除选中 */
|
||||
allowClear?: boolean;
|
||||
/** 值改变前的回调 */
|
||||
beforeChange?: (
|
||||
value: ValueType,
|
||||
isChecked: boolean,
|
||||
) => boolean | PromiseLike<boolean | undefined> | undefined;
|
||||
/** 按钮样式 */
|
||||
btnClass?: any;
|
||||
/** 按钮间隔距离 */
|
||||
gap?: number;
|
||||
/** 多选模式下限制最多选择的数量。0表示不限制 */
|
||||
maxCount?: number;
|
||||
/** 是否允许多选 */
|
||||
multiple?: boolean;
|
||||
/** 选项 */
|
||||
options?: { [key: string]: any; label: CustomRenderType; value: ValueType }[];
|
||||
/** 显示图标 */
|
||||
showIcon?: boolean;
|
||||
/** 尺寸 */
|
||||
size?: 'large' | 'middle' | 'small';
|
||||
}
|
||||
|
@ -19,6 +19,8 @@ const props = withDefaults(defineProps<VbenButtonGroupProps>(), {
|
||||
multiple: false,
|
||||
showIcon: true,
|
||||
size: 'middle',
|
||||
allowClear: false,
|
||||
maxCount: 0,
|
||||
});
|
||||
const emit = defineEmits(['btnClick']);
|
||||
const btnDefaultProps = computed(() => {
|
||||
@ -82,12 +84,22 @@ async function onBtnClick(value: ValueType) {
|
||||
if (innerValue.value.includes(value)) {
|
||||
innerValue.value = innerValue.value.filter((item) => item !== value);
|
||||
} else {
|
||||
if (props.maxCount > 0 && innerValue.value.length >= props.maxCount) {
|
||||
innerValue.value = innerValue.value.slice(0, props.maxCount - 1);
|
||||
}
|
||||
innerValue.value.push(value);
|
||||
}
|
||||
modelValue.value = innerValue.value;
|
||||
} else {
|
||||
innerValue.value = [value];
|
||||
modelValue.value = value;
|
||||
if (props.allowClear && innerValue.value.includes(value)) {
|
||||
innerValue.value = [];
|
||||
modelValue.value = undefined;
|
||||
emit('btnClick', undefined);
|
||||
return;
|
||||
} else {
|
||||
innerValue.value = [value];
|
||||
modelValue.value = value;
|
||||
}
|
||||
}
|
||||
emit('btnClick', value);
|
||||
}
|
||||
@ -112,12 +124,18 @@ async function onBtnClick(value: ValueType) {
|
||||
@click="onBtnClick(btn.value)"
|
||||
>
|
||||
<div class="icon-wrapper" v-if="props.showIcon">
|
||||
<LoaderCircle
|
||||
class="animate-spin"
|
||||
v-if="loadingValues.includes(btn.value)"
|
||||
/>
|
||||
<CircleCheckBig v-else-if="innerValue.includes(btn.value)" />
|
||||
<Circle v-else />
|
||||
<slot
|
||||
name="icon"
|
||||
:loading="loadingValues.includes(btn.value)"
|
||||
:checked="innerValue.includes(btn.value)"
|
||||
>
|
||||
<LoaderCircle
|
||||
class="animate-spin"
|
||||
v-if="loadingValues.includes(btn.value)"
|
||||
/>
|
||||
<CircleCheckBig v-else-if="innerValue.includes(btn.value)" />
|
||||
<Circle v-else />
|
||||
</slot>
|
||||
</div>
|
||||
<slot name="option" :label="btn.label" :value="btn.value" :data="btn">
|
||||
<VbenRenderContent :content="btn.label" />
|
||||
|
@ -9,6 +9,7 @@ import {
|
||||
VbenButtonGroup,
|
||||
VbenCheckButtonGroup,
|
||||
} from '@vben/common-ui';
|
||||
import { LoaderCircle, Square, SquareCheckBig } from '@vben/icons';
|
||||
|
||||
import { Button, Card, message } from 'ant-design-vue';
|
||||
|
||||
@ -51,6 +52,7 @@ const compProps = reactive({
|
||||
gap: 0,
|
||||
showIcon: true,
|
||||
size: 'middle',
|
||||
allowClear: false,
|
||||
} as Recordable<any>);
|
||||
|
||||
const [Form] = useVbenForm({
|
||||
@ -63,6 +65,9 @@ const [Form] = useVbenForm({
|
||||
}
|
||||
});
|
||||
},
|
||||
commonConfig: {
|
||||
labelWidth: 150,
|
||||
},
|
||||
schema: [
|
||||
{
|
||||
component: 'RadioGroup',
|
||||
@ -109,6 +114,20 @@ const [Form] = useVbenForm({
|
||||
fieldName: 'beforeChange',
|
||||
label: '前置回调',
|
||||
},
|
||||
{
|
||||
component: 'Switch',
|
||||
defaultValue: false,
|
||||
fieldName: 'allowClear',
|
||||
label: '允许清除',
|
||||
help: '单选时是否允许取消选中(值为undefined)',
|
||||
},
|
||||
{
|
||||
component: 'InputNumber',
|
||||
defaultValue: 0,
|
||||
fieldName: 'maxCount',
|
||||
label: '最大选中数量',
|
||||
help: '多选时有效,0表示不限制',
|
||||
},
|
||||
],
|
||||
showDefaultActions: false,
|
||||
submitOnChange: true,
|
||||
@ -186,6 +205,21 @@ function onBtnClick(value: any) {
|
||||
v-bind="compProps"
|
||||
/>
|
||||
</div>
|
||||
<p class="mt-4">自定义图标{{ checkValue }}</p>
|
||||
<div class="mt-2 flex flex-col gap-2">
|
||||
<VbenCheckButtonGroup
|
||||
v-model="checkValue"
|
||||
multiple
|
||||
:options="options"
|
||||
v-bind="compProps"
|
||||
>
|
||||
<template #icon="{ loading, checked }">
|
||||
<LoaderCircle class="animate-spin" v-if="loading" />
|
||||
<SquareCheckBig v-else-if="checked" />
|
||||
<Square v-else />
|
||||
</template>
|
||||
</VbenCheckButtonGroup>
|
||||
</div>
|
||||
</Card>
|
||||
|
||||
<Card title="设置" class="mt-4">
|
||||
|
Loading…
Reference in New Issue
Block a user