119 lines
3.4 KiB
Vue
119 lines
3.4 KiB
Vue
<template>
|
|
<!-- 表格 -->
|
|
<Table :columns="columns" :data="list" :height="tableH" :loading="loading" no-data-text="暂无数据"
|
|
class="link-table table-bottom-box" @on-selection-change="selectChange">
|
|
<template #loading>
|
|
<div class="table-spin-load">加载中</div>
|
|
</template>
|
|
</Table>
|
|
|
|
<!-- 分页 / 插槽 -->
|
|
<div class="page-panel">
|
|
<div class="fl ml-15 align-middle">
|
|
<slot :checkList="selectList" />
|
|
</div>
|
|
|
|
<Page class="page-box fr" :total="total" :model-value="page" :page-size="pageSize"
|
|
:page-size-opts="[10, 20, 30, 40]" show-total show-sizer placement="top" @on-change="onPageChange"
|
|
@on-page-size-change="onSizeChange" />
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { computed, ref, onMounted } from 'vue'
|
|
import { Message } from 'view-ui-plus'
|
|
import Utils from '@/utils'
|
|
import { OperatorEnum } from '@/types'
|
|
|
|
interface Props {
|
|
/** 必填:alova-gen 生成的 selectTextbook 方法(或任意同形方法) */
|
|
dataApi: any
|
|
columns: any[]
|
|
dataParams: any
|
|
tableHeight?: number
|
|
autoLoad?: boolean
|
|
dataFilter?: (resp: any) => any[],
|
|
formatResponse?: (res: any) => { total: number; list: any[] }
|
|
}
|
|
const props = withDefaults(defineProps<Props>(), {
|
|
autoLoad: true,
|
|
formatResponse: (res: any) => ({ total: res.total, list: res.content })
|
|
})
|
|
|
|
const emit = defineEmits<{
|
|
(e: 'selection-change', list: number[]): void
|
|
}>()
|
|
|
|
onMounted(() => {
|
|
})
|
|
|
|
/* ---------------- 表格高度 ---------------- */
|
|
const tableH = ref(props.tableHeight ?? Utils.useTableHeight())
|
|
|
|
/* ---------------- 选中行 ---------------- */
|
|
const selectList = ref<number[]>([])
|
|
function selectChange(rows: any[]) {
|
|
selectList.value = rows.map((r: any) => r.id)
|
|
emit('selection-change', selectList.value)
|
|
}
|
|
|
|
/* ---------------- 分页 + 请求 ---------------- */
|
|
const {
|
|
loading,
|
|
data: resp,
|
|
send: sendLoad,
|
|
page,
|
|
pageSize,
|
|
total,
|
|
reload
|
|
} = usePagination(
|
|
(current: number, size: number) =>
|
|
props.dataApi({
|
|
...props.dataParams, // 合并外部条件
|
|
pageIndex: current,
|
|
pageSize: size,
|
|
}),
|
|
{
|
|
// total: res => res.total,
|
|
// data: res => res.list,
|
|
total: res => props.formatResponse(res).total,
|
|
data: res => props.formatResponse(res).list,
|
|
// 默认分页参数
|
|
initialPage: 1,
|
|
initialPageSize: 10,
|
|
immediate: props.autoLoad,
|
|
watchingStates: [() => props.dataParams]
|
|
}
|
|
)
|
|
/* 列表数据 */
|
|
const list = computed(() => {
|
|
if (!resp.value) return []
|
|
return props.dataFilter ? props.dataFilter(resp.value) : resp.value
|
|
})
|
|
|
|
/* ---------------- 翻页事件 ---------------- */
|
|
const onPageChange = (p: number) => (page.value = p)
|
|
const onSizeChange = (s: number) => (pageSize.value = s)
|
|
|
|
/* ---------------- 外部可调用 ---------------- */
|
|
function refreshData() {
|
|
page.value = 1
|
|
reload()
|
|
}
|
|
function reloadData(type: OperatorEnum = OperatorEnum.sel) {
|
|
let p = page.value
|
|
const s = pageSize.value
|
|
|
|
if (type === OperatorEnum.add && p * s === total.value) p += 1
|
|
if (type === OperatorEnum.del && (p - 1) * s + 1 === total.value) p -= 1
|
|
if (p < 1) p = 1
|
|
page.value = p
|
|
sendLoad()
|
|
}
|
|
|
|
defineExpose({ list, refreshData, reloadData })
|
|
</script>
|
|
|
|
<style scoped>
|
|
/* 沿用旧样式即可 */
|
|
</style> |