DeJewelry是一套面向珠宝制作工坊的轻量级生产管理概念系统,核心目标是将接单、备料、镶嵌、抛光、质检到出库的全流程用软件记录与驱动。Node.js凭借事件驱动和非阻塞IO特性,非常适合处理珠宝店同时发生的多工种并发上报与图片传输。借助JavaScript同构优势,前端工单页面与后端业务逻辑可复用部分校验规则,降低小团队开发成本。

系统架构与核心模块划分
在DeJewelry中,我们将系统拆分为接入层、业务层与数据层。接入层使用Express框架提供REST接口,供车间平板上报工序;业务层由多个Node.js模块组成,例如orderService负责解析客户来图,materialService计算银料与宝石损耗;数据层采用MongoDB存储文档型工单,方便随时扩展字段如"表面处理工艺"。这种分层让后续增加3D打印工序时只需新增一个服务文件。
为什么选择Node.js而不是Java或Python?珠宝作坊的并发并不高,但存在大量小文件上传与实时进度推送。Node.js的Stream能边接收边转存,避免内存爆满;配合Socket.IO可把抛光完成事件秒级推给前台销售。若用同步语言,每个上传请求都占一个线程,十几个工人同时拍质检图就容易阻塞。下面的代码展示了基础服务拆分:
// jewelryApp.js 入口文件
const express = require('express');
const http = require('http');
const { OrderService } = require('./service/orderService');
const { MaterialService } = require('./service/materialService');
const app = express();
const server = http.createServer(app);
const orderSvc = new OrderService();
const materialSvc = new MaterialService();
app.post('/api/order', (req, res) => {
const result = orderSvc.create(req.body);
res.json(result);
});
server.listen(3000, () => console.log('DeJewelry running'));
珠宝制作工序的状态机实现
珠宝制作不是线性流水线,而是带回流的状态机。一枚戒指可能镶嵌后发现爪位歪了,要回到"镶嵌"前重做。我们用一个stateMachine模块定义状态:接单、备料、镶嵌、抛光、质检、出库,以及异常回流边。Node.js的面向对象语法虽弱,但用普通对象和switch足以清晰表达。每次状态变更都产生一条事件日志,写入MongoDB的events集合,便于追溯责任。
状态流转必须做幂等校验,防止工人误点两次导致工单跳步。我们在transition方法中先查当前状态,再比对允许的目标集。如下代码演示了简化版流转逻辑,真实项目还可加入角色权限,比如只有质检员能置"出库":
// stateMachine.js
const FLOW = {
'接单': ['备料'],
'备料': ['镶嵌', '接单'],
'镶嵌': ['抛光', '备料'],
'抛光': ['质检'],
'质检': ['出库', '镶嵌'],
'出库': []
};
function transition(current, target) {
const allowed = FLOW[current] || [];
if (!allowed.includes(target)) {
throw new Error('非法工序流转: ' + current + '->' + target);
}
return target;
}
module.exports = { transition };
除了正常流转,DeJewelry还要处理急单插队。我们在工单文档里加priority字段,查询待办列表时按优先级与创建时间排序。Node.js异步查库返回Promise,用async/await写出的代码读起来像同步,降低了新手维护难度。相比把状态写进关系表再用多表join,文档模型让回流日志和工单本身待在同一行,查询速度也更快。
贵金属损耗算法与库存联动
珠宝制作最怕金料算错。DeJewelry的materialService根据款式库中的标准用量,加上历史损耗率动态修正。比如素圈戒标准用金3.2克,车间近一月平均损耗4%,则下单备料自动申请3.33克。Node.js的浮点运算需注意精度,我们统一用整数"毫克"计算再除1000,避开0.1+0.2类问题。算法独立成模块后,既能在下单时调用,也能在月末盘点时批量重算。
库存联动是另一重点。每次备料出库都调用stock.decrease,若库存不足则经Socket.IO发告警给店长。下面的例子展示损耗计算与库存扣减的协作,其中calcRequired返回毫克数:
// materialService.js
class MaterialService {
calcRequired(baseGram, lossRate) {
const baseMg = Math.round(baseGram * 1000);
return Math.round(baseMg * (1 + lossRate));
}
async decrease(stock, gram) {
const need = this.calcRequired(gram, stock.lossRate);
if (stock.leftMg < need) {
throw new Error('库存不足,需补料');
}
stock.leftMg -= need;
return stock.save();
}
}
module.exports = { MaterialService };
实际运行中,我们把损耗率存在每个工匠的子文档里,因为老师傅和新手报废率不同。Node.js处理嵌套文档很自然,无需像SQL那样连三四张表。当系统跑满三个月,就能用这些数据分析哪道工序最费料,进而改进DeJewelry的工艺参数。这种用代码把老师傅经验变成可调参数的做法,正是小珠宝坊数字化的关键一步。