feat(core): Implements core configuration file generation functionality

- Adds the bootArgs.ts utility module for generating and deleting configuration files
- Integrates configuration file generation and cleanup logic into spary.vue
- Integrates the tauri-plugin-fs plugin to support file system operations
- Adds a Linux system proxy configuration script
This commit is contained in:
2025-10-21 15:37:04 +08:00
parent 2b8f09b4b2
commit 462f70f35d
17 changed files with 731 additions and 56 deletions

View File

@@ -23,3 +23,4 @@ tauri-plugin-opener = "2"
serde = { version = "1", features = ["derive"] }
serde_json = "1"
tauri-plugin-sql = { version = "2", features = ["sqlite"] }
tauri-plugin-fs = "2"

View File

@@ -9,6 +9,23 @@
"core:default",
"opener:default",
"sql:default",
"sql:allow-execute"
"sql:allow-execute",
"fs:default",
{
"identifier": "fs:allow-write-text-file",
"allow": [
{
"path": "$APPCONFIG/*"
}
]
},
{
"identifier": "fs:allow-remove",
"allow": [
{
"path": "$APPCONFIG/*"
}
]
}
]
}

3
src-tauri/src/cores.rs Normal file
View File

@@ -0,0 +1,3 @@
enum Core{
XRAY(String),
}

130
src-tauri/src/exe.rs Normal file
View File

@@ -0,0 +1,130 @@
use std::io::{BufRead, BufReader};
use std::path::PathBuf;
use std::process::{Child, Command, Stdio};
use std::sync::{Arc, Mutex};
use std::thread;
pub struct Exe {
path: PathBuf,
args: Vec<String>,
child: Arc<Mutex<Option<Child>>>,
pub pid: Arc<Mutex<Option<u32>>>,
}
impl Exe {
pub fn new<P: Into<PathBuf>, S: Into<String>>(path: P, args: Vec<S>) -> Self {
Self {
path: path.into(),
args: args.into_iter().map(|s| s.into()).collect(),
child: Arc::new(Mutex::new(None)),
pid: Arc::new(Mutex::new(None)),
}
}
pub fn start<F, E, X>(
&mut self,
mut on_stdout: F,
mut on_stderr: E,
mut on_exit: X,
) -> std::io::Result<()>
where
F: FnMut(String) + Send + 'static,
E: FnMut(String) + Send + 'static,
X: FnMut(i32) + Send + 'static,
{
let mut cmd = Command::new(&self.path);
cmd.args(&self.args)
.stdout(Stdio::piped())
.stderr(Stdio::piped());
let mut child = cmd.spawn()?;
// ✅ 保存 PID
let pid = child.id();
{
*self.pid.lock().unwrap() = Some(pid);
}
// ✅ 异步读取 stdout
if let Some(out) = child.stdout.take() {
let mut reader = BufReader::new(out);
let mut line = String::new();
thread::spawn(move || {
while let Ok(n) = reader.read_line(&mut line) {
if n == 0 {
break;
}
on_stdout(line.clone());
line.clear();
}
});
}
if let Some(err) = child.stderr.take() {
let mut reader = BufReader::new(err);
let mut line = String::new();
thread::spawn(move || {
while let Ok(n) = reader.read_line(&mut line) {
if n == 0 {
break;
}
on_stderr(line.clone());
line.clear();
}
});
}
let child_arc = self.child.clone();
*child_arc.lock().unwrap() = Some(child);
let pid_clone = self.pid.clone();
thread::spawn(move || {
if let Some(mut c) = child_arc.lock().unwrap().take() {
match c.wait() {
Ok(status) => {
let code = status.code().unwrap_or(-1);
*pid_clone.lock().unwrap() = None;
on_exit(code);
}
Err(e) => {
eprintln!("Error waiting for process: {e}");
*pid_clone.lock().unwrap() = None;
on_exit(-1);
}
}
}
});
Ok(())
}
pub fn kill(&self) -> std::io::Result<()> {
let mut guard = self.child.lock().unwrap();
if let Some(child) = guard.as_mut() {
child.kill()?;
Ok(())
} else {
Err(std::io::Error::new(
std::io::ErrorKind::Other,
"No running process",
))
}
}
pub fn is_alive(&self) -> bool {
let mut guard = self.child.lock().unwrap();
if let Some(child) = guard.as_mut() {
match child.try_wait() {
Ok(Some(_)) => false, // 已退出
Ok(None) => true, // 仍在运行
Err(_) => false,
}
} else {
false
}
}
pub fn get_pid(&self) -> Option<u32> {
*self.pid.lock().unwrap()
}
}

View File

@@ -3,8 +3,10 @@
use crate::group::add_group;
use crate::spary::spary_switch;
use tauri_plugin_sql::{Migration, MigrationKind};
mod exe;
mod group;
mod spary;
mod cores;
#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
@@ -21,8 +23,15 @@ pub fn run() {
sql: "CREATE TABLE node(id INTEGER PRIMARY KEY AUTOINCREMENT, alias VARCHAR(60) NOT NULL,arguments JSON NOT NULL default '{}', created_at DATETIME DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME DEFAULT CURRENT_TIMESTAMP, group_id INTEGER NOT NULL)",
kind: MigrationKind::Up,
},
Migration{
version:3,
description:"add default group",
sql:"INSERT INTO `group`(name) VALUES('default')",
kind:MigrationKind::Up,
}
];
tauri::Builder::default()
.plugin(tauri_plugin_fs::init())
.plugin(
tauri_plugin_sql::Builder::default()
.add_migrations("sqlite:spary.db", migrations)