• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (C) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16export class JSONToCSV {
17  static setCsvData(obj: any): void {
18    let that = this;
19    let browserType = this.browserType();
20    if (browserType.ie < 9) {
21      return;
22    }
23    let data = obj.data;
24    let isShowLabel = typeof obj.showLabel === 'undefined' ? true : obj.showLabel;
25    let fileName = (obj.fileName || 'UserExport') + '.csv';
26    let columns = obj.columns || {
27      title: [],
28      key: [],
29      formatter: undefined,
30    };
31    let showLabel = typeof isShowLabel === 'undefined' ? true : isShowLabel;
32    let row = '',
33      csv = '',
34      key;
35    // 如果要现实表头文字
36    if (showLabel) {
37      // 如果有传入自定义的表头文字
38      if (columns.title.length) {
39        columns.title.map(function (n: any) {
40          row += n + ',';
41        });
42      } else {
43        // 如果没有,就直接取数据第一条的对象的属性
44        for (key in data[0]) row += key + ',';
45      }
46      row = row.slice(0, -1);
47      csv += row + '\r\n';
48    }
49    // 具体的数据处理
50    data.map(function (n: any) {
51      row = '';
52      // 如果存在自定义key值
53      if (columns.key.length) {
54        row = that.getCsvStr(columns,obj,n,row);
55      } else {
56        for (key in n) {
57          row +=
58            '"' + (typeof columns.formatter === 'function' ? columns.formatter(key, n[key]) || n[key] : n[key]) + '",';
59        }
60      }
61      row.slice(0, row.length - 1); // 删除最后一个,
62      csv += row + '\r\n'; // 添加换行符号
63    });
64    if (!csv) {
65      return;
66    }
67    this.saveCsvFile(fileName, csv);
68  }
69
70  static getCsvStr(columns: any,obj: any,n: any,row: string){
71    let that = this;
72    columns.key.map(function (m: any, idx: number) {
73      let strItem: any = '';
74      if (obj.exportFormatter && obj.exportFormatter.has(m)) {
75        strItem = obj.exportFormatter.get(m)?.(n) || n[m];
76      } else if (obj.formatter && obj.formatter.has(m)) {
77        strItem = obj.formatter.get(m)?.(n[m]) || n[m];
78      } else {
79        strItem = n[m];
80      }
81      if (typeof strItem == 'undefined') {
82        strItem = '';
83      } else if (typeof strItem == 'object') {
84        strItem = JSON.stringify(strItem);
85        strItem = strItem.replaceAll('"', '');
86      }
87      if (idx === 0 && typeof n['depthCSV'] !== 'undefined') {
88        row +=
89          '"' +
90          that.treeDepth(n['depthCSV']) +
91          (typeof columns.formatter === 'function' ? columns.formatter(m, n[m]) || n[m] : strItem) +
92          '",';
93      } else {
94        row +=
95          '"' + (typeof columns.formatter === 'function' ? columns.formatter(m, n[m]) || n[m] : strItem) + '",';
96      }
97    });
98    return row;
99  }
100
101  static saveCsvFile(fileName: any, csvData: any): void {
102    let browserType: any = this.browserType();
103    if (!browserType.edge || !browserType.ie) {
104      let alink: any = document.createElement('a');
105      alink.id = 'csvDownloadLink';
106      alink.href = this.getDownloadUrl(csvData);
107      document.body.appendChild(alink);
108      let linkDom: any = document.getElementById('csvDownloadLink');
109      linkDom.setAttribute('download', fileName);
110      linkDom.click();
111      document.body.removeChild(linkDom);
112    } else if (browserType.ie >= 10 || browserType.edge === 'edge') {
113      (navigator as any).msSaveBlob(
114        new Blob(['\uFEFF' + csvData], {
115          type: 'text/csv',
116        }),
117        fileName
118      );
119    } else {
120      let oWin: any = window.top?.open('about:blank', '_blank');
121      oWin.document.write('sep=,\r\n' + csvData);
122      oWin.document.close();
123      oWin.document.execCommand('SaveAs', true, fileName);
124      oWin.close();
125    }
126  }
127
128  static getDownloadUrl(csvData: any) {
129    if (window.Blob && window.URL && (window.URL as any).createObjectURL) {
130      return URL.createObjectURL(
131        new Blob(['\uFEFF' + csvData], {
132          type: 'text/csv',
133        })
134      );
135    }
136  }
137
138  static browserType(): any {
139    let type: any = {};
140    let agent = navigator.userAgent.toLowerCase();
141    let has;
142    (has = agent.indexOf('edge') !== -1 ? (type.edge = 'edge') : agent.match(/rv:([\d.]+)\) like gecko/))
143      ? (type.ie = has[1])
144      : (has = agent.match(/msie ([\d.]+)/))
145      ? (type.ie = has[1])
146      : (has = agent.match(/firefox\/([\d.]+)/))
147      ? (type.firefox = has[1])
148      : (has = agent.match(/chrome\/([\d.]+)/))
149      ? (type.chrome = has[1])
150      : (has = agent.match(/opera.([\d.]+)/))
151      ? (type.opera = has[1])
152      : (has = agent.match(/version\/([\d.]+).*safari/))
153      ? (type.safari = has[1])
154      : 0;
155    return type;
156  }
157
158  static treeDepth(depth: number) {
159    let str = '';
160    for (let i = 0; i < depth; i++) {
161      str += '    ';
162    }
163    return str;
164  }
165
166  static treeToArr(data: any) {
167    const result: Array<any> = [];
168    data.forEach((item: any) => {
169      let depthCSV = 0;
170      const loop = (data: any, depth: any) => {
171        result.push({ depthCSV: depth, ...data });
172        let child = data.children;
173        if (child) {
174          for (let i = 0; i < child.length; i++) {
175            loop(child[i], depth + 1);
176          }
177        }
178      };
179      loop(item, depthCSV);
180    });
181    return result;
182  }
183
184  static columnsData(columns: Array<any>): {
185    titleList: any[];
186    ketList: any[];
187  } {
188    let titleList: Array<any> = [];
189    let ketList: Array<any> = [];
190    columns.forEach((column) => {
191      let dataIndex = column.getAttribute('data-index');
192      let columnName = column.getAttribute('title');
193      if (columnName == '') {
194        columnName = dataIndex == 'busyTimeStr' ? 'GetBusyTime(ms)' : dataIndex;
195      }
196      if (columnName !== '  ') {
197        titleList.push(columnName);
198        ketList.push(dataIndex);
199      }
200    });
201    return {
202      titleList: titleList,
203      ketList: ketList,
204    };
205  }
206
207  static async csvExport(dataSource: {
208    columns: any[];
209    tables: any[];
210    fileName: string;
211    columnFormatter: Map<string, (value: any) => string>;
212    exportFormatter: Map<string, (value: any) => string>;
213  }): Promise<string> {
214    return new Promise((resolve) => {
215      let data: any = this.columnsData(dataSource.columns);
216      let columns = {
217        title: data.titleList,
218        key: data.ketList,
219      };
220      if (dataSource.tables.length > 0) {
221        if (Array.isArray(dataSource.tables[0])) {
222          dataSource.tables.forEach((childArr, childIndex) => {
223            let resultArr = JSONToCSV.treeToArr(childArr);
224            JSONToCSV.setCsvData({
225              data: resultArr,
226              fileName: `${dataSource.fileName}_${childIndex}`,
227              columns: columns,
228              formatter: dataSource.columnFormatter,
229            });
230          });
231        } else {
232          let resultArr = JSONToCSV.treeToArr(dataSource.tables);
233          JSONToCSV.setCsvData({
234            data: resultArr,
235            fileName: dataSource.fileName,
236            columns: columns,
237            formatter: dataSource.columnFormatter,
238            exportFormatter: dataSource.exportFormatter,
239          });
240        }
241      }
242      resolve('ok');
243    });
244  }
245}
246