diff --git a/core/frontend/src/lang/en.js b/core/frontend/src/lang/en.js
index 60fbf8b68c..d9107a87b7 100644
--- a/core/frontend/src/lang/en.js
+++ b/core/frontend/src/lang/en.js
@@ -1488,6 +1488,8 @@ export default {
label_content: 'Label Content',
percent: 'Percent',
table_index_desc: 'Index Header Name',
+ table_row_tooltip: 'Row Tooltip',
+ table_col_tooltip: 'Column Tooltip',
total_sort: 'Total Sort',
total_sort_none: 'None',
total_sort_asc: 'ASC',
diff --git a/core/frontend/src/lang/tw.js b/core/frontend/src/lang/tw.js
index d09ad5b60b..46f81309e5 100644
--- a/core/frontend/src/lang/tw.js
+++ b/core/frontend/src/lang/tw.js
@@ -1487,6 +1487,8 @@ export default {
label_content: '標籤展示',
percent: '占比',
table_index_desc: '表頭名稱',
+ table_row_tooltip: '行頭提示',
+ table_col_tooltip: '列頭提示',
total_sort: '總計排序',
total_sort_none: '無',
total_sort_asc: '升序',
diff --git a/core/frontend/src/lang/zh.js b/core/frontend/src/lang/zh.js
index ec9e6a5618..9caef8aa21 100644
--- a/core/frontend/src/lang/zh.js
+++ b/core/frontend/src/lang/zh.js
@@ -1486,6 +1486,8 @@ export default {
label_content: '标签展示',
percent: '占比',
table_index_desc: '表头名称',
+ table_row_tooltip: '行头提示',
+ table_col_tooltip: '列头提示',
total_sort: '总计排序',
total_sort_none: '无',
total_sort_asc: '升序',
diff --git a/core/frontend/src/main.js b/core/frontend/src/main.js
index 8081fd0d2b..dc12881242 100644
--- a/core/frontend/src/main.js
+++ b/core/frontend/src/main.js
@@ -40,6 +40,7 @@ import VueFriendlyIframe from 'vue-friendly-iframe'
import vueToPdf from 'vue-to-pdf'
import VueVideoPlayer from 'vue-video-player'
import 'video.js/dist/video-js.css'
+import '@antv/s2/dist/style.min.css'
// 控制标签宽高成比例的指令
import proportion from 'vue-proportion-directive'
diff --git a/core/frontend/src/views/chart/chart/chart.js b/core/frontend/src/views/chart/chart/chart.js
index 1af8b92939..9028a31522 100644
--- a/core/frontend/src/views/chart/chart/chart.js
+++ b/core/frontend/src/views/chart/chart/chart.js
@@ -86,6 +86,12 @@ export const DEFAULT_SIZE = {
tableHeaderAlign: 'left',
tableItemAlign: 'right',
tableAutoBreakLine: false,
+ tableRowTooltip: {
+ show: false
+ },
+ tableColTooltip: {
+ show: false
+ },
gaugeMinType: 'fix', // fix or dynamic
gaugeMinField: {
id: '',
diff --git a/core/frontend/src/views/chart/chart/table/table-info.js b/core/frontend/src/views/chart/chart/table/table-info.js
index 4f262bf81e..37f026b1b6 100644
--- a/core/frontend/src/views/chart/chart/table/table-info.js
+++ b/core/frontend/src/views/chart/chart/table/table-info.js
@@ -1,4 +1,4 @@
-import { TableSheet, S2Event, PivotSheet, DataCell, EXTRA_FIELD, TOTAL_VALUE } from '@antv/s2'
+import { TableSheet, S2Event, PivotSheet, DataCell, EXTRA_FIELD, TOTAL_VALUE, BaseEvent } from '@antv/s2'
import { getCustomTheme, getSize } from '@/views/chart/chart/common/common_table'
import { DEFAULT_COLOR_CASE, DEFAULT_TOTAL } from '@/views/chart/chart/chart'
import { formatterItem, valueFormatter } from '@/views/chart/chart/formatter'
@@ -7,7 +7,7 @@ export function baseTableInfo(s2, container, chart, action, tableData, pageInfo)
const containerDom = document.getElementById(container)
// fields
- const fields = chart.data.fields
+ let fields = chart.data.fields
if (!fields || fields.length === 0) {
if (s2) {
s2.destroy()
@@ -17,8 +17,17 @@ export function baseTableInfo(s2, container, chart, action, tableData, pageInfo)
const columns = []
const meta = []
-
- // add drill list
+ // 记录下钻起始字段的index
+ let xAxis = []
+ try {
+ xAxis = JSON.parse(chart.xaxis)
+ } catch (err) {
+ xAxis = JSON.parse(JSON.stringify(chart.xaxis))
+ }
+ const nameMap = xAxis.reduce((pre, next) => {
+ pre[next.dataeaseName] = next
+ return pre
+ }, {})
if (chart.drill) {
let drillFields = []
try {
@@ -26,107 +35,44 @@ export function baseTableInfo(s2, container, chart, action, tableData, pageInfo)
} catch (err) {
drillFields = JSON.parse(JSON.stringify(chart.drillFields))
}
-
- const drillField = drillFields[chart.drillFilters.length]
-
- const drillFilters = JSON.parse(JSON.stringify(chart.drillFilters))
- const drillExp = drillFilters[drillFilters.length - 1].datasetTableField
-
- // 记录下钻起始字段的index
- let xAxis = []
- try {
- xAxis = JSON.parse(chart.xaxis)
- } catch (err) {
- xAxis = JSON.parse(JSON.stringify(chart.xaxis))
- }
- let index = 0
- for (let i = 0; i < xAxis.length; i++) {
- if (xAxis[i].id === drillFilters[0].fieldId) {
- index = i
- break
- }
- }
-
- // 移除所有下钻字段
- const removeField = []
- for (let i = 0; i < chart.drillFilters.length; i++) {
- const ele = chart.drillFilters[i].datasetTableField
- removeField.push(ele.dataeaseName)
- }
-
- // build field
- fields.forEach(ele => {
- if (removeField.indexOf(ele.dataeaseName) < 0) {
- // 用下钻字段替换当前字段
- if (drillExp.dataeaseName === ele.dataeaseName) {
- columns.push(drillField.dataeaseName)
- meta.push({
- field: drillField.dataeaseName,
- name: drillField.name
- })
- } else {
- const f = getCurrentField(chart.xaxis, ele)
- columns.push(ele.dataeaseName)
- meta.push({
- field: ele.dataeaseName,
- name: ele.name,
- formatter: function(value) {
- if (!f) {
- return value
- }
- if (value === null || value === undefined) {
- return value
- }
- if (f.groupType === 'd') {
- return value
- } else {
- if (f.formatterCfg) {
- const v = valueFormatter(value, f.formatterCfg)
- return v.includes('NaN') ? value : v
- } else {
- const v = valueFormatter(value, formatterItem)
- return v.includes('NaN') ? value : v
- }
- }
- }
- })
- }
- }
- })
-
- // 修正下钻字段的index,获取下钻位置元素添加到index位置,并删除
- const ele = columns[columns.length - 1]
- columns.splice(index, 0, ele)
- columns.splice(columns.length - 1, 1)
- } else {
- fields.forEach(ele => {
- const f = getCurrentField(chart.xaxis, ele)
- columns.push(ele.dataeaseName)
- meta.push({
- field: ele.dataeaseName,
- name: ele.name,
- formatter: function(value) {
- if (!f) {
- return value
- }
- if (value === null || value === undefined) {
- return value
- }
- if (f.groupType === 'd') {
- return value
- } else {
- if (f.formatterCfg) {
- const v = valueFormatter(value, f.formatterCfg)
- return v.includes('NaN') ? value : v
- } else {
- const v = valueFormatter(value, formatterItem)
- return v.includes('NaN') ? value : v
- }
- }
- }
- })
- })
+ // 总下钻过滤字段
+ const drillFilters = JSON.parse(JSON.stringify(chart.drillFilters)).map(i => i.fieldId)
+ // 当前下钻字段
+ const curDrillField = drillFields[chart.drillFilters.length]
+ drillFilters.push(curDrillField.id)
+ // 下钻入口字段的下标
+ const drillEnterFieldIndex = xAxis.findIndex(item => item.id === drillFilters[0])
+ // 移除所有下钻字段,调整当前下钻字段到下钻入口位置
+ fields = fields.filter(item => !drillFilters.includes(item.id))
+ fields.splice(drillEnterFieldIndex, 0, curDrillField)
}
+ fields.forEach(ele => {
+ const f = nameMap[ele.dataeaseName]
+ columns.push(ele.dataeaseName)
+ meta.push({
+ field: ele.dataeaseName,
+ name: ele.name,
+ formatter: function(value) {
+ if (!f) {
+ return value
+ }
+ if (value === null || value === undefined) {
+ return value
+ }
+ if (f.groupType === 'd') {
+ return value
+ } else {
+ if (f.formatterCfg) {
+ const v = valueFormatter(value, f.formatterCfg)
+ return v.includes('NaN') ? value : v
+ } else {
+ const v = valueFormatter(value, formatterItem)
+ return v.includes('NaN') ? value : v
+ }
+ }
+ }
+ })
+ })
// 空值处理
const newData = handleTableEmptyStrategy(tableData, chart)
// data config
@@ -174,6 +120,11 @@ export function baseTableInfo(s2, container, chart, action, tableData, pageInfo)
// click
s2.on(S2Event.DATA_CELL_CLICK, action)
+ // hover
+ const size = customAttr.size
+ if (size.tableColTooltip?.show) {
+ s2.on(S2Event.COL_CELL_HOVER, event => showTooltip(s2, event))
+ }
// theme
const customTheme = getCustomTheme(chart)
@@ -342,7 +293,11 @@ export function baseTableNormal(s2, container, chart, action, tableData) {
// click
s2.on(S2Event.DATA_CELL_CLICK, action)
-
+ // hover
+ const size = customAttr.size
+ if (size.tableColTooltip?.show) {
+ s2.on(S2Event.COL_CELL_HOVER, event => showTooltip(s2, event))
+ }
// theme
const customTheme = getCustomTheme(chart)
s2.setThemeCfg({ theme: customTheme })
@@ -455,8 +410,8 @@ export function baseTablePivot(s2, container, chart, action, headerAction, table
// total config
let totalCfg = {}
const chartObj = JSON.parse(JSON.stringify(chart))
+ let customAttr
if (chartObj.customAttr) {
- let customAttr = null
if (Object.prototype.toString.call(chartObj.customAttr) === '[object Object]') {
customAttr = JSON.parse(JSON.stringify(chartObj.customAttr))
} else {
@@ -528,7 +483,14 @@ export function baseTablePivot(s2, container, chart, action, headerAction, table
s2.on(S2Event.DATA_CELL_CLICK, action)
s2.on(S2Event.ROW_CELL_CLICK, headerAction)
s2.on(S2Event.COL_CELL_CLICK, headerAction)
-
+ // hover
+ const size = customAttr?.size
+ if (size?.tableRowTooltip?.show) {
+ s2.on(S2Event.ROW_CELL_HOVER, event => showTooltip(s2, event))
+ }
+ if (size?.tableColTooltip?.show) {
+ s2.on(S2Event.COL_CELL_HOVER, event => showTooltip(s2, event))
+ }
// theme
const customTheme = getCustomTheme(chart)
s2.setThemeCfg({ theme: customTheme })
@@ -740,3 +702,17 @@ function mappingColor(value, defaultColor, field, type) {
}
return color
}
+
+function showTooltip(s2Instance, event) {
+ const cell = s2Instance.getCell(event.target)
+ const meta = cell.getMeta()
+ const content = meta.value
+
+ s2Instance.showTooltip({
+ position: {
+ x: event.clientX,
+ y: event.clientY
+ },
+ content
+ })
+}
diff --git a/core/frontend/src/views/chart/chart/util.js b/core/frontend/src/views/chart/chart/util.js
index fdacc429a7..cbde5bcffd 100644
--- a/core/frontend/src/views/chart/chart/util.js
+++ b/core/frontend/src/views/chart/chart/util.js
@@ -62,7 +62,8 @@ export const TYPE_CONFIGS = [
'tableItemHeight',
'tableColumnMode',
'showIndex',
- 'indexLabel'
+ 'indexLabel',
+ 'tableColTooltip'
],
'title-selector-ant-v': [
'show',
@@ -111,7 +112,8 @@ export const TYPE_CONFIGS = [
'tableItemHeight',
'tableColumnMode',
'showIndex',
- 'indexLabel'
+ 'indexLabel',
+ 'tableColTooltip'
],
'title-selector-ant-v': [
'show',
@@ -157,7 +159,9 @@ export const TYPE_CONFIGS = [
'tableItemAlign',
'tableTitleHeight',
'tableItemHeight',
- 'tableColumnMode'
+ 'tableColumnMode',
+ 'tableRowTooltip',
+ 'tableColTooltip'
],
'total-cfg': [
'row',
diff --git a/core/frontend/src/views/chart/components/ChartComponentS2.vue b/core/frontend/src/views/chart/components/ChartComponentS2.vue
index 31d5e3ca22..66597743cd 100644
--- a/core/frontend/src/views/chart/components/ChartComponentS2.vue
+++ b/core/frontend/src/views/chart/components/ChartComponentS2.vue
@@ -613,3 +613,8 @@ export default {
background: transparent !important;
}
+
diff --git a/core/frontend/src/views/chart/components/shapeAttr/SizeSelectorAntV.vue b/core/frontend/src/views/chart/components/shapeAttr/SizeSelectorAntV.vue
index bbb8916efa..92b4155b21 100644
--- a/core/frontend/src/views/chart/components/shapeAttr/SizeSelectorAntV.vue
+++ b/core/frontend/src/views/chart/components/shapeAttr/SizeSelectorAntV.vue
@@ -384,6 +384,28 @@
@blur="changeBarSizeCase('indexLabel')"
/>
+
+
+
+
+
+
@@ -1565,6 +1587,8 @@ export default {
this.sizeForm.tableHeaderAlign = this.sizeForm.tableHeaderAlign ? this.sizeForm.tableHeaderAlign : DEFAULT_SIZE.tableHeaderAlign
this.sizeForm.tableItemAlign = this.sizeForm.tableItemAlign ? this.sizeForm.tableItemAlign : DEFAULT_SIZE.tableItemAlign
+ this.sizeForm.tableRowTooltip = this.sizeForm.tableRowTooltip ?? DEFAULT_SIZE.tableRowTooltip
+ this.sizeForm.tableColTooltip = this.sizeForm.tableColTooltip ?? DEFAULT_SIZE.tableColTooltip
this.sizeForm.showIndex = this.sizeForm.showIndex ? this.sizeForm.showIndex : DEFAULT_SIZE.showIndex
if (this.sizeForm.indexLabel === null || this.sizeForm.indexLabel === undefined) {