From ab39091ad43a27ea7adb51ee5ca4c63d33350145 Mon Sep 17 00:00:00 2001 From: "han\\hanst" Date: Mon, 18 May 2026 13:34:59 +0800 Subject: [PATCH] init --- src/api/rack/closedLoop.js | 20 + src/views/modules/rack/execution-control.vue | 97 +++- .../modules/rack/external-device-config.vue | 220 +++++++++ .../modules/rack/package-label-management.vue | 428 ++++++++++++++++++ 4 files changed, 761 insertions(+), 4 deletions(-) create mode 100644 src/views/modules/rack/external-device-config.vue create mode 100644 src/views/modules/rack/package-label-management.vue diff --git a/src/api/rack/closedLoop.js b/src/api/rack/closedLoop.js index 686becb..5a257e6 100644 --- a/src/api/rack/closedLoop.js +++ b/src/api/rack/closedLoop.js @@ -79,5 +79,25 @@ export const productionComplete = (jobCode, data) => createAPI('/rack/closedLoop export const listManualRecord = (data) => createAPI('/rack/closedLoop/manual/list', 'post', data || {}) export const saveManualRecord = (data) => createAPI('/rack/closedLoop/manual/save', 'post', data) +export const listExternalDevice = (data) => createAPI('/rack/closedLoop/device/list', 'post', data || {}) +export const saveExternalDevice = (data) => createAPI('/rack/closedLoop/device/save', 'post', data) +export const updateExternalDevice = (data) => createAPI('/rack/closedLoop/device/update', 'post', data) +export const deleteExternalDevice = (deviceId) => createAPI(`/rack/closedLoop/device/delete/${deviceId}`, 'post', {}) +export const deleteExternalDeviceByCode = (deviceCode) => createAPI('/rack/closedLoop/device/delete-by-code', 'post', { deviceCode }) + +export const ingestPlcEvent = (data) => createAPI('/rack/closedLoop/plc/ingest', 'post', data || {}) +export const listPlcStatus = () => createAPI('/rack/closedLoop/plc/status', 'get', {}) + +export const listPackageOrder = (data) => createAPI('/rack/closedLoop/package/order/list', 'post', data || {}) +export const savePackageOrder = (data) => createAPI('/rack/closedLoop/package/order/save', 'post', data || {}) +export const updatePackageOrder = (data) => createAPI('/rack/closedLoop/package/order/update', 'post', data || {}) +export const deletePackageOrderByNo = (packageNo) => createAPI('/rack/closedLoop/package/order/delete-by-no', 'post', { packageNo }) +export const listLabelTemplate = (data) => createAPI('/rack/closedLoop/package/template/list', 'post', data || {}) +export const saveLabelTemplate = (data) => createAPI('/rack/closedLoop/package/template/save', 'post', data || {}) +export const updateLabelTemplate = (data) => createAPI('/rack/closedLoop/package/template/update', 'post', data || {}) +export const deleteLabelTemplateByCode = (templateCode) => createAPI('/rack/closedLoop/package/template/delete-by-code', 'post', { templateCode }) +export const printPackageLabel = (data) => createAPI('/rack/closedLoop/package/label/print', 'post', data || {}) +export const listLabelPrintLog = (data) => createAPI('/rack/closedLoop/package/print-log/list', 'post', data || {}) + export const traceQuery = (data) => createAPI('/rack/closedLoop/trace/query', 'post', data || {}) export const reportOverview = () => createAPI('/rack/closedLoop/report/overview', 'get', {}) diff --git a/src/views/modules/rack/execution-control.vue b/src/views/modules/rack/execution-control.vue index 8506914..de0d8a0 100644 --- a/src/views/modules/rack/execution-control.vue +++ b/src/views/modules/rack/execution-control.vue @@ -37,8 +37,24 @@ style="width: 240px" @keyup.enter.native="onRackScanned" /> + + + + + @@ -66,6 +82,32 @@ 模拟全部剩余池 任务完工 + + + + + + + + + + + + + + + + + @@ -122,6 +164,7 @@ import { listJob, listRack, + listPlcStatus, productionView, productionStart, productionUpHang, @@ -139,6 +182,7 @@ export default { jobScanCode: '', materialScanCode: '', rackScanCode: '', + batchDownHangCode: '', selectedJobCode: '', selectedRackCode: '', selectedBindingRackCode: '', @@ -150,7 +194,10 @@ export default { simulateSubmitting: false, completeSubmitting: false, autoRefresh: true, - timer: null + timer: null, + plcStatusRows: [], + plcStatusLoading: false, + plcStatusTimer: null } }, computed: { @@ -168,7 +215,9 @@ export default { }, canDownHang () { const hasAnyActiveRack = this.getActiveRackCodes().length > 0 - return !!this.selectedJobCode && hasAnyActiveRack && !!(this.selectedRackCode || this.rackScanCode) && !this.downHangSubmitting + const hasRackCode = !!(this.selectedRackCode || this.rackScanCode) + const hasBatchCode = !!this.batchDownHangCode + return !!this.selectedJobCode && hasAnyActiveRack && (hasRackCode || hasBatchCode) && !this.downHangSubmitting }, canComplete () { const hasAnyActiveRack = this.getActiveRackCodes().length > 0 @@ -223,14 +272,29 @@ export default { return '先点“开始生产”下达任务,再扫码来料和挂具,校验通过后自动上挂。' } return '请先扫码来料,再扫码挂具;校验通过后会自动上挂。全部来料完成后再点“任务完工”。' + }, + plcOfflineCount () { + return (this.plcStatusRows || []).filter(item => item && !item.online).length + }, + plcStatusSummary () { + const rows = (this.plcStatusRows || []).filter(item => item && !item.online) + if (!rows.length) { + return '' + } + const names = rows.slice(0, 3).map(item => `${item.deviceCode || '未知设备'}${item.offlineReason ? `(${item.offlineReason})` : ''}`) + const extra = rows.length > 3 ? ` 等${rows.length}台` : '' + return `${names.join('、')}${extra},请检查采集链路或使用手工补录兜底。` } }, mounted () { this.refreshBaseOptions() this.startTimer() + this.loadPlcStatus() + this.startPlcStatusTimer() }, beforeDestroy () { this.stopTimer() + this.stopPlcStatusTimer() }, methods: { async refreshBaseOptions () { @@ -254,6 +318,7 @@ export default { this.selectedJobCode = this.jobScanCode this.materialScanCode = '' this.rackScanCode = '' + this.batchDownHangCode = '' this.selectedRackCode = '' await this.onJobChange() }, @@ -380,11 +445,12 @@ export default { return } this.syncScanCodes() + const hasBatchCode = !!String(this.batchDownHangCode || '').trim() if (!this.selectedRackCode && this.getActiveRackCodes().length === 1) { this.selectedRackCode = this.getActiveRackCodes()[0] } - if (!this.selectedRackCode) { - this.$message.warning('请先扫码要下挂的挂具') + if (!this.selectedRackCode && !hasBatchCode) { + this.$message.warning('请先扫码挂具码,或扫码批次编码执行下挂') return } const downRackCode = this.selectedRackCode @@ -393,6 +459,7 @@ export default { const resp = await productionDownHang({ jobCode: this.selectedJobCode, rackCode: downRackCode, + batchCode: hasBatchCode ? this.batchDownHangCode : '', operatorName: this.operatorName }) this.assertApiSuccess(resp, '下挂失败') @@ -400,6 +467,7 @@ export default { this.$message.success('下挂成功') this.selectedRackCode = '' this.rackScanCode = '' + this.batchDownHangCode = '' } catch (e) { this.$message.error(this.resolveErrorMessage(e)) } finally { @@ -694,6 +762,27 @@ export default { this.timer = null } }, + async loadPlcStatus () { + this.plcStatusLoading = true + try { + const { data } = await listPlcStatus() + this.plcStatusRows = data.rows || [] + } finally { + this.plcStatusLoading = false + } + }, + startPlcStatusTimer () { + this.stopPlcStatusTimer() + this.plcStatusTimer = setInterval(() => { + this.loadPlcStatus() + }, 10000) + }, + stopPlcStatusTimer () { + if (this.plcStatusTimer) { + clearInterval(this.plcStatusTimer) + this.plcStatusTimer = null + } + }, formatDateTime (v) { if (!v) return '-' let date = null diff --git a/src/views/modules/rack/external-device-config.vue b/src/views/modules/rack/external-device-config.vue new file mode 100644 index 0000000..80032fd --- /dev/null +++ b/src/views/modules/rack/external-device-config.vue @@ -0,0 +1,220 @@ + + + + + diff --git a/src/views/modules/rack/package-label-management.vue b/src/views/modules/rack/package-label-management.vue new file mode 100644 index 0000000..2bf95f3 --- /dev/null +++ b/src/views/modules/rack/package-label-management.vue @@ -0,0 +1,428 @@ + + + + +