Open grasilife opened 3 months ago
<CubeTable
:columns="columns"
:data="dataSource"
:loading="loading"
:pagination="pagination"
@page-change="changePage"
@page-size-change="pageSizeChange"
>
<template #name="{ record }">
<Link @click="toApps(record)"> {{ record.name }}</Link>
</template>
<template #domain="{ record }">
<Link :href="record.domain"> {{ record.domain }}</Link>
</template>
<template #description="{ record }">
{{ record.description || '-' }}
</template>
<template #actions="{ record }">
<Button type="text" @click="edit(record)">编辑</Button>
<Popconfirm content="你确定要删除吗?" @ok="remove(record)">
<Button type="text" status="danger"> 删除 </Button>
</Popconfirm>
</template>
</CubeTable>
给你们一个好用的minWidth的demo
const columns: TableColumnData[] = [
{
dataIndex: 'appKey',
slotName: 'appKey',
title: 'AppKey',
ellipsis: true,
tooltip: true,
},
{
dataIndex: 'name',
slotName: 'name',
title: '应用名',
ellipsis: true,
tooltip: true,
},
{
dataIndex: 'domain',
slotName: 'domain',
title: '应用域名',
width: 200,
ellipsis: true,
tooltip: true,
},
{
dataIndex: 'description',
slotName: 'description',
title: '描述',
ellipsis: true,
tooltip: true,
},
...commonColumns,
{
dataIndex: 'actions',
slotName: 'actions',
title: '操作',
width: 160,
fixed: 'right',
},
];
<template>
<div class="CubeTableCom">
<Spin :loading="props.loading" tip="数据加载中">
<div class="tableContain">
<table>
<!-- 表头 -->
<thead>
<tr class="tableRow">
<th
v-for="(columnsItem, index) in props.columns"
:key="index"
:class="{
fixed: columnsItem.fixed,
fixedBackground: columnsItem.fixed,
lastBorder: !columnsItem.fixed,
}"
:style="{
minWidth: `${columnsItem.minWidth}px`,
width: `${columnsItem.width}px`,
}"
>
<Ellipsis :switch="columnsItem.ellipsis">
{{ columnsItem.title }}
</Ellipsis>
</th>
</tr>
</thead>
<!-- 表格内容 -->
<tbody>
<tr
v-for="(dataSourceItem, dataSourceIndex) in props.data"
:key="dataSourceIndex"
class="tableRow"
:class="{ trListHover: dataSourceIndex === activeKey }"
@mouseenter="mouseenter(dataSourceIndex)"
@mouseleave="mouseleave(dataSourceIndex)"
>
<td
v-for="(columnsItem, columnsIndex) in props.columns"
:key="columnsIndex"
:class="{
fixed: columnsItem.fixed,
trListHover: dataSourceIndex === activeKey,
lastBorder: !columnsItem.fixed,
ellipsis: columnsItem.ellipsis,
}"
:style="{
minWidth: `${columnsItem.minWidth}px`,
width: `${columnsItem.width}px`,
}"
>
<Ellipsis :switch="columnsItem.ellipsis">
<template v-if="hasSlot(columnsItem.slotName)">
<slot
:name="columnsItem.slotName"
:record="dataSourceItem"
></slot>
</template>
<template v-else>
<Tooltip
v-if="columnsItem.tooltip"
:content="getValue(dataSourceItem, columnsItem.dataIndex)"
position="bottom"
>
<span>{{
getValue(dataSourceItem, columnsItem.dataIndex)
}}</span>
</Tooltip>
<template v-else>
{{ getValue(dataSourceItem, columnsItem.dataIndex) }}
</template>
</template>
</Ellipsis>
</td>
</tr>
</tbody>
</table>
<div class="contain" v-if="props.data.length === 0">
<Empty v-if="props.data.length === 0" />
</div>
</div>
<div class="pagination">
<Pagination
v-if="props.pagination"
v-model="props.pagination.current"
:total="props.pagination?.total || 0"
:pageSize="pagination.pageSize"
:showTotal="pagination.showTotal"
:showJumper="pagination.showJumper"
:showPageSize="pagination.showPageSize"
@change="change"
@page-size-change="pageSizeChange"
/>
</div>
</Spin>
</div>
</template>
<script setup lang="ts">
import {
TableColumnData,
Empty,
PaginationProps,
Pagination,
Spin,
Tooltip,
} from '@arco-design/web-vue';
import { PropType, ref, useSlots, VNode } from 'vue';
import Ellipsis from '~/components/Ellipsis.vue';
import { beautifyJSON } from '~/utils';
type Slots = Record<string, () => VNode[]>;
const activeKey = ref(-1);
const emit = defineEmits([
'mouseenter',
'mouseleave',
'pageChange',
'pageSizeChange',
]);
const change = (currentPage: number) => {
console.log(currentPage, 'currentPage');
emit('pageChange', currentPage);
};
const pageSizeChange = (pageSize: number) => {
console.log(pageSize, 'pageSize');
emit('pageSizeChange', pageSize);
};
const props = defineProps({
loading: {
type: Boolean,
required: false,
default: () => false,
},
bordered: {
type: Boolean,
required: false,
default: () => true,
},
data: {
type: Array as PropType<any[]>,
required: true,
default: () => [],
},
pagination: {
type: Object as PropType<PaginationProps>,
required: false,
default: () => null,
},
columns: {
type: Array as PropType<TableColumnData[]>,
required: true,
default: () => [],
},
});
function hasSlot(slotName: string | undefined): boolean {
const slots = useSlots() as Slots;
return slotName ? !!slots[slotName] : false;
}
function getValue(dataSourceItem: any, dataIndex: string | undefined): string {
if (dataIndex) {
const value = dataSourceItem[dataIndex as keyof typeof dataSourceItem];
// 如果值是对象或数组,使用 beautifyJSON 进行美化处理
if (typeof value === 'object' && value !== null) {
return beautifyJSON(value);
}
// 如果值是布尔值或数字,将其转换为字符串
if (typeof value === 'boolean' || typeof value === 'number') {
return value.toString();
}
// 默认情况,直接返回值,确保其为字符串
return value !== undefined && value !== null ? value.toString() : '-';
}
// 如果没有 dataIndex 或值为空,返回占位符 '-'
return '-';
}
function mouseenter(dataSourceIndex: number) {
activeKey.value = dataSourceIndex;
emit('mouseenter', dataSourceIndex);
}
function mouseleave(dataSourceIndex: number) {
activeKey.value = -1;
emit('mouseleave', dataSourceIndex);
}
</script>
<style scoped>
.CubeTableCom {
display: flex;
flex-direction: column;
flex: 1;
}
.tableContain {
display: flex;
flex-direction: column;
flex: 1;
font-size: 14px;
border-top: 1px solid var(--color-border);
border-left: 1px solid var(--color-border);
border-right: 1px solid var(--color-border);
overflow-x: auto;
overflow-y: hidden;
}
table {
border-collapse: collapse;
width: 100%;
}
tr {
width: 100%;
}
th,
td {
text-align: left;
padding: 12px 16px;
}
th {
background-color: var(--color-fill-2);
color: var(--color-text);
border-bottom: 1px solid var(--color-border);
}
.borderedRight {
border-right: 1px solid var(--color-border);
}
td {
color: var(--color-text-secondary);
border-bottom: 1px solid var(--color-border);
}
.fixed {
position: sticky;
right: 0;
background: #fff;
z-index: 2;
display: inline-block;
border-left: 1px solid var(--color-border);
}
.fixedBackground {
background-color: var(--color-fill-2);
}
.lastBorder {
border-left: 1px solid var(--color-border);
}
.trListHover {
transition: background-color 0.2s;
background-color: var(--color-fill-2);
}
.contain {
display: flex;
height: 200px;
align-items: center;
justify-content: center;
border-bottom: 1px solid var(--color-border);
}
.pagination {
display: flex;
flex: 1;
justify-content: flex-end;
margin-top: 12px;
}
/* 选择除最后两个子元素之外的所有子元素 */
.tableRow > :not(:nth-last-child(-n + 2)) {
border-right: 1px solid var(--color-border);
}
</style>
<template>
<div ref="ellipsisContainer" :style="ellipsisStyle">
<slot></slot>
</div>
</template>
<script lang="ts" setup>
import { onMounted, onBeforeUnmount, ref, computed } from 'vue';
const props = defineProps({
switch: {
type: Boolean,
required: false,
default: () => false,
},
});
const ellipsisContainer = ref<HTMLElement | null>(null);
const ellipsisStyle = computed(() => {
if (props.switch) {
if (ellipsisContainer.value && ellipsisContainer.value) {
const parentWidth = ellipsisContainer.value.clientWidth;
return {
maxWidth: `${parentWidth}px`,
whiteSpace: 'nowrap',
overflow: 'hidden',
textOverflow: 'ellipsis',
};
}
} else {
return {};
}
});
const setEllipsisWidth = () => {
if (props.switch && ellipsisContainer.value) {
const parentWidth = ellipsisContainer.value.clientWidth;
ellipsisContainer.value.style.maxWidth = `${parentWidth}px`;
}
};
onMounted(() => {
if (props.switch) {
setEllipsisWidth();
window.addEventListener('resize', setEllipsisWidth);
}
});
onBeforeUnmount(() => {
if (props.switch) {
window.removeEventListener('resize', setEllipsisWidth);
}
});
</script>
<style scoped>
.ellipsis {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
</style>
为了点小问题,写这堆屎山代码,又不是不能用
为了点小问题,写这堆屎山代码,又不是不能用 我只是想要一个好用的minwidth而已,代码你可以写的比我好,相信你,太常用了,其他功能需要不是很大,这个太大了
为了点小问题,写这堆屎山代码,又不是不能用
经典的“又不是不能用”,那太好了,BUG也别修了,项目也别维护了,张嘴闭嘴就屎山代码,你又不是维护者,别人提个意见碍着你啥事了?什么毛病都带到这里来了,污染环境
为了点小问题,写这堆屎山代码,又不是不能用
经典的“又不是不能用”,那太好了,BUG也别修了,项目也别维护了,张嘴闭嘴就屎山代码,你又不是维护者,别人提个意见碍着你啥事了?什么毛病都带到这里来了,污染环境
arco-table的min-width用这没问题啊,反正我测了没问题,而且就算要弄td的min-width,也有个td插槽,封装这么麻烦干嘛,arco的灵活度不是那么差的,不会用怪组件库呗
为了点小问题,写这堆屎山代码,又不是不能用
经典的“又不是不能用”,那太好了,BUG也别修了,项目也别维护了,张嘴闭嘴就屎山代码,你又不是维护者,别人提个意见碍着你啥事了?什么毛病都带到这里来了,污染环境
如果你接手一个项目,看到这个二次封装的,一没有文档,要你看源码,行如果你厉害你看得懂了,可以往下做,如果要扩展需求,a-table能实现,这个不能,你要咋弄,继续给源码加props是吧,到时候你别骂街就行,你不骂街,下个人就要骂你
为了点小问题,写这堆屎山代码,又不是不能用
经典的“又不是不能用”,那太好了,BUG也别修了,项目也别维护了,张嘴闭嘴就屎山代码,你又不是维护者,别人提个意见碍着你啥事了?什么毛病都带到这里来了,污染环境
楼主的也不是基于a-table二次封装,而是自己封装的,这样会导致什么呢,样式不统一,风格不统一,你告诉我这不是变成屎山的节奏吗以后,而且也没有文档,我宁愿用着组件库的table,也不会搞这么复杂
Basic Info
What is expected?
{ dataIndex: 'appKey', slotName: 'appKey', title: 'AppKey', minWidth: 100, ellipsis: true, tooltip: true, }, { dataIndex: 'name', slotName: 'name', title: '应用名', minWidth: 100, ellipsis: true, tooltip: true, }, { dataIndex: 'domain', slotName: 'domain', title: '应用域名1', minWidth: 10, ellipsis: true, tooltip: true, }, { dataIndex: 'description', slotName: 'description', title: '描述', minWidth: 100, ellipsis: true, tooltip: true, }, 列宽有问题,根本和设置的不一样