Files
maintenance_system/src/views/largeScreen/components/newMap/dialog/model.vue

548 lines
16 KiB
Vue
Raw Normal View History

2025-10-11 09:56:33 +08:00
<script setup lang="ts">
import { getCurrentInstance } from 'vue';
import { getModelList, getModelTypeList, addOtherSource } from '@/views/largeScreen/components/api';
import { useTreeNode } from '../treeNode';
const isShowPup = ref(false);
const categories = ref<any[]>([]);
const loading = ref(false);
const { cusAddNodes } = useTreeNode();
//-----------类型树-----------
interface TypeNode {
id: string;
label: string;
parentId: string | null;
children?: TypeNode[];
}
let typeArr = {
point: '点',
line: '线',
area: '面'
};
const currentTypeId = ref<string>('');
const typeTreeData = ref<TypeNode[]>([]);
let activeIndex: any = ref(null);
// 获取组件实例
const instance = getCurrentInstance();
instance.proxy['$recvChanel']('open-model', () => {
console.log('open-model');
isShowPup.value = true;
typeList();
});
const typeList = async () => {
const res: any = await getModelTypeList();
if (res.code == 0 || res.code == 200) {
console.log('typeList', res);
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 handleTypeClick = (row: TypeNode) => {
getModelListByType(row.id);
currentTypeId.value = row['$treeNodeId'];
};
const getModelListByType = (id) => {
let formData = new FormData();
formData.append('modelTypeId', id);
console.log('formData', formData.get('modelTypeId'));
getModelList(formData).then((res) => {
categories.value = res.data;
});
};
const filterNode: any = (value, data) => {
if (!value) return true;
return data.label.includes(value);
};
const modelClick = (index, row) => {
activeIndex.value = index;
console.log('modelClick', row);
// 轨迹运动选择模型
// if (selectCallback && typeof selectCallback === 'function' && addType.value === 'trajectoryMotion') {
// selectCallback('http://127.0.0.1:8848' + row.data);
// close();
// return;
// }
// if (!isSetting) {
// ElMessage.warning('请先设置模型默认参数');
// return;
// }
isShowPup.value = false;
let id = new window['YJ'].Tools().randomString();
new window['YJ'].Obj.BatchModel(window['Earth1'], { id, type: typeArr['point'] }, function (data) {
console.log(data);
renderModel(data, row);
});
const renderModel = async (option, model) => {
let selectedNode = window['treeObj'].getSelectedNodes()[0];
// 存在坐标
if (option.positions.length > 0) {
let id = new window['YJ'].Tools().randomString();
let params = {
id: id,
position: option.positions[0],
name: model.modelName,
show: true,
scale: { x: 1, y: 1, z: 1 },
url: getURL(model.modelDataUrl),
maximumScale: 1,
rotate: {
x: 0,
y: 0,
z: 0
}
};
await new window['YJ'].Obj.Model(window['Earth1'], params);
let DbOption: any = {
params,
id,
sourceName: model.modelName,
sourceType: 'model',
parentId: selectedNode ? (selectedNode.sourceType == 'directory' ? selectedNode.id : selectedNode.parentId) : undefined
};
addOtherSource(DbOption);
DbOption.params = JSON.stringify(DbOption.params);
DbOption.isShow = true;
cusAddNodes(window['treeObj'], DbOption.parentId, [DbOption]);
}
};
};
const getURL = (url) => {
// 'http://192.168.110.2:3456';
return import.meta.env.VITE_APP_MAP_API + url;
};
</script>
<template>
<div class="set_pup">
<el-dialog :close-on-click-modal="false" v-model="isShowPup" :modal="false" draggable>
<template #header>
<div class="set_pup_header">
<div class="system_title">模型选择</div>
</div>
</template>
<div class="set_detail">
<!-- 搜索和参数设置-->
<!-- <div class="top">
<el-input v-model="modelName" class="w-50 m-2" placeholder="请输入模型名称进行搜索" :suffix-icon="Search" />
<button @click="setting" class="btn">
<svg-icon name="sys_set" class="setIcon" :size="12" color="rgba(255,255,255, 1)" style="margin-right: 5px"></svg-icon>默认模型参数设置
</button>
</div>-->
<div class="content">
<!-- 左侧Tab导航 -->
<div class="treeCon">
<el-tree
style="max-width: 600px"
:data="typeTreeData"
ref="treeRef"
node-key="id"
@node-click="handleTypeClick"
:filter-node-method="filterNode"
>
<template #default="{ node, data }">
<!-- <span> {{ node.label }}</span> -->
<!-- @click.stop="toggleExpand(node)" @click.stop="toggleExpand(node)" -->
<span
:class="{
'primary-type': !(node.childNodes.length != 0),
'selected-text': node.id === currentTypeId
}"
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"
></svg-icon>
{{ node.label }}</span
>
</template>
</el-tree>
</div>
<div class="model-gallery" ref="galleryRef">
<div class="model-section">
<!-- <h2 class="section-title">{{ categories[Number(currentTypeId)].name }}</h2> -->
<div class="model-grid">
<div v-for="(model, mIndex) in categories" :key="mIndex" class="model-item" @click="modelClick(mIndex, model)">
<div class="imgbg">
<el-image :src="getURL(model.posterDataUrl)" fit="cover" class="thumbnail">
<!-- <template #error>-->
<!-- <div class="image-error">加载失败</div>-->
<!-- </template>-->
</el-image>
</div>
<div class="model-name" :class="{ isactive: activeIndex == mIndex }">
{{ model.modelName }}
</div>
</div>
</div>
</div>
<div v-show="loading" class="loading-more">加载中...</div>
</div>
</div>
</div>
</el-dialog>
</div>
</template>
<style scoped lang="scss">
:root {
--color-sdk-base-rgb: 0, 255, 255;
--color-sdk-auxiliary: 0, 66, 66;
--color-sdk-auxiliary-public: #ffffff;
--color-sdk-warning-0: #1bf8c3;
--color-sdk-warning-1: #f16c55;
--color-sdk-warning-2: #ffa145;
--color-sdk-warning-3: #ffdf53;
--color-sdk-text-head: #ffffff;
--color-sdk-text-head-1: #e6f7ff;
--color-sdk-text-head-2: #adf1ff;
--color-sdk-gradual: rgb(0, 255, 255) 6.25%, rgb(0, 200, 255) 100%;
--color-sdk-bg-gradual: #00ffff33 0%, #00ffff00 100%;
--color-sdk-text-shadow: rgba(20, 118, 255, 1);
}
.set_pup {
position: fixed;
width: 40vw;
height: 50vh;
:deep(.el-dialog) {
background: linear-gradient(180deg, rgba(0, 255, 255, 0.2) 0%, rgba(0, 255, 255, 0) 100%), rgba(0, 0, 0, 0.6);
border: 1px solid #00c9ff;
padding-left: 0 !important;
}
:deep(.el-dialog__body) {
padding: 0 !important;
}
:deep(.el-dialog__headerbtn) {
height: 30px;
width: 30px;
border-bottom-left-radius: 80%;
background-color: #008989;
&:hover {
background-color: #00ffff;
.el-dialog__close {
color: rgba(0, 66, 66, 1); // 悬停时改变关闭图标为红色
}
}
}
:deep(.el-dialog__headerbtn .el-dialog__close) {
color: #fff;
}
.set_pup_header {
width: 100%;
height: 100%;
// background-color: #00ffff;
display: flex;
justify-content: center;
align-items: center;
padding-bottom: 20px;
.system_title {
background: url('@/assets/images/map/titlebg.png') no-repeat;
background-size: 100% 100%;
width: 229px;
height: 34px;
line-height: 34px;
text-align: center;
font-family: 'alimamashuheiti';
font-size: 18px;
color: #fff;
font-weight: 700;
}
}
.set_detail {
box-sizing: border-box;
// height: 50vh;
:deep(
.el-tabs--left .el-tabs__active-bar.is-left,
.el-tabs--left .el-tabs__active-bar.is-right,
.el-tabs--right .el-tabs__active-bar.is-left,
.el-tabs--right .el-tabs__active-bar.is-right
) {
width: 3px;
background: rgba(0, 255, 255, 1);
height: 40px !important;
}
:deep(
.el-tabs--left .el-tabs__nav-wrap.is-left::after,
.el-tabs--left .el-tabs__nav-wrap.is-right::after,
.el-tabs--right .el-tabs__nav-wrap.is-left::after,
.el-tabs--right .el-tabs__nav-wrap.is-right::after
) {
width: 3px;
}
:deep(.el-tabs__nav-wrap::after) {
background: rgba(204, 204, 204, 0.5);
border-radius: 4px;
}
// .switchmy {
// display: flex;
// flex-wrap: wrap;
// margin-top: 15px;
// .center {
// width: 33%;
// margin-bottom: 15px;
// }
// }
:deep(.el-tabs__content) {
height: 50vh;
width: 80%;
padding: 0 10px;
overflow: hidden;
overflow-y: scroll;
color: #fff;
}
// 美化滚动条
:deep(.el-tabs__content::-webkit-scrollbar) {
width: 5px;
height: 5px;
}
:deep(.el-tabs__content::-webkit-scrollbar-thumb) {
background-color: #0ff;
border-radius: 5px;
}
:deep(.el-tabs__content::-webkit-scrollbar-track) {
background-color: rgba(0, 255, 255, 0.2);
}
:deep(.el-tabs__item) {
width: 8vw;
color: #fff !important;
font-size: 1.1rem;
font-family: 黑体;
font-weight: 500;
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 3px;
box-sizing: border-box;
}
:deep(.el-tabs__item:hover) {
background: linear-gradient(90deg, rgba(0, 255, 255, 0) 0%, rgba(0, 255, 255, 0.5) 48.91%, rgba(0, 255, 255, 0) 100%);
border: 1px solid;
box-sizing: border-box;
border-image: linear-gradient(90deg, rgba(0, 255, 255, 0) 0%, rgba(0, 255, 255, 1) 55.55%, rgba(0, 255, 255, 0) 100%) 1;
}
:deep(.el-tabs__item.is-active) {
background: linear-gradient(90deg, rgba(0, 255, 255, 0) 0%, rgba(0, 255, 255, 0.5) 48.91%, rgba(0, 255, 255, 0) 100%) !important;
border: 0.1px solid;
// box-sizing: border-box;
border-image: linear-gradient(90deg, rgba(0, 255, 255, 0) 0%, rgba(0, 255, 255, 1) 55.55%, rgba(0, 255, 255, 0) 100%) 1 !important;
}
:deep(.el-tabs__header) {
height: 50vh !important;
width: 8vw;
overflow-y: auto;
overflow-x: hidden;
}
:deep(.el-tabs__nav-next, .el-tabs__nav-prev) {
color: #fff;
}
}
.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;
--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;
}
.btn {
float: right;
height: 32px;
line-height: 32px;
background: rgba(var(--color-sdk-base-rgb), 0.2) !important;
border: 1px solid rgba(var(--color-sdk-base-rgb), 0.5) !important;
border-radius: 4px;
color: #fff !important;
padding: 0 15px;
}
.btn:hover {
color: rgba(var(--color-sdk-base-rgb), 1) !important;
border: 1px solid rgba(var(--color-sdk-base-rgb), 1) !important;
.setIcon {
color: rgba(var(--color-sdk-base-rgb), 1) !important;
}
}
.content {
margin-top: 20px;
height: 400px;
}
}
.model-container {
display: flex;
height: 100vh;
}
.model-tabs {
width: 130px;
height: 100%;
float: left;
}
.treeCon {
width: 140px;
height: 100%;
float: left;
border-right: 1px solid rgba(204, 204, 204, 0.2);
}
.model-gallery {
flex: 1;
/* padding: 20px; */
overflow-y: auto;
height: 100%;
width: calc(100% - 160px);
float: left;
margin-left: 10px;
}
.model-section {
min-height: 10vh;
margin-bottom: 40px;
}
.model-grid {
display: flex;
flex-wrap: wrap;
/* justify-content: space-around; */
//justify-content: space-between;
gap: 10px;
}
.model-name {
width: 100%;
//height: 30px;
//line-height: 30px;
text-align: center;
word-break: break-all;
/* overflow-wrap: break-word; */
overflow-wrap: break-word;
color: rgba(255, 255, 255, 1);
}
.isactive {
color: rgba(var(--color-sdk-base-rgb), 1) !important;
}
.model-item {
border-radius: 8px;
overflow: hidden;
width: 18%;
/* box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1); */
}
.model-item:hover {
cursor: pointer !important;
color: rgba(var(--color-sdk-base-rgb), 1) !important;
.model-name {
color: rgba(var(--color-sdk-base-rgb), 1) !important;
}
}
.imgbg {
//width: 70px;
//height: 70px;
width: 100%;
margin: 0 auto;
background: url('@/assets/images/map/model-bg.png') no-repeat;
background-size: 100% 100%;
}
.thumbnail {
width: 100%;
//width: 66px;
//height: 66px;
//margin-left: 2px;
//margin-top: 2px;
}
.loading-more {
text-align: center;
padding: 20px;
}
::v-deep .el-tabs__content {
display: none !important;
}
/* 修改滚动条轨道的颜色 */
::v-deep ::-webkit-scrollbar-track {
background: rgba(var(--color-sdk-base-rgb), 0.1) !important;
}
/* 修改滚动条滑块的样式 */
::v-deep ::-webkit-scrollbar-thumb {
background: rgba(var(--color-sdk-base-rgb), 1) !important;
border-radius: 10px;
}
/* 当滑块被激活(用户点击或拖动时) */
::v-deep ::-webkit-scrollbar-thumb:hover {
background: rgba(var(--color-sdk-base-rgb), 1) !important;
}
</style>
<style>
::-webkit-scrollbar {
width: 5px;
height: 5px;
}
/* 定义背景颜色和圆角 */
::-webkit-scrollbar-thumb {
border-radius: 1em;
background-color: rgba(50, 50, 50, 0.3);
}
/* //定义滚动条轨道 内阴影+圆角 */
::-webkit-scrollbar-track {
border-radius: 1em;
background-color: rgba(50, 50, 50, 0.1);
}
/* tree */
.el-tree-node__content > .el-tree-node__expand-icon {
display: none !important;
}
.el-tree {
background: transparent !important;
--el-tree-node-hover-bg-color: rgba(var(--color-sdk-base-rgb), 0.2) !important;
color: rgba(255, 255, 255, 1) !important;
/* font-size: 12px !important; */
width: 130px;
float: left;
margin-left: 10px;
}
::v-deep .el-text {
color: rgba(255, 255, 255, 1) !important;
font-size: 12px !important;
}
.selected-text {
color: rgba(var(--color-sdk-base-rgb), 1) !important; /* Element UI主色可自定义 */
}
::v-deep .el-tree--highlight-current .el-tree-node.is-current > .el-tree-node__content {
border-right: 1px solid rgba(var(--color-sdk-base-rgb), 0.2) !important;
}
</style>