feat(video-sources): add visible UID import entry for submissions

fix(build): rerun rust build when web/build changes
This commit is contained in:
2026-02-10 18:04:28 +08:00
parent 30f3745ac3
commit 47909dd6bf
2 changed files with 111 additions and 8 deletions

View File

@@ -1,3 +1,4 @@
fn main() {
println!("cargo:rerun-if-changed=../../web/build");
built::write_built_file().expect("Failed to acquire build-time information");
}

View File

@@ -71,6 +71,8 @@
let favoriteForm = { fid: '' };
let collectionForm = { sid: '', mid: '', collection_type: '2' }; // 默认为合集
let submissionForm = { upper_id: '' };
let importingSubmissions = false;
let submissionImportInput: HTMLInputElement | null = null;
let selectedIds: Record<string, number[]> = {
favorites: [],
collections: [],
@@ -383,6 +385,53 @@
}
}
function parseUidLines(content: string): number[] {
return [...new Set(content.split(/\r?\n/).map((line) => line.trim()).filter((line) => /^\d+$/.test(line)))].map(
(uid) => parseInt(uid)
);
}
async function handleImportSubmissionUids(file: File | null) {
if (!file) return;
importingSubmissions = true;
try {
const content = await file.text();
const uids = parseUidLines(content);
if (uids.length === 0) {
toast.error('未在文件中识别到有效 UID');
return;
}
let success = 0;
let failed = 0;
for (const uid of uids) {
try {
await api.insertSubmission({ upper_id: uid });
success += 1;
} catch {
failed += 1;
}
}
if (failed > 0) {
toast.warning('UID 文件导入完成(部分失败)', {
description: `成功 ${success} 条,失败 ${failed} 条`
});
} else {
toast.success(`UID 文件导入成功,共 ${success} 条`);
}
loadVideoSources();
} catch (error) {
toast.error('导入 UID 文件失败', {
description: (error as ApiError).message
});
} finally {
importingSubmissions = false;
}
}
function openSubmissionUidImport() {
submissionImportInput?.click();
}
// 初始化
onMount(() => {
setBreadcrumb([{ label: '视频源' }]);
@@ -451,10 +500,34 @@
{/if}
</div>
{#if key === 'favorites' || key === 'collections' || key === 'submissions'}
<div class="flex items-center gap-2">
{#if key === 'submissions'}
<input
bind:this={submissionImportInput}
type="file"
accept=".txt,text/plain"
class="hidden"
disabled={importingSubmissions}
onchange={(event) => {
const file = (event.currentTarget as HTMLInputElement).files?.[0] ?? null;
handleImportSubmissionUids(file);
(event.currentTarget as HTMLInputElement).value = '';
}}
/>
<Button
size="sm"
variant="outline"
onclick={openSubmissionUidImport}
disabled={importingSubmissions}
>
{importingSubmissions ? '导入中...' : '导入 UID.txt'}
</Button>
{/if}
<Button size="sm" onclick={() => openAddDialog(key)} class="flex items-center gap-2">
<PlusIcon class="h-4 w-4" />
手动添加
</Button>
</div>
{/if}
</div>
{#if sources.length > 0}
@@ -620,10 +693,21 @@
{/if}
</p>
{#if key === 'favorites' || key === 'collections' || key === 'submissions'}
<div class="flex items-center gap-2">
{#if key === 'submissions'}
<Button
variant="outline"
onclick={openSubmissionUidImport}
disabled={importingSubmissions}
>
{importingSubmissions ? '导入中...' : '导入 UID.txt'}
</Button>
{/if}
<Button onclick={() => openAddDialog(key)} class="flex items-center gap-2">
<PlusIcon class="h-4 w-4" />
手动添加
</Button>
</div>
{/if}
</div>
{/if}
@@ -839,6 +923,24 @@
class="mt-1"
/>
</div>
<div>
<Label for="uid-file" class="text-sm font-medium">导入 UID.txt</Label>
<Input
id="uid-file"
type="file"
accept=".txt,text/plain"
class="mt-1"
disabled={importingSubmissions}
onchange={(event) => {
const file = (event.currentTarget as HTMLInputElement).files?.[0] ?? null;
handleImportSubmissionUids(file);
(event.currentTarget as HTMLInputElement).value = '';
}}
/>
<p class="text-muted-foreground mt-1 text-xs">
每行一个 UID例如2122895527
</p>
</div>
</div>
{/if}
<div class="mt-4 space-y-1.5">