feat(视图-表格): 明细表/汇总表支持表头排序#6754

This commit is contained in:
wisonic-s 2024-01-28 19:01:17 +08:00
parent 036c1a01cc
commit 434c7e9489
7 changed files with 162 additions and 11 deletions

View File

@ -602,6 +602,7 @@ export default {
asc: '升序',
desc: '降序',
sort: '排序',
default: '默认',
filter: '过滤',
none: '无',
background: '背景',

View File

@ -0,0 +1,48 @@
<script setup lang="ts">
import { SpreadSheet, Node } from '@antv/s2'
import { PropType } from 'vue'
import { useI18n } from '@/hooks/web/useI18n'
import { S2Event } from '@antv/s2'
import { SortUp, SortDown, Sort } from '@element-plus/icons-vue'
const { t } = useI18n()
const props = defineProps({
table: {
type: Object as PropType<SpreadSheet>,
required: true
},
meta: {
type: Object as PropType<Node>
}
})
const sort = type => {
props.table.updateSortMethodMap(props.meta.field, type, true)
props.table.emit(S2Event.RANGE_SORT, [
{
sortFieldId: props.meta.field,
sortMethod: type
}
])
}
</script>
<template>
<el-col>
<el-row align="middle">
<el-icon><SortUp /></el-icon>
<span class="sort-btn" @click="() => sort('asc')">{{ t('chart.asc') }}</span>
</el-row>
<el-row align="middle">
<el-icon><SortDown /></el-icon>
<span class="sort-btn" @click="() => sort('desc')">{{ t('chart.desc') }}</span>
</el-row>
<el-row align="middle">
<el-icon><Sort /></el-icon>
<span class="sort-btn" @click="() => sort()">{{ t('chart.default') }}</span>
</el-row>
</el-col>
</template>
<style scoped>
.sort-btn {
cursor: pointer;
}
</style>

View File

@ -1,4 +1,4 @@
import { S2Event, S2Options, TableColCell, TableDataCell, TableSheet } from '@antv/s2/esm/index'
import { S2Event, S2Options, TableColCell, TableDataCell, TableSheet } from '@antv/s2'
import { formatterItem, valueFormatter } from '../../../formatter'
import { parseJson } from '../../../util'
import { S2ChartView, S2DrawOptions } from '../../types/impl/s2'
@ -125,7 +125,8 @@ export class TableInfo extends S2ChartView<TableSheet> {
return new TableDataCell(viewMeta, viewMeta?.spreadsheet)
}
}
// tooltip
this.configTooltip(s2Options)
// 开始渲染
const newChart = new TableSheet(containerDom, s2DataConfig, s2Options)

View File

@ -1,12 +1,11 @@
import { S2ChartView, S2DrawOptions } from '@/views/chart/components/js/panel/types/impl/s2'
import { S2Event, S2Options, TableSheet } from '@antv/s2/esm/index'
import { S2Event, S2Options, TableSheet, TableColCell } from '@antv/s2'
import { parseJson } from '@/views/chart/components/js/util'
import { formatterItem, valueFormatter } from '@/views/chart/components/js/formatter'
import { getCurrentField } from '@/views/chart/components/js/panel/common/common_table'
import { TABLE_EDITOR_PROPERTY, TABLE_EDITOR_PROPERTY_INNER } from './common'
import { useI18n } from '@/hooks/web/useI18n'
import { isNumber } from 'lodash-es'
import { TableColCell } from '@antv/s2'
const { t } = useI18n()
/**
@ -121,7 +120,8 @@ export class TableNormal extends S2ChartView<TableSheet> {
return new TableColCell(node, sheet, config)
}
}
// tooltip
this.configTooltip(s2Options)
// 开始渲染
const newChart = new TableSheet(containerDom, s2DataConfig, s2Options)

View File

@ -1,11 +1,10 @@
import { EXTRA_FIELD, PivotSheet, S2Event, S2Options, TOTAL_VALUE } from '@antv/s2/esm/index'
import { EXTRA_FIELD, PivotSheet, S2Event, S2Options, TOTAL_VALUE, S2Theme } from '@antv/s2'
import { formatterItem, valueFormatter } from '../../../formatter'
import { hexColorToRGBA, parseJson } from '../../../util'
import { S2ChartView, S2DrawOptions } from '../../types/impl/s2'
import { TABLE_EDITOR_PROPERTY_INNER } from './common'
import { useI18n } from '@/hooks/web/useI18n'
import { maxBy, merge, minBy } from 'lodash-es'
import { S2Theme } from '@antv/s2'
const { t } = useI18n()

View File

@ -4,8 +4,19 @@ import {
DEFAULT_TABLE_CELL,
DEFAULT_TABLE_HEADER
} from '@/views/chart/components/editor/util/chart'
import { S2Theme, Style } from '@antv/s2'
import {
BaseTooltip,
getAutoAdjustPosition,
getTooltipDefaultOptions,
S2Theme,
setTooltipContainerStyle,
Style,
S2Options,
SERIES_NUMBER_FIELD
} from '@antv/s2'
import { keys, intersection, filter, cloneDeep, merge } from 'lodash-es'
import { createVNode, render } from 'vue'
import TableTooltip from '@/views/chart/components/editor/common/TableTooltip.vue'
export function getCustomTheme(chart: Chart): S2Theme {
const headerColor = hexColorToRGBA(
@ -537,3 +548,90 @@ export function handleTableEmptyStrategy(chart: Chart) {
}
return newData
}
class SortTooltip extends BaseTooltip {
show(showOptions) {
const { iconName } = showOptions
if (iconName) {
this.showSortTooltip(showOptions)
return
}
super.show(showOptions)
}
showSortTooltip(showOptions) {
const { position, options, meta, event } = showOptions
const { enterable } = getTooltipDefaultOptions(options)
const { autoAdjustBoundary, adjustPosition } = this.spreadsheet.options.tooltip || {}
this.visible = true
this.options = showOptions
const container = this['getContainer']()
// vue 手动 patch
const vNode = createVNode(TableTooltip, {
table: this.spreadsheet,
meta
})
this.spreadsheet.tooltip.container.innerHTML = ''
const childElement = document.createElement('div')
this.spreadsheet.tooltip.container.appendChild(childElement)
render(vNode, childElement, false)
const { x, y } = getAutoAdjustPosition({
spreadsheet: this.spreadsheet,
position,
tooltipContainer: container,
autoAdjustBoundary
})
this.position = adjustPosition?.({ position: { x, y }, event }) ?? {
x,
y
}
setTooltipContainerStyle(container, {
style: {
left: `${this.position?.x}px`,
top: `${this.position?.y}px`,
pointerEvents: enterable ? 'all' : 'none'
},
visible: true
})
}
}
export function configTooltip(option: S2Options) {
const sortIconMap = {
asc: 'SortUp',
desc: 'SortDown'
}
option.tooltip = {
...option.tooltip,
renderTooltip: sheet => new SortTooltip(sheet)
}
option.headerActionIcons = [
{
iconNames: ['GroupAsc', 'SortUp', 'SortDown'],
belongsCell: 'colCell',
displayCondition: (meta, iconName) => {
if (meta.field === SERIES_NUMBER_FIELD) {
return false
}
const sortMethodMap = meta.spreadsheet.store.get('sortMethodMap')
const sortType = sortMethodMap?.[meta.field]
if (sortType) {
return iconName === sortIconMap[sortType]
}
return iconName === 'GroupAsc'
},
onClick: props => {
const { meta, event } = props
meta.spreadsheet.showTooltip({
position: {
x: event.clientX,
y: event.clientY
},
event,
...props
})
}
}
]
}

View File

@ -3,13 +3,15 @@ import {
AntVDrawOptions,
ChartLibraryType
} from '@/views/chart/components/js/panel/types'
import { S2Theme, SpreadSheet, Style } from '@antv/s2'
import { S2Theme, SpreadSheet, Style, S2Options } from '@antv/s2'
import {
configTooltip,
getConditions,
getCustomTheme,
getStyle,
handleTableEmptyStrategy
} from '@/views/chart/components/js/panel/common/common_table'
import '@antv/s2/dist/style.min.css'
declare interface PageInfo {
currentPage: number
@ -19,9 +21,7 @@ declare interface PageInfo {
export interface S2DrawOptions<O> extends AntVDrawOptions<O> {
pageInfo?: PageInfo
tableHeaderClick?: (args: any[]) => void
}
export abstract class S2ChartView<P extends SpreadSheet> extends AntVAbstractChartView {
public abstract drawChart(drawOption: S2DrawOptions<P>): P
protected constructor(name: string, defaultData: any[]) {
@ -39,6 +39,10 @@ export abstract class S2ChartView<P extends SpreadSheet> extends AntVAbstractCha
return handleTableEmptyStrategy(chart)
}
protected configTooltip(option: S2Options) {
configTooltip(option)
}
protected configConditions(chart: Chart) {
return getConditions(chart)
}