# occupation_confirm **Repository Path**: tausum/occupation_confirm ## Basic Information - **Project Name**: occupation_confirm - **Description**: 资源占用确认工具 - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-09-14 - **Last Updated**: 2026-09-15 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 资源占用确认(Occupation Confirm) 一个基于 Tauri 2 的桌面常驻工具,用于在自动化场景中确认某台电脑的资源是否仍被人工占用。 外部系统(如自动化测试平台、CI 任务调度器)在使用目标电脑资源前,通过 HTTP 接口发起询问;本机收到请求后会弹出置顶确认窗口,由使用者手动答复,**30 秒内无操作则自动确认“不占用”**,从而避免无人值守时任务被永久阻塞。 ## 功能特性 - **HTTP 询问接口**:内置 axum HTTP 服务(默认端口 `18721`),一个 GET 请求即可发起占用确认。 - **置顶倒计时弹窗**:收到请求后自动弹出确认窗口并置顶、聚焦,30 秒倒计时后自动答复。 - 点击「确认」→ 资源已使用完毕,**不占用**(手动确认) - 点击「再用 N 分钟」→ **占用中,N 分钟后可用**(可设置 1-60 分钟,占用人正在收尾) - 点击「继续使用」→ **占用中**(手动确认) - 倒计时结束无操作 → **不占用**(自动确认) - **智能倒计时延长**:用户开始设置"再用 N 分钟"输入框时,倒计时自动延长 30 秒,给用户足够时间操作。 - **客户端临时占用时间**:客户端发起请求时可声明预计临时占用时长(1-30 分钟,留空为长期),该信息会展示在服务端确认弹窗中并记入确认记录;支持"记住"勾选,不勾选则每次请求后恢复默认。 - **确认记录持久化**:确认记录以 JSONL 格式按天写入 `logs/confirm.<日期>.log`,包含时间、占用结果、是否自动确认、请求 IP、再用分钟数、客户端临时占用时间;合并今天与昨天日志,返回最近 50 条。 - **请求 IP 记录**:通过 TCP 连接对端地址(`ConnectInfo`)提取发起确认请求的客户端真实 IP,经反向代理时优先取 `X-Forwarded-For`,展示在记录列表中用于识别请求来源。 - **向后兼容**:老记录没有 `requestIp`、`extendMinutes` 或 `occupyMinutes` 字段时反序列化为默认值,历史数据正常展示。 - **系统托盘常驻**:启动后主窗口隐藏,仅保留托盘图标;可通过托盘菜单「查看记录」「复制占用确认页面地址」「设置」「退出应用」操作。 - **跨平台**:基于 Tauri 2,支持 Windows、macOS、Linux;附带 Windows 一键构建脚本。 ## 工作流程 ``` 外部系统 本机(本应用) │ │ │ GET /confirm/isOccupied │ 弹出置顶确认窗口(30s 倒计时) │ │ ├─ 点击「确认」 → 不占用(手动) │ │ ├─ 点击「再用N分钟」 → 占用中,N分钟后可用 │ │ ├─ 点击「继续使用」 → 占用(手动) │ │ └─ 超时无操作 → 不占用(自动) │ { data: { isOccupied, extendMinutes, ... } } │ ◄─────────────────────────────── │ 记录写入 JSONL 日志文件 ``` ## HTTP API 服务默认监听 `0.0.0.0:18721`,已开启宽松 CORS(允许跨域调用)。默认端口被占用时自动递增扫描最多 64 个端口。 ### 发起占用确认 ``` GET /confirm/isOccupied GET /confirm/isOccupied?occupyMinutes=15 ``` 请求会**同步阻塞**,直到用户点击按钮或 30 秒超时后返回结果。 **查询参数** | 参数 | 类型 | 说明 | | --- | --- | --- | | `occupyMinutes` | number,可选 | 客户端声明的预计临时占用时间(分钟),范围 1-30;缺省/0/留空 = 长期,服务端弹窗不展示该提示并沿用原逻辑,越界值自动收敛到 30 | 响应示例: ```json { "success": true, "errCode": "", "data": { "isOccupied": false, "isAutoCheck": true, "extendMinutes": 0 } } ``` | 字段 | 类型 | 说明 | | --- | --- | --- | | `data.isOccupied` | boolean | `true` = 资源仍被占用;`false` = 不占用 | | `data.isAutoCheck` | boolean | `true` = 30 秒超时后自动确认;`false` = 用户手动点击 | | `data.extendMinutes` | number | 非 0 时表示用户选择"再用 N 分钟"(占用人正在收尾,N 分钟后可用);0 = 无延长 | 调用示例: ```bash curl http://<本机IP>:18721/confirm/isOccupied # 声明预计临时占用 15 分钟(服务端确认弹窗会展示该信息) curl "http://<本机IP>:18721/confirm/isOccupied?occupyMinutes=15" ``` ### 查询确认记录 ``` GET /api/records ``` 返回最近 50 条记录(合并今天与昨天的 JSONL 日志,最新在前): ```json { "success": true, "errCode": "", "data": [ { "timestamp": "2026-09-12 10:23:45", "isOccupied": false, "isAutoCheck": true, "requestIp": "192.168.1.100", "extendMinutes": 0, "occupyMinutes": 15 } ] } ``` | 字段 | 类型 | 说明 | | --- | --- | --- | | `timestamp` | string | 确认时间(本地时区,`YYYY-MM-DD HH:MM:SS`) | | `isOccupied` | boolean | `true` = 资源仍被占用 | | `isAutoCheck` | boolean | `true` = 自动确认 | | `requestIp` | string | 发起确认请求的客户端 IP(老记录可能为空字符串) | | `extendMinutes` | number | 非 0 时表示用户选择"再用 N 分钟"(老记录可能为 0) | | `occupyMinutes` | number | 客户端发起请求时声明的临时占用时间(1-30 分钟);0 = 未声明/长期,列表中显示 `长期`(老记录为 0) | ### 页面与静态资源 | 路径 | 说明 | | --- | --- | | `/`、`/index.html` | 记录查看页(浏览器可直接访问) | | `/confirm.html` | 确认弹窗页 | | `/src/main.js`、`/src/confirm.js`、`/src/styles.css` | 页面资源 | ## 技术栈 - **桌面框架**:Tauri 2(系统托盘 `tray-icon`、多窗口、进程间命令与事件) - **后端**:Rust + axum 0.7 + tokio + tower-http(CORS)+ chrono - **前端**:原生 HTML / CSS / JavaScript(无框架,通过 `include_str!` 在编译时嵌入二进制) - **共享状态**:`Arc>` + `tokio::sync::oneshot`,HTTP 请求与窗口按钮之间一次性结果传递 ## 项目结构 ``` occupation_confirm/ └── dev/ # 工程根目录 ├── frontend/ # 前端静态资源(编译时嵌入) │ ├── index.html # 主窗口:记录列表 + 手动发起确认 │ ├── confirm.html # 确认弹窗:30 秒倒计时 + 再用N分钟 │ ├── settings.html # 设置窗口(开机自启) │ ├── notice.html # 端口变更提示窗口 │ └── src/ │ ├── main.js # 主窗口逻辑 │ ├── confirm.js # 确认弹窗逻辑(Tauri 事件 / invoke) │ └── styles.css ├── src-tauri/ │ ├── src/ │ │ ├── main.rs # 程序入口 │ │ ├── lib.rs # Tauri 初始化、托盘菜单、Tauri 命令 │ │ ├── http_server.rs # axum HTTP 服务与接口处理 │ │ ├── state.rs # 共享状态、待响应请求、确认记录结构 │ │ ├── logger.rs # 文件日志(app + confirm JSONL) │ │ ├── client_url.rs # 客户端访问地址生成与剪贴板 │ │ ├── autostart.rs # 开机自启管理 │ │ └── install.rs # Windows 自部署(首次启动复制到应用目录) │ ├── capabilities/ # Tauri 权限配置 │ ├── icons/ # 各平台应用图标 │ ├── Cargo.toml │ ├── build.rs │ └── tauri.conf.json # 窗口、端口无关的 Tauri 配置 ├── build_windows.bat # Windows 一键构建(纯 ASCII,GBK 控制台安全) ├── build_windows.ps1 # Windows 一键构建(PowerShell 中文版) ├── gen-icon.js # 生成 512x512 图标源文件(零依赖) ├── icon-source.png └── package.json ``` ## 环境要求 - [Rust](https://rustup.rs)(stable) - [Node.js](https://nodejs.org) LTS(含 npm,仅用于 Tauri CLI 与构建) - 各平台 Tauri 2 的系统依赖: - **Windows**:Visual Studio Build Tools(MSVC,“使用 C++ 的桌面开发”工作负载)、WebView2 Runtime(Win11 通常自带) - **macOS**:Xcode Command Line Tools - **Linux**:参见 [Tauri 官方前置依赖说明](https://v2.tauri.app/start/prerequisites/) ## 开发运行 在 `dev/` 目录下执行: ```bash npm install npm run dev ``` 应用启动后主窗口默认隐藏并驻留系统托盘;点击托盘菜单「查看记录」可打开主窗口。 也可以在浏览器中直接打开前端页面进行界面调试(接口走相对地址,需要 Tauri 内的 HTTP 服务已在运行)。 ## 构建打包 在 `dev/` 目录下执行: ```bash npm run build ``` 产物为 `dev/src-tauri/target/release/occupation-confirm.exe`。已在 `tauri.conf.json` 中关闭安装包打包(`bundle.active = false`),不再生成 MSI/NSIS 安装包。 ### Windows 一键构建 双击运行 `dev/build_windows.bat`(或在 PowerShell 中运行 `build_windows.ps1`),脚本会自动完成: 1. 检查 Rust / MSVC / Node.js / WebView2 环境,缺失时可通过 winget 自动安装; 2. `npm install` 安装依赖; 3. 执行 Tauri 构建(`--no-bundle`,仅编译 exe,无需下载 WiX 等打包工具); 4. 将 `occupation-confirm.exe` 收集到 `dev/release-output/` 并自动打开该目录。 > 产出的 `occupation-confirm.exe` 为绿色可执行文件,可直接双击运行,无需安装。 ### 应用图标 `gen-icon.js` 不依赖任何第三方库,可重新生成 512×512 的图标源图 `icon-source.png`: ```bash node gen-icon.js ``` 之后可使用 `npm run tauri icon icon-source.png` 生成各平台所需的全套图标。 ## 配置说明 - **HTTP 端口**:默认 `18721`,定义在 [http_server.rs](dev/src-tauri/src/http_server.rs) 的 `SERVER_PORT` 常量中。端口被占用时自动向后扫描最多 64 个端口,实际端口通过托盘弹窗和 `get_server_port` 命令获取。 - **自动确认超时**:30 秒,后端 `handle_confirm` 的 `timeout` 与前端 [confirm.js](dev/frontend/src/confirm.js) 倒计时需保持一致。 - **倒计时延长**:用户开始设置"再用 N 分钟"输入框时,剩余倒计时不足 30 秒则延长到 30 秒(每次确认请求只触发一次)。 - **再用分钟范围**:1-60 分钟,输入框失焦时自动校验并 clamp 到该范围。 - **客户端临时占用时间**:1-30 分钟,留空为长期;"记住"勾选状态与分钟数保存在浏览器 `localStorage`(键名 `occupyConfirm.*`),不勾选时每次请求结束后清空恢复默认。 - **日志目录**:可执行文件同级 `logs/`,包含 `app.<日期>.log`(应用日志)与 `confirm.<日期>.log`(确认记录 JSONL),按天切片。 - **窗口行为**:在 [tauri.conf.json](dev/src-tauri/tauri.conf.json) 中配置——确认弹窗置顶、不可缩放/最小化/最大化;主窗口与确认弹窗启动时均隐藏。 ## 注意事项 - 确认记录以 **JSONL 文件持久化**(`logs/confirm.<日期>.log`),按天切片,应用重启后历史记录仍可查看;读取时合并今天与昨天的日志,返回最近 50 条。 - HTTP 服务监听 `0.0.0.0` 且 CORS 为宽松策略,同一网络内的主机均可调用,建议仅在可信内网环境使用。 - 同一时刻只处理一个待响应请求;超时后旧请求自动失效,后续按钮点击不会影响其结果。 - 老记录(无 `requestIp` / `extendMinutes` 字段)通过 `#[serde(default)]` 向后兼容,前端展示为 `—` / 普通占用。