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( console.log(
boxen( boxen(
gradientString('cyan', 'magenta').multiline( gradientString('cyan', 'magenta').multiline(
`🎉 恭喜打包完成(总用时${format})打包大小(${logOutputSize()}` `🎉 恭喜打包完成(总用时${format})打包大小(${logOutputSize()})`
), ),
boxenOptions 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: { xAxis: {
type: 'category', type: 'category',
show: true, show: true,
data: ['02.01', '02.02', '02.03', '02.04', '02.05', '02.06', '02.07'], data: [],
itemStyle: { color: '#ccc' }, itemStyle: { color: '#ccc' },
splitLine: { splitLine: {
show: true, show: true,
@ -108,7 +108,10 @@ export const renderEcharts = (element: Ref<HTMLDivElement>) => {
/** 更新图表数据 */ /** 更新图表数据 */
export const updateChart = (option: any) => { export const updateChart = (option: any) => {
const series = myChart.getOption().series; const series = myChart.getOption().series;
series[0].data = option.data1; const xAxis = myChart.getOption().xAxis;
series[1].data = option.data2; series[0].data = option.outer;
myChart.setOption({ series }); series[1].data = option.enter;
xAxis[0].data = option.timeline;
myChart.setOption({ series, xAxis });
}; };

View File

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

View File

@ -1,11 +1,36 @@
<script lang="ts" setup> <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 SmartParkContent from '@/views/smart-park/components/smart-park-content.vue';
import SmartParkFooter from '@/views/smart-park/components/smart-park-footer.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> </script>
<template> <template>
<div class="smart-park"> <div class="smart-park" @mousemove="handleMouseMovement">
<div class="smart-park__arrow left-[38px]"> <div v-show="showNavigationArrows" class="smart-park__arrow left-[38px]">
<img alt="左箭头" src="@/views/smart-park/images/arrow/arrow-left.png" /> <img alt="左箭头" src="@/views/smart-park/images/arrow/arrow-left.png" />
</div> </div>
@ -13,7 +38,7 @@ import SmartParkFooter from '@/views/smart-park/components/smart-park-footer.vue
<smart-park-footer /> <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" /> <img alt="左箭头" src="@/views/smart-park/images/arrow/arrow-right.png" />
</div> </div>
</div> </div>

View File

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