Files
hzdyjs/mobile/src/pages/xgss/jqzs/apply.vue
T

371 lines
13 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="page-container">
<u-navbar title="申请假期留宿" :border-bottom="false" bg-color="#3c9cff" title-color="#fff">
<view slot="left" @click="goBack">
<u-icon name="arrow-left" color="#fff" size="22"></u-icon>
</view>
</u-navbar>
<view class="form-wrap">
<view class="dorm-card">
<view class="dorm-title">当前宿舍(自动带出)</view>
<view v-if="dormLoading" class="dorm-text">加载中...</view>
<view v-else-if="dormText" class="dorm-text">{{ dormText }}</view>
<view v-else class="dorm-text dorm-warn">未查询到在住床位,请先完成宿舍床位分配后再申请</view>
</view>
<u-form :model="form" ref="formRef" label-width="90">
<u-form-item label="假期类型" prop="holidayType" required>
<view @click="openHolidayPicker" style="width: 100%">
<u-input
v-model="holidayTypeLabel"
placeholder="请选择假期类型"
readonly
border="none"
suffix-icon="arrow-down"
suffix-icon-style="color: #c8c9cc;"
style="pointer-events: none"
/>
</view>
</u-form-item>
<u-form-item label="开始时间" prop="applyStartDate" required>
<view @click="openDate('start')" style="width: 100%">
<u-input
v-model="form.applyStartDate"
placeholder="请选择开始时间"
readonly
border="none"
suffix-icon="arrow-down"
suffix-icon-style="color: #c8c9cc;"
style="pointer-events: none"
/>
</view>
</u-form-item>
<u-form-item label="结束时间" prop="applyEndDate" required>
<view @click="openDate('end')" style="width: 100%">
<u-input
v-model="form.applyEndDate"
placeholder="请选择结束时间"
readonly
border="none"
suffix-icon="arrow-down"
suffix-icon-style="color: #c8c9cc;"
style="pointer-events: none"
/>
</view>
</u-form-item>
<u-form-item label="原因类型" prop="stayReasonType">
<view @click="openReasonPicker" style="width: 100%">
<u-input
v-model="stayReasonTypeLabel"
placeholder="请选择原因类型"
readonly
border="none"
suffix-icon="arrow-down"
suffix-icon-style="color: #c8c9cc;"
style="pointer-events: none"
/>
</view>
</u-form-item>
<u-form-item label="留宿原因" prop="stayReason" required>
<u-textarea
v-model="form.stayReason"
placeholder="请填写留宿原因"
maxlength="500"
count
></u-textarea>
</u-form-item>
<u-form-item label="联系电话" prop="studentPhone">
<u-input v-model="form.studentPhone" placeholder="可自动带出,可修改" />
</u-form-item>
<u-form-item label="紧急联系人" prop="emergencyContact">
<u-input v-model="form.emergencyContact" placeholder="请输入紧急联系人" />
</u-form-item>
<u-form-item label="紧急电话" prop="emergencyPhone">
<u-input v-model="form.emergencyPhone" placeholder="请输入紧急联系电话" />
</u-form-item>
<u-form-item label="家长同意" prop="parentConsent">
<u-radio-group v-model="form.parentConsent" class="radio-group">
<u-radio label="1" name="1" class="radio-item">是</u-radio>
<u-radio label="0" name="0" class="radio-item">否</u-radio>
</u-radio-group>
</u-form-item>
<u-form-item label="备注" prop="remark">
<u-textarea v-model="form.remark" placeholder="选填" maxlength="200"></u-textarea>
</u-form-item>
</u-form>
<u-button type="primary" :loading="submitting" text="提交申请" @click="submit"></u-button>
<view class="tip">提交后由班主任一级审批;宿舍信息将按当前入住床位自动带出。</view>
</view>
<u-picker
:show="showHolidayPicker"
:columns="holidayColumns"
keyName="label"
@confirm="onHolidayConfirm"
@cancel="showHolidayPicker = false"
@close="showHolidayPicker = false"
></u-picker>
<u-picker
:show="showReasonPicker"
:columns="reasonColumns"
keyName="label"
@confirm="onReasonConfirm"
@cancel="showReasonPicker = false"
@close="showReasonPicker = false"
></u-picker>
<u-datetime-picker
:show="showDatePicker"
v-model="dateValue"
mode="datetime"
@confirm="onDateConfirm"
@cancel="showDatePicker = false"
@close="showDatePicker = false"
></u-datetime-picker>
</view>
</template>
<script>
import { applyHolidayStay } from '@/api/holidayStay.js';
import { getDict } from '@/api/system/dict/data.js';
import { request } from '@/common/request.js';
export default {
data() {
return {
submitting: false,
showHolidayPicker: false,
showReasonPicker: false,
showDatePicker: false,
dateField: 'start',
dateValue: Number(new Date()),
holidayTypeDict: [],
stayReasonTypeDict: [],
holidayTypeLabel: '',
stayReasonTypeLabel: '',
dormLoading: false,
dormText: '',
hasDorm: false,
studentId: null,
form: {
holidayType: '',
applyStartDate: '',
applyEndDate: '',
stayReasonType: 'other',
stayReason: '',
studentPhone: '',
emergencyContact: '',
emergencyPhone: '',
parentConsent: '1',
remark: ''
}
};
},
computed: {
holidayColumns() {
return [this.holidayTypeDict || []];
},
reasonColumns() {
return [this.stayReasonTypeDict || []];
}
},
async onLoad() {
try {
this.holidayTypeDict = (await getDict('xg_holiday_type')) || [];
this.stayReasonTypeDict = (await getDict('xg_stay_reason_type')) || [];
const reason = this.stayReasonTypeDict.find((d) => String(d.value) === 'other');
if (reason) {
this.stayReasonTypeLabel = reason.label;
this.form.stayReasonType = reason.value;
}
const stuRes = await request({
url: '/studentMsg/studentMsg/currentUserInfo',
method: 'GET'
});
const stu = stuRes.data || stuRes;
if (stu && stu.phone) {
this.form.studentPhone = stu.phone;
}
if (stu && stu.id) {
this.studentId = stu.id;
await this.loadDormInfo(stu.id);
}
} catch (e) {
// ignore
}
},
methods: {
goBack() {
uni.navigateBack();
},
async loadDormInfo(studentId) {
this.dormLoading = true;
this.hasDorm = false;
this.dormText = '';
try {
const res = await request({
url: `/dormBedStudent/dormBedStudent/currentDormInfo/${studentId}`,
method: 'GET'
});
const dorm = res.data || res;
if (dorm && (dorm.roomId || dorm.bedId || dorm.buildingName || dorm.roomName)) {
const parts = [
dorm.campusName,
dorm.buildingName,
dorm.roomName || dorm.roomNo,
dorm.bedName || dorm.bedNo
].filter(Boolean);
this.dormText = parts.join(' / ');
this.hasDorm = !!(dorm.roomId && dorm.bedId);
}
} catch (e) {
this.dormText = '';
this.hasDorm = false;
} finally {
this.dormLoading = false;
}
},
openHolidayPicker() {
if (!this.holidayTypeDict.length) {
uni.showToast({ title: '假期类型加载中,请稍后', icon: 'none' });
return;
}
this.showHolidayPicker = true;
},
openReasonPicker() {
if (!this.stayReasonTypeDict.length) {
uni.showToast({ title: '原因类型加载中,请稍后', icon: 'none' });
return;
}
this.showReasonPicker = true;
},
openDate(field) {
this.dateField = field;
const current = field === 'start' ? this.form.applyStartDate : this.form.applyEndDate;
this.dateValue = current ? new Date(current.replace(/-/g, '/')).getTime() : Number(new Date());
this.showDatePicker = true;
},
onHolidayConfirm(e) {
const item = (e.value && e.value[0]) || null;
if (item) {
this.form.holidayType = item.value;
this.holidayTypeLabel = item.label;
}
this.showHolidayPicker = false;
},
onReasonConfirm(e) {
const item = (e.value && e.value[0]) || null;
if (item) {
this.form.stayReasonType = item.value;
this.stayReasonTypeLabel = item.label;
}
this.showReasonPicker = false;
},
onDateConfirm(e) {
const ts = e && e.value !== undefined ? e.value : e;
const d = new Date(Number(ts));
if (Number.isNaN(d.getTime())) {
this.showDatePicker = false;
return;
}
const pad = (n) => (n < 10 ? '0' + n : '' + n);
const str =
d.getFullYear() +
'-' +
pad(d.getMonth() + 1) +
'-' +
pad(d.getDate()) +
' ' +
pad(d.getHours()) +
':' +
pad(d.getMinutes()) +
':' +
pad(d.getSeconds());
if (this.dateField === 'start') {
this.form.applyStartDate = str;
} else {
this.form.applyEndDate = str;
}
this.showDatePicker = false;
},
async submit() {
if (!this.hasDorm) {
return uni.showToast({ title: '未分配宿舍床位,无法申请', icon: 'none' });
}
if (!this.form.holidayType) {
return uni.showToast({ title: '请选择假期类型', icon: 'none' });
}
if (!this.form.applyStartDate || !this.form.applyEndDate) {
return uni.showToast({ title: '请选择留宿时间', icon: 'none' });
}
if (!this.form.stayReason || !this.form.stayReason.trim()) {
return uni.showToast({ title: '请填写留宿原因', icon: 'none' });
}
this.submitting = true;
try {
await applyHolidayStay({ ...this.form });
uni.showToast({ title: '提交成功', icon: 'success' });
setTimeout(() => {
uni.navigateBack();
}, 500);
} catch (e) {
uni.showToast({ title: (e && e.msg) || '提交失败', icon: 'none' });
} finally {
this.submitting = false;
}
}
}
};
</script>
<style scoped>
.page-container {
min-height: 100vh;
background: #f5f6f8;
}
.form-wrap {
margin: 24rpx;
padding: 24rpx;
background: #fff;
border-radius: 16rpx;
}
.tip {
margin-top: 24rpx;
font-size: 24rpx;
color: #909399;
line-height: 1.5;
}
.dorm-card {
margin-bottom: 24rpx;
padding: 20rpx;
background: #f7f8fa;
border-radius: 12rpx;
}
.dorm-title {
font-size: 26rpx;
color: #909399;
margin-bottom: 8rpx;
}
.dorm-text {
font-size: 28rpx;
color: #303133;
}
.dorm-warn {
color: #e6a23c;
}
.radio-group {
display: flex;
align-items: center;
}
.radio-item {
margin-right: 32rpx;
}
</style>