|
|
<script setup lang="ts"> import { list as listMatrix } from 'apis/matrix' import { getListByMatrixId, update } from 'apis/matrixCraft' import { getDeviceStatus, getSprayStatus } from 'apis/system' import route from 'assets/images/route.png' import route_active from 'assets/images/route_active.png' import route_horizontal_active from 'assets/images/route_horizontal2.png' import route_horizontal from 'assets/images/route_horizontal.png' import route_vertical_active from 'assets/images/route_vertical2.png' import route_vertical from 'assets/images/route_vertical.png' import Edit from 'components/martixCraft/Edit/index.vue' import TrayGraph from 'components/spray/trayGraph/index.vue' import { FtMessage } from 'libs/message' import { socket } from 'libs/socket' import { colors, sendControl } from 'libs/utils' import { useSystemStore } from 'stores/useSystemStore' import { nextTick, onMounted, onUnmounted, ref } from 'vue'
const systemStore = useSystemStore()
onMounted(async () => { socket.init(sprayPointReceiveMessage, 'spray_point') socket.init(finishMessage, 'cmd_response') await getMatrixList() await getDeviceStatus().then((res: any) => { systemStore.updateSystemStatus(res) if (systemStore.systemStatus.spraying) { FtMessage.info('正在喷涂中...') maskVisible.value = true getSpraying() } }) })
onUnmounted(() => { socket.unregisterCallback(sprayPointReceiveMessage, 'spray_point') socket.unregisterCallback(finishMessage, 'cmd_response') })
const matrixList = ref<{ name: string, id: number }[]>([]) const getMatrixList = async () => { const res = await listMatrix({ pageNum: 1, pageSize: 100, matrixName: '' }) matrixList.value = res.list }
const matrixCraftList = ref<any>([]) const matrixChange = async (value: number) => { form.value.matrixCraftId = undefined matrixCraftList.value = await getListByMatrixId(value) }
const matrixCraftChange = (value: number) => { form.value = { ...form.value, ...matrixCraftList.value.find((item: { id: number }) => item.id === value), } // formRef.value.validate()
}
const getSpraying = async () => { const res: any = await getSprayStatus() const sprayTaskSprayedList = res.sprayTaskSprayedList cmdId = res.cmdId
form.value = { ...res.sprayParams, position: [{ select: false }, { select: false }, { select: false }, { select: false }], } res.sprayParams.position.forEach((p: any) => { form.value.position[p.index] = p nextTick(() => { console.log('x', p.x1 * 5) console.log('y', p.y1 * 5) console.log('width', (p.x1 + p.x2) * 5) console.log('height', (p.y1 + p.y2) * 5) sprayRefs.value[p.index].updateSelection(p.x1 * 5, p.y1 * 5, (p.x2 - p.x1) * 5, (p.y2 - p.y1) * 5) }) }) sprayTaskSprayedList.forEach((task: any) => { nextTick(() => { drawLine(task.index, { x: task.sprayedPoints.x * 5, y: task.sprayedPoints.y * 5 }, task.number) }) }) }
const sprayRefs = ref<any>([])
const infoVisible = ref(false)
const updateParam = () => { updateForm.value = { motorZHeight: form.value.motorZHeight, // 高度
gasPressure: form.value.gasPressure, // Mpa兆帕
volume: form.value.volume, // 单位uL微升
highVoltage: form.value.highVoltage, // 是否打开高压
highVoltageValue: form.value.highVoltageValue, // 高压值
movingSpeed: form.value.movingSpeed, // 毫米
} infoVisible.value = true }
const updateFormRef = ref() const submitParam = async () => { updateFormRef.value.validate(async (valid: boolean) => { if (!valid) { return } const params = { cmdCode: 'matrix_spray_change_param', cmdId: '', params: updateForm.value, } form.value = { ...form.value, ...updateForm.value, } await sendControl(params) infoVisible.value = false }) }
const form = ref<SprayForm>({ matrixId: undefined, matrixCraftId: undefined, matrixPathType: 'horizontal', // 路径类型
motorZHeight: undefined, // 高度
gasPressure: undefined, // Mpa兆帕
volume: undefined, // 单位uL微升
highVoltage: true, // 是否打开高压
highVoltageValue: undefined, // 高压值
spacing: undefined, // 毫米
movingSpeed: undefined, // 移动速度
times: undefined, // 喷涂遍数
position: [ { select: true, x1: 0, y1: 0, x2: 25, y2: 75, index: 0 }, { select: false, x1: 0, y1: 0, x2: 25, y2: 75, index: 1 }, { select: false, x1: 0, y1: 0, x2: 25, y2: 75, index: 2 }, { select: false, x1: 0, y1: 0, x2: 25, y2: 75, index: 3 }, ], })
const updateForm = ref<SprayUpdateForm>({ motorZHeight: undefined, // 高度
gasPressure: undefined, // Mpa兆帕
volume: undefined, // 单位uL微升
highVoltage: true, // 是否打开高压
highVoltageValue: undefined, // 高压值
movingSpeed: undefined, // 移动速度
})
const formRef = ref()
const checkPosition = () => { let position = form.value.position.filter((item: { select: boolean }) => item.select) if (!position.length) { FtMessage.error('至少选择一个玻片') return false } position = form.value.position .map((item: any, index: number) => { return { ...item, ...sprayRefs.value[index].getSelection(), index, } }) .filter((item: { select: boolean }) => item.select)
for (let i = 0; i < position.length; i++) { const p = position[i] if (p.x1 < 0 || p.y1 < 0 || p.x2 < 0 || p.y2 < 0 || p.x1 > 25 || p.y1 > 75 || p.x2 > 25 || p.y2 > 75) { FtMessage.error(`玻片${p.index + 1}喷涂区域超出玻片范围`) return false } } return position }
const maskVisible = ref(false)
const startWork = async () => { formRef.value.validate(async (valid: boolean) => { console.log('valid', valid) if (!valid) { FtMessage.error('请检查参数配置') }
const position = checkPosition() if (!position) { return } cmdId = Date.now().toString() const params = { cmdCode: 'matrix_spray_start', cmdId, params: { ...form.value, position, }, }
maskVisible.value = true await sendControl(params) currentSpeed = Number(form.value.movingSpeed) }) }
const pauseWork = async () => { const params = { cmdCode: 'matrix_spray_pause', cmdId: '', } await sendControl(params) }
const continueWork = async () => { const params = { cmdCode: 'matrix_spray_continue', cmdId: '', params: { motorZHeight: form.value.motorZHeight, // 高度
gasPressure: form.value.gasPressure, // Mpa兆帕
volume: form.value.volume, // 单位uL微升
highVoltage: form.value.highVoltage, // 是否打开高压
highVoltageValue: form.value.highVoltageValue, // 高压值
movingSpeed: form.value.movingSpeed, // 毫米
}, } await sendControl(params) currentSpeed = Number(form.value.movingSpeed) }
const stopWork = async () => { const params = { cmdCode: 'matrix_spray_stop', cmdId: '', } await sendControl(params) form.value.position.forEach((item, index) => { if (item.select) { sprayRefs.value[index].clearLines() } }) }
let currentSpeed = 0 console.log(currentSpeed) // let poll: ReturnType<typeof setInterval>
let cmdId = '' const sprayPointReceiveMessage = (data: any) => { if (data.cmdId === cmdId) { const { currentPoint, index, number } = data drawLine(index, { x: currentPoint.x * 5, y: currentPoint.y * 5 }, number) // drawLine(index, { x: nextPoint.x * 5, y: nextPoint.y * 5 }, number)
}
// if (poll) {
// clearInterval(poll)
// }
// const { currentPoint, nextPoint, index } = data
// // 计算累加的mm
// const moveDistance = currentSpeed / 2
// // y轴移动
// if (currentPoint.x === nextPoint.x) {
// let currentY = currentPoint.y
// poll = setInterval(() => {
// currentY += moveDistance
// if (currentY >= nextPoint.y) {
// clearInterval(poll)
// }
// drawLine(index, { x: currentPoint.x * 5, y: currentY * 5 })
// }, 500)
// }
// else if (currentPoint.y === nextPoint.y) {
// // x轴移动
// let currentX = currentPoint.x
// poll = setInterval(() => {
// currentX += moveDistance
// if (currentX >= nextPoint.x) {
// clearInterval(poll)
// }
// drawLine(index, { x: currentX * 5, y: currentPoint.y * 5 })
// }, 500)
// }
}
const finishMessage = (data: any) => { if (data.cmdId === cmdId) { if (data.status === 'fail') { FtMessage.error(data.title) } if (data.status === 'success') { FtMessage.success('喷涂执行成功') } if (data.status === 'spray_task_finish') { form.value.position.forEach((item, index) => { if (item.select) { sprayRefs.value[index].clearLines() } }) maskVisible.value = false } } }
const drawLine = async (index: number, point: { x: number, y: number }, number: number) => { console.log('drawLine', sprayRefs.value[index], index, point, number) await nextTick(() => { if (!sprayRefs.value[index].hasLine(number)) { sprayRefs.value[index].addLine(colors[number]) } sprayRefs.value[index].updateLine(point, number, colors[number]) }) }
const updateFormRules = { motorZHeight: [ { required: true, trigger: 'blur', validator: (rule: any, value: any, callback: any) => { setTimeout(() => { if (!value) { callback(new Error('请输入高度')) } else if (value < 15) { callback(new Error('最小安全高度为15mm')) } else { callback() } }, 500) }, }, ], gasPressure: [{ required: true, message: '请输入氮气气压', trigger: 'blur' }], volume: [{ required: true, trigger: 'blur', validator: (rule: any, value: any, callback: any) => { if (!value) { callback(new Error('请输入基质流速')) } else if (value > 100) { callback(new Error('基质流速最大为100 uL/min')) } else { callback() } } }], highVoltageValue: [ { required: true, trigger: 'blur', validator: (rule: any, value: any, callback: any) => { if (form.value.highVoltage && !value) { callback(new Error('请输入电压')) } else if (value > 6000) { callback(new Error('最大电压为6000V')) } else { callback() } }, }, ], movingSpeed: [{ required: true, trigger: 'blur', validator: (rule: any, value: any, callback: any) => { if (!value) { callback(new Error('请输入移动速度')) } else if (value > 30) { callback(new Error('移动速度最大为30 mm/s')) } else { callback() } } }], }
const rules = { matrixId: [{ required: true, message: '请选择基质', trigger: 'change' }], spacing: [{ required: true, message: '请输入间距', trigger: 'blur' }], times: [{ required: true, message: '请输入喷涂次数', trigger: 'blur' }], ...updateFormRules, }
const addVisible = ref(false) const ok = async () => { addVisible.value = false matrixCraftList.value = await getListByMatrixId(form.value.matrixId as number) }
const upDateLoading = ref(false) const updateCraft = async () => { if (!form.value.matrixCraftId) { FtMessage.error('请选择工艺') return } upDateLoading.value = true const params = { ...form.value, id: form.value.matrixCraftId, } await update(params) FtMessage.success('保存成功') upDateLoading.value = false }
const formData = ref({}) const addCraft = () => { console.log(form.value) formData.value = { ...form.value, id: undefined, name: undefined, } console.log(formData.value) addVisible.value = true } </script>
<template> <div class="spray-container"> <el-form ref="formRef" label-width="120" :model="form" :rules="rules"> <div class="button-box"> <ft-button type="primary" :disabled="systemStore.systemStatus.spraying" @click="startWork"> 开始喷涂 </ft-button> <ft-button type="primary" :disabled="!systemStore.systemStatus.spraying" @click="updateParam"> 调整参数 </ft-button> <ft-button type="primary" :disabled="!systemStore.systemStatus.suspendable" @click="pauseWork"> 暂停喷涂 </ft-button> <ft-button type="primary" :disabled="!systemStore.systemStatus.paused" @click="continueWork"> 继续喷涂 </ft-button> <ft-button type="primary" :disabled="!systemStore.systemStatus.spraying" @click="stopWork"> 结束喷涂 </ft-button> </div> <div class="spray-box"> <div class="spray-left"> <div style="display: flex; position: relative;height: fit-content"> <div v-show="maskVisible" class="mask-box" /> <div v-for="(p, index) in form.position" :key="index" style="display: flex; flex-direction: column; align-items: center" > <p class="tray-name"> 玻片{{ index + 1 }} </p> <TrayGraph ref="sprayRefs" :key="index" :container="`spray-${index + 1}`" :select="p.select" /> <el-checkbox v-model="p.select" /> </div> </div> </div> <div class="spray-form"> <el-form-item label="基质" prop="matrixId"> <el-select v-model="form.matrixId" placeholder="" @change="matrixChange"> <el-option v-for="item in matrixList" :key="item.id" :label="item.name" :value="item.id" /> </el-select> </el-form-item> <el-form-item label="工艺"> <el-select v-model="form.matrixCraftId" placeholder="" @change="matrixCraftChange"> <el-option v-for="item in matrixCraftList" :key="item.id" :label="item.name" :value="item.id" /> </el-select> </el-form-item> <el-form-item label="喷涂路线"> <div class="route-img"> <img style="margin-left: 20px" :src="form.matrixPathType === 'horizontal' ? route_horizontal_active : route_horizontal" alt="" @click="form.matrixPathType = 'horizontal'" > <img style="margin: 0 20px" :src="form.matrixPathType === 'vertical' ? route_vertical_active : route_vertical" alt="" @click="form.matrixPathType = 'vertical'" > <img :src="form.matrixPathType === 'grid' ? route_active : route" alt="" @click="form.matrixPathType = 'grid'" > </div> </el-form-item> <el-form-item label="Z轴高度" prop="motorZHeight"> <el-input v-model="form.motorZHeight" type="number" /> <span class="unit-text">mm</span> </el-form-item> <el-form-item label="氮气气压" prop="gasPressure"> <el-input v-model="form.gasPressure" type="number" /> <span class="unit-text">Mpa</span> </el-form-item> <el-form-item label="基质流速" prop="volume"> <el-input v-model="form.volume" type="number" /> <span class="unit-text">uL/min</span> </el-form-item> <el-form-item label="是否加电" prop="highVoltageValue"> <div class="voltage-box"> <el-switch v-model="form.highVoltage" /> <el-input v-show="form.highVoltage" v-model="form.highVoltageValue" type="number" class="voltage-input" /> <span v-show="form.highVoltage" class="unit-text"> V</span> </div> </el-form-item> <el-form-item label="移动速度" prop="movingSpeed"> <el-input v-model="form.movingSpeed" type="number" /> <span class="unit-text">mm/s</span> </el-form-item> <el-form-item label="间距" prop="spacing"> <el-input v-model="form.spacing" type="number" /> <span class="unit-text">mm</span> </el-form-item> <el-form-item label="喷涂次数" prop="times"> <el-input v-model="form.times" type="number" /> <span class="unit-text">次</span> </el-form-item> <el-form-item> <div style="display: flex; justify-content: center;width: 100%"> <ft-button type="primary" :loading="upDateLoading" @click="updateCraft"> 更新工艺 </ft-button> <ft-button type="primary" @click="addCraft"> 保存到新工艺 </ft-button> </div> </el-form-item> </div> </div> </el-form> <el-drawer v-model="infoVisible" title="调整参数" direction="rtl" :close-on-click-modal="false"> <el-form ref="updateFormRef" :model="updateForm" label-width="auto" style="display: flex; flex-direction: column; justify-content: center" :rules="updateFormRules"> <div> <el-form-item label="Z轴高度" prop="motorZHeight"> <el-input v-model="updateForm.motorZHeight" type="number" /> <span class="unit-text">mm</span> </el-form-item> <el-form-item label="氮气气压" prop="gasPressure"> <el-input v-model="updateForm.gasPressure" type="number" /> <span class="unit-text">Mpa</span> </el-form-item> <el-form-item label="基质流速" prop="volume"> <el-input v-model="updateForm.volume" type="number" /> <span class="unit-text">uL/min</span> </el-form-item> <el-form-item label="是否加电" prop="highVoltageValue"> <div class="voltage-box"> <el-switch v-model="updateForm.highVoltage" /> <el-input v-show="updateForm.highVoltage" v-model="updateForm.highVoltageValue" type="number" class="voltage-input" /> <span v-show="updateForm.highVoltage" class="unit-text"> V</span> </div> </el-form-item> <el-form-item label="移动速度" prop="movingSpeed"> <el-input v-model="updateForm.movingSpeed" type="number" /> <span class="unit-text">mm/s</span> </el-form-item> <el-form-item> <div style="display: flex; justify-content: center; width: 100%"> <ft-button type="primary" @click="submitParam"> 确定 </ft-button> </div> </el-form-item> </div> </el-form> </el-drawer> <Edit v-if="addVisible" :matrix-list :form-data other-page @ok="ok" @cancel="addVisible = false" /> </div> </template>
<style scoped lang="scss"> .spray-container { width: 100%; height: 100%; .el-form { width: 100%; height: 100%; display: flex; flex-direction: column; justify-content: space-between; overflow: auto; .button-box { display: flex; justify-content: center; } .spray-box { display: flex; justify-content: space-between; .spray-left { display: flex; flex-direction: column; justify-content: center } .spray-form { display: flex; flex-direction: column; justify-content: center; } }
} } .el-input, .el-select { width: 400px; margin: 0 40px; } .unit-text { font-size: 40px; color: #0349a8; font-weight: 500; } .select-box { display: flex; margin: 40px; } .route-img { display: flex; img { width: 70px; } }
.voltage-box { display: flex; align-items: center; margin-left: 40px; height: 100px; .voltage-input { width: 280px; } } :deep(.el-form-item__error) { font-size: 22px; margin-left: 50px; } .mask-box { position: absolute; width: 100%; height: 100%; background: rgba(255, 255, 255, 0.1); z-index: 2000; } .tray-name { color: var(--el-color-primary); } :deep(.el-drawer) { width: 33% !important; } </style>
|