263 lines
6.8 KiB
Vue
263 lines
6.8 KiB
Vue
<!--
|
|
* @Author: zhaojinfeng 121016171@qq.com
|
|
* @Date: 2023-07-18 12:30:07
|
|
* @LastEditors: zhaojinfeng 121016171@qq.com
|
|
* @LastEditTime: 2023-08-16 11:45:31
|
|
* @FilePath: \vue3\packages\select-table-modal\index.vue
|
|
* @Description: 模态框选择表格
|
|
*
|
|
-->
|
|
<template>
|
|
<span v-if="!hideButton" @click="open">
|
|
<slot>
|
|
<el-button type="primary" plain>点击选择</el-button>
|
|
</slot>
|
|
</span>
|
|
<el-config-provider :locale="locale">
|
|
<el-dialog v-model="showDialog" :title="title" :width="width" append-to-body :z-index="zIndex" @open="getList" @closed="closed">
|
|
<el-form ref="queryRef" :model="queryParams" inline>
|
|
<el-form-item v-for="formItem in formItems" :key="formItem.prop" :label="formItem.label" :prop="formItem.prop">
|
|
<el-select v-if="formItem.selectOptions" :placeholder="formItem.placeholder">
|
|
<el-option v-for="option in formItem.selectOptions" :key="option.value" :value="option.value">
|
|
{{ option.label }}
|
|
</el-option>
|
|
</el-select>
|
|
<el-input v-else v-model="queryParams[formItem.prop]" :placeholder="formItem.placeholder" />
|
|
</el-form-item>
|
|
<el-form-item>
|
|
<el-button type="primary" :loading="loading" @click="getList">
|
|
查询
|
|
</el-button>
|
|
<el-button :loading="loading" @click="resetQuery">
|
|
重置
|
|
</el-button>
|
|
</el-form-item>
|
|
</el-form>
|
|
<el-table
|
|
v-loading="loading"
|
|
border
|
|
:data="tableData"
|
|
highlight-current-row
|
|
:row-key="rowKey"
|
|
:empty-text="emptyText"
|
|
:reserve-selection="multiple"
|
|
@current-change="handleCurrentChange"
|
|
@selection-change="handleSelectionChange"
|
|
>
|
|
<el-table-column v-if="multiple" type="selection" width="55" align="center" />
|
|
<el-table-column
|
|
v-for="column in columns"
|
|
:key="column.prop"
|
|
:align="column.align || 'center'"
|
|
:label="column.label"
|
|
:prop="column.prop"
|
|
:formatter="column.formatter"
|
|
>
|
|
<template v-if="isExist(column.prop)" #default="{ row, $index }">
|
|
<!-- element自带的属性$index -->
|
|
<!-- eslint-disable-next-line vue/valid-attribute-name -->
|
|
<slot :name="`column-${column.prop}`" :row="row" :$index="$index" />
|
|
</template>
|
|
</el-table-column>
|
|
</el-table>
|
|
<div w-full h-70px relative>
|
|
<el-pagination
|
|
v-model:current-page="queryParams.pageNum"
|
|
v-model:page-size="queryParams.pageSize"
|
|
absolute
|
|
right-50px
|
|
top-20px
|
|
background
|
|
hide-on-single-page
|
|
:layout="layout"
|
|
:page-sizes="pageSizes"
|
|
:pager-count="pagerCount"
|
|
:total="total"
|
|
@size-change="handleSizeChange"
|
|
@current-change="getList"
|
|
/>
|
|
</div>
|
|
<template #footer>
|
|
<el-space>
|
|
<el-button :disabled="disabled" type="primary" @click="confirm">
|
|
确定
|
|
</el-button>
|
|
<el-button @click="showDialog = false">
|
|
取消
|
|
</el-button>
|
|
</el-space>
|
|
</template>
|
|
</el-dialog>
|
|
</el-config-provider>
|
|
</template>
|
|
|
|
<script lang="ts" setup name="ThSelectTableModal">
|
|
import type { FormInstance, TableColumnCtx, TableInstance } from 'element-plus'
|
|
import locale from 'element-plus/lib/locale/lang/zh-cn'
|
|
|
|
const props = withDefaults(
|
|
defineProps<{
|
|
emptyText?: string
|
|
value?: any
|
|
rowKey?: string
|
|
show?: boolean
|
|
columns: Partial<TableColumnCtx<any>>[]
|
|
formItems: FormItem[]
|
|
defaultParams?: Record<string, any>
|
|
request: (args: any) => Promise<Page>
|
|
layout?: string
|
|
pageSizes?: number[]
|
|
pagerCount?: number
|
|
hideButton?: boolean
|
|
hidePagination?: boolean
|
|
title?: string
|
|
width?: string | number
|
|
/** 是否多选 */
|
|
multiple?: boolean
|
|
zIndex?: number
|
|
/** 单击确认按钮后的数据格式化函数 */
|
|
formattter?: (row: Record<string, any>) => any
|
|
}>(),
|
|
{
|
|
hidePagination: false,
|
|
layout: 'total, sizes, prev, pager, next, jumper',
|
|
rowKey: 'id',
|
|
pageSizes: () => [10, 20, 30, 50],
|
|
pagerCount: () => document.body.clientWidth < 992 ? 5 : 7,
|
|
hideButton: false,
|
|
width: '1000px',
|
|
title: '选择',
|
|
emptyText: '暂无数据',
|
|
zIndex: 2023,
|
|
formattter: (row: Record<string, any>) => {
|
|
return { ...row }
|
|
},
|
|
},
|
|
)
|
|
const emit = defineEmits<{
|
|
(event: 'update:show', show: boolean): void
|
|
(event: 'update:value', show: any): void
|
|
(event: 'confirm', row: any): void
|
|
}>()
|
|
|
|
const showDialog = ref(false)
|
|
|
|
const slots = Object.keys(useSlots())
|
|
|
|
function isExist(prop: string) {
|
|
return slots.includes(`column-${prop}`)
|
|
}
|
|
|
|
let tableData = $ref<any[]>([])
|
|
let selection = $ref<any>()
|
|
let selections = $ref<Record<string, any>[] | null>(null)
|
|
|
|
const disabled = computed(() => {
|
|
if (props.multiple)
|
|
return !selections?.length
|
|
|
|
return !selection
|
|
})
|
|
|
|
function open() {
|
|
if (props.hideButton)
|
|
emit('update:show', true)
|
|
else
|
|
showDialog.value = true
|
|
}
|
|
|
|
let total = $ref(0)
|
|
|
|
function handleCurrentChange(val?: any) {
|
|
selection = val
|
|
}
|
|
|
|
/* 表单绑定的ref */
|
|
const queryRef = $ref<FormInstance>(null)
|
|
const tableRef = $ref<TableInstance>(null)
|
|
|
|
/* 初始加载 */
|
|
let loading = $ref(false)
|
|
|
|
/* 查询参数 */
|
|
const queryParams = reactive({
|
|
pageNum: 1,
|
|
pageSize: 10,
|
|
})
|
|
|
|
function initSelections() {
|
|
const rows = tableData.map(props.formattter)
|
|
tableRef?.toggleRowSelection(rows, true)
|
|
}
|
|
function initSelection() {
|
|
const row = tableData.find(row => row[props.rowKey] === props.value)
|
|
if (row)
|
|
tableRef?.setCurrentRow(row)
|
|
}
|
|
|
|
/** 查询表格数据 */
|
|
async function getList() {
|
|
loading = true
|
|
tableData = []
|
|
try {
|
|
const response = await props.request({
|
|
...props.defaultParams,
|
|
...queryParams,
|
|
})
|
|
tableData = response.rows
|
|
total = response.total
|
|
if (props.multiple)
|
|
initSelections()
|
|
|
|
else
|
|
initSelection()
|
|
}
|
|
finally {
|
|
loading = false
|
|
}
|
|
}
|
|
|
|
/** 多选框选中数据 */
|
|
function handleSelectionChange(rows: any[]) {
|
|
selections = rows.map(props.formattter)
|
|
}
|
|
function confirm() {
|
|
if (props.multiple) {
|
|
emit('confirm', selections)
|
|
emit('update:value', selections)
|
|
}
|
|
else {
|
|
emit('confirm', selection)
|
|
emit('update:value', selection && selection[props.rowKey])
|
|
}
|
|
|
|
if (props.hideButton)
|
|
emit('update:show', false)
|
|
else
|
|
showDialog.value = false
|
|
}
|
|
|
|
/** 重置按钮操作 */
|
|
function resetQuery() {
|
|
queryRef?.resetFields()
|
|
queryParams.pageNum = 1
|
|
getList()
|
|
}
|
|
function handleSizeChange(val: number) {
|
|
if (queryParams.pageNum * val > total)
|
|
queryParams.pageNum = 1
|
|
}
|
|
|
|
function closed() {
|
|
queryRef?.resetFields()
|
|
tableData = []
|
|
queryParams.pageNum = 1
|
|
selection = undefined
|
|
}
|
|
|
|
watch(() => props.show,
|
|
(show) => {
|
|
showDialog.value = show
|
|
})
|
|
</script>
|