Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

min-width 有bug啊,arco和antd没一个做的好的,学习一下element ui的吧 #3275

Open
1 task
grasilife opened this issue Aug 22, 2024 · 7 comments
Open
1 task

Comments

@grasilife
Copy link

Basic Info

  • Package Name And Version: @arco-design/web-vue@2.56.0
  • Browser: chrome127.0.0.0

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,
}, 列宽有问题,根本和设置的不一样

@grasilife
Copy link
Author

      <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>

@grasilife
Copy link
Author

给你们一个好用的minWidth的demo

@grasilife
Copy link
Author

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',
  },
];

@grasilife
Copy link
Author

<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>

@grasilife
Copy link
Author

<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>

@lin-97
Copy link

lin-97 commented Aug 26, 2024

为了点小问题,写这堆屎山代码,又不是不能用

@grasilife
Copy link
Author

为了点小问题,写这堆屎山代码,又不是不能用
我只是想要一个好用的minwidth而已,代码你可以写的比我好,相信你,太常用了,其他功能需要不是很大,这个太大了

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants