feat:对接景区数据和监控视频
This commit is contained in:
@@ -3,22 +3,22 @@ import request from './request'
|
|||||||
// 部门列表
|
// 部门列表
|
||||||
export function getComDeptsApi() {
|
export function getComDeptsApi() {
|
||||||
return request({
|
return request({
|
||||||
url: '/api/largeScreen/com/depts',
|
url: '/fjtcc-api/api/largeScreen/com/depts',
|
||||||
method: 'get'
|
method: 'get'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
// 部门成员
|
// 部门成员
|
||||||
export function getComDeptUsersApi(data) {
|
export function getComDeptUsersApi(data) {
|
||||||
return request({
|
return request({
|
||||||
url: '/api/largeScreen/com/deptUsers',
|
url: '/fjtcc-api/api/largeScreen/com/deptUsers',
|
||||||
method: 'get',
|
method: 'get',
|
||||||
params: data
|
params: data
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
// 最近联系
|
// 最近联系
|
||||||
export function getComRecordApi() {
|
export function getComRecordApi() {
|
||||||
return request({
|
return request({
|
||||||
url: '/api/largeScreen/com/record',
|
url: '/fjtcc-api/api/largeScreen/com/record',
|
||||||
method: 'get'
|
method: 'get'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -4,7 +4,7 @@
|
|||||||
<ul class="list">
|
<ul class="list">
|
||||||
<li
|
<li
|
||||||
class="item"
|
class="item"
|
||||||
:style="{ backgroundImage: `url(${index == 0 ? primary : error})` }"
|
:style="{ backgroundImage: `url(${primary})` }"
|
||||||
v-for="(item, index) in list"
|
v-for="(item, index) in list"
|
||||||
:key="index"
|
:key="index"
|
||||||
@click.shop="handleItem(item)"
|
@click.shop="handleItem(item)"
|
||||||
|
|||||||
@@ -1,20 +1,17 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="box-4-content">
|
<div class="correspondence">
|
||||||
<div class="top-box">
|
<div class="top-box">
|
||||||
<div class="title">融合通信</div>
|
<div class="title">融合通信</div>
|
||||||
<div class="icon-box flex">
|
<div class="icon-box flex">
|
||||||
<div class="item"
|
<div
|
||||||
@click="handleDepsUser(item.id,item)"
|
class="item"
|
||||||
v-for="(item,index) in deptsList"
|
v-for="item in deptsList"
|
||||||
:key="item.id">
|
:key="item.id"
|
||||||
<img src="/src/assets/images/r-icon-1.png" />
|
@click="handleDepsUser(item.id, item)"
|
||||||
<view class="item-name">{{item.name}}</view>
|
>
|
||||||
</div>
|
<img src="/src/assets/images/r-icon-1.png" />
|
||||||
<!-- <div class="item"><img src="/src/assets/images/r-icon-2.png" />三峡之颠</div>
|
<view class="item-name">{{ item.name }}</view>
|
||||||
<div class="item"><img src="/src/assets/images/r-icon-3.png" />龙桥河</div>
|
</div>
|
||||||
<div class="item"><img src="/src/assets/images/r-icon-4.png" />消防队</div>
|
|
||||||
<div class="item"><img src="/src/assets/images/r-icon-5.png" />文旅城</div>
|
|
||||||
<div class="item"><img src="/src/assets/images/r-icon-6.png" />交通城</div> -->
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="bom-box">
|
<div class="bom-box">
|
||||||
@@ -23,107 +20,99 @@
|
|||||||
<div class="header">
|
<div class="header">
|
||||||
<div>人员姓名</div>
|
<div>人员姓名</div>
|
||||||
<div>部门</div>
|
<div>部门</div>
|
||||||
<div>职位</div>
|
|
||||||
<div>时间</div>
|
<div>时间</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="list">
|
<div class="list">
|
||||||
<div class="item" v-for="(item, index) in recordList" :key="index">
|
<div class="item" v-for="(item, index) in recordList" :key="index">
|
||||||
<div>{{item.nickname}}</div>
|
<div>{{ item.nickname }}</div>
|
||||||
<div>{{item.department}}</div>
|
<div>{{ item.department }}</div>
|
||||||
<div>{{item.postion}}</div>
|
<div>{{ item.time }}</div>
|
||||||
<div>{{item.time}}</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<el-dialog :title="gridTitle" center v-model="dialogTableVisible">
|
<el-dialog :title="gridTitle" center v-model="dialogTableVisible">
|
||||||
<div class="bom-box">
|
<div class="bom-box">
|
||||||
<div class="table">
|
<div class="table">
|
||||||
<div class="header">
|
<div class="header">
|
||||||
<div>姓名</div>
|
<div>姓名</div>
|
||||||
<div>部门</div>
|
<div>部门</div>
|
||||||
<div>职位</div>
|
<div>职位</div>
|
||||||
<div>电话号码</div>
|
<div>电话号码</div>
|
||||||
<div>操作</div>
|
<div>操作</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="list">
|
<div class="list">
|
||||||
<div class="item" v-for="(item, index) in gridData" :key="index">
|
<div class="item" v-for="(item, index) in gridData" :key="index">
|
||||||
<div>{{item.nickName}}</div>
|
<div>{{ item.nickName }}</div>
|
||||||
<div>{{item.depthName}}</div>
|
<div>{{ item.depthName }}</div>
|
||||||
<div>{{item.postName}}</div>
|
<div>{{ item.postName }}</div>
|
||||||
<div>{{item.phoneNumber}}</div>
|
<div>{{ item.phoneNumber }}</div>
|
||||||
<div>
|
<div>
|
||||||
<img class="sp-ico" src="@/assets/images/sp-icom.png" />
|
<img class="sp-ico" src="@/assets/images/sp-icom.png" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { useRouter } from 'vue-router'
|
import { getComDeptsApi, getComDeptUsersApi, getComRecordApi } from '@/api/common'
|
||||||
import { getComDeptsApi,getComDeptUsersApi,getComRecordApi } from '@/api/common'
|
|
||||||
let deptsList = ref([])
|
let deptsList = ref([])
|
||||||
let dialogTableVisible = ref(false)
|
let dialogTableVisible = ref(false)
|
||||||
const getComDepts = async()=>{
|
const getComDepts = async () => {
|
||||||
let res = await getComDeptsApi()
|
let res = await getComDeptsApi()
|
||||||
deptsList.value = res.data
|
deptsList.value = res.data
|
||||||
}
|
}
|
||||||
let recordList = ref([])
|
let recordList = ref([])
|
||||||
const getComRecord = async()=>{
|
const getComRecord = async () => {
|
||||||
let res = await getComRecordApi()
|
let res = await getComRecordApi()
|
||||||
recordList.value = res.data
|
recordList.value = res.data
|
||||||
}
|
}
|
||||||
let gridData = ref([])
|
let gridData = ref([])
|
||||||
let gridTitle = ref('')
|
let gridTitle = ref('')
|
||||||
const handleDepsUser = async(id,item)=>{
|
const handleDepsUser = async (id, item) => {
|
||||||
gridTitle.value = item.name
|
gridTitle.value = item.name
|
||||||
let res = await getComDeptUsersApi({id})
|
dialogTableVisible.value = true
|
||||||
gridData.value = res.data
|
let res = await getComDeptUsersApi({ id })
|
||||||
dialogTableVisible.value = true
|
gridData.value = res.data
|
||||||
console.log(gridData.value,'getcomdepts')
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
getComDepts()
|
getComDepts()
|
||||||
getComRecord()
|
getComRecord()
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
<style>
|
<style>
|
||||||
.el-dialog {
|
.el-dialog {
|
||||||
background:url('/src/assets/images/map-bg-2.png') no-repeat top center;
|
background: url('/src/assets/images/map-bg-2.png') no-repeat top center;
|
||||||
background-size: 100% 100%;
|
background-size: 100% 100%;
|
||||||
}
|
}
|
||||||
.el-dialog__title{
|
.el-dialog__title {
|
||||||
color:#fff;
|
color: #fff;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.sp-ico{
|
.sp-ico {
|
||||||
width:vw(50);
|
width: vw(40);
|
||||||
// height:vh(30);
|
}
|
||||||
}
|
.item-name {
|
||||||
.item-name{
|
width: 90%;
|
||||||
overflow: hidden;
|
text-align: center;
|
||||||
text-overflow: ellipsis;
|
}
|
||||||
white-space: nowrap;
|
.sp-img {
|
||||||
width:100%;
|
width: vw(100);
|
||||||
}
|
}
|
||||||
.sp-img{
|
.correspondence {
|
||||||
width:vw(100);
|
|
||||||
}
|
|
||||||
.box-4-content {
|
|
||||||
position: relative;
|
|
||||||
margin: vw(8);
|
margin: vw(8);
|
||||||
width: vw(300);
|
width: vw(300);
|
||||||
height: vh(1060);
|
height: vh(1070);
|
||||||
background-image: url('@/assets/images/bg-1.png');
|
background-image: url('@/assets/images/bg-1.png');
|
||||||
background-size: 100% 100%;
|
background-size: 100% 100%;
|
||||||
|
|
||||||
}
|
}
|
||||||
.bom-box {
|
.bom-box {
|
||||||
.table {
|
.table {
|
||||||
@@ -211,7 +200,8 @@
|
|||||||
line-height: vh(16);
|
line-height: vh(16);
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
.item {
|
.item {
|
||||||
width: 33.33%;
|
cursor: pointer;
|
||||||
|
width: 50%;
|
||||||
margin-top: vh(40);
|
margin-top: vh(40);
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|||||||
@@ -71,13 +71,13 @@
|
|||||||
formatter: (e) => {
|
formatter: (e) => {
|
||||||
let valueStr = ''
|
let valueStr = ''
|
||||||
e.map((item) => {
|
e.map((item) => {
|
||||||
valueStr += `<div>${item.seriesName}:${item.value}</div>`
|
valueStr += `<div>${item.axisValueLabel}:${item.value}</div>`
|
||||||
})
|
})
|
||||||
let str = `<div style="
|
let str = `<div style="
|
||||||
background: #07356B;
|
background: #07356B;
|
||||||
border: 1px solid #0096FF;
|
border: 1px solid #0096FF;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
font-weight: 600;
|
font-weight: bold;
|
||||||
font-size: ${fitChartSize(16)}px;
|
font-size: ${fitChartSize(16)}px;
|
||||||
border-radius: ${fitChartSize(4)}px;
|
border-radius: ${fitChartSize(4)}px;
|
||||||
padding: ${fitChartSize(4)}px ${fitChartSize(12)}px;">
|
padding: ${fitChartSize(4)}px ${fitChartSize(12)}px;">
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
class="video-item"
|
class="video-item"
|
||||||
v-for="(item, index) in videoList"
|
v-for="(item, index) in videoList"
|
||||||
:key="index"
|
:key="index"
|
||||||
@click="handleItemVideo(item.hlsUrl, item.cameraName, item.updateTime)"
|
@click="handleItemVideo(item.hlsUrl, 100)"
|
||||||
>
|
>
|
||||||
<div class="video-item__inner">
|
<div class="video-item__inner">
|
||||||
<video
|
<video
|
||||||
@@ -25,13 +25,8 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="video-detail" v-if="videoLog == 2">
|
<div class="video-detail" v-if="videoLog == 2">
|
||||||
<div class="video-detail__wrapper v-error-bg">
|
<div class="video-detail__wrapper">
|
||||||
<div class="video-detail__title">
|
|
||||||
<span>{{ videoTitle }}</span>
|
|
||||||
<span>{{ videoUpdateTime }}</span>
|
|
||||||
</div>
|
|
||||||
<video
|
<video
|
||||||
class="video-detail__video"
|
class="video-detail__video"
|
||||||
ref="videoRef"
|
ref="videoRef"
|
||||||
@@ -43,16 +38,39 @@
|
|||||||
<source src="" type="application/x-mpegURL" />
|
<source src="" type="application/x-mpegURL" />
|
||||||
</video>
|
</video>
|
||||||
</div>
|
</div>
|
||||||
<!-- <div class="video-rt">
|
<div class="video-right">
|
||||||
<div class="title">
|
<div class="flex justify-between">
|
||||||
<span>最近联系</span>
|
<Title2 title="异常告警" />
|
||||||
</div>
|
<div class="back-box" @click="handleBack">
|
||||||
<div class="rt-v-box">
|
<img class="icon" src="@/assets/images/back.png" />
|
||||||
<div class="rt-video v-error-bg" v-for="item in 8">
|
<span>返回</span>
|
||||||
<div class="desc">核心路段:这是一条信息说明</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div> -->
|
<ul class="list">
|
||||||
|
<li
|
||||||
|
class="item"
|
||||||
|
v-for="(item, index) in videoList"
|
||||||
|
:key="index"
|
||||||
|
@click="handleItemVideo(item.hlsUrl, 101)"
|
||||||
|
>
|
||||||
|
<div>
|
||||||
|
<p class="item-title--primary">
|
||||||
|
{{ item.cameraName }}
|
||||||
|
</p>
|
||||||
|
<video
|
||||||
|
class="item-img"
|
||||||
|
:id="'monitorVideo' + index"
|
||||||
|
muted
|
||||||
|
autoplay
|
||||||
|
:controls="false"
|
||||||
|
style="object-fit: cover"
|
||||||
|
>
|
||||||
|
<source src="" type="application/x-mpegURL" />
|
||||||
|
</video>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -96,23 +114,41 @@
|
|||||||
|
|
||||||
let videoLog = ref(1)
|
let videoLog = ref(1)
|
||||||
let videoRef = ref()
|
let videoRef = ref()
|
||||||
let videoTitle = ref('')
|
|
||||||
let videoUpdateTime = ref('')
|
|
||||||
|
|
||||||
const handleItemVideo = (url, title, time) => {
|
const initVideo = () => {
|
||||||
|
nextTick(() => {
|
||||||
|
videoList.value.forEach(async (item, index) => {
|
||||||
|
const video = document.getElementById(`monitorVideo${index}`)
|
||||||
|
let res = await postRefreshApi({
|
||||||
|
type: 'hls',
|
||||||
|
businessVideoDisplayPosition: item.businessVideoDisplayPosition,
|
||||||
|
cameraIndexCode: item.cameraIndexCode
|
||||||
|
})
|
||||||
|
item.hlsUrl = res.data.hlsUrl
|
||||||
|
const hls = new Hls()
|
||||||
|
hls.loadSource(res.data.hlsUrl)
|
||||||
|
hls.attachMedia(video)
|
||||||
|
hls.on(Hls.Events.MANIFEST_PARSED, () => {
|
||||||
|
video.play()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
const handleBack = () => {
|
||||||
|
videoLog.value = 1
|
||||||
|
initVideo()
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleItemVideo = (url, type) => {
|
||||||
videoLog.value = 2
|
videoLog.value = 2
|
||||||
videoTitle.value = title
|
|
||||||
videoUpdateTime.value = time
|
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
const hls = new Hls()
|
const hls = new Hls()
|
||||||
console.log(url, '111')
|
|
||||||
console.log(videoRef.value, '222')
|
|
||||||
|
|
||||||
hls.loadSource(url)
|
hls.loadSource(url)
|
||||||
hls.attachMedia(videoRef.value)
|
hls.attachMedia(videoRef.value)
|
||||||
hls.on(Hls.Events.MANIFEST_PARSED, () => {
|
hls.on(Hls.Events.MANIFEST_PARSED, () => {
|
||||||
videoRef.value.play()
|
videoRef.value.play()
|
||||||
})
|
})
|
||||||
|
if (type == 100) initVideo()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
@@ -149,7 +185,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
&-item {
|
&-item {
|
||||||
width: vw(404);
|
width: vw(410);
|
||||||
height: vh(300);
|
height: vh(300);
|
||||||
padding: vw(10);
|
padding: vw(10);
|
||||||
background-image: url('/src/assets/images/item-primary.png');
|
background-image: url('/src/assets/images/item-primary.png');
|
||||||
@@ -195,8 +231,8 @@
|
|||||||
&-detail__wrapper {
|
&-detail__wrapper {
|
||||||
position: relative;
|
position: relative;
|
||||||
padding: vh(40) vw(50);
|
padding: vh(40) vw(50);
|
||||||
width: vw(1666);
|
width: vw(1660);
|
||||||
height: vh(950);
|
height: vh(960);
|
||||||
background-image: url('/src/assets/images/one-video-bg.png');
|
background-image: url('/src/assets/images/one-video-bg.png');
|
||||||
background-size: 100% 100%;
|
background-size: 100% 100%;
|
||||||
}
|
}
|
||||||
@@ -218,6 +254,90 @@
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
height: vh(880);
|
height: vh(880);
|
||||||
}
|
}
|
||||||
|
&-right {
|
||||||
|
margin-left: vw(8);
|
||||||
|
width: vw(440);
|
||||||
|
height: vh(956);
|
||||||
|
background: #082f5a;
|
||||||
|
.back-box {
|
||||||
|
cursor: pointer;
|
||||||
|
padding-right: vw(20);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
.icon {
|
||||||
|
width: vw(30);
|
||||||
|
height: auto;
|
||||||
|
margin-right: vw(10);
|
||||||
|
}
|
||||||
|
& > span {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: vw(20);
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.list {
|
||||||
|
overflow-y: auto;
|
||||||
|
overflow-x: hidden;
|
||||||
|
height: vh(920);
|
||||||
|
padding: vw(8);
|
||||||
|
/* 滚动条整体样式 */
|
||||||
|
&::-webkit-scrollbar {
|
||||||
|
width: vw(0); /* 滚动条的宽度 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 滚动条轨道 */
|
||||||
|
&::-webkit-scrollbar-track {
|
||||||
|
background: #f1f1f1; /* 轨道的背景色 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 滚动条滑块 */
|
||||||
|
&::-webkit-scrollbar-thumb {
|
||||||
|
background: #888; /* 滑块的背景色 */
|
||||||
|
border-radius: 5px; /* 滑块的圆角 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 当鼠标悬停在滚动条上时滑块的样式 */
|
||||||
|
&::-webkit-scrollbar-thumb:hover {
|
||||||
|
background: #555; /* 滑块的背景色 */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.item {
|
||||||
|
margin-bottom: vh(10);
|
||||||
|
padding: vw(10);
|
||||||
|
background-image: url('@/assets/images/item-primary.png');
|
||||||
|
background-size: 100% 100%;
|
||||||
|
& > div {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
&-title {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
width: 100%;
|
||||||
|
padding: vw(10);
|
||||||
|
color: #fff;
|
||||||
|
font-size: vw(14);
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
z-index: 999;
|
||||||
|
}
|
||||||
|
&-title--error {
|
||||||
|
@extend .item-title;
|
||||||
|
background-color: rgba(226, 27, 27, 0.72);
|
||||||
|
}
|
||||||
|
&-title--primary {
|
||||||
|
@extend .item-title;
|
||||||
|
background-color: rgba(4, 30, 69, 0.72);
|
||||||
|
}
|
||||||
|
&-img {
|
||||||
|
width: 100%;
|
||||||
|
height: vh(164);
|
||||||
|
display: block;
|
||||||
|
object-fit: cover;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
.video-live {
|
.video-live {
|
||||||
.video-rt {
|
.video-rt {
|
||||||
width: vw(400);
|
width: vw(400);
|
||||||
|
|||||||
@@ -44,6 +44,12 @@ export const useHomeStore = defineStore('home', () => {
|
|||||||
let baiduMapData = ref(null)
|
let baiduMapData = ref(null)
|
||||||
// 工单列表
|
// 工单列表
|
||||||
let wordkOrderList = ref([])
|
let wordkOrderList = ref([])
|
||||||
|
// 工单统计
|
||||||
|
let wordkOrderData = ref({
|
||||||
|
toDayData: { count: 15, end: 0, rate: '0.0' },
|
||||||
|
warnData: { count: 15, end: 0, rate: '0.0' }
|
||||||
|
})
|
||||||
|
|
||||||
// 交通信息
|
// 交通信息
|
||||||
let trafficInfoData = ref({
|
let trafficInfoData = ref({
|
||||||
data: {
|
data: {
|
||||||
@@ -102,6 +108,9 @@ export const useHomeStore = defineStore('home', () => {
|
|||||||
const setScenicQueueData = (val) => {
|
const setScenicQueueData = (val) => {
|
||||||
scenicQueueData.value = val
|
scenicQueueData.value = val
|
||||||
}
|
}
|
||||||
|
const setWordkOrderData = (val) => {
|
||||||
|
wordkOrderData.value = val
|
||||||
|
}
|
||||||
const setWordkOrderList = (val) => {
|
const setWordkOrderList = (val) => {
|
||||||
wordkOrderList.value = val
|
wordkOrderList.value = val
|
||||||
}
|
}
|
||||||
@@ -119,6 +128,7 @@ export const useHomeStore = defineStore('home', () => {
|
|||||||
userPortraitData,
|
userPortraitData,
|
||||||
baiduMapData,
|
baiduMapData,
|
||||||
wordkOrderList,
|
wordkOrderList,
|
||||||
|
wordkOrderData,
|
||||||
scenicQueueData,
|
scenicQueueData,
|
||||||
scenicBearData,
|
scenicBearData,
|
||||||
visitorInfoData,
|
visitorInfoData,
|
||||||
@@ -131,6 +141,7 @@ export const useHomeStore = defineStore('home', () => {
|
|||||||
setUserPortraitData,
|
setUserPortraitData,
|
||||||
setBaiduMapData,
|
setBaiduMapData,
|
||||||
setWordkOrderList,
|
setWordkOrderList,
|
||||||
|
setWordkOrderData,
|
||||||
setScenicQueueData,
|
setScenicQueueData,
|
||||||
setScenicBearData,
|
setScenicBearData,
|
||||||
setVisitorInfoData,
|
setVisitorInfoData,
|
||||||
|
|||||||
@@ -47,7 +47,12 @@ export const useScenicStore = defineStore('scenic', () => {
|
|||||||
provinceRate: []
|
provinceRate: []
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
// 工单列表
|
||||||
|
let wordkOrderList = ref([])
|
||||||
|
|
||||||
|
const setWordkOrderList = (val) => {
|
||||||
|
wordkOrderList.value = val
|
||||||
|
}
|
||||||
const setUserPortraitData = (val) => {
|
const setUserPortraitData = (val) => {
|
||||||
userPortraitData.value = val
|
userPortraitData.value = val
|
||||||
}
|
}
|
||||||
@@ -70,6 +75,7 @@ export const useScenicStore = defineStore('scenic', () => {
|
|||||||
scenicSpotData.value = val
|
scenicSpotData.value = val
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
|
wordkOrderList,
|
||||||
scenicSpotData,
|
scenicSpotData,
|
||||||
scenicQueueData,
|
scenicQueueData,
|
||||||
scenicBearData,
|
scenicBearData,
|
||||||
@@ -77,6 +83,7 @@ export const useScenicStore = defineStore('scenic', () => {
|
|||||||
secureData,
|
secureData,
|
||||||
trafficData,
|
trafficData,
|
||||||
userPortraitData,
|
userPortraitData,
|
||||||
|
setWordkOrderList,
|
||||||
setScenicSpotData,
|
setScenicSpotData,
|
||||||
setScenicQueueData,
|
setScenicQueueData,
|
||||||
setScenicBearData,
|
setScenicBearData,
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
export const baseUrl = 'http://36.138.38.16:8001'
|
export const baseUrl = 'http://36.138.38.16:8001'
|
||||||
export const proBaseUrl = ' http://192.168.77.200'
|
export const proBaseUrl = 'http://192.168.77.200'
|
||||||
|
|
||||||
export const socketBaseUrl = 'ws://36.138.38.16:81'
|
export const socketBaseUrl = 'ws://36.138.38.16:81'
|
||||||
export const proSocketBaseUrl = 'ws://192.168.77.200:8060'
|
export const proSocketBaseUrl = 'ws://192.168.77.200:8060'
|
||||||
|
|||||||
@@ -90,7 +90,7 @@
|
|||||||
<div class="mt-8">
|
<div class="mt-8">
|
||||||
<age :list="homeStore.userPortraitData?.ageRate" />
|
<age :list="homeStore.userPortraitData?.ageRate" />
|
||||||
</div>
|
</div>
|
||||||
<div v-if="ageRateTotal > 0" class="count">总人数:<countup :end-val="ageRateTotal" /></div>
|
<div class="count">总人数:<countup :end-val="ageRateTotal" /></div>
|
||||||
<div
|
<div
|
||||||
class="cell pt-20"
|
class="cell pt-20"
|
||||||
v-for="(item, index) in homeStore?.userPortraitData.genderRate"
|
v-for="(item, index) in homeStore?.userPortraitData.genderRate"
|
||||||
|
|||||||
@@ -58,38 +58,44 @@
|
|||||||
<div class="flex justify-center pt-10">
|
<div class="flex justify-center pt-10">
|
||||||
<div class="item">
|
<div class="item">
|
||||||
<p class="label">今日工单总条数</p>
|
<p class="label">今日工单总条数</p>
|
||||||
<countup :endVal="1234" />
|
<countup :end-val="homeStore.wordkOrderData.toDayData.count" />
|
||||||
</div>
|
</div>
|
||||||
<div class="item">
|
<div class="item">
|
||||||
<p class="label">工单完成数</p>
|
<p class="label">工单完成数</p>
|
||||||
<countup :endVal="1234" />
|
<countup class="complete" :end-val="homeStore.wordkOrderData.toDayData.end" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="progress-box">
|
<div class="progress-box">
|
||||||
<span class="text">工单完成数</span>
|
<span class="text">工单完成数</span>
|
||||||
<div class="progress-1">
|
<div class="progress-1">
|
||||||
<el-progress :percentage="50" :show-text="false" />
|
<el-progress
|
||||||
|
:percentage="homeStore.wordkOrderData.toDayData.rate"
|
||||||
|
:show-text="false"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<span class="value">50%</span>
|
<span class="value">{{ homeStore.wordkOrderData.toDayData.rate }}%</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<div class="flex justify-center pt-10">
|
<div class="flex justify-center pt-10">
|
||||||
<div class="item">
|
<div class="item">
|
||||||
<p class="label">紧急工单数</p>
|
<p class="label">紧急工单数</p>
|
||||||
<countup :endVal="1234" />
|
<countup class="error" :end-val="homeStore.wordkOrderData.warnData.count" />
|
||||||
</div>
|
</div>
|
||||||
<div class="item">
|
<div class="item">
|
||||||
<p class="label">紧急工单完成数</p>
|
<p class="label">紧急工单完成数</p>
|
||||||
<countup :endVal="1234" />
|
<countup class="complete" :end-val="homeStore.wordkOrderData.warnData.end" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="progress-box">
|
<div class="progress-box">
|
||||||
<span class="text">工单完成数</span>
|
<span class="text">工单完成数</span>
|
||||||
<div class="progress-2">
|
<div class="progress-2">
|
||||||
<el-progress :percentage="50" :show-text="false" />
|
<el-progress
|
||||||
|
:percentage="homeStore.wordkOrderData.warnData.rate"
|
||||||
|
:show-text="false"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<span class="value">50%</span>
|
<span class="value">{{ homeStore.wordkOrderData.warnData.rate }}%</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -162,9 +168,10 @@
|
|||||||
const getSpotList = async () => {
|
const getSpotList = async () => {
|
||||||
let res = await getSpotListApi()
|
let res = await getSpotListApi()
|
||||||
spotList.value = res.data
|
spotList.value = res.data
|
||||||
// let res1 = await getBaiduMapCrowdedApi({
|
let res1 = await getBaiduMapCrowdedApi({
|
||||||
// nodeId: res.data[0].nodeid
|
nodeId: res.data[0].nodeid
|
||||||
// })
|
})
|
||||||
|
console.log(res1, 'res1')
|
||||||
}
|
}
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
@@ -338,16 +345,22 @@
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
.label {
|
.label {
|
||||||
|
margin-bottom: vh(10);
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
font-size: vw(14);
|
font-size: vw(14);
|
||||||
margin-bottom: vh(10);
|
color: #ffffff;
|
||||||
color: rgba(255, 255, 255, 0.9);
|
|
||||||
}
|
}
|
||||||
.countup-wrap {
|
.countup-wrap {
|
||||||
color: #02f9fa;
|
color: #02f9fa;
|
||||||
font-size: vw(28);
|
font-size: vw(28);
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
.error {
|
||||||
|
color: #e21b1b;
|
||||||
|
}
|
||||||
|
.complete {
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
.progress-box {
|
.progress-box {
|
||||||
margin-top: vh(10);
|
margin-top: vh(10);
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -388,7 +401,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
.right {
|
.right {
|
||||||
margin-top: vh(8);
|
margin-top: vh(4);
|
||||||
padding: vh(10) vw(10);
|
padding: vh(10) vw(10);
|
||||||
height: vh(106);
|
height: vh(106);
|
||||||
width: vw(1040);
|
width: vw(1040);
|
||||||
|
|||||||
@@ -359,7 +359,7 @@
|
|||||||
flex: 1;
|
flex: 1;
|
||||||
& > div {
|
& > div {
|
||||||
position: relative;
|
position: relative;
|
||||||
height: vh(110);
|
height: vh(114);
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
background-image: url('@/assets/images/bg-4.png');
|
background-image: url('@/assets/images/bg-4.png');
|
||||||
|
|||||||
@@ -127,7 +127,7 @@
|
|||||||
fontSize: fitChartSize(12)
|
fontSize: fitChartSize(12)
|
||||||
},
|
},
|
||||||
verticalAlign: 'bottom',
|
verticalAlign: 'bottom',
|
||||||
padding: [0, 0, 6, 0],
|
padding: [0, 0, 10, 0],
|
||||||
inside: true,
|
inside: true,
|
||||||
formatter: function (value) {
|
formatter: function (value) {
|
||||||
return `{value|${value}}{value|%}`
|
return `{value|${value}}{value|%}`
|
||||||
@@ -156,7 +156,7 @@
|
|||||||
},
|
},
|
||||||
label: {
|
label: {
|
||||||
show: true,
|
show: true,
|
||||||
offset: [10, -10],
|
offset: [10, -14],
|
||||||
color: '#fff',
|
color: '#fff',
|
||||||
fontWeight: 500,
|
fontWeight: 500,
|
||||||
position: 'left',
|
position: 'left',
|
||||||
|
|||||||
@@ -66,7 +66,7 @@
|
|||||||
legend: {
|
legend: {
|
||||||
show: true,
|
show: true,
|
||||||
x: 'center',
|
x: 'center',
|
||||||
y: 'bottom',
|
y: '70%',
|
||||||
itemHeight: fitChartSize(12),
|
itemHeight: fitChartSize(12),
|
||||||
itemWidth: fitChartSize(12),
|
itemWidth: fitChartSize(12),
|
||||||
itemGap: fitChartSize(6),
|
itemGap: fitChartSize(6),
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
<box1 />
|
<box1 />
|
||||||
<box2 @switch-spot="switchSpot" />
|
<box2 @switch-spot="switchSpot" />
|
||||||
<box3 />
|
<box3 />
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
@@ -63,6 +62,9 @@
|
|||||||
case 'wordkOrderlist':
|
case 'wordkOrderlist':
|
||||||
homeStore.setWordkOrderList(val.data)
|
homeStore.setWordkOrderList(val.data)
|
||||||
break
|
break
|
||||||
|
case 'wordkOrderTotal':
|
||||||
|
homeStore.setWordkOrderData(val)
|
||||||
|
break
|
||||||
case 'trafficInformation':
|
case 'trafficInformation':
|
||||||
homeStore.setTrafficInfoData(val)
|
homeStore.setTrafficInfoData(val)
|
||||||
break
|
break
|
||||||
|
|||||||
@@ -26,9 +26,9 @@
|
|||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.box-2 {
|
.box-2 {
|
||||||
margin-top: vh(120);
|
|
||||||
width: vw(2356);
|
|
||||||
height: vh(965);
|
|
||||||
display: flex;
|
display: flex;
|
||||||
|
flex: 1;
|
||||||
|
margin-top: vh(120);
|
||||||
|
height: vh(965);
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -67,29 +67,24 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="flex align-center justify-between">
|
<div class="flex align-center justify-between">
|
||||||
<div>
|
<div>
|
||||||
<div class="cell">
|
<vue3-seamless-scroll
|
||||||
<span class="tag tag--success">普通</span>
|
class="list"
|
||||||
<p class="content">
|
:list="scenicStore.wordkOrderList"
|
||||||
工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工工单信息工单信息工单信息工单信息工单信息
|
:limitScrollNum="3"
|
||||||
工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工工单信息工单信息工单信息工单信息工单信息
|
:hover="true"
|
||||||
</p>
|
:step="0.2"
|
||||||
</div>
|
:wheel="true"
|
||||||
<div class="cell">
|
:isWatch="true"
|
||||||
<span class="tag tag--error">普通</span>
|
>
|
||||||
<p class="content">
|
<div class="cell" v-for="(item, index) in scenicStore.wordkOrderList" :key="index">
|
||||||
工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工工单信息工单信息工单信息工单信息工单信息
|
<span :class="`tag--${item.level}`">{{ item.level_text }}</span>
|
||||||
工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工工单信息工单信息工单信息工单信息工单信息
|
<p class="content">
|
||||||
</p>
|
{{ item.title }}
|
||||||
</div>
|
</p>
|
||||||
<div class="cell">
|
</div>
|
||||||
<span class="tag tag--primary">普通</span>
|
</vue3-seamless-scroll>
|
||||||
<p class="content">
|
|
||||||
工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工工单信息工单信息工单信息工单信息工单信息
|
|
||||||
工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工工单信息工单信息工单信息工单信息工单信息
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<img class="more" src="@/assets/images/more-col.png" alt="查看更多" />
|
<img class="more" src="@/assets/images/more-col.png" alt="查看更多" @click="handleMore" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -97,9 +92,16 @@
|
|||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import countup from 'vue-countup-v3'
|
import countup from 'vue-countup-v3'
|
||||||
|
import { Vue3SeamlessScroll } from 'vue3-seamless-scroll'
|
||||||
import { useScenicStore } from '@/stores/scenic'
|
import { useScenicStore } from '@/stores/scenic'
|
||||||
|
import { useRouter } from 'vue-router'
|
||||||
|
|
||||||
|
const router = useRouter()
|
||||||
const scenicStore = useScenicStore()
|
const scenicStore = useScenicStore()
|
||||||
|
|
||||||
|
const handleMore = () => {
|
||||||
|
router.push('/workOrder')
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
@@ -205,6 +207,11 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.list {
|
||||||
|
margin-top: vh(4);
|
||||||
|
height: vh(116);
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
.cell {
|
.cell {
|
||||||
display: flex;
|
display: flex;
|
||||||
margin-left: vw(4);
|
margin-left: vw(4);
|
||||||
@@ -216,30 +223,28 @@
|
|||||||
padding: 0 vw(16);
|
padding: 0 vw(16);
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
font-size: vw(14);
|
font-size: vw(14);
|
||||||
|
color: #fff;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
border-radius: vw(2);
|
border-radius: vw(2);
|
||||||
&--success {
|
}
|
||||||
color: #02f9fa;
|
.tag--important {
|
||||||
border: 1px solid #02f9fa;
|
@extend .tag;
|
||||||
box-shadow: inset 0 0 vw(8) 0 #0be1ab;
|
background: #feae00;
|
||||||
}
|
}
|
||||||
&--error {
|
.tag--warn {
|
||||||
color: #ee2c2c;
|
@extend .tag;
|
||||||
border: 1px solid #ee2c2c;
|
background: #d9011b;
|
||||||
box-shadow: inset 0 0 vw(8) 0 #ee2c2c;
|
}
|
||||||
}
|
.tag--normal {
|
||||||
&--primary {
|
@extend .tag;
|
||||||
color: #00aaff;
|
background: #2380fb;
|
||||||
border: 1px solid #00aaff;
|
|
||||||
box-shadow: inset 0 0 vw(8) 0 #00aaff;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
.content {
|
.content {
|
||||||
margin-left: vw(4);
|
margin-left: vw(4);
|
||||||
padding: 0 vw(10);
|
padding: 0 vw(10);
|
||||||
width: vw(660);
|
width: vw(760);
|
||||||
height: vh(24);
|
height: vh(24);
|
||||||
line-height: vh(24);
|
line-height: vh(24);
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
|
|||||||
@@ -115,7 +115,7 @@
|
|||||||
label="安全告警占比"
|
label="安全告警占比"
|
||||||
:dataList="scenicStore.secureData.dataList"
|
:dataList="scenicStore.secureData.dataList"
|
||||||
:total="alarmTotal"
|
:total="alarmTotal"
|
||||||
:width="350"
|
:width="460"
|
||||||
:height="300"
|
:height="300"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@@ -141,26 +141,10 @@
|
|||||||
<div class="border mr-8">
|
<div class="border mr-8">
|
||||||
<Title3 title="拥堵次数占比" />
|
<Title3 title="拥堵次数占比" />
|
||||||
<jam :width="220" :height="160" />
|
<jam :width="220" :height="160" />
|
||||||
<!-- <div class="legend">
|
|
||||||
<ul class="legend__wrapper">
|
|
||||||
<li class="legend-item" v-for="(item, index) in 6" :key="index">
|
|
||||||
<p class="legend-item-label">路段1</p>
|
|
||||||
<p class="legend-item-value">10%</p>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div> -->
|
|
||||||
</div>
|
</div>
|
||||||
<div class="border">
|
<div class="border">
|
||||||
<Title3 title="拥堵时长占比" />
|
<Title3 title="拥堵时长占比" />
|
||||||
<jam :width="220" :height="160" />
|
<jam :width="220" :height="160" />
|
||||||
<!-- <div class="legend">
|
|
||||||
<ul class="legend__wrapper">
|
|
||||||
<li class="legend-item" v-for="(item, index) in 6" :key="index">
|
|
||||||
<p class="legend-item-label">路段1</p>
|
|
||||||
<p class="legend-item-value">10%</p>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div> -->
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,195 +1,106 @@
|
|||||||
|
<!-- 购票来源 -->
|
||||||
<template>
|
<template>
|
||||||
<div class="ticket" :id="id" />
|
<div class="ticket" :id="id" />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { fitChartSize } from '@/utils/dataUtil'
|
import { fitChartSize } from '@/utils/dataUtil'
|
||||||
import * as echarts from 'echarts'
|
import { useEchart } from '@/hooks/echart'
|
||||||
import { guid } from '@/utils/util'
|
|
||||||
|
|
||||||
let id = ref(guid())
|
import { useScenicStore } from '@/stores/scenic'
|
||||||
let ticketChart = null
|
|
||||||
var qxzbData = [
|
const scenicStore = useScenicStore()
|
||||||
{
|
|
||||||
name: '处理中',
|
const { id, setOption } = useEchart()
|
||||||
value: 500,
|
|
||||||
full: 1000 // 最大值
|
let x = 15
|
||||||
|
let y = 25
|
||||||
|
let params = null
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => scenicStore.userPortraitData.data.channel,
|
||||||
|
(val) => {
|
||||||
|
if (val.length > 0) {
|
||||||
|
setTimeout(() => {
|
||||||
|
init()
|
||||||
|
}, 1000)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: '超期中',
|
immediate: true
|
||||||
value: 756,
|
|
||||||
full: 1000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: '延期中',
|
|
||||||
value: 800,
|
|
||||||
full: 1000
|
|
||||||
}
|
}
|
||||||
]
|
)
|
||||||
var returnData = function (qxzbData, name) {
|
|
||||||
for (var a = 0; a < qxzbData.length; a++) {
|
const setSeries = () => {
|
||||||
if (qxzbData[a].name == name) {
|
return scenicStore.userPortraitData.data.channel.map((item, index) => {
|
||||||
return qxzbData[a].value
|
return {
|
||||||
|
name: item.name,
|
||||||
|
type: 'pie',
|
||||||
|
clockwise: false,
|
||||||
|
silent: true,
|
||||||
|
radius: [`${x * (index + 1)}%`, `${y + index * 15}%`],
|
||||||
|
center: ['50%', '40%'],
|
||||||
|
label: { show: false },
|
||||||
|
labelLine: { show: false },
|
||||||
|
emphasis: { show: false },
|
||||||
|
data: [
|
||||||
|
{
|
||||||
|
value: parseFloat(item.value),
|
||||||
|
name: item.name
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 100,
|
||||||
|
itemStyle: {
|
||||||
|
color: '#07439C'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
}
|
|
||||||
let option = {
|
|
||||||
backgroundColor: 'transparent',
|
|
||||||
tooltip: {
|
|
||||||
trigger: 'item',
|
|
||||||
formatter: function (rsp) {
|
|
||||||
if (rsp.name != '') {
|
|
||||||
return rsp.name + '<br/>' + rsp.marker + ' ' + rsp.value + ' (' + rsp.percent + ')'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
legend: {
|
|
||||||
x: 'center',
|
|
||||||
y: 'bottom',
|
|
||||||
data: qxzbData,
|
|
||||||
itemHeight: fitChartSize(8),
|
|
||||||
itemWidth: fitChartSize(8),
|
|
||||||
itemGap: fitChartSize(20),
|
|
||||||
formatter: function (name) {
|
|
||||||
return '{title|' + name + '} {value|' + returnData(qxzbData, name) + '}'
|
|
||||||
},
|
|
||||||
textStyle: {
|
|
||||||
rich: {
|
|
||||||
title: {
|
|
||||||
color: '#fff',
|
|
||||||
fontSize: fitChartSize(14)
|
|
||||||
},
|
|
||||||
value: {
|
|
||||||
color: '#00D5F6',
|
|
||||||
fontSize: fitChartSize(14)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
color: ['#F15A25', '#01FEFE', '#12B5FD'],
|
|
||||||
series: [
|
|
||||||
{
|
|
||||||
name: qxzbData[0].name, //最里面的圈
|
|
||||||
type: 'pie',
|
|
||||||
clockWise: false, //顺时加载
|
|
||||||
radius: ['15%', '25%'],
|
|
||||||
center: ['50%', '40%'],
|
|
||||||
label: {
|
|
||||||
normal: {
|
|
||||||
show: false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
labelLine: {
|
|
||||||
show: false
|
|
||||||
},
|
|
||||||
itemStyle: {
|
|
||||||
emphasis: {
|
|
||||||
show: false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
data: [
|
|
||||||
{
|
|
||||||
value: qxzbData[0].value,
|
|
||||||
name: qxzbData[0].name
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: qxzbData[0].full,
|
|
||||||
itemStyle: {
|
|
||||||
normal: {
|
|
||||||
color: '#07439C'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: qxzbData[1].name, //第二个圈
|
|
||||||
type: 'pie',
|
|
||||||
clockWise: false, //顺时加载
|
|
||||||
radius: ['35%', '45%'],
|
|
||||||
center: ['50%', '40%'],
|
|
||||||
label: {
|
|
||||||
normal: {
|
|
||||||
show: false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
labelLine: {
|
|
||||||
show: false
|
|
||||||
},
|
|
||||||
itemStyle: {
|
|
||||||
emphasis: {
|
|
||||||
show: false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
data: [
|
|
||||||
{
|
|
||||||
value: qxzbData[1].value,
|
|
||||||
name: qxzbData[1].name
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: qxzbData[1].full,
|
|
||||||
itemStyle: {
|
|
||||||
normal: {
|
|
||||||
color: '#07439C'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: qxzbData[2].name, //最外层圈
|
|
||||||
type: 'pie',
|
|
||||||
clockWise: false, //顺时加载
|
|
||||||
radius: ['55%', '65%'],
|
|
||||||
center: ['50%', '40%'],
|
|
||||||
label: {
|
|
||||||
normal: {
|
|
||||||
show: false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
labelLine: {
|
|
||||||
show: false
|
|
||||||
},
|
|
||||||
itemStyle: {
|
|
||||||
emphasis: {
|
|
||||||
show: false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
data: [
|
|
||||||
{
|
|
||||||
value: qxzbData[2].value,
|
|
||||||
name: qxzbData[2].name
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: qxzbData[2].full,
|
|
||||||
itemStyle: {
|
|
||||||
normal: {
|
|
||||||
color: '#07439C'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const init = () => {
|
const init = () => {
|
||||||
ticketChart = echarts.init(document.getElementById(id.value))
|
if (!params) {
|
||||||
ticketChart.setOption(option)
|
params = {
|
||||||
}
|
backgroundColor: 'transparent',
|
||||||
const resize = () => {
|
legend: {
|
||||||
if (ticketChart) {
|
show: true,
|
||||||
ticketChart.resize()
|
x: 'center',
|
||||||
|
y: '70%',
|
||||||
|
itemHeight: fitChartSize(12),
|
||||||
|
itemWidth: fitChartSize(12),
|
||||||
|
itemGap: fitChartSize(6),
|
||||||
|
formatter: function (name) {
|
||||||
|
let obj = scenicStore.userPortraitData.data.channel.find((item) => item.name == name)
|
||||||
|
return '{name|' + name + '} {value|' + obj?.value + '}{value|%}'
|
||||||
|
},
|
||||||
|
textStyle: {
|
||||||
|
rich: {
|
||||||
|
name: {
|
||||||
|
color: '#fff',
|
||||||
|
fontSize: fitChartSize(12)
|
||||||
|
},
|
||||||
|
value: {
|
||||||
|
color: '#00D5F6',
|
||||||
|
fontWeight: 600,
|
||||||
|
fontSize: fitChartSize(12)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
color: ['#F15A25', '#01FEFE', '#12B5FD'],
|
||||||
|
series: setSeries()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
params.series = setSeries()
|
||||||
}
|
}
|
||||||
|
setOption(params)
|
||||||
}
|
}
|
||||||
onMounted(() => {
|
|
||||||
init()
|
|
||||||
window.addEventListener('resize', resize)
|
|
||||||
})
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
.ticket {
|
.ticket {
|
||||||
width: vw(250);
|
width: vw(260);
|
||||||
height: vh(300);
|
height: vh(336);
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,187 +1,134 @@
|
|||||||
|
<!-- 客源地分析TOP5 -->
|
||||||
<template>
|
<template>
|
||||||
<div class="top" :id="id" />
|
<div class="top" :id="id" />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { fitChartSize } from '@/utils/dataUtil'
|
import { fitChartSize } from '@/utils/dataUtil'
|
||||||
import * as echarts from 'echarts'
|
import { useEchart } from '@/hooks/echart'
|
||||||
import { guid } from '@/utils/util'
|
import { useScenicStore } from '@/stores/scenic'
|
||||||
|
|
||||||
|
const scenicStore = useScenicStore()
|
||||||
|
const { id, setOption } = useEchart()
|
||||||
|
let params = null
|
||||||
|
|
||||||
let id = ref(guid())
|
|
||||||
let topChart = null
|
|
||||||
let colorList = [
|
|
||||||
'rgba(255, 38, 38, 1)',
|
|
||||||
'rgba(255, 96, 0, 1)',
|
|
||||||
'rgba(255, 165, 7, 1)',
|
|
||||||
'rgba(0, 234, 255, 1)',
|
|
||||||
'rgba(0, 132, 255, 1)',
|
|
||||||
'#2379FF'
|
|
||||||
]
|
|
||||||
let colorListA = [
|
|
||||||
'rgba(255, 38, 38, 0.1)',
|
|
||||||
'rgba(255, 96, 0, 0.1)',
|
|
||||||
'rgba(255, 165, 7, 0.1)',
|
|
||||||
'rgba(0, 234, 255, 0.1)',
|
|
||||||
'rgba(0, 132, 255, 0.1)',
|
|
||||||
'#49B1FF'
|
|
||||||
]
|
|
||||||
let result = [
|
|
||||||
{ name: '河北', value: 86 },
|
|
||||||
{ name: '山西', value: 83 },
|
|
||||||
{ name: '河南', value: 73 },
|
|
||||||
{ name: '内蒙', value: 61 },
|
|
||||||
{ name: '辽宁', value: 61 }
|
|
||||||
]
|
|
||||||
let option = {
|
|
||||||
color: colorList,
|
|
||||||
backgroundColor: 'transparent',
|
|
||||||
tooltip: {
|
|
||||||
show: false
|
|
||||||
},
|
|
||||||
legend: {
|
|
||||||
show: false
|
|
||||||
},
|
|
||||||
grid: {
|
|
||||||
left: '4%',
|
|
||||||
right: '4%',
|
|
||||||
top: '6%',
|
|
||||||
bottom: '4%',
|
|
||||||
containLabel: true
|
|
||||||
},
|
|
||||||
xAxis: [
|
|
||||||
{
|
|
||||||
splitLine: {
|
|
||||||
show: false
|
|
||||||
},
|
|
||||||
type: 'value',
|
|
||||||
show: false
|
|
||||||
}
|
|
||||||
],
|
|
||||||
yAxis: [
|
|
||||||
{
|
|
||||||
splitLine: {
|
|
||||||
show: false
|
|
||||||
},
|
|
||||||
axisLine: {
|
|
||||||
show: false
|
|
||||||
},
|
|
||||||
type: 'category',
|
|
||||||
axisTick: {
|
|
||||||
show: false
|
|
||||||
},
|
|
||||||
data: result.map((item) => item.name),
|
|
||||||
axisLabel: {
|
|
||||||
show: false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'category',
|
|
||||||
inverse: true,
|
|
||||||
axisTick: 'none',
|
|
||||||
axisLine: 'none',
|
|
||||||
show: true,
|
|
||||||
axisLabel: {
|
|
||||||
textStyle: {
|
|
||||||
color: '#fff',
|
|
||||||
fontSize: fitChartSize(12)
|
|
||||||
},
|
|
||||||
verticalAlign: 'bottom',
|
|
||||||
padding: [0, 0, 10, 0],
|
|
||||||
inside: true,
|
|
||||||
formatter: function (value) {
|
|
||||||
return `{value|${value}}`
|
|
||||||
},
|
|
||||||
rich: {
|
|
||||||
name: {
|
|
||||||
align: 'center',
|
|
||||||
color: '#D3E5FF',
|
|
||||||
fontSize: fitChartSize(14),
|
|
||||||
fontFamily: 'Source Han Sans CN'
|
|
||||||
},
|
|
||||||
value: {
|
|
||||||
align: 'center',
|
|
||||||
color: '#fff',
|
|
||||||
fontSize: fitChartSize(14),
|
|
||||||
fontFamily: 'Source Han Sans CN'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
data: result.map((item) => item.value)
|
|
||||||
}
|
|
||||||
],
|
|
||||||
series: [
|
|
||||||
{
|
|
||||||
name: '',
|
|
||||||
type: 'bar',
|
|
||||||
barWidth: fitChartSize(12),
|
|
||||||
MaxSize: 0,
|
|
||||||
showBackground: true,
|
|
||||||
barBorderRadius: [30, 0, 0, 30],
|
|
||||||
backgroundStyle: {
|
|
||||||
color: 'rgba(0, 150, 255, 0.15)'
|
|
||||||
},
|
|
||||||
label: {
|
|
||||||
show: true,
|
|
||||||
offset: [10, -17],
|
|
||||||
color: '#D3E5FF',
|
|
||||||
fontWeight: 500,
|
|
||||||
position: 'left',
|
|
||||||
align: 'left',
|
|
||||||
fontSize: fitChartSize(14),
|
|
||||||
fontFamily: 'Source Han Sans CN',
|
|
||||||
formatter: function (params) {
|
|
||||||
return params.data.name
|
|
||||||
}
|
|
||||||
},
|
|
||||||
data: result.map((item, index) => {
|
|
||||||
return {
|
|
||||||
name: item.name,
|
|
||||||
value: item.value,
|
|
||||||
itemStyle: {
|
|
||||||
barBorderRadius: [3, 0, 0, 3],
|
|
||||||
color: {
|
|
||||||
type: 'linear',
|
|
||||||
x: 0,
|
|
||||||
y: 0,
|
|
||||||
x2: 1,
|
|
||||||
y2: 1,
|
|
||||||
colorStops: [
|
|
||||||
{
|
|
||||||
offset: 0,
|
|
||||||
color: colorListA[index]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
offset: 1,
|
|
||||||
color: colorList[index]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
const init = () => {
|
const init = () => {
|
||||||
topChart = echarts.init(document.getElementById(id.value))
|
if (!params) {
|
||||||
topChart.setOption(option)
|
params = {
|
||||||
}
|
backgroundColor: 'transparent',
|
||||||
const resize = () => {
|
tooltip: {
|
||||||
if (topChart) {
|
show: false
|
||||||
topChart.dispose()
|
},
|
||||||
topChart = null
|
legend: {
|
||||||
init()
|
show: false
|
||||||
|
},
|
||||||
|
grid: {
|
||||||
|
left: '4%',
|
||||||
|
right: '4%',
|
||||||
|
top: '10%',
|
||||||
|
bottom: '-4%',
|
||||||
|
containLabel: false
|
||||||
|
},
|
||||||
|
xAxis: [{ max: 100, show: false }],
|
||||||
|
yAxis: [
|
||||||
|
{
|
||||||
|
type: 'category',
|
||||||
|
splitLine: {
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
axisLine: {
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
axisTick: {
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
axisLabel: {
|
||||||
|
show: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'category',
|
||||||
|
axisTick: 'none',
|
||||||
|
axisLine: 'none',
|
||||||
|
show: true,
|
||||||
|
axisLabel: {
|
||||||
|
textStyle: {
|
||||||
|
color: '#fff',
|
||||||
|
fontSize: fitChartSize(18)
|
||||||
|
},
|
||||||
|
verticalAlign: 'bottom',
|
||||||
|
padding: [0, -fitChartSize(10), fitChartSize(10), 0],
|
||||||
|
inside: true,
|
||||||
|
formatter: function (value) {
|
||||||
|
return `{value|${value}}%`
|
||||||
|
},
|
||||||
|
rich: {
|
||||||
|
value: {
|
||||||
|
align: 'center',
|
||||||
|
color: '#fff',
|
||||||
|
fontSize: fitChartSize(14)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data: scenicStore.userPortraitData.data.provinceRate.map((item) => Number(item.value))
|
||||||
|
}
|
||||||
|
],
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
type: 'bar',
|
||||||
|
barWidth: fitChartSize(12),
|
||||||
|
showBackground: true,
|
||||||
|
barBorderRadius: [0, 0, 0, 0],
|
||||||
|
backgroundStyle: {
|
||||||
|
color: 'rgba(0, 150, 255, 0.15)'
|
||||||
|
},
|
||||||
|
label: {
|
||||||
|
show: true,
|
||||||
|
offset: [fitChartSize(12), -fitChartSize(20)],
|
||||||
|
color: '#D3E5FF',
|
||||||
|
fontWeight: 500,
|
||||||
|
position: 'left',
|
||||||
|
align: 'left',
|
||||||
|
fontSize: fitChartSize(14),
|
||||||
|
formatter: function (params) {
|
||||||
|
return params.data.name ?? '其他'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data: scenicStore.userPortraitData.data.provinceRate.map((item) => {
|
||||||
|
return {
|
||||||
|
name: item.name,
|
||||||
|
value: Number(item.value),
|
||||||
|
itemStyle: {
|
||||||
|
barBorderRadius: [0, 0, 0, 0],
|
||||||
|
color: parseFloat(item.value) > 50 ? '#FF7021' : '#00CCFF'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
setOption(params)
|
||||||
}
|
}
|
||||||
onMounted(() => {
|
|
||||||
init()
|
watch(
|
||||||
window.addEventListener('resize', resize)
|
() => scenicStore.userPortraitData.data.provinceRate,
|
||||||
})
|
(val) => {
|
||||||
|
if (val.length > 0) {
|
||||||
|
setTimeout(() => {
|
||||||
|
init()
|
||||||
|
}, 1000)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
immediate: true
|
||||||
|
}
|
||||||
|
)
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
.top {
|
.top {
|
||||||
width: vw(240);
|
width: vw(250);
|
||||||
height: vh(360);
|
height: vh(366);
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -30,6 +30,9 @@
|
|||||||
if (val) {
|
if (val) {
|
||||||
console.log(val, '接受消息')
|
console.log(val, '接受消息')
|
||||||
switch (val.type) {
|
switch (val.type) {
|
||||||
|
case 'wordkOrderlist':
|
||||||
|
scenicStore.setWordkOrderList(val.data)
|
||||||
|
break
|
||||||
case 'scenicSpotData':
|
case 'scenicSpotData':
|
||||||
scenicStore.setScenicSpotData(val.data)
|
scenicStore.setScenicSpotData(val.data)
|
||||||
break
|
break
|
||||||
|
|||||||
Reference in New Issue
Block a user