From 4ff83492f1aeeb94174285d0e95be9c8fc9be885 Mon Sep 17 00:00:00 2001 From: lychang <632945494@qq.com> Date: Wed, 25 Mar 2026 14:50:50 +0800 Subject: [PATCH] update code level --- assets/js/app.js | 6 - src/database.rs | 405 +++++++++++++++++++++-------------------------- src/models.rs | 4 +- 3 files changed, 180 insertions(+), 235 deletions(-) diff --git a/assets/js/app.js b/assets/js/app.js index 2cd9884..7389d27 100644 --- a/assets/js/app.js +++ b/assets/js/app.js @@ -995,12 +995,6 @@ function removeFavoriteFromPreview(favoriteId) { } } -// 排序收藏夹 -function sortFavorites(mode) { - // 这里可以实现排序功能 - alert('排序功能开发中...'); -} - // 从收藏夹移除图片 function removeFavorite(event, favoriteId) { event.stopPropagation(); // 阻止事件冒泡 diff --git a/src/database.rs b/src/database.rs index 1ceaa1c..ea610f1 100644 --- a/src/database.rs +++ b/src/database.rs @@ -1,9 +1,7 @@ -use sqlx::{SqlitePool, sqlite::SqlitePoolOptions, Row, Error as SqlxError}; +use sqlx::{SqlitePool, sqlite::SqlitePoolOptions, Row}; use crate::config::Config; use crate::models::*; use uuid::Uuid; -use std::time::Duration; -use tokio::time::sleep; pub struct Database { pub pool: SqlitePool, @@ -61,102 +59,55 @@ impl Database { Ok(db) } - - /// 带重试机制的数据库操作执行器 - async fn execute_with_retry(&self, operation: F, operation_name: &str) -> Result - where - F: Fn() -> std::pin::Pin> + Send>>, - { - const MAX_RETRIES: u32 = 3; - const BASE_DELAY_MS: u64 = 100; - - for attempt in 0..=MAX_RETRIES { - match operation().await { - Ok(result) => return Ok(result), - Err(e) => { - // 检查是否是死锁或超时错误 - if self.is_retryable_error(&e) && attempt < MAX_RETRIES { - let delay_ms = BASE_DELAY_MS * 2u64.pow(attempt); - eprintln!("⚠️ {} 操作失败 (尝试 {}): {}, 等待 {}ms 后重试", - operation_name, attempt + 1, e, delay_ms); - sleep(Duration::from_millis(delay_ms)).await; - } else { - eprintln!("❌ {} 操作失败 (尝试 {}): {}", operation_name, attempt + 1, e); - return Err(e); - } - } - } - } - - unreachable!() - } - - /// 判断错误是否可重试 - fn is_retryable_error(&self, error: &SqlxError) -> bool { - match error { - SqlxError::Database(db_err) => { - // SQLite 死锁错误码 - if let Some(code) = db_err.code() { - code == "5" || // SQLITE_BUSY - code == "6" || // SQLITE_LOCKED - code == "261" // SQLITE_BUSY_SNAPSHOT - } else { - false - } - } - SqlxError::PoolTimedOut => true, - _ => false, - } - } - pub async fn get_albums(&self, page: Option, limit: Option) -> Result, sqlx::Error> { - let page = page.unwrap_or(1); - let limit = limit.unwrap_or(50); // 减少默认加载数量,提高响应速度 - let offset = (page - 1) * limit; - - let albums = sqlx::query( - r#" - SELECT - id, - title, - document, - description, - cover_image_id, - image_count, - created_at - FROM albums - ORDER BY created_at DESC - LIMIT ? OFFSET ? - "# - ) - .bind(limit as i64) - .bind(offset as i64) - .fetch_all(&self.pool) - .await?; - - let mut result = Vec::new(); - for row in albums { - let id_str = row.get::("id"); - let id = match Uuid::parse_str(&id_str) { - Ok(uuid) => uuid, - Err(e) => { - eprintln!("无效的UUID格式: {} - 错误: {}", id_str, e); - continue; // 跳过无效的记录 - } - }; - - result.push(AlbumInfo { - id, - title: row.get("title"), - document: row.get("document"), - description: row.get("description"), - cover_image_id: row.get("cover_image_id"), - image_count: row.get("image_count"), - created_at: row.get::("created_at"), - }); - } - - Ok(result) - } + // pub async fn get_albums(&self, page: Option, limit: Option) -> Result, sqlx::Error> { + // let page = page.unwrap_or(1); + // let limit = limit.unwrap_or(50); // 减少默认加载数量,提高响应速度 + // let offset = (page - 1) * limit; + // + // let albums = sqlx::query( + // r#" + // SELECT + // id, + // title, + // document, + // description, + // cover_image_id, + // image_count, + // created_at + // FROM albums + // ORDER BY created_at DESC + // LIMIT ? OFFSET ? + // "# + // ) + // .bind(limit as i64) + // .bind(offset as i64) + // .fetch_all(&self.pool) + // .await?; + // + // let mut result = Vec::new(); + // for row in albums { + // let id_str = row.get::("id"); + // let id = match Uuid::parse_str(&id_str) { + // Ok(uuid) => uuid, + // Err(e) => { + // eprintln!("无效的UUID格式: {} - 错误: {}", id_str, e); + // continue; // 跳过无效的记录 + // } + // }; + // + // result.push(AlbumInfo { + // id, + // title: row.get("title"), + // document: row.get("document"), + // description: row.get("description"), + // cover_image_id: row.get("cover_image_id"), + // image_count: row.get("image_count"), + // created_at: row.get::("created_at"), + // }); + // } + // + // Ok(result) + // } // 相册操作 pub async fn get_all_albums(&self) -> Result, sqlx::Error> { @@ -202,58 +153,58 @@ impl Database { Ok(result) } - pub async fn search_albums(&self, query: &str, page: Option, limit: Option) -> Result, sqlx::Error> { - let search_pattern = format!("%{}%", query); - let page = page.unwrap_or(1); - let limit = limit.unwrap_or(50); // 减少默认加载数量,提高响应速度 - let offset = (page - 1) * limit; - - let albums = sqlx::query( - r#" - SELECT - id, - title, - document, - description, - cover_image_id, - image_count, - created_at - FROM albums - WHERE title LIKE ? - ORDER BY created_at DESC - LIMIT ? OFFSET ? - "# - ) - .bind(&search_pattern) - .bind(limit as i64) - .bind(offset as i64) - .fetch_all(&self.pool) - .await?; - - let mut result = Vec::new(); - for row in albums { - let id_str = row.get::("id"); - let id = match Uuid::parse_str(&id_str) { - Ok(uuid) => uuid, - Err(e) => { - eprintln!("无效的UUID格式: {} - 错误: {}", id_str, e); - continue; // 跳过无效的记录 - } - }; - - result.push(AlbumInfo { - id, - title: row.get("title"), - document: row.get("document"), - description: row.get("description"), - cover_image_id: row.get("cover_image_id"), - image_count: row.get("image_count"), - created_at: row.get::("created_at"), - }); - } - - Ok(result) - } + // pub async fn search_albums(&self, query: &str, page: Option, limit: Option) -> Result, sqlx::Error> { + // let search_pattern = format!("%{}%", query); + // let page = page.unwrap_or(1); + // let limit = limit.unwrap_or(50); // 减少默认加载数量,提高响应速度 + // let offset = (page - 1) * limit; + // + // let albums = sqlx::query( + // r#" + // SELECT + // id, + // title, + // document, + // description, + // cover_image_id, + // image_count, + // created_at + // FROM albums + // WHERE title LIKE ? + // ORDER BY created_at DESC + // LIMIT ? OFFSET ? + // "# + // ) + // .bind(&search_pattern) + // .bind(limit as i64) + // .bind(offset as i64) + // .fetch_all(&self.pool) + // .await?; + // + // let mut result = Vec::new(); + // for row in albums { + // let id_str = row.get::("id"); + // let id = match Uuid::parse_str(&id_str) { + // Ok(uuid) => uuid, + // Err(e) => { + // eprintln!("无效的UUID格式: {} - 错误: {}", id_str, e); + // continue; // 跳过无效的记录 + // } + // }; + // + // result.push(AlbumInfo { + // id, + // title: row.get("title"), + // document: row.get("document"), + // description: row.get("description"), + // cover_image_id: row.get("cover_image_id"), + // image_count: row.get("image_count"), + // created_at: row.get::("created_at"), + // }); + // } + // + // Ok(result) + // } pub async fn get_album_with_images(&self, album_id: Uuid) -> Result, sqlx::Error> { // 获取相册基本信息 @@ -370,50 +321,50 @@ impl Database { } // 图片操作 - pub async fn add_image(&self, image: CreateImage) -> Result { - let id = Uuid::new_v4(); - let now = chrono::Utc::now().to_rfc3339(); - - sqlx::query( - "INSERT INTO images (id, album_id, filename, original_url, title, description, file_size, width, height, mime_type, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)" - ) - .bind(id.to_string()) - .bind(image.album_id.to_string()) - .bind(image.filename) - .bind(image.original_url) - .bind(image.title) - .bind(image.description) - .bind(image.file_size) - .bind(image.width) - .bind(image.height) - .bind(image.mime_type) - .bind(&now) - .execute(&self.pool) - .await?; - - // 更新相册的图片数量 - self.update_album_image_count(image.album_id).await?; - - // 如果这是相册的第一张图片,设置为封面 - let image_count = sqlx::query_scalar::<_, i64>( - "SELECT COUNT(*) FROM images WHERE album_id = ?" - ) - .bind(image.album_id.to_string()) - .fetch_one(&self.pool) - .await?; - - if image_count == 1 { - sqlx::query( - "UPDATE albums SET cover_image_id = ? WHERE id = ?" - ) - .bind(id.to_string()) - .bind(image.album_id.to_string()) - .execute(&self.pool) - .await?; - } - - Ok(id) - } + // pub async fn add_image(&self, image: CreateImage) -> Result { + // let id = Uuid::new_v4(); + // let now = chrono::Utc::now().to_rfc3339(); + // + // sqlx::query( + // "INSERT INTO images (id, album_id, filename, original_url, title, description, file_size, width, height, mime_type, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)" + // ) + // .bind(id.to_string()) + // .bind(image.album_id.to_string()) + // .bind(image.filename) + // .bind(image.original_url) + // .bind(image.title) + // .bind(image.description) + // .bind(image.file_size) + // .bind(image.width) + // .bind(image.height) + // .bind(image.mime_type) + // .bind(&now) + // .execute(&self.pool) + // .await?; + // + // // 更新相册的图片数量 + // self.update_album_image_count(image.album_id).await?; + // + // // 如果这是相册的第一张图片,设置为封面 + // let image_count = sqlx::query_scalar::<_, i64>( + // "SELECT COUNT(*) FROM images WHERE album_id = ?" + // ) + // .bind(image.album_id.to_string()) + // .fetch_one(&self.pool) + // .await?; + // + // if image_count == 1 { + // sqlx::query( + // "UPDATE albums SET cover_image_id = ? WHERE id = ?" + // ) + // .bind(id.to_string()) + // .bind(image.album_id.to_string()) + // .execute(&self.pool) + // .await?; + // } + // + // Ok(id) + // } /// 更新相册的图片数量 pub async fn update_album_image_count(&self, album_id: Uuid) -> Result<(), sqlx::Error> { @@ -569,38 +520,38 @@ impl Database { Ok(()) } - pub async fn delete_image(&self, image_id: Uuid) -> Result { - // 先获取图片所属的相册ID - let album_id_result = sqlx::query_scalar::<_, String>( - r#" - SELECT album_id FROM images WHERE id = ? - "# - ) - .bind(image_id.to_string()) - .fetch_optional(&self.pool) - .await?; - - let result = sqlx::query( - r#" - DELETE FROM images - WHERE id = ? - "# - ) - .bind(image_id.to_string()) - .execute(&self.pool) - .await?; - - // 如果删除成功且找到了相册ID,更新相册图片数量 - if result.rows_affected() > 0 { - if let Some(album_id_str) = album_id_result { - if let Ok(album_id) = Uuid::parse_str(&album_id_str) { - self.update_album_image_count(album_id).await?; - } - } - } - - Ok(result.rows_affected() > 0) - } + // pub async fn delete_image(&self, image_id: Uuid) -> Result { + // // 先获取图片所属的相册ID + // let album_id_result = sqlx::query_scalar::<_, String>( + // r#" + // SELECT album_id FROM images WHERE id = ? + // "# + // ) + // .bind(image_id.to_string()) + // .fetch_optional(&self.pool) + // .await?; + // + // let result = sqlx::query( + // r#" + // DELETE FROM images + // WHERE id = ? + // "# + // ) + // .bind(image_id.to_string()) + // .execute(&self.pool) + // .await?; + // + // // 如果删除成功且找到了相册ID,更新相册图片数量 + // if result.rows_affected() > 0 { + // if let Some(album_id_str) = album_id_result { + // if let Ok(album_id) = Uuid::parse_str(&album_id_str) { + // self.update_album_image_count(album_id).await?; + // } + // } + // } + // + // Ok(result.rows_affected() > 0) + // } pub async fn update_album_cover(&self, album_id: Uuid, cover_image_id: Option) -> Result<(), sqlx::Error> { let cover_id_str = cover_image_id.map(|id| id.to_string()); diff --git a/src/models.rs b/src/models.rs index 30ea745..aa67973 100644 --- a/src/models.rs +++ b/src/models.rs @@ -99,7 +99,7 @@ pub struct FavoriteStatus { #[derive(Debug, Clone)] pub struct AlbumsCache { pub albums: Vec, - pub search_index: std::collections::HashMap>, + pub search_index: HashMap>, pub last_updated: chrono::DateTime, } @@ -107,7 +107,7 @@ impl AlbumsCache { pub fn new() -> Self { Self { albums: Vec::new(), - search_index: std::collections::HashMap::new(), + search_index: HashMap::new(), last_updated: chrono::Utc::now(), } }