fix(admin): stop cropping the layout preview images in image_select

AksImageSelectField pinned every preview to a 60x60 box with
object-fit:cover, but these are wide layout strips: header layouts are
597x57 (10.47:1), the footer template is 800x190 (4.21:1) and the slide
align set is 200x101. A 10:1 strip inside a square crop keeps ~6% of its
width, so the layout it is supposed to illustrate is unrecognisable.

Constrain the width instead and let the height follow, which is what the
reference theme's CSF image_select does (max-width:100%; height:auto).
Each field now declares the width that suits its images, and an option
may still override it: header 200, footer 240, slide align 160, mobile
header 120.

Only presentation changed. No image files and no stored values moved,
so existing settings are unaffected.
This commit is contained in:
kate522 committed 2026-11-01 12:18:14 +08:00
1 parent 4740078135
commit df12f51199
4 files changed
+32 -16

No files matched your search

@@ -329,6 +329,7 @@
:model-value="modelValue"
:options="normalizedOptions"
:disabled="schema.disabled"
:preview-width="schema.previewWidth"
@update:model-value="emit('update:modelValue', $event)"
/>
@@ -11,8 +11,8 @@
:disabled="disabled"
@click="emit('update:modelValue', opt.value)"
>
<img v-if="opt.image" :src="opt.image" :alt="opt.label" class="aksrt-image-select__img" />
<span v-else class="aksrt-image-select__placeholder">
<img v-if="opt.image" :src="opt.image" :alt="opt.label" class="aksrt-image-select__img" :style="imgStyle(opt)" />
<span v-else class="aksrt-image-select__placeholder" :style="imgStyle(opt)">
<FaIcon :icon="opt.icon || 'fa fas fa-image'" :size="20" />
</span>
<span class="aksrt-image-select__label">{{ opt.label }}</span>
@@ -24,12 +24,21 @@
/** image_select:带预览图的单选。 */
import FaIcon from './FaIcon.vue'
defineProps({
const props = defineProps({
modelValue: { default: null },
options: { type: Array, default: () => [] },
disabled: { type: Boolean, default: false },
// Preview width in px. Layout strips (header/footer) are very wide and only
// need enough width to be legible; near-square previews want more room.
previewWidth: { type: [Number, String], default: 140 },
})
const emit = defineEmits(['update:modelValue'])
// An option may override the group width via its own `width`.
function imgStyle(opt) {
const width = opt && opt.width ? opt.width : props.previewWidth
return { '--aksrt-image-select-max': typeof width === 'number' ? `${width}px` : width }
}
</script>
<style scoped>
@@ -69,17 +78,23 @@ const emit = defineEmits(['update:modelValue'])
}
.aksrt-image-select__img {
width: 60px;
height: 60px;
object-fit: cover;
display: block;
/* Preview images are wide layout strips (header 597x57, footer 800x190, slide
align 200x101), so let them keep their own aspect ratio inside the card.
A fixed square box with object-fit:cover crops the layout to an
unrecognisable sliver — the width is capped instead and the height follows. */
width: 100%;
max-width: var(--aksrt-image-select-max, 140px);
height: auto;
border-radius: 4px;
background: var(--aksrt-color-canvas);
}
.aksrt-image-select__placeholder {
display: flex;
align-items: center;
justify-content: center;
width: 60px;
width: var(--aksrt-image-select-max, 140px);
height: 60px;
border-radius: 4px;
background: var(--aksrt-color-canvas);