<template>
|
<div class="main-container" :style="{
|
zoom: zoom_main,
|
width: screen_width + 'rem',
|
height: screen_height + 'rem',
|
// width:'100%',
|
// height:'calc(100vh - 10rem)'
|
}">
|
|
<div id="content" class="equipments-container area-map" v-show="hideServe"
|
@mousedown="handleMouseDown"
|
:style="{
|
transform: `scale(${scale_container})`,
|
width: screen_width + 'rem',
|
height: screen_height + 'rem',
|
'margin-left': `${container_offset_left}rem`,
|
'margin-top': `${container_offset_top}rem`,
|
|
backgroundImage: `url(${areaUrl})`,
|
backgroundSize: 'cover',
|
backgroundPosition: 'center',
|
backgroundRepeat: 'no-repeat',
|
top: `${position.top}px`,
|
left: `${position.left}px`,
|
}">
|
|
<div v-for="(item, index) in elements" :key="index" class="grid-item bridge-items" :style="{
|
width: elementWidth + 'rem',
|
height: elementHeight + 'rem',
|
top: `${item.row * elementHeight}rem`,
|
left: `${item.cell * elementWidth}rem`
|
}">
|
<!-- 每个元素的内容可以放在这里 -->
|
|
<div v-if="item.isPlaceholder" class="bridge-item" @dblclick="handleItemClickCancel(item)"
|
@click="handleClickToAddItem(index,item)"
|
|
:class="[item?.deviceInfo ? 'space-in' : '',!item?.deviceInfo || !item?.deviceInfo?.id?'space-text-gray': '',
|
status_indrag &&
|
(!item?.deviceInfo || !item?.deviceInfo?.id)? 'space-drag': '',
|
]"
|
>
|
<div
|
class="space-text"
|
:class="[
|
item?.deviceInfo?.statusInt == 2 ||
|
item?.deviceInfo?.statusInt == 3 ||
|
item?.deviceInfo?.statusInt == 4? 'space-text-red' : '',
|
item?.deviceInfo?.statusInt == 1 ? 'space-text-yellow' : '',
|
]"
|
@dragstart="dragstart($event, index)" @dragend="dragend($event, index)"
|
@drop="handleDrop($event, index)" @dragover="handleDragOver($event)" draggable="true"
|
@click="showDeviceInfo(index,item,$event)"
|
>
|
{{ item.deviceInfo?.networkPort }}
|
<device-info v-show="selectedIndex === index " :show_info="show_device_info"
|
:device_info="cur_device_info" @toSwitchInfo="toSwitchInfo" @statusPort="statusPort"
|
@delPort="delPort"
|
></device-info>
|
</div>
|
</div>
|
<div v-else @click="handleItemClick(item)" class="bridge-item-none hover-shadow">
|
<div :style="{
|
width: elementWidth + 'rem',
|
height: elementHeight / 2 + 'rem'
|
}"></div>
|
</div>
|
|
</div>
|
|
</div>
|
<!-- 需要渲染一个canvas,然后基于数据,和滚动坐标,缩放坐标,位置中点吧 -->
|
<tj-container v-if="true && code" :code="code" :key="code" @closeself="closeself"
|
:chartclose="chartclose"></tj-container>
|
<!-- 显示图标的开关 -->
|
<div v-if="true && code && chartclose" class="chart-open" @click="chartclose = false">
|
<div class="img-button"></div>
|
</div>
|
<equ-add-form ref="equAddForm" :code="code" :areas="areas" :init_device_list="device_list"
|
@update="update_device_info" :cur_item="cur_item"></equ-add-form>
|
<server-info v-if="!hideServe" :serve_info="serve_info" :serve_select="serve_select" :code="code"></server-info>
|
|
<div class="back-button-left-bottom" @click="backToTop">返回</div>
|
|
</div>
|
</template>
|
<script>
|
import tjContainer from "./tj-container";
|
import bridge from "@/components/bridge";
|
import serverInfo from "./server-info";
|
import equAddForm from "@/components/equ-add-form.vue";
|
import deviceInfo from "@/components/device-info";
|
|
import A27 from '@/assets/screen/screen5/svgs3d/A27.svg'
|
|
import {
|
getAreaServeInfo,
|
getFaultInfo,
|
getDeviceList,
|
updateDevicePosition,
|
getBridgeInfos,
|
delport,
|
statusPort,
|
getAreaModuleBycode,
|
} from "@/api/area";
|
import { getAreaTjData } from "@/api/area";
|
|
import { mapdata } from "./map-data.js";
|
import Bridge from "@/components/bridge.vue";
|
|
export default {
|
components: { tjContainer, bridge, equAddForm, Bridge, serverInfo, deviceInfo },
|
props: {
|
item_show: false,
|
code: "",
|
query_networkPort: '',
|
},
|
//根据
|
//后端存储的是世界坐标,初次时候也是世界坐标,最小单位为0.01吧,这个间距或者大小,不考虑实际像素
|
//渲染时候,需要把 坐标,变为实际rem等像素坐标
|
//每个厂房大小不一样,先用一定的数代表吧.
|
|
data() {
|
return {
|
status_indrag: false,
|
current_drag_index: undefined,
|
bridge_infos: {},
|
//如果显示服务器的话
|
hideServe: true,
|
|
html_base: 10,
|
zoom_main: 0.8,
|
width: "160",
|
height: "60",
|
//默认的视点
|
x: 0,
|
y: 0,
|
zoom: 1, //默认的缩放级别,应该保证可以容纳整个项目
|
scale_container: 0.9,
|
//设备数据,实际便宜多少米+实际的宽高大小
|
equipmentdata: [
|
{ t: "a", x: 20, y: 30, w: 1, h: 2 },
|
{ t: "a", x: 40, y: 30, w: 2, h: 2 },
|
{ t: "a", x: 60, y: 35, w: 2, h: 1 },
|
],
|
|
//实际的像素比,单位rem
|
//屏幕和实际像素,默认比应该是,1:1?,反正有个比例吧,类似1米(其他单位)=多少px
|
//这个可以定死
|
screen_width: "160",
|
screen_height: "80",
|
base_move_offset: 0.6,
|
screen_margin_left: 0,
|
screen_margin_top: 0, //放大后的实际坐标-原本坐标,就是实际可以做的偏移量了,不能小于0,不能大于比例的,
|
// 当scale变化时候,的时候,恢复一下?或者scale放大的时候会有个,变化
|
|
//至于网桥,实际无非也是一组设备,到时候按照渲染出来就好了,先考虑canvas的拖拽?
|
mouse_click: undefined,
|
mouse_offset_last: undefined,
|
tleft: 20,
|
cal_offset_x: 0,
|
cal_offset_y: 0,
|
startclientX: 0, // 元素拖拽前距离浏览器的X轴位置
|
startclientY: 0, //元素拖拽前距离浏览器的Y轴位置
|
//设备列表
|
device_list: [],
|
device_list_map: {},
|
container_offset_x: 0,
|
container_offset_y: 0,
|
container_offset_left: 0,
|
container_offset_top: 0,
|
//服务器的
|
serve_timer: null,
|
serve_scroll_num: 0,
|
serve_info: {},
|
serve_select: {},
|
data_service_list: [
|
// {
|
// time: "1-10",
|
// desc: "Host: SZHMESVMA544<br/>Line: SMT26<br/>Critical",
|
// status: "red",
|
// }
|
],
|
//图标的
|
chartclose: false,
|
current_show_id: "",
|
//新增的
|
areas: [],
|
activateSwitchPorts: {},
|
switchAllDetialInfos: [],
|
dialog_activateSwitchPorts: false,
|
first_query_ip: true,
|
|
totalElements: 1000, // 元素总数
|
areaUrl: A27, // 区域背景图
|
elements: [], // 初始化 elements 数据为空数组
|
isDragging: false,
|
dragSource: null, // 当前被拖拽的元素
|
|
show_device_info: false, // 展示设备信息
|
selectedIndex: null,
|
cur_device_info: null, // 当前的设备信息
|
cur_item:null,// 当前的element
|
|
offsetX: 0, // 鼠标点击时相对元素的 X 偏移量
|
offsetY: 0, // 鼠标点击时相对元素的 Y 偏移量
|
position: {
|
top: 100, // 元素初始位置
|
left: 100, // 元素初始位置
|
},
|
};
|
},
|
computed: {
|
// 计算行数和列数
|
gridDimensions() {
|
const columns = Math.ceil(Math.sqrt(this.totalElements * (this.screen_width / this.screen_height)));
|
const rows = Math.ceil(this.totalElements / columns);
|
return { columns, rows };
|
},
|
// 每个元素的宽度
|
elementWidth() {
|
return this.screen_width / this.gridDimensions.columns;
|
},
|
// 每个元素的高度
|
elementHeight() {
|
return this.screen_height / this.gridDimensions.rows;
|
},
|
},
|
created() {
|
var zoom = this.$route.query.zoom;
|
// console.log(this.$route, this.$router);
|
if (zoom) {
|
this.zoom_main = parseFloat(zoom);
|
}
|
this.x = parseFloat(this.width) / 2;
|
this.y = parseFloat(this.height) / 2;
|
this.screen_width = parseFloat(this.screen_width) * this.zoom;
|
this.screen_height = parseFloat(this.screen_height) * this.zoom;
|
},
|
async mounted() {
|
// console.log("main-container1,mounted");
|
const content = document.getElementById("content");
|
content.addEventListener("wheel", this.handleWheel);
|
//获取到此区域的全部信息
|
this.device_list = [];
|
if (this.code) {
|
// this.update_map();
|
}
|
|
getAreaTjData().then((res) => {
|
this.areas = res.switchAreaInfo || [];
|
});
|
if(this.code){
|
// 获取当前页面的背景图和数量
|
this.initArea();
|
// 根据屏幕初始化格子
|
this.initializeElements(); // 在组件加载时初始化 elements
|
// 初始化设备信息
|
this.handleBindElementsItems()
|
}
|
|
// this.handleBindElementsItemsTest()
|
},
|
destroyed() {
|
const content = document.getElementById("content");
|
content.removeEventListener("wheel", this.handleWheel);
|
this.stopScrolling();
|
},
|
methods: {
|
|
// 获取区域的背景图和数量
|
async initArea(){
|
const areaInfo = await getAreaModuleBycode(this.code)
|
if(areaInfo&&areaInfo.areaModuleItems){
|
let areaModuleItems=areaInfo.areaModuleItems
|
if(areaModuleItems.areaConfigNum){
|
this.totalElements = areaModuleItems.areaConfigNum;
|
}
|
|
this.areaUrl =areaModuleItems.url
|
}
|
|
},
|
|
initializeElements() {
|
const elements = [];
|
for (let i = 0; i < this.totalElements; i++) {
|
const cell = i % this.gridDimensions.columns;
|
const row = Math.floor(i / this.gridDimensions.columns);
|
const isPlaceholder = false
|
const name = row + "-" + cell
|
// 绑定设备信息
|
const deviceInfo = {}
|
elements.push({ row, cell, isPlaceholder, name, deviceInfo });
|
}
|
|
// 判断最后一行是否需要补齐
|
const remainder = this.totalElements % this.gridDimensions.columns;
|
if (remainder !== 0) {
|
const placeholdersNeeded = this.gridDimensions.columns - remainder;
|
for (let i = 0; i < placeholdersNeeded; i++) {
|
const cell = remainder + i;
|
const row = Math.floor(this.totalElements / this.gridDimensions.columns);
|
const isPlaceholder = false
|
const name = row + "-" + cell
|
// 绑定设备信息
|
const deviceInfo = {}
|
elements.push({ row, cell, isPlaceholder, name, deviceInfo });
|
}
|
}
|
|
// TODO 遍历elements给每个elements复制index,为当前的遍历的索引
|
// 遍历 elements 添加 index 属性
|
elements.forEach((element, index) => {
|
element.index = index;
|
});
|
this.elements = elements; // 赋值给 data 中的 elements
|
},
|
|
|
async handleBindElementsItems() {
|
let deviceInfoList = await getDeviceList(this.code);
|
|
// 获取 switchDetialInfos
|
let switchDetialInfos = deviceInfoList.switchDetialInfos;
|
console.log("所有的数量:"+this.totalElements)
|
console.log("switchDetialInfos")
|
console.log(switchDetialInfos)
|
|
// 用于存放无效的设备信息
|
let invalidSwitchDetails = [];
|
|
// 用于存放重复 key 的设备信息
|
let duplicateSwitchDetails = [];
|
|
// 用于存放 areaRow 或 areaCell 为 -1 的设备信息
|
let filteredSwitchDetails = [];
|
|
// 创建一个 Map 来存储有效的设备信息
|
let switchDetailInfosMap = new Map();
|
|
// 遍历 switchDetialInfos
|
switchDetialInfos.forEach((info) => {
|
let { areaRow, areaCell } = info;
|
|
// 检查是否为无效值:""(空字符串)、undefined、null、-1
|
if ([null, undefined, "", -1].includes(areaRow) || [null, undefined, "", -1].includes(areaCell)) {
|
invalidSwitchDetails.push(info);
|
return; // 跳过后续逻辑
|
}
|
|
// 检查是否包含 -1,记录到 filteredSwitchDetails
|
if (areaRow == -1 || areaCell == -1) {
|
filteredSwitchDetails.push(info);
|
return; // 跳过后续逻辑
|
}
|
|
// 构造唯一 key
|
let key = `${areaRow}-${areaCell}`;
|
console.log(key)
|
// 检查 key 是否已经存在
|
if (switchDetailInfosMap.has(key)) {
|
// 如果存在,将当前 info 添加到重复数组中
|
duplicateSwitchDetails.push(info);
|
} else {
|
// 如果不存在,将 info 存入 Map
|
switchDetailInfosMap.set(key, info);
|
|
}
|
});
|
|
console.log("总数量:",switchDetialInfos.length)
|
console.log("无效的设备信息:", invalidSwitchDetails);
|
console.log("包含 -1 的设备信息:", filteredSwitchDetails);
|
console.log("重复的设备信息:", duplicateSwitchDetails);
|
console.log("设备信息转换后的 Map:", switchDetailInfosMap);
|
|
// Step 1: 将 this.elements 转换为 Map,方便快速查找
|
// let elementsMap = new Map(
|
// this.elements.map((element) => [`${element.row}-${element.cell}`, element])
|
// );
|
|
// // Step 2: 遍历 switchDetailInfosMap,直接匹配 elementsMap 中的 key
|
// switchDetailInfosMap.forEach((info, key) => {
|
// // 在 elementsMap 中查找匹配的元素
|
// let element = elementsMap.get(key);
|
// if (element) {
|
// // 如果找到匹配的元素,更新其信息
|
// element.deviceInfo = info;
|
// element.isPlaceholder = true;
|
// }
|
// });
|
|
|
// 遍历 elements,将匹配的设备信息绑定到对应的元素
|
this.elements.forEach((element) => {
|
let key = `${element.row}-${element.cell}`; // 使用元素的 row 和 cell 构造 key
|
let deviceInfo = switchDetailInfosMap.get(key); // 从 Map 中查找设备信息
|
if (deviceInfo) {
|
// 如果找到设备信息,存放到 element 的 deviceInfo 属性
|
element.deviceInfo = deviceInfo;
|
element.isPlaceholder = true;
|
} else {
|
// 如果未找到,则清空或设置默认值
|
element.deviceInfo = null;
|
element.isPlaceholder = false;
|
}
|
});
|
|
// 合并无效和重复的设备信息数组,并倒序 filteredSwitchDetails
|
let allDeviceDetails = [...invalidSwitchDetails, ...duplicateSwitchDetails,...filteredSwitchDetails];
|
console.log("allDeviceDetails:", allDeviceDetails);
|
|
// 遍历 elements,并查找 deviceInfo 为空的元素
|
let emptyDeviceInfoElements = [];
|
|
// 创建 elements 的浅拷贝,并倒序遍历
|
const reversedElements = [...this.elements].reverse();
|
|
// 遍历 reversedElements,并查找 deviceInfo 为空的元素
|
reversedElements.forEach((element) => {
|
if (!element.deviceInfo) {
|
// 记录所有 deviceInfo 为空的元素
|
emptyDeviceInfoElements.push(element);
|
}
|
});
|
|
// 确保空的 deviceInfo 元素数组的长度与 allDeviceDetails 数组的长度一致
|
let totalDevices = Math.min(emptyDeviceInfoElements.length, allDeviceDetails.length);
|
|
// 动态为这些元素赋值设备信息
|
for (let i = 0; i < totalDevices; i++) {
|
const device = allDeviceDetails[i] || {}; // 防止越界
|
const element = emptyDeviceInfoElements[i];
|
device.areaRow = element.row;
|
device.areaCell = element.cell;
|
element.deviceInfo = device;
|
element.isPlaceholder = true; // 设置占位符
|
|
// 根据索引更新原数组的元素
|
const originalIndex = this.elements.findIndex((el) => el.row === element.row && el.cell === element.cell);
|
if (originalIndex !== -1) {
|
this.elements[originalIndex] = element;
|
}
|
}
|
},
|
|
async handleBindElementsItemsTest() {
|
const deviceInfoList = await getDeviceList(this.code)
|
const switchDetialInfos = deviceInfoList.switchDetialInfos
|
|
// const evenIndexes = this.elements.filter((_, index) => index % 2 === 0);
|
const evenIndexes = this.elements.filter(element => element.cell % 2 == 0);
|
evenIndexes.forEach((element, index) => {
|
element.deviceInfo = switchDetialInfos[index] || null;
|
// element.isPlaceholder = !!switchDetialInfos[index];
|
element.isPlaceholder=true;
|
});
|
|
console.log("所有布局元素")
|
console.log(this.elements)
|
|
},
|
|
handleItemClick(item) {
|
this.isDragging = false;
|
item.deviceInfo = null;
|
this.$set(item, 'isPlaceholder', true)
|
},
|
handleItemClickCancel(item) {
|
this.isDragging = false;
|
// 这里的取消操作需要判断当前的元素是不是空的
|
if(item?.deviceInfo?.id){
|
// this.$message('空设备才可双击删除!');
|
}else{
|
this.$set(item, 'isPlaceholder', false)
|
this.$message('空设备删除成功!');
|
}
|
|
},
|
|
|
toSwitchInfo(info) {
|
this.isDragging = false;
|
this.showServe(info);
|
},
|
async statusPort(info) {
|
//设置状态为正常
|
console.log("statusPort", info);
|
// return
|
var json = {
|
id: info.id,
|
operateType: 0,
|
networkPort: info.name,
|
};
|
this.$modal.loading("更新中");
|
|
const data = await statusPort(json);
|
|
this.$modal.closeLoading();
|
|
|
// 根据屏幕初始化格子
|
this.initializeElements(); // 在组件加载时初始化 elements
|
// 初始化设备信息
|
this.handleBindElementsItems()
|
// this.update_map();
|
},
|
async delPort(info) {
|
|
var json = {
|
id: info.id,
|
operateType: 4,
|
networkPort: info.name,
|
};
|
this.$modal.loading("删除中");
|
|
const data = await delport(json);
|
|
this.$modal.closeLoading();
|
|
// 根据屏幕初始化格子
|
this.initializeElements(); // 在组件加载时初始化 elements
|
// 初始化设备信息
|
this.handleBindElementsItems()
|
},
|
backToTop() {
|
if (!this.hideServe) {
|
this.hideServe = !this.hideServe;
|
return;
|
}
|
this.$router.push({ path: "/area-all" });
|
},
|
|
async update_device_info() {
|
// 根据屏幕初始化格子
|
this.initializeElements(); // 在组件加载时初始化 elements
|
// 初始化设备信息
|
this.handleBindElementsItems()
|
},
|
|
async update_map() {
|
this.$modal.loading("加载中");
|
var re = await getDeviceList(this.code);
|
this.device_list = re.switchDetialInfos || [];
|
await this.init_data();
|
this.$modal.closeLoading();
|
if (this.query_networkPort && this.bridge_infos && this.first_query_ip) {
|
this.first_query_ip = false
|
|
console.log('this.bridge_infos', this.bridge_infos, this.query_networkPort)
|
|
for (var key of Object.keys(this.bridge_infos)) {
|
var allcells = this.bridge_infos[key]
|
for (var cell of allcells.cells) {
|
var datamaps = cell.datamap || {}
|
console.log('datamaps', datamaps)
|
for (var itemkey of Object.keys(datamaps)) {
|
if (datamaps[itemkey].name === this.query_networkPort) {
|
//默认打开
|
// id itemcode@3_3_14 ud itemtext@3_3_14
|
var dom = document.getElementById('itemtext@' + key + '_' + (cell.cell) + '_' + itemkey)
|
|
// console.log('datamaps get',datamaps[itemkey],dom,datamaps,this.bridge_infos,)
|
if (dom) {
|
dom.click()
|
}
|
}
|
}
|
}
|
}
|
}
|
},
|
click_item(id) {
|
this.current_show_id = id;
|
},
|
click_item_add(locInfo) {
|
console.log("this.$refs.equAddForm", this.$refs.equAddForm);
|
this.$refs.equAddForm && this.$refs.equAddForm.openform(locInfo);
|
},
|
|
|
closeself() {
|
console.log("closeself parent");
|
this.chartclose = true;
|
},
|
|
// 鼠标按下事件
|
handleMouseDown(event) {
|
this.isDragging = true;
|
this.offsetX = event.clientX - this.position.left;
|
this.offsetY = event.clientY - this.position.top;
|
document.addEventListener('mousemove', this.handleMouseMove);
|
document.addEventListener('mouseup', this.handleMouseUp);
|
document.body.style.cursor = 'grabbing'; // 改变光标为抓取状态
|
},
|
// 鼠标移动事件
|
handleMouseMove(event) {
|
if (this.isDragging) {
|
this.position.left = event.clientX - this.offsetX;
|
this.position.top = event.clientY - this.offsetY;
|
}
|
},
|
// 鼠标松开事件
|
handleMouseUp() {
|
if (this.isDragging) {
|
this.isDragging = false;
|
document.removeEventListener('mousemove', this.handleMouseMove);
|
document.removeEventListener('mouseup', this.handleMouseUp);
|
document.body.style.cursor = 'grab'; // 改变光标为抓取状态
|
}
|
},
|
|
|
handleWheel(event) {
|
event.preventDefault();
|
const delta = event.deltaY < 0 ? 0.2 : -0.2;
|
this.container_offset_left =
|
this.container_offset_left /
|
(this.scale_container / (delta + this.scale_container));
|
this.container_offset_top =
|
this.container_offset_top /
|
(this.scale_container / (delta + this.scale_container));
|
|
this.scale_container += delta;
|
if (this.scale_container < 0.2) {
|
this.scale_container = 0.2;
|
}
|
if (this.scale_container <= 1) {
|
this.container_offset_left = 0;
|
this.container_offset_top = 0;
|
}
|
console.log("滚轮的缩放比")
|
|
console.log(this.scale_container)
|
},
|
dragstart(e, index) {
|
this.isDragging = false;
|
console.log(e);
|
this.dragSource = index; // 记录拖拽的源元素
|
console.log("start", e);
|
console.log("拖拽事件开始", index)
|
console.log(this.elements[index])
|
},
|
// 拖拽完成事件
|
async dragend(e, index) {
|
this.isDragging = false;
|
//确定是否需要更新
|
let that = this;
|
console.log("拖拽事件完成", index)
|
console.log("拖拽目标Id:", e.target.id)
|
},
|
|
/**两个元素交换位置 */
|
handleDrop(e, targetIndex) {
|
this.isDragging = false;
|
console.log("handleDrop")
|
console.log(targetIndex)
|
|
let that = this;
|
let sourceIndex = this.dragSource;
|
// 实现逻辑,例如交换两个元素的位置
|
if (sourceIndex !== targetIndex && (this.elements[sourceIndex].deviceInfo || this.elements[targetIndex].deviceInfo)) {
|
const sourceDeviceInfo = this.elements[sourceIndex].deviceInfo;
|
const targetDeviceInfo = this.elements[targetIndex].deviceInfo;
|
const sourceElement=this.elements[sourceIndex]
|
const targetElement=this.elements[targetIndex]
|
let sourceNetworkPort = "指定位置"
|
if (sourceDeviceInfo?.networkPort) {
|
sourceNetworkPort = sourceDeviceInfo?.networkPort
|
}
|
let targetNetworkPort = "指定位置"
|
if (targetDeviceInfo?.networkPort) {
|
targetNetworkPort = targetDeviceInfo?.networkPort
|
}
|
let type = false;
|
if (sourceDeviceInfo?.networkPort && targetDeviceInfo?.networkPort) {
|
type = true;
|
}
|
that.$modal
|
.confirm(
|
`是否确定${type ? "交换" : "移动"}位置:从${sourceNetworkPort
|
}到${targetNetworkPort}上`
|
)
|
.then(async (res) => {
|
|
// this.elements[sourceIndex].deviceInfo = targetDeviceInfo
|
// this.elements[targetIndex].deviceInfo = sourceDeviceInfo
|
|
if (this.elements[sourceIndex].deviceInfo == null) {
|
this.elements[sourceIndex].isPlaceholder = false;
|
}
|
|
if (this.elements[targetIndex].deviceInfo == null) {
|
this.elements[targetIndex].isPlaceholder = false;
|
}
|
|
that.$modal.loading();
|
let json;
|
console.log()
|
if (type) {
|
|
// 交换
|
json = {
|
id: sourceDeviceInfo.id,
|
operateType: 3,
|
operateTime: new Date(),
|
networkPort: sourceDeviceInfo.networkPort,
|
changeId:targetDeviceInfo?.id,
|
changeAreaRow: targetElement.row,
|
changeAreaCell: targetElement.cell,
|
deviceInfo: {
|
areaRow: sourceElement.row,
|
areaCell:sourceElement.cell,
|
areaCode:this.code
|
},
|
};
|
|
} else {
|
// 移动
|
|
const { id, networkPort } = sourceDeviceInfo ? sourceDeviceInfo : targetDeviceInfo;
|
const { row, cell } = sourceDeviceInfo ? targetElement : sourceElement;
|
|
json = {
|
id: id,
|
operateType: 1,
|
operateTime: new Date(),
|
networkPort: networkPort,
|
deviceInfo: {
|
areaRow: row,
|
areaCell: cell,
|
areaCode:this.code
|
},
|
};
|
|
}
|
|
const data = await updateDevicePosition(json);
|
that.$modal.closeLoading();
|
if (data) {
|
this.$message.success(`${type ? "交换" : "移动"}成功`);
|
}
|
|
// 根据屏幕初始化格子
|
this.initializeElements(); // 在组件加载时初始化 elements
|
// 初始化设备信息
|
this.handleBindElementsItems()
|
|
})
|
.catch((e) => {
|
console.log(e);
|
})
|
.finally(() => { });
|
|
}
|
|
},
|
|
handleDragOver(e) {
|
this.isDragging = false;
|
e.preventDefault();
|
},
|
|
|
// 点击增加
|
handleClickToAddItem(index,item){
|
|
this.cur_item=item
|
// 如果存在设备的话则直接返回
|
if(item?.deviceInfo?.id) return;
|
this.$refs.equAddForm && this.$refs.equAddForm.openform();
|
},
|
|
async init_data() {
|
this.$modal.loading();
|
var { data } = await getBridgeInfos(this.code);
|
this.$modal.closeLoading();
|
var arr = (data && data) || [];
|
var currentareaconfig = mapdata[this.code] || {};
|
|
this.bridge_infos = {};
|
|
// var name2ip = {}
|
// for(var item of this.device_list){
|
// name2ip[item.networkPort] = item.ip
|
// }
|
// console.log('name2ip',name2ip)
|
for (var item of arr) {
|
if (item.areaCellRow) {
|
for (var each of item.areaCellRow) {
|
each.datamap = {};
|
//需要遍历,然后设置进去
|
if (each.areaPosition) {
|
for (var cell of each.areaPosition) {
|
// var ip = name2ip[cell.networkPort] || ''
|
var tid = "";
|
var status = 0;
|
var cabinetName = "";
|
var switchName = "";
|
for (var itemvv of this.device_list) {
|
if (itemvv.networkPort == cell.networkPort) {
|
tid = itemvv.id;
|
cabinetName = itemvv.cabinetName || "";
|
status = itemvv.statusInt || 0;
|
switchName = itemvv.switchName || "";
|
break;
|
}
|
}
|
|
each.datamap["" + cell.networkPortRow] = {
|
name: cell.networkPort,
|
cabinetName: cabinetName,
|
id: tid,
|
status: status,
|
switchName: switchName,
|
};
|
}
|
}
|
|
each.width = each.dataRow || "";
|
// console.log('cell',cell)
|
}
|
}
|
|
this.bridge_infos[item.areaIndex] = {
|
left: 0,
|
top: 0,
|
bottom: 0,
|
right: 0,
|
...(mapdata["common"] || {}),
|
...(currentareaconfig[item.areaIndex] || ""),
|
cells: item.areaCellRow || [],
|
code: item.areaIndex,
|
};
|
// console.log("bridge_infos", this.bridge_infos);
|
// console.log(
|
// "currentareaconfig",
|
// currentareaconfig[item.areaIndex],
|
// currentareaconfig["pad"]
|
// );
|
if (currentareaconfig["pad"]) {
|
this.bridge_infos[item.areaIndex]["pad"] = currentareaconfig["pad"];
|
}
|
if (
|
currentareaconfig[item.areaIndex] &&
|
currentareaconfig[item.areaIndex]["pad"]
|
) {
|
this.bridge_infos[item.areaIndex]["pad"] =
|
currentareaconfig[item.areaIndex]["pad"];
|
}
|
|
}
|
},
|
|
startScrolling() {
|
this.stopScrolling();
|
const myDiv = document.getElementById("my_serve_info_list");
|
this.serve_timer = setInterval(() => {
|
if (myDiv) {
|
myDiv.scrollTo(0, this.serve_scroll_num);
|
this.serve_scroll_num++;
|
if (myDiv.scrollTop >= myDiv.scrollHeight - myDiv.clientHeight) {
|
this.serve_timer && clearInterval(this.serve_timer);
|
this.serve_timer = null;
|
setTimeout(() => {
|
this.serve_scroll_num = 0;
|
this.startScrolling();
|
}, 1500);
|
}
|
}
|
}, 20);
|
},
|
stopScrolling() {
|
this.serve_scroll_num = 0;
|
this.serve_timer && clearInterval(this.serve_timer);
|
},
|
async showServe(info) {
|
|
if (!this.hideServe) {
|
this.hideServe = !this.hideServe;
|
return;
|
}
|
this.$modal.loading();
|
this.serve_info = {};
|
this.serve_select = info;
|
console.log("serve_select", this.serve_select);
|
const { switchCabinet } = await getAreaServeInfo(this.code, info);
|
console.log("switchCabinet", switchCabinet);
|
if (switchCabinet && switchCabinet.length > 0) {
|
this.serve_info = switchCabinet[0];
|
}
|
|
this.hideServe = false;
|
|
this.$modal.closeLoading();
|
},
|
showDeviceInfo(index, item,event) {
|
this.isDragging = false;
|
event.stopPropagation(); // 阻止事件冒泡
|
if(item.deviceInfo){
|
// 如果点击的是同一个元素,则切换显示状态
|
if (this.selectedIndex === index) {
|
this.show_device_info = !this.show_device_info;
|
} else {
|
// 切换到新元素,自动关闭之前的
|
this.selectedIndex = index;
|
this.show_device_info = true;
|
this.cur_device_info = item.deviceInfo;
|
}
|
}
|
},
|
},
|
};
|
</script>
|
<style lang="scss" scoped>
|
@import "@/common/itm_svg.scss";
|
@import "@/common/area-bg.scss";
|
|
$width-screen1: 174.17rem;
|
|
.main-container {
|
/* position: fixed;
|
right: calc(5rem);
|
top: calc($height-header - 8rem);
|
left: calc((100% - $width-screen1 - 10rem - 18rem) / 2);
|
left: 0;
|
right: 0; */
|
/* background-color: rgba(209, 227, 247, 1); */
|
// overflow: hidden;
|
margin: 0 auto;
|
margin-bottom: 5rem;
|
|
.equipments-container {
|
background: #d3e3f3;
|
position: relative;
|
margin: 0 auto;
|
cursor: pointer;
|
max-width: 100%;
|
max-height: 100vh;
|
|
.equipment-item {
|
cursor: pointer;
|
position: absolute;
|
width: 5rem;
|
height: 5rem;
|
background-size: 100% 100%;
|
filter: drop-shadow(2px 2px 2px rgba(0, 0, 0, 0.2));
|
}
|
}
|
|
.chart-open {
|
width: 6.1rem;
|
height: 7.5rem;
|
background: #e9f4fd;
|
box-shadow: 0.6rem 0.4rem 2.4rem 0rem rgba(198, 212, 228, 0.83),
|
inset 0rem 0.2rem 0.3rem 0rem rgba(255, 255, 255, 0.5);
|
border-radius: 1rem;
|
position: fixed;
|
right: 3rem;
|
top: 50%;
|
transform: translate(0%, 50%);
|
cursor: pointer;
|
|
.img-button {
|
background-size: 100% 100%;
|
background-image: url("@/assets/area/chart-open.svg");
|
width: 2.6rem;
|
height: 2.6rem;
|
transform: translate(-50%, -50%);
|
left: 50%;
|
top: 50%;
|
position: absolute;
|
}
|
}
|
}
|
</style>
|
<style scoped lang="scss">
|
//7个设备
|
.equ-0 {
|
background-image: url("@/assets/equipment/arm.svg");
|
width: 9.6rem;
|
height: 9.6rem;
|
}
|
|
.equ-1 {
|
background-image: url("@/assets/equipment/pda.svg");
|
width: 4.1rem;
|
height: 6.1rem;
|
}
|
|
.equ-2 {
|
background-image: url("@/assets/equipment/pc.svg");
|
width: 15rem;
|
height: 12.6rem;
|
}
|
|
.equ-3 {
|
background-image: url("@/assets/equipment/print.svg");
|
width: 8.2rem;
|
height: 8.1rem;
|
}
|
|
.equ-4 {
|
background-image: url("@/assets/equipment/screen.svg");
|
width: 15.9rem;
|
height: 13.1rem;
|
}
|
|
.equ-5 {
|
background-image: url("@/assets/equipment/setting.svg");
|
width: 7.8rem;
|
height: 7.5rem;
|
}
|
|
.equ-6 {
|
background-image: url("@/assets/equipment/video.svg");
|
width: 12.7rem;
|
height: 9.4rem;
|
}
|
</style>
|
<style scoped lang="scss">
|
.back-button-left-bottom {
|
width: 10.6rem;
|
height: 3.9rem;
|
background: #6eb3ff;
|
border-radius: 0.4rem;
|
border: 0.2rem solid #278afa;
|
font-size: 1.6rem;
|
font-family: PingFangSC-Semibold, PingFang SC;
|
font-weight: 600;
|
color: #ffffff;
|
line-height: 3.9rem;
|
position: fixed;
|
left: 3rem;
|
bottom: 3.5rem;
|
cursor: pointer;
|
z-index: 99;
|
}
|
</style>
|
|
<!-- 交换机的端口 -->
|
<style scoped lang="scss">
|
.port-items {
|
display: flex;
|
margin-bottom: 8rem;
|
/* height: 2rem; */
|
width: fit-content;
|
|
.port-item {
|
background: #e9f4fd;
|
border-top: 5px solid #e9f4fd;
|
flex: 1;
|
margin: 0 auto;
|
min-width: 6rem;
|
max-width: 6rem;
|
/* max-width: 6rem; */
|
height: 1.6rem;
|
// background: #fff;
|
// box-shadow: 0rem -2rem 2.1rem 0rem #fff;
|
background-image: url("@/assets/area/space.svg");
|
background-size: 100% 100%;
|
position: relative;
|
|
.port-tip {
|
position: absolute;
|
bottom: -2.5rem;
|
height: 2.5rem;
|
font-size: 1.8rem;
|
font-family: PingFangSC-Semibold, PingFang SC;
|
font-weight: 600;
|
color: #265696;
|
line-height: 2.5rem;
|
text-align: center;
|
/* margin-bottom: 0.5rem; */
|
left: 0;
|
right: 0;
|
}
|
|
.space-text {
|
background-image: url("@/assets/area/space-text.svg");
|
// background-size: 100% 100%;
|
// min-width: 6rem;
|
// min-height: 2.5rem;
|
transform: translate(-50%, 0%);
|
left: 50%;
|
padding-top: 0.5rem;
|
top: -2.5rem;
|
position: absolute;
|
/* line-height: 100%; */
|
/* font-size: 12px; */
|
/* span { */
|
word-break: break-all;
|
word-wrap: break-word;
|
/*但在有些场景中,还需要加上下面这行代码*/
|
white-space: normal;
|
overflow-wrap: anywhere;
|
/* } */
|
|
font-size: 1rem;
|
font-family: PingFangSC-Semibold, PingFang SC;
|
font-weight: 600;
|
color: #3299ff;
|
z-index: 20;
|
}
|
|
.space-text-yellow {
|
color: #e8be19;
|
}
|
|
.space-text-red {
|
color: #e20909;
|
}
|
}
|
|
.port-item:nth-child(6n) {
|
margin-right: 3rem;
|
}
|
}
|
|
.port-items:nth-child(2n) {
|
margin-bottom: 8rem;
|
}
|
</style>
|
|
<style scoped>
|
.grid-item {
|
position: absolute;
|
box-sizing: border-box;
|
/* border: 1px solid #ccc; 可选样式,便于查看布局 */
|
border: 1px solid #ccc;
|
display: flex;
|
justify-content: center;
|
align-items: center;
|
border: none;
|
}
|
</style>
|
|
|
<style lang="scss" scoped>
|
.bridge-items {
|
//width: 102.8rem;
|
// height: 1.5rem;
|
// background: #a6c6e5;
|
// box-shadow: 0rem -2rem 2.1rem 0rem #89a2bd;
|
display: flex;
|
position: absolute;
|
/* flex-wrap: wrap; */
|
|
.bridge-item {
|
background: #A6C7E3;
|
flex: 1;
|
margin: 0 auto;
|
// min-width: 7.5rem;
|
/* max-width: 6rem; */
|
height: 1.3rem;
|
|
// background: #fff;
|
// box-shadow: 0rem -2rem 2.1rem 0rem #fff;
|
|
background-image: url("@/assets/area/space.svg");
|
background-size: 100% 100%;
|
position: relative;
|
|
|
.bridge-item-element {
|
margin: 1 auto;
|
background-image: url("@/assets/area/space.svg");
|
background-repeat: no-repeat;
|
/* 不重复显示图片 */
|
background-position: center;
|
/* 图片居中显示 */
|
background-size: contain;
|
/* 调整图片大小以适应容器 */
|
cursor: grabbing;
|
cursor: move;
|
}
|
|
.space-text {
|
background-image: url("@/assets/area/space-text.svg");
|
background-size: 100% 100%;
|
min-width: 7.5rem;
|
min-height: 2.5rem;
|
transform: translate(-50%, 0%);
|
left: 50%;
|
padding-top: 0.5rem;
|
top: -2.5rem;
|
position: absolute;
|
cursor: grabbing;
|
cursor: move;
|
/* line-height: 100%; */
|
/* font-size: 12px; */
|
/* span { */
|
word-break: break-all;
|
word-wrap: break-word;
|
/*但在有些场景中,还需要加上下面这行代码*/
|
white-space: normal;
|
overflow-wrap: anywhere;
|
/* } */
|
|
font-size: 1rem;
|
font-family: PingFangSC-Semibold, PingFang SC;
|
font-weight: 600;
|
color: #3299ff;
|
z-index: 20;
|
}
|
|
.space-text-yellow {
|
color: #e8be19;
|
}
|
|
.space-text-red {
|
color: #e20909;
|
}
|
}
|
|
|
.bridge-item-none {
|
transition: box-shadow 0.3s ease;
|
/* 平滑的阴影过渡效果 */
|
}
|
|
.hover-shadow:hover {
|
// box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3); /* 鼠标悬停时的阴影效果 */
|
box-shadow: 0 6px 15px rgba(0, 0, 0, 0.5);
|
/* 加深的阴影效果 */
|
// box-shadow: 0 6px 15px rgba(162, 194, 221, 0.5); /* 加深的阴影效果 */
|
|
}
|
|
.space-drag {
|
filter: unset !important;
|
background-color: rgb(243, 15, 15);
|
|
.space-text-gray {
|
z-index: -1;
|
}
|
}
|
|
.space-drag-start {
|
background-color: rgb(243, 15, 15);
|
}
|
}
|
|
.space-text-gray {
|
.space-text {
|
color: #818181 !important;
|
background-image: url("@/assets/area/space-text-gray.svg") !important;
|
}
|
}
|
</style>
|