项目结构

了解 Linch Desktop 项目的目录结构和关键文件

目录结构

使用脚手架创建的项目具有以下结构:

my-app/
├── src/                           # 前端源码目录
│   ├── main.tsx                   # React 应用入口
│   ├── App.tsx                    # 路由和 Provider 配置
│   ├── config.ts                  # 基座配置
│   ├── index.css                  # 全局样式
│   ├── vite-env.d.ts              # Vite 类型声明
│   └── pages/                     # 页面组件目录
│       ├── Dashboard.tsx          # 首页
│       └── Settings.tsx           # 设置页

├── src-tauri/                     # Tauri/Rust 源码目录
│   ├── src/
│   │   ├── lib.rs                 # Rust 入口(插件初始化)
│   │   └── main.rs                # 程序主入口
│   ├── capabilities/
│   │   └── default.json           # 权限配置
│   ├── icons/                     # 应用图标(各尺寸)
│   ├── Cargo.toml                 # Rust 依赖配置
│   ├── build.rs                   # 构建脚本
│   └── tauri.conf.json            # Tauri 配置

├── index.html                     # HTML 模板
├── package.json                   # Node 依赖和脚本
├── tsconfig.json                  # TypeScript 配置
├── vite.config.ts                 # Vite 配置
└── .gitignore

关键文件详解

src/main.tsx

React 应用入口文件,负责渲染根组件:

import { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';
import App from './App';
import './index.css';

createRoot(document.getElementById('root')!).render(
  <StrictMode>
    <App />
  </StrictMode>
);

src/App.tsx

应用的核心组件,配置 Provider 和路由:

import { BrowserRouter, Routes, Route } from 'react-router-dom';
import {
  LinchDesktopProvider,
  Shell,
} from '@linch-tech/desktop-core';
import { config } from './config';
import { Dashboard } from './pages/Dashboard';
import { Settings } from './pages/Settings';

export default function App() {
  return (
    <LinchDesktopProvider config={config}>
      <BrowserRouter>
        <Routes>
          <Route element={<Shell />}>
            <Route path="/" element={<Dashboard />} />
            <Route path="/settings" element={<Settings />} />
          </Route>
        </Routes>
      </BrowserRouter>
    </LinchDesktopProvider>
  );
}

关键点:

  • LinchDesktopProvider 包裹整个应用,提供配置和初始化
  • Shell 作为布局组件,包含侧边栏和标题栏
  • 页面作为 Shell 的子路由渲染

src/config.ts

应用配置文件,控制基座的各项功能:

import { Home, Settings } from 'lucide-react';
import type { LinchDesktopConfig } from '@linch-tech/desktop-core';

export const config: Partial<LinchDesktopConfig> = {
  brand: {
    name: 'app.name',           // 应用名(i18n key)
    version: `v${__APP_VERSION__}`,
  },

  nav: [
    { title: 'app.home', path: '/', icon: Home },
    { title: 'settings.title', path: '/settings', icon: Settings },
  ],

  features: {
    updater: true,              // 启用自动更新
    database: true,             // 启用数据库
    sentry: false,              // 禁用 Sentry
  },

  i18n: {
    defaultLanguage: 'zh',
    supportedLanguages: ['zh', 'en'],
    resources: { ... },
  },
};

src/pages/

页面组件目录,每个页面是一个 React 组件:

// src/pages/Dashboard.tsx
import { useTranslation } from 'react-i18next';
import { PageHeader, ScrollArea } from '@linch-tech/desktop-core';

export function Dashboard() {
  const { t } = useTranslation();

  return (
    <ScrollArea className="flex-1">
      <div className="p-6">
        <PageHeader
          title={t('app.welcome')}
          description={t('app.description')}
        />
        {/* 页面内容 */}
      </div>
    </ScrollArea>
  );
}

src-tauri/src/lib.rs

Rust 入口文件,初始化 Tauri 插件:

use linch_tech_desktop_core::{LinchDesktopExt, LinchConfig};

#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
    let config = LinchConfig::from_env();

    tauri::Builder::default()
        .with_linch_desktop(config)
        .run(tauri::generate_context!())
        .expect("error while running tauri application");
}

with_linch_desktop() 会自动注册以下 Tauri 插件:

  • tauri-plugin-sql - SQLite 数据库
  • tauri-plugin-updater - 自动更新
  • tauri-plugin-dialog - 对话框
  • tauri-plugin-shell - Shell 操作
  • tauri-plugin-fs - 文件系统
  • tauri-plugin-opener - 打开外部链接
  • tauri-plugin-process - 进程控制

src-tauri/tauri.conf.json

Tauri 核心配置文件:

{
  "$schema": "https://schema.tauri.app/config/2",
  "productName": "My App",
  "version": "0.1.0",
  "identifier": "com.mycompany.myapp",
  "build": {
    "beforeDevCommand": "pnpm dev",
    "devUrl": "http://localhost:1450",
    "beforeBuildCommand": "pnpm build",
    "frontendDist": "../dist"
  },
  "app": {
    "withGlobalTauri": true,
    "windows": [
      {
        "title": "My App",
        "width": 1200,
        "height": 800,
        "minWidth": 800,
        "minHeight": 600,
        "decorations": false,
        "resizable": true
      }
    ]
  },
  "bundle": {
    "active": true,
    "targets": "all",
    "icon": [...]
  }
}

重要配置项:

  • decorations: false - 隐藏系统窗口装饰,使用自定义标题栏
  • withGlobalTauri: true - 在 window 对象上暴露 Tauri API

vite.config.ts

Vite 构建配置:

import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import tailwindcss from '@tailwindcss/vite';

export default defineConfig({
  define: {
    '__APP_VERSION__': JSON.stringify(pkg.version),
  },
  plugins: [react(), tailwindcss()],
  server: {
    port: 1450,
    strictPort: true,
  },
});

src-tauri/Cargo.toml

Rust 依赖配置:

[dependencies]
linch_tech_desktop_core = "0.1"
tauri = { version = "2", features = [] }
tauri-plugin-sql = { version = "2", features = ["sqlite"] }
tauri-plugin-updater = "2"
# ... 其他插件

开发工作流

添加新页面

  1. src/pages/ 创建页面组件
  2. src/App.tsx 添加路由
  3. src/config.ts 添加导航项(可选)
  4. i18n.resources 添加翻译(如果使用 i18n)

添加 Rust 功能

  1. src-tauri/Cargo.toml 添加依赖
  2. src-tauri/src/ 编写 Rust 代码
  3. 使用 #[tauri::command] 导出命令
  4. 在前端使用 invoke() 调用

下一步