663 lines
15 KiB
Vue
663 lines
15 KiB
Vue
<template>
|
||
<view class="detail">
|
||
<Nav :navs="navs" @change="navChange" />
|
||
<view class="form" v-if="navIndex==0">
|
||
<view class="container" style="padding-bottom: 60px;" v-if="form!=null">
|
||
<!-- 入伍保留学籍申请 -->
|
||
<view v-if="category == 'enlistmentReserve'" style="width: 100%;">
|
||
<enlistmentReserve :form="form"></enlistmentReserve>
|
||
</view>
|
||
<!-- 外宿申请 -->
|
||
<view v-if="category == 'outsideAccommodation'" style="width: 100%;">
|
||
<outsideAccommodation :form="form"></outsideAccommodation>
|
||
</view>
|
||
<view class="btns" v-if="tag==1">
|
||
<button class="turn-down" @tap="onReject" v-if="role!=='学生'">驳回</button>
|
||
<button class="return" @tap="onReturn" v-if="returnTaskList.length>0">回退</button>
|
||
<button class="submit" @tap="onComplete">审批</button>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
<view class="progress" v-if="navIndex==1">
|
||
<FlowStep :procInsId="taskForm.procInsId" :deployId="taskForm.deployId" />
|
||
</view>
|
||
|
||
<uni-popup class="popup" ref="approveDialog" type="dialog" background-color="#fff">
|
||
<view class="popup-content">
|
||
<view class="title">
|
||
流程审批
|
||
</view>
|
||
<view class="content">
|
||
<view class="form-item">
|
||
<label class="label"><text class="required">*</text>审批意见</label>
|
||
<input type="text" placeholder-class="placeholderColor" placeholder="审批意见"
|
||
v-model="taskForm.variables.approvalOpinion" />
|
||
</view>
|
||
</view>
|
||
<view class="btns">
|
||
<button type="default" @tap="onCancel">取消</button>
|
||
<button type="primary" @tap="approveDialogConfirm" :disabled="isSubmitting">确定</button>
|
||
</view>
|
||
</view>
|
||
</uni-popup>
|
||
</view>
|
||
|
||
</template>
|
||
|
||
<script>
|
||
import Nav from "@/components/navs/navs.vue";
|
||
import FlowStep from "@/components/flow-step/flow-step.vue";
|
||
import {
|
||
baseUrl
|
||
} from "@/config.js";
|
||
import {
|
||
getDiseaseTypeByDictValue
|
||
} from "@/utils/dict.js";
|
||
import {
|
||
complete,
|
||
reject,
|
||
returnList,
|
||
returnTask
|
||
} from "@/api/task.js";
|
||
import {
|
||
getDicts
|
||
} from "@/api/system/dict/data";
|
||
import {
|
||
getEnlistmentReserveByProcessInstanceId,
|
||
updateStudent
|
||
} from "@/api/routine/enlistmentReserve/enlistmentReserve";
|
||
import {
|
||
getOutsideAccommodationApplyByProcessInstanceId,
|
||
updateOutsideAccommodationApply
|
||
} from "@/api/dms/outsideAccommodation/outsideAccommodationApply";
|
||
import {
|
||
insertOrUpdateByStuAndApprover
|
||
} from "@/api/routine/enlistmentReserve/enlistmentReserveApproval";
|
||
import {
|
||
getUserProfile
|
||
} from '@/api/system/user'
|
||
import enlistmentReserve from "@/pages/Approval/handleTask/processHandling/components/enlistmentReserve.vue"
|
||
import outsideAccommodation from "@/pages/Approval/handleTask/processHandling/components/outsideAccommodation.vue"
|
||
export default {
|
||
components: {
|
||
Nav,
|
||
FlowStep,
|
||
enlistmentReserve,
|
||
outsideAccommodation
|
||
},
|
||
data() {
|
||
return {
|
||
isSubmitting: false, //表单提交标志位
|
||
navs: [{
|
||
text: "表单信息",
|
||
val: 0
|
||
},
|
||
{
|
||
text: "流程跟踪",
|
||
val: 1
|
||
}
|
||
],
|
||
taskDotIndex: 0,
|
||
navIndex: 0,
|
||
form: null,
|
||
ImageUrl: baseUrl,
|
||
role: uni.getStorageSync("roles"),
|
||
inputReject: "",
|
||
taskName: "", //节点名
|
||
category: "",
|
||
taskForm: {
|
||
multiple: false,
|
||
comment: '', // 意见内容
|
||
procInsId: '', // 流程实例编号
|
||
instanceId: '', // 流程实例编号
|
||
deployId: '', // 流程定义编号
|
||
taskId: '', // 流程任务编号
|
||
procDefId: '', // 流程编号
|
||
vars: '',
|
||
targetKey: '',
|
||
variables: {
|
||
approvalOpinion: '', // 必须初始化,避免 null 报错
|
||
approvalResult: '',
|
||
targetNodeName: '',
|
||
signature: ''
|
||
},
|
||
},
|
||
returnTaskList: [], // 回退列表数据
|
||
tag: '',
|
||
user: []
|
||
}
|
||
},
|
||
onLoad(option) {
|
||
let query = JSON.parse(option.query);
|
||
this.category = query.category;
|
||
this.tag = query.tag;
|
||
this.taskForm.deployId = query.deployId;
|
||
this.taskForm.instanceId = query.procInsId
|
||
this.taskForm.procInsId = query.procInsId
|
||
this.taskForm.executionId = query.executionId
|
||
this.taskForm.taskId = query.taskId
|
||
this.taskName = query.taskName
|
||
if (this.category == 'enlistmentReserve') { // 入伍保留学籍申请表单
|
||
this.getEnlistmentReserve(this.taskForm.procInsId);
|
||
// 页面标题修改
|
||
uni.setNavigationBarTitle({
|
||
title: '入伍保留学籍申请详情'
|
||
});
|
||
} else if (this.category == 'outsideAccommodation') { // 外宿申请表单
|
||
this.getOutsideAccommodation(this.taskForm.procInsId);
|
||
// 页面标题修改
|
||
uni.setNavigationBarTitle({
|
||
title: '外宿申请详情'
|
||
});
|
||
}
|
||
getUserProfile().then(res => {
|
||
this.user = res.data
|
||
})
|
||
},
|
||
methods: {
|
||
navChange(index) {
|
||
this.navIndex = index;
|
||
},
|
||
// 请求 入伍保留学籍表单数据
|
||
async getEnlistmentReserve(procInsId) {
|
||
try {
|
||
const res = await getEnlistmentReserveByProcessInstanceId(procInsId.toString());
|
||
this.form = res.data;
|
||
// 将字典中的民族提取
|
||
let nation = await getDicts("rt_nation")
|
||
let nationArr = nation.data
|
||
if (!Array.isArray(nationArr) || nationArr.length === 0 || !this.form.nation) {
|
||
console.warn("民族字典数据为空或表单民族值未设置");
|
||
return;
|
||
}
|
||
// 使用find方法查找匹配项(性能更优,匹配到即停止)
|
||
const matchItem = nationArr.find(item => {
|
||
return String(item.dictValue) === String(this.form.nation);
|
||
});
|
||
console.log(matchItem);
|
||
// 如果找到匹配项,更新值;否则保留原值或置空
|
||
if (matchItem) {
|
||
this.form.nation = matchItem.dictLabel;
|
||
} else {
|
||
console.warn(`未找到民族值【${this.form.nation}】对应的字典标签`);
|
||
// 可选:如果需要,匹配不到时置空
|
||
// this.form.nation = "未知民族";
|
||
}
|
||
|
||
// 处理审批意见列表,添加意见类型
|
||
if (this.form?.enlistmentReserveApprovalList) {
|
||
// 定义意见类型数组(与索引对应:0=辅导员,1=学务,2=二级学院,3=学籍管理科,4=教务处主管领导)
|
||
const opinionTypes = [
|
||
"辅导员意见",
|
||
"学务意见",
|
||
"二级学院意见",
|
||
"学籍管理科意见",
|
||
"教务处主管领导意见"
|
||
];
|
||
// 遍历审批列表,为每条数据添加 opinionType 字段
|
||
this.form.enlistmentReserveApprovalList.forEach((item, index) => {
|
||
// 只处理前5条数据(超出部分不添加,或可根据实际需求调整)
|
||
if (index < opinionTypes.length) {
|
||
item.opinionType = opinionTypes[index];
|
||
} else {
|
||
// 若超过5条,可设置默认值或不设置
|
||
item.opinionType = "其他意见";
|
||
}
|
||
});
|
||
}
|
||
} catch (error) {
|
||
// 错误捕获,避免接口调用失败导致页面异常
|
||
console.error("获取数据失败:", error);
|
||
uni.showToast({
|
||
title: "数据加载失败",
|
||
icon: "none"
|
||
});
|
||
}
|
||
},
|
||
// 请求 外宿申请表单数据
|
||
getOutsideAccommodation(procInsId) {
|
||
getOutsideAccommodationApplyByProcessInstanceId(procInsId.toString()).then((res) => {
|
||
this.form = res.data
|
||
if (this.form?.outsideAccommodationApprovals) {
|
||
// 定义外宿审批意见类型数组(与索引严格对应)
|
||
const opinionTypes = [
|
||
"辅导员意见",
|
||
"二级学院书记意见",
|
||
"学工处意见",
|
||
"学校领导意见"
|
||
];
|
||
// 遍历审批列表,为每条数据添加 opinionType 字段
|
||
this.form.outsideAccommodationApprovals.forEach((item, index) => {
|
||
// 前4条数据按索引匹配意见类型,超出部分设为默认值
|
||
if (index < opinionTypes.length) {
|
||
item.opinionType = opinionTypes[index];
|
||
} else {
|
||
// 超出4条时的兜底值
|
||
item.opinionType = "其他审批意见";
|
||
}
|
||
});
|
||
}
|
||
})
|
||
},
|
||
onComplete() {
|
||
this.taskForm.variables.signature = this.user.signature
|
||
this.$refs.approveDialog.open();
|
||
},
|
||
onReturn() {
|
||
this.$refs.returnDialog.open();
|
||
},
|
||
onReject() {
|
||
this.$refs.rejectDialog.open();
|
||
},
|
||
onCancel() {
|
||
this.$refs.approveDialog.close();
|
||
this.$refs.returnDialog.close();
|
||
},
|
||
approveDialogConfirm() {
|
||
if (this.taskForm.variables.approvalOpinion == '') {
|
||
uni.showToast({
|
||
title: `请填写审批意见`,
|
||
icon: "none"
|
||
})
|
||
return;
|
||
}
|
||
uni.showLoading({
|
||
title: "正在审批"
|
||
});
|
||
this.isSubmitting = true; // 设置为正在提交
|
||
this.taskForm.comment = this.taskForm.variables.approvalOpinion != '' ? this.taskForm.variables
|
||
.approvalOpinion : '同意'
|
||
this.taskForm.variables.approvalResult = 1
|
||
complete(this.taskForm).then(res => {
|
||
if (res.code == 200) {
|
||
if (this.taskName ==
|
||
'教务处主管领导审批') { // (最后一个领导审核完成之后,修改学生学籍状态, status:07是入伍保留学籍)
|
||
updateStudent({
|
||
stuId: this.form.studentId,
|
||
status: '07'
|
||
}).then(response => {})
|
||
}
|
||
uni.showToast({
|
||
title: "审批成功"
|
||
});
|
||
} else {
|
||
uni.showToast({
|
||
title: "审批失败"
|
||
});
|
||
}
|
||
uni.hideLoading();
|
||
uni.navigateBack({
|
||
success: () => {
|
||
const pages = getCurrentPages();
|
||
if (pages && pages.length > 0) {
|
||
const prevPage = pages[pages.length - 2] || pages[pages
|
||
.length - 1];
|
||
if (prevPage && typeof prevPage.handleChange ===
|
||
'function') {
|
||
prevPage.handleChange(this.tag || 1);
|
||
}
|
||
}
|
||
|
||
}
|
||
})
|
||
})
|
||
},
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style scoped lang="scss">
|
||
.detail {
|
||
padding-top: 90rpx;
|
||
|
||
.progress {
|
||
padding: 0 30rpx 30rpx;
|
||
|
||
.title {
|
||
font-weight: bold;
|
||
color: #202020;
|
||
display: inline-block;
|
||
font-size: 30rpx;
|
||
margin-bottom: 30rpx;
|
||
}
|
||
}
|
||
|
||
.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;
|
||
border-bottom: 1px solid #ededee;
|
||
|
||
}
|
||
|
||
.custom-input {
|
||
width: 100%;
|
||
}
|
||
|
||
.form-text {
|
||
width: 95%;
|
||
margin-bottom: 20rpx;
|
||
border-bottom: 1px solid #ededee;
|
||
}
|
||
|
||
.form-img {
|
||
width: 100px;
|
||
height: 100px;
|
||
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;
|
||
text-wrap: nowrap;
|
||
}
|
||
|
||
.select {
|
||
color: #888889;
|
||
white-space: nowrap;
|
||
/* 防止换行 */
|
||
overflow: hidden;
|
||
/* 隐藏溢出部分 */
|
||
text-overflow: ellipsis;
|
||
/* 显示省略号 */
|
||
}
|
||
|
||
.uni-input {
|
||
color: #888889;
|
||
text-align: right;
|
||
}
|
||
|
||
.btn {
|
||
width: 100%;
|
||
height: 90rpx;
|
||
display: flex;
|
||
justify-content: space-between;
|
||
|
||
position: fixed;
|
||
bottom: 20px;
|
||
left: 0;
|
||
margin: 0 auto;
|
||
}
|
||
|
||
button {
|
||
width: 30%;
|
||
background-color: #87CEFA;
|
||
color: white;
|
||
}
|
||
|
||
.form-address {
|
||
|
||
width: 100%;
|
||
display: flex;
|
||
justify-content: space-between;
|
||
}
|
||
|
||
.labelsafe {
|
||
color: red;
|
||
}
|
||
|
||
.form-canvas {
|
||
width: 95%;
|
||
height: 700rpx;
|
||
}
|
||
|
||
.tab-box {
|
||
width: 80%;
|
||
height: 100vh;
|
||
background-color: #f0f0f0;
|
||
|
||
.success-img {
|
||
width: 90%;
|
||
height: 300rpx;
|
||
|
||
}
|
||
}
|
||
|
||
.btns {
|
||
display: flex;
|
||
position: fixed;
|
||
bottom: 0;
|
||
left: 0;
|
||
right: 0;
|
||
|
||
button {
|
||
height: 50px;
|
||
line-height: 50px;
|
||
// width: 50%;
|
||
flex: 1;
|
||
border-radius: 0;
|
||
|
||
&.turn-down {
|
||
background-color: #FF3334;
|
||
}
|
||
|
||
&.return {
|
||
background-color: #FFBA00;
|
||
}
|
||
|
||
&.submit {
|
||
background-color: #0092FF;
|
||
}
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
.popup {
|
||
.popup-content {
|
||
width: 90vw;
|
||
max-height: 80vh;
|
||
overflow: scroll;
|
||
// padding: 0 40rpx;
|
||
|
||
.title {
|
||
font-size: 40rpx;
|
||
font-weight: bold;
|
||
text-align: center;
|
||
margin: 20rpx 0;
|
||
}
|
||
|
||
.content {
|
||
padding: 0 40rpx;
|
||
|
||
.show-letter {
|
||
.title {
|
||
font-size: 30rpx;
|
||
}
|
||
|
||
.stu-name {
|
||
margin-bottom: 8rpx;
|
||
}
|
||
|
||
.desc {
|
||
color: #797979;
|
||
}
|
||
|
||
.bottom {
|
||
button {
|
||
margin: 20rpx 0;
|
||
}
|
||
|
||
.gaizhang {
|
||
text-align: right;
|
||
position: relative;
|
||
|
||
image {
|
||
width: 200rpx;
|
||
}
|
||
|
||
.time {
|
||
position: absolute;
|
||
right: 30rpx;
|
||
bottom: 55rpx;
|
||
display: flex;
|
||
flex-direction: column;
|
||
}
|
||
|
||
|
||
}
|
||
}
|
||
}
|
||
|
||
.form-item {
|
||
.required {
|
||
color: red;
|
||
margin-right: 8rpx;
|
||
}
|
||
|
||
&.download {
|
||
margin: 50rpx 0 30rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
color: #4097FE;
|
||
justify-content: center;
|
||
|
||
.file-icon {
|
||
width: 50rpx;
|
||
margin-right: 20rpx;
|
||
}
|
||
|
||
text {
|
||
border-bottom: 1px solid #4097FE;
|
||
padding-bottom: 2px;
|
||
}
|
||
}
|
||
|
||
.label {
|
||
display: inline-block;
|
||
margin: 30rpx 0 20rpx;
|
||
color: #202020;
|
||
font-weight: 600;
|
||
}
|
||
|
||
|
||
input {
|
||
display: inline-block;
|
||
padding: 0 20rpx;
|
||
height: 70rpx;
|
||
}
|
||
|
||
textarea {
|
||
height: 200rpx;
|
||
padding: 10rpx;
|
||
}
|
||
|
||
.placeholderColor {
|
||
color: #D8D8D8;
|
||
}
|
||
|
||
input,
|
||
textarea {
|
||
width: 100%;
|
||
border: 1px solid #E1E1E1;
|
||
border-radius: 16rpx;
|
||
|
||
}
|
||
|
||
picker {
|
||
border: 1px solid #E1E1E1;
|
||
height: 70rpx;
|
||
line-height: 70rpx;
|
||
padding: 0 30rpx;
|
||
|
||
.uni-input {
|
||
display: flex;
|
||
color: #202020;
|
||
opacity: 0.35;
|
||
|
||
&.select {
|
||
opacity: 1;
|
||
}
|
||
|
||
.val {
|
||
flex: 1;
|
||
|
||
}
|
||
}
|
||
}
|
||
|
||
.uni-file-picker {
|
||
/deep/ .uni-progress-bar {
|
||
background-color: transparent !important;
|
||
}
|
||
}
|
||
|
||
}
|
||
}
|
||
|
||
.btns {
|
||
display: flex;
|
||
margin-top: 80rpx;
|
||
|
||
button {
|
||
flex: 1;
|
||
border-radius: 0;
|
||
border-bottom: 0;
|
||
|
||
&:first-child {
|
||
background-color: transparent;
|
||
border: 1px solid #4097FE;
|
||
border-bottom: 0;
|
||
color: #4097FE;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
.return-dialog {
|
||
.form-item {
|
||
label {
|
||
font-weight: bold;
|
||
display: inline-block;
|
||
margin-bottom: 10px;
|
||
}
|
||
|
||
&:last-child {
|
||
margin-top: 15px;
|
||
}
|
||
|
||
.list {
|
||
height: auto;
|
||
max-height: 200px;
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
// height: 200px;
|
||
// display: flex;
|
||
// flex-wrap: wrap;
|
||
|
||
.item {
|
||
width: 100%;
|
||
height: 40px;
|
||
line-height: 40px;
|
||
text-align: center;
|
||
|
||
&.active {
|
||
background-color: #0092FF;
|
||
color: white;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
</style> |