Browse Source

添加表格导出

martin.ma 4 years ago
parent
commit
66b1601d6f
3 changed files with 365 additions and 202 deletions
  1. 1 0
      package.json
  2. 236 202
      pages/main/index/data.vue
  3. 128 0
      utils/excel.js

+ 1 - 0
package.json

@@ -28,6 +28,7 @@
 		"svgo": "^1.3.0",
 		"vue-quill-editor": "^3.0.6",
 		"vuedraggable": "^2.24.1",
+		"xlsx": "^0.18.5",
 		"yarn": "^1.22.10"
 	},
 	"devDependencies": {

+ 236 - 202
pages/main/index/data.vue

@@ -1,82 +1,92 @@
 <template>
-<div style="padding: 20px">
+  <div style="padding: 20px">
     <div style="padding-bottom: 20px">
-      <el-tag @click="getData_(0,'全部数据')">全部数据</el-tag>
-      <el-tag @click="getData_(1,'实名认证')" type="info">实名认证</el-tag>
-      <el-tag @click="getData_(2,'技术认证')" type="info">技术认证</el-tag>
-      <el-tag @click="getData_(3,'注册用户')" type="info">注册用户</el-tag>
-      <el-tag @click="getData_(4,'签约数量')" type="info">签约数量</el-tag>
-      <el-tag @click="getData_(5,'云端数量')" type="info">云端数量</el-tag>
-      <el-tag @click="getData_(7,'雇佣数量')" type="info">雇佣数量</el-tag>
-      <el-tag @click="getData_(6,'整包数量')" type="info">整包数量</el-tag>
+      <el-tag @click="getData_(0, '全部数据')">全部数据</el-tag>
+      <el-tag @click="getData_(1, '实名认证')" type="info">实名认证</el-tag>
+      <el-tag @click="getData_(2, '技术认证')" type="info">技术认证</el-tag>
+      <el-tag @click="getData_(3, '注册用户')" type="info">注册用户</el-tag>
+      <el-tag @click="getData_(4, '签约数量')" type="info">签约数量</el-tag>
+      <el-tag @click="getData_(5, '云端数量')" type="info">云端数量</el-tag>
+      <el-tag @click="getData_(7, '雇佣数量')" type="info">雇佣数量</el-tag>
+      <el-tag @click="getData_(6, '整包数量')" type="info">整包数量</el-tag>
     </div>
 
-  <div style="padding-bottom: 20px">
-    <el-select v-model="time_type" placeholder="请选择">
-      <el-option
-        v-for="item in time_type_data"
-        :key="item.value"
-        :label="item.label"
-        :value="item.value">
-      </el-option>
-    </el-select>
-    <el-date-picker
-      v-if="time_type==1"
-      v-model="date"
-      type="daterange"
-      style="width: 400px"
-      range-separator="至"
-      start-placeholder="开始日期"
-      end-placeholder="结束日期">
-    </el-date-picker>
-
-    <el-date-picker
-      v-if="time_type==2"
-      v-model="month"
-      style="width: 400px"
-      type="monthrange"
-      range-separator="至"
-      start-placeholder="开始月份"
-      end-placeholder="结束月份">
-    </el-date-picker>
-
-    <el-button @click="search" type="primary">查询</el-button>
-  </div>
+    <div style="padding-bottom: 20px">
+      <el-select v-model="time_type" placeholder="请选择">
+        <el-option
+          v-for="item in time_type_data"
+          :key="item.value"
+          :label="item.label"
+          :value="item.value"
+        >
+        </el-option>
+      </el-select>
+      <el-date-picker
+        v-if="time_type == 1"
+        v-model="date"
+        type="daterange"
+        style="width: 400px"
+        range-separator="至"
+        start-placeholder="开始日期"
+        end-placeholder="结束日期"
+      >
+      </el-date-picker>
 
-  <el-row>
-    <el-col :span="24">
-      <div class="grid-content bg-purple">
-        <Line-Chart :source="source" :title="title" :width="1200" :height="400"></Line-Chart>
-      </div>
-    </el-col>
-  </el-row>
-
-
-  <el-table
-    :data="source.rows"
-    :default-sort = "{prop: 'date', order: 'descending'}"
-    style="width: 100%">
-    <el-table-column
-      prop="date"
-      label="日期">
-      <template slot-scope="scope">
-        {{scope.row}}
-      </template>
-    </el-table-column>
-    <el-table-column
-      v-for="(value, index) in source.data"
-      :label="value.title">
-      <template slot-scope="scope">
-        {{source.data[index].data[source.rows.length-scope.$index-1]}}
-      </template>
-    </el-table-column>
-  </el-table>
-
-</div>
+      <el-date-picker
+        v-if="time_type == 2"
+        v-model="month"
+        style="width: 400px"
+        type="monthrange"
+        range-separator="至"
+        start-placeholder="开始月份"
+        end-placeholder="结束月份"
+      >
+      </el-date-picker>
+
+      <el-button @click="search" type="primary">查询</el-button>
+      <el-button @click="exportExcel" type="primary">导出表格</el-button>
+    </div>
+
+    <el-row>
+      <el-col :span="24">
+        <div class="grid-content bg-purple">
+          <Line-Chart
+            :source="source"
+            :title="title"
+            :width="1200"
+            :height="400"
+          ></Line-Chart>
+        </div>
+      </el-col>
+    </el-row>
+
+    <el-table
+      :data="source.rows"
+      :default-sort="{ prop: 'date', order: 'descending' }"
+      style="width: 100%"
+    >
+      <el-table-column prop="date" label="日期">
+        <template slot-scope="scope">
+          {{ scope.row }}
+        </template>
+      </el-table-column>
+      <el-table-column
+        v-for="(value, index) in source.data"
+        :label="value.title"
+      >
+        <template slot-scope="scope">
+          {{ source.data[index].data[source.rows.length - scope.$index - 1] }}
+        </template>
+      </el-table-column>
+    </el-table>
+  </div>
 </template>
 
 <script>
-import LineChart from "@/components/Echart/line"
+import LineChart from "@/components/Echart/line";
+import {
+  exportExcelFile
+} from "@/utils/excel";
 let firstDayOfThisMonth = new Date();
 firstDayOfThisMonth.setDate(1);
 firstDayOfThisMonth.setHours(0);
@@ -85,149 +95,173 @@ firstDayOfThisMonth.setSeconds(0);
 const startMonth = new Date();
 startMonth.setMonth(startMonth.getMonth() - 12);
 export default {
-    inheritAttrs: false,
-    components: {
-        LineChart
+  inheritAttrs: false,
+  components: {
+    LineChart
+  },
+  props: [],
+  data() {
+    return {
+      title: "实名认证数据面板",
+      source: {
+        rows: [],
+        data: []
+      },
+      time_type_data: [
+        {
+          value: "1",
+          label: "按日"
+        },
+        {
+          value: "2",
+          label: "按月"
+        }
+      ],
+      time_type: "1",
+      date: [firstDayOfThisMonth, new Date()],
+      month: [startMonth, firstDayOfThisMonth],
+      type: "0"
+    };
+  },
+  computed: {},
+  watch: {},
+  created() {},
+  mounted() {
+    this.getData_(0, "全部数据");
+  },
+  methods: {
+    async search() {
+      this.getData_(this.type, this.title);
     },
-    props: [],
-    data() {
-        return {
-            title: "实名认证数据面板",
-            source: {
-                rows: [],
-                data: []
-            },
-            time_type_data: [{
-              value: '1',
-              label: '按日'
-            }, {
-              value: '2',
-              label: '按月'
-            }],
-            time_type: '1',
-            date:[firstDayOfThisMonth, new Date()],
-            month:[startMonth,firstDayOfThisMonth],
-            type:"0",
+    async getData_(type, title) {
+      this.title = title;
+
+      let url = "";
+      if (type == 1) {
+        url = "/uapi/data/day/real_card";
+      } else if (type == 0) {
+        url = "/uapi/data/day/all";
+      } else if (type == 2) {
+        url = "/uapi/data/day/freework_level";
+      } else if (type == 3) {
+        url = "/uapi/data/day/user_register";
+      } else if (type == 4) {
+        url = "/uapi/data/day/user_sign";
+      } else if (type == 5) {
+        url = "/uapi/data/day/job?job_form_type=2";
+      } else if (type == 7) {
+        url = "/uapi/data/day/job?job_form_type=1";
+      } else if (type == 6) {
+        url = "/uapi/data/day/project";
+      }
+
+      let stime = "";
+      let etime = "";
+      if (this.time_type == 1) {
+        stime = this.formatDate(this.date[0] / 1000);
+        etime = this.formatDate(this.date[1] / 1000);
+      } else {
+        stime = this.formatDate(this.month[0] / 1000);
+        etime = this.formatDate(this.month[1] / 1000);
+      }
+
+      let res = await this.$post(url, {
+        time_type: this.time_type,
+        stime: stime,
+        etime: etime
+      });
+      if (res.status == 1) {
+        this.source = {
+          rows: res.data.day,
+          data: res.data.data
         };
+      }
     },
-    computed: {},
-    watch: {},
-    created() {},
-     mounted() {
-        this.getData_(0,"全部数据");
+    formatDate(time) {
+      if (time === "0") {
+        return "--";
+      }
+      let now = new Date(time * 1000);
+      let year = now.getFullYear();
+      let month = now.getMonth() + 1;
+      let date = now.getDate();
+      let hour = now.getHours();
+      let minute = now.getMinutes();
+      let second = now.getSeconds();
+
+      if (date < 10) {
+        date = "0" + date;
+      }
+
+      if (month < 10) {
+        month = "0" + month;
+      }
+
+      if (hour < 10) {
+        hour = "0" + hour;
+      }
+      if (minute < 10) {
+        minute = "0" + minute;
+      }
+      if (second < 10) {
+        second = "0" + second;
+      }
+      return (
+        year +
+        "-" +
+        month +
+        "-" +
+        date +
+        " " +
+        hour +
+        ":" +
+        minute +
+        ":" +
+        second
+      );
     },
-    methods: {
-      async search()
-      {
-        this.getData_(this.type,this.title)
-      },
-      async getData_(type,title) {
-        this.title=title;
+    exportExcel() {
+      console.log(this.source);
+      let title = this.source.data.map(item => {
+        return item.title;
+      });
+      let colArr = [];
 
-        let url="";
-        if(type==1)
-        {
-          url="/uapi/data/day/real_card";
-        }
-        else if(type==0)
-        {
-          url="/uapi/data/day/all";
-        }
-        else if(type==2)
-        {
-          url="/uapi/data/day/freework_level";
-        }
-        else if(type==3)
-        {
-          url="/uapi/data/day/user_register";
-        }
-        else if(type==4)
-        {
-          url="/uapi/data/day/user_sign";
-        }
-        else if(type==5)
-        {
-          url="/uapi/data/day/job?job_form_type=2";
-        }
-        else if(type==7)
-        {
-          url="/uapi/data/day/job?job_form_type=1";
-        }
-        else if(type==6)
-        {
-          url="/uapi/data/day/project";
-        }
+      this.source.rows.forEach((item, index) => {
+        let arr = [];
+        arr.push(item);
+        this.source.data.forEach((item2, index2) => {
+          arr.push(this.source.data[index2].data[index]);
+        });
+        colArr.push(arr);
+      });
 
-        let stime="";
-        let etime="";
-        if(this.time_type==1)
-        {
-          stime=this.formatDate(this.date[0]/1000);
-          etime=this.formatDate(this.date[1]/1000);
-        }
-        else
-        {
-          stime=this.formatDate(this.month[0]/1000);
-          etime=this.formatDate(this.month[1]/1000);
-        }
+      colArr = colArr.reverse();
+      colArr.unshift(["日期", ...title]);
+      let wscols = colArr.map((item) => {
+        return { wch: 10 }
+      });
 
-        let res = await this.$post(url,{time_type:this.time_type,stime:stime,etime:etime});
-        if(res.status==1)
-        {
-          this.source = {
-            rows: res.data.day,
-            data: res.data.data,
-          }
-        }
-      },
-      formatDate(time) {
-        if (time === "0") {
-          return "--";
-        }
-        let now = new Date(time * 1000);
-        let year = now.getFullYear();
-        let month = now.getMonth() + 1;
-        let date = now.getDate();
-        let hour = now.getHours();
-        let minute = now.getMinutes();
-        let second = now.getSeconds();
-
-        if (date < 10) {
-          date = "0" + date;
-        }
+      let stime = "";
+      let etime = "";
+      if (this.time_type == 1) {
+        stime = this.formatDate(this.date[0] / 1000);
+        etime = this.formatDate(this.date[1] / 1000);
+      } else {
+        stime = this.formatDate(this.month[0] / 1000);
+        etime = this.formatDate(this.month[1] / 1000);
+      }
 
-        if (month < 10) {
-          month = "0" + month;
-        }
 
-        if (hour < 10) {
-          hour = "0" + hour;
-        }
-        if (minute < 10) {
-          minute = "0" + minute;
-        }
-        if (second < 10) {
-          second = "0" + second;
-        }
-        return (
-          year +
-          "-" +
-          month +
-          "-" +
-          date +
-          " " +
-          hour +
-          ":" +
-          minute +
-          ":" +
-          second
-        );
-      },
+      exportExcelFile(colArr, wscols, `${stime} - ${etime}数据看版`);
+      console.log(colArr);
     }
+  }
 };
 </script>
 
-
 <style scoped>
-  .el-tag{cursor: pointer}
+.el-tag {
+  cursor: pointer;
+}
 </style>

+ 128 - 0
utils/excel.js

@@ -0,0 +1,128 @@
+var XLSX = require('xlsx')
+// 读取本地excel文件
+function readWorkbookFromLocalFile(file, callback) {
+    var reader = new FileReader();
+    reader.onload = function (e) {
+        var data = e.target.result;
+        var workbook = XLSX.read(data, { type: 'binary' });
+        if (callback) callback(workbook);
+    };
+    reader.readAsBinaryString(file);
+}
+/**
+     * 通用的打开下载对话框方法,没有测试过具体兼容性
+     * @param url 下载地址,也可以是一个blob对象,必选
+     * @param saveName 保存文件名,可选
+     */
+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);
+}
+
+// 将一个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 exportSpecialExcel() {
+    var aoa = [
+        ['扣款方id', '扣款方姓名', '收款方id', '收款方姓名', '调整款金额(元)'],
+        // ['A1', '张三', 'A2', '李四', 100],
+    ];
+    var sheet = XLSX.utils.aoa_to_sheet(aoa);
+
+    var wscols = [
+        { wch: 20 },
+        { wch: 20 },
+        { wch: 20 },
+        { wch: 20 },
+        { wch: 20 }
+    ];
+
+    sheet['!cols'] = wscols;
+    openDownloadDialog(sheet2blob(sheet), '调整款模板.xlsx');
+}
+
+
+function exportExcel(data,colSetting,fileName){
+    var aoa = [
+        ...data
+    ];
+    var sheet = XLSX.utils.aoa_to_sheet(aoa);
+
+    var wscols = [
+        ...colSetting
+    ];
+
+    sheet['!cols'] = wscols;
+    openDownloadDialog(sheet2blob(sheet), fileName+'.xlsx');
+}
+
+function readWorkbook2(workbook) {
+    var sheetNames = workbook.SheetNames; // 工作表名称集合
+    var worksheet = workbook.Sheets[sheetNames[0]]; // 这里我们只读取第一张sheet
+    var csv = XLSX.utils.sheet_to_csv(worksheet);
+    let getTabelData = csv2table(csv)
+}
+
+function csv2table(csv){
+
+    let array = [];
+    var rows = csv.split('\n');
+	rows.pop(); // 最后一行没用的
+    rows.forEach(function(row, idx) {
+        var columns = row.split(',');
+        if(idx > 0){
+            let params = {
+                c_merchant_id:columns[0],
+                charge_name:columns[1],
+                r_merchant_id:columns[2],
+                receive_name:columns[3],
+                adjust_cash:columns[4],
+            }
+            array.push(params)
+        }  
+    })
+    return array
+}
+
+export const downloadFile = exportSpecialExcel
+
+export const loadFile = readWorkbookFromLocalFile
+
+export const readWorkbook = readWorkbook2 
+
+export const exportExcelFile = exportExcel