wangrong
2026-08-28 17b92e9b60dda6dcc20c748046a5ff3c3958d52e
src/modules/report/views/screen/overview.vue
@@ -1,38 +1,46 @@
<template>
   <div class="screen-page">
         <el-row :gutter="10" class="kpi-row">
            <el-col v-for="item in kpis" :key="item.label" :xl="3" :lg="6" :sm="12" :xs="24">
               <kpi-card v-bind="item" />
            </el-col>
         </el-row>
      <el-row :gutter="10" class="kpi-row">
         <el-col v-for="item in kpis" :key="item.label" :xl="3" :lg="6" :sm="12" :xs="24">
            <kpi-card v-bind="item" :demo="isDemoField(item.field)" />
         </el-col>
      </el-row>
         <el-row :gutter="10" class="mid-row">
            <el-col :lg="10" :xs="24">
               <panel-card title="垃圾分类结构" sub="学校管理层看结构,不看单次称重">
                  <template #extra>
                     <cl-select-button v-model="mixMetric" :options="mixOptions" small />
                  </template>
                  <v-chart :option="mixOption" autoresize class="chart" />
               </panel-card>
            </el-col>
            <el-col :lg="14" :xs="24">
               <panel-card title="回收趋势" :sub="trendHint">
                  <template #extra>
                     <cl-select-button v-model="trendMetric" :options="trendOptions" small />
                  </template>
                  <v-chart :option="trendOption" autoresize class="chart" />
               </panel-card>
            </el-col>
         </el-row>
      <el-row :gutter="10" class="charts-row">
         <el-col :lg="7" :xs="24">
            <panel-card title="垃圾分类结构" sub="学校管理层看结构,不看单次称重" :demo="isDemoSection('wasteMix')">
               <template #extra>
                  <cl-select-button v-model="mixMetric" :options="mixOptions" small />
               </template>
               <v-chart :option="mixOption" autoresize class="chart" />
            </panel-card>
         </el-col>
         <el-col :lg="10" :xs="24">
            <panel-card title="回收趋势" :sub="trendHint" :demo="isDemoSection('trend')">
               <template #extra>
                  <cl-select-button v-model="trendMetric" :options="trendOptions" small />
               </template>
               <v-chart :option="trendOption" autoresize class="chart" />
            </panel-card>
         </el-col>
         <el-col :lg="7" :xs="24">
            <panel-card title="各院系参与人数" sub="按用户学院名称 collegeName 汇总" :demo="isDemoSection('deptRank')">
               <v-chart :option="rankOption" autoresize class="chart chart--bar" />
            </panel-card>
         </el-col>
      </el-row>
         <el-row :gutter="10">
            <el-col :span="24">
               <panel-card title="各院系参与人数" sub="按用户学院名称 collegeName 汇总,人均按参与人数">
                  <v-chart :option="rankOption" autoresize class="chart chart--bar" />
               </panel-card>
            </el-col>
         </el-row>
      </div>
      <el-row :gutter="10" class="camera-row">
         <el-col :span="24">
            <panel-card title="现场监控" sub="重点站点实时画面,首帧后暂停拉流以节省带宽">
               <template #extra>
                  <router-link class="camera-more" to="/monitor/device">更多</router-link>
               </template>
               <CameraMonitor :limit="6" />
            </panel-card>
         </el-col>
      </el-row>
   </div>
</template>
<script lang="ts" setup>
@@ -41,11 +49,14 @@
});
import { computed, ref } from 'vue';
import CameraMonitor from '../../../monitor/views/cameras.vue';
import KpiCard from '../../components/kpi-card.vue';
import PanelCard from '../../components/panel-card.vue';
import { useChartTheme, useScreenData } from '../../hooks/use-screen';
import ScreenCameraPreview from '../../components/screen-camera-preview.vue';
import { useChartTheme, useScreenData, useScreenFieldSource } from '../../hooks/use-screen';
const { data, timeRange } = useScreenData();
const { isDemoField, isDemoSection } = useScreenFieldSource();
const { textColor, mutedColor, splitColor, primary, baseGrid, axisStyle, tooltip } = useChartTheme();
const mixMetric = ref<'weight' | 'value' | 'count'>('weight');
@@ -64,14 +75,14 @@
];
const kpis = computed(() => [
   { label: '今日回收量', value: data.value.kpis.todayWeightKg, suffix: 'kg', fixed: 1, hint: '实时称重汇总' },
   { label: '本区间回收量', value: data.value.kpis.periodWeightTon, suffix: '吨', fixed: 2, hint: '当前时间范围' },
   { label: '资源化率', value: data.value.kpis.resourceRate, suffix: '%', fixed: 1, hint: '可回收物重量 / 总重量,不含大件和电子' },
   { label: '回收价值', value: data.value.kpis.periodValue, suffix: '元', fixed: 0, hint: '日表估算销售额' },
   { label: '碳减排', value: data.value.kpis.periodCarbonTon, suffix: '吨CO₂e', fixed: 2, hint: '分类重量 × 碳减因数' },
   { label: '累计回收量', value: data.value.kpis.totalWeightTon, suffix: '吨', fixed: 1, hint: '上线以来累计' },
   { label: '累计参与人数', value: data.value.kpis.totalParticipants, suffix: '人', fixed: 0, hint: '去重校园用户' },
   { label: '累计碳积分', value: data.value.kpis.totalPoints, suffix: '分', fixed: 0, hint: '账户余额合计' }
   { field: 'kpis.todayWeightKg', label: '今日回收量', value: data.value.kpis.todayWeightKg, suffix: 'kg', fixed: 1, hint: '实时称重汇总' },
   { field: 'kpis.periodWeightTon', label: '本区间回收量', value: data.value.kpis.periodWeightTon, suffix: '吨', fixed: 2, hint: '当前时间范围' },
   { field: 'kpis.resourceRate', label: '资源化率', value: data.value.kpis.resourceRate, suffix: '%', fixed: 1, hint: '可回收物重量/总重量,不含大件' },
   { field: 'kpis.periodValue', label: '回收价值', value: data.value.kpis.periodValue, suffix: '元', fixed: 0, hint: '日表估算销售额' },
   { field: 'kpis.periodCarbonTon', label: '碳减排', value: data.value.kpis.periodCarbonTon, suffix: '吨CO₂e', fixed: 2, hint: '分类重量 × 碳减因数' },
   { field: 'kpis.totalWeightTon', label: '累计回收量', value: data.value.kpis.totalWeightTon, suffix: '吨', fixed: 1, hint: '上线以来累计' },
   { field: 'kpis.totalParticipants', label: '累计参与人数', value: data.value.kpis.totalParticipants, suffix: '人', fixed: 0, hint: '去重校园用户' },
   { field: 'kpis.totalPoints', label: '累计碳积分', value: data.value.kpis.totalPoints, suffix: '分', fixed: 0, hint: '账户余额合计' }
]);
const mixOption = computed(() => ({
@@ -162,7 +173,8 @@
<style lang="scss" scoped>
.screen-page {
   .kpi-row,
   .mid-row {
   .charts-row,
   .camera-row {
      margin-bottom: 10px;
   }
@@ -172,19 +184,19 @@
      }
   }
   .mid-row {
   .charts-row {
      :deep(.panel-card) {
         min-height: 360px;
         min-height: 380px;
      }
   }
   .chart {
      height: 300px;
      height: 340px;
      width: 100%;
      &--bar {
         height: 320px;
         height: 370px;
      }
   }
}
</style>
</style>