feat(视图): 明细表/汇总表支持按列设置宽度,拖拽调整宽度。#7707

This commit is contained in:
wisonic-s 2024-02-22 19:22:38 +08:00
parent b478a26c62
commit 3e0f51a7e6
10 changed files with 211 additions and 15 deletions

View File

@ -101,6 +101,7 @@
:terminal-type="scaleCoefficientType"
:track-menu="trackMenu"
:search-count="searchCount"
:in-screen="inScreen"
@onChartClick="chartClick"
@onJumpClick="jumpClick"
@onPageChange="pageClick"

View File

@ -1398,6 +1398,7 @@ export default {
table_column_width_config: 'Column Width',
table_column_adapt: 'Adapt',
table_column_custom: 'Custom',
table_column_fixed: 'Fixed',
chart_table_pivot: 'Pivot Table',
table_pivot_row: 'Data Row',
field_error_tips: 'This field is changed(Include dimension、quotafield typedeleted),please edit again.',
@ -1539,7 +1540,7 @@ export default {
drill_dimension_tip: 'Only fields in the dataset can be drilled',
table_scroll_tip: 'The detail table is only effective when the pagination mode is "Drop-down".',
table_threshold_tip: 'Tip: Do not select fields repeatedly. If the same field is configured repeatedly, only the last field will take effect.',
table_column_width_tip: `Column width do not always work.<br/>
table_column_width_tip: `Fixed Column width do not always work.<br/>
The priority of the container width is higher than the column width, <br/>
which means if the result of dividing the width of the table container by the number of columns is greater than specified column width, <br/>
the former will take effect.`,

View File

@ -1396,6 +1396,7 @@ export default {
table_freeze: '表格凍結',
table_column_adapt: '自適應',
table_column_custom: '自定義',
table_column_fixed: '固定列寬',
chart_table_pivot: '透視表',
table_pivot_row: '數據行',
field_error_tips: '該字段所對應的數據集原始字段發生變更(包括維度、指標,字段類型,字段被刪除等),建議重新編輯',
@ -1536,7 +1537,7 @@ export default {
drill_dimension_tip: '鑽取字段僅支持數據集中的字段',
table_scroll_tip: '明細表僅在分頁模式為"下拉"時生效。',
table_threshold_tip: '提示:請勿重複選擇字段,若同一字段重複配置,則只有最後的字段配置生效。',
table_column_width_tip: '列寬並非任何時候都能生效。<br/>容器寬度優先級高於列寬。即(表格容器寬度 / 列數 > 指定列寬),則列寬優先取(容器寬度 / 列數)',
table_column_width_tip: '固定列寬並非任何時候都能生效。<br/>容器寬度優先級高於列寬。即(表格容器寬度 / 列數 > 指定列寬),則列寬優先取(容器寬度 / 列數)',
reference_field_tip: '引用字段以 "[" 開始,"]" 結束。請<br/>勿修改引用內容,否則將引用失敗。<br/>若輸入與引用字段相同格式的內容,將被當做引用字段處理。',
scatter_tip: '該指標生效時,樣式大小中的氣泡大小屬性將失效',
scatter_group_tip: '僅當橫軸內為指標時生效',

View File

@ -1396,6 +1396,7 @@ export default {
table_column_width_config: '列宽调整',
table_column_adapt: '自适应',
table_column_custom: '自定义',
table_column_fixed: '固定列宽',
chart_table_pivot: '透视表',
table_pivot_row: '数据行',
field_error_tips: '该字段所对应的数据集原始字段发生变更(包括维度、指标,字段类型,字段被删除等),建议重新编辑',
@ -1536,7 +1537,7 @@ export default {
drill_dimension_tip: '钻取字段仅支持数据集中的字段',
table_scroll_tip: '明细表仅在分页模式为"下拉"时生效。',
table_threshold_tip: '提示:请勿重复选择字段,若同一字段重复配置,则只有最后的字段配置生效',
table_column_width_tip: '列宽并非任何时候都能生效。<br/>容器宽度优先级高于列宽,即(表格容器宽度 / 列数 > 指定列宽),则列宽优先取(容器宽度 / 列数)。',
table_column_width_tip: '固定列宽并非任何时候都能生效。<br/>容器宽度优先级高于列宽,即(表格容器宽度 / 列数 > 指定列宽),则列宽优先取(容器宽度 / 列数)。',
reference_field_tip: '引用字段以 "[" 开始, "]" 结束。<br/>请勿修改引用内容,否则将引用失败。<br/>若输入与引用字段相同格式的内容,将被当作引用字段处理。',
scatter_tip: '该指标生效时,样式大小中的气泡大小属性将失效',
scatter_group_tip: '仅当横轴内为指标时生效',

View File

@ -103,6 +103,7 @@ export const DEFAULT_SIZE = {
tableCellTooltip: {
show: false
},
tableFieldWidth: [],
gaugeMinType: 'fix', // fix or dynamic
gaugeMinField: {
id: '',

View File

@ -249,12 +249,33 @@ export function getSize(chart) {
size.cellCfg = {
height: s.tableItemHeight
}
if (s.tableColumnMode && s.tableColumnMode === 'adapt') {
delete size.cellCfg.width
size.layoutWidthType = 'compact'
} else {
delete size.layoutWidthType
size.cellCfg.width = s.tableColumnWidth
switch (s.tableColumnMode) {
case 'adapt': {
delete size.cellCfg.width
size.layoutWidthType = 'compact'
break
}
case 'field': {
delete size.layoutWidthType
const fieldMap = s.tableFieldWidth?.reduce((p, n) => {
p[n.fieldId] = n
return p
}, {}) || {}
size.colCfg.width = node => {
const width = node.spreadsheet.container.cfg.el.offsetWidth
if (!s.tableFieldWidth?.length) {
let columnCount = s.showIndex ? chart.data.fields.length + 1 : chart.data.fields.length
return width / columnCount
}
const baseWidth = width / 100
return fieldMap[node.field] ? fieldMap[node.field].width * baseWidth : baseWidth * 10
}
break
}
default: {
delete size.layoutWidthType
size.cellCfg.width = s.tableColumnWidth
}
}
}
}

View File

@ -75,7 +75,7 @@ class SortTooltip extends BaseTooltip {
})
}
}
export function baseTableInfo(s2, container, chart, action, tableData, pageInfo, vueCom) {
export function baseTableInfo(s2, container, chart, action, tableData, pageInfo, vueCom, resizeFunc) {
const containerDom = document.getElementById(container)
// fields
@ -256,6 +256,10 @@ export function baseTableInfo(s2, container, chart, action, tableData, pageInfo,
if (size.tableCellTooltip?.show) {
s2.on(S2Event.DATA_CELL_HOVER, event => showTooltipValue(s2, event, meta))
}
// column resize
if (size.tableColumnMode === 'field') {
s2.on(S2Event.LAYOUT_RESIZE_COL_WIDTH, event => resizeFunc(event))
}
// theme
const customTheme = getCustomTheme(chart)
s2.setThemeCfg({ theme: customTheme })
@ -263,7 +267,7 @@ export function baseTableInfo(s2, container, chart, action, tableData, pageInfo,
return s2
}
export function baseTableNormal(s2, container, chart, action, tableData, vueCom) {
export function baseTableNormal(s2, container, chart, action, tableData, vueCom, resizeFunc) {
const containerDom = document.getElementById(container)
if (!containerDom) return
@ -490,6 +494,10 @@ export function baseTableNormal(s2, container, chart, action, tableData, vueCom)
if (size.tableCellTooltip?.show) {
s2.on(S2Event.DATA_CELL_HOVER, event => showTooltipValue(s2, event, meta))
}
// column resize
if (size.tableColumnMode === 'field') {
s2.on(S2Event.LAYOUT_RESIZE_COL_WIDTH, event => resizeFunc(event))
}
// theme
const customTheme = getCustomTheme(chart)
s2.setThemeCfg({ theme: customTheme })

View File

@ -102,6 +102,7 @@ import { CHART_CONT_FAMILY_MAP, DEFAULT_TITLE_STYLE, NOT_SUPPORT_PAGE_DATASET }
import ChartTitleUpdate from './ChartTitleUpdate.vue'
import { mapState } from 'vuex'
import DePagination from '@/components/deCustomCm/pagination.js'
import bus from '@/utils/bus'
export default {
name: 'ChartComponentS2',
@ -133,6 +134,10 @@ export default {
type: Number,
required: false,
default: 0
},
inScreen: {
type: Boolean,
default: false
}
},
data() {
@ -296,9 +301,9 @@ export default {
}
}
if (chart.type === 'table-info') {
this.myChart = baseTableInfo(this.myChart, this.chartId, chart, this.antVAction, this.tableData, this.currentPage, this)
this.myChart = baseTableInfo(this.myChart, this.chartId, chart, this.antVAction, this.tableData, this.currentPage, this, this.columnResize)
} else if (chart.type === 'table-normal') {
this.myChart = baseTableNormal(this.myChart, this.chartId, chart, this.antVAction, this.tableData, this)
this.myChart = baseTableNormal(this.myChart, this.chartId, chart, this.antVAction, this.tableData, this, this.columnResize)
} else if (chart.type === 'table-pivot') {
this.myChart = baseTablePivot(this.myChart, this.chartId, chart, this.antVAction, this.tableHeaderClick, this.tableData)
} else {
@ -554,6 +559,21 @@ export default {
},
initRemark() {
this.remarkCfg = getRemark(this.chart)
},
columnResize(resizeColumn) {
if (!this.inScreen) {
// /
return
}
const fieldId = resizeColumn.info.meta.field
const size = JSON.parse(this.chart.customAttr).size
size.tableFieldWidth?.forEach(item => {
if (item.fieldId === fieldId) {
const containerWidth = document.getElementById(this.chartId).offsetWidth
item.width = (resizeColumn.info.resizedWidth / containerWidth * 100).toFixed(2)
}
})
bus.$emit('set-table-column-width', size.tableFieldWidth)
}
}
}

View File

@ -258,10 +258,15 @@
>
<el-radio-group
v-model="sizeForm.tableColumnMode"
class="column-radio"
@change="changeBarSizeCase('tableColumnMode')"
>
<el-radio label="adapt"><span>{{ $t('chart.table_column_adapt') }}</span></el-radio>
<!--此处为了兼容原有的配置原先的自定义效果实际为固定列宽后续添加的按列配置才是实际的自定义列宽-->
<el-radio label="custom">
<span>{{ $t('chart.table_column_fixed') }}</span>
</el-radio>
<el-radio v-if="equalsAny(chart.type, 'table-info', 'table-normal')" label="field">
<span>{{ $t('chart.table_column_custom') }}</span>
</el-radio>
</el-radio-group>
@ -295,6 +300,43 @@
@change="changeBarSizeCase('tableColumnWidth')"
/>
</el-form-item>
<el-form-item
v-if="showProperty('tableColumnMode') && sizeForm.tableColumnMode === 'field'"
label=""
class="form-item"
>
<el-row>
<el-col :span="10">
<el-select
v-model="fieldColumnWidth.fieldId"
:min="10"
:max="500"
show-input
:show-input-controls="false"
input-size="mini"
@change="changeFieldColumn()"
>
<el-option
v-for="item in sizeForm.tableFieldWidth"
:key="item.fieldId"
:label="item.name"
:value="item.fieldId"
/>
</el-select>
</el-col>
<el-col :span="12" :offset="2">
<el-input
v-model.number="fieldColumnWidth.width"
type="number"
:min="0"
:max="100"
@change="changeFieldColumnWidth()"
>
<template #append>%</template>
</el-input>
</el-col>
</el-row>
</el-form-item>
<el-form-item
v-if="showProperty('tableFreeze')"
:label="$t('chart.table_freeze')"
@ -1555,6 +1597,7 @@
import { CHART_FONT_FAMILY, CHART_FONT_LETTER_SPACE, DEFAULT_SIZE } from '../../chart/chart'
import { equalsAny, includesAny } from '@/utils/StringUtils'
import { mapState } from 'vuex'
import { SERIES_NUMBER_FIELD } from '@antv/s2'
export default {
name: 'SizeSelectorAntV',
@ -1618,7 +1661,11 @@ export default {
{ name: this.$t('chart.map_line_type_line'), value: 'line' },
{ name: this.$t('chart.map_line_type_arc'), value: 'arc' },
{ name: this.$t('chart.map_line_type_arc_3d'), value: 'arc3d' }
]
],
fieldColumnWidth: {
fieldId: '',
width: 10
}
}
},
computed: {
@ -1775,6 +1822,67 @@ export default {
}
this.sizeForm.wordSizeRange = this.sizeForm.wordSizeRange ?? DEFAULT_SIZE.wordSizeRange
this.sizeForm.wordSpacing = this.sizeForm.wordSpacing ?? DEFAULT_SIZE.wordSpacing
if (this.chart.type !== 'table-pivot') {
let { xaxis, xaxisExt } = this.chart
if (!(xaxis instanceof Object)) {
xaxis = JSON.parse(xaxis)
}
if (!(xaxisExt instanceof Object)) {
xaxisExt = JSON.parse(xaxisExt)
}
let allAxis = xaxis
if (this.chart.type === 'table-normal') {
allAxis = allAxis.concat(xaxisExt)
}
if (allAxis.length && this.sizeForm.showIndex) {
allAxis.unshift({
dataeaseName: SERIES_NUMBER_FIELD,
name: this.sizeForm.indexLabel
})
}
if (!allAxis.length) {
this.sizeForm.tableFieldWidth?.splice(0)
this.fieldColumnWidth.fieldId = ''
this.fieldColumnWidth.width = ''
} else {
if (!this.sizeForm.tableFieldWidth?.length) {
this.sizeForm.tableFieldWidth = []
const defaultWidth = (100 / allAxis.length).toFixed(2)
allAxis.forEach(item => {
this.sizeForm.tableFieldWidth.push({
fieldId: item.dataeaseName,
name: item.name,
width: defaultWidth
})
})
} else {
const fieldMap = this.sizeForm.tableFieldWidth.reduce((p, n) => {
p[n.fieldId] = n
return p
},{})
this.sizeForm.tableFieldWidth.splice(0)
allAxis.forEach(item => {
let width = 10
if (fieldMap[item.dataeaseName]) {
width = fieldMap[item.dataeaseName].width
}
this.sizeForm.tableFieldWidth.push({
fieldId: item.dataeaseName,
name: item.name,
width
})
})
}
let selectedField = this.sizeForm.tableFieldWidth[0]
const curFieldIndex = this.sizeForm.tableFieldWidth.findIndex(i => i.fieldId === this.fieldColumnWidth.fieldId)
if (curFieldIndex !== -1) {
selectedField = this.sizeForm.tableFieldWidth[curFieldIndex]
}
this.fieldColumnWidth.fieldId = selectedField.fieldId
this.fieldColumnWidth.width = selectedField.width
}
}
}
}
},
@ -1905,6 +2013,19 @@ export default {
}
}
return false
},
changeFieldColumn() {
const fieldWidth = this.sizeForm.tableFieldWidth?.find(i => i.fieldId === this.fieldColumnWidth.fieldId)
if (fieldWidth) {
this.fieldColumnWidth.width = fieldWidth.width
}
},
changeFieldColumnWidth() {
const fieldWidth = this.sizeForm.tableFieldWidth?.find(i => i.fieldId === this.fieldColumnWidth.fieldId)
if (fieldWidth) {
fieldWidth.width = this.fieldColumnWidth.width
this.changeBarSizeCase('tableFieldWidth')
}
}
}
}
@ -1965,4 +2086,17 @@ export default {
.form-flex >>> .el-form-item__content {
display: flex;
}
::v-deep input::-webkit-outer-spin-button,
::v-deep input::-webkit-inner-spin-button {
-webkit-appearance: none !important;
}
::v-deep input[type="number"] {
-moz-appearance: textfield !important;
}
.column-radio {
label {
margin-right: 10px;
}
}
</style>

View File

@ -2323,6 +2323,7 @@ export default {
bus.$off('plugins-calc-style', this.calcStyle)
bus.$off('plugin-chart-click', this.chartClick)
bus.$off('set-dynamic-area-code', this.setDynamicAreaCode)
bus.$off('set-table-column-width', this.onTableFieldWidthChange)
},
activated() {
},
@ -2413,6 +2414,7 @@ export default {
bus.$on('plugins-calc-style', this.calcStyle)
bus.$on('plugin-chart-click', this.chartClick)
bus.$on('set-dynamic-area-code', this.setDynamicAreaCode)
bus.$on('set-table-column-width', this.onTableFieldWidthChange)
},
initTableData(id, optType) {
if (id != null) {
@ -2962,7 +2964,10 @@ export default {
this.view.customAttr.size = val
this.calcData()
},
onTableFieldWidthChange(val) {
this.view.customAttr.size.tableFieldWidth = val
this.calcData()
},
onTextChange(val) {
this.view.customStyle.text = val
this.view.title = val.title
@ -3651,6 +3656,9 @@ export default {
} else if (type === 'label-normal') {
this.view.senior.functionCfg.emptyDataStrategy = 'breakLine'
}
if (type === 'table-pivot') {
this.view.customAttr.size.tableColumnMode = 'custom'
}
// reset custom colors
this.view.customAttr.color.seriesColors = []
},