This commit is contained in:
zh
2025-10-09 17:50:07 +08:00
18 changed files with 626 additions and 191 deletions

View File

@ -46,7 +46,7 @@ export const GraphApi = {
//军标类型列表 //军标类型列表
modelTypeList: async () => { modelTypeList: async () => {
return await request.get({ return await request.get({
url: `/militaryLibrary/militaryTypeList` url: `/militaryLibrary/militaryTypeTree`
}) })
}, },
//添加军标文件 //添加军标文件
@ -76,6 +76,15 @@ export const GraphApi = {
data data
}) })
}, },
//拖动层级(tree)
dragModelType: async (data: any) => {
return await request.post({
url: `/militaryLibrary/dragMilitaryType`,
data,
})
},
// //默认军标参数设置 // //默认军标参数设置
// modelSetting: async (data: any) => { // modelSetting: async (data: any) => {
// return await request.post({ // return await request.post({

View File

@ -92,5 +92,11 @@ export const ModelApi = {
url: `/businessConfig/list` url: `/businessConfig/list`
}) })
}, },
//拖动层级(tree)
dragModelType: async (data: any) => {
return await request.post({
url: `/modelLibrary/dragModelType`,
data,
})
},
} }

View File

@ -76,6 +76,13 @@ export const PhotoApi = {
data data
}) })
}, },
//拖动调整图标类型层级
dragModelType: async (data: any) => {
return await request.post({
url: `/iconLibrary/dragIconType`,
data
})
},
// //默认图标参数设置 // //默认图标参数设置
// modelSetting: async (data: any) => { // modelSetting: async (data: any) => {
// return await request.post({ // return await request.post({

View File

@ -10,16 +10,38 @@ export const RouteApi = {
}, },
//获取地图列表 //获取地图列表
getRouteList: async () => { getRouteList: async () => {
return await request.get({ return await request.post({
url: `/graphhopper/list` url: `/pbfInfo/list`
}) })
}, },
//加载路网数据 // //加载路网数据
// loadRoute: async (data: any) => {
// return await request.post({
// url: `/graphhopper/loadMap`,
// data,
// headersType: 'application/x-www-form-urlencoded'
// })
// },
//添加路网数据
loadRoute: async (data: any) => { loadRoute: async (data: any) => {
return await request.post({ return await request.post({
url: `/graphhopper/loadMap`, url: `/pbfInfo/add`,
data, data,
headersType: 'application/x-www-form-urlencoded' headersType: 'application/x-www-form-urlencoded'
}) })
}, },
//启用路网数据
enableRoute: async (data: any) => {
return await request.post({
url: `/pbfInfo/enable`,
data,
})
},
//删除路网数据
delRoute: async (data: any) => {
return await request.post({
url: `/pbfInfo/delete`,
data,
})
},
} }

View File

@ -4,7 +4,7 @@
<span class="fankuai"></span> <span class="fankuai"></span>
<span class="setting_title">工程设置</span> <span class="setting_title">工程设置</span>
<el-upload <!-- <el-upload
:action="uploadUrl()" :action="uploadUrl()"
:headers="headers" :headers="headers"
:data="data" :data="data"
@ -13,17 +13,21 @@
:on-success="handleSuccess" :on-success="handleSuccess"
:on-error="handleError" :on-error="handleError"
class="simple-upload" class="simple-upload"
> -->
<el-button
color="#004b4b"
style="border: 1px solid rgba(0, 255, 255, 0.5)"
@click="routeImport"
> >
<el-button color="#004b4b" style="border: 1px solid rgba(0, 255, 255, 0.5)"> <template #icon>
<template #icon> <svg-icon name="road_network" />
<svg-icon name="road_network" /> </template>
</template> <span>路网导入</span>
<span>路网导入</span> </el-button>
</el-button> <!-- </el-upload> -->
</el-upload>
</div> </div>
<div class="fileList"> <div class="fileList" v-if="routeList.length">
<div class="fileList_nav" v-if="routeList.length"> <div class="fileList_nav">
<div class="fileList_nav_item" v-for="(item, index) in routeList" :key="index"> <div class="fileList_nav_item" v-for="(item, index) in routeList" :key="index">
<div class="item_left"> <div class="item_left">
<div class="img"> <div class="img">
@ -33,12 +37,27 @@
/> />
</div> </div>
<div class="file_name"> <div class="file_name">
<span>{{ item.fileName }}</span> <span>{{ item.name }}</span>
<span>{{ item.createdAt }}</span> <span>{{ item.createdAt }}</span>
</div> </div>
</div> </div>
<div class="item_right"> <div class="item_right">
<el-button color="#004b4b" style="border: 1px solid rgba(0, 255, 255, 0.5)"> <span v-if="item.isEnable">已启用</span>
<el-button
v-if="!item.isEnable"
color="#004b4b"
style="border: 1px solid rgba(0, 255, 255, 0.5)"
@click="enableRouteData(item)"
>
<span>启用</span>
</el-button>
<el-button
v-if="!item.isEnable"
color="#004b4b"
style="border: 1px solid rgba(0, 255, 255, 0.5)"
@click="delRouteData(item)"
>
<span>删除</span> <span>删除</span>
</el-button> </el-button>
</div> </div>
@ -122,10 +141,15 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ElMessage } from 'element-plus'
import { ref } from 'vue' import { ref } from 'vue'
import { GisApi } from '@/api/gisApi' import { GisApi } from '@/api/gisApi'
import { RouteApi } from '@/api/route' import { RouteApi } from '@/api/route'
import {
$sendElectronChanel,
$recvElectronChanel,
$changeComponentShow
} from '@/utils/communication'
import { ElMessage, ElMessageBox } from 'element-plus'
// 上传状态 // 上传状态
const isUploading = ref(false) const isUploading = ref(false)
@ -152,9 +176,78 @@ const props = defineProps({
} }
}) })
const routeImport = () => {
let option = {
properties: ['openFile'],
filters: [
{
name: '路网', //、底图
extensions: ['pbf']
}
]
}
$sendElectronChanel('open-directory-dialog', option)
$recvElectronChanel('selectedItem', (e, path) => {
if (path.length) {
RouteApi.loadRoute({
path: path[0]
}).then((res) => {
if (res.code === 200) {
ElMessage({
message: '上传成功',
type: 'success'
})
getList()
}
})
}
})
}
const enableRouteData = (row) => {
ElMessageBox.confirm(`是否启用${row.name}数据?`, '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
.then(() => {
let formData = new FormData()
formData.append('id', row.id)
RouteApi.enableRoute(formData).then((res) => {
if (res.code === 200) {
ElMessage({
message: '启用成功',
type: 'success'
})
getList()
}
})
})
.catch(() => {})
}
const delRouteData = (row) => {
ElMessageBox.confirm(`是否删除${row.name}数据?`, '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
.then(() => {
let formData = new FormData()
formData.append('id', row.id)
RouteApi.delRoute(formData).then((res) => {
if (res.code === 200) {
ElMessage({
message: '删除成功',
type: 'success'
})
getList()
}
})
})
.catch(() => {})
}
const uploadUrl = () => { const uploadUrl = () => {
//process.env.BASE_API + //process.env.BASE_API +
console.log(process.env.BASE_API, 'yyyyy')
let url = 'http://192.168.110.25:8848' + '/yjearth4.0/api/v1/fileInfo/upload' let url = 'http://192.168.110.25:8848' + '/yjearth4.0/api/v1/fileInfo/upload'
return url return url
} }
@ -164,12 +257,10 @@ const handleBeforeUpload = (file: File) => {
ElMessage.error(`文件大小不能超过 ${props.maxSize}MB`) ElMessage.error(`文件大小不能超过 ${props.maxSize}MB`)
return false return false
} }
console.log(file)
// 标记为上传中 // 标记为上传中
const formData = new FormData() const formData = new FormData()
// fileArray.forEach((file, index) => { // fileArray.forEach((file, index) => {
formData.append(`files`, file) // 生成files[0]格式参数 formData.append(`files`, file) // 生成files[0]格式参数
console.log(formData, 'formData')
// }) // })
GisApi.linkFile(formData).then((res) => { GisApi.linkFile(formData).then((res) => {
if (res.code == 0 || res.code == 200) { if (res.code == 0 || res.code == 200) {
@ -192,14 +283,12 @@ const handleBeforeUpload = (file: File) => {
var routeList: any = reactive([]) var routeList: any = reactive([])
const getList = async () => { const getList = async () => {
let list = await RouteApi.getRouteList() let list = await RouteApi.getRouteList()
console.log(list, 'list')
routeList.splice(0, routeList.length, ...list.data) routeList.splice(0, routeList.length, ...list.data)
} }
getList() getList()
const addRoute = async (fileId) => { const addRoute = async (fileId) => {
let res = await RouteApi.loadRoute({ fileId }) let res = await RouteApi.loadRoute({ fileId })
console.log(res, 'res')
} }
// 上传成功处理 // 上传成功处理
@ -212,7 +301,6 @@ const handleSuccess = (response: any) => {
const handleError = (error: Error) => { const handleError = (error: Error) => {
isUploading.value = false isUploading.value = false
ElMessage.error('文件上传失败') ElMessage.error('文件上传失败')
console.error('上传错误:', error)
} }
</script> </script>
@ -226,6 +314,7 @@ const handleError = (error: Error) => {
box-sizing: border-box; box-sizing: border-box;
display: flex; display: flex;
line-height: 32px; // padding: 20px 0; line-height: 32px; // padding: 20px 0;
padding: 0 0 20px 0;
.fankuai { .fankuai {
width: 10px; width: 10px;
height: 10px; height: 10px;
@ -267,9 +356,10 @@ const handleError = (error: Error) => {
} }
.fileList { .fileList {
width: 100%; width: 100%;
height: 20vh; // height: 20vh;
max-height: 20vh;
box-sizing: border-box; box-sizing: border-box;
padding: 20px 0; padding: 0 0 20px 0;
.fileList_nav { .fileList_nav {
width: 100%; width: 100%;

View File

@ -37,6 +37,8 @@
draggable draggable
ref="treeRef" ref="treeRef"
node-key="id" node-key="id"
empty-text=""
:default-expanded-keys="expandedKeys"
@node-click="handleTypeClick" @node-click="handleTypeClick"
@node-contextmenu="handleContextMenu" @node-contextmenu="handleContextMenu"
@node-drag-start="handleDragStart" @node-drag-start="handleDragStart"
@ -56,6 +58,8 @@
}" }"
@click.stop="toggleExpand(node)" @click.stop="toggleExpand(node)"
class="allowDrag" class="allowDrag"
style="width: 100%; text-overflow: ellipsis; overflow: hidden"
:title="node.label"
> >
<svg-icon <svg-icon
:name="node.expanded ? 'arrow' : 'more'" :name="node.expanded ? 'arrow' : 'more'"
@ -79,12 +83,13 @@
<el-table :data="modelList" border style="width: 100%"> <el-table :data="modelList" border style="width: 100%">
<el-table-column type="index" label="序号" width="60" align="center" /> <el-table-column type="index" label="序号" width="60" align="center" />
<el-table-column prop="militaryName" label="名称" /> <el-table-column prop="militaryName" label="名称" />
<el-table-column prop="thumbnail" label="缩略图" width="100"> <el-table-column prop="militaryDataUrl" label="缩略图" width="100">
<template #default="{ row }"> <template #default="{ row }">
<el-image <!-- <el-image
style="width: 80px; height: 60px" style="width: 80px; height: 60px"
:src="'http://127.0.0.1:8848' + row.data" :src="'http://127.0.0.1:8848' + row.militaryDataUrl"
/> /> -->
<el-image style="width: 80px; height: 60px" :src="service + row.militaryDataUrl" />
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="操作"> <el-table-column label="操作">
@ -145,6 +150,8 @@ import {
const fs = require('fs') const fs = require('fs')
const eventBus: any = inject('bus') const eventBus: any = inject('bus')
var clickTreeNode: any = reactive({}) var clickTreeNode: any = reactive({})
var leftClickTreeNode: any = reactive({})
const service = ref(localStorage.getItem('service'))
interface TypeNode { interface TypeNode {
id: string id: string
@ -159,8 +166,8 @@ interface ModelItem {
id: string id: string
typeId: string typeId: string
name: string name: string
thumbnail: string
militaryId: string militaryId: string
militaryDataUrl: string
} }
const typeTreeData = ref<TypeNode[]>([]) const typeTreeData = ref<TypeNode[]>([])
@ -225,12 +232,26 @@ const addType = () => {
dialogVisible.value = false dialogVisible.value = false
} }
var expandedKeys: any = ref([])
// 获取当前所有展开节点的key
const getExpandedKeys = () => {
const nodesMap = treeRef.value?.store?.nodesMap || {}
return Object.values(nodesMap)
.filter((node) => node.expanded)
.map((node) => node.key)
}
// 节点展开/折叠时更新状态
const updateExpandedState = () => {
const keys = getExpandedKeys()
expandedKeys.value = keys
}
//获取模型列表 //获取模型列表
eventBus.on('settingPop', (data) => { eventBus.on('settingPop', (data) => {
if (data) { if (data) {
//关闭弹框时更新模型列表 //关闭弹框时更新模型列表
// getModelList() // getModelListByType(showImageRow.militaryTypeId)
getModelListByType(showImageRow.militaryTypeId)
showImageRow = null showImageRow = null
} }
}) })
@ -321,10 +342,11 @@ const importModelDB = () => {
const addModelDB = (path) => { const addModelDB = (path) => {
let formData = new FormData() let formData = new FormData()
formData.append('modelPath', path) formData.append('militaryPath', path)
GraphApi.importModelDB(formData).then((res) => { GraphApi.importModelDB(formData).then((res) => {
if (res.code == 0 || res.code == 200) { if (res.code == 0 || res.code == 200) {
ElMessage.success('导入成功') ElMessage.success('导入成功')
modelList.value = []
getModelList() getModelList()
} }
}) })
@ -352,6 +374,19 @@ const handleDragEnd = (
ev: DragEvents ev: DragEvents
) => { ) => {
console.log('tree drag end:', dropNode, dropType, ev, draggingNode) console.log('tree drag end:', dropNode, dropType, ev, draggingNode)
let nodeList = dropNode.childNodes.map((item, index) => {
return {
id: item.data.id,
parentId: dropNode.data.id,
treeIndex: index
}
})
GraphApi.dragModelType(nodeList).then((res) => {
if (res.code == 0 || res.code == 200) {
ElMessage.success('拖拽成功')
getModelList()
}
})
} }
const handleDrop = (draggingNode: Node, dropNode: Node, dropType: NodeDropType, ev: DragEvents) => { const handleDrop = (draggingNode: Node, dropNode: Node, dropType: NodeDropType, ev: DragEvents) => {
console.log('tree drop:', dropNode.label, dropType) console.log('tree drop:', dropNode.label, dropType)
@ -370,7 +405,7 @@ const allowDrag = (draggingNode: Node) => {
//拖拽结束 //拖拽结束
//---------------------查看缩略图-------------------- //---------------------查看缩略图--------------------
var showImageRow:any = null var showImageRow: any = null
const showImage = (row: any) => { const showImage = (row: any) => {
showImageRow = row showImageRow = row
eventBus.emit('imagePopDialog', row) eventBus.emit('imagePopDialog', row)
@ -414,8 +449,10 @@ const toggleExpand = (row: any) => {
if (row.expanded) { if (row.expanded) {
row.collapse() row.collapse()
updateExpandedState()
} else { } else {
row.expand() row.expand()
updateExpandedState()
// getModelListByType(row.data.id) // getModelListByType(row.data.id)
} }
} else { } else {
@ -423,6 +460,7 @@ const toggleExpand = (row: any) => {
} }
getModelListByType(row.data.id) getModelListByType(row.data.id)
currentTypeId.value = row.id currentTypeId.value = row.id
leftClickTreeNode = row.data
// loadModelsByType(row.id) // loadModelsByType(row.id)
contextMenu.visible && (contextMenu.visible = false) contextMenu.visible && (contextMenu.visible = false)
} }
@ -472,6 +510,7 @@ const handleMenuCommand = (command: string) => {
const handleTypeClick = (row: any) => { const handleTypeClick = (row: any) => {
getModelListByType(row.id) getModelListByType(row.id)
currentTypeId.value = row.$treeNodeId currentTypeId.value = row.$treeNodeId
leftClickTreeNode = row
// // 模拟根据类型ID加载模型数据 // // 模拟根据类型ID加载模型数据
// loadModelsByType(row.id) // loadModelsByType(row.id)
// contextMenu.visible && (contextMenu.visible = false) // contextMenu.visible && (contextMenu.visible = false)
@ -520,7 +559,7 @@ const handleRenameType = (row: TypeNode) => {
} }
const handleDeleteType = (row: TypeNode) => { const handleDeleteType = (row: TypeNode) => {
ElMessageBox.confirm('是否删除数据?', '警告', { ElMessageBox.confirm('是否删除数据?', '提示', {
confirmButtonText: '确定', confirmButtonText: '确定',
cancelButtonText: '取消', cancelButtonText: '取消',
type: 'warning' type: 'warning'
@ -637,7 +676,7 @@ const getNamefromPath = (path) => {
} }
const handleDelete = (row: any) => { const handleDelete = (row: any) => {
ElMessageBox.confirm('是否删除数据?', '警告', { ElMessageBox.confirm('是否删除数据?', '提示', {
confirmButtonText: '确定', confirmButtonText: '确定',
cancelButtonText: '取消', cancelButtonText: '取消',
type: 'warning' type: 'warning'
@ -828,3 +867,30 @@ onMounted(() => {
letter-spacing: 1px; letter-spacing: 1px;
} }
</style> </style>
<style lang="scss">
.el-message-box {
--el-messagebox-title-color: #fff !important;
--el-messagebox-content-color: #fff !important;
background:
linear-gradient(
180deg,
rgba(var(--color-sdk-base-rgb), 0) 0%,
rgba(var(--color-sdk-base-rgb), 0.2) 100%
),
rgba(0, 0, 0, 0.6) !important;
.el-message-box__btns {
.el-button {
--el-button-text-color: #fff;
--el-button-bg-color: rgba(var(--color-sdk-base-rgb), 0.2) !important;
--el-button-hover-bg-color: rgba(var(--color-sdk-base-rgb), 0.2) !important;
--el-button-border-color: rgba(var(--color-sdk-base-rgb), 0.5) !important;
--el-button-hover-border-color: rgba(var(--color-sdk-base-rgb), 1) !important;
--el-button-hover-text-color: rgba(var(--color-sdk-base-rgb), 1) !important;
}
.el-button--primary {
--el-button-bg-color: rgba(var(--color-sdk-base-rgb), 0.2) !important;
--el-button-hover-bg-color: rgba(var(--color-sdk-base-rgb), 0.2) !important;
}
}
}
</style>

View File

@ -34,9 +34,11 @@
:allow-drop="allowDrop" :allow-drop="allowDrop"
:allow-drag="allowDrag" :allow-drag="allowDrag"
:data="typeTreeData" :data="typeTreeData"
:default-expanded-keys="expandedKeys"
draggable draggable
ref="treeRef" ref="treeRef"
node-key="id" node-key="id"
empty-text=""
@node-click="handleTypeClick" @node-click="handleTypeClick"
@node-contextmenu="handleContextMenu" @node-contextmenu="handleContextMenu"
@node-drag-start="handleDragStart" @node-drag-start="handleDragStart"
@ -56,6 +58,8 @@
}" }"
@click.stop="toggleExpand(node)" @click.stop="toggleExpand(node)"
class="allowDrag" class="allowDrag"
style="width: 100%; text-overflow: ellipsis; overflow: hidden"
:title="node.label"
> >
<svg-icon <svg-icon
:name="node.expanded ? 'arrow' : 'more'" :name="node.expanded ? 'arrow' : 'more'"
@ -83,7 +87,7 @@
<template #default="{ row }"> <template #default="{ row }">
<el-image <el-image
style="width: 80px; height: 60px" style="width: 80px; height: 60px"
:src="'http://127.0.0.1:8848' + row.poster" :src="service + row.posterDataUrl"
fit="contain" fit="contain"
/> />
</template> </template>
@ -137,7 +141,7 @@
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { ref, reactive, onMounted } from 'vue' import { ref, reactive, onMounted, nextTick } from 'vue'
import type { TableColumnCtx } from 'element-plus' import type { TableColumnCtx } from 'element-plus'
import contextMenuCom from './contentMenu.vue' import contextMenuCom from './contentMenu.vue'
import Sortable from 'sortablejs' import Sortable from 'sortablejs'
@ -154,6 +158,8 @@ import {
const fs = require('fs') const fs = require('fs')
const eventBus: any = inject('bus') const eventBus: any = inject('bus')
var clickTreeNode: any = reactive({}) var clickTreeNode: any = reactive({})
var leftClickTreeNode: any = reactive({})
const service = ref(localStorage.getItem('service'))
interface TypeNode { interface TypeNode {
id: string id: string
@ -239,16 +245,48 @@ eventBus.on('settingPop', (data) => {
if (data) { if (data) {
//关闭弹框时更新模型列表 //关闭弹框时更新模型列表
// getModelList() // getModelList()
getModelListByType(showImageRow.modelTypeId)
// getModelListByType(showImageRow.modelTypeId)
showImageRow = null showImageRow = null
} }
}) })
var expandedKeys: any = ref([])
// 获取当前所有展开节点的key
const getExpandedKeys = () => {
const nodesMap = treeRef.value?.store?.nodesMap || {}
return Object.values(nodesMap)
.filter((node) => node.expanded)
.map((node) => node.key)
}
// 节点展开/折叠时更新状态
const updateExpandedState = () => {
const keys = getExpandedKeys()
expandedKeys.value = keys
}
const getModelList = async () => { const getModelList = async () => {
const res: any = await ModelApi.modelTypeList() const res: any = await ModelApi.modelTypeList()
if (res.code == 0 || res.code == 200) { if (res.code == 0 || res.code == 200) {
let data = transformNestedJson(res.data, 'name', 'label') let data = transformNestedJson(res.data, 'name', 'label')
typeTreeData.value = data typeTreeData.value = data
const saved = localStorage.getItem('tree-expanded-keys')
if (saved) {
expandedKeys.value = JSON.parse(saved)
localStorage.removeItem('tree-expanded-keys')
}
let click = localStorage.getItem('tree-click-node')
if (click) {
let data = JSON.parse(click)
await nextTick(() => {
let node = treeRef.value!.getNode(data.id)
currentTypeId.value = node.id
leftClickTreeNode = data
getModelListByType(node.data.id)
})
localStorage.removeItem('tree-click-node')
}
} }
} }
const transformNestedJson = (data, oldKey, newKey) => { const transformNestedJson = (data, oldKey, newKey) => {
@ -282,6 +320,7 @@ const handleFileChange = (e: Event) => {
ModelApi.addModel(formData).then((res) => { ModelApi.addModel(formData).then((res) => {
if (res.code == 0 || res.code == 200) { if (res.code == 0 || res.code == 200) {
ElMessage.success('导入成功') ElMessage.success('导入成功')
getModelListByType(clickTreeNode.id) getModelListByType(clickTreeNode.id)
} }
}) })
@ -334,6 +373,7 @@ const addModelDB = (path) => {
ModelApi.importModelDB(formData).then((res) => { ModelApi.importModelDB(formData).then((res) => {
if (res.code == 0 || res.code == 200) { if (res.code == 0 || res.code == 200) {
ElMessage.success('导入成功') ElMessage.success('导入成功')
modelList.value = []
getModelList() getModelList()
} }
}) })
@ -361,6 +401,19 @@ const handleDragEnd = (
ev: DragEvents ev: DragEvents
) => { ) => {
console.log('tree drag end:', dropNode, dropType, ev, draggingNode) console.log('tree drag end:', dropNode, dropType, ev, draggingNode)
let nodeList = dropNode.childNodes.map((item, index) => {
return {
id: item.data.id,
parentId: dropNode.data.id,
treeIndex: index
}
})
ModelApi.dragModelType(nodeList).then((res) => {
if (res.code == 0 || res.code == 200) {
ElMessage.success('拖拽成功')
getModelList()
}
})
} }
const handleDrop = (draggingNode: Node, dropNode: Node, dropType: NodeDropType, ev: DragEvents) => { const handleDrop = (draggingNode: Node, dropNode: Node, dropType: NodeDropType, ev: DragEvents) => {
console.log('tree drop:', dropNode.label, dropType) console.log('tree drop:', dropNode.label, dropType)
@ -382,6 +435,8 @@ const allowDrag = (draggingNode: Node) => {
var showImageRow: any = null var showImageRow: any = null
const showImage = (row: any) => { const showImage = (row: any) => {
showImageRow = row showImageRow = row
localStorage.setItem('tree-expanded-keys', JSON.stringify(expandedKeys.value)) //打开弹框前记录展开状态和点击状态
localStorage.setItem('tree-click-node', JSON.stringify(leftClickTreeNode)) //打开弹框前记录展开状态和点击状态
eventBus.emit('imagePopDialog', row) eventBus.emit('imagePopDialog', row)
eventBus.emit('settingPop', false) eventBus.emit('settingPop', false)
} }
@ -394,22 +449,22 @@ const handleContextMenu = (event: MouseEvent, row: TypeNode) => {
contextMenu.x = event.clientX contextMenu.x = event.clientX
contextMenu.y = event.clientY contextMenu.y = event.clientY
if (row.parentId) { // if (row.parentId) {
// 二级分类菜单 // // 二级分类菜单
contextMenu.items = [ // contextMenu.items = [
{ command: 'import', label: '导入模型', icon: 'importModel' }, // { command: 'import', label: '导入模型', icon: 'importModel' },
{ command: 'rename', label: '重命名', icon: 'rename' }, // { command: 'rename', label: '重命名', icon: 'rename' },
{ command: 'delete', label: '删除', icon: 'delModel' } // { command: 'delete', label: '删除', icon: 'delModel' }
] // ]
} else { // } else {
// 一级分类菜单 // 一级分类菜单
contextMenu.items = [ contextMenu.items = [
{ command: 'add-child', label: '添加子类型', icon: 'add' }, { command: 'add-child', label: '添加子类型', icon: 'add' },
{ command: 'import', label: '导入模型', icon: 'importModel' }, { command: 'import', label: '导入模型', icon: 'importModel' },
{ command: 'rename', label: '重命名', icon: 'rename' }, { command: 'rename', label: '重命名', icon: 'rename' },
{ command: 'delete', label: '删除', icon: 'delModel' } { command: 'delete', label: '删除', icon: 'delModel' }
] ]
} // }
clickTreeNode = row clickTreeNode = row
contextMenu.visible = true contextMenu.visible = true
@ -423,8 +478,10 @@ const toggleExpand = (row: any) => {
if (row.expanded) { if (row.expanded) {
row.collapse() row.collapse()
updateExpandedState()
} else { } else {
row.expand() row.expand()
updateExpandedState()
// getModelListByType(row.data.id) // getModelListByType(row.data.id)
} }
} else { } else {
@ -432,6 +489,7 @@ const toggleExpand = (row: any) => {
} }
getModelListByType(row.data.id) getModelListByType(row.data.id)
currentTypeId.value = row.id currentTypeId.value = row.id
leftClickTreeNode = row.data
// loadModelsByType(row.id) // loadModelsByType(row.id)
contextMenu.visible && (contextMenu.visible = false) contextMenu.visible && (contextMenu.visible = false)
} }
@ -481,6 +539,7 @@ const handleMenuCommand = (command: string) => {
const handleTypeClick = (row: any) => { const handleTypeClick = (row: any) => {
getModelListByType(row.id) getModelListByType(row.id)
currentTypeId.value = row.$treeNodeId currentTypeId.value = row.$treeNodeId
leftClickTreeNode = row
// // 模拟根据类型ID加载模型数据 // // 模拟根据类型ID加载模型数据
// loadModelsByType(row.id) // loadModelsByType(row.id)
// contextMenu.visible && (contextMenu.visible = false) // contextMenu.visible && (contextMenu.visible = false)

View File

@ -25,7 +25,7 @@
</el-button> </el-button>
</div> </div>
<div class="typeBut"> <!-- <div class="typeBut">
<span <span
v-for="(item, index) in butList" v-for="(item, index) in butList"
:key="index" :key="index"
@ -33,7 +33,7 @@
@click="typeClick(index)" @click="typeClick(index)"
>{{ item }}</span >{{ item }}</span
> >
</div> </div> -->
</div> </div>
<el-row :gutter="20"> <el-row :gutter="20">
<!-- 左侧分类树 --> <!-- 左侧分类树 -->
@ -49,6 +49,8 @@
draggable draggable
ref="treeRef" ref="treeRef"
node-key="id" node-key="id"
empty-text=""
:default-expanded-keys="expandedKeys"
@node-click="handleTypeClick" @node-click="handleTypeClick"
@node-contextmenu="handleContextMenu" @node-contextmenu="handleContextMenu"
@node-drag-start="handleDragStart" @node-drag-start="handleDragStart"
@ -68,6 +70,8 @@
}" }"
@click.stop="toggleExpand(node)" @click.stop="toggleExpand(node)"
class="allowDrag" class="allowDrag"
style="width: 100%; text-overflow: ellipsis; overflow: hidden"
:title="node.label"
> >
<svg-icon <svg-icon
:name="node.expanded ? 'arrow' : 'more'" :name="node.expanded ? 'arrow' : 'more'"
@ -91,15 +95,15 @@
<el-table :data="modelList" border style="width: 100%"> <el-table :data="modelList" border style="width: 100%">
<el-table-column type="index" label="序号" width="60" align="center" /> <el-table-column type="index" label="序号" width="60" align="center" />
<el-table-column prop="iconName" label="名称" /> <el-table-column prop="iconName" label="名称" />
<el-table-column prop="thumbnail" label="缩略图" width="100"> <el-table-column prop="iconDataUrl" label="缩略图" width="100">
<template #default="{ row, $index }" v-if="activeIndex === 2"> <template #default="{ row, $index }" v-if="activeIndex === 2">
<el-image <el-image
ref="imageRef" ref="imageRef"
fit="contain" fit="contain"
:preview-teleported="true" :preview-teleported="true"
:preview-src-list="modelList.map((item:any) => 'http://127.0.0.1:8848' + item.data)" :preview-src-list="modelList.map((item: any) => service + item.iconDataUrl)"
style="width: 80px; height: 60px" style="width: 80px; height: 60px"
:src="'http://127.0.0.1:8848' + row.data" :src="service + item.iconDataUrl"
:initial-index="currentIndex" :initial-index="currentIndex"
@click="seeBigPhoto($index)" @click="seeBigPhoto($index)"
/> />
@ -109,9 +113,11 @@
ref="imageRef" ref="imageRef"
fit="contain" fit="contain"
:preview-teleported="true" :preview-teleported="true"
:preview-src-list="modelList.map((item:any) => 'http://localhost:55110/' + item.data)" :preview-src-list="
modelList.map((item: any) => 'http://localhost:55110/' + item.iconDataUrl)
"
style="width: 80px; height: 60px" style="width: 80px; height: 60px"
:src="'http://localhost:55110/' + row.data" :src="'http://localhost:55110/' + row.iconDataUrl"
:initial-index="currentIndex" :initial-index="currentIndex"
@click="seeBigPhoto($index)" @click="seeBigPhoto($index)"
/> />
@ -187,6 +193,7 @@ const fs = require('fs')
const eventBus: any = inject('bus') const eventBus: any = inject('bus')
const imageRef: any = ref('') const imageRef: any = ref('')
var clickTreeNode: any = reactive({}) var clickTreeNode: any = reactive({})
const service = ref(localStorage.getItem('service'))
interface TypeNode { interface TypeNode {
id: string id: string
@ -219,7 +226,7 @@ const contextMenu = reactive({
}) })
//按钮 //按钮
var activeIndex = ref(0) var activeIndex = ref(2)
var butList = reactive(['立体图标', '普通图标', '自定义图标']) var butList = reactive(['立体图标', '普通图标', '自定义图标'])
const typeClick = (index) => { const typeClick = (index) => {
activeIndex.value = index activeIndex.value = index
@ -227,6 +234,21 @@ const typeClick = (index) => {
getModelList() getModelList()
} }
var expandedKeys: any = ref([])
// 获取当前所有展开节点的key
const getExpandedKeys = () => {
const nodesMap = treeRef.value?.store?.nodesMap || {}
return Object.values(nodesMap)
.filter((node) => node.expanded)
.map((node) => node.key)
}
// 节点展开/折叠时更新状态
const updateExpandedState = () => {
const keys = getExpandedKeys()
expandedKeys.value = keys
}
const treeRef = ref() const treeRef = ref()
var currentIndex = ref(0) var currentIndex = ref(0)
const reviewPhoto = (index) => { const reviewPhoto = (index) => {
@ -303,9 +325,8 @@ const addType = () => {
eventBus.on('settingPop', (data) => { eventBus.on('settingPop', (data) => {
if (data) { if (data) {
//关闭弹框时更新模型列表 //关闭弹框时更新模型列表
// getModelList() // getModelListByType(showImageRow.iconTypeId)
getModelListByType(showImageRow.iconTypeId) // showImageRow = null
showImageRow = null
} }
}) })
@ -437,6 +458,19 @@ const handleDragEnd = (
ev: DragEvents ev: DragEvents
) => { ) => {
console.log('tree drag end:', dropNode, dropType, ev, draggingNode) console.log('tree drag end:', dropNode, dropType, ev, draggingNode)
let nodeList = dropNode.childNodes.map((item, index) => {
return {
id: item.data.id,
parentId: dropNode.data.id,
treeIndex: index
}
})
PhotoApi.dragModelType(nodeList).then((res) => {
if (res.code == 0 || res.code == 200) {
ElMessage.success('拖拽成功')
getModelList()
}
})
} }
const handleDrop = (draggingNode: Node, dropNode: Node, dropType: NodeDropType, ev: DragEvents) => { const handleDrop = (draggingNode: Node, dropNode: Node, dropType: NodeDropType, ev: DragEvents) => {
console.log('tree drop:', dropNode.label, dropType) console.log('tree drop:', dropNode.label, dropType)
@ -502,8 +536,10 @@ const toggleExpand = (row: any) => {
if (row.expanded) { if (row.expanded) {
row.collapse() row.collapse()
updateExpandedState()
} else { } else {
row.expand() row.expand()
updateExpandedState()
// getModelListByType(row.data.id) // getModelListByType(row.data.id)
} }
} else { } else {

View File

@ -61,9 +61,13 @@ const { t } = useI18n()
const tabPosition = ref('left') const tabPosition = ref('left')
const activeName = ref('authorize') const activeName = ref('authorize')
const isShowPup = ref(false) const isShowPup = ref(false)
const open = () => { const open = (data) => {
isShowPup.value = true isShowPup.value = true
activeName.value = 'authorize' console.log(data, 'kkkkkkkk')
if (data !== 'current') {
//如果不是传curent打开就回到第一个tab
activeName.value = 'authorize'
}
} }
const close = () => { const close = () => {
isShowPup.value = false isShowPup.value = false

View File

@ -13,8 +13,14 @@
</div> </div>
</div> </div>
</div> --> </div> -->
<div class="set_item" :title="t('iconTitle.' + item.name)" v-for="(item, i) of setList" :key="item.id" <div
:class="{ 'last-item': i === setList.length - 1 }" @click="item.callback"> class="set_item"
:title="t('iconTitle.' + item.name)"
v-for="(item, i) of setList"
:key="item.id"
:class="{ 'last-item': i === setList.length - 1 }"
@click="item.callback"
>
<svg-icon :name="item.icon" :size="20"></svg-icon> <svg-icon :name="item.icon" :size="20"></svg-icon>
</div> </div>
<setPup ref="setPupRef"></setPup> <setPup ref="setPupRef"></setPup>
@ -26,7 +32,7 @@ import { useRouter } from 'vue-router'
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
import setPup from '../setPup/setPup.vue' import setPup from '../setPup/setPup.vue'
import { inject } from 'vue' import { inject } from 'vue'
const { ipcRenderer } = require('electron'); const { ipcRenderer } = require('electron')
const router = useRouter() // 路由实例 const router = useRouter() // 路由实例
const { t } = useI18n() const { t } = useI18n()
import { uesSetTool } from './hooks' import { uesSetTool } from './hooks'
@ -37,7 +43,7 @@ const { setShow } = uesSetTool(setPupRef)
//控制显隐 //控制显隐
const eventBus: any = inject('bus') const eventBus: any = inject('bus')
eventBus.on('settingPop', (data) => { eventBus.on('settingPop', (data) => {
data ? setPupRef.value.open() : setPupRef.value.close() data ? setPupRef.value.open('current') : setPupRef.value.close()
}) })
const logout = async (e) => { const logout = async (e) => {
let res = await LoginApi.logout() let res = await LoginApi.logout()
@ -47,14 +53,12 @@ const logout = async (e) => {
} }
} }
const fullScreen = (item) => { const fullScreen = (item) => {
ipcRenderer.send('toggle-fullscreen'); ipcRenderer.send('toggle-fullscreen')
} }
const resetShow = (item) => { const resetShow = (item) => {
//重置 //重置
new YJ.Tools(window.earth).flyHome(); new YJ.Tools(window.earth).flyHome()
} }
const setList = ref([ const setList = ref([
@ -65,8 +69,8 @@ const setList = ref([
icon: 'beidou', icon: 'beidou',
name: 'locate', name: 'locate',
className: 'header_public', className: 'header_public',
dbcallback: (e)=>{}, dbcallback: (e) => {},
callback: (e)=>{} callback: (e) => {}
// dbcallback: this.flyTo, // dbcallback: this.flyTo,
// callback: this.locate, // callback: this.locate,
}, },
@ -77,7 +81,7 @@ const setList = ref([
className: 'header_public', className: 'header_public',
name: 'reset', name: 'reset',
dbcallback: null, dbcallback: null,
callback: resetShow, callback: resetShow
}, },
{ {
id: 2, id: 2,
@ -86,7 +90,7 @@ const setList = ref([
className: 'header_public', className: 'header_public',
name: 'fullScreen', name: 'fullScreen',
dbcallback: null, dbcallback: null,
callback: fullScreen, callback: fullScreen
}, },
{ {
id: 3, id: 3,
@ -114,7 +118,7 @@ ipcRenderer.invoke('getIsFullScreen').then((res) => {
}) })
ipcRenderer.on('fullscreen-status-changed', (event, isFullscreen) => { ipcRenderer.on('fullscreen-status-changed', (event, isFullscreen) => {
setList.value[2].icon = isFullscreen ? 'full_screen_exit' : 'full_screen' setList.value[2].icon = isFullscreen ? 'full_screen_exit' : 'full_screen'
}); })
</script> </script>
<style lang="scss"> <style lang="scss">
@ -148,10 +152,12 @@ ipcRenderer.on('fullscreen-status-changed', (event, isFullscreen) => {
top: 0; top: 0;
bottom: 0; bottom: 0;
width: 1px; width: 1px;
background: linear-gradient(180deg, background: linear-gradient(
rgba(0, 255, 255, 0), 180deg,
rgba(0, 255, 255, 1), rgba(0, 255, 255, 0),
rgba(204, 204, 204, 0)); rgba(0, 255, 255, 1),
rgba(204, 204, 204, 0)
);
} }
.set_item.last-item::after { .set_item.last-item::after {

View File

@ -198,6 +198,7 @@ const handleClick = (item: any, e) => {
//模型库 //模型库
if ((window as any).checkAuthIsValid) { if ((window as any).checkAuthIsValid) {
eventBus.emit('openModel', true) eventBus.emit('openModel', true)
console.log('打开模型库')
} else { } else {
ElMessage({ ElMessage({
message: '您没有该功能的权限', message: '您没有该功能的权限',
@ -214,14 +215,12 @@ const handleClick = (item: any, e) => {
type: 'warning' type: 'warning'
}) })
} }
} } else if (item.key === 'ersanwei') {
else if (item.key === 'ersanwei') { if (YJ.Global.multiViewportMode.getSdk().sdkD) {
if(YJ.Global.multiViewportMode.getSdk().sdkD) { YJ.Global.multiViewportMode.off(window.earth)
YJ.Global.multiViewportMode.off(window.earth); } else {
}
else {
eventBus.emit('closeSplitScreen') eventBus.emit('closeSplitScreen')
YJ.Global.multiViewportMode.on(window.earth); YJ.Global.multiViewportMode.on(window.earth)
} }
} }
} }

View File

@ -161,7 +161,6 @@ eventBus.on('routePlanningDialog', () => {
host host
}) })
routePlanning.Dialog.queryCallBack = async (v) => { routePlanning.Dialog.queryCallBack = async (v) => {
console.log(v, 'vvvvvvvvv')
// await queryRoute(params, (response) => { // await queryRoute(params, (response) => {
// if (response) { // if (response) {
// routePlanning.createRoute(response.list[0].positions) // routePlanning.createRoute(response.list[0].positions)
@ -174,8 +173,9 @@ eventBus.on('routePlanningDialog', () => {
endLat: endLat.value, endLat: endLat.value,
waypoints: [] waypoints: []
}) })
routePlanning.createRoute(res.data.pathPoints) if (res.code === 200) {
console.log(res, 'routLIst') routePlanning.createRoute(res.data.pathPoints)
}
} }
}, 100) }, 100)
}) })
@ -184,7 +184,6 @@ eventBus.on('routePlanningDialog', () => {
const addRoute = async (fileId) => { const addRoute = async (fileId) => {
let res = await RouteApi.loadRoute({ fileId }) let res = await RouteApi.loadRoute({ fileId })
console.log(res, 'res')
} }
const getList = async () => { const getList = async () => {
let list = await RouteApi.getRouteList() let list = await RouteApi.getRouteList()
@ -192,7 +191,6 @@ const getList = async () => {
let file = list.data[list.data.length - 1] let file = list.data[list.data.length - 1]
addRoute(file.id) addRoute(file.id)
} }
console.log(list, 'list')
} }
const closeCallBack = (e) => { const closeCallBack = (e) => {
@ -202,7 +200,6 @@ const closeCallBack = (e) => {
endLat.value = null endLat.value = null
} }
const routeQuery = async (e) => { const routeQuery = async (e) => {
console.log('aaaaa')
let res = await RouteApi.queryRoute({ let res = await RouteApi.queryRoute({
startLng: startLng.value, startLng: startLng.value,
startLat: startLat.value, startLat: startLat.value,
@ -210,12 +207,10 @@ const routeQuery = async (e) => {
endLat: endLat.value, endLat: endLat.value,
waypoints: [] waypoints: []
}) })
console.log(res, 'res')
} }
const clearRoute = (e) => {} const clearRoute = (e) => {}
const pickStartPos = () => { const pickStartPos = () => {
routePlanning.pickStartPos((position) => { routePlanning.pickStartPos((position) => {
console.log(position, 'position')
startLng.value = position.lng startLng.value = position.lng
startLat.value = position.lat startLat.value = position.lat
}) })

View File

@ -35,6 +35,7 @@
:data="typeTreeData" :data="typeTreeData"
ref="treeRef" ref="treeRef"
node-key="id" node-key="id"
empty-text=""
@node-click="handleTypeClick" @node-click="handleTypeClick"
:filter-node-method="filterNode" :filter-node-method="filterNode"
> >
@ -48,6 +49,8 @@
}" }"
@click.stop="toggleExpand(node)" @click.stop="toggleExpand(node)"
class="allowDrag" class="allowDrag"
style="width: 100%; text-overflow: ellipsis; overflow: hidden"
:title="node.label"
> >
<svg-icon <svg-icon
:name="node.expanded ? 'arrow' : 'more'" :name="node.expanded ? 'arrow' : 'more'"
@ -64,7 +67,7 @@
</div> </div>
<div class="model-gallery" ref="galleryRef"> <div class="model-gallery" ref="galleryRef">
<div class="model-section"> <div class="model-section" v-if="categories.length != 0">
<!-- <h2 class="section-title">{{ categories[Number(currentTypeId)].name }}</h2> --> <!-- <h2 class="section-title">{{ categories[Number(currentTypeId)].name }}</h2> -->
<div class="model-grid"> <div class="model-grid">
<div <div
@ -75,7 +78,7 @@
> >
<div class="imgbg"> <div class="imgbg">
<el-image <el-image
:src="'http://127.0.0.1:8848' + model.data" :src="service + model.militaryDataUrl"
fit="contain" fit="contain"
class="thumbnail" class="thumbnail"
> >
@ -91,7 +94,12 @@
</div> </div>
</div> </div>
</div> </div>
<div v-show="loading" class="loading-more">加载中...</div> <div v-if="categories.length == 0">
<div class="custom-empty">
<img src="@/assets/images/noData.png" alt="暂无数据" />
<div class="noData">暂无数据</div>
</div>
</div>
</div> </div>
</div> </div>
</div> </div>
@ -113,6 +121,7 @@ const isShowPup = ref(false)
const eventBus: any = inject('bus') const eventBus: any = inject('bus')
const { cusUpdateNode } = useTreeNode() const { cusUpdateNode } = useTreeNode()
var modelName = ref('') var modelName = ref('')
const service = ref(localStorage.getItem('service'))
//tab //tab
interface Model { interface Model {
@ -295,7 +304,7 @@ const renderModel = async (model) => {
let option = { let option = {
id: id, id: id,
name: model.militaryName, name: model.militaryName,
url: 'http://127.0.0.1:8848' + model.data, url: service.value + model.militaryDataUrl,
position: positions position: positions
} }
@ -387,7 +396,7 @@ eventBus.on('openGraph', (data) => {
getSetting() getSetting()
} }
}) })
eventBus.on('closeModelSet', (data) => { eventBus.on('closeModelSetGraph', (data) => {
isShowPup.value = data isShowPup.value = data
if (data) { if (data) {
getSetting() getSetting()
@ -640,6 +649,7 @@ defineExpose({
height: 100%; height: 100%;
float: left; float: left;
border-right: 1px solid rgba(204, 204, 204, 0.2); border-right: 1px solid rgba(204, 204, 204, 0.2);
overflow-x: hidden;
} }
.model-gallery { .model-gallery {
flex: 1; flex: 1;
@ -649,6 +659,18 @@ defineExpose({
width: calc(100% - 160px); width: calc(100% - 160px);
float: left; float: left;
margin-left: 10px; margin-left: 10px;
.custom-empty {
display: flex;
justify-content: center; /* 水平居中 */
align-items: center; /* 垂直居中 */
flex-direction: column;
height: 300px;
}
.custom-empty img {
display: block;
width: 130px;
}
} }
.model-section { .model-section {
min-height: 10vh; min-height: 10vh;
@ -762,4 +784,9 @@ defineExpose({
::v-deep .el-tree--highlight-current .el-tree-node.is-current > .el-tree-node__content { ::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; border-right: 1px solid rgba(var(--color-sdk-base-rgb), 0.2) !important;
} }
::v-deep .allowDrag {
width: 100% !important;
overflow: hidden !important;
text-overflow: ellipsis !important;
}
</style> </style>

View File

@ -341,9 +341,7 @@ const closeCallback = () => {
} }
const nodeEdit = () => { const nodeEdit = () => {
console.log(entityOptions.value._isdrag, '_isdrag')
that.drag(!entityOptions.value._isdrag, (data) => { that.drag(!entityOptions.value._isdrag, (data) => {
console.log(data, 'data')
that.options = data that.options = data
}) })
} }

View File

@ -121,7 +121,7 @@ const viewPointHeightInput = () => {
const closeCallBack = (e) => { const closeCallBack = (e) => {
type.value = 'point' type.value = 'point'
distance.value = null distance.value = null
eventBus.emit('closeModelSet', true) eventBus.emit('closeModelSetGraph', true)
} }
const close = () => { const close = () => {
baseDialog.value?.close() baseDialog.value?.close()

View File

@ -15,7 +15,7 @@
</div> </div>
<div class="inputCon"> <div class="inputCon">
<span class="label">模型名称</span> <span class="label">模型名称</span>
<input class="input" maxlength="40" type="text" v-model="newData.name" /> <input class="input" maxlength="40" type="text" v-model="rowData.name" />
</div> </div>
</div> </div>
</template> </template>
@ -45,9 +45,10 @@ const eventBus: any = inject('bus')
const viewPointHeight: any = ref(1.8) const viewPointHeight: any = ref(1.8)
var rowData: any = reactive([]) var rowData: any = reactive([])
var imageData: any = ref(null) var imageData: any = ref(null)
var newData: any = reactive({ const service = ref(localStorage.getItem('service'))
name: '' // var newData: any = reactive({
}) // name: ''
// })
eventBus.on('imagePopDialog', (data) => { eventBus.on('imagePopDialog', (data) => {
rowData = data rowData = data
rowData.name = data.modelName rowData.name = data.modelName
@ -59,7 +60,7 @@ eventBus.on('imagePopDialog', (data) => {
}) })
}) })
//----------------模型预览--------------- //----------------模型预览---------------
const threeCanvas:any = ref(null) const threeCanvas: any = ref(null)
let scene, camera, renderer, model, controls let scene, camera, renderer, model, controls
const initThreeJS = () => { const initThreeJS = () => {
@ -114,7 +115,7 @@ const initThreeJS = () => {
const loadModel = () => { const loadModel = () => {
const loader = new GLTFLoader() const loader = new GLTFLoader()
loader.load( loader.load(
'http://127.0.0.1:8848' + rowData.data, // 模型路径 service.value + rowData.modelDataUrl, // 模型路径
function (gltf) { function (gltf) {
// onLoad回调函数 // onLoad回调函数
model = gltf.scene model = gltf.scene
@ -151,7 +152,6 @@ const closeCallBack = (e) => {
renderer.domElement.remove() // 从DOM中移除渲染器。 renderer.domElement.remove() // 从DOM中移除渲染器。
imageData.value = null imageData.value = null
rowData = [] rowData = []
newData.name = ''
//打开系统设置弹框 //打开系统设置弹框
eventBus.emit('settingPop', true) eventBus.emit('settingPop', true)
} }
@ -162,7 +162,8 @@ const setImage = (e) => {
const canvas = renderer.domElement const canvas = renderer.domElement
canvas.toBlob((blob) => { canvas.toBlob((blob) => {
imageData.value = blob const file = new File([blob], 'filename.png', { type: 'image/png' })
imageData.value = file
ElMessage.warning('点击保存是会应用当前图片') ElMessage.warning('点击保存是会应用当前图片')
}, 'image/png') }, 'image/png')
} }
@ -172,7 +173,7 @@ const close = (e) => {
const save = (e) => { const save = (e) => {
const formData = new FormData() const formData = new FormData()
formData.append('modelId', rowData.id) formData.append('modelId', rowData.id)
newData.name && formData.append('modelName', newData.name) rowData.name && formData.append('modelName', rowData.name)
imageData.value && formData.append('file', imageData.value) imageData.value && formData.append('file', imageData.value)
ModelApi.updatePoster(formData).then((res) => { ModelApi.updatePoster(formData).then((res) => {
if (res.code == 0 || res.code == 200) { if (res.code == 0 || res.code == 200) {

View File

@ -13,7 +13,7 @@
<el-input <el-input
v-model="modelName" v-model="modelName"
class="w-50 m-2" class="w-50 m-2"
placeholder="请输入模型名称进行搜索" placeholder="请输入模型类型进行搜索"
:suffix-icon="Search" :suffix-icon="Search"
/> />
<button @click="setting" class="btn"> <button @click="setting" class="btn">
@ -35,6 +35,7 @@
:data="typeTreeData" :data="typeTreeData"
ref="treeRef" ref="treeRef"
node-key="id" node-key="id"
empty-text=""
@node-click="handleTypeClick" @node-click="handleTypeClick"
:filter-node-method="filterNode" :filter-node-method="filterNode"
> >
@ -48,6 +49,8 @@
}" }"
@click.stop="toggleExpand(node)" @click.stop="toggleExpand(node)"
class="allowDrag" class="allowDrag"
style="width: 100%; text-overflow: ellipsis; overflow: hidden"
:title="node.label"
> >
<svg-icon <svg-icon
:name="node.expanded ? 'arrow' : 'more'" :name="node.expanded ? 'arrow' : 'more'"
@ -64,7 +67,7 @@
</div> </div>
<div class="model-gallery" ref="galleryRef"> <div class="model-gallery" ref="galleryRef">
<div class="model-section"> <div class="model-section" v-if="categories.length != 0">
<!-- <h2 class="section-title">{{ categories[Number(currentTypeId)].name }}</h2> --> <!-- <h2 class="section-title">{{ categories[Number(currentTypeId)].name }}</h2> -->
<div class="model-grid"> <div class="model-grid">
<div <div
@ -74,24 +77,29 @@
@click="modelClick(mIndex, model)" @click="modelClick(mIndex, model)"
> >
<div class="imgbg"> <div class="imgbg">
<el-image <el-image :src="service + model.posterDataUrl" fit="contain" class="thumbnail">
:src="'http://127.0.0.1:8848' + model.poster"
fit="contain"
class="thumbnail"
>
<template #error> <template #error>
<div class="image-error">加载失败</div> <div class="image-error">加载失败</div>
</template> </template>
</el-image> </el-image>
</div> </div>
<div class="model-name" :class="{ isactive: activeIndex == mIndex }"> <div
class="model-name"
:class="{ isactive: activeIndex == mIndex }"
:title="model.modelName"
>
{{ model.modelName }} {{ model.modelName }}
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<div v-show="loading" class="loading-more">加载中...</div> <div v-if="categories.length == 0">
<div class="custom-empty">
<img src="@/assets/images/noData.png" alt="暂无数据" />
<div class="noData">暂无数据</div>
</div>
</div>
</div> </div>
</div> </div>
</div> </div>
@ -112,6 +120,9 @@ const { findParentId, findTreeIndex, cusAddNodes } = useTreeNode()
const isShowPup = ref(false) const isShowPup = ref(false)
const eventBus: any = inject('bus') const eventBus: any = inject('bus')
var modelName = ref('') var modelName = ref('')
var clickTreeNode: any = ref('')
const service = ref(localStorage.getItem('service'))
//tab //tab
interface Model { interface Model {
@ -252,6 +263,7 @@ const toggleExpand = (row: any) => {
} }
} }
getModelListByType(row.data.id) getModelListByType(row.data.id)
clickTreeNode.value = row.data.id
currentTypeId.value = row.id currentTypeId.value = row.id
// loadModelsByType(row.id) // loadModelsByType(row.id)
} }
@ -259,6 +271,7 @@ const addType = ref('')
const handleTypeClick = (row: any) => { const handleTypeClick = (row: any) => {
getModelListByType(row.id) getModelListByType(row.id)
clickTreeNode.value = row.id
currentTypeId.value = row.$treeNodeId currentTypeId.value = row.$treeNodeId
} }
@ -281,7 +294,7 @@ const modelClick = (index, row) => {
typeof selectCallback === 'function' && typeof selectCallback === 'function' &&
addType.value === 'trajectoryMotion' addType.value === 'trajectoryMotion'
) { ) {
selectCallback('http://127.0.0.1:8848' + row.data) selectCallback(service.value + row.modelDataUrl)
close() close()
return return
} }
@ -299,7 +312,7 @@ const modelClick = (index, row) => {
id: id, id: id,
type: typeArr[isSetting.key], type: typeArr[isSetting.key],
spacing: isSetting['value'] * 1, spacing: isSetting['value'] * 1,
url: 'http://127.0.0.1:8848' + isSetting[row.data] url: service.value + isSetting[row.modelDataUrl]
}, },
function (data) { function (data) {
// posiArr.forEach((item, index) => { // posiArr.forEach((item, index) => {
@ -325,9 +338,9 @@ const renderModel = async (data, model) => {
// let source_id = this.$md5(new Date().getTime() + model.model_name+index); // let source_id = this.$md5(new Date().getTime() + model.model_name+index);
let id = new YJ.Tools().randomString() let id = new YJ.Tools().randomString()
if (data.type == '面') { if (data.type == '面') {
z = data.rotate.z z = data.rotate - 90
} else if (data.type == '线') { } else if (data.type == '线') {
z = data.rotate[index] z = data.rotate[index] - 90
} }
let option = { let option = {
@ -336,7 +349,7 @@ const renderModel = async (data, model) => {
name: model.modelName + index, name: model.modelName + index,
show: true, show: true,
scale: { x: 1, y: 1, z: 1 }, scale: { x: 1, y: 1, z: 1 },
url: model.data, url: service.value + model.modelDataUrl,
maximumScale: 1, maximumScale: 1,
// host: 'http://127.0.0.1:8848', // host: 'http://127.0.0.1:8848',
rotate: { rotate: {
@ -438,6 +451,7 @@ eventBus.on('closeModelSet', (data) => {
isShowPup.value = data isShowPup.value = data
if (data) { if (data) {
getSetting() getSetting()
clickTreeNode.value && getModelListByType(clickTreeNode.value)
} }
}) })
@ -691,6 +705,7 @@ defineExpose({
height: 100%; height: 100%;
float: left; float: left;
border-right: 1px solid rgba(204, 204, 204, 0.2); border-right: 1px solid rgba(204, 204, 204, 0.2);
overflow-x: hidden;
} }
.model-gallery { .model-gallery {
flex: 1; flex: 1;
@ -700,6 +715,17 @@ defineExpose({
width: calc(100% - 160px); width: calc(100% - 160px);
float: left; float: left;
margin-left: 10px; margin-left: 10px;
.custom-empty {
display: flex;
justify-content: center; /* 水平居中 */
align-items: center; /* 垂直居中 */
flex-direction: column;
height: 300px;
}
.custom-empty img {
display: block;
width: 130px;
}
} }
.model-section { .model-section {
min-height: 10vh; min-height: 10vh;

View File

@ -11,73 +11,132 @@
<div class="set_detail"> <div class="set_detail">
<div class="top"> <div class="top">
<div> <div>
<el-input v-model="modelName" class="w-50 m-2" placeholder="请输入图标类型进行搜索" :suffix-icon="Search" /> <el-input
v-model="modelName"
class="w-50 m-2"
placeholder="请输入图标类型进行搜索"
:suffix-icon="Search"
/>
</div> </div>
<div class="typeBut"> <div class="typeBut">
<span v-for="(item, index) in butList" :key="index" :class="{ clickButClass: butActiveIndex === index }" <span
@click="typeClick(index)">{{ item }}</span> v-for="(item, index) in butList"
:key="index"
:class="{ clickButClass: butActiveIndex === index }"
@click="typeClick(index)"
>{{ item }}</span
>
</div> </div>
</div> </div>
<div class="content"> <div class="content">
<!-- 左侧Tab导航 --> <!-- 左侧Tab导航 -->
<div class="treeCon"> <div class="treeCon">
<el-tree style="max-width: 600px" :data="typeTreeData" ref="treeRef" node-key="id" <el-tree
@node-click="handleTypeClick" :filter-node-method="filterNode"> style="max-width: 600px"
:data="typeTreeData"
ref="treeRef"
node-key="id"
@node-click="handleTypeClick"
:filter-node-method="filterNode"
>
<template #default="{ node, data }"> <template #default="{ node, data }">
<!-- <span> {{ node.label }}</span> --> <!-- <span> {{ node.label }}</span> -->
<span :class="{ <span
'primary-type': !(node.childNodes.length != 0), :class="{
'selected-text': node.id === currentTypeId 'primary-type': !(node.childNodes.length != 0),
}" @click.stop="toggleExpand(node)" class="allowDrag"> 'selected-text': node.id === currentTypeId
<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)"
@click.stop="toggleExpand(node)"></svg-icon> class="allowDrag"
{{ node.label }}</span> style="width: 100%; text-overflow: ellipsis; overflow: hidden"
:title="node.label"
>
<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> </template>
</el-tree> </el-tree>
</div> </div>
<div class="model-gallery" ref="galleryRef"> <div class="model-gallery" ref="galleryRef">
<div class="model-section" v-if="butActiveIndex === 2"> <div class="model-section" v-if="butActiveIndex === 2 && categories.length != 0">
<!-- <h2 class="section-title">{{ categories[Number(currentTypeId)].name }}</h2> --> <!-- <h2 class="section-title">{{ categories[Number(currentTypeId)].name }}</h2> -->
<div class="model-grid"> <div class="model-grid">
<div v-for="(model, mIndex) in categories" :key="mIndex" class="model-item" <div
@click="modelClick(mIndex, model)"> v-for="(model, mIndex) in categories"
:key="mIndex"
class="model-item"
@click="modelClick(mIndex, model)"
>
<div class="imgbg"> <div class="imgbg">
<el-image :src="service + model.data" fit="contain" class="thumbnail"> <el-image :src="service + model.iconDataUrl" fit="contain" class="thumbnail">
<template #error> <template #error>
<div class="image-error">加载失败</div> <div class="image-error">加载失败</div>
</template> </template>
</el-image> </el-image>
</div> </div>
<div class="model-name" :class="{ isactive: activeIndex == mIndex }" :title="model.iconName"> <div
class="model-name"
:class="{ isactive: activeIndex == mIndex }"
:title="model.iconName"
>
{{ model.iconName }} {{ model.iconName }}
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<div v-if="butActiveIndex === 2 && categories.length == 0">
<div class="custom-empty">
<img src="@/assets/images/noData.png" alt="暂无数据" />
<div class="noData">暂无数据</div>
</div>
</div>
<!-- 基础类型 --> <!-- 基础类型 -->
<div class="model-section2" v-else> <div class="model-section2" v-else-if="butActiveIndex === 1 || butActiveIndex === 0">
<!-- <h2 class="section-title">{{ categories[Number(currentTypeId)].name }}</h2> --> <!-- <h2 class="section-title">{{ categories[Number(currentTypeId)].name }}</h2> -->
<div class="typeTitltName" v-if="categories.length"> <div class="typeTitltName" v-if="categories.length">
<svg-icon name="fk" :size="16" color="rgba(0, 255, 255, 1)" style="margin-right: 5px"></svg-icon>基本类型 <svg-icon
name="fk"
:size="16"
color="rgba(0, 255, 255, 1)"
style="margin-right: 5px"
></svg-icon
>基本类型
</div> </div>
<div class="model-grid"> <div class="model-grid">
<div v-for="(model, mIndex) in categories" :key="mIndex" class="model-item" <div
@click="modelClick(mIndex, model)"> v-for="(model, mIndex) in categories"
:key="mIndex"
class="model-item"
@click="modelClick(mIndex, model)"
>
<div class="imgbg"> <div class="imgbg">
<el-image :src="'http://localhost:' + availablePort + '/' + model.data" fit="contain" <el-image
class="thumbnail"> :src="'http://localhost:' + availablePort + '/' + model.data"
fit="contain"
class="thumbnail"
>
<template #error> <template #error>
<div class="image-error">加载失败</div> <div class="image-error">加载失败</div>
</template> </template>
</el-image> </el-image>
</div> </div>
<div class="model-name" :class="{ isactive: activeIndex == mIndex }" :title="model.iconName"> <div
class="model-name"
:class="{ isactive: activeIndex == mIndex }"
:title="model.iconName"
>
{{ model.iconName }} {{ model.iconName }}
</div> </div>
</div> </div>
@ -114,7 +173,7 @@ const { cusUpdateNode } = useTreeNode()
var modelName = ref('') var modelName = ref('')
const availablePort = ref(55110) const availablePort = ref(55110)
const service = ref(localStorage.getItem("service")) const service = ref(localStorage.getItem('service'))
ipcRenderer.invoke('get-available-port').then((port) => { ipcRenderer.invoke('get-available-port').then((port) => {
availablePort.value = port availablePort.value = port
@ -292,17 +351,16 @@ const modelClick = (index, row) => {
isShowPup.value = false isShowPup.value = false
console.log(index, row) console.log(index, row)
let selectedImg let selectedImg
if(selectCallback) { if (selectCallback) {
if(butActiveIndex.value === 0) if (butActiveIndex.value === 0) {
{ selectedImg =
selectedImg = 'http://localhost:' + availablePort.value + '/' + (row.data.indexOf("1s/") > -1 ? row.data.replace(/1s/g, "1") : row.data) 'http://localhost:' +
} availablePort.value +
else if(butActiveIndex.value === 1) '/' +
{ (row.data.indexOf('1s/') > -1 ? row.data.replace(/1s/g, '1') : row.data)
} else if (butActiveIndex.value === 1) {
selectedImg = 'http://localhost:' + availablePort.value + '/' + row.data selectedImg = 'http://localhost:' + availablePort.value + '/' + row.data
} } else if (butActiveIndex.value === 2) {
else if(butActiveIndex.value === 2)
{
selectedImg = service.value + row.data selectedImg = service.value + row.data
} }
selectCallback(selectedImg) selectCallback(selectedImg)
@ -332,10 +390,10 @@ const getModelList = async () => {
parentId: null parentId: null
} }
] ]
if(butActiveIndex.value==0) { if (butActiveIndex.value == 0) {
categories.value = [...threePhoto] categories.value = [...threePhoto]
} }
if(butActiveIndex.value==1) { if (butActiveIndex.value == 1) {
categories.value = [...ordinaryPhoto] categories.value = [...ordinaryPhoto]
} }
} else { } else {
@ -343,7 +401,7 @@ const getModelList = async () => {
if (res.code == 0 || res.code == 200) { if (res.code == 0 || res.code == 200) {
let data = transformNestedJson(res.data, 'name', 'label') let data = transformNestedJson(res.data, 'name', 'label')
typeTreeData.value = data typeTreeData.value = data
if(typeTreeData.value.length>0) { if (typeTreeData.value.length > 0) {
getModelListByType(typeTreeData.value[0].id) getModelListByType(typeTreeData.value[0].id)
} }
} }
@ -374,7 +432,7 @@ onBeforeUnmount(() => {
observer?.disconnect() observer?.disconnect()
}) })
//end //end
eventBus.on('openPhoto', async(cb) => { eventBus.on('openPhoto', async (cb) => {
isShowPup.value = true isShowPup.value = true
selectCallback = cb selectCallback = cb
getModelList() getModelList()
@ -502,19 +560,23 @@ defineExpose({
box-sizing: border-box; box-sizing: border-box;
// height: 50vh; // height: 50vh;
:deep(.el-tabs--left .el-tabs__active-bar.is-left, :deep(
.el-tabs--left .el-tabs__active-bar.is-left,
.el-tabs--left .el-tabs__active-bar.is-right, .el-tabs--left .el-tabs__active-bar.is-right,
.el-tabs--right .el-tabs__active-bar.is-left, .el-tabs--right .el-tabs__active-bar.is-left,
.el-tabs--right .el-tabs__active-bar.is-right) { .el-tabs--right .el-tabs__active-bar.is-right
) {
width: 3px; width: 3px;
background: rgba(0, 255, 255, 1); background: rgba(0, 255, 255, 1);
height: 40px !important; height: 40px !important;
} }
:deep(.el-tabs--left .el-tabs__nav-wrap.is-left::after, :deep(
.el-tabs--left .el-tabs__nav-wrap.is-left::after,
.el-tabs--left .el-tabs__nav-wrap.is-right::after, .el-tabs--left .el-tabs__nav-wrap.is-right::after,
.el-tabs--right .el-tabs__nav-wrap.is-left::after, .el-tabs--right .el-tabs__nav-wrap.is-left::after,
.el-tabs--right .el-tabs__nav-wrap.is-right::after) { .el-tabs--right .el-tabs__nav-wrap.is-right::after
) {
width: 3px; width: 3px;
} }
@ -571,29 +633,39 @@ defineExpose({
} }
:deep(.el-tabs__item:hover) { :deep(.el-tabs__item:hover) {
background: linear-gradient(90deg, background: linear-gradient(
rgba(0, 255, 255, 0) 0%, 90deg,
rgba(0, 255, 255, 0.5) 48.91%, rgba(0, 255, 255, 0) 0%,
rgba(0, 255, 255, 0) 100%); rgba(0, 255, 255, 0.5) 48.91%,
rgba(0, 255, 255, 0) 100%
);
border: 1px solid; border: 1px solid;
box-sizing: border-box; box-sizing: border-box;
border-image: linear-gradient(90deg, border-image: linear-gradient(
90deg,
rgba(0, 255, 255, 0) 0%, rgba(0, 255, 255, 0) 0%,
rgba(0, 255, 255, 1) 55.55%, rgba(0, 255, 255, 1) 55.55%,
rgba(0, 255, 255, 0) 100%) 1; rgba(0, 255, 255, 0) 100%
)
1;
} }
:deep(.el-tabs__item.is-active) { :deep(.el-tabs__item.is-active) {
background: linear-gradient(90deg, background: linear-gradient(
rgba(0, 255, 255, 0) 0%, 90deg,
rgba(0, 255, 255, 0.5) 48.91%, rgba(0, 255, 255, 0) 0%,
rgba(0, 255, 255, 0) 100%) !important; rgba(0, 255, 255, 0.5) 48.91%,
rgba(0, 255, 255, 0) 100%
) !important;
border: 0.1px solid; border: 0.1px solid;
// box-sizing: border-box; // box-sizing: border-box;
border-image: linear-gradient(90deg, border-image: linear-gradient(
90deg,
rgba(0, 255, 255, 0) 0%, rgba(0, 255, 255, 0) 0%,
rgba(0, 255, 255, 1) 55.55%, rgba(0, 255, 255, 1) 55.55%,
rgba(0, 255, 255, 0) 100%) 1 !important; rgba(0, 255, 255, 0) 100%
)
1 !important;
} }
:deep(.el-tabs__header) { :deep(.el-tabs__header) {
@ -668,6 +740,7 @@ defineExpose({
height: 100%; height: 100%;
float: left; float: left;
border-right: 1px solid rgba(204, 204, 204, 0.2); border-right: 1px solid rgba(204, 204, 204, 0.2);
overflow-x: hidden;
} }
.model-gallery { .model-gallery {
@ -678,6 +751,17 @@ defineExpose({
width: calc(100% - 160px); width: calc(100% - 160px);
float: left; float: left;
margin-left: 10px; margin-left: 10px;
.custom-empty {
display: flex;
justify-content: center; /* 水平居中 */
align-items: center; /* 垂直居中 */
flex-direction: column;
height: 300px;
}
.custom-empty img {
display: block;
width: 130px;
}
} }
.model-section { .model-section {
@ -788,7 +872,7 @@ defineExpose({
} }
/* tree */ /* tree */
.el-tree-node__content>.el-tree-node__expand-icon { .el-tree-node__content > .el-tree-node__expand-icon {
display: none !important; display: none !important;
} }
@ -812,7 +896,7 @@ defineExpose({
/* Element UI主色可自定义 */ /* Element UI主色可自定义 */
} }
::v-deep .el-tree--highlight-current .el-tree-node.is-current>.el-tree-node__content { ::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; border-right: 1px solid rgba(var(--color-sdk-base-rgb), 0.2) !important;
} }