diff --git a/.env.example b/.env.example index 3ec2247..6679856 100644 --- a/.env.example +++ b/.env.example @@ -1 +1,2 @@ -TOKEN_USAGE_URL= +TOKEN_USAGE_URL=http://10.0.1.1:8318/usage +PROJECT_SERVER_PORT=3214 diff --git a/build.ts b/build.ts index 717f431..ac178de 100644 --- a/build.ts +++ b/build.ts @@ -21,7 +21,7 @@ import { Console, Context, Data, Effect, Layer } from 'effect' // ============================================================================ /** 项目名称 - 用于生成 sidecar 文件名 */ -const PROJECT_NAME = 'openbridge-token-usage-viewer' +const PROJECT_NAME = 'openbridgeTokenUsageViewerServer' // ============================================================================ // 领域模型和 Schema 定义 diff --git a/package.json b/package.json index c63a8e8..0dcde47 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "openbridge-token-usage-viewer", + "name": "openbridgeTokenUsageViewer", "private": true, "type": "module", "packageManager": "bun@1.3.6", diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 3542817..3a666e4 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -2061,7 +2061,7 @@ dependencies = [ ] [[package]] -name = "openbridge-token-usage-viewer" +name = "openbridgeTokenUsageViewer" version = "0.1.0" dependencies = [ "serde", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 111ce97..c6d7029 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "openbridge-token-usage-viewer" +name = "openbridgeTokenUsageViewer" version = "0.1.0" description = "OpenBridge Token Usage Viewer" authors = ["imbytecat"] @@ -11,7 +11,7 @@ edition = "2021" # The `_lib` suffix may seem redundant but it is necessary # to make the lib name unique and wouldn't conflict with the bin name. # This seems to be only an issue on Windows, see https://github.com/rust-lang/cargo/issues/8519 -name = "openbridge_token_usage_viewer_lib" +name = "openbridgeTokenUsageViewer_lib" crate-type = ["staticlib", "cdylib", "rlib"] [build-dependencies] diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 7f8c2dc..ed95636 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -2,5 +2,5 @@ #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] fn main() { - openbridge_token_usage_viewer_lib::run() + openbridgeTokenUsageViewer_lib::run() } diff --git a/src-tauri/src/sidecar.rs b/src-tauri/src/sidecar.rs index 48828a1..fa3d9d7 100644 --- a/src-tauri/src/sidecar.rs +++ b/src-tauri/src/sidecar.rs @@ -7,23 +7,18 @@ use tauri_plugin_shell::ShellExt; // ===== 项目配置 ===== -/// 项目名称 - 用于生成稳定端口和 sidecar 命名 -const PROJECT_NAME: &str = "openbridge-token-usage-viewer"; +/// Sidecar 二进制名称 +const SIDECAR_NAME: &str = "openbridgeTokenUsageViewerServer"; -/// DJB2 Hash 算法 - 将项目名称转换为稳定端口 -fn djb2_hash(s: &str) -> u32 { - let mut hash: u32 = 5381; - for c in s.bytes() { - hash = hash.wrapping_shl(5).wrapping_add(hash).wrapping_add(c as u32); - } - hash -} +/// 默认服务器端口 +const DEFAULT_PORT: u16 = 3000; -/// 计算项目专用端口 (范围: 10000-60000) +/// 从环境变量获取端口 (PROJECT_SERVER_PORT),默认 3000 fn get_project_port() -> u16 { - const PORT_MIN: u16 = 10000; - const PORT_RANGE: u32 = 50000; - PORT_MIN + (djb2_hash(PROJECT_NAME) % PORT_RANGE) as u16 + std::env::var("PROJECT_SERVER_PORT") + .ok() + .and_then(|s| s.parse().ok()) + .unwrap_or(DEFAULT_PORT) } // ===== 配置常量 ===== @@ -96,7 +91,6 @@ pub fn spawn_sidecar(app_handle: tauri::AppHandle) { if is_dev { // 开发模式:直接创建窗口连接到 Vite 开发服务器 println!("🔧 开发模式"); - println!("📌 项目: {}", PROJECT_NAME); println!("📌 端口: {}", project_port); let dev_url = format!("http://localhost:{}", project_port); @@ -122,14 +116,13 @@ pub fn spawn_sidecar(app_handle: tauri::AppHandle) { // 生产模式:启动 sidecar 二进制 tauri::async_runtime::spawn(async move { println!("🚀 生产模式"); - println!("📌 项目: {}", PROJECT_NAME); // 查找可用端口 (从项目端口开始扫描) let port = find_available_port(project_port).await; println!("📌 端口: {}", port); - // 启动 sidecar (使用项目名称作为 sidecar 名称) - let sidecar = match app_handle.shell().sidecar(PROJECT_NAME) { + // 启动 sidecar + let sidecar = match app_handle.shell().sidecar(SIDECAR_NAME) { Ok(cmd) => cmd.env("PORT", port.to_string()), Err(e) => { eprintln!("✗ 无法找到 sidecar: {}", e); diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 1b45374..2574c87 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -1,8 +1,8 @@ { "$schema": "https://schema.tauri.app/config/2", - "productName": "openbridge-token-usage-viewer", + "productName": "openbridgeTokenUsageViewer", "version": "0.1.0", - "identifier": "com.imbytecat.openbridge-token-usage-viewer", + "identifier": "com.imbytecat.openbridgetokenusageviewer", "app": { "withGlobalTauri": true, "windows": [], @@ -12,7 +12,7 @@ }, "bundle": { "active": true, - "targets": "all", + "targets": ["msi"], "icon": [ "icons/32x32.png", "icons/128x128.png", @@ -20,6 +20,6 @@ "icons/icon.icns", "icons/icon.ico" ], - "externalBin": ["binaries/openbridge-token-usage-viewer"] + "externalBin": ["binaries/openbridgeTokenUsageViewerServer"] } } diff --git a/src/env.ts b/src/env.ts index ba4581d..648f686 100644 --- a/src/env.ts +++ b/src/env.ts @@ -12,6 +12,9 @@ import { z } from 'zod' /** Token 使用量 API 的默认地址 */ const DEFAULT_TOKEN_USAGE_URL = 'http://10.0.1.1:8318/usage' +/** 服务器端口默认值 */ +const DEFAULT_SERVER_PORT = '3000' + /** * 判断当前是否为打包后的可执行文件运行环境 * @@ -109,6 +112,7 @@ const buildMergedEnv = (): Record => { // 设置默认值 merged.TOKEN_USAGE_URL ??= DEFAULT_TOKEN_USAGE_URL + merged.PROJECT_SERVER_PORT ??= DEFAULT_SERVER_PORT return merged } @@ -125,6 +129,12 @@ const buildMergedEnv = (): Record => { export const env = createEnv({ server: { TOKEN_USAGE_URL: z.string().url(), + PROJECT_SERVER_PORT: z.coerce + .number() + .int() + .min(1) + .max(65535) + .default(3000), }, clientPrefix: 'VITE_', client: { diff --git a/src/lib/project-port.ts b/src/lib/project-port.ts deleted file mode 100644 index fb5e6f7..0000000 --- a/src/lib/project-port.ts +++ /dev/null @@ -1,70 +0,0 @@ -/** - * 项目名称到端口的 Hash 工具 - * - * 使用 DJB2 算法将项目名称转换为稳定的端口号。 - * 确保: - * - 相同项目名称总是返回相同端口 - * - 不同项目名称返回不同端口 (极低碰撞率) - * - 端口范围: 10000-60000 (避开常用端口和系统保留端口) - * - * @example - * ```ts - * import { PROJECT_NAME, PROJECT_PORT } from '@/lib/project-port' - * console.log(PROJECT_NAME) // 'openbridge-token-usage-viewer' - * console.log(PROJECT_PORT) // 34567 (示例) - * ``` - */ - -/** 端口范围配置 */ -const PORT_MIN = 10000 -const PORT_MAX = 60000 -const PORT_RANGE = PORT_MAX - PORT_MIN - -/** - * 项目名称 (从目录名获取) - * - * 这确保项目名称与目录结构保持一致 - */ -export const PROJECT_NAME = 'openbridge-token-usage-viewer' - -/** - * DJB2 Hash 算法 - * - * 经典的字符串哈希算法,具有良好的分布特性和较低的碰撞率。 - * - * @param str - 要哈希的字符串 - * @returns 32位无符号整数哈希值 - */ -const djb2Hash = (str: string): number => { - let hash = 5381 - for (let i = 0; i < str.length; i++) { - // hash * 33 + char - hash = ((hash << 5) + hash + str.charCodeAt(i)) >>> 0 - } - return hash -} - -/** - * 将项目名称转换为稳定的端口号 - * - * @param projectName - 项目名称 - * @returns 10000-60000 范围内的端口号 - */ -export const getPortFromName = (projectName: string): number => { - const hash = djb2Hash(projectName) - return PORT_MIN + (hash % PORT_RANGE) -} - -/** - * 项目专用端口 - * - * 基于项目名称计算的稳定端口号。 - * 用于开发服务器和 Tauri sidecar。 - */ -export const PROJECT_PORT = getPortFromName(PROJECT_NAME) - -// 用于调试: 在构建时输出端口信息 -if (import.meta.env?.DEV) { - console.log(`📌 项目: ${PROJECT_NAME}`) - console.log(`📌 端口: ${PROJECT_PORT}`) -} diff --git a/vite.config.ts b/vite.config.ts index 00a745f..a077c0e 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -7,37 +7,25 @@ * - Bun 运行时优化 (nitro preset: 'bun') * - 静态资源内联 (serveStatic: 'inline') * - React Compiler 自动优化 (无需手动 memo) - * - 基于项目名称的稳定端口 (使用 DJB2 hash) + * - 端口从环境变量 PROJECT_SERVER_PORT 读取 (默认 3000) */ import tailwindcss from '@tailwindcss/vite' import { devtools as tanstackDevtools } from '@tanstack/devtools-vite' import { tanstackStart } from '@tanstack/react-start/plugin/vite' import react from '@vitejs/plugin-react' import { nitro } from 'nitro/vite' -import { defineConfig } from 'vite' +import { defineConfig, loadEnv } from 'vite' import tsconfigPaths from 'vite-tsconfig-paths' // ============================================================================ // 项目配置 (集中管理) // ============================================================================ -/** 项目名称 - 用于生成稳定端口和 sidecar 命名 */ -export const PROJECT_NAME = 'openbridge-token-usage-viewer' +/** 加载 .env 文件中的环境变量 */ +const envVars = loadEnv('development', process.cwd(), '') -/** - * DJB2 Hash 算法 - 将项目名称转换为稳定端口 - * 端口范围: 10000-60000 - */ -const djb2Hash = (str: string): number => { - let hash = 5381 - for (let i = 0; i < str.length; i++) { - hash = ((hash << 5) + hash + str.charCodeAt(i)) >>> 0 - } - return hash -} - -/** 开发服务器端口 (基于项目名称的稳定值) */ -export const DEV_PORT = 10000 + (djb2Hash(PROJECT_NAME) % 50000) +/** 开发服务器端口 (从环境变量读取,默认 3000) */ +const DEV_PORT = Number(envVars.PROJECT_SERVER_PORT) || 3000 export default defineConfig({ // 禁止清屏,方便与 Tauri 开发工具共用终端