Browse Source

看课记录页面优化

yjwang 1 ngày trước cách đây
mục cha
commit
18b0e4380e
1 tập tin đã thay đổi với 487 bổ sung324 xóa
  1. 487 324
      src/views/course/courseWatchLog/index.vue

+ 487 - 324
src/views/course/courseWatchLog/index.vue

@@ -1,49 +1,86 @@
 <template>
   <div class="app-container">
     <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="100px">
+      <el-form-item label="看课方式" prop="sendType">
+        <el-select v-model="queryParams.sendType" placeholder="选择看课方式" clearable size="small" @change="handleSendTypeChange">
+          <el-option v-for="dict in sendTypeOptions" :key="dict.dictValue" :label="dict.dictLabel" :value="dict.dictValue" />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="销售公司" prop="companyIds">
+        <el-select
+          v-model="queryParams.companyIds"
+          multiple
+          collapse-tags
+          filterable
+          clearable
+          placeholder="请选择销售公司"
+          size="small"
+          style="width: 280px"
+          @change="handleCompanyIdsChange"
+        >
+          <el-option v-for="item in companyList" :key="item.dictValue" :label="item.dictLabel" :value="item.dictValue" />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="会员昵称" prop="nickName" v-if="queryParams.sendType == 1">
+        <el-input v-model="queryParams.nickName" placeholder="请输入会员昵称" clearable size="small" @keyup.enter.native="handleQuery" />
+      </el-form-item>
+      <el-form-item label="会员ID" prop="userId" v-if="queryParams.sendType == 1">
+        <el-input v-model="queryParams.userId" placeholder="请输入会员ID" clearable size="small" @keyup.enter.native="handleQuery" />
+      </el-form-item>
+      <el-form-item label="企微客户昵称" prop="externalUserName" v-if="queryParams.sendType == 2">
+        <el-input v-model="queryParams.externalUserName" placeholder="请输入企微客户昵称" clearable size="small" @keyup.enter.native="handleQuery" />
+      </el-form-item>
       <el-form-item label="课程" prop="courseId">
-        <el-select filterable  v-model="queryParams.courseId" placeholder="请选择课程"  clearable size="small" @change="courseChange(queryParams.courseId)">
-          <el-option
-            v-for="dict in courseLists"
-            :key="dict.dictValue"
-            :label="dict.dictLabel"
-            :value="dict.dictValue"
-          />
+        <el-select filterable v-model="queryParams.courseId" placeholder="请选择课程" clearable size="small" @change="courseChange(queryParams.courseId)">
+          <el-option v-for="dict in courseLists" :key="dict.dictValue" :label="dict.dictLabel" :value="dict.dictValue" />
         </el-select>
       </el-form-item>
       <el-form-item label="小节" prop="videoId">
-        <el-select filterable  v-model="queryParams.videoId" placeholder="请选择小节"  clearable size="small">
-          <el-option
-            v-for="dict in videoList"
-            :key="dict.dictValue"
-            :label="dict.dictLabel"
-            :value="dict.dictValue"
-          />
+        <el-select filterable v-model="queryParams.videoId" placeholder="请选择小节" clearable size="small">
+          <el-option v-for="dict in videoList" :key="dict.dictValue" :label="dict.dictLabel" :value="dict.dictValue" />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="所属销售" prop="companyUserId">
+        <el-select v-model="queryParams.companyUserId" clearable filterable remote placeholder="请输入关键词"
+                   :remote-method="loadCompanyUserOptions" v-select-load-more="loadMoreCompanyUserOptions" :loading="companyUserOptionsLoading">
+          <el-option v-for="item in companyUserOptions" :key="item.dictValue" :label="item.dictLabel" :value="item.dictValue" />
         </el-select>
       </el-form-item>
+      <el-form-item label="SOP名称" prop="sopId" v-if="queryParams.sendType == 2">
+        <el-autocomplete v-model="sopSearchText" :fetch-suggestions="querySopAsync" placeholder="请输入SOP名称"
+                         clearable size="small" style="width: 200px" @select="handleSopSelect" @clear="handleSopClear" :trigger-on-focus="false">
+          <template slot-scope="{ item }">
+            <span>{{ item.name }}</span>
+          </template>
+        </el-autocomplete>
+      </el-form-item>
       <el-form-item label="营期时间" prop="scheduleTime">
-        <el-date-picker
-          v-model="scheduleTime"
-          type="daterange"
-          size="small"
-          style="width: 240px"
-          value-format="yyyy-MM-dd"
-          range-separator="-"
-          start-placeholder="开始日期"
-          end-placeholder="结束日期"
-          @change="handleScheduleTimeChange">
-        </el-date-picker>
+        <el-date-picker v-model="scheduleTime" type="daterange" size="small" style="width: 240px" value-format="yyyy-MM-dd"
+                        range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" @change="handleScheduleTimeChange" />
       </el-form-item>
       <el-form-item label="创建时间" prop="createTime">
-        <el-date-picker v-model="createTime" size="small" style="width: 220px" value-format="yyyy-MM-dd" type="daterange"
-                        range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" @change="createChange"></el-date-picker>
+        <el-date-picker v-model="createTime" type="daterange" size="small" style="width: 240px" value-format="yyyy-MM-dd"
+                        range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期"
+                        :picker-options="createTimePickerOptions" @change="createChange" />
       </el-form-item>
       <el-form-item label="最新更新时间" prop="updateTime">
-        <el-date-picker v-model="updateTime" size="small" style="width: 220px" value-format="yyyy-MM-dd" type="daterange"
-                        range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" @change="updateChange"></el-date-picker>
+        <el-date-picker v-model="updateTime" type="daterange" size="small" style="width: 240px" value-format="yyyy-MM-dd"
+                        range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" @change="updateChange" />
+      </el-form-item>
+      <el-form-item label="进线时间" prop="qecCreateTime">
+        <el-date-picker v-model="qecCreateTime" type="daterange" size="small" style="width: 240px" value-format="yyyy-MM-dd"
+                        range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" :picker-options="qecPickerOptions" @change="qecCreateTimeChange" />
+      </el-form-item>
+      <el-form-item label="是否为会员" prop="isVip">
+        <el-select filterable v-model="queryParams.isVip" placeholder="请选择是否为会员" clearable size="small">
+          <el-option v-for="dict in isVipList" :key="dict.dictValue" :label="dict.dictLabel" :value="dict.dictValue" />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="营期" prop="periodId">
+        <el-select filterable v-model="queryParams.periodId" placeholder="请选择营期" clearable size="small" style="width: 220px">
+          <el-option v-for="period in periodOptions" :key="period.periodId" :label="period.periodName" :value="period.periodId" />
+        </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>
@@ -52,394 +89,520 @@
 
     <el-row :gutter="10" class="mb8">
       <el-col :span="1.5">
-        <el-button
-          type="warning"
-          plain
-          icon="el-icon-download"
-          size="mini"
-          :loading="exportLoading"
-          @click="handleExport"
-          v-hasPermi="['course:courseWatchLog:export']"
-        >导出</el-button>
+        <el-button type="warning" plain icon="el-icon-download" size="mini" :loading="exportLoading" @click="handleExport"
+                   v-hasPermi="['course:courseWatchLog:export']">导出</el-button>
       </el-col>
-      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList" />
     </el-row>
 
     <el-tabs type="card" v-model="activeName" @tab-click="handleClickX">
-      <el-tab-pane label="全部" name="00"></el-tab-pane>
-      <el-tab-pane v-for="(item,index) in logTypeOptions" :label="item.dictLabel" :name="item.dictValue"></el-tab-pane>
+      <el-tab-pane label="全部" name="00" />
+      <el-tab-pane v-for="item in logTypeOptions" :key="item.dictValue" :label="item.dictLabel" :name="item.dictValue" />
     </el-tabs>
+
     <el-table border v-loading="loading" :data="courseWatchLogList" @selection-change="handleSelectionChange">
       <el-table-column type="selection" width="55" align="center" />
       <el-table-column label="记录编号" align="center" prop="logId" />
-      <el-table-column label="用户账号" align="center" prop="qwUserName" />
-      <el-table-column label="企微客户" align="center" prop="externalUserName">
+      <el-table-column label="销售公司" align="center" prop="companyName" />
+      <el-table-column label="用户昵称" align="center">
         <template slot-scope="scope">
-          <div style="display: flex;white-space: nowrap">
-            <div style="margin: auto">
-              {{scope.row.externalUserName}}
-            </div>
-            <el-popover
-              placement="right"
-              title=""
-              trigger="hover">
-              <img slot="reference" :src="scope.row.externalUserAvatar" style="width: 30px;height: 30px">
-              <img :src="scope.row.externalUserAvatar" style="max-width: 200px;max-height: 200px">
-            </el-popover>
-          </div>
+          {{ queryParams.sendType == '1' ? scope.row.fsNickName : scope.row.externalUserName }}
         </template>
       </el-table-column>
+      <el-table-column label="会员ID" align="center" prop="userId" />
       <el-table-column label="会员昵称" align="center" prop="fsNickName">
         <template slot-scope="scope">
-          <div style="display: flex;white-space: nowrap">
-            <div style="margin: auto">
-              {{scope.row.fsNickName}}
-            </div>
-            <el-popover
-              placement="right"
-              title=""
-              trigger="hover">
-              <img slot="reference" :src="scope.row.fsAvatar" style="width: 30px;height: 30px">
-              <img :src="scope.row.fsAvatar" style="max-width: 200px;max-height: 200px">
+          <div style="display: flex; white-space: nowrap">
+            <div style="margin: auto">{{ scope.row.fsNickName }}</div>
+            <el-popover placement="right" trigger="hover" v-if="scope.row.fsAvatar">
+              <img slot="reference" :src="scope.row.fsAvatar" style="width: 30px; height: 30px">
+              <img :src="scope.row.fsAvatar" style="max-width: 200px; max-height: 200px">
             </el-popover>
           </div>
         </template>
       </el-table-column>
-      <el-table-column label="项目" align="center" prop="projectName" />
       <el-table-column label="课程名称" align="center" prop="courseName" />
       <el-table-column label="小节名称" align="center" prop="videoName" />
-      <el-table-column label="企微员工名称" align="center" prop="qwUserName" v-if="queryParams.sourceType == 2"/>
       <el-table-column label="记录类型" align="center" prop="logType">
         <template slot-scope="scope">
-          <dict-tag :options="logTypeOptions" :value="scope.row.logType"/>
+          <dict-tag :options="logTypeOptions" :value="scope.row.logType" />
         </template>
       </el-table-column>
       <el-table-column label="播放时长" align="center" prop="duration" />
       <el-table-column label="所属销售" align="center" prop="companyUserName" />
-<!--      <el-table-column label="所属公司" align="center" prop="companyName" />-->
-<!--      <el-table-column label="企微员工名称" align="center" prop="qwUserName" />-->
-      <el-table-column label="所属发送方式" align="center" prop="sendType" />
+      <el-table-column label="所属企微" align="center" prop="qwUserName" v-if="queryParams.sendType == 2" />
       <el-table-column label="创建时间" align="center" prop="createTime" />
       <el-table-column label="更新时间" align="center" prop="updateTime" />
       <el-table-column label="完课时间" align="center" prop="finishTime" />
       <el-table-column label="营期时间" align="center" prop="campPeriodTime" />
+      <el-table-column label="进线时间" align="center" prop="qecCreateTime" />
+      <el-table-column fixed="right" label="操作" width="100">
+        <template slot-scope="scope">
+          <el-button @click="openAnswerLogFun(scope.row)" type="text" size="small">答题记录</el-button>
+          <el-button @click="openRedLogFun(scope.row)" type="text" size="small">红包记录</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"
-    />
+    <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" @pagination="getList" />
+
+    <el-drawer title="答题记录" :visible.sync="openAnswerLog" size="70%" append-to-body>
+      <el-table border v-loading="loadingAnswerLog" :data="answerLogsList">
+        <el-table-column label="会员用户" align="center" prop="userName">
+          <template slot-scope="scope">
+            <div style="display: flex; white-space: nowrap">
+              <div style="margin: auto">{{ scope.row.userName }}</div>
+              <el-popover placement="right" trigger="hover" v-if="scope.row.fsAvatar">
+                <img slot="reference" :src="scope.row.fsAvatar" style="width: 30px; height: 30px">
+                <img :src="scope.row.fsAvatar" style="max-width: 200px; max-height: 200px">
+              </el-popover>
+            </div>
+          </template>
+        </el-table-column>
+        <el-table-column label="课程名称" align="center" prop="courseName" />
+        <el-table-column label="小节名称" align="center" prop="videoName" />
+        <el-table-column label="是否全部正确" align="center">
+          <template slot-scope="scope">
+            <el-tag v-if="scope.row.isRight == 1" type="success">是</el-tag>
+            <el-tag v-else type="danger">否</el-tag>
+          </template>
+        </el-table-column>
+        <el-table-column label="销售名称" align="center" prop="companyUserName" />
+        <el-table-column label="企微员工名称" align="center" prop="qwUserName" />
+        <el-table-column label="公司名称" align="center" prop="companyName" />
+        <el-table-column label="创建时间" align="center" prop="createTime" />
+      </el-table>
+      <pagination v-show="answerLogTotal > 0" :total="answerLogTotal" :page.sync="answerLogQueryParams.pageNum"
+                  :limit.sync="answerLogQueryParams.pageSize" @pagination="answerLogList" />
+    </el-drawer>
 
+    <el-drawer title="红包记录" :visible.sync="openRedLog" size="70%" append-to-body>
+      <el-table border v-loading="loadingRedLog" :data="redLogsList">
+        <el-table-column label="记录编号" align="center" prop="logId" />
+        <el-table-column label="批次单号" align="center" prop="outBatchNo" />
+        <el-table-column label="课程名称" align="center" prop="courseId">
+          <template slot-scope="scope">
+            <span v-for="item in courseLists" :key="item.dictValue" v-if="scope.row.courseId == item.dictValue">{{ item.dictLabel }}</span>
+          </template>
+        </el-table-column>
+        <el-table-column label="小节名称" align="center" prop="title" />
+        <el-table-column label="会员用户" align="center" prop="fsNickName">
+          <template slot-scope="scope">
+            <div style="display: flex; white-space: nowrap">
+              <div style="margin: auto">{{ scope.row.fsNickName }}</div>
+              <el-popover placement="right" trigger="hover" v-if="scope.row.fsAvatar">
+                <img slot="reference" :src="scope.row.fsAvatar" style="width: 30px; height: 30px">
+                <img :src="scope.row.fsAvatar" style="max-width: 200px; max-height: 200px">
+              </el-popover>
+            </div>
+          </template>
+        </el-table-column>
+        <el-table-column label="转帐金额" align="center" prop="amount" />
+        <el-table-column label="状态" align="center" prop="status">
+          <template slot-scope="scope">
+            <el-tag>{{ scope.row.status === 0 ? '发送中' : scope.row.status === 2 ? '待补发' : '已完成' }}</el-tag>
+          </template>
+        </el-table-column>
+        <el-table-column label="所属企微" align="center" prop="qwUserName" />
+        <el-table-column label="创建时间" align="center" prop="createTime" />
+      </el-table>
+      <pagination v-show="redLogTotal > 0" :total="redLogTotal" :page.sync="redLogQueryParams.pageNum"
+                  :limit.sync="redLogQueryParams.pageSize" @pagination="redLogList" />
+    </el-drawer>
   </div>
 </template>
 
 <script>
-import { listCourseWatchLog, getCourseWatchLog, delCourseWatchLog, addCourseWatchLog, updateCourseWatchLog, exportCourseWatchLog } from "@/api/course/courseWatchLog";
-import {allList}from "@/api/company/company";
-import { courseList,videoList } from '@/api/course/courseRedPacketLog'
-import {getUserList} from "@/api/company/companyUser";
-import {getFsUserList} from "@/api/users/user";
+import { listCourseWatchLog, exportCourseWatchLog } from '@/api/course/courseWatchLog'
+import { courseList, videoList, listCourseRedPacketLog } from '@/api/course/courseRedPacketLog'
+import { listLogs } from '@/api/course/courseAnswerlogs'
+import { allList } from '@/api/company/company'
+import { getCompanyUserListLikeName } from '@/api/company/companyUser'
+import { listPeriod } from '@/api/course/userCoursePeriod'
+import { listSop } from '@/api/qw/sop'
+
 export default {
-  name: "CourseWatchLog",
+  name: 'CourseWatchLog',
   data() {
     return {
-      userSourceTypeOptions: [],
-      activeName:"00",
-      createTime:null,
-      updateTime:null,
-      courseLists:[],
-      videoList:[],
-      logTypeOptions:[],
-      queryUserLoading: false,
-      // 遮罩层
+      activeName: '2',
+      createTime: null,
+      updateTime: null,
+      scheduleTime: null,
+      qecCreateTime: null,
+      qecPickerOptions: {
+        disabledDate(time) {
+          const sixDaysAgo = new Date()
+          sixDaysAgo.setDate(sixDaysAgo.getDate() - 6)
+          sixDaysAgo.setHours(0, 0, 0, 0)
+          const tomorrow = new Date()
+          tomorrow.setDate(tomorrow.getDate() + 1)
+          tomorrow.setHours(0, 0, 0, 0)
+          return time.getTime() < sixDaysAgo.getTime() || time.getTime() >= tomorrow.getTime()
+        }
+      },
+      createTimePickerOptions: {
+        disabledDate: (time) => {
+          const minDate = new Date()
+          minDate.setMonth(minDate.getMonth() - 3)
+          minDate.setHours(0, 0, 0, 0)
+          const tomorrow = new Date()
+          tomorrow.setDate(tomorrow.getDate() + 1)
+          tomorrow.setHours(0, 0, 0, 0)
+          return time.getTime() < minDate.getTime() || time.getTime() >= tomorrow.getTime()
+        }
+      },
+      companyList: [],
+      courseLists: [],
+      videoList: [],
+      logTypeOptions: [],
+      periodOptions: [],
+      sendTypeOptions: [
+        { dictLabel: '会员', dictValue: '1' },
+        { dictLabel: '企微', dictValue: '2' }
+      ],
+      isVipList: [
+        { dictLabel: '是', dictValue: 1 },
+        { dictLabel: '否', dictValue: 0 }
+      ],
       loading: true,
-      // 导出遮罩层
       exportLoading: false,
-      // 选中数组
       ids: [],
-      // 非单个禁用
-      single: true,
-      // 非多个禁用
-      multiple: true,
-      // 显示搜索条件
       showSearch: true,
-      // 总条数
       total: 0,
-      companyUserList: [],
-      // 短链课程看课记录表格数据
       courseWatchLogList: [],
-      fsUserList: [],
-      // 弹出层标题
-      title: "",
-      // 是否显示弹出层
-      open: false,
-
-      // 查询参数
+      sopSearchText: '',
+      openAnswerLog: false,
+      loadingAnswerLog: true,
+      answerLogsList: [],
+      answerLogTotal: 0,
+      answerLogQueryParams: { pageNum: 1, pageSize: 10 },
+      openRedLog: false,
+      loadingRedLog: true,
+      redLogsList: [],
+      redLogTotal: 0,
+      redLogQueryParams: { pageNum: 1, pageSize: 10 },
       queryParams: {
         pageNum: 1,
         pageSize: 10,
         userId: null,
         nickName: null,
         videoId: null,
-        logType: null,
-        qwExternalContactId: null,
-        externalUserName:null,
-        duration: null,
-        qwUserId: null,
+        logType: 2,
+        externalUserName: null,
         companyUserId: null,
-        companyId: null,
+        companyIds: [],
         courseId: null,
-        sTime:null,
-        eTime:null,
-        upSTime:null,
-        upETime:null,
+        sTime: null,
+        eTime: null,
+        upSTime: null,
+        upETime: null,
+        qecSTime: null,
+        qecETime: null,
         scheduleStartTime: null,
         scheduleEndTime: null,
-        sourceType: 1
-      },
-      // 表单参数
-      form: {},
-      // 表单校验
-      rules: {
+        sendType: '2',
+        isVip: null,
+        sopId: null,
+        periodId: null
       },
-      scheduleTime: null,
-    };
+      companyUserOptionsParams: { name: undefined, hasNextPage: false, pageNum: 1, pageSize: 10 },
+      companyUserOptions: [],
+      companyUserOptionsLoading: false
+    }
   },
   created() {
     courseList().then(response => {
-      this.courseLists = response.list;
-    });
-    this.getList();
-    this.getDicts("sys_course_watch_log_type").then(response => {
-      this.logTypeOptions = response.data;
-    });
-
-
-    this.getDicts('user_source_type').then(response => {
-      this.userSourceTypeOptions = response.data;
+      this.courseLists = response.list
+    })
+    this.initDefaultCreateTime()
+    allList().then(res => {
+      this.companyList = res.rows || []
+      this.queryParams.companyIds = this.getDefaultCompanyIds()
+      this.loadPeriodOptions()
+      this.getList()
+    })
+    this.getDicts('sys_course_watch_log_type').then(response => {
+      this.logTypeOptions = response.data
     })
-
-  },
-  computed: {
-    sourceTypeModel: {
-      get() {
-        return this.queryParams.sourceType !== null && this.queryParams.sourceType !== undefined ? this.queryParams.sourceType.toString() : null;
-      },
-      set(newVal) {
-        this.queryParams.sourceType = newVal;
-      }
-    }
   },
   methods: {
-    handleClear(){
-      this.queryUserLoading = false;
-      this.fsUserList = [];
+    formatDate(date) {
+      const y = date.getFullYear()
+      const m = String(date.getMonth() + 1).padStart(2, '0')
+      const d = String(date.getDate()).padStart(2, '0')
+      return `${y}-${m}-${d}`
     },
-    remoteGetFsUserList(query){
-      if(query){
-        this.queryUserLoading = true;
-        const isNumeric = /^\d+$/.test(query);
-        let payload = {
-          username: query,
-          nickname: query
-        }
-        if(isNumeric) {
-          payload = {
-            userId: query,
-            username: query,
-            phone: query
-          }
-        }
-        getFsUserList(payload).then(res=>{
-          if(res.code === 200) {
-            this.fsUserList = res.data
-          }
-        }).finally(()=>{
-          this.queryUserLoading = false;
+    getDefaultThreeMonthsRange() {
+      const end = new Date()
+      const start = new Date()
+      start.setMonth(start.getMonth() - 3)
+      return [this.formatDate(start), this.formatDate(end)]
+    },
+    initDefaultCreateTime() {
+      const range = this.getDefaultThreeMonthsRange()
+      this.createTime = range
+      this.queryParams.sTime = range[0]
+      this.queryParams.eTime = range[1]
+    },
+    getFirstCompanyId() {
+      return this.companyList.length > 0 ? this.companyList[0].dictValue : null
+    },
+    getDefaultCompanyIds() {
+      const firstId = this.getFirstCompanyId()
+      return firstId != null ? [firstId] : []
+    },
+    buildQueryParams() {
+      const params = { ...this.queryParams }
+      params.companyId = null
+      params.allCompany = 0
+      if (!params.companyIds || params.companyIds.length === 0) {
+        params.companyIds = this.getDefaultCompanyIds()
+      }
+      return params
+    },
+    loadCompanyUserOptions(query) {
+      this.companyUserOptions = []
+      if (query === '') return
+      this.companyUserOptionsParams.pageNum = 1
+      this.companyUserOptionsParams.name = query
+      this.companyUserOptionsLoading = true
+      this.getCompanyUserListLikeName()
+    },
+    loadMoreCompanyUserOptions() {
+      if (!this.companyUserOptionsParams.hasNextPage) return
+      this.companyUserOptionsParams.pageNum += 1
+      this.getCompanyUserListLikeName()
+    },
+    getCompanyUserListLikeName() {
+      getCompanyUserListLikeName(this.companyUserOptionsParams).then(response => {
+        this.companyUserOptions = [...this.companyUserOptions, ...response.data.list]
+        this.companyUserOptionsParams.hasNextPage = response.data.hasNextPage
+        this.companyUserOptionsLoading = false
+      })
+    },
+    handleCompanyIdsChange(val) {
+      if (!val || val.length === 0) {
+        const defaultIds = this.getDefaultCompanyIds()
+        this.$nextTick(() => {
+          this.queryParams.companyIds = defaultIds
         })
+        if (defaultIds.length === 0) {
+          return
+        }
+      }
+      this.queryParams.periodId = null
+      this.loadPeriodOptions()
+    },
+    loadPeriodOptions() {
+      const params = { pageNum: 1, pageSize: 9999 }
+      const companyIds = this.queryParams.companyIds || []
+      if (companyIds.length === 1) {
+        params.companyId = companyIds[0]
       }
+      listPeriod(params).then(response => {
+        this.periodOptions = response.rows || []
+      })
     },
-    courseChange(row){
-      this.queryParams.videoId=null;
-      if(row === ''){
-        this.videoList=[];
+    courseChange(row) {
+      this.queryParams.videoId = null
+      if (row === '') {
+        this.videoList = []
         return
       }
       videoList(row).then(response => {
-        this.videoList=response.list
-      });
+        this.videoList = response.list
+      })
     },
-    createChange() {
-      if (this.createTime != null) {
-        this.queryParams.sTime = this.createTime[0];
-        this.queryParams.eTime = this.createTime[1];
+    handleScheduleTimeChange(val) {
+      if (val) {
+        this.queryParams.scheduleStartTime = val[0]
+        this.queryParams.scheduleEndTime = val[1]
       } else {
-        this.queryParams.sTime = null;
-        this.queryParams.eTime = null;
+        this.queryParams.scheduleStartTime = null
+        this.queryParams.scheduleEndTime = null
       }
     },
-
-    updateChange(){
-      if (this.updateTime != null) {
-        this.queryParams.upSTime = this.updateTime[0];
-        this.queryParams.upETime = this.updateTime[1];
+    createChange(val) {
+      if (val) {
+        const minDate = new Date()
+        minDate.setMonth(minDate.getMonth() - 3)
+        minDate.setHours(0, 0, 0, 0)
+        let start = new Date(val[0])
+        let end = new Date(val[1])
+        if (start.getTime() < minDate.getTime()) {
+          this.$message.warning('创建时间最早只能选近三个月')
+          start = minDate
+        }
+        const today = new Date()
+        today.setHours(23, 59, 59, 999)
+        if (end.getTime() > today.getTime()) {
+          end = today
+        }
+        const startStr = this.formatDate(start)
+        const endStr = this.formatDate(end)
+        this.createTime = [startStr, endStr]
+        this.queryParams.sTime = startStr
+        this.queryParams.eTime = endStr
       } else {
-        this.queryParams.upSTime = null;
-        this.queryParams.upETime = null;
+        this.initDefaultCreateTime()
       }
     },
-    handleClickX(tab,event){
-      this.activeName=tab.name;
-      if(tab.name=="00"){
-        this.queryParams.logType=null;
-      }else{
-        this.queryParams.logType=tab.name;
+    updateChange(val) {
+      if (val) {
+        this.queryParams.upSTime = val[0]
+        this.queryParams.upETime = val[1]
+      } else {
+        this.queryParams.upSTime = null
+        this.queryParams.upETime = null
       }
-      this.getList()
     },
-    /** 查询短链课程看课记录列表 */
-    getList() {
-      this.loading = true;
-      if(this.queryParams.logType == "10"){
-        this.queryParams.logType = null;
+    qecCreateTimeChange(val) {
+      if (val) {
+        const startDate = new Date(val[0])
+        const endDate = new Date(val[1])
+        const diffDays = Math.ceil(Math.abs(endDate - startDate) / (1000 * 60 * 60 * 24))
+        if (diffDays > 6) {
+          this.$message.error('进线时间选择范围不能超过7天')
+          this.qecCreateTime = null
+          this.queryParams.qecSTime = null
+          this.queryParams.qecETime = null
+          return
+        }
+        this.queryParams.qecSTime = val[0]
+        this.queryParams.qecETime = val[1]
+      } else {
+        this.queryParams.qecSTime = null
+        this.queryParams.qecETime = null
       }
-
-      listCourseWatchLog(this.queryParams).then(response => {
-        this.courseWatchLogList = response.rows;
-        this.total = response.total;
-        this.loading = false;
-      });
     },
-    // 取消按钮
-    cancel() {
-      this.open = false;
-      this.reset();
+    handleClickX(tab) {
+      this.activeName = tab.name
+      this.queryParams.logType = tab.name === '00' ? null : tab.name
+      this.getList()
     },
-    // 表单重置
-    reset() {
-      this.form = {
-        logId: null,
-        userId: null,
-        videoId: null,
-        logType: null,
-        createTime: null,
-        updateTime: null,
-        qwExternalContactId: null,
-        externalUserName:null,
-        duration: null,
-        qwUserId: null,
-        companyUserId: null,
-        companyId: null,
-        courseId: null,
-        scheduleStartTime: null,
-        scheduleEndTime: null,
-      };
-      this.scheduleTime=null;
-      this.resetForm("form");
+    handleSendTypeChange() {
+      this.handleQuery()
+    },
+    getList() {
+      this.loading = true
+      listCourseWatchLog(this.buildQueryParams()).then(response => {
+        this.courseWatchLogList = response.rows
+        this.total = response.total
+        this.loading = false
+      })
     },
-    /** 搜索按钮操作 */
     handleQuery() {
-      this.queryParams.pageNum = 1;
-      this.getList();
+      this.queryParams.pageNum = 1
+      this.getList()
     },
-    /** 重置按钮操作 */
     resetQuery() {
-      this.resetForm("queryForm");
-      this.createTime = null;
-      this.scheduleTime = null;
-      this.queryParams.sTime = null;
-      this.queryParams.eTime = null;
-      this.queryParams.upSTime = null;
-      this.queryParams.upETime = null;
-      this.queryParams.scheduleStartTime = null;
-      this.queryParams.scheduleEndTime = null;
-      this.scheduleTime=null;
-      this.updateTime=null;
-      this.handleQuery();
+      this.resetForm('queryForm')
+      this.updateTime = null
+      this.scheduleTime = null
+      this.qecCreateTime = null
+      this.queryParams.upSTime = null
+      this.queryParams.upETime = null
+      this.queryParams.qecSTime = null
+      this.queryParams.qecETime = null
+      this.queryParams.scheduleStartTime = null
+      this.queryParams.scheduleEndTime = null
+      this.queryParams.sopId = null
+      this.queryParams.periodId = null
+      this.queryParams.companyIds = this.getDefaultCompanyIds()
+      this.handleSopClear()
+      this.initDefaultCreateTime()
+      this.loadPeriodOptions()
+      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 = "添加短链课程看课记录";
+    validateExportConditions() {
+      const p = this.buildQueryParams()
+      const hasCreateTime = p.sTime && p.eTime
+      const hasUpdateTime = p.upSTime && p.upETime
+      const hasScheduleTime = p.scheduleStartTime && p.scheduleEndTime
+      const hasQecTime = p.qecSTime && p.qecETime
+      const hasOther = (p.companyIds && p.companyIds.length > 0) || p.courseId || p.videoId || p.periodId || p.userId || p.companyUserId || p.nickName || p.externalUserName || p.sopId
+      if (!hasCreateTime && !hasUpdateTime && !hasScheduleTime && !hasQecTime && !hasOther) {
+        this.$message.warning('导出请至少选择时间范围,或指定公司/课程/营期/销售等条件')
+        return false
+      }
+      const checkRange = (start, end, maxDays, label) => {
+        if (!start || !end) return true
+        const diff = (new Date(end) - new Date(start)) / (1000 * 60 * 60 * 24)
+        if (diff > maxDays - 1) {
+          this.$message.warning(label + '导出范围不能超过' + maxDays + '天')
+          return false
+        }
+        return true
+      }
+      return checkRange(p.sTime, p.eTime, 31, '创建时间')
+        && checkRange(p.upSTime, p.upETime, 31, '更新时间')
+        && checkRange(p.scheduleStartTime, p.scheduleEndTime, 31, '营期时间')
+        && checkRange(p.qecSTime, p.qecETime, 7, '进线时间')
     },
-    /** 修改按钮操作 */
-    handleUpdate(row) {
-      this.reset();
-      const logId = row.logId || this.ids
-      getCourseWatchLog(logId).then(response => {
-        this.form = response.data;
-        this.open = true;
-        this.title = "修改短链课程看课记录";
-      });
+    handleExport() {
+      if (!this.validateExportConditions()) return
+      this.$confirm('是否确认按当前筛选条件导出看课记录?', '警告', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      }).then(() => {
+        this.exportLoading = true
+        return exportCourseWatchLog(this.buildQueryParams())
+      }).then(response => {
+        this.download(response.msg)
+        this.exportLoading = false
+      }).catch(() => {
+        this.exportLoading = false
+      })
     },
-    /** 提交按钮 */
-    submitForm() {
-      this.$refs["form"].validate(valid => {
-        if (valid) {
-          if (this.form.logId != null) {
-            updateCourseWatchLog(this.form).then(response => {
-              this.msgSuccess("修改成功");
-              this.open = false;
-              this.getList();
-            });
-          } else {
-            addCourseWatchLog(this.form).then(response => {
-              this.msgSuccess("新增成功");
-              this.open = false;
-              this.getList();
-            });
-          }
-        }
-      });
+    openAnswerLogFun(row) {
+      this.openAnswerLog = true
+      this.answerLogQueryParams.watchLogId = row.logId
+      this.answerLogList()
     },
-    /** 删除按钮操作 */
-    handleDelete(row) {
-      const logIds = row.logId || this.ids;
-      this.$confirm('是否确认删除短链课程看课记录编号为"' + logIds + '"的数据项?', "警告", {
-          confirmButtonText: "确定",
-          cancelButtonText: "取消",
-          type: "warning"
-        }).then(function() {
-          return delCourseWatchLog(logIds);
-        }).then(() => {
-          this.getList();
-          this.msgSuccess("删除成功");
-        }).catch(() => {});
+    answerLogList() {
+      this.loadingAnswerLog = true
+      listLogs(this.answerLogQueryParams).then(e => {
+        this.answerLogsList = e.rows
+        this.answerLogTotal = e.total
+        this.loadingAnswerLog = false
+      })
     },
-    /** 导出按钮操作 */
-    handleExport() {
-      const queryParams = this.queryParams;
-      this.$confirm('是否确认导出所有短链课程看课记录数据项?', "警告", {
-          confirmButtonText: "确定",
-          cancelButtonText: "取消",
-          type: "warning"
-        }).then(() => {
-          this.exportLoading = true;
-          return exportCourseWatchLog(queryParams);
-        }).then(response => {
-          this.download(response.msg);
-          this.exportLoading = false;
-        }).catch(() => {});
+    openRedLogFun(row) {
+      this.openRedLog = true
+      this.redLogQueryParams.watchLogId = row.logId
+      this.redLogList()
     },
-    handleScheduleTimeChange(val) {
-      if (val) {
-        this.queryParams.scheduleStartTime = val[0];
-        this.queryParams.scheduleEndTime = val[1];
-      } else {
-        this.queryParams.scheduleStartTime = null;
-        this.queryParams.scheduleEndTime = null;
+    redLogList() {
+      this.loadingRedLog = true
+      listCourseRedPacketLog(this.redLogQueryParams).then(e => {
+        this.redLogsList = e.rows
+        this.redLogTotal = e.total
+        this.loadingRedLog = false
+      })
+    },
+    querySopAsync(queryString, callback) {
+      if (!queryString) {
+        callback([])
+        return
       }
+      listSop({ name: queryString, pageNum: 1, pageSize: 20 }).then(response => {
+        const rows = response.rows || []
+        callback(rows.map(item => ({ value: item.name, id: item.id, name: item.name })))
+      }).catch(() => callback([]))
+    },
+    handleSopSelect(item) {
+      this.queryParams.sopId = item.id
+      this.sopSearchText = item.name
     },
+    handleSopClear() {
+      this.queryParams.sopId = null
+      this.sopSearchText = ''
+    }
   }
-};
+}
 </script>