194 lines
4.5 KiB
Vue
194 lines
4.5 KiB
Vue
<template>
|
|
|
|
<div class="go-parking-scene">
|
|
<PublicSmallBorder :title-text="option.titleText">
|
|
<div class="content">
|
|
<div v-for="(scene, index) in option.dataset" :key="index" class="scene-item">
|
|
<div class="scene-header">
|
|
<img src="./assets/dot.png" alt="" class="dots"></img>
|
|
<span class="scene-name" :style="{ color: option.sceneNameColor, fontSize: option.sceneNameSize + 'px' }">{{
|
|
scene.name }}</span>
|
|
</div>
|
|
<div class="scene-metrics">
|
|
<img src="./assets/area.png" alt="" class="metric-icon"></img>
|
|
<div class="scene-content">
|
|
<div v-for="(metric, mIndex) in scene.metrics" :key="mIndex" class="metric-box">
|
|
<span class="metric-label" :style="{ color: option.labelColor, fontSize: option.labelSize + 'px' }">{{
|
|
metric.label }}</span>
|
|
<span class="metric-value"
|
|
:style="{ color: mIndex === 0 ? option.valueColor : option.valueColor2, fontSize: option.valueSize + 'px' }">{{
|
|
metric.value }}</span>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
</div>
|
|
</PublicSmallBorder>
|
|
|
|
</div>
|
|
|
|
</template>
|
|
<script setup lang="ts">
|
|
import { PropType, computed, onMounted, watch, ref } from 'vue'
|
|
import { option as configOption } from './config'
|
|
import { ParkingSceneConfig } from './index'
|
|
import axios from 'axios';
|
|
import PublicSmallBorder from '../../PublicSmallBorder/index.vue'
|
|
const props = defineProps({
|
|
chartConfig: {
|
|
type: Object as PropType<{ option: typeof configOption }>,
|
|
required: true
|
|
}
|
|
})
|
|
|
|
const key = ParkingSceneConfig.key;
|
|
const option = computed(() => props.chartConfig.option)
|
|
const isFetching = ref(false) // 防止重复请求
|
|
|
|
// 获取静态数据
|
|
const getStaticData = async (key: string, componentIndexKey: string, sceneCode: string) => {
|
|
try {
|
|
const response = await axios.get('/staticData/static.json');
|
|
if (response.data) {
|
|
console.log('静态数据:', response.data);
|
|
const dataTemp = response.data[sceneCode]?.[key]?.[componentIndexKey]?.['source'];
|
|
if (!dataTemp) {
|
|
console.warn(`Data not found for sceneCode: ${sceneCode}, key: ${key}, componentIndexKey: ${componentIndexKey}`);
|
|
return props.chartConfig.option.dataset; // 返回默认数据
|
|
}
|
|
return dataTemp;
|
|
}
|
|
} catch (err) {
|
|
console.error('获取static.json失败:', err);
|
|
}
|
|
return props.chartConfig.option.dataset; // 出错时返回默认数据
|
|
}
|
|
|
|
|
|
// 统一数据获取方法
|
|
const fetchData = async () => {
|
|
// 防止重复请求
|
|
if (isFetching.value) return;
|
|
|
|
isFetching.value = true;
|
|
try {
|
|
let data;
|
|
|
|
// 静态数据
|
|
data = await getStaticData(key, option.value.componentIndexKey, option.value.sceneCode);
|
|
props.chartConfig.option.dataset = data;
|
|
|
|
if (JSON.stringify(data) !== JSON.stringify(option.value.dataset)) {
|
|
|
|
console.log('更新数据:', data);
|
|
}
|
|
} finally {
|
|
isFetching.value = false;
|
|
}
|
|
}
|
|
|
|
watch(
|
|
() => [
|
|
props.chartConfig.option.sceneCode,
|
|
props.chartConfig.option.componentIndexKey
|
|
],
|
|
async () => {
|
|
await fetchData();
|
|
},
|
|
{
|
|
immediate: true,
|
|
deep: true
|
|
}
|
|
)
|
|
|
|
// 组件挂载时获取数据
|
|
onMounted(async () => {
|
|
await fetchData();
|
|
})
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
.go-parking-scene {
|
|
width: 100%;
|
|
box-sizing: border-box;
|
|
display: flex;
|
|
flex-direction: column;
|
|
|
|
.content {
|
|
flex: 1;
|
|
display: flex;
|
|
flex-direction: column;
|
|
justify-content: space-around;
|
|
z-index: 2;
|
|
}
|
|
|
|
.scene-item:nth-child(n+2) {
|
|
margin-top: 7px;
|
|
;
|
|
}
|
|
|
|
.scene-header {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
|
|
.dots {
|
|
color: #4A90E2;
|
|
font-weight: bold;
|
|
margin-right: 10px;
|
|
}
|
|
|
|
.scene-name {
|
|
font-weight: bold;
|
|
}
|
|
}
|
|
|
|
.scene-metrics {
|
|
|
|
height: 46px;
|
|
width: 384px;
|
|
margin: 0 auto;
|
|
position: relative;
|
|
display: flex;
|
|
|
|
.metric-icon {
|
|
position: absolute;
|
|
top: 0;
|
|
left: 0;
|
|
width: 100%;
|
|
height: 100%;
|
|
}
|
|
}
|
|
|
|
.scene-content {
|
|
position: absolute;
|
|
left: 0;
|
|
top: 0;
|
|
width: 100%;
|
|
height: 100%;
|
|
display: flex;
|
|
}
|
|
|
|
.metric-box {
|
|
flex: 1;
|
|
display: flex;
|
|
align-items: center;
|
|
height: 100%;
|
|
padding: 0 20px 0 70px;
|
|
box-sizing: border-box;
|
|
justify-content: space-between;
|
|
// background-color: #4A90E2;
|
|
}
|
|
|
|
.metric-value {
|
|
flex: 1; // 占据剩余空间
|
|
text-align: left; // 右对齐确保数值对齐
|
|
margin-left: 8px;
|
|
}
|
|
|
|
}
|
|
</style>
|