| | |
| | | <template> |
| | | <div class="screen-page"> |
| | | <el-row :gutter="10" class="kpi-row"> |
| | | <el-col :lg="3" :sm="8" :xs="12"> |
| | | <kpi-card label="在线分拣员" :value="data.kpis.sorterOnline" |
| | | :hint="`${data.kpis.sorterOnline} / ${data.kpis.sorterTotal}`" |
| | | :demo="isDemoField('kpis.sorterOnline')" /> |
| | | </el-col> |
| | | <el-col :lg="3" :sm="8" :xs="12"> |
| | | <kpi-card label="在线车辆" :value="data.kpis.vehicleOnline" |
| | | :hint="`${data.kpis.vehicleOnline} / ${data.kpis.vehicleTotal}`" |
| | | :demo="isDemoField('kpis.vehicleOnline')" /> |
| | | </el-col> |
| | | <el-col :lg="3" :sm="8" :xs="12"> |
| | | <kpi-card label="在线分拣点" :value="data.kpis.siteOnline" |
| | | :hint="`${data.kpis.siteOnline} / ${data.kpis.siteTotal},按站点启用`" |
| | | :demo="isDemoField('kpis.siteOnline')" /> |
| | | </el-col> |
| | | <el-col :lg="3" :sm="8" :xs="12"> |
| | | <kpi-card label="今日回收订单" :value="data.kpis.todayOrders" :demo="isDemoField('kpis.todayOrders')" /> |
| | | </el-col> |
| | | <el-col :lg="4" :sm="8" :xs="12"> |
| | | <kpi-card label="今日预约 / 待处理" :value="data.kpis.todayAppointments" |
| | | :hint="`待处理 ${data.kpis.pendingAppointments}`" |
| | | :demo="isDemoField('kpis.todayAppointments')" /> |
| | | </el-col> |
| | | <el-col :lg="4" :sm="8" :xs="12"> |
| | | <kpi-card label="异常告警" :value="data.kpis.alerts" alert |
| | | :hint="`健康异常 ${data.kpis.healthAlerts},不展示隐私体征`" |
| | | :demo="isDemoField('kpis.alerts')" /> |
| | | </el-col> |
| | | <el-col :lg="4" :sm="8" :xs="12"> |
| | | <kpi-card label="车辆安全事件" :value="safetyCount" hint="超速 / 急刹等,来自车辆日汇总" |
| | | :demo="isDemoSection('vehicles')" /> |
| | | </el-col> |
| | | </el-row> |
| | | <div class="kpi-grid" style="--kpi-cols: 7"> |
| | | <kpi-card |
| | | label="在线分拣员" |
| | | :value="data.kpis.sorterOnline" |
| | | :hint="`${data.kpis.sorterOnline} / ${data.kpis.sorterTotal}`" |
| | | /> |
| | | <kpi-card |
| | | label="在线车辆" |
| | | :value="data.kpis.vehicleOnline" |
| | | :hint="`${data.kpis.vehicleOnline} / ${data.kpis.vehicleTotal}`" |
| | | /> |
| | | <kpi-card |
| | | label="在线分拣点" |
| | | :value="data.kpis.siteOnline" |
| | | :hint="`${data.kpis.siteOnline} / ${data.kpis.siteTotal},按站点启用`" |
| | | /> |
| | | <kpi-card label="今日回收订单" :value="data.kpis.todayOrders" /> |
| | | <kpi-card |
| | | label="今日预约 / 待处理" |
| | | :value="data.kpis.todayAppointments" |
| | | :hint="`待处理 ${data.kpis.pendingAppointments}`" |
| | | /> |
| | | <kpi-card |
| | | label="异常告警" |
| | | :value="data.kpis.alerts" |
| | | alert |
| | | :hint="`健康异常 ${data.kpis.healthAlerts},不展示隐私体征`" |
| | | /> |
| | | <kpi-card label="车辆安全事件" :value="safetyCount" hint="超速 / 急刹等,来自车辆日汇总" /> |
| | | </div> |
| | | |
| | | <el-row :gutter="10" class="mid-row"> |
| | | <el-col :lg="14" :xs="24"> |
| | |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <el-row :gutter="10"> |
| | | <el-row :gutter="10" class="bottom-row"> |
| | | <el-col :lg="8" :xs="24"> |
| | | <panel-card title="分拣员状态" sub="来自分拣员日表,只汇总状态,不展示体征明细" :demo="isDemoSection('sorterStatus')"> |
| | | <div class="status-list"> |
| | |
| | | </el-col> |
| | | <el-col :lg="8" :xs="24"> |
| | | <panel-card title="车辆运行" sub="公司领导看运力与安全,不进校领导首页" :demo="isDemoSection('vehicles')"> |
| | | <div class="table table--vehicle"> |
| | | <div class="table__head"> |
| | | <span>车牌</span> |
| | | <span>里程km</span> |
| | | <span>怠速分</span> |
| | | <span>超速</span> |
| | | <span>状态</span> |
| | | </div> |
| | | <screen-auto-scroll class="table table--vehicle" :watch-key="vehicleWatchKey"> |
| | | <template #head> |
| | | <div class="table__head"> |
| | | <span>车牌</span> |
| | | <span>里程km</span> |
| | | <span>怠速分</span> |
| | | <span>超速</span> |
| | | <span>状态</span> |
| | | </div> |
| | | </template> |
| | | <div v-for="item in data.vehicles" :key="item.no" class="table__row"> |
| | | <span>{{ item.no }}</span> |
| | | <span>{{ item.km }}</span> |
| | |
| | | <span>{{ item.overspeed }}</span> |
| | | <span :class="item.status === '在线' ? 'is-on' : 'is-off'">{{ item.status }}</span> |
| | | </div> |
| | | </div> |
| | | </screen-auto-scroll> |
| | | </panel-card> |
| | | </el-col> |
| | | <el-col :lg="8" :xs="24"> |
| | | <panel-card title="分拣点吞吐" sub="运营维度才下钻到点位" :demo="isDemoSection('sites')"> |
| | | <div class="table table--site"> |
| | | <div class="table__head"> |
| | | <span>收集点</span> |
| | | <span>今日kg</span> |
| | | <span>在线</span> |
| | | </div> |
| | | <screen-auto-scroll class="table table--site" :watch-key="siteWatchKey"> |
| | | <template #head> |
| | | <div class="table__head"> |
| | | <span>收集点</span> |
| | | <span>今日kg</span> |
| | | <span>在线</span> |
| | | </div> |
| | | </template> |
| | | <div v-for="item in data.sites" :key="item.name" class="table__row"> |
| | | <span>{{ item.name }}</span> |
| | | <span>{{ item.weight }}</span> |
| | | <span :class="item.online ? 'is-on' : 'is-off'">{{ item.online ? '在线' : '离线' }}</span> |
| | | </div> |
| | | </div> |
| | | </screen-auto-scroll> |
| | | </panel-card> |
| | | </el-col> |
| | | </el-row> |
| | |
| | | import { computed } from 'vue'; |
| | | import KpiCard from '../../components/kpi-card.vue'; |
| | | import PanelCard from '../../components/panel-card.vue'; |
| | | import ScreenAutoScroll from '../../components/screen-auto-scroll.vue'; |
| | | import { useChartTheme, useScreenData, useScreenFieldSource } from '../../hooks/use-screen'; |
| | | |
| | | const { data } = useScreenData(); |
| | | const { isDemoField, isDemoSection } = useScreenFieldSource(); |
| | | const { isDemoSection } = useScreenFieldSource(); |
| | | const { mutedColor, splitColor, tooltip } = useChartTheme(); |
| | | |
| | | const safetyCount = computed(() => data.value.vehicles.reduce((s, e) => s + e.overspeed, 0)); |
| | | const vehicleWatchKey = computed(() => data.value.vehicles.map(e => e.no).join('|')); |
| | | const siteWatchKey = computed(() => data.value.sites.map(e => e.name).join('|')); |
| | | |
| | | function funnelWidth(value: number) { |
| | | const max = data.value.appointmentFlow[0]?.value || 1; |
| | |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .screen-page { |
| | | @import '../../styles/screen-kpi.scss'; |
| | | |
| | | .kpi-row, |
| | | .screen-page { |
| | | .mid-row { |
| | | margin-bottom: 10px; |
| | | } |
| | | |
| | | .kpi-row { |
| | | :deep(.el-col) { |
| | | margin-bottom: 10px; |
| | | } |
| | | } |
| | | |
| | | .mid-row, |
| | |
| | | } |
| | | } |
| | | |
| | | .table { |
| | | padding: 8px 12px 16px; |
| | | font-size: 13px; |
| | | .bottom-row { |
| | | :deep(.panel-card) { |
| | | min-height: 280px; |
| | | } |
| | | |
| | | &--vehicle &__head, |
| | | &--vehicle &__row { |
| | | :deep(.panel-card__body) { |
| | | display: flex; |
| | | flex-direction: column; |
| | | min-height: 0; |
| | | overflow: hidden; |
| | | } |
| | | } |
| | | |
| | | .table { |
| | | padding: 8px 12px 12px; |
| | | font-size: 13px; |
| | | height: 100%; |
| | | min-height: 0; |
| | | |
| | | &--vehicle :deep(.table__head), |
| | | &--vehicle .table__row { |
| | | grid-template-columns: 1.4fr repeat(4, 0.8fr); |
| | | } |
| | | |
| | | &--site &__head, |
| | | &--site &__row { |
| | | &--site :deep(.table__head), |
| | | &--site .table__row { |
| | | grid-template-columns: 1.6fr 0.8fr 0.6fr; |
| | | } |
| | | |
| | | &__head, |
| | | &__row { |
| | | :deep(.table__head), |
| | | .table__row { |
| | | display: grid; |
| | | gap: 8px; |
| | | padding: 10px 4px; |
| | | } |
| | | |
| | | &__head { |
| | | :deep(.table__head) { |
| | | color: var(--el-text-color-secondary); |
| | | } |
| | | |
| | | &__row { |
| | | .table__row { |
| | | border-top: 1px solid var(--el-border-color-extra-light); |
| | | } |
| | | |