使用:
<cqsb-table
:loading="loading"
:data="vesselSchedulesDatas"
:columns="vesselSchedulesColumns"
/>
组件:
<script>
import CqsbPagination from 'components/CqsbPagination.vue'
import { dom } from 'quasar'
import {decryptData} from "boot/encryAndDecrypt";
const {/* ready,*/ width, css } = dom
function headerFixed (el, bind, vnode ) {
if (!vnode.context.fixedHeight) return
vnode.context.$nextTick(() => {
const style = {
position: 'sticky',
top: '0',
'z-index': '1'
}
const topArea = el.querySelector('.q-table__top')
const tHeader = el.querySelector('.q-table__middle thead')
if (topArea) {
css(topArea, style)
}
if (tHeader) {
css(tHeader, style)
}
/**
* 表格的最大高度 = 视口高度 - 页头的高度 - 表格的上下填充
* 使其达到最佳视觉: 中间表格最高占满剩余高度
* */
const header = document.querySelector('header.q-header')
// const publicAreas = document.querySelector('div.__public__areas')
const pagination = document.querySelector('div.mark_pagination')
if (header) {
// console.log(header.getBoundingClientRect())
// console.log(getComputedStyle(el.parentNode))
const { paddingBottom, paddingTop } = getComputedStyle(el.parentNode)
const py = parseInt(paddingTop) + parseInt(paddingBottom)
el.style.maxHeight = `calc(100vh - ${header.offsetHeight + (pagination?.offsetHeight || 0) + py + 16}px)`
}
})
}
function columnFixed (el, bind, vnode) {
vnode.context.$nextTick(() => {
const { left, right } = bind.value
const table = el.querySelector('.cqsb_table')
table.style.position = 'relative'
const thead = el.querySelector('thead tr')
const tbody = el.querySelectorAll('tbody tr')
const style = {
position: 'sticky'
}
const shadow = document.createElement('div')
const shadowStyle = {
width: '1px',
height: '100%',
'z-index': '1',
position: 'sticky'
}
if (left) {
let leftOffset = 0
for (let i = 0; i < left; i++) {
const w = width(thead.children[i])
style.left = `${leftOffset}px`
css(thead.children[i], style)
tbody.forEach(tr => css(tr.children[i], style))
leftOffset += w
}
}
if (right) {
let rightOffset = 0
for (let i = 0; i < right; i++) {
const len = thead.children.length - 1 - i
const w = width(thead.children[i])
style.right = `${rightOffset}px`
css(thead.children[len], style)
tbody.forEach(tr => css(tr.children[len], style))
rightOffset += w
}
if (!table.querySelector('div[style*="right"]')) {
shadowStyle.right = rightOffset + 'px'
shadowStyle.top = '0px'
css(shadow, shadowStyle)
table.appendChild(shadow)
}
}
})
}
export default {
name: 'CqsbTable',
components: { CqsbPagination },
props: {
colFixed: {
type: Object,
default: () => ({ right: 1 })
},
data: {
type: Array,
default: () => []
},
columns: {
type: Array,
default: () => []
},
hidePage: {
type: Boolean,
default: false
},
fixedHeight: {
type: Boolean,
default: true
}
},
data () {
return {
page: {
pageNum: 1,
pageSize: 20
},
selectedIndex: null, // 用于追踪选中的行索引
}
},
computed: {
tableData () {
const { pageNum, pageSize } = this.page
let start = (pageNum - 1) * pageSize
if (start >= this.data.length) start = 0
let end = pageNum * pageSize
if (end >= this.data.length) end = this.data.length
return this.data.slice(start, end)
},
pages () {
return Math.ceil(this.data.length / this.page.pageSize)
},
total () {
return this.data.length
}
},
methods: {
pageChange ({ pageNum, pageSize }) {
this.page.pageNum = pageNum
this.page.pageSize = pageSize
},
handleRowClick(evt, row, index){
// 如果之前的选中索引不为null,且对应的元素存在,则移除其背景色
if (this.selectedIndex !== null && this.$el.querySelector(`.cqsb_table tbody tr:nth-child(${this.selectedIndex + 1})`)) {
const previousRow = this.$el.querySelector(`.cqsb_table tbody tr:nth-child(${this.selectedIndex + 1})`);
previousRow.classList.remove('bg-amber-2'); // 假设'bg-amber-2'是应用于整个行的背景色类
}
// 更新选中索引并给新的行添加背景色
this.selectedIndex = index;
const newRow = this.$el.querySelector(`.cqsb_table tbody tr:nth-child(${index + 1})`);
if (newRow) {
newRow.classList.add('bg-amber-2'); // 直接给整个<tr>添加背景色类
}
}
},
directives: {
/* rowSelected (el, _, vnode) {
vnode.context.$nextTick(() => {
/!* const tbody = el.querySelector('.cqsb_table tbody')
let rowIndex = -1
const rowBgClass = 'bg-amber-2'
for (let i = 0; i < tbody.children.length; i++) {
updateLastCellStyles()
function updateLastCellStyles() {
for (let i = 0; i < tbody.children.length; i++) {
const tds = tbody.children[i].children
const lastTd = tds[tds.length-1]
if (i === rowIndex) {
lastTd.classList.remove('bg-white')
lastTd.classList.add(rowBgClass)
} else {
lastTd.classList.remove(rowBgClass)
lastTd.classList.add('bg-white')
}
}
}
tbody.children[i].addEventListener('click', () => {
if (rowIndex !== -1) {
tbody.children[rowIndex].classList.remove(rowBgClass)
}
tbody.children[i].classList.add(rowBgClass)
rowIndex = i
updateLastCellStyles()
})
}*!/
const tbody = el.querySelector('.cqsb_table tbody')
const rowBgClass = 'bg-amber-2'
let selectedRow = null
function updateRowStyles(row, isSelected) {
row.classList.toggle(rowBgClass, isSelected)
const lastCell = row.lastElementChild
// lastCell.classList.toggle('bg-white', !isSelected)
lastCell.classList.toggle(rowBgClass, isSelected)
}
function handleRowClick(event) {
const clickedRow = event.currentTarget
if (selectedRow) {
updateRowStyles(selectedRow, false)
}
updateRowStyles(clickedRow, true)
selectedRow = clickedRow
}
Array.from(tbody.children).forEach(row => {
updateRowStyles(row, false)
row.addEventListener('click', handleRowClick)
})
})
},*/
columnFixed,
headerFixed
},
created() {
const encryPageSize = localStorage.getItem('pageSize')
if(encryPageSize !== null){
this.page.pageSize = decryptData(encryPageSize)
}
},
}
</script>
<template>
<div>
<q-table
flat square
v-header-fixed
v-bind="$attrs"
hide-pagination
v-on="$listeners"
:data="tableData"
:columns="columns"
v-column-fixed="colFixed"
:pagination="{ rowsPerPage: 0 }"
table-class="cqsb_table"
@row-click="handleRowClick"
table-header-class="bg-grey-2"
>
<template
v-for="(_, slotName) in $scopedSlots"
#[slotName]="scope"
>
<slot :name="slotName" v-bind="scope"></slot>
</template>
</q-table>
<cqsb-pagination
v-if="!hidePage"
:max="pages"
:options="page"
:total="total"
@change="pageChange"
class="justify-end q-py-sm"
/>
</div>
</template>
<style scoped lang="scss">
</style>