mirror of
https://github.com/JefferyHcool/BiliNote.git
synced 2026-07-07 23:51:21 +08:00
chore:打包测试
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -320,4 +320,5 @@ cython_debug/
|
|||||||
/backend/uploads/*
|
/backend/uploads/*
|
||||||
/backend/.idea/*
|
/backend/.idea/*
|
||||||
/backend/config/*
|
/backend/config/*
|
||||||
/BiliNote_frontend/.idea/*
|
/BiliNote_frontend/.idea/*
|
||||||
|
/BiliNote_frontend/src-tauri/bin/
|
||||||
1
BillNote_frontend/.gitignore
vendored
1
BillNote_frontend/.gitignore
vendored
@@ -23,3 +23,4 @@ dist-ssr
|
|||||||
*.sln
|
*.sln
|
||||||
*.sw?
|
*.sw?
|
||||||
/pnpm-lock.yaml
|
/pnpm-lock.yaml
|
||||||
|
/src-tauri/bin/
|
||||||
|
|||||||
4
BillNote_frontend/src-tauri/.gitignore
vendored
Normal file
4
BillNote_frontend/src-tauri/.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
# Generated by Cargo
|
||||||
|
# will have compiled files and executables
|
||||||
|
/target/
|
||||||
|
/gen/schemas
|
||||||
5027
BillNote_frontend/src-tauri/Cargo.lock
generated
Normal file
5027
BillNote_frontend/src-tauri/Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
31
BillNote_frontend/src-tauri/Cargo.toml
Normal file
31
BillNote_frontend/src-tauri/Cargo.toml
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
[package]
|
||||||
|
name = "app"
|
||||||
|
version = "0.1.0"
|
||||||
|
description = "A Tauri App"
|
||||||
|
authors = ["you"]
|
||||||
|
license = ""
|
||||||
|
repository = ""
|
||||||
|
edition = "2021"
|
||||||
|
rust-version = "1.77.2"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
name = "app_lib"
|
||||||
|
crate-type = ["staticlib", "cdylib", "rlib"]
|
||||||
|
|
||||||
|
[build-dependencies]
|
||||||
|
tauri-build = { version = "2.2.0", features = [] }
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
serde_json = "1.0"
|
||||||
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
|
log = "0.4"
|
||||||
|
tauri = { version = "2.5.0", features = ["devtools"] }
|
||||||
|
tauri-plugin-log = "2.0.0-rc"
|
||||||
|
tauri-plugin-shell = "2"
|
||||||
|
|
||||||
|
[package.metadata.tauri.bundle.macOS]
|
||||||
|
frameworks = ["bin/BiliNoteBackend/_internal/"]
|
||||||
|
|
||||||
|
|
||||||
3
BillNote_frontend/src-tauri/build.rs
Normal file
3
BillNote_frontend/src-tauri/build.rs
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
fn main() {
|
||||||
|
tauri_build::build()
|
||||||
|
}
|
||||||
19
BillNote_frontend/src-tauri/capabilities/default.json
Normal file
19
BillNote_frontend/src-tauri/capabilities/default.json
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"$schema": "../gen/schemas/desktop-schema.json",
|
||||||
|
"identifier": "default",
|
||||||
|
"description": "enables the default permissions",
|
||||||
|
"windows": ["main"],
|
||||||
|
"permissions": [
|
||||||
|
"core:default",
|
||||||
|
{
|
||||||
|
"identifier": "shell:allow-execute",
|
||||||
|
"allow": [
|
||||||
|
{
|
||||||
|
"name": "BiliNoteBackend",
|
||||||
|
"sidecar": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"shell:allow-open"
|
||||||
|
]
|
||||||
|
}
|
||||||
BIN
BillNote_frontend/src-tauri/icons/icon.ico
Normal file
BIN
BillNote_frontend/src-tauri/icons/icon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 78 KiB |
BIN
BillNote_frontend/src-tauri/icons/icon.png
Normal file
BIN
BillNote_frontend/src-tauri/icons/icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
285
BillNote_frontend/src-tauri/src/lib.rs
Normal file
285
BillNote_frontend/src-tauri/src/lib.rs
Normal file
@@ -0,0 +1,285 @@
|
|||||||
|
use tauri::{Manager, Emitter};
|
||||||
|
use tauri_plugin_shell::ShellExt;
|
||||||
|
use tauri_plugin_shell::process::CommandEvent;
|
||||||
|
use std::env;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
#[cfg_attr(mobile, tauri::mobile_entry_point)]
|
||||||
|
pub fn run() {
|
||||||
|
tauri::Builder::default()
|
||||||
|
.plugin(tauri_plugin_shell::init())
|
||||||
|
.setup(|app| {
|
||||||
|
if cfg!(debug_assertions) {
|
||||||
|
app.handle().plugin(
|
||||||
|
tauri_plugin_log::Builder::default()
|
||||||
|
.level(log::LevelFilter::Info)
|
||||||
|
.build(),
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
let exe_path = env::current_exe().expect("无法获取当前可执行文件路径");
|
||||||
|
let sidecar_dir = exe_path.parent().expect("无法获取可执行文件的父目录");
|
||||||
|
|
||||||
|
// 收集所有系统环境变量
|
||||||
|
let mut all_env_vars = HashMap::new();
|
||||||
|
for (key, value) in env::vars() {
|
||||||
|
all_env_vars.insert(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 增强 PATH 环境变量,添加常见的二进制路径
|
||||||
|
let current_path = all_env_vars.get("PATH").cloned().unwrap_or_default();
|
||||||
|
let additional_paths = get_additional_binary_paths();
|
||||||
|
let enhanced_path = enhance_path_variable(¤t_path, &additional_paths);
|
||||||
|
all_env_vars.insert("PATH".to_string(), enhanced_path);
|
||||||
|
|
||||||
|
// 打印一些关键环境变量用于调试
|
||||||
|
println!("Enhanced PATH: {}", all_env_vars.get("PATH").unwrap_or(&"Not found".to_string()));
|
||||||
|
println!("Total environment variables: {}", all_env_vars.len());
|
||||||
|
|
||||||
|
// 检查 ffmpeg 是否在 PATH 中可用
|
||||||
|
check_ffmpeg_availability();
|
||||||
|
|
||||||
|
// 启动 Python 后端侧车
|
||||||
|
let mut sidecar_command = app.shell().sidecar("BiliNoteBackend").unwrap();
|
||||||
|
|
||||||
|
// 设置所有环境变量到 sidecar
|
||||||
|
for (key, value) in &all_env_vars {
|
||||||
|
sidecar_command = sidecar_command.env(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
let (mut rx, _child) = sidecar_command
|
||||||
|
.current_dir(sidecar_dir)
|
||||||
|
.spawn()
|
||||||
|
.expect("Failed to spawn sidecar");
|
||||||
|
|
||||||
|
// 获取主窗口句柄用于发送事件
|
||||||
|
let window = app.get_webview_window("main").unwrap();
|
||||||
|
|
||||||
|
tauri::async_runtime::spawn(async move {
|
||||||
|
// 读取诸如 stdout 之类的事件
|
||||||
|
while let Some(event) = rx.recv().await {
|
||||||
|
match event {
|
||||||
|
CommandEvent::Stdout(line) => {
|
||||||
|
let output = String::from_utf8_lossy(&line);
|
||||||
|
println!("Backend stdout: {}", output);
|
||||||
|
|
||||||
|
// 发送到前端
|
||||||
|
window
|
||||||
|
.emit("backend-message", Some(format!("'{}'", output)))
|
||||||
|
.expect("failed to emit event");
|
||||||
|
}
|
||||||
|
CommandEvent::Stderr(line) => {
|
||||||
|
let error = String::from_utf8_lossy(&line);
|
||||||
|
eprintln!("Backend stderr: {}", error);
|
||||||
|
|
||||||
|
window
|
||||||
|
.emit("backend-error", Some(format!("'{}'", error)))
|
||||||
|
.expect("failed to emit event");
|
||||||
|
}
|
||||||
|
CommandEvent::Terminated(payload) => {
|
||||||
|
println!("Backend terminated with code: {:?}", payload.code);
|
||||||
|
window
|
||||||
|
.emit("backend-terminated", Some(payload.code))
|
||||||
|
.expect("failed to emit event");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
println!("Backend event: {:?}", event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
})
|
||||||
|
.invoke_handler(tauri::generate_handler![
|
||||||
|
get_system_env_vars,
|
||||||
|
find_executable_path,
|
||||||
|
run_command_with_env,
|
||||||
|
test_ffmpeg_access
|
||||||
|
])
|
||||||
|
.run(tauri::generate_context!())
|
||||||
|
.expect("error while running tauri application");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取额外的二进制路径
|
||||||
|
fn get_additional_binary_paths() -> Vec<String> {
|
||||||
|
if cfg!(target_os = "windows") {
|
||||||
|
vec![
|
||||||
|
"C:\\ffmpeg\\bin".to_string(),
|
||||||
|
"C:\\Program Files\\ffmpeg\\bin".to_string(),
|
||||||
|
"C:\\Program Files (x86)\\ffmpeg\\bin".to_string(),
|
||||||
|
"C:\\tools\\ffmpeg\\bin".to_string(),
|
||||||
|
"C:\\ProgramData\\chocolatey\\bin".to_string(),
|
||||||
|
]
|
||||||
|
} else if cfg!(target_os = "macos") {
|
||||||
|
vec![
|
||||||
|
"/usr/local/bin".to_string(),
|
||||||
|
"/opt/homebrew/bin".to_string(),
|
||||||
|
"/usr/bin".to_string(),
|
||||||
|
"/bin".to_string(),
|
||||||
|
"/opt/local/bin".to_string(), // MacPorts
|
||||||
|
]
|
||||||
|
} else {
|
||||||
|
vec![
|
||||||
|
"/usr/local/bin".to_string(),
|
||||||
|
"/usr/bin".to_string(),
|
||||||
|
"/bin".to_string(),
|
||||||
|
"/snap/bin".to_string(),
|
||||||
|
"/opt/bin".to_string(),
|
||||||
|
"/usr/local/sbin".to_string(),
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 增强 PATH 环境变量
|
||||||
|
fn enhance_path_variable(current_path: &str, additional_paths: &[String]) -> String {
|
||||||
|
let path_separator = if cfg!(target_os = "windows") { ";" } else { ":" };
|
||||||
|
|
||||||
|
let mut paths: Vec<String> = additional_paths.to_vec();
|
||||||
|
|
||||||
|
// 添加当前 PATH
|
||||||
|
if !current_path.is_empty() {
|
||||||
|
paths.push(current_path.to_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
paths.join(path_separator)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查 ffmpeg 可用性
|
||||||
|
fn check_ffmpeg_availability() {
|
||||||
|
use std::process::Command;
|
||||||
|
|
||||||
|
match Command::new("ffmpeg").arg("-version").output() {
|
||||||
|
Ok(output) => {
|
||||||
|
if output.status.success() {
|
||||||
|
println!("✓ FFmpeg is available in PATH");
|
||||||
|
let version_info = String::from_utf8_lossy(&output.stdout);
|
||||||
|
let first_line = version_info.lines().next().unwrap_or("Unknown version");
|
||||||
|
println!("FFmpeg version: {}", first_line);
|
||||||
|
} else {
|
||||||
|
println!("✗ FFmpeg found but returned error");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
println!("✗ FFmpeg not found in PATH: {}", e);
|
||||||
|
|
||||||
|
// 尝试在常见路径中查找
|
||||||
|
let common_paths = get_additional_binary_paths();
|
||||||
|
for path in common_paths {
|
||||||
|
let ffmpeg_path = if cfg!(target_os = "windows") {
|
||||||
|
format!("{}\\ffmpeg.exe", path)
|
||||||
|
} else {
|
||||||
|
format!("{}/ffmpeg", path)
|
||||||
|
};
|
||||||
|
|
||||||
|
if std::path::Path::new(&ffmpeg_path).exists() {
|
||||||
|
println!("✓ Found FFmpeg at: {}", ffmpeg_path);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
println!("✗ FFmpeg not found in common installation paths");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tauri 命令:获取系统环境变量
|
||||||
|
#[tauri::command]
|
||||||
|
fn get_system_env_vars() -> HashMap<String, String> {
|
||||||
|
env::vars().collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tauri 命令:查找可执行文件路径
|
||||||
|
#[tauri::command]
|
||||||
|
fn find_executable_path(executable_name: String) -> Option<String> {
|
||||||
|
use std::process::Command;
|
||||||
|
|
||||||
|
// 首先尝试直接执行
|
||||||
|
if Command::new(&executable_name).arg("--version").output().is_ok() {
|
||||||
|
return Some(executable_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 使用 which/where 命令查找
|
||||||
|
let which_cmd = if cfg!(target_os = "windows") { "where" } else { "which" };
|
||||||
|
|
||||||
|
if let Ok(output) = Command::new(which_cmd).arg(&executable_name).output() {
|
||||||
|
if output.status.success() {
|
||||||
|
let path = String::from_utf8_lossy(&output.stdout).trim().to_string();
|
||||||
|
if !path.is_empty() {
|
||||||
|
return Some(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 在常见路径中搜索
|
||||||
|
let common_paths = get_additional_binary_paths();
|
||||||
|
for base_path in common_paths {
|
||||||
|
let executable_path = if cfg!(target_os = "windows") {
|
||||||
|
format!("{}\\{}.exe", base_path, executable_name)
|
||||||
|
} else {
|
||||||
|
format!("{}/{}", base_path, executable_name)
|
||||||
|
};
|
||||||
|
|
||||||
|
if std::path::Path::new(&executable_path).exists() {
|
||||||
|
return Some(executable_path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tauri 命令:使用完整环境变量运行命令
|
||||||
|
#[tauri::command]
|
||||||
|
async fn run_command_with_env(
|
||||||
|
program: String,
|
||||||
|
args: Vec<String>
|
||||||
|
) -> Result<String, String> {
|
||||||
|
use std::process::Command;
|
||||||
|
|
||||||
|
let mut cmd = Command::new(&program);
|
||||||
|
cmd.args(&args);
|
||||||
|
|
||||||
|
// 设置所有环境变量
|
||||||
|
for (key, value) in env::vars() {
|
||||||
|
cmd.env(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 增强 PATH
|
||||||
|
let current_path = env::var("PATH").unwrap_or_default();
|
||||||
|
let additional_paths = get_additional_binary_paths();
|
||||||
|
let enhanced_path = enhance_path_variable(¤t_path, &additional_paths);
|
||||||
|
cmd.env("PATH", enhanced_path);
|
||||||
|
|
||||||
|
match cmd.output() {
|
||||||
|
Ok(output) => {
|
||||||
|
if output.status.success() {
|
||||||
|
Ok(String::from_utf8_lossy(&output.stdout).to_string())
|
||||||
|
} else {
|
||||||
|
Err(String::from_utf8_lossy(&output.stderr).to_string())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(e) => Err(format!("Failed to execute {}: {}", program, e))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tauri 命令:测试 ffmpeg 访问
|
||||||
|
#[tauri::command]
|
||||||
|
async fn test_ffmpeg_access() -> Result<String, String> {
|
||||||
|
run_command_with_env("ffmpeg".to_string(), vec!["-version".to_string()]).await
|
||||||
|
}
|
||||||
|
|
||||||
|
// 可选:添加一个函数来动态更新 sidecar 的环境变量
|
||||||
|
#[tauri::command]
|
||||||
|
async fn update_sidecar_environment(
|
||||||
|
app_handle: tauri::AppHandle,
|
||||||
|
additional_env_vars: HashMap<String, String>
|
||||||
|
) -> Result<(), String> {
|
||||||
|
// 这个函数可以用来在运行时更新环境变量
|
||||||
|
// 注意:这需要重启 sidecar 才能生效
|
||||||
|
|
||||||
|
for (key, value) in additional_env_vars {
|
||||||
|
env::set_var(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
6
BillNote_frontend/src-tauri/src/main.rs
Normal file
6
BillNote_frontend/src-tauri/src/main.rs
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
// Prevents additional console window on Windows in release, DO NOT REMOVE!!
|
||||||
|
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
app_lib::run();
|
||||||
|
}
|
||||||
46
BillNote_frontend/src-tauri/tauri.conf.json
Normal file
46
BillNote_frontend/src-tauri/tauri.conf.json
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
{
|
||||||
|
"$schema": "../node_modules/@tauri-apps/cli/config.schema.json",
|
||||||
|
"productName": "BiliNote",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"identifier": "com.jefferyhuang.bilinote",
|
||||||
|
"build": {
|
||||||
|
"frontendDist": "../dist",
|
||||||
|
"devUrl": "http://localhost:3015",
|
||||||
|
"beforeDevCommand": "pnpm dev",
|
||||||
|
"beforeBuildCommand": "pnpm build"
|
||||||
|
},
|
||||||
|
"app": {
|
||||||
|
"windows": [
|
||||||
|
{
|
||||||
|
"title": "BiliNote",
|
||||||
|
"width": 1400,
|
||||||
|
"height": 900,
|
||||||
|
"resizable": true,
|
||||||
|
"fullscreen": false,
|
||||||
|
"devtools": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"security": {
|
||||||
|
"csp": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"bundle": {
|
||||||
|
"externalBin": [
|
||||||
|
"bin/BiliNoteBackend/BiliNoteBackend"
|
||||||
|
],
|
||||||
|
"resources": {
|
||||||
|
"bin/BiliNoteBackend/_internal":"_internal"
|
||||||
|
},
|
||||||
|
"macOS":{
|
||||||
|
"files": {
|
||||||
|
"Frameworks": "bin/BiliNoteBackend/_internal"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"active": true,
|
||||||
|
"targets": "all",
|
||||||
|
"icon": [
|
||||||
|
"icons/icon.ico",
|
||||||
|
"icons/icon.png"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -28,7 +28,7 @@ pyinstaller \
|
|||||||
--hidden-import fastapi \
|
--hidden-import fastapi \
|
||||||
--hidden-import starlette \
|
--hidden-import starlette \
|
||||||
--add-data "app/db/builtin_providers.json:."\
|
--add-data "app/db/builtin_providers.json:."\
|
||||||
--add-data "../.env:." \
|
--add-data "../.env.env.example:.env" \
|
||||||
"$(pwd)/backend/main.py" # 确保这里没有额外的空格,并使用绝对路径
|
"$(pwd)/backend/main.py" # 确保这里没有额外的空格,并使用绝对路径
|
||||||
mv \
|
mv \
|
||||||
./BillNote_frontend/src-tauri/bin/BiliNoteBackend/BiliNoteBackend\
|
./BillNote_frontend/src-tauri/bin/BiliNoteBackend/BiliNoteBackend\
|
||||||
|
|||||||
Reference in New Issue
Block a user