Procházet zdrojové kódy

feat:appim发课、标签、欢迎语等

caoliqin před 1 týdnem
rodič
revize
37c2f468a4

+ 25 - 0
src/api/course/courseWatchLog.js

@@ -145,3 +145,28 @@ export function exportCourseStatisticsUserDetail(videoId, periodId) {
     params: { videoId, periodId }
   })
 }
+
+// 根据名称模糊查询用户列表app看课
+export function getCustomerListLikeName(params) {
+  return request({
+    url: '/course/appCourseWatchLog/getCustomerListLikeName',
+    method: 'get',
+    params: params
+  })
+}
+// 查询短链课程看课记录列表app看课
+export function listAppCourseWatchLog(query) {
+  return request({
+    url: '/course/appCourseWatchLog/list',
+    method: 'get',
+    params: query
+  })
+}
+// 导出短链课程看课记录app看课
+export function exportAppCourseWatchLog(query) {
+  return request({
+    url: '/course/appCourseWatchLog/export',
+    method: 'get',
+    params: query
+  })
+}

+ 51 - 0
src/router/index.js

@@ -166,6 +166,57 @@ export const constantRoutes = [
       }
     ]
   },
+
+  {
+    path: '/user/sopTemp',
+    component: Layout,
+    hidden: true,
+    children: [
+      {
+        path: 'updateSopTemp/:id/:type(\\d+)', // 确保 :type 的正则匹配数字
+        component: () => import('@/views/app/sop/template/updateSopTemp'),
+        name: 'updateSopTemp',
+        meta: { title: '改动SOP模板', activeMenu: '/user/sopTemp' }
+      }
+    ]
+  },
+  {
+    path: '/app',
+    component: Layout,
+    hidden: true,
+    children: [
+      {
+        path: 'sop',
+        component: (resolve) => require(['@/views/app/sop/info'], resolve),
+        name: 'info',
+        meta: { title: 'SOP任务', activeMenu: '/app/sop'}
+      },
+      {
+        path: 'sop/addSop',
+        component: (resolve) => require(['@/views/app/sop/info/addSop'], resolve),
+        name: 'addSop',
+        meta: { title: '新增SOP任务', activeMenu: '/app/sop'}
+      },
+      {
+        path: 'sop/updateSop/:id/:type',
+        component: (resolve) => require(['@/views/app/sop/info/addSop.vue'], resolve),
+        name: 'updateSop',
+        meta: { title: '修改/查看SOP任务', activeMenu: '/app/sop'}
+      },
+      {
+        path: 'sop/sopUserLogsSchedule/:id',
+        component: (resolve) => require(['@/views/app/sop/userLogs/sopUserLogsSchedule.vue'], resolve),
+        name: 'sopUserLogsSchedule',
+        meta: { title: '查看营期', activeMenu: '/app/sop'}
+      },
+      {
+        path: 'invitationCode',
+        component: (resolve) => require(['@/views/app/invitationCode'], resolve),
+        name: 'invitationCode',
+        meta: { title: '邀请码', activeMenu: '/app/invitationCode'}
+      },
+    ]
+  },
   {
     path: '/course/sopTempe',
     component: Layout,

+ 3 - 3
src/views/app/sop/info/index.vue

@@ -648,7 +648,7 @@ export default {
         },
         /**
          * 获取科普列表
-         * @param keyword 
+         * @param keyword
          */
         async getCourseList(keyword) {
             let query = {
@@ -869,8 +869,8 @@ export default {
         },
         /**
          * 新客户自动创建sop
-         * @param row 
-         * @param checked 
+         * @param row
+         * @param checked
          */
         switchAutoSopChange(row, checked) {
             this.form.startTime = row.startTime;

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 168 - 168
src/views/app/sop/template/updateSopTemp.vue


+ 25 - 25
src/views/app/sop/userLogs/sopLogsList.vue

@@ -140,7 +140,7 @@
                   <span>类型:</span>
                   <el-tag
                     type="primary"
-                    v-for="op in contentTypeOptions" 
+                    v-for="op in contentTypeOptions"
                     :key="op.dictValue"
                     v-if="item.contentType == op.dictValue"
                   >
@@ -152,10 +152,10 @@
                 </div>
               </div>
               <div v-if="!item.success">失败原因:<span style="color: #ff4949">{{item.message}}</span></div>
-              
+
               <!-- 文本 -->
               <div v-if="item.contentType == 11" v-html="item.value"></div>
-              
+
               <!-- 图片 -->
               <div v-else-if="item.contentType == 2" class="message-style">
                 <div
@@ -222,7 +222,7 @@
                     <div style="font-size: 13px; flex: 1; display: flex; align-items: center;">
                       {{ item.packageName }}
                     </div>
-                    <ImageUpload 
+                    <ImageUpload
                       :disabled="true"
                       v-model="item.packageImgUrl"
                       type="image"
@@ -381,7 +381,7 @@
                   <span>类型:</span>
                   <el-tag
                     type="primary"
-                    v-for="op in contentTypeOptions" 
+                    v-for="op in contentTypeOptions"
                     :key="op.dictValue"
                     v-if="item.contentType == op.dictValue"
                   >
@@ -392,10 +392,10 @@
                   发送状态:<el-tag type="primary" v-text="'待发送'"/>
                 </div>
               </div>
-              
+
               <!-- 文本 -->
               <div v-if="item.contentType == 11" v-html="item.value"></div>
-              
+
               <!-- 图片 -->
               <div v-else-if="item.contentType == 2" class="message-style">
                 <div
@@ -462,7 +462,7 @@
                     <div style="font-size: 13px; flex: 1; display: flex; align-items: center;">
                       {{ item.packageName }}
                     </div>
-                    <ImageUpload 
+                    <ImageUpload
                       :disabled="true"
                       v-model="item.packageImgUrl"
                       type="image"
@@ -637,10 +637,10 @@
       @pagination="getList"
     />
 
-    <el-dialog 
-      title="标签搜索" 
-      :visible.sync="tagSearchConfig.visible" 
-      custom-class="dialog-search-tag" 
+    <el-dialog
+      title="标签搜索"
+      :visible.sync="tagSearchConfig.visible"
+      custom-class="dialog-search-tag"
       append-to-body
     >
       <div>搜索标签:
@@ -665,12 +665,12 @@
           </div>
         </div>
       </div>
-      
-      <pagination 
-        v-show="tagSearchConfig.total > 0" 
-        :total="tagSearchConfig.total" 
+
+      <pagination
+        v-show="tagSearchConfig.total > 0"
+        :total="tagSearchConfig.total"
         :page.sync="tagSearchConfig.queryParams.pageNum"
-        :limit.sync="tagSearchConfig.queryParams.pageSize" 
+        :limit.sync="tagSearchConfig.queryParams.pageSize"
         @pagination="getSearchTagGroupList"
       />
       <div slot="footer" class="dialog-footer">
@@ -680,10 +680,10 @@
     </el-dialog>
 
     <el-dialog title="客服搜索" :visible.sync="bindAISearch.visible" width="1000px" append-to-body>
-      <CusRoleList 
+      <CusRoleList
         ref="QwUserList"
         @confirm="customerSelectedConfirmCallForBind"
-        @selectionChange="customerSelectionChangeCallForBind" 
+        @selectionChange="customerSelectionChangeCallForBind"
         :selected="bindAISearch.selected"
         :ids="customerIds"
       />
@@ -696,7 +696,7 @@
 import { exportSopLogs, listSopLogsList, delSopLogs, editCourseSopLogs} from '@/api/app/sopLogs';
 
 import { listTagGroupForUserBindTag } from "@/api/app/tag/tagGroup";
-import { getLiveOptions,} from "@/api/app/live";
+// import { getLiveOptions,} from "@/api/app/live";
 
 
 import CusRoleList from '@/views/app/user/CusRoleList.vue';
@@ -819,9 +819,9 @@ export default {
 
   },
   methods: {
-    async getLiveList() {
-      return await getLiveOptions();
-    },
+    // async getLiveList() {
+    //   return await getLiveOptions();
+    // },
     getList(val) {
       let qp = {...this.queryParams};
       qp['sopId'] = val.id || this.rowDetailFrom.id;
@@ -1094,7 +1094,7 @@ export default {
       row.isSelected = !row.isSelected;
       if (row.isSelected) {
         this.tagSearchConfig.selected.push({tagId: row.id, tagName: row.name});
-      } 
+      }
       //
       else {
         this.tagSearchConfig.selected = this.tagSearchConfig.selected.filter(item => item.tagId !== row.id);
@@ -1139,7 +1139,7 @@ export default {
     },
     /**
      * 确认客服
-     * @param list 
+     * @param list
      */
     customerSelectedConfirmCallForBind() {
       this.bindAISearch.visible = false;

+ 135 - 135
src/views/app/sop/userLogsInfo/groupSendMessage.vue

@@ -9,7 +9,7 @@
       </template>
     </el-alert>
 
-    <el-form 
+    <el-form
       ref="groupSendMessageForm"
       :model="groupSendMessageForm"
       :rules="groupSendRules"
@@ -97,7 +97,7 @@
         >
           <el-row style="padding-bottom: 20px">
             <el-col :span="22">
-              <el-form 
+              <el-form
                 :model="content"
                 label-width="100px"
               >
@@ -105,7 +105,7 @@
                   style="margin: 2%"
                 >
                   <div>
-                    <el-radio-group 
+                    <el-radio-group
                       v-model="content.contentType"
                       @change="handleContentTypeChange()"
                     >
@@ -164,7 +164,7 @@
                       <el-form-item label="链接地址:"
                         label-width="100px"
                       >
-                        <el-tag 
+                        <el-tag
                           type="warning"
                           v-model="content.isBindUrl"
                         >选择的科普小节
@@ -173,7 +173,7 @@
                       </el-form-item>
                       <el-form-item label="课节过期时间">
                         <el-row>
-                          <el-input 
+                          <el-input
                             type="number"
                             v-model="content.expiresDays"
                             style="width: 200px"
@@ -242,7 +242,7 @@
 
                 <!-- 语音 -->
                 <el-form-item label="内容" v-else-if="12 == content.contentType">
-                  
+
                   <div>
                     <el-input
                       v-model="content.value"
@@ -260,7 +260,7 @@
 
                 <!-- 图片 -->
                 <el-form-item label="内容" v-else-if="2 == content.contentType">
-                  
+
                   <ImageUpload
                     v-model="content.imgUrl"
                     type="image"
@@ -273,9 +273,9 @@
 
                 <!-- 视频 -->
                 <el-form-item label="内容" v-else-if="6 == content.contentType">
-                
+
                   <div>
-                    <el-form-item 
+                    <el-form-item
                       label="上传视频:"
                       prop="videoUrl"
                       label-width="100px"
@@ -290,7 +290,7 @@
                       >
                         <i class="el-icon-plus avatar-uploader-icon"></i>
                       </el-upload>
-                      <video 
+                      <video
                         v-if="content.videoUrl"
                         :src="content.videoUrl"
                         controls
@@ -304,9 +304,9 @@
 
                 <!-- 疗法 -->
                 <el-form-item label="内容" v-else-if="20 == content.contentType">
-                    
+
                   <el-card class="box-card">
-                    <el-form-item 
+                    <el-form-item
                       label="选择疗法:"
                       label-width="100px"
                       required
@@ -331,7 +331,7 @@
                         />
                       </el-select>
                     </el-form-item>
-                    <el-form-item 
+                    <el-form-item
                       label="疗法名称:"
                       label-width="100px"
                     >
@@ -342,11 +342,11 @@
                         style="width: 90%;margin-top: 1%;"
                       />
                     </el-form-item>
-                    <el-form-item 
+                    <el-form-item
                       label="疗法封面:"
                       label-width="100px"
                     >
-                      <ImageUpload 
+                      <ImageUpload
                         :disabled="true"
                         v-model="content.packageImgUrl"
                         type="image"
@@ -417,7 +417,7 @@
                 <el-form-item label="内容" v-else-if="22 == content.contentType">
                   <div>
                     <el-card class="box-card">
-                      <el-form-item 
+                      <el-form-item
                         label="选择民品:"
                         label-width="100px"
                         required
@@ -442,7 +442,7 @@
                           />
                         </el-select>
                       </el-form-item>
-                      <el-form-item 
+                      <el-form-item
                         label="民品名称:"
                         label-width="100px"
                       >
@@ -453,11 +453,11 @@
                           style="width: 90%;margin-top: 1%;"
                         />
                       </el-form-item>
-                      <el-form-item 
+                      <el-form-item
                         label="民品封面:"
                         label-width="100px"
                       >
-                        <ImageUpload 
+                        <ImageUpload
                           :disabled="true"
                           v-model="content.productImgUrl"
                           type="image"
@@ -476,7 +476,7 @@
                 <el-form-item label="内容" v-else-if="23 == content.contentType">
                   <div>
                     <el-card class="box-card">
-                      <el-form-item 
+                      <el-form-item
                         label="选择药品:"
                         label-width="100px"
                         required
@@ -501,7 +501,7 @@
                           />
                         </el-select>
                       </el-form-item>
-                      <el-form-item 
+                      <el-form-item
                         label="药品名称:"
                         label-width="100px"
                       >
@@ -512,11 +512,11 @@
                           style="width: 90%;margin-top: 1%;"
                         />
                       </el-form-item>
-                      <el-form-item 
+                      <el-form-item
                         label="药品封面:"
                         label-width="100px"
                       >
-                        <ImageUpload 
+                        <ImageUpload
                           :disabled="true"
                           v-model="content.medicinesImgUrl"
                           type="image"
@@ -535,7 +535,7 @@
                 <el-form-item label="内容" v-else-if="24 == content.contentType">
                   <div>
                     <el-card class="box-card">
-                      <el-form-item 
+                      <el-form-item
                         label="选择短视频:"
                         label-width="100px"
                         required
@@ -560,7 +560,7 @@
                           />
                         </el-select>
                       </el-form-item>
-                      <el-form-item 
+                      <el-form-item
                         label="短视频名称:"
                         label-width="100px"
                       >
@@ -571,11 +571,11 @@
                           style="width: 90%;margin-top: 1%;"
                         />
                       </el-form-item>
-                      <el-form-item 
+                      <el-form-item
                         label="短视频封面:"
                         label-width="100px"
                       >
-                        <ImageUpload 
+                        <ImageUpload
                           :disabled="true"
                           v-model="content.shortVideoImgUrl"
                           type="image"
@@ -594,7 +594,7 @@
                 <el-form-item label="内容" v-else-if="25 == content.contentType">
                   <div>
                     <el-card class="box-card">
-                      <el-form-item 
+                      <el-form-item
                         label="选择文章:"
                         label-width="100px"
                         required
@@ -619,7 +619,7 @@
                           />
                         </el-select>
                       </el-form-item>
-                      <el-form-item 
+                      <el-form-item
                         label="文章名称:"
                         label-width="100px"
                       >
@@ -630,11 +630,11 @@
                           style="width: 90%;margin-top: 1%;"
                         />
                       </el-form-item>
-                      <el-form-item 
+                      <el-form-item
                         label="文章封面:"
                         label-width="100px"
                       >
-                        <ImageUpload 
+                        <ImageUpload
                           :disabled="true"
                           v-model="content.articleImgUrl"
                           type="image"
@@ -653,7 +653,7 @@
                 <el-form-item label="内容" v-else-if="26 == content.contentType">
                   <div>
                     <el-card class="box-card">
-                      <el-form-item 
+                      <el-form-item
                         label="选择公开课:"
                         label-width="100px"
                         required
@@ -678,7 +678,7 @@
                           />
                         </el-select>
                       </el-form-item>
-                      <el-form-item 
+                      <el-form-item
                         label="公开课名称:"
                         label-width="100px"
                       >
@@ -689,11 +689,11 @@
                           style="width: 90%;margin-top: 1%;"
                         />
                       </el-form-item>
-                      <el-form-item 
+                      <el-form-item
                         label="公开课封面:"
                         label-width="100px"
                       >
-                        <ImageUpload 
+                        <ImageUpload
                           :disabled="true"
                           v-model="content.openClassVideoImgUrl"
                           type="image"
@@ -712,7 +712,7 @@
                 <!-- <el-form-item label="内容" v-else-if="27 == content.contentType">
                   <div>
                     <el-card class="box-card">
-                      
+
                     </el-card>
                   </div>
                 </el-form-item> -->
@@ -721,7 +721,7 @@
                 <!-- <el-form-item label="内容" v-else-if="28 == content.contentType">
                   <div>
                     <el-card class="box-card">
-                      
+
                     </el-card>
                   </div>
                 </el-form-item> -->
@@ -729,12 +729,12 @@
               </el-form>
             </el-col>
 
-            <el-col 
+            <el-col
               :span="1"
               :offset="1"
             >
               <!-- 删除内容节点 -->
-              <i 
+              <i
                 class="el-icon-delete"
                 @click="delContentNode(contentIndex)"
                 style="margin-top: 20px;"
@@ -768,7 +768,7 @@
       <el-button @click="cancelGroupSendMessage">取 消</el-button>
     </div>
 
-    <el-dialog 
+    <el-dialog
       title="查看分割后内容"
       :visible.sync="openShowContent"
       width="800px"
@@ -797,7 +797,7 @@
       </el-table>
 
       <div slot="footer" class="dialog-footer" style="text-align: right;">
-        <el-button 
+        <el-button
           type="primary"
           @click="comfirmContent"
         >确定</el-button>
@@ -812,7 +812,7 @@ import ImageUpload from "@/views/qw/sop/ImageUpload.vue";
 import {courseList, videoList} from "@/api/app/course";
 import { getPackageOptions,} from "@/api/app/pkg";
 import { groupSendMessage, } from '@/api/app/userLogs'
-import { getLiveOptions,} from "@/api/app/live";
+// import { getLiveOptions,} from "@/api/app/live";
 import { getMedicinesOptions, } from "@/api/app/medicines";
 import { getProductOptions, } from "@/api/app/product";
 import { getShortVideoOptions, } from "@/api/app/shortVideo";
@@ -921,7 +921,7 @@ export default {
         //打开新建
         if (n) {
           this.addContent();
-        } 
+        }
         //关闭销毁
         else {
           this.resetForm();
@@ -945,8 +945,8 @@ export default {
     },
     /**
      * 根据科普获取视频小节
-     * @param courseId 
-     * @param title 
+     * @param courseId
+     * @param title
      */
     async getVideoList(courseId, title) {
       return await videoList({
@@ -965,55 +965,55 @@ export default {
       };
       return await getPackageOptions(data);
     },
-    /**
-     * 获取直播间信息
-     */
-    async getLiveList() {
-      return await getLiveOptions();
-    },
-    /**
-     * 获取民品列表
-     * @param keyword 
-     * @param selectedId 
-     */
-    async getProductList(keyword, selectedId) {
-      let data = {
-        keyword: keyword,
-        metaId: selectedId,
-        limit: 50
-      };
-      return await getProductOptions(data);
-    },
-    /**
-     * 获取药品列表
-     * @param keyword 
-     * @param selectedId 
-     */
-    async getMedicinesList(keyword, selectedId) {
-      let data = {
-        keyword: keyword,
-        metaId: selectedId,
-        limit: 50
-      };
-      return await getMedicinesOptions(data);
-    },
-    /**
-     * 获取短视频列表
-     * @param keyword 
-     * @param selectedId 
-     */
-    async getShortVideoList(keyword, selectedId) {
-      let data = {
-        keyword: keyword,
-        metaId: selectedId,
-        limit: 50
-      };
-      return await getShortVideoOptions(data);
-    },
+    // /**
+    //  * 获取直播间信息
+    //  */
+    // async getLiveList() {
+    //   return await getLiveOptions();
+    // },
+    // /**
+    //  * 获取民品列表
+    //  * @param keyword
+    //  * @param selectedId
+    //  */
+    // async getProductList(keyword, selectedId) {
+    //   let data = {
+    //     keyword: keyword,
+    //     metaId: selectedId,
+    //     limit: 50
+    //   };
+    //   return await getProductOptions(data);
+    // },
+    // /**
+    //  * 获取药品列表
+    //  * @param keyword
+    //  * @param selectedId
+    //  */
+    // async getMedicinesList(keyword, selectedId) {
+    //   let data = {
+    //     keyword: keyword,
+    //     metaId: selectedId,
+    //     limit: 50
+    //   };
+    //   return await getMedicinesOptions(data);
+    // },
+    // /**
+    //  * 获取短视频列表
+    //  * @param keyword
+    //  * @param selectedId
+    //  */
+    // async getShortVideoList(keyword, selectedId) {
+    //   let data = {
+    //     keyword: keyword,
+    //     metaId: selectedId,
+    //     limit: 50
+    //   };
+    //   return await getShortVideoOptions(data);
+    // },
     /**
      * 获取文章列表
-     * @param keyword 
-     * @param selectedId 
+     * @param keyword
+     * @param selectedId
      */
     async getArticleList(keyword, selectedId) {
       let data = {
@@ -1025,8 +1025,8 @@ export default {
     },
     /**
      * 获取公开课列表
-     * @param keyword 
-     * @param selectedId 
+     * @param keyword
+     * @param selectedId
      */
     async getOpenClassVideoList(keyword, selectedId) {
       let data = {
@@ -1038,9 +1038,9 @@ export default {
     },
     /**
      * 科普变动处理
-     * @param ruleItem 
-     * @param dayIndex 
-     * @param ruleIndex 
+     * @param ruleItem
+     * @param dayIndex
+     * @param ruleIndex
      */
     async courseChangeUpdate() {
       //将当前规则已选中的视频小节清空
@@ -1083,8 +1083,8 @@ export default {
     },
     /**
      * 疗法下拉搜索
-     * @param keyword 
-     * @param content 
+     * @param keyword
+     * @param content
      */
     async handlePkgRemoteSearch(keyword, content) {
       content.meta.pkgLoading = true;
@@ -1094,7 +1094,7 @@ export default {
     },
     /**
      * 疗法变动处理
-     * @param content 
+     * @param content
      */
     async pkgChangeUpdate(content) {
       //将当前规则已选中的视频小节清空
@@ -1109,8 +1109,8 @@ export default {
     },
     /**
      * 民品下拉搜索
-     * @param keyword 
-     * @param content 
+     * @param keyword
+     * @param content
      */
     async handleProductRemoteSearch(keyword, content) {
       content.meta.productLoading = true;
@@ -1120,7 +1120,7 @@ export default {
     },
     /**
      * 民品变动处理
-     * @param content 
+     * @param content
      */
     async productChangeUpdate(content) {
       this.$set(content, 'productName', null);
@@ -1134,8 +1134,8 @@ export default {
     },
     /**
      * 药品下拉搜索
-     * @param keyword 
-     * @param content 
+     * @param keyword
+     * @param content
      */
     async handleMedicinesRemoteSearch(keyword, content) {
       content.meta.medicinesLoading = true;
@@ -1145,7 +1145,7 @@ export default {
     },
     /**
      * 药品变动处理
-     * @param content 
+     * @param content
      */
     async medicinesChangeUpdate(content) {
       this.$set(content, 'medicinesName', null);
@@ -1159,8 +1159,8 @@ export default {
     },
     /**
      * 短视频下拉搜索
-     * @param keyword 
-     * @param content 
+     * @param keyword
+     * @param content
      */
     async handleShortVideoRemoteSearch(keyword, content) {
       content.meta.shortVideoLoading = true;
@@ -1170,7 +1170,7 @@ export default {
     },
     /**
      * 短视频变动处理
-     * @param content 
+     * @param content
      */
     async shortVideoChangeUpdate(content) {
       this.$set(content, 'shortVideoName', null);
@@ -1184,8 +1184,8 @@ export default {
     },
     /**
      * 文章下拉搜索
-     * @param keyword 
-     * @param content 
+     * @param keyword
+     * @param content
      */
     async handleArticleRemoteSearch(keyword, content) {
       content.meta.articleLoading = true;
@@ -1195,7 +1195,7 @@ export default {
     },
     /**
      * 文章变动处理
-     * @param content 
+     * @param content
      */
     async articleChangeUpdate(content) {
       this.$set(content, 'articleName', null);
@@ -1209,8 +1209,8 @@ export default {
     },
     /**
      * 公开课下拉搜索
-     * @param keyword 
-     * @param content 
+     * @param keyword
+     * @param content
      */
     async handleOpenClassVideoRemoteSearch(keyword, content) {
       content.meta.openClassVideoLoading = true;
@@ -1220,7 +1220,7 @@ export default {
     },
     /**
      * 公开课变动处理
-     * @param content 
+     * @param content
      */
     async openClassVideoChangeUpdate(content) {
       this.$set(content, 'openClassVideoName', null);
@@ -1234,7 +1234,7 @@ export default {
     },
     /**
      * 直播间切换
-     * @param content 
+     * @param content
      */
     liveChange(content) {
       content.liveTitle = null;
@@ -1247,9 +1247,9 @@ export default {
     },
     /**
      * 科普小节变化
-     * @param ruleItem 
-     * @param dayIndex 
-     * @param ruleIndex 
+     * @param ruleItem
+     * @param dayIndex
+     * @param ruleIndex
      */
     videoIdChange() {
       //选择了科普小节则 默认绑上
@@ -1275,9 +1275,9 @@ export default {
     },
     /**
      * 上传视频成功处理
-     * @param res 
-     * @param file 
-     * @param item 
+     * @param res
+     * @param file
+     * @param item
      */
     handleSuccessVideo(res, file, item) {
       if(res.code == 200) {
@@ -1290,7 +1290,7 @@ export default {
     },
     /**
      * 上传视频前置处理
-     * @param file 
+     * @param file
      */
     beforeUploadVideo(file){
       const isLt30M = file.size / 1024 / 1024 < 10;
@@ -1307,8 +1307,8 @@ export default {
     },
     /**
      * 语音文本录入
-     * @param value 
-     * @param content 
+     * @param value
+     * @param content
      */
     handleInputVoiceText(value,content){
       // 允许的字符:中文、英文(大小写)、数字和指定标点符号(,。!?)
@@ -1319,7 +1319,7 @@ export default {
     },
     /**
      * 删除内容节点
-     * @param index 
+     * @param index
      */
     delContentNode(index){
       this.groupSendMessageForm.setting.splice(index, 1)
@@ -1336,9 +1336,9 @@ export default {
       this.handleContentTypeChange();
     },
     /**
-     * 
-     * @param event 
-     * @param index 
+     *
+     * @param event
+     * @param index
      */
     handleKeydown(event, index) {
       const item = this.groupSendMessageForm.setting[index];
@@ -1419,7 +1419,7 @@ export default {
     },
     /**
      * 切换添加客服称呼按钮点击事件
-     * @param index 
+     * @param index
      */
     toggleSalesCall(index) {
       const item = this.groupSendMessageForm.setting[index];
@@ -1557,11 +1557,11 @@ export default {
         }
         //舌诊
         else if(item.contentType == 27) {
-          
+
         }
         //健康周报
         else if(item.contentType == 28) {
-          
+
         }
       })
     },
@@ -1631,7 +1631,7 @@ export default {
     },
     /**
      * 空校验
-     * @param obj 
+     * @param obj
      */
     isEmpty(obj) {
       return obj === null || obj === undefined || obj.length === 0;
@@ -1684,7 +1684,7 @@ export default {
     },
     /**
      * 显示分割后的内容
-     * @param contentIndex 
+     * @param contentIndex
      */
     showOpenContent(contentIndex) {
       let setItem = this.groupSendMessageForm.setting[contentIndex];
@@ -1728,4 +1728,4 @@ export default {
     padding: 5px 16px;
   }
 }
-</style>
+</style>

+ 108 - 108
src/views/app/welcome/index.vue

@@ -171,9 +171,9 @@
                             placement="top-start">
                             <el-dropdown-menu slot="dropdown" style="width: 120px;">
                                 <!-- 和模板那边的消息类型一致,文本在上面输入框输入,故此不显示在此处 -->
-                                <el-dropdown-item 
-                                    v-for="ct in contentTypeOptions" 
-                                    :key="ct.dictValue" 
+                                <el-dropdown-item
+                                    v-for="ct in contentTypeOptions"
+                                    :key="ct.dictValue"
                                     :command="ct.dictValue"
                                     v-show="ct.dictValue != 11"
                                 >
@@ -198,20 +198,20 @@
 
         <!-- 列表搜索条件:选择app客服角色 -->
         <el-dialog title="选择客服" :visible.sync="appCustomerSearchConfig.visible" width="1000px" append-to-body :close-on-click-modal="false">
-            <CusRoleList 
+            <CusRoleList
                 ref="customerSearchRef"
                 @confirm="customerSelectedConfirmCallForSearch"
-                @selectionChange="customerSelectionChangeCallForSearch" 
+                @selectionChange="customerSelectionChangeCallForSearch"
                 :selected="appCustomerSearchConfig.selected"
             />
         </el-dialog>
 
         <!-- 新增编辑:选择app客服角色 -->
         <el-dialog title="选择客服" :visible.sync="appCustomerBindConfig.visible" width="1000px" append-to-body :close-on-click-modal="false">
-            <CusRoleList 
+            <CusRoleList
                 ref="customerBindRef"
                 @confirm="customerSelectedConfirmCallForBind"
-                @selectionChange="customerSelectionChangeCallForBind" 
+                @selectionChange="customerSelectionChangeCallForBind"
                 :selected="appCustomerBindConfig.selected"
             />
         </el-dialog>
@@ -223,7 +223,7 @@
             <el-form  v-if="welcomeItem.contentType == '9'" ref="courseForm" :model="courseForm" :rules="courseFormRule" label-width="110px">
                 <div>
                     <el-form-item label="选择科普" prop="videoId">
-                        <el-select 
+                        <el-select
                             v-model="courseForm.courseId"
                             placeholder="默认50条,可输入关键字检索"
                             style="margin-right: 10px;"
@@ -309,7 +309,7 @@
             <!-- 疗法: welcomeItem.contentType == '20' -->
             <el-form v-else-if="welcomeItem.contentType == '20'" ref="pkgForm" :model="pkgForm" :rules="pkgFormRule" label-width="110px">
                 <div>
-                    <el-form-item 
+                    <el-form-item
                         label="选择疗法:"
                         label-width="100px"
                         required
@@ -334,7 +334,7 @@
                         />
                         </el-select>
                     </el-form-item>
-                    <el-form-item 
+                    <el-form-item
                         label="疗法名称:"
                         label-width="100px"
                     >
@@ -345,11 +345,11 @@
                             style="width: 90%;margin-top: 1%;"
                         />
                     </el-form-item>
-                    <el-form-item 
+                    <el-form-item
                         label="疗法封面:"
                         label-width="100px"
                     >
-                        <ImageUpload 
+                        <ImageUpload
                             :disabled="true"
                             v-model="pkgForm.packageImgUrl"
                             type="image"
@@ -363,57 +363,57 @@
                 </div>
             </el-form>
             <!-- 直播 -->
-            <el-form v-else-if="welcomeItem.contentType == '21'" ref="liveForm" :model="liveForm" :rules="liveFormRule" label-width="110px">
-                <div>
-                    <el-card class="box-card">
-                        <el-form-item label="直播间"
-                            required
-                            style="margin-bottom: 5px;"
-                        >
-                            <el-select
-                                v-model="liveForm.liveId"
-                                placeholder="请选择直播间"
-                                size="mini"
-                                filterable
-                                @change="liveChange()"
-                            >
-                            <el-option
-                                v-for="dict in liveList"
-                                :key="dict.liveId"
-                                :label="dict.liveName"
-                                :value="parseInt(dict.liveId)"
-                            />
-                            </el-select>
-                        </el-form-item>
-                        <el-form-item label="标题"
-                            prop="liveTitle"
-                            style="margin-bottom: 5px;"
-                        >
-                            <el-input
-                                v-model="liveForm.liveTitle"
-                                placeholder="请输入消息标题,最长为64字节"
-                                :rows="2"
-                                maxlength="64"
-                                type="textarea"
-                                disabled
-                                @input="checkByteLength(liveForm, 'liveTitle')"
-                            />
-                        </el-form-item>
-                        <el-form-item label="封面"
-                            prop="liveImgUrl"
-                        >
-                            <ImageUpload
-                                v-model="liveForm.liveImgUrl"
-                                type="image"
-                                :num="10"
-                                :width="150"
-                                :height="150"
-                                disabled
-                            />
-                        </el-form-item>
-                    </el-card>
-                </div>
-            </el-form>
+<!--            <el-form v-else-if="welcomeItem.contentType == '21'" ref="liveForm" :model="liveForm" :rules="liveFormRule" label-width="110px">-->
+<!--                <div>-->
+<!--                    <el-card class="box-card">-->
+<!--                        <el-form-item label="直播间"-->
+<!--                            required-->
+<!--                            style="margin-bottom: 5px;"-->
+<!--                        >-->
+<!--                            <el-select-->
+<!--                                v-model="liveForm.liveId"-->
+<!--                                placeholder="请选择直播间"-->
+<!--                                size="mini"-->
+<!--                                filterable-->
+<!--                                @change="liveChange()"-->
+<!--                            >-->
+<!--                            <el-option-->
+<!--                                v-for="dict in liveList"-->
+<!--                                :key="dict.liveId"-->
+<!--                                :label="dict.liveName"-->
+<!--                                :value="parseInt(dict.liveId)"-->
+<!--                            />-->
+<!--                            </el-select>-->
+<!--                        </el-form-item>-->
+<!--                        <el-form-item label="标题"-->
+<!--                            prop="liveTitle"-->
+<!--                            style="margin-bottom: 5px;"-->
+<!--                        >-->
+<!--                            <el-input-->
+<!--                                v-model="liveForm.liveTitle"-->
+<!--                                placeholder="请输入消息标题,最长为64字节"-->
+<!--                                :rows="2"-->
+<!--                                maxlength="64"-->
+<!--                                type="textarea"-->
+<!--                                disabled-->
+<!--                                @input="checkByteLength(liveForm, 'liveTitle')"-->
+<!--                            />-->
+<!--                        </el-form-item>-->
+<!--                        <el-form-item label="封面"-->
+<!--                            prop="liveImgUrl"-->
+<!--                        >-->
+<!--                            <ImageUpload-->
+<!--                                v-model="liveForm.liveImgUrl"-->
+<!--                                type="image"-->
+<!--                                :num="10"-->
+<!--                                :width="150"-->
+<!--                                :height="150"-->
+<!--                                disabled-->
+<!--                            />-->
+<!--                        </el-form-item>-->
+<!--                    </el-card>-->
+<!--                </div>-->
+<!--            </el-form>-->
             <div slot="footer" class="dialog-footer" style="text-align: center">
                 <el-button type="primary" @click="confirmUpload">确定</el-button>
                 <el-button @click="cancelUpload">取消</el-button>
@@ -429,7 +429,7 @@ import ImageUpload from "@/views/qw/sop/ImageUpload";
 import CusRoleList from '@/views/app/user/CusRoleList.vue';
 import {courseList, videoList} from "@/api/app/course";
 import { getPackageOptions,} from "@/api/app/pkg";
-import { getLiveOptions,} from "@/api/app/live";
+// import { getLiveOptions,} from "@/api/app/live";
 
 export default {
     name: "AppWelcome",
@@ -527,8 +527,8 @@ export default {
         this.getList();
         let defaultPkg = await this.getPkgList(null, null);
         this.pkgList = defaultPkg.data;
-        let defaultLive = await this.getLiveList();
-        this.liveList = defaultLive.data;
+        // let defaultLive = await this.getLiveList();
+        // this.liveList = defaultLive.data;
     },
     methods: {
         /**
@@ -557,12 +557,12 @@ export default {
         /**
          * 获取直播间信息
          */
-        async getLiveList() {
-            return await getLiveOptions();
-        },
+        // async getLiveList() {
+        //     return await getLiveOptions();
+        // },
         /**
          * 疗法下拉搜索
-         * @param keyword 
+         * @param keyword
          */
         async handlePkgRemoteSearch(keyword) {
             this.pkgForm.pkgLoading = true;
@@ -584,18 +584,18 @@ export default {
                 this.pkgForm.packageImgUrl = selectedPkg.imgUrl;
             }
         },
-        /**
-         * 直播间切换
-         */
-        liveChange() {
-            this.liveForm.liveTitle = null;
-            this.liveForm.liveImgUrl = null;
-            const selectedLive = this.liveList.find(live => live.liveId === this.liveForm.liveId);
-            if (selectedLive) {
-                this.liveForm.liveTitle = selectedLive.liveName; // 自动填充标题
-                this.liveForm.liveImgUrl = selectedLive.liveImgUrl; // 自动填充封面
-            }
-        },
+        // /**
+        //  * 直播间切换
+        //  */
+        // liveChange() {
+        //     this.liveForm.liveTitle = null;
+        //     this.liveForm.liveImgUrl = null;
+        //     const selectedLive = this.liveList.find(live => live.liveId === this.liveForm.liveId);
+        //     if (selectedLive) {
+        //         this.liveForm.liveTitle = selectedLive.liveName; // 自动填充标题
+        //         this.liveForm.liveImgUrl = selectedLive.liveImgUrl; // 自动填充封面
+        //     }
+        // },
         /**
          * 搜索条件:客服选中确认回调
          */
@@ -610,7 +610,7 @@ export default {
         },
         /**
          * 搜索条件:客服选中变更回调
-         * @param config 
+         * @param config
          */
         customerSelectionChangeCallForSearch(config) {
             let selected = config.selected;
@@ -647,7 +647,7 @@ export default {
         },
         /**
          * 新增/编辑:客服选中变更回调
-         * @param config 
+         * @param config
          */
         customerSelectionChangeCallForBind(config) {
             let selected = config.selected;
@@ -695,8 +695,8 @@ export default {
         },
         /**
          * 删除客服
-         * @param cus 
-         * @param mode 
+         * @param cus
+         * @param mode
          */
         handleCloseCustomer(cus, mode) {
             if (mode == 0) {
@@ -715,8 +715,8 @@ export default {
         },
         /**
          * 检查长度
-         * @param formInfo 
-         * @param key 
+         * @param formInfo
+         * @param key
          */
         checkByteLength(formInfo, key) {
             const text = formInfo[key];
@@ -727,15 +727,15 @@ export default {
         },
         /**
          * 获取字节长度
-         * @param text 
+         * @param text
          */
         getByteLength(text) {
             return new Blob([text]).size;
         },
         /**
          * 截断字节长度
-         * @param text 
-         * @param maxByteLength 
+         * @param text
+         * @param maxByteLength
          */
         truncateTextByByteLength(text, maxByteLength) {
             let byteLength = 0;
@@ -754,7 +754,7 @@ export default {
         },
         /**
          * 点击具体的欢迎语选项进行新增附件
-         * @param command 
+         * @param command
          */
         handleCommand(command) {
             if (this.form.attachments.length >= 9) {
@@ -769,14 +769,14 @@ export default {
         },
         /**
          * 根据消息类型编码获取消息类型名称
-         * @param command 
+         * @param command
          */
         getTitleByCommand(command) {
             let option = this.contentTypeOptions.find(cto => cto.dictValue == command);
             return option.dictLabel;
         },
         /**
-         * 
+         *
          */
         async handleCourseRemoteSearch(keyword, courseForm) {
             this.welcomeItem.courseLoading = true;
@@ -787,7 +787,7 @@ export default {
         },
         /**
          * 科普变化
-         * @param form 
+         * @param form
          */
         courseChange(form) {
             this.$set(form, 'videoId', null);
@@ -801,8 +801,8 @@ export default {
         },
         /**
          * 科普小节改变
-         * @param form 
-         * @param type 
+         * @param form
+         * @param type
          */
         videoIdChange(form, type) {
             if (form.videoId != null) {
@@ -816,7 +816,7 @@ export default {
         },
         /**
          * 编辑附件信息
-         * @param item 
+         * @param item
          */
         async editFileItem(item, index) {
             this.welcomeItem = {
@@ -828,7 +828,7 @@ export default {
             //图片
              if (item.contentType == '2') {
                 this.imageForm = JSON.parse(JSON.stringify(item.image));//深拷贝
-            } 
+            }
             // 科普
             else if (item.contentType == '9') {
                 this.courseForm = JSON.parse(JSON.stringify(item.course));//深拷贝
@@ -843,7 +843,7 @@ export default {
         },
         /**
          * 移除欢迎语附件
-         * @param index 
+         * @param index
          */
         removeFileItem(index) {
             this.form.attachments.splice(index, 1);
@@ -900,14 +900,14 @@ export default {
         },
         /**
          * 添加附件
-         * @param index 
-         * @param attachment 
+         * @param index
+         * @param attachment
          */
         addFile(index, attachment) {
             //编辑模式:执行替换
             if (index > -1) {
                 this.form.attachments.splice(index, 1, attachment);
-            } 
+            }
             //新增模式:直接追加
             else {
                 this.form.attachments.push(attachment);
@@ -951,7 +951,7 @@ export default {
         },
         /**
          * 切换发送状态
-         * @param val 
+         * @param val
          */
         async toggleSendStatus(val, row) {
             console.log(row)
@@ -964,7 +964,7 @@ export default {
                 await setSendStatus({id: row.id, sendStatus: val});
                 this.msgSuccess(`${activeName}成功!`);
                 this.getList();
-            }).catch(() => { 
+            }).catch(() => {
                 this.getList();
             });
         },
@@ -1008,7 +1008,7 @@ export default {
         },
         /**
          * 编辑欢迎语
-         * @param row 
+         * @param row
          */
         async handleUpdate(row) {
             this.reset();
@@ -1051,7 +1051,7 @@ export default {
         },
         /**
          * 删除
-         * @param row 
+         * @param row
          */
         handleDelete(row) {
             const ids = row.id || this.ids;
@@ -1076,4 +1076,4 @@ export default {
     overflow-y: auto;
     line-height: 1.5em;
 }
-</style>
+</style>

+ 466 - 0
src/views/course/courseWatchLog/indexApp.vue

@@ -0,0 +1,466 @@
+<template>
+  <div class="app-container">
+    <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="100px">
+      <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="会员昵称" prop="nickName">
+        <el-input
+          v-model="queryParams.nickName"
+          placeholder="请输入会员昵称"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="所属客服" prop="appCustomerId">
+        <el-select v-model="queryParams.appCustomerId" clearable filterable remote
+                   placeholder="请输入关键词" :remote-method="loadCompanyUserOptions"
+                   v-select-load-more="loadMoreCompanyUserOptions"
+                   :loading="companyUserOptionsLoading">
+          <el-option
+            v-for="item in companyUserOptions"
+            :key="item.value"
+            :label="item.label"
+            :value="item.value">
+          </el-option>
+        </el-select>
+      </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.remark"
+            :value="dict.dictValue"
+          >
+          <!-- <el-tooltip
+        v-if="dict.remark"
+        :content="dict.remark"
+        placement="right"
+        effect="dark"
+        :disabled="!dict.remark"
+      >
+        <span>{{ dict.dictLabel }}</span>
+      </el-tooltip>
+      <span v-else>{{ dict.dictLabel }}</span> -->
+        </el-option>
+        </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>
+      </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="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-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-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-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="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>
+    </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-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="remarkName"/>
+      <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">
+            </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" prop="logType">
+        <template slot-scope="scope">
+          <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="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>
+
+    <pagination
+      v-show="total>0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    />
+
+  </div>
+</template>
+
+<script>
+import { listAppCourseWatchLog, exportAppCourseWatchLog,getCustomerListLikeName } from "@/api/course/courseWatchLog";
+import { courseList,videoList } from '../../../api/course/courseRedPacketLog'
+import {getTask} from "@/api/common";
+export default {
+  name: "CourseWatchLog",
+  data() {
+    return {
+      activeName:"00",
+      createTime:null,
+      updateTime:null,
+      courseLists:[],
+      videoList:[],
+      logTypeOptions:[],
+      // 遮罩层
+      loading: true,
+      // 导出遮罩层
+      exportLoading: false,
+      // 选中数组
+      ids: [],
+      // 非单个禁用
+      single: true,
+      // 非多个禁用
+      multiple: true,
+      // 显示搜索条件
+      showSearch: true,
+      // 总条数
+      total: 0,
+      // 短链科普学习记录表格数据
+      courseWatchLogList: [],
+      // 弹出层标题
+      title: "",
+      // 是否显示弹出层
+      open: false,
+      isVipList: [
+        { dictLabel: '是', dictValue: 1 },
+        { dictLabel: '否', dictValue: 0 }
+      ],
+      watchTypeList: [
+        { dictLabel: 'app', dictValue: 1 },
+        { dictLabel: '小程序', dictValue: 2 }
+      ],
+      // 查询参数
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        userId: null,
+        nickName: null,
+        videoId: null,
+        logType: null,
+        qwExternalContactId: null,
+        externalUserName:null,
+        duration: null,
+        qwUserId: null,
+        qwUserName: null, //企微名称
+        qwUserUserId: null, //企微id
+        deptName: null, //部门名称
+        companyUserId: null,
+        companyId: null,
+        courseId: null,
+        sTime:null,
+        eTime:null,
+        upSTime:null,
+        upETime:null,
+        scheduleStartTime: null,
+        scheduleEndTime: null,
+        isVip: null,
+        watchType:null,
+      },
+      // 表单参数
+      form: {},
+      // 表单校验
+      rules: {
+      },
+      scheduleTime: null,
+      // 员工选项列表
+      companyUserOptionsParams: {
+        name: undefined,
+        hasNextPage: false,
+        pageNum: 1,
+        pageSize: 10
+      },
+      companyUserOptionsLoading: false,
+      companyUserOptions: [],
+    };
+  },
+  created() {
+    courseList().then(response => {
+      this.courseLists = response.list;
+    });
+    this.getList();
+    this.getDicts("sys_course_watch_log_type").then(response => {
+      this.logTypeOptions = response.data;
+    });
+  },
+  methods: {
+    courseChange(row){
+      this.queryParams.videoId=null;
+      if(row === ''){
+        this.videoList=[];
+        return
+      }
+      videoList(row).then(response => {
+        this.videoList=response.list
+      });
+    },
+    createChange() {
+      if (this.createTime != null) {
+        this.queryParams.sTime = this.createTime[0];
+        this.queryParams.eTime = this.createTime[1];
+      } else {
+        this.queryParams.sTime = null;
+        this.queryParams.eTime = null;
+      }
+    },
+
+    updateChange(){
+      if (this.updateTime != null) {
+        this.queryParams.upSTime = this.updateTime[0];
+        this.queryParams.upETime = this.updateTime[1];
+      } else {
+        this.queryParams.upSTime = null;
+        this.queryParams.upETime = null;
+      }
+    },
+    handleClickX(tab,event){
+      this.activeName=tab.name;
+      if(tab.name=="00"){
+        this.queryParams.logType=null;
+      }else{
+        this.queryParams.logType=tab.name;
+      }
+      this.getList()
+    },
+    /** 查询短链科普学习记录列表 */
+    getList() {
+      this.loading = true;
+      if(this.queryParams.logType == "10"){
+        this.queryParams.logType = null;
+      }
+
+      listAppCourseWatchLog(this.queryParams).then(response => {
+        this.courseWatchLogList = response.rows;
+        this.total = response.total;
+        this.loading = false;
+      });
+    },
+    // 取消按钮
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 表单重置
+    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");
+    },
+    /** 搜索按钮操作 */
+    handleQuery() {
+      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();
+    },
+    // 多选框选中数据
+    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 = "添加短链科普学习记录";
+    },
+   
+    /** 提交按钮 */
+    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();
+            });
+          }
+        }
+      });
+    },
+    
+    /** 导出按钮操作 */
+    handleExport() {
+      const that = this
+      const queryParams = this.queryParams;
+      this.$confirm('是否确认导出所有短链科普学习记录数据项?', "警告", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        }).then(() => {
+          this.exportLoading = true;
+          return exportAppCourseWatchLog(queryParams);
+        }).then(response => {
+          this.download(response.msg);
+          this.exportLoading = false;
+        }).catch(() => {});
+    },
+    handleScheduleTimeChange(val) {
+      if (val) {
+        this.queryParams.scheduleStartTime = val[0];
+        this.queryParams.scheduleEndTime = val[1];
+      } else {
+        this.queryParams.scheduleStartTime = null;
+        this.queryParams.scheduleEndTime = null;
+      }
+    },
+    /**
+     * 根据名称模糊查询用户列表
+     * @param query 参数
+     */
+    loadCompanyUserOptions(query) {
+      this.companyUserOptions = [];
+      if (query === '') {
+        return;
+      }
+
+      this.companyUserOptionsParams.pageNum = 1
+      this.companyUserOptionsParams.name = query
+      this.companyUserOptionsLoading = true;
+      this.getCompanyUserListLikeName()
+    },
+    /**
+     * 获取员工列表
+     */
+    getCompanyUserListLikeName() {
+      getCustomerListLikeName(this.companyUserOptionsParams).then(response => {
+        this.companyUserOptions = [...this.companyUserOptions, ...response.data.list]
+        this.companyUserOptionsParams.hasNextPage = response.data.hasNextPage
+        this.companyUserOptionsLoading = false;
+      });
+    },
+    /**
+     * 加载更多员工选项
+     */
+    loadMoreCompanyUserOptions() {
+      if (!this.companyUserOptionsParams.hasNextPage) {
+        return;
+      }
+
+      this.companyUserOptionsParams.pageNum += 1
+      this.getCompanyUserListLikeName()
+    },
+  }
+};
+</script>

Některé soubory nejsou zobrazeny, neboť je v těchto rozdílových datech změněno mnoho souborů