1
1
import React from 'react' ;
2
-
3
- import CopyUtils from '../utils/copy' ;
4
- import { HotTable } from '@handsontable/react' ;
5
2
import type { HotTableProps } from '@handsontable/react' ;
3
+ import { HotTable } from '@handsontable/react' ;
6
4
import classNames from 'classnames' ;
7
- import 'handsontable/dist/handsontable.full.css' ;
8
5
import 'handsontable/languages/zh-CN.js' ;
9
6
7
+ import CopyUtils from '../utils/copy' ;
8
+ import 'handsontable/dist/handsontable.full.css' ;
9
+
10
10
type IOptions = HotTableProps & {
11
- /** 是否展示复制值以及列名 */
12
- showCopyWithHeader ?: boolean ;
11
+ // 右击右键菜单中展示的选项 复制值/复制列名/复制列名和值 按钮 */
12
+ copyTypes ?: Array < 'copyData' | 'copyHeaders' | 'copyHeadersAndData' > ;
13
13
} ;
14
14
15
- export interface SpreadSheetProps {
15
+ export interface ISpreadSheetProps {
16
16
data : Array < Array < string | null | number > > ;
17
17
columns : any ;
18
18
className ?: string ;
@@ -27,7 +27,7 @@ export interface SpreadSheetProps {
27
27
hotTableInstanceRef ?: ( instance : any ) => void ;
28
28
}
29
29
30
- class SpreadSheet extends React . PureComponent < SpreadSheetProps , any > {
30
+ class SpreadSheet extends React . PureComponent < ISpreadSheetProps , any > {
31
31
tableRef : any = React . createRef ( ) ;
32
32
copyUtils = new CopyUtils ( ) ;
33
33
_renderTimer : any ;
@@ -54,7 +54,7 @@ class SpreadSheet extends React.PureComponent<SpreadSheetProps, any> {
54
54
componentWillUnmount ( ) {
55
55
this . removeRenderClock ( ) ;
56
56
}
57
- getData ( ) {
57
+ getShowData ( ) {
58
58
const { data, columns = [ ] } = this . props ;
59
59
let showData = data ;
60
60
if ( ! showData || ! showData . length ) {
@@ -78,63 +78,110 @@ class SpreadSheet extends React.PureComponent<SpreadSheetProps, any> {
78
78
}
79
79
return null ;
80
80
}
81
- beforeCopy ( arr : any , _arr2 ?: any ) {
82
- /**
83
- * 去除格式化
84
- */
81
+
82
+ /**
83
+ * 去除格式化
84
+ */
85
+ beforeCopy ( arr : Array < Array < any > > ) {
85
86
const value = arr
86
87
. map ( ( row : any ) => {
87
88
return row . join ( '\t' ) ;
88
89
} )
89
90
. join ( '\n' ) ;
91
+
90
92
this . copyUtils . copy ( value ) ;
91
93
return false ;
92
94
}
93
95
getContextMenu ( ) {
94
96
const that = this ;
95
97
const { columns = [ ] , options } = this . props ;
96
- const items = {
97
- copy : {
98
- name : '复制' ,
99
- callback : function ( _key ) {
100
- const indexArr = this . getSelected ( ) ;
101
- // eslint-disable-next-line prefer-spread
102
- const copyDataArr = this . getData . apply ( this , indexArr [ 0 ] ) ;
103
- that . beforeCopy ( copyDataArr ) ;
104
- } ,
105
- } ,
98
+ const { copyTypes = [ ] } = options || { } ;
99
+
100
+ // 获取值
101
+ const getCopyData = ( _that ) => {
102
+ // _that 调用的是 handsontable 的方法(在 handsontable.d.ts), this/that 调用的是当前文件的方法
103
+ const selectedIndexArr = _that . getSelected ( ) ;
104
+ let dataArr = [ ] ;
105
+
106
+ if ( Array . isArray ( selectedIndexArr ) ) {
107
+ selectedIndexArr . forEach ( ( arr , index ) => {
108
+ const [ r , c , r2 , c2 ] = arr || [ ] ;
109
+ const colData : [ ] = _that . getData ( r , c , r2 , c2 ) || [ ] ;
110
+ if ( index === 0 ) {
111
+ dataArr . push ( ...colData ) ;
112
+ } else {
113
+ dataArr = dataArr . map ( ( item : any [ ] , index : number ) => {
114
+ return item . concat ( colData [ index ] ) ;
115
+ } ) ;
116
+ }
117
+ } ) ;
118
+ }
119
+ return dataArr ;
106
120
} ;
107
- if ( options ?. showCopyWithHeader ) {
108
- const copyWithHeaderItem = {
109
- name : '复制值以及列名' ,
110
- callback : function ( _key , selection ) {
111
- const indexArr = this . getSelected ( ) ;
112
- // eslint-disable-next-line prefer-spread
113
- let copyDataArr = this . getData . apply ( this , indexArr [ 0 ] ) ;
114
- const columnStart = selection ?. [ 0 ] ?. start ?. col ;
115
- const columnEnd = selection ?. [ 0 ] ?. end ?. col ;
116
- let columnArr ;
121
+ // 获取列名
122
+ const getCopyHeaders = ( selection ) => {
123
+ // _that 调用的是 handsontable 的方法(在 handsontable.d.ts), this/that 调用的是当前文件的方法
124
+ let headerArr = [ ] ;
125
+ if ( Array . isArray ( selection ) ) {
126
+ selection . forEach ( ( it ) => {
127
+ const columnStart = it . start ?. col ;
128
+ const columnEnd = it . end ?. col ;
117
129
if ( columnStart !== undefined && columnEnd !== undefined ) {
118
- columnArr = columns . slice ( columnStart , columnEnd + 1 ) ;
130
+ headerArr = headerArr . concat ( columns . slice ( columnStart , columnEnd + 1 ) ) ;
119
131
}
120
- if ( columnArr ) {
121
- copyDataArr = [ columnArr , ...copyDataArr ] ;
122
- }
123
- that . beforeCopy ( copyDataArr ) ;
124
- } ,
125
- } ;
126
- // 目前版本不支持 copy_with_column_headers 暂时用 cut 代替,以达到与copy类似的表现
127
- items [ 'cut' ] = copyWithHeaderItem ;
132
+ } ) ;
133
+ }
134
+ return headerArr ;
135
+ } ;
136
+
137
+ const copyDataItem = {
138
+ name : '复制值' ,
139
+ callback : function ( _key ) {
140
+ const copyDataArr = getCopyData ( this ) ;
141
+ that . beforeCopy ( copyDataArr ) ;
142
+ } ,
143
+ } ;
144
+ const copyHeadersItem = {
145
+ name : '复制列名' ,
146
+ callback : function ( _key , selection ) {
147
+ const copyHeaders = getCopyHeaders ( selection ) ;
148
+ that . beforeCopy ( [ copyHeaders ] ) ;
149
+ } ,
150
+ } ;
151
+ const copyHeadersAndDataItem = {
152
+ name : '复制列名和值' ,
153
+ callback : function ( _key , selection ) {
154
+ const copyDataArr = getCopyData ( this ) ;
155
+ const copyHeaders = getCopyHeaders ( selection ) ;
156
+ that . beforeCopy ( [ copyHeaders , ...copyDataArr ] ) ;
157
+ } ,
158
+ } ;
159
+
160
+ // 目前 items 在 https://github.com/handsontable/handsontable/blob/6.2.2/handsontable.d.ts#L779,自定义方法也可以被执行
161
+ const items = { } ;
162
+ if ( Array . isArray ( copyTypes ) && copyTypes ?. length ) {
163
+ // 复制值
164
+ if ( copyTypes . includes ( 'copyData' ) ) {
165
+ items [ 'copyData' ] = copyDataItem ;
166
+ }
167
+ // 复制列名
168
+ if ( copyTypes . includes ( 'copyHeaders' ) ) {
169
+ items [ 'copyHeaders' ] = copyHeadersItem ;
170
+ }
171
+ // 复制列名和值
172
+ if ( copyTypes . includes ( 'copyHeadersAndData' ) ) {
173
+ items [ 'copyHeadersAndData' ] = copyHeadersAndDataItem ;
174
+ }
175
+ } else {
176
+ items [ 'copyData' ] = copyDataItem ;
128
177
}
129
- return {
130
- items,
131
- } as any ;
178
+
179
+ return { items } as any ;
132
180
}
133
181
render ( ) {
134
182
const { columns = [ ] , className = '' , options, columnTypes = [ ] } = this . props ;
135
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
136
- const { trimWhitespace = true , showCopyWithHeader, ...restOptions } = options || { } ;
137
- const showData = this . getData ( ) ;
183
+ const { trimWhitespace = true , ...restOptions } = options || { } ;
184
+ const showData = this . getShowData ( ) ;
138
185
// 空数组情况,不显示colHeaders,否则colHeaders默认会按照 A、B...显示
139
186
// 具体可见 https://handsontable.com/docs/7.1.1/Options.html#colHeaders
140
187
let isShowColHeaders = false ;
@@ -153,7 +200,9 @@ class SpreadSheet extends React.PureComponent<SpreadSheetProps, any> {
153
200
if ( ! isShowColHeaders ) return false ;
154
201
// handsontable 不支持 renderCustomHeader,所以只能用 html string 实现 tooltip
155
202
const fieldTypeStr = columnTypes ?. [ index ] ?. type ;
156
- const title = fieldTypeStr ? `${ columns ?. [ index ] } : ${ fieldTypeStr } ` : columns ?. [ index ] ;
203
+ const title = fieldTypeStr
204
+ ? `${ columns ?. [ index ] } : ${ fieldTypeStr } `
205
+ : columns ?. [ index ] ;
157
206
return `<span title="${ title } ">${ title } </span>` ;
158
207
} }
159
208
data = { showData }
0 commit comments