<!-- 用户管理页面 -->
|
<!-- art-full-height 自动计算出页面剩余高度 -->
|
<!-- art-table-card 一个符合系统样式的 class,同时自动撑满剩余高度 -->
|
<!-- 更多 useTable 使用示例请移步至 功能示例 下面的高级表格示例或者查看官方文档 -->
|
<!-- useTable 文档:https://www.artd.pro/docs/zh/guide/hooks/use-table.html -->
|
<template>
|
<div class="user-page art-full-height">
|
<!-- 搜索栏 -->
|
<UserSearch v-model="searchForm" @search="handleSearch" @reset="resetSearchParams"></UserSearch>
|
|
<ElCard class="art-table-card">
|
<!-- 表格头部 -->
|
<ArtTableHeader v-model:columns="columnChecks" :loading="loading" @refresh="refreshData">
|
<template #left>
|
<ElSpace wrap>
|
<ElButton @click="showDialog('add')" v-ripple>新增用户</ElButton>
|
</ElSpace>
|
</template>
|
</ArtTableHeader>
|
|
<!-- 表格 -->
|
<ArtTable
|
:loading="loading"
|
:data="data"
|
:columns="columns"
|
:pagination="pagination"
|
@selection-change="handleSelectionChange"
|
@pagination:size-change="handleSizeChange"
|
@pagination:current-change="handleCurrentChange"
|
>
|
</ArtTable>
|
|
<!-- 用户弹窗 -->
|
<UserDialog
|
v-model:visible="dialogVisible"
|
:type="dialogType"
|
:user-data="currentUserData"
|
@submit="handleDialogSubmit"
|
/>
|
</ElCard>
|
</div>
|
</template>
|
|
<script setup>
|
import UserSearch from './modules/user-search.vue'
|
import UserDialog from './modules/user-dialog.vue'
|
|
import ArtButtonTable from '@/components/core/forms/art-button-table/index.vue'
|
import { ACCOUNT_TABLE_DATA } from '@/mock/temp/formData'
|
import { useTable } from '@/hooks/core/useTable'
|
import { fetchGetUserList } from '@/api/system-manage'
|
import { ElTag, ElMessageBox, ElImage } from 'element-plus'
|
defineOptions({ name: 'User' })
|
const dialogType = ref('add')
|
const dialogVisible = ref(false)
|
const currentUserData = ref({})
|
const selectedRows = ref([])
|
const searchForm = ref({
|
userName: void 0,
|
userGender: void 0,
|
userPhone: void 0,
|
userEmail: void 0,
|
status: '1'
|
})
|
const USER_STATUS_CONFIG = {
|
1: { type: 'success', text: '在线' },
|
2: { type: 'info', text: '离线' },
|
3: { type: 'warning', text: '异常' },
|
4: { type: 'danger', text: '注销' }
|
}
|
const getUserStatusConfig = (status) => {
|
return (
|
USER_STATUS_CONFIG[status] || {
|
type: 'info',
|
text: '未知'
|
}
|
)
|
}
|
const {
|
columns,
|
columnChecks,
|
data,
|
loading,
|
pagination,
|
getData,
|
replaceSearchParams,
|
resetSearchParams,
|
handleSizeChange,
|
handleCurrentChange,
|
refreshData
|
} = useTable({
|
// 核心配置
|
core: {
|
apiFn: fetchGetUserList,
|
apiParams: {
|
current: 1,
|
size: 20,
|
...searchForm.value
|
},
|
// 自定义分页字段映射,未设置时将使用全局配置 tableConfig.ts 中的 paginationKey
|
// paginationKey: {
|
// current: 'pageNum',
|
// size: 'pageSize'
|
// },
|
columnsFactory: () => [
|
{ type: 'selection' },
|
// 勾选列
|
{ type: 'index', width: 60, label: '序号' },
|
// 序号
|
{
|
prop: 'userInfo',
|
label: '用户名',
|
width: 280,
|
// visible: false, // 默认是否显示列
|
formatter: (row) => {
|
return h('div', { class: 'user flex-c' }, [
|
h(ElImage, {
|
class: 'size-9.5 rounded-md',
|
src: row.avatar,
|
previewSrcList: [row.avatar],
|
// 图片预览是否插入至 body 元素上,用于解决表格内部图片预览样式异常
|
previewTeleported: true
|
}),
|
h('div', { class: 'ml-2' }, [
|
h('p', { class: 'user-name' }, row.userName),
|
h('p', { class: 'email' }, row.userEmail)
|
])
|
])
|
}
|
},
|
{
|
prop: 'userGender',
|
label: '性别',
|
sortable: true,
|
formatter: (row) => row.userGender
|
},
|
{ prop: 'userPhone', label: '手机号' },
|
{
|
prop: 'status',
|
label: '状态',
|
formatter: (row) => {
|
const statusConfig = getUserStatusConfig(row.status)
|
return h(ElTag, { type: statusConfig.type }, () => statusConfig.text)
|
}
|
},
|
{
|
prop: 'createTime',
|
label: '创建日期',
|
sortable: true
|
},
|
{
|
prop: 'operation',
|
label: '操作',
|
width: 120,
|
fixed: 'right',
|
// 固定列
|
formatter: (row) =>
|
h('div', [
|
h(ArtButtonTable, {
|
type: 'edit',
|
onClick: () => showDialog('edit', row)
|
}),
|
h(ArtButtonTable, {
|
type: 'delete',
|
onClick: () => deleteUser(row)
|
})
|
])
|
}
|
]
|
},
|
// 数据处理
|
transform: {
|
// 数据转换器 - 替换头像
|
dataTransformer: (records) => {
|
if (!Array.isArray(records)) {
|
console.warn('数据转换器: 期望数组类型,实际收到:', typeof records)
|
return []
|
}
|
return records.map((item, index) => {
|
return {
|
...item,
|
avatar: ACCOUNT_TABLE_DATA[index % ACCOUNT_TABLE_DATA.length].avatar
|
}
|
})
|
}
|
}
|
})
|
const handleSearch = (params) => {
|
replaceSearchParams(params)
|
getData()
|
}
|
const showDialog = (type, row) => {
|
console.log('打开弹窗:', { type, row })
|
dialogType.value = type
|
currentUserData.value = row || {}
|
nextTick(() => {
|
dialogVisible.value = true
|
})
|
}
|
const deleteUser = (row) => {
|
console.log('删除用户:', row)
|
ElMessageBox.confirm(`确定要注销该用户吗?`, '注销用户', {
|
confirmButtonText: '确定',
|
cancelButtonText: '取消',
|
type: 'error'
|
}).then(() => {
|
ElMessage.success('注销成功')
|
})
|
}
|
const handleDialogSubmit = async () => {
|
try {
|
dialogVisible.value = false
|
currentUserData.value = {}
|
} catch (error) {
|
console.error('提交失败:', error)
|
}
|
}
|
const handleSelectionChange = (selection) => {
|
selectedRows.value = selection
|
console.log('选中行数据:', selectedRows.value)
|
}
|
</script>
|