好学探索 · 技术架构设计
配套:
docs/策划文档.md(内部档案)
1. 总体架构
┌─────────────────────────────────────────────────────────────┐
│ Client(Web PWA / 后续 Capacitor App) │
│ iOS27 Liquid Glass UI · 竖滑 Feed · 随手拍 · 片库管理 │
└───────────────────────────┬─────────────────────────────────┘
│ HTTPS / LAN HTTP
│ Cookie + Bearer Session
┌───────────────────────────▼─────────────────────────────────┐
│ Docker Compose │
│ ┌──────────────┐ ┌─────────────┐ ┌────────────────────┐ │
│ │ api │ │ worker │ │ db (sqlite/pg) │ │
│ │ Node 22 │─▶│ 扫描/刮削 │─▶│ 元数据·互动·任务 │ │
│ │ Express API │ │ 缩略图 │ └────────────────────┘ │
│ └──────┬───────┘ └──────┬──────┘ │
│ │ │ │
│ ▼ ▼ │
│ /media/* bind mounts(NAS/本地) /data(配置·上传·缓存) │
└─────────────────────────────────────────────────────────────┘
│ 在线认证/刮削
▼
好学 PT · 寸光集 · 豆瓣 · TMDB原则
- 厚后端:鉴权、扫描、刮削、权限、路径安全都在服务端
- 媒体直出:视频文件走 Range 流式,不经无谓转码(MVP)
- 账号外置:不自建用户密码库,复用好学/寸光集(与 jiapu 一致)
- 可插拔源:Storage Adapter + Scraper Provider 接口化
2. 目录结构
HX-Tanqu/
├── docker-compose.yml
├── .env.example
├── README.md
├── docs/
├── backend/
│ ├── Dockerfile
│ ├── package.json
│ └── src/
│ ├── index.js # 入口
│ ├── config.js
│ ├── db/ # schema + repo
│ ├── auth/ # jiapu 同构登录链
│ ├── routes/ # HTTP 路由
│ ├── services/ # feed/library/social
│ ├── storage/ # local/webdav adapters
│ └── scrapers/ # douban/tmdb/pt/ptang
├── frontend/
│ ├── index.html
│ ├── public/
│ └── src/
│ ├── main.js
│ ├── styles/ios27.css
│ ├── auth/
│ ├── api/
│ ├── components/
│ └── views/
├── data/ # 运行时数据(volume)
└── scripts/3. 认证架构(对齐 D:\jiapu)
3.1 登录链
输入 login + password (+ twoStepCode?)
│
▼
含 @ ? ──是──▶ [寸光集在线 → 寸光集本地 → 好学本地]
│否
▼
是 admin 类?─是─▶ [寸光集本地/admin]
│否
▼
[好学在线 → 好学本地 → 寸光集本地]3.2 好学在线(hxpt)
- GET/访问
login.php建 Cookie 会话 POST /api/challenge→{ secret, challenge }clientHash = sha256(password)serverSideHash = sha256(secret + clientHash)response = hmac_sha256(challenge, serverSideHash)POST takelogin.phpform:username/response/two_step_code- 302 到首页即成功
3.3 寸光集在线(ptang)
POST https://ptang.top/api/auth/loginJSON{ email, password }- 成功返回 user 对象
3.4 会话
SESSION_SECRET签名 JWT-like:base64url(payload).base64url(hmac)- Cookie 名:
tanqu_session;同时支持Authorization: Bearer - 对外用户:
{ id, username, email, source, sourceLabel, avatar? } - id 前缀:
hxpt:/ptang:
4. 数据模型(核心表)
users_cache
登录成功后的资料缓存(非密码)
media_sources
- id, name, type(
local|webdav|pt|ptang), root_path/url, config_json, enabled
media_items
- id, source_id, path, rel_path, title, sort_title
- duration, width, height, size, mtime
- poster_path, fingerprint
- category_ids_json, series_id, episode_no
- meta_json, scraped_at, created_at
categories
- id, user_id(nullable 全局), name, icon, sort, visible, folder_bind
interactions
- user_id, media_id, liked, collected, progress_sec, updated_at
comments
- id, user_id, media_id, parent_id, body, created_at
scrape_jobs
- id, target_type(
item|folder), target_id, providers[], status, result_json
captures
- id, user_id, media_id, local_path, created_at
默认 SQLite(/data/tanqu.db),可通过 DATABASE_URL 切 PostgreSQL。
5. 模块设计
5.1 Storage Adapter
js
interface StorageAdapter {
list(dir): Promise<Entry[]>
stat(path): Promise<Stat>
openReadStream(path, { start, end }): Readable
exists(path): Promise<boolean>
}LocalAdapter:读 bind mount,严格 root jailWebdavAdapter:v0.2
5.2 Library Scanner
- 队列化目录遍历
- 指纹:
size + mtime + rel_path(可升级 hash 抽样) - 产出/更新
media_items,删除丢失文件(软删)
5.3 Stream Service
GET /api/media/:id/stream支持 HTTP Range- 校验登录 + 分类可见性 + 路径仍在 jail 内
- MIME 探测,缓存缩略图
GET /api/media/:id/poster
5.4 Feed Service
- 输入:user, tab, cursor, limit
- 过滤:visible categories、用户屏蔽
- 排序:精选分 = 新入库权重 + 未看完 + 点赞偏好
- 返回卡片 DTO(播放地址、互动态、元数据)
5.5 Scraper Providers
js
interface ScraperProvider {
id: 'douban' | 'tmdb' | 'pt' | 'ptang'
search(query, type): Promise<Candidate[]>
detail(externalId): Promise<Metadata>
}- 统一归一化:
title/original_title/year/overview/poster/actors/genres/rating/episodes
5.6 Social Service
- like toggle / collect toggle / comment CRUD / history upsert
- 全部 user 维度隔离
6. Docker 部署拓扑
yaml
services:
api: # 提供静态前端 + REST + 视频流
worker: # 扫描与刮削(可与 api 同进程 MVP)
# db: # 可选 postgres卷:
tanqu-data:/data配置、数据库、上传、海报缓存${NAS_MOVIES}:/media/movies:ro${NAS_SHORTS}:/media/shorts:ro
环境变量见 .env.example。
7. 安全设计
- 路径穿越:所有文件访问
path.resolve后必须仍以 root 为前缀 - 登录限流:15 分钟窗口失败次数(同 jiapu)
- CORS:可配置白名单;App 跨域 credentials
- 上传限制:随手拍大小/时长上限
- 密钥:
TANQU_AUTH_SECRET至少 32 字符 - 刮削密钥:TMDB API Key 仅存服务端
8. 性能策略
| 点 | 策略 |
|---|---|
| 列表 | 游标分页,避免深 offset |
| 海报 | 本地缓存 + 长缓存头 |
| 视频 | 直链 Range;可选 nginx 加速后续 |
| 扫描 | worker 单飞锁,防并发双扫 |
| SQLite | WAL;重负载可迁 PG |
9. 与 jiapu 的复用边界
| 复用 | 不复用 |
|---|---|
| 登录链、CookieJar、session 签名思想 | 家谱业务/WASM 布局 |
| Docker 一键部署体验 | 云谱同步协议 |
| 前端 session.js 模式 | 家谱 UI |
10. 技术选型
| 层 | 选型 | 原因 |
|---|---|---|
| 运行时 | Node.js 22 | 与 jiapu 认证代码同构易迁 |
| HTTP | Express | 清晰中间件、Range 友好 |
| DB | better-sqlite3 / sql.js 可切换 | 私有化零运维 |
| 前端 | 原生 ES Module + CSS | 轻、可控液态玻璃细节 |
| 容器 | Docker Compose | 用户要求与落地简单 |
| 后续 App | Capacitor | 与 jiapu 一致可复用经验 |
11. 多端客户端架构
frontend/ (共享 UI)
├── web 静态资源 ──▶ Docker api 托管
├── desktop/Electron 加载 dist 或远程 api
├── mobile Capacitor (android/ios)
└── harmony ArkWeb 加载 dist 或远程 api- 业务 UI 禁止在五端分叉复制;差异收敛到
platform桥 - 电脑端负责窗口/快捷键/协议关联
- 移动端/鸿蒙/iOS 负责相机、安全存储、状态栏、返回手势
- 详细矩阵与发版节奏见
docs/多端方案.md(内部档案)
目录增量:
desktop/ # Electron
mobile/android|ios # Capacitor
harmony/ # DevEco 工程