Files
cutThink_lite/docs/phase3_examples.md
Claude e2ea309ee6 feat: CutThenThink v3.0 初始版本
完整实现 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>
2026-02-12 18:59:26 +08:00

8.7 KiB

Phase 3 API 使用示例

本文档展示如何使用 Phase 3 实现的上传、配置和数据库功能。

前端使用示例

1. 配置管理

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. 上传图片

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. 记录管理

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. 设置管理

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. 完整的上传流程示例

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 单元测试

#[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: 截图后自动上传

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: 批量处理历史截图

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: 查看和清理历史记录

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} 条旧记录`);
  }
}

错误处理

网络错误处理

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);
  }
}

配置验证

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. 批量操作

对于大量记录操作,使用批量方法而非循环调用单个方法:

// 不推荐
for (const id of ids) {
  await recordsStore.removeRecord(id);
}

// 推荐
await recordsStore.removeMultipleRecords(ids);

2. 分页加载

对于大量记录,使用分页加载:

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. 缓存策略

合理使用设置缓存:

// 首次从数据库加载
let theme = await settingsStore.fetchSetting('theme');

// 后续从缓存读取
theme = settingsStore.getSettingValue('theme');

总结

Phase 3 提供了完整的上传和存储功能,包括:

  1. 多种图床支持: GitHub、Imgur、自定义
  2. 配置管理: 完善的配置读写和验证
  3. 数据持久化: SQLite 数据库存储
  4. 前端封装: TypeScript 类型和 Pinia Store
  5. UI 组件: 配置管理和历史查看界面

通过合理组合这些功能,可以实现完整的截图-上传-管理流程。