| | |
| | | |
| | | 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; |
| | |
| | | export const SENSOR_TYPE = Object.freeze({ |
| | | 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({ |
| | |
| | | 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 } })); |
| | |
| | | return |
| | | } |
| | | const { width, height } = sprite; |
| | | const scale = sprite.scale.x; |
| | | const scale = sprite?.scale.x; |
| | | const sideLen = (Math.max(width, height) + 10) * scale; |
| | | const scaledWidth = sideLen * (1 / scale); |
| | | const scaledHeight = sideLen * (1 / scale); |
| | |
| | | } |
| | | |
| | | 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); |
| | |
| | | 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.SHUTTLE: |
| | | options.push({ |
| | | value: value, |
| | | label: intl.formatMessage({ id: 'map.sensor.type.shuttle', 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) { |
| | |
| | | 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); |
| | | } |
| | | } |
| | | }) |
| | | |
| | |
| | | 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) |
| | | }) |
| | | } |
| | | } |
| | | }) |
| | | |
| | |
| | | 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; |
| | |
| | | return row + '-' + bay + '-' + lev; |
| | | } |
| | | |
| | | export const updateMapStatusInRealTime = (data) => { |
| | | export const updateMapStatusInRealTime = (data, curFloorGetter, setCurSPrite) => { |
| | | const curFloor = curFloorGetter(); |
| | | if (isNullOfUndefined(curFloor)) { return; } |
| | | const mapVo = JSON.parse(data); |
| | | // shuttle |
| | | // shuttleVo |
| | | for (const shuttleVo of mapVo.shuttleVos) { |
| | | const shuttle = querySprite(SENSOR_TYPE.SHUTTLE, shuttleVo.shuttleNo); |
| | | if (!shuttle && !shuttleVo.curLocNo) { continue; } |
| | | const { row, bay, lev } = parseLocNo(shuttleVo.curLocNo); |
| | | // 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; } |
| | | new TWEEDLE.Tween(shuttle?.position).easing(TWEEDLE.Easing.Linear.None).to({ |
| | | x: shelf.position.x, |
| | | y: shelf.position.y |
| | | }, 1000).onUpdate(() => { |
| | | updateEffect(shuttle); |
| | | }).start(); |
| | | 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); |
| | | } |
| | | } |