Compare commits

...

4 Commits

  1. 7
      public/dahua/demo.html
  2. 2
      public/dahua/lib/WSPlayer/player.css
  3. BIN
      src/assets/font/大屏标题.OTF
  4. BIN
      src/assets/images/bigbj.png
  5. BIN
      src/assets/images/changtitle.png
  6. BIN
      src/assets/images/databj.png
  7. BIN
      src/assets/images/datacontentbj.png
  8. BIN
      src/assets/images/datatitle.png
  9. BIN
      src/assets/images/datatopbj.png
  10. BIN
      src/assets/images/menu.png
  11. BIN
      src/assets/images/menutwo.png
  12. BIN
      src/assets/images/videoitembj.png
  13. BIN
      src/assets/images/videoitembjtwo.png
  14. 7
      src/assets/styles/index.scss
  15. 3
      src/components/texttooltip/index.vue
  16. 2
      src/layout/components/AppMain.vue
  17. 2
      src/main.js
  18. 1
      src/permission.js
  19. 1
      src/views/constructionScheduling/progress-monitoring/index.vue
  20. 527
      src/views/large-screen/index.vue
  21. 132
      src/views/large-screen/options.js
  22. 141
      src/views/large-screen/video.vue

@ -18,7 +18,7 @@
}
.container {
display: flex;
padding: 0 10px !important;
padding: 0 0px !important;
margin: 0!important;
max-width: none;
}
@ -75,7 +75,7 @@
</div>
</div>
<!-- 中间内容部分 -->
<div class="container">
<div class="container" id="container">
<div class="real-container">
<span id="real-title">实时预览:</span>
<div id="ws-real-player" style="height: 500px; margin-bottom: 20px;"></div>
@ -110,6 +110,9 @@
document.getElementById('real-btn-box').style.display = 'none';
let readDom = document.getElementsByClassName('real-container')[0];
readDom.style.width = '100%';
readDom.style.marginLeft = '0px';
document.getElementById('ws-real-player').style.marginBottom = '0px';
}

@ -28,7 +28,7 @@
position: absolute;
}
.ws-player .wsplayer-item.selected {
border: 1px solid #009cff;
/* border: 1px solid #009cff; */
transition: all cubic-bezier(0.19, 1, 0.22, 1) .3s;
}
.ws-player .wsplayer-item.unselected {

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 192 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 79 KiB

After

Width:  |  Height:  |  Size: 99 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 396 KiB

After

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

@ -12,7 +12,12 @@
font-weight: normal;
font-style: normal;
}
@font-face {
font-family: 'Alibaba-PuHuiTi-Heavytwo';
src: url('../font/大屏标题.OTF') format('truetype');
font-weight: normal;
font-style: normal;
}
body {
height: 100%;
margin: 0;

@ -61,6 +61,9 @@ export default {
</script>
<style lang="scss" scoped>
.text-tooltip{
width: 100%;
}
:deep(.is-light) {
font-size: 20px !important;
}

@ -4,7 +4,7 @@
<router-view v-slot="{ Component, route }">
<transition name="fade-transform" mode="out-in">
<keep-alive :include="tagsViewStore.cachedViews">
<component v-if="!route.meta.link" :is="Component" :key="route.path"/>
<component v-if="!route.meta.link" :is="Component" :key="route.fullPath"/>
</keep-alive>
</transition>
</router-view>

@ -28,6 +28,7 @@ import locale from 'element-plus/lib/locale/lang/zh-cn' // 中文语言
import vue3SeamlessScroll from 'vue3-seamless-scroll';
import elementIcons from '@/components/SvgIcon/svgicon'
import util from '@/components-zbry/utils'
import texttooltip from '@/components/texttooltip'
const app = createApp(App)
// 懒加载组件
@ -55,6 +56,7 @@ app.component('BaseFilter', BaseFilter)
app.component('BaseModel', BaseModel)
app.component('BaseSelect', BaseSelect)
app.component('BaseControl', BaseControl)
app.component('texttooltip', texttooltip)
app.component('BaseTablePage', BaseTablePage)
app.component('BaseRadioGroup', BaseRadioGroup)
app.component('BaseUpload', BaseUpload)

@ -16,6 +16,7 @@ const indexArr = ["/index", "/"]
router.beforeEach((to, from, next) => {
NProgress.start()
if (getToken()) {
to.meta.title && useSettingsStore().setTitle(to.meta.title)
/* has token*/
if (to.path === '/login') {

@ -131,6 +131,7 @@ function getList(params) {
// max-height: calc(100% - 150px);
overflow: auto;
/* 子元素超出宽度时换行 */
}
.app-container {

@ -4,56 +4,199 @@
<div class="gradient">
辽沈集团新火工区项目智慧工地数据看板
</div>
<div class="xitong" @click="Jump()"></div>
<div class="leftmenu">
<div style="background: none;justify-content: flex-start;line-height: 0rem;">
<span style="margin-top: .625rem;">
{{ state.time }}
</span>
</div>
<div :class="item.path == $route.path ? 'activeMenu' : ''" @click="resolvePath(item)"
v-for="item, index in meunList().slice(0, 2)">{{ item.meta.title }}
</div>
</div>
<div class="rightmenu">
<div @click="resolvePath(item)" v-for="item, index in meunList().slice(-3)">{{ item.meta.title }}</div>
</div>
<!-- <div class="xitong" @click="Jump()"></div> -->
</div>
<div class="main-box">
<div class="top-box">
<div class="bottom-box">
<!-- 项目介绍 -->
<div class="top-item">
<div class="boxtitle">项目介绍</div>
<div class="boxcontent" style="display: flex;flex-direction: column;padding: .9375rem 1.25rem;">
<div class="displaybox" style="margin-bottom: .625rem;">
<div class="diamond"></div>项目名称 新火工区建设项目
<div class="right-top-item" style="overflow: hidden;">
<div class="top-item">
<div class="boxtitle"> 项目介绍</div>
<div class="boxcontent" style="display: flex;flex-direction: column;padding: .9375rem 1.25rem;">
<div class="displaybox" style="margin-bottom: .625rem;">
<div class="diamond"></div>项目名称 新火工区建设项目
</div>
<div class="displaybox" style="margin-bottom: .75rem;">
<div class="diamond" style="background-color: #FFAE3C;"></div>工地负责人xxx
</div>
<div class="chaochu" style="flex: 1;font-size: .8125rem;">
项目简介本项目拟新建单体包括一期5305#5601#5806#5826#5827#7310#等6栋单体建筑二期5602#5606#5607#5606#5609#5610#5701#5801#5801-1#5802#5802-1#5803#5805#5807#5808#5810#5810-1#5811#5811-1#5812#5813#5815#5816#5816-1#5817#5818#5821#5822#5828#5829#5830#5831#5909#等34栋单体建筑建筑物基础形式为杯形基础独立基础条形基础主体结构为框架结构排架结构抗爆间室屏院墙体为钢筋混凝土剪力墙结构
</div>
</div>
<div class="displaybox" style="margin-bottom: .75rem;">
<div class="diamond" style="background-color: #FFAE3C;"></div>工地负责人xxx
</div>
<!-- 工程日志 -->
<div class="top-item">
<div class="boxtitle">工程日志</div>
<div class="boxcontent"
style="display: flex;flex-direction: column;justify-content: space-around;padding: .9375rem 1.25rem;">
<div class="log-top">
<div class="tq-box">
<img src="../../assets/images/riqi.png" alt="">
<span>日期</span>
<span v-if="state.logList && state.logList.length > 0">{{ state.logList[0].date
}}</span>
<span v-else>-</span>
</div>
<div class="tq-box">
<img src="../../assets/images/wd.png" alt="">
<span>温度</span>
<span v-if="state.logList && state.logList.length > 0">{{
state.logList[0].temperature
}}</span>
<span v-else>-</span>
</div>
<div class="tq-box">
<img src="../../assets/images/fl.png" alt="">
<span>风力</span>
<span v-if="state.logList && state.logList.length > 0">{{ state.logList[0].wind
}}</span>
<span v-else>-</span>
</div>
<div class="tq-box">
<img src="../../assets/images/tq.png" alt="">
<span>天气</span>
<span v-if="state.logList && state.logList.length > 0">{{ state.logList[0].weather
}}</span>
<span v-else>-</span>
</div>
</div>
<div>
<table class="construction-table">
<thead>
<tr>
<th width="25%">现场负责人</th>
<th width="25%">联系方式</th>
<th width="50%">施工情况</th>
</tr>
</thead>
<tbody>
<tr>
<td width="25%">{{ state.logList && state.logList.length >
0 ? state.logList[0].principalName : '-' }}</td>
<td width="25%">{{ state.logList && state.logList.length >
0 ? state.logList[0].principalTel : '-' }}</td>
<td width="50%">
<el-tooltip v-if="state.logList && state.logList.length > 0"
class="box-item" effect="dark"
:content="state.logList[0].constructionSituation" placement="top">
<div style="width: 10rem;" class="chaochutwo">
{{ state.logList[0].constructionSituation }}</div>
</el-tooltip>
<span v-else>-</span>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="chaochu" style="flex: 1;font-size: .8125rem;">
项目简介本项目拟新建单体包括一期5305#5601#5806#5826#5827#7310#等6栋单体建筑二期5602#5606#5607#5606#5609#5610#5701#5801#5801-1#5802#5802-1#5803#5805#5807#5808#5810#5810-1#5811#5811-1#5812#5813#5815#5816#5816-1#5817#5818#5821#5822#5828#5829#5830#5831#5909#等34栋单体建筑建筑物基础形式为杯形基础独立基础条形基础主体结构为框架结构排架结构抗爆间室屏院墙体为钢筋混凝土剪力墙结构
</div>
</div>
<!-- 视频监控 -->
<div class="center-top-item">
<div class="boxtitle changtitle">视频监控</div>
<div class="center-item bigbj">
<myVideo></myVideo>
<!-- <div class="alarm-table-header">
<div>序号</div>
<div>姓名</div>
<div>进出门类型</div>
<div>刷卡时间</div>
<div>人员类型</div>
<div>是否佩戴口罩</div>
<div>是否超温</div>
</div>
<div class="scooll-box" ref="Access">
<vue3-seamless-scroll :copyNum="10" :wheel="true" style="height: 100%;overflow: hidden;"
:scrollbar="{
type: 'mini',
invert: false,
}" :list="state.tableData" :hoverStop="true" :hover="true" :step="0.3">
<div v-for="item, index in state.tableData" :key="index"
:class="index % 2 != 0 ? 'dark' : 'light'" class="table-item">
<div>{{ index + 1 }}</div>
<div>
{{ item.personName }}
</div>
<div>{{ stausList().find((res) =>
res.value == item.openType)?.label || '-' }}</div>
<div>
{{ item.startSwingTime }}
</div>
<div>{{ item.imageType == 1 ? '内部人员' : item.imageType == 2 ? '访客' : '-' }}</div>
<div
:style="{ color: item.maskState == 2 ? '#FF0A0A' : item.maskState == 3 ? '#00E287' : '#fff' }">
{{ item.maskState == 3 ? '带口罩' : item.maskState == 2 ? '没带口罩' : '未识别' }}
</div>
<div :style="{ color: item.overTemp ? '#FF0A0A' : '#00E287' }">
{{ item.overTemp ? '是' : '否' }}
</div>
</div>
<div class="zanwu" v-if="state.tableData.length == 0">
<img style="width: 12.5rem;" src="../../assets/images/zw.png" alt="">
<div class="zwtext">
暂无门禁记录
</div>
</div>
</vue3-seamless-scroll>
</div> -->
</div>
</div>
<!-- 数据概览 -->
<div class="top-item">
<div class="boxtitle">数据概览</div>
<div class="boxcontent">
<div class="overview-top">
<div class="data-font">
<span class="number-font">{{ state.gk.list }} <span></span></span>
<span>总工期</span>
</div>
<div class="data-font jbborder">
<span class="number-font">{{ parseFloat(state.gk.gcjd).toFixed(0)
}}<span>%</span></span>
<span>工程进度</span>
<!-- 数据概览 and 施工人员工种分析 -->
<div class="right-top-item">
<div class="top-item" style="overflow: hidden;">
<div class="boxtitle">数据概览</div>
<div class="boxcontent">
<div class="overview-top">
<div class="data-font">
<span class="number-font">{{ state.gk.list }} <span></span></span>
<span>总工期</span>
</div>
<div class="data-font jbborder">
<span class="number-font">{{ parseFloat(state.gk.gcjd).toFixed(0)
}}<span>%</span></span>
<span>工程进度</span>
</div>
<div class="data-font jbborder">
<span class="number-font">{{ state.gk.ysg }}<span></span></span>
<span>已施工</span>
</div>
</div>
<div class="data-font jbborder">
<span class="number-font">{{ state.gk.ysg }}<span></span></span>
<span>已施工</span>
<div class="overview-top" style="grid-template-columns: repeat(2, 1fr);border-bottom: 0;">
<div class="data-font ">
<span class="number-font">{{ state.gk.sg }}<span></span></span>
<span>施工人员</span>
</div>
<div class="data-font jbborder">
<span class="number-font">{{ state.gk.gl }}<span></span></span>
<span>管理人员</span>
</div>
</div>
</div>
<div class="overview-top" style="grid-template-columns: repeat(2, 1fr);border-bottom: 0;">
<div class="data-font ">
<span class="number-font">{{ state.gk.sg }}<span></span></span>
<span>施工人员</span>
</div>
<div class="data-font jbborder">
<span class="number-font">{{ state.gk.gl }}<span></span></span>
<span>管理人员</span>
</div>
</div>
<div class="top-item">
<div class="boxtitle">施工人员工种分析</div>
<div class="boxcontent" id="staff">
</div>
</div>
</div>
</div>
<div class="top-box">
<!-- 智能资源调度 -->
<div class="top-item">
<div class="boxtitle">智能资源调度</div>
@ -83,209 +226,91 @@
</div>
</div>
</div>
</div>
<!-- 工程日志 -->
<!-- 进度预警 -->
<div class="top-item">
<div class="boxtitle">工程日志</div>
<div class="boxcontent"
style="display: flex;flex-direction: column;justify-content: space-around;padding: .9375rem 1.25rem;">
<div class="log-top">
<div class="tq-box">
<img src="../../assets/images/riqi.png" alt="">
<span>日期</span>
<span v-if="state.logList && state.logList.length > 0">{{ state.logList[0].date
}}</span>
<span v-else>-</span>
</div>
<div class="tq-box">
<img src="../../assets/images/wd.png" alt="">
<span>温度</span>
<span v-if="state.logList && state.logList.length > 0">{{ state.logList[0].temperature
}}</span>
<span v-else>-</span>
</div>
<div class="tq-box">
<img src="../../assets/images/fl.png" alt="">
<span>风力</span>
<span v-if="state.logList && state.logList.length > 0">{{ state.logList[0].wind
}}</span>
<span v-else>-</span>
</div>
<div class="tq-box">
<img src="../../assets/images/tq.png" alt="">
<span>天气</span>
<span v-if="state.logList && state.logList.length > 0">{{ state.logList[0].weather
}}</span>
<span v-else>-</span>
<div class="boxtitle">进度预警</div>
<div class="boxcontent" v-if="state.warnList.length == 0">
<div class="zanwu">
<img style="width: 9.375rem;" src="../../assets/images/zw.png" alt="">
<div class="zwtext">
暂无进度预警
</div>
</div>
<div>
<table class="construction-table">
<thead>
<tr>
<th width="25%">现场负责人</th>
<th width="25%">联系方式</th>
<th width="50%">施工情况</th>
</tr>
</thead>
<tbody>
<tr>
<td width="25%">{{ state.logList && state.logList.length >
0 ? state.logList[0].principalName : '-' }}</td>
<td width="25%">{{ state.logList && state.logList.length >
0 ? state.logList[0].principalTel : '-' }}</td>
<td width="50%">
<el-tooltip v-if="state.logList && state.logList.length > 0"
class="box-item" effect="dark"
:content="state.logList[0].constructionSituation" placement="top">
<div style="width: 10rem;" class="chaochutwo">
{{ state.logList[0].constructionSituation }}</div>
</el-tooltip>
<span v-else>-</span>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
<div class="bottom-box">
<div class="right-top-item" style="overflow: hidden;">
<div class="top-item">
<div class="boxtitle">进度预警</div>
<div class="boxcontent" v-if="state.warnList.length == 0">
<div class="zanwu">
<img style="width: 9.375rem;" src="../../assets/images/zw.png" alt="">
<div class="zwtext">
暂无进度预警
</div>
</div>
</div>
<div v-else class="boxcontent"
style="display: grid;grid-template-columns: 1fr 1fr ;grid-gap: .75rem;padding: 1.5625rem 1.3125rem;">
<div class="yj-box" v-for="item, index in state.warnList.slice(0, 2)" :key="index">
<img v-if="index == 0" class="jgbj" src="../../assets/images/jglv.png" alt="">
<img v-else class="jgbj" src="../../assets/images/jgred.png" alt="">
<div style="text-align: center;font-size: .875rem;">{{ item.planName }}</div>
<div>开始时间{{ item.startTime }}</div>
<div>计划结束时间{{ item.endTime }}</div>
<div style="display: flex;align-items: center;">当前进度<div style="flex: 1;"> <el-progress
color="#0AA0FE" :stroke-width="8"
:percentage="Number(item.currentProgress ? item.currentProgress : 0)"
class="jd">
</el-progress>
</div>
<div v-else class="boxcontent"
style="display: grid;grid-template-columns: 1fr 1fr ;grid-gap: .75rem;padding: 1.5625rem 1.3125rem;">
<div class="yj-box" v-for="item, index in state.warnList.slice(0, 2)" :key="index">
<img v-if="index == 0" class="jgbj" src="../../assets/images/jglv.png" alt="">
<img v-else class="jgbj" src="../../assets/images/jgred.png" alt="">
<div style="text-align: center;font-size: .875rem;">{{ item.planName }}</div>
<div>开始时间{{ item.startTime }}</div>
<div>计划结束时间{{ item.endTime }}</div>
<div style="display: flex;align-items: center;">当前进度<div style="flex: 1;"> <el-progress
color="#0AA0FE" :stroke-width="8"
:percentage="Number(item.currentProgress ? item.currentProgress : 0)"
class="jd">
</el-progress>
</div>
<div>备注{{ item.warnInfo ? item.warnInfo : '-' }}</div>
</div>
</div>
</div>
<!-- 进度监控 -->
<div class="top-item" style="overflow: hidden;">
<div class="boxtitle">进度监控</div>
<div class="center-item">
<div class="alarm-table-header" style=" grid-template-columns: 1.5fr 2.5fr 3fr 2.5fr;">
<div>序号</div>
<div>任务</div>
<div>时间</div>
<div>累计进度</div>
</div>
<div class="scooll-box" ref="monitor">
<vue3-seamless-scroll :copyNum="10" :wheel="true" style="height: 100%;overflow: hidden;"
:scrollbar="{
type: 'mini',
invert: false,
}" :list="state.monitorList" :hoverStop="true" :hover="true" :step="0.3">
<div v-for="item, index in state.monitorList" :key="index"
:class="index % 2 != 0 ? 'dark' : 'light'" class="table-item"
style=" grid-template-columns: 1.5fr 2.5fr 3fr 2.5fr;">
<div>{{ index + 1 }}</div>
<div>
{{ item.planName }}
</div>
<div>{{ item.keystageTime }}</div>
<div>
{{ item.accumulativeProgress ? item.accumulativeProgress : 0 }}%
</div>
</div>
<div class="zanwu" v-if="state.monitorList.length == 0">
<img style="width: 9.375rem;" src="../../assets/images/zw.png" alt="">
<div class="zwtext">
暂无进度监控
</div>
</div>
</vue3-seamless-scroll>
</div>
<div>备注{{ item.warnInfo ? item.warnInfo : '-' }}</div>
</div>
</div>
</div>
<!-- 门禁记录 -->
<div class="center-top-item">
<myVideo></myVideo>
<!-- <div class="boxtitle">门禁记录</div>
<!-- 进度监控 -->
<div class="top-item">
<div class="boxtitle">进度监控</div>
<div class="center-item">
<div class="alarm-table-header">
<div class="alarm-table-header" style=" grid-template-columns: 1.5fr 2.5fr 3fr 2.5fr;">
<div>序号</div>
<div>姓名</div>
<div>进出门类型</div>
<div>刷卡时间</div>
<div>人员类型</div>
<div>是否佩戴口罩</div>
<div>是否超温</div>
<div>任务</div>
<div>时间</div>
<div>累计进度</div>
</div>
<div class="scooll-box" ref="Access">
<div class="scooll-box" ref="monitor">
<vue3-seamless-scroll :copyNum="10" :wheel="true" style="height: 100%;overflow: hidden;"
:scrollbar="{
type: 'mini',
invert: false,
}" :list="state.tableData" :hoverStop="true" :hover="true" :step="0.3">
<div v-for="item, index in state.tableData" :key="index"
:class="index % 2 != 0 ? 'dark' : 'light'" class="table-item">
}" :list="state.monitorList" :hoverStop="true" :hover="true" :step="0.3">
<div v-for="item, index in state.monitorList" :key="index"
:class="index % 2 != 0 ? 'dark' : 'light'" class="table-item"
style=" grid-template-columns: 1.5fr 2.5fr 3fr 2.5fr;">
<div>{{ index + 1 }}</div>
<div>
{{ item.personName }}
{{ item.planName }}
</div>
<div>{{ stausList().find((res) =>
res.value == item.openType)?.label || '-' }}</div>
<div>{{ item.keystageTime }}</div>
<div>
{{ item.startSwingTime }}
</div>
<div>{{ item.imageType == 1 ? '内部人员' : item.imageType == 2 ? '访客' : '-' }}</div>
<div
:style="{ color: item.maskState == 2 ? '#FF0A0A' : item.maskState == 3 ? '#00E287' : '#fff' }">
{{ item.maskState == 3 ? '带口罩' : item.maskState == 2 ? '没带口罩' : '未识别' }}
</div>
<div :style="{ color: item.overTemp ? '#FF0A0A' : '#00E287' }">
{{ item.overTemp ? '是' : '否' }}
{{ item.accumulativeProgress ? item.accumulativeProgress : 0 }}%
</div>
</div>
<div class="zanwu" v-if="state.tableData.length == 0">
<img style="width: 12.5rem;" src="../../assets/images/zw.png" alt="">
<div class="zanwu" v-if="state.monitorList.length == 0">
<img style="width: 9.375rem;" src="../../assets/images/zw.png" alt="">
<div class="zwtext">
暂无门禁记录
暂无进度监控
</div>
</div>
</vue3-seamless-scroll>
</div>
</div> -->
</div>
</div>
<!-- 施工人员工种分析 and 车辆机械设备统计 -->
<div class="right-top-item">
<div class="top-item">
<div class="boxtitle">施工人员工种分析</div>
<div class="boxcontent" id="staff">
</div>
</div>
<div class="top-item">
<div class="boxtitle">车辆机械设备统计</div>
<div class="boxcontent" id="car">
<!-- 车辆机械设备统计 -->
<div class="top-item">
<div class="boxtitle">车辆机械设备统计</div>
<div class="boxcontent" id="car">
</div>
</div>
</div>
</div>
</div>
<promptfrom></promptfrom>
</div>
@ -298,6 +323,7 @@ import { echartsZhu, echartsBing } from "./echartsOptions";
import { echart } from "../../echarts";
import { stausList } from './options'
import { retryAndRepeatRequest } from "@/utils/vctgo";
import { meunList } from './options'
import { getRecordPage, iengineerlogList, iuserworkerType, iresourcescheduleList, vehiclestat, statistics, dataOverview, iwarnlist } from './api'
const { proxy } = getCurrentInstance();
const tableTrue = ref(false);
@ -454,12 +480,14 @@ const state = reactive({
"ysg": 0,
gcjd: ""
},
requestController: null
requestController: null,
time: null,
})
onUnmounted(() => {
if (state.requestController) state.requestController.stop();
});
onMounted(async () => {
getTime()
if (state.requestController) {
state.requestController.stop();
state.requestController = null
@ -493,6 +521,17 @@ onMounted(async () => {
state.requestController = retryAndRepeatRequest(requestFn, 3, 30000, 300000);
state.loading = false
})
function getTime() {
state.time = proxy.parseTime(new Date());
setTimeout(() => {
getTime();
}, 1000);
}
function resolvePath(item) {
router.push({
path: item.children && item.children.length > 0 ? (item.path + '/' + item.children[0].path) : item.path
})
}
function Jump() {
router.push({
path: "/constructionScheduling/productionPlan"
@ -574,6 +613,46 @@ function engineeringLog(params) {
</script>
<style scoped lang='scss'>
.leftmenu {
width: 32.5rem;
height: 2.5rem;
position: absolute;
left: 1.25rem;
bottom: -.3125rem;
display: grid;
grid-template-columns: 1fr 1fr 1fr;
font-size: .9375rem;
color: #fff;
line-height: 2.5rem;
}
.rightmenu>div,
.leftmenu>div {
background: url('../../assets/images/menu.png') no-repeat;
background-size: 100% 100%;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
}
.activeMenu {
background: url('../../assets/images/menutwo.png') no-repeat !important;
}
.rightmenu {
line-height: 2.5rem;
width: 32.5rem;
height: 2.5rem;
position: absolute;
right: 1.25rem;
bottom: -.3125rem;
display: grid;
grid-template-columns: 1fr 1fr 1fr;
font-size: .9375rem;
color: #fff;
}
.xitong {
width: 6.25rem;
height: 2.1875rem;
@ -698,18 +777,24 @@ function engineeringLog(params) {
height: calc(100% - 3rem);
width: 100%;
margin-top: .5rem;
background: url('../../assets/images/cneterbj.png') no-repeat;
background: url('../../assets/images/datacontentbj.png') no-repeat;
background-size: 100% 100%;
overflow: hidden;
padding: 1.25rem;
}
.bigbj {
background: url('../../assets/images/bigbj.png') no-repeat;
background-size: 100% 100%;
padding-left: .625rem;
}
.dark {
background: rgba(50, 165, 210, 0.15);
}
.light {
background: rgba(50, 165, 210, 0.05);
background: none;
}
.right-top-item {
@ -727,7 +812,7 @@ function engineeringLog(params) {
.bottom-box {
width: 100%;
height: calc(66.66% - 1.25rem);
margin-top: 1.25rem;
display: grid;
grid-template-columns: 1fr 2fr 1fr;
grid-gap: 1.25rem;
@ -740,7 +825,7 @@ function engineeringLog(params) {
font-weight: 400;
font-size: .875rem;
color: #FFFFFF;
background-color: #08223b;
// background: rgba(50,165,210,0.4);
/* 深蓝色背景,可根据实际需求调整颜色值 */
}
@ -893,15 +978,17 @@ function engineeringLog(params) {
.boxtitle {
width: 100%;
height: 2.5rem;
line-height: 2.5rem;
background: url('../../assets/images/datatitle.png') no-repeat;
background-size: 100% 100%;
font-family: Source Han Sans CN, Source Han Sans CN;
font-weight: bold;
font-size: 1rem;
color: #FFFFFF;
display: flex;
align-items: center;
padding: 0 1.5625rem;
padding: 0 2.375rem;
font-family: 'Alibaba-PuHuiTi-Heavytwo';
font-style: italic;
}
.top-item {
@ -912,6 +999,7 @@ function engineeringLog(params) {
.top-box {
width: 100%;
height: 33.33%;
margin-top: 1.25rem;
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-gap: 1.25rem;
@ -927,7 +1015,8 @@ function engineeringLog(params) {
.topheader {
width: 100%;
height: 6.25rem;
height: 4.6875rem;
margin-bottom: 1.5625rem;
background: url('../../assets/images/datatopbj.png') no-repeat;
background-size: 100% 100%;
display: flex;
@ -942,13 +1031,21 @@ function engineeringLog(params) {
background: linear-gradient(270.0000000000008deg, #F2F7FF 0%, #D4F7FF 50%, #F2F7FF 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
font-size: 2rem;
font-size: 2.125rem;
font-weight: bold;
}
.changtitle {
background: url('../../assets/images/changtitle.png') no-repeat;
background-size: 100% 100%;
}
.data-screen {
width: 100%;
height: 100vh;
background: #040614;
background: url('../../assets/images/databj.png') no-repeat;
background-size: 100% 100%;
background-color: black;
// height: 67.5rem;
}
</style>

@ -1,64 +1,70 @@
export const stausList = () => {
return [
{ "value": 42, "label": "合法密码开门" },
{ "value": 43, "label": "非法密码开门" },
{ "value": 45, "label": "合法指纹开门" },
{ "value": 46, "label": "非法指纹开门" },
{ "value": 48, "label": "远程开门" },
{ "value": 49, "label": "按钮开门" },
{ "value": 50, "label": "钥匙开门" },
{ "value": 51, "label": "合法刷卡开门" },
{ "value": 52, "label": "非法刷卡开门" },
{ "value": 53, "label": "门磁事件" },
{ "value": 54, "label": "异常开门" },
{ "value": 55, "label": "异常关门" },
{ "value": 56, "label": "正常关门" },
{ "value": 57, "label": "正常开门" },
{ "value": 59, "label": "对讲请求事件" },
{ "value": 61, "label": "人脸合法开门" },
{ "value": 62, "label": "人脸非法开门" },
{ "value": 1421, "label": "RFID有源合法" },
{ "value": 1422, "label": "RFID无源合法" },
{ "value": 1423, "label": "RFID有源非法" },
{ "value": 1424, "label": "RFID无源非法" },
{ "value": 1433, "label": "黑名单事件" },
{ "value": 1436, "label": "人证合法开门" },
{ "value": 1437, "label": "人证非法开门" },
{ "value": 1438, "label": "人证和身份证非法开门" },
{ "value": 1439, "label": "人证和身份证合法开门" },
{ "value": 1448, "label": "RFID感应事件" },
{ "value": 1449, "label": "RFID非法感应事件" },
{ "value": 1450, "label": "RFID按键事件" },
{ "value": 1451, "label": "RFID非法按键事件" },
{ "value": 1455, "label": "先刷卡后密码合法开门" },
{ "value": 1456, "label": "先刷卡后密码非法开门" },
{ "value": 1461, "label": "刷卡+指纹组合合法开门" },
{ "value": 1462, "label": "刷卡+指纹组合非法开门" },
{ "value": 1463, "label": "多人合法开门" },
{ "value": 1464, "label": "多人非法开门" },
{ "value": 1467, "label": "人员编号+密码合法开门" },
{ "value": 1468, "label": "人员编号+密码非法开门" },
{ "value": 1469, "label": "人脸+密码合法开门" },
{ "value": 1470, "label": "人脸+密码非法开门" },
{ "value": 1471, "label": "指纹+密码合法开门" },
{ "value": 1472, "label": "指纹+密码非法开门" },
{ "value": 1473, "label": "指纹+人脸合法开门" },
{ "value": 1474, "label": "指纹+人脸非法开门" },
{ "value": 1475, "label": "刷卡+人脸合法开门" },
{ "value": 1476, "label": "刷卡+人脸非法开门" },
{ "value": 1487, "label": "指纹+人脸+密码合法开门" },
{ "value": 1488, "label": "指纹+人脸+密码非法开门" },
{ "value": 1489, "label": "刷卡+人脸+密码合法开门" },
{ "value": 1490, "label": "刷卡+人脸+密码非法开门" },
{ "value": 1491, "label": "刷卡+指纹+密码合法开门" },
{ "value": 1492, "label": "刷卡+指纹+密码非法开门" },
{ "value": 1493, "label": "卡+指纹+人脸组合合法开门" },
{ "value": 1494, "label": "卡+指纹+人脸组合非法开门" },
{ "value": 4603, "label": "卡+指纹+人脸+密码组合合法开门" },
{ "value": 4604, "label": "卡+指纹+人脸+密码组合非法开门" },
{ "value": 4626, "label": "人脸+安全帽合法开门" },
{ "value": 4627, "label": "人脸+安全帽非法开门" },
{ "value": 10001, "label": "健康码合法开门" },
{ "value": 10002, "label": "异常健康码开门" }
]
}
return [
{ "value": 42, "label": "合法密码开门" },
{ "value": 43, "label": "非法密码开门" },
{ "value": 45, "label": "合法指纹开门" },
{ "value": 46, "label": "非法指纹开门" },
{ "value": 48, "label": "远程开门" },
{ "value": 49, "label": "按钮开门" },
{ "value": 50, "label": "钥匙开门" },
{ "value": 51, "label": "合法刷卡开门" },
{ "value": 52, "label": "非法刷卡开门" },
{ "value": 53, "label": "门磁事件" },
{ "value": 54, "label": "异常开门" },
{ "value": 55, "label": "异常关门" },
{ "value": 56, "label": "正常关门" },
{ "value": 57, "label": "正常开门" },
{ "value": 59, "label": "对讲请求事件" },
{ "value": 61, "label": "人脸合法开门" },
{ "value": 62, "label": "人脸非法开门" },
{ "value": 1421, "label": "RFID有源合法" },
{ "value": 1422, "label": "RFID无源合法" },
{ "value": 1423, "label": "RFID有源非法" },
{ "value": 1424, "label": "RFID无源非法" },
{ "value": 1433, "label": "黑名单事件" },
{ "value": 1436, "label": "人证合法开门" },
{ "value": 1437, "label": "人证非法开门" },
{ "value": 1438, "label": "人证和身份证非法开门" },
{ "value": 1439, "label": "人证和身份证合法开门" },
{ "value": 1448, "label": "RFID感应事件" },
{ "value": 1449, "label": "RFID非法感应事件" },
{ "value": 1450, "label": "RFID按键事件" },
{ "value": 1451, "label": "RFID非法按键事件" },
{ "value": 1455, "label": "先刷卡后密码合法开门" },
{ "value": 1456, "label": "先刷卡后密码非法开门" },
{ "value": 1461, "label": "刷卡+指纹组合合法开门" },
{ "value": 1462, "label": "刷卡+指纹组合非法开门" },
{ "value": 1463, "label": "多人合法开门" },
{ "value": 1464, "label": "多人非法开门" },
{ "value": 1467, "label": "人员编号+密码合法开门" },
{ "value": 1468, "label": "人员编号+密码非法开门" },
{ "value": 1469, "label": "人脸+密码合法开门" },
{ "value": 1470, "label": "人脸+密码非法开门" },
{ "value": 1471, "label": "指纹+密码合法开门" },
{ "value": 1472, "label": "指纹+密码非法开门" },
{ "value": 1473, "label": "指纹+人脸合法开门" },
{ "value": 1474, "label": "指纹+人脸非法开门" },
{ "value": 1475, "label": "刷卡+人脸合法开门" },
{ "value": 1476, "label": "刷卡+人脸非法开门" },
{ "value": 1487, "label": "指纹+人脸+密码合法开门" },
{ "value": 1488, "label": "指纹+人脸+密码非法开门" },
{ "value": 1489, "label": "刷卡+人脸+密码合法开门" },
{ "value": 1490, "label": "刷卡+人脸+密码非法开门" },
{ "value": 1491, "label": "刷卡+指纹+密码合法开门" },
{ "value": 1492, "label": "刷卡+指纹+密码非法开门" },
{ "value": 1493, "label": "卡+指纹+人脸组合合法开门" },
{ "value": 1494, "label": "卡+指纹+人脸组合非法开门" },
{ "value": 4603, "label": "卡+指纹+人脸+密码组合合法开门" },
{ "value": 4604, "label": "卡+指纹+人脸+密码组合非法开门" },
{ "value": 4626, "label": "人脸+安全帽合法开门" },
{ "value": 4627, "label": "人脸+安全帽非法开门" },
{ "value": 10001, "label": "健康码合法开门" },
{ "value": 10002, "label": "异常健康码开门" }
]
}
import usePermissionStore from '@/store/modules/permission'
const permissionStore = usePermissionStore()
export const meunList = () => {
let list = permissionStore.sidebarRouters.filter((item) => !item.hidden)
return list
}

@ -1,6 +1,6 @@
<script setup>
import { reactive,onMounted } from 'vue'
import { getRtspUrl,getDevicePage,getPlaybackByTimeRtspUrl,getRegularVideoRecords } from './api'
import { reactive, onMounted } from 'vue'
import { getRtspUrl, getDevicePage, getPlaybackByTimeRtspUrl, getRegularVideoRecords } from './api'
import { ElMessage } from 'element-plus'
const state = reactive({
@ -8,14 +8,14 @@ const state = reactive({
cameraList: [],
cameraInfo: null
})
const switchCamera = (index)=>{
const switchCamera = (index) => {
state.currentCameraIndex = index;
startVideo();
}
const startVideo = () => {
let index = state.currentCameraIndex;
let channelCode = state.cameraList[index].units && state.cameraList[index].units[0].channels[0].channelCode;
if(!channelCode){
if (!channelCode) {
ElMessage({
message: '设备异常',
type: 'error'
@ -28,24 +28,24 @@ const startVideo = () => {
dataType: "1",
streamType: "1"
}
}).then(res=>{
}).then(res => {
state.cameraInfo = {
channelId: channelCode,
url: res.data.url,
token: res.data.token
}
//
let video = document.getElementById('video')
let video = document.getElementById('video')
video.contentWindow.postMessage({
type: 'startVideo',
data: {...state.cameraInfo}
data: { ...state.cameraInfo }
}, '*')
})
}
const playRecord = (date) => {
let index = state.currentCameraIndex;
let channelCode = state.cameraList[index].units && state.cameraList[index].units[0].channels[0].channelCode;
if(!channelCode){
if (!channelCode) {
ElMessage({
message: '设备异常',
type: 'error'
@ -54,8 +54,8 @@ const playRecord = (date) => {
}
//
let current = new Date(date);
let startTime = parseInt(current.setHours(0, 0, 0, 0)/1000);
let endTime = parseInt(current.setHours(23, 59, 59, 999)/1000);
let startTime = parseInt(current.setHours(0, 0, 0, 0) / 1000);
let endTime = parseInt(current.setHours(23, 59, 59, 999) / 1000);
getRegularVideoRecords({
data: {
channelId: channelCode,
@ -65,7 +65,7 @@ const playRecord = (date) => {
streamType: "1",
recordType: "1"
}
}).then(res=>{
}).then(res => {
console.log('res :>> ', res);
let records = res.data.records;
getPlaybackByTimeRtspUrl({
@ -77,7 +77,7 @@ const playRecord = (date) => {
streamType: records[0].streamType,
recordType: records[0].recordType
}
}).then(res=>{
}).then(res => {
let recordInfo = {
records: records,
channelId: records[0].channelId,
@ -89,15 +89,15 @@ const playRecord = (date) => {
recordType: records[0].recordType
}
//
let video = document.getElementById('video')
console.log('video :>> ', video);
let video = document.getElementById('video')
console.log('video :>> ', video);
video.contentWindow.postMessage({
type: 'playRecord',
data: JSON.parse(JSON.stringify(recordInfo))
}, '*')
})
})
}
onMounted(() => {
getDevicePage({
@ -105,15 +105,18 @@ onMounted(() => {
"pageSize": 100,
}).then((res) => {
state.cameraList = res.data.pageData
const index = state.cameraList.findIndex(item => item.isOnline === 1);
state.currentCameraIndex = index
}).catch((err) => {
});
//
window.addEventListener('message', (event) => {
console.log('event :>> ', event.data);
if (event.data.type === 'startVideo') {
startVideo();
}else if(event.data.type ==='playRecord'){
} else if (event.data.type === 'playRecord') {
playRecord(event.data.date);
}
});
@ -122,59 +125,85 @@ onMounted(() => {
</script>
<template>
<div class="app-container">
<div class="app-containertwo">
<!-- 监控摄像头名称列表 -->
<div class="camera-name-list">
<template v-for="(camera, index) in state.cameraList" :key="index">
<span
class="camera-name"
@click="switchCamera(index)"
:class="{ active: state.currentCameraIndex === index }"
>
<!-- -->
<div :class="state.currentCameraIndex === index ? 'active' : ''" @click="switchCamera(index)" class="camera-item"
v-for="(camera, index) in state.cameraList" :key="index">
<div style="width:3.75rem;margin-right: 1.25rem;text-align: center;position: relative;">
<texttooltip :content="camera.deviceName" :class="state.currentCameraIndex === index ? 'wid202' : 'wid201'"
refName=" tooltipOverd"></texttooltip>
<el-tag style="scale: 0.7;position: absolute;top:-20px;right:-.9375rem;border-radius: 1.25rem;"
:type="camera.isOnline == 1 ? 'success' : 'danger'">{{ camera.isOnline == 1 ? '在线' : '离线' }}</el-tag>
</div>
</div>
<!-- <template v-for="(camera, index) in state.cameraList" :key="index">
<span class="camera-name" @click="switchCamera(index)" :class="{ active: state.currentCameraIndex === index }">
{{ camera.deviceName }}
<el-tag style="scale: 0.8;position: absolute;top: -10px;right:-15px;border-radius: 20px;" :type="camera.isOnline == 1 ? 'success':'danger'">{{ camera.isOnline == 1 ? '在线' : '离线' }}</el-tag>
</span>
</template>
</template> -->
</div>
<!-- 摄像头展示区域 -->
<div class="camera-display">
<iframe id="video" src="/dahua/demo.html?real=true" style="width:100%;height:100%;" frameborder="0"></iframe>
<!-- <video
v-if="state.currentCameraIndex !== -1"
:src="cameraList[state.currentCameraIndex].source"
controls
autoplay
muted
></video> -->
<!-- <p v-else>请选择摄像头</p> -->
<iframe v-if="state.cameraList.length > 0" id="video" src="/dahua/demo.html?real=true"
style="width:100%;height:100%;" frameborder="0"></iframe>
</div>
</div>
</template>
<style scoped>
.app-container {
.wid202 {
background: linear-gradient(90deg, #FFFFFF 0%, #FFF8C2 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
.wid201 {
background: linear-gradient(90deg, #FFFFFF 0%, #45B1FE 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
.camera-item {
cursor: pointer;
width: 100%;
background: url('../../assets/images/videoitembj.png') no-repeat;
background-size: 100% 100%;
/* margin-top: -1.25rem; */
display: flex;
flex-shrink: 0;
height: 3.125rem;
align-items: center;
justify-content: flex-end;
font-family: Source Han Sans CN, Source Han Sans CN;
font-weight: 400;
font-size: .875rem;
margin-bottom: .625rem;
color: #fff;
}
.app-containertwo {
display: flex;
flex-direction: row;
align-items: center;
padding: 20px;
height: calc(100vh - 135px);
height: 100%;
padding: 0;
}
.camera-name-list {
display: flex;
gap: 15px;
margin-bottom: 20px;
flex-wrap: wrap;
justify-content: center;
width: 130px;
width: 11.875rem;
height: 100%;
overflow-y: auto;
margin-right: 1.25rem;
overflow-y: auto;
overflow-x: hidden;
}
.camera-name {
padding: 8px 32px;
border: 1px solid #ccc;
border-radius: 20px;
padding: .5rem 2rem;
border: .0625rem solid #ccc;
border-radius: 1.25rem;
cursor: pointer;
transition: all 0.3s ease;
background-color: white;
@ -183,23 +212,21 @@ onMounted(() => {
.camera-name:hover {
background-color: #e0e0e0;
transform: translateY(-2px);
transform: translateY(-.125rem);
}
.camera-name.active {
background-color: #2196F3;
.active {
background: url('../../assets/images/videoitembjtwo.png') no-repeat;
background-size: 100% 100%;
/* background-color: #2196F3;
color: white;
border-color: #2196F3;
border-color: #2196F3; */
}
.camera-display {
width: 100%;
height: 100%;
box-sizing: border-box;
background-color: #fff;
padding: 20px;
border-radius: 8px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}
video {
@ -210,6 +237,6 @@ video {
p {
text-align: center;
color: #666;
font-size: 18px;
font-size: 1.125rem;
}
</style>

Loading…
Cancel
Save