feat&refactor: 完成多模块功能迭代与配置优化

本次提交覆盖多个业务模块的功能完善与体验优化:
1.  **鉴权与配置调整**:
    - 统一JWT滑动续签逻辑,简化Token存储,移除RefreshToken相关冗余代码
    - 调整多项目配置文件中JWT过期时间为3600秒,统一会话闲置窗口
    - 工位配置放开1~12限制,改为仅校验大于0
2.  **术语统一替换**:全链路将"精密件"替换为"电气件",修正物料管理描述
3.  **功能新增**:
    - 新增工位类型、工艺路线与产线点位台账模块
    - 添加工艺PDF预览面板、工位终端代理转发接口
    - 新增操作日志按操作人列表筛选、工位登出日志记录
    - 新增PLC移料指令与产线点位状态管理
4.  **业务流程优化**:
    - 调整BOM物料删除校验逻辑,优化工单备料计算
    - 补充物料图号、检测单号等追溯字段
    - 完善工艺流程图与工位绑定关系说明
    - 优化前端页面文案与交互细节
5.  **代码规范与维护**:
    - 新增通用工具函数与前端静态资源
    - 整理路由权限与中间件逻辑
    - 修复部分接口与配置的不兼容问题
This commit is contained in:
SunYF
2026-09-10 16:59:15 +08:00
parent 6d8bb75696
commit 0ab21b1234
202 changed files with 21397 additions and 3172 deletions
+2 -2
View File
@@ -7,7 +7,7 @@ import (
)
// InboundDetail 入库明细(一张入库单可含多行)
// 结构件记录 batch_no精密件记录 sn_code(逐件一行),quantity 冗余记录该行数量。
// 结构件记录 batch_no电气件记录 sn_code(逐件一行),quantity 冗余记录该行数量。
// 用于入库单正向追溯(查某入库单具体入了哪些批次/SN)。
type InboundDetail struct {
ent.Schema
@@ -16,7 +16,7 @@ type InboundDetail struct {
func (InboundDetail) Fields() []ent.Field {
return []ent.Field{
field.String("inbound_no").Comment("入库单号"),
field.String("sn_code").Optional().Comment("SN(精密件)"),
field.String("sn_code").Optional().Comment("SN(电气件)"),
field.String("batch_no").Optional().Comment("批次号(结构件)"),
field.String("material_code").Comment("物料编码"),
field.Int("quantity").Default(1).Comment("数量"),
+3 -1
View File
@@ -18,13 +18,15 @@ func (InboundOrder) Fields() []ent.Field {
field.String("inbound_type").Default("purchase").Comment("入库类型"),
field.String("material_code").Comment("物料编码"),
field.String("material_name").Optional().Comment("物料名称(冗余)"),
// 管理粒度 1批次(结构件)/2序列号(精密件),冗余自物料档案,便于单单据直接判断
// 管理粒度 1批次(结构件)/2序列号(电气件),冗余自物料档案,便于单单据直接判断
field.Int("manage_mode").Default(1).Comment("管理粒度 1批次/2序列号"),
field.String("batch_no").Optional().Comment("批次号(结构件)"),
field.String("zone_code").Optional().Comment("入库区域"),
field.Int("quantity").Default(0).Comment("本次入库总数量(批次合计或SN条数)"),
field.String("operator").Optional().Comment("操作人"),
field.String("remark").Optional().Comment("备注"),
// 检测单号:入库检报告单号,必填以闭环质量追溯
field.String("inspection_no").Comment("检测单号(入库检报告单号)"),
field.Int64("created_at").DefaultFunc(nowUnix).Comment("创建时间"),
}
}
+3 -1
View File
@@ -27,8 +27,10 @@ func (InspectionRecord) Fields() []ent.Field {
field.Int("pass_qty").Default(0).Comment("合格数量(≤检验数量)"),
// 检测说明 / 不合格原因
field.String("check_desc").Optional().Comment("检测说明(检验项目/方法)"),
field.String("fail_reason").Optional().Comment("不合格原因(不合格时必填)"),
field.String("inspector").Optional().Comment("检验人"),
// 检测单号:对应的检验报告单号(与入库单检测单号关联)
field.String("inspection_no").Optional().Comment("检测单号(检验报告单号)"),
field.String("report_no").Optional().Comment("报检单号(生产报检关联)"),
field.String("remark").Optional().Comment("备注"),
field.Int64("created_at").DefaultFunc(nowUnix),
field.Int64("updated_at").DefaultFunc(nowUnix),
+14 -14
View File
@@ -8,7 +8,7 @@ import (
// Inventory 统一库存台账
//
// 业务背景:原系统把库存拆成「结构件批次(inventory_batch)」与「精密件序列号(serial_number)」
// 业务背景:原系统把库存拆成「结构件批次(inventory_batch)」与「电气件序列号(serial_number)」
// 两张表,导致 锁库存 / 导出 / 汇总 都要分别写两套逻辑,运维成本高且容易不一致。
// 现合并为一张表,用 manage_mode 区分管理粒度,对外提供统一的 锁/查询/汇总/盘点 能力。
//
@@ -16,7 +16,7 @@ import (
// - manage_mode = 1 结构件(批次管理):
// 一条记录 = 一个批次,quantity 表示该批次当前余量,locked_qty 表示已锁定件数。
// 可用量 = quantity - locked_qty。出库/盘点都按"数量"增减。
// - manage_mode = 2 精密件(SN 管理):
// - manage_mode = 2 电气件(SN 管理):
// 一条记录 = 一个单件(SN)quantity 恒为 1locked_qty 为 0 或 1(锁定时=1)。
// 生命周期用 status 字段跟踪:在库/锁定/出库/使用/报废。
// 可用量 = quantity - locked_qty(锁定时为 0)。
@@ -38,8 +38,8 @@ const (
func (Inventory) Fields() []ent.Field {
return []ent.Field{
// 管理粒度:1=结构件(批次) 2=精密件(SN)。决定本行按"数量"还是按"单件"解释。
field.Int("manage_mode").Comment("管理粒度 1=结构件(批次) 2=精密件(SN)"),
// 管理粒度:1=结构件(批次) 2=电气件(SN)。决定本行按"数量"还是按"单件"解释。
field.Int("manage_mode").Comment("管理粒度 1=结构件(批次) 2=电气件(SN)"),
// 品类:1=原材料 2=半成品 3=成品(统一库存主表收编 semi_finished 后新增)
field.Int("category").Default(InvCategoryRaw).Comment("品类 1=原材料 2=半成品 3=成品"),
@@ -48,15 +48,15 @@ func (Inventory) Fields() []ent.Field {
// 物料名称冗余存储,查询时无需再 join 主数据。
field.String("material_name").Optional().Comment("物料名称(冗余,便于直接展示)"),
// 批次号:结构件必填(系统生成)精密件可填所属批次用于分组追溯。
field.String("batch_no").Optional().Comment("批次号(系统生成)精密件可关联所属批次"),
// 序列号:仅精密件填写,作为单件唯一追溯锚点。空字符串不保证唯一,由代码层查重。
field.String("sn_code").Optional().Comment("序列号(SN,仅精密件);空值表示非 SN 行"),
// 批次号:结构件必填(系统生成)电气件可填所属批次用于分组追溯。
field.String("batch_no").Optional().Comment("批次号(系统生成)电气件可关联所属批次"),
// 序列号:仅电气件填写,作为单件唯一追溯锚点。空字符串不保证唯一,由代码层查重。
field.String("sn_code").Optional().Comment("序列号(SN,仅电气件);空值表示非 SN 行"),
// 数量:结构件=批次余量;精密件恒为 1。
field.Int("quantity").Default(0).Comment("数量:结构件=批次余量;精密件=1"),
// 已锁定数量:结构件=锁定件数;精密件=0或1。可用量 = quantity - locked_qty。
field.Int("locked_qty").Default(0).Comment("已锁定数量(库存占用):结构件=件数;精密件=0/1"),
// 数量:结构件=批次余量;电气件恒为 1。
field.Int("quantity").Default(0).Comment("数量:结构件=批次余量;电气件=1"),
// 已锁定数量:结构件=锁定件数;电气件=0或1。可用量 = quantity - locked_qty。
field.Int("locked_qty").Default(0).Comment("已锁定数量(库存占用):结构件=件数;电气件=0/1"),
// 检验状态,由质量检验模块翻转。
field.String("quality_status").Default("未检").Comment("检验状态 未检/合格/不合格"),
@@ -65,8 +65,8 @@ func (Inventory) Fields() []ent.Field {
// 生命周期状态:
// 结构件一律"在库"(锁定看 locked_qty,不靠本字段);
// 精密件随业务流转:在库/锁定/出库/使用/报废。
field.String("status").Default("在库").Comment("生命周期:在库/锁定/出库/使用/报废(精密件用;结构件恒在库)"),
// 电气件随业务流转:在库/锁定/出库/使用/报废。
field.String("status").Default("在库").Comment("生命周期:在库/锁定/出库/使用/报废(电气件用;结构件恒在库)"),
// 生产日期(结构件批次用)。
field.String("production_date").Optional().Comment("生产日期"),
+4 -2
View File
@@ -10,7 +10,7 @@ import (
// 全系统物料的唯一定义来源,入库/出库/库存/检验都通过 material_code 关联本表。
// 管理粒度由 manage_mode 决定,贯穿整个库存链路:
// - manage_mode=1 结构件:按"批次"管理,一次到货入一批,库存以 quantity 计数;
// - manage_mode=2 精密件:按"SN 序列号"逐件管理,库存以单件行计数,可单件追溯。
// - manage_mode=2 电气件:按"SN 序列号"逐件管理,库存以单件行计数,可单件追溯。
// 品类由 item_type 区分(与库存主表 inventories.category 对应):
// - item_type=1 原材料 / 2 半成品 / 3 成品(成品即"产品型号"档案,MES 实时从本表拉取,
// 消除两系统双录——2026-09-08 并表定稿)。
@@ -29,12 +29,14 @@ func (Material) Fields() []ent.Field {
field.String("description").Optional().Comment("描述"),
// 品类:1=原材料 2=半成品 3=成品(成品=产品型号档案)
field.Int("item_type").Default(1).Comment("品类 1原材料/2半成品/3成品"),
// 管理粒度:1=批次管理(结构件) 2=序列号管理(精密件)
// 管理粒度:1=批次管理(结构件) 2=序列号管理(电气件)
field.Int("manage_mode").Default(1).Comment("管理粒度 1批次/2序列号"),
field.Bool("is_batch_managed").Default(false).Comment("是否批次管理"),
field.Bool("is_serial_managed").Default(false).Comment("是否序列号管理"),
// 所属物料模板(种类)
field.String("template_code").Optional().Comment("物料模板编码(物料种类)"),
// 图号(零件图纸编号,用于装配定位与追溯,可选)
field.String("drawing_no").Optional().Comment("图号(图纸编号)"),
// 启用状态:停用后不在新建工单/备料下拉出现(对齐 MES 产品型号 isActive
field.Bool("is_active").Default(true).Comment("是否启用"),
field.Int64("created_at").DefaultFunc(nowUnix).Comment("创建时间"),
+1 -1
View File
@@ -16,7 +16,7 @@ type OutboundDetail struct {
func (OutboundDetail) Fields() []ent.Field {
return []ent.Field{
field.String("outbound_no").Comment("出库单号"),
field.String("sn_code").Optional().Comment("SN(精密件)"),
field.String("sn_code").Optional().Comment("SN(电气件)"),
field.String("batch_no").Optional().Comment("批次号(结构件)"),
field.String("material_code").Comment("物料编码"),
field.Int("quantity").Default(1).Comment("数量"),