feat(ui): YkStaffDetailModal shared detail-modal component
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,88 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, watch } from 'vue'
|
||||
import type { Page } from '@/api/types'
|
||||
|
||||
/**
|
||||
* 通用明细 modal —— 复刻云客"统计数字点击弹明细表"。
|
||||
* 调用方传 fetcher(返回 Page<T>)+ 列定义;组件负责 dialog/table/pagination。
|
||||
*/
|
||||
interface Col {
|
||||
prop: string
|
||||
label: string
|
||||
width?: number | string
|
||||
minWidth?: number | string
|
||||
align?: 'left' | 'center' | 'right'
|
||||
}
|
||||
const props = defineProps<{
|
||||
modelValue: boolean
|
||||
title: string
|
||||
cols: Col[]
|
||||
/** fetcher(page, page_size) → Page<T>。宽松 Page<any>:Customer 无 index signature,
|
||||
* 不可直接赋 Page<Record<string,unknown>>,故用 any 接纳 Page<Customer> 等。 */
|
||||
fetcher: (page: number, page_size: number) => Promise<Page<any>>
|
||||
pageSizes?: number[]
|
||||
}>()
|
||||
const emit = defineEmits<{ 'update:modelValue': [boolean] }>()
|
||||
|
||||
const loading = ref(false)
|
||||
const items = ref<any[]>([])
|
||||
const total = ref(0)
|
||||
const page = ref(1)
|
||||
const pageSize = ref(props.pageSizes?.[0] ?? 10)
|
||||
|
||||
async function load() {
|
||||
loading.value = true
|
||||
try {
|
||||
const res = await props.fetcher(page.value, pageSize.value)
|
||||
items.value = res.items
|
||||
total.value = res.total
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
(open) => {
|
||||
if (open) {
|
||||
page.value = 1
|
||||
load()
|
||||
}
|
||||
},
|
||||
)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<el-dialog
|
||||
:model-value="modelValue"
|
||||
:title="title"
|
||||
width="900px"
|
||||
@update:model-value="emit('update:modelValue', $event)"
|
||||
>
|
||||
<el-table v-loading="loading" :data="items" border style="width: 100%" size="small">
|
||||
<el-table-column
|
||||
v-for="c in cols"
|
||||
:key="c.prop"
|
||||
:prop="c.prop"
|
||||
:label="c.label"
|
||||
:width="c.width"
|
||||
:min-width="c.minWidth"
|
||||
:align="c.align"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
</el-table>
|
||||
<div style="margin-top: 10px; display: flex; justify-content: flex-end">
|
||||
<el-pagination
|
||||
:current-page="page"
|
||||
:page-size="pageSize"
|
||||
:page-sizes="pageSizes ?? [10, 20, 50]"
|
||||
:total="total"
|
||||
layout="total, sizes, prev, pager, next"
|
||||
background
|
||||
size="small"
|
||||
@current-change="(p: number) => { page = p; load() }"
|
||||
@size-change="(s: number) => { pageSize = s; page = 1; load() }"
|
||||
/>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</template>
|
||||
Reference in New Issue
Block a user