| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152 |
- <template>
- <n-data-table class="normal-table"
- :columns="columns"
- :data="tableData"
- :single-line="true"
- />
- </template>
- <script setup lang="ts">
- import { NDataTable, DataTableColumn } from 'naive-ui'
- interface ColumnConfig {
- title: string;
- children?: ColumnConfig[];
- align?: 'left' | 'right' | 'center'; // 列文本对齐方式,默认left
- titleAlign?: 'left' | 'right' | 'center'; // 列标题对齐方式,默认同文本
- minWidth?: number | string;
- maxWidth?: number | string;
- width?: number | string;
- }
- type TableConfig = (string | ColumnConfig)[]
- interface CellDataExt {
- text: string;
- colspan?: number | undefined; // 向右合并 N 个单元格
- rowspan?: number | undefined; // 向下合并 N 个单元格
- }
- interface CellDataType {
- [title: string]: string | CellDataExt
- }
- interface Props {
- config?: TableConfig;
- data?: CellDataType[];
- }
- const props = withDefaults(defineProps<Props>(), {
- config: () => ({}),
- data: () => []
- })
- const handleRowSpan = (rowData: DataTableColumn, rowIndex: number, key: string): number => {
- const data = props.data[rowIndex]
- if (!data) return 1
- const keyValue = data[key]
- if (!keyValue) return 1
- if (typeof keyValue === "string") return 1
- return keyValue.rowspan ?? 1
- }
- const handleColSpan = (rowData: DataTableColumn, rowIndex: number, key: string): number => {
- const data = props.data[rowIndex]
- if (!data) return 1
- const keyValue = data[key]
- if (!keyValue) return 1
- if (typeof keyValue === "string") return 1
- return keyValue.colspan ?? 1
- }
- function traversalChildren(child: ColumnConfig[]) {
- return child.map(item => {
- let obj: DataTableColumn = {}
- obj.title = item.title
- obj.key = item.title
- obj.align = item.align
- obj.titleAlign = item.titleAlign
- obj.minWidth = item.minWidth
- obj.maxWidth = item.maxWidth
- obj.width = item.width
- if (item.children) {
- obj.children = traversalChildren(item.children)
- } else {
- obj.rowSpan = (rowData, rowIndex) => {
- return handleRowSpan(rowData, rowIndex, item.title)
- }
- obj.colSpan = (rowData, rowIndex) => {
- return handleColSpan(rowData, rowIndex, item.title)
- }
- }
- return obj
- })
- }
- function createColumns(config: TableConfig) {
- return config.map(column => {
- let obj: DataTableColumn = {}
- if (typeof column === 'string') {
- obj.title = column
- obj.key = column
- obj.rowSpan = (rowData, rowIndex) => {
- return handleRowSpan(rowData, rowIndex, column)
- }
- obj.colSpan = (rowData, rowIndex) => {
- return handleColSpan(rowData, rowIndex, column)
- }
- } else {
- obj.title = column.title
- obj.key = column.title
- obj.align = column.align
- obj.titleAlign = column.titleAlign
- obj.minWidth = column.minWidth
- obj.maxWidth = column.maxWidth
- obj.width = column.width
- if (column.children) {
- obj.children = traversalChildren(column.children)
- } else {
- obj.rowSpan = (rowData, rowIndex) => {
- return handleRowSpan(rowData, rowIndex, column.title)
- }
- obj.colSpan = (rowData, rowIndex) => {
- return handleColSpan(rowData, rowIndex, column.title)
- }
- }
- }
- return obj
- })
- }
- function createData(data: CellDataType[]) {
- return data.map((row, index) => {
- let obj = {
- key: index
- }
- for (const key in row) {
- const value = row[key as keyof typeof row];
- if (typeof value === "string") {
- obj[key] = value
- } else {
- obj[key] = value.text
- }
- }
- return obj
- })
- }
- const columns = createColumns(props.config)
- const tableData = createData(props.data)
- </script>
- <style scoped>
- /* 覆盖.vp-doc table */
- .normal-table :deep(table) {
- margin: 0 0 !important;
- }
- .normal-table :deep(td) {
- white-space: pre-wrap; /* 保留换行和空格 */
- }
- </style>
|