优化用户管理页
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
# 开发环境变量
|
# 开发环境变量
|
||||||
|
|
||||||
# API 基础地址
|
# API 基础地址(使用代理,设置为空字符串)
|
||||||
VITE_API_BASE_URL=http://localhost:3000
|
VITE_API_BASE_URL=
|
||||||
|
|||||||
@@ -54,8 +54,6 @@ const route = useRoute()
|
|||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const adminStore = useAdminStore()
|
const adminStore = useAdminStore()
|
||||||
|
|
||||||
console.log('AdminLayout - adminStore.userInfo:', adminStore.userInfo)
|
|
||||||
|
|
||||||
const activeKey = ref(String(route.name))
|
const activeKey = ref(String(route.name))
|
||||||
|
|
||||||
const menuOptions = [
|
const menuOptions = [
|
||||||
|
|||||||
@@ -30,13 +30,9 @@ export const useAdminStore = defineStore('admin', () => {
|
|||||||
const login = async (username: string, password: string) => {
|
const login = async (username: string, password: string) => {
|
||||||
try {
|
try {
|
||||||
const data = await loginApi(username, password)
|
const data = await loginApi(username, password)
|
||||||
console.log('登录API返回的数据:', data)
|
|
||||||
if (data.success && data.data) {
|
if (data.success && data.data) {
|
||||||
console.log('设置token:', data.data.token)
|
|
||||||
console.log('设置用户信息:', data.data.user)
|
|
||||||
setToken(data.data.token)
|
setToken(data.data.token)
|
||||||
setUserInfo(data.data.user)
|
setUserInfo(data.data.user)
|
||||||
console.log('登录后userInfo:', userInfo.value)
|
|
||||||
return { success: true, message: data.message || '登录成功' }
|
return { success: true, message: data.message || '登录成功' }
|
||||||
}
|
}
|
||||||
return { success: false, message: data.message || '登录失败' }
|
return { success: false, message: data.message || '登录失败' }
|
||||||
|
|||||||
@@ -1,9 +1,16 @@
|
|||||||
import axios from 'axios'
|
import axios, { type AxiosInstance, type AxiosResponse } from 'axios'
|
||||||
|
import type { ApiResponse } from '@/types/api'
|
||||||
|
|
||||||
const request = axios.create({
|
const request = axios.create({
|
||||||
baseURL: import.meta.env.VITE_API_BASE_URL,
|
baseURL: import.meta.env.VITE_API_BASE_URL || '',
|
||||||
timeout: 10000
|
timeout: 10000
|
||||||
})
|
}) as AxiosInstance & {
|
||||||
|
<T = any>(config: any): Promise<ApiResponse<T>>
|
||||||
|
get<T = any>(url: string, config?: any): Promise<ApiResponse<T>>
|
||||||
|
post<T = any>(url: string, data?: any, config?: any): Promise<ApiResponse<T>>
|
||||||
|
put<T = any>(url: string, data?: any, config?: any): Promise<ApiResponse<T>>
|
||||||
|
delete<T = any>(url: string, config?: any): Promise<ApiResponse<T>>
|
||||||
|
}
|
||||||
|
|
||||||
request.interceptors.request.use(
|
request.interceptors.request.use(
|
||||||
(config) => {
|
(config) => {
|
||||||
@@ -26,11 +33,10 @@ request.interceptors.request.use(
|
|||||||
)
|
)
|
||||||
|
|
||||||
request.interceptors.response.use(
|
request.interceptors.response.use(
|
||||||
(response) => {
|
(response: AxiosResponse<ApiResponse>): any => {
|
||||||
return response.data
|
return response.data
|
||||||
},
|
},
|
||||||
(error) => {
|
(error) => {
|
||||||
console.error('请求错误:', error)
|
|
||||||
return Promise.reject(error)
|
return Promise.reject(error)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="user-management-container">
|
<div class="user-management-container">
|
||||||
<n-card title="用户管理">
|
<!-- 搜索区域 -->
|
||||||
<!-- 搜索表单 -->
|
<n-card title="搜索用户" class="search-card">
|
||||||
<n-form inline :model="searchForm" label-placement="left" label-width="auto">
|
<n-form inline :model="searchForm" label-placement="left" label-width="auto">
|
||||||
<n-grid :cols="24" :x-gap="12">
|
<n-grid :cols="24" :x-gap="12">
|
||||||
<n-gi :span="6">
|
<n-gi :span="6">
|
||||||
@@ -37,7 +37,10 @@
|
|||||||
</n-gi>
|
</n-gi>
|
||||||
</n-grid>
|
</n-grid>
|
||||||
</n-form>
|
</n-form>
|
||||||
|
</n-card>
|
||||||
|
|
||||||
|
<!-- 用户列表区域 -->
|
||||||
|
<n-card title="用户列表" class="table-card">
|
||||||
<!-- 操作按钮 -->
|
<!-- 操作按钮 -->
|
||||||
<n-space class="action-buttons" justify="space-between">
|
<n-space class="action-buttons" justify="space-between">
|
||||||
<n-space>
|
<n-space>
|
||||||
@@ -65,16 +68,16 @@
|
|||||||
:row-key="(row: any) => row.id"
|
:row-key="(row: any) => row.id"
|
||||||
class="user-table"
|
class="user-table"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<!-- 新建/编辑用户对话框 -->
|
|
||||||
<UserFormModal
|
|
||||||
v-model:show="showUserFormModal"
|
|
||||||
:user="currentUser"
|
|
||||||
:mode="userFormMode"
|
|
||||||
:roles="roleList"
|
|
||||||
@success="handleUserFormSuccess"
|
|
||||||
/>
|
|
||||||
</n-card>
|
</n-card>
|
||||||
|
|
||||||
|
<!-- 新建/编辑用户对话框 -->
|
||||||
|
<UserFormModal
|
||||||
|
v-model:show="showUserFormModal"
|
||||||
|
:user="currentUser"
|
||||||
|
:mode="userFormMode"
|
||||||
|
:roles="roleList"
|
||||||
|
@success="handleUserFormSuccess"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -82,7 +85,8 @@
|
|||||||
import { ref, reactive, onMounted, h } from 'vue'
|
import { ref, reactive, onMounted, h } from 'vue'
|
||||||
import { NCard, NForm, NFormItem, NInput, NSelect, NButton, NSpace, NGrid, NGi, NDataTable, useMessage, useDialog } from 'naive-ui'
|
import { NCard, NForm, NFormItem, NInput, NSelect, NButton, NSpace, NGrid, NGi, NDataTable, useMessage, useDialog } from 'naive-ui'
|
||||||
import { RiAddLine, RiUploadLine, RiEditLine, RiDeleteBinLine, RiLockLine, RiLockUnlockLine } from '@remixicon/vue'
|
import { RiAddLine, RiUploadLine, RiEditLine, RiDeleteBinLine, RiLockLine, RiLockUnlockLine } from '@remixicon/vue'
|
||||||
import axios from 'axios'
|
import request from '@/utils/request'
|
||||||
|
import type { ApiResponse } from '@/types/api'
|
||||||
import UserFormModal from './components/UserFormModal.vue'
|
import UserFormModal from './components/UserFormModal.vue'
|
||||||
|
|
||||||
// 消息提示
|
// 消息提示
|
||||||
@@ -147,8 +151,18 @@ const columns = [
|
|||||||
}, row.status === 1 ? '启用' : '禁用')
|
}, row.status === 1 ? '启用' : '禁用')
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{ title: '创建时间', key: 'createdAt', width: 180 },
|
{
|
||||||
{ title: '更新时间', key: 'updatedAt', width: 180 },
|
title: '创建时间',
|
||||||
|
key: 'createdAt',
|
||||||
|
width: 180,
|
||||||
|
render: (row: any) => formatDate(row.createdAt)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '更新时间',
|
||||||
|
key: 'updatedAt',
|
||||||
|
width: 180,
|
||||||
|
render: (row: any) => formatDate(row.updatedAt)
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: '操作',
|
title: '操作',
|
||||||
key: 'actions',
|
key: 'actions',
|
||||||
@@ -181,11 +195,23 @@ const showUserFormModal = ref(false)
|
|||||||
const userFormMode = ref<'create' | 'edit'>('create')
|
const userFormMode = ref<'create' | 'edit'>('create')
|
||||||
const currentUser = ref<any>(null)
|
const currentUser = ref<any>(null)
|
||||||
|
|
||||||
|
// 格式化时间函数
|
||||||
|
const formatDate = (dateString: string) => {
|
||||||
|
if (!dateString) return ''
|
||||||
|
const date = new Date(dateString)
|
||||||
|
const year = date.getFullYear()
|
||||||
|
const month = String(date.getMonth() + 1).padStart(2, '0')
|
||||||
|
const day = String(date.getDate()).padStart(2, '0')
|
||||||
|
const hours = String(date.getHours()).padStart(2, '0')
|
||||||
|
const minutes = String(date.getMinutes()).padStart(2, '0')
|
||||||
|
return `${year}-${month}-${day} ${hours}:${minutes}`
|
||||||
|
}
|
||||||
|
|
||||||
// 获取用户列表
|
// 获取用户列表
|
||||||
const fetchUserList = async () => {
|
const fetchUserList = async () => {
|
||||||
loading.value = true
|
loading.value = true
|
||||||
try {
|
try {
|
||||||
const response = await axios.get('/api/admin/users', {
|
const response = await request.get('/api/admin/users', {
|
||||||
params: {
|
params: {
|
||||||
username: searchForm.username || undefined,
|
username: searchForm.username || undefined,
|
||||||
roleId: searchForm.roleId || undefined,
|
roleId: searchForm.roleId || undefined,
|
||||||
@@ -193,11 +219,11 @@ const fetchUserList = async () => {
|
|||||||
page: pagination.page,
|
page: pagination.page,
|
||||||
pageSize: pagination.pageSize
|
pageSize: pagination.pageSize
|
||||||
}
|
}
|
||||||
})
|
}) as ApiResponse<{ list: any[]; total: number }>
|
||||||
|
|
||||||
if (response.data.success) {
|
if (response.success && response.data) {
|
||||||
userList.value = response.data.data.list
|
userList.value = response.data.list
|
||||||
pagination.itemCount = response.data.data.total
|
pagination.itemCount = response.data.total
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
message.error('获取用户列表失败')
|
message.error('获取用户列表失败')
|
||||||
@@ -209,10 +235,10 @@ const fetchUserList = async () => {
|
|||||||
// 获取角色列表
|
// 获取角色列表
|
||||||
const fetchRoleList = async () => {
|
const fetchRoleList = async () => {
|
||||||
try {
|
try {
|
||||||
const response = await axios.get('/api/admin/roles/list')
|
const response = await request.get('/api/admin/roles/list') as ApiResponse<any[]>
|
||||||
if (response.data.success) {
|
if (response.success && response.data) {
|
||||||
roleList.value = response.data.data
|
roleList.value = response.data
|
||||||
roleOptions.value = response.data.data.map((role: any) => ({
|
roleOptions.value = response.data.map((role: any) => ({
|
||||||
label: role.roleName,
|
label: role.roleName,
|
||||||
value: role.id
|
value: role.id
|
||||||
}))
|
}))
|
||||||
@@ -261,7 +287,7 @@ const handleToggleStatus = (row: any) => {
|
|||||||
negativeText: '取消',
|
negativeText: '取消',
|
||||||
onPositiveClick: async () => {
|
onPositiveClick: async () => {
|
||||||
try {
|
try {
|
||||||
await axios.put(`/api/admin/users/${row.id}`, {
|
await request.put(`/api/admin/users/${row.id}`, {
|
||||||
roleId: row.roleId,
|
roleId: row.roleId,
|
||||||
status: newStatus
|
status: newStatus
|
||||||
})
|
})
|
||||||
@@ -283,7 +309,7 @@ const handleDelete = (row: any) => {
|
|||||||
negativeText: '取消',
|
negativeText: '取消',
|
||||||
onPositiveClick: async () => {
|
onPositiveClick: async () => {
|
||||||
try {
|
try {
|
||||||
await axios.delete(`/api/admin/users/${row.id}`)
|
await request.delete(`/api/admin/users/${row.id}`)
|
||||||
message.success('删除成功')
|
message.success('删除成功')
|
||||||
fetchUserList()
|
fetchUserList()
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
@@ -316,6 +342,14 @@ onMounted(() => {
|
|||||||
padding: 20px;
|
padding: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.search-card {
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-card {
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
.action-buttons {
|
.action-buttons {
|
||||||
margin: 16px 0;
|
margin: 16px 0;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user