You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

609 lines
18 KiB

5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
  1. <script setup lang="ts">
  2. import { list as listMatrix } from 'apis/matrix'
  3. import { getListByMatrixId, update } from 'apis/matrixCraft'
  4. import { getDeviceStatus, getSprayStatus } from 'apis/system'
  5. import route from 'assets/images/route.png'
  6. import route_active from 'assets/images/route_active.png'
  7. import route_horizontal_active from 'assets/images/route_horizontal2.png'
  8. import route_horizontal from 'assets/images/route_horizontal.png'
  9. import route_vertical_active from 'assets/images/route_vertical2.png'
  10. import route_vertical from 'assets/images/route_vertical.png'
  11. import Edit from 'components/martixCraft/Edit/index.vue'
  12. import TrayGraph from 'components/spray/trayGraph/index.vue'
  13. import { FtMessage } from 'libs/message'
  14. import { socket } from 'libs/socket'
  15. import { sendControl } from 'libs/utils'
  16. import { useSystemStore } from 'stores/useSystemStore'
  17. import { nextTick, onMounted, onUnmounted, ref } from 'vue'
  18. const systemStore = useSystemStore()
  19. const sprayRefs = ref<any>([])
  20. const updateParam = () => {
  21. updateForm.value = {
  22. motorZHeight: form.value.motorZHeight, // 高度
  23. gasPressure: form.value.gasPressure, // Mpa兆帕
  24. volume: form.value.volume, // 单位uL微升
  25. highVoltage: form.value.highVoltage, // 是否打开高压
  26. highVoltageValue: form.value.highVoltageValue, // 高压值
  27. movingSpeed: form.value.movingSpeed, // 毫米
  28. }
  29. infoVisible.value = true
  30. }
  31. const submitParam = async () => {
  32. const params = {
  33. cmdCode: 'matrix_spray_change_param',
  34. cmdId: '',
  35. params: updateForm.value,
  36. }
  37. form.value = {
  38. ...form.value,
  39. ...updateForm.value,
  40. }
  41. await sendControl(params)
  42. infoVisible.value = false
  43. }
  44. const infoVisible = ref(false)
  45. onMounted(async () => {
  46. socket.init(sprayPointReceiveMessage, 'spray_point')
  47. socket.init(finishMessage, 'cmd_response')
  48. await getMatrixList()
  49. await getDeviceStatus().then((res: any) => {
  50. systemStore.updateSystemStatus(res)
  51. if (systemStore.systemStatus.spraying) {
  52. getSpraying()
  53. }
  54. })
  55. })
  56. const isActive = true
  57. onUnmounted(() => {
  58. socket.unregisterCallback(sprayPointReceiveMessage, 'spray_point')
  59. socket.unregisterCallback(finishMessage, 'cmd_response')
  60. // isActive = false
  61. })
  62. const getSpraying = async () => {
  63. const res: any = await getSprayStatus()
  64. const sprayTaskSprayedList = res.sprayTaskSprayedList
  65. cmdId = res.cmdId
  66. form.value = {
  67. ...res.sprayParams,
  68. position: [{ select: false }, { select: false }, { select: false }, { select: false }],
  69. }
  70. res.sprayParams.position.forEach((p: any) => {
  71. form.value.position[p.index] = p
  72. nextTick(() => {
  73. console.log('x', p.x1 * 5)
  74. console.log('y', p.y1 * 5)
  75. console.log('width', (p.x1 + p.x2) * 5)
  76. console.log('height', (p.y1 + p.y2) * 5)
  77. sprayRefs.value[p.index].updateSelection(p.x1 * 5, p.y1 * 5, (p.x2 - p.x1) * 5, (p.y2 - p.y1) * 5)
  78. })
  79. })
  80. sprayTaskSprayedList.forEach((task: any) => {
  81. nextTick(() => {
  82. drawLine(task.index, { x: task.sprayedPoints.x * 5, y: task.sprayedPoints.y * 5 }, task.number)
  83. })
  84. })
  85. }
  86. const matrixList = ref([])
  87. const getMatrixList = async () => {
  88. const res = await listMatrix({ pageNum: 1, pageSize: 100, matrixName: '' })
  89. matrixList.value = res.list
  90. }
  91. const form = ref({
  92. matrixId: undefined,
  93. matrixCraftId: undefined,
  94. matrixPathType: 'horizontal', // 路径类型
  95. motorZHeight: undefined, // 高度
  96. gasPressure: undefined, // Mpa兆帕
  97. volume: undefined, // 单位uL微升
  98. highVoltage: true, // 是否打开高压
  99. highVoltageValue: undefined, // 高压值
  100. spacing: undefined, // 毫米
  101. movingSpeed: undefined, // 移动速度
  102. times: undefined, // 喷涂遍数
  103. position: [{ select: true }, { select: false }, { select: false }, { select: false }],
  104. })
  105. const updateForm = ref({
  106. motorZHeight: undefined, // 高度
  107. gasPressure: undefined, // Mpa兆帕
  108. volume: undefined, // 单位uL微升
  109. highVoltage: true, // 是否打开高压
  110. highVoltageValue: undefined, // 高压值
  111. movingSpeed: undefined, // 移动速度
  112. })
  113. const formRef = ref()
  114. const checkPosition = () => {
  115. let position = form.value.position.filter((item: { select: boolean }) => item.select)
  116. if (!position.length) {
  117. FtMessage.error('至少选择一个玻片')
  118. return false
  119. }
  120. position = form.value.position
  121. .map((item: any, index: number) => {
  122. return {
  123. ...item,
  124. ...sprayRefs.value[index].getSelection(),
  125. index,
  126. }
  127. })
  128. .filter((item: { select: boolean }) => item.select)
  129. console.log(position)
  130. for (let i = 0; i < position.length; i++) {
  131. const p = position[i]
  132. 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) {
  133. FtMessage.error(`玻片${p.index + 1}喷涂区域超出玻片范围`)
  134. return false
  135. }
  136. }
  137. return position
  138. }
  139. const maskVisible = ref(false)
  140. const startWork = async () => {
  141. formRef.value.validate(async (valid: boolean) => {
  142. console.log('valid', valid)
  143. if (!valid) {
  144. FtMessage.error('请检查参数配置')
  145. return
  146. }
  147. const position = checkPosition()
  148. if (!position) {
  149. return
  150. }
  151. cmdId = Date.now().toString()
  152. const params = {
  153. cmdCode: 'matrix_spray_start',
  154. cmdId,
  155. params: {
  156. ...form.value,
  157. position,
  158. },
  159. }
  160. console.log(params)
  161. // socket.init(sprayPointReceiveMessage, 'spray_point')
  162. // socket.init(finishMessage, 'cmd_response')
  163. maskVisible.value = true
  164. await sendControl(params)
  165. currentSpeed = Number(form.value.movingSpeed)
  166. })
  167. }
  168. let currentSpeed = 0
  169. // let poll: ReturnType<typeof setInterval>
  170. console.log(currentSpeed)
  171. const colors = ['#FAF0E6', '#191970', '#2E8B57', '#C0FF3E', '#8B658B', '#EE7942', '#EE1289', '#FF00FF', '#C6E2FF', '#556B2F', '#00BFFF', '#7B68EE']
  172. const sprayPointReceiveMessage = (data: any) => {
  173. if (data.cmdId === cmdId) {
  174. const { currentPoint, index, number } = data
  175. drawLine(index, { x: currentPoint.x * 5, y: currentPoint.y * 5 }, number)
  176. // drawLine(index, { x: nextPoint.x * 5, y: nextPoint.y * 5 }, number)
  177. }
  178. // if (poll) {
  179. // clearInterval(poll)
  180. // }
  181. // const { currentPoint, nextPoint, index } = data
  182. // // 计算累加的mm
  183. // const moveDistance = currentSpeed / 2
  184. // // y轴移动
  185. // if (currentPoint.x === nextPoint.x) {
  186. // let currentY = currentPoint.y
  187. // poll = setInterval(() => {
  188. // currentY += moveDistance
  189. // if (currentY >= nextPoint.y) {
  190. // clearInterval(poll)
  191. // }
  192. // drawLine(index, { x: currentPoint.x * 5, y: currentY * 5 })
  193. // }, 500)
  194. // }
  195. // else if (currentPoint.y === nextPoint.y) {
  196. // // x轴移动
  197. // let currentX = currentPoint.x
  198. // poll = setInterval(() => {
  199. // currentX += moveDistance
  200. // if (currentX >= nextPoint.x) {
  201. // clearInterval(poll)
  202. // }
  203. // drawLine(index, { x: currentX * 5, y: currentPoint.y * 5 })
  204. // }, 500)
  205. // }
  206. }
  207. let cmdId = ''
  208. const finishMessage = (data: any) => {
  209. if (data.cmdId === cmdId && data.status === 'spray_task_finish') {
  210. form.value.position.forEach((item, index) => {
  211. if (item.select) {
  212. sprayRefs.value[index].clearLines()
  213. }
  214. })
  215. maskVisible.value = false
  216. }
  217. }
  218. const drawLine = async (index: number, point: { x: number, y: number }, number: number) => {
  219. console.log('drawLine', sprayRefs.value[index], index, point, number)
  220. await nextTick(() => {
  221. if (!isActive) {
  222. return
  223. }
  224. if (!(sprayRefs.value[index].hasLine(number))) {
  225. sprayRefs.value[index].addLine(colors[number])
  226. }
  227. sprayRefs.value[index].updateLine(point, number, colors[number])
  228. })
  229. }
  230. const pauseWork = async () => {
  231. const params = {
  232. cmdCode: 'matrix_spray_pause',
  233. cmdId: '',
  234. }
  235. await sendControl(params)
  236. }
  237. const continueWork = async () => {
  238. const params = {
  239. cmdCode: 'matrix_spray_continue',
  240. cmdId: '',
  241. params: {
  242. motorZHeight: form.value.motorZHeight, // 高度
  243. gasPressure: form.value.gasPressure, // Mpa兆帕
  244. volume: form.value.volume, // 单位uL微升
  245. highVoltage: form.value.highVoltage, // 是否打开高压
  246. highVoltageValue: form.value.highVoltageValue, // 高压值
  247. movingSpeed: form.value.movingSpeed, // 毫米
  248. },
  249. }
  250. await sendControl(params)
  251. currentSpeed = Number(form.value.movingSpeed)
  252. }
  253. const stopWork = async () => {
  254. const params = {
  255. cmdCode: 'matrix_spray_stop',
  256. cmdId: '',
  257. }
  258. await sendControl(params)
  259. form.value.position.forEach((item, index) => {
  260. if (item.select) {
  261. sprayRefs.value[index].clearLines()
  262. }
  263. })
  264. }
  265. const matrixCraftList = ref<any>([])
  266. const matrixChange = async (value: number) => {
  267. form.value.matrixCraftId = undefined
  268. matrixCraftList.value = await getListByMatrixId(value)
  269. }
  270. const matrixCraftChange = (value: number) => {
  271. form.value = {
  272. ...form.value,
  273. ...matrixCraftList.value.find((item: { id: number }) => item.id === value),
  274. }
  275. // formRef.value.validate()
  276. }
  277. const rules = {
  278. matrixId: [{ required: true, message: '请选择基质', trigger: 'change' }],
  279. motorZHeight: [
  280. {
  281. required: true,
  282. trigger: 'blur',
  283. validator: (rule: any, value: any, callback: any) => {
  284. setTimeout(() => {
  285. if (value < 15) {
  286. callback(new Error('最小安全高度为15mm'))
  287. }
  288. else {
  289. callback()
  290. }
  291. }, 500)
  292. },
  293. },
  294. ],
  295. gasPressure: [{ required: true, message: '请输入氮气气压', trigger: 'blur' }],
  296. volume: [{ required: true, message: '请输入基质流速', trigger: 'blur' }],
  297. highVoltageValue: [
  298. {
  299. required: true,
  300. trigger: 'blur',
  301. validator: (rule: any, value: any, callback: any) => {
  302. if (form.value.highVoltage && !value) {
  303. callback(new Error('请输入电压'))
  304. }
  305. else if (value > 6000) {
  306. callback(new Error('最大电压为6000V'))
  307. }
  308. else {
  309. callback()
  310. }
  311. },
  312. },
  313. ],
  314. movingSpeed: [{ required: true, message: '请输入移动速度', trigger: 'blur' }],
  315. spacing: [{ required: true, message: '请输入间距', trigger: 'blur' }],
  316. times: [{ required: true, message: '请输入喷涂次数', trigger: 'blur' }],
  317. }
  318. const addVisible = ref(false)
  319. const ok = async () => {
  320. addVisible.value = false
  321. matrixCraftList.value = await getListByMatrixId(form.value.matrixId)
  322. }
  323. const upDateLoading = ref(false)
  324. const updateCraft = async () => {
  325. if (!form.value.matrixCraftId) {
  326. FtMessage.error('请选择工艺')
  327. return
  328. }
  329. upDateLoading.value = true
  330. const params = {
  331. ...form.value,
  332. id: form.value.matrixCraftId,
  333. }
  334. await update(params)
  335. FtMessage.success('保存成功')
  336. upDateLoading.value = false
  337. }
  338. const formData = ref({})
  339. const addCraft = () => {
  340. console.log(form.value)
  341. formData.value = {
  342. ...form.value,
  343. id: undefined,
  344. name: undefined,
  345. }
  346. console.log(formData.value)
  347. addVisible.value = true
  348. }
  349. </script>
  350. <template>
  351. <div class="spray-container">
  352. <el-form ref="formRef" label-width="120" :model="form" :rules="rules">
  353. <div class="spray-left">
  354. <div>
  355. <ft-button type="primary" @click="startWork">
  356. 开始喷涂
  357. </ft-button>
  358. <ft-button type="primary" @click="updateParam">
  359. 调整参数
  360. </ft-button>
  361. <ft-button @click="pauseWork">
  362. 暂停喷涂
  363. </ft-button>
  364. <ft-button @click="continueWork">
  365. 继续喷涂
  366. </ft-button>
  367. <ft-button @click="stopWork">
  368. 结束喷涂
  369. </ft-button>
  370. </div>
  371. <div style="display: flex">
  372. <div class="select-box" />
  373. </div>
  374. <div style="display: flex; position: relative">
  375. <div v-show="maskVisible" class="mask-box" />
  376. <div
  377. v-for="(p, index) in form.position"
  378. :key="index"
  379. style="display: flex; flex-direction: column; align-items: center"
  380. >
  381. <p class="tray-name">
  382. 玻片{{ index + 1 }}
  383. </p>
  384. <TrayGraph ref="sprayRefs" :container="`spray-${index + 1}`" :select="p.select" />
  385. <el-checkbox v-model="p.select" style="margin-top: 10px" />
  386. </div>
  387. </div>
  388. </div>
  389. <div class="spray-form">
  390. <el-form-item label="基质" prop="matrixId">
  391. <el-select v-model="form.matrixId" placeholder="" @change="matrixChange">
  392. <el-option v-for="item in matrixList" :key="item.id" :label="item.name" :value="item.id" />
  393. </el-select>
  394. </el-form-item>
  395. <el-form-item label="工艺">
  396. <el-select v-model="form.matrixCraftId" placeholder="" @change="matrixCraftChange">
  397. <el-option v-for="item in matrixCraftList" :key="item.id" :label="item.name" :value="item.id" />
  398. </el-select>
  399. </el-form-item>
  400. <el-form-item label="喷涂路线">
  401. <div class="route-img">
  402. <img
  403. style="margin-left: 20px"
  404. :src="form.matrixPathType === 'horizontal' ? route_horizontal_active : route_horizontal"
  405. alt=""
  406. @click="form.matrixPathType = 'horizontal'"
  407. >
  408. <img
  409. style="margin: 0 20px"
  410. :src="form.matrixPathType === 'vertical' ? route_vertical_active : route_vertical"
  411. alt=""
  412. @click="form.matrixPathType = 'vertical'"
  413. >
  414. <img
  415. :src="form.matrixPathType === 'grid' ? route_active : route"
  416. alt=""
  417. @click="form.matrixPathType = 'grid'"
  418. >
  419. </div>
  420. </el-form-item>
  421. <el-form-item label="Z轴高度" prop="motorZHeight">
  422. <el-input v-model="form.motorZHeight" type="number" />
  423. <span class="unit-text">mm</span>
  424. </el-form-item>
  425. <el-form-item label="氮气气压" prop="gasPressure">
  426. <el-input v-model="form.gasPressure" type="number" />
  427. <span class="unit-text">Mpa</span>
  428. </el-form-item>
  429. <el-form-item label="基质流速" prop="volume">
  430. <el-input v-model="form.volume" type="number" />
  431. <span class="unit-text">uL/min</span>
  432. </el-form-item>
  433. <el-form-item label="是否加电" prop="highVoltageValue">
  434. <div class="voltage-box">
  435. <el-switch v-model="form.highVoltage" />
  436. <el-input
  437. v-show="form.highVoltage"
  438. v-model="form.highVoltageValue"
  439. max="5000"
  440. type="number"
  441. class="voltage-input"
  442. />
  443. <span v-show="form.highVoltage" class="unit-text"> V</span>
  444. </div>
  445. </el-form-item>
  446. <el-form-item label="移动速度" prop="movingSpeed">
  447. <el-input v-model="form.movingSpeed" type="number" />
  448. <span class="unit-text">mm/s</span>
  449. </el-form-item>
  450. <el-form-item label="间距" prop="spacing">
  451. <el-input v-model="form.spacing" type="number" />
  452. <span class="unit-text">mm</span>
  453. </el-form-item>
  454. <el-form-item label="喷涂次数" prop="times">
  455. <el-input v-model="form.times" type="number" />
  456. <span class="unit-text"></span>
  457. </el-form-item>
  458. <div style="display: flex; justify-content: center">
  459. <ft-button type="primary" :loading="upDateLoading" @click="updateCraft">
  460. 更新工艺
  461. </ft-button>
  462. <ft-button type="primary" @click="addCraft">
  463. 保存到新工艺
  464. </ft-button>
  465. </div>
  466. </div>
  467. </el-form>
  468. <el-drawer v-model="infoVisible" title="调整参数" direction="rtl" :close-on-click-modal="false">
  469. <el-form label-width="auto" style="display: flex; flex-direction: column; justify-content: center">
  470. <div>
  471. <el-form-item label="Z轴高度" prop="motorZHeight">
  472. <el-input v-model="updateForm.motorZHeight" type="number" />
  473. <span class="unit-text">mm</span>
  474. </el-form-item>
  475. <el-form-item label="氮气气压" prop="gasPressure">
  476. <el-input v-model="updateForm.gasPressure" type="number" />
  477. <span class="unit-text">Mpa</span>
  478. </el-form-item>
  479. <el-form-item label="基质流速" prop="volume">
  480. <el-input v-model="updateForm.volume" type="number" />
  481. <span class="unit-text">uL/min</span>
  482. </el-form-item>
  483. <el-form-item label="是否加电" prop="highVoltageValue">
  484. <div class="voltage-box">
  485. <el-switch v-model="updateForm.highVoltage" />
  486. <el-input
  487. v-show="updateForm.highVoltage"
  488. v-model="updateForm.highVoltageValue"
  489. type="number"
  490. class="voltage-input"
  491. />
  492. <span v-show="updateForm.highVoltage" class="unit-text"> V</span>
  493. </div>
  494. </el-form-item>
  495. <el-form-item label="移动速度" prop="movingSpeed">
  496. <el-input v-model="updateForm.movingSpeed" type="number" />
  497. <span class="unit-text">mm/s</span>
  498. </el-form-item>
  499. <el-form-item>
  500. <div style="display: flex; justify-content: center; width: 100%">
  501. <ft-button type="primary" @click="submitParam">
  502. 确定
  503. </ft-button>
  504. </div>
  505. </el-form-item>
  506. </div>
  507. </el-form>
  508. </el-drawer>
  509. <!-- <start-spray v-model="wsList" :visible @close="visible = false" /> -->
  510. <Edit v-if="addVisible" :matrix-list :form-data other-page @ok="ok" @cancel="addVisible = false" />
  511. </div>
  512. </template>
  513. <style scoped lang="scss">
  514. .spray-container {
  515. width: 100%;
  516. height: 100%;
  517. .el-form {
  518. width: 100%;
  519. height: 100%;
  520. display: flex;
  521. justify-content: space-between;
  522. overflow: auto;
  523. .spray-left {
  524. display: flex;
  525. flex-direction: column;
  526. }
  527. .spray-form {
  528. display: flex;
  529. flex-direction: column;
  530. justify-content: center;
  531. }
  532. }
  533. }
  534. .el-input,
  535. .el-select {
  536. width: 400px;
  537. margin: 0 40px;
  538. }
  539. .unit-text {
  540. font-size: 40px;
  541. color: #0349a8;
  542. font-weight: 500;
  543. }
  544. .select-box {
  545. display: flex;
  546. margin: 40px;
  547. }
  548. .route-img {
  549. display: flex;
  550. img {
  551. width: 70px;
  552. }
  553. }
  554. .voltage-box {
  555. display: flex;
  556. align-items: center;
  557. margin-left: 40px;
  558. .voltage-input {
  559. width: 280px;
  560. }
  561. }
  562. :deep(.el-form-item__error) {
  563. font-size: 22px;
  564. margin-left: 50px;
  565. }
  566. .mask-box {
  567. position: absolute;
  568. width: 100%;
  569. height: 100%;
  570. background: rgba(255, 255, 255, 0.1);
  571. z-index: 5000;
  572. }
  573. .tray-name {
  574. color: var(--el-color-primary);
  575. }
  576. </style>