Files
cutThink_lite/lightweight-redesign.md

524 lines
15 KiB
Markdown
Raw Permalink Normal View History

# CutThenThink v3.0 - 轻量级语言重构设计
## 项目背景
当前 Python + PyQt6 方案存在的问题:
- 打包体积大(~214MB
- 启动速度慢
- 依赖 PyQt6 大型框架
- 用户需要安装 Python 环境
## 新技术栈选择
### 方案对比
| 方案 | 语言 | 框架 | 包体积 | 跨平台 | 开发效率 | 热更新 |
|------|------|--------|--------|---------|---------|---------|
| **Tauri** | Rust + Web 前端 | 系统WebView | ~5-10MB | ✅ | ⭐⭐⭐ | 快 |
| **Electron** | Node.js + Web 前端 | Chromium 内嵌 | ~100-150MB | ✅ | ⭐⭐ | 快 |
| **Flutter** | Dart + Skia 引擎 | 自绘引擎 | ~20MB | ✅ | ⭐ | 中等 |
| **Go + Fyne** | Go + 自绘引擎 | 轻量 OpenGL | ~10-15MB | ✅ | ⭐ | 快 |
### 推荐方案Tauri
**理由:**
1. **极小体积**5-10MB 完整应用
2. **原生性能**Rust 后端前端任选HTML/React/Vue/Svelte
3. **现代体验**:支持热更新
4. **活跃生态**Tauri 1.0 已非常成熟
---
## 架构设计
```
┌─────────────────────────────────────────────────────────┐
│ CutThenThink v3.0 │
├─────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────────────────────────────────────────┐ │
│ │ Rust Core (tauri backend) │ │
│ ├─────────────────────────────────────────────────┤ │
│ │ │ │
│ │ ┌────────────────────────────────────────────┐ │ │
│ │ │ Web Frontend (任选) │ │ │
│ │ │ - HTML/CSS/JS │ │ │
│ │ │ - React/Vue/Svelte │ │ │
│ │ │ - TailwindCSS │ │ │
│ │ └────────────────────────────────────┘ │ │
│ │ │ │
│ └─────────────────────────────────────────────┘ │ │
│ │ │ │
│ │ ┌──────────────────────────────────────────┐ │ │
│ │ │ System Integration (平台API) │ │
│ │ │ - 截图 API │ │
│ │ │ - 文件系统 │ │
│ │ │ - 剪贴板 │ │
│ │ │ - 全局快捷键 │ │
│ │ │ - 通知 │ │
│ │ └────────────────────────────────────┘ │ │
│ │ │ │
│ │ ┌──────────────────────────────────────────┐ │ │
│ │ │ External Services (可选) │ │
│ │ │ - RapidOCR (本地) │ │
│ │ │ - 云端 OCR API │ │
│ │ │ - 云存储 (S3/OSS/WebDAV) │ │
│ │ │ - AI 分类 API (可选) │ │
│ │ └────────────────────────────────────┘ │ │
│ │ │ │
│ └─────────────────────────────────────────────┘ │ │
│ │ │
└─────────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────┘
```
---
## 目录结构
```
cutthenthink-v3/
├── src-tauri/ # Rust 后端 (Tauri CLI)
│ ├── src/
│ │ ├── main.rs # Rust 入口
│ │ ├── lib.rs # 核心库
│ │ ├── commands.rs # 命令处理
│ │ ├── screenshot.rs # 截图模块
│ │ ├── upload.rs # 上传模块
│ │ ├── database.rs # 数据库 (SQLite)
│ │ └── ocr.rs # OCR 接口
│ ├── Cargo.toml # Rust 项目配置
│ ├── tauri.conf.json # Tauri 配置
│ └── build.rs # 构建脚本
├── src-ui/ # Web 前端
│ ├── index.html # 入口 HTML
│ ├── src/
│ │ ├── main.js # 主 JS
│ │ ├── styles.css # 样式
│ │ ├── components/ # UI 组件
│ │ │ ├── screenshot.html
│ │ │ ├── upload.html
│ │ │ ├── browse.html
│ │ │ └── settings.html
│ │ ├── api/
│ │ │ ├── commands.js # Tauri API 调用
│ │ │ ├── database.js # 数据库操作
│ │ │ ├── screenshot.js # 截图功能
│ │ │ └── upload.js # 上传功能
│ └── assets/ # 静态资源
│ ├── icons/
│ └── screenshots/
├── src-ocr-plugin/ # 可选的本地 OCR 插件 (Go)
│ ├── main.go
│ ├── ocr.go
│ └── models/ # OCR 模型文件
└── docs/
├── architecture.md # 本文档
├── api.md # API 文档
└── development.md # 开发指南
```
---
## 核心功能模块
### 1. 截图模块 (screenshot.rs)
```rust
use tauri::command::screenshot::ScreenshotConfig;
/// 截全屏
#[tauri::command]
pub fn capture_fullscreen() -> Result<String, String> {
let screen = Window::current_monitor()?.ok_or("无法获取屏幕")?;
// 调用平台截图 API
match screen {
Screen::CaptureFullscreen(path) => Ok(path.to_string_lossy()),
_ => Err("未实现".to_string()),
}
}
/// 区域截图
#[tauri::command]
pub fn capture_region() -> Result<String, String> {
// 显示区域选择器
// 使用 Tauri 对话框 API
Ok("region_capture".to_string())
}
```
### 2. 上传模块 (upload.rs)
```rust
use reqwest::blocking::Client;
use serde_json::json;
/// 上传文件
pub struct UploadConfig {
pub provider: String,
pub endpoint: String,
pub api_key: Option<String>,
}
#[tauri::command]
pub fn upload_file(filepath: String) -> Result<String, String> {
let config = get_upload_config()?;
let client = Client::new();
let form = multipart::Form::new()
.text("file", filepath_to_name(&filepath)?)
.text("provider", &config.provider);
// 执行上传
let response = client.post(&config.endpoint, &body)?;
// 返回 URL
Ok(parse_upload_response(&response.text())?)
}
```
### 3. 数据库模块 (database.rs)
```rust
use rusqlite::{Connection, Result as SQLResult};
use serde::{Serialize, Deserialize};
#[derive(Serialize, Deserialize)]
pub struct Record {
pub id: Option<i64>,
pub filename: String,
pub filepath: String,
pub upload_url: Option<String>,
pub category: String,
pub ocr_text: Option<String>,
pub created_at: String,
pub uploaded_at: Option<String>,
pub file_size: i64,
}
impl Database {
pub fn add_record(&self, record: &Record) -> SQLResult<i64> {
self.conn.execute(
"INSERT INTO records (filename, filepath, category, created_at, file_size)
VALUES (?1, ?2, ?3, datetime('now'), ?4)",
[&record.filename, &record.filepath, &record.category, &record.created_at, &record.file_size],
)?;
Ok(conn.last_insert_rowid())
}
pub fn get_all_records(&self, limit: i64) -> SQLResult<Vec<Record>> {
// 查询实现
}
}
```
### 4. 前端 API 绑定 (api/commands.js)
```javascript
import { invoke } from '@tauri-apps/api/commands';
// 截图命令
export const captureFullscreen = async () => {
const filepath = await invoke('capture_fullscreen');
return filepath;
};
// 上传命令
export const uploadFile = async (filepath, config) => {
const url = await invoke('upload_file', {
filepath,
provider: config.provider,
endpoint: config.endpoint,
apiKey: config.apiKey
});
return url;
};
// 数据库命令
export const getRecords = async () => {
const records = await invoke('get_all_records', { limit: 100 });
return records;
};
```
### 5. 前端 UI (components/screenshot.html)
```html
<div class="screenshot-view">
<div class="toolbar">
<button id="btn-fullscreen" class="primary-btn">
<span class="icon">📷</span>
<span class="text">截全屏</span>
<span class="shortcut">Ctrl+Shift+A</span>
</button>
<button id="btn-region" class="secondary-btn">
<span class="icon">⛶</span>
<span class="text">区域截图</span>
<span class="shortcut">Ctrl+Shift+R</span>
</button>
</div>
<div id="preview-container">
<img id="preview" src="assets/placeholder.png" alt="预览">
</div>
<div class="actions">
<button id="btn-upload" disabled>
<span class="icon">☁️</span>
<span class="text">上传</span>
</button>
<button id="btn-ocr" disabled>
<span class="icon">🔍</span>
<span class="text">OCR 识别</span>
</button>
</div>
</div>
<style>
.screenshot-view {
display: flex;
flex-direction: column;
gap: 16px;
}
.toolbar {
display: flex;
gap: 8px;
}
.primary-btn, .secondary-btn {
flex: 1;
align-items: center;
gap: 8px;
padding: 10px 16px;
border: none;
border-radius: 6px;
cursor: pointer;
}
.primary-btn {
background: #8B6914;
color: white;
}
.secondary-btn {
background: #f1f3f4;
color: #2C2C2C;
}
button:disabled {
opacity: 0.5;
cursor: not-allowed;
}
</style>
```
---
## Tauri 配置 (tauri.conf.json)
```json
{
"$schema": "https://schema.tauri.app/config/1.0.0",
"build": {
"beforeBuildCommand": "npm run build",
"beforeDevCommand": "npm run dev",
"devUrl": "http://localhost:3000",
"frontendDist": "../src-ui/dist"
},
"package": {
"productName": "CutThenThink",
"version": "3.0.0"
},
"tauri": {
"allowlist": {
"all": false,
"shell": {
"all": false,
"open": true
}
},
"bundle": {
"identifier": "com.cutthenthink.app",
"icon": [
"icons/128x128.png"
],
"targets": ["all"]
},
"windows": {
"webviewInstallMode": "embed",
"nsis": {
"displayName": "CutThenThink",
"installerIcon": "icons/icon.ico"
}
}
}
},
"plugins": {
"shell": {
"open": true
}
}
}
```
---
## 可选 OCR 插件 (Go)
使用 Go 编写独立的 OCR 插件,通过 IPC 或本地服务器通信:
```go
package main
import (
"github.com/tetratelabs/tesseract-go/tesseract"
"github.com/genmo/invoices/invoices"
)
type OCRResult struct {
Text string
Confidence float64
Error string
}
func Recognize(imagePath string) OCRResult {
// 使用 RapidOCR 或 Tesseract
// 通过本地 socket 或 HTTP 与主程序通信
return OCRResult{
Text: "识别的文字",
Confidence: 0.95,
Error: "",
}
}
```
---
## 依赖清单
### Rust 后端依赖
```toml
[dependencies]
tauri = { version = "1.0", features = ["shell-open"] }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
tokio = { version = "1", features = ["full"] }
rusqlite = "0.3"
reqwest = { version = "0.11", features = ["blocking", "multipart"] }
chrono = { version = "0.4", features = ["serde"] }
dirs = "2.0"
```
### Web 前端依赖
```json
{
"devDependencies": {
"vite": "^4.0.0",
"@tauri-apps/api": "^1.0.0"
"tailwindcss": "^3.0.0",
"react": "^18.0.0",
"react-dom": "^18.0.0"
}
}
```
---
## 构建与打包
### 开发命令
```bash
# 前端开发
cd src-ui && npm run dev
# Rust 后端开发
cd src-tauri && cargo tauri dev
# 完整构建
npm run tauri build
```
### 打包输出
| 平台 | 输出位置 | 说明 |
|--------|---------|------|
| Linux | `src-tauri/target/release/bundle/appimage` | AppImage 单文件 |
| Windows | `src-tauri/target/release/bundle/msi` | MSI 安装包 |
| macOS | `src-tauri/target/release/bundle/dmg` | DMG 磁盘镜像 |
**预估体积**
- 基础应用5-10MB
- 包含 OCR 模型:+15-20MB
---
## 实施计划
### Phase 1: 项目初始化 (1周)
- [ ] 创建 Rust Tauri 项目骨架
- [ ] 设置前端项目 (Vite + React)
- [ ] 配置构建工具链
- [ ] 基础 UI 框架
### Phase 2: 核心功能 (2周)
- [ ] Rust 后端:截图 API 集成
- [ ] Rust 后端:文件系统访问
- [ ] 前端:截图 UI 组件
- [ ] Rust 后端SQLite 数据库实现
- [ ] 前端:记录列表和浏览
### Phase 3: 上传功能 (1周)
- [ ] Rust 后端HTTP 上传模块
- [ ] 前端:上传配置界面
- [ ] 支持多种上传服务
### Phase 4: OCR 集成 (1周)
- [ ] Go OCR 插件基础框架
- [ ] RapidOCR 模型集成
- [ ] IPC 通信机制
- [ ] 前端OCR 结果展示
### Phase 5: 打包发布 (1周)
- [ ] 各平台构建配置
- [ ] 图标和资源
- [ ] 代码签名 (Windows/macOS)
- [ ] GitHub Actions 自动构建
- [ ] 安装包测试
---
## 优势总结
| 特性 | Python 方案 | Tauri 方案 |
|------|-----------|-----------|
| 安装体积 | 需要 Python (~200MB+) | **单文件,无需运行时** |
| 启动速度 | 较慢 | **极快Rust 原生)** |
| 内存占用 | 高 (~100MB+) | **低 (~20-30MB)** |
| 更新机制 | 需要重新打包 | **支持热更新** |
| 开发体验 | 框架限制 | **现代 Web 开发** |
| 跨平台 | 依赖复杂 | **一次编译,多平台** |
---
## 参考
- **Tauri 文档**: https://tauri.app/
- **Tauri Examples**: https://github.com/tauri-apps/tauri/tree/dev/examples
- **Rusqlite**: https://github.com/rusqlite/rusqlite
- **RapidOCR**: https://github.com/RapidAI/RapidOCR
---
*文档版本: v3.0*
*创建日期: 2025-02-12*
*技术栈: Tauri (Rust) + Web 前端*