这一篇的灵魂是一句不太好听的话:图纸链路「跑得通,但跑不满」。代码能跑、接口能出图、三格式能导出、中文标注能渲染——但真要往下发,数据撑不住。这不是 bug,是数据问题,是我在就任时就得当着人讲清楚的事。
项目:德莉玛(dlmware.cn)淋浴房定制业务里,一张订单怎么变成一张能下发的玻璃图纸这条链路。
技术栈(真实):后端 Express + better-sqlite3,本地端口 8787;部署走 pm2 + rsync。图纸导出三格式 PNG / PDF / DXF,导出后自动落盘归档。相关接口三个:/api/bom(拆料)、/api/glass_dwg(出图)、/api/quote(报价)。
版本状态:在产 v2.5.0;v2.4.9 新增了一个岗位环节——「拆单员 → 技术确认岗」(把老师傅的经验活儿固化成标准流转)。
数据资产(全量):33,176 单 / 387 家经销商 / 2,799 个型号;400 单抽样里 97% 的 spec 是 null 或「否」(等于没有尺寸),只有 3 单有真实尺寸,且这 3 单属于 K / Y 系列。
| 校验结果(实测命中率) | 值 | 对图纸链路意味着什么 |
|---|---|---|
| 型号匹配 | 96.6% | 能认出型号,图有东西可画 |
| 玻璃厚度匹配 | 95.2% | 厚度参数基本齐,DXF 的框线画得出来 |
| 尺寸覆盖 | 29% | 🔴 真正卡点:没尺寸就等于没图 |
| 客户 / 经销商匹配 | 0% | 🔴 图下发给谁,对不上号 |
同系列往前看:复盘 24 · 德莉玛 monorepo(这套代码怎么组织的)、复盘 25 · 订单到报价流水线(本文档那条链路的前三段体检);单体架构见 复盘 29 · 订购单系统(单体)。跨模块踩坑总账在 20 · 踩坑总账。
复盘一条图纸链路,第一件事不是看代码,是把「谁画、谁认、谁发」写清楚。图纸这个东西很特殊:它错了不报错,它只是浪费一块玻璃。
/api/bom。这一段能兜底——模板在,料就拆得出来。/api/glass_dwg。这一段没有任何兜底:没有长宽,图就是空的。/api/quote。这一段是四个接口里唯一需要「钱」的。| 段 | 接口 | 缺数据时能否兜底 | 缺什么就废 |
|---|---|---|---|
| 1 解析 | ——(录单) | 能(型号 96.6% 兜住大部分) | 型号词表 |
| 2 BOM | /api/bom | 能(模板兜底) | 模板缺失 |
| 3 图纸 | /api/glass_dwg | 不能 | 尺寸(spec) |
| 3.5 技术确认 | ——(岗位流转) | 能(人工兜底,这是它存在的理由) | 人不在岗 |
| 4 报价 | /api/quote | 不能 | 尺寸 + 出厂价 + 经销商对应关系 |
?? 800 这类写法在图纸链路里同样视为伪造);唯独这一段,我把它做成一个正式的岗位节点,而不是「让老师傅顺手看一眼」。区别在哪?「顺手看一眼」不在系统里,它今天在、明天人调岗就没了;做成节点,它就有状态、有记录、有交接。刚做导出的时候我以为一个格式就够。结论:这三种格式服务的是三种完全不同的人,缺一个整条链路就断在一半。
| 格式 | 主用途 | 谁在用 | 不能替代谁 |
|---|---|---|---|
| DXF | 切割 / 排版数据 | 下游机器、排版软件 | 替代不了 PNG/PDF(人读不了) |
| PNG | 预览 / 沟通 / 工单附图 | 拆单员、销售、车间 | 替代不了 PDF/DXF(打印糊、机器不认) |
| 正式下发 / 打印 / 存档 | 技术确认岗、归档 | 替代不了 DXF(人能看但不代表线能切) |
淋浴房图纸必须带中文标注——系列代号看人认,但「上沿 8mm」「左固定」「开孔 φ35」这种字是给车间看的。结果第一版出来的图纸,中文要么不出、要么是一堆方块。
| 我第一反应 | 真实情况 |
|---|---|
| 「渲染库没装中文支持」→ 换渲染库 | 换库解决不了:换完还是方块,因为根因不在库 selection,在字体没有在绘图层显式注册 |
| 「换个默认字体就行」 | 系统里有中文字体≠渲染环境里注册了它。headless 环境下渲染进程拿不到系统字体映射,中文填空 |
| 「导出后我人眼看一眼图,没乱码就发」 | 这条最危险:一张整页黑块/空白的图,肉眼也能「看过去」,人眼看图会漏——尤其批量归档以后,没人会一张张看 |
两步,第一步解决「出不出得来」,第二步解决「怎么确认它出来了」。
| 验证手段 | 查什么 | 为什么不能省 |
|---|---|---|
| 文件字节 | 产物体积是否落在合理区间 | 整页空白的图体积会缩到异常小,这条能挡住 80% 的「图是空的」 |
| 内容采样 | 按点采样统计非背景像素占比(墨迹率) | 挡住「体积正常但内容错版 / 全黑 / 字挤成一团」这类字节骗不过肉眼、但肉眼看不过来的情况 |
| 人眼看图 | —— | 不写进自动化流程。批量归档场景下人眼不可靠也不可持续 |
在产版本 v2.5.0;v2.4.9 干了一件事——在拆单和发图之间,插进一个「技术确认岗」。这不是加个审批按钮,是把原来靠人肉扛的复核,变成流水线里的一段。
| 加岗位之前 | 加岗位之后(v2.4.9) | |
|---|---|---|
| 图纸怎么走到车间 | 拆单员画完 → 直接流转,靠老师傅顺手看一眼 | 拆单员出图 → 技术确认岗确认 → 下发 |
| 复核在哪发生 | 脑子里 / 口头 / 半成品上才发现 | 在系统里,是一个可见状态 |
| 人不在怎么办 | 没人复核就直接流下去(真的发生过) | 状态卡在「待技术确认」,图下不发 |
| 经验怎么传 | 人带人,走了就断 | 固化成标准流转,新人照着节点走 |
图纸导出后自动落盘归档——导出这个动作和落盘这个动作,我在设计上绑成同一个原子操作,不做成「先出图、再回头存一下」。原因很简单:中了「下发了但没存」,出事时你拿不出任何版本记录。
| 环节 | 要求 | 为什么 |
|---|---|---|
| 导出即落盘 | 导出成功后立刻写盘;失败就是失败,不返回「成功」 | 下发和归档不能分成两步,分成两步就一定会丢 |
| 文件名 ASCII | 用订单号 + 系列 + 型号 + 时间戳,全 ASCII;中文文件名一律不许进文件名 | ① 中文文件名在传输 / 跨目录拷贝时会乱码;② 归档要能被程序检索,中文名检索不了 |
| 目录结构 | 按订单号 / 时间归档,路径可回溯 | 日后要能一句话答出「这张图当时是哪一版」 |
| 三格式同批落 | PNG / PDF / DXF 同一次导出一起存,不是三个接口各存一次 | 三者描述的是同一张图,存成三次就会出现「PDF 是新的、DXF 是旧的」这种鬼情况 |
/api/glass_dwg 能画,但下发给谁这个问题上,订单 ↔ 经销商的对应关系实测是 0%。我跑过一轮全量校验,四个数:型号 96.6%、玻璃厚度 95.2%、尺寸 29%、客户匹配 0%。把这组词扔到任何汇报里,别人第一反应都是「前两个挺好」。
| 指标 | 值 | 正确读法 | 容易误读成 |
|---|---|---|---|
| 型号匹配 | 96.6% | 第 1 段过关,图有东西可画 | ❌「数据没问题,就快能全量出图了」 |
| 玻璃厚度匹配 | 95.2% | 厚度参数基本齐,框线能画 | ❌「参数齐了图就完整」 |
| 尺寸覆盖 | 29% | 🔴 第 3 段的命门,没尺寸就是没图 | ❌「平均一下还有 60% 左右」 |
| 客户匹配 | 0% | 🔴 图下发给谁,一个都对不上 | ❌「0% 才要紧,别的还能救」 |
spec 是 null 或「否」,真正有尺寸的只有 3 单,还是 K / Y 系列,不是 H / H4 / M / S 主流系列。我最需要拿去验证出图链路的那批主流数据,一份都摸不到。这是我在这篇里最想要的一句结论,也是最难开口的一句:这条链路的代码是好的,问题全在数据和岗位上。
| 层 | 现状 | 归因 | 归谁负责 |
|---|---|---|---|
| 出图代码 | ✅ 三格式能导出,中文能标注,落盘能归档 | 能跑通 | 代码(已解决) |
| 可画的样本 | 🔴 尺寸覆盖 29%;400 单抽样 97% 无尺寸 | 数据问题 | 录单口径 / 采集层 |
| 下发对象 | 🔴 客户匹配 0%,不知道发给谁 | 主数据问题 | 主数据补录 |
| 复核环节 | v2.4.9 已补齐为「拆单员 → 技术确认岗」 | 岗位问题(已修) | 流程 |
这一节的关键词是客户那句原话:「先看不要改任何东西。」——驻场工程师最容易犯的职业病,就是看到问题顺手改掉,然后被问「那之前那三个月数据是怎么回事」。
把相关接口、归档目录、落盘文件读一遍。这一步全程只读,一个字节都不写。
看图对不对这个问题,用文件字节 + 内容采样回答(第 03 节那两条断言)。肉眼在这个场景里不是证据。
诊断结果落成四栏:能跑通的 / 缺数据的 / 主数据断的 / 岗位缺的。分别对应不同的负责方和不同的工期,混成一团就等于没诊断。
| 纪律 | 具体口径 | 我为什么守它 |
|---|---|---|
| ① 诊断期只读 | 用户说「先看」就是真的只看,不备份、不改配置、不重启 | read-only 是把责任边界画清楚;顺手改了,出了事分不清是原问题还是我改出来的 |
| ② 验证靠机械测量 | 文件字节、内容采样、接口返回结构 | 图纸类产物失败不报错,只有测量能兜 |
| ③ 归类先于修复 | 先分「代码 / 数据 / 主数据 / 岗位」四桶 | 四桶对应四种工期和四种人,不分类开出的单子没人能认领 |
| ④ 生产变更走版本 | v2.4.9 / v2.5.0 有明确版本,改流转节点记变更单 | 模板见 模板库 · 变更单;踩坑总账在 20 · 踩坑总账 |
| 项 | 决定 | 理由(真实取舍) |
|---|---|---|
| 三格式并存 | 保留 PNG / PDF / DXF | 三拨人各拿各的;「一键转换」我没做也没量化,动导出层风险面太大 |
| 中文渲染 | 绕行方案:显式注册字体 + 出图断言 | 没动绘图层——那一层被三格式共用,重写风险是整个模块;先让图出得来 |
| 人工复核 | 做成节点,不做成人肉提醒(v2.4.9) | 「顺手看一眼」不在系统里,人一调岗就断;做成节点才有状态和交接 |
| 出得来但画不满 | 如实报,不改代码去凑数 | 用默认值补尺寸能「跑满」,但那是伪造图,一线拿着去下单,废的是玻璃 |
| 归档文件名 | 只准 ASCII | 中文文件名在跨机 / 跨目录搬移时会变形,归档检索会失效(我踩过) |
| 没做的优化 | 没做的就写没做 | 比如 DXF 下游实际接入率、改造后出图成功率,我没测 / 还没量化,不编 |
/api/bom /api/glass_dwg /api/quote我会先问一句「跑得通是跑给谁看的」,然后报四个实测命中率。德莉玛玻璃图纸这条链路就是我最好的例子——三格式导出、中文标注、自动归档、岗位流转全都做完了,但我不会说它「做好了」。
背景是这样的:德莉玛(dlmware.cn)淋浴房定制,订单 → BOM → 玻璃图纸 → 报价。技术栈是 Express + better-sqlite3,本地端口 8787,pm2 + rsync 部署。图纸导出 PNG / PDF / DXF 三种:DXF 给下游切割排版用,PNG 给人快速看,PDF 是唯一能正式下发打印的——三个格式不是冗余,是三拨人各拿各的,缺一个整条链就断在一半。相关接口三个:/api/bom、/api/glass_dwg、/api/quote。
我跑的实测命中率:型号匹配 96.6%、玻璃厚度 95.2%、尺寸覆盖 29%、客户匹配 0%。全量历史是 33,176 单、387 家经销商、2,799 个型号;抽样 400 单查尺寸字段 spec,97% 是 null 或「否」,真正有尺寸的只有 3 单,而且这 3 单属于 K / Y 系列,不是主流系列。
我的判断是四个数里取最小值,不取平均数。96.6 和 0 平均是 48.3%,但实际上能完整下发到人的单量是 0%——因为出图缺尺寸是画不出来,报价缺尺寸还能手工估一下;图纸缺尺寸,DXF 里就没有坐标,PDF 里就没有框线。所以我的结论是:这条链路「跑得通但跑不满」,是数据问题,不是代码问题。我当着客户的面这么讲,不美化。
技术上有两块坑值得说,因为都是「不报错的失败」。
第一块是中文标注:图纸必须带中文(「上沿 8mm」「左固定」「开孔 φ35」是给车间看的),第一版出来是方块。我第一反应是换渲染库、换默认字体,都没用——根因是字体没在绘图层显式注册,headless 环境拿不到系统字体映射。修法我是绕着做的:显式注册一个能用且渲染稳定的字体,没去动绘图层本身的字体抽象层,因为那一层被三个导出共用,重写风险是整个图纸模块。
第二块是验证方式:修完之后我没靠「人眼看一眼图,没乱码就发」——这条最危险,一张整页空白的图肉眼也能看过去,批量归档后更不可能一张张看。我挂的是机械断言:出图后查文件字节(整页空白体积会异常小)+ 内容采样(按点采样统计非背景像素占比)。凡是「不报错的失败」,只能靠对产物做机械测量来兜,断言必须挂在接口后面,不能挂在人身上。
还有一条是产品/流程上的:我在 v2.4.9 加了个岗位节点「拆单员 → 技术确认岗」。以前是拆单员画完直接流下去,靠老师傅顺手看一眼;人不在、人调岗,这复核就没了。做成节点之后,图卡在「待技术确认」,下不发,状态可查。
取舍我如实说:多一个节点就多一次人工环节,效率一定下降,具体下降多少我没测(没有可比的对照组)。但我愿意它慢,因为图纸错一次的代价是废一块定尺裁的玻璃加返工,跟几分钟的确认摆在一起是压倒性划算的。
节点位置我也坚持过:放在「拆完」和「下发」之间,不放录单前——确认岗面前必须有实物,不能让他审一个连型号都不确定的东西。
归档这块我踩过一个很土但很贵的坑:中文文件名。第一版我拿订单备注里的中文(「金框 / 白框 / 长虹玻璃」)进文件名,结果同一批图在两台机器之间搬一次文件名就变形,归档检索直接失效,代价是一批文件要重命名。现在的规矩很硬:文件名只准 ASCII(订单号 + 系列 + 型号 + 时间戳),中文一律进内容字段和索引表,绝不进文件名。另外我设计上把导出和落盘绑成同一个原子操作——分成两步就一定会丢;三格式同批落,不是三个接口各落一次。
最后是我在这条链上守的 FDE 纪律,也是我觉得对面试官最有信号的一点。客户当时只跟我说「先看不要改任何东西」,我就真的全程只读:不备份、不改配置、不重启。诊断完我也不直接动手修,先把问题分成代码 / 数据 / 主数据 / 岗位四桶——四桶对应四种工期和四种人,不分类开出的单子没人能认领——然后给个「先做哪一段」的建议,等「可以改了」再动。
驻场这个岗位卖的不是「我会写代码」,是「我在你们生产系统上改东西之前,知道会发生什么」。生产系统里 90% 的「改一下试试」,最后都要靠加班还原。
我没做的事我也照说不减:「一键把 DXF 转三格式」没做(动导出层风险面太大,收益没量化过);改造后出图成功率会到多少、技术确认岗实际能拦下多少错误,这些我没测 / 还没量化,我就给不出数。拿一个估的数当承诺交出去,是把技术债提前转成信任债。