构建前后端service层——从tauri-plugin-sql重构到seaorm #3

构建前后端service层——从tauri-plugin-sql重构到seaorm #3

huoshen80
2025-11-17 / 0 评论 / 38 阅读 / 正在检测是否收录...

回顾前文

seaorm迁移初体验——从tauri-plugin-sql重构到seaorm #1 数据库迁移脚本
构建数据库repository层——从tauri-plugin-sql重构到seaorm #2

使用tauri::command构建后端service层

写好了repository层,显然前端没法直接调用这些curd操作,传统的前后端架构往往都需要通过写一些HTTP接口来实现前后端通信,而在Tauri应用中,可以利用tauri::command宏来简化这个过程。tauri::command允许我们通过进程间通信的方式,将Rust函数暴露给前端调用,从而实现前后端的数据交互。
tauri command

一个tauri command的示例:

/// 插入游戏数据(包含关联数据)
#[tauri::command]
pub async fn insert_game_with_related(
    db: State<'_, DatabaseConnection>,
    game: InsertGameData,
    bgm: Option<BgmDataInput>,
    vndb: Option<VndbDataInput>,
    other: Option<OtherDataInput>,
) -> Result<i32, String> {
    GamesRepository::insert_with_related(&db, game, bgm, vndb, other)
        .await
        .map_err(|e| format!("插入游戏数据失败: {}", e))
};

lib.rs中注册command

写好了一个tauri command之后,还需要在lib.rs中注册这个command,才能让Tauri应用识别它:

tauri::Builder::default()
.invoke_handler(tauri::generate_handler![
    insert_game_with_related,
    // 其他command...
])

在前端使用invoke构建前端service层(调用command)

在前端,我们可以通过Tauri提供的invoke方法来调用后端暴露的command,从而实现前后端的数据交互。我们可以将这些调用封装成一个service层,方便在应用中使用。
由于command较多,如果一个command就写一个函数,那前端service层会显得非常臃肿,因此我们可以将相关的command进行分类,以及使用OOP的编程思想,将相关的command封装到一个类中。

基础Service类:

// 统一处理错误
export class BaseService {
    protected async invoke<T>(
        command: string,
        args?: Record<string, unknown>,
    ): Promise<T> {
        try {
            const result = await invoke<T>(command, args);
            return result;
        } catch (error) {
            console.error(`[Service Error] ${command}:`, error);
            throw error;
        }
    }
}

GameService类:

class GameService extends BaseService {
    /**
     * 插入游戏数据(包含关联数据)
     */
    async insertGame(
        game: RawGameData,
        bgm?: BgmData | null,
        vndb?: VndbData | null,
        other?: OtherData | null,
    ): Promise<number> {
        return this.invoke<number>("insert_game_with_related", {
            game,
            bgm: bgm || null,
            vndb: vndb || null,
            other: other || null,
        });
    }

    //...更多的方法
}

insertGame方法调用示例:

import { gameService } from "@/services";
            addGame: async (fullgame: FullGameData) => {
                try {
                    if (isTauri()) {
                        await gameService.insertGame(
                            fullgame.game,
                            fullgame.bgm_data,
                            fullgame.vndb_data,
                            fullgame.other_data,
                        );
                    } else {
                        insertGameLocal(fullgame);
                    }
                    // 使用通用刷新函数
                    await get().refreshGameData();
                } catch (error) {
                    console.error("Error adding game:", error);
                }
            },

结语

至此,完成了从tauri-plugin-sql重构到seaorm的重构工作。前端的职责变回了纯粹的UI展示和交互逻辑,后端则专注于数据库curd和部分底层功能逻辑。通过这种清晰的分层架构,代码的可维护性和扩展性都得到了显著提升。

0

评论 (0)

取消