feat(mes): 添加定时同步可生产数量到WMS及BOM项相关标准字段
- 在main.go中添加定时任务每10分钟同步可生产数量到WMS系统 - 为BomItem实体添加relatedStandard字段及相关CRUD方法 - 为InspectionRecord实体添加reportNo、materialCode、materialName等字段 - 更新ent schema确保新字段的验证和默认值设置 - 添加必要的数据库迁移和字段映射逻辑
This commit is contained in:
@@ -10,25 +10,28 @@ import {
|
||||
getSyncStats,
|
||||
getTaskCurrent,
|
||||
getTighteningList,
|
||||
getWip,
|
||||
issueLineMove,
|
||||
occupyLinePoint
|
||||
occupyLinePoint,
|
||||
submitTorque
|
||||
} from '../api'
|
||||
import { getUser } from '../utils/request'
|
||||
|
||||
export const state = reactive({
|
||||
stationNo: 0,
|
||||
screwCount: 0,
|
||||
orderNo: '',
|
||||
currentSn: '',
|
||||
task: null,
|
||||
points: [],
|
||||
moves: [],
|
||||
tightRows: [],
|
||||
wip: [],
|
||||
bindPanel: null,
|
||||
stats: { pendingTorque: 0, pendingQueue: 0 },
|
||||
stepValues: {},
|
||||
stepChecks: {},
|
||||
bindInputs: {},
|
||||
startedAt: '',
|
||||
lastError: ''
|
||||
})
|
||||
|
||||
@@ -44,16 +47,41 @@ export const orderNo = computed({
|
||||
set: (v) => { state.orderNo = v || '' }
|
||||
})
|
||||
export const stationNo = computed(() => state.stationNo)
|
||||
export const screwCount = computed(() => state.screwCount)
|
||||
export const stepValues = computed(() => state.stepValues)
|
||||
export const stepChecks = computed(() => state.stepChecks)
|
||||
export const bindInputs = computed(() => state.bindInputs)
|
||||
export const tightRows = computed(() => state.tightRows)
|
||||
export const wip = computed(() => state.wip)
|
||||
// 进工位(上料)时刻——作业时长起点(P0-3),报工时随载荷上传 MES
|
||||
export const startedAt = computed(() => state.startedAt)
|
||||
|
||||
// 当前步骤(5.1 工艺文件高亮):第一个尚未录入的手填步骤;全部录入后回退到首个步骤
|
||||
export const currentStep = computed(() => {
|
||||
const ms = manualSteps.value
|
||||
const pending = ms.find((s) => {
|
||||
const v = state.stepValues[s.id]
|
||||
return v === null || v === undefined || v === ''
|
||||
})
|
||||
return pending || ms[0] || taskSteps.value[0] || null
|
||||
})
|
||||
export const currentStepId = computed(() => currentStep.value?.id || 0)
|
||||
|
||||
// ---------- 派生数据 ----------
|
||||
export const taskSteps = computed(() => (Array.isArray(state.task?.steps) ? state.task.steps : []))
|
||||
export const manualSteps = computed(() => taskSteps.value.filter((s) => s.collectType === 'MANUAL'))
|
||||
export const autoSteps = computed(() => taskSteps.value.filter((s) => s.collectType === 'AUTO'))
|
||||
// 拧紧工艺步骤(需要拧紧枪的步骤):应拧颗数 = 拧紧步骤数量,每个拧紧步骤录入一条扭矩数据
|
||||
export const torqueSteps = computed(() => autoSteps.value.filter((s) => s.isTorque))
|
||||
export const torqueStepCount = computed(() => torqueSteps.value.length)
|
||||
// 某拧紧步骤已录入的记录(tightRows 已按当前工件 SN 过滤,按 stepId 匹配)
|
||||
export const torqueRowOfStep = (stepId) =>
|
||||
state.tightRows.find((r) => String(r.stepId) === String(stepId))
|
||||
export const torqueDoneCount = computed(
|
||||
() => torqueSteps.value.filter((s) => torqueRowOfStep(s.id)).length
|
||||
)
|
||||
export const missingTorqueSteps = computed(
|
||||
() => torqueSteps.value.filter((s) => !torqueRowOfStep(s.id))
|
||||
)
|
||||
export const orderNos = computed(() => (Array.isArray(state.task?.orderNos) ? state.task.orderNos : []))
|
||||
export const flowName = computed(() => state.task?.flow?.name || '-')
|
||||
export const flowActive = computed(() => !!state.task?.flowActive)
|
||||
@@ -74,10 +102,14 @@ export const beltPoints = computed(() =>
|
||||
export const pointByNo = (no) => state.points.find((p) => p.pointNo === no)
|
||||
|
||||
export const autoTorqueOk = computed(() => state.tightRows.filter((r) => r.result === 'OK').length)
|
||||
// 拧紧完成态:应拧颗数 = 拧紧工艺步骤数;全部拧紧步骤录入且无不合格才算完成。
|
||||
export const autoTorqueState = computed(() => {
|
||||
const total = state.tightRows.length
|
||||
if (total === 0) return { ok: false, text: '待拧紧' }
|
||||
return autoTorqueOk.value >= total ? { ok: true, text: '合格' } : { ok: false, text: '不合格' }
|
||||
const total = torqueStepCount.value
|
||||
if (total === 0) return { ok: true, text: '无拧紧步骤' }
|
||||
if (autoNg.value) return { ok: false, text: '有不合格' }
|
||||
const done = torqueDoneCount.value
|
||||
if (done < total) return { ok: false, text: `待拧紧 ${done}/${total}` }
|
||||
return { ok: true, text: '合格' }
|
||||
})
|
||||
export const manualNg = computed(() =>
|
||||
manualSteps.value.some((s) => {
|
||||
@@ -112,7 +144,8 @@ export const canReport = computed(
|
||||
!bindBlocking.value &&
|
||||
missingSteps.value.length === 0 &&
|
||||
missingChecks.value.length === 0 &&
|
||||
(!autoSteps.value.some((s) => s.isTorque) || autoTorqueState.value.ok)
|
||||
missingTorqueSteps.value.length === 0 &&
|
||||
!autoNg.value
|
||||
)
|
||||
|
||||
// ---------- 判定工具 ----------
|
||||
@@ -152,8 +185,8 @@ export function stepDisplay(s) {
|
||||
export async function loadConfig() {
|
||||
try {
|
||||
const cfg = await getConfig()
|
||||
if (cfg?.stationNo > 0) state.stationNo = cfg.stationNo
|
||||
if (cfg?.screwCount > 0) state.screwCount = cfg.screwCount
|
||||
// 0=上线位、13=下线位为虚拟工位,需允许 stationNo=0(不能用 >0 否则上线位被当未配置)
|
||||
if (cfg && typeof cfg.stationNo === 'number' && cfg.stationNo >= 0) state.stationNo = cfg.stationNo
|
||||
} catch { /* 静默 */ }
|
||||
}
|
||||
|
||||
@@ -185,14 +218,46 @@ export async function loadMoves() {
|
||||
}
|
||||
}
|
||||
|
||||
// loadTight 只加载「当前工件」的拧紧记录(按 SN 过滤):拧紧数据绑定工件,切换工件即切换明细。
|
||||
export async function loadTight() {
|
||||
if (!state.currentSn) {
|
||||
state.tightRows = []
|
||||
return
|
||||
}
|
||||
try {
|
||||
state.tightRows = (await getTighteningList({ limit: 50 })) || []
|
||||
const data = await getTighteningList({ sn: state.currentSn, limit: 100 })
|
||||
state.tightRows = Array.isArray(data) ? data : (data?.list || [])
|
||||
} catch {
|
||||
state.tightRows = []
|
||||
}
|
||||
}
|
||||
|
||||
// submitTorqueStep 录入一条拧紧数据:工件走到拧紧工艺步骤、拧紧枪把扭矩值打入输入框回车时调用。
|
||||
// OK/NG 由该步骤考核标准(扭矩 RANGE)判定;成功后刷新当前工件拧紧记录,返回判定结果。
|
||||
export async function submitTorqueStep(step, torque, angle) {
|
||||
if (!state.currentSn) throw new Error('请先上料工件再拧紧')
|
||||
const t = Number(torque)
|
||||
if (isNaN(t)) throw new Error('扭矩值无效')
|
||||
const torqueCrits = (step?.criteria || []).filter((c) => /扭矩|扭力/.test(c.name || ''))
|
||||
const useCrits = torqueCrits.length ? torqueCrits : (step?.criteria || [])
|
||||
const result = useCrits.length && !useCrits.every((c) => criterionOk(c, t)) ? 'NG' : 'OK'
|
||||
const idx = torqueSteps.value.findIndex((s) => s.id === step.id)
|
||||
const screwNo = 'S' + (step.seq || idx + 1 || 1)
|
||||
await submitTorque({
|
||||
sn: state.currentSn,
|
||||
workOrderNo: state.orderNo || '',
|
||||
stepId: String(step.id),
|
||||
stepName: step.name || '',
|
||||
screwNo,
|
||||
torque: t,
|
||||
angle: Number(angle) || 0,
|
||||
result,
|
||||
operator: operatorName()
|
||||
})
|
||||
await loadTight()
|
||||
return result
|
||||
}
|
||||
|
||||
export async function loadBind() {
|
||||
const code = Number(state.stationNo)
|
||||
if (!state.currentSn || !code) {
|
||||
@@ -216,13 +281,28 @@ export async function loadStats() {
|
||||
} catch { /* 静默 */ }
|
||||
}
|
||||
|
||||
// loadWip 拉取停在本工位的未完工在制品(5.2 默认展示)。
|
||||
// stationNo 传本工位号;上线位(0)/下线位(13) 面板同样复用。
|
||||
export async function loadWip(atStation) {
|
||||
const code = atStation === undefined ? state.stationNo : atStation
|
||||
try {
|
||||
const data = await getWip({ stationNo: code })
|
||||
state.wip = (data && data.list) ? data.list : (Array.isArray(data) ? data : [])
|
||||
} catch {
|
||||
state.wip = []
|
||||
}
|
||||
}
|
||||
|
||||
export function refreshAll() {
|
||||
return Promise.all([loadTask(), loadTight(), loadStats(), loadPoints()])
|
||||
return Promise.all([loadTask(), loadTight(), loadStats(), loadPoints(), loadWip()])
|
||||
}
|
||||
|
||||
// 切换工件:清空步骤录入与绑定缓存,重新加载拧紧/绑定
|
||||
export function setCurrentSn(sn) {
|
||||
state.currentSn = sn || ''
|
||||
const next = sn || ''
|
||||
// 切换到不同工件(或清空)时重置进工位时刻,避免沿用上件的作业起点
|
||||
if (next !== state.currentSn) state.startedAt = ''
|
||||
state.currentSn = next
|
||||
state.stepValues = {}
|
||||
state.stepChecks = {}
|
||||
state.bindInputs = {}
|
||||
@@ -266,3 +346,9 @@ export async function moveOut(sn, toPoint) {
|
||||
}
|
||||
|
||||
export const operatorName = () => user.name || user.username || ''
|
||||
|
||||
// markStationArrival 记录「进工位 / 上料到本工位」时刻(作业时长起点,P0-3)。
|
||||
// 仅在尚未记录时写入,同一工件重复扫码/确认不会重置起点。
|
||||
export function markStationArrival() {
|
||||
if (!state.startedAt) state.startedAt = new Date().toISOString()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user