Compare commits
4 Commits
268d7eed07
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
38f2f853d8 | ||
|
|
b914adba74 | ||
|
|
920c7fab9c | ||
|
|
b6b87e5800 |
@@ -1,9 +1,9 @@
|
|||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="zh-CN">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>Review Videos</title>
|
<title>视频审核工具</title>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<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);
|
let destination = target_parent.join(&new_folder_name);
|
||||||
|
|
||||||
if !template.exists() {
|
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
|
// Remove the check for existing destination to allow merging/overwriting
|
||||||
@@ -155,7 +155,7 @@ fn check_dir_exists(path: String) -> bool {
|
|||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
fn rename_videos(files: Vec<String>, prefix: String, base_name: String) -> Result<String, String> {
|
fn rename_videos(files: Vec<String>, prefix: String, base_name: String) -> Result<String, String> {
|
||||||
if files.is_empty() {
|
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
|
// 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 ---
|
// --- 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> {
|
fn delete_empty_dirs(path: String) -> Result<Vec<String>, String> {
|
||||||
let root_path = Path::new(&path);
|
let root_path = Path::new(&path);
|
||||||
if !root_path.exists() || !root_path.is_dir() {
|
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();
|
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> {
|
fn check_file_naming(path: String, prefix: String) -> Result<Vec<String>, String> {
|
||||||
let root_path = Path::new(&path);
|
let root_path = Path::new(&path);
|
||||||
if !root_path.exists() || !root_path.is_dir() {
|
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();
|
let mut mismatches = Vec::new();
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
"app": {
|
"app": {
|
||||||
"windows": [
|
"windows": [
|
||||||
{
|
{
|
||||||
"title": "review-videos",
|
"title": "视频审核工具",
|
||||||
"width": 1200,
|
"width": 1200,
|
||||||
"height": 840
|
"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 historyMap = ref<Record<string, string[]>>({});
|
||||||
const currentHistoryKey = ref("");
|
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
|
// Check Data
|
||||||
const checkLogs = ref<string[]>([]);
|
const checkLogs = ref<string[]>([]);
|
||||||
const logContainerRef = ref<HTMLElement | null>(null);
|
const logContainerRef = ref<HTMLElement | null>(null);
|
||||||
@@ -108,7 +115,7 @@ const loadConfig = async () => {
|
|||||||
if (config.working_dir) workingDir.value = config.working_dir;
|
if (config.working_dir) workingDir.value = config.working_dir;
|
||||||
if (config.template_dir) templateDir.value = config.template_dir;
|
if (config.template_dir) templateDir.value = config.template_dir;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error("Failed to load config:", e);
|
console.error("加载配置失败:", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,7 +128,7 @@ const saveConfig = async () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
} catch (e) {
|
} 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');
|
const history = await invoke<Record<string, string[]>>('load_history');
|
||||||
historyMap.value = history || {};
|
historyMap.value = history || {};
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error("Failed to load history", e);
|
console.error("加载历史记录失败", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -214,7 +221,7 @@ const handleRename = async () => {
|
|||||||
historyMap.value = newMap;
|
historyMap.value = newMap;
|
||||||
updateHistoryList();
|
updateHistoryList();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error("History save failed", e);
|
console.error("保存历史记录失败", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -504,7 +511,7 @@ watch(currentDir, (newPath) => {
|
|||||||
</div>
|
</div>
|
||||||
</el-aside>
|
</el-aside>
|
||||||
|
|
||||||
<el-main>
|
<el-main :class="{ 'review-active': activeMenu === 'review' }">
|
||||||
<!-- Preparation Page -->
|
<!-- Preparation Page -->
|
||||||
<div v-if="activeMenu === 'preparation'">
|
<div v-if="activeMenu === 'preparation'">
|
||||||
|
|
||||||
@@ -575,7 +582,7 @@ watch(currentDir, (newPath) => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Review Page -->
|
<!-- 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
|
<el-alert
|
||||||
v-if="isReviewDisabled"
|
v-if="isReviewDisabled"
|
||||||
@@ -586,7 +593,7 @@ watch(currentDir, (newPath) => {
|
|||||||
style="margin-bottom: 20px"
|
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 -->
|
<!-- Drag Area -->
|
||||||
<div class="drag-area">
|
<div class="drag-area">
|
||||||
<el-icon class="el-icon--upload"><upload-filled /></el-icon>
|
<el-icon class="el-icon--upload"><upload-filled /></el-icon>
|
||||||
@@ -602,18 +609,19 @@ watch(currentDir, (newPath) => {
|
|||||||
|
|
||||||
<!-- Action Area -->
|
<!-- Action Area -->
|
||||||
<div class="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>
|
<template #prepend>{{ videoNamePrefix }}</template>
|
||||||
</el-input>
|
</el-input>
|
||||||
<el-button type="primary" @click="handleRename" :disabled="isReviewDisabled || importedFiles.length === 0">命名</el-button>
|
<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>
|
</div>
|
||||||
|
|
||||||
<!-- History List -->
|
<!-- 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>
|
<h4>历史记录 ({{ currentHistoryKey || '未关联目录' }})</h4>
|
||||||
<el-scrollbar max-height="300px">
|
<el-scrollbar style="flex: 1" class="history-scrollbar">
|
||||||
<ul class="history-list">
|
<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>
|
<span class="history-text">{{ item }}</span>
|
||||||
<el-icon class="delete-icon" @click.stop="deleteHistoryItem(item)"><Delete /></el-icon>
|
<el-icon class="delete-icon" @click.stop="deleteHistoryItem(item)"><Delete /></el-icon>
|
||||||
</li>
|
</li>
|
||||||
@@ -760,6 +768,7 @@ body {
|
|||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
}
|
}
|
||||||
.history-area h4 {
|
.history-area h4 {
|
||||||
|
margin-top: 0;
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
color: var(--el-text-color-primary);
|
color: var(--el-text-color-primary);
|
||||||
}
|
}
|
||||||
@@ -767,6 +776,8 @@ body {
|
|||||||
list-style: none;
|
list-style: none;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
}
|
||||||
|
.history-scrollbar {
|
||||||
border: 1px solid var(--el-border-color);
|
border: 1px solid var(--el-border-color);
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
}
|
}
|
||||||
@@ -841,4 +852,10 @@ body {
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
margin-top: 20px;
|
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>
|
</style>
|
||||||
Reference in New Issue
Block a user