import { TitleStateComp } from '../common/component/TitleStateComp'; import { RobotPreviewComp } from '../common/component/RobotPreviewComp'; import RobotInfo from '../model/RobotInfo'; import CommonConstants from '../common/constants/CommonConstants'; import StorageInfo from '../model/StorageInfo'; import StorageSpace from '../model/StorageSpace'; import SpaceStateList from '../model/SpaceStateList'; import StorageModel from '../model/database/StorageModel'; import StorageSpaceModel from '../model/database/StorageSpaceModel'; import { RobotLogComp } from '../common/component/RobotLogComp'; import StorageConfig from '../viewmodel/StorageConfig'; import JGRequest from '../common/util/request/Request'; export interface NavigationItem { id: number; text: string; icon: Resource; } export const NavigationList: NavigationItem[] = [ { id: 0, text: '总控', icon: $r('app.media.daohangzongkong') }, { id: 1, text: '位移', icon: $r('app.media.daohangyidong') }, { id: 2, text: '车轮', icon: $r('app.media.daohangchelun') }, { id: 3, text: '吊篮', icon: $r('app.media.daohangdiaolan') }, { id: 4, text: '充电', icon: $r('app.media.daohangchongdian') }, ] @Entry @Component export struct RobotDebug { @State mCurrentPage: number = 0; private isHomePage: boolean = false private mTabController: TabsController = new TabsController() @State selectRobot: number = 1 // todo @State storages: StorageInfo[] = [] @State list: Resource[] = [$r('app.media.car_preview'), $r('app.media.car_preview'), $r('app.media.car_preview')] @State robots: RobotInfo[] = CommonConstants.ROBOTS @State robotX: number | undefined = 0 @State robotY: number | undefined = 0 @State robotStorage: StorageInfo = {} // 机器人在网格中展示的图片 @State robotImage: Resource = $r('app.media.robot_toward_1') @State robotArmX: number | undefined= 0 @State robotArmY: number | undefined= 0 scroller: Scroller = new Scroller() /* * 仓储格子相关 * */ // key为storageSpace的y值 @State spaceArray: StorageSpace[][] = [] // 储位状态(1:禁用 2:未设置类型 3:正常 4:禁用+选中 5:未设置类型+选中 6:正常+选中) @State stateArray: Array = []; @State selectSpace: StorageSpace = {} @State yNum: number[] = [] async aboutToAppear() { let storageId:number | undefined = 0 if (this.robots && this.robots[this.selectRobot]) { let robot: RobotInfo = this.robots[this.selectRobot] storageId = robot.storageId switch (robot.robotToward) { case 1: this.robotImage = $r('app.media.robot_toward_1') this.robotArmX = (robot.x?robot.x:0) + 1 this.robotArmY = robot.y break case 2: this.robotImage = $r('app.media.robot_toward_2') this.robotArmX = (robot.x?robot.x:0)- 1 this.robotArmY = robot.y break case 3: this.robotImage = $r('app.media.robot_toward_3') this.robotArmX = (robot.x?robot.x:0) this.robotArmY = (robot.y?robot.y:0) + 1 break default: this.robotImage = $r('app.media.robot_toward_4') this.robotArmX = (robot.x?robot.x:0) this.robotArmY = (robot.y?robot.y:0) - 1 break } } if (storageId === 0) { return } let spaces: StorageSpace[] = [] // 查询本地数据库,没有则添加数据(仓储和储位数据) this.storages = await StorageModel.getStorageList() if (!this.storages || this.storages.length <= 0) { // 查询后台数据库的线边库 let config: StorageConfig = await JGRequest.get("/api/v1/wms/position/houseConfigInfo/" + 1, {}) if (!config) { return } this.storages.push({ storageName: config.houseName, xSize: config.xNum, ySize: config.yNum, defaultLayer: config.layer } as StorageInfo) let storageId = await StorageModel.addStorage(config.houseName as string, config.xNum as number, config.yNum as number, config.layer as number) this.storages[0].id = storageId if (config.xNum && config.xNum > 0 && config.yNum && config.yNum > 0) { for (let y = 1; y <= config.yNum; y++) { for (let x = 1; x <= config.xNum; x++) { let space: StorageSpace = { storageId: storageId, x: x, y: y, enableState: 1, storageType: '', capacity: config.layer, canWay: 1, canPark: 0 } space.id = await StorageSpaceModel.addStorageSpace(space) // spaces.push(space) } } } } for (const storage of this.storages) { if (storageId === storage.id) { this.robotStorage = storage break } } if (this.robotStorage) { let x: number = 0 if (this.robotStorage.xSize && this.robotStorage.xSize > 0) { x = this.robotStorage.xSize } else { return } // 生成需要遍历的行 (y倒序) if (this.robotStorage.ySize && this.robotStorage.ySize > 0) { if (this.robotStorage.ySize && this.robotStorage.ySize > 0) { for (let index = this.robotStorage.ySize - 1; index >= 0; index--) { this.yNum.push(index) } } } else { return } StorageSpaceModel.getListByStorageId((this.robotStorage.id?this.robotStorage.id:0)).then(spaces => { if (spaces && spaces.length > 0) { let tempArray: StorageSpace[] = [] let stateList = new SpaceStateList() for (const space of spaces) { tempArray.push(space) // 储位状态创建 if (space.enableState === 2) { stateList.push(1) } else if (!space.storageType || space.storageType.length === 0) { stateList.push(2) } else { stateList.push(3) } if (tempArray.length === x) { this.spaceArray.push(tempArray) this.stateArray.push(stateList) tempArray = [] stateList = new SpaceStateList() } } } }) } } updateViewData() { if (this.robots && this.robots[this.selectRobot]) { this.robotX = this.robots[this.selectRobot].x ? this.robots[this.selectRobot].x : 0 this.robotY = this.robots[this.selectRobot].y ? this.robots[this.selectRobot].y : 0 if (this.robots[this.selectRobot].robotType === 2) { let robot: RobotInfo = this.robots[this.selectRobot - 1] switch (robot.robotToward) { case 1: this.robotImage = $r('app.media.robot_toward_1') this.robotArmX =(robot.x?robot.x:0) + 1 this.robotArmY = robot?.y break case 2: this.robotImage = $r('app.media.robot_toward_2') this.robotArmX = (robot.x?robot.x:0)- 1 this.robotArmY = robot.y break case 3: this.robotImage = $r('app.media.robot_toward_3') this.robotArmX = robot.x this.robotArmY = (robot.y?robot.y:0) + 1 break default: this.robotImage = $r('app.media.robot_toward_4') this.robotArmX = robot.x this.robotArmY = (robot.y?robot.y:0) - 1 break } } } for (const storage of this.storages) { if (this.robots && this.robots[this.selectRobot] && this.robots[this.selectRobot].storageId && this.robots[this.selectRobot].storageId === storage.id) { this.robotStorage = storage } } } build() { Column() { TitleStateComp({ isHomePage: this.isHomePage}) Row() { Column() { Column() { Text('机器人调试') .padding(10) .width('100%') .height('8%') .fontSize($r('app.float.title_font_size')) .textAlign(TextAlign.Start) Flex() { Tabs({ barPosition: BarPosition.Start, controller: this.mTabController }) { TabContent() { Column() { this.card('调试模式', $r('app.media.zongkongtiaoshi')) this.card('自动模式', $r('app.media.zongkongzidong')) Divider().width('90%') .margin({ bottom: '20px' }) this.card('电机通电', $r('app.media.zongkongdianjitongdian')) this.card('电机断电', $r('app.media.zongkongguanbidianji')) } .alignItems(HorizontalAlign.Start) .width('100%') .height('100%') .margin({ left: '24px' }) } .tabBar(this.TabBuilder(0)) TabContent() { Column() { Row() { Column() { Text('当前坐标') .fontSize('24px') .fontWeight(FontWeight.Medium) .margin({ left: '26px' }) Text('X:2 Y:3') .fontSize('20px') .fontWeight(FontWeight.Regular) .margin({ left: '26px' }) } .height('52px') .alignItems(HorizontalAlign.Start) Blank() Image($r('app.media.weiyibianjiweizhi')) .width('48px') .height('48px') .margin('20px') } .width('90%') .height('12%') .backgroundColor('#FFFFFF') .alignItems(VerticalAlign.Center) .borderRadius('16px') .margin({ bottom: '18px' }) Divider().margin({ bottom: '20px' }).width('90%') this.card('+X轴移1格', $r('app.media.weiyix')) this.card('-X轴移1格', $r('app.media.weiyixx')) this.card('+Y轴移1格', $r('app.media.weiyiy')) this.card('-Y轴移1格', $r('app.media.weiyiyy')) Divider().margin({ bottom: '20px' }).width('90%') this.card('中止', $r('app.media.weiyizhongzhi')) this.card('急停', $r('app.media.weiyijiting')) } .alignItems(HorizontalAlign.Start) .width('100%') .height('100%') .margin({ left: '24px' }) } .tabBar(this.TabBuilder(1)) TabContent() { Column() { this.card('置顶', $r('app.media.chelunzhiding')) this.card('置中', $r('app.media.chelunzhizhong')) this.card('置底', $r('app.media.chelunzhidi')) } .alignItems(HorizontalAlign.Start) .width('100%') .height('100%') .margin({ left: '24px' }) } .tabBar(this.TabBuilder(2)) TabContent() { Column() { Row() { Text('当前吊篮位') .fontSize('20px') .fontWeight(FontWeight.Medium) .margin({ right: '110px' }) Text('上限位') .fontSize('20px') .fontWeight(FontWeight.Medium) } .height('7%') .width('90%') .justifyContent(FlexAlign.SpaceBetween) .alignItems(VerticalAlign.Bottom) Divider().margin({ bottom: '20px' }).width('90%') this.card('提起', $r('app.media.dianlanshang')) this.card('放下', $r('app.media.dianlanxia')) Divider().margin({ bottom: '20px' }).width('90%') this.card('张开爪夹', $r('app.media.dianlanzhangkai')) this.card('闭合爪夹', $r('app.media.dianlanbihe')) Divider().margin({ bottom: '20px' }).width('90%') this.card('急停', $r('app.media.dianlanjiting')) } .alignItems(HorizontalAlign.Start) .width('100%') .height('100%') .margin({ left: '24px' }) } .tabBar(this.TabBuilder(3)) TabContent() { Column() { Row() { Text('当前状态') .fontSize('20px') .fontWeight(FontWeight.Medium) .margin({ right: '130px' }) .width('90px') .height('26px') Text('充电中') .fontSize('20px') .fontWeight(FontWeight.Medium) .width('60px') .height('26px') } .alignItems(VerticalAlign.Bottom) .width('90%') .justifyContent(FlexAlign.SpaceBetween) .height('5%') Divider().width('90%') Row() { Text('当前电量') .fontSize('20px') .fontWeight(FontWeight.Medium) .margin({ right: '130px' }) .width('90px') .height('26px') Text('80%') .fontSize('20px') .fontWeight(FontWeight.Medium) .width('60px') .height('26px') } .width('90%') .justifyContent(FlexAlign.SpaceBetween) .height('26px') .margin({ top: '20px' }) Divider().width('90%') Row() { Text('电压') .fontSize('20px') .fontWeight(FontWeight.Medium) .margin({ right: '130px' }) .width('90px') .height('26px') Text('50V') .fontSize('20px') .fontWeight(FontWeight.Medium) .width('60px') .height('26px') } .height('26px') .margin({ top: '20px' }) .width('90%') .justifyContent(FlexAlign.SpaceBetween) Divider().width('90%') Row() { Text('电流') .fontSize('20px') .fontWeight(FontWeight.Medium) .margin({ right: '130px' }) .width('90px') .height('26px') Text('10mA') .fontSize('20px') .fontWeight(FontWeight.Medium) .width('60px') .height('26px') } .width('90%') .justifyContent(FlexAlign.SpaceBetween) .height('26px') .margin({ top: '20px' }) Divider().margin({ bottom: '20px' }).width('90%') this.card('开始充电', $r('app.media.chongdianlianjie')) this.card('停止充电', $r('app.media.chongdianduankai')) } .alignItems(HorizontalAlign.Start) .width('100%') .height('100%') .margin({ left: '24px' }) } .tabBar(this.TabBuilder(4)) } .vertical(true) .onChange((index) => { this.mCurrentPage = index; }) .borderRadius($r('app.float.general_border_radius')) .barWidth('30%') .barHeight('100%') .scrollable(false) .barMode(BarMode.Fixed) } .width('100%') .height('90%') .margin({ bottom: '27px', left: '40px' }) } .width('100%') .height('95%') } .width('25%') .height('100%') Column() { // 机器人预览图片和当前机器人状态 Row() { RobotPreviewComp({ list: $list, selectRobot: $selectRobot, robots: $robots, robotX: $robotX, robotY: $robotY, robotStorage: $robotStorage, storages: $storages, }) .width($r('app.float.robot_image_list_size')) Blank() Row() { Image($r('app.media.robot')) .width($r('app.float.card_image_size')) .height($r('app.float.card_image_size')) Text(this.robots && this.robots[this.selectRobot] && this.robots[this.selectRobot].robotCode ? this.robots[this.selectRobot].robotCode : '') .fontSize($r('app.float.robot_state_font_size')) .fontWeight(FontWeight.Medium) .fontColor($r('app.color.general_font_color')) .opacity($r('app.float.general_font_opacity')) .width('40%') } .width('15%') .justifyContent(FlexAlign.SpaceEvenly) Row() { Image($r('app.media.battery_level')) .width($r('app.float.card_image_size')) .height($r('app.float.card_image_size')) Text('98%') .fontSize($r('app.float.robot_state_font_size')) .fontWeight(FontWeight.Medium) .fontColor($r('app.color.general_font_color')) .opacity($r('app.float.general_font_opacity')) } .width('10%') .justifyContent(FlexAlign.SpaceEvenly) Row() { Image($r('app.media.coordinate')) .width($r('app.float.card_image_size')) .height($r('app.float.card_image_size')) Text('x:' + (this.robots && this.robots[this.selectRobot] && this.robots[this.selectRobot].x ? this.robots[this.selectRobot].x : ' ') + 'y:' + (this.robots && this.robots[this.selectRobot] && this.robots[this.selectRobot].y ? this.robots[this.selectRobot].y : ' ')) .fontSize($r('app.float.robot_state_font_size')) .fontWeight(FontWeight.Medium) .fontColor($r('app.color.general_font_color')) .opacity($r('app.float.general_font_opacity')) } .width('10%') .justifyContent(FlexAlign.SpaceEvenly) Row() { Image($r('app.media.robot_auto_mode')) .width($r('app.float.card_image_size')) .height($r('app.float.card_image_size')) Text('自动模式') .fontSize($r('app.float.robot_state_font_size')) .fontWeight(FontWeight.Medium) .fontColor($r('app.color.general_font_color')) .opacity($r('app.float.general_font_opacity')) } .width('12%') .justifyContent(FlexAlign.SpaceEvenly) } .width('100%') .height('8%') .justifyContent(FlexAlign.End) .padding({ right: '2%' }) Row() { SpaceGrid({ stateArray: $stateArray, selectSpace: $selectSpace, yNum: $yNum, spaceArray: $spaceArray, robotX: $robotX, robotY: $robotY, robotArmX: $robotArmX, robotArmY: $robotArmY, robotImage: $robotImage, }) } .width('100%') .alignItems(VerticalAlign.Center) .layoutWeight(1) .onDragEnter(() => { if (this.selectSpace) { this.stateArray[(this.selectSpace.y?this.selectSpace.y:0)-1][(this.selectSpace.x?this.selectSpace.x:0)-1] -= 3 } this.selectSpace = {} }) .onClick(()=>{ if (this.selectSpace) { this.stateArray[(this.selectSpace.y?this.selectSpace.y:0)-1][(this.selectSpace.x?this.selectSpace.x:0)-1] -= 3 } this.selectSpace = {} }) Row() { Row() { RobotLogComp() } .width('20%') .height('100%') } .width('100%') .height('20%') .justifyContent(FlexAlign.End) .padding({ right: '3%' }) } .width('75%') .height('100%') } .backgroundColor('#F1F3F5') .width('100%') .height('92%') } .width('100%') .height('100%') } // 动画效果 pageTransition() { PageTransitionEnter({ duration: 400, curve: Curve.Linear, delay: 400 }) .scale({ x: 0, y: 0, z: 0, centerX: '50%', centerY: '50%' }) PageTransitionExit({ duration: 400, curve: Curve.Linear }) .scale({ x: 0, y: 0, z: 0 }) } @Builder TabBuilder(index: number) { Column() { Image(NavigationList[index].icon) .width($r('app.float.general_icon_size')) .height($r('app.float.general_icon_size')) Text(NavigationList[index].text) .fontSize($r('app.float.set_card_font_size')) .fontColor($r('app.color.general_font_color')) .opacity($r('app.float.general_font_opacity')) .fontWeight(FontWeight.Medium) } .margin({ left: 10, right: 10 }) .backgroundColor(index === this.mCurrentPage ? '#FFFFFF' : '#F1F3F5') .borderRadius($r('app.float.general_border_radius')) .justifyContent(FlexAlign.Center) .opacity(index === this.mCurrentPage ? 1 : 0.6) .width('100%') .height('80%') } @Builder card(text: string, icon: Resource) { Row() { Text(text) .fontSize('24px') .fontWeight(FontWeight.Medium) .margin({ left: '26px' }) Blank() Image(icon) .width('48px') .height('48px') .margin('20px') } .width('90%') .height('12%') .backgroundColor('#FFFFFF') .alignItems(VerticalAlign.Center) .borderRadius('16px') .margin({ bottom: '20px' }) } } @Component struct SpaceGrid { @Link stateArray: Array @Link selectSpace: StorageSpace @Link yNum: number[] @Link spaceArray: StorageSpace[][] @Link robotX: number @Link robotY: number @Link robotArmX: number @Link robotArmY: number @Link robotImage: Resource scroller: Scroller = new Scroller() build() { Column() { Scroll(this.scroller) { Scroll(this.scroller) { List() { ForEach(this.yNum, (y: number) => { ListItem() { List() { ForEach(this.spaceArray[y], (item: StorageSpace) => { ListItem() { Stack() { if (this.robotX && this.robotY && item.x === this.robotX && item.y === this.robotY) { Image($r('app.media.robot_top')) .objectFit(ImageFit.Fill) } else if (this.robotArmX && this.robotArmY && item.x === this.robotArmX && item.y === this.robotArmY) { Image($r('app.media.robot_arm')) .objectFit(ImageFit.Fill) } else { Image((this.stateArray[y][(item.x?item.x:0)-1] === 1 || this.stateArray[y][(item.x?item.x:0)-1] === 4) ? $r("app.media.storage_space_disable") : (this.stateArray[y][(item.x?item.x:0)-1] === 2 || this.stateArray[y][(item.x?item.x:0)-1] === 5 ? $r('app.media.storage_space_no_type') : $r("app.media.storage_space"))) .objectFit(ImageFit.Fill) } if (this.selectSpace && this.selectSpace.id === item.id) { Image($r('app.media.storage_space_select')) .objectFit(ImageFit.Auto) } if (this.selectSpace && this.selectSpace.id === item.id) { Text(item.x + ':' + item.y) .fontSize($r('app.float.robot_set_font_size')) .fontColor($r('app.color.general_font_color')) .opacity($r('app.float.card_font_default_opacity')) } else { Text(item.x + ':' + item.y) .fontSize($r('app.float.robot_set_font_size')) .fontColor(item.enableState === 2 ? $r('app.color.robot_set_card_white') : $r('app.color.general_font_color')) .opacity(item.enableState === 2 ? 1 : $r('app.float.card_font_default_opacity')) } } .width($r('app.float.storage_space_set_size')) .height($r('app.float.storage_space_set_size')) .onClick(() => { if (this.selectSpace) { this.stateArray[(this.selectSpace.y?this.selectSpace.y:0)-1][(this.selectSpace.y?this.selectSpace.y:0)-1] -= 3 } this.stateArray[y][(item.x?item.x:0)-1] += 3 this.selectSpace = item }) .onDragStart(() => { let isRobotPosition = false if ((this.robotX && this.robotY && item.x === this.robotX && item.y === this.robotY) || (this.robotArmX && this.robotArmY && item.x === this.robotArmX && item.y === this.robotArmY)) { isRobotPosition = true } if (!isRobotPosition) { return } // 设置拖拽过程中显示的图片 return this.pixelMapBuilder }) .onDragEnter(() => { if (this.selectSpace) { this.stateArray[(this.selectSpace.y?this.selectSpace.y:0)-1][(this.selectSpace.x?this.selectSpace.x:0)-1] -= 3 } this.stateArray[y][(item.x?item.x:0)-1] += 3 this.selectSpace = item }) } }) } .listDirection(Axis.Horizontal) } }) } .alignListItem(ListItemAlign.Center) .onDrop((event: DragEvent, extraParams: string) => { console.log('List onDragMove, ' + extraParams + 'X:' + event.getWindowX() + 'Y:' + event.getWindowY()) }) } .scrollable(ScrollDirection.Horizontal) } } .width('100%') .layoutWeight(1) .justifyContent(FlexAlign.Center) .alignItems(HorizontalAlign.Center) } @Builder pixelMapBuilder() { Column() { Image(this.robotImage) .width('262px') .height($r('app.float.storage_space_set_size')) } } }