跳到正文
灵动桌面框架
Esc
本栏目菜单

Service 业务层

Service 层负责业务逻辑处理,是 Command 和 Database 之间的桥梁。

结构

每个业务模块对应一个 Service 文件:

src-tauri/src/services/
├── mod.rs                    # 模块导出
├── config.rs                 # 配置业务逻辑(ConfigService)
└── main_window_placement.rs  # 主窗口显示器记忆与纠偏

示例

ConfigService 是无字段的单元结构体,方法都是关联函数,数据库引用通过参数传入(services/config.rs):

/// 配置管理服务
pub struct ConfigService;

impl ConfigService {
    /// 获取所有配置
    pub fn get_all(db: &Database) -> Result<Vec<AppConfig>, AppError> {
        db.get_all_config()
    }

    /// 设置配置值
    pub fn set(db: &Database, key: &str, value: &str) -> Result<(), AppError> {
        if key.is_empty() {
            return Err(AppError::InvalidInput("配置键不能为空".into()));
        }
        db.set_config(key, value)
    }

    /// 删除配置
    pub fn delete(db: &Database, key: &str) -> Result<(), AppError> {
        let deleted = db.delete_config(key)?;
        if !deleted {
            return Err(AppError::NotFound(format!("配置项 '{}' 不存在", key)));
        }
        Ok(())
    }
}

Command 层这样调用:ConfigService::set(&state.db, &key, &value)。

主窗口显示器记忆

main_window_placement.rs 不访问数据库,负责记住主窗口所在的显示器,在冷启动、托盘唤回、二次启动、插拔副屏后把窗口放回原来的屏;记录持久化到 app_config_dir 下的 json 文件(开发版 main-window-placement-dev.json,正式版 main-window-placement.json)。对外入口:

函数用途
init(app, will_show)启动时读取记录,把主窗口摆回上次的屏
show_main(app, source)唤回主窗口(还原 + 显示 + 聚焦 + 纠偏),托盘、二次启动、macOS Dock 都走它
capture_now(app, reason)立即记录一次当前位置
on_main_window_event(app, event)在 on_window_event 中处理主窗口的移动 / 缩放 / 缩放比例变化

新增「唤回主窗口」的入口时一律调用 show_main,不要手写 unminimize + show + set_focus,否则会绕过显示器纠偏。

规范

  • Service 方法通过参数接收 &Database(来自 state.db),不在 Service 内持有连接
  • 使用 AppError 作为错误类型(非 CommandError)
  • 参数校验与业务判定(如“配置项不存在”)在 Service 层完成
  • 复杂逻辑拆分为多个小方法
  • 一个 Service 对应一个业务模块