feat 无项目数据--
This commit is contained in:
2
src/auto-imports.d.ts
vendored
2
src/auto-imports.d.ts
vendored
@@ -184,6 +184,7 @@ declare global {
|
|||||||
const useCssVar: typeof import('@vueuse/core')['useCssVar']
|
const useCssVar: typeof import('@vueuse/core')['useCssVar']
|
||||||
const useCssVars: typeof import('vue')['useCssVars']
|
const useCssVars: typeof import('vue')['useCssVars']
|
||||||
const useCurrentElement: typeof import('@vueuse/core')['useCurrentElement']
|
const useCurrentElement: typeof import('@vueuse/core')['useCurrentElement']
|
||||||
|
const useCurrentProject: typeof import('./composables/useCurrentProject')['useCurrentProject']
|
||||||
const useCycleList: typeof import('@vueuse/core')['useCycleList']
|
const useCycleList: typeof import('@vueuse/core')['useCycleList']
|
||||||
const useDark: typeof import('@vueuse/core')['useDark']
|
const useDark: typeof import('@vueuse/core')['useDark']
|
||||||
const useDateFormat: typeof import('@vueuse/core')['useDateFormat']
|
const useDateFormat: typeof import('@vueuse/core')['useDateFormat']
|
||||||
@@ -531,6 +532,7 @@ declare module 'vue' {
|
|||||||
readonly useCssVar: UnwrapRef<typeof import('@vueuse/core')['useCssVar']>
|
readonly useCssVar: UnwrapRef<typeof import('@vueuse/core')['useCssVar']>
|
||||||
readonly useCssVars: UnwrapRef<typeof import('vue')['useCssVars']>
|
readonly useCssVars: UnwrapRef<typeof import('vue')['useCssVars']>
|
||||||
readonly useCurrentElement: UnwrapRef<typeof import('@vueuse/core')['useCurrentElement']>
|
readonly useCurrentElement: UnwrapRef<typeof import('@vueuse/core')['useCurrentElement']>
|
||||||
|
readonly useCurrentProject: UnwrapRef<typeof import('./composables/useCurrentProject')['useCurrentProject']>
|
||||||
readonly useCycleList: UnwrapRef<typeof import('@vueuse/core')['useCycleList']>
|
readonly useCycleList: UnwrapRef<typeof import('@vueuse/core')['useCycleList']>
|
||||||
readonly useDark: UnwrapRef<typeof import('@vueuse/core')['useDark']>
|
readonly useDark: UnwrapRef<typeof import('@vueuse/core')['useDark']>
|
||||||
readonly useDateFormat: UnwrapRef<typeof import('@vueuse/core')['useDateFormat']>
|
readonly useDateFormat: UnwrapRef<typeof import('@vueuse/core')['useDateFormat']>
|
||||||
|
|||||||
@@ -1,3 +1,9 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { useCurrentProject } from '@/composables/useCurrentProject'
|
||||||
|
|
||||||
|
const { hasCurrentProject, currentProject } = useCurrentProject()
|
||||||
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<view class="card">
|
<view class="card">
|
||||||
<view class="card-header">
|
<view class="card-header">
|
||||||
@@ -10,10 +16,10 @@
|
|||||||
<view class="icon-placeholder" />
|
<view class="icon-placeholder" />
|
||||||
<view class="info">
|
<view class="info">
|
||||||
<text class="segment">
|
<text class="segment">
|
||||||
K12+300 — K125+800
|
{{ hasCurrentProject ? (currentProject?.stake_range || '--') : '暂无施工段' }}
|
||||||
</text>
|
</text>
|
||||||
<text class="requirement">
|
<text class="requirement">
|
||||||
压实遍数要求:≥6遍
|
压实遍数要求:{{ hasCurrentProject ? '≥6遍' : '--' }}
|
||||||
</text>
|
</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|||||||
@@ -1,12 +1,7 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import storage from '@/utils/storage'
|
import { useCurrentProject } from '@/composables/useCurrentProject'
|
||||||
|
|
||||||
const project = ref(storage.get('current_project'))
|
const { currentProject } = useCurrentProject()
|
||||||
|
|
||||||
// 页面显示时刷新数据(从设置页返回时)
|
|
||||||
onShow(() => {
|
|
||||||
project.value = storage.get('current_project')
|
|
||||||
})
|
|
||||||
|
|
||||||
function onIconClick(name: string) {
|
function onIconClick(name: string) {
|
||||||
if (name === '通知') {
|
if (name === '通知') {
|
||||||
@@ -36,10 +31,10 @@ function onIconClick(name: string) {
|
|||||||
<image class="nav-logo" src="/static/logo.png" mode="aspectFit" @tap="onIconClick('logo')" />
|
<image class="nav-logo" src="/static/logo.png" mode="aspectFit" @tap="onIconClick('logo')" />
|
||||||
<view class="nav-info">
|
<view class="nav-info">
|
||||||
<text class="nav-title">
|
<text class="nav-title">
|
||||||
{{ project?.project_name || '--' }}
|
{{ currentProject?.project_name || '--' }}
|
||||||
</text>
|
</text>
|
||||||
<text class="nav-subtitle">
|
<text class="nav-subtitle">
|
||||||
{{ project?.stake_range || '--' }}
|
{{ currentProject?.stake_range || '--' }}
|
||||||
</text>
|
</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|||||||
@@ -1,24 +1,44 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, onMounted } from 'vue'
|
import { computed, onMounted } from 'vue'
|
||||||
|
import { useCurrentProject } from '@/composables/useCurrentProject'
|
||||||
import { useDbStore } from '@/store/modules/db'
|
import { useDbStore } from '@/store/modules/db'
|
||||||
|
|
||||||
const db = useDbStore()
|
const db = useDbStore()
|
||||||
|
const { hasCurrentProject } = useCurrentProject()
|
||||||
|
|
||||||
const now = new Date()
|
const now = new Date()
|
||||||
const dateStr = `${now.getFullYear()}年${now.getMonth() + 1}月${now.getDate()}日`
|
const dateStr = `${now.getFullYear()}年${now.getMonth() + 1}月${now.getDate()}日`
|
||||||
|
|
||||||
const totalCompactionArea = computed(() =>
|
const totalCompactionArea = computed(() => {
|
||||||
(db.work_record || []).reduce((sum, item) => sum + (item.compaction_area ?? 0), 0),
|
if (!hasCurrentProject.value)
|
||||||
)
|
return null
|
||||||
|
return (db.work_record || []).reduce((sum, item) => sum + (item.compaction_area ?? 0), 0)
|
||||||
|
})
|
||||||
|
|
||||||
const totalDuration = computed(() =>
|
const totalDuration = computed(() => {
|
||||||
(db.work_record || []).reduce((sum, item) => sum + (item.duration ?? 0), 0),
|
if (!hasCurrentProject.value)
|
||||||
)
|
return null
|
||||||
|
return (db.work_record || []).reduce((sum, item) => sum + (item.duration ?? 0), 0)
|
||||||
|
})
|
||||||
|
|
||||||
function formatNumber(value: number) {
|
const onlineCount = computed(() => {
|
||||||
|
if (!hasCurrentProject.value)
|
||||||
|
return null
|
||||||
|
return 1
|
||||||
|
})
|
||||||
|
|
||||||
|
function formatNumber(value: number | null) {
|
||||||
|
if (value == null)
|
||||||
|
return '--'
|
||||||
return Number.isInteger(value) ? String(value) : value.toFixed(1)
|
return Number.isInteger(value) ? String(value) : value.toFixed(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function formatCount(value: number | null) {
|
||||||
|
if (value == null)
|
||||||
|
return '--'
|
||||||
|
return `${value}台`
|
||||||
|
}
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
if (!db.work_record?.length)
|
if (!db.work_record?.length)
|
||||||
await db.loadAll()
|
await db.loadAll()
|
||||||
@@ -41,7 +61,7 @@ onMounted(async () => {
|
|||||||
实时作业状态(台)
|
实时作业状态(台)
|
||||||
</text>
|
</text>
|
||||||
<text class="stat-value">
|
<text class="stat-value">
|
||||||
1台
|
{{ formatCount(onlineCount) }}
|
||||||
</text>
|
</text>
|
||||||
</view>
|
</view>
|
||||||
<view class="stat-item">
|
<view class="stat-item">
|
||||||
|
|||||||
@@ -1,31 +1,28 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { onShow } from '@dcloudio/uni-app'
|
import { computed, onMounted } from 'vue'
|
||||||
import { computed, onMounted, ref } from 'vue'
|
import { useCurrentProject } from '@/composables/useCurrentProject'
|
||||||
import { calcUncompactedArea } from '@/service/project'
|
import { calcUncompactedArea } from '@/service/project'
|
||||||
import { useDbStore } from '@/store/modules/db'
|
import { useDbStore } from '@/store/modules/db'
|
||||||
import storage from '@/utils/storage'
|
|
||||||
|
|
||||||
const db = useDbStore()
|
const db = useDbStore()
|
||||||
const currentProjectId = ref<number | null>(storage.get('current_project')?.id ?? null)
|
const { currentProject: storedProject, hasCurrentProject } = useCurrentProject()
|
||||||
|
|
||||||
const currentProject = computed(() => {
|
const currentProject = computed(() => {
|
||||||
const list = db.project || []
|
if (!hasCurrentProject.value)
|
||||||
if (!list.length)
|
|
||||||
return null
|
return null
|
||||||
|
|
||||||
const stored = currentProjectId.value != null
|
const list = db.project || []
|
||||||
? list.find(item => item.id === currentProjectId.value)
|
const storedId = storedProject.value?.id
|
||||||
: null
|
if (storedId == null)
|
||||||
if (stored)
|
return null
|
||||||
return stored
|
|
||||||
|
|
||||||
return list.find(item => item.status === 2) || list[0]
|
return list.find(item => item.id === storedId) || null
|
||||||
})
|
})
|
||||||
|
|
||||||
const progressPercent = computed(() => {
|
const progressPercent = computed(() => {
|
||||||
const project = currentProject.value
|
const project = currentProject.value
|
||||||
if (!project)
|
if (!project)
|
||||||
return 0
|
return null
|
||||||
if (project.progress)
|
if (project.progress)
|
||||||
return clampPercent(project.progress)
|
return clampPercent(project.progress)
|
||||||
|
|
||||||
@@ -35,16 +32,28 @@ const progressPercent = computed(() => {
|
|||||||
return clampPercent(((project.total_compaction_area ?? 0) / total) * 100)
|
return clampPercent(((project.total_compaction_area ?? 0) / total) * 100)
|
||||||
})
|
})
|
||||||
|
|
||||||
const qualifiedRate = computed(() => currentProject.value?.qualified_rate ?? 0)
|
const qualifiedRate = computed(() => {
|
||||||
|
if (!currentProject.value)
|
||||||
|
return null
|
||||||
|
return currentProject.value.qualified_rate ?? 0
|
||||||
|
})
|
||||||
|
|
||||||
const totalArea = computed(() => currentProject.value?.total_area ?? 0)
|
const totalArea = computed(() => {
|
||||||
|
if (!currentProject.value)
|
||||||
|
return null
|
||||||
|
return currentProject.value.total_area ?? 0
|
||||||
|
})
|
||||||
|
|
||||||
const compactedArea = computed(() => currentProject.value?.total_compaction_area ?? 0)
|
const compactedArea = computed(() => {
|
||||||
|
if (!currentProject.value)
|
||||||
|
return null
|
||||||
|
return currentProject.value.total_compaction_area ?? 0
|
||||||
|
})
|
||||||
|
|
||||||
const uncompactedArea = computed(() => {
|
const uncompactedArea = computed(() => {
|
||||||
const project = currentProject.value
|
const project = currentProject.value
|
||||||
if (!project)
|
if (!project)
|
||||||
return 0
|
return null
|
||||||
if (project.uncompacted_area != null)
|
if (project.uncompacted_area != null)
|
||||||
return Math.max(0, project.uncompacted_area)
|
return Math.max(0, project.uncompacted_area)
|
||||||
return calcUncompactedArea(project.total_area, project.total_compaction_area)
|
return calcUncompactedArea(project.total_area, project.total_compaction_area)
|
||||||
@@ -54,24 +63,30 @@ function clampPercent(value: number) {
|
|||||||
return Math.min(100, Math.max(0, Number(value.toFixed(1))))
|
return Math.min(100, Math.max(0, Number(value.toFixed(1))))
|
||||||
}
|
}
|
||||||
|
|
||||||
function formatArea(value: number) {
|
function formatArea(value: number | null) {
|
||||||
|
if (value == null)
|
||||||
|
return '--'
|
||||||
const text = Number.isInteger(value) ? String(value) : String(value)
|
const text = Number.isInteger(value) ? String(value) : String(value)
|
||||||
return `${text}m²`
|
return `${text}m²`
|
||||||
}
|
}
|
||||||
|
|
||||||
function formatRate(value: number) {
|
function formatRate(value: number | null) {
|
||||||
|
if (value == null)
|
||||||
|
return '--'
|
||||||
const text = Number.isInteger(value) ? String(value) : value.toFixed(2)
|
const text = Number.isInteger(value) ? String(value) : value.toFixed(2)
|
||||||
return `${text}%`
|
return `${text}%`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function formatPercent(value: number | null) {
|
||||||
|
if (value == null)
|
||||||
|
return '--'
|
||||||
|
return `${value}%`
|
||||||
|
}
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
if (!db.project?.length)
|
if (!db.project?.length)
|
||||||
await db.loadAll()
|
await db.loadAll()
|
||||||
})
|
})
|
||||||
|
|
||||||
onShow(() => {
|
|
||||||
currentProjectId.value = storage.get('current_project')?.id ?? null
|
|
||||||
})
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -81,22 +96,19 @@ onShow(() => {
|
|||||||
项目作业进度
|
项目作业进度
|
||||||
</text>
|
</text>
|
||||||
<text class="card-sub">
|
<text class="card-sub">
|
||||||
{{ currentProject?.stake_range || currentProject?.project_name || '暂无项目' }}
|
{{ currentProject?.stake_range || currentProject?.project_name || '暂无施工段' }}
|
||||||
</text>
|
</text>
|
||||||
</view>
|
</view>
|
||||||
<view class="card-body">
|
<view class="card-body">
|
||||||
<view v-if="!currentProject" class="empty-tip">
|
<view class="progress-content">
|
||||||
暂无项目数据
|
|
||||||
</view>
|
|
||||||
<view v-else class="progress-content">
|
|
||||||
<view class="progress-circle">
|
<view class="progress-circle">
|
||||||
<wd-circle :model-value="progressPercent" :size="120">
|
<wd-circle :model-value="progressPercent ?? 0" :size="120">
|
||||||
<view class="progress-circle-text">
|
<view class="progress-circle-text">
|
||||||
<text class="progress-percent">
|
<text class="progress-percent">
|
||||||
{{ progressPercent }}%
|
{{ hasCurrentProject ? `${progressPercent}%` : '0%' }}
|
||||||
</text>
|
</text>
|
||||||
<text class="progress-label">
|
<text class="progress-label">
|
||||||
已完成
|
{{ hasCurrentProject ? '已完成' : '未开始' }}
|
||||||
</text>
|
</text>
|
||||||
</view>
|
</view>
|
||||||
</wd-circle>
|
</wd-circle>
|
||||||
@@ -111,7 +123,7 @@ onShow(() => {
|
|||||||
{{ formatRate(qualifiedRate) }}
|
{{ formatRate(qualifiedRate) }}
|
||||||
</text>
|
</text>
|
||||||
</view>
|
</view>
|
||||||
<wd-progress :percentage="clampPercent(qualifiedRate)" hide-text />
|
<wd-progress :percentage="clampPercent(qualifiedRate ?? 0)" hide-text />
|
||||||
</view>
|
</view>
|
||||||
<view class="progress-item">
|
<view class="progress-item">
|
||||||
<view class="progress-row">
|
<view class="progress-row">
|
||||||
@@ -119,10 +131,10 @@ onShow(() => {
|
|||||||
完成进度
|
完成进度
|
||||||
</text>
|
</text>
|
||||||
<text class="progress-value">
|
<text class="progress-value">
|
||||||
{{ progressPercent }}%
|
{{ formatPercent(progressPercent) }}
|
||||||
</text>
|
</text>
|
||||||
</view>
|
</view>
|
||||||
<wd-progress :percentage="progressPercent" hide-text />
|
<wd-progress :percentage="progressPercent ?? 0" hide-text />
|
||||||
</view>
|
</view>
|
||||||
<view class="progress-item progress-item-inline">
|
<view class="progress-item progress-item-inline">
|
||||||
<text class="progress-name">
|
<text class="progress-name">
|
||||||
@@ -187,13 +199,6 @@ onShow(() => {
|
|||||||
padding: 12px 16px;
|
padding: 12px 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.empty-tip {
|
|
||||||
font-size: 14px;
|
|
||||||
color: #999999;
|
|
||||||
text-align: center;
|
|
||||||
padding: 16px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.progress-content {
|
.progress-content {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|||||||
@@ -1,12 +1,18 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { Project } from '@/service/project'
|
import type { Project } from '@/service/project'
|
||||||
import { onMounted } from 'vue'
|
import { computed, onMounted } from 'vue'
|
||||||
|
import { useCurrentProject } from '@/composables/useCurrentProject'
|
||||||
import { useDbStore } from '@/store/modules/db'
|
import { useDbStore } from '@/store/modules/db'
|
||||||
|
|
||||||
const db = useDbStore()
|
const db = useDbStore()
|
||||||
|
const { hasCurrentProject } = useCurrentProject()
|
||||||
|
|
||||||
/** 首页只展示最近几条 */
|
/** 首页只展示最近几条 */
|
||||||
const list = computed(() => (db.project || []).slice(0, 2))
|
const list = computed(() => {
|
||||||
|
if (!hasCurrentProject.value)
|
||||||
|
return []
|
||||||
|
return (db.project || []).slice(0, 2)
|
||||||
|
})
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
if (!db.project?.length)
|
if (!db.project?.length)
|
||||||
@@ -39,7 +45,10 @@ function goToDetail(item: Project) {
|
|||||||
</wd-button>
|
</wd-button>
|
||||||
</view>
|
</view>
|
||||||
<view class="card-body">
|
<view class="card-body">
|
||||||
<view v-if="!list.length" class="empty-tip">
|
<view v-if="!hasCurrentProject" class="empty-tip">
|
||||||
|
--
|
||||||
|
</view>
|
||||||
|
<view v-else-if="!list.length" class="empty-tip">
|
||||||
暂无项目
|
暂无项目
|
||||||
</view>
|
</view>
|
||||||
<home-list
|
<home-list
|
||||||
@@ -79,7 +88,7 @@ function goToDetail(item: Project) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.empty-tip {
|
.empty-tip {
|
||||||
font-size: 14px;
|
font-size: 18px;
|
||||||
color: #999999;
|
color: #999999;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
padding: 16px 0;
|
padding: 16px 0;
|
||||||
|
|||||||
@@ -1,4 +1,8 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import { useCurrentProject } from '@/composables/useCurrentProject'
|
||||||
|
|
||||||
|
const { hasCurrentProject } = useCurrentProject()
|
||||||
|
|
||||||
function goToWork() {
|
function goToWork() {
|
||||||
uni.switchTab({
|
uni.switchTab({
|
||||||
url: '/pages/work/index',
|
url: '/pages/work/index',
|
||||||
@@ -14,6 +18,10 @@ function goToWork() {
|
|||||||
</text>
|
</text>
|
||||||
</view>
|
</view>
|
||||||
<view class="card-body">
|
<view class="card-body">
|
||||||
|
<view v-if="!hasCurrentProject" class="empty-tip">
|
||||||
|
--
|
||||||
|
</view>
|
||||||
|
<template v-else>
|
||||||
<view class="status-info">
|
<view class="status-info">
|
||||||
<view class="avatar" />
|
<view class="avatar" />
|
||||||
<view class="info">
|
<view class="info">
|
||||||
@@ -67,6 +75,7 @@ function goToWork() {
|
|||||||
进入作业监控
|
进入作业监控
|
||||||
</wd-button>
|
</wd-button>
|
||||||
</view>
|
</view>
|
||||||
|
</template>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
@@ -97,6 +106,13 @@ function goToWork() {
|
|||||||
padding: 12px 16px;
|
padding: 12px 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.empty-tip {
|
||||||
|
font-size: 18px;
|
||||||
|
color: #999999;
|
||||||
|
text-align: center;
|
||||||
|
padding: 24px 0;
|
||||||
|
}
|
||||||
|
|
||||||
.status-info {
|
.status-info {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|||||||
@@ -1,12 +1,21 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { WarningRecord } from '@/service/warningRecord'
|
import type { WarningRecord } from '@/service/warningRecord'
|
||||||
import { onMounted } from 'vue'
|
import { computed, onMounted } from 'vue'
|
||||||
|
import { useCurrentProject } from '@/composables/useCurrentProject'
|
||||||
import { useDbStore } from '@/store/modules/db'
|
import { useDbStore } from '@/store/modules/db'
|
||||||
|
|
||||||
const db = useDbStore()
|
const db = useDbStore()
|
||||||
|
const { hasCurrentProject, currentProject } = useCurrentProject()
|
||||||
|
|
||||||
/** 首页只展示最近几条 */
|
/** 首页只展示当前项目最近几条 */
|
||||||
const list = computed(() => (db.warning_record || []).slice(0, 3))
|
const list = computed(() => {
|
||||||
|
if (!hasCurrentProject.value)
|
||||||
|
return []
|
||||||
|
const projectId = currentProject.value?.id
|
||||||
|
return (db.warning_record || [])
|
||||||
|
.filter(item => projectId == null || item.project_id === projectId)
|
||||||
|
.slice(0, 3)
|
||||||
|
})
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
if (!db.warning_record?.length)
|
if (!db.warning_record?.length)
|
||||||
@@ -39,7 +48,10 @@ function goToDetail(item: WarningRecord) {
|
|||||||
</wd-button>
|
</wd-button>
|
||||||
</view>
|
</view>
|
||||||
<view class="card-body">
|
<view class="card-body">
|
||||||
<view v-if="!list.length" class="empty-tip">
|
<view v-if="!hasCurrentProject" class="empty-tip">
|
||||||
|
--
|
||||||
|
</view>
|
||||||
|
<view v-else-if="!list.length" class="empty-tip">
|
||||||
暂无异常警告
|
暂无异常警告
|
||||||
</view>
|
</view>
|
||||||
<home-warning_list
|
<home-warning_list
|
||||||
@@ -79,7 +91,7 @@ function goToDetail(item: WarningRecord) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.empty-tip {
|
.empty-tip {
|
||||||
font-size: 14px;
|
font-size: 18px;
|
||||||
color: #999999;
|
color: #999999;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
padding: 16px 0;
|
padding: 16px 0;
|
||||||
|
|||||||
@@ -1,23 +1,40 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed } from 'vue'
|
import { computed } from 'vue'
|
||||||
|
import { useCurrentProject } from '@/composables/useCurrentProject'
|
||||||
|
|
||||||
|
const { hasCurrentProject } = useCurrentProject()
|
||||||
|
|
||||||
// 压实度 (假数据,后续替换)
|
// 压实度 (假数据,后续替换)
|
||||||
const compactionValue = 25
|
const compactionValue = computed(() => (hasCurrentProject.value ? 25 : 0))
|
||||||
|
const compactionText = computed(() => (hasCurrentProject.value ? `${compactionValue.value}%` : '--'))
|
||||||
|
|
||||||
// 车速 (假数据,范围 0-12,中间值 6)
|
// 车速 (假数据,范围 0-12,中间值 6)
|
||||||
const speedValue = 4.2
|
const speedValue = computed(() => (hasCurrentProject.value ? 4.2 : 0))
|
||||||
|
const speedText = computed(() => (hasCurrentProject.value ? `${speedValue.value}KM/H` : '--'))
|
||||||
const speedMax = 12
|
const speedMax = 12
|
||||||
|
|
||||||
// 指针旋转角度:0km/h → 225°(左下),12km/h → -45°(右下),中间90°(正上)
|
// 指针旋转角度:0km/h → 225°(左下),12km/h → -45°(右下),中间90°(正上)
|
||||||
const needleRotation = computed(() => 225 - (speedValue / speedMax) * 270)
|
const needleRotation = computed(() => 225 - (speedValue.value / speedMax) * 270)
|
||||||
|
|
||||||
// 今日作业概览数据 (假数据)
|
const frequencyText = computed(() => (hasCurrentProject.value ? '8939HZ' : '--'))
|
||||||
const overviewData = [
|
|
||||||
|
// 今日作业概览数据
|
||||||
|
const overviewData = computed(() => {
|
||||||
|
if (!hasCurrentProject.value) {
|
||||||
|
return [
|
||||||
|
{ label: '作业时长', value: '--' },
|
||||||
|
{ label: '压实面积', value: '--' },
|
||||||
|
{ label: '碾压遍数', value: '--' },
|
||||||
|
{ label: '异常次数', value: '--' },
|
||||||
|
]
|
||||||
|
}
|
||||||
|
return [
|
||||||
{ label: '作业时长', value: '8h' },
|
{ label: '作业时长', value: '8h' },
|
||||||
{ label: '压实面积', value: '28.5m²' },
|
{ label: '压实面积', value: '28.5m²' },
|
||||||
{ label: '碾压遍数', value: '10遍' },
|
{ label: '碾压遍数', value: '10遍' },
|
||||||
{ label: '异常次数', value: '0' },
|
{ label: '异常次数', value: '0' },
|
||||||
]
|
]
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -43,7 +60,7 @@ const overviewData = [
|
|||||||
</view>
|
</view>
|
||||||
<!-- 圆环进度(使用 wotui 的 wd-circle 组件) -->
|
<!-- 圆环进度(使用 wotui 的 wd-circle 组件) -->
|
||||||
<view class="ring-wrap">
|
<view class="ring-wrap">
|
||||||
<wd-circle v-model="compactionValue" :text="`${compactionValue}%`" />
|
<wd-circle :model-value="compactionValue" :text="compactionText" />
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
@@ -58,7 +75,7 @@ const overviewData = [
|
|||||||
</text>
|
</text>
|
||||||
</view>
|
</view>
|
||||||
<text class="gauge-value">
|
<text class="gauge-value">
|
||||||
{{ speedValue }}KM/H
|
{{ speedText }}
|
||||||
</text>
|
</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
@@ -71,7 +88,7 @@ const overviewData = [
|
|||||||
振动频率
|
振动频率
|
||||||
</text>
|
</text>
|
||||||
<text class="freq-value">
|
<text class="freq-value">
|
||||||
8939HZ
|
{{ frequencyText }}
|
||||||
</text>
|
</text>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
@@ -80,7 +97,7 @@ const overviewData = [
|
|||||||
振动频率
|
振动频率
|
||||||
</text>
|
</text>
|
||||||
<text class="freq-value">
|
<text class="freq-value">
|
||||||
8939HZ
|
{{ frequencyText }}
|
||||||
</text>
|
</text>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
|
|||||||
@@ -1,15 +1,29 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
// 设备状态 + 作业控制组件
|
import { computed } from 'vue'
|
||||||
|
import { useCurrentProject } from '@/composables/useCurrentProject'
|
||||||
|
|
||||||
const deviceInfo = {
|
const { hasCurrentProject } = useCurrentProject()
|
||||||
|
|
||||||
|
const deviceInfo = computed(() => {
|
||||||
|
if (!hasCurrentProject.value) {
|
||||||
|
return {
|
||||||
|
编号: '--',
|
||||||
|
status: '--',
|
||||||
|
connected: '--',
|
||||||
|
workStatus: '--',
|
||||||
|
signalStatus: '--',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {
|
||||||
编号: '徐工XS65H #01',
|
编号: '徐工XS65H #01',
|
||||||
status: '作业中',
|
status: '作业中',
|
||||||
connected: '已连接',
|
connected: '已连接',
|
||||||
workStatus: '正常运行',
|
workStatus: '正常运行',
|
||||||
signalStatus: '信号良好',
|
signalStatus: '信号良好',
|
||||||
}
|
}
|
||||||
|
})
|
||||||
|
|
||||||
const workStatus = '作业进行中'
|
const workStatus = computed(() => (hasCurrentProject.value ? '作业进行中' : '--'))
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -35,13 +49,13 @@ const workStatus = '作业进行中'
|
|||||||
<!-- 左列:作业状态 -->
|
<!-- 左列:作业状态 -->
|
||||||
<view class="status-col">
|
<view class="status-col">
|
||||||
<view class="tag">
|
<view class="tag">
|
||||||
<view class="dot dot--green" />
|
<view class="dot" :class="hasCurrentProject ? 'dot--green' : 'dot--gray'" />
|
||||||
<text>{{ deviceInfo.status }}</text>
|
<text>{{ deviceInfo.status }}</text>
|
||||||
</view>
|
</view>
|
||||||
<text class="info-label">
|
<text class="info-label">
|
||||||
压实作业
|
压实作业
|
||||||
</text>
|
</text>
|
||||||
<text class="info-value info-value--green">
|
<text class="info-value" :class="{ 'info-value--green': hasCurrentProject }">
|
||||||
{{ deviceInfo.workStatus }}
|
{{ deviceInfo.workStatus }}
|
||||||
</text>
|
</text>
|
||||||
</view>
|
</view>
|
||||||
@@ -49,13 +63,13 @@ const workStatus = '作业进行中'
|
|||||||
<!-- 右列:连接状态 -->
|
<!-- 右列:连接状态 -->
|
||||||
<view class="status-col">
|
<view class="status-col">
|
||||||
<view class="tag">
|
<view class="tag">
|
||||||
<view class="dot dot--green" />
|
<view class="dot" :class="hasCurrentProject ? 'dot--green' : 'dot--gray'" />
|
||||||
<text>{{ deviceInfo.connected }}</text>
|
<text>{{ deviceInfo.connected }}</text>
|
||||||
</view>
|
</view>
|
||||||
<text class="info-label">
|
<text class="info-label">
|
||||||
设备连接
|
设备连接
|
||||||
</text>
|
</text>
|
||||||
<text class="info-value info-value--green">
|
<text class="info-value" :class="{ 'info-value--green': hasCurrentProject }">
|
||||||
{{ deviceInfo.signalStatus }}
|
{{ deviceInfo.signalStatus }}
|
||||||
</text>
|
</text>
|
||||||
</view>
|
</view>
|
||||||
@@ -85,14 +99,14 @@ const workStatus = '作业进行中'
|
|||||||
<!-- 第二行:当前状态(对齐左侧 label 行) -->
|
<!-- 第二行:当前状态(对齐左侧 label 行) -->
|
||||||
<view class="control-row">
|
<view class="control-row">
|
||||||
<view class="tag">
|
<view class="tag">
|
||||||
<view class="dot dot--green" />
|
<view class="dot" :class="hasCurrentProject ? 'dot--green' : 'dot--gray'" />
|
||||||
<text>当前:{{ workStatus }}</text>
|
<text>当前:{{ workStatus }}</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 第三行:暂停按钮(对齐左侧 value 行) -->
|
<!-- 第三行:暂停按钮(对齐左侧 value 行) -->
|
||||||
<view class="control-row">
|
<view class="control-row">
|
||||||
<wd-button type="warning" class="pause-btn" round>
|
<wd-button type="warning" class="pause-btn" round :disabled="!hasCurrentProject">
|
||||||
暂停作业
|
暂停作业
|
||||||
</wd-button>
|
</wd-button>
|
||||||
</view>
|
</view>
|
||||||
@@ -188,6 +202,10 @@ const workStatus = '作业进行中'
|
|||||||
background: #22c55e;
|
background: #22c55e;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.dot--gray {
|
||||||
|
background: #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
.info-label {
|
.info-label {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
color: #333333;
|
color: #333333;
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
// RTK 轨迹画布 - 占位组件,后续实现轨迹动画
|
import { useCurrentProject } from '@/composables/useCurrentProject'
|
||||||
|
|
||||||
|
const { hasCurrentProject } = useCurrentProject()
|
||||||
|
|
||||||
function goToRtk() {
|
function goToRtk() {
|
||||||
uni.navigateTo({
|
uni.navigateTo({
|
||||||
@@ -12,9 +14,9 @@ function goToRtk() {
|
|||||||
<view class="rtk-canvas" @click="goToRtk">
|
<view class="rtk-canvas" @click="goToRtk">
|
||||||
<view class="canvas-placeholder">
|
<view class="canvas-placeholder">
|
||||||
<text class="placeholder-text">
|
<text class="placeholder-text">
|
||||||
轨迹动画区域
|
{{ hasCurrentProject ? '轨迹动画区域' : '--' }}
|
||||||
</text>
|
</text>
|
||||||
<text class="placeholder-hint">
|
<text v-if="hasCurrentProject" class="placeholder-hint">
|
||||||
(Canvas 绘制行驶轨迹 + 压实热力图)
|
(Canvas 绘制行驶轨迹 + 压实热力图)
|
||||||
</text>
|
</text>
|
||||||
</view>
|
</view>
|
||||||
|
|||||||
@@ -1,5 +1,11 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
// RTK 轨迹底部信息组件(图例 + 位置信息)
|
import { computed } from 'vue'
|
||||||
|
import { useCurrentProject } from '@/composables/useCurrentProject'
|
||||||
|
|
||||||
|
const { hasCurrentProject } = useCurrentProject()
|
||||||
|
|
||||||
|
const headingText = computed(() => (hasCurrentProject.value ? '航向:NE45°' : '航向:--'))
|
||||||
|
const locationText = computed(() => (hasCurrentProject.value ? '114.39°E, 39.9087°N' : '--'))
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -26,10 +32,10 @@
|
|||||||
</view>
|
</view>
|
||||||
<view class="location-info">
|
<view class="location-info">
|
||||||
<text class="location-text">
|
<text class="location-text">
|
||||||
航向:NE45°
|
{{ headingText }}
|
||||||
</text>
|
</text>
|
||||||
<text class="location-text">
|
<text class="location-text">
|
||||||
114.39°E, 39.9087°N
|
{{ locationText }}
|
||||||
</text>
|
</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
// RTK 轨迹实时监测 - 状态头部组件
|
import { computed } from 'vue'
|
||||||
|
import { useCurrentProject } from '@/composables/useCurrentProject'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
deviceName?: string
|
deviceName?: string
|
||||||
@@ -9,7 +10,7 @@ interface Props {
|
|||||||
rtkFixed?: boolean
|
rtkFixed?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
withDefaults(defineProps<Props>(), {
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
deviceName: '徐工XS65H #01',
|
deviceName: '徐工XS65H #01',
|
||||||
speed: 4.2,
|
speed: 4.2,
|
||||||
frequency: 28.5,
|
frequency: 28.5,
|
||||||
@@ -17,6 +18,13 @@ withDefaults(defineProps<Props>(), {
|
|||||||
rtkFixed: true,
|
rtkFixed: true,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const { hasCurrentProject } = useCurrentProject()
|
||||||
|
|
||||||
|
const displayDeviceName = computed(() => (hasCurrentProject.value ? props.deviceName : '--'))
|
||||||
|
const displaySpeed = computed(() => (hasCurrentProject.value ? `${props.speed} km/h` : '--'))
|
||||||
|
const displayStatusText = computed(() => (hasCurrentProject.value ? '实时监测中' : '--'))
|
||||||
|
const displayRtkText = computed(() => (hasCurrentProject.value ? 'RTK固定' : '--'))
|
||||||
|
|
||||||
function goToHeatmap() {
|
function goToHeatmap() {
|
||||||
uni.navigateTo({
|
uni.navigateTo({
|
||||||
url: '/pages/heatmap/index',
|
url: '/pages/heatmap/index',
|
||||||
@@ -38,12 +46,12 @@ function goToHeatmap() {
|
|||||||
|
|
||||||
<!-- 设备状态 -->
|
<!-- 设备状态 -->
|
||||||
<view class="device-status">
|
<view class="device-status">
|
||||||
<view class="status-dot" />
|
<view class="status-dot" :class="{ 'status-dot--active': hasCurrentProject }" />
|
||||||
<text class="device-name">
|
<text class="device-name">
|
||||||
{{ deviceName }}
|
{{ displayDeviceName }}
|
||||||
</text>
|
</text>
|
||||||
<text class="status-text">
|
<text class="status-text">
|
||||||
实时监测中
|
{{ displayStatusText }}
|
||||||
</text>
|
</text>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
@@ -54,29 +62,13 @@ function goToHeatmap() {
|
|||||||
车速
|
车速
|
||||||
</text>
|
</text>
|
||||||
<text class="data-value">
|
<text class="data-value">
|
||||||
{{ speed }} km/h
|
{{ displaySpeed }}
|
||||||
</text>
|
</text>
|
||||||
</view>
|
</view>
|
||||||
<!-- <view class="data-item">
|
|
||||||
<text class="data-label">
|
|
||||||
振动频率
|
|
||||||
</text>
|
|
||||||
<text class="data-value">
|
|
||||||
{{ frequency }} HZ
|
|
||||||
</text>
|
|
||||||
</view> -->
|
|
||||||
<!-- <view class="data-item">
|
|
||||||
<text class="data-label">
|
|
||||||
振幅
|
|
||||||
</text>
|
|
||||||
<text class="data-value">
|
|
||||||
{{ amplitude }} mm
|
|
||||||
</text>
|
|
||||||
</view> -->
|
|
||||||
<view class="rtk-status">
|
<view class="rtk-status">
|
||||||
<view class="rtk-dot" :class="{ 'rtk-dot--active': rtkFixed }" />
|
<view class="rtk-dot" :class="{ 'rtk-dot--active': hasCurrentProject && rtkFixed }" />
|
||||||
<text class="rtk-text">
|
<text class="rtk-text">
|
||||||
RTK固定
|
{{ displayRtkText }}
|
||||||
</text>
|
</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
@@ -101,11 +93,6 @@ function goToHeatmap() {
|
|||||||
color: #333;
|
color: #333;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* .subtitle {
|
|
||||||
font-size: 20px;
|
|
||||||
color: #333;
|
|
||||||
} */
|
|
||||||
|
|
||||||
.device-status {
|
.device-status {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@@ -117,6 +104,10 @@ function goToHeatmap() {
|
|||||||
width: 8px;
|
width: 8px;
|
||||||
height: 8px;
|
height: 8px;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
|
background: #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-dot--active {
|
||||||
background: #22c55e;
|
background: #22c55e;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
28
src/composables/useCurrentProject.ts
Normal file
28
src/composables/useCurrentProject.ts
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
import { onShow } from '@dcloudio/uni-app'
|
||||||
|
import { computed, ref } from 'vue'
|
||||||
|
import storage from '@/utils/storage'
|
||||||
|
|
||||||
|
const PROJECT_KEY = 'current_project'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 读取本地当前项目;无项目时首页/压实作业数据统一展示为 `--`
|
||||||
|
*/
|
||||||
|
export function useCurrentProject() {
|
||||||
|
const currentProject = ref(storage.get(PROJECT_KEY))
|
||||||
|
|
||||||
|
const hasCurrentProject = computed(() => currentProject.value?.id != null)
|
||||||
|
|
||||||
|
function refreshCurrentProject() {
|
||||||
|
currentProject.value = storage.get(PROJECT_KEY)
|
||||||
|
}
|
||||||
|
|
||||||
|
onShow(() => {
|
||||||
|
refreshCurrentProject()
|
||||||
|
})
|
||||||
|
|
||||||
|
return {
|
||||||
|
currentProject,
|
||||||
|
hasCurrentProject,
|
||||||
|
refreshCurrentProject,
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user