|
|
@@ -38,6 +38,22 @@
|
|
|
<view v-else-if="column.type === 'note'">
|
|
|
<text>{{ getNoteText(row, locale, userStore) }}</text>
|
|
|
</view>
|
|
|
+ <view v-else-if="column.type === 'action'" class="action-wrapper">
|
|
|
+ <view class="action-list">
|
|
|
+ <template v-for="(item, idx) in getVisibleActions(column.menuList, row)" :key="idx">
|
|
|
+ <text v-if="actionExpanded[`${rowIndex}-${column.prop}`] || idx < 2"
|
|
|
+ class="action-btn"
|
|
|
+ @click.stop="item.btnClick && item.btnClick(row)">
|
|
|
+ {{ item.label || item.text || item.name }}
|
|
|
+ </text>
|
|
|
+ </template>
|
|
|
+ <text v-if="getVisibleActions(column.menuList, row).length > 2"
|
|
|
+ class="action-toggle-btn"
|
|
|
+ @click.stop="toggleAction(rowIndex, column.prop)">
|
|
|
+ {{ actionExpanded[`${rowIndex}-${column.prop}`] ? '隐藏' : '更多' }}
|
|
|
+ </text>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
<cwg-icon v-else-if="column.type === 'more'" name="crm-chevron-down"
|
|
|
class="crm-chevron-down" :size="16" color="#007" />
|
|
|
<template v-else>
|
|
|
@@ -58,7 +74,7 @@
|
|
|
</template>
|
|
|
|
|
|
<!-- 总计行 -->
|
|
|
- <uni-tr v-if="showSummary" class="summary-row">
|
|
|
+ <uni-tr v-if="showSummary &&tableData.length !== 0" class="summary-row">
|
|
|
<uni-td v-for="(column, index) in displayColumns" :key="'summary-' + column.prop"
|
|
|
:align="column.align || 'center'" class="summary-cell"
|
|
|
:style="getCellStyle(column, currentSummaryData)">
|
|
|
@@ -96,10 +112,10 @@
|
|
|
<view class="table-loading-mask">
|
|
|
<uni-loading v-if="loading" />
|
|
|
</view>
|
|
|
- <!-- 空状态 -->
|
|
|
- <view v-if="!loading && tableData.length === 0">
|
|
|
- <cwg-empty-state />
|
|
|
- </view>
|
|
|
+ <!-- 空状态 -->
|
|
|
+ <view v-if="!loading && tableData.length === 0" style="width: 100%;">
|
|
|
+ <cwg-empty-state />
|
|
|
+ </view>
|
|
|
<!-- 分页 -->
|
|
|
<view class="pagination-container" v-if="showPagination && tableData.length > 0">
|
|
|
<!-- <view class="pagination-info">
|
|
|
@@ -168,6 +184,7 @@ const props = defineProps({
|
|
|
* - 'file': 使用 cwg-file 渲染
|
|
|
* - 'more': 展示“更多”图标(用于移动端点击查看详情等)
|
|
|
* - 'date': 日期格式化(搭配 dateFormat)
|
|
|
+ * - 'action': 操作按钮
|
|
|
* - tagMap: 标签映射对象
|
|
|
* - tagTypeMap: 标签类型映射对象
|
|
|
* - dateFormat: 日期格式
|
|
|
@@ -264,6 +281,22 @@ const isMobile = ref(false)
|
|
|
// 排序状态
|
|
|
const sortState = ref({ prop: '', order: '' }) // order: 'asc' | 'desc' | ''
|
|
|
|
|
|
+// action 列的状态
|
|
|
+const actionExpanded = ref({})
|
|
|
+const getVisibleActions = (menuList, row) => {
|
|
|
+ if (!menuList) return []
|
|
|
+ return menuList.filter(item => {
|
|
|
+ if (typeof item.show === 'function') {
|
|
|
+ return item.show(row) !== false
|
|
|
+ }
|
|
|
+ return item.show !== false
|
|
|
+ })
|
|
|
+}
|
|
|
+const toggleAction = (rowIndex, prop) => {
|
|
|
+ const key = `${rowIndex}-${prop}`
|
|
|
+ actionExpanded.value[key] = !actionExpanded.value[key]
|
|
|
+}
|
|
|
+
|
|
|
// ========== 计算属性 ==========
|
|
|
// 显示的列(根据设备类型)
|
|
|
const displayColumns = computed(() => {
|
|
|
@@ -351,7 +384,7 @@ const getCellStyle = (column, row) => {
|
|
|
style.minWidth = w
|
|
|
style.maxWidth = w
|
|
|
style.wordBreak = 'break-all'
|
|
|
-
|
|
|
+
|
|
|
// 如果是自定义插槽,允许内容换行或由内部元素自己控制溢出,不强制隐藏
|
|
|
if (column.slot) {
|
|
|
style.whiteSpace = 'normal'
|
|
|
@@ -362,6 +395,11 @@ const getCellStyle = (column, row) => {
|
|
|
style.overflow = 'hidden'
|
|
|
style.textOverflow = 'ellipsis'
|
|
|
}
|
|
|
+ } else {
|
|
|
+ // 如果没有定宽,保证默认情况下单元格内容不会被直接 hidden 切掉下拉弹窗
|
|
|
+ if (column.slot) {
|
|
|
+ style.overflow = 'visible'
|
|
|
+ }
|
|
|
}
|
|
|
if (column.cellStyle) {
|
|
|
if (typeof column.cellStyle === 'function') {
|
|
|
@@ -481,9 +519,9 @@ const openRowDetail = (row) => {
|
|
|
if (props.isPages) {
|
|
|
emit('go-pages', row)
|
|
|
} else {
|
|
|
- // 保存当前行和需要显示的列(有 prop 且有 label)
|
|
|
+ // 保存当前行和需要显示的列(有 prop 且有 label) pc 详情不展示操作按钮
|
|
|
detailRow.value = { ...row, note: getNoteText(row, locale.value, userStore) }
|
|
|
- detailColumns.value = props.columns.filter(col => col && col.prop && col.label)
|
|
|
+ detailColumns.value = !isMobile.value ? props.columns.filter(col => col && col.prop && col.label && col.type !== 'action') : props.columns.filter(col => col && col.prop && col.label)
|
|
|
detailVisible.value = true
|
|
|
}
|
|
|
}
|
|
|
@@ -684,6 +722,7 @@ defineExpose({
|
|
|
width: 100%;
|
|
|
// overflow-x: auto;
|
|
|
// -webkit-overflow-scrolling: touch;
|
|
|
+ margin-top: px2rpx(20);
|
|
|
max-height: calc(100vh - 209px);
|
|
|
color: var(--color-slate-800);
|
|
|
|
|
|
@@ -699,19 +738,43 @@ defineExpose({
|
|
|
:deep(.uni-table-scroll) {
|
|
|
width: 100%;
|
|
|
max-height: calc(100vh - 375px);
|
|
|
- /* 当只有一条数据时,下拉菜单或弹窗会溢出,因此需设为可见 */
|
|
|
- overflow: visible !important;
|
|
|
+ //min-height: 300px;
|
|
|
+ overflow-y: auto;
|
|
|
+ overflow-x: auto;
|
|
|
+
|
|
|
+ /* 强制显示滚动条并美化 */
|
|
|
+ &::-webkit-scrollbar {
|
|
|
+ width: 8px;
|
|
|
+ height: 8px;
|
|
|
+ display: block; /* 强制在某些webkit浏览器中显示 */
|
|
|
+ background-color: transparent;
|
|
|
+ }
|
|
|
+ &::-webkit-scrollbar-track {
|
|
|
+ background-color: #f5f5f5;
|
|
|
+ border-radius: 4px;
|
|
|
+ }
|
|
|
+ &::-webkit-scrollbar-thumb {
|
|
|
+ background-color: #c0c4cc;
|
|
|
+ border-radius: 4px;
|
|
|
+
|
|
|
+ &:hover {
|
|
|
+ background-color: #909399;
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
:deep(.uni-table) {
|
|
|
- min-height: px2rpx(200) !important;
|
|
|
- overflow: visible !important;
|
|
|
+ border-radius: 8px;
|
|
|
+ box-shadow: 0 1px 4px rgba(0,0,0,0.02);
|
|
|
|
|
|
.uni-table-th {
|
|
|
position: sticky;
|
|
|
top: 0;
|
|
|
z-index: 100;
|
|
|
transition: all 0.3s;
|
|
|
+ background-color: #fafafa !important;
|
|
|
+ border-bottom: 1px solid #ebeef5 !important;
|
|
|
+ color: #606266;
|
|
|
|
|
|
.header-content {
|
|
|
display: flex;
|
|
|
@@ -739,12 +802,15 @@ defineExpose({
|
|
|
}
|
|
|
|
|
|
.uni-table-tr {
|
|
|
- &:last-child {
|
|
|
- border-bottom: none !important;
|
|
|
+ transition: background-color 0.2s ease;
|
|
|
+ border-bottom: 1px solid #ebeef5 !important;
|
|
|
+
|
|
|
+ &:hover {
|
|
|
+ background-color: #f5f7fa !important;
|
|
|
}
|
|
|
|
|
|
- .uni-table-th {
|
|
|
- border-bottom: 1px solid #141d22 !important;
|
|
|
+ &:last-child {
|
|
|
+ border-bottom: none !important;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -761,13 +827,50 @@ defineExpose({
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- .uni-table-th,
|
|
|
.uni-table-td {
|
|
|
padding: px2rpx(16) px2rpx(5);
|
|
|
- color: var(--color-slate-800);
|
|
|
+ color: #303133;
|
|
|
+ box-sizing: border-box;
|
|
|
+ vertical-align: middle;
|
|
|
+ font-size: 14px;
|
|
|
+ white-space: nowrap;
|
|
|
+ }
|
|
|
+
|
|
|
+ .uni-table-th {
|
|
|
+ padding: px2rpx(14) px2rpx(5);
|
|
|
box-sizing: border-box;
|
|
|
- /* 保证只有一条数据时,插槽弹窗不会被父元素裁剪 */
|
|
|
- overflow: visible !important;
|
|
|
+ vertical-align: middle;
|
|
|
+ font-size: 14px;
|
|
|
+ white-space: nowrap;
|
|
|
+ word-break: keep-all;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ .action-wrapper {
|
|
|
+ max-width: 180px;
|
|
|
+ white-space: normal;
|
|
|
+ }
|
|
|
+
|
|
|
+ .action-list {
|
|
|
+ display: flex;
|
|
|
+ flex-wrap: wrap;
|
|
|
+ gap: 6px 5px;
|
|
|
+ align-items: center;
|
|
|
+ }
|
|
|
+
|
|
|
+ .action-btn {
|
|
|
+ color: var(--color-primary);
|
|
|
+ text-decoration: underline;
|
|
|
+ cursor: pointer;
|
|
|
+ font-size: px2rpx(12);
|
|
|
+ white-space: nowrap;
|
|
|
+ }
|
|
|
+
|
|
|
+ .action-toggle-btn {
|
|
|
+ color: #909399;
|
|
|
+ cursor: pointer;
|
|
|
+ font-size: px2rpx(12);
|
|
|
+ white-space: nowrap;
|
|
|
}
|
|
|
|
|
|
.expand-cell {
|
|
|
@@ -794,16 +897,19 @@ defineExpose({
|
|
|
|
|
|
/* 分页样式 */
|
|
|
.pagination-container {
|
|
|
- margin: px2rpx(20) px2rpx(20);
|
|
|
+ margin: px2rpx(20) 0;
|
|
|
display: flex;
|
|
|
align-items: center;
|
|
|
justify-content: flex-end;
|
|
|
gap: px2rpx(20);
|
|
|
+ position: relative;
|
|
|
+ z-index: 10;
|
|
|
+ background-color: transparent;
|
|
|
|
|
|
.pagination {
|
|
|
display: flex;
|
|
|
align-items: center;
|
|
|
- padding: px2rpx(10);
|
|
|
+ //padding: px2rpx(10);
|
|
|
}
|
|
|
|
|
|
.page-item {
|