forked from github/dataease
feat: 表格滚动
This commit is contained in:
parent
2421b5c80c
commit
a3e8f31e71
@ -1113,7 +1113,13 @@ export default {
|
|||||||
chart_field_edit: 'Chart Field Manage',
|
chart_field_edit: 'Chart Field Manage',
|
||||||
copy_field: 'Copy Field',
|
copy_field: 'Copy Field',
|
||||||
calc_field: 'Calculate Field',
|
calc_field: 'Calculate Field',
|
||||||
form_type: 'From Type'
|
form_type: 'From Type',
|
||||||
|
scroll_cfg: 'Scroll Config',
|
||||||
|
scroll: 'Scroll',
|
||||||
|
open: 'Open',
|
||||||
|
row: 'Row',
|
||||||
|
interval: 'Interval',
|
||||||
|
max_more_than_mix: 'Max must more than Min'
|
||||||
},
|
},
|
||||||
dataset: {
|
dataset: {
|
||||||
select_year: 'Select Year',
|
select_year: 'Select Year',
|
||||||
|
@ -1113,7 +1113,13 @@ export default {
|
|||||||
chart_field_edit: '視圖字段管理',
|
chart_field_edit: '視圖字段管理',
|
||||||
copy_field: '復製字段',
|
copy_field: '復製字段',
|
||||||
calc_field: '計算字段',
|
calc_field: '計算字段',
|
||||||
form_type: '類別'
|
form_type: '類別',
|
||||||
|
scroll_cfg: '滾動設置',
|
||||||
|
scroll: '滾動',
|
||||||
|
open: '開啟',
|
||||||
|
row: '行數',
|
||||||
|
interval: '間隔',
|
||||||
|
max_more_than_mix: '最大值必須大於最小值'
|
||||||
},
|
},
|
||||||
dataset: {
|
dataset: {
|
||||||
select_year: '選擇年',
|
select_year: '選擇年',
|
||||||
|
@ -1115,7 +1115,13 @@ export default {
|
|||||||
chart_field_edit: '视图字段管理',
|
chart_field_edit: '视图字段管理',
|
||||||
copy_field: '复制字段',
|
copy_field: '复制字段',
|
||||||
calc_field: '计算字段',
|
calc_field: '计算字段',
|
||||||
form_type: '类别'
|
form_type: '类别',
|
||||||
|
scroll_cfg: '滚动设置',
|
||||||
|
scroll: '滚动',
|
||||||
|
open: '开启',
|
||||||
|
row: '行数',
|
||||||
|
interval: '间隔',
|
||||||
|
max_more_than_mix: '最大值必须大于最小值'
|
||||||
},
|
},
|
||||||
dataset: {
|
dataset: {
|
||||||
select_year: '选择年',
|
select_year: '选择年',
|
||||||
|
@ -339,6 +339,11 @@ export const DEFAULT_THRESHOLD = {
|
|||||||
gaugeThreshold: '',
|
gaugeThreshold: '',
|
||||||
labelThreshold: []
|
labelThreshold: []
|
||||||
}
|
}
|
||||||
|
export const DEFAULT_SCROLL = {
|
||||||
|
open: false,
|
||||||
|
row: 1,
|
||||||
|
interval: 2000
|
||||||
|
}
|
||||||
// chart config
|
// chart config
|
||||||
export const BASE_BAR = {
|
export const BASE_BAR = {
|
||||||
title: {
|
title: {
|
||||||
|
@ -100,7 +100,9 @@ export default {
|
|||||||
show: 0
|
show: 0
|
||||||
},
|
},
|
||||||
tableData: [],
|
tableData: [],
|
||||||
showPage: false
|
showPage: false,
|
||||||
|
scrollTimer: null,
|
||||||
|
scrollTop: 0
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -133,6 +135,9 @@ export default {
|
|||||||
mounted() {
|
mounted() {
|
||||||
this.preDraw()
|
this.preDraw()
|
||||||
},
|
},
|
||||||
|
beforeDestroy() {
|
||||||
|
clearInterval(this.scrollTimer)
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
initData() {
|
initData() {
|
||||||
let datas = []
|
let datas = []
|
||||||
@ -208,6 +213,7 @@ export default {
|
|||||||
|
|
||||||
if (this.myChart && this.antVRenderStatus) {
|
if (this.myChart && this.antVRenderStatus) {
|
||||||
this.myChart.render()
|
this.myChart.render()
|
||||||
|
this.initScroll()
|
||||||
}
|
}
|
||||||
this.setBackGroundBorder()
|
this.setBackGroundBorder()
|
||||||
},
|
},
|
||||||
@ -371,6 +377,34 @@ export default {
|
|||||||
pageSize: 20,
|
pageSize: 20,
|
||||||
show: 0
|
show: 0
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
initScroll() {
|
||||||
|
clearInterval(this.scrollTimer)
|
||||||
|
// 首先回到最顶部,然后计算行高*行数作为top,最后判断:如果top<数据量*行高,继续滚动,否则回到顶部
|
||||||
|
const customAttr = JSON.parse(this.chart.customAttr)
|
||||||
|
const senior = JSON.parse(this.chart.senior)
|
||||||
|
|
||||||
|
this.scrollTop = 0
|
||||||
|
this.myChart.store.set('scrollY', this.scrollTop)
|
||||||
|
this.myChart.render()
|
||||||
|
|
||||||
|
if (senior.scrollCfg.open && (this.chart.type === 'table-normal' || (this.chart.type === 'table-info' && !this.showPage))) {
|
||||||
|
const rowHeight = customAttr.size.tableItemHeight
|
||||||
|
const headerHeight = customAttr.size.tableTitleHeight
|
||||||
|
|
||||||
|
this.scrollTimer = setInterval(() => {
|
||||||
|
const top = rowHeight * senior.scrollCfg.row
|
||||||
|
const dom = document.getElementById(this.chartId)
|
||||||
|
if ((dom.offsetHeight - headerHeight + this.scrollTop) < rowHeight * this.chart.data.tableRow.length) {
|
||||||
|
this.scrollTop += top
|
||||||
|
} else {
|
||||||
|
this.scrollTop = 0
|
||||||
|
}
|
||||||
|
this.myChart.store.set('scrollY', this.scrollTop)
|
||||||
|
this.myChart.render()
|
||||||
|
}, senior.scrollCfg.interval)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
116
frontend/src/views/chart/components/senior/ScrollCfg.vue
Normal file
116
frontend/src/views/chart/components/senior/ScrollCfg.vue
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
<template>
|
||||||
|
<div style="width: 100%;display: block;">
|
||||||
|
<el-row class="scroll-style">
|
||||||
|
<el-form ref="scrollForm" :model="scrollForm" label-width="80px" size="mini">
|
||||||
|
<el-form-item :label="$t('chart.scroll')" class="form-item">
|
||||||
|
<el-checkbox v-model="scrollForm.open" @change="changeScrollCfg">{{ $t('chart.open') }}</el-checkbox>
|
||||||
|
<el-tooltip class="item" effect="dark" placement="bottom">
|
||||||
|
<div slot="content">
|
||||||
|
明细表仅在分页模式为"下拉"时生效。
|
||||||
|
</div>
|
||||||
|
<i class="el-icon-info" style="cursor: pointer;color: gray;font-size: 12px;" />
|
||||||
|
</el-tooltip>
|
||||||
|
</el-form-item>
|
||||||
|
<span v-show="scrollForm.open">
|
||||||
|
<el-form-item :label="$t('chart.row')" class="form-item">
|
||||||
|
<el-input-number v-model="scrollForm.row" :min="1" :max="1000" :precision="0" size="mini" @change="changeScrollCfg" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item :label="$t('chart.interval') + '(ms)'" class="form-item">
|
||||||
|
<el-input-number v-model="scrollForm.interval" :min="500" :step="1000" :precision="0" size="mini" @change="changeScrollCfg" />
|
||||||
|
</el-form-item>
|
||||||
|
</span>
|
||||||
|
</el-form>
|
||||||
|
</el-row>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { DEFAULT_SCROLL } from '@/views/chart/chart/chart'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'ScrollCfg',
|
||||||
|
props: {
|
||||||
|
chart: {
|
||||||
|
type: Object,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
scrollForm: JSON.parse(JSON.stringify(DEFAULT_SCROLL))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
'chart': {
|
||||||
|
handler: function() {
|
||||||
|
this.initData()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.initData()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
initData() {
|
||||||
|
const chart = JSON.parse(JSON.stringify(this.chart))
|
||||||
|
if (chart.senior) {
|
||||||
|
let senior = null
|
||||||
|
if (Object.prototype.toString.call(chart.senior) === '[object Object]') {
|
||||||
|
senior = JSON.parse(JSON.stringify(chart.senior))
|
||||||
|
} else {
|
||||||
|
senior = JSON.parse(chart.senior)
|
||||||
|
}
|
||||||
|
if (senior.scrollCfg) {
|
||||||
|
this.scrollForm = senior.scrollCfg
|
||||||
|
} else {
|
||||||
|
this.scrollForm = JSON.parse(JSON.stringify(DEFAULT_SCROLL))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
changeScrollCfg() {
|
||||||
|
this.$emit('onScrollCfgChange', this.scrollForm)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.shape-item{
|
||||||
|
padding: 6px;
|
||||||
|
border: none;
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
.form-item-slider>>>.el-form-item__label{
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 38px;
|
||||||
|
}
|
||||||
|
.form-item>>>.el-form-item__label{
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
.el-select-dropdown__item{
|
||||||
|
padding: 0 20px;
|
||||||
|
}
|
||||||
|
span{
|
||||||
|
font-size: 12px
|
||||||
|
}
|
||||||
|
.el-form-item{
|
||||||
|
margin-bottom: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.switch-style{
|
||||||
|
position: absolute;
|
||||||
|
right: 10px;
|
||||||
|
margin-top: -4px;
|
||||||
|
}
|
||||||
|
.color-picker-style{
|
||||||
|
cursor: pointer;
|
||||||
|
z-index: 1003;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scroll-style >>> .el-input-number--mini {
|
||||||
|
width: 120px !important;
|
||||||
|
}
|
||||||
|
</style>
|
@ -119,7 +119,9 @@ export default {
|
|||||||
show: 0
|
show: 0
|
||||||
},
|
},
|
||||||
showPage: false,
|
showPage: false,
|
||||||
columnWidth: DEFAULT_SIZE.tableColumnWidth
|
columnWidth: DEFAULT_SIZE.tableColumnWidth,
|
||||||
|
scrollTimer: null,
|
||||||
|
scrollTop: 0
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@ -143,6 +145,9 @@ export default {
|
|||||||
this.chartResize()
|
this.chartResize()
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
beforeDestroy() {
|
||||||
|
clearInterval(this.scrollTimer)
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
init() {
|
init() {
|
||||||
this.resetHeight()
|
this.resetHeight()
|
||||||
@ -224,6 +229,10 @@ export default {
|
|||||||
} else {
|
} else {
|
||||||
this.height = 'auto'
|
this.height = 'auto'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.initScroll()
|
||||||
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
@ -355,6 +364,42 @@ export default {
|
|||||||
pageSize: 20,
|
pageSize: 20,
|
||||||
show: 0
|
show: 0
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
initScroll() {
|
||||||
|
clearInterval(this.scrollTimer)
|
||||||
|
// 首先回到最顶部,然后计算行高*行数作为top,最后判断:如果top<数据量*行高,继续滚动,否则回到顶部
|
||||||
|
const customAttr = JSON.parse(this.chart.customAttr)
|
||||||
|
const senior = JSON.parse(this.chart.senior)
|
||||||
|
|
||||||
|
const scrollContainer = document.getElementsByClassName(this.chart.id)[0].getElementsByClassName('elx-table--body-wrapper')[0]
|
||||||
|
|
||||||
|
this.scrollTop = 0
|
||||||
|
setTimeout(() => {
|
||||||
|
scrollContainer.scrollTo({
|
||||||
|
top: this.scrollTop,
|
||||||
|
behavior: this.scrollTop === 0 ? 'instant' : 'smooth'
|
||||||
|
})
|
||||||
|
}, 0)
|
||||||
|
|
||||||
|
if (senior.scrollCfg.open && (this.chart.type === 'table-normal' || (this.chart.type === 'table-info' && !this.showPage))) {
|
||||||
|
let rowHeight = customAttr.size.tableItemHeight
|
||||||
|
if (rowHeight < 36) {
|
||||||
|
rowHeight = 36
|
||||||
|
}
|
||||||
|
this.scrollTimer = setInterval(() => {
|
||||||
|
const top = rowHeight * senior.scrollCfg.row
|
||||||
|
if (scrollContainer.clientHeight + scrollContainer.scrollTop < scrollContainer.scrollHeight) {
|
||||||
|
this.scrollTop += top
|
||||||
|
} else {
|
||||||
|
this.scrollTop = 0
|
||||||
|
}
|
||||||
|
scrollContainer.scrollTo({
|
||||||
|
top: this.scrollTop,
|
||||||
|
behavior: this.scrollTop === 0 ? 'instant' : 'smooth'
|
||||||
|
})
|
||||||
|
}, senior.scrollCfg.interval)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -32,8 +32,8 @@
|
|||||||
</span>
|
</span>
|
||||||
</el-row>
|
</el-row>
|
||||||
<el-row class="view-panel-row">
|
<el-row class="view-panel-row">
|
||||||
<el-tabs :stretch="true" class="tab-header">
|
<el-tabs v-model="tabActive" :stretch="true" class="tab-header">
|
||||||
<el-tab-pane :label="$t('chart.chart_data')" class="padding-tab" style="width: 350px">
|
<el-tab-pane name="data" :label="$t('chart.chart_data')" class="padding-tab" style="width: 350px">
|
||||||
<div v-if="view.dataFrom==='template'" class="view-panel-Mask">
|
<div v-if="view.dataFrom==='template'" class="view-panel-Mask">
|
||||||
<span style="opacity: 1;">
|
<span style="opacity: 1;">
|
||||||
<el-button
|
<el-button
|
||||||
@ -95,7 +95,7 @@
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-if="fieldShow" class="field-split">
|
<div v-if="fieldShow && tabActive === 'data'" class="field-split">
|
||||||
<fu-split-pane top="50%" direction="vertical">
|
<fu-split-pane top="50%" direction="vertical">
|
||||||
<template v-slot:top>
|
<template v-slot:top>
|
||||||
<div class="padding-lr field-height">
|
<div class="padding-lr field-height">
|
||||||
@ -669,7 +669,7 @@
|
|||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
<el-tab-pane :label="$t('chart.chart_style')" class="padding-tab" style="width: 350px">
|
<el-tab-pane name="style" :label="$t('chart.chart_style')" class="padding-tab" style="width: 350px">
|
||||||
<chart-style
|
<chart-style
|
||||||
v-if="chartProperties || view.isPlugin"
|
v-if="chartProperties || view.isPlugin"
|
||||||
:param="param"
|
:param="param"
|
||||||
@ -694,19 +694,19 @@
|
|||||||
@onChangeBackgroundForm="onChangeBackgroundForm"
|
@onChangeBackgroundForm="onChangeBackgroundForm"
|
||||||
/>
|
/>
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
<el-tab-pane :label="$t('chart.senior')" class="padding-tab" style="width: 350px;">
|
<el-tab-pane name="senior" :label="$t('chart.senior')" class="padding-tab" style="width: 350px;">
|
||||||
<el-row class="view-panel">
|
<el-row class="view-panel">
|
||||||
<div
|
<div
|
||||||
v-if="view.type && (view.type.includes('bar') || view.type.includes('line') || view.type.includes('mix') || view.type.includes('gauge')) || view.type === 'text'"
|
v-if="view.type && (view.type.includes('bar') || view.type.includes('line') || view.type.includes('mix') || view.type.includes('gauge')) || view.type === 'text' || view.type === 'table-normal' || view.type === 'table-info'"
|
||||||
style="overflow:auto;border-right: 1px solid #e6e6e6;height: 100%;width: 100%;"
|
style="overflow:auto;border-right: 1px solid #e6e6e6;height: 100%;width: 100%;"
|
||||||
class="attr-style theme-border-class"
|
class="attr-style theme-border-class"
|
||||||
>
|
>
|
||||||
<el-row
|
<el-row
|
||||||
v-if="view.type && (view.type.includes('bar') || view.type.includes('line') || view.type.includes('mix'))"
|
v-if="view.type && (view.type.includes('bar') || view.type.includes('line') || view.type.includes('mix') || view.type.includes('table'))"
|
||||||
>
|
>
|
||||||
<span class="padding-lr">{{ $t('chart.senior_cfg') }}</span>
|
<span class="padding-lr">{{ $t('chart.senior_cfg') }}</span>
|
||||||
<el-collapse v-model="attrActiveNames" class="style-collapse">
|
<el-collapse v-model="attrActiveNames" class="style-collapse">
|
||||||
<el-collapse-item name="function" :title="$t('chart.function_cfg')">
|
<el-collapse-item v-if="view.type && (view.type.includes('bar') || view.type.includes('line') || view.type.includes('mix'))" name="function" :title="$t('chart.function_cfg')">
|
||||||
<function-cfg
|
<function-cfg
|
||||||
:param="param"
|
:param="param"
|
||||||
class="attr-selector"
|
class="attr-selector"
|
||||||
@ -714,6 +714,14 @@
|
|||||||
@onFunctionCfgChange="onFunctionCfgChange"
|
@onFunctionCfgChange="onFunctionCfgChange"
|
||||||
/>
|
/>
|
||||||
</el-collapse-item>
|
</el-collapse-item>
|
||||||
|
<el-collapse-item v-if="false && view.type && (view.type.includes('table'))" name="scroll" :title="$t('chart.scroll_cfg')">
|
||||||
|
<scroll-cfg
|
||||||
|
:param="param"
|
||||||
|
class="attr-selector"
|
||||||
|
:chart="chart"
|
||||||
|
@onScrollCfgChange="onScrollChange"
|
||||||
|
/>
|
||||||
|
</el-collapse-item>
|
||||||
</el-collapse>
|
</el-collapse>
|
||||||
</el-row>
|
</el-row>
|
||||||
<el-row
|
<el-row
|
||||||
@ -1077,12 +1085,14 @@ import { pluginTypes } from '@/api/chart/chart'
|
|||||||
import ValueFormatterEdit from '@/views/chart/components/value-formatter/ValueFormatterEdit'
|
import ValueFormatterEdit from '@/views/chart/components/value-formatter/ValueFormatterEdit'
|
||||||
import ChartStyle from '@/views/chart/view/ChartStyle'
|
import ChartStyle from '@/views/chart/view/ChartStyle'
|
||||||
import CustomSortEdit from '@/views/chart/components/compare/CustomSortEdit'
|
import CustomSortEdit from '@/views/chart/components/compare/CustomSortEdit'
|
||||||
|
import ScrollCfg from '@/views/chart/components/senior/ScrollCfg'
|
||||||
import ChartFieldEdit from '@/views/chart/view/ChartFieldEdit'
|
import ChartFieldEdit from '@/views/chart/view/ChartFieldEdit'
|
||||||
import CalcChartFieldEdit from '@/views/chart/view/CalcChartFieldEdit'
|
import CalcChartFieldEdit from '@/views/chart/view/CalcChartFieldEdit'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'ChartEdit',
|
name: 'ChartEdit',
|
||||||
components: {
|
components: {
|
||||||
|
ScrollCfg,
|
||||||
CalcChartFieldEdit,
|
CalcChartFieldEdit,
|
||||||
ChartFieldEdit,
|
ChartFieldEdit,
|
||||||
CustomSortEdit,
|
CustomSortEdit,
|
||||||
@ -1231,7 +1241,8 @@ export default {
|
|||||||
showEditChartField: false,
|
showEditChartField: false,
|
||||||
currEditField: {},
|
currEditField: {},
|
||||||
editChartCalcField: false,
|
editChartCalcField: false,
|
||||||
fieldShow: false
|
fieldShow: false,
|
||||||
|
tabActive: 'data'
|
||||||
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -1953,6 +1964,11 @@ export default {
|
|||||||
this.calcStyle()
|
this.calcStyle()
|
||||||
},
|
},
|
||||||
|
|
||||||
|
onScrollChange(val) {
|
||||||
|
this.view.senior.scrollCfg = val
|
||||||
|
this.calcStyle()
|
||||||
|
},
|
||||||
|
|
||||||
showDimensionEditFilter(item) {
|
showDimensionEditFilter(item) {
|
||||||
this.dimensionItem = JSON.parse(JSON.stringify(item))
|
this.dimensionItem = JSON.parse(JSON.stringify(item))
|
||||||
this.dimensionFilterEdit = true
|
this.dimensionFilterEdit = true
|
||||||
@ -2695,6 +2711,7 @@ export default {
|
|||||||
.drag-list {
|
.drag-list {
|
||||||
height: calc(100% - 26px);
|
height: calc(100% - 26px);
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
|
padding: 2px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.item-dimension {
|
.item-dimension {
|
||||||
@ -3062,4 +3079,12 @@ span {
|
|||||||
height: calc(100% - 40px);
|
height: calc(100% - 40px);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.field-split >>> .fu-split-pane__left{
|
||||||
|
padding-right: 0!important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.field-split >>> .fu-split-pane__right{
|
||||||
|
padding-left: 0!important;
|
||||||
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
Loading…
Reference in New Issue
Block a user