|
|
@@ -1,5 +1,5 @@
|
|
|
<template >
|
|
|
- <div v-loading="loading">
|
|
|
+ <div class="watch-reward-page" v-loading="loading">
|
|
|
<!-- 提示信息 -->
|
|
|
<div class="tip-message" >
|
|
|
设置观看奖励,用户达到直播观看时长后可领取奖励
|
|
|
@@ -88,6 +88,39 @@
|
|
|
<!-- </el-form-item>-->
|
|
|
|
|
|
|
|
|
+ <div v-if="watchRewardForm.participateCondition === '3'">
|
|
|
+ <div class="section-title">直播红包答题设置</div>
|
|
|
+ <el-form-item label="可答题次数">
|
|
|
+ <el-input-number
|
|
|
+ v-model="watchRewardForm.answerAttempts"
|
|
|
+ :min="1"
|
|
|
+ :precision="0"
|
|
|
+ placeholder="请输入可答题次数"
|
|
|
+ style="width: 200px;"
|
|
|
+ ></el-input-number>
|
|
|
+ </el-form-item>
|
|
|
+ <el-button type="primary" plain icon="el-icon-plus" style="margin-bottom: 1%" @click="openQuestionDialog">选择试题</el-button>
|
|
|
+ <div v-if="selectedQuestionList.length > 0" class="selected-question-card-list">
|
|
|
+ <div
|
|
|
+ v-for="row in selectedQuestionList"
|
|
|
+ :key="row.id"
|
|
|
+ class="selected-question-card"
|
|
|
+ >
|
|
|
+ <div class="selected-question-card-body">
|
|
|
+ <div class="selected-question-card-title">{{ row.title }}</div>
|
|
|
+ <div v-if="row.answer" class="selected-question-card-answer">答案:{{ row.answer }}</div>
|
|
|
+ <div class="selected-question-card-meta">
|
|
|
+ <el-tag :type="row.type === 1 ? 'primary' : 'success'" size="small">{{ row.type === 1 ? '单选题' : '多选题' }}</el-tag>
|
|
|
+ <span class="selected-question-card-creator">{{ row.createBy }}</span>
|
|
|
+ <span class="selected-question-card-time">{{ row.createTime }}</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <el-button type="text" class="selected-question-card-remove" @click="removeSelectedQuestion(row)">移除</el-button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ </div>
|
|
|
+
|
|
|
<div v-if="watchRewardForm.participateCondition === '3'">
|
|
|
<div class="section-title">直播红包设置</div>
|
|
|
<!-- 红包金额 -->
|
|
|
@@ -130,7 +163,7 @@
|
|
|
</el-checkbox-group>
|
|
|
<el-input-number v-if="item.rewardTypes.includes('1')" v-model="item.redPacketAmount" :min="0.1" :max="10" :step="0.1" style="width: 140px; margin-left: 15px;"></el-input-number>
|
|
|
<el-input v-if="item.rewardTypes.includes('2')" v-model="item.scoreAmount" placeholder="积分值" style="width: 140px; margin-left: 15px;"></el-input>
|
|
|
- <el-select v-if="item.rewardTypes.includes('3')" v-model="item.couponId" placeholder="请选择核销卷" clearable style="width: 200px; margin-left: 15px;">
|
|
|
+ <el-select v-if="item.rewardTypes.includes('3')" v-model="item.couponIds" placeholder="请选择核销卷" clearable multiple style="width: 200px; margin-left: 15px;">
|
|
|
<el-option
|
|
|
v-for="c in couponList"
|
|
|
:key="c.id"
|
|
|
@@ -255,6 +288,68 @@
|
|
|
</div>
|
|
|
</el-form>
|
|
|
</div>
|
|
|
+
|
|
|
+ <!-- 选择今日问题弹窗 -->
|
|
|
+ <el-dialog
|
|
|
+ title="选择今日问题"
|
|
|
+ :visible.sync="questionDialogVisible"
|
|
|
+ width="800px"
|
|
|
+ append-to-body
|
|
|
+ :close-on-click-modal="false"
|
|
|
+ custom-class="question-select-dialog"
|
|
|
+ >
|
|
|
+ <div style="text-align: right; margin-bottom: 16px;">
|
|
|
+ <el-input
|
|
|
+ v-model="questionSearchTitle"
|
|
|
+ placeholder="请输入题干搜索"
|
|
|
+ style="width: 300px;"
|
|
|
+ clearable
|
|
|
+ @keyup.enter.native="handleQuestionSearch"
|
|
|
+ >
|
|
|
+ <el-button slot="append" icon="el-icon-search" @click="handleQuestionSearch"></el-button>
|
|
|
+ </el-input>
|
|
|
+ </div>
|
|
|
+ <div v-loading="questionLoading" class="question-card-list">
|
|
|
+ <div
|
|
|
+ v-for="row in questionOptionList"
|
|
|
+ :key="row.id"
|
|
|
+ class="question-card"
|
|
|
+ :class="{ 'is-selected': isQuestionSelected(row.id) }"
|
|
|
+ @click="toggleQuestionCard(row)"
|
|
|
+ >
|
|
|
+ <div class="question-card-check">
|
|
|
+ <i v-if="isQuestionSelected(row.id)" class="el-icon-success" style="color: #409EFF; font-size: 20px;"></i>
|
|
|
+ <span v-else class="question-card-check-empty"></span>
|
|
|
+ </div>
|
|
|
+ <div class="question-card-body">
|
|
|
+ <div class="question-card-title">{{ row.title }}</div>
|
|
|
+ <div v-if="row.answer" class="question-card-answer">答案:{{ row.answer }}</div>
|
|
|
+ <div class="question-card-meta">
|
|
|
+ <el-tag :type="row.type === 1 ? 'primary' : 'success'" size="small">{{ row.type === 1 ? '单选' : '多选' }}</el-tag>
|
|
|
+ <span class="question-card-creator">{{ row.createBy }}</span>
|
|
|
+ <span class="question-card-time">{{ row.createTime }}</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div v-if="!questionLoading && questionOptionList.length === 0" class="question-card-empty">暂无数据</div>
|
|
|
+ </div>
|
|
|
+ <pagination
|
|
|
+ v-show="questionOptionTotal > 0"
|
|
|
+ :total="questionOptionTotal"
|
|
|
+ :page.sync="questionQueryParams.pageNum"
|
|
|
+ :limit.sync="questionQueryParams.pageSize"
|
|
|
+ @pagination="loadQuestionOptions"
|
|
|
+ style="margin-top: 16px;"
|
|
|
+ />
|
|
|
+ <div slot="footer">
|
|
|
+ <span style="float: left; line-height: 32px; color: #606266;">
|
|
|
+ 已选择 <span style="color: #409EFF;">{{ tempSelectedQuestions.length }}</span> 题
|
|
|
+ </span>
|
|
|
+ <el-button @click="questionDialogVisible = false">取 消</el-button>
|
|
|
+ <el-button type="primary" @click="confirmQuestionSelection">确 定</el-button>
|
|
|
+ </div>
|
|
|
+ </el-dialog>
|
|
|
+
|
|
|
</div>
|
|
|
</template>
|
|
|
|
|
|
@@ -262,6 +357,7 @@
|
|
|
import {addConfig, getConfig, updateConfig} from "@/api/live/liveQuestionLive";
|
|
|
import { listStoreCouponIssue } from "@/api/live/liveCouponIssue";
|
|
|
import { options as courserCouponOptions } from '@/api/his/courserCoupon'
|
|
|
+import { getCourseQuestionBank, listCourseQuestionBank } from '@/api/course/courseQuestionBank'
|
|
|
|
|
|
export default {
|
|
|
data() {
|
|
|
@@ -301,7 +397,7 @@ export default {
|
|
|
// 是否录播可领取奖励
|
|
|
recordRedPacketEnabled: false,
|
|
|
// 录播奖励配置列表(前端展示用)
|
|
|
- recordTimeRanges: [{ range: null, rewardTypes: ['1'], redPacketAmount: '', scoreAmount: '', couponId: '' }],
|
|
|
+ recordTimeRanges: [{ range: null, rewardTypes: ['1'], redPacketAmount: '', scoreAmount: '', couponIds: [] }],
|
|
|
// 录播奖励配置字符串(提交后端用)
|
|
|
recordTimeRangeStr: '',
|
|
|
// // 最大领取人数
|
|
|
@@ -314,7 +410,11 @@ export default {
|
|
|
// 完课率要求(1-100)
|
|
|
completionRate: 90,
|
|
|
// 连续完课积分配置(第1-10天)
|
|
|
- pointsConfig: [100, 110, 120, 130, 140, 150, 160, 170, 180, 200]
|
|
|
+ pointsConfig: [100, 110, 120, 130, 140, 150, 160, 170, 180, 200],
|
|
|
+ // 可答题次数
|
|
|
+ answerAttempts: 3,
|
|
|
+ // 今日问题ID(逗号分隔)
|
|
|
+ finishQuestionIds: '',
|
|
|
},
|
|
|
rules:{
|
|
|
participateCondition:[
|
|
|
@@ -406,6 +506,20 @@ export default {
|
|
|
timeRangeOverlap: false,
|
|
|
// 核销卷列表(couponType=3)
|
|
|
couponList: [],
|
|
|
+ //答题
|
|
|
+ questionDialogVisible: false,
|
|
|
+ questionLoading: false,
|
|
|
+ questionSearchTitle: '',
|
|
|
+ questionOptionList: [],
|
|
|
+ questionOptionTotal: 0,
|
|
|
+ questionQueryParams: {
|
|
|
+ pageNum: 1,
|
|
|
+ pageSize: 10,
|
|
|
+ title: null,
|
|
|
+ status: 1
|
|
|
+ },
|
|
|
+ selectedQuestionList: [],
|
|
|
+ tempSelectedQuestions: []
|
|
|
};
|
|
|
},
|
|
|
watch: {
|
|
|
@@ -436,6 +550,7 @@ export default {
|
|
|
this.getCouponList();
|
|
|
},
|
|
|
methods: {
|
|
|
+
|
|
|
// 获取核销卷列表(couponType=3)
|
|
|
getCouponList() {
|
|
|
|
|
|
@@ -448,7 +563,7 @@ export default {
|
|
|
});
|
|
|
},
|
|
|
addRecordTimeRange() {
|
|
|
- this.watchRewardForm.recordTimeRanges.push({ range: null, rewardTypes: ['1'], redPacketAmount: '', scoreAmount: '', couponId: '' })
|
|
|
+ this.watchRewardForm.recordTimeRanges.push({ range: null, rewardTypes: ['1'], redPacketAmount: '', scoreAmount: '', couponIds: [] })
|
|
|
},
|
|
|
removeRecordTimeRange(index) {
|
|
|
this.watchRewardForm.recordTimeRanges.splice(index, 1)
|
|
|
@@ -520,16 +635,20 @@ export default {
|
|
|
if (this.watchRewardForm.recordTimeRangeStr) {
|
|
|
this.watchRewardForm.recordTimeRanges = this.watchRewardForm.recordTimeRangeStr.split(',').map(item => {
|
|
|
const parts = item.split('-')
|
|
|
- return { range: [parts[0], parts[1]], rewardTypes: parts[2] ? parts[2].split('|') : ['1'], redPacketAmount: parts[3] || '', scoreAmount: parts[4] || '', couponId: parts[5] ? Number(parts[5]) : '' }
|
|
|
+ return { range: [parts[0], parts[1]], rewardTypes: parts[2] ? parts[2].split('|') : ['1'], redPacketAmount: parts[3] || '', scoreAmount: parts[4] || '', couponIds: parts[5] ? parts[5].split('~').filter(Boolean).map(Number) : [] }
|
|
|
})
|
|
|
} else {
|
|
|
- this.watchRewardForm.recordTimeRanges = [{ range: null, rewardTypes: ['1'], redPacketAmount: '', scoreAmount: '', couponId: '' }]
|
|
|
+ this.watchRewardForm.recordTimeRanges = [{ range: null, rewardTypes: ['1'], redPacketAmount: '', scoreAmount: '', couponIds: [] }]
|
|
|
}
|
|
|
if(this.watchRewardForm.isRedPackageBalanceDeduction == null){
|
|
|
this.watchRewardForm.isRedPackageBalanceDeduction = '1'
|
|
|
} else {
|
|
|
this.watchRewardForm.isRedPackageBalanceDeduction = String(this.watchRewardForm.isRedPackageBalanceDeduction)
|
|
|
}
|
|
|
+ if(this.watchRewardForm.answerAttempts == null){
|
|
|
+ this.watchRewardForm.answerAttempts = 3
|
|
|
+ }
|
|
|
+ this.loadSelectedQuestions();
|
|
|
}
|
|
|
this.loading = false
|
|
|
})
|
|
|
@@ -540,7 +659,7 @@ export default {
|
|
|
if (submitData.recordTimeRanges && submitData.recordTimeRanges.length > 0) {
|
|
|
submitData.recordTimeRangeStr = submitData.recordTimeRanges
|
|
|
.filter(item => item.range && item.range.length === 2)
|
|
|
- .map(item => item.range[0] + '-' + item.range[1] + '-' + (item.rewardTypes || []).join('|') + '-' + (item.redPacketAmount || '') + '-' + (item.scoreAmount || '') + '-' + (item.couponId || ''))
|
|
|
+ .map(item => item.range[0] + '-' + item.range[1] + '-' + (item.rewardTypes || []).join('|') + '-' + (item.redPacketAmount || '') + '-' + (item.scoreAmount || '') + '-' + (item.couponIds || []).join('~'))
|
|
|
.join(',')
|
|
|
} else {
|
|
|
submitData.recordTimeRangeStr = ''
|
|
|
@@ -598,7 +717,7 @@ export default {
|
|
|
this.$message.error('第' + (i + 1) + '个时间段选择了积分,请填写积分值')
|
|
|
return
|
|
|
}
|
|
|
- if (item.rewardTypes.includes('3') && !item.couponId) {
|
|
|
+ if (item.rewardTypes.includes('3') && (!item.couponIds || item.couponIds.length === 0)) {
|
|
|
this.$message.error('第' + (i + 1) + '个时间段选择了核销卷,请选择核销卷')
|
|
|
return
|
|
|
}
|
|
|
@@ -608,7 +727,7 @@ export default {
|
|
|
if (submitData.recordTimeRanges && submitData.recordTimeRanges.length > 0) {
|
|
|
submitData.recordTimeRangeStr = submitData.recordTimeRanges
|
|
|
.filter(item => item.range && item.range.length === 2)
|
|
|
- .map(item => item.range[0] + '-' + item.range[1] + '-' + (item.rewardTypes || []).join('|') + '-' + (item.redPacketAmount || '') + '-' + (item.scoreAmount || '') + '-' + (item.couponId || ''))
|
|
|
+ .map(item => item.range[0] + '-' + item.range[1] + '-' + (item.rewardTypes || []).join('|') + '-' + (item.redPacketAmount || '') + '-' + (item.scoreAmount || '') + '-' + (item.couponIds || []).join('~'))
|
|
|
.join(',')
|
|
|
} else {
|
|
|
submitData.recordTimeRangeStr = ''
|
|
|
@@ -628,11 +747,83 @@ export default {
|
|
|
}
|
|
|
})
|
|
|
},
|
|
|
+ openQuestionDialog() {
|
|
|
+ this.questionDialogVisible = true;
|
|
|
+ this.questionSearchTitle = '';
|
|
|
+ this.questionQueryParams.pageNum = 1;
|
|
|
+ this.questionQueryParams.title = null;
|
|
|
+ this.tempSelectedQuestions = [...this.selectedQuestionList];
|
|
|
+ this.loadQuestionOptions();
|
|
|
+ },
|
|
|
+ loadQuestionOptions() {
|
|
|
+ this.questionLoading = true;
|
|
|
+ listCourseQuestionBank(this.questionQueryParams).then(response => {
|
|
|
+ this.questionOptionList = response.rows || [];
|
|
|
+ this.questionOptionTotal = response.total || 0;
|
|
|
+ this.questionLoading = false;
|
|
|
+ }).catch(() => {
|
|
|
+ this.questionLoading = false;
|
|
|
+ });
|
|
|
+ },
|
|
|
+ handleQuestionSearch() {
|
|
|
+ this.questionQueryParams.pageNum = 1;
|
|
|
+ this.questionQueryParams.title = this.questionSearchTitle;
|
|
|
+ this.loadQuestionOptions();
|
|
|
+ },
|
|
|
+ isQuestionSelected(id) {
|
|
|
+ return this.tempSelectedQuestions.some(item => item.id === id);
|
|
|
+ },
|
|
|
+ toggleQuestionCard(row) {
|
|
|
+ const idx = this.tempSelectedQuestions.findIndex(item => item.id === row.id);
|
|
|
+ if (idx > -1) {
|
|
|
+ this.tempSelectedQuestions.splice(idx, 1);
|
|
|
+ } else {
|
|
|
+ this.tempSelectedQuestions.push(row);
|
|
|
+ }
|
|
|
+ },
|
|
|
+ confirmQuestionSelection() {
|
|
|
+ if (this.tempSelectedQuestions.length === 0) {
|
|
|
+ this.$message.warning('请至少选择一题');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ this.selectedQuestionList = [...this.tempSelectedQuestions];
|
|
|
+ this.syncFinishQuestionIds();
|
|
|
+ this.questionDialogVisible = false;
|
|
|
+ },
|
|
|
+ removeSelectedQuestion(row) {
|
|
|
+ this.selectedQuestionList = this.selectedQuestionList.filter(item => item.id !== row.id);
|
|
|
+ this.syncFinishQuestionIds();
|
|
|
+ },
|
|
|
+ syncFinishQuestionIds() {
|
|
|
+ this.watchRewardForm.finishQuestionIds = this.selectedQuestionList.map(item => item.id).join(',');
|
|
|
+ },
|
|
|
+ loadSelectedQuestions() {
|
|
|
+ if (!this.watchRewardForm.finishQuestionIds) {
|
|
|
+ this.selectedQuestionList = [];
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ const ids = this.watchRewardForm.finishQuestionIds.split(',').filter(Boolean);
|
|
|
+ if (ids.length === 0) {
|
|
|
+ this.selectedQuestionList = [];
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ Promise.all(ids.map(id => getCourseQuestionBank(id))).then(results => {
|
|
|
+ this.selectedQuestionList = results
|
|
|
+ .filter(res => res.code === 200 && res.data)
|
|
|
+ .map(res => res.data);
|
|
|
+ });
|
|
|
+ }
|
|
|
}
|
|
|
};
|
|
|
</script>
|
|
|
|
|
|
<style scoped>
|
|
|
+.watch-reward-page {
|
|
|
+ min-height: 100%;
|
|
|
+ padding-bottom: 40px;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
/* 录播奖励配置项样式 */
|
|
|
.record-reward-item {
|
|
|
display: flex;
|
|
|
@@ -747,4 +938,138 @@ export default {
|
|
|
padding: 8px 20px;
|
|
|
font-size: 13px;
|
|
|
}
|
|
|
+
|
|
|
+/* 题目卡片列表 */
|
|
|
+.question-card-list {
|
|
|
+ max-height: 400px;
|
|
|
+ overflow-y: auto;
|
|
|
+ padding-right: 4px;
|
|
|
+}
|
|
|
+.question-card {
|
|
|
+ display: flex;
|
|
|
+ align-items: flex-start;
|
|
|
+ padding: 14px 16px;
|
|
|
+ margin-bottom: 10px;
|
|
|
+ border: 1px solid #e4e7ed;
|
|
|
+ border-radius: 6px;
|
|
|
+ cursor: pointer;
|
|
|
+ transition: border-color 0.2s, background-color 0.2s;
|
|
|
+}
|
|
|
+.question-card:hover {
|
|
|
+ border-color: #c0c4cc;
|
|
|
+ background-color: #f5f7fa;
|
|
|
+}
|
|
|
+.question-card.is-selected {
|
|
|
+ border-color: #409EFF;
|
|
|
+ background-color: #ecf5ff;
|
|
|
+}
|
|
|
+.question-card-check {
|
|
|
+ flex-shrink: 0;
|
|
|
+ width: 24px;
|
|
|
+ height: 24px;
|
|
|
+ margin-right: 12px;
|
|
|
+ margin-top: 2px;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+}
|
|
|
+.question-card-check-empty {
|
|
|
+ width: 18px;
|
|
|
+ height: 18px;
|
|
|
+ border: 2px solid #dcdfe6;
|
|
|
+ border-radius: 50%;
|
|
|
+}
|
|
|
+.question-card-body {
|
|
|
+ flex: 1;
|
|
|
+ min-width: 0;
|
|
|
+}
|
|
|
+.question-card-title {
|
|
|
+ font-size: 14px;
|
|
|
+ color: #303133;
|
|
|
+ line-height: 1.5;
|
|
|
+ margin-bottom: 8px;
|
|
|
+ word-break: break-all;
|
|
|
+}
|
|
|
+.question-card-answer {
|
|
|
+ font-size: 12px;
|
|
|
+ color: #67C23A;
|
|
|
+ margin-bottom: 8px;
|
|
|
+ word-break: break-all;
|
|
|
+}
|
|
|
+.question-card-meta {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ gap: 12px;
|
|
|
+ font-size: 12px;
|
|
|
+ color: #909399;
|
|
|
+}
|
|
|
+.question-card-creator {
|
|
|
+ color: #909399;
|
|
|
+}
|
|
|
+.question-card-time {
|
|
|
+ color: #909399;
|
|
|
+ margin-left: auto;
|
|
|
+}
|
|
|
+.question-card-empty {
|
|
|
+ text-align: center;
|
|
|
+ padding: 40px 0;
|
|
|
+ color: #909399;
|
|
|
+ font-size: 14px;
|
|
|
+}
|
|
|
+
|
|
|
+/* 已选题目卡片列表 */
|
|
|
+.selected-question-card-list {
|
|
|
+ margin-bottom: 12px;
|
|
|
+ max-width: 600px;
|
|
|
+}
|
|
|
+.selected-question-card {
|
|
|
+ display: flex;
|
|
|
+ align-items: flex-start;
|
|
|
+ padding: 10px 14px;
|
|
|
+ margin-bottom: 8px;
|
|
|
+ border: 1px solid #e4e7ed;
|
|
|
+ border-radius: 6px;
|
|
|
+ background-color: #fafbfc;
|
|
|
+ transition: border-color 0.2s;
|
|
|
+}
|
|
|
+.selected-question-card:hover {
|
|
|
+ border-color: #c0c4cc;
|
|
|
+}
|
|
|
+.selected-question-card-body {
|
|
|
+ flex: 1;
|
|
|
+ min-width: 0;
|
|
|
+}
|
|
|
+.selected-question-card-title {
|
|
|
+ font-size: 14px;
|
|
|
+ color: #303133;
|
|
|
+ line-height: 1.5;
|
|
|
+ margin-bottom: 6px;
|
|
|
+ word-break: break-all;
|
|
|
+}
|
|
|
+.selected-question-card-answer {
|
|
|
+ font-size: 12px;
|
|
|
+ color: #67C23A;
|
|
|
+ margin-bottom: 6px;
|
|
|
+ word-break: break-all;
|
|
|
+}
|
|
|
+.selected-question-card-meta {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ gap: 12px;
|
|
|
+ font-size: 12px;
|
|
|
+ color: #909399;
|
|
|
+}
|
|
|
+.selected-question-card-creator {
|
|
|
+ color: #909399;
|
|
|
+}
|
|
|
+.selected-question-card-time {
|
|
|
+ color: #909399;
|
|
|
+ margin-left: auto;
|
|
|
+}
|
|
|
+.selected-question-card-remove {
|
|
|
+ flex-shrink: 0;
|
|
|
+ color: #F56C6C !important;
|
|
|
+ margin-left: 12px;
|
|
|
+ padding: 0;
|
|
|
+}
|
|
|
</style>
|