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