wuzhen update
This commit is contained in:
1 parent
e06d8fca2c
commit
9b7a6e2103
138 files changed
+29581
No files matched your search
@@ -0,0 +1,171 @@
|
||||
import request from '@/utils/request';
|
||||
import { AxiosPromise } from 'axios';
|
||||
import {
|
||||
ScholarshipApplicationVO,
|
||||
ScholarshipApplicationForm,
|
||||
ScholarshipApplicationQuery,
|
||||
ScholarshipClassQuotaVO,
|
||||
ScholarshipAttachmentVO
|
||||
} from './types';
|
||||
|
||||
/**
|
||||
* 查询奖学金申请记录列表
|
||||
* @param query 查询参数
|
||||
*/
|
||||
export const listScholarshipApplication = (query?: ScholarshipApplicationQuery): AxiosPromise<ScholarshipApplicationVO[]> => {
|
||||
return request({
|
||||
url: '/jcbt/scholarshipApplication/list',
|
||||
method: 'get',
|
||||
params: query
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 查询奖学金申请记录详细信息
|
||||
* @param id 申请记录ID
|
||||
*/
|
||||
export const getScholarshipApplication = (id: string | number): AxiosPromise<ScholarshipApplicationVO> => {
|
||||
return request({
|
||||
url: `/jcbt/scholarshipApplication/${id}`,
|
||||
method: 'get'
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 新增奖学金申请记录
|
||||
* @param data 申请数据
|
||||
*/
|
||||
export const addScholarshipApplication = (data: ScholarshipApplicationForm) => {
|
||||
return request({
|
||||
url: '/jcbt/scholarshipApplication',
|
||||
method: 'post',
|
||||
data: data
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 修改奖学金申请记录
|
||||
* @param data 申请数据
|
||||
*/
|
||||
export const updateScholarshipApplication = (data: ScholarshipApplicationForm) => {
|
||||
return request({
|
||||
url: '/jcbt/scholarshipApplication',
|
||||
method: 'put',
|
||||
data: data
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 删除奖学金申请记录
|
||||
* @param id 申请记录ID
|
||||
*/
|
||||
export const delScholarshipApplication = (id: string | number | Array<string | number>) => {
|
||||
return request({
|
||||
url: `/jcbt/scholarshipApplication/${id}`,
|
||||
method: 'delete'
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 导出奖学金申请记录
|
||||
* @param query 查询参数
|
||||
*/
|
||||
export const exportScholarshipApplication = (query: ScholarshipApplicationQuery) => {
|
||||
return request({
|
||||
url: '/jcbt/scholarshipApplication/export',
|
||||
method: 'post',
|
||||
data: query,
|
||||
responseType: 'blob'
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 下载导入模板
|
||||
*/
|
||||
export const importTemplate = () => {
|
||||
return request({
|
||||
url: '/jcbt/scholarshipApplication/importTemplate',
|
||||
method: 'post',
|
||||
responseType: 'blob'
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 批量导入奖学金申请记录
|
||||
* @param file 导入文件
|
||||
*/
|
||||
export const importData = (file: File) => {
|
||||
const formData = new FormData();
|
||||
formData.append('file', file);
|
||||
return request({
|
||||
url: '/jcbt/scholarshipApplication/import',
|
||||
method: 'post',
|
||||
data: formData,
|
||||
headers: {
|
||||
'Content-Type': 'multipart/form-data'
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 查询班级奖学金名额
|
||||
* @param query 查询参数
|
||||
*/
|
||||
export const listScholarshipClassQuota = (query?: any): AxiosPromise<ScholarshipClassQuotaVO[]> => {
|
||||
return request({
|
||||
url: '/jcbt/scholarshipClassQuota/list',
|
||||
method: 'get',
|
||||
params: query
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 查询奖学金附件信息
|
||||
* @param applicationId 申请记录ID
|
||||
*/
|
||||
export const listScholarshipAttachment = (applicationId: string | number): AxiosPromise<ScholarshipAttachmentVO[]> => {
|
||||
return request({
|
||||
url: '/jcbt/scholarshipAttachment/list',
|
||||
method: 'get',
|
||||
params: { applicationId }
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 审核奖学金申请
|
||||
* @param id 申请记录ID
|
||||
* @param auditStatus 审核状态
|
||||
* @param auditRemark 审核备注
|
||||
*/
|
||||
export const auditScholarshipApplication = (id: string | number, auditStatus: string, auditRemark?: string) => {
|
||||
return request({
|
||||
url: `/jcbt/scholarshipApplication/${id}/audit`,
|
||||
method: 'put',
|
||||
params: {
|
||||
auditStatus,
|
||||
auditRemark
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 提交奖学金申请
|
||||
* @param id 申请记录ID
|
||||
*/
|
||||
export const submitScholarshipApplication = (id: string | number) => {
|
||||
return request({
|
||||
url: `/jcbt/scholarshipApplication/${id}/submit`,
|
||||
method: 'put'
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 撤销奖学金申请
|
||||
* @param id 申请记录ID
|
||||
*/
|
||||
export const revokeScholarshipApplication = (id: string | number) => {
|
||||
return request({
|
||||
url: `/jcbt/scholarshipApplication/${id}/revoke`,
|
||||
method: 'put'
|
||||
});
|
||||
};
|
||||
@@ -0,0 +1,192 @@
|
||||
import request from '@/utils/request';
|
||||
import { AxiosPromise } from 'axios';
|
||||
|
||||
export interface ScholarshipApplicationVO {
|
||||
/** 主键ID */
|
||||
id?: string | number;
|
||||
/** 批次ID */
|
||||
batchId?: string | number;
|
||||
/** 奖学金类型ID */
|
||||
scholarshipTypeId?: string | number;
|
||||
/** 学生学号 */
|
||||
studentCode?: string;
|
||||
/** 学生姓名 */
|
||||
studentName?: string;
|
||||
/** 学生ID */
|
||||
studentId?: string | number;
|
||||
/** 学院ID */
|
||||
deptId?: string | number;
|
||||
/** 学院名称 */
|
||||
deptName?: string;
|
||||
/** 班级ID */
|
||||
classId?: string | number;
|
||||
/** 班级名称 */
|
||||
className?: string;
|
||||
/** 申请人类型 */
|
||||
applicantType?: string;
|
||||
/** 申请人ID */
|
||||
applicantId?: string | number;
|
||||
/** 申请人姓名 */
|
||||
applicantName?: string;
|
||||
/** 申请类型 */
|
||||
applicationType?: string;
|
||||
/** 申请原因 */
|
||||
applicationReason?: string;
|
||||
/** 申请说明 */
|
||||
applicationDescription?: string;
|
||||
/** 状态 */
|
||||
status?: string;
|
||||
/** 创建时间 */
|
||||
createTime?: string;
|
||||
}
|
||||
|
||||
export interface ScholarshipApplicationForm {
|
||||
/** 主键ID */
|
||||
id?: string | number;
|
||||
/** 批次ID */
|
||||
batchId?: string | number;
|
||||
/** 奖学金类型ID */
|
||||
scholarshipTypeId?: string | number;
|
||||
/** 学生ID列表(班主任勾选) */
|
||||
studentIds?: number[];
|
||||
/** 申请人类型 */
|
||||
applicantType?: string;
|
||||
/** 申请人ID */
|
||||
applicantId?: string | number;
|
||||
/** 申请人姓名 */
|
||||
applicantName?: string;
|
||||
/** 申请类型 */
|
||||
applicationType?: string;
|
||||
/** 申请原因 */
|
||||
applicationReason?: string;
|
||||
/** 申请说明 */
|
||||
applicationDescription?: string;
|
||||
}
|
||||
|
||||
export interface ScholarshipApplicationQuery extends PageQuery {
|
||||
/** 批次ID */
|
||||
batchId?: string | number;
|
||||
/** 奖学金类型ID */
|
||||
scholarshipTypeId?: string | number;
|
||||
/** 学生学号 */
|
||||
studentCode?: string;
|
||||
/** 学生姓名 */
|
||||
studentName?: string;
|
||||
/** 申请人ID */
|
||||
applicantId?: string | number;
|
||||
/** 状态 */
|
||||
status?: string;
|
||||
}
|
||||
|
||||
// 查询奖学金申请记录列表
|
||||
export function listScholarshipApplication(query: ScholarshipApplicationQuery): AxiosPromise<ScholarshipApplicationVO[]> {
|
||||
return request({
|
||||
url: '/jcbt/scholarshipApplication/list',
|
||||
method: 'get',
|
||||
params: query
|
||||
});
|
||||
}
|
||||
|
||||
// 查询奖学金申请记录详细
|
||||
export function getScholarshipApplication(id: string | number): AxiosPromise<ScholarshipApplicationVO> {
|
||||
return request({
|
||||
url: '/jcbt/scholarshipApplication/' + id,
|
||||
method: 'get'
|
||||
});
|
||||
}
|
||||
|
||||
// 新增奖学金申请记录
|
||||
export function addScholarshipApplication(data: ScholarshipApplicationForm) {
|
||||
return request({
|
||||
url: '/jcbt/scholarshipApplication',
|
||||
method: 'post',
|
||||
data: data
|
||||
});
|
||||
}
|
||||
|
||||
// 修改奖学金申请记录
|
||||
export function updateScholarshipApplication(data: ScholarshipApplicationForm) {
|
||||
return request({
|
||||
url: '/jcbt/scholarshipApplication',
|
||||
method: 'put',
|
||||
data: data
|
||||
});
|
||||
}
|
||||
|
||||
// 删除奖学金申请记录
|
||||
export function delScholarshipApplication(id: string | number | Array<string | number>) {
|
||||
return request({
|
||||
url: '/jcbt/scholarshipApplication/' + id,
|
||||
method: 'delete'
|
||||
});
|
||||
}
|
||||
|
||||
// 导出奖学金申请记录
|
||||
export function exportScholarshipApplication(query: ScholarshipApplicationQuery) {
|
||||
return request({
|
||||
url: '/jcbt/scholarshipApplication/export',
|
||||
method: 'post',
|
||||
data: query
|
||||
});
|
||||
}
|
||||
|
||||
// ========== 班主任申请专用接口 ==========
|
||||
|
||||
// 获取班主任所带班级信息
|
||||
export function getClassInfoByTeacher(teacherId: string | number): AxiosPromise<any> {
|
||||
return request({
|
||||
url: '/jcbt/scholarshipApplication/classInfo',
|
||||
method: 'get',
|
||||
params: { teacherId }
|
||||
});
|
||||
}
|
||||
|
||||
// 获取班级学生列表(用于勾选)
|
||||
export function getClassStudents(classId: string | number): AxiosPromise<any[]> {
|
||||
return request({
|
||||
url: '/jcbt/scholarshipApplication/students',
|
||||
method: 'get',
|
||||
params: { classId }
|
||||
});
|
||||
}
|
||||
|
||||
// 根据批次获取可申请的奖学金类型
|
||||
export function getScholarshipTypesByBatch(batchId: string | number): AxiosPromise<any[]> {
|
||||
return request({
|
||||
url: '/jcbt/scholarshipApplication/scholarshipTypes',
|
||||
method: 'get',
|
||||
params: { batchId }
|
||||
});
|
||||
}
|
||||
|
||||
// 根据批次和班级获取带名额信息的奖学金类型(班主任专用)
|
||||
export function getScholarshipTypesWithQuota(batchId: string | number, classId: string | number): AxiosPromise<any[]> {
|
||||
return request({
|
||||
url: '/jcbt/scholarshipApplication/scholarshipTypesWithQuota',
|
||||
method: 'get',
|
||||
params: { batchId, classId }
|
||||
});
|
||||
}
|
||||
|
||||
// 确认选择班级(多班级时用户选择后调用)
|
||||
export function confirmClassSelection(teacherId: string | number, classId: string | number): AxiosPromise<any> {
|
||||
return request({
|
||||
url: '/jcbt/scholarshipApplication/confirmClass',
|
||||
method: 'post',
|
||||
params: { teacherId, classId }
|
||||
});
|
||||
}
|
||||
|
||||
// 班主任批量申请提交
|
||||
export function batchSubmitByTeacher(batchId: string | number, scholarshipTypeId: string | number, classId: string | number, studentApplications: any[]) {
|
||||
return request({
|
||||
url: '/jcbt/scholarshipApplication/batch',
|
||||
method: 'post',
|
||||
params: {
|
||||
batchId,
|
||||
scholarshipTypeId,
|
||||
classId
|
||||
},
|
||||
data: studentApplications
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,226 @@
|
||||
import request from '@/utils/request';
|
||||
import { AxiosPromise } from 'axios';
|
||||
|
||||
export interface ScholarshipBatchVO {
|
||||
/** 主键ID */
|
||||
id?: string | number;
|
||||
/** 批次编码 */
|
||||
batchCode?: string;
|
||||
/** 批次名称 */
|
||||
batchName?: string;
|
||||
/** 学年 */
|
||||
academicYear?: string;
|
||||
/** 学期 */
|
||||
semester?: number;
|
||||
/** 批次类型 */
|
||||
batchType?: string;
|
||||
/** 开始时间 */
|
||||
startTime?: string;
|
||||
/** 结束时间 */
|
||||
endTime?: string;
|
||||
/** 申请开始时间 */
|
||||
applyStartTime?: string;
|
||||
/** 申请结束时间 */
|
||||
applyEndTime?: string;
|
||||
/** 审核开始时间 */
|
||||
reviewStartTime?: string;
|
||||
/** 审核结束时间 */
|
||||
reviewEndTime?: string;
|
||||
/** 状态 */
|
||||
status?: string;
|
||||
/** 批次描述 */
|
||||
description?: string;
|
||||
/** 通知内容 */
|
||||
noticeContent?: string;
|
||||
/** 关联的奖学金类型ID列表 */
|
||||
scholarshipTypeIds?: Array<string | number>;
|
||||
/** 创建者 */
|
||||
createBy?: number;
|
||||
/** 创建时间 */
|
||||
createTime?: string;
|
||||
/** 更新者 */
|
||||
updateBy?: number;
|
||||
/** 更新时间 */
|
||||
updateTime?: string;
|
||||
}
|
||||
|
||||
export interface ScholarshipBatchForm {
|
||||
/** 主键ID */
|
||||
id?: string | number;
|
||||
/** 批次编码 */
|
||||
batchCode?: string;
|
||||
/** 批次名称 */
|
||||
batchName?: string;
|
||||
/** 学年 */
|
||||
academicYear?: string;
|
||||
/** 学期 */
|
||||
semester?: number;
|
||||
/** 批次类型 */
|
||||
batchType?: string;
|
||||
/** 开始时间 */
|
||||
startTime?: string;
|
||||
/** 结束时间 */
|
||||
endTime?: string;
|
||||
/** 申请开始时间 */
|
||||
applyStartTime?: string;
|
||||
/** 申请结束时间 */
|
||||
applyEndTime?: string;
|
||||
/** 审核开始时间 */
|
||||
reviewStartTime?: string;
|
||||
/** 审核结束时间 */
|
||||
reviewEndTime?: string;
|
||||
/** 状态 */
|
||||
status?: string;
|
||||
/** 批次描述 */
|
||||
description?: string;
|
||||
/** 通知内容 */
|
||||
noticeContent?: string;
|
||||
/** 关联的奖学金类型ID列表 */
|
||||
scholarshipTypeIds?: Array<string | number>;
|
||||
}
|
||||
|
||||
export interface ScholarshipBatchQuery extends PageQuery {
|
||||
/** 批次编码 */
|
||||
batchCode?: string;
|
||||
/** 批次名称 */
|
||||
batchName?: string;
|
||||
/** 学年 */
|
||||
academicYear?: string;
|
||||
/** 学期 */
|
||||
semester?: number;
|
||||
/** 批次类型 */
|
||||
batchType?: string;
|
||||
/** 状态 */
|
||||
status?: string;
|
||||
/** 创建时间 */
|
||||
createTime?: string;
|
||||
}
|
||||
|
||||
// 查询奖学金评定批次列表
|
||||
export function listScholarshipBatch(query: ScholarshipBatchQuery): AxiosPromise<ScholarshipBatchVO[]> {
|
||||
return request({
|
||||
url: '/jcbt/scholarshipBatch/list',
|
||||
method: 'get',
|
||||
params: query
|
||||
});
|
||||
}
|
||||
|
||||
// 查询奖学金评定批次详细
|
||||
export function getScholarshipBatch(id: string | number): AxiosPromise<ScholarshipBatchVO> {
|
||||
return request({
|
||||
url: '/jcbt/scholarshipBatch/' + id,
|
||||
method: 'get'
|
||||
});
|
||||
}
|
||||
|
||||
// 新增奖学金评定批次
|
||||
export function addScholarshipBatch(data: ScholarshipBatchForm) {
|
||||
return request({
|
||||
url: '/jcbt/scholarshipBatch',
|
||||
method: 'post',
|
||||
data: data
|
||||
});
|
||||
}
|
||||
|
||||
// 修改奖学金评定批次
|
||||
export function updateScholarshipBatch(data: ScholarshipBatchForm) {
|
||||
return request({
|
||||
url: '/jcbt/scholarshipBatch',
|
||||
method: 'put',
|
||||
data: data
|
||||
});
|
||||
}
|
||||
|
||||
// 删除奖学金评定批次
|
||||
export function delScholarshipBatch(id: string | number | Array<string | number>) {
|
||||
return request({
|
||||
url: '/jcbt/scholarshipBatch/' + id,
|
||||
method: 'delete'
|
||||
});
|
||||
}
|
||||
|
||||
// 导出奖学金评定批次
|
||||
export function exportScholarshipBatch(query: ScholarshipBatchQuery) {
|
||||
return request({
|
||||
url: '/jcbt/scholarshipBatch/export',
|
||||
method: 'post',
|
||||
data: query
|
||||
});
|
||||
}
|
||||
|
||||
// 根据批次编码查询批次信息
|
||||
export function getScholarshipBatchByCode(batchCode: string): AxiosPromise<ScholarshipBatchVO> {
|
||||
return request({
|
||||
url: '/jcbt/scholarshipBatch/getByCode/' + batchCode,
|
||||
method: 'get'
|
||||
});
|
||||
}
|
||||
|
||||
// 根据学年和学期查询批次列表
|
||||
export function getScholarshipBatchByAcademicYear(academicYear: string, semester?: number): AxiosPromise<ScholarshipBatchVO[]> {
|
||||
return request({
|
||||
url: '/jcbt/scholarshipBatch/getByAcademicYear',
|
||||
method: 'get',
|
||||
params: {
|
||||
academicYear,
|
||||
semester
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 查询启用状态的批次列表
|
||||
export function getActiveBatches(): AxiosPromise<ScholarshipBatchVO[]> {
|
||||
return request({
|
||||
url: '/jcbt/scholarshipBatch/getActiveBatches',
|
||||
method: 'get'
|
||||
});
|
||||
}
|
||||
|
||||
// 检查批次编码是否唯一
|
||||
export function checkBatchCodeUnique(batchCode: string, id?: string | number): AxiosPromise<boolean> {
|
||||
return request({
|
||||
url: '/jcbt/scholarshipBatch/checkBatchCodeUnique',
|
||||
method: 'get',
|
||||
params: {
|
||||
batchCode,
|
||||
id
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 更改批次状态
|
||||
export function changeScholarshipBatchStatus(id: string | number, status: string) {
|
||||
return request({
|
||||
url: '/jcbt/scholarshipBatch/changeStatus',
|
||||
method: 'put',
|
||||
params: {
|
||||
id,
|
||||
status
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 查询当前进行中的批次
|
||||
export function getCurrentActiveBatches(): AxiosPromise<ScholarshipBatchVO[]> {
|
||||
return request({
|
||||
url: '/jcbt/scholarshipBatch/getCurrentActiveBatches',
|
||||
method: 'get'
|
||||
});
|
||||
}
|
||||
|
||||
// 根据状态查询批次列表
|
||||
export function getScholarshipBatchByStatus(status: string): AxiosPromise<ScholarshipBatchVO[]> {
|
||||
return request({
|
||||
url: '/jcbt/scholarshipBatch/getByStatus/' + status,
|
||||
method: 'get'
|
||||
});
|
||||
}
|
||||
|
||||
// 检查批次时间是否有冲突
|
||||
export function checkTimeConflict(data: ScholarshipBatchForm): AxiosPromise<boolean> {
|
||||
return request({
|
||||
url: '/jcbt/scholarshipBatch/checkTimeConflict',
|
||||
method: 'post',
|
||||
data: data
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,217 @@
|
||||
import request from '@/utils/request';
|
||||
|
||||
// 奖学金名额分配查询参数类型
|
||||
export interface ScholarshipQuotaQuery extends PageQuery {
|
||||
batchId?: number;
|
||||
scholarshipTypeId?: number;
|
||||
allocationLevel?: string;
|
||||
targetDeptId?: number;
|
||||
status?: string;
|
||||
isLocked?: number;
|
||||
}
|
||||
|
||||
// 奖学金名额分配对象类型
|
||||
export interface ScholarshipQuotaVO {
|
||||
id?: number;
|
||||
batchId: number;
|
||||
batchName?: string;
|
||||
scholarshipTypeId: number;
|
||||
scholarshipTypeName?: string;
|
||||
allocationLevel: string;
|
||||
targetDeptId: number;
|
||||
targetDeptName?: string;
|
||||
parentQuotaId?: number;
|
||||
totalQuota: number;
|
||||
usedQuota?: number;
|
||||
availableQuota?: number;
|
||||
reservedQuota?: number;
|
||||
allocationRule?: string;
|
||||
allocationBasis?: string;
|
||||
allocationMethod?: string;
|
||||
isAdjustable?: number;
|
||||
isLocked?: number;
|
||||
status?: string;
|
||||
remark?: string;
|
||||
createBy?: number;
|
||||
createTime?: string;
|
||||
updateBy?: number;
|
||||
updateTime?: string;
|
||||
children?: ScholarshipQuotaVO[];
|
||||
}
|
||||
|
||||
// 奖学金名额分配表单类型
|
||||
export interface ScholarshipQuotaForm {
|
||||
id?: number;
|
||||
batchId: number;
|
||||
scholarshipTypeId: number;
|
||||
allocationLevel: string;
|
||||
targetDeptId: number;
|
||||
parentQuotaId?: number;
|
||||
totalQuota: number;
|
||||
usedQuota?: number;
|
||||
reservedQuota?: number;
|
||||
allocationRule?: string;
|
||||
allocationBasis?: string;
|
||||
allocationMethod?: string;
|
||||
isAdjustable?: number;
|
||||
status?: string;
|
||||
remark?: string;
|
||||
}
|
||||
|
||||
// 名额使用统计类型
|
||||
export interface QuotaStatistics {
|
||||
totalQuota: number;
|
||||
usedQuota: number;
|
||||
availableQuota: number;
|
||||
usageRate: number;
|
||||
allocationCount: number;
|
||||
}
|
||||
|
||||
// 批量分配名额类型
|
||||
export interface BatchAllocateQuota {
|
||||
allocationLevel: string;
|
||||
targetDeptId: number;
|
||||
totalQuota: number;
|
||||
allocationBasis?: string;
|
||||
}
|
||||
|
||||
// 查询奖学金名额分配列表
|
||||
export const listScholarshipQuota = (query: ScholarshipQuotaQuery) => {
|
||||
return request({
|
||||
url: '/jcbt/scholarshipQuota/list',
|
||||
method: 'get',
|
||||
params: query
|
||||
});
|
||||
};
|
||||
|
||||
// 按批次查询名额分配
|
||||
export const listScholarshipQuotaByBatch = (batchId: number) => {
|
||||
return request({
|
||||
url: `/jcbt/scholarshipQuota/listByBatch/${batchId}`,
|
||||
method: 'get'
|
||||
});
|
||||
};
|
||||
|
||||
// 按批次和类型查询名额分配
|
||||
export const listScholarshipQuotaByBatchAndType = (batchId: number, scholarshipTypeId: number) => {
|
||||
return request({
|
||||
url: '/jcbt/scholarshipQuota/listByBatchAndType',
|
||||
method: 'get',
|
||||
params: { batchId, scholarshipTypeId }
|
||||
});
|
||||
};
|
||||
|
||||
// 查询名额分配树形结构
|
||||
export const getScholarshipQuotaTree = (batchId: number, scholarshipTypeId?: number) => {
|
||||
return request({
|
||||
url: '/jcbt/scholarshipQuota/tree',
|
||||
method: 'get',
|
||||
params: { batchId, scholarshipTypeId }
|
||||
});
|
||||
};
|
||||
|
||||
// 查询名额使用统计
|
||||
export const getScholarshipQuotaStatistics = (batchId: number) => {
|
||||
return request({
|
||||
url: `/jcbt/scholarshipQuota/statistics/${batchId}`,
|
||||
method: 'get'
|
||||
});
|
||||
};
|
||||
|
||||
// 查询奖学金名额分配详细
|
||||
export const getScholarshipQuota = (id: number) => {
|
||||
return request({
|
||||
url: `/jcbt/scholarshipQuota/${id}`,
|
||||
method: 'get'
|
||||
});
|
||||
};
|
||||
|
||||
// 新增奖学金名额分配
|
||||
export const addScholarshipQuota = (data: ScholarshipQuotaForm) => {
|
||||
return request({
|
||||
url: '/jcbt/scholarshipQuota',
|
||||
method: 'post',
|
||||
data: data
|
||||
});
|
||||
};
|
||||
|
||||
// 修改奖学金名额分配
|
||||
export const updateScholarshipQuota = (data: ScholarshipQuotaForm) => {
|
||||
return request({
|
||||
url: '/jcbt/scholarshipQuota',
|
||||
method: 'put',
|
||||
data: data
|
||||
});
|
||||
};
|
||||
|
||||
// 删除奖学金名额分配
|
||||
export const delScholarshipQuota = (ids: string | number) => {
|
||||
return request({
|
||||
url: `/jcbt/scholarshipQuota/${ids}`,
|
||||
method: 'delete'
|
||||
});
|
||||
};
|
||||
|
||||
// 导出奖学金名额分配
|
||||
export const exportScholarshipQuota = (query: ScholarshipQuotaQuery) => {
|
||||
return request({
|
||||
url: '/jcbt/scholarshipQuota/export',
|
||||
method: 'post',
|
||||
data: query
|
||||
});
|
||||
};
|
||||
|
||||
// 批量分配名额
|
||||
export const batchAllocateQuota = (batchId: number, scholarshipTypeId: number, data: BatchAllocateQuota[]) => {
|
||||
return request({
|
||||
url: '/jcbt/scholarshipQuota/batchAllocate',
|
||||
method: 'post',
|
||||
params: { batchId, scholarshipTypeId },
|
||||
data: data
|
||||
});
|
||||
};
|
||||
|
||||
// 调整名额分配
|
||||
export const adjustQuota = (fromQuotaId: number, toQuotaId: number, adjustAmount: number, reason: string) => {
|
||||
return request({
|
||||
url: '/jcbt/scholarshipQuota/adjust',
|
||||
method: 'post',
|
||||
params: { fromQuotaId, toQuotaId, adjustAmount, reason }
|
||||
});
|
||||
};
|
||||
|
||||
// 锁定/解锁名额分配
|
||||
export const lockScholarshipQuota = (id: number, isLocked: number) => {
|
||||
return request({
|
||||
url: `/jcbt/scholarshipQuota/lock/${id}`,
|
||||
method: 'put',
|
||||
params: { isLocked }
|
||||
});
|
||||
};
|
||||
|
||||
// 自动分配名额
|
||||
export const autoAllocateQuota = (batchId: number, scholarshipTypeId: number, allocationRule: string) => {
|
||||
return request({
|
||||
url: '/jcbt/scholarshipQuota/autoAllocate',
|
||||
method: 'post',
|
||||
params: { batchId, scholarshipTypeId, allocationRule }
|
||||
});
|
||||
};
|
||||
|
||||
// 复制名额分配
|
||||
export const copyScholarshipQuota = (sourceBatchId: number, targetBatchId: number) => {
|
||||
return request({
|
||||
url: '/jcbt/scholarshipQuota/copy',
|
||||
method: 'post',
|
||||
params: { sourceBatchId, targetBatchId }
|
||||
});
|
||||
};
|
||||
|
||||
// 更新名额使用
|
||||
export const updateQuotaUsage = (id: number, usedQuota: number) => {
|
||||
return request({
|
||||
url: `/jcbt/scholarshipQuota/updateUsage/${id}`,
|
||||
method: 'put',
|
||||
params: { usedQuota }
|
||||
});
|
||||
};
|
||||
@@ -0,0 +1,331 @@
|
||||
import request from '@/utils/request';
|
||||
import { AxiosPromise } from 'axios';
|
||||
|
||||
export interface ScholarshipTypeVO {
|
||||
/** 主键ID */
|
||||
id?: string | number;
|
||||
/** 奖学金类型编码 */
|
||||
typeCode?: string;
|
||||
/** 奖学金名称 */
|
||||
typeName?: string;
|
||||
/** 奖学金类别 */
|
||||
typeCategory?: string;
|
||||
/** 奖学金等级 */
|
||||
levelType?: string;
|
||||
/** 奖励金额 */
|
||||
awardAmount?: number;
|
||||
/** 奖学金描述 */
|
||||
description?: string;
|
||||
/** 申请指南 */
|
||||
applicationGuide?: string;
|
||||
/** 兼得类型 */
|
||||
compatibilityType?: string;
|
||||
/** 排序号 */
|
||||
sortOrder?: number;
|
||||
/** 状态 */
|
||||
status?: number;
|
||||
/** 是否系统内置 */
|
||||
isSystem?: number;
|
||||
/** 创建者 */
|
||||
createBy?: number;
|
||||
/** 创建时间 */
|
||||
createTime?: string;
|
||||
/** 更新者 */
|
||||
updateBy?: number;
|
||||
/** 更新时间 */
|
||||
updateTime?: string;
|
||||
}
|
||||
|
||||
export interface ScholarshipTypeForm {
|
||||
/** 主键ID */
|
||||
id?: string | number;
|
||||
/** 奖学金类型编码 */
|
||||
typeCode?: string;
|
||||
/** 奖学金名称 */
|
||||
typeName?: string;
|
||||
/** 奖学金类别 */
|
||||
typeCategory?: string;
|
||||
/** 奖学金等级 */
|
||||
levelType?: string;
|
||||
/** 奖励金额 */
|
||||
awardAmount?: number;
|
||||
/** 奖学金描述 */
|
||||
description?: string;
|
||||
/** 申请指南 */
|
||||
applicationGuide?: string;
|
||||
/** 兼得类型 */
|
||||
compatibilityType?: string;
|
||||
/** 排序号 */
|
||||
sortOrder?: number;
|
||||
/** 状态 */
|
||||
status?: number;
|
||||
/** 是否系统内置 */
|
||||
isSystem?: number;
|
||||
/** 自定义互斥类型ID列表 */
|
||||
exclusiveTypeIds?: Array<string | number>;
|
||||
}
|
||||
|
||||
export interface ScholarshipTypeQuery {
|
||||
/** 当前页码 */
|
||||
pageNum?: number;
|
||||
/** 每页显示记录数 */
|
||||
pageSize?: number;
|
||||
/** 奖学金类型编码 */
|
||||
typeCode?: string;
|
||||
/** 奖学金名称 */
|
||||
typeName?: string;
|
||||
/** 奖学金类别 */
|
||||
typeCategory?: string;
|
||||
/** 奖学金等级 */
|
||||
levelType?: string;
|
||||
/** 兼得类型 */
|
||||
compatibilityType?: string;
|
||||
/** 状态 */
|
||||
status?: number;
|
||||
/** 是否系统内置 */
|
||||
isSystem?: number;
|
||||
/** 创建时间范围 */
|
||||
params?: {
|
||||
beginCreateTime?: string;
|
||||
endCreateTime?: string;
|
||||
};
|
||||
}
|
||||
|
||||
export interface ScholarshipTypeOption {
|
||||
/** 选项值 */
|
||||
value?: string | number;
|
||||
/** 选项标签 */
|
||||
label?: string;
|
||||
/** 扩展数据 */
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询奖学金类型列表
|
||||
* @param query 查询参数
|
||||
*/
|
||||
export const listScholarshipType = (query?: ScholarshipTypeQuery): AxiosPromise<ScholarshipTypeVO[]> => {
|
||||
return request({
|
||||
url: '/jcbt/scholarshipType/list',
|
||||
method: 'get',
|
||||
params: query
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 查询奖学金类型详细信息
|
||||
* @param id 奖学金类型ID
|
||||
*/
|
||||
export const getScholarshipType = (id: string | number): AxiosPromise<ScholarshipTypeVO> => {
|
||||
return request({
|
||||
url: `/jcbt/scholarshipType/${id}`,
|
||||
method: 'get'
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 新增奖学金类型
|
||||
* @param data 奖学金类型数据
|
||||
*/
|
||||
export const addScholarshipType = (data: ScholarshipTypeForm) => {
|
||||
return request({
|
||||
url: '/jcbt/scholarshipType',
|
||||
method: 'post',
|
||||
data: data
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 修改奖学金类型
|
||||
* @param data 奖学金类型数据
|
||||
*/
|
||||
export const updateScholarshipType = (data: ScholarshipTypeForm) => {
|
||||
return request({
|
||||
url: '/jcbt/scholarshipType',
|
||||
method: 'put',
|
||||
data: data
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 删除奖学金类型
|
||||
* @param id 奖学金类型ID
|
||||
*/
|
||||
export const delScholarshipType = (id: string | number | Array<string | number>) => {
|
||||
return request({
|
||||
url: `/jcbt/scholarshipType/${id}`,
|
||||
method: 'delete'
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 导出奖学金类型数据
|
||||
* @param query 查询参数
|
||||
*/
|
||||
export const exportScholarshipType = (query?: ScholarshipTypeQuery) => {
|
||||
return request({
|
||||
url: '/jcbt/scholarshipType/export',
|
||||
method: 'post',
|
||||
data: query
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 根据名称查询奖学金类型
|
||||
* @param typeName 奖学金名称
|
||||
*/
|
||||
export const getScholarshipTypeByName = (typeName: string): AxiosPromise<ScholarshipTypeVO> => {
|
||||
return request({
|
||||
url: `/jcbt/scholarshipType/getByName/${typeName}`,
|
||||
method: 'get'
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 根据类别查询奖学金类型
|
||||
* @param typeCategory 奖学金类别
|
||||
*/
|
||||
export const getScholarshipTypeByCategory = (typeCategory: string): AxiosPromise<ScholarshipTypeVO[]> => {
|
||||
return request({
|
||||
url: `/jcbt/scholarshipType/getByCategory/${typeCategory}`,
|
||||
method: 'get'
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 查询启用状态的奖学金类型
|
||||
*/
|
||||
export const getActiveScholarshipTypes = (): AxiosPromise<ScholarshipTypeVO[]> => {
|
||||
return request({
|
||||
url: '/jcbt/scholarshipType/getActiveTypes',
|
||||
method: 'get'
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 根据兼得类型查询奖学金类型
|
||||
* @param compatibilityType 兼得类型
|
||||
*/
|
||||
export const getScholarshipTypeByCompatibilityType = (compatibilityType: string): AxiosPromise<ScholarshipTypeVO[]> => {
|
||||
return request({
|
||||
url: `/jcbt/scholarshipType/getByCompatibilityType/${compatibilityType}`,
|
||||
method: 'get'
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 检查奖学金名称是否唯一
|
||||
* @param typeName 奖学金名称
|
||||
* @param id 排除的ID
|
||||
*/
|
||||
export const checkScholarshipTypeNameUnique = (typeName: string, id?: string | number) => {
|
||||
return request({
|
||||
url: '/jcbt/scholarshipType/checkTypeNameUnique',
|
||||
method: 'get',
|
||||
params: { typeName, id }
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 批量更新排序号
|
||||
* @param data 排序数据
|
||||
*/
|
||||
export const batchUpdateSort = (data: Array<{ id: string | number; sortOrder: number }>) => {
|
||||
return request({
|
||||
url: '/jcbt/scholarshipType/batchUpdateSort',
|
||||
method: 'put',
|
||||
data: data
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 启用/停用奖学金类型
|
||||
* @param id 奖学金类型ID
|
||||
* @param status 状态
|
||||
*/
|
||||
export const changeScholarshipTypeStatus = (id: string | number, status: number) => {
|
||||
return request({
|
||||
url: '/jcbt/scholarshipType/changeStatus',
|
||||
method: 'put',
|
||||
params: { id, status }
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取奖学金类型选项列表
|
||||
*/
|
||||
export const getScholarshipTypeOptions = (): AxiosPromise<ScholarshipTypeOption[]> => {
|
||||
return request({
|
||||
url: '/jcbt/scholarshipType/options',
|
||||
method: 'get'
|
||||
});
|
||||
};
|
||||
|
||||
// 兼得关系配置相关接口
|
||||
|
||||
export interface CompatibilityConfig {
|
||||
/** 所有可配置的奖学金类型 */
|
||||
allTypes?: ScholarshipTypeVO[];
|
||||
/** 互斥的奖学金类型ID列表 */
|
||||
exclusiveTypeIds?: number[];
|
||||
/** 兼容的奖学金类型ID列表 */
|
||||
compatibleTypeIds?: number[];
|
||||
/** 互斥的奖学金类型详细信息(包含名称) */
|
||||
exclusiveTypes?: ScholarshipTypeVO[];
|
||||
/** 兼容的奖学金类型详细信息(包含名称) */
|
||||
compatibleTypes?: ScholarshipTypeVO[];
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取奖学金类型的兼得关系配置
|
||||
* @param id 奖学金类型ID
|
||||
*/
|
||||
export const getCompatibilityConfig = (id: string | number): AxiosPromise<CompatibilityConfig> => {
|
||||
return request({
|
||||
url: `/jcbt/scholarshipType/${id}/compatibility`,
|
||||
method: 'get'
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 保存奖学金类型的兼得关系配置
|
||||
* @param id 奖学金类型ID
|
||||
* @param config 配置数据
|
||||
*/
|
||||
export const saveCompatibilityConfig = (
|
||||
id: string | number,
|
||||
config: {
|
||||
exclusiveTypeIds?: number[];
|
||||
compatibleTypeIds?: number[];
|
||||
}
|
||||
) => {
|
||||
return request({
|
||||
url: `/jcbt/scholarshipType/${id}/compatibility`,
|
||||
method: 'post',
|
||||
data: config
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 检查两个奖学金类型是否兼容
|
||||
* @param typeId1 奖学金类型1
|
||||
* @param typeId2 奖学金类型2
|
||||
*/
|
||||
export const checkCompatibility = (typeId1: string | number, typeId2: string | number): AxiosPromise<boolean> => {
|
||||
return request({
|
||||
url: '/jcbt/scholarshipType/checkCompatibility',
|
||||
method: 'get',
|
||||
params: { typeId1, typeId2 }
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取可与指定奖学金兼得的奖学金类型列表
|
||||
* @param id 奖学金类型ID
|
||||
*/
|
||||
export const getCompatibleTypes = (id: string | number): AxiosPromise<ScholarshipTypeVO[]> => {
|
||||
return request({
|
||||
url: `/jcbt/scholarshipType/${id}/compatibleTypes`,
|
||||
method: 'get'
|
||||
});
|
||||
};
|
||||
@@ -0,0 +1,503 @@
|
||||
/**
|
||||
* 奖学金申请模块 - 类型定义
|
||||
*/
|
||||
|
||||
/**
|
||||
* 奖学金申请记录 VO
|
||||
*/
|
||||
export interface ScholarshipApplicationVO {
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
id: string | number;
|
||||
|
||||
/**
|
||||
* 租户编号
|
||||
*/
|
||||
tenantId: string;
|
||||
|
||||
/**
|
||||
* 学年
|
||||
*/
|
||||
academicYear: string;
|
||||
|
||||
/**
|
||||
* 学期
|
||||
*/
|
||||
semester: string;
|
||||
|
||||
/**
|
||||
* 奖学金类型
|
||||
*/
|
||||
scholarshipType: string;
|
||||
|
||||
/**
|
||||
* 奖学金等级
|
||||
*/
|
||||
scholarshipLevel: string;
|
||||
|
||||
/**
|
||||
* 奖学金金额
|
||||
*/
|
||||
amount?: number;
|
||||
|
||||
/**
|
||||
* 学生学号
|
||||
*/
|
||||
studentId: string;
|
||||
|
||||
/**
|
||||
* 学生姓名
|
||||
*/
|
||||
studentName: string;
|
||||
|
||||
/**
|
||||
* 学生性别
|
||||
*/
|
||||
studentGender?: string;
|
||||
|
||||
/**
|
||||
* 学生联系方式
|
||||
*/
|
||||
studentPhone?: string;
|
||||
|
||||
/**
|
||||
* 学生邮箱
|
||||
*/
|
||||
studentEmail?: string;
|
||||
|
||||
/**
|
||||
* 学院名称
|
||||
*/
|
||||
collegeName?: string;
|
||||
|
||||
/**
|
||||
* 专业名称
|
||||
*/
|
||||
majorName?: string;
|
||||
|
||||
/**
|
||||
* 班级名称
|
||||
*/
|
||||
className?: string;
|
||||
|
||||
/**
|
||||
* 年级
|
||||
*/
|
||||
grade?: string;
|
||||
|
||||
/**
|
||||
* 学业成绩排名
|
||||
*/
|
||||
academicRanking?: number;
|
||||
|
||||
/**
|
||||
* 综合测评排名
|
||||
*/
|
||||
comprehensiveRanking?: number;
|
||||
|
||||
/**
|
||||
* 申请理由
|
||||
*/
|
||||
applicationReason?: string;
|
||||
|
||||
/**
|
||||
* 申请状态:draft-草稿,submitted-已提交,approved-已通过,rejected-已驳回
|
||||
*/
|
||||
applicationStatus: string;
|
||||
|
||||
/**
|
||||
* 申请时间
|
||||
*/
|
||||
applicationTime?: string;
|
||||
|
||||
/**
|
||||
* 审核人ID
|
||||
*/
|
||||
auditUserId?: string | number;
|
||||
|
||||
/**
|
||||
* 审核人姓名
|
||||
*/
|
||||
auditUserName?: string;
|
||||
|
||||
/**
|
||||
* 审核时间
|
||||
*/
|
||||
auditTime?: string;
|
||||
|
||||
/**
|
||||
* 审核备注
|
||||
*/
|
||||
auditRemark?: string;
|
||||
|
||||
/**
|
||||
* 审核状态:pending-待审核,approved-已通过,rejected-已驳回
|
||||
*/
|
||||
auditStatus?: string;
|
||||
|
||||
/**
|
||||
* 是否获奖:0-否,1-是
|
||||
*/
|
||||
isAwarded?: string;
|
||||
|
||||
/**
|
||||
* 获奖时间
|
||||
*/
|
||||
awardTime?: string;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
remark?: string;
|
||||
|
||||
/**
|
||||
* 创建人
|
||||
*/
|
||||
createBy?: string | number;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
createTime?: string;
|
||||
|
||||
/**
|
||||
* 更新人
|
||||
*/
|
||||
updateBy?: string | number;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
updateTime?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 奖学金申请记录表单类型
|
||||
*/
|
||||
export interface ScholarshipApplicationForm {
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
id?: string | number;
|
||||
|
||||
/**
|
||||
* 学年
|
||||
*/
|
||||
academicYear: string;
|
||||
|
||||
/**
|
||||
* 学期
|
||||
*/
|
||||
semester: string;
|
||||
|
||||
/**
|
||||
* 奖学金类型
|
||||
*/
|
||||
scholarshipType: string;
|
||||
|
||||
/**
|
||||
* 奖学金等级
|
||||
*/
|
||||
scholarshipLevel: string;
|
||||
|
||||
/**
|
||||
* 奖学金金额
|
||||
*/
|
||||
amount?: number;
|
||||
|
||||
/**
|
||||
* 学生学号
|
||||
*/
|
||||
studentId: string;
|
||||
|
||||
/**
|
||||
* 学生姓名
|
||||
*/
|
||||
studentName: string;
|
||||
|
||||
/**
|
||||
* 学生性别
|
||||
*/
|
||||
studentGender?: string;
|
||||
|
||||
/**
|
||||
* 学生联系方式
|
||||
*/
|
||||
studentPhone?: string;
|
||||
|
||||
/**
|
||||
* 学生邮箱
|
||||
*/
|
||||
studentEmail?: string;
|
||||
|
||||
/**
|
||||
* 学院名称
|
||||
*/
|
||||
collegeName?: string;
|
||||
|
||||
/**
|
||||
* 专业名称
|
||||
*/
|
||||
majorName?: string;
|
||||
|
||||
/**
|
||||
* 班级名称
|
||||
*/
|
||||
className?: string;
|
||||
|
||||
/**
|
||||
* 年级
|
||||
*/
|
||||
grade?: string;
|
||||
|
||||
/**
|
||||
* 学业成绩排名
|
||||
*/
|
||||
academicRanking?: number;
|
||||
|
||||
/**
|
||||
* 综合测评排名
|
||||
*/
|
||||
comprehensiveRanking?: number;
|
||||
|
||||
/**
|
||||
* 申请理由
|
||||
*/
|
||||
applicationReason?: string;
|
||||
|
||||
/**
|
||||
* 申请状态
|
||||
*/
|
||||
applicationStatus?: string;
|
||||
|
||||
/**
|
||||
* 审核备注
|
||||
*/
|
||||
auditRemark?: string;
|
||||
|
||||
/**
|
||||
* 是否获奖
|
||||
*/
|
||||
isAwarded?: string;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
remark?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 奖学金申请记录查询参数
|
||||
*/
|
||||
export interface ScholarshipApplicationQuery extends PageQuery {
|
||||
/**
|
||||
* 学年
|
||||
*/
|
||||
academicYear?: string;
|
||||
|
||||
/**
|
||||
* 学期
|
||||
*/
|
||||
semester?: string;
|
||||
|
||||
/**
|
||||
* 奖学金类型
|
||||
*/
|
||||
scholarshipType?: string;
|
||||
|
||||
/**
|
||||
* 奖学金等级
|
||||
*/
|
||||
scholarshipLevel?: string;
|
||||
|
||||
/**
|
||||
* 学生学号
|
||||
*/
|
||||
studentId?: string;
|
||||
|
||||
/**
|
||||
* 学生姓名
|
||||
*/
|
||||
studentName?: string;
|
||||
|
||||
/**
|
||||
* 学院名称
|
||||
*/
|
||||
collegeName?: string;
|
||||
|
||||
/**
|
||||
* 专业名称
|
||||
*/
|
||||
majorName?: string;
|
||||
|
||||
/**
|
||||
* 班级名称
|
||||
*/
|
||||
className?: string;
|
||||
|
||||
/**
|
||||
* 申请状态
|
||||
*/
|
||||
applicationStatus?: string;
|
||||
|
||||
/**
|
||||
* 审核状态
|
||||
*/
|
||||
auditStatus?: string;
|
||||
|
||||
/**
|
||||
* 是否获奖
|
||||
*/
|
||||
isAwarded?: string;
|
||||
|
||||
/**
|
||||
* 申请时间范围
|
||||
*/
|
||||
applicationTimeRange?: string[];
|
||||
|
||||
/**
|
||||
* 审核时间范围
|
||||
*/
|
||||
auditTimeRange?: string[];
|
||||
|
||||
/**
|
||||
* 获奖时间范围
|
||||
*/
|
||||
awardTimeRange?: string[];
|
||||
}
|
||||
|
||||
/**
|
||||
* 班级奖学金名额 VO
|
||||
*/
|
||||
export interface ScholarshipClassQuotaVO {
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
id: string | number;
|
||||
|
||||
/**
|
||||
* 学年
|
||||
*/
|
||||
academicYear: string;
|
||||
|
||||
/**
|
||||
* 学期
|
||||
*/
|
||||
semester: string;
|
||||
|
||||
/**
|
||||
* 奖学金类型
|
||||
*/
|
||||
scholarshipType: string;
|
||||
|
||||
/**
|
||||
* 奖学金等级
|
||||
*/
|
||||
scholarshipLevel: string;
|
||||
|
||||
/**
|
||||
* 学院名称
|
||||
*/
|
||||
collegeName: string;
|
||||
|
||||
/**
|
||||
* 专业名称
|
||||
*/
|
||||
majorName: string;
|
||||
|
||||
/**
|
||||
* 班级名称
|
||||
*/
|
||||
className: string;
|
||||
|
||||
/**
|
||||
* 分配名额
|
||||
*/
|
||||
quotaCount: number;
|
||||
|
||||
/**
|
||||
* 已申请名额
|
||||
*/
|
||||
appliedCount?: number;
|
||||
|
||||
/**
|
||||
* 已获奖名额
|
||||
*/
|
||||
awardedCount?: number;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
createTime?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 奖学金附件 VO
|
||||
*/
|
||||
export interface ScholarshipAttachmentVO {
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
id: string | number;
|
||||
|
||||
/**
|
||||
* 申请记录ID
|
||||
*/
|
||||
applicationId: string | number;
|
||||
|
||||
/**
|
||||
* 附件类型
|
||||
*/
|
||||
attachmentType: string;
|
||||
|
||||
/**
|
||||
* 文件名称
|
||||
*/
|
||||
fileName: string;
|
||||
|
||||
/**
|
||||
* 文件路径
|
||||
*/
|
||||
filePath: string;
|
||||
|
||||
/**
|
||||
* 文件大小
|
||||
*/
|
||||
fileSize?: number;
|
||||
|
||||
/**
|
||||
* 上传时间
|
||||
*/
|
||||
uploadTime?: string;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
remark?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页查询基础接口
|
||||
*/
|
||||
export interface PageQuery {
|
||||
/**
|
||||
* 当前页码
|
||||
*/
|
||||
pageNum?: number;
|
||||
|
||||
/**
|
||||
* 每页显示记录数
|
||||
*/
|
||||
pageSize?: number;
|
||||
|
||||
/**
|
||||
* 排序字段
|
||||
*/
|
||||
orderByColumn?: string;
|
||||
|
||||
/**
|
||||
* 排序方向
|
||||
*/
|
||||
isAsc?: string;
|
||||
}
|
||||
@@ -0,0 +1,488 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<el-card class="detail-card">
|
||||
<template #header>
|
||||
<div class="detail-header">
|
||||
<span class="detail-title">奖学金申请详情</span>
|
||||
<div class="header-actions">
|
||||
<el-button
|
||||
v-if="canEdit"
|
||||
type="primary"
|
||||
icon="Edit"
|
||||
@click="handleEdit"
|
||||
>
|
||||
编辑
|
||||
</el-button>
|
||||
<el-button @click="goBack" class="back-button">
|
||||
<el-icon><ArrowLeft /></el-icon>
|
||||
返回
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<div v-loading="loading">
|
||||
<!-- 基本信息 -->
|
||||
<div class="detail-section">
|
||||
<div class="section-title">
|
||||
<el-icon><Document /></el-icon>
|
||||
基本信息
|
||||
</div>
|
||||
<el-descriptions :column="2" border>
|
||||
<el-descriptions-item label="学年">
|
||||
{{ detail.academicYear || '-' }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="学期">
|
||||
{{ detail.semester || '-' }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="奖学金类型">
|
||||
{{ detail.scholarshipType || '-' }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="奖学金等级">
|
||||
{{ detail.scholarshipLevel || '-' }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="奖学金金额">
|
||||
<span v-if="detail.amount" class="amount-text">¥{{ detail.amount }}</span>
|
||||
<span v-else>-</span>
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</div>
|
||||
|
||||
<!-- 学生信息 -->
|
||||
<div class="detail-section">
|
||||
<div class="section-title">
|
||||
<el-icon><User /></el-icon>
|
||||
学生信息
|
||||
</div>
|
||||
<el-descriptions :column="2" border>
|
||||
<el-descriptions-item label="学生学号">
|
||||
{{ detail.studentId || '-' }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="学生姓名">
|
||||
{{ detail.studentName || '-' }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="学生性别">
|
||||
{{ detail.studentGender || '-' }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="联系方式">
|
||||
{{ detail.studentPhone || '-' }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="学生邮箱" :span="2">
|
||||
{{ detail.studentEmail || '-' }}
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</div>
|
||||
|
||||
<!-- 班级信息 -->
|
||||
<div class="detail-section">
|
||||
<div class="section-title">
|
||||
<el-icon><School /></el-icon>
|
||||
班级信息
|
||||
</div>
|
||||
<el-descriptions :column="2" border>
|
||||
<el-descriptions-item label="学院名称">
|
||||
{{ detail.collegeName || '-' }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="专业名称">
|
||||
{{ detail.majorName || '-' }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="班级名称">
|
||||
{{ detail.className || '-' }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="年级">
|
||||
{{ detail.grade || '-' }}
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</div>
|
||||
|
||||
<!-- 成绩信息 -->
|
||||
<div class="detail-section">
|
||||
<div class="section-title">
|
||||
<el-icon><Trophy /></el-icon>
|
||||
成绩信息
|
||||
</div>
|
||||
<el-descriptions :column="2" border>
|
||||
<el-descriptions-item label="学业成绩排名">
|
||||
<span v-if="detail.academicRanking">第{{ detail.academicRanking }}名</span>
|
||||
<span v-else>-</span>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="综合测评排名">
|
||||
<span v-if="detail.comprehensiveRanking">第{{ detail.comprehensiveRanking }}名</span>
|
||||
<span v-else>-</span>
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</div>
|
||||
|
||||
<!-- 申请信息 -->
|
||||
<div class="detail-section">
|
||||
<div class="section-title">
|
||||
<el-icon><Edit /></el-icon>
|
||||
申请信息
|
||||
</div>
|
||||
<el-descriptions :column="1" border>
|
||||
<el-descriptions-item label="申请理由">
|
||||
<div class="reason-content">
|
||||
{{ detail.applicationReason || '-' }}
|
||||
</div>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="备注" v-if="detail.remark">
|
||||
<div class="remark-content">
|
||||
{{ detail.remark }}
|
||||
</div>
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</div>
|
||||
|
||||
<!-- 状态信息 -->
|
||||
<div class="detail-section">
|
||||
<div class="section-title">
|
||||
<el-icon><InfoFilled /></el-icon>
|
||||
状态信息
|
||||
</div>
|
||||
<el-descriptions :column="2" border>
|
||||
<el-descriptions-item label="申请状态">
|
||||
<dict-tag :options="application_status" :value="detail.applicationStatus" />
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="审核状态">
|
||||
<dict-tag :options="audit_status" :value="detail.auditStatus" />
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="是否获奖">
|
||||
<dict-tag :options="yes_no" :value="detail.isAwarded" />
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="申请时间">
|
||||
{{ detail.applicationTime || '-' }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="审核时间" v-if="detail.auditTime">
|
||||
{{ detail.auditTime }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="获奖时间" v-if="detail.awardTime">
|
||||
{{ detail.awardTime }}
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</div>
|
||||
|
||||
<!-- 审核信息 -->
|
||||
<div v-if="detail.auditRemark || detail.auditUserName" class="detail-section">
|
||||
<div class="section-title">
|
||||
<el-icon><ChatLineSquare /></el-icon>
|
||||
审核信息
|
||||
</div>
|
||||
<el-descriptions :column="1" border>
|
||||
<el-descriptions-item label="审核人" v-if="detail.auditUserName">
|
||||
{{ detail.auditUserName }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="审核备注" v-if="detail.auditRemark">
|
||||
<div class="audit-remark">
|
||||
{{ detail.auditRemark }}
|
||||
</div>
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</div>
|
||||
|
||||
<!-- 附件信息 -->
|
||||
<div v-if="attachmentList.length > 0" class="detail-section">
|
||||
<div class="section-title">
|
||||
<el-icon><Paperclip /></el-icon>
|
||||
相关附件
|
||||
</div>
|
||||
<el-table :data="attachmentList" border>
|
||||
<el-table-column label="序号" type="index" width="60" align="center" />
|
||||
<el-table-column label="附件类型" prop="attachmentType" width="120" align="center" />
|
||||
<el-table-column label="文件名称" prop="fileName" align="center" />
|
||||
<el-table-column label="文件大小" prop="fileSize" width="100" align="center">
|
||||
<template #default="scope">
|
||||
{{ formatFileSize(scope.row.fileSize) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="上传时间" prop="uploadTime" width="180" align="center" />
|
||||
<el-table-column label="操作" width="100" align="center">
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
type="primary"
|
||||
link
|
||||
icon="Download"
|
||||
@click="handleDownload(scope.row)"
|
||||
>
|
||||
下载
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
|
||||
<!-- 操作日志 -->
|
||||
<div class="detail-section">
|
||||
<div class="section-title">
|
||||
<el-icon><Clock /></el-icon>
|
||||
操作记录
|
||||
</div>
|
||||
<el-timeline>
|
||||
<el-timeline-item
|
||||
v-if="detail.createTime"
|
||||
:timestamp="detail.createTime"
|
||||
type="primary"
|
||||
>
|
||||
<div class="timeline-content">
|
||||
<div class="timeline-title">创建申请</div>
|
||||
<div class="timeline-desc">申请记录已创建</div>
|
||||
</div>
|
||||
</el-timeline-item>
|
||||
<el-timeline-item
|
||||
v-if="detail.applicationTime && detail.applicationStatus !== 'draft'"
|
||||
:timestamp="detail.applicationTime"
|
||||
type="success"
|
||||
>
|
||||
<div class="timeline-content">
|
||||
<div class="timeline-title">提交申请</div>
|
||||
<div class="timeline-desc">申请已提交,等待审核</div>
|
||||
</div>
|
||||
</el-timeline-item>
|
||||
<el-timeline-item
|
||||
v-if="detail.auditTime"
|
||||
:timestamp="detail.auditTime"
|
||||
:type="detail.auditStatus === 'approved' ? 'success' : 'danger'"
|
||||
>
|
||||
<div class="timeline-content">
|
||||
<div class="timeline-title">
|
||||
{{ detail.auditStatus === 'approved' ? '审核通过' : '审核驳回' }}
|
||||
</div>
|
||||
<div class="timeline-desc">
|
||||
审核人:{{ detail.auditUserName || '系统' }}
|
||||
<span v-if="detail.auditRemark">,备注:{{ detail.auditRemark }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</el-timeline-item>
|
||||
<el-timeline-item
|
||||
v-if="detail.awardTime"
|
||||
:timestamp="detail.awardTime"
|
||||
type="warning"
|
||||
>
|
||||
<div class="timeline-content">
|
||||
<div class="timeline-title">获得奖学金</div>
|
||||
<div class="timeline-desc">恭喜获得奖学金</div>
|
||||
</div>
|
||||
</el-timeline-item>
|
||||
</el-timeline>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup name="ScholarshipApplicationDetail" lang="ts">
|
||||
import { getScholarshipApplication, listScholarshipAttachment } from '@/api/jcbt';
|
||||
import { ScholarshipApplicationVO, ScholarshipAttachmentVO } from '@/api/jcbt/types';
|
||||
|
||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||
const { application_status, audit_status, yes_no } = proxy?.useDict('application_status', 'audit_status', 'yes_no');
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
|
||||
// 数据定义
|
||||
const loading = ref(true);
|
||||
const detail = ref<ScholarshipApplicationVO>({});
|
||||
const attachmentList = ref<ScholarshipAttachmentVO[]>([]);
|
||||
|
||||
// 计算属性
|
||||
const canEdit = computed(() => {
|
||||
// 草稿状态或审核驳回状态可以编辑
|
||||
return detail.value.applicationStatus === 'draft' || detail.value.auditStatus === 'rejected';
|
||||
});
|
||||
|
||||
/** 获取详情数据 */
|
||||
const getDetail = async () => {
|
||||
loading.value = true;
|
||||
try {
|
||||
const id = route.params.id as string;
|
||||
|
||||
// 获取申请详情
|
||||
const detailRes = await getScholarshipApplication(id);
|
||||
detail.value = detailRes.data;
|
||||
|
||||
// 获取附件列表
|
||||
const attachmentRes = await listScholarshipAttachment(id);
|
||||
attachmentList.value = attachmentRes.data;
|
||||
|
||||
} catch (error) {
|
||||
proxy?.$modal.msgError('获取详情失败');
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
/** 编辑操作 */
|
||||
const handleEdit = () => {
|
||||
router.push(`/jcbt/scholarship/application/form/${detail.value.id}`);
|
||||
};
|
||||
|
||||
/** 返回 */
|
||||
const goBack = () => {
|
||||
router.back();
|
||||
};
|
||||
|
||||
/** 格式化文件大小 */
|
||||
const formatFileSize = (size: number): string => {
|
||||
if (!size) return '-';
|
||||
|
||||
const units = ['B', 'KB', 'MB', 'GB'];
|
||||
let index = 0;
|
||||
let fileSize = size;
|
||||
|
||||
while (fileSize >= 1024 && index < units.length - 1) {
|
||||
fileSize /= 1024;
|
||||
index++;
|
||||
}
|
||||
|
||||
return `${fileSize.toFixed(1)} ${units[index]}`;
|
||||
};
|
||||
|
||||
/** 下载附件 */
|
||||
const handleDownload = (row: ScholarshipAttachmentVO) => {
|
||||
// 这里可以实现文件下载逻辑
|
||||
window.open(row.filePath, '_blank');
|
||||
};
|
||||
|
||||
// 组件挂载时获取数据
|
||||
onMounted(() => {
|
||||
getDetail();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* 详情卡片样式 */
|
||||
.detail-card {
|
||||
margin: 20px;
|
||||
}
|
||||
|
||||
.detail-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.detail-title {
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
.header-actions {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.back-button {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 5px;
|
||||
}
|
||||
|
||||
/* 详情分组样式 */
|
||||
.detail-section {
|
||||
margin-bottom: 30px;
|
||||
padding: 20px;
|
||||
background-color: #fafafa;
|
||||
border-radius: 8px;
|
||||
border-left: 4px solid #409eff;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
margin-bottom: 20px;
|
||||
padding-bottom: 10px;
|
||||
border-bottom: 1px solid #e4e7ed;
|
||||
}
|
||||
|
||||
.section-title .el-icon {
|
||||
margin-right: 8px;
|
||||
color: #409eff;
|
||||
}
|
||||
|
||||
/* 内容样式 */
|
||||
.amount-text {
|
||||
color: #f56c6c;
|
||||
font-weight: 600;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.reason-content,
|
||||
.remark-content,
|
||||
.audit-remark {
|
||||
line-height: 1.6;
|
||||
color: #606266;
|
||||
white-space: pre-wrap;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
/* 时间轴样式 */
|
||||
.timeline-content {
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
.timeline-title {
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.timeline-desc {
|
||||
color: #909399;
|
||||
font-size: 14px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
/* 描述列表样式调整 */
|
||||
:deep(.el-descriptions__label) {
|
||||
font-weight: 600;
|
||||
color: #606266;
|
||||
width: 120px;
|
||||
}
|
||||
|
||||
:deep(.el-descriptions__content) {
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
/* 表格样式 */
|
||||
:deep(.el-table th) {
|
||||
background-color: #f8f9fa;
|
||||
color: #333;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
:deep(.el-table td) {
|
||||
padding: 12px 0;
|
||||
}
|
||||
|
||||
/* 响应式调整 */
|
||||
@media (max-width: 768px) {
|
||||
.detail-card {
|
||||
margin: 10px;
|
||||
}
|
||||
|
||||
.detail-header {
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.header-actions {
|
||||
width: 100%;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.detail-section {
|
||||
padding: 15px;
|
||||
}
|
||||
|
||||
:deep(.el-descriptions) {
|
||||
--el-descriptions-table-border: none;
|
||||
}
|
||||
|
||||
:deep(.el-descriptions__label) {
|
||||
width: 80px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,718 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<el-card class="form-card">
|
||||
<template #header>
|
||||
<div class="form-header">
|
||||
<span class="form-title">{{ formTitle }}</span>
|
||||
<el-button @click="goBack" class="back-button">
|
||||
<el-icon><ArrowLeft /></el-icon>
|
||||
返回
|
||||
</el-button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<el-form
|
||||
ref="formRef"
|
||||
:model="form"
|
||||
:rules="rules"
|
||||
label-width="140px"
|
||||
v-loading="formLoading"
|
||||
>
|
||||
<!-- 批次选择 -->
|
||||
<div class="form-section">
|
||||
<div class="section-title">
|
||||
<el-icon><Calendar /></el-icon>
|
||||
批次信息
|
||||
</div>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="申报批次" prop="batchId">
|
||||
<el-select
|
||||
v-model="form.batchId"
|
||||
placeholder="请选择申报批次"
|
||||
style="width: 100%"
|
||||
:disabled="isView"
|
||||
@change="handleBatchChange"
|
||||
>
|
||||
<el-option
|
||||
v-for="batch in batchList"
|
||||
:key="batch.id"
|
||||
:label="batch.batchName"
|
||||
:value="batch.id"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="奖学金类型" prop="scholarshipTypeId">
|
||||
<el-select
|
||||
v-model="form.scholarshipTypeId"
|
||||
placeholder="请选择奖学金类型"
|
||||
style="width: 100%"
|
||||
:disabled="isView || !form.batchId"
|
||||
@change="handleScholarshipTypeChange"
|
||||
>
|
||||
<el-option
|
||||
v-for="type in scholarshipTypes"
|
||||
:key="type.id"
|
||||
:value="type.id"
|
||||
:disabled="type.quotaStatus === 'full'"
|
||||
>
|
||||
<div class="scholarship-type-option">
|
||||
<span
|
||||
:class="[
|
||||
'type-name',
|
||||
type.quotaStatus === 'available' || type.quotaStatus === 'unlimited' ? 'available' : 'full'
|
||||
]"
|
||||
>
|
||||
{{ type.name }}
|
||||
</span>
|
||||
<span class="quota-info" v-if="type.quotaStatus === 'unlimited'">
|
||||
<span class="quota-badge available">
|
||||
无限制
|
||||
</span>
|
||||
</span>
|
||||
<span class="quota-info" v-else>
|
||||
<span
|
||||
:class="[
|
||||
'quota-badge',
|
||||
type.quotaStatus === 'available' ? 'available' : 'full'
|
||||
]"
|
||||
>
|
||||
{{ type.availableQuota || 0 }}/{{ type.totalQuota || 0 }}
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
|
||||
<!-- 班级信息(自动获取) -->
|
||||
<div class="form-section" v-if="classInfo.teacherId">
|
||||
<div class="section-title">
|
||||
<el-icon><School /></el-icon>
|
||||
班级信息
|
||||
</div>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="8">
|
||||
<el-form-item label="学院名称">
|
||||
<el-input v-model="classInfo.deptName" readonly />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="专业名称">
|
||||
<el-input v-model="classInfo.majorName" readonly />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="班级名称">
|
||||
<el-input v-model="classInfo.className" readonly />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="8">
|
||||
<el-form-item label="年级">
|
||||
<el-input v-model="classInfo.grade" readonly />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="班主任">
|
||||
<el-input v-model="classInfo.teacherName" readonly />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
|
||||
<!-- 学生选择 -->
|
||||
<div class="form-section">
|
||||
<div class="section-title">
|
||||
<el-icon><User /></el-icon>
|
||||
学生选择
|
||||
<span v-if="selectedStudents.length > 0" class="selection-count">
|
||||
(已选择 {{ selectedStudents.length }} 人)
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- 学生选择表格 -->
|
||||
<el-table
|
||||
ref="studentsTable"
|
||||
:data="filteredStudents"
|
||||
v-loading="studentsLoading"
|
||||
@selection-change="handleStudentSelectionChange"
|
||||
style="width: 100%; margin-bottom: 20px;"
|
||||
>
|
||||
<el-table-column type="selection" width="55" />
|
||||
<el-table-column prop="studentCode" label="学号" width="120" />
|
||||
<el-table-column prop="studentName" label="姓名" width="100" />
|
||||
<el-table-column prop="gender" label="性别" width="80" />
|
||||
<el-table-column prop="phone" label="联系方式" width="130" />
|
||||
<el-table-column prop="email" label="邮箱" />
|
||||
<el-table-column label="在校状态" width="100">
|
||||
<template #default="scope">
|
||||
<el-tag :type="scope.row.status === '1' ? 'success' : 'danger'">
|
||||
{{ scope.row.status === '1' ? '在校' : '离校' }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<!-- 学生搜索 -->
|
||||
<div class="student-search">
|
||||
<el-input
|
||||
v-model="studentSearchKeyword"
|
||||
placeholder="搜索学生姓名或学号"
|
||||
style="width: 300px;"
|
||||
clearable
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 申请信息 -->
|
||||
<div class="form-section">
|
||||
<div class="section-title">
|
||||
<el-icon><Document /></el-icon>
|
||||
申请信息
|
||||
</div>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="24">
|
||||
<el-form-item label="申请类型" prop="applicationType">
|
||||
<el-select
|
||||
v-model="form.applicationType"
|
||||
placeholder="请选择申请类型"
|
||||
style="width: 300px"
|
||||
:disabled="isView"
|
||||
>
|
||||
<el-option label="教师推荐" value="RECOMMEND" />
|
||||
<el-option label="直接指定" value="DIRECT" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="24">
|
||||
<el-form-item label="申请原因" prop="applicationReason">
|
||||
<el-input
|
||||
v-model="form.applicationReason"
|
||||
type="textarea"
|
||||
:rows="4"
|
||||
placeholder="请输入申请原因"
|
||||
:disabled="isView"
|
||||
maxlength="500"
|
||||
show-word-limit
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="24">
|
||||
<el-form-item label="申请说明" prop="applicationDescription">
|
||||
<el-input
|
||||
v-model="form.applicationDescription"
|
||||
type="textarea"
|
||||
:rows="4"
|
||||
placeholder="请输入申请说明(选填)"
|
||||
:disabled="isView"
|
||||
maxlength="1000"
|
||||
show-word-limit
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
|
||||
<!-- 操作按钮 -->
|
||||
<div class="form-actions" v-if="!isView">
|
||||
<el-button @click="goBack">取消</el-button>
|
||||
<el-button type="primary" @click="submitForm" :loading="submitLoading">
|
||||
{{ form.id ? '更新' : '提交申请' }}
|
||||
</el-button>
|
||||
</div>
|
||||
</el-form>
|
||||
</el-card>
|
||||
|
||||
<!-- 班级选择对话框 -->
|
||||
<el-dialog v-model="showClassSelector" title="选择班级" width="600px" :close-on-click-modal="false">
|
||||
<div class="class-selector">
|
||||
<p class="tip">检测到您是多个班级的班主任,请选择要进行奖学金申请的班级:</p>
|
||||
<el-radio-group v-model="selectedClassId" class="class-options">
|
||||
<el-radio
|
||||
v-for="option in classOptions"
|
||||
:key="option.classId"
|
||||
:value="option.classId"
|
||||
class="class-option"
|
||||
>
|
||||
<div class="class-info">
|
||||
<div class="class-name">{{ option.className }}</div>
|
||||
<div class="class-detail">{{ option.collegeName }} - {{ option.majorName }} - {{ option.grade }}</div>
|
||||
</div>
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
</div>
|
||||
<template #footer>
|
||||
<el-button @click="showClassSelector = false">取消</el-button>
|
||||
<el-button type="primary" @click="confirmClassChoice" :disabled="!selectedClassId">确认选择</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup name="ScholarshipApplicationForm">
|
||||
import { ref, reactive, computed, onMounted } from 'vue';
|
||||
import { useRoute, useRouter } from 'vue-router';
|
||||
import { ElMessage, ElMessageBox } from 'element-plus';
|
||||
import { ArrowLeft, Calendar, School, User, Document } from '@element-plus/icons-vue';
|
||||
import {
|
||||
getScholarshipApplication,
|
||||
addScholarshipApplication,
|
||||
updateScholarshipApplication,
|
||||
getClassInfoByTeacher,
|
||||
getClassStudents,
|
||||
getScholarshipTypesByBatch,
|
||||
getScholarshipTypesWithQuota,
|
||||
batchSubmitByTeacher,
|
||||
confirmClassSelection
|
||||
} from '@/api/jcbt/scholarshipApplication';
|
||||
import { getActiveBatches } from '@/api/jcbt/scholarshipBatch';
|
||||
import { useUserStore } from '@/store/modules/user';
|
||||
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
const userStore = useUserStore();
|
||||
|
||||
// 组件状态
|
||||
const formRef = ref();
|
||||
const studentsTable = ref();
|
||||
const formLoading = ref(false);
|
||||
const studentsLoading = ref(false);
|
||||
const submitLoading = ref(false);
|
||||
|
||||
// 表单数据
|
||||
const form = reactive({
|
||||
id: null,
|
||||
batchId: null,
|
||||
scholarshipTypeId: null,
|
||||
studentIds: [],
|
||||
applicantType: 'TEACHER',
|
||||
applicantId: userStore.userId,
|
||||
applicantName: userStore.nickname,
|
||||
applicationType: 'RECOMMEND',
|
||||
applicationReason: '',
|
||||
applicationDescription: ''
|
||||
});
|
||||
|
||||
// 下拉选项数据
|
||||
const batchList = ref([]);
|
||||
const scholarshipTypes = ref([]);
|
||||
const studentList = ref([]);
|
||||
const selectedStudents = ref([]);
|
||||
const studentSearchKeyword = ref('');
|
||||
|
||||
// 班级信息
|
||||
const classInfo = reactive({
|
||||
teacherId: userStore.userId,
|
||||
teacherName: userStore.nickname,
|
||||
classId: null,
|
||||
className: '',
|
||||
deptId: null,
|
||||
deptName: '',
|
||||
majorName: '',
|
||||
grade: ''
|
||||
});
|
||||
|
||||
// 班级选择对话框状态
|
||||
const showClassSelector = ref(false);
|
||||
const classOptions = ref([]);
|
||||
const selectedClassId = ref('');
|
||||
|
||||
// 计算属性
|
||||
const isView = computed(() => route.query.type === 'view');
|
||||
const formTitle = computed(() => {
|
||||
if (isView.value) return '查看奖学金申请';
|
||||
return form.id ? '编辑奖学金申请' : '新增奖学金申请';
|
||||
});
|
||||
|
||||
const filteredStudents = computed(() => {
|
||||
if (!studentSearchKeyword.value) return studentList.value;
|
||||
const keyword = studentSearchKeyword.value.toLowerCase();
|
||||
return studentList.value.filter(student =>
|
||||
student.studentName.toLowerCase().includes(keyword) ||
|
||||
student.studentCode.toLowerCase().includes(keyword)
|
||||
);
|
||||
});
|
||||
|
||||
// 表单验证规则
|
||||
const rules = {
|
||||
batchId: [{ required: true, message: '请选择申报批次', trigger: 'change' }],
|
||||
scholarshipTypeId: [{ required: true, message: '请选择奖学金类型', trigger: 'change' }],
|
||||
applicationType: [{ required: true, message: '请选择申请类型', trigger: 'change' }],
|
||||
applicationReason: [{ required: true, message: '请输入申请原因', trigger: 'blur' }]
|
||||
};
|
||||
|
||||
// 初始化
|
||||
onMounted(() => {
|
||||
loadBatchList();
|
||||
loadClassInfo();
|
||||
if (route.params.id) {
|
||||
loadScholarshipApplication(route.params.id);
|
||||
}
|
||||
});
|
||||
|
||||
// 加载批次列表
|
||||
const loadBatchList = async () => {
|
||||
try {
|
||||
const response = await getActiveBatches();
|
||||
batchList.value = response.data || [];
|
||||
} catch (error) {
|
||||
console.error('加载批次列表失败:', error);
|
||||
ElMessage.error('加载批次列表失败');
|
||||
}
|
||||
};
|
||||
|
||||
// 加载班级信息
|
||||
const loadClassInfo = async () => {
|
||||
if (!userStore.userId) {
|
||||
ElMessage.error('未获取到用户信息,请重新登录');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const res = await getClassInfoByTeacher(userStore.userId);
|
||||
console.log('API响应:', res);
|
||||
|
||||
if (res && res.data) {
|
||||
if (res.data.needSelection) {
|
||||
// 需要用户选择班级
|
||||
classOptions.value = res.data.classOptions;
|
||||
showClassSelector.value = true;
|
||||
console.log('需要用户选择班级,共', classOptions.value.length, '个选项');
|
||||
} else if (res.data.error) {
|
||||
ElMessage.error(res.data.error);
|
||||
} else {
|
||||
// 直接获取到班级信息
|
||||
Object.assign(classInfo, res.data);
|
||||
console.log('自动获取班级信息成功:', res.data);
|
||||
if (classInfo.classId) {
|
||||
await loadClassStudents(classInfo.classId);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取班级信息失败:', error);
|
||||
ElMessage.error('获取班级信息失败');
|
||||
}
|
||||
};
|
||||
|
||||
// 确认班级选择
|
||||
const confirmClassChoice = async () => {
|
||||
if (!selectedClassId.value) {
|
||||
ElMessage.warning('请选择一个班级');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const res = await confirmClassSelection(userStore.userId, selectedClassId.value);
|
||||
if (res && res.data && !res.data.error) {
|
||||
Object.assign(classInfo, res.data);
|
||||
showClassSelector.value = false;
|
||||
selectedClassId.value = '';
|
||||
ElMessage.success('班级选择成功');
|
||||
|
||||
if (classInfo.classId) {
|
||||
await loadClassStudents(classInfo.classId);
|
||||
}
|
||||
} else {
|
||||
ElMessage.error(res.data?.error || '确认班级选择失败');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('确认班级选择失败:', error);
|
||||
ElMessage.error('确认班级选择失败');
|
||||
}
|
||||
};
|
||||
|
||||
// 加载班级学生列表
|
||||
const loadClassStudents = async (classId) => {
|
||||
studentsLoading.value = true;
|
||||
try {
|
||||
const response = await getClassStudents(classId);
|
||||
studentList.value = response.data || [];
|
||||
} catch (error) {
|
||||
console.error('加载班级学生失败:', error);
|
||||
ElMessage.error('加载班级学生失败');
|
||||
} finally {
|
||||
studentsLoading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
// 批次变更处理
|
||||
const handleBatchChange = async () => {
|
||||
if (!form.batchId) {
|
||||
scholarshipTypes.value = [];
|
||||
form.scholarshipTypeId = null;
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
let response;
|
||||
// 如果有班级信息,使用带名额信息的API
|
||||
if (classInfo.classId) {
|
||||
response = await getScholarshipTypesWithQuota(form.batchId, classInfo.classId);
|
||||
} else {
|
||||
// 否则使用普通API
|
||||
response = await getScholarshipTypesByBatch(form.batchId);
|
||||
}
|
||||
|
||||
const types = response.data || [];
|
||||
|
||||
// 确保每个类型都有必要的字段
|
||||
scholarshipTypes.value = types.map(type => ({
|
||||
...type,
|
||||
hasQuota: type.hasQuota !== undefined ? type.hasQuota : true,
|
||||
totalQuota: type.totalQuota || 0,
|
||||
usedQuota: type.usedQuota || 0,
|
||||
availableQuota: type.availableQuota || 0,
|
||||
quotaStatus: type.quotaStatus || (type.totalQuota > 0 ? (type.availableQuota > 0 ? 'available' : 'full') : 'unlimited')
|
||||
}));
|
||||
|
||||
form.scholarshipTypeId = null;
|
||||
} catch (error) {
|
||||
console.error('加载奖学金类型失败:', error);
|
||||
ElMessage.error('加载奖学金类型失败');
|
||||
}
|
||||
};
|
||||
|
||||
// 奖学金类型变更处理
|
||||
const handleScholarshipTypeChange = () => {
|
||||
// 可以在这里添加额外的逻辑
|
||||
};
|
||||
|
||||
// 学生选择变更处理
|
||||
const handleStudentSelectionChange = (selection) => {
|
||||
selectedStudents.value = selection;
|
||||
form.studentIds = selection.map(student => student.id);
|
||||
};
|
||||
|
||||
// 加载申请详情(编辑模式)
|
||||
const loadScholarshipApplication = async (id) => {
|
||||
formLoading.value = true;
|
||||
try {
|
||||
const response = await getScholarshipApplication(id);
|
||||
const data = response.data;
|
||||
Object.assign(form, data);
|
||||
|
||||
// 如果有批次ID,加载对应的奖学金类型
|
||||
if (data.batchId) {
|
||||
await handleBatchChange();
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('加载申请详情失败:', error);
|
||||
ElMessage.error('加载申请详情失败');
|
||||
} finally {
|
||||
formLoading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
// 提交表单
|
||||
const submitForm = async () => {
|
||||
if (!formRef.value) return;
|
||||
|
||||
try {
|
||||
await formRef.value.validate();
|
||||
|
||||
// 检查是否选择了学生
|
||||
if (!form.studentIds || form.studentIds.length === 0) {
|
||||
ElMessage.error('请至少选择一名学生');
|
||||
return;
|
||||
}
|
||||
|
||||
submitLoading.value = true;
|
||||
|
||||
const submitData = {
|
||||
...form,
|
||||
classId: classInfo.classId,
|
||||
className: classInfo.className,
|
||||
deptId: classInfo.deptId,
|
||||
deptName: classInfo.deptName
|
||||
};
|
||||
|
||||
if (form.id) {
|
||||
await updateScholarshipApplication(submitData);
|
||||
ElMessage.success('更新成功');
|
||||
} else {
|
||||
// 使用班主任批量申请接口
|
||||
await batchSubmitByTeacher({
|
||||
batchId: form.batchId,
|
||||
scholarshipTypeId: form.scholarshipTypeId,
|
||||
classId: classInfo.classId,
|
||||
studentApplications: form.studentIds.map(studentId => ({
|
||||
studentId,
|
||||
applicationType: form.applicationType,
|
||||
applicationReason: form.applicationReason,
|
||||
applicationDescription: form.applicationDescription
|
||||
}))
|
||||
});
|
||||
ElMessage.success('申请提交成功');
|
||||
}
|
||||
|
||||
goBack();
|
||||
} catch (error) {
|
||||
console.error('提交失败:', error);
|
||||
ElMessage.error('提交失败');
|
||||
} finally {
|
||||
submitLoading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
// 返回
|
||||
const goBack = () => {
|
||||
router.back();
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.form-card {
|
||||
margin: 20px;
|
||||
}
|
||||
|
||||
.form-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.form-title {
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.back-button {
|
||||
border: none;
|
||||
background: none;
|
||||
color: #606266;
|
||||
}
|
||||
|
||||
.back-button:hover {
|
||||
color: #409eff;
|
||||
}
|
||||
|
||||
.form-section {
|
||||
margin-bottom: 30px;
|
||||
padding: 20px;
|
||||
background: #f8f9fa;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
margin-bottom: 20px;
|
||||
color: #303133;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.selection-count {
|
||||
font-size: 14px;
|
||||
color: #409eff;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.student-search {
|
||||
margin-top: 10px;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.form-actions {
|
||||
text-align: center;
|
||||
padding: 20px 0;
|
||||
border-top: 1px solid #ebeef5;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.form-actions .el-button {
|
||||
margin: 0 10px;
|
||||
padding: 10px 30px;
|
||||
}
|
||||
|
||||
.class-selector .tip {
|
||||
margin-bottom: 20px;
|
||||
color: #666;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.class-options .class-option {
|
||||
display: block;
|
||||
margin-bottom: 12px;
|
||||
padding: 12px;
|
||||
border: 1px solid #e4e7ed;
|
||||
border-radius: 6px;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
|
||||
.class-options .class-option:hover {
|
||||
border-color: #409eff;
|
||||
background-color: #f0f8ff;
|
||||
}
|
||||
|
||||
.class-info .class-name {
|
||||
font-weight: bold;
|
||||
font-size: 16px;
|
||||
color: #303133;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.class-info .class-detail {
|
||||
font-size: 14px;
|
||||
color: #606266;
|
||||
}
|
||||
|
||||
/* 奖学金类型选择框样式 */
|
||||
.scholarship-type-option {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.type-name {
|
||||
flex: 1;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.type-name.available {
|
||||
color: #67c23a;
|
||||
}
|
||||
|
||||
.type-name.full {
|
||||
color: #f56c6c;
|
||||
}
|
||||
|
||||
.quota-info {
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
.quota-badge {
|
||||
font-size: 12px;
|
||||
padding: 2px 6px;
|
||||
border-radius: 12px;
|
||||
font-weight: bold;
|
||||
min-width: 40px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.quota-badge.available {
|
||||
background-color: #f0f9ff;
|
||||
color: #67c23a;
|
||||
border: 1px solid #b3e19d;
|
||||
}
|
||||
|
||||
.quota-badge.full {
|
||||
background-color: #fef0f0;
|
||||
color: #f56c6c;
|
||||
border: 1px solid #fbc4c4;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,961 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<el-row :gutter="20">
|
||||
<!-- 查询面板 -->
|
||||
<el-col :span="24" class="search-container">
|
||||
<el-form :model="queryParams" ref="queryFormRef" :inline="true" v-show="showSearch" label-width="80px">
|
||||
<el-form-item label="学生姓名" prop="studentName">
|
||||
<el-input
|
||||
v-model="queryParams.studentName"
|
||||
placeholder="请输入学生姓名"
|
||||
clearable
|
||||
@keyup.enter="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="学号" prop="studentCode">
|
||||
<el-input
|
||||
v-model="queryParams.studentCode"
|
||||
placeholder="请输入学号"
|
||||
clearable
|
||||
@keyup.enter="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="申请状态" prop="applicationStatus">
|
||||
<el-select v-model="queryParams.applicationStatus" placeholder="请选择申请状态" clearable>
|
||||
<el-option label="草稿" value="draft" />
|
||||
<el-option label="已提交" value="submitted" />
|
||||
<el-option label="已审核" value="reviewed" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
|
||||
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-col>
|
||||
|
||||
<!-- 工具栏 -->
|
||||
<el-col :span="24">
|
||||
<el-row :gutter="10" class="mb8">
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="primary"
|
||||
plain
|
||||
icon="Plus"
|
||||
@click="handleAdd"
|
||||
v-hasPermi="['jcbt:scholarshipApplication:add']"
|
||||
>班主任批量申请</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="success"
|
||||
plain
|
||||
icon="Edit"
|
||||
:disabled="single"
|
||||
@click="handleUpdate()"
|
||||
v-hasPermi="['jcbt:scholarshipApplication:edit']"
|
||||
>修改</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="danger"
|
||||
plain
|
||||
icon="Delete"
|
||||
:disabled="multiple"
|
||||
@click="handleDelete()"
|
||||
v-hasPermi="['jcbt:scholarshipApplication:remove']"
|
||||
>删除</el-button>
|
||||
</el-col>
|
||||
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
</el-col>
|
||||
|
||||
<!-- 数据表格 -->
|
||||
<el-col :span="24">
|
||||
<el-table v-loading="loading" :data="applicationList" @selection-change="handleSelectionChange">
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column label="学号" align="center" prop="studentCode" min-width="120" />
|
||||
<el-table-column label="学生姓名" align="center" prop="studentName" min-width="100" />
|
||||
<el-table-column label="班级" align="center" prop="className" min-width="120" />
|
||||
<el-table-column label="奖学金类型" align="center" prop="scholarshipType" min-width="120" />
|
||||
<el-table-column label="等级" align="center" prop="scholarshipLevel" min-width="80" />
|
||||
<el-table-column label="金额" align="center" prop="amount" min-width="100">
|
||||
<template #default="scope">
|
||||
<span class="text-primary font-bold">¥{{ scope.row.amount }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="申请状态" align="center" prop="applicationStatus" min-width="100">
|
||||
<template #default="scope">
|
||||
<el-tag v-if="scope.row.applicationStatus === 'draft'" type="info">草稿</el-tag>
|
||||
<el-tag v-else-if="scope.row.applicationStatus === 'submitted'" type="warning">已提交</el-tag>
|
||||
<el-tag v-else-if="scope.row.applicationStatus === 'reviewed'" type="success">已审核</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="审核状态" align="center" prop="auditStatus" min-width="100">
|
||||
<template #default="scope">
|
||||
<el-tag v-if="scope.row.auditStatus === 'pending'" type="warning">待审核</el-tag>
|
||||
<el-tag v-else-if="scope.row.auditStatus === 'approved'" type="success">通过</el-tag>
|
||||
<el-tag v-else-if="scope.row.auditStatus === 'rejected'" type="danger">拒绝</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="申请时间" align="center" prop="applicationTime" min-width="160">
|
||||
<template #default="scope">
|
||||
<span>{{ parseTime(scope.row.applicationTime, '{y}-{m}-{d} {h}:{i}:{s}') }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="160">
|
||||
<template #default="scope">
|
||||
<el-tooltip content="修改" placement="top">
|
||||
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['jcbt:scholarshipApplication:edit']"></el-button>
|
||||
</el-tooltip>
|
||||
<el-tooltip content="删除" placement="top">
|
||||
<el-button link type="danger" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['jcbt:scholarshipApplication:remove']"></el-button>
|
||||
</el-tooltip>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<pagination
|
||||
v-show="total > 0"
|
||||
:total="total"
|
||||
v-model:page="queryParams.pageNum"
|
||||
v-model:limit="queryParams.pageSize"
|
||||
@pagination="getList"
|
||||
/>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<!-- 班主任批量申请奖学金对话框 -->
|
||||
<el-dialog :title="dialog.title" v-model="dialog.visible" width="1000px" append-to-body>
|
||||
<el-form ref="scholarshipApplicationRef" :model="form" :rules="rules" label-width="120px">
|
||||
<!-- 第一步:选择申报批次 -->
|
||||
<el-card class="mb-4">
|
||||
<template #header>
|
||||
<span>第一步:选择申报批次</span>
|
||||
</template>
|
||||
<el-form-item label="申报批次" prop="batchId" required>
|
||||
<el-select
|
||||
v-model="selectedBatch"
|
||||
placeholder="请选择申报批次"
|
||||
@change="handleBatchChange"
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-option
|
||||
v-for="batch in batchList"
|
||||
:key="batch.id"
|
||||
:label="`${batch.batchName} (${batch.academicYear} ${batch.semester}学期)`"
|
||||
:value="batch"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<div v-if="selectedBatch" class="batch-info mt-4 p-4 bg-blue-50 rounded">
|
||||
<div class="text-sm text-gray-600">
|
||||
<p><strong>批次名称:</strong>{{ selectedBatch.batchName }}</p>
|
||||
<p><strong>学年学期:</strong>{{ selectedBatch.academicYear }} {{ selectedBatch.semester }}学期</p>
|
||||
<p><strong>申请时间:</strong>{{ selectedBatch.startTime }} 至 {{ selectedBatch.endTime }}</p>
|
||||
<p><strong>可申请奖学金类型:</strong></p>
|
||||
<div class="mt-2">
|
||||
<el-tag
|
||||
v-for="type in availableScholarshipTypes"
|
||||
:key="type.id"
|
||||
class="mr-2 mb-2"
|
||||
type="success"
|
||||
>
|
||||
{{ type.name }} - {{ type.levelType }} (¥{{ type.amount }})
|
||||
</el-tag>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
|
||||
<!-- 第二步:班级信息显示 -->
|
||||
<el-card class="mb-4" v-if="selectedBatch">
|
||||
<template #header>
|
||||
<span>第二步:班级信息确认</span>
|
||||
</template>
|
||||
<div class="class-info-grid">
|
||||
<div class="info-item">
|
||||
<label>学院:</label>
|
||||
<span>{{ classInfo.collegeName || '未获取' }}</span>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<label>专业:</label>
|
||||
<span>{{ classInfo.majorName || '未获取' }}</span>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<label>班级:</label>
|
||||
<span>{{ classInfo.className || '未获取' }}</span>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<label>年级:</label>
|
||||
<span>{{ classInfo.grade || '未获取' }}</span>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<label>班主任:</label>
|
||||
<span>{{ classInfo.teacherName || '未获取' }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
|
||||
<!-- 第三步:选择申请学生 -->
|
||||
<el-card v-if="selectedBatch && classInfo.classId">
|
||||
<template #header>
|
||||
<div class="flex justify-between items-center">
|
||||
<span>第三步:选择申请学生</span>
|
||||
<div class="flex items-center space-x-4">
|
||||
<el-input
|
||||
v-model="studentKeyword"
|
||||
placeholder="搜索学生姓名或学号"
|
||||
@input="filterStudents"
|
||||
style="width: 200px"
|
||||
clearable
|
||||
>
|
||||
<template #prefix>
|
||||
<el-icon><Search /></el-icon>
|
||||
</template>
|
||||
</el-input>
|
||||
<div class="text-sm text-gray-600">
|
||||
已选择:{{ selectedStudents.length }} 人
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<div class="mb-4 flex gap-2">
|
||||
<el-button size="small" @click="selectAllStudents">全选</el-button>
|
||||
<el-button size="small" @click="clearSelectedStudents">清空</el-button>
|
||||
</div>
|
||||
|
||||
<div class="student-selection-container max-h-96 overflow-y-auto">
|
||||
<div
|
||||
v-for="student in filteredStudents"
|
||||
:key="student.id"
|
||||
class="student-card p-4 border rounded mb-3"
|
||||
:class="{ 'border-blue-500 bg-blue-50': isStudentSelected(student.id) }"
|
||||
>
|
||||
<div class="flex items-start space-x-4">
|
||||
<el-checkbox
|
||||
:model-value="isStudentSelected(student.id)"
|
||||
@change="toggleStudentSelection(student, $event)"
|
||||
/>
|
||||
<div class="flex-1">
|
||||
<div class="student-basic-info flex items-center space-x-4 mb-2">
|
||||
<span class="font-bold">{{ student.studentName }}</span>
|
||||
<span class="text-gray-600">{{ student.studentCode }}</span>
|
||||
<span class="text-gray-500">{{ student.gender }}</span>
|
||||
<span class="text-gray-500">{{ student.phone }}</span>
|
||||
</div>
|
||||
|
||||
<div v-if="isStudentSelected(student.id)" class="scholarship-selection mt-3 p-3 bg-gray-50 rounded">
|
||||
<div class="grid grid-cols-3 gap-4">
|
||||
<div>
|
||||
<label class="block text-sm font-medium mb-1">奖学金类型</label>
|
||||
<el-select
|
||||
v-model="student.selectedScholarshipType"
|
||||
placeholder="选择奖学金类型"
|
||||
@change="updateScholarshipInfo(student)"
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-option
|
||||
v-for="type in availableScholarshipTypes"
|
||||
:key="type.id"
|
||||
:label="`${type.name} (¥${type.amount})`"
|
||||
:value="type"
|
||||
/>
|
||||
</el-select>
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-sm font-medium mb-1">等级</label>
|
||||
<el-input
|
||||
v-model="student.selectedLevel"
|
||||
:value="student.selectedScholarshipType?.levelType || ''"
|
||||
readonly
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-sm font-medium mb-1">金额(元)</label>
|
||||
<el-input
|
||||
v-model="student.selectedAmount"
|
||||
:value="student.selectedScholarshipType?.amount || ''"
|
||||
readonly
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="filteredStudents.length === 0" class="text-center text-gray-500 py-8">
|
||||
暂无学生信息,请检查班级设置
|
||||
</div>
|
||||
</el-card>
|
||||
</el-form>
|
||||
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button @click="dialog.visible = false">取 消</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="submitBatchApplication"
|
||||
:disabled="selectedStudents.length === 0"
|
||||
:loading="submitLoading"
|
||||
>
|
||||
提交申请 ({{ selectedStudents.length }}人)
|
||||
</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup name="ScholarshipApplication" lang="ts">
|
||||
import { ref, reactive, computed, getCurrentInstance, ComponentInternalInstance, onMounted, nextTick } from 'vue';
|
||||
import type { FormInstance, DateModelType } from 'element-plus';
|
||||
import { Search, Plus, Edit, Delete, Refresh } from '@element-plus/icons-vue';
|
||||
|
||||
// 导入API函数和类型
|
||||
import {
|
||||
listScholarshipApplication,
|
||||
getScholarshipApplication,
|
||||
delScholarshipApplication,
|
||||
addScholarshipApplication,
|
||||
updateScholarshipApplication,
|
||||
exportScholarshipApplication,
|
||||
getClassInfoByTeacher,
|
||||
getClassStudents,
|
||||
getScholarshipTypesByBatch,
|
||||
batchSubmitByTeacher
|
||||
} from '@/api/jcbt/scholarshipApplication';
|
||||
|
||||
import {
|
||||
listScholarshipBatch,
|
||||
getScholarshipBatchByStatus
|
||||
} from '@/api/jcbt/scholarshipBatch';
|
||||
|
||||
// 导入通用类型
|
||||
import type { PageQuery } from '@/utils/ruoyi';
|
||||
|
||||
// 导入用户状态管理
|
||||
import { useUserStore } from '@/store/modules/user';
|
||||
|
||||
// 本地类型定义
|
||||
interface ScholarshipApplicationVO {
|
||||
id?: number | string;
|
||||
batchId?: number | string;
|
||||
studentId?: string;
|
||||
studentName?: string;
|
||||
studentCode?: string;
|
||||
classId?: number | string;
|
||||
scholarshipTypeId?: number | string;
|
||||
scholarshipLevel?: string;
|
||||
amount?: number;
|
||||
applicationStatus?: string;
|
||||
auditStatus?: string;
|
||||
applicationTime?: string;
|
||||
createTime?: string;
|
||||
}
|
||||
|
||||
interface QueryParams {
|
||||
pageNum: number;
|
||||
pageSize: number;
|
||||
studentName?: string;
|
||||
studentCode?: string;
|
||||
status?: string;
|
||||
}
|
||||
|
||||
interface BatchQuery {
|
||||
pageNum?: number;
|
||||
pageSize?: number;
|
||||
status?: string;
|
||||
}
|
||||
|
||||
interface ScholarshipBatchVO {
|
||||
id?: number | string;
|
||||
batchName?: string;
|
||||
academicYear?: string;
|
||||
semester?: string;
|
||||
startTime?: string;
|
||||
endTime?: string;
|
||||
status?: string;
|
||||
createTime?: string;
|
||||
}
|
||||
|
||||
interface ScholarshipBatchQuery {
|
||||
pageNum?: number;
|
||||
pageSize?: number;
|
||||
status?: string;
|
||||
}
|
||||
|
||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||
|
||||
// 用户状态管理
|
||||
const userStore = useUserStore();
|
||||
|
||||
// 基础数据定义
|
||||
const applicationList = ref<ScholarshipApplicationVO[]>([]);
|
||||
const total = ref(0);
|
||||
const loading = ref(true);
|
||||
const showSearch = ref(true);
|
||||
const ids = ref<Array<string | number>>([]);
|
||||
const single = ref(true);
|
||||
const multiple = ref(true);
|
||||
|
||||
// 查询参数
|
||||
const queryParams = ref<QueryParams>({
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
studentName: '',
|
||||
studentCode: '',
|
||||
status: ''
|
||||
});
|
||||
|
||||
// 表单相关
|
||||
const queryFormRef = ref<FormInstance>();
|
||||
const scholarshipApplicationRef = ref<FormInstance>();
|
||||
|
||||
// 弹出层标题和状态
|
||||
const title = ref('');
|
||||
const open = ref(false);
|
||||
const formLoading = ref(false);
|
||||
const submitLoading = ref(false);
|
||||
|
||||
// 班主任批量申请对话框状态
|
||||
const dialog = ref({
|
||||
title: '',
|
||||
visible: false
|
||||
});
|
||||
|
||||
// 弹出框表单需要的数据
|
||||
const batchList = ref<ScholarshipBatchVO[]>([]);
|
||||
const batchOptions = ref([]);
|
||||
const scholarshipTypes = ref([]);
|
||||
const availableScholarshipTypes = ref<any[]>([]);
|
||||
const classInfo = ref({
|
||||
teacherId: '',
|
||||
collegeName: '',
|
||||
majorName: '',
|
||||
className: '',
|
||||
grade: '',
|
||||
teacherName: '',
|
||||
classId: '',
|
||||
deptId: ''
|
||||
});
|
||||
|
||||
// 学生相关数据
|
||||
const classStudents = ref<any[]>([]);
|
||||
const filteredStudents = ref<any[]>([]);
|
||||
const selectedStudents = ref<any[]>([]);
|
||||
const studentKeyword = ref('');
|
||||
|
||||
// 表单数据
|
||||
const form = ref<any>({
|
||||
batchId: undefined,
|
||||
scholarshipTypeId: undefined,
|
||||
applicationType: 'batch',
|
||||
studentIds: []
|
||||
});
|
||||
|
||||
// 选择的批次
|
||||
const selectedBatch = ref<ScholarshipBatchVO | null>(null);
|
||||
|
||||
// 表单验证规则
|
||||
const rules = reactive({
|
||||
batchId: [{ required: true, message: '申报批次不能为空', trigger: 'change' }]
|
||||
});
|
||||
|
||||
/** 查询奖学金申请列表 */
|
||||
const getList = async () => {
|
||||
loading.value = true;
|
||||
try {
|
||||
const res: any = await listScholarshipApplication(queryParams.value);
|
||||
// 处理响应数据结构
|
||||
if (res.data) {
|
||||
applicationList.value = res.data.rows || res.data.list || res.data || [];
|
||||
total.value = res.data.total || 0;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取列表失败:', error);
|
||||
applicationList.value = [];
|
||||
total.value = 0;
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
/** 搜索按钮操作 */
|
||||
const handleQuery = () => {
|
||||
queryParams.value.pageNum = 1;
|
||||
getList();
|
||||
};
|
||||
|
||||
/** 重置按钮操作 */
|
||||
const resetQuery = () => {
|
||||
queryFormRef.value?.resetFields();
|
||||
handleQuery();
|
||||
};
|
||||
|
||||
/** 重置批量申请表单 */
|
||||
const resetBatchForm = () => {
|
||||
// 重置选择的批次
|
||||
selectedBatch.value = null;
|
||||
availableScholarshipTypes.value = [];
|
||||
|
||||
// 重置班级信息
|
||||
classInfo.value = {
|
||||
teacherId: '',
|
||||
collegeName: '',
|
||||
majorName: '',
|
||||
className: '',
|
||||
grade: '',
|
||||
teacherName: '',
|
||||
classId: '',
|
||||
deptId: ''
|
||||
};
|
||||
|
||||
// 重置学生相关数据
|
||||
classStudents.value = [];
|
||||
filteredStudents.value = [];
|
||||
selectedStudents.value = [];
|
||||
studentKeyword.value = '';
|
||||
|
||||
// 重置表单数据
|
||||
form.value = {
|
||||
batchId: undefined,
|
||||
scholarshipTypeId: undefined,
|
||||
applicationType: 'batch',
|
||||
studentIds: []
|
||||
};
|
||||
|
||||
// 重置表单验证
|
||||
scholarshipApplicationRef.value?.resetFields();
|
||||
};
|
||||
|
||||
/** 多选框选中数据 */
|
||||
const handleSelectionChange = (selection: ScholarshipApplicationVO[]) => {
|
||||
ids.value = selection.map(item => item.id);
|
||||
single.value = selection.length !== 1;
|
||||
multiple.value = !selection.length;
|
||||
};
|
||||
|
||||
/** 新增按钮操作 - 班主任批量申请 */
|
||||
const handleAdd = async () => {
|
||||
resetBatchForm();
|
||||
dialog.value.visible = true;
|
||||
dialog.value.title = "班主任批量申请奖学金";
|
||||
|
||||
// 获取批次列表
|
||||
await getBatchList();
|
||||
|
||||
// 获取班主任班级信息
|
||||
await getTeacherClassInfo();
|
||||
};
|
||||
|
||||
/** 修改按钮操作 */
|
||||
const handleUpdate = async (row?: ScholarshipApplicationVO) => {
|
||||
console.log('修改功能暂未实现', row);
|
||||
};
|
||||
|
||||
/** 删除按钮操作 */
|
||||
const handleDelete = async (row?: ScholarshipApplicationVO) => {
|
||||
console.log('删除功能暂未实现', row);
|
||||
};
|
||||
|
||||
/** 获取批次列表 */
|
||||
const getBatchList = async () => {
|
||||
try {
|
||||
console.log('正在获取批次列表...');
|
||||
// 使用专门的按状态查询方法
|
||||
const res: any = await getScholarshipBatchByStatus('ACTIVE');
|
||||
batchList.value = res.data || [];
|
||||
console.log('成功获取批次列表:', batchList.value);
|
||||
} catch (error) {
|
||||
console.error('获取批次列表失败:', error);
|
||||
batchList.value = [];
|
||||
}
|
||||
};
|
||||
|
||||
/** 获取班主任班级信息 */
|
||||
const getTeacherClassInfo = async () => {
|
||||
try {
|
||||
console.log('开始获取班级信息...');
|
||||
|
||||
// 检查用户是否已登录并有用户ID
|
||||
if (!userStore.userId) {
|
||||
console.log('用户未登录,尝试获取用户信息...');
|
||||
try {
|
||||
await userStore.getInfo();
|
||||
} catch (userError) {
|
||||
console.warn('获取用户信息失败:', userError);
|
||||
}
|
||||
}
|
||||
|
||||
// 如果仍然没有用户ID,使用默认数据
|
||||
if (!userStore.userId) {
|
||||
console.warn('无法获取当前用户ID,使用默认班级信息');
|
||||
setDefaultClassInfo();
|
||||
await getStudentList();
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('当前用户ID:', userStore.userId);
|
||||
|
||||
// 尝试调用API获取班级信息
|
||||
try {
|
||||
const res: any = await getClassInfoByTeacher(userStore.userId);
|
||||
console.log('API响应:', res);
|
||||
|
||||
if (res && res.data) {
|
||||
classInfo.value = res.data;
|
||||
console.log('获取班级信息成功:', res.data);
|
||||
|
||||
// 如果有班级信息,获取学生列表
|
||||
if (classInfo.value.classId) {
|
||||
await getStudentList();
|
||||
}
|
||||
} else {
|
||||
console.log('API返回的数据为空');
|
||||
setDefaultClassInfo();
|
||||
await getStudentList();
|
||||
}
|
||||
} catch (apiError) {
|
||||
console.warn('API调用失败,可能是后端接口未实现:', apiError);
|
||||
setDefaultClassInfo();
|
||||
await getStudentList();
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取班级信息过程中发生未知错误:', error);
|
||||
// 确保即使出错也能显示基本信息
|
||||
setDefaultClassInfo();
|
||||
await getStudentList();
|
||||
}
|
||||
};
|
||||
|
||||
/** 设置默认的班级信息 */
|
||||
const setDefaultClassInfo = () => {
|
||||
classInfo.value = {
|
||||
teacherId: userStore.userId || '',
|
||||
collegeName: '',
|
||||
majorName: '',
|
||||
className: '',
|
||||
grade: '',
|
||||
teacherName: userStore.nickname || '',
|
||||
classId: '',
|
||||
deptId: ''
|
||||
};
|
||||
console.log('已设置默认班级信息:', classInfo.value);
|
||||
};
|
||||
|
||||
/** 获取班级学生列表 */
|
||||
const getStudentList = async () => {
|
||||
try {
|
||||
console.log('🔍 开始获取学生列表,班级ID:', classInfo.value.classId);
|
||||
|
||||
if (!classInfo.value.classId) {
|
||||
console.warn('⚠️ 班级ID为空');
|
||||
setDefaultStudents();
|
||||
return;
|
||||
}
|
||||
|
||||
// 尝试调用API获取学生列表
|
||||
try {
|
||||
const res: any = await getClassStudents(classInfo.value.classId);
|
||||
console.log('📡 获取学生列表API响应:', res);
|
||||
|
||||
if (res && res.data && Array.isArray(res.data) && res.data.length > 0) {
|
||||
classStudents.value = res.data;
|
||||
filteredStudents.value = res.data;
|
||||
console.log('✅ 获取学生列表成功,学生数量:', res.data.length);
|
||||
console.log('📋 学生数据结构示例:', res.data[0]);
|
||||
console.log('🔑 学生ID字段:', res.data[0]?.id);
|
||||
console.log('📝 学生姓名字段:', res.data[0]?.studentName);
|
||||
} else {
|
||||
console.log('📭 API返回学生数据为空');
|
||||
setDefaultStudents();
|
||||
}
|
||||
} catch (apiError) {
|
||||
console.warn('❌ 获取学生列表API调用失败,可能是后端接口未实现:', apiError);
|
||||
setDefaultStudents();
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('💥 获取学生列表过程中发生未知错误:', error);
|
||||
// 确保即使出错也能显示基本学生信息
|
||||
setDefaultStudents();
|
||||
}
|
||||
};
|
||||
|
||||
/** 设置默认的学生数据 */
|
||||
const setDefaultStudents = () => {
|
||||
classStudents.value = [];
|
||||
filteredStudents.value = [];
|
||||
console.log('学生数据为空');
|
||||
};
|
||||
|
||||
/** 批次变更处理 */
|
||||
const handleBatchChange = async (batch: ScholarshipBatchVO) => {
|
||||
if (batch) {
|
||||
form.value.batchId = batch.id;
|
||||
|
||||
// 获取该批次可申请的奖学金类型
|
||||
try {
|
||||
const res: any = await getScholarshipTypesByBatch(batch.id);
|
||||
availableScholarshipTypes.value = res.data || [];
|
||||
} catch (error) {
|
||||
console.error('获取奖学金类型失败:', error);
|
||||
availableScholarshipTypes.value = [];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/** 筛选学生 */
|
||||
const filterStudents = () => {
|
||||
if (!studentKeyword.value) {
|
||||
filteredStudents.value = classStudents.value;
|
||||
} else {
|
||||
filteredStudents.value = classStudents.value.filter((student: any) =>
|
||||
student.studentName?.includes(studentKeyword.value) ||
|
||||
student.studentCode?.includes(studentKeyword.value)
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
/** 检查学生是否已选择 */
|
||||
const isStudentSelected = (studentId: string | number) => {
|
||||
return selectedStudents.value.some((s: any) => s.id === studentId);
|
||||
};
|
||||
|
||||
/** 切换学生选择状态 */
|
||||
const toggleStudentSelection = (student: any, checked: boolean) => {
|
||||
console.log('🔄 切换学生选择状态:', { student, checked });
|
||||
|
||||
if (checked) {
|
||||
selectedStudents.value.push({
|
||||
...student,
|
||||
selectedScholarshipType: null,
|
||||
selectedLevel: '',
|
||||
selectedAmount: ''
|
||||
});
|
||||
console.log('✅ 添加学生到选择列表:', student.studentName);
|
||||
} else {
|
||||
const index = selectedStudents.value.findIndex((s: any) => s.id === student.id);
|
||||
if (index > -1) {
|
||||
selectedStudents.value.splice(index, 1);
|
||||
console.log('❌ 从选择列表移除学生:', student.studentName);
|
||||
}
|
||||
}
|
||||
|
||||
console.log('📊 当前选择的学生数量:', selectedStudents.value.length);
|
||||
};
|
||||
|
||||
/** 全选学生 */
|
||||
const selectAllStudents = () => {
|
||||
console.log('🎯 执行全选操作,当前学生数量:', filteredStudents.value.length);
|
||||
|
||||
filteredStudents.value.forEach((student: any) => {
|
||||
if (!isStudentSelected(student.id)) {
|
||||
selectedStudents.value.push({
|
||||
...student,
|
||||
selectedScholarshipType: null,
|
||||
selectedLevel: '',
|
||||
selectedAmount: ''
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
console.log('✅ 全选完成,已选择学生数量:', selectedStudents.value.length);
|
||||
};
|
||||
|
||||
/** 清空选择的学生 */
|
||||
const clearSelectedStudents = () => {
|
||||
console.log('🧹 清空所有选择的学生');
|
||||
selectedStudents.value = [];
|
||||
};
|
||||
|
||||
/** 更新奖学金信息 */
|
||||
const updateScholarshipInfo = (student: any) => {
|
||||
if (student.selectedScholarshipType) {
|
||||
student.selectedLevel = student.selectedScholarshipType.level;
|
||||
student.selectedAmount = student.selectedScholarshipType.amount;
|
||||
}
|
||||
};
|
||||
|
||||
/** 提交批量申请 */
|
||||
const submitBatchApplication = async () => {
|
||||
try {
|
||||
// 表单验证
|
||||
await scholarshipApplicationRef.value?.validate();
|
||||
|
||||
if (selectedStudents.value.length === 0) {
|
||||
console.error('请至少选择一名学生');
|
||||
return;
|
||||
}
|
||||
|
||||
// 检查每个学生是否都选择了奖学金类型
|
||||
const invalidStudents = selectedStudents.value.filter((s: any) => !s.selectedScholarshipType);
|
||||
if (invalidStudents.length > 0) {
|
||||
console.error('请为所有选择的学生指定奖学金类型');
|
||||
return;
|
||||
}
|
||||
|
||||
submitLoading.value = true;
|
||||
|
||||
// 检查是否所有学生都选择了相同的奖学金类型(根据后端接口要求)
|
||||
const scholarshipTypeId = selectedStudents.value[0].selectedScholarshipType.id;
|
||||
const allSameType = selectedStudents.value.every(s => s.selectedScholarshipType.id === scholarshipTypeId);
|
||||
|
||||
if (!allSameType) {
|
||||
console.error('批量申请要求所有学生选择相同的奖学金类型');
|
||||
return;
|
||||
}
|
||||
|
||||
// 构造符合后端API的提交数据
|
||||
const batchId = form.value.batchId;
|
||||
const classId = classInfo.value.classId;
|
||||
const studentApplications = selectedStudents.value.map((s: any) => ({
|
||||
studentId: s.studentId,
|
||||
studentName: s.studentName,
|
||||
studentCode: s.studentCode,
|
||||
scholarshipTypeId: s.selectedScholarshipType.id,
|
||||
applicationReason: `班主任批量申请 - ${s.selectedScholarshipType.name}`,
|
||||
applicationDescription: `申请等级:${s.selectedScholarshipType.levelType},金额:${s.selectedScholarshipType.amount}元`
|
||||
}));
|
||||
|
||||
// 调用批量提交API
|
||||
await batchSubmitByTeacher(batchId, scholarshipTypeId, classId, studentApplications);
|
||||
|
||||
console.log('批量申请提交成功');
|
||||
dialog.value.visible = false;
|
||||
|
||||
// 刷新列表
|
||||
await getList();
|
||||
|
||||
} catch (error) {
|
||||
console.error('提交失败:', error);
|
||||
} finally {
|
||||
submitLoading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
// 页面加载时获取数据
|
||||
onMounted(() => {
|
||||
getList();
|
||||
getTeacherClassInfo(); // 获取班级信息
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.search-container {
|
||||
background: #fff;
|
||||
padding: 20px;
|
||||
margin-bottom: 10px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.class-info-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
||||
gap: 16px;
|
||||
margin-top: 12px;
|
||||
}
|
||||
|
||||
.info-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.info-item label {
|
||||
font-weight: 500;
|
||||
color: #606266;
|
||||
margin-right: 8px;
|
||||
min-width: 60px;
|
||||
}
|
||||
|
||||
.student-card {
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.student-card:hover {
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.student-basic-info {
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
padding-bottom: 8px;
|
||||
}
|
||||
|
||||
.text-primary {
|
||||
color: #409eff;
|
||||
}
|
||||
|
||||
.font-bold {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.batch-info {
|
||||
background-color: #f0f9ff;
|
||||
border: 1px solid #bfdbfe;
|
||||
}
|
||||
|
||||
.mb-4 {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.mt-4 {
|
||||
margin-top: 1rem;
|
||||
}
|
||||
|
||||
.p-4 {
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.rounded {
|
||||
border-radius: 0.375rem;
|
||||
}
|
||||
|
||||
.max-h-96 {
|
||||
max-height: 24rem;
|
||||
}
|
||||
|
||||
.overflow-y-auto {
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.flex {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.items-center {
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.justify-between {
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.space-x-4 > * + * {
|
||||
margin-left: 1rem;
|
||||
}
|
||||
|
||||
.gap-2 > * + * {
|
||||
margin-left: 0.5rem;
|
||||
}
|
||||
|
||||
.grid-cols-3 {
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
}
|
||||
|
||||
.gap-4 {
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.text-center {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.py-8 {
|
||||
padding-top: 2rem;
|
||||
padding-bottom: 2rem;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,983 @@
|
||||
<template>
|
||||
<div class="p-2 page-container">
|
||||
<!-- 搜索区域 -->
|
||||
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
|
||||
<div v-show="showSearch" class="mb-[10px]">
|
||||
<el-card shadow="hover">
|
||||
<el-form ref="queryFormRef" :model="queryParams" label-width="100px">
|
||||
<!-- 第一行:4个搜索条件 -->
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="6">
|
||||
<el-form-item label="批次名称" prop="batchName">
|
||||
<el-input v-model="queryParams.batchName" placeholder="请输入批次名称" clearable @keyup.enter="handleQuery" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item label="批次编码" prop="batchCode">
|
||||
<el-input v-model="queryParams.batchCode" placeholder="请输入批次编码" clearable @keyup.enter="handleQuery" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item label="学年" prop="academicYear">
|
||||
<el-select v-model="queryParams.academicYear" placeholder="请选择学年" clearable style="width: 100%">
|
||||
<el-option label="2028-2029" value="2028-2029" />
|
||||
<el-option label="2027-2028" value="2027-2028" />
|
||||
<el-option label="2026-2027" value="2026-2027" />
|
||||
<el-option label="2025-2026" value="2025-2026" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item label="学期" prop="semester">
|
||||
<el-select v-model="queryParams.semester" placeholder="请选择学期" clearable style="width: 100%">
|
||||
<el-option label="第一学期" :value="1" />
|
||||
<el-option label="第二学期" :value="2" />
|
||||
<el-option label="全年" :value="3" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<!-- 第二行:3个搜索条件 + 操作按钮 -->
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="6">
|
||||
<el-form-item label="批次类型" prop="batchType">
|
||||
<el-select v-model="queryParams.batchType" placeholder="请选择批次类型" clearable style="width: 100%">
|
||||
<el-option label="常规批次" value="REGULAR" />
|
||||
<el-option label="专项批次" value="SPECIAL" />
|
||||
<el-option label="补充批次" value="SUPPLEMENTARY" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item label="状态" prop="status">
|
||||
<el-select v-model="queryParams.status" placeholder="请选择状态" clearable style="width: 100%">
|
||||
<el-option label="草稿" value="DRAFT" />
|
||||
<el-option label="进行中" value="ACTIVE" />
|
||||
<el-option label="已完成" value="COMPLETED" />
|
||||
<el-option label="已取消" value="CANCELLED" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item label="创建时间">
|
||||
<el-date-picker
|
||||
v-model="daterangeCreateTime"
|
||||
value-format="YYYY-MM-DD"
|
||||
type="daterange"
|
||||
range-separator="-"
|
||||
start-placeholder="开始日期"
|
||||
end-placeholder="结束日期"
|
||||
@change="handleQuery"
|
||||
style="width: 100%"
|
||||
></el-date-picker>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
|
||||
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
</el-card>
|
||||
</div>
|
||||
</transition>
|
||||
|
||||
<!-- 统计卡片区域 -->
|
||||
<div class="mb-[10px]">
|
||||
<el-row :gutter="16" class="stats-row">
|
||||
<el-col :span="6">
|
||||
<el-card shadow="hover" class="stat-card stat-card-primary">
|
||||
<div class="stat-content">
|
||||
<div class="stat-icon">
|
||||
<el-icon><Calendar /></el-icon>
|
||||
</div>
|
||||
<div class="stat-info">
|
||||
<div class="stat-value">{{ statistics.totalBatches }}</div>
|
||||
<div class="stat-label">批次总数</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-card shadow="hover" class="stat-card stat-card-success">
|
||||
<div class="stat-content">
|
||||
<div class="stat-icon">
|
||||
<el-icon><CircleCheck /></el-icon>
|
||||
</div>
|
||||
<div class="stat-info">
|
||||
<div class="stat-value">{{ statistics.activeBatches }}</div>
|
||||
<div class="stat-label">进行中批次</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-card shadow="hover" class="stat-card stat-card-warning">
|
||||
<div class="stat-content">
|
||||
<div class="stat-icon">
|
||||
<el-icon><Clock /></el-icon>
|
||||
</div>
|
||||
<div class="stat-info">
|
||||
<div class="stat-value">{{ statistics.draftBatches }}</div>
|
||||
<div class="stat-label">草稿批次</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-card shadow="hover" class="stat-card stat-card-info">
|
||||
<div class="stat-content">
|
||||
<div class="stat-icon">
|
||||
<el-icon><Finished /></el-icon>
|
||||
</div>
|
||||
<div class="stat-info">
|
||||
<div class="stat-value">{{ statistics.completedBatches }}</div>
|
||||
<div class="stat-label">已完成批次</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
|
||||
<!-- 表格区域 -->
|
||||
<el-card shadow="never" class="button-card table-card">
|
||||
<template #header>
|
||||
<el-row :gutter="10" class="mb8">
|
||||
<el-col :span="1.5">
|
||||
<el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['jcbt:scholarshipBatch:add']">新增</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button icon="Edit" :disabled="single" @click="handleUpdate()" v-hasPermi="['jcbt:scholarshipBatch:edit']">修改</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button icon="Delete" :disabled="multiple" @click="handleDelete()" v-hasPermi="['jcbt:scholarshipBatch:remove']">删除</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button icon="Download" @click="handleExport" v-hasPermi="['jcbt:scholarshipBatch:export']">导出</el-button>
|
||||
</el-col>
|
||||
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
</template>
|
||||
|
||||
<el-table v-loading="loading" border :data="batchList" @selection-change="handleSelectionChange" @row-dblclick="handleView">
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column label="批次编码" align="center" prop="batchCode" min-width="120" />
|
||||
<el-table-column label="批次名称" align="center" prop="batchName" min-width="150" show-overflow-tooltip />
|
||||
<el-table-column label="学年" align="center" prop="academicYear" width="120" />
|
||||
<el-table-column label="学期" align="center" prop="semester" width="80">
|
||||
<template #default="scope">
|
||||
<span v-if="scope.row.semester === 1">第一学期</span>
|
||||
<span v-else-if="scope.row.semester === 2">第二学期</span>
|
||||
<span v-else-if="scope.row.semester === 3">全年</span>
|
||||
<span v-else>-</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="批次类型" align="center" prop="batchType" width="100">
|
||||
<template #default="scope">
|
||||
<el-tag v-if="scope.row.batchType === 'REGULAR'" type="primary">常规批次</el-tag>
|
||||
<el-tag v-else-if="scope.row.batchType === 'SPECIAL'" type="warning">专项批次</el-tag>
|
||||
<el-tag v-else-if="scope.row.batchType === 'SUPPLEMENTARY'" type="info">补充批次</el-tag>
|
||||
<el-tag v-else type="info">未知</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="状态" align="center" prop="status" width="100">
|
||||
<template #default="scope">
|
||||
<el-tag v-if="scope.row.status === 'DRAFT'" type="info">草稿</el-tag>
|
||||
<el-tag v-else-if="scope.row.status === 'ACTIVE'" type="success">进行中</el-tag>
|
||||
<el-tag v-else-if="scope.row.status === 'COMPLETED'" type="primary">已完成</el-tag>
|
||||
<el-tag v-else-if="scope.row.status === 'CANCELLED'" type="danger">已取消</el-tag>
|
||||
<el-tag v-else type="info">未知</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="申请时间" align="center" width="200">
|
||||
<template #default="scope">
|
||||
<div v-if="scope.row.applyStartTime && scope.row.applyEndTime">
|
||||
<div>{{ parseTime(scope.row.applyStartTime, '{y}-{m}-{d}') }}</div>
|
||||
<div style="color: #909399; font-size: 12px;">至 {{ parseTime(scope.row.applyEndTime, '{y}-{m}-{d}') }}</div>
|
||||
</div>
|
||||
<span v-else>-</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="审核时间" align="center" width="200">
|
||||
<template #default="scope">
|
||||
<div v-if="scope.row.reviewStartTime && scope.row.reviewEndTime">
|
||||
<div>{{ parseTime(scope.row.reviewStartTime, '{y}-{m}-{d}') }}</div>
|
||||
<div style="color: #909399; font-size: 12px;">至 {{ parseTime(scope.row.reviewEndTime, '{y}-{m}-{d}') }}</div>
|
||||
</div>
|
||||
<span v-else>-</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
|
||||
<template #default="scope">
|
||||
<span>{{ parseTime(scope.row.createTime, '{y}-{m}-{d} {h}:{i}:{s}') }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="280">
|
||||
<template #default="scope">
|
||||
<el-tooltip content="查看" placement="top">
|
||||
<el-button
|
||||
link
|
||||
type="primary"
|
||||
icon="View"
|
||||
size="default"
|
||||
style="font-size: 16px; margin-right: 8px; color: blue"
|
||||
@click="handleView(scope.row)"
|
||||
v-hasPermi="['jcbt:scholarshipBatch:query']"
|
||||
></el-button>
|
||||
</el-tooltip>
|
||||
<el-tooltip content="修改" placement="top">
|
||||
<el-button
|
||||
link
|
||||
type="primary"
|
||||
icon="Edit"
|
||||
size="default"
|
||||
style="font-size: 16px; margin-right: 8px"
|
||||
@click="handleUpdate(scope.row)"
|
||||
v-hasPermi="['jcbt:scholarshipBatch:edit']"
|
||||
></el-button>
|
||||
</el-tooltip>
|
||||
<el-tooltip content="状态变更" placement="top">
|
||||
<el-button
|
||||
link
|
||||
type="warning"
|
||||
icon="Switch"
|
||||
size="default"
|
||||
style="font-size: 16px; margin-right: 8px"
|
||||
@click="handleStatusChange(scope.row)"
|
||||
v-hasPermi="['jcbt:scholarshipBatch:edit']"
|
||||
></el-button>
|
||||
</el-tooltip>
|
||||
<el-tooltip content="删除" placement="top">
|
||||
<el-button
|
||||
link
|
||||
type="danger"
|
||||
icon="Delete"
|
||||
size="default"
|
||||
style="font-size: 16px"
|
||||
@click="handleDelete(scope.row)"
|
||||
v-hasPermi="['jcbt:scholarshipBatch:remove']"
|
||||
></el-button>
|
||||
</el-tooltip>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<div class="pagination-container">
|
||||
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
|
||||
</div>
|
||||
</el-card>
|
||||
|
||||
<!-- 添加或修改批次对话框 -->
|
||||
<el-dialog :title="dialog.title" v-model="dialog.visible" width="1200px" append-to-body>
|
||||
<el-form ref="batchFormRef" :model="form" :rules="rules" label-width="120px">
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="批次编码" prop="batchCode">
|
||||
<el-input v-model="form.batchCode" placeholder="请输入批次编码" :disabled="form.id !== undefined" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="批次名称" prop="batchName">
|
||||
<el-input v-model="form.batchName" placeholder="请输入批次名称" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="8">
|
||||
<el-form-item label="学年" prop="academicYear">
|
||||
<el-select v-model="form.academicYear" placeholder="请选择学年" style="width: 100%">
|
||||
<el-option label="2028-2029" value="2028-2029" />
|
||||
<el-option label="2027-2028" value="2027-2028" />
|
||||
<el-option label="2026-2027" value="2026-2027" />
|
||||
<el-option label="2025-2026" value="2025-2026" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="学期" prop="semester">
|
||||
<el-select v-model="form.semester" placeholder="请选择学期" style="width: 100%">
|
||||
<el-option label="第一学期" :value="1" />
|
||||
<el-option label="第二学期" :value="2" />
|
||||
<el-option label="全年" :value="3" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="批次类型" prop="batchType">
|
||||
<el-select v-model="form.batchType" placeholder="请选择批次类型" style="width: 100%">
|
||||
<el-option label="常规批次" value="REGULAR" />
|
||||
<el-option label="专项批次" value="SPECIAL" />
|
||||
<el-option label="补充批次" value="SUPPLEMENTARY" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="开始时间" prop="startTime">
|
||||
<el-date-picker
|
||||
v-model="form.startTime"
|
||||
type="datetime"
|
||||
placeholder="选择开始时间"
|
||||
format="YYYY-MM-DD HH:mm:ss"
|
||||
value-format="YYYY-MM-DD HH:mm:ss"
|
||||
style="width: 100%"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="结束时间" prop="endTime">
|
||||
<el-date-picker
|
||||
v-model="form.endTime"
|
||||
type="datetime"
|
||||
placeholder="选择结束时间"
|
||||
format="YYYY-MM-DD HH:mm:ss"
|
||||
value-format="YYYY-MM-DD HH:mm:ss"
|
||||
style="width: 100%"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="申请开始时间" prop="applyStartTime">
|
||||
<el-date-picker
|
||||
v-model="form.applyStartTime"
|
||||
type="datetime"
|
||||
placeholder="选择申请开始时间"
|
||||
format="YYYY-MM-DD HH:mm:ss"
|
||||
value-format="YYYY-MM-DD HH:mm:ss"
|
||||
style="width: 100%"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="申请结束时间" prop="applyEndTime">
|
||||
<el-date-picker
|
||||
v-model="form.applyEndTime"
|
||||
type="datetime"
|
||||
placeholder="选择申请结束时间"
|
||||
format="YYYY-MM-DD HH:mm:ss"
|
||||
value-format="YYYY-MM-DD HH:mm:ss"
|
||||
style="width: 100%"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="审核开始时间" prop="reviewStartTime">
|
||||
<el-date-picker
|
||||
v-model="form.reviewStartTime"
|
||||
type="datetime"
|
||||
placeholder="选择审核开始时间"
|
||||
format="YYYY-MM-DD HH:mm:ss"
|
||||
value-format="YYYY-MM-DD HH:mm:ss"
|
||||
style="width: 100%"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="审核结束时间" prop="reviewEndTime">
|
||||
<el-date-picker
|
||||
v-model="form.reviewEndTime"
|
||||
type="datetime"
|
||||
placeholder="选择审核结束时间"
|
||||
format="YYYY-MM-DD HH:mm:ss"
|
||||
value-format="YYYY-MM-DD HH:mm:ss"
|
||||
style="width: 100%"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="24">
|
||||
<el-form-item label="奖学金类型" prop="scholarshipTypeIds">
|
||||
<el-select
|
||||
v-model="form.scholarshipTypeIds"
|
||||
multiple
|
||||
placeholder="请选择奖学金类型"
|
||||
style="width: 100%"
|
||||
clearable
|
||||
collapse-tags
|
||||
collapse-tags-tooltip
|
||||
:max-collapse-tags="3"
|
||||
>
|
||||
<el-option
|
||||
v-for="option in scholarshipTypeOptions"
|
||||
:key="option.value"
|
||||
:label="option.label"
|
||||
:value="option.value"
|
||||
/>
|
||||
</el-select>
|
||||
<div class="form-help-text">
|
||||
选择该批次支持申请的奖学金类型,可多选
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="24">
|
||||
<el-form-item label="批次描述" prop="description">
|
||||
<el-input
|
||||
v-model="form.description"
|
||||
type="textarea"
|
||||
placeholder="请输入批次描述"
|
||||
resize="none"
|
||||
:autosize="{ minRows: 3, maxRows: 5 }"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="24">
|
||||
<el-form-item label="通知内容" prop="noticeContent">
|
||||
<el-input
|
||||
v-model="form.noticeContent"
|
||||
type="textarea"
|
||||
placeholder="请输入通知内容"
|
||||
resize="none"
|
||||
:autosize="{ minRows: 3, maxRows: 5 }"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button :loading="buttonLoading" plain type="primary" @click="submitForm">确 定</el-button>
|
||||
<el-button @click="cancel">取 消</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 状态变更对话框 -->
|
||||
<el-dialog title="状态变更" v-model="statusDialog.visible" width="400px" append-to-body>
|
||||
<el-form :model="statusForm" label-width="80px">
|
||||
<el-form-item label="当前状态">
|
||||
<el-tag v-if="statusForm.currentStatus === 'DRAFT'" type="info">草稿</el-tag>
|
||||
<el-tag v-else-if="statusForm.currentStatus === 'ACTIVE'" type="success">进行中</el-tag>
|
||||
<el-tag v-else-if="statusForm.currentStatus === 'COMPLETED'" type="primary">已完成</el-tag>
|
||||
<el-tag v-else-if="statusForm.currentStatus === 'CANCELLED'" type="danger">已取消</el-tag>
|
||||
</el-form-item>
|
||||
<el-form-item label="变更为">
|
||||
<el-select v-model="statusForm.newStatus" placeholder="请选择状态" style="width: 100%">
|
||||
<el-option v-if="statusForm.currentStatus === 'DRAFT'" label="进行中" value="ACTIVE" />
|
||||
<el-option v-if="statusForm.currentStatus === 'DRAFT'" label="已取消" value="CANCELLED" />
|
||||
<el-option v-if="statusForm.currentStatus === 'ACTIVE'" label="已完成" value="COMPLETED" />
|
||||
<el-option v-if="statusForm.currentStatus === 'ACTIVE'" label="已取消" value="CANCELLED" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button type="primary" @click="confirmStatusChange">确 定</el-button>
|
||||
<el-button @click="statusDialog.visible = false">取 消</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 查看详情对话框 -->
|
||||
<el-dialog title="批次详情" v-model="viewDialog.visible" width="1000px" append-to-body>
|
||||
<el-descriptions :column="2" border>
|
||||
<el-descriptions-item label="批次编码">{{ viewData.batchCode }}</el-descriptions-item>
|
||||
<el-descriptions-item label="批次名称">{{ viewData.batchName }}</el-descriptions-item>
|
||||
<el-descriptions-item label="学年">{{ viewData.academicYear }}</el-descriptions-item>
|
||||
<el-descriptions-item label="学期">
|
||||
<span v-if="viewData.semester === 1">第一学期</span>
|
||||
<span v-else-if="viewData.semester === 2">第二学期</span>
|
||||
<span v-else-if="viewData.semester === 3">全年</span>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="批次类型">
|
||||
<el-tag v-if="viewData.batchType === 'REGULAR'" type="primary">常规批次</el-tag>
|
||||
<el-tag v-else-if="viewData.batchType === 'SPECIAL'" type="warning">专项批次</el-tag>
|
||||
<el-tag v-else-if="viewData.batchType === 'SUPPLEMENTARY'" type="info">补充批次</el-tag>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="状态">
|
||||
<el-tag v-if="viewData.status === 'DRAFT'" type="info">草稿</el-tag>
|
||||
<el-tag v-else-if="viewData.status === 'ACTIVE'" type="success">进行中</el-tag>
|
||||
<el-tag v-else-if="viewData.status === 'COMPLETED'" type="primary">已完成</el-tag>
|
||||
<el-tag v-else-if="viewData.status === 'CANCELLED'" type="danger">已取消</el-tag>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="开始时间">{{ parseTime(viewData.startTime) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="结束时间">{{ parseTime(viewData.endTime) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="申请开始时间">{{ parseTime(viewData.applyStartTime) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="申请结束时间">{{ parseTime(viewData.applyEndTime) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="审核开始时间">{{ parseTime(viewData.reviewStartTime) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="审核结束时间">{{ parseTime(viewData.reviewEndTime) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="批次描述" :span="2">{{ viewData.description || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="奖学金类型" :span="2">
|
||||
<el-tag v-for="typeName in getScholarshipTypeNames(viewData.scholarshipTypeIds)"
|
||||
:key="typeName"
|
||||
type="primary"
|
||||
class="mr-2">
|
||||
{{ typeName }}
|
||||
</el-tag>
|
||||
<span v-if="!viewData.scholarshipTypeIds || viewData.scholarshipTypeIds.length === 0" class="text-gray-400">
|
||||
暂无关联奖学金类型
|
||||
</span>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="通知内容" :span="2">{{ viewData.noticeContent || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="创建时间">{{ parseTime(viewData.createTime) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="更新时间">{{ parseTime(viewData.updateTime) }}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup name="ScholarshipBatch" lang="ts">
|
||||
import {
|
||||
listScholarshipBatch,
|
||||
getScholarshipBatch,
|
||||
delScholarshipBatch,
|
||||
addScholarshipBatch,
|
||||
updateScholarshipBatch,
|
||||
exportScholarshipBatch,
|
||||
changeScholarshipBatchStatus,
|
||||
checkTimeConflict,
|
||||
type ScholarshipBatchVO,
|
||||
type ScholarshipBatchForm,
|
||||
type ScholarshipBatchQuery
|
||||
} from '@/api/jcbt/scholarshipBatch';
|
||||
import { listScholarshipType, type ScholarshipTypeVO } from '@/api/jcbt/scholarshipType';
|
||||
|
||||
|
||||
const { proxy } = getCurrentInstance()!;
|
||||
const { sys_normal_disable } = toRefs<any>(proxy?.useDict('sys_normal_disable'));
|
||||
|
||||
const batchList = ref<ScholarshipBatchVO[]>([]);
|
||||
const loading = ref(true);
|
||||
const showSearch = ref(true);
|
||||
const ids = ref<Array<string | number>>([]);
|
||||
const single = ref(true);
|
||||
const multiple = ref(true);
|
||||
const total = ref(0);
|
||||
const buttonLoading = ref(false);
|
||||
|
||||
const queryFormRef = ref<ElFormInstance>();
|
||||
const batchFormRef = ref<ElFormInstance>();
|
||||
|
||||
const dialog = reactive<DialogOption>({
|
||||
visible: false,
|
||||
title: ''
|
||||
});
|
||||
|
||||
const statusDialog = reactive<DialogOption>({
|
||||
visible: false,
|
||||
title: ''
|
||||
});
|
||||
|
||||
const viewDialog = reactive<DialogOption>({
|
||||
visible: false,
|
||||
title: ''
|
||||
});
|
||||
|
||||
const initFormData: ScholarshipBatchForm = {
|
||||
id: undefined,
|
||||
batchCode: '',
|
||||
batchName: '',
|
||||
academicYear: '',
|
||||
semester: undefined,
|
||||
batchType: '',
|
||||
startTime: '',
|
||||
endTime: '',
|
||||
applyStartTime: '',
|
||||
applyEndTime: '',
|
||||
reviewStartTime: '',
|
||||
reviewEndTime: '',
|
||||
status: 'DRAFT',
|
||||
description: '',
|
||||
noticeContent: '',
|
||||
scholarshipTypeIds: []
|
||||
};
|
||||
|
||||
const data = reactive<PageData<ScholarshipBatchForm, ScholarshipBatchQuery>>({
|
||||
form: { ...initFormData },
|
||||
queryParams: {
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
batchCode: '',
|
||||
batchName: '',
|
||||
academicYear: '',
|
||||
semester: undefined,
|
||||
batchType: '',
|
||||
status: '',
|
||||
createTime: ''
|
||||
},
|
||||
rules: {
|
||||
batchCode: [
|
||||
{ required: true, message: '批次编码不能为空', trigger: 'blur' }
|
||||
],
|
||||
batchName: [
|
||||
{ required: true, message: '批次名称不能为空', trigger: 'blur' }
|
||||
],
|
||||
academicYear: [
|
||||
{ required: true, message: '学年不能为空', trigger: 'change' }
|
||||
],
|
||||
semester: [
|
||||
{ required: true, message: '学期不能为空', trigger: 'change' }
|
||||
],
|
||||
batchType: [
|
||||
{ required: true, message: '批次类型不能为空', trigger: 'change' }
|
||||
],
|
||||
startTime: [
|
||||
{ required: true, message: '开始时间不能为空', trigger: 'blur' }
|
||||
],
|
||||
endTime: [
|
||||
{ required: true, message: '结束时间不能为空', trigger: 'blur' }
|
||||
],
|
||||
applyStartTime: [
|
||||
{ required: true, message: '申请开始时间不能为空', trigger: 'blur' }
|
||||
],
|
||||
applyEndTime: [
|
||||
{ required: true, message: '申请结束时间不能为空', trigger: 'blur' }
|
||||
],
|
||||
scholarshipTypeIds: [
|
||||
{ required: true, message: '请至少选择一个奖学金类型', trigger: 'change' }
|
||||
]
|
||||
}
|
||||
});
|
||||
|
||||
const { queryParams, form, rules } = toRefs(data);
|
||||
|
||||
// 时间范围
|
||||
const daterangeCreateTime = ref<[DateModelType, DateModelType]>(['', '']);
|
||||
|
||||
// 状态变更表单
|
||||
const statusForm = ref({
|
||||
id: '',
|
||||
currentStatus: '',
|
||||
newStatus: ''
|
||||
});
|
||||
|
||||
// 查看详情数据
|
||||
const viewData = ref<ScholarshipBatchVO>({});
|
||||
|
||||
// 统计数据
|
||||
const statistics = ref({
|
||||
totalBatches: 0,
|
||||
activeBatches: 0,
|
||||
draftBatches: 0,
|
||||
completedBatches: 0
|
||||
});
|
||||
|
||||
// 奖学金类型选项
|
||||
const scholarshipTypeOptions = ref<Array<{ value: string | number; label: string }>>([]);
|
||||
|
||||
|
||||
|
||||
/** 查询批次列表 */
|
||||
function getList() {
|
||||
loading.value = true;
|
||||
if (daterangeCreateTime.value[0] && daterangeCreateTime.value[1]) {
|
||||
queryParams.value.params = {
|
||||
beginCreateTime: daterangeCreateTime.value[0],
|
||||
endCreateTime: daterangeCreateTime.value[1]
|
||||
};
|
||||
} else {
|
||||
queryParams.value.params = {};
|
||||
}
|
||||
|
||||
listScholarshipBatch(queryParams.value).then(response => {
|
||||
batchList.value = response.rows;
|
||||
total.value = response.total;
|
||||
loading.value = false;
|
||||
|
||||
// 更新统计数据
|
||||
updateStatistics();
|
||||
});
|
||||
}
|
||||
|
||||
/** 更新统计数据 */
|
||||
function updateStatistics() {
|
||||
statistics.value.totalBatches = batchList.value.length;
|
||||
statistics.value.activeBatches = batchList.value.filter(item => item.status === 'ACTIVE').length;
|
||||
statistics.value.draftBatches = batchList.value.filter(item => item.status === 'DRAFT').length;
|
||||
statistics.value.completedBatches = batchList.value.filter(item => item.status === 'COMPLETED').length;
|
||||
}
|
||||
|
||||
/** 获取奖学金类型选项 */
|
||||
async function getScholarshipTypeOptions() {
|
||||
try {
|
||||
// 从奖学金类型管理模块获取真实数据
|
||||
const res = await listScholarshipType({
|
||||
pageNum: 1,
|
||||
pageSize: 1000, // 获取所有启用的奖学金类型
|
||||
status: 1 // 只获取启用状态的类型
|
||||
});
|
||||
|
||||
if (res.rows && res.rows.length > 0) {
|
||||
scholarshipTypeOptions.value = res.rows.map((item: ScholarshipTypeVO) => ({
|
||||
value: item.id!,
|
||||
label: item.typeName!
|
||||
}));
|
||||
} else {
|
||||
scholarshipTypeOptions.value = [];
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取奖学金类型选项失败', error);
|
||||
scholarshipTypeOptions.value = [];
|
||||
}
|
||||
}
|
||||
|
||||
/** 搜索按钮操作 */
|
||||
function handleQuery() {
|
||||
queryParams.value.pageNum = 1;
|
||||
getList();
|
||||
}
|
||||
|
||||
/** 重置按钮操作 */
|
||||
function resetQuery() {
|
||||
daterangeCreateTime.value = ['', ''];
|
||||
queryFormRef.value?.resetFields();
|
||||
queryParams.value.pageNum = 1;
|
||||
queryParams.value.params = {};
|
||||
handleQuery();
|
||||
}
|
||||
|
||||
/** 多选框选中数据 */
|
||||
function handleSelectionChange(selection: ScholarshipBatchVO[]) {
|
||||
ids.value = selection.map(item => item.id!);
|
||||
single.value = selection.length !== 1;
|
||||
multiple.value = !selection.length;
|
||||
}
|
||||
|
||||
/** 新增按钮操作 */
|
||||
function handleAdd() {
|
||||
reset();
|
||||
dialog.visible = true;
|
||||
dialog.title = '添加奖学金评定批次';
|
||||
}
|
||||
|
||||
/** 修改按钮操作 */
|
||||
async function handleUpdate(row?: ScholarshipBatchVO) {
|
||||
reset();
|
||||
const _id = row?.id || ids.value[0];
|
||||
const res = await getScholarshipBatch(_id);
|
||||
|
||||
// 先赋值基本数据
|
||||
Object.assign(form.value, res.data);
|
||||
|
||||
// 确保scholarshipTypeIds正确赋值
|
||||
if (res.data.scholarshipTypeIds && Array.isArray(res.data.scholarshipTypeIds)) {
|
||||
form.value.scholarshipTypeIds = [...res.data.scholarshipTypeIds];
|
||||
} else {
|
||||
form.value.scholarshipTypeIds = [];
|
||||
}
|
||||
|
||||
dialog.visible = true;
|
||||
dialog.title = '修改奖学金评定批次';
|
||||
}
|
||||
|
||||
/** 查看详情 */
|
||||
async function handleView(row: ScholarshipBatchVO) {
|
||||
const res = await getScholarshipBatch(row.id!);
|
||||
viewData.value = res.data;
|
||||
viewDialog.visible = true;
|
||||
}
|
||||
|
||||
/** 提交按钮 */
|
||||
function submitForm() {
|
||||
batchFormRef.value?.validate(async valid => {
|
||||
if (!valid) return;
|
||||
|
||||
buttonLoading.value = true;
|
||||
|
||||
try {
|
||||
// 检查时间冲突
|
||||
const conflictCheck = await checkTimeConflict(form.value);
|
||||
if (conflictCheck.data) {
|
||||
proxy?.$modal.msgError('批次时间与现有批次冲突,请重新选择时间');
|
||||
return;
|
||||
}
|
||||
|
||||
if (form.value.id) {
|
||||
await updateScholarshipBatch(form.value);
|
||||
proxy?.$modal.msgSuccess('修改成功');
|
||||
} else {
|
||||
await addScholarshipBatch(form.value);
|
||||
proxy?.$modal.msgSuccess('新增成功');
|
||||
}
|
||||
dialog.visible = false;
|
||||
await getList();
|
||||
} finally {
|
||||
buttonLoading.value = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/** 删除按钮操作 */
|
||||
async function handleDelete(row?: ScholarshipBatchVO) {
|
||||
const _ids = row?.id || ids.value;
|
||||
|
||||
await proxy?.$modal.confirm('是否确认删除批次编号为"' + _ids + '"的数据项?');
|
||||
await delScholarshipBatch(_ids);
|
||||
proxy?.$modal.msgSuccess('删除成功');
|
||||
await getList();
|
||||
}
|
||||
|
||||
/** 导出按钮操作 */
|
||||
function handleExport() {
|
||||
proxy?.$download.excel(exportScholarshipBatch, queryParams.value, `scholarship_batch_${new Date().getTime()}.xlsx`);
|
||||
}
|
||||
|
||||
/** 状态变更操作 */
|
||||
function handleStatusChange(row: ScholarshipBatchVO) {
|
||||
statusForm.value = {
|
||||
id: row.id as string,
|
||||
currentStatus: row.status!,
|
||||
newStatus: ''
|
||||
};
|
||||
statusDialog.visible = true;
|
||||
}
|
||||
|
||||
/** 确认状态变更 */
|
||||
async function confirmStatusChange() {
|
||||
if (!statusForm.value.newStatus) {
|
||||
proxy?.$modal.msgError('请选择要变更的状态');
|
||||
return;
|
||||
}
|
||||
|
||||
await changeScholarshipBatchStatus(statusForm.value.id, statusForm.value.newStatus);
|
||||
proxy?.$modal.msgSuccess('状态变更成功');
|
||||
statusDialog.visible = false;
|
||||
await getList();
|
||||
}
|
||||
|
||||
/** 取消按钮 */
|
||||
function cancel() {
|
||||
dialog.visible = false;
|
||||
reset();
|
||||
}
|
||||
|
||||
/** 表单重置 */
|
||||
function reset() {
|
||||
form.value = { ...initFormData };
|
||||
batchFormRef.value?.resetFields();
|
||||
}
|
||||
|
||||
/** 根据奖学金类型ID获取名称 */
|
||||
function getScholarshipTypeNames(typeIds: Array<string | number> | undefined): string[] {
|
||||
if (!typeIds || typeIds.length === 0) return [];
|
||||
|
||||
return typeIds.map(id => {
|
||||
const option = scholarshipTypeOptions.value.find(opt => opt.value === id);
|
||||
return option ? option.label : `未知类型(${id})`;
|
||||
});
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
getList();
|
||||
getScholarshipTypeOptions();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.form-help-text {
|
||||
font-size: 12px;
|
||||
color: #909399;
|
||||
margin-top: 4px;
|
||||
line-height: 1.4;
|
||||
}
|
||||
.stats-row {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.stat-card {
|
||||
cursor: pointer;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
|
||||
.stat-card:hover {
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
.stat-content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.stat-icon {
|
||||
margin-right: 16px;
|
||||
font-size: 32px;
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.stat-info {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.stat-value {
|
||||
font-size: 24px;
|
||||
font-weight: bold;
|
||||
line-height: 1;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.stat-label {
|
||||
font-size: 14px;
|
||||
opacity: 0.8;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
/* 不同主题颜色 */
|
||||
.stat-card-primary .stat-icon {
|
||||
background-color: #ecf5ff;
|
||||
color: #409eff;
|
||||
}
|
||||
|
||||
.stat-card-primary .stat-value {
|
||||
color: #409eff;
|
||||
}
|
||||
|
||||
.stat-card-success .stat-icon {
|
||||
background-color: #f0f9ff;
|
||||
color: #67c23a;
|
||||
}
|
||||
|
||||
.stat-card-success .stat-value {
|
||||
color: #67c23a;
|
||||
}
|
||||
|
||||
.stat-card-warning .stat-icon {
|
||||
background-color: #fdf6ec;
|
||||
color: #e6a23c;
|
||||
}
|
||||
|
||||
.stat-card-warning .stat-value {
|
||||
color: #e6a23c;
|
||||
}
|
||||
|
||||
.stat-card-info .stat-icon {
|
||||
background-color: #f4f4f5;
|
||||
color: #909399;
|
||||
}
|
||||
|
||||
.stat-card-info .stat-value {
|
||||
color: #909399;
|
||||
}
|
||||
|
||||
.pagination-container {
|
||||
margin-top: 16px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.description-cell {
|
||||
max-width: 200px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
</style>
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
Reference in new issue
Block a user