663 lines
23 KiB
TypeScript
663 lines
23 KiB
TypeScript
/* @jsxImportSource vue */
|
||
import APage from '@/components/a-page/APage.vue'
|
||
import styles from '@/components/a-page/a-table-page/a-table-page.module.styl'
|
||
import {
|
||
ElButton,
|
||
ElDropdown,
|
||
ElDropdownItem,
|
||
ElDropdownMenu,
|
||
ElForm,
|
||
ElLoading,
|
||
ElMessageBox,
|
||
ElPagination,
|
||
ElPopconfirm,
|
||
ElScrollbar,
|
||
ElTable,
|
||
ElTableColumn,
|
||
ElTooltip,
|
||
type TableColumnCtx,
|
||
type TableProps,
|
||
} from 'element-plus'
|
||
import {
|
||
defineComponent,
|
||
withDirectives,
|
||
withModifiers,
|
||
} from 'vue'
|
||
import type { R } from '@/common/utils/http-util.ts'
|
||
import {
|
||
elIcons,
|
||
type ElIconType,
|
||
} from '@/common/element/element.ts'
|
||
import type { FormProps } from 'element-plus/es/components/form/src/form'
|
||
import Utils, { type ResetAble } from '@/common/utils'
|
||
import Strings from '@/common/utils/strings.ts'
|
||
import { saveFile } from '@/common/app'
|
||
import Colls from '@/common/utils/colls.ts'
|
||
import type { SetupContext } from '@vue/runtime-core'
|
||
import Types from '@/common/utils/types.ts'
|
||
import {
|
||
type IconName,
|
||
iconNames,
|
||
} from '@/components/a-icon/iconfont.ts'
|
||
import AIcon from '@/components/a-icon/AIcon.vue'
|
||
import type { DefaultRow } from 'element-plus/es/components/table/src/table/defaults'
|
||
|
||
|
||
interface ColumnScopeType<T> {
|
||
row: T,
|
||
column: TableColumnCtx,
|
||
$index: number
|
||
}
|
||
|
||
interface TableActionType<T> {
|
||
icon?: ElIconType | IconName
|
||
type?: 'text' | 'default' | 'primary' | 'success' | 'warning' | 'info' | 'danger'
|
||
tooltip: string | ((data: ColumnScopeType<T>) => string)
|
||
loading?: boolean
|
||
show?: (data: ColumnScopeType<T>) => boolean
|
||
action: (data: ColumnScopeType<T>) => Promise<boolean> | void
|
||
confirm?: {
|
||
title: string | ((data: ColumnScopeType<T>) => string)
|
||
width?: string
|
||
confirmButtonText?: string
|
||
cancelButtonText?: string
|
||
}
|
||
}
|
||
|
||
interface ActionColumnType<T> {
|
||
/**
|
||
* 列宽,默认:80px
|
||
*/
|
||
width: number
|
||
foldLimit: number
|
||
/**
|
||
* 按钮列表
|
||
*/
|
||
tableActions: TableActionType<T>[]
|
||
}
|
||
|
||
interface ToolType {
|
||
icon?: ElIconType
|
||
type?: 'text' | 'default' | 'primary' | 'success' | 'warning' | 'info' | 'danger'
|
||
label?: string
|
||
action: () => void
|
||
}
|
||
|
||
interface ToolBarType {
|
||
leftTools: ToolType[]
|
||
rightTools: Required<Omit<ToolType, 'type' | 'label'>>[]
|
||
}
|
||
|
||
interface TablePropsType<T extends DefaultRow, F extends object> extends Omit<TableProps<T>, 'data' | 'headerRowClassName' | 'cellClassName' | 'context'> {
|
||
treeLoad?: (param: F, row: T, expanded: any, resolve?: (data: T[]) => void) => void
|
||
/**
|
||
* 操作列配置
|
||
*/
|
||
actionColumn: ActionColumnType<T>
|
||
}
|
||
|
||
interface FormPropsType<P, T extends DefaultRow> {
|
||
/**
|
||
* 分页函数
|
||
* @param param 查询条件
|
||
*/
|
||
paging: (param: P) => Promise<R<G.PageResult<T>>>
|
||
/**
|
||
* 导出函数
|
||
* @param param 查询条件
|
||
*/
|
||
export?: (param: P) => Promise<R<{ content: Blob, filename: string }>>
|
||
/**
|
||
* 表单默认值
|
||
*/
|
||
defaultData: P
|
||
/**
|
||
* 高级查询表单配置
|
||
*/
|
||
highForm: Partial<Omit<FormProps, 'labelWidth'>> & {
|
||
/**
|
||
* 标签宽度,单位:px,默认:90px
|
||
*/
|
||
labelWidth: number,
|
||
/**
|
||
* 输入框宽度,单位:px,默认:200px
|
||
*/
|
||
contentWidth: number,
|
||
/**
|
||
* 行间隔,单位:px,默认:10px
|
||
*/
|
||
rgap: number,
|
||
/**
|
||
* 列间隔,单位:px,默认:10px
|
||
*/
|
||
cgap: number
|
||
}
|
||
/**
|
||
* 简单查询表单配置
|
||
*/
|
||
simpleForm: Partial<FormProps> & {
|
||
/**
|
||
* 列数,默认:1
|
||
*/
|
||
colCount: number,
|
||
/**
|
||
* 输入框宽度,单位:px,默认:200px
|
||
*/
|
||
contentWidth: number,
|
||
|
||
/**
|
||
* 行间隔,单位:px,默认:10px
|
||
*/
|
||
// rgap: number,
|
||
/**
|
||
* 列间隔,单位:px,默认:10px
|
||
*/
|
||
// cgap: number
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 页布局配置
|
||
*/
|
||
interface PageLayoutType {
|
||
/**
|
||
* 查询表单高度,传入数字时,单位:fr,传入字符串时不会而外添加单位,,默认:1fr
|
||
*/
|
||
searchFormHeight: number | string
|
||
/**
|
||
* 数据表格高度,传入数字时,单位:fr,传入字符串时不会而外添加单位,,默认:9fr
|
||
*/
|
||
dataListHeight: number | string
|
||
showHighForm: boolean
|
||
enableHighForm: boolean
|
||
}
|
||
|
||
interface ATablePageType<P extends object, T extends DefaultRow> {
|
||
/**
|
||
* 页布局配置
|
||
*/
|
||
pageLayout: PageLayoutType
|
||
/**
|
||
* 查询表单配置
|
||
*/
|
||
searchForm: FormPropsType<P, T>
|
||
/**
|
||
* 工具栏配置
|
||
*/
|
||
toolBar: ToolBarType
|
||
/**
|
||
* 表格配置
|
||
*/
|
||
table: TablePropsType<T, P>
|
||
}
|
||
|
||
function buildSearchForm<P, T extends DefaultRow>(searchForm: DeepPartial<FormPropsType<P, T>> = {}) {
|
||
if (searchForm.defaultData == null) {
|
||
searchForm.defaultData = {} as DeepPartial<P>
|
||
}
|
||
if (searchForm.highForm == null) {
|
||
searchForm.highForm = {
|
||
labelWidth: 90,
|
||
contentWidth: 200,
|
||
rgap: 10,
|
||
cgap: 10,
|
||
}
|
||
}
|
||
|
||
if (searchForm.highForm.labelWidth == null) searchForm.highForm.labelWidth = 90
|
||
if (searchForm.highForm.contentWidth == null) searchForm.highForm.contentWidth = 200
|
||
if (searchForm.highForm.rgap == null) searchForm.highForm.rgap = 10
|
||
if (searchForm.highForm.cgap == null) searchForm.highForm.cgap = 10
|
||
if (searchForm.simpleForm == null) {
|
||
searchForm.simpleForm = {
|
||
contentWidth: 200,
|
||
colCount: 1,
|
||
// rgap: 10,
|
||
// cgap: 10,
|
||
}
|
||
}
|
||
if (searchForm.simpleForm.colCount == null) searchForm.simpleForm.colCount = 1
|
||
if (searchForm.simpleForm.contentWidth == null) searchForm.simpleForm.contentWidth = 200
|
||
// if (searchForm.simpleForm.rgap == null) searchForm.simpleForm.rgap = 10
|
||
// if (searchForm.simpleForm.cgap == null) searchForm.simpleForm.cgap = 10
|
||
return searchForm
|
||
}
|
||
|
||
function buildPageLayout(pageLayout: DeepPartial<PageLayoutType> = {}) {
|
||
if (pageLayout.searchFormHeight == null) {
|
||
pageLayout.searchFormHeight = 1
|
||
}
|
||
|
||
if (pageLayout.dataListHeight == null) {
|
||
pageLayout.dataListHeight = 9
|
||
}
|
||
|
||
if (pageLayout.showHighForm == null) {
|
||
pageLayout.showHighForm = false
|
||
}
|
||
|
||
if (pageLayout.enableHighForm == null) {
|
||
pageLayout.enableHighForm = true
|
||
}
|
||
|
||
return pageLayout
|
||
}
|
||
|
||
function buildTable<P extends object, T extends object>(table: DeepPartial<TablePropsType<T, P>> = {}) {
|
||
if (table.actionColumn == null) {
|
||
table.actionColumn = {
|
||
width: 80,
|
||
foldLimit: 3,
|
||
tableActions: [],
|
||
}
|
||
}
|
||
if (table.actionColumn.tableActions == null) {
|
||
table.actionColumn.tableActions = []
|
||
}
|
||
for (let tableAction of table.actionColumn.tableActions) {
|
||
if (tableAction.confirm != null) {
|
||
if (tableAction.confirm.cancelButtonText == null) tableAction.confirm.cancelButtonText = '否'
|
||
if (tableAction.confirm.confirmButtonText == null) tableAction.confirm.confirmButtonText = '是'
|
||
if (tableAction.confirm.width == null) tableAction.confirm.width = '180'
|
||
}
|
||
if (tableAction.type == null) {
|
||
tableAction.type = 'primary'
|
||
}
|
||
}
|
||
if (table.actionColumn.foldLimit == null) {
|
||
table.actionColumn.foldLimit = 3
|
||
}
|
||
|
||
if (table.actionColumn.width == null) {
|
||
table.actionColumn.width = Math.min(table.actionColumn.tableActions.length, table.actionColumn.foldLimit) * 50 + 10
|
||
}
|
||
|
||
if (table.emptyText == null) {
|
||
table.emptyText = '暂无数据'
|
||
}
|
||
if (table.rowKey == null) {
|
||
table.rowKey = 'id'
|
||
}
|
||
|
||
return table
|
||
}
|
||
|
||
function buildToolBar(toolBar: DeepPartial<ToolBarType> = {}) {
|
||
if (toolBar.leftTools == null) toolBar.leftTools = []
|
||
for (let leftTool of toolBar.leftTools) {
|
||
if (leftTool.type == null) {
|
||
leftTool.type = 'primary'
|
||
}
|
||
}
|
||
if (toolBar.rightTools == null) toolBar.rightTools = []
|
||
|
||
return toolBar
|
||
}
|
||
|
||
export function buildTablePageProps<P extends G.PageParam, T extends DefaultRow>({pageLayout, searchForm, toolBar, table}: DeepPartial<ATablePageType<P, T>>) {
|
||
return reactive({
|
||
pageLayout: buildPageLayout(pageLayout),
|
||
searchForm: buildSearchForm(searchForm),
|
||
toolBar: buildToolBar(toolBar),
|
||
table: buildTable(table),
|
||
})
|
||
}
|
||
|
||
const component = defineComponent(
|
||
<P extends G.PageParam, T extends DefaultRow>(props: ATablePageType<P, T>, {slots, expose}: SetupContext) => {
|
||
const formData = Utils.resetAble(reactive<P>({
|
||
...(props.searchForm.defaultData),
|
||
current: 1,
|
||
size: 20,
|
||
})) as ResetAble<P>
|
||
const tableData = Utils.resetAble(reactive<T[]>([])) as ResetAble<T[]>
|
||
|
||
const totalCount = ref(0)
|
||
const loading = ref<boolean>(false)
|
||
const showHighForm = ref<boolean>(props.pageLayout.showHighForm)
|
||
|
||
const doSearch = () => {
|
||
loading.value = true
|
||
if (props.searchForm.paging != null) {
|
||
props.searchForm.paging(formData.$clone() as P)
|
||
.then(res => {
|
||
totalCount.value = res.data?.total ?? 0
|
||
const records = res.data?.records ?? ([] as T[])
|
||
tableData.$reset(records)
|
||
})
|
||
.finally(() => {
|
||
loading.value = false
|
||
})
|
||
return
|
||
}
|
||
}
|
||
expose({doSearch})
|
||
const showHighFormHandle = () => {
|
||
showHighForm.value = !showHighForm.value
|
||
formData.$reset()
|
||
}
|
||
const doExport = () => {
|
||
if (props.searchForm.export == null) {
|
||
return
|
||
}
|
||
loading.value = true
|
||
saveFile(props.searchForm.export(formData.$clone() as P))
|
||
.finally(() => {
|
||
loading.value = false
|
||
})
|
||
}
|
||
const rowAction = (data: ColumnScopeType<T>, action: TableActionType<T>) => {
|
||
if (action.loading != null) {
|
||
action.loading = true
|
||
}
|
||
const result = action.action(data)
|
||
if (result instanceof Promise) {
|
||
result
|
||
.then(reload => {
|
||
if (reload) {
|
||
doSearch()
|
||
}
|
||
})
|
||
.finally(() => {
|
||
if (action.loading != null) {
|
||
action.loading = false
|
||
}
|
||
})
|
||
}
|
||
}
|
||
|
||
function doReset() {
|
||
formData.$reset()
|
||
doSearch()
|
||
}
|
||
|
||
const highFormCssParam = computed(() => {
|
||
const labelWidth = props.searchForm.highForm.labelWidth
|
||
const contentWidth = props.searchForm.highForm.contentWidth
|
||
return {
|
||
'--item-min-width': (labelWidth + contentWidth) + 'px',
|
||
'--rgap': props.searchForm.highForm.rgap + 'px',
|
||
'--cgap': props.searchForm.highForm.cgap + 'px',
|
||
}
|
||
})
|
||
|
||
const toolBarRightCssParam = computed(() => {
|
||
const colCount = props.searchForm.simpleForm.colCount
|
||
const contentWidth = props.searchForm.simpleForm.contentWidth
|
||
const btnCount = props.toolBar.rightTools.length + (props.searchForm.export == null ? 0 : 1) + (props.pageLayout.enableHighForm ? 1 : 0)
|
||
return {
|
||
'--form-item-count': colCount,
|
||
'--form-item-width': contentWidth + 'px',
|
||
// '--rgap': props.searchForm.simpleForm.rgap + 'px',
|
||
// '--cgap': props.searchForm.simpleForm.cgap + 'px',
|
||
'--btn-count': btnCount,
|
||
}
|
||
})
|
||
|
||
const pageCssParam = computed(() => {
|
||
const dataListHeight = props.pageLayout.dataListHeight
|
||
const searchFormHeight = props.pageLayout.searchFormHeight
|
||
return {
|
||
'--data-list-height': Types.isString(dataListHeight) ? dataListHeight : dataListHeight + 'fr',
|
||
'--search-form-height': Types.isString(searchFormHeight) ? searchFormHeight : searchFormHeight + 'fr',
|
||
}
|
||
})
|
||
const actionColumnBtnRender = (scope: ColumnScopeType<T>, tableAction: TableActionType<T>) => {
|
||
let elIcon: any | undefined = undefined
|
||
if (iconNames.includes(tableAction.icon as IconName)) {
|
||
elIcon = <AIcon name={tableAction.icon as IconName}/>
|
||
} else if (Object.keys(elIcons).includes(tableAction.icon as unknown as string)) {
|
||
elIcon = elIcons[tableAction.icon as ElIconType]
|
||
}
|
||
const tooltipTxt = tableAction.tooltip == null ? '' : (typeof tableAction.tooltip === 'function' ? tableAction.tooltip(scope) : tableAction.tooltip)
|
||
if (!Strings.isBlank(tooltipTxt)) {
|
||
return (<ElTooltip content={tooltipTxt} placement="top">
|
||
<ElButton
|
||
icon={elIcon}
|
||
loading={tableAction.loading}
|
||
type={tableAction.type}
|
||
class={styles.iconBtn}
|
||
onClick={tableAction.confirm == null ? () => rowAction(scope, tableAction) : undefined}
|
||
plain/>
|
||
</ElTooltip>)
|
||
}
|
||
return (<ElButton
|
||
icon={elIcon}
|
||
loading={tableAction.loading}
|
||
type={tableAction.type}
|
||
class={styles.iconBtn}
|
||
onClick={tableAction.confirm == null ? () => rowAction(scope, tableAction) : undefined}
|
||
text/>)
|
||
}
|
||
const actionColumnRender = () => {
|
||
const actionColumn = props.table.actionColumn
|
||
if (Colls.isEmpty(actionColumn.tableActions)) return (<></>)
|
||
return (<ElTableColumn width={actionColumn.width + 'px'} fixed="right" label="操作" prop="tableAction">
|
||
{{
|
||
default: (scope: ColumnScopeType<T>) => {
|
||
const len = actionColumn.tableActions.filter(it => it.show == null || it.show(scope)).length
|
||
let btns: any[]
|
||
if (len <= actionColumn.foldLimit) {
|
||
btns = (actionColumn.tableActions
|
||
.filter(it => (it.show == null ? true : it.show(scope)))
|
||
.map((tableAction, i) => (tableAction.confirm != null ?
|
||
(<ElPopconfirm
|
||
key={'action-btn-' + i}
|
||
cancel-button-text={tableAction.confirm.cancelButtonText}
|
||
confirm-button-text={tableAction.confirm.confirmButtonText}
|
||
title={typeof tableAction.confirm.title === 'function' ? tableAction.confirm.title(scope) : tableAction.confirm.title}
|
||
width={tableAction.confirm.width}
|
||
cancel-button-type="primary"
|
||
confirm-button-type="danger"
|
||
onConfirm={() => rowAction(scope, tableAction)}>
|
||
{{
|
||
reference: () => (<div>
|
||
{actionColumnBtnRender(scope, tableAction)}
|
||
</div>),
|
||
}}
|
||
</ElPopconfirm>) : actionColumnBtnRender(scope, tableAction)))
|
||
)
|
||
} else {
|
||
btns = (actionColumn.tableActions
|
||
.filter(it => (it.show == null ? true : it.show(scope)))
|
||
.filter((_, i) => i < actionColumn.foldLimit - 1)
|
||
.map((tableAction, i) => (tableAction.confirm != null ?
|
||
(<ElPopconfirm
|
||
key={'action-btn-' + i}
|
||
cancel-button-text={tableAction.confirm.cancelButtonText}
|
||
confirm-button-text={tableAction.confirm.confirmButtonText}
|
||
title={typeof tableAction.confirm.title === 'function' ? tableAction.confirm.title(scope) : tableAction.confirm.title}
|
||
width={tableAction.confirm.width}
|
||
cancel-button-type="primary"
|
||
confirm-button-type="danger"
|
||
onConfirm={() => rowAction(scope, tableAction)}>
|
||
{{
|
||
reference: () => (<div>
|
||
{actionColumnBtnRender(scope, tableAction)}
|
||
</div>),
|
||
}}
|
||
</ElPopconfirm>) : actionColumnBtnRender(scope, tableAction)))
|
||
)
|
||
btns.push(<ElDropdown onCommand={(cmd) => {
|
||
const tableAction = actionColumn.tableActions[cmd]
|
||
if (tableAction.confirm != null) {
|
||
ElMessageBox.confirm(
|
||
typeof tableAction.confirm.title === 'function' ? tableAction.confirm.title(scope) : tableAction.confirm.title,
|
||
'操作提示',
|
||
{
|
||
confirmButtonText: tableAction.confirm.confirmButtonText,
|
||
cancelButtonText: tableAction.confirm.cancelButtonText,
|
||
confirmButtonType: 'primary',
|
||
cancelButtonType: 'danger',
|
||
type: 'warning',
|
||
},
|
||
)
|
||
.then(() => {
|
||
rowAction(scope, tableAction)
|
||
})
|
||
.catch(() => {
|
||
})
|
||
return
|
||
}
|
||
rowAction(scope, tableAction)
|
||
}}>
|
||
{{
|
||
default: () => (<ElButton icon={elIcons.More} class={[ styles.iconBtn, styles.moreIcon ]} text/>),
|
||
dropdown: () => (<ElDropdownMenu>
|
||
{
|
||
actionColumn.tableActions
|
||
.filter(it => (it.show == null ? true : it.show(scope)))
|
||
.filter((_, i) => i >= actionColumn.foldLimit - 1)
|
||
.map((it, i) => {
|
||
let elIcon: any | undefined = undefined
|
||
if (iconNames.includes(it.icon as IconName)) {
|
||
elIcon = <AIcon name={it.icon as IconName}/>
|
||
} else if (Object.keys(elIcons).includes(it.icon as unknown as string)) {
|
||
elIcon = elIcons[it.icon as ElIconType]
|
||
}
|
||
return (
|
||
<ElDropdownItem key={'action-btn-' + i} command={i + 2} icon={elIcon}>
|
||
{typeof it.tooltip === 'function' ? it.tooltip(scope) : it.tooltip}
|
||
</ElDropdownItem>
|
||
)
|
||
})
|
||
}
|
||
</ElDropdownMenu>),
|
||
}}
|
||
</ElDropdown>)
|
||
}
|
||
return (<div class={styles.actionBtn}>
|
||
{btns}
|
||
</div>)
|
||
},
|
||
}}
|
||
</ElTableColumn>)
|
||
}
|
||
const sortChangeHandler = ({prop, order}: { prop: string, order: 'ascending' | 'descending' | null }) => {
|
||
formData.orders = order == null ? undefined : (prop + ':' + (order == 'ascending' ? 'asc' : 'desc'))
|
||
doSearch()
|
||
}
|
||
onMounted(doSearch)
|
||
return () => (<APage class={[ styles.tablePage, showHighForm.value ? '' : styles.folder ]} style={pageCssParam.value}>
|
||
<div class={styles.searchFormWrapper} style={highFormCssParam.value}>
|
||
{props.pageLayout.enableHighForm ? (<ElScrollbar>
|
||
{/*@ts-ignore*/}
|
||
<ElForm class={styles.searchForm} onSubmit={withModifiers(doSearch, [ 'prevent' ])} labelWidth={props.searchForm.highForm.labelWidth + 'px'}>
|
||
{
|
||
slots.highFormItem?.(formData)
|
||
}
|
||
<button style="display: none" type="submit"/>
|
||
</ElForm>
|
||
</ElScrollbar>) : <></>}
|
||
</div>
|
||
<div class={styles.dataList}>
|
||
<div class={styles.toolBar}>
|
||
<div class={styles.toolBarLeft}>
|
||
{
|
||
props.toolBar.leftTools.map((tool, i) => (
|
||
<ElButton key={'tool-bar-left-' + i}
|
||
icon={Strings.isBlank(tool.icon) ? undefined : elIcons[tool.icon!]}
|
||
type={tool.type}
|
||
onClick={tool.action}>
|
||
{tool.label}
|
||
</ElButton>
|
||
))
|
||
}
|
||
</div>
|
||
<div class={styles.toolBarRight} style={toolBarRightCssParam.value}>
|
||
<ElScrollbar>
|
||
{/*@ts-ignore*/}
|
||
<ElForm onSubmit={withModifiers(doSearch, [ 'prevent' ])}>
|
||
{
|
||
slots.simpleFormItem?.(formData)
|
||
}
|
||
<button style="display: none" type="submit"/>
|
||
</ElForm>
|
||
</ElScrollbar>
|
||
<div>
|
||
<ElTooltip content="搜索" placement="top">
|
||
<ElDropdown split-button onClick={doSearch} onCommand={(command: string) => {
|
||
if (command === 'reset') {
|
||
doReset()
|
||
}
|
||
}}>
|
||
{{
|
||
default: () => (<ElButton icon={elIcons.Search} loading={loading.value} type="default"/>),
|
||
dropdown: () => (<ElDropdownMenu>
|
||
<ElDropdownItem icon={elIcons.Refresh} command="reset">重置并刷新</ElDropdownItem>
|
||
</ElDropdownMenu>),
|
||
}}
|
||
</ElDropdown>
|
||
</ElTooltip>
|
||
{
|
||
props.toolBar.rightTools.map((tool, i) => (
|
||
<ElButton key={'tool-bar-right-' + i}
|
||
icon={elIcons[tool.icon]}
|
||
onClick={tool.action}/>
|
||
))
|
||
}
|
||
{
|
||
props.searchForm.export == null ? <></> : (<ElTooltip content="导出" placement="top">
|
||
<ElButton icon={elIcons.Download} loading={loading.value} type="default" onClick={doExport}/>
|
||
</ElTooltip>)
|
||
}
|
||
{
|
||
props.pageLayout.enableHighForm ? (<ElTooltip
|
||
content={showHighForm.value ? '关闭高级搜索' : '打开高级搜索'} placement="top">
|
||
<ElButton class={showHighForm.value ? styles.filterBtnActive : ''} icon={elIcons.Filter} type="default" onClick={showHighFormHandle}/>
|
||
</ElTooltip>) : <></>}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
{
|
||
withDirectives(<ElTable
|
||
data={tableData}
|
||
empty-text={props.table.emptyText}
|
||
row-key={props.table.rowKey}
|
||
ref="dataTable"
|
||
lazy={props.table.treeLoad == null ? undefined : true}
|
||
load={props.table.treeLoad ? ((row, expanded, resolve) => props.table.treeLoad!(formData as P, row, expanded, resolve)) : undefined}
|
||
onExpand-change={props.table.treeLoad ? ((row: any, expandedRows: any) => props.table.treeLoad!(formData as P, row, expandedRows, undefined)) : undefined}
|
||
cell-class-name="table-cell"
|
||
header-row-class-name="table-header"
|
||
class="data-table"
|
||
onSort-change={sortChangeHandler}
|
||
>
|
||
{
|
||
slots.columns?.()
|
||
}
|
||
{
|
||
actionColumnRender()
|
||
}
|
||
</ElTable>, [ [ ElLoading.directive, loading.value ] ])
|
||
}
|
||
<ElPagination
|
||
current-page={(formData as G.PageParam).current}
|
||
page-size={(formData as G.PageParam).size}
|
||
onUpdate:current-page={(val) => (formData as G.PageParam).current = val}
|
||
onUpdate:page-size={(val) => (formData as G.PageParam).size = val}
|
||
hide-on-single-page={false}
|
||
page-sizes={[ 10, 20, 50, 100, 500 ]}
|
||
teleported={false}
|
||
total={totalCount.value}
|
||
background={true}
|
||
layout="total, prev, pager, next, sizes, jumper"
|
||
onChange={doSearch}/>
|
||
{
|
||
slots?.default?.()
|
||
}
|
||
</div>
|
||
</APage>)
|
||
},
|
||
{
|
||
name: 'ATablePage',
|
||
props: [ 'pageLayout', 'searchForm', 'toolBar', 'table' ],
|
||
},
|
||
)
|
||
|
||
export interface ATablePageInstance extends InstanceType<typeof component> {
|
||
doSearch: () => void
|
||
}
|
||
|
||
export default component
|