|
@@ -47,12 +47,25 @@
|
|
|
@click="handleDetails(scope.row)"
|
|
@click="handleDetails(scope.row)"
|
|
|
>查看</el-button>
|
|
>查看</el-button>
|
|
|
|
|
|
|
|
- <el-button
|
|
|
|
|
- size="mini"
|
|
|
|
|
- type="text"
|
|
|
|
|
- v-hasPermi="['course:userCourseVideo:edit']"
|
|
|
|
|
- @click="updateMoney(scope.row)"
|
|
|
|
|
- >设置红包金额</el-button>
|
|
|
|
|
|
|
+<!-- <el-button-->
|
|
|
|
|
+<!-- size="mini"-->
|
|
|
|
|
+<!-- type="text"-->
|
|
|
|
|
+<!-- v-hasPermi="['course:userCourseVideo:changeRewardConfig']"-->
|
|
|
|
|
+<!-- @click="updateAnswerReward(scope.row)"-->
|
|
|
|
|
+<!-- >设置答题奖励</el-button>-->
|
|
|
|
|
+
|
|
|
|
|
+ <el-button
|
|
|
|
|
+ size="mini"
|
|
|
|
|
+ type="text"
|
|
|
|
|
+ v-hasPermi="['course:userCourseVideo:edit']"
|
|
|
|
|
+ @click="updateMoney(scope.row)"
|
|
|
|
|
+ >设置红包金额</el-button>
|
|
|
|
|
+<!-- <el-button-->
|
|
|
|
|
+<!-- size="mini"-->
|
|
|
|
|
+<!-- type="text"-->
|
|
|
|
|
+<!-- v-hasPermi="['course:relation:edit']"-->
|
|
|
|
|
+<!-- @click="updateReward(scope.row)"-->
|
|
|
|
|
+<!-- >设置课程奖励</el-button>-->
|
|
|
|
|
|
|
|
<el-button size="mini"
|
|
<el-button size="mini"
|
|
|
type="text" @click="openTagDialog(scope.row)">
|
|
type="text" @click="openTagDialog(scope.row)">
|
|
@@ -121,18 +134,376 @@
|
|
|
</el-dialog>
|
|
</el-dialog>
|
|
|
|
|
|
|
|
<AutoTagDialog
|
|
<AutoTagDialog
|
|
|
|
|
+ v-if="currentVideoId !== null"
|
|
|
:visible.sync="tagDialogVisible"
|
|
:visible.sync="tagDialogVisible"
|
|
|
:title="tagDialogTitle"
|
|
:title="tagDialogTitle"
|
|
|
:videoId="currentVideoId"
|
|
:videoId="currentVideoId"
|
|
|
append-to-body
|
|
append-to-body
|
|
|
/>
|
|
/>
|
|
|
|
|
|
|
|
|
|
+ <el-dialog
|
|
|
|
|
+ title="课程奖励选择"
|
|
|
|
|
+ :visible.sync="rewardOpen"
|
|
|
|
|
+ width="80%"
|
|
|
|
|
+ append-to-body
|
|
|
|
|
+ @close="handleRewardDialogClose"
|
|
|
|
|
+ >
|
|
|
|
|
+ <div class="reward-dialog">
|
|
|
|
|
+ <div class="selection-info" v-if="rewardType === 1">
|
|
|
|
|
+ <span>已选择 {{ selectedRewards.length }}/2 个奖励项目</span>
|
|
|
|
|
+ <el-button
|
|
|
|
|
+ type="text"
|
|
|
|
|
+ @click="clearSelection"
|
|
|
|
|
+ :disabled="selectedRewards.length === 0"
|
|
|
|
|
+ >
|
|
|
|
|
+ 清空选择
|
|
|
|
|
+ </el-button>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ <el-table
|
|
|
|
|
+ border
|
|
|
|
|
+ v-loading="rewardLoading"
|
|
|
|
|
+ :data="rewardList"
|
|
|
|
|
+ @selection-change="handleRewardSelectionChange"
|
|
|
|
|
+ ref="rewardTable"
|
|
|
|
|
+ >
|
|
|
|
|
+ <el-table-column
|
|
|
|
|
+ type="selection"
|
|
|
|
|
+ width="55"
|
|
|
|
|
+ align="center"
|
|
|
|
|
+ :selectable="checkSelectable"
|
|
|
|
|
+ />
|
|
|
|
|
+ <el-table-column label="主键ID" align="center" prop="id" />
|
|
|
|
|
+ <el-table-column label="奖励名称" align="center" prop="name" />
|
|
|
|
|
+ <el-table-column label="奖励描述" align="center" prop="description" />
|
|
|
|
|
+ <el-table-column label="奖励类型" align="center" prop="rewardType">
|
|
|
|
|
+ <template slot-scope="scope">
|
|
|
|
|
+ <dict-tag :options="rewardTypeOptions" :value="scope.row.rewardType"/>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </el-table-column>
|
|
|
|
|
+
|
|
|
|
|
+ <el-table-column label="期望值" align="center" prop="expectedValue" />
|
|
|
|
|
+ <el-table-column label="实际奖励内容" align="center" prop="actualRewards">
|
|
|
|
|
+ <template slot-scope="scope">
|
|
|
|
|
+ <el-button
|
|
|
|
|
+ size="mini"
|
|
|
|
|
+ type="text"
|
|
|
|
|
+ icon="el-icon-view"
|
|
|
|
|
+ @click="handleViewReward(scope.row)"
|
|
|
|
|
+ >查看详情</el-button>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </el-table-column>
|
|
|
|
|
+ <el-table-column label="创建时间" align="center" prop="createTime" />
|
|
|
|
|
+ </el-table>
|
|
|
|
|
+
|
|
|
|
|
+ <pagination
|
|
|
|
|
+ v-show="rewardTotal>0"
|
|
|
|
|
+ :total="rewardTotal"
|
|
|
|
|
+ :page.sync="rewardQueryParams.pageNum"
|
|
|
|
|
+ :limit.sync="rewardQueryParams.pageSize"
|
|
|
|
|
+ @pagination="getRewardList"
|
|
|
|
|
+ />
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ <div slot="footer" class="dialog-footer">
|
|
|
|
|
+ <el-button @click="rewardOpen = false">取 消</el-button>
|
|
|
|
|
+ <el-button
|
|
|
|
|
+ type="primary"
|
|
|
|
|
+ @click="submitRewardSelection"
|
|
|
|
|
+ :disabled="selectedRewards.length === 0 || (rewardType !== 1 && selectedRewards.length > 1)"
|
|
|
|
|
+ >
|
|
|
|
|
+ 确 定
|
|
|
|
|
+ </el-button>
|
|
|
|
|
+ <el-dialog
|
|
|
|
|
+ :title="`奖励详情 - ${currentReward.name || '未知奖励'}`"
|
|
|
|
|
+ :visible.sync="detailVisible"
|
|
|
|
|
+ width="700px"
|
|
|
|
|
+ append-to-body
|
|
|
|
|
+ >
|
|
|
|
|
+ <div class="reward-detail-container">
|
|
|
|
|
+ <!-- 基础信息 -->
|
|
|
|
|
+ <el-descriptions :column="2" border class="base-info">
|
|
|
|
|
+ <el-descriptions-item label="奖励名称">{{ currentReward.name || '-' }}</el-descriptions-item>
|
|
|
|
|
+ <el-descriptions-item label="奖励类型">
|
|
|
|
|
+ <dict-tag :options="rewardTypeOptions" :value="currentReward.rewardType"/>
|
|
|
|
|
+ </el-descriptions-item>
|
|
|
|
|
+ <el-descriptions-item label="状态">
|
|
|
|
|
+ <dict-tag :options="statusOptions" :value="currentReward.status"/>
|
|
|
|
|
+ </el-descriptions-item>
|
|
|
|
|
+ <el-descriptions-item label="期望值">{{ currentReward.expectedValue || 0 }}</el-descriptions-item>
|
|
|
|
|
+ <el-descriptions-item label="描述" :span="2">{{ currentReward.description || '-' }}</el-descriptions-item>
|
|
|
|
|
+ </el-descriptions>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 奖励内容详情 -->
|
|
|
|
|
+ <div class="reward-content">
|
|
|
|
|
+ <h4>奖励内容详情</h4>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 宝箱类型奖励 -->
|
|
|
|
|
+ <div v-if="currentReward.rewardType === 1" class="chest-reward">
|
|
|
|
|
+ <el-table :data="parsedRewardItems" size="small" border stripe>
|
|
|
|
|
+ <el-table-column label="数量" prop="amount" align="center">
|
|
|
|
|
+ <template slot-scope="{row}">
|
|
|
|
|
+ {{ row.amount || 1 }}
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </el-table-column>
|
|
|
|
|
+ <el-table-column label="概率" prop="probability"align="center">
|
|
|
|
|
+ <template slot-scope="{row}">
|
|
|
|
|
+ <el-tag v-if="row.probability" size="small">{{ row.probability }}</el-tag>
|
|
|
|
|
+ <span v-else>-</span>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </el-table-column>
|
|
|
|
|
+ </el-table>
|
|
|
|
|
+ <div v-if="!parsedRewardItems || parsedRewardItems.length === 0" class="empty-tip">
|
|
|
|
|
+ 暂无奖励配置
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 红包类型奖励 -->
|
|
|
|
|
+ <div v-else-if="currentReward.rewardType === 2" class="redpacket-reward">
|
|
|
|
|
+ <div class="reward-amount">
|
|
|
|
|
+ <i class="el-icon-money" style="color: #e6a23c; font-size: 24px;"></i>
|
|
|
|
|
+ <span class="amount-text">{{ rewardAmount }} 元</span>
|
|
|
|
|
+ <el-tag type="warning" size="small">红包奖励</el-tag>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 芳华币类型奖励 -->
|
|
|
|
|
+ <div v-else-if="currentReward.rewardType === 3" class="points-reward">
|
|
|
|
|
+ <div class="reward-amount">
|
|
|
|
|
+ <i class="el-icon-coin" style="color: #67c23a; font-size: 24px;"></i>
|
|
|
|
|
+ <span class="amount-text">{{ rewardAmount }} 芳华币</span>
|
|
|
|
|
+ <el-tag type="success" size="small">芳华币奖励</el-tag>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 转盘类型奖励 -->
|
|
|
|
|
+ <div v-else-if="currentReward.rewardType === 4" class="chest-reward">
|
|
|
|
|
+ <el-table :data="parsedRewardItems" size="small" border stripe>
|
|
|
|
|
+ <el-table-column label="图标" prop="iconUrl" align="center" width="80">
|
|
|
|
|
+ <template slot-scope="{row}">
|
|
|
|
|
+ <el-image
|
|
|
|
|
+ v-if="row.iconUrl"
|
|
|
|
|
+ :src="row.iconUrl"
|
|
|
|
|
+ :preview-src-list="[row.iconUrl]"
|
|
|
|
|
+ fit="cover"
|
|
|
|
|
+ style="width:32px;height:32px;border:1px solid #ebeef5;border-radius:4px;"
|
|
|
|
|
+ />
|
|
|
|
|
+ <span v-else>-</span>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </el-table-column>
|
|
|
|
|
+ <el-table-column label="奖品名称" prop="name" align="center" />
|
|
|
|
|
+ <el-table-column label="奖品类型" prop="type" align="center">
|
|
|
|
|
+ <template slot-scope="{row}">
|
|
|
|
|
+ <el-tag v-if="row.type" size="small">
|
|
|
|
|
+ {{ getSpinItemTypeLabel(row.type) }}
|
|
|
|
|
+ </el-tag>
|
|
|
|
|
+ <span v-else>-</span>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </el-table-column>
|
|
|
|
|
+ <el-table-column label="数量" prop="amount" align="center">
|
|
|
|
|
+ <template slot-scope="{row}">
|
|
|
|
|
+ <span v-if="row.amount">
|
|
|
|
|
+ {{ row.amount }} {{ getSpinItemUnit(row.type) }}
|
|
|
|
|
+ </span>
|
|
|
|
|
+ <span v-else>-</span>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </el-table-column>
|
|
|
|
|
+ <el-table-column label="概率" prop="probability" align="center">
|
|
|
|
|
+ <template slot-scope="{row}">
|
|
|
|
|
+ <el-tag v-if="row.probability" size="small">{{ row.probability }}</el-tag>
|
|
|
|
|
+ <span v-else>-</span>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </el-table-column>
|
|
|
|
|
+ </el-table>
|
|
|
|
|
+ <div v-if="!parsedRewardItems || parsedRewardItems.length === 0" class="empty-tip">
|
|
|
|
|
+ 暂无奖励配置
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 保底转盘类型奖励 -->
|
|
|
|
|
+ <div v-else-if="currentReward.rewardType === 5" class="chest-reward">
|
|
|
|
|
+ <el-table :data="parsedRewardItems" size="small" border stripe>
|
|
|
|
|
+ <el-table-column label="图标" prop="iconUrl" align="center" width="80">
|
|
|
|
|
+ <template slot-scope="{row}">
|
|
|
|
|
+ <el-image
|
|
|
|
|
+ v-if="row.iconUrl"
|
|
|
|
|
+ :src="row.iconUrl"
|
|
|
|
|
+ :preview-src-list="[row.iconUrl]"
|
|
|
|
|
+ fit="cover"
|
|
|
|
|
+ style="width:32px;height:32px;border:1px solid #ebeef5;border-radius:4px;"
|
|
|
|
|
+ />
|
|
|
|
|
+ <span v-else>-</span>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </el-table-column>
|
|
|
|
|
+ <el-table-column label="奖品名称" prop="name" align="center" />
|
|
|
|
|
+ <el-table-column label="奖品类型" prop="type" align="center">
|
|
|
|
|
+ <template slot-scope="{row}">
|
|
|
|
|
+ <el-tag v-if="row.type" size="small">
|
|
|
|
|
+ {{ getSpinItemTypeLabel(row.type) }}
|
|
|
|
|
+ </el-tag>
|
|
|
|
|
+ <span v-else>-</span>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </el-table-column>
|
|
|
|
|
+ <el-table-column label="数量" prop="amount" align="center">
|
|
|
|
|
+ <template slot-scope="{row}">
|
|
|
|
|
+ <span v-if="row.amount">
|
|
|
|
|
+ {{ row.amount }} {{ getSpinItemUnit(row.type) }}
|
|
|
|
|
+ </span>
|
|
|
|
|
+ <span v-else>-</span>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </el-table-column>
|
|
|
|
|
+ <el-table-column label="概率" prop="probability" align="center">
|
|
|
|
|
+ <template slot-scope="{row}">
|
|
|
|
|
+ <el-tag v-if="row.probability" size="small">{{ row.probability }}</el-tag>
|
|
|
|
|
+ <span v-else>-</span>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </el-table-column>
|
|
|
|
|
+ <el-table-column label="保底" prop="isGuarantee" align="center">
|
|
|
|
|
+ <template slot-scope="{row}">
|
|
|
|
|
+ <el-tag size="small" :type="row.isGuarantee ? 'success' : 'info'">{{ row.isGuarantee ? '是' : '否' }}</el-tag>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </el-table-column>
|
|
|
|
|
+ </el-table>
|
|
|
|
|
+ <div v-if="!parsedRewardItems || parsedRewardItems.length === 0" class="empty-tip">
|
|
|
|
|
+ 暂无奖励配置
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 未知类型 -->
|
|
|
|
|
+ <div v-else class="unknown-reward">
|
|
|
|
|
+ <el-alert type="info" title="未知奖励类型" :closable="false"></el-alert>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ <div slot="footer" class="dialog-footer">
|
|
|
|
|
+ <el-button @click="detailVisible = false">关 闭</el-button>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </el-dialog>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </el-dialog>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 答题奖励弹窗 -->
|
|
|
|
|
+ <el-dialog
|
|
|
|
|
+ :title="answerRewardDialog.title"
|
|
|
|
|
+ :visible.sync="answerRewardDialog.open"
|
|
|
|
|
+ width="700px"
|
|
|
|
|
+ append-to-body
|
|
|
|
|
+ >
|
|
|
|
|
+ <el-form :model="answerRewardDialog.answerRewardForm" v-loading="answerRewardDialog.loading" label-width="120px">
|
|
|
|
|
+ <div class="default-amounts">
|
|
|
|
|
+ <!-- <div class="amount-item">-->
|
|
|
|
|
+ <!-- <i class="el-icon-money amount-icon red"></i>-->
|
|
|
|
|
+ <!-- <span class="label">默认红包奖励</span>-->
|
|
|
|
|
+ <!-- <span class="value">{{answerRewardDialog.answerRewardForm.defaultRedPacketAmount || 0}} 元</span>-->
|
|
|
|
|
+ <!-- <el-tag :type="answerRewardDialog.answerRewardForm.redPacketRuleId ? 'info' : 'warning'" size="mini">{{ answerRewardDialog.answerRewardForm.redPacketRuleId ? '已选择配置' : '配置生效中' }}</el-tag>-->
|
|
|
|
|
+ <!-- </div>-->
|
|
|
|
|
+ <div class="amount-item">
|
|
|
|
|
+ <i class="el-icon-coin amount-icon green"></i>
|
|
|
|
|
+ <span class="label">默认小程序芳华币奖励</span>
|
|
|
|
|
+ <span class="value">{{answerRewardDialog.answerRewardForm.defaultPointNum || 0}} 芳华币</span>
|
|
|
|
|
+ <el-tag :type="'success'" size="mini">{{ '生效中' }}</el-tag>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="amount-item">
|
|
|
|
|
+ <i class="el-icon-coin amount-icon green"></i>
|
|
|
|
|
+ <span class="label">默认APP小程序芳华币奖励</span>
|
|
|
|
|
+ <span class="value">{{answerRewardDialog.answerRewardForm.defaultAppPointNum || 0}} 芳华币</span>
|
|
|
|
|
+ <el-tag :type="answerRewardDialog.answerRewardForm.pointRuleId ? 'info' : 'success'" size="mini">{{ answerRewardDialog.answerRewardForm.pointRuleId ? '已选择配置' : '生效中' }}</el-tag>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="amount-item">
|
|
|
|
|
+ <i class="el-icon-money amount-icon red"></i>
|
|
|
|
|
+ <span class="label">默认转盘奖励</span>
|
|
|
|
|
+ <span class="value" v-if="shouldShowTurntableRule">{{getTurntableRuleName(answerRewardDialog.answerRewardForm.defaultTurntableRuleId)}}</span>
|
|
|
|
|
+ <span class="value" v-else>-</span>
|
|
|
|
|
+ <el-tag :type="answerRewardDialog.answerRewardForm.turntableRuleId ? 'info' : 'success'" size="mini">{{ answerRewardDialog.answerRewardForm.turntableRuleId ? '已选择配置' : '生效中' }}</el-tag>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <el-form-item label="红包配置">
|
|
|
|
|
+ <el-select
|
|
|
|
|
+ ref="customSelect2"
|
|
|
|
|
+ v-model="answerRewardDialog.answerRewardForm.redPacketRuleId"
|
|
|
|
|
+ placeholder="请选择红包"
|
|
|
|
|
+ @click.native.stop="openRuleDialog(answerRewardDialog.answerRewardForm.redPacketRuleId, 2)"
|
|
|
|
|
+ clearable
|
|
|
|
|
+ style="width: 100%;">
|
|
|
|
|
+ <el-option
|
|
|
|
|
+ v-for="item in ruleList"
|
|
|
|
|
+ :key="item.id"
|
|
|
|
|
+ :label="item.name"
|
|
|
|
|
+ :value="item.id">
|
|
|
|
|
+ </el-option>
|
|
|
|
|
+ </el-select>
|
|
|
|
|
+ </el-form-item>
|
|
|
|
|
+ <el-form-item label="芳华币配置">
|
|
|
|
|
+ <el-select
|
|
|
|
|
+ ref="customSelect3"
|
|
|
|
|
+ v-model="answerRewardDialog.answerRewardForm.pointRuleId"
|
|
|
|
|
+ placeholder="请选择芳华币"
|
|
|
|
|
+ @click.native.stop="openRuleDialog(answerRewardDialog.answerRewardForm.pointRuleId, 3)"
|
|
|
|
|
+ clearable
|
|
|
|
|
+ style="width: 100%;">
|
|
|
|
|
+ <el-option
|
|
|
|
|
+ v-for="item in ruleList"
|
|
|
|
|
+ :key="item.id"
|
|
|
|
|
+ :label="item.name"
|
|
|
|
|
+ :value="item.id">
|
|
|
|
|
+ </el-option>
|
|
|
|
|
+ </el-select>
|
|
|
|
|
+ </el-form-item>
|
|
|
|
|
+ <el-form-item label="随机转盘配置">
|
|
|
|
|
+ <el-select
|
|
|
|
|
+ ref="customSelect4"
|
|
|
|
|
+ v-model="answerRewardDialog.answerRewardForm.turntableRuleId"
|
|
|
|
|
+ placeholder="请选择转盘"
|
|
|
|
|
+ @click.native.stop="openRuleDialog(answerRewardDialog.answerRewardForm.turntableRuleId, 4)"
|
|
|
|
|
+ clearable
|
|
|
|
|
+ style="width: 100%;">
|
|
|
|
|
+ <el-option
|
|
|
|
|
+ v-for="item in ruleList"
|
|
|
|
|
+ :key="item.id"
|
|
|
|
|
+ :label="item.name"
|
|
|
|
|
+ :value="item.id">
|
|
|
|
|
+ </el-option>
|
|
|
|
|
+ </el-select>
|
|
|
|
|
+ </el-form-item>
|
|
|
|
|
+ <el-form-item label="保底转盘配置">
|
|
|
|
|
+ <el-select
|
|
|
|
|
+ ref="customSelect5"
|
|
|
|
|
+ v-model="answerRewardDialog.answerRewardForm.turntableGuaranteeRuleId"
|
|
|
|
|
+ placeholder="请选择保底转盘"
|
|
|
|
|
+ @click.native.stop="openRuleDialog(answerRewardDialog.answerRewardForm.turntableGuaranteeRuleId, 5)"
|
|
|
|
|
+ clearable
|
|
|
|
|
+ style="width: 100%;">
|
|
|
|
|
+ <el-option
|
|
|
|
|
+ v-for="item in ruleList"
|
|
|
|
|
+ :key="item.id"
|
|
|
|
|
+ :label="item.name"
|
|
|
|
|
+ :value="item.id">
|
|
|
|
|
+ </el-option>
|
|
|
|
|
+ </el-select>
|
|
|
|
|
+ </el-form-item>
|
|
|
|
|
+ </el-form>
|
|
|
|
|
+
|
|
|
|
|
+ <div slot="footer" class="dialog-footer">
|
|
|
|
|
+ <el-button @click="answerRewardDialog.open=false">取 消</el-button>
|
|
|
|
|
+ <el-button type="primary" :loading="saving" :disabled="saving" @click="submitAnswerReward">确 定</el-button>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </el-dialog>
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
</div>
|
|
</div>
|
|
|
</template>
|
|
</template>
|
|
|
|
|
|
|
|
<script>
|
|
<script>
|
|
|
-import {getVideoListByCourseId, updatePacketMoney, updateUserCourseVideoUpdate} from "@/api/course/userCourseVideo";
|
|
|
|
|
|
|
+import {
|
|
|
|
|
+ updatePacketMoney,
|
|
|
|
|
+ getVideoListByCourseId,
|
|
|
|
|
+ getAnswerRewardConfig,
|
|
|
|
|
+ changeAnswerRewardConfig,
|
|
|
|
|
+} from "@/api/course/userCourseVideo";
|
|
|
import userCourseVideoDetails from '../../components/course/userCourseVideoDetails.vue';
|
|
import userCourseVideoDetails from '../../components/course/userCourseVideoDetails.vue';
|
|
|
|
|
+import {listReward, getReward, listByIds} from "@/api/course/reward";
|
|
|
|
|
+import { listRelation, updateRelation, } from "@/api/course/relation";
|
|
|
import {createLinkUrl, createRoomLinkUrl, queryQwIds} from "@/api/course/sopCourseLink";
|
|
import {createLinkUrl, createRoomLinkUrl, queryQwIds} from "@/api/course/sopCourseLink";
|
|
|
import AutoTagDialog from "@/views/components/tag/AutoTagDialog.vue";
|
|
import AutoTagDialog from "@/views/components/tag/AutoTagDialog.vue";
|
|
|
import {addTag, updateTag} from "@/api/tag/api";
|
|
import {addTag, updateTag} from "@/api/tag/api";
|
|
@@ -143,14 +514,52 @@ export default {
|
|
|
userCourseVideoDetails,
|
|
userCourseVideoDetails,
|
|
|
AutoTagDialog
|
|
AutoTagDialog
|
|
|
},
|
|
},
|
|
|
- props: {
|
|
|
|
|
- video: {
|
|
|
|
|
- type: Object,
|
|
|
|
|
- required: true,
|
|
|
|
|
- },
|
|
|
|
|
|
|
+ props: {
|
|
|
|
|
+ video: {
|
|
|
|
|
+ type: Object,
|
|
|
|
|
+ required: false, // 改为非必需
|
|
|
|
|
+ default: () => ({}) // 提供默认值
|
|
|
},
|
|
},
|
|
|
|
|
+ },
|
|
|
data() {
|
|
data() {
|
|
|
return {
|
|
return {
|
|
|
|
|
+ answerRewardDialog: {
|
|
|
|
|
+ open: false,
|
|
|
|
|
+ title: '设置答题奖励',
|
|
|
|
|
+ loading: false,
|
|
|
|
|
+ answerRewardForm: {
|
|
|
|
|
+ videoId: null,
|
|
|
|
|
+ redPacketRuleId: null,
|
|
|
|
|
+ pointRuleId: null,
|
|
|
|
|
+ turntableRuleId: null,
|
|
|
|
|
+ turntableGuaranteeRuleId: null,
|
|
|
|
|
+ defaultRedPacketAmount: null,
|
|
|
|
|
+ defaultPointNum: null,
|
|
|
|
|
+ defaultAppPointNum: null,
|
|
|
|
|
+ defaultTurntableRuleId: null
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ ruleList: [],
|
|
|
|
|
+ // 转盘奖励-奖励类型选项
|
|
|
|
|
+ spinItemTypeOptions: [],
|
|
|
|
|
+ saving: false,
|
|
|
|
|
+ currentReward: {},
|
|
|
|
|
+ rewardOpen: false,
|
|
|
|
|
+ rewardType: null,
|
|
|
|
|
+ rewardLoading: false,
|
|
|
|
|
+ rewardList: [],
|
|
|
|
|
+ selectedRewards: [], // 选中的奖励项
|
|
|
|
|
+ rewardsRelation: [], // 选中的奖励项
|
|
|
|
|
+ rewardTotal: 0,
|
|
|
|
|
+ rewardQueryParams: {
|
|
|
|
|
+ pageNum: 1,
|
|
|
|
|
+ pageSize: 10,
|
|
|
|
|
+ videoId: null,
|
|
|
|
|
+ rewardType:1
|
|
|
|
|
+ },
|
|
|
|
|
+ statusOptions:[],
|
|
|
|
|
+ rewardTypeOptions:[],
|
|
|
|
|
+ detailVisible: false,
|
|
|
currentRow: null,
|
|
currentRow: null,
|
|
|
// 假设这里有当前课程小节的数据传入,里面含id等
|
|
// 假设这里有当前课程小节的数据传入,里面含id等
|
|
|
tagGroups: [],
|
|
tagGroups: [],
|
|
@@ -256,12 +665,298 @@ export default {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
},
|
|
},
|
|
|
|
|
+ computed: {
|
|
|
|
|
+ // 解析奖励项数据
|
|
|
|
|
+ parsedRewardItems() {
|
|
|
|
|
+ if (!this.currentReward.actualRewards) return null;
|
|
|
|
|
+ try {
|
|
|
|
|
+ const parsed = JSON.parse(this.currentReward.actualRewards);
|
|
|
|
|
+ return Array.isArray(parsed) ? parsed : null;
|
|
|
|
|
+ } catch (e) {
|
|
|
|
|
+ console.error("解析奖励内容失败", e);
|
|
|
|
|
+ return null;
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+
|
|
|
|
|
+ // 获取红包或芳华币金额
|
|
|
|
|
+ rewardAmount() {
|
|
|
|
|
+ if (!this.currentReward.actualRewards) return 0;
|
|
|
|
|
+
|
|
|
|
|
+ try {
|
|
|
|
|
+ const parsed = JSON.parse(this.currentReward.actualRewards);
|
|
|
|
|
+ if (this.currentReward.rewardType === 2) {
|
|
|
|
|
+ return parsed.amount || parsed.money || 0;
|
|
|
|
|
+ } else if (this.currentReward.rewardType === 3) {
|
|
|
|
|
+ return parsed.points || parsed.score || 0;
|
|
|
|
|
+ }
|
|
|
|
|
+ return 0;
|
|
|
|
|
+ } catch (e) {
|
|
|
|
|
+ return 0;
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+
|
|
|
|
|
+ // 只有在dialog打开时才显示转盘规则名称
|
|
|
|
|
+ shouldShowTurntableRule() {
|
|
|
|
|
+ return this.answerRewardDialog.open && this.answerRewardDialog.answerRewardForm.defaultTurntableRuleId
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
created() {
|
|
created() {
|
|
|
this.getDicts("sys_course_temp_type").then(response => {
|
|
this.getDicts("sys_course_temp_type").then(response => {
|
|
|
this.typeOptions = response.data;
|
|
this.typeOptions = response.data;
|
|
|
});
|
|
});
|
|
|
|
|
+ this.getDicts("sys_reward_type").then((response) => {
|
|
|
|
|
+ this.rewardTypeOptions = response.data;
|
|
|
|
|
+ });
|
|
|
|
|
+ this.getDicts("sys_user_status").then((response) => {
|
|
|
|
|
+ this.statusOptions = response.data;
|
|
|
|
|
+ });
|
|
|
|
|
+ this.getDicts("spin_reward_type").then((response) => {
|
|
|
|
|
+ this.spinItemTypeOptions = response.data;
|
|
|
|
|
+ });
|
|
|
},
|
|
},
|
|
|
methods: {
|
|
methods: {
|
|
|
|
|
+ getTurntableRuleName(ruleId) {
|
|
|
|
|
+ if (!ruleId) return '-'
|
|
|
|
|
+
|
|
|
|
|
+ // 从ruleList中查找对应的规则名称
|
|
|
|
|
+ const rule = this.ruleList.find(item => item.id === ruleId)
|
|
|
|
|
+ if (rule) {
|
|
|
|
|
+ return rule.name
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 如果ruleList中没有,则异步获取
|
|
|
|
|
+ getReward(ruleId).then(response => {
|
|
|
|
|
+ const {code,data} = response
|
|
|
|
|
+ if (code === 200 && data) {
|
|
|
|
|
+ if (!this.ruleList.find(item => item.id === ruleId)) {
|
|
|
|
|
+ this.ruleList.push(data)
|
|
|
|
|
+ }
|
|
|
|
|
+ return data.name
|
|
|
|
|
+ }
|
|
|
|
|
+ }).catch(() => {
|
|
|
|
|
+ console.error('获取转盘规则失败:', ruleId)
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ return '加载中...'
|
|
|
|
|
+ },
|
|
|
|
|
+ // 查看奖励详情
|
|
|
|
|
+ handleViewReward(row) {
|
|
|
|
|
+ this.currentReward = { ...row };
|
|
|
|
|
+ this.detailVisible = true;
|
|
|
|
|
+ },
|
|
|
|
|
+ updateReward(row) {
|
|
|
|
|
+ this.currentVideoId = row.videoId;
|
|
|
|
|
+ this.rewardQueryParams.videoId = row.videoId;
|
|
|
|
|
+ this.rewardOpen = true;
|
|
|
|
|
+ this.rewardType = 1
|
|
|
|
|
+ this.getRewardList();
|
|
|
|
|
+
|
|
|
|
|
+ // 获取已设置的奖励(如果有)
|
|
|
|
|
+ this.getCurrentRewards(row.videoId);
|
|
|
|
|
+ },
|
|
|
|
|
+
|
|
|
|
|
+ // 获取奖励列表
|
|
|
|
|
+ getRewardList() {
|
|
|
|
|
+ this.rewardLoading = true;
|
|
|
|
|
+ listRelation({
|
|
|
|
|
+ videoSectionId: this.currentVideoId,
|
|
|
|
|
+ type: 1
|
|
|
|
|
+ }).then(response => {
|
|
|
|
|
+ this.rewardsRelation = response.rows;
|
|
|
|
|
+ }).catch(() => {
|
|
|
|
|
+ this.rewardLoading = false;
|
|
|
|
|
+ });
|
|
|
|
|
+ listReward(this.rewardQueryParams).then(response => {
|
|
|
|
|
+ this.rewardList = response.rows;
|
|
|
|
|
+ this.rewardTotal = response.total;
|
|
|
|
|
+ this.rewardLoading = false;
|
|
|
|
|
+ // 设置已选中的奖励
|
|
|
|
|
+ this.$nextTick(() => {
|
|
|
|
|
+ this.rewardList.forEach(row => {
|
|
|
|
|
+ if (this.rewardsRelation.some(item => item.rewardId === row.id)) {
|
|
|
|
|
+ this.$refs.rewardTable.toggleRowSelection(row, true);
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+ });
|
|
|
|
|
+ }).catch(() => {
|
|
|
|
|
+ this.rewardLoading = false;
|
|
|
|
|
+ });
|
|
|
|
|
+ },
|
|
|
|
|
+
|
|
|
|
|
+ // 获取当前视频已设置的奖励
|
|
|
|
|
+ getCurrentRewards(videoId) {
|
|
|
|
|
+ // 这里假设有一个API可以获取视频已设置的奖励
|
|
|
|
|
+ // 实际实现中需要根据后端API调整
|
|
|
|
|
+ this.selectedRewards = []; // 先清空
|
|
|
|
|
+ // 模拟数据,实际应从API获取
|
|
|
|
|
+ /*
|
|
|
|
|
+ getVideoRewards(videoId).then(response => {
|
|
|
|
|
+ this.selectedRewards = response.data || [];
|
|
|
|
|
+ });
|
|
|
|
|
+ */
|
|
|
|
|
+ },
|
|
|
|
|
+
|
|
|
|
|
+ // 处理奖励选择变化
|
|
|
|
|
+ handleRewardSelectionChange(selection) {
|
|
|
|
|
+ // 限制最多选择两项
|
|
|
|
|
+ if (selection.length > 2) {
|
|
|
|
|
+ this.$refs.rewardTable.clearSelection();
|
|
|
|
|
+ // 保留前两项
|
|
|
|
|
+ const limitedSelection = selection.slice(0, 2);
|
|
|
|
|
+ limitedSelection.forEach(item => {
|
|
|
|
|
+ this.$refs.rewardTable.toggleRowSelection(item, true);
|
|
|
|
|
+ });
|
|
|
|
|
+ this.selectedRewards = limitedSelection;
|
|
|
|
|
+ this.$message.warning('最多只能选择两个奖励项目');
|
|
|
|
|
+ } else {
|
|
|
|
|
+ this.selectedRewards = selection;
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ updateAnswerReward(row) {
|
|
|
|
|
+ this.answerRewardDialog.answerRewardForm = {}
|
|
|
|
|
+ this.answerRewardDialog.open = true
|
|
|
|
|
+ this.answerRewardDialog.loading = true
|
|
|
|
|
+ getAnswerRewardConfig(row.videoId).then(response => {
|
|
|
|
|
+ this.answerRewardDialog.answerRewardForm = response.data
|
|
|
|
|
+ this.answerRewardDialog.answerRewardForm.videoId = row.videoId
|
|
|
|
|
+ // 查询已配置列表
|
|
|
|
|
+ let ids = []
|
|
|
|
|
+ for (const [key, value] of Object.entries(response.data)) {
|
|
|
|
|
+ if (key === "redPacketRuleId" || key === "pointRuleId" ||
|
|
|
|
|
+ key === "turntableRuleId" || key === "turntableGuaranteeRuleId")
|
|
|
|
|
+ if (value) {
|
|
|
|
|
+ ids.push(value)
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ if (ids.length > 0) {
|
|
|
|
|
+ listByIds(ids).then(response => {
|
|
|
|
|
+ this.ruleList = response.data
|
|
|
|
|
+ this.answerRewardDialog.loading = false
|
|
|
|
|
+ })
|
|
|
|
|
+ } else {
|
|
|
|
|
+ this.answerRewardDialog.loading = false
|
|
|
|
|
+ }
|
|
|
|
|
+ })
|
|
|
|
|
+ },
|
|
|
|
|
+ submitAnswerReward(){
|
|
|
|
|
+ this.saving = true
|
|
|
|
|
+ changeAnswerRewardConfig(this.answerRewardDialog.answerRewardForm).then(response => {
|
|
|
|
|
+ const {code, msg} = response
|
|
|
|
|
+ if (code === 200){
|
|
|
|
|
+ this.msgSuccess("修改成功");
|
|
|
|
|
+ this.getList()
|
|
|
|
|
+ this.answerRewardDialog.open = false
|
|
|
|
|
+ } else {
|
|
|
|
|
+ this.msgError(msg);
|
|
|
|
|
+ }
|
|
|
|
|
+ this.saving = false
|
|
|
|
|
+ })
|
|
|
|
|
+ },
|
|
|
|
|
+ openRuleDialog(id, type) {
|
|
|
|
|
+ this.$nextTick(() => {
|
|
|
|
|
+ this.$refs['customSelect' + type]?.blur();
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ this.rewardList =[]
|
|
|
|
|
+ this.rewardOpen = true
|
|
|
|
|
+ this.rewardLoading = true
|
|
|
|
|
+ listReward({"rewardType": type, "status": 1}).then(response => {
|
|
|
|
|
+ const {rows, total} = response
|
|
|
|
|
+ this.rewardList = rows
|
|
|
|
|
+ this.rewardTotal = total
|
|
|
|
|
+ // 根据传入的规则ID,默认选中对应项
|
|
|
|
|
+ const preselected = this.rewardList.filter(item => item.id === id)
|
|
|
|
|
+ this.selectedRewards = preselected
|
|
|
|
|
+ this.$nextTick(() => {
|
|
|
|
|
+ if (this.$refs.rewardTable && preselected.length > 0) {
|
|
|
|
|
+ // 先清空再选中,避免残留状态
|
|
|
|
|
+ this.$refs.rewardTable.clearSelection()
|
|
|
|
|
+ preselected.forEach(row => this.$refs.rewardTable.toggleRowSelection(row, true))
|
|
|
|
|
+ }
|
|
|
|
|
+ })
|
|
|
|
|
+ this.rewardLoading = false
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ this.rewardType = type
|
|
|
|
|
+ },
|
|
|
|
|
+ // 获取转盘奖励类型标签
|
|
|
|
|
+ getSpinItemTypeLabel(type) {
|
|
|
|
|
+ const option = this.spinItemTypeOptions.find(item => item.dictValue === type.toString());
|
|
|
|
|
+ return option ? option.dictLabel : type;
|
|
|
|
|
+ },
|
|
|
|
|
+ // 获取转盘奖励类型单位
|
|
|
|
|
+ getSpinItemUnit(type) {
|
|
|
|
|
+ const option = this.spinItemTypeOptions.find(item => item.dictValue === type.toString());
|
|
|
|
|
+ const label = option ? option.dictLabel : '';
|
|
|
|
|
+ if (label.includes("红包")) {
|
|
|
|
|
+ return '元';
|
|
|
|
|
+ } else if (label.includes("芳华币")) {
|
|
|
|
|
+ return '芳华币';
|
|
|
|
|
+ } else {
|
|
|
|
|
+ return '';
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ // 检查是否可选
|
|
|
|
|
+ checkSelectable(row, index) {
|
|
|
|
|
+ // 如果已选择两项且当前行未被选中,则禁用选择
|
|
|
|
|
+ return this.selectedRewards.length < 2 ||
|
|
|
|
|
+ this.selectedRewards.some(item => item.rewardId === row.rewardId);
|
|
|
|
|
+ },
|
|
|
|
|
+
|
|
|
|
|
+ // 清空选择
|
|
|
|
|
+ clearSelection() {
|
|
|
|
|
+ this.$refs.rewardTable.clearSelection();
|
|
|
|
|
+ this.selectedRewards = [];
|
|
|
|
|
+ },
|
|
|
|
|
+
|
|
|
|
|
+ // 提交奖励选择
|
|
|
|
|
+ submitRewardSelection() {
|
|
|
|
|
+ if (this.selectedRewards.length === 0) {
|
|
|
|
|
+ this.$message.warning('请至少选择一个奖励项目');
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const rewardIds = this.selectedRewards.map(item => item.id);
|
|
|
|
|
+ const rewardIdList = this.rewardsRelation.map(item => item.rewardId);
|
|
|
|
|
+ if (this.rewardType === 1) {
|
|
|
|
|
+ updateRelation({
|
|
|
|
|
+ videoSectionId: this.currentVideoId,
|
|
|
|
|
+ rewardIds: rewardIds,
|
|
|
|
|
+ rewardIdList: rewardIdList
|
|
|
|
|
+ }).then(response => {
|
|
|
|
|
+ if (response.code === 200) {
|
|
|
|
|
+ this.$message.success('奖励设置成功');
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+ } else {
|
|
|
|
|
+ const ruleId = rewardIds[0]
|
|
|
|
|
+ if (this.rewardType === 2) {
|
|
|
|
|
+ this.answerRewardDialog.answerRewardForm.redPacketRuleId = ruleId
|
|
|
|
|
+ }
|
|
|
|
|
+ if (this.rewardType === 3) {
|
|
|
|
|
+ this.answerRewardDialog.answerRewardForm.pointRuleId = ruleId
|
|
|
|
|
+ }
|
|
|
|
|
+ if (this.rewardType === 4) {
|
|
|
|
|
+ this.answerRewardDialog.answerRewardForm.turntableRuleId = ruleId
|
|
|
|
|
+ }
|
|
|
|
|
+ if (this.rewardType === 5) {
|
|
|
|
|
+ this.answerRewardDialog.answerRewardForm.turntableGuaranteeRuleId = ruleId
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ let rule = this.rewardList.find(item => item.id === ruleId)
|
|
|
|
|
+ if (!this.ruleList.some(item => item.id === rule.id)) {
|
|
|
|
|
+ this.ruleList.push(rule)
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ this.rewardOpen = false
|
|
|
|
|
+ },
|
|
|
|
|
+
|
|
|
|
|
+ // 处理奖励弹窗关闭
|
|
|
|
|
+ handleRewardDialogClose() {
|
|
|
|
|
+ this.selectedRewards = [];
|
|
|
|
|
+ this.currentVideoId = null;
|
|
|
|
|
+ },
|
|
|
|
|
+
|
|
|
formatOptionLabel(item) {
|
|
formatOptionLabel(item) {
|
|
|
return item.corpName ? `${item.qwUserName} (${item.corpName})` : item.qwUserName;
|
|
return item.corpName ? `${item.qwUserName} (${item.corpName})` : item.qwUserName;
|
|
|
},
|
|
},
|
|
@@ -544,5 +1239,32 @@ export default {
|
|
|
line-height: 150px;
|
|
line-height: 150px;
|
|
|
text-align: center;
|
|
text-align: center;
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+ .default-amounts {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ flex-direction: column;
|
|
|
|
|
+ gap: 8px;
|
|
|
|
|
+ margin-bottom: 8px;
|
|
|
|
|
+ }
|
|
|
|
|
+ .amount-item {
|
|
|
|
|
+ display: inline-flex;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ gap: 8px;
|
|
|
|
|
+ padding: 8px 10px;
|
|
|
|
|
+ background: #fafafa;
|
|
|
|
|
+ border: 1px solid #ebeef5;
|
|
|
|
|
+ border-radius: 4px;
|
|
|
|
|
+ }
|
|
|
|
|
+ .amount-icon {
|
|
|
|
|
+ font-size: 18px;
|
|
|
|
|
+ }
|
|
|
|
|
+ .amount-icon.red { color: #e6a23c; }
|
|
|
|
|
+ .amount-icon.green { color: #67c23a; }
|
|
|
|
|
+ .amount-item .label {
|
|
|
|
|
+ color: #606266;
|
|
|
|
|
+ }
|
|
|
|
|
+ .amount-item .value {
|
|
|
|
|
+ font-weight: 600;
|
|
|
|
|
+ color: #303133;
|
|
|
|
|
+ margin-right: 6px;
|
|
|
|
|
+ }
|
|
|
</style>
|
|
</style>
|