Files
maintenance_system/src/views/largeScreen/components/newMap/dialog/model.vue
2025-10-11 09:56:33 +08:00

548 lines
16 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<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>