Files
property-manager-side/wuye-manager-uniapp/uni_modules/uview-plus/components/u-table2/tableRow.vue

417 lines
13 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<style lang="scss" scoped>
.u-table-row {
display: flex;
flex-direction: row;
position: relative;
color: var(--up-content-color, #606266);
}
// 添加border样式支持
.u-table-border {
border-top: 1px solid var(--up-border-color, #ebeef5);
border-left: 1px solid var(--up-border-color, #ebeef5);
border-right: 1px solid var(--up-border-color, #ebeef5);
.u-table-cell {
border-right: 1px solid var(--up-border-color, #ebeef5);
}
.u-table-cell:last-child {
border-right: none;
}
}
.u-table-cell {
flex: 1;
display: flex;
flex-direction: row;
align-items: center;
min-width: 0;
box-sizing: border-box;
padding: 10px 1px;
font-size: 14px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
line-height: 1.1;
color: var(--up-content-color, #606266);
border-bottom: 1px solid var(--up-border-color, #ebeef5);
&.u-text-left {
justify-content: flex-start;
text-align: left;
}
&.u-text-center {
justify-content: center;
text-align: center;
}
&.u-text-right {
justify-content: flex-end;
text-align: right;
}
}
.u-table-cell_content {
width: 100%;
min-width: 0;
max-width: 100%;
flex: 1;
box-sizing: border-box;
display: block;
text-align: inherit;
}
.u-table-cell_text {
width: 100%;
min-width: 0;
max-width: 100%;
display: block;
box-sizing: border-box;
text-align: inherit;
}
.u-table-cell_content-overflow,
.u-table-cell_content-overflow .u-table-cell_text {
width: 100%;
min-width: 0;
max-width: 100%;
display: block;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.u-table-row-zebra {
background-color: var(--up-table2-zebra-bg-color, #fafafa);
}
.u-table-row-highlight {
background-color: var(--up-table2-highlight-bg-color, #f5f7fa);
}
.u-table-empty {
text-align: center;
padding: 20px;
color: var(--up-tips-color, #999);
}
// 隐藏被合并的单元格
.u-table-cell-hidden {
opacity: 0;
}
// 合并单元格样式
.u-table-cell-merged {
z-index: 1;
}
</style>
<template>
<view class="u-table-row u-table-row-child"
:class="[highlightCurrentRow && currentRow === row ? 'u-table-row-highlight' : '',
rowClassName ? rowClassName(row, rowIndex, context) : '',
stripe && rowIndex % 2 === 1 ? 'u-table-row-zebra' : ''
]" :style="[{height: rowHeight}, getRowStyle(row, rowIndex)]" @click="handleRowClick(row)">
<view v-for="(col, colIndex) in columns" :key="col.key"
class="u-table-cell"
:class="[col.align ? 'u-text-' + col.align : '',
cellClassName ? cellClassName(row, col, context) : '',
getFixedClass(col),
isOverflowTooltipEnabled(col) ? 'u-table-cell-overflow' : '',
getCellSpanClass(rowIndex, colIndex)
]"
:style="[cellStyleInner({row: row, column: col, rowIndex: rowIndex, columnIndex: colIndex, level: level}), getCellSpanStyle(rowIndex, colIndex)]">
<!-- 复选框列 -->
<view v-if="col.type === 'selection'">
<checkbox :checked="isSelected(row)"
@click.stop="$emit('toggleSelect', row)" />
</view>
<template v-else>
<!-- 在mainCol列显示展开图标 -->
<view v-if="col.key === computedMainCol && hasTree"
@click.stop="toggleExpand(row, level)" :style="{width: expandWidth}">
<view v-if="hasExpandableChildren(row)">
{{ isLazyLoading(row) ? '...' : (isExpanded(row) ? '▼' : '▶') }}
</view>
</view>
<view class="u-table-cell_content"
:class="{ 'u-table-cell_content-overflow': isOverflowTooltipEnabled(col) }">
<slot name="cellChild" :row="row" :column="col" :prow="parentRow"
:rowIndex="rowIndex" :columnIndex="colIndex" :level="level" :context="context">
<text class="u-table-cell_text" :class="{ 'u-line-1': isOverflowTooltipEnabled(col) }" :lines="isOverflowTooltipEnabled(col) ? 1 : undefined">
{{ row[col.key] }}
</text>
</slot>
</view>
</template>
</view>
</view>
<!-- 递归渲染更深层的子级 -->
<template v-if="isExpanded(row) && row[treeProps.children] && row[treeProps.children].length">
<template v-for="(rowChild, childIndex) in row[treeProps.children]" :key="rowChild[rowKey] || childIndex">
<table-row
:row="rowChild"
:rowIndex="childIndex"
:parent-row="row"
:columns="columns"
:tree-props="treeProps"
:row-key="rowKey"
:expanded-keys="expandedKeys"
:cell-style-inner="cellStyleInner"
:is-expanded="isExpanded"
:row-class-name="rowClassName"
:row-style="rowStyle"
:stripe="stripe"
:cell-class-name="cellClassName"
:get-fixed-class="getFixedClass"
:context="context"
:highlight-current-row="highlightCurrentRow"
:current-row="currentRow"
:handle-row-click="handleRowClick"
:toggle-expand="toggleExpand"
:level="level + 1"
:rowHeight="rowHeight"
:hasTree="hasTree"
:selectedRows="selectedRows"
:expandWidth="expandWidth"
:computed-main-col="computedMainCol"
:span-method="spanMethod"
:show-overflow-tooltip="showOverflowTooltip"
:has-expandable-children="hasExpandableChildren"
:is-lazy-loading="isLazyLoading"
@toggle-select="$emit('toggleSelect', $event)"
@row-click="$emit('rowClick', $event)"
@toggle-expand="$emit('toggleExpand', $event)"
>
<template v-slot:cellChild="scope">
<slot name="cellChild" :row="scope.row" :column="scope.column" :prow="scope.prow"
:rowIndex="scope.rowIndex" :columnIndex="scope.columnIndex" :level="level" :context="context">
<text class="u-table-cell_text" :class="{ 'u-line-1': isOverflowTooltipEnabled(scope.column) }" :lines="isOverflowTooltipEnabled(scope.column) ? 1 : undefined">
{{ scope.row[scope.column.key] }}
</text>
</slot>
</template>
</table-row>
</template>
</template>
</template>
<script>
export default {
name: 'tableRow',
props: {
row: {
type: Object,
required: true
},
rowIndex: {
type: Number,
required: true
},
parentRow: {
type: Object,
default: null
},
columns: {
type: Array,
required: true
},
treeProps: {
type: Object,
required: true
},
rowKey: {
type: String,
required: true
},
expandedKeys: {
type: Array,
required: true
},
cellStyleInner: {
type: Function,
required: true
},
isExpanded: {
type: Function,
required: true
},
rowClassName: {
type: Function,
default: null
},
rowStyle: {
type: [Object, Function],
default: () => ({})
},
stripe: {
type: Boolean,
default: false
},
cellClassName: {
type: Function,
default: null
},
getFixedClass: {
type: Function,
required: true
},
context: {
type: Object,
default: null
},
highlightCurrentRow: {
type: Boolean,
default: false
},
currentRow: {
type: Object,
default: null
},
handleRowClick: {
type: Function,
required: true
},
toggleExpand: {
type: Function,
required: true
},
level: {
type: Number,
required: true
},
// 添加computedMainCol属性
computedMainCol: {
type: String,
required: true
},
showOverflowTooltip: {
type: [Boolean, Object],
default: false
},
expandWidth: {
type: String,
required: true
},
hasTree: {
type: Boolean,
required: false
},
selectedRows: {
type: Array,
required: false
},
rowHeight: {
type: String,
required: true
},
// 添加spanMethod属性
spanMethod: {
type: Function,
default: null
},
hasExpandableChildren: {
type: Function,
required: true
},
isLazyLoading: {
type: Function,
required: true
}
},
emits: ['rowClick', 'toggleExpand', 'toggleSelect'],
methods: {
isSelected(row) {
return this.selectedRows.some(r => r[this.rowKey] === row[this.rowKey]);
},
isOverflowTooltipEnabled(column) {
if (column && column.type === 'selection') {
return false;
}
if (column && typeof column.showOverflowTooltip !== 'undefined') {
return !!column.showOverflowTooltip;
}
return !!this.showOverflowTooltip;
},
getRowStyle(row, rowIndex) {
if (typeof this.rowStyle === 'function') {
return this.rowStyle({
row,
rowIndex,
level: this.level,
parentRow: this.parentRow,
context: this.context
}) || {};
}
return this.rowStyle || {};
},
// 获取单元格的合并信息
getCellSpan(rowIndex, columnIndex) {
if (typeof this.spanMethod !== 'function') {
return { rowspan: 1, colspan: 1 };
}
const row = this.row;
const column = this.columns[columnIndex];
const result = this.spanMethod({
row,
column,
rowIndex,
columnIndex,
context: this.context
});
if (Array.isArray(result)) {
const [rowspan, colspan] = result;
return { rowspan: rowspan != null ? rowspan : 1, colspan: colspan != null ? colspan : 1 };
} else if (typeof result === 'object') {
return {
rowspan: rowspan != null ? rowspan : 1,
colspan: colspan != null ? colspan : 1
};
}
return { rowspan: 1, colspan: 1 };
},
// 获取单元格的样式类
getCellSpanClass(rowIndex, columnIndex) {
const span = this.getCellSpan(rowIndex, columnIndex);
// 如果rowspan为0或colspan为0,表示该单元格被合并,需要隐藏
if (span.rowspan === 0 || span.colspan === 0) {
return 'u-table-cell-hidden';
} else if (span.rowspan > 1 || span.colspan > 1) {
// 如果有合并,添加合并样式类
return 'u-table-cell-merged';
}
return '';
},
// 获取单元格的样式
getCellSpanStyle(rowIndex, columnIndex) {
const span = this.getCellSpan(rowIndex, columnIndex);
const style = {};
// 设置rowspan
if (span.rowspan > 1) {
// 正确计算合并后的高度
const currentHeight = parseInt(this.rowHeight);
if (!isNaN(currentHeight)) {
style.height = `${span.rowspan * currentHeight}px`;
}
}
// 设置colspan
if (span.colspan > 1) {
style.flex = span.colspan;
}
// 如果rowspan为0或colspan为0,表示该单元格被合并,需要隐藏
if (span.rowspan === 0 || span.colspan === 0) {
style.display = 'none';
}
return style;
}
}
}
</script>