查验
This commit is contained in:
@@ -20,7 +20,9 @@ createApp({
|
||||
agvCameraError: false,
|
||||
hasAgvCamera: false, // AGV 车体是否有可用相机
|
||||
armCameraError: false,
|
||||
reconnectingDevice: null
|
||||
reconnectingDevice: null,
|
||||
// 环境切换
|
||||
testMode: true,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@@ -38,6 +40,7 @@ createApp({
|
||||
mounted() {
|
||||
this.refresh()
|
||||
this.refreshCameraCapabilities()
|
||||
this.loadEnvMode()
|
||||
setInterval(this.refreshStatus, 3000)
|
||||
this.refreshCams()
|
||||
setInterval(() => this.refreshCams(), 2000)
|
||||
@@ -133,6 +136,36 @@ createApp({
|
||||
} else {
|
||||
window.location.href = '/running'
|
||||
}
|
||||
}
|
||||
},
|
||||
async loadEnvMode() {
|
||||
try {
|
||||
const res = await fetch(API + '/api/config/mode')
|
||||
const data = await res.json()
|
||||
if (data.ok) {
|
||||
this.testMode = data.test_mode
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('加载环境配置失败:', e)
|
||||
}
|
||||
},
|
||||
async toggleEnvMode() {
|
||||
const newMode = !this.testMode
|
||||
try {
|
||||
const res = await fetch(API + '/api/config/mode', {
|
||||
method: 'POST',
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
body: JSON.stringify({test_mode: newMode})
|
||||
})
|
||||
const data = await res.json()
|
||||
if (data.ok) {
|
||||
this.testMode = data.test_mode
|
||||
alert('已切换至: ' + data.label)
|
||||
} else {
|
||||
alert('切换失败: ' + (data.error || '未知错误'))
|
||||
}
|
||||
} catch (e) {
|
||||
alert('切换请求失败: ' + e.message)
|
||||
}
|
||||
},
|
||||
}
|
||||
}).mount('#app')
|
||||
|
||||
@@ -28,6 +28,7 @@ createApp({
|
||||
errorMsg: '',
|
||||
waitingStep: false,
|
||||
stepLabel: '',
|
||||
qrMessage: '所有姿态均未识别到二维码,请手动输入:',
|
||||
// 任务步骤控制开关(机械臂初始化并入AGV移动)
|
||||
agvMoveEnabled: true,
|
||||
qrScanEnabled: true,
|
||||
@@ -36,6 +37,8 @@ createApp({
|
||||
// 速度控制
|
||||
agvSpeed: 1.0,
|
||||
armSpeed: 1000,
|
||||
// 查验
|
||||
inspection: null,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@@ -51,6 +54,14 @@ createApp({
|
||||
}
|
||||
return map[this.missionState] || '未知'
|
||||
},
|
||||
inspectionTotal() {
|
||||
if (!this.inspection || !this.inspection.items) return 0
|
||||
return this.inspection.items.reduce((s, i) => s + (i.inspected || 0), 0)
|
||||
},
|
||||
inspectionTarget() {
|
||||
if (!this.inspection || !this.inspection.items) return 0
|
||||
return this.inspection.items.reduce((s, i) => s + (i.quantify || 0), 0)
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.poll()
|
||||
@@ -101,6 +112,7 @@ createApp({
|
||||
if (data.grid) this.missionGrid = data.grid
|
||||
if (data.point_status) this.pointStatus = data.point_status
|
||||
if (data.machine_status) this.machineStatus = data.machine_status
|
||||
if (data.inspection) this.inspection = data.inspection
|
||||
this.armCameraOpened = data.arm_camera_opened
|
||||
if (this.armCameraOpened && !this.armPreviewUrl) {
|
||||
this.armPreviewUrl = API + '/api/camera/arm_preview'
|
||||
@@ -122,6 +134,11 @@ createApp({
|
||||
this.waitingStep = false
|
||||
}
|
||||
|
||||
// QR 弹窗消息
|
||||
if (data.qr_message) {
|
||||
this.qrMessage = data.qr_message
|
||||
}
|
||||
|
||||
// QR 弹窗(防止提交后重复弹出)
|
||||
if (this.missionState !== 'waiting_qr') {
|
||||
this.qrSubmitting = false
|
||||
@@ -129,6 +146,9 @@ createApp({
|
||||
if (this.missionState === 'waiting_qr' && !this.showQrModal && !this.qrSubmitting) {
|
||||
this.showQrModal = true
|
||||
this.qrValue = ''
|
||||
if (!this.qrMessage) {
|
||||
this.qrMessage = '所有姿态均未识别到二维码,请手动输入:'
|
||||
}
|
||||
}
|
||||
|
||||
// 完成后获取报告
|
||||
@@ -156,6 +176,11 @@ createApp({
|
||||
},
|
||||
async startMission() {
|
||||
if (this.missionState !== 'idle') return
|
||||
// 没有设置报关单时阻止启动(后端也会校验,这里提前友好提示)
|
||||
if (!this.inspection) {
|
||||
alert('⚠️ 请先在「设置→报关单」中选择报关单并点击「开始查验」')
|
||||
return
|
||||
}
|
||||
this.logs = []
|
||||
this.progress = 0
|
||||
this.report = null
|
||||
@@ -186,6 +211,11 @@ createApp({
|
||||
},
|
||||
async startSingleStep() {
|
||||
if (this.missionState !== 'idle') return
|
||||
// 没有设置报关单时阻止启动(后端会校验,这里提前友好提示)
|
||||
if (!this.inspection) {
|
||||
alert('⚠️ 请先在「设置→报关单」中选择报关单并点击「开始查验」')
|
||||
return
|
||||
}
|
||||
this.logs = []
|
||||
this.progress = 0
|
||||
this.report = null
|
||||
|
||||
+113
-55
@@ -82,8 +82,9 @@ createApp({
|
||||
this.refreshAngles()
|
||||
this.loadQrConfigs()
|
||||
this.nav2Timer = setInterval(this.refreshNavStatus, 3000)
|
||||
this.armCameraUrl = API + '/api/camera/arm_preview?t=' + Date.now()
|
||||
},
|
||||
this.armSnapshotUrl = ""; this.armCameraUrl = API + '/api/camera/arm_preview?t=' + Date.now()
|
||||
this.armSnapshotUrl = ""; this.armCameraUrl = API + "/api/camera/arm_preview?t=" + Date.now()
|
||||
},
|
||||
computed: {
|
||||
customsTotalPages() {
|
||||
return Math.max(1, Math.ceil(this.customsTotal / this.customsPageSize))
|
||||
@@ -1203,64 +1204,121 @@ createApp({
|
||||
alert('❌ 复位请求失败: ' + e.message)
|
||||
}
|
||||
},
|
||||
},
|
||||
// ===== 报关单方法 =====
|
||||
async loadCustomsList() {
|
||||
this.customsLoading = true
|
||||
try {
|
||||
const url = API + '/api/customs/list?pageNum=' + this.customsPage + '&pageSize=' + this.customsPageSize
|
||||
const res = await fetch(url)
|
||||
const d = await res.json()
|
||||
if (d.ok && d.data) {
|
||||
const raw = d.data
|
||||
let list = []
|
||||
let total = 0
|
||||
if (raw.rows) { list = raw.rows; total = raw.total || list.length }
|
||||
else if (raw.records) { list = raw.records; total = raw.total || list.length }
|
||||
else if (Array.isArray(raw)) { list = raw; total = list.length }
|
||||
else if (raw.data && raw.data.rows) { list = raw.data.rows; total = raw.data.total || list.length }
|
||||
else if (raw.data && raw.data.records) { list = raw.data.records; total = raw.data.total || list.length }
|
||||
else if (raw.data && Array.isArray(raw.data)) { list = raw.data; total = list.length }
|
||||
this.customsList = list
|
||||
this.customsTotal = total || list.length
|
||||
} else {
|
||||
// ===== 报关单方法 =====
|
||||
async loadCustomsList() {
|
||||
this.customsLoading = true
|
||||
try {
|
||||
const url = API + '/api/customs/list?pageNum=' + this.customsPage + '&pageSize=' + this.customsPageSize + '&customsName=' + encodeURIComponent(this.customsName) + '&customsNo=' + encodeURIComponent(this.customsNo)
|
||||
const res = await fetch(url)
|
||||
const d = await res.json()
|
||||
if (d.ok && d.data) {
|
||||
const raw = d.data
|
||||
let list = []
|
||||
let total = 0
|
||||
if (raw.rows) { list = raw.rows; total = raw.total || list.length }
|
||||
else if (raw.records) { list = raw.records; total = raw.total || list.length }
|
||||
else if (Array.isArray(raw)) { list = raw; total = list.length }
|
||||
else if (raw.data && raw.data.rows) { list = raw.data.rows; total = raw.data.total || list.length }
|
||||
else if (raw.data && raw.data.records) { list = raw.data.records; total = raw.data.total || list.length }
|
||||
else if (raw.data && Array.isArray(raw.data)) { list = raw.data; total = list.length }
|
||||
this.customsList = list
|
||||
this.customsTotal = total || list.length
|
||||
} else {
|
||||
this.customsList = []
|
||||
this.customsTotal = 0
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('加载报关单列表失败', e)
|
||||
this.customsList = []
|
||||
this.customsTotal = 0
|
||||
} finally {
|
||||
this.customsLoading = false
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('加载报关单列表失败', e)
|
||||
this.customsList = []
|
||||
this.customsTotal = 0
|
||||
} finally {
|
||||
this.customsLoading = false
|
||||
}
|
||||
},
|
||||
async selectCustomsRow(item) {
|
||||
const id = item.id || item.customsId || item.customs_id || ''
|
||||
if (!id) return
|
||||
this.selectedCustomsId = id
|
||||
this.selectedCustomsName = item.customsNo || item.customs_no || item.name || item.customsName || item.customs_name || id
|
||||
this.customsMachines = []
|
||||
try {
|
||||
const res = await fetch(API + '/api/customs/machines?customsId=' + encodeURIComponent(id))
|
||||
const d = await res.json()
|
||||
if (d.ok && d.data) {
|
||||
const raw = d.data
|
||||
let machines = []
|
||||
if (raw.rows) { machines = raw.rows }
|
||||
else if (raw.records) { machines = raw.records }
|
||||
else if (raw.data && Array.isArray(raw.data)) { machines = raw.data }
|
||||
else if (Array.isArray(raw)) { machines = raw }
|
||||
else if (Array.isArray(raw.data)) { machines = raw.data }
|
||||
this.customsMachines = machines
|
||||
} else {
|
||||
},
|
||||
async selectCustomsRow(item) {
|
||||
// 新数据结构: { customs:{id,orderId,..}, orderCode, drawCode }
|
||||
const id = (item.customs && item.customs.id) || item.id || item.customsId || item.customs_id || ''
|
||||
if (!id) return
|
||||
this.selectedCustomsId = id
|
||||
this.selectedCustomsName = (item.customs && item.customs.customsCode) || item.orderCode || item.drawCode || id
|
||||
this.customsMachines = []
|
||||
try {
|
||||
const url = API + '/api/customs/machines?customsId=' + encodeURIComponent(id)
|
||||
const res = await fetch(url)
|
||||
const d = await res.json()
|
||||
if (d.ok && d.data) {
|
||||
const raw = d.data
|
||||
let machines = []
|
||||
// customsMachines 返回格式: {"code":"0","data":[{serialNumber,inventoryName,...}]}
|
||||
if (raw.rows) { machines = raw.rows }
|
||||
else if (raw.records) { machines = raw.records }
|
||||
else if (raw.data && Array.isArray(raw.data)) { machines = raw.data }
|
||||
else if (Array.isArray(raw)) { machines = raw }
|
||||
else if (Array.isArray(raw.data)) { machines = raw.data }
|
||||
this.customsMachines = machines
|
||||
} else {
|
||||
this.customsMachines = []
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('加载机器列表失败', e)
|
||||
this.customsMachines = []
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('加载机器列表失败', e)
|
||||
this.customsMachines = []
|
||||
},
|
||||
async startInspection(item) {
|
||||
const id = (item.customs && item.customs.id) || item.id || item.customsId || item.customs_id || ''
|
||||
const name = (item.customs && item.customs.customsCode) || item.orderCode || item.drawCode || id
|
||||
if (!id) return
|
||||
if (!confirm(`确定要对报关单「${name}」开始查验吗?\n点击确定后,运行页将以该报关单的机器进行查验。`)) return
|
||||
try {
|
||||
const res = await fetch(API + '/api/customs/inspection/start', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ customsId: id, customsName: name })
|
||||
})
|
||||
const d = await res.json()
|
||||
if (d.ok) {
|
||||
alert(`✅ 查验已开始!\n报关单: ${name}\n机型: ${d.inspection.items.length} 种\n总数: ${d.inspection.items.reduce((s,i)=>s+i.quantify,0)} 台\n\n请前往「运行」页执行任务。`)
|
||||
// 同时选中该报关单,显示机器列表
|
||||
this.selectedCustomsId = id
|
||||
this.selectedCustomsName = name
|
||||
// 用 inspection items 填充 customsMachines 显示(聚合后)
|
||||
this.customsMachines = d.inspection.items.map(it => ({
|
||||
inventoryCode: it.inventoryCode,
|
||||
inventoryName: it.inventoryName,
|
||||
inventorySpecification: it.spec,
|
||||
serialNumber: '',
|
||||
quantify: it.quantify,
|
||||
inspectionCount: it.inspected,
|
||||
}))
|
||||
} else {
|
||||
alert('❌ 开始查验失败: ' + (d.error || '未知错误'))
|
||||
}
|
||||
} catch (e) {
|
||||
alert('❌ 请求失败: ' + e.message)
|
||||
}
|
||||
},
|
||||
async loadInspectionCounts() {
|
||||
// 轮询查验计数,更新 customsMachines 的 inspectionCount
|
||||
try {
|
||||
const res = await fetch(API + '/api/customs/inspection')
|
||||
const d = await res.json()
|
||||
if (d.ok && d.inspection && this.customsMachines.length) {
|
||||
for (const item of d.inspection.items) {
|
||||
const match = this.customsMachines.find(m => m.inventoryCode === item.inventoryCode)
|
||||
if (match) {
|
||||
match.inspectionCount = item.inspected
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e) {}
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
tab(newVal) {
|
||||
if (newVal === 'customs' && this.customsMachines.length > 0) {
|
||||
// 切换到报关单 tab 时刷新查验计数
|
||||
this.loadInspectionCounts()
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
}).mount('#app')
|
||||
|
||||
Reference in New Issue
Block a user