模型文件散落各处、版本混乱、找不到旧版?这篇文章分享我如何从零搭建一个轻量级的图纸文档管理系统,支持 DWG/STEP/STL 等工程文件在线预览和版本管理,后端跑在 NAS 上,客户端是原生桌面应用。


一、为什么要做这个

作为一个 3D 打印爱好者和机械设计从业者,我的硬盘里堆积了上百个模型文件:

  • 同一款支架改了五六个版本,不知道哪个是最终版
  • 想找一个月前下载的零件,翻遍文件夹也找不到
  • 设计迭代时改了一版尺寸,旧版直接被覆盖,想回退只能重画
  • DWG 图纸用 AutoCAD 才能看,临时查看非常不方便

市面上的 PDM(Product Data Management)系统要么太重(需要企业级部署),要么不支持工程文件预览。于是我决定自己搭一个——PlotVault PDM。

二、系统架构

1
2
3
4
5
6
7
8
┌─────────────────┐  HTTP      ┌──────────────────────────────┐
│ Windows 客户端 │ ────────▶ │ NAS Docker 容器 │
│ Tauri + Vue3 │ │ Rust API (Axum) │
│ Three.js 渲染 │ ◀───────── │ libredwg (DWG→DXF,源码编译) │
└─────────────────┘ │ 图纸存储卷 /data │
│ 缓存卷 /config │
│ PostgreSQL 容器 (元数据) │
└──────────────────────────────┘

技术选型理由

层级 技术 为什么选它
后端 Rust + Axum 单个静态二进制,镜像约 20MB,7×24 常驻零负担;性能远超 Node.js
数据库 PostgreSQL 异步连接池(sqlx),并发天然支持多请求;比 SQLite 更适合网络访问
客户端 Tauri 2 + Vue 3 原生窗口体验,安装包小(~5MB),启动快;比 Electron 轻量 10 倍
3D 预览 Three.js + occt-import-js 支持 STEP/IGES/STL/3MF,WASM 解析不冻结界面
2D 预览 Three.js (DXF) + pdf.js 支持 DWG(转 DXF)、PDF,无需安装 AutoCAD

三、核心功能

1. 文件夹树 + 文件列表

左侧文件夹树支持无限层级展开,支持拖拽调整宽度。文件列表显示名称、类型、大小、修改时间,支持复选框批量选择。

2. 版本管理(核心特性)

同目录同名文件重复上传会自动成为新版本,旧版归档到 blobs/ 目录。每个版本保留 SHA256 哈希和备注信息,支持:

  • 查看完整版本历史
  • 下载任意旧版本
  • 上传新版本并附备注
  • SHA256 内容去重(相同内容自动复用,不创建冗余归档)

3. 工程文件在线预览

格式 预览方案 说明
DWG 服务端 libredwg → DXF → Three.js 支持 LINE/多段线/圆/圆弧/文字标注
DXF Three.js 直接渲染 INSERT/BLOCK 展开,支持平移缩放旋转
STEP / STP occt-import-js WASM 完整曲面和装配体,Web Worker 解析不冻结 UI
IGES / IGS occt-import-js WASM 同上
STL Three.js 直接渲染 三角网格模型
3MF Three.js + ThreeMFLoader 3D 制造格式
PDF pdf.js 浏览器原生渲染
图片 / 文本 内建视图 PNG/JPG/TXT 等

所有 2D/3D 预览都支持鼠标旋转、缩放、平移。

4. 属性面板系统

点击文件夹或文件,右侧弹出属性面板,包含多个 Tab:

  • 属性:编码、名称、阶段、状态、描述、版本、图幅等字段,支持编辑保存
  • 文件列表:子文件夹和文件的表格化展示,支持全选、右键菜单(预览/下载/重命名/删除)
  • 版本控制:版本历史表格,支持上传新版本、下载、删除、回滚
  • 关联文档 / 历史任务(预留接口)

5. 双主题 UI

支持白天/晚上两套主题,顶栏三态切换(跟随系统/白天/晚上)。护眼模式采用暖黄纸质色调,减少长时间工作的视觉疲劳。

6. 其他特性

  • 拖拽上传:整窗口任意位置拖入文件即可上传,支持文件夹递归读取
  • 批量操作:复选框多选后批量下载(自动打包 zip)、批量移动、批量删除
  • 文件树右键菜单:新建子文件夹、重命名、删除、打开文件夹
  • NAS 真实目录同步:文件夹映射为磁盘真实目录,NAS 上可直接浏览备份
  • 自动同步:每 30 秒扫描 library/ 目录,外部新增的文件自动导入数据库
  • 上传进度:字节级进度条 + 实时网速 + 预计剩余时间
  • API Token 鉴权:可选的访问令牌保护

四、部署指南

前置条件

  • 一台 NAS 或 Linux 服务器(Docker 环境)
  • Windows PC(构建客户端用)

4.1 部署后端

最简单的方式是 Docker Compose。复制仓库中的 docker-compose.yml,替换所有 <...> 占位符:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
services:
db:
image: postgres:18-alpine
container_name: plotvault-pdm-db
restart: unless-stopped
environment:
- POSTGRES_USER=plotvault_pdm
- POSTGRES_PASSWORD=你的数据库密码 # ← 替换
- POSTGRES_DB=plotvault_pdm
volumes:
- /mnt/pool1/apps/plotvault-pdm/pgdata:/var/lib/postgresql # ← 替换宿主路径

plotvault-pdm:
image: donniemarc/plotvault-pdm-server:latest # ← 替换为你的 Docker Hub 用户名
container_name: plotvault-pdm
restart: unless-stopped
depends_on:
- db
ports:
- "8642:8642" # ← 替换对外端口
environment:
- DATA_DIR=/data
- CONFIG_DIR=/config
- DATABASE_URL=postgres://plotvault_pdm:你的数据库密码@db:5432/plotvault_pdm # ← 密码与上面一致
- BIND=0.0.0.0:8642
- API_TOKEN=你的访问令牌 # ← 替换,建议随机生成
volumes:
- /mnt/pool1/apps/plotvault-pdm/data:/data # ← 替换:图纸数据
- /mnt/pool1/apps/plotvault-pdm/config:/config # ← 替换:软件缓存

启动:

1
docker compose up -d

验证:

1
2
curl http://<主机IP>:8642/api/health
# {"service":"plotvault-pdm","status":"ok"}

TrueNAS 用户:Apps → Discover → Custom App → 勾选 Use docker-compose → 粘贴修改后的 compose 文件即可。注意不要加 build: 行(TrueNAS 无源码目录会报错)。

4.2 构建 Windows 客户端

需要:Rust(MSVC 工具链 + VS Build Tools C++ 工作负载)、Node.js 18+、WebView2 运行时(Win10/11 自带)。

1
2
3
4
cd client
npm install
npm run tauri build # 生成 NSIS 安装包
# 产物:client/src-tauri/target/release/bundle/nsis/PlotVault PDM_x.x.x_x64-setup.exe

安装包可以分发给其他机器使用,只需在设置中填入服务器地址和 Token 即可连接。

4.3 目录结构说明

1
2
3
4
5
6
7
8
9
DATA_DIR/                      # 图纸数据(NAS 上可直接浏览/备份)
├── library/<文件夹路径>/<文件名> # 真实目录镜像:最新版本文件在此
└── blobs/<file_id>/<ver>_<uuid>.<ext> # 仅历史版本归档

CONFIG_DIR/ # 软件缓存(可随镜像丢弃重建)
├── dxf_cache/ # DWG→DXF 转换缓存
└── tmp/ # 上传临时文件

pgdata/ # PostgreSQL 元数据(folders/files/versions)

备份策略:拷贝 data/ + pgdata/ 两个目录即可完整备份。图纸文件为主,数据库丢了不影响文件本身。

五、使用说明

5.1 首次连接

  1. 启动客户端
  2. 点击右上角 设置
  3. 填入服务器地址 http://<NAS-IP>:8642 和 API Token
  4. 点击 测试连接 → 显示成功后 保存

5.2 文件管理

  • 新建文件夹:文件树节点悬停点击 +,或顶部「新建文件夹」按钮
  • 上传文件:右上角「上传」按钮,或直接把文件拖进窗口
  • 预览文件:点击文件名,右侧弹出属性面板和预览区域
  • 下载文件:属性面板「下载文件」按钮,或右键菜单下载
  • 重命名:文件树/文件列表右键菜单 → 重命名
  • 移动:拖拽文件到左侧文件夹树的目标节点,或右键菜单 → 移动
  • 删除:右键菜单 → 删除,需二次确认

5.3 版本管理

  1. 点击文件 → 属性面板 → 版本控制 Tab
  2. 点击 创建小版本 上传新版本(同名上传自动成为新版本)
  3. 查看版本历史列表,点击 下载 获取任意旧版本
  4. 支持版本备注,方便标注每次修改内容

5.4 文件列表操作

在属性面板的 文件列表 Tab 中:

  • 表头 全选复选框 可一键选中所有文件
  • 右键文件行弹出菜单:预览、下载、重命名、删除
  • 勾选多个文件后可批量操作

六、环境变量配置

环境变量 默认值 说明
DATA_DIR /data 图纸数据目录(library 真实目录 + blobs 版本归档)
CONFIG_DIR /config 软件缓存目录(dxf_cache + tmp)
DATABASE_URL postgres://postgres:postgres@localhost:5432/plotvault_pdm PostgreSQL 连接串
BIND 0.0.0.0:8642 监听地址
API_TOKEN 空 设置后所有 API 需 Bearer Token 鉴权

七、常见问题

Q: DWG 预览报错「dwg2dxf not available」?

Docker 镜像已内置 libredwg,确保使用 Docker 部署。本地裸跑二进制需要自行编译 libredwg。转换结果会缓存到 CONFIG_DIR/dxf_cache。

Q: 数据库连不上?

确认 db 容器已启动(docker compose ps),DATABASE_URL 中的用户/密码/库名与 POSTGRES_* 环境变量一致。后端启动时会自动重试连接(最多 240 秒)。

Q: PG 18 容器拒绝启动?

PG 18+ 的数据目录改为 /var/lib/postgresql/18/docker,compose 中必须挂载父目录 /var/lib/postgresql,不是 /var/lib/postgresql/data。

Q: 如何清空重建?

删除 config/ + 清空数据库即可重置元数据。删除 data/ 则连图纸一起清空。重启容器后 scan_library_to_db 会自动从磁盘重建元数据。

Q: STEP 预览卡顿?

默认使用客户端 Web Worker 解析。如需服务端解析(适合超大文件),部署 converter 容器(端口 8000),然后修改客户端 api.ts 的 STEP_CONVERT_URL。

八、后续计划

  • 缩略图(STL/STEP 服务端渲染小图)
  • 版本对比叠加显示
  • DWG 导出 PDF
  • 批量打包下载(zip)
  • 标签 / 分类 / 全文检索
  • 审计日志、多用户权限
  • 客户端自动更新(Tauri updater)

九、开源信息


如果你也有工程文件管理的困扰,欢迎试用 PlotVault PDM。有问题或建议,欢迎在 GitHub 提 Issue。