watchReward.vue 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519
  1. <template >
  2. <div v-loading="loading">
  3. <!-- 提示信息 -->
  4. <div class="tip-message" >
  5. 设置观看奖励,用户达到直播观看时长后可领取奖励
  6. </div>
  7. <!-- 开启观看奖励开关 -->
  8. <div class="reward-switch">
  9. <span class="switch-label">开启观看奖励</span>
  10. <el-switch v-model="watchRewardForm.enabled"></el-switch>
  11. </div>
  12. <!-- 观看奖励设置 -->
  13. <div v-if="watchRewardForm.enabled" class="section-block">
  14. <div class="section-title">观看奖励设置</div>
  15. <!-- 表单内容 -->
  16. <el-form
  17. :model="watchRewardForm"
  18. :rules="rules"
  19. ref="watchRewardForm"
  20. label-width="130px"
  21. >
  22. <!-- 参与条件 -->
  23. <el-form-item label="参与条件" prop="participateCondition">
  24. <el-radio-group v-model="watchRewardForm.participateCondition">
  25. <el-radio label="1">达到指定观看时长</el-radio>
  26. <el-radio label="2">启用完课积分</el-radio>
  27. </el-radio-group>
  28. </el-form-item>
  29. <!-- 观看时长 -->
  30. <el-form-item label="观看时长" prop="watchDuration" v-if="watchRewardForm.participateCondition === '1'">
  31. <el-input v-model="watchRewardForm.watchDuration" placeholder="请输入观看时长" class="duration-input">
  32. <template #append>分钟</template>
  33. </el-input>
  34. </el-form-item>
  35. <!-- 完课率要求 -->
  36. <el-form-item label="完课率要求" prop="completionRate" v-if="watchRewardForm.participateCondition === '2'">
  37. <el-input-number
  38. v-model="watchRewardForm.completionRate"
  39. :min="1"
  40. :max="100"
  41. :precision="0"
  42. placeholder="请输入完课率"
  43. style="width: 200px;"
  44. ></el-input-number>
  45. <span style="margin-left: 10px; color: #909399;">%(观看时长占直播总时长的比例)</span>
  46. </el-form-item>
  47. <!-- 连续完课积分配置 -->
  48. <el-form-item label="连续完课积分" prop="pointsConfig" v-if="watchRewardForm.participateCondition === '2'">
  49. <div style="display: flex; flex-direction: column; gap: 10px;">
  50. <div v-for="(point, index) in watchRewardForm.pointsConfig" :key="index" style="display: flex; align-items: center;">
  51. <span style="width: 80px;">第{{ index + 1 }}天:</span>
  52. <el-input-number
  53. v-model="watchRewardForm.pointsConfig[index]"
  54. :min="0"
  55. :precision="0"
  56. placeholder="请输入积分值"
  57. style="width: 200px;"
  58. ></el-input-number>
  59. <span style="margin-left: 10px; color: #909399;">积分</span>
  60. </div>
  61. </div>
  62. </el-form-item>
  63. <!-- 实施动作(仅在达到指定观看时长时显示) -->
  64. <el-form-item label="实施动作" prop="action" v-if="watchRewardForm.participateCondition === '1'">
  65. <el-select v-model="watchRewardForm.action" placeholder="请选择实施动作" style="width: 300px;">
  66. <el-option
  67. v-for="item in actionOptions"
  68. :key="item.value"
  69. :label="item.label"
  70. :value="item.value"
  71. ></el-option>
  72. </el-select>
  73. </el-form-item>
  74. <!-- 领取提示语 -->
  75. <!-- <el-form-item label="领取提示语" prop="receivePrompt">-->
  76. <!-- <el-input v-model="watchRewardForm.receivePrompt" placeholder="请输入领取提示语"></el-input>-->
  77. <!-- </el-form-item>-->
  78. <!-- 红包设置(仅在达到指定观看时长时显示) -->
  79. <div v-if="watchRewardForm.participateCondition === '1'">
  80. <div class="section-title">红包设置</div>
  81. <!-- 根据实施动作类型显示不同的表单内容 -->
  82. <template v-if="watchRewardForm.action === '1'">
  83. <!-- 现金红包设置 -->
  84. <!-- 红包发放方式 1固定金额 2随机金额 -->
  85. <el-form-item label="红包发放方式" prop="redPacketType">
  86. <el-radio-group v-model="watchRewardForm.redPacketType">
  87. <el-radio label="1">固定金额</el-radio>
  88. <el-radio label="2">随机金额</el-radio>
  89. </el-radio-group>
  90. </el-form-item>
  91. <!-- 红包金额 -->
  92. <el-form-item label="红包金额" prop="redPacketAmount">
  93. <el-input v-model="watchRewardForm.redPacketAmount" placeholder="请输入红包金额"></el-input>
  94. </el-form-item>
  95. <!-- 红包发放数量 -->
  96. <el-form-item label="红包发放数量" prop="redPacketCount">
  97. <el-input v-model="watchRewardForm.redPacketCount" placeholder="红包数量+28888人数"></el-input>
  98. </el-form-item>
  99. <!-- 红包领取方式 1二维码核销 2微信提现 -->
  100. <el-form-item label="红包领取方式" prop="receiveMethod">
  101. <el-radio-group v-model="watchRewardForm.receiveMethod">
  102. <el-radio label="1">二维码领取</el-radio>
  103. <el-radio label="2">微信发放</el-radio>
  104. </el-radio-group>
  105. </el-form-item>
  106. </template>
  107. <template v-else>
  108. <!-- 积分红包设置 -->
  109. <!-- 积分值 -->
  110. <el-form-item label="积分值" prop="scoreAmount">
  111. <el-input
  112. v-model="watchRewardForm.scoreAmount"
  113. placeholder="请输入积分值" style="width: 300px;"
  114. ></el-input>
  115. </el-form-item>
  116. <!-- 最大领取人数 -->
  117. <!-- <el-form-item label="最大领取人数" prop="maxReceivers">-->
  118. <!-- <el-input-->
  119. <!-- v-model="watchRewardForm.maxReceivers"-->
  120. <!-- placeholder="请输入最大领取人数" style="width: 300px;"-->
  121. <!-- ></el-input>-->
  122. <!-- </el-form-item>-->
  123. </template>
  124. </div>
  125. <!-- 其他设置(仅在达到指定观看时长时显示) -->
  126. <div v-if="watchRewardForm.participateCondition === '1'">
  127. <div class="section-title">其他设置</div>
  128. <template v-if="watchRewardForm.action === '1'">
  129. <!-- 客服引导 1跟进企业微信 2不设置 -->
  130. <el-form-item label="客服引导" prop="showGuide">
  131. <el-radio-group v-model="watchRewardForm.showGuide">
  132. <el-radio label="1">跟进企业微信</el-radio>
  133. <el-radio label="2">不设置</el-radio>
  134. </el-radio-group>
  135. </el-form-item>
  136. <!-- 客服引导语 -->
  137. <el-form-item label="客服引导语" prop="guideText">
  138. <el-input
  139. v-model="watchRewardForm.guideText"
  140. placeholder="请输入客服引导语" style="width: 300px;"
  141. ></el-input>
  142. </el-form-item>
  143. </template>
  144. <template v-else>
  145. <!-- 积分使用引导语 -->
  146. <el-form-item label="积分使用引导语" prop="scoreGuideText">
  147. <el-input
  148. v-model="watchRewardForm.scoreGuideText"
  149. placeholder="请输入积分使用引导语" style="width: 300px;"
  150. ></el-input>
  151. </el-form-item>
  152. <!-- 积分使用引导链接 -->
  153. <el-form-item label="积分使用引导链接" prop="scoreGuideLink">
  154. <el-input
  155. v-model="watchRewardForm.scoreGuideLink"
  156. placeholder="请输入积分使用引导链接" style="width: 300px;"
  157. ></el-input>
  158. </el-form-item>
  159. <!-- 引导语 -->
  160. <!-- <el-form-item label="引导语" prop="guideText">-->
  161. <!-- <el-input-->
  162. <!-- v-model="watchRewardForm.guideText"-->
  163. <!-- placeholder="请输入引导语" style="width: 300px;"-->
  164. <!-- ></el-input>-->
  165. <!-- </el-form-item>-->
  166. </template>
  167. </div>
  168. <!-- 保存按钮 -->
  169. <div class="form-actions">
  170. <el-button type="primary" @click="saveWatchReward">保存</el-button>
  171. </div>
  172. </el-form>
  173. </div>
  174. </div>
  175. </template>
  176. <script>
  177. import {addConfig, getConfig, updateConfig} from "@/api/live/liveQuestionLive";
  178. export default {
  179. data() {
  180. return {
  181. loading: true,
  182. liveId: null,
  183. watchRewardForm: {
  184. id: null,
  185. liveId: null,
  186. // 是否启用观看奖励
  187. enabled: false,
  188. // 参与条件 1:达到指定观看时长 2:启用完课积分
  189. participateCondition: '1',
  190. // 观看时长
  191. watchDuration: '',
  192. // 实施动作
  193. action: '2',
  194. // 领取提示语
  195. receivePrompt: '',
  196. // 红包发放方式(固定金额/随机金额)
  197. redPacketType: '1',
  198. // 红包金额
  199. redPacketAmount: '',
  200. // 红包发放数量
  201. redPacketCount: '',
  202. // 红包领取方式
  203. receiveMethod: '1',
  204. // 是否显示客服引导
  205. showGuide: '1',
  206. // 客服引导语
  207. guideText: '',
  208. // 积分值
  209. scoreAmount: '',
  210. // // 最大领取人数
  211. // maxReceivers: '',
  212. // 积分使用引导语
  213. scoreGuideText: '',
  214. // 积分使用引导链接
  215. scoreGuideLink: '',
  216. // 完课积分相关配置(participateCondition为2时使用)
  217. // 完课率要求(1-100)
  218. completionRate: 90,
  219. // 连续完课积分配置(第1-10天)
  220. pointsConfig: [100, 110, 120, 130, 140, 150, 160, 170, 180, 200]
  221. },
  222. rules:{
  223. participateCondition:[
  224. { required: true, message: '请选择参与条件', trigger: 'change'}
  225. ],
  226. watchDuration:[
  227. {
  228. validator: (rule, value, callback) => {
  229. if (this.watchRewardForm.participateCondition === '1') {
  230. if (!value) {
  231. callback(new Error('请输入观看时长'));
  232. } else {
  233. callback();
  234. }
  235. } else {
  236. callback();
  237. }
  238. },
  239. trigger: 'blur'
  240. }
  241. ],
  242. completionRate:[
  243. {
  244. validator: (rule, value, callback) => {
  245. if (this.watchRewardForm.participateCondition === '2') {
  246. if (!value && value !== 0) {
  247. callback(new Error('请输入完课率要求'));
  248. } else if (value < 1 || value > 100) {
  249. callback(new Error('完课率要求范围为1-100'));
  250. } else {
  251. callback();
  252. }
  253. } else {
  254. callback();
  255. }
  256. },
  257. trigger: 'blur'
  258. }
  259. ],
  260. action:[
  261. {
  262. validator: (rule, value, callback) => {
  263. if (this.watchRewardForm.participateCondition === '1') {
  264. if (!value) {
  265. callback(new Error('请选择实施动作'));
  266. } else {
  267. callback();
  268. }
  269. } else {
  270. callback();
  271. }
  272. },
  273. trigger: 'change'
  274. }
  275. ],
  276. // receivePrompt:[
  277. // { required: true, message: '请输入领取提示语', trigger: 'blur'}
  278. // ],
  279. redPacketType:[
  280. { required: true, message: '请选择红包发放方式', trigger: 'blur'}
  281. ],
  282. redPacketAmount:[
  283. { required: true, message: '请输入红包金额', trigger: 'blur'}
  284. ],
  285. receiveMethod:[
  286. { required: true, message: '请选择红包领取方式', trigger: 'blur'}
  287. ],
  288. // guideText:[
  289. // { required: true, message: '请输入客服引导语', trigger: 'blur'}
  290. // ],
  291. showGuide:[
  292. { required: true, message: '请选择是否显示客服引导', trigger: 'blur'}
  293. ]
  294. },
  295. // 添加实施动作选项
  296. actionOptions: [
  297. // {
  298. // label: '现金红包',
  299. // value: '1'
  300. // },
  301. {
  302. label: '积分红包',
  303. value: '2'
  304. }
  305. ],
  306. };
  307. },
  308. watch: {
  309. // 监听路由的 query 参数变化
  310. '$route.query': {
  311. handler(newQuery) {
  312. this.liveId = this.$route.params.liveId
  313. this.watchRewardForm.liveId = this.liveId
  314. if(this.liveId == null) {
  315. return;
  316. }
  317. this.getLiveConfig();
  318. },
  319. // 初始化时立即执行一次
  320. immediate: true
  321. },
  322. // 监听开启观看奖励开关变化
  323. 'watchRewardForm.enabled': {
  324. handler(newValue, oldValue) {
  325. // 只有当关闭开关时才自动保存(从 true 变为 false)
  326. if (oldValue === true && newValue === false && this.liveId) {
  327. this.autoSaveEnabled();
  328. }
  329. }
  330. }
  331. },
  332. created() {
  333. },
  334. methods: {
  335. getLiveConfig(){
  336. getConfig(this.liveId).then(response => {
  337. if(response.code === 200 && response.data != null && response.data.length > 0){
  338. this.watchRewardForm = JSON.parse(response.data)
  339. }
  340. this.loading = false
  341. })
  342. },
  343. // 自动保存开关状态
  344. autoSaveEnabled() {
  345. if (this.watchRewardForm.id == null) {
  346. addConfig(this.watchRewardForm, this.liveId).then(res => {
  347. if (res.code == 200) {
  348. this.msgSuccess("已关闭观看奖励");
  349. // 更新 id,下次修改时使用 update
  350. if (res.data && res.data.id) {
  351. this.watchRewardForm.id = res.data.id;
  352. }
  353. }
  354. }).catch(() => {
  355. // 如果保存失败,恢复开关状态
  356. this.watchRewardForm.enabled = true;
  357. });
  358. } else {
  359. updateConfig(this.watchRewardForm, this.liveId).then(response => {
  360. if (response.code == 200) {
  361. this.msgSuccess("已关闭观看奖励");
  362. }
  363. }).catch(() => {
  364. // 如果保存失败,恢复开关状态
  365. this.watchRewardForm.enabled = true;
  366. });
  367. }
  368. },
  369. saveWatchReward() {
  370. this.$refs["watchRewardForm"].validate(valid => {
  371. console.log(valid)
  372. if (valid) {
  373. if (this.watchRewardForm.id == null) {
  374. // 调用保存观看奖励接口
  375. // 实现保存逻辑
  376. addConfig(this.watchRewardForm,this.liveId).then(res => {
  377. if (res.code == 200) {
  378. this.msgSuccess("修改成功");
  379. }
  380. })
  381. } else {
  382. updateConfig(this.watchRewardForm,this.liveId).then(response => {
  383. this.msgSuccess("修改成功");
  384. });
  385. }
  386. }
  387. })
  388. },
  389. }
  390. };
  391. </script>
  392. <style scoped>
  393. /* 提示信息样式 */
  394. .tip-message {
  395. padding: 12px 16px;
  396. background-color: #FFF6F2;
  397. border-radius: 4px;
  398. color: #666;
  399. font-size: 14px;
  400. margin-bottom: 20px;
  401. }
  402. /* 开关容器样式 */
  403. .reward-switch {
  404. margin-left: 200px;
  405. margin-bottom: 20px;
  406. padding: 20px;
  407. background-color: #fff;
  408. border-radius: 4px;
  409. display: flex;
  410. align-items: center;
  411. }
  412. /* 开关标签样式 */
  413. .reward-switch .switch-label {
  414. margin-right: 10px;
  415. font-size: 14px;
  416. color: #333;
  417. margin-left: 50px;
  418. }
  419. /* 表单区块样式 */
  420. .section-block {
  421. width: 50%;
  422. background-color: #fff;
  423. padding: 20px;
  424. border-radius: 4px;
  425. margin-left: 50px;
  426. margin-bottom: 20px;
  427. }
  428. /* 标题样式 */
  429. .section-block .section-title {
  430. font-size: 14px;
  431. color: #333;
  432. margin-bottom: 20px;
  433. border-left: 4px solid #409EFF;
  434. padding-left: 10px;
  435. line-height: 1;
  436. }
  437. /* 表单样式 */
  438. .reward-form {
  439. margin-top: 20px;
  440. }
  441. /* 表单项样式 */
  442. .reward-form .el-form-item {
  443. margin-bottom: 22px;
  444. padding-left: 50px;
  445. }
  446. .reward-form .el-form-item:last-child {
  447. margin-bottom: 0;
  448. }
  449. /* 表单标签样式 */
  450. .reward-form .el-form-item .el-form-item__label {
  451. color: #606266;
  452. }
  453. /* 输入框统一宽度 */
  454. .reward-form .el-form-item .el-input {
  455. width: 300px;
  456. }
  457. /* 必填项星号样式 */
  458. .reward-form .el-form-item.is-required .el-form-item__label:before {
  459. color: #F56C6C;
  460. }
  461. /* 观看时长输入框样式 */
  462. .reward-form .el-form-item .duration-input {
  463. width: 300px;
  464. }
  465. .reward-form .el-form-item .duration-input .el-input__inner {
  466. text-align: left;
  467. }
  468. /* 保存按钮样式 */
  469. .form-actions {
  470. width: 600px;
  471. text-align: center;
  472. margin-top: 30px;
  473. }
  474. .form-actions .el-button {
  475. padding: 8px 20px;
  476. font-size: 13px;
  477. }
  478. </style>