parent
0dd026279b
commit
6921e89a77
@ -0,0 +1,120 @@
|
||||
import request from '@/utils/request'
|
||||
import type { ApiResponse } from '@/types'
|
||||
|
||||
export const adminApi = {
|
||||
// 获取系统统计数据
|
||||
getSystemStats(): Promise<ApiResponse> {
|
||||
return request.get('/admin/stats')
|
||||
},
|
||||
|
||||
// 获取用户列表
|
||||
getUserList(params: {
|
||||
page?: number
|
||||
size?: number
|
||||
keyword?: string
|
||||
role?: number | null
|
||||
status?: number
|
||||
}): Promise<ApiResponse> {
|
||||
return request.get('/admin/users', { params })
|
||||
},
|
||||
|
||||
// 更新用户状态
|
||||
updateUserStatus(userId: number, data: { status: number }): Promise<ApiResponse> {
|
||||
return request.put(`/admin/users/${userId}/status`, data)
|
||||
},
|
||||
|
||||
// 更新用户角色
|
||||
updateUserRole(userId: number, data: { role: number }): Promise<ApiResponse> {
|
||||
return request.put(`/admin/users/${userId}/role`, data)
|
||||
},
|
||||
|
||||
// 删除用户
|
||||
deleteUser(userId: number): Promise<ApiResponse> {
|
||||
return request.delete(`/admin/users/${userId}`)
|
||||
},
|
||||
|
||||
// 获取帖子列表
|
||||
getPostList(params: {
|
||||
page?: number
|
||||
size?: number
|
||||
keyword?: string
|
||||
categoryId?: number
|
||||
status?: number
|
||||
}): Promise<ApiResponse> {
|
||||
return request.get('/admin/posts', { params })
|
||||
},
|
||||
|
||||
// 更新帖子状态
|
||||
updatePostStatus(postId: number, data: { status: number }): Promise<ApiResponse> {
|
||||
return request.put(`/admin/posts/${postId}/status`, data)
|
||||
},
|
||||
|
||||
// 删除帖子
|
||||
deletePost(postId: number): Promise<ApiResponse> {
|
||||
return request.delete(`/admin/posts/${postId}`)
|
||||
},
|
||||
|
||||
// 获取评论列表
|
||||
getCommentList(params: {
|
||||
page?: number
|
||||
size?: number
|
||||
keyword?: string
|
||||
postId?: number
|
||||
status?: number
|
||||
}): Promise<ApiResponse> {
|
||||
return request.get('/admin/comments', { params })
|
||||
},
|
||||
|
||||
// 删除评论
|
||||
deleteComment(commentId: number): Promise<ApiResponse> {
|
||||
return request.delete(`/admin/comments/${commentId}`)
|
||||
},
|
||||
|
||||
// 获取分类列表
|
||||
getCategoryList(): Promise<ApiResponse> {
|
||||
return request.get('/admin/categories')
|
||||
},
|
||||
|
||||
// 创建分类
|
||||
createCategory(data: {
|
||||
name: string
|
||||
description?: string
|
||||
icon?: string
|
||||
sort?: number
|
||||
status?: number
|
||||
}): Promise<ApiResponse> {
|
||||
return request.post('/admin/categories', data)
|
||||
},
|
||||
|
||||
// 更新分类
|
||||
updateCategory(categoryId: number, data: {
|
||||
name: string
|
||||
description?: string
|
||||
icon?: string
|
||||
sort?: number
|
||||
status?: number
|
||||
}): Promise<ApiResponse> {
|
||||
return request.put(`/admin/categories/${categoryId}`, data)
|
||||
},
|
||||
|
||||
// 删除分类
|
||||
deleteCategory(categoryId: number): Promise<ApiResponse> {
|
||||
return request.delete(`/admin/categories/${categoryId}`)
|
||||
},
|
||||
|
||||
// 获取资源列表
|
||||
getResourceList(params: {
|
||||
page?: number
|
||||
size?: number
|
||||
keyword?: string
|
||||
categoryId?: number
|
||||
status?: number
|
||||
}): Promise<ApiResponse> {
|
||||
return request.get('/admin/resources', { params })
|
||||
},
|
||||
|
||||
// 删除资源
|
||||
deleteResource(resourceId: number): Promise<ApiResponse> {
|
||||
return request.delete(`/admin/resources/${resourceId}`)
|
||||
}
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
import axios from 'axios'
|
||||
|
||||
// 创建axios实例
|
||||
const request = axios.create({
|
||||
baseURL: 'http://localhost:8087',
|
||||
timeout: 10000,
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
})
|
||||
|
||||
// 请求拦截器
|
||||
request.interceptors.request.use(
|
||||
(config) => {
|
||||
const token = localStorage.getItem('token')
|
||||
if (token) {
|
||||
config.headers.Authorization = `Bearer ${token}`
|
||||
}
|
||||
return config
|
||||
},
|
||||
(error) => {
|
||||
return Promise.reject(error)
|
||||
}
|
||||
)
|
||||
|
||||
// 响应拦截器
|
||||
request.interceptors.response.use(
|
||||
(response) => {
|
||||
return response.data
|
||||
},
|
||||
(error) => {
|
||||
if (error.response?.status === 401) {
|
||||
localStorage.removeItem('token')
|
||||
window.location.href = '/login'
|
||||
}
|
||||
return Promise.reject(error)
|
||||
}
|
||||
)
|
||||
|
||||
export default request
|
@ -0,0 +1,453 @@
|
||||
<template>
|
||||
<div class="admin-dashboard">
|
||||
<!-- 顶部导航 -->
|
||||
<div class="admin-header">
|
||||
<div class="header-left">
|
||||
<h1 class="admin-title">UniLife 管理后台</h1>
|
||||
</div>
|
||||
<div class="header-right">
|
||||
<span class="admin-user">{{ userStore.user?.nickname }}</span>
|
||||
<el-button @click="logout" type="danger" size="small">退出登录</el-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 主要内容区域 -->
|
||||
<div class="admin-content">
|
||||
<!-- 侧边栏 -->
|
||||
<div class="admin-sidebar">
|
||||
<el-menu
|
||||
:default-active="activeMenu"
|
||||
class="admin-menu"
|
||||
@select="handleMenuSelect"
|
||||
>
|
||||
<el-menu-item index="dashboard">
|
||||
<el-icon><DataBoard /></el-icon>
|
||||
<span>数据概览</span>
|
||||
</el-menu-item>
|
||||
<el-menu-item index="users">
|
||||
<el-icon><User /></el-icon>
|
||||
<span>用户管理</span>
|
||||
</el-menu-item>
|
||||
<el-menu-item index="posts">
|
||||
<el-icon><Document /></el-icon>
|
||||
<span>帖子管理</span>
|
||||
</el-menu-item>
|
||||
<el-menu-item index="comments">
|
||||
<el-icon><ChatDotRound /></el-icon>
|
||||
<span>评论管理</span>
|
||||
</el-menu-item>
|
||||
<el-menu-item index="categories">
|
||||
<el-icon><FolderOpened /></el-icon>
|
||||
<span>分类管理</span>
|
||||
</el-menu-item>
|
||||
<el-menu-item index="resources">
|
||||
<el-icon><Files /></el-icon>
|
||||
<span>资源管理</span>
|
||||
</el-menu-item>
|
||||
</el-menu>
|
||||
</div>
|
||||
|
||||
<!-- 主内容区 -->
|
||||
<div class="admin-main">
|
||||
<!-- 数据概览 -->
|
||||
<div v-if="activeMenu === 'dashboard'" class="dashboard-content">
|
||||
<h2>系统数据概览</h2>
|
||||
<div class="stats-grid">
|
||||
<div class="stat-card">
|
||||
<div class="stat-icon user-icon">
|
||||
<el-icon><User /></el-icon>
|
||||
</div>
|
||||
<div class="stat-info">
|
||||
<div class="stat-number">{{ stats.totalUsers || 0 }}</div>
|
||||
<div class="stat-label">总用户数</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="stat-icon post-icon">
|
||||
<el-icon><Document /></el-icon>
|
||||
</div>
|
||||
<div class="stat-info">
|
||||
<div class="stat-number">{{ stats.totalPosts || 0 }}</div>
|
||||
<div class="stat-label">总帖子数</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="stat-icon comment-icon">
|
||||
<el-icon><ChatDotRound /></el-icon>
|
||||
</div>
|
||||
<div class="stat-info">
|
||||
<div class="stat-number">{{ stats.totalComments || 0 }}</div>
|
||||
<div class="stat-label">总评论数</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="stat-icon resource-icon">
|
||||
<el-icon><Files /></el-icon>
|
||||
</div>
|
||||
<div class="stat-info">
|
||||
<div class="stat-number">{{ stats.totalResources || 0 }}</div>
|
||||
<div class="stat-label">总资源数</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 用户管理 -->
|
||||
<div v-if="activeMenu === 'users'" class="users-content">
|
||||
<h2>用户管理</h2>
|
||||
<div class="table-toolbar">
|
||||
<el-input
|
||||
v-model="userSearch"
|
||||
placeholder="搜索用户..."
|
||||
style="width: 300px"
|
||||
@input="searchUsers"
|
||||
/>
|
||||
<el-select v-model="userRoleFilter" placeholder="角色筛选" @change="searchUsers">
|
||||
<el-option label="全部" :value="null" />
|
||||
<el-option label="普通用户" :value="0" />
|
||||
<el-option label="版主" :value="1" />
|
||||
<el-option label="管理员" :value="2" />
|
||||
</el-select>
|
||||
</div>
|
||||
<el-table :data="users" style="width: 100%">
|
||||
<el-table-column prop="id" label="ID" width="80" />
|
||||
<el-table-column prop="username" label="用户名" width="120" />
|
||||
<el-table-column prop="nickname" label="昵称" width="120" />
|
||||
<el-table-column prop="email" label="邮箱" width="200" />
|
||||
<el-table-column prop="role" label="角色" width="100">
|
||||
<template #default="scope">
|
||||
<el-tag :type="getRoleType(scope.row.role)">
|
||||
{{ getRoleText(scope.row.role) }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="status" label="状态" width="100">
|
||||
<template #default="scope">
|
||||
<el-tag :type="scope.row.status === 1 ? 'success' : 'danger'">
|
||||
{{ scope.row.status === 1 ? '正常' : '禁用' }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="createdAt" label="注册时间" width="180" />
|
||||
<el-table-column label="操作" width="200">
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
size="small"
|
||||
:type="scope.row.status === 1 ? 'warning' : 'success'"
|
||||
@click="toggleUserStatus(scope.row)"
|
||||
>
|
||||
{{ scope.row.status === 1 ? '禁用' : '启用' }}
|
||||
</el-button>
|
||||
<el-button
|
||||
size="small"
|
||||
type="danger"
|
||||
@click="deleteUser(scope.row)"
|
||||
:disabled="scope.row.role === 2"
|
||||
>
|
||||
删除
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-pagination
|
||||
v-model:current-page="userPage"
|
||||
v-model:page-size="userPageSize"
|
||||
:total="userTotal"
|
||||
@current-change="loadUsers"
|
||||
layout="total, prev, pager, next"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- 其他管理模块的占位符 -->
|
||||
<div v-if="activeMenu === 'posts'" class="posts-content">
|
||||
<h2>帖子管理</h2>
|
||||
<p>帖子管理功能开发中...</p>
|
||||
</div>
|
||||
|
||||
<div v-if="activeMenu === 'comments'" class="comments-content">
|
||||
<h2>评论管理</h2>
|
||||
<p>评论管理功能开发中...</p>
|
||||
</div>
|
||||
|
||||
<div v-if="activeMenu === 'categories'" class="categories-content">
|
||||
<h2>分类管理</h2>
|
||||
<p>分类管理功能开发中...</p>
|
||||
</div>
|
||||
|
||||
<div v-if="activeMenu === 'resources'" class="resources-content">
|
||||
<h2>资源管理</h2>
|
||||
<p>资源管理功能开发中...</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import {
|
||||
DataBoard,
|
||||
User,
|
||||
Document,
|
||||
ChatDotRound,
|
||||
FolderOpened,
|
||||
Files
|
||||
} from '@element-plus/icons-vue'
|
||||
import { useUserStore } from '@/stores/user'
|
||||
import { adminApi } from '@/api/admin'
|
||||
|
||||
// 定义统计数据接口
|
||||
interface SystemStats {
|
||||
totalUsers?: number
|
||||
totalPosts?: number
|
||||
totalComments?: number
|
||||
totalResources?: number
|
||||
}
|
||||
|
||||
const router = useRouter()
|
||||
const userStore = useUserStore()
|
||||
|
||||
// 当前激活的菜单
|
||||
const activeMenu = ref('dashboard')
|
||||
|
||||
// 统计数据
|
||||
const stats = ref<SystemStats>({})
|
||||
|
||||
// 用户管理相关
|
||||
const users = ref([])
|
||||
const userSearch = ref('')
|
||||
const userRoleFilter = ref(null)
|
||||
const userPage = ref(1)
|
||||
const userPageSize = ref(10)
|
||||
const userTotal = ref(0)
|
||||
|
||||
// 菜单选择处理
|
||||
const handleMenuSelect = (index: string) => {
|
||||
activeMenu.value = index
|
||||
if (index === 'dashboard') {
|
||||
loadStats()
|
||||
} else if (index === 'users') {
|
||||
loadUsers()
|
||||
}
|
||||
}
|
||||
|
||||
// 加载统计数据
|
||||
const loadStats = async () => {
|
||||
try {
|
||||
const response = await adminApi.getSystemStats()
|
||||
if (response.code === 200) {
|
||||
stats.value = response.data
|
||||
}
|
||||
} catch (error) {
|
||||
ElMessage.error('加载统计数据失败')
|
||||
}
|
||||
}
|
||||
|
||||
// 加载用户列表
|
||||
const loadUsers = async () => {
|
||||
try {
|
||||
const response = await adminApi.getUserList({
|
||||
page: userPage.value,
|
||||
size: userPageSize.value,
|
||||
keyword: userSearch.value || undefined,
|
||||
role: userRoleFilter.value
|
||||
})
|
||||
if (response.code === 200) {
|
||||
users.value = response.data.list
|
||||
userTotal.value = response.data.total
|
||||
}
|
||||
} catch (error) {
|
||||
ElMessage.error('加载用户列表失败')
|
||||
}
|
||||
}
|
||||
|
||||
// 搜索用户
|
||||
const searchUsers = () => {
|
||||
userPage.value = 1
|
||||
loadUsers()
|
||||
}
|
||||
|
||||
// 切换用户状态
|
||||
const toggleUserStatus = async (user: any) => {
|
||||
try {
|
||||
const newStatus = user.status === 1 ? 0 : 1
|
||||
const response = await adminApi.updateUserStatus(user.id, { status: newStatus })
|
||||
if (response.code === 200) {
|
||||
user.status = newStatus
|
||||
ElMessage.success('用户状态更新成功')
|
||||
}
|
||||
} catch (error) {
|
||||
ElMessage.error('更新用户状态失败')
|
||||
}
|
||||
}
|
||||
|
||||
// 删除用户
|
||||
const deleteUser = async (user: any) => {
|
||||
try {
|
||||
await ElMessageBox.confirm('确定要删除该用户吗?此操作不可恢复!', '警告', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
})
|
||||
|
||||
const response = await adminApi.deleteUser(user.id)
|
||||
if (response.code === 200) {
|
||||
ElMessage.success('用户删除成功')
|
||||
loadUsers()
|
||||
}
|
||||
} catch (error) {
|
||||
if (error !== 'cancel') {
|
||||
ElMessage.error('删除用户失败')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 获取角色类型
|
||||
const getRoleType = (role: number) => {
|
||||
switch (role) {
|
||||
case 0: return ''
|
||||
case 1: return 'warning'
|
||||
case 2: return 'danger'
|
||||
default: return ''
|
||||
}
|
||||
}
|
||||
|
||||
// 获取角色文本
|
||||
const getRoleText = (role: number) => {
|
||||
switch (role) {
|
||||
case 0: return '普通用户'
|
||||
case 1: return '版主'
|
||||
case 2: return '管理员'
|
||||
default: return '未知'
|
||||
}
|
||||
}
|
||||
|
||||
// 退出登录
|
||||
const logout = () => {
|
||||
userStore.logout()
|
||||
router.push('/login')
|
||||
}
|
||||
|
||||
// 页面加载时初始化
|
||||
onMounted(() => {
|
||||
loadStats()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.admin-dashboard {
|
||||
min-height: 100vh;
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
.admin-header {
|
||||
background: white;
|
||||
padding: 0 20px;
|
||||
height: 60px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
.admin-title {
|
||||
margin: 0;
|
||||
color: #409EFF;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.header-right {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 15px;
|
||||
}
|
||||
|
||||
.admin-user {
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.admin-content {
|
||||
display: flex;
|
||||
height: calc(100vh - 60px);
|
||||
}
|
||||
|
||||
.admin-sidebar {
|
||||
width: 200px;
|
||||
background: white;
|
||||
border-right: 1px solid #e6e6e6;
|
||||
}
|
||||
|
||||
.admin-menu {
|
||||
border: none;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.admin-main {
|
||||
flex: 1;
|
||||
padding: 20px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.stats-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
|
||||
gap: 20px;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.stat-card {
|
||||
background: white;
|
||||
padding: 20px;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 15px;
|
||||
}
|
||||
|
||||
.stat-icon {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 24px;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.user-icon { background: #409EFF; }
|
||||
.post-icon { background: #67C23A; }
|
||||
.comment-icon { background: #E6A23C; }
|
||||
.resource-icon { background: #F56C6C; }
|
||||
|
||||
.stat-number {
|
||||
font-size: 24px;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.stat-label {
|
||||
color: #666;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.table-toolbar {
|
||||
display: flex;
|
||||
gap: 15px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.users-content,
|
||||
.posts-content,
|
||||
.comments-content,
|
||||
.categories-content,
|
||||
.resources-content {
|
||||
background: white;
|
||||
padding: 20px;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
||||
}
|
||||
</style>
|
@ -0,0 +1,140 @@
|
||||
package com.unilife.controller;
|
||||
|
||||
import com.unilife.common.result.Result;
|
||||
import com.unilife.service.AdminService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequestMapping("/admin")
|
||||
@Tag(name = "管理员接口", description = "后台管理相关接口")
|
||||
public class AdminController {
|
||||
|
||||
@Autowired
|
||||
private AdminService adminService;
|
||||
|
||||
@Operation(summary = "获取系统统计数据")
|
||||
@GetMapping("/stats")
|
||||
public Result getSystemStats() {
|
||||
return adminService.getSystemStats();
|
||||
}
|
||||
|
||||
@Operation(summary = "获取用户列表")
|
||||
@GetMapping("/users")
|
||||
public Result getUserList(
|
||||
@RequestParam(defaultValue = "1") Integer page,
|
||||
@RequestParam(defaultValue = "10") Integer size,
|
||||
@RequestParam(required = false) String keyword,
|
||||
@RequestParam(required = false) Integer role,
|
||||
@RequestParam(required = false) Integer status) {
|
||||
return adminService.getUserList(page, size, keyword, role, status);
|
||||
}
|
||||
|
||||
@Operation(summary = "更新用户状态")
|
||||
@PutMapping("/users/{userId}/status")
|
||||
public Result updateUserStatus(@PathVariable Long userId, @RequestBody Map<String, Integer> request) {
|
||||
Integer status = request.get("status");
|
||||
return adminService.updateUserStatus(userId, status);
|
||||
}
|
||||
|
||||
@Operation(summary = "更新用户角色")
|
||||
@PutMapping("/users/{userId}/role")
|
||||
public Result updateUserRole(@PathVariable Long userId, @RequestBody Map<String, Integer> request) {
|
||||
Integer role = request.get("role");
|
||||
return adminService.updateUserRole(userId, role);
|
||||
}
|
||||
|
||||
@Operation(summary = "删除用户")
|
||||
@DeleteMapping("/users/{userId}")
|
||||
public Result deleteUser(@PathVariable Long userId) {
|
||||
return adminService.deleteUser(userId);
|
||||
}
|
||||
|
||||
@Operation(summary = "获取帖子列表")
|
||||
@GetMapping("/posts")
|
||||
public Result getPostList(
|
||||
@RequestParam(defaultValue = "1") Integer page,
|
||||
@RequestParam(defaultValue = "10") Integer size,
|
||||
@RequestParam(required = false) String keyword,
|
||||
@RequestParam(required = false) Long categoryId,
|
||||
@RequestParam(required = false) Integer status) {
|
||||
return adminService.getPostList(page, size, keyword, categoryId, status);
|
||||
}
|
||||
|
||||
@Operation(summary = "更新帖子状态")
|
||||
@PutMapping("/posts/{postId}/status")
|
||||
public Result updatePostStatus(@PathVariable Long postId, @RequestBody Map<String, Integer> request) {
|
||||
Integer status = request.get("status");
|
||||
return adminService.updatePostStatus(postId, status);
|
||||
}
|
||||
|
||||
@Operation(summary = "删除帖子")
|
||||
@DeleteMapping("/posts/{postId}")
|
||||
public Result deletePost(@PathVariable Long postId) {
|
||||
return adminService.deletePost(postId);
|
||||
}
|
||||
|
||||
@Operation(summary = "获取评论列表")
|
||||
@GetMapping("/comments")
|
||||
public Result getCommentList(
|
||||
@RequestParam(defaultValue = "1") Integer page,
|
||||
@RequestParam(defaultValue = "10") Integer size,
|
||||
@RequestParam(required = false) String keyword,
|
||||
@RequestParam(required = false) Long postId,
|
||||
@RequestParam(required = false) Integer status) {
|
||||
return adminService.getCommentList(page, size, keyword, postId, status);
|
||||
}
|
||||
|
||||
@Operation(summary = "删除评论")
|
||||
@DeleteMapping("/comments/{commentId}")
|
||||
public Result deleteComment(@PathVariable Long commentId) {
|
||||
return adminService.deleteComment(commentId);
|
||||
}
|
||||
|
||||
@Operation(summary = "获取分类列表")
|
||||
@GetMapping("/categories")
|
||||
public Result getCategoryList() {
|
||||
return adminService.getCategoryList();
|
||||
}
|
||||
|
||||
@Operation(summary = "创建分类")
|
||||
@PostMapping("/categories")
|
||||
public Result createCategory(@RequestBody Map<String, Object> request) {
|
||||
return adminService.createCategory(request);
|
||||
}
|
||||
|
||||
@Operation(summary = "更新分类")
|
||||
@PutMapping("/categories/{categoryId}")
|
||||
public Result updateCategory(@PathVariable Long categoryId, @RequestBody Map<String, Object> request) {
|
||||
return adminService.updateCategory(categoryId, request);
|
||||
}
|
||||
|
||||
@Operation(summary = "删除分类")
|
||||
@DeleteMapping("/categories/{categoryId}")
|
||||
public Result deleteCategory(@PathVariable Long categoryId) {
|
||||
return adminService.deleteCategory(categoryId);
|
||||
}
|
||||
|
||||
@Operation(summary = "获取资源列表")
|
||||
@GetMapping("/resources")
|
||||
public Result getResourceList(
|
||||
@RequestParam(defaultValue = "1") Integer page,
|
||||
@RequestParam(defaultValue = "10") Integer size,
|
||||
@RequestParam(required = false) String keyword,
|
||||
@RequestParam(required = false) Long categoryId,
|
||||
@RequestParam(required = false) Integer status) {
|
||||
return adminService.getResourceList(page, size, keyword, categoryId, status);
|
||||
}
|
||||
|
||||
@Operation(summary = "删除资源")
|
||||
@DeleteMapping("/resources/{resourceId}")
|
||||
public Result deleteResource(@PathVariable Long resourceId) {
|
||||
return adminService.deleteResource(resourceId);
|
||||
}
|
||||
}
|
@ -0,0 +1,88 @@
|
||||
package com.unilife.service;
|
||||
|
||||
import com.unilife.common.result.Result;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public interface AdminService {
|
||||
|
||||
/**
|
||||
* 获取系统统计数据
|
||||
*/
|
||||
Result getSystemStats();
|
||||
|
||||
/**
|
||||
* 获取用户列表
|
||||
*/
|
||||
Result getUserList(Integer page, Integer size, String keyword, Integer role, Integer status);
|
||||
|
||||
/**
|
||||
* 更新用户状态
|
||||
*/
|
||||
Result updateUserStatus(Long userId, Integer status);
|
||||
|
||||
/**
|
||||
* 更新用户角色
|
||||
*/
|
||||
Result updateUserRole(Long userId, Integer role);
|
||||
|
||||
/**
|
||||
* 删除用户
|
||||
*/
|
||||
Result deleteUser(Long userId);
|
||||
|
||||
/**
|
||||
* 获取帖子列表
|
||||
*/
|
||||
Result getPostList(Integer page, Integer size, String keyword, Long categoryId, Integer status);
|
||||
|
||||
/**
|
||||
* 更新帖子状态
|
||||
*/
|
||||
Result updatePostStatus(Long postId, Integer status);
|
||||
|
||||
/**
|
||||
* 删除帖子
|
||||
*/
|
||||
Result deletePost(Long postId);
|
||||
|
||||
/**
|
||||
* 获取评论列表
|
||||
*/
|
||||
Result getCommentList(Integer page, Integer size, String keyword, Long postId, Integer status);
|
||||
|
||||
/**
|
||||
* 删除评论
|
||||
*/
|
||||
Result deleteComment(Long commentId);
|
||||
|
||||
/**
|
||||
* 获取分类列表
|
||||
*/
|
||||
Result getCategoryList();
|
||||
|
||||
/**
|
||||
* 创建分类
|
||||
*/
|
||||
Result createCategory(Map<String, Object> request);
|
||||
|
||||
/**
|
||||
* 更新分类
|
||||
*/
|
||||
Result updateCategory(Long categoryId, Map<String, Object> request);
|
||||
|
||||
/**
|
||||
* 删除分类
|
||||
*/
|
||||
Result deleteCategory(Long categoryId);
|
||||
|
||||
/**
|
||||
* 获取资源列表
|
||||
*/
|
||||
Result getResourceList(Integer page, Integer size, String keyword, Long categoryId, Integer status);
|
||||
|
||||
/**
|
||||
* 删除资源
|
||||
*/
|
||||
Result deleteResource(Long resourceId);
|
||||
}
|
@ -0,0 +1,339 @@
|
||||
package com.unilife.service.impl;
|
||||
|
||||
import com.unilife.common.result.Result;
|
||||
import com.unilife.mapper.*;
|
||||
import com.unilife.model.entity.*;
|
||||
import com.unilife.service.AdminService;
|
||||
import com.unilife.service.UserService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
public class AdminServiceImpl implements AdminService {
|
||||
|
||||
@Autowired
|
||||
private UserMapper userMapper;
|
||||
|
||||
@Autowired
|
||||
private PostMapper postMapper;
|
||||
|
||||
@Autowired
|
||||
private CommentMapper commentMapper;
|
||||
|
||||
@Autowired
|
||||
private CategoryMapper categoryMapper;
|
||||
|
||||
@Autowired
|
||||
private ResourceMapper resourceMapper;
|
||||
|
||||
@Autowired
|
||||
private UserService userService;
|
||||
|
||||
@Override
|
||||
public Result getSystemStats() {
|
||||
try {
|
||||
Map<String, Object> stats = new HashMap<>();
|
||||
|
||||
// 用户统计
|
||||
stats.put("totalUsers", userMapper.getTotalCount());
|
||||
stats.put("activeUsers", userMapper.getActiveUserCount());
|
||||
stats.put("newUsersToday", userMapper.getNewUserCountToday());
|
||||
|
||||
// 帖子统计
|
||||
stats.put("totalPosts", postMapper.getTotalCount());
|
||||
stats.put("newPostsToday", postMapper.getNewPostCountToday());
|
||||
|
||||
// 评论统计
|
||||
stats.put("totalComments", commentMapper.getTotalCount());
|
||||
stats.put("newCommentsToday", commentMapper.getNewCommentCountToday());
|
||||
|
||||
// 资源统计
|
||||
stats.put("totalResources", resourceMapper.getTotalCount());
|
||||
stats.put("newResourcesToday", resourceMapper.getNewResourceCountToday());
|
||||
|
||||
// 分类统计
|
||||
stats.put("totalCategories", categoryMapper.getTotalCount());
|
||||
|
||||
return Result.success(stats);
|
||||
} catch (Exception e) {
|
||||
log.error("获取系统统计数据失败", e);
|
||||
return Result.error(500, "获取系统统计数据失败");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result getUserList(Integer page, Integer size, String keyword, Integer role, Integer status) {
|
||||
try {
|
||||
int offset = (page - 1) * size;
|
||||
List<User> users = userMapper.getAdminUserList(offset, size, keyword, role, status);
|
||||
int total = userMapper.getAdminUserCount(keyword, role, status);
|
||||
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
result.put("list", users);
|
||||
result.put("total", total);
|
||||
result.put("pages", (total + size - 1) / size);
|
||||
|
||||
return Result.success(result);
|
||||
} catch (Exception e) {
|
||||
log.error("获取用户列表失败", e);
|
||||
return Result.error(500, "获取用户列表失败");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result updateUserStatus(Long userId, Integer status) {
|
||||
try {
|
||||
User user = userMapper.getUserById(userId);
|
||||
if (user == null) {
|
||||
return Result.error(404, "用户不存在");
|
||||
}
|
||||
|
||||
userMapper.updateUserStatus(userId, status);
|
||||
return Result.success(null, "用户状态更新成功");
|
||||
} catch (Exception e) {
|
||||
log.error("更新用户状态失败", e);
|
||||
return Result.error(500, "更新用户状态失败");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result updateUserRole(Long userId, Integer role) {
|
||||
try {
|
||||
User user = userMapper.getUserById(userId);
|
||||
if (user == null) {
|
||||
return Result.error(404, "用户不存在");
|
||||
}
|
||||
|
||||
userMapper.updateUserRole(userId, role);
|
||||
return Result.success(null, "用户角色更新成功");
|
||||
} catch (Exception e) {
|
||||
log.error("更新用户角色失败", e);
|
||||
return Result.error(500, "更新用户角色失败");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result deleteUser(Long userId) {
|
||||
try {
|
||||
User user = userMapper.getUserById(userId);
|
||||
if (user == null) {
|
||||
return Result.error(404, "用户不存在");
|
||||
}
|
||||
|
||||
// 检查是否为管理员
|
||||
if (user.getRole() == 2) {
|
||||
return Result.error(400, "不能删除管理员账号");
|
||||
}
|
||||
|
||||
// 调用UserService的完整删除逻辑
|
||||
return userService.deleteUser(userId);
|
||||
} catch (Exception e) {
|
||||
log.error("删除用户失败", e);
|
||||
return Result.error(500, "删除用户失败");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result getPostList(Integer page, Integer size, String keyword, Long categoryId, Integer status) {
|
||||
try {
|
||||
int offset = (page - 1) * size;
|
||||
List<Post> posts = postMapper.getAdminPostList(offset, size, keyword, categoryId, status);
|
||||
int total = postMapper.getAdminPostCount(keyword, categoryId, status);
|
||||
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
result.put("list", posts);
|
||||
result.put("total", total);
|
||||
result.put("pages", (total + size - 1) / size);
|
||||
|
||||
return Result.success(result);
|
||||
} catch (Exception e) {
|
||||
log.error("获取帖子列表失败", e);
|
||||
return Result.error(500, "获取帖子列表失败");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result updatePostStatus(Long postId, Integer status) {
|
||||
try {
|
||||
Post post = postMapper.getPostById(postId);
|
||||
if (post == null) {
|
||||
return Result.error(404, "帖子不存在");
|
||||
}
|
||||
|
||||
postMapper.updatePostStatus(postId, status);
|
||||
return Result.success(null, "帖子状态更新成功");
|
||||
} catch (Exception e) {
|
||||
log.error("更新帖子状态失败", e);
|
||||
return Result.error(500, "更新帖子状态失败");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result deletePost(Long postId) {
|
||||
try {
|
||||
Post post = postMapper.getPostById(postId);
|
||||
if (post == null) {
|
||||
return Result.error(404, "帖子不存在");
|
||||
}
|
||||
|
||||
postMapper.deletePost(postId);
|
||||
return Result.success(null, "帖子删除成功");
|
||||
} catch (Exception e) {
|
||||
log.error("删除帖子失败", e);
|
||||
return Result.error(500, "删除帖子失败");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result getCommentList(Integer page, Integer size, String keyword, Long postId, Integer status) {
|
||||
try {
|
||||
int offset = (page - 1) * size;
|
||||
List<Comment> comments = commentMapper.getAdminCommentList(offset, size, keyword, postId, status);
|
||||
int total = commentMapper.getAdminCommentCount(keyword, postId, status);
|
||||
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
result.put("list", comments);
|
||||
result.put("total", total);
|
||||
result.put("pages", (total + size - 1) / size);
|
||||
|
||||
return Result.success(result);
|
||||
} catch (Exception e) {
|
||||
log.error("获取评论列表失败", e);
|
||||
return Result.error(500, "获取评论列表失败");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result deleteComment(Long commentId) {
|
||||
try {
|
||||
Comment comment = commentMapper.getCommentById(commentId);
|
||||
if (comment == null) {
|
||||
return Result.error(404, "评论不存在");
|
||||
}
|
||||
|
||||
commentMapper.deleteComment(commentId);
|
||||
return Result.success(null, "评论删除成功");
|
||||
} catch (Exception e) {
|
||||
log.error("删除评论失败", e);
|
||||
return Result.error(500, "删除评论失败");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result getCategoryList() {
|
||||
try {
|
||||
List<Category> categories = categoryMapper.getAllCategories();
|
||||
return Result.success(categories);
|
||||
} catch (Exception e) {
|
||||
log.error("获取分类列表失败", e);
|
||||
return Result.error(500, "获取分类列表失败");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result createCategory(Map<String, Object> request) {
|
||||
try {
|
||||
Category category = new Category();
|
||||
category.setName((String) request.get("name"));
|
||||
category.setDescription((String) request.get("description"));
|
||||
category.setIcon((String) request.get("icon"));
|
||||
category.setSort((Integer) request.get("sort"));
|
||||
Integer statusInt = (Integer) request.get("status");
|
||||
category.setStatus(statusInt != null ? statusInt.byteValue() : (byte) 1);
|
||||
|
||||
categoryMapper.insertCategory(category);
|
||||
return Result.success(null, "分类创建成功");
|
||||
} catch (Exception e) {
|
||||
log.error("创建分类失败", e);
|
||||
return Result.error(500, "创建分类失败");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result updateCategory(Long categoryId, Map<String, Object> request) {
|
||||
try {
|
||||
Category category = categoryMapper.getCategoryById(categoryId);
|
||||
if (category == null) {
|
||||
return Result.error(404, "分类不存在");
|
||||
}
|
||||
|
||||
category.setName((String) request.get("name"));
|
||||
category.setDescription((String) request.get("description"));
|
||||
category.setIcon((String) request.get("icon"));
|
||||
category.setSort((Integer) request.get("sort"));
|
||||
Integer statusInt = (Integer) request.get("status");
|
||||
category.setStatus(statusInt != null ? statusInt.byteValue() : (byte) 1);
|
||||
|
||||
categoryMapper.updateCategory(category);
|
||||
return Result.success(null, "分类更新成功");
|
||||
} catch (Exception e) {
|
||||
log.error("更新分类失败", e);
|
||||
return Result.error(500, "更新分类失败");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result deleteCategory(Long categoryId) {
|
||||
try {
|
||||
Category category = categoryMapper.getCategoryById(categoryId);
|
||||
if (category == null) {
|
||||
return Result.error(404, "分类不存在");
|
||||
}
|
||||
|
||||
// 检查是否有帖子或资源使用该分类
|
||||
int postCount = postMapper.getCountByCategoryId(categoryId);
|
||||
int resourceCount = resourceMapper.getCountByCategoryId(categoryId);
|
||||
|
||||
if (postCount > 0 || resourceCount > 0) {
|
||||
return Result.error(400, "该分类下还有帖子或资源,无法删除");
|
||||
}
|
||||
|
||||
categoryMapper.deleteCategory(categoryId);
|
||||
return Result.success(null, "分类删除成功");
|
||||
} catch (Exception e) {
|
||||
log.error("删除分类失败", e);
|
||||
return Result.error(500, "删除分类失败");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result getResourceList(Integer page, Integer size, String keyword, Long categoryId, Integer status) {
|
||||
try {
|
||||
int offset = (page - 1) * size;
|
||||
List<Resource> resources = resourceMapper.getAdminResourceList(offset, size, keyword, categoryId, status);
|
||||
int total = resourceMapper.getAdminResourceCount(keyword, categoryId, status);
|
||||
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
result.put("list", resources);
|
||||
result.put("total", total);
|
||||
result.put("pages", (total + size - 1) / size);
|
||||
|
||||
return Result.success(result);
|
||||
} catch (Exception e) {
|
||||
log.error("获取资源列表失败", e);
|
||||
return Result.error(500, "获取资源列表失败");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result deleteResource(Long resourceId) {
|
||||
try {
|
||||
Resource resource = resourceMapper.getResourceById(resourceId);
|
||||
if (resource == null) {
|
||||
return Result.error(404, "资源不存在");
|
||||
}
|
||||
|
||||
resourceMapper.deleteResource(resourceId);
|
||||
return Result.success(null, "资源删除成功");
|
||||
} catch (Exception e) {
|
||||
log.error("删除资源失败", e);
|
||||
return Result.error(500, "删除资源失败");
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in new issue