251 lines
5.8 KiB
Vue
251 lines
5.8 KiB
Vue
<template>
|
|
<div class="search-table-container">
|
|
<a-card class="general-card" :title="title">
|
|
<!-- 搜索表单 -->
|
|
<SearchForm
|
|
:model-value="formModel"
|
|
:form-items="formItems"
|
|
:show-buttons="showSearchButtons"
|
|
:search-button-text="searchButtonText"
|
|
:reset-button-text="resetButtonText"
|
|
@update:model-value="handleFormModelUpdate"
|
|
@search="handleSearch"
|
|
@reset="handleReset"
|
|
>
|
|
<template #form-items>
|
|
<slot name="form-items" />
|
|
</template>
|
|
</SearchForm>
|
|
|
|
<a-divider style="margin-top: 0" />
|
|
|
|
<!-- 数据表格 -->
|
|
<DataTable
|
|
:data="data"
|
|
:columns="columns"
|
|
:loading="loading"
|
|
:pagination="pagination"
|
|
:bordered="bordered"
|
|
:row-selection="rowSelection"
|
|
:scroll="scroll"
|
|
:show-toolbar="showToolbar"
|
|
:show-download="showDownload"
|
|
:show-refresh="showRefresh"
|
|
:show-density="showDensity"
|
|
:show-column-setting="showColumnSetting"
|
|
:download-button-text="downloadButtonText"
|
|
:refresh-tooltip-text="refreshTooltipText"
|
|
:density-tooltip-text="densityTooltipText"
|
|
:column-setting-tooltip-text="columnSettingTooltipText"
|
|
@page-change="handlePageChange"
|
|
@page-size-change="handlePageSizeChange"
|
|
@selection-change="handleSelectionChange"
|
|
@row-click="handleRowClick"
|
|
@refresh="handleRefresh"
|
|
@download="handleDownload"
|
|
@density-change="handleDensityChange"
|
|
@column-change="handleColumnChange"
|
|
>
|
|
<template #toolbar-left>
|
|
<slot name="toolbar-left" />
|
|
</template>
|
|
<template #toolbar-right>
|
|
<slot name="toolbar-right" />
|
|
</template>
|
|
<!-- 动态插槽透传 -->
|
|
<template v-for="col in slotColumns" :key="col.dataIndex" #[String(col.slotName)]="slotProps">
|
|
<slot :name="col.slotName" v-bind="slotProps" />
|
|
</template>
|
|
</DataTable>
|
|
</a-card>
|
|
</div>
|
|
</template>
|
|
|
|
<script lang="ts" setup>
|
|
import { computed, PropType } from 'vue'
|
|
import SearchForm from '../search-form/index.vue'
|
|
import type { FormItem } from '../search-form/types'
|
|
import DataTable from '../data-table/index.vue'
|
|
import type { TableColumnData, TableRowSelection } from '@arco-design/web-vue/es/table/interface'
|
|
|
|
type SizeProps = 'mini' | 'small' | 'medium' | 'large'
|
|
|
|
const props = defineProps({
|
|
// 表单相关
|
|
formModel: {
|
|
type: Object as PropType<Record<string, any>>,
|
|
required: true,
|
|
},
|
|
formItems: {
|
|
type: Array as PropType<FormItem[]>,
|
|
default: () => [],
|
|
},
|
|
showSearchButtons: {
|
|
type: Boolean,
|
|
default: true,
|
|
},
|
|
searchButtonText: {
|
|
type: String,
|
|
default: '查询',
|
|
},
|
|
resetButtonText: {
|
|
type: String,
|
|
default: '重置',
|
|
},
|
|
// 表格相关
|
|
data: {
|
|
type: Array as PropType<any[]>,
|
|
default: () => [],
|
|
},
|
|
columns: {
|
|
type: Array as PropType<TableColumnData[]>,
|
|
required: true,
|
|
},
|
|
loading: {
|
|
type: Boolean,
|
|
default: false,
|
|
},
|
|
pagination: {
|
|
type: Object as PropType<{
|
|
current: number
|
|
pageSize: number
|
|
total?: number
|
|
}>,
|
|
default: () => ({
|
|
current: 1,
|
|
pageSize: 20,
|
|
}),
|
|
},
|
|
bordered: {
|
|
type: Boolean,
|
|
default: false,
|
|
},
|
|
rowSelection: {
|
|
type: Object as PropType<TableRowSelection | undefined>,
|
|
default: undefined,
|
|
},
|
|
scroll: {
|
|
type: Object as PropType<{ x?: number | string; y?: number | string } | undefined>,
|
|
default: undefined,
|
|
},
|
|
// 工具栏相关
|
|
showToolbar: {
|
|
type: Boolean,
|
|
default: true,
|
|
},
|
|
showDownload: {
|
|
type: Boolean,
|
|
default: false,
|
|
},
|
|
showRefresh: {
|
|
type: Boolean,
|
|
default: true,
|
|
},
|
|
showDensity: {
|
|
type: Boolean,
|
|
default: true,
|
|
},
|
|
showColumnSetting: {
|
|
type: Boolean,
|
|
default: true,
|
|
},
|
|
// 文本配置
|
|
title: {
|
|
type: String,
|
|
default: '',
|
|
},
|
|
downloadButtonText: {
|
|
type: String,
|
|
default: '下载',
|
|
},
|
|
refreshTooltipText: {
|
|
type: String,
|
|
default: '刷新',
|
|
},
|
|
densityTooltipText: {
|
|
type: String,
|
|
default: '密度',
|
|
},
|
|
columnSettingTooltipText: {
|
|
type: String,
|
|
default: '列设置',
|
|
},
|
|
})
|
|
|
|
const emit = defineEmits<{
|
|
(e: 'update:formModel', value: Record<string, any>): void
|
|
(e: 'search'): void
|
|
(e: 'reset'): void
|
|
(e: 'page-change', current: number): void
|
|
(e: 'page-size-change', pageSize: number): void
|
|
(e: 'selection-change', rowKeys: (string | number)[]): void
|
|
(e: 'row-click', record: any, ev: Event): void
|
|
(e: 'refresh'): void
|
|
(e: 'download'): void
|
|
(e: 'density-change', size: SizeProps): void
|
|
(e: 'column-change', columns: TableColumnData[]): void
|
|
}>()
|
|
|
|
|
|
// 计算需要插槽的列(动态插槽透传)
|
|
const slotColumns = computed(() => {
|
|
return props.columns.filter(col => col.slotName)
|
|
})
|
|
|
|
const handleFormModelUpdate = (value: Record<string, any>) => {
|
|
emit('update:formModel', value)
|
|
}
|
|
|
|
const handleSearch = () => {
|
|
emit('search')
|
|
}
|
|
|
|
const handleReset = () => {
|
|
emit('reset')
|
|
}
|
|
|
|
const handlePageChange = (current: number) => {
|
|
emit('page-change', current)
|
|
}
|
|
|
|
const handlePageSizeChange = (pageSize: number) => {
|
|
emit('page-size-change', pageSize)
|
|
}
|
|
|
|
const handleSelectionChange = (rowKeys: (string | number)[]) => {
|
|
emit('selection-change', rowKeys)
|
|
}
|
|
|
|
const handleRowClick = (record: any, ev: Event) => {
|
|
emit('row-click', record, ev)
|
|
}
|
|
|
|
const handleRefresh = () => {
|
|
emit('refresh')
|
|
}
|
|
|
|
const handleDownload = () => {
|
|
emit('download')
|
|
}
|
|
|
|
const handleDensityChange = (size: SizeProps) => {
|
|
emit('density-change', size)
|
|
}
|
|
|
|
const handleColumnChange = (columns: TableColumnData[]) => {
|
|
emit('column-change', columns)
|
|
}
|
|
</script>
|
|
|
|
<script lang="ts">
|
|
export default {
|
|
name: 'SearchTable',
|
|
}
|
|
</script>
|
|
|
|
<style scoped lang="less">
|
|
.search-table-container {
|
|
padding: 0 20px 20px 20px;
|
|
}
|
|
</style>
|