Merge branch 'master' of http://47.99.164.66:3000/hzdyjs-xg/all-project
This commit is contained in:
commit
79c798ef30
63 files changed
+6476
-509
No files matched your search
@@ -145,10 +145,16 @@ export interface StglActivityVO {
|
||||
activityRange?: number;
|
||||
|
||||
/**
|
||||
* 活动状态
|
||||
* 活动状态(动态计算后的状态)
|
||||
*/
|
||||
activityStatus?: string;
|
||||
|
||||
/**
|
||||
* 原始活动状态(数据库中存储的实际状态)
|
||||
* 用于权限控制和业务逻辑判断
|
||||
*/
|
||||
originalActivityStatus?: string;
|
||||
|
||||
/**
|
||||
* 是否为已办活动
|
||||
*/
|
||||
|
||||
@@ -211,8 +211,8 @@ export interface MyRegistrationQuery {
|
||||
pageNum?: number;
|
||||
/** 每页显示记录数 */
|
||||
pageSize?: number;
|
||||
/** 名称 */
|
||||
name?: string;
|
||||
/** 报名类型 */
|
||||
registrationType?: string;
|
||||
/** 审核状态 */
|
||||
approvalStatus?: string;
|
||||
}
|
||||
@@ -134,6 +134,7 @@
|
||||
<el-table-column label="申请类型" align="center" prop="applicationType" min-width="100">
|
||||
<template #default="scope">
|
||||
<el-tag v-if="scope.row.applicationType === 'RECOMMEND'" type="primary">教师推荐</el-tag>
|
||||
<el-tag v-else-if="scope.row.applicationType === 'TEACHER_RECOMMEND'" type="primary">教师推荐</el-tag>
|
||||
<el-tag v-else-if="scope.row.applicationType === 'STUDENT'" type="success">学生申请</el-tag>
|
||||
<el-tag v-else-if="scope.row.applicationType === 'AUTO'" type="info">自动评定</el-tag>
|
||||
<el-tag v-else-if="scope.row.applicationType === 'DIRECT'" type="warning">直接指定</el-tag>
|
||||
@@ -311,7 +312,7 @@
|
||||
<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.studentNo }}</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>
|
||||
@@ -963,7 +964,7 @@ const filterStudents = () => {
|
||||
filteredStudents.value = classStudents.value;
|
||||
} else {
|
||||
filteredStudents.value = classStudents.value.filter(
|
||||
(student: any) => student.studentName?.includes(studentKeyword.value) || student.studentNo?.includes(studentKeyword.value)
|
||||
(student: any) => student.studentName?.includes(studentKeyword.value) || student.studentCode?.includes(studentKeyword.value)
|
||||
);
|
||||
}
|
||||
};
|
||||
@@ -989,7 +990,8 @@ const toggleStudentSelection = (student: any, checked: boolean) => {
|
||||
if (availableScholarshipTypes.value.length === 1) {
|
||||
const scholarshipType = availableScholarshipTypes.value[0];
|
||||
if (canSelectScholarshipType(student, scholarshipType)) {
|
||||
student.selectedScholarshipType = scholarshipType;
|
||||
// ✅ 创建对象副本,避免引用问题
|
||||
student.selectedScholarshipType = { ...scholarshipType };
|
||||
updateScholarshipInfo(student);
|
||||
console.log('🎯 自动选择唯一可用的奖学金类型:', scholarshipType.name);
|
||||
} else {
|
||||
@@ -1042,12 +1044,25 @@ const clearSelectedStudents = () => {
|
||||
|
||||
/** 更新奖学金信息 */
|
||||
const updateScholarshipInfo = (student: any) => {
|
||||
console.log('🔄 更新奖学金信息:', { studentName: student.studentName, selectedType: student.selectedScholarshipType?.name });
|
||||
console.log('🔄 更新奖学金信息:', {
|
||||
studentName: student.studentName,
|
||||
selectedType: student.selectedScholarshipType?.name,
|
||||
originalType: student.selectedScholarshipType
|
||||
});
|
||||
|
||||
if (student.selectedScholarshipType) {
|
||||
// ✅ 立即创建对象副本,确保 v-model 绑定的是副本而不是原始引用
|
||||
student.selectedScholarshipType = { ...student.selectedScholarshipType };
|
||||
|
||||
// 使用副本更新相关字段
|
||||
student.selectedLevel = student.selectedScholarshipType.levelType;
|
||||
student.selectedAmount = student.selectedScholarshipType.amount;
|
||||
|
||||
console.log('✅ 创建奖学金类型副本:', {
|
||||
copy: student.selectedScholarshipType,
|
||||
name: student.selectedScholarshipType.name
|
||||
});
|
||||
|
||||
// 检查名额是否足够
|
||||
if (!canSelectScholarshipType(student, student.selectedScholarshipType)) {
|
||||
ElMessage.warning(`${student.selectedScholarshipType.name} 名额不足,请选择其他类型`);
|
||||
@@ -1120,7 +1135,7 @@ const submitBatchApplication = async () => {
|
||||
const studentApplications = selectedStudents.value.map((s: any) => ({
|
||||
studentId: String(s.studentId || s.id),
|
||||
studentName: s.studentName,
|
||||
studentNo: s.studentNo,
|
||||
studentNo: s.studentCode, // ✅ 修复:使用后端返回的 studentCode 字段作为学号
|
||||
scholarshipTypeId: s.selectedScholarshipType.id,
|
||||
deptId: classInfo.value.deptId,
|
||||
applicationReason: `班主任批量申请 - ${s.selectedScholarshipType.name}`,
|
||||
|
||||
@@ -114,6 +114,7 @@
|
||||
<el-form-item label="申请类型" prop="applicationType">
|
||||
<el-select v-model="queryParams.applicationType" placeholder="请选择申请类型" clearable style="width: 100%">
|
||||
<el-option label="教师推荐" value="RECOMMEND" />
|
||||
<el-option label="教师推荐" value="TEACHER_RECOMMEND" />
|
||||
<el-option label="学生申请" value="STUDENT" />
|
||||
<el-option label="自动评定" value="AUTO" />
|
||||
<el-option label="直接指定" value="DIRECT" />
|
||||
@@ -194,6 +195,7 @@
|
||||
<template #default="scope">
|
||||
<el-tag v-if="scope.row.applicationType === 'RECOMMEND'" type="primary">教师推荐</el-tag>
|
||||
<el-tag v-else-if="scope.row.applicationType === 'STUDENT'" type="success">学生申请</el-tag>
|
||||
<el-tag v-else-if="scope.row.applicationType === 'TEACHER_RECOMMEND'" type="primary">教师推荐</el-tag>
|
||||
<el-tag v-else-if="scope.row.applicationType === 'AUTO'" type="info">自动评定</el-tag>
|
||||
<el-tag v-else-if="scope.row.applicationType === 'DIRECT'" type="warning">直接指定</el-tag>
|
||||
<el-tag v-else type="info">{{ scope.row.applicationType }}</el-tag>
|
||||
@@ -684,14 +686,25 @@ function handleReview(row) {
|
||||
console.log('🔍 [DEBUG] handleReview 开始执行');
|
||||
console.log('🔍 [DEBUG] 传入的row数据:', JSON.stringify(row, null, 2));
|
||||
|
||||
reviewForm.value = {
|
||||
id: row.id,
|
||||
status: 'APPROVED',
|
||||
reviewComment: ''
|
||||
};
|
||||
// 先获取完整的申请数据
|
||||
getScholarshipApplication(row.id)
|
||||
.then((response) => {
|
||||
console.log('🔍 [DEBUG] 获取到完整申请数据:', response.data);
|
||||
|
||||
console.log('🔍 [DEBUG] 设置的reviewForm:', JSON.stringify(reviewForm.value, null, 2));
|
||||
reviewOpen.value = true;
|
||||
// 设置完整的审核表单数据
|
||||
reviewForm.value = {
|
||||
...response.data, // 包含所有申请信息
|
||||
status: 'APPROVED', // 默认审核状态
|
||||
reviewComment: '' // 审核意见
|
||||
};
|
||||
|
||||
console.log('🔍 [DEBUG] 设置的完整reviewForm:', JSON.stringify(reviewForm.value, null, 2));
|
||||
reviewOpen.value = true;
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('❌ [ERROR] 获取申请详情失败:', error);
|
||||
proxy.$modal.msgError('获取申请详情失败');
|
||||
});
|
||||
}
|
||||
|
||||
/** 查看详情 */
|
||||
|
||||
@@ -171,6 +171,9 @@
|
||||
@cancel="applyDialogVisible = false"
|
||||
/>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 申请详情对话框(复用组件) -->
|
||||
<ApplicationDetail ref="applicationDetailRef" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -183,12 +186,14 @@ import type { WorkStudyPositionVO } from '@/api/jcbt/workStudyPosition';
|
||||
import { getStudentApplicationStatusList } from '@/api/jcbt/workStudyApplication';
|
||||
import PositionDetail from './detail.vue';
|
||||
import ApplicationForm from './form.vue';
|
||||
import ApplicationDetail from './components/ApplicationDetail.vue';
|
||||
|
||||
const router = useRouter();
|
||||
|
||||
// 组件引用
|
||||
const queryFormRef = ref();
|
||||
const tableRef = ref();
|
||||
const applicationDetailRef = ref();
|
||||
|
||||
// 响应式数据
|
||||
const loading = ref(false);
|
||||
@@ -313,7 +318,14 @@ const handleApply = (position: WorkStudyPositionVO) => {
|
||||
|
||||
// 如果已有申请且状态为已提交或审核中,跳转到申请管理页面
|
||||
if (application && ['submitted', 'college_reviewing', 'final_reviewing'].includes(application.status)) {
|
||||
router.push('/jcbt/workstudy/my-applications');
|
||||
const id = application?.applicationId || application?.id;
|
||||
if (id && applicationDetailRef.value) {
|
||||
applicationDetailRef.value.handleDetail(id, 'application');
|
||||
} else {
|
||||
// 回退到岗位详情对话框
|
||||
selectedPositionId.value = position.id as number;
|
||||
detailDialogVisible.value = true;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,186 +3,69 @@
|
||||
<el-tabs type="border-card" v-model="activeTab">
|
||||
<!-- 基本信息标签页 -->
|
||||
<el-tab-pane label="基本信息" name="basic">
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<div class="detail-item">
|
||||
<label class="detail-label">活动名称</label>
|
||||
<div class="detail-value">{{ activity.activityName || '暂无' }}</div>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<div class="detail-item">
|
||||
<label class="detail-label">活动类型</label>
|
||||
<div class="detail-value">
|
||||
<dict-tag :options="stgl_activity_type" :value="activity.activityType" />
|
||||
</div>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<!-- 基本信息区域 -->
|
||||
<el-divider content-position="left">基本信息</el-divider>
|
||||
<el-descriptions :column="2" border class="basic-info-section custom-width-registration">
|
||||
<el-descriptions-item label="活动名称">{{ activity.activityName || '暂无' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="活动类型">
|
||||
<dict-tag :options="stgl_activity_type" :value="activity.activityType" />
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="活动主题">{{ activity.activityTheme || '暂无' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="活动地点">{{ activity.location || '暂无' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="开始时间">{{ activity.startTime || '暂无' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="结束时间">{{ activity.endTime || '暂无' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="活动状态">
|
||||
<dict-tag :options="stgl_activity_status" :value="activity.activityStatus" />
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="关联社团/队伍">{{ activity.relatedClubName || '暂无' }}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<div class="detail-item">
|
||||
<label class="detail-label">活动主题</label>
|
||||
<div class="detail-value">{{ activity.activityTheme || '暂无' }}</div>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<div class="detail-item">
|
||||
<label class="detail-label">活动地点</label>
|
||||
<div class="detail-value">{{ activity.location || '暂无' }}</div>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<div class="detail-item">
|
||||
<label class="detail-label">开始时间</label>
|
||||
<div class="detail-value">{{ activity.startTime || '暂无' }}</div>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<div class="detail-item">
|
||||
<label class="detail-label">结束时间</label>
|
||||
<div class="detail-value">{{ activity.endTime || '暂无' }}</div>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<div class="detail-item">
|
||||
<label class="detail-label">活动状态</label>
|
||||
<div class="detail-value">
|
||||
<dict-tag :options="stgl_activity_status" :value="activity.activityStatus" />
|
||||
</div>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<div class="detail-item">
|
||||
<label class="detail-label">关联社团/队伍</label>
|
||||
<div class="detail-value">{{ activity.relatedClubName || '暂无' }}</div>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<div class="detail-item">
|
||||
<label class="detail-label">活动海报</label>
|
||||
<div class="detail-value">
|
||||
<div v-if="activity.posterUrl" class="view-poster">
|
||||
<image-preview :src="activity.posterUrl" :width="200" :height="150" />
|
||||
</div>
|
||||
<div v-else class="no-poster">
|
||||
<span class="no-poster-text">暂无海报</span>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 活动海报区域 -->
|
||||
<el-divider content-position="left">活动海报</el-divider>
|
||||
<div v-if="activity.posterUrl" class="view-poster">
|
||||
<image-preview :src="activity.posterUrl" :width="200" :height="150" />
|
||||
</div>
|
||||
<div v-else class="no-poster">
|
||||
<span class="no-poster-text">暂无海报</span>
|
||||
</div>
|
||||
|
||||
<div class="detail-item">
|
||||
<label class="detail-label">活动简介</label>
|
||||
<div class="detail-value">
|
||||
<div class="view-description">
|
||||
{{ activity.description || '暂无简介' }}
|
||||
</div>
|
||||
</div>
|
||||
<!-- 活动简介区域 -->
|
||||
<el-divider content-position="left">活动简介</el-divider>
|
||||
<div class="view-description">
|
||||
{{ activity.description || '暂无简介' }}
|
||||
</div>
|
||||
|
||||
<!-- 主办方信息 -->
|
||||
<div class="section-divider">
|
||||
<h4 class="section-title">主办方信息</h4>
|
||||
</div>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<div class="detail-item">
|
||||
<label class="detail-label">主办方名称</label>
|
||||
<div class="detail-value">{{ activity.organizerName || '暂无' }}</div>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<div class="detail-item">
|
||||
<label class="detail-label">联系人</label>
|
||||
<div class="detail-value">{{ activity.organizerContact || '暂无' }}</div>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<div class="detail-item">
|
||||
<label class="detail-label">联系电话</label>
|
||||
<div class="detail-value">{{ activity.organizerPhone || '暂无' }}</div>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<!-- 主办方信息区域 -->
|
||||
<el-divider content-position="left">主办方信息</el-divider>
|
||||
<el-descriptions :column="3" border class="organizer-info-section custom-width-organizer">
|
||||
<el-descriptions-item label="主办方名称" :label-style="{ width: '13%' }" :content-style="{ width: '35%' }">{{ activity.organizerName || '暂无' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="联系人" :label-style="{ width: '10%' }" :content-style="{ width: '15%' }">{{ activity.organizerContact || '暂无' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="联系电话" :label-style="{ width: '10%' }" :content-style="{ width: '17%' }">{{ activity.organizerPhone || '暂无' }}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
|
||||
<!-- 承办方信息 -->
|
||||
<div class="section-divider">
|
||||
<h4 class="section-title">承办方信息</h4>
|
||||
</div>
|
||||
<!-- 承办方信息区域 -->
|
||||
<el-divider content-position="left">承办方信息</el-divider>
|
||||
<div v-if="coOrganizerList.length > 0">
|
||||
<div v-for="(organizer, index) in coOrganizerList" :key="index" class="co-organizer-item">
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="6">
|
||||
<div class="detail-item">
|
||||
<label class="detail-label">承办方名称</label>
|
||||
<div class="detail-value">{{ organizer.name || '暂无' }}</div>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<div class="detail-item">
|
||||
<label class="detail-label">承办方类型</label>
|
||||
<div class="detail-value">{{ organizer.type || '暂无' }}</div>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<div class="detail-item">
|
||||
<label class="detail-label">联系人</label>
|
||||
<div class="detail-value">{{ organizer.contact || '暂无' }}</div>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<div class="detail-item">
|
||||
<label class="detail-label">联系电话</label>
|
||||
<div class="detail-value">{{ organizer.phone || '暂无' }}</div>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<div v-for="(organizer, index) in coOrganizerList" :key="index" class="co-organizer-item custom-width-co-organizer">
|
||||
<el-descriptions :column="3" border>
|
||||
<el-descriptions-item label="承办方名称" :label-style="{ width: '12%' }" :content-style="{ width: '36%' }">{{ organizer.name || '暂无' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="联系人" :label-style="{ width: '10%' }" :content-style="{ width: '16%' }">{{ organizer.contact || '暂无' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="联系电话" :label-style="{ width: '10%' }" :content-style="{ width: '16%' }">{{ organizer.phone || '暂无' }}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="no-data">暂无承办方信息</div>
|
||||
|
||||
<!-- 指导老师信息 -->
|
||||
<div class="section-divider">
|
||||
<h4 class="section-title">指导老师信息</h4>
|
||||
</div>
|
||||
<!-- 指导老师信息区域 -->
|
||||
<el-divider content-position="left">指导老师信息</el-divider>
|
||||
<div v-if="instructorList.length > 0">
|
||||
<div v-for="(instructor, index) in instructorList" :key="index" class="instructor-item">
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="6">
|
||||
<div class="detail-item">
|
||||
<label class="detail-label">姓名</label>
|
||||
<div class="detail-value">{{ instructor.name || '暂无' }}</div>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<div class="detail-item">
|
||||
<label class="detail-label">部门</label>
|
||||
<div class="detail-value">{{ instructor.dept || '暂无' }}</div>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<div class="detail-item">
|
||||
<label class="detail-label">电话</label>
|
||||
<div class="detail-value">{{ instructor.phone || '暂无' }}</div>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<div class="detail-item">
|
||||
<label class="detail-label">邮箱</label>
|
||||
<div class="detail-value">{{ instructor.email || '暂无' }}</div>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<div v-for="(instructor, index) in instructorList" :key="index" class="instructor-item custom-width-instructor">
|
||||
<el-descriptions :column="4" border size="small">
|
||||
<el-descriptions-item label="姓名" :label-style="{ width: '8%' }" :content-style="{ width: '15%' }">{{ instructor.name || '暂无' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="部门" :label-style="{ width: '8%' }" :content-style="{ width: '17%' }">{{ instructor.dept || '暂无' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="电话" :label-style="{ width: '8%' }" :content-style="{ width: '15%' }">{{ instructor.phone || '暂无' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="邮箱" :label-style="{ width: '8%' }" :content-style="{ width: '17%' }">{{ instructor.email || '暂无' }}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="no-data">暂无指导老师信息</div>
|
||||
@@ -190,100 +73,46 @@
|
||||
|
||||
<!-- 报名设置标签页 -->
|
||||
<el-tab-pane label="报名设置" name="registration">
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<div class="detail-item">
|
||||
<label class="detail-label">报名方式</label>
|
||||
<div class="detail-value">
|
||||
<dict-tag :options="stgl_registration_type" :value="activity.registrationType" />
|
||||
</div>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<div class="detail-item">
|
||||
<label class="detail-label">是否需要审核</label>
|
||||
<div class="detail-value">
|
||||
<!-- 临时解决方案:直接显示中文文本 -->
|
||||
<el-tag v-if="activity.needApproval === 1" type="warning" size="small">需要审核</el-tag>
|
||||
<el-tag v-else-if="activity.needApproval === 0" type="success" size="small">无需审核</el-tag>
|
||||
<span v-else class="text-gray-400">{{ activity.needApproval }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<!-- 报名方式和审核设置区域 -->
|
||||
<el-divider content-position="left">报名方式和审核设置</el-divider>
|
||||
<el-descriptions :column="2" border class="registration-info-section custom-width-registration">
|
||||
<el-descriptions-item label="报名方式" :label-style="{ width: '10%' }" :content-style="{ width: '40%' }">
|
||||
<dict-tag :options="stgl_registration_type" :value="activity.registrationType" />
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="是否需要审核" :label-style="{ width: '10%' }" :content-style="{ width: '40%' }">
|
||||
<!-- 临时解决方案:直接显示中文文本 -->
|
||||
<el-tag v-if="activity.needApproval === 1" type="warning" size="small">需要审核</el-tag>
|
||||
<el-tag v-else-if="activity.needApproval === 0" type="success" size="small">无需审核</el-tag>
|
||||
<span v-else class="text-gray-400">{{ activity.needApproval }}</span>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="报名范围" :label-style="{ width: '10%' }" :content-style="{ width: '40%' }">
|
||||
<dict-tag :options="stgl_activity_range" :value="activity.activityRange" />
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="报名状态" :label-style="{ width: '10%' }" :content-style="{ width: '40%' }">
|
||||
<dict-tag :options="stgl_registration_status" :value="activity.registrationStatus" />
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<div class="detail-item">
|
||||
<label class="detail-label">报名范围</label>
|
||||
<div class="detail-value">
|
||||
<dict-tag :options="stgl_activity_range" :value="activity.activityRange" />
|
||||
</div>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<!-- 报名时间区域 -->
|
||||
<el-divider content-position="left">报名时间</el-divider>
|
||||
<el-descriptions :column="2" border class="registration-time-section custom-width-registration">
|
||||
<el-descriptions-item label="报名开始时间">{{ activity.registrationStart || '暂无' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="报名结束时间">{{ activity.registrationEnd || '暂无' }}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<div class="detail-item">
|
||||
<label class="detail-label">报名开始时间</label>
|
||||
<div class="detail-value">{{ activity.registrationStart || '暂无' }}</div>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<div class="detail-item">
|
||||
<label class="detail-label">报名结束时间</label>
|
||||
<div class="detail-value">{{ activity.registrationEnd || '暂无' }}</div>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<!-- 人数限制区域 -->
|
||||
<el-divider content-position="left">人数限制</el-divider>
|
||||
<el-descriptions :column="2" border class="registration-limit-section custom-width-registration">
|
||||
<el-descriptions-item label="总人数上限" v-if="activity.maxParticipants">{{ activity.maxParticipants }}</el-descriptions-item>
|
||||
<el-descriptions-item label="团队数量上限" v-if="activity.maxTeams">{{ activity.maxTeams }}</el-descriptions-item>
|
||||
<el-descriptions-item label="每队最小人数" v-if="activity.teamSizeMin">{{ activity.teamSizeMin }}</el-descriptions-item>
|
||||
<el-descriptions-item label="每队最大人数" v-if="activity.teamSizeMax">{{ activity.teamSizeMax }}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
|
||||
<el-row :gutter="20" v-if="activity.maxParticipants">
|
||||
<el-col :span="12">
|
||||
<div class="detail-item">
|
||||
<label class="detail-label">总人数上限</label>
|
||||
<div class="detail-value">{{ activity.maxParticipants }}</div>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-row :gutter="20" v-if="activity.maxTeams || activity.teamSizeMin || activity.teamSizeMax">
|
||||
<el-col :span="8" v-if="activity.maxTeams">
|
||||
<div class="detail-item">
|
||||
<label class="detail-label">团队数量上限</label>
|
||||
<div class="detail-value">{{ activity.maxTeams }}</div>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="8" v-if="activity.teamSizeMin">
|
||||
<div class="detail-item">
|
||||
<label class="detail-label">每队最小人数</label>
|
||||
<div class="detail-value">{{ activity.teamSizeMin }}</div>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="8" v-if="activity.teamSizeMax">
|
||||
<div class="detail-item">
|
||||
<label class="detail-label">每队最大人数</label>
|
||||
<div class="detail-value">{{ activity.teamSizeMax }}</div>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<div class="detail-item">
|
||||
<label class="detail-label">报名状态</label>
|
||||
<div class="detail-value">
|
||||
<dict-tag :options="stgl_registration_status" :value="activity.registrationStatus" />
|
||||
</div>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<div class="detail-item">
|
||||
<label class="detail-label">报名人数</label>
|
||||
<div class="detail-value">{{ activity.registrationCount || 0 }}</div>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<!-- 如果没有任何限制信息,显示提示 -->
|
||||
<div v-if="!activity.maxParticipants && !activity.maxTeams && !activity.teamSizeMin && !activity.teamSizeMax" class="no-limit-data">
|
||||
暂无人数限制设置
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
|
||||
<!-- 报名查看标签页 -->
|
||||
@@ -506,36 +335,149 @@ onMounted(() => {
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
/* 详情项样式 */
|
||||
.detail-item {
|
||||
/* el-descriptions组件相关样式 */
|
||||
.basic-info-section,
|
||||
.organizer-info-section,
|
||||
.registration-info-section,
|
||||
.registration-time-section,
|
||||
.registration-limit-section {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.detail-label {
|
||||
display: inline-block;
|
||||
width: 120px;
|
||||
color: #606266;
|
||||
font-weight: 500;
|
||||
font-size: 14px;
|
||||
margin-bottom: 8px;
|
||||
text-align: right;
|
||||
padding-right: 12px;
|
||||
/* 自定义宽度的报名信息表格 */
|
||||
.custom-width-registration :deep(.el-descriptions__table) {
|
||||
table-layout: fixed !important;
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
.custom-width-registration :deep(.el-descriptions__cell) {
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.detail-value {
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
width: calc(100% - 120px);
|
||||
color: #303133;
|
||||
font-size: 14px;
|
||||
line-height: 1.5;
|
||||
/* 强制设置标签和内容的宽度 */
|
||||
.custom-width-registration :deep(.el-descriptions__label) {
|
||||
width: 20% !important;
|
||||
min-width: 20% !important;
|
||||
}
|
||||
|
||||
.custom-width-registration :deep(.el-descriptions__content) {
|
||||
width: 30% !important;
|
||||
min-width: 30% !important;
|
||||
}
|
||||
|
||||
/* 自定义宽度的主办方信息表格 */
|
||||
.custom-width-organizer :deep(.el-descriptions__table) {
|
||||
table-layout: fixed !important;
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
.custom-width-organizer :deep(.el-descriptions__cell) {
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
/* 强制设置主办方信息标签和内容的宽度 */
|
||||
.custom-width-organizer :deep(.el-descriptions__label) {
|
||||
box-sizing: border-box !important;
|
||||
word-wrap: break-word !important;
|
||||
}
|
||||
|
||||
.custom-width-organizer :deep(.el-descriptions__content) {
|
||||
box-sizing: border-box !important;
|
||||
word-wrap: break-word !important;
|
||||
}
|
||||
|
||||
/* 主办方信息区域 - 具体宽度控制 */
|
||||
.custom-width-organizer :deep(.el-descriptions__table tr td:nth-child(1)) {
|
||||
width: 13% !important;
|
||||
}
|
||||
.custom-width-organizer :deep(.el-descriptions__table tr td:nth-child(2)) {
|
||||
width: 35% !important;
|
||||
}
|
||||
.custom-width-organizer :deep(.el-descriptions__table tr td:nth-child(3)) {
|
||||
width: 10% !important;
|
||||
}
|
||||
.custom-width-organizer :deep(.el-descriptions__table tr td:nth-child(4)) {
|
||||
width: 15% !important;
|
||||
}
|
||||
.custom-width-organizer :deep(.el-descriptions__table tr td:nth-child(5)) {
|
||||
width: 10% !important;
|
||||
}
|
||||
.custom-width-organizer :deep(.el-descriptions__table tr td:nth-child(6)) {
|
||||
width: 17% !important;
|
||||
}
|
||||
|
||||
/* 承办方信息区域 - 具体宽度控制 */
|
||||
.custom-width-co-organizer :deep(.el-descriptions__table tr td:nth-child(1)) {
|
||||
width: 12% !important;
|
||||
}
|
||||
.custom-width-co-organizer :deep(.el-descriptions__table tr td:nth-child(2)) {
|
||||
width: 36% !important;
|
||||
}
|
||||
.custom-width-co-organizer :deep(.el-descriptions__table tr td:nth-child(3)) {
|
||||
width: 10% !important;
|
||||
}
|
||||
.custom-width-co-organizer :deep(.el-descriptions__table tr td:nth-child(4)) {
|
||||
width: 16% !important;
|
||||
}
|
||||
.custom-width-co-organizer :deep(.el-descriptions__table tr td:nth-child(5)) {
|
||||
width: 10% !important;
|
||||
}
|
||||
.custom-width-co-organizer :deep(.el-descriptions__table tr td:nth-child(6)) {
|
||||
width: 16% !important;
|
||||
}
|
||||
|
||||
/* 自定义宽度的指导老师信息表格 */
|
||||
.custom-width-instructor :deep(.el-descriptions__table) {
|
||||
table-layout: fixed !important;
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
.custom-width-instructor :deep(.el-descriptions__cell) {
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
/* 强制设置指导老师信息标签和内容的宽度 */
|
||||
.custom-width-instructor :deep(.el-descriptions__label) {
|
||||
box-sizing: border-box !important;
|
||||
word-wrap: break-word !important;
|
||||
}
|
||||
|
||||
.custom-width-instructor :deep(.el-descriptions__content) {
|
||||
box-sizing: border-box !important;
|
||||
word-wrap: break-word !important;
|
||||
}
|
||||
|
||||
/* 指导老师信息区域 - 具体宽度控制 (8+15+8+17+8+15+8+17) */
|
||||
.custom-width-instructor :deep(.el-descriptions__table tr td:nth-child(1)) {
|
||||
width: 8% !important;
|
||||
}
|
||||
.custom-width-instructor :deep(.el-descriptions__table tr td:nth-child(2)) {
|
||||
width: 15% !important;
|
||||
}
|
||||
.custom-width-instructor :deep(.el-descriptions__table tr td:nth-child(3)) {
|
||||
width: 8% !important;
|
||||
}
|
||||
.custom-width-instructor :deep(.el-descriptions__table tr td:nth-child(4)) {
|
||||
width: 17% !important;
|
||||
}
|
||||
.custom-width-instructor :deep(.el-descriptions__table tr td:nth-child(5)) {
|
||||
width: 8% !important;
|
||||
}
|
||||
.custom-width-instructor :deep(.el-descriptions__table tr td:nth-child(6)) {
|
||||
width: 15% !important;
|
||||
}
|
||||
.custom-width-instructor :deep(.el-descriptions__table tr td:nth-child(7)) {
|
||||
width: 8% !important;
|
||||
}
|
||||
.custom-width-instructor :deep(.el-descriptions__table tr td:nth-child(8)) {
|
||||
width: 17% !important;
|
||||
}
|
||||
|
||||
/* 海报显示区域样式 */
|
||||
.view-poster {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
justify-content: center;
|
||||
padding: 20px 0;
|
||||
}
|
||||
|
||||
@@ -548,6 +490,7 @@ onMounted(() => {
|
||||
border: 1px dashed #dcdfe6;
|
||||
border-radius: 4px;
|
||||
background-color: #fafafa;
|
||||
margin: 20px auto;
|
||||
}
|
||||
|
||||
.no-poster-text {
|
||||
@@ -556,6 +499,7 @@ onMounted(() => {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* 描述文本区域样式 */
|
||||
.view-description {
|
||||
padding: 12px;
|
||||
border: 1px solid #e4e7ed;
|
||||
@@ -567,26 +511,12 @@ onMounted(() => {
|
||||
white-space: pre-wrap;
|
||||
word-break: break-word;
|
||||
background-color: #fafafa;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
/* 章节分隔样式 */
|
||||
.section-divider {
|
||||
margin: 24px 0 16px 0;
|
||||
padding-top: 16px;
|
||||
border-top: 1px solid #e4e7ed;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
margin: 0 0 16px 0;
|
||||
color: #303133;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
border-bottom: 2px solid #409eff;
|
||||
padding-bottom: 8px;
|
||||
}
|
||||
|
||||
/* 承办方项目样式 */
|
||||
.co-organizer-item {
|
||||
/* 承办方和指导老师项目样式 */
|
||||
.co-organizer-item,
|
||||
.instructor-item {
|
||||
margin-bottom: 16px;
|
||||
padding: 16px;
|
||||
background: #f8f9fa;
|
||||
@@ -594,24 +524,14 @@ onMounted(() => {
|
||||
border: 1px solid #e9ecef;
|
||||
}
|
||||
|
||||
.co-organizer-item:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
/* 指导老师项目样式 */
|
||||
.instructor-item {
|
||||
margin-bottom: 16px;
|
||||
padding: 16px;
|
||||
background: #fafafa;
|
||||
border-radius: 6px;
|
||||
border: 1px solid #ebeef5;
|
||||
}
|
||||
|
||||
.co-organizer-item:last-child,
|
||||
.instructor-item:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.no-data {
|
||||
/* 无数据提示样式 */
|
||||
.no-data,
|
||||
.no-limit-data {
|
||||
color: #909399;
|
||||
font-size: 13px;
|
||||
font-style: italic;
|
||||
@@ -620,10 +540,9 @@ onMounted(() => {
|
||||
background: #f8f9fa;
|
||||
border-radius: 4px;
|
||||
border: 1px solid #e9ecef;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* 附件显示区域样式 */
|
||||
.attachment-list {
|
||||
display: flex;
|
||||
@@ -647,4 +566,78 @@ onMounted(() => {
|
||||
.attachment-icon {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
/* el-divider样式优化 */
|
||||
:deep(.el-divider--horizontal) {
|
||||
margin: 24px 0 16px 0;
|
||||
}
|
||||
|
||||
:deep(.el-divider__text) {
|
||||
background-color: #fff;
|
||||
color: #303133;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
padding: 0 20px;
|
||||
}
|
||||
|
||||
/* el-descriptions样式优化 */
|
||||
:deep(.el-descriptions) {
|
||||
.el-descriptions__header {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.el-descriptions__title {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
.el-descriptions__body {
|
||||
.el-descriptions__table {
|
||||
.el-descriptions__cell {
|
||||
padding: 12px 16px;
|
||||
}
|
||||
|
||||
.el-descriptions__label {
|
||||
font-weight: 500;
|
||||
color: #606266;
|
||||
background-color: #fafafa;
|
||||
}
|
||||
|
||||
.el-descriptions__content {
|
||||
color: #303133;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 标签样式优化 */
|
||||
:deep(.el-tag) {
|
||||
border-radius: 4px;
|
||||
font-size: 12px;
|
||||
height: 24px;
|
||||
line-height: 22px;
|
||||
}
|
||||
|
||||
/* 响应式布局优化 */
|
||||
@media (max-width: 768px) {
|
||||
.activity-detail-view {
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
:deep(.el-descriptions) {
|
||||
.el-descriptions__body {
|
||||
.el-descriptions__table {
|
||||
.el-descriptions__cell {
|
||||
padding: 8px 12px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.co-organizer-item,
|
||||
.instructor-item {
|
||||
padding: 12px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -90,7 +90,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, onMounted } from 'vue';
|
||||
import { ref, computed, onMounted, watch } from 'vue';
|
||||
import { getActivityRatings } from '@/api/stgl/activity';
|
||||
import { ActivityRatingVO } from '@/api/stgl/activity/types';
|
||||
|
||||
@@ -146,19 +146,23 @@ const formatDateTimeCompact = (dateStr?: string): string => {
|
||||
|
||||
// 加载评分数据
|
||||
const loadRatings = async () => {
|
||||
if (!props.activityId) return;
|
||||
if (!props.activityId) {
|
||||
ratings.value = [];
|
||||
return;
|
||||
}
|
||||
|
||||
loading.value = true;
|
||||
try {
|
||||
console.log('开始加载活动评分数据,活动ID:', props.activityId);
|
||||
const res = await getActivityRatings(props.activityId);
|
||||
ratings.value = res.data || [];
|
||||
console.log('加载的评分数据:', ratings.value);
|
||||
console.log('成功加载评分数据,活动ID:', props.activityId, '评分数量:', ratings.value.length);
|
||||
} catch (error: any) {
|
||||
// 如果是404错误,说明后端暂未实现该功能,静默处理
|
||||
if (error.response?.status === 404) {
|
||||
console.log('活动评分功能暂未实现');
|
||||
console.log('活动评分功能暂未实现,活动ID:', props.activityId);
|
||||
} else {
|
||||
console.error('加载评分数据失败:', error);
|
||||
console.error('加载评分数据失败,活动ID:', props.activityId, '错误:', error);
|
||||
}
|
||||
ratings.value = [];
|
||||
} finally {
|
||||
@@ -166,9 +170,15 @@ const loadRatings = async () => {
|
||||
}
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
loadRatings();
|
||||
});
|
||||
// 监听 activityId 变化,自动重新加载评分数据
|
||||
watch(() => props.activityId, (newId, oldId) => {
|
||||
console.log('活动ID发生变化:', oldId, '->', newId);
|
||||
if (newId && newId !== oldId) {
|
||||
loadRatings();
|
||||
}
|
||||
}, { immediate: true }); // immediate: true 确保组件挂载时也会执行一次
|
||||
|
||||
// 移除 onMounted,因为 watch 的 immediate: true 已经覆盖了这个功能
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
@@ -321,7 +321,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { getCurrentInstance, onMounted, reactive, ref, toRefs } from 'vue';
|
||||
import { getCurrentInstance, onMounted, reactive, ref, toRefs, watch } from 'vue';
|
||||
import {
|
||||
listActivityRegister,
|
||||
getActivityRegister,
|
||||
@@ -507,6 +507,20 @@ const data = reactive<PageData<ExtendedActivityRegisterForm, StglActivityRegistr
|
||||
|
||||
const { queryParams, form, rules } = toRefs(data);
|
||||
|
||||
// 监听activityId变化,同步更新查询参数
|
||||
watch(() => props.activityId, (newActivityId) => {
|
||||
if (newActivityId) {
|
||||
console.log('RegisteredMembersTab: activityId发生变化,从', queryParams.value.activityId, '更新为', newActivityId);
|
||||
queryParams.value.activityId = newActivityId;
|
||||
// 重置分页到第一页
|
||||
queryParams.value.pageNum = 1;
|
||||
// 如果组件已经挂载,则立即重新查询
|
||||
if (memberList.value.length > 0 || loading.value === false) {
|
||||
getList();
|
||||
}
|
||||
}
|
||||
}, { immediate: true });
|
||||
|
||||
// 上传相关
|
||||
const uploadRef = ref<UploadInstance>();
|
||||
const upload = reactive<{
|
||||
@@ -529,8 +543,11 @@ const upload = reactive<{
|
||||
const getList = async () => {
|
||||
loading.value = true;
|
||||
try {
|
||||
// 构建查询参数,查询已审核通过的报名记录
|
||||
const queryData = { ...queryParams.value };
|
||||
// 构建查询参数,确保使用最新的activityId
|
||||
const queryData = {
|
||||
...queryParams.value,
|
||||
activityId: props.activityId // 强制使用最新的props值
|
||||
};
|
||||
|
||||
// 如果状态字段为空或未选择,则查询已通过(approvalStatus=1)的报名记录
|
||||
if (!queryData.approvalStatus) {
|
||||
@@ -538,6 +555,8 @@ const getList = async () => {
|
||||
}
|
||||
|
||||
console.log('RegisteredMembersTab: getList 开始查询,参数:', queryData);
|
||||
console.log('RegisteredMembersTab: props.activityId:', props.activityId);
|
||||
console.log('RegisteredMembersTab: queryParams.activityId:', queryParams.value.activityId);
|
||||
|
||||
const res = await listActivityRegister(queryData);
|
||||
console.log('RegisteredMembersTab: 查询结果:', res);
|
||||
@@ -560,7 +579,10 @@ const cancel = () => {
|
||||
|
||||
/** 表单重置 */
|
||||
const reset = () => {
|
||||
form.value = { ...initFormData, activityId: props.activityId };
|
||||
form.value = {
|
||||
...initFormData,
|
||||
activityId: props.activityId // 确保使用最新的activityId
|
||||
};
|
||||
memberFormRef.value?.resetFields();
|
||||
};
|
||||
|
||||
@@ -635,7 +657,7 @@ const submitForm = () => {
|
||||
const { selectedStudent, ...submitData } = form.value;
|
||||
|
||||
// 确保包含必要字段
|
||||
submitData.activityId = props.activityId;
|
||||
submitData.activityId = props.activityId; // 使用最新的activityId
|
||||
submitData.approvalStatus = 1; // 新增的报名默认为已通过状态
|
||||
|
||||
try {
|
||||
|
||||
@@ -61,8 +61,8 @@
|
||||
<dict-tag :options="stgl_activity_type" :value="scope.row.activityType" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="主办方" align="center" prop="organizerName" width="120" show-overflow-tooltip />
|
||||
<el-table-column label="关联社团/队伍" align="center" width="120" show-overflow-tooltip>
|
||||
<el-table-column label="主办方" align="center" prop="organizerName" min-width="150" show-overflow-tooltip />
|
||||
<el-table-column label="关联社团/队伍" align="center" min-width="150" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
<span v-if="scope.row.relatedClubName">{{ scope.row.relatedClubName }}</span>
|
||||
<span v-else class="text-gray-400">未关联</span>
|
||||
|
||||
@@ -84,13 +84,13 @@
|
||||
<el-col :span="1.5">
|
||||
<el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['stgl:activity:add']">新增</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5" v-if="!single && selectedActivity && ['0', '7', '6'].includes(selectedActivity.activityStatus) && hasActivityOperationPermission(selectedActivity)">
|
||||
<el-col :span="1.5" v-if="!single && selectedActivity && ['0', '7', '6'].includes(getOriginalActivityStatus(selectedActivity)) && hasActivityOperationPermission(selectedActivity)">
|
||||
<el-button icon="Edit" @click="handleUpdate()" v-hasPermi="['stgl:activity:edit']">修改</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5" v-if="!single && selectedActivity && selectedActivity.activityStatus === '0' && hasActivityOperationPermission(selectedActivity)">
|
||||
<el-col :span="1.5" v-if="!single && selectedActivity && getOriginalActivityStatus(selectedActivity) === '0' && hasActivityOperationPermission(selectedActivity)">
|
||||
<el-button type="success" icon="Upload" @click="handleSubmit()" v-hasPermi="['stgl:activity:edit']">提交</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5" v-if="!single && selectedActivity && selectedActivity.activityStatus === '2' && hasActivityOperationPermission(selectedActivity)">
|
||||
<el-col :span="1.5" v-if="!single && selectedActivity && getOriginalActivityStatus(selectedActivity) === '2' && hasActivityOperationPermission(selectedActivity)">
|
||||
<el-button type="warning" icon="Check" @click="handleApprove()" v-hasPermi="['stgl:activity:approve']">审批</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5" v-if="!single && selectedActivity && ['3', '4'].includes(selectedActivity.activityStatus) && hasActivityOperationPermission(selectedActivity)">
|
||||
@@ -102,10 +102,10 @@
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
icon="Delete"
|
||||
:disabled="multiple || !['0', '7'].includes(selectedActivity?.activityStatus || '')"
|
||||
:disabled="multiple || !['0', '7'].includes(getOriginalActivityStatus(selectedActivity) || '')"
|
||||
@click="handleDelete()"
|
||||
v-hasPermi="['stgl:activity:remove']"
|
||||
:title="selectedActivity && !['0', '7'].includes(selectedActivity.activityStatus) ? '只有草稿和已驳回状态的活动可以删除' : ''"
|
||||
:title="selectedActivity && !['0', '7'].includes(getOriginalActivityStatus(selectedActivity)) ? '只有草稿和已驳回状态的活动可以删除' : ''"
|
||||
>删除</el-button
|
||||
>
|
||||
</el-col>
|
||||
@@ -209,7 +209,7 @@
|
||||
v-hasPermi="['stgl:activity:query']"
|
||||
></el-button>
|
||||
</el-tooltip>
|
||||
<el-tooltip content="修改" placement="top" v-if="['0', '7', '6'].includes(scope.row.activityStatus) && hasActivityOperationPermission(scope.row)">
|
||||
<el-tooltip content="修改" placement="top" v-if="['0', '7', '6'].includes(getOriginalActivityStatus(scope.row)) && hasActivityOperationPermission(scope.row)">
|
||||
<el-button
|
||||
link
|
||||
type="primary"
|
||||
@@ -220,7 +220,7 @@
|
||||
v-hasPermi="['stgl:activity:edit']"
|
||||
></el-button>
|
||||
</el-tooltip>
|
||||
<el-tooltip content="提交" placement="top" v-if="scope.row.activityStatus === '0' && hasActivityOperationPermission(scope.row)">
|
||||
<el-tooltip content="提交" placement="top" v-if="getOriginalActivityStatus(scope.row) === '0' && hasActivityOperationPermission(scope.row)">
|
||||
<el-button
|
||||
link
|
||||
type="success"
|
||||
@@ -231,7 +231,7 @@
|
||||
v-hasPermi="['stgl:activity:edit']"
|
||||
></el-button>
|
||||
</el-tooltip>
|
||||
<el-tooltip content="审批" placement="top" v-if="scope.row.activityStatus === '2' && hasActivityOperationPermission(scope.row)">
|
||||
<el-tooltip content="审批" placement="top" v-if="getOriginalActivityStatus(scope.row) === '2' && hasActivityOperationPermission(scope.row)">
|
||||
<el-button
|
||||
link
|
||||
type="warning"
|
||||
@@ -286,7 +286,7 @@
|
||||
v-hasPermi="['stgl:activity:query']"
|
||||
></el-button>
|
||||
</el-tooltip>
|
||||
<el-tooltip content="删除" placement="top" v-if="['0', '7'].includes(scope.row.activityStatus) && hasActivityOperationPermission(scope.row)">
|
||||
<el-tooltip content="删除" placement="top" v-if="['0', '7'].includes(getOriginalActivityStatus(scope.row)) && hasActivityOperationPermission(scope.row)">
|
||||
<el-button
|
||||
link
|
||||
type="danger"
|
||||
@@ -1014,8 +1014,9 @@ const handleUpdate = async (row?: StglActivityVO) => {
|
||||
const res = await getStglActivity(_id);
|
||||
|
||||
// 检查活动状态是否允许修改(只有草稿0、已驳回7、已取消6状态允许修改)
|
||||
if (!['0', '7', '6'].includes(res.data.activityStatus)) {
|
||||
const statusDict = stgl_activity_status.value.find((dict: any) => dict.value === res.data.activityStatus);
|
||||
const originalStatus = getOriginalActivityStatus(res.data);
|
||||
if (!['0', '7', '6'].includes(originalStatus)) {
|
||||
const statusDict = stgl_activity_status.value.find((dict: any) => dict.value === originalStatus);
|
||||
const statusName = statusDict ? statusDict.label : '当前状态';
|
||||
proxy?.$modal.msgWarning(`活动状态为"${statusName}",不允许修改`);
|
||||
return;
|
||||
@@ -1276,8 +1277,9 @@ const handleDelete = async (row?: StglActivityVO) => {
|
||||
|
||||
// 检查删除权限 - 只有草稿(状态0)和已驳回(状态7)的活动可以删除
|
||||
if (row) {
|
||||
if (!['0', '7'].includes(row.activityStatus)) {
|
||||
const statusDict = stgl_activity_status.value.find((dict: any) => dict.value === row.activityStatus);
|
||||
const originalStatus = getOriginalActivityStatus(row);
|
||||
if (!['0', '7'].includes(originalStatus)) {
|
||||
const statusDict = stgl_activity_status.value.find((dict: any) => dict.value === originalStatus);
|
||||
const statusName = statusDict ? statusDict.label : '当前状态';
|
||||
proxy?.$modal.msgWarning(`活动状态为"${statusName}",只有草稿和已驳回状态的活动可以删除`);
|
||||
return;
|
||||
@@ -1287,7 +1289,7 @@ const handleDelete = async (row?: StglActivityVO) => {
|
||||
const selectedItems = activityList.value.filter((item) => ids.value.includes(item.id));
|
||||
|
||||
// 检查选中的活动是否都是草稿或已驳回状态
|
||||
const nonDeletableItems = selectedItems.filter((item) => !['0', '7'].includes(item.activityStatus));
|
||||
const nonDeletableItems = selectedItems.filter((item) => !['0', '7'].includes(getOriginalActivityStatus(item)));
|
||||
if (nonDeletableItems.length > 0) {
|
||||
const names = nonDeletableItems.map((item) => item.activityName).join('、');
|
||||
proxy?.$modal.msgWarning(`活动"${names}"不是草稿或已驳回状态,只有草稿和已驳回状态的活动可以删除`);
|
||||
@@ -1505,6 +1507,7 @@ const handleRegistrationTypeChange = (value: string) => {
|
||||
/** 判断是否显示总结按钮 */
|
||||
const shouldShowSummaryButton = (row: StglActivityVO): boolean => {
|
||||
// 只有进行中(4)和已结束(5)状态的活动才显示总结按钮
|
||||
// 注意:这里使用显示状态,因为总结功能应该基于活动的实际进行状态
|
||||
return row.activityStatus === '4' || row.activityStatus === '5';
|
||||
};
|
||||
|
||||
@@ -1716,6 +1719,13 @@ const hasActivityOperationPermission = (activity: StglActivityVO): boolean => {
|
||||
return false;
|
||||
};
|
||||
|
||||
/** 获取原始活动状态(用于权限控制) */
|
||||
const getOriginalActivityStatus = (activity: StglActivityVO | null): string => {
|
||||
if (!activity) return '';
|
||||
// 优先使用 originalActivityStatus 字段,如果不存在则使用 activityStatus
|
||||
return activity.originalActivityStatus || activity.activityStatus || '';
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
initUrlParams();
|
||||
getList();
|
||||
|
||||
@@ -479,10 +479,11 @@ const getList = async () => {
|
||||
|
||||
console.log('JoinedMembersTab: getList 开始查询,参数:', queryData);
|
||||
|
||||
// 如果状态字段为空或未选择,则查询已加入(status=2)和已退出(status=3)的成员
|
||||
// 已加入页面:查询已加入(status=2)和已退出(status=4)的成员
|
||||
// 字典配置:0-待审核,1-审核中,2-已加入,3-已驳回,4-已退出
|
||||
if (!queryData.status) {
|
||||
// 使用params传递多状态查询
|
||||
queryData.params = { ...queryData.params, statusList: ['2', '3'] } as any;
|
||||
queryData.params = { ...queryData.params, statusList: ['2', '4'] } as any;
|
||||
delete queryData.status; // 删除单个status字段
|
||||
}
|
||||
|
||||
|
||||
@@ -283,10 +283,11 @@ const getList = async () => {
|
||||
|
||||
console.log('PendingMembersTab: getList 开始查询,参数:', queryData);
|
||||
|
||||
// 如果状态字段为空或未选择,则查询待审核(status=0)和已驳回(status=4)的成员
|
||||
// 待审核页面:查询待审核(status=0)和已驳回(status=3)的成员
|
||||
// 字典配置:0-待审核,1-审核中,2-已加入,3-已驳回,4-已退出
|
||||
if (!queryData.status) {
|
||||
// 使用params传递多状态查询
|
||||
queryData.params = { ...queryData.params, statusList: ['0', '4'] } as any;
|
||||
queryData.params = { ...queryData.params, statusList: ['0', '3'] } as any;
|
||||
delete queryData.status; // 删除单个status字段
|
||||
}
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
|
||||
<el-table v-loading="loading" border :data="clubList" @row-dblclick="handleView">
|
||||
<el-table-column label="序号" type="index" align="center" width="60" />
|
||||
<el-table-column label="社团LOGO" align="center" width="80">
|
||||
<el-table-column label="社团LOGO" align="center" width="150">
|
||||
<template #default="scope">
|
||||
<div v-if="scope.row.logoUrl" class="table-image">
|
||||
<image-preview :src="scope.row.logoUrl" :width="50" :height="50" />
|
||||
@@ -56,35 +56,35 @@
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="社团名称" align="center" prop="clubName" min-width="150" show-overflow-tooltip />
|
||||
<el-table-column label="社团类型" align="center" prop="clubType" width="100">
|
||||
<el-table-column label="社团类型" align="center" prop="clubType" width="150">
|
||||
<template #default="scope">
|
||||
<dict-tag :options="stgl_club_type" :value="scope.row.clubType" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="我的角色" align="center" prop="myRole" width="100">
|
||||
<el-table-column label="我的角色" align="center" prop="myRole" width="140">
|
||||
<template #default="scope">
|
||||
<dict-tag :options="stgl_member_role" :value="scope.row.myRole" />
|
||||
<span class="role-text">{{ scope.row.myRole || '暂无' }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="社长姓名" align="center" prop="presidentName" width="100" show-overflow-tooltip />
|
||||
<el-table-column label="社长姓名" align="center" prop="presidentName" width="140" show-overflow-tooltip />
|
||||
<el-table-column label="指导老师" align="center" width="120" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
<span v-if="scope.row.advisorName">{{ scope.row.advisorName }}</span>
|
||||
<span v-else class="text-gray-400">暂无</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="成员数量" align="center" width="100">
|
||||
<el-table-column label="成员数量" align="center" width="140">
|
||||
<template #default="scope">
|
||||
<span class="member-count">{{ scope.row.memberCount || 0 }}</span>
|
||||
<span v-if="scope.row.memberLimit" class="member-limit">/ {{ scope.row.memberLimit }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="加入时间" align="center" width="180">
|
||||
<el-table-column label="加入时间" align="center" width="200">
|
||||
<template #default="scope">
|
||||
<span>{{ parseTime(scope.row.joinTime, '{y}-{m}-{d} {h}:{i}') }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="状态" align="center" prop="status" width="80">
|
||||
<el-table-column label="状态" align="center" prop="status" width="120">
|
||||
<template #default="scope">
|
||||
<dict-tag :options="sys_normal_disable" :value="scope.row.status" />
|
||||
</template>
|
||||
@@ -124,7 +124,7 @@
|
||||
<dict-tag :options="sys_normal_disable" :value="detailForm.status" />
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="我的角色">
|
||||
<dict-tag :options="stgl_member_role" :value="detailForm.myRole" />
|
||||
<span class="role-text">{{ detailForm.myRole || '暂无' }}</span>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="加入时间">{{ parseTime(detailForm.joinTime, '{y}-{m}-{d} {h}:{i}') }}</el-descriptions-item>
|
||||
<el-descriptions-item label="成员状态">
|
||||
@@ -166,8 +166,8 @@ import type { MyClubVO, MyClubQuery } from '@/api/stgl/my/types';
|
||||
import { UserFilled } from '@element-plus/icons-vue';
|
||||
|
||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||
const { stgl_club_type, sys_normal_disable, stgl_member_role, stgl_member_status } = toRefs<any>(
|
||||
proxy?.useDict('stgl_club_type', 'sys_normal_disable', 'stgl_member_role', 'stgl_member_status')
|
||||
const { stgl_club_type, sys_normal_disable, stgl_member_status } = toRefs<any>(
|
||||
proxy?.useDict('stgl_club_type', 'sys_normal_disable', 'stgl_member_status')
|
||||
);
|
||||
|
||||
const queryRef = ref();
|
||||
|
||||
@@ -16,15 +16,17 @@
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item label="审核状态" prop="approvalStatus">
|
||||
<el-select v-model="queryParams.approvalStatus" placeholder="请选择审核状态" clearable style="width: 100%">
|
||||
<el-option label="全部" value="" />
|
||||
<el-option label="待审核" value="待审核" />
|
||||
<el-option label="已通过" value="已通过" />
|
||||
<el-option label="已拒绝" value="已拒绝" />
|
||||
</el-select>
|
||||
<el-form-item label="名称" prop="name">
|
||||
<el-input
|
||||
v-model="queryParams.name"
|
||||
placeholder="请输入名称"
|
||||
clearable
|
||||
style="width: 100%"
|
||||
@keyup.enter="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
</el-row>
|
||||
|
||||
<el-row>
|
||||
@@ -69,13 +71,7 @@
|
||||
<span>{{ parseTime(scope.row.registrationTime, '{y}-{m}-{d} {h}:{i}') }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="审核状态" align="center" prop="approvalStatus" width="100">
|
||||
<template #default="scope">
|
||||
<el-tag :type="getApprovalStatusTag(scope.row.approvalStatus)" size="small">
|
||||
{{ scope.row.approvalStatus }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column label="当前状态" align="center" prop="currentStatus" width="100">
|
||||
<template #default="scope">
|
||||
<el-tag :type="getCurrentStatusTag(scope.row.currentStatus)" size="small">
|
||||
@@ -83,7 +79,7 @@
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="时间信息" align="center" width="180">
|
||||
<el-table-column label="创办时间" align="center" width="180">
|
||||
<template #default="scope">
|
||||
<span v-if="scope.row.timeInfo">
|
||||
{{ parseTime(scope.row.timeInfo, '{y}-{m}-{d} {h}:{i}') }}
|
||||
@@ -129,11 +125,7 @@
|
||||
<el-descriptions-item label="我的角色">{{ detailForm.role || '暂无' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="组织者">{{ detailForm.organizer || '暂无' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="报名时间">{{ parseTime(detailForm.registrationTime, '{y}-{m}-{d} {h}:{i}') }}</el-descriptions-item>
|
||||
<el-descriptions-item label="审核状态">
|
||||
<el-tag :type="getApprovalStatusTag(detailForm.approvalStatus)" size="small">
|
||||
{{ detailForm.approvalStatus }}
|
||||
</el-tag>
|
||||
</el-descriptions-item>
|
||||
|
||||
<el-descriptions-item label="当前状态">
|
||||
<el-tag :type="getCurrentStatusTag(detailForm.currentStatus)" size="small">
|
||||
{{ detailForm.currentStatus }}
|
||||
@@ -143,7 +135,7 @@
|
||||
{{ parseTime(detailForm.approvalTime, '{y}-{m}-{d} {h}:{i}') }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="审核人" v-if="detailForm.approvalBy">{{ detailForm.approvalBy }}</el-descriptions-item>
|
||||
<el-descriptions-item label="时间信息" v-if="detailForm.timeInfo">
|
||||
<el-descriptions-item label="创办时间" v-if="detailForm.timeInfo">
|
||||
{{ parseTime(detailForm.timeInfo, '{y}-{m}-{d} {h}:{i}') }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="地点" v-if="detailForm.location">{{ detailForm.location }}</el-descriptions-item>
|
||||
@@ -178,8 +170,8 @@ const queryFormRef = ref<ElFormInstance>();
|
||||
const queryParams = ref<MyRegistrationQuery>({
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
registrationType: '',
|
||||
approvalStatus: ''
|
||||
name: '',
|
||||
registrationType: ''
|
||||
});
|
||||
|
||||
/** 查询我的报名记录列表 */
|
||||
@@ -236,22 +228,22 @@ const getRegistrationTypeTag = (type: string) => {
|
||||
return tagMap[type as keyof typeof tagMap] || ('info' as const);
|
||||
};
|
||||
|
||||
/** 获取审核状态标签样式 */
|
||||
const getApprovalStatusTag = (status: string) => {
|
||||
const tagMap = {
|
||||
'已通过': 'success' as const,
|
||||
'已拒绝': 'danger' as const,
|
||||
'待审核': 'warning' as const
|
||||
};
|
||||
return tagMap[status as keyof typeof tagMap] || ('info' as const);
|
||||
};
|
||||
|
||||
|
||||
/** 获取当前状态标签样式 */
|
||||
const getCurrentStatusTag = (status: string) => {
|
||||
const tagMap = {
|
||||
// 成员状态
|
||||
'待审核': 'warning' as const,
|
||||
'审核中': 'info' as const,
|
||||
'已加入': 'success' as const,
|
||||
'已驳回': 'danger' as const,
|
||||
'已退出': 'danger' as const,
|
||||
// 活动审核状态
|
||||
'已通过': 'success' as const,
|
||||
// 兼容旧状态
|
||||
'正常': 'success' as const,
|
||||
'已报名': 'primary' as const,
|
||||
'待审核': 'warning' as const
|
||||
'已报名': 'primary' as const
|
||||
};
|
||||
return tagMap[status as keyof typeof tagMap] || ('info' as const);
|
||||
};
|
||||
|
||||
@@ -107,7 +107,7 @@
|
||||
<dict-tag :options="stgl_volunteer_role" :value="detailForm.myRole" />
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="成员状态">
|
||||
<dict-tag :options="stgl_volunteer_status" :value="detailForm.memberStatus" />
|
||||
<dict-tag :options="stgl_member_status" :value="detailForm.memberStatus" />
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="加入时间">{{ parseTime(detailForm.joinTime, '{y}-{m}-{d} {h}:{i}') }}</el-descriptions-item>
|
||||
<el-descriptions-item label="联系电话">{{ detailForm.contactPhone || '暂无' }}</el-descriptions-item>
|
||||
@@ -143,8 +143,8 @@ import type { MyVolunteerTeamVO, MyVolunteerQuery } from '@/api/stgl/my/types';
|
||||
import { User } from '@element-plus/icons-vue';
|
||||
|
||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||
const { sys_normal_disable, stgl_volunteer_role, stgl_volunteer_status } = toRefs<any>(
|
||||
proxy?.useDict('sys_normal_disable', 'stgl_volunteer_role', 'stgl_volunteer_status')
|
||||
const { sys_normal_disable, stgl_volunteer_role, stgl_member_status } = toRefs<any>(
|
||||
proxy?.useDict('sys_normal_disable', 'stgl_volunteer_role', 'stgl_member_status')
|
||||
);
|
||||
|
||||
const teamList = ref<MyVolunteerTeamVO[]>([]);
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
</el-row>
|
||||
</template>
|
||||
|
||||
<el-table v-loading="loading" border :data="studentList" @selection-change="handleSelectionChange" @row-dblclick="handleView">
|
||||
<el-table v-loading="loading" border :data="studentList" row-key="id" @selection-change="handleSelectionChange" @row-dblclick="handleView">
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column label="序号" type="index" width="60" align="center" />
|
||||
<el-table-column label="学生姓名" align="center" prop="studentName" min-width="40" />
|
||||
|
||||
@@ -48,6 +48,7 @@
|
||||
</span>
|
||||
</template>
|
||||
</el-tab-pane>
|
||||
<!--
|
||||
<el-tab-pane label="我的申请" name="my">
|
||||
<template #label>
|
||||
<span class="tab-label">
|
||||
@@ -56,6 +57,7 @@
|
||||
</span>
|
||||
</template>
|
||||
</el-tab-pane>
|
||||
-->
|
||||
</el-tabs>
|
||||
|
||||
<!-- 工具栏 -->
|
||||
@@ -520,6 +522,8 @@ function resetQuery() {
|
||||
function handleTabChange(tabName: string) {
|
||||
activeTab.value = tabName;
|
||||
queryParams.value.pageNum = 1;
|
||||
// 注释掉"我的申请"页签相关逻辑
|
||||
/*
|
||||
if (tabName === 'my') {
|
||||
// 切换到"我的申请"页签时,直接打开申请列表对话框
|
||||
handleMyApplications();
|
||||
@@ -531,6 +535,9 @@ function handleTabChange(tabName: string) {
|
||||
// 切换到"志愿者大厅"页签时,刷新队伍列表
|
||||
getList();
|
||||
}
|
||||
*/
|
||||
// 简化逻辑,只刷新队伍列表
|
||||
getList();
|
||||
}
|
||||
|
||||
/** 查看详情 */
|
||||
|
||||
@@ -91,7 +91,7 @@
|
||||
<el-button type="primary" :disabled="multiple" @click="handleBatchApplyBed()"> 批量申请床位 </el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button type="danger" :disabled="multiple" @click="handleBatchCancelBed()"> 批量取消床位 </el-button>
|
||||
<el-button type="danger" :disabled="multiple" @click="handleBatchCancelBed()"> 批量取消床位申请 </el-button>
|
||||
</el-col>
|
||||
<!-- <el-col :span="1.5">
|
||||
<el-button :disabled="multiple" icon="Delete" @click="handleDelete()"> 删除 </el-button>
|
||||
@@ -2285,7 +2285,7 @@ const resetQuery = () => {
|
||||
/** 删除按钮操作 */
|
||||
const handleDelete = async (row?: StudentVO) => {
|
||||
const studentIds = row?.id || ids.value;
|
||||
const [err] = await to(ElMessageBox.confirm('是否确认删除学生编号为"' + row?.name + '"的数据项?', '提示'));
|
||||
const [err] = await to(ElMessageBox.confirm('是否确认删除学生姓名为"' + row?.name + '"的数据项?', '提示'));
|
||||
if (!err) {
|
||||
try {
|
||||
const res = await service.delete(`/studentMsg/studentMsg/${studentIds}`);
|
||||
@@ -2342,23 +2342,93 @@ const handleBatchCancelBed = async () => {
|
||||
return;
|
||||
}
|
||||
|
||||
// 获取选中学生的详细信息
|
||||
const selectedStudents = studentList.value.filter((student) => ids.value.includes(student.id));
|
||||
|
||||
// 分类学生:可以取消和不可以取消的
|
||||
const canCancelStudents: any[] = [];
|
||||
const cannotCancelStudents: any[] = [];
|
||||
|
||||
selectedStudents.forEach((student) => {
|
||||
// 检查学生是否已分配宿舍(宿舍楼栋、房间号、床位号任一不为空)
|
||||
const studentAny = student as any;
|
||||
const hasAssignedBed = studentAny.dormitoryBuilding || studentAny.dormitoryRoom || studentAny.extField1; // 床位号字段
|
||||
|
||||
if (hasAssignedBed) {
|
||||
cannotCancelStudents.push(student);
|
||||
} else {
|
||||
canCancelStudents.push(student);
|
||||
}
|
||||
});
|
||||
|
||||
// 构建确认消息
|
||||
let confirmMessage = '';
|
||||
|
||||
if (canCancelStudents.length > 0) {
|
||||
confirmMessage += `<div style="margin-bottom: 15px;">
|
||||
<strong style="color: #67c23a;">✅ 可以取消床位申请的学生 (${canCancelStudents.length}人):</strong><br/>
|
||||
${canCancelStudents.map((student) => `• ${student.name} (${student.studentNo})`).join('<br/>')}
|
||||
</div>`;
|
||||
}
|
||||
|
||||
if (cannotCancelStudents.length > 0) {
|
||||
confirmMessage += `<div style="margin-bottom: 15px;">
|
||||
<strong style="color: #f56c6c;">❌ 无法取消床位申请的学生 (${cannotCancelStudents.length}人):</strong><br/>
|
||||
${cannotCancelStudents.map((student) => `• ${student.name} (${student.studentNo}) - 已分配宿舍`).join('<br/>')}
|
||||
</div>`;
|
||||
}
|
||||
|
||||
// 如果没有学生可以取消,直接提示
|
||||
if (canCancelStudents.length === 0) {
|
||||
ElMessage.warning('选中的学生都已分配宿舍,无法取消床位申请');
|
||||
return;
|
||||
}
|
||||
|
||||
// 显示确认对话框
|
||||
const [err] = await to(
|
||||
ElMessageBox.confirm('请确认是否取消,会将学生已有宿舍清除!!!', '批量取消床位', {
|
||||
confirmButtonText: '确认取消',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning',
|
||||
dangerouslyUseHTMLString: true
|
||||
})
|
||||
ElMessageBox.confirm(
|
||||
`<div style="text-align: left; max-height: 400px; overflow-y: auto;">
|
||||
<div style="margin-bottom: 15px; font-size: 14px;">
|
||||
<strong>批量取消床位申请确认</strong><br/>
|
||||
系统将只对未分配宿舍的学生执行取消床位申请操作。
|
||||
</div>
|
||||
${confirmMessage}
|
||||
<div style="margin-top: 15px; padding: 10px; background-color: #f0f9ff; border-left: 4px solid #409eff; border-radius: 4px;">
|
||||
<strong>操作说明:</strong><br/>
|
||||
• 已分配宿舍的学生将被跳过<br/>
|
||||
• 仅对未分配宿舍的学生执行取消操作<br/>
|
||||
• 确认后将无法撤销此操作
|
||||
</div>
|
||||
</div>`,
|
||||
'批量取消床位申请',
|
||||
{
|
||||
confirmButtonText: '确认取消',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning',
|
||||
dangerouslyUseHTMLString: true,
|
||||
customClass: 'batch-cancel-bed-dialog'
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
if (!err) {
|
||||
try {
|
||||
// 只对可以取消的学生执行操作
|
||||
const allowedStudentIds = canCancelStudents.map((student) => student.id);
|
||||
|
||||
const res = await service.post('/studentMsg/studentMsg/batchCancelBed', {
|
||||
studentIds: ids.value
|
||||
studentIds: allowedStudentIds
|
||||
});
|
||||
|
||||
if (res && res.code === 200) {
|
||||
await getList();
|
||||
ElMessage.success('批量取消床位成功');
|
||||
|
||||
// 根据操作结果给出不同的提示
|
||||
if (cannotCancelStudents.length > 0) {
|
||||
ElMessage.success(`批量取消床位成功!成功取消 ${canCancelStudents.length} 名学生,跳过 ${cannotCancelStudents.length} 名已分配宿舍的学生`);
|
||||
} else {
|
||||
ElMessage.success('批量取消床位成功');
|
||||
}
|
||||
} else {
|
||||
ElMessage.error(res?.msg || '批量取消床位失败');
|
||||
}
|
||||
@@ -2652,7 +2722,7 @@ const handleAdd = async () => {
|
||||
form.majorName = classData.major_name || classData.majorName;
|
||||
// 确保学历层次为数字类型,避免类型不匹配导致的显示问题
|
||||
const classType = classData.class_type || classData.classType;
|
||||
form.academicLevel = classType ? Number(classType) : undefined;
|
||||
form.academicLevel = classType ? classType : undefined;
|
||||
form.grade = classData.grade;
|
||||
form.enrollmentYear = classData.enrollment_year || classData.enrollmentYear;
|
||||
form.classTeacherId = classData.class_teacher_id || classData.classTeacherId;
|
||||
@@ -3154,4 +3224,26 @@ onMounted(() => {
|
||||
:deep(.el-message) {
|
||||
z-index: 4000 !important;
|
||||
}
|
||||
|
||||
/* 批量取消床位申请确认对话框样式 */
|
||||
:deep(.batch-cancel-bed-dialog) {
|
||||
max-width: 600px !important;
|
||||
}
|
||||
|
||||
:deep(.batch-cancel-bed-dialog .el-message-box__content) {
|
||||
max-height: 500px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
:deep(.batch-cancel-bed-dialog .el-message-box__message) {
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
:deep(.batch-cancel-bed-dialog .el-message-box__message div) {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
:deep(.batch-cancel-bed-dialog .el-message-box__message strong) {
|
||||
font-weight: 600;
|
||||
}
|
||||
</style>
|
||||
Reference in new issue
Block a user