|
|
@@ -203,6 +203,15 @@
|
|
|
|
|
|
</view>
|
|
|
|
|
|
+ <!-- 直播答题入口(socket liveQuizStart 显示,liveQuizClose 隐藏) -->
|
|
|
+ <view class="slide-group live-quiz-entry-wrap" v-if="!isFocus && !isFullscreen && liveQuizShowEntry">
|
|
|
+ <view class="action-button-group end">
|
|
|
+ <view :class="[liveItem.showType === 1 ? 'horizontal' : 'vertical','ml20']" @tap.stop="openLiveQuizSheet">
|
|
|
+ <view class="live-quiz-entry-btn">参与答题</view>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+
|
|
|
<!-- 底部聊天区域 -->
|
|
|
<view class="chat-area-container" :class="{
|
|
|
'chat-area-container2': liveItem.showType == 1,
|
|
|
@@ -387,6 +396,47 @@
|
|
|
</view>
|
|
|
</u-popup>
|
|
|
|
|
|
+ <!-- 课堂答题弹窗(与抽奖弹窗同结构,u-popup) -->
|
|
|
+ <u-popup
|
|
|
+ :show="liveQuizSheetVisible"
|
|
|
+ mode="center"
|
|
|
+ round="40rpx"
|
|
|
+ zIndex="10080"
|
|
|
+ @close="closeLiveQuizSheet"
|
|
|
+ >
|
|
|
+ <view class="lottery-popup live-quiz-lottery-popup">
|
|
|
+ <view class="lottery-content">
|
|
|
+ <view class="lottery-close-section">
|
|
|
+ <view class="close-button-wrapper">
|
|
|
+ <view class="close-button" @click="closeLiveQuizSheet">
|
|
|
+ <u-icon class="close-icon" name="close" color="#fff" size="20"></u-icon>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ <view class="lottery-main-content">
|
|
|
+ <view class="live-quiz-popup-question">{{ liveQuiz.title || '课堂答题' }}</view>
|
|
|
+ <view v-if="Number(liveQuiz.type) === 2" class="live-quiz-popup-type-tip">可多选</view>
|
|
|
+ <view class="live-quiz-popup-options">
|
|
|
+ <view
|
|
|
+ v-for="(quizOpt, idx) in liveQuizOptionList"
|
|
|
+ :key="idx"
|
|
|
+ :class="isQuizOptionSelected(quizOpt) ? 'live-quiz-popup-opt live-quiz-popup-opt-active' : 'live-quiz-popup-opt'"
|
|
|
+ @click="selectQuizOption(quizOpt)"
|
|
|
+ >
|
|
|
+ <view class="quiz-opt-key">{{ numberToLetter(idx) }}.</view>
|
|
|
+ <view class="quiz-opt-label">{{ quizOpt.name }}</view>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ <view
|
|
|
+ class="lottery-action-button"
|
|
|
+ :class="{ 'live-quiz-popup-submit-disabled': !liveQuizCanSubmit || !hasQuizSelection }"
|
|
|
+ @click="submitLiveQuizAnswer"
|
|
|
+ >参与答题</view>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ </u-popup>
|
|
|
+
|
|
|
<!-- 积分弹窗(完课) -->
|
|
|
<!-- showPoints -->
|
|
|
<!-- :show="!!integral.status" -->
|
|
|
@@ -731,7 +781,8 @@
|
|
|
loginByMp,
|
|
|
getUserInfo,
|
|
|
getIsAddKf,
|
|
|
- liveWatchUser
|
|
|
+ liveWatchUser,
|
|
|
+ submitLiveQuiz
|
|
|
} from '@/api/living.js';
|
|
|
import {
|
|
|
editUser
|
|
|
@@ -997,6 +1048,20 @@
|
|
|
diffReplayGenerationSeconds: 0, //经历回放生成的秒速
|
|
|
completionTime: 0, //领取积分所需时间
|
|
|
hasLiveEnd: false, //是否经历过首播结束
|
|
|
+
|
|
|
+ // 直播答题(WebSocket: liveQuizStart / liveQuizClose)
|
|
|
+ liveQuizShowEntry: false,
|
|
|
+ liveQuizSheetVisible: false,
|
|
|
+ liveQuizCanSubmit: true,
|
|
|
+ liveQuiz: {
|
|
|
+ title: '',
|
|
|
+ type: 1,
|
|
|
+ options: [],
|
|
|
+ relId: null,
|
|
|
+ questionBankId: null
|
|
|
+ },
|
|
|
+ liveQuizSelectedKey: null,
|
|
|
+ liveQuizSelectedKeys: [],
|
|
|
isPageLoadFirst: true, //是否首次加载直播间
|
|
|
pointsRetryTimer: null, // 积分领取重试定时器
|
|
|
completionPointsEnabled: false //是否开启积分
|
|
|
@@ -1347,6 +1412,18 @@
|
|
|
formattedLikeCount() {
|
|
|
return this.formatNumber(this.liveViewData.like || 0);
|
|
|
},
|
|
|
+ hasQuizSelection() {
|
|
|
+ if (this.liveQuiz && Number(this.liveQuiz.type) === 2) {
|
|
|
+ return Array.isArray(this.liveQuizSelectedKeys) && this.liveQuizSelectedKeys.length > 0;
|
|
|
+ }
|
|
|
+ return !!this.liveQuizSelectedKey;
|
|
|
+ },
|
|
|
+ // 答题选项列表(模板 v-for 只用稳定数组,避免部分端解析异常)
|
|
|
+ liveQuizOptionList() {
|
|
|
+ const q = this.liveQuiz;
|
|
|
+ if (!q || !Array.isArray(q.options)) return [];
|
|
|
+ return q.options;
|
|
|
+ },
|
|
|
filteredViewers() {
|
|
|
// 获取3个随机假头像,而不是显示真实观众
|
|
|
const avatarCount = 3; // 需要显示的假头像数量
|
|
|
@@ -4960,6 +5037,67 @@
|
|
|
// url: '/pages/home/newindex'
|
|
|
// });
|
|
|
},
|
|
|
+ openLiveQuizSheet() {
|
|
|
+ if (!this.liveQuizCanSubmit) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ this.liveQuizSheetVisible = true;
|
|
|
+ },
|
|
|
+ closeLiveQuizSheet() {
|
|
|
+ this.liveQuizSheetVisible = false;
|
|
|
+ },
|
|
|
+ numberToLetter(num) {
|
|
|
+ return String.fromCharCode(Number(num) + 65);
|
|
|
+ },
|
|
|
+ isQuizOptionSelected(opt) {
|
|
|
+ if (!opt || opt.key == null) return false;
|
|
|
+ if (this.liveQuiz && Number(this.liveQuiz.type) === 2) {
|
|
|
+ return this.liveQuizSelectedKeys.indexOf(opt.key) !== -1;
|
|
|
+ }
|
|
|
+ return this.liveQuizSelectedKey === opt.key;
|
|
|
+ },
|
|
|
+ selectQuizOption(opt) {
|
|
|
+ if (!this.liveQuizCanSubmit || !opt) return;
|
|
|
+ if (Number(this.liveQuiz.type) === 2) {
|
|
|
+ const k = opt.key;
|
|
|
+ const i = this.liveQuizSelectedKeys.indexOf(k);
|
|
|
+ if (i >= 0) {
|
|
|
+ this.liveQuizSelectedKeys.splice(i, 1);
|
|
|
+ } else {
|
|
|
+ this.liveQuizSelectedKeys.push(k);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ this.liveQuizSelectedKey = opt.key;
|
|
|
+ }
|
|
|
+ },
|
|
|
+ async submitLiveQuizAnswer() {
|
|
|
+ if (!this.liveQuizCanSubmit || !this.hasQuizSelection) return;
|
|
|
+ const keys = Number(this.liveQuiz.type) === 2
|
|
|
+ ? [...this.liveQuizSelectedKeys]
|
|
|
+ : [this.liveQuizSelectedKey];
|
|
|
+ try {
|
|
|
+ const res = await submitLiveQuiz({
|
|
|
+ liveId: this.liveId,
|
|
|
+ relId: this.liveQuiz.relId,
|
|
|
+ questionBankId: this.liveQuiz.questionBankId,
|
|
|
+ type: this.liveQuiz.type,
|
|
|
+ answerKeys: keys
|
|
|
+ });
|
|
|
+ if (res && res.code === 200) {
|
|
|
+ if (res.correct === false) {
|
|
|
+ uni.showToast({ title: res.msg || '回答错误', icon: 'none' });
|
|
|
+ } else {
|
|
|
+ uni.showToast({ title: res.msg || '已提交', icon: 'success' });
|
|
|
+ this.liveQuizSheetVisible = false;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ uni.showToast({ title: (res && res.msg) || '提交失败', icon: 'none' });
|
|
|
+ }
|
|
|
+ } catch (e) {
|
|
|
+ console.error('submitLiveQuizAnswer', e);
|
|
|
+ uni.showToast({ title: '网络异常', icon: 'none' });
|
|
|
+ }
|
|
|
+ },
|
|
|
// 点赞
|
|
|
async onLike() {
|
|
|
if (!this.liveId) return;
|
|
|
@@ -5250,7 +5388,7 @@
|
|
|
).toString(CryptoJS.enc.Hex);
|
|
|
|
|
|
try {
|
|
|
- const baseWsUrl = 'wss://ws.klbycp.com/ws/app/webSocket';
|
|
|
+ const baseWsUrl = 'ws://localhost:7114/ws/app/webSocket';
|
|
|
// const baseWsUrl = 'wss://api.fhhx.runtzh.com/ws/app/webSocket';
|
|
|
// const baseWsUrl = 'ws://d6998672.natappfree.cc/ws/app/webSocket';
|
|
|
// const baseWsUrl = 'ws://nd967d83.natappfree.cc/ws/app/webSocket';
|
|
|
@@ -5758,6 +5896,28 @@
|
|
|
});
|
|
|
}
|
|
|
});
|
|
|
+ } else if (socketMessage.cmd == 'liveQuizStart') {
|
|
|
+ try {
|
|
|
+ const rawStr = socketMessage.data;
|
|
|
+ const raw = rawStr ? (typeof rawStr === 'string' ? JSON.parse(rawStr) : rawStr) : {};
|
|
|
+ this.liveQuiz = {
|
|
|
+ title: raw.title || '',
|
|
|
+ type: raw.type != null ? Number(raw.type) : 1,
|
|
|
+ options: Array.isArray(raw.options) ? raw.options : [],
|
|
|
+ relId: raw.relId != null ? raw.relId : null,
|
|
|
+ questionBankId: raw.questionBankId != null ? raw.questionBankId : null
|
|
|
+ };
|
|
|
+ this.liveQuizSelectedKey = null;
|
|
|
+ this.liveQuizSelectedKeys = [];
|
|
|
+ this.liveQuizShowEntry = true;
|
|
|
+ this.liveQuizCanSubmit = true;
|
|
|
+ } catch (err) {
|
|
|
+ console.error('liveQuizStart 解析失败:', err);
|
|
|
+ }
|
|
|
+ } else if (socketMessage.cmd == 'liveQuizClose') {
|
|
|
+ this.liveQuizShowEntry = false;
|
|
|
+ this.liveQuizSheetVisible = false;
|
|
|
+ this.liveQuizCanSubmit = false;
|
|
|
}
|
|
|
} else {
|
|
|
uni.showToast({
|
|
|
@@ -6619,6 +6779,86 @@
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ .live-quiz-entry-wrap {
|
|
|
+ top: calc(60% + 240rpx);
|
|
|
+ }
|
|
|
+
|
|
|
+ .live-quiz-entry-btn {
|
|
|
+ padding: 20rpx 28rpx;
|
|
|
+ background: linear-gradient(270deg, #02B176, #04d68f);
|
|
|
+ color: #fff;
|
|
|
+ font-size: 26rpx;
|
|
|
+ border-radius: 40rpx;
|
|
|
+ font-weight: 500;
|
|
|
+ box-shadow: 0 8rpx 24rpx rgba(2, 177, 118, 0.35);
|
|
|
+ white-space: nowrap;
|
|
|
+ }
|
|
|
+
|
|
|
+ .live-quiz-lottery-popup {
|
|
|
+ .lottery-title-image {
|
|
|
+ margin-bottom: 8rpx;
|
|
|
+ }
|
|
|
+
|
|
|
+ .live-quiz-popup-question {
|
|
|
+ font-size: 28rpx;
|
|
|
+ color: #fff;
|
|
|
+ text-align: center;
|
|
|
+ line-height: 1.45;
|
|
|
+ padding: 0 28rpx 12rpx;
|
|
|
+ max-height: 160rpx;
|
|
|
+ overflow-y: auto;
|
|
|
+ }
|
|
|
+
|
|
|
+ .live-quiz-popup-type-tip {
|
|
|
+ font-size: 24rpx;
|
|
|
+ color: rgba(255, 255, 255, 0.88);
|
|
|
+ margin-bottom: 16rpx;
|
|
|
+ }
|
|
|
+
|
|
|
+ .live-quiz-popup-options {
|
|
|
+ max-height: 340rpx;
|
|
|
+ width: 100%;
|
|
|
+ padding: 0 28rpx;
|
|
|
+ box-sizing: border-box;
|
|
|
+ }
|
|
|
+
|
|
|
+ .live-quiz-popup-opt {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ padding: 20rpx 24rpx;
|
|
|
+ margin-bottom: 14rpx;
|
|
|
+ border-radius: 16rpx;
|
|
|
+ background: rgba(255, 255, 255, 0.96);
|
|
|
+ border: 2rpx solid transparent;
|
|
|
+ box-sizing: border-box;
|
|
|
+
|
|
|
+ &:last-child {
|
|
|
+ margin-bottom: 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ &.live-quiz-popup-opt-active {
|
|
|
+ border-color: #ffeb66;
|
|
|
+ background: #fffef0;
|
|
|
+ }
|
|
|
+
|
|
|
+ .quiz-opt-key {
|
|
|
+ width: 48rpx;
|
|
|
+ font-weight: 600;
|
|
|
+ color: #f4410b;
|
|
|
+ }
|
|
|
+
|
|
|
+ .quiz-opt-label {
|
|
|
+ flex: 1;
|
|
|
+ font-size: 28rpx;
|
|
|
+ color: #333;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .lottery-action-button.live-quiz-popup-submit-disabled {
|
|
|
+ opacity: 0.45;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
// 聊天区域
|
|
|
.chat-area-container {
|
|
|
background: var(--chat-bg);
|