use chrono::{Local, NaiveDate}; use rusqlite::{Connection, Result}; use serde::Serialize; use std::fs; use tauri::Manager; fn init_database(app: &tauri::App) -> Result<(), Box> { // 获取应用数据目录 let app_dir = app.path().app_data_dir()?; // 确保目录存在 fs::create_dir_all(&app_dir)?; // 构建数据库文件路径 let db_path = app_dir.join("anniversaries.db"); // 打开数据库连接 let conn = Connection::open(db_path)?; // 创建表 conn.execute( "CREATE TABLE IF NOT EXISTS anniversaries ( id INTEGER PRIMARY KEY AUTOINCREMENT, title TEXT NOT NULL, start_date TEXT NOT NULL, created_at DATETIME DEFAULT CURRENT_TIMESTAMP )", [], )?; Ok(()) } #[derive(Serialize)] struct Anniversary { id: i32, title: String, start_date: String, days: i64, } #[tauri::command] async fn get_anniversaries(app_handle: tauri::AppHandle) -> Result, String> { // 返回主页数据 let app_dir = app_handle .path() .app_data_dir() .map_err(|e| e.to_string())?; let db_path = app_dir.join("anniversaries.db"); let conn = Connection::open(db_path).map_err(|e| e.to_string())?; let mut stmt = conn .prepare("SELECT id, title, start_date FROM anniversaries ORDER BY created_at DESC") .map_err(|e| e.to_string())?; let today = Local::now().date_naive(); let anniversaries = stmt .query_map([], |row| { let id: i32 = row.get(0)?; let title: String = row.get(1)?; let start_date: String = row.get(2)?; // 计算天数 let start = NaiveDate::parse_from_str(&start_date, "%Y-%m-%d") .map_err(|e| rusqlite::Error::InvalidParameterName(e.to_string()))?; let days = (today - start).num_days(); Ok(Anniversary { id, title, start_date, days, }) }) .map_err(|e| e.to_string())?; let result: Result, _> = anniversaries.collect(); result.map_err(|e| e.to_string()) } #[tauri::command] async fn get_anniversary_by_id( app_handle: tauri::AppHandle, id: i32, ) -> Result { // 返回详情页数据 let app_dir = app_handle .path() .app_data_dir() .map_err(|e| e.to_string())?; let db_path = app_dir.join("anniversaries.db"); let conn = Connection::open(db_path).map_err(|e| e.to_string())?; let mut stmt = conn .prepare("SELECT title, start_date FROM anniversaries WHERE id = ?") .map_err(|e| e.to_string())?; let today = Local::now().date_naive(); let result = stmt .query_row([id], |row| { let title: String = row.get(0)?; let start_date: String = row.get(1)?; // 计算天数 let start = NaiveDate::parse_from_str(&start_date, "%Y-%m-%d") .map_err(|e| rusqlite::Error::InvalidParameterName(e.to_string()))?; let days = (today - start).num_days(); Ok(Anniversary { id, title, start_date, days, }) }) .map_err(|e| e.to_string())?; Ok(result) } #[tauri::command] async fn delete_anniversary(app_handle: tauri::AppHandle, id: i64) -> Result<(), String> { // 详情页删除 let app_dir = app_handle .path() .app_data_dir() .map_err(|e| e.to_string())?; let db_path = app_dir.join("anniversaries.db"); let conn = Connection::open(db_path).map_err(|e| e.to_string())?; conn.execute("DELETE FROM anniversaries WHERE id = ?", [id]) .map_err(|e| e.to_string())?; Ok(()) } #[tauri::command] async fn add_anniversary( app_handle: tauri::AppHandle, title: String, start_date: String, ) -> Result<(), String> { // 主页添加 let app_dir = app_handle .path() .app_data_dir() .map_err(|e| e.to_string())?; let db_path = app_dir.join("anniversaries.db"); let conn = Connection::open(db_path).map_err(|e| e.to_string())?; conn.execute( "INSERT INTO anniversaries (title, start_date) VALUES (?1, ?2)", [&title, &start_date], ) .map_err(|e| e.to_string())?; Ok(()) } #[cfg_attr(mobile, tauri::mobile_entry_point)] pub fn run() { tauri::Builder::default() .plugin(tauri_plugin_opener::init()) .setup(|app| { init_database(app).expect("failed to initialize database"); Ok(()) }) .invoke_handler(tauri::generate_handler![ get_anniversaries, get_anniversary_by_id, add_anniversary, delete_anniversary, ]) .run(tauri::generate_context!()) .expect("error while running tauri application"); }