v0.2.14 前端代码优化
parent
260a85d8f3
commit
6522a9cf05
|
|
@ -0,0 +1,20 @@
|
||||||
|
# SAMS系统文档
|
||||||
|
|
||||||
|
本目录包含SAMS系统的相关文档。
|
||||||
|
|
||||||
|
## 文档结构
|
||||||
|
|
||||||
|
- `api.md`: API接口文档,包含所有后端接口的详细说明
|
||||||
|
- 认证接口
|
||||||
|
- 系统管理接口
|
||||||
|
- 活动管理接口
|
||||||
|
- 社团管理接口
|
||||||
|
- 通用说明
|
||||||
|
|
||||||
|
## 文档更新
|
||||||
|
|
||||||
|
本文档会随着系统开发持续更新。如果您发现文档中的任何问题或有改进建议,请及时反馈。
|
||||||
|
|
||||||
|
## 文档格式
|
||||||
|
|
||||||
|
所有文档均使用Markdown格式编写,可以使用任何支持Markdown的编辑器或查看器阅读。
|
||||||
|
|
@ -0,0 +1,961 @@
|
||||||
|
# SAMS系统接口文档
|
||||||
|
|
||||||
|
## 1. 认证接口 (AuthController)
|
||||||
|
|
||||||
|
### 1.1 用户登录
|
||||||
|
- **接口路径**: `/login`
|
||||||
|
- **请求方式**: POST
|
||||||
|
- **请求参数**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"username": "string", // 用户名/学号/邮箱
|
||||||
|
"password": "string" // 密码
|
||||||
|
}
|
||||||
|
```
|
||||||
|
- **响应结果**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"msg": "登录成功",
|
||||||
|
"data": "JWT令牌"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 2. 系统管理接口 (sys)
|
||||||
|
|
||||||
|
### 2.1 用户管理 (UserController)
|
||||||
|
- **接口路径**: `/api/user`
|
||||||
|
- **功能**: 普通用户管理相关接口
|
||||||
|
|
||||||
|
#### 2.1.1 修改密码
|
||||||
|
- **接口路径**: `/api/user/change-password`
|
||||||
|
- **请求方式**: PUT
|
||||||
|
- **请求参数**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"userId": "number", // 用户ID
|
||||||
|
"oldPassword": "string", // 旧密码
|
||||||
|
"newPassword": "string" // 新密码
|
||||||
|
}
|
||||||
|
```
|
||||||
|
- **响应结果**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"msg": "密码修改成功",
|
||||||
|
"data": null
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 2.1.2 更新个人信息
|
||||||
|
- **接口路径**: `/api/user/profile`
|
||||||
|
- **请求方式**: PUT
|
||||||
|
- **请求参数**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"userId": "number", // 用户ID
|
||||||
|
"nickname": "string", // 昵称
|
||||||
|
"email": "string", // 邮箱
|
||||||
|
"avatar": "string" // 头像URL
|
||||||
|
}
|
||||||
|
```
|
||||||
|
- **响应结果**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"msg": "个人信息更新成功",
|
||||||
|
"data": null
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 2.1.3 获取用户详情
|
||||||
|
- **接口路径**: `/api/user/{userId}`
|
||||||
|
- **请求方式**: GET
|
||||||
|
- **路径参数**:
|
||||||
|
- userId: 用户ID
|
||||||
|
- **响应结果**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"msg": "success",
|
||||||
|
"data": {
|
||||||
|
"userId": "number",
|
||||||
|
"username": "string",
|
||||||
|
"nickname": "string",
|
||||||
|
"email": "string",
|
||||||
|
"avatar": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 2.1.4 上传头像
|
||||||
|
- **接口路径**: `/api/user/avatar`
|
||||||
|
- **请求方式**: POST
|
||||||
|
- **请求参数**:
|
||||||
|
- file: 头像文件(MultipartFile)
|
||||||
|
- **响应结果**: 返回上传后的头像URL字符串
|
||||||
|
|
||||||
|
### 2.2 管理员用户管理 (AdminUserController)
|
||||||
|
- **接口路径**: `/api/admin/user`
|
||||||
|
- **功能**: 管理员用户管理相关接口
|
||||||
|
|
||||||
|
#### 2.2.1 批量导入用户
|
||||||
|
- **接口路径**: `/api/admin/user/import`
|
||||||
|
- **请求方式**: POST
|
||||||
|
- **请求参数**:
|
||||||
|
```json
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"username": "string",
|
||||||
|
"password": "string",
|
||||||
|
"email": "string",
|
||||||
|
"role": "string"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
- **响应结果**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"msg": "用户导入成功",
|
||||||
|
"data": null
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 2.2.2 查询用户列表
|
||||||
|
- **接口路径**: `/api/admin/user/list`
|
||||||
|
- **请求方式**: GET
|
||||||
|
- **请求参数**:
|
||||||
|
- keyword: 关键字(可选,用于搜索用户名、学号、邮箱)
|
||||||
|
- **响应结果**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"msg": "success",
|
||||||
|
"data": [
|
||||||
|
{
|
||||||
|
"userId": "number",
|
||||||
|
"username": "string",
|
||||||
|
"email": "string",
|
||||||
|
"role": "string",
|
||||||
|
"status": "string"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 2.2.3 更新用户信息
|
||||||
|
- **接口路径**: `/api/admin/user/update`
|
||||||
|
- **请求方式**: PUT
|
||||||
|
- **请求参数**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"userId": "number",
|
||||||
|
"role": "string",
|
||||||
|
"status": "string",
|
||||||
|
"password": "string"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
- **响应结果**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"msg": "用户信息更新成功",
|
||||||
|
"data": null
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 2.2.4 重置用户密码
|
||||||
|
- **接口路径**: `/api/admin/user/reset-password/{userId}`
|
||||||
|
- **请求方式**: PUT
|
||||||
|
- **路径参数**:
|
||||||
|
- userId: 用户ID
|
||||||
|
- **响应结果**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"msg": "密码已重置为 123456",
|
||||||
|
"data": null
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 2.2.5 封禁用户
|
||||||
|
- **接口路径**: `/api/admin/user/ban/{userId}`
|
||||||
|
- **请求方式**: PUT
|
||||||
|
- **路径参数**:
|
||||||
|
- userId: 用户ID
|
||||||
|
- **响应结果**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"msg": "用户已封禁",
|
||||||
|
"data": null
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 2.2.6 删除用户
|
||||||
|
- **接口路径**: `/api/admin/user/{userId}`
|
||||||
|
- **请求方式**: DELETE
|
||||||
|
- **路径参数**:
|
||||||
|
- userId: 用户ID
|
||||||
|
- **响应结果**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"msg": "用户已删除",
|
||||||
|
"data": null
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2.3 文件管理 (FileController)
|
||||||
|
- **接口路径**: `/api/file`
|
||||||
|
- **功能**: 文件上传下载相关接口
|
||||||
|
- **说明**: 该模块目前为空,待实现
|
||||||
|
|
||||||
|
## 3. 活动管理接口 (ams)
|
||||||
|
|
||||||
|
### 3.1 活动管理 (ActivityController)
|
||||||
|
- **接口路径**: `/api/admin/activity`
|
||||||
|
- **功能**: 活动创建、修改、查询等
|
||||||
|
- **权限要求**: 需要相应角色权限
|
||||||
|
|
||||||
|
#### 3.1.1 创建活动
|
||||||
|
- **接口路径**: `/api/admin/activity/create`
|
||||||
|
- **请求方式**: POST
|
||||||
|
- **权限要求**: USER, CLUB_ADMIN
|
||||||
|
- **请求参数**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"title": "string", // 活动标题
|
||||||
|
"description": "string", // 活动描述
|
||||||
|
"startTime": "string", // 开始时间
|
||||||
|
"endTime": "string", // 结束时间
|
||||||
|
"location": "string", // 活动地点
|
||||||
|
"maxParticipants": "number", // 最大参与人数
|
||||||
|
"clubId": "number" // 主办社团ID
|
||||||
|
}
|
||||||
|
```
|
||||||
|
- **响应结果**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"msg": "活动创建成功,等待审批",
|
||||||
|
"data": null
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 3.1.2 取消活动
|
||||||
|
- **接口路径**: `/api/admin/activity/cancel`
|
||||||
|
- **请求方式**: PUT
|
||||||
|
- **权限要求**: CLUB_ADMIN
|
||||||
|
- **请求参数**:
|
||||||
|
- actId: 活动ID
|
||||||
|
- **响应结果**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"msg": "活动已取消",
|
||||||
|
"data": null
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3.2 审批管理 (ApprovalController)
|
||||||
|
- **接口路径**: `/api/admin/approval`
|
||||||
|
- **功能**: 活动审批相关接口
|
||||||
|
- **权限要求**: 需要相应角色权限
|
||||||
|
|
||||||
|
#### 3.2.1 审批通过
|
||||||
|
- **接口路径**: `/api/admin/approval/approve`
|
||||||
|
- **请求方式**: POST
|
||||||
|
- **权限要求**: CLUB_ADMIN, DEPARTMENT_ADMIN, COLLEGE_ADMIN
|
||||||
|
- **请求参数**:
|
||||||
|
- apprId: 审批ID
|
||||||
|
- approverId: 审批人ID
|
||||||
|
- **响应结果**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"msg": "审批已通过",
|
||||||
|
"data": null
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 3.2.2 审批拒绝
|
||||||
|
- **接口路径**: `/api/admin/approval/reject`
|
||||||
|
- **请求方式**: POST
|
||||||
|
- **权限要求**: CLUB_ADMIN, DEPARTMENT_ADMIN, COLLEGE_ADMIN
|
||||||
|
- **请求参数**:
|
||||||
|
- apprId: 审批ID
|
||||||
|
- reason: 拒绝原因
|
||||||
|
- approverId: 审批人ID
|
||||||
|
- **响应结果**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"msg": "审批已拒绝",
|
||||||
|
"data": null
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3.3 评论管理 (CommentController)
|
||||||
|
- **接口路径**: `/api/comment`
|
||||||
|
- **功能**: 活动评论相关接口
|
||||||
|
- **权限要求**: 需要相应角色权限
|
||||||
|
|
||||||
|
#### 3.3.1 发表评论
|
||||||
|
- **接口路径**: `/api/comment/add`
|
||||||
|
- **请求方式**: POST
|
||||||
|
- **权限要求**: USER
|
||||||
|
- **请求参数**:
|
||||||
|
- userId: 用户ID
|
||||||
|
- actId: 活动ID
|
||||||
|
- content: 评论内容
|
||||||
|
- parentCommentId: 父评论ID(可选,用于回复)
|
||||||
|
- **响应结果**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"msg": "评论成功",
|
||||||
|
"data": null
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 3.3.2 删除评论
|
||||||
|
- **接口路径**: `/api/comment/delete`
|
||||||
|
- **请求方式**: DELETE
|
||||||
|
- **权限要求**: USER, ADMIN
|
||||||
|
- **请求参数**:
|
||||||
|
- commentId: 评论ID
|
||||||
|
- userId: 用户ID
|
||||||
|
- isAdmin: 是否为管理员
|
||||||
|
- **响应结果**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"msg": "评论已删除",
|
||||||
|
"data": null
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 3.3.3 获取活动评论列表
|
||||||
|
- **接口路径**: `/api/comment/list`
|
||||||
|
- **请求方式**: GET
|
||||||
|
- **请求参数**:
|
||||||
|
- actId: 活动ID
|
||||||
|
- **响应结果**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"msg": "success",
|
||||||
|
"data": [
|
||||||
|
{
|
||||||
|
"commentId": "number",
|
||||||
|
"userId": "number",
|
||||||
|
"content": "string",
|
||||||
|
"createTime": "string"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 3.3.4 获取评论回复
|
||||||
|
- **接口路径**: `/api/comment/replies`
|
||||||
|
- **请求方式**: GET
|
||||||
|
- **请求参数**:
|
||||||
|
- parentCommentId: 父评论ID
|
||||||
|
- **响应结果**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"msg": "success",
|
||||||
|
"data": [
|
||||||
|
{
|
||||||
|
"commentId": "number",
|
||||||
|
"userId": "number",
|
||||||
|
"content": "string",
|
||||||
|
"createTime": "string"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3.4 反应管理 (ReactionController)
|
||||||
|
- **接口路径**: `/api/reaction`
|
||||||
|
- **功能**: 活动反应(点赞等)相关接口
|
||||||
|
- **权限要求**: 需要相应角色权限
|
||||||
|
|
||||||
|
#### 3.4.1 添加反应
|
||||||
|
- **接口路径**: `/api/reaction/add`
|
||||||
|
- **请求方式**: POST
|
||||||
|
- **权限要求**: USER
|
||||||
|
- **请求参数**:
|
||||||
|
- actId: 活动ID
|
||||||
|
- userId: 用户ID
|
||||||
|
- reactionType: 反应类型(LIKE/DISLIKE)
|
||||||
|
- **响应结果**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"msg": "操作成功",
|
||||||
|
"data": null
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 3.4.2 取消反应
|
||||||
|
- **接口路径**: `/api/reaction/remove`
|
||||||
|
- **请求方式**: DELETE
|
||||||
|
- **权限要求**: USER
|
||||||
|
- **请求参数**:
|
||||||
|
- actId: 活动ID
|
||||||
|
- userId: 用户ID
|
||||||
|
- **响应结果**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"msg": "已取消点赞/点踩",
|
||||||
|
"data": null
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 3.4.3 获取反应统计
|
||||||
|
- **接口路径**: `/api/reaction/stats`
|
||||||
|
- **请求方式**: GET
|
||||||
|
- **请求参数**:
|
||||||
|
- actId: 活动ID
|
||||||
|
- **响应结果**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"msg": "success",
|
||||||
|
"data": {
|
||||||
|
"likes": "number",
|
||||||
|
"dislikes": "number"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 3.4.4 获取活动反应列表
|
||||||
|
- **接口路径**: `/api/reaction/list`
|
||||||
|
- **请求方式**: GET
|
||||||
|
- **权限要求**: ADMIN
|
||||||
|
- **请求参数**:
|
||||||
|
- actId: 活动ID
|
||||||
|
- **响应结果**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"msg": "success",
|
||||||
|
"data": [
|
||||||
|
{
|
||||||
|
"reactionId": "number",
|
||||||
|
"userId": "number",
|
||||||
|
"reactionType": "string",
|
||||||
|
"createTime": "string"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3.5 报名管理 (RegistrationController)
|
||||||
|
- **接口路径**: `/api/registration`
|
||||||
|
- **功能**: 活动报名相关接口
|
||||||
|
- **权限要求**: 需要相应角色权限
|
||||||
|
|
||||||
|
#### 3.5.1 报名活动
|
||||||
|
- **接口路径**: `/api/registration/register`
|
||||||
|
- **请求方式**: POST
|
||||||
|
- **权限要求**: USER
|
||||||
|
- **请求参数**:
|
||||||
|
- actId: 活动ID
|
||||||
|
- userId: 用户ID
|
||||||
|
- **响应结果**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"msg": "报名成功",
|
||||||
|
"data": null
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 3.5.2 取消报名
|
||||||
|
- **接口路径**: `/api/registration/cancel`
|
||||||
|
- **请求方式**: PUT
|
||||||
|
- **权限要求**: USER
|
||||||
|
- **请求参数**:
|
||||||
|
- actId: 活动ID
|
||||||
|
- userId: 用户ID
|
||||||
|
- **响应结果**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"msg": "报名已取消",
|
||||||
|
"data": null
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 3.5.3 活动签到
|
||||||
|
- **接口路径**: `/api/registration/attend`
|
||||||
|
- **请求方式**: PUT
|
||||||
|
- **权限要求**: USER
|
||||||
|
- **请求参数**:
|
||||||
|
- actId: 活动ID
|
||||||
|
- userId: 用户ID
|
||||||
|
- **响应结果**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"msg": "签到成功",
|
||||||
|
"data": null
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 3.5.4 获取我的报名列表
|
||||||
|
- **接口路径**: `/api/registration/my-registrations`
|
||||||
|
- **请求方式**: GET
|
||||||
|
- **权限要求**: USER
|
||||||
|
- **请求参数**:
|
||||||
|
- userId: 用户ID
|
||||||
|
- **响应结果**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"msg": "success",
|
||||||
|
"data": [
|
||||||
|
{
|
||||||
|
"registrationId": "number",
|
||||||
|
"actId": "number",
|
||||||
|
"userId": "number",
|
||||||
|
"status": "string",
|
||||||
|
"createTime": "string"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 3.5.5 获取活动报名列表
|
||||||
|
- **接口路径**: `/api/registration/list`
|
||||||
|
- **请求方式**: GET
|
||||||
|
- **权限要求**: ADMIN, COLLEGE_ADMIN, DEPARTMENT_ADMIN
|
||||||
|
- **请求参数**:
|
||||||
|
- actId: 活动ID
|
||||||
|
- **响应结果**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"msg": "success",
|
||||||
|
"data": [
|
||||||
|
{
|
||||||
|
"registrationId": "number",
|
||||||
|
"actId": "number",
|
||||||
|
"userId": "number",
|
||||||
|
"status": "string",
|
||||||
|
"createTime": "string"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 4. 社团管理接口 (sms)
|
||||||
|
|
||||||
|
### 4.1 社团管理 (ClubController)
|
||||||
|
- **接口路径**: `/api/admin/club`
|
||||||
|
- **功能**: 社团基本信息管理
|
||||||
|
- **权限要求**: 需要相应角色权限
|
||||||
|
|
||||||
|
#### 4.1.1 添加社团
|
||||||
|
- **接口路径**: `/api/admin/club/add`
|
||||||
|
- **请求方式**: POST
|
||||||
|
- **权限要求**: ADMIN, COLLEGE_ADMIN, DEPARTMENT_ADMIN
|
||||||
|
- **请求参数**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"name": "string", // 社团名称
|
||||||
|
"description": "string", // 社团描述
|
||||||
|
"collegeId": "number", // 所属学院ID
|
||||||
|
"type": "string" // 社团类型
|
||||||
|
}
|
||||||
|
```
|
||||||
|
- **响应结果**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"msg": "社团添加成功",
|
||||||
|
"data": null
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 4.1.2 更新社团信息
|
||||||
|
- **接口路径**: `/api/admin/club/update`
|
||||||
|
- **请求方式**: PUT
|
||||||
|
- **权限要求**: ADMIN, CLUB_ADMIN
|
||||||
|
- **请求参数**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"clubId": "number", // 社团ID
|
||||||
|
"name": "string", // 社团名称
|
||||||
|
"description": "string", // 社团描述
|
||||||
|
"type": "string" // 社团类型
|
||||||
|
}
|
||||||
|
```
|
||||||
|
- **响应结果**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"msg": "社团信息更新成功",
|
||||||
|
"data": null
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 4.1.3 删除社团
|
||||||
|
- **接口路径**: `/api/admin/club/delete/{clubId}`
|
||||||
|
- **请求方式**: DELETE
|
||||||
|
- **权限要求**: ADMIN, COLLEGE_ADMIN, DEPARTMENT_ADMIN
|
||||||
|
- **路径参数**:
|
||||||
|
- clubId: 社团ID
|
||||||
|
- **响应结果**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"msg": "社团删除成功",
|
||||||
|
"data": null
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 4.1.4 获取社团详情
|
||||||
|
- **接口路径**: `/api/admin/club/{clubId}`
|
||||||
|
- **请求方式**: GET
|
||||||
|
- **权限要求**: ADMIN, COLLEGE_ADMIN, DEPARTMENT_ADMIN, CLUB_ADMIN
|
||||||
|
- **路径参数**:
|
||||||
|
- clubId: 社团ID
|
||||||
|
- **响应结果**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"msg": "success",
|
||||||
|
"data": {
|
||||||
|
"clubId": "number",
|
||||||
|
"name": "string",
|
||||||
|
"description": "string",
|
||||||
|
"collegeId": "number",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 4.1.5 查询社团列表
|
||||||
|
- **接口路径**: `/api/admin/club/list`
|
||||||
|
- **请求方式**: GET
|
||||||
|
- **权限要求**: ADMIN, COLLEGE_ADMIN, DEPARTMENT_ADMIN, CLUB_ADMIN
|
||||||
|
- **请求参数**:
|
||||||
|
- keyword: 关键字(可选,用于搜索)
|
||||||
|
- userId: 用户ID
|
||||||
|
- **响应结果**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"msg": "success",
|
||||||
|
"data": [
|
||||||
|
{
|
||||||
|
"clubId": "number",
|
||||||
|
"name": "string",
|
||||||
|
"description": "string",
|
||||||
|
"collegeId": "number",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4.2 社团成员管理 (ClubUserController)
|
||||||
|
- **接口路径**: `/api/admin/club/user`
|
||||||
|
- **功能**: 社团成员管理相关接口
|
||||||
|
- **权限要求**: 需要相应角色权限
|
||||||
|
|
||||||
|
#### 4.2.1 添加社团成员
|
||||||
|
- **接口路径**: `/api/admin/club/user/add`
|
||||||
|
- **请求方式**: POST
|
||||||
|
- **权限要求**: CLUB_ADMIN
|
||||||
|
- **请求参数**:
|
||||||
|
- clubId: 社团ID
|
||||||
|
- userId: 用户ID
|
||||||
|
- **响应结果**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"msg": "成员已加入社团",
|
||||||
|
"data": null
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 4.2.2 移除社团成员
|
||||||
|
- **接口路径**: `/api/admin/club/user/remove`
|
||||||
|
- **请求方式**: DELETE
|
||||||
|
- **权限要求**: CLUB_ADMIN, COLLEGE_ADMIN
|
||||||
|
- **请求参数**:
|
||||||
|
- clubId: 社团ID
|
||||||
|
- userId: 用户ID
|
||||||
|
- **响应结果**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"msg": "成员已移除",
|
||||||
|
"data": null
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 4.2.3 查询社团成员列表
|
||||||
|
- **接口路径**: `/api/admin/club/user/list`
|
||||||
|
- **请求方式**: GET
|
||||||
|
- **权限要求**: ADMIN, COLLEGE_ADMIN, DEPARTMENT_ADMIN
|
||||||
|
- **请求参数**:
|
||||||
|
- clubId: 社团ID
|
||||||
|
- userId: 用户ID
|
||||||
|
- **响应结果**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"msg": "success",
|
||||||
|
"data": [
|
||||||
|
{
|
||||||
|
"userId": "number",
|
||||||
|
"username": "string",
|
||||||
|
"role": "string"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 4.2.4 查看我的社团成员
|
||||||
|
- **接口路径**: `/api/admin/club/user/my-club-members`
|
||||||
|
- **请求方式**: GET
|
||||||
|
- **权限要求**: CLUB_ADMIN
|
||||||
|
- **请求参数**:
|
||||||
|
- clubId: 社团ID
|
||||||
|
- **响应结果**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"msg": "success",
|
||||||
|
"data": [
|
||||||
|
{
|
||||||
|
"userId": "number",
|
||||||
|
"username": "string",
|
||||||
|
"role": "string"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4.3 学院管理 (CollegeController)
|
||||||
|
- **接口路径**: `/api/admin/college`
|
||||||
|
- **功能**: 学院信息管理相关接口
|
||||||
|
- **权限要求**: 需要相应角色权限
|
||||||
|
|
||||||
|
#### 4.3.1 添加学院
|
||||||
|
- **接口路径**: `/api/admin/college/add`
|
||||||
|
- **请求方式**: POST
|
||||||
|
- **权限要求**: ADMIN, COLLEGE_ADMIN
|
||||||
|
- **请求参数**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"name": "string", // 学院名称
|
||||||
|
"description": "string", // 学院描述
|
||||||
|
"code": "string" // 学院代码
|
||||||
|
}
|
||||||
|
```
|
||||||
|
- **响应结果**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"msg": "学院添加成功",
|
||||||
|
"data": null
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 4.3.2 更新学院信息
|
||||||
|
- **接口路径**: `/api/admin/college/update`
|
||||||
|
- **请求方式**: PUT
|
||||||
|
- **权限要求**: ADMIN, COLLEGE_ADMIN
|
||||||
|
- **请求参数**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"collegeId": "number", // 学院ID
|
||||||
|
"name": "string", // 学院名称
|
||||||
|
"description": "string", // 学院描述
|
||||||
|
"code": "string" // 学院代码
|
||||||
|
}
|
||||||
|
```
|
||||||
|
- **响应结果**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"msg": "学院更新成功",
|
||||||
|
"data": null
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 4.3.3 删除学院
|
||||||
|
- **接口路径**: `/api/admin/college/delete/{collegeId}`
|
||||||
|
- **请求方式**: DELETE
|
||||||
|
- **权限要求**: ADMIN, COLLEGE_ADMIN
|
||||||
|
- **路径参数**:
|
||||||
|
- collegeId: 学院ID
|
||||||
|
- **响应结果**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"msg": "学院删除成功",
|
||||||
|
"data": null
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 4.3.4 获取学院详情
|
||||||
|
- **接口路径**: `/api/admin/college/{collegeId}`
|
||||||
|
- **请求方式**: GET
|
||||||
|
- **权限要求**: ADMIN, COLLEGE_ADMIN
|
||||||
|
- **路径参数**:
|
||||||
|
- collegeId: 学院ID
|
||||||
|
- **响应结果**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"msg": "success",
|
||||||
|
"data": {
|
||||||
|
"collegeId": "number",
|
||||||
|
"name": "string",
|
||||||
|
"description": "string",
|
||||||
|
"code": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 4.3.5 获取我的学院信息
|
||||||
|
- **接口路径**: `/api/admin/college/my-college`
|
||||||
|
- **请求方式**: GET
|
||||||
|
- **权限要求**: DEPARTMENT_ADMIN
|
||||||
|
- **请求参数**:
|
||||||
|
- userId: 用户ID
|
||||||
|
- **响应结果**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"msg": "success",
|
||||||
|
"data": {
|
||||||
|
"collegeId": "number",
|
||||||
|
"name": "string",
|
||||||
|
"description": "string",
|
||||||
|
"code": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 4.3.6 查询学院列表
|
||||||
|
- **接口路径**: `/api/admin/college/list`
|
||||||
|
- **请求方式**: GET
|
||||||
|
- **权限要求**: ADMIN, COLLEGE_ADMIN, DEPARTMENT_ADMIN
|
||||||
|
- **请求参数**:
|
||||||
|
- keyword: 关键字(可选,用于搜索)
|
||||||
|
- userId: 用户ID
|
||||||
|
- **响应结果**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"msg": "success",
|
||||||
|
"data": [
|
||||||
|
{
|
||||||
|
"collegeId": "number",
|
||||||
|
"name": "string",
|
||||||
|
"description": "string",
|
||||||
|
"code": "string"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 4.3.7 指派学院负责人
|
||||||
|
- **接口路径**: `/api/admin/college/assign`
|
||||||
|
- **请求方式**: POST
|
||||||
|
- **权限要求**: ADMIN, COLLEGE_ADMIN
|
||||||
|
- **请求参数**:
|
||||||
|
- collegeId: 学院ID
|
||||||
|
- userId: 用户ID
|
||||||
|
- **响应结果**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"msg": "负责人指派成功",
|
||||||
|
"data": null
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 4.3.8 移除学院负责人
|
||||||
|
- **接口路径**: `/api/admin/college/remove`
|
||||||
|
- **请求方式**: DELETE
|
||||||
|
- **权限要求**: ADMIN, COLLEGE_ADMIN
|
||||||
|
- **请求参数**:
|
||||||
|
- collegeId: 学院ID
|
||||||
|
- userId: 用户ID
|
||||||
|
- **响应结果**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"msg": "负责人移除成功",
|
||||||
|
"data": null
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 4.3.9 获取学院负责人
|
||||||
|
- **接口路径**: `/api/admin/college/getleader/{collegeId}`
|
||||||
|
- **请求方式**: GET
|
||||||
|
- **权限要求**: ADMIN, COLLEGE_ADMIN, DEPARTMENT_ADMIN
|
||||||
|
- **路径参数**:
|
||||||
|
- collegeId: 学院ID
|
||||||
|
- **请求参数**:
|
||||||
|
- userId: 用户ID
|
||||||
|
- **响应结果**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"msg": "success",
|
||||||
|
"data": {
|
||||||
|
"userId": "number",
|
||||||
|
"username": "string",
|
||||||
|
"role": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 通用说明
|
||||||
|
|
||||||
|
1. **认证方式**:
|
||||||
|
- 除登录接口外,所有接口都需要在请求头中携带 JWT Token
|
||||||
|
- Token 格式:`Authorization: Bearer <token>`
|
||||||
|
|
||||||
|
2. **响应格式**:
|
||||||
|
- 所有接口统一使用 `AjaxResult` 封装响应
|
||||||
|
- 成功响应示例:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"msg": "操作成功",
|
||||||
|
"data": {}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
- 失败响应示例:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 500,
|
||||||
|
"msg": "操作失败",
|
||||||
|
"data": null
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **请求方式**:
|
||||||
|
- 查询类接口使用 GET
|
||||||
|
- 创建类接口使用 POST
|
||||||
|
- 更新类接口使用 PUT
|
||||||
|
- 删除类接口使用 DELETE
|
||||||
|
|
||||||
|
4. **数据格式**:
|
||||||
|
- 请求和响应均使用 JSON 格式
|
||||||
|
- 日期时间格式统一使用 ISO 8601 标准
|
||||||
|
|
@ -0,0 +1,53 @@
|
||||||
|
import request from '@/utils/request'
|
||||||
|
|
||||||
|
// 创建活动
|
||||||
|
export function createActivity(data) {
|
||||||
|
return request({
|
||||||
|
url: '/api/admin/activity/create',
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 取消活动
|
||||||
|
export function cancelActivity(data) {
|
||||||
|
return request({
|
||||||
|
url: '/api/admin/activity/cancel',
|
||||||
|
method: 'put',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取活动列表
|
||||||
|
export function getActivityList(params) {
|
||||||
|
return request({
|
||||||
|
url: '/api/admin/activity/list',
|
||||||
|
method: 'get',
|
||||||
|
params
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取活动详情
|
||||||
|
export function getActivityDetail(actId) {
|
||||||
|
return request({
|
||||||
|
url: `/api/admin/activity/${actId}`,
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新活动信息
|
||||||
|
export function updateActivity(data) {
|
||||||
|
return request({
|
||||||
|
url: '/api/admin/activity/update',
|
||||||
|
method: 'put',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除活动
|
||||||
|
export function deleteActivity(actId) {
|
||||||
|
return request({
|
||||||
|
url: `/api/admin/activity/delete/${actId}`,
|
||||||
|
method: 'delete'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,69 @@
|
||||||
|
import request from '@/utils/request'
|
||||||
|
|
||||||
|
// 添加社团
|
||||||
|
export function addClub(data) {
|
||||||
|
return request({
|
||||||
|
url: '/api/admin/club/add',
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新社团信息
|
||||||
|
export function updateClub(data) {
|
||||||
|
return request({
|
||||||
|
url: '/api/admin/club/update',
|
||||||
|
method: 'put',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除社团
|
||||||
|
export function deleteClub(clubId) {
|
||||||
|
return request({
|
||||||
|
url: `/api/admin/club/delete/${clubId}`,
|
||||||
|
method: 'delete'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取社团详情
|
||||||
|
export function getClubDetail(clubId) {
|
||||||
|
return request({
|
||||||
|
url: `/api/admin/club/${clubId}`,
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取社团列表
|
||||||
|
export function getClubList(params) {
|
||||||
|
return request({
|
||||||
|
url: '/api/admin/club/list',
|
||||||
|
method: 'get',
|
||||||
|
params
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取社团成员列表
|
||||||
|
export function getClubMembers(clubId) {
|
||||||
|
return request({
|
||||||
|
url: `/api/admin/club/${clubId}/members`,
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加社团成员
|
||||||
|
export function addClubMember(data) {
|
||||||
|
return request({
|
||||||
|
url: '/api/admin/club/member/add',
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 移除社团成员
|
||||||
|
export function removeClubMember(clubId, userId) {
|
||||||
|
return request({
|
||||||
|
url: `/api/admin/club/${clubId}/member/${userId}`,
|
||||||
|
method: 'delete'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,48 @@
|
||||||
|
import request from '@/utils/request'
|
||||||
|
|
||||||
|
// 用户登录
|
||||||
|
export function login(data) {
|
||||||
|
return request({
|
||||||
|
url: '/api/login',
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取用户信息
|
||||||
|
export function getUserInfo(userId) {
|
||||||
|
return request({
|
||||||
|
url: `/api/user/${userId}`,
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 修改密码
|
||||||
|
export function changePassword(data) {
|
||||||
|
return request({
|
||||||
|
url: '/api/user/change-password',
|
||||||
|
method: 'put',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新用户信息
|
||||||
|
export function updateProfile(data) {
|
||||||
|
return request({
|
||||||
|
url: '/api/user/profile',
|
||||||
|
method: 'put',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 上传头像
|
||||||
|
export function uploadAvatar(data) {
|
||||||
|
return request({
|
||||||
|
url: '/api/user/avatar',
|
||||||
|
method: 'post',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'multipart/form-data'
|
||||||
|
},
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
export default {
|
||||||
|
development: {
|
||||||
|
baseUrl: 'http://localhost:8080',
|
||||||
|
uploadUrl: 'http://localhost:8080/api/file/upload'
|
||||||
|
},
|
||||||
|
production: {
|
||||||
|
baseUrl: 'http://your-production-domain',
|
||||||
|
uploadUrl: 'http://your-production-domain/api/file/upload'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
import env from './env'
|
||||||
|
import settings from './settings'
|
||||||
|
|
||||||
|
const config = {
|
||||||
|
...env[process.env.NODE_ENV || 'development'],
|
||||||
|
...settings
|
||||||
|
}
|
||||||
|
|
||||||
|
export default config
|
||||||
|
|
@ -0,0 +1,83 @@
|
||||||
|
export default {
|
||||||
|
/**
|
||||||
|
* 系统标题
|
||||||
|
*/
|
||||||
|
title: 'SAMS学生社团管理系统',
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 系统logo
|
||||||
|
*/
|
||||||
|
logo: '/logo.png',
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否显示设置右面板
|
||||||
|
*/
|
||||||
|
showSettings: true,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否显示标签视图
|
||||||
|
*/
|
||||||
|
tagsView: true,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否固定头部
|
||||||
|
*/
|
||||||
|
fixedHeader: true,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否显示侧边栏Logo
|
||||||
|
*/
|
||||||
|
sidebarLogo: true,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否显示动态标题
|
||||||
|
*/
|
||||||
|
dynamicTitle: true,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 主题色
|
||||||
|
*/
|
||||||
|
theme: '#409EFF',
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 导航模式 vertical / horizontal
|
||||||
|
*/
|
||||||
|
navMode: 'vertical',
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 内容区域宽度 fluid / fixed
|
||||||
|
*/
|
||||||
|
contentWidth: 'fluid',
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 侧边栏主题 dark / light
|
||||||
|
*/
|
||||||
|
sidebarTheme: 'dark',
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 侧边栏折叠
|
||||||
|
*/
|
||||||
|
sidebarCollapse: false,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 布局模式
|
||||||
|
* default / classic / transverse / columns
|
||||||
|
*/
|
||||||
|
layout: 'default',
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否开启水印
|
||||||
|
*/
|
||||||
|
watermark: false,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 水印配置
|
||||||
|
*/
|
||||||
|
watermarkConfig: {
|
||||||
|
text: 'SAMS',
|
||||||
|
fontColor: '#333',
|
||||||
|
fontSize: 16,
|
||||||
|
rotate: -30,
|
||||||
|
zIndex: 1000
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
const TokenKey = 'Admin-Token'
|
||||||
|
|
||||||
|
export function getToken() {
|
||||||
|
return localStorage.getItem(TokenKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setToken(token) {
|
||||||
|
return localStorage.setItem(TokenKey, token)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function removeToken() {
|
||||||
|
return localStorage.removeItem(TokenKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getUserInfo() {
|
||||||
|
const userInfo = localStorage.getItem('userInfo')
|
||||||
|
return userInfo ? JSON.parse(userInfo) : null
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setUserInfo(userInfo) {
|
||||||
|
return localStorage.setItem('userInfo', JSON.stringify(userInfo))
|
||||||
|
}
|
||||||
|
|
||||||
|
export function removeUserInfo() {
|
||||||
|
return localStorage.removeItem('userInfo')
|
||||||
|
}
|
||||||
|
|
@ -1,31 +1,62 @@
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
import { ElMessage } from 'element-plus'
|
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||||
|
import { getToken } from '@/utils/auth'
|
||||||
|
import config from '@/config'
|
||||||
|
|
||||||
|
// 创建axios实例
|
||||||
const service = axios.create({
|
const service = axios.create({
|
||||||
baseURL: '/api',
|
baseURL: config.baseUrl,
|
||||||
timeout: 5000
|
timeout: 10000
|
||||||
})
|
})
|
||||||
|
|
||||||
service.interceptors.request.use(config => {
|
// 请求拦截器
|
||||||
const token = localStorage.getItem('token')
|
service.interceptors.request.use(
|
||||||
|
config => {
|
||||||
// 只给非登录接口加 token
|
const token = getToken()
|
||||||
if (token && config.url !== '/login') {
|
if (token && config.url !== '/login') {
|
||||||
config.headers.Authorization = `Bearer ${token}`
|
config.headers.Authorization = `Bearer ${token}`
|
||||||
}
|
}
|
||||||
|
return config
|
||||||
return config
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
service.interceptors.response.use(
|
|
||||||
res => {
|
|
||||||
if (res.data.code === 200) return res.data
|
|
||||||
ElMessage.error(res.data.message || '请求出错')
|
|
||||||
return Promise.reject(new Error(res.data.message || 'Error'))
|
|
||||||
},
|
},
|
||||||
error => {
|
error => {
|
||||||
ElMessage.error(error.response?.data?.message || '服务器异常')
|
console.log(error)
|
||||||
|
return Promise.reject(error)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// 响应拦截器
|
||||||
|
service.interceptors.response.use(
|
||||||
|
response => {
|
||||||
|
const res = response.data
|
||||||
|
if (res.code !== 200) {
|
||||||
|
ElMessage({
|
||||||
|
message: res.message || '系统错误',
|
||||||
|
type: 'error',
|
||||||
|
duration: 5 * 1000
|
||||||
|
})
|
||||||
|
|
||||||
|
// 401: 未登录或token过期
|
||||||
|
if (res.code === 401) {
|
||||||
|
ElMessageBox.confirm('登录状态已过期,请重新登录', '系统提示', {
|
||||||
|
confirmButtonText: '重新登录',
|
||||||
|
cancelButtonText: '取消',
|
||||||
|
type: 'warning'
|
||||||
|
}).then(() => {
|
||||||
|
location.reload()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return Promise.reject(new Error(res.message || '系统错误'))
|
||||||
|
} else {
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
},
|
||||||
|
error => {
|
||||||
|
console.log('err' + error)
|
||||||
|
ElMessage({
|
||||||
|
message: error.message,
|
||||||
|
type: 'error',
|
||||||
|
duration: 5 * 1000
|
||||||
|
})
|
||||||
return Promise.reject(error)
|
return Promise.reject(error)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,277 @@
|
||||||
|
<template>
|
||||||
|
<div class="app-container">
|
||||||
|
<el-card class="box-card">
|
||||||
|
<template #header>
|
||||||
|
<div class="card-header">
|
||||||
|
<span>活动列表</span>
|
||||||
|
<el-button type="primary" @click="handleAdd">新增活动</el-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<el-form :inline="true" :model="queryParams" class="demo-form-inline">
|
||||||
|
<el-form-item label="活动名称">
|
||||||
|
<el-input v-model="queryParams.title" placeholder="请输入活动名称" clearable />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="活动状态">
|
||||||
|
<el-select v-model="queryParams.status" placeholder="请选择活动状态" clearable>
|
||||||
|
<el-option label="进行中" value="ACTIVE" />
|
||||||
|
<el-option label="已结束" value="ENDED" />
|
||||||
|
<el-option label="已取消" value="CANCELLED" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<el-button type="primary" @click="handleQuery">查询</el-button>
|
||||||
|
<el-button @click="resetQuery">重置</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
|
||||||
|
<el-table v-loading="loading" :data="activityList" style="width: 100%">
|
||||||
|
<el-table-column prop="title" label="活动名称" />
|
||||||
|
<el-table-column prop="description" label="活动描述" show-overflow-tooltip />
|
||||||
|
<el-table-column prop="startTime" label="开始时间" width="180" />
|
||||||
|
<el-table-column prop="endTime" label="结束时间" width="180" />
|
||||||
|
<el-table-column prop="location" label="活动地点" width="150" />
|
||||||
|
<el-table-column prop="status" label="状态" width="100">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-tag :type="getStatusType(scope.row.status)">
|
||||||
|
{{ getStatusText(scope.row.status) }}
|
||||||
|
</el-tag>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="操作" width="200" fixed="right">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-button type="primary" link @click="handleEdit(scope.row)">编辑</el-button>
|
||||||
|
<el-button type="primary" link @click="handleView(scope.row)">查看</el-button>
|
||||||
|
<el-button type="danger" link @click="handleDelete(scope.row)">删除</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
|
||||||
|
<div class="pagination-container">
|
||||||
|
<el-pagination
|
||||||
|
v-model:current-page="queryParams.page"
|
||||||
|
v-model:page-size="queryParams.size"
|
||||||
|
:page-sizes="[10, 20, 50, 100]"
|
||||||
|
:total="total"
|
||||||
|
layout="total, sizes, prev, pager, next, jumper"
|
||||||
|
@size-change="handleSizeChange"
|
||||||
|
@current-change="handleCurrentChange"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</el-card>
|
||||||
|
|
||||||
|
<!-- 添加或修改活动对话框 -->
|
||||||
|
<el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body>
|
||||||
|
<el-form ref="activityFormRef" :model="form" :rules="rules" label-width="80px">
|
||||||
|
<el-form-item label="活动名称" prop="title">
|
||||||
|
<el-input v-model="form.title" placeholder="请输入活动名称" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="活动描述" prop="description">
|
||||||
|
<el-input v-model="form.description" type="textarea" placeholder="请输入活动描述" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="开始时间" prop="startTime">
|
||||||
|
<el-date-picker
|
||||||
|
v-model="form.startTime"
|
||||||
|
type="datetime"
|
||||||
|
placeholder="选择开始时间"
|
||||||
|
value-format="YYYY-MM-DD HH:mm:ss"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="结束时间" prop="endTime">
|
||||||
|
<el-date-picker
|
||||||
|
v-model="form.endTime"
|
||||||
|
type="datetime"
|
||||||
|
placeholder="选择结束时间"
|
||||||
|
value-format="YYYY-MM-DD HH:mm:ss"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="活动地点" prop="location">
|
||||||
|
<el-input v-model="form.location" placeholder="请输入活动地点" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<template #footer>
|
||||||
|
<div class="dialog-footer">
|
||||||
|
<el-button type="primary" @click="submitForm">确 定</el-button>
|
||||||
|
<el-button @click="cancel">取 消</el-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref, onMounted } from 'vue'
|
||||||
|
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||||
|
import { getActivityList, createActivity, updateActivity, deleteActivity } from '@/api/activity/activity'
|
||||||
|
|
||||||
|
const loading = ref(false)
|
||||||
|
const activityList = ref([])
|
||||||
|
const total = ref(0)
|
||||||
|
|
||||||
|
const queryParams = ref({
|
||||||
|
page: 1,
|
||||||
|
size: 10,
|
||||||
|
title: '',
|
||||||
|
status: ''
|
||||||
|
})
|
||||||
|
|
||||||
|
const dialog = ref({
|
||||||
|
visible: false,
|
||||||
|
title: ''
|
||||||
|
})
|
||||||
|
|
||||||
|
const form = ref({
|
||||||
|
id: undefined,
|
||||||
|
title: '',
|
||||||
|
description: '',
|
||||||
|
startTime: '',
|
||||||
|
endTime: '',
|
||||||
|
location: ''
|
||||||
|
})
|
||||||
|
|
||||||
|
const rules = {
|
||||||
|
title: [{ required: true, message: '请输入活动名称', trigger: 'blur' }],
|
||||||
|
description: [{ required: true, message: '请输入活动描述', trigger: 'blur' }],
|
||||||
|
startTime: [{ required: true, message: '请选择开始时间', trigger: 'change' }],
|
||||||
|
endTime: [{ required: true, message: '请选择结束时间', trigger: 'change' }],
|
||||||
|
location: [{ required: true, message: '请输入活动地点', trigger: 'blur' }]
|
||||||
|
}
|
||||||
|
|
||||||
|
const getStatusType = (status) => {
|
||||||
|
const statusMap = {
|
||||||
|
ACTIVE: 'success',
|
||||||
|
ENDED: 'info',
|
||||||
|
CANCELLED: 'danger'
|
||||||
|
}
|
||||||
|
return statusMap[status] || 'info'
|
||||||
|
}
|
||||||
|
|
||||||
|
const getStatusText = (status) => {
|
||||||
|
const statusMap = {
|
||||||
|
ACTIVE: '进行中',
|
||||||
|
ENDED: '已结束',
|
||||||
|
CANCELLED: '已取消'
|
||||||
|
}
|
||||||
|
return statusMap[status] || '未知'
|
||||||
|
}
|
||||||
|
|
||||||
|
const getList = async () => {
|
||||||
|
loading.value = true
|
||||||
|
try {
|
||||||
|
const res = await getActivityList(queryParams.value)
|
||||||
|
activityList.value = res.data.records
|
||||||
|
total.value = res.data.total
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取活动列表失败:', error)
|
||||||
|
} finally {
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleQuery = () => {
|
||||||
|
queryParams.value.page = 1
|
||||||
|
getList()
|
||||||
|
}
|
||||||
|
|
||||||
|
const resetQuery = () => {
|
||||||
|
queryParams.value = {
|
||||||
|
page: 1,
|
||||||
|
size: 10,
|
||||||
|
title: '',
|
||||||
|
status: ''
|
||||||
|
}
|
||||||
|
getList()
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleSizeChange = (val) => {
|
||||||
|
queryParams.value.size = val
|
||||||
|
getList()
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleCurrentChange = (val) => {
|
||||||
|
queryParams.value.page = val
|
||||||
|
getList()
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleAdd = () => {
|
||||||
|
dialog.value = {
|
||||||
|
visible: true,
|
||||||
|
title: '添加活动'
|
||||||
|
}
|
||||||
|
form.value = {
|
||||||
|
id: undefined,
|
||||||
|
title: '',
|
||||||
|
description: '',
|
||||||
|
startTime: '',
|
||||||
|
endTime: '',
|
||||||
|
location: ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleEdit = (row) => {
|
||||||
|
dialog.value = {
|
||||||
|
visible: true,
|
||||||
|
title: '修改活动'
|
||||||
|
}
|
||||||
|
form.value = { ...row }
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleView = (row) => {
|
||||||
|
// TODO: 实现查看详情功能
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleDelete = (row) => {
|
||||||
|
ElMessageBox.confirm('确认要删除该活动吗?', '警告', {
|
||||||
|
confirmButtonText: '确定',
|
||||||
|
cancelButtonText: '取消',
|
||||||
|
type: 'warning'
|
||||||
|
}).then(async () => {
|
||||||
|
try {
|
||||||
|
await deleteActivity(row.id)
|
||||||
|
ElMessage.success('删除成功')
|
||||||
|
getList()
|
||||||
|
} catch (error) {
|
||||||
|
console.error('删除活动失败:', error)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const submitForm = async () => {
|
||||||
|
try {
|
||||||
|
if (form.value.id) {
|
||||||
|
await updateActivity(form.value)
|
||||||
|
ElMessage.success('修改成功')
|
||||||
|
} else {
|
||||||
|
await createActivity(form.value)
|
||||||
|
ElMessage.success('新增成功')
|
||||||
|
}
|
||||||
|
dialog.value.visible = false
|
||||||
|
getList()
|
||||||
|
} catch (error) {
|
||||||
|
console.error('提交表单失败:', error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const cancel = () => {
|
||||||
|
dialog.value.visible = false
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
getList()
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.app-container {
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
.card-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
.pagination-container {
|
||||||
|
margin-top: 20px;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,310 @@
|
||||||
|
<template>
|
||||||
|
<div class="app-container">
|
||||||
|
<el-card class="box-card">
|
||||||
|
<template #header>
|
||||||
|
<div class="card-header">
|
||||||
|
<span>社团列表</span>
|
||||||
|
<el-button type="primary" @click="handleAdd">新增社团</el-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<el-form :inline="true" :model="queryParams" class="demo-form-inline">
|
||||||
|
<el-form-item label="社团名称">
|
||||||
|
<el-input v-model="queryParams.name" placeholder="请输入社团名称" clearable />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="所属学院">
|
||||||
|
<el-select v-model="queryParams.collegeId" placeholder="请选择学院" clearable>
|
||||||
|
<el-option
|
||||||
|
v-for="item in collegeOptions"
|
||||||
|
:key="item.id"
|
||||||
|
:label="item.name"
|
||||||
|
:value="item.id"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<el-button type="primary" @click="handleQuery">查询</el-button>
|
||||||
|
<el-button @click="resetQuery">重置</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
|
||||||
|
<el-table v-loading="loading" :data="clubList" style="width: 100%">
|
||||||
|
<el-table-column prop="name" label="社团名称" />
|
||||||
|
<el-table-column prop="description" label="社团描述" show-overflow-tooltip />
|
||||||
|
<el-table-column prop="collegeName" label="所属学院" width="150" />
|
||||||
|
<el-table-column prop="memberCount" label="成员数" width="100" />
|
||||||
|
<el-table-column prop="activityCount" label="活动数" width="100" />
|
||||||
|
<el-table-column prop="createTime" label="创建时间" width="180" />
|
||||||
|
<el-table-column label="操作" width="250" fixed="right">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-button type="primary" link @click="handleEdit(scope.row)">编辑</el-button>
|
||||||
|
<el-button type="primary" link @click="handleView(scope.row)">查看</el-button>
|
||||||
|
<el-button type="primary" link @click="handleMembers(scope.row)">成员管理</el-button>
|
||||||
|
<el-button type="danger" link @click="handleDelete(scope.row)">删除</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
|
||||||
|
<div class="pagination-container">
|
||||||
|
<el-pagination
|
||||||
|
v-model:current-page="queryParams.page"
|
||||||
|
v-model:page-size="queryParams.size"
|
||||||
|
:page-sizes="[10, 20, 50, 100]"
|
||||||
|
:total="total"
|
||||||
|
layout="total, sizes, prev, pager, next, jumper"
|
||||||
|
@size-change="handleSizeChange"
|
||||||
|
@current-change="handleCurrentChange"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</el-card>
|
||||||
|
|
||||||
|
<!-- 添加或修改社团对话框 -->
|
||||||
|
<el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body>
|
||||||
|
<el-form ref="clubFormRef" :model="form" :rules="rules" label-width="80px">
|
||||||
|
<el-form-item label="社团名称" prop="name">
|
||||||
|
<el-input v-model="form.name" placeholder="请输入社团名称" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="社团描述" prop="description">
|
||||||
|
<el-input v-model="form.description" type="textarea" placeholder="请输入社团描述" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="所属学院" prop="collegeId">
|
||||||
|
<el-select v-model="form.collegeId" placeholder="请选择学院">
|
||||||
|
<el-option
|
||||||
|
v-for="item in collegeOptions"
|
||||||
|
:key="item.id"
|
||||||
|
:label="item.name"
|
||||||
|
:value="item.id"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<template #footer>
|
||||||
|
<div class="dialog-footer">
|
||||||
|
<el-button type="primary" @click="submitForm">确 定</el-button>
|
||||||
|
<el-button @click="cancel">取 消</el-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
|
||||||
|
<!-- 成员管理对话框 -->
|
||||||
|
<el-dialog title="成员管理" v-model="memberDialog.visible" width="800px" append-to-body>
|
||||||
|
<el-table :data="memberDialog.members" style="width: 100%">
|
||||||
|
<el-table-column prop="username" label="用户名" />
|
||||||
|
<el-table-column prop="realName" label="姓名" />
|
||||||
|
<el-table-column prop="role" label="角色" width="100">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-tag :type="scope.row.role === 'ADMIN' ? 'danger' : 'info'">
|
||||||
|
{{ scope.row.role === 'ADMIN' ? '管理员' : '普通成员' }}
|
||||||
|
</el-tag>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="joinTime" label="加入时间" width="180" />
|
||||||
|
<el-table-column label="操作" width="150" fixed="right">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-button type="danger" link @click="handleRemoveMember(scope.row)">移除</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
<template #footer>
|
||||||
|
<div class="dialog-footer">
|
||||||
|
<el-button type="primary" @click="handleAddMember">添加成员</el-button>
|
||||||
|
<el-button @click="memberDialog.visible = false">关 闭</el-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref, onMounted } from 'vue'
|
||||||
|
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||||
|
import { getClubList, addClub, updateClub, deleteClub, getClubMembers, removeClubMember } from '@/api/club/club'
|
||||||
|
|
||||||
|
const loading = ref(false)
|
||||||
|
const clubList = ref([])
|
||||||
|
const total = ref(0)
|
||||||
|
const collegeOptions = ref([])
|
||||||
|
|
||||||
|
const queryParams = ref({
|
||||||
|
page: 1,
|
||||||
|
size: 10,
|
||||||
|
name: '',
|
||||||
|
collegeId: undefined
|
||||||
|
})
|
||||||
|
|
||||||
|
const dialog = ref({
|
||||||
|
visible: false,
|
||||||
|
title: ''
|
||||||
|
})
|
||||||
|
|
||||||
|
const memberDialog = ref({
|
||||||
|
visible: false,
|
||||||
|
clubId: undefined,
|
||||||
|
members: []
|
||||||
|
})
|
||||||
|
|
||||||
|
const form = ref({
|
||||||
|
id: undefined,
|
||||||
|
name: '',
|
||||||
|
description: '',
|
||||||
|
collegeId: undefined
|
||||||
|
})
|
||||||
|
|
||||||
|
const rules = {
|
||||||
|
name: [{ required: true, message: '请输入社团名称', trigger: 'blur' }],
|
||||||
|
description: [{ required: true, message: '请输入社团描述', trigger: 'blur' }],
|
||||||
|
collegeId: [{ required: true, message: '请选择所属学院', trigger: 'change' }]
|
||||||
|
}
|
||||||
|
|
||||||
|
const getList = async () => {
|
||||||
|
loading.value = true
|
||||||
|
try {
|
||||||
|
const res = await getClubList(queryParams.value)
|
||||||
|
clubList.value = res.data.records
|
||||||
|
total.value = res.data.total
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取社团列表失败:', error)
|
||||||
|
} finally {
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleQuery = () => {
|
||||||
|
queryParams.value.page = 1
|
||||||
|
getList()
|
||||||
|
}
|
||||||
|
|
||||||
|
const resetQuery = () => {
|
||||||
|
queryParams.value = {
|
||||||
|
page: 1,
|
||||||
|
size: 10,
|
||||||
|
name: '',
|
||||||
|
collegeId: undefined
|
||||||
|
}
|
||||||
|
getList()
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleSizeChange = (val) => {
|
||||||
|
queryParams.value.size = val
|
||||||
|
getList()
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleCurrentChange = (val) => {
|
||||||
|
queryParams.value.page = val
|
||||||
|
getList()
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleAdd = () => {
|
||||||
|
dialog.value = {
|
||||||
|
visible: true,
|
||||||
|
title: '添加社团'
|
||||||
|
}
|
||||||
|
form.value = {
|
||||||
|
id: undefined,
|
||||||
|
name: '',
|
||||||
|
description: '',
|
||||||
|
collegeId: undefined
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleEdit = (row) => {
|
||||||
|
dialog.value = {
|
||||||
|
visible: true,
|
||||||
|
title: '修改社团'
|
||||||
|
}
|
||||||
|
form.value = { ...row }
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleView = (row) => {
|
||||||
|
// TODO: 实现查看详情功能
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleDelete = (row) => {
|
||||||
|
ElMessageBox.confirm('确认要删除该社团吗?', '警告', {
|
||||||
|
confirmButtonText: '确定',
|
||||||
|
cancelButtonText: '取消',
|
||||||
|
type: 'warning'
|
||||||
|
}).then(async () => {
|
||||||
|
try {
|
||||||
|
await deleteClub(row.id)
|
||||||
|
ElMessage.success('删除成功')
|
||||||
|
getList()
|
||||||
|
} catch (error) {
|
||||||
|
console.error('删除社团失败:', error)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleMembers = async (row) => {
|
||||||
|
memberDialog.value = {
|
||||||
|
visible: true,
|
||||||
|
clubId: row.id,
|
||||||
|
members: []
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
const res = await getClubMembers(row.id)
|
||||||
|
memberDialog.value.members = res.data
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取社团成员失败:', error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleAddMember = () => {
|
||||||
|
// TODO: 实现添加成员功能
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleRemoveMember = (row) => {
|
||||||
|
ElMessageBox.confirm('确认要移除该成员吗?', '警告', {
|
||||||
|
confirmButtonText: '确定',
|
||||||
|
cancelButtonText: '取消',
|
||||||
|
type: 'warning'
|
||||||
|
}).then(async () => {
|
||||||
|
try {
|
||||||
|
await removeClubMember(memberDialog.value.clubId, row.id)
|
||||||
|
ElMessage.success('移除成功')
|
||||||
|
handleMembers({ id: memberDialog.value.clubId })
|
||||||
|
} catch (error) {
|
||||||
|
console.error('移除成员失败:', error)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const submitForm = async () => {
|
||||||
|
try {
|
||||||
|
if (form.value.id) {
|
||||||
|
await updateClub(form.value)
|
||||||
|
ElMessage.success('修改成功')
|
||||||
|
} else {
|
||||||
|
await addClub(form.value)
|
||||||
|
ElMessage.success('新增成功')
|
||||||
|
}
|
||||||
|
dialog.value.visible = false
|
||||||
|
getList()
|
||||||
|
} catch (error) {
|
||||||
|
console.error('提交表单失败:', error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const cancel = () => {
|
||||||
|
dialog.value.visible = false
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
getList()
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.app-container {
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
.card-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
.pagination-container {
|
||||||
|
margin-top: 20px;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,169 @@
|
||||||
|
<template>
|
||||||
|
<div class="home-container">
|
||||||
|
<el-row :gutter="20">
|
||||||
|
<el-col :span="6">
|
||||||
|
<el-card class="box-card">
|
||||||
|
<template #header>
|
||||||
|
<div class="card-header">
|
||||||
|
<span>社团总数</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="number">{{ statistics.clubCount }}</div>
|
||||||
|
</div>
|
||||||
|
</el-card>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="6">
|
||||||
|
<el-card class="box-card">
|
||||||
|
<template #header>
|
||||||
|
<div class="card-header">
|
||||||
|
<span>活动总数</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="number">{{ statistics.activityCount }}</div>
|
||||||
|
</div>
|
||||||
|
</el-card>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="6">
|
||||||
|
<el-card class="box-card">
|
||||||
|
<template #header>
|
||||||
|
<div class="card-header">
|
||||||
|
<span>成员总数</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="number">{{ statistics.memberCount }}</div>
|
||||||
|
</div>
|
||||||
|
</el-card>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="6">
|
||||||
|
<el-card class="box-card">
|
||||||
|
<template #header>
|
||||||
|
<div class="card-header">
|
||||||
|
<span>今日活动</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="number">{{ statistics.todayActivityCount }}</div>
|
||||||
|
</div>
|
||||||
|
</el-card>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
<el-row :gutter="20" class="mt-20">
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-card class="box-card">
|
||||||
|
<template #header>
|
||||||
|
<div class="card-header">
|
||||||
|
<span>最近活动</span>
|
||||||
|
<el-button type="text" @click="$router.push('/activity/list')">查看更多</el-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<div class="activity-list">
|
||||||
|
<el-table :data="recentActivities" style="width: 100%">
|
||||||
|
<el-table-column prop="title" label="活动名称" />
|
||||||
|
<el-table-column prop="startTime" label="开始时间" width="180" />
|
||||||
|
<el-table-column prop="status" label="状态" width="100">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-tag :type="scope.row.status === 'ACTIVE' ? 'success' : 'info'">
|
||||||
|
{{ scope.row.status === 'ACTIVE' ? '进行中' : '已结束' }}
|
||||||
|
</el-tag>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
</div>
|
||||||
|
</el-card>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-card class="box-card">
|
||||||
|
<template #header>
|
||||||
|
<div class="card-header">
|
||||||
|
<span>热门社团</span>
|
||||||
|
<el-button type="text" @click="$router.push('/club/list')">查看更多</el-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<div class="club-list">
|
||||||
|
<el-table :data="popularClubs" style="width: 100%">
|
||||||
|
<el-table-column prop="name" label="社团名称" />
|
||||||
|
<el-table-column prop="memberCount" label="成员数" width="100" />
|
||||||
|
<el-table-column prop="activityCount" label="活动数" width="100" />
|
||||||
|
</el-table>
|
||||||
|
</div>
|
||||||
|
</el-card>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref, onMounted } from 'vue'
|
||||||
|
import { getActivityList } from '@/api/activity/activity'
|
||||||
|
import { getClubList } from '@/api/club/club'
|
||||||
|
|
||||||
|
const statistics = ref({
|
||||||
|
clubCount: 0,
|
||||||
|
activityCount: 0,
|
||||||
|
memberCount: 0,
|
||||||
|
todayActivityCount: 0
|
||||||
|
})
|
||||||
|
|
||||||
|
const recentActivities = ref([])
|
||||||
|
const popularClubs = ref([])
|
||||||
|
|
||||||
|
const fetchData = async () => {
|
||||||
|
try {
|
||||||
|
// 获取活动列表
|
||||||
|
const activityRes = await getActivityList({ page: 1, size: 5 })
|
||||||
|
recentActivities.value = activityRes.data.records
|
||||||
|
|
||||||
|
// 获取社团列表
|
||||||
|
const clubRes = await getClubList({ page: 1, size: 5 })
|
||||||
|
popularClubs.value = clubRes.data.records
|
||||||
|
|
||||||
|
// 更新统计数据
|
||||||
|
statistics.value = {
|
||||||
|
clubCount: clubRes.data.total,
|
||||||
|
activityCount: activityRes.data.total,
|
||||||
|
memberCount: clubRes.data.records.reduce((sum, club) => sum + club.memberCount, 0),
|
||||||
|
todayActivityCount: activityRes.data.records.filter(activity => {
|
||||||
|
const today = new Date().toISOString().split('T')[0]
|
||||||
|
return activity.startTime.startsWith(today)
|
||||||
|
}).length
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取数据失败:', error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
fetchData()
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.home-container {
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
.mt-20 {
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
.card-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
.card-body {
|
||||||
|
text-align: center;
|
||||||
|
padding: 20px 0;
|
||||||
|
}
|
||||||
|
.number {
|
||||||
|
font-size: 36px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #409EFF;
|
||||||
|
}
|
||||||
|
.activity-list,
|
||||||
|
.club-list {
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -2,10 +2,10 @@
|
||||||
<div class="login-page">
|
<div class="login-page">
|
||||||
<div class="login-left">
|
<div class="login-left">
|
||||||
<div class="login-box">
|
<div class="login-box">
|
||||||
<h2 class="title">欢迎登录</h2>
|
<h2 class="title">SAMS学生社团管理系统</h2>
|
||||||
<el-form :model="loginForm" :rules="loginRules" ref="loginRef" label-position="top" size="large">
|
<el-form :model="loginForm" :rules="loginRules" ref="loginRef" label-position="top" size="large">
|
||||||
<el-form-item label="账号登录" prop="account">
|
<el-form-item label="账号登录" prop="username">
|
||||||
<el-input v-model="loginForm.account" placeholder="请输入用户名 / 学号 / 邮箱" />
|
<el-input v-model="loginForm.username" placeholder="请输入用户名 / 学号 / 邮箱" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item label="密码" prop="password">
|
<el-form-item label="密码" prop="password">
|
||||||
|
|
@ -32,20 +32,21 @@
|
||||||
import { ref } from 'vue'
|
import { ref } from 'vue'
|
||||||
import { useRouter } from 'vue-router'
|
import { useRouter } from 'vue-router'
|
||||||
import { ElMessage } from 'element-plus'
|
import { ElMessage } from 'element-plus'
|
||||||
import { login } from '@/api/auth'
|
import { login } from '@/api/system/user'
|
||||||
|
import { setToken, setUserInfo } from '@/utils/auth'
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const loginRef = ref(null)
|
const loginRef = ref(null)
|
||||||
const loading = ref(false)
|
const loading = ref(false)
|
||||||
|
|
||||||
const loginForm = ref({
|
const loginForm = ref({
|
||||||
account: '',
|
username: '',
|
||||||
password: '',
|
password: '',
|
||||||
remember: false
|
remember: false
|
||||||
})
|
})
|
||||||
|
|
||||||
const loginRules = {
|
const loginRules = {
|
||||||
account: [{ required: true, message: '请输入用户名/学号/邮箱', trigger: 'blur' }],
|
username: [{ required: true, message: '请输入用户名/学号/邮箱', trigger: 'blur' }],
|
||||||
password: [{ required: true, message: '请输入密码', trigger: 'blur' }]
|
password: [{ required: true, message: '请输入密码', trigger: 'blur' }]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -54,22 +55,13 @@ const submitLogin = () => {
|
||||||
if (!valid) return
|
if (!valid) return
|
||||||
loading.value = true
|
loading.value = true
|
||||||
try {
|
try {
|
||||||
const token = await login(loginForm.value)
|
const res = await login(loginForm.value)
|
||||||
localStorage.setItem('token', token)
|
setToken(res.data.token)
|
||||||
|
setUserInfo(res.data.userInfo)
|
||||||
ElMessage.success('登录成功')
|
ElMessage.success('登录成功')
|
||||||
// 登录成功后
|
router.push('/')
|
||||||
const payload = jwtDecode(token)
|
} catch (error) {
|
||||||
const roles = Array.isArray(payload.role) ? payload.role : [payload.role]
|
ElMessage.error(error.message || '登录失败')
|
||||||
|
|
||||||
if (roles.includes('PARTICIPANT')) {
|
|
||||||
router.push('/user/home')
|
|
||||||
} else if (roles.includes('COLLEGE_ADMIN') ||roles.includes('DEPARTMENT_ADMIN') ||roles.includes('CLUB_ADMIN') ) {
|
|
||||||
router.push('/admin/home')
|
|
||||||
} else {
|
|
||||||
router.push('/403') // 无匹配权限
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
ElMessage.error(e.message || '登录失败')
|
|
||||||
} finally {
|
} finally {
|
||||||
loading.value = false
|
loading.value = false
|
||||||
}
|
}
|
||||||
|
|
@ -97,6 +89,7 @@ const submitLogin = () => {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
margin-bottom: 32px;
|
margin-bottom: 32px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
color: #409EFF;
|
||||||
}
|
}
|
||||||
.login-btn {
|
.login-btn {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue