Appearance
DataPickerTable 表格选择器
基于弹窗表格的选择器组件,点击后弹出 DataTable 供用户选择。支持单选/多选、分页搜索、标签展示、自定义触发等。
在线演示
tsx
import { defineComponent, ref } from 'vue'
import { ElMessage as message } from 'element-plus'
import DataPickerTable from '@/components/DataPickerTable'
export default defineComponent({
name: 'DemoDataPickerTableFull',
setup() {
const single = ref<any>(null)
const multiple = ref<any[]>([])
const mockData = Array.from({ length: 30 }, (_, i) => ({
id: i + 1,
code: `P${String(i + 1).padStart(4, '0')}`,
name: `商品${i + 1}`,
category: ['电子产品', '办公用品', '食品饮料', '家居用品'][i % 4],
price: +(Math.random() * 10000).toFixed(2),
stock: Math.floor(Math.random() * 1000),
}))
const columns: any[] = [
{ label: '编号', field: 'code', width: 100 },
{ label: '名称', field: 'name', minWidth: 140 },
{ label: '分类', field: 'category', width: 100 },
{ label: '单价', field: 'price', type: 'money', width: 110 },
{ label: '库存', field: 'stock', width: 80 },
]
const query = (params: any) => {
const { page, pageSize, keyword } = params
let filtered = mockData
if (keyword) {
filtered = mockData.filter((r) => r.name.includes(keyword) || r.code.includes(keyword))
}
const start = (page - 1) * pageSize
return Promise.resolve({
totalRows: filtered.length,
rows: filtered.slice(start, start + pageSize),
})
}
return () => (
<div style="display:flex;flex-direction:column;gap:24px;">
<div class="demo-block">
<h4 style="margin:0 0 12px;font-size:15px;">🔘 单选</h4>
<DataPickerTable
modelValue={single.value}
onUpdate:modelValue={(val: any) => (single.value = val)}
label="选择商品"
labelKey="name"
columns={columns}
query={query}
searchFields={[
{ label: '关键词', field: 'keyword', type: 'el-input', props: { placeholder: '搜索名称/编号' } },
]}
tableProps={{ height: 320 }}
/>
<div style="margin-top:8px;font-size:13px;color:#666;font-family:monospace;">
选中:{JSON.stringify(single.value)}
</div>
</div>
<div class="demo-block">
<h4 style="margin:0 0 12px;font-size:15px;">🔘 多选(标签模式)</h4>
<DataPickerTable
modelValue={multiple.value}
onUpdate:modelValue={(val: any) => (multiple.value = val)}
label="选择商品(多选)"
labelKey="name"
columns={columns}
query={query}
multiple
mode="tags"
tableProps={{ height: 320 }}
/>
<div style="margin-top:8px;font-size:13px;color:#666;font-family:monospace;">
选中:{JSON.stringify(multiple.value)}
</div>
</div>
</div>
)
},
})Props
| 属性名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| modelValue | any | - | 选中值(v-model) |
| columns | TableColumn[] | - | 必填。弹窗表格列配置 |
| query | (params) => Promise<Result> | - | 必填。弹窗表格数据查询函数 |
| label | string | - | 触发器前的标签 |
| multiple | boolean | false | 是否多选 |
| searchFields | FormColumn[] | - | 弹窗内的搜索栏字段配置 |
| keywordField | string | 'keyword' | 搜索时传递关键词的字段名 |
| mode | 'tags' | 'input' | 'tags' | 多选展示模式:标签/文本 |
| placeholder | string | '请选择' | 占位文本 |
| allowClear | boolean | true | 是否可清除 |
| disabled | boolean | false | 是否禁用 |
| rowKey | string | 'id' | 行唯一标识 |
| labelKey | string | 'label' | 显示的 label 字段 |
| valueKey | string | 'id' | 绑定的 value 字段 |
| labelToModel | string | - | 将选中项的 label 同步到 model 的指定字段 |
| width | string | number | '100%' | 触发器宽度 |
| popoverWidth | string | number | 500 | 弹窗宽度 |
| tableProps | Object | - | 透传 DataTable 的其他属性 |
示例:在 DataForm 中使用
ts
const columns = [
{
label: '关联商品',
field: 'productId',
type: 'data-picker-table',
props: {
columns: [
{ label: '编号', field: 'code', width: 100 },
{ label: '名称', field: 'name', minWidth: 140 },
{ label: '单价', field: 'price', type: 'money', width: 110 },
],
query: (params) => fetch('/api/products', { body: JSON.stringify(params) }).then(r => r.json()),
multiple: false,
},
},
]