feat: 添加 LoRA 类型和反馈控制器,优化数据集名称和目标模型保存功能
This commit is contained in:
@@ -12,3 +12,14 @@ export const ModelChoices: Option<TargetModels>[] = [
|
|||||||
{ label: 'Flux', value: 'flux' },
|
{ label: 'Flux', value: 'flux' },
|
||||||
{ label: 'Flux 2', value: 'flux2' },
|
{ label: 'Flux 2', value: 'flux2' },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
export type LoRATypes = 'char' | 'clothing' | 'style' | 'concept' | 'scene' | 'other';
|
||||||
|
|
||||||
|
export const LoRATypeChoices: Option<LoRATypes>[] = [
|
||||||
|
{ label: 'Character', value: 'char' },
|
||||||
|
{ label: 'Clothing', value: 'clothing' },
|
||||||
|
{ label: 'Style', value: 'style' },
|
||||||
|
{ label: 'Concept', value: 'concept' },
|
||||||
|
{ label: 'Scene', value: 'scene' },
|
||||||
|
{ label: 'Other', value: 'other' },
|
||||||
|
]
|
||||||
|
|||||||
@@ -0,0 +1,55 @@
|
|||||||
|
export type SaveFeedbackState = 'idle' | 'updated' | 'not-updated';
|
||||||
|
|
||||||
|
export function createSaveFeedbackController(
|
||||||
|
setState: (state: SaveFeedbackState) => void,
|
||||||
|
resetDelayMs = 2000,
|
||||||
|
) {
|
||||||
|
let feedbackTimer: ReturnType<typeof setTimeout> | null = null;
|
||||||
|
|
||||||
|
const resetLater = () => {
|
||||||
|
if (feedbackTimer) {
|
||||||
|
clearTimeout(feedbackTimer);
|
||||||
|
}
|
||||||
|
|
||||||
|
feedbackTimer = setTimeout(() => {
|
||||||
|
setState('idle');
|
||||||
|
}, resetDelayMs);
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
markUpdated() {
|
||||||
|
setState('updated');
|
||||||
|
resetLater();
|
||||||
|
},
|
||||||
|
markNotUpdated() {
|
||||||
|
setState('not-updated');
|
||||||
|
resetLater();
|
||||||
|
},
|
||||||
|
dispose() {
|
||||||
|
if (feedbackTimer) {
|
||||||
|
clearTimeout(feedbackTimer);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function createDebouncedTrigger(callback: () => void, delayMs: number) {
|
||||||
|
let timer: ReturnType<typeof setTimeout> | null = null;
|
||||||
|
|
||||||
|
return {
|
||||||
|
trigger() {
|
||||||
|
if (timer) {
|
||||||
|
clearTimeout(timer);
|
||||||
|
}
|
||||||
|
|
||||||
|
timer = setTimeout(() => {
|
||||||
|
callback();
|
||||||
|
}, delayMs);
|
||||||
|
},
|
||||||
|
cancel() {
|
||||||
|
if (timer) {
|
||||||
|
clearTimeout(timer);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -1,16 +1,65 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { activeDatasetMeta } from '$lib/stores/dataset';
|
import { activeDatasetMeta, updateActiveDatasetMeta } from '$lib/stores/dataset';
|
||||||
import { onMount } from 'svelte';
|
import {
|
||||||
|
createDebouncedTrigger,
|
||||||
|
createSaveFeedbackController,
|
||||||
|
type SaveFeedbackState,
|
||||||
|
} from '$lib/utils/form-save';
|
||||||
|
import { onDestroy, onMount } from 'svelte';
|
||||||
import { get } from 'svelte/store';
|
import { get } from 'svelte/store';
|
||||||
|
|
||||||
let name = $state('');
|
let name = $state('');
|
||||||
|
let saveFeedback = $state<SaveFeedbackState>('idle');
|
||||||
|
|
||||||
|
const feedback = createSaveFeedbackController((state) => {
|
||||||
|
saveFeedback = state;
|
||||||
|
});
|
||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
name = get(activeDatasetMeta)?.name ?? '';
|
name = get(activeDatasetMeta)?.name ?? '';
|
||||||
});
|
});
|
||||||
|
|
||||||
|
onDestroy(() => {
|
||||||
|
saveLater.cancel();
|
||||||
|
feedback.dispose();
|
||||||
|
});
|
||||||
|
|
||||||
|
async function saveDatasetName(value: string) {
|
||||||
|
const nextName = value.trim();
|
||||||
|
|
||||||
|
if (!nextName) {
|
||||||
|
feedback.markNotUpdated();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
await updateActiveDatasetMeta({ name: nextName });
|
||||||
|
feedback.markUpdated();
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to save dataset name:', error);
|
||||||
|
feedback.markNotUpdated();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const saveLater = createDebouncedTrigger(() => {
|
||||||
|
void saveDatasetName(name);
|
||||||
|
}, 5000);
|
||||||
|
|
||||||
|
function saveNameDelayed() {
|
||||||
|
saveLater.trigger();
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<label class="input w-fit in-focus-within:outline-0">
|
<label
|
||||||
|
class={[
|
||||||
|
'input w-fit in-focus-within:outline-0 transition-colors duration-300 ease-out',
|
||||||
|
saveFeedback === 'updated' && 'border-green-500',
|
||||||
|
saveFeedback === 'not-updated' && 'border-red-500',
|
||||||
|
]}>
|
||||||
<span class="label min-w-[10em]">Dataset Name</span>
|
<span class="label min-w-[10em]">Dataset Name</span>
|
||||||
<input type="text" bind:value={name} class="min-w-[20em] focus:outline-0" />
|
<input
|
||||||
|
type="text"
|
||||||
|
bind:value={name}
|
||||||
|
oninput={saveNameDelayed}
|
||||||
|
class="min-w-[20em] focus:outline-0" />
|
||||||
</label>
|
</label>
|
||||||
|
|||||||
@@ -1,62 +1,46 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { activeDatasetMeta, updateActiveDatasetMeta } from '$lib/stores/dataset';
|
import { activeDatasetMeta, updateActiveDatasetMeta } from '$lib/stores/dataset';
|
||||||
import { ModelChoices, type TargetModels } from '$lib/types/models';
|
import { ModelChoices, type TargetModels } from '$lib/types/models';
|
||||||
|
import { createSaveFeedbackController, type SaveFeedbackState } from '$lib/utils/form-save';
|
||||||
import { onDestroy, onMount } from 'svelte';
|
import { onDestroy, onMount } from 'svelte';
|
||||||
import { get } from 'svelte/store';
|
import { get } from 'svelte/store';
|
||||||
|
|
||||||
let selected: TargetModels | null = $state(null);
|
let selected: TargetModels | null = $state(null);
|
||||||
let updated = $state(false);
|
let saveFeedback = $state<SaveFeedbackState>('idle');
|
||||||
let notUpdated = $state(false);
|
|
||||||
let feedbackTimer: ReturnType<typeof setTimeout> | null = null;
|
const feedback = createSaveFeedbackController((state) => {
|
||||||
|
saveFeedback = state;
|
||||||
|
});
|
||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
selected = get(activeDatasetMeta)?.targetModel ?? null;
|
selected = get(activeDatasetMeta)?.targetModel ?? null;
|
||||||
});
|
});
|
||||||
|
|
||||||
onDestroy(() => {
|
onDestroy(() => {
|
||||||
if (feedbackTimer) {
|
feedback.dispose();
|
||||||
clearTimeout(feedbackTimer);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
function resetFeedbackIn2s() {
|
|
||||||
if (feedbackTimer) {
|
|
||||||
clearTimeout(feedbackTimer);
|
|
||||||
}
|
|
||||||
|
|
||||||
feedbackTimer = setTimeout(() => {
|
|
||||||
updated = false;
|
|
||||||
notUpdated = false;
|
|
||||||
}, 2000);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function saveTargetModel() {
|
async function saveTargetModel() {
|
||||||
if (!selected) {
|
if (!selected) {
|
||||||
updated = false;
|
feedback.markNotUpdated();
|
||||||
notUpdated = true;
|
|
||||||
resetFeedbackIn2s();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await updateActiveDatasetMeta({ targetModel: selected });
|
await updateActiveDatasetMeta({ targetModel: selected });
|
||||||
updated = true;
|
feedback.markUpdated();
|
||||||
notUpdated = false;
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Failed to save target model:', error);
|
console.error('Failed to save target model:', error);
|
||||||
updated = false;
|
feedback.markNotUpdated();
|
||||||
notUpdated = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
resetFeedbackIn2s();
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<label
|
<label
|
||||||
class={[
|
class={[
|
||||||
'input w-fit in-focus-within:outline-0 transition-colors duration-300 ease-out',
|
'input w-fit in-focus-within:outline-0 transition-colors duration-300 ease-out',
|
||||||
updated && 'border-green-500',
|
saveFeedback === 'updated' && 'border-green-500',
|
||||||
notUpdated && 'border-red-500',
|
saveFeedback === 'not-updated' && 'border-red-500',
|
||||||
]}>
|
]}>
|
||||||
<span class="label min-w-[10em]">Target Model</span>
|
<span class="label min-w-[10em]">Target Model</span>
|
||||||
<select bind:value={selected} onchange={saveTargetModel} class="min-w-[20em] focus:outline-0">
|
<select bind:value={selected} onchange={saveTargetModel} class="min-w-[20em] focus:outline-0">
|
||||||
|
|||||||
Reference in New Issue
Block a user