diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 83f1a70..4948553 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -17,6 +17,18 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" +[[package]] +name = "ahash" +version = "0.8.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" +dependencies = [ + "cfg-if", + "once_cell", + "version_check", + "zerocopy", +] + [[package]] name = "aho-corasick" version = "1.1.3" @@ -910,6 +922,18 @@ dependencies = [ "pin-project-lite", ] +[[package]] +name = "fallible-iterator" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649" + +[[package]] +name = "fallible-streaming-iterator" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a" + [[package]] name = "fastrand" version = "2.3.0" @@ -1394,12 +1418,30 @@ version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +dependencies = [ + "ahash", +] + [[package]] name = "hashbrown" version = "0.15.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5" +[[package]] +name = "hashlink" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ba4ff7128dee98c7dc9794b6a411377e1404dba1c97deb8d1a55297bd25d8af" +dependencies = [ + "hashbrown 0.14.5", +] + [[package]] name = "heck" version = "0.4.1" @@ -1905,6 +1947,17 @@ dependencies = [ "libc", ] +[[package]] +name = "libsqlite3-sys" +version = "0.30.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e99fb7a497b1e3339bc746195567ed8d3e24945ecd636e3619d20b9de9e9149" +dependencies = [ + "cc", + "pkg-config", + "vcpkg", +] + [[package]] name = "linux-raw-sys" version = "0.9.4" @@ -2963,6 +3016,20 @@ dependencies = [ "web-sys", ] +[[package]] +name = "rusqlite" +version = "0.32.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7753b721174eb8ff87a9a0e799e2d7bc3749323e773db92e0984debb00019d6e" +dependencies = [ + "bitflags 2.9.1", + "fallible-iterator", + "fallible-streaming-iterator", + "hashlink", + "libsqlite3-sys", + "smallvec", +] + [[package]] name = "rustc-demangle" version = "0.1.25" @@ -4259,6 +4326,12 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + [[package]] name = "version-compare" version = "0.2.0" @@ -5163,6 +5236,7 @@ name = "zuanbot" version = "0.1.0" dependencies = [ "anyhow", + "rusqlite", "serde", "serde_json", "tauri", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 082b778..4e5aa09 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -23,4 +23,5 @@ tauri-plugin-opener = "2" serde = { version = "1", features = ["derive"] } serde_json = "1" anyhow = { version = "^1.0.98" } +rusqlite = { version = "0.32", features = ["bundled"] } diff --git a/src-tauri/data.db b/src-tauri/data.db new file mode 100644 index 0000000..5fb1765 Binary files /dev/null and b/src-tauri/data.db differ diff --git a/src-tauri/src/commands/mod.rs b/src-tauri/src/commands/mod.rs index 4d8f5cb..d835fef 100644 --- a/src-tauri/src/commands/mod.rs +++ b/src-tauri/src/commands/mod.rs @@ -1,10 +1,29 @@ +use tauri::{State}; +use rusqlite::{OptionalExtension}; +use crate::database::Database; // 自己定义的含互斥锁包装 SQLite 连接的结构 + #[tauri::command] pub fn greet(name: &str) -> String { format!("Hello, {}! You've been greeted from Rust!", name) } #[tauri::command] -pub fn get_message(level: &str) -> String { - println!("level = {level}"); - "".to_string() +pub async fn get_message(state: State<'_, Database>, level: Option) -> Result { + let conn = state.connection().lock().map_err(|e| e.to_string())?; + + let mut stmt = if let Some(ref _level) = level { + conn.prepare("SELECT `text` FROM `main` WHERE LEVEL = ?1 ORDER BY RANDOM() LIMIT 1") + .map_err(|e| e.to_string())? + } else { + conn.prepare("SELECT `text` FROM `main` ORDER BY RANDOM() LIMIT 1") + .map_err(|e| e.to_string())? + }; + + let message_opt: Option = if let Some(_level) = &level { + stmt.query_row([_level], |row| row.get(0)).optional().map_err(|e| e.to_string())? + } else { + stmt.query_row([], |row| row.get(0)).optional().map_err(|e| e.to_string())? + }; + + Ok(message_opt.unwrap_or_default()) } \ No newline at end of file diff --git a/src-tauri/src/constants.rs b/src-tauri/src/constants.rs deleted file mode 100644 index f9b4271..0000000 --- a/src-tauri/src/constants.rs +++ /dev/null @@ -1 +0,0 @@ -pub const APP_NAME: &str = "ZuAnBot"; \ No newline at end of file diff --git a/src-tauri/src/database/mod.rs b/src-tauri/src/database/mod.rs new file mode 100644 index 0000000..2be90ca --- /dev/null +++ b/src-tauri/src/database/mod.rs @@ -0,0 +1,37 @@ +use rusqlite::Connection; +use std::path::PathBuf; +use std::sync::Mutex; +use anyhow::Result; +use tauri::Manager; + +pub struct Database { + conn: Mutex, +} + +impl Database { + /// 初始化数据库连接 + pub fn new(app_handle: &tauri::AppHandle) -> Result { + let db_path = get_bundled_database_path(app_handle)?; + let conn = Connection::open_with_flags( + db_path, + rusqlite::OpenFlags::SQLITE_OPEN_READ_ONLY, + )?; + + Ok(Database { conn: Mutex::from(conn) }) + } + + /// 获取数据库连接的引用 + pub fn connection(&self) -> &Mutex { + &self.conn + } +} + +/// 获取打包的数据库文件路径 +fn get_bundled_database_path(app_handle: &tauri::AppHandle) -> Result { + let resource_path = app_handle + .path() + .resolve("data.db", tauri::path::BaseDirectory::Resource)?; + + println!("Database path: {:?}", resource_path); + Ok(resource_path) +} \ No newline at end of file diff --git a/src-tauri/src/dirs/mod.rs b/src-tauri/src/dirs/mod.rs deleted file mode 100644 index e977779..0000000 --- a/src-tauri/src/dirs/mod.rs +++ /dev/null @@ -1,16 +0,0 @@ -use anyhow::Result; -use std::path::PathBuf; - -/// Get system-wide data dir. -pub fn get_global_data_dir() -> Result { - #[cfg(target_os = "macos")] - let global_data_dir = PathBuf::from("/Library/Application Support/"); - - #[cfg(target_os = "windows")] - let global_data_dir = PathBuf::from("C:\\ProgramData\\"); - - #[cfg(target_os = "linux")] - let global_data_dir = PathBuf::from("/var/lib/"); - - Ok(global_data_dir) -} \ No newline at end of file diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index b019a29..5f1dcd7 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -1,14 +1,30 @@ -use crate::commands::{greet, get_message}; +use tauri::Manager; +use crate::commands::{get_message}; +use crate::database::Database; mod commands; -mod dirs; -mod constants; +mod database; #[cfg_attr(mobile, tauri::mobile_entry_point)] pub fn run() { tauri::Builder::default() .plugin(tauri_plugin_opener::init()) - .invoke_handler(tauri::generate_handler![greet, get_message]) + .setup(|app| { + // 初始化数据库 + match Database::new(app.handle()) { + Ok(db) => { + println!("Database initialized successfully"); + // 可以将数据库实例存储到应用状态中,供后续使用 + app.manage(db); + }, + Err(e) => { + eprintln!("Failed to initialize database: {}", e); + return Err(Box::from(e)); + } + } + Ok(()) + }) + .invoke_handler(tauri::generate_handler![get_message]) .run(tauri::generate_context!()) .expect("error while running tauri application"); } diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 9415acb..5b893ef 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -30,6 +30,9 @@ "icons/128x128@2x.png", "icons/icon.icns", "icons/icon.ico" + ], + "resources": [ + "./data.db" ] } } diff --git a/src/App.tsx b/src/App.tsx index cd9253a..c9c50f3 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,4 +1,4 @@ -import React, { useState } from "react" +import React, { useEffect, useState } from "react" import { invoke } from "@tauri-apps/api/core" enum Level { @@ -6,60 +6,91 @@ enum Level { max = "max", } -function App() { - const [greetMsg, setGreetMsg] = useState("") - const [level, setLevel] = useState(Level.min) - const [dbInfo, setDbInfo] = useState("") +export default function App() { + // 文本内容状态 + const [text, setText] = useState("") + const [isLast, setIsLast] = useState(false) + const [last, setLast] = useState("") - async function getMessage() { - setGreetMsg(await invoke("get_message", { level })) + useEffect(() => { + ;(async () => { + await getMessage() + })() + }, []) + + const getMessage = async (level?: Level) => { + // 保存上一条信息 + setLast(text) + + // 获取下一条信息 + const nextMessage = await invoke("get_message", { level }) + setText(nextMessage) } - async function queryDatabase() { - try { - const result = await invoke("query_database") - setDbInfo(result as string) - } catch (error) { - setDbInfo(`Error: ${error}`) + const showLast = () => { + setIsLast(true) + setText(last) + } + + // 复制文字到剪贴板 + const copyToClipboard = () => { + if (navigator.clipboard) { + navigator.clipboard.writeText(text).then( + () => { + alert("复制成功!") + }, + () => { + alert("复制失败,请手动复制!") + } + ) + } else { + alert("当前浏览器不支持复制功能") } } - function onChange(event: React.ChangeEvent) { - const value = event.target.value as Level - setLevel(value) - } - return ( -
-

Welcome to Tauri + React

+
+
+

骂人宝典

+ +
-
- - -
-

{greetMsg}

- -
- -
-

{dbInfo}

-
+
+
+ + + +
+ + {text} + +
+ + + +
+ +
+ ⚠️ 不管怎么说骂人都是不对的,请不要主动攻击别人。 +
+
+ ) } - -export default App