import { uuid } from '@/utils/common' ; import { compareDate } from '@/utils/date' ; import { isArray , isDate } from '@/utils/is' ; import { Row } from './row' ; interface RowOperateOptions { index : number ; uuid ? : undefined | string ; } let UID = 0 ; /**
 * 整个gantt项目的数据结构，整理外部的数据
 */ export class GanttData { /**
     * 数据集合，内部使用
     */ data : Row [ ] ; /**
     * 源数据集合
     */ originData : any [ ] ; private __start : Date | null ; private __end : Date | null ; private __hierarchy : number ; private __selected : RowOperateOptions ; private __hovered : RowOperateOptions ; private __len : number ; private readonly __that : GanttData ; private uid : string ; constructor ( ) { this . uid = uuid ( 12 ) ; this . data = [ ] ; this . originData = [ ] ; this . __start = null ; this . __end = null ; this . __hierarchy = 0 ; this . __selected = { index : - 1 } ; this . __hovered = { index : - 1 } ; this . __len = 0 ; this . __that = this ; } param data param options initData ( data , options = { } ) { this . originData = data ; this . data = this . __createDataTree ( data , [ ] , options ) ; this . __len = this . data . length ; } /**
     * 获取数据的展示长度。可通过该属性计算wrap的完整高度
     */ get len ( ) { return this . __len ; } /**
     * 获取选中的信息
     */ get selected ( ) { return this . __selected ; } /**
     * 获取鼠标悬停的信息
     */ get hovered ( ) { return this . __hovered ; } /**
     * 获取数据集合的最起始时间
     */ get start ( ) { return this . __start ; } param v setStart ( v ? ) { if ( v && isDate ( v ) ) this . __start = v ; else this . __start = null ; } /**
     * 获取数据集合的最截止时间
     */ get end ( ) { return this . __end ; } param v setEnd ( v ? ) { if ( v && isDate ( v ) ) this . __end = v ; else this . __end = null ; } private __createDataTree ( data , parentId , options = { } , level = 0 , parentNode = null ) { const r = [ ] ; for ( let i = 0 ; i < data . length ; i ++ ) { r . push ( this . __createDataNode ( data [ i ] , i , parentId , level , parentNode , options ) ) ; } return r ; } private __createDataNode ( data , index , parentId , level , parentNode , options ) { const item = new Row ( ) ; item . initData ( data , options ) ; item . index = index ; item . level = level ; item . parentId = parentId ; item . parentNode = parentNode ; this . __updateDate ( item ) ; const p = [ ... parentId ] ; p . push ( index ) ; if ( isArray ( data . children ) ) { item . children = this . __createDataTree ( data . children , p , options , level + 1 , item ) ; } if ( level > this . __hierarchy ) this . __hierarchy = level ; return item ; } /**
     * 更新起止时间
     */ private __updateDate ( item ) { if ( ! this . start || compareDate ( item . start as Date , this . start ) === 'l' ) { this . __start = item . start ; } if ( ! this . end || compareDate ( item . end as Date , this . end ) === 'r' ) { this . __end = item . end ; } } param newData param item param options returns update ( newData , item = null , options = { } ) { this . __diff ( options , this . data , newData ) ; if ( ! item ) return ; const t = this . flatData . find ( x => x . uuid === item . uuid ) ; this . __selected = { index : t ?. __uindex ?? - 1 , uuid : t ?. uuid ?? undefined } ; } param options param originData param newData param parentNode private __diff ( options , originData , newData , parentNode = null ) { let i = 0 ; while ( i < newData . length ) { if ( i < originData . length && ! originData [ i ] . isSame ( newData [ i ] ) ) { if ( i + 1 < originData . length && originData [ i + 1 ] . isSame ( newData [ i ] ) ) { originData . splice ( i , 1 ) ; } else if ( i + 1 < newData . length && originData [ i ] . isSame ( newData [ i + 1 ] ) ) { const item = this . __createDataNode ( newData [ i ] , i , originData [ i ] . parentId , originData [ i ] . level , originData [ i ] . parentNode , options ) ; originData . splice ( i , 0 , item ) ; } else { const item = this . __createDataNode ( newData [ i ] , i , originData [ i ] . parentId , originData [ i ] . level , originData [ i ] . parentNode , options ) ; originData . splice ( i , 1 , item ) ; } } if ( originData [ i ] === undefined ) { const item = this . __createDataNode ( newData [ i ] , i , parentNode ? [ ... parentNode . parentId , parentNode . index ] : [ ] , parentNode ? parentNode . level + 1 : 0 , parentNode , options ) ; originData . splice ( i , 1 , item ) ; } this . __diff ( options , originData [ i ] . children , newData [ i ] . children , originData [ i ] ) ; this . __updateDate ( originData [ i ] ) ; i += 1 ; } if ( originData [ i ] ) { originData . splice ( i , originData . length ) ; } } param data setSelectedByData ( data ) { const fn = ( d ) => { if ( isArray ( d ) ) { for ( let i = 0 ; i < d . length ; i ++ ) { if ( d [ i ] . isSame ( data ) ) { this . __selected = { index : d [ i ] . __uindex , uuid : d [ i ] . uuid } ; break ; } else if ( d [ i ] . children ) { fn ( d [ i ] . children ) ; } } } } ; fn ( this . data ) ; } param options setHovered ( options ) { this . __hovered = options ; } param options setSelected ( options ) { this . __selected = options ; } /**
     * 获取整个数据集合的层级规模
     */ get hierarchy ( ) { return this . __hierarchy + 1 ; } /**
     * 获取数据的展平列表
     */ get flatData ( ) : Row [ ] { UID = 0 ; const arr = [ ] ; this . __flatten ( this . data , arr ) ; this . __len = arr . length ; return arr ; } private __flatten ( data , arr ) { for ( let i = 0 ; i < data . length ; i ++ ) { data [ i ] . __uindex = UID ; UID += 1 ; arr . push ( data [ i ] ) ; if ( data [ i ] . isExpand && isArray ( data [ i ] . children ) ) { this . __flatten ( data [ i ] . children , arr ) ; } } } } export default GanttData ;