隧道定位页面大屏接口对接

This commit is contained in:
jxj_yjl 2023-09-25 13:33:47 +08:00
parent 8ab9a1d352
commit 02aa20f1c4
12 changed files with 1113 additions and 8 deletions

View File

@ -3,9 +3,9 @@ NODE_ENV = 'development'
# 本地环境接口地址(/api/index.ts文件中使用)
# VITE_API_URL = 'http://121.196.214.246/api'
VITE_API_URL = 'http://182.90.224.147:100'
# VITE_API_URL = 'http://182.90.224.147:100'
# VITE_API_URL = 'http://192.168.34.221:12360'
# VITE_API_URL = 'http://192.168.34.221:30002'
VITE_API_URL = 'http://192.168.34.221:30002'
# 上传

View File

@ -0,0 +1,27 @@
import http from "@/api";
const BASEURL = import.meta.env.VITE_API_URL;
// 项目信息
export const getProjectInfoBySnApi = (params: {}) => {
return http.post(BASEURL + `/xmgl/projectExtend/getProjectExtendInfo`, params);
};
// 今日统计
export const getLocationTunnelApi = (params: {}) => {
return http.get(BASEURL + `/xmgl/locationTunnel/list`, params);
};
// 报警信息
export const getTagLowVoltageAlarmApi = (params: {}) => {
return http.post(BASEURL + `/xmgl/locationTagLowVoltageAlarm/countLocationTagLowVoltageAlarmEveryDay`, params);
};
// 地图上的人(场内人员名单)
export const getRealTimeLocationWorkerApi = (params: {}) => {
return http.post(BASEURL + `/xmgl/locationData/getRealTimeLocationWorker`, params);
};
// 班组统计
export const getCountRealTimeLocationWorkerApi = (params: {}) => {
return http.post(BASEURL + `/xmgl/locationData/countRealTimeLocationWorker`, params);
};

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 918 KiB

View File

@ -406,11 +406,12 @@ function jumpBgd() {
background-size: 100% 100%;
margin-left: -1%;
.subItem {
width: 5%;
width: 100px;
margin-top: -1.5%;
text-align: center;
}
:nth-child(1) {
margin-left: 3%;
margin-left: 2%;
}
}
}

View File

@ -1,13 +1,201 @@
<template>
<div>
隧道定位监测
</div>
<div class="tunnelContent">
<div class="select-right">
<el-select v-model="selectDay" style="width: 85%" size="small">
<el-option
v-for="(item, index) in tunnelList"
:key="index"
:label="item.tunnelName"
:value="item.id"
@click="checkId(item, index)"
/>
</el-select>
</div>
<div class="left">
<leftTop class="leftTop"></leftTop>
<leftCenter class="leftCenter" :sonData="sonData"></leftCenter>
<leftBottom class="leftBottom" :alarmEcharts="alarmEcharts"></leftBottom>
</div>
<div class="right">
<rightTop class="rightTop" :activeImgUrl="activeImgUrl" :pointTunnelList="pointTunnelList"></rightTop>
<div class="rightBottom">
<rightBottomLeft class="rightBottomLeft" :workerEcharts="workerEcharts"></rightBottomLeft>
<rightBottomRight class="rightBottomRight" :mapPeopleData="mapPeopleData"></rightBottomRight>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { onMounted, ref, onBeforeUnmount } from "vue";
import leftTop from "./leftTop.vue";
import leftCenter from "./leftCenter.vue";
import leftBottom from "./leftBottom.vue";
import rightTop from "./rightTop.vue";
import rightBottomLeft from "./rightBottomLeft.vue";
import rightBottomRight from "./rightBottomRight.vue";
import {
getLocationTunnelApi, //
getTagLowVoltageAlarmApi, //
getCountRealTimeLocationWorkerApi, //
getRealTimeLocationWorkerApi //
} from "@/api/modules/tunnelPosition";
import { GlobalStore } from "@/stores";
const BASEURL = import.meta.env.VITE_API_URL;
const store = GlobalStore();
let selectDay = ref("");
let tunnelList = ref([] as any);
let sonData = ref([] as any);
let activeImgUrl = ref("");
//
const getSelectData = async () => {
const res = await getLocationTunnelApi({
projectSn: store.sn
});
tunnelList.value = res.result;
selectDay.value = res.result[0].id;
checkId(res.result[0], 0);
};
//
const alarmEcharts = ref([] as any);
const getAlarmData = async () => {
const res = await getTagLowVoltageAlarmApi({
type: 1, //
locationTunnelId: selectDay.value
});
alarmEcharts.value = res.result;
// console.log("::", res);
};
//
const workerEcharts = ref([] as any);
const getnWorkerData = async () => {
const res = await getCountRealTimeLocationWorkerApi({
locationTunnelId: selectDay.value
});
// console.log("::", res);
workerEcharts.value = res.result;
};
//
const mapPeopleData = ref([] as any);
const pointTunnelList = ref([] as any);
const getRealTimeLocationData = async (tunnelLength: any, width: any) => {
const res = await getRealTimeLocationWorkerApi({
locationTunnelId: selectDay.value
});
if (res.result) {
mapPeopleData.value = res.result;
pointTunnelList.value = [];
res.result.forEach(item => {
//
//xnx÷*=x
let xPx = (item.inlX / tunnelLength) * width;
let pointTunneObj = {
topPx: item.py,
leftPx: xPx,
name: item.personName
};
pointTunnelList.value.push(pointTunneObj);
});
}
};
//
const checkId = async(val: any, index: any) => {
activeImgUrl.value = "";
sonData.value = [];
tunnelList.value.forEach((item: any) => {
if (val.id == item.id) {
sonData.value = item;
}
});
let width = 0;
if (val.planarGraph && val.planarGraph != "" && val.planarGraph != null) {
let Img = JSON.parse(val.planarGraph);
activeImgUrl.value = Img[0].url;
//
let img = new Image();
img.src = BASEURL + "/image/" + Img[0].url;
img.onload = function () {
width = img.width;
getRealTimeLocationData(val.tunnelLength, width);
};
} else {
activeImgUrl.value = "";
}
getnWorkerData();
getAlarmData();
};
onMounted(() => {
getSelectData();
});
</script>
<style lang="scss" scoped>
.tunnelContent {
width: 100%;
height: 100%;
display: flex;
<style scoped>
.select-right {
position: absolute;
top: 18.5%;
left: 90%;
}
.left {
width: 26%;
.leftTop {
height: 28%;
}
.leftCenter {
height: 30%;
margin: 9% 0 8.5% 0;
}
.leftBottom {
height: 29.5%;
}
}
.right {
width: 73%;
margin-left: 1%;
.rightTop {
height: 66%;
}
.rightBottom {
margin-top: 1%;
height: 32%;
display: flex;
.rightBottomLeft {
width: 35%;
}
.rightBottomRight {
width: 63.5%;
margin-left: 1.5%;
}
}
}
}
:deep(.el-input__wrapper) {
background: #112d59;
padding-left: 10%;
}
:deep(.el-input__inner) {
color: #fff;
}
:deep(.el-select .el-input .el-select__caret) {
color: #fff;
}
</style>

View File

@ -0,0 +1,223 @@
<template>
<div class="leftBottom">
<Card title="报警信息">
<div id="tunnelTrend" ref="tunnelTrend" style="width: 100%; height: 100%"></div>
</Card>
</div>
</template>
<script setup lang="ts">
import Card from "@/components/card.vue";
import symbolIcon from "@/assets/images/lineSymbol.png";
import { onMounted, ref, onBeforeUnmount, defineProps, watch } from "vue";
import * as echarts from "echarts";
const props = defineProps({
alarmEcharts: []
});
//alarmEcharts
watch(
() => props.alarmEcharts,
newVal => {
var data = newVal;
twenty_four_time.value=[]
yData.value=[]
if (data.length > 0) {
data.forEach((element: any) => {
twenty_four_time.value.push(element.x);
yData.value.push(element.y);
});
}
drawChart();
}
);
// x
let twenty_four_time = ref([] as any);
// Y
let yData = ref([] as any);
//
let option = ref(null as any);
function initOption() {
option.value = {
// backgroundColor: '#071c3a',
title: {
// text: '',
textStyle: {
align: "center",
color: "#fff",
fontSize: 20
},
top: "2%",
left: "center"
},
tooltip: {
trigger: "axis",
axisPointer: {
lineStyle: {
color: {
type: "linear",
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [
{
offset: 0,
color: "rgba(0, 255, 233,0)"
},
{
offset: 0.5,
color: "rgba(255, 255, 255,1)"
},
{
offset: 1,
color: "rgba(0, 255, 233,0)"
}
],
global: false
}
}
}
},
grid: {
top: "10%",
left: "10%",
right: "6%",
bottom: "15%"
// containLabel: true
},
xAxis: [
{
type: "category",
axisLine: {
show: true,
lineStyle: {
color: "#14346C"
}
},
splitArea: {
// show: true,
color: "#f00",
lineStyle: {
color: "#f00"
}
},
axisLabel: {
color: "#fff"
},
splitLine: {
show: false
},
boundaryGap: false,
data: twenty_four_time.value
}
],
yAxis: [
{
type: "value",
// name: unit.value,
nameTextStyle: {
color: "#fff",
nameLocation: "start"
},
min: 0,
// max: 140,
splitNumber: 3,
splitLine: {
show: true,
lineStyle: {
color: "#14346C"
}
},
axisLine: {
show: true,
lineStyle: {
color: "#14346C"
}
},
axisLabel: {
show: true,
margin: 20,
textStyle: {
color: "#fff"
}
},
axisTick: {
show: true
}
}
],
series: [
{
type: "line",
// smooth: true, //
showAllSymbol: true,
symbol: `image://${symbolIcon}`,
// symbol: 'image://./static/images/guang-circle.png',
// symbol: "circle",
symbolSize: 35,
label: {
show: false,
position: "top",
textStyle: {
color: "#fff"
}
},
itemStyle: {
color: "#D2FFF9",
lineStyle: {
width: 0.1,
normal: {
color: "#fff",
shadowBlur: 0
}
}
},
tooltip: {
show: true
},
areaStyle: {
normal: {
color: new echarts.graphic.LinearGradient(
0,
0,
0,
1,
[
{
offset: 0,
color: "rgba(130, 251, 234, 0.40)"
},
{
offset: 1,
color: "rgba(130, 251, 234, 0.1)"
}
],
false
),
shadowColor: "rgba(130, 251, 234, 1)",
shadowBlur: 20
}
},
data: yData.value
}
]
};
}
function drawChart() {
initOption();
console.log("绘制前数据", yData.value);
let AITodayTrend = echarts.init(document.getElementById("tunnelTrend"));
AITodayTrend.setOption(option.value);
}
onMounted(async () => {
drawChart();
});
</script>
<style lang="scss" scoped>
.leftBottom {
width: 100%;
height: 100%;
}
</style>

View File

@ -0,0 +1,233 @@
<template>
<div class="leftCenter">
<Card title="今日统计">
<div class="dataBox">
<div class="tunnelLenth">
<div>
隧道全长<span style="margin-left: 11%">{{ tunnelObject.tunnelLength }}m</span>
</div>
<div>
当前施工进度<span>{{ tunnelObject.constructionProgressBegin }}/{{ tunnelObject.constructionProgressEnd }}</span>
</div>
</div>
<div class="tunnelSchedule">
<div id="tunnelDule" ref="tunnelDule" style="width: 100%; height: 100%"></div>
</div>
</div>
</Card>
</div>
</template>
<script setup lang="ts">
import { onMounted, ref, defineProps, watch } from "vue";
import * as echarts from "echarts";
import Card from "@/components/card.vue";
const props = defineProps({
sonData: []
});
const sonData = ref(props.sonData);
const tunnelObject = ref({} as any);
const airTypeEchart = ref(["隧道进度"]);
const airTypeData = ref([]);
//sonData
watch(
() => props.sonData,
newVal => {
tunnelObject.value = newVal;
airTypeData.value = [tunnelObject.value.constructionProgressBegin];
drawChart();
}
);
function drawChart() {
let chartDom = document.getElementById("tunnelDule");
if (chartDom) {
chartDom.removeAttribute("_echarts_instance_");
}
let option = ref({
grid: {
left: "3%",
right: "0%",
bottom: "10%",
top: "60%",
containLabel: true
},
// backgroundColor: '#101129',
xAxis: {
show: false,
type: "value",
max: 1000
},
yAxis: [
{
type: "category",
inverse: true,
axisLabel: {
show: true,
inside: true,
verticalAlign: "bottom",
padding: [0, 0, 10, 0],
lineHeight: "20",
textStyle: {
color: "#FFFFFF",
fontSize: "14"
}
// formatter: function (val, index) {
// console.log("val", val, index);
// return val;
// }
},
splitLine: {
show: false
},
axisTick: {
show: false
},
axisLine: {
show: false
},
data: airTypeEchart.value
},
{
inverse: true,
axisTick: "none",
axisLine: "none",
axisLabel: {
inside: true,
verticalAlign: "bottom",
padding: [0, 0, 10, 0],
lineHeight: "20",
textStyle: {
color: "#FFFFFF",
fontSize: "12"
},
formatter: function (val, index) {
// console.log("val", val, index);
return val;
}
},
data: airTypeData.value
},
{
type: "category",
inverse: true,
axisTick: "none",
axisLine: "none",
show: true,
data: airTypeData.value
}
],
series: [
{
type: "bar",
showBackground: true,
backgroundStyle: {
color: "#14346c",
borderRadius: 30
},
label: {
show: false,
// position:'right',
// formatter:'{@score}%',
textStyle: {
color: "#03fcfe",
fontSize: "12"
}
},
itemStyle: {
normal: {
barBorderRadius: 10,
color: new echarts.graphic.LinearGradient(0, 0, 1, 0, [
{
offset: 0,
color: "#194077"
},
{
offset: 1,
color: "#4CC4F8"
}
])
}
},
barWidth: 3,
data: airTypeData.value
},
{
name: "内圆",
type: "scatter",
stack: "圆",
yAxisIndex: 0,
data: airTypeData.value, //
label: false,
symbolSize: 2,
itemStyle: {
normal: {
borderColor: "#fff",
borderWidth: 4,
color: "#fff",
opacity: 1
}
},
z: 3
},
{
name: "内圆框",
type: "scatter",
stack: "圆",
yAxisIndex: 0,
data: [0], //
label: false,
symbolSize: 15,
itemStyle: {
normal: {
borderColor: "#4CC4F8",
borderWidth: 2,
color: "#14346c",
opacity: 1
}
},
z: 2
}
]
});
let AIWarnTotal = echarts.init(document.getElementById("tunnelDule"));
AIWarnTotal.setOption(option.value);
}
onMounted(async () => {
drawChart();
});
</script>
<style lang="scss" scoped>
.leftCenter {
width: 100%;
height: 100%;
.dataBox {
width: 90%;
height: 95%;
padding: 1% 5%;
.tunnelLenth {
margin-top: 7%;
height: 30%;
background: url("@/assets/images/securityManagement/menImg.png") no-repeat;
background-size: 100% 100%;
color: #fff;
font-size: 14px;
padding-top: 1.5%;
div {
padding: 1% 3%;
span {
color: #4ac0f3;
margin-left: 5%;
}
}
}
.tunnelSchedule {
height: 50%;
// background: pink;
}
}
}
</style>

View File

@ -0,0 +1,47 @@
<template>
<div class="leftTop">
<Card title="项目信息">
<div class="contentBox">
<p style="line-height: 1.5" :title="projectInfo.projectOverview || ''">
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{{ projectInfo.projectOverview || "" }}
</p>
</div>
</Card>
</div>
</template>
<script setup lang="ts">
import { onMounted, ref } from "vue";
import Card from "@/components/card.vue";
import { getProjectInfoBySnApi } from "@/api/modules/tunnelPosition";
import { GlobalStore } from "@/stores";
const store = GlobalStore();
const projectInfo = ref({} as any);
//
const getProjectInfo = async () => {
const res = await getProjectInfoBySnApi({
projectSn: store.sn
});
projectInfo.value = res.result;
console.log("获取项目信息::", res);
};
onMounted(() => {
getProjectInfo();
});
</script>
<style lang="scss" scoped>
.leftTop {
width: 100%;
height: 100%;
.contentBox {
width: 93%;
height: 98%;
color: #fff;
font-size: 14px;
padding: 1% 5%;
overflow: hidden;
cursor: pointer;
}
}
</style>

View File

@ -0,0 +1,189 @@
<template>
<div class="rightBottomLeft">
<Card title="班组统计">
<div id="tunnelEcharts" style="width: 100%; height: 100%"></div>
</Card>
</div>
</template>
<script setup lang="ts">
import Card from "@/components/card.vue";
import { onMounted, ref, onBeforeUnmount, defineProps, watch } from "vue";
import * as echarts from "echarts";
const props = defineProps({
workerEcharts: []
});
watch(
() => props.workerEcharts,
newVal => {
var data = newVal,
xData = [],
yData = [];
if (data.length > 0) {
data.forEach((element: any) => {
xData.push(element.count);
yData.push(element.teamName);
});
}
draw(xData,yData);
}
);
function draw(xData:any,yData:any) {
let chartDom = document.getElementById("tunnelEcharts");
if (chartDom) {
chartDom.removeAttribute("_echarts_instance_");
}
let echartsTest = echarts.init(document.getElementById("tunnelEcharts"));
let option = {
tooltip: {
trigger: "axis",
axisPointer: {
//
type: "shadow" // 线'line' | 'shadow'
},
borderRadius: 5,
borderWidth: 5,
formatter: function (params) {
let dot =
'<span style="display:inline-block;margin-right:5px;border-radius:50%;width:10px;height:10px;background-color:#02C4DD"></span>';
return params[0].name + "<br>" + params[0].value;
}
},
grid: {
left: "4%",
right: "4%",
bottom: "6%",
top: "15%",
containLabel: true
},
xAxis: {
show: true,
data: yData,
triggerEvent: true,
axisTick: {
show: false,
lineStyle: {
color: "red"
}
},
axisLine: {
show: true,
lineStyle: {
color: "#193c81"
}
},
axisLabel: {
show: true,
rotate: 0,
interval: 0,
textStyle: {
padding: [0, 0, 0, 0],
fontSize: 12,
color: "#fff"
}
}
},
yAxis: {
name: "",
triggerEvent: true,
nameTextStyle: {
color: "#fff",
fontSize: 10,
padding: [0, 0, 10, 0]
},
splitLine: {
show: true,
lineStyle: {
color: "#193c81"
}
},
axisTick: {
show: false
},
axisLine: {
show: true,
lineStyle: {
color: "#193c81"
}
},
axisLabel: {
show: true,
textStyle: {
color: "#fff",
fontSize: 12
}
}
},
// color: ["#e54035"],
series: [
{
name: "数量",
barMinHeight: 10,
type: "pictorialBar",
barCategoryGap: "5%",
// symbol: 'path://M0,10 L10,10 L5,0 L0,10 z',
symbol: "path://M0,10 L10,10 C5.5,10 5.5,5 5,0 C4.5,5 4.5,10 0,10 z",
itemStyle: {
normal: {
//barBorderRadius: 5,
//
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{
offset: 0,
color: "#071b34"
},
{
offset: 0.5,
color: "#7bf0e1"
},
{
offset: 1,
color: "#3a787f"
}
])
}
},
label: {
normal: {
show: true,
position: "top",
textStyle: {
color: "#fff",
fontSize: 12
}
}
},
data: xData,
z: 10
},
{
name: "hill",
type: "bar",
barWidth: "10%",
symbol: "path://M0,10 L10,10 C5.5,10 5.5,5 5,0 C4.5,5 4.5,10 0,10 z",
itemStyle: {
normal: {
color: "rgba(11,47,68,.8)"
}
},
// data: 200,
z: 9
}
]
};
echartsTest.setOption(option);
}
onMounted(() => {
draw([],[]);
});
</script>
<style lang="scss" scoped>
.rightBottomLeft {
width: 100%;
height: 100%;
}
::v-deep .h-card .content {
height: 82%;
}
</style>

View File

@ -0,0 +1,127 @@
<template>
<div class="rightBottomRight">
<Card title="场内人员名单">
<div class="tabList">
<div>序号</div>
<div>姓名</div>
<div>卡号</div>
<div>班组</div>
<div>所在区域</div>
<div>坐标</div>
<div>电量(%)</div>
<div>通过设备</div>
<div>联系电话</div>
<div>累积工作时长</div>
</div>
<div class="listBox" ref="scrollRef">
<el-scrollbar style="height: 80%">
<div v-for="(item, index) in list" class="listStyle">
<div>{{ index + 1 }}</div>
<div>{{ item.personName }}</div>
<div>{{ item.cardno }}</div>
<div>{{ item.teamName }}</div>
<div>{{ item.regionName }}</div>
<div>{{ item.inlX }}</div>
<div>{{ item.volume }}</div>
<div>{{ item.deviceName }}</div>
<div>{{ item.phone }}</div>
<div>{{ item.workingTimeName }}</div>
</div>
</el-scrollbar>
<div class="notoDta" v-if="list.length == 0">
<img src="@/assets/images/noData.png" alt="" />
<p>暂无数据</p>
</div>
</div>
</Card>
</div>
</template>
<script setup lang="ts">
import Card from "@/components/card.vue";
import { ref, defineProps, watch } from "vue";
const props = defineProps({
mapPeopleData: []
});
watch(
() => props.mapPeopleData,
newVal => {
if (newVal.length > 0) {
list.value = newVal;
}
}
);
const list = ref([]);
</script>
<style lang="scss" scoped>
.rightBottomRight {
width: 100%;
height: 100%;
.tabList {
display: flex;
width: 100%;
height: 14%;
background: url("@/assets/images/dustNoise/rightBottom.png") no-repeat;
background-size: 100% 100%;
left: 75.5%;
top: 75%;
color: #7b86a3;
font-size: 14px;
line-height: 30px;
justify-content: space-around;
text-align: center;
div {
width: 100px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
}
.listBox {
height: 91%;
.listStyle {
display: flex;
justify-content: space-around;
color: #fff;
height: 12%;
line-height: 25px;
font-size: 12px;
text-align: center;
div {
width: 100px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
}
.listStyle:hover {
background: #091f3f;
}
}
.notoDta {
top: 75%;
width: 12%;
margin: 5% -40%;
left: 110%;
position: absolute;
img {
width: 40%;
margin: 5% 30%;
}
p {
color: #fff;
font-size: 14px;
margin: -6% 37%;
}
}
}
::v-deep .h-card .content {
margin-top: 1.5%;
height: 82.5%;
}
::v-deep .h-card .title .titltText {
margin: 0% 0 0.5% 2%;
}
</style>

View File

@ -0,0 +1,70 @@
<template>
<div class="rightTop">
<Card title="地图">
<div class="mapBox">
<!-- 动态大图 -->
<img :src="BASEURL + '/image/' + activeImgUrl" alt="" />
<div class="pointTunnel" v-for="item in pointTunnelList" :style="{ top: item.topPx + 'px', left: item.leftPx + 'px' }">
<span style="position: absolute; top: 58%; left: 25%">{{ item.name }}</span>
<img style="width: 55px; height: 50px" src="@/assets/images/testImg/tunneIcon.png" />
</div>
</div>
</Card>
</div>
</template>
<script setup lang="ts">
import Card from "@/components/card.vue";
import { defineProps, watch, ref } from "vue";
const BASEURL = import.meta.env.VITE_API_URL;
const pointList = ref([]);
const activeImgUrl = ref("");
const props = defineProps({
pointTunnelList: [],
activeImgUrl: ""
});
watch(
() => props.pointTunnelList,
newVal => {
if (newVal.length > 0) {
pointList.value = newVal;
}
}
);
watch(
() => props.activeImgUrl,
newVal => {
if (newVal) {
activeImgUrl.value = newVal;
}
}
);
</script>
<style lang="scss" scoped>
.rightTop {
width: 100%;
height: 100%;
.mapBox {
width: 100%;
height: 100%;
overflow-x: scroll;
position: relative;
.pointTunnel {
position: absolute;
}
img {
max-width: 300%;
max-height: 100%;
}
}
}
::v-deep .h-card .content {
margin-top: 1%;
height: 90%;
}
::v-deep .h-card .title .titltText {
margin: 0% 0 0.5% 1%;
}
</style>