Commit 43509ad87630e5062539d340f11229433617a621

Authored by 梁灏
1 parent 2f0b086d

Table support export .csv file

Table support export .csv file
package.json
1 1 {
2 2 "name": "iview",
3   - "version": "0.9.10-rc-2",
  3 + "version": "0.9.10-rc-3",
4 4 "title": "iView",
5 5 "description": "A high quality UI components Library with Vue.js",
6 6 "homepage": "http://www.iviewui.com",
... ...
src/components/table/export-csv.js 0 → 100644
  1 +function has (browser) {
  2 + const ua = navigator.userAgent;
  3 + if (browser === 'ie') {
  4 + const isIE = ua.indexOf('compatible') > -1 && ua.indexOf('MSIE') > -1;
  5 + if (isIE) {
  6 + const reIE = new RegExp("MSIE (\\d+\\.\\d+);");
  7 + reIE.test(ua);
  8 + return parseFloat(RegExp["$1"]);
  9 + } else {
  10 + return false
  11 + }
  12 + } else {
  13 + return ua.indexOf(browser) > -1;
  14 + }
  15 +}
  16 +
  17 +const csv = {
  18 + _isIE11 () {
  19 + let iev = 0;
  20 + const ieold = (/MSIE (\d+\.\d+);/.test(navigator.userAgent));
  21 + const trident = !!navigator.userAgent.match(/Trident\/7.0/);
  22 + const rv = navigator.userAgent.indexOf("rv:11.0");
  23 +
  24 + if (ieold) {
  25 + iev = Number(RegExp.$1);
  26 + }
  27 + if (navigator.appVersion.indexOf("MSIE 10") !== -1) {
  28 + iev = 10;
  29 + }
  30 + if (trident && rv !== -1) {
  31 + iev = 11;
  32 + }
  33 +
  34 + return iev === 11;
  35 + },
  36 +
  37 + _isEdge () {
  38 + return /Edge/.test(navigator.userAgent);
  39 + },
  40 +
  41 + _getDownloadUrl (text) {
  42 + const BOM = "\uFEFF";
  43 + // Add BOM to text for open in excel correctly
  44 + if (window.Blob && window.URL && window.URL.createObjectURL && !has('Safari')) {
  45 + const csvData = new Blob([BOM + text], { type: 'text/csv' });
  46 + return URL.createObjectURL(csvData);
  47 + } else {
  48 + return 'data:attachment/csv;charset=utf-8,' + BOM + encodeURIComponent(text);
  49 + }
  50 + },
  51 +
  52 + download (filename, text) {
  53 + if (has('ie') && has('ie') < 10) {
  54 + // has module unable identify ie11 and Edge
  55 + const oWin = window.top.open("about:blank", "_blank");
  56 + oWin.document.charset = 'utf-8';
  57 + oWin.document.write(text);
  58 + oWin.document.close();
  59 + oWin.document.execCommand('SaveAs', filename);
  60 + oWin.close();
  61 + } else if (has("ie") === 10 || this._isIE11() || this._isEdge()) {
  62 + const BOM = "\uFEFF";
  63 + const csvData = new Blob([BOM + text], { type: 'text/csv' });
  64 + navigator.msSaveBlob(csvData, filename);
  65 + } else {
  66 + const link = document.createElement('a');
  67 + link.download = filename;
  68 + link.href = this._getDownloadUrl(text);
  69 + link.target = '_blank';
  70 + document.body.appendChild(link);
  71 + link.click();
  72 + document.body.removeChild(link);
  73 + }
  74 + }
  75 +};
  76 +
  77 +export default csv;
0 78 \ No newline at end of file
... ...
src/components/table/table.vue
... ... @@ -73,6 +73,8 @@
73 73 import tableHead from './table-head.vue';
74 74 import tableBody from './table-body.vue';
75 75 import { oneOf, getStyle, deepCopy } from '../../utils/assist';
  76 + import Csv from '../../utils/csv';
  77 + import ExportCsv from './export-csv';
76 78 const prefixCls = 'ivu-table';
77 79  
78 80 export default {
... ... @@ -516,6 +518,32 @@
516 518 }
517 519 });
518 520 return left.concat(center).concat(right);
  521 + },
  522 + exportCsv (params) {
  523 + if (params.filename) {
  524 + if (params.filename.indexOf('.csv') === -1) {
  525 + params.filename += '.csv';
  526 + }
  527 + } else {
  528 + params.filename = 'table.csv';
  529 + }
  530 +
  531 + let columns = [];
  532 + let datas = [];
  533 + if (params.columns && params.data) {
  534 + columns = params.columns;
  535 + datas = params.data;
  536 + } else {
  537 + columns = this.columns;
  538 + if (!('original' in params)) params.original = true;
  539 + datas = params.original ? this.data : this.rebuildData;
  540 + }
  541 +
  542 + let noHeader = false;
  543 + if ('noHeader' in params) noHeader = params.noHeader;
  544 +
  545 + const data = Csv(columns, datas, ',', noHeader);
  546 + ExportCsv.download(params.filename, data);
519 547 }
520 548 },
521 549 compiled () {
... ...
src/utils/csv.js 0 → 100644
  1 +// https://github.com/Terminux/react-csv-downloader/blob/master/src/lib/csv.js
  2 +
  3 +const newLine = '\r\n';
  4 +
  5 +export default function csv(columns, datas, separator = ',', noHeader = false) {
  6 + let columnOrder;
  7 + const content = [];
  8 + const column = [];
  9 +
  10 + if (columns) {
  11 + columnOrder = columns.map(v => {
  12 + if (typeof v === 'string') {
  13 + return v;
  14 + }
  15 + if (!noHeader) {
  16 + column.push((typeof v.title !== 'undefined') ? v.title : v.key);
  17 + }
  18 + return v.key;
  19 + });
  20 + if (column.length > 0) {
  21 + content.push(column.join(separator));
  22 + }
  23 + } else {
  24 + columnOrder = [];
  25 + datas.forEach(v => {
  26 + if (!Array.isArray(v)) {
  27 + columnOrder = columnOrder.concat(Object.keys(v));
  28 + }
  29 + });
  30 + if (columnOrder.length > 0) {
  31 + columnOrder = columnOrder.filter((value, index, self) => self.indexOf(value) === index);
  32 +
  33 + if (!noHeader) {
  34 + content.push(columnOrder.join(separator));
  35 + }
  36 + }
  37 + }
  38 +
  39 + if (Array.isArray(datas)) {
  40 + datas.map(v => {
  41 + if (Array.isArray(v)) {
  42 + return v;
  43 + }
  44 + return columnOrder.map(k => {
  45 + if (typeof v[k] !== 'undefined') {
  46 + return v[k];
  47 + }
  48 + return '';
  49 + });
  50 + }).forEach(v => {
  51 + content.push(v.join(separator));
  52 + });
  53 + }
  54 + return content.join(newLine);
  55 +}
0 56 \ No newline at end of file
... ...
test/routers/table.vue
1 1 <template>
2   - <i-table :columns="columns1" :data="data1"></i-table>
3   - <i-table size="small" :columns="columns1" :data="data1"></i-table>
  2 + <i-button @click="down">down</i-button>
  3 + <checkbox-group :model.sync="tableColumnsChecked" @on-change="changeTableColumns">
  4 + <checkbox value="show">展示</checkbox>
  5 + <checkbox value="weak">唤醒</checkbox>
  6 + <checkbox value="signin">登录</checkbox>
  7 + <checkbox value="click">点击</checkbox>
  8 + <checkbox value="active">激活</checkbox>
  9 + <checkbox value="day7">7日留存</checkbox>
  10 + <checkbox value="day30">30日留存</checkbox>
  11 + <checkbox value="tomorrow">次日留存</checkbox>
  12 + <checkbox value="day">日活跃</checkbox>
  13 + <checkbox value="week">周活跃</checkbox>
  14 + <checkbox value="month">月活跃</checkbox>
  15 + </checkbox-group>
  16 + <i-table :content="self" :data="tableData2" :columns="tableColumns2" border v-ref:table></i-table>
4 17 </template>
5 18 <script>
6 19 export default {
7 20 data () {
8 21 return {
9   - columns1: [
10   - {
11   - title: '姓名',
12   - key: 'name'
  22 + self: this,
  23 + tableData2: this.mockTableData2(),
  24 + tableColumns2: [],
  25 + tableColumnsChecked: ['show', 'weak', 'signin', 'click', 'active', 'day7', 'day30', 'tomorrow', 'day', 'week', 'month']
  26 + }
  27 + },
  28 + methods: {
  29 + mockTableData2 () {
  30 + let data = [];
  31 + function getNum() {
  32 + return Math.floor(Math.random () * 10000 + 1);
  33 + }
  34 + for (let i = 0; i < 10; i++) {
  35 + data.push({
  36 + name: '推广名称' + (i+1),
  37 + fav: 0,
  38 + show: getNum(),
  39 + weak: getNum(),
  40 + signin: getNum(),
  41 + click: getNum(),
  42 + active: getNum(),
  43 + day7: getNum(),
  44 + day30: getNum(),
  45 + tomorrow: getNum(),
  46 + day: getNum(),
  47 + week: getNum(),
  48 + month: getNum()
  49 + })
  50 + }
  51 + return data;
  52 + },
  53 + getTable2Columns () {
  54 + const table2ColumnList = {
  55 + name: {
  56 + title: '名称',
  57 + key: 'name',
  58 + fixed: 'left',
  59 + width: 200,
  60 + render (row, column, index) {
  61 + return `<Icon style="cursor: pointer" type="ios-star-outline" v-if="tableData2[${index}].fav === 0" @click="toggleFav(${index})"></Icon>
  62 + <Icon style="cursor: pointer;color:#f60" type="ios-star" v-if="tableData2[${index}].fav === 1" @click="toggleFav(${index})"></Icon>
  63 + <span>${row.name}</span>`;
  64 + }
13 65 },
14   - {
15   - title: '年龄',
16   - key: 'age',
  66 + show: {
  67 + title: '展示',
  68 + key: 'show',
  69 + width: 150,
17 70 sortable: true
18 71 },
19   - {
20   - title: '地址',
21   - key: 'address'
22   - }
23   - ],
24   - data1: [
25   - {
26   - name: '王小明',
27   - age: 18,
28   - address: '北京市朝阳区芍药居'
29   - },
30   - {
31   - name: '张小刚',
32   - age: 25,
33   - address: '北京市海淀区西二旗'
34   - },
35   - {
36   - name: '李小红',
37   - age: 30,
38   - address: '上海市浦东新区世纪大道'
39   - },
40   - {
41   - name: '周小伟',
42   - age: 26,
43   - address: '深圳市南山区深南大道'
  72 + weak: {
  73 + title: '唤醒',
  74 + key: 'weak',
  75 + width: 150,
  76 + sortable: true
  77 + },
  78 + signin: {
  79 + title: '登录',
  80 + key: 'signin',
  81 + width: 150,
  82 + sortable: true
  83 + },
  84 + click: {
  85 + title: '点击',
  86 + key: 'click',
  87 + width: 150,
  88 + sortable: true
  89 + },
  90 + active: {
  91 + title: '激活',
  92 + key: 'active',
  93 + width: 150,
  94 + sortable: true
  95 + },
  96 + day7: {
  97 + title: '7日留存',
  98 + key: 'day7',
  99 + width: 150,
  100 + sortable: true
  101 + },
  102 + day30: {
  103 + title: '30日留存',
  104 + key: 'day30',
  105 + width: 150,
  106 + sortable: true
  107 + },
  108 + tomorrow: {
  109 + title: '次日留存',
  110 + key: 'tomorrow',
  111 + width: 150,
  112 + sortable: true
  113 + },
  114 + day: {
  115 + title: '日活跃',
  116 + key: 'day',
  117 + width: 150,
  118 + sortable: true
  119 + },
  120 + week: {
  121 + title: '周活跃',
  122 + key: 'week',
  123 + width: 150,
  124 + sortable: true
  125 + },
  126 + month: {
  127 + title: '月活跃',
  128 + key: 'month',
  129 + width: 150,
  130 + sortable: true
44 131 }
45   - ]
  132 + };
  133 +
  134 + let data = [table2ColumnList.name];
  135 +
  136 + this.tableColumnsChecked.forEach(col => data.push(table2ColumnList[col]));
  137 +
  138 + return data;
  139 + },
  140 + changeTableColumns () {
  141 + this.tableColumns2 = this.getTable2Columns();
  142 + },
  143 + toggleFav (index) {
  144 + this.tableData2[index].fav = this.tableData2[index].fav === 0 ? 1 : 0;
  145 + },
  146 + down () {
  147 + this.$refs.table.exportCsv({
  148 + filename: '2132',
  149 + original: false
  150 + });
46 151 }
  152 + },
  153 + ready () {
  154 + this.changeTableColumns();
47 155 }
48 156 }
49 157 </script>
... ...