fix: 清空重置、全量刷新时跳过空路径的删除,微调前端样式 (#679)
This commit is contained in:
@@ -413,11 +413,17 @@ pub async fn full_sync_video_source(
|
||||
let warnings = if request.delete_local {
|
||||
let tasks = video_paths
|
||||
.into_iter()
|
||||
.map(|path| async move {
|
||||
tokio::fs::remove_dir_all(&path)
|
||||
.await
|
||||
.with_context(|| format!("failed to remove {path}"))?;
|
||||
Result::<_, anyhow::Error>::Ok(())
|
||||
.filter_map(|path| {
|
||||
if path.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(async move {
|
||||
tokio::fs::remove_dir_all(&path)
|
||||
.await
|
||||
.with_context(|| format!("failed to remove {path}"))?;
|
||||
Result::<_, anyhow::Error>::Ok(())
|
||||
})
|
||||
}
|
||||
})
|
||||
.collect::<FuturesUnordered<_>>();
|
||||
Some(
|
||||
|
||||
@@ -185,11 +185,15 @@ pub async fn clear_and_reset_video_status(
|
||||
.await?;
|
||||
txn.commit().await?;
|
||||
let video_info = video_info.try_into_model()?;
|
||||
let warning = tokio::fs::remove_dir_all(&video_info.path)
|
||||
.await
|
||||
.context(format!("删除本地路径「{}」失败", video_info.path))
|
||||
.err()
|
||||
.map(|e| format!("{:#}", e));
|
||||
let warning = if video_info.path.is_empty() {
|
||||
None
|
||||
} else {
|
||||
tokio::fs::remove_dir_all(&video_info.path)
|
||||
.await
|
||||
.context(format!("删除本地路径「{}」失败", video_info.path))
|
||||
.err()
|
||||
.map(|e| format!("{:#}", e))
|
||||
};
|
||||
Ok(ApiResponse::ok(ClearAndResetVideoStatusResponse {
|
||||
warning,
|
||||
video: VideoInfo {
|
||||
|
||||
@@ -137,7 +137,7 @@
|
||||
|
||||
<Card class={cardClasses}>
|
||||
<CardHeader class="shrink-0 pb-1">
|
||||
<div class="flex min-w-0 items-start justify-between gap-3 {source ? 'min-h-12' : ''}">
|
||||
<div class="flex min-w-0 items-start justify-between gap-3">
|
||||
<CardTitle
|
||||
class="line-clamp-2 min-w-0 flex-1 cursor-default {mode === 'default'
|
||||
? 'text-sm'
|
||||
@@ -163,7 +163,7 @@
|
||||
{/if}
|
||||
{#if source}
|
||||
<div class="text-muted-foreground mt-2 flex min-w-0 items-center justify-end gap-1 text-sm">
|
||||
<Badge variant="outline" class="shrink-0 px-1.5 py-0.5">
|
||||
<Badge variant="outline" class="max-w-full shrink px-1.5 py-0.5">
|
||||
{#if source.type === 'favorite'}
|
||||
<HeartIcon class="h-3.5 w-3.5 shrink-0" />
|
||||
{:else if source.type === 'collection'}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
import { Switch } from '$lib/components/ui/switch/index.js';
|
||||
import { Input } from '$lib/components/ui/input/index.js';
|
||||
import { Label } from '$lib/components/ui/label/index.js';
|
||||
import { Checkbox } from '$lib/components/ui/checkbox/index.js';
|
||||
import { Badge } from '$lib/components/ui/badge/index.js';
|
||||
import * as Table from '$lib/components/ui/table/index.js';
|
||||
import * as Tabs from '$lib/components/ui/tabs/index.js';
|
||||
@@ -648,19 +649,23 @@
|
||||
<AlertDialog.Title>全量更新视频</AlertDialog.Title>
|
||||
<AlertDialog.Description>
|
||||
确定要全量更新视频源 <strong>"{fullSyncSource?.name}"</strong> 吗?<br />
|
||||
该操作会拉取该视频源下所有当前存在的视频,移除数据库中已不存在于该源的视频及其分页数据,<span
|
||||
该操作会获取该视频源下所有当前存在的视频,移除数据库中已不存在于该源的视频及其分页数据,<span
|
||||
class="text-destructive font-medium">无法撤销</span
|
||||
>。<br />
|
||||
>。<br /><br />
|
||||
请谨慎对“稍后再看”执行全量更新操作,因为其视频源本身就具有较强的时效性,执行全量更新可能导致大量视频被移除。<br
|
||||
/>
|
||||
</AlertDialog.Description>
|
||||
</AlertDialog.Header>
|
||||
<div class="flex items-center space-x-2 py-2">
|
||||
<input
|
||||
type="checkbox"
|
||||
id="delete-local"
|
||||
bind:checked={fullSyncDeleteLocal}
|
||||
class="text-primary focus:ring-primary h-4 w-4 rounded border-gray-300"
|
||||
/>
|
||||
<label for="delete-local" class="text-sm font-medium"> 同时删除本地视频文件夹 </label>
|
||||
<div class="rounded-lg border border-orange-200 bg-orange-50 p-3">
|
||||
<div class="mb-2 flex items-center space-x-2">
|
||||
<Checkbox id="delete-local" bind:checked={fullSyncDeleteLocal} />
|
||||
<Label for="delete-local" class="text-sm font-medium text-orange-700">
|
||||
⚠️ 同时删除本地视频文件夹
|
||||
</Label>
|
||||
</div>
|
||||
<p class="text-xs leading-relaxed text-orange-700">
|
||||
删除多余视频时同时删除视频对应的本地文件夹,请谨慎勾选
|
||||
</p>
|
||||
</div>
|
||||
<AlertDialog.Footer>
|
||||
<AlertDialog.Cancel
|
||||
|
||||
@@ -293,7 +293,7 @@
|
||||
};
|
||||
parts.push(`状态:${statusLabels[state.statusFilter]}`);
|
||||
}
|
||||
if (state.validationFilter && state.validationFilter !== 'normal') {
|
||||
if (state.validationFilter) {
|
||||
const validationLabels = {
|
||||
skipped: '跳过',
|
||||
invalid: '失效',
|
||||
@@ -369,6 +369,22 @@
|
||||
}}
|
||||
></SearchBar>
|
||||
<div class="flex items-center gap-3">
|
||||
<div class="flex items-center gap-1">
|
||||
<span class="text-muted-foreground text-xs">有效性:</span>
|
||||
<ValidationFilter
|
||||
value={$appStateStore.validationFilter}
|
||||
onSelect={(value) => {
|
||||
setValidationFilter(value);
|
||||
resetCurrentPage();
|
||||
goto(`/${ToQuery($appStateStore)}`);
|
||||
}}
|
||||
onRemove={() => {
|
||||
setValidationFilter(null);
|
||||
resetCurrentPage();
|
||||
goto(`/${ToQuery($appStateStore)}`);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<!-- 状态筛选 -->
|
||||
<div class="flex items-center gap-1">
|
||||
<span class="text-muted-foreground text-xs">状态:</span>
|
||||
@@ -386,22 +402,6 @@
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div class="flex items-center gap-1">
|
||||
<span class="text-muted-foreground text-xs">有效性:</span>
|
||||
<ValidationFilter
|
||||
value={$appStateStore.validationFilter}
|
||||
onSelect={(value) => {
|
||||
setValidationFilter(value);
|
||||
resetCurrentPage();
|
||||
goto(`/${ToQuery($appStateStore)}`);
|
||||
}}
|
||||
onRemove={() => {
|
||||
setValidationFilter(null);
|
||||
resetCurrentPage();
|
||||
goto(`/${ToQuery($appStateStore)}`);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<!-- 视频源筛选 -->
|
||||
<div class="flex items-center gap-1">
|
||||
<span class="text-muted-foreground text-xs">来源:</span>
|
||||
|
||||
Reference in New Issue
Block a user