Files
zhxg_app_v1.0/pages/applyleave/editLeave.vue
2025-07-16 15:34:34 +08:00

864 lines
23 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="container" style="padding-bottom: 60px;">
<!--学号 -->
<view class="form-item">
<text class="label">学号</text>
<text class="uni-input">{{ stuInfo.stuNo }}</text>
</view>
<!--姓名 -->
<view class="form-item">
<text class="label">姓名</text>
<text class="uni-input">{{ stuInfo.studentName }}</text>
</view>
<!-- 性别 -->
<view class="form-item">
<text class="label">性别</text>
<text class="uni-input">{{ stuInfo.gender }}</text>
</view>
<!--院部 -->
<view class="form-item">
<text class="label">院部</text>
<text class="uni-input">{{ stuInfo.departmentName }}</text>
</view>
<!--班级 -->
<view class="form-item">
<text class="label">班级</text>
<text class="uni-input">{{ stuInfo.className }}</text>
</view>
<!--联系电话 -->
<view class="form-item">
<text class="label">联系电话</text>
<text class="uni-input">{{ stuInfo.phoneNumber }}</text>
</view>
<!--家长姓名 -->
<view class="form-item">
<text class="label">家长姓名</text>
<text class="uni-input">{{ stuInfo.fatherName }}</text>
</view>
<!--家长联系电话 -->
<view class="form-item">
<text class="label">家长联系电话</text>
<text class="uni-input">{{ stuInfo.fatherRelation }}</text>
</view>
<!-- 请假事由 -->
<view class="form-item">
<text class="label"> <text class="required">*</text> 请假事由</text>
<picker :range="politicalOptions" v-model="formData.selectedPoliticalIndex" @change="onPoliticalChange">
<view class="select">{{ politicalOptions[formData.selectedPoliticalIndex] || '请选择请假事由' }}</view>
</picker>
</view>
<!-- 请假事由说明 -->
<view class="form-text">
<text class="label"> <text class="required">*</text> 请假事由说明</text>
<view class="txt">
<uni-forms-item>
<uni-easyinput type="textarea" v-model="formData.deeds" maxlength="500" placeholder="输入请假事由说明" />
</uni-forms-item>
</view>
</view>
<!-- 请假时间 -->
<view class="form-item">
<text class="label"> <text class="required">*</text> 请假起始时间</text>
<view class="example-body">
<uni-datetime-picker @change="changeDate('start',$event)" returnType="timestamp" v-model="formData.single" />
</view>
</view>
<view class="form-item">
<text class="label"> <text class="required">*</text> 请假结束时间</text>
<view class="example-body">
<uni-datetime-picker @change="changeDate('end',$event)" returnType="timestamp" v-model="formData.endsingle" />
</view>
</view>
<!--请假天数 -->
<view class="form-item">
<text class="label"> <text class="required">*</text> 请假天数</text>
<input v-model="formData.dataNum" class="uni-input" focus placeholder="请输入请假天数 " />
</view>
<!-- 目的地 -->
<view class="form-item">
<text class="label"> <text class="required">*</text> 目的地</text>
<input v-model="formData.endAddress" class="uni-input" focus placeholder="请输入目的地 " />
</view>
<!--详细地址 -->
<view class="form-item">
<text class="label"><text class="required">*</text> 详细地址</text>
<input v-model="formData.address" class="uni-input" focus placeholder="请输入详细地址 " />
</view>
<!-- 是否离桂 -->
<view class="form-item">
<text class="label">是否离桂:</text>
<checkbox class="uni-input" :value="isLeaveGui!=null?isLeaveGui.toString():'0'" :checked="isLeaveGui==1?true:false"
@click="toggleLG" />
</view>
<!-- 上传佐证 -->
<view class="form-img">
<text class="label">上传佐证</text>
<view class="example-body">
<uni-file-picker @select="uploadEvidence" v-model="imgVals" @delete="onDelImg" :auto-upload="false"
limit="9"></uni-file-picker>
</view>
</view>
<!--协议 -->
<view class="form-item">
安全承诺书
<text class="labelsafe">广西水利电力职业技术学院安全承诺书
</text>
<label>
<checkbox :value="checkboxValue.toString()" @click="toggleCheckbox" />
</label>
</view>
<!-- 签名 -->
<view class="form-canvas">
<text class="label">手写签字</text>
<view class="sign-img" v-if="signImg!=''">
<image :src="signImg" mode=""></image>
<text @tap="signToggle">重新签名</text>
</view>
<view v-else class="sign" @tap="signToggle">
点击签名
</view>
</view>
<view class="form-item">
<text class="label">备注</text>
<input v-model="remark" class="uni-input" placeholder="请输入备注" />
</view>
<!-- 按钮 -->
<view class="btn" v-if="type!='task'">
<button style="background-color: red;" @click="clean">清除</button>
<button style="background-color: #fff; color: #4097FE;border: 1px solid #4097FE;" :disabled="isSubmitting" @click="save">保存</button>
<button :disabled="isSubmitting" @click="applyLeave()">提交申请</button>
</view>
<view class="btn" v-else>
<button style="width: 100%;" :disabled="isSubmitting" @tap="resubmitTask">重新提交</button>
</view>
<uni-popup ref="popup" background-color="#fff">
<view class="popup-content" style="height: 35vh;">
<liu-signature @change="uploadSign" bgColor="#e8e8e8" lineColor="#000" :width="700"></liu-signature>
</view>
</uni-popup>
<uni-popup class="safety-popup" :is-mask-click="false" ref="safetyPopup" background-color="#fff">
<view class="popup-content">
<view class="title">
请假承诺书
</view>
<view class="content">
<scroll-view scroll-y="true" style="height:300px;">
<view class="txt">
为进一步加强学生的安全教育和管理切实维护校园安全及校园秩序结合我校实际学生请假外出期间就以下安全事项作如下承诺:
<view>
1.严格遵守国家法律法规和公民道德行为规范健康文明生活不赌博不打架不从事非法传销活动不参与宗教迷信宣传等不造谣不传谣不信谣不做任何违法违纪行为自觉维护良好大学生形象
</view>
<view>2.自觉遵守学校规章制度在规定允许时间内出入校园按时返校离开宿舍时确认断电和锁好门窗保管好自己的贵重物品</view>
<view>
3.增强安全防范意识不轻信陌生人注意防骗防盗防抢防踩踏等保护人身换人财产安全不携带易燃易爆等危险品进入公共场所不在非吸烟区吸烟不乱扔烟头不私拉电线防范消防安全隐患不买不吃三无食品和野味确保饮食卫生安全
</view>
<view>4.增强安全保护意识,遵守交通规则乘坐合法正规营运车辆不到不明水域游泳戏水垂钓等</view>
<view>5.增强个人健康安全意识认真履行个人健康第一责任人责任自觉做好健康监测身体出现异常情况随时向辅导员和家长报告及时就医</view>
<view>6.主动与家长辅导员保持联系随时保持通讯畅通并如实告知自己的情况</view>
<view>7.本人承诺已经认真阅读并自愿遵守上述规定离校期间个人安全将由本人自行负责</view>
</view>
</scroll-view>
<view class="time" v-if="safetime>0">
请阅读{{safetime}}s承诺书
</view>
</view>
<view class="safety-btn">
<button :disabled="isDisabled" @tap="closeSafePopup">我知道了</button>
</view>
</view>
</uni-popup>
</view>
</template>
<script>
import uploadFile from "@/plugins/upload.js";
import {
baseUrl
} from "@/config.js";
import {
calculateDays,
convertToTimestamp
} from "@/utils/time-calculation.js"
import {
editApply,
getStuInfo,
commonUpload,
leaveSave,
leaveDetail,
addApply
} from "@/api/applyleave/applyleave.js";
import {
getLeaveApplicationByProcInsId,
complete
} from "@/api/task.js";
export default {
data() {
return {
isSubmitting: false, //表单提交标志位
isDisabled: true,
safetime: 5,
// 用户信息
stuInfo: {},
studID: "",
name: "",
courtyard: "",
sex: '',
classroom: "",
phone: "",
parent: "",
parentPhone: "",
selectedOptionIndex: -1, // 当前选中的奖项索引
politicalOptions: ['因病', '因事'], // 请假选项
beginData: '',
endData: "",
remark: "",
leave: ['是', '否'],
leaveIndex: -1,
url: "",
urltwo: "",
checkboxValue: 0,
//附件
attachmentFile: "",
signImg: "",
imgVals: [],
isLeaveGui: 0, //是否离桂
formData: {
selectedPoliticalIndex: "", // 当前选中的请假索引
deeds: "",
endsingle: "",
single: '',
dataNum: "",
endAddress: "",
address: "",
signFile: "",
}
};
},
created() {
},
onLoad(option) {
this.procInsId = option.id;
this.taskId = option.taskId
this.type = option.type;
if (option.type == 'task') {
this.getTaskDetail();
} else {
this.getLeaveDetail();
}
},
methods: {
toggleLG() {
this.isLeaveGui = this.isLeaveGui === 1 ? 0 : 1;
},
changeDate(type, e) {
this.formData.single = convertToTimestamp(this.formData.single);
this.formData.endsingle = convertToTimestamp(this.formData.endsingle);
if (type == "end") {
this.formData.endsingle = e;
if (this.formData.endsingle < this.formData.single) {
uni.showToast({
title: "时间不能早于请假开始时间",
icon: "none"
})
}
this.formData.dataNum = calculateDays(this.formData.single, this.formData.endsingle);
} else {
this.single = e;
if (this.formData.endsingle < this.formData.single) {
uni.showToast({
title: "起始时间不能晚于结束时间",
icon: "none"
})
}
this.formData.dataNum = calculateDays(this.formData.single, this.formData.endsingle);
}
},
getLeaveDetail() {
let sdata = this.procInsId;
leaveDetail(sdata).then(res => {
this.stuInfo = res.data;
this.formData.selectedPoliticalIndex = res.data.leaveType;
this.formData.deeds = res.data.reason;
this.formData.single = res.data.startDate;
this.formData.endsingle = res.data.endDate;
this.formData.dataNum = res.data.leaveDays;
this.formData.endAddress = res.data.destination;
this.formData.address = res.data.destinationDetails;
this.formData.signFile = res.data.applicantSignature;
this.attachmentFile = res.data.attachment;
this.signImg = baseUrl + res.data.applicantSignature;
this.remark = res.data.remark;
this.leaveApplicationId = res.data.leaveApplicationId;
this.isLeaveGui = res.data.leavingGx;
console.log(this.formData);
if (res.data.attachment != "" && res.data.attachment != null) {
let imgs = res.data.attachment.split(',');
this.imgVals = imgs.map(img => {
return {
url: baseUrl + img
};
})
}
})
},
getTaskDetail() {
getLeaveApplicationByProcInsId(this.procInsId).then(res => {
this.stuInfo = res.data;
this.formData.selectedPoliticalIndex = res.data.leaveType;
this.formData.deeds = res.data.reason;
this.formData.single = res.data.startDate;
this.formData.endsingle = res.data.endDate;
this.formData.dataNum = res.data.leaveDays;
this.formData.endAddress = res.data.destination;
this.formData.address = res.data.destinationDetails;
this.attachmentFile = res.data.attachment;
this.signImg = baseUrl + res.data.applicantSignature;
this.formData.signFile = res.data.applicantSignature;
this.remark = res.data.remark;
this.leaveApplicationId = res.data.leaveApplicationId;
this.isLeaveGui = res.data.leavingGx;
if (res.data.attachment != "" && res.data.attachment != null) {
let imgs = res.data.attachment.split(',');
this.imgVals = imgs.map(img => {
return {
url: baseUrl + img
};
})
}
})
},
// 提交申请
applyLeave() {
if (this.checkboxValue == 0) {
// 如果复选框未被选中,则不允许提交
uni.showToast({
title: "请勾选承诺书",
icon: "error"
});
return; // 阻止表单提交
}
if (this.signFile == '') {
// 如果复选框未被选中,则不允许提交
uni.showToast({
title: "请先进行签名",
icon: "error"
});
return; // 阻止表单提交
}
if (this.endsingle < this.single) {
uni.showToast({
title: "起始时间不能晚于结束时间",
icon: "none"
})
return; // 阻止表单提交
}
//表单非空校验
const requiredFields = [
'selectedPoliticalIndex',
'deeds',
'endsingle',
'single',
'dataNum',
'endAddress',
'address'
];
const emptyField = requiredFields.find(field => this.formData[field] === ""||this.formData[field] ==null);
if (emptyField) {
uni.showToast({
title: `请填写完必填字段`,
icon: "none"
})
return;
}
console.log(this.formData);
uni.showLoading({
title: "正在提交"
})
let data = {
applicantSignature: this.formData.signFile,
attachment: this.attachmentFile,
destination: this.formData.endAddress,
destinationDetails: this.formData.address,
startDate: this.formData.single,
endDate: this.formData.endsingle,
leaveDays: this.formData.dataNum,
leaveType: this.formData.selectedPoliticalIndex,
reason: this.formData.deeds,
remark: this.remark,
safetyPromise: 1,
leaveApplicationId: this.leaveApplicationId,
leavingGx:this.isLeaveGui
}
this.isSubmitting = true; // 设置为正在提交
if (this.type == "task") {
editApply(data).then(res => {
if (res.code == 200) {
let sData = {
taskId: this.taskId,
comment: "",
}
complete(sData).then(res => {
console.log(res);
if (res.code == 200) {
uni.hideLoading();
this.isSubmitting = false;
uni.navigateBack({
success: () => {
const pages = getCurrentPages();
if (pages.length > 0) {
const prevPage = pages[pages.length - 2]
if (prevPage && typeof prevPage.getList ===
'function') {
prevPage.handleChange(2);
console.log('刷新已办任务数据');
}
}
}
})
}
})
} else {
uni.showToast({
title: "提交失败,请先填写完整内容",
icon: "none"
});
}
});
} else {
addApply(data).then(res => {
if (res.code == 200) {
uni.showToast({
title: "提交成功",
icon: "success"
});
this.isSubmitting = false;
uni.navigateBack({
success: () => {
const pages = getCurrentPages();
if (pages.length > 0) {
const prevPage = pages[pages.length - 2]
if (prevPage && typeof prevPage.getLeaveList ===
'function') {
prevPage.getLeaveList();
}
}
}
})
} else {
uni.showToast({
title: "提交失败,请先填写完整内容",
icon: "none"
});
}
});
}
},
// 重新提交任务
resubmitTask() {
this.applyLeave();
},
//上传佐证
uploadEvidence(e) {
uploadFile('/common/upload', e.tempFilePaths[0]).then((res) => {
console.log(this.attachmentFile);
if (this.attachmentFile !== "") {
this.attachmentFile = this.attachmentFile + "," + JSON.parse(res).fileName;
} else {
this.attachmentFile = JSON.parse(res).fileName;
}
console.log(this.attachmentFile);
})
},
//删除已选图片
onDelImg(e) {
let newImgs = this.imgVals.filter(fileName => fileName.path !== e.tempFilePath);
newImgs = newImgs.map(img => img.url.replace(baseUrl, ''))
newImgs = newImgs.join(",");
this.attachmentFile = newImgs;
},
//上传签名
uploadSign(e) {
const blob = this.base64ToBlob(e);
const fileObj = new File([blob], 'signature', {
type: 'image/png'
});
const formData = new FormData();
formData.append("file", fileObj);
const formDataObj = this.formDataToObject(formData);
uploadFile('/common/upload', '', formDataObj).then((res) => {
this.formData.signFile = JSON.parse(res).fileName;
this.signImg = baseUrl + JSON.parse(res).fileName;
this.$refs.popup.close('center')
})
},
// onPickerChange(event) {
// this.selectedOptionIndex = event.detail.value;
// },
onPoliticalChange(event) {
this.formData.selectedPoliticalIndex = event.detail.value;
},
toggleCheckbox() {
// 切换 checkboxValue 的值
this.checkboxValue = this.checkboxValue === 1 ? 0 : 1;
if (this.checkboxValue) {
this.$refs.safetyPopup.open('center')
if (this.safetime > 0) {
const intervalId = setInterval(() => {
this.safetime--;
console.log(this.safetime);
if (this.safetime === 0) {
clearInterval(intervalId); // 停止倒计时
this.isDisabled = false;
}
}, 1000);
}
}
},
// 清空表单
clean() {
this.studID = "";
this.name = "";
this.courtyard = "";
this.formData.selectedOptionIndex = "";
this.classroom = '';
this.phone = '';
this.parent = '';
this.parentPhone = "";
this.formData.selectedPoliticalIndex = ""
this.beginData = "";
this.endData = '';
this.formData.dataNum = '';
this.formData.deeds = '';
this.leaveIndex = -1;
this.formData.endAddress = '';
this.formData.address = '';
this.isChecked = false;
this.$forceUpdate(); // 强制更新组件
this.url = ''
localStorage.removeItem('formData');
},
//保存假条信息
save() {
if (this.checkboxValue == 0) {
// 如果复选框未被选中,则不允许提交
uni.showToast({
title: "请勾选承诺书",
icon: "error"
});
return; // 阻止表单提交
}
if (this.formData.signFile == '' || this.formData.signFile == null) {
// 如果复选框未被选中,则不允许提交
uni.showToast({
title: "请先进行签名",
icon: "error"
});
return; // 阻止表单提交
}
if (this.formData.endsingle < this.formData.single) {
uni.showToast({
title: "起始时间不能晚于结束时间",
icon: "none"
})
return; // 阻止表单提交
}
//表单非空校验
const requiredFields = [
'selectedPoliticalIndex',
'deeds',
'endsingle',
'single',
'dataNum',
'endAddress',
'address'
];
const emptyField = requiredFields.find(field => this.formData[field] === ""||this.formData[field] ==null);
if (emptyField) {
uni.showToast({
title: `请填写完必填字段`,
icon: "none"
})
return;
}
this.isSubmitting=true;
let data = {
applicantSignature: this.formData.signFile,
attachment: this.attachmentFile,
destination: this.formData.endAddress,
destinationDetails: this.formData.address,
endDate: this.formData.endsingle,
leaveDays: this.formData.dataNum,
leaveType: this.formData.selectedPoliticalIndex,
reason: this.formData.deeds,
remark: this.remark,
safetyPromise: 1,
startDate: this.formData.single,
leaveApplicationId: this.procInsId,
leavingGx:this.isLeaveGui
}
leaveSave(data).then(res => {
if (res.code == 200) {
uni.showToast({
title: "保存成功",
icon: "success"
});
this.isSubmitting=false;
uni.navigateBack({
success: () => {
const pages = getCurrentPages();
if (pages.length > 0) {
const prevPage = pages[pages.length - 2]
if (prevPage && typeof prevPage.getLeaveList ===
'function') {
prevPage.getLeaveList();
}
}
}
})
} else {
uni.showToast({
title: "提交失败,请先填写完整内容",
icon: "none"
});
}
});
},
signToggle() {
this.$refs.popup.open('center')
},
closeSafePopup() {
this.$refs.safetyPopup.close('center')
this.safetime = 5;
},
base64ToBlob(base64String) {
const byteCharacters = atob(base64String.split(',')[1]);
const byteNumbers = new Array(byteCharacters.length);
for (let i = 0; i < byteCharacters.length; i++) {
byteNumbers[i] = byteCharacters.charCodeAt(i);
}
const byteArray = new Uint8Array(byteNumbers);
return new Blob([byteArray], {
type: 'application/octet-stream'
});
},
formDataToObject(formData) {
const obj = {};
formData.forEach((value, key) => {
obj[key] = value;
});
return obj;
},
},
};
</script>
<style scoped lang="scss">
.container {
display: flex;
flex-direction: column;
align-items: center;
padding: 10rpx;
}
.form-item {
width: 95%;
height: 80rpx;
display: flex;
align-items: center;
margin-bottom: 20rpx;
justify-content: space-between;
checkbox {
/deep/.uni-checkbox-input.uni-checkbox-input-checked {
background: #007aff;
}
}
.label {
flex-shrink: 0;
}
text:last-child {
text-wrap: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
}
.form-text {
width: 95%;
margin-bottom: 20rpx;
border-bottom: 1px solid #ededee;
}
.form-img {
width: 95%;
margin-bottom: 20rpx;
border-bottom: 1px solid #ededee;
}
.example-body {
margin-top: 20rpx;
margin-bottom: 20rpx;
}
.txt {
margin-top: 20rpx;
}
.label {
text-align: right;
margin-right: 20rpx;
}
.select {
color: #888889;
white-space: nowrap;
/* 防止换行 */
overflow: hidden;
/* 隐藏溢出部分 */
text-overflow: ellipsis;
/* 显示省略号 */
}
.uni-input {
color: #888889;
text-align: right;
}
.btn {
display: flex;
justify-content: space-between;
position: fixed;
bottom: 0;
left: 0;
margin: 0 auto;
border-top: 1px solid #d6d6d6;
background: #fff;
padding: 10px;
right: 0;
button {
width: 30%;
background-color: #1890FF;
color: white;
}
}
.form-address {
width: 100%;
display: flex;
justify-content: space-between;
}
.labelsafe {
color: red;
font-size: 24rpx;
}
.form-canvas {
width: 95%;
margin-bottom: 25px;
.sign-img {
position: relative;
margin-top: 8px;
image {
width: 100%;
}
text {
position: absolute;
right: 9px;
bottom: 10px;
background: white;
padding: 3px 5px;
border-radius: 2px;
color: #5c5c5c;
}
}
.sign {
margin-top: 8px;
border: 1px solid #ebebeb;
padding: 25px;
color: #1e6fff;
text-align: center;
font-weight: bold;
}
}
.tab-box {
width: 80%;
height: 100vh;
background-color: #f0f0f0;
.success-img {
width: 90%;
height: 300rpx;
}
}
.safety-popup {
scroll-view {
::-webkit-scrollbar {
display: none;
}
}
.popup-content {
width: 90vw;
box-sizing: border-box;
.title {
text-align: center;
font-size: 18px;
font-weight: bold;
padding: 25px;
}
.content {
color: #7e7e7e;
padding: 0 25px 0 25px;
line-height: 25px;
.time {
text-align: center;
margin-top: 25px;
}
}
.safety-btn {
margin-top: 20px;
border-top: 1px solid #b6b6b6;
padding: 5px 0;
button {
&::after {
border: none;
}
}
}
}
}
</style>