bucket 6 anni fa
parent
commit
e6ed810f44

+ 4 - 1
package.json

@@ -15,6 +15,7 @@
15 15
     "axios": "0.17.1",
16 16
     "decimal.js": "^9.0.1",
17 17
     "element-ui": "2.0.5",
18
+    "file-saver": "^1.3.3",
18 19
     "js-cookie": "2.2.0",
19 20
     "lodash": "^4.17.4",
20 21
     "moment": "^2.19.4",
@@ -25,7 +26,8 @@
25 26
     "vue": "2.5.9",
26 27
     "vue-multiselect": "^2.0.8",
27 28
     "vue-router": "3.0.1",
28
-    "vuex": "3.0.1"
29
+    "vuex": "3.0.1",
30
+    "xlsx": "^0.11.19"
29 31
   },
30 32
   "devDependencies": {
31 33
     "autoprefixer": "7.1.6",
@@ -57,6 +59,7 @@
57 59
     "ora": "1.3.0",
58 60
     "rimraf": "2.6.2",
59 61
     "sass-loader": "6.0.6",
62
+    "script-loader": "^0.7.2",
60 63
     "semver": "5.4.1",
61 64
     "shelljs": "0.7.8",
62 65
     "svg-sprite-loader": "3.4.1",

+ 1 - 1
src/api/agnetManagement.js

@@ -55,7 +55,7 @@ export function fetchAllMemberList(query) {
55 55
 
56 56
 export function fetchGroupDetail(data, query) {
57 57
   return request({
58
-    url: `/agents/${data.GambleMember.id}/groupDetail`,
58
+    url: `/agents/${data.id}/groupDetail`,
59 59
     method: 'get',
60 60
     params: {
61 61
       startAt: query.startAt,

+ 179 - 0
src/vendor/Blob.js

@@ -0,0 +1,179 @@
1
+/* eslint-disable */
2
+/* Blob.js
3
+ * A Blob implementation.
4
+ * 2014-05-27
5
+ *
6
+ * By Eli Grey, http://eligrey.com
7
+ * By Devin Samarin, https://github.com/eboyjr
8
+ * License: X11/MIT
9
+ *   See LICENSE.md
10
+ */
11
+
12
+/*global self, unescape */
13
+/*jslint bitwise: true, regexp: true, confusion: true, es5: true, vars: true, white: true,
14
+ plusplus: true */
15
+
16
+/*! @source http://purl.eligrey.com/github/Blob.js/blob/master/Blob.js */
17
+
18
+(function (view) {
19
+    "use strict";
20
+
21
+    view.URL = view.URL || view.webkitURL;
22
+
23
+    if (view.Blob && view.URL) {
24
+        try {
25
+            new Blob;
26
+            return;
27
+        } catch (e) {}
28
+    }
29
+
30
+    // Internally we use a BlobBuilder implementation to base Blob off of
31
+    // in order to support older browsers that only have BlobBuilder
32
+    var BlobBuilder = view.BlobBuilder || view.WebKitBlobBuilder || view.MozBlobBuilder || (function(view) {
33
+            var
34
+                get_class = function(object) {
35
+                    return Object.prototype.toString.call(object).match(/^\[object\s(.*)\]$/)[1];
36
+                }
37
+                , FakeBlobBuilder = function BlobBuilder() {
38
+                    this.data = [];
39
+                }
40
+                , FakeBlob = function Blob(data, type, encoding) {
41
+                    this.data = data;
42
+                    this.size = data.length;
43
+                    this.type = type;
44
+                    this.encoding = encoding;
45
+                }
46
+                , FBB_proto = FakeBlobBuilder.prototype
47
+                , FB_proto = FakeBlob.prototype
48
+                , FileReaderSync = view.FileReaderSync
49
+                , FileException = function(type) {
50
+                    this.code = this[this.name = type];
51
+                }
52
+                , file_ex_codes = (
53
+                    "NOT_FOUND_ERR SECURITY_ERR ABORT_ERR NOT_READABLE_ERR ENCODING_ERR "
54
+                    + "NO_MODIFICATION_ALLOWED_ERR INVALID_STATE_ERR SYNTAX_ERR"
55
+                ).split(" ")
56
+                , file_ex_code = file_ex_codes.length
57
+                , real_URL = view.URL || view.webkitURL || view
58
+                , real_create_object_URL = real_URL.createObjectURL
59
+                , real_revoke_object_URL = real_URL.revokeObjectURL
60
+                , URL = real_URL
61
+                , btoa = view.btoa
62
+                , atob = view.atob
63
+
64
+                , ArrayBuffer = view.ArrayBuffer
65
+                , Uint8Array = view.Uint8Array
66
+                ;
67
+            FakeBlob.fake = FB_proto.fake = true;
68
+            while (file_ex_code--) {
69
+                FileException.prototype[file_ex_codes[file_ex_code]] = file_ex_code + 1;
70
+            }
71
+            if (!real_URL.createObjectURL) {
72
+                URL = view.URL = {};
73
+            }
74
+            URL.createObjectURL = function(blob) {
75
+                var
76
+                    type = blob.type
77
+                    , data_URI_header
78
+                    ;
79
+                if (type === null) {
80
+                    type = "application/octet-stream";
81
+                }
82
+                if (blob instanceof FakeBlob) {
83
+                    data_URI_header = "data:" + type;
84
+                    if (blob.encoding === "base64") {
85
+                        return data_URI_header + ";base64," + blob.data;
86
+                    } else if (blob.encoding === "URI") {
87
+                        return data_URI_header + "," + decodeURIComponent(blob.data);
88
+                    } if (btoa) {
89
+                        return data_URI_header + ";base64," + btoa(blob.data);
90
+                    } else {
91
+                        return data_URI_header + "," + encodeURIComponent(blob.data);
92
+                    }
93
+                } else if (real_create_object_URL) {
94
+                    return real_create_object_URL.call(real_URL, blob);
95
+                }
96
+            };
97
+            URL.revokeObjectURL = function(object_URL) {
98
+                if (object_URL.substring(0, 5) !== "data:" && real_revoke_object_URL) {
99
+                    real_revoke_object_URL.call(real_URL, object_URL);
100
+                }
101
+            };
102
+            FBB_proto.append = function(data/*, endings*/) {
103
+                var bb = this.data;
104
+                // decode data to a binary string
105
+                if (Uint8Array && (data instanceof ArrayBuffer || data instanceof Uint8Array)) {
106
+                    var
107
+                        str = ""
108
+                        , buf = new Uint8Array(data)
109
+                        , i = 0
110
+                        , buf_len = buf.length
111
+                        ;
112
+                    for (; i < buf_len; i++) {
113
+                        str += String.fromCharCode(buf[i]);
114
+                    }
115
+                    bb.push(str);
116
+                } else if (get_class(data) === "Blob" || get_class(data) === "File") {
117
+                    if (FileReaderSync) {
118
+                        var fr = new FileReaderSync;
119
+                        bb.push(fr.readAsBinaryString(data));
120
+                    } else {
121
+                        // async FileReader won't work as BlobBuilder is sync
122
+                        throw new FileException("NOT_READABLE_ERR");
123
+                    }
124
+                } else if (data instanceof FakeBlob) {
125
+                    if (data.encoding === "base64" && atob) {
126
+                        bb.push(atob(data.data));
127
+                    } else if (data.encoding === "URI") {
128
+                        bb.push(decodeURIComponent(data.data));
129
+                    } else if (data.encoding === "raw") {
130
+                        bb.push(data.data);
131
+                    }
132
+                } else {
133
+                    if (typeof data !== "string") {
134
+                        data += ""; // convert unsupported types to strings
135
+                    }
136
+                    // decode UTF-16 to binary string
137
+                    bb.push(unescape(encodeURIComponent(data)));
138
+                }
139
+            };
140
+            FBB_proto.getBlob = function(type) {
141
+                if (!arguments.length) {
142
+                    type = null;
143
+                }
144
+                return new FakeBlob(this.data.join(""), type, "raw");
145
+            };
146
+            FBB_proto.toString = function() {
147
+                return "[object BlobBuilder]";
148
+            };
149
+            FB_proto.slice = function(start, end, type) {
150
+                var args = arguments.length;
151
+                if (args < 3) {
152
+                    type = null;
153
+                }
154
+                return new FakeBlob(
155
+                    this.data.slice(start, args > 1 ? end : this.data.length)
156
+                    , type
157
+                    , this.encoding
158
+                );
159
+            };
160
+            FB_proto.toString = function() {
161
+                return "[object Blob]";
162
+            };
163
+            FB_proto.close = function() {
164
+                this.size = this.data.length = 0;
165
+            };
166
+            return FakeBlobBuilder;
167
+        }(view));
168
+
169
+    view.Blob = function Blob(blobParts, options) {
170
+        var type = options ? (options.type || "") : "";
171
+        var builder = new BlobBuilder();
172
+        if (blobParts) {
173
+            for (var i = 0, len = blobParts.length; i < len; i++) {
174
+                builder.append(blobParts[i]);
175
+            }
176
+        }
177
+        return builder.getBlob(type);
178
+    };
179
+}(typeof self !== "undefined" && self || typeof window !== "undefined" && window || this.content || this));

+ 160 - 0
src/vendor/Export2Excel.js

@@ -0,0 +1,160 @@
1
+/* eslint-disable */
2
+require('script-loader!file-saver');
3
+require('script-loader!@/vendor/Blob');
4
+import XLSX from 'xlsx'
5
+
6
+function generateArray(table) {
7
+    var out = [];
8
+    var rows = table.querySelectorAll('tr');
9
+    var ranges = [];
10
+    for (var R = 0; R < rows.length; ++R) {
11
+        var outRow = [];
12
+        var row = rows[R];
13
+        var columns = row.querySelectorAll('td');
14
+        for (var C = 0; C < columns.length; ++C) {
15
+            var cell = columns[C];
16
+            var colspan = cell.getAttribute('colspan');
17
+            var rowspan = cell.getAttribute('rowspan');
18
+            var cellValue = cell.innerText;
19
+            if (cellValue !== "" && cellValue == +cellValue) cellValue = +cellValue;
20
+
21
+            //Skip ranges
22
+            ranges.forEach(function (range) {
23
+                if (R >= range.s.r && R <= range.e.r && outRow.length >= range.s.c && outRow.length <= range.e.c) {
24
+                    for (var i = 0; i <= range.e.c - range.s.c; ++i) outRow.push(null);
25
+                }
26
+            });
27
+
28
+            //Handle Row Span
29
+            if (rowspan || colspan) {
30
+                rowspan = rowspan || 1;
31
+                colspan = colspan || 1;
32
+                ranges.push({s: {r: R, c: outRow.length}, e: {r: R + rowspan - 1, c: outRow.length + colspan - 1}});
33
+            }
34
+            ;
35
+
36
+            //Handle Value
37
+            outRow.push(cellValue !== "" ? cellValue : null);
38
+
39
+            //Handle Colspan
40
+            if (colspan) for (var k = 0; k < colspan - 1; ++k) outRow.push(null);
41
+        }
42
+        out.push(outRow);
43
+    }
44
+    return [out, ranges];
45
+};
46
+
47
+function datenum(v, date1904) {
48
+    if (date1904) v += 1462;
49
+    var epoch = Date.parse(v);
50
+    return (epoch - new Date(Date.UTC(1899, 11, 30))) / (24 * 60 * 60 * 1000);
51
+}
52
+
53
+function sheet_from_array_of_arrays(data, opts) {
54
+    var ws = {};
55
+    var range = {s: {c: 10000000, r: 10000000}, e: {c: 0, r: 0}};
56
+    for (var R = 0; R != data.length; ++R) {
57
+        for (var C = 0; C != data[R].length; ++C) {
58
+            if (range.s.r > R) range.s.r = R;
59
+            if (range.s.c > C) range.s.c = C;
60
+            if (range.e.r < R) range.e.r = R;
61
+            if (range.e.c < C) range.e.c = C;
62
+            var cell = {v: data[R][C]};
63
+            if (cell.v == null) continue;
64
+            var cell_ref = XLSX.utils.encode_cell({c: C, r: R});
65
+
66
+            if (typeof cell.v === 'number') cell.t = 'n';
67
+            else if (typeof cell.v === 'boolean') cell.t = 'b';
68
+            else if (cell.v instanceof Date) {
69
+                cell.t = 'n';
70
+                cell.z = XLSX.SSF._table[14];
71
+                cell.v = datenum(cell.v);
72
+            }
73
+            else cell.t = 's';
74
+
75
+            ws[cell_ref] = cell;
76
+        }
77
+    }
78
+    if (range.s.c < 10000000) ws['!ref'] = XLSX.utils.encode_range(range);
79
+    return ws;
80
+}
81
+
82
+function Workbook() {
83
+    if (!(this instanceof Workbook)) return new Workbook();
84
+    this.SheetNames = [];
85
+    this.Sheets = {};
86
+}
87
+
88
+function s2ab(s) {
89
+    var buf = new ArrayBuffer(s.length);
90
+    var view = new Uint8Array(buf);
91
+    for (var i = 0; i != s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF;
92
+    return buf;
93
+}
94
+
95
+export function export_table_to_excel(id) {
96
+    var theTable = document.getElementById(id);
97
+    var oo = generateArray(theTable);
98
+    var ranges = oo[1];
99
+
100
+    /* original data */
101
+    var data = oo[0];
102
+    var ws_name = "SheetJS";
103
+
104
+    var wb = new Workbook(), ws = sheet_from_array_of_arrays(data);
105
+
106
+    /* add ranges to worksheet */
107
+    // ws['!cols'] = ['apple', 'banan'];
108
+    ws['!merges'] = ranges;
109
+
110
+    /* add worksheet to workbook */
111
+    wb.SheetNames.push(ws_name);
112
+    wb.Sheets[ws_name] = ws;
113
+
114
+    var wbout = XLSX.write(wb, {bookType: 'xlsx', bookSST: false, type: 'binary'});
115
+
116
+    saveAs(new Blob([s2ab(wbout)], {type: "application/octet-stream"}), "test.xlsx")
117
+}
118
+
119
+export function export_json_to_excel(th, jsonData, defaultTitle) {
120
+
121
+    /* original data */
122
+
123
+    var data = jsonData;
124
+    data.unshift(th);
125
+    var ws_name = "SheetJS";
126
+
127
+    var wb = new Workbook(), ws = sheet_from_array_of_arrays(data);
128
+
129
+    /*设置worksheet每列的最大宽度*/
130
+    const colWidth = data.map(row => row.map(val => {
131
+      /*先判断是否为null/undefined*/
132
+      if (val == null) {
133
+        return {'wch': 10};
134
+      }
135
+      /*再判断是否为中文*/
136
+      else if (val.toString().charCodeAt(0) > 255) {
137
+        return {'wch': val.toString().length * 2};
138
+      } else {
139
+        return {'wch': val.toString().length};
140
+      }
141
+    }))
142
+    /*以第一行为初始值*/
143
+    let result = colWidth[0];
144
+    for (let i = 1; i < colWidth.length; i++) {
145
+      for (let j = 0; j < colWidth[i].length; j++) {
146
+        if (result[j]['wch'] < colWidth[i][j]['wch']) {
147
+          result[j]['wch'] = colWidth[i][j]['wch'];
148
+        }
149
+      }
150
+    }
151
+    ws['!cols'] = result;
152
+
153
+    /* add worksheet to workbook */
154
+    wb.SheetNames.push(ws_name);
155
+    wb.Sheets[ws_name] = ws;
156
+
157
+    var wbout = XLSX.write(wb, {bookType: 'xlsx', bookSST: false, type: 'binary'});
158
+    var title = defaultTitle || 'excel-list'
159
+    saveAs(new Blob([s2ab(wbout)], {type: "application/octet-stream"}), title + ".xlsx")
160
+}

+ 2 - 2
src/views/agnetManagement/gambleMemberManagement/index.vue

@@ -54,7 +54,7 @@
54 54
           </el-table-column>
55 55
       </el-table>
56 56
       <el-table show-summary :summary-method="getSummaries" :data="combine" v-loading.body="listLoading" element-loading-text="Loading" border fit highlight-current-row>
57
-        <el-table-column :label="`${(this.data.secondLayer.GambleMember.name).slice(19)}的會員`" align="center">
57
+        <el-table-column :label="`${this.data.secondLayer.name}的會員`" align="center">
58 58
           <el-table-column label="當莊次數" prop="bookieCount"  align="center"></el-table-column>          
59 59
           <el-table-column label="名稱" align="center">
60 60
             <template slot-scope="scope">
@@ -184,7 +184,7 @@ export default {
184 184
          
185 185
         this.combine = response.data
186 186
         this.allCombine.push({
187
-          name: (this.data.secondLayer.GambleMember.name).slice(19),
187
+          name: this.data.secondLayer.name,
188 188
           allUp: _.sumBy(response.data, 'totalUp'),
189 189
           allDown: _.sumBy(response.data, 'totalDown'),
190 190
           allReward: _.sumBy(response.data, 'totalReward'),

+ 38 - 12
src/views/agnetManagement/index.vue

@@ -6,6 +6,8 @@
6 6
         </el-input>
7 7
         <el-button class="filter-item" type="primary" v-waves icon="el-icon-search" @click="handleFilter">搜尋</el-button>
8 8
         <el-button class="filter-item" @click="handleCreate" type="primary" icon="el-icon-edit">創建代理商</el-button>
9
+        <el-input style='width:100px;' placeholder="輸入檔案名稱" prefix-icon="el-icon-document" v-model="filename"></el-input>
10
+        <el-button style='margin-bottom:20px;' type="primary" icon="document" @click="handleDownload" :loading="downloadLoading">匯出 excel</el-button>
9 11
       </div>
10 12
       <el-table :data="list" v-loading.body="listLoading" element-loading-text="Loading" border fit highlight-current-row
11 13
         style="width: 100%">
@@ -16,24 +18,24 @@
16 18
         </el-table-column> -->
17 19
         <el-table-column label="名稱" align="center">
18 20
           <template slot-scope="scope">
19
-            {{(scope.row.GambleMember.name).slice(19)}}
20
-          </template>
21
-        </el-table-column>
22
-        <el-table-column label="上繳工作室金額70%" align="center">
23
-          <template slot-scope="scope">
24
-            <span :style="moneyColor(scope.row.all70)">{{scope.row.all70}}</span>
21
+            {{scope.row.name}}
25 22
           </template>
26 23
         </el-table-column>
27 24
         <el-table-column label="抽水%" align="center">
28 25
           <template slot-scope="scope">
29 26
             {{scope.row.feeRatio}}
30 27
           </template>
31
-        </el-table-column>
32
-          <el-table-column label="代理商上繳金額" align="center">
28
+        </el-table-column>        
29
+        <el-table-column label="代理商上繳金額" align="center">
33 30
             <template slot-scope="scope">
34 31
               <span :style="moneyColor(scope.row.all)">{{scope.row.all}}</span>
35 32
             </template>
36 33
         </el-table-column>
34
+        <el-table-column label="上繳工作室金額70%" align="center">
35
+          <template slot-scope="scope">
36
+            <span :style="moneyColor(scope.row.all70)">{{scope.row.all70}}</span>
37
+          </template>
38
+        </el-table-column>
37 39
         <el-table-column align="center" label="操作" width="450">
38 40
           <template slot-scope="scope">          
39 41
             <router-link to="/agent/index/gambleMemberManagement">
@@ -86,12 +88,14 @@ export default {
86 88
       list: [],
87 89
       total: null,
88 90
       listLoading: true,
91
+      downloadLoading: false,
89 92
       listQuery: {
90 93
         page: 1,
91 94
         limit: 20,
92 95
         // startAt: moment.utc(moment().day('sunday').hour(12).minute(0).second(0).subtract(1, 'weeks').day(7).hour(16).minute(0).second(0)).format(),
93 96
         // endAt: moment.utc(moment().day('sunday').hour(12).minute(0).second(0).day(7).hour(11).minute(59).second(59)).format()
94 97
       },
98
+      filename: '',
95 99
       dialogCreateFormVisible: false,
96 100
       dialogStatus: '',
97 101
       // agent: {},
@@ -133,10 +137,12 @@ export default {
133 137
             console.log('response' , response.data.all)
134 138
             this.list.push({
135 139
               // id: agent.GambleMember.id,
136
-              GambleMember: {
137
-                id: agent.GambleMember.id,
138
-                name: agent.GambleMember.name
139
-              },
140
+              // GambleMember: {
141
+              //   id: agent.GambleMember.id,
142
+              //   name: agent.GambleMember.name
143
+              // },
144
+              id: agent.GambleMember.id,
145
+              name: agent.GambleMember.name.slice(19),
140 146
               feeRatio: response.data.feeRatio,
141 147
               all: response.data.all,
142 148
               all70: response.data.all70
@@ -246,6 +252,26 @@ export default {
246 252
         }
247 253
       })
248 254
     },
255
+    handleDownload() {
256
+      this.downloadLoading = true
257
+      import('@/vendor/Export2Excel').then(excel => {
258
+        const tHeader = ['名稱', '抽水%', '代理商上繳金額', '上繳工作室金額70%' ]
259
+        const filterVal = ['name', 'feeRatio', 'all', 'all70' ]
260
+        const list = this.list
261
+        const data = this.formatJson(filterVal, list)
262
+        excel.export_json_to_excel(tHeader, data, this.filename)
263
+        this.downloadLoading = false
264
+      })
265
+    },
266
+    formatJson(filterVal, jsonData) {
267
+      return jsonData.map(v => filterVal.map(j => {
268
+        if (j === 'timestamp') {
269
+          return parseTime(v[j])
270
+        } else {
271
+          return v[j]
272
+        }
273
+      }))
274
+    },
249 275
     handleFilter() {
250 276
       this.listQuery.page = 1
251 277
       this.getList()