Files
Fairscan_cyy/requirements/IMPLEMENTATION_COMPLETE.md
MobKBK 1848a88fcf
Some checks failed
Android CI / build (push) Has been cancelled
初步完成框架
- 实时图传:WebSocket JPEG 帧发送 + 帧率控制 + PC 浏览器预览
- PDF 上传与处理:上传/处理分离,支持 ocrpdf 和 markdown 两种类型
- MinerU 真实接入:markdown 处理 + images ZIP 打包
- OCRmyPDF 接入:ocrpdf 生成可搜索双层 PDF
- 手机端任务管理面板:轮询状态 + SAF 目录选择下载
- PC 管理面板:/dashboard 文件与任务管理
- 网络层:OkHttp 客户端、WebSocket 图传、局域网发现占位

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-04 17:03:18 +08:00

12 KiB
Raw Blame History

实现完成报告(完整版 v3

执行概览

状态Streaming (P1) + Upload/Task Pipeline (P2/P3) + MinerU 真实接入 + 任务管理面板 + Markdown ZIP 打包 已完成

最近更新2026-06-04 范围MinerU 真实 markdown 处理、任务管理面板手机端、ZIP 打包下载、HF_HUB_OFFLINE 离线模式


已完成的工作

P1实时网络图传

网络基础设施

文件 说明
network/ServerEndpoint.kt 服务端点模型host/port/url/wsUrl
network/NetworkInfoProvider.kt 本地 IP 获取
network/stream/StreamState.kt 图传状态模型Disconnected/Connecting/Connected/Error
network/stream/StreamQualityPreset.kt 质量预设 ↔ StreamQuality 映射
network/stream/FrameCompressor.kt JPEG 压缩 + 缩放
network/stream/FrameDropController.kt 丢帧控制AtomicBoolean + 时间间隔)
network/stream/OkHttpStreamClient.kt WebSocket 图传客户端(包含 StreamClient 接口)

相机页集成

  • CameraViewModel:添加 streamState、streamTargetHost、toggleStreaming()、sendStreamFrame()
  • liveAnalysis() 中嵌入图传帧发送fire-and-forget不影响 ML 分析)
  • CameraScreen:添加 StreamToggleButtonCast 图标 + 状态颜色 + 主机显示)
  • 图传断连不影响正式扫描

PC 服务器

  • pc-server/main.pyFastAPI 服务,含 /healthWS /stream、Web 预览页面
  • 支持帧广播:接收手机帧并转发给浏览器客户端
  • 帧率统计和日志

帧率控制

  • 添加 StreamFrameRate 枚举UNLIMITED / FPS_15 / FPS_10 / FPS_5
  • 设置页 RadioButton 选择
  • 无限制模式minIntervalMs <= 0仅以 isSending 状态控制

P2/P3PDF 上传与任务处理流水线

上传与处理分离(最新重构)

遵循 pc-api-spec.md 接口规范,将上传和处理解耦为独立步骤:

上传(纯传输)

  • POST /upload/pdf → 返回 fileId201 Created
  • 仅保存 PDF 到 ./uploads/,不触发任何处理
  • PC 服务端使用独立 files_db 字典存储文件记录

处理(任务创建)

  • POST /tasks/process → 基于 fileId + processType 创建任务202 Accepted
  • processType 可选值:ocrpdfmarkdown
  • 异步模拟处理queued → processing(10%→50%→90%) → completed
  • OCR PDF 模式:复制原始 PDF 作为处理结果(修复了之前空白 PDF 的问题)
  • Markdown 模式:生成示例 .md 文件

Android 端网络客户端

文件 说明
network/upload/PdfUploadClient.kt HTTP multipart POST 上传 PDF返回 (fileId, fileName, sizeBytes)
network/tasks/TaskModels.kt 任务数据模型TaskStatus / ArtifactInfo / ProcessTaskResult
network/tasks/TaskClient.kt REST 客户端:processPdf(fileId, processType)、查询状态、产物列表、下载

导出页三按钮 UI

Android 导出页新增三个独立操作按钮:

  1. 仅传输到电脑uploadPdfToServer():纯上传,设置 Uploaded(fileId, taskId=null)
  2. 上传并处理 (OCR PDF)uploadAndProcess("ocrpdf"):上传 + 创建 OCR 任务
  3. 上传并处理 (Markdown)uploadAndProcess("markdown"):上传 + 创建 Markdown 任务

UploadState 状态模型:

  • Idle — 未操作
  • Uploading(progress) — 上传中
  • Uploaded(fileId, taskId?) — 上传成功taskId 为 null 表示纯传输
  • Error(message) — 上传失败

PC 管理面板

浏览器访问 /dashboard,包含:

统计卡片

  • 已上传文件数
  • 处理任务数(排队中/处理中/已完成)

文件列表

  • 显示所有已上传的原始 PDF
  • 列:文件名、文件 ID、大小、时间、操作
  • 操作列提供 ⬇ 下载按钮(/files/{fileId}/download

任务列表

  • 显示所有处理任务及其状态
  • 列:文件名、任务 ID、状态带 badge、进度条、处理类型、时间、操作
  • 已完成任务的操作列提供 ⬇ 下载产物按钮

导航

  • 顶部导航栏可在图传预览页(/)和管理面板(/dashboard间切换
  • 自动刷新(每 2 秒)


MinerU 真实接入

替换了之前的模拟 markdown 处理,使用真实 MinerU pipeline 后端:

  • 使用 aio_do_parse() 异步接口,不阻塞 FastAPI 事件循环
  • Pipeline 后端配置:backend="pipeline", parse_method="auto"
  • 环境Conda 环境 MinerUPython 3.10.20, PyTorch 2.6.0+cu124, CUDA 12.4
  • GPU: NVIDIA RTX 4060 Laptop (8 GB VRAM)
  • 模型缓存路径:C:/Users/32892/.cache/huggingface/hub/
  • HF_HUB_OFFLINE=1 强制使用本地缓存,绕过国内网络不可达 huggingface.co 的问题

MinerU markdown 输出

  • {name}.md — markdown 产物
  • images/ — 提取的图片资源
  • {name}_result.zip.md + images/ 的完整打包(新增,便于手机端下载后直接使用)

MinerU ocrpdf 输出

  • {name}_layout.pdf — 带布局框的 PDF当前模式
  • 注:此处不是真正的 OCRmyPDF 双层 PDF详见 NEXT_STEPS

Markdown ZIP 打包

PC 服务器 markdown 处理完成后,自动检查 images/ 目录:

  • 有图片 → 打包 {name}.md + images/{name}_result.zip
  • 无图片 → 仅保留 .md 产物
  • 两种产物(.md.zip)均注册为独立 artifact客户端可按需下载
  • download_artifact 支持 application/zip MIME 类型

手机端任务管理面板

在导出页底部新增 TaskPanelSection UI 组件:

  • 任务状态显示:排队中 / 处理中(进度条) / 已完成 / 失败
  • 后台轮询2 秒间隔轮询 PC 任务状态,自动更新 UI完成后自动停止
  • 下载到指定目录:用户点击"选择目录" → SAF 文件夹选择器 → 点击"下载" → 保存到指定目录
  • 产物优选markdown 任务默认下载 ZIPocrpdf 任务默认下载 PDF
  • 下载进度:实时显示下载进度条
  • 已下载状态:显示"已下载 — 打开"按钮,可打开文件

涉及文件:

  • ExportUiState.kt:新增 RemoteTaskTaskPanelStateDownloadState
  • ExportViewModel.kt:新增 _taskPanelState、轮询逻辑、downloadResult()
  • ExportScreen.kt:新增 TaskPanelSectionTaskRow UI 组件
  • ExportActions:新增 downloadResultresetDownloadState 回调

Bug 修复

问题 原因 修复
MinerU 无法处理SSL 错误) huggingface_hub 启动时在线校验 revision main.py 顶部设置 HF_HUB_OFFLINE=1
main.py 重复 @Composable 编译错误 编辑失误 移除重复注解
ButtonDefaults.TextButtonContentPadding.copy() 不存在 Material3 API 差异 改用 PaddingValues() 直接构造
DownloadState.Error 不含 taskId 无法区分哪个任务的错误 添加 taskId 参数
WebSocket.send(ByteArray) 编译错误 OkHttp WebSocket.send 需要 ByteString 使用 toByteString() 扩展
网络权限未申请 tools:node="remove" 删除声明 移除冲突行
明文通信被禁止 <domain> 不支持 CIDR 改用 <base-config>
帧未显示在浏览器 服务器未广播帧到浏览器客户端 添加 broadcast 循环
端口输入框"删除不干净" toIntOrNull() 返回 null 后未更新 remember + LaunchedEffect
下载的 PDF 为空白页 _create_minimal_pdf() 缺少内容流 改为复制原始上传文件
上传进度卡在 0% upload_pdf 未启动 simulate_processing 添加 asyncio.create_task(后因分离重构移除)
Preview 函数编译错误 缺少 onUploadAndProcess 参数 添加 onUploadAndProcess = {}

架构总结

完整数据流

相机预览 → liveAnalysis()
  ├── → ML 分析(不变)               → 文档页面
  │
  ├── → Streaming图传开启时
  │       FrameCompressor → FrameDropController → OkHttpStreamClient → PC WS /stream → Browser
  │
  └── → 拍照 → 处理 → PDF 生成
          ExportViewModel
            ├── uploadPdfToServer()
            │     → PdfUploadClient.uploadPdf() → PC POST /upload/pdf
            │     → 返回 fileId → Uploaded(fileId, taskId=null)
            │
            └── uploadAndProcess(processType)
                  → PdfUploadClient.uploadPdf() → PC POST /upload/pdf → fileId
                  → TaskClient.processPdf(fileId, processType) → PC POST /tasks/process → taskId
                  → Uploaded(fileId, taskId)

PC 服务端架构

files_db (dict):      fileId → {fileId, fileName, sizeBytes, uploadPath, createdAt}
tasks_db (dict):      taskId → {taskId, fileId, status, progress, processType, ...}
artifacts_db (dict):  taskId → [{artifactId, fileName, ...}]
artifacts_map (dict): artifactId → {artifactId, fileName, filePath, ...}

AppContainer 新增注入

- networkInfoProvider
- okHttpClient
- streamClient: StreamClient
- pdfUploadClient: PdfUploadClient
- taskClient: TaskClient

PC 端端点总览

端点 方法 功能
/health GET 健康检查
/ GET 图传预览页面
/stream WS 接收 JPEG 帧
/dashboard GET 管理面板页面
/api/dashboard GET 管理面板 JSON 数据
/upload/pdf POST 上传 PDF纯上传201
/tasks/process POST 创建处理任务202
/tasks/{taskId} GET 查询任务状态
/tasks/{taskId}/artifacts GET 查询任务产物列表
/artifacts/{artifactId}/download GET 下载处理产物
/files/{fileId}/download GET 下载已上传的原始文件

文件清单

新增文件Android 网络层)

  1. network/ServerEndpoint.kt
  2. network/NetworkInfoProvider.kt
  3. network/stream/StreamState.kt
  4. network/stream/StreamQualityPreset.kt
  5. network/stream/FrameCompressor.kt
  6. network/stream/FrameDropController.kt
  7. network/stream/OkHttpStreamClient.kt
  8. network/upload/PdfUploadClient.kt
  9. network/tasks/TaskModels.kt
  10. network/tasks/TaskClient.kt
  11. res/xml/network_security_config.xml
  12. network/discovery/DiscoveredHost.kt(占位,待 P0 实现)
  13. network/discovery/DiscoveryState.kt(占位,待 P0 实现)
  14. network/discovery/LanServiceDiscovery.kt(占位,待 P0 实现)

新增文件PC

  1. pc-server/main.py

修改文件

文件 修改内容
gradle/libs.versions.toml 添加 OkHttp 4.12.0
app/build.gradle.kts 添加 OkHttp 依赖
AndroidManifest.xml 添加网络权限、网络安全配置
FairScanApp.kt 添加 okHttpClient、streamClient、pdfUploadClient、taskClient
CameraViewModel.kt 添加图传字段和方法、帧率控制
CameraScreen.kt 添加 StreamToggleButton
SettingsRepository.kt 添加 StreamFrameRate、ServerHost、ServerPort 等
SettingsViewModel.kt 添加 streamFrameRate、serverHost 等字段
SettingsScreen.kt 添加帧率选择、网络配置 UI
MainActivity.kt 添加上传回调、taskPanelState 收集、downloadResult 回调
ExportViewModel.kt 添加 uploadPdfToServer()、uploadAndProcess()、downloadResult()、startPolling()
ExportUiState.kt 添加 UploadState、RemoteTask、TaskPanelState、DownloadState
ExportScreen.kt 添加上传按钮、TaskPanelSection、TaskRow UI 组件
pc-server/main.py 添加 MinerU 真实接入、ZIP 打包、HF_HUB_OFFLINE

待实现

项目 状态
OCRmyPDF 真实接入 📌 下一步(当前 ocrpdf 用 MinerU 生成 layout PDF非真正双层可搜索 PDF
NSD 局域网自动发现 📌 占位(接口已定义)
设置页"扫描主机"/"测试连接"按钮功能 📌 待实现
图传延迟/帧率实时显示 🔜 可优化

修改人Claude Code 最后更新2026-06-04 修改类型Feature - Streaming + Upload/Process Pipeline + Dashboard + Real MinerU + Task Panel + ZIP