OneBot: Leantime 改造版源码(BOM/Univer 表格/AI 接管/品牌替换等)

This commit is contained in:
wangruiguo
2026-09-03 18:49:20 +08:00
commit d647428529
3501 changed files with 1988906 additions and 0 deletions

163
dev/DWGViewer/说明.md Normal file
View File

@@ -0,0 +1,163 @@
# 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 目录里的样例按原路径仍可打开,但可被直链下载,
要保护的文件必须移进私有目录。
网页端无法绝对防抓包(数据最终要进浏览器内存,懂行的人总能从调试台把解密后的字节导出来),
这套方案挡的是直接下载、批量爬取和链接外传后的猜名。