From 940eeb96efd70c6b32eb6100c695730731a8ea73 Mon Sep 17 00:00:00 2001
From: "fengchuanhn@gmail.com"
Date: Mon, 25 May 2026 01:15:42 +0800
Subject: [PATCH] 11
---
src-tauri/src/audio_db.rs | 18 ++++++++++++++
src-tauri/src/commands/fs_util.rs | 19 +++++++++++++++
src-tauri/src/commands/material.rs | 39 +++++++-----------------------
src-tauri/src/material_db.rs | 31 ++++++++++++++----------
src-tauri/src/material_store.rs | 7 +++++-
src/views/MaterialView.vue | 31 +++++++++++++++++++++---
6 files changed, 98 insertions(+), 47 deletions(-)
diff --git a/src-tauri/src/audio_db.rs b/src-tauri/src/audio_db.rs
index 6ad2eff..242d51d 100644
--- a/src-tauri/src/audio_db.rs
+++ b/src-tauri/src/audio_db.rs
@@ -3,6 +3,7 @@
use std::path::PathBuf;
use std::sync::Mutex;
+use crate::commands::fs_util;
use chrono::{Datelike, Local, Timelike};
use rusqlite::{params, Connection};
use serde::Serialize;
@@ -182,16 +183,33 @@ impl AudioDb {
return Ok(());
}
let excess = count - MAX_RECORDS;
+ let mut stmt = conn.prepare(
+ "SELECT file_path FROM generated_audios ORDER BY id ASC LIMIT ?1",
+ )?;
+ let paths: Vec = stmt
+ .query_map(params![excess], |row| row.get(0))?
+ .filter_map(|r| r.ok())
+ .collect();
conn.execute(
"DELETE FROM generated_audios WHERE id IN (
SELECT id FROM generated_audios ORDER BY id ASC LIMIT ?1
)",
params![excess],
)?;
+ for path in paths {
+ if let Err(e) = fs_util::remove_allowed_local_media_file(&path) {
+ log::warn!(target: "audio", "裁剪历史时删除音频文件失败 {path}: {e}");
+ }
+ }
Ok(())
}
pub fn delete(&self, id: i64) -> Result {
+ let Some(record) = self.get(id)? else {
+ return Ok(false);
+ };
+ fs_util::remove_allowed_local_media_file(&record.file_path)
+ .map_err(AudioDbError::Message)?;
let conn = self.conn.lock().map_err(|_| {
AudioDbError::Message("语音数据库锁异常".into())
})?;
diff --git a/src-tauri/src/commands/fs_util.rs b/src-tauri/src/commands/fs_util.rs
index 525d081..e6877ac 100644
--- a/src-tauri/src/commands/fs_util.rs
+++ b/src-tauri/src/commands/fs_util.rs
@@ -26,6 +26,7 @@ fn is_allowed_local_media(path: &Path) -> bool {
|| lower.contains("aiclient-subtitle-bgm")
|| lower.contains("aiclient-cover")
|| lower.contains("aiclient-cover-previews")
+ || lower.contains("video-material")
|| lower.contains("avatars")
{
return true;
@@ -38,6 +39,24 @@ fn is_allowed_local_media(path: &Path) -> bool {
false
}
+/// 删除受信任目录下的本地媒体文件(语音/视频历史记录删除时清理磁盘)。
+pub(crate) fn remove_allowed_local_media_file(path: &str) -> Result<(), String> {
+ let normalized = normalize_path(path.trim());
+ if normalized.as_os_str().is_empty() {
+ return Ok(());
+ }
+ if !normalized.is_file() {
+ return Ok(());
+ }
+ if !is_allowed_local_media(&normalized) {
+ return Err(format!(
+ "不允许删除该路径下的文件: {}",
+ normalized.display()
+ ));
+ }
+ std::fs::remove_file(&normalized).map_err(|e| format!("删除文件失败: {e}"))
+}
+
/// 读取本地文件为 base64(用于 `
-