feat:对接景区数据和监控视频
This commit is contained in:
@@ -67,29 +67,24 @@
|
||||
</div>
|
||||
<div class="flex align-center justify-between">
|
||||
<div>
|
||||
<div class="cell">
|
||||
<span class="tag tag--success">普通</span>
|
||||
<p class="content">
|
||||
工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工工单信息工单信息工单信息工单信息工单信息
|
||||
工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工工单信息工单信息工单信息工单信息工单信息
|
||||
</p>
|
||||
</div>
|
||||
<div class="cell">
|
||||
<span class="tag tag--error">普通</span>
|
||||
<p class="content">
|
||||
工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工工单信息工单信息工单信息工单信息工单信息
|
||||
工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工工单信息工单信息工单信息工单信息工单信息
|
||||
</p>
|
||||
</div>
|
||||
<div class="cell">
|
||||
<span class="tag tag--primary">普通</span>
|
||||
<p class="content">
|
||||
工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工工单信息工单信息工单信息工单信息工单信息
|
||||
工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工工单信息工单信息工单信息工单信息工单信息
|
||||
</p>
|
||||
</div>
|
||||
<vue3-seamless-scroll
|
||||
class="list"
|
||||
:list="scenicStore.wordkOrderList"
|
||||
:limitScrollNum="3"
|
||||
:hover="true"
|
||||
:step="0.2"
|
||||
:wheel="true"
|
||||
:isWatch="true"
|
||||
>
|
||||
<div class="cell" v-for="(item, index) in scenicStore.wordkOrderList" :key="index">
|
||||
<span :class="`tag--${item.level}`">{{ item.level_text }}</span>
|
||||
<p class="content">
|
||||
{{ item.title }}
|
||||
</p>
|
||||
</div>
|
||||
</vue3-seamless-scroll>
|
||||
</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>
|
||||
@@ -97,9 +92,16 @@
|
||||
|
||||
<script setup>
|
||||
import countup from 'vue-countup-v3'
|
||||
import { Vue3SeamlessScroll } from 'vue3-seamless-scroll'
|
||||
import { useScenicStore } from '@/stores/scenic'
|
||||
import { useRouter } from 'vue-router'
|
||||
|
||||
const router = useRouter()
|
||||
const scenicStore = useScenicStore()
|
||||
|
||||
const handleMore = () => {
|
||||
router.push('/workOrder')
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@@ -205,6 +207,11 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
.list {
|
||||
margin-top: vh(4);
|
||||
height: vh(116);
|
||||
overflow: hidden;
|
||||
}
|
||||
.cell {
|
||||
display: flex;
|
||||
margin-left: vw(4);
|
||||
@@ -216,30 +223,28 @@
|
||||
padding: 0 vw(16);
|
||||
font-weight: bold;
|
||||
font-size: vw(14);
|
||||
color: #fff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: vw(2);
|
||||
&--success {
|
||||
color: #02f9fa;
|
||||
border: 1px solid #02f9fa;
|
||||
box-shadow: inset 0 0 vw(8) 0 #0be1ab;
|
||||
}
|
||||
&--error {
|
||||
color: #ee2c2c;
|
||||
border: 1px solid #ee2c2c;
|
||||
box-shadow: inset 0 0 vw(8) 0 #ee2c2c;
|
||||
}
|
||||
&--primary {
|
||||
color: #00aaff;
|
||||
border: 1px solid #00aaff;
|
||||
box-shadow: inset 0 0 vw(8) 0 #00aaff;
|
||||
}
|
||||
}
|
||||
.tag--important {
|
||||
@extend .tag;
|
||||
background: #feae00;
|
||||
}
|
||||
.tag--warn {
|
||||
@extend .tag;
|
||||
background: #d9011b;
|
||||
}
|
||||
.tag--normal {
|
||||
@extend .tag;
|
||||
background: #2380fb;
|
||||
}
|
||||
.content {
|
||||
margin-left: vw(4);
|
||||
padding: 0 vw(10);
|
||||
width: vw(660);
|
||||
width: vw(760);
|
||||
height: vh(24);
|
||||
line-height: vh(24);
|
||||
white-space: nowrap;
|
||||
|
||||
@@ -115,7 +115,7 @@
|
||||
label="安全告警占比"
|
||||
:dataList="scenicStore.secureData.dataList"
|
||||
:total="alarmTotal"
|
||||
:width="350"
|
||||
:width="460"
|
||||
:height="300"
|
||||
/>
|
||||
</div>
|
||||
@@ -141,26 +141,10 @@
|
||||
<div class="border mr-8">
|
||||
<Title3 title="拥堵次数占比" />
|
||||
<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 class="border">
|
||||
<Title3 title="拥堵时长占比" />
|
||||
<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>
|
||||
|
||||
@@ -1,195 +1,106 @@
|
||||
<!-- 购票来源 -->
|
||||
<template>
|
||||
<div class="ticket" :id="id" />
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { fitChartSize } from '@/utils/dataUtil'
|
||||
import * as echarts from 'echarts'
|
||||
import { guid } from '@/utils/util'
|
||||
import { useEchart } from '@/hooks/echart'
|
||||
|
||||
let id = ref(guid())
|
||||
let ticketChart = null
|
||||
var qxzbData = [
|
||||
{
|
||||
name: '处理中',
|
||||
value: 500,
|
||||
full: 1000 // 最大值
|
||||
import { useScenicStore } from '@/stores/scenic'
|
||||
|
||||
const scenicStore = useScenicStore()
|
||||
|
||||
const { id, setOption } = useEchart()
|
||||
|
||||
let x = 15
|
||||
let y = 25
|
||||
let params = null
|
||||
|
||||
watch(
|
||||
() => scenicStore.userPortraitData.data.channel,
|
||||
(val) => {
|
||||
if (val.length > 0) {
|
||||
setTimeout(() => {
|
||||
init()
|
||||
}, 1000)
|
||||
}
|
||||
},
|
||||
{
|
||||
name: '超期中',
|
||||
value: 756,
|
||||
full: 1000
|
||||
},
|
||||
{
|
||||
name: '延期中',
|
||||
value: 800,
|
||||
full: 1000
|
||||
immediate: true
|
||||
}
|
||||
]
|
||||
var returnData = function (qxzbData, name) {
|
||||
for (var a = 0; a < qxzbData.length; a++) {
|
||||
if (qxzbData[a].name == name) {
|
||||
return qxzbData[a].value
|
||||
)
|
||||
|
||||
const setSeries = () => {
|
||||
return scenicStore.userPortraitData.data.channel.map((item, index) => {
|
||||
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 = () => {
|
||||
ticketChart = echarts.init(document.getElementById(id.value))
|
||||
ticketChart.setOption(option)
|
||||
}
|
||||
const resize = () => {
|
||||
if (ticketChart) {
|
||||
ticketChart.resize()
|
||||
if (!params) {
|
||||
params = {
|
||||
backgroundColor: 'transparent',
|
||||
legend: {
|
||||
show: true,
|
||||
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>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.ticket {
|
||||
width: vw(250);
|
||||
height: vh(300);
|
||||
width: vw(260);
|
||||
height: vh(336);
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,187 +1,134 @@
|
||||
<!-- 客源地分析TOP5 -->
|
||||
<template>
|
||||
<div class="top" :id="id" />
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { fitChartSize } from '@/utils/dataUtil'
|
||||
import * as echarts from 'echarts'
|
||||
import { guid } from '@/utils/util'
|
||||
import { useEchart } from '@/hooks/echart'
|
||||
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 = () => {
|
||||
topChart = echarts.init(document.getElementById(id.value))
|
||||
topChart.setOption(option)
|
||||
}
|
||||
const resize = () => {
|
||||
if (topChart) {
|
||||
topChart.dispose()
|
||||
topChart = null
|
||||
init()
|
||||
if (!params) {
|
||||
params = {
|
||||
backgroundColor: 'transparent',
|
||||
tooltip: {
|
||||
show: false
|
||||
},
|
||||
legend: {
|
||||
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()
|
||||
window.addEventListener('resize', resize)
|
||||
})
|
||||
|
||||
watch(
|
||||
() => scenicStore.userPortraitData.data.provinceRate,
|
||||
(val) => {
|
||||
if (val.length > 0) {
|
||||
setTimeout(() => {
|
||||
init()
|
||||
}, 1000)
|
||||
}
|
||||
},
|
||||
{
|
||||
immediate: true
|
||||
}
|
||||
)
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.top {
|
||||
width: vw(240);
|
||||
height: vh(360);
|
||||
width: vw(250);
|
||||
height: vh(366);
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user