feat: smart-park接口模拟完成

This commit is contained in:
bunny 2025-05-13 15:38:42 +08:00
parent a74f51fdb0
commit c5072da2b1
9 changed files with 240 additions and 89 deletions

View File

@ -47,7 +47,7 @@ export const viteConsoleLog = (mode: string) => {
console.log(
boxen(
gradientString('cyan', 'magenta').multiline(
`🎉 恭喜打包完成(总用时${format})打包大小(${logOutputSize()}`
`🎉 恭喜打包完成(总用时${format})打包大小(${logOutputSize()})`
),
boxenOptions
)

88
mock/smart-park.ts Normal file
View File

@ -0,0 +1,88 @@
import { defineFakeRoute } from 'vite-plugin-fake-server';
const randomNumber = (range: number = 100) => {
return parseInt((Math.random() * range).toFixed(0));
};
const mockRoadStatus = () => {
const list = ['拥堵', '畅通'];
const index = randomNumber(1);
return list[index];
};
export default defineFakeRoute([
// 道路状况
{
url: '/api/smart-park/road-status',
method: 'GET',
response: () => ({
code: 200,
data: {
entrances: [
{
id: 1,
name: '入卡口(西北门)',
status: mockRoadStatus(),
},
{
id: 2,
name: '入卡口(东北门)',
status: mockRoadStatus(),
},
{
id: 3,
name: '入卡口(东南门)',
status: mockRoadStatus(),
},
{
id: 4,
name: '入卡口(东南门)',
status: mockRoadStatus(),
},
],
suggest: ` 高峰时段大量车流量容易造成拥堵主要由XXX企业、XXX企业的车辆构成
<span>XXX企业向后延迟15min错峰入园</span>
XXX企业XXX企业的车辆构成`,
},
message: '操作成功',
}),
},
// 车辆监控
{
url: '/api/smart-park/monitor',
method: 'GET',
response: () => ({
code: 200,
data: [
{ count: randomNumber(999), door: '入卡口(西北门)', percent: randomNumber() },
{ count: randomNumber(999), door: '入卡口(东北门)', percent: randomNumber() },
{ count: randomNumber(999), door: '入卡口(东南门)', percent: randomNumber() },
{ count: randomNumber(999), door: '入卡口(东南门)', percent: randomNumber() },
],
message: '操作成功',
}),
},
// 车流量
{
url: '/api/smart-park/flow-rate',
method: 'GET',
response: () => ({
code: 200,
data: {
overview: [
{ title: '最高进园车流量', statistics: randomNumber(9999) },
{ title: '最高出园车流量', statistics: randomNumber(9999) },
],
timeline: ['02.01', '02.02', '02.03', '02.04', '02.05', '02.06', '02.22'],
enter: Array(11)
.fill(0)
.map(() => randomNumber(999).toFixed(2)),
outer: Array(11)
.fill(0)
.map(() => randomNumber(999).toFixed(2)),
},
message: '操作成功',
}),
},
]);

View File

@ -93,4 +93,4 @@
}
}
}
}
}

16
src/api/smartPark.ts Normal file
View File

@ -0,0 +1,16 @@
import request from '@/api/server/request';
/* 实时道路 */
export const fetchRoadStatus = () => {
return request.get('/smart-park/road-status');
};
/* 车辆监控 */
export const fetchTollgateMonitoringData = () => {
return request.get('smart-park/monitor');
};
/* 车流量概览 */
export const fetchTrafficStatistics = () => {
return request.get('/smart-park/flow-rate');
};

View File

@ -0,0 +1,38 @@
import { defineStore } from 'pinia';
import {
fetchRoadStatus,
fetchTollgateMonitoringData,
fetchTrafficStatistics,
} from '@/api/smartPark';
export const useSmartPark = defineStore('smartparkStore', {
state: () => ({
// 道路状态
roadStatus: [],
// 道路建议
roadStatusSuggest: '',
// 卡口车辆监控
tollgateMonitoringData: [],
// 车浏览概览
trafficStatistics: { overview: [], outer: [], enter: [], timeline: [] },
}),
actions: {
/* 道路情况 */
async loadRoadStatus() {
const result: any = await fetchRoadStatus();
this.roadStatus = result.entrances;
this.roadStatusSuggest = result.suggest;
},
/* 卡口车辆监控 */
async loadTollgateMonitoringData() {
const result = await fetchTollgateMonitoringData();
this.tollgateMonitoringData = result;
},
/* 车流量概览 */
async loadFlowRate() {
const result = await fetchTrafficStatistics();
this.trafficStatistics = result;
},
},
});

View File

@ -31,7 +31,7 @@ const option = {
xAxis: {
type: 'category',
show: true,
data: ['02.01', '02.02', '02.03', '02.04', '02.05', '02.06', '02.07'],
data: [],
itemStyle: { color: '#ccc' },
splitLine: {
show: true,
@ -108,7 +108,10 @@ export const renderEcharts = (element: Ref<HTMLDivElement>) => {
/** 更新图表数据 */
export const updateChart = (option: any) => {
const series = myChart.getOption().series;
series[0].data = option.data1;
series[1].data = option.data2;
myChart.setOption({ series });
const xAxis = myChart.getOption().xAxis;
series[0].data = option.outer;
series[1].data = option.enter;
xAxis[0].data = option.timeline;
myChart.setOption({ series, xAxis });
};

View File

@ -1,33 +1,38 @@
<script lang="ts" setup>
import { useIntervalFn } from '@vueuse/core';
import { storeToRefs } from 'pinia';
import { onMounted, ref } from 'vue';
import { useSmartPark } from '@/store/modules/smartPark';
import { renderEcharts, updateChart } from '@/views/smart-park/charts/right-sidebar';
import ContentItem from '@/views/smart-park/components/common/content-item.vue';
import ContentPercent from '@/views/smart-park/components/common/content-percent.vue';
const weekDataChart = ref<HTMLDivElement>();
/** 随机数据 */
const randomData = () => {
renderEcharts(weekDataChart);
const smartPark = useSmartPark();
const { roadStatus, roadStatusSuggest, tollgateMonitoringData, trafficStatistics } =
storeToRefs(smartPark);
function random() {
return Array(11)
.fill(0)
.map(() => {
const num = (Math.random() * 100).toFixed(2);
return parseInt(num);
});
}
const initData = () => {
smartPark.loadRoadStatus();
smartPark.loadTollgateMonitoringData();
smartPark.loadFlowRate();
useIntervalFn(() => {
updateChart({ data1: random(), data2: random() });
}, 1000);
updateChart({
enter: trafficStatistics.value.enter,
outer: trafficStatistics.value.outer,
timeline: trafficStatistics.value.timeline,
});
};
onMounted(() => {
randomData();
renderEcharts(weekDataChart);
initData();
useIntervalFn(() => {
initData();
}, 1000);
});
</script>
@ -42,36 +47,33 @@ onMounted(() => {
<!-- 汽车列表 -->
<ul class="mt-[32px]">
<li class="smart-park__sidebar--left-item">
<img alt="car-1" src="../images/car/car-1.png" />
<p>入卡口西北门</p>
<span class="dashed-circle c-primary-secondary border-b-primary-secondary">畅通</span>
</li>
<li class="smart-park__sidebar--left-item">
<img alt="car-1" src="../images/car/car-1.png" />
<p>入卡口东北门</p>
<span class="dashed-circle c-primary-secondary border-b-primary-secondary">畅通</span>
</li>
<li class="smart-park__sidebar--left-item">
<img alt="car-1" src="../images/car/car-2.png" />
<p>入卡口东北门</p>
<span class="dashed-circle c-warning border-b-warning">拥堵</span>
</li>
<li class="smart-park__sidebar--left-item">
<img alt="car-1" src="../images/car/car-1.png" />
<p>入卡口东南门</p>
<span class="dashed-circle c-primary-secondary border-b-primary-secondary">畅通</span>
<li
v-for="(item, index) in roadStatus"
:key="index"
class="smart-park__sidebar--left-item"
>
<div v-show="item.status === '畅通'" class="flex-x-around w-[100%]">
<img alt="car-1" src="../images/car/car-1.png" />
<p>{{ item.name }}</p>
<span class="dashed-circle c-primary-secondary border-b-primary-secondary">
{{ item.status }}
</span>
</div>
<div v-show="item.status === '拥堵'" class="flex-x-around w-[100%]">
<img alt="car-1" src="../images/car/car-2.png" />
<p>{{ item.name }}</p>
<span class="dashed-circle c-warning border-b-warning">
{{ item.status }}
</span>
</div>
</li>
</ul>
<!-- 建议 -->
<div class="smart-park__sidebar--left-suggest">
<h5>车流量建议</h5>
<p>
高峰时段大量车流量容易造成拥堵主要由XXX企业XXX企业的车辆构成
<span>可建议XXX企业向后延迟15min错峰入园</span>
高峰时段大量车流量容易造成拥堵 主要由XXX企业XXX企业的车辆构成
</p>
<p v-html="roadStatusSuggest" />
</div>
</div>
</div>
@ -84,21 +86,13 @@ onMounted(() => {
<!-- 中间布局 -->
<div class="smart-park__body-inner">
<div class="pos-relative">
<content-item :count="45" class="top-[37px] left-[40px] w-[175px]" door="西北门" />
<content-percent :percent="44" class="top-[73px] left-[193px]" />
</div>
<div class="pos-relative">
<content-item :count="67" class="top-[37px] left-[120px] w-[175px]" door="东北门" />
<content-percent :percent="25" class="top-[73px] right-[192px]" />
</div>
<div class="pos-relative">
<content-item :count="345" class="top-[45px] left-[34px] w-[175px]" door="西南门" />
<content-percent :percent="25" class="top-[40px] left-[193px]" />
</div>
<div class="pos-relative">
<content-item :count="145" class="top-[45px] left-[130px] w-[175px]" door="东南门" />
<content-percent :percent="44" class="top-[40px] left-[66px]" />
<div v-for="(item, index) in tollgateMonitoringData" :key="index" class="pos-relative">
<content-item
:count="item.count"
class="top-[37px] left-[40px] w-[175px]"
:door="item.door"
/>
<content-percent :percent="item.percent" class="top-[73px] left-[193px]" />
</div>
<div class="smart-park__body-content">
@ -119,13 +113,13 @@ onMounted(() => {
<!-- 汽车列表 -->
<ul class="flex-x-around mt-[32px] w-[331px]">
<li class="smart-park__sidebar-flow-item">
<span>最高进园车流量</span>
<span>897</span>
</li>
<li class="smart-park__sidebar-flow-item">
<span>最高进园车流量</span>
<span>494</span>
<li
v-for="(item, index) in trafficStatistics.overview"
:key="index"
class="smart-park__sidebar-flow-item"
>
<span>{{ item.title }}</span>
<span>{{ item.statistics }}</span>
</li>
</ul>
@ -172,7 +166,7 @@ onMounted(() => {
background: url('@/views/smart-park/images/bg/bg-suggest.png') no-repeat center;
background-size: cover;
span {
:deep(span) {
color: var(--color-warning-secondary);
}
}

View File

@ -1,11 +1,36 @@
<script lang="ts" setup>
import { useTimeoutFn } from '@vueuse/core';
import { ref } from 'vue';
import SmartParkContent from '@/views/smart-park/components/smart-park-content.vue';
import SmartParkFooter from '@/views/smart-park/components/smart-park-footer.vue';
const showNavigationArrows = ref(false);
let hideArrowsTimeout: (() => void) | null = null;
/* 鼠标经过显示箭头 */
const handleMouseMovement = () => {
//
showNavigationArrows.value = true;
//
if (hideArrowsTimeout) {
hideArrowsTimeout();
}
// 2
const { start, stop } = useTimeoutFn(() => {
showNavigationArrows.value = false;
}, 2000);
hideArrowsTimeout = stop;
start();
};
</script>
<template>
<div class="smart-park">
<div class="smart-park__arrow left-[38px]">
<div class="smart-park" @mousemove="handleMouseMovement">
<div v-show="showNavigationArrows" class="smart-park__arrow left-[38px]">
<img alt="左箭头" src="@/views/smart-park/images/arrow/arrow-left.png" />
</div>
@ -13,7 +38,7 @@ import SmartParkFooter from '@/views/smart-park/components/smart-park-footer.vue
<smart-park-footer />
<div class="smart-park__arrow right-[38px]">
<div v-show="showNavigationArrows" class="smart-park__arrow right-[38px]">
<img alt="左箭头" src="@/views/smart-park/images/arrow/arrow-right.png" />
</div>
</div>

View File

@ -17,22 +17,12 @@
"baseUrl": ".",
"allowJs": false,
"resolveJsonModule": true,
"lib": [
"ESNext",
"DOM"
],
"lib": ["ESNext", "DOM"],
"paths": {
"@/*": [
"src/*"
]
// "@build/*": [
// "build/*"
// ]
"vue": ["node_modules/vue/dist/vue.esm.js"],
"@/*": ["src/*"]
},
"types": [
"node",
"vite/client"
]
"types": ["node", "vite/client"]
},
"include": [
"mock/*.ts",
@ -42,8 +32,5 @@
"vite.config.ts",
"src/**/*.d.ts"
],
"exclude": [
"dist",
"node_modules"
]
"exclude": ["dist", "node_modules"]
}