1759 lines
47 KiB
Vue
Raw Normal View History

2024-10-18 17:31:35 +08:00
<!--
* @Author: SunTao 328867980@qq.com
* @Date: 2024-10-17 11:34:00
* @LastEditors: SunTao 328867980@qq.com
* @LastEditTime: 2024-11-21 09:12:52
2024-10-18 17:31:35 +08:00
* @FilePath: \znxjxt-ui\src\views\big-screen\index.vue
* @Description: 大屏首页
-->
<template>
<div class="screen-content">
<div class="screen-header">
2024-10-22 09:55:33 +08:00
<div class="header-weather">
<iframe
width="150"
scrolling="no"
height="45"
frameborder="0"
allowtransparency="true"
src="https://i.tianqi.com?c=code&id=12&icon=1&color=%2389C5E8&py=shenyang&num=1&site=12"
></iframe>
</div>
2024-10-18 17:31:35 +08:00
<div class="header-time">
2024-11-20 14:46:20 +08:00
<!-- 消息中心 -->
<div class="header-news">
<el-popover
placement="bottom-end"
width="400"
popper-class="screen-message-popover"
trigger="click"
>
<div class="screen-message-content">
<div class="message-content">
<fssm-scroll>
<div
class="message-item"
v-for="(item, index) in messageList"
:key="`message-item-${index}`"
>
<div
class="item-top"
@click="handleMessageItemClick(item.status)"
>
2024-11-20 14:46:20 +08:00
<div class="index">
<i
v-if="item.status === '1'"
style="color: #67c23a"
class="el-icon-success"
></i>
<i
v-if="item.status === '2'"
style="color: #e6a23c"
class="el-icon-info"
></i>
<i
v-if="item.status === '3'"
style="color: #909399"
class="el-icon-warning"
></i>
<i
v-if="item.status === '4'"
style="color: #f56c6c"
class="el-icon-error"
></i>
</div>
<div class="time">
<span>{{ item.time }}</span>
</div>
<div class="carNo">
<span>{{ item.car }}</span>
</div>
</div>
<div class="item-content">
{{ item.content }}
</div>
</div>
</fssm-scroll>
</div>
<div class="message-footer">
<el-button
@click="handleMessageClick"
icon="el-icon-d-arrow-right"
type="text"
>查看更多</el-button
>
</div>
</div>
<i slot="reference" class="el-icon-message-solid">
<div class="num">48</div>
</i>
</el-popover>
</div>
2024-10-18 17:31:35 +08:00
<div class="header-data">{{ dataTime }}</div>
<div class="header-week">
<span>{{ weekTime }}</span>
<span>{{ yearTime }}</span>
</div>
<div class="header-home">
2024-10-22 09:55:33 +08:00
<div class="home" @click="goIndex"></div>
2024-10-18 17:31:35 +08:00
</div>
</div>
</div>
<div class="screen-middle">
<div class="screen-left">
<module-block
v-for="(item, index) in leftModuleList"
:key="`left-module-list-${index}`"
:width="item.width"
:height="item.height"
:title="item.title"
:class="item.class"
>
2024-10-22 09:55:33 +08:00
<template
><component
:select="item.select"
:is="item.component"
:bottomTipClick="bottomTipClick"
></component
2024-10-22 09:55:33 +08:00
></template>
<template slot="operation" v-if="item.selectIsShow">
<el-radio-group class="screen-checkBox" v-model="item.select">
2024-10-25 17:29:08 +08:00
<el-radio-button
v-for="(item, index) in selectTypeArr"
:label="item.value"
:key="`left-screen-${index}`"
>{{ item.label }}</el-radio-button
>
2024-10-22 09:55:33 +08:00
</el-radio-group>
</template>
2024-10-18 17:31:35 +08:00
</module-block>
</div>
<div class="screen-right">
<module-block
v-for="(item, index) in rightModuleList"
:key="`right-module-list-${index}`"
:width="item.width"
:height="item.height"
:title="item.title"
:class="item.class"
>
2024-10-25 17:29:08 +08:00
<template
><component
:select="item.select"
:is="item.component"
:bottomTipClick="bottomTipClick"
@imagePoint="getimagePoint"
></component
2024-10-25 17:29:08 +08:00
></template>
2024-10-22 09:55:33 +08:00
<template slot="operation" v-if="item.selectIsShow">
<el-radio-group class="screen-checkBox" v-model="item.select">
2024-10-25 17:29:08 +08:00
<el-radio-button
v-for="(item, index) in selectTypeArr"
:label="item.value"
:key="`right-screen-${index}`"
>{{ item.label }}</el-radio-button
>
2024-10-22 09:55:33 +08:00
</el-radio-group>
</template>
2024-10-18 17:31:35 +08:00
</module-block>
</div>
<div class="road-content">
<!-- 地图右上角多选框切换坐标类型 -->
<div class="road-checkBox" v-if="showIconList">
<fssm-scroll class="road-scroll">
<el-checkbox-group v-model="iconType" @change="handleChecked">
<el-checkbox
v-for="(item, index) in iconTypeList"
:label="item.value"
:key="`check-${index}`"
2024-11-01 13:15:24 +08:00
>{{ item.label }}</el-checkbox
>
</el-checkbox-group>
</fssm-scroll>
</div>
<!-- 地图图例 -->
<div class="map-legend"></div>
<!-- 图片背景 -->
<div class="disease-content" v-if="elementDiv === 'OverviewScreen'">
2024-10-28 10:00:28 +08:00
<div class="disease-title"></div>
<!-- 图背景下选择框 -->
<div class="map-image-select">
病害类型筛选
2024-11-15 11:03:30 +08:00
<el-cascader
v-model="mapCareSelect"
popper-class="screen-index-cascader"
:options="dieaseOptions"
:props="{
checkStrictly: true,
emitPath: true,
children: 'subTypes',
}"
2024-11-15 11:03:30 +08:00
@change="getMapCare"
clearable
></el-cascader>
</div>
2024-10-25 17:29:08 +08:00
<div class="map-care">
2024-10-28 10:00:28 +08:00
<div
class="map-care-div"
:class="`map-care-div-${item.status}`"
2024-10-28 10:00:28 +08:00
v-for="(item, index) in mapCareList"
:key="`map-care-${index}`"
:style="{ left: item.left, top: item.top }"
>
<span>{{ item.name }}</span>
2024-10-28 10:00:28 +08:00
</div>
2024-10-25 17:29:08 +08:00
</div>
</div>
<!-- 地图 -->
<fssm-map
v-if="elementDiv !== 'OverviewScreen'"
ref="roadMap"
:showChange="true"
:controlStyle="{ top: '10%', left: '26%' }"
@feature-select="featureSelect"
@map-zoom="getZoom"
></fssm-map>
<!-- @map-moveend="mapMoveend" -->
</div>
2024-10-18 17:31:35 +08:00
</div>
<div class="screen-footer">
<!-- 病害巡检4种类型按钮 -->
2024-10-18 17:31:35 +08:00
<div class="footer-change-map">
<template v-if="elementDiv === 'DiseaseScreen'">
2024-10-22 09:55:33 +08:00
<div
class="change-map-div"
:class="bottomTipClick === item.click ? 'change-map-click' : ''"
2024-10-22 09:55:33 +08:00
v-for="(item, index) in changeMapBtn"
:key="`btn-${index}`"
@click="changeIconType(item.click)"
2024-10-22 09:55:33 +08:00
>
{{ item.name }}
</div>
</template>
2024-10-18 17:31:35 +08:00
</div>
<!-- 切换3种导航栏按钮 -->
2024-10-18 17:31:35 +08:00
<div class="footer-change-vue">
<div
:class="
elementDiv === item.component
? `change-vue-click-${item.component}`
: `change-vue-${item.component}`
"
v-for="(item, index) in elementList"
:key="`footer-${index}`"
@click="changeElement(item)"
></div>
</div>
</div>
<!-- 详情图片弹窗 -->
<el-dialog
:title="imgTitle"
:visible.sync="imgVisible"
width="95rem"
append-to-body
fullscreen
:close-on-click-modal="false"
destroy-on-close
@close="imgCancel"
>
<img-dialog
v-if="imgTitle === '查看'"
:imageItem="imageItem"
:bottomTipClick="bottomTipClick"
></img-dialog>
</el-dialog>
<!-- 查看点位图片弹窗 -->
<el-dialog
title="查看点位"
:visible.sync="showImageDialog"
width="90rem"
append-to-body
:close-on-click-modal="false"
destroy-on-close
@close="screenImgCancel"
>
<div class="view-image-container" ref="imageContainer">
<img
:src="screenImage.imageUrl"
alt="Main Image"
ref="mainImage"
@load="updateScreenRects"
/>
<div
v-for="(rect, index) in screenRects"
:key="index"
class="rect-overlay"
:style="getScreenRectStyle(rect)"
></div>
<div class="rect-image">
采集时间:
{{ screenImage.createTime }} 起始桩号
{{ screenImage.stakeStart || "暂无数据" }} 终止桩号
{{ screenImage.stakeEnd || "暂无数据" }}
{{ `${this.elementDiv === "RoadScreen" ? "路产" : "病害"}类型:` }}
{{ screenImage.iconTypeName || "暂无数据" }}
<span v-if="this.elementDiv === 'DiseaseScreen'">
病害面积{{ screenImage.targetArea }}平方米 病害长度{{
screenImage.targetLen
}}
</span>
</div>
</div>
</el-dialog>
2024-10-18 17:31:35 +08:00
</div>
</template>
<script>
// websocket
import {
connectWebsocket,
closeWebsocket,
sendMsg,
} from "@/plugins/websocket.js";
// 登陆人信息
import { getToken } from "@/utils/auth.js";
// 地图
import FssmMap from "@/components/map/fssm-map.vue";
import { Feature } from "ol";
import { Point } from "ol/geom";
import { Style, Icon, Fill, Stroke, Circle, Text } from "ol/style";
import VectorSource from "ol/source/Vector";
import VectorLayer from "ol/layer/Vector";
import * as geomExports from "ol/geom";
import Cluster from "ol/source/Cluster";
// 组件
2024-10-18 17:31:35 +08:00
import ModuleBlock from "./module-block.vue";
import TodayInspection from "./overview-components/today-inspection.vue";
import DiseaseTrends from "./overview-components/disease-trends.vue";
import DiseaseCurrent from "./overview-components/disease-current.vue";
import PatrolOrder from "./overview-components/patrol-order.vue";
import InspectionVehicles from "./overview-components/inspection-vehicles.vue";
2024-10-18 17:31:35 +08:00
import RoadStatistic from "./road-components/road-statistic.vue";
import ManageMaintain from "./road-components/manage-maintain.vue";
import AnomalyFacilities from "./road-components/anomaly-facilities";
import AncillaryFacilities from "./road-components/ancillary-facilities.vue";
import TrafficSafety from "./disease-components/traffic-safety.vue";
import TrafficTrend from "./disease-components/traffic-trend.vue";
import TrafficStatistic from "./disease-components/traffic-statistic.vue";
import TrafficLog from "./disease-components/traffic-log.vue";
import ImgDialog from "./components/img-dialog.vue";
import FssmScroll from "@/components/scroll/fssm-scroll.vue";
2024-10-25 17:29:08 +08:00
// 接口
import {
selectTypeList,
mapPointList,
mapPciList,
comppanyImg,
2024-11-01 13:15:24 +08:00
getItemTypes,
getRoadListTypes,
getDefectTypes,
} from "@/api/xj/screen/index";
2024-10-18 17:31:35 +08:00
export default {
name: "BigScreen",
components: {
FssmMap,
2024-10-18 17:31:35 +08:00
ModuleBlock,
TodayInspection,
DiseaseTrends,
DiseaseCurrent,
PatrolOrder,
InspectionVehicles,
2024-10-18 17:31:35 +08:00
RoadStatistic,
ManageMaintain,
AnomalyFacilities,
AncillaryFacilities,
2024-10-22 09:55:33 +08:00
TrafficSafety,
TrafficTrend,
TrafficStatistic,
ImgDialog,
FssmScroll,
TrafficLog,
2024-10-18 17:31:35 +08:00
},
data() {
return {
// 计时器标识
timeFlag: null,
// 时间
dataTime: "",
// 星期
weekTime: "",
// 年
yearTime: "",
2024-11-20 14:46:20 +08:00
// 预警中心消息数据
messageList: [],
2024-10-25 17:29:08 +08:00
// 数据栏右上角选择框
selectTypeArr: [],
2024-10-18 17:31:35 +08:00
// 左侧切换模块
leftModuleList: [
{
width: "100%",
height: "27%",
2024-10-22 09:55:33 +08:00
title: "今日巡查",
component: TodayInspection,
2024-10-18 17:31:35 +08:00
selectIsShow: false,
class: "one",
},
{
width: "100%",
height: "27%",
2024-11-26 16:26:39 +08:00
title: "主要病害趋势",
2024-10-22 09:55:33 +08:00
component: DiseaseTrends,
2024-10-18 17:31:35 +08:00
selectIsShow: false,
class: "twe",
},
2024-10-22 09:55:33 +08:00
{
width: "100%",
height: "29%",
2024-11-13 15:37:25 +08:00
title: "病害统计",
2024-10-22 09:55:33 +08:00
component: DiseaseCurrent,
selectIsShow: true,
2024-10-25 17:29:08 +08:00
select: "",
2024-10-22 09:55:33 +08:00
class: "twe",
},
2024-10-18 17:31:35 +08:00
],
// 右侧切换模块
rightModuleList: [
{
width: "100%",
2024-11-13 15:37:25 +08:00
height: "18%",
title: "巡查里程",
component: PatrolOrder,
2024-10-18 17:31:35 +08:00
selectIsShow: false,
class: "one",
},
{
width: "100%",
2024-11-13 15:37:25 +08:00
height: "65%",
title: "巡检车辆",
component: InspectionVehicles,
2024-10-18 17:31:35 +08:00
selectIsShow: false,
class: "twe",
},
],
2024-10-28 10:00:28 +08:00
// 图片背景下打点坐标数据
mapCareList: [],
// 具体icon类别
iconTypeList: [],
// icon类别绑定
iconType: [],
// 地图右上角多选显隐控制
showIconList: false,
// 图片背景下病害类型下拉选择绑定
mapCareSelect: "",
// 图片背景下病害类型下拉选择数据
2024-11-20 14:46:20 +08:00
dieaseOptions: [],
// 路段下拉绑定
roadList: [],
// 地图打点-路段绑定
roadSelect: "",
// 图标类别切换标识
bottomTipClick: "1",
// 切换地图图标类别按钮
changeMapBtn: [
{ name: "路面", click: "1" },
{ name: "交安", click: "2" },
{ name: "桥隧", click: "3" },
{ name: "绿化", click: "4" },
],
2024-10-18 17:31:35 +08:00
// 中间展示的动态组件绑定
elementDiv: "OverviewScreen",
// 下方三个按钮数据
2024-10-18 17:31:35 +08:00
elementList: [
{ name: "总览", component: "OverviewScreen" },
{ name: "病害巡检", component: "DiseaseScreen" },
2024-11-13 15:37:25 +08:00
{ name: "道路资产", component: "RoadScreen" },
2024-10-18 17:31:35 +08:00
],
2024-11-01 13:15:24 +08:00
// 中心点集合(全部)
centerPiont: [],
2024-11-01 13:15:24 +08:00
// 中心点集合(当前)
drawPointList: [],
// 点位图标map
mapLogeList: {},
// 线段点集合
lineString: [],
// 地图放大缩小层级
mapZoom: "",
// 聚合图层
clusters: null,
// 线段图层
markLayerLines: null,
// 图片弹窗标题
imgTitle: "查看",
// 图片弹窗显隐控制
2024-11-13 15:37:25 +08:00
imgVisible: false,
// 传图片弹窗数据
imageItem: {},
// 查看大图点位图片数据
screenImage: {},
// 查看大图点位图片弹窗显隐控制
showImageDialog: false,
// 查看大图点位图片弹窗红框数据
screenRects: [],
2024-10-18 17:31:35 +08:00
};
},
created() {
this.setTime();
2024-10-25 17:29:08 +08:00
this.getSelect();
2024-10-28 10:00:28 +08:00
this.getMapCare();
this.getRoadList();
this.getDieaseTypeList();
2024-11-20 14:46:20 +08:00
this.getMessageList();
// this.initWebSocket();
2024-10-18 17:31:35 +08:00
},
methods: {
/* 获取当前时间 */
setTime() {
this.timeFlag = setInterval(() => {
const weekMap = [
"星期天",
"星期一",
"星期二",
"星期三",
"星期四",
"星期五",
"星期六",
];
const date = new Date();
const year = date.getFullYear();
const month =
date.getMonth() + 1 < 10
? `0${date.getMonth() + 1}`
: date.getMonth() + 1;
const day = date.getDate() < 10 ? `0${date.getDate()}` : date.getDate();
const hours =
date.getHours() < 10 ? `0${date.getHours()}` : date.getHours();
const minutes =
date.getMinutes() < 10 ? `0${date.getMinutes()}` : date.getMinutes();
const seconds =
date.getSeconds() < 10 ? `0${date.getSeconds()}` : date.getSeconds();
const week = date.getDay();
// this.currentTime = `${year}-${month}-${day}\t\t${hours}:${minutes}:${seconds}\t\t${weekMap[week]}`;
this.yearTime = `${year}.${month}.${day}`;
this.weekTime = `${weekMap[week]}`;
this.dataTime = `${hours}:${minutes}:${seconds}`;
}, 1000);
},
2024-11-20 14:46:20 +08:00
/* 获取消息中心数据 */
getMessageList() {
// getMessageList().then(({ code, data }) => {
// if (code === 200) {
// this.messageList = data;
// }
// });
this.messageList = [
{
status: "1",
time: "2024/45/62",
car: "辽jskdn",
content: "骄傲的是否哈德half绝对符合卡的法拉第",
},
{
status: "2",
time: "2024/45/62",
car: "辽jskdn",
content: "骄傲的是否哈德half绝对符合卡的法拉第",
},
{
status: "3",
time: "2024/45/62",
car: "辽jskdn",
content: "骄傲的是否哈德half绝对符合卡的法拉第",
},
];
},
/**
* @description: 消息中心点击具体数据事件
* @return {*}
*/
handleMessageItemClick(value) {
this.$router.push({
name: "Warning-center",
params: { status: value },
});
},
/**
* @description: 消息中心查看更多事件
* @return {*}
*/
handleMessageClick() {
this.$router.push("/inspection_warn/warning-center");
},
2024-10-25 17:29:08 +08:00
/* 获取数据栏右上角选项数据 */
getSelect() {
selectTypeList().then(({ code, data }) => {
if (code === 200) {
this.selectTypeArr = data;
}
});
},
/* 获取路段下拉数据 */
getRoadList() {
getRoadListTypes().then(({ code, data }) => {
if (code === 200) {
this.roadList = data;
}
});
},
/* 获取图片背景左上角病害类型下拉 */
getDieaseTypeList() {
getDefectTypes().then(({ code, data }) => {
2024-11-13 15:37:25 +08:00
if (code === 200) {
this.dieaseOptions = data;
2024-11-13 15:37:25 +08:00
}
});
},
2024-10-28 10:00:28 +08:00
/* 获取图片背景下坐标数据 */
2024-11-15 11:03:30 +08:00
getMapCare(value) {
const data = {
classType: value ? value[0] : "",
type: value ? (value.length > 1 ? value[1] : "") : "",
};
comppanyImg(data).then(({ code, data }) => {
if (code === 200) {
this.mapCareList = data;
}
});
2024-10-28 10:00:28 +08:00
},
/* 点击病害日志详情打开弹窗进行地图打点 */
getimagePoint(item) {
this.imgTitle = "查看";
this.imageItem = item;
this.imgVisible = true;
// 地图右上角多选按钮显示
this.getIconType();
this.showIconList = true;
// 地图打点\改变地图层级
this.$nextTick(() => {
const map = this.$refs.roadMap.instance.get("map");
map.getView().setCenter(item.tablePoint);
map.getView().setZoom(16);
});
this.roadSelect = item.segmentId;
this.getCenterPiont();
},
/* 关闭图片查看弹窗 */
imgCancel() {
this.imgTitle = "";
this.imageItem = {};
this.imgVisible = false;
},
/* 关闭查看点位大图弹窗 */
screenImgCancel() {
this.$refs.roadMap.removeSelectClick();
this.showImageDialog = false;
},
/* 切换icon类型多选框事件 */
handleChecked(value) {
2024-11-01 13:15:24 +08:00
this.centerPiont = this.drawPointList.filter(
(item) => value.indexOf(item.iconType) > -1
);
this.$nextTick(() => {
const map = this.$refs.roadMap.instance.get("map");
map.removeLayer(this.clusters);
this.clusters = null;
this.drawPoint();
});
},
/* 获取地图点位信息 */
getCenterPiont() {
// 如果当前已经有打点坐标
if (this.clusters) {
this.$nextTick(() => {
const map = this.$refs.roadMap.instance.get("map");
map.removeLayer(this.clusters);
this.clusters = null;
});
}
mapPointList({
type: this.elementDiv,
classType: this.bottomTipClick,
segmentId: this.roadSelect,
}).then(({ code, data }) => {
if (code === 200) {
this.drawPointList = data.map((item) => {
if (item.geometry) {
return {
...item,
geometry: [item.geometry[0], item.geometry[1]],
};
}
return [];
});
this.centerPiont = data.map((item) => {
if (item.geometry) {
return {
...item,
geometry: [item.geometry[0], item.geometry[1]],
};
}
return [];
});
// 如果不是病害巡检,则绘制点位
// 如果图片弹窗打开,则绘制点位
if (this.elementDiv !== "DiseaseScreen" || this.imgVisible) {
this.drawPoint();
}
}
});
},
/* 绘制地图点位 */
drawPoint() {
const features = [];
this.centerPiont.forEach((element) => {
// 修改坐标样式
2024-11-01 13:15:24 +08:00
const point = new Point(element.geometry);
const feature = new Feature({
geometry: point,
data: element,
// 自己设置一个标识
type: "icon",
});
// 可以给点位设置样式
// feature.setStyle([
// new Style({
// image: new Icon({
// crossOrigin: "anonymous",
// src: logo,
// // 图标缩放比例
// scale: 0.05,
// }),
// }),
// ]);
features.push(feature);
});
const clusterSource = new Cluster({
distance: this.mapZoom > 15 ? 0 : 100,
minDistance: this.mapZoom > 15 ? 0 : 100,
source: new VectorSource({
features,
}),
type: "Cluster",
});
this.clusters = new VectorLayer({
source: clusterSource,
name: "clusterLayer",
zIndex: 10,
2024-11-01 13:15:24 +08:00
style: (feature) => {
const count = feature.get("features").length;
2024-11-01 13:15:24 +08:00
if (count > 1) {
return new Style({
image: new Icon({
crossOrigin: "anonymous",
src: require(`@/assets/screen/index/龟裂.png`),
// 图标缩放比例
scale: 0.6,
displacement: [0, 30],
// 0.3为30度
// rotation: 0.3,
}),
2024-11-01 13:15:24 +08:00
text: new Text({
textAlign: "center", //位置
textBaseline: "middle",
font: "normal 14px 微软雅黑",
offsetY: -50,
fill: new Fill({
color: "#ffffff",
}),
text: count.toString(),
}),
});
} else {
return new Style({
image: new Icon({
crossOrigin: "anonymous",
src: require(`@/assets/screen/index/${
this.mapLogeList[
feature.getProperties().features[0].get("data").iconType
]
}.png`),
// 图标缩放比例
scale: 0.6,
displacement: [0, 30],
// 0.3为30度
// rotation: 0.3,
}),
text: new Text({
textAlign: "center", //位置
textBaseline: "middle",
font: "normal 14px 微软雅黑",
offsetY: -50,
fill: new Fill({
color: "#ffffff",
}),
text: "",
}),
});
}
},
});
this.$nextTick(() => {
const map = this.$refs.roadMap.instance.get("map");
map.addLayer(this.clusters);
});
},
/* 获取地图线段点位信息 */
getLinePoint() {
if (!this.markLayerLines) {
mapPciList().then(({ code, data }) => {
if (code === 200) {
this.lineString = data.filter((item) => item.coordinates !== null);
this.drawLine();
}
});
}
},
/* 绘制地图线段 */
drawLine() {
const features = [];
this.lineString.forEach((element) => {
const lines = element?.coordinates?.split(";")?.map((it) => {
return it.split(",").map(Number);
});
const line = new Feature({
geometry: new geomExports.LineString(lines),
type: "line",
});
line.setStyle([
new Style({
// 填充色
fill: new Fill({
color: "red",
}),
// 边线颜色
stroke: new Stroke({
2024-11-15 18:08:37 +08:00
color: this.getLineColor(element.pci),
width: 5,
}),
// 形状
image: new Circle({
radius: 17,
fill: new Fill({
color: "#ffffff",
}),
}),
}),
]);
features.push(line);
});
const lineSource = new VectorSource({
features,
});
this.markLayerLines = new VectorLayer({
source: lineSource,
properties: {
type: "line",
},
});
this.$nextTick(() => {
const map = this.$refs.roadMap.instance.get("map");
map.addLayer(this.markLayerLines);
});
},
2024-11-15 18:08:37 +08:00
/* 地图线段颜色区分 */
getLineColor(value) {
if (value > 92) {
return "#0ABE67";
} else if (92 >= value > 80) {
return "#03BDE7";
} else if (80 >= value > 70) {
return "#E7CA03";
} else if (70 >= value > 60) {
return "#D47F07";
} else {
return "#E64548";
}
},
/* 地图下方4图标类别切换点击事件 */
changeIconType(value) {
if (this.bottomTipClick !== value) {
this.bottomTipClick = value;
this.$nextTick(() => {
const map = this.$refs.roadMap.instance.get("map");
map.removeLayer(this.clusters);
this.clusters = null;
// map.getView().setZoom(10);
// map.getView().setCenter([123.30297096718999, 41.87942945541742]);
});
// 地图右上角多选按钮隐藏
this.showIconList = false;
// this.getIconType();
// this.getCenterPiont();
}
},
/* 获取icon多选数据 */
getIconType() {
2024-11-01 13:15:24 +08:00
this.mapLogeList = {};
getItemTypes({
classType: this.bottomTipClick,
type: this.elementDiv,
}).then(({ code, data }) => {
2024-11-01 13:15:24 +08:00
if (code === 200) {
this.iconTypeList = data;
this.iconType = data.map((item) => {
return item.value;
});
data.forEach((item) => {
this.mapLogeList[item.value] = item.label;
});
}
});
},
/* 传回来的地图图层 */
getZoom(zoom) {
this.mapZoom = zoom;
if (this.clusters && zoom * 1 > 15) {
this.clusters.getSource().setDistance(0);
} else if (this.clusters && zoom * 1 <= 15) {
this.clusters.getSource().setDistance(100);
}
},
/* 地图选中feature事件 */
featureSelect(e) {
const map = this.$refs.roadMap.instance.get("map");
const selectedFeatures = e.selected;
if (selectedFeatures.length > 0) {
let feature = selectedFeatures[0];
let features = feature.get("features");
// 点击线段事件
if (feature.getProperties().type === "line") {
console.log(feature, "线段参数");
} else {
if (features.length === 1) {
// 单个点位
// 执行之前的业务逻辑
// 获取点击的图层信息
const selectFeature = feature.getProperties().features[0];
console.log(selectFeature, "点位");
// 获取点位数据
this.screenImage = selectFeature.get("data");
this.showImageDialog = true;
console.log(selectFeature.get("data"));
} else {
// 聚合点
// 放大地图层级
map.getView().animate({
center: feature.getGeometry().getCoordinates(),
zoom: map.getView().getZoom() + 1,
});
}
}
2024-10-18 17:31:35 +08:00
}
},
2024-10-18 17:31:35 +08:00
/* 数据栏切换事件 */
changeElement(item) {
if (this.elementDiv !== item) {
this.elementDiv = item.component;
this.roadSelect = "";
if (item.component === "OverviewScreen") {
/* 清空线段图层 */
this.markLayerLines = null;
2024-10-18 17:31:35 +08:00
this.leftModuleList = [
{
width: "100%",
height: "27%",
2024-10-18 17:31:35 +08:00
title: "今日巡查",
component: TodayInspection,
selectIsShow: false,
class: "one",
},
{
width: "100%",
height: "27%",
2024-10-18 17:31:35 +08:00
title: "病害趋势",
component: DiseaseTrends,
selectIsShow: false,
class: "twe",
},
{
width: "100%",
height: "29%",
2024-11-13 15:37:25 +08:00
title: "病害统计",
2024-10-18 17:31:35 +08:00
component: DiseaseCurrent,
2024-10-22 09:55:33 +08:00
selectIsShow: true,
2024-10-25 17:29:08 +08:00
select: "",
2024-10-18 17:31:35 +08:00
class: "twe",
},
];
this.rightModuleList = [
{
width: "100%",
2024-11-13 15:37:25 +08:00
height: "18%",
title: "巡查里程",
component: PatrolOrder,
2024-10-18 17:31:35 +08:00
selectIsShow: false,
class: "one",
},
{
width: "100%",
2024-11-13 15:37:25 +08:00
height: "65%",
title: "巡检车辆",
component: InspectionVehicles,
2024-10-18 17:31:35 +08:00
selectIsShow: false,
class: "twe",
},
];
// 地图右上角多选按钮隐藏
this.showIconList = false;
// 图层恢复
2024-11-15 11:03:30 +08:00
this.mapZoom = "";
2024-10-18 17:31:35 +08:00
} else if (item.component === "RoadScreen") {
this.leftModuleList = [
{
width: "100%",
height: "17%",
2024-10-18 17:31:35 +08:00
title: "管养道路统计",
component: ManageMaintain,
selectIsShow: false,
class: "one",
},
{
width: "100%",
height: "55%",
2024-10-18 17:31:35 +08:00
title: "附属设施分布",
component: AncillaryFacilities,
selectIsShow: false,
class: "twe",
},
];
this.rightModuleList = [
{
width: "100%",
height: "29%",
2024-10-18 17:31:35 +08:00
title: "附属设施异常统计",
component: AnomalyFacilities,
2024-10-22 09:55:33 +08:00
selectIsShow: true,
2024-10-25 17:29:08 +08:00
select: "",
2024-10-18 17:31:35 +08:00
class: "one",
},
{
width: "100%",
height: "57%",
2024-10-18 17:31:35 +08:00
title: "路产统计",
component: RoadStatistic,
2024-10-22 09:55:33 +08:00
selectIsShow: true,
2024-10-25 17:29:08 +08:00
select: "",
2024-10-22 09:55:33 +08:00
class: "twe",
},
];
this.$nextTick(() => {
const map = this.$refs.roadMap.instance.get("map");
map.getView().setZoom(10);
map.getView().setCenter([123.30297096718999, 41.87942945541742]);
});
// 地图右上角多选按钮显示
this.getIconType();
this.showIconList = true;
// 进行地图打点
this.getCenterPiont();
this.getLinePoint();
} else if (item.component === "DiseaseScreen") {
2024-10-22 09:55:33 +08:00
this.leftModuleList = [
{
width: "100%",
height: "27%",
2024-11-13 15:37:25 +08:00
title: "今日巡查",
2024-10-22 09:55:33 +08:00
component: TrafficSafety,
selectIsShow: false,
class: "one",
},
{
width: "100%",
height: "27%",
2024-11-26 16:26:39 +08:00
title: "主要病害趋势",
2024-10-22 09:55:33 +08:00
component: TrafficTrend,
2024-10-25 17:29:08 +08:00
selectIsShow: true,
2024-10-22 09:55:33 +08:00
class: "twe",
},
{
width: "100%",
height: "33%",
2024-11-13 15:37:25 +08:00
title: "病害统计",
2024-10-22 09:55:33 +08:00
component: TrafficStatistic,
selectIsShow: true,
2024-10-25 17:29:08 +08:00
select: "",
2024-10-22 09:55:33 +08:00
class: "twe",
},
];
this.rightModuleList = [
{
width: "100%",
height: "85%",
2024-11-13 15:37:25 +08:00
title: "病害日志",
component: TrafficLog,
2024-11-13 15:37:25 +08:00
selectIsShow: false,
2024-10-25 17:29:08 +08:00
select: "",
2024-10-22 09:55:33 +08:00
class: "one",
},
2024-10-18 17:31:35 +08:00
];
// 地图右上角多选按钮隐藏
this.showIconList = false;
// 图层恢复
this.mapZoom = "";
this.$nextTick(() => {
const map = this.$refs.roadMap.instance.get("map");
map.removeLayer(this.clusters);
this.clusters = null;
map.getView().setZoom(10);
map.getView().setCenter([123.30297096718999, 41.87942945541742]);
});
// 地图右上角多选按钮显示
// this.getIconType();
// this.showIconList = true;
// 进行地图打点
// this.getCenterPiont();
this.getLinePoint();
2024-10-18 17:31:35 +08:00
}
}
},
2024-10-18 17:31:35 +08:00
/* 跳转系统首页 */
goIndex() {
this.$router.push("/index");
},
/* 图片位置信息获取 */
updateScreenRects() {
1;
this.screenRects = [];
const image = this.$refs.mainImage;
const rects = this.screenImage?.rect?.split(",").map(Number) || [];
this.screenRects = [
{
left: rects[0],
top: rects[1],
width: rects[2],
height: rects[3],
},
];
},
/* 图片红框位置 */
getScreenRectStyle({ left, top, width, height }) {
const image = this.$refs.mainImage;
const container = this.$refs.imageContainer;
if (!image || !container) return {};
const scaleX = container.clientWidth / image.naturalWidth;
const scaleY = container.clientHeight / image.naturalHeight;
const scale = Math.min(scaleX, scaleY);
const renderedWidth = image.naturalWidth * scale;
const renderedHeight = image.naturalHeight * scale;
const offsetX = (container.clientWidth - renderedWidth) / 2;
const offsetY = (container.clientHeight - renderedHeight) / 2;
return {
position: "absolute",
left: `${left * scale + offsetX}px`,
top: `${top * scale + offsetY}px`,
width: `${width * scale}px`,
height: `${height * scale}px`,
border: "2px solid #FF0000",
boxSizing: "border-box",
};
},
/* 初始化websocket */
initWebSocket() {
const url = `ws://192.168.1.188:8080/websocket?token=${getToken()}`;
const data = { type: "carLocation", status: true };
connectWebsocket(
url,
data,
(res) => {
// console.log("onWsMessage接收到服务器的数据: ", res);
console.log(JSON.parse(res));
},
(err) => {
console.log("断开重连");
}
);
},
/* 发送消息 */
sendMsg() {
sendMsg(5555); //value是发送的值
// this.value = "";
},
2024-10-18 17:31:35 +08:00
},
beforeDestroy() {
clearInterval(this.timeFlag);
closeWebsocket();
2024-10-18 17:31:35 +08:00
},
};
</script>
<style lang="scss" scoped>
.screen-content {
width: 100%;
height: 100%;
}
// 中间样式
.screen-middle {
width: 100%;
height: 100%;
.screen-left {
width: 25.5%;
height: calc(100% - 5rem);
padding-left: 3.5rem;
position: fixed;
top: 5rem;
z-index: 1;
background-image: url("../../assets/screen/index/bg-left.png");
background-repeat: no-repeat;
background-size: 100% 100%;
::v-deep .screen-checkBox {
.el-radio-button__inner {
background-color: transparent;
padding: 0 0.3rem;
border: none;
}
.el-radio-button__orig-radio:checked + .el-radio-button__inner {
color: #1cb6ff;
}
}
2024-10-18 17:31:35 +08:00
}
.screen-right {
width: 25.5%;
height: calc(100% - 5rem);
top: 5rem;
padding-right: 3.5rem;
position: fixed;
right: 0;
z-index: 1;
background-image: url("../../assets/screen/index/bg-right.png");
background-repeat: no-repeat;
background-size: 100% 100%;
::v-deep .screen-checkBox {
.el-radio-button__inner {
background-color: transparent;
padding: 0 0.3rem;
border: none;
}
.el-radio-button__orig-radio:checked + .el-radio-button__inner {
color: #1cb6ff;
}
}
2024-10-18 17:31:35 +08:00
}
2024-10-22 09:55:33 +08:00
.road-content {
width: 100%;
height: 100%;
position: relative;
// 图例
.map-legend {
height: 7rem;
width: 2rem;
position: absolute;
top: 17%;
left: 26%;
z-index: 1;
background-image: url("../../assets/screen/index/map-legend.png");
background-repeat: no-repeat;
background-size: 100% 100%;
2024-10-22 09:55:33 +08:00
}
// 右上角切换图标样式多选框
.road-checkBox {
width: 8rem;
height: 10rem;
position: absolute;
2024-10-25 17:29:08 +08:00
right: 26%;
top: 10%;
padding: 0.4rem;
border-radius: 0.4rem;
border: 1px solid #193dae;
background-color: #082843;
z-index: 1;
.road-scroll {
overflow-x: hidden;
}
::v-deep .el-checkbox__label {
color: #9aadd8;
}
}
// 图片背景样式
.disease-content {
width: 100%;
height: 100%;
background-image: url("../../assets/screen/index/map-liaoning.jpg");
background-repeat: no-repeat;
background-size: 100% 100%;
position: relative;
2024-10-25 17:29:08 +08:00
// 标题
.disease-title {
width: 20rem;
height: 2.8rem;
position: absolute;
// top: 5rem;
left: 50%;
transform: translate(-50%, 5rem);
background-image: url("../../assets/screen/index/disease-title.png");
background-repeat: no-repeat;
background-size: 100%;
}
2024-10-25 17:29:08 +08:00
// 筛选病害类型下拉
.map-image-select {
left: 28%;
top: 10%;
position: absolute;
2024-11-13 15:37:25 +08:00
color: #ffffff;
2024-10-25 17:29:08 +08:00
}
// 打点部分
.map-care {
width: 48%;
height: 73%;
position: absolute;
left: 26%;
top: 13%;
2024-10-28 10:00:28 +08:00
.map-care-div {
height: 8.5rem;
min-width: 3.5rem;
display: flex;
justify-content: center;
line-height: 1.6rem;
font-size: 0.7rem;
color: #ffffff;
position: absolute;
background-repeat: no-repeat;
background-size: 100% 100%;
background-position: 50%;
span {
height: 1rem;
2024-10-28 10:00:28 +08:00
}
}
.map-care-div-1 {
background-image: url("../../assets/screen/index/map-care-div-1.png");
}
.map-care-div-2 {
background-image: url("../../assets/screen/index/map-care-div-2.png");
}
.map-care-div-3 {
background-image: url("../../assets/screen/index/map-care-div-3.png");
}
.map-care-div-4 {
background-image: url("../../assets/screen/index/map-care-div-4.png");
}
.map-care-div-5 {
background-image: url("../../assets/screen/index/map-care-div-5.png");
}
.map-care-div-6 {
background-image: url("../../assets/screen/index/map-care-div-6.png");
}
2024-10-25 17:29:08 +08:00
}
}
2024-10-25 17:29:08 +08:00
::v-deep .baseLayerClass {
filter: grayscale(200%) invert(200%) sepia(50%) hue-rotate(175deg)
brightness(80%) saturate(550%);
2024-10-22 09:55:33 +08:00
}
}
2024-10-18 17:31:35 +08:00
}
// 头部样式
.screen-header {
width: 100%;
height: 5rem;
2024-10-22 09:55:33 +08:00
padding: 1rem 3rem;
2024-10-18 17:31:35 +08:00
position: fixed;
top: 0;
display: flex;
justify-content: space-between;
z-index: 1;
background-image: url("../../assets/screen/index/bg-top.png");
background-repeat: no-repeat;
background-size: 100% 120%;
background-position-x: 50%;
.header-weather {
display: flex;
align-items: flex-end;
font-size: 1rem;
color: #89c5e8;
}
.header-time {
display: flex;
color: #89c5e8;
> div {
margin: 0 0.5rem;
display: flex;
align-items: flex-end;
}
2024-11-20 14:46:20 +08:00
// 消息中心样式
.header-news {
2024-11-20 14:46:20 +08:00
i {
position: relative;
cursor: pointer;
font-size: 1.5rem;
.num {
min-width: 0.9rem;
position: absolute;
top: -0.2rem;
right: -0.5rem;
padding: 0.2rem;
font-size: 0.6rem;
border-radius: 0.5rem;
color: #ffffff;
background-color: red;
}
}
}
2024-10-18 17:31:35 +08:00
.header-data {
font-size: 1.8rem;
}
.header-week {
display: flex;
align-items: flex-start;
justify-content: flex-end;
flex-direction: column;
}
.header-home {
2024-10-22 09:55:33 +08:00
.home {
cursor: pointer;
height: 1.5rem;
width: 1.2rem;
background-image: url("../../assets/screen/index/exit.png");
background-repeat: no-repeat;
background-size: 100%;
}
2024-10-18 17:31:35 +08:00
}
}
}
// 大屏下方样式
.screen-footer {
width: 49%;
height: 7.55rem;
position: fixed;
bottom: 0;
left: 25.5%;
background-image: url("../../assets/screen/index/bg-foot.png");
background-repeat: no-repeat;
background-size: 100.1% 99%;
.footer-change-map {
width: 100%;
height: 40%;
display: flex;
justify-content: center;
align-items: center;
color: #8deeff;
font-style: italic;
font-size: 0.7rem;
.change-map-div {
cursor: pointer;
2024-10-25 17:29:08 +08:00
margin: 0 2rem;
2024-10-18 17:31:35 +08:00
}
.change-map-click {
color: #fffed2;
}
}
.footer-change-vue {
width: 100%;
height: 60%;
display: flex;
justify-content: center;
align-items: center;
> div {
height: 100%;
width: 37.5%;
}
> div:nth-child(2) {
height: 100%;
width: 25%;
}
// 未点击样式
.change-vue-OverviewScreen {
2024-11-13 15:37:25 +08:00
background-image: url("../../assets//screen/index/button-overview.png");
2024-10-18 17:31:35 +08:00
background-repeat: no-repeat;
2024-11-13 15:37:25 +08:00
background-size: 95% 60%;
background-position: 75% 15%;
2024-10-18 17:31:35 +08:00
}
.change-vue-click-OverviewScreen {
2024-11-13 15:37:25 +08:00
background-image: url("../../assets//screen/index/button-overview-click.png");
2024-10-18 17:31:35 +08:00
background-repeat: no-repeat;
2024-11-13 15:37:25 +08:00
background-size: 95% 60%;
background-position: 75% 15%;
2024-10-18 17:31:35 +08:00
}
2024-11-13 15:37:25 +08:00
.change-vue-DiseaseScreen {
background-image: url("../../assets//screen/index/button-disease.png");
2024-10-18 17:31:35 +08:00
background-repeat: no-repeat;
2024-11-13 15:37:25 +08:00
background-size: 99% 60%;
background-position: 50% 13%;
2024-10-18 17:31:35 +08:00
}
2024-11-13 15:37:25 +08:00
.change-vue-click-DiseaseScreen {
background-image: url("../../assets//screen/index/button-disease-click.png");
2024-10-18 17:31:35 +08:00
background-repeat: no-repeat;
2024-11-13 15:37:25 +08:00
background-size: 99% 60%;
background-position: 50% 13%;
2024-10-18 17:31:35 +08:00
}
2024-11-13 15:37:25 +08:00
.change-vue-RoadScreen {
background-image: url("../../assets//screen/index/button-road.png");
2024-10-18 17:31:35 +08:00
background-repeat: no-repeat;
2024-11-13 15:37:25 +08:00
background-size: 93% 60%;
2024-10-18 17:31:35 +08:00
background-position: 15% 15%;
}
2024-11-13 15:37:25 +08:00
.change-vue-click-RoadScreen {
background-image: url("../../assets//screen/index/button-road-click.png");
2024-10-18 17:31:35 +08:00
background-repeat: no-repeat;
2024-11-13 15:37:25 +08:00
background-size: 93% 60%;
2024-10-18 17:31:35 +08:00
background-position: 15% 15%;
}
2024-11-13 15:37:25 +08:00
2024-10-18 17:31:35 +08:00
// .change-vue-click {
// color: red;
// }
}
}
/* 修改弹窗样式 */
::v-deep .el-dialog {
background-color: transparent;
}
::v-deep .el-dialog__header {
padding: 10px;
background-color: #113463;
span,
i {
color: #ffffff;
}
}
::v-deep .el-dialog__body {
padding: 0;
background-color: #113463;
/* 查看点位大图弹窗 */
.view-image-container {
position: relative;
width: 100%;
height: 80%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
overflow: hidden;
}
.view-image-container img {
max-width: 100%;
max-height: 100%;
object-fit: contain;
}
.rect-overlay {
position: absolute;
2024-11-13 15:37:25 +08:00
// pointer-events: none;
border: 2px solid red;
}
}
// 图片信息
.rect-image {
width: 80%;
position: absolute;
top: 0;
font-size: 1.2rem;
color: #ffffff;
background-color: rgba(0, 0, 0, 0.5);
}
// 大屏下拉框样式
::v-deep .el-select {
width: 6.5rem;
.el-input .el-select__caret {
line-height: 1.5rem;
}
.el-input--medium .el-input__inner {
height: 1.5rem;
background-color: transparent;
color: #89c5e8;
border-color: #6991cd;
}
.el-select-dropdown {
background-color: #102649;
border-color: #08204f;
.el-scrollbar {
.el-select-dropdown__wrap {
.el-scrollbar__view {
2024-11-13 15:37:25 +08:00
.el-select-dropdown__item {
color: #aaabb8;
}
.el-select-dropdown__item:hover {
background-color: #2b4c7e;
}
.el-select-dropdown__item.selected {
background-color: #2b4c7e;
}
.el-select-dropdown__item.hover {
background-color: #2b4c7e;
}
}
.el-select-dropdown__list {
background-color: #102649;
}
}
}
}
}
2024-11-15 11:03:30 +08:00
// 修改级联样式
::v-deep .el-cascader {
width: 8rem;
.el-input--medium .el-input__inner {
height: 1.5rem;
background-color: transparent;
color: #89c5e8;
border-color: #6991cd;
}
}
</style>
<style lang="scss">
.screen-index-cascader {
background-color: #102649;
border-color: #08204f;
2024-11-15 18:08:37 +08:00
2024-11-15 11:03:30 +08:00
.el-cascader-node__label {
color: #aaabb8;
}
2024-11-15 18:08:37 +08:00
2024-11-15 11:03:30 +08:00
.el-cascader-node:hover {
background-color: #2b4c7e;
}
2024-11-15 18:08:37 +08:00
2024-11-15 11:03:30 +08:00
.el-cascader-node:active {
background-color: #2b4c7e;
}
2024-11-15 18:08:37 +08:00
2024-11-15 11:03:30 +08:00
.el-cascader-node:focus {
background-color: #2b4c7e;
}
}
2024-11-20 14:46:20 +08:00
// 大屏消息弹出框样式
.screen-message-popover {
background-color: rgba(0, 0, 0, 0.8);
border: none;
.screen-message-content {
width: 100%;
color: #ffffff;
.message-content {
width: 100%;
height: 12rem;
.message-item {
padding: 0.5rem 0;
border-bottom: 1px dashed rgb(115, 115, 116);
.item-top {
width: 100%;
display: flex;
&:hover {
span {
color: rgb(113, 179, 255);
}
}
.time {
width: 40%;
}
}
.item-content {
padding-left: 1rem;
}
}
}
.message-footer {
display: flex;
justify-content: flex-end;
}
}
}
2024-11-15 11:03:30 +08:00
</style>