Sfoglia il codice sorgente

Merge branch 'master' of http://git.xt.wenhq.top:8083/hs/zhny_ui

hsshuxian 9 mesi fa
parent
commit
91959ac30f

+ 1 - 0
ems-ui/package.json

@@ -50,6 +50,7 @@
     "dayjs": "^1.11.13",
     "diagram-js": "^14.11.3",
     "echarts": "5.4.0",
+    "echarts-gl": "^2.0.9",
     "element-resize-detector": "^1.2.4",
     "element-ui": "^2.15.14",
     "file-saver": "2.0.5",

+ 8 - 0
ems-ui/src/api/mgr/pgSupplyH.js

@@ -50,3 +50,11 @@ export function listPvSupplyH(query) {
     params: query
   })
 }
+// 查询发电量根据日
+export function listPvSupplyD(query) {
+  return request({
+    url: '/ems/prod/pv/day/list',
+    method: 'get',
+    params: query
+  })
+}

+ 5 - 0
ems-ui/src/router/index.js

@@ -58,6 +58,11 @@ export const constantRoutes = [
   //   hidden: true
   // },
   {
+    path: '/test',
+    component: () => import('@/views/largeScreen/test.vue'),
+    hidden: true
+  },
+  {
     path: '/404',
     component: () => import('@/views/error/404'),
     hidden: true

+ 5 - 1
ems-ui/src/store/modules/userState.js

@@ -2,17 +2,21 @@ export const userState = {
   namespaced: true,
   state: {
     selectedServiceArea: '',
+    areaType:''
   },
 
   mutations: {
     setSelectedArea: (state, area) => {
       state.selectedServiceArea = area;
+    },
+    setAreaType: (state, type) => {
+      state.areaType = type;
     }
   },
 
   getters: {
     getSelectedArea(state) {
       return state.selectedServiceArea;
-    }
+    },
   }
 }

+ 11 - 0
ems-ui/src/utils/index.js

@@ -23,6 +23,16 @@ export function dateFormat(date, format = 'yyyy-MM-dd HH:mm:ss') {
   }
   return format;
 }
+
+/**
+ * @description: 获取n天前指定日期
+ * @param {*} n
+ */
+export const getDayAgoDate = (n = 0) => {
+  let curDate = new Date();
+  let newDate = new Date(curDate - 1000 * 60 * 60 * 24 * n);
+  return newDate
+}
 /**
  * 表格时间格式化
  */
@@ -409,3 +419,4 @@ export const uuid = () => {
 export const copyObj = obj => {
   return JSON.parse(JSON.stringify(obj));
 };
+

+ 291 - 257
ems-ui/src/views/analysis/power/prod.vue

@@ -1,297 +1,331 @@
 <template>
-  <div class="app-container power-index-content">
-    <el-row type="flex" :gutter="20">
-      <el-col :span="24">
-        <div class="gl-filters">
-          <SwitchTag
-              :ds="areaTag"
-              :def-tag="defArea"
-              :tagClick="onSwitchTagClick"
-          />
+  <div class="app-container">
+    <el-row :gutter="10">
+      <el-col :span="4" :xs="24">
+        <div class="head-container">
+          <el-input v-model="areaName" placeholder="请输入区域名称" clearable size="small" prefix-icon="el-icon-search"
+            style="margin-bottom: 20px" />
+        </div>
+        <div class="head-container" style="height: 100vh; overflow: hidden; position: relative;">
+          <el-tree :data="areaOptions" :props="defaultProps" :expand-on-click-node="false"
+            :filter-node-method="filterNode" ref="tree" node-key="id" default-expand-all highlight-current
+            @node-click="handleNodeClick" style="height: calc(100vh - 50px); overflow-y: auto;" />
         </div>
       </el-col>
-    </el-row>
-    <el-row type="flex" :gutter="20" style="margin-top: 20px">
-      <el-col :span="12">
-        <LineChartBlock
-            title="发电量"
-            :on-filter="getPvList"
-            :opt-cfg="pvData"
-        >
-          <template v-slot:filters>
-            <SwitchTag
-                :ds="[{val: 'day', text: '按日'},{val: 'month', text: '按月'},{val: 'year', text: '按年'}]"
-                :defTag="{val: 'day'}"
-                :tagClick="getPvList"
-            />
-          </template>
-        </LineChartBlock>
-      </el-col>
-      <el-col :span="12">
-        <LineChartBlock
-            title="发电功率"
-            :on-filter="()=>{}"
-            :opt-cfg="pvPower"
-        >
-          <template v-slot:filters>
-            <SwitchTag
-                :ds="[{val: 'day', text: '按日'},{val: 'month', text: '按月'},{val: 'year', text: '按年'}]"
-                :defTag="{val: 'day'}"
-                :tagClick="getPvList"
-            />
-          </template>
-        </LineChartBlock>
-      </el-col>
-    </el-row>
-    <el-row type="flex" :gutter="20" style="margin-top: 20px">
-      <el-col :span="12">
-        <LineChartBlock title="发电效率" :on-filter="()=>{}" :opt-cfg="pvEff">
-          <template v-slot:filters>
-            <SwitchTag
-                :ds="[{val: 'day', text: '按日'},{val: 'month', text: '按月'},{val: 'year', text: '按年'}]"
-                :defTag="{val: 'day'}"
-                :tagClick="getPvList"
-            />
-          </template>
-        </LineChartBlock>
-      </el-col>
-      <el-col :span="12">
-        <LineChartBlock title="近七天发电趋势分析" :on-filter="()=>{}" :opt-cfg="pvWeek">
-          <template v-slot:filters>
-            <SwitchTag
-                :ds="[{val: 'day', text: '按日'},{val: 'month', text: '按月'},{val: 'year', text: '按年'}]"
-                :defTag="{val: 'day'}"
-                :tagClick="getPvList"
-            />
-          </template>
-        </LineChartBlock>
+      <el-col :span="20" :xs="24">
+        <div class="container-block">
+          <div style="display: flex;justify-content: space-between;">
+            <SubTitle :title="`发电量【${selectedLabel}】`" />
+            <el-button-group>
+              <el-button v-for="item in btnGroup" :key="item.name" size="mini"
+                :type="item.name === activeBtn ? 'primary' : ''" :icon="item.icon" @click="btnChange(item)" />
+            </el-button-group>
+          </div>
+          <div class="ctl-container">
+            <el-date-picker v-model="dateRange" type="daterange" @change="getList" :picker-options="pickerOptions"
+              value-format="yyyy-MM-dd" range-separator="至" start-placeholder="开始日期" end-placeholder="结束日期"
+              align="right" :clearable="false">
+            </el-date-picker>
+          </div>
+          <el-table v-if="activeBtn == 'table'" v-loading="loading" :data="elecStoreHList" max-height="400px">
+            <el-table-column label="日期" align="center" prop="date" width="180">
+            </el-table-column>
+            <el-table-column label="发电量(kW·h)" align="center" prop="genElecQuantity" />
+            <el-table-column label="上网电量(kW·h)" align="center" prop="upElecQuantity" />
+            <el-table-column label="自用电量(kW·h)" align="center" prop="useElecQuantity" />
+            <el-table-column label="上网收益(元)" align="center" prop="upElecEarn" />
+          </el-table>
+          <BaseChart v-else width="100%" height="500px" :option="elecOptions" />
+        </div>
       </el-col>
     </el-row>
   </div>
 </template>
 
-<script>
-
-import { ApiCode } from '@/api/apiEmums';
-import { get } from '@/api/commonApi';
-import { DateTool } from '@/utils/DateTool';
-import * as areaApi from '../../../api/basecfg/area';
-import LineChartBlock from '../../../components/Block/charts/LineChartBlock.vue';
-import SwitchTag from '../../../components/SwitchTag/index.vue';
 
+<script>
+import {listPvSupplyD} from '@/api/mgr/pgSupplyH.js'
+import {areaWithFacsCategoryAsTree} from '@/api/basecfg/area'
+import BaseChart from '@/components/BaseChart'
+import SubTitle from '@/components/SubTitle'
+import Treeselect from "@riophae/vue-treeselect";
+import "@riophae/vue-treeselect/dist/vue-treeselect.css";
+import {dateFormat, getDayAgoDate} from '@/utils'
 export default {
+  name: 'ElecStoreD',
   components: {
-    LineChartBlock,
-    SwitchTag,
+    Treeselect,
+    BaseChart,
+    SubTitle
   },
-  data() {
+  data () {
+    const lastWeek = getDayAgoDate(7)
+    const nowDay = new Date()
     return {
-      areaTag: [],
-      defArea: {},
-      pvData: {
+      // 遮罩层
+      loading: true,
+      facsCategory: 'E',
+      facsSubCategory: '',
+      elecStoreHList: [],
+      areaName: undefined,
+      defaultProps: {
+        children: "children",
+        label: "label"
+      },
+      selectedLabel: '',
+      // 查询参数
+      queryParams: {
+        areaCode: ''
+      },
+      pickerOptions: {
+        shortcuts: [
+          {
+            text: '最近一周',
+            onClick (picker) {
+              const end = new Date()
+              const start = new Date()
+              start.setTime(start.getTime() - 3600 * 1000 * 24 * 7)
+              picker.$emit('pick', [start, end])
+            }
+          }, {
+            text: '最近一个月',
+            onClick (picker) {
+              const end = new Date()
+              const start = new Date()
+              start.setTime(start.getTime() - 3600 * 1000 * 24 * 30)
+              picker.$emit('pick', [start, end])
+            }
+          }, {
+            text: '最近三个月',
+            onClick (picker) {
+              const end = new Date()
+              const start = new Date()
+              start.setTime(start.getTime() - 3600 * 1000 * 24 * 90)
+              picker.$emit('pick', [start, end])
+            }
+          }
+        ]
+      },
+      // 表单参数
+      areaOptions: [],
+      dateRange: [dateFormat(lastWeek, 'yyyy-MM-dd'), dateFormat(nowDay, 'yyyy-MM-dd')],
+      activeBtn: 'chart', //--chart图表 --table表格
+      btnGroup: [
+        {
+          name: 'chart',
+          icon: 'el-icon-s-data'
+        },
+        {
+          name: 'table',
+          icon: 'el-icon-menu'
+        }]
+    }
+  },
+  computed: {
+    elecOptions () {
+      return {
+        tooltip: {
+          trigger: 'axis',
+          axisPointer: {
+            type: 'cross',
+            crossStyle: {
+              color: '#999'
+            }
+          }
+        },
+        legend: {
+          data: ['自用电量', '上网电量', '上网收益']
+        },
         xAxis: {
           type: 'category',
-          data: [],
+          data: this.elecStoreHList.map(item => item.date),
+          axisPointer: {
+            type: 'shadow'
+          }
         },
-        series: [
+        yAxis: [
           {
-            data: [],
-            type: 'line',
-            areaStyle: {
-              color: '#d7e4fc',
-              emphasis: {
-                color: '#6093f5',
-              },
-            },
+            name: 'kW·h(千瓦时)',
+            type: 'value'
           },
+          {
+            name: '¥(元)',
+            type: 'value'
+          }
         ],
-      },
-      pvPower: {
-        xAxis: {
-          type: 'category',
-          data: [
-            '00:00',
-            '01:00',
-            '02:00',
-            '03:00',
-            '04:00',
-            '05:00',
-            '06:00',
-            '07:00',
-            '08:00',
-            '09:00',
-            '10:00',
-            '11:00',
-            '12:00',
-            '13:00',
-            '14:00',
-            '15:00',
-            '16:00',
-            '17:00',
-            '18:00',
-            '19:00',
-            '20:00',
-            '21:00',
-            '22:00',
-            '23:00',
-          ],
-        },
-        series: [
+        dataZoom: [
           {
-            data: [
-              735, 577, 377, 403, 377, 400, 239, 500, 550, 600, 800, 900, 991, 980,
-              990, 600, 540, 500, 600, 700, 789, 790, 500, 450, 400,
-            ],
-            type: 'line',
-            areaStyle: {
-              color: '#d7e4fc',
-              emphasis: {
-                color: '#6093f5',
-              },
-            },
+            type: 'slider',
+            realtime: true,
+            start: 0,
+            // end: 20,  // 数据窗口范围的结束百分比。范围是:0 ~ 100。
+            height: 5, //组件高度
+            left: '25%', //左边的距离
+            right: '25%', //右边的距离
+            bottom: '0%', //下边的距离
+            show: true, // 是否展示
+            fillerColor: 'rgba(102, 177, 255,1)', // 滚动条颜色
+            borderColor: 'rgba(17, 100, 210, 0.12)',
+            backgroundColor: 'rgba(232,244,255,0.51)', //两边未选中的滑动条区域的颜色
+            handleSize: 0, //两边手柄尺寸
+            showDetail: false, //拖拽时是否展示滚动条两侧的文字
+            zoomLock: true, //是否只平移不缩放
+            moveOnMouseMove: false, //鼠标移动能触发数据窗口平移
+            startValue: 0, // 从头开始。
+            endValue: 8 // 最多展示几个柱体
           },
+          {
+            type: 'inside', // 支持内部鼠标滚动平移
+            start: 0,
+            // end: 20,
+            startValue: 0, // 从头开始。
+            endValue: 5, // 最多5个
+            zoomOnMouseWheel: false, // 关闭滚轮缩放
+            moveOnMouseWheel: true, // 开启滚轮平移
+            moveOnMouseMove: true // 鼠标移动能触发数据窗口平移
+          }
         ],
-      },
-      pvEff: {
-        xAxis: {
-          type: 'category',
-          data: [
-            '00:00',
-            '01:00',
-            '02:00',
-            '03:00',
-            '04:00',
-            '05:00',
-            '06:00',
-            '07:00',
-            '08:00',
-            '09:00',
-            '10:00',
-            '11:00',
-            '12:00',
-            '13:00',
-            '14:00',
-            '15:00',
-            '16:00',
-            '17:00',
-            '18:00',
-            '19:00',
-            '20:00',
-            '21:00',
-            '22:00',
-            '23:00',
-          ],
-        },
         series: [
           {
-            data: [
-              735, 577, 377, 403, 377, 400, 239, 500, 550, 600, 800, 900, 991, 980,
-              990, 600, 540, 500, 600, 700, 789, 790, 500, 450, 400,
-            ],
-            type: 'line',
-            areaStyle: {
-              color: '#d7e4fc',
-              emphasis: {
-                color: '#6093f5',
-              },
+            name: '自用电量',
+            type: 'bar',
+            stack: '总数',
+            barWidth: 30,
+            label: {
+              show: false,
+              position: 'insideRight'
             },
+            data: this.elecStoreHList.map(item => item.useElecQuantity),
+            itemStyle: {
+              normal: {
+                color: '#6395FA',
+                label: {
+                  show: true, // 开启显示
+                  position: 'top', // 在上方显示
+                  textStyle: {
+                    // 数值样式
+                    color: '#000',
+                    fontSize: 14,
+                    fontWeight: 600
+                  }
+                }
+              }
+            }
           },
-        ],
-      },
-      pvWeek: {
-        xAxis: {
-          type: 'category',
-          data: [
-            '08-01',
-            '08-02',
-            '08-03',
-            '08-04',
-            '08-05',
-            '08-06',
-          ],
-        },
-        series: [
           {
-            data: [
-              735, 577, 377, 403, 377, 400,
-            ],
-            type: 'line',
-            areaStyle: {
-              color: '#d7e4fc',
-              emphasis: {
-                color: '#6093f5',
-              },
+            name: '上网电量',
+            type: 'bar',
+            stack: '总数',
+            barWidth: 30,
+            label: {
+              show: false,
+              position: 'insideRight'
             },
+            data: this.elecStoreHList.map(item => item.upElecQuantity),
+            itemStyle: {
+              normal: {
+                color: '#8CDF6C',
+                label: {
+                  show: true, // 开启显示
+                  position: 'top', // 在上方显示
+                  textStyle: {
+                    // 数值样式
+                    color: '#000',
+                    fontSize: 14,
+                    fontWeight: 600
+                  }
+                }
+              }
+            }
           },
-        ],
-      },
-    };
+          {
+            name: '上网收益',
+            type: 'line',
+            yAxisIndex: 1,
+            data: this.elecStoreHList.map(item => item.upElecEarn),
+            smooth: false
+          }
+        ]
+      }
+    },
+
   },
-  mounted() {
-    this.initData();
+  watch: {
+    // 根据名称筛选区域树
+    areaName (val) {
+      this.$refs.tree.filter(val)
+    }
   },
-  created() {
+  async created () {
+    await this.getAreaList()
+    this.getList()
   },
   methods: {
-    onSwitchTagClick(item) {
-      console.log(item);
-    },
-    async initData() {
-      const {
-        rows,
-        total,
-      } = await areaApi.listArea({
-        pageNum: 1,
-        pageSize: 10,
-      });
-      if (rows.length > 0) {
-        rows.forEach(item => {
-          this.areaTag.push({
-            val: item.areaCode,
-            text: item.areaName,
-          });
-        });
-        this.defArea = this.areaTag[0];
-      }
-      this.queryCharts();
+    btnChange (item) {
+      this.activeBtn = item.name
     },
-    queryCharts() {
-      this.getPvList();
+    // 查询区域列表
+    async getAreaList () {
+      await areaWithFacsCategoryAsTree(this.facsCategory, this.facsSubCategory).then(response => {
+        this.areaOptions = [{
+          id: '-1',
+          label: '全部',
+          children: response.data
+        }]
+        this.selectedLabel = '全部'
+        this.queryParams.areaCode = '-1'
+      })
     },
-    async getPvList() {
-      const {
-        data,
-        code,
-      } = await get('/prod/list/prod/this/day/index', {
-        areaCode: this.defArea.val,
-      });
-      const result = {};
-      if (ApiCode.SUCCESS !== code || !data || data.length < 1) {
-        return null;
+    /** 查询储能计量-小时列表 */
+    getList () {
+      this.loading = true
+      const {areaCode} = this.queryParams
+      let startTime = ''
+      let endTime = ''
+      if (this.dateRange && this.dateRange.length) {
+        const [start, end] = this.dateRange
+        startTime = start
+        endTime = end
       }
-      const xAxis = DateTool.getTime(60);
-      data.forEach(item => {
-        const {
-          elecQuantity,
-          timeIndex,
-        } = item;
-        result[timeIndex] = {
-          elecQuantity,
-        };
-      });
-      const chartData = [];
-      xAxis.forEach((item, index) => {
-        const timeIndex = index + 1;
-        if (result[timeIndex]) {
-          chartData.push(result[timeIndex].elecQuantity);
-        } else {
-          chartData.push(0);
+      listPvSupplyD({
+        areaCode,
+        startTime,
+        endTime
+      }).then(({code, data}) => {
+        this.loading = false
+        if (code === 200) {
+          this.elecStoreHList = data
         }
-      });
-      this.pvData.xAxis.data = xAxis;
-      this.pvData.series[0].data = chartData;
+
+      })
+    },
+    // 筛选节点
+    filterNode (value, data) {
+      if (!value) return true
+      return data.label.indexOf(value) !== -1
+    },
+    // 节点单击事件
+    handleNodeClick (data) {
+      this.queryParams.areaCode = data.id
+      this.selectedLabel = data.label
+      this.getList()
     },
   }
-};
+}
 </script>
-<style src="./index.scss" lang="scss" />
+
+<style lang="scss" scoped>
+@import './index.scss';
+
+.app-container {
+  ::v-deep .el-tabs__content {
+    overflow: initial;
+  }
+}
+
+.ctl-container {
+  display: flex;
+  justify-content: flex-end;
+  margin: 10px 0;
+}
+</style>

+ 22 - 5
ems-ui/src/views/largeScreen/center.vue

@@ -1,19 +1,29 @@
 <template>
   <div class="center">
-    <!-- <img src="@/assets/images/center.jpg" alt=""> -->
+    <CusTabs  :tabs="areaTabs" :active.sync="areaType" @tab-click="areaTabClick" />
   </div>
 </template>
 <script>
+import CusTabs from './components/CusTabs.vue';
+import { mapMutations } from 'vuex';
 export default {
-name: 'index',
+name: 'Center',
   data () {
     return {
+      areaType:'',
+      areaTabs: [{name: '全部', value: ''}, {name: '北区', value: '1'}, {name: '南区', value: '2'}],
     };
   },
-  components: {},
-  computed: {},
+  components: {
+    CusTabs
+  },
   mounted(){},
-  methods: {}
+  methods: {
+    ...mapMutations('userState',['setAreaType']),
+    areaTabClick () {
+      this.setAreaType(this.areaType)
+    }
+  }
 }
 </script>
 <style lang='scss' scoped>
@@ -23,5 +33,12 @@ name: 'index',
   width: calc(100% - 806px);
   margin:auto auto 0;
   height: calc(100% - 90px);
+  position: relative;
+  .tabs{
+    position: absolute;
+    top: 20px;
+    left: 20px;
+    z-index: 45;
+  }
 }
 </style>

+ 194 - 268
ems-ui/src/views/largeScreen/device/left.vue

@@ -1,43 +1,43 @@
 <template>
   <div>
-    <CusModule title="产能情况">
-      <CusTabs slot="title-right" :tabs="dateTabs" :active.sync="dateType" @tab-click="dateTabClick" />
-      <div class="production">
-        <div v-for="i in productionList" :key="i.id" class="production-item"
-          :style="{ backgroundImage: `url(${i.image})` }">
-          <div class="item-value">
-            <span class="value">{{ i.value }}</span>
-            <span class="unit">{{ i.unit }}</span>
+    <CusModule title="设备类型统计">
+      <Pie3d :pieData="pieData" />
+    </CusModule>
+    <CusModule class="module-top" title="设备状态分析">
+      <div class="dev-top">
+        <div class="dev-ttl">
+          <div class="txt-sml txt-clr">设备总数</div>
+          <div class="num">
+            <span v-for="value, index in countFormat(deviceTotal, 6)" :key="index">{{ value }}</span>
           </div>
-          <div class="item-name">{{ i.name }}</div>
         </div>
       </div>
-    </CusModule>
-    <CusModule class="module-top" title="用能情况">
-      <CusTabs slot="title-right" :tabs="buildingTabs" :active.sync="buildingType" />
-      <BaseChart width="100%" height="300px" :option="usePieOptions"></BaseChart>
-    </CusModule>
-    <CusModule class="module-top" title="储能数据">
-      <div class="storage-container">
-        <div class="center-spinner"></div>
-        <div class="percentage-display">
-          <span class="value">100</span><span class="unit">%</span>
-        </div>
-        <div class="charge-status">
-          实时充电量
+      <div class="dev-flx">
+        <div v-for="i in equipList" class="dev-itm" :key="i.name" :style="{ backgroundImage: `url(${i.image})` }">
+          <div class="val">
+            <span class="num">{{ i.value }}</span><span class="unit">{{ i.unit }}</span>
+          </div>
+          <div class="pct">
+            {{ i.pct }}<span class="unit">%</span>
+          </div>
+          <div class="name">
+            {{ i.name }}
+          </div>
         </div>
       </div>
-      <div class="storage-grid">
-        <div class="grid-item" v-for="i in storageData" :key="i.name">
-          <div class="image-container">
-            <img :src="i.image" alt="" />
-          </div>
-          <div class="item-details">
-            <div class="item-value">
-              <span class="value">{{ i.value }}</span>
-              <span class="unit">{{ i.unit }}</span>
+    </CusModule>
+    <CusModule class="module-top" title="处置状态">
+      <div class="dev-flex">
+        <div class="dev-item" v-for="item in deal" :key="item.name">
+          <div class="percent">{{item.percent}} %</div>
+          <div class="details">
+            <div class="alarm">
+              {{item.name}}:<span class="alarm-count">{{item.value}}次</span>
+            </div>
+            <div>
+              <span class="value">{{item.dealValue}}</span><span class="unit">次</span>
             </div>
-            <div class="item-name">{{ i.name }}</div>
+            <div>已处理</div>
           </div>
         </div>
       </div>
@@ -45,295 +45,221 @@
   </div>
 </template>
 <script>
-import CusTabs from '../components/CusTabs.vue';
 import CusModule from '../components/CusModule.vue';
 import BaseChart from '@/components/BaseChart/index.vue'
-
+import Pie3d from './pie3d.vue'
+import {mapState} from 'vuex';
 export default {
-  name:'HomeLeft',
+  name: 'DeviceLeft',
   data () {
     return {
-      dateType: '1',
-      dateTabs: [{name: '当日', value: '1'}, {name: '本周', value: '2'}, {name: '本月', value: '3'}, {name: '本年', value: '4'}],
-      productionList: [
-        {
-          name: "装机容量",
-          value: 100,
-          unit: "kW",
-          image: require("@/assets/images/source/item_bg1.png"),
-        },
-        {
-          name: "光伏发电量",
-          value: 86.3,
-          unit: "kW·h",
-          image: require("@/assets/images/source/item_bg1.png"),
-        },
+      pieData: [],
+      deviceTotal:1220,
+      equipList: [
         {
-          name: "负荷消耗",
-          value: 82.1,
-          unit: "kW·h",
-          image: require("@/assets/images/source/item_bg3.png"),
+          name: "在线设备",
+          value: 530,
+          pct: 50,
+          unit: "件",
+          image: require("@/assets/images/device/l2-item1_bg.png"),
         },
         {
-          name: "入网",
-          value: 78.09,
-          unit: "kW·h",
-          image: require("@/assets/images/source/item_bg4.png"),
-        },
-      ],
-      buildingType: '1',
-      buildingTabs: [{name: '按建筑', value: '1'}, {name: '按设施', value: '2'}],
-      useStorage: [
-        {
-          name: "配电泵房",
-          value: 100
-        },
-        {
-          name: "北区综合楼",
-          value: 500
-        },
-        {
-          name: "南区综合楼",
-          value: 300
-        },
-        {
-          name: "北区加油站",
-          value: 200
-        },
-        {
-          name: "南区加油站",
-          value: 100
-        },
-        {
-          name: "北区停车场",
-          value: 100
+          name: "故障设备",
+          value: 12,
+          pct: 30,
+          unit: "次",
+          image: require("@/assets/images/device/l2-item2_bg.png"),
         },
         {
-          name: "南区停车场",
-          value: 80
+          name: "离线设备",
+          value: 6,
+          pct: 20,
+          unit: "次",
+          image: require("@/assets/images/device/l2-item3_bg.png"),
         },
       ],
-      storageData: [
+      deal: [
         {
-          name: "今日充电",
-          image: require("@/assets/images/home/icon1.png"),
-          value: 250,
-          unit: "kW·h",
+          name: '今日报警',
+          percent: 70,
+          value: 10,
+          dealValue:7
         },
         {
-          name: "今日放电",
-          image: require("@/assets/images/home/icon2.png"),
-          value: 58,
-          unit: "kW·h",
-        },
-        {
-          name: "电池温度",
-          image: require("@/assets/images/home/icon3.png"),
-          value: 36,
-          unit: "°C",
-        },
-        {
-          name: "累计充电次数",
-          image: require("@/assets/images/home/icon4.png"),
-          value: 289,
-          unit: "次",
+          name: '本月报警',
+          percent: 80,
+          value: 300,
+          dealValue:240
         },
       ]
     };
   },
   components: {
     CusModule,
-    CusTabs,
-    BaseChart
+    BaseChart,
+    Pie3d
   },
   computed: {
-    usePieOptions () {
-      return {
-        calculable: true,
-        tooltip: {
-          trigger: 'item',
-          formatter: (params) => {
-            const {name, value, percent, seriesName} = params
-            if (seriesName != '透明圆圈') {
-              return `${name} : ${value} (${percent}%)`
-            }
-            return ''
-          }
-        },
-        series: [
-          {
-            name: '',
-            type: 'pie',
-            clockWise: false,
-            radius: ['10%', '70%'],
-            center: ['50%', '50%'],
-            roseType: 'area',
-            data: this.useStorage,
-            label: {
-              color: '#fff',
-              formatter: "{b} : {d}%",
-              padding: [0, -75]
-            },
-            labelLine: {
-              normal: {
-                show: true,
-                length: 10,
-                length2: 20,
-              }
-            },
-          },
-          {
-            name: '透明圆圈',
-            type: 'pie',
-            radius: [10, 27],
-            center: ['50%', '50%'],
-            itemStyle: {
-              color: 'rgba(250, 250, 250, 0.3)',
-            },
-            data: [
-              {value: 10, name: ''}
-            ]
-          },
-          {
-            name: '透明圆圈',
-            type: 'pie',
-            radius: [10, 35],
-            center: ['50%', '50%'],
-            itemStyle: {
-              color: 'rgba(250, 250, 250, 0.3)',
-            },
-            data: [
-              {value: 10, name: ''}
-            ]
-          }
-        ]
-
-      };
-
+    ...mapState('userState', ['areaType']),
+  },
+  watch: {
+    areaType () {
+      this.getDeviceData()
     }
   },
-  mounted () { },
+  mounted () {
+    this.getDeviceData()
+  },
   methods: {
-    dateTabClick () { }
+    //字符串转数组 总数
+    countFormat (val, total = 0) {
+      let str = String(val);
+      let numArr = str.split("");
+      if (total === 0) return numArr;
+      let c = numArr.length <= total && total - numArr.length;
+      let arr = [];
+      if (c || c === 0) {
+        for (let i = 0; i < c; i++) {
+          numArr.unshift("0");
+        }
+        return numArr;
+      } else {
+        for (let i = 0; i < total; i++) {
+          arr.push("9");
+        }
+        return arr;
+      }
+    },
+    getDeviceData () {
+      const equip = ['空调', '照明', '电梯', '其他']
+      this.pieData = equip.map(item => ({
+        name: item,
+        value: Math.floor(Math.random() * 100)
+      }))
+      this.deviceTotal = this.areaType=='1'?600:this.areaType=='2'?620:1220
+      this.equipList = this.equipList.map((item,index) => ({
+        ...item,
+        value: index === 0 ? Math.floor(Math.random() * 100 + 500) : Math.floor(Math.random() * 100),
+        pct:Math.floor(Math.random() * 100)
+      }))
+      this.deal = this.deal.map((item,index) => ({
+        ...item,
+        percent:Math.floor(Math.random()*100),
+        value:Math.floor(Math.random()*100+(index+1)*100),
+        dealValue:Math.floor(Math.random()*100+index*100)
+      }))
+    }
   }
 }
 </script>
 <style lang='scss' scoped>
 @import url("../index.scss");
-.production {
-  display: flex;
-  flex-wrap: wrap;
 
-  .production-item {
-    height: 51px;
-    flex-basis: 50%;
-    background-repeat: no-repeat;
-    display: flex;
-    flex-direction: column;
-    padding-left: 70px;
-    padding-top: 10px;
-    margin-top: 15px;
+.dev-top {
+  height: 66px;
+  background-image: url('~@/assets/images/device/l2-top_bg.png');
+  background-position: center;
+  background-repeat: no-repeat;
+  text-align: center;
+  padding-top: 5px;
+  margin-top: 2px;
 
-    .item-name {
+  .dev-ttl {
+    .txt-sml {
+      margin-top: 12px;
+      color: #B3E3E8;
       font-size: 12px;
     }
 
-    .item-value {
-      .value {
-        color: #07e3f9;
-        font-weight: bold;
-        font-size: 20px;
-      }
-
-      .unit {
-        color: #768f95;
-        font-size: 12px;
-        margin-left: 2px;
-      }
+    .num {
+      margin-top: 2px;
+      font-size: 16px;
+      font-weight: bold;
+      letter-spacing: 16px;
+      margin-left: 16px;
     }
   }
 }
-.storage-container {
-  position: relative;
-  margin-top: 8px;
-  width: 335px;
-  height: 172px;
-  background-image: url('~@/assets/images/home/l2-top_bg.png');
 
-  .center-spinner {
-    position: absolute;
-    animation: spin 10s linear infinite;
-    left: calc(50% - 61.5px);
-    top: 0;
-    width: 123px;
-    height: 123px;
-    background-image: url('~@/assets/images/home/l2-top_center.png');
-  }
-  .percentage-display {
-    position: absolute;
-    left: 50%;
-    top: 44px;
-    transform: translateX(-50%);
-    span.value {
-      font-size: 36px;
+.dev-flx {
+  display: flex;
+  justify-content: space-between;
+  margin-top: 4px;
+
+  .dev-itm {
+    width: 103px;
+    height: 150px;
+    position: relative;
+
+    .val {
+      width: 100%;
+      text-align: center;
+      position: absolute;
+      bottom: 82px;
+      color: #07e3f9;
     }
-    span.unit {
-      font-size: inherit;
+
+    .pct {
+      width: 100%;
+      text-align: center;
+      position: absolute;
+      bottom: 50px;
     }
-  }
 
-  .charge-status {
-    position: absolute;
-    bottom: 20px;
-    left: 50%;
-    transform: translateX(-50%);
-    color: #B3E3E8;
-    font-size: 14px;
-  }
-}
+    .name {
+      width: 100%;
+      text-align: center;
+      position: absolute;
+      color: #B3E3E8;
+      font-size: 14px;
+      bottom: 18px;
+    }
 
-.storage-grid {
-  display: flex;
-  flex-wrap: wrap;
+    .num {
+      font-size: 18px;
+      font-weight: bold;
+    }
+  }
 }
 
-.grid-item {
-  flex-basis: 50%;
-  height: 62px;
+.dev-flex {
   display: flex;
-  background: url('~@/assets/images/home/l2_item_bg.png') no-repeat;
-  &:nth-child(n+3){
-    margin-top: 10px;
-  }
-  .image-container {
-    width: 90px;
-    display: flex;
-    align-items: center;
-    justify-content: center;
-  }
+  justify-content: space-around;
+  margin-top: 3px;
 
-  .item-details {
-    width: calc(100% - 22px);
-    display: flex;
-    flex-direction: column;
-    justify-content: center;
-    margin-left: 5px;
+  .dev-item {
+    width: 157px;
+    height: 235px;
+    text-align: center;
     color: #B3E3E8;
+    font-size: 12px;
+    background: url("~@/assets/images/device/l3-item_bg.png");
+    background-position: center;
+    background-repeat: no-repeat;
 
-    .item-value {
-      span.value {
-        font-size: 20px;
-        font-weight: bold;
+    .percent {
+      margin-top: 45px;
+      font-size: 18px;
+    }
+
+    .details {
+      margin-top: 40px;
+      font-size: 14px;
+
+      .alarm {
+        margin-bottom: 15px;
+        font-size: 14px;
+
+        .alarm-count {
+          color: #E15050;
+        }
       }
-      span.unit {
-        color: #768f95;
-        font-size: 12px;
-        margin-left: 2px;
+
+      .value {
+        color: #07e3f9;
+        font-size: 18px;
       }
-    }
 
-    .item-name {
-      font-size: 12px;
     }
   }
 }

+ 501 - 0
ems-ui/src/views/largeScreen/device/pie3d.vue

@@ -0,0 +1,501 @@
+<template>
+  <div class="chart-container">
+    <div class="chart" ref="chart"></div>
+  </div>
+</template>
+
+<script>
+const color = ['#005aff', '#f8b551', '#EF6666', '#3FA7FD']
+import * as echarts from 'echarts';
+import 'echarts-gl';
+export default {
+  name: 'chart',
+  props: ['pieData'],
+  data () {
+    return {
+      statusChart: null,
+      option: {}
+    }
+  },
+  watch: {
+    pieData: {
+      handler (val) {
+        if (val.length) {
+          this.$nextTick(() => {
+            this.initChart()
+          })
+        }
+      },
+      deep: true,
+      immediate: true
+    }
+  },
+  mounted () {},
+  beforeDestroy () {
+    if (!this.statusChart) {
+      return
+    }
+    // 销毁图表实例
+    this.statusChart.dispose()
+    this.statusChart = null
+  },
+  methods: {
+    // 图表初始化
+    initChart () {
+      if (!this.statusChart) {
+        this.statusChart = echarts.init(this.$refs.chart)
+      }
+      const pieData = this.pieData.map((item, index) => ({
+        ...item,
+        itemStyle: {
+          color: color[index]
+        },
+        label: {
+          normal: {
+            show: true,
+            color: color[index],
+            formatter: [
+              '{b|{b}}',
+              '{c|{c}}{b|件}',
+              '{d|{d}%}'
+            ].join('\n'), // 用\n来换行
+            rich: {
+              b: {
+                color: '#fff',
+                fontSize: 16,
+                lineHeight: 25,
+                align: 'left'
+              },
+              c: {
+                fontSize: 22,
+                color: '#fff',
+                textShadowColor: '#1c90a6',
+                textShadowOffsetX: 0,
+                textShadowOffsetY: 2,
+                textShadowBlur: 5
+              },
+              d: {
+                color: color[index],
+                align: 'left',
+                fontSize: 16
+              }
+            }
+          }
+        },
+        labelLine: {
+          normal: {
+            lineStyle: {
+              width: 1,
+              color: 'rgba(255,255,255,0.7)'
+            }
+          }
+        }
+      }))
+      // 传入数据生成 option, 构建3d饼状图, 参数工具文件已经备注的很详细
+      this.option = this.getPie3D(pieData, 0.8, 240, 28, 26, 0.5)
+      // this.statusChart.setOption(this.option)
+      // 是否需要label指引线,如果要就添加一个透明的2d饼状图并调整角度使得labelLine和3d的饼状图对齐,并再次setOption
+      this.option.series.push({
+        name: '设备类型统计', //自己根据场景修改
+        backgroundColor: 'transparent',
+        type: 'pie',
+        label: {
+          opacity: 1,
+          fontSize: 13,
+          lineHeight: 20
+        },
+        startAngle: -40, // 起始角度,支持范围[0, 360]。
+        clockwise: false, // 饼图的扇区是否是顺时针排布。上述这两项配置主要是为了对齐3d的样式
+        radius: ['20%', '50%'],
+        center: ['50%', '50%'],
+        data: pieData,
+        itemStyle: {
+          opacity: 0  //这里必须是0,不然2d的图会覆盖在表面
+        }
+      })
+      this.statusChart.setOption(this.option)
+      // this.bindListen(this.statusChart)
+    },
+    // 监听鼠标事件,实现饼图选中效果(单选),近似实现高亮(放大)效果。
+    // optionName是防止有多个图表进行定向option传递,单个图表可以不传,默认是opiton
+    bindListen (myChart, optionName = 'option') {
+      let selectedIndex = ''
+      let hoveredIndex = ''
+      // 监听点击事件,实现选中效果(单选)
+      myChart.on('click', (params) => {
+        // 从 option.series 中读取重新渲染扇形所需的参数,将是否选中取反。
+        const isSelected = !this[optionName].series[hoveredIndex].pieStatus.isSelected
+        const isHovered =
+          this[optionName].series[params.seriesIndex].pieStatus.hovered
+        const k = this[optionName].series[params.seriesIndex].pieStatus.k
+        const startRatio =
+          this[optionName].series[params.seriesIndex].pieData.startRatio
+        const endRatio =
+          this[optionName].series[params.seriesIndex].pieData.endRatio
+        // 如果之前选中过其他扇形,将其取消选中(对 option 更新)
+        if (selectedIndex !== '' && selectedIndex !== params.seriesIndex) {
+          this[optionName].series[
+            selectedIndex
+          ].parametricEquation = this.getParametricEquation(
+            this[optionName].series[selectedIndex].pieData.startRatio,
+            this[optionName].series[selectedIndex].pieData.endRatio,
+            false,
+            false,
+            k,
+            this[optionName].series[selectedIndex].pieData.value
+          )
+          this[optionName].series[selectedIndex].pieStatus.selected = false
+        }
+        // 对当前点击的扇形,执行选中/取消选中操作(对 option 更新)
+        this[optionName].series[
+          params.seriesIndex
+        ].parametricEquation = this.getParametricEquation(
+          startRatio,
+          endRatio,
+          isSelected,
+          isHovered,
+          k,
+          this[optionName].series[params.seriesIndex].pieData.value
+        )
+        this[optionName].series[params.seriesIndex].pieStatus.selected = isSelected
+        // 如果本次是选中操作,记录上次选中的扇形对应的系列号 seriesIndex
+        selectedIndex = isSelected ? params.seriesIndex : null
+        // 使用更新后的 option,渲染图表
+        myChart.setOption(this[optionName])
+      })
+      // 监听 mouseover,近似实现高亮(放大)效果
+      myChart.on('mouseover', (params) => {
+        // 准备重新渲染扇形所需的参数
+        let isSelected
+        let isHovered
+        let startRatio
+        let endRatio
+        let k
+        // 如果触发 mouseover 的扇形当前已高亮,则不做操作
+        if (hoveredIndex === params.seriesIndex) {
+          // 否则进行高亮及必要的取消高亮操作
+        } else {
+          // 如果当前有高亮的扇形,取消其高亮状态(对 option 更新)
+          if (hoveredIndex !== '') {
+            // 从 option.series 中读取重新渲染扇形所需的参数,将是否高亮设置为 false。
+            isSelected = this[optionName].series[hoveredIndex].pieStatus.isSelected
+            isHovered = false
+            startRatio = this[optionName].series[hoveredIndex].pieData.startRatio
+            endRatio = this[optionName].series[hoveredIndex].pieData.endRatio
+            k = this[optionName].series[hoveredIndex].pieStatus.k
+            // 对当前点击的扇形,执行取消高亮操作(对 option 更新)
+            this[optionName].series[
+              hoveredIndex
+            ].parametricEquation = this.getParametricEquation(
+              startRatio,
+              endRatio,
+              isSelected,
+              isHovered,
+              k,
+              this[optionName].series[hoveredIndex].pieData.value
+            )
+            this[optionName].series[hoveredIndex].pieStatus.hovered = isHovered
+            // 将此前记录的上次选中的扇形对应的系列号 seriesIndex 清空
+            hoveredIndex = ''
+          }
+          // 如果触发 mouseover 的扇形不是透明圆环,将其高亮(对 option 更新)
+          if (
+            params.seriesName !== 'mouseoutSeries' &&
+            params.seriesName !== 'pie2d'
+          ) {
+            // 从 option.series 中读取重新渲染扇形所需的参数,将是否高亮设置为 true。
+            isSelected = this[optionName].series[hoveredIndex].pieStatus.isSelected
+            isHovered = true
+            startRatio =
+              this[optionName].series[params.seriesIndex].pieData.startRatio
+            endRatio = this[optionName].series[params.seriesIndex].pieData.endRatio
+            k = this[optionName].series[params.seriesIndex].pieStatus.k
+            // 对当前点击的扇形,执行高亮操作(对 option 更新)
+            this[optionName].series[
+              params.seriesIndex
+            ].parametricEquation = this.getParametricEquation(
+              startRatio,
+              endRatio,
+              isSelected,
+              isHovered,
+              k,
+              this[optionName].series[params.seriesIndex].pieData.value + 60
+            )
+            this[optionName].series[
+              params.seriesIndex
+            ].pieStatus.hovered = isHovered
+            // 记录上次高亮的扇形对应的系列号 seriesIndex
+            hoveredIndex = params.seriesIndex
+          }
+          // 使用更新后的 option,渲染图表
+          myChart.setOption(this[optionName])
+        }
+      })
+    },
+    // 自适应宽高
+    changeSize () {
+      this.statusChart.resize()
+    },
+    /**
+   * 绘制3d图
+   * @param pieData 总数据
+   * @param internalDiameterRatio:透明的空心占比
+   * @param distance 视角到主体的距离
+   * @param alpha 旋转角度
+   * @param pieHeight 立体的高度
+   * @param opacity 饼或者环的透明度
+   */
+    getPie3D (pieData, internalDiameterRatio, distance, alpha, pieHeight, opacity = 1) {
+      const series = []
+      let sumValue = 0
+      let startValue = 0
+      let endValue = 0
+      let legendData = []
+      let legendBfb = []
+      const k = 1 - internalDiameterRatio
+      pieData.sort((a, b) => {
+        return b.value - a.value
+      })
+      // 为每一个饼图数据,生成一个 series-surface 配置
+      for (let i = 0; i < pieData.length; i++) {
+        sumValue += pieData[i].value
+        const seriesItem = {
+          name:
+            typeof pieData[i].name === 'undefined'
+              ? `series${i}`
+              : pieData[i].name,
+          type: 'surface',
+          parametric: true,
+          wireframe: {
+            show: false
+          },
+          pieData: pieData[i],
+          pieStatus: {
+            selected: false,
+            hovered: false,
+            k: k
+          },
+          center: ['10%', '50%']
+        }
+        if (typeof pieData[i].itemStyle !== 'undefined') {
+          const itemStyle = {}
+          itemStyle.color =
+            typeof pieData[i].itemStyle.color !== 'undefined'
+              ? pieData[i].itemStyle.color
+              : opacity
+          itemStyle.opacity =
+            typeof pieData[i].itemStyle.opacity !== 'undefined'
+              ? pieData[i].itemStyle.opacity
+              : opacity
+          seriesItem.itemStyle = itemStyle
+        }
+        series.push(seriesItem)
+      }
+
+      // 使用上一次遍历时,计算出的数据和 sumValue,调用 this.getParametricEquation 函数,
+      // 向每个 series-surface 传入不同的参数方程 series-surface.parametricEquation,也就是实现每一个扇形。
+      legendData = []
+      legendBfb = []
+      for (let i = 0; i < series.length; i++) {
+        endValue = startValue + series[i].pieData.value
+        series[i].pieData.startRatio = startValue / sumValue
+        series[i].pieData.endRatio = endValue / sumValue
+        series[i].parametricEquation = this.getParametricEquation(
+          series[i].pieData.startRatio,
+          series[i].pieData.endRatio,
+          false,
+          false,
+          k,
+          series[i].pieData.value
+        )
+        startValue = endValue
+        const bfb = this.fomatFloat(series[i].pieData.value / sumValue, 4)
+        legendData.push({
+          name: series[i].name,
+          value: bfb
+        })
+        legendBfb.push({
+          name: series[i].name,
+          value: bfb
+        })
+      }
+      const boxHeight = this.getHeight3D(series, pieHeight) // 通过pieHeight设定3d饼/环的高度,单位是px
+      // 准备待返回的配置项,把准备好的 legendData、series 传入。
+      const option = {
+        legend: {
+          show: false,
+          data: legendData,
+          orient: 'vertical',
+          left: 10,
+          top: 10,
+          itemGap: 10,
+          textStyle: {
+            color: '#A1E2FF'
+          },
+          icon: 'circle',
+          formatter: function (param) {
+            const item = legendBfb.filter(item => item.name === param)[0]
+            const bfs = this.fomatFloat(item.value * 100, 2) + '%'
+            return `${item.name}  ${bfs}`
+          }
+        },
+        labelLine: {
+          show: true,
+          lineStyle: {
+            color: '#fff'
+          }
+        },
+        label: {
+          show: true,
+          position: 'outside',
+          formatter: '{b} \n{c} {d}%'
+        },
+        xAxis3D: {
+          min: -1,
+          max: 1
+        },
+        yAxis3D: {
+          min: -1,
+          max: 1
+        },
+        zAxis3D: {
+          min: -1,
+          max: 1
+        },
+        grid3D: {
+          show: false,
+          boxHeight: boxHeight, // 圆环的高度
+          viewControl: {
+            // 3d效果可以放大、旋转等,请自己去查看官方配置
+            alpha, // 角度
+            distance, // 调整视角到主体的距离,类似调整zoom
+            rotateSensitivity: 0, // 设置为0无法旋转
+            zoomSensitivity: 0, // 设置为0无法缩放
+            panSensitivity: 0, // 设置为0无法平移
+            autoRotate: false // 自动旋转
+          }
+        },
+        series: series
+      }
+      return option
+    },
+
+    /**
+     * 生成扇形的曲面参数方程,用于 series-surface.parametricEquation
+     */
+    getParametricEquation (startRatio, endRatio, isSelected, isHovered, k, h) {
+      // 计算
+      const midRatio = (startRatio + endRatio) / 2
+      const startRadian = startRatio * Math.PI * 2
+      const endRadian = endRatio * Math.PI * 2
+      const midRadian = midRatio * Math.PI * 2
+      // 如果只有一个扇形,则不实现选中效果。
+      if (startRatio === 0 && endRatio === 1) {
+        isSelected = false
+      }
+      // 通过扇形内径/外径的值,换算出辅助参数 k(默认值 1/3)
+      k = typeof k !== 'undefined' ? k : 1 / 3
+      // 计算选中效果分别在 x 轴、y 轴方向上的位移(未选中,则位移均为 0)
+      const offsetX = isSelected ? Math.cos(midRadian) * 0.1 : 0
+      const offsetY = isSelected ? Math.sin(midRadian) * 0.1 : 0
+      // 计算高亮效果的放大比例(未高亮,则比例为 1)
+      const hoverRate = isHovered ? 1.05 : 1
+      // 返回曲面参数方程
+      return {
+        u: {
+          min: -Math.PI,
+          max: Math.PI * 3,
+          step: Math.PI / 32
+        },
+        v: {
+          min: 0,
+          max: Math.PI * 2,
+          step: Math.PI / 20
+        },
+        x: function (u, v) {
+          if (u < startRadian) {
+            return (
+              offsetX +
+              Math.cos(startRadian) * (1 + Math.cos(v) * k) * hoverRate
+            )
+          }
+          if (u > endRadian) {
+            return (
+              offsetX + Math.cos(endRadian) * (1 + Math.cos(v) * k) * hoverRate
+            )
+          }
+          return offsetX + Math.cos(u) * (1 + Math.cos(v) * k) * hoverRate
+        },
+        y: function (u, v) {
+          if (u < startRadian) {
+            return (
+              offsetY +
+              Math.sin(startRadian) * (1 + Math.cos(v) * k) * hoverRate
+            )
+          }
+          if (u > endRadian) {
+            return (
+              offsetY + Math.sin(endRadian) * (1 + Math.cos(v) * k) * hoverRate
+            )
+          }
+          return offsetY + Math.sin(u) * (1 + Math.cos(v) * k) * hoverRate
+        },
+        z: function (u, v) {
+          if (u < -Math.PI * 0.5) {
+            return Math.sin(u)
+          }
+          if (u > Math.PI * 2.5) {
+            return Math.sin(u) * h * 0.1
+          }
+          return Math.sin(v) > 0 ? 1 * h * 0.1 : -1
+        }
+      }
+    },
+
+    /**
+     * 获取3d丙图的最高扇区的高度
+     */
+    getHeight3D (series, height) {
+      series.sort((a, b) => {
+        return b.pieData.value - a.pieData.value
+      })
+      return (height * 25) / series[0].pieData.value
+    },
+
+    /**
+     * 格式化浮点数
+     */
+    fomatFloat (num, n) {
+      let f = parseFloat(num)
+      if (isNaN(f)) {
+        return false
+      }
+      f = Math.round(num * Math.pow(10, n)) / Math.pow(10, n) // n 幂
+      let s = f.toString()
+      let rs = s.indexOf('.')
+      // 判定如果是整数,增加小数点再补0
+      if (rs < 0) {
+        rs = s.length
+        s += '.'
+      }
+      while (s.length <= rs + n) {
+        s += '0'
+      }
+      return s
+    }
+  }
+}
+</script>
+
+<style lang='scss' scoped>
+.chart-container {
+  position: relative;
+  width: 100%;
+  height: 300px;
+
+  .chart {
+    width: 100%;
+    height: 100%;
+  }
+}
+</style>

+ 339 - 315
ems-ui/src/views/largeScreen/device/right.vue

@@ -1,381 +1,405 @@
 <template>
   <div>
-    <CusModule title="节能分析">
-      <div class="grid-container">
-        <div class="left-panel">
-          <div class="spinner"></div>
-          <div class="value-display">
-            <span class="value">2589</span>
-            <span class="unit">度</span>
-          </div>
-          <div class="description">
-            <span class="text">本月用电量</span>
-            <div class="rate">
-              <span>环比</span>
-              <img src="@/assets/images/home/down-arrow.svg" alt="">
-              <span>12%</span>
-            </div>
-          </div>
-        </div>
-        <div class="right-panel ">
-          <div class="panel-content">
-            <div class="image-container">
-              <img src="@/assets/images/home/water.svg" alt="">
-            </div>
-            <div class="whitespace-pre">
-              <span class="value">989</span>
-              <span class="unit">吨</span>
-              <div class="label">本月用水量</div>
-              <div class="rate">
-                <span>环比</span>
-                <img src="@/assets/images/home/down-arrow.svg" alt="">
-                <span>12%</span>
-              </div>
-            </div>
-          </div>
-          <div class="panel-content">
-            <div class="image-container">
-              <img src="@/assets/images/home/cost.svg" alt="">
-            </div>
-            <div class="whitespace-pre">
-              <span class="value">4892</span>
-              <span class="unit">元</span>
-              <div class="label">本月用能费用</div>
-              <div class="rate">
-                <span>环比</span>
-                <img src="@/assets/images/home/down-arrow.svg" alt="">
-                <span>12%</span>
-              </div>
-            </div>
-          </div>
-        </div>
+    <CusModule title="告警信息">
+      <BaseChart height="200px" width="100%" :option="pieOptions" />
+      <div class="custom-table">
+        <el-table :data="tableData" class="customer-table" style="width: 100%" height="650">
+          <el-table-column type="index" label="序号" width="60" align="center" />
+          <el-table-column prop="type" label="报警类型" align="center">
+            <template #default="{ row }">
+              <el-tag v-if="row.type == '预警'" type="info">预警</el-tag>
+              <el-tag v-else-if="row.type == '一般'">一般</el-tag>
+              <el-tag v-else-if="row.type == '严重'" type="warning">严重</el-tag>
+              <el-tag v-else-if="row.type == '紧急'" type="danger">紧急</el-tag>
+            </template>
+          </el-table-column>
+          <el-table-column prop="content" label="报警内容" align="center" />
+          <el-table-column prop="time" label="处理时间" align="center" />
+        </el-table>
+        <el-pagination :current-page="page.pageIndex" :page-size="100" :small="'small'" :background="true"
+          layout="total,  prev, pager, next, jumper" :total="400" @size-change="handleSizeChange"
+          @current-change="handleCurrentChange" />
       </div>
     </CusModule>
-    <CusModule class="module-top" title="设备设施">
-      <div class="equip">
-        <div v-for="item in equipment" :style="{ 'color': item.color }" class="equip-item" :key="item.name">
-          <div><span>{{ item.value }}</span> <span class="unit">{{ item.unit }}</span></div>
-          <div>{{ item.name }}</div>
-        </div>
-      </div>
-      <div class="pie-chart">
-        <BaseChart height="100%" width="100%" :option="pieOptions" />
-      </div>
-    </CusModule>
-    <CusModule class="module-top" title="告警信息">
-      <div class="seamless-header">
-        <div>告警内容</div>
-        <div>告警设备</div>
-        <div>告警时间</div>
-      </div>
-      <vue-seamless-scroll :data="listData" class="seamless-warp" :class-option="classOption">
-        <div class="seamless-item" v-for="(item, index) in listData" :key="index">
-          <div>{{ item.name }}</div>
-          <div>{{ item.type }}</div>
-          <div>{{ item.createTime }}</div>
-        </div>
-      </vue-seamless-scroll>
-    </CusModule>
   </div>
 </template>
 <script>
 import CusModule from '../components/CusModule.vue';
 import BaseChart from '@/components/BaseChart/index.vue'
-import vueSeamlessScroll from 'vue-seamless-scroll'
+import {mapState} from 'vuex';
 export default {
-  name: 'HomeRight',
+  name: 'DeviceRight',
   data () {
     return {
-      equipment: [{name: '设备总数', value: '2024', unit: '个', color: '#01A7F0'},
-      {name: '在线设备', value: '1800', unit: '个', color: '#B3E3E8'},
-      {name: '离线设备', value: '200', unit: '个', color: '#fff'},
-      {name: '故障设备', value: '24', unit: '个', color: '#EB808D'}],
-      classOption: {
-        step: 0.3, // 数值越大速度滚动越快
-        limitMoveNum: 4, // 开始无缝滚动的数据量 this.dataList.length
-        hoverStop: true, // 是否开启鼠标悬停stop
-        direction: 1, // 0向下 1向上 2向左 3向右
-        openWatch: true, // 开启数据实时监控刷新dom
-        singleHeight: 0, // 单步运动停止的高度(默认值0是无缝不停止的滚动) direction => 0/1
-        singleWidth: 0, // 单步运动停止的宽度(默认值0是无缝不停止的滚动) direction => 2/3
-        waitTime: 1000 // 单步运动停止
-      },
-      listData: [
+      pieData: [],
+      tableData: [
         {
-          name: '温度超阈值上限',
-          type: '温湿度01',
-          createTime: '2024-10-07 12:15:46'
+          code: "12321",
+          time: "2023/02/23 12:02",
+          content: "变压器报警",
+          type: "紧急",
         },
         {
-          name: '制冷压力超阈值上限',
-          type: '精密空调',
-          createTime: '2024-10-08 11:11:41'
+          code: "12321",
+          time: "2023/02/23 12:02",
+          content: "电梯报警",
+          type: "严重",
         },
         {
-          name: '检测到有水',
-          type: '水浸',
-          createTime: '2024-10-09 15:15:46'
+          code: "12321",
+          time: "2023/02/23 12:02",
+          content: "路灯报警",
+          type: "一般",
         },
         {
-          name: '开门时间异常',
-          type: '东门门禁',
-          createTime: '2024-10-10 09:15:46'
+          code: "12321",
+          time: "2023/02/23 12:02",
+          content: "空调报警",
+          type: "一般",
         },
         {
-          name: '设备离线',
-          type: '摄像机1',
-          createTime: '2024-10-10 12:33:40'
+          code: "12321",
+          time: "2023/02/23 12:02",
+          content: "变压器报警",
+          type: "一般",
         },
         {
-          name: '检测到有人',
-          type: '红外1',
-          createTime: '2024-10-10 12:35:40'
-        }
-      ]
+          code: "12321",
+          time: "2023/02/23 12:02",
+          content: "变压器报警",
+          type: "预警",
+        },
+        {
+          code: "12321",
+          time: "2023/02/23 12:02",
+          content: "变压器报警",
+          type: "预警",
+        },
+        {
+          code: "12321",
+          time: "2023/02/23 12:02",
+          content: "变压器报警",
+          type: "预警",
+        },
+        {
+          code: "12321",
+          time: "2023/02/23 12:02",
+          content: "变压器报警",
+          type: "预警",
+        },
+        {
+          code: "12321",
+          time: "2023/02/23 12:02",
+          content: "变压器报警",
+          type: "预警",
+        },
+      ],
+      page: {
+        pageIndex: 1,
+        pageNun: 10
+      }
 
     }
   },
   components: {
     CusModule,
     BaseChart,
-    vueSeamlessScroll
   },
   computed: {
+    ...mapState('userState', ['areaType']),
     pieOptions () {
-      return {
-        legend: {
-          show: false,
+      return this.getPie3D(this.pieData, 0)// 可做为调整内环大小 0为实心圆饼图,大于0 小于1 为圆环
+    }
+  },
+  watch: {
+    areaType () {
+      this.getPieData()
+    }
+  },
+  mounted () {
+    this.getPieData()
+  },
+  methods: {
+    handleSizeChange () {
+
+    },
+    handleCurrentChange () {
+
+    },
+    getPieData () {
+      const pieData = [
+        {
+          name: '紧急',
+          value: Math.floor(Math.random() * 100),
+          itemStyle: {
+            color: '#FF4949'
+          },
         },
-        tooltip: {
-          trigger: 'item',
-          formatter: (params) => {
-            const {name, value, percent, } = params
-            return `${name} : ${value}个 (${percent}%)`
-          }
+        {
+          name: '严重',
+          value: Math.floor(Math.random() * 100),
+          itemStyle: {
+            color: '#FFBD1F'
+          },
+        },
+        {
+          name: '一般',
+          value: Math.floor(Math.random() * 100),
+          itemStyle: {
+            color: '#1990FF'
+          },
         },
-        color: ["#3FA7FD", "#8AC540", "#F9AF39", "#82D8F9"],
-        series: [
-          {
-            name: "类别统计",
-            type: "pie",
-            radius: ["40%", "55%"],
-            center: ["50%", "39%"],
-            emphasis: {
-              label: {
-                show: true,
-              },
-            },
-            data: [
-              {value: 123, name: "照明设备", },
-              {value: 96, name: "暖通设备"},
-              {value: 43, name: "电气设备"},
-              {value: 21, name: "安防设备"},
-            ],
-            label: {
-              color: "#fff",
-              alignTo: "edge",
-              fontSize: 14,
-              minMargin: 5,
-              edgeDistance: 20,
-              lineHeight: 20,
-              formatter: "{name|{b}}\n{value|{c}个}",
-              rich: {
-                name: {
-                  color: "#B3E3E8",
-                },
-                value: {
-                  color: "#07E3F9",
-                },
-              },
-            },
-            labelLine: {
-              length: 5,
-              length2: 3,
-              smooth: true,
-            },
+        {
+          name: '预警',
+          value: Math.floor(Math.random() * 100),
+          itemStyle: {
+            color: '#A1A2A7'
           },
-        ],
+        }]
+      let totalValue = pieData.reduce((acc, cur) => acc + cur.value, 0);
+      this.pieData = pieData.map(item => ({
+        ...item,
+        proportion: ((item.value / totalValue) * 100).toFixed(2)
+      }))
+    },
+    getParametricEquation (startRatio, endRatio, isSelected, isHovered, k, h) {
+      const midRatio = (startRatio + endRatio) / 2;
+      const startRadian = startRatio * Math.PI * 2;
+      const endRadian = endRatio * Math.PI * 2;
+      const midRadian = midRatio * Math.PI * 2;
+      // 如果只有一个扇形,则不实现选中效果。
+      if (startRatio === 0 && endRatio === 1) {
+        isSelected = false;
       }
-    }
-  },
-  mounted () { },
-  methods: {}
-}
-</script>
-<style lang='scss' scoped>
-@import url("../index.scss");
-
-.grid-container {
-  display: flex;
-  margin-top: 20px;
-  .left-panel {
-    position: relative;
-    text-align: center;
-    margin-left: 20px;
-    width: 111px;
-    background: url('~@/assets/images/home/r1-left_bg.png') no-repeat;
-    background-size: 100% 100%;
+      k = typeof k !== 'undefined' ? k : 1 / 3;
+      const offsetX = isSelected ? Math.cos(midRadian) * 0.1 : 0;
+      const offsetY = isSelected ? Math.sin(midRadian) * 0.1 : 0;
+      // 鼠标滑过时外环放大大小
+      const hoverRate = isHovered ? 1.05 : 1;
+      // 返回曲面参数方程
+      return {
+        u: {
+          min: -Math.PI,
+          max: Math.PI * 3,
+          step: Math.PI / 32,
+        },
 
-    .spinner {
-      position: absolute;
-      animation: spin 10s linear infinite;
-      top: 40px;
-      left: 25px;
-      width: 63px;
-      height: 63px;
-      background-image: url('~@/assets/images/home/r1-top_center.png');
-    }
+        v: {
+          min: 0,
+          max: Math.PI * 2,
+          step: Math.PI / 20,
+        },
 
-    .value-display {
-      margin-top: 10px;
+        x (u, v) {
+          if (u < startRadian) {
+            return offsetX + Math.cos(startRadian) * (1 + Math.cos(v) * k) * hoverRate;
+          }
+          if (u > endRadian) {
+            return offsetX + Math.cos(endRadian) * (1 + Math.cos(v) * k) * hoverRate;
+          }
+          return offsetX + Math.cos(u) * (1 + Math.cos(v) * k) * hoverRate;
+        },
 
-      span.value {
-        font-size: 18px;
-        font-weight: bold;
-      }
-    }
+        y (u, v) {
+          if (u < startRadian) {
+            return offsetY + Math.sin(startRadian) * (1 + Math.cos(v) * k) * hoverRate;
+          }
+          if (u > endRadian) {
+            return offsetY + Math.sin(endRadian) * (1 + Math.cos(v) * k) * hoverRate;
+          }
+          return offsetY + Math.sin(u) * (1 + Math.cos(v) * k) * hoverRate;
+        },
 
-    .description {
-      position: absolute;
-      bottom: 8px;
-      width: 100%;
-      text-align: center;
+        z (u, v) {
+          if (u < -Math.PI * 0.5) {
+            return Math.sin(u);
+          }
+          if (u > Math.PI * 2.5) {
+            return Math.sin(u) * h * 0.1;
+          }
+          // 当前图形的高度是Z根据h(每个value的值决定的)
+          return Math.sin(v) > 0 ? 1 * h * 0.1 : -1;
+        },
+      };
+    },
+    getPie3D (pieData, internalDiameterRatio) {
+      const series = [];
+      let sumValue = 0;
+      let startValue = 0;
+      let endValue = 0;
+      const legendData = [];
+      const k =
+        typeof internalDiameterRatio !== 'undefined'
+          ? (1 - internalDiameterRatio) / (1 + internalDiameterRatio)
+          : 1 / 3;
+      for (let i = 0; i < pieData.length; i += 1) {
+        sumValue += pieData[i].value;
+        const seriesItem = {
+          name: typeof pieData[i].name === 'undefined' ? `series${i}` : pieData[i].name,
+          type: 'surface',
+          parametric: true,
+          wireframe: {
+            show: false,
+          },
+          pieData: pieData[i],
+          pieStatus: {
+            selected: false,
+            hovered: false,
+            k,
+          },
+        };
+        if (typeof pieData[i].itemStyle !== 'undefined') {
+          const {itemStyle} = pieData[i];
+          // eslint-disable-next-line no-unused-expressions
+          typeof pieData[i].itemStyle.color !== 'undefined' ? (itemStyle.color = pieData[i].itemStyle.color) : null;
+          // eslint-disable-next-line no-unused-expressions
+          typeof pieData[i].itemStyle.opacity !== 'undefined'
+            ? (itemStyle.opacity = pieData[i].itemStyle.opacity)
+            : null;
 
-      span.text {
-        color: #B3E3E8;
-        font-size: 14px;
+          seriesItem.itemStyle = itemStyle;
+        }
+        series.push(seriesItem);
       }
-
-      .rate {
-        justify-content: center;
+      for (let i = 0; i < series.length; i += 1) {
+        endValue = startValue + series[i].pieData.value;
+        series[i].pieData.startRatio = startValue / sumValue;
+        series[i].pieData.endRatio = endValue / sumValue;
+        series[i].parametricEquation = this.getParametricEquation(
+          series[i].pieData.startRatio,
+          series[i].pieData.endRatio,
+          false,
+          false,
+          k,
+          10//在此处传入饼图初始高度h
+        );
+        startValue = endValue;
+        legendData.push(series[i].name);
       }
-    }
-  }
-
-  .rate {
-    color: #00C852;
-    font-size: 12px;
-    display: flex;
-    align-items: center;
+      // 准备待返回的配置项,把准备好的series 传入。
+      const option = {
+        legend: {
+          orient: "vertical",
+          right: '8%',
+          top: '22%',
+          textStyle: {
+            color: "#fff",
+            fontSize: 14,
+          },
+          icon: 'circle',
+          formatter: (name) => {
+            if (this.pieData.length) {
+              const item = this.pieData.filter((item) => item.name === name)[0];
+              let str = `${name}(${item.value}) ${item.proportion}%`
+              return str
+            }
+          },
+        },
+        tooltip: {
+          formatter: (params) => {
+            let str = `${params.marker}${params.seriesName}:${this.pieData[params.seriesIndex].value}` + '个,占比:' + `${this.pieData[params.seriesIndex].proportion}` + '%'
+            return str;
 
-    img {
-      margin-left: 3px;
+          },
+        },
+        xAxis3D: {
+          min: -1,
+          max: 1,
+        },
+        yAxis3D: {
+          min: -1,
+          max: 1,
+        },
+        zAxis3D: {
+          min: -1,
+          max: 1,
+        },
+        grid3D: {
+          show: false,
+          boxHeight: 25,//修改立体饼图的高度
+          top: '-10%',
+          left: '-20%',
+          viewControl: {
+            // 3d效果可以放大、旋转等,
+            alpha: 35,//饼图翻转的程度
+            beta: 30,
+            rotateSensitivity: 1,
+            zoomSensitivity: 0,
+            panSensitivity: 0,
+            autoRotate: true,//是否自动旋转
+            distance: 300,//距离越小看到的饼图越大
+          },
+        },
+        series,
+      };
+      return option;
     }
   }
+}
+</script>
+<style lang='scss' scoped>
+@import url("../index.scss");
 
-  .right-panel {
-    padding-left: 20px;
-    display: flex;
-    flex-direction: column;
-    justify-content: space-between;
-
-    .panel-content {
-      width: 200px;
-      height: 75px;
-      color: #B3E3E8;
-      background: url('~@/assets/images/home/l2_item_bg.png') no-repeat;
-      background-size: 100% 100%;
-      display: flex;
-
-      .whitespace-pre {
-        margin-top: 5px;
-        margin-left: 20px;
 
-        span.value {
-          font-size: 18px;
-          font-weight: bold;
-        }
-      }
+.custom-table {
+  position: relative;
 
-      .label {
-        font-size: 14px;
-      }
+  /* 去掉table所有边框 */
+  ::v-deep.el-table--border th.el-table__cell,
+  ::v-deep.el-table td.el-table__cell {
+    border-bottom: 1px solid #204D74;
+  }
 
-      .image-container {
-        width: 70px;
-        display: flex;
-        align-items: center;
-        justify-content: center;
+  ::v-deep .el-table th.is-leaf {
+    /* 去除上边框 */
+    border: none;
+  }
 
-        img {
-          height: 24px;
-          margin-bottom: 5px;
-        }
-      }
-    }
+  ::v-deep.el-table--border .el-table__cell {
+    border-right: none !important;
   }
-}
 
-.equip {
-  display: flex;
-  justify-content: space-between;
-  margin-top: 20px;
-  .equip-item {
-    display: flex;
-    flex-direction: column;
-    align-items: center;
-    background: #1B4A64;
-    color: #B3E3E8;
-    border-radius: 4px;
-    padding: 5px 13px;
-    font-size: 14px;
+  ::v-deep.el-table--group,
+  .el-table--border {
+    border: none !important;
+  }
 
-    >div:first-of-type {
-      span:first-of-type {
-        font-size: 18px;
-        font-weight: bold;
-      }
-    }
+  ::v-deep.el-table::before,
+  .el-table--group::after,
+  .el-table--border::after {
+    background-color: unset !important;
   }
-}
 
-.pie-chart {
-  margin: 30px;
-  height: 201px;
-  background: url("~@/assets/images/device/l1-pie_bg.png") no-repeat;
-  background-position: center;
-}
+  // 去掉el-table的所有背景颜色以及所有hover的颜色
+  ::v-deep.el-table,
+  ::v-deep.el-table .el-table__header-wrapper th,
+  ::v-deep.el-table--border {
+    background-color: transparent;
+    color: #07e3f9;
+  }
 
-.seamless-header {
-  margin-top: 20px;
-  display: flex;
-  align-items: center;
-  justify-content: space-between;
-  padding: 5px 10px;
-  color: #7DBAFF;
-  background: #1B4A64;
-  font-size: 16px;
+  ::v-deep.el-table tr,
+  ::v-deep.el-table__body tr:hover>td {
+    background-color: transparent !important;
+  }
 
-  >div:first-of-type,
-  >div:last-of-type {
-    flex-basis: 35%;
+  ::v-deep .el-table__header-wrapper thead th {
+    background: #1B4B6D !important;
+    color: #07e3f9;
   }
 
-  >div {
-    text-align: center;
+  ::v-deep .el-table__body-wrapper td {
+    color: #B3E3E8;
+    background: #0A2431;
   }
 }
 
-.seamless-warp {
-  overflow: hidden;
-  height: 200px;
+.el-pagination {
+  margin-top: 10px;
+}
 
-  .seamless-item {
-    display: flex;
-    align-items: center;
-    justify-content: space-between;
-    padding: 5px 0;
-    &:nth-child(odd){
-      background: #000;
-    }
-    >div:first-of-type,
-    >div:last-of-type {
-      flex-basis: 38%;
-    }
-    >div {
-      text-align: center;
-      font-size: 13px;
-    }
-  }
+::v-deep .el-pagination__total,
+::v-deep .el-pagination__jump {
+  color: #fff;
 }
 </style>

+ 38 - 65
ems-ui/src/views/largeScreen/home/left.vue

@@ -14,14 +14,14 @@
       </div>
     </CusModule>
     <CusModule class="module-top" title="用能情况">
-      <CusTabs slot="title-right" :tabs="buildingTabs" :active.sync="buildingType" />
+      <CusTabs slot="title-right" :tabs="buildingTabs" :active.sync="buildingType" @tab-click="getBuildingData"/>
       <BaseChart width="100%" height="300px" :option="usePieOptions"></BaseChart>
     </CusModule>
     <CusModule class="module-top" title="储能数据">
       <div class="storage-container">
         <div class="center-spinner"></div>
         <div class="percentage-display">
-          <span class="value">100</span><span class="unit">%</span>
+          <span class="value">{{energy}}</span><span class="unit">%</span>
         </div>
         <div class="charge-status">
           实时充电量
@@ -48,6 +48,7 @@
 import CusTabs from '../components/CusTabs.vue';
 import CusModule from '../components/CusModule.vue';
 import BaseChart from '@/components/BaseChart/index.vue'
+import {mapState} from 'vuex';
 
 export default {
   name: 'HomeLeft',
@@ -83,66 +84,8 @@ export default {
       ],
       buildingType: '1',
       buildingTabs: [{name: '按建筑', value: '1'}, {name: '按设施', value: '2'}],
-      useStorage: [
-        {
-          name: "配电泵房",
-          value: 100
-        },
-        {
-          name: "北区综合楼",
-          value: 500
-        },
-        {
-          name: "南区综合楼",
-          value: 300
-        },
-        {
-          name: "北区加油站",
-          value: 200
-        },
-        {
-          name: "南区加油站",
-          value: 100
-        },
-        {
-          name: "北区停车场",
-          value: 100
-        },
-        {
-          name: "南区停车场",
-          value: 80
-        },
-      ],
-      facStorage: [
-        {
-          name: "北区-供电网",
-          value: 500
-        },
-        {
-          name: "南区-供电网",
-          value: 600
-        },
-        {
-          name: "南区-空调设施",
-          value: 200
-        },
-        {
-          name: "北区-空调设施",
-          value: 400
-        },
-        {
-          name: "南区-公共设施",
-          value: 300
-        },
-        {
-          name: "北区-室外照明",
-          value: 100
-        },
-        {
-          name: "北区-公共设施",
-          value: 80
-        },
-      ],
+      buildingData: [],
+      energy:'100',
       storageData: [
         {
           name: "今日充电",
@@ -177,6 +120,7 @@ export default {
     BaseChart
   },
   computed: {
+    ...mapState('userState', ['areaType']),
     usePieOptions () {
       return {
         calculable: true,
@@ -198,7 +142,7 @@ export default {
             radius: ['10%', '70%'],
             center: ['50%', '50%'],
             roseType: 'area',
-            data:this.buildingType==='1'? this.useStorage:this.facStorage,
+            data: this.buildingData,
             label: {
               color: '#fff',
               formatter: "{b} : {d}%",
@@ -242,13 +186,42 @@ export default {
 
     }
   },
-  mounted () { },
+  watch: {
+    areaType () {
+      this.dateTabClick()
+      this.getBuildingData()
+      this.getStorageData()
+    }
+  },
+  mounted () {
+    this.getBuildingData()
+    this.getStorageData()
+   },
   methods: {
     dateTabClick () {
       this.productionList = this.productionList.map(item => ({
         ...item,
-        value: parseFloat((Math.random() * 100+(Number(this.dateType)*100)).toFixed(1)),
+        value: parseFloat((Math.random() * 100 + (Number(this.dateType) * 100)).toFixed(1)),
       }));
+    },
+    getBuildingData () {
+      const useStorage = ['配电泵房', '北区综合楼', '南区综合楼', '北区加油站', '南区加油站', '北区停车场', '南区停车场']
+      const facStorage = ['北区供电网', '南区供电网', '南区空调设施', '北区空调设施', '南区公共设施', '北区室外照明', '北区公共设施']
+      const fliterName = this.areaType=='1'?'北区':this.areaType=='2'?'南区':''
+      this.buildingData= this.buildingType === '1' ? useStorage.filter(item=>item.includes(fliterName)).map(item => ({
+        name: item,
+        value: Math.floor(Math.random() * 100 + 200)
+      })) : facStorage.filter(item=>item.includes(fliterName)).map(item => ({
+        name: item,
+        value: Math.floor(Math.random() * 100 + 200)
+      }))
+    },
+    getStorageData () {
+      this.energy = Math.floor(Math.random() * 100)
+      this.storageData = this.storageData.map(item => ({
+        ...item,
+        value : Math.floor(Math.random() * 100)
+      }))
     }
   }
 }

+ 65 - 18
ems-ui/src/views/largeScreen/home/right.vue

@@ -5,15 +5,15 @@
         <div class="left-panel">
           <div class="spinner"></div>
           <div class="value-display">
-            <span class="value">2589</span>
-            <span class="unit"></span>
+            <span class="value">{{ useElec.value }}</span>
+            <span class="unit">{{ useElec.unit }}</span>
           </div>
           <div class="description">
             <span class="text">本月用电量</span>
             <div class="rate">
               <span>环比</span>
               <img src="@/assets/images/home/down-arrow.svg" alt="">
-              <span>12%</span>
+              <span>{{ useElec.rate }}%</span>
             </div>
           </div>
         </div>
@@ -23,13 +23,13 @@
               <img src="@/assets/images/home/water.svg" alt="">
             </div>
             <div class="whitespace-pre">
-              <span class="value">989</span>
-              <span class="unit"></span>
+              <span class="value">{{ userWater.value }}</span>
+              <span class="unit">{{ userWater.unit }}</span>
               <div class="label">本月用水量</div>
               <div class="rate">
                 <span>环比</span>
                 <img src="@/assets/images/home/down-arrow.svg" alt="">
-                <span>10%</span>
+                <span>{{ userWater.rate }}%</span>
               </div>
             </div>
           </div>
@@ -38,13 +38,13 @@
               <img src="@/assets/images/home/cost.svg" alt="">
             </div>
             <div class="whitespace-pre">
-              <span class="value">4892</span>
-              <span class="unit"></span>
+              <span class="value">{{ userEnergy.value }}</span>
+              <span class="unit">{{ userEnergy.unit }}</span>
               <div class="label">本月用能费用</div>
               <div class="rate">
                 <span>环比</span>
                 <img src="@/assets/images/home/down-arrow.svg" alt="">
-                <span>9%</span>
+                <span>{{ userEnergy.rate }}%</span>
               </div>
             </div>
           </div>
@@ -82,14 +82,31 @@
 import CusModule from '../components/CusModule.vue';
 import BaseChart from '@/components/BaseChart/index.vue'
 import vueSeamlessScroll from 'vue-seamless-scroll'
+import {mapState} from 'vuex';
 export default {
   name: 'HomeRight',
   data () {
     return {
+      useElec: {
+        value: '2589',
+        unit: '度',
+        rate: '12'
+      },
+      userWater: {
+        value: '989',
+        unit: '吨',
+        rate: '10'
+      },
+      userEnergy: {
+        value: '4892',
+        unit: '元',
+        rate: '9'
+      },
       equipment: [{name: '设备总数', value: '2024', unit: '个', color: '#01A7F0'},
       {name: '在线设备', value: '1800', unit: '个', color: '#B3E3E8'},
       {name: '离线设备', value: '200', unit: '个', color: '#fff'},
       {name: '故障设备', value: '24', unit: '个', color: '#EB808D'}],
+      equipmentPieData: [],
       classOption: {
         step: 0.3, // 数值越大速度滚动越快
         limitMoveNum: 4, // 开始无缝滚动的数据量 this.dataList.length
@@ -141,6 +158,7 @@ export default {
     vueSeamlessScroll
   },
   computed: {
+    ...mapState('userState', ['areaType']),
     pieOptions () {
       return {
         legend: {
@@ -165,12 +183,7 @@ export default {
                 show: true,
               },
             },
-            data: [
-              {value: 123, name: "照明设备", },
-              {value: 96, name: "暖通设备"},
-              {value: 43, name: "电气设备"},
-              {value: 21, name: "安防设备"},
-            ],
+            data: this.equipmentPieData,
             label: {
               color: "#fff",
               alignTo: "edge",
@@ -198,8 +211,37 @@ export default {
       }
     }
   },
-  mounted () { },
-  methods: {}
+  watch: {
+    areaType () {
+      this.getUseInfo()
+      this.getEquipment()
+    }
+  },
+  mounted () {
+    this.getUseInfo()
+    this.getEquipment()
+  },
+  methods: {
+    getUseInfo () {
+      this.useElec.value = Math.floor(Math.random() * 100 + 2000)
+      this.useElec.rate = Math.floor(Math.random() * 10)
+      this.userWater.value = Math.floor(Math.random() * 100 + 1000)
+      this.userWater.rate = Math.floor(Math.random() * 10)
+      this.userEnergy.value = Math.floor(Math.random() * 100 + 4000)
+      this.userEnergy.rate = Math.floor(Math.random() * 10)
+    },
+    getEquipment () {
+      this.equipment = this.equipment.map(item => ({
+        ...item,
+        value: Math.floor(Math.random() * 100)
+      }))
+      const pieData = ['照明设备', '暖通设备', '电气设备', '安防设备']
+      this.equipmentPieData = pieData.map(item => ({
+        name: item,
+        value: Math.floor(Math.random() * 100)
+      }))
+    }
+  }
 }
 </script>
 <style lang='scss' scoped>
@@ -208,6 +250,7 @@ export default {
 .grid-container {
   display: flex;
   margin-top: 20px;
+
   .left-panel {
     position: relative;
     text-align: center;
@@ -310,6 +353,7 @@ export default {
   display: flex;
   justify-content: space-between;
   margin-top: 20px;
+
   .equip-item {
     display: flex;
     flex-direction: column;
@@ -365,13 +409,16 @@ export default {
     align-items: center;
     justify-content: space-between;
     padding: 5px 0;
-    &:nth-child(odd){
+
+    &:nth-child(odd) {
       background: #000;
     }
+
     >div:first-of-type,
     >div:last-of-type {
       flex-basis: 38%;
     }
+
     >div {
       text-align: center;
       font-size: 13px;

+ 17 - 3
ems-ui/src/views/largeScreen/net/left.vue

@@ -24,7 +24,8 @@
 import CusModule from '../components/CusModule.vue';
 import BaseChart from '@/components/BaseChart/index.vue'
 import * as echarts from 'echarts'
-import { dateFormat} from '@/utils'
+import {dateFormat} from '@/utils'
+import {mapState} from 'vuex';
 export default {
   name: 'NetLeft',
   data () {
@@ -55,6 +56,7 @@ export default {
     BaseChart
   },
   computed: {
+    ...mapState('userState', ['areaType']),
     lineOptions () {
       return {
         grid: {
@@ -230,9 +232,13 @@ export default {
       }
     }
   },
+  watch: {
+    areaType () {
+      this.getNetData()
+    }
+  },
   mounted () {
-    this.lineData = this.getDatesOfLastTenDays()
-    this.netlineData =this.getLatestDays()
+    this.getNetData()
    },
   methods: {
     getDatesOfLastTenDays () {
@@ -264,6 +270,14 @@ export default {
         yData: parseFloat(((Math.random() * 100 + 100)).toFixed(1))
       }));
     },
+    getNetData () {
+      this.lineData = this.getDatesOfLastTenDays()
+      this.netlineData = this.getLatestDays()
+      this.energyList = this.energyList.map((item,index) => ({
+        ...item,
+        value:Math.floor(Math.random() * 100+(index+2)*100)
+      }))
+    }
   }
 }
 </script>

+ 13 - 3
ems-ui/src/views/largeScreen/net/right.vue

@@ -28,6 +28,7 @@ import BaseChart from '@/components/BaseChart/index.vue'
 import vueSeamlessScroll from 'vue-seamless-scroll'
 import {dateFormat} from '@/utils';
 import * as echarts from 'echarts'
+import {mapState} from 'vuex';
 export default {
   name: 'NetRight',
   data () {
@@ -55,7 +56,7 @@ export default {
         },
       ],
       barData: [],
-      lineData:[]
+      lineData: []
     }
   },
   components: {
@@ -64,6 +65,7 @@ export default {
     vueSeamlessScroll
   },
   computed: {
+    ...mapState('userState', ['areaType']),
     barOptions () {
       const xData = this.barData.map(item => item.xData)
       const line = this.barData.map(item => item.yData);
@@ -265,9 +267,13 @@ export default {
 
     }
   },
+  watch: {
+    areaType () {
+      this.getNetData()
+    }
+  },
   mounted () {
-    this.barData = this.getMonthsOfLastTenMonths()
-    this.lineData = this.getMonthsOfLastTenMonths()
+    this.getNetData()
   },
   methods: {
     getMonthsOfLastTenMonths () {
@@ -283,6 +289,10 @@ export default {
         xData: item,
         yData: parseFloat(((Math.random() * 100)).toFixed(1)),
       }));
+    },
+    getNetData () {
+      this.barData = this.getMonthsOfLastTenMonths()
+      this.lineData = this.getMonthsOfLastTenMonths()
     }
   }
 }

+ 101 - 40
ems-ui/src/views/largeScreen/soc/left.vue

@@ -4,25 +4,25 @@
       <div class="soc-container">
         <div class="soc-data-point soc-left-data">
           <div>
-            <span class="soc-value">45</span>
+            <span class="soc-value">{{ meterReading.actual }}</span>
             <span class="unit">个</span>
           </div>
           <div class="soc-description">实采数据</div>
         </div>
         <div class="soc-central-data">
-          <span class="soc-value">50</span>
+          <span class="soc-value">{{ meterReading.rate }}</span>
           <span class="unit">%</span>
         </div>
         <div class="soc-data-point soc-right-data">
           <div>
-            <span class="soc-failure">5</span>
+            <span class="soc-failure">{{ meterReading.fail }}</span>
             <span class="soc-failure unit">个</span>
           </div>
           <div class="soc-description">失败数据</div>
         </div>
         <div class="soc-bottom-data">
           <div>
-            <span class="soc-value">50</span>
+            <span class="soc-value">{{ meterReading.total }}</span>
             <span class="unit">个</span>
           </div>
           <div class="soc-description">应采数据</div>
@@ -32,28 +32,6 @@
     <CusModule class="module-top" title="用能情况">
       <div class="soc-pie-chart-container">
         <BaseChart width="100%" height="100%" :option="pieOptions"></BaseChart>
-        <div class="soc-chart-label soc-top-left">
-          <div class="soc-chart-label-text">空调</div>
-          <div>
-            <span class="soc-chart-value">24.5</span>
-            <span class="unit">kW·h</span>
-          </div>
-        </div>
-        <div class="soc-chart-label soc-top-right">
-          <div class="soc-chart-label-text">照明</div>
-          <span class="soc-chart-value">26.7</span>
-          <span class="unit">kW·h</span>
-        </div>
-        <div class="soc-chart-label soc-bottom-left">
-          <div class="soc-chart-label-text">电梯</div>
-          <span class="soc-chart-value">25.5</span>
-          <span class="unit">kW·h</span>
-        </div>
-        <div class="soc-chart-label soc-bottom-right">
-          <div class="soc-chart-label-text">其他</div>
-          <span class="soc-chart-value">23.3</span>
-          <span class="unit">kW·h</span>
-        </div>
       </div>
 
     </CusModule>
@@ -67,11 +45,24 @@ import CusModule from '../components/CusModule.vue';
 import BaseChart from '@/components/BaseChart/index.vue'
 import {dateFormat} from '@/utils';
 import * as echarts from 'echarts'
+import {mapState} from 'vuex';
 export default {
   name: 'SocLeft',
   data () {
     return {
-      lineData:[]
+      lineData: [],
+      meterReading: {
+        total: '50',
+        actual: '45',
+        fail: '5',
+        rate: '90'
+      },
+      energyUse: [
+        {value: 123, name: "空调", },
+        {value: 96, name: "照明"},
+        {value: 43, name: "电梯"},
+        {value: 21, name: "其他"},
+      ]
     };
   },
   components: {
@@ -79,6 +70,7 @@ export default {
     BaseChart
   },
   computed: {
+    ...mapState('userState', ['areaType']),
     pieOptions () {
       return {
         legend: {
@@ -86,7 +78,7 @@ export default {
         },
         color: ["#3FA7FD", "#8AC540", "#F9AF39", "#82D8F9"],
         grid: {
-          top:'20%'
+          top: '20%'
         },
         series: [
           {
@@ -94,15 +86,50 @@ export default {
             type: "pie",
             radius: ["40%", "55%"],
             center: ["50%", "50%"],
-            data: [
-              {value: 123, name: "照明设备", },
-              {value: 96, name: "暖通设备"},
-              {value: 43, name: "电气设备"},
-              {value: 21, name: "安防设备"},
-            ],
+            data: this.energyUse,
             label: {
-              show:false,
+              normal: {
+                show: true,
+                formatter: [
+                  '{b|{b}}',
+                  '{c|{c}}{b|kW·h}',
+                  '{d|{d}%}'
+                ].join('\n'), // 用\n来换行
+                rich: {
+                  b: {
+                    color: '#fff',
+                    fontSize: 13,
+                    lineHeight: 20,
+                    align: 'left'
+                  },
+                  c: {
+                    fontSize: 18,
+                    fontWeight: 'bold',
+                    color: '#06E3F9',
+                    textShadowColor: '#1c90a6',
+                    textShadowOffsetX: 0,
+                    textShadowOffsetY: 2,
+                    textShadowBlur: 5
+                  },
+                  d: {
+                    color: '#fff',
+                    align: 'left',
+                    fontSize: 12
+                  }
+                }
+              }
             },
+            labelLine: {
+              normal: {
+                length: 10,
+                length2: 30,
+                smooth: true,
+                lineStyle: {
+                  width: 1,
+                  color: 'rgba(255,255,255,0.7)'
+                }
+              }
+            }
           },
         ],
       }
@@ -128,7 +155,7 @@ export default {
           splitLine: {
             show: false,
           },
-          data: this.lineData.map(item=>item.xData),
+          data: this.lineData.map(item => item.xData),
         },
         series: [
           {
@@ -161,14 +188,21 @@ export default {
                 shadowBlur: 20 //shadowBlur设图形阴影的模糊大小。配合shadowColor,shadowOffsetX/Y, 设置图形的阴影效果。
               }
             },
-            data: this.lineData.map(item=>item.yData),
+            data: this.lineData.map(item => item.yData),
           },
         ],
       }
     }
   },
+  watch: {
+    areaType () {
+      this.lineData = this.getDatesOfLastTenDays()
+      this.getMeterReading()
+    }
+  },
   mounted () {
     this.lineData = this.getDatesOfLastTenDays()
+    this.getMeterReading()
   },
   methods: {
     getDatesOfLastTenDays () {
@@ -185,7 +219,28 @@ export default {
         yData: parseFloat(((Math.random() * 100 + 100)).toFixed(1))
       }));
     },
-
+    getMeterReading () {
+      if (this.areaType == '') {
+        this.meterReading.total=120
+        this.meterReading.actual=105
+        this.meterReading.fail=15
+        this.meterReading.rate=87.5
+      } else if (this.areaType == '1') {
+        this.meterReading.total=65
+        this.meterReading.actual=54
+        this.meterReading.fail=9
+        this.meterReading.rate=83.1
+      } else if (this.areaType == '2') {
+        this.meterReading.total=55
+        this.meterReading.actual=49
+        this.meterReading.fail=6
+        this.meterReading.rate=89.1
+      }
+      this.energyUse = this.energyUse.map(item => ({
+        ...item,
+        value:parseFloat(((Math.random() * 100 + 100)).toFixed(1))
+      }))
+    }
   }
 }
 </script>
@@ -272,9 +327,11 @@ export default {
   padding-right: 17px;
   position: relative;
   background-image: url('~@/assets/images/soc/l2-pie_bg.png');
+
   .soc-chart-label {
     position: absolute;
     text-align: center;
+
     .soc-chart-label-text {
       color: #B3E3E8;
       font-size: 14px;
@@ -286,20 +343,24 @@ export default {
       color: #06E3F9;
     }
   }
+
   .soc-top-left {
     top: 12px;
     left: 20px;
   }
+
   .soc-top-right {
     top: 12px;
     right: 35px;
   }
+
   .soc-bottom-left {
-    bottom:32px;
+    bottom: 32px;
     left: 20px;
   }
+
   .soc-bottom-right {
-    bottom:32px;
+    bottom: 32px;
     right: 35px;
   }
 }

+ 20 - 58
ems-ui/src/views/largeScreen/soc/right.vue

@@ -42,8 +42,9 @@ import CusProgress from '../components/CusProgress.vue';
 import BaseChart from '@/components/BaseChart/index.vue'
 import * as echarts from 'echarts'
 import {dateFormat} from '@/utils'
+import {mapState} from 'vuex';
 export default {
-  name: 'HomeRight',
+  name: 'SocRight',
   data () {
     return {
       socList: [
@@ -103,62 +104,7 @@ export default {
     BaseChart,
   },
   computed: {
-    pieOptions () {
-      return {
-        legend: {
-          show: false,
-        },
-        tooltip: {
-          trigger: 'item',
-          formatter: (params) => {
-            const {name, value, percent, } = params
-            return `${name} : ${value}个 (${percent}%)`
-          }
-        },
-        color: ["#3FA7FD", "#8AC540", "#F9AF39", "#82D8F9"],
-        series: [
-          {
-            name: "类别统计",
-            type: "pie",
-            radius: ["40%", "55%"],
-            center: ["50%", "39%"],
-            emphasis: {
-              label: {
-                show: true,
-              },
-            },
-            data: [
-              {value: 123, name: "照明设备", },
-              {value: 96, name: "暖通设备"},
-              {value: 43, name: "电气设备"},
-              {value: 21, name: "安防设备"},
-            ],
-            label: {
-              color: "#fff",
-              alignTo: "edge",
-              fontSize: 14,
-              minMargin: 5,
-              edgeDistance: 20,
-              lineHeight: 20,
-              formatter: "{name|{b}}\n{value|{c}个}",
-              rich: {
-                name: {
-                  color: "#B3E3E8",
-                },
-                value: {
-                  color: "#07E3F9",
-                },
-              },
-            },
-            labelLine: {
-              length: 5,
-              length2: 3,
-              smooth: true,
-            },
-          },
-        ],
-      }
-    },
+    ...mapState('userState', ['areaType']),
     lineOptions () {
       return {
         grid: {
@@ -296,8 +242,13 @@ export default {
       }
     }
   },
+  watch: {
+    areaType () {
+      this.getSocData()
+    }
+  },
   mounted () {
-    this.lineData = this.getDatesOfLastTenDays()
+    this.getSocData()
   },
   methods: {
     getDatesOfLastTenDays () {
@@ -315,6 +266,17 @@ export default {
         yData2: parseFloat(((Math.random() * 100 + 100)).toFixed(1))
       }));
     },
+    getSocData () {
+      this.lineData = this.getDatesOfLastTenDays()
+      this.socList = this.socList.map((item,index) => ({
+        ...item,
+        value:Math.floor(Math.random() * 100+ (index+1)*100)
+      }))
+      this.ranking = this.ranking.map((item,index) => ({
+        ...item,
+        value:Math.floor(Math.random() * 100 + (index+1)*100)
+      })).reverse();
+    }
   }
 }
 </script>

+ 22 - 3
ems-ui/src/views/largeScreen/source/left.vue

@@ -3,7 +3,7 @@
     <CusModule title="光伏发电量">
       <div class="elec-top-bar">
         <span class="elec-content">
-          今日发电量<span class="elec-value">321</span><span class="unit"> kW·h</span>
+          今日发电量<span class="elec-value">{{todayEnergy}}</span><span class="unit"> kW·h</span>
         </span>
       </div>
       <div class="elec-items-container">
@@ -16,8 +16,6 @@
             {{ i.name }}
           </div>
         </div>
-        <div></div>
-        <div></div>
       </div>
     </CusModule>
     <CusModule class="module-top" title="光伏发电指标">
@@ -43,11 +41,13 @@
 import CusModule from '../components/CusModule.vue';
 import BaseChart from '@/components/BaseChart/index.vue'
 import {dateFormat} from '@/utils';
+import {mapState} from 'vuex';
 import * as echarts from 'echarts'
 export default {
   name: 'SourceLeft',
   data () {
     return {
+      todayEnergy:'321',
       elecList: [
         {
           name: "本月发电量",
@@ -98,6 +98,7 @@ export default {
     BaseChart
   },
   computed: {
+    ...mapState('userState', ['areaType']),
     lineOptions () {
       return {
         legend: {
@@ -158,8 +159,15 @@ export default {
       }
     }
   },
+  watch: {
+    areaType () {
+      this.getElecData()
+      this.lineData = this.getDatesOfLastTenDays()
+    }
+  },
   mounted () {
     this.lineData = this.getDatesOfLastTenDays()
+    this.getElecData()
   },
   methods: {
     getDatesOfLastTenDays () {
@@ -176,6 +184,17 @@ export default {
         yData: parseFloat(((Math.random() * 100 + 100)).toFixed(1))
       }));
     },
+    getElecData () {
+      this.todayEnergy = Math.floor(Math.random() * 100 + 300)
+      this.elecList = this.elecList.map((item,index) => ({
+        ...item,
+        value:Math.floor(Math.random() * 100 + 900*(index+1))
+      }))
+      this.elecIndexList = this.elecIndexList.map(item => ({
+        ...item,
+        value:parseFloat(Math.random() * 100).toFixed(1)
+      }))
+    }
 
   }
 }

+ 23 - 4
ems-ui/src/views/largeScreen/source/right.vue

@@ -17,15 +17,15 @@
     <CusModule class="module-top" title="节能减排(今年)">
       <div class="energy">
         <div class="energy-item">
-          <div class="energy-item-value">721.1</div>
+          <div class="energy-item-value">{{reduce.coal}}</div>
           <div class="energy-item-name">标煤当量(吨)</div>
         </div>
         <div class="energy-item">
-          <div class="energy-item-value">2276.8</div>
+          <div class="energy-item-value">{{reduce.co2}}</div>
           <div class="energy-item-name">CO2当量(吨)</div>
         </div>
         <div class="energy-item">
-          <div class="energy-item-value">1210</div>
+          <div class="energy-item-value">{{reduce.tree}}</div>
           <div class="energy-item-name">植树当量(棵)</div>
         </div>
       </div>
@@ -41,11 +41,17 @@ import BaseChart from '@/components/BaseChart/index.vue'
 import vueSeamlessScroll from 'vue-seamless-scroll'
 import {dateFormat} from '@/utils';
 import * as echarts from 'echarts'
+import {mapState} from 'vuex';
 export default {
   name: 'SourceRight',
   data () {
     return {
-      lineData:[],
+      lineData: [],
+      reduce: {
+        coal: '',
+        co2: '',
+        tree:''
+      },
       classOption: {
         step: 0.3, // 数值越大速度滚动越快
         limitMoveNum: 4, // 开始无缝滚动的数据量 this.dataList.length
@@ -97,6 +103,7 @@ export default {
     vueSeamlessScroll
   },
   computed: {
+    ...mapState('userState', ['areaType']),
     lineOptions () {
       return {
         legend: {
@@ -157,8 +164,15 @@ export default {
       }
     }
   },
+  watch: {
+    areaType () {
+      this.lineData = this.getDatesOfLastTenDays()
+      this.getReduceData()
+    }
+  },
   mounted () {
     this.lineData = this.getDatesOfLastTenDays()
+    this.getReduceData()
   },
   methods: {
     getDatesOfLastTenDays () {
@@ -175,6 +189,11 @@ export default {
         yData: parseFloat(((Math.random() * 100 + 100)).toFixed(1))
       }));
     },
+    getReduceData () {
+      this.reduce.coal =parseFloat(((Math.random() * 100 + 500)).toFixed(1))
+      this.reduce.co2 =parseFloat(((Math.random() * 100 + 600)).toFixed(1))
+      this.reduce.tree =Math.floor(Math.random() * 100 + 1000)
+    }
   }
 }
 </script>

+ 48 - 0
ems-ui/src/views/largeScreen/test.vue

@@ -0,0 +1,48 @@
+<template>
+  <div style="min-height: 580px;">
+    <el-table :data="papers" style="width: 100%;">
+      <el-table-column :label="`${$t('print.paperSize')} (mm)`">
+        <template #default="{ row }">
+          {{ row.paperNo + ' - ' + row.width + ' * ' + row.height }}
+        </template>
+      </el-table-column>
+      <el-table-column :label="`${$t('print.printer')}`">
+        <template #default="{ row }">
+          <el-select style="width: 300px" v-model="row.printer">
+            <el-option
+              v-for="printer in printers"
+              :key="printer.label"
+              :label="printer.label"
+              :value="printer.value">
+            </el-option>
+          </el-select>
+        </template>
+      </el-table-column>
+    </el-table>
+  </div>
+</template>
+
+<script>
+export default {
+  data() {
+    return {
+      papers: [
+        // 示例数据
+        { paperNo: 'A4', width: 210, height: 297, printer: '' },
+        // 更多paper对象...
+      ],
+      printers: [
+        // 打印机选项
+        { label: 'Printer 1', value: 'printer1' },
+        { label: 'Printer 2', value: 'printer2' },
+        // 更多打印机...
+      ]
+    };
+  },
+  methods: {
+    $t (val) {
+      return val==='print.paperSize'?'纸张尺寸':'打印机'
+    }
+  }
+}
+</script>