Commit 829acf34 authored by 郭铭瑶's avatar 郭铭瑶 🤘

接入电梯视频及发现统计数据

parent 432b0f00
......@@ -51,7 +51,7 @@ export default {
GET_PUBLICSAFE_TRUE_COMPANY:
'/service-special-nandong/public/company/statistical', // 公共安全-右侧-实有单位
GET_PUBLICSAFE_SOS_MATERIAL:
'/service-special-nandong/public/emergencySupplies', // 公共安全-右侧-应急物资储备
'/service-special-nandong/public/emergencySupplies/1', // 公共安全-右侧-应急物资储备
GET_PUBLICSAFE_OUTHOUSEWALL:
'/service-special-nandong/public/inspection/statistical', // 公共安全-右侧-房屋外立面
GET_PUBLICSAFE_BUILDINGS: '/service-special-nandong/public/inspections', // 公共安全-右侧-重点关注楼宇
......@@ -65,7 +65,7 @@ export default {
GET_PUBLICSAFE_STREETPOWER: '/service-special-nandong/public/workstations', // 网格工作站(原名街道力量)
GET_GRIDPOWER: '/service-special-nandong/public/workstationDepartments', // 网格力量
GET_PUBLICSAFE_PARTY: '/service-special-nandong/public/partyConstruction/1', // 党建
GET_PUBLICSAFE_ECONOMIC: '/service-special-nandong/public/economic', // 经济
GET_PUBLICSAFE_ECONOMIC: '/service-special-nandong/public/economic/1', // 经济
/** 小区屏 */
GET_COMMUNITY_IDS: '/service-special-nandong/public/getSectIdList', // 获取小区id列表
......@@ -127,4 +127,17 @@ export default {
'/service-special-nandong/public/beautifulHome/threeYearStatistics', // 美丽家园项目实施情况
GET_EVENTS: '/service-special-nandong/public/compairs', // 事件
GET_WISDOM_OLD: '/service-special-nandong/public/wisdom/0', // 智慧养老
GET_FOCUS_WORK: '/service-special-nandong/public/focusWorks', // 重点工作
/** 新版小区屏 */
GET_MONITOR:
'http://yapi.omniview.pro/mock/377/service-special-nandong/public/equipments/0', // 获取监控设备
GET_VIDEO_URL:
'http://yapi.omniview.pro/mock/377/service-special-nandong/public/video/{id}', // 根据设备id获取视频流
GET_DISCOVER_SUM:
'http://yapi.omniview.pro/mock/377/service-special-nandong/public/discover/method/count', // 发现方式统计
GET_DISCOVER_STATISTICS:
'http://yapi.omniview.pro/mock/377/service-special-nandong/public/discover/category/count', // 发现数据
GET_DISCOVER_COUNT:
'http://yapi.omniview.pro/mock/377/service-special-nandong/public/discover/count', // 今日及历史发现数
}
<template>
<div class="video-component">
<video v-if="isM3U8" ref="videoRef" class="video" :controls="controls">
您的浏览器不支持播放此视频。
</video>
<video
v-if="isM3U8"
ref="videoRef"
v-else-if="isMP4"
class="video"
autoplay="autoplay"
controls
:autoplay="autoplay"
:controls="controls"
>
您的浏览器不支持播放此视频。
</video>
<video v-else-if="isMP4" class="video" autoplay="autoplay" controls>
<source :src="videoSrc" type="video/mp4" />
</video>
<iframe v-else class="video" :src="videoSrc" frameborder="0" />
......@@ -34,6 +33,14 @@ export default defineComponent({
type: String as PropType<string>,
required: true,
},
autoplay: {
type: String as PropType<string>,
default: 'autoplay',
},
controls: {
type: Boolean as PropType<boolean>,
default: true,
},
},
setup(props) {
const videoRef = ref<any | null>(null)
......@@ -54,12 +61,16 @@ export default defineComponent({
hls.loadSource(props.videoSrc)
hls.attachMedia(videoRef.value)
hls.on(Hls.Events.MANIFEST_PARSED, () => {
videoRef.value.play()
if (props.autoplay === 'autoplay') {
videoRef.value.play()
}
})
} else if (videoRef.value.canPlayType('application/vnd.apple.mpegurl')) {
videoRef.value.src = props.videoSrc
videoRef.value.addEventListener('canplay', () => {
videoRef.value.play()
if (props.autoplay === 'autoplay') {
videoRef.value.play()
}
})
}
}
......@@ -79,7 +90,8 @@ export default defineComponent({
<style lang="stylus" scoped>
.video-component
.video
width 100%
height 100%
.video
width 100%
</style>
......@@ -219,11 +219,11 @@ export default defineComponent({
return [
{
name: '商办空置率',
value: economic.value.vacancyRate.split('%')[0] || 0,
value: economic.value.vacancyRate || 0,
},
{
name: '综合商业体使用率',
value: economic.value.useRate.split('%')[0] || 0,
value: economic.value.useRate || 0,
},
]
})
......
<template>
<m-card class="card" title="场景监控视频">
<div class="nav">
<a-select
<!-- <a-select
v-model:value="curScene"
dropdown-class-name="community-video-selector-drop-down"
>
......@@ -12,14 +12,14 @@
>
{{ option.name }}
</a-select-option>
</a-select>
</a-select> -->
<a-select
v-model:value="curAddress"
dropdown-class-name="community-video-selector-drop-down"
>
<a-select-option
v-for="option in addresses"
:key="option.value"
v-for="(option, i) in addresses"
:key="i + '-' + option.value"
:value="option.value"
>
{{ option.name }}
......@@ -27,7 +27,7 @@
</a-select>
</div>
<div class="community-video">
<div
<!-- <div
v-for="item in list"
:key="item.name"
:style="`background:url(${
......@@ -42,7 +42,26 @@
<div class="mask">
<img src="@/assets/images/play.png" />
</div>
</div>
</div> -->
<template v-if="videoList.length > 0">
<div
v-for="item in videoList.slice(0, 3)"
:key="item.name"
@click="handleClick(item.video)"
>
<VideoComponent
v-if="item.video"
:video-src="item.video"
autoplay="none"
:controls="false"
/>
<p>{{ item.name }}</p>
<div class="mask">
<img src="@/assets/images/play.png" />
</div>
</div>
</template>
<m-empty v-else />
</div>
</m-card>
<m-modal v-model="showModal" title="视频" width="30%" offset="-70%">
......@@ -51,7 +70,7 @@
</template>
<script lang="ts">
import { computed, defineComponent, ref } from 'vue'
import { computed, defineComponent, ref, watch } from 'vue'
// import photo1 from '@/assets/images/community1.png'
// import photo2 from '@/assets/images/community2.png'
// import photo3 from '@/assets/images/community3.png'
......@@ -59,7 +78,7 @@ import { computed, defineComponent, ref } from 'vue'
import VideoComponent from '../components/video-component.vue'
import store from '@/store'
import { useRoute } from 'vue-router'
import { api } from '@/ajax'
import { ajax, api } from '@/ajax'
export default defineComponent({
name: 'CommunityPhoto',
......@@ -86,64 +105,111 @@ export default defineComponent({
const curId = computed(
() => (route && route.query.id) || store.state.communityOptions[0].type
)
const list = computed(() => {
if (curId.value === '527635870583459840') {
// 振兴小区
return [
{
name: '重庆北路后门',
photo:
'http://zhongbang.omniview.pro/file/group1/M00/00/30/CgAG5WB9AXyAIUKZAAIFC2qNmKI384.jpg',
video:
'http://zhongbang.omniview.pro/file/group1/M00/00/1A/CgAG5GB9PlmAH8-oAEmHxWhriqw954.mov',
},
{
name: '大沽路大门',
photo:
'http://zhongbang.omniview.pro/file/group1/M00/00/30/CgAG5WB9AYmAT-A1AAMElShNriM149.jpg',
video:
'http://zhongbang.omniview.pro/file/group1/M00/00/1A/CgAG5GB9QE6AckoPAEM3swvgmFQ182.mov',
},
{
name: '重庆北路177弄64号',
photo:
'http://zhongbang.omniview.pro/file/group1/M00/00/30/CgAG5WB9AQCAEc3pAASC2UqtXWs052.jpg',
video:
'http://zhongbang.omniview.pro/file/group1/M00/00/30/CgAG5WB9AVyAanZkApsdVDHEGc0527.mp4',
},
]
}
return [
{
name: '62弄朝北',
photo:
'http://zhongbang.omniview.pro/file/group1/M00/00/1A/CgAG5GB5GdOAW6qQAAvNhxSqO-g179.jpg',
video:
'http://zhongbang.omniview.pro/file/group1/M00/00/30/CgAG5WB9OkmAFxVMAS7MAmRH2Xc004.mp4',
const list = ref<any[]>([])
ajax
.get({
url: api.GET_MONITOR,
params: {
communityId: curId.value || undefined,
pageSize: 9000,
},
{
name: '62弄朝东',
photo:
'http://zhongbang.omniview.pro/file/group1/M00/00/30/CgAG5WB5Kj-AX3OMAAwPqHZi_Kg064.jpg',
video:
'http://zhongbang.omniview.pro/file/group1/M00/00/30/CgAG5WB9QIiAaz9fAS3gvWsrxYQ927.mp4',
},
{
name: '62弄朝南',
photo:
'http://zhongbang.omniview.pro/file/group1/M00/00/1A/CgAG5GB5KrOAVcluAAnbZjB7fNA165.jpg',
video:
'http://zhongbang.omniview.pro/file/group1/M00/00/1A/CgAG5GB9P1mALYigATKoQQw6Y8k841.mp4',
},
]
})
})
.then((res) => {
list.value = (res?.data?.content || []).map((item: any) => ({
name: item.buildingAddr,
...item,
}))
addresses.value.push(
...list.value.map((item: any) => ({
name: item.buildingAddr,
value: item.buildingAddr,
}))
)
Promise.all(
list.value.map((item) =>
ajax.get({
url: api.GET_VIDEO_URL.replace('{id}', item.id),
})
)
).then((res) => {
const urls = res.map((item) => item?.data?.content || null)
list.value.forEach((item, i) => {
item.video = urls[i]
})
videoList.value = [...list.value]
})
})
// const list = computed(() => {
// if (curId.value === '527635870583459840') {
// // 振兴小区
// return [
// {
// name: '重庆北路后门',
// photo:
// 'http://zhongbang.omniview.pro/file/group1/M00/00/30/CgAG5WB9AXyAIUKZAAIFC2qNmKI384.jpg',
// video:
// 'http://zhongbang.omniview.pro/file/group1/M00/00/1A/CgAG5GB9PlmAH8-oAEmHxWhriqw954.mov',
// },
// {
// name: '大沽路大门',
// photo:
// 'http://zhongbang.omniview.pro/file/group1/M00/00/30/CgAG5WB9AYmAT-A1AAMElShNriM149.jpg',
// video:
// 'http://zhongbang.omniview.pro/file/group1/M00/00/1A/CgAG5GB9QE6AckoPAEM3swvgmFQ182.mov',
// },
// {
// name: '重庆北路177弄64号',
// photo:
// 'http://zhongbang.omniview.pro/file/group1/M00/00/30/CgAG5WB9AQCAEc3pAASC2UqtXWs052.jpg',
// video:
// 'http://zhongbang.omniview.pro/file/group1/M00/00/30/CgAG5WB9AVyAanZkApsdVDHEGc0527.mp4',
// },
// ]
// }
// return [
// {
// name: '62弄朝北',
// photo:
// 'http://zhongbang.omniview.pro/file/group1/M00/00/1A/CgAG5GB5GdOAW6qQAAvNhxSqO-g179.jpg',
// video:
// 'http://zhongbang.omniview.pro/file/group1/M00/00/30/CgAG5WB9OkmAFxVMAS7MAmRH2Xc004.mp4',
// },
// {
// name: '62弄朝东',
// photo:
// 'http://zhongbang.omniview.pro/file/group1/M00/00/30/CgAG5WB5Kj-AX3OMAAwPqHZi_Kg064.jpg',
// video:
// 'http://zhongbang.omniview.pro/file/group1/M00/00/30/CgAG5WB9QIiAaz9fAS3gvWsrxYQ927.mp4',
// },
// {
// name: '62弄朝南',
// photo:
// 'http://zhongbang.omniview.pro/file/group1/M00/00/1A/CgAG5GB5KrOAVcluAAnbZjB7fNA165.jpg',
// video:
// 'http://zhongbang.omniview.pro/file/group1/M00/00/1A/CgAG5GB9P1mALYigATKoQQw6Y8k841.mp4',
// },
// ]
// })
const curScene = ref('all')
const curAddress = ref('all')
const scenes = [{ name: '全部场景', value: 'all' }]
const addresses = [{ name: '全部地址', value: 'all' }]
const addresses = ref([{ name: '全部地址', value: 'all' }])
const videoList = ref<any[]>([])
watch(
() => curAddress.value,
(address: string) => {
if (address === 'all') {
videoList.value = list.value
} else {
videoList.value = list.value.filter(
(item) => item.buildingAddr === address
)
}
}
)
return {
prefix,
list,
videoList,
handleClick,
showModal,
src,
......@@ -159,33 +225,27 @@ export default defineComponent({
<style lang="stylus" scoped>
@import '../../components/MyComponent/main.styl'
.card
:deep(.card-content)
display flex
flex-direction column
justify-content space-between
overflow hidden
.nav
display flex
justify-content space-between
margin .04rem 0
padding 0 .06rem
>div
width 48%
width 100%
.community-video
flex 1
display flex
flex-direction column
justify-content space-between
padding .05rem
box-sizing border-box
overflow hidden
>div
height 32%
height 1.68rem
// width 100%
position relative
cursor pointer
margin-bottom .05rem
overflow hidden
.mask
$center()
display flex
position absolute
top 0
left 0
width 100%
height 100%
opacity 0.8
......@@ -203,8 +263,8 @@ export default defineComponent({
transform scale(1.2) rotate(360deg)
>p
position absolute
bottom .05rem
right @bottom
top .05rem
left @top
padding .04rem .1rem
border-radius .14rem
color #fff
......
......@@ -62,38 +62,98 @@
</template>
<script lang="ts" setup>
import { ref } from 'vue'
import { ajax, api } from '@/ajax'
import c1 from '@/assets/images/c1.png'
import c2 from '@/assets/images/c2.png'
const sum = [
const sum = ref([
{
name: '今日预警数量',
value: 3,
value: 0,
},
{
name: '历史预警数量',
value: 41,
value: 0,
},
{
name: '预警类型',
value: 5,
value: 0,
},
]
const sub = [
{ name: '视频识别', value: 2 },
{ name: '物联感知', value: 2 },
{ name: '数据关联分析', value: 2 },
{ name: '数据统计预警', value: 1 },
]
const list = [
{ name: '电瓶车入库', value: 38 },
{ name: '垃圾暴露', value: 5 },
{ name: '占用消防通道', value: 2 },
{ name: '垃圾满溢', value: 28 },
{ name: '高叠隐患', value: 2 },
{ name: '易积水预警', value: 19 },
{ name: '群租', value: 16 },
]
])
ajax
.get({
url: api.GET_DISCOVER_COUNT,
})
.then((res) => {
const { year = 0, today = 0 } = res?.data?.content || {}
sum.value = [
{
name: '今日预警数量',
value: today,
},
{
name: '历史预警数量',
value: year,
},
{
name: '预警类型',
value: 0,
},
]
})
const sub = ref([
{ name: '视频识别', value: 0 },
{ name: '物联感知', value: 0 },
{ name: '数据关联分析', value: 0 },
{ name: '人为发现', value: 0 },
])
ajax
.get({
url: api.GET_DISCOVER_SUM,
})
.then((res) => {
const {
person = 0, //人为发现
iot = 0, //物联感知
video = 0, //视频识别
analyze = 0, //数据分析
} = res?.data?.content || {}
sub.value = [
{ name: '视频识别', value: video },
{ name: '物联感知', value: iot },
{ name: '数据关联分析', value: analyze },
{ name: '人为发现', value: person },
]
})
const list = ref([
{ name: '电瓶车入梯', value: 0 },
{ name: '垃圾暴露', value: 0 },
{ name: '占用消防通道', value: 0 },
{ name: '垃圾满溢', value: 0 },
{ name: '高叠隐患', value: 0 },
// { name: '易积水预警', value: 0 },
{ name: '群租', value: 0 },
])
ajax
.get({
url: api.GET_DISCOVER_STATISTICS,
})
.then((res) => {
const {
fire = 0, //消防通道
batteryCar = 0, //电瓶车入梯
overflowingGarbage = 0, //垃圾满溢
groupRent = 0, //群租
} = res?.data?.content || {}
list.value = [
{ name: '电瓶车入梯', value: batteryCar },
{ name: '垃圾暴露', value: 0 },
{ name: '占用消防通道', value: fire },
{ name: '垃圾满溢', value: overflowingGarbage },
{ name: '高叠隐患', value: 0 },
{ name: '群租', value: groupRent },
]
})
const events = [
{
name: '占用消防通道',
......@@ -198,7 +258,7 @@ i.dot
flex-direction column
overflow hidden
.events
height 3.4rem
height 3.7rem
overflow hidden
.event-item
height .74rem
......
......@@ -12,11 +12,12 @@ import {
shallowRef,
onMounted,
PropType,
nextTick,
onBeforeUnmount,
ref,
} from 'vue'
import { init as initChart, ECharts } from 'echarts/core'
import 'echarts-wordcloud'
import { ajax, api } from '@/ajax'
export default defineComponent({
name: 'KeyTask',
......@@ -45,34 +46,34 @@ export default defineComponent({
]
},
},
data: {
type: Array as PropType<{ name: string; value: number }[]>,
default: () => {
return [
{ name: '明厨亮灶', value: 100 * Math.random() },
{ name: '民宿群租', value: 100 * Math.random() },
{ name: '垃圾分类', value: 120 },
{ name: '小型工程纳管', value: 100 * Math.random() },
{ name: '非机动车停放', value: 100 * Math.random() },
{ name: '马桶改造', value: 100 * Math.random() },
{ name: '电梯加装', value: 100 * Math.random() },
{ name: '居改非', value: 100 * Math.random() },
{ name: '无证无照整治', value: 100 * Math.random() },
{ name: '楼道堆物', value: 100 * Math.random() },
{ name: '党建联建', value: 100 * Math.random() },
{ name: '动迁改造', value: 100 * Math.random() },
{ name: '文明城区创建', value: 120 },
// { name: '重塑老城厢', value: 100 * Math.random() },
{ name: '推动商旅文联动', value: 100 * Math.random() },
{ name: '水环境治理', value: 100 * Math.random() },
{ name: '供水防涝', value: 100 * Math.random() },
{ name: '美丽街区', value: 100 * Math.random() },
{ name: '美丽家园', value: 100 * Math.random() },
{ name: '非机动车安全管理', value: 100 * Math.random() },
{ name: '房屋隐患排查', value: 100 * Math.random() },
]
},
},
// data: {
// type: Array as PropType<{ name: string; value: number }[]>,
// default: () => {
// return [
// { name: '明厨亮灶', value: 100 * Math.random() },
// { name: '民宿群租', value: 100 * Math.random() },
// { name: '垃圾分类', value: 120 },
// { name: '小型工程纳管', value: 100 * Math.random() },
// { name: '非机动车停放', value: 100 * Math.random() },
// { name: '马桶改造', value: 100 * Math.random() },
// { name: '电梯加装', value: 100 * Math.random() },
// { name: '居改非', value: 100 * Math.random() },
// { name: '无证无照整治', value: 100 * Math.random() },
// { name: '楼道堆物', value: 100 * Math.random() },
// { name: '党建联建', value: 100 * Math.random() },
// { name: '动迁改造', value: 100 * Math.random() },
// { name: '文明城区创建', value: 120 },
// // { name: '重塑老城厢', value: 100 * Math.random() },
// { name: '推动商旅文联动', value: 100 * Math.random() },
// { name: '水环境治理', value: 100 * Math.random() },
// { name: '供水防涝', value: 100 * Math.random() },
// { name: '美丽街区', value: 100 * Math.random() },
// { name: '美丽家园', value: 100 * Math.random() },
// { name: '非机动车安全管理', value: 100 * Math.random() },
// { name: '房屋隐患排查', value: 100 * Math.random() },
// ]
// },
// },
show: {
type: Boolean as PropType<boolean>,
default: false,
......@@ -86,6 +87,7 @@ export default defineComponent({
const sizeRate = computed(() => Math.floor((screen.height * 1.6) / 100))
const cloudRef = shallowRef<HTMLElement | null>(null)
const myChart = shallowRef<ECharts | null>(null)
const data = ref<any[]>([])
const init = () => {
if (!cloudRef.value) return
myChart.value = initChart(cloudRef.value)
......@@ -97,7 +99,7 @@ export default defineComponent({
series: [
{
type: 'wordCloud',
sizeRange: [sizeRate.value, sizeRate.value * 2.2],
sizeRange: [sizeRate.value, sizeRate.value * 2],
rotationRange: [0, 90],
rotationStep: 45,
gridSize: sizeRate.value,
......@@ -105,14 +107,14 @@ export default defineComponent({
width: '100%',
height: '100%',
textStyle: {
color: function ({ data }: { data: any }) {
color: function (item: any) {
// const index = Math.floor(Math.random() * props.color.length)
// return props.color[index]
return `rgba(255,255,255,${data.value / 120})`
return `rgba(255,255,255,${(item?.data?.value || 0) / 100})`
},
fontWeight: 550,
},
data: props.data,
data: data.value,
},
],
}
......@@ -135,10 +137,22 @@ export default defineComponent({
watch(
() => props.show,
async (type) => {
(type) => {
if (!type) return
await nextTick()
init()
ajax
.get({
url: api.GET_FOCUS_WORK,
params: { pageSize: 9000 },
showLoading: false,
})
.then((res) => {
const { content = [] } = res?.data || {}
data.value = content.map((item: any) => ({
name: item.focusWorkName,
value: +item.showRate || 0,
}))
init()
})
},
{ immediate: true }
)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment