@ -7,18 +7,30 @@
<!-- Mini header row -- >
<!-- Mini header row -- >
< div ref = "miniHeaderRef" class = "mini-row mini-header" >
< div ref = "miniHeaderRef" class = "mini-row mini-header" >
< div
< div
v - for = "item in prop.c olumns || []"
v - for = "(column, columnIndex) in tableC olumns || []"
: key = "item .key"
: key = "column .key"
class = "mini-cell mini-header-cell"
class = "mini-cell mini-header-cell"
: style = "getMiniCellStyle(item )"
: style = "getMiniCellStyle(column )"
>
>
< span class = "mini-header-content" > { item . name || ( item . i18n ? t ( item . i18n ) : item . key ) } < / span >
< MiniTableHeader : cellData = "undefined as T" : columnIndex :columns ="tableColumns" : column / >
< / div >
< / div >
< / div >
< / div >
<!-- Mini data rows -- >
<!-- Mini data rows -- >
< div v-for ="(row, rowIdx) in miniTableData" :key="rowIdx" class="mini-row" >
< div v-for ="(rowData, rowIndex) in miniTableData" :key="rowIndex" class="mini-row" >
< div v-for ="item in prop.columns || []" :key="item.key" class="mini-cell" :style="getMiniCellStyle(item)" >
< div
{ renderCellContent ( item , lodash . get ( row , item . dataKey || item . key ) , row , slots ) }
v - for = "(column, columnIndex) in tableColumns || []"
: key = "column.key"
class = "mini-cell"
: style = "getMiniCellStyle(column)"
>
< MiniTableCell
: cellData = "lodash.get(rowData, String(column.dataKey || column.key))"
: columnIndex
: columns = "tableColumns"
: column
: rowData
: rowIndex
/ >
< / div >
< / div >
< / div >
< / div >
< / div >
< / div >
@ -61,13 +73,34 @@
< / div >
< / div >
< / template >
< / template >
< script lang = "tsx" setup >
< script lang = "tsx" setup generic = "T" >
import { useStore } from "vuex" ;
import { useStore } from "vuex" ;
import { ref , computed , watch , h , onMounted , onUpdated , onUnmounted , useSlots , renderSlot , nextTick } from "vue" ;
import {
ref ,
computed ,
watch ,
h ,
onMounted ,
onUpdated ,
onUnmounted ,
useSlots ,
renderSlot ,
nextTick ,
VNode ,
StyleValue ,
} from "vue" ;
import { useI18n } from "vue3-i18n" ;
import { useI18n } from "vue3-i18n" ;
import { ElAutoResizer , ElTableV2 } from "element-plus" ;
import { Column , ElAutoResizer , ElTableV2 } from "element-plus" ;
import * as lodash from "lodash-es" ;
import * as lodash from "lodash-es" ;
import TzDateTime from "../item/tzDateTime.vue" ;
import TzDateTime from "../item/tzDateTime.vue" ;
import {
CellRenderer ,
CellRendererParams ,
HeaderCellRenderer ,
HeaderCellRendererParams ,
} from "element-plus/es/components/table-v2/src/types.mjs" ;
import { match , P } from "ts-pattern" ;
import { FixedDir } from "element-plus/es/components/table-v2/src/constants.mjs" ;
const slots = useSlots ( ) ;
const slots = useSlots ( ) ;
@ -114,7 +147,7 @@ interface TzDateTimeConfig {
type ? : "iso8601" | "unix" | "unixMillis" ;
type ? : "iso8601" | "unix" | "unixMillis" ;
}
}
interface TableColumn {
interface List TableColumn< T > {
key : string ;
key : string ;
dataKey ? : string ;
dataKey ? : string ;
name ? : string ;
name ? : string ;
@ -128,13 +161,16 @@ interface TableColumn {
dict ? : string ;
dict ? : string ;
timestamp ? : TimestampValue ;
timestamp ? : TimestampValue ;
filesize ? : boolean ;
filesize ? : boolean ;
/ / C u s t o m r e n d e r e r s - J S X - r e t u r n i n g f u n c t i o n s t h a t o v e r r i d e s l o t / d e f a u l t r e n d e r i n g
cellRenderer ? : CellRenderer < T > ;
headerCellRenderer ? : HeaderCellRenderer < T > ;
[ others : string ] : any ;
[ others : string ] : any ;
}
}
interface Props {
interface Props {
data ? : any ;
data ? : any ;
columns ? : TableColumn [ ] ;
columns ? : List TableColumn< T > [ ] ;
page ? : boolean ;
page ? : boolean ;
height ? : number | string ;
height ? : number | string ;
maxHeight ? : number | string ;
maxHeight ? : number | string ;
@ -182,17 +218,6 @@ const pageData = computed(() => {
return [ ] ;
return [ ] ;
} ) ;
} ) ;
/ / P r o b e r o w t e x t e x t r a c t i o n ( s a m e l o g i c a s c e l l R e n d e r e r b u t r e t u r n s t e x t o n l y )
const getProbeCellText = ( rowData : any , item : TableColumn ) : string => {
const value = lodash . get ( rowData , item . dataKey || item . key ) ;
if ( item . dict ) return formatterByDist ( item . dict , value ) ;
if ( item . timestamp ) return formatStamp ( value ) ;
if ( item . filesize ) return formatFileSize ( value ) ;
if ( rowData . scheme ) return formatterByDist ( rowData . scheme + "_" + ( item . dataKey || item . key ) , value ) ;
return getValue ( value ) ;
} ;
/ / W h e t h e r t o u s e p r o b e r o w f o r d y n a m i c h e i g h t m e a s u r e m e n t
/ / W h e t h e r t o u s e p r o b e r o w f o r d y n a m i c h e i g h t m e a s u r e m e n t
/ / O n l y u s e p r o b e r o w w h e n r o w H e i g h t i s N O T e x p l i c i t l y s p e c i f i e d
/ / O n l y u s e p r o b e r o w w h e n r o w H e i g h t i s N O T e x p l i c i t l y s p e c i f i e d
const shouldUseProbeRow = computed ( ( ) => {
const shouldUseProbeRow = computed ( ( ) => {
@ -368,23 +393,23 @@ const resolveTimestampProps = (ts: TimestampValue): TzDateTimeConfig | null => {
return config ;
return config ;
} ;
} ;
const formatterByDist = ( dictKey : string , value : any ) => {
const formatterByDist = ( dictKey : string , cellData : any ) => {
if ( ! dictKey ) {
if ( ! dictKey ) {
return getValue ( value ) ;
return getValue ( cellData ) ;
}
}
const mapping = state . dict [ dictKey ] ;
const mapping = state . dict [ dictKey ] ;
if ( mapping == null ) {
if ( mapping == null ) {
return getValue ( value ) ;
return getValue ( cellData ) ;
}
}
return mapping [ value ] == null ? value : mapping [ value ] ;
return mapping [ cellData ] == null ? cellData : mapping [ cellData ] ;
} ;
} ;
const formatCellValue = ( value : any , item : TableColumn , row : any ) => {
const formatCellValue = ( cellData : T , column : ListTableColumn < T > , rowData : any ) => {
if ( item . dict ) return formatterByDist ( item . dict , value ) ;
if ( column . dict ) return formatterByDist ( column . dict , cellData ) ;
if ( item . timestamp ) return formatStamp ( value ) ;
if ( column . timestamp ) return formatStamp ( cellData ) ;
if ( item . filesize ) return formatFileSize ( value ) ;
if ( column . filesize ) return formatFileSize ( cellData ) ;
if ( row . scheme ) return formatterByDist ( row . scheme + "_" + ( item . dataKey || item . key ) , value ) ;
if ( rowData . scheme ) return formatterByDist ( rowData . scheme + "_" + ( column . dataKey || column . key ) , cellData ) ;
return getValue ( value ) ;
return getValue ( cellData ) ;
} ;
} ;
const handleSizeChange = ( val : number ) => {
const handleSizeChange = ( val : number ) => {
@ -418,54 +443,75 @@ const onCellClick = ({ row, column }: { row: any; column: any }) => {
/ / B u i l d c o l u m n s f o r e l - t a b l e - v 2
/ / B u i l d c o l u m n s f o r e l - t a b l e - v 2
const tableColumns = computed ( ( ) => {
const tableColumns = computed ( ( ) => {
return prop . columns . map ( ( item : TableColumn ) => {
return prop . columns . map ( ( column ) : Column < T > => {
const col : any = {
const col : Column < T > = {
key : item . key ,
key : column . key ,
title : item . name || ( item . i18n ? t ( item . i18n ) : item . key ) ,
title : column . name || ( column . i18n ? t ( column . i18n ) : column . key ) ,
dataKey : item . dataKey || item . key ,
dataKey : column . dataKey || column . key ,
align : item . align || "center" ,
align : column . align || "center" ,
fixed : item . fixed ,
fixed : match ( column . fixed )
} ;
. with ( "left" , ( ) => FixedDir . LEFT )
. with ( "right" , ( ) => FixedDir . RIGHT )
. with ( false , ( ) => undefined )
. otherwise ( ( value ) => value ) ,
minWidth : match ( column . minWidth )
. with ( P . number , ( n ) => n )
. with (
P . string ,
( str ) => ! isNaN ( parseInt ( str ) ) ,
( str ) => parseInt ( str )
)
. otherwise ( ( ) => 120 ) ,
/ / I f w i d t h i s e x p l i c i t l y p r o v i d e d , u s e i t ; o t h e r w i s e u s e f l e x G r o w t o a u t o - d i s t r i b u t e
/ / I f w i d t h i s e x p l i c i t l y p r o v i d e d , u s e i t ; o t h e r w i s e u s e f l e x G r o w t o a u t o - d i s t r i b u t e
if ( item . width !== undefined ) {
... match ( column . width )
col . width = typeof item . width === "number" ? item . width : parseInt ( String ( item . width ) ) || 120 ;
. with ( P . number , ( width ) => ( { width } ) )
} else {
. with (
/ / U s e f l e x G r o w : 1 t o a u t o - e x p a n d c o l u m n s t o f i l l a v a i l a b l e w i d t h
P . string ,
col . flexGrow = 1 ;
( str ) => ! isNaN ( parseInt ( str ) ) ,
col . width = 120 ; / / m i n i m u m w i d t h
( str ) => ( { width : parseInt ( str ) } )
}
)
. otherwise ( ( ) => ( { width : 120 , flexGrow : 1 } ) ) ,
} ;
if ( item . minWidth !== undefined ) {
/ / C e l l r e n d e r e r - u s e s r e n d e r C e l l C o n t e n t w h i c h h a n d l e s s l o t , c e l l R e n d e r e r , a n d b u i l t - i n t y p e s
col . minWidth = typeof item . minWidth === "number" ? item . minWidth : parseInt ( String ( item . minWidth ) ) || 120 ;
col . cellRenderer = renderCellContent ;
}
/ / C e l l r e n d e r e r - e l - t a b l e - v 2 u s e s c e l l R e n d e r e r f u n c t i o n
/ / H e a d e r c e l l r e n d e r e r - u s e c u s t o m h e a d e r C e l l R e n d e r e r i f p r o v i d e d
col . cellRenderer = ( { cellData , rowData } : { cellData : any ; rowData : any } ) => {
col . headerCellRenderer = undefined ; / / T O D O
return renderCellContent ( item , cellData , rowData , slots ) ;
} ;
col . _listTableColumn = column ;
return col ;
return col ;
} ) ;
} ) ;
} ) ;
} ) ;
const MiniTableCell = ( params : CellRendererParams < T > ) => renderCellContent ( params ) ;
const MiniTableHeader = ( params : HeaderCellRendererParams < T > ) => renderHeaderCellContent ( params ) ;
/ / S h a r e d c e l l r e n d e r e r - u s e d b y b o t h e l - t a b l e - v 2 a n d m i n i t a b l e f o r c o n s i s t e n t r e n d e r i n g
/ / S h a r e d c e l l r e n d e r e r - u s e d b y b o t h e l - t a b l e - v 2 a n d m i n i t a b l e f o r c o n s i s t e n t r e n d e r i n g
const renderCellContent = ( item : TableColumn , value : any , row : any , slots : ReturnType < typeof useSlots > ) => {
const renderCellContent = ( params : CellRendererParams < T > ) => {
const slotName = item . key ;
const { cellData , rowData , column : elColumn } = params ;
const column : ListTableColumn < T > = elColumn . _listTableColumn ;
const slotName = column . key ;
/ / I f c u s t o m c e l l R e n d e r e r i s p r o v i d e d , u s e i t ( h i g h e s t p r i o r i t y )
if ( column . cellRenderer ) {
return column . cellRenderer ( params ) ;
}
/ / I f c o l u m n h a s s l o t = t r u e , r e n d e r t h e p a r e n t ' s s l o t c o n t e n t
/ / I f c o l u m n h a s s l o t = t r u e , r e n d e r t h e p a r e n t ' s s l o t c o n t e n t
if ( item . slot && slots [ slotName ] ) {
if ( column . slot && slots [ slotName ] ) {
return renderSlot ( slots , slotName , { row } ) ;
return renderSlot ( slots , slotName , { row : rowData } ) ;
}
}
/ / H a n d l e t i m e s t a m p d i s p l a y u s i n g T z D a t e T i m e c o m p o n e n t
/ / H a n d l e t i m e s t a m p d i s p l a y u s i n g T z D a t e T i m e c o m p o n e n t
if ( item . timestamp ) {
if ( column . timestamp && ( typeof cellData === "string" || typeof cellData === "number" ) ) {
const tzProps = resolveTimestampProps ( item . timestamp ) ;
const tzProps = resolveTimestampProps ( column . timestamp ) ;
if ( tzProps ) {
if ( tzProps ) {
const { valueFormat , valueTz , displayFormat , locale , type } = tzProps ;
const { valueFormat , valueTz , displayFormat , locale , type } = tzProps ;
return (
return (
< TzDateTime
< TzDateTime
value = { value }
value = { cellData }
valueFormat = { valueFormat }
valueFormat = { valueFormat }
valueTz = { valueTz }
valueTz = { valueTz }
displayFormat = { displayFormat }
displayFormat = { displayFormat }
@ -477,23 +523,33 @@ const renderCellContent = (item: TableColumn, value: any, row: any, slots: Retur
}
}
/ / H a n d l e d i c t d i s p l a y
/ / H a n d l e d i c t d i s p l a y
if ( item . dict ) {
if ( column . dict ) {
return < span class = "cell-text" > { formatterByDist ( item . dict , value ) } < / span > ;
return < span class = "mini- cell-text" > { formatterByDist ( column . dict , cellData ) } < / span > ;
}
}
/ / H a n d l e f o r m a t t i n g
/ / H a n d l e f o r m a t t i n g
const formatted = formatCellValue ( value , item , row ) ;
const formatted = formatCellValue ( cellData , column , rowData ) ;
return < span class = "cell-text" > { formatted } < / span > ;
return < span class = "mini- cell-text" > { formatted } < / span > ;
} ;
} ;
/ / G e t m i n i c e l l s t y l e - m i r r o r s t h e r e a l t a b l e ' s c o l u m n w i d t h / f l e x d i s t r i b u t i o n
const renderHeaderCellContent = ( params : HeaderCellRendererParams < T > ) => {
const getMiniCellStyle = ( item : TableColumn ) : Record < string , string > => {
const { column : elColumn } = params ;
if ( item . width !== undefined ) {
const column : ListTableColumn < T > = elColumn . _listTableColumn ;
const w = typeof item . width === "number" ? item . width : parseInt ( String ( item . width ) ) || 120 ;
return { width : ` ${ w } px ` , flex : "none" } ;
if ( column . headerCellRenderer ) {
return column . headerCellRenderer ( params ) ;
}
}
/ / U s e f l e x : 1 t o a u t o - e x p a n d c o l u m n s t o f i l l a v a i l a b l e w i d t h ( s a m e a s f l e x G r o w : 1 )
const header = match ( column )
return { flex : "1" , minWidth : "120px" } ;
. with ( { name : P . select ( P . string ) } , ( name ) => name )
. with ( { i18n : P . select ( P . string ) } , ( i18n ) => t ( i18n ) )
. otherwise ( ( c ) => c . key ) ;
return < span class = "mini-header-cell-text" > { header } < / span > ;
} ;
/ / G e t m i n i c e l l s t y l e - m i r r o r s t h e r e a l t a b l e ' s c o l u m n w i d t h / f l e x d i s t r i b u t i o n
const getMiniCellStyle = ( { width , minWidth , maxWidth , flexGrow , flexShrink } : Column < T > ) : StyleValue => {
return { width : ` ${ width } px ` , minWidth : ` ${ minWidth } px ` , maxWidth : ` ${ maxWidth } px ` , flexGrow , flexShrink } ;
} ;
} ;
< / script >
< / script >
@ -514,6 +570,7 @@ const getMiniCellStyle = (item: TableColumn): Record<string, string> => {
left : - 9999 px ;
left : - 9999 px ;
top : 0 ;
top : 0 ;
width : 100 % ;
width : 100 % ;
font - size : var ( -- el - font - size - base ) ;
}
}
. mini - table - inner {
. mini - table - inner {
@ -524,14 +581,17 @@ const getMiniCellStyle = (item: TableColumn): Record<string, string> => {
. mini - row {
. mini - row {
display : flex ;
display : flex ;
align - items : center ;
align - items : stretch ;
padding : v - bind ( "state.size.tablePad" ) ;
padding : v - bind ( "state.size.tablePad" ) ;
border - right : var ( -- el - table - border ) ;
border - right : var ( -- el - table - border ) ;
border - bottom : var ( -- el - table - border ) ;
border - bottom : var ( -- el - table - border ) ;
background : v - bind ( "state.style.tableBg" ) ;
background : v - bind ( "state.style.tableBg" ) ;
color : v - bind ( "state.style.tableColor" ) ;
color : v - bind ( "state.style.tableColor" ) ;
font - size : var ( -- el - font - size - base ) ;
box - sizing : border - box ;
box - sizing : border - box ;
overflow : hidden ;
overflow : hidden ;
width : 100 % ;
min - height : min - content ;
}
}
. mini - header {
. mini - header {
@ -539,28 +599,27 @@ const getMiniCellStyle = (item: TableColumn): Record<string, string> => {
font - weight : bold ;
font - weight : bold ;
}
}
. mini - header - content {
. mini - header - cell {
overflow : visible ;
justify - content : center ;
text - overflow : clip ;
white - space : normal ;
word - break : break - word ;
}
}
. mini - header - cell {
. mini - header - cell - text {
overflow : visible ;
display : block ;
align - self : stretch ;
}
}
. mini - cell {
. mini - cell {
display : flex ;
flex - direction : row ;
align - items : center ;
padding : 4 px ;
box - sizing : border - box ;
box - sizing : border - box ;
white - space : normal ;
word - break : normal ;
overflow : hidden ;
overflow : hidden ;
text - overflow : ellipsis ;
white - space : nowrap ;
}
}
. mini - cell - content {
. mini - cell - text {
overflow : hidden ;
display : block ;
text - overflow : ellipsis ;
}
}
. my - table {
. my - table {
@ -615,12 +674,6 @@ const getMiniCellStyle = (item: TableColumn): Record<string, string> => {
background : v - bind ( "state.style.tableChildBg" ) ! important ;
background : v - bind ( "state.style.tableChildBg" ) ! important ;
}
}
. my - table : deep ( . cell - text ) {
display : block ;
overflow : hidden ;
text - overflow : ellipsis ;
}
. my - pagination {
. my - pagination {
display : flex ;
display : flex ;
justify - content : center ;
justify - content : center ;