附录 C 完整代码索引(CloudTone 骨架)

本附录给出 CloudTone 项目的完整目录结构与每个关键文件的入口注释。

目录结构

cloudtone/
├── Cargo.toml
├── package.json
├── pnpm-lock.yaml
├── tsconfig.json
├── vite.config.ts
├── tailwind.config.ts
├── postcss.config.js
├── index.html
├── mini.html
├── lyric.html
├── README.md
├── .github/
│   └── workflows/
│       ├── ci.yml
│       └── release.yml
├── scripts/
│   ├── compose-latest-json.js
│   └── gen-bindings.mjs
├── public/
│   ├── fonts/
│   └── icons/
├── src/                                # 前端 (React + TS)
│   ├── main.tsx                         # 主窗口入口
│   ├── mini/
│   │   ├── main.tsx
│   │   └── MiniApp.tsx
│   ├── lyric/
│   │   ├── main.tsx
│   │   └── LyricOverlay.tsx
│   ├── app/
│   │   ├── router.tsx
│   │   ├── home/HomePage.tsx
│   │   ├── library/LibraryPage.tsx
│   │   ├── playlist/PlaylistPage.tsx
│   │   ├── search/SearchPage.tsx
│   │   ├── lyrics/LyricsPage.tsx
│   │   ├── downloads/DownloadsPage.tsx
│   │   └── settings/SettingsPage.tsx
│   ├── components/
│   │   ├── shell/Shell.tsx
│   │   ├── shell/Sidebar.tsx
│   │   ├── shell/PlayerBar.tsx
│   │   ├── shell/TitleBar.tsx
│   │   ├── shell/NowPlayingPanel.tsx
│   │   ├── shell/SearchOverlay.tsx
│   │   ├── SongList.tsx
│   │   ├── SongRow.tsx
│   │   ├── LikeButton.tsx
│   │   ├── ContextMenu.tsx
│   │   └── ui/            (shadcn)
│   ├── features/
│   │   ├── player/player.ts             # Zustand store
│   │   ├── player/usePlayerSync.ts
│   │   ├── library/queries.ts
│   │   ├── search/useSearch.ts
│   │   ├── lyrics/useLyrics.ts
│   │   ├── playlists/queries.ts
│   │   ├── download/useDownloads.ts
│   │   ├── equalizer/useEq.ts
│   │   ├── plugins/host.ts
│   │   └── updater/useUpdater.ts
│   ├── hooks/
│   │   ├── useDebouncedValue.ts
│   │   ├── useHotkeys.ts
│   │   └── useMediaEvents.ts
│   ├── lib/
│   │   ├── ipc.ts                       # specta 自动生成
│   │   ├── cn.ts
│   │   ├── fmt.ts                       # 时间/大小格式化
│   │   └── types.ts
│   ├── i18n/
│   │   ├── index.ts
│   │   └── locales/
│   ├── styles/
│   │   ├── index.css
│   │   └── tokens.css
│   └── test/
│       ├── setup.ts
│       └── *.test.tsx
└── src-tauri/                         # Rust 后端
    ├── Cargo.toml
    ├── tauri.conf.json
    ├── build.rs
    ├── icons/
    ├── capabilities/
    │   ├── default.json
    │   ├── mini.json
    │   └── lyric.json
    ├── migrations/
    │   ├── 20260115_init.sql
    │   └── 20260201_addons.sql
    ├── entitlements.plist
    └── src/
        ├── main.rs
        ├── lib.rs
        ├── state.rs                    # AppState
        ├── error.rs                    # AppError
        ├── cmds/
        │   ├── mod.rs
        │   ├── library.rs
        │   ├── player.rs
        │   ├── queue.rs
        │   ├── playlist.rs
        │   ├── search.rs
        │   ├── lyrics.rs
        │   ├── download.rs
        │   ├── eq.rs
        │   ├── settings.rs
        │   ├── plugins.rs
        │   └── updater.rs
        ├── core/
        │   ├── mod.rs
        │   ├── audio/
        │   │   ├── mod.rs
        │   │   ├── decoder.rs
        │   │   ├── output.rs
        │   │   ├── player.rs
        │   │   ├── queue.rs
        │   │   ├── fader.rs
        │   │   ├── media_controls.rs
        │   │   └── dsp/
        │   │       ├── biquad.rs
        │   │       └── equalizer.rs
        │   ├── library/
        │   │   ├── mod.rs
        │   │   ├── scanner.rs
        │   │   ├── importer.rs
        │   │   └── manager.rs
        │   ├── db/
        │   │   ├── mod.rs
        │   │   ├── migrations.rs
        │   │   ├── models.rs
        │   │   ├── queries.rs
        │   │   └── search.rs
        │   ├── lyrics/mod.rs
        │   ├── providers/
        │   │   ├── mod.rs
        │   │   ├── demo.rs
        │   │   └── registry.rs
        │   ├── download/mod.rs
        │   ├── plugins/mod.rs
        │   ├── protocol/
        │   │   ├── mod.rs
        │   │   └── cover.rs
        │   └── window/
        │       ├── mod.rs
        │       ├── main.rs
        │       ├── mini.rs
        │       └── lyric.rs
        └── tests/
            ├── db_test.rs
            └── fixtures/

关键入口文件

src-tauri/src/lib.rs

use tauri_specta::Builder;

#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
    let builder = Builder::<tauri::Wry>::new()
        .commands(tauri_specta::collect_commands![
            cmds::library::library_scan,
            cmds::library::library_list_songs,
            cmds::library::library_toggle_favorite,
            cmds::player::player_play,
            cmds::player::player_pause,
            cmds::player::player_toggle,
            cmds::player::player_seek,
            cmds::player::player_set_volume,
            cmds::queue::queue_set,
            cmds::queue::queue_next,
            cmds::queue::queue_prev,
            cmds::queue::queue_set_mode,
            cmds::playlist::playlist_create,
            cmds::playlist::playlist_list,
            cmds::playlist::playlist_add,
            cmds::playlist::playlist_remove,
            cmds::playlist::playlist_move,
            cmds::search::search,
            cmds::lyrics::lyrics_load,
            cmds::download::download_start,
            cmds::download::download_cancel,
            cmds::eq::eq_set,
            cmds::eq::eq_preset,
            cmds::settings::settings_get,
            cmds::settings::settings_set,
            cmds::plugins::plugins_list,
        ]);

    #[cfg(debug_assertions)]
    builder.export(specta_typescript::Typescript::default(), "../src/lib/ipc.ts").unwrap();

    tauri::Builder::default()
        .plugin(tauri_plugin_log::Builder::default().build())
        .plugin(tauri_plugin_single_instance::init(|app, _, _| { /* focus main */ }))
        .plugin(tauri_plugin_fs::init())
        .plugin(tauri_plugin_http::init())
        .plugin(tauri_plugin_dialog::init())
        .plugin(tauri_plugin_shell::init())
        .plugin(tauri_plugin_notification::init())
        .plugin(tauri_plugin_global_shortcut::Builder::new().build())
        .plugin(tauri_plugin_updater::Builder::new().build())
        .invoke_handler(builder.invoke_handler())
        .setup(move |app| {
            builder.mount_events(app);
            state::setup(app)?;
            core::window::main::configure(app)?;
            core::protocol::cover::register(app)?;
            Ok(())
        })
        .run(tauri::generate_context!())
        .expect("error while running tauri application");
}

src-tauri/src/main.rs

fn main() { cloudtone::run(); }

src/main.tsx

import React from "react";
import ReactDOM from "react-dom/client";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { RouterProvider } from "react-router-dom";
import { router } from "./app/router";
import "./styles/index.css";
import "./i18n";

const qc = new QueryClient();

ReactDOM.createRoot(document.getElementById("root")!).render(
  <React.StrictMode>
    <QueryClientProvider client={qc}>
      <RouterProvider router={router} />
    </QueryClientProvider>
  </React.StrictMode>,
);

一页 Cheatsheet

要做……翻到第几章
注册一个命令第 11 章
发事件 / 监听第 12 章
多窗口第 14、36 章
全局快捷键第 15 章
读写文件第 17 章
调 HTTP第 18 章
SQLite第 19、29 章
音频引擎第 26、27 章
扫描音乐库第 28 章
搜索第 33 章
自定义协议第 32 章
媒体键第 37 章
自动更新第 43 章
CI/CD第 46 章
发布第 47 章

完结

本书到此结束。感谢一路同行。你现在手里有:

  • 一本完整的 Tauri 2.x + 现代前端 + Rust 生产工程指南。
  • 一个可日常使用的桌面音乐播放器 CloudTone。
  • 面试 Tauri / 桌面应用高级岗所需的叙事和深度。

祝你快速拿到心仪 offer,或者把 CloudTone 做成下一个现象级开源项目。