123 lines
3.1 KiB
Rust
123 lines
3.1 KiB
Rust
//! 从应用目录 `resources/data/oem` 读取 OEM 编号。
|
|
|
|
use std::path::{Path, PathBuf};
|
|
|
|
use serde_json::Value;
|
|
use tauri::{AppHandle, Manager, path::BaseDirectory};
|
|
|
|
pub const DEFAULT_OEM_ID: i64 = 1;
|
|
|
|
/// 相对可执行文件目录的 OEM 配置路径:`resources/data/oem`。
|
|
pub const OEM_RESOURCE_RELATIVE: &[&str] = &["resources", "data", "oem"];
|
|
|
|
/// 开发时源码树中的 OEM 配置路径。
|
|
pub const OEM_DEV_RELATIVE: &str = "src-tauri/resources/data/oem";
|
|
|
|
pub fn read_oem_id_file(path: &Path) -> i64 {
|
|
let content = match std::fs::read_to_string(path) {
|
|
Ok(s) => s,
|
|
Err(_) => return DEFAULT_OEM_ID,
|
|
};
|
|
parse_oem_id_content(&content).unwrap_or(DEFAULT_OEM_ID)
|
|
}
|
|
|
|
/// 解析 OEM 配置文件路径(打包资源 → 应用目录 → 开发目录)。
|
|
pub fn resolve_oem_id_path(handle: &AppHandle) -> Option<PathBuf> {
|
|
if let Ok(path) = handle.path().resolve("data/oem", BaseDirectory::Resource) {
|
|
if path.is_file() {
|
|
return Some(path);
|
|
}
|
|
}
|
|
locate_oem_id_file()
|
|
}
|
|
|
|
/// 读取当前应用的 OEM 编号。
|
|
pub fn load_oem_id(handle: &AppHandle) -> i64 {
|
|
resolve_oem_id_path(handle)
|
|
.map(|path| read_oem_id_file(&path))
|
|
.unwrap_or(DEFAULT_OEM_ID)
|
|
}
|
|
|
|
/// 按可执行文件旁 `resources/data/oem` 或开发目录定位配置文件。
|
|
pub fn locate_oem_id_file() -> Option<PathBuf> {
|
|
if let Ok(path) = std::env::var("AICLIENT_OEM_FILE") {
|
|
let custom = PathBuf::from(path);
|
|
if custom.is_file() {
|
|
return Some(custom);
|
|
}
|
|
}
|
|
|
|
if let Ok(exe) = std::env::current_exe() {
|
|
if let Some(dir) = exe.parent() {
|
|
let bundled = dir.join(path_from_parts(OEM_RESOURCE_RELATIVE));
|
|
if bundled.is_file() {
|
|
return Some(bundled);
|
|
}
|
|
}
|
|
}
|
|
|
|
let dev = PathBuf::from(OEM_DEV_RELATIVE);
|
|
if dev.is_file() {
|
|
return Some(dev);
|
|
}
|
|
|
|
None
|
|
}
|
|
|
|
fn path_from_parts(parts: &[&str]) -> PathBuf {
|
|
let mut path = PathBuf::new();
|
|
for part in parts {
|
|
path.push(part);
|
|
}
|
|
path
|
|
}
|
|
|
|
fn parse_oem_id_content(content: &str) -> Option<i64> {
|
|
let trimmed = content.trim();
|
|
if trimmed.is_empty() {
|
|
return None;
|
|
}
|
|
|
|
if let Ok(value) = serde_json::from_str::<Value>(trimmed) {
|
|
if let Some(id) = value.get("oem_id").and_then(|v| v.as_i64()) {
|
|
if id >= 1 {
|
|
return Some(id);
|
|
}
|
|
}
|
|
if let Some(id) = value.as_i64() {
|
|
if id >= 1 {
|
|
return Some(id);
|
|
}
|
|
}
|
|
}
|
|
|
|
let first_line = trimmed.lines().next()?.trim();
|
|
let id: i64 = first_line.parse().ok()?;
|
|
if id >= 1 {
|
|
Some(id)
|
|
} else {
|
|
None
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn parse_integer_line() {
|
|
assert_eq!(parse_oem_id_content("2\n"), Some(2));
|
|
}
|
|
|
|
#[test]
|
|
fn parse_json_object() {
|
|
assert_eq!(parse_oem_id_content(r#"{"oem_id":3}"#), Some(3));
|
|
}
|
|
|
|
#[test]
|
|
fn invalid_defaults_none() {
|
|
assert_eq!(parse_oem_id_content("abc"), None);
|
|
assert_eq!(parse_oem_id_content(""), None);
|
|
}
|
|
}
|