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) { 18 let that = this; 19 let browserType = this.browserType(); 20 if (browserType['ie'] < 9) return; 21 let data = obj['data']; 22 let isShowLabel = typeof obj['showLabel'] === 'undefined' ? true : obj['showLabel']; 23 let fileName = (obj['fileName'] || 'UserExport') + '.csv'; 24 let columns = obj['columns'] || { 25 title: [], 26 key: [], 27 formatter: undefined, 28 }; 29 let showLabel = typeof isShowLabel === 'undefined' ? true : isShowLabel; 30 let row = '', csv = '', key; 31 // 如果要现实表头文字 32 if (showLabel) { 33 // 如果有传入自定义的表头文字 34 if (columns.title.length) { 35 columns.title.map(function (n: any) { 36 row += n + ','; 37 }); 38 } else { 39 // 如果没有,就直接取数据第一条的对象的属性 40 for (key in data[0]) row += key + ','; 41 } 42 row = row.slice(0, -1); 43 csv += row + '\r\n'; 44 } 45 // 具体的数据处理 46 data.map(function (n: any) { 47 row = ''; 48 // 如果存在自定义key值 49 if (columns.key.length) { 50 columns.key.map(function (m: any, idx: number) { 51 let strItem = n[m]; 52 if (typeof n[m] == 'undefined') { 53 strItem = ''; 54 } else if (typeof n[m] == 'object') { 55 strItem = JSON.stringify(n[m]); 56 strItem = strItem.replaceAll('"', ''); 57 } 58 if (idx === 0 && typeof n['depthCSV'] !== 'undefined') { 59 row += 60 '"' + 61 that.treeDepth(n['depthCSV']) + 62 (typeof columns.formatter === 'function' ? columns.formatter(m, n[m]) || n[m] : strItem) + 63 '",'; 64 } else { 65 row += 66 '"' + (typeof columns.formatter === 'function' ? columns.formatter(m, n[m]) || n[m] : strItem) + '",'; 67 } 68 }); 69 } else { 70 for (key in n) { 71 row += 72 '"' + (typeof columns.formatter === 'function' ? columns.formatter(key, n[key]) || n[key] : n[key]) + '",'; 73 } 74 } 75 row.slice(0, row.length - 1); // 删除最后一个, 76 csv += row + '\r\n'; // 添加换行符号 77 }); 78 if (!csv) return; 79 this.saveCsvFile(fileName, csv); 80 } 81 82 static saveCsvFile(fileName: any, csvData: any) { 83 let browserType: any = this.browserType(); 84 if (!browserType['edge'] || !browserType['ie']) { 85 let alink: any = document.createElement('a'); 86 alink.id = 'csvDownloadLink'; 87 alink.href = this.getDownloadUrl(csvData); 88 document.body.appendChild(alink); 89 let linkDom: any = document.getElementById('csvDownloadLink'); 90 linkDom.setAttribute('download', fileName); 91 linkDom.click(); 92 document.body.removeChild(linkDom); 93 } else if (browserType['ie'] >= 10 || browserType['edge'] == 'edge') { 94 (navigator as any).msSaveBlob(new Blob(['\uFEFF' + csvData], { 95 type: 'text/csv', 96 }), fileName); 97 } else { 98 let oWin: any = window.top?.open('about:blank', '_blank'); 99 oWin.document.write('sep=,\r\n' + csvData); 100 oWin.document.close(); 101 oWin.document.execCommand('SaveAs', true, fileName); 102 oWin.close(); 103 } 104 } 105 106 static getDownloadUrl(csvData: any) { 107 if (window.Blob && window.URL && (window.URL as any).createObjectURL) { 108 return URL.createObjectURL(new Blob(['\uFEFF' + csvData], { 109 type: 'text/csv', 110 })); 111 } 112 } 113 114 static browserType() { 115 let type: any = {}; 116 let agent = navigator.userAgent.toLowerCase(); 117 let has; 118 (has = agent.indexOf('edge') !== -1 ? (type.edge = 'edge') : agent.match(/rv:([\d.]+)\) like gecko/)) 119 ? (type.ie = has[1]) 120 : (has = agent.match(/msie ([\d.]+)/)) 121 ? (type.ie = has[1]) 122 : (has = agent.match(/firefox\/([\d.]+)/)) 123 ? (type.firefox = has[1]) 124 : (has = agent.match(/chrome\/([\d.]+)/)) 125 ? (type.chrome = has[1]) 126 : (has = agent.match(/opera.([\d.]+)/)) 127 ? (type.opera = has[1]) 128 : (has = agent.match(/version\/([\d.]+).*safari/)) 129 ? (type.safari = has[1]) 130 : 0; 131 return type; 132 } 133 134 static treeDepth(depth: number) { 135 let str = ''; 136 for (let i = 0; i < depth; i++) { 137 str += ' '; 138 } 139 return str; 140 } 141 142 static treeToArr(data: any) { 143 const result: Array<any> = []; 144 data.forEach((item: any) => { 145 let depthCSV = 0; 146 const loop = (data: any, depth: any) => { 147 result.push({depthCSV: depth, ...data}); 148 let child = data.children; 149 if (child) { 150 for (let i = 0; i < child.length; i++) { 151 loop(child[i], depth + 1); 152 } 153 } 154 }; 155 loop(item, depthCSV); 156 }); 157 return result; 158 } 159 160 static columnsData(columns: Array<any>) { 161 let titleList: Array<any> = []; 162 let ketList: Array<any> = []; 163 columns.forEach((column) => { 164 let dataIndex = column.getAttribute('data-index'); 165 let columnName = column.getAttribute('title'); 166 if (columnName == '') { 167 columnName = dataIndex; 168 } 169 if (columnName !== ' ') { 170 titleList.push(columnName); 171 ketList.push(dataIndex); 172 } 173 }); 174 return { 175 titleList: titleList, 176 ketList: ketList, 177 }; 178 } 179 180 static async csvExport(dataSource: { columns: any[]; tables: any[]; fileName: string }): Promise<string> { 181 return new Promise((resolve) => { 182 let data: any = this.columnsData(dataSource.columns); 183 let columns = { 184 title: data.titleList, 185 key: data.ketList, 186 }; 187 if (dataSource.tables.length > 0) { 188 if (Array.isArray(dataSource.tables[0])) { 189 dataSource.tables.forEach((childArr, childIndex) => { 190 let resultArr = JSONToCSV.treeToArr(childArr); 191 JSONToCSV.setCsvData({ 192 data: resultArr, 193 fileName: `${dataSource.fileName}_${childIndex}`, 194 columns: columns 195 }); 196 }) 197 } else { 198 let resultArr = JSONToCSV.treeToArr(dataSource.tables); 199 JSONToCSV.setCsvData({ 200 data: resultArr, 201 fileName: dataSource.fileName, 202 columns: columns, 203 }); 204 } 205 } 206 resolve('ok'); 207 }); 208 } 209} 210