YingXingAI/pages/my/BackApply/BackApply.vue

800 lines
23 KiB
Vue
Raw Normal View History

2025-06-30 14:43:02 +08:00
<template>
<view style="background-color: white; height: 100vh">
<u-navbar title="返校预约申请"></u-navbar>
<!-- 内容 -->
<scroll-view
scroll-y="true"
style="
height: calc(100vh - 240rpx);
width: 100%;
border-top: 1px solid #edf2fa;
background-color: #fff;
box-sizing: border-box;
"
>
<!-- 基础信息 -->
<view class="base-box">
<view class="item-line">
<text class="line-label"> 预约人</text>
<text class="line-value"> {{ baseMsg.name || "-" }} </text>
</view>
<view class="item-line">
<text class="line-label"> 学院专业</text>
<text class="line-value"> {{ baseMsg.college + "-" + baseMsg.major }} </text>
</view>
<view class="item-line">
<text class="line-label"> 学历层次</text>
<text class="line-value"> {{ baseMsg.educationStr || "-" }} </text>
</view>
<view class="item-line">
<text class="line-label"> 毕业年份</text>
<text class="line-value"> {{ baseMsg.endYear || "-" }} </text>
</view>
</view>
<!-- 表单 -->
<view class="form-box">
<!-- 返校日期 -->
<view class="item-date" @click="dateShowFn">
<text class="line-label must"> 返校日期</text>
<u-input
:custom-style="inputStyle"
type="text"
input-align="right"
:border="false"
v-model="formData.date"
@click.native="dateShowFn"
placeholder="请选择"
disabled
/>
<view class="img">
<image
style="width:15rpx; height: 25rpx; margin-left: 20rpx"
src="/static/common/img/row_right.png"
/>
</view>
<!-- 点击盒子 -->
<view class="input-mask"></view>
</view>
<!-- 提示 -->
<view class="item-tip" v-if="weekSet.length">
<text class="line-label"> 提示每周{{ dateTip }}暂停开放返校服务</text>
</view>
<!-- 车牌号 -->
<view class="item-line" style="border: none;">
<text class="line-label"> 车牌号</text>
<u-input
:custom-style="inputStyle"
type="text"
input-align="right"
:border="false"
maxlength="10"
v-model="formData.carNumber"
placeholder="如果车辆入校请务必填写"
/>
</view>
<!-- 联系电话 -->
<view class="item-line" style="border: none;">
<text class="line-label must"> 联系电话</text>
<u-input
:custom-style="inputStyle"
type="number"
input-align="right"
:border="false"
maxlength="20"
v-model="formData.phone"
placeholder="请输入"
/>
</view>
<!-- 随行人信息 -->
<view class="item-line">
<text class="line-label"> 随行人信息</text>
<text @click="addPersonFn" style="color: #3cb5fb"> 添加随行人 </text>
</view>
<!-- 动态随行人 -->
<view class="item-box">
<view class="item-for" v-for="(x, xIndex) in sxList" :key="xIndex">
<!-- 左侧内容 -->
<view class="for-left">
<view class="each">
<text class="must"> 随行人{{ xIndex + 1 }}</text>
<u-input
:custom-style="eachStyle"
type="text"
input-align="right"
:border="false"
maxlength="20"
v-model="x.name"
placeholder="请输入"
/>
</view>
<view class="each">
<text class="must"> 手机号</text>
<u-input
:custom-style="eachStyle"
type="number"
input-align="right"
:border="false"
maxlength="20"
v-model="x.phone"
placeholder="请输入"
/>
</view>
</view>
<!-- 右侧删除 -->
<view class="del">
<!-- <u-icon
@click="delFn(xIndex)"
name="trash"
color="#2799f6"
size="45"
></u-icon> -->
<image style="width: 32rpx;height: 32rpx;" src="/static/common/img/delete.svg" @click="delFn(xIndex)"></image>
</view>
</view>
</view>
<!-- 返校事由 -->
<view class="item-line">
<text class="line-label must"> 返校事由</text>
</view>
<view class="item-text">
<u-input
type="textarea"
height="200"
:border="false"
v-model="formData.retuenSchoolReason"
placeholder="请输入"
/>
</view>
<!-- 同意区域 -->
<view class="item-agree">
<view class="agree-left">
<u-checkbox-group>
<u-checkbox v-model="formData.checked"></u-checkbox>
</u-checkbox-group>
</view>
<view class="agree-right">{{ desc }}</view>
</view>
</view>
<view style="height: 50rpx"></view>
</scroll-view>
<!-- 按钮 -->
<view class="btn-box">
<u-button style="width: 80%" shape="circle" type="primary" @click="btnSubmitFn"
>提交</u-button
>
</view>
<u-top-tips ref="uTips" :navbar-height="50"></u-top-tips>
<!-- 选择日期范围 -->
<!-- date 单个日期范围 range 多个日期范围 min-date="" -->
<u-calendarWeek
max-year="2030"
min-year="2020"
max-date="2030"
:min-date="minDate"
:max-date="maxDate"
v-model="dateShow"
:filterWeek="weekSet"
:filterDate="filterDate"
mode="range"
@change="dateChangeFn"
></u-calendarWeek>
<u-toast ref="uToast" />
</view>
</template>
<script>
export default {
data() {
return {
// 表单
formData: {
carNumber: "", // 车牌号
phone: "", // 联系电话
checked: false, //是否同意
retuenSchoolReason: "", //返校事由
date: "", //返校日期
},
// 日期的值
dateList: [],
// 随行人
sxList: [
{
name: "",
phone: "",
},
],
// 选择日期
dateShow: false,
//
inputStyle: {
lineHeight: "90rpx",
height: "90rpx",
width: "400rpx",
},
eachStyle: {
lineHeight: "80rpx",
height: "80rpx",
width: "400rpx",
},
desc:
"本人承诺进校期间,遵守国家相关规律法规和校园管理相关规定,服从工作人员的指挥和管理",
// 基础信息
baseMsg: {
id: "",
name: "", //姓名
schoolName: "",
schoolLogo: "",
startYear: "", //入学年份
college: "", //学院
educationStr: "", //学历层次
major: "", //专业
endYear: "", //毕业年份
},
// 星期设置
weekSet: [],
// 已预约的日期 这里需要两个格式 2025-2-19 2025/2/19
filterDate:[],
// 选择日期提示
dateTip: "",
// 最小日期
minDate: "",
// 最大日期
maxDate: "",
};
},
async onLoad(e) {
await this.getSchoolFn();
// 获取返校设置
this.getSetFn();
// 获取已预约的日期
this.getFilterDate();
},
created() {},
methods: {
async getFilterDate(){
const req = {
// userId: this.vuex_user.id,
educationId: this.baseMsg.id,
}
// return
const res = await this.$u.apiList.GetDateTimeReturnApi(req);
console.log(res,'res--获取已预约日期')
// 截取一下
const result = res.map(x=>x.retuenSchoolTime.slice(0,10))
// 保存一份不去0的
this.filterDateSource = [...result];
// 去0 [2025-2-18]
const arr1 = result.map(x=>x.replace(/(?<=-)0/g, ''))
// 在生成一个 [2025/02/18]
const arr2 = arr1.map(x=>x.replaceAll('-','/'))
// 已预约的日期
this.filterDate = [...arr1,...arr2];
},
arrayToString(arr) {
let result = "";
const map = new Map([
[0, "周日"],
[1, "周一"],
[2, "周二"],
[3, "周三"],
[4, "周四"],
[5, "周五"],
[6, "周六"],
]);
arr.forEach((x) => {
if (map.has(x)) {
result += map.get(x) + "、";
}
});
return arr.length ? result.slice(0, result.length - 1) : result;
},
//获取返校设置
async getSetFn() {
const req = {
schoolId: this.baseMsg.schoolId,
}
const res = await this.$u.apiList.SelectInfoSetApi(req);
console.log(res, "res--");
let AllArr = [0, 1, 2, 3, 4, 5, 6];
// 星期设置
if (res.isDayOfWeek) {
let result = res.dayOfWeek.split(",").map((x) => Number(x));
this.weekSet = AllArr.filter((x) => {
return !result.includes(x);
});
// 处理tip提示
this.dateTip = this.arrayToString(this.weekSet);
}
// 限制选择日期
// 在用户需要提前几天申请预约
if (res.isBefore) {
const date = new Date();
date.setDate(date.getDate() + res.beforeDay);
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, "0");
const day = String(date.getDate()).padStart(2, "0");
this.minDate = `${year}-${month}-${day}`;
} else {
// 默认最小日期是今天
const date = new Date();
date.setDate(date.getDate());
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, "0");
const day = String(date.getDate()).padStart(2, "0");
this.minDate = `${year}-${month}-${day}`;
}
// 用户最大可选日期 默认180天
const dateRes = new Date();
// 在用户需要提前几天申请预约
let maxDay = res.isDayOfWeek ? res.returnSchoolDays : 180
dateRes.setDate(dateRes.getDate() + maxDay);
const year1 = dateRes.getFullYear();
const month1 = String(dateRes.getMonth() + 1).padStart(2, "0");
const day1 = String(dateRes.getDate()).padStart(2, "0");
this.maxDate = `${year1}-${month1}-${day1}`;
},
async getSchoolFn() {
const req = {
userId: this.vuex_user.id,
};
const res = await this.$u.apiList.MyEducations(req);
console.log(res, "res--");
const findRow = res.find((x) => x.isSelected === true);
if (!findRow) {
/* uni.showToast({
title: "未查询到当前教育经历",
icon: "none",
}); */
this.$refs.uToast.show({
title: "未查询到当前教育经历",
type: "error",
});
return;
}
Object.assign(this.baseMsg, findRow);
this.baseMsg.name = this.vuex_user.name;
},
// 添加随行人
addPersonFn() {
this.sxList.push({
name: "",
phone: "",
});
},
// 删除随行人
delFn(index) {
uni.showModal({
// title: "提示",
content: `确定删除随行人${index + 1}`,
success: (res) => {
if (res.confirm) {
this.sxList.splice(index, 1);
}
if (res.cancel) {
// console.log('用户点击取消');
}
},
});
},
// 选择日期
dateShowFn() {
this.dateShow = true;
},
// 日期change
dateChangeFn(e) {
console.log(e, "e--");
this.currentList = this.getDatesArray(e.startDate, e.endDate);
console.log(JSON.parse(JSON.stringify(this.currentList)),'this.currentList--1');
// 判断是否包含不可选中日期
let flag = this.currentList.some(function(x){
// 包含禁用的日期
if (this.disArr.includes(new Date(x).getDay())) {
return true;
}
// 包含已预约的日期
if(this.selectArr.includes(x)){
return true;
}
return false;
},{
disArr:this.weekSet, // 禁用的星期
selectArr:this.filterDateSource // 已预约的日期
})
// 过滤一下禁用的星期
// this.currentList = this.currentList.filter((x) => {
// // 当天的星期
// const dateWeek = new Date(x).getDay();
// // 包含禁用的星期过滤掉
// if (this.weekSet.includes(dateWeek)) {
// return false;
// }
// return true;
// });
// 过滤掉已预约的日期
// this.currentList = this.currentList.filter((x) => {
// if(this.filterDateSource.includes(x)){
// return false;
// }else{
// return true;
// }
// });
if(flag){
/* uni.showToast({
icon:'none',
title: `当前返校时间包含不可预约的日期,请重新选择!`,
duration: 2000,
}); */
this.$refs.uToast.show({
title: `当前返校时间包含不可预约的日期,请重新选择!`,
type: "error",
});
this.dateShow = true;
return
}
// 显示的值
this.formData.date = e.startDate + " ~ " + e.endDate;
console.log(JSON.parse(JSON.stringify(this.currentList)),'this.currentList--2');
// 处理成后端要的格式
this.dateList = this.currentList.map((x) => {
return {
time: x,
};
});
console.log(JSON.parse(JSON.stringify(this.dateList)),'this.dateList');
},
// 校验表单信息
validate() {
// 校验手机号的正则表达式
const phoneReg = /^[1][3-9][0-9]{9}$/;
return new Promise((resolve, reject) => {
// 校验返校日期
if (!this.formData.date) {
// this.$tips("返校日期不能为空", "error");
this.$refs.uToast.show({
title: "返校日期不能为空",
type: "error",
});
return reject(false);
}
// 校验联系电话
if (!this.formData.phone) {
// this.$tips("联系电话不能为空", "error");
this.$refs.uToast.show({
title: "联系电话不能为空",
type: "error",
});
return reject(false);
}
if (!phoneReg.test(this.formData.phone)) {
// this.$tips("联系电话格式不正确,请输入有效的手机号", "error");
this.$refs.uToast.show({
title: "联系电话格式不正确,请输入有效的手机号",
type: "error",
});
return reject(false);
}
// 校验随行人信息
if (this.sxList.length) {
for (let i = 0; i < this.sxList.length; i++) {
const item = this.sxList[i];
// 校验随行人名称
if (!item.name) {
// this.$tips(`随行人${i + 1}的名称不能为空`, "error");
this.$refs.uToast.show({
title: `随行人${i + 1}的名称不能为空`,
type: "error",
});
return reject(false);
}
// 校验随行人手机号
if (!item.phone) {
// this.$tips(`随行人${i + 1}的手机号不能为空`, "error");
this.$refs.uToast.show({
title: `随行人${i + 1}的手机号不能为空`,
type: "error",
});
return reject(false);
}
if (!phoneReg.test(item.phone)) {
// this.$tips(`随行人${i + 1}的手机号格式不正确,请输入有效的手机号`, "error");
this.$refs.uToast.show({
title: `随行人${i + 1}的手机号格式不正确,请输入有效的手机号`,
type: "error",
});
return reject(false);
}
}
}
// 校验返校事由
if (!this.formData.retuenSchoolReason) {
// this.$tips("返校事由不能为空", "error");
this.$refs.uToast.show({
title: "返校事由不能为空",
type: "error",
});
return reject(false);
}
resolve(true);
});
},
// 日期转换数组
getDatesArray(startDate, endDate) {
// 将输入的字符串转换为 Date 对象
const start = new Date(startDate);
const end = new Date(endDate);
// 创建一个用于存储结果的数组
let datesArray = [];
// 复制开始日期,以免修改原始对象
let currentDate = new Date(start);
// 使用循环从开始日期遍历到结束日期
while (currentDate <= end) {
// 将当前日期添加到数组中
// 使用 toISOString 方法去掉 T 后面的时间部分并去掉最后的 Z 和小数秒
datesArray.push(new Date(currentDate).toISOString().split("T")[0]);
// 增加一天
currentDate.setDate(currentDate.getDate() + 1);
}
return datesArray;
},
// 我要预约
async btnSubmitFn() {
const result = await this.validate().catch((e) => e);
console.log(result, "result");
if (!result) {
return;
}
// 校验是否勾选了同意
if (!this.formData.checked) {
return uni.showModal({
// title: "提示",
content: this.desc,
success: (res) => {
if (res.confirm) {
// 默认帮用户勾选上 提交
this.formData.checked = true;
this.submit();
}
if (res.cancel) {
// console.log('用户点击取消');
}
},
});
}
this.submit();
},
// 提交的函数
async submit() {
// this.$tips("开发中", "success");
const req = {
userId: this.vuex_user.id,
educationId: this.baseMsg.id,
carNumber: this.formData.carNumber, //车牌号
phone: String(this.formData.phone), //联系电话
retuenSchoolReason: this.formData.retuenSchoolReason, //返校事由
// 随行人
TogetherPersonDtoList: this.sxList.map((x, xIndex) => {
x.index = xIndex;
x.phone = String(x.phone);
return x;
}),
// 日期
TimeList: this.dateList,
};
const res = await this.$u.apiList.AddReturnSchoolApi(req).catch(e=>e);
console.log(res, "res---");
if (res?.succeed === false) {
/* uni.showToast({
icon:'none',
title: res.error || "提交失败",
duration: 2000,
}); */
this.$refs.uToast.show({
title: res.error || "提交失败",
type: "error",
});
return;
}
/* uni.showToast({
title: "提交成功",
duration: 2000,
}); */
this.$refs.uToast.show({
title: "提交成功",
type: "success",
});
setTimeout(() => {
// 返回上一页
/* this.$u.route({
url: "pages/my/BackSchool/BackSchool",
}); */
uni.navigateBack({
delta: 1
});
}, 1000);
},
},
};
</script>
<style lang="scss" scoped>
// 必填的样式
.must {
position: relative;
&::before {
content: "*";
color: red;
position: absolute;
top: -10rpx;
right: -17rpx;
transform: scale(0.8);
/* 相对于父元素的左上角定位 */
}
}
.body-box {
max-height: calc(100vh - 250rpx);
overflow-y: auto;
border: 1px solid red;
}
// 基础信息
.base-box {
background-color: white;
// 单行样式
.item-line {
text-align: left;
padding-left: 30rpx;
padding-right: 30rpx;
font-size: 30rpx;
line-height: 90rpx;
height: 90rpx;
display: flex;
justify-content: space-between;
border-bottom: 1px solid #f1f2f6;
.line-label {
// font-size: 30rpx;
color: black;
}
.line-value {
// font-weight: 700;
color: #969696;
}
}
}
// 表单
.form-box {
margin-top: 20rpx;
background-color: white;
// 返校日期
.item-date {
padding-left: 30rpx;
padding-right: 30rpx;
font-size: 30rpx;
line-height: 90rpx;
height: 90rpx;
display: flex;
position: relative;
.input-mask {
position: absolute;
width: 100%;
height: 90rpx;
// background-color: red;
}
.img {
display: flex;
align-items: center;
justify-content: center;
width: 30rpx;
// padding-right: 30rpx;
}
}
// 单行样式
.item-line {
text-align: left;
padding-left: 30rpx;
padding-right: 30rpx;
font-size: 30rpx;
line-height: 90rpx;
height: 90rpx;
display: flex;
justify-content: space-between;
border-bottom: 1px solid #f1f2f6;
.line-label {
// font-size: 30rpx;
color: black;
}
}
// 提示
.item-tip {
text-align: left;
padding-left: 30rpx;
padding-right: 30rpx;
padding-bottom: 10rpx;
font-size: 22rpx;
// line-height: 90rpx;
// height: 90rpx;
display: flex;
justify-content: space-between;
border-bottom: 1px solid #f1f2f6;
.line-label {
// font-size: 30rpx;
color: red;
}
}
// 随行人样式
.item-for {
background-color: #f7f6f9;
padding-left: 30rpx;
display: flex;
width: 100%;
border-bottom: 1px solid #e1e1e1 ;
.for-left {
// border: 1px solid blue;
width: calc(100% - 50rpx);
.each {
flex: 1;
display: flex;
justify-content: space-between;
line-height: 80rpx;
height: 80rpx;
padding-right: 30rpx;
}
}
.del {
// border: 1px solid red;
width: 40rpx;
display: flex;
justify-content: center;
align-items: center;
}
&:last-of-type{
border-bottom: none;
}
}
// 文本框
.item-text {
padding-left: 30rpx;
padding-right: 30rpx;
}
// 同意样式
.item-agree {
padding-left: 30rpx;
padding-right: 30rpx;
display: flex;
padding-bottom: 20rpx;
padding-top: 20rpx;
border-top: 1px solid #f1f2f6;
// margin-bottom: 50rpx;
// flex-wrap: wrap;
.agree-left {
width: 50rpx;
}
.agree-right {
color: black;
flex: 1;
}
}
}
// 按钮
.btn-box {
position: fixed;
width: 100%;
bottom: 0;
height: 150rpx;
border-top: 1px solid #f1f2f6;
display: flex;
align-items: center;
justify-content: center;
}
</style>