调整buttongroup和checkgroup布局

This commit is contained in:
fofolee 2025-02-12 15:09:42 +08:00
parent ed609b3fa9
commit 6e8a0c79e3
2 changed files with 75 additions and 20 deletions

View File

@ -7,15 +7,32 @@
> >
<div class="button-group"> <div class="button-group">
<div <div
v-for="opt in options" v-for="opt in formattedOptions"
:key="opt.value" :key="opt.value"
:style="{ :style="{
height: height, height: height,
flex: `1 0 calc(${100 / formattedOptions.length}% - ${
(4 * (formattedOptions.length - 1)) / formattedOptions.length
}px)`,
}" }"
:class="['button-item', { active: modelValue === opt.value }]" :class="[
'button-item',
{
active: modelValue === opt.value,
disabled: opt.disabled,
},
]"
@click="$emit('update:modelValue', opt.value)" @click="$emit('update:modelValue', opt.value)"
> >
{{ opt.label }} <div class="q-mr-sm" v-if="opt.icon">
<q-img
:src="opt.icon"
width="24px"
v-if="opt.icon.includes('.png')"
/>
<q-icon :name="opt.icon" v-else />
</div>
<div>{{ opt.label }}</div>
</div> </div>
</div> </div>
</component> </component>
@ -34,10 +51,6 @@ export default defineComponent({
modelValue: { modelValue: {
required: true, required: true,
}, },
height: {
type: String,
default: "26px",
},
options: { options: {
type: Array, type: Array,
required: true, required: true,
@ -54,8 +67,20 @@ export default defineComponent({
type: Boolean, type: Boolean,
default: false, default: false,
}, },
height: {
type: String,
default: "32px",
},
}, },
emits: ["update:modelValue"], emits: ["update:modelValue"],
computed: {
formattedOptions() {
return this.options.map((opt) => ({
...opt,
value: opt.value ?? opt.name,
}));
},
},
}); });
</script> </script>
@ -64,13 +89,11 @@ export default defineComponent({
display: flex; display: flex;
width: 100%; width: 100%;
flex-wrap: wrap; flex-wrap: wrap;
gap: 6px; gap: 4px;
border-radius: 6px;
} }
.button-item { .button-item {
flex: 1; min-width: fit-content;
min-width: 80px;
display: inline-flex; display: inline-flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
@ -95,4 +118,11 @@ export default defineComponent({
background: var(--q-primary); background: var(--q-primary);
border-color: var(--q-primary); border-color: var(--q-primary);
} }
.button-item.disabled {
opacity: 0.5;
cursor: not-allowed;
pointer-events: none;
filter: grayscale(1);
}
</style> </style>

View File

@ -7,7 +7,7 @@
> >
<div class="check-btn-group"> <div class="check-btn-group">
<q-btn <q-btn
v-for="option in options" v-for="option in formattedOptions"
:key="option.value" :key="option.value"
:color="isSelected(option.value) ? 'primary' : 'grey-7'" :color="isSelected(option.value) ? 'primary' : 'grey-7'"
:flat="!isSelected(option.value)" :flat="!isSelected(option.value)"
@ -18,15 +18,24 @@
{ 'check-btn--selected': isSelected(option.value) }, { 'check-btn--selected': isSelected(option.value) },
]" ]"
:style="{ :style="{
flex: `1 0 calc(${100 / options.length}% - ${ flex: `1 0 calc(${100 / formattedOptions.length}% - ${
(4 * (options.length - 1)) / options.length (4 * (formattedOptions.length - 1)) / formattedOptions.length
}px)`, }px)`,
height: height,
}" }"
@click="toggleOption(option.value)" @click="toggleOption(option.value)"
> >
<template #default> <template #default>
<div class="row items-center full-width"> <div class="row items-center full-width">
<div class="check-btn-content"> <div class="check-btn-content row items-center">
<div class="q-mr-sm" v-if="option.icon">
<q-img
:src="option.icon"
width="24px"
v-if="option.icon.includes('.png')"
/>
<q-icon :name="option.icon" v-else />
</div>
<div class="check-btn-label">{{ option.label }}</div> <div class="check-btn-label">{{ option.label }}</div>
</div> </div>
<q-icon <q-icon
@ -61,8 +70,6 @@ export default defineComponent({
options: { options: {
type: Array, type: Array,
required: true, required: true,
validator: (options) =>
options.every((opt) => opt.label && opt.value !== undefined),
}, },
label: { label: {
type: String, type: String,
@ -76,6 +83,26 @@ export default defineComponent({
type: Boolean, type: Boolean,
default: false, default: false,
}, },
height: {
type: String,
default: "36px",
},
},
computed: {
formattedOptions() {
return this.options.map((opt) => {
if (typeof opt === "string") {
return {
label: opt,
value: opt,
};
}
return {
...opt,
value: opt.value ?? opt.name,
};
});
},
}, },
emits: ["update:model-value"], emits: ["update:model-value"],
methods: { methods: {
@ -107,10 +134,8 @@ export default defineComponent({
.check-btn { .check-btn {
min-width: fit-content !important; min-width: fit-content !important;
max-width: 100% !important; max-width: 100% !important;
height: auto !important;
min-height: 32px;
font-size: 12px; font-size: 12px;
padding: 4px 8px; padding: 0 8px;
border-radius: 4px !important; border-radius: 4px !important;
transition: all 0.3s; transition: all 0.3s;
background-color: rgba(0, 0, 0, 0.03); background-color: rgba(0, 0, 0, 0.03);