refactor: 统一术语BOM为物料清单并补充工位扩展能力
主要变更: 1. 后端:重构工位管理逻辑,新增工位自定义扩展能力,将工位号上限调整为999并支持14+虚拟工位 2. 前后端:全量替换"BOM"术语为"物料清单",包括提示语、注释和文档 3. WMS模块:新增AGV任务取消接口与前端页面,对接海康RCS取消任务逻辑 4. 权限与种子数据:新增工位新增权限并更新权限配置 5. 修复错误校验逻辑,优化AGV客户端签名与请求处理
This commit is contained in:
@@ -389,7 +389,7 @@ export const helpInspect = {
|
||||
export const helpProcessCard = {
|
||||
title: '生产流程卡(产品型号级全景流程卡)',
|
||||
overview:
|
||||
'这个菜单做什么用:按**产品型号**全方位展示该型号的完整制造定义,用于工艺交底、审核与客户查阅;与「工件追溯」页里按单个 SN 打印的流程卡互补——后者记的是“这一件实际怎么做的”,本页讲的是“这个型号应该怎么做”。\n\n内容构成(页面按页签展示,打印时全部输出):①工位流程总览——工位组合、每工位绑定的工艺流程、流程状态、步骤数、检验点数、拧紧步骤数、工艺图纸、该型号的历史作业时间;②工艺流程与步骤——逐工位列出每条步骤的采集方式(手工录入/自动采集/无需采集)、是否需检测确认、是否拧紧采集、考核标准(含上下限);③物料清单——该型号的 BOM 明细,按 BOM 名称分组,含图号/名称/规格/单位/管理方式/装配工位/单台用量/损耗率/需求总量;④检验卡项——把所有「需要检测确认」的步骤汇总成检验项清单,含判定标准。\n\n工位组合从哪来:优先取该产品编号最近一张工单的「工位组合」;若该型号还没有工单,则按全产线工位顺序(升序)展示,页面顶部会标注来源。\n\n打印/导出:点「打印 / 导出 PDF」,系统会在新窗口打开排版好的 A4 卡片版式,用浏览器打印即可(选择“另存为 PDF”即导出电子档)。',
|
||||
'这个菜单做什么用:按**产品型号**全方位展示该型号的完整制造定义,用于工艺交底、审核与客户查阅;与「工件追溯」页里按单个 SN 打印的流程卡互补——后者记的是“这一件实际怎么做的”,本页讲的是“这个型号应该怎么做”。\n\n内容构成(页面按页签展示,打印时全部输出):①工位流程总览——工位组合、每工位绑定的工艺流程、流程状态、步骤数、检验点数、拧紧步骤数、工艺图纸、该型号的历史作业时间;②工艺流程与步骤——逐工位列出每条步骤的采集方式(手工录入/自动采集/无需采集)、是否需检测确认、是否拧紧采集、考核标准(含上下限);③物料清单——该型号的物料清单明细,按物料清单名称分组,含图号/名称/规格/单位/管理方式/装配工位/单台用量/损耗率/需求总量;④检验卡项——把所有「需要检测确认」的步骤汇总成检验项清单,含判定标准。\n\n工位组合从哪来:优先取该产品编号最近一张工单的「工位组合」;若该型号还没有工单,则按全产线工位顺序(升序)展示,页面顶部会标注来源。\n\n打印/导出:点「打印 / 导出 PDF」,系统会在新窗口打开排版好的 A4 卡片版式,用浏览器打印即可(选择“另存为 PDF”即导出电子档)。',
|
||||
fields: [
|
||||
{ name: '产品型号', source: '下拉选择,来自「产品型号」页。', purpose: '要查看哪个型号的全景流程', fill: '选定后自动带出产品编号' },
|
||||
{ name: '产品编号', source: '自动带出(也可手工填写,直接按编号生成)。', purpose: '匹配工单、物料清单的关键字', fill: '一般无需手填' },
|
||||
@@ -421,9 +421,9 @@ export const helpQtyReport = {
|
||||
export const helpQuality = {
|
||||
title: '质量检验(过程检 / 完工检)',
|
||||
overview:
|
||||
'质量检验 = 对物料/产品做检验判定并留痕,分「过程检」与「完工检」两个 Tab。来料检在 WMS 库房侧完成,本页不重复。\n\n录入流程:选图号(输入图号或名称远程检索 BOM 料,自动带出物料名称)→ 填报检单号/生产厂家/检验单号 → 上传附件 → 判定合格/不合格 → 保存。\n\n不合格闭环:结论为「不合格」时可当场选择处置方式(退货/返修/退换)并写处置说明;也可在列表操作列「处置」补录,或点「不合格单」一键导出《不合格单.xlsx》(预填本次检验数据)。\n\n查询:图号 / 物料名称 / 报检单号 / 记录日期范围组合筛选,每个框内模糊匹配、多框取交集;记录按时间倒序,后端真分页。',
|
||||
'质量检验 = 对物料/产品做检验判定并留痕,分「过程检」与「完工检」两个 Tab。来料检在 WMS 库房侧完成,本页不重复。\n\n录入流程:选图号(输入图号或名称远程检索物料清单,自动带出物料名称)→ 填报检单号/生产厂家/检验单号 → 上传附件 → 判定合格/不合格 → 保存。\n\n不合格闭环:结论为「不合格」时可当场选择处置方式(退货/返修/退换)并写处置说明;也可在列表操作列「处置」补录,或点「不合格单」一键导出《不合格单.xlsx》(预填本次检验数据)。\n\n查询:图号 / 物料名称 / 报检单号 / 记录日期范围组合筛选,每个框内模糊匹配、多框取交集;记录按时间倒序,后端真分页。',
|
||||
fields: [
|
||||
{ name: '图号', source: '远程检索 BOM 料(/quality/bom-material),也可手填。', purpose: '被检物料的图号(即 WMS 物料档案的图号)', fill: '输入图号或名称关键字选择' },
|
||||
{ name: '图号', source: '远程检索物料清单(/quality/bom-material),也可手填。', purpose: '被检物料的图号(即 WMS 物料档案的图号)', fill: '输入图号或名称关键字选择' },
|
||||
{ name: '物料名称', source: '选图号后自动带出,可手改。', purpose: '被检物料名称', fill: '一般无需手填' },
|
||||
{ name: '报检单号', source: '系统自动生成(RQ+时间戳),可改。', purpose: '本次报检的唯一编号,也是附件挂靠键', fill: '一般无需改,须唯一' },
|
||||
{ name: '生产厂家', source: '手工填写。', purpose: '该物料的生产/供货厂家', fill: '如 XX电气有限公司' },
|
||||
|
||||
@@ -107,7 +107,7 @@
|
||||
<el-tab-pane label="物料清单" name="bom">
|
||||
<el-empty v-if="!card.bomGroups || !card.bomGroups.length" description="该产品型号暂无物料清单" />
|
||||
<div v-for="g in card.bomGroups" :key="g.bomName" class="blk">
|
||||
<div class="blk-t">BOM:{{ g.bomName }}</div>
|
||||
<div class="blk-t">物料清单:{{ g.bomName }}</div>
|
||||
<el-table :data="g.items" border size="small">
|
||||
<el-table-column prop="materialCode" label="图号" min-width="140" show-overflow-tooltip />
|
||||
<el-table-column prop="materialName" label="物料名称" min-width="150" show-overflow-tooltip />
|
||||
|
||||
@@ -71,7 +71,7 @@
|
||||
<el-form :model="dialog" label-width="100px">
|
||||
<el-form-item label="图号">
|
||||
<el-select v-model="dialog.materialCode" filterable remote reserve-keyword
|
||||
placeholder="输入图号或名称检索 BOM 料" :remote-method="searchBom" :loading="bomLoading"
|
||||
placeholder="输入图号或名称检索物料清单" :remote-method="searchBom" :loading="bomLoading"
|
||||
style="width:100%" @change="onBomPick">
|
||||
<el-option v-for="b in bomOptions" :key="b.id"
|
||||
:label="`${b.materialCode} / ${b.materialName}`" :value="b.materialCode" />
|
||||
|
||||
@@ -1,11 +1,23 @@
|
||||
<template>
|
||||
<el-card>
|
||||
<el-alert type="info" :closable="false" style="margin-bottom:12px"
|
||||
title="工位数以数据库为准(仅改名称,不增删工位)。本页为工位总览,每个工位的工艺流程在「关联工位」页维护:在下拉选择启用的工艺流程即绑定到该工位;一个工位只能有一个启用的工艺流程。" />
|
||||
title="工位数量以数据库为准。本页可新增工位(工位号自定义,可扩展到 14、15…)与改名;每个工位的工艺流程在「关联工位」页维护:在下拉选择启用的工艺流程即绑定到该工位;一个工位只能有一个启用的工艺流程。" />
|
||||
|
||||
<div style="margin-bottom:12px">
|
||||
<el-button v-if="can('produce.station:add')" type="primary" @click="openAdd">新增工位</el-button>
|
||||
<span style="margin-left:12px;color:#909399;font-size:12px">虚拟工位(如 0 上线位、13 下线位)类型选「线下位」,不连 PLC、仅记录上下线。</span>
|
||||
</div>
|
||||
|
||||
<el-table :data="rows" border size="small">
|
||||
<el-table-column prop="stationNo" label="工位号" width="90" align="center" />
|
||||
<el-table-column prop="name" label="工位名称" min-width="170" show-overflow-tooltip />
|
||||
<el-table-column label="类型" width="90" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-tag size="small" :type="row.stationType === 'OFFLINE' ? 'info' : 'success'">
|
||||
{{ row.stationType === 'OFFLINE' ? '线下位' : '线上位' }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="绑定工艺流程" min-width="240">
|
||||
<template #default="{ row }">
|
||||
<el-select :model-value="row.flowId" size="small" placeholder="未绑定" @change="(v) => bindFlow(row, v)" style="width:100%">
|
||||
@@ -21,11 +33,23 @@
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<el-dialog v-model="dlg.show" :title="`工位${dlg.stationNo} - 修改名称`" width="420px">
|
||||
<el-dialog v-model="dlg.show" :title="dlg.title" width="440px">
|
||||
<el-form :model="dlg" label-width="90px">
|
||||
<el-form-item label="工位号" required>
|
||||
<el-input-number v-model="dlg.stationNo" :min="0" :max="999" :disabled="!dlg.isAdd" style="width:100%" />
|
||||
<div v-if="dlg.isAdd" style="color:#909399;font-size:12px;line-height:1.5;margin-top:4px">
|
||||
自定义工位号,可与现有工位不连续(如 14、15…);0 为上线位、13 为下线位以外的编号均按物理/虚拟位识别。
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="工位名称" required>
|
||||
<el-input v-model="dlg.name" placeholder="如 一号装配工位" />
|
||||
</el-form-item>
|
||||
<el-form-item label="工位类型">
|
||||
<el-radio-group v-model="dlg.stationType">
|
||||
<el-radio label="LINE">线上位(连 PLC)</el-radio>
|
||||
<el-radio label="OFFLINE">线下位(虚拟,不连 PLC)</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="dlg.show = false">取消</el-button>
|
||||
@@ -50,32 +74,42 @@ const flows = ref([])
|
||||
const rows = computed(() => {
|
||||
return [...stations.value]
|
||||
.sort((a, b) => (a.stationNo || 0) - (b.stationNo || 0))
|
||||
.map((s) => ({ id: s.id, stationNo: s.stationNo, name: s.name, flowId: s.flowId, flowName: s.flowName }))
|
||||
.map((s) => ({ id: s.id, stationNo: s.stationNo, name: s.name, flowId: s.flowId, flowName: s.flowName, stationType: s.stationType }))
|
||||
})
|
||||
|
||||
const dlg = reactive({ show: false, id: 0, stationNo: 1, name: '' })
|
||||
const dlg = reactive({ show: false, isAdd: false, title: '', id: 0, stationNo: 1, name: '', stationType: 'LINE' })
|
||||
|
||||
async function load() {
|
||||
stations.value = (await request.get('/stations')) || []
|
||||
}
|
||||
|
||||
function openAdd() {
|
||||
const used = new Set(stations.value.map((s) => s.stationNo))
|
||||
let next = 14
|
||||
while (used.has(next)) next++
|
||||
Object.assign(dlg, { show: true, isAdd: true, title: '新增工位', id: 0, stationNo: next, name: '', stationType: 'LINE' })
|
||||
}
|
||||
|
||||
function openName(row) {
|
||||
Object.assign(dlg, { show: true, id: row.id, stationNo: row.stationNo, name: row.name })
|
||||
Object.assign(dlg, { show: true, isAdd: false, title: `工位${row.stationNo} - 修改`, id: row.id, stationNo: row.stationNo, name: row.name, stationType: row.stationType || 'LINE' })
|
||||
}
|
||||
|
||||
async function save() {
|
||||
if (!dlg.name) return ElMessage.warning('请输入工位名称')
|
||||
if (dlg.isAdd && stations.value.some((s) => s.stationNo === dlg.stationNo)) {
|
||||
return ElMessage.warning(`工位${dlg.stationNo} 已存在,请换一个工位号`)
|
||||
}
|
||||
await request.post('/stations', {
|
||||
id: dlg.id, stationNo: dlg.stationNo, name: dlg.name
|
||||
id: dlg.id, stationNo: dlg.stationNo, name: dlg.name, stationType: dlg.stationType
|
||||
})
|
||||
ElMessage.success('已保存')
|
||||
ElMessage.success(dlg.isAdd ? '工位已新增' : '已保存')
|
||||
dlg.show = false
|
||||
load()
|
||||
}
|
||||
|
||||
async function bindFlow(row, fid) {
|
||||
try {
|
||||
await request.post('/stations', { id: row.id, stationNo: row.stationNo, name: row.name, flowId: fid })
|
||||
await request.post('/stations', { id: row.id, stationNo: row.stationNo, name: row.name, stationType: row.stationType || 'LINE', flowId: fid })
|
||||
ElMessage.success(fid ? '已绑定工艺流程' : '已解除绑定')
|
||||
} catch {
|
||||
// 拦截器已提示(如绑定到未启用的流程)
|
||||
|
||||
@@ -18,6 +18,7 @@ import (
|
||||
"bj_power_mes/ent/workorder"
|
||||
"bj_power_mes/ent/workpiece"
|
||||
"bj_power_mes/ent/workpieceprocess"
|
||||
"bj_power_mes/internal/logic"
|
||||
"bj_power_mes/internal/svc"
|
||||
)
|
||||
|
||||
@@ -237,7 +238,7 @@ func parseCardSeq(s string) []int {
|
||||
continue
|
||||
}
|
||||
var n int
|
||||
if _, err := fmt.Sscanf(p, "%d", &n); err == nil && n >= 1 && n <= 12 {
|
||||
if _, err := fmt.Sscanf(p, "%d", &n); err == nil && n >= 1 && n <= logic.ProcessSeqMaxStation {
|
||||
out = append(out, n)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,7 +86,7 @@ func ImportBomHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
count++
|
||||
}
|
||||
if count == 0 {
|
||||
httpx.Fail(w, 3111, "未解析到有效 BOM 行(至少需产品编号与物料编码)")
|
||||
httpx.Fail(w, 3111, "未解析到有效物料清单行(至少需产品编号与图号)")
|
||||
return
|
||||
}
|
||||
for _, k := range order {
|
||||
|
||||
@@ -278,14 +278,50 @@ func (s *Service) ListStations(ctx context.Context) ([]*StationVO, error) {
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// SaveStation 维护工位:只改名称/绑定流程。工位主数据由数据库维护,本接口不新增工位。
|
||||
// SaveStation 维护工位:
|
||||
// - 工位号已存在 → 只改名称/类型/绑定流程(不增删工位)
|
||||
// - 工位号不存在 → 新增工位;新增的工位号由用户自定义,允许扩展 14、15…(虚拟/物理均可)
|
||||
//
|
||||
// 工位数量以数据库为准,前端下拉随 station 表自动增减;虚拟工位(0/13/14...)不连 PLC、仅记录。
|
||||
func (s *Service) SaveStation(ctx context.Context, req StationReq, operator string) error {
|
||||
if req.StationNo <= 0 {
|
||||
if req.StationNo < 0 {
|
||||
return errors.New("工位号非法(需 ≥ 0)")
|
||||
}
|
||||
if req.StationNo == 0 && req.Name == "" {
|
||||
return errors.New("工位号非法")
|
||||
}
|
||||
st, err := s.ctx.EntClient.Station.Query().Where(station.StationNo(req.StationNo)).First(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("工位 %d 不存在,请先在工位主数据中维护", req.StationNo)
|
||||
// 新增工位:工位号不存在即创建
|
||||
if req.Name == "" {
|
||||
return errors.New("请填写工位名称")
|
||||
}
|
||||
stype := "LINE"
|
||||
if req.StationType != nil {
|
||||
stype = *req.StationType
|
||||
if stype != "LINE" && stype != "OFFLINE" {
|
||||
return errors.New("工位类型仅支持 LINE/OFFLINE")
|
||||
}
|
||||
}
|
||||
cr := s.ctx.EntClient.Station.Create().
|
||||
SetStationNo(req.StationNo).SetName(req.Name).SetStationType(stype).SetStatus("ENABLED")
|
||||
if req.FlowId != nil && *req.FlowId > 0 {
|
||||
flow, fErr := s.ctx.EntClient.ProcessFlow.Get(ctx, *req.FlowId)
|
||||
if fErr != nil {
|
||||
return errors.New("所选工艺流程不存在")
|
||||
}
|
||||
if flow.Status != "ACTIVE" {
|
||||
return errors.New("该工艺流程已停用,请先启用后再绑定工位")
|
||||
}
|
||||
cr.SetFlowId(*req.FlowId)
|
||||
}
|
||||
created, cErr := cr.Save(ctx)
|
||||
if cErr != nil {
|
||||
return cErr
|
||||
}
|
||||
s.ctx.EventLog.Write(ctx, "station.create", "", operator, "station", "",
|
||||
"新增工位", map[string]any{"stationNo": created.StationNo, "name": created.Name})
|
||||
return nil
|
||||
}
|
||||
// 仅改名称:flowId 不传(nil)保留原绑定;0=解绑;>0=绑定指定启用流程
|
||||
upd := s.ctx.EntClient.Station.UpdateOneID(st.ID).SetName(req.Name)
|
||||
|
||||
@@ -10,8 +10,12 @@ import (
|
||||
// FullProcessSeq 全部 12 个工位的完整组合(按顺序执行)
|
||||
const FullProcessSeq = "1,2,3,4,5,6,7,8,9,10,11,12"
|
||||
|
||||
// ProcessSeqMaxStation 工位组合允许的最大工位号(工位主数据可自行扩展,故放宽上限)。
|
||||
const ProcessSeqMaxStation = 999
|
||||
|
||||
// ParseProcessSeq 解析工位组合字符串为升序去重的工位码列表。
|
||||
// 唯一格式:逗号分隔 "1,3,5" / "10,11,12"。传送带不回走,故组合天然按工位号升序执行。
|
||||
// 工位号取值 1..ProcessSeqMaxStation:工位主数据可扩展到 14、15…(虚拟工位仅记录,不连 PLC)。
|
||||
func ParseProcessSeq(s string) []int {
|
||||
s = strings.TrimSpace(s)
|
||||
if s == "" {
|
||||
@@ -25,7 +29,7 @@ func ParseProcessSeq(s string) []int {
|
||||
continue
|
||||
}
|
||||
n, err := strconv.Atoi(p)
|
||||
if err != nil || n < 1 || seen[n] {
|
||||
if err != nil || n < 1 || n > ProcessSeqMaxStation || seen[n] {
|
||||
continue
|
||||
}
|
||||
seen[n] = true
|
||||
@@ -48,7 +52,7 @@ func NormalizeProcessSeq(s string) string {
|
||||
return strings.Join(parts, ",")
|
||||
}
|
||||
|
||||
// ValidateProcessSeq 校验工位组合:非空、1~12 升序执行。
|
||||
// ValidateProcessSeq 校验工位组合:非空、按工位号升序执行(工位号上限见 ProcessSeqMaxStation)。
|
||||
func ValidateProcessSeq(s string) error {
|
||||
if len(ParseProcessSeq(s)) == 0 {
|
||||
return errors.New("工位组合不能为空,请至少选择一个工位")
|
||||
|
||||
@@ -33,7 +33,7 @@ func (s *Service) Seed(ctx context.Context) error {
|
||||
"produce.qtyreport", "produce.quality", "produce.quality:edit",
|
||||
"produce.plc:send", "produce.product:add", "produce.product:edit", "produce.product:delete",
|
||||
"produce.processflow:add", "produce.processflow:edit", "produce.processflow:delete",
|
||||
"produce.processflow:upload", "produce.station:edit",
|
||||
"produce.processflow:upload", "produce.station:edit", "produce.station:add",
|
||||
}
|
||||
} else if r.code == "INSPECTOR" {
|
||||
codes = []string{"produce.trace", "produce.wip", "produce.torque", "produce.performance", "sys.eventlog",
|
||||
@@ -74,8 +74,7 @@ func (s *Service) Seed(ctx context.Context) error {
|
||||
{"produce.plc", "工位组合下发", "MENU", "/plc-send"},
|
||||
{"produce.torque", "拧紧查询", "MENU", "/torque"},
|
||||
{"produce.processflow", "工艺流程", "MENU", "/process-flow"},
|
||||
{"produce.station", "关联工位", "MENU", "/station"},
|
||||
{"produce.performance", "绩效报表", "MENU", "/performance"},
|
||||
{"produce.station", "关联工位", "MENU", "/station"}, {"produce.performance", "绩效报表", "MENU", "/performance"},
|
||||
{"produce.scan", "手动报工", "MENU", "/scan"},
|
||||
{"produce.trace", "工件追溯", "MENU", "/trace"},
|
||||
{"produce.wip", "在制品", "MENU", "/wip"},
|
||||
@@ -115,7 +114,8 @@ func (s *Service) Seed(ctx context.Context) error {
|
||||
{"produce.processflow:edit", "工艺流程-编辑", "BUTTON", "", "produce.processflow"},
|
||||
{"produce.processflow:delete", "工艺流程-删除", "BUTTON", "", "produce.processflow"},
|
||||
{"produce.processflow:upload", "工艺流程-上传图纸", "BUTTON", "", "produce.processflow"},
|
||||
{"produce.station:edit", "工位-绑定", "BUTTON", "", "produce.station"},
|
||||
{"produce.station:edit", "工位-绑定与改名", "BUTTON", "", "produce.station"},
|
||||
{"produce.station:add", "工位-新增", "BUTTON", "", "produce.station"},
|
||||
{"sys.account:add", "账号-新增", "BUTTON", "", "sys.account"},
|
||||
{"sys.account:edit", "账号-编辑", "BUTTON", "", "sys.account"},
|
||||
{"sys.account:delete", "账号-删除", "BUTTON", "", "sys.account"},
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<title>MES 产线控制</title>
|
||||
<!-- 系统图标:产线齿轮(内联 SVG,避免依赖外部文件) -->
|
||||
<link rel="icon" type="image/svg+xml" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'><rect width='32' height='32' rx='6' fill='%231668dc'/><circle cx='16' cy='16' r='4.2' fill='none' stroke='%23fff' stroke-width='2'/><path d='M16 5v3M16 24v3M5 16h3M24 16h3M8.2 8.2l2.1 2.1M21.7 21.7l2.1 2.1M23.8 8.2l-2.1 2.1M10.3 21.7l-2.1 2.1' stroke='%23fff' stroke-width='2' stroke-linecap='round'/></svg>">
|
||||
<script type="module" crossorigin src="./assets/index-BlmM93M7.js"></script>
|
||||
<script type="module" crossorigin src="./assets/index-DENbNV0h.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="./assets/index-CuDvktnz.css">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
@@ -11,7 +11,7 @@ import (
|
||||
"entgo.io/ent/schema/index"
|
||||
)
|
||||
|
||||
// BomItem 产品 BOM 明细(一个产品型号可并存多份 BOM:不同厂家供货/含半成品等不同料单结构,工单建单时选定一份)
|
||||
// BomItem 产品物料清单明细(一个产品型号可并存多份:不同厂家供货/含半成品等不同料单结构,工单建单时选定一份)
|
||||
type BomItem struct {
|
||||
ent.Schema
|
||||
}
|
||||
@@ -24,7 +24,7 @@ func (BomItem) Fields() []ent.Field {
|
||||
return []ent.Field{
|
||||
field.Int("id").Positive(),
|
||||
field.String("productCode").Default("").MaxLen(64).Comment("产品编码"),
|
||||
field.String("bomName").Default("默认").MaxLen(64).Comment("BOM名称:同一型号多份并存(如 厂家A/厂家B/含半成品),工单按名选用"),
|
||||
field.String("bomName").Default("默认").MaxLen(64).Comment("物料清单名称:同一型号多份并存(如 厂家A/厂家B/含半成品),工单按名选用"),
|
||||
field.String("materialCode").MaxLen(64).Comment("物料编码"),
|
||||
field.String("materialName").Default("").MaxLen(128),
|
||||
field.String("spec").Default("").MaxLen(128),
|
||||
|
||||
Reference in New Issue
Block a user