diff --git a/backend/ruoyi-modules/ruoyi-jcbt/src/main/java/org/dromara/jcbt/controller/JcbtWorkStudyApplicationController.java b/backend/ruoyi-modules/ruoyi-jcbt/src/main/java/org/dromara/jcbt/controller/JcbtWorkStudyApplicationController.java index 35662e1e..458e3672 100644 --- a/backend/ruoyi-modules/ruoyi-jcbt/src/main/java/org/dromara/jcbt/controller/JcbtWorkStudyApplicationController.java +++ b/backend/ruoyi-modules/ruoyi-jcbt/src/main/java/org/dromara/jcbt/controller/JcbtWorkStudyApplicationController.java @@ -324,7 +324,6 @@ public class JcbtWorkStudyApplicationController extends BaseController { * 获取当前用户学生信息 */ @Operation(summary = "获取当前用户学生信息") - @SaCheckPermission("jcbt:workStudyApplication:query") @GetMapping("/currentStudentInfo") public R getCurrentStudentInfo() { try { diff --git a/mobile/src/api/workStudy.js b/mobile/src/api/workStudy.js index d6dda780..cb83cb48 100644 --- a/mobile/src/api/workStudy.js +++ b/mobile/src/api/workStudy.js @@ -131,3 +131,13 @@ export const updateApplication = (data) => { data: data }); }; + +/** + * 获取学生已申请岗位状态列表 + */ +export const getStudentApplicationStatusList = () => { + return request({ + url: '/jcbt/workStudyApplication/student/applicationStatus', + method: 'GET' + }); +}; diff --git a/mobile/src/pages/workStudy/apply.vue b/mobile/src/pages/workStudy/apply.vue index 7b6fbbce..99882682 100644 --- a/mobile/src/pages/workStudy/apply.vue +++ b/mobile/src/pages/workStudy/apply.vue @@ -113,19 +113,7 @@ /> - - - - - + @@ -137,14 +125,15 @@ prop="familyFinancialStatus" :required="true" > - - + - + - - - - + + @@ -293,7 +268,7 @@ export default { collegeName: '', majorName: '', className: '', - grade: '', + familyFinancialStatus: '', plannedWorkHours: '', applicationReason: '', @@ -302,17 +277,13 @@ export default { remark: '' }, - // 选择器显示状态 - showGradePicker: false, - showFinancialPicker: false, - - // 选择器文本 - gradeText: '', - financialText: '', - - // 选择器选项 - gradeOptions: [[]], - financialOptions: [[]], + // 家庭经济情况选项(与web端保持一致) + familyStatusOptions: [ + { value: '特困', label: '特困' }, + { value: '贫困', label: '贫困' }, + { value: '一般', label: '一般' }, + { value: '良好', label: '良好' } + ], // 加载状态 loading: false, @@ -348,8 +319,7 @@ export default { // 并行加载数据 const promises = [ this.loadPositionData(), - this.loadStudentInfo(), - this.loadApplicationOptions() + this.loadStudentInfo() ]; await Promise.all(promises); @@ -396,20 +366,6 @@ export default { } }, - // 加载申请选项 - async loadApplicationOptions() { - const response = await getApplicationOptions(); - if (response.code === 200) { - const options = response.data; - - // 设置年级选项 - this.gradeOptions = [options.gradeOptions || []]; - - // 设置家庭经济情况选项 - this.financialOptions = [options.familyFinancialStatusOptions || []]; - } - }, - // 加载申请详情(编辑模式) async loadApplicationDetail() { const response = await getApplicationDetail(this.applicationId); @@ -423,16 +379,16 @@ export default { } }); - // 设置选择器文本 - this.updatePickerTexts(); + } }, // 填充学生基本信息 fillStudentInfo() { if (this.studentInfo) { - this.formData.studentName = this.studentInfo.studentName || ''; - this.formData.studentNumber = this.studentInfo.studentNumber || ''; + // 修改字段映射以匹配后端返回的字段名 + this.formData.studentName = this.studentInfo.name || ''; // 修正:name + this.formData.studentNumber = this.studentInfo.studentNo || ''; // 修正:studentNo this.formData.collegeName = this.studentInfo.collegeName || ''; this.formData.majorName = this.studentInfo.majorName || ''; this.formData.className = this.studentInfo.className || ''; @@ -440,47 +396,12 @@ export default { // 如果是创建模式,填充其他基本信息 if (this.mode === 'create') { this.formData.idCard = this.studentInfo.idCard || ''; - this.formData.contactPhone = this.studentInfo.contactPhone || ''; - this.formData.grade = this.studentInfo.grade || ''; + this.formData.contactPhone = this.studentInfo.phone || ''; // 修正:phone + } - - this.updatePickerTexts(); } }, - // 更新选择器文本显示 - updatePickerTexts() { - // 更新年级文本 - if (this.formData.grade && this.gradeOptions[0].length > 0) { - const gradeOption = this.gradeOptions[0].find(item => item.value === this.formData.grade); - this.gradeText = gradeOption ? gradeOption.label : ''; - } - - // 更新家庭经济情况文本 - if (this.formData.familyFinancialStatus && this.financialOptions[0].length > 0) { - const financialOption = this.financialOptions[0].find(item => item.value === this.formData.familyFinancialStatus); - this.financialText = financialOption ? financialOption.label : ''; - } - }, - - // 年级选择确认 - onGradeConfirm(e) { - const index = e.indexs[0]; - const selected = this.gradeOptions[0][index]; - this.formData.grade = selected.value; - this.gradeText = selected.label; - this.showGradePicker = false; - }, - - // 家庭经济情况选择确认 - onFinancialConfirm(e) { - const index = e.indexs[0]; - const selected = this.financialOptions[0][index]; - this.formData.familyFinancialStatus = selected.value; - this.financialText = selected.label; - this.showFinancialPicker = false; - }, - // 表单验证 validateForm() { const requiredFields = [ diff --git a/mobile/src/pages/workStudy/index.vue b/mobile/src/pages/workStudy/index.vue index ef954759..06633c00 100644 --- a/mobile/src/pages/workStudy/index.vue +++ b/mobile/src/pages/workStudy/index.vue @@ -142,6 +142,11 @@ 有效期:{{ item.startDate }} 至 {{ item.endDate }} + + + + 我的申请:{{ getPositionApplicationStatus(item) }} + @@ -286,7 +291,8 @@ import { getAvailablePositions, getMyApplications, cancelApplication, - getCurrentStudentInfo + getCurrentStudentInfo, + getStudentApplicationStatusList } from '@/api/workStudy.js'; export default { @@ -354,7 +360,10 @@ export default { refreshing: false, // 用户信息 - studentInfo: null + studentInfo: null, + + // 学生申请状态列表(用于判断申请状态) + studentApplications: [] }; }, @@ -396,6 +405,8 @@ export default { try { // 获取学生信息 await this.loadStudentInfo(); + // 获取学生申请状态列表 + await this.loadStudentApplications(); // 加载岗位列表 await this.loadPositionList(true); } catch (error) { @@ -419,6 +430,18 @@ export default { } }, + // 加载学生申请状态列表 + async loadStudentApplications() { + try { + const response = await getStudentApplicationStatusList(); + if (response.code === 200) { + this.studentApplications = response.data || []; + } + } catch (error) { + console.error('获取申请状态失败:', error); + } + }, + // 加载岗位列表 async loadPositionList(reset = false) { if (this.loading) return; @@ -532,16 +555,21 @@ export default { }, // 刷新数据 - refreshData() { + async refreshData() { this.refreshing = true; - if (this.currentTab === 0) { - this.loadPositionList(true).finally(() => { - this.refreshing = false; - }); - } else { - this.loadMyApplications(true).finally(() => { - this.refreshing = false; - }); + try { + // 同时刷新学生申请状态 + await this.loadStudentApplications(); + + if (this.currentTab === 0) { + await this.loadPositionList(true); + } else { + await this.loadMyApplications(true); + } + } catch (error) { + console.error('刷新数据失败:', error); + } finally { + this.refreshing = false; } }, @@ -564,23 +592,45 @@ export default { }); }, - // 申请岗位 - handleApply(event, item) { - // 如果只传了一个参数,说明是从卡片点击调用的,第一个参数就是item - if (!item && typeof event === 'object' && event.id) { - item = event; + // 申请岗位(参考web端实现) + handleApply(event, position) { + // 如果只传了一个参数,说明是从卡片点击调用的,第一个参数就是position + if (!position && typeof event === 'object' && event.id) { + position = event; } - if (!this.canApply(item)) { + const application = this.studentApplications.find(app => app.positionId === position.id); + + // 如果已有申请且状态为已提交或审核中,跳转到申请管理页面 + if (application && ['submitted', 'college_reviewing', 'final_reviewing'].includes(application.status)) { + uni.switchTab({ + url: '/pages/workStudy/index' + }); + // 切换到"我的申请"标签页 + this.currentTab = 1; + this.onTabChange(1); + return; + } + + // 如果已录用,不允许操作 + if (application && application.status === 'approved') { uni.showToast({ - title: this.getApplyButtonText(item), + title: '您已被该岗位录用', + icon: 'none' + }); + return; + } + + if (!this.canApply(position)) { + uni.showToast({ + title: '该岗位当前不可申请', icon: 'none' }); return; } uni.navigateTo({ - url: `/pages/workStudy/apply?positionId=${item.id}` + url: `/pages/workStudy/apply?positionId=${position.id}` }); }, @@ -661,53 +711,140 @@ export default { return typeMap[status] || 'default'; }, - // 判断是否可以申请 - canApply(item) { - return item.status === 'RECRUITING' && - (item.currentCount || 0) < (item.requiredCount || 0); + // 判断是否可以申请(完全参考web端实现) + canApply(position) { + const application = this.studentApplications.find(app => app.positionId === position.id); + + // 如果已录用,禁用按钮 + if (application && application.status === 'approved') { + return false; + } + + // 检查岗位状态 + if (!['PUBLISHED', 'RECRUITING'].includes(position.status || '')) { + return false; + } + + // 检查是否还有空缺 + const current = position.currentCount || 0; + const required = position.requiredCount || 0; + if (current >= required) { + return false; + } + + // 检查有效期 + if (position.endDate) { + const endDate = new Date(position.endDate); + if (endDate < new Date()) { + return false; + } + } + + return true; }, - // 获取申请按钮文字 - getApplyButtonText(item) { - if (item.status !== 'RECRUITING') { - return '暂不可申请'; + // 获取申请按钮文字(参考web端实现8种状态) + getApplyButtonText(position) { + const application = this.studentApplications.find(app => app.positionId === position.id); + + // 如果已录用 + if (application && application.status === 'approved') { + return '申请已通过'; } - if ((item.currentCount || 0) >= (item.requiredCount || 0)) { - return '已满员'; + + // 如果有申请且状态为审核中 + if (application && ['submitted', 'college_reviewing', 'final_reviewing'].includes(application.status)) { + return '申请审核中'; } - return '申请岗位'; + + // 如果被拒绝 + if (application && application.status === 'rejected') { + return '重新申请'; + } + + // 检查岗位状态 + if (!['PUBLISHED', 'RECRUITING'].includes(position.status || '')) { + if (position.status === 'EXPIRED') { + return '岗位已过期'; + } else if (position.status === 'SUSPENDED') { + return '岗位已暂停'; + } else if (position.status === 'CANCELLED') { + return '岗位已取消'; + } else { + return '暂不可申请'; + } + } + + // 检查是否还有空缺 + const current = position.currentCount || 0; + const required = position.requiredCount || 0; + if (current >= required) { + return '岗位已满员'; + } + + // 检查有效期 + if (position.endDate) { + const endDate = new Date(position.endDate); + if (endDate < new Date()) { + return '岗位已过期'; + } + } + + // 默认可申请 + return '申请此岗位'; }, - // 获取申请状态文字 + // 获取申请状态文字(与web端保持一致) getApplicationStatusText(item) { - const statusMap = { - 'DRAFT': '草稿', - 'SUBMITTED': '已提交', - 'COLLEGE_REVIEWING': '学院审核中', - 'COLLEGE_APPROVED': '学院审核通过', - 'COLLEGE_REJECTED': '学院审核未通过', - 'FINAL_REVIEWING': '学生处审核中', - 'FINAL_APPROVED': '审核通过', - 'FINAL_REJECTED': '审核未通过', - 'CANCELLED': '已撤销' - }; - return statusMap[item.status] || '未知状态'; + if (!item) return '未申请'; + + // 支持两种格式:web端的小写格式和移动端的大写格式 + const status = item.status ? item.status.toLowerCase() : ''; + + switch (status) { + case 'submitted': + case 'SUBMITTED': + return '已提交'; + case 'college_reviewing': + case 'COLLEGE_REVIEWING': + return '学院审核中'; + case 'final_reviewing': + case 'FINAL_REVIEWING': + return '学生处审核中'; + case 'approved': + case 'FINAL_APPROVED': + return '审核通过'; + case 'rejected': + case 'FINAL_REJECTED': + return '审核不通过'; + case 'cancelled': + case 'CANCELLED': + return '已撤销'; + case 'draft': + case 'DRAFT': + return '草稿'; + default: + return '未知状态'; + } }, - // 获取申请状态类型 + // 获取申请状态类型(与web端保持一致) getApplicationStatusType(item) { + if (!item) return 'default'; + + // 支持两种格式:web端的小写格式和移动端的大写格式 + const status = item.status ? item.status.toLowerCase() : ''; + const typeMap = { - 'DRAFT': 'info', - 'SUBMITTED': 'warning', - 'COLLEGE_REVIEWING': 'warning', - 'COLLEGE_APPROVED': 'success', - 'COLLEGE_REJECTED': 'error', - 'FINAL_REVIEWING': 'warning', - 'FINAL_APPROVED': 'success', - 'FINAL_REJECTED': 'error', - 'CANCELLED': 'info' + 'draft': 'info', + 'submitted': 'warning', + 'college_reviewing': 'warning', + 'final_reviewing': 'warning', + 'approved': 'success', + 'rejected': 'error', + 'cancelled': 'info' }; - return typeMap[item.status] || 'default'; + return typeMap[status] || 'default'; }, // 获取审核状态文字 @@ -720,9 +857,22 @@ export default { return statusMap[status] || '未知'; }, - // 判断是否可以撤销申请 + // 判断是否可以撤销申请(与web端保持一致) canCancelApplication(item) { - return ['DRAFT', 'SUBMITTED', 'COLLEGE_REVIEWING'].includes(item.status); + if (!item) return false; + + // 支持两种格式:web端的小写格式和移动端的大写格式 + const status = item.status ? item.status.toLowerCase() : ''; + return ['draft', 'submitted', 'college_reviewing'].includes(status) || + ['DRAFT', 'SUBMITTED', 'COLLEGE_REVIEWING'].includes(item.status); + }, + + // 获取岗位的申请状态(用于在岗位卡片中显示) + getPositionApplicationStatus(position) { + const application = this.studentApplications.find(app => app.positionId === position.id); + if (!application) return null; + + return this.getApplicationStatusText(application); } } }; diff --git a/web/src/views/jcbt/workstudy/Application/form.vue b/web/src/views/jcbt/workstudy/Application/form.vue index c38b3439..23092eb8 100644 --- a/web/src/views/jcbt/workstudy/Application/form.vue +++ b/web/src/views/jcbt/workstudy/Application/form.vue @@ -232,8 +232,6 @@ const initFormData = async () => { formData.positionId = props.position.id as number; formData.positionName = props.position.positionName || ''; formData.positionType = '勤工俭学'; // 默认类型 - // 使用学院名称作为工作地点 - formData.workLocation = props.position.collegeName || '待确定'; } try { diff --git a/web/src/views/jcbt/workstudy/Application/index.vue b/web/src/views/jcbt/workstudy/Application/index.vue index 6697ea19..f3ea20fa 100644 --- a/web/src/views/jcbt/workstudy/Application/index.vue +++ b/web/src/views/jcbt/workstudy/Application/index.vue @@ -156,8 +156,7 @@ - -
岗位详情页面开发中...
+ @@ -165,17 +164,12 @@ - -
申请表单页面开发中...
- + />
@@ -187,8 +181,8 @@ import { useRouter } from 'vue-router'; import { listVisiblePositions } from '@/api/jcbt/workStudyPosition'; import type { WorkStudyPositionVO } from '@/api/jcbt/workStudyPosition'; import { getStudentApplicationStatusList } from '@/api/jcbt/workStudyApplication'; -// import PositionDetail from './detail.vue'; -// import ApplicationForm from './form.vue'; +import PositionDetail from './detail.vue'; +import ApplicationForm from './form.vue'; const router = useRouter(); @@ -557,13 +551,11 @@ onMounted(() => { margin-bottom: 20px; } -:deep(.el-table__header) { - th { - background: linear-gradient(135deg, #fafbff 0%, #f8fafc 100%); - color: #303133; - font-weight: 600; - border-color: rgba(93, 135, 255, 0.1); - } +:deep(.el-table__header th) { + background: linear-gradient(135deg, #fafbff 0%, #f8fafc 100%); + color: #303133; + font-weight: 600; + border-color: rgba(93, 135, 255, 0.1); } :deep(.el-table__row:hover) { @@ -579,10 +571,10 @@ onMounted(() => { .number-display { font-weight: 600; color: rgb(93, 135, 255); +} - &.text-success { - color: rgb(19, 222, 185); - } +.number-display.text-success { + color: rgb(19, 222, 185); } .salary-info { @@ -591,10 +583,10 @@ onMounted(() => { gap: 4px; color: rgb(255, 174, 31); font-weight: 500; +} - .el-icon { - color: rgb(255, 174, 31); - } +.salary-info .el-icon { + color: rgb(255, 174, 31); } .date-range { @@ -602,17 +594,17 @@ onMounted(() => { flex-direction: column; gap: 2px; font-size: 12px; +} - .date-item { - color: #606266; - font-family: monospace; - } +.date-range .date-item { + color: #606266; + font-family: monospace; +} - .date-separator { - color: #909399; - text-align: center; - font-size: 10px; - } +.date-range .date-separator { + color: #909399; + text-align: center; + font-size: 10px; } .action-buttons {