feat: 为特色图选择器增加预览功能与自适应高度支持

This commit is contained in:
seahi committed 2026-08-06 12:51:35 +08:00
1 parent 9e33fabdbe
commit edcf251945
1 file changed
+62 -4
@@ -1,19 +1,32 @@
<script lang="ts"> <script lang="ts">
import { addToast } from '$lib/stores/toast.svelte'; import { addToast } from '$lib/stores/toast.svelte';
import { Fancybox } from '@fancyapps/ui/dist/index.js';
import '@fancyapps/ui/dist/fancybox/fancybox.css';
import { onMount } from 'svelte';
import Tabs from './Tabs.svelte'; import Tabs from './Tabs.svelte';
let { let {
cover = $bindable(''), cover = $bindable(''),
title = '特色图', title = '特色图',
inputName = 'cover', inputName = 'cover',
aspectRatio = '16/9' aspectRatio = '16/9',
adaptiveHeight = false,
previewable = false
} = $props<{ } = $props<{
cover?: string | null; cover?: string | null;
title?: string; title?: string;
inputName?: string; inputName?: string;
aspectRatio?: string; aspectRatio?: string;
adaptiveHeight?: boolean;
previewable?: boolean;
}>(); }>();
let pickerElement = $state<HTMLDivElement>();
let previewHeightRatio = $derived((() => {
const [width, height] = aspectRatio.split('/').map(Number);
return width > 0 && height > 0 ? height / width : 9 / 16;
})());
let activeTab = $state('url'); let activeTab = $state('url');
let isUploading = $state(false); let isUploading = $state(false);
@@ -22,6 +35,16 @@
let hasMore = $state(true); let hasMore = $state(true);
let isLoadingLibrary = $state(false); let isLoadingLibrary = $state(false);
onMount(() => {
if (!previewable || !pickerElement) return;
const selector = '[data-fancybox="featured-image-preview"]';
const container = pickerElement;
Fancybox.bind(container, selector, {});
return () => Fancybox.unbind(container, selector);
});
async function loadLibrary(reset = false) { async function loadLibrary(reset = false) {
if (reset) { if (reset) {
page = 1; page = 1;
@@ -89,14 +112,31 @@
} }
</script> </script>
<div class="sidebar-box"> <div class="sidebar-box" bind:this={pickerElement}>
{#if title} {#if title}
<h3>{title}</h3> <h3>{title}</h3>
{/if} {/if}
{#if cover} {#if cover}
<div class="cover-preview"> <div
<img src={cover} alt="图片预览" style:aspect-ratio={aspectRatio} /> class="cover-preview"
class:adaptive-height={adaptiveHeight}
style={`--preview-aspect-ratio: ${aspectRatio}; --preview-height-ratio: ${previewHeightRatio}`}
>
{#if previewable}
<a
class="cover-preview-link"
href={cover}
data-fancybox="featured-image-preview"
data-caption={title || '特色图'}
aria-label="查看特色图大图"
title="点击查看大图"
>
<img src={cover} alt="图片预览" />
</a>
{:else}
<img src={cover} alt="图片预览" />
{/if}
<button type="button" class="btn-clear" onclick={() => cover = ''}>移除</button> <button type="button" class="btn-clear" onclick={() => cover = ''}>移除</button>
</div> </div>
{/if} {/if}
@@ -166,6 +206,16 @@
overflow: hidden; overflow: hidden;
} }
.cover-preview.adaptive-height {
container-type: inline-size;
}
.cover-preview-link {
display: block;
background: #f5f5f5;
cursor: zoom-in;
}
.cover-preview img { .cover-preview img {
width: 100%; width: 100%;
height: auto; height: auto;
@@ -174,6 +224,14 @@
max-height: 280px; max-height: 280px;
} }
.cover-preview:not(.adaptive-height) img {
aspect-ratio: var(--preview-aspect-ratio);
}
.cover-preview.adaptive-height img {
max-height: min(280px, calc(100cqw * var(--preview-height-ratio)));
}
.btn-clear { .btn-clear {
position: absolute; position: absolute;
top: 8px; top: 8px;