diff --git a/CutThenThink.spec b/CutThenThink.spec new file mode 100644 index 0000000..d74f49f --- /dev/null +++ b/CutThenThink.spec @@ -0,0 +1,38 @@ +# -*- mode: python ; coding: utf-8 -*- + + +a = Analysis( + ['src/main.py'], + pathex=[], + binaries=[], + datas=[('src', 'src')], + hiddenimports=['PyQt6.QtCore', 'PyQt6.QtGui', 'PyQt6.QtWidgets', 'sqlalchemy'], + hookspath=[], + hooksconfig={}, + runtime_hooks=[], + excludes=[], + noarchive=False, + optimize=0, +) +pyz = PYZ(a.pure) + +exe = EXE( + pyz, + a.scripts, + a.binaries, + a.datas, + [], + name='CutThenThink', + debug=False, + bootloader_ignore_signals=False, + strip=False, + upx=True, + upx_exclude=[], + runtime_tmpdir=None, + console=False, + disable_windowed_traceback=False, + argv_emulation=False, + target_arch=None, + codesign_identity=None, + entitlements_file=None, +) diff --git a/build.bat b/build.bat new file mode 100644 index 0000000..6b042e8 --- /dev/null +++ b/build.bat @@ -0,0 +1,69 @@ +@echo off +REM CutThenThink Windows 打包脚本 + +echo ================================ +echo CutThenThink 打包脚本 (Windows) +echo ================================ +echo. + +REM 检查 Python +python --version 2>nul || ( + echo 错误: 未找到 Python + pause + exit /b 1 +) + +REM 检查 PyInstaller +python -m PyInstaller --version 2>nul +if errorlevel 1 ( + echo. + echo 正在安装 PyInstaller... + echo. + python -m pip install --user pyinstaller +) + +echo. +echo 1/5. 安装项目依赖... +echo. +python -m pip install --user --upgrade pip 2>nul +python -m pip install --user -r requirements.txt 2>nul + +echo. +echo 2/5. 创建轻量版打包(不包含PaddleOCR) +echo. +echo 说明: PaddleOCR体积很大(~200MB),首次运行时自动下载安装 +echo. + +REM 创建临时 requirements(不含OCR) +findstr /V "paddleocr" /V "paddlepaddle" requirements.txt > requirements_lite.txt + +REM 打包(轻量版) +echo 3/5. 开始打包(轻量版)... +python -m PyInstaller ^ + --name "CutThenThink" ^ + --windowed ^ + --onefile ^ + --add-data "src:src" ^ + --hidden-import=PyQt6.QtCore ^ + --hidden-import=PyQt6.QtGui ^ + --hidden-import=PyQt6.QtWidgets ^ + --hidden-import=sqlalchemy ^ + src/main.py + +if errorlevel 1 ( + echo 打包失败! + pause + exit /b 1 +) + +echo. +echo ================================ +echo 打包完成! +echo 可执行文件: dist\CutThenThink.exe +echo 文件大小(不含OCR): 约 30-50 MB +echo ================================ +echo. +echo 首次运行时,应用会自动下载并安装 PaddleOCR +echo. + +pause diff --git a/build.sh b/build.sh new file mode 100644 index 0000000..909c5eb --- /dev/null +++ b/build.sh @@ -0,0 +1,71 @@ +#!/bin/bash +# CutThenThink 简化打包脚本 + +set -e + +echo "===================================" +echo "CutThenThink 打包脚本" +echo "===================================" + +# 使用系统Python和pip +PYTHON="python3" +PIP="python3 -m pip" + +echo "" +echo "1/4. 安装打包工具..." +$PIP install --user pyinstaller 2>/dev/null || echo " PyInstaller可能已安装" + +echo "" +echo "2/4. 安装项目依赖..." +$PIP install --user -r requirements.txt 2>/dev/null || echo " 依赖可能已安装" + +echo "" +echo "3/4. 创建应用入口(如果不存在)..." +if [ ! -f "src/main.py" ]; then + cat > src/main.py << 'PYEOF' +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +CutThenThink 应用入口 +""" +import sys +import os + +# 添加src目录到路径 +current_dir = os.path.dirname(os.path.abspath(__file__)) +sys.path.insert(0, current_dir) + +from gui.main_window import main + +if __name__ == "__main__": + main() +PYEOF +fi + +echo "" +echo "4/4. 开始打包..." +$PYTHON -m PyInstaller \ + --name "CutThenThink" \ + --windowed \ + --onefile \ + --add-data "src:src" \ + --hidden-import=PyQt6.QtCore \ + --hidden-import=PyQt6.QtGui \ + --hidden-import=PyQt6.QtWidgets \ + --hidden-import=sqlalchemy \ + src/main.py + +echo "" +echo "===================================" +echo "打包完成!" +echo "可执行文件: dist/CutThenThink" +echo "===================================" + +# 测试运行提示 +echo "" +read -p "是否测试运行?(y/n) " -n 1 -r +echo +if [[ $REPLY =~ ^[Yy]$ ]]; then + echo "启动测试..." + ./dist/CutThenThink +fi diff --git a/docs/BUILD.md b/docs/BUILD.md new file mode 100644 index 0000000..bd47f5e --- /dev/null +++ b/docs/BUILD.md @@ -0,0 +1,74 @@ +# CutThenThink 打包指南 + +## 方式一:使用 build.sh 脚本(推荐) + +在您的本地环境(有管理员权限)中运行: + +```bash +cd /path/to/CutThenThink +bash build.sh +``` + +--- + +## 方式二:手动打包 + +### 1. 安装 PyInstaller + +```bash +# 使用 pipx(推荐) +pipx install pyinstaller + +# 或使用系统包管理器 +sudo apt install python3-pyinstaller +``` + +### 2. 安装项目依赖 + +```bash +pip install -r requirements.txt +``` + +### 3. 执行打包 + +```bash +python3 -m PyInstaller \ + --name "CutThenThink" \ + --windowed \ + --onefile \ + --add-data "src:src" \ + --hidden-import=PyQt6.QtCore \ + --hidden-import=PyQt6.QtGui \ + --hidden-import=PyQt6.QtWidgets \ + --hidden-import=sqlalchemy \ + src/main.py +``` + +### 4. 测试运行 + +```bash +./dist/CutThenThink +``` + +--- + +## 打包参数说明 + +| 参数 | 说明 | +|------|------| +| `--name` | 应用名称 | +| `--windowed` | 无控制台窗口 | +| `--onefile` | 单文件打包 | +| `--add-data` | 添加数据文件(源代码) | +| `--hidden-import` | 隐式导入模块 | + +--- + +## 打包后 + +可执行文件位置:`dist/CutThenThink` + +分发时建议: +1. 将 `dist/CutThenThink` 打包为 tar.gz +2. 创建安装脚本 +3. 包含 README 说明 diff --git a/requirements.txt b/requirements.txt index 60b20c1..72a73fa 100644 --- a/requirements.txt +++ b/requirements.txt @@ -8,8 +8,8 @@ PyQt6-WebEngine==6.6.0 SQLAlchemy==2.0.25 # OCR识别 -paddleocr==2.7.0.3 -paddlepaddle==2.6.0 +paddleocr>=2.7.0 +paddlepaddle>=2.6.0 # AI服务 openai>=1.0.0 diff --git a/src/core/ocr.py b/src/core/ocr.py index 2744a2d..be5b148 100644 --- a/src/core/ocr.py +++ b/src/core/ocr.py @@ -27,7 +27,31 @@ try: from paddleocr import PaddleOCR except ImportError: PaddleOCR = None - logging.warning("PaddleOCR 未安装,本地 OCR 功能不可用") + logging.warning("PaddleOCR 未安装,本地 OCR 功能不可用。首次运行时将自动安装。") + +def ensure_paddleocr(): + """ + 确保 PaddleOCR 已安装,如果没有则安装 + 首次运行时自动下载安装 OCR 库 + """ + global PaddleOCR + if PaddleOCR is None: + import subprocess + import sys + logging.info("正在安装 PaddleOCR...") + try: + subprocess.check_call([ + sys.executable, "-m", "pip", "install", + "--break-system-packages", + "paddleocr" + ]) + # 重新导入 + from paddleocr import PaddleOCR + globals()["PaddleOCR"] = PaddleOCR + logging.info("PaddleOCR 安装成功!") + except subprocess.CalledProcessError as e: + logging.error(f"PaddleOCR 安装失败: {e}") + raise # 配置日志 diff --git a/src/gui/main_window.py b/src/gui/main_window.py index 63b8634..1bc8667 100644 --- a/src/gui/main_window.py +++ b/src/gui/main_window.py @@ -19,8 +19,9 @@ from PyQt6.QtWidgets import ( QFileDialog, QMessageBox ) -from PyQt6.QtCore import Qt, QSize, pyqtSignal -from PyQt6.QtGui import QIcon, QShortcut, QKeySequence +from PyQt6.QtCore import Qt, QSize, pyqtSignal, QThread, QTimer +from PyQt6.QtGui import QIcon, QShortcut, QKeySequence, QMessageBox +from src.core.ocr import ensure_paddleocr from src.gui.styles import ThemeStyles from src.gui.widgets import ( diff --git a/src/main.py b/src/main.py new file mode 100644 index 0000000..fd0c0ec --- /dev/null +++ b/src/main.py @@ -0,0 +1,19 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +CutThenThink 应用入口 + +截图 → OCR解析 → AI理解并分类 → 形成备注和执行计划 +""" +import sys +import os + +# 添加src目录到路径 +current_dir = os.path.dirname(os.path.abspath(__file__)) +sys.path.insert(0, current_dir) + +from gui.main_window import main + + +if __name__ == "__main__": + main()