Browse Source

Model2DEditor 读取

master
修宁 7 months ago
parent
commit
0e0b7bf0da
  1. 27
      src/core/ModelUtils.ts
  2. 2
      src/core/engine/SceneHelp.ts
  3. 20
      src/core/engine/Viewport.ts
  4. 88
      src/core/manager/EntityManager.ts
  5. 25
      src/core/manager/StateManager.ts
  6. 35
      src/core/manager/WorldModel.ts
  7. 49
      src/editor/Model2DEditor.vue
  8. 84
      src/example/example1.js
  9. 2
      src/runtime/EventBus.ts
  10. 17
      src/types/Types.d.ts

27
src/core/ModelUtils.ts

@ -6,16 +6,31 @@ import { computeBoundsTree, disposeBoundsTree } from 'three-mesh-bvh'
import { Vector2 } from 'three/src/math/Vector2' import { Vector2 } from 'three/src/math/Vector2'
import type Toolbox from '@/model/itemType/Toolbox.ts' import type Toolbox from '@/model/itemType/Toolbox.ts'
/**
* 线 ID
*/
export function getLineId(startId: string, endId: string, type: LinkType): string { export function getLineId(startId: string, endId: string, type: LinkType): string {
if (type === 'center') { if (type === 'center' && startId > endId) {
// 无序线, start / end 大的在前 // 无序线, start / end 大的在前
if (startId > endId) { return `${type}$${endId}$${startId}`
return `${type}_${endId}_${startId}`
}
} }
// 其他的线是有序线 // 其他的线是有序线
// 线条必须加上 type, 因为 center 与 in/out 是可以并存的, 他们类型不一样 // 线条必须加上 type, 因为 center 与 in/out 是可以并存的
return `${type}_${startId}_${endId}` return `${type}$${startId}$${endId}`
}
/**
* 线 ID, 线, ID ID
*/
export function parseLineId(lineId): [LinkType, string, string] {
const parts = lineId.split('$')
if (parts.length !== 3) {
throw new Error(`Invalid lineId format: ${lineId}`)
}
const type = parts[0] as LinkType
const startId = parts[1]
const endId = parts[2]
return [type, startId, endId]
} }
export function deletePointByKeyboard() { export function deletePointByKeyboard() {

2
src/core/engine/SceneHelp.ts

@ -74,7 +74,7 @@ export default class SceneHelp {
// async loadFloorEntities(floorId: string): Promise<void> { // async loadFloorEntities(floorId: string): Promise<void> {
// const items = await this.worldModel.loadFloor(floorId) // const items = await this.worldModel.loadFloor(floorId)
// items.forEach((item) => { // items.forEach((item) => {
// this.entityManager.createEntity(item) // this.entityManager.createOrUpdateEntity(item)
// }) // })
// } // }

20
src/core/engine/Viewport.ts

@ -4,7 +4,7 @@ import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
import Stats from 'three/examples/jsm/libs/stats.module' import Stats from 'three/examples/jsm/libs/stats.module'
import type WorldModel from '../manager/WorldModel' import type WorldModel from '../manager/WorldModel'
import $ from 'jquery' import $ from 'jquery'
import { reactive, watch } from 'vue' import { reactive, toRaw, watch } from 'vue'
import type IControls from '../controls/IControls' import type IControls from '../controls/IControls'
import { CSS3DRenderer } from 'three/examples/jsm/renderers/CSS3DRenderer' import { CSS3DRenderer } from 'three/examples/jsm/renderers/CSS3DRenderer'
import { CSS2DRenderer } from 'three/examples/jsm/renderers/CSS2DRenderer' import { CSS2DRenderer } from 'three/examples/jsm/renderers/CSS2DRenderer'
@ -19,6 +19,7 @@ import EntityManager from '../manager/EntityManager'
import InteractionManager from '@/core/manager/InteractionManager' import InteractionManager from '@/core/manager/InteractionManager'
import { calcPositionUseSnap } from '@/core/ModelUtils' import { calcPositionUseSnap } from '@/core/ModelUtils'
import StateManager from '@/core/manager/StateManager.ts' import StateManager from '@/core/manager/StateManager.ts'
import EventBus from '@/runtime/EventBus.ts'
/** /**
* *
@ -82,7 +83,7 @@ export default class Viewport {
/** /**
* THREE * THREE
*/ */
initThree(option: InitThreeOption) { async initThree(option: InitThreeOption) {
console.log('viewport on catelogCode: ' + this.scene.catalogCode) console.log('viewport on catelogCode: ' + this.scene.catalogCode)
const viewerDom = this.viewerDom const viewerDom = this.viewerDom
@ -185,7 +186,20 @@ export default class Viewport {
itemType.clazz.afterAddViewport(this) itemType.clazz.afterAddViewport(this)
}) })
this.state.isReady = true try {
const vdata = await this.worldModel.getCatalogData(this.scene.catalogCode)
if (!vdata) {
return
}
if (!vdata.catalog) {
vdata.catalog = toRaw(this.worldModel.state.catalog)
}
await this.stateManager.load(vdata)
EventBus.dispatch('dataLoadComplete', {})
} finally {
this.state.isReady = true
}
} }
/** /**

88
src/core/manager/EntityManager.ts

@ -2,7 +2,7 @@ import * as THREE from 'three'
import type Viewport from '@/core/engine/Viewport' import type Viewport from '@/core/engine/Viewport'
import type BaseRenderer from '@/core/base/BaseRenderer' import type BaseRenderer from '@/core/base/BaseRenderer'
import { getRenderer } from './ModuleManager' import { getRenderer } from './ModuleManager'
import { getLineId } from '@/core/ModelUtils' import { getLineId, parseLineId } from '@/core/ModelUtils'
/** /**
* *
@ -21,20 +21,21 @@ export default class EntityManager {
// 关系索引 // 关系索引
readonly relationIndex = new Map<string, Relation>() readonly relationIndex = new Map<string, Relation>()
// 所有 THREEJS "点"对象 // 所有 THREEJS "点"对象, 检索值是"点实体"的 id, 值是 THREE.Object3D 数组
readonly objects = new Map<string, THREE.Object3D[]>() readonly objects = new Map<string, THREE.Object3D[]>()
// 所有 THREEJS "线"对象 // 所有 THREEJS "线"对象, 检索值是"线实体"的 id, 取值方式是 {type}${startId}${endId}, 值是 THREE.Object3D 数组
readonly lines = new Map<string, THREE.Object3D[]>() readonly lines = new Map<string, THREE.Object3D[]>()
// 差量渲染器 // 差量渲染器
readonly diffRenderer = new Map<string, BaseRenderer>() readonly diffRenderer = new Map<string, BaseRenderer>()
// 线差量记录 // 线差量记录
lineDiffs = { readonly lineDiffs = {
create: new Map<string, LineDiffItem>(), create: new Map<string, LineDiffItem>(),
update: new Map<string, LineDiffItem>(), update: new Map<string, LineDiffItem>(),
delete: new Map<string, LineDiffItem>() delete: new Map<string, LineDiffItem>()
} }
isUpdating = false
init(viewport: Viewport) { init(viewport: Viewport) {
this.viewport = viewport this.viewport = viewport
@ -44,6 +45,7 @@ export default class EntityManager {
* *
*/ */
beginUpdate(): void { beginUpdate(): void {
this.isUpdating = true
this.viewport.beginUpdate() this.viewport.beginUpdate()
this.diffRenderer.clear() this.diffRenderer.clear()
this.lineDiffs.create.clear() this.lineDiffs.create.clear()
@ -134,6 +136,7 @@ export default class EntityManager {
renderer.endUpdate() renderer.endUpdate()
} }
this.viewport.endUpdate() this.viewport.endUpdate()
this.isUpdating = false
} }
/** /**
@ -210,6 +213,71 @@ export default class EntityManager {
} }
/** /**
*
* , .
*/
renamePoint(newId: string, originId: string) {
if (this.isUpdating) {
throw new Error('Cannot rename point during update')
}
const entity = this.entities.get(originId)
if (!entity) {
throw new Error(`Entity with id ${originId} does not exist`)
}
if (this.entities.has(newId)) {
throw new Error(`Entity with id ${newId} already exists`)
}
entity.id = newId
this.entities.set(newId, entity)
this.entities.delete(originId)
this.objects.set(newId, this.objects.get(originId) || [])
this.objects.delete(originId)
// 更新关系索引
const relations = this.relationIndex.get(originId)
if (relations) {
this.relationIndex.delete(originId)
// 更新所有关系中的 id
relations.center.forEach((relatedId) => {
const rev = this.relationIndex.get(relatedId)
if (rev && rev.delete('center', originId)) {
rev.add('center', newId)
}
})
relations.input.forEach((relatedId) => {
const rev = this.relationIndex.get(relatedId)
if (rev && rev.delete('out', originId)) {
rev.add('out', newId)
}
})
relations.output.forEach((relatedId) => {
const rev = this.relationIndex.get(relatedId)
if (rev && rev.delete('in', originId)) {
rev.add('in', newId)
}
})
this.relationIndex.set(newId, relations)
}
// 更新所有线段数据
for (const [lineId, lineObjects] of this.lines.entries()) {
const [type, startId, endId] = parseLineId(lineId)
if (startId === originId) {
const newLineId = getLineId(newId, endId, type)
this.lines.set(newLineId, lineObjects)
this.lines.delete(lineId)
} else if (endId === originId) {
const newLineId = getLineId(startId, newId, type)
this.lines.set(newLineId, lineObjects)
this.lines.delete(lineId)
}
}
}
/**
* , , diffRenderer , commitUpdate * , , diffRenderer , commitUpdate
*/ */
private removeRelations(id: string): void { private removeRelations(id: string): void {
@ -291,22 +359,22 @@ export class Relation {
add(type: LinkType, id: string) { add(type: LinkType, id: string) {
if (type === 'in') if (type === 'in')
this.input.add(id) return this.input.add(id)
else if (type === 'out') else if (type === 'out')
this.output.add(id) return this.output.add(id)
else if (type === 'center') else if (type === 'center')
this.center.add(id) return this.center.add(id)
else else
throw new Error(`Unknown link type: ${type}`) throw new Error(`Unknown link type: ${type}`)
} }
delete(type: LinkType, id: string) { delete(type: LinkType, id: string) {
if (type === 'in') if (type === 'in')
this.input.delete(id) return this.input.delete(id)
else if (type === 'out') else if (type === 'out')
this.output.delete(id) return this.output.delete(id)
else if (type === 'center') else if (type === 'center')
this.center.delete(id) return this.center.delete(id)
else else
throw new Error(`Unknown link type: ${type}`) throw new Error(`Unknown link type: ${type}`)
} }

25
src/core/manager/StateManager.ts

@ -63,6 +63,8 @@ export default class StateManager {
*/ */
readonly isLoading = ref(false) readonly isLoading = ref(false)
readonly storeKey: string
/** /**
* *
*/ */
@ -101,6 +103,7 @@ export default class StateManager {
*/ */
constructor(id: string, viewport: Viewport, bufferSize = 50) { constructor(id: string, viewport: Viewport, bufferSize = 50) {
this.id = id this.id = id
this.storeKey = `-tmp-yvan-lcc-${this.id}`
this.entityManager = viewport.entityManager this.entityManager = viewport.entityManager
this.historyBufferSize = bufferSize this.historyBufferSize = bufferSize
@ -222,14 +225,14 @@ export default class StateManager {
// 处理新增 // 处理新增
if (this.changeTracker.added) { if (this.changeTracker.added) {
for (const item of this.changeTracker.added) { for (const item of this.changeTracker.added) {
this.entityManager.createEntity(item) this.entityManager.createOrUpdateEntity(item)
} }
} }
// 处理更新 // 处理更新
if (this.changeTracker.updated) { if (this.changeTracker.updated) {
for (const item of this.changeTracker.updated) { for (const item of this.changeTracker.updated) {
this.entityManager.updateEntity(item) this.entityManager.createOrUpdateEntity(item)
} }
} }
@ -240,7 +243,7 @@ export default class StateManager {
/** /**
* *
*/ */
async load(data: VData) { async load(data: Partial<VData>) {
this.isLoading.value = true this.isLoading.value = true
this.historySteps = new Array(this.maxHistorySteps).fill(null) this.historySteps = new Array(this.maxHistorySteps).fill(null)
this.historyIndex = -1 this.historyIndex = -1
@ -250,11 +253,11 @@ export default class StateManager {
this.stopAutoSave() this.stopAutoSave()
// 直接替换数组引用(避免响应式开销) // 直接替换数组引用(避免响应式开销)
//@ts-ignore
this.vdata = { this.vdata = {
id: this.id, id: this.id,
items: data.items,
isChanged: false, isChanged: false,
catalog: data.catalog ...data
} }
this.fullSync() // 同步到视口 this.fullSync() // 同步到视口
@ -404,7 +407,7 @@ export default class StateManager {
// itemsCount: this.vdata.items.length // itemsCount: this.vdata.items.length
// } // }
// //
// await localforage.setItem(`scene-tmp-${this.id}`, saveData) // await localforage.setItem(this.storeKey, saveData)
// } // }
// //
// /** // /**
@ -413,7 +416,7 @@ export default class StateManager {
// async loadFromLocalstore() { // async loadFromLocalstore() {
// try { // try {
// this.isLoading.value = true // this.isLoading.value = true
// const saved: any = await localforage.getItem(`scene-tmp-${this.id}`) // const saved: any = await localforage.getItem(this.storeKey)
// if (saved && saved.diff) { // if (saved && saved.diff) {
// this.applyDiff(saved.diff) // this.applyDiff(saved.diff)
// this.isChanged.value = true // this.isChanged.value = true
@ -433,7 +436,7 @@ export default class StateManager {
* indexDb() * indexDb()
*/ */
async saveToLocalstore() { async saveToLocalstore() {
await localforage.setItem(`scene-tmp-${this.id}`, this.vdata) await localforage.setItem(this.storeKey, this.vdata)
} }
/** /**
@ -442,7 +445,7 @@ export default class StateManager {
async loadFromLocalstore() { async loadFromLocalstore() {
try { try {
this.isLoading.value = true this.isLoading.value = true
const saved: VData = await localforage.getItem(`scene-tmp-${this.id}`) const saved: VData = await localforage.getItem(this.storeKey)
if (saved) { if (saved) {
this.vdata.items = saved.items || [] this.vdata.items = saved.items || []
this.isChanged.value = saved.isChanged || false this.isChanged.value = saved.isChanged || false
@ -461,7 +464,7 @@ export default class StateManager {
private fullSync() { private fullSync() {
this.entityManager.beginUpdate() this.entityManager.beginUpdate()
this.vdata.items.forEach(item => { this.vdata.items.forEach(item => {
this.entityManager.createEntity(item) this.entityManager.createOrUpdateEntity(item)
}) })
this.entityManager.commitUpdate() this.entityManager.commitUpdate()
} }
@ -480,7 +483,7 @@ export default class StateManager {
*/ */
async removeLocalstore() { async removeLocalstore() {
try { try {
await localforage.removeItem(`scene-tmp-${this.id}`) await localforage.removeItem(this.storeKey)
console.log('[StateManager] 本地存储已清除') console.log('[StateManager] 本地存储已清除')
} catch (error) { } catch (error) {
console.error('[StateManager] 清除本地存储失败:', error) console.error('[StateManager] 清除本地存储失败:', error)

35
src/core/manager/WorldModel.ts

@ -50,9 +50,7 @@ export default class WorldModel {
init() { init() {
// 观察 this.state.catalogCode 的变化, 如果变化就调用 catalogCodeChange 方法 // 观察 this.state.catalogCode 的变化, 如果变化就调用 catalogCodeChange 方法
watch(() => this.state.catalogCode, (newValue, oldValue) => { watch(() => this.state.catalogCode, this.onCatalogCodeChanged.bind(this))
worldModel.loadFloor(newValue)
})
return Promise.all([ return Promise.all([
import('@/modules/measure') import('@/modules/measure')
@ -72,11 +70,10 @@ export default class WorldModel {
} }
/** /**
* , +id * ,
*/ */
loadFloor(catalogCode: string) { onCatalogCodeChanged(catalogCode: string) {
if (!catalogCode) { if (!catalogCode) {
this.state.catalogCode = ''
this.state.stateManagerId = '' this.state.stateManagerId = ''
EventBus.dispatch('catalogChanged', { EventBus.dispatch('catalogChanged', {
catalogCode: this.state.catalogCode, catalogCode: this.state.catalogCode,
@ -88,10 +85,10 @@ export default class WorldModel {
const floor = _.find(this.data.items, r => r.catalogCode === catalogCode && r.t === 'floor') const floor = _.find(this.data.items, r => r.catalogCode === catalogCode && r.t === 'floor')
if (!floor) { if (!floor) {
system.msg('楼层不存在: ' + catalogCode) system.msg('楼层不存在: ' + catalogCode)
this.state.catalogCode = ''
return return
} }
this.state.catalogCode = catalogCode
this.state.stateManagerId = this.data.project_uuid + '_' + catalogCode this.state.stateManagerId = this.data.project_uuid + '_' + catalogCode
EventBus.dispatch('catalogChanged', { EventBus.dispatch('catalogChanged', {
catalogCode: this.state.catalogCode, catalogCode: this.state.catalogCode,
@ -99,6 +96,30 @@ export default class WorldModel {
}) })
} }
async getCatalogData(catalogCode: string): Promise<Partial<VData>> {
if (!this.data || !this.data.items) {
return Promise.reject('楼层数据未加载, catalogCode=' + catalogCode)
}
const floor = _.find(this.data.items, r => r.catalogCode === this.state.catalogCode && r.t === 'floor')
if (floor) {
if (!floor.items) {
floor.items = []
}
const vdata: Partial<VData> = {
items: _.cloneDeep(floor.items) as ItemJson[],
isChanged: false,
server: '',
projectId: '',
catalogCode: catalogCode,
}
return Promise.resolve(vdata)
}
return Promise.reject('楼层不存在, catalogCode=' + catalogCode)
}
// loadFloorToScene(viewport: Viewport, scene: THREE.Scene, levelCode: string) { // loadFloorToScene(viewport: Viewport, scene: THREE.Scene, levelCode: string) {
// let floor = _.find(this.data.items, r => r.name === levelCode && r.t === 'floor') // let floor = _.find(this.data.items, r => r.name === levelCode && r.t === 'floor')
// if (!floor) { // if (!floor) {

49
src/editor/Model2DEditor.vue

@ -120,20 +120,6 @@ export default defineComponent({
return parseFloat(num).toFixed(2) return parseFloat(num).toFixed(2)
}, },
initByFloor() { initByFloor() {
// url ?store=${stateManager.id}
// if (stateManager) {
// window.history.replaceState({}, '', window.location.href + '?store=' + stateManager.id)
// }
// const stateManager = new StateManager(id, 50)
// worldModel.stateManager = stateManager
// worldModel.stateManager = stateManager
// system.showLoading()
// stateManager.load(floor.items)
// .finally(() => {
// system.clearLoading()
// })
// return stateManager
this.destroyScene() this.destroyScene()
delete window['editor'] delete window['editor']
@ -149,7 +135,7 @@ export default defineComponent({
if (!worldModel.state.catalogCode || !worldModel.state.isOpened || !id) { if (!worldModel.state.catalogCode || !worldModel.state.isOpened || !id) {
// //
setQueryParam('store', id) setQueryParam('store', '')
return return
} }
@ -163,23 +149,28 @@ export default defineComponent({
this.scene = markRaw(sceneHelp) this.scene = markRaw(sceneHelp)
this.viewport = markRaw(viewport) this.viewport = markRaw(viewport)
viewport.initThree({ stateManagerId: id }) system.showLoading('正在加载视口...')
setQueryParam('store', id) viewport.initThree({ stateManagerId: id }).then(() => {
// window.history.replaceState({}, '', window.location.href + '?store=' + id) setQueryParam('store', id)
// window.history.replaceState({}, '', window.location.href + '?store=' + id)
window['viewport'] = viewport
window['THREE'] = THREE
window['scene'] = sceneHelp.scene
window['renderer'] = viewport.renderer
window['camera'] = viewport.camera
window['renderer'] = viewport.renderer
window['controls'] = viewport.controls
window['viewport'] = viewport viewerDom.focus()
window['THREE'] = THREE
window['scene'] = sceneHelp.scene
window['renderer'] = viewport.renderer
window['camera'] = viewport.camera
window['renderer'] = viewport.renderer
window['controls'] = viewport.controls
viewerDom.focus() //
this.$emit('viewportChanged', viewport)
this.isReady = true
// }).finally(() => {
this.$emit('viewportChanged', viewport) system.clearLoading()
this.isReady = true })
}) })
} }
}, },

84
src/example/example1.js

@ -35,50 +35,46 @@ export default {
catalogCode: 'f1', t: 'floor', // 楼层 catalogCode: 'f1', t: 'floor', // 楼层
items: [ items: [
{ {
name: 'measure-group', t: 'measure', a: 'gp', // 类型, itemType.name == 'measure' 的组件处理. a:'gp' 代表分组, 渲染时他会是 Three.Group id: 'p1', // 物体ID, 唯一标识, 需保证唯一, three.js 中的 uuid
items: [ t: 'measure', // 物体类型, measure表示测量, 需交给 itemType.name == 'measure' 的组件处理
{ tf: [ // 变换矩阵, 3x3矩阵, 采用Y轴向上为正, X轴向右, Z轴向前的右手坐标系
id: 'p1', // 物体ID, 唯一标识, 需保证唯一, three.js 中的 uuid [-9.0, 0, -1.0], // 平移向量 position
t: 'measure', // 物体类型, measure表示测量, 需交给 itemType.name == 'measure' 的组件处理 [0, 0, 0], // 旋转向量 rotation, 表示绕Y轴旋转的角度, 单位为度。对应 three.js 应进行"角度"转"弧度"的换算
a: 'ln', // 交互类型, ln表示线点操作, pt 表示点操作 [0.25, 0.1, 0.25] // 缩放向量 scale
l: '测量1', // 标签名称, 显示用 ],
c: '#ff0000', // 颜色, 显示用. 十六进制颜色值, three.js 中的材质颜色 dt: { // 用户数据, 可自定义, 一般用在 three.js 的 userData 中
tf: [ // 变换矩阵, 3x3矩阵, 采用Y轴向上为正, X轴向右, Z轴向前的右手坐标系 label: '测量1', // 标签名称, 显示用
[-9.0, 0, -1.0], // 平移向量 position color: '#ff0000', // 颜色, 显示用. 十六进制颜色值, three.js 中的材质颜色
[0, 0, 0], // 旋转向量 rotation, 表示绕Y轴旋转的角度, 单位为度。对应 three.js 应进行"角度"转"弧度"的换算 center: ['p2'], // 用于 a='ln' 的测量线段, 关联的点对象(uuid)
[0.25, 0.1, 0.25] // 缩放向量 scale in: [], // 物流入方向关联的对象(id)
], out: [] // 物流出方向关联的对象(id)
dt: { // 用户数据, 可自定义, 一般用在 three.js 的 userData 中 }
center: ['p2'], // 用于 a='ln' 的测量线段, 关联的点对象(uuid) },
in: [], // 物流入方向关联的对象(uuid) {
out: [] // 物流出方向关联的对象(uuid) id: 'p2',
} t: 'measure',
}, tf: [[-9.0, 0, 3], [0, 0, 0], [0.25, 0.1, 0.25]],
{ dt: {
id: 'p2', color: '#ff0000',
t: 'measure', a: 'ln', l: '测量2', c: '#ff0000', label: '测量2',
tf: [[-9.0, 0, 3], [0, 0, 0], [0.25, 0.1, 0.25]], center: ['p1', 'p3', 'p4']
dt: { }
center: ['p3', 'p4'] },
} {
}, id: 'p3',
{ t: 'measure', a: 'ln', l: '测量3', c: '#ff0000',
id: 'p3', tf: [[-5.0, 0, 3], [0, 0, 0], [0.25, 0.1, 0.25]],
t: 'measure', a: 'ln', l: '测量3', c: '#ff0000', dt: {
tf: [[-5.0, 0, 3], [0, 0, 0], [0.25, 0.1, 0.25]], center: ['p2']
dt: { }
center: [] },
} {
}, id: 'p4',
{ t: 'measure', a: 'ln', l: '测量3', c: '#ff0000',
id: 'p4', tf: [[-9.0, 0, 8], [0, 0, 0], [0.25, 0.1, 0.25]],
t: 'measure', a: 'ln', l: '测量3', c: '#ff0000', dt: {
tf: [[-9.0, 0, 8], [0, 0, 0], [0.25, 0.1, 0.25]], center: ['p2']
dt: { }
center: []
}
}
]
} }
] ]
} }

2
src/runtime/EventBus.ts

@ -2,7 +2,7 @@ import mitt from 'mitt'
const instance = mitt() const instance = mitt()
export type DispatchNames = 'objectChanged' | 'catalogChanged' export type DispatchNames = 'objectChanged' | 'catalogChanged' | 'dataLoadComplete'
export default { export default {
dispatch(name: DispatchNames, data?: any) { dispatch(name: DispatchNames, data?: any) {

17
src/types/Types.d.ts

@ -28,9 +28,24 @@ interface VData {
id: string id: string
/** /**
* *
*/ */
catalog: Catalog catalog: Catalog
/**
*
*/
server?: string
/**
* ID
*/
projectId?: string
/**
*
*/
catalogCode: string
} }
interface CatalogItem { interface CatalogItem {

Loading…
Cancel
Save