| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114 |
- <template>
- <view class="">
- <view class="table-header">
- <view class="table-header-cell" v-for="item in tableColumns" :key="item.prop" :style="getHeaderStyle(item)">
- {{ item.label }}
- </view>
- </view>
- <view class="table-body">
- <block v-if="data.length">
- <view class="table-row" :class="{ 'sibling-border-top': getTableConfig.border }" v-for="(row, index) in data"
- :key="getRowKey(row, index)" @click="handleRowClick(row)">
- <view class="table-row-cell" v-for="item in tableColumns" :key="item.prop" :style="getCellStyle(item)">
- <view v-if="item.type === 'index'">
- {{ index + 1 }}
- </view>
- <slot v-else :name="item.slot" :item="row" :index="index">
- <text>{{ getCellValue(row, item.prop) }}</text>
- </slot>
- </view>
- </view>
- </block>
- <view v-else class="no-data">{{ getTableConfig.emptyText }}</view>
- </view>
- </view>
- </template>
- <script lang="ts" setup generic="T extends Record<string, any>">
- import { TableColumnConfig, TableConfig } from '@/types';
- import { CSSProperties } from 'vue';
- // 使用泛型定义props
- interface Props<T> {
- tableConfig: TableConfig;
- tableColumns: TableColumnConfig[];
- data: T[];
- cellStyle: CSSProperties;
- }
- const props = defineProps<Props<any>>();
- // 使用泛型定义emits
- const emit = defineEmits<{
- rowClick: [row: T]
- }>();
- const getTableConfig = computed(() => {
- return {
- ...{
- border: true,
- stripe: false,
- emptyText: '暂无数据',
- loading: false,
- rowKey: 'id'
- },
- ...props.tableConfig
- };
- });
- const getHeaderStyle = (item: TableColumnConfig) => {
- return {
- flex: item.flex ? item.flex : 1,
- minWidth: '1px',
- textAlign: item.headerAlign ? item.headerAlign : 'center'
- };
- };
- const getCellStyle = (item: TableColumnConfig) => {
- return {
- flex: item.flex ? item.flex : 1,
- minWidth: '1px',
- flexShrink: 0,
- width: '100%',
- textAlign: item.align ? item.align : 'center',
- ...props.cellStyle
- };
- };
- const handleRowClick = (row: any) => {
- emit('rowClick', row);
- };
- // 安全地获取行key
- const getRowKey = (row: any, index: number) => {
- const rowKey = getTableConfig.value.rowKey;
- return row[rowKey] || index;
- };
- // 安全地获取单元格值
- const getCellValue = (row: any, prop: string) => {
- return row[prop] || '';
- };
- </script>
- <style lang="scss" scoped>
- .table-header {
- @apply flex items-center bg-[#EBF9FF] rounded-5;
- }
- .table-header-cell {
- @apply flex-1 px-20 py-20 text-30 text-fore-light;
- }
- .table-row {
- @apply flex items-center;
- }
- .table-row-cell {
- @apply px-20 py-20 text-28 text-fore-title;
- }
- .no-data {
- @apply mt-16 bg-[#F6F8FA] text-center py-50 text-26 text-fore-light rounded-5;
- }
- </style>
|