367 lines
7.4 KiB
Vue
367 lines
7.4 KiB
Vue
<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>
|