Files
hzdyjs/mobile/src/pages/workStudy/apply.vue
T
2025-08-21 23:47:30 +08:00

744 lines
24 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<view class="apply-container">
<!-- 岗位信息卡片 -->
<view class="position-card" v-if="positionData">
<view class="card-title">申请岗位</view>
<view class="position-info">
<view class="position-name">{{ positionData.positionName }}</view>
<view class="position-detail">
<text>工作时间:{{ positionData.workTime }}</text>
<text>联系老师:{{ positionData.contactTeacher }}</text>
</view>
</view>
</view>
<!-- 申请表单 -->
<view class="form-container">
<u-form
:model="formData"
ref="form"
label-width="140"
label-position="left"
>
<!-- 基本信息 -->
<view class="form-section">
<view class="section-title">基本信息</view>
<u-form-item
label="学生姓名"
prop="studentName"
:required="true"
>
<u-input
v-model="formData.studentName"
placeholder="请输入学生姓名"
:disabled="true"
/>
</u-form-item>
<u-form-item
label="学号"
prop="studentNumber"
:required="true"
>
<u-input
v-model="formData.studentNumber"
placeholder="请输入学号"
:disabled="true"
/>
</u-form-item>
<u-form-item
label="身份证号"
prop="idCard"
:required="true"
>
<u-input
v-model="formData.idCard"
placeholder="请输入身份证号"
maxlength="18"
/>
</u-form-item>
<u-form-item
label="联系电话"
prop="contactPhone"
:required="true"
>
<u-input
v-model="formData.contactPhone"
placeholder="请输入联系电话"
maxlength="11"
/>
</u-form-item>
</view>
<!-- 学籍信息 -->
<view class="form-section">
<view class="section-title">学籍信息</view>
<u-form-item
label="学院名称"
prop="collegeName"
:required="true"
>
<u-input
v-model="formData.collegeName"
placeholder="学院名称"
:disabled="true"
/>
</u-form-item>
<u-form-item
label="专业名称"
prop="majorName"
:required="true"
>
<u-input
v-model="formData.majorName"
placeholder="专业名称"
:disabled="true"
/>
</u-form-item>
<u-form-item
label="班级名称"
prop="className"
:required="true"
>
<u-input
v-model="formData.className"
placeholder="班级名称"
:disabled="true"
/>
</u-form-item>
<u-form-item
label="年级"
prop="grade"
>
<view @click="showGradePicker = true">
<u-input
v-model="gradeText"
placeholder="请选择年级"
readonly
suffix-icon="arrow-down"
/>
</view>
</u-form-item>
</view>
<!-- 申请信息 -->
<view class="form-section">
<view class="section-title">申请信息</view>
<u-form-item
label="家庭经济情况"
prop="familyFinancialStatus"
:required="true"
>
<view @click="showFinancialPicker = true">
<u-input
v-model="financialText"
placeholder="请选择家庭经济情况"
readonly
suffix-icon="arrow-down"
/>
</view>
</u-form-item>
<u-form-item
label="计划工作时长"
prop="plannedWorkHours"
>
<u-input
v-model="formData.plannedWorkHours"
placeholder="请输入计划工作时长(小时/周)"
type="number"
/>
</u-form-item>
<u-form-item
label="申请理由"
prop="applicationReason"
:required="true"
>
<u-textarea
v-model="formData.applicationReason"
placeholder="请详细说明申请此岗位的理由"
:maxlength="500"
:show-word-limit="true"
height="200"
count
/>
</u-form-item>
<u-form-item
label="个人能力及经验"
prop="personalAbility"
:required="true"
>
<u-textarea
v-model="formData.personalAbility"
placeholder="请描述与岗位相关的个人能力和经验"
:maxlength="500"
:show-word-limit="true"
height="200"
count
/>
</u-form-item>
<u-form-item
label="时间安排"
prop="timeArrangement"
:required="true"
>
<u-textarea
v-model="formData.timeArrangement"
placeholder="请说明您的时间安排,确保能够胜任此岗位工作"
:maxlength="300"
:show-word-limit="true"
height="150"
count
/>
</u-form-item>
<u-form-item
label="备注"
prop="remark"
>
<u-textarea
v-model="formData.remark"
placeholder="其他需要说明的情况(选填)"
:maxlength="200"
:show-word-limit="true"
height="120"
count
/>
</u-form-item>
</view>
</u-form>
</view>
<!-- 底部操作按钮 -->
<view class="bottom-actions">
<u-button
type="default"
size="large"
@click="saveDraft"
:loading="saving"
style="margin-right: 20rpx;"
>
保存草稿
</u-button>
<u-button
type="primary"
size="large"
@click="submitApplication"
:loading="submitting"
>
提交申请
</u-button>
</view>
<!-- 年级选择器 -->
<u-picker
:show="showGradePicker"
:columns="gradeOptions"
keyName="label"
@confirm="onGradeConfirm"
@cancel="showGradePicker = false"
/>
<!-- 家庭经济情况选择器 -->
<u-picker
:show="showFinancialPicker"
:columns="financialOptions"
keyName="label"
@confirm="onFinancialConfirm"
@cancel="showFinancialPicker = false"
/>
<!-- 加载状态 -->
<u-loading-page :loading="loading" loading-text="加载中..." />
</view>
</template>
<script>
import {
getPositionWithApplicationStatus,
getCurrentStudentInfo,
getApplicationOptions,
addApplication,
updateApplication,
getApplicationDetail
} from '@/api/workStudy.js';
export default {
name: 'WorkStudyApply',
data() {
return {
positionId: '',
applicationId: '',
mode: 'create', // create 或 edit
positionData: null,
studentInfo: null,
// 表单数据
formData: {
studentName: '',
studentNumber: '',
idCard: '',
contactPhone: '',
collegeName: '',
majorName: '',
className: '',
grade: '',
familyFinancialStatus: '',
plannedWorkHours: '',
applicationReason: '',
personalAbility: '',
timeArrangement: '',
remark: ''
},
// 选择器显示状态
showGradePicker: false,
showFinancialPicker: false,
// 选择器文本
gradeText: '',
financialText: '',
// 选择器选项
gradeOptions: [[]],
financialOptions: [[]],
// 加载状态
loading: false,
saving: false,
submitting: false
};
},
onLoad(options) {
if (options.positionId) {
this.positionId = options.positionId;
this.applicationId = options.applicationId || '';
this.mode = options.mode || 'create';
this.initData();
} else {
uni.showToast({
title: '岗位ID不能为空',
icon: 'none'
});
setTimeout(() => {
uni.navigateBack();
}, 1500);
}
},
methods: {
// 初始化数据
async initData() {
this.loading = true;
try {
// 并行加载数据
const promises = [
this.loadPositionData(),
this.loadStudentInfo(),
this.loadApplicationOptions()
];
await Promise.all(promises);
// 如果是编辑模式,加载申请详情
if (this.mode === 'edit' && this.applicationId) {
await this.loadApplicationDetail();
}
// 填充学生基本信息
this.fillStudentInfo();
} catch (error) {
console.error('初始化数据失败:', error);
uni.showToast({
title: '加载数据失败',
icon: 'none'
});
setTimeout(() => {
uni.navigateBack();
}, 1500);
} finally {
this.loading = false;
}
},
// 加载岗位数据
async loadPositionData() {
const response = await getPositionWithApplicationStatus(this.positionId);
if (response.code === 200) {
this.positionData = response.data.position;
} else {
throw new Error(response.msg || '获取岗位信息失败');
}
},
// 加载学生信息
async loadStudentInfo() {
const response = await getCurrentStudentInfo();
if (response.code === 200) {
this.studentInfo = response.data;
} else {
throw new Error(response.msg || '获取学生信息失败');
}
},
// 加载申请选项
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);
if (response.code === 200) {
const data = response.data;
// 填充表单数据
Object.keys(this.formData).forEach(key => {
if (data[key] !== undefined) {
this.formData[key] = data[key];
}
});
// 设置选择器文本
this.updatePickerTexts();
}
},
// 填充学生基本信息
fillStudentInfo() {
if (this.studentInfo) {
this.formData.studentName = this.studentInfo.studentName || '';
this.formData.studentNumber = this.studentInfo.studentNumber || '';
this.formData.collegeName = this.studentInfo.collegeName || '';
this.formData.majorName = this.studentInfo.majorName || '';
this.formData.className = this.studentInfo.className || '';
// 如果是创建模式,填充其他基本信息
if (this.mode === 'create') {
this.formData.idCard = this.studentInfo.idCard || '';
this.formData.contactPhone = this.studentInfo.contactPhone || '';
this.formData.grade = this.studentInfo.grade || '';
}
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 = [
{ field: 'studentName', name: '学生姓名' },
{ field: 'studentNumber', name: '学号' },
{ field: 'idCard', name: '身份证号' },
{ field: 'contactPhone', name: '联系电话' },
{ field: 'collegeName', name: '学院名称' },
{ field: 'majorName', name: '专业名称' },
{ field: 'className', name: '班级名称' },
{ field: 'familyFinancialStatus', name: '家庭经济情况' },
{ field: 'applicationReason', name: '申请理由' },
{ field: 'personalAbility', name: '个人能力及经验' },
{ field: 'timeArrangement', name: '时间安排' }
];
for (const item of requiredFields) {
if (!this.formData[item.field] || this.formData[item.field].trim() === '') {
uni.showToast({
title: `请填写${item.name}`,
icon: 'none'
});
return false;
}
}
// 验证身份证号格式
if (this.formData.idCard && !/^[1-9]\d{5}(18|19|20)\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/.test(this.formData.idCard)) {
uni.showToast({
title: '身份证号格式不正确',
icon: 'none'
});
return false;
}
// 验证手机号格式
if (this.formData.contactPhone && !/^1[3-9]\d{9}$/.test(this.formData.contactPhone)) {
uni.showToast({
title: '手机号格式不正确',
icon: 'none'
});
return false;
}
return true;
},
// 保存草稿
async saveDraft(autoNavigate = true) {
if (!this.validateForm()) return false;
this.saving = true;
try {
const requestData = {
...this.formData,
positionId: this.positionId,
positionName: this.positionData.positionName,
positionType: this.positionData.positionType || ''
};
let response;
if (this.mode === 'edit' && this.applicationId) {
requestData.id = this.applicationId;
response = await updateApplication(requestData);
} else {
response = await addApplication(requestData);
}
if (response.code === 200) {
uni.showToast({
title: '保存成功',
icon: 'success'
});
if (autoNavigate) {
setTimeout(() => {
uni.navigateBack();
}, 1000);
}
return true;
} else {
throw new Error(response.msg || '保存失败');
}
} catch (error) {
console.error('保存草稿失败:', error);
uni.showToast({
title: error.message || '保存失败',
icon: 'none'
});
return false;
} finally {
this.saving = false;
}
},
// 提交申请
async submitApplication() {
if (!this.validateForm()) return;
try {
const { confirm } = await uni.showModal({
title: '确认提交',
content: '确定要提交申请吗?提交后将无法修改。',
showCancel: true
});
if (!confirm) return; // 用户取消
this.submitting = true;
// 先保存申请(不自动跳转)
const saveSuccess = await this.saveDraft(false);
if (saveSuccess) {
// 这里可以添加提交申请的逻辑
// 如果后端有单独的提交接口,可以调用
uni.showToast({
title: '提交成功',
icon: 'success'
});
setTimeout(() => {
uni.navigateBack();
}, 1000);
}
} catch (error) {
console.error('提交申请失败:', error);
uni.showToast({
title: error.message || '提交失败',
icon: 'none'
});
} finally {
this.submitting = false;
}
}
}
};
</script>
<style scoped>
.apply-container {
min-height: 100vh;
background-color: #f5f5f5;
padding-bottom: 120rpx; /* 为底部按钮留空间 */
}
.position-card {
background-color: #fff;
margin: 20rpx;
border-radius: 12rpx;
padding: 30rpx;
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
}
.card-title {
font-size: 32rpx;
font-weight: bold;
color: #333;
margin-bottom: 20rpx;
padding-bottom: 16rpx;
border-bottom: 1rpx solid #f0f0f0;
}
.position-info {
margin-top: 12rpx;
}
.position-name {
font-size: 30rpx;
font-weight: 500;
color: #1890ff;
margin-bottom: 12rpx;
}
.position-detail {
display: flex;
flex-direction: column;
gap: 8rpx;
}
.position-detail text {
font-size: 26rpx;
color: #666;
}
.form-container {
background-color: #fff;
margin: 20rpx;
border-radius: 12rpx;
padding: 30rpx;
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
}
.form-section {
margin-bottom: 40rpx;
}
.form-section:last-child {
margin-bottom: 0;
}
.section-title {
font-size: 30rpx;
font-weight: bold;
color: #333;
margin-bottom: 30rpx;
padding-bottom: 12rpx;
border-bottom: 2rpx solid #1890ff;
position: relative;
}
.section-title::after {
content: '';
position: absolute;
bottom: -2rpx;
left: 0;
width: 60rpx;
height: 2rpx;
background-color: #1890ff;
}
.bottom-actions {
position: fixed;
bottom: 0;
left: 0;
right: 0;
background-color: #fff;
padding: 20rpx 30rpx;
border-top: 1rpx solid #eee;
display: flex;
z-index: 100;
}
.bottom-actions .u-button {
flex: 1;
}
/* 覆盖uview样式 */
:deep(.u-form-item) {
margin-bottom: 30rpx;
}
:deep(.u-form-item__body__left__content__label) {
font-size: 28rpx;
color: #333;
font-weight: 500;
}
:deep(.u-input__content__field-wrapper__field) {
font-size: 28rpx;
}
:deep(.u-textarea__count) {
font-size: 24rpx;
color: #999;
}
</style>