updates
This commit is contained in:
parent
1b7baf85df
commit
d5cffd2a76
|
|
@ -0,0 +1,515 @@
|
||||||
|
# 用户志愿控制器 API 接口文档
|
||||||
|
|
||||||
|
## 概述
|
||||||
|
|
||||||
|
用户志愿控制器 (UserVolunteerController) 提供了志愿管理的相关接口,包括志愿保存、详情查询、名称修改、列表查询、删除和切换功能。
|
||||||
|
|
||||||
|
**基础路径**: `/api/user/volunteer`
|
||||||
|
|
||||||
|
**认证方式**: 需要登录认证,通过 JWT Token 进行身份验证
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. 保存志愿明细
|
||||||
|
|
||||||
|
保存用户选择的志愿专业列表到当前激活的志愿表中。
|
||||||
|
|
||||||
|
**请求**
|
||||||
|
|
||||||
|
- **方法**: `POST`
|
||||||
|
- **路径**: `/api/user/volunteer/save`
|
||||||
|
- **Content-Type**: `application/json`
|
||||||
|
|
||||||
|
**请求参数**
|
||||||
|
|
||||||
|
| 参数名 | 类型 | 必填 | 说明 |
|
||||||
|
|--------|--------|------|----------------------------------------|
|
||||||
|
| keys | string[] | 是 | 志愿专业Key列表,格式:`学校代码_专业代码_招生代码` |
|
||||||
|
|
||||||
|
**请求示例**
|
||||||
|
|
||||||
|
```json
|
||||||
|
[
|
||||||
|
"10001_1001_001",
|
||||||
|
"10002_2001_002",
|
||||||
|
"10003_3001_003"
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
**响应**
|
||||||
|
|
||||||
|
| 字段名 | 类型 | 说明 |
|
||||||
|
|----------|--------|----------|
|
||||||
|
| code | int | 状态码 |
|
||||||
|
| message | string | 响应消息 |
|
||||||
|
| data | string | 响应数据 |
|
||||||
|
|
||||||
|
**成功响应示例**
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"message": "success",
|
||||||
|
"data": "保存成功"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**错误响应示例**
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 500,
|
||||||
|
"message": "未找到计算表名",
|
||||||
|
"data": null
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**错误码说明**
|
||||||
|
|
||||||
|
| 错误码 | 说明 |
|
||||||
|
|--------|----------------------------|
|
||||||
|
| 500 | 获取用户成绩信息失败 |
|
||||||
|
| 500 | 未找到计算表名 |
|
||||||
|
| 500 | 查找志愿表失败 |
|
||||||
|
| 500 | 请先创建志愿表 |
|
||||||
|
| 500 | 查找专业信息失败 |
|
||||||
|
| 500 | 删除旧数据失败 |
|
||||||
|
| 500 | 保存失败 |
|
||||||
|
|
||||||
|
**业务逻辑**
|
||||||
|
|
||||||
|
1. 对传入的keys进行去重处理
|
||||||
|
2. 获取当前登录用户的激活成绩信息
|
||||||
|
3. 查找当前激活的志愿表
|
||||||
|
4. 根据keys查找对应的专业信息
|
||||||
|
5. 构建志愿记录列表,保持提交顺序
|
||||||
|
6. 先删除旧的志愿记录,再批量插入新记录
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. 获取当前志愿单详情
|
||||||
|
|
||||||
|
获取当前激活志愿单的详细信息,包括志愿记录按批次分组展示。
|
||||||
|
|
||||||
|
**请求**
|
||||||
|
|
||||||
|
- **方法**: `GET`
|
||||||
|
- **路径**: `/api/user/volunteer/detail`
|
||||||
|
|
||||||
|
**请求参数**
|
||||||
|
|
||||||
|
无
|
||||||
|
|
||||||
|
**响应**
|
||||||
|
|
||||||
|
| 字段名 | 类型 | 说明 |
|
||||||
|
|----------|--------|--------------------|
|
||||||
|
| code | int | 状态码 |
|
||||||
|
| message | string | 响应消息 |
|
||||||
|
| data | object | 志愿详情数据 |
|
||||||
|
|
||||||
|
**data 数据结构**
|
||||||
|
|
||||||
|
| 字段名 | 类型 | 说明 |
|
||||||
|
|------------|--------|--------------------------|
|
||||||
|
| volunteer | object | 志愿单基本信息 |
|
||||||
|
| items | object | 按批次分组的志愿明细 |
|
||||||
|
|
||||||
|
**items 数据结构**
|
||||||
|
|
||||||
|
| 批次 | 类型 | 说明 |
|
||||||
|
|--------|------|------|
|
||||||
|
| 提前批 | array | 提前批志愿记录列表 |
|
||||||
|
| 本科批 | array | 本科批志愿记录列表 |
|
||||||
|
| 专科批 | array | 专科批志愿记录列表 |
|
||||||
|
|
||||||
|
**志愿记录项数据结构**
|
||||||
|
|
||||||
|
| 字段名 | 类型 | 说明 |
|
||||||
|
|------------------------|---------|--------------------------------|
|
||||||
|
| volunteerID | string | 志愿单ID |
|
||||||
|
| schoolCode | string | 学校代码 |
|
||||||
|
| majorCode | string | 专业代码 |
|
||||||
|
| enrollmentCode | string | 招生代码 |
|
||||||
|
| indexs | int | 志愿序号 |
|
||||||
|
| batch | string | 批次 |
|
||||||
|
| enrollProbability | float64 | 录取概率 |
|
||||||
|
| studentConvertedScore | float64 | 学生折合分 |
|
||||||
|
| calculationMajorID | string | 计算专业ID |
|
||||||
|
| schoolName | string | 学校名称 |
|
||||||
|
| majorName | string | 专业名称 |
|
||||||
|
| planNum | int | 计划人数 |
|
||||||
|
| tuition | string | 学费 |
|
||||||
|
| province | string | 省份 |
|
||||||
|
| schoolNature | string | 院校性质 |
|
||||||
|
| institutionType | string | 院校类型 |
|
||||||
|
| majorDetail | string | 专业详情 |
|
||||||
|
|
||||||
|
**成功响应示例**
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"message": "success",
|
||||||
|
"data": {
|
||||||
|
"volunteer": {
|
||||||
|
"id": "123456789",
|
||||||
|
"volunteerName": "我的志愿表",
|
||||||
|
"scoreId": "987654321",
|
||||||
|
"createType": 1,
|
||||||
|
"state": 1
|
||||||
|
},
|
||||||
|
"items": {
|
||||||
|
"提前批": [
|
||||||
|
{
|
||||||
|
"volunteerID": "123456789",
|
||||||
|
"schoolCode": "10001",
|
||||||
|
"majorCode": "1001",
|
||||||
|
"enrollmentCode": "001",
|
||||||
|
"indexs": 1,
|
||||||
|
"batch": "本科提前批",
|
||||||
|
"schoolName": "某某大学",
|
||||||
|
"majorName": "美术学",
|
||||||
|
"planNum": 30,
|
||||||
|
"tuition": "8000元/年",
|
||||||
|
"enrollProbability": 85.5
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"本科批": [],
|
||||||
|
"专科批": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**错误码说明**
|
||||||
|
|
||||||
|
| 错误码 | 说明 |
|
||||||
|
|--------|------------------------|
|
||||||
|
| 500 | 获取用户成绩信息失败 |
|
||||||
|
| 500 | 查找志愿表失败 |
|
||||||
|
| 500 | 查找志愿明细失败 |
|
||||||
|
|
||||||
|
**批次分类规则**
|
||||||
|
|
||||||
|
- **提前批**: `提前批`、`本科提前批`
|
||||||
|
- **专科批**: `高职高专`、`专科批`
|
||||||
|
- **本科批**: 其他所有批次
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. 编辑志愿单名称
|
||||||
|
|
||||||
|
修改志愿单的名称。
|
||||||
|
|
||||||
|
**请求**
|
||||||
|
|
||||||
|
- **方法**: `PUT`
|
||||||
|
- **路径**: `/api/user/volunteer/updateName`
|
||||||
|
|
||||||
|
**请求参数**
|
||||||
|
|
||||||
|
| 参数名 | 类型 | 必填 | 位置 | 说明 |
|
||||||
|
|--------|--------|------|--------|------------|
|
||||||
|
| id | string | 是 | query | 志愿单ID |
|
||||||
|
| name | string | 是 | query | 志愿单名称 |
|
||||||
|
|
||||||
|
**请求示例**
|
||||||
|
|
||||||
|
```
|
||||||
|
PUT /api/user/volunteer/updateName?id=123456789&name=我的新志愿表
|
||||||
|
```
|
||||||
|
|
||||||
|
**响应**
|
||||||
|
|
||||||
|
| 字段名 | 类型 | 说明 |
|
||||||
|
|----------|--------|----------|
|
||||||
|
| code | int | 状态码 |
|
||||||
|
| message | string | 响应消息 |
|
||||||
|
| data | string | 响应数据 |
|
||||||
|
|
||||||
|
**成功响应示例**
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"message": "success",
|
||||||
|
"data": "更新成功"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**错误响应示例**
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 400,
|
||||||
|
"message": "参数错误",
|
||||||
|
"data": null
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**错误码说明**
|
||||||
|
|
||||||
|
| 错误码 | 说明 |
|
||||||
|
|--------|----------------|
|
||||||
|
| 400 | 参数错误 |
|
||||||
|
| 500 | 更新失败 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. 获取当前用户志愿单列表
|
||||||
|
|
||||||
|
分页查询当前用户的志愿单列表。
|
||||||
|
|
||||||
|
**请求**
|
||||||
|
|
||||||
|
- **方法**: `GET`
|
||||||
|
- **路径**: `/api/user/volunteer/list`
|
||||||
|
|
||||||
|
**请求参数**
|
||||||
|
|
||||||
|
| 参数名 | 类型 | 必填 | 位置 | 默认值 | 说明 |
|
||||||
|
|--------|------|------|-------|--------|--------|
|
||||||
|
| page | int | 否 | query | 1 | 页码 |
|
||||||
|
| size | int | 否 | query | 10 | 每页数量 |
|
||||||
|
|
||||||
|
**请求示例**
|
||||||
|
|
||||||
|
```
|
||||||
|
GET /api/user/volunteer/list?page=1&size=10
|
||||||
|
```
|
||||||
|
|
||||||
|
**响应**
|
||||||
|
|
||||||
|
| 字段名 | 类型 | 说明 |
|
||||||
|
|----------|--------|----------|
|
||||||
|
| code | int | 状态码 |
|
||||||
|
| message | string | 响应消息 |
|
||||||
|
| data | object | 响应数据 |
|
||||||
|
|
||||||
|
**data 数据结构**
|
||||||
|
|
||||||
|
| 字段名 | 类型 | 说明 |
|
||||||
|
|--------|--------|--------------|
|
||||||
|
| items | array | 志愿单列表 |
|
||||||
|
| total | int64 | 总数量 |
|
||||||
|
|
||||||
|
**志愿单数据结构**
|
||||||
|
|
||||||
|
| 字段名 | 类型 | 说明 |
|
||||||
|
|----------------|---------|------------------------------|
|
||||||
|
| id | string | 志愿单ID |
|
||||||
|
| volunteerName | string | 志愿单名称 |
|
||||||
|
| scoreId | string | 关联成绩ID |
|
||||||
|
| createType | int | 生成类型 (1.手动, 2.智能) |
|
||||||
|
| state | string | 状态 (0.未使用, 1.使用中, 2.历史) |
|
||||||
|
| createBy | string | 创建人 |
|
||||||
|
| createTime | string | 创建时间 |
|
||||||
|
| updateBy | string | 更新人 |
|
||||||
|
| updateTime | string | 更新时间 |
|
||||||
|
|
||||||
|
**成功响应示例**
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"message": "success",
|
||||||
|
"data": {
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"id": "123456789",
|
||||||
|
"volunteerName": "我的志愿表",
|
||||||
|
"scoreId": "987654321",
|
||||||
|
"createType": 1,
|
||||||
|
"state": "1",
|
||||||
|
"createBy": "user001",
|
||||||
|
"createTime": "2026-01-31T10:00:00Z"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"total": 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**错误码说明**
|
||||||
|
|
||||||
|
| 错误码 | 说明 |
|
||||||
|
|--------|----------------|
|
||||||
|
| 500 | 查询失败 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. 删除志愿单
|
||||||
|
|
||||||
|
删除指定的志愿单。
|
||||||
|
|
||||||
|
**请求**
|
||||||
|
|
||||||
|
- **方法**: `DELETE`
|
||||||
|
- **路径**: `/api/user/volunteer/delete`
|
||||||
|
|
||||||
|
**请求参数**
|
||||||
|
|
||||||
|
| 参数名 | 类型 | 必填 | 位置 | 说明 |
|
||||||
|
|--------|--------|------|-------|----------|
|
||||||
|
| id | string | 是 | query | 志愿单ID |
|
||||||
|
|
||||||
|
**请求示例**
|
||||||
|
|
||||||
|
```
|
||||||
|
DELETE /api/user/volunteer/delete?id=123456789
|
||||||
|
```
|
||||||
|
|
||||||
|
**响应**
|
||||||
|
|
||||||
|
| 字段名 | 类型 | 说明 |
|
||||||
|
|----------|--------|----------|
|
||||||
|
| code | int | 状态码 |
|
||||||
|
| message | string | 响应消息 |
|
||||||
|
| data | string | 响应数据 |
|
||||||
|
|
||||||
|
**成功响应示例**
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"message": "success",
|
||||||
|
"data": "删除成功"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**错误响应示例**
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 400,
|
||||||
|
"message": "参数错误",
|
||||||
|
"data": null
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**错误码说明**
|
||||||
|
|
||||||
|
| 错误码 | 说明 |
|
||||||
|
|--------|----------------|
|
||||||
|
| 400 | 参数错误 |
|
||||||
|
| 500 | 删除失败 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. 切换当前志愿单
|
||||||
|
|
||||||
|
切换当前激活的志愿单。
|
||||||
|
|
||||||
|
**请求**
|
||||||
|
|
||||||
|
- **方法**: `POST`
|
||||||
|
- **路径**: `/api/user/volunteer/switch`
|
||||||
|
|
||||||
|
**请求参数**
|
||||||
|
|
||||||
|
| 参数名 | 类型 | 必填 | 位置 | 说明 |
|
||||||
|
|--------|--------|------|-------|----------|
|
||||||
|
| id | string | 是 | query | 志愿单ID |
|
||||||
|
|
||||||
|
**请求示例**
|
||||||
|
|
||||||
|
```
|
||||||
|
POST /api/user/volunteer/switch?id=123456789
|
||||||
|
```
|
||||||
|
|
||||||
|
**响应**
|
||||||
|
|
||||||
|
| 字段名 | 类型 | 说明 |
|
||||||
|
|----------|--------|----------|
|
||||||
|
| code | int | 状态码 |
|
||||||
|
| message | string | 响应消息 |
|
||||||
|
| data | string | 响应数据 |
|
||||||
|
|
||||||
|
**成功响应示例**
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"message": "success",
|
||||||
|
"data": "切换成功"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**特殊响应示例(已是当前志愿单)**
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"message": "success",
|
||||||
|
"data": "已是当前志愿单,忽略切换"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**错误码说明**
|
||||||
|
|
||||||
|
| 错误码 | 说明 |
|
||||||
|
|--------|----------------------------|
|
||||||
|
| 400 | 参数错误 |
|
||||||
|
| 500 | 获取用户成绩信息失败 |
|
||||||
|
| 500 | 切换失败 |
|
||||||
|
|
||||||
|
**业务逻辑**
|
||||||
|
|
||||||
|
1. 检查当前是否已是该志愿单,如果是则忽略切换
|
||||||
|
2. 执行志愿单切换操作
|
||||||
|
3. Redis 缓存同步(由 Service 层处理)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 通用响应格式说明
|
||||||
|
|
||||||
|
### 成功响应
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"message": "success",
|
||||||
|
"data": {}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 错误响应
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 错误码,
|
||||||
|
"message": "错误信息",
|
||||||
|
"data": null
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 常见错误码
|
||||||
|
|
||||||
|
| 错误码 | 说明 |
|
||||||
|
|--------|--------------------|
|
||||||
|
| 200 | 成功 |
|
||||||
|
| 400 | 请求参数错误 |
|
||||||
|
| 500 | 服务器内部错误 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 认证说明
|
||||||
|
|
||||||
|
所有接口都需要在请求头中携带 JWT Token:
|
||||||
|
|
||||||
|
```
|
||||||
|
Authorization: Bearer {token}
|
||||||
|
```
|
||||||
|
|
||||||
|
Token 从登录接口获取,有效期24小时。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 注意事项
|
||||||
|
|
||||||
|
1. **保存志愿明细**: 每次保存会先删除当前志愿表中的所有记录,再插入新记录
|
||||||
|
2. **批次分类**: 志愿详情按 提前批、本科批、专科批 三大类分组展示
|
||||||
|
3. **数据去重**: 保存志愿时会自动去重,避免重复添加相同专业
|
||||||
|
4. **顺序保持**: 志愿序号按照提交的 keys 顺序依次递增
|
||||||
|
5. **权限控制**: 所有操作都基于当前登录用户的身份,只能操作自己的志愿数据
|
||||||
|
|
@ -3,7 +3,7 @@ import type { FilterState } from '~/components/FilterBar.vue'
|
||||||
import { onMounted, ref, watch, computed } from 'vue'
|
import { onMounted, ref, watch, computed } from 'vue'
|
||||||
import { onBeforeRouteLeave } from 'vue-router'
|
import { onBeforeRouteLeave } from 'vue-router'
|
||||||
import { getUserMajorList, type MajorItem } from '~/service/api/major'
|
import { getUserMajorList, type MajorItem } from '~/service/api/major'
|
||||||
import { saveVolunteer, getVolunteerDetail, type VolunteerItem, type VolunteerInfo } from '~/service/api/volunteer'
|
import { saveVolunteer, getVolunteerDetail, updateVolunteerName, getVolunteerList, deleteVolunteer, switchVolunteer, type VolunteerItem, type VolunteerInfo, type VolunteerPlanItem } from '~/service/api/volunteer'
|
||||||
|
|
||||||
// --- 类型定义 ---
|
// --- 类型定义 ---
|
||||||
type TabKey = 'all' | 'hard' | 'risky' | 'safe' | 'stable' | '本科' | '专科' | '985/211/双一流' | '公办本科' | '民办本科'
|
type TabKey = 'all' | 'hard' | 'risky' | 'safe' | 'stable' | '本科' | '专科' | '985/211/双一流' | '公办本科' | '民办本科'
|
||||||
|
|
@ -32,34 +32,12 @@ interface MajorDetail {
|
||||||
|
|
||||||
// --- 状态数据 ---
|
// --- 状态数据 ---
|
||||||
const showSwitchModal = ref(false) // 控制切换方案弹窗显示
|
const showSwitchModal = ref(false) // 控制切换方案弹窗显示
|
||||||
const activePlanId = ref('2025121426') // 当前选中的方案ID
|
const showEditNameModal = ref(false) // 控制编辑名称弹窗显示
|
||||||
|
const editingPlanName = ref('') // 正在编辑的志愿单名称
|
||||||
|
const isUpdatingName = ref(false) // 更新名称Loading状态
|
||||||
|
const activePlanId = ref('') // 当前选中的方案ID
|
||||||
// 模拟方案列表数据 (对应截图)
|
// 模拟方案列表数据 (对应截图)
|
||||||
const volunteerPlans = ref([
|
const volunteerPlans = ref([])
|
||||||
{
|
|
||||||
id: '2025121426',
|
|
||||||
name: '志愿2025121426',
|
|
||||||
tag: '手动', // 截图中的橙色标签
|
|
||||||
province: '北京',
|
|
||||||
artType: '美术与设计类',
|
|
||||||
cultureScore: 450,
|
|
||||||
cultureSubjects: '物化生',
|
|
||||||
artScore: 250,
|
|
||||||
updateTime: '2025-12-14 10:33:46',
|
|
||||||
status: '有效',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '2025121427',
|
|
||||||
name: '志愿2025121427',
|
|
||||||
tag: '智能',
|
|
||||||
province: '湖北',
|
|
||||||
artType: '音乐类',
|
|
||||||
cultureScore: 480,
|
|
||||||
cultureSubjects: '历史',
|
|
||||||
artScore: 240,
|
|
||||||
updateTime: '2025-12-13 14:20:00',
|
|
||||||
status: '有效',
|
|
||||||
},
|
|
||||||
])
|
|
||||||
|
|
||||||
const activePanel = ref<PanelType>('market') // 当前激活的面板
|
const activePanel = ref<PanelType>('market') // 当前激活的面板
|
||||||
const myVolunteers = ref<VolunteerItem[]>([])
|
const myVolunteers = ref<VolunteerItem[]>([])
|
||||||
|
|
@ -560,30 +538,133 @@ function handleCreatePlan() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleEditPlan() {
|
function handleEditPlan() {
|
||||||
console.warn('点击修改方案信息')
|
if (!currentVolunteerInfo.value?.volunteerName) {
|
||||||
// 逻辑:修改当前方案的分数/选科等...
|
// @ts-ignore
|
||||||
|
window.$message?.warning?.('当前志愿单信息为空')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
editingPlanName.value = currentVolunteerInfo.value.volunteerName
|
||||||
|
showEditNameModal.value = true
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleSwitchPlan() {
|
/**
|
||||||
|
* 保存志愿单名称
|
||||||
|
*/
|
||||||
|
async function saveVolunteerName() {
|
||||||
|
if (!currentVolunteerInfo.value?.id || !editingPlanName.value.trim()) {
|
||||||
|
// @ts-ignore
|
||||||
|
window.$message?.warning?.('志愿单名称不能为空')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
isUpdatingName.value = true
|
||||||
|
try {
|
||||||
|
await updateVolunteerName(currentVolunteerInfo.value.id, editingPlanName.value.trim())
|
||||||
|
// @ts-ignore
|
||||||
|
window.$message?.success?.('名称修改成功')
|
||||||
|
// 更新本地数据
|
||||||
|
if (currentVolunteerInfo.value) {
|
||||||
|
currentVolunteerInfo.value.volunteerName = editingPlanName.value.trim()
|
||||||
|
}
|
||||||
|
showEditNameModal.value = false
|
||||||
|
} catch (error) {
|
||||||
|
console.error('修改志愿单名称失败:', error)
|
||||||
|
// @ts-ignore
|
||||||
|
window.$message?.error?.('修改失败,请重试')
|
||||||
|
} finally {
|
||||||
|
isUpdatingName.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 取消编辑名称
|
||||||
|
*/
|
||||||
|
function cancelEditName() {
|
||||||
|
showEditNameModal.value = false
|
||||||
|
editingPlanName.value = ''
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 打开切换方案弹框并加载方案列表
|
||||||
|
*/
|
||||||
|
async function handleSwitchPlan() {
|
||||||
showSwitchModal.value = true
|
showSwitchModal.value = true
|
||||||
|
try {
|
||||||
|
const res = await getVolunteerList(1, 100)
|
||||||
|
if (res && res.items) {
|
||||||
|
// 将 API 返回的数据转换为界面需要的格式
|
||||||
|
volunteerPlans.value = res.items.map(item => ({
|
||||||
|
id: item.id,
|
||||||
|
name: item.volunteerName,
|
||||||
|
tag: item.createType === '1' ? '手动' : '智能',
|
||||||
|
province: '河南', // API 返回数据中没有这些字段,暂时使用默认值
|
||||||
|
artType: '美术与设计类',
|
||||||
|
culturalScore: item.culturalScore,
|
||||||
|
professionalScore: item.professionalScore,
|
||||||
|
cultureSubjects: '-',
|
||||||
|
updateTime: item.updateTime,
|
||||||
|
status: item.state === '1' ? '使用中' : (item.state === '0' ? '未使用' : '历史'),
|
||||||
|
}))
|
||||||
|
// 更新当前激活的方案ID
|
||||||
|
if (currentVolunteerInfo.value?.id) {
|
||||||
|
activePlanId.value = currentVolunteerInfo.value.id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取志愿单列表失败:', error)
|
||||||
|
// @ts-ignore
|
||||||
|
window.$message?.error?.('获取志愿单列表失败')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleExportPlan() {
|
function handleExportPlan() {
|
||||||
console.warn('点击导出当前方案')
|
console.warn('点击导出当前方案')
|
||||||
}
|
}
|
||||||
|
|
||||||
// 切换到指定方案
|
/**
|
||||||
function switchActivePlan(planId: string) {
|
* 切换到指定方案
|
||||||
activePlanId.value = planId
|
*/
|
||||||
showSwitchModal.value = false
|
async function switchActivePlan(planId: string) {
|
||||||
console.warn('切换到了方案:', planId)
|
try {
|
||||||
// 逻辑:重新加载 myVolunteers 数据...
|
await switchVolunteer(planId)
|
||||||
// isLoading.value = true ...
|
activePlanId.value = planId
|
||||||
|
showSwitchModal.value = false
|
||||||
|
// @ts-ignore
|
||||||
|
window.$message?.success?.('切换志愿单成功')
|
||||||
|
// 重新加载志愿详情
|
||||||
|
await fetchVolunteerDetail()
|
||||||
|
} catch (error) {
|
||||||
|
console.error('切换志愿单失败:', error)
|
||||||
|
// @ts-ignore
|
||||||
|
window.$message?.error?.('切换志愿单失败')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function deletePlan(planId: string) {
|
/**
|
||||||
console.warn('删除方案:', planId)
|
* 删除志愿单
|
||||||
// 逻辑:删除API调用...
|
*/
|
||||||
|
async function deletePlan(planId: string) {
|
||||||
|
const confirmDelete = window.confirm('确定要删除这个志愿单吗?删除后无法恢复。')
|
||||||
|
if (!confirmDelete) return
|
||||||
|
|
||||||
|
try {
|
||||||
|
await deleteVolunteer(planId)
|
||||||
|
// @ts-ignore
|
||||||
|
window.$message?.success?.('删除成功')
|
||||||
|
// 从列表中移除
|
||||||
|
const index = volunteerPlans.value.findIndex(p => p.id === planId)
|
||||||
|
if (index > -1) {
|
||||||
|
volunteerPlans.value.splice(index, 1)
|
||||||
|
}
|
||||||
|
// 如果删除的是当前激活的志愿单,重新加载详情
|
||||||
|
if (activePlanId.value === planId) {
|
||||||
|
await fetchVolunteerDetail()
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('删除志愿单失败:', error)
|
||||||
|
// @ts-ignore
|
||||||
|
window.$message?.error?.('删除失败')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
@ -1478,8 +1559,7 @@ function deletePlan(planId: string) {
|
||||||
class="appearance-none border border-slate-300 dark:border-slate-700 rounded bg-white dark:bg-slate-800 py-1.5 pl-3 pr-8 text-sm text-slate-700 dark:text-slate-300 focus:border-blue-500 focus:outline-none focus:ring-1 focus:ring-blue-500"
|
class="appearance-none border border-slate-300 dark:border-slate-700 rounded bg-white dark:bg-slate-800 py-1.5 pl-3 pr-8 text-sm text-slate-700 dark:text-slate-300 focus:border-blue-500 focus:outline-none focus:ring-1 focus:ring-blue-500"
|
||||||
>
|
>
|
||||||
<option>请选择省份</option>
|
<option>请选择省份</option>
|
||||||
<option>北京</option>
|
<option>河南</option>
|
||||||
<option>湖北</option>
|
|
||||||
</select>
|
</select>
|
||||||
<div class="pointer-events-none absolute inset-y-0 right-0 flex items-center px-2 text-slate-500 dark:text-slate-600">
|
<div class="pointer-events-none absolute inset-y-0 right-0 flex items-center px-2 text-slate-500 dark:text-slate-600">
|
||||||
<svg class="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
<svg class="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
|
@ -1540,12 +1620,12 @@ function deletePlan(planId: string) {
|
||||||
{{ plan.artType }}
|
{{ plan.artType }}
|
||||||
</td>
|
</td>
|
||||||
<td class="border-r border-slate-100 dark:border-slate-800 px-4 py-3 text-center">
|
<td class="border-r border-slate-100 dark:border-slate-800 px-4 py-3 text-center">
|
||||||
<span class="text-slate-800 dark:text-slate-200 font-medium">{{ plan.cultureScore }}</span>
|
<span class="text-slate-800 dark:text-slate-200 font-medium">{{ plan.culturalScore }}</span>
|
||||||
<span class="ml-1 text-xs text-slate-400 dark:text-slate-500">{{ plan.cultureSubjects }}</span>
|
<!-- <span class="ml-1 text-xs text-slate-400 dark:text-slate-500">{{ plan.professionalScore }}</span> -->
|
||||||
</td>
|
</td>
|
||||||
<td class="border-r border-slate-100 dark:border-slate-800 px-4 py-3 text-center text-slate-800 dark:text-slate-200 font-medium">
|
<td class="border-r border-slate-100 dark:border-slate-800 px-4 py-3 text-center text-slate-800 dark:text-slate-200 font-medium">
|
||||||
{{
|
{{
|
||||||
plan.artScore }}
|
plan.professionalScore }}
|
||||||
</td>
|
</td>
|
||||||
<td class="border-r border-slate-100 dark:border-slate-800 px-4 py-3 text-center text-xs text-slate-500 dark:text-slate-500 font-mono">
|
<td class="border-r border-slate-100 dark:border-slate-800 px-4 py-3 text-center text-xs text-slate-500 dark:text-slate-500 font-mono">
|
||||||
{{
|
{{
|
||||||
|
|
@ -1584,6 +1664,72 @@ function deletePlan(planId: string) {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- =========================================================
|
||||||
|
编辑名称弹框 (新增)
|
||||||
|
========================================================== -->
|
||||||
|
<div
|
||||||
|
v-if="showEditNameModal"
|
||||||
|
class="fixed inset-0 z-[110] flex items-center justify-center bg-black/50 backdrop-blur-sm"
|
||||||
|
@click.self="cancelEditName"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="w-[400px] flex flex-col animate-fade-in-up overflow-hidden rounded-lg bg-white dark:bg-slate-900 shadow-2xl border border-transparent dark:border-slate-800"
|
||||||
|
>
|
||||||
|
<!-- Header -->
|
||||||
|
<div class="flex items-center justify-between border-b border-slate-200 dark:border-slate-800 px-6 py-4">
|
||||||
|
<h3 class="text-lg text-slate-800 dark:text-slate-100 font-bold">
|
||||||
|
修改志愿单名称
|
||||||
|
</h3>
|
||||||
|
<button class="text-slate-400 dark:text-slate-500 hover:text-slate-600 dark:hover:text-slate-300" @click="cancelEditName">
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24"
|
||||||
|
stroke="currentColor"
|
||||||
|
>
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Content -->
|
||||||
|
<div class="p-6">
|
||||||
|
<div class="mb-4">
|
||||||
|
<label class="block mb-2 text-sm font-medium text-slate-700 dark:text-slate-300">
|
||||||
|
志愿单名称
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
v-model="editingPlanName"
|
||||||
|
type="text"
|
||||||
|
class="w-full border border-slate-300 dark:border-slate-700 rounded-lg bg-white dark:bg-slate-800 px-4 py-2.5 text-sm text-slate-900 dark:text-slate-100 focus:border-blue-500 focus:outline-none focus:ring-2 focus:ring-blue-500/50"
|
||||||
|
placeholder="请输入志愿单名称"
|
||||||
|
maxlength="50"
|
||||||
|
@keyup.enter="saveVolunteerName"
|
||||||
|
/>
|
||||||
|
<p class="mt-1 text-xs text-slate-500 dark:text-slate-400">
|
||||||
|
最多输入 50 个字符
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Footer -->
|
||||||
|
<div class="flex items-center justify-end gap-3 border-t border-slate-200 dark:border-slate-800 bg-slate-50 dark:bg-slate-800/50 px-6 py-4">
|
||||||
|
<button
|
||||||
|
class="rounded-lg px-4 py-2 text-sm text-slate-600 dark:text-slate-400 transition-colors hover:bg-slate-100 dark:hover:bg-slate-800"
|
||||||
|
@click="cancelEditName"
|
||||||
|
>
|
||||||
|
取消
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
class="rounded-lg bg-blue-600 px-4 py-2 text-sm text-white font-medium transition-colors hover:bg-blue-700 disabled:opacity-50 disabled:cursor-not-allowed"
|
||||||
|
:disabled="!editingPlanName.trim() || isUpdatingName"
|
||||||
|
@click="saveVolunteerName"
|
||||||
|
>
|
||||||
|
<span v-if="isUpdatingName" class="mr-1 inline-block h-3 w-3 animate-spin border-2 border-white/30 border-t-white rounded-full"></span>
|
||||||
|
保存
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</Teleport>
|
</Teleport>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
|
|
@ -28,12 +28,29 @@ export interface VolunteerDetailResponse {
|
||||||
items: Record<string, VolunteerItem[]>
|
items: Record<string, VolunteerItem[]>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface VolunteerPlanItem {
|
||||||
|
id: string
|
||||||
|
volunteerName: string
|
||||||
|
scoreId: string
|
||||||
|
createType: string
|
||||||
|
state: string
|
||||||
|
createBy: string
|
||||||
|
createTime: string
|
||||||
|
updateBy: string
|
||||||
|
updateTime: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface VolunteerListResponse {
|
||||||
|
items: VolunteerPlanItem[]
|
||||||
|
total: number
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 保存志愿明细
|
* 保存志愿明细
|
||||||
* @param data schoolCode_majorCode_enrollmentCode 字符串数组
|
* @param data schoolCode_majorCode_enrollmentCode 字符串数组
|
||||||
*/
|
*/
|
||||||
export function saveVolunteer(data: string[]) {
|
export function saveVolunteer(data: string[]) {
|
||||||
return request.post('/user/volunteer/save', data)
|
return request.post('/user/volunteer/save', {keys:data})
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -42,3 +59,37 @@ export function saveVolunteer(data: string[]) {
|
||||||
export function getVolunteerDetail() {
|
export function getVolunteerDetail() {
|
||||||
return request.get<VolunteerDetailResponse>('/user/volunteer/detail')
|
return request.get<VolunteerDetailResponse>('/user/volunteer/detail')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 编辑志愿单名称
|
||||||
|
* @param id 志愿单ID
|
||||||
|
* @param name 志愿单名称
|
||||||
|
*/
|
||||||
|
export function updateVolunteerName(id: string, name: string) {
|
||||||
|
return request.put('/user/volunteer/updateName', null, { params: { id, name } })
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取当前用户志愿单列表
|
||||||
|
* @param page 页码
|
||||||
|
* @param size 每页数量
|
||||||
|
*/
|
||||||
|
export function getVolunteerList(page: number = 1, size: number = 10) {
|
||||||
|
return request.get<VolunteerListResponse>('/user/volunteer/list', { params: { page, size } })
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除志愿单
|
||||||
|
* @param id 志愿单ID
|
||||||
|
*/
|
||||||
|
export function deleteVolunteer(id: string) {
|
||||||
|
return request.delete('/user/volunteer/delete', { params: { id } })
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 切换当前志愿单
|
||||||
|
* @param id 志愿单ID
|
||||||
|
*/
|
||||||
|
export function switchVolunteer(id: string) {
|
||||||
|
return request.post('/user/volunteer/switch', null, { params: { id } })
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -141,6 +141,14 @@ class Request {
|
||||||
post<T = any>(url: string, data?: any, config?: RequestConfig): Promise<T> {
|
post<T = any>(url: string, data?: any, config?: RequestConfig): Promise<T> {
|
||||||
return this.instance.post(url, data, config)
|
return this.instance.post(url, data, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
put<T = any>(url: string, data?: any, config?: RequestConfig): Promise<T> {
|
||||||
|
return this.instance.put(url, data, config)
|
||||||
|
}
|
||||||
|
|
||||||
|
delete<T = any>(url: string, config?: RequestConfig): Promise<T> {
|
||||||
|
return this.instance.delete(url, config)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default new Request({
|
export default new Request({
|
||||||
|
|
|
||||||
|
|
@ -22,9 +22,13 @@ export interface DictType {
|
||||||
const staticDicts: DictType = {
|
const staticDicts: DictType = {
|
||||||
// 专业类别
|
// 专业类别
|
||||||
professionalCategory: [
|
professionalCategory: [
|
||||||
{ label: '理工类', value: 'science', color: '#108ee9' },
|
{ label: '美术与设计类', value: 'science', color: '#108ee9' },
|
||||||
{ label: '文史类', value: 'liberal_arts', color: '#2db7f5' },
|
{ label: '播音与主持类', value: 'liberal_arts', color: '#2db7f5' },
|
||||||
{ label: '艺术类', value: 'art', color: '#87d068' },
|
{ label: '表演类', value: 'art', color: '#87d068' },
|
||||||
|
{ label: '音乐类', value: 'sports', color: '#ff5500' },
|
||||||
|
{ label: '舞蹈类', value: 'sports', color: '#ff5500' },
|
||||||
|
{ label: '书法类', value: 'sports', color: '#ff5500' },
|
||||||
|
{ label: '戏曲类', value: 'sports', color: '#ff5500' },
|
||||||
{ label: '体育类', value: 'sports', color: '#ff5500' },
|
{ label: '体育类', value: 'sports', color: '#ff5500' },
|
||||||
],
|
],
|
||||||
|
|
||||||
|
|
@ -73,9 +77,9 @@ const staticDicts: DictType = {
|
||||||
|
|
||||||
// 科目列表
|
// 科目列表
|
||||||
subjectList: [
|
subjectList: [
|
||||||
{ label: '语文', value: 'chinese', color: '#108ee9' },
|
// { label: '语文', value: 'chinese', color: '#108ee9' },
|
||||||
{ label: '数学', value: 'mathematics', color: '#2db7f5' },
|
// { label: '数学', value: 'mathematics', color: '#2db7f5' },
|
||||||
{ label: '英语', value: 'english', color: '#87d068' },
|
// { label: '英语', value: 'english', color: '#87d068' },
|
||||||
{ label: '物理', value: 'physics', color: '#ff5500' },
|
{ label: '物理', value: 'physics', color: '#ff5500' },
|
||||||
{ label: '化学', value: 'chemistry', color: '#f5222d' },
|
{ label: '化学', value: 'chemistry', color: '#f5222d' },
|
||||||
{ label: '生物', value: 'biology', color: '#fa8c16' },
|
{ label: '生物', value: 'biology', color: '#fa8c16' },
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@ const Message = (options: MessageOptions) => {
|
||||||
if (!messageContainer) {
|
if (!messageContainer) {
|
||||||
messageContainer = document.createElement('div')
|
messageContainer = document.createElement('div')
|
||||||
// Common classes
|
// Common classes
|
||||||
let classes = `w-message-container ${containerClass} fixed z-50 flex pointer-events-none transition-all duration-300`
|
let classes = `w-message-container ${containerClass} fixed z-[9999] flex pointer-events-none transition-all duration-300`
|
||||||
// Position specific classes
|
// Position specific classes
|
||||||
classes += ` ${positionClasses[position]}`
|
classes += ` ${positionClasses[position]}`
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue