From 0d04bc5d8080b82338302fba0a59fccff2eaedfc Mon Sep 17 00:00:00 2001 From: Junjie <fallin.jie@qq.com> Date: 星期日, 06 七月 2025 11:28:29 +0800 Subject: [PATCH] # --- zy-asrs-flow/src/pages/map/utils.js | 365 +++++++++++++++++++++++++++++++++++++++++++-------- 1 files changed, 303 insertions(+), 62 deletions(-) diff --git a/zy-asrs-flow/src/pages/map/utils.js b/zy-asrs-flow/src/pages/map/utils.js index 981d032..cefb134 100644 --- a/zy-asrs-flow/src/pages/map/utils.js +++ b/zy-asrs-flow/src/pages/map/utils.js @@ -6,13 +6,15 @@ import agv from '/public/img/map/agv.svg' import shelf from '/public/img/map/shelf.png' +import conveyor from '/public/img/map/conveyor.png' import point from '/public/img/map/point.svg' import shuttle from '/public/img/map/shuttle.svg' +import { log } from 'three/examples/jsm/nodes/Nodes.js'; let app = null; let mapContainer = null; let notify = null; -let effectTick, effectHalfCircle, effectRectangle; +let selectedSprite, effectTick, effectHalfCircle, effectRectangle; export function syncApp(param) { app = param; @@ -35,16 +37,30 @@ }) export const SENSOR_TYPE = Object.freeze({ - SHUTTLE: "SHUTTLE", SHELF: "SHELF", + SHUTTLE: "SHUTTLE", + LIFT: "LIFT", + CONVEYOR: "CONVEYOR", POINT: "POINT", AGV: "AGV", +}) + +export const SENSOR_ZINDEX = Object.freeze({ + SHELF: 1, + CONVEYOR: 1, + POINT: 1, + TRAVEL_PATH: 80, + SHUTTLE: 100, + AGV: 100, }) export const SHELF_TYPE = Object.freeze({ STORE: 0, TRACK: 3, - DISABLE: 1, + LIFT: 67, + CHARGE: 5, + CONVEYOR: 4, + DISABLE: -1, }) export const NOTIFY_TYPE = Object.freeze({ @@ -70,21 +86,31 @@ sprite = new PIXI.Sprite(PIXI.Texture.from(shuttle, { resourceOptions: { scale: 5 } })); sprite.width = 50; sprite.height = 50; + sprite.zIndex = SENSOR_ZINDEX.SHUTTLE; break; case SENSOR_TYPE.AGV: sprite = new PIXI.Sprite(PIXI.Texture.from(agv, { resourceOptions: { scale: 5 } })); sprite.width = 50; sprite.height = 50; + sprite.zIndex = SENSOR_ZINDEX.AGV; break; case SENSOR_TYPE.SHELF: sprite = new PIXI.Sprite(PIXI.Texture.from(shelf, { resourceOptions: { scale: 1 } })); sprite.width = 60; sprite.height = 60; + sprite.zIndex = SENSOR_ZINDEX.SHELF; + break; + case SENSOR_TYPE.CONVEYOR: + sprite = new PIXI.Sprite(PIXI.Texture.from(conveyor, { resourceOptions: { scale: 5 } })); + sprite.width = 112; + sprite.height = 63; + sprite.zIndex = SENSOR_ZINDEX.CONVEYOR; break; case SENSOR_TYPE.POINT: sprite = new PIXI.Sprite(PIXI.Texture.from(point, { resourceOptions: { scale: 5 } })); sprite.width = 10; sprite.height = 10; + sprite.zIndex = SENSOR_ZINDEX.POINT; break; default: break; @@ -100,6 +126,17 @@ type: type, uuid: generateID() }; +} + +export const querySprite = (type, no) => { + if (!mapContainer) { + return; + } + for (const sprite of mapContainer.children) { + if (sprite.data?.type === type && sprite.data?.no === no) { + return sprite; + } + } } // show sprite feature from sprite click event @@ -249,12 +286,14 @@ effectHalfCircle.endFill(); effectHalfCircle.position.set(sprite.x, sprite.y); effectHalfCircle.scale.set(1 / scale); + effectHalfCircle.zIndex = 9999; effectRectangle = new PIXI.Graphics(); effectRectangle.lineStyle(5 * scale, color, 1); effectRectangle.drawRoundedRect(0, 0, sideLen, sideLen, 16 * scale); effectRectangle.endFill(); effectRectangle.mask = effectHalfCircle; + effectRectangle.zIndex = 9999; const scaledWidth = sideLen * (1 / scale); const scaledHeight = sideLen * (1 / scale); @@ -264,6 +303,8 @@ mapContainer.addChild(effectRectangle); mapContainer.addChild(effectHalfCircle); + + selectedSprite = sprite; let phase = 0; effectTick = (delta) => { @@ -275,6 +316,21 @@ }; app.ticker.add(effectTick); +} + +export const updateEffect = (sprite) => { + if (!sprite || sprite !== selectedSprite || !effectRectangle || !effectHalfCircle) { + return + } + const { width, height } = sprite; + const scale = sprite?.scale.x; + const sideLen = (Math.max(width, height) + 10) * scale; + const scaledWidth = sideLen * (1 / scale); + const scaledHeight = sideLen * (1 / scale); + + effectRectangle.position.set(sprite.x - scaledWidth / 2, sprite.y - scaledHeight / 2); + + effectHalfCircle.position.set(sprite.x, sprite.y); } export const removeSelectedEffect = () => { @@ -289,17 +345,20 @@ mapContainer.removeChild(effectRectangle); effectRectangle = null; } + selectedSprite = null; } export const copySprite = (sprite) => { - const copiedSprite = new PIXI.Sprite(sprite.texture); + const copiedSprite = generateSprite(sprite.data.type) initSprite(copiedSprite); copiedSprite.position.set(sprite.position.x, sprite.position.y); copiedSprite.scale.set(sprite.scale.x, sprite.scale.y); copiedSprite.rotation = sprite.rotation; copiedSprite.data = deepCopy(sprite.data); copiedSprite.data.uuid = generateID(); - showSheflType(copiedSprite); + if (copiedSprite.data.type === SENSOR_TYPE.SHELF) { + showSheflType(copiedSprite); + } return copiedSprite; } @@ -345,36 +404,6 @@ return mapContainer?.children?.find(child => child?.data?.uuid === uuid); } -export const sensorTypeSelectOptions = (intl) => { - let options = []; - Object.entries(SENSOR_TYPE).forEach(([key, value]) => { - switch (key) { - case SENSOR_TYPE.SHELF: - options.push({ - value: value, - label: intl.formatMessage({ id: 'map.sensor.type.shelf', defaultMessage: '璐ф灦' }) - }) - break; - case SENSOR_TYPE.AGV: - options.push({ - value: value, - label: intl.formatMessage({ id: 'map.sensor.type.agv', defaultMessage: '鏃犱汉灏忚溅' }) - }) - break; - case SENSOR_TYPE.POINT: - options.push({ - value: value, - label: intl.formatMessage({ id: 'map.sensor.type.point', defaultMessage: '瀹氫綅鐐�' }) - }) - break; - default: - break; - } - - }) - return options; -} - export const fetchMapFloor = async () => { const res = await Http.doPost('api/map/floor/list'); if (res.code === 200) { @@ -389,23 +418,30 @@ await Http.doPostPromise('api/map/list', { floor: curFloor }, (res) => { const mapItemList = eval(res.data); mapItemList.forEach(item => { - const sprite = generateSprite(item.type); - if (sprite) { - initSprite(sprite, item.type); - // data - sprite.data.uuid = item.uuid; - sprite.data.no = item.no; + if (!( + item.type === SENSOR_TYPE.SHUTTLE + || item.type === SENSOR_TYPE.AGV + )) { + const sprite = generateSprite(item.type); + if (sprite) { + initSprite(sprite, item.type); + // data + sprite.data.uuid = item.uuid; + sprite.data.no = item.no; - // dynamical data - Object.assign(sprite.data, item.property); + // dynamical data + Object.assign(sprite.data, item.property); - showSheflType(sprite); - // graph - sprite.position.set(item.positionX, item.positionY); - sprite.scale.set(item.scaleX, item.scaleY); - sprite.rotation = rotationParseNum(item.rotation); + showSheflType(sprite); + // graph + setTimeout(() => { + sprite.position.set(item.positionX, item.positionY); + sprite.scale.set(item.scaleX, item.scaleY); + sprite.rotation = rotationParseNum(item.rotation); + }, 50); - mapContainer.addChild(sprite); + mapContainer.addChild(sprite); + } } }) @@ -423,20 +459,25 @@ mapContainer?.children.forEach(child => { if (child.data?.uuid) { const { type, uuid, no, ...property } = child.data; - mapItemList.push({ - // data - type: type, - uuid: uuid, - no: no, - property: property, + if (!( + type === SENSOR_TYPE.SHUTTLE + || type === SENSOR_TYPE.AGV + )) { + mapItemList.push({ + // data + type: type, + uuid: uuid, + no: no, + property: property, - // graph - positionX: child.position.x, - positionY: child.position.y, - scaleX: child.scale.x, - scaleY: child.scale.y, - rotation: rotationToNum(child.rotation) - }) + // graph + positionX: child.position.x, + positionY: child.position.y, + scaleX: child.scale.x, + scaleY: child.scale.y, + rotation: rotationToNum(child.rotation) + }) + } } }) @@ -516,6 +557,15 @@ case SHELF_TYPE.TRACK: showColor = '#faf6e9'; break; + case SHELF_TYPE.LIFT: + showColor = '#EBDEF0'; + break; + case SHELF_TYPE.CHARGE: + showColor = '#D4EFDF'; + break; + case SHELF_TYPE.CONVEYOR: + showColor = '#54FF9F'; + break; case SHELF_TYPE.DISABLE: showColor = '#ffc8c8'; break; @@ -544,4 +594,195 @@ } else { return false; } +} + +export const parseLocNo = (locNo) => { + if (!locNo || typeof locNo !== 'string') { + return null; + } + const locParseArr = locNo.split('-'); + return { + row: locParseArr?.[0], + bay: locParseArr?.[1], + lev: locParseArr?.[2], + } +} + +export const generateLocNo = (row, bay, lev) => { + return row + '-' + bay + '-' + lev; +} + +export const updateMapStatusInRealTime = (data, curFloorGetter, setCurSPrite) => { + const curFloor = curFloorGetter(); + if (isNullOfUndefined(curFloor)) { return; } + const mapVo = JSON.parse(data); + // shuttleVo + for (const shuttleVo of mapVo.shuttleVos) { + // path + drawTravelPath(shuttleVo, curFloor); + // shuttle + showShuttle(shuttleVo, curFloor, setCurSPrite); + } + + showLockPath(mapVo.lockPath, curFloor, setCurSPrite); + showConveyorSta(mapVo.conveyorSta, curFloor, setCurSPrite); +} + +export const drawTravelPath = (shuttleVo, curFloor) => { + const { shuttleNo, curLocNo, travelPath: path } = shuttleVo; + if (!mapContainer) { + return; + } + const pathLineName = 'preTravelPath-' + shuttleNo; + let pathLine = mapContainer.getChildByName(pathLineName); + if (pathLine) { + mapContainer.removeChild(pathLine); + } + + pathLine = new PIXI.Graphics(); + pathLine.name = pathLineName; + pathLine.lineStyle(3 * (1 / mapContainer.scale.x), 0x3498db, 0.8); + pathLine.zIndex = SENSOR_ZINDEX.TRAVEL_PATH; + let firstNode = true; + for (let i = Math.max(0, path.indexOf(curLocNo)); i < path.length; i++) { + const { row, bay, lev } = parseLocNo(path[i]); + if (Number(lev) !== curFloor) { continue } + const shelf = querySprite(SENSOR_TYPE.SHELF, row + '-' + bay); + if (!shelf) { continue }; + let position = shelf.position; + let x = position.x; + let y = position.y; + if (firstNode) { + pathLine.moveTo(x, y); + firstNode = false; + } else { + pathLine.lineTo(x, y); + } + } + mapContainer.addChild(pathLine); +} + +export const showShuttle = (shuttleVo, curFloor, setCurSPrite) => { + const { shuttleNo, curLocNo } = shuttleVo; + if (!curLocNo) { return } + const { row, bay, lev } = parseLocNo(curLocNo); + if (Number(lev) !== curFloor) { return } + + const shelf = querySprite(SENSOR_TYPE.SHELF, row + '-' + bay); + if (!shelf) { return } + + let shuttle = querySprite(SENSOR_TYPE.SHUTTLE, shuttleNo); + if (!shuttle) { + shuttle = generateSprite(SENSOR_TYPE.SHUTTLE); + initSprite(shuttle, SENSOR_TYPE.SHUTTLE); + shuttle.data.no = shuttleNo; + shuttle.position.set(shelf.position.x, shelf.position.y); + mapContainer.addChild(shuttle); + viewFeature(shuttle, setCurSPrite); + } + + new TWEEDLE.Tween(shuttle?.position).easing(TWEEDLE.Easing.Linear.None).to({ + x: shelf.position.x, + y: shelf.position.y + }, 1000).onUpdate(() => { + updateEffect(shuttle); + }).start(); +} + +export const showLockPath = (lockPath, curFloor, setCurSPrite) => { + const pathLineName = 'lockPath'; + let pathLine = mapContainer.getChildByName(pathLineName); + if (pathLine) { + mapContainer.removeChild(pathLine); + } + + for (let i = 0; i < lockPath.length; i++) { + const item = lockPath[i] + if(item.lev != curFloor) {continue} + const nodes = item.path; + + pathLine = new PIXI.Graphics(); + pathLine.name = pathLineName; + pathLine.lineStyle(3 * (1 / mapContainer.scale.x), 0xff0000, 0.8); + pathLine.zIndex = SENSOR_ZINDEX.TRAVEL_PATH; + let firstNode = true; + + for (let i = 0; i < nodes.length; i++) { + const node = nodes[i]; + const shelf = querySprite(SENSOR_TYPE.SHELF, node.x + '-' + node.y); + if (!shelf) { continue } + + let position = shelf.position; + let x = position.x; + let y = position.y; + if (firstNode) { + pathLine.moveTo(x, y); + firstNode = false; + } else { + pathLine.lineTo(x, y); + } + + } + + mapContainer.addChild(pathLine); + } +} + +export const showConveyorSta = (conveyorSta, curFloor, setCurSPrite) => { + for (let i = 0; i < conveyorSta.length; i++) { + const sta = conveyorSta[i]; + if (!sta.locNo) { continue } + const { row, bay, lev } = parseLocNo(sta.locNo); + if (Number(lev) !== curFloor) { continue } + const sprite = querySprite(SENSOR_TYPE.SHELF, row + '-' + bay); + if (!sprite) { continue } + if (sprite.data.conveyorNo !== sta.siteNo) { continue } + + const conveyorName = 'conveyorSta-' + sprite.data.conveyorNo; + let conveyorChild = sprite.getChildByName(conveyorName); + if (conveyorChild) { + sprite.removeChild(conveyorChild); + } + + let textColor; + let staText; + let positionX = -11; + let positionY = -6; + if (sta.siteStatusType$ == 'site-auto-run') { + textColor = 0xfa51f6; + staText = sprite.data.conveyorNo; + } else if (sta.siteStatusType$ == 'site-unauto') { + textColor = 0xb8b8b8; + staText = sprite.data.conveyorNo; + } else if (sta.siteStatusType$ == 'site-auto-id') { + textColor = 0xc4c40; + staText = sprite.data.conveyorNo + '(' + sta.taskNo + ')'; + positionX = -20; + positionY = -6; + } else if (sta.siteStatusType$ == 'site-auto-run-id') { + textColor = 0xfc3030; + staText = sprite.data.conveyorNo + '(' + sta.taskNo + ')'; + positionX = -20; + positionY = -6; + }else { + textColor = '#54FF9F'; + staText = sprite.data.conveyorNo; + } + + const text = new PIXI.Text(staText, { + fill: 0x000000, + fontSize: 13, + fontFamily: 'MicrosoftYaHei', + }); + text.name = conveyorName; + text.position.set(positionX, positionY); + sprite.addChild(text); + sprite.textObj = text; + sprite.tint = textColor; + // sprite.tint = showColor; + // let position = shelf.position; + // let x = position.x; + // let y = position.y; + // conveyorChild.lineTo(x, y); + } } \ No newline at end of file -- Gitblit v1.9.1