소스 검색

导出excel

zhuxinbo 5 년 전
부모
커밋
1f8effdc80
11개의 변경된 파일31083개의 추가작업 그리고 643개의 파일을 삭제
  1. 122 125
      package.json
  2. 42 0
      public/export.js
  3. 305 300
      public/index.html
  4. 0 0
      public/logo1.png
  5. 30150 0
      public/xlsx.extendscript.js
  6. 24 0
      public/xlsx.full.min.js
  7. 10 0
      src/api/statistics.js
  8. BIN
      src/assets/logo.png
  9. BIN
      src/assets/logo1.png
  10. 153 153
      src/components/layouts/UserLayout.vue
  11. 277 65
      src/views/modules/Statistics/dataDisplayStatistics.vue

+ 122 - 125
package.json

@@ -1,129 +1,126 @@
 {
-  "name": "ant-design-vue-jeecg",
-  "version": "2.0.2",
-  "private": true,
-  "scripts": {
-    "serve": "vue-cli-service serve --open",
-    "build": "vue-cli-service build",
-    "lint": "vue-cli-service lint",
-    "test:unit": "vue-cli-service test:unit",
-    "test:e2e": "vue-cli-service test:e2e"
-  },
-  "dependencies": {
-    "@antv/data-set": "^0.10.2",
-    "@femessage/upload-to-ali": "^1.8.1",
-    "@tinymce/tinymce-vue": "^2.0.0",
-    "ali-oss": "^6.1.1",
-    "ant-design-vue": "^1.3.9",
-    "apexcharts": "^3.6.5",
-    "axios": "^0.18.0",
-    "babel-loader": "^8.0.6",
-    "blueimp-md5": "^2.11.0",
-    "browser-md5-file": "^1.1.1",
-    "clipboard": "^2.0.4",
-    "codemirror": "^5.46.0",
-    "dayjs": "^1.8.0",
-    "echarts": "^4.3.0",
-    "enquire.js": "^2.1.6",
-    "file-save": "^0.2.0",
-    "html2canvas": "^1.0.0-rc.3",
-    "iview": "2.0.0-rc.17",
-    "jquery": "^3.4.1",
-    "js-cookie": "^2.2.0",
-    "lodash.get": "^4.4.2",
-    "lodash.pick": "^4.4.0",
-    "mcanvas": "^1.3.9",
-    "md5": "^2.2.1",
-    "nprogress": "^0.2.0",
-    "promise.prototype.finally": "^3.1.1",
-    "tinymce": "^5.0.2",
-    "viser-vue": "^2.4.4",
-    "vue": "^2.6.10",
-    "vue-apexcharts": "^1.3.2",
-    "vue-class-component": "^6.0.0",
-    "vue-count-to": "^1.0.13",
-    "vue-cropper": "^0.4.8",
-    "vue-i18n": "^8.7.0",
-    "vue-layer": "^1.0.2",
-    "vue-loader": "^15.7.0",
-    "vue-ls": "^3.2.0",
-    "vue-oss-uploader": "^0.1.10",
-    "vue-photo-preview": "^1.1.3",
-    "vue-preview": "^1.1.3",
-    "vue-print-nb-jeecg": "^1.0.8",
-    "vue-property-decorator": "^7.3.0",
-    "vue-router": "^3.0.1",
-    "vue-splitpane": "^1.0.4",
-    "vue-video-player": "^5.0.2",
-    "vue-waterfall-easy": "^2.4.3",
-    "vuedraggable": "^2.20.0",
-    "vuex": "^3.0.1",
-    "vuex-class": "^0.3.1"
-  },
-  "devDependencies": {
-    "@babel/polyfill": "^7.2.5",
-    "@vue/cli-plugin-babel": "^3.3.0",
-    "@vue/cli-plugin-eslint": "^3.3.0",
-    "@vue/cli-service": "^3.3.0",
-    "@vue/eslint-config-standard": "^4.0.0",
-    "babel-eslint": "^10.0.1",
-    "eslint": "^5.16.0",
-    "eslint-plugin-vue": "^5.1.0",
-    "file-saver": "^2.0.2",
-    "html-webpack-plugin": "^3.2.0",
-    "less": "^3.9.0",
-    "less-loader": "^4.1.0",
-    "node-sass": "^4.11.0",
-    "sass-loader": "^7.0.1",
-    "vue-template-compiler": "^2.6.10",
-    "xlsx": "^0.15.1"
-  },
-  "eslintConfig": {
-    "root": true,
-    "env": {
-      "node": true
+    "name": "ant-design-vue-jeecg",
+    "version": "2.0.2",
+    "private": true,
+    "scripts": {
+      "serve": "vue-cli-service serve --open",
+      "build": "vue-cli-service build",
+      "lint": "vue-cli-service lint",
+      "test:unit": "vue-cli-service test:unit",
+      "test:e2e": "vue-cli-service test:e2e"
     },
-    "extends": [
-      "plugin:vue/strongly-recommended",
-      "eslint:recommended"
-    ],
-    "parserOptions": {
-      "parser": "babel-eslint"
+    "dependencies": {
+      "@antv/data-set": "^0.10.2",
+      "@femessage/upload-to-ali": "^1.8.1",
+      "@tinymce/tinymce-vue": "^2.0.0",
+      "ali-oss": "^6.1.1",
+      "ant-design-vue": "^1.3.9",
+      "apexcharts": "^3.6.5",
+      "axios": "^0.18.0",
+      "babel-loader": "^8.0.6",
+      "blueimp-md5": "^2.11.0",
+      "browser-md5-file": "^1.1.1",
+      "clipboard": "^2.0.4",
+      "codemirror": "^5.46.0",
+      "dayjs": "^1.8.0",
+      "echarts": "^4.3.0",
+      "enquire.js": "^2.1.6",
+      "html2canvas": "^1.0.0-rc.3",
+      "iview": "2.0.0-rc.17",
+      "jquery": "^3.4.1",
+      "js-cookie": "^2.2.0",
+      "lodash.get": "^4.4.2",
+      "lodash.pick": "^4.4.0",
+      "mcanvas": "^1.3.9",
+      "md5": "^2.2.1",
+      "nprogress": "^0.2.0",
+      "promise.prototype.finally": "^3.1.1",
+      "tinymce": "^5.0.2",
+      "viser-vue": "^2.4.4",
+      "vue": "^2.6.10",
+      "vue-apexcharts": "^1.3.2",
+      "vue-class-component": "^6.0.0",
+      "vue-count-to": "^1.0.13",
+      "vue-cropper": "^0.4.8",
+      "vue-i18n": "^8.7.0",
+      "vue-layer": "^1.0.2",
+      "vue-loader": "^15.7.0",
+      "vue-ls": "^3.2.0",
+      "vue-oss-uploader": "^0.1.10",
+      "vue-photo-preview": "^1.1.3",
+      "vue-preview": "^1.1.3",
+      "vue-print-nb-jeecg": "^1.0.8",
+      "vue-property-decorator": "^7.3.0",
+      "vue-router": "^3.0.1",
+      "vue-splitpane": "^1.0.4",
+      "vue-video-player": "^5.0.2",
+      "vue-waterfall-easy": "^2.4.3",
+      "vuedraggable": "^2.20.0",
+      "vuex": "^3.0.1",
+      "vuex-class": "^0.3.1"
     },
-    "rules": {
-      "generator-star-spacing": "off",
-      "no-mixed-operators": 0,
-      "vue/max-attributes-per-line": [
-        2,
-        {
-          "singleline": 5,
-          "multiline": {
-            "max": 1,
-            "allowFirstLine": false
-          }
-        }
+    "devDependencies": {
+      "@babel/polyfill": "^7.2.5",
+      "@vue/cli-plugin-babel": "^3.3.0",
+      "@vue/cli-plugin-eslint": "^3.3.0",
+      "@vue/cli-service": "^3.3.0",
+      "@vue/eslint-config-standard": "^4.0.0",
+      "babel-eslint": "^10.0.1",
+      "eslint": "^5.16.0",
+      "eslint-plugin-vue": "^5.1.0",
+      "html-webpack-plugin": "^3.2.0",
+      "less": "^3.9.0",
+      "less-loader": "^4.1.0",
+      "node-sass": "^4.11.0",
+      "sass-loader": "^7.0.1",
+      "vue-template-compiler": "^2.6.10"
+    },
+    "eslintConfig": {
+      "root": true,
+      "env": {
+        "node": true
+      },
+      "extends": [
+        "plugin:vue/strongly-recommended",
+        "eslint:recommended"
       ],
-      "vue/attribute-hyphenation": 0,
-      "vue/html-self-closing": 0,
-      "vue/component-name-in-template-casing": 0,
-      "vue/html-closing-bracket-spacing": 0,
-      "vue/singleline-html-element-content-newline": 0,
-      "vue/no-unused-components": 0,
-      "vue/multiline-html-element-content-newline": 0,
-      "vue/no-use-v-if-with-v-for": 0,
-      "vue/html-closing-bracket-newline": 0,
-      "vue/no-parsing-error": 0,
-      "no-console": 0
-    }
-  },
-  "postcss": {
-    "plugins": {
-      "autoprefixer": {}
-    }
-  },
-  "browserslist": [
-    "> 1%",
-    "last 2 versions",
-    "not ie <= 8"
-  ]
-}
+      "parserOptions": {
+        "parser": "babel-eslint"
+      },
+      "rules": {
+        "generator-star-spacing": "off",
+        "no-mixed-operators": 0,
+        "vue/max-attributes-per-line": [
+          2,
+          {
+            "singleline": 5,
+            "multiline": {
+              "max": 1,
+              "allowFirstLine": false
+            }
+          }
+        ],
+        "vue/attribute-hyphenation": 0,
+        "vue/html-self-closing": 0,
+        "vue/component-name-in-template-casing": 0,
+        "vue/html-closing-bracket-spacing": 0,
+        "vue/singleline-html-element-content-newline": 0,
+        "vue/no-unused-components": 0,
+        "vue/multiline-html-element-content-newline": 0,
+        "vue/no-use-v-if-with-v-for": 0,
+        "vue/html-closing-bracket-newline": 0,
+        "vue/no-parsing-error": 0,
+        "no-console": 0
+      }
+    },
+    "postcss": {
+      "plugins": {
+        "autoprefixer": {}
+      }
+    },
+    "browserslist": [
+      "> 1%",
+      "last 2 versions",
+      "not ie <= 8"
+    ]
+  }

+ 42 - 0
public/export.js

@@ -0,0 +1,42 @@
+// 将一个sheet转成最终的excel文件的blob对象,然后利用URL.createObjectURL下载
+function sheet2blob(sheet, sheetName) {
+    sheetName = sheetName || 'sheet1';
+    var workbook = {
+        SheetNames: [sheetName],
+        Sheets: {}
+    };
+    workbook.Sheets[sheetName] = sheet; // 生成excel的配置项
+
+    var wopts = {
+        bookType: 'xlsx', // 要生成的文件类型
+        bookSST: false, // 是否生成Shared String Table,官方解释是,如果开启生成速度会下降,但在低版本IOS设备上有更好的兼容性
+        type: 'binary'
+    };
+    var wbout = XLSX.write(workbook, wopts);
+    var blob = new Blob([s2ab(wbout)], {
+        type: "application/octet-stream"
+    }); // 字符串转ArrayBuffer
+    function s2ab(s) {
+        var buf = new ArrayBuffer(s.length);
+        var view = new Uint8Array(buf);
+        for (var i = 0; i != s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF;
+        return buf;
+    }
+    return blob;
+}
+
+function openDownloadDialog(url, saveName) {
+    if (typeof url == 'object' && url instanceof Blob) {
+        url = URL.createObjectURL(url); // 创建blob地址
+    }
+    var aLink = document.createElement('a');
+    aLink.href = url;
+    aLink.download = saveName || ''; // HTML5新增的属性,指定保存文件名,可以不要后缀,注意,file:///模式下不会生效
+    var event;
+    if (window.MouseEvent) event = new MouseEvent('click');
+    else {
+        event = document.createEvent('MouseEvents');
+        event.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
+    }
+    aLink.dispatchEvent(event);
+}

+ 305 - 300
public/index.html

@@ -1,301 +1,306 @@
-<!DOCTYPE html>
-<html lang="zh-cmn-Hans">
-
-<head>
-  <meta charset="utf-8">
-  <meta http-equiv="X-UA-Compatible" content="IE=edge">
-  <meta name="viewport" content="width=device-width,initial-scale=1.0">
-  <title>汇创投放助手</title>
-  <link rel="icon" href="<%= BASE_URL %>logo.png">
-  <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-polyfill/7.2.5/polyfill.js"></script>
-  <style>
-    html,
-    body,
-    #app {
-      height: 100%;
-      margin: 0px;
-      padding: 0px;
-    }
-
-    .chromeframe {
-      margin: 0.2em 0;
-      background: #ccc;
-      color: #000;
-      padding: 0.2em 0;
-    }
-
-    #loader-wrapper {
-      position: fixed;
-      top: 0;
-      left: 0;
-      width: 100%;
-      height: 100%;
-      z-index: 999999;
-    }
-
-    #loader {
-      display: block;
-      position: relative;
-      left: 50%;
-      top: 50%;
-      width: 120px;
-      height: 120px;
-      margin: -75px 0 0 -75px;
-      border-radius: 50%;
-      border: 3px solid transparent;
-      /* COLOR 1 */
-      border-top-color: #FFF;
-      -webkit-animation: spin 2s linear infinite;
-      /* Chrome, Opera 15+, Safari 5+ */
-      -ms-animation: spin 2s linear infinite;
-      /* Chrome, Opera 15+, Safari 5+ */
-      -moz-animation: spin 2s linear infinite;
-      /* Chrome, Opera 15+, Safari 5+ */
-      -o-animation: spin 2s linear infinite;
-      /* Chrome, Opera 15+, Safari 5+ */
-      animation: spin 2s linear infinite;
-      /* Chrome, Firefox 16+, IE 10+, Opera */
-      z-index: 1001;
-    }
-
-    #loader:before {
-      content: "";
-      position: absolute;
-      top: 5px;
-      left: 5px;
-      right: 5px;
-      bottom: 5px;
-      border-radius: 50%;
-      border: 3px solid transparent;
-      /* COLOR 2 */
-      border-top-color: #FFF;
-      -webkit-animation: spin 3s linear infinite;
-      /* Chrome, Opera 15+, Safari 5+ */
-      -moz-animation: spin 3s linear infinite;
-      /* Chrome, Opera 15+, Safari 5+ */
-      -o-animation: spin 3s linear infinite;
-      /* Chrome, Opera 15+, Safari 5+ */
-      -ms-animation: spin 3s linear infinite;
-      /* Chrome, Opera 15+, Safari 5+ */
-      animation: spin 3s linear infinite;
-      /* Chrome, Firefox 16+, IE 10+, Opera */
-    }
-
-    #loader:after {
-      content: "";
-      position: absolute;
-      top: 15px;
-      left: 15px;
-      right: 15px;
-      bottom: 15px;
-      border-radius: 50%;
-      border: 3px solid transparent;
-      border-top-color: #FFF;
-      /* COLOR 3 */
-      -moz-animation: spin 1.5s linear infinite;
-      /* Chrome, Opera 15+, Safari 5+ */
-      -o-animation: spin 1.5s linear infinite;
-      /* Chrome, Opera 15+, Safari 5+ */
-      -ms-animation: spin 1.5s linear infinite;
-      /* Chrome, Opera 15+, Safari 5+ */
-      -webkit-animation: spin 1.5s linear infinite;
-      /* Chrome, Opera 15+, Safari 5+ */
-      animation: spin 1.5s linear infinite;
-      /* Chrome, Firefox 16+, IE 10+, Opera */
-    }
-
-    @-webkit-keyframes spin {
-      0% {
-        -webkit-transform: rotate(0deg);
-        /* Chrome, Opera 15+, Safari 3.1+ */
-        -ms-transform: rotate(0deg);
-        /* IE 9 */
-        transform: rotate(0deg);
-        /* Firefox 16+, IE 10+, Opera */
-      }
-      100% {
-        -webkit-transform: rotate(360deg);
-        /* Chrome, Opera 15+, Safari 3.1+ */
-        -ms-transform: rotate(360deg);
-        /* IE 9 */
-        transform: rotate(360deg);
-        /* Firefox 16+, IE 10+, Opera */
-      }
-    }
-
-    @keyframes spin {
-      0% {
-        -webkit-transform: rotate(0deg);
-        /* Chrome, Opera 15+, Safari 3.1+ */
-        -ms-transform: rotate(0deg);
-        /* IE 9 */
-        transform: rotate(0deg);
-        /* Firefox 16+, IE 10+, Opera */
-      }
-      100% {
-        -webkit-transform: rotate(360deg);
-        /* Chrome, Opera 15+, Safari 3.1+ */
-        -ms-transform: rotate(360deg);
-        /* IE 9 */
-        transform: rotate(360deg);
-        /* Firefox 16+, IE 10+, Opera */
-      }
-    }
-
-    #loader-wrapper .loader-section {
-      position: fixed;
-      top: 0;
-      width: 51%;
-      height: 100%;
-      background: #49a9ee;
-      /* Old browsers */
-      z-index: 1000;
-      -webkit-transform: translateX(0);
-      /* Chrome, Opera 15+, Safari 3.1+ */
-      -ms-transform: translateX(0);
-      /* IE 9 */
-      transform: translateX(0);
-      /* Firefox 16+, IE 10+, Opera */
-    }
-
-    #loader-wrapper .loader-section.section-left {
-      left: 0;
-    }
-
-    #loader-wrapper .loader-section.section-right {
-      right: 0;
-    }
-
-    /* Loaded */
-    .loaded #loader-wrapper .loader-section.section-left {
-      -webkit-transform: translateX(-100%);
-      /* Chrome, Opera 15+, Safari 3.1+ */
-      -ms-transform: translateX(-100%);
-      /* IE 9 */
-      transform: translateX(-100%);
-      /* Firefox 16+, IE 10+, Opera */
-      -webkit-transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1.000);
-      transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1.000);
-    }
-
-    .loaded #loader-wrapper .loader-section.section-right {
-      -webkit-transform: translateX(100%);
-      /* Chrome, Opera 15+, Safari 3.1+ */
-      -ms-transform: translateX(100%);
-      /* IE 9 */
-      transform: translateX(100%);
-      /* Firefox 16+, IE 10+, Opera */
-      -webkit-transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1.000);
-      transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1.000);
-    }
-
-    .loaded #loader {
-      opacity: 0;
-      -webkit-transition: all 0.3s ease-out;
-      transition: all 0.3s ease-out;
-    }
-
-    .loaded #loader-wrapper {
-      visibility: hidden;
-      -webkit-transform: translateY(-100%);
-      /* Chrome, Opera 15+, Safari 3.1+ */
-      -ms-transform: translateY(-100%);
-      /* IE 9 */
-      transform: translateY(-100%);
-      /* Firefox 16+, IE 10+, Opera */
-      -webkit-transition: all 0.3s 1s ease-out;
-      transition: all 0.3s 1s ease-out;
-    }
-
-    /* JavaScript Turned Off */
-    .no-js #loader-wrapper {
-      display: none;
-    }
-
-    .no-js h1 {
-      color: #222222;
-    }
-
-    #loader-wrapper .load_title {
-      font-family: 'Open Sans';
-      color: #FFF;
-      font-size: 14px;
-      width: 100%;
-      text-align: center;
-      z-index: 9999999999999;
-      position: absolute;
-      top: 60%;
-      opacity: 1;
-      line-height: 30px;
-    }
-
-    #loader-wrapper .load_title span {
-      font-weight: normal;
-      font-style: italic;
-      font-size: 14px;
-      color: #FFF;
-      opacity: 0.5;
-    }
-
-    /* 滚动条优化 start */
-    ::-webkit-scrollbar {
-      width: 8px;
-      height: 8px;
-    }
-
-    ::-webkit-scrollbar-track {
-      background: #f6f6f6;
-      border-radius: 2px;
-    }
-
-    ::-webkit-scrollbar-thumb {
-      background: #cdcdcd;
-      border-radius: 2px;
-    }
-
-    ::-webkit-scrollbar-thumb:hover {
-      background: #747474;
-    }
-
-    ::-webkit-scrollbar-corner {
-      background: #f6f6f6;
-    }
-
-    /* 滚动条优化 end */
-  </style>
-  <!-- 全局配置 -->
-  <script>
-    window._CONFIG = {};
-    window._CONFIG['domianURL'] = 'http://localhost:8080/jeecg-boot';
-    window._CONFIG['imgDomainURL'] = 'http://localhost:8080/jeecg-boot/sys/common/view';
-    window._CONFIG['pdfDomainURL'] = 'http://localhost:8080/jeecg-boot/sys/common/pdf/pdfPreviewIframe';
-  </script>
-</head>
-
-<body>
-<!-- built files will be auto injected -->
-<div id="app">
-  <div id="loader-wrapper">
-    <div id="loader"></div>
-    <div class="loader-section section-left"></div>
-    <div class="loader-section section-right"></div>
-
-    <div class="load_title">正在加载数据,请耐心等待
-
-
-    </div>
-  </div>
-</div>
-
-<!-- update_begin author:sunjianlei date:20190524 for: 去指定页面的加载动画 -->
-<script src="https://ssl.captcha.qq.com/TCaptcha.js"></script>
-<script>
-  // 去指定页面的加载动画
-  if (location.href.indexOf('online/desform/pureview') !== -1) {
-    document.getElementById('loader-wrapper').style.display = 'none'
-  }
-</script>
-<!-- update_end author:sunjianlei date:20190524 for: 去指定页面的加载动画 -->
-</body>
-
+<!DOCTYPE html>
+<html lang="zh-cmn-Hans">
+
+<head>
+  <meta charset="utf-8">
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="viewport" content="width=device-width,initial-scale=1.0">
+  <title>汇创投放助手</title>
+  <link rel="icon" href="<%= BASE_URL %>logo.png">
+  <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-polyfill/7.2.5/polyfill.js"></script>
+  <style>
+    html,
+    body,
+    #app {
+      height: 100%;
+      margin: 0px;
+      padding: 0px;
+    }
+
+    .chromeframe {
+      margin: 0.2em 0;
+      background: #ccc;
+      color: #000;
+      padding: 0.2em 0;
+    }
+
+    #loader-wrapper {
+      position: fixed;
+      top: 0;
+      left: 0;
+      width: 100%;
+      height: 100%;
+      z-index: 999999;
+    }
+
+    #loader {
+      display: block;
+      position: relative;
+      left: 50%;
+      top: 50%;
+      width: 120px;
+      height: 120px;
+      margin: -75px 0 0 -75px;
+      border-radius: 50%;
+      border: 3px solid transparent;
+      /* COLOR 1 */
+      border-top-color: #FFF;
+      -webkit-animation: spin 2s linear infinite;
+      /* Chrome, Opera 15+, Safari 5+ */
+      -ms-animation: spin 2s linear infinite;
+      /* Chrome, Opera 15+, Safari 5+ */
+      -moz-animation: spin 2s linear infinite;
+      /* Chrome, Opera 15+, Safari 5+ */
+      -o-animation: spin 2s linear infinite;
+      /* Chrome, Opera 15+, Safari 5+ */
+      animation: spin 2s linear infinite;
+      /* Chrome, Firefox 16+, IE 10+, Opera */
+      z-index: 1001;
+    }
+
+    #loader:before {
+      content: "";
+      position: absolute;
+      top: 5px;
+      left: 5px;
+      right: 5px;
+      bottom: 5px;
+      border-radius: 50%;
+      border: 3px solid transparent;
+      /* COLOR 2 */
+      border-top-color: #FFF;
+      -webkit-animation: spin 3s linear infinite;
+      /* Chrome, Opera 15+, Safari 5+ */
+      -moz-animation: spin 3s linear infinite;
+      /* Chrome, Opera 15+, Safari 5+ */
+      -o-animation: spin 3s linear infinite;
+      /* Chrome, Opera 15+, Safari 5+ */
+      -ms-animation: spin 3s linear infinite;
+      /* Chrome, Opera 15+, Safari 5+ */
+      animation: spin 3s linear infinite;
+      /* Chrome, Firefox 16+, IE 10+, Opera */
+    }
+
+    #loader:after {
+      content: "";
+      position: absolute;
+      top: 15px;
+      left: 15px;
+      right: 15px;
+      bottom: 15px;
+      border-radius: 50%;
+      border: 3px solid transparent;
+      border-top-color: #FFF;
+      /* COLOR 3 */
+      -moz-animation: spin 1.5s linear infinite;
+      /* Chrome, Opera 15+, Safari 5+ */
+      -o-animation: spin 1.5s linear infinite;
+      /* Chrome, Opera 15+, Safari 5+ */
+      -ms-animation: spin 1.5s linear infinite;
+      /* Chrome, Opera 15+, Safari 5+ */
+      -webkit-animation: spin 1.5s linear infinite;
+      /* Chrome, Opera 15+, Safari 5+ */
+      animation: spin 1.5s linear infinite;
+      /* Chrome, Firefox 16+, IE 10+, Opera */
+    }
+
+    @-webkit-keyframes spin {
+      0% {
+        -webkit-transform: rotate(0deg);
+        /* Chrome, Opera 15+, Safari 3.1+ */
+        -ms-transform: rotate(0deg);
+        /* IE 9 */
+        transform: rotate(0deg);
+        /* Firefox 16+, IE 10+, Opera */
+      }
+      100% {
+        -webkit-transform: rotate(360deg);
+        /* Chrome, Opera 15+, Safari 3.1+ */
+        -ms-transform: rotate(360deg);
+        /* IE 9 */
+        transform: rotate(360deg);
+        /* Firefox 16+, IE 10+, Opera */
+      }
+    }
+
+    @keyframes spin {
+      0% {
+        -webkit-transform: rotate(0deg);
+        /* Chrome, Opera 15+, Safari 3.1+ */
+        -ms-transform: rotate(0deg);
+        /* IE 9 */
+        transform: rotate(0deg);
+        /* Firefox 16+, IE 10+, Opera */
+      }
+      100% {
+        -webkit-transform: rotate(360deg);
+        /* Chrome, Opera 15+, Safari 3.1+ */
+        -ms-transform: rotate(360deg);
+        /* IE 9 */
+        transform: rotate(360deg);
+        /* Firefox 16+, IE 10+, Opera */
+      }
+    }
+
+    #loader-wrapper .loader-section {
+      position: fixed;
+      top: 0;
+      width: 51%;
+      height: 100%;
+      background: #49a9ee;
+      /* Old browsers */
+      z-index: 1000;
+      -webkit-transform: translateX(0);
+      /* Chrome, Opera 15+, Safari 3.1+ */
+      -ms-transform: translateX(0);
+      /* IE 9 */
+      transform: translateX(0);
+      /* Firefox 16+, IE 10+, Opera */
+    }
+
+    #loader-wrapper .loader-section.section-left {
+      left: 0;
+    }
+
+    #loader-wrapper .loader-section.section-right {
+      right: 0;
+    }
+
+    /* Loaded */
+    .loaded #loader-wrapper .loader-section.section-left {
+      -webkit-transform: translateX(-100%);
+      /* Chrome, Opera 15+, Safari 3.1+ */
+      -ms-transform: translateX(-100%);
+      /* IE 9 */
+      transform: translateX(-100%);
+      /* Firefox 16+, IE 10+, Opera */
+      -webkit-transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1.000);
+      transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1.000);
+    }
+
+    .loaded #loader-wrapper .loader-section.section-right {
+      -webkit-transform: translateX(100%);
+      /* Chrome, Opera 15+, Safari 3.1+ */
+      -ms-transform: translateX(100%);
+      /* IE 9 */
+      transform: translateX(100%);
+      /* Firefox 16+, IE 10+, Opera */
+      -webkit-transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1.000);
+      transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1.000);
+    }
+
+    .loaded #loader {
+      opacity: 0;
+      -webkit-transition: all 0.3s ease-out;
+      transition: all 0.3s ease-out;
+    }
+
+    .loaded #loader-wrapper {
+      visibility: hidden;
+      -webkit-transform: translateY(-100%);
+      /* Chrome, Opera 15+, Safari 3.1+ */
+      -ms-transform: translateY(-100%);
+      /* IE 9 */
+      transform: translateY(-100%);
+      /* Firefox 16+, IE 10+, Opera */
+      -webkit-transition: all 0.3s 1s ease-out;
+      transition: all 0.3s 1s ease-out;
+    }
+
+    /* JavaScript Turned Off */
+    .no-js #loader-wrapper {
+      display: none;
+    }
+
+    .no-js h1 {
+      color: #222222;
+    }
+
+    #loader-wrapper .load_title {
+      font-family: 'Open Sans';
+      color: #FFF;
+      font-size: 14px;
+      width: 100%;
+      text-align: center;
+      z-index: 9999999999999;
+      position: absolute;
+      top: 60%;
+      opacity: 1;
+      line-height: 30px;
+    }
+
+    #loader-wrapper .load_title span {
+      font-weight: normal;
+      font-style: italic;
+      font-size: 14px;
+      color: #FFF;
+      opacity: 0.5;
+    }
+
+    /* 滚动条优化 start */
+    ::-webkit-scrollbar {
+      width: 8px;
+      height: 8px;
+    }
+
+    ::-webkit-scrollbar-track {
+      background: #f6f6f6;
+      border-radius: 2px;
+    }
+
+    ::-webkit-scrollbar-thumb {
+      background: #cdcdcd;
+      border-radius: 2px;
+    }
+
+    ::-webkit-scrollbar-thumb:hover {
+      background: #747474;
+    }
+
+    ::-webkit-scrollbar-corner {
+      background: #f6f6f6;
+    }
+
+    /* 滚动条优化 end */
+  </style>
+  <!-- 全局配置 -->
+  <script>
+    window._CONFIG = {};
+    window._CONFIG['domianURL'] = 'http://localhost:8080/jeecg-boot';
+    window._CONFIG['imgDomainURL'] = 'http://localhost:8080/jeecg-boot/sys/common/view';
+    window._CONFIG['pdfDomainURL'] = 'http://localhost:8080/jeecg-boot/sys/common/pdf/pdfPreviewIframe';
+  </script>
+</head>
+
+<body>
+<!-- built files will be auto injected -->
+<div id="app">
+  <div id="loader-wrapper">
+    <div id="loader"></div>
+    <div class="loader-section section-left"></div>
+    <div class="loader-section section-right"></div>
+
+    <div class="load_title">正在加载数据,请耐心等待
+
+
+    </div>
+  </div>
+</div>
+
+<!-- update_begin author:sunjianlei date:20190524 for: 去指定页面的加载动画 -->
+<script src="https://ssl.captcha.qq.com/TCaptcha.js"></script>
+
+<script src="<%= BASE_URL %>xlsx.extendscript.js"></script>
+<script src="<%= BASE_URL %>xlsx.full.min.js"></script>
+
+<script src="<%= BASE_URL %>export.js"></script>
+<script>
+  // 去指定页面的加载动画
+  if (location.href.indexOf('online/desform/pureview') !== -1) {
+    document.getElementById('loader-wrapper').style.display = 'none'
+  }
+</script>
+<!-- update_end author:sunjianlei date:20190524 for: 去指定页面的加载动画 -->
+</body>
+
 </html>

public/logo.png → public/logo1.png


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 30150 - 0
public/xlsx.extendscript.js


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 24 - 0
public/xlsx.full.min.js


+ 10 - 0
src/api/statistics.js

@@ -17,4 +17,14 @@ export function getReportList(parameter) {
       method: 'post',
       data: parameter
     })
+}
+
+
+// getReportList 
+export function getStatistics(parameter) {
+    return axios({
+      url: "/ctop/accountReport/getStatistics",
+      method: 'post',
+      data: parameter
+    })
 }

BIN
src/assets/logo.png


BIN
src/assets/logo1.png


+ 153 - 153
src/components/layouts/UserLayout.vue

@@ -1,154 +1,154 @@
-<template>
-  <div id="userLayout" :class="['user-layout-wrapper', device]">
-    <div class="container">
-      <div class="top">
-        <div class="header">
-          <a href="/">
-            <img src="~@/assets/logo.png" class="logo" alt="logo" style="height: 66px">
-            <!--            <span class="title">Jeecg Boot</span>-->
-          </a>
-        </div>
-        <!--        <div class="desc">-->
-        <!--          Jeecg Boot 是中国最具影响力的 企业级 快速开发平台-->
-        <!--        </div>-->
-      </div>
-
-      <route-view></route-view>
-
-      <div class="footer">
-        <div class="links">
-          <a href="http://jeecg-boot.mydoc.io" target="_blank">帮助</a>
-          <a href="https://github.com/zhangdaiscott/jeecg-boot" target="_blank">隐私</a>
-          <a href="https://github.com/zhangdaiscott/jeecg-boot" target="_blank">条款</a>
-        </div>
-        <div class="copyright">
-          Copyright &copy; 2019 <a href="http://www.jeecg.org" target="_blank">JEECG开源社区</a> 出品
-        </div>
-      </div>
-    </div>
-  </div>
-</template>
-
-<script>
-  import RouteView from "@/components/layouts/RouteView"
-  import {mixinDevice} from '@/utils/mixin.js'
-
-  export default {
-    name: "UserLayout",
-    components: {RouteView},
-    mixins: [mixinDevice],
-    data() {
-      return {}
-    },
-    mounted() {
-      document.body.classList.add('userLayout')
-    },
-    beforeDestroy() {
-      document.body.classList.remove('userLayout')
-    },
-  }
-</script>
-
-<style lang="scss" scoped>
-  #userLayout.user-layout-wrapper {
-    height: 100%;
-
-    &.mobile {
-      .container {
-        .main {
-          max-width: 368px;
-          width: 98%;
-        }
-      }
-    }
-
-    .container {
-      width: 100%;
-      min-height: 100%;
-      background: #f0f2f5 url(~@/assets/background.svg) no-repeat 50%;
-      background-size: 100%;
-      padding: 110px 0 144px;
-      position: relative;
-
-      a {
-        text-decoration: none;
-      }
-
-      .top {
-        text-align: center;
-
-        .header {
-          height: 44px;
-          line-height: 44px;
-
-          .badge {
-            position: absolute;
-            display: inline-block;
-            line-height: 1;
-            vertical-align: middle;
-            margin-left: -12px;
-            margin-top: -10px;
-            opacity: 0.8;
-          }
-
-          .logo {
-            height: 44px;
-            vertical-align: top;
-            margin-right: 16px;
-            border-style: none;
-          }
-
-          .title {
-            font-size: 33px;
-            color: rgba(0, 0, 0, .85);
-            font-family: "Chinese Quote", -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
-            font-weight: 600;
-            position: relative;
-            top: 2px;
-          }
-        }
-
-        .desc {
-          font-size: 14px;
-          color: rgba(0, 0, 0, 0.45);
-          margin-top: 12px;
-          margin-bottom: 40px;
-        }
-      }
-
-      .main {
-        min-width: 260px;
-        width: 368px;
-        margin: 0 auto;
-      }
-
-      .footer {
-        position: absolute;
-        width: 100%;
-        bottom: 0;
-        padding: 0 16px;
-        margin: 48px 0 24px;
-        text-align: center;
-
-        .links {
-          margin-bottom: 8px;
-          font-size: 14px;
-
-          a {
-            color: rgba(0, 0, 0, 0.45);
-            transition: all 0.3s;
-
-            &:not(:last-child) {
-              margin-right: 40px;
-            }
-          }
-        }
-
-        .copyright {
-          color: rgba(0, 0, 0, 0.45);
-          font-size: 14px;
-        }
-      }
-    }
-  }
+<template>
+  <div id="userLayout" :class="['user-layout-wrapper', device]">
+    <div class="container">
+      <div class="top" style="margin-bottom:15px">
+        <div class="header">
+          <a href="/">
+            <img src="~@/assets/logo.png" class="logo" alt="logo" style="height: 66px" />
+            <!--            <span class="title">Jeecg Boot</span>-->
+          </a>
+        </div>
+        <!--        <div class="desc">-->
+        <!--          Jeecg Boot 是中国最具影响力的 企业级 快速开发平台-->
+        <!--        </div>-->
+      </div>
+
+      <route-view></route-view>
+
+      <div class="footer">
+        <!-- <div class="links">
+          <a href="http://jeecg-boot.mydoc.io" target="_blank">帮助</a>
+          <a href="https://github.com/zhangdaiscott/jeecg-boot" target="_blank">隐私</a>
+          <a href="https://github.com/zhangdaiscott/jeecg-boot" target="_blank">条款</a>
+        </div>-->
+        <div class="copyright">Copyright &copy; 2019 汇创思拓</div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import RouteView from '@/components/layouts/RouteView'
+import { mixinDevice } from '@/utils/mixin.js'
+
+export default {
+  name: 'UserLayout',
+  components: { RouteView },
+  mixins: [mixinDevice],
+  data() {
+    return {}
+  },
+  mounted() {
+    document.body.classList.add('userLayout')
+  },
+  beforeDestroy() {
+    document.body.classList.remove('userLayout')
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+#userLayout.user-layout-wrapper {
+  height: 100%;
+
+  &.mobile {
+    .container {
+      .main {
+        max-width: 368px;
+        width: 98%;
+      }
+    }
+  }
+
+  .container {
+    width: 100%;
+    min-height: 100%;
+    background: #f0f2f5 url(~@/assets/background.svg) no-repeat 50%;
+    background-size: 100%;
+    padding: 110px 0 144px;
+    position: relative;
+
+    a {
+      text-decoration: none;
+    }
+
+    .top {
+      text-align: center;
+
+      .header {
+        height: 44px;
+        line-height: 44px;
+
+        .badge {
+          position: absolute;
+          display: inline-block;
+          line-height: 1;
+          vertical-align: middle;
+          margin-left: -12px;
+          margin-top: -10px;
+          opacity: 0.8;
+        }
+
+        .logo {
+          height: 44px;
+          vertical-align: top;
+          margin-right: 16px;
+          border-style: none;
+        }
+
+        .title {
+          font-size: 33px;
+          color: rgba(0, 0, 0, 0.85);
+          font-family: 'Chinese Quote', -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', 'Hiragino Sans GB',
+            'Microsoft YaHei', 'Helvetica Neue', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji',
+            'Segoe UI Symbol';
+          font-weight: 600;
+          position: relative;
+          top: 2px;
+        }
+      }
+
+      .desc {
+        font-size: 14px;
+        color: rgba(0, 0, 0, 0.45);
+        margin-top: 12px;
+        margin-bottom: 40px;
+      }
+    }
+
+    .main {
+      min-width: 260px;
+      width: 368px;
+      margin: 0 auto;
+    }
+
+    .footer {
+      position: absolute;
+      width: 100%;
+      bottom: 0;
+      padding: 0 16px;
+      margin: 48px 0 24px;
+      text-align: center;
+
+      .links {
+        margin-bottom: 8px;
+        font-size: 14px;
+
+        a {
+          color: rgba(0, 0, 0, 0.45);
+          transition: all 0.3s;
+
+          &:not(:last-child) {
+            margin-right: 40px;
+          }
+        }
+      }
+
+      .copyright {
+        color: rgba(0, 0, 0, 0.45);
+        font-size: 14px;
+      }
+    }
+  }
+}
 </style>

+ 277 - 65
src/views/modules/Statistics/dataDisplayStatistics.vue

@@ -85,7 +85,19 @@
               v-for="appModel in options"
               :key="appModel.accountId"
               :value="appModel.accountId"
-            >{{appModel.advertiserName}}&#12288;&#12288;{{appModel.accountId}}&#12288;&nbsp;&#12288;{{appModel.authName}}&#12288;&#12288;{{appModel.operationName}}</a-select-option>
+            >
+              <!-- <div
+                style="width:220px;text-align:right;display:inline-block"
+              >{{appModel.advertiserName}}</div>
+              <div
+                style="width:100px;text-align:center;display:inline-block;margin-right:30px"
+              >{{appModel.accountId}}</div>
+              <div style="width:150px;text-align:left;display:inline-block">{{appModel.authName}}</div>
+              <div
+                style="width:100px;text-align:center;display:inline-block"
+              >{{appModel.operationName}}</div>-->
+              {{appModel.advertiserName}}&#12288;&#12288;{{appModel.accountId}}&#12288;&nbsp;&#12288;{{appModel.authName}}&#12288;&#12288;{{appModel.operationName}}
+            </a-select-option>
           </a-select>
           <a-input-number
             :min="1"
@@ -205,8 +217,18 @@
     <a-row :gutter="10" style="margin-top:10px">
       <a-col :span="24">
         <a-card style="width:100%;">
-          <div @click="exportExcel">导出</div>
-          <a-table :columns="columns" :dataSource="data" bordered id="outTable"></a-table>
+          <div style="display:flex;margin-bottom:15px" v-show="active==1||active==2">
+            <a-select
+              style="width: 120px"
+              v-model="statHour"
+              placeholder="请选择账户"
+              @change="getElseData"
+            >
+              <a-select-option v-for="item of 24" :key="item-1" :value="item-1">{{item-1}}</a-select-option>
+            </a-select>
+            <a-button type="primary" @click="exportExcel" style="margin-left:15px">导出</a-button>
+          </div>
+          <a-table :columns="columns" :dataSource="data" bordered id="outTable" :pagination="false"></a-table>
         </a-card>
       </a-col>
     </a-row>
@@ -218,12 +240,8 @@ import ARow from 'ant-design-vue/es/grid/Row'
 import ACol from 'ant-design-vue/es/grid/Col'
 import countTo from 'vue-count-to'
 import moment from 'moment'
-import { getAdvertiserList, getReportList } from '@api/statistics'
+import { getAdvertiserList, getReportList, getStatistics } from '@api/statistics'
 import axios from 'axios'
-
-import FileSaver from 'file-saver'
-
-import XLSX from 'xlsx'
 import lifting from './components/lifting'
 
 // 引入基本模板
@@ -238,68 +256,88 @@ require('echarts/lib/component/title')
 require('echarts/lib/component/graphic')
 require('echarts/lib/component/toolbox')
 require('echarts/lib/component/legend')
+var length = 0
 const columns = [
+  { title: '账户名称', dataIndex: 'accountName', align: 'left' },
   {
-    title: 'Name',
-    dataIndex: 'name',
-    scopedSlots: { customRender: 'name' },
-    customRender: function(text, record, index) {
-      const obj = {
-        children: text,
-        attrs: {}
-      }
-      if (index == 0) {
-        obj.attrs.rowSpan = 4
-      }
-      if (index == 1) {
-        obj.attrs.rowSpan = 0
-      }
-      if (index == 2) {
-        obj.attrs.rowSpan = 0
-      }
-      if (index == 3) {
-        obj.attrs.rowSpan = 0
-      }
-      return obj
-    }
+    title: '消耗',
+    dataIndex: 'cost',
+    scopedSlots: { customRender: 'cost' },
+    align: 'center'
   },
   {
-    title: 'Cash Assets',
-    className: 'column-money',
-    dataIndex: 'money'
+    title: '折后消耗',
+    dataIndex: 'costY',
+    align: 'center'
   },
   {
-    title: 'Address',
-    dataIndex: 'address'
-  }
-]
-
-const data = [
+    title: '封面展示',
+    dataIndex: 'photoShow',
+    align: 'center'
+  },
+  {
+    title: '封面点击',
+    dataIndex: 'photoClick',
+    align: 'center'
+  },
+  {
+    title: '素材曝光数',
+    dataIndex: 'aclick',
+    align: 'center'
+  },
   {
-    key: '1',
-    name: 'John Brown',
-    money: '¥300,000.00',
-    address: 'New York No. 1 Lake Park'
+    title: '封面点击率',
+    dataIndex: 'photoClickRatio',
+    align: 'center'
   },
   {
-    key: '2',
-    name: 'Jim Green',
-    money: '¥1,256,000.00',
-    address: 'London No. 1 Lake Park'
+    title: 'cvr',
+    dataIndex: 'cvr',
+    align: 'center'
   },
   {
-    key: '3',
-    name: 'Joe Black',
-    money: '¥120,000.00',
-    address: 'Sidney No. 1 Lake Park'
+    title: 'cpm',
+    dataIndex: 'cpm',
+    align: 'center'
   },
   {
-    key: '4',
-    name: 'Joe Black',
-    money: '合计',
-    address: '123123'
+    title: '行为数',
+    dataIndex: 'bClick',
+    align: 'center'
+  },
+  {
+    title: '表单提交数',
+    dataIndex: 'formCount',
+    align: 'center'
+  },
+  {
+    title: '表单提交单价',
+    dataIndex: 'formPrice',
+    align: 'center'
+  },
+  {
+    title: '单价区间',
+    dataIndex: 'price',
+    align: 'center',
+    customRender: function(text, record, index) {
+      const obj = {
+        children: text,
+        attrs: {}
+      }
+      for (let i = 0; i < length; i++) {
+        if (index == 0 && i == 0) {
+          obj.attrs.rowSpan = length
+        } else {
+          if (index == i) {
+            obj.attrs.rowSpan = 0
+          }
+        }
+      }
+      return obj
+    }
   }
 ]
+
 export default {
   name: 'data-display-statistics',
   components: {
@@ -312,11 +350,12 @@ export default {
   data: function() {
     return {
       title: '账户数据展示',
-      data,
+      data: [],
       columns,
       options: [],
       list: [],
       appId: [],
+      statHour: null,
       keyValue: null,
       keyValueData: [],
       active: 1,
@@ -388,6 +427,9 @@ export default {
       console.log(value)
       //   this.appId = value
     },
+    getElseData(value) {
+      this.getStatistics()
+    },
     handleBlur() {
       console.log('blur')
     },
@@ -412,6 +454,7 @@ export default {
           var data = item.accountId + ' ' + item.authName + ' ' + item.advertiserName + ' ' + item.operationName
           return data.toLowerCase().indexOf(value.toLowerCase()) > -1
         })
+        console.log(this.options)
       } else {
         this.options = this.list
       }
@@ -441,10 +484,91 @@ export default {
             that.drawPie(that.noTitleKey, res.trend)
           }
         })
+        that.getStatistics()
       } else {
         this.$message.error('请选择账户')
       }
     },
+    getStatistics() {
+      var params = {}
+      params.accountIds = JSON.stringify(this.appId)
+      params.type = this.active
+      params.statHour = this.statHour
+      if (this.active == 9) {
+        params.startDate = dateValue[0]
+        params.endDate = dateValue[1]
+      }
+      this.data = []
+      getStatistics(params).then(res => {
+        console.log(res)
+        this.data = res.accountDetail.map((item, index) => {
+          return {
+            key: index,
+            ...item,
+            accountName: item.accountId,
+            photoClickRatio: item.photoClickRatio ? (item.photoClickRatio * 100).toFixed(2) + '%' : 0 + '%',
+            cpm: item.cpm ? '¥' + item.cpm.toFixed(2) : '¥' + 0,
+            cost: '¥' + item.cost.toFixed(2),
+            cvr: item.cvr ? item.cvr.toFixed(2) + '%' : 0 + '%',
+            costY: '¥' + (item.cost / this.discount).toFixed(2),
+            formPrice: item.formPrice ? item.formPrice : 0
+          }
+        })
+        var index = this.data.length
+        if (this.active == 1) {
+          var allNow = {
+            key: index + 1,
+            ...res.now,
+            photoClickRatio: res.now.photoClickRatio ? (res.now.photoClickRatio * 100).toFixed(2) + '%' : 0 + '%',
+            cpm: res.now.cpm ? '¥' + res.now.cpm.toFixed(2) : '¥' + 0,
+            cost: '¥' + res.now.cost.toFixed(2),
+            cvr: res.now.cvr ? res.now.cvr.toFixed(2) + '%' : 0 + '%',
+            costY: '¥' + (res.now.cost / this.discount).toFixed(2),
+            accountName: '总计',
+            formPrice: res.now.formPrice ? res.now.formPrice : 0
+          }
+          var allYesterday = {
+            key: index + 2,
+            ...res.yesterday,
+            photoClickRatio: res.yesterday.photoClickRatio
+              ? (res.yesterday.photoClickRatio * 100).toFixed(2) + '%'
+              : 0 + '%',
+            cpm: res.yesterday.cpm ? '¥' + res.yesterday.cpm.toFixed(2) : '¥' + 0,
+            cost: '¥' + res.yesterday.cost.toFixed(2),
+            cvr: res.yesterday.cvr ? res.yesterday.cvr.toFixed(2) + '%' : 0 + '%',
+            costY: '¥' + (res.yesterday.cost / this.discount).toFixed(2),
+            accountName: '昨日总计',
+            formPrice: res.now.yesterday ? res.now.yesterday : 0
+          }
+          var chainRatio = {
+            key: index + 3,
+            cost: (res.chainRatio.costProportion * 100).toFixed(2) + '%',
+            photoShow: (res.chainRatio.showProportion * 100).toFixed(2) + '%',
+            photoClick: (res.chainRatio.photoClickProportion * 100).toFixed(2) + '%',
+            aclick: (res.chainRatio.aClickProportion * 100).toFixed(2) + '%',
+            photoClickRatio: res.chainRatio.photoClickRatioProportion
+              ? (res.chainRatio.photoClickRatioProportion * 100).toFixed(2) + '%'
+              : 0 + '%',
+            cvr: (res.chainRatio.cvrProportion * 100).toFixed(2) + '%',
+            cpm: (res.chainRatio.cpmProportion * 100).toFixed(2) + '%',
+            bClick: (res.chainRatio.bClickProportion * 100).toFixed(2) + '%',
+            formCount: res.chainRatio.formCountProportion
+              ? (res.chainRatio.formCountProportion * 100).toFixed(2) + '%'
+              : 0 + '%',
+            formPrice: res.chainRatio.formPriceProportion
+              ? (res.chainRatio.formPriceProportion * 100).toFixed(2) + '%'
+              : 0 + '%',
+            costY: (res.chainRatio.costProportion * 100).toFixed(2) + '%',
+            accountName: '环比'
+          }
+          this.data.push(allNow)
+          this.data.push(allYesterday)
+          this.data.push(chainRatio)
+        }
+
+        length = this.data.length
+      })
+    },
     getAdd(checked) {
       if (checked == 9) {
         if (this.startValue.length > 0 && this.startValue[0]) {
@@ -694,16 +818,104 @@ export default {
       }
     },
     exportExcel() {
-      let vb = XLSX.utils.table_to_book(document.getElementById('outTable'), { display: true })
-      console.log(document.getElementById('outTable'), vb)
-      let vbout = XLSX.write(vb, { bookType: 'xlsx', bookSST: true, type: 'array' })
-
-      try {
-        FileSaver.saveAs(new Blob([vbout], { type: 'application/octet-stream' }), 'sheetjs.xlsx')
-      } catch (e) {
-        if (typeof console !== 'undefined') console.log(e, vbout)
+      var title = ''
+      let date = new Date()
+      let y = date.getFullYear()
+      let MM = date.getMonth() + 1
+      MM = MM < 10 ? '0' + MM : MM
+      let d = date.getDate()
+      d = d < 10 ? '0' + d : d
+      let h = date.getHours() - 1
+      h = h < 10 ? '0' + h : h
+      if (this.statHour) {
+        title = y + '-' + MM + '-' + d + '  ' + this.statHour + '时数据报表'
+      } else {
+        title = y + '-' + MM + '-' + d + '  ' + h + '时数据报表'
       }
-      return vbout
+      var opt = {
+        rowIndex: 4
+      } //开头空4行
+      var sheet = XLSX2.utils.table_to_sheet(document.getElementById('outTable'), opt)
+      sheet['A1'] = {
+        t: 's',
+        v: title
+      } //给A1单元格赋值
+      sheet['A5'].s = {
+        alignment: {
+          horizontal: 'center',
+          vertical: 'center',
+          wrap_text: true
+        },
+        font: {
+          name: '宋体',
+          sz: 24,
+          bold: true,
+          underline: true,
+          color: {
+            rgb: 'FFFFAA00'
+          }
+        }
+      }
+      console.log(sheet['A5'])
+      //["!merges"]这个属性是专门用来进行单元格合并的
+      sheet['!merges'].push({
+        //如果不为空push 为空 = 赋值
+        //合并单元格 index都从0开始
+        s: {
+          //s开始
+          c: 0, //开始列
+          r: 0 //开始行
+        },
+        e: {
+          //e结束
+          c: 12, //结束列
+          r: 3 //结束行
+        }
+      })
+
+      sheet['!cols'] = [
+        {
+          wpx: 200
+        },
+        {
+          wpx: 100
+        },
+        {
+          wpx: 100
+        },
+        {
+          wpx: 100
+        },
+        {
+          wpx: 100
+        },
+        {
+          wpx: 100
+        },
+        {
+          wpx: 100
+        },
+        {
+          wpx: 100
+        },
+        {
+          wpx: 100
+        },
+        {
+          wpx: 100
+        },
+        {
+          wpx: 100
+        },
+        {
+          wpx: 100
+        },
+        {
+          wpx: 100
+        }
+      ] //单元格列宽
+
+      openDownloadDialog(sheet2blob(sheet), title + '.xlsx')
     }
   },
   watch: {},