This commit is contained in:
zh
2025-09-25 16:22:46 +08:00
18 changed files with 2448 additions and 765 deletions

View File

@ -158,6 +158,7 @@ export default {
project: '工程信息',
device: '设备管理',
modelManage: '模型管理',
graphLabelManage: '军标管理',
version: '版本信息'
},
auths: {
@ -214,5 +215,9 @@ export default {
model: {
title: '模型选择',
setting: '默认模型参数设置'
},
graph: {
title: '军标选择',
setting: '默认军标参数设置'
}
}

View File

@ -0,0 +1,93 @@
import request from '@/axios/request'
//军标库
export const GraphApi = {
//创建军标库
createModelDB: async (data: any) => {
return await request.post({
url: `/militaryLibrary/createMilitaryLibrary`,
data
})
},
//导入军标库
importModelDB: async (data: any) => {
return await request.post({
url: `/militaryLibrary/importMilitaryLibrary`,
data
})
},
//删除军标
delModel: async (data: any) => {
return await request.post({
url: `/militaryLibrary/deleteMilitary`,
data,
})
},
//删除军标类型
delModelType: async (data: any) => {
return await request.post({
url: `/militaryLibrary/deleteMilitaryType`,
data,
})
},
//添加军标类型
addModelType: async (data: any) => {
return await request.post({
url: `/militaryLibrary/addMilitaryType`,
data
})
},
//修改军标类型名称
updateMilitaryTypeName: async (data: any) => {
return await request.post({
url: `/militaryLibrary/updateMilitaryTypeName`,
data
})
},
//军标类型列表
modelTypeList: async () => {
return await request.get({
url: `/militaryLibrary/militaryTypeList`
})
},
//添加军标文件
addGraph: async (data: any) => {
return await request.post({
url: `/militaryLibrary/addMilitaryFile`,
data,
headers: {
'Content-Type': 'multipart/form-data'
}
})
},
//根据军标类型查看军标列表
showModelByType: async (data: any) => {
return await request.post({
url: `/militaryLibrary/militaryList`,
data,
// headers: {
// 'content-type': 'application/x-www-form-urlencoded'
// }
})
},
//更新军标信息
updatePoster: async (data: any) => {
return await request.post({
url: `/militaryLibrary/uploadMilitaryInfo`,
data
})
},
// //默认军标参数设置
// modelSetting: async (data: any) => {
// return await request.post({
// url: `/businessConfig/addBusinessConfig`,
// data,
// })
// },
// //获取默认军标参数设置
// getModelSetting: async () => {
// return await request.get({
// url: `/businessConfig/list`
// })
// },
}

View File

@ -36,6 +36,13 @@ export const ModelApi = {
data
})
},
//修改模型类型名称
updateModelTypeName: async (data: any) => {
return await request.post({
url: `/modelLibrary/updateModelTypeName`,
data
})
},
//模型类型列表
modelTypeList: async () => {
return await request.get({

View File

@ -44,6 +44,11 @@ export const initMapData = async (type, data, cd) => {
case 'model':
entityObject = new YJ.Obj.Model(window.earth, data)
break
case 'military':
console.log('data', data)
entityObject = new YJ.Obj.GroundSvg(window.earth, data)
entityObject.load(() => { })
break
case 'terrain':
data.host = baseURL
entityObject = new YJ.Obj.Terrain(window.earth, data)

View File

@ -0,0 +1,819 @@
<template>
<div class="model-management-container">
<div class="equipment_title" style="margin-bottom: 10px">
<el-button
color="#004b4b"
style="border: 1px solid rgba(0, 255, 255, 0.5)"
@click="importModelDB"
>
<template #icon>
<svg-icon name="leading_in" />
</template>
<span>选择军标库</span>
</el-button>
<el-button
color="#004b4b"
style="border: 1px solid rgba(0, 255, 255, 0.5)"
@click="createModelDB"
>
<template #icon>
<svg-icon name="leading_in" />
</template>
<span>创建军标库</span>
</el-button>
</div>
<el-row :gutter="20">
<!-- 左侧分类树 -->
<el-col :span="6" class="tree">
<el-card shadow="hover">
<div class="tree-container" @click="handleClick" @contextmenu="divContextMenu">
<el-tree
style="max-width: 600px"
:allow-drop="allowDrop"
:allow-drag="allowDrag"
:data="typeTreeData"
draggable
ref="treeRef"
node-key="id"
@node-click="handleTypeClick"
@node-contextmenu="handleContextMenu"
@node-drag-start="handleDragStart"
@node-drag-enter="handleDragEnter"
@node-drag-leave="handleDragLeave"
@node-drag-over="handleDragOver"
@node-drag-end="handleDragEnd"
@node-drop="handleDrop"
>
<template #default="{ node, data }">
<!-- <span> {{ node.label }}</span> -->
<span
:class="{
'primary-type': !(node.childNodes.length != 0),
'selected-text': node.id === currentTypeId
}"
@click.stop="toggleExpand(node)"
class="allowDrag"
>
<svg-icon
:name="node.expanded ? 'arrow' : 'more'"
:size="12"
color="rgba(0, 255, 255, 1)"
style="margin-right: 5px; margin-left: 5px"
v-if="node.childNodes.length != 0"
@click.stop="toggleExpand(node)"
></svg-icon>
{{ node.label }}</span
>
</template>
</el-tree>
</div>
</el-card>
</el-col>
<!-- 右侧模型列表 -->
<el-col :span="18">
<el-card shadow="hover">
<el-table :data="modelList" border style="width: 100%">
<el-table-column type="index" label="序号" width="60" align="center" />
<el-table-column prop="militaryName" label="名称" />
<el-table-column prop="thumbnail" label="缩略图" width="100">
<template #default="{ row }">
<el-image
style="width: 80px; height: 60px"
:src="'http://127.0.0.1:8848' + row.data"
/>
</template>
</el-table-column>
<el-table-column label="操作">
<template #default="{ row }">
<el-button size="small">编辑军标</el-button>
<el-button size="small" @click="handleDelete(row)">删除</el-button>
</template>
</el-table-column>
<template #empty>
<div class="custom-empty">
<img src="@/assets/images/noData.png" alt="暂无数据" />
<div class="noData">暂无数据</div>
</div>
</template>
</el-table>
</el-card>
</el-col>
</el-row>
<!-- 右键菜单 -->
<contextMenuCom
v-model:visible="contextMenu.visible"
:x="contextMenu.x"
:y="contextMenu.y"
:menu-items="contextMenu.items"
@command="handleMenuCommand"
/>
<!-- 添加类型弹窗 -->
<el-dialog v-model="dialogVisible" :title="dialogTitle" width="30%" :before-close="handleClose">
<el-input v-model="modelType" placeholder="请输入数据" />
<template #footer>
<span class="dialog-footer">
<el-button @click="closeDialog">取消</el-button>
<el-button type="primary" @click="addType"> 确定 </el-button>
</span>
</template>
</el-dialog>
<input ref="fileInput" type="file" hidden @change="handleFileChange" accept="image/svg+xml" />
</div>
</template>
<script lang="ts" setup>
import { ref, reactive, onMounted } from 'vue'
import type { TableColumnCtx } from 'element-plus'
import contextMenuCom from './contentMenu.vue'
import Sortable from 'sortablejs'
import { inject } from 'vue'
import type { DragEvents } from 'element-plus/es/components/tree/src/model/useDragNode'
import type { AllowDropType, NodeDropType, RenderContentContext } from 'element-plus'
import { GraphApi } from '@/api/graphLabel/index'
import { ElMessage, ElMessageBox } from 'element-plus'
import {
$sendElectronChanel,
$recvElectronChanel,
$changeComponentShow
} from '@/utils/communication'
const fs = require('fs')
const eventBus: any = inject('bus')
var clickTreeNode: any = reactive({})
interface TypeNode {
id: string
label: string
parentId: string | null
children?: TypeNode[]
createdAt?: string | null
updatedAt?: string | null
}
interface ModelItem {
id: string
typeId: string
name: string
thumbnail: string
militaryId: string
}
const typeTreeData = ref<TypeNode[]>([])
const modelList = ref<ModelItem[]>([])
const currentTypeId = ref<string>('')
const contextMenu = reactive({
visible: false,
x: 0,
y: 0,
currentRow: null as TypeNode | null,
items: [] as { command: string; icon: string; label: string; disabled?: boolean }[]
})
const treeRef = ref()
// @ts-ignore
var sortableInstance: any = reactive(null)
//--------------添加模型类型----------------
var dialogVisible: any = ref(false)
var dialogTitle: any = ref('添加军标类型')
var modelType: any = ref('')
const handleClose = () => {
dialogVisible.value = false
}
const closeDialog = () => {
modelType.value = ''
dialogVisible.value = false
}
const addType = () => {
if (!modelType.value) {
return ElMessage.warning('请输入军标类型名称')
}
if (dialogTitle.value == '添加军标类型') {
let params = {
name: modelType.value,
parentId: clickTreeNode && clickTreeNode.id ? clickTreeNode.id : undefined
}
GraphApi.addModelType(params).then((res) => {
if (res.code == 0 || res.code == 200) {
ElMessage.success('添加成功')
getModelList()
}
})
} else {
let params = {
name: modelType.value,
id: clickTreeNode.id
}
GraphApi.updateMilitaryTypeName(params).then((res) => {
if (res.code == 0 || res.code == 200) {
ElMessage.success('修改成功')
getModelList()
}
})
}
modelType.value = ''
dialogVisible.value = false
}
//获取模型列表
eventBus.on('settingPop', (data) => {
if (data) {
//关闭弹框时更新模型列表
// getModelList()
getModelListByType(showImageRow.militaryTypeId)
showImageRow = null
}
})
const getModelList = async () => {
const res: any = await GraphApi.modelTypeList()
if (res.code == 0 || res.code == 200) {
let data = transformNestedJson(res.data, 'name', 'label')
typeTreeData.value = data
}
}
const transformNestedJson = (data, oldKey, newKey) => {
if (Array.isArray(data)) {
return data.map((item) => transformNestedJson(item, oldKey, newKey))
} else if (data && typeof data === 'object') {
const newObj = {}
for (const key in data) {
// 替换键名
const currentKey = key === oldKey ? newKey : key
// 递归处理子元素
newObj[currentKey] = transformNestedJson(data[key], oldKey, newKey)
}
return newObj
}
return data
}
//------------导入模型--------------
const fileInput = ref<HTMLInputElement>()
const triggerUpload = () => {
fileInput.value?.click()
}
const handleFileChange = (e: Event) => {
const files = (e.target as HTMLInputElement).files
if (files) {
const formData = new FormData()
formData.append('files', files[0])
formData.append('militaryTypeId', clickTreeNode.id)
GraphApi.addGraph(formData).then((res) => {
if (res.code == 0 || res.code == 200) {
ElMessage.success('导入成功')
getModelListByType(clickTreeNode.id)
}
})
// 此处可添加文件验证或预处理逻辑
}
}
//创建模型库
const createModelDB = async () => {
let option = {
title: '创建军标库',
filename: 'YJEarth.junbiao',
filters: [{ name: '保存库文件', extensions: ['junbiao'] }]
}
$sendElectronChanel('saveFile', option)
$recvElectronChanel('selectedFileItem', (e, path) => {
if (path) {
let index = path.lastIndexOf('/')
let model_lib_path = path.slice(0, index)
let model_lib_name = path.slice(index + 1)
GraphApi.createModelDB({ name: model_lib_name, path: model_lib_path }).then((res) => {
if (res.code == 0 || res.code == 200) {
ElMessage.success('创建成功')
getModelList()
}
})
}
})
}
//导入模型库
const importModelDB = () => {
let option = {
properties: ['openFile'],
filters: [
{
name: '军标库', //、底图
extensions: ['junbiao']
}
]
}
$sendElectronChanel('open-directory-dialog', option)
$recvElectronChanel('selectedItem', (e, path) => {
if (path.length) addModelDB(path[0])
})
}
const addModelDB = (path) => {
let formData = new FormData()
formData.append('modelPath', path)
GraphApi.importModelDB(formData).then((res) => {
if (res.code == 0 || res.code == 200) {
ElMessage.success('导入成功')
getModelList()
}
})
}
//拖拽
type Node = RenderContentContext['node']
const handleDragStart = (node: Node, ev: DragEvents) => {
console.log('drag start', node)
}
const handleDragEnter = (draggingNode: Node, dropNode: Node, ev: DragEvents) => {
console.log('tree drag enter:', dropNode.label)
}
const handleDragLeave = (draggingNode: Node, dropNode: Node, ev: DragEvents) => {
console.log('tree drag leave:', dropNode.label)
}
const handleDragOver = (draggingNode: Node, dropNode: Node, ev: DragEvents) => {
console.log('tree drag over:', dropNode.label)
}
const handleDragEnd = (
draggingNode: Node,
dropNode: Node,
dropType: NodeDropType,
ev: DragEvents
) => {
console.log('tree drag end:', dropNode && dropNode.label, dropType)
}
const handleDrop = (draggingNode: Node, dropNode: Node, dropType: NodeDropType, ev: DragEvents) => {
console.log('tree drop:', dropNode.label, dropType)
}
const allowDrop = (draggingNode: Node, dropNode: Node, type: AllowDropType) => {
if (dropNode.data.label === 'Level two 3-1') {
return type !== 'inner'
} else {
return true
}
}
const allowDrag = (draggingNode: Node) => {
return !draggingNode.data.label.includes('Level three 3-1-1')
}
//拖拽结束
//---------------------查看缩略图--------------------
var showImageRow = null
const showImage = (row: any) => {
showImageRow = row
eventBus.emit('imagePopDialog', row)
eventBus.emit('settingPop', false)
}
const handleContextMenu = (event: MouseEvent, row: TypeNode) => {
event.stopPropagation()
event.preventDefault()
contextMenu.currentRow = row
contextMenu.x = event.clientX
contextMenu.y = event.clientY
if (row.parentId) {
// 二级分类菜单
contextMenu.items = [
{ command: 'import', label: '导入军标', icon: 'importModel' },
{ command: 'rename', label: '重命名', icon: 'rename' },
{ command: 'delete', label: '删除', icon: 'delModel' }
]
} else {
// 一级分类菜单
contextMenu.items = [
{ command: 'add-child', label: '添加子类型', icon: 'add' },
{ command: 'import', label: '导入军标', icon: 'importModel' },
{ command: 'rename', label: '重命名', icon: 'rename' },
{ command: 'delete', label: '删除', icon: 'delModel' }
]
}
clickTreeNode = row
contextMenu.visible = true
}
const toggleExpand = (row: any) => {
if (row.childNodes.length != 0) {
// row._expanded = !row._expanded
// 这里需要调用el-table的toggleRowExpansion方法
// 需要通过ref获取table实例
// tableRef.value?.toggleRowExpansion(row, row._expanded)
if (row.expanded) {
row.collapse()
} else {
row.expand()
// getModelListByType(row.data.id)
}
} else {
// getModelListByType(row.data.id)
}
getModelListByType(row.data.id)
currentTypeId.value = row.id
// loadModelsByType(row.id)
contextMenu.visible && (contextMenu.visible = false)
}
const getModelListByType = (id) => {
let formData = new FormData()
formData.append('militaryTypeId', id)
GraphApi.showModelByType(formData).then((res) => {
modelList.value = res.data
})
}
const divContextMenu = (event: MouseEvent) => {
event.preventDefault()
contextMenu.x = event.clientX
contextMenu.y = event.clientY
clickTreeNode = null
contextMenu.items = [{ command: 'addType', label: '添加类型', icon: 'add' }]
contextMenu.visible = true
}
const handleMenuCommand = (command: string) => {
const row = contextMenu.currentRow
if (!row) {
//添加类型
handleAddType()
} else {
switch (command) {
case 'addType':
handleAddType()
break
case 'add-child':
handleAddChildType(row)
break
case 'import':
handleImportModel(row)
break
case 'rename':
handleRenameType(row)
break
case 'delete':
handleDeleteType(row)
break
}
}
}
const handleTypeClick = (row: TypeNode) => {
getModelListByType(row.id)
currentTypeId.value = row.$treeNodeId
// // 模拟根据类型ID加载模型数据
// loadModelsByType(row.id)
// contextMenu.visible && (contextMenu.visible = false)
}
const handleClick = () => {
contextMenu.visible && (contextMenu.visible = false)
}
const loadModelsByType = (typeId: string) => {
// 模拟数据加载
modelList.value = [
// {
// id: '1',
// typeId: typeId,
// name: `模型_${typeId}_1`,
// thumbnail: 'https://picsum.photos/200/150?random=1'
// },
// {
// id: '2',
// typeId: typeId,
// name: `模型_${typeId}_2`,
// thumbnail: 'https://picsum.photos/200/150?random=2'
// }
]
}
const handleAddType = () => {
dialogTitle.value = '添加军标类型'
modelType.value = ''
dialogVisible.value = true
}
const handleAddChildType = (row: TypeNode) => {
dialogTitle.value = '添加军标类型'
modelType.value = ''
dialogVisible.value = true
}
const handleImportModel = (row: TypeNode) => {
triggerUpload()
}
const handleRenameType = (row: TypeNode) => {
dialogTitle.value = '军标类型重命名'
modelType.value = row.label
dialogVisible.value = true
}
const handleDeleteType = (row: TypeNode) => {
ElMessageBox.confirm('是否删除数据?', '警告', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
.then(() => {
let formData = new FormData()
formData.append('militaryTypeId', row.id)
GraphApi.delModelType(formData).then((res) => {
if (res.code == 0 || res.code == 200) {
ElMessage.success('删除成功')
getModelList()
}
})
})
.catch(() => {})
}
const handleEdit = (row: ModelItem) => {
updatePoster(row)
}
const updatePoster1 = (row, flag = false, path = '') => {
let cb = (c) => {
const formData = new FormData()
formData.append('militaryId', row.id)
formData.append('file', c)
GraphApi.updatePoster(formData).then((res) => {
if (res.code == 0 || res.code == 200) {
getModelListByType(row.militaryTypeId)
ElMessage.success('添加成功')
}
})
}
if (!flag) {
let option = {
properties: ['openFile'],
filters: [
{
name: '军标',
extensions: ['svg']
}
]
}
$sendElectronChanel('open-directory-dialog', option)
$recvElectronChanel('selectedItem', (e, paths) => {
if (paths.length) {
cb(paths[0])
}
})
} else {
cb(path)
}
}
const updatePoster = (row, flag = false, path = '') => {
let that = this
let cb = (c) => {
const formData = new FormData()
formData.append('militaryId', row.id)
formData.append('file', c)
GraphApi.updatePoster(formData).then((res) => {
if (res.code == 0 || res.code == 200) {
getModelListByType(row.militaryTypeId)
ElMessage.success('添加成功')
}
})
}
if (!flag) {
let option = {
properties: ['openFile'],
filters: [
{
name: '军标',
extensions: ['svg']
}
]
}
$sendElectronChanel('open-directory-dialog', option)
$recvElectronChanel('selectedItem', (e, paths) => {
if (paths.length) {
// 取出路径中的文件名
let name = getNamefromPath(paths[0])
// 读取文件
fs.readFile(paths[0], (err, data) => {
const blob = new Blob([data], {
type: 'image/png, image/jpeg, image/jpg'
})
var file = new File([blob], `${name}` + '.png')
cb(file)
})
// cb(paths[0]);
}
})
} else {
cb(path)
}
}
const getNamefromPath = (path) => {
let index = 1
if (path.endsWith('.json')) {
index = 2
}
let arr = path.split('/')
let str = arr[arr.length - index]
let name = str
if (!path.endsWith('.json')) {
let arr1 = str.split('.')
arr1.pop()
name = arr1.join('.')
}
return name
}
const handleDelete = (row: ModelItem) => {
ElMessageBox.confirm('是否删除数据?', '警告', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
.then(() => {
let formData = new FormData()
formData.append('militaryId', row.id)
GraphApi.delModel(formData).then((res) => {
if (res.code == 0 || res.code == 200) {
ElMessage.success('删除成功')
getModelListByType(row.militaryTypeId)
}
})
})
.catch(() => {})
}
onMounted(() => {
getModelList()
})
</script>
<style scoped>
.model-management-container {
padding: 20px;
height: 100%;
}
.tree {
border-right: 1px solid rgba(var(--color-sdk-base-rgb), 0.5);
}
.tree-container {
height: 400px;
overflow-y: auto;
}
.el-row {
border: 1px solid rgba(var(--color-sdk-base-rgb), 0.5);
}
::v-deep .el-button--small {
padding: 5px 7px !important;
}
.el-button {
background-color: rgba(var(--color-sdk-base-rgb), 0.2) !important;
--el-button-text-color: rgba(255, 255, 255, 1) !important;
--el-button-border-color: rgba(var(--color-sdk-base-rgb), 0.2);
--el-button-hover-text-color: rgba(var(--color-sdk-base-rgb), 1) !important;
--el-button-hover-border-color: rgba(var(--color-sdk-base-rgb), 1) !important;
}
.primary-type {
font-weight: bold;
color: var(--el-color-primary);
}
::v-deep .el-scrollbar {
height: 360px !important;
overflow: auto;
}
.el-card {
--el-card-border-color: 1px solid rgba(var(--color-sdk-base-rgb), 0.5);
background-color: transparent !important;
}
.el-table {
--el-table-border: 1px solid rgba(var(--color-sdk-base-rgb), 0.5);
--el-table-header-bg-color: transparent !important;
--el-table-tr-bg-color: transparent !important;
--el-table-bg-color: transparent !important;
--el-table-current-row-bg-color: transparent !important;
--el-table-row-hover-bg-color: transparent !important;
--el-table-border-color: transparent !important;
--el-table-text-color: rgba(230, 247, 255, 1) !important;
--el-table-header-text-color: rgba(230, 247, 255, 1) !important;
font-size: 14px !important;
font-weight: 500 !important;
}
/* 一级菜单 */
.primary-type {
color: rgba(255, 255, 255, 1) !important;
font-size: 12px !important;
font-weight: 400 !important;
}
.tree .el-table {
--el-table-border: unset !important;
--el-table-text-color: rgba(255, 255, 255, 1) !important;
--el-table-header-text-color: rgba(255, 255, 255, 1) !important;
font-size: 12px !important;
font-weight: 400 !important;
}
::v-deep .tree .el-table__header-wrapper {
border-bottom: 1px solid rgba(var(--color-sdk-base-rgb), 0.5) !important;
}
.el-table__body {
height: 360px !important;
}
.el-table td.el-table__cell,
.el-table th.el-table__cell.is-leaf {
border-bottom: transparent !important;
height: 80px;
}
::v-deep .el-card.is-always-shadow,
::v-deep .el-card.is-hover-shadow:focus,
::v-deep .el-card.is-hover-shadow:hover {
box-shadow: transparent !important;
}
::v-deep .el-card.is-always-shadow,
::v-deep .el-card.is-hover-shadow:focus,
::v-deep .el-card.is-hover-shadow:hover {
box-shadow: transparent !important;
}
::v-deep .el-card__body {
padding: 0 !important;
}
::v-deep .el-col,
.el-col-6,
.is-guttered {
padding: 0 !important;
}
::v-deep .el-icon svg {
color: rgba(var(--color-sdk-base-rgb), 1) !important;
}
.selected-text {
color: rgba(var(--color-sdk-base-rgb), 1) !important; /* Element UI主色可自定义 */
}
::v-deep .el-table__expand-icon {
display: none !important;
}
::v-deep .el-tree-node__expand-icon {
display: none !important;
}
.el-table__empty-text {
line-height: 0px !important;
}
.noData {
height: 20px;
line-height: 20px;
font-size: 14px;
font-weight: 400;
margin-top: 10px;
}
.custom-empty {
display: flex;
justify-content: center; /* 水平居中 */
align-items: center; /* 垂直居中 */
flex-direction: column;
height: 300px;
}
.custom-empty img {
display: block;
width: 130px;
}
.el-tree {
background: transparent !important;
/* --el-tree-node-hover-bg-color: rgba(var(--color-sdk-base-rgb), 0.2) !important; */
--el-tree-node-hover-bg-color: unset !important;
color: rgba(255, 255, 255, 1) !important;
/* font-size: 12px !important; */
}
::v-deep .el-text {
color: rgba(255, 255, 255, 1) !important;
font-size: 12px !important;
}
::v-deep .el-input {
width: 300px;
margin-left: 30px;
--el-input-placeholder-color: rgba(173, 241, 255, 1) !important;
--el-input-placeholder-font-size: 14px;
--el-input-text-color: #fff !important;
--el-input-border-color: rgba(var(--color-sdk-base-rgb), 0.5) !important;
--el-input-hover-border-color: rgba(var(--color-sdk-base-rgb), 0.5) !important;
--el-input-focus-border-color: rgba(var(--color-sdk-base-rgb), 0.5) !important;
}
::v-deep .el-input__wrapper {
background-color: rgba(0, 0, 0, 0.5) !important;
}
::v-deep .el-dialog__title {
text-shadow: 0px 0px 9px var(--color-sdk-text-shadow) !important;
color: rgba(255, 255, 255, 1) !important;
}
</style>

View File

@ -1,443 +0,0 @@
<template>
<div class="model-management-container">
<div class="equipment_title" style="margin-bottom: 10px">
<el-button color="#004b4b" style="border: 1px solid rgba(0, 255, 255, 0.5)">
<template #icon>
<svg-icon name="leading_in" />
</template>
<span>选择模型库</span>
</el-button>
<el-button color="#004b4b" style="border: 1px solid rgba(0, 255, 255, 0.5)">
<template #icon>
<svg-icon name="leading_in" />
</template>
<span>创建模型库</span>
</el-button>
</div>
<el-row :gutter="20">
<!-- 左侧分类树 -->
<el-col :span="6" class="tree">
<el-card shadow="hover">
<div class="tree-container" @click="handleClick" @contextmenu="divContextMenu">
<el-table
:data="typeTreeData"
row-key="id"
ref="tableRef"
:tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
@row-contextmenu="handleContextMenu"
@row-click="handleTypeClick"
>
<el-table-column prop="name" label="模型类型" width="180">
<template #default="{ row }">
<span
:class="{
'primary-type': !row.parentId,
'selected-text': row.id === currentTypeId
}"
@click.stop="toggleExpand(row)"
class="allowDrag"
>
<svg-icon
:name="row._expanded ? 'arrow' : 'more'"
:size="12"
color="rgba(0, 255, 255, 1)"
style="margin-right: 5px"
v-if="row.parentId == null"
@click.stop="toggleExpand(row)"
></svg-icon>
{{ row.name }}</span
>
</template>
</el-table-column>
</el-table>
</div>
</el-card>
</el-col>
<!-- 右侧模型列表 -->
<el-col :span="18">
<el-card shadow="hover">
<el-table :data="modelList" border style="width: 100%">
<el-table-column type="index" label="序号" width="60" align="center" />
<el-table-column prop="name" label="模型名称" />
<el-table-column prop="thumbnail" label="缩略图" width="100">
<template #default="{ row }">
<el-image
style="width: 80px; height: 60px"
:src="row.thumbnail"
:preview-src-list="[row.thumbnail]"
fit="cover"
/>
</template>
</el-table-column>
<el-table-column label="操作">
<template #default="{ row }">
<!-- <el-button size="small" @click="handleEdit(row)">编辑</el-button> -->
<el-button size="small" @click="handleEdit(row)">预览</el-button>
<el-button size="small" @click="changePhoto(row)">更换缩略图</el-button>
<el-button size="small" @click="handleDelete(row)">删除</el-button>
</template>
</el-table-column>
<template #empty>
<div class="custom-empty">
<img src="@/assets/images/noData.png" alt="暂无数据" />
<div class="noData">暂无数据</div>
</div>
</template>
</el-table>
</el-card>
</el-col>
</el-row>
<!-- 右键菜单 -->
<contextMenuCom
v-model:visible="contextMenu.visible"
:x="contextMenu.x"
:y="contextMenu.y"
:menu-items="contextMenu.items"
@command="handleMenuCommand"
/>
</div>
</template>
<script lang="ts" setup>
import { ref, reactive, nextTick, onMounted } from 'vue'
import type { TableColumnCtx } from 'element-plus'
import contextMenuCom from './contentMenu.vue'
import Sortable from 'sortablejs'
interface TypeNode {
id: string
name: string
parentId: string | null
children?: TypeNode[]
}
interface ModelItem {
id: string
typeId: string
name: string
thumbnail: string
}
const typeTreeData = ref<TypeNode[]>([
{
id: '1',
name: '一级分类1',
parentId: null,
children: [
{ id: '1-1', name: '二级分类1-1', parentId: '1' },
{ id: '1-2', name: '二级分类1-2', parentId: '1' }
]
},
{
id: '2',
name: '一级分类2',
parentId: null,
children: [
{ id: '2-1', name: '二级分类2-1', parentId: '2' },
{ id: '2-2', name: '二级分类2-2', parentId: '2' }
]
}
])
const modelList = ref<ModelItem[]>([])
const currentTypeId = ref<string>('')
const contextMenu = reactive({
visible: false,
x: 0,
y: 0,
currentRow: null as TypeNode | null,
items: [] as { command: string; icon: string; label: string; disabled?: boolean }[]
})
const tableRef = ref()
// @ts-ignore
var sortableInstance: any = reactive(null)
//拖拽
const setSort = () => {
nextTick(() => {
const tbody = tableRef.value?.$el.querySelector('.el-table__body-wrapper tbody')
if (!tbody) {
console.warn('tbody 不存在,拖拽初始化失败')
return
}
// 销毁旧实例
if (sortableInstance) {
sortableInstance.destroy()
}
console.log('tbody', tbody)
// 创建新的拖拽实例
sortableInstance = Sortable.create(tbody, {
handle: '.allowDrag', // 指定拖拽区域
animation: 150,
onEnd: (evt) => {
console.log(evt, 'evt')
const movedItem = typeTreeData.value.splice(evt.oldIndex, 1)[0]
typeTreeData.value.splice(evt.newIndex, 0, movedItem)
console.log(typeTreeData, 'typeTreeData')
}
})
})
}
const handleContextMenu = (row: TypeNode, column: TableColumnCtx<TypeNode>, event: MouseEvent) => {
event.stopPropagation()
event.preventDefault()
contextMenu.currentRow = row
contextMenu.x = event.clientX
contextMenu.y = event.clientY
if (row.parentId) {
// 二级分类菜单
contextMenu.items = [
{ command: 'import', label: '导入模型', icon: 'importModel' },
{ command: 'rename', label: '重命名', icon: 'rename' },
{ command: 'delete', label: '删除', icon: 'delModel' }
]
} else {
// 一级分类菜单
contextMenu.items = [
{ command: 'add-child', label: '添加子类型', icon: 'add' },
{ command: 'import', label: '导入模型', icon: 'importModel' },
{ command: 'rename', label: '重命名', icon: 'rename' },
{ command: 'delete', label: '删除', icon: 'delModel' }
]
}
contextMenu.visible = true
}
const toggleExpand = (row: any) => {
if (row.parentId == null) {
row._expanded = !row._expanded
// 这里需要调用el-table的toggleRowExpansion方法
// 需要通过ref获取table实例
tableRef.value?.toggleRowExpansion(row, row._expanded)
}
currentTypeId.value = row.id
loadModelsByType(row.id)
contextMenu.visible && (contextMenu.visible = false)
}
const divContextMenu = (event: MouseEvent) => {
event.preventDefault()
contextMenu.x = event.clientX
contextMenu.y = event.clientY
console.log('空白右击')
contextMenu.items = [{ command: 'addType', label: '添加类型', icon: 'add' }]
contextMenu.visible = true
}
const handleMenuCommand = (command: string) => {
const row = contextMenu.currentRow
if (!row) return
switch (command) {
case 'add-child':
handleAddChildType(row)
break
case 'import':
handleImportModel(row)
break
case 'rename':
handleRenameType(row)
break
case 'delete':
handleDeleteType(row)
break
}
}
const handleTypeClick = (row: TypeNode) => {
// currentTypeId.value = row.id
// // 模拟根据类型ID加载模型数据
// loadModelsByType(row.id)
// contextMenu.visible && (contextMenu.visible = false)
}
const handleClick = () => {
contextMenu.visible && (contextMenu.visible = false)
}
const loadModelsByType = (typeId: string) => {
// 模拟数据加载
modelList.value = [
{
id: '1',
typeId: typeId,
name: `模型_${typeId}_1`,
thumbnail: 'https://picsum.photos/200/150?random=1'
},
{
id: '2',
typeId: typeId,
name: `模型_${typeId}_2`,
thumbnail: 'https://picsum.photos/200/150?random=2'
}
]
}
const handleAddChildType = (row: TypeNode) => {
console.log('添加子类型', row)
}
const handleImportModel = (row: TypeNode) => {
console.log('导入模型到', row)
}
const handleRenameType = (row: TypeNode) => {
console.log('重命名类型', row)
}
const handleDeleteType = (row: TypeNode) => {
console.log('删除类型', row)
}
const handleEdit = (row: ModelItem) => {
console.log('编辑模型', row)
}
const changePhoto = (row: ModelItem) => {
console.log('编辑模型', row)
}
const handleDelete = (row: ModelItem) => {
console.log('删除模型', row)
}
onMounted(() => {
setSort() //删除,新增都必须再调用一次
})
</script>
<style scoped>
.model-management-container {
padding: 20px;
height: 100%;
}
.tree {
border-right: 1px solid rgba(var(--color-sdk-base-rgb), 0.5);
}
.tree-container {
height: 400px;
overflow-y: auto;
}
.el-row {
border: 1px solid rgba(var(--color-sdk-base-rgb), 0.5);
}
::v-deep .el-button--small {
padding: 5px 7px !important;
}
.el-button {
background-color: rgba(var(--color-sdk-base-rgb), 0.2) !important;
--el-button-text-color: rgba(255, 255, 255, 1) !important;
--el-button-border-color: rgba(var(--color-sdk-base-rgb), 0.2);
--el-button-hover-text-color: rgba(var(--color-sdk-base-rgb), 1) !important;
--el-button-hover-border-color: rgba(var(--color-sdk-base-rgb), 1) !important;
}
.primary-type {
font-weight: bold;
color: var(--el-color-primary);
}
::v-deep .el-scrollbar {
height: 360px !important;
overflow: auto;
}
.el-card {
--el-card-border-color: 1px solid rgba(var(--color-sdk-base-rgb), 0.5);
background-color: transparent !important;
}
.el-table {
--el-table-border: 1px solid rgba(var(--color-sdk-base-rgb), 0.5);
--el-table-header-bg-color: transparent !important;
--el-table-tr-bg-color: transparent !important;
--el-table-bg-color: transparent !important;
--el-table-current-row-bg-color: transparent !important;
--el-table-row-hover-bg-color: transparent !important;
--el-table-border-color: transparent !important;
--el-table-text-color: rgba(230, 247, 255, 1) !important;
--el-table-header-text-color: rgba(230, 247, 255, 1) !important;
font-size: 14px !important;
font-weight: 500 !important;
}
/* 一级菜单 */
.primary-type {
color: rgba(255, 255, 255, 1) !important;
font-size: 14px !important;
font-weight: 500 !important;
}
.tree .el-table {
--el-table-border: unset !important;
--el-table-text-color: rgba(255, 255, 255, 1) !important;
--el-table-header-text-color: rgba(255, 255, 255, 1) !important;
font-size: 12px !important;
font-weight: 400 !important;
}
::v-deep .tree .el-table__header-wrapper {
border-bottom: 1px solid rgba(var(--color-sdk-base-rgb), 0.5) !important;
}
.el-table__body {
height: 360px !important;
}
.el-table td.el-table__cell,
.el-table th.el-table__cell.is-leaf {
border-bottom: transparent !important;
height: 80px;
}
::v-deep .el-card.is-always-shadow,
::v-deep .el-card.is-hover-shadow:focus,
::v-deep .el-card.is-hover-shadow:hover {
box-shadow: transparent !important;
}
::v-deep .el-card.is-always-shadow,
::v-deep .el-card.is-hover-shadow:focus,
::v-deep .el-card.is-hover-shadow:hover {
box-shadow: transparent !important;
}
::v-deep .el-card__body {
padding: 0 !important;
}
::v-deep .el-col,
.el-col-6,
.is-guttered {
padding: 0 !important;
}
::v-deep .el-icon svg {
color: rgba(var(--color-sdk-base-rgb), 1) !important;
}
.selected-text {
color: rgba(var(--color-sdk-base-rgb), 1) !important; /* Element UI主色可自定义 */
}
::v-deep .el-table__expand-icon {
display: none !important;
}
.el-table__empty-text {
line-height: 0px !important;
}
.noData {
height: 20px;
line-height: 20px;
font-size: 14px;
font-weight: 400;
margin-top: 10px;
}
.custom-empty {
display: flex;
justify-content: center; /* 水平居中 */
align-items: center; /* 垂直居中 */
flex-direction: column;
height: 300px;
}
.custom-empty img {
display: block;
width: 130px;
}
</style>

View File

@ -1,7 +1,11 @@
<template>
<div class="model-management-container">
<div class="equipment_title" style="margin-bottom: 10px">
<el-button color="#004b4b" style="border: 1px solid rgba(0, 255, 255, 0.5)" @click="importModelDB">
<el-button
color="#004b4b"
style="border: 1px solid rgba(0, 255, 255, 0.5)"
@click="importModelDB"
>
<template #icon>
<svg-icon name="leading_in" />
</template>
@ -112,8 +116,8 @@
/>
<!-- 添加类型弹窗 -->
<el-dialog v-model="dialogVisible" title="添加模型类型" width="30%" :before-close="handleClose">
<el-input v-model="modelType" placeholder="请输入模型类型" />
<el-dialog v-model="dialogVisible" :title="dialogTitle" width="30%" :before-close="handleClose">
<el-input v-model="modelType" placeholder="请输入模型类型名称" />
<template #footer>
<span class="dialog-footer">
<el-button @click="closeDialog">取消</el-button>
@ -121,7 +125,13 @@
</span>
</template>
</el-dialog>
<input ref="fileInput" type="file" hidden @change="handleFileChange" />
<input
ref="fileInput"
type="file"
hidden
@change="handleFileChange"
accept=".gltf,.glb,model/gltf-binary,model/gltf+json"
/>
</div>
</template>
@ -140,7 +150,7 @@ import {
$recvElectronChanel,
$changeComponentShow
} from '@/utils/communication'
const fs = require("fs");
const fs = require('fs')
const eventBus: any = inject('bus')
var clickTreeNode: any = reactive({})
@ -180,6 +190,7 @@ var sortableInstance: any = reactive(null)
//--------------添加模型类型----------------
var dialogVisible: any = ref(false)
var dialogTitle: any = ref('添加模型类型')
var modelType: any = ref('')
const handleClose = () => {
@ -194,6 +205,7 @@ const addType = () => {
if (!modelType.value) {
return ElMessage.warning('请输入模型类型名称')
}
if (dialogTitle.value == '添加模型类型') {
let params = {
name: modelType.value,
parentId: clickTreeNode && clickTreeNode.id ? clickTreeNode.id : undefined
@ -204,6 +216,19 @@ const addType = () => {
getModelList()
}
})
} else {
let params = {
name: modelType.value,
id: clickTreeNode.id
}
ModelApi.updateModelTypeName(params).then((res) => {
if (res.code == 0 || res.code == 200) {
ElMessage.success('修改成功')
getModelList()
}
})
}
modelType.value = ''
dialogVisible.value = false
}
@ -286,26 +311,26 @@ const createModelDB = async () => {
}
//导入模型库
const importModelDB = ()=>{
const importModelDB = () => {
let option = {
properties: ["openFile"],
properties: ['openFile'],
filters: [
{
name: '模型库', //、底图
extensions: ['model'],
},
],
};
$sendElectronChanel("open-directory-dialog", option);
$recvElectronChanel("selectedItem", (e, path) => {
if (path.length) addModelDB(path[0]);
});
extensions: ['model']
}
]
}
$sendElectronChanel('open-directory-dialog', option)
$recvElectronChanel('selectedItem', (e, path) => {
if (path.length) addModelDB(path[0])
})
}
const addModelDB = (path)=>{
const addModelDB = (path) => {
let formData = new FormData()
formData.append('modelPath',path)
ModelApi.importModelDB(formData).then(res=>{
formData.append('modelPath', path)
ModelApi.importModelDB(formData).then((res) => {
if (res.code == 0 || res.code == 200) {
ElMessage.success('导入成功')
getModelList()
@ -453,8 +478,8 @@ const handleMenuCommand = (command: string) => {
}
const handleTypeClick = (row: TypeNode) => {
console.log(row)
// currentTypeId.value = row.id
getModelListByType(row.id)
currentTypeId.value = row.$treeNodeId
// // 模拟根据类型ID加载模型数据
// loadModelsByType(row.id)
// contextMenu.visible && (contextMenu.visible = false)
@ -482,9 +507,13 @@ const loadModelsByType = (typeId: string) => {
}
const handleAddType = () => {
dialogTitle.value = '添加模型类型'
modelType.value = ''
dialogVisible.value = true
}
const handleAddChildType = (row: TypeNode) => {
dialogTitle.value = '添加模型类型'
modelType.value = ''
dialogVisible.value = true
}
@ -493,11 +522,12 @@ const handleImportModel = (row: TypeNode) => {
}
const handleRenameType = (row: TypeNode) => {
console.log('重命名类型', row)
dialogTitle.value = '模型类型重命名'
modelType.value = row.label
dialogVisible.value = true
}
const handleDeleteType = (row: TypeNode) => {
ElMessageBox.confirm('是否删除数据?', '警告', {
confirmButtonText: '确定',
cancelButtonText: '取消',
@ -521,7 +551,6 @@ const handleEdit = (row: ModelItem) => {
}
const updatePoster1 = (row, flag = false, path = '') => {
let cb = (c) => {
const formData = new FormData()
formData.append('modelId', row.id)
formData.append('file', c)
@ -553,10 +582,9 @@ const updatePoster1 = (row, flag = false, path = '') => {
}
}
const updatePoster = (row, flag = false, path = "")=> {
let that = this;
const updatePoster = (row, flag = false, path = '') => {
let that = this
let cb = (c) => {
const formData = new FormData()
formData.append('modelId', row.id)
formData.append('file', c)
@ -566,58 +594,57 @@ const updatePoster = (row, flag = false, path = "")=> {
ElMessage.success('添加成功')
}
})
};
}
if (!flag) {
let option = {
properties: ["openFile"],
properties: ['openFile'],
filters: [
{
name: "图片",
extensions: ["png", "jpg", "jpeg"],
},
],
};
$sendElectronChanel("open-directory-dialog", option);
$recvElectronChanel("selectedItem", (e, paths) => {
name: '图片',
extensions: ['png', 'jpg', 'jpeg']
}
]
}
$sendElectronChanel('open-directory-dialog', option)
$recvElectronChanel('selectedItem', (e, paths) => {
if (paths.length) {
// 取出路径中的文件名
let name = getNamefromPath(paths[0]);
let name = getNamefromPath(paths[0])
// 读取文件
fs.readFile(paths[0], (err, data) => {
const blob = new Blob([data], {
type: "image/png, image/jpeg, image/jpg",
});
var file = new File([blob], `${name}` + ".png");
cb(file);
});
type: 'image/png, image/jpeg, image/jpg'
})
var file = new File([blob], `${name}` + '.png')
cb(file)
})
// cb(paths[0]);
}
});
})
} else {
cb(path);
cb(path)
}
}
const getNamefromPath = (path) => {
let index = 1
if (path.endsWith('.json')) {
index = 2
}
let arr = path.split('/')
let str = arr[arr.length - index]
let name = str
if (!path.endsWith('.json')) {
let arr1 = str.split('.')
arr1.pop()
name = arr1.join('.')
}
const getNamefromPath = (path) => {
let index = 1;
if (path.endsWith(".json")) {
index = 2;
}
let arr = path.split("/");
let str = arr[arr.length - index];
let name = str;
if (!path.endsWith(".json")) {
let arr1 = str.split(".");
arr1.pop();
name = arr1.join(".");
}
return name;
return name
}
const handleDelete = (row: ModelItem) => {
ElMessageBox.confirm('是否删除数据?', '警告', {
confirmButtonText: '确定',
cancelButtonText: '取消',
@ -772,7 +799,8 @@ onMounted(() => {
}
.el-tree {
background: transparent !important;
--el-tree-node-hover-bg-color: rgba(var(--color-sdk-base-rgb), 0.2) !important;
/* --el-tree-node-hover-bg-color: rgba(var(--color-sdk-base-rgb), 0.2) !important; */
--el-tree-node-hover-bg-color: unset !important;
color: rgba(255, 255, 255, 1) !important;
/* font-size: 12px !important; */
}

View File

@ -25,6 +25,9 @@
<el-tab-pane :label="t('system.modelManage')" name="modelManage">
<modelManage></modelManage>
</el-tab-pane>
<el-tab-pane :label="t('system.graphLabelManage')" name="graphLabelManage">
<graphLabelManage></graphLabelManage>
</el-tab-pane>
<el-tab-pane :label="t('system.version')" name="version">
<version></version>
</el-tab-pane>
@ -41,6 +44,7 @@ import engineering from './components/engineering.vue'
import equipment from './components/equipment.vue'
import version from './components/version.vue'
import modelManage from './components/modelManage.vue'
import graphLabelManage from './components/graphLabelManage.vue'
import { useI18n } from 'vue-i18n'
const { t } = useI18n()

View File

@ -204,6 +204,16 @@ const handleClick = (item: any, e) => {
type: 'warning'
})
}
} else if (item.key === 'military') {
//军标库
if ((window as any).checkAuthIsValid) {
eventBus.emit('openGraph', true)
} else {
ElMessage({
message: '您没有该功能的权限',
type: 'warning'
})
}
}
}
const fold = () => {

View File

@ -4,7 +4,7 @@
<template #header>
<div class="set_pup_header">
<div class="system_title">
{{ t('model.title') }}
{{ t('graph.title') }}
</div>
</div>
</template>
@ -13,55 +13,81 @@
<el-input
v-model="modelName"
class="w-50 m-2"
placeholder="请输入模型名称进行搜索"
placeholder="请输入军标名称进行搜索"
:suffix-icon="Search"
/>
<button @click="setting" class="btn">
<svg-icon
name="sys_set"
class="setIcon"
:size="12"
color="rgba(var(--color-sdk-base-rgb), 1)"
color="rgba(255,255,255, 1)"
style="margin-right: 5px"
></svg-icon
>默认模型参数设置
>默认军标参数设置
</button>
</div>
<div class="content">
<!-- 左侧Tab导航 -->
<el-tabs
v-model="activeTab"
tab-position="left"
class="model-tabs"
@tab-click="handleTabClick"
<div class="treeCon">
<el-tree
style="max-width: 600px"
:data="typeTreeData"
ref="treeRef"
node-key="id"
@node-click="handleTypeClick"
:filter-node-method="filterNode"
>
<el-tab-pane
v-for="(category, index) in categories"
:key="index"
:label="category.name"
:name="index.toString()"
>
</el-tab-pane>
</el-tabs>
<template #default="{ node, data }">
<!-- <span> {{ node.label }}</span> -->
<div class="model-gallery" ref="galleryRef" @scroll="handleScroll">
<div
v-for="(category, cIndex) in categories"
:key="cIndex"
class="model-section"
:data-category="cIndex"
<span
:class="{
'primary-type': !(node.childNodes.length != 0),
'selected-text': node.id === currentTypeId
}"
@click.stop="toggleExpand(node)"
class="allowDrag"
>
<h2 class="section-title">{{ category.name }}</h2>
<svg-icon
:name="node.expanded ? 'arrow' : 'more'"
:size="12"
color="rgba(0, 255, 255, 1)"
style="margin-right: 5px; margin-left: 5px"
v-if="node.childNodes.length != 0"
@click.stop="toggleExpand(node)"
></svg-icon>
{{ node.label }}</span
>
</template>
</el-tree>
</div>
<div class="model-gallery" ref="galleryRef">
<div class="model-section">
<!-- <h2 class="section-title">{{ categories[Number(currentTypeId)].name }}</h2> -->
<div class="model-grid">
<div v-for="(model, mIndex) in category.models" :key="mIndex" class="model-item">
<div
v-for="(model, mIndex) in categories"
:key="mIndex"
class="model-item"
@click="modelClick(mIndex, model)"
>
<div class="imgbg">
<el-image :src="model.thumbnail" fit="cover" class="thumbnail">
<el-image
:src="'http://127.0.0.1:8848' + model.data"
fit="cover"
class="thumbnail"
>
<template #error>
<div class="image-error">加载失败</div>
</template>
</el-image>
</div>
<div class="model-name">{{ model.name }}</div>
<div class="model-name" :class="{ isactive: activeIndex == mIndex }">
{{ model.militaryName }}
</div>
</div>
</div>
</div>
@ -76,11 +102,16 @@
<script setup lang="ts">
import { useI18n } from 'vue-i18n'
import { Search } from '@element-plus/icons-vue'
import { ref, onMounted, onBeforeUnmount } from 'vue'
import { ref, onMounted, onBeforeUnmount, watch } from 'vue'
import { GraphApi } from '@/api/graphLabel/index'
import type { TabsPaneContext } from 'element-plus'
import { useTreeNode } from '../tree/hooks/treeNode'
import { TreeApi } from '@/api/tree'
const { t } = useI18n()
const { findParentId, findTreeIndex, cusAddNodes } = useTreeNode()
const isShowPup = ref(false)
const eventBus: any = inject('bus')
const { cusUpdateNode } = useTreeNode()
var modelName = ref('')
//tab
@ -92,53 +123,29 @@ interface Model {
interface Category {
id: string
name: string
models: Model[]
militaryName: string
poster: string
data: string
}
//
const categories = ref<Category[]>([
{
id: '0',
name: '建筑模型',
models: Array(10)
.fill(0)
.map((_, i) => ({
id: `b${i}`,
name: `建筑_${i}`,
thumbnail: `https://picsum.photos/300/200?random=${i}`
}))
},
{
id: '1',
name: '海军车',
models: Array(10)
.fill(0)
.map((_, i) => ({
id: `b${i}`,
name: `建筑_${i}`,
thumbnail: `https://picsum.photos/300/200?random=${i}`
}))
},
{
id: '2',
name: '装备车',
models: Array(10)
.fill(0)
.map((_, i) => ({
id: `b${i}`,
name: `建筑_${i}`,
thumbnail: `https://picsum.photos/300/200?random=${i}`
}))
}
// ...
])
const categories = ref<Category[]>([])
const activeTab = ref('0')
const galleryRef = ref<HTMLElement>()
const loading = ref(false)
let observer: IntersectionObserver | null = null
const treeRef: any = ref('')
watch(modelName, (val) => {
treeRef.value!.filter(val)
})
const filterNode: any = (value, data) => {
if (!value) return true
return data.label.includes(value)
}
// Tab
const handleTabClick = (tab: TabsPaneContext) => {
const section = document.querySelector(`.model-section[data-category="${tab.index}"]`)
@ -183,7 +190,7 @@ const loadMoreData = () => {
.fill(0)
.map((_, i) => ({
id: `n${i}`,
name: `新增模型_${i}`,
name: `新增军标_${i}`,
thumbnail: `https://picsum.photos/300/200?random=${i + 100}`
}))
})
@ -206,6 +213,152 @@ const handleScroll = () => {
})
}
//-----------tree-----------
const currentTypeId = ref<string>('')
var activeIndex: any = ref(null)
interface TypeNode {
id: string
label: string
parentId: string | null
children?: TypeNode[]
}
const typeTreeData = ref<TypeNode[]>([])
const toggleExpand = (row: any) => {
if (row.childNodes.length != 0) {
// row._expanded = !row._expanded
// el-tabletoggleRowExpansion
// reftable
// tableRef.value?.toggleRowExpansion(row, row._expanded)
if (row.expanded) {
row.collapse()
} else {
row.expand()
}
}
getModelListByType(row.data.id)
currentTypeId.value = row.id
// loadModelsByType(row.id)
}
const handleTypeClick = (row: TypeNode) => {
getModelListByType(row.id)
currentTypeId.value = row.$treeNodeId
}
let typeArr = {
point: '点',
line: '线',
area: '面'
}
const modelClick = (index, row) => {
activeIndex.value = index
// let selectedNode = window.treeObj.getSelectedNodes()[0]
// if(!selectedNode){
// ElMessage.warning('')
// return
// }
// if (!isSetting) {
// ElMessage.warning('')
// return
// }
isShowPup.value = false
let id = new YJ.Tools().randomString()
renderModel(row)
}
const renderModel = async (model) => {
let selectedNode = window.treeObj.getSelectedNodes()[0]
// if (data.positions.length > 0) {
// data.positions.forEach(async (position, index) => {
// let source_id = this.$md5(new Date().getTime() + model.model_name+index);
let id = new YJ.Tools().randomString()
let Draw = new YJ.Draw.DrawPoint(window.earth)
Draw.start((a, positions) => {
let option = {
id: id,
name: model.militaryName,
url: 'http://127.0.0.1:8848' + model.data,
position: positions
}
let GroundSvg = new YJ.Obj.GroundSvg(window.earth, option)
GroundSvg.load(() => {
GroundSvg.drag(true, (data) => {
let params = data
delete params.attributeType
delete params.attribute.ISC
delete params.attribute.camera
delete params.attribute.goods
delete params.attribute.vr
let params2 = {
id: params.id,
sourceName: params.name,
params: params,
isShow: params.show ? 1 : 0
}
TreeApi.updateDirectoryInfo(params2)
cusUpdateNode({ id: params.id, sourceName: params.name, params: JSON.stringify(params) })
})
let DbOption = {
params: option,
id,
sourceName: model.militaryName,
sourceType: 'military',
parentId: selectedNode
? selectedNode.sourceType == 'directory'
? selectedNode.id
: selectedNode.parentId
: undefined
}
TreeApi.addOtherSource(DbOption)
DbOption.isShow = true
DbOption.params = JSON.stringify(DbOption.params)
cusAddNodes(window.treeObj, DbOption.parentId, [DbOption])
})
})
}
const getModelListByType = (id) => {
let formData = new FormData()
formData.append('militaryTypeId', id)
GraphApi.showModelByType(formData).then((res) => {
categories.value = res.data
})
}
const getModelList = async () => {
const res: any = await GraphApi.modelTypeList()
if (res.code == 0 || res.code == 200) {
let data = transformNestedJson(res.data, 'name', 'label')
typeTreeData.value = data
}
}
const transformNestedJson = (data, oldKey, newKey) => {
if (Array.isArray(data)) {
return data.map((item) => transformNestedJson(item, oldKey, newKey))
} else if (data && typeof data === 'object') {
const newObj = {}
for (const key in data) {
//
const currentKey = key === oldKey ? newKey : key
//
newObj[currentKey] = transformNestedJson(data[key], oldKey, newKey)
}
return newObj
}
return data
}
onMounted(() => {
initObserver()
})
@ -215,9 +368,29 @@ onBeforeUnmount(() => {
})
//end
eventBus.on('openModel', (data) => {
eventBus.on('openGraph', (data) => {
isShowPup.value = data
if (data) {
getModelList()
getSetting()
}
})
eventBus.on('closeModelSet', (data) => {
isShowPup.value = data
if (data) {
getSetting()
}
})
//
var isSetting = null
const getSetting = () => {
// ModelApi.getModelSetting().then((res) => {
// if (res.code == 0 || res.code == 200) {
// isSetting = res.data[res.data.length - 1]
// }
// })
}
const open = () => {
isShowPup.value = true
}
@ -226,7 +399,7 @@ const close = () => {
}
const setting = () => {
isShowPup.value = false
eventBus.emit('openModelSetting', true)
eventBus.emit('openGraphSetting', (true, isSetting))
}
defineExpose({
@ -419,11 +592,19 @@ defineExpose({
height: 32px;
line-height: 32px;
background: rgba(var(--color-sdk-base-rgb), 0.2) !important;
border: 1px solid rgba(var(--color-sdk-base-rgb), 1) !important;
border: 1px solid rgba(var(--color-sdk-base-rgb), 0.5) !important;
border-radius: 4px;
color: rgba(var(--color-sdk-base-rgb), 1) !important;
color: #fff !important;
padding: 0 15px;
}
.btn:hover {
color: rgba(var(--color-sdk-base-rgb), 1) !important;
border: 1px solid rgba(var(--color-sdk-base-rgb), 1) !important;
.setIcon {
color: rgba(var(--color-sdk-base-rgb), 1) !important;
}
}
.content {
margin-top: 20px;
height: 400px;
@ -431,7 +612,7 @@ defineExpose({
}
</style>
<style scoped>
<style lang="scss" scoped>
.model-container {
display: flex;
height: 100vh;
@ -441,13 +622,20 @@ defineExpose({
height: 100%;
float: left;
}
.treeCon {
width: 140px;
height: 100%;
float: left;
border-right: 1px solid rgba(204, 204, 204, 0.2);
}
.model-gallery {
flex: 1;
/* padding: 20px; */
overflow-y: auto;
height: 100%;
width: calc(100% - 130px);
width: calc(100% - 160px);
float: left;
margin-left: 10px;
}
.model-section {
min-height: 10vh;
@ -459,11 +647,6 @@ defineExpose({
/* justify-content: space-around; */
gap: 20px;
}
.model-item {
border-radius: 8px;
overflow: hidden;
/* box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1); */
}
.model-name {
width: 100%;
height: 30px;
@ -472,6 +655,22 @@ defineExpose({
color: rgba(255, 255, 255, 1);
}
.isactive {
color: rgba(var(--color-sdk-base-rgb), 1) !important;
}
.model-item {
border-radius: 8px;
overflow: hidden;
/* box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1); */
}
.model-item:hover {
cursor: pointer !important;
color: rgba(var(--color-sdk-base-rgb), 1) !important;
.model-name {
color: rgba(var(--color-sdk-base-rgb), 1) !important;
}
}
.imgbg {
width: 70px;
height: 70px;
@ -479,10 +678,10 @@ defineExpose({
background-size: 100% 100%;
}
.thumbnail {
width: 66px;
height: 66px;
margin-left: 2px;
margin-top: 2px;
width: 64px;
height: 64px;
margin-left: 3px;
margin-top: 3px;
}
.loading-more {
text-align: center;
@ -522,4 +721,28 @@ defineExpose({
border-radius: 1em;
background-color: rgba(50, 50, 50, 0.1);
}
/* tree */
.el-tree-node__content > .el-tree-node__expand-icon {
display: none !important;
}
.el-tree {
background: transparent !important;
--el-tree-node-hover-bg-color: rgba(var(--color-sdk-base-rgb), 0.2) !important;
color: rgba(255, 255, 255, 1) !important;
/* font-size: 12px !important; */
width: 130px;
float: left;
margin-left: 10px;
}
::v-deep .el-text {
color: rgba(255, 255, 255, 1) !important;
font-size: 12px !important;
}
.selected-text {
color: rgba(var(--color-sdk-base-rgb), 1) !important; /* Element UI主色可自定义 */
}
::v-deep .el-tree--highlight-current .el-tree-node.is-current > .el-tree-node__content {
border-right: 1px solid rgba(var(--color-sdk-base-rgb), 0.2) !important;
}
</style>

View File

@ -0,0 +1,450 @@
<template>
<Dialog
ref="baseDialog"
:title="title + '属性'"
left="180px"
top="100px"
className="polygon"
:closeCallback="closeCallback"
>
<template #content>
<span class="custom-divider"></span>
<div class="div-item">
<div class="row" style="align-items: flex-start">
<div class="col">
<span class="label">名称</span>
<input class="input" maxlength="40" type="text" v-model="entityOptions.name" />
</div>
<div class="col">
<span class="label">颜色</span>
<div class="color" ref="colorRef"></div>
</div>
</div>
</div>
<span class="custom-divider"></span>
<div class="div-item">
<div class="row">
<div class="col">
<span class="label">旋转角度</span>
<input type="range" min="0" max="360" step="0.01" v-model="entityOptions.angle" />
<div class="input-number input-number-unit-1" style="width: auto; margin-left: 10px">
<input
style="width: 100px"
type="number"
title=""
min="0"
max="360"
step="0.1"
v-model="entityOptions.angle"
/>
<span class="unit">°</span>
<span class="arrow"></span>
</div>
</div>
</div>
<div class="row">
<div class="col">
<span class="label">X 轴大小</span>
<input
type="range"
min="0.001"
max="200"
step="0.001"
v-model="entityOptions.scale.x"
/>
<div class="input-number input-number-unit-1" style="width: auto; margin-left: 10px">
<input
style="width: 100px"
type="number"
title=""
min="0.001"
max="200"
step="0.001"
v-model="entityOptions.scale.x"
/>
<span class="arrow"></span>
</div>
</div>
</div>
<div class="row">
<div class="col">
<span class="label">Y 轴大小</span>
<input
type="range"
min="0.001"
max="200"
step="0.001"
v-model="entityOptions.scale.y"
/>
<div class="input-number input-number-unit-1" style="width: auto; margin-left: 10px">
<input
style="width: 100px"
type="number"
title=""
min="0.001"
max="200"
step="0.001"
v-model="entityOptions.scale.y"
/>
<span class="arrow"></span>
</div>
</div>
</div>
</div>
<span class="custom-divider"></span>
<div class="div-item">
<div class="row">
<div class="col" style="flex: 5">
<span class="label">文字内容</span>
<input class="input" maxlength="40" type="text" v-model="entityOptions.textValue" />
</div>
<div class="col">
<button class="btn" @click="textPosPick">设置位置</button>
</div>
</div>
<div class="row">
<div class="col">
<span class="label">文字开关</span>
<input class="btn-switch" type="checkbox" v-model="entityOptions.textShow" />
</div>
<div class="col">
<span class="label">字体颜色</span>
<div class="textColor" ref="textColorRef"></div>
</div>
<div class="col">
<span class="label">字体大小</span>
<div class="input-number input-number-unit-2">
<input
class="input"
type="number"
title=""
min="1"
max="99"
v-model="entityOptions.textFontSize"
/>
<span class="unit">px</span>
<span class="arrow"></span>
</div>
</div>
</div>
<div class="row">
<div class="col">
<div class="col">
<span class="label">视野缩放</span>
<input
class="btn-switch"
type="checkbox"
v-model="entityOptions.textScaleByDistance"
/>
</div>
</div>
<div class="col">
<span class="label">最近距离</span>
<div class="input-number input-number-unit-2">
<input
class="input"
type="number"
title=""
min="1"
max="99999999"
v-model="entityOptions.textNear"
/>
<span class="unit">m</span>
<span class="arrow"></span>
</div>
</div>
<div class="col">
<span class="label">最远距离</span>
<div class="input-number input-number-unit-2">
<input
class="input"
type="number"
title=""
min="1"
max="99999999"
v-model="entityOptions.textFar"
/>
<span class="unit">m</span>
<span class="arrow"></span>
</div>
</div>
</div>
</div>
<span class="custom-divider"></span>
<div class="div-item">
<div class="row">
<attribute :entityOptions="entityOptions"></attribute>
</div>
</div>
</template>
<template #footer>
<button @click="nodeEdit">
<svg class="icon-edit">
<use xlink:href="#yj-icon-edit"></use></svg
>编辑
</button>
<button @click="returnX">X轴翻转</button>
<button @click="returnY">Y轴翻转</button>
<button @click="remove">删除</button>
<button @click="confirm">确定</button>
<button @click="close">关闭</button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import { inject } from 'vue'
import { TreeApi } from '@/api/tree'
import Dialog from '@/components/dialog/baseDialog.vue'
import attribute from './attribute.vue'
import labelStyle from './labelStyle.vue'
import { useTreeNode } from '@/views/components/tree/hooks/treeNode'
import { getFontList } from './fontSelect'
const { cusUpdateNode } = useTreeNode()
const fontList = ref(getFontList())
const title = ref('军标')
const baseDialog: any = ref(null)
const eventBus: any = inject('bus')
const options = ref({})
const equalSwitch = ref(true) //是否等比例缩放
const colorRef = ref(null)
const textColorRef = ref(null)
const labelLineColorRef = ref(null)
const labelBackgroundColorStartRef = ref(null)
const labelBackgroundColorEndRef = ref(null)
eventBus.on('openPolygonEdit', () => {
baseDialog.value?.open()
})
const area = ref(0)
const height = ref(10)
const activeName = ref('1')
const activeTd = ref({
index: -1,
name: ''
})
const positions = ref([])
const heightMode = ref(0)
const entityOptions: any = ref({})
let originalOptions: any
let that: any
const scaleChange = () => {
entityOptions.value.scaleY = entityOptions.value.scaleX
entityOptions.value.scaleZ = entityOptions.value.scaleX
}
const open = async (id: any, type: any) => {
that = window.earth.entityMap.get(id)
originalOptions = structuredClone(that.options)
entityOptions.value = that
heightMode.value = entityOptions.value.heightMode
area.value = entityOptions.value.areaByMeter
positions.value = structuredClone(that.options.positions)
heightModeChange(heightMode.value)
baseDialog.value?.open()
await nextTick()
let colorPicker = new window.YJColorPicker({
el: colorRef.value,
size: 'mini', //颜色box类型
alpha: true, //是否开启透明度
defaultColor: entityOptions.value.color,
disabled: false, //是否禁止打开颜色选择器
openPickerAni: 'opacity', //打开颜色选择器动画
sure: (color) => {
entityOptions.value.color = color
}, //点击确认按钮事件回调
clear: () => {
entityOptions.value.color = 'rgba(255,255,255,1)'
} //点击清空按钮事件回调
})
let linecolorPicker = new window.YJColorPicker({
el: textColorRef.value,
size: 'mini', //颜色box类型
alpha: true, //是否开启透明度
defaultColor: entityOptions.value.textColor,
disabled: false, //是否禁止打开颜色选择器
openPickerAni: 'opacity', //打开颜色选择器动画
sure: (color) => {
entityOptions.value.textColor = color
}, //点击确认按钮事件回调
clear: () => {
entityOptions.value.textColor = 'rgba(255,255,255,1)'
} //点击清空按钮事件回调
})
let ylinecolorPicker = new window.YJColorPicker({
el: labelLineColorRef.value,
size: 'mini', //颜色box类型
alpha: true, //是否开启透明度
defaultColor: entityOptions.value.labelLineColor,
disabled: false, //是否禁止打开颜色选择器
openPickerAni: 'opacity', //打开颜色选择器动画
sure: (color) => {
entityOptions.value.labelLineColor = color
}, //点击确认按钮事件回调
clear: () => {
entityOptions.value.labelLineColor = 'rgba(255,255,255,1)'
} //点击清空按钮事件回调
})
let bgcolorPicker1 = new window.YJColorPicker({
el: labelBackgroundColorStartRef.value,
size: 'mini', //颜色box类型
alpha: true, //是否开启透明度
defaultColor: entityOptions.value.labelBackgroundColorStart,
disabled: false, //是否禁止打开颜色选择器
openPickerAni: 'opacity', //打开颜色选择器动画
sure: (color) => {
entityOptions.value.labelBackgroundColorStart = color
}, //点击确认按钮事件回调
clear: () => {
entityOptions.value.labelBackgroundColorStart = 'rgba(255,255,255,1)'
} //点击清空按钮事件回调
})
let bgcolorPicker2 = new window.YJColorPicker({
el: labelBackgroundColorEndRef.value,
size: 'mini', //颜色box类型
alpha: true, //是否开启透明度
defaultColor: entityOptions.value.labelBackgroundColorEnd,
disabled: false, //是否禁止打开颜色选择器
openPickerAni: 'opacity', //打开颜色选择器动画
sure: (color) => {
entityOptions.value.labelBackgroundColorEnd = color
}, //点击确认按钮事件回调
clear: () => {
entityOptions.value.labelBackgroundColorEnd = 'rgba(255,255,255,1)'
} //点击清空按钮事件回调
})
}
const textPosPick = (val) => {
that.textPosPick()
}
const heightModeChange = (val) => {
that.heightMode = heightMode.value
}
const returnX = (val) => {
that.flipeX = !that.flipeX
}
const returnY = (val) => {
that.flipeY = !that.flipeY
}
const heightConfirm = () => {
if (entityOptions.value.operate.positionEditing) {
that.positionEditing = false
entityOptions.value.height = Number(
(entityOptions.value.height + Number(height.value)).toFixed(2)
)
} else {
that.closeNodeEdit(this)
that.heightMode = that.heightMode
setTimeout(() => {
entityOptions.value.height = Number(
(entityOptions.value.height + Number(height.value)).toFixed(2)
)
}, 100)
}
}
const inputDblclick = async (event, i, anme) => {
if (heightMode.value == 2) {
return
}
activeTd.value = {
index: i,
name: anme
}
await nextTick()
let inputElm = event.target.getElementsByClassName('input')[0]
if (inputElm) {
inputElm.focus()
}
}
const inputBlurCallBack = (event, i, name, digit = 2) => {
activeTd.value = {
index: -1,
name: ''
}
}
var moveFlag: any = ref(false)
const closeCallback = () => {
entityOptions.value.originalOptions = structuredClone(originalOptions)
that.positionEditing = false
// entityOptions.value.closeNodeEdit()
entityOptions.value.reset()
eventBus.emit('destroyComponent')
}
const nodeEdit = () => {
console.log(entityOptions.value._isdrag, '_isdrag')
that.drag(!entityOptions.value._isdrag, (data) => {
console.log(data, 'data')
that.options = data
})
}
const confirm = () => {
originalOptions = structuredClone(that.options)
that.drag(false)
baseDialog.value?.close()
let params = structuredClone(that.options)
delete params.attributeType
delete params.attribute.ISC
delete params.attribute.camera
delete params.attribute.goods
delete params.attribute.vr
let params2 = {
id: params.id,
sourceName: params.name,
params: params,
isShow: params.show ? 1 : 0
}
TreeApi.updateDirectoryInfo(params2)
cusUpdateNode({ id: params.id, sourceName: params.name, params: JSON.stringify(params) })
}
const close = () => {
that.drag(false)
that.reset()
baseDialog.value?.close()
}
const remove = () => {
that.remove()
close()
}
//-----------------方法-----------------------
defineExpose({
open,
close
})
</script>
<style scoped lang="scss">
::v-deep .el-checkbox.el-checkbox--large .el-checkbox__label {
color: #fff !important;
}
::v-deep .el-select__wrapper {
background-color: rgba(0, 0, 0, 0.5) !important;
box-shadow: 0 0 0 1px rgba(var(--color-sdk-base-rgb), 0.5) inset !important;
}
::v-deep .el-select {
--el-select-input-focus-border-color: rgba(var(--color-sdk-base-rgb), 0.5) !important;
--el-select-text-color: #fff;
--el-select-border-color: rgba(var(--color-sdk-base-rgb), 0.5) !important;
--el-select-hover-border-color: rgba(var(--color-sdk-base-rgb), 0.5) !important;
--el-select-multiple-input-color: #fff !important;
}
::v-deep .el-select__placeholder {
color: rgba(204, 204, 204, 1) !important;
}
</style>

View File

@ -0,0 +1,157 @@
<template>
<Dialog
ref="baseDialog"
title="默认军标参数设置"
left="180px"
top="100px"
:closeCallback="closeCallBack"
>
<template #content>
<span class="custom-divider"></span>
<div class="div-item">
<div class="row">
<div class="col">
<span class="label">添加方式</span>
<div class="input-number input-number-unit-1">
<el-select
v-model="type"
class="m-2"
placeholder="请选择添加方式"
style="width: 240px"
@change="typeChange"
>
<el-option
v-for="item in options"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</div>
</div>
<div class="col" v-show="showDis">
<span class="label">间距</span>
<div class="input-number input-number-unit-1">
<input
id="modelDistance"
type="number"
title=""
min="0"
max="999999"
step="0.1"
placeholder="请输入数值"
v-model="distance"
@input="viewPointHeightInput"
@change="clangeViewPointHeight"
/>
<span class="unit">m</span>
<span class="arrow"></span>
</div>
</div>
</div>
</div>
</template>
<template #footer>
<button @click="save">保存</button>
<button @click="close">关闭</button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import { ref, reactive } from 'vue'
import { inject } from 'vue'
import { ModelApi } from '@/api/model/index'
import Dialog from '@/components/dialog/baseDialog.vue'
import { ElMessage, ElMessageBox } from 'element-plus'
const baseDialog: any = ref(null)
const eventBus: any = inject('bus')
const viewPointHeight: any = ref(1.8)
var visibility: any = reactive([])
var showDis: any = ref(false)
var type: any = ref('point')
var distance: any = ref(null)
const options = [
{
value: 'point',
label: '点'
},
{
value: 'line',
label: '线'
},
{
value: 'area',
label: '面'
}
]
eventBus.on('openGraphSetting', (show, data) => {
baseDialog.value?.open()
show && (type.value = show.key)
show && (distance.value = show.value * 1)
typeChange()
})
const typeChange = () => {
switch (type.value) {
case 'point':
showDis.value = false
break
case 'line':
showDis.value = true
break
case 'area':
showDis.value = true
break
}
}
const clangeViewPointHeight = () => {}
const viewPointHeightInput = () => {
let dom: any = document.getElementById('modelDistance')
if (viewPointHeight.value < dom.min * 1) {
viewPointHeight.value = dom.min * 1
} else if (viewPointHeight.value > dom.max * 1) {
viewPointHeight.value = dom.max * 1
}
}
const closeCallBack = (e) => {
type.value = 'point'
distance.value = null
eventBus.emit('closeModelSet', true)
}
const close = () => {
baseDialog.value?.close()
}
const save = () => {
ModelApi.modelSetting({
key: type.value,
value: showDis.value ? distance.value : ''
}).then((res) => {
if (res.code == 0 || res.code == 200) {
ElMessage.success('设置成功')
baseDialog.value?.close()
}
})
}
</script>
<style scoped lang="scss">
::v-deep .el-select__wrapper {
background-color: rgba(0, 0, 0, 0.5) !important;
box-shadow: 0 0 0 1px rgba(var(--color-sdk-base-rgb), 0.5) inset !important;
}
::v-deep .el-select {
--el-select-input-focus-border-color: rgba(var(--color-sdk-base-rgb), 0.5) !important;
--el-select-text-color: #fff;
--el-select-border-color: rgba(var(--color-sdk-base-rgb), 0.5) !important;
--el-select-hover-border-color: rgba(var(--color-sdk-base-rgb), 0.5) !important;
--el-select-multiple-input-color: #fff !important;
}
::v-deep .el-select__placeholder {
color: rgba(204, 204, 204, 1) !important;
}
</style>

View File

@ -30,7 +30,14 @@
<div class="content">
<!-- 左侧Tab导航 -->
<div class="treeCon">
<el-tree style="max-width: 600px" :data="typeTreeData" ref="treeRef" node-key="id">
<el-tree
style="max-width: 600px"
:data="typeTreeData"
ref="treeRef"
node-key="id"
@node-click="handleTypeClick"
:filter-node-method="filterNode"
>
<template #default="{ node, data }">
<!-- <span> {{ node.label }}</span> -->
@ -95,7 +102,7 @@
<script setup lang="ts">
import { useI18n } from 'vue-i18n'
import { Search } from '@element-plus/icons-vue'
import { ref, onMounted, onBeforeUnmount } from 'vue'
import { ref, onMounted, onBeforeUnmount, watch } from 'vue'
import { ModelApi } from '@/api/model/index'
import type { TabsPaneContext } from 'element-plus'
import { useTreeNode } from '../tree/hooks/treeNode'
@ -128,6 +135,16 @@ const galleryRef = ref<HTMLElement>()
const loading = ref(false)
let observer: IntersectionObserver | null = null
const treeRef: any = ref('')
watch(modelName, (val) => {
treeRef.value!.filter(val)
})
const filterNode: any = (value, data) => {
if (!value) return true
return data.label.includes(value)
}
// 处理Tab点击
const handleTabClick = (tab: TabsPaneContext) => {
const section = document.querySelector(`.model-section[data-category="${tab.index}"]`)
@ -208,7 +225,6 @@ interface TypeNode {
const typeTreeData = ref<TypeNode[]>([])
const toggleExpand = (row: any) => {
console.log('opoop')
if (row.childNodes.length != 0) {
// row._expanded = !row._expanded
// 这里需要调用el-table的toggleRowExpansion方法
@ -226,13 +242,18 @@ const toggleExpand = (row: any) => {
// loadModelsByType(row.id)
}
const addType = ref('')
const handleTypeClick = (row: TypeNode) => {
getModelListByType(row.id)
currentTypeId.value = row.$treeNodeId
}
let typeArr = {
point: '点',
line: '线',
area: '面'
}
const modelClick = (index, row) => {
console.log(row, 'dddddd')
activeIndex.value = index
// let selectedNode = window.treeObj.getSelectedNodes()[0]
// if(!selectedNode){
@ -263,8 +284,6 @@ const modelClick = (index, row) => {
url: 'http://127.0.0.1:8848' + isSetting[row.data]
},
function (data) {
console.log('data,url,source_id', data, row)
// posiArr.forEach((item, index) => {
// let model = new Model(that.sdk, {
// id: 'model' + index,
@ -298,10 +317,10 @@ const renderModel = async (data, model) => {
position,
name: model.modelName + index,
show: true,
scale: 1,
scale: { x: 1, y: 1, z: 1 },
url: model.data,
maximumScale: 1,
host: 'http://127.0.0.1:8848',
// host: 'http://127.0.0.1:8848',
rotate: {
x: 0,
y: 0,
@ -349,7 +368,6 @@ const getModelListByType = (id) => {
let formData = new FormData()
formData.append('modelTypeId', id)
ModelApi.showModelByType(formData).then((res) => {
console.log(res.data, 'cccc')
categories.value = res.data
})
}
@ -401,7 +419,6 @@ eventBus.on('closeModelSet', (data) => {
selectCallback = null
isShowPup.value = data
if (data) {
console.log('设置后')
getSetting()
}
})
@ -412,7 +429,6 @@ const getSetting = () => {
ModelApi.getModelSetting().then((res) => {
if (res.code == 0 || res.code == 200) {
isSetting = res.data[res.data.length - 1]
console.log(res, 'resres')
}
})
}

View File

@ -16,7 +16,7 @@
<input class="input" maxlength="40" type="text" v-model="entityOptions.name" />
</div>
<div class="col">
<span class="label">颜色</span>
<span class="label">颜色</span>
<div class="color" ref="colorRef"></div>
</div>
</div>
@ -26,21 +26,25 @@
<div class="row" style="align-items: flex-start">
<div class="col">
<span class="label">经度</span>
<input class="input" maxlength="40" type="text" v-model="entityOptions.name" />
<input
class="input"
type="number"
title=""
min="-180"
max="180"
v-model="entityOptions.lng"
/>
</div>
<div class="col">
<span class="label">最大比例</span>
<div
class="input-number input-number-unit-1 height-box"
:class="{ disabled: heightMode == 2 }"
>
<div class="input-number input-number-unit-1">
<input
class="input height"
type="number"
title=""
min="-9999999"
max="999999999"
v-model="height"
min="0.1"
max="99999"
v-model="entityOptions.maximumScale"
/>
<span class="unit"></span>
<span class="arrow"></span>
@ -50,23 +54,27 @@
<div class="row" style="align-items: flex-start">
<div class="col">
<span class="label">纬度</span>
<input class="input" maxlength="40" type="text" v-model="entityOptions.name" />
<input
class="input"
type="number"
title=""
min="-90"
max="90"
v-model="entityOptions.lat"
/>
</div>
<div class="col">
<span class="label">最小像素</span>
<div
class="input-number input-number-unit-1 height-box"
:class="{ disabled: heightMode == 2 }"
>
<div class="input-number input-number-unit-1">
<input
class="input height"
class="input"
type="number"
title=""
min="-9999999"
max="999999999"
v-model="height"
min="1"
max="99999"
v-model="entityOptions.minimumPixelSize"
/>
<span class="unit"></span>
<span class="unit">px</span>
<span class="arrow"></span>
</div>
</div>
@ -74,17 +82,14 @@
<div class="row" style="align-items: flex-start">
<div class="col">
<span class="label">高度</span>
<div
class="input-number input-number-unit-1 height-box"
:class="{ disabled: heightMode == 2 }"
>
<div class="input-number input-number-unit-1">
<input
class="input height"
type="number"
title=""
min="-9999999"
max="999999999"
v-model="height"
min="-99999"
max="9999999"
v-model="entityOptions.alt"
/>
<span class="unit">m</span>
<span class="arrow"></span>
@ -92,7 +97,7 @@
</div>
<div class="col">
<span class="label">固定大小</span>
<input class="btn-switch" type="checkbox" v-model="entityOptions.labelShow" />
<input class="btn-switch" type="checkbox" v-model="entityOptions.scaleByDistance" />
</div>
</div>
</div>
@ -114,9 +119,9 @@
<input
type="range"
min="0"
max="1"
max="360"
step="0.01"
v-model="entityOptions.transparency"
v-model="entityOptions.rotateX"
/>
<div
class="input-number input-number-unit-1"
@ -128,7 +133,7 @@
title=""
min="0"
max="360"
v-model="entityOptions.transparency"
v-model="entityOptions.rotateX"
/>
<span class="unit">°</span>
<span class="arrow"></span>
@ -141,9 +146,9 @@
<input
type="range"
min="0"
max="1"
max="360"
step="0.01"
v-model="entityOptions.transparency"
v-model="entityOptions.rotateY"
/>
<div
class="input-number input-number-unit-1"
@ -155,7 +160,7 @@
title=""
min="0"
max="360"
v-model="entityOptions.transparency"
v-model="entityOptions.rotateY"
/>
<span class="unit">°</span>
<span class="arrow"></span>
@ -168,9 +173,9 @@
<input
type="range"
min="0"
max="1"
max="360"
step="0.01"
v-model="entityOptions.transparency"
v-model="entityOptions.rotateZ"
/>
<div
class="input-number input-number-unit-1"
@ -182,7 +187,7 @@
title=""
min="0"
max="360"
v-model="entityOptions.transparency"
v-model="entityOptions.rotateZ"
/>
<span class="unit">°</span>
<span class="arrow"></span>
@ -192,37 +197,287 @@
</div>
<div class="row">
<div class="row">
<div width="46%">
<div class="col" style="flex: 0 0 50px">
<p class="lable-left-line">缩放</p>
<el-checkbox
v-model="entityOptions.transparency"
label="是否等比例缩放"
size="large"
</div>
<div class="col">
<el-checkbox v-model="equalSwitch" label="是否等比例缩放" size="large" />
</div>
</div>
<div class="row" v-if="equalSwitch">
<div class="col">
<span class="label">等比例缩放</span>
<input
type="range"
min="0"
max="99999"
step="1"
@change="scaleChange"
v-model="entityOptions.scaleX"
/>
<div
class="input-number input-number-unit-1"
style="width: auto; margin-left: 10px"
>
<input
style="width: 100px"
type="number"
title=""
min="0"
max="360"
@change="scaleChange"
v-model="entityOptions.scaleX"
/>
<span class="unit"></span>
<span class="arrow"></span>
</div>
</div>
</div>
<div class="row" v-if="!equalSwitch">
<div class="col">
<span class="label">x </span>
<input
type="range"
min="0"
max="99999"
step="0.01"
v-model="entityOptions.scaleX"
/>
<div
class="input-number input-number-unit-1"
style="width: auto; margin-left: 10px"
>
<input
style="width: 100px"
type="number"
title=""
min="0"
max="360"
v-model="entityOptions.scaleX"
/>
<span class="unit">°</span>
<span class="arrow"></span>
</div>
</div>
</div>
<div class="row" v-if="!equalSwitch">
<div class="col">
<span class="label">y </span>
<input
type="range"
min="0"
max="99999"
step="0.01"
v-model="entityOptions.scaleY"
/>
<div
class="input-number input-number-unit-1"
style="width: auto; margin-left: 10px"
>
<input
style="width: 100px"
type="number"
title=""
min="0"
max="360"
v-model="entityOptions.scaleY"
/>
<span class="unit">°</span>
<span class="arrow"></span>
</div>
</div>
</div>
<div class="row" v-if="!equalSwitch">
<div class="col">
<span class="label">z </span>
<input
type="range"
min="0"
max="99999"
step="0.01"
v-model="entityOptions.scaleZ"
/>
<div
class="input-number input-number-unit-1"
style="width: auto; margin-left: 10px"
>
<input
style="width: 100px"
type="number"
title=""
min="0"
max="360"
v-model="entityOptions.scaleZ"
/>
<span class="unit">°</span>
<span class="arrow"></span>
</div>
</div>
</div>
</div>
<div class="row">
<div class="row">
<p class="lable-left-line">高度</p>
</div>
<div class="row">
<div class="col">
<span class="label">高度</span>
<input
type="range"
min="-99999"
max="999999"
step="0.01"
v-model="entityOptions.alt"
/>
<div
class="input-number input-number-unit-1"
style="width: auto; margin-left: 10px"
>
<input
style="width: 100px"
type="number"
title=""
min="0"
max="360"
v-model="entityOptions.alt"
/>
<span class="unit">m</span>
<span class="arrow"></span>
</div>
</div>
</div>
</div>
</el-tab-pane>
<el-tab-pane label="标风格" name="3">
<el-tab-pane label="标风格" name="3">
<div class="row">
<!-- <div class="col">
<span class="label">面颜色</span>
<div class="color" ref="colorRef"></div>
</div> -->
<div class="col">
<span class="label">描边颜色</span>
<div class="lineColor" ref="lineColorRef"></div>
<span class="label">标注开关</span>
<input class="btn-switch" type="checkbox" v-model="entityOptions.labelShow" />
</div>
</div>
<div class="row">
<div class="col">
<span class="label">字体颜色</span>
<div class="labelColor" ref="labelColorRef"></div>
</div>
<div class="col font-select-box">
<span class="label" style="flex: none">字体选择</span>
<el-select
class="input input-select font-select"
style="width: 100px"
v-model="entityOptions.labelFontFamily"
>
<el-option
v-for="item in fontList"
:key="item.key"
:label="item.name"
:value="item.key"
>
</el-option>
</el-select>
</div>
<div class="col">
<span class="label">描边宽度</span>
<span class="label">字体大小</span>
<div class="input-number input-number-unit-2">
<input
class="input"
type="number"
title=""
min="1"
max="99"
v-model="entityOptions.labelFontSize"
/>
<span class="unit">px</span>
<span class="arrow"></span>
</div>
</div>
</div>
<div class="row">
<div class="col">
<div class="col">
<span class="label">视野缩放</span>
<input
class="btn-switch"
type="checkbox"
v-model="entityOptions.labelScaleByDistance"
/>
</div>
</div>
<div class="col">
<span class="label">最近距离</span>
<div class="input-number input-number-unit-2">
<input
class="input"
type="number"
title=""
min="1"
max="99999999"
v-model="entityOptions.labelNear"
/>
<span class="unit">m</span>
<span class="arrow"></span>
</div>
</div>
<div class="col">
<span class="label">最远距离</span>
<div class="input-number input-number-unit-2">
<input
class="input"
type="number"
title=""
min="1"
max="99999999"
v-model="entityOptions.labelFar"
/>
<span class="unit">m</span>
<span class="arrow"></span>
</div>
</div>
</div>
</el-tab-pane>
<el-tab-pane label="标签风格" name="4">
<div class="row">
<div class="col">
<span class="label">引线颜色</span>
<div class="labelLineColor" ref="labelLineColorRef"></div>
</div>
<div class="col">
<span class="label">背景颜色</span>
<div class="labelBackgroundColorStart" ref="labelBackgroundColorStartRef"></div>
<div
class="labelBackgroundColorEnd"
ref="labelBackgroundColorEndRef"
style="margin-left: 10px"
></div>
</div>
</div>
<div class="row">
<div class="col">
<span class="label">引线宽度</span>
<div class="input-number input-number-unit-2">
<input
class="input"
type="number"
title=""
min="1"
max="999"
v-model="entityOptions.labelLineWidth"
/>
<span class="unit">px</span>
<span class="arrow"></span>
</div>
</div>
<div class="col">
<span class="label">引线长度</span>
<div class="input-number input-number-unit-2">
<input
class="input"
type="number"
title=""
min="0"
max="99"
v-model="entityOptions.lineWidth"
max="999"
v-model="entityOptions.labelPixelOffset"
/>
<span class="unit">px</span>
<span class="arrow"></span>
@ -230,13 +485,9 @@
</div>
</div>
</el-tab-pane>
<el-tab-pane label="标签风格" name="4">
<labelStyle :type="title" :entityOptions="entityOptions"></labelStyle>
</el-tab-pane>
</el-tabs>
</div>
</div>
<span class="custom-divider"></span>
</template>
<template #footer>
<div style="position: absolute; left: 24px; display: flex">
@ -244,10 +495,15 @@
<svg class="icon-edit">
<use xlink:href="#yj-icon-edit"></use></svg>二次编辑
</button>
<button style="margin-left: 10px" @click="translate">
<button style="margin-left: 10px" v-if="!moveFlag" @click="translate">
<svg class="icon-py">
<use xlink:href="#yj-icon-py"></use></svg>平移
</button>
<button style="margin-left: 10px" v-if="moveFlag" @click="translate">
<svg class="icon-py">
<use xlink:href="#yj-icon-py"></use></svg
>结束平移
</button>
</div>
<button @click="remove">删除</button>
<button @click="confirm">确定</button>
@ -264,39 +520,28 @@ import Dialog from '@/components/dialog/baseDialog.vue'
import attribute from './attribute.vue'
import labelStyle from './labelStyle.vue'
import { useTreeNode } from '@/views/components/tree/hooks/treeNode'
import { getFontList } from './fontSelect'
const { cusUpdateNode } = useTreeNode()
const title = ref('面')
const fontList = ref(getFontList())
const title = ref('模型')
const baseDialog: any = ref(null)
const eventBus: any = inject('bus')
const options = ref({})
const equalSwitch = ref(true) //是否等比例缩放
const colorRef = ref(null)
const lineColorRef = ref(null)
const labelColorRef = ref(null)
const labelLineColorRef = ref(null)
const labelBackgroundColorStartRef = ref(null)
const labelBackgroundColorEndRef = ref(null)
eventBus.on('openPolygonEdit', () => {
baseDialog.value?.open()
})
const area = ref(0)
const areaUnit = ref('m2')
const height = ref(10)
const heightModeData = ref([
{
name: '海拔高度',
value: '海拔高度',
key: 0
},
{
name: '相对地表',
value: '相对地表',
key: 1
},
{
name: '依附模型',
value: '依附模型',
key: 2
}
])
const activeName = ref('1')
const activeTd = ref({
@ -309,36 +554,18 @@ const entityOptions: any = ref({})
let originalOptions: any
let that: any
const scaleChange = () => {
entityOptions.value.scaleY = entityOptions.value.scaleX
entityOptions.value.scaleZ = entityOptions.value.scaleX
}
const open = async (id: any, type: any) => {
if (type && type === 'rectangle') {
title.value = '矩形'
} else if (type && type === 'rendezvous') {
title.value = '集结地'
}
that = window.earth.entityMap.get(id)
originalOptions = structuredClone(that.options)
entityOptions.value = that
heightMode.value = entityOptions.value.heightMode
area.value = entityOptions.value.areaByMeter
positions.value = structuredClone(that.options.positions)
that.areaChangeCallBack = () => {
switch (areaUnit.value) {
case 'm2': //平方米
area.value = entityOptions.value.areaByMeter
break
case 'km2': //平方千米
area.value = Number((entityOptions.value.areaByMeter / 1000000).toFixed(8))
break
case 'mu': //亩
area.value = Number((entityOptions.value.areaByMeter / 666.6666667).toFixed(4))
break
case 'ha': //公顷
area.value = Number((entityOptions.value.areaByMeter / 10000).toFixed(6))
break
default:
area.value = entityOptions.value.areaByMeter
}
}
heightModeChange(heightMode.value)
baseDialog.value?.open()
@ -358,17 +585,59 @@ const open = async (id: any, type: any) => {
} //点击清空按钮事件回调
})
let linecolorPicker = new window.YJColorPicker({
el: lineColorRef.value,
el: labelColorRef.value,
size: 'mini', //颜色box类型
alpha: true, //是否开启透明度
defaultColor: entityOptions.value.lineColor,
defaultColor: entityOptions.value.labelColor,
disabled: false, //是否禁止打开颜色选择器
openPickerAni: 'opacity', //打开颜色选择器动画
sure: (color) => {
entityOptions.value.lineColor = color
entityOptions.value.labelColor = color
}, //点击确认按钮事件回调
clear: () => {
entityOptions.value.lineColor = 'rgba(255,255,255,1)'
entityOptions.value.labelColor = 'rgba(255,255,255,1)'
} //点击清空按钮事件回调
})
let ylinecolorPicker = new window.YJColorPicker({
el: labelLineColorRef.value,
size: 'mini', //颜色box类型
alpha: true, //是否开启透明度
defaultColor: entityOptions.value.labelLineColor,
disabled: false, //是否禁止打开颜色选择器
openPickerAni: 'opacity', //打开颜色选择器动画
sure: (color) => {
entityOptions.value.labelLineColor = color
}, //点击确认按钮事件回调
clear: () => {
entityOptions.value.labelLineColor = 'rgba(255,255,255,1)'
} //点击清空按钮事件回调
})
let bgcolorPicker1 = new window.YJColorPicker({
el: labelBackgroundColorStartRef.value,
size: 'mini', //颜色box类型
alpha: true, //是否开启透明度
defaultColor: entityOptions.value.labelBackgroundColorStart,
disabled: false, //是否禁止打开颜色选择器
openPickerAni: 'opacity', //打开颜色选择器动画
sure: (color) => {
entityOptions.value.labelBackgroundColorStart = color
}, //点击确认按钮事件回调
clear: () => {
entityOptions.value.labelBackgroundColorStart = 'rgba(255,255,255,1)'
} //点击清空按钮事件回调
})
let bgcolorPicker2 = new window.YJColorPicker({
el: labelBackgroundColorEndRef.value,
size: 'mini', //颜色box类型
alpha: true, //是否开启透明度
defaultColor: entityOptions.value.labelBackgroundColorEnd,
disabled: false, //是否禁止打开颜色选择器
openPickerAni: 'opacity', //打开颜色选择器动画
sure: (color) => {
entityOptions.value.labelBackgroundColorEnd = color
}, //点击确认按钮事件回调
clear: () => {
entityOptions.value.labelBackgroundColorEnd = 'rgba(255,255,255,1)'
} //点击清空按钮事件回调
})
}
@ -414,23 +683,32 @@ const inputBlurCallBack = (event, i, name, digit = 2) => {
}
}
var moveFlag: any = ref(false)
const translate = () => {
that.openPositionEditing(() => {
entityOptions.value.options.positions = structuredClone(that.options.positions)
})
moveFlag.value = !moveFlag.value
that.positionEditing = moveFlag.value
if (moveFlag.value) {
that.rotationEditingCallBack = (res) => {
entityOptions.value.options.positions = structuredClone(res)
that.options.positions = res
}
}
// that.openPositionEditing(() => {
// entityOptions.value.options.positions = structuredClone(that.options.positions)
// })
}
const closeCallback = () => {
// entityOptions.value.originalOptions = structuredClone(originalOptions)
// that.positionEditing = false
entityOptions.value.originalOptions = structuredClone(originalOptions)
that.positionEditing = false
// entityOptions.value.closeNodeEdit()
// entityOptions.value.reset()
// eventBus.emit('destroyComponent')
entityOptions.value.reset()
eventBus.emit('destroyComponent')
}
const nodeEdit = () => {
that.nodeEdit((e, positions, areaByMeter) => {
console.log('positions', positions)
entityOptions.value.options.positions = structuredClone(positions)
})
}
@ -439,7 +717,12 @@ const confirm = () => {
originalOptions = structuredClone(that.options)
baseDialog.value?.close()
let params = structuredClone(that.options)
delete params.host
delete params.attributeType
delete params.attribute.ISC
delete params.attribute.camera
delete params.attribute.goods
delete params.attribute.vr
let params2 = {
id: params.id,
sourceName: params.name,
@ -450,6 +733,7 @@ const confirm = () => {
cusUpdateNode({ id: params.id, sourceName: params.name, params: JSON.stringify(params) })
}
const close = () => {
that.positionEditing = false
baseDialog.value?.close()
}
@ -458,15 +742,7 @@ const remove = () => {
close()
}
watch(
() => areaUnit.value,
(val) => {
if ((entityOptions.value.areaByMeter || entityOptions.value.areaByMeter == 0) && that) {
that.areaChangeCallBack()
}
},
{ immediate: true }
)
//-----------------方法-----------------------
defineExpose({
open,
@ -474,4 +750,22 @@ defineExpose({
})
</script>
<style scoped lang="scss"></style>
<style scoped lang="scss">
::v-deep .el-checkbox.el-checkbox--large .el-checkbox__label {
color: #fff !important;
}
::v-deep .el-select__wrapper {
background-color: rgba(0, 0, 0, 0.5) !important;
box-shadow: 0 0 0 1px rgba(var(--color-sdk-base-rgb), 0.5) inset !important;
}
::v-deep .el-select {
--el-select-input-focus-border-color: rgba(var(--color-sdk-base-rgb), 0.5) !important;
--el-select-text-color: #fff;
--el-select-border-color: rgba(var(--color-sdk-base-rgb), 0.5) !important;
--el-select-hover-border-color: rgba(var(--color-sdk-base-rgb), 0.5) !important;
--el-select-multiple-input-color: #fff !important;
}
::v-deep .el-select__placeholder {
color: rgba(204, 204, 204, 1) !important;
}
</style>

View File

@ -88,12 +88,11 @@ const options = [
label: '面'
}
]
eventBus.on('openModelSetting', (show,data) => {
eventBus.on('openModelSetting', (show, data) => {
baseDialog.value?.open()
show&& (type.value = show.key)
show&& (distance.value = show.value * 1)
show && (type.value = show.key)
show && (distance.value = show.value * 1)
typeChange()
console.log(show,'data')
})
const typeChange = () => {
@ -137,7 +136,6 @@ const save = () => {
baseDialog.value?.close()
}
})
}
</script>

View File

@ -391,7 +391,7 @@ export const useTree = () => {
let isShift = event.shiftKey
let isCtrl = event.ctrlKey
if (!isCtrl || !isShift) {
let source_ids:any = [];
let source_ids: any = [];
// 判断是否是图层文件
if (treeNode.sourceType == "directory") {
// 获取treeNode下面的所有souer_id

View File

@ -180,6 +180,12 @@ export const useTreeNode = () => {
// render: renderGlb,
// allowChildren: false,
},
military: {
rightMenus: ['edit', 'del', 'setView', 'resetView']
// detailFun: get_detail_glb,
// render: renderGlb,
// allowChildren: false,
},
diffuseScan: {
rightMenus: ['edit', 'del', 'setView', 'resetView']
// detailFun: get_detail_diffuseScan,

View File

@ -34,11 +34,14 @@
<tufuSelect ref="tufuselect"></tufuSelect>
<imagePop ref="imagepop"></imagePop>
<model ref="Model"></model>
<graph ref="Graph"></graph>
<graphSetting ref="graphsetting"></graphSetting>
<!-- 图标列表 -->
<selectImg ref="selectImgRef"></selectImg>
<modelSetting ref="modelsetting"></modelSetting>
<modelObject ref="modelobject"></modelObject>
<graphObject ref="graphobject"></graphObject>
</template>
<script setup lang="ts">
@ -107,6 +110,9 @@ import flyLine from '../components/propertyBox/flyLine.vue'
import explosion from '../components/propertyBox/explosion.vue'
import graphObject from '../components/propertyBox/graphObject.vue'
import graph from '../components/propertyBox/graph.vue'
import graphSetting from '../components/propertyBox/graphSetting.vue'
import { GisApi } from '@/api/gisApi'
@ -237,7 +243,12 @@ eventBus.on('openDialog', async (sourceType: any, id: any) => {
case 'model':
currentComponent.value = modelObject
await nextTick()
dynamicComponentRef.value?.open(id)
dynamicComponentRef.value?.open(id, 'model')
break
case 'military':
currentComponent.value = graphObject
await nextTick()
dynamicComponentRef.value?.open(id, 'military')
break
case 'pressModel':
currentComponent.value = flat