364 lines
9.9 KiB
Vue
364 lines
9.9 KiB
Vue
<template>
|
||
<view class="qj-push-page">
|
||
<!-- 顶部区域 - Logo -->
|
||
<view class="header-section">
|
||
<image class="logo" src="@/static/system/login/logo.png" mode="aspectFit"></image>
|
||
</view>
|
||
|
||
<!-- 中间白色卡片 -->
|
||
<view class="content-section">
|
||
<view class="info-card">
|
||
<!-- 审批印章 - 右上角,如果已审批通过 -->
|
||
<view v-if="qjData.spResult === 'B'" class="approval-stamp">
|
||
<image class="stamp-image" src="@/static/base/view/sptg.png" mode="aspectFit"></image>
|
||
</view>
|
||
|
||
<!-- 申请人头像 - 中央 -->
|
||
<view class="student-photo-center">
|
||
<BasicImage :src="qjData.xstx || '/static/base/default-avatar.png'" />
|
||
</view>
|
||
|
||
<!-- 请假信息 -->
|
||
<view class="info-list">
|
||
<view class="info-item">
|
||
<text class="label">学生姓名:</text>
|
||
<text class="value">{{ qjData.xsxm }}</text>
|
||
</view>
|
||
<view class="info-item">
|
||
<text class="label">所在班级:</text>
|
||
<text class="value">{{ qjData.bc }}</text>
|
||
</view>
|
||
<view class="info-item">
|
||
<text class="label">请假类型:</text>
|
||
<text class="value">{{ qjData.qjlx }}</text>
|
||
</view>
|
||
<view class="info-item">
|
||
<text class="label">开始时间:</text>
|
||
<text class="value">{{ qjData.qjkstime }}</text>
|
||
</view>
|
||
<view class="info-item">
|
||
<text class="label">结束时间:</text>
|
||
<text class="value">{{ qjData.qjjstime }}</text>
|
||
</view>
|
||
<view class="info-item">
|
||
<text class="label">时长(天):</text>
|
||
<text class="value">{{ qjData.qjsc }}</text>
|
||
</view>
|
||
<view class="info-item">
|
||
<text class="label">是否离校:</text>
|
||
<text class="value">{{ qjData.sflx === 1 ? '是' : '否' }}</text>
|
||
</view>
|
||
<view class="info-item info-item-vertical">
|
||
<text class="label">请假事由:</text>
|
||
<text class="value">{{ qjData.qjsy }}</text>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 确认放行按钮 -->
|
||
<view class="action-button" @click="handleConfirm">
|
||
<text class="button-text">确认放行</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 底部区域 -->
|
||
<view class="footer-section"></view>
|
||
</view>
|
||
</template>
|
||
|
||
<script setup lang="ts">
|
||
import { computed, nextTick } from 'vue';
|
||
import { onLoad } from "@dcloudio/uni-app";
|
||
import { useDataStore } from "@/store/modules/data";
|
||
import { useUserStore } from "@/store/modules/user";
|
||
import { xsQjFindByIdApi, xsQjConfirmReleaseApi } from "@/api/base/server";
|
||
import { xxtsFindByIdApi } from "@/api/base/xxtsApi";
|
||
import BasicImage from "@/components/BasicImage/Image.vue";
|
||
|
||
const { loginByOpenId, getJs } = useUserStore();
|
||
const dataStore = useDataStore();
|
||
const { setQjData } = dataStore;
|
||
|
||
// 请假ID - 从 store 中通过 computed 访问,保持响应式
|
||
const qjId = computed(() => {
|
||
return (dataStore.qjData as any)?.id || '';
|
||
});
|
||
|
||
// 请假基础数据 - 直接访问 store 的 state,保持响应式
|
||
const qjData = computed(() => (dataStore.qjData || {}) as any);
|
||
|
||
const goHome = () => {
|
||
uni.reLaunch({ url: '/pages/base/message/index' });
|
||
};
|
||
|
||
// 确认放行
|
||
const handleConfirm = async () => {
|
||
// 检查是否有请假ID
|
||
if (!qjId.value) {
|
||
uni.showToast({ title: '请假ID不存在', icon: 'none' });
|
||
return;
|
||
}
|
||
|
||
// 获取当前教师信息
|
||
const js = getJs;
|
||
if (!js || !js.id) {
|
||
uni.showToast({ title: '获取教师信息失败', icon: 'none' });
|
||
return;
|
||
}
|
||
|
||
uni.showModal({
|
||
title: '确认放行',
|
||
content: '确认该学生已成功离校?',
|
||
success: async (res) => {
|
||
if (res.confirm) {
|
||
try {
|
||
uni.showLoading({ title: '放行中...' });
|
||
|
||
// 调用放行接口
|
||
const result = await xsQjConfirmReleaseApi({
|
||
id: qjId.value,
|
||
fxjsId: js.id,
|
||
fxjsxm: js.jsxm
|
||
});
|
||
|
||
uni.hideLoading();
|
||
|
||
if (result.resultCode === 1) {
|
||
uni.showToast({ title: '放行成功', icon: 'success' });
|
||
setTimeout(() => {
|
||
goHome();
|
||
}, 1500);
|
||
} else {
|
||
uni.showToast({
|
||
title: result.message || '放行失败',
|
||
icon: 'none'
|
||
});
|
||
}
|
||
} catch (error) {
|
||
console.error('放行失败:', error);
|
||
uni.hideLoading();
|
||
uni.showToast({ title: '放行失败,请重试', icon: 'none' });
|
||
}
|
||
}
|
||
}
|
||
});
|
||
};
|
||
|
||
onLoad(async (options: any) => {
|
||
console.log('detail.vue onLoad 接收到的参数:', options);
|
||
|
||
try {
|
||
uni.showLoading({ title: "加载中..." });
|
||
|
||
// 场景1: 从待办过来的(from=db),需要先获取待办信息
|
||
if (options && options.from === "db") {
|
||
console.log('从待办过来,参数:', options);
|
||
|
||
// 检查登录状态
|
||
if (options.openId) {
|
||
const isLoggedIn = await loginByOpenId(options.openId);
|
||
if (!isLoggedIn) {
|
||
console.log("用户未登录,跳过处理");
|
||
uni.hideLoading();
|
||
return;
|
||
}
|
||
await nextTick();
|
||
}
|
||
|
||
// 优先从后端根据url中的id去查询Xxts(待办信息)
|
||
if (options.id) {
|
||
const xxtsRes = await xxtsFindByIdApi({ id: options.id });
|
||
if (xxtsRes && xxtsRes.result) {
|
||
const xxts = xxtsRes.result;
|
||
console.log('获取到待办信息:', xxts);
|
||
|
||
// 根据待办中的主表ID获取请假详情
|
||
const qjRes = await xsQjFindByIdApi({ id: xxts.xxzbId });
|
||
if (qjRes && qjRes.result) {
|
||
setQjData(qjRes.result);
|
||
await nextTick();
|
||
console.log('获取到请假详情:', qjRes.result);
|
||
} else {
|
||
throw new Error('获取请假详情失败');
|
||
}
|
||
} else {
|
||
throw new Error('获取待办信息失败');
|
||
}
|
||
} else {
|
||
throw new Error('缺少待办ID参数');
|
||
}
|
||
}
|
||
// 场景2: 直接传请假ID(内部跳转)
|
||
else if (options && options.id) {
|
||
console.log('直接传请假ID:', options.id);
|
||
const qjRes = await xsQjFindByIdApi({ id: options.id });
|
||
if (qjRes && qjRes.result) {
|
||
setQjData(qjRes.result);
|
||
await nextTick();
|
||
console.log('获取到请假详情:', qjRes.result);
|
||
} else {
|
||
throw new Error('获取请假详情失败');
|
||
}
|
||
}
|
||
// 场景3: 从 store 获取(兼容某些场景)
|
||
else if (dataStore.qjData && (dataStore.qjData as any).id) {
|
||
console.log('从 store 获取请假ID:', (dataStore.qjData as any).id);
|
||
// store 中已有数据,无需重新获取
|
||
} else {
|
||
throw new Error('缺少请假ID参数');
|
||
}
|
||
|
||
uni.hideLoading();
|
||
} catch (error: any) {
|
||
console.error('加载请假详情失败:', error);
|
||
uni.hideLoading();
|
||
uni.showToast({
|
||
title: error.message || "加载失败",
|
||
icon: "none"
|
||
});
|
||
setTimeout(() => {
|
||
uni.navigateBack();
|
||
}, 1500);
|
||
}
|
||
});
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
.qj-push-page {
|
||
width: 100%;
|
||
min-height: 100vh;
|
||
background: url("@/static/base/bg.jpg") no-repeat;
|
||
background-size: 100% 100%;
|
||
display: flex;
|
||
flex-direction: column;
|
||
position: relative;
|
||
}
|
||
|
||
/* 顶部区域 - Logo */
|
||
.header-section {
|
||
flex: 0 0 auto;
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
padding: 80rpx 30rpx 40rpx;
|
||
|
||
.logo {
|
||
width: 500rpx;
|
||
height: 120rpx;
|
||
}
|
||
}
|
||
|
||
/* 中间白色卡片区域 */
|
||
.content-section {
|
||
flex: 1 0 auto;
|
||
padding: 0 30rpx 40rpx;
|
||
|
||
.info-card {
|
||
background: #FFFFFF;
|
||
border-radius: 40rpx 40rpx 20rpx 20rpx;
|
||
padding: 40rpx 30rpx;
|
||
box-shadow: 0 8rpx 30rpx rgba(0, 0, 0, 0.15);
|
||
position: relative;
|
||
min-height: 700rpx;
|
||
|
||
/* 审批印章 - 右上角 */
|
||
.approval-stamp {
|
||
position: absolute;
|
||
top: 30rpx;
|
||
right: 30rpx;
|
||
width: 160rpx;
|
||
height: 160rpx;
|
||
z-index: 10;
|
||
|
||
.stamp-image {
|
||
width: 100%;
|
||
height: 100%;
|
||
}
|
||
}
|
||
|
||
/* 学生头像 - 中央 */
|
||
.student-photo-center {
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
margin-bottom: 40rpx;
|
||
padding-top: 20rpx;
|
||
|
||
// BasicImage 组件的容器样式
|
||
:deep(.wh-full) {
|
||
width: 280rpx !important;
|
||
height: 280rpx !important;
|
||
border-radius: 32rpx;
|
||
overflow: hidden;
|
||
background: #F5F5F5;
|
||
box-shadow: 0 8rpx 24rpx rgba(0, 0, 0, 0.15);
|
||
display: block;
|
||
}
|
||
}
|
||
|
||
/* 信息列表 */
|
||
.info-list {
|
||
padding-top: 0;
|
||
|
||
.info-item {
|
||
display: flex;
|
||
margin-bottom: 32rpx;
|
||
line-height: 1.6;
|
||
|
||
&.info-item-vertical {
|
||
flex-direction: column;
|
||
|
||
.label {
|
||
margin-bottom: 12rpx;
|
||
}
|
||
}
|
||
|
||
.label {
|
||
font-size: 28rpx;
|
||
color: #999999;
|
||
width: 160rpx;
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.value {
|
||
font-size: 28rpx;
|
||
color: #333333;
|
||
flex: 1;
|
||
word-break: break-all;
|
||
}
|
||
}
|
||
}
|
||
|
||
/* 确认按钮 */
|
||
.action-button {
|
||
margin-top: 60rpx;
|
||
height: 88rpx;
|
||
background: linear-gradient(90deg, #FF9500 0%, #FF6B00 100%);
|
||
border-radius: 44rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
box-shadow: 0 8rpx 20rpx rgba(255, 107, 0, 0.3);
|
||
|
||
&:active {
|
||
opacity: 0.8;
|
||
}
|
||
|
||
.button-text {
|
||
font-size: 32rpx;
|
||
font-weight: bold;
|
||
color: #FFFFFF;
|
||
letter-spacing: 4rpx;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/* 底部区域 */
|
||
.footer-section {
|
||
flex: 0 0 auto;
|
||
height: 80rpx;
|
||
background: transparent;
|
||
}
|
||
</style>
|