军标库 模型库
This commit is contained in:
@ -158,6 +158,7 @@ export default {
|
|||||||
project: '工程信息',
|
project: '工程信息',
|
||||||
device: '设备管理',
|
device: '设备管理',
|
||||||
modelManage: '模型管理',
|
modelManage: '模型管理',
|
||||||
|
graphLabelManage: '军标管理',
|
||||||
version: '版本信息'
|
version: '版本信息'
|
||||||
},
|
},
|
||||||
auths: {
|
auths: {
|
||||||
@ -214,5 +215,9 @@ export default {
|
|||||||
model: {
|
model: {
|
||||||
title: '模型选择',
|
title: '模型选择',
|
||||||
setting: '默认模型参数设置'
|
setting: '默认模型参数设置'
|
||||||
|
},
|
||||||
|
graph: {
|
||||||
|
title: '军标选择',
|
||||||
|
setting: '默认军标参数设置'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
93
src/renderer/src/api/graphLabel/index.ts
Normal file
93
src/renderer/src/api/graphLabel/index.ts
Normal 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`
|
||||||
|
// })
|
||||||
|
// },
|
||||||
|
|
||||||
|
}
|
||||||
@ -36,6 +36,13 @@ export const ModelApi = {
|
|||||||
data
|
data
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
//修改模型类型名称
|
||||||
|
updateModelTypeName: async (data: any) => {
|
||||||
|
return await request.post({
|
||||||
|
url: `/modelLibrary/updateModelTypeName`,
|
||||||
|
data
|
||||||
|
})
|
||||||
|
},
|
||||||
//模型类型列表
|
//模型类型列表
|
||||||
modelTypeList: async () => {
|
modelTypeList: async () => {
|
||||||
return await request.get({
|
return await request.get({
|
||||||
|
|||||||
@ -44,6 +44,11 @@ export const initMapData = async (type, data, cd) => {
|
|||||||
case 'model':
|
case 'model':
|
||||||
entityObject = new YJ.Obj.Model(window.earth, data)
|
entityObject = new YJ.Obj.Model(window.earth, data)
|
||||||
break
|
break
|
||||||
|
case 'military':
|
||||||
|
console.log('data', data)
|
||||||
|
entityObject = new YJ.Obj.GroundSvg(window.earth, data)
|
||||||
|
entityObject.load(() => { })
|
||||||
|
break
|
||||||
case 'terrain':
|
case 'terrain':
|
||||||
data.host = baseURL
|
data.host = baseURL
|
||||||
entityObject = new YJ.Obj.Terrain(window.earth, data)
|
entityObject = new YJ.Obj.Terrain(window.earth, data)
|
||||||
|
|||||||
@ -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) => {
|
||||||
|
console.log(row)
|
||||||
|
// 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 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) => {
|
||||||
|
console.log('重命名类型', row)
|
||||||
|
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;
|
||||||
|
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>
|
||||||
@ -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>
|
|
||||||
@ -1,7 +1,11 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="model-management-container">
|
<div class="model-management-container">
|
||||||
<div class="equipment_title" style="margin-bottom: 10px">
|
<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>
|
<template #icon>
|
||||||
<svg-icon name="leading_in" />
|
<svg-icon name="leading_in" />
|
||||||
</template>
|
</template>
|
||||||
@ -112,8 +116,8 @@
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<!-- 添加类型弹窗 -->
|
<!-- 添加类型弹窗 -->
|
||||||
<el-dialog v-model="dialogVisible" title="添加模型类型" width="30%" :before-close="handleClose">
|
<el-dialog v-model="dialogVisible" :title="dialogTitle" width="30%" :before-close="handleClose">
|
||||||
<el-input v-model="modelType" placeholder="请输入模型类型" />
|
<el-input v-model="modelType" placeholder="请输入模型类型名称" />
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<span class="dialog-footer">
|
<span class="dialog-footer">
|
||||||
<el-button @click="closeDialog">取消</el-button>
|
<el-button @click="closeDialog">取消</el-button>
|
||||||
@ -121,7 +125,13 @@
|
|||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</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>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -140,7 +150,7 @@ import {
|
|||||||
$recvElectronChanel,
|
$recvElectronChanel,
|
||||||
$changeComponentShow
|
$changeComponentShow
|
||||||
} from '@/utils/communication'
|
} from '@/utils/communication'
|
||||||
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({})
|
||||||
|
|
||||||
@ -180,6 +190,7 @@ var sortableInstance: any = reactive(null)
|
|||||||
|
|
||||||
//--------------添加模型类型----------------
|
//--------------添加模型类型----------------
|
||||||
var dialogVisible: any = ref(false)
|
var dialogVisible: any = ref(false)
|
||||||
|
var dialogTitle: any = ref('添加模型类型')
|
||||||
var modelType: any = ref('')
|
var modelType: any = ref('')
|
||||||
|
|
||||||
const handleClose = () => {
|
const handleClose = () => {
|
||||||
@ -193,16 +204,30 @@ const addType = () => {
|
|||||||
if (!modelType.value) {
|
if (!modelType.value) {
|
||||||
return ElMessage.warning('请输入模型类型名称')
|
return ElMessage.warning('请输入模型类型名称')
|
||||||
}
|
}
|
||||||
let params = {
|
if (dialogTitle.value == '添加模型类型') {
|
||||||
name: modelType.value,
|
let params = {
|
||||||
parentId: clickTreeNode && clickTreeNode.id ? clickTreeNode.id : undefined
|
name: modelType.value,
|
||||||
}
|
parentId: clickTreeNode && clickTreeNode.id ? clickTreeNode.id : undefined
|
||||||
ModelApi.addModelType(params).then((res) => {
|
|
||||||
if (res.code == 0 || res.code == 200) {
|
|
||||||
ElMessage.success('添加成功')
|
|
||||||
getModelList()
|
|
||||||
}
|
}
|
||||||
})
|
ModelApi.addModelType(params).then((res) => {
|
||||||
|
if (res.code == 0 || res.code == 200) {
|
||||||
|
ElMessage.success('添加成功')
|
||||||
|
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 = ''
|
modelType.value = ''
|
||||||
dialogVisible.value = false
|
dialogVisible.value = false
|
||||||
}
|
}
|
||||||
@ -285,30 +310,30 @@ const createModelDB = async () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//导入模型库
|
//导入模型库
|
||||||
const importModelDB = ()=>{
|
const importModelDB = () => {
|
||||||
let option = {
|
let option = {
|
||||||
properties: ["openFile"],
|
properties: ['openFile'],
|
||||||
filters: [
|
filters: [
|
||||||
{
|
{
|
||||||
name: '模型库', //、底图
|
name: '模型库', //、底图
|
||||||
extensions: ['model'],
|
extensions: ['model']
|
||||||
},
|
}
|
||||||
],
|
]
|
||||||
};
|
}
|
||||||
$sendElectronChanel("open-directory-dialog", option);
|
$sendElectronChanel('open-directory-dialog', option)
|
||||||
$recvElectronChanel("selectedItem", (e, path) => {
|
$recvElectronChanel('selectedItem', (e, path) => {
|
||||||
if (path.length) addModelDB(path[0]);
|
if (path.length) addModelDB(path[0])
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const addModelDB = (path)=>{
|
const addModelDB = (path) => {
|
||||||
let formData = new FormData()
|
let formData = new FormData()
|
||||||
formData.append('modelPath',path)
|
formData.append('modelPath', 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('导入成功')
|
||||||
getModelList()
|
getModelList()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -481,9 +506,13 @@ const loadModelsByType = (typeId: string) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const handleAddType = () => {
|
const handleAddType = () => {
|
||||||
|
dialogTitle.value = '添加模型类型'
|
||||||
|
modelType.value = ''
|
||||||
dialogVisible.value = true
|
dialogVisible.value = true
|
||||||
}
|
}
|
||||||
const handleAddChildType = (row: TypeNode) => {
|
const handleAddChildType = (row: TypeNode) => {
|
||||||
|
dialogTitle.value = '添加模型类型'
|
||||||
|
modelType.value = ''
|
||||||
dialogVisible.value = true
|
dialogVisible.value = true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -492,11 +521,13 @@ const handleImportModel = (row: TypeNode) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const handleRenameType = (row: TypeNode) => {
|
const handleRenameType = (row: TypeNode) => {
|
||||||
|
dialogTitle.value = '模型类型重命名'
|
||||||
|
modelType.value = row.label
|
||||||
|
dialogVisible.value = true
|
||||||
console.log('重命名类型', row)
|
console.log('重命名类型', row)
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleDeleteType = (row: TypeNode) => {
|
const handleDeleteType = (row: TypeNode) => {
|
||||||
|
|
||||||
ElMessageBox.confirm('是否删除数据?', '警告', {
|
ElMessageBox.confirm('是否删除数据?', '警告', {
|
||||||
confirmButtonText: '确定',
|
confirmButtonText: '确定',
|
||||||
cancelButtonText: '取消',
|
cancelButtonText: '取消',
|
||||||
@ -520,7 +551,6 @@ const handleEdit = (row: ModelItem) => {
|
|||||||
}
|
}
|
||||||
const updatePoster1 = (row, flag = false, path = '') => {
|
const updatePoster1 = (row, flag = false, path = '') => {
|
||||||
let cb = (c) => {
|
let cb = (c) => {
|
||||||
|
|
||||||
const formData = new FormData()
|
const formData = new FormData()
|
||||||
formData.append('modelId', row.id)
|
formData.append('modelId', row.id)
|
||||||
formData.append('file', c)
|
formData.append('file', c)
|
||||||
@ -552,71 +582,69 @@ const updatePoster1 = (row, flag = false, path = '') => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const updatePoster = (row, flag = false, path = "")=> {
|
const updatePoster = (row, flag = false, path = '') => {
|
||||||
let that = this;
|
let that = this
|
||||||
let cb = (c) => {
|
let cb = (c) => {
|
||||||
|
const formData = new FormData()
|
||||||
const formData = new FormData()
|
formData.append('modelId', row.id)
|
||||||
formData.append('modelId', row.id)
|
formData.append('file', c)
|
||||||
formData.append('file', c)
|
ModelApi.updatePoster(formData).then((res) => {
|
||||||
ModelApi.updatePoster(formData).then((res) => {
|
if (res.code == 0 || res.code == 200) {
|
||||||
if (res.code == 0 || res.code == 200) {
|
getModelListByType(row.modelTypeId)
|
||||||
getModelListByType(row.modelTypeId)
|
ElMessage.success('添加成功')
|
||||||
ElMessage.success('添加成功')
|
|
||||||
}
|
|
||||||
})
|
|
||||||
};
|
|
||||||
if (!flag) {
|
|
||||||
let option = {
|
|
||||||
properties: ["openFile"],
|
|
||||||
filters: [
|
|
||||||
{
|
|
||||||
name: "图片",
|
|
||||||
extensions: ["png", "jpg", "jpeg"],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
$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);
|
|
||||||
}
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if (!flag) {
|
||||||
|
let option = {
|
||||||
|
properties: ['openFile'],
|
||||||
|
filters: [
|
||||||
|
{
|
||||||
|
name: '图片',
|
||||||
|
extensions: ['png', 'jpg', 'jpeg']
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
$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('.')
|
||||||
}
|
}
|
||||||
|
|
||||||
const getNamefromPath = (path) => {
|
return name
|
||||||
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) => {
|
const handleDelete = (row: ModelItem) => {
|
||||||
|
|
||||||
ElMessageBox.confirm('是否删除数据?', '警告', {
|
ElMessageBox.confirm('是否删除数据?', '警告', {
|
||||||
confirmButtonText: '确定',
|
confirmButtonText: '确定',
|
||||||
cancelButtonText: '取消',
|
cancelButtonText: '取消',
|
||||||
|
|||||||
@ -25,6 +25,9 @@
|
|||||||
<el-tab-pane :label="t('system.modelManage')" name="modelManage">
|
<el-tab-pane :label="t('system.modelManage')" name="modelManage">
|
||||||
<modelManage></modelManage>
|
<modelManage></modelManage>
|
||||||
</el-tab-pane>
|
</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">
|
<el-tab-pane :label="t('system.version')" name="version">
|
||||||
<version></version>
|
<version></version>
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
@ -41,6 +44,7 @@ import engineering from './components/engineering.vue'
|
|||||||
import equipment from './components/equipment.vue'
|
import equipment from './components/equipment.vue'
|
||||||
import version from './components/version.vue'
|
import version from './components/version.vue'
|
||||||
import modelManage from './components/modelManage.vue'
|
import modelManage from './components/modelManage.vue'
|
||||||
|
import graphLabelManage from './components/graphLabelManage.vue'
|
||||||
|
|
||||||
import { useI18n } from 'vue-i18n'
|
import { useI18n } from 'vue-i18n'
|
||||||
const { t } = useI18n()
|
const { t } = useI18n()
|
||||||
|
|||||||
@ -202,6 +202,16 @@ const handleClick = (item: any, e) => {
|
|||||||
type: 'warning'
|
type: 'warning'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
} else if (item.key === 'military') {
|
||||||
|
//军标库
|
||||||
|
if ((window as any).checkAuthIsValid) {
|
||||||
|
eventBus.emit('openGraph', true)
|
||||||
|
} else {
|
||||||
|
ElMessage({
|
||||||
|
message: '您没有该功能的权限',
|
||||||
|
type: 'warning'
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const fold = () => {
|
const fold = () => {
|
||||||
|
|||||||
@ -4,7 +4,7 @@
|
|||||||
<template #header>
|
<template #header>
|
||||||
<div class="set_pup_header">
|
<div class="set_pup_header">
|
||||||
<div class="system_title">
|
<div class="system_title">
|
||||||
{{ t('model.title') }}
|
{{ t('graph.title') }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@ -13,55 +13,80 @@
|
|||||||
<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">
|
||||||
<svg-icon
|
<svg-icon
|
||||||
name="sys_set"
|
name="sys_set"
|
||||||
|
class="setIcon"
|
||||||
:size="12"
|
:size="12"
|
||||||
color="rgba(var(--color-sdk-base-rgb), 1)"
|
color="rgba(255,255,255, 1)"
|
||||||
style="margin-right: 5px"
|
style="margin-right: 5px"
|
||||||
></svg-icon
|
></svg-icon
|
||||||
>默认模型参数设置
|
>默认军标参数设置
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<!-- 左侧Tab导航 -->
|
<!-- 左侧Tab导航 -->
|
||||||
<el-tabs
|
<div class="treeCon">
|
||||||
v-model="activeTab"
|
<el-tree
|
||||||
tab-position="left"
|
style="max-width: 600px"
|
||||||
class="model-tabs"
|
:data="typeTreeData"
|
||||||
@tab-click="handleTabClick"
|
ref="treeRef"
|
||||||
>
|
node-key="id"
|
||||||
<el-tab-pane
|
:filter-node-method="filterNode"
|
||||||
v-for="(category, index) in categories"
|
|
||||||
:key="index"
|
|
||||||
:label="category.name"
|
|
||||||
:name="index.toString()"
|
|
||||||
>
|
>
|
||||||
</el-tab-pane>
|
<template #default="{ node, data }">
|
||||||
</el-tabs>
|
<!-- <span> {{ node.label }}</span> -->
|
||||||
|
|
||||||
<div class="model-gallery" ref="galleryRef" @scroll="handleScroll">
|
<span
|
||||||
<div
|
:class="{
|
||||||
v-for="(category, cIndex) in categories"
|
'primary-type': !(node.childNodes.length != 0),
|
||||||
:key="cIndex"
|
'selected-text': node.id === currentTypeId
|
||||||
class="model-section"
|
}"
|
||||||
:data-category="cIndex"
|
@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 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">
|
<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>
|
<template #error>
|
||||||
<div class="image-error">加载失败</div>
|
<div class="image-error">加载失败</div>
|
||||||
</template>
|
</template>
|
||||||
</el-image>
|
</el-image>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="model-name">{{ model.name }}</div>
|
<div class="model-name" :class="{ isactive: activeIndex == mIndex }">
|
||||||
|
{{ model.militaryName }}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -76,11 +101,16 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { useI18n } from 'vue-i18n'
|
import { useI18n } from 'vue-i18n'
|
||||||
import { Search } from '@element-plus/icons-vue'
|
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 type { TabsPaneContext } from 'element-plus'
|
||||||
|
import { useTreeNode } from '../tree/hooks/treeNode'
|
||||||
|
import { TreeApi } from '@/api/tree'
|
||||||
const { t } = useI18n()
|
const { t } = useI18n()
|
||||||
|
const { findParentId, findTreeIndex, cusAddNodes } = useTreeNode()
|
||||||
const isShowPup = ref(false)
|
const isShowPup = ref(false)
|
||||||
const eventBus: any = inject('bus')
|
const eventBus: any = inject('bus')
|
||||||
|
const { cusUpdateNode } = useTreeNode()
|
||||||
var modelName = ref('')
|
var modelName = ref('')
|
||||||
|
|
||||||
//tab
|
//tab
|
||||||
@ -92,53 +122,29 @@ interface Model {
|
|||||||
|
|
||||||
interface Category {
|
interface Category {
|
||||||
id: string
|
id: string
|
||||||
name: string
|
militaryName: string
|
||||||
models: Model[]
|
poster: string
|
||||||
|
data: string
|
||||||
}
|
}
|
||||||
|
|
||||||
// 模拟数据
|
// 模拟数据
|
||||||
const categories = ref<Category[]>([
|
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 activeTab = ref('0')
|
const activeTab = ref('0')
|
||||||
const galleryRef = ref<HTMLElement>()
|
const galleryRef = ref<HTMLElement>()
|
||||||
const loading = ref(false)
|
const loading = ref(false)
|
||||||
let observer: IntersectionObserver | null = null
|
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点击
|
// 处理Tab点击
|
||||||
const handleTabClick = (tab: TabsPaneContext) => {
|
const handleTabClick = (tab: TabsPaneContext) => {
|
||||||
const section = document.querySelector(`.model-section[data-category="${tab.index}"]`)
|
const section = document.querySelector(`.model-section[data-category="${tab.index}"]`)
|
||||||
@ -183,7 +189,7 @@ const loadMoreData = () => {
|
|||||||
.fill(0)
|
.fill(0)
|
||||||
.map((_, i) => ({
|
.map((_, i) => ({
|
||||||
id: `n${i}`,
|
id: `n${i}`,
|
||||||
name: `新增模型_${i}`,
|
name: `新增军标_${i}`,
|
||||||
thumbnail: `https://picsum.photos/300/200?random=${i + 100}`
|
thumbnail: `https://picsum.photos/300/200?random=${i + 100}`
|
||||||
}))
|
}))
|
||||||
})
|
})
|
||||||
@ -206,6 +212,150 @@ 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-table的toggleRowExpansion方法
|
||||||
|
// 需要通过ref获取table实例
|
||||||
|
// 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)
|
||||||
|
}
|
||||||
|
|
||||||
|
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()
|
||||||
|
|
||||||
|
console.log('model', model)
|
||||||
|
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(() => {
|
||||||
|
console.log('GroundSvg')
|
||||||
|
GroundSvg.drag(true, (data) => {
|
||||||
|
console.log(data, 'loaddata')
|
||||||
|
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(() => {
|
onMounted(() => {
|
||||||
initObserver()
|
initObserver()
|
||||||
})
|
})
|
||||||
@ -215,9 +365,29 @@ onBeforeUnmount(() => {
|
|||||||
})
|
})
|
||||||
//end
|
//end
|
||||||
|
|
||||||
eventBus.on('openModel', (data) => {
|
eventBus.on('openGraph', (data) => {
|
||||||
isShowPup.value = 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 = () => {
|
const open = () => {
|
||||||
isShowPup.value = true
|
isShowPup.value = true
|
||||||
}
|
}
|
||||||
@ -226,7 +396,7 @@ const close = () => {
|
|||||||
}
|
}
|
||||||
const setting = () => {
|
const setting = () => {
|
||||||
isShowPup.value = false
|
isShowPup.value = false
|
||||||
eventBus.emit('openModelSetting', true)
|
eventBus.emit('openGraphSetting', (true, isSetting))
|
||||||
}
|
}
|
||||||
|
|
||||||
defineExpose({
|
defineExpose({
|
||||||
@ -419,11 +589,19 @@ defineExpose({
|
|||||||
height: 32px;
|
height: 32px;
|
||||||
line-height: 32px;
|
line-height: 32px;
|
||||||
background: rgba(var(--color-sdk-base-rgb), 0.2) !important;
|
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;
|
border-radius: 4px;
|
||||||
color: rgba(var(--color-sdk-base-rgb), 1) !important;
|
color: #fff !important;
|
||||||
padding: 0 15px;
|
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 {
|
.content {
|
||||||
margin-top: 20px;
|
margin-top: 20px;
|
||||||
height: 400px;
|
height: 400px;
|
||||||
@ -431,7 +609,7 @@ defineExpose({
|
|||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style scoped>
|
<style lang="scss" scoped>
|
||||||
.model-container {
|
.model-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
@ -441,13 +619,20 @@ defineExpose({
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
float: left;
|
float: left;
|
||||||
}
|
}
|
||||||
|
.treeCon {
|
||||||
|
width: 140px;
|
||||||
|
height: 100%;
|
||||||
|
float: left;
|
||||||
|
border-right: 1px solid rgba(204, 204, 204, 0.2);
|
||||||
|
}
|
||||||
.model-gallery {
|
.model-gallery {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
/* padding: 20px; */
|
/* padding: 20px; */
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
width: calc(100% - 130px);
|
width: calc(100% - 160px);
|
||||||
float: left;
|
float: left;
|
||||||
|
margin-left: 10px;
|
||||||
}
|
}
|
||||||
.model-section {
|
.model-section {
|
||||||
min-height: 10vh;
|
min-height: 10vh;
|
||||||
@ -459,11 +644,6 @@ defineExpose({
|
|||||||
/* justify-content: space-around; */
|
/* justify-content: space-around; */
|
||||||
gap: 20px;
|
gap: 20px;
|
||||||
}
|
}
|
||||||
.model-item {
|
|
||||||
border-radius: 8px;
|
|
||||||
overflow: hidden;
|
|
||||||
/* box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1); */
|
|
||||||
}
|
|
||||||
.model-name {
|
.model-name {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 30px;
|
height: 30px;
|
||||||
@ -472,6 +652,22 @@ defineExpose({
|
|||||||
|
|
||||||
color: rgba(255, 255, 255, 1);
|
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 {
|
.imgbg {
|
||||||
width: 70px;
|
width: 70px;
|
||||||
height: 70px;
|
height: 70px;
|
||||||
@ -479,10 +675,10 @@ defineExpose({
|
|||||||
background-size: 100% 100%;
|
background-size: 100% 100%;
|
||||||
}
|
}
|
||||||
.thumbnail {
|
.thumbnail {
|
||||||
width: 66px;
|
width: 64px;
|
||||||
height: 66px;
|
height: 64px;
|
||||||
margin-left: 2px;
|
margin-left: 3px;
|
||||||
margin-top: 2px;
|
margin-top: 3px;
|
||||||
}
|
}
|
||||||
.loading-more {
|
.loading-more {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
@ -522,4 +718,28 @@ defineExpose({
|
|||||||
border-radius: 1em;
|
border-radius: 1em;
|
||||||
background-color: rgba(50, 50, 50, 0.1);
|
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>
|
</style>
|
||||||
450
src/renderer/src/views/components/propertyBox/graphObject.vue
Normal file
450
src/renderer/src/views/components/propertyBox/graphObject.vue
Normal 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>
|
||||||
157
src/renderer/src/views/components/propertyBox/graphSetting.vue
Normal file
157
src/renderer/src/views/components/propertyBox/graphSetting.vue
Normal 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>
|
||||||
@ -415,7 +415,7 @@
|
|||||||
max="99999999"
|
max="99999999"
|
||||||
v-model="entityOptions.labelNear"
|
v-model="entityOptions.labelNear"
|
||||||
/>
|
/>
|
||||||
<span class="unit">px</span>
|
<span class="unit">m</span>
|
||||||
<span class="arrow"></span>
|
<span class="arrow"></span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -430,7 +430,7 @@
|
|||||||
max="99999999"
|
max="99999999"
|
||||||
v-model="entityOptions.labelFar"
|
v-model="entityOptions.labelFar"
|
||||||
/>
|
/>
|
||||||
<span class="unit">px</span>
|
<span class="unit">m</span>
|
||||||
<span class="arrow"></span>
|
<span class="arrow"></span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -488,7 +488,6 @@
|
|||||||
</el-tabs>
|
</el-tabs>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<span class="custom-divider"></span>
|
|
||||||
</template>
|
</template>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<div style="position: absolute; left: 24px; display: flex">
|
<div style="position: absolute; left: 24px; display: flex">
|
||||||
@ -731,6 +730,7 @@ const confirm = () => {
|
|||||||
cusUpdateNode({ id: params.id, sourceName: params.name, params: JSON.stringify(params) })
|
cusUpdateNode({ id: params.id, sourceName: params.name, params: JSON.stringify(params) })
|
||||||
}
|
}
|
||||||
const close = () => {
|
const close = () => {
|
||||||
|
that.positionEditing = false
|
||||||
baseDialog.value?.close()
|
baseDialog.value?.close()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -173,6 +173,12 @@ export const useTreeNode = () => {
|
|||||||
// render: renderGlb,
|
// render: renderGlb,
|
||||||
// allowChildren: false,
|
// allowChildren: false,
|
||||||
},
|
},
|
||||||
|
military: {
|
||||||
|
rightMenus: ['edit', 'del', 'setView', 'resetView']
|
||||||
|
// detailFun: get_detail_glb,
|
||||||
|
// render: renderGlb,
|
||||||
|
// allowChildren: false,
|
||||||
|
},
|
||||||
diffuseScan: {
|
diffuseScan: {
|
||||||
rightMenus: ['edit', 'del', 'setView', 'resetView']
|
rightMenus: ['edit', 'del', 'setView', 'resetView']
|
||||||
// detailFun: get_detail_diffuseScan,
|
// detailFun: get_detail_diffuseScan,
|
||||||
|
|||||||
@ -40,11 +40,14 @@
|
|||||||
<tufuSelect ref="tufuselect"></tufuSelect>
|
<tufuSelect ref="tufuselect"></tufuSelect>
|
||||||
<imagePop ref="imagepop"></imagePop>
|
<imagePop ref="imagepop"></imagePop>
|
||||||
<model ref="Model"></model>
|
<model ref="Model"></model>
|
||||||
|
<graph ref="Graph"></graph>
|
||||||
|
<graphSetting ref="graphsetting"></graphSetting>
|
||||||
|
|
||||||
<!-- 图标列表 -->
|
<!-- 图标列表 -->
|
||||||
<selectImg ref="selectImgRef"></selectImg>
|
<selectImg ref="selectImgRef"></selectImg>
|
||||||
<modelSetting ref="modelsetting"></modelSetting>
|
<modelSetting ref="modelsetting"></modelSetting>
|
||||||
<modelObject ref="modelobject"></modelObject>
|
<modelObject ref="modelobject"></modelObject>
|
||||||
|
<graphObject ref="graphobject"></graphObject>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
@ -107,6 +110,9 @@ import waterSurface from '../components/propertyBox/waterSurface.vue'
|
|||||||
import { addMapSource } from '../../common/addMapSource'
|
import { addMapSource } from '../../common/addMapSource'
|
||||||
import modelSetting from '../components/propertyBox/modelSetting.vue'
|
import modelSetting from '../components/propertyBox/modelSetting.vue'
|
||||||
import modelObject from '../components/propertyBox/modelObject.vue'
|
import modelObject from '../components/propertyBox/modelObject.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'
|
import { GisApi } from '@/api/gisApi'
|
||||||
|
|
||||||
@ -234,6 +240,11 @@ eventBus.on('openDialog', async (sourceType: any, id: any) => {
|
|||||||
await nextTick()
|
await nextTick()
|
||||||
dynamicComponentRef.value?.open(id, 'model')
|
dynamicComponentRef.value?.open(id, 'model')
|
||||||
break
|
break
|
||||||
|
case 'military':
|
||||||
|
currentComponent.value = graphObject
|
||||||
|
await nextTick()
|
||||||
|
dynamicComponentRef.value?.open(id, 'military')
|
||||||
|
break
|
||||||
case 'pressModel':
|
case 'pressModel':
|
||||||
currentComponent.value = flat
|
currentComponent.value = flat
|
||||||
await nextTick()
|
await nextTick()
|
||||||
|
|||||||
Reference in New Issue
Block a user