v0.3.1 前端重做
parent
260a85d8f3
commit
89775e7084
|
|
@ -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 标准
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 207 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 613 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 122 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 126 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 212 KiB |
|
|
@ -9,8 +9,10 @@
|
||||||
"preview": "vite preview"
|
"preview": "vite preview"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@element-plus/icons-vue": "^2.3.1",
|
||||||
"axios": "^1.8.4",
|
"axios": "^1.8.4",
|
||||||
"element-plus": "^2.9.7",
|
"element-plus": "^2.9.7",
|
||||||
|
"icons-vue": "^1.0.9",
|
||||||
"jwt-decode": "^4.0.0",
|
"jwt-decode": "^4.0.0",
|
||||||
"pinia": "^3.0.1",
|
"pinia": "^3.0.1",
|
||||||
"vue": "^3.5.13",
|
"vue": "^3.5.13",
|
||||||
|
|
|
||||||
|
|
@ -8,28 +8,34 @@ importers:
|
||||||
|
|
||||||
.:
|
.:
|
||||||
dependencies:
|
dependencies:
|
||||||
|
'@element-plus/icons-vue':
|
||||||
|
specifier: ^2.3.1
|
||||||
|
version: 2.3.1(vue@3.5.13(typescript@4.9.5))
|
||||||
axios:
|
axios:
|
||||||
specifier: ^1.8.4
|
specifier: ^1.8.4
|
||||||
version: 1.8.4
|
version: 1.8.4
|
||||||
element-plus:
|
element-plus:
|
||||||
specifier: ^2.9.7
|
specifier: ^2.9.7
|
||||||
version: 2.9.7(vue@3.5.13)
|
version: 2.9.7(vue@3.5.13(typescript@4.9.5))
|
||||||
|
icons-vue:
|
||||||
|
specifier: ^1.0.9
|
||||||
|
version: 1.0.9(vue@3.5.13(typescript@4.9.5))
|
||||||
jwt-decode:
|
jwt-decode:
|
||||||
specifier: ^4.0.0
|
specifier: ^4.0.0
|
||||||
version: 4.0.0
|
version: 4.0.0
|
||||||
pinia:
|
pinia:
|
||||||
specifier: ^3.0.1
|
specifier: ^3.0.1
|
||||||
version: 3.0.1(vue@3.5.13)
|
version: 3.0.1(typescript@4.9.5)(vue@3.5.13(typescript@4.9.5))
|
||||||
vue:
|
vue:
|
||||||
specifier: ^3.5.13
|
specifier: ^3.5.13
|
||||||
version: 3.5.13
|
version: 3.5.13(typescript@4.9.5)
|
||||||
vue-router:
|
vue-router:
|
||||||
specifier: '4'
|
specifier: '4'
|
||||||
version: 4.5.0(vue@3.5.13)
|
version: 4.5.0(vue@3.5.13(typescript@4.9.5))
|
||||||
devDependencies:
|
devDependencies:
|
||||||
'@vitejs/plugin-vue':
|
'@vitejs/plugin-vue':
|
||||||
specifier: ^5.2.1
|
specifier: ^5.2.1
|
||||||
version: 5.2.3(vite@6.2.2)(vue@3.5.13)
|
version: 5.2.3(vite@6.2.2)(vue@3.5.13(typescript@4.9.5))
|
||||||
vite:
|
vite:
|
||||||
specifier: ^6.2.0
|
specifier: ^6.2.0
|
||||||
version: 6.2.2
|
version: 6.2.2
|
||||||
|
|
@ -513,6 +519,11 @@ packages:
|
||||||
hookable@5.5.3:
|
hookable@5.5.3:
|
||||||
resolution: {integrity: sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==}
|
resolution: {integrity: sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==}
|
||||||
|
|
||||||
|
icons-vue@1.0.9:
|
||||||
|
resolution: {integrity: sha512-9/yH38wV4fRmPq3vncy5pofA0jfNlT8UDzXJOtRLGn8ap8Gy6B9YBO4Unj6pz5jg4MdmN49D6IiqDzqr5Ec2IQ==}
|
||||||
|
peerDependencies:
|
||||||
|
vue: '>=3.0.3'
|
||||||
|
|
||||||
is-what@4.1.16:
|
is-what@4.1.16:
|
||||||
resolution: {integrity: sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A==}
|
resolution: {integrity: sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A==}
|
||||||
engines: {node: '>=12.13'}
|
engines: {node: '>=12.13'}
|
||||||
|
|
@ -605,6 +616,11 @@ packages:
|
||||||
resolution: {integrity: sha512-5JRxVqC8I8NuOUjzBbvVJAKNM8qoVuH0O77h4WInc/qC2q5IreqKxYwgkga3PfA22OayK2ikceb/B26dztPl+Q==}
|
resolution: {integrity: sha512-5JRxVqC8I8NuOUjzBbvVJAKNM8qoVuH0O77h4WInc/qC2q5IreqKxYwgkga3PfA22OayK2ikceb/B26dztPl+Q==}
|
||||||
engines: {node: '>=16'}
|
engines: {node: '>=16'}
|
||||||
|
|
||||||
|
typescript@4.9.5:
|
||||||
|
resolution: {integrity: sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==}
|
||||||
|
engines: {node: '>=4.2.0'}
|
||||||
|
hasBin: true
|
||||||
|
|
||||||
vite@6.2.2:
|
vite@6.2.2:
|
||||||
resolution: {integrity: sha512-yW7PeMM+LkDzc7CgJuRLMW2Jz0FxMOsVJ8Lv3gpgW9WLcb9cTW+121UEr1hvmfR7w3SegR5ItvYyzVz1vxNJgQ==}
|
resolution: {integrity: sha512-yW7PeMM+LkDzc7CgJuRLMW2Jz0FxMOsVJ8Lv3gpgW9WLcb9cTW+121UEr1hvmfR7w3SegR5ItvYyzVz1vxNJgQ==}
|
||||||
engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0}
|
engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0}
|
||||||
|
|
@ -686,9 +702,9 @@ snapshots:
|
||||||
|
|
||||||
'@ctrl/tinycolor@3.6.1': {}
|
'@ctrl/tinycolor@3.6.1': {}
|
||||||
|
|
||||||
'@element-plus/icons-vue@2.3.1(vue@3.5.13)':
|
'@element-plus/icons-vue@2.3.1(vue@3.5.13(typescript@4.9.5))':
|
||||||
dependencies:
|
dependencies:
|
||||||
vue: 3.5.13
|
vue: 3.5.13(typescript@4.9.5)
|
||||||
|
|
||||||
'@esbuild/aix-ppc64@0.25.1':
|
'@esbuild/aix-ppc64@0.25.1':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
@ -847,10 +863,10 @@ snapshots:
|
||||||
|
|
||||||
'@types/web-bluetooth@0.0.16': {}
|
'@types/web-bluetooth@0.0.16': {}
|
||||||
|
|
||||||
'@vitejs/plugin-vue@5.2.3(vite@6.2.2)(vue@3.5.13)':
|
'@vitejs/plugin-vue@5.2.3(vite@6.2.2)(vue@3.5.13(typescript@4.9.5))':
|
||||||
dependencies:
|
dependencies:
|
||||||
vite: 6.2.2
|
vite: 6.2.2
|
||||||
vue: 3.5.13
|
vue: 3.5.13(typescript@4.9.5)
|
||||||
|
|
||||||
'@vue/compiler-core@3.5.13':
|
'@vue/compiler-core@3.5.13':
|
||||||
dependencies:
|
dependencies:
|
||||||
|
|
@ -918,29 +934,29 @@ snapshots:
|
||||||
'@vue/shared': 3.5.13
|
'@vue/shared': 3.5.13
|
||||||
csstype: 3.1.3
|
csstype: 3.1.3
|
||||||
|
|
||||||
'@vue/server-renderer@3.5.13(vue@3.5.13)':
|
'@vue/server-renderer@3.5.13(vue@3.5.13(typescript@4.9.5))':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@vue/compiler-ssr': 3.5.13
|
'@vue/compiler-ssr': 3.5.13
|
||||||
'@vue/shared': 3.5.13
|
'@vue/shared': 3.5.13
|
||||||
vue: 3.5.13
|
vue: 3.5.13(typescript@4.9.5)
|
||||||
|
|
||||||
'@vue/shared@3.5.13': {}
|
'@vue/shared@3.5.13': {}
|
||||||
|
|
||||||
'@vueuse/core@9.13.0(vue@3.5.13)':
|
'@vueuse/core@9.13.0(vue@3.5.13(typescript@4.9.5))':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/web-bluetooth': 0.0.16
|
'@types/web-bluetooth': 0.0.16
|
||||||
'@vueuse/metadata': 9.13.0
|
'@vueuse/metadata': 9.13.0
|
||||||
'@vueuse/shared': 9.13.0(vue@3.5.13)
|
'@vueuse/shared': 9.13.0(vue@3.5.13(typescript@4.9.5))
|
||||||
vue-demi: 0.14.10(vue@3.5.13)
|
vue-demi: 0.14.10(vue@3.5.13(typescript@4.9.5))
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- '@vue/composition-api'
|
- '@vue/composition-api'
|
||||||
- vue
|
- vue
|
||||||
|
|
||||||
'@vueuse/metadata@9.13.0': {}
|
'@vueuse/metadata@9.13.0': {}
|
||||||
|
|
||||||
'@vueuse/shared@9.13.0(vue@3.5.13)':
|
'@vueuse/shared@9.13.0(vue@3.5.13(typescript@4.9.5))':
|
||||||
dependencies:
|
dependencies:
|
||||||
vue-demi: 0.14.10(vue@3.5.13)
|
vue-demi: 0.14.10(vue@3.5.13(typescript@4.9.5))
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- '@vue/composition-api'
|
- '@vue/composition-api'
|
||||||
- vue
|
- vue
|
||||||
|
|
@ -984,15 +1000,15 @@ snapshots:
|
||||||
es-errors: 1.3.0
|
es-errors: 1.3.0
|
||||||
gopd: 1.2.0
|
gopd: 1.2.0
|
||||||
|
|
||||||
element-plus@2.9.7(vue@3.5.13):
|
element-plus@2.9.7(vue@3.5.13(typescript@4.9.5)):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@ctrl/tinycolor': 3.6.1
|
'@ctrl/tinycolor': 3.6.1
|
||||||
'@element-plus/icons-vue': 2.3.1(vue@3.5.13)
|
'@element-plus/icons-vue': 2.3.1(vue@3.5.13(typescript@4.9.5))
|
||||||
'@floating-ui/dom': 1.6.13
|
'@floating-ui/dom': 1.6.13
|
||||||
'@popperjs/core': '@sxzz/popperjs-es@2.11.7'
|
'@popperjs/core': '@sxzz/popperjs-es@2.11.7'
|
||||||
'@types/lodash': 4.17.16
|
'@types/lodash': 4.17.16
|
||||||
'@types/lodash-es': 4.17.12
|
'@types/lodash-es': 4.17.12
|
||||||
'@vueuse/core': 9.13.0(vue@3.5.13)
|
'@vueuse/core': 9.13.0(vue@3.5.13(typescript@4.9.5))
|
||||||
async-validator: 4.2.5
|
async-validator: 4.2.5
|
||||||
dayjs: 1.11.13
|
dayjs: 1.11.13
|
||||||
escape-html: 1.0.3
|
escape-html: 1.0.3
|
||||||
|
|
@ -1001,7 +1017,7 @@ snapshots:
|
||||||
lodash-unified: 1.0.3(@types/lodash-es@4.17.12)(lodash-es@4.17.21)(lodash@4.17.21)
|
lodash-unified: 1.0.3(@types/lodash-es@4.17.12)(lodash-es@4.17.21)(lodash@4.17.21)
|
||||||
memoize-one: 6.0.0
|
memoize-one: 6.0.0
|
||||||
normalize-wheel-es: 1.2.0
|
normalize-wheel-es: 1.2.0
|
||||||
vue: 3.5.13
|
vue: 3.5.13(typescript@4.9.5)
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- '@vue/composition-api'
|
- '@vue/composition-api'
|
||||||
|
|
||||||
|
|
@ -1100,6 +1116,11 @@ snapshots:
|
||||||
|
|
||||||
hookable@5.5.3: {}
|
hookable@5.5.3: {}
|
||||||
|
|
||||||
|
icons-vue@1.0.9(vue@3.5.13(typescript@4.9.5)):
|
||||||
|
dependencies:
|
||||||
|
typescript: 4.9.5
|
||||||
|
vue: 3.5.13(typescript@4.9.5)
|
||||||
|
|
||||||
is-what@4.1.16: {}
|
is-what@4.1.16: {}
|
||||||
|
|
||||||
jwt-decode@4.0.0: {}
|
jwt-decode@4.0.0: {}
|
||||||
|
|
@ -1138,10 +1159,12 @@ snapshots:
|
||||||
|
|
||||||
picocolors@1.1.1: {}
|
picocolors@1.1.1: {}
|
||||||
|
|
||||||
pinia@3.0.1(vue@3.5.13):
|
pinia@3.0.1(typescript@4.9.5)(vue@3.5.13(typescript@4.9.5)):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@vue/devtools-api': 7.7.2
|
'@vue/devtools-api': 7.7.2
|
||||||
vue: 3.5.13
|
vue: 3.5.13(typescript@4.9.5)
|
||||||
|
optionalDependencies:
|
||||||
|
typescript: 4.9.5
|
||||||
|
|
||||||
postcss@8.5.3:
|
postcss@8.5.3:
|
||||||
dependencies:
|
dependencies:
|
||||||
|
|
@ -1186,6 +1209,8 @@ snapshots:
|
||||||
dependencies:
|
dependencies:
|
||||||
copy-anything: 3.0.5
|
copy-anything: 3.0.5
|
||||||
|
|
||||||
|
typescript@4.9.5: {}
|
||||||
|
|
||||||
vite@6.2.2:
|
vite@6.2.2:
|
||||||
dependencies:
|
dependencies:
|
||||||
esbuild: 0.25.1
|
esbuild: 0.25.1
|
||||||
|
|
@ -1194,19 +1219,21 @@ snapshots:
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
fsevents: 2.3.3
|
fsevents: 2.3.3
|
||||||
|
|
||||||
vue-demi@0.14.10(vue@3.5.13):
|
vue-demi@0.14.10(vue@3.5.13(typescript@4.9.5)):
|
||||||
dependencies:
|
dependencies:
|
||||||
vue: 3.5.13
|
vue: 3.5.13(typescript@4.9.5)
|
||||||
|
|
||||||
vue-router@4.5.0(vue@3.5.13):
|
vue-router@4.5.0(vue@3.5.13(typescript@4.9.5)):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@vue/devtools-api': 6.6.4
|
'@vue/devtools-api': 6.6.4
|
||||||
vue: 3.5.13
|
vue: 3.5.13(typescript@4.9.5)
|
||||||
|
|
||||||
vue@3.5.13:
|
vue@3.5.13(typescript@4.9.5):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@vue/compiler-dom': 3.5.13
|
'@vue/compiler-dom': 3.5.13
|
||||||
'@vue/compiler-sfc': 3.5.13
|
'@vue/compiler-sfc': 3.5.13
|
||||||
'@vue/runtime-dom': 3.5.13
|
'@vue/runtime-dom': 3.5.13
|
||||||
'@vue/server-renderer': 3.5.13(vue@3.5.13)
|
'@vue/server-renderer': 3.5.13(vue@3.5.13(typescript@4.9.5))
|
||||||
'@vue/shared': 3.5.13
|
'@vue/shared': 3.5.13
|
||||||
|
optionalDependencies:
|
||||||
|
typescript: 4.9.5
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,56 @@
|
||||||
|
<template>
|
||||||
|
<el-row :gutter="20">
|
||||||
|
<el-col v-for="item in activities" :key="item.actId" :span="6">
|
||||||
|
<el-card class="activity-card" shadow="hover">
|
||||||
|
<h3 class="title">{{ item.title }}</h3>
|
||||||
|
<div class="meta">
|
||||||
|
<span><el-icon><Location /></el-icon> {{ item.location }}</span>
|
||||||
|
<span><el-icon><Calendar /></el-icon> {{ formatDate(item.startTime) }}</span>
|
||||||
|
</div>
|
||||||
|
<p class="desc">{{ item.description }}</p>
|
||||||
|
<el-button type="primary" size="small" @click="join(item.actId)">我要报名</el-button>
|
||||||
|
</el-card>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref, onMounted } from 'vue'
|
||||||
|
import { Location, Calendar } from '@element-plus/icons-vue'
|
||||||
|
// import { listHotActivities } from '@/api/activity'
|
||||||
|
import { ElMessage } from 'element-plus'
|
||||||
|
|
||||||
|
const activities = ref([])
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
activities.value = await listHotActivities()
|
||||||
|
})
|
||||||
|
|
||||||
|
const formatDate = (str) => new Date(str).toLocaleString()
|
||||||
|
|
||||||
|
const join = (actId) => {
|
||||||
|
ElMessage.success(`报名成功!活动ID:${actId}`)
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.activity-card {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
.title {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.meta {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #888;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin: 8px 0;
|
||||||
|
}
|
||||||
|
.desc {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #555;
|
||||||
|
margin: 10px 0;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
<template>
|
||||||
|
<el-carousel height="200px" :interval="4000" type="card">
|
||||||
|
<el-carousel-item v-for="club in clubs" :key="club.clubId">
|
||||||
|
<div class="club-card">
|
||||||
|
<img class="club-img" :src="club.logo || '/default-club.png'" />
|
||||||
|
<h3>{{ club.clubName }}</h3>
|
||||||
|
<p>{{ club.description }}</p>
|
||||||
|
</div>
|
||||||
|
</el-carousel-item>
|
||||||
|
</el-carousel>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref, onMounted } from 'vue'
|
||||||
|
// import { listTopClubs } from '@/api/club'
|
||||||
|
|
||||||
|
const clubs = ref([])
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
clubs.value = await listTopClubs()
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.club-card {
|
||||||
|
text-align: center;
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
.club-img {
|
||||||
|
width: 80px;
|
||||||
|
height: 80px;
|
||||||
|
border-radius: 50%;
|
||||||
|
object-fit: cover;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
h3 {
|
||||||
|
font-size: 16px;
|
||||||
|
margin: 5px 0;
|
||||||
|
}
|
||||||
|
p {
|
||||||
|
font-size: 13px;
|
||||||
|
color: #777;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,53 @@
|
||||||
|
<template>
|
||||||
|
<el-row :gutter="20">
|
||||||
|
<el-col v-for="item in newsList" :key="item.id" :span="8">
|
||||||
|
<el-card class="news-card" shadow="hover">
|
||||||
|
<h3 class="news-title">{{ item.title }}</h3>
|
||||||
|
<p class="news-desc">{{ item.summary }}</p>
|
||||||
|
<div class="news-footer">
|
||||||
|
<el-icon><Clock /></el-icon>
|
||||||
|
<span class="time">{{ formatTime(item.createTime) }}</span>
|
||||||
|
</div>
|
||||||
|
</el-card>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref, onMounted } from 'vue'
|
||||||
|
import { Clock } from '@element-plus/icons-vue'
|
||||||
|
// import { listLatestNews } from '@/api/news'
|
||||||
|
|
||||||
|
const newsList = ref([])
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
newsList.value = await listLatestNews()
|
||||||
|
})
|
||||||
|
|
||||||
|
const formatTime = (str) => new Date(str).toLocaleDateString()
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.news-card {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
.news-title {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 16px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
.news-desc {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
.news-footer {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
font-size: 12px;
|
||||||
|
color: #999;
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
.time {
|
||||||
|
margin-left: 4px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,118 @@
|
||||||
|
<template>
|
||||||
|
<el-container class="admin-layout">
|
||||||
|
<!-- 左侧菜单 -->
|
||||||
|
<el-aside width="220px" class="sidebar">
|
||||||
|
<div class="logo">社团后台管理</div>
|
||||||
|
<el-menu
|
||||||
|
router
|
||||||
|
class="el-menu-vertical-demo"
|
||||||
|
background-color="#304156"
|
||||||
|
text-color="#fff"
|
||||||
|
active-text-color="#409EFF"
|
||||||
|
:default-active="activePath"
|
||||||
|
>
|
||||||
|
<el-menu-item index="/admin/dashboard">
|
||||||
|
<el-icon><HomeFilled /></el-icon>
|
||||||
|
<span>首页</span>
|
||||||
|
</el-menu-item>
|
||||||
|
<el-menu-item index="/admin/activity">
|
||||||
|
<el-icon><List /></el-icon>
|
||||||
|
<span>活动管理</span>
|
||||||
|
</el-menu-item>
|
||||||
|
<el-menu-item index="/admin/club">
|
||||||
|
<el-icon><User /></el-icon>
|
||||||
|
<span>社团管理</span>
|
||||||
|
</el-menu-item>
|
||||||
|
<el-menu-item index="/admin/user">
|
||||||
|
<el-icon><Avatar /></el-icon>
|
||||||
|
<span>用户管理</span>
|
||||||
|
</el-menu-item>
|
||||||
|
<el-menu-item index="/admin/approval">
|
||||||
|
<el-icon><Check /></el-icon>
|
||||||
|
<span>审批中心</span>
|
||||||
|
</el-menu-item>
|
||||||
|
</el-menu>
|
||||||
|
</el-aside>
|
||||||
|
|
||||||
|
<!-- 右侧主内容 -->
|
||||||
|
<el-container>
|
||||||
|
<!-- 顶部导航栏 -->
|
||||||
|
<el-header class="top-header">
|
||||||
|
<div class="right">
|
||||||
|
<el-dropdown>
|
||||||
|
<span class="el-dropdown-link">
|
||||||
|
<el-avatar size="small" src="/avatar.png" />
|
||||||
|
<span class="username">管理员</span>
|
||||||
|
</span>
|
||||||
|
<template #dropdown>
|
||||||
|
<el-dropdown-menu>
|
||||||
|
<el-dropdown-item @click="goProfile">个人中心</el-dropdown-item>
|
||||||
|
<el-dropdown-item divided @click="logout">退出登录</el-dropdown-item>
|
||||||
|
</el-dropdown-menu>
|
||||||
|
</template>
|
||||||
|
</el-dropdown>
|
||||||
|
</div>
|
||||||
|
</el-header>
|
||||||
|
|
||||||
|
<!-- 内容展示区 -->
|
||||||
|
<el-main class="main-content">
|
||||||
|
<router-view />
|
||||||
|
</el-main>
|
||||||
|
</el-container>
|
||||||
|
</el-container>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { useRoute, useRouter } from 'vue-router'
|
||||||
|
import { HomeFilled, List, User, Avatar, Check } from '@element-plus/icons-vue'
|
||||||
|
import { ElMessage } from 'element-plus'
|
||||||
|
|
||||||
|
const router = useRouter()
|
||||||
|
const route = useRoute()
|
||||||
|
const activePath = route.path
|
||||||
|
|
||||||
|
const logout = () => {
|
||||||
|
localStorage.removeItem('token')
|
||||||
|
ElMessage.success('退出成功')
|
||||||
|
router.push('/login')
|
||||||
|
}
|
||||||
|
|
||||||
|
const goProfile = () => {
|
||||||
|
ElMessage.info('暂未开放个人中心')
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.admin-layout {
|
||||||
|
height: 100vh;
|
||||||
|
}
|
||||||
|
.logo {
|
||||||
|
height: 60px;
|
||||||
|
color: #fff;
|
||||||
|
text-align: center;
|
||||||
|
line-height: 60px;
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: bold;
|
||||||
|
background-color: #1f2d3d;
|
||||||
|
}
|
||||||
|
.sidebar {
|
||||||
|
background-color: #304156;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
.top-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
align-items: center;
|
||||||
|
background-color: #fff;
|
||||||
|
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
|
||||||
|
padding-right: 30px;
|
||||||
|
}
|
||||||
|
.username {
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
|
.main-content {
|
||||||
|
padding: 20px;
|
||||||
|
background-color: #f5f6fa;
|
||||||
|
min-height: calc(100vh - 60px);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,58 @@
|
||||||
|
<template>
|
||||||
|
<div class="layout">
|
||||||
|
<el-header class="layout-header">
|
||||||
|
<div class="logo">社团活动系统</div>
|
||||||
|
<el-menu mode="horizontal" router>
|
||||||
|
<el-menu-item index="/">首页</el-menu-item>
|
||||||
|
<el-menu-item index="/club">社团</el-menu-item>
|
||||||
|
<el-menu-item index="/activity">活动</el-menu-item>
|
||||||
|
<el-menu-item index="/notice">公告</el-menu-item>
|
||||||
|
</el-menu>
|
||||||
|
<div class="user-area">
|
||||||
|
<el-avatar size="small" src="/avatar.png" />
|
||||||
|
<span>欢迎你,张三</span>
|
||||||
|
</div>
|
||||||
|
</el-header>
|
||||||
|
|
||||||
|
<el-main class="layout-main">
|
||||||
|
<slot />
|
||||||
|
</el-main>
|
||||||
|
|
||||||
|
<el-footer class="layout-footer">
|
||||||
|
<div>© 山东建筑大学 - 校园社团活动系统</div>
|
||||||
|
</el-footer>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.layout-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
background-color: #409EFF;
|
||||||
|
color: #fff;
|
||||||
|
padding: 0 30px;
|
||||||
|
}
|
||||||
|
.logo {
|
||||||
|
font-size: 20px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.user-area {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
.layout-main {
|
||||||
|
padding: 40px;
|
||||||
|
background: #f8f9fa;
|
||||||
|
min-height: calc(100vh - 120px);
|
||||||
|
}
|
||||||
|
.layout-footer {
|
||||||
|
text-align: center;
|
||||||
|
padding: 20px;
|
||||||
|
color: #888;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -1,19 +1,52 @@
|
||||||
import { createRouter, createWebHistory } from 'vue-router'
|
import { createRouter, createWebHistory } from 'vue-router'
|
||||||
import Login from '@/views/login/index.vue'
|
import Login from '@/views/login/index.vue'
|
||||||
|
import UserHome from '@/views/student/home/index.vue'
|
||||||
|
import AdminLayout from '@/layout/AdminLayout.vue'
|
||||||
|
import AdminDashboard from '@/views/admin/dashboard.vue'
|
||||||
|
|
||||||
|
// 获取用户角色(从 token 中或 localStorage 中)
|
||||||
|
function getUserRole() {
|
||||||
|
// 示例:从 localStorage 模拟获取
|
||||||
|
const role = localStorage.getItem('userRole')
|
||||||
|
return role || ''
|
||||||
|
}
|
||||||
|
|
||||||
const routes = [
|
const routes = [
|
||||||
{
|
{
|
||||||
path: '/',
|
path: '/',
|
||||||
redirect: '/login' // 默认重定向到登录页
|
redirect: '/login'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/login',
|
path: '/login',
|
||||||
|
name: 'Login',
|
||||||
component: Login
|
component: Login
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// 学生端主页(角色为 PARTICIPANT)
|
||||||
{
|
{
|
||||||
path: '/user/home',
|
path: '/student/home',
|
||||||
component: () => import('@/views/home/UserHome.vue'),
|
name: 'UserHome',
|
||||||
|
component: UserHome,
|
||||||
meta: { roles: ['PARTICIPANT'] }
|
meta: { roles: ['PARTICIPANT'] }
|
||||||
|
},
|
||||||
|
|
||||||
|
// 管理端页面(角色为 COLLEGE_ADMIN / DEPARTMENT_ADMIN / CLUB_ADMIN)
|
||||||
|
{
|
||||||
|
path: '/admin',
|
||||||
|
component: AdminLayout,
|
||||||
|
meta: { roles: ['COLLEGE_ADMIN', 'DEPARTMENT_ADMIN', 'CLUB_ADMIN'] },
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: 'dashboard',
|
||||||
|
name: 'AdminDashboard',
|
||||||
|
component: AdminDashboard
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/403',
|
||||||
|
name: 'Forbidden',
|
||||||
|
component: () => import('@/views/error/403.vue')
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
@ -22,4 +55,37 @@ const router = createRouter({
|
||||||
routes
|
routes
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// 全局路由守卫:根据角色权限控制访问页面
|
||||||
|
router.beforeEach((to, from, next) => {
|
||||||
|
const token = localStorage.getItem('token')
|
||||||
|
const raw = localStorage.getItem('userRoles')
|
||||||
|
let roles = []
|
||||||
|
try {
|
||||||
|
roles = JSON.parse(raw) || []
|
||||||
|
} catch {
|
||||||
|
roles = []
|
||||||
|
}
|
||||||
|
|
||||||
|
if (to.path === '/login') return next()
|
||||||
|
|
||||||
|
if (!token) return next('/login')
|
||||||
|
|
||||||
|
// 权限校验失败时避免无限重定向
|
||||||
|
if (to.meta.roles && !roles.some(r => to.meta.roles.includes(r))) {
|
||||||
|
if (roles.includes('PARTICIPANT') && to.path !== '/student/home') {
|
||||||
|
return next('/student/home')
|
||||||
|
} else if (
|
||||||
|
roles.some(r => ['COLLEGE_ADMIN', 'DEPARTMENT_ADMIN', 'CLUB_ADMIN'].includes(r)) &&
|
||||||
|
to.path !== '/admin/dashboard'
|
||||||
|
) {
|
||||||
|
return next('/admin/dashboard')
|
||||||
|
} else {
|
||||||
|
return next('/403')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
next()
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
export default router
|
export default router
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,147 @@
|
||||||
|
<template>
|
||||||
|
<admin-layout>
|
||||||
|
<div class="dashboard">
|
||||||
|
<h2 class="welcome-text">你好,管理员!欢迎使用社团管理系统</h2>
|
||||||
|
|
||||||
|
<!-- 顶部数据卡片 -->
|
||||||
|
<el-row :gutter="20" class="stat-boxes">
|
||||||
|
<el-col :span="6" v-for="stat in stats" :key="stat.label">
|
||||||
|
<el-card>
|
||||||
|
<div class="stat-card">
|
||||||
|
<el-icon :size="28">{{ stat.icon }}</el-icon>
|
||||||
|
<div class="stat-info">
|
||||||
|
<div class="stat-label">{{ stat.label }}</div>
|
||||||
|
<div class="stat-value">{{ stat.value }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-card>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
<!-- 活动列表 -->
|
||||||
|
<section class="section">
|
||||||
|
<div class="section-header">
|
||||||
|
<h3>活动列表</h3>
|
||||||
|
<el-input v-model="activitySearch" placeholder="搜索活动名称" size="small" class="search-box" />
|
||||||
|
<el-button type="primary" size="small">➕ 新建活动</el-button>
|
||||||
|
</div>
|
||||||
|
<el-table :data="filteredActivities" border>
|
||||||
|
<el-table-column prop="title" label="活动名称" />
|
||||||
|
<el-table-column prop="club" label="申请社团" />
|
||||||
|
<el-table-column prop="time" label="活动时间" />
|
||||||
|
<el-table-column prop="place" label="活动地点" />
|
||||||
|
<el-table-column prop="status" label="状态" />
|
||||||
|
<el-table-column label="操作">
|
||||||
|
<template #default>
|
||||||
|
<el-button size="small" type="primary" link>查看</el-button>
|
||||||
|
<el-button size="small" type="success" link>审批</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
<el-pagination layout="prev, pager, next" :total="24" background class="mt-4" />
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- 社团列表 -->
|
||||||
|
<section class="section">
|
||||||
|
<div class="section-header">
|
||||||
|
<h3>社团列表</h3>
|
||||||
|
<el-input v-model="clubSearch" placeholder="搜索社团名称" size="small" class="search-box" />
|
||||||
|
<el-button type="primary" size="small">➕ 新建社团</el-button>
|
||||||
|
</div>
|
||||||
|
<el-table :data="filteredClubs" border>
|
||||||
|
<el-table-column prop="name" label="社团名称" />
|
||||||
|
<el-table-column prop="type" label="社团类型" />
|
||||||
|
<el-table-column prop="createTime" label="成立时间" />
|
||||||
|
<el-table-column prop="leader" label="指导老师" />
|
||||||
|
<el-table-column prop="members" label="成员数量" />
|
||||||
|
<el-table-column prop="status" label="状态" />
|
||||||
|
<el-table-column label="操作">
|
||||||
|
<template #default>
|
||||||
|
<el-button size="small" type="primary" link>查看</el-button>
|
||||||
|
<el-button size="small" type="warning" link>编辑</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
<el-pagination layout="prev, pager, next" :total="56" background class="mt-4" />
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
</admin-layout>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { Document, User, Check, Avatar } from '@element-plus/icons-vue'
|
||||||
|
import { ref, reactive, computed, onMounted } from 'vue'
|
||||||
|
|
||||||
|
|
||||||
|
const activitySearch = ref('')
|
||||||
|
const clubSearch = ref('')
|
||||||
|
|
||||||
|
const stats = [
|
||||||
|
{ label: '待审批活动', value: 12, icon: Document },
|
||||||
|
{ label: '进行中活动', value: 8, icon: Check },
|
||||||
|
{ label: '待审核入团', value: 25, icon: User },
|
||||||
|
{ label: '社团总数', value: 56, icon: Avatar }
|
||||||
|
]
|
||||||
|
|
||||||
|
const activities = [
|
||||||
|
{ title: '2023年秋新生欢迎会', club: '学生会', time: '2023-11-20 14:00', place: '大学生活动中心', status: '待审批' },
|
||||||
|
{ title: '摄影社作品展', club: '摄影社', time: '2023-11-25 09:00', place: '图书馆展厅', status: '进行中' },
|
||||||
|
{ title: '街舞社年度汇演', club: '街舞社', time: '2023-12-01 19:00', place: '大礼堂', status: '已结束' }
|
||||||
|
]
|
||||||
|
|
||||||
|
const filteredActivities = computed(() => {
|
||||||
|
return activities.filter(act => act.title.includes(activitySearch.value))
|
||||||
|
})
|
||||||
|
|
||||||
|
const clubs = [
|
||||||
|
{ name: '学生会', type: '学生组织', createTime: '2010-09-01', leader: '王教武', members: 126, status: '正常' },
|
||||||
|
{ name: '摄影社', type: '艺术类', createTime: '2015-03-15', leader: '李明远', members: 45, status: '正常' },
|
||||||
|
{ name: '街舞社', type: '体育类', createTime: '2018-09-10', leader: '张建国', members: 38, status: '正常' }
|
||||||
|
]
|
||||||
|
|
||||||
|
const filteredClubs = computed(() => {
|
||||||
|
return clubs.filter(c => c.name.includes(clubSearch.value))
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.dashboard {
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
.welcome-text {
|
||||||
|
font-size: 20px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
.stat-boxes {
|
||||||
|
margin-bottom: 30px;
|
||||||
|
}
|
||||||
|
.stat-card {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 16px;
|
||||||
|
}
|
||||||
|
.stat-info {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
.stat-label {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
.stat-value {
|
||||||
|
font-size: 22px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.section {
|
||||||
|
margin-top: 40px;
|
||||||
|
}
|
||||||
|
.section-header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
.search-box {
|
||||||
|
width: 200px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
<template>
|
||||||
|
<div class="error-page">
|
||||||
|
<h1>403</h1>
|
||||||
|
<p>抱歉,您没有权限访问此页面。</p>
|
||||||
|
<el-button type="primary" @click="$router.push('/')">返回首页</el-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup></script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.error-page {
|
||||||
|
text-align: center;
|
||||||
|
padding: 100px 20px;
|
||||||
|
}
|
||||||
|
.error-page h1 {
|
||||||
|
font-size: 72px;
|
||||||
|
color: #f56c6c;
|
||||||
|
}
|
||||||
|
.error-page p {
|
||||||
|
font-size: 20px;
|
||||||
|
margin: 20px 0;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -1,177 +0,0 @@
|
||||||
<template>
|
|
||||||
<div class="user-home">
|
|
||||||
<!-- 顶部导航 -->
|
|
||||||
<el-menu mode="horizontal" class="top-nav" background-color="#2c3e50" text-color="#fff" active-text-color="#ffd04b">
|
|
||||||
<div class="nav-left">🏠 社团活动管理系统</div>
|
|
||||||
<el-menu-item index="1">首页</el-menu-item>
|
|
||||||
<el-menu-item index="2">社团中心</el-menu-item>
|
|
||||||
<el-menu-item index="3">活动</el-menu-item>
|
|
||||||
<el-menu-item index="4">公告</el-menu-item>
|
|
||||||
<el-menu-item index="5">个人中心</el-menu-item>
|
|
||||||
<div class="nav-right">欢迎你,{{ nickname }}</div>
|
|
||||||
</el-menu>
|
|
||||||
|
|
||||||
<!-- 轮播图 -->
|
|
||||||
<el-carousel height="360px">
|
|
||||||
<el-carousel-item v-for="item in banners" :key="item">
|
|
||||||
<img :src="item" class="banner-img" />
|
|
||||||
</el-carousel-item>
|
|
||||||
</el-carousel>
|
|
||||||
|
|
||||||
<!-- 社团资讯和活动 -->
|
|
||||||
<div class="info-section">
|
|
||||||
<el-card class="info-box">
|
|
||||||
<div class="section-header">
|
|
||||||
<h3>社团资讯</h3>
|
|
||||||
<el-link>更多</el-link>
|
|
||||||
</div>
|
|
||||||
<el-timeline>
|
|
||||||
<el-timeline-item v-for="news in newsList" :key="news.id" :timestamp="news.date">
|
|
||||||
{{ news.title }}
|
|
||||||
</el-timeline-item>
|
|
||||||
</el-timeline>
|
|
||||||
</el-card>
|
|
||||||
|
|
||||||
<el-card class="info-box">
|
|
||||||
<div class="section-header">
|
|
||||||
<h3>社团活动</h3>
|
|
||||||
<el-link>更多</el-link>
|
|
||||||
</div>
|
|
||||||
<el-timeline>
|
|
||||||
<el-timeline-item v-for="act in activityList" :key="act.id" :timestamp="act.date">
|
|
||||||
{{ act.title }}
|
|
||||||
</el-timeline-item>
|
|
||||||
</el-timeline>
|
|
||||||
</el-card>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 优秀社团 -->
|
|
||||||
<el-card class="club-section">
|
|
||||||
<h3>优秀社团</h3>
|
|
||||||
<div class="club-list">
|
|
||||||
<div class="club-item" v-for="club in clubs" :key="club.id">
|
|
||||||
<img :src="club.logo" />
|
|
||||||
<p>{{ club.name }}</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</el-card>
|
|
||||||
|
|
||||||
<!-- 页脚 -->
|
|
||||||
<el-footer class="footer">
|
|
||||||
<div class="footer-cols">
|
|
||||||
<div>
|
|
||||||
<h4>关于我们</h4>
|
|
||||||
<p>致力于为用户提供优质的社团活动管理服务</p>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<h4>快速链接</h4>
|
|
||||||
<p>社团中心<br />公告</p>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<h4>联系方式</h4>
|
|
||||||
<p>电话: 400-123-4567<br />邮箱: contact@example.com</p>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<h4>关注我们</h4>
|
|
||||||
<p>🌐 📱 🧧</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<p class="footer-note">© 2024 社团活动管理系统. 保留所有权利.</p>
|
|
||||||
</el-footer>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import { ref } from 'vue'
|
|
||||||
|
|
||||||
const nickname = localStorage.getItem('nickname') || '学生'
|
|
||||||
|
|
||||||
const banners = ['/login-bg.jpg', '/login-bg.jpg'] // 用自己的图片
|
|
||||||
const newsList = [
|
|
||||||
{ id: 1, title: '乒乓社招新啦!', date: '2023-11-14' },
|
|
||||||
{ id: 2, title: '街舞社重磅来袭!', date: '2023-11-14' },
|
|
||||||
]
|
|
||||||
|
|
||||||
const activityList = [
|
|
||||||
{ id: 1, title: '小小球员,等你来战!', date: '2023-11-14' },
|
|
||||||
{ id: 2, title: '舞蹈嗨翻,敬“梦”想!', date: '2023-11-14' },
|
|
||||||
]
|
|
||||||
|
|
||||||
const clubs = [
|
|
||||||
{ id: 1, name: '乒乓社', logo: '/pingpong.png' },
|
|
||||||
{ id: 2, name: '街舞社', logo: '/street.png' },
|
|
||||||
{ id: 3, name: '书法社', logo: '/calligraphy.png' },
|
|
||||||
{ id: 4, name: '英语社', logo: '/english.png' },
|
|
||||||
{ id: 5, name: '足球社', logo: '/soccer.png' },
|
|
||||||
]
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.user-home {
|
|
||||||
font-family: "Microsoft YaHei", sans-serif;
|
|
||||||
}
|
|
||||||
.top-nav {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: space-between;
|
|
||||||
}
|
|
||||||
.nav-left {
|
|
||||||
color: #fff;
|
|
||||||
font-size: 18px;
|
|
||||||
padding: 0 20px;
|
|
||||||
}
|
|
||||||
.nav-right {
|
|
||||||
padding: 0 20px;
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
.banner-img {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
object-fit: cover;
|
|
||||||
}
|
|
||||||
.info-section {
|
|
||||||
display: flex;
|
|
||||||
gap: 20px;
|
|
||||||
padding: 20px;
|
|
||||||
}
|
|
||||||
.info-box {
|
|
||||||
flex: 1;
|
|
||||||
}
|
|
||||||
.section-header {
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
.club-section {
|
|
||||||
margin: 20px;
|
|
||||||
}
|
|
||||||
.club-list {
|
|
||||||
display: flex;
|
|
||||||
gap: 30px;
|
|
||||||
margin-top: 20px;
|
|
||||||
justify-content: start;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
}
|
|
||||||
.club-item {
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
.club-item img {
|
|
||||||
width: 70px;
|
|
||||||
height: 70px;
|
|
||||||
border-radius: 50%;
|
|
||||||
}
|
|
||||||
.footer {
|
|
||||||
background: #2c3e50;
|
|
||||||
color: #fff;
|
|
||||||
padding: 30px;
|
|
||||||
margin-top: 50px;
|
|
||||||
}
|
|
||||||
.footer-cols {
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
}
|
|
||||||
.footer-note {
|
|
||||||
text-align: center;
|
|
||||||
margin-top: 20px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
@ -33,6 +33,8 @@ 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/auth'
|
||||||
|
import { jwtDecode } from 'jwt-decode'
|
||||||
|
import { nextTick } from 'vue'
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const loginRef = ref(null)
|
const loginRef = ref(null)
|
||||||
|
|
@ -56,17 +58,28 @@ const submitLogin = () => {
|
||||||
try {
|
try {
|
||||||
const token = await login(loginForm.value)
|
const token = await login(loginForm.value)
|
||||||
localStorage.setItem('token', token)
|
localStorage.setItem('token', token)
|
||||||
ElMessage.success('登录成功')
|
|
||||||
// 登录成功后
|
|
||||||
const payload = jwtDecode(token)
|
const payload = jwtDecode(token)
|
||||||
const roles = Array.isArray(payload.role) ? payload.role : [payload.role]
|
const roles = Array.isArray(payload.role) ? payload.role : [payload.role]
|
||||||
|
localStorage.setItem('userRoles', JSON.stringify(roles))
|
||||||
|
|
||||||
if (roles.includes('PARTICIPANT')) {
|
ElMessage.success('登录成功')
|
||||||
router.push('/user/home')
|
|
||||||
} else if (roles.includes('COLLEGE_ADMIN') ||roles.includes('DEPARTMENT_ADMIN') ||roles.includes('CLUB_ADMIN') ) {
|
|
||||||
router.push('/admin/home')
|
await nextTick()
|
||||||
} else {
|
|
||||||
router.push('/403') // 无匹配权限
|
|
||||||
|
const currentPath = router.currentRoute.value.path
|
||||||
|
|
||||||
|
if (roles.includes('PARTICIPANT') && currentPath !== '/student/home') {
|
||||||
|
router.push('/student/home')
|
||||||
|
} else if (
|
||||||
|
roles.some(r => ['COLLEGE_ADMIN', 'DEPARTMENT_ADMIN', 'CLUB_ADMIN'].includes(r)) &&
|
||||||
|
currentPath !== '/admin/dashboard'
|
||||||
|
) {
|
||||||
|
router.push('/admin/dashboard')
|
||||||
|
} else if (currentPath !== '/403') {
|
||||||
|
router.push('/403')
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
ElMessage.error(e.message || '登录失败')
|
ElMessage.error(e.message || '登录失败')
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,52 @@
|
||||||
|
<template>
|
||||||
|
<student-layout>
|
||||||
|
<!-- 首页 Banner -->
|
||||||
|
<el-carousel height="400px" class="home-banner">
|
||||||
|
<el-carousel-item v-for="i in 2" :key="i">
|
||||||
|
<img :src="`/banner${i}.jpg`" class="banner-img" />
|
||||||
|
</el-carousel-item>
|
||||||
|
</el-carousel>
|
||||||
|
|
||||||
|
<!-- 社团资讯 -->
|
||||||
|
<section class="section">
|
||||||
|
<h2 class="section-title">📢 最新社团资讯</h2>
|
||||||
|
<NewsList />
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- 活动推荐 -->
|
||||||
|
<section class="section">
|
||||||
|
<h2 class="section-title">🔥 活动推荐</h2>
|
||||||
|
<ActivityList />
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- 优秀社团 -->
|
||||||
|
<section class="section">
|
||||||
|
<h2 class="section-title">🏅 优秀社团</h2>
|
||||||
|
<ClubCarousel />
|
||||||
|
</section>
|
||||||
|
</student-layout>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import NewsList from '@/components/student/NewsList.vue'
|
||||||
|
import ActivityList from '@/components/student/ActivityList.vue'
|
||||||
|
import ClubCarousel from '@/components/student/ClubCarousel.vue'
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.section {
|
||||||
|
margin: 40px auto;
|
||||||
|
max-width: 1200px;
|
||||||
|
}
|
||||||
|
.section-title {
|
||||||
|
font-size: 20px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
.banner-img {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
object-fit: cover;
|
||||||
|
border-radius: 12px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
package com.bruce.sams.service.impl;
|
package com.bruce.sams.service.impl;
|
||||||
|
|
||||||
import com.bruce.sams.common.utils.PasswordUtil;
|
|
||||||
import com.bruce.sams.domain.entity.LoginRequest;
|
import com.bruce.sams.domain.entity.LoginRequest;
|
||||||
import com.bruce.sams.service.AuthService;
|
import com.bruce.sams.service.AuthService;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
@ -8,7 +7,6 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.boot.test.context.SpringBootTest;
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
|
||||||
|
|
||||||
@SpringBootTest
|
@SpringBootTest
|
||||||
class AuthServiceImplTest {
|
class AuthServiceImplTest {
|
||||||
|
|
@ -30,4 +28,4 @@ class AuthServiceImplTest {
|
||||||
|
|
||||||
// authService.authenticate(loginRequest);
|
// authService.authenticate(loginRequest);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
package com.bruce.sams.service.impl;
|
||||||
|
|
||||||
|
import com.bruce.sams.common.utils.TokenUtil;
|
||||||
|
import com.bruce.sams.domain.sys.User;
|
||||||
|
import com.bruce.sams.service.UserService;
|
||||||
|
import io.jsonwebtoken.Claims;
|
||||||
|
import org.junit.jupiter.api.Assertions;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TokenUtil 工具类单元测试
|
||||||
|
*/
|
||||||
|
public class TokenUtilTest {
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetRoleFromToken() {
|
||||||
|
|
||||||
|
|
||||||
|
String token = "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiI2Iiwicm9sZSI6WyJQQVJUSUNJUEFOVCJdLCJpYXQiOjE3NDI5MTg2MzAsImV4cCI6MTc0MjkyMjIzMH0.si-0JKvdzxxXHWPFRozc0EOSa6Vp5lF4pE1KWKD2fRY";
|
||||||
|
|
||||||
|
String roleStr = TokenUtil.getRoleFromToken(token);
|
||||||
|
System.out.println(roleStr);
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue