ソースを参照

会议管理图表转换逻辑

Bella 2 年 前
コミット
fa1855b797

+ 28 - 20
src/components/common/timeRange.vue

@@ -1,7 +1,10 @@
 <template>
-  <a-range-picker v-if="show" :default-value="[defaultStartTime,defaultEndTime]" :showTime="showTime"
-                  :format="timeFormat"
-                  @change="change"
+  <a-range-picker
+    v-if="show"
+    :default-value="[defaultStartTime, defaultEndTime]"
+    :showTime="showTime"
+    :format="timeFormat"
+    @change="change"
   />
 </template>
 
@@ -12,47 +15,52 @@ export default {
       show: false,
       defaultStartTime: null,
       defaultEndTime: null,
-    }
+    };
   },
   props: {
     showTime: Object,
     timeFormat: {
       type: String,
-      default: "YYYY/MM/DD"
+      default: "YYYY/MM/DD",
     },
     timeRange: Object,
   },
-  created() {
-
-  },
+  created() {},
   mounted() {
-    this.$nextTick(()=>{
+    this.$nextTick(() => {
       if (this.timeRange) {
         if (this.timeRange.startDate) {
-          this.defaultStartTime = this.$moment(this.timeRange.startDate, this.timeFormat)
+          console.log("this.timeRange.startDate", this.timeRange.startDate);
+          this.defaultStartTime = this.$moment(
+            this.timeRange.startDate,
+            this.timeFormat
+          );
         }
         if (this.timeRange.endDate) {
-          this.defaultEndTime = this.$moment(this.timeRange.endDate, this.timeFormat)
+          this.defaultEndTime = this.$moment(
+            this.timeRange.endDate,
+            this.timeFormat
+          );
         }
       }
-      this.show = true
-    })
+      this.show = true;
+    });
   },
-  emits: ['update:timeRange'],
+  emits: ["update:timeRange"],
   setup(props, context) {
     const methods = {
       updateTimeRange(obj) {
-        context.emit('update:timeRange', obj)
+        context.emit("update:timeRange", obj);
       },
-    }
-    return methods
+    };
+    return methods;
   },
   methods: {
     change(date, dateStr) {
       let obj = {
         startDate: dateStr[0],
-        endDate: dateStr[1]
-      }
+        endDate: dateStr[1],
+      };
       this.updateTimeRange(obj);
     },
     range(start, end) {
@@ -92,4 +100,4 @@ export default {
 };
 </script>
 
-<style></style>
+<style></style>

+ 16 - 3
src/components/scene/meeting/chart/meetingTimeCharts.vue

@@ -3,6 +3,9 @@
 </template>
 
 <script>
+/**
+ * 楼层选择全部时展示的图标
+ */
 import apiSceneMeeting from "@/api/scene/meeting/apiSceneMeeting";
 
 export default {
@@ -18,7 +21,15 @@ export default {
           containLabel: true,
           //grid区域是否包含坐标轴的刻度标签
         },
-        legend: {},
+        legend: {
+          align: "left",
+          top: "5%",
+          //itemWidth: 30,
+          //itemHeight: 10,
+          formatter: (name) => {
+            return `{a|${name}} `;
+          },
+        },
         xAxis: {
           type: "category",
           data: [
@@ -38,7 +49,7 @@ export default {
         },
         yAxis: [
           {
-            name: "使用时长(分钟)",
+            name: "使用时长(h)",
             type: "value",
             nameTextStyle: {
               padding: [0, 20, 0, 0],
@@ -108,10 +119,12 @@ export default {
     },
     getData() {
       this.loading = true;
+      console.log(this.queryData.timeRange, "会议开始和结束时间");
       return apiSceneMeeting
         .getMeetingMinutes(this.queryData.timeRange)
         .then((res) => {
-          let data = this.$util.dataUtil.covertDataToEcharts(res, ["times"]);
+          let data = this.$util.dataUtil.covertDataToEcharts(res, ["minutes"]);
+          // console.log(data, "会议时间");
           this.$util.dataUtil.refreshEchartsData(this.chart, this.option, data);
           this.loading = false;
         })

+ 139 - 0
src/components/scene/meeting/chart/meetingTimeFloorCharts.vue

@@ -0,0 +1,139 @@
+<template>
+  <div class="myChart" ref="myChart" :style="{ height: height + 'px' }"></div>
+</template>
+
+<script>
+/**
+ * 楼层选择具体楼层时展示的图表
+ */
+import apiSceneMeeting from "@/api/scene/meeting/apiSceneMeeting";
+
+export default {
+  data() {
+    return {
+      option: {
+        color: ["#80B2FF", "#FFDF80"],
+        grid: {
+          left: "2%", //默认10%
+          right: "2%", //默认10%
+          bottom: "0%", //默认60
+          top: "15%",
+          containLabel: true,
+          //grid区域是否包含坐标轴的刻度标签
+        },
+        legend: {
+          align: "left",
+          top: "5%",
+          //itemWidth: 30,
+          //itemHeight: 10,
+          formatter: (name) => {
+            return `{a|${name}} `;
+          },
+        },
+        xAxis: {
+          type: "category",
+          data: [
+            "4月1日",
+            "4月2日",
+            "4月3日",
+            "4月4日",
+            "4月5日",
+            "4月6日",
+            "4月7日",
+            "4月8日",
+            "4月9日",
+            "4月10日",
+            "4月11日",
+            "4月12日",
+          ],
+        },
+        yAxis: [
+          {
+            name: "使用时长(h)",
+            type: "value",
+            nameTextStyle: {
+              padding: [0, 20, 0, 0],
+            },
+            splitLine: {
+              show: true,
+              lineStyle: {
+                color: "#e8e8e8",
+              },
+            },
+            axisLine: {
+              show: true,
+              lineStyle: {
+                color: "#233653",
+              },
+            },
+          },
+        ],
+        tooltip: {
+          trigger: "axis",
+          axisPointer: {
+            type: "shadow",
+          },
+          textStyle: {
+            color: "#fff",
+            align: "left",
+            fontSize: 14,
+          },
+          axisLine: {
+            //x坐标轴轴线
+            show: true,
+            lineStyle: {
+              //x坐标轴轴线样式
+              color: "#000", //'#ccc' | 'rgb(128, 128, 128)' | 'rgba(128, 128, 128, 0.5)',设置标签颜色
+            },
+          },
+          backgroundColor: "rgba(0,0,0,0.8)",
+        },
+        series: [
+          {
+            data: [32, 39, 54, 55, 101, 76, 60, 42, 36, 57, 40, 85],
+            type: "bar",
+            stack: "A",
+            barWidth: "30px",
+            backgroundStyle: {
+              color: "rgba(180, 180, 180, 0.2)",
+            },
+          },
+        ],
+      },
+    };
+  },
+  props: {
+    height: Number,
+    queryData: Object,
+  },
+  mounted() {
+    this.init();
+  },
+  methods: {
+    init() {
+      let chart = this.$echarts.init(this.$refs.myChart);
+      this.chart = chart;
+      this.$util.chartsResize(this.chart);
+      chart.setOption(this.option);
+      this.$store.loadingStore().loadingWithApi(this.getData());
+    },
+    getData() {
+      this.loading = true;
+      console.log(this.queryData.timeRange, "会议开始和结束时间");
+      return apiSceneMeeting
+        .getMeetingMinutes(this.queryData.timeRange)
+        .then((res) => {
+          let data = this.$util.dataUtil.covertDataToEcharts(res, ["minutes"]);
+          console.log(data, "会议时间");
+          this.$util.dataUtil.refreshEchartsData(this.chart, this.option, data);
+          this.loading = false;
+        })
+        .catch((err) => {
+          this.loading = false;
+        });
+    },
+  },
+};
+</script>
+
+<style lang="less" scoped></style>

+ 78 - 13
src/components/work/meeting/workMeeting.vue

@@ -24,7 +24,7 @@
       <a-row>
         <a-col :span="24">
           <div class="workMeeting-left ioc-card-content">
-            <card title="会议分析">
+            <card title="会议分析" v-show="chartShow.timeline">
               <a-row>
                 <a-col :span="2">
                   <a-menu
@@ -205,9 +205,23 @@
                 </a-descriptions>
               </div>
             </card>
+            <card v-show="chartShow.usageAllPanel">
+              <MeetingTimeCharts
+                :height="300"
+                :queryData="queryData"
+                ref="meetingTimeRef"
+              ></MeetingTimeCharts>
+            </card>
+            <card v-show="chartShow.usageFloorPanel">
+              <MeetingTimeFloorCharts
+                :height="300"
+                :queryData="queryData"
+                ref="meetingTimeFloorRef"
+              ></MeetingTimeFloorCharts>
+            </card>
           </div>
         </a-col>
-        <a-col :span="24" style="margin-top:12px;">
+        <a-col :span="24" style="margin-top: 12px">
           <div class="workMeeting-right ioc-card-content">
             <card title="成本趋势" moduleType="智慧办公" mainTitleSize="20px">
               <template #sub-title>
@@ -225,16 +239,19 @@
             </card>
           </div>
         </a-col>
-        <a-col :span="24" style="margin-top:12px;">
+        <!-- <a-col :span="24" style="margin-top: 12px">
           <div
             class="workMeeting-left ioc-card-content"
             style="margin-bottom: 15px"
           >
             <card>
-              <MeetingTimeCharts :height="300"></MeetingTimeCharts>
+              <MeetingTimeCharts
+                :height="300"
+                :queryData="queryData"
+              ></MeetingTimeCharts>
             </card>
           </div>
-        </a-col>
+        </a-col> -->
       </a-row>
     </div>
   </div>
@@ -245,7 +262,7 @@ import card from "@/components/common/card.vue";
 import timeline from "@/components/common/timeLine.vue";
 import WorkMeetingCostTrend from "@/components/work/meeting/component/workMeetingCostTrend.vue";
 import MeetingTimeCharts from "@/components/scene/meeting/chart/meetingTimeCharts.vue";
-
+import MeetingTimeFloorCharts from "@/components/scene/meeting/chart/meetingTimeFloorCharts.vue";
 import apiWorkMeeting from "@/api/work/apiWorkMeeting";
 
 export default {
@@ -255,6 +272,7 @@ export default {
     timeline,
     WorkMeetingCostTrend,
     MeetingTimeCharts,
+    MeetingTimeFloorCharts,
   },
   data() {
     let timeRange = this.$util.dateUtil.getNearlyMonthRange();
@@ -440,14 +458,18 @@ export default {
       },
       meetingInfo: {},
       currMeeting: {},
+      chartShow: {
+        timeLine: false,
+        usageFloorPanel: false,
+        usageAllPanel: false,
+      },
     };
   },
   mounted() {
-    //this.changeTab(1);
     this.init();
     this.setDate();
-    this.getMeetingRecordData();
   },
+  watch: {},
   methods: {
     init() {
       this.$store.loadingStore().loadingWithApi(this.getCoreData(), 2000);
@@ -472,13 +494,55 @@ export default {
     },
     reset() {},
     search() {
-      this.$util.asyncPromise(
-        this.getCoreData(),
-        this.$refs.WorkMeetingCostTrend.getData(),
-        this.getMeetingRecordData()
-      );
+      // 楼层选全部时展示使用时长面板
+      if (this.queryData.floorId === "0") {
+        this.chartShow.timeLine = false;
+        this.chartShow.usageAllPanel = true;
+        this.chartShow.usageFloorPanel = false;
+        console.log("楼层选全部");
+        this.$nextTick(() => {
+          this.$util.asyncPromise(
+            this.getCoreData(),
+            this.$refs.WorkMeetingCostTrend.getData(),
+            this.$refs.meetingTimeRef.getData()
+            // this.getMeetingRecordData()
+          );
+        });
+      } else {
+        let start = this.$moment(this.queryData.timeRange.startDate);
+        let end = this.$moment(this.queryData.timeRange.endDate);
+        let diff = end.diff(start, "days");
+        if (diff > 1) {
+          this.chartShow.timeLine = false;
+          this.chartShow.usageFloorPanel = true;
+          this.chartShow.usageAllPanel = false;
+          console.log("楼层选具体楼层 --时间差大于一天 ");
+          this.$nextTick(() => {
+            this.$util.asyncPromise(
+              this.getCoreData(),
+              this.$refs.WorkMeetingCostTrend.getData(),
+              this.$refs.meetingTimeFloorRef.getData()
+              // this.getMeetingRecordData()
+            );
+          });
+        } else {
+          this.chartShow.timeLine = true;
+          this.chartShow.usageAllPanel = false;
+          this.chartShow.usageFloorPanel = false;
+          console.log("楼层选具体楼层 -- 时间差小于或等于一天");
+          this.$util.asyncPromise(
+            this.getCoreData(),
+            this.$refs.WorkMeetingCostTrend.getData(),
+            this.getMeetingRecordData()
+          );
+        }
+        // 楼层选择具体楼层时 -- 起止时间差大于一天
+        // 楼层选择具体楼层时,起止时间差小于一天
+      }
     },
+    // 会议记录
     getMeetingRecordData() {
+      debugger
       this.showMeetingLine = false;
       let params = {};
       Object.assign(params, this.queryData);
@@ -512,6 +576,7 @@ export default {
     //changeTab(index) {
     //  this.tabsItemArr = this.tabsArr[index].content;
     //},
+    // 核心指标
     getCoreData() {
       return apiWorkMeeting.getCoreData(this.queryData).then((res) => {
         this.coreData[0].num = res.list[0].value;

+ 192 - 193
src/utils/dataUtil.js

@@ -1,219 +1,218 @@
 import constant from "@/utils/constant";
 
 const covertDataToEcharts = (obj, params) => {
-    let res = {
-        label: []
-    };
-    for (let i = 0; i < params.length; i++) {
-        res[params[i]] = [];
-    }
-    if (obj) {
-        obj.forEach(item => {
-            res.label.push(item.label);
-            if (!item.jsonObject) {
-                for (let i = 0; i < params.length; i++) {
-                    res[params[i]].push('');
-                }
-                return;
-            }
-            for (let i = 0; i < params.length; i++) {
-                res[params[i]].push(item.jsonObject[params[i]]);
-            }
-        })
-    }
-    return res;
-}
+  let res = {
+    label: [],
+  };
+  for (let i = 0; i < params.length; i++) {
+    res[params[i]] = [];
+  }
+  if (obj) {
+    obj.forEach((item) => {
+      res.label.push(item.label);
+      if (!item.jsonObject) {
+        for (let i = 0; i < params.length; i++) {
+          res[params[i]].push("");
+        }
+        return;
+      }
+      for (let i = 0; i < params.length; i++) {
+        res[params[i]].push(item.jsonObject[params[i]]);
+      }
+    });
+  }
+  return res;
+};
 
 const refreshEchartsData = (instance, option, data) => {
-    option.xAxis.data = data.label;
-    let arr = [];
-    for (const key in data) {
-        if (key == 'label') {
-            continue;
-        }
-        arr.push(data[key])
+  option.xAxis.data = data.label;
+  let arr = [];
+  for (const key in data) {
+    if (key == "label") {
+      continue;
     }
-    option.color = constant.echartsColors;
-    let stackMap = new Map();
-    let barNum = {};
-    for (let i = 0; i < option.series.length; i++) {
-        if (option.series[i].type=='bar') {
-            let stack1 = option.series[i].stack;
-            if (stack1) {
-                barNum[stack1] = i;
-            } else {
-                barNum['index'+i] = i
-            }
-
-        }
-        option.series[i].data = arr[i];
-        option.series[i].smooth = true;
-        option.series[i].showSymbol = false;
-        if (option.series[i].areaStyle && i <= constant.echartsGradientColors.length) {
-            option.series[i].areaStyle = {
-                color: constant.echartsGradientColors[i]
-            }
-        }
-
-        let stack = option.series[i].stack;
-        let index = option.series[i].yAxisIndex ? option.series[i].yAxisIndex : 0;
-        if (stack) {
-            let key = stack + "---" + index;
-            if (!stackMap.has(key)) {
-                stackMap.set(key, []);
-            }
-            stackMap.get(key).push(arr[i])
-        } else {
-            let obj = getInterval(arr[i]);
-            let yAxis = option.yAxis[index];
-            if (!yAxis.max || yAxis.max < obj.max) {
-                Object.assign(option.yAxis[index], obj)
-            }
-        }
+    arr.push(data[key]);
+  }
+  option.color = constant.echartsColors;
+  let stackMap = new Map();
+  let barNum = {};
+  for (let i = 0; i < option.series.length; i++) {
+    if (option.series[i].type == "bar") {
+      let stack1 = option.series[i].stack;
+      if (stack1) {
+        barNum[stack1] = i;
+      } else {
+        barNum["index" + i] = i;
+      }
     }
-    for (const barNumKey in barNum) {
-        option.series[barNum[barNumKey]].itemStyle = {
-            barBorderRadius: [5, 5, 0, 0]
-        };
+    option.series[i].data = arr[i];
+    option.series[i].smooth = true;
+    option.series[i].showSymbol = false;
+    if (
+      option.series[i].areaStyle &&
+      i <= constant.echartsGradientColors.length
+    ) {
+      option.series[i].areaStyle = {
+        color: constant.echartsGradientColors[i],
+      };
     }
 
-    stackMap = dealStackInterval(stackMap);
-    stackMap.forEach((value, key, map) => {
-        let index = key.split("---")[1];
-        let obj = getInterval(value);
-        let yAxis = option.yAxis[index];
-        if (!yAxis.max || yAxis.max < obj.max) {
-            Object.assign(option.yAxis[index], obj)
-        }
-    });
-    option.textStyle = {
-        fontSize: '12px',
-        fontFamily: "PingFangSC-Regular, serif",
-        color: '#757575'
-    };
-    if (!option.legend) {
-        option.legend = {};
+    let stack = option.series[i].stack;
+    let index = option.series[i].yAxisIndex ? option.series[i].yAxisIndex : 0;
+    if (stack) {
+      let key = stack + "---" + index;
+      if (!stackMap.has(key)) {
+        stackMap.set(key, []);
+      }
+      stackMap.get(key).push(arr[i]);
+    } else {
+      let obj = getInterval(arr[i]);
+      let yAxis = option.yAxis[index];
+      if (!yAxis.max || yAxis.max < obj.max) {
+        Object.assign(option.yAxis[index], obj);
+      }
     }
-    option.legend.textStyle = {
-        fontSize: '12px',
-        fontFamily: "Microsoft YaHei, PingFangSC-Regular, serif",
-        color: '#757575'
+  }
+  for (const barNumKey in barNum) {
+    option.series[barNum[barNumKey]].itemStyle = {
+      barBorderRadius: [5, 5, 0, 0],
     };
-    if (option.yAxis && option.yAxis.length>0) {
-        for (let i = 0; i < option.yAxis.length; i++) {
-            option.yAxis[i]['axisLine']={
-                show: true
-            }
-            option.yAxis[i]['axisTick']={
-                show: true
-            }
-        }
+  }
+
+  stackMap = dealStackInterval(stackMap);
+  stackMap.forEach((value, key, map) => {
+    let index = key.split("---")[1];
+    let obj = getInterval(value);
+    let yAxis = option.yAxis[index];
+    if (!yAxis.max || yAxis.max < obj.max) {
+      Object.assign(option.yAxis[index], obj);
     }
-    instance.setOption(option)
-}
+  });
+  option.textStyle = {
+    fontSize: "12px",
+    fontFamily: "PingFangSC-Regular, serif",
+    color: "#757575",
+  };
+  if (!option.legend) {
+    option.legend = {};
+  }
+  option.legend.textStyle = {
+    fontSize: "12px",
+    fontFamily: "Microsoft YaHei, PingFangSC-Regular, serif",
+    color: "#757575",
+  };
+  if (option.yAxis && option.yAxis.length > 0) {
+    for (let i = 0; i < option.yAxis.length; i++) {
+      option.yAxis[i]["axisLine"] = {
+        show: true,
+      };
+      option.yAxis[i]["axisTick"] = {
+        show: true,
+      };
+    }
+  }
+  instance.setOption(option);
+};
 
 const dealStackInterval = (stackMap) => {
-    let indexMap = new Map();
-    stackMap.forEach((value, key, map) => {
-        let arr = [];
-        for (let i = 0; i < value[0].length; i++) {
-            let num = 0;
-            for (let j = 0; j < value.length; j++) {
-                num = num + value[j][i]
-            }
-            arr.push(num);
-        }
-        indexMap.set(key, arr);
-    })
-    return indexMap
-}
+  let indexMap = new Map();
+  stackMap.forEach((value, key, map) => {
+    let arr = [];
+    for (let i = 0; i < value[0].length; i++) {
+      let num = 0;
+      for (let j = 0; j < value.length; j++) {
+        num = num + value[j][i];
+      }
+      arr.push(num);
+    }
+    indexMap.set(key, arr);
+  });
+  return indexMap;
+};
 
 const getInterval = (arr) => {
-    let splitNum = 5;
-    let max = Math.ceil(Math.max.apply(null, arr) * 1.2 / splitNum) * splitNum;
-    let interval = Math.ceil(max / splitNum)
-    if (max <= 10) {
-        return {
-            min: 0,
-            max: 10,
-            interval: 2
-        }
-    }
+  let splitNum = 5;
+  let max = Math.ceil((Math.max.apply(null, arr) * 1.2) / splitNum) * splitNum;
+  let interval = Math.ceil(max / splitNum);
+  if (max <= 10) {
     return {
-        max: max,
-        min: 0,
-        interval: interval,
+      min: 0,
+      max: 10,
+      interval: 2,
     };
-}
+  }
+  return {
+    max: max,
+    min: 0,
+    interval: interval,
+  };
+};
 
 const circleChartConfig = (option) => {
-    if (option.title) {
-        option.title.textStyle = {
-            color: "#B2B2B2",
-            fontSize: '15px',
-            align: "center",
-            lineHeight: 20,
-            fontWeight: "normal",
-        }
-    }
-    let label = {
-        show: true,
-        avoidLabelOverlap: true,
-        position: 'outer',
-        alignTo: 'labelLine',
-        overflow: 'none',
-        formatter: (params) => {
-            const arr = [
-                `{a|${params.name}}`,
-                `{b|${params.value}}`,
-            ]
-            return arr.join('\n\n')
-        },
-        rich: {
-            b: {
-                color: '#4D4D4D'
-            },
-        },
-        textStyle: {
-            align: "left",
-            baseline: "middle",
-            fontSize: 14,
-            color: "#b3b3b3",
-        },
-    }
-    if (!option.series[0].label) {
-        option.series[0].label = {}
-    }
-    Object.assign(option.series[0].label, label)
-    let labelLine = {
-        show: true,
-        length: 10,
-        length2: 30,
+  if (option.title) {
+    option.title.textStyle = {
+      color: "#B2B2B2",
+      fontSize: "15px",
+      align: "center",
+      lineHeight: 20,
+      fontWeight: "normal",
     };
-    if (!option.series[0].labelLine) {
-        option.series[0].labelLine = {
-            show: true
-        }
-    }
-    option.legend.show = false
-    option.color = constant.echartsColors;
-    Object.assign(option.series[0].labelLine, labelLine)
-    return option;
-}
+  }
+  let label = {
+    show: true,
+    avoidLabelOverlap: true,
+    position: "outer",
+    alignTo: "labelLine",
+    overflow: "none",
+    formatter: (params) => {
+      const arr = [`{a|${params.name}}`, `{b|${params.value}}`];
+      return arr.join("\n\n");
+    },
+    rich: {
+      b: {
+        color: "#4D4D4D",
+      },
+    },
+    textStyle: {
+      align: "left",
+      baseline: "middle",
+      fontSize: 14,
+      color: "#b3b3b3",
+    },
+  };
+  if (!option.series[0].label) {
+    option.series[0].label = {};
+  }
+  Object.assign(option.series[0].label, label);
+  let labelLine = {
+    show: true,
+    length: 10,
+    length2: 30,
+  };
+  if (!option.series[0].labelLine) {
+    option.series[0].labelLine = {
+      show: true,
+    };
+  }
+  option.legend.show = false;
+  option.color = constant.echartsColors;
+  Object.assign(option.series[0].labelLine, labelLine);
+  return option;
+};
 
 const circleChartArrToObj = (arr) => {
-    let obj = {};
-    if (arr) {
-        for (let i = 0; i < arr.length; i++) {
-            obj[arr[i].name] = arr[i].value;
-        }
+  let obj = {};
+  if (arr) {
+    for (let i = 0; i < arr.length; i++) {
+      obj[arr[i].name] = arr[i].value;
     }
-    return obj;
-}
+  }
+  return obj;
+};
 
 export default {
-    covertDataToEcharts,
-    refreshEchartsData,
-    circleChartArrToObj,
-    circleChartConfig,
-}
+  covertDataToEcharts,
+  refreshEchartsData,
+  circleChartArrToObj,
+  circleChartConfig,
+};