完整实现 Tauri + Vanilla JS 轻量级截图工具 Phase 1 - 项目搭建 - Tauri 2.x 项目初始化 - Vite 前端项目搭建 - 基础 UI 框架(CSS 变量、组件库) - 构建配置优化 Phase 2 - 核心截图功能 - 全屏/区域/窗口截图 - 截图预览和管理 - 文件命名和缩略图 - 全局快捷键集成 Phase 3 - 上传与存储 - 多图床上传(GitHub/Imgur/自定义) - 配置管理系统 - SQLite 数据库 Phase 4 - OCR 集成 - 云端 OCR(百度/腾讯云) - 插件管理系统 - 本地 OCR 插件(Go) - OCR 结果处理 Phase 5 - AI 分类系统 - Claude/OpenAI API 集成 - Prompt 模板引擎 - 模板管理界面 - 自动分类流程 Phase 6 - 历史记录与管理 - 图库视图(网格/列表) - 搜索与筛选 - 批量操作 - 导出功能(JSON/CSV/ZIP) Phase 7 - 打包与发布 - 多平台构建配置 - CI/CD 工作流 - 图标和资源 - 安装包配置 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
382 lines
8.7 KiB
Markdown
382 lines
8.7 KiB
Markdown
# Phase 3 API 使用示例
|
|
|
|
本文档展示如何使用 Phase 3 实现的上传、配置和数据库功能。
|
|
|
|
## 前端使用示例
|
|
|
|
### 1. 配置管理
|
|
|
|
```typescript
|
|
import { useConfigStore } from '@/store';
|
|
|
|
const configStore = useConfigStore();
|
|
|
|
// 加载配置
|
|
await configStore.loadConfig();
|
|
|
|
// 添加 GitHub 图床
|
|
await configStore.addImageHost({
|
|
type: 'github',
|
|
token: 'your_github_token',
|
|
owner: 'your_username',
|
|
repo: 'your_repo',
|
|
path: 'screenshots',
|
|
branch: 'main'
|
|
});
|
|
|
|
// 设置为默认图床
|
|
const githubHost = {
|
|
type: 'github',
|
|
token: 'your_github_token',
|
|
owner: 'your_username',
|
|
repo: 'your_repo',
|
|
path: 'screenshots',
|
|
branch: 'main'
|
|
};
|
|
await configStore.setDefaultImageHost(githubHost);
|
|
|
|
// 更新上传设置
|
|
await configStore.updateRetryCount(5);
|
|
await configStore.updateUploadTimeout(60);
|
|
```
|
|
|
|
### 2. 上传图片
|
|
|
|
```typescript
|
|
import { useUploadStore } from '@/store';
|
|
|
|
const uploadStore = useUploadStore();
|
|
|
|
// 单个上传
|
|
const result = await uploadStore.startUpload(
|
|
'/path/to/image.png',
|
|
'screenshot.png'
|
|
);
|
|
console.log('上传成功:', result.url);
|
|
|
|
// 批量上传
|
|
const images = [
|
|
{ path: '/path/to/image1.png', filename: 'image1.png' },
|
|
{ path: '/path/to/image2.png', filename: 'image2.png' }
|
|
];
|
|
const results = await uploadStore.startBatchUpload(images);
|
|
```
|
|
|
|
### 3. 记录管理
|
|
|
|
```typescript
|
|
import { useRecordsStore } from '@/store';
|
|
|
|
const recordsStore = useRecordsStore();
|
|
|
|
// 加载所有记录
|
|
await recordsStore.loadRecords();
|
|
|
|
// 添加记录
|
|
const record = await recordsStore.addRecord({
|
|
record_type: 'image',
|
|
content: 'https://example.com/image.png',
|
|
file_path: '/path/to/image.png',
|
|
thumbnail: 'data:image/png;base64,...',
|
|
metadata: JSON.stringify({ size: 1024, width: 1920, height: 1080 })
|
|
});
|
|
|
|
// 删除记录
|
|
await recordsStore.removeRecord(record.id);
|
|
|
|
// 清空所有记录
|
|
await recordsStore.clearAllRecords();
|
|
```
|
|
|
|
### 4. 设置管理
|
|
|
|
```typescript
|
|
import { useSettingsStore } from '@/store';
|
|
|
|
const settingsStore = useSettingsStore();
|
|
|
|
// 设置值
|
|
await settingsStore.updateSetting('theme', 'dark');
|
|
await settingsStore.updateSetting('language', 'zh-CN');
|
|
|
|
// 获取值
|
|
const theme = await settingsStore.fetchSetting('theme');
|
|
// 或从缓存获取
|
|
const theme = settingsStore.getSettingValue('theme');
|
|
|
|
// 便捷方法
|
|
await settingsStore.setLastImageHostType('github');
|
|
const lastType = await settingsStore.getLastImageHostType();
|
|
```
|
|
|
|
### 5. 完整的上传流程示例
|
|
|
|
```typescript
|
|
import { useUploadStore, useRecordsStore, useConfigStore } from '@/store';
|
|
|
|
async function uploadAndRecord(imagePath: string) {
|
|
const configStore = useConfigStore();
|
|
const uploadStore = useUploadStore();
|
|
const recordsStore = useRecordsStore();
|
|
|
|
try {
|
|
// 1. 确保有配置的图床
|
|
if (!configStore.defaultImageHost) {
|
|
throw new Error('请先配置图床');
|
|
}
|
|
|
|
// 2. 上传图片
|
|
const uploadResult = await uploadStore.startUpload(
|
|
imagePath,
|
|
'screenshot.png'
|
|
);
|
|
|
|
// 3. 保存到数据库
|
|
const record = await recordsStore.addRecord({
|
|
record_type: 'image',
|
|
content: uploadResult.url,
|
|
file_path: imagePath,
|
|
metadata: JSON.stringify({
|
|
image_host: uploadResult.image_host,
|
|
file_size: uploadResult.file_size,
|
|
uploaded_at: uploadResult.uploaded_at
|
|
})
|
|
});
|
|
|
|
console.log('上传成功,记录已保存:', record);
|
|
return record;
|
|
|
|
} catch (error) {
|
|
console.error('上传失败:', error);
|
|
throw error;
|
|
}
|
|
}
|
|
```
|
|
|
|
## 后端测试示例
|
|
|
|
### Rust 单元测试
|
|
|
|
```rust
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
use std::fs;
|
|
use tempfile::tempdir;
|
|
|
|
#[test]
|
|
fn test_config_manager() {
|
|
let temp_dir = tempdir().unwrap();
|
|
let config_file = temp_dir.path().join("config.json");
|
|
|
|
let config_manager = ConfigManager::new_with_path(&config_file).unwrap();
|
|
|
|
// 测试保存和加载
|
|
let config = AppConfig::default();
|
|
config_manager.save(&config).unwrap();
|
|
|
|
let loaded_config = config_manager.load().unwrap();
|
|
assert_eq!(loaded_config.upload_retry_count, 3);
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_database_operations() {
|
|
let db = Database::open(":memory:").unwrap();
|
|
|
|
// 插入记录
|
|
let record = db.insert_record(
|
|
RecordType::Image,
|
|
"https://example.com/image.png",
|
|
Some("/path/to/image.png"),
|
|
None,
|
|
None,
|
|
).unwrap();
|
|
|
|
// 查询记录
|
|
let found = db.get_record(&record.id).unwrap();
|
|
assert!(found.is_some());
|
|
|
|
// 删除记录
|
|
let deleted = db.delete_record(&record.id).unwrap();
|
|
assert!(deleted);
|
|
}
|
|
}
|
|
```
|
|
|
|
## 常见使用场景
|
|
|
|
### 场景 1: 截图后自动上传
|
|
|
|
```typescript
|
|
import { screenshotFullscreen } from '@/api';
|
|
import { uploadAndRecord } from './upload-flow';
|
|
|
|
async function captureAndUpload() {
|
|
// 1. 截图
|
|
const screenshot = await screenshotFullscreen();
|
|
|
|
// 2. 上传并记录
|
|
const record = await uploadAndRecord(screenshot.filepath);
|
|
|
|
// 3. 如果配置了自动复制,复制链接
|
|
if (configStore.autoCopyLink) {
|
|
await navigator.clipboard.writeText(record.content);
|
|
}
|
|
|
|
return record;
|
|
}
|
|
```
|
|
|
|
### 场景 2: 批量处理历史截图
|
|
|
|
```typescript
|
|
import { screenshotList } from '@/api';
|
|
import { useUploadStore } from '@/store';
|
|
|
|
async function batchUploadHistory() {
|
|
const uploadStore = useUploadStore();
|
|
|
|
// 1. 获取所有截图
|
|
const screenshots = await screenshotList();
|
|
|
|
// 2. 批量上传
|
|
const images = screenshots.map(ss => ({
|
|
path: ss.filepath,
|
|
filename: ss.filename
|
|
}));
|
|
|
|
const results = await uploadStore.startBatchUpload(images);
|
|
|
|
console.log(`成功上传 ${results.length}/${images.length} 张图片`);
|
|
return results;
|
|
}
|
|
```
|
|
|
|
### 场景 3: 查看和清理历史记录
|
|
|
|
```typescript
|
|
import { useRecordsStore } from '@/store';
|
|
import { getRecordsCount } from '@/api';
|
|
|
|
async function cleanupOldRecords() {
|
|
const recordsStore = useRecordsStore();
|
|
|
|
// 1. 获取当前记录数
|
|
const count = await getRecordsCount();
|
|
|
|
// 2. 如果超过限制,删除最旧的
|
|
const limit = 100;
|
|
if (count > limit) {
|
|
const records = await recordsStore.loadRecords(limit + 1);
|
|
const toDelete = records.slice(limit);
|
|
|
|
for (const record of toDelete) {
|
|
await recordsStore.removeRecord(record.id);
|
|
}
|
|
|
|
console.log(`清理了 ${toDelete.length} 条旧记录`);
|
|
}
|
|
}
|
|
```
|
|
|
|
## 错误处理
|
|
|
|
### 网络错误处理
|
|
|
|
```typescript
|
|
try {
|
|
const result = await uploadStore.startUpload(imagePath, filename);
|
|
} catch (error) {
|
|
if (error.message.includes('timeout')) {
|
|
console.error('上传超时,请检查网络连接');
|
|
} else if (error.message.includes('401')) {
|
|
console.error('认证失败,请检查图床凭据');
|
|
} else {
|
|
console.error('上传失败:', error.message);
|
|
}
|
|
}
|
|
```
|
|
|
|
### 配置验证
|
|
|
|
```typescript
|
|
function validateImageHostConfig(config: ImageHostConfig): string[] {
|
|
const errors: string[] = [];
|
|
|
|
if (config.type === 'github') {
|
|
if (!config.token) errors.push('GitHub Token 不能为空');
|
|
if (!config.owner) errors.push('GitHub Owner 不能为空');
|
|
if (!config.repo) errors.push('GitHub Repository 不能为空');
|
|
} else if (config.type === 'imgur') {
|
|
if (!config.client_id) errors.push('Imgur Client ID 不能为空');
|
|
} else if (config.type === 'custom') {
|
|
if (!config.url) errors.push('自定义 URL 不能为空');
|
|
}
|
|
|
|
return errors;
|
|
}
|
|
```
|
|
|
|
## 性能优化建议
|
|
|
|
### 1. 批量操作
|
|
|
|
对于大量记录操作,使用批量方法而非循环调用单个方法:
|
|
|
|
```typescript
|
|
// 不推荐
|
|
for (const id of ids) {
|
|
await recordsStore.removeRecord(id);
|
|
}
|
|
|
|
// 推荐
|
|
await recordsStore.removeMultipleRecords(ids);
|
|
```
|
|
|
|
### 2. 分页加载
|
|
|
|
对于大量记录,使用分页加载:
|
|
|
|
```typescript
|
|
const PAGE_SIZE = 50;
|
|
|
|
async function loadAllRecords() {
|
|
let allRecords: Record[] = [];
|
|
let page = 0;
|
|
|
|
while (true) {
|
|
const records = await recordsStore.loadRecords(PAGE_SIZE, page * PAGE_SIZE);
|
|
if (records.length === 0) break;
|
|
|
|
allRecords = allRecords.concat(records);
|
|
page++;
|
|
}
|
|
|
|
return allRecords;
|
|
}
|
|
```
|
|
|
|
### 3. 缓存策略
|
|
|
|
合理使用设置缓存:
|
|
|
|
```typescript
|
|
// 首次从数据库加载
|
|
let theme = await settingsStore.fetchSetting('theme');
|
|
|
|
// 后续从缓存读取
|
|
theme = settingsStore.getSettingValue('theme');
|
|
```
|
|
|
|
## 总结
|
|
|
|
Phase 3 提供了完整的上传和存储功能,包括:
|
|
|
|
1. **多种图床支持**: GitHub、Imgur、自定义
|
|
2. **配置管理**: 完善的配置读写和验证
|
|
3. **数据持久化**: SQLite 数据库存储
|
|
4. **前端封装**: TypeScript 类型和 Pinia Store
|
|
5. **UI 组件**: 配置管理和历史查看界面
|
|
|
|
通过合理组合这些功能,可以实现完整的截图-上传-管理流程。
|