Compare commits
4 Commits
268d7eed07
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
38f2f853d8 | ||
|
|
b914adba74 | ||
|
|
920c7fab9c | ||
|
|
b6b87e5800 |
@@ -1,9 +1,9 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Review Videos</title>
|
||||
<title>视频审核工具</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
@@ -24,7 +24,7 @@ fn copy_directory(template_path: String, target_path: String, new_folder_name: S
|
||||
let destination = target_parent.join(&new_folder_name);
|
||||
|
||||
if !template.exists() {
|
||||
return Err("Template directory does not exist".to_string());
|
||||
return Err("模板目录不存在".to_string());
|
||||
}
|
||||
|
||||
// Remove the check for existing destination to allow merging/overwriting
|
||||
@@ -155,7 +155,7 @@ fn check_dir_exists(path: String) -> bool {
|
||||
#[tauri::command]
|
||||
fn rename_videos(files: Vec<String>, prefix: String, base_name: String) -> Result<String, String> {
|
||||
if files.is_empty() {
|
||||
return Err("No files provided".to_string());
|
||||
return Err("未提供文件".to_string());
|
||||
}
|
||||
|
||||
// 1. Group files by parent directory to ensure index uniqueness per directory
|
||||
@@ -244,7 +244,7 @@ fn rename_videos(files: Vec<String>, prefix: String, base_name: String) -> Resul
|
||||
}
|
||||
}
|
||||
|
||||
Ok(format!("Successfully renamed {} files.", renamed_count))
|
||||
Ok(format!("成功重命名 {} 个文件。", renamed_count))
|
||||
}
|
||||
|
||||
// --- Check Logic ---
|
||||
@@ -281,7 +281,7 @@ fn remove_empty_dirs_recursive(path: &Path, deleted_list: &mut Vec<String>) -> s
|
||||
fn delete_empty_dirs(path: String) -> Result<Vec<String>, String> {
|
||||
let root_path = Path::new(&path);
|
||||
if !root_path.exists() || !root_path.is_dir() {
|
||||
return Err("Path is not a valid directory".to_string());
|
||||
return Err("路径不是有效的目录".to_string());
|
||||
}
|
||||
|
||||
let mut deleted = Vec::new();
|
||||
@@ -305,7 +305,7 @@ fn delete_empty_dirs(path: String) -> Result<Vec<String>, String> {
|
||||
fn check_file_naming(path: String, prefix: String) -> Result<Vec<String>, String> {
|
||||
let root_path = Path::new(&path);
|
||||
if !root_path.exists() || !root_path.is_dir() {
|
||||
return Err("Path is not a valid directory".to_string());
|
||||
return Err("路径不是有效的目录".to_string());
|
||||
}
|
||||
|
||||
let mut mismatches = Vec::new();
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
"app": {
|
||||
"windows": [
|
||||
{
|
||||
"title": "review-videos",
|
||||
"title": "视频审核工具",
|
||||
"width": 1200,
|
||||
"height": 840
|
||||
}
|
||||
|
||||
39
src/App.vue
39
src/App.vue
@@ -40,6 +40,13 @@ const historyList = ref<string[]>([]);
|
||||
const historyMap = ref<Record<string, string[]>>({});
|
||||
const currentHistoryKey = ref("");
|
||||
|
||||
const filteredHistoryList = computed(() => {
|
||||
if (!videoNameInput.value) {
|
||||
return historyList.value;
|
||||
}
|
||||
return historyList.value.filter(item => item.toLowerCase().includes(videoNameInput.value.toLowerCase()));
|
||||
});
|
||||
|
||||
// Check Data
|
||||
const checkLogs = ref<string[]>([]);
|
||||
const logContainerRef = ref<HTMLElement | null>(null);
|
||||
@@ -108,7 +115,7 @@ const loadConfig = async () => {
|
||||
if (config.working_dir) workingDir.value = config.working_dir;
|
||||
if (config.template_dir) templateDir.value = config.template_dir;
|
||||
} catch (e) {
|
||||
console.error("Failed to load config:", e);
|
||||
console.error("加载配置失败:", e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -121,7 +128,7 @@ const saveConfig = async () => {
|
||||
}
|
||||
});
|
||||
} catch (e) {
|
||||
console.error("Failed to save config:", e);
|
||||
console.error("保存配置失败:", e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -147,7 +154,7 @@ const loadHistory = async () => {
|
||||
const history = await invoke<Record<string, string[]>>('load_history');
|
||||
historyMap.value = history || {};
|
||||
} catch (e) {
|
||||
console.error("Failed to load history", e);
|
||||
console.error("加载历史记录失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -214,7 +221,7 @@ const handleRename = async () => {
|
||||
historyMap.value = newMap;
|
||||
updateHistoryList();
|
||||
} catch (e) {
|
||||
console.error("History save failed", e);
|
||||
console.error("保存历史记录失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -504,7 +511,7 @@ watch(currentDir, (newPath) => {
|
||||
</div>
|
||||
</el-aside>
|
||||
|
||||
<el-main>
|
||||
<el-main :class="{ 'review-active': activeMenu === 'review' }">
|
||||
<!-- Preparation Page -->
|
||||
<div v-if="activeMenu === 'preparation'">
|
||||
|
||||
@@ -575,7 +582,7 @@ watch(currentDir, (newPath) => {
|
||||
</div>
|
||||
|
||||
<!-- Review Page -->
|
||||
<div v-else-if="activeMenu === 'review'">
|
||||
<div v-else-if="activeMenu === 'review'" style="display: flex; flex-direction: column; height: 100%; overflow: hidden;">
|
||||
|
||||
<el-alert
|
||||
v-if="isReviewDisabled"
|
||||
@@ -586,7 +593,7 @@ watch(currentDir, (newPath) => {
|
||||
style="margin-bottom: 20px"
|
||||
/>
|
||||
|
||||
<div :class="{ 'disabled-area': isReviewDisabled }">
|
||||
<div :class="{ 'disabled-area': isReviewDisabled }" style="display: flex; flex-direction: column; flex: 1; overflow: hidden;">
|
||||
<!-- Drag Area -->
|
||||
<div class="drag-area">
|
||||
<el-icon class="el-icon--upload"><upload-filled /></el-icon>
|
||||
@@ -602,18 +609,19 @@ watch(currentDir, (newPath) => {
|
||||
|
||||
<!-- Action Area -->
|
||||
<div class="action-area">
|
||||
<el-input v-model="videoNameInput" placeholder="输入视频名称 (例如: 文本)" class="name-input">
|
||||
<el-input v-model="videoNameInput" placeholder="视频名称" class="name-input" @keyup.enter="handleRename">
|
||||
<template #prepend>{{ videoNamePrefix }}</template>
|
||||
</el-input>
|
||||
<el-button type="primary" @click="handleRename" :disabled="isReviewDisabled || importedFiles.length === 0">命名</el-button>
|
||||
<el-button @click="videoNameInput = ''" class="clear-button-margin-fix">清空</el-button>
|
||||
</div>
|
||||
|
||||
<!-- History List -->
|
||||
<div class="history-area" v-if="historyList.length > 0">
|
||||
<div class="history-area" v-if="historyList.length > 0" style="display: flex; flex-direction: column; flex: 1; overflow: hidden; margin-bottom: 0px;">
|
||||
<h4>历史记录 ({{ currentHistoryKey || '未关联目录' }})</h4>
|
||||
<el-scrollbar max-height="300px">
|
||||
<el-scrollbar style="flex: 1" class="history-scrollbar">
|
||||
<ul class="history-list">
|
||||
<li v-for="item in historyList" :key="item" @click="useHistoryItem(item)">
|
||||
<li v-for="item in filteredHistoryList" :key="item" @click="useHistoryItem(item)">
|
||||
<span class="history-text">{{ item }}</span>
|
||||
<el-icon class="delete-icon" @click.stop="deleteHistoryItem(item)"><Delete /></el-icon>
|
||||
</li>
|
||||
@@ -760,6 +768,7 @@ body {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.history-area h4 {
|
||||
margin-top: 0;
|
||||
margin-bottom: 10px;
|
||||
color: var(--el-text-color-primary);
|
||||
}
|
||||
@@ -767,6 +776,8 @@ body {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
.history-scrollbar {
|
||||
border: 1px solid var(--el-border-color);
|
||||
border-radius: 4px;
|
||||
}
|
||||
@@ -841,4 +852,10 @@ body {
|
||||
text-align: center;
|
||||
margin-top: 20px;
|
||||
}
|
||||
.el-main.review-active {
|
||||
padding: 20px;
|
||||
}
|
||||
.action-area .clear-button-margin-fix {
|
||||
margin-left: 0; /* Adjust this value as needed to fine-tune the gap */
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user