From 43509ad87630e5062539d340f11229433617a621 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=A2=81=E7=81=8F?= Date: Fri, 9 Dec 2016 13:24:39 +0800 Subject: [PATCH] Table support export .csv file Table support export .csv file --- package.json | 2 +- src/components/table/export-csv.js | 77 +++++++++++++ src/components/table/table.vue | 28 +++++ src/utils/csv.js | 55 +++++++++ test/routers/table.vue | 178 +++++++++++++++++++++++------ 5 files changed, 304 insertions(+), 36 deletions(-) create mode 100644 src/components/table/export-csv.js create mode 100644 src/utils/csv.js diff --git a/package.json b/package.json index 2896c3cf..073158e7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "iview", - "version": "0.9.10-rc-2", + "version": "0.9.10-rc-3", "title": "iView", "description": "A high quality UI components Library with Vue.js", "homepage": "http://www.iviewui.com", diff --git a/src/components/table/export-csv.js b/src/components/table/export-csv.js new file mode 100644 index 00000000..92451ce0 --- /dev/null +++ b/src/components/table/export-csv.js @@ -0,0 +1,77 @@ +function has (browser) { + const ua = navigator.userAgent; + if (browser === 'ie') { + const isIE = ua.indexOf('compatible') > -1 && ua.indexOf('MSIE') > -1; + if (isIE) { + const reIE = new RegExp("MSIE (\\d+\\.\\d+);"); + reIE.test(ua); + return parseFloat(RegExp["$1"]); + } else { + return false + } + } else { + return ua.indexOf(browser) > -1; + } +} + +const csv = { + _isIE11 () { + let iev = 0; + const ieold = (/MSIE (\d+\.\d+);/.test(navigator.userAgent)); + const trident = !!navigator.userAgent.match(/Trident\/7.0/); + const rv = navigator.userAgent.indexOf("rv:11.0"); + + if (ieold) { + iev = Number(RegExp.$1); + } + if (navigator.appVersion.indexOf("MSIE 10") !== -1) { + iev = 10; + } + if (trident && rv !== -1) { + iev = 11; + } + + return iev === 11; + }, + + _isEdge () { + return /Edge/.test(navigator.userAgent); + }, + + _getDownloadUrl (text) { + const BOM = "\uFEFF"; + // Add BOM to text for open in excel correctly + if (window.Blob && window.URL && window.URL.createObjectURL && !has('Safari')) { + const csvData = new Blob([BOM + text], { type: 'text/csv' }); + return URL.createObjectURL(csvData); + } else { + return 'data:attachment/csv;charset=utf-8,' + BOM + encodeURIComponent(text); + } + }, + + download (filename, text) { + if (has('ie') && has('ie') < 10) { + // has module unable identify ie11 and Edge + const oWin = window.top.open("about:blank", "_blank"); + oWin.document.charset = 'utf-8'; + oWin.document.write(text); + oWin.document.close(); + oWin.document.execCommand('SaveAs', filename); + oWin.close(); + } else if (has("ie") === 10 || this._isIE11() || this._isEdge()) { + const BOM = "\uFEFF"; + const csvData = new Blob([BOM + text], { type: 'text/csv' }); + navigator.msSaveBlob(csvData, filename); + } else { + const link = document.createElement('a'); + link.download = filename; + link.href = this._getDownloadUrl(text); + link.target = '_blank'; + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + } + } +}; + +export default csv; \ No newline at end of file diff --git a/src/components/table/table.vue b/src/components/table/table.vue index f5dc220a..18ddec84 100644 --- a/src/components/table/table.vue +++ b/src/components/table/table.vue @@ -73,6 +73,8 @@ import tableHead from './table-head.vue'; import tableBody from './table-body.vue'; import { oneOf, getStyle, deepCopy } from '../../utils/assist'; + import Csv from '../../utils/csv'; + import ExportCsv from './export-csv'; const prefixCls = 'ivu-table'; export default { @@ -516,6 +518,32 @@ } }); return left.concat(center).concat(right); + }, + exportCsv (params) { + if (params.filename) { + if (params.filename.indexOf('.csv') === -1) { + params.filename += '.csv'; + } + } else { + params.filename = 'table.csv'; + } + + let columns = []; + let datas = []; + if (params.columns && params.data) { + columns = params.columns; + datas = params.data; + } else { + columns = this.columns; + if (!('original' in params)) params.original = true; + datas = params.original ? this.data : this.rebuildData; + } + + let noHeader = false; + if ('noHeader' in params) noHeader = params.noHeader; + + const data = Csv(columns, datas, ',', noHeader); + ExportCsv.download(params.filename, data); } }, compiled () { diff --git a/src/utils/csv.js b/src/utils/csv.js new file mode 100644 index 00000000..ff03c177 --- /dev/null +++ b/src/utils/csv.js @@ -0,0 +1,55 @@ +// https://github.com/Terminux/react-csv-downloader/blob/master/src/lib/csv.js + +const newLine = '\r\n'; + +export default function csv(columns, datas, separator = ',', noHeader = false) { + let columnOrder; + const content = []; + const column = []; + + if (columns) { + columnOrder = columns.map(v => { + if (typeof v === 'string') { + return v; + } + if (!noHeader) { + column.push((typeof v.title !== 'undefined') ? v.title : v.key); + } + return v.key; + }); + if (column.length > 0) { + content.push(column.join(separator)); + } + } else { + columnOrder = []; + datas.forEach(v => { + if (!Array.isArray(v)) { + columnOrder = columnOrder.concat(Object.keys(v)); + } + }); + if (columnOrder.length > 0) { + columnOrder = columnOrder.filter((value, index, self) => self.indexOf(value) === index); + + if (!noHeader) { + content.push(columnOrder.join(separator)); + } + } + } + + if (Array.isArray(datas)) { + datas.map(v => { + if (Array.isArray(v)) { + return v; + } + return columnOrder.map(k => { + if (typeof v[k] !== 'undefined') { + return v[k]; + } + return ''; + }); + }).forEach(v => { + content.push(v.join(separator)); + }); + } + return content.join(newLine); +} \ No newline at end of file diff --git a/test/routers/table.vue b/test/routers/table.vue index f57ccf07..09685eb4 100644 --- a/test/routers/table.vue +++ b/test/routers/table.vue @@ -1,49 +1,157 @@