175 lines
4.9 KiB
Rust

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<dyn std::error::Error>> {
// 获取应用数据目录
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<Vec<Anniversary>, 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<Vec<_>, _> = anniversaries.collect();
result.map_err(|e| e.to_string())
}
#[tauri::command]
async fn get_anniversary_by_id(
app_handle: tauri::AppHandle,
id: i32,
) -> Result<Anniversary, 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 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");
}