Files
Leantime/dev/DWGViewer/说明.md

164 lines
9.3 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# DWG / DXF 网页查看器
浏览器端直接打开 DWG / DXF 图纸,**不经过任何转换服务**。界面沿用新迪 2D 查看器的模板
(顶栏 + 左侧图层面板 + 底部大图标工具栏 + 浮动子面板 + 状态栏)。
配套的 3D 版本在 `../STEPViewer/`;两者的统一入口在 `../index.html`(按文件后缀自动分发,
入口也支持拖拽打开,文件只在本机流转、不落地)。
---
## 一、能力
| | |
|---|---|
| **格式** | `.dwg`LibreDWG 覆盖 R13 ~ R2018越新的版本支持度越低`.dxf`ASCIIUTF-8 / GBK 自动识别) |
| **实体** | LINE / CIRCLE / ARC / ELLIPSE / LWPOLYLINE / POLYLINE / SPLINE(NURBS+拟合点) / POINT / SOLID / 3DFACE / HATCH / TEXT / MTEXT / ATTRIB / DIMENSION / LEADER / MULTILEADER / INSERT含阵列、嵌套、块内 0 层继承) |
| **显示** | 图层开关与单层隔离、真实线宽、线型(虚线/中心线、ACI 与真彩色、**三种背景(浅灰/米白/黑,同新迪 2D**、过暗/过亮线色按背景自动调整(可关)、剖面线(含 ANSI31~38 内置图案、文字中文、MTEXT 格式码/堆叠分数/按框宽折行) |
| **交互** | 滚轮定点缩放、拖动平移、框选放大、双击全图、**视图旋转(设置里左转/右转 90° + 角度滑杆,旋转后拾取/测量/平移仍然准确)**、点选查属性、对象捕捉(端点/中点/圆心/象限点/最近点) |
| **测量** | 坐标、点到点、连续、线段长、弧长、点到线、线到线(平行间距 / 夹角、线性ΔX/ΔY、角度、半径直径、面积周长、结果统计单位/小数位可调,已有结果跟着变 |
| **批注** | 文字、自由线、直线、箭头、矩形、圆、云线;颜色与线宽可调、可撤销(批注存世界坐标,跟着图纸缩放旋转) |
| **其它** | 文字全图查找并定位、模型/布局切换、PNG 截图、打印/导出 PDF、全屏顶栏 + 底部工具栏各一个、iframe 嵌入模式、上传加密存服务器并生成随机文件名的嵌入链接 |
实测Edge headless1500×950
| 图纸 | 实体数 | 解析+展平 | 每帧重绘 |
|---|---|---|---|
| XQD601线图.dwg542 KBCAXA | 3 865 | 340 ms | 3.1 ms |
| 行星滚柱丝杠专利图.dwg2.0 MB | 29 097 | 991 ms | 6.3 ms |
| 气垫调整机构.dxf4.3 MB | 21 732 | ~1.5 s | 8.8 ms |
---
## 二、目录
```
DWGViewer/
├── index.html 界面骨架(新迪 2D 模板)
├── style.css
├── app.js UI 装配:加载、图层面板、工具切换、面板、导出
├── js/
│ ├── source.js 文件 → 统一文档模型(分发 dwg / dxf角度统一成弧度
│ ├── dxfHatch.js DXF 的 HATCH 补丁解析dxf-parser 不支持 HATCH
│ ├── flatten.js 文档 → 显示列表INSERT 递归展开、变换烘焙进坐标)
│ ├── curves.js 圆弧/椭圆/NURBS/bulge 离散化、二维仿射、紧包围盒
│ ├── hatch.js 填充边界提取 + 图案线生成(奇偶规则裁剪)+ 内置 acad.pat 图案表
│ ├── mtext.js MTEXT 格式码解析(\P \H \S \F {} 等)
│ ├── render.js Canvas2D 渲染器、空间索引、拾取
│ └── tools.js 对象捕捉、测量、批注
├── libs/
│ ├── dxf-parser/ MITDXF 解析(已改成浏览器可直接 import 的相对路径)
│ ├── shims/loglevel.js dxf-parser 依赖的 loglevel 替身importmap 映射)
│ └── libredwg/ GPL-3.0DWG 解析dist 包装 + 10 MB wasm只在打开 .dwg 时才加载
├── icons/ 取自新迪 2D/3D 案例的图标
└── samples/ 测试图纸
```
**数据流**:文件 → `source.js``flatten.js``render.js`
展平只在加载时做一次,把 INSERT 的变换全部烘焙进世界坐标;之后缩放平移只重算屏幕坐标,
所以三万实体也能保持 6 ms 一帧。
---
## 三、本地运行
```powershell
python $env:TEMP\nds_server_dwg.py # 端口 8920服务 dev/ 根目录,日志 %TEMP%\req_log_dwg.txt
```
浏览器打开统一入口 `http://127.0.0.1:8920/index.html`,支持:
- 直接带参数(按后缀自动进 2D / 3D 查看器):
`?file=DWGViewer/samples/XQD601.dwg``?file=STEPViewer/samples/as1-oc-214.stp`
- 落地页选文件 / 拖拽:文件内容经 postMessage 直接送进查看器,只在本机流转
- 单独打开查看器也行:`/DWGViewer/index.html?file=samples/XQD601.dwg`
把 dwg/dxf 直接拖进页面也可以。
---
## 四、部署
纯静态站点,把整个目录传上去即可,**没有服务端依赖**。两个必须确认的点:
1. **`.wasm` 的 MIME 必须是 `application/wasm`**,否则 DWG 解析加载不起来。
Apache 用同目录的 `.htaccess`nginx 在 `mime.types` 里加 `application/wasm wasm;`
2. **开 gzip/br 压缩**`libredwg-web.wasm` 原始 10 MB压缩后约 3 MB差别很大。
嵌入到别的页面:
```html
<iframe src="https://你的域名/DWGViewer/index.html?file=图纸路径.dwg&embed=1"
width="100%" height="640" frameborder="0" allowfullscreen></iframe>
```
`embed=1` 会隐藏顶栏。页面里的「嵌入」按钮可以直接生成这段代码。
> 启用防下载api/*.php + .htaccess图纸文件必须放在 DWGViewer 目录内(如
> `samples/xxx.dwg`),路径写 `file=samples/xxx.dwg``../` 逃出查看器目录的路径
> 会被令牌通道拒绝(防目录穿越)。
---
## 五、许可证(重要)
| 模块 | 许可证 | 何时加载 |
|---|---|---|
| 本项目自身代码 | 自有 | 总是 |
| `dxf-parser` | **MIT** | 打开 .dxf 时 |
| `libredwg-web`LibreDWG | **GPL-3.0** | **只有打开 .dwg 时**才动态 import |
GPL-3.0 的传染性对前端是成立的wasm 和 js 会下发到浏览器,这构成「分发」。
商用前请评估。三条可选路线:
1. **只对内 / 接受 GPL** —— 按 GPL-3.0 公开本查看器源码,最省事。
2. **只支持 DXF** —— 删掉 `libs/libredwg/``source.js` 里的 `loadDwg` 直接抛错,整套依赖就只剩 MIT。
代价是用户得先把 DWG 另存成 DXF。
3. **DWG 解析挪到服务端** —— 用 LibreDWG 的 `dwg2dxf` 命令行做 DWG→DXF以独立进程调用
通常被认为是「聚合」而非衍生作品),前端只留 MIT 的 DXF 路径;或换成 ODA SDK商业授权
代码结构已经为此做了准备:`source.js` 里 DWG 只有 `loadDwg()` 一个入口,换掉它不影响其余任何模块。
---
## 六、已知限制
- **SHX 字体不渲染真实字形**。DWG 里的 `.shx` 是矢量字库,浏览器读不了,这里按字体名映射到
系统字体(`gbcbig`/`hztxt` → 宋体,`txt`/`romans`/`isocp` → Arial。字形和 AutoCAD 里有差异,
但内容、大小、位置、对齐都是对的。
- **DIMENSION 画的是它的匿名块**,也就是文件里存的那份图形,不会按标注样式重新排。
绝大多数情况这就是 AutoCAD 里看到的样子;只有别的软件生成的、没写块的标注会缺失。
- **DXF 只支持 ASCII 格式**。二进制 DXF 会给出明确提示,让用户另存。
- **非等比缩放 + 旋转的 INSERT 里的圆弧**会退化成折线(等比或无旋转时保留解析曲线,
任意放大都不出锯齿)。这种组合在机械图里极少见。
- **OLE、光栅图像IMAGE、代理实体PROXY不显示**,会计入「跳过」统计。
- `$INSUNITS` 在国内图纸里常年是默认值,所以测量单位默认按毫米,可在「设置」里改。
---
## 七、防下载(已实现)
查看器读站内图纸时走「令牌 → 解密接口」,同时 `.htaccess` 封掉 `.dwg/.dxf/.enc` 的直接 GET
1. 上传(嵌入面板的「上传当前图纸」):`api/upload.php` 把图纸 gzip 后 XOR 加密落盘,
**落盘名是纯随机 hex**`uploads/ab12cd34….enc`),原文件名藏在加密体里——
链接里看不出是哪张图、属于哪个项目,也没法按名字猜其它图纸;
2. 读取:`api/token.php` 同源校验 + HMAC 短时令牌5 分钟),`api/model.php` 校验后
解密流式返回,原文件名通过 `X-Filename` 头带回来显示;
3. `.htaccess`(站点根 + `api/` 目录双层)禁止源文件直链。
`app.js``fetchDrawing()` 会自动走令牌流程;接口没部署(纯静态托管/本地 python
时自动退回直连,不影响开发。部署 PHP 后无需任何前端改动。
**部署注意**`token.php` / `model.php` / `upload.php` 里的 `SECRET` 三个文件必须一致,
并且要改掉默认值。`uploads/` 目录要有写权限。
**群晖/nginx.htaccess 不生效)**`upload.php``model.php` 已预设
`$PRIVATE_DIR = '/volume1/dwgviewer_private';`——在 File Station 里于 Web 目录外建这个
文件夹并给 `http` 用户组读写权限(路径不对就改成实际路径)。图纸存私有目录,嵌入链接写
`?file=纯文件名.dwg`;留在 Web 目录里的样例按原路径仍可打开,但可被直链下载,
要保护的文件必须移进私有目录。
网页端无法绝对防抓包(数据最终要进浏览器内存,懂行的人总能从调试台把解密后的字节导出来),
这套方案挡的是直接下载、批量爬取和链接外传后的猜名。