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