11import React from 'react' ;
2-
3- import CopyUtils from '../utils/copy' ;
4- import { HotTable } from '@handsontable/react' ;
52import type { HotTableProps } from '@handsontable/react' ;
3+ import { HotTable } from '@handsontable/react' ;
64import classNames from 'classnames' ;
7- import 'handsontable/dist/handsontable.full.css' ;
85import 'handsontable/languages/zh-CN.js' ;
96
7+ import CopyUtils from '../utils/copy' ;
8+ import 'handsontable/dist/handsontable.full.css' ;
9+
1010type IOptions = HotTableProps & {
11- /** 是否展示复制值以及列名 */
12- showCopyWithHeader ?: boolean ;
11+ // 右击右键菜单中展示的选项 复制值/复制列名/复制列名和值 按钮 */
12+ copyTypes ?: Array < 'copyData' | 'copyHeaders' | 'copyHeadersAndData' > ;
1313} ;
1414
15- export interface SpreadSheetProps {
15+ export interface ISpreadSheetProps {
1616 data : Array < Array < string | null | number > > ;
1717 columns : any ;
1818 className ?: string ;
@@ -27,7 +27,7 @@ export interface SpreadSheetProps {
2727 hotTableInstanceRef ?: ( instance : any ) => void ;
2828}
2929
30- class SpreadSheet extends React . PureComponent < SpreadSheetProps , any > {
30+ class SpreadSheet extends React . PureComponent < ISpreadSheetProps , any > {
3131 tableRef : any = React . createRef ( ) ;
3232 copyUtils = new CopyUtils ( ) ;
3333 _renderTimer : any ;
@@ -54,7 +54,7 @@ class SpreadSheet extends React.PureComponent<SpreadSheetProps, any> {
5454 componentWillUnmount ( ) {
5555 this . removeRenderClock ( ) ;
5656 }
57- getData ( ) {
57+ getShowData ( ) {
5858 const { data, columns = [ ] } = this . props ;
5959 let showData = data ;
6060 if ( ! showData || ! showData . length ) {
@@ -78,63 +78,110 @@ class SpreadSheet extends React.PureComponent<SpreadSheetProps, any> {
7878 }
7979 return null ;
8080 }
81- beforeCopy ( arr : any , _arr2 ?: any ) {
82- /**
83- * 去除格式化
84- */
81+
82+ /**
83+ * 去除格式化
84+ */
85+ beforeCopy ( arr : Array < Array < any > > ) {
8586 const value = arr
8687 . map ( ( row : any ) => {
8788 return row . join ( '\t' ) ;
8889 } )
8990 . join ( '\n' ) ;
91+
9092 this . copyUtils . copy ( value ) ;
9193 return false ;
9294 }
9395 getContextMenu ( ) {
9496 const that = this ;
9597 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 ;
106120 } ;
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 ;
117129 if ( columnStart !== undefined && columnEnd !== undefined ) {
118- columnArr = columns . slice ( columnStart , columnEnd + 1 ) ;
130+ headerArr = headerArr . concat ( columns . slice ( columnStart , columnEnd + 1 ) ) ;
119131 }
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 ;
128177 }
129- return {
130- items,
131- } as any ;
178+
179+ return { items } as any ;
132180 }
133181 render ( ) {
134182 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 ( ) ;
138185 // 空数组情况,不显示colHeaders,否则colHeaders默认会按照 A、B...显示
139186 // 具体可见 https://handsontable.com/docs/7.1.1/Options.html#colHeaders
140187 let isShowColHeaders = false ;
@@ -153,7 +200,9 @@ class SpreadSheet extends React.PureComponent<SpreadSheetProps, any> {
153200 if ( ! isShowColHeaders ) return false ;
154201 // handsontable 不支持 renderCustomHeader,所以只能用 html string 实现 tooltip
155202 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 ] ;
157206 return `<span title="${ title } ">${ title } </span>` ;
158207 } }
159208 data = { showData }
0 commit comments