sysmgr-admin/src/components/ty-table.vue
liuyun 104b7678d3 feat: rename ty-form, add search form collapse, use UnoCSS @apply
- ty-schema-form 改名 ty-form
- ty-search-form 支持折叠/展开(collapseCount 默认 2,查询/重置置右)
- ty-table/ty-crud/ty-search-form 样式改用 @apply 工具类

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-10-11 09:27:55 +08:00

112 lines
3.0 KiB
Vue

<template>
<div class="ty-table">
<el-table v-loading="loading" :data="data" border>
<el-table-column
v-for="col in columns"
:key="col.prop"
:label="col.label"
:width="col.width"
:min-width="col.minWidth"
:align="col.align"
>
<template #default="{ row }">
<el-tag
v-if="col.type === 'tag'"
:type="col.tagMap?.[String(row[col.prop])]?.type ?? 'info'"
size="small"
>
{{ col.tagMap?.[String(row[col.prop])]?.label ?? row[col.prop] }}
</el-tag>
<span v-else-if="col.type === 'datetime'">{{ formatDateTime(row[col.prop]) }}</span>
<span v-else-if="col.formatter">{{ col.formatter(row[col.prop], row) }}</span>
<span v-else>{{ row[col.prop] }}</span>
</template>
</el-table-column>
<el-table-column v-if="$slots.actions" label="操作" :width="actionsWidth" align="center" fixed="right">
<template #default="{ row }">
<slot name="actions" :row="row" />
</template>
</el-table-column>
</el-table>
<el-pagination
v-if="total > 0"
v-model:current-page="currentPage"
v-model:page-size="currentPageSize"
class="ty-table__pagination"
:total="total"
:page-sizes="pageSizes"
layout="total, sizes, prev, pager, next, jumper"
@current-change="onPageChange"
@size-change="onSizeChange"
/>
</div>
</template>
<script setup lang="ts">
import { computed } from 'vue'
import type { TableColumn } from '@/types/crud'
defineOptions({ name: 'TyTable' })
const props = withDefaults(
defineProps<{
/** 列配置。 */
columns: TableColumn[]
/** 表格数据。 */
data: Record<string, any>[]
loading?: boolean
/** 总条数(分页用)。 */
total?: number
page?: number
pageSize?: number
pageSizes?: number[]
/** 操作列宽度。 */
actionsWidth?: number | string
}>(),
{
loading: false,
total: 0,
page: 1,
pageSize: 10,
pageSizes: () => [10, 20, 50],
actionsWidth: 200,
},
)
const emit = defineEmits<{
(e: 'update:page', page: number): void
(e: 'update:pageSize', pageSize: number): void
}>()
const currentPage = computed({
get: () => props.page,
set: (v) => emit('update:page', v),
})
const currentPageSize = computed({
get: () => props.pageSize,
set: (v) => emit('update:pageSize', v),
})
function onPageChange(page: number): void {
emit('update:page', page)
}
function onSizeChange(size: number): void {
emit('update:pageSize', size)
}
function formatDateTime(value: unknown): string {
if (value == null || value === '') return '-'
const d = new Date(Number(value))
const pad = (n: number) => String(n).padStart(2, '0')
return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}`
}
</script>
<style scoped lang="scss">
.ty-table__pagination {
@apply mt-md justify-end;
}
</style>