大屏提交
This commit is contained in:
@ -1,275 +1,328 @@
|
||||
<template>
|
||||
<div class="centerPage">
|
||||
<div class="topPage">
|
||||
<div id="earth" style="width: 100%;height: 100%;"></div>
|
||||
<div class="centerPage_map">
|
||||
<div ref="mapRef" class="map-container" style="width: 100%; height: 100%" />
|
||||
</div>
|
||||
<div class="endPage" :class="{ 'slide-out-down': isHide }">
|
||||
<Title title="AI安全巡检">
|
||||
<img src="@/assets/projectLarge/robot.svg" alt="" height="20px" width="20px">
|
||||
<div class="centerPage_bottom">
|
||||
<Title title="风险预警">
|
||||
<img src="@/assets/projectLarge/robot.svg" alt="" height="20px" width="20px" />
|
||||
</Title>
|
||||
<div class="swiper" v-if="inspectionList.length">
|
||||
<div class="arrow" :class="{ 'canUse': canLeft }" @click="swiperClick('left')">
|
||||
<el-icon size="16" :color="canLeft ? 'rgba(29, 214, 255, 1)' : 'rgba(29, 214, 255, 0.3)'">
|
||||
<ArrowLeft />
|
||||
</el-icon>
|
||||
</div>
|
||||
<div class="swiper_content" ref="swiperContent">
|
||||
<div class="swiper_item" v-for="(item, i) in inspectionList" :key="i">
|
||||
<img :src="item.picture" alt="安全巡检" class="swiper_img">
|
||||
<div class="swiper_date">{{ item.createTime.slice(5) }}</div>
|
||||
<div class="swiper_tip">{{ item.label }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="arrow" :class="{ 'canUse': canRight }" @click="swiperClick('right')">
|
||||
<el-icon size="16" :color="canRight ? 'rgba(29, 214, 255, 1)' : 'rgba(29, 214, 255, 0.3)'">
|
||||
<ArrowRight />
|
||||
</el-icon>
|
||||
</div>
|
||||
<div class="centerPage_bottom_table">
|
||||
<el-table v-loading="loading" :data="tableData" show-overflow-tooltip>
|
||||
<el-table-column label="时间" align="center" prop="date" />
|
||||
<el-table-column label="类型" align="center" prop="riskType">
|
||||
<template #default="scope">
|
||||
{{ safety_inspection_type[scope.row.riskType] }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="报警内容" align="center" prop="alarmContent" />
|
||||
<el-table-column label="危险等级" align="center" prop="dangerLevel" />
|
||||
<el-table-column label="来源" align="center" prop="source" />
|
||||
<el-table-column label="警告等级" align="center" prop="alarmLevel">
|
||||
<template #default="scope">
|
||||
{{ risk_level_type[scope.row.alarmLevel] }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted, toRefs, getCurrentInstance } from "vue"
|
||||
import Title from './title.vue'
|
||||
import { ArrowLeft, ArrowRight } from '@element-plus/icons-vue'
|
||||
import { getScreenSafetyInspection } from '@/api/projectScreen'
|
||||
|
||||
const { proxy } = getCurrentInstance();
|
||||
const { violation_level_type } = toRefs(proxy?.useDict('violation_level_type'));
|
||||
|
||||
const props = defineProps({
|
||||
isHide: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
projectId: {
|
||||
type: String,
|
||||
default: ""
|
||||
<script setup lang="ts">
|
||||
import * as echarts from 'echarts';
|
||||
import china from '@/assets/china.json';
|
||||
import RevenueContractCard from './RevenueContractCard.vue';
|
||||
import bottomboxconpoent from './bottomboxconpoent.vue';
|
||||
import { totalAmount, projectGis } from '@/api/largeScreen/index'; // 导入projectGis接口
|
||||
import { ref, onMounted, onUnmounted, nextTick } from 'vue';
|
||||
import Title from './title.vue';
|
||||
import { earlyWarning } from '@/api/outputApi';
|
||||
import { useDict } from '@/utils/dict';
|
||||
import { getDicts } from '@/api/system/dict/data';
|
||||
// 地图相关变量
|
||||
const mapRef = ref<HTMLDivElement | null>(null);
|
||||
let myChart: any = null;
|
||||
const projectData = ref<any[]>([]); // 存储项目地理信息数据
|
||||
const loading = ref(false);
|
||||
const tableData = ref([]);
|
||||
const risk_level_type = ref();
|
||||
const safety_inspection_type = ref();
|
||||
// 新增:获取项目地理信息数据
|
||||
const getProjectGisData = async () => {
|
||||
try {
|
||||
const response = await projectGis();
|
||||
if (response.code === 200) {
|
||||
// 过滤掉没有经纬度的项目
|
||||
projectData.value = response.data.filter((item: any) => item.lng !== null && item.lat !== null && item.lng !== '' && item.lat !== '');
|
||||
console.log('项目地理数据:', projectData.value);
|
||||
} else {
|
||||
console.error('项目地理数据请求失败:', response.msg);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('项目地理数据调用异常:', error);
|
||||
}
|
||||
})
|
||||
};
|
||||
//获取字典
|
||||
const getDictsType = async () => {
|
||||
const res = await getDicts('risk_level_type');
|
||||
if (res.code === 200) {
|
||||
risk_level_type.value = res.data.reduce((acc, item) => {
|
||||
acc[item.dictValue] = item.dictLabel;
|
||||
return acc;
|
||||
}, {});
|
||||
}
|
||||
};
|
||||
const getDictsType2 = async () => {
|
||||
const res = await getDicts('safety_inspection_type');
|
||||
if (res.code === 200) {
|
||||
safety_inspection_type.value = res.data.reduce((acc, item) => {
|
||||
acc[item.dictValue] = item.dictLabel;
|
||||
return acc;
|
||||
}, {});
|
||||
}
|
||||
};
|
||||
//获取表格数据
|
||||
const getTableList = async () => {
|
||||
const res = await earlyWarning();
|
||||
if (res.code === 200) {
|
||||
tableData.value = res.data;
|
||||
}
|
||||
};
|
||||
|
||||
const inspectionList = ref([{
|
||||
id: "",
|
||||
label: "",
|
||||
picture: "",
|
||||
createTime: ""
|
||||
}])
|
||||
const swiperContent = ref()
|
||||
const swiperItemWidth = ref(100)
|
||||
const canLeft = ref(false)
|
||||
const canRight = ref(true)
|
||||
// 地图resize处理
|
||||
const handleResize = () => {
|
||||
if (myChart) myChart.resize();
|
||||
};
|
||||
|
||||
const swiperClick = (direction) => {
|
||||
if (!swiperContent.value) return
|
||||
|
||||
if (direction === 'right') {
|
||||
if (swiperContent.value.scrollLeft >= swiperContent.value.scrollWidth - swiperContent.value.clientWidth) {
|
||||
canRight.value = false
|
||||
canLeft.value = true
|
||||
return
|
||||
}
|
||||
swiperContent.value.scrollLeft += swiperItemWidth.value
|
||||
} else {
|
||||
if (swiperContent.value.scrollLeft <= 0) {
|
||||
canLeft.value = false
|
||||
canRight.value = true
|
||||
return
|
||||
}
|
||||
swiperContent.value.scrollLeft -= swiperItemWidth.value
|
||||
// 初始化地图(修改为使用接口数据)
|
||||
const initEcharts = () => {
|
||||
if (!mapRef.value || projectData.value.length === 0) {
|
||||
console.error('未找到地图容器或项目数据');
|
||||
return;
|
||||
}
|
||||
|
||||
// 更新箭头状态
|
||||
canLeft.value = swiperContent.value.scrollLeft > 0
|
||||
canRight.value = swiperContent.value.scrollLeft < swiperContent.value.scrollWidth - swiperContent.value.clientWidth
|
||||
}
|
||||
echarts.registerMap('china', china as any);
|
||||
|
||||
const getInspectionList = async () => {
|
||||
const res = await getScreenSafetyInspection(props.projectId)
|
||||
const { code, data } = res
|
||||
if (code === 200) {
|
||||
data.map(item => {
|
||||
item.label = violation_level_type.value.find((i) => i.value === item.violationType)?.label
|
||||
})
|
||||
inspectionList.value = data
|
||||
}
|
||||
}
|
||||
// 创建地球
|
||||
const createEarth = () => {
|
||||
window.YJ.on({
|
||||
ws: true,
|
||||
// host: getIP(), //资源所在服务器地址
|
||||
// username: this.loginForm.username, //用户名 可以不登录(不填写用户名),不登录时无法加载服务端的数据
|
||||
// password: md5pass, //密码 生成方式:md5(用户名_密码)
|
||||
}).then((res) => {
|
||||
let earth = new YJ.YJEarth("earth");
|
||||
window.Earth1 = earth;
|
||||
YJ.Global.openRightClick(window.Earth1);
|
||||
YJ.Global.openLeftClick(window.Earth1);
|
||||
let view = {
|
||||
"position": {
|
||||
"lng": 102.03643298211526,
|
||||
"lat": 34.393586474501,
|
||||
"alt": 11298179.51993155
|
||||
},
|
||||
"orientation": {
|
||||
"heading": 360,
|
||||
"pitch": -89.94481747201486,
|
||||
"roll": 0
|
||||
}
|
||||
// 从接口数据生成散点数据
|
||||
const scatterData = projectData.value.map((item) => ({
|
||||
name: item.projectName,
|
||||
value: [parseFloat(item.lng), parseFloat(item.lat)], // 转换为数值类型
|
||||
shortName: item.shortName,
|
||||
projectSite: item.projectSite,
|
||||
symbol: 'diamond',
|
||||
itemStyle: { color: '#0166d6' },
|
||||
symbolSize: [20, 20],
|
||||
label: {
|
||||
show: true,
|
||||
formatter: '{b}', // 显示项目名称
|
||||
position: 'top',
|
||||
color: '#fff',
|
||||
fontSize: 12,
|
||||
backgroundColor: 'rgba(3, 26, 52, 0.7)',
|
||||
padding: [3, 6],
|
||||
borderRadius: 3
|
||||
}
|
||||
loadBaseMap(earth.viewer)
|
||||
YJ.Global.CesiumContainer(window.Earth1, {
|
||||
compass: false, //罗盘
|
||||
});
|
||||
// YJ.Global.flyTo(earth, view);
|
||||
// YJ.Global.setDefaultView(earth.viewer, view)
|
||||
})
|
||||
}
|
||||
// 加载底图
|
||||
const loadBaseMap = (viewer) => {
|
||||
// 创建瓦片提供器
|
||||
const imageryProvider = new Cesium.UrlTemplateImageryProvider({
|
||||
url: 'https://webst01.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}',
|
||||
// 可选:设置瓦片的格式
|
||||
fileExtension: 'png',
|
||||
// 可选:设置瓦片的范围和级别
|
||||
minimumLevel: 0,
|
||||
maximumLevel: 18,
|
||||
// 可选:设置瓦片的投影(默认为Web Mercator)
|
||||
projection: Cesium.WebMercatorProjection,
|
||||
// 可选:如果瓦片服务需要跨域请求,设置请求头部
|
||||
credit: new Cesium.Credit('卫星图数据来源')
|
||||
}));
|
||||
|
||||
myChart = echarts.init(mapRef.value, null, {
|
||||
renderer: 'canvas',
|
||||
useDirtyRect: false
|
||||
});
|
||||
|
||||
// 添加图层到视图
|
||||
const layer = viewer.imageryLayers.addImageryProvider(imageryProvider);
|
||||
}
|
||||
onMounted(() => {
|
||||
getInspectionList()
|
||||
createEarth()
|
||||
if (swiperContent.value && swiperContent.value.children.length > 0) {
|
||||
swiperItemWidth.value = swiperContent.value.children[0].clientWidth + 20
|
||||
}
|
||||
})
|
||||
const option: any = {
|
||||
roam: true, // 允许缩放和平移
|
||||
geo: {
|
||||
type: 'map',
|
||||
map: 'china',
|
||||
zoom: 2, // 调整初始缩放级别
|
||||
center: [108.95, 34.27], // 中国中心位置经纬度
|
||||
label: { show: false, color: '#fff' },
|
||||
itemStyle: {
|
||||
areaColor: '#031a34',
|
||||
borderColor: '#1e3a6e',
|
||||
borderWidth: 1
|
||||
}
|
||||
},
|
||||
tooltip: {
|
||||
trigger: 'item',
|
||||
backgroundColor: 'rgba(3, 26, 52, 0.8)',
|
||||
borderColor: '#1e3a6e',
|
||||
textStyle: {
|
||||
color: '#fff'
|
||||
},
|
||||
formatter: function (params: any) {
|
||||
if (params.data) {
|
||||
// 处理散点数据
|
||||
const data = params.data;
|
||||
return `
|
||||
<div style="font-weight: bold;">${data.name}</div>
|
||||
<div>地点:${data.projectSite}</div>
|
||||
<div>经纬度:${data.value[0].toFixed(6)}, ${data.value[1].toFixed(6)}</div>
|
||||
`;
|
||||
}
|
||||
if (params.seriesType === 'map') {
|
||||
// console.log(params, 111111);
|
||||
return `
|
||||
<div style="font-weight: bold;">${params.name}</div>
|
||||
|
||||
`;
|
||||
}
|
||||
}
|
||||
},
|
||||
series: [
|
||||
{
|
||||
type: 'map',
|
||||
map: 'china',
|
||||
geoIndex: 0,
|
||||
emphasis: {
|
||||
areaColor: '#fff',
|
||||
label: { show: true, color: '#fff' },
|
||||
itemStyle: { areaColor: '#02417e' }
|
||||
},
|
||||
select: { itemStyle: { areaColor: '#02417e' } },
|
||||
data: [] // 可以留空,或根据需要添加区域数据
|
||||
},
|
||||
{
|
||||
type: 'scatter',
|
||||
coordinateSystem: 'geo',
|
||||
data: scatterData,
|
||||
emphasis: {
|
||||
scale: true, // 鼠标悬停时放大
|
||||
symbolSize: [25, 25]
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
myChart.setOption(option);
|
||||
};
|
||||
const risk_level_type1 = ref([]);
|
||||
const safety_inspection_type1 = ref([]);
|
||||
// 组件生命周期
|
||||
onMounted(() => {
|
||||
nextTick(async () => {
|
||||
// 先获取合同数据和项目地理数据,再初始化地图
|
||||
getDictsType();
|
||||
getDictsType2();
|
||||
await Promise.all([getProjectGisData()]);
|
||||
initEcharts();
|
||||
getTableList();
|
||||
window.addEventListener('resize', handleResize);
|
||||
});
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
window.removeEventListener('resize', handleResize);
|
||||
if (myChart) {
|
||||
myChart.dispose();
|
||||
myChart = null;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.centerPage {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.topPage,
|
||||
.endPage {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
padding: 15px 0;
|
||||
border: 1px solid rgba(230, 247, 255, 0.1);
|
||||
// justify-content: space-between;
|
||||
padding: 0 10px 10px 10px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.topPage {
|
||||
flex: 1;
|
||||
margin-bottom: 23px;
|
||||
transition: flex 0.5s ease;
|
||||
}
|
||||
|
||||
.endPage {
|
||||
max-height: 300px;
|
||||
opacity: 1;
|
||||
transition: all 0.5s ease;
|
||||
}
|
||||
|
||||
/* 向下滑出动画 */
|
||||
.slide-out-down {
|
||||
transform: translateY(100%);
|
||||
opacity: 0;
|
||||
max-height: 0;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.swiper {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 20px;
|
||||
padding: 20px 20px 10px 20px;
|
||||
|
||||
.swiper_content {
|
||||
.centerPage_map {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
gap: 20px;
|
||||
transition: all 0.3s ease-in-out;
|
||||
overflow-x: auto;
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
height: 65vh;
|
||||
}
|
||||
|
||||
.swiper_item {
|
||||
position: relative;
|
||||
.centerPage_bottom {
|
||||
width: 100%;
|
||||
height: 25vh;
|
||||
border: 1px solid rgba(29, 214, 255, 0.1);
|
||||
padding: 10px 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
width: 133px;
|
||||
height: 84px;
|
||||
|
||||
.swiper_img {
|
||||
width: 133px;
|
||||
height: 84px;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.swiper_date {
|
||||
position: absolute;
|
||||
top: 4px;
|
||||
right: 4px;
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
color: rgba(230, 247, 255, 1);
|
||||
}
|
||||
|
||||
.swiper_tip {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
.centerPage_bottom_table {
|
||||
width: 100%;
|
||||
padding: 5px 0;
|
||||
text-align: center;
|
||||
font-size: 12px;
|
||||
font-weight: 400;
|
||||
color: rgba(230, 247, 255, 1);
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
:deep(.el-table, .el-table__expanded-cell) {
|
||||
background: rgba(0, 0, 0, 0);
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
:deep(.el-table tr) {
|
||||
background: rgba(0, 0, 0, 0);
|
||||
// border: 1px solid rgba(0, 255, 255, 0.5) !important;
|
||||
}
|
||||
:deep(.el-table .el-table__header-wrapper th, .el-table .el-table__fixed-header-wrapper th) {
|
||||
background: rgba(0, 0, 0, 0) !important;
|
||||
}
|
||||
:deep(.el-table th.el-table__cell) {
|
||||
background: rgba(0, 0, 0, 0);
|
||||
color: #fff;
|
||||
border-bottom: 1px solid transparent !important;
|
||||
border-right: 1px solid transparent !important;
|
||||
}
|
||||
:deep(.el-table--enable-row-transition .el-table__body td.el-table__cell) {
|
||||
border-right: 1px solid transparent !important;
|
||||
border-bottom: 1px solid transparent !important;
|
||||
}
|
||||
|
||||
:deep(.el-table__body tr:hover > td) {
|
||||
background-color: rgba(40, 75, 91, 0.9) !important;
|
||||
}
|
||||
/* 表格边框颜色 */
|
||||
:deep(.el-table, .el-table__header-wrapper, .el-table__body-wrapper, .el-table__footer-wrapper, .el-table th, .el-table td) {
|
||||
border: 1px solid transparent !important;
|
||||
background: rgba(0, 0, 0, 0);
|
||||
}
|
||||
:deep(.el-table__inner-wrapper:before) {
|
||||
background-color: transparent !important;
|
||||
}
|
||||
|
||||
/* 固定列的边框 */
|
||||
:deep(.el-table__fixed, .el-table__fixed-right) {
|
||||
border: 1px solid transparent !important;
|
||||
}
|
||||
:deep(.el-table__body-wrapper::-webkit-scrollbar) {
|
||||
width: 4px;
|
||||
height: 10px;
|
||||
}
|
||||
|
||||
:deep(.el-table__body-wrapper::-webkit-scrollbar-thumb) {
|
||||
-webkit-box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.2);
|
||||
opacity: 0.2;
|
||||
background: #00c0ff;
|
||||
}
|
||||
|
||||
:deep(.el-table__body-wrapper::-webkit-scrollbar-track) {
|
||||
-webkit-box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.2);
|
||||
border-radius: 0;
|
||||
background: rgba(220, 228, 245, 0.8);
|
||||
}
|
||||
|
||||
:deep(.el-icon-arrow-right:before) {
|
||||
color: #0ff;
|
||||
font-weight: bold;
|
||||
font-size: 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.arrow {
|
||||
display: grid;
|
||||
place-items: center;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
border-radius: 50%;
|
||||
border: 1px solid rgba(29, 214, 255, 0.3);
|
||||
color: skyblue;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
// 滚动条优化
|
||||
.centerPage_bottom_table::-webkit-scrollbar {
|
||||
width: 5px;
|
||||
height: 5px;
|
||||
}
|
||||
|
||||
&.canUse {
|
||||
border: 1px solid rgba(29, 214, 255, 1);
|
||||
}
|
||||
.centerPage_bottom_table::-webkit-scrollbar-thumb {
|
||||
background-color: #0ff;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
&:hover:not(.canUse) {
|
||||
opacity: 0.7;
|
||||
.centerPage_bottom_table::-webkit-scrollbar-track {
|
||||
background-color: rgba(0, 255, 255, 0.2);
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
Reference in New Issue
Block a user