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.
278 lines
9.1 KiB
278 lines
9.1 KiB
import _ from 'lodash'
|
|
import { reactive } from 'vue'
|
|
import { Request } from '@ease-forge/shared'
|
|
import EventBus from '@/runtime/EventBus'
|
|
import StateManager from '@/core/manager/StateManager.ts'
|
|
import { getQueryParams, setQueryParam } from '@/utils/webutils.ts'
|
|
import BackendMessageReceiver from '@/core/manager/BackendMessageReceiver.ts'
|
|
import EnvManager from '@/core/manager/EnvManager.ts'
|
|
import RCSScript from '@/core/script/RCSScript.ts'
|
|
import LCCScript from '@/core/script/LCCScript.ts'
|
|
|
|
export interface WorldModelState {
|
|
authorizationConfig: ServerAuthorizationConfigVo // 服务器授权配置
|
|
isOpened: boolean // 是否已打开世界模型
|
|
worldData: any // 世界模型数据, 包含排除 items 楼层数据之外的所有数据
|
|
|
|
infos: any // 当前楼层的其他数据
|
|
isChanged: boolean // 当前楼层数据是否被修改
|
|
catalog: Catalog // 当前世界模型目录数据
|
|
server: string // 当前楼层服务器地址
|
|
project_uuid: string // 当前楼层所在项目ID
|
|
project_label: string // 项目名称
|
|
sub_system_list: string[] // 子系统集合, 用于标识当前楼层所属的子系统
|
|
catalogCode: string // 当前楼层的目录代码
|
|
|
|
stateManagerId: string // 当前楼层的状态管理器id
|
|
isDraft: boolean // 是否是草稿数据
|
|
|
|
runState: {
|
|
currentEnvId: number,
|
|
isLoading: boolean,
|
|
isRunning: boolean,
|
|
isVirtual: boolean,
|
|
timeRate: number,
|
|
currentEnv: EnvInfo
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 物流世界模型
|
|
*/
|
|
export default class WorldModel {
|
|
currentStateManager: StateManager
|
|
backendMessageReceiver = new BackendMessageReceiver()
|
|
envManager = new EnvManager()
|
|
|
|
/**
|
|
* 世界模型双向绑定的状态数据
|
|
*/
|
|
state: WorldModelState = reactive({
|
|
authorizationConfig: null,
|
|
isOpened: false, // 是否已打开世界模型
|
|
worldData: null, // 世界模型数据, 包含排除 items 楼层数据之外的所有数据
|
|
|
|
infos: {} as any, // 楼层的其他数据
|
|
isChanged: false,
|
|
catalog: [] as Catalog, // 世界模型目录
|
|
server: '',
|
|
project_uuid: '', // 项目ID
|
|
project_label: '', // 项目名称
|
|
sub_system_list: [], // 子系统集合, 用于标识当前楼层所属的子系统
|
|
catalogCode: '', // 当前楼层的目录代码
|
|
|
|
stateManagerId: '', // 当前楼层的状态管理器id, 一般是 项目ID+目录项ID
|
|
isDraft: false, // 是否是草稿数据, 如果是草稿数据, 则不需要再从服务器加载数据
|
|
|
|
|
|
runState: {
|
|
currentEnvId: null,
|
|
isLoading: false,
|
|
isRunning: false,
|
|
isVirtual: false,
|
|
timeRate: 1,
|
|
currentEnv: null
|
|
}
|
|
})
|
|
|
|
get gridOption(): IGridHelper {
|
|
const data = _.get(this.state.worldData, 'Tool.gridHelper')
|
|
return _.defaultsDeep(data, {
|
|
axesEnabled: true,
|
|
axesSize: 5,
|
|
axesColor: 0xDDDDDD,
|
|
axesWidth: 2,
|
|
|
|
gridEnabled: true, // 启用网格
|
|
gridSize: 1000, // 网格大小, 单位米
|
|
gridDivisions: 1000, // 网格分割数
|
|
gridColor: 0xDDDDDD, // 网格颜色, 十六进制颜色值
|
|
gridOpacity: 0.8, // 网格透明度
|
|
|
|
backgroundColor: 0xF5F5F5, // 背景颜色, 十六进制颜色值
|
|
snapEnabled: true, // 启用吸附
|
|
snapDistance: 0.25 // 吸附距离, 单位米
|
|
})
|
|
}
|
|
|
|
/**
|
|
* 初始化世界模型
|
|
*/
|
|
async init() {
|
|
system.showLoading('Authenticating...')
|
|
const configRes = await LCC.getAuthorizationConfig()
|
|
if (!configRes.success) {
|
|
system.showErrorDialog('Authentication failed: ' + configRes.msg)
|
|
return Promise.reject(configRes)
|
|
}
|
|
this.state.authorizationConfig = configRes.data
|
|
await this.backendMessageReceiver.start(configRes.data.frontendMqtt)
|
|
|
|
// 观察 this.state.catalogCode 的变化, 如果变化就调用 catalogCodeChange 方法
|
|
return Promise.all([
|
|
import('../../modules/measure'),
|
|
import('../../modules/way'),
|
|
import('../../modules/gstore'),
|
|
import('../../modules/rack'),
|
|
import('../../modules/shuttle_rack'),
|
|
import('../../modules/pallet'),
|
|
import('../../modules/palletTz'),
|
|
import('../../modules/tote'),
|
|
import('../../modules/carton'),
|
|
import('../../modules/amr/ptr/cl2'),
|
|
import('../../modules/amr/ptr/clx'),
|
|
import('../../modules/charger'),
|
|
import('../../modules/bracket'),
|
|
import('../../modules/amr/fm600'),
|
|
import('../../modules/amr/cc/cc5')
|
|
|
|
]).then((configRes) => {
|
|
console.log('世界模型初始化完成')
|
|
system.clearLoading()
|
|
|
|
// 尝试从草稿中加载数据
|
|
const stateManagerId = getQueryParams()?.get('store')
|
|
|
|
StateManager.tryLoadCatalogFromLocalstore(stateManagerId).then(data => {
|
|
if (data) {
|
|
this.state.isOpened = true
|
|
this.state.worldData = data.worldData
|
|
|
|
this.state.infos = data.infos
|
|
this.state.isChanged = data.isChanged
|
|
this.state.catalog = data.catalog
|
|
this.state.server = data.server
|
|
this.state.project_uuid = data.project_uuid
|
|
this.state.project_label = data.project_label
|
|
this.state.sub_system_list = data.sub_system_list || []
|
|
this.state.isDraft = true
|
|
|
|
this.tryOpenCatelog(data.catalogCode, true).then(() => {
|
|
this.state.catalogCode = data.catalogCode
|
|
this.state.stateManagerId = data.project_uuid + '_' + data.catalogCode
|
|
})
|
|
}
|
|
})
|
|
})
|
|
}
|
|
|
|
async tryOpenCatelog(catalogCode: string, isDraft: boolean = false) {
|
|
if (!catalogCode) {
|
|
// 没有地图
|
|
this.clear()
|
|
return
|
|
}
|
|
|
|
if (!this.state.project_uuid) {
|
|
system.showErrorDialog('项目未初始化, 请先打开一个项目!')
|
|
this.state.catalogCode = ''
|
|
this.state.stateManagerId = null
|
|
return
|
|
}
|
|
|
|
this.state.catalogCode = catalogCode
|
|
this.state.isDraft = isDraft
|
|
this.state.stateManagerId = this.state.project_uuid + '_' + catalogCode
|
|
const stateManager = new StateManager(this.state.stateManagerId)
|
|
|
|
if (isDraft) {
|
|
// 从草稿捞数据
|
|
await stateManager.loadFromLocalstore()
|
|
} else {
|
|
// 从服务器捞数据
|
|
const vdata = await worldModel.getCatalogData(catalogCode)
|
|
await stateManager.load(vdata)
|
|
}
|
|
this.currentStateManager = stateManager
|
|
}
|
|
|
|
/**
|
|
* 从远程服务器读取世界地图数据目录
|
|
*/
|
|
async loadWorldFromRemoting(lccModelWorld) {
|
|
const worldData = lccModelWorld
|
|
const catalog = lccModelWorld.directoryData
|
|
delete lccModelWorld.directoryData
|
|
|
|
this.state.isOpened = true
|
|
this.state.worldData = worldData
|
|
|
|
// 没有打开楼层,不加载 this.state.infos
|
|
// 没有打开楼层,不加载 this.state.isChanged
|
|
this.state.catalog = catalog
|
|
this.state.server = lccModelWorld.server
|
|
this.state.project_uuid = lccModelWorld.projectUuid
|
|
this.state.project_label = lccModelWorld.projectLabel
|
|
this.state.sub_system_list = lccModelWorld.subSystemList || []
|
|
|
|
// 没有打开楼层,不加载 this.state.catalogCode
|
|
this.state.isDraft = false
|
|
}
|
|
|
|
/**
|
|
* 从服务器获取当前目录楼层的所有数据
|
|
*/
|
|
async getCatalogData(catalogCode: string): Promise<VData> {
|
|
const items = await Request.request.get('/api/workbench/LccModelManager@getFloor', { params: { catalogCode, project_uuid: this.state.project_uuid } })
|
|
if (!items) {
|
|
system.showErrorDialog('can\'t get floor data')
|
|
return Promise.reject('can\'t get floor data')
|
|
}
|
|
const vdata: any = {
|
|
items: items as ItemJson[],
|
|
infos: { catalogCode, t: 'floor' },
|
|
isChanged: false,
|
|
catalog: _.cloneDeep(this.state.catalog),
|
|
server: this.state.server,
|
|
project_uuid: this.state.project_uuid,
|
|
project_label: this.state.project_label,
|
|
sub_system_list: _.cloneDeep(this.state.sub_system_list),
|
|
catalogCode: catalogCode,
|
|
worldData: _.cloneDeep(this.state.worldData)
|
|
}
|
|
return Promise.resolve(vdata)
|
|
}
|
|
|
|
clear() {
|
|
this.currentStateManager = null
|
|
this.state.catalogCode = ''
|
|
this.state.stateManagerId = null
|
|
setQueryParam('store', '')
|
|
EventBus.dispatch('dataLoadComplete', {
|
|
stateManager: null
|
|
})
|
|
}
|
|
|
|
/**
|
|
* 改变当前运行环境
|
|
*/
|
|
setEnv(env: EnvInfo) {
|
|
if (this.state.runState.currentEnvId && this.state.runState.isRunning) {
|
|
system.showErrorDialog('cannot change env when running')
|
|
|
|
} else {
|
|
// 更新当前环境 ID
|
|
if (!env) {
|
|
this.state.runState.currentEnvId = null
|
|
this.state.runState.isLoading = false
|
|
this.state.runState.isRunning = false
|
|
this.state.runState.isVirtual = false
|
|
this.state.runState.timeRate = 0
|
|
this.state.runState.currentEnv = null
|
|
} else {
|
|
this.state.runState.currentEnvId = env.envId
|
|
this.state.runState.isLoading = false
|
|
this.state.runState.isRunning = false
|
|
this.state.runState.isVirtual = env.isVirtual
|
|
this.state.runState.timeRate = 1
|
|
this.state.runState.currentEnv = env
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
const worldModel = new WorldModel()
|
|
window['worldModel'] = worldModel
|
|
window['RCS'] = new RCSScript()
|
|
window['LCC'] = new LCCScript()
|
|
export { worldModel }
|
|
|