Files
front/src/views/list/search-table/demo.vue
2026-03-07 20:11:25 +08:00

327 lines
7.7 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<div class="container">
<Breadcrumb :items="['menu.list', '公共组件Demo']" />
<!-- 使用 SearchTable 公共组件 -->
<SearchTable
:form-model="formModel"
:form-items="formItems"
:data="tableData"
:columns="columns"
:loading="loading"
:pagination="pagination"
title="公共组件演示"
search-button-text="查询"
reset-button-text="重置"
download-button-text="导出"
refresh-tooltip-text="刷新数据"
density-tooltip-text="表格密度"
column-setting-tooltip-text="列设置"
@search="handleSearch"
@reset="handleReset"
@page-change="handlePageChange"
@refresh="handleRefresh"
@download="handleDownload"
>
<!-- 工具栏左侧按钮 -->
<template #toolbar-left>
<a-button type="primary" @click="handleAdd">
<template #icon>
<icon-plus />
</template>
新增
</a-button>
<a-button status="success" @click="handleBatchDelete">
<template #icon>
<icon-delete />
</template>
批量删除
</a-button>
</template>
<!-- 表格自定义列序号 -->
<template #index="{ rowIndex }">
{{ rowIndex + 1 + (pagination.current - 1) * pagination.pageSize }}
</template>
<!-- 表格自定义列状态 -->
<template #status="{ record }">
<a-tag :color="record.status === 'active' ? 'green' : 'red'">
{{ record.status === 'active' ? '启用' : '禁用' }}
</a-tag>
</template>
<!-- 表格自定义列头像 -->
<template #avatar="{ record }">
<a-avatar :style="{ backgroundColor: record.avatarColor }">
{{ record.name.charAt(0) }}
</a-avatar>
</template>
<!-- 表格自定义列操作 -->
<template #operations="{ record }">
<a-space>
<a-button type="text" size="small" @click="handleView(record)">
查看
</a-button>
<a-button type="text" size="small" @click="handleEdit(record)">
编辑
</a-button>
<a-popconfirm content="确定要删除吗?" @ok="handleDelete(record)">
<a-button type="text" size="small" status="danger">
删除
</a-button>
</a-popconfirm>
</a-space>
</template>
</SearchTable>
</div>
</template>
<script lang="ts" setup>
import { computed, ref, reactive } from 'vue'
import { Message } from '@arco-design/web-vue'
import type { TableColumnData } from '@arco-design/web-vue/es/table/interface'
import type { FormItem } from '@/components/search-form/types'
// 定义表格数据类型
interface UserRecord {
id: number
name: string
email: string
department: string
role: string
status: 'active' | 'inactive'
avatarColor: string
createdAt: string
}
// 模拟数据生成
const generateMockData = (count: number): UserRecord[] => {
const departments = ['技术部', '产品部', '运营部', '市场部', '财务部']
const roles = ['管理员', '普通用户', '访客']
const names = ['张三', '李四', '王五', '赵六', '钱七', '孙八', '周九', '吴十']
const colors = ['#165DFF', '#0FC6C2', '#722ED1', '#F53F3F', '#FF7D00', '#00B42A']
return Array.from({ length: count }, (_, i) => ({
id: i + 1,
name: names[i % names.length] + (Math.floor(i / names.length) || ''),
email: `user${i + 1}@example.com`,
department: departments[i % departments.length],
role: roles[i % roles.length],
status: i % 3 === 0 ? 'inactive' : 'active',
avatarColor: colors[i % colors.length],
createdAt: `2024-${String((i % 12) + 1).padStart(2, '0')}-${String((i % 28) + 1).padStart(2, '0')}`,
}))
}
// 状态管理
const loading = ref(false)
const tableData = ref<UserRecord[]>([])
const formModel = ref({
name: '',
department: '',
status: '',
email: '',
})
const pagination = reactive({
current: 1,
pageSize: 10,
total: 0,
})
// 表单项配置
const formItems = computed<FormItem[]>(() => [
{
field: 'name',
label: '用户名',
type: 'input',
placeholder: '请输入用户名',
},
{
field: 'email',
label: '邮箱',
type: 'input',
placeholder: '请输入邮箱',
},
{
field: 'department',
label: '部门',
type: 'select',
placeholder: '请选择部门',
options: [
{ label: '技术部', value: '技术部' },
{ label: '产品部', value: '产品部' },
{ label: '运营部', value: '运营部' },
{ label: '市场部', value: '市场部' },
{ label: '财务部', value: '财务部' },
],
},
{
field: 'status',
label: '状态',
type: 'select',
placeholder: '请选择状态',
options: [
{ label: '启用', value: 'active' },
{ label: '禁用', value: 'inactive' },
],
},
])
// 表格列配置
const columns = computed<TableColumnData[]>(() => [
{
title: '序号',
dataIndex: 'index',
slotName: 'index',
width: 80,
},
{
title: '头像',
dataIndex: 'avatar',
slotName: 'avatar',
width: 80,
},
{
title: '用户名',
dataIndex: 'name',
width: 120,
},
{
title: '邮箱',
dataIndex: 'email',
width: 200,
},
{
title: '部门',
dataIndex: 'department',
width: 120,
},
{
title: '角色',
dataIndex: 'role',
width: 100,
},
{
title: '状态',
dataIndex: 'status',
slotName: 'status',
width: 100,
},
{
title: '创建时间',
dataIndex: 'createdAt',
width: 120,
},
{
title: '操作',
dataIndex: 'operations',
slotName: 'operations',
width: 200,
fixed: 'right',
},
])
// 模拟异步获取数据
const fetchData = async () => {
loading.value = true
// 模拟网络延迟
await new Promise(resolve => setTimeout(resolve, 500))
let data = generateMockData(86)
// 根据搜索条件过滤
if (formModel.value.name) {
data = data.filter(item => item.name.includes(formModel.value.name))
}
if (formModel.value.email) {
data = data.filter(item => item.email.includes(formModel.value.email))
}
if (formModel.value.department) {
data = data.filter(item => item.department === formModel.value.department)
}
if (formModel.value.status) {
data = data.filter(item => item.status === formModel.value.status)
}
// 更新分页
pagination.total = data.length
// 分页截取
const start = (pagination.current - 1) * pagination.pageSize
const end = start + pagination.pageSize
tableData.value = data.slice(start, end)
loading.value = false
}
// 事件处理
const handleSearch = () => {
pagination.current = 1
fetchData()
}
const handleReset = () => {
formModel.value = {
name: '',
department: '',
status: '',
email: '',
}
pagination.current = 1
fetchData()
}
const handlePageChange = (current: number) => {
pagination.current = current
fetchData()
}
const handleRefresh = () => {
fetchData()
Message.success('数据已刷新')
}
const handleDownload = () => {
Message.info('导出功能开发中...')
}
const handleAdd = () => {
Message.info('新增功能开发中...')
}
const handleBatchDelete = () => {
Message.warning('请先选择要删除的数据')
}
const handleView = (record: UserRecord) => {
Message.info(`查看用户:${record.name}`)
}
const handleEdit = (record: UserRecord) => {
Message.info(`编辑用户:${record.name}`)
}
const handleDelete = (record: UserRecord) => {
Message.success(`已删除用户:${record.name}`)
}
// 初始化加载数据
fetchData()
</script>
<script lang="ts">
export default {
name: 'SearchTableDemo',
}
</script>
<style scoped lang="less">
.container {
padding: 0 20px 20px 20px;
}
</style>