Files
Road_roller/src/components/work/dashboard.vue
2026-09-17 16:50:24 +08:00

367 lines
7.4 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<script setup lang="ts">
import { computed } from 'vue'
import { useCurrentProject } from '@/composables/useCurrentProject'
import { useRtkLive } from '@/composables/useRtkLive'
const { hasCurrentProject } = useCurrentProject()
const {
compactionValue: liveCompaction,
speed,
compactionText: liveCompactionText,
tempText: liveTempText,
passCountText: livePassCountText,
} = useRtkLive()
const compactionValue = computed(() => {
if (!hasCurrentProject.value || liveCompaction.value == null)
return 0
return Math.round(liveCompaction.value)
})
const compactionText = computed(() => (hasCurrentProject.value ? liveCompactionText.value : '--'))
const speedValue = computed(() => {
if (!hasCurrentProject.value || speed.value == null)
return 0
return speed.value
})
const speedText = computed(() => {
if (!hasCurrentProject.value || speed.value == null)
return '--'
return `${speed.value}KM/H`
})
const speedMax = 12
/** 数学角(0=东,逆时针)→ CSS 旋转(0=上,顺时针) */
const needleRotation = computed(() => {
const mathDeg = 225 - (speedValue.value / speedMax) * 270
return 90 - mathDeg
})
const tempText = computed(() => (hasCurrentProject.value ? liveTempText.value : '--'))
const passCountText = computed(() => (hasCurrentProject.value ? livePassCountText.value : '--'))
const overviewData = computed(() => {
if (!hasCurrentProject.value) {
return [
{ label: '作业时长', value: '--' },
{ label: '压实面积', value: '--' },
{ label: '碾压遍数', value: '--' },
{ label: '异常次数', value: '--' },
]
}
return [
{ label: '作业时长', value: '8h' },
{ label: '压实面积', value: '28.5m²' },
{ label: '碾压遍数', value: '10遍' },
{ label: '异常次数', value: '0' },
]
})
</script>
<template>
<view class="card">
<!-- 标题 -->
<text class="card-title">
实时数据仪表盘
</text>
<!-- 仪表盘区域 - 左右flex布局 -->
<view class="gauge-section">
<!-- 左侧 -->
<view class="gauge-left">
<!-- 压实度 -->
<view class="gauge-item">
<view class="gauge-header">
<text class="gauge-icon">
🚜
</text>
<text class="gauge-label">
压实度
</text>
</view>
<!-- 圆环进度(使用 wotui 的 wd-circle 组件) -->
<view class="ring-wrap">
<wd-circle :model-value="compactionValue" :text="compactionText" :size="80" />
</view>
</view>
<!-- 行驶速度 -->
<view class="gauge-item">
<view class="gauge-header">
<text class="gauge-icon">
🚜
</text>
<text class="gauge-label">
行驶速度
</text>
</view>
<text class="gauge-value">
{{ speedText }}
</text>
</view>
</view>
<!-- 右侧 -->
<view class="gauge-right">
<!-- 钢轮温度 -->
<view class="freq-item">
<text class="freq-label">
钢轮温度
</text>
<text class="freq-value">
{{ tempText }}
</text>
</view>
<view class="freq-item">
<text class="freq-label">
压实遍数
</text>
<text class="freq-value">
{{ passCountText }}
</text>
</view>
<!-- 车速仪表:App 端不支持内联 SVG,改用 view + CSS -->
<view class="speed-gauge">
<view class="gauge-clip gauge-clip--left">
<view class="gauge-ring gauge-ring--blue" />
</view>
<view class="gauge-clip gauge-clip--right">
<view class="gauge-ring gauge-ring--orange" />
</view>
<view class="gauge-mask" />
<view class="needle-wrap" :style="{ transform: `rotate(${needleRotation}deg)` }">
<view class="needle" />
</view>
<view class="needle-hub" />
</view>
</view>
</view>
<!-- 今日作业概览 -->
<view class="section-title">
<text>
今日作业概览
</text>
</view>
<view class="overview-section">
<view v-for="item in overviewData" :key="item.label" class="overview-item">
<text class="overview-label">
{{ item.label }}
</text>
<text class="overview-value">
{{ item.value }}
</text>
</view>
</view>
</view>
</template>
<style scoped>
.card {
background: #fff;
border-radius: 12px;
padding: 16px;
}
.card-title {
font-size: 20px;
font-weight: 600;
color: #333;
margin-bottom: 16px;
}
/* 仪表盘区域 - 左右分布 */
.gauge-section {
display: flex;
gap: 12px;
}
.gauge-left,
.gauge-right {
flex: 1;
display: flex;
flex-direction: column;
margin-top: 30px;
gap: 30px;
}
/* 左侧仪表项 */
.gauge-item {
margin-bottom: 16px;
gap:100px
}
.gauge-header {
display: flex;
align-items: center;
gap: 6px;
margin-bottom: 8px;
}
.gauge-icon {
font-size: 16px;
}
.gauge-label {
font-size: 16px;
color: #666;
}
.gauge-value {
font-size: 18px;
font-weight: 600;
color: #333;
}
/* ===== 压实度圆环 ===== */
.ring-wrap {
margin-top: 20px;
position: relative;
width: 100px;
height: 100px;
}
/* ===== 右侧频率项 ===== */
.freq-item {
margin-bottom: 16px;
}
.freq-label {
font-size: 18px;
color: #666;
display: block;
margin-bottom: 4px;
}
.freq-value {
font-size: 18px;
font-weight: 600;
color: #333;
}
/* ===== 车速仪表(view+CSS,兼容 Android App) ===== */
.speed-gauge {
position: relative;
width: 110px;
height: 100px;
margin-top: 4px;
}
.gauge-clip {
position: absolute;
top: 0;
width: 50px;
height: 100px;
overflow: hidden;
}
.gauge-clip--left {
left: 5px;
}
.gauge-clip--right {
left: 55px;
}
.gauge-ring {
width: 90px;
height: 90px;
margin-top: 5px;
border-radius: 50%;
border-style: solid;
border-width: 10px;
box-sizing: border-box;
}
/* 左半:蓝弧约 225°→90° */
.gauge-ring--blue {
margin-left: 5px;
border-color: #3b82f6 transparent transparent #3b82f6;
transform: rotate(-45deg);
}
/* 右半:橙弧约 90°→-45° */
.gauge-ring--orange {
margin-left: -45px;
border-color: #f97316 #f97316 transparent transparent;
transform: rotate(45deg);
}
.gauge-mask {
position: absolute;
left: 5px;
bottom: 0;
width: 100px;
height: 42px;
background: #fff;
}
.needle-wrap {
position: absolute;
left: 52px;
top: 12px;
width: 6px;
height: 38px;
transform-origin: 50% 100%;
}
.needle {
width: 4px;
height: 36px;
margin: 0 auto;
border-radius: 2px;
background: #f97316;
}
.needle-hub {
position: absolute;
left: 50px;
top: 45px;
width: 10px;
height: 10px;
border-radius: 50%;
background: #f97316;
}
/* ===== 分割线 ===== */
.divider {
height: 1px;
background: #eee;
margin: 16px 0;
}
/* ===== 今日作业概览 ===== */
.section-title {
font-size: 20px;
font-weight: 600;
color: #333;
margin: 25px 0px;
}
.overview-section {
display: flex;
justify-content: space-between;
}
.overview-item {
display: flex;
flex-direction: column;
align-items: center;
gap: 8px;
}
.overview-label {
font-size: 18px;
color: #999;
}
.overview-value {
font-size: 18px;
font-weight: 600;
color: #333;
}
</style>