浏览代码

直播 奖励设置 回放时按照时间范围 设置奖励 新增 多选奖励/核销卷

三七 13 小时之前
父节点
当前提交
c49619d5e6

+ 53 - 0
src/api/live/liveGroupType.js

@@ -0,0 +1,53 @@
+import request from '@/utils/request'
+
+// 查询直播间分组分类列表
+export function listLiveGroupType(query) {
+  return request({
+    url: '/live/liveGroupType/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 查询直播间分组分类详细
+export function getLiveGroupType(id) {
+  return request({
+    url: '/live/liveGroupType/' + id,
+    method: 'get'
+  })
+}
+
+// 新增直播间分组分类
+export function addLiveGroupType(data) {
+  return request({
+    url: '/live/liveGroupType',
+    method: 'post',
+    data: data
+  })
+}
+
+// 修改直播间分组分类
+export function updateLiveGroupType(data) {
+  return request({
+    url: '/live/liveGroupType',
+    method: 'put',
+    data: data
+  })
+}
+
+// 删除直播间分组分类
+export function delLiveGroupType(id) {
+  return request({
+    url: '/live/liveGroupType/' + id,
+    method: 'delete'
+  })
+}
+
+// 导出直播间分组分类
+export function exportLiveGroupType(query) {
+  return request({
+    url: '/live/liveGroupType/export',
+    method: 'get',
+    params: query
+  })
+}

+ 53 - 0
src/api/live/liveRedPacketLog.js

@@ -0,0 +1,53 @@
+import request from '@/utils/request'
+
+// 查询直播红包 记录列表
+export function listLiveRedPacketLog(query) {
+  return request({
+    url: '/live/liveRedPacketLog/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 查询直播红包 记录详细
+export function getLiveRedPacketLog(logId) {
+  return request({
+    url: '/live/liveRedPacketLog/' + logId,
+    method: 'get'
+  })
+}
+
+// 新增直播红包 记录
+export function addLiveRedPacketLog(data) {
+  return request({
+    url: '/live/liveRedPacketLog',
+    method: 'post',
+    data: data
+  })
+}
+
+// 修改直播红包 记录
+export function updateLiveRedPacketLog(data) {
+  return request({
+    url: '/live/liveRedPacketLog',
+    method: 'put',
+    data: data
+  })
+}
+
+// 删除直播红包 记录
+export function delLiveRedPacketLog(logId) {
+  return request({
+    url: '/live/liveRedPacketLog/' + logId,
+    method: 'delete'
+  })
+}
+
+// 导出直播红包 记录
+export function exportLiveRedPacketLog(query) {
+  return request({
+    url: '/live/liveRedPacketLog/export',
+    method: 'get',
+    params: query
+  })
+}

+ 147 - 33
src/views/live/live/index.vue

@@ -1,5 +1,36 @@
 <template>
   <div class="app-container">
+    <div class="live-layout">
+      <!-- 左侧分组列表 -->
+      <div class="live-left-panel">
+        <div class="group-title">
+          <span>直播间分组</span>
+          <el-button
+            type="primary"
+            size="mini"
+            icon="el-icon-plus"
+            circle
+            @click="handleAddGroup"
+            v-hasPermi="['live:liveGroupType:add']"
+          ></el-button>
+        </div>
+        <div class="group-list">
+          <div
+            class="group-item"
+            :class="{ active: currentGroupId === null }"
+            @click="selectGroup(null)"
+          >全部</div>
+          <div
+            v-for="item in groupList"
+            :key="item.id"
+            class="group-item"
+            :class="{ active: currentGroupId === item.id }"
+            @click="selectGroup(item.id)"
+          >{{ item.liveGroupType }}</div>
+        </div>
+      </div>
+      <!-- 右侧内容区 -->
+      <div class="live-right-panel">
     <el-row :gutter="10" class="mb8">
       <el-col :span="1.5">
         <el-button
@@ -12,28 +43,6 @@
           >新增</el-button
         >
       </el-col>
-      <!--      <el-col :span="1.5">-->
-      <!--        <el-button-->
-      <!--          type="success"-->
-      <!--          plain-->
-      <!--          icon="el-icon-edit"-->
-      <!--          size="mini"-->
-      <!--          :disabled="single"-->
-      <!--          @click="handleUpdate"-->
-      <!--          v-hasPermi="['live:live:edit']"-->
-      <!--        >修改</el-button>-->
-      <!--      </el-col>-->
-      <!--      <el-col :span="1.5">-->
-      <!--        <el-button-->
-      <!--          type="warning"-->
-      <!--          plain-->
-      <!--          icon="el-icon-download"-->
-      <!--          size="mini"-->
-      <!--          :loading="exportLoading"-->
-      <!--          @click="handleExport"-->
-      <!--          v-hasPermi="['live:live:export']"-->
-      <!--        >导出</el-button>-->
-      <!--      </el-col>-->
       <right-toolbar
         :showSearch.sync="showSearch"
         @queryTable="getList"
@@ -182,15 +191,6 @@
         v-hasPermi="['live:live:operation']"
         >删除</el-button
       >
-      <!--      <el-dropdown>-->
-      <!--        <el-button plain size="mini">-->
-      <!--          更多操作<i class="el-icon-arrow-down el-icon&#45;&#45;right"></i>-->
-      <!--        </el-button>-->
-      <!--        <el-dropdown-menu slot="dropdown">-->
-      <!--          <el-dropdown-item>操作一</el-dropdown-item>-->
-      <!--          <el-dropdown-item>操作二</el-dropdown-item>-->
-      <!--        </el-dropdown-menu>-->
-      <!--      </el-dropdown>-->
     </div>
     <el-table
       ref="liveTable"
@@ -403,11 +403,27 @@
     />
 
     <!-- 添加或修改直播对话框 -->
-    <el-dialog :title="title" :visible.sync="open" width="900px" append-to-body>
-      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+    <el-dialog :title="title" :visible.sync="open" width="1000px" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="90px">
         <el-form-item label="直播名称" prop="liveName">
           <el-input v-model="form.liveName" placeholder="请输入直播名称" />
         </el-form-item>
+        <el-form-item label="直播间分组" prop="liveGroupType">
+          <el-select
+            v-model="form.liveGroupType"
+            placeholder="请选择直播间分组"
+            clearable
+            size="small"
+            style="width: 100%"
+          >
+            <el-option
+              v-for="item in groupList"
+              :key="item.id"
+              :label="item.liveGroupType"
+              :value="item.id"
+            />
+          </el-select>
+        </el-form-item>
         <el-form-item label="显示类型" prop="showType">
           <el-radio-group v-model="form.showType">
             <el-radio :label="1">横屏</el-radio>
@@ -741,6 +757,8 @@
         <el-button @click="addTagCancel">取 消</el-button>
       </div>
     </el-dialog>
+      </div>
+    </div>
   </div>
 </template>
 
@@ -765,6 +783,7 @@ import {
   clearLiveCache,
 } from "@/api/live/live";
 import { exportLiveMsgComments } from "@/api/live/liveMsg";
+import { listLiveGroupType, addLiveGroupType } from "@/api/live/liveGroupType";
 import Editor from "@/components/Editor/wang";
 import user from "@/store/modules/user";
 import VideoUpload from "@/components/LiveVideoUpload/single.vue";
@@ -775,6 +794,10 @@ export default {
   data() {
     return {
       liveTypeDictList: [],
+      // 直播间分组列表
+      groupList: [],
+      // 当前选中的分组ID,null表示全部
+      currentGroupId: null,
       currentCheck:null,
       currentCheckTagIndex:null,
       lastCheckTagRow:null,
@@ -831,6 +854,7 @@ export default {
         status: null,
         anchorId: null,
         liveType: null,
+        liveGroupType: null,
         startTime: null,
         startTimeS: null,
         endTimeE: null,
@@ -853,6 +877,7 @@ export default {
         fileSize: null,
         lineOne: null,
         liveTagList: [],
+        liveGroupType: null,
       },
       liveTagItemBase: {
         companyId: null,
@@ -898,6 +923,7 @@ export default {
   },
   created() {
     this.getList();
+    this.getGroupList();
     this.initCompanyDropList();
     this.getDicts("live_mark_type").then((response) => {
       this.markTypeDropList = response.data;
@@ -1118,6 +1144,33 @@ export default {
         this.loading = false;
       });
     },
+    /** 获取直播间分组列表 */
+    getGroupList() {
+      listLiveGroupType({ pageNum: 1, pageSize: 999 }).then((response) => {
+        this.groupList = response.rows;
+      });
+    },
+    /** 选择分组 */
+    selectGroup(groupId) {
+      this.currentGroupId = groupId;
+      this.queryParams.liveGroupType = groupId;
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 新增分组 */
+    handleAddGroup() {
+      this.$prompt('请输入直播间分组名称', '新增分组', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        inputPattern: /\S/,
+        inputErrorMessage: '分组名称不能为空'
+      }).then(({ value }) => {
+        addLiveGroupType({ liveGroupType: value }).then(() => {
+          this.msgSuccess('新增成功');
+          this.getGroupList();
+        });
+      }).catch(() => {});
+    },
     urlChange(url) {
       this.form.videoUrl = url;
       this.getVideoDuration();
@@ -1188,6 +1241,7 @@ export default {
         isTranscode: 0,
         transcodeFileKey: null,
         liveTagList: [],
+        liveGroupType: null,
       };
       this.videoUrl = "";
       this.resetForm("form");
@@ -1608,6 +1662,66 @@ export default {
 </script>
 
 <style scoped>
+.app-container {
+  position: relative;
+  height: calc(100vh - 150px);
+  overflow: hidden;
+  box-sizing: border-box;
+}
+.live-layout {
+  position: absolute;
+  top: 20px;
+  left: 20px;
+  right: 20px;
+  bottom: 20px;
+  display: flex;
+}
+.live-left-panel {
+  width: 200px;
+  min-width: 200px;
+  background: #fff;
+  border-right: 1px solid #e8e8e8;
+  display: flex;
+  flex-direction: column;
+}
+.group-title {
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  font-size: 16px;
+  font-weight: bold;
+  padding: 16px 16px 12px;
+  border-bottom: 1px solid #e8e8e8;
+  flex-shrink: 0;
+}
+.group-list {
+  padding: 8px 8px 0;
+  overflow-y: auto;
+  flex: 1;
+}
+.group-item {
+  padding: 10px 12px;
+  cursor: pointer;
+  border-radius: 4px;
+  font-size: 14px;
+  color: #333;
+  transition: all 0.2s;
+}
+.group-item:hover {
+  background: #f0f2f5;
+}
+.group-item.active {
+  background: #e6f7ff;
+  color: #1890ff;
+  font-weight: bold;
+}
+.live-right-panel {
+  flex: 1;
+  padding-left: 16px;
+  min-width: 0;
+  overflow-y: auto;
+  overflow-x: hidden;
+}
 .selection-toolbar {
   display: flex;
   align-items: center;

+ 9 - 4
src/views/live/liveConfig/barrage.vue

@@ -112,7 +112,7 @@
         <div class="el-upload__tip" style="color:red" slot="tip">提示:仅允许导入“xls”或“xlsx”格式文件!</div>
       </el-upload>
       <div slot="footer" class="dialog-footer">
-        <el-button type="primary" @click="submitFileForm">确 定</el-button>
+        <el-button type="primary" :loading="uploadLoading" @click="submitFileForm">确 定</el-button>
         <el-button @click="upload.open = false">取 消</el-button>
       </div>
     </el-dialog>
@@ -204,6 +204,7 @@ export default {
       socket: null,
       isLoading: false, // 是否正在加载
       hasMore: true, // 是否还有更多数据
+      uploadLoading: false, // 导入上传loading
     };
   },
   watch: {
@@ -275,9 +276,7 @@ export default {
       }
       this.loading = true;
       listTaskBarrage(this.queryParams).then(res => {
-        if(res.rows.length > 0) {
-          this.taskList = res.rows;
-        }
+        this.taskList = res.rows;
         this.total = res.total;
         this.loading = false;
       });
@@ -363,6 +362,7 @@ export default {
     },
     /** 删除按钮操作 */
     handleDelete(row) {
+      this.loading=true;
       const ids = row.id || this.ids;
       this.$confirm('是否确认删除直播间弹幕脚本配置编号为"' + ids + '"的数据项?', "警告", {
         confirmButtonText: "确定",
@@ -371,6 +371,7 @@ export default {
       }).then(function() {
         return delTask(ids);
       }).then(() => {
+        this.loading=false;
         this.getList();
         this.msgSuccess("删除成功");
         const msg={
@@ -403,10 +404,13 @@ export default {
     },
     // 文件上传中处理
     handleFileUploadProgress(event, file, fileList) {
+      this.loading=true;
       this.upload.isUploading = true;
     },
     // 文件上传成功处理
     handleFileSuccess(response, file, fileList) {
+      this.loading=false;
+      this.uploadLoading = false;
       this.upload.open = false;
       this.upload.isUploading = false;
       this.$refs.upload.clearFiles();
@@ -420,6 +424,7 @@ export default {
         this.$message.error("错误直播间,请联系管理员处理");
         return ;
       }
+      this.uploadLoading = true;
       this.$refs.upload.submit();
     },
     /** 下载模板操作 */

+ 59 - 13
src/views/live/liveConfig/watchReward.vue

@@ -123,12 +123,21 @@
                 style="width: 280px;"
                 @change="onTimeRangeChange(index)"
               ></el-time-picker>
-              <el-radio-group v-model="item.rewardType" style="margin-left: 15px;">
-                <el-radio label="1">红包</el-radio>
-                <el-radio label="2">积分</el-radio>
-              </el-radio-group>
-              <el-input-number v-if="item.rewardType === '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.rewardType === '2'" v-model="item.scoreAmount" placeholder="积分值" style="width: 140px; margin-left: 15px;"></el-input>
+              <el-checkbox-group v-model="item.rewardTypes" style="margin-left: 15px; flex-shrink: 0; width: 200px;">
+                <el-checkbox label="1">红包</el-checkbox>
+                <el-checkbox label="2">积分</el-checkbox>
+                <el-checkbox label="3">核销卷</el-checkbox>
+              </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-option
+                  v-for="c in couponList"
+                  :key="c.id"
+                  :label="c.couponName + ' (' + c.id + ')'"
+                  :value="c.id"
+                ></el-option>
+              </el-select>
               <el-button type="danger" icon="el-icon-delete" circle style="margin-left: 10px;" @click="removeRecordTimeRange(index)" v-if="watchRewardForm.recordTimeRanges.length > 1"></el-button>
             </div>
             <div v-if="timeRangeOverlap" style="color: #F56C6C; font-size: 12px; margin-top: -5px; margin-bottom: 10px;">时间段之间存在重叠,请重新选择</div>
@@ -251,6 +260,7 @@
 
 <script>
 import {addConfig, getConfig, updateConfig} from "@/api/live/liveQuestionLive";
+import { listStoreCouponIssue } from "@/api/live/liveCouponIssue";
 
 export default {
   data() {
@@ -290,7 +300,7 @@ export default {
         // 是否录播可领取奖励
         recordRedPacketEnabled: false,
         // 录播奖励配置列表(前端展示用)
-        recordTimeRanges: [{ range: null, rewardType: '1', redPacketAmount: '', scoreAmount: '' }],
+        recordTimeRanges: [{ range: null, rewardTypes: ['1'], redPacketAmount: '', scoreAmount: '', couponId: '' }],
         // 录播奖励配置字符串(提交后端用)
         recordTimeRangeStr: '',
         // // 最大领取人数
@@ -393,6 +403,8 @@ export default {
         }
       ],
       timeRangeOverlap: false,
+      // 核销卷列表(couponType=3)
+      couponList: [],
     };
   },
   watch: {
@@ -420,10 +432,17 @@ export default {
     }
   },
   created() {
+    this.getCouponList();
   },
   methods: {
+    // 获取核销卷列表(couponType=3)
+    getCouponList() {
+      listStoreCouponIssue({ pageNum: 1, pageSize: 999, couponType: '3' }).then(response => {
+        this.couponList = response.rows || [];
+      });
+    },
     addRecordTimeRange() {
-      this.watchRewardForm.recordTimeRanges.push({ range: null, rewardType: '1', redPacketAmount: '', scoreAmount: '' })
+      this.watchRewardForm.recordTimeRanges.push({ range: null, rewardTypes: ['1'], redPacketAmount: '', scoreAmount: '', couponId: '' })
     },
     removeRecordTimeRange(index) {
       this.watchRewardForm.recordTimeRanges.splice(index, 1)
@@ -495,10 +514,10 @@ 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]], rewardType: parts[2] || '1', redPacketAmount: parts[3] || '', scoreAmount: parts[4] || '' }
+              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]) : '' }
             })
           } else {
-            this.watchRewardForm.recordTimeRanges = [{ range: null, rewardType: '1', redPacketAmount: '', scoreAmount: '' }]
+            this.watchRewardForm.recordTimeRanges = [{ range: null, rewardTypes: ['1'], redPacketAmount: '', scoreAmount: '', couponId: '' }]
           }
           if(this.watchRewardForm.isRedPackageBalanceDeduction == null){
             this.watchRewardForm.isRedPackageBalanceDeduction = '1'
@@ -515,7 +534,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.rewardType + '-' + (item.rewardType === '1' ? item.redPacketAmount : '') + '-' + (item.rewardType === '2' ? item.scoreAmount : ''))
+          .map(item => item.range[0] + '-' + item.range[1] + '-' + (item.rewardTypes || []).join('|') + '-' + (item.redPacketAmount || '') + '-' + (item.scoreAmount || '') + '-' + (item.couponId || ''))
           .join(',')
       } else {
         submitData.recordTimeRangeStr = ''
@@ -553,11 +572,37 @@ export default {
             this.$message.error('时间段之间存在重叠,请重新选择')
             return
           }
+          // 录播奖励必填校验
+          if (this.watchRewardForm.recordRedPacketEnabled) {
+            for (let i = 0; i < this.watchRewardForm.recordTimeRanges.length; i++) {
+              const item = this.watchRewardForm.recordTimeRanges[i]
+              if (!item.range || item.range.length !== 2) {
+                this.$message.error('请选择第' + (i + 1) + '个时间段')
+                return
+              }
+              if (!item.rewardTypes || item.rewardTypes.length === 0) {
+                this.$message.error('第' + (i + 1) + '个时间段请至少选择一个奖励类型')
+                return
+              }
+              if (item.rewardTypes.includes('1') && !item.redPacketAmount) {
+                this.$message.error('第' + (i + 1) + '个时间段选择了红包,请填写红包金额')
+                return
+              }
+              if (item.rewardTypes.includes('2') && !item.scoreAmount) {
+                this.$message.error('第' + (i + 1) + '个时间段选择了积分,请填写积分值')
+                return
+              }
+              if (item.rewardTypes.includes('3') && !item.couponId) {
+                this.$message.error('第' + (i + 1) + '个时间段选择了核销卷,请选择核销卷')
+                return
+              }
+            }
+          }
           const submitData = Object.assign({}, this.watchRewardForm)
           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.rewardType + '-' + (item.rewardType === '1' ? item.redPacketAmount : '') + '-' + (item.rewardType === '2' ? item.scoreAmount : ''))
+              .map(item => item.range[0] + '-' + item.range[1] + '-' + (item.rewardTypes || []).join('|') + '-' + (item.redPacketAmount || '') + '-' + (item.scoreAmount || '') + '-' + (item.couponId || ''))
               .join(',')
           } else {
             submitData.recordTimeRangeStr = ''
@@ -586,6 +631,7 @@ export default {
 .record-reward-item {
   display: flex;
   align-items: center;
+  width: 100%;
   margin-bottom: 10px;
   padding: 10px 0;
   border-top: 1px dashed #dcdfe6;
@@ -627,7 +673,7 @@ export default {
 
 /* 表单区块样式 */
 .section-block {
-  width: 50%;
+  width: 100%;
   background-color: #fff;
   padding: 20px;
   border-radius: 4px;

+ 195 - 1
src/views/live/liveData/index.vue

@@ -190,6 +190,7 @@
     >
       <el-table-column type="selection" width="55"></el-table-column>
       <el-table-column type="index" label="序号" width="55" align="center"></el-table-column>
+      <el-table-column prop="liveId" label="直播间编码" width="90" ></el-table-column>
       <el-table-column prop="liveName" label="直播间名称" min-width="160" show-overflow-tooltip></el-table-column>
       <el-table-column prop="liveType" label="直播类型" width="100" align="center">
         <template slot-scope="scope">
@@ -315,7 +316,7 @@
       title="直播间详情"
       :visible.sync="detailDrawerVisible"
       direction="rtl"
-      size="60%"
+      size="80%"
       :before-close="closeDetailDrawer"
     >
       <div v-if="!showUserDetail" class="detail-content">
@@ -554,6 +555,31 @@
           </el-table-column>
           <el-table-column prop="companyName" label="分公司" min-width="150"></el-table-column>
           <el-table-column prop="salesName" label="销售" min-width="120"></el-table-column>
+          <el-table-column prop="isCompleted" label="是否完课" min-width="120">
+            <template slot-scope="scope">
+              <el-tag v-if="scope.row.isCompleted == 1" type="success">完课</el-tag>
+              <el-tag v-if="scope.row.isCompleted == 0" type="info">未完课</el-tag>
+            </template>
+          </el-table-column>
+          <el-table-column prop="rewardType" label="领取类型" min-width="160">
+            <template slot-scope="scope">
+              <dict-tag :options="liveRewardTypeList" :value="scope.row.rewardType"/>
+              <el-button
+                v-if="scope.row.rewardType != 4 && scope.row.rewardType != 99"
+                type="text"
+                size="small"
+                style="margin-left: 8px;"
+                @click="handleOpenRedPacketLog(scope.row)"
+              >红包/积分领取详细</el-button>
+              <el-button
+                v-if="scope.row.rewardType == 4 || scope.row.rewardType == 5 || scope.row.rewardType == 6 || scope.row.rewardType == 7"
+                type="text"
+                size="small"
+                style="margin-left: 8px;"
+                @click="handleOpenCouponLog(scope.row)"
+              >核销卷领取详情</el-button>
+            </template>
+          </el-table-column>
         </el-table>
         <!-- 用户详情分页组件 -->
         <pagination
@@ -567,6 +593,89 @@
         />
       </div>
     </el-drawer>
+
+    <!-- 红包领取详情侧边栏 -->
+    <el-drawer
+      title="红包领取详情"
+      :visible.sync="redPacketLogDrawerVisible"
+      direction="rtl"
+      size="60%"
+    >
+      <el-table
+        :data="redPacketLogList"
+        v-loading="redPacketLogLoading"
+        border
+        style="width: 100%"
+      >
+        <el-table-column type="index" label="序号" width="60" align="center"></el-table-column>
+        <el-table-column prop="liveId" label="直播间id" min-width="120"></el-table-column>
+        <el-table-column prop="userId" label="用户id" min-width="120"></el-table-column>
+        <el-table-column prop="amount" label="金额" min-width="120" align="center">
+          <template slot-scope="scope">
+            {{ scope.row.amount != null ? scope.row.amount : '-' }}
+          </template>
+        </el-table-column>
+        <el-table-column prop="status" label="状态" min-width="100" align="center">
+          <template slot-scope="scope">
+            <el-tag v-if="scope.row.status == 1" type="success">已领取</el-tag>
+            <el-tag v-else-if="scope.row.status == 0" type="info">未领取</el-tag>
+            <el-tag v-else type="info">{{ scope.row.status }}</el-tag>
+          </template>
+        </el-table-column>
+        <el-table-column prop="createTime" label="领取时间" min-width="160" align="center"></el-table-column>
+        <el-table-column prop="remark" label="备注" min-width="160" align="center"></el-table-column>
+      </el-table>
+      <pagination
+        v-show="redPacketLogTotal > 0"
+        :total="redPacketLogTotal"
+        :page.sync="redPacketLogQueryParams.pageNum"
+        :limit.sync="redPacketLogQueryParams.pageSize"
+        :page-sizes="[10, 20, 50]"
+        @pagination="loadRedPacketLogList"
+        style="margin-top: 20px;"
+      />
+    </el-drawer>
+
+    <!-- 核销卷领取详情侧边栏 -->
+    <el-drawer
+      title="核销卷领取详情"
+      :visible.sync="couponLogDrawerVisible"
+      direction="rtl"
+      size="60%"
+    >
+      <el-table
+        :data="couponLogList"
+        v-loading="couponLogLoading"
+        border
+        style="width: 100%"
+      >
+        <el-table-column type="index" label="序号" width="60" align="center"></el-table-column>
+        <el-table-column prop="nickname" label="会员昵称" min-width="120"></el-table-column>
+        <el-table-column prop="phone" label="会员手机号" min-width="120"></el-table-column>
+        <el-table-column prop="couponTitle" label="优惠券名称" min-width="120"></el-table-column>
+        <el-table-column prop="couponPrice" label="优惠券面值" min-width="100" align="center"></el-table-column>
+        <el-table-column prop="useMinPrice" label="最低消费" min-width="100" align="center"></el-table-column>
+        <el-table-column prop="limitTime" label="优惠券结束时间" min-width="160" align="center"></el-table-column>
+        <el-table-column prop="createTime" label="领取时间" min-width="160" align="center"></el-table-column>
+        <el-table-column prop="useTime" label="使用时间" min-width="160" align="center"></el-table-column>
+        <el-table-column prop="status" label="状态" min-width="100" align="center">
+          <template slot-scope="scope">
+            <el-tag v-if="scope.row.status == 1" type="success">已使用</el-tag>
+            <el-tag v-else-if="scope.row.status == 0" type="info">未使用</el-tag>
+            <el-tag v-else type="info">{{ scope.row.status }}</el-tag>
+          </template>
+        </el-table-column>
+      </el-table>
+      <pagination
+        v-show="couponLogTotal > 0"
+        :total="couponLogTotal"
+        :page.sync="couponLogQueryParams.pageNum"
+        :limit.sync="couponLogQueryParams.pageSize"
+        :page-sizes="[10, 20, 50]"
+        @pagination="loadCouponLogList"
+        style="margin-top: 20px;"
+      />
+    </el-drawer>
   </div>
 </template>
 
@@ -574,6 +683,9 @@
 import { listLiveData, exportLiveData, autoTagAndRemark, dashboardData, getLiveDataDetailBySql, getLiveUserDetailListBySql, exportLiveUserDetail } from "@/api/live/liveData";
 import { batchUpdateExternalContactNotes } from "@/api/qw/externalContact";
 import { addTag } from "@/api/qw/externalContact";
+import { listLiveRedPacketLog } from "@/api/live/liveRedPacketLog";
+import { listStoreCouponUser } from "@/api/live/liveCouponUser";
+import { selectDictLabel } from '@/utils/common'
 
 export default {
   name: "LiveData",
@@ -584,6 +696,7 @@ export default {
       exportLoading: false,
       showSearch: true,
       dataList: [],
+      liveRewardTypeList: [],
       total: 0,
       multipleSelection: [],
       allChecked: false,
@@ -648,6 +761,28 @@ export default {
       userDetailQueryParams: {
         pageNum: 1,
         pageSize: 10
+      },
+      // 红包领取详情
+      redPacketLogDrawerVisible: false,
+      redPacketLogList: [],
+      redPacketLogLoading: false,
+      redPacketLogTotal: 0,
+      redPacketLogQueryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        liveId: null,
+        userId: null
+      },
+      // 核销卷领取详情
+      couponLogDrawerVisible: false,
+      couponLogList: [],
+      couponLogLoading: false,
+      couponLogTotal: 0,
+      couponLogQueryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        userId: null,
+        type: null
       }
     };
   },
@@ -655,9 +790,14 @@ export default {
     this.liveId = this.$route.query.liveId;
     this.queryParams.liveId = this.liveId;
 
+    this.getDicts("sys_live_reward_type").then((response) => {
+      this.liveRewardTypeList = response.data;
+    });
+
     this.getList();
   },
   methods: {
+    selectDictLabel,
     /** 获取统计数据 */
     getStatistics() {
       if (!this.liveId) return;
@@ -956,6 +1096,60 @@ export default {
       }).catch(() => {
         this.userDetailExportLoading = false;
       });
+    },
+    /** 打开红包领取详情 */
+    handleOpenRedPacketLog(row) {
+      this.redPacketLogDrawerVisible = true;
+      this.redPacketLogQueryParams.liveId = this.currentLiveId;
+      this.redPacketLogQueryParams.userId = row.userId;
+      this.redPacketLogQueryParams.pageNum = 1;
+      this.loadRedPacketLogList();
+    },
+    /**
+    * 打开核销卷详情
+    */
+    handleOpenCouponLog(row){
+      this.couponLogDrawerVisible = true;
+      this.couponLogQueryParams.userId = row.userId;
+      this.couponLogQueryParams.type = '4-live-' + this.currentLiveId;
+      this.couponLogQueryParams.pageNum = 1;
+      this.loadCouponLogList();
+    },
+
+    /** 加载核销卷领取详情列表 */
+    loadCouponLogList() {
+      this.couponLogLoading = true;
+      listStoreCouponUser({
+        pageNum: this.couponLogQueryParams.pageNum,
+        pageSize: this.couponLogQueryParams.pageSize,
+        userId: this.couponLogQueryParams.userId,
+        type: this.couponLogQueryParams.type
+      }).then(response => {
+        this.couponLogList = response.rows || [];
+        this.couponLogTotal = response.total || 0;
+        this.couponLogLoading = false;
+      }).catch(() => {
+        this.couponLogLoading = false;
+      });
+    },
+
+    /** 加载红包领取详情列表 */
+    loadRedPacketLogList() {
+      this.redPacketLogLoading = true;
+      listLiveRedPacketLog({
+        pageNum: this.redPacketLogQueryParams.pageNum,
+        pageSize: this.redPacketLogQueryParams.pageSize,
+        liveId: this.redPacketLogQueryParams.liveId,
+        userId: this.redPacketLogQueryParams.userId
+      }).then(response => {
+        if (response.code === 200) {
+          this.redPacketLogList = response.rows || [];
+          this.redPacketLogTotal = response.total || 0;
+        }
+        this.redPacketLogLoading = false;
+      }).catch(() => {
+        this.redPacketLogLoading = false;
+      });
     }
   }
 };

+ 268 - 0
src/views/live/liveGroupType/index.vue

@@ -0,0 +1,268 @@
+<template>
+  <div class="app-container">
+    <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
+      <el-form-item label="直播间分组" prop="liveGroupType">
+        <el-input
+          v-model="queryParams.liveGroupType"
+          placeholder="请输入分组名称"
+          clearable
+          size="small"
+        />
+      </el-form-item>
+      <el-form-item>
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
+      </el-form-item>
+    </el-form>
+
+    <el-row :gutter="10" class="mb8">
+      <el-col :span="1.5">
+        <el-button
+          type="primary"
+          plain
+          icon="el-icon-plus"
+          size="mini"
+          @click="handleAdd"
+          v-hasPermi="['live:liveGroupType:add']"
+        >新增</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="success"
+          plain
+          icon="el-icon-edit"
+          size="mini"
+          :disabled="single"
+          @click="handleUpdate"
+          v-hasPermi="['live:liveGroupType:edit']"
+        >修改</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="danger"
+          plain
+          icon="el-icon-delete"
+          size="mini"
+          :disabled="multiple"
+          @click="handleDelete"
+          v-hasPermi="['live:liveGroupType:remove']"
+        >删除</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="warning"
+          plain
+          icon="el-icon-download"
+          size="mini"
+          :loading="exportLoading"
+          @click="handleExport"
+          v-hasPermi="['live:liveGroupType:export']"
+        >导出</el-button>
+      </el-col>
+      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+
+    <el-table border v-loading="loading" :data="liveGroupTypeList" @selection-change="handleSelectionChange">
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="分组id" align="center" prop="id" />
+      <el-table-column label="直播间分组" align="center" prop="liveGroupType" />
+      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+        <template slot-scope="scope">
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-edit"
+            @click="handleUpdate(scope.row)"
+            v-hasPermi="['live:liveGroupType:edit']"
+          >修改</el-button>
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-delete"
+            @click="handleDelete(scope.row)"
+            v-hasPermi="['live:liveGroupType:remove']"
+          >删除</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <pagination
+      v-show="total>0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    />
+
+    <!-- 添加或修改直播间分组分类对话框 -->
+    <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+        <el-form-item label="直播间分组" prop="liveGroupType">
+          <el-input
+            v-model="form.liveGroupType"
+            placeholder="请输入直播间分组"
+            clearable
+            size="small"
+          />
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">确 定</el-button>
+        <el-button @click="cancel">取 消</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { listLiveGroupType, getLiveGroupType, delLiveGroupType, addLiveGroupType, updateLiveGroupType, exportLiveGroupType } from "@/api/live/liveGroupType";
+
+export default {
+  name: "LiveGroupType",
+  data() {
+    return {
+      // 遮罩层
+      loading: true,
+      // 导出遮罩层
+      exportLoading: false,
+      // 选中数组
+      ids: [],
+      // 非单个禁用
+      single: true,
+      // 非多个禁用
+      multiple: true,
+      // 显示搜索条件
+      showSearch: true,
+      // 总条数
+      total: 0,
+      // 直播间分组分类表格数据
+      liveGroupTypeList: [],
+      // 弹出层标题
+      title: "",
+      // 是否显示弹出层
+      open: false,
+      // 查询参数
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        liveGroupType: null,
+      },
+      // 表单参数
+      form: {},
+      // 表单校验
+      rules: {
+      }
+    };
+  },
+  created() {
+    this.getList();
+  },
+  methods: {
+    /** 查询直播间分组分类列表 */
+    getList() {
+      this.loading = true;
+      listLiveGroupType(this.queryParams).then(response => {
+        this.liveGroupTypeList = response.rows;
+        this.total = response.total;
+        this.loading = false;
+      });
+    },
+    // 取消按钮
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 表单重置
+    reset() {
+      this.form = {
+        id: null,
+        liveGroupType: null,
+        createTime: null,
+        updateTime: null
+      };
+      this.resetForm("form");
+    },
+    /** 搜索按钮操作 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 重置按钮操作 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    // 多选框选中数据
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.id)
+      this.single = selection.length!==1
+      this.multiple = !selection.length
+    },
+    /** 新增按钮操作 */
+    handleAdd() {
+      this.reset();
+      this.open = true;
+      this.title = "添加直播间分组分类";
+    },
+    /** 修改按钮操作 */
+    handleUpdate(row) {
+      this.reset();
+      const id = row.id || this.ids
+      getLiveGroupType(id).then(response => {
+        this.form = response.data;
+        this.open = true;
+        this.title = "修改直播间分组分类";
+      });
+    },
+    /** 提交按钮 */
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          if (this.form.id != null) {
+            updateLiveGroupType(this.form).then(response => {
+              this.msgSuccess("修改成功");
+              this.open = false;
+              this.getList();
+            });
+          } else {
+            addLiveGroupType(this.form).then(response => {
+              this.msgSuccess("新增成功");
+              this.open = false;
+              this.getList();
+            });
+          }
+        }
+      });
+    },
+    /** 删除按钮操作 */
+    handleDelete(row) {
+      const ids = row.id || this.ids;
+      this.$confirm('是否确认删除直播间分组分类编号为"' + ids + '"的数据项?', "警告", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        }).then(function() {
+          return delLiveGroupType(ids);
+        }).then(() => {
+          this.getList();
+          this.msgSuccess("删除成功");
+        }).catch(() => {});
+    },
+    /** 导出按钮操作 */
+    handleExport() {
+      const queryParams = this.queryParams;
+      this.$confirm('是否确认导出所有直播间分组分类数据项?', "警告", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        }).then(() => {
+          this.exportLoading = true;
+          return exportLiveGroupType(queryParams);
+        }).then(response => {
+          this.download(response.msg);
+          this.exportLoading = false;
+        }).catch(() => {});
+    }
+  }
+};
+</script>

+ 384 - 0
src/views/live/liveRedPacketLog/index.vue

@@ -0,0 +1,384 @@
+<template>
+  <div class="app-container">
+    <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
+      <el-form-item label="直播间id" prop="liveId">
+        <el-input
+          v-model="queryParams.liveId"
+          placeholder="请输入直播间id"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="用户id" prop="userId">
+        <el-input
+          v-model="queryParams.userId"
+          placeholder="请输入用户id"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="公司员工id" prop="companyUserId">
+        <el-input
+          v-model="queryParams.companyUserId"
+          placeholder="请输入公司员工id"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="公司id" prop="companyId">
+        <el-input
+          v-model="queryParams.companyId"
+          placeholder="请输入公司id"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+
+      <el-form-item label="状态 0 发送中  1  已发送  2余额不足待发送" prop="status">
+        <el-select v-model="queryParams.status" placeholder="请选择状态 0 发送中  1  已发送  2余额不足待发送" clearable size="small">
+          <el-option label="请选择字典生成" value="" />
+        </el-select>
+      </el-form-item>
+
+      <el-form-item label="直播方式 1 app 2浏览器(可能有)" prop="wathcType">
+        <el-select v-model="queryParams.wathcType" placeholder="请选择直播方式 1 app 2浏览器(可能有)" clearable size="small">
+          <el-option label="请选择字典生成" value="" />
+        </el-select>
+      </el-form-item>
+      <el-form-item>
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
+      </el-form-item>
+    </el-form>
+
+    <el-row :gutter="10" class="mb8">
+      <el-col :span="1.5">
+        <el-button
+          type="primary"
+          plain
+          icon="el-icon-plus"
+          size="mini"
+          @click="handleAdd"
+          v-hasPermi="['liveRedPacketLog:liveRedPacketLog:add']"
+        >新增</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="success"
+          plain
+          icon="el-icon-edit"
+          size="mini"
+          :disabled="single"
+          @click="handleUpdate"
+          v-hasPermi="['liveRedPacketLog:liveRedPacketLog:edit']"
+        >修改</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="danger"
+          plain
+          icon="el-icon-delete"
+          size="mini"
+          :disabled="multiple"
+          @click="handleDelete"
+          v-hasPermi="['liveRedPacketLog:liveRedPacketLog:remove']"
+        >删除</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="warning"
+          plain
+          icon="el-icon-download"
+          size="mini"
+          :loading="exportLoading"
+          @click="handleExport"
+          v-hasPermi="['liveRedPacketLog:liveRedPacketLog:export']"
+        >导出</el-button>
+      </el-col>
+      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+
+    <el-table border v-loading="loading" :data="liveRedPacketLogList" @selection-change="handleSelectionChange">
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="日志id" align="center" prop="logId" />
+      <el-table-column label="批次单号" align="center" prop="outBatchNo" />
+      <el-table-column label="直播间id" align="center" prop="liveId" />
+      <el-table-column label="用户id" align="center" prop="userId" />
+      <el-table-column label="公司员工id" align="center" prop="companyUserId" />
+      <el-table-column label="公司id" align="center" prop="companyId" />
+      <el-table-column label="转载金额" align="center" prop="amount" />
+      <el-table-column label="状态 0 发送中  1  已发送  2余额不足待发送" align="center" prop="status" />
+      <el-table-column label="观看记录id live_watch_log" align="center" prop="watchLogId" />
+      <el-table-column label="备注" align="center" prop="remark" />
+      <el-table-column label="微信返回结果" align="center" prop="result" />
+      <el-table-column label="微信批次ID" align="center" prop="batchId" />
+      <el-table-column label="微信批次ID" align="center" prop="appId" />
+      <el-table-column label="商户ID" align="center" prop="mchId" />
+      <el-table-column label="直播方式 1 app 2浏览器(可能有)" align="center" prop="wathcType" />
+      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+        <template slot-scope="scope">
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-edit"
+            @click="handleUpdate(scope.row)"
+            v-hasPermi="['liveRedPacketLog:liveRedPacketLog:edit']"
+          >修改</el-button>
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-delete"
+            @click="handleDelete(scope.row)"
+            v-hasPermi="['liveRedPacketLog:liveRedPacketLog:remove']"
+          >删除</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <pagination
+      v-show="total>0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    />
+
+    <!-- 添加或修改直播红包 记录对话框 -->
+    <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+        <el-form-item label="批次单号" prop="outBatchNo">
+          <el-input v-model="form.outBatchNo" placeholder="请输入批次单号" />
+        </el-form-item>
+        <el-form-item label="直播间id" prop="liveId">
+          <el-input v-model="form.liveId" placeholder="请输入直播间id" />
+        </el-form-item>
+        <el-form-item label="用户id" prop="userId">
+          <el-input v-model="form.userId" placeholder="请输入用户id" />
+        </el-form-item>
+        <el-form-item label="公司员工id" prop="companyUserId">
+          <el-input v-model="form.companyUserId" placeholder="请输入公司员工id" />
+        </el-form-item>
+        <el-form-item label="公司id" prop="companyId">
+          <el-input v-model="form.companyId" placeholder="请输入公司id" />
+        </el-form-item>
+        <el-form-item label="转载金额" prop="amount">
+          <el-input v-model="form.amount" placeholder="请输入转载金额" />
+        </el-form-item>
+        <el-form-item label="状态 0 发送中  1  已发送  2余额不足待发送">
+          <el-radio-group v-model="form.status">
+            <el-radio label="1">请选择字典生成</el-radio>
+          </el-radio-group>
+        </el-form-item>
+        <el-form-item label="观看记录id live_watch_log" prop="watchLogId">
+          <el-input v-model="form.watchLogId" placeholder="请输入观看记录id live_watch_log" />
+        </el-form-item>
+        <el-form-item label="备注" prop="remark">
+          <el-input v-model="form.remark" placeholder="请输入备注" />
+        </el-form-item>
+        <el-form-item label="微信返回结果" prop="result">
+          <el-input v-model="form.result" type="textarea" placeholder="请输入内容" />
+        </el-form-item>
+        <el-form-item label="微信批次ID" prop="batchId">
+          <el-input v-model="form.batchId" placeholder="请输入微信批次ID" />
+        </el-form-item>
+        <el-form-item label="微信批次ID" prop="appId">
+          <el-input v-model="form.appId" placeholder="请输入微信批次ID" />
+        </el-form-item>
+        <el-form-item label="商户ID" prop="mchId">
+          <el-input v-model="form.mchId" placeholder="请输入商户ID" />
+        </el-form-item>
+        <el-form-item label="直播方式 1 app 2浏览器(可能有)" prop="wathcType">
+          <el-select v-model="form.wathcType" placeholder="请选择直播方式 1 app 2浏览器(可能有)">
+            <el-option label="请选择字典生成" value="" />
+          </el-select>
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">确 定</el-button>
+        <el-button @click="cancel">取 消</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { listLiveRedPacketLog, getLiveRedPacketLog, delLiveRedPacketLog, addLiveRedPacketLog, updateLiveRedPacketLog, exportLiveRedPacketLog } from "@/api/live/liveRedPacketLog";
+
+export default {
+  name: "LiveRedPacketLog",
+  data() {
+    return {
+      // 遮罩层
+      loading: true,
+      // 导出遮罩层
+      exportLoading: false,
+      // 选中数组
+      ids: [],
+      // 非单个禁用
+      single: true,
+      // 非多个禁用
+      multiple: true,
+      // 显示搜索条件
+      showSearch: true,
+      // 总条数
+      total: 0,
+      // 直播红包 记录表格数据
+      liveRedPacketLogList: [],
+      // 弹出层标题
+      title: "",
+      // 是否显示弹出层
+      open: false,
+      // 查询参数
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        outBatchNo: null,
+        liveId: null,
+        userId: null,
+        companyUserId: null,
+        companyId: null,
+        amount: null,
+        status: null,
+        watchLogId: null,
+        result: null,
+        batchId: null,
+        appId: null,
+        mchId: null,
+        wathcType: null
+      },
+      // 表单参数
+      form: {},
+      // 表单校验
+      rules: {
+      }
+    };
+  },
+  created() {
+    this.getList();
+  },
+  methods: {
+    /** 查询直播红包 记录列表 */
+    getList() {
+      this.loading = true;
+      listLiveRedPacketLog(this.queryParams).then(response => {
+        this.liveRedPacketLogList = response.rows;
+        this.total = response.total;
+        this.loading = false;
+      });
+    },
+    // 取消按钮
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 表单重置
+    reset() {
+      this.form = {
+        logId: null,
+        outBatchNo: null,
+        liveId: null,
+        userId: null,
+        companyUserId: null,
+        companyId: null,
+        amount: null,
+        createTime: null,
+        status: 0,
+        updateTime: null,
+        watchLogId: null,
+        remark: null,
+        result: null,
+        batchId: null,
+        appId: null,
+        mchId: null,
+        wathcType: null
+      };
+      this.resetForm("form");
+    },
+    /** 搜索按钮操作 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 重置按钮操作 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    // 多选框选中数据
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.logId)
+      this.single = selection.length!==1
+      this.multiple = !selection.length
+    },
+    /** 新增按钮操作 */
+    handleAdd() {
+      this.reset();
+      this.open = true;
+      this.title = "添加直播红包 记录";
+    },
+    /** 修改按钮操作 */
+    handleUpdate(row) {
+      this.reset();
+      const logId = row.logId || this.ids
+      getLiveRedPacketLog(logId).then(response => {
+        this.form = response.data;
+        this.open = true;
+        this.title = "修改直播红包 记录";
+      });
+    },
+    /** 提交按钮 */
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          if (this.form.logId != null) {
+            updateLiveRedPacketLog(this.form).then(response => {
+              this.msgSuccess("修改成功");
+              this.open = false;
+              this.getList();
+            });
+          } else {
+            addLiveRedPacketLog(this.form).then(response => {
+              this.msgSuccess("新增成功");
+              this.open = false;
+              this.getList();
+            });
+          }
+        }
+      });
+    },
+    /** 删除按钮操作 */
+    handleDelete(row) {
+      const logIds = row.logId || this.ids;
+      this.$confirm('是否确认删除直播红包 记录编号为"' + logIds + '"的数据项?', "警告", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        }).then(function() {
+          return delLiveRedPacketLog(logIds);
+        }).then(() => {
+          this.getList();
+          this.msgSuccess("删除成功");
+        }).catch(() => {});
+    },
+    /** 导出按钮操作 */
+    handleExport() {
+      const queryParams = this.queryParams;
+      this.$confirm('是否确认导出所有直播红包 记录数据项?', "警告", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        }).then(() => {
+          this.exportLoading = true;
+          return exportLiveRedPacketLog(queryParams);
+        }).then(response => {
+          this.download(response.msg);
+          this.exportLoading = false;
+        }).catch(() => {});
+    }
+  }
+};
+</script>