web
5 天以前 05a001098514eb86065b6277ebe3ead90837f833
src/views/screen/flow/graphic/index.vue
@@ -1,40 +1,46 @@
<script setup>
import {onMounted, ref, onUnmounted} from "vue";
import {onMounted, ref} from "vue";
import {getUserType} from '@/utils/auth.js'
import {getFlowPointList} from '@/api/screen/index'
import {getFlowVideoData} from '@/api/screen/graphic/index.js'
import EZUIKit from 'ezuikit-js';
import {useRoute} from "vue-router";
import {useRoute, useRouter} from "vue-router";
import VideoPlayer from "@/components/VideoPlayer/VideoPlayer.vue";
import html2canvas from 'html2canvas';
const route = useRoute();
const router = useRouter();
const menuList = ref([])
const userType = ref(getUserType())
const searchVal = ref('')
const playerData = ref([])
const hasFullScreen = ref(false)
let ezKitList = []; //视频组件实例数组
let ezKitId = []; //视频盒子id数组
let timer = null;
const showFullScreen = ref(false)
const fullIndex = ref()
// 全屏操作
const handleFullScreen = () => {
    const dom = document.getElementById(ezKitId[0])
    dom.requestFullscreen()
// 全屏弹窗
const handleFullScreen = (index) => {
    fullIndex.value = index
    showFullScreen.value = true
}
const closeFullScreen = () => {
    showFullScreen.value = false
}
// 监听全屏状态,是否要开起蒙层
document.addEventListener('fullscreenchange', (val) => {
    if (!document.fullscreenElement) {  //退出全屏
        hasFullScreen.value = false;
    } else { //开起全屏
        hasFullScreen.value = true;
    }
});
// 抓拍
const handleSnap = (index) => {
    ezKitList[index].capturePicture(`capture-${new Date().getTime()}`, 0.8); // 参数:回调函数,图片格式,质量(0-1)
const handleSnap = async (index) => {
    const dom = document.getElementById(`player${index}`)
    const canvas = await html2canvas(dom, {
        backgroundColor: null, // 透明背景
        scale: 2, // 提高分辨率
        logging: false, // 关闭日志
        useCORS: true, // 允许跨域图片
        allowTaint: true, // 允许污染图片
    });
    const imgUrl = canvas.toDataURL('image/png');
    const adom = document.createElement("a");
    adom.download = `截图_${new Date().getTime()}.png`
    adom.href = imgUrl;
    adom.click()
}
// 获取监控点菜单
@@ -46,59 +52,27 @@
// 选择菜单
const handleSelect = (id) => {
    ezKitList = []
    ezKitId = []
    playerData.value = []
    clearInterval(timer)
    getPlayerList(id)
}
// 搜索
const handleSearch = () => {
    ezKitList = []
    ezKitId = []
    playerData.value = []
    clearInterval(timer)
    getPlayerList()
}
// 获取监控点
const getPlayerList = async (id) => {
    getFlowVideoData({pointId: id, pointName: searchVal.value}).then(async res => {
        res.data.forEach((item, index) => {
            ezKitId[index] = `ezuikitPlayer${index}`
        })
        playerData.value = res.data
        await nextTick()
        // 渲染视频
        res.data.forEach((item, index) => {
            ezKitList[index] = new EZUIKit.EZUIKitPlayer({
                id: ezKitId[index],
                url: item.url,
                accessToken: item.accessToken,
            })
        })
    })
    //  挂载定时器, 只获取数据,不重新渲染视频节点
    timer = setInterval(() => {
        getFlowVideoData({pointId: id, pointName: searchVal.value}).then(res => {
            playerData.value = res.data
        })
    }, 10000)
}
onMounted(() => {
    getMoitorList()
    getPlayerList(route.params.id || '')
})
onUnmounted(() => {
    if (timer) {
        clearInterval(timer)
    }
})
</script>
@@ -134,23 +108,21 @@
                        </el-icon>
                        搜索
                    </el-button>
                    <el-button style="margin-left: 0" v-if="userType === '1'">
                    <el-button style="margin-left: 0" v-if="userType === '1'" @click="router.push('/monitorList')">
                        <el-icon>
                            <Plus/>
                        </el-icon>
                        新增
                    </el-button>
                </div>
                <div class="tool-r" @click="handleFullScreen">
                    <img src="@/assets/images/flow/fullscreen.png"/>
                    全屏
                </div>
            </div>
            <div class="monitor-box">
                <div class="monitor-list">
                    <div class="item" v-for="(item, index) in playerData" :key="index">
                        <div class="title">{{ item.pointName }}</div>
                        <div class="videoBox" :id="ezKitId[index]"></div>
                        <div class="item-video" :id="`player${index}`">
                            <VideoPlayer :item="item" :autoPlay="true" />
                        </div>
                        <div class="info">
                            <div class="info-list">
                                <div class="info-item">
@@ -158,19 +130,39 @@
                                    <div class="val"><span>{{ item.waterLevel }}</span>m</div>
                                </div>
                                <div class="info-item">
                                    <div class="name">流速:</div>
                                    <div class="name">表面流速:</div>
                                    <div class="val"><span>{{ item.flowVelocity }}</span>m/s</div>
                                </div>
                                <div class="info-item">
                                    <div class="name">瞬时流量:</div>
                                    <div class="name">水面宽度:</div>
                                    <div class="val"><span>{{ item.waterWidth }}</span>m</div>
                                </div>
                                <div class="info-item">
                                    <div class="name">平均流速:</div>
                                    <div class="val"><span>{{ item.avgVelocity }}</span>m/s</div>
                                </div>
                                <div class="info-item">
                                    <div class="name">过水面积:</div>
                                    <div class="val"><span>{{ item.waterArea }}</span>m³</div>
                                </div>
                                <div class="info-item">
                                    <div class="name">雷达流速:</div>
                                    <div class="val"><span>{{ item.radarVelocity }}</span>m/s</div>
                                </div>
                                <div class="info-item">
                                    <div class="name">实时流量:</div>
                                    <div class="val"><span>{{ item.newFlow }}</span>m³/h</div>
                                </div>
                                <div class="info-item">
                                    <div class="name">累计流量:</div>
                                    <div class="val"><span>{{ item.totalFlow }}</span>m³</div>
                                    <div class="name">起点距:</div>
                                    <div class="val"><span>{{ item.radarDistance }}</span>m</div>
                                </div>
                            </div>
                            <div class="info-btn">
                                <div class="fullScreen" v-if="item.url" @click="handleFullScreen(index)">
                                    <img src="@/assets/images/flow/screenIconWhite.png" alt="" />
                                    全屏
                                </div>
                                <el-button style="width: 6rem" @click="handleSnap(index)">抓拍</el-button>
                            </div>
                        </div>
@@ -178,8 +170,46 @@
                </div>
            </div>
        </div>
        <div class="mask" v-show="hasFullScreen">
            <div class="mask-item"></div>
        <div class="fullDialog" v-if="showFullScreen">
            <VideoPlayer :item="playerData[fullIndex]" :autoPlay="true" />
            <div class="closeIcon" @click="closeFullScreen"><el-icon><CircleClose /></el-icon></div>
            <div class="full-mask">
                <div class="mask-list">
                    <div class="mask-item">
                        <div class="name">水位:</div>
                        <div class="val"><span>{{ playerData[fullIndex].waterLevel }}</span>m</div>
                    </div>
                    <div class="mask-item">
                        <div class="name">表面流速:</div>
                        <div class="val"><span>{{ playerData[fullIndex].flowVelocity }}</span>m/s</div>
                    </div>
                    <div class="mask-item">
                        <div class="name">水面宽度:</div>
                        <div class="val"><span>{{ playerData[fullIndex].waterWidth }}</span>m</div>
                    </div>
                    <div class="mask-item">
                        <div class="name">平均流速:</div>
                        <div class="val"><span>{{ playerData[fullIndex].avgVelocity }}</span>m/s</div>
                    </div>
                    <div class="mask-item">
                        <div class="name">过水面积:</div>
                        <div class="val"><span>{{ playerData[fullIndex].waterArea }}</span>m³</div>
                    </div>
                    <div class="mask-item">
                        <div class="name">雷达流速:</div>
                        <div class="val"><span>{{ playerData[fullIndex].radarVelocity }}</span>m/s</div>
                    </div>
                    <div class="mask-item">
                        <div class="name">实时流量:</div>
                        <div class="val"><span>{{ playerData[fullIndex].newFlow }}</span>m³/h</div>
                    </div>
                    <div class="mask-item">
                        <div class="name">起点距:</div>
                        <div class="val"><span>{{ playerData[fullIndex].radarDistance }}</span>m</div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</template>
@@ -252,16 +282,6 @@
                    font-size: 1.1rem;
                }
            }
            .tool-r {
                display: flex;
                align-items: center;
                img {
                    width: 25px;
                    margin-right: 10px;
                }
            }
        }
        .monitor-box {
@@ -290,7 +310,7 @@
                        color: #fff;
                    }
                    .videoBox {
                    .item-video {
                        width: 100%;
                        height: 60%;
                        background-color: #000;
@@ -320,24 +340,43 @@
                                    width: 100px;
                                }
                                .val span {
                                    display: inline-block;
                                    padding: 0 20px;
                                .val{
                                    display: flex;
                                    align-items: center;
                                    span {
                                        display: inline-block;
                                        width: 6rem;
                                        overflow: hidden;
                                        text-overflow: ellipsis;
                                        white-space: nowrap;
                                    }
                                }
                            }
                        }
                        .info-btn {
                            width: 20%;
                            width: 15%;
                            padding: 1rem 0;
                            display: flex;
                            align-items: flex-end;
                            position: relative;
                            :deep(.el-button) {
                                color: #fff;
                                background: rgba(94, 229, 92, 0.6);
                                border-radius: 4px 4px 4px 4px;
                                border: 1px solid rgba(94, 229, 92, 0.6);
                                position: absolute;
                                bottom: 1rem;
                            }
                            .fullScreen{
                                width: 100%;
                                height: 50px;
                                display: flex;
                                align-items: center;
                                justify-content: center;
                                color: #fff;
                                img{
                                    width: 25px;
                                    margin-right: 10px;
                                }
                            }
                        }
                    }
@@ -346,20 +385,41 @@
        }
    }
    .mask{
        position: absolute;
    .fullDialog{
        position: fixed;
        left: 0;
        top: 0;
        z-index: 100;
        width: 100vw;
        height: 100vh;
        .mask-item{
        z-index: 200;
        width: 100%;
        height: 100%;
        background-color: #000;
        .closeIcon{
            position: absolute;
            left: 5%;
            bottom: 10%;
            height: 400px;
            width: 300px;
            background-color: rgba(0, 0, 0, 0.4);
            right: 20px;
            top: 20px;
            color: #fff;
            font-size: 36px;
        }
        .full-mask{
            position: absolute;
            left: 100px;
            bottom: 100px;
            width: 250px;
            height: 270px;
            background-color: rgba(0, 0, 0, 0.5);
            border-radius: 20px;
            .mask-list{
                padding: 10px 20px;
                .mask-item{
                    display: flex;
                    align-items: center;
                    color: #fff;
                    padding: 5px 0;
                    .name{
                        width: 50%;
                    }
                }
            }
        }
    }
}