feat: 实现CutThenThink P0阶段核心功能

项目初始化
- 创建完整项目结构(src/, data/, docs/, examples/, tests/)
- 配置requirements.txt依赖
- 创建.gitignore

P0基础框架
- 数据库模型:Record模型,6种分类类型
- 配置管理:YAML配置,支持AI/OCR/云存储/UI配置
- OCR模块:PaddleOCR本地识别,支持云端扩展
- AI模块:支持OpenAI/Claude/通义/Ollama,6种分类
- 存储模块:完整CRUD,搜索,统计,导入导出
- 主窗口框架:侧边栏导航,米白配色方案
- 图片处理:截图/剪贴板/文件选择/图片预览
- 处理流程整合:OCR→AI→存储串联,Markdown展示,剪贴板复制
- 分类浏览:卡片网格展示,分类筛选,搜索,详情查看

技术栈
- PyQt6 + SQLAlchemy + PaddleOCR + OpenAI/Claude SDK
- 共47个Python文件,4000+行代码

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
congsh
2026-02-11 18:21:31 +08:00
commit c4a77f8aa4
79 changed files with 19412 additions and 0 deletions

23
src/models/__init__.py Normal file
View File

@@ -0,0 +1,23 @@
"""
数据模型
"""
from src.models.database import (
Base,
Record,
RecordCategory,
DatabaseManager,
db_manager,
init_database,
get_db,
)
__all__ = [
'Base',
'Record',
'RecordCategory',
'DatabaseManager',
'db_manager',
'init_database',
'get_db',
]

196
src/models/database.py Normal file
View File

@@ -0,0 +1,196 @@
"""
数据库模型定义
使用 SQLAlchemy ORM 定义 Record 模型
"""
from datetime import datetime
from typing import Optional
from sqlalchemy import Column, Integer, String, Text, DateTime, JSON
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
Base = declarative_base()
class RecordCategory:
"""记录分类常量"""
TODO = "TODO" # 待办事项
NOTE = "NOTE" # 笔记
IDEA = "IDEA" # 灵感
REF = "REF" # 参考资料
FUNNY = "FUNNY" # 搞笑文案
TEXT = "TEXT" # 纯文本
@classmethod
def all(cls):
"""获取所有分类类型"""
return [cls.TODO, cls.NOTE, cls.IDEA, cls.REF, cls.FUNNY, cls.TEXT]
@classmethod
def is_valid(cls, category: str) -> bool:
"""验证分类是否有效"""
return category in cls.all()
class Record(Base):
"""记录模型 - 存储图片识别和AI处理结果"""
__tablename__ = 'records'
# 主键
id = Column(Integer, primary_key=True, autoincrement=True, comment='记录ID')
# 图片路径
image_path = Column(String(512), nullable=False, unique=True, index=True, comment='图片存储路径')
# OCR识别结果
ocr_text = Column(Text, nullable=True, comment='OCR识别的文本内容')
# 分类类型
category = Column(
String(20),
nullable=False,
default=RecordCategory.NOTE,
index=True,
comment='记录分类'
)
# AI生成的Markdown内容
ai_result = Column(Text, nullable=True, comment='AI处理生成的Markdown内容')
# 标签JSON格式存储
tags = Column(JSON, nullable=True, comment='标签列表')
# 用户备注
notes = Column(Text, nullable=True, comment='用户手动添加的备注')
# 时间戳
created_at = Column(DateTime, default=datetime.utcnow, nullable=False, comment='创建时间')
updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow, nullable=False, comment='更新时间')
def __repr__(self):
return f"<Record(id={self.id}, category='{self.category}', image_path='{self.image_path}')>"
def to_dict(self):
"""转换为字典格式"""
return {
'id': self.id,
'image_path': self.image_path,
'ocr_text': self.ocr_text,
'category': self.category,
'ai_result': self.ai_result,
'tags': self.tags or [],
'notes': self.notes,
'created_at': self.created_at.isoformat() if self.created_at else None,
'updated_at': self.updated_at.isoformat() if self.updated_at else None,
}
def update_tags(self, tags: list):
"""更新标签"""
self.tags = tags
def add_tag(self, tag: str):
"""添加单个标签"""
if self.tags is None:
self.tags = []
if tag not in self.tags:
self.tags.append(tag)
# 数据库连接管理
class DatabaseManager:
"""数据库管理器 - 负责连接和会话管理"""
def __init__(self, db_path: str = "sqlite:///cutnthink.db"):
"""
初始化数据库管理器
Args:
db_path: 数据库连接路径默认使用SQLite
"""
self.db_path = db_path
self.engine = None
self.SessionLocal = None
def init_db(self, db_path: Optional[str] = None):
"""
初始化数据库连接和表结构
Args:
db_path: 可选的数据库路径,如果提供则覆盖初始化时的路径
"""
if db_path:
self.db_path = db_path
# 创建数据库引擎
self.engine = create_engine(
self.db_path,
echo=False, # 不输出SQL日志
connect_args={"check_same_thread": False} # SQLite特定配置
)
# 创建会话工厂
self.SessionLocal = sessionmaker(
autocommit=False,
autoflush=False,
bind=self.engine
)
# 创建所有表
Base.metadata.create_all(bind=self.engine)
def get_session(self):
"""
获取数据库会话
Returns:
SQLAlchemy Session对象
"""
if self.SessionLocal is None:
raise RuntimeError("数据库未初始化,请先调用 init_db() 方法")
return self.SessionLocal()
def close(self):
"""关闭数据库连接"""
if self.engine:
self.engine.dispose()
self.engine = None
self.SessionLocal = None
# 全局数据库管理器实例
db_manager = DatabaseManager()
def init_database(db_path: str = "sqlite:////home/congsh/CodeSpace/ClaudeSpace/CutThenThink/data/cutnthink.db"):
"""
初始化数据库的便捷函数
Args:
db_path: 数据库文件路径
Returns:
DatabaseManager实例
"""
db_manager.init_db(db_path)
return db_manager
def get_db():
"""
获取数据库会话的便捷函数
Returns:
SQLAlchemy Session对象
Example:
>>> session = get_db()
>>> try:
... # 使用session进行数据库操作
... records = session.query(Record).all()
... finally:
... session.close()
"""
return db_manager.get_session()