动态table高度

This commit is contained in:
仲么了
2024-01-04 10:38:41 +08:00
parent 2bb7a82778
commit d4ee8e7821
5 changed files with 147 additions and 99 deletions

View File

@@ -1,48 +1,54 @@
<template> <template>
<!-- 通用搜索 --> <div ref="tableHeader">
<transition name='el-zoom-in-bottom' mode='out-in' v-if='$slots.select'> <!-- 通用搜索 -->
<div class='table-com-search' v-if='showSelect'> <transition name="el-zoom-in-bottom" mode="out-in" v-if="$slots.select">
<el-form @submit.prevent='' @keyup.enter='onComSearch' label-position='left' :inline='true'> <div class="table-com-search" v-if="showSelect">
<slot name='select'></slot> <el-form @submit.prevent="" @keyup.enter="onComSearch" label-position="left" :inline="true">
<el-form-item label='日期' v-if='datePicker'> <slot name="select"></slot>
<DatePicker v-model='date' @change='dateChange'></DatePicker> <el-form-item label="日期" v-if="datePicker">
</el-form-item> <DatePicker v-model="date" @change="dateChange"></DatePicker>
<el-form-item> </el-form-item>
<el-button @click='onComSearch' type='primary'>查询</el-button> <el-form-item>
<el-button @click='onResetForm'>重置</el-button> <el-button @click="onComSearch" type="primary">查询</el-button>
</el-form-item> <el-button @click="onResetForm">重置</el-button>
</el-form> </el-form-item>
</div> </el-form>
</transition> </div>
</transition>
<div class='table-header ba-scroll-style' v-if='showOperation'> <div class="table-header ba-scroll-style" v-if="showOperation">
<slot name='operation'></slot> <slot name="operation"></slot>
<!-- 右侧搜索框和工具按钮 --> <!-- 右侧搜索框和工具按钮 -->
<div class='table-search' > <div class="table-search">
<slot name='right'></slot> <slot name="right"></slot>
<div class='table-search-button-group' v-if='$slots.select'> <div class="table-search-button-group" v-if="$slots.select">
<el-button class='table-search-button-item' color='#dcdfe6' plain @click='showSelectChange'> <el-button class="table-search-button-item" color="#dcdfe6" plain @click="showSelectChange">
<Icon size='14' name='el-icon-Search' /> <Icon size="14" name="el-icon-Search" />
</el-button> </el-button>
</div>
</div> </div>
</div> </div>
</div> </div>
</template> </template>
<script setup lang='ts'> <script setup lang="ts">
import { inject, ref } from 'vue' import { inject, ref, onMounted, nextTick, onUnmounted } from 'vue'
import type TableStore from '@/utils/tableStore' import type TableStore from '@/utils/tableStore'
import DatePicker from '@/components/form/datePicker/index.vue' import DatePicker from '@/components/form/datePicker/index.vue'
import { mainHeight } from '@/utils/layout'
const tableStore = inject('tableStore') as TableStore const tableStore = inject('tableStore') as TableStore
const date = ref([window.XEUtils.toDateString(new Date(), 'yyyy-MM-dd'), window.XEUtils.toDateString(new Date(), 'yyyy-MM-dd')]) const tableHeader = ref()
const date = ref([
window.XEUtils.toDateString(new Date(), 'yyyy-MM-dd'),
window.XEUtils.toDateString(new Date(), 'yyyy-MM-dd')
])
interface Props { interface Props {
// 默认展开 // 默认展开
showSelect?: boolean showSelect?: boolean
showOperation?: boolean // 是否显示operation showOperation?: boolean // 是否显示operation
datePicker?: boolean datePicker?: boolean
} }
const props = withDefaults(defineProps<Props>(), { const props = withDefaults(defineProps<Props>(), {
@@ -54,9 +60,30 @@ if (props.datePicker) {
tableStore.table.params.searchBeginTime = date.value[0] tableStore.table.params.searchBeginTime = date.value[0]
tableStore.table.params.searchEndTime = date.value[1] tableStore.table.params.searchEndTime = date.value[1]
} }
// 动态计算table高度
const resizeObserver = new ResizeObserver(entries => {
for (const entry of entries) {
handlerHeight()
}
})
onMounted(() => {
resizeObserver.observe(tableHeader.value)
})
onUnmounted(() => {
resizeObserver.disconnect()
})
const handlerHeight = () => {
tableStore.table.height = mainHeight(
tableStore.table.publicHeight + tableHeader.value.offsetHeight + (tableStore.showPage ? 58 : 0) + 20
).height as string
}
const showSelect = ref(props.showSelect) const showSelect = ref(props.showSelect)
const showSelectChange = () => { const showSelectChange = () => {
showSelect.value = !showSelect.value showSelect.value = !showSelect.value
nextTick(() => {
handlerHeight()
})
} }
const onComSearch = () => { const onComSearch = () => {
tableStore.onTableAction('search', {}) tableStore.onTableAction('search', {})
@@ -70,7 +97,7 @@ const dateChange = () => {
} }
</script> </script>
<style scoped lang='scss'> <style scoped lang="scss">
.table-header { .table-header {
position: relative; position: relative;
overflow-x: auto; overflow-x: auto;

View File

@@ -1,78 +1,93 @@
<template> <template>
<vxe-table <div :style="{ height: tableStore.table.height }">
ref='tableRef' <vxe-table
:data='tableStore.table.data' ref="tableRef"
v-loading='tableStore.table.loading' height="auto"
v-bind='Object.assign({}, defaultAttribute, $attrs)' :data="tableStore.table.data"
> v-loading="tableStore.table.loading"
<!-- Column 组件内部是 el-table-column --> v-bind="Object.assign({}, defaultAttribute, $attrs)"
<template v-if='isGroup'> >
<vxe-table-colgroup <!-- Column 组件内部是 el-table-column -->
v-if='isGroup' <template v-if="isGroup">
v-for='(item, index) in tableStore.table.column' <vxe-table-colgroup
:field='item.field' v-if="isGroup"
:title='item.title' v-for="(item, index) in tableStore.table.column"
:key='index' :field="item.field"
:min-width='item.width' :title="item.title"
show-overflow :key="index"
align='center' :min-width="item.width"
> show-overflow
align="center"
>
<Column
:attr="child"
:key="key + '-column'"
v-for="(child, key) in item.children"
:tree-node="child.treeNode"
>
<!-- tableStore 预设的列 render 方案 -->
<template v-if="child.render" #default="scope">
<FieldRender
:field="child"
:row="scope.row"
:column="scope.column"
:index="scope.rowIndex"
:key="
key +
'-' +
child.render +
'-' +
(child.field ? '-' + child.field + '-' + scope.row[child.field] : '')
"
/>
</template>
</Column>
</vxe-table-colgroup>
</template>
<template v-else>
<Column <Column
:attr='child' :attr="item"
:key="key + '-column'" :key="key + '-column'"
v-for='(child, key) in item.children' v-for="(item, key) in tableStore.table.column"
:tree-node='child.treeNode' :tree-node="item.treeNode"
> >
<!-- tableStore 预设的列 render 方案 --> <!-- tableStore 预设的列 render 方案 -->
<template v-if='child.render' #default='scope'> <template v-if="item.render" #default="scope">
<FieldRender <FieldRender
:field='child' :field="item"
:row='scope.row' :row="scope.row"
:column='scope.column' :column="scope.column"
:index='scope.rowIndex' :index="scope.rowIndex"
:key=" key + '-' + child.render + '-' + (child.field ? '-' + child.field + '-' + scope.row[child.field] : '')" :key="
key +
'-' +
item.render +
'-' +
(item.field ? '-' + item.field + '-' + scope.row[item.field] : '')
"
/> />
</template> </template>
</Column> </Column>
</vxe-table-colgroup> </template>
</template> </vxe-table>
<template v-else> </div>
<Column
:attr='item'
:key="key + '-column'"
v-for='(item, key) in tableStore.table.column'
:tree-node='item.treeNode'
>
<!-- tableStore 预设的列 render 方案 -->
<template v-if='item.render' #default='scope'>
<FieldRender
:field='item'
:row='scope.row'
:column='scope.column'
:index='scope.rowIndex'
:key=" key + '-' +item.render +'-' +(item.field ? '-' + item.field + '-' + scope.row[item.field] : '')" />
</template>
</Column>
</template> <div v-if="tableStore.showPage" class="table-pagination">
</vxe-table>
<div v-if='props.pagination' class='table-pagination'>
<el-pagination <el-pagination
:currentPage='tableStore.table.params!.pageNum' :currentPage="tableStore.table.params!.pageNum"
:page-size='tableStore.table.params!.pageSize' :page-size="tableStore.table.params!.pageSize"
:page-sizes='pageSizes' :page-sizes="pageSizes"
background background
:layout="config.layout.shrink ? 'prev, next, jumper' : 'sizes,total, ->, prev, pager, next, jumper'" :layout="config.layout.shrink ? 'prev, next, jumper' : 'sizes,total, ->, prev, pager, next, jumper'"
:total='tableStore.table.total' :total="tableStore.table.total"
@size-change='onTableSizeChange' @size-change="onTableSizeChange"
@current-change='onTableCurrentChange' @current-change="onTableCurrentChange"
></el-pagination> ></el-pagination>
</div> </div>
<slot name='footer'></slot> <slot name="footer"></slot>
</template> </template>
<script setup lang='ts'> <script setup lang="ts">
import { ref, nextTick, inject, computed } from 'vue' import { ref, nextTick, inject, computed } from 'vue'
import type { ElTable, TableInstance } from 'element-plus' import type { ElTable, TableInstance } from 'element-plus'
import FieldRender from '@/components/table/fieldRender/index.vue' import FieldRender from '@/components/table/fieldRender/index.vue'
@@ -86,12 +101,10 @@ const tableRef = ref<TableInstance>()
const tableStore = inject('tableStore') as TableStoreClass const tableStore = inject('tableStore') as TableStoreClass
interface Props extends /* @vue-ignore */ Partial<InstanceType<typeof ElTable>> { interface Props extends /* @vue-ignore */ Partial<InstanceType<typeof ElTable>> {
pagination?: boolean
isGroup?: boolean isGroup?: boolean
} }
const props = withDefaults(defineProps<Props>(), { const props = withDefaults(defineProps<Props>(), {
pagination: true,
isGroup: false isGroup: false
}) })
console.log(props) console.log(props)
@@ -113,7 +126,6 @@ const pageSizes = computed(() => {
return defaultSizes return defaultSizes
}) })
/* /*
* 记录选择的项 * 记录选择的项
*/ */
@@ -130,7 +142,7 @@ defineExpose({
}) })
</script> </script>
<style scoped lang='scss'> <style scoped lang="scss">
.ba-data-table :deep(.el-button + .el-button) { .ba-data-table :deep(.el-button + .el-button) {
margin-left: 6px; margin-left: 6px;
} }

View File

@@ -2,7 +2,7 @@ import { reactive } from 'vue'
import createAxios from '@/utils/request' import createAxios from '@/utils/request'
import { requestPayload } from '@/utils/request' import { requestPayload } from '@/utils/request'
import { Method } from 'axios' import { Method } from 'axios'
import { mainHeight } from '@/utils/layout'
interface TableStoreParams { interface TableStoreParams {
url: string url: string
pk?: string pk?: string
@@ -10,6 +10,8 @@ interface TableStoreParams {
params?: anyObj params?: anyObj
method?: Method method?: Method
isWebPaging?: boolean // 是否前端分页 isWebPaging?: boolean // 是否前端分页
showPage?: boolean
publicHeight?: number
resetCallback?: () => void resetCallback?: () => void
loadCallback?: () => void loadCallback?: () => void
} }
@@ -20,6 +22,7 @@ export default class TableStore {
public method: Method public method: Method
public initData: any = null public initData: any = null
public isWebPaging = false public isWebPaging = false
public showPage = true
public table: CnTable = reactive({ public table: CnTable = reactive({
ref: null, ref: null,
selection: [], selection: [],
@@ -33,7 +36,9 @@ export default class TableStore {
loading: true, loading: true,
column: [], column: [],
loadCallback: null, loadCallback: null,
resetCallback: null resetCallback: null,
height: mainHeight(20 + (this.showPage ? 58 : 0)).height as string,
publicHeight: 0
}) })
constructor(public options: TableStoreParams) { constructor(public options: TableStoreParams) {
@@ -42,6 +47,8 @@ export default class TableStore {
this.isWebPaging = options.isWebPaging || false this.isWebPaging = options.isWebPaging || false
this.method = options.method || 'GET' this.method = options.method || 'GET'
this.table.column = options.column this.table.column = options.column
this.showPage = options.showPage || true
this.table.publicHeight = options.publicHeight || 0
this.table.resetCallback = options.resetCallback || null this.table.resetCallback = options.resetCallback || null
this.table.loadCallback = options.loadCallback || null this.table.loadCallback = options.loadCallback || null
Object.assign(this.table.params, options.params) Object.assign(this.table.params, options.params)

View File

@@ -145,7 +145,7 @@ const tableStore = new TableStore({
fontSize: 14 fontSize: 14
}, },
backgroundColor: 'rgba(0,0,0,0.35)', backgroundColor: 'rgba(0,0,0,0.35)',
formatter: function (params) { formatter: function (params: any) {
var tips = '' var tips = ''
tips += params[0].name + '</br/>' tips += params[0].name + '</br/>'
for (var i = 0; i < params.length; i++) { for (var i = 0; i < params.length; i++) {
@@ -165,7 +165,7 @@ const tableStore = new TableStore({
data: tableStore.table.data.area.areaInfo.map((item: any) => item.normalRate), data: tableStore.table.data.area.areaInfo.map((item: any) => item.normalRate),
itemStyle: { itemStyle: {
normal: { normal: {
color: function (params) { color: function (params: any) {
if (params.value != 3.14159) { if (params.value != 3.14159) {
return new echarts.graphic.LinearGradient(0, 1, 0, 0, [ return new echarts.graphic.LinearGradient(0, 1, 0, 0, [
{ {
@@ -193,7 +193,7 @@ const tableStore = new TableStore({
type: 'bar', type: 'bar',
itemStyle: { itemStyle: {
normal: { normal: {
color: function (params) { color: function (params: any) {
if (params.value != 3.14159) { if (params.value != 3.14159) {
return new echarts.graphic.LinearGradient(0, 1, 0, 0, [ return new echarts.graphic.LinearGradient(0, 1, 0, 0, [
{ {
@@ -219,7 +219,7 @@ const tableStore = new TableStore({
data: tableStore.table.data.area.areaInfo.map((item: any) => item.onlineRate), data: tableStore.table.data.area.areaInfo.map((item: any) => item.onlineRate),
itemStyle: { itemStyle: {
normal: { normal: {
color: function (params) { color: function (params: any) {
if (params.value >= 90) { if (params.value >= 90) {
return new echarts.graphic.LinearGradient(0, 1, 0, 0, [ return new echarts.graphic.LinearGradient(0, 1, 0, 0, [
{ {

6
types/table.d.ts vendored
View File

@@ -23,8 +23,10 @@ declare global {
pageSize: number pageSize: number
[key: string]: any [key: string]: any
} }
loadCallback: (() => void )| null loadCallback: (() => void) | null
resetCallback: (() => void)| null resetCallback: (() => void) | null
height: string
publicHeight: number
} }
/* 表格行 */ /* 表格行 */