feat:对接消息相关接口
@@ -11,7 +11,7 @@ export function getWeatherApi() {
|
|||||||
// 核心景区视频
|
// 核心景区视频
|
||||||
export function getVideoListApi(data) {
|
export function getVideoListApi(data) {
|
||||||
return request({
|
return request({
|
||||||
url: '/api/video/list',
|
url: 'http://36.138.38.16:6180/fjtcc-api/api/video/list',
|
||||||
method: 'get',
|
method: 'get',
|
||||||
params: data
|
params: data
|
||||||
})
|
})
|
||||||
@@ -20,8 +20,25 @@ export function getVideoListApi(data) {
|
|||||||
// 刷新播放地址
|
// 刷新播放地址
|
||||||
export function postRefreshApi(data) {
|
export function postRefreshApi(data) {
|
||||||
return request({
|
return request({
|
||||||
url: '/api/video/refresh',
|
url: 'http://36.138.38.16:6180/fjtcc-api/api/video/refresh',
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
data: data
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 景区
|
||||||
|
export function getSpotListApi() {
|
||||||
|
return request({
|
||||||
|
url: '/api/largeScreen/spot/list',
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 百度地图拥堵
|
||||||
|
export function getBaiduMapCrowdedApi(data) {
|
||||||
|
return request({
|
||||||
|
url: '/api/largeScreen/spot/baiduMapCrowded',
|
||||||
|
method: 'get',
|
||||||
|
params: data
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
33
src/api/news.js
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
import request from './request'
|
||||||
|
|
||||||
|
// 最新消息
|
||||||
|
export function getNewsListApi() {
|
||||||
|
return request({
|
||||||
|
url: '/api/largeScreen/news/list',
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 异常点位告警排行
|
||||||
|
export function getNewsPointRankApi() {
|
||||||
|
return request({
|
||||||
|
url: '/api/largeScreen/news/pointRank',
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 消息分类统计
|
||||||
|
export function getNewsStateApi() {
|
||||||
|
return request({
|
||||||
|
url: '/api/largeScreen/news/state',
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 消息统计
|
||||||
|
export function getNewsTotalApi() {
|
||||||
|
return request({
|
||||||
|
url: '/api/largeScreen/news/total',
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -4,95 +4,11 @@ import { ElMessage } from 'element-plus'
|
|||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
|
||||||
const CODE_MESSAGE = {
|
|
||||||
200: '服务器成功返回请求数据',
|
|
||||||
201: '新建或修改数据成功',
|
|
||||||
202: '一个请求已经进入后台排队(异步任务)',
|
|
||||||
204: '删除数据成功',
|
|
||||||
400: '发出信息有误',
|
|
||||||
401: '用户没有权限(令牌失效、用户名、密码错误、登录过期)',
|
|
||||||
402: '令牌过期',
|
|
||||||
403: '用户得到授权,但是访问是被禁止的',
|
|
||||||
404: '访问资源不存在',
|
|
||||||
406: '请求格式不可得',
|
|
||||||
410: '请求资源被永久删除,且不会被看到',
|
|
||||||
500: '服务器发生错误',
|
|
||||||
502: '网关错误',
|
|
||||||
503: '服务不可用,服务器暂时过载或维护',
|
|
||||||
504: '网关超时'
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* axios响应拦截器
|
|
||||||
* @param config 请求配置
|
|
||||||
* @param data response数据
|
|
||||||
* @param status HTTP status
|
|
||||||
* @param statusText HTTP status text
|
|
||||||
* @returns {Promise<*|*>}
|
|
||||||
*/
|
|
||||||
const handleData = async ({ data, status, statusText }) => {
|
|
||||||
// 若data.code存在,覆盖默认code
|
|
||||||
let code = data && data['code'] ? data['code'] : status
|
|
||||||
// 若code属于操作正常code,则status修改为200
|
|
||||||
const codeVerificationArray = [200, 1, '200', '1']
|
|
||||||
if (codeVerificationArray.indexOf(data['code']) + 1) code = 1
|
|
||||||
switch (code) {
|
|
||||||
case 1:
|
|
||||||
// 业务层级错误处理,以下是假定restful有一套统一输出格式(指不管成功与否都有相应的数据格式)情况下进行处理
|
|
||||||
// 例如响应内容:
|
|
||||||
// 错误内容:{ code: 0, msg: '非法参数' }
|
|
||||||
// 正确内容:{ code: 1, data: { }, msg: '操作正常' }
|
|
||||||
// return data
|
|
||||||
return data
|
|
||||||
case 401:
|
|
||||||
router
|
|
||||||
.push({
|
|
||||||
path: '/',
|
|
||||||
replace: true
|
|
||||||
})
|
|
||||||
.then(() => {})
|
|
||||||
break
|
|
||||||
case 402:
|
|
||||||
router
|
|
||||||
.push({
|
|
||||||
path: '/',
|
|
||||||
replace: true
|
|
||||||
})
|
|
||||||
.then(() => {})
|
|
||||||
break
|
|
||||||
case 403:
|
|
||||||
router
|
|
||||||
.push({
|
|
||||||
path: '/'
|
|
||||||
})
|
|
||||||
.then(() => {})
|
|
||||||
break
|
|
||||||
}
|
|
||||||
// 异常处理
|
|
||||||
// 若data.msg存在,覆盖默认提醒消息
|
|
||||||
let errMsg = `${
|
|
||||||
data && data['msg'] ? data['msg'] : CODE_MESSAGE[code] ? CODE_MESSAGE[code] : statusText
|
|
||||||
}`
|
|
||||||
if (code === 401) {
|
|
||||||
errMsg = '您的登录信息已过期,请重新登录...'
|
|
||||||
} else if (code == 500 && errMsg == '房间不存在') {
|
|
||||||
console.log('') //大屏直播页面没有直播时做了轮询,如果没有房间,会一直报异常,这里把异常弹窗去掉
|
|
||||||
} else {
|
|
||||||
// 是否显示高亮错误(与errorHandler钩子触发逻辑一致)
|
|
||||||
// $baseMessage(errMsg, 'error', 'vab-hey-message-error', false)
|
|
||||||
ElMessage({
|
|
||||||
message: errMsg,
|
|
||||||
type: 'error',
|
|
||||||
duration: 5 * 1000
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return Promise.reject(data)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description axios初始化
|
* @description axios初始化
|
||||||
*/
|
*/
|
||||||
const instance = axios.create({
|
const instance = axios.create({
|
||||||
|
// baseURL: 'http://36.138.38.16:6180/fjtcc-api',
|
||||||
baseURL: 'http://36.138.38.16:8001/fjtcc-api',
|
baseURL: 'http://36.138.38.16:8001/fjtcc-api',
|
||||||
timeout: 100000,
|
timeout: 100000,
|
||||||
headers: {
|
headers: {
|
||||||
@@ -102,13 +18,18 @@ const instance = axios.create({
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const isHttpsOrHttp = (url) => {
|
||||||
|
return /^https?:\/\//i.test(url)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description axios请求拦截器
|
* @description axios请求拦截器
|
||||||
*/
|
*/
|
||||||
instance.interceptors.request.use(
|
instance.interceptors.request.use(
|
||||||
(config) => {
|
(config) => {
|
||||||
if (config.data && config.headers['Content-Type'] === 'application/json";charset=UTF-8')
|
if (isHttpsOrHttp(config.url)) {
|
||||||
config.data = config.data
|
config.baseURL = ''
|
||||||
|
}
|
||||||
return config
|
return config
|
||||||
},
|
},
|
||||||
(error) => {
|
(error) => {
|
||||||
@@ -116,21 +37,17 @@ instance.interceptors.request.use(
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
/**
|
|
||||||
* @description axios响应拦截器
|
|
||||||
*/
|
|
||||||
instance.interceptors.response.use(
|
instance.interceptors.response.use(
|
||||||
(response) => handleData(response),
|
(res) => {
|
||||||
(error) => {
|
if (res.data.code == 200) {
|
||||||
const { response } = error
|
return res.data
|
||||||
if (response === undefined) {
|
} else {
|
||||||
// Message({
|
return Promise.reject(res.data)
|
||||||
// message: '连接后台接口失败,可能由以下原因造成:后端不支持跨域CORS、接口地址不存在、请求超时等,请联系管理员排查后端接口问题',
|
}
|
||||||
// type: 'error',
|
},
|
||||||
// duration: 5 * 1000,
|
(err) => {
|
||||||
// })
|
// 对响应错误做些什么
|
||||||
return {}
|
return Promise.reject(err.response)
|
||||||
} else return handleData(response)
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
6
src/assets/images/dot-error.svg
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<svg width="8" height="8" viewBox="0 0 8 8" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<g id="Group 1364">
|
||||||
|
<circle id="Ellipse 141" cx="4" cy="4" r="4" fill="#D9011B" fill-opacity="0.4"/>
|
||||||
|
<circle id="Ellipse 142" cx="2" cy="4" r="2" fill="#D9011B"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 267 B |
|
Before Width: | Height: | Size: 267 B After Width: | Height: | Size: 267 B |
6
src/assets/images/dot-success.svg
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<svg width="8" height="8" viewBox="0 0 8 8" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<g id="Group 1366">
|
||||||
|
<circle id="Ellipse 141" cx="4" cy="4" r="4" fill="#2380FB" fill-opacity="0.4"/>
|
||||||
|
<circle id="Ellipse 142" cx="2" cy="4" r="2" fill="#2380FB"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 267 B |
6
src/assets/images/dot-warning.svg
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<svg width="8" height="8" viewBox="0 0 8 8" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<g id="Group 1365">
|
||||||
|
<circle id="Ellipse 141" cx="4" cy="4" r="4" fill="#FEAE00" fill-opacity="0.4"/>
|
||||||
|
<circle id="Ellipse 142" cx="2" cy="4" r="2" fill="#FEAE00"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 267 B |
|
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 28 KiB |
BIN
src/assets/images/mask-primary.png
Normal file
|
After Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 28 KiB |
BIN
src/assets/images/mask-warning.png
Normal file
|
After Width: | Height: | Size: 28 KiB |
@@ -11,12 +11,11 @@
|
|||||||
>
|
>
|
||||||
<div>
|
<div>
|
||||||
<p :class="[index % 2 === 0 ? 'item-title--primary' : 'item-title--error']">
|
<p :class="[index % 2 === 0 ? 'item-title--primary' : 'item-title--error']">
|
||||||
三峡之巅-最新异常名称三峡之巅-最新异常名称三峡之巅-最新异常名称
|
{{ item.cameraName }}
|
||||||
</p>
|
</p>
|
||||||
<!-- <img class="item-img" src="@/assets/images/cover.png" /> -->
|
|
||||||
<video
|
<video
|
||||||
class="item-img"
|
class="item-img"
|
||||||
:ref="(el) => getRefs(el, index)"
|
:ref="(el) => getRefs(el, item, index)"
|
||||||
muted
|
muted
|
||||||
autoplay
|
autoplay
|
||||||
controls
|
controls
|
||||||
@@ -38,10 +37,15 @@
|
|||||||
|
|
||||||
let list = ref([])
|
let list = ref([])
|
||||||
|
|
||||||
const getRefs = (el) => {
|
const getRefs = async (el, item) => {
|
||||||
if (el) {
|
if (el) {
|
||||||
|
let res = await postRefreshApi({
|
||||||
|
businessVideoDisplayPosition: item.businessVideoDisplayPosition,
|
||||||
|
cameraIndexCode: item.cameraIndexCode
|
||||||
|
})
|
||||||
|
let hlsUrl = res.data.hlsUrl.replace('http://172.22.15.170:8050', 'http://36.138.38.16:6150')
|
||||||
const hls = new Hls()
|
const hls = new Hls()
|
||||||
hls.loadSource('http://36.138.38.16:6106/live/042f4987808b444aa96c1e8bc6e3ad2a/hls.m3u8')
|
hls.loadSource(hlsUrl)
|
||||||
hls.attachMedia(el)
|
hls.attachMedia(el)
|
||||||
hls.on(Hls.Events.MANIFEST_PARSED, () => {
|
hls.on(Hls.Events.MANIFEST_PARSED, () => {
|
||||||
el.play()
|
el.play()
|
||||||
@@ -135,7 +139,7 @@
|
|||||||
}
|
}
|
||||||
&-img {
|
&-img {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: vw(164);
|
height: vh(164);
|
||||||
display: block;
|
display: block;
|
||||||
object-fit: cover;
|
object-fit: cover;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="count-item">
|
<div class="count-item">
|
||||||
<div class="flex align-center">
|
<div class="flex align-center">
|
||||||
<img src="@/assets/images/dian.svg" />
|
<img src="@/assets/images/dot-primary.svg" />
|
||||||
<span class="label">{{ label }}</span>
|
<span class="label">{{ label }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="count">
|
<div class="count">
|
||||||
|
|||||||
@@ -131,10 +131,8 @@
|
|||||||
{ name: '交通', path: '/traffic' }
|
{ name: '交通', path: '/traffic' }
|
||||||
]
|
]
|
||||||
navRight.value = [
|
navRight.value = [
|
||||||
{ name: '停车' },
|
|
||||||
{ name: '工单', path: '/workOrder' },
|
{ name: '工单', path: '/workOrder' },
|
||||||
{ name: '舆情', path: '/sentiment' },
|
{ name: '舆情', path: '/sentiment' }
|
||||||
{ name: '酒店' }
|
|
||||||
]
|
]
|
||||||
break
|
break
|
||||||
case '/scenic':
|
case '/scenic':
|
||||||
|
|||||||
@@ -3,28 +3,11 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
onMounted(() => {
|
import { useMap } from '@/hooks/map'
|
||||||
var map = new BMapGL.Map('container')
|
|
||||||
map.centerAndZoom(new BMapGL.Point(109.643452, 31.028006), 15)
|
|
||||||
map.enableScrollWheelZoom(true)
|
|
||||||
map.setMapType(BMAP_SATELLITE_MAP)
|
|
||||||
|
|
||||||
// 绘制线
|
onMounted(() => {
|
||||||
var polyline = new BMapGL.Polyline(
|
const { initMap, addMarker } = useMap()
|
||||||
[
|
initMap('car-ship', 109.491961, 31.024285, 13)
|
||||||
new BMapGL.Point(109.65053, 31.034752),
|
|
||||||
new BMapGL.Point(109.647332, 31.033104),
|
|
||||||
new BMapGL.Point(109.646883, 31.031797),
|
|
||||||
new BMapGL.Point(109.640254, 31.021136)
|
|
||||||
],
|
|
||||||
{
|
|
||||||
strokeStyle: 'solid',
|
|
||||||
strokeColor: 'red ',
|
|
||||||
strokeWeight: 4,
|
|
||||||
strokeOpacity: 0.8
|
|
||||||
}
|
|
||||||
)
|
|
||||||
map.addOverlay(polyline)
|
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -3,10 +3,11 @@ import { ref } from 'vue'
|
|||||||
export function useMap() {
|
export function useMap() {
|
||||||
let map = ref(null)
|
let map = ref(null)
|
||||||
// 初始化地图
|
// 初始化地图
|
||||||
const initMap = (id, lat, lng, scale = 15) => {
|
const initMap = (id, lat, lng, scale = 15, satellite) => {
|
||||||
map.value = new BMapGL.Map(id)
|
map.value = new BMapGL.Map(id)
|
||||||
map.value.centerAndZoom(new BMapGL.Point(lat, lng), scale)
|
map.value.centerAndZoom(new BMapGL.Point(lat, lng), scale)
|
||||||
map.value.enableScrollWheelZoom(true)
|
map.value.enableScrollWheelZoom(true)
|
||||||
|
if (satellite) map.value.setMapType(BMAP_SATELLITE_MAP)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 添加图标
|
// 添加图标
|
||||||
|
|||||||
@@ -48,6 +48,7 @@
|
|||||||
series: [
|
series: [
|
||||||
{
|
{
|
||||||
type: 'pie',
|
type: 'pie',
|
||||||
|
clockwise: false,
|
||||||
silent: true,
|
silent: true,
|
||||||
center: ['30%', '50%'],
|
center: ['30%', '50%'],
|
||||||
radius: ['60%', '70%'],
|
radius: ['60%', '70%'],
|
||||||
@@ -65,6 +66,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'pie',
|
type: 'pie',
|
||||||
|
clockwise: false,
|
||||||
silent: true,
|
silent: true,
|
||||||
center: ['30%', '50%'],
|
center: ['30%', '50%'],
|
||||||
radius: ['54%', '58%'],
|
radius: ['54%', '58%'],
|
||||||
@@ -82,6 +84,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'pie',
|
type: 'pie',
|
||||||
|
clockwise: false,
|
||||||
silent: true,
|
silent: true,
|
||||||
center: ['30%', '50%'],
|
center: ['30%', '50%'],
|
||||||
radius: ['0', '40%'],
|
radius: ['0', '40%'],
|
||||||
@@ -95,6 +98,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'pie',
|
type: 'pie',
|
||||||
|
clockwise: false,
|
||||||
silent: true,
|
silent: true,
|
||||||
center: ['30%', '50%'],
|
center: ['30%', '50%'],
|
||||||
radius: ['0', '26%'],
|
radius: ['0', '26%'],
|
||||||
@@ -116,7 +120,7 @@
|
|||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.age {
|
.age {
|
||||||
width: vw(290);
|
width: vw(300);
|
||||||
height: vh(120);
|
height: vh(120);
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -5,14 +5,14 @@
|
|||||||
<img class="more" src="@/assets/images/more.png" />
|
<img class="more" src="@/assets/images/more.png" />
|
||||||
</template>
|
</template>
|
||||||
</Title1>
|
</Title1>
|
||||||
<div class="flex pt-20">
|
<div class="list flex pt-20">
|
||||||
<div class="item" v-for="(item, index) in homeData?.scenicSpot" :key="index">
|
<div class="item" v-for="(item, index) in scenicSpot" :key="index">
|
||||||
<img v-if="index == 0" class="item-icon" src="@/assets/images/core.png" />
|
<img v-if="index == 0" class="item-icon" src="@/assets/images/core.png" />
|
||||||
<img v-if="index == 1" class="item-icon" src="@/assets/images/queue.png" />
|
<img v-if="index == 1" class="item-icon" src="@/assets/images/queue.png" />
|
||||||
<img v-if="index == 2" class="item-icon" src="@/assets/images/congestion.png" />
|
<img v-if="index == 2" class="item-icon" src="@/assets/images/congestion.png" />
|
||||||
<span class="item-label">{{ item.name }}</span>
|
<span class="item-label">{{ item.name }}</span>
|
||||||
<div class="item-value flex align-end rela">
|
<div class="item-value flex align-end rela">
|
||||||
<countup :end-val="item.value" /><span class="unit">个</span>
|
<countup :end-val="item.value || 0" /><span class="unit">个</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -145,7 +145,7 @@
|
|||||||
<Title2 title="景区购票数" />
|
<Title2 title="景区购票数" />
|
||||||
<div class="ticket-wrap">
|
<div class="ticket-wrap">
|
||||||
<img src="@/assets/images/ticket.png" />
|
<img src="@/assets/images/ticket.png" />
|
||||||
<div v-for="(item, index) in homeData?.admission" :key="index">
|
<div v-for="(item, index) in admission" :key="index">
|
||||||
<span class="label">{{ item.name }}:</span><countup :end-val="item.value" />
|
<span class="label">{{ item.name }}:</span><countup :end-val="item.value" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -155,7 +155,7 @@
|
|||||||
<div class="flex">
|
<div class="flex">
|
||||||
<div class="age-box">
|
<div class="age-box">
|
||||||
<Title3 title="年龄/性别占比" />
|
<Title3 title="年龄/性别占比" />
|
||||||
<age />
|
<div class="mt-8"> <age /></div>
|
||||||
<div 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"
|
||||||
@@ -193,14 +193,32 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import countup from 'vue-countup-v3'
|
|
||||||
import top from './top.vue'
|
import top from './top.vue'
|
||||||
import age from './age.vue'
|
import age from './age.vue'
|
||||||
import gauge from './gauge.vue'
|
import gauge from './gauge.vue'
|
||||||
import ticket from './ticket.vue'
|
import ticket from './ticket.vue'
|
||||||
|
import countup from 'vue-countup-v3'
|
||||||
|
|
||||||
const homeData = inject('homeData')
|
const homeData = inject('homeData')
|
||||||
|
|
||||||
|
// 景区信息
|
||||||
|
const scenicSpot = computed(() => {
|
||||||
|
if (homeData.value) return homeData.value?.scenicSpot
|
||||||
|
return [
|
||||||
|
{ value: 0, name: '全县景区数量' },
|
||||||
|
{ value: 0, name: '核心景区数' },
|
||||||
|
{ value: 0, name: '低感景区总数' }
|
||||||
|
]
|
||||||
|
})
|
||||||
|
const admission = computed(() => {
|
||||||
|
if (homeData.value) return homeData.value?.admission
|
||||||
|
return [
|
||||||
|
{ name: '当日购票量:', value: 0 },
|
||||||
|
{ name: '未来3天购票量:', value: 0 },
|
||||||
|
{ name: '3天后购票量:', value: 0 }
|
||||||
|
]
|
||||||
|
})
|
||||||
|
// 年龄占比
|
||||||
const ageRateTotal = computed(() => {
|
const ageRateTotal = computed(() => {
|
||||||
return homeData.value?.userPortrait.genderRate.reduce(
|
return homeData.value?.userPortrait.genderRate.reduce(
|
||||||
(total, current) => Number(current.count) + total,
|
(total, current) => Number(current.count) + total,
|
||||||
@@ -208,9 +226,9 @@
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
const channelTotal = computed(() => {
|
const channelTotal = computed(() => {
|
||||||
return (
|
return homeData.value?.userPortrait?.channel.reduce(
|
||||||
homeData.value?.userPortrait?.channel ||
|
(total, current) => Number(current.count) + total,
|
||||||
[].reduce((total, current) => Number(current.count) + total, 0)
|
0
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
@@ -238,6 +256,9 @@
|
|||||||
bottom: -30%;
|
bottom: -30%;
|
||||||
z-index: 990;
|
z-index: 990;
|
||||||
}
|
}
|
||||||
|
.list {
|
||||||
|
height: vh(72);
|
||||||
|
}
|
||||||
.item {
|
.item {
|
||||||
position: relative;
|
position: relative;
|
||||||
height: vh(52);
|
height: vh(52);
|
||||||
@@ -258,8 +279,8 @@
|
|||||||
left: vw(70);
|
left: vw(70);
|
||||||
top: vh(-10);
|
top: vh(-10);
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
font-size: vw(14);
|
font-size: vw(16);
|
||||||
color: rgba(255, 255, 255, 0.7);
|
color: #ffffff;
|
||||||
}
|
}
|
||||||
&-value {
|
&-value {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
@@ -299,7 +320,7 @@
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
&-title {
|
&-title {
|
||||||
font-size: vw(14);
|
font-size: vw(18);
|
||||||
color: rgba(255, 255, 255, 0.9);
|
color: rgba(255, 255, 255, 0.9);
|
||||||
}
|
}
|
||||||
&-value {
|
&-value {
|
||||||
@@ -321,8 +342,8 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
.age-box {
|
.age-box {
|
||||||
width: vw(290);
|
width: vw(320);
|
||||||
height: vh(290);
|
height: vh(296);
|
||||||
background-image: url('@/assets/images/bg-3.png');
|
background-image: url('@/assets/images/bg-3.png');
|
||||||
background-size: 100% 100%;
|
background-size: 100% 100%;
|
||||||
&:nth-child(1) {
|
&:nth-child(1) {
|
||||||
@@ -330,8 +351,8 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
.box-1 {
|
.box-1 {
|
||||||
width: vw(240);
|
width: vw(230);
|
||||||
height: vh(290);
|
height: vh(296);
|
||||||
background-image: url('@/assets/images/bg-3.png');
|
background-image: url('@/assets/images/bg-3.png');
|
||||||
background-size: 100% 100%;
|
background-size: 100% 100%;
|
||||||
&:nth-child(2) {
|
&:nth-child(2) {
|
||||||
@@ -374,7 +395,7 @@
|
|||||||
color: rgba(255, 255, 255, 0.9);
|
color: rgba(255, 255, 255, 0.9);
|
||||||
}
|
}
|
||||||
.progress {
|
.progress {
|
||||||
width: vw(170);
|
width: vw(150);
|
||||||
margin-left: vw(4);
|
margin-left: vw(4);
|
||||||
:deep(.el-progress-bar__outer) {
|
:deep(.el-progress-bar__outer) {
|
||||||
background-color: #0858ae !important;
|
background-color: #0858ae !important;
|
||||||
|
|||||||
@@ -49,7 +49,19 @@
|
|||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<Map />
|
<div class="map" id="map"></div>
|
||||||
|
<div class="spot-wrap">
|
||||||
|
<ul class="spot-list">
|
||||||
|
<li
|
||||||
|
class="spot-item"
|
||||||
|
v-for="(item, index) in spotList"
|
||||||
|
:key="index"
|
||||||
|
@click="handleMap(item.scenicSpotId)"
|
||||||
|
>
|
||||||
|
<img :src="`http://36.138.38.16:8001/fjtcc-api${item.img}`" />
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="footer">
|
<div class="footer">
|
||||||
<div class="left">
|
<div class="left">
|
||||||
@@ -122,12 +134,24 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import countup from 'vue-countup-v3'
|
import countup from 'vue-countup-v3'
|
||||||
import ScrollNumber from '@/components/ScrollNumber/index.vue'
|
import ScrollNumber from '@/components/ScrollNumber/index.vue'
|
||||||
|
import { getSpotListApi, getBaiduMapCrowdedApi } from '@/api/home'
|
||||||
|
|
||||||
import icon8 from '@/assets/images/icon-8.png'
|
import icon8 from '@/assets/images/icon-8.png'
|
||||||
import icon9 from '@/assets/images/icon-9.png'
|
import icon9 from '@/assets/images/icon-9.png'
|
||||||
import icon10 from '@/assets/images/icon-10.png'
|
import icon10 from '@/assets/images/icon-10.png'
|
||||||
import icon11 from '@/assets/images/icon-11.png'
|
import icon11 from '@/assets/images/icon-11.png'
|
||||||
|
|
||||||
let count = ref('6945959')
|
import { useMap } from '@/hooks/map'
|
||||||
|
|
||||||
|
let emit = defineEmits(['switch-spot'])
|
||||||
|
|
||||||
|
const { map, initMap, addMarker } = useMap()
|
||||||
|
|
||||||
|
const homeData = inject('homeData')
|
||||||
|
|
||||||
|
let count = ref(69459)
|
||||||
|
let spotList = ref([])
|
||||||
|
|
||||||
let list = ref([
|
let list = ref([
|
||||||
{
|
{
|
||||||
label: '安全异常',
|
label: '安全异常',
|
||||||
@@ -146,14 +170,65 @@
|
|||||||
icon: icon11
|
icon: icon11
|
||||||
}
|
}
|
||||||
])
|
])
|
||||||
|
const handleMap = (e) => {
|
||||||
|
emit('switch-spot', e)
|
||||||
|
// map.value.centerAndZoom(new BMapGL.Point('108.704166', '30.94776'), 16)
|
||||||
|
}
|
||||||
|
const getSpotList = async () => {
|
||||||
|
let res = await getSpotListApi()
|
||||||
|
spotList.value = res.data
|
||||||
|
let res1 = await getBaiduMapCrowdedApi({
|
||||||
|
nodeId: res.data[0].nodeid
|
||||||
|
})
|
||||||
|
console.log(res1, 'res1')
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => homeData.value?.baiduMap,
|
||||||
|
(val) => {
|
||||||
|
if (val) init(val)
|
||||||
|
},
|
||||||
|
{ immediate: true }
|
||||||
|
)
|
||||||
|
const init = (val) => {
|
||||||
|
initMap('map', val.index.lng, val.index.lat, 15, false)
|
||||||
|
val.list.map((item) => {
|
||||||
|
item.map((i) => {
|
||||||
|
// 创建折线
|
||||||
|
let arr = []
|
||||||
|
i.path.map((j) => {
|
||||||
|
arr.push(new BMapGL.Point(j[0], j[1]))
|
||||||
|
})
|
||||||
|
var polyline = new BMapGL.Polyline(arr, {
|
||||||
|
strokeColor: '#1EBA29',
|
||||||
|
strokeWeight: 4,
|
||||||
|
strokeOpacity: 0.8
|
||||||
|
})
|
||||||
|
map.value.addOverlay(polyline)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
onMounted(() => {
|
||||||
|
getSpotList()
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
:deep(.BMap_cpyCtrl) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
:deep(.anchorBL) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.map {
|
||||||
|
width: 100%;
|
||||||
|
height: vh(700);
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
.box-3 {
|
.box-3 {
|
||||||
width: vw(1614);
|
width: vw(1614);
|
||||||
height: vh(950);
|
height: vh(950);
|
||||||
margin-top: vh(120);
|
margin-top: vh(120);
|
||||||
|
|
||||||
.header {
|
.header {
|
||||||
width: vw(1614);
|
width: vw(1614);
|
||||||
height: vh(128);
|
height: vh(128);
|
||||||
@@ -163,7 +238,7 @@
|
|||||||
background-size: 100% 100%;
|
background-size: 100% 100%;
|
||||||
.left {
|
.left {
|
||||||
display: flex;
|
display: flex;
|
||||||
width: vw(950);
|
width: vw(890);
|
||||||
margin-top: vh(20);
|
margin-top: vh(20);
|
||||||
}
|
}
|
||||||
.right {
|
.right {
|
||||||
@@ -176,7 +251,7 @@
|
|||||||
.label {
|
.label {
|
||||||
margin-bottom: vh(20);
|
margin-bottom: vh(20);
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
font-size: vw(16);
|
font-size: vw(18);
|
||||||
color: rgba(255, 255, 255, 0.9);
|
color: rgba(255, 255, 255, 0.9);
|
||||||
}
|
}
|
||||||
.value {
|
.value {
|
||||||
@@ -224,6 +299,26 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.spot-wrap {
|
||||||
|
position: absolute;
|
||||||
|
bottom: vw(20);
|
||||||
|
left: vw(20);
|
||||||
|
z-index: 99999;
|
||||||
|
}
|
||||||
|
.spot-list {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
.spot-item {
|
||||||
|
cursor: pointer;
|
||||||
|
width: vw(80);
|
||||||
|
height: vw(80);
|
||||||
|
margin-right: vw(10);
|
||||||
|
> img {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
.footer {
|
.footer {
|
||||||
display: flex;
|
display: flex;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|||||||
@@ -204,7 +204,7 @@
|
|||||||
v-for="(item, index) in homeData?.carShipData?.car.info"
|
v-for="(item, index) in homeData?.carShipData?.car.info"
|
||||||
:key="index"
|
:key="index"
|
||||||
>
|
>
|
||||||
<div>{{ item.scenic_area }}</div>
|
<div>{{ item.name }}</div>
|
||||||
<div>{{ item.started_count }}<span class="unit-1">辆</span></div>
|
<div>{{ item.started_count }}<span class="unit-1">辆</span></div>
|
||||||
<div>{{ item.not_started_count }}<span class="unit-1">辆</span></div>
|
<div>{{ item.not_started_count }}<span class="unit-1">辆</span></div>
|
||||||
</div>
|
</div>
|
||||||
@@ -213,7 +213,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<div class="ship">
|
<div class="ship">
|
||||||
<div class="label">车总数</div>
|
<div class="label">船总数</div>
|
||||||
<div class="flex align-center">
|
<div class="flex align-center">
|
||||||
<countup class="value" :end-val="homeData?.carShipData?.ship?.count || 0" />
|
<countup class="value" :end-val="homeData?.carShipData?.ship?.count || 0" />
|
||||||
<span class="unit">辆</span>
|
<span class="unit">辆</span>
|
||||||
@@ -231,7 +231,7 @@
|
|||||||
v-for="(item, index) in homeData?.carShipData.ship.info"
|
v-for="(item, index) in homeData?.carShipData.ship.info"
|
||||||
:key="index"
|
:key="index"
|
||||||
>
|
>
|
||||||
<div>白帝城</div>
|
<div>{{ item.name }}</div>
|
||||||
<div>{{ item.started_count }}<span class="unit-1">辆</span></div>
|
<div>{{ item.started_count }}<span class="unit-1">辆</span></div>
|
||||||
<div>{{ item.not_started_count }}<span class="unit-1">辆</span></div>
|
<div>{{ item.not_started_count }}<span class="unit-1">辆</span></div>
|
||||||
</div>
|
</div>
|
||||||
@@ -366,7 +366,7 @@
|
|||||||
}
|
}
|
||||||
.stop-box {
|
.stop-box {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: vw(20);
|
gap: vw(8);
|
||||||
|
|
||||||
& > div {
|
& > div {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
|
|||||||
@@ -90,21 +90,19 @@
|
|||||||
},
|
},
|
||||||
detail: {
|
detail: {
|
||||||
width: '100%',
|
width: '100%',
|
||||||
lineHeight: 20,
|
|
||||||
height: 20,
|
|
||||||
offsetCenter: [0, '20%'],
|
offsetCenter: [0, '20%'],
|
||||||
valueAnimation: true,
|
valueAnimation: true,
|
||||||
formatter: function (value) {
|
formatter: function (value) {
|
||||||
return '{value|' + value.toFixed(0) + '}{unit|%}'
|
return '{value|' + value + '}{unit|%}'
|
||||||
},
|
},
|
||||||
rich: {
|
rich: {
|
||||||
value: {
|
value: {
|
||||||
fontSize: fitChartSize(12),
|
fontSize: fitChartSize(18),
|
||||||
fontWeight: 'bolder',
|
fontWeight: 'bolder',
|
||||||
color: '#02F9FA'
|
color: '#02F9FA'
|
||||||
},
|
},
|
||||||
unit: {
|
unit: {
|
||||||
fontSize: fitChartSize(12),
|
fontSize: fitChartSize(18),
|
||||||
color: '#02F9FA'
|
color: '#02F9FA'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
<!-- 酒店入住人数及入住率 -->
|
||||||
<template>
|
<template>
|
||||||
<div class="lodging-ratio" :id="id" />
|
<div class="lodging-ratio" :id="id" />
|
||||||
</template>
|
</template>
|
||||||
@@ -9,10 +10,61 @@
|
|||||||
const { id, setOption } = useEchart()
|
const { id, setOption } = useEchart()
|
||||||
|
|
||||||
const homeData = inject('homeData')
|
const homeData = inject('homeData')
|
||||||
|
|
||||||
|
let params = null
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => homeData.value?.hotelData?.list,
|
() => homeData.value?.hotelData?.list,
|
||||||
() => {
|
() => {
|
||||||
setOption({
|
init()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
const setSeriesData = () => {
|
||||||
|
return homeData.value?.hotelData?.list.map((item) => {
|
||||||
|
return {
|
||||||
|
name: item.hotel_name,
|
||||||
|
value: item.occupancy_rate,
|
||||||
|
itemStyle: {
|
||||||
|
barBorderRadius: [0, 0, 0, 0],
|
||||||
|
color: {
|
||||||
|
type: 'linear',
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
x2: 1,
|
||||||
|
y2: 1,
|
||||||
|
colorStops: [
|
||||||
|
{
|
||||||
|
offset: 0,
|
||||||
|
color: 'rgba(255, 112, 33, 0)'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
offset: 1,
|
||||||
|
color: parseFloat(item.occupancy_rate) > 50 ? '#FF7021' : '#00CCFF'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const setCircleData = () => {
|
||||||
|
return homeData.value?.hotelData?.list.map((item) => {
|
||||||
|
return {
|
||||||
|
name: item.hotel_name,
|
||||||
|
value: item.occupancy_rate,
|
||||||
|
itemStyle: {
|
||||||
|
color: '#fff',
|
||||||
|
opacity: 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const init = () => {
|
||||||
|
if (!params) {
|
||||||
|
params = {
|
||||||
backgroundColor: 'transparent',
|
backgroundColor: 'transparent',
|
||||||
tooltip: {
|
tooltip: {
|
||||||
show: false
|
show: false
|
||||||
@@ -30,20 +82,20 @@
|
|||||||
xAxis: [{ max: 100, show: false }],
|
xAxis: [{ max: 100, show: false }],
|
||||||
yAxis: [
|
yAxis: [
|
||||||
{
|
{
|
||||||
|
type: 'category',
|
||||||
splitLine: {
|
splitLine: {
|
||||||
show: false
|
show: false
|
||||||
},
|
},
|
||||||
axisLine: {
|
axisLine: {
|
||||||
show: false
|
show: false
|
||||||
},
|
},
|
||||||
type: 'category',
|
|
||||||
axisTick: {
|
axisTick: {
|
||||||
show: false
|
show: false
|
||||||
},
|
},
|
||||||
data: homeData.value?.hotelData?.list.map((item) => item.hotel_name),
|
|
||||||
axisLabel: {
|
axisLabel: {
|
||||||
show: false
|
show: false
|
||||||
}
|
},
|
||||||
|
data: homeData.value?.hotelData?.list.map((item) => item.hotel_name)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'category',
|
type: 'category',
|
||||||
@@ -56,23 +108,21 @@
|
|||||||
fontSize: fitChartSize(12)
|
fontSize: fitChartSize(12)
|
||||||
},
|
},
|
||||||
verticalAlign: 'bottom',
|
verticalAlign: 'bottom',
|
||||||
padding: [0, 0, fitChartSize(6), 0],
|
padding: [0, 0, 6, 0],
|
||||||
inside: true,
|
inside: true,
|
||||||
formatter: function (value) {
|
formatter: function (value) {
|
||||||
return `{value|${value}}`
|
return `{value|${value}} {value|%}`
|
||||||
},
|
},
|
||||||
rich: {
|
rich: {
|
||||||
name: {
|
name: {
|
||||||
align: 'center',
|
align: 'center',
|
||||||
color: '#D3E5FF',
|
color: '#D3E5FF',
|
||||||
fontSize: fitChartSize(14),
|
fontSize: fitChartSize(14)
|
||||||
fontFamily: 'Source Han Sans CN'
|
|
||||||
},
|
},
|
||||||
value: {
|
value: {
|
||||||
align: 'center',
|
align: 'center',
|
||||||
color: '#fff',
|
color: '#fff',
|
||||||
fontSize: fitChartSize(14),
|
fontSize: fitChartSize(14)
|
||||||
fontFamily: 'Source Han Sans CN'
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -81,54 +131,27 @@
|
|||||||
],
|
],
|
||||||
series: [
|
series: [
|
||||||
{
|
{
|
||||||
name: '',
|
name: '内圆',
|
||||||
type: 'bar',
|
type: 'bar',
|
||||||
barWidth: fitChartSize(4),
|
barWidth: 4,
|
||||||
MaxSize: 0,
|
|
||||||
showBackground: true,
|
showBackground: true,
|
||||||
barBorderRadius: [30, 0, 0, 30],
|
barBorderRadius: [0, 0, 0, 0],
|
||||||
backgroundStyle: {
|
backgroundStyle: {
|
||||||
color: 'rgba(0, 150, 255, 0.15)'
|
color: 'rgba(0, 150, 255, 0.15)'
|
||||||
},
|
},
|
||||||
label: {
|
label: {
|
||||||
show: true,
|
show: true,
|
||||||
offset: [fitChartSize(10), -fitChartSize(20)],
|
offset: [6, -10],
|
||||||
color: '#D3E5FF',
|
color: '#D3E5FF',
|
||||||
fontWeight: 500,
|
fontWeight: 500,
|
||||||
position: 'left',
|
position: 'left',
|
||||||
align: 'left',
|
align: 'left',
|
||||||
fontSize: fitChartSize(14),
|
fontSize: fitChartSize(14),
|
||||||
fontFamily: 'Source Han Sans CN',
|
|
||||||
formatter: function (params) {
|
formatter: function (params) {
|
||||||
return params.data.name
|
return params.data.name
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data: homeData.value?.hotelData?.list.map((item) => {
|
data: setSeriesData()
|
||||||
return {
|
|
||||||
name: item.hotel_name,
|
|
||||||
value: item.occupancy_rate,
|
|
||||||
itemStyle: {
|
|
||||||
barBorderRadius: [3, 0, 0, 3],
|
|
||||||
color: {
|
|
||||||
type: 'linear',
|
|
||||||
x: 0,
|
|
||||||
y: 0,
|
|
||||||
x2: 1,
|
|
||||||
y2: 1,
|
|
||||||
colorStops: [
|
|
||||||
{
|
|
||||||
offset: 0,
|
|
||||||
color: 'rgba(255, 112, 33, 0)'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
offset: 1,
|
|
||||||
color: 'rgba(255, 112, 33, 1)'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: '外圆',
|
name: '外圆',
|
||||||
@@ -140,22 +163,17 @@
|
|||||||
symbol: 'circle',
|
symbol: 'circle',
|
||||||
symbolSize: fitChartSize(10),
|
symbolSize: fitChartSize(10),
|
||||||
z: 2,
|
z: 2,
|
||||||
data: homeData.value?.hotelData?.list.map((item) => {
|
data: setCircleData(),
|
||||||
return {
|
|
||||||
name: item.hotel_name,
|
|
||||||
value: item.occupancy_rate,
|
|
||||||
itemStyle: {
|
|
||||||
color: '#fff',
|
|
||||||
opacity: 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
animationDelay: 500
|
animationDelay: 500
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
})
|
}
|
||||||
|
} else {
|
||||||
|
params.series[0].data = setSeriesData()
|
||||||
|
params.series[1].data = setCircleData()
|
||||||
}
|
}
|
||||||
)
|
setOption(params)
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
|
|||||||
@@ -1,5 +1,19 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="ticket" :id="id" />
|
<div>
|
||||||
|
<div class="ticket" :id="id" />
|
||||||
|
<!-- <div class="legend">
|
||||||
|
<ul class="legend__wrapper">
|
||||||
|
<li
|
||||||
|
class="legend-item"
|
||||||
|
v-for="(item, index) in homeData?.userPortrait?.channel"
|
||||||
|
:key="index"
|
||||||
|
>
|
||||||
|
<p class="legend-item-label">{{ item.name }}</p>
|
||||||
|
<p class="legend-item-value">{{ item.value }}%</p>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div> -->
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
@@ -12,13 +26,51 @@
|
|||||||
|
|
||||||
let x = 15
|
let x = 15
|
||||||
let y = 25
|
let y = 25
|
||||||
|
let params = null
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => homeData.value?.userPortrait?.channel,
|
() => homeData.value?.userPortrait?.channel,
|
||||||
() => {
|
(val) => {
|
||||||
setOption({
|
if (val) init()
|
||||||
|
},
|
||||||
|
{
|
||||||
|
immediate: true
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
const setSeries = () => {
|
||||||
|
return homeData.value?.userPortrait?.channel.map((item, index) => {
|
||||||
|
return {
|
||||||
|
name: item.name,
|
||||||
|
clockwise: false,
|
||||||
|
type: 'pie',
|
||||||
|
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'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const init = () => {
|
||||||
|
if (!params) {
|
||||||
|
params = {
|
||||||
backgroundColor: 'transparent',
|
backgroundColor: 'transparent',
|
||||||
legend: {
|
legend: {
|
||||||
|
show: true,
|
||||||
x: 'center',
|
x: 'center',
|
||||||
y: 'bottom',
|
y: 'bottom',
|
||||||
itemHeight: fitChartSize(8),
|
itemHeight: fitChartSize(8),
|
||||||
@@ -41,35 +93,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
color: ['#F15A25', '#01FEFE', '#12B5FD'],
|
color: ['#F15A25', '#01FEFE', '#12B5FD'],
|
||||||
series:
|
series: setSeries()
|
||||||
homeData.value?.userPortrait?.channel ||
|
}
|
||||||
[].map((item, index) => {
|
} else {
|
||||||
return {
|
params.series = setSeries()
|
||||||
name: item.name,
|
|
||||||
type: 'pie',
|
|
||||||
clockwise: false, //顺时加载
|
|
||||||
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'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
)
|
setOption(params)
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
@@ -77,4 +107,69 @@
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
height: vh(200);
|
height: vh(200);
|
||||||
}
|
}
|
||||||
|
.legend {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
@mixin icon($column) {
|
||||||
|
padding: 0 vw(10);
|
||||||
|
height: vh(70);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: $column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__wrapper {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: vw(8);
|
||||||
|
}
|
||||||
|
&-item {
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
&-item:nth-child(1) {
|
||||||
|
@include icon(column);
|
||||||
|
background-image: url('@/assets/images/legend-item-1.png');
|
||||||
|
background-size: 100% 100%;
|
||||||
|
}
|
||||||
|
&-item:nth-child(2) {
|
||||||
|
@include icon(column);
|
||||||
|
background-image: url('@/assets/images/legend-item-1.png');
|
||||||
|
background-size: 100% 100%;
|
||||||
|
}
|
||||||
|
&-item:nth-child(3) {
|
||||||
|
@include icon(column);
|
||||||
|
background-image: url('@/assets/images/legend-item-1.png');
|
||||||
|
background-size: 100% 100%;
|
||||||
|
}
|
||||||
|
&-item:nth-child(4) {
|
||||||
|
@include icon(column-reverse);
|
||||||
|
background-image: url('@/assets/images/legend-item-2.png');
|
||||||
|
background-size: 100% 100%;
|
||||||
|
}
|
||||||
|
&-item:nth-child(5) {
|
||||||
|
@include icon(column-reverse);
|
||||||
|
background-image: url('@/assets/images/legend-item-2.png');
|
||||||
|
background-size: 100% 100%;
|
||||||
|
}
|
||||||
|
&-item:nth-child(6) {
|
||||||
|
@include icon(column-reverse);
|
||||||
|
background-image: url('@/assets/images/legend-item-2.png');
|
||||||
|
background-size: 100% 100%;
|
||||||
|
}
|
||||||
|
&-item-label {
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: vw(12);
|
||||||
|
line-height: vh(14);
|
||||||
|
}
|
||||||
|
&-item-value {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: vw(16);
|
||||||
|
line-height: vh(18);
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -51,26 +51,19 @@
|
|||||||
axisLabel: {
|
axisLabel: {
|
||||||
textStyle: {
|
textStyle: {
|
||||||
color: '#fff',
|
color: '#fff',
|
||||||
fontSize: fitChartSize(12)
|
fontSize: fitChartSize(18)
|
||||||
},
|
},
|
||||||
verticalAlign: 'bottom',
|
verticalAlign: 'bottom',
|
||||||
padding: [0, 0, fitChartSize(10), 0],
|
padding: [0, -fitChartSize(10), fitChartSize(10), 0],
|
||||||
inside: true,
|
inside: true,
|
||||||
formatter: function (value) {
|
formatter: function (value) {
|
||||||
return `{value|${value}}%`
|
return `{value|${value}}%`
|
||||||
},
|
},
|
||||||
rich: {
|
rich: {
|
||||||
name: {
|
|
||||||
align: 'center',
|
|
||||||
color: '#D3E5FF',
|
|
||||||
fontSize: fitChartSize(14),
|
|
||||||
fontFamily: 'Source Han Sans CN'
|
|
||||||
},
|
|
||||||
value: {
|
value: {
|
||||||
align: 'center',
|
align: 'center',
|
||||||
color: '#fff',
|
color: '#fff',
|
||||||
fontSize: fitChartSize(14),
|
fontSize: fitChartSize(14)
|
||||||
fontFamily: 'Source Han Sans CN'
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -79,51 +72,32 @@
|
|||||||
],
|
],
|
||||||
series: [
|
series: [
|
||||||
{
|
{
|
||||||
name: '',
|
|
||||||
type: 'bar',
|
type: 'bar',
|
||||||
barWidth: fitChartSize(12),
|
barWidth: fitChartSize(12),
|
||||||
MaxSize: 0,
|
|
||||||
showBackground: true,
|
showBackground: true,
|
||||||
barBorderRadius: [fitChartSize(30), 0, 0, fitChartSize(30)],
|
barBorderRadius: [0, 0, 0, 0],
|
||||||
backgroundStyle: {
|
backgroundStyle: {
|
||||||
color: 'rgba(0, 150, 255, 0.15)'
|
color: 'rgba(0, 150, 255, 0.15)'
|
||||||
},
|
},
|
||||||
label: {
|
label: {
|
||||||
show: true,
|
show: true,
|
||||||
offset: [fitChartSize(10), -fitChartSize(17)],
|
offset: [fitChartSize(12), -fitChartSize(20)],
|
||||||
color: '#D3E5FF',
|
color: '#D3E5FF',
|
||||||
fontWeight: 500,
|
fontWeight: 500,
|
||||||
position: 'left',
|
position: 'left',
|
||||||
align: 'left',
|
align: 'left',
|
||||||
fontSize: fitChartSize(14),
|
fontSize: fitChartSize(14),
|
||||||
fontFamily: 'Source Han Sans CN',
|
|
||||||
formatter: function (params) {
|
formatter: function (params) {
|
||||||
return params.data.name
|
return params.data.name ?? '其他'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data: homeData.value?.userPortrait?.provinceRate.map((item, index) => {
|
data: homeData.value?.userPortrait?.provinceRate.map((item) => {
|
||||||
return {
|
return {
|
||||||
name: item.name,
|
name: item.name,
|
||||||
value: Number(item.value),
|
value: Number(item.value),
|
||||||
itemStyle: {
|
itemStyle: {
|
||||||
barBorderRadius: [3, 0, 0, 3],
|
barBorderRadius: [0, 0, 0, 0],
|
||||||
color: {
|
color: parseFloat(item.value) > 50 ? '#FF7021' : '#00CCFF'
|
||||||
type: 'linear',
|
|
||||||
x: 0,
|
|
||||||
y: 0,
|
|
||||||
x2: 1,
|
|
||||||
y2: 1,
|
|
||||||
colorStops: [
|
|
||||||
{
|
|
||||||
offset: 0,
|
|
||||||
color: 'transparent'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
offset: 1,
|
|
||||||
color: parseFloat(item.value) > 50 ? '#FF7021' : '#00CCFF'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<box1 />
|
<box1 />
|
||||||
<box2 />
|
<box2 @switch-spot="switchSpot" />
|
||||||
<box3 />
|
<box3 />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -22,10 +22,20 @@
|
|||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
action: 'start',
|
action: 'start',
|
||||||
type: 'index',
|
type: 'index',
|
||||||
scenitspot: 'index'
|
scenicSpot: '4'
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const switchSpot = (e) => {
|
||||||
|
sendMessage(
|
||||||
|
JSON.stringify({
|
||||||
|
action: 'start',
|
||||||
|
type: 'index',
|
||||||
|
scenicSpot: e
|
||||||
|
})
|
||||||
|
)
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -43,7 +43,7 @@
|
|||||||
<div class="footer">
|
<div class="footer">
|
||||||
<div class="flex">
|
<div class="flex">
|
||||||
<div class="item">
|
<div class="item">
|
||||||
<progress1 :width="140" :height="70" />
|
<CircleProgress :width="170" :height="90" />
|
||||||
<div>
|
<div>
|
||||||
<div class="bg">
|
<div class="bg">
|
||||||
<span class="label">今日工单总条数:</span>
|
<span class="label">今日工单总条数:</span>
|
||||||
@@ -56,7 +56,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="item">
|
<div class="item">
|
||||||
<progress1 :width="140" :height="70" />
|
<CircleProgress :width="170" :height="90" />
|
||||||
<div>
|
<div>
|
||||||
<div class="bg">
|
<div class="bg">
|
||||||
<span class="label">今日工单总条数:</span>
|
<span class="label">今日工单总条数:</span>
|
||||||
@@ -101,9 +101,6 @@
|
|||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import countup from 'vue-countup-v3'
|
import countup from 'vue-countup-v3'
|
||||||
import progress1 from './progress-1.vue'
|
|
||||||
|
|
||||||
let count = ref('58459')
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
@@ -178,7 +175,7 @@
|
|||||||
.footer {
|
.footer {
|
||||||
.item {
|
.item {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
height: vh(120);
|
height: vh(140);
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
background-image: url('@/assets/images/bg-3.png');
|
background-image: url('@/assets/images/bg-3.png');
|
||||||
@@ -197,6 +194,7 @@
|
|||||||
margin-bottom: vh(4);
|
margin-bottom: vh(4);
|
||||||
}
|
}
|
||||||
.label {
|
.label {
|
||||||
|
width: vw(120);
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
font-size: vw(14);
|
font-size: vw(14);
|
||||||
color: #fff;
|
color: #fff;
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
<div class="box mr-8">
|
<div class="box mr-8">
|
||||||
<Title1 title="景区承载" />
|
<Title1 title="景区承载" />
|
||||||
<div class="flex">
|
<div class="flex">
|
||||||
<progress1 :width="200" :height="70" />
|
<circle-progress :width="200" :height="70" />
|
||||||
<div class="flex flex-1 justify-between">
|
<div class="flex flex-1 justify-between">
|
||||||
<count-item label="景区当前人数" :count="35600" suffix="张" />
|
<count-item label="景区当前人数" :count="35600" suffix="张" />
|
||||||
<count-item label="景区最大承载" :count="35600" suffix="人" />
|
<count-item label="景区最大承载" :count="35600" suffix="人" />
|
||||||
@@ -36,9 +36,9 @@
|
|||||||
<Title1 title="停车信息" />
|
<Title1 title="停车信息" />
|
||||||
<div class="flex">
|
<div class="flex">
|
||||||
<div class="flex">
|
<div class="flex">
|
||||||
<progress1 :width="140" :height="70" />
|
<circle-progress :width="140" :height="70" />
|
||||||
<progress1 :width="140" :height="70" />
|
<circle-progress :width="140" :height="70" />
|
||||||
<progress1 :width="140" :height="70" />
|
<circle-progress :width="140" :height="70" />
|
||||||
</div>
|
</div>
|
||||||
<div class="ml-20 flex flex-1 justify-between">
|
<div class="ml-20 flex flex-1 justify-between">
|
||||||
<count-item label="总停车场数" :count="561" suffix="个" />
|
<count-item label="总停车场数" :count="561" suffix="个" />
|
||||||
@@ -90,7 +90,7 @@
|
|||||||
<traffic-flow />
|
<traffic-flow />
|
||||||
</div>
|
</div>
|
||||||
<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">
|
<div class="legend">
|
||||||
<ul class="legend__wrapper">
|
<ul class="legend__wrapper">
|
||||||
@@ -102,7 +102,7 @@
|
|||||||
</div>
|
</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">
|
<div class="legend">
|
||||||
<ul class="legend__wrapper">
|
<ul class="legend__wrapper">
|
||||||
@@ -229,7 +229,6 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import progress1 from './progress-1.vue'
|
|
||||||
import { useMap } from '@/hooks/map'
|
import { useMap } from '@/hooks/map'
|
||||||
import carIcon from '@/assets/images/car.png'
|
import carIcon from '@/assets/images/car.png'
|
||||||
import shipIcon from '@/assets/images/ship.png'
|
import shipIcon from '@/assets/images/ship.png'
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="traffic-flow" id="traffic-flow" />
|
<div class="traffic-flow" :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'
|
||||||
|
|
||||||
let trafficChart = null
|
const { id, setOption } = useEchart()
|
||||||
|
|
||||||
let option = {
|
let option = {
|
||||||
grid: {
|
grid: {
|
||||||
@@ -19,7 +19,7 @@
|
|||||||
xAxis: {
|
xAxis: {
|
||||||
boundaryGap: true,
|
boundaryGap: true,
|
||||||
type: 'category',
|
type: 'category',
|
||||||
data: ['河北', '山西', '河南', '内蒙', '辽宁'],
|
data: ['10:00', '10:05', '10:10', '10:15', '10:20'],
|
||||||
axisTick: {
|
axisTick: {
|
||||||
show: false
|
show: false
|
||||||
},
|
},
|
||||||
@@ -49,12 +49,11 @@
|
|||||||
},
|
},
|
||||||
series: [
|
series: [
|
||||||
{
|
{
|
||||||
data: [820, 932, 901, 934, 1290],
|
data: [45, 53, 23, 45, 12],
|
||||||
type: 'bar',
|
type: 'bar',
|
||||||
showBackground: true,
|
showBackground: true,
|
||||||
barWidth: fitChartSize(8),
|
barWidth: fitChartSize(16),
|
||||||
itemStyle: {
|
itemStyle: {
|
||||||
barBorderRadius: [3, 3, 0, 0],
|
|
||||||
color: {
|
color: {
|
||||||
type: 'linear',
|
type: 'linear',
|
||||||
x: 0,
|
x: 0,
|
||||||
@@ -62,11 +61,11 @@
|
|||||||
colorStops: [
|
colorStops: [
|
||||||
{
|
{
|
||||||
offset: 0,
|
offset: 0,
|
||||||
color: 'rgba(0, 208, 255, 0)'
|
color: 'rgba(0, 99, 255, 1)'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
offset: 1,
|
offset: 1,
|
||||||
color: 'rgba(0, 208, 255, 1)'
|
color: 'rgba(2, 249, 250, 1)'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -78,17 +77,9 @@
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
const init = () => {
|
const init = () => {
|
||||||
trafficChart = echarts.init(document.getElementById('traffic-flow'))
|
setOption(option)
|
||||||
trafficChart.setOption(option)
|
|
||||||
window.addEventListener('resize', resize)
|
|
||||||
}
|
|
||||||
const resize = () => {
|
|
||||||
if (trafficChart) {
|
|
||||||
trafficChart.dispose()
|
|
||||||
trafficChart = null
|
|
||||||
init()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
init()
|
init()
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -26,11 +26,18 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="list-item">
|
<div class="chart">
|
||||||
<div class="item-li" v-for="item in 4">
|
<div class="chart-item" v-for="item in 4" :key="item">
|
||||||
<div class="title-3"><span>拥堵频次占比</span></div>
|
<Title3 title="拥堵频次占比" />
|
||||||
<div class="chart-box">
|
<div class="chart__inner">
|
||||||
<v-chart class="chart" :option="option1" autoresize />
|
<spotRate :dataList="spotRateData" :total="8888" />
|
||||||
|
<ul class="chart__legend">
|
||||||
|
<li class="chart__legend-item" v-for="(item, index) in spotRateData" :key="index">
|
||||||
|
<p class="dot" :style="{ background: colors[index] }" />
|
||||||
|
<p class="name">{{ item.name }}</p>
|
||||||
|
<p class="value">{{ item.value }}%</p>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -38,204 +45,87 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
|
import spotRate from './spotRate.vue'
|
||||||
import countup from 'vue-countup-v3'
|
import countup from 'vue-countup-v3'
|
||||||
import * as echarts from 'echarts'
|
import { getSpotRateApi } from '@/api/workOrder.js'
|
||||||
import { fitChartSize } from '@/utils/dataUtil'
|
|
||||||
import Map from '@/components/Map/marker.vue'
|
|
||||||
import VChart, { THEME_KEY } from 'vue-echarts'
|
|
||||||
import { ref, provide } from 'vue'
|
|
||||||
|
|
||||||
provide(THEME_KEY, 'dark')
|
const colors = ['#FDC40A', '#FF5232', '#50F0A6', '#5FDFFA']
|
||||||
const option1 = ref({
|
let spotRateData = ref([])
|
||||||
backgroundColor: 'transparent',
|
const getSpotRate = async () => {
|
||||||
tooltip: {
|
let res = await getSpotRateApi()
|
||||||
trigger: 'item'
|
spotRateData.value = res.data.data
|
||||||
},
|
}
|
||||||
legend: {
|
onMounted(() => {
|
||||||
type: 'scroll',
|
getSpotRate()
|
||||||
orient: 'vertical',
|
|
||||||
right: fitChartSize(10),
|
|
||||||
top: fitChartSize(70),
|
|
||||||
bottom: fitChartSize(20),
|
|
||||||
itemWidth: 5,
|
|
||||||
itemHeight: 5,
|
|
||||||
padding: [20, 10, 20, 10],
|
|
||||||
// itemGap:15,
|
|
||||||
show: true,
|
|
||||||
lineStyle: {
|
|
||||||
borderColor: '#fff',
|
|
||||||
width: 5
|
|
||||||
},
|
|
||||||
textStyle: {
|
|
||||||
color: '#fff',
|
|
||||||
fontSize: fitChartSize(16),
|
|
||||||
lineHeight: 16,
|
|
||||||
rich: {
|
|
||||||
d: {
|
|
||||||
width: '100%',
|
|
||||||
borderWidth: 0.5,
|
|
||||||
height: 5,
|
|
||||||
backgroundColor: '1'
|
|
||||||
},
|
|
||||||
a: {
|
|
||||||
width: fitChartSize(75),
|
|
||||||
align: 'left',
|
|
||||||
fontSize: fitChartSize(16)
|
|
||||||
// backgroundColor:'1'
|
|
||||||
// color:'1',
|
|
||||||
// borderColor:'#eee',
|
|
||||||
// borderWidth:2
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
formatter: (e) => {
|
|
||||||
let ratio = 0
|
|
||||||
let value = 0
|
|
||||||
if (option1.value.series[0].data.length > 0) {
|
|
||||||
option1.value.series[0].data.forEach((item) => {
|
|
||||||
if (e == item.name) {
|
|
||||||
ratio = ((item.value * 100) / 3799).toFixed(0)
|
|
||||||
value = item.value
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
// return `${e} ${ratio}%
|
|
||||||
let arr = ['{a|' + e + '}', '{b|' + ratio + '%}']
|
|
||||||
return arr.join('')
|
|
||||||
},
|
|
||||||
itemStyle: {
|
|
||||||
// color:'#fff'
|
|
||||||
},
|
|
||||||
backgroundColor: 'rgba(0,77,136,0.6)'
|
|
||||||
},
|
|
||||||
series: [
|
|
||||||
{
|
|
||||||
name: 'Access From',
|
|
||||||
type: 'pie',
|
|
||||||
left: fitChartSize(-50),
|
|
||||||
top: fitChartSize(40),
|
|
||||||
width: fitChartSize(350),
|
|
||||||
height: fitChartSize(350),
|
|
||||||
// width:200,
|
|
||||||
// height:200,
|
|
||||||
radius: ['40%', '50%'],
|
|
||||||
avoidLabelOverlap: false,
|
|
||||||
padAngle: 5,
|
|
||||||
itemStyle: {
|
|
||||||
borderRadius: 2
|
|
||||||
},
|
|
||||||
label: {
|
|
||||||
show: false,
|
|
||||||
position: 'center',
|
|
||||||
fontWeight: 'bold'
|
|
||||||
// formatter: function (o) {
|
|
||||||
// let data = o.data.value
|
|
||||||
// return `{value|${data}}` + '\n' + `{name|整改率}`
|
|
||||||
// },
|
|
||||||
// rich: {
|
|
||||||
|
|
||||||
// value: {
|
|
||||||
// color: '#fff',
|
|
||||||
// fontSize: fitChartSize(24),
|
|
||||||
// fontWeight: 'bold',
|
|
||||||
// padding: [0, 0, 5, 0]
|
|
||||||
// },
|
|
||||||
// name: {
|
|
||||||
// color: '#7894A8',
|
|
||||||
// fontSize: fitChartSize(12)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
},
|
|
||||||
emphasis: {
|
|
||||||
label: {
|
|
||||||
show: true,
|
|
||||||
fontSize: fitChartSize(16),
|
|
||||||
fontWeight: 'bold',
|
|
||||||
color: '#fff',
|
|
||||||
fontWeight: 'bold',
|
|
||||||
formatter: function (o) {
|
|
||||||
let data = o.data.value
|
|
||||||
return `{value|${data}}` + '\n' + `{name|整改率}`
|
|
||||||
},
|
|
||||||
rich: {
|
|
||||||
value: {
|
|
||||||
color: '#fff',
|
|
||||||
fontSize: fitChartSize(24),
|
|
||||||
fontWeight: 'bold',
|
|
||||||
padding: [0, 0, 5, 0]
|
|
||||||
},
|
|
||||||
name: {
|
|
||||||
color: '#7894A8',
|
|
||||||
fontSize: fitChartSize(12)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
labelLine: {
|
|
||||||
show: true
|
|
||||||
},
|
|
||||||
data: [
|
|
||||||
{ value: 200, name: '异常状况1' },
|
|
||||||
{ value: 500, name: '异常状况2' },
|
|
||||||
{ value: 234, name: '异常状况3' },
|
|
||||||
{ value: 135, name: '异常状况4' },
|
|
||||||
{ value: 100, name: '异常状况5' },
|
|
||||||
{ value: 777, name: '异常状况6' },
|
|
||||||
{ value: 888, name: '其他' }
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.traffic-box-1 {
|
.chart {
|
||||||
width: vw(815);
|
display: flex;
|
||||||
height: vh(975);
|
flex-wrap: wrap;
|
||||||
background: linear-gradient(321deg, #0b2f64 0%, #062b57 100%);
|
gap: vw(8);
|
||||||
border-radius: 0px 0px 0px 0px;
|
padding: vw(8);
|
||||||
margin-top: vh(100);
|
|
||||||
position: relative;
|
&-item {
|
||||||
z-index: 9;
|
width: vw(444);
|
||||||
.list-item {
|
height: vh(420);
|
||||||
|
background-image: url('@/assets/images/bg-3.png');
|
||||||
|
background-size: 100% 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__inner {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
align-items: center;
|
||||||
flex-wrap: wrap;
|
}
|
||||||
padding: 0 vw(10);
|
|
||||||
.item-li {
|
|
||||||
width: vw(388);
|
|
||||||
height: vh(420);
|
|
||||||
background-image: url('@/assets/images/bg-3.png');
|
|
||||||
background-size: 100% 100%;
|
|
||||||
|
|
||||||
.title-3 {
|
&__legend {
|
||||||
margin-left: vw(10);
|
flex: 1;
|
||||||
position: relative;
|
|
||||||
width: vw(344);
|
|
||||||
height: vh(12);
|
|
||||||
margin-top: vh(20);
|
|
||||||
background-image: url('@/assets/images/title-6.png');
|
|
||||||
background-size: 100% 100%;
|
|
||||||
|
|
||||||
& > span {
|
&-item {
|
||||||
position: absolute;
|
position: relative;
|
||||||
bottom: vh(4);
|
width: 100%;
|
||||||
left: vw(20);
|
height: vh(40);
|
||||||
font-size: vw(15);
|
display: flex;
|
||||||
font-weight: bold;
|
align-items: center;
|
||||||
background-image: linear-gradient(to bottom, #ffffff 0%, #0096ff 100%);
|
margin-bottom: vh(8);
|
||||||
-webkit-background-clip: text;
|
background: linear-gradient(90deg, rgba(0, 150, 255, 0.34) 0%, rgba(0, 150, 255, 0) 100%);
|
||||||
background-clip: text;
|
|
||||||
-webkit-text-fill-color: transparent; /* 兼容WebKit内核浏览器 */
|
&::before {
|
||||||
color: transparent; /* 兼容其他浏览器 */
|
position: absolute;
|
||||||
}
|
content: '';
|
||||||
|
width: vw(4);
|
||||||
|
height: vh(40);
|
||||||
|
background-color: #0096ff;
|
||||||
}
|
}
|
||||||
.chart-box {
|
|
||||||
width: 100%;
|
.dot {
|
||||||
height: vh(370);
|
width: vw(4);
|
||||||
|
height: vw(4);
|
||||||
|
margin: 0 vw(16);
|
||||||
|
}
|
||||||
|
|
||||||
|
.name {
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: vw(12);
|
||||||
|
color: #ffffff;
|
||||||
|
width: vw(130);
|
||||||
|
}
|
||||||
|
|
||||||
|
.value {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: vw(15);
|
||||||
|
color: #ffffff;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.traffic-box-1 {
|
||||||
|
position: relative;
|
||||||
|
margin-top: vh(120);
|
||||||
|
background: linear-gradient(321deg, #0b2f64 0%, #062b57 100%);
|
||||||
|
|
||||||
.title-num {
|
.title-num {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: flex-start;
|
justify-content: flex-start;
|
||||||
|
|||||||
@@ -1,162 +1,159 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="n-box-traffic">
|
<div class="n-box-traffic">
|
||||||
<!-- nav -->
|
<!-- nav -->
|
||||||
<div class="left-nav">
|
<div class="left-nav">
|
||||||
<div class="top-box">
|
<div class="top-box">
|
||||||
|
<div class="ul">
|
||||||
<div class="ul">
|
<div class="li active">路段1</div>
|
||||||
<div class="li active">路段1</div>
|
<div class="li">路段1</div>
|
||||||
<div class="li">路段1</div>
|
<div class="li">路段1</div>
|
||||||
<div class="li">路段1</div>
|
<div class="li">路段1</div>
|
||||||
<div class="li">路段1</div>
|
<div class="li">路段1</div>
|
||||||
<div class="li">路段1</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div class="traffic-box-2">
|
||||||
<div class="traffic-box-2">
|
<div class="map-box">
|
||||||
<div class="map-box">
|
<Map></Map>
|
||||||
|
<!-- 视频 -->
|
||||||
<Map></Map>
|
<div class="video-list">
|
||||||
<!-- 视频 -->
|
<div class="li">
|
||||||
<div class="video-list">
|
<vue3VideoPlay v-bind="options" />
|
||||||
<div class="li">
|
</div>
|
||||||
<vue3VideoPlay v-bind="options"/>
|
<div class="li">
|
||||||
</div>
|
<vue3VideoPlay v-bind="options" />
|
||||||
<div class="li">
|
</div>
|
||||||
<vue3VideoPlay v-bind="options"/>
|
<div class="menu">查看更多</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="menu">查看更多</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import Map from '@/components/Map/marker.vue'
|
import Map from '@/components/Map/marker.vue'
|
||||||
const options = reactive({
|
const options = reactive({
|
||||||
src: "http://192.168.1.60:8080/live/340200000013200000011_34020000001320000001/hls.m3u8", //视频源
|
src: 'http://192.168.1.60:8080/live/340200000013200000011_34020000001320000001/hls.m3u8', //视频源
|
||||||
type: 'm3u8', //视频类型
|
type: 'm3u8', //视频类型
|
||||||
width:"100%",
|
width: '100%',
|
||||||
height:"100%",
|
height: '100%',
|
||||||
color: "#409eff", //主题色
|
color: '#409eff', //主题色
|
||||||
title: "", //视频名称
|
title: '', //视频名称
|
||||||
muted: false, //静音
|
muted: false, //静音
|
||||||
webFullScreen: false,
|
webFullScreen: false,
|
||||||
speedRate: ["0.75", "1.0", "1.25", "1.5", "2.0"], //播放倍速
|
speedRate: ['0.75', '1.0', '1.25', '1.5', '2.0'], //播放倍速
|
||||||
autoPlay: true, //自动播放
|
autoPlay: true, //自动播放
|
||||||
loop: false, //循环播放
|
loop: false, //循环播放
|
||||||
mirror: false, //镜像画面
|
mirror: false, //镜像画面
|
||||||
ligthOff: false, //关灯模式
|
ligthOff: false, //关灯模式
|
||||||
volume: 0.3, //默认音量大小
|
volume: 0.3, //默认音量大小
|
||||||
control: true, //是否显示控制
|
control: true, //是否显示控制
|
||||||
controlBtns: [
|
controlBtns: [
|
||||||
// "audioTrack",
|
// "audioTrack",
|
||||||
// "quality",
|
// "quality",
|
||||||
// "speedRate",
|
// "speedRate",
|
||||||
// "volume",
|
// "volume",
|
||||||
"setting",
|
'setting',
|
||||||
"pip",
|
'pip',
|
||||||
"pageFullScreen",
|
'pageFullScreen',
|
||||||
"fullScreen",
|
'fullScreen'
|
||||||
], //显示所有按钮,
|
] //显示所有按钮,
|
||||||
});
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.n-box-traffic{
|
.n-box-traffic {
|
||||||
display: flex;
|
display: flex;
|
||||||
margin-top:vh(100);
|
margin-top: vh(120);
|
||||||
}
|
}
|
||||||
.left-nav{
|
.left-nav {
|
||||||
margin-left:vw(10);
|
margin-left: vw(10);
|
||||||
// margin-top:vh(35);
|
// margin-top:vh(35);
|
||||||
// width:vw(250);
|
// width:vw(250);
|
||||||
.top-box{
|
.top-box {
|
||||||
text-align: left;
|
text-align: left;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
font-size: vw(18);
|
font-size: vw(18);
|
||||||
color: rgba(255,255,255,0.7);
|
color: rgba(255, 255, 255, 0.7);
|
||||||
line-height: 21px;
|
line-height: 21px;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
text-transform: none;
|
text-transform: none;
|
||||||
.title{
|
.title {
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
font-size: vw(15);
|
font-size: vw(15);
|
||||||
text-align: left;
|
text-align: left;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
text-transform: none;
|
text-transform: none;
|
||||||
height:vh(35);
|
height: vh(35);
|
||||||
line-height: vh(34);
|
line-height: vh(34);
|
||||||
padding-left:vw(20);
|
padding-left: vw(20);
|
||||||
// background: linear-gradient(90deg, #FFFFFF 0%, #75C1FF 100%);
|
// background: linear-gradient(90deg, #FFFFFF 0%, #75C1FF 100%);
|
||||||
}
|
}
|
||||||
.ul{
|
.ul {
|
||||||
.li{
|
.li {
|
||||||
background: url('/src/assets/images/m-nav-bg-1.png');
|
background: url('/src/assets/images/m-nav-bg-1.png');
|
||||||
background-size: 100% 100%;
|
background-size: 100% 100%;
|
||||||
width:vw(120);
|
width: vw(120);
|
||||||
height:vh(58);
|
height: vh(58);
|
||||||
line-height:vh(58);
|
line-height: vh(58);
|
||||||
text-align: center;
|
text-align: center;
|
||||||
margin-bottom:vh(15);
|
margin-bottom: vh(15);
|
||||||
}
|
}
|
||||||
.active{
|
.active {
|
||||||
background: url('/src/assets/images/m-nav-bg-2.png');
|
background: url('/src/assets/images/m-nav-bg-2.png');
|
||||||
background-size: 100% 100%;
|
background-size: 100% 100%;
|
||||||
// width:vw(178);
|
// width:vw(178);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.traffic-box-2{
|
.traffic-box-2 {
|
||||||
width:vw(1390);
|
position: relative;
|
||||||
height:vh(975);
|
z-index: 9;
|
||||||
background-image: url('/src/assets/images/map-bg-2.png');
|
width: vw(1290);
|
||||||
background-size: 100% 100%;
|
height: vh(955);
|
||||||
margin:0 vw(10);
|
margin: 0 vw(8);
|
||||||
padding:vh(35) vw(30);
|
padding: vw(20);
|
||||||
margin-right:0;
|
box-sizing: border-box;
|
||||||
position:relative;
|
background-image: url('/src/assets/images/map-bg-2.png');
|
||||||
z-index:9;
|
background-size: 100% 100%;
|
||||||
.map-box{
|
.map-box {
|
||||||
width:100%;
|
width: 100%;
|
||||||
height:100%;
|
height: 100%;
|
||||||
position:relative;
|
position: relative;
|
||||||
.video-list{
|
.video-list {
|
||||||
width:vw(320);
|
width: vw(320);
|
||||||
height:vh(120);
|
height: vh(120);
|
||||||
background: #0A254B;
|
background: #0a254b;
|
||||||
border-radius: 0px 0px 0px 0px;
|
border-radius: 0px 0px 0px 0px;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
bottom:vw(10);
|
bottom: vw(10);
|
||||||
right:vw(10);
|
right: vw(10);
|
||||||
z-index: 99;
|
z-index: 99;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
.li{
|
.li {
|
||||||
width:vw(140);
|
width: vw(140);
|
||||||
height:vh(105);
|
height: vh(105);
|
||||||
background-image: url('/src/assets/images/small-v-bg.png');
|
background-image: url('/src/assets/images/small-v-bg.png');
|
||||||
background-size: 100% 100%;
|
background-size: 100% 100%;
|
||||||
margin-right:vw(6);
|
margin-right: vw(6);
|
||||||
}
|
}
|
||||||
.menu{
|
.menu {
|
||||||
width: vw(12);
|
width: vw(12);
|
||||||
height: vh(60);
|
height: vh(60);
|
||||||
font-family: Inter, Inter;
|
font-family: Inter, Inter;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
font-size: vw(12);
|
font-size: vw(12);
|
||||||
color: #FFFFFF;
|
color: #ffffff;
|
||||||
line-height: vh(14);
|
line-height: vh(14);
|
||||||
text-align: left;
|
text-align: left;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
text-transform: none;
|
text-transform: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,474 +1,462 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="traffic-box-3">
|
<div class="traffic-box-3">
|
||||||
<!-- 1 -->
|
<!-- 1 -->
|
||||||
<div class="content-1">
|
<div class="content-1">
|
||||||
<div class="tp-title">
|
<div class="tp-title">
|
||||||
<div class="box-1">
|
<div class="box-1">
|
||||||
<img class="icon-xl" src="@/assets/images/work-icon-xl-1.png" alt="">
|
<img class="icon-xl" src="@/assets/images/work-icon-xl-1.png" alt="" />
|
||||||
<div class="xl-title">施家梁子大桥</div>
|
<div class="xl-title">施家梁子大桥</div>
|
||||||
<div class="tp-item">3号摄像机</div>
|
<div class="tp-item">3号摄像机</div>
|
||||||
<div class="tp-item item-bg-2">3号点位</div>
|
<div class="tp-item item-bg-2">3号点位</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="rt-text">严重拥堵</div>
|
<div class="rt-text">严重拥堵</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="title-num">
|
<div class="title-num">
|
||||||
<div class="item-box">
|
<div class="item-box">
|
||||||
<div class="item-t flex">
|
<div class="item-t flex"> <img src="@/assets/images/t-icon-1.png" alt="" />路段长度 </div>
|
||||||
<img src="@/assets/images/t-icon-1.png" alt="">路段长度
|
<div class="item-num"
|
||||||
</div>
|
><span>
|
||||||
<div class="item-num"><span>
|
<countup endVal="88895" />
|
||||||
<countup endVal="88895" />
|
</span>
|
||||||
</span> </div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="item-box">
|
<div class="item-box">
|
||||||
<div class="item-t flex">
|
<div class="item-t flex"> <img src="@/assets/images/t-icon-1.png" alt="" />平均车速 </div>
|
||||||
<img src="@/assets/images/t-icon-1.png" alt="">平均车速
|
<div class="item-num"
|
||||||
</div>
|
><span> <countup endVal="88895" /> </span
|
||||||
<div class="item-num"><span>
|
></div>
|
||||||
<countup endVal="88895" />
|
</div>
|
||||||
</span></div>
|
<div class="item-box">
|
||||||
</div>
|
<div class="item-t flex"> <img src="@/assets/images/t-icon-1.png" alt="" />拥堵距离 </div>
|
||||||
<div class="item-box">
|
<div class="item-num"
|
||||||
<div class="item-t flex">
|
><span> <countup endVal="88895" /> </span
|
||||||
<img src="@/assets/images/t-icon-1.png" alt="">拥堵距离
|
></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="item-num"><span>
|
<div class="item-box">
|
||||||
<countup endVal="88895" />
|
<div class="item-t flex"> <img src="@/assets/images/t-icon-1.png" alt="" />拥堵次数 </div>
|
||||||
</span></div>
|
<div class="item-num"
|
||||||
</div>
|
><span> <countup endVal="88895" /> </span
|
||||||
<div class="item-box">
|
></div>
|
||||||
<div class="item-t flex">
|
</div>
|
||||||
<img src="@/assets/images/t-icon-1.png" alt="">拥堵次数
|
<div class="item-box">
|
||||||
</div>
|
<div class="item-t flex">
|
||||||
<div class="item-num"><span>
|
<img src="@/assets/images/t-icon-1.png" alt="" />拥堵开始时间
|
||||||
<countup endVal="88895" />
|
</div>
|
||||||
</span></div>
|
<div class="item-num"><span>12:00:00</span></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="item-box">
|
<div class="item-box">
|
||||||
<div class="item-t flex">
|
<div class="item-t flex">
|
||||||
<img src="@/assets/images/t-icon-1.png" alt="">拥堵开始时间
|
<img src="@/assets/images/t-icon-1.png" alt="" />拥堵持续时长
|
||||||
</div>
|
</div>
|
||||||
<div class="item-num"><span>12:00:00</span></div>
|
<div class="item-num"><span>1h30S</span></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="item-box">
|
</div>
|
||||||
<div class="item-t flex">
|
<!-- chart -->
|
||||||
<img src="@/assets/images/t-icon-1.png" alt="">拥堵持续时长
|
<div class="chart-item">
|
||||||
</div>
|
<div class="title-3"><span>拥堵频次占比</span></div>
|
||||||
<div class="item-num"><span>1h30S</span></div>
|
<div class="chart-box">
|
||||||
</div>
|
<v-chart class="chart" :option="option1" autoresize />
|
||||||
</div>
|
</div>
|
||||||
<!-- chart -->
|
</div>
|
||||||
<div class="chart-item">
|
</div>
|
||||||
<div class="title-3"><span>拥堵频次占比</span></div>
|
<!-- 2 -->
|
||||||
<div class="chart-box">
|
<div class="content-1 content-2">
|
||||||
<v-chart class="chart" :option="option1" autoresize />
|
<div class="tp-title">
|
||||||
</div>
|
<div class="box-1">
|
||||||
</div>
|
<img class="icon-xl" src="@/assets/images/work-icon-xl-1.png" alt="" />
|
||||||
</div>
|
<div class="xl-title">施家梁子大桥</div>
|
||||||
<!-- 2 -->
|
<div class="tp-item">3号摄像机</div>
|
||||||
<div class="content-1 content-2">
|
<div class="tp-item item-bg-2">3号点位</div>
|
||||||
<div class="tp-title">
|
</div>
|
||||||
<div class="box-1">
|
<div class="rt-text rt-text-2">常规拥堵</div>
|
||||||
<img class="icon-xl" src="@/assets/images/work-icon-xl-1.png" alt="">
|
</div>
|
||||||
<div class="xl-title">施家梁子大桥</div>
|
<div class="title-num">
|
||||||
<div class="tp-item">3号摄像机</div>
|
<div class="item-box">
|
||||||
<div class="tp-item item-bg-2">3号点位</div>
|
<div class="item-t flex"> <img src="@/assets/images/t-icon-1.png" alt="" />路段长度 </div>
|
||||||
</div>
|
<div class="item-num"
|
||||||
<div class="rt-text rt-text-2">常规拥堵</div>
|
><span>
|
||||||
</div>
|
<countup endVal="88895" />
|
||||||
<div class="title-num">
|
</span>
|
||||||
<div class="item-box">
|
</div>
|
||||||
<div class="item-t flex">
|
</div>
|
||||||
<img src="@/assets/images/t-icon-1.png" alt="">路段长度
|
<div class="item-box">
|
||||||
</div>
|
<div class="item-t flex"> <img src="@/assets/images/t-icon-1.png" alt="" />平均车速 </div>
|
||||||
<div class="item-num"><span>
|
<div class="item-num"
|
||||||
<countup endVal="88895" />
|
><span> <countup endVal="88895" /> </span
|
||||||
</span> </div>
|
></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="item-box">
|
<div class="item-box">
|
||||||
<div class="item-t flex">
|
<div class="item-t flex"> <img src="@/assets/images/t-icon-1.png" alt="" />拥堵距离 </div>
|
||||||
<img src="@/assets/images/t-icon-1.png" alt="">平均车速
|
<div class="item-num"
|
||||||
</div>
|
><span> <countup endVal="88895" /> </span
|
||||||
<div class="item-num"><span>
|
></div>
|
||||||
<countup endVal="88895" />
|
</div>
|
||||||
</span></div>
|
<div class="item-box">
|
||||||
</div>
|
<div class="item-t flex"> <img src="@/assets/images/t-icon-1.png" alt="" />拥堵次数 </div>
|
||||||
<div class="item-box">
|
<div class="item-num"
|
||||||
<div class="item-t flex">
|
><span> <countup endVal="88895" /> </span
|
||||||
<img src="@/assets/images/t-icon-1.png" alt="">拥堵距离
|
></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="item-num"><span>
|
<div class="item-box">
|
||||||
<countup endVal="88895" />
|
<div class="item-t flex">
|
||||||
</span></div>
|
<img src="@/assets/images/t-icon-1.png" alt="" />拥堵开始时间
|
||||||
</div>
|
</div>
|
||||||
<div class="item-box">
|
<div class="item-num"><span>12:00:00</span></div>
|
||||||
<div class="item-t flex">
|
</div>
|
||||||
<img src="@/assets/images/t-icon-1.png" alt="">拥堵次数
|
<div class="item-box">
|
||||||
</div>
|
<div class="item-t flex">
|
||||||
<div class="item-num"><span>
|
<img src="@/assets/images/t-icon-1.png" alt="" />拥堵持续时长
|
||||||
<countup endVal="88895" />
|
</div>
|
||||||
</span></div>
|
<div class="item-num"><span>1h30S</span></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="item-box">
|
</div>
|
||||||
<div class="item-t flex">
|
<!-- chart -->
|
||||||
<img src="@/assets/images/t-icon-1.png" alt="">拥堵开始时间
|
<div class="chart-item">
|
||||||
</div>
|
<div class="title-3"><span>拥堵频次占比</span></div>
|
||||||
<div class="item-num"><span>12:00:00</span></div>
|
<div class="chart-box">
|
||||||
</div>
|
<v-chart class="chart" :option="option1" autoresize />
|
||||||
<div class="item-box">
|
</div>
|
||||||
<div class="item-t flex">
|
</div>
|
||||||
<img src="@/assets/images/t-icon-1.png" alt="">拥堵持续时长
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="item-num"><span>1h30S</span></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<!-- chart -->
|
|
||||||
<div class="chart-item">
|
|
||||||
<div class="title-3"><span>拥堵频次占比</span></div>
|
|
||||||
<div class="chart-box">
|
|
||||||
<v-chart class="chart" :option="option1" autoresize />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import countup from 'vue-countup-v3'
|
import countup from 'vue-countup-v3'
|
||||||
import * as echarts from 'echarts'
|
import { fitChartSize } from '@/utils/dataUtil'
|
||||||
import {
|
import VChart, { THEME_KEY } from 'vue-echarts'
|
||||||
fitChartSize
|
|
||||||
} from '@/utils/dataUtil'
|
|
||||||
import Map from '@/components/Map/marker.vue'
|
|
||||||
import VChart, {
|
|
||||||
THEME_KEY
|
|
||||||
} from 'vue-echarts';
|
|
||||||
import {
|
|
||||||
ref,
|
|
||||||
provide
|
|
||||||
} from 'vue';
|
|
||||||
|
|
||||||
provide(THEME_KEY, 'dark');
|
provide(THEME_KEY, 'dark')
|
||||||
const option1 = ref({
|
|
||||||
backgroundColor: 'transparent',
|
const option1 = ref({
|
||||||
width: '92%',
|
backgroundColor: 'transparent',
|
||||||
// height: fitChartSize(300),
|
width: '92%',
|
||||||
grid: {
|
grid: {
|
||||||
top: fitChartSize(90),
|
top: fitChartSize(90),
|
||||||
bottom: '0',
|
bottom: '0',
|
||||||
left: '4%',
|
left: '4%',
|
||||||
containLabel: true,
|
containLabel: true
|
||||||
},
|
},
|
||||||
color: [{
|
color: [
|
||||||
type: 'linear',
|
{
|
||||||
x: 0,
|
type: 'linear',
|
||||||
y: 0,
|
x: 0,
|
||||||
x2: 0,
|
y: 0,
|
||||||
y2: 1,
|
x2: 0,
|
||||||
colorStops: [{
|
y2: 1,
|
||||||
offset: 0,
|
colorStops: [
|
||||||
color: '#0096FF' // 0% 处的颜色
|
{
|
||||||
},
|
offset: 0,
|
||||||
{
|
color: '#0096FF' // 0% 处的颜色
|
||||||
offset: 1,
|
},
|
||||||
color: '#004D88' // 100% 处的颜色
|
{
|
||||||
}
|
offset: 1,
|
||||||
],
|
color: '#004D88' // 100% 处的颜色
|
||||||
global: false // 缺省为 false
|
}
|
||||||
},
|
],
|
||||||
{
|
global: false // 缺省为 false
|
||||||
type: 'linear',
|
},
|
||||||
x: 0,
|
{
|
||||||
y: 0,
|
type: 'linear',
|
||||||
x2: 0,
|
x: 0,
|
||||||
y2: 1,
|
y: 0,
|
||||||
colorStops: [{
|
x2: 0,
|
||||||
offset: 0,
|
y2: 1,
|
||||||
color: '#FFCB39' // 0% 处的颜色
|
colorStops: [
|
||||||
}, {
|
{
|
||||||
offset: 1,
|
offset: 0,
|
||||||
color: '#0A4190' // 100% 处的颜色
|
color: '#FFCB39' // 0% 处的颜色
|
||||||
}],
|
},
|
||||||
global: false // 缺省为 false
|
{
|
||||||
},
|
offset: 1,
|
||||||
{
|
color: '#0A4190' // 100% 处的颜色
|
||||||
type: 'linear',
|
}
|
||||||
x: 0,
|
],
|
||||||
y: 0,
|
global: false // 缺省为 false
|
||||||
x2: 0,
|
},
|
||||||
y2: 1,
|
{
|
||||||
colorStops: [{
|
type: 'linear',
|
||||||
offset: 0,
|
x: 0,
|
||||||
color: '#9846FE' // 0% 处的颜色
|
y: 0,
|
||||||
}, {
|
x2: 0,
|
||||||
offset: 1,
|
y2: 1,
|
||||||
color: '#0A4190' // 100% 处的颜色
|
colorStops: [
|
||||||
}],
|
{
|
||||||
global: false // 缺省为 false
|
offset: 0,
|
||||||
},
|
color: '#9846FE' // 0% 处的颜色
|
||||||
{
|
},
|
||||||
type: 'linear',
|
{
|
||||||
x: 0,
|
offset: 1,
|
||||||
y: 0,
|
color: '#0A4190' // 100% 处的颜色
|
||||||
x2: 0,
|
}
|
||||||
y2: 1,
|
],
|
||||||
colorStops: [{
|
global: false // 缺省为 false
|
||||||
offset: 0,
|
},
|
||||||
color: '#FF5619' // 0% 处的颜色
|
{
|
||||||
}, {
|
type: 'linear',
|
||||||
offset: 1,
|
x: 0,
|
||||||
color: '#0A4190' // 100% 处的颜色
|
y: 0,
|
||||||
}],
|
x2: 0,
|
||||||
global: false // 缺省为 false
|
y2: 1,
|
||||||
},
|
colorStops: [
|
||||||
],
|
{
|
||||||
legend: {
|
offset: 0,
|
||||||
type: 'plain',
|
color: '#FF5619' // 0% 处的颜色
|
||||||
orient: 'horizontal',
|
},
|
||||||
right: fitChartSize(10),
|
{
|
||||||
top: fitChartSize(10),
|
offset: 1,
|
||||||
bottom: fitChartSize(20),
|
color: '#0A4190' // 100% 处的颜色
|
||||||
itemWidth: 6,
|
}
|
||||||
itemHeight: 6,
|
],
|
||||||
},
|
global: false // 缺省为 false
|
||||||
tooltip: {},
|
}
|
||||||
dataset: {
|
],
|
||||||
source: [
|
legend: {
|
||||||
['product', '路段类型1', '路段类型2', '路段类型3', '路段类型4'],
|
type: 'plain',
|
||||||
['10:00', 399.3, 185.8, 293.7, 123],
|
orient: 'horizontal',
|
||||||
['10:30', 83.1, 273.4, 455.1, 123],
|
right: fitChartSize(10),
|
||||||
['11:00', 86.4, 465.2, 382.5, 123],
|
top: fitChartSize(10),
|
||||||
['11:30', 72.4, 153.9, 439.1, 123],
|
bottom: fitChartSize(20),
|
||||||
['12:00', 72.4, 453.9, 239.1, 123],
|
itemWidth: 6,
|
||||||
['12:30', 72.4, 453.9, 239.1, 123],
|
itemHeight: 6
|
||||||
['13:00', 86.4, 465.2, 282.5, 123],
|
},
|
||||||
['13:30', 72.4, 453.9, 239.1, 123],
|
tooltip: {},
|
||||||
['14:00', 72.4, 453.9, 239.1, 123],
|
dataset: {
|
||||||
['14:30', 72.4, 453.9, 239.1],
|
source: [
|
||||||
]
|
['product', '路段类型1', '路段类型2', '路段类型3', '路段类型4'],
|
||||||
},
|
['10:00', 399.3, 185.8, 293.7, 123],
|
||||||
xAxis: {
|
['10:30', 83.1, 273.4, 455.1, 123],
|
||||||
type: 'category',
|
['11:00', 86.4, 465.2, 382.5, 123],
|
||||||
axisTisk: {
|
['11:30', 72.4, 153.9, 439.1, 123],
|
||||||
show: true,
|
['12:00', 72.4, 453.9, 239.1, 123],
|
||||||
// 设置刻度长度
|
['12:30', 72.4, 453.9, 239.1, 123],
|
||||||
length: 1,
|
['13:00', 86.4, 465.2, 282.5, 123],
|
||||||
lineStyle: {
|
['13:30', 72.4, 453.9, 239.1, 123],
|
||||||
type: 'dashed', // 设置为虚线
|
['14:00', 72.4, 453.9, 239.1, 123],
|
||||||
width: 0,
|
['14:30', 72.4, 453.9, 239.1]
|
||||||
}
|
]
|
||||||
},
|
},
|
||||||
},
|
xAxis: {
|
||||||
yAxis: {
|
type: 'category',
|
||||||
type: 'value',
|
axisTisk: {
|
||||||
min: 0,
|
show: true,
|
||||||
max: 500,
|
// 设置刻度长度
|
||||||
interval: 100,
|
length: 1,
|
||||||
axisLabel: {
|
lineStyle: {
|
||||||
fontSize: fitChartSize(12), // 设置Y轴刻度字体大小
|
type: 'dashed', // 设置为虚线
|
||||||
color: '#eee',
|
width: 0
|
||||||
},
|
}
|
||||||
splitLine: {
|
}
|
||||||
show: true,
|
},
|
||||||
lineStyle: {
|
yAxis: {
|
||||||
type: 'dashed',
|
type: 'value',
|
||||||
color: '#00D0FF'
|
min: 0,
|
||||||
}
|
max: 500,
|
||||||
}
|
interval: 100,
|
||||||
},
|
axisLabel: {
|
||||||
// Declare several bar series, each will be mapped
|
fontSize: fitChartSize(12), // 设置Y轴刻度字体大小
|
||||||
// to a column of dataset.source by default.
|
color: '#eee'
|
||||||
series: [{
|
},
|
||||||
type: 'bar'
|
splitLine: {
|
||||||
}, {
|
show: true,
|
||||||
type: 'bar'
|
lineStyle: {
|
||||||
}, {
|
type: 'dashed',
|
||||||
type: 'bar'
|
color: '#00D0FF'
|
||||||
},
|
}
|
||||||
{
|
}
|
||||||
type: 'bar'
|
},
|
||||||
}
|
// Declare several bar series, each will be mapped
|
||||||
]
|
// to a column of dataset.source by default.
|
||||||
})
|
series: [
|
||||||
|
{
|
||||||
|
type: 'bar'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'bar'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'bar'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'bar'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.traffic-box-3 {
|
.traffic-box-3 {
|
||||||
width: vw(818);
|
margin-top: vh(120);
|
||||||
height: vh(480);
|
width: vw(818);
|
||||||
background: linear-gradient(330deg, #0B2F64 0%, #062B57 100%);
|
height: vh(480);
|
||||||
border-radius: 0px 0px 0px 0px;
|
padding: vw(8);
|
||||||
padding: vw(10);
|
position: relative;
|
||||||
position: relative;
|
z-index: 9;
|
||||||
z-index: 9;
|
background: linear-gradient(330deg, #0b2f64 0%, #062b57 100%);
|
||||||
margin: 0 vw(10);
|
|
||||||
margin-top: vh(100);
|
|
||||||
.content-2{
|
|
||||||
margin-top:vh(20);
|
|
||||||
}
|
|
||||||
.content-1 {
|
|
||||||
.chart-item {
|
|
||||||
margin-top: vh(10);
|
|
||||||
height: vh(293);
|
|
||||||
background: radial-gradient(70% at 99% 50%, #0A4190 0%, rgba(0, 77, 136, 0.6) 100%);
|
|
||||||
border-radius: 0px 0px 0px 0px;
|
|
||||||
border: 1px solid;
|
|
||||||
border-image: linear-gradient(180deg, rgba(0, 150, 255, 1), rgba(0, 90, 153, 0)) 1 1;
|
|
||||||
|
|
||||||
.chart-box {
|
.content-2 {
|
||||||
width: 100%;
|
margin-top: vh(20);
|
||||||
height: vh(250);
|
}
|
||||||
}
|
.content-1 {
|
||||||
|
.chart-item {
|
||||||
|
margin-top: vh(10);
|
||||||
|
height: vh(293);
|
||||||
|
background: radial-gradient(70% at 99% 50%, #0a4190 0%, rgba(0, 77, 136, 0.6) 100%);
|
||||||
|
border-radius: 0px 0px 0px 0px;
|
||||||
|
border: 1px solid;
|
||||||
|
border-image: linear-gradient(180deg, rgba(0, 150, 255, 1), rgba(0, 90, 153, 0)) 1 1;
|
||||||
|
|
||||||
.title-3 {
|
.chart-box {
|
||||||
margin-left: vw(10);
|
width: 100%;
|
||||||
position: relative;
|
height: vh(250);
|
||||||
width: vw(344);
|
}
|
||||||
height: vh(12);
|
|
||||||
margin-top: vh(20);
|
|
||||||
background-image: url('@/assets/images/title-6.png');
|
|
||||||
background-size: 100% 100%;
|
|
||||||
|
|
||||||
&>span {
|
.title-3 {
|
||||||
position: absolute;
|
margin-left: vw(10);
|
||||||
bottom: vh(4);
|
position: relative;
|
||||||
left: vw(20);
|
width: vw(344);
|
||||||
font-size: vw(15);
|
height: vh(12);
|
||||||
font-weight: bold;
|
margin-top: vh(20);
|
||||||
background-image: linear-gradient(to bottom, #ffffff 0%, #0096ff 100%);
|
background-image: url('@/assets/images/title-6.png');
|
||||||
-webkit-background-clip: text;
|
background-size: 100% 100%;
|
||||||
background-clip: text;
|
|
||||||
-webkit-text-fill-color: transparent;
|
|
||||||
/* 兼容WebKit内核浏览器 */
|
|
||||||
color: transparent;
|
|
||||||
/* 兼容其他浏览器 */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.title-num {
|
& > span {
|
||||||
display: flex;
|
position: absolute;
|
||||||
justify-content: flex-start;
|
bottom: vh(4);
|
||||||
padding: vw(20);
|
left: vw(20);
|
||||||
background: radial-gradient(70% at 99% 50%, #0A4190 0%, rgba(0, 77, 136, 0.6) 100%);
|
font-size: vw(15);
|
||||||
border-radius: 0px 0px 0px 0px;
|
font-weight: bold;
|
||||||
border: 1px solid;
|
background-image: linear-gradient(to bottom, #ffffff 0%, #0096ff 100%);
|
||||||
border-image: linear-gradient(180deg, rgba(0, 150, 255, 1), rgba(0, 90, 153, 0)) 1 1;
|
-webkit-background-clip: text;
|
||||||
|
background-clip: text;
|
||||||
|
-webkit-text-fill-color: transparent;
|
||||||
|
/* 兼容WebKit内核浏览器 */
|
||||||
|
color: transparent;
|
||||||
|
/* 兼容其他浏览器 */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.item-box {
|
.title-num {
|
||||||
flex: 1;
|
display: flex;
|
||||||
|
justify-content: flex-start;
|
||||||
|
padding: vw(20);
|
||||||
|
background: radial-gradient(70% at 99% 50%, #0a4190 0%, rgba(0, 77, 136, 0.6) 100%);
|
||||||
|
border-radius: 0px 0px 0px 0px;
|
||||||
|
border: 1px solid;
|
||||||
|
border-image: linear-gradient(180deg, rgba(0, 150, 255, 1), rgba(0, 90, 153, 0)) 1 1;
|
||||||
|
|
||||||
.item-t {
|
.item-box {
|
||||||
display: flex;
|
flex: 1;
|
||||||
font-weight: 400;
|
|
||||||
font-size: vw(14);
|
|
||||||
color: rgba(255, 255, 255, 0.8);
|
|
||||||
text-align: left;
|
|
||||||
font-style: normal;
|
|
||||||
text-transform: none;
|
|
||||||
margin-bottom: vh(20);
|
|
||||||
|
|
||||||
img {
|
.item-t {
|
||||||
margin-right: vw(5);
|
display: flex;
|
||||||
width: vw(8);
|
font-weight: 400;
|
||||||
height: vh(8);
|
font-size: vw(14);
|
||||||
}
|
color: rgba(255, 255, 255, 0.8);
|
||||||
|
text-align: left;
|
||||||
|
font-style: normal;
|
||||||
|
text-transform: none;
|
||||||
|
margin-bottom: vh(20);
|
||||||
|
|
||||||
}
|
img {
|
||||||
|
margin-right: vw(5);
|
||||||
|
width: vw(8);
|
||||||
|
height: vh(8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.item-num {
|
.item-num {
|
||||||
width: vw(134);
|
width: vw(134);
|
||||||
height: vh(30);
|
height: vh(30);
|
||||||
background-image: url('@/assets/images/t-box-title-bg-1.png');
|
background-image: url('@/assets/images/t-box-title-bg-1.png');
|
||||||
background-size: 100% 100%;
|
background-size: 100% 100%;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
font-size: vw(24);
|
font-size: vw(24);
|
||||||
color: #02F9FA;
|
color: #02f9fa;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
text-transform: none;
|
text-transform: none;
|
||||||
padding-left: vw(15);
|
padding-left: vw(15);
|
||||||
position: relative;
|
position: relative;
|
||||||
left: vw(-8);
|
left: vw(-8);
|
||||||
|
|
||||||
span {
|
span {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 50%;
|
top: 50%;
|
||||||
transform: translateY(-50%);
|
transform: translateY(-50%);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.tp-title {
|
.tp-title {
|
||||||
display: flex;
|
height: vh(72);
|
||||||
align-items: center;
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
.box-1 {
|
.box-1 {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
||||||
.icon-xl {
|
.icon-xl {
|
||||||
width: vw(30);
|
width: vw(30);
|
||||||
height: vh(22);
|
height: vh(22);
|
||||||
margin-right: vw(15);
|
margin-right: vw(15);
|
||||||
}
|
}
|
||||||
|
|
||||||
.xl-title {
|
.xl-title {
|
||||||
font-size: vw(28);
|
font-size: vw(28);
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
color: transparent;
|
color: transparent;
|
||||||
-webkit-background-clip: text;
|
-webkit-background-clip: text;
|
||||||
background-clip: text;
|
background-clip: text;
|
||||||
-webkit-text-fill-color: transparent;
|
-webkit-text-fill-color: transparent;
|
||||||
background-image: linear-gradient(to bottom, #ffffff 0%, #87c9ff 100%);
|
background-image: linear-gradient(to bottom, #ffffff 0%, #87c9ff 100%);
|
||||||
margin-right: vw(20);
|
margin-right: vw(20);
|
||||||
}
|
}
|
||||||
|
|
||||||
.tp-item {
|
.tp-item {
|
||||||
width: vw(120);
|
width: vw(120);
|
||||||
height: vh(72);
|
height: vw(72);
|
||||||
background-image: url('/src/assets/images/t-a-1.png');
|
background-image: url('/src/assets/images/t-a-1.png');
|
||||||
background-size: 100% 100%;
|
background-size: 100% 100%;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
font-size: vw(15);
|
font-size: vw(15);
|
||||||
color: #FFFFFF;
|
color: #ffffff;
|
||||||
padding-left: vw(42);
|
padding-left: vw(42);
|
||||||
text-align: left;
|
text-align: left;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
text-transform: none;
|
text-transform: none;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
margin: 0 vw(20)
|
margin: 0 vw(20);
|
||||||
}
|
}
|
||||||
|
|
||||||
.item-bg-2 {
|
.item-bg-2 {
|
||||||
background-image: url('/src/assets/images/t-a-2.png');
|
background-image: url('/src/assets/images/t-a-2.png');
|
||||||
background-size: 100% 100%;
|
background-size: 100% 100%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.rt-text {
|
.rt-text {
|
||||||
width: vw(116);
|
width: vw(116);
|
||||||
height: vh(40);
|
height: vw(40);
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
font-size: vw(14);
|
font-size: vw(14);
|
||||||
color: #FFFFFF;
|
color: #ffffff;
|
||||||
padding-left: vw(15);
|
text-align: left;
|
||||||
text-align: left;
|
line-height: vw(40);
|
||||||
font-style: normal;
|
padding-left: vw(40);
|
||||||
text-transform: none;
|
background-image: url('/src/assets/images/t-b-1.png');
|
||||||
background-image: url('/src/assets/images/t-b-1.png');
|
background-size: 100% 100%;
|
||||||
background-size: 100% 100%;
|
}
|
||||||
line-height: vh(40);
|
.rt-text-2 {
|
||||||
padding-left: vw(40);
|
background-image: url('/src/assets/images/t-b-2.png');
|
||||||
}
|
background-size: 100% 100%;
|
||||||
.rt-text-2{
|
}
|
||||||
background-image: url('/src/assets/images/t-b-2.png');
|
}
|
||||||
background-size: 100% 100%;
|
}
|
||||||
}
|
}
|
||||||
}
|
</style>
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|||||||
94
src/views/traffic/components/spotRate.vue
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
<template>
|
||||||
|
<div class="spotRate" :id="id" />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { fitChartSize } from '@/utils/dataUtil'
|
||||||
|
import { useEchart } from '@/hooks/echart'
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
config: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
dataList: {
|
||||||
|
type: Array,
|
||||||
|
default: () => []
|
||||||
|
},
|
||||||
|
total: {
|
||||||
|
type: Number,
|
||||||
|
default: () => 0
|
||||||
|
},
|
||||||
|
colors: {
|
||||||
|
type: Array,
|
||||||
|
default: () => ['#FDC40A', '#FF5232', '#50F0A6', '#5FDFFA']
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const { id, setOption } = useEchart()
|
||||||
|
|
||||||
|
var defaultCofig = {
|
||||||
|
color: [],
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
type: 'pie',
|
||||||
|
center: ['50%', '50%'],
|
||||||
|
radius: ['70%', '90%'],
|
||||||
|
itemStyle: {
|
||||||
|
borderWidth: fitChartSize(4),
|
||||||
|
borderColor: '#093672'
|
||||||
|
},
|
||||||
|
label: {
|
||||||
|
show: true,
|
||||||
|
position: 'center',
|
||||||
|
fontWeight: 'bold',
|
||||||
|
rich: {
|
||||||
|
value: {
|
||||||
|
color: '#fff',
|
||||||
|
fontSize: fitChartSize(24),
|
||||||
|
fontWeight: 'bold',
|
||||||
|
padding: [0, 0, 5, 0]
|
||||||
|
},
|
||||||
|
name: {
|
||||||
|
color: '#7894A8',
|
||||||
|
fontSize: fitChartSize(12)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
labelLine: {
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
data: []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.dataList,
|
||||||
|
(newVal) => {
|
||||||
|
if (newVal.length > 0) {
|
||||||
|
nextTick(() => {
|
||||||
|
defaultCofig.color = props.colors
|
||||||
|
defaultCofig.series[0].data = props.dataList
|
||||||
|
defaultCofig.series[0].label.formatter = () => {
|
||||||
|
return `{value|${props.total}}` + '\n' + `{name|工单总数}`
|
||||||
|
}
|
||||||
|
setOption({
|
||||||
|
...defaultCofig,
|
||||||
|
...props.config
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ immediate: true }
|
||||||
|
)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.spotRate {
|
||||||
|
width: vw(240);
|
||||||
|
height: vh(320);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -1,9 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="work-box-1">
|
<div class="work-box-1">
|
||||||
<!-- 最新工单 -->
|
<!-- 最新工单 -->
|
||||||
<div class="header">
|
<Title1 title="最新工单" />
|
||||||
<div class="title"> <span>最新工单</span> </div>
|
|
||||||
</div>
|
|
||||||
<!-- 列表 -->
|
<!-- 列表 -->
|
||||||
<div class="list">
|
<div class="list">
|
||||||
<div class="li" v-for="(item, index) in list" :key="index">
|
<div class="li" v-for="(item, index) in list" :key="index">
|
||||||
@@ -32,9 +30,9 @@
|
|||||||
width: vw(815);
|
width: vw(815);
|
||||||
height: vh(950);
|
height: vh(950);
|
||||||
margin-top: vh(120);
|
margin-top: vh(120);
|
||||||
|
box-sizing: border-box;
|
||||||
background: linear-gradient(321deg, #0b2f64 0%, #062b57 100%);
|
background: linear-gradient(321deg, #0b2f64 0%, #062b57 100%);
|
||||||
position: relative;
|
|
||||||
z-index: 99;
|
|
||||||
padding: 0 vw(20);
|
padding: 0 vw(20);
|
||||||
.list {
|
.list {
|
||||||
/* 滚动条整体样式 */
|
/* 滚动条整体样式 */
|
||||||
@@ -113,30 +111,5 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.header {
|
|
||||||
position: relative;
|
|
||||||
margin: vh(20);
|
|
||||||
.title {
|
|
||||||
margin: vh(5) auto;
|
|
||||||
width: vw(468);
|
|
||||||
height: vh(32);
|
|
||||||
font-weight: 800;
|
|
||||||
font-size: vw(16);
|
|
||||||
color: #fff;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
background-image: url('@/assets/images/title-4.png');
|
|
||||||
background-size: 100% 100%;
|
|
||||||
span {
|
|
||||||
font-weight: 800;
|
|
||||||
color: transparent;
|
|
||||||
-webkit-background-clip: text;
|
|
||||||
background-clip: text;
|
|
||||||
-webkit-text-fill-color: transparent;
|
|
||||||
background-image: linear-gradient(to bottom, #ffffff 0%, #87c9ff 100%);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="work-box-2">
|
<div class="work-box-2">
|
||||||
<div class="box-1">
|
<div class="box-1">
|
||||||
<Title1 title="今日工单" />
|
<div>
|
||||||
|
<Title1 title="今日工单" />
|
||||||
|
</div>
|
||||||
<div class="hd-list">
|
<div class="hd-list">
|
||||||
<img class="h-icon" src="@/assets/images/work-icon-1.png" />
|
<img class="h-icon" src="@/assets/images/work-icon-1.png" />
|
||||||
<div class="item item1">
|
<div class="item item1">
|
||||||
@@ -21,7 +23,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="chart">
|
<div class="chart">
|
||||||
<div class="chart__wrapper">
|
<div class="chart__wrapper mr-8">
|
||||||
<Title3 title="工单总数" />
|
<Title3 title="工单总数" />
|
||||||
<!-- <div class="check-label">
|
<!-- <div class="check-label">
|
||||||
<span class="active">全部</span>
|
<span class="active">全部</span>
|
||||||
@@ -55,7 +57,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="progress-item">
|
<div class="progress-item">
|
||||||
<span class="progress-item__label">紧急</span>
|
<span class="progress-item__label">重要</span>
|
||||||
<div class="progress-item__inner">
|
<div class="progress-item__inner">
|
||||||
<el-progress
|
<el-progress
|
||||||
:percentage="completeRateData.important * 100"
|
:percentage="completeRateData.important * 100"
|
||||||
@@ -86,11 +88,11 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="chart__wrapper">
|
<div class="chart__wrapper">
|
||||||
<Title3 title="景区工单占比" />
|
<Title3 title="景区工单类型占比" />
|
||||||
<div class="chart__inner">
|
<div class="chart__inner">
|
||||||
<spotRate :dataList="spotRateData" :total="8888" />
|
<spotRate :dataList="typeRateData" :total="8888" />
|
||||||
<ul class="chart__legend">
|
<ul class="chart__legend">
|
||||||
<li class="chart__legend-item" v-for="(item, index) in spotRateData" :key="index">
|
<li class="chart__legend-item" v-for="(item, index) in typeRateData" :key="index">
|
||||||
<p class="dot" :style="{ background: colors[index] }" />
|
<p class="dot" :style="{ background: colors[index] }" />
|
||||||
<p class="name">{{ item.name }}</p>
|
<p class="name">{{ item.name }}</p>
|
||||||
<p class="value">{{ item.value }}%</p>
|
<p class="value">{{ item.value }}%</p>
|
||||||
@@ -99,7 +101,7 @@
|
|||||||
<div class="alarm">
|
<div class="alarm">
|
||||||
<Title2 title="异常点位告警排名" />
|
<Title2 title="异常点位告警排名" />
|
||||||
<ul class="alarm__wrapper">
|
<ul class="alarm__wrapper">
|
||||||
<li class="alarm-item" v-for="(item, index) in 8" :key="index">
|
<li class="alarm-item" v-for="(item, index) in pointRankData" :key="index">
|
||||||
<p
|
<p
|
||||||
class="alarm-item__rank"
|
class="alarm-item__rank"
|
||||||
:class="{
|
:class="{
|
||||||
@@ -108,9 +110,9 @@
|
|||||||
'alarm-item__rank--primary': index == 2
|
'alarm-item__rank--primary': index == 2
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
{{ item }}
|
{{ index + 1 }}
|
||||||
</p>
|
</p>
|
||||||
<p class="alarm-item__content">异常点位告警1号名称</p>
|
<p class="alarm-item__content">{{ item.link_title }}</p>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
@@ -131,7 +133,8 @@
|
|||||||
getCompleteRateApi,
|
getCompleteRateApi,
|
||||||
getSpotRateApi,
|
getSpotRateApi,
|
||||||
getTypeRateApi
|
getTypeRateApi
|
||||||
} from '@/api/workOrder.js'
|
} from '@/api/workOrder'
|
||||||
|
import { getNewsPointRankApi } from '@/api/news'
|
||||||
|
|
||||||
const colors = ['#FDC40A', '#FF5232', '#50F0A6', '#5FDFFA']
|
const colors = ['#FDC40A', '#FF5232', '#50F0A6', '#5FDFFA']
|
||||||
let totalData = ref({
|
let totalData = ref({
|
||||||
@@ -146,7 +149,13 @@
|
|||||||
let xAxisData = ref([])
|
let xAxisData = ref([])
|
||||||
let typeRateData = ref([])
|
let typeRateData = ref([])
|
||||||
let spotRateData = ref([])
|
let spotRateData = ref([])
|
||||||
|
let pointRankData = ref([])
|
||||||
|
|
||||||
|
const getNewsPointRank = async () => {
|
||||||
|
let res = await getNewsPointRankApi()
|
||||||
|
pointRankData.value = res.data
|
||||||
|
console.log(res, '1111')
|
||||||
|
}
|
||||||
const getTypeRate = async () => {
|
const getTypeRate = async () => {
|
||||||
let res = await getTypeRateApi()
|
let res = await getTypeRateApi()
|
||||||
typeRateData.value = res.data.data
|
typeRateData.value = res.data.data
|
||||||
@@ -174,6 +183,7 @@
|
|||||||
getCompleteRate()
|
getCompleteRate()
|
||||||
getTypeRate()
|
getTypeRate()
|
||||||
getSpotRate()
|
getSpotRate()
|
||||||
|
getNewsPointRank()
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -219,14 +229,13 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
.work-box-2 {
|
.work-box-2 {
|
||||||
width: vw(1522);
|
|
||||||
margin-top: vh(120);
|
margin-top: vh(120);
|
||||||
margin-left: vw(10);
|
margin-left: vw(8);
|
||||||
position: relative;
|
|
||||||
z-index: 99;
|
|
||||||
.box-1 {
|
.box-1 {
|
||||||
height: vh(500);
|
padding: vw(1) 0;
|
||||||
background: linear-gradient(321deg, #0b2f64 0%, #062b57 100%);
|
box-sizing: border-box;
|
||||||
|
background: linear-gradient(to bottom, #0b2f64 0%, #062b57 100%);
|
||||||
.chart {
|
.chart {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
@@ -313,7 +322,9 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
.box-2 {
|
.box-2 {
|
||||||
height: vh(434);
|
padding: vw(1);
|
||||||
|
height: vh(442);
|
||||||
|
box-sizing: border-box;
|
||||||
background: linear-gradient(321deg, #0b2f64 0%, #062b57 100%);
|
background: linear-gradient(321deg, #0b2f64 0%, #062b57 100%);
|
||||||
|
|
||||||
.chart {
|
.chart {
|
||||||
|
|||||||
@@ -1,48 +1,69 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="work-box-3">
|
<div class="work-box-3">
|
||||||
<!-- 1 -->
|
|
||||||
<div class="work-2-flex">
|
<div class="work-2-flex">
|
||||||
<div class="header">
|
<Title1 title="消息统计" />
|
||||||
<div class="title"> <span>消息情况</span> </div>
|
<div class="statistics">
|
||||||
</div>
|
<div class="statistics-item">
|
||||||
<div class="hd-list">
|
<div class="flex align-center">
|
||||||
<div class="item item1">
|
<img class="statistics-item__icon" src="@/assets/images/dot-primary.svg" alt="" />
|
||||||
工单完成数 <span class="color1"><countup endVal="45678" /></span>
|
<span class="statistics-item__label">今日消息总条数</span>
|
||||||
|
</div>
|
||||||
|
<div class="statistics-item__value--primary">
|
||||||
|
<countup end-val="45678" />
|
||||||
|
<span class="statistics-item__value-suffix">条</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="item item3">
|
<div class="statistics-item">
|
||||||
紧急工单数 <span class=""><countup endVal="45678" /></span>
|
<div class="flex align-center">
|
||||||
|
<img class="statistics-item__icon" src="@/assets/images/dot-error.svg" alt="" />
|
||||||
|
<span class="statistics-item__label">紧急消息</span>
|
||||||
|
</div>
|
||||||
|
<div class="statistics-item__value--error">
|
||||||
|
<countup end-val="45678" />
|
||||||
|
<span class="statistics-item__value-suffix">条</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="item item2">
|
<div class="statistics-item">
|
||||||
重要工单数 <span class=""><countup endVal="45678" /></span>
|
<div class="flex align-center">
|
||||||
|
<img class="statistics-item__icon" src="@/assets/images/dot-warning.svg" alt="" />
|
||||||
|
<span class="statistics-item__label">重要消息</span>
|
||||||
|
</div>
|
||||||
|
<div class="statistics-item__value--warning">
|
||||||
|
<countup end-val="45678" />
|
||||||
|
<span class="statistics-item__value-suffix">条</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="item item1">
|
<div class="statistics-item">
|
||||||
普通工单数 <span class=""><countup endVal="45678" /></span>
|
<div class="flex align-center">
|
||||||
|
<img class="statistics-item__icon" src="@/assets/images/dot-success.svg" alt="" />
|
||||||
|
<span class="statistics-item__label">普通消息</span>
|
||||||
|
</div>
|
||||||
|
<div class="statistics-item__value--success">
|
||||||
|
<countup end-val="45678" />
|
||||||
|
<span class="statistics-item__value-suffix">条</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="chart-box flex">
|
<div class="chart-box">
|
||||||
<div class="box-item">
|
<pie :width="150" :height="150" />
|
||||||
<v-chart class="line-chart" :option="option" autoresize />
|
<pie :width="150" :height="150" />
|
||||||
</div>
|
<pie :width="150" :height="150" />
|
||||||
<div class="box-item">
|
|
||||||
<v-chart class="line-chart" :option="option" autoresize />
|
|
||||||
</div>
|
|
||||||
<div class="box-item">
|
|
||||||
<v-chart class="line-chart" :option="option" autoresize />
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- 2 -->
|
|
||||||
<div class="work-box-1">
|
<div class="work-box-1">
|
||||||
<!-- 最新工单 -->
|
<Title1 title="消息情况" />
|
||||||
<div class="header">
|
|
||||||
<div class="title"> <span>消息情况</span> </div>
|
|
||||||
</div>
|
|
||||||
<!-- 列表 -->
|
|
||||||
<div class="list">
|
<div class="list">
|
||||||
<div class="li" v-for="item in 40">
|
<div class="item" v-for="(item, index) in list" :key="index">
|
||||||
<span class="label label1">普通</span>
|
<span
|
||||||
<p>这是一条工单信息这是一条工单信息这是一条工单信息这是一条工单信息这是一条</p>
|
:class="{
|
||||||
<span class="time">2024-12.16 23:58</span>
|
'label--primary': item.level == 'normal',
|
||||||
|
'label--warning': item.level == 'warn',
|
||||||
|
'label--error': item.level == 'important'
|
||||||
|
}"
|
||||||
|
>{{ item.level_text }}</span
|
||||||
|
>
|
||||||
|
<p>{{ item.title }}</p>
|
||||||
|
<span class="time">{{ item.time }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -51,162 +72,42 @@
|
|||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import countup from 'vue-countup-v3'
|
import countup from 'vue-countup-v3'
|
||||||
import * as echarts from 'echarts'
|
import pie from './pie.vue'
|
||||||
import { fitChartSize } from '@/utils/dataUtil'
|
import { getNewsListApi, getNewsStateApi, getNewsTotalApi } from '@/api/news'
|
||||||
import Map from '@/components/Map/marker.vue'
|
|
||||||
import VChart, { THEME_KEY } from 'vue-echarts'
|
const list = ref([])
|
||||||
import { ref, provide } from 'vue'
|
|
||||||
provide(THEME_KEY, 'dark')
|
const getNewsTotal = async () => {
|
||||||
const option = ref({
|
let res = await getNewsTotalApi()
|
||||||
backgroundColor: 'transparent',
|
console.log(res, '============')
|
||||||
title: [
|
}
|
||||||
{
|
const getNewsState = async () => {
|
||||||
text: '45.5%',
|
let res = await getNewsStateApi()
|
||||||
x: 'center',
|
}
|
||||||
top: '34%',
|
const getNewsList = async () => {
|
||||||
textStyle: {
|
let res = await getNewsListApi()
|
||||||
color: '#00D0FF',
|
list.value = res.data
|
||||||
fontSize: fitChartSize(12)
|
}
|
||||||
}
|
onMounted(() => {
|
||||||
},
|
getNewsList()
|
||||||
{
|
getNewsTotal()
|
||||||
text: '完成率',
|
getNewsState()
|
||||||
x: 'center',
|
|
||||||
top: '56%',
|
|
||||||
textStyle: {
|
|
||||||
color: '#fff',
|
|
||||||
fontSize: fitChartSize(12)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
series: [
|
|
||||||
// 内侧环
|
|
||||||
{
|
|
||||||
type: 'gauge',
|
|
||||||
radius: '100%',
|
|
||||||
center: ['50%', '50%'],
|
|
||||||
min: 0,
|
|
||||||
max: 100,
|
|
||||||
startAngle: 360,
|
|
||||||
endAngle: 0,
|
|
||||||
itemStyle: {
|
|
||||||
color: '#00D0FF'
|
|
||||||
},
|
|
||||||
axisLine: {
|
|
||||||
show: true,
|
|
||||||
roundCap: false,
|
|
||||||
lineStyle: {
|
|
||||||
color: [
|
|
||||||
[0, '#075199'],
|
|
||||||
[1, '#075199']
|
|
||||||
],
|
|
||||||
width: fitChartSize(6)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
progress: {
|
|
||||||
show: true,
|
|
||||||
roundCap: false,
|
|
||||||
width: fitChartSize(6)
|
|
||||||
},
|
|
||||||
pointer: {
|
|
||||||
// 指针
|
|
||||||
show: false
|
|
||||||
},
|
|
||||||
axisTick: {
|
|
||||||
// 刻度
|
|
||||||
show: false
|
|
||||||
},
|
|
||||||
splitLine: {
|
|
||||||
// 分割线
|
|
||||||
show: false
|
|
||||||
},
|
|
||||||
axisLabel: {
|
|
||||||
// 刻度标签
|
|
||||||
show: false
|
|
||||||
},
|
|
||||||
detail: {
|
|
||||||
// 仪表盘详情
|
|
||||||
show: false
|
|
||||||
},
|
|
||||||
data: [
|
|
||||||
{
|
|
||||||
value: 50
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'gauge',
|
|
||||||
radius: '95%',
|
|
||||||
center: ['50%', '50%'],
|
|
||||||
min: 0,
|
|
||||||
max: 100,
|
|
||||||
startAngle: 360,
|
|
||||||
endAngle: 0,
|
|
||||||
itemStyle: {
|
|
||||||
color: '#057EB9'
|
|
||||||
},
|
|
||||||
axisLine: {
|
|
||||||
roundCap: false,
|
|
||||||
lineStyle: {
|
|
||||||
color: [
|
|
||||||
[0, '#075199'],
|
|
||||||
[1, '#075199']
|
|
||||||
],
|
|
||||||
width: fitChartSize(10)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
progress: {
|
|
||||||
show: true,
|
|
||||||
roundCap: false,
|
|
||||||
width: fitChartSize(10)
|
|
||||||
},
|
|
||||||
pointer: {
|
|
||||||
// 指针
|
|
||||||
show: false
|
|
||||||
},
|
|
||||||
axisTick: {
|
|
||||||
// 刻度
|
|
||||||
show: false
|
|
||||||
},
|
|
||||||
splitLine: {
|
|
||||||
// 分割线
|
|
||||||
show: false
|
|
||||||
},
|
|
||||||
axisLabel: {
|
|
||||||
// 刻度标签
|
|
||||||
show: false
|
|
||||||
},
|
|
||||||
detail: {
|
|
||||||
// 仪表盘详情
|
|
||||||
show: false
|
|
||||||
},
|
|
||||||
data: [
|
|
||||||
{
|
|
||||||
value: 50
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.work-box-3 {
|
.work-box-3 {
|
||||||
width: vw(813);
|
width: vw(840);
|
||||||
height: vh(380);
|
|
||||||
margin-top: vh(120);
|
margin-top: vh(120);
|
||||||
margin-left: vw(10);
|
margin-left: vw(8);
|
||||||
position: relative;
|
|
||||||
z-index: 99;
|
|
||||||
background: linear-gradient(321deg, #0b2f64 0%, #062b57 100%);
|
|
||||||
|
|
||||||
.work-box-1 {
|
.work-box-1 {
|
||||||
width: vw(815);
|
|
||||||
height: vh(588);
|
|
||||||
background: linear-gradient(321deg, #0b2f64 0%, #062b57 100%);
|
|
||||||
position: relative;
|
|
||||||
z-index: 99;
|
|
||||||
padding: 0 vw(20);
|
padding: 0 vw(20);
|
||||||
|
height: vh(566);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
background: linear-gradient(321deg, #0b2f64 0%, #062b57 100%);
|
||||||
|
|
||||||
.list {
|
.list {
|
||||||
/* 滚动条整体样式 */
|
/* 滚动条整体样式 */
|
||||||
&::-webkit-scrollbar {
|
&::-webkit-scrollbar {
|
||||||
@@ -221,15 +122,15 @@
|
|||||||
background: rgba(0, 150, 255, 0.63); /* 滑块的背景色 */
|
background: rgba(0, 150, 255, 0.63); /* 滑块的背景色 */
|
||||||
border-radius: 5px; /* 滑块的圆角 */
|
border-radius: 5px; /* 滑块的圆角 */
|
||||||
}
|
}
|
||||||
height: vh(510);
|
height: vh(500);
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
.li:nth-child(odd) {
|
.item:nth-child(odd) {
|
||||||
background: rgba(3, 78, 153, 0.3);
|
background: rgba(3, 78, 153, 0.3);
|
||||||
}
|
}
|
||||||
.li:nth-child(even) {
|
.item:nth-child(even) {
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
}
|
}
|
||||||
.li {
|
.item {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: flex-start;
|
justify-content: flex-start;
|
||||||
@@ -245,13 +146,16 @@
|
|||||||
display: inline-block;
|
display: inline-block;
|
||||||
margin-right: vw(10);
|
margin-right: vw(10);
|
||||||
}
|
}
|
||||||
.label1 {
|
.label--primary {
|
||||||
|
@extend .label;
|
||||||
background: #2380fb;
|
background: #2380fb;
|
||||||
}
|
}
|
||||||
.label2 {
|
.label--warning {
|
||||||
|
@extend .label;
|
||||||
background: #feae00;
|
background: #feae00;
|
||||||
}
|
}
|
||||||
.label3 {
|
.label--error {
|
||||||
|
@extend .label;
|
||||||
background: #d9011b;
|
background: #d9011b;
|
||||||
}
|
}
|
||||||
.time {
|
.time {
|
||||||
@@ -281,128 +185,72 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.header {
|
|
||||||
position: relative;
|
|
||||||
margin: 0 vh(20);
|
|
||||||
.title {
|
|
||||||
margin: vh(5) auto;
|
|
||||||
width: vw(468);
|
|
||||||
height: vh(32);
|
|
||||||
font-weight: 800;
|
|
||||||
font-size: vw(16);
|
|
||||||
color: #fff;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
background-image: url('@/assets/images/title-4.png');
|
|
||||||
background-size: 100% 100%;
|
|
||||||
span {
|
|
||||||
font-weight: 800;
|
|
||||||
color: transparent;
|
|
||||||
-webkit-background-clip: text;
|
|
||||||
background-clip: text;
|
|
||||||
-webkit-text-fill-color: transparent;
|
|
||||||
background-image: linear-gradient(to bottom, #ffffff 0%, #87c9ff 100%);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
.work-2-flex {
|
.work-2-flex {
|
||||||
background: linear-gradient(321deg, #0b2f64 0%, #062b57 100%);
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
height: vh(380);
|
height: vh(380);
|
||||||
overflow: hidden;
|
margin-bottom: vw(8);
|
||||||
|
background: linear-gradient(321deg, #0b2f64 0%, #062b57 100%);
|
||||||
|
|
||||||
.chart-box {
|
.chart-box {
|
||||||
|
padding: vw(20) vw(15);
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
padding: vw(20) vw(15);
|
|
||||||
height: vh(360);
|
|
||||||
padding-top: vh(35);
|
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
.box-item {
|
|
||||||
flex: 1;
|
|
||||||
width: vw(140);
|
|
||||||
height: vh(140);
|
|
||||||
padding: vw(10);
|
|
||||||
.line-chart {
|
|
||||||
// width:100%;
|
|
||||||
// height:100%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
.header {
|
|
||||||
position: relative;
|
|
||||||
margin: vh(20);
|
|
||||||
|
|
||||||
.title {
|
.statistics {
|
||||||
margin: vh(5) auto;
|
|
||||||
width: vw(468);
|
|
||||||
height: vh(32);
|
|
||||||
font-weight: 800;
|
|
||||||
font-size: vw(16);
|
|
||||||
color: #fff;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
background-image: url('@/assets/images/title-4.png');
|
|
||||||
background-size: 100% 100%;
|
|
||||||
span {
|
|
||||||
font-weight: 800;
|
|
||||||
color: transparent;
|
|
||||||
-webkit-background-clip: text;
|
|
||||||
background-clip: text;
|
|
||||||
-webkit-text-fill-color: transparent;
|
|
||||||
background-image: linear-gradient(to bottom, #ffffff 0%, #87c9ff 100%);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.hd-list {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
position: relative;
|
|
||||||
padding: 0 vw(20);
|
padding: 0 vw(20);
|
||||||
.h-icon {
|
display: flex;
|
||||||
position: absolute;
|
justify-content: space-around;
|
||||||
left: vw(70);
|
&-item {
|
||||||
top: 50%;
|
|
||||||
transform: translateY(-50%);
|
|
||||||
width: vw(74);
|
|
||||||
height: vh(74);
|
|
||||||
}
|
|
||||||
.item {
|
|
||||||
display: flex;
|
|
||||||
width: vw(210);
|
|
||||||
height: vh(58);
|
|
||||||
line-height: vh(58);
|
|
||||||
padding-left: vw(10);
|
|
||||||
text-align: center;
|
|
||||||
margin: 0 vw(15);
|
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
font-size: vw(14);
|
font-size: vw(14);
|
||||||
color: rgba(255, 255, 255, 0.9);
|
}
|
||||||
text-align: left;
|
&-item__icon {
|
||||||
font-style: normal;
|
width: vw(24);
|
||||||
text-transform: none;
|
height: vw(24);
|
||||||
span {
|
}
|
||||||
font-size: vw(24);
|
&-item__label {
|
||||||
position: relative;
|
color: #fff;
|
||||||
top: vh(2);
|
font-size: vw(14);
|
||||||
margin-left: vw(5);
|
}
|
||||||
}
|
&-item__value {
|
||||||
.color1 {
|
position: relative;
|
||||||
|
margin-top: vh(16);
|
||||||
|
padding-left: vw(12);
|
||||||
|
padding-bottom: vh(12);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: vw(28);
|
||||||
|
color: #fff;
|
||||||
|
&--primary {
|
||||||
|
@extend .statistics-item__value;
|
||||||
color: #02f9fa;
|
color: #02f9fa;
|
||||||
|
background-image: url('@/assets/images/mask-primary.png');
|
||||||
|
background-size: 100% 100%;
|
||||||
|
}
|
||||||
|
&--error {
|
||||||
|
@extend .statistics-item__value;
|
||||||
|
background-image: url('@/assets/images/mask-error.png');
|
||||||
|
background-size: 100% 100%;
|
||||||
|
}
|
||||||
|
&--warning {
|
||||||
|
@extend .statistics-item__value;
|
||||||
|
background-image: url('@/assets/images/mask-warning.png');
|
||||||
|
background-size: 100% 100%;
|
||||||
|
}
|
||||||
|
&--success {
|
||||||
|
@extend .statistics-item__value;
|
||||||
|
background-image: url('@/assets/images/mask-success.png');
|
||||||
|
background-size: 100% 100%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.item1 {
|
&-item__value-suffix {
|
||||||
background-image: url('@/assets/images/work-n-bg-1.png');
|
font-size: vw(12);
|
||||||
background-size: 100% 100%;
|
margin-top: vh(6);
|
||||||
}
|
|
||||||
.item2 {
|
|
||||||
background-image: url('@/assets/images/work-n-bg-2.png');
|
|
||||||
background-size: 100% 100%;
|
|
||||||
}
|
|
||||||
.item3 {
|
|
||||||
background-image: url('@/assets/images/work-n-bg-3.png');
|
|
||||||
background-size: 100% 100%;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
157
src/views/workOrder/components/pie.vue
Normal file
@@ -0,0 +1,157 @@
|
|||||||
|
<template>
|
||||||
|
<div class="pie" :id="id" />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { fitChartSize } from '@/utils/dataUtil'
|
||||||
|
import { useEchart } from '@/hooks/echart'
|
||||||
|
|
||||||
|
const { id, setOption } = useEchart()
|
||||||
|
|
||||||
|
let option = {
|
||||||
|
backgroundColor: 'transparent',
|
||||||
|
title: [
|
||||||
|
{
|
||||||
|
text: '45.5%',
|
||||||
|
x: 'center',
|
||||||
|
top: '42%',
|
||||||
|
textStyle: {
|
||||||
|
color: '#02F9FA',
|
||||||
|
fontSize: fitChartSize(24)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: '完成率',
|
||||||
|
x: 'center',
|
||||||
|
top: '54%',
|
||||||
|
textStyle: {
|
||||||
|
color: '#fff',
|
||||||
|
fontSize: fitChartSize(12)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
type: 'gauge',
|
||||||
|
radius: '100%',
|
||||||
|
center: ['50%', '50%'],
|
||||||
|
min: 0,
|
||||||
|
max: 100,
|
||||||
|
startAngle: 90,
|
||||||
|
endAngle: 450,
|
||||||
|
clockwise: false,
|
||||||
|
itemStyle: {
|
||||||
|
color: '#00D0FF'
|
||||||
|
},
|
||||||
|
axisLine: {
|
||||||
|
show: true,
|
||||||
|
roundCap: false,
|
||||||
|
lineStyle: {
|
||||||
|
color: [
|
||||||
|
[0, '#075199'],
|
||||||
|
[1, '#075199']
|
||||||
|
],
|
||||||
|
width: fitChartSize(6)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
progress: {
|
||||||
|
show: true,
|
||||||
|
roundCap: false,
|
||||||
|
width: fitChartSize(6)
|
||||||
|
},
|
||||||
|
pointer: {
|
||||||
|
// 指针
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
axisTick: {
|
||||||
|
// 刻度
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
splitLine: {
|
||||||
|
// 分割线
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
axisLabel: {
|
||||||
|
// 刻度标签
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
detail: {
|
||||||
|
// 仪表盘详情
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
data: [
|
||||||
|
{
|
||||||
|
value: 50
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'gauge',
|
||||||
|
radius: '95%',
|
||||||
|
center: ['50%', '50%'],
|
||||||
|
min: 0,
|
||||||
|
max: 100,
|
||||||
|
startAngle: 90,
|
||||||
|
endAngle: 450,
|
||||||
|
clockwise: false,
|
||||||
|
itemStyle: {
|
||||||
|
color: '#057EB9'
|
||||||
|
},
|
||||||
|
axisLine: {
|
||||||
|
roundCap: false,
|
||||||
|
lineStyle: {
|
||||||
|
color: [
|
||||||
|
[0, '#075199'],
|
||||||
|
[1, '#075199']
|
||||||
|
],
|
||||||
|
width: fitChartSize(10)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
progress: {
|
||||||
|
show: true,
|
||||||
|
roundCap: false,
|
||||||
|
width: fitChartSize(10)
|
||||||
|
},
|
||||||
|
pointer: {
|
||||||
|
// 指针
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
axisTick: {
|
||||||
|
// 刻度
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
splitLine: {
|
||||||
|
// 分割线
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
axisLabel: {
|
||||||
|
// 刻度标签
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
detail: {
|
||||||
|
// 仪表盘详情
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
data: [
|
||||||
|
{
|
||||||
|
value: 50
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
const init = () => {
|
||||||
|
setOption(option)
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
init()
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.pie {
|
||||||
|
width: vw(200);
|
||||||
|
height: vh(200);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -31,7 +31,8 @@ export default defineConfig({
|
|||||||
resolve: {
|
resolve: {
|
||||||
alias: {
|
alias: {
|
||||||
'@': fileURLToPath(new URL('./src', import.meta.url))
|
'@': fileURLToPath(new URL('./src', import.meta.url))
|
||||||
}
|
},
|
||||||
|
extensions: ['.js', '.vue']
|
||||||
},
|
},
|
||||||
css: {
|
css: {
|
||||||
preprocessorOptions: {
|
preprocessorOptions: {
|
||||||
|
|||||||