ywyonui 8c79a8e745 1、拆分点名页面
2、默认加载班主任和副班主任陪餐
2025-09-12 19:44:12 +08:00

286 lines
6.7 KiB
Vue
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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="start-dm-content">
<!-- 班级选择器 -->
<view class="section">
<view class="section-title">选择班级</view>
<NjBjPicker @change="changeNjBj" icon-arrow="right" :customStyle="{ backgroundColor: '#fff', borderRadius: '0', padding: '12px 15px' }" />
<!-- 班级选择提示 -->
<view v-if="!curBj" class="class-tip">
<text class="tip-icon"></text>
<text class="tip-text">请先选择班级</text>
</view>
</view>
<!-- 陪餐教师选择 -->
<dm-js v-if="curBj" :bj-id="curBj?.key" ref="dmJsRef" />
<!-- 学生状态列表 -->
<dm-xs
v-if="curBj"
:bz-id="getJcBz.id"
:nj-id="curNj?.key"
:bj-id="curBj?.key"
ref="dmXsRef"
/>
<!-- 拍照视频组件 -->
<view class="section" v-if="curBj">
<DmPsComponent
v-model="mediaData"
:photo-title="'就餐现场拍照'"
:video-title="'就餐现场视频'"
:max-photo-count="9"
:max-video-count="3"
:max-video-duration="60"
ref="dmPsRef"
/>
</view>
<!-- 加载提示 -->
<view v-if="isLoading" class="loading-overlay">
<view class="loading-content">
<text>加载中...</text>
</view>
</view>
</view>
<!-- 提交按钮 - 固定在底部 -->
<view class="fixed-bottom" v-if="curBj">
<button
class="submit-btn"
:disabled="isSubmitting"
@click="tjDm"
>
提交点名
</button>
</view>
</template>
<script setup lang="ts">
import { ref, computed } from 'vue'
import NjBjPicker from '@/pages/components/NjBjPicker/index.vue'
import DmJs from './dmJs.vue'
import DmXs from './dmXs.vue'
import DmPsComponent from '@/pages/components/dmPs/index.vue'
import { submitJcDmDataApi } from '@/api/base/jcApi'
import { useUserStore } from '@/store/modules/user'
import { useDataStore } from '@/store/modules/data'
import { useDebounce } from "@/utils/debounce";
const { getJs } = useUserStore()
const { getJcBz } = useDataStore();
// 替换 isSubmitting 状态为 useDebounce
const { isProcessing: isSubmitting, debounce } = useDebounce(2000);
/**
* 就餐点名组件
* 功能:
* 1. 选择班级,获取学生列表
* 2. 将学生分为两类:已缴费(可切换正常/请假/缺勤)和未缴费/未报名(状态为未缴费/未报名)
* 3. 选择陪餐教师
* 4. 批量提交点名记录包含jsId和dmPcId字段
*/
// 接收外部传入属性
const props = withDefaults(defineProps<{
title?: string
}>(), {
title: '点名'
});
const isLoading = ref(false);
// 响应式数据
const curNj = ref<any>(null);
const curBj = ref<any>(null);
const dmXsRef = ref<any>(null);
const dmJsRef = ref<any>(null);
// 媒体数据
const mediaData = ref({
photoList: [],
videoList: []
});
const dmPsRef = ref<any>(null);
// 改变了年级班级
const changeNjBj = async (nj: any, bj: any) => {
curNj.value = nj
curBj.value = bj
};
const tjDm = debounce(async () => {
if (!curBj.value) { // 改为检查已缴费学生数量
uni.showToast({
title: '请先选择班级',
icon: 'none'
})
return;
}
try {
const dmXsList = dmXsRef.value.getDmXsList();
const dmJsList = dmJsRef.value.getDmJsList();
// 先上传媒体文件
let photoUrls = '';
let videoUrls = '';
if (mediaData.value.photoList.length > 0 || mediaData.value.videoList.length > 0) {
try {
if (dmPsRef.value) {
const uploadResult = await dmPsRef.value.uploadMedia();
photoUrls = uploadResult.photoUrls;
videoUrls = uploadResult.videoUrls;
}
} catch (uploadError) {
console.error('媒体文件上传失败:', uploadError);
uni.showToast({
title: '媒体文件上传失败,请重试',
icon: 'none'
});
return;
}
}
let dmData: any = {
jcTime: new Date(),
bjId: curBj.value.key,
njId: curNj.value.key,
bjmc: curBj.value.title,
njmc: curNj.value.title,
dmJsId: getJs.id || '', // 点名教师ID
pcRs: dmJsList.length,
zrs: dmXsList.length,
sdRs: dmXsList.filter((s: any) => s.jcZt === 'A').length,
qjRs: dmXsList.filter((s: any) => s.jcZt === 'B').length,
qqRs: dmXsList.filter((s: any) => s.jcZt === 'C').length,
// 媒体文件地址
zp: photoUrls, // 照片字段,逗号分隔的字符串
sp: videoUrls, // 视频字段,逗号分隔的字符串
xsList: dmXsList,
ptJsList: dmJsList
};
console.log('提交数据:', dmData);
// return;
// 提交点名数据
const response = await submitJcDmDataApi(dmData);
if (response.result) {
uni.showToast({
title: '提交成功',
icon: 'success'
})
// 重置表单
curNj.value = null
curBj.value = null
mediaData.value = {
photoList: [],
videoList: []
};
// 返回上一页
uni.navigateBack()
} else {
throw new Error(response.message || '提交失败')
}
} catch (error) {
console.error('提交失败:', error)
uni.showToast({
title: error instanceof Error ? error.message : '提交失败',
icon: 'none'
})
}
});
</script>
<style lang="scss" scoped>
.start-dm-content {
padding: 20rpx;
padding-bottom: 120rpx; /* 为固定底部按钮留出空间 */
}
.section {
background-color: #fff;
border-radius: 16rpx;
padding: 30rpx;
margin-bottom: 20rpx;
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
}
.section-title {
font-size: 32rpx;
font-weight: bold;
color: #333;
margin-bottom: 20rpx;
display: flex;
justify-content: space-between;
align-items: center;
}
.class-tip {
display: flex;
align-items: center;
margin-top: 20rpx;
padding: 15rpx 20rpx;
background-color: #fffbe6;
border: 1rpx solid #ffe58f;
border-radius: 12rpx;
color: #faad14;
font-size: 28rpx;
font-weight: bold;
.tip-icon {
margin-right: 10rpx;
font-size: 32rpx;
}
}
.fixed-bottom {
position: fixed;
bottom: 0;
left: 0;
right: 0;
padding: 20rpx;
background-color: #fff;
box-shadow: 0 -2rpx 8rpx rgba(0, 0, 0, 0.1);
z-index: 10;
}
.submit-btn {
width: 100%;
height: 80rpx;
background-color: #007aff;
color: #fff;
border: none;
border-radius: 40rpx;
font-size: 32rpx;
font-weight: bold;
&:disabled {
background-color: #d9d9d9;
color: #999;
}
}
.loading-overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.5);
display: flex;
justify-content: center;
align-items: center;
z-index: 1000;
}
.loading-content {
background-color: #fff;
padding: 40rpx;
border-radius: 16rpx;
color: #333;
font-size: 28rpx;
}
</style>