Browse Source

报表统计

chenrui  2 years ago
parent
commit
3c72a7f756

+ 7 - 0
src/router/routes/routes-file-six.js

@@ -35,6 +35,13 @@ const statisticsChartsRoutes = {
           component: () => import('@/views/statisticsCharts/views/nodeStatisticsCharts'),
           meta: { title: '扫描节点与位置分析', keepAlive: false, roles: ['scanning_node_and_location_analysis'] }
         },
+        {
+          path: 'reportStatistics',
+          name: 'ReportStatistics',
+          hidden: true,
+          component: () => import('@/views/statisticsCharts/views/reportStatistics'),
+          meta: { title: '报表统计', keepAlive: false, roles: ['scanning_node_and_location_analysis'] }
+        },
         {
           path: 'baggage',
           name: 'BaggageStatisticsCharts',

+ 71 - 77
src/views/statisticsCharts/components/statisticsTabs.vue

@@ -1,14 +1,7 @@
 <template>
   <div class="statistics-tabs">
-    <el-row
-      :gutter="16"
-      type="flex"
-    >
-      <el-col
-        v-for="(tab, index) in tabList"
-        :key="index"
-        :span="4"
-      >
+    <el-row :gutter="16" type="flex">
+      <el-col v-for="(tab, index) in tabList" :key="index" :span="4">
         <el-dropdown
           v-if="tab.children && tab.children.length"
           placement="bottom"
@@ -19,11 +12,8 @@
               class="tab-icon"
               :src="activeIndex === index ? activeIcon : defaultIcon"
               :alt="tab.title"
-            >
-            <el-tooltip
-              :content="tab.title"
-              placement="top"
-            >
+            />
+            <el-tooltip :content="tab.title" placement="top">
               <span class="tab-title">{{ tab.title }}</span>
             </el-tooltip>
             <i class="icon-arrow el-icon-caret-bottom" />
@@ -33,23 +23,24 @@
               v-for="(childTab, childIndex) in tab.children"
               :key="childIndex"
               :command="{ path: childTab.path, parentIndex: index }"
-            >{{ childTab.title }}</el-dropdown-item>
+              >{{ childTab.title }}</el-dropdown-item
+            >
           </el-dropdown-menu>
         </el-dropdown>
         <div
           v-else
-          :class="['tab-bar tab-bar-single', { 'tab-active': activeIndex === index }]"
+          :class="[
+            'tab-bar tab-bar-single',
+            { 'tab-active': activeIndex === index },
+          ]"
           @click="clickHandler(index)"
         >
           <img
             class="tab-icon"
             :src="activeIndex === index ? activeIcon : defaultIcon"
             :alt="tab.title"
-          >
-          <el-tooltip
-            :content="tab.title"
-            placement="top"
-          >
+          />
+          <el-tooltip :content="tab.title" placement="top">
             <span class="tab-title">{{ tab.title }}</span>
           </el-tooltip>
         </div>
@@ -60,118 +51,121 @@
 
 <script>
 export default {
-  name: 'StatisticsTabs',
+  name: "StatisticsTabs",
   data() {
     return {
-      defaultIcon: require('@/assets/nav/ic_statistical_top_default.png'),
-      activeIcon: require('@/assets/nav/ic_statistical_top_check.png'),
+      defaultIcon: require("@/assets/nav/ic_statistical_top_default.png"),
+      activeIcon: require("@/assets/nav/ic_statistical_top_check.png"),
       tabList: [
         {
-          title: '公司行李相关总统计',
+          title: "公司行李相关总统计",
           children: [
             {
-              path: '/statisticsCharts/flight',
-              title: '航班量统计'
+              path: "/statisticsCharts/flight",
+              title: "航班量统计",
             },
             {
-              path: '/statisticsCharts/baggage',
-              title: '行李量统计'
+              path: "/statisticsCharts/baggage",
+              title: "行李量统计",
             },
             {
-              path: '/statisticsCharts/baggagePassenger',
-              title: '行李旅客量统计'
+              path: "/statisticsCharts/baggagePassenger",
+              title: "行李旅客量统计",
             },
             {
-              path: '/statisticsCharts/specialBaggage',
-              title: '特殊行李量统计'
+              path: "/statisticsCharts/specialBaggage",
+              title: "特殊行李量统计",
             },
             {
-              path: '/statisticsCharts/baggageAverage',
-              title: '平均行李量统计'
+              path: "/statisticsCharts/baggageAverage",
+              title: "平均行李量统计",
             },
             {
-              path: '/statisticsCharts/abnormalBaggage',
-              title: '异常行李量统计'
+              path: "/statisticsCharts/abnormalBaggage",
+              title: "异常行李量统计",
             },
             {
-              path: '/statisticsCharts/complaintBaggage',
-              title: '投诉行李量统计'
+              path: "/statisticsCharts/complaintBaggage",
+              title: "投诉行李量统计",
             },
             {
-              path: '/statisticsCharts/compensationBaggage',
-              title: '赔偿行李量统计'
+              path: "/statisticsCharts/compensationBaggage",
+              title: "赔偿行李量统计",
             },
             {
-              path: '/statisticsCharts/compensation',
-              title: '赔偿金额统计'
-            }
-          ]
+              path: "/statisticsCharts/compensation",
+              title: "赔偿金额统计",
+            },
+          ],
         },
         {
-          title: '旅客分类统计'
+          title: "旅客分类统计",
         },
         {
-          title: '航班分类相关统计'
+          title: "航班分类相关统计",
         },
         {
-          path: '/statisticsCharts/node',
-          title: '扫描节点与位置分析'
+          path: "/statisticsCharts/node",
+          title: "扫描节点与位置分析",
         },
         {
-          title: '报表统计'
+          path: "/statisticsCharts/reportStatistics",
+          title: "报表统计",
         },
         {
-          title: '特殊赔偿异常分类统计'
-        }
+          title: "特殊赔偿异常分类统计",
+        },
       ],
-      activeIndex: null
-    }
+      activeIndex: null,
+    };
   },
   watch: {
-    '$route.path': {
+    "$route.path": {
       handler(path) {
-        let activeIndex = null
+        let activeIndex = null;
         this.tabList.some((tab, index) => {
           if (tab.path === path) {
-            activeIndex = index
-            return true
+            activeIndex = index;
+            return true;
           } else if (tab.children?.length) {
-            const matchedChildTab = tab.children.find(childTab => childTab.path === path)
+            const matchedChildTab = tab.children.find(
+              (childTab) => childTab.path === path
+            );
             if (matchedChildTab) {
-              activeIndex = index
-              return true
+              activeIndex = index;
+              return true;
             }
           }
-        })
-        this.activeIndex = activeIndex
+        });
+        this.activeIndex = activeIndex;
       },
-      immediate: true
+      immediate: true,
     },
     activeIndex(index) {
-      const path = this.tabList[index].path
+      const path = this.tabList[index].path;
       if (path) {
         this.$router.push({
-          path
-        })
+          path,
+        });
       }
-    }
+    },
   },
   methods: {
     commandHandler({ path, parentIndex }) {
-      this.activeIndex = parentIndex
+      this.activeIndex = parentIndex;
       this.$router.push({
-        path
-      })
+        path,
+      });
     },
     clickHandler(index) {
       if (this.tabList[index].path) {
-        this.activeIndex = index
+        this.activeIndex = index;
       } else {
-        this.$message.info('开发中')
+        this.$message.info("开发中");
       }
-    }
-  }
-}
+    },
+  },
+};
 </script>
 
 <style lang="scss" scoped>
@@ -206,7 +200,7 @@ export default {
         padding-left: 12px;
         padding-right: 8px;
         font-size: 14px;
-        font-family: Helvetica, 'Microsoft YaHei';
+        font-family: Helvetica, "Microsoft YaHei";
         font-weight: bold;
         color: #101116;
         letter-spacing: 0;

+ 481 - 0
src/views/statisticsCharts/components/tableform.vue

@@ -0,0 +1,481 @@
+<template>
+  <div class="data-table">
+    <div
+      :style="dataTableContentStyle"
+      v-loading="loading"
+      element-loading-text="拼命加载中"
+      element-loading-spinner="el-icon-loading"
+      element-loading-background="rgba(0, 0, 0, 0.8)"
+      class="data-table-content"
+    >
+      <template v-if="tableData.length">
+        <div>
+          <el-table
+            v-el-table-infinite-scroll="load"
+            :data="filteredTableData"
+            :summary-method="getSummaries"
+            :tree-props="treeProps"
+            :row-key="rowKeyTree"
+            stripe
+            :show-summary="showSummary"
+            border
+            ref="table"
+            :height="tableHeight ? tableHeight : minHeight - 8 + 'vh'"
+            class="table infinite-list"
+            style="width: 100%; overflow: auto"
+            @select="selectHandler"
+          >
+            <el-table-column
+              v-if="selectionEnable"
+              type="selection"
+              width="35"
+            />
+            <el-table-column
+              v-for="(item, index) in tableColsCopy"
+              :sortable="item.needSort ? true : false"
+              :key="index"
+              :prop="item.columnName"
+              :label="item.columnLabel"
+              :show-overflow-tooltip="showOverflowTooltip"
+            >
+              <template #header>
+                <span class="colTips">
+                  <el-tooltip :content="item.columnDescribe" placement="top">
+                    <span>{{ item.columnLabel }}</span>
+                  </el-tooltip>
+                </span>
+                <span v-if="item.needFilters">
+                  <el-popover
+                    placement="bottom"
+                    trigger="click"
+                    @show="popoverShowHandler(item.columnName)"
+                    @hide="popoverHideHandler"
+                  >
+                    <i
+                      slot="reference"
+                      :class="[
+                        'filter-arrow',
+                        'el-icon-arrow-down',
+                        arrowClass(item.columnName),
+                      ]"
+                    />
+                    <el-form>
+                      <el-form-item :label="item.columnLabel">
+                        <el-select
+                          v-model="filterValues[item.columnName]"
+                          size="small"
+                          placeholder="筛选"
+                          default-first-option
+                          filterable
+                          clearable
+                        >
+                          <el-option
+                            v-for="(option, optionIndex) in tableDataFilters[
+                              item.columnName
+                            ]"
+                            :key="option.value + optionIndex"
+                            :value="option.value"
+                            :label="option.text"
+                          />
+                        </el-select>
+                      </el-form-item>
+                    </el-form>
+                  </el-popover>
+                </span>
+              </template>
+            </el-table-column>
+          </el-table>
+          <!-- <p v-if="noMore" style="text-align: center">没有更多了</p> -->
+        </div>
+      </template>
+      <template v-else>
+        <NoData image-width="auto" image-height="100%" />
+      </template>
+    </div>
+  </div>
+</template>
+<script>
+import { setTableFilters } from "@/utils/table";
+import NoData from "@/components/nodata";
+export default {
+  isDialog: {
+    type: Boolean,
+    default: true,
+  },
+  //接口ID
+  dataId: {
+    type: [String, Number],
+    default: "",
+  },
+  editId: {
+    type: [String, Number],
+    default: "",
+  },
+  dataContent: {
+    type: Object,
+    default: () => ({}),
+  },
+  //是否显示状态
+  isStatus: {
+    type: Boolean,
+    default: false,
+  },
+  //弹框宽度
+  width: {
+    type: String,
+    default: "560px",
+  },
+  //弹框表单-行数
+  rows: {
+    type: Number,
+    default: 3,
+  },
+  //弹框-表单文字宽度
+  labelWidth: {
+    type: String,
+    default: "80px",
+  },
+  //表格高度
+  tableHeight: {
+    type: [String, Number],
+    default: 0,
+  },
+  minHeight: {
+    type: Number,
+    default: 65,
+  },
+  //是否显示树形表格
+  isTree: {
+    type: Boolean,
+    default: false,
+  },
+  //树形props
+  treeProps: {
+    type: Object,
+    default: function () {
+      return { children: "children", hasChildren: "hasChildren" };
+    },
+  },
+  //树形标识id
+  rowKeyTree: {
+    type: String,
+    default: "companyID",
+  },
+  //是否显示新增按钮
+  isBtn: {
+    type: Boolean,
+    default: true,
+  },
+  // 是否显示合计行
+  showSummary: {
+    type: Boolean,
+    default: false,
+  },
+  marginTop: {
+    type: String,
+    default: "0px",
+  },
+  // 是否可选中行
+  selectionEnable: {
+    type: Boolean,
+    default: false,
+  },
+  // 懒加载
+  withLazyLoad: {
+    type: Boolean,
+    default: false,
+  },
+  // 不换行,溢出隐藏
+  showOverflowTooltip: {
+    type: Boolean,
+    default: false,
+  },
+  // 表格-操作-列设置按钮显示
+  withColumnSet: {
+    type: Boolean,
+    default: false,
+  },
+  // 表格-操作-项设置按钮显示
+  withItemSet: {
+    type: Boolean,
+    default: false,
+  },
+  // 表格-操作-项设置按钮显示
+  withlodSet: {
+    type: Boolean,
+    default: false,
+  },
+  // 表格-操作-节点按钮显示
+  withnodeSet: {
+    type: Boolean,
+    default: false,
+  },
+  //操作列宽度
+  fixedWidth: {
+    type: String,
+    default: "180px",
+  },
+  //树形props
+  treeProps: {
+    type: Object,
+    default: function () {
+      return { children: "children", hasChildren: "hasChildren" };
+    },
+  },
+  data() {
+    return {
+      loading: false,
+      flag: false,
+      serviceId: null,
+      rmFlag: false,
+      rowTitle: "",
+      page: 0,
+      noMore: false,
+      tableCols: [], //表头数据
+      tableData: [], //表格数据
+      tableColsCopy: [
+        {
+          columnName: "行李平均运输时间",
+          columnLabel: "行李平均运输时间",
+          needSort: true,
+        },
+        {
+          columnName: "行李平均装机时间",
+          columnLabel: "行李平均装机时间",
+          needSort: true,
+        },
+        {
+          columnName: "值机-分拣平均时间",
+          columnLabel: "值机-分拣平均时间",
+          needSort: true,
+        },
+        {
+          columnName: "值机-装车平均时间",
+          columnLabel: "值机-装车平均时间",
+          needSort: true,
+        },
+      ], //表头数据缓存
+      tableDataFilters: {}, //表头-下拉数据
+      filterValues: {}, //表头-下拉-选中数据
+      tableDataCopy: [], //缓存table数据
+      tableGroups: [], //表格分组数据
+      colShowFilter: "", //表头-下拉-箭头
+      spanArr: [], //表格分组数据缓存
+      pos: 0, //表格分组计数
+      tableTitle: "新增", //弹框标题
+      tableType: "add", //弹框类型=新增/编辑
+      tableForm: {}, //弹框表单
+      rmTitle: "", //弹框-删除-标题
+      tableObj: {}, //增/删/改数据缓存
+      tableOptions: {}, //弹框-下来数据缓存
+      tableArrs: [], //重组table-表头下拉
+      proAll: false, //重组时-所有请求是否都完成
+    };
+  },
+  computed: {
+    dataTableContentStyle() {
+      const style = {};
+      if (this.minHeight) {
+        style["min-height"] = this.minHeight;
+      }
+      if (this.tableHeight) {
+        style["height"] = this.tableHeight;
+      }
+      return style;
+    },
+  },
+  mounted() {
+    this.initTableData();
+  },
+  methods: {
+    load() {
+      // console.log("分页");
+      if (!this.isTree) {
+        if (this.noMore || this.loading) {
+          return;
+        }
+        this.getQuery();
+      }
+    },
+    //获取表格数据
+    async getQuery() {
+      try {
+        this.loading = true;
+        const { code, returnData } = await Query({
+          id: this.dataId,
+          needPage: ++this.page,
+          dataContent: [this.dataContent.companyID],
+        });
+        if (code == 0) {
+          if (returnData.listValues.length === 0) {
+            this.page--;
+            this.noMore = true;
+            this.loading = false;
+          }
+          const titleColumn = returnData.columnSet.find(
+            (item) => item.needShow === 1
+          );
+          if (titleColumn) {
+            this.rowTitle = titleColumn.columnName;
+          }
+          this.tableData.push(...returnData.listValues);
+          this.tableCols = returnData.columnSet;
+          this.serviceId = returnData.submitID;
+          setTimeout(() => {
+            this.initTableData();
+            this.loading = false;
+          }, 100);
+        } else {
+          this.page--;
+          this.loading = false;
+          this.$message.error("获取表格数据失败");
+        }
+      } catch (error) {
+        this.page--;
+        this.loading = false;
+        console.log(error);
+      }
+    },
+    //初始化表格
+    initTableData() {
+      this.tableColsCopy = this.tableCols.filter((item) => item.needShow);
+      // console.log(this.tableColsCopy);
+      // debugger;
+      this.tableDataCopy = _.cloneDeep(this.tableData);
+      const datas = _.cloneDeep(this.tableColsCopy);
+      // const reqUts = [];
+      datas.forEach(async (item) => {
+        this.tableDataFilters[item.columnName] = [];
+        if (item.needGroup) {
+          this.tableGroups.push(item.columnName);
+        }
+        if (item.listqueryTemplateID || item.listqueryTemplateID == 0) {
+          this.tableArrs.push(item.columnName);
+          // const reqUt = this.getSelectData(item.listqueryTemplateID)
+          // reqUts.push(reqUt)
+          if (!this.tableOptions[item.columnName]) {
+            this.tableOptions[item.columnName] = await this.getSelectData(
+              item.listqueryTemplateID
+            );
+          }
+          // console.log(this.tableOptions[item.columnName])
+        }
+        // this.filterValues[item.columnName] = ''
+      });
+      setTableFilters(this.tableData, this.tableDataFilters);
+      // this.tableGroup(this.tableData);
+      // this.selectTableRows(this.tableData, "DeployID");
+      // this.getSelectDataAll(reqUts)
+    },
+    //合计
+    getSummaries(param) {
+      const { columns, data } = param;
+      const sums = [];
+      columns.forEach((column, index) => {
+        this.tableColsCopy.forEach((p) => {
+          if (column.property == p.columnName && p.needCount) {
+            const values = data.map((item) => Number(item[column.property]));
+            if (!values.every((value) => isNaN(value))) {
+              sums[index] = values.reduce((prev, curr) => {
+                const value = Number(curr);
+                if (!isNaN(value)) {
+                  return prev + curr;
+                } else {
+                  return prev;
+                }
+              }, 0);
+              sums[index] += "";
+            }
+          }
+        });
+      });
+      return sums;
+    },
+    //分组
+    tableGroup(tableData) {
+      const spanArr = [];
+      let pos = 0;
+      let ifYj = this.tableGroups[0];
+      for (let i = 0; i < tableData.length; i++) {
+        if (i === 0) {
+          spanArr.push(1);
+        } else {
+          if (tableData[i][ifYj] === tableData[i - 1][ifYj]) {
+            spanArr[pos] += 1;
+            spanArr.push(0);
+          } else {
+            spanArr.push(1);
+            pos = i;
+          }
+        }
+      }
+      this.spanArr = spanArr;
+      this.pos = pos;
+    },
+  },
+  components: { NoData },
+};
+</script>
+<style lang="scss" scoped>
+.statistics-tabs {
+  > .el-row > .el-col {
+    max-width: 232px;
+    min-width: 186px;
+    .el-dropdown {
+      width: 100%;
+    }
+    .tab-bar {
+      width: 100%;
+      height: 56px;
+      background-color: #ffffff;
+      padding-left: 16px;
+      padding-right: 16px;
+      display: flex;
+      align-items: center;
+      box-shadow: 0px 6px 7px 0px rgba(0, 0, 0, 0.06);
+      border-radius: 4px;
+      &-single {
+        cursor: pointer;
+      }
+      &:not(:last-child) {
+        margin-right: 16px;
+      }
+      .tab-icon {
+        width: 14px;
+        height: 14px;
+      }
+      .tab-title {
+        padding-left: 12px;
+        padding-right: 8px;
+        font-size: 14px;
+        font-family: Helvetica, "Microsoft YaHei";
+        font-weight: bold;
+        color: #101116;
+        letter-spacing: 0;
+        overflow: hidden;
+        white-space: nowrap;
+        text-overflow: ellipsis;
+      }
+      &.tab-active {
+        background-color: #2d67e3;
+        .tab-title {
+          color: #ffffff;
+        }
+      }
+      .icon-arrow {
+        position: absolute;
+        right: 16px;
+        color: #101116;
+        font-size: 14px;
+        transition: transform 0.3s;
+      }
+      &.tab-active .icon-arrow {
+        color: #ffffff;
+      }
+      &:hover .icon-arrow {
+        transform: rotate(180deg);
+      }
+    }
+  }
+}
+</style>

+ 62 - 0
src/views/statisticsCharts/views/reportStatistics.vue

@@ -0,0 +1,62 @@
+<template>
+  <!-- 报表统计 -->
+  <div class="statstics-wrapper">
+    <StatisticsHeader
+      title="报表统计"
+      :items="formItems"
+      :data="formData"
+      with-setting
+      :withSetting="false"
+      :withExport="false"
+    />
+    <Tableform
+      :rows="12"
+      label-width="140px"
+      :min-height="70"
+      width="800px"
+      tableHeight="750"
+    />
+  </div>
+</template>
+<script>
+import StatisticsHeader from "../components/statisticsHeader.vue";
+import Tableform from "../components/tableform";
+export default {
+  name: "ReportStatistics",
+  data() {
+    return {
+      formData: {
+        airport: "",
+        dateTime: "",
+      },
+      formItems: [
+        {
+          prop: "airport",
+          inputType: "select",
+          placeholder: "航站选择",
+          filterable: true,
+          clearable: true,
+          // multiple: true,
+          disabled: true,
+          queryId: DATACONTENT_ID.nodeAirport,
+          setKey: "a2",
+          options: [],
+        },
+        {
+          prop: "dateTime",
+          inputType: "datePicker",
+          clearable: true,
+          width: "240px",
+          options: [],
+        },
+      ],
+    };
+  },
+  components: {
+    StatisticsHeader,
+    Tableform,
+  },
+};
+</script>
+<style lang="scss" scoped>
+</style>