158 lines
3.9 KiB
Rust
158 lines
3.9 KiB
Rust
use serde::{Deserialize, Serialize};
|
|
use sqlx::SqlitePool;
|
|
use tauri::State;
|
|
use tauri_helper::auto_collect_command;
|
|
|
|
use crate::models::{ApiResponse, Books, Chapters, PageResult};
|
|
|
|
#[derive(Debug, Deserialize, Serialize)]
|
|
pub struct BookSaveReq {
|
|
pub id: i64,
|
|
pub title: String,
|
|
pub author: String,
|
|
pub cover: String,
|
|
pub instruction: String,
|
|
}
|
|
|
|
/**
|
|
* 导入书籍
|
|
* @param path 书籍文件路径
|
|
* @returns 导入结果
|
|
*/
|
|
#[tauri::command]
|
|
#[auto_collect_command]
|
|
pub async fn import_book(
|
|
pool: State<'_, SqlitePool>,
|
|
path: String,
|
|
) -> Result<ApiResponse<()>, String> {
|
|
let title = std::path::Path::new(&path)
|
|
.file_stem()
|
|
.and_then(|s| s.to_str())
|
|
.unwrap_or("未命名")
|
|
.to_string();
|
|
sqlx::query("INSERT INTO books (title, file_path) VALUES (?,?)")
|
|
.bind(&title)
|
|
.bind(&path)
|
|
.execute(&*pool)
|
|
.await
|
|
.map_err(|e| e.to_string())?;
|
|
Ok(ApiResponse::<()>::success_empty())
|
|
}
|
|
|
|
/**
|
|
* 获取书籍列表
|
|
*
|
|
* @param title 书籍标题模糊查询
|
|
* @returns 书籍列表
|
|
*/
|
|
#[tauri::command]
|
|
#[auto_collect_command]
|
|
pub async fn book_list(
|
|
pool: State<'_, SqlitePool>,
|
|
title: String,
|
|
) -> Result<ApiResponse<Vec<Books>>, String> {
|
|
let title = title.trim().to_string();
|
|
let books = sqlx::query_as::<_, Books>("SELECT * FROM books WHERE title LIKE ?")
|
|
.bind(format!("%{}%", title))
|
|
.fetch_all(&*pool)
|
|
.await
|
|
.map_err(|e| e.to_string())?;
|
|
Ok(ApiResponse::success(books))
|
|
}
|
|
|
|
/**
|
|
* 更新书籍
|
|
* @param id 书籍ID
|
|
* @returns 更新结果
|
|
*/
|
|
#[tauri::command]
|
|
#[auto_collect_command]
|
|
pub async fn book_edit(
|
|
pool: State<'_, SqlitePool>,
|
|
params: BookSaveReq,
|
|
) -> Result<ApiResponse<()>, String> {
|
|
sqlx::query("UPDATE books SET title = ?, author = ?, cover = ?, instruction = ? WHERE id = ?")
|
|
.bind(params.title)
|
|
.bind(params.author)
|
|
.bind(params.cover)
|
|
.bind(params.instruction)
|
|
.bind(params.id)
|
|
.execute(&*pool)
|
|
.await
|
|
.map_err(|e| e.to_string())?;
|
|
Ok(ApiResponse::<()>::success_empty())
|
|
}
|
|
|
|
/**
|
|
* 删除书籍
|
|
* @param id 书籍ID
|
|
* @returns 删除结果
|
|
*/
|
|
#[tauri::command]
|
|
#[auto_collect_command]
|
|
pub async fn book_del(pool: State<'_, SqlitePool>, id: i64) -> Result<ApiResponse<()>, String> {
|
|
sqlx::query("DELETE FROM books WHERE id = ?")
|
|
.bind(id)
|
|
.execute(&*pool)
|
|
.await
|
|
.map_err(|e| e.to_string())?;
|
|
Ok(ApiResponse::<()>::success_empty())
|
|
}
|
|
|
|
/**
|
|
* 获取书籍详情
|
|
* @param id 书籍ID
|
|
* @returns 书籍详情
|
|
*/
|
|
#[tauri::command]
|
|
#[auto_collect_command]
|
|
pub async fn book_detail(
|
|
pool: State<'_, SqlitePool>,
|
|
id: i64,
|
|
) -> Result<ApiResponse<Books>, String> {
|
|
let book = sqlx::query_as::<_, Books>("SELECT * FROM books WHERE id = ?")
|
|
.bind(id)
|
|
.fetch_one(&*pool)
|
|
.await
|
|
.map_err(|e| e.to_string())?;
|
|
Ok(ApiResponse::success(book))
|
|
}
|
|
|
|
/**
|
|
* 获取书籍章节列表
|
|
* @param book_id 书籍ID
|
|
* @param page 页码
|
|
* @param limit 每页数量
|
|
* @returns 章节列表
|
|
*/
|
|
#[tauri::command]
|
|
#[auto_collect_command]
|
|
pub async fn chapter_page(
|
|
pool: State<'_, SqlitePool>,
|
|
book_id: i64,
|
|
page: i32,
|
|
limit: i32,
|
|
) -> Result<ApiResponse<PageResult<Chapters>>, String> {
|
|
let offset = (page - 1) * limit;
|
|
let total: i64 =
|
|
sqlx::query_scalar::<_, i64>("SELECT COUNT(id) FROM chapters WHERE book_id = ?")
|
|
.bind(book_id)
|
|
.fetch_one(&*pool)
|
|
.await
|
|
.map_err(|e| e.to_string())?;
|
|
let chapters =
|
|
sqlx::query_as::<_, Chapters>("SELECT * FROM chapters WHERE book_id = ? LIMIT ?,?")
|
|
.bind(book_id)
|
|
.bind(offset)
|
|
.bind(limit)
|
|
.fetch_all(&*pool)
|
|
.await
|
|
.map_err(|e| e.to_string())?;
|
|
Ok(ApiResponse::success(PageResult {
|
|
total,
|
|
list: chapters,
|
|
page,
|
|
page_size: limit,
|
|
}))
|
|
}
|