签到调整

This commit is contained in:
hebo 2025-09-30 21:53:10 +08:00
parent daf902029b
commit 1a154398b9
6 changed files with 933 additions and 44 deletions

View File

@ -694,6 +694,14 @@
"navigationStyle": "custom"
}
},
{
"path": "pages/view/routine/qd/confirmself",
"style": {
"navigationBarTitleText": "签到确认",
"navigationStyle": "custom"
}
},
{
"path": "pages/view/routine/JiaoXueZiYuan/add-resource",
"style": {

View File

@ -54,20 +54,15 @@ async function forceRefreshPermission(changeTime?: string): Promise<void> {
}
}
function goByJs(js: any) {
//
const globalData = getGlobal;
console.log('goByJs - globalData:', globalData);
console.log('goByJs - js:', js);
if (globalData && globalData.qdId) {
function goByqd(data: any) {
if (data && data.qdId) {
//
let confirmUrl = `/pages/view/routine/qd/confirm?qdId=${globalData.qdId}`;
if (globalData.rqgqtime) {
confirmUrl += `&rqgqtime=${globalData.rqgqtime}`;
let confirmUrl = `/pages/view/routine/qd/confirm?qdId=${data.qdId}`;
if (data.rqgqtime) {
confirmUrl += `&rqgqtime=${data.rqgqtime}`;
}
if (globalData.timestampqd) {
confirmUrl += `&timestampqd=${globalData.timestampqd}`;
if (data.timestampqd) {
confirmUrl += `&timestampqd=${data.timestampqd}`;
}
console.log('重定向到签到确认页面:', confirmUrl);
@ -77,11 +72,9 @@ function goByJs(js: any) {
return;
}
if (getGlobal && getGlobal.type === '1') {
uni.reLaunch({
url: "/pages/view/routine/xk/qd?from=login"
});
}
function goByJs(js: any) {
if (js.confirmStatus == "A") {
//
uni.reLaunch({
@ -102,20 +95,15 @@ function goByJs(js: any) {
onLoad(async (data: any) => {
console.log('launchPage onLoad - 接收到的参数:', data);
if (data && data.openId) {
setGlobal(data);
console.log('launchPage onLoad - 设置global数据后:', getGlobal);
try {
const res = await checkOpenId({
openId: data.openId,
appCode: "JS",
});
console.log('launchPage onLoad - checkOpenId结果:', res);
if (res.resultCode == 1 && res.result) {
if (data && data.qdId) {
goByqd(data);
}else if (res.resultCode == 1 && res.result) {
//
afterLoginAction(res.result);

View File

@ -0,0 +1,717 @@
<template>
<view class="confirm-page">
<!-- 确认签到阶段 -->
<view v-if="currentStep === 'confirm'" class="confirm-step">
<view class="confirm-header">
<text class="confirm-title">确认签到</text>
</view>
<view class="meeting-info">
<view class="info-item">
<text class="info-label">会议名称</text>
<text class="info-value">{{ meetingInfo?.qdmc || '未设置' }}</text>
</view>
<view class="info-item">
<text class="info-label">会议时间</text>
<text class="info-value">{{ formatTime(meetingInfo?.qdkstime) }} - {{ formatTime(meetingInfo?.qdjstime) }}</text>
</view>
<view class="info-item">
<text class="info-label">会议地点</text>
<text class="info-value">{{ meetingInfo?.qdwz || '未设置' }}</text>
</view>
<view class="info-item">
<text class="info-label">签到人员</text>
<text class="info-value">{{ userInfo?.jsxm || '未设置' }}</text>
</view>
</view>
<view v-if="sign_file" class="signature-preview">
<text class="preview-label">签名预览</text>
<image :src="sign_file" class="signature-preview-img" />
</view>
<button @click="submitSignIn" class="submit-btn">确认签到</button>
</view>
<!-- 签到成功阶段 -->
<view v-else-if="currentStep === 'success'" class="success-step">
<view class="success-content">
<u-icon name="checkmark-circle" size="80" color="#67C23A" />
<text class="success-title">签到成功</text>
<text class="success-time">{{ formatTime(new Date()) }}</text>
<text class="success-tip">您已成功完成签到</text>
</view>
</view>
<!-- 不在签到名单阶段 -->
<view v-else-if="currentStep === 'notInList'" class="not-in-list-step">
<view class="not-in-list-content">
<u-icon name="close-circle" size="80" color="#F56C6C" />
<text class="not-in-list-title">您不在签到名单中</text>
<text class="not-in-list-subtitle">抱歉您没有在此次会议的签到名单中</text>
<text class="not-in-list-tip">请联系会议组织者确认您的参会资格</text>
<view class="meeting-info-card">
<text class="card-title">会议信息</text>
<view class="info-item">
<text class="info-label">会议名称</text>
<text class="info-value">{{ meetingInfo?.qdmc || '未设置' }}</text>
</view>
<view class="info-item">
<text class="info-label">会议时间</text>
<text class="info-value">{{ formatTime(meetingInfo?.qdkstime) }} - {{ formatTime(meetingInfo?.qdjstime) }}</text>
</view>
<view class="info-item">
<text class="info-label">会议地点</text>
<text class="info-value">{{ meetingInfo?.qdwz || '未设置' }}</text>
</view>
</view>
<button @click="goBack" class="back-btn">返回</button>
</view>
</view>
<!-- 签到时间未开始阶段 -->
<view v-else-if="currentStep === 'timeNotStarted'" class="time-not-started-step">
<view class="time-not-started-content">
<u-icon name="clock" size="80" color="#409EFF" />
<text class="time-not-started-title">签到时间未开始</text>
<text class="time-not-started-subtitle">签到打卡时间还未开始请耐心等待</text>
<text class="time-not-started-tip">请关注签到开始时间</text>
<view class="meeting-info-card">
<text class="card-title">会议信息</text>
<view class="info-item">
<text class="info-label">会议名称</text>
<text class="info-value">{{ meetingInfo?.qdmc || '未设置' }}</text>
</view>
<view class="info-item">
<text class="info-label">签到时间</text>
<text class="info-value">{{ formatTime(meetingInfo?.qdkstime) }} - {{ formatTime(meetingInfo?.qdjstime) }}</text>
</view>
<view class="info-item">
<text class="info-label">打卡开始</text>
<text class="info-value">{{ formatTime(meetingInfo?.dkkstime) }}</text>
</view>
<view class="info-item">
<text class="info-label">会议地点</text>
<text class="info-value">{{ meetingInfo?.qdwz || '未设置' }}</text>
</view>
<view class="info-item">
<text class="info-label">当前时间</text>
<text class="info-value">{{ formatTime(new Date()) }}</text>
</view>
</view>
<button @click="goBack" class="back-btn">返回</button>
</view>
</view>
<!-- 签到时间已结束阶段 -->
<view v-else-if="currentStep === 'timeExpired'" class="time-expired-step">
<view class="time-expired-content">
<u-icon name="clock" size="80" color="#E6A23C" />
<text class="time-expired-title">签到时间已结束</text>
<text class="time-expired-subtitle">抱歉本次签到的时间已经结束</text>
<text class="time-expired-tip">请关注下次签到通知</text>
<view class="meeting-info-card">
<text class="card-title">会议信息</text>
<view class="info-item">
<text class="info-label">会议名称</text>
<text class="info-value">{{ meetingInfo?.qdmc || '未设置' }}</text>
</view>
<view class="info-item">
<text class="info-label">会议时间</text>
<text class="info-value">{{ formatTime(meetingInfo?.qdkstime) }} - {{ formatTime(meetingInfo?.qdjstime) }}</text>
</view>
<view class="info-item">
<text class="info-label">会议地点</text>
<text class="info-value">{{ meetingInfo?.qdwz || '未设置' }}</text>
</view>
<view class="info-item">
<text class="info-label">当前时间</text>
<text class="info-value">{{ formatTime(new Date()) }}</text>
</view>
</view>
<button @click="goBack" class="back-btn">返回</button>
</view>
</view>
<!-- 重复签到阶段 -->
<view v-else-if="currentStep === 'alreadySigned'" class="already-signed-step">
<view class="already-signed-content">
<u-icon name="checkmark-circle" size="80" color="#67C23A" />
<text class="already-signed-title">您已签到成功</text>
<text class="already-signed-subtitle">您已经完成本次签到请勿重复签到</text>
<text class="already-signed-tip">如需重新签到请联系会议组织者</text>
<view class="meeting-info-card">
<text class="card-title">会议信息</text>
<view class="info-item">
<text class="info-label">会议名称</text>
<text class="info-value">{{ meetingInfo?.qdmc || '未设置' }}</text>
</view>
<view class="info-item">
<text class="info-label">会议时间</text>
<text class="info-value">{{ formatTime(meetingInfo?.qdkstime) }} - {{ formatTime(meetingInfo?.qdjstime) }}</text>
</view>
<view class="info-item">
<text class="info-label">会议地点</text>
<text class="info-value">{{ meetingInfo?.qdwz || '未设置' }}</text>
</view>
<view class="info-item">
<text class="info-label">签到时间</text>
<text class="info-value">{{ formatTime(qdzxRecord?.qdwctime) }}</text>
</view>
</view>
<button @click="goBack" class="back-btn">返回</button>
</view>
</view>
</view>
<!-- 签名组件 -->
<BasicSign v-if="showSignature" ref="signCompRef" :title="signTitle"></BasicSign>
</template>
<script lang="ts" setup>
import { ref, reactive, onMounted, onUnmounted, nextTick } from 'vue';
import { onLoad } from '@dcloudio/uni-app';
import { qdFindByIdApi, qdzxSignInApi, qdzxFindByQdParamsApi, qdzxFindByQdAndJsApi } from '@/api/base/server';
import { useUserStore } from '@/store/modules/user';
const { checkToken } = useUserStore();
//
const options = ref<any>({});
//
onLoad((params) => {
console.log('confirmself.vue onLoad - 接收到的参数:', params);
// URLqdId
if (params && params.qdId) {
console.log('confirmself.vue onLoad - 检测到qdId参数:', params.qdId);
options.value = params;
//
setTimeout(() => {
console.log('confirmself.vue onLoad - 开始执行initializePage');
initializePage();
}, 100);
} else {
console.log('confirmself.vue onLoad - 没有qdId参数显示错误');
uni.showToast({ title: '缺少签到ID参数', icon: 'none' });
setTimeout(() => {
uni.navigateBack();
}, 1500);
}
});
//
const qdId = ref('');
const qdzxId = ref('');
//
const currentStep = ref<'sign' | 'confirm' | 'success' | 'notInList' | 'timeNotStarted' | 'timeExpired' | 'alreadySigned'>('confirm');
//
const userInfo = ref<any>(null);
//
const meetingInfo = ref<any>(null);
//
const qdzxRecord = ref<any>(null);
//
const signCompRef = ref<any>(null);
const signTitle = ref<string>("签到签名");
const sign_file = ref<string>("");
const showSignature = ref<boolean>(false);
// store
const userStore = useUserStore();
//
const initializePage = async () => {
console.log('confirmself.vue initializePage - 开始初始化');
console.log('confirmself.vue initializePage - options.value:', options.value);
// ID
qdId.value = options.value.qdId;
console.log('confirmself.vue initializePage - 设置qdId:', qdId.value);
//
const jsData = userStore.getJs;
console.log('confirmself.vue initializePage - 获取教师信息:', jsData);
if (jsData && Object.keys(jsData).length > 0) {
userInfo.value = jsData;
console.log('confirmself.vue initializePage - 教师信息有效,继续执行');
} else {
console.log('confirmself.vue initializePage - 教师信息无效,跳转登录页面');
uni.showToast({ title: '请先登录', icon: 'none' });
//
setTimeout(() => {
uni.navigateTo({
url: '/pages/system/login/login'
});
}, 1500);
return;
}
// qdIdID
console.log('confirmself.vue initializePage - 准备调用checkTeacherSignInPermission');
await checkTeacherSignInPermission();
};
//
onMounted(async () => {
// onLoad
// DOM
});
//
const checkTeacherSignInPermission = async () => {
console.log('confirmself.vue checkTeacherSignInPermission - 开始检查签到权限');
console.log('confirmself.vue checkTeacherSignInPermission - qdId:', qdId.value);
console.log('confirmself.vue checkTeacherSignInPermission - userInfo.value.id:', userInfo.value?.id);
try {
console.log('confirmself.vue checkTeacherSignInPermission - 准备调用qdzxFindByQdAndJsApi');
const result = await qdzxFindByQdAndJsApi({
qdId: qdId.value,
jsId: userInfo.value.id
});
console.log('confirmself.vue checkTeacherSignInPermission - API调用结果:', result);
if (result && result.resultCode === 1 && result.result) {
//
console.log('confirmself.vue checkTeacherSignInPermission - 找到签到记录');
qdzxRecord.value = result.result;
qdzxId.value = result.result.id;
//
console.log('confirmself.vue checkTeacherSignInPermission - 准备调用loadMeetingInfo');
await loadMeetingInfo();
} else if (result && result.resultCode === 0) {
//
console.log('confirmself.vue checkTeacherSignInPermission - 未找到签到记录');
currentStep.value = 'notInList';
await loadMeetingInfo(); //
} else {
//
console.log('confirmself.vue checkTeacherSignInPermission - 查询失败:', result);
uni.showToast({ title: '查询签到权限失败', icon: 'none' });
}
} catch (error) {
console.error('confirmself.vue checkTeacherSignInPermission - 网络异常:', error);
uni.showToast({ title: '网络异常,请重试', icon: 'none' });
}
};
//
const loadMeetingInfo = async () => {
try {
const result = await qdFindByIdApi({ id: qdId.value });
if (result && result.resultCode === 1) {
meetingInfo.value = result.result;
// 1.
const currentTime = new Date();
const startTime = meetingInfo.value?.dkkstime ? new Date(meetingInfo.value.dkkstime) : null;
const endTime = meetingInfo.value?.qdjstime ? new Date(meetingInfo.value.qdjstime) : null;
//
if (startTime && currentTime < startTime) {
// ""
currentStep.value = 'timeNotStarted';
return;
}
//
if (endTime && currentTime > endTime) {
// ""
currentStep.value = 'timeExpired';
return;
}
// qdzxId
if (qdzxId.value) {
//
if (qdzxRecord.value?.qdStatus === '1') {
//
currentStep.value = 'alreadySigned';
return;
}
//
if (meetingInfo.value?.mdqz === '1') {
//
await handleSignature();
} else {
//
currentStep.value = 'confirm';
}
}
}
} catch (error) {
uni.showToast({ title: '加载会议信息失败', icon: 'none' });
}
};
//
const handleSignature = async () => {
try {
showSignature.value = true;
sign_file.value = '';
signTitle.value = "签到签名";
//
await nextTick();
const data = await signCompRef.value.getSyncSignature();
sign_file.value = data.base64;
showSignature.value = false;
//
currentStep.value = 'confirm';
} catch (error) {
showSignature.value = false;
uni.showToast({ title: '签名失败', icon: 'none' });
}
};
//
const submitSignIn = async () => {
try {
const params: any = {
qdzxId: qdzxId.value,
signInTime: new Date().toISOString() // ISO
};
//
if (sign_file.value) {
params.signatureImage = sign_file.value;
}
const result = await qdzxSignInApi(params);
if (result && result.resultCode === 1) {
currentStep.value = 'success';
} else {
const errorMsg = result?.message || '签到失败';
uni.showToast({ title: errorMsg, icon: 'none' });
}
} catch (error) {
uni.showToast({ title: '网络异常,请重试', icon: 'none' });
}
};
//
const formatTime = (time: string | Date) => {
if (!time) return '未设置';
const date = new Date(time);
return date.toLocaleString('zh-CN', {
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit'
});
};
//
const goBack = () => {
uni.navigateBack();
};
</script>
<style lang="scss" scoped>
.confirm-page {
min-height: 100vh;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
padding: 20px;
box-sizing: border-box;
}
//
.confirm-step {
background: white;
border-radius: 16px;
padding: 24px;
margin-top: 40px;
}
.confirm-header {
text-align: center;
margin-bottom: 24px;
.confirm-title {
font-size: 24px;
font-weight: 600;
color: #333;
}
}
.meeting-info {
margin-bottom: 24px;
.info-item {
display: flex;
margin-bottom: 16px;
align-items: flex-start;
.info-label {
font-size: 14px;
color: #666;
min-width: 80px;
text-align: right !important;
margin-right: 12px;
}
.info-value {
font-size: 14px;
color: #333;
flex: 1;
text-align: left !important;
}
}
}
.signature-preview {
margin-bottom: 24px;
.preview-label {
display: block;
font-size: 14px;
color: #666;
margin-bottom: 8px;
}
.signature-preview-img {
width: 100%;
height: 100px;
border: 1px solid #ddd;
border-radius: 8px;
}
}
.submit-btn {
width: 100%;
height: 44px;
background: linear-gradient(135deg, #67C23A 0%, #85ce61 100%);
color: white;
border: none;
border-radius: 8px;
font-size: 16px;
font-weight: 600;
}
//
.success-step {
background: white;
border-radius: 16px;
padding: 40px 24px;
margin-top: 40px;
text-align: center;
}
.success-content {
.success-title {
display: block;
font-size: 24px;
font-weight: 600;
color: #333;
margin: 16px 0 8px;
}
.success-time {
display: block;
font-size: 16px;
color: #666;
margin-bottom: 16px;
}
.success-tip {
font-size: 14px;
color: #999;
}
}
//
.not-in-list-step {
background: white;
border-radius: 16px;
padding: 24px;
margin-top: 40px;
text-align: center;
}
.not-in-list-content {
.not-in-list-title {
display: block;
font-size: 24px;
font-weight: 600;
color: #333;
margin: 16px 0 8px;
}
.not-in-list-subtitle {
font-size: 14px;
color: #666;
margin-bottom: 16px;
}
.not-in-list-tip {
font-size: 14px;
color: #999;
margin-bottom: 24px;
}
}
.meeting-info-card {
background: #f9f9f9;
border-radius: 8px;
padding: 16px;
margin-bottom: 24px;
.card-title {
font-size: 16px;
font-weight: 600;
color: #333;
margin-bottom: 12px;
padding-bottom: 8px;
border-bottom: 1px solid #eee;
}
.info-item {
display: flex;
margin-bottom: 12px;
align-items: flex-start;
.info-label {
font-size: 14px;
color: #666;
min-width: 80px;
text-align: right !important;
margin-right: 12px;
}
.info-value {
font-size: 14px;
color: #333;
flex: 1;
text-align: left !important;
}
}
}
.back-btn {
width: 100%;
height: 44px;
background: #f5f5f5;
color: #666;
border: none;
border-radius: 8px;
font-size: 16px;
}
/* 签到时间未开始阶段 */
.time-not-started-step {
background: white;
border-radius: 16px;
padding: 40px 24px;
margin-top: 40px;
text-align: center;
}
.time-not-started-content {
.time-not-started-title {
display: block;
font-size: 24px;
font-weight: 600;
color: #333;
margin: 16px 0 8px;
}
.time-not-started-subtitle {
font-size: 14px;
color: #666;
margin-bottom: 16px;
}
.time-not-started-tip {
font-size: 14px;
color: #999;
margin-bottom: 24px;
}
}
/* 签到时间已结束阶段 */
.time-expired-step {
background: white;
border-radius: 16px;
padding: 40px 24px;
margin-top: 40px;
text-align: center;
}
.time-expired-content {
.time-expired-title {
display: block;
font-size: 24px;
font-weight: 600;
color: #333;
margin: 16px 0 8px;
}
.time-expired-subtitle {
font-size: 14px;
color: #666;
margin-bottom: 16px;
}
.time-expired-tip {
font-size: 14px;
color: #999;
margin-bottom: 24px;
}
}
/* 重复签到阶段 */
.already-signed-step {
background: white;
border-radius: 16px;
padding: 40px 24px;
margin-top: 40px;
text-align: center;
}
.already-signed-content {
.already-signed-title {
display: block;
font-size: 24px;
font-weight: 600;
color: #333;
margin: 16px 0 8px;
}
.already-signed-subtitle {
font-size: 14px;
color: #666;
margin-bottom: 16px;
}
.already-signed-tip {
font-size: 14px;
color: #999;
margin-bottom: 24px;
}
}
</style>

View File

@ -84,22 +84,34 @@
</view>
<view class="card-footer">
<view class="footer-actions">
<view class="action-item" @click="goToQRCode(data.id)">
<image
src="/static/base/qr-code.png"
class="footer-action-icon qr-icon"
@click="goToQRCode(data.id)"
/>
<view v-if="showTooltip" class="tooltip">二维码</view>
</view>
<view class="action-item" @click="goToSignIn(data.id)">
<image
src="/static/base/view/qdself.png"
class="footer-action-icon qdself-icon"
/>
<view v-if="showTooltip" class="tooltip">签到</view>
</view>
<view class="action-item" @click="goToFeedback(data.id)">
<image
src="/static/base/details.png"
class="footer-action-icon details-icon"
@click="goToFeedback(data.id)"
/>
<view v-if="showTooltip" class="tooltip">详情</view>
</view>
<view v-if="data.qdStatus === 'A'" class="action-item" @click="goToPush(data.id)">
<image
v-if="data.qdStatus === 'A'"
src="/static/base/push.png"
class="footer-action-icon push-icon"
@click="goToPush(data.id)"
/>
<view v-if="showTooltip" class="tooltip">推送</view>
</view>
</view>
</view>
</view>
@ -124,6 +136,7 @@
import { qdFindPageApi } from "@/api/base/server";
import { ref, reactive, onMounted } from "vue";
import { onShow } from "@dcloudio/uni-app";
import { useUserStore } from "@/store/modules/user";
interface QdItem {
id: string;
@ -149,6 +162,9 @@ const searchForm = reactive({
const dataList = ref<QdItem[]>([]);
const isLoading = ref(false);
//
const showTooltip = ref(true);
//
const onStartTimeChange = (e: any) => {
searchForm.startTime = e.detail.value;
@ -258,6 +274,43 @@ const goToQRCode = (id: string) => {
});
};
//
const goToSignIn = (id: string) => {
// store
const userStore = useUserStore();
//
const jsData = userStore.getJs;
//
const qdItem = dataList.value.find(item => item.id === id);
if (!qdItem) {
uni.showToast({ title: '签到信息不存在', icon: 'none' });
return;
}
//
if (jsData && jsData.id && qdItem.jsId) {
if (jsData.id !== qdItem.jsId) {
uni.showToast({
title: '只有发布者才能使用点击签到功能',
icon: 'none',
duration: 3000
});
return;
}
} else {
uni.showToast({ title: '用户信息获取失败,请重新登录', icon: 'none' });
return;
}
//
uni.navigateTo({
url: `/pages/view/routine/qd/confirmself?qdId=${id}`
});
};
//
onShow(() => {
getQdList();
@ -266,6 +319,11 @@ onShow(() => {
//
onMounted(() => {
getQdList();
// 6
setTimeout(() => {
showTooltip.value = false;
}, 6000);
});
</script>
@ -474,6 +532,14 @@ onMounted(() => {
display: flex;
gap: 10px;
.action-item {
position: relative;
display: flex;
flex-direction: column;
align-items: center;
padding: 5px;
}
.footer-action-icon {
padding: 5px;
}
@ -484,6 +550,22 @@ onMounted(() => {
cursor: pointer;
}
.qdself-icon {
width: 22px;
height: 22px;
cursor: pointer;
transition: all 0.2s ease;
&:hover {
transform: scale(1.1);
opacity: 0.8;
}
&:active {
transform: scale(0.95);
}
}
.details-icon {
width: 22px;
height: 22px;
@ -498,6 +580,43 @@ onMounted(() => {
}
}
//
.tooltip {
position: absolute;
top: -35px;
left: 50%;
transform: translateX(-50%);
background: rgba(0, 0, 0, 0.8);
color: white;
padding: 4px 8px;
border-radius: 4px;
font-size: 12px;
white-space: nowrap;
z-index: 1000;
animation: tooltipFadeIn 0.3s ease-out;
&::after {
content: '';
position: absolute;
top: 100%;
left: 50%;
transform: translateX(-50%);
border: 4px solid transparent;
border-top-color: rgba(0, 0, 0, 0.8);
}
}
@keyframes tooltipFadeIn {
from {
opacity: 0;
transform: translateX(-50%) translateY(-5px);
}
to {
opacity: 1;
transform: translateX(-50%) translateY(0);
}
}
// -
.add-button-fixed {
position: fixed;

View File

@ -42,8 +42,23 @@
</picker>
</view>
<!-- 自定义教师选择 -->
<view class="filter-row" v-if="selectType === 0">
<view class="filter-label">{{ getSecondSelectLabel() }}</view>
<view class="custom-teacher-picker">
<BasicJsPicker
:defaultValue="customSelectedTeachers"
:multiple="true"
@change="onCustomTeacherChange"
placeholder="请选择教师"
title="选择教师"
ref="customTeacherPickerRef"
/>
</view>
</view>
<!-- 具体选择 -->
<view class="filter-row" v-if="selectType && selectType !== 1">
<view class="filter-row" v-if="selectType && selectType !== 1 && selectType !== 0">
<view class="filter-label">{{ getSecondSelectLabel() }}</view>
<view class="multi-select-container">
<view class="selected-items-display" @click="showMultiSelectModal">
@ -60,6 +75,11 @@
<text class="tip-text">💡 提示选择"所有老师"将直接加载所有教师数据</text>
</view>
<!-- 自定义教师提示 -->
<view class="filter-tip" v-if="selectType === 0">
<text class="tip-text">💡 提示选择"自定义教师"可以手动选择特定的教师</text>
</view>
<!-- 多选弹窗 -->
<view v-if="showModal" class="modal-overlay" @click="hideMultiSelectModal">
<view class="modal-content" @click.stop>
@ -159,6 +179,7 @@ import {
kmFindAllApi,
zwFindAllApi
} from "@/api/base/server";
import BasicJsPicker from '@/components/BasicJsPicker/Picker.vue';
interface TeacherInfo {
id: string;
@ -177,8 +198,13 @@ const selectedTeachers = ref<TeacherInfo[]>([]);
const isLoading = ref(false);
const showModal = ref(false); //
//
const customTeacherPickerRef = ref<any>(null);
const customSelectedTeachers = ref<string[]>([]);
//
const selectTypeOptions = [
{ value: 0, label: '自定义教师' },
{ value: 1, label: '所有老师' },
{ value: 2, label: '按科目' },
{ value: 3, label: '按班主任' },
@ -207,6 +233,8 @@ const getZwTypeText = () => {
//
const getSecondSelectLabel = () => {
switch (selectType.value) {
case 0:
return '选择教师';
case 1:
return '年级/班级';
case 2:
@ -241,6 +269,12 @@ const onSelectTypeChange = async (e: any) => {
selectType.value = selectTypeOptions[e.detail.value].value;
selectTwoType.value = [];
selectedTeachers.value = [];
customSelectedTeachers.value = [];
// ""
if (selectType.value === 0) {
return;
}
// ""
if (selectType.value === 1) {
@ -293,6 +327,25 @@ const confirmMultiSelect = () => {
loadTeachers();
};
//
const onCustomTeacherChange = (teachers: any[]) => {
console.log('自定义教师选择变化:', teachers);
// ID
customSelectedTeachers.value = teachers.map(teacher => teacher.value || teacher.id);
//
selectedTeachers.value = teachers.map(teacher => ({
id: teacher.id || teacher.value,
jsxm: teacher.jsxm || teacher.label,
jsId: teacher.id || teacher.value,
dzzw: teacher.dzzw || '',
qtzw: teacher.qtzw || ''
}));
console.log('处理后的自定义教师数据:', selectedTeachers.value);
};
// localStorage
const loadAllTeachersFromStorage = async () => {
try {
@ -1114,6 +1167,10 @@ const ensureTeacherDataCached = async () => {
position: relative;
}
.custom-teacher-picker {
flex: 1;
}
.selected-items-display {
display: flex;
justify-content: space-between;

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB