feat: 添加目标尺寸组件,支持动态保存和反馈机制

This commit is contained in:
Vixalie
2026-03-28 18:48:05 +08:00
parent bb59e88e8e
commit 66a8c1f931
3 changed files with 88 additions and 0 deletions

View File

@@ -4,3 +4,11 @@
html, body {
@apply size-full;
}
input {
&[type='number']::-webkit-outer-spin-button,
&[type='number']::-webkit-inner-spin-button {
-webkit-appearance: none;
margin: 0;
}
}

View File

@@ -2,10 +2,12 @@
import DatasetName from './meta-form/DatasetName.svelte';
import SelectLoraType from './meta-form/SelectLoraType.svelte';
import SelectModel from './meta-form/SelectModel.svelte';
import TargetSize from './meta-form/TargetSize.svelte';
</script>
<div class="flex flex-col gap-2 px-4 py-4">
<DatasetName />
<SelectModel />
<SelectLoraType />
<TargetSize />
</div>

View File

@@ -0,0 +1,78 @@
<script lang="ts">
import { activeDatasetMeta, updateActiveDatasetMeta } from '$lib/stores/dataset';
import {
createDebouncedTrigger,
createSaveFeedbackController,
type SaveFeedbackState,
} from '$lib/utils/form-save';
import { onDestroy, onMount } from 'svelte';
import { get } from 'svelte/store';
let width = $state<number>(512);
let height = $state<number>(512);
let saveFeedback = $state<SaveFeedbackState>('idle');
const feedback = createSaveFeedbackController((state) => {
saveFeedback = state;
});
onMount(() => {
const meta = get(activeDatasetMeta);
if (meta?.imageSize) {
width = meta.imageSize?.[0] ?? 512;
height = meta.imageSize?.[1] ?? 512;
}
});
onDestroy(() => {
saveLater.cancel();
feedback.dispose();
});
async function saveTargetSize(nextWidth: number, nextHeight: number) {
const normalizedWidth = Number.isFinite(nextWidth) ? Math.floor(nextWidth) : 0;
const normalizedHeight = Number.isFinite(nextHeight) ? Math.floor(nextHeight) : 0;
if (normalizedWidth <= 0 || normalizedHeight <= 0) {
feedback.markNotUpdated();
return;
}
try {
await updateActiveDatasetMeta({ imageSize: [normalizedWidth, normalizedHeight] });
feedback.markUpdated();
} catch (error) {
console.error('Failed to save target size:', error);
feedback.markNotUpdated();
}
}
const saveLater = createDebouncedTrigger(() => {
void saveTargetSize(width, height);
}, 5000);
function saveTargetSizeDelayed() {
saveLater.trigger();
}
</script>
<label
class={[
'input w-fit focus-within:outline-none transition-colors duration-300 ease-out',
saveFeedback === 'updated' && 'border-green-500',
saveFeedback === 'not-updated' && 'border-red-500',
]}>
<span class="label min-w-[10em]">Scale To</span>
<input
type="number"
class="text-right max-w-[5em]"
bind:value={width}
oninput={saveTargetSizeDelayed} />
<span>&times;</span>
<input
type="number"
class="text-right max-w-[5em]"
bind:value={height}
oninput={saveTargetSizeDelayed} />
<span>px</span>
</label>