吴树波 4 hete
szülő
commit
1a35559018
69 módosított fájl, 6462 hozzáadás és 3127 törlés
  1. 0 9
      src/api/company/companyUser.js
  2. 0 9
      src/api/course/courseAnswerlogs.js
  3. 0 9
      src/api/course/courseRedPacketLog.js
  4. 0 8
      src/api/course/courseWatchLog.js
  5. 54 0
      src/api/course/userCourseCamp.js
  6. 176 0
      src/api/course/userCoursePeriod.js
  7. 0 9
      src/api/doctor/doctor.js
  8. 2 28
      src/api/qw/QwWorkTask.js
  9. 7 0
      src/api/qw/groupChat.js
  10. 7 0
      src/api/qw/sop.js
  11. 0 10
      src/api/qw/sopLogs.js
  12. 25 8
      src/api/qw/sopTemp.js
  13. 0 13
      src/api/qw/user.js
  14. 0 18
      src/api/store/package.js
  15. 1 19
      src/api/store/patient.js
  16. 2 2
      src/api/watch/deviceInfo.js
  17. BIN
      src/assets/image/profile.jpg
  18. BIN
      src/assets/logo/crm.png
  19. BIN
      src/assets/logo/logo.png
  20. 1 1
      src/components/PaginationMore/index.vue
  21. 0 13
      src/router/index.js
  22. 4 2
      src/store/modules/user.js
  23. 97 111
      src/views/company/companyUser/index.vue
  24. 426 0
      src/views/course/Material/index.vue
  25. 2 10
      src/views/course/courseAnswerlogs/myCourseAnswerlogs.vue
  26. 32 147
      src/views/course/courseFinishTemp/index.vue
  27. 2 12
      src/views/course/courseRedPacketLog/myCourseRedPacketLog.vue
  28. 178 236
      src/views/course/courseWatchLog/index.vue
  29. 4 12
      src/views/course/courseWatchLog/myCourseWatchLog.vue
  30. 4 4
      src/views/course/courseWatchLog/watchLog.vue
  31. 1 1
      src/views/course/sop/SopDialog.vue
  32. 1 1
      src/views/course/sop/index.vue
  33. 126 0
      src/views/course/userCoursePeriod/batchRedPacket.vue
  34. 1495 0
      src/views/course/userCoursePeriod/index.vue
  35. 173 0
      src/views/course/userCoursePeriod/redPacket.vue
  36. 338 0
      src/views/course/userCoursePeriod/statistics.vue
  37. 2 2
      src/views/fastGpt/fastGptRole/fastGptRoleUpdate.vue
  38. 1 0
      src/views/login.vue
  39. 188 186
      src/views/qw/QwWorkTask/index.vue
  40. 73 35
      src/views/qw/autoTags/dayPartingIndex.vue
  41. 9 9
      src/views/qw/autoTags/dayPartingIndexDetails.vue
  42. 60 36
      src/views/qw/autoTags/groupIndex.vue
  43. 0 1
      src/views/qw/autoTags/groupIndexDetails.vue
  44. 288 117
      src/views/qw/externalContact/index.vue
  45. 256 29
      src/views/qw/externalContact/myExternalContact.vue
  46. 1 1
      src/views/qw/friendWelcome/index.vue
  47. 4 4
      src/views/qw/friendWelcome/indexNew.vue
  48. 1 1
      src/views/qw/groupMsgUser/groupMsg.vue
  49. 8 0
      src/views/qw/sop/ImageUpload.vue
  50. 1 1
      src/views/qw/sop/addAiChatSop.vue
  51. 372 248
      src/views/qw/sop/addSop.vue
  52. 347 357
      src/views/qw/sop/sop.vue
  53. 1 1
      src/views/qw/sop/updateSop.vue
  54. 14 11
      src/views/qw/sopLogs/sopLogsList.vue
  55. 264 227
      src/views/qw/sopTemp/index.vue
  56. 11 5
      src/views/qw/sopTemp/sopTemp.vue
  57. 446 332
      src/views/qw/sopTemp/updateSopTemp.vue
  58. 5 0
      src/views/qw/sopUserLogs/sopUserLogsSchedule.vue
  59. 745 0
      src/views/qw/sopUserLogsInfo/sendMsgOpenTool.vue
  60. 82 239
      src/views/qw/sopUserLogsInfo/sopUserLogsInfoDetails.vue
  61. 8 7
      src/views/qw/tagGroup/tagGroupList.vue
  62. 11 11
      src/views/qw/user/index.vue
  63. 2 2
      src/views/qw/user/qwUserSelectOne.vue
  64. 33 122
      src/views/store/inquiryOrder/list.vue
  65. 18 119
      src/views/store/packageOrder/list.vue
  66. 13 78
      src/views/store/prescribe/list.vue
  67. 29 128
      src/views/store/storeOrder/list.vue
  68. 2 4
      src/views/watch/deviceInfo/details.vue
  69. 9 122
      src/views/watch/deviceInfo/index.vue

+ 0 - 9
src/api/company/companyUser.js

@@ -215,12 +215,3 @@ export function updateCompanyUserAreaList(data) {
     data: data
   })
 }
-
- // 根据名称模糊查询用户列表
- export function getCompanyUserListLikeName(params) {
-  return request({
-      url: '/company/user/getCompanyUserListLikeName',
-      method: 'get',
-      params: params
-  })
-}

+ 0 - 9
src/api/course/courseAnswerlogs.js

@@ -60,12 +60,3 @@ export function exportLogs(query) {
     params: query
   })
 }
-
-// 导出答题日志
-export function exportLogsMy(query) {
-  return request({
-    url: '/course/courseAnswerLog/myExport',
-    method: 'get',
-    params: query
-  })
-}

+ 0 - 9
src/api/course/courseRedPacketLog.js

@@ -77,12 +77,3 @@ export function exportCourseRedPacketLog(query) {
     params: query
   })
 }
-
-// 导出短链课程看课记录
-export function exportCourseRedPacketLogMy(query) {
-  return request({
-    url: '/course/courseRedPacketLog/myExport',
-    method: 'get',
-    params: query
-  })
-}

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

@@ -105,14 +105,6 @@ export function exportCourseWatchLog(query) {
   })
 }
 
-export function exportCourseWatchLogMy(query) {
-  return request({
-    url: '/course/courseWatchLog/myExport',
-    method: 'get',
-    params: query
-  })
-}
-
 export function watchLogStatisticsExport(query) {
   return request({
     url: '/course/courseWatchLog/watchLogStatisticsExport',

+ 54 - 0
src/api/course/userCourseCamp.js

@@ -0,0 +1,54 @@
+import request from '@/utils/request'
+
+// 训练营列表
+export function listCamp(query) {
+  return request({
+    url: '/course/trainingCamp/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 新增训练营
+export function addCamp(data) {
+  return request({
+    url: '/course/trainingCamp',
+    method: 'post',
+    data: data
+  })
+}
+
+// 修改训练营
+export function editCamp(data) {
+  return request({
+    url: '/course/trainingCamp',
+    method: 'put',
+    data: data
+  })
+}
+
+// 删除训练营
+export function delCamp(trainingCampId) {
+  return request({
+    url: `/course/trainingCamp/${trainingCampId}`,
+    method: 'delete'
+  })
+}
+
+// 复制训练营
+export function copyCamp(trainingCampId) {
+  return request({
+    url: `/course/trainingCamp/copy/${trainingCampId}`,
+    method: 'post'
+  })
+}
+
+// 获取训练营选项列表
+export function getCampListLikeName(query) {
+  return request({
+    url: '/course/trainingCamp/getCampListLikeName',
+    method: 'get',
+    params: query
+  })
+}
+

+ 176 - 0
src/api/course/userCoursePeriod.js

@@ -0,0 +1,176 @@
+import request from '@/utils/request'
+
+// 查询会员营期列表
+export function listPeriod(query) {
+  return request({
+    url: '/course/period/list',
+    method: 'get',
+    params: query
+  })
+}
+// 查询会员营期列表
+export function getDays(query) {
+  return request({
+    url: '/course/period/getDays',
+    method: 'get',
+    params: query
+  })
+}
+
+// 自定义查询主列表分页
+export function pagePeriod(data) {
+  return request({
+    url: '/course/period/page',
+    method: 'post',
+    data: data
+  })
+}
+
+// 查询会员营期详细
+export function getPeriod(periodId) {
+  return request({
+    url: '/course/period/' + periodId,
+    method: 'get'
+  })
+}
+
+// 新增会员营期
+export function addPeriod(data) {
+  return request({
+    url: '/course/period',
+    method: 'post',
+    data: data
+  })
+}
+
+// 新增会员营期
+export function addCourse(data) {
+  return request({
+    url: '/course/period/addCourse',
+    method: 'post',
+    data: data
+  })
+}
+
+// 新增会员营期
+export function updateCourseTime(data) {
+  return request({
+    url: '/course/period/updateCourseTime',
+    method: 'post',
+    data: data
+  })
+}
+// 新增会员营期
+export function updateCourseDate(data) {
+  return request({
+    url: '/course/period/updateCourseDate',
+    method: 'post',
+    data: data
+  })
+}
+// 新增会员营期
+export function updateListCourseData(data) {
+  return request({
+    url: '/course/period/updateListCourseData',
+    method: 'post',
+    data: data
+  })
+}
+
+// 修改会员营期
+export function updatePeriod(data) {
+  return request({
+    url: '/course/period',
+    method: 'put',
+    data: data
+  })
+}
+
+// 删除会员营期
+export function delPeriod(periodId) {
+  return request({
+    url: '/course/period/' + periodId,
+    method: 'delete'
+  })
+}
+
+// 导出会员营期
+export function exportPeriod(query) {
+  return request({
+    url: '/course/period/export',
+    method: 'get',
+    params: query
+  })
+}
+
+// 根据营期id获取公司红包金额列表
+export function getPeriodCompanyList(query) {
+  return request({
+    url: '/course/period/companyList',
+    method: 'get',
+    params: query
+  })
+}
+
+// 按照课程批量设置红包金额
+export function batchSaveRedPacket(data) {
+  return request({
+    url: '/course/period/batchRedPacket',
+    method: 'post',
+    data: data
+  })
+}
+
+// 获取设置红包金额列表展示
+export function getPeriodRedPacketList(query) {
+  return request({
+    url: '/course/period/redPacketList',
+    method: 'get',
+    params: query
+  })
+}
+
+// 按照营期批量设置红包金额
+export function batchSaveRedPacketByPeriod(data) {
+  return request({
+    url: '/course/period/batchRedPacket/byPeriod',
+    method: 'post',
+    data: data
+  })
+}
+
+// 按照营期、按课程统计
+export function periodCountSelect(data) {
+  return request({
+    url: '/course/period/periodCount',
+    method: 'post',
+    data: data
+  })
+}
+
+// 获取营期选项列表
+export function getPeriodListLikeName(query) {
+  return request({
+    url: '/course/period/getPeriodListLikeName',
+    method: 'get',
+    params: query
+  })
+}
+
+// 营期课程上移下移
+export function periodCourseMove(data) {
+  return request({
+    url: '/course/period/courseMove',
+    method: 'put',
+    params: data
+  })
+}
+
+// 结束营期
+export function closePeriod(query) {
+  return request({
+    url: '/course/period/closePeriod',
+    method: 'post',
+    params: query
+  })
+}

+ 0 - 9
src/api/doctor/doctor.js

@@ -141,12 +141,3 @@ export function exportDoctor(query) {
     params: query
   })
 }
-
-// 根据名称模糊查询医生列表
-export function getDoctorListLikeName(params) {
-  return request({
-    url: '/his/doctor/getDoctorListLikeName',
-    method: 'get',
-    params: params
-  })
-}

+ 2 - 28
src/api/qw/QwWorkTask.js

@@ -8,20 +8,7 @@ export function listQwWorkTask(query) {
     params: query
   })
 }
-export function allListQwWorkTask(query) {
-  return request({
-    url: '/qw/QwWorkTask/allList',
-    method: 'get',
-    params: query
-  })
-}
-export function glList(query) {
-  return request({
-    url: '/qw/QwWorkTask/glList',
-    method: 'get',
-    params: query
-  })
-}
+
 // 查询企微任务看板详细
 export function getQwWorkTask(id) {
   return request({
@@ -47,20 +34,7 @@ export function updateQwWorkTask(data) {
     data: data
   })
 }
-export function updateQwWorkTask2(data) {
-  return request({
-    url: '/qw/QwWorkTask/edit2',
-    method: 'put',
-    data: data
-  })
-}
-export function updateQwWorkTask3(data) {
-  return request({
-    url: '/qw/QwWorkTask/edit3',
-    method: 'put',
-    data: data
-  })
-}
+
 // 删除企微任务看板
 export function delQwWorkTask(id) {
   return request({

+ 7 - 0
src/api/qw/groupChat.js

@@ -31,3 +31,10 @@ export function cogradientGroupChat(corpId) {
 }
 
 
+export function listAll(qwUserIds) {
+  return request({
+    url: '/qw/groupChat/listAll',
+    method: 'get',
+    params:{qwUserIds}
+  })
+}

+ 7 - 0
src/api/qw/sop.js

@@ -121,3 +121,10 @@ export function updateSopQwUser(data) {
     data: data
   })
 }
+
+export function getRoles() {
+  return request({
+    url: '/qw/sop/getRoles',
+    method: 'get'
+  })
+}

+ 0 - 10
src/api/qw/sopLogs.js

@@ -54,16 +54,6 @@ export function delQwSopLogs(id) {
   })
 }
 
-//修改 执行记录为待发送
-export function editCourseQwSopLogs(id) {
-  return request({
-    url: '/qw/sopLogs/editCourseQwSopLogs/' + id,
-    method: 'put'
-  })
-}
-
-
-
 // 导出企业微信SOP  定时任务
 export function exportQwSopLogs(query) {
   return request({

+ 25 - 8
src/api/qw/sopTemp.js

@@ -8,6 +8,14 @@ export function listSopTemp(query) {
     params: query
   })
 }
+// 查询sop模板列表
+export function redList(id) {
+  return request({
+    url: '/qw/sopTemp/redList',
+    method: 'get',
+    params: {id}
+  })
+}
 
 // 查询sop模板详细
 export function getSopTemp(id) {
@@ -57,6 +65,14 @@ export function addSopTemp(data) {
   })
 }
 // 新增sop模板
+export function updateRedPackage(data) {
+  return request({
+    url: '/qw/sopTemp/updateRedPackage',
+    method: 'post',
+    data: data
+  })
+}
+// 新增sop模板
 export function addTemp(data) {
   return request({
     url: '/qw/sopTemp/add',
@@ -106,14 +122,6 @@ export function delSopTemp(id) {
     method: 'delete'
   })
 }
-// 删除sop模板
-export function updateImage(id) {
-  return request({
-    url: '/qw/sopTemp/updateImage',
-    method: 'get',
-    params: {id}
-  })
-}
 
 
 export function shareSopTemp(data) {
@@ -132,3 +140,12 @@ export function exportSopTemp(query) {
     params: query
   })
 }
+
+
+// 导出sop模板
+export function getSelectableRange() {
+  return request({
+    url: '/qw/sopTemp/getSelectableRange',
+    method: 'get'
+  })
+}

+ 0 - 13
src/api/qw/user.js

@@ -263,16 +263,3 @@ export function selectCloudAP(data) {
     data: data
   })
 }
-
-/**
- * 模糊查询企微用户列表
- * @param params 参数
- * @returns {*}
- */
-export function getQwUserListLikeName(params) {
-  return request({
-    url: '/qw/user/getQwUserListLikeName',
-    method: 'get',
-    params: params
-  })
-}

+ 0 - 18
src/api/store/package.js

@@ -63,21 +63,3 @@ export function exportPackage(query) {
     params: query
   })
 }
-
-// 根据别名模糊查询列表
-export function getPackageListLikeSecondName(query) {
-  return request({
-    url: '/store/package/getPackageListLikeSecondName',
-    method: 'get',
-    params: query
-  })
-}
-
-// 根据套餐名称模糊查询列表
-export function getPackageListLikeName(query) {
-  return request({
-    url: '/store/package/getPackageListLikeName',
-    method: 'get',
-    params: query
-  })
-}

+ 1 - 19
src/api/store/patient.js

@@ -57,22 +57,4 @@ export function exportPatient(query) {
     method: 'get',
     params: query
   })
-}
-
-// 根据名称模糊查询患者列表
-export function getPatientListLikeName(params) {
-  return request({
-    url: '/store/patient/getPatientListLikeName',
-    method: 'get',
-    params: params
-  })
-}
-
-// 根据电话号码模糊查询患者列表
-export function getPatientListLikeTel(params) {
-  return request({
-    url: '/store/patient/getPatientListLikeTel',
-    method: 'get',
-    params: params
-  })
-}
+}

+ 2 - 2
src/api/watch/deviceInfo.js

@@ -90,11 +90,11 @@ export function exportMy(query) {
 }
 
   // 查询用户信息
-export function getUser(data) {
+export function getUser(deviceId) {
   return request({
     url: '/watch-api/device/set/up/getUserInfo',
     method: 'get',
-    params:data
+    params: { deviceId } 
   })
 }
 

BIN
src/assets/image/profile.jpg


BIN
src/assets/logo/crm.png


BIN
src/assets/logo/logo.png


+ 1 - 1
src/components/PaginationMore/index.vue

@@ -35,7 +35,7 @@ export default {
     pageSizes: {
       type: Array,
       default() {
-        return [5,10, 20, 30, 50,100,200,300]
+        return [5,10, 20, 30, 50,100,200,300,500]
       }
     },
     layout: {

+ 0 - 13
src/router/index.js

@@ -242,19 +242,6 @@ export const constantRoutes = [
       }
     ]
   },
-  {
-    path: '/watch/deviceInfo/details',
-    component: Layout,
-    hidden: true,
-    children: [
-      {
-        path: ':deviceId(\\d+)',
-        component: (resolve) => require(['@/views/watch/deviceInfo/details'], resolve),
-        name: 'details',
-        meta: { title: '设备详情', activeMenu: '/watch/deviceInfo'}
-      }
-    ]
-  },
 
 
 

+ 4 - 2
src/store/modules/user.js

@@ -37,6 +37,7 @@ const user = {
       state.user = user
     },
     SET_CALL_USER: (state, callUser) => {
+      console.log(callUser)
       state.callUser = callUser
     },
     SET_CALL_REALM: (state, callRealm) => {
@@ -49,6 +50,7 @@ const user = {
       state.isCall = call
     },
     SET_CALL_STATUS: (state, title) => {
+      console.log(title)
       state.callTitle = title
     },
   },
@@ -112,14 +114,14 @@ const user = {
           commit('SET_NAME', user.userName)
           commit('SET_AVATAR', avatar)
           commit('SET_USER', user)
-
+          
           resolve(res)
         }).catch(error => {
           reject(error)
         })
       })
     },
-
+    
     // 退出系统
     LogOut({ commit, state }) {
       return new Promise((resolve, reject) => {

+ 97 - 111
src/views/company/companyUser/index.vue

@@ -49,9 +49,9 @@
           <el-col :span="1.5">
             <el-button  plain type="danger" icon="el-icon-delete" size="mini" :disabled="multiple" @click="handleDelete" v-hasPermi="['company:user:remove']">删除</el-button>
           </el-col>
-          <el-col :span="1.5">
+          <!-- <el-col :span="1.5">
             <el-button  plain type="info" icon="el-icon-upload2" size="mini" @click="handleImport" v-hasPermi="['company:user:import']">导入</el-button>
-          </el-col>
+          </el-col> -->
           <el-col :span="1.5">
             <el-button  plain type="warning" icon="el-icon-download" size="mini" @click="handleExport" v-hasPermi="['company:user:export']">导出</el-button>
           </el-col>
@@ -64,15 +64,6 @@
              v-hasPermi="['qw:user:sync']"
            >同步企微员工和部门</el-button>
           </el-col>
-		  <el-col :span="1.5">
-		   <el-button
-		     type="primary"
-		     plain
-		     size="mini"
-		     @click="synNameOpen=true"
-		     v-hasPermi="['qw:user:sync']"
-		   >同步企微员工名称</el-button>
-		  </el-col>
           <el-col :span="1.5">
             <el-button
               type="primary"
@@ -166,27 +157,6 @@
         <el-button @click="qwCancel">取 消</el-button>
       </div>
     </el-dialog>
-
-	<el-dialog title="选择企微主体" :visible.sync="synNameOpen" width="800px" append-to-body>
-
-	  <el-form   label-width="80px">
-	    <el-form-item label="企微公司" prop="corpId">
-	      <el-select v-model="synNameform.corpId" placeholder="企微公司"  >
-	        <el-option
-	          v-for="dict in myQwCompanyList"
-	          :key="dict.dictValue"
-	          :label="dict.dictLabel"
-	          :value="dict.dictValue"
-	        />
-	      </el-select>
-	    </el-form-item>
-	  </el-form>
-	  <div slot="footer" class="dialog-footer">
-	    <el-button type="primary" @click="synNameSubmitForm">确 定</el-button>
-	    <el-button @click="synNameOpen=false">取 消</el-button>
-	  </div>
-	</el-dialog>
-
     <el-dialog title="选择企微主体" :visible.sync="synOpen" width="800px" append-to-body>
 
       <el-form   label-width="80px">
@@ -200,6 +170,8 @@
             />
           </el-select>
         </el-form-item>
+
+
       </el-form>
       <div slot="footer" class="dialog-footer">
         <el-button type="primary" @click="synSubmitForm">确 定</el-button>
@@ -211,8 +183,11 @@
       <el-form ref="form" :model="form" :rules="rules" label-width="80px">
         <el-row>
           <el-col :span="12">
+            <el-form-item label="员工账号" prop="userName">
+              <el-input v-model="form.userName" placeholder="请输入员工后台账号" />
+            </el-form-item>
             <el-form-item label="员工姓名" prop="nickName">
-              <el-input v-model="form.nickName" placeholder="请输入员工后台昵称搜索" />
+              <el-input v-model="form.nickName" placeholder="请输入员工后台昵称" />
             </el-form-item>
           </el-col>
           <el-col :span="12">
@@ -308,6 +283,18 @@
             </el-form-item>
           </el-col>
         </el-row>
+        <el-row>
+          <el-col :span="24">
+            <el-form-item label="看课域名">
+              <el-input
+                v-model="form.domain"
+                style="width: 250px"
+                placeholder="请输入域名"
+                @change="onDomainBlur"
+              ></el-input>
+            </el-form-item>
+          </el-col>
+        </el-row>
         <el-row>
           <el-col :span="24">
             <el-form-item label="备注">
@@ -322,25 +309,25 @@
       </div>
     </el-dialog>
 
-    <!-- 用户导入对话框 -->
-    <el-dialog :title="upload.title" :visible.sync="upload.open" width="400px" append-to-body>
-      <el-upload ref="upload" :limit="1" accept=".xlsx, .xls" :headers="upload.headers" :action="upload.url + '?deptId=' + upload.deptId" :disabled="upload.isUploading" :on-progress="handleFileUploadProgress" :on-success="handleFileSuccess" :auto-upload="false" drag>
-        <i class="el-icon-upload"></i>
-        <div class="el-upload__text">
-          将文件拖到此处,或
-          <em>点击上传</em>
-        </div>
-        <div class="el-upload__tip" slot="tip">
-          <!--          <el-checkbox v-model="upload.updateSupport" />是否更新已经存在的用户数据-->
-          <span>仅允许导入xls、xlsx格式文件。</span>
-          <el-link type="primary" :underline="false" style="font-size:12px;vertical-align: baseline;" @click="importTemplate">下载模板</el-link>
-        </div>
-      </el-upload>
-      <div slot="footer" class="dialog-footer">
-        <el-button type="primary" @click="submitFileForm">确 定</el-button>
-        <el-button @click="upload.open = false">取 消</el-button>
-      </div>
-    </el-dialog>
+<!--    &lt;!&ndash; 用户导入对话框 &ndash;&gt;-->
+<!--    <el-dialog :title="upload.title" :visible.sync="upload.open" width="400px" append-to-body>-->
+<!--      <el-upload ref="upload" :limit="1" accept=".xlsx, .xls" :headers="upload.headers" :action="upload.url + '?updateSupport=' + upload.updateSupport" :disabled="upload.isUploading" :on-progress="handleFileUploadProgress" :on-success="handleFileSuccess" :auto-upload="false" drag>-->
+<!--        <i class="el-icon-upload"></i>-->
+<!--        <div class="el-upload__text">-->
+<!--          将文件拖到此处,或-->
+<!--          <em>点击上传</em>-->
+<!--        </div>-->
+<!--        <div class="el-upload__tip" slot="tip">-->
+<!--          <el-checkbox v-model="upload.updateSupport" />是否更新已经存在的用户数据-->
+<!--          <el-link type="info" style="font-size:12px" @click="importTemplate">下载模板</el-link>-->
+<!--        </div>-->
+<!--        <div class="el-upload__tip" style="color:red" slot="tip">提示:仅允许导入“xls”或“xlsx”格式文件!</div>-->
+<!--      </el-upload>-->
+<!--      <div slot="footer" class="dialog-footer">-->
+<!--        <el-button type="primary" @click="submitFileForm">确 定</el-button>-->
+<!--        <el-button @click="upload.open = false">取 消</el-button>-->
+<!--      </div>-->
+<!--    </el-dialog>-->
     <el-dialog :title="user.title" :visible.sync="user.open" width="1000px" append-to-body>
       <selectUser ref="selectUser" @bindQwUser="bindQwUser"></selectUser>
     </el-dialog>
@@ -375,12 +362,12 @@ import {
   changeUserStatus,
   importTemplate,
   getCitysAreaList, updateCompanyUserAreaList,
-} from "@/api/company/companyUser";
+} from "../../../api/company/companyUser";
 import { getToken } from "@/utils/auth";
 import { treeselect } from "@/api/company/companyDept";
 import Treeselect from "@riophae/vue-treeselect";
 import "@riophae/vue-treeselect/dist/vue-treeselect.css";
-import {bindQwUser, getQwUserList, addQwUser, getQwUser, getQwUserByIds,addQwUserName} from '@/api/qw/user';
+import {bindQwUser, getQwUserList, addQwUser, getQwUser, getQwUserByIds} from '@/api/qw/user';
 import { syncDept } from '@/api/qw/qwDept';
 import { getMyQwUserList,getMyQwCompanyList } from "@/api/qw/user";
 import  selectUser  from "@/views/company/components/selectQwUser.vue";
@@ -403,8 +390,6 @@ export default {
       ids: [],
       synform:{corpId:null},
       synOpen:false,
-	  synNameform:{corpId:null},
-	  synNameOpen:false,
       // 非单个禁用
       single: true,
       // 非多个禁用
@@ -458,23 +443,21 @@ export default {
         children: "children",
         label: "label",
       },
-      // 用户导入参数
-      upload: {
-        // 是否显示弹出层(用户导入)
-        open: false,
-        // 弹出层标题(用户导入)
-        title: "",
-        // 是否禁用上传
-        isUploading: false,
-        // 是否更新已经存在的用户数据
-        updateSupport: 0,
-        //用户职位
-        deptId: 0,
-        // 设置上传的请求头部
-        headers: { Authorization: "Bearer " + getToken() },
-        // 上传的地址
-        url: process.env.VUE_APP_BASE_API + "/company/user/importData",
-      },
+      // // 用户导入参数
+      // upload: {
+      //   // 是否显示弹出层(用户导入)
+      //   open: false,
+      //   // 弹出层标题(用户导入)
+      //   title: "",
+      //   // 是否禁用上传
+      //   isUploading: false,
+      //   // 是否更新已经存在的用户数据
+      //   updateSupport: 0,
+      //   // 设置上传的请求头部
+      //   headers: { Authorization: "Bearer " + getToken() },
+      //   // 上传的地址
+      //   url: process.env.VUE_APP_BASE_API + "/system/user/importData",
+      // },
       // 查询参数
       queryParams: {
         pageNum: 1,
@@ -554,6 +537,31 @@ export default {
     });
   },
   methods: {
+    onDomainBlur() {
+      if (this.form.domain!=null){
+        let value = this.form.domain.trim();
+
+        // 强制只保留第一个 http://
+        const httpCount = (value.match(/http:\/\//g) || []).length;
+        if (httpCount > 1) {
+          value = value.replace(/(http:\/\/)+/, 'http://'); // 只留第一个
+        }
+
+        // 如果不是 http:// 开头,自动补充
+        if (!value.startsWith('http://')) {
+          value = 'http://' + value.replace(/^https?:\/\//, ''); // 去掉其他 http(s):// 再补
+        }
+
+        this.form.domain = value; // 重新赋值,保证输入正确
+
+        // 正则校验最终格式,提醒用户
+        const domainPattern = /^http:\/\/([a-zA-Z0-9-]+\.)+[a-zA-Z]{2,}$/;
+        if (!domainPattern.test(this.form.domain)) {
+          return  this.$message.error('请输入正确格式的域名,如:http://xxx.xxx.com');
+        }
+      }
+
+    },
     /** 查询用户列表 */
     getList() {
       this.loading = true;
@@ -660,6 +668,7 @@ export default {
         sex: undefined,
         status: "0",
         remark: undefined,
+        domain: null,
         postIds: [],
         roleIds: [],
       };
@@ -761,6 +770,15 @@ export default {
     },
     /** 提交按钮 */
     submitForm: function () {
+
+      this.onDomainBlur();
+
+      const domainPattern = /^http:\/\/([a-zA-Z0-9-]+\.)+[a-zA-Z]{2,}$/;
+      if (this.form.domain!=null && !domainPattern.test(this.form.domain)) {
+        this.$message.error('请输入正确格式的域名,如:http://xxx.xxx.com');
+        return;
+      }
+
       this.$refs["form"].validate((valid) => {
         if (valid) {
           if (this.form.userId != undefined) {
@@ -809,32 +827,6 @@ export default {
         loadingRock.close();
       });
     },
-
-	synNameSubmitForm() {
-      this.synNameOpen=false;
-      this.loading=true;
-      this.msgSuccess("");
-
-      let loadingRock = this.$loading({
-        lock: true,
-        text: '同步中.....请等待.....请不要重复点击!!',
-        spinner: 'el-icon-loading',
-        background: 'rgba(0, 0, 0, 0.7)'
-      });
-
-
-      addQwUserName(this.synNameform.corpId).then(response => {
-        this.msgSuccess("同步成功");
-        this.getList();
-        this.synNameOpen=false;
-      }).finally(()=>{
-        this.loading=false;
-        this.synNameOpen=false;
-        loadingRock.close();
-      });
-    },
-
-
     /**
     * 同步企业微信部门
     */
@@ -867,16 +859,11 @@ export default {
         loadingRock.close()
       });
     },
-
-
-
-
-
     /** 删除按钮操作 */
     handleDelete(row) {
       const userIds = row.userId || this.ids;
       this.$confirm(
-        '是否确认删除员工编号为"' + userIds + '"的数据项?',
+        '是否确认删除员工编号为"' + userIds + '"的数据项?【注意:删除后绑定的企业微信相关信息可能会错乱!!】',
         "警告",
         {
           confirmButtonText: "确定",
@@ -909,12 +896,11 @@ export default {
         })
         .catch(function () {});
     },
-    /** 导入按钮操作 */
-    handleImport() {
-      this.upload.title = "用户导入";
-      this.upload.deptId = this.queryParams.deptId;
-      this.upload.open = true;
-    },
+    // /** 导入按钮操作 */
+    // handleImport() {
+    //   this.upload.title = "用户导入";
+    //   this.upload.open = true;
+    // },
     /** 下载模板操作 */
     importTemplate() {
       importTemplate().then((response) => {

+ 426 - 0
src/views/course/Material/index.vue

@@ -0,0 +1,426 @@
+<template>
+  <div v-if="type == 'image'">
+    <ul v-for="(item,index) in value" :key="index" class="el-upload-list el-upload-list--picture-card">
+      <li tabindex="0" class="el-upload-list__item is-ready" :style="'width: '+width+'px;height: '+height+'px'">
+        <div>
+          <img :src="item" alt="" class="el-upload-list__item-thumbnail">
+          <span class="el-upload-list__item-actions">
+            <span v-if="index != 0" class="el-upload-list__item-preview" @click="moveMaterial(index,'up')">
+              <i class="el-icon-back" />
+            </span>
+            <span class="el-upload-list__item-preview" @click="zoomMaterial(index)">
+              <i class="el-icon-view" />
+            </span>
+            <span class="el-upload-list__item-delete" @click="deleteMaterial(index)">
+              <i class="el-icon-delete" />
+            </span>
+            <span v-if="index != value.length-1" class="el-upload-list__item-preview" @click="moveMaterial(index,'down')">
+              <i class="el-icon-right" />
+            </span>
+          </span>
+        </div>
+      </li>
+    </ul>
+    <div v-if="num > value.length" tabindex="0" class="el-upload el-upload--picture-card" :style="'width: '+width+'px;height: '+height+'px;'+'line-height:'+height+'px;'" @click="toSeleteMaterial">
+      <i class="el-icon-plus" />
+    </div>
+    <!-- 查看 -->
+    <el-dialog
+      append-to-body
+      :visible.sync="dialogVisible"
+      width="35%"
+    >
+      <img :src="materialUrl" alt="" style="width: 100%">
+    </el-dialog>
+    <!-- 素材列表 -->
+    <el-dialog
+      title="朋友圈图片素材库"
+      append-to-body
+      :visible.sync="listDialogVisible"
+      width="70%"
+    >
+      <el-container>
+        <el-aside width="unset">
+          <div style="margin-bottom: 10px">
+            <el-button
+              class="el-icon-plus"
+              size="small"
+              @click="materialgroupAdd()"
+            >
+              添加分组
+            </el-button>
+          </div>
+          <div class="group-list">
+            <div class="group-item" v-for="(group) in materialGroupList">
+                <el-button  @click="selectGroup(group)" type="primary" plain >{{group.materialGroupName}}</el-button>
+            </div>
+          </div>
+        </el-aside>
+        <el-main>
+          <el-card>
+            <div slot="header">
+              <el-row>
+                <el-col :span="12">
+                  <span>{{ materialGroup.materialGroupName }}</span>
+                  <span v-if="materialGroup.materialGroupId >0">
+                    <el-button size="small" type="text" class="el-icon-edit" style="margin-left: 10px;" @click="materialgroupEdit(materialGroup)">重命名</el-button>
+                    <el-button size="small" type="text" class="el-icon-delete" style="margin-left: 10px;color: red" @click="materialgroupDelete(materialGroup)">删除</el-button>
+                  </span>
+                </el-col>
+                <el-col :span="12" style="text-align: right;">
+                  <el-upload
+                    :action="uploadUrl"
+                    :file-list="[]"
+                    :on-progress="handleProgress"
+                    :before-upload="beforeUpload"
+                    :on-success="handleSuccess"
+                    :data="{type: 1}"
+                    multiple
+                  >
+                    <el-button size="small" type="primary">批量上传</el-button>
+                  </el-upload>
+                </el-col>
+              </el-row>
+            </div>
+            <div v-loading="tableLoading">
+              <el-alert
+                v-if="tableData.length <= 0"
+                title="暂无数据"
+                type="info"
+                :closable="false"
+                center
+                show-icon
+              />
+              <el-row :gutter="5">
+                <el-checkbox-group v-model="urls" :max="num - value.length">
+                  <el-col v-for="(item,index) in tableData" :key="index" :span="4">
+                    <el-card :body-style="{ padding: '5px' }">
+                      <el-image
+                        style="width: 100%;height: 100px"
+                        :src="item.materialUrl"
+                        fit="contain"
+                        :preview-src-list="[item.materialUrl]"
+                        :z-index="9999"
+                      />
+                      <div>
+                        <el-checkbox class="material-name" :label="item.materialUrl">
+                          选择
+                        </el-checkbox>
+                        <el-row>
+                          <el-col :span="24" class="col-do">
+                            <el-button type="text" size="medium" @click="materialDel(item)">删除</el-button>
+                          </el-col>
+                        </el-row>
+
+                      </div>
+                    </el-card>
+                  </el-col>
+                </el-checkbox-group>
+              </el-row>
+               <pagination
+                  v-show="total>0"
+                  :total="total"
+                  :page.sync="queryParams.pageNum"
+                  :limit.sync="queryParams.pageSize"
+                  @pagination="getMaterialList"
+                />
+
+            </div>
+          </el-card>
+        </el-main>
+      </el-container>
+      <span slot="footer" class="dialog-footer">
+        <el-button @click="listDialogVisible = false">取 消</el-button>
+        <el-button type="primary" @click="submit">确 定</el-button>
+      </span>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { listMaterial, getMaterial, delMaterial, addMaterial, updateMaterial, } from "@/api/qw/material";
+import { listMaterialGroup, getMaterialGroup, delMaterialGroup, addMaterialGroup, updateMaterialGroup } from "@/api/qw/materialGroup";
+export default {
+  name: 'ImageSelect',
+  props: {
+    // 素材数据
+    value: {
+      type: Array,
+      default() {
+        return []
+      }
+    },
+    // 素材类型
+    type: {
+      type: String
+    },
+    // 素材限制选择数量,最多9个
+    num: {
+      type: Number,
+      default() {
+        return 9
+      }
+    },
+    // 宽度
+    width: {
+      type: Number,
+      default() {
+        return 150
+      }
+    },
+    // 宽度
+    height: {
+      type: Number,
+      default() {
+        return 150
+      }
+    }
+  },
+  data() {
+    return {
+      uploadUrl:process.env.VUE_APP_BASE_API+"/common/uploadOSS",
+      dialogVisible: false,
+      materialUrl: '',
+      listDialogVisible: false,
+      //素材组列表
+      materialGroupList: [],
+      materialGroupLoading: false,
+      //选择的某个素材组
+      materialGroup:{},
+      tableData: [],
+      resultNumber: 0,
+      total: 0,
+      //查询素材列表
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        groupType:2,
+        materialGroupName: null,
+        materialGroupId:null,
+        materialUrl: null,
+        createUserId: null,
+      },
+      tableLoading: false,
+      urls: []
+    }
+  },
+  mounted(){
+    this.getAllMaterialGroup();
+  },
+  methods: {
+    //查询素材组下的素材列表
+    selectGroup(item){
+      this.materialGroup=item;
+      this.queryParams.materialGroupId=item.materialGroupId;
+      this.getMaterialList();
+    },
+    //添加分组
+    materialgroupAdd() {
+      const that = this
+      this.$prompt('请输入分组名', '提示', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消'
+      }).then(({ value }) => {
+        addMaterialGroup({
+          materialGroupName: value,
+          groupType:2
+        }).then(function() {
+          that.materialGroup={};
+          that.getAllMaterialGroup();
+        })
+      }).catch(() => {
+
+      })
+    },
+    //删除素材组
+    materialgroupDelete(materialgroupObj) {
+      const that = this
+      this.$confirm('是否确认删除该分组?', '提示', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      }).then(function() {
+        delMaterialGroup(materialgroupObj.materialGroupId)
+          .then(function() {
+            that.materialGroup={};
+            that.getAllMaterialGroup()
+          })
+      })
+      this.resetGroup();
+      this.getAllMaterialGroup();
+    },
+    //修改素材组名称
+    materialgroupEdit(materialgroupObj) {
+      const that = this
+      this.$prompt('请输入分组名', '提示', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        inputValue: materialgroupObj.materialGroupName
+      }).then(({ value }) => {
+        updateMaterialGroup({
+          materialGroupId: materialgroupObj.materialGroupId,
+          materialGroupName: value,
+          groupType:2,
+        }).then(function() {
+          that.materialGroup={};
+          that.getAllMaterialGroup()
+        })
+      }).catch(() => {
+
+      })
+    },
+    //获取所有素材分组
+    getAllMaterialGroup() {
+      this.materialGroupLoading = true;
+      listMaterialGroup({groupType:2}).then(response => {
+        this.materialGroupList = response.rows
+        this.materialGroupLoading = false;
+      });
+    },
+    resetGroup(){
+      this.queryParams= {
+        pageNum: 1,
+          pageSize: 10,
+          groupType:2,
+          materialGroupName: null,
+          materialGroupId:null,
+          materialUrl: null,
+          createUserId: null,
+      };
+    },
+    //查询分组 下的素材
+    getMaterialList() {
+      this.tableLoading = true;
+      listMaterial(this.queryParams).then(response => {
+        this.tableData = response.rows;
+        this.total = response.total;
+        this.tableLoading = false;
+      });
+    },
+    //移动素材
+    moveMaterial(index, type) {
+      if (type == 'up') {
+        const tempOption = this.value[index - 1]
+        this.$set(this.value, index - 1, this.value[index])
+        this.$set(this.value, index, tempOption)
+      }
+      if (type == 'down') {
+        const tempOption = this.value[index + 1]
+        this.$set(this.value, index + 1, this.value[index])
+        this.$set(this.value, index, tempOption)
+      }
+    },
+    //缩小图片
+    zoomMaterial(index) {
+      this.dialogVisible = true
+      this.materialUrl = this.value[index]
+    },
+    //删除素材
+    deleteMaterial(index) {
+      const that = this
+      this.$confirm('是否确认删除?', '提示', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      }).then(function() {
+        that.value.splice(index, 1)
+        that.urls = []
+      })
+    },
+
+    toSeleteMaterial() {
+      this.listDialogVisible = true
+      this.getAllMaterialGroup()
+      this.getMaterialList();
+    },
+    //删除素材
+    materialDel(item) {
+      const that = this
+      this.$confirm('是否确认删除该素材?', '提示', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      }).then(function() {
+        delMaterial(item.materialId)
+          .then(function() {
+            that.queryParams.pageNum=0;
+            that.getMaterialList();
+          })
+      })
+    },
+
+    //上传进度
+    handleProgress(event, file, fileList) {
+    },
+    //上传成功后
+    handleSuccess(response, file, fileList) {
+      const that = this
+      addMaterial({
+        materialType: 'image',
+        materialGroupId: this.queryParams.materialGroupId,
+        materialName: file.name,
+        materialUrl: response.url,
+        groupType:2,
+      }).then(() => {
+        this.resultNumber++
+        if (fileList.length === this.resultNumber) {
+          that.getMaterialList()
+          this.resultNumber = 0
+        }
+      })
+    },
+    //上传之前
+    beforeUpload(file) {
+      const isPic =
+        file.type === 'image/jpeg' ||
+        file.type === 'image/png' ||
+        file.type === 'image/gif' ||
+        file.type === 'image/jpg'
+      const isLt2M = file.size / 1024 / 1024 < 10
+      if (!isPic) {
+        this.$message.error('上传图片只能是 JPG、JPEG、PNG、GIF 格式!')
+        return false
+      }
+      if (!isLt2M) {
+        this.$message.error('上传图片大小不能超过 10MB!')
+      }
+      return isPic && isLt2M
+    },
+    //提交
+    submit() {
+      this.urls.forEach(item => {
+        console.log("item",item)
+        console.log("this.value",this.value)
+        console.log("this.value.length",this.value.length)
+
+        this.$set(this.value, this.value.length, item)
+      })
+      this.listDialogVisible = false
+    }
+  }
+}
+</script>
+
+<style rel="stylesheet/scss" lang="scss" scoped>
+  ::v-deep .el-icon-circle-close{
+    color: red;
+  }
+  .material-name{
+    padding: 8px 0px;
+  }
+  .col-do{
+    text-align: center;
+  }
+  .button-do{
+    padding: unset!important;
+    font-size: 12px;
+  }
+  .group-list{
+    display: flex;
+    flex-direction:column;
+    align-items: flex-start;
+  }
+  .group-item{
+    margin: 5px;
+  }
+</style>

+ 2 - 10
src/views/course/courseAnswerlogs/myCourseAnswerlogs.vue

@@ -146,15 +146,7 @@
 </template>
 
 <script>
-import {
-  myListLogs,
-  getLogs,
-  delLogs,
-  addLogs,
-  updateLogs,
-  exportLogs,
-  exportLogsMy
-} from "@/api/course/courseAnswerlogs";
+import { myListLogs, getLogs, delLogs, addLogs, updateLogs, exportLogs } from "@/api/course/courseAnswerlogs";
 import { courseList, videoList } from '@/api/course/courseRedPacketLog'
 import {allListTagGroup} from "@/api/qw/tagGroup";
 import {listTag} from "@/api/qw/tag";
@@ -371,7 +363,7 @@ export default {
           type: "warning"
         }).then(() => {
           this.exportLoading = true;
-          return exportLogsMy(queryParams);
+          return exportLogs(queryParams);
         }).then(response => {
           this.download(response.msg);
           this.exportLoading = false;

+ 32 - 147
src/views/course/courseFinishTemp/index.vue

@@ -104,11 +104,6 @@
       <el-table-column label="小节名称" align="center" prop="videoName" />
       <el-table-column label="创建时间" align="center" prop="createTime" />
       <el-table-column label="修改时间" align="center" prop="updateTime" />
-      <el-table-column label="全选销售" align="center" prop="isAllCompanyUser">
-        <template slot-scope="scope">
-          <dict-tag :options="allowSelect" :value="scope.row.isAllCompanyUser"/>
-        </template>
-      </el-table-column>
       <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
         <template slot-scope="scope">
           <el-button
@@ -207,6 +202,9 @@
                         <el-input v-model="item.linkUrl" placeholder="请输入链接地址" style="width: 90%;"/>
                       </el-form-item>
                     </el-card>
+                  </div>
+                  <div v-if="item.contentType == 4">
+
                   </div>
                   <div v-if="item.contentType == 5 ">
 
@@ -244,6 +242,16 @@
                       </video>
                     </el-form-item>
                   </div>
+                  <div v-if="item.contentType == 7 ">
+                      <el-input
+                        v-model="item.value"
+                        type="textarea" :rows="3" maxlength="66" show-word-limit
+                        placeholder="输入要转为语音的内容" style="width: 90%;margin-top: 10px;"
+                        @input="handleInputVideoText(item.value,item)"/>
+                  </div>
+                  <div v-if="item.contentType == 8">
+
+                  </div>
 
                 </el-form-item>
               </el-form>
@@ -254,46 +262,17 @@
           </el-row>
           </div>
         <el-link type="primary" class="el-icon-plus" :underline="false" @click='addSetList()' v-if="formType==1" >添加内容</el-link>
+
         </el-form-item>
-        <el-form-item label="全选销售" prop="isAllCompanyUser">
-          <el-switch
-            v-model="form.isAllCompanyUser"
-            active-color="#13ce66"
-            inactive-color="#ff4949"
-            :active-value="1"
-            :inactive-value="2">
-          </el-switch>
-          <span v-if="form.isAllCompanyUser == '1'" style="margin-left: 10px;color: #13ce66">是</span>
-          <span v-else style="margin-left: 10px;color: #ff4949">否</span>
-        </el-form-item>
-        <el-form-item label="所属企微员工" prop="companyUserIds" label-width="100px" v-if="form.isAllCompanyUser != 1 ">
-<!--          <el-select v-model="companyUserIds" remote multiple placeholder="请选择" filterable  style="width: 100%;">-->
-<!--            <el-option-->
-<!--              v-for="dict in userList"-->
-<!--              :key="dict.userId"-->
-<!--              :label="dict.nickName"-->
-<!--              :value="dict.userId.toString()">-->
-<!--            </el-option>-->
-<!--          </el-select>-->
-          <div>
-            <el-button
-              size="medium"
-              icon="el-icon-circle-plus-outline"
-              plain
-              @click="handlelistUser">请选择使用成员</el-button>
-          </div>
-          <div>
-            <el-tag
-              style="margin-left: 5px"
-              size="medium"
-              :key="list.id"
-              v-for="list in userSelectList"
-              closable
-              :disable-transitions="false"
-              @close="handleClosegroupUser(list)">
-              {{list.qwUserId}}({{list.qwUserName}})({{list.nickName}})
-            </el-tag>
-          </div>
+        <el-form-item label="所属销售" prop="companyUserIds">
+          <el-select v-model="companyUserIds" remote multiple placeholder="请选择" filterable  style="width: 100%;">
+            <el-option
+              v-for="dict in userList"
+              :key="dict.userId"
+              :label="dict.nickName"
+              :value="dict.userId.toString()">
+            </el-option>
+          </el-select>
         </el-form-item>
       </el-form>
       <div slot="footer" class="dialog-footer" v-if="formType==1">
@@ -301,11 +280,6 @@
         <el-button @click="cancel">取 消</el-button>
       </div>
     </el-dialog>
-
-    <!-- 选择成员账号弹窗   -->
-    <el-dialog :title="listUser.title" :visible.sync="listUser.open" width="800px" append-to-body>
-      <qwUserListByCompany ref="QwUserList" @selectUserList="selectUserList"></qwUserListByCompany>
-    </el-dialog>
   </div>
 </template>
 
@@ -314,27 +288,20 @@ import { listCourseFinishTemp, getCourseFinishTemp, addCourseFinishTemp, updateC
 import { getUserList } from '@/api/company/companyUser'
 import {courseList, videoList} from '@/api/qw/sop'
 import ImageUpload from "@/views/qw/sop/ImageUpload.vue";
-import qwUserList from "@/views/qw/user/qwUserList.vue";
-import QwUserListByCompany from "@/views/qw/user/qwUserListByCompany.vue";
 
 export default {
   name: "CourseFinishTemp",
-  components: {QwUserListByCompany, qwUserList, ImageUpload},
+  components: {ImageUpload},
   data() {
     return {
       //上传语音的遮罩层
       voiceLoading :false,
       uploadUrl:process.env.VUE_APP_BASE_API+"/common/uploadOSS2",
       uploadUrlByVoice:process.env.VUE_APP_BASE_API+"/common/uploadOSSByHOOKVoice",
-
-      // 存储每一行的展开状态
-      expandedRows: {},
-
       companyUserIds:[],
       userList:[],
       // 状态字典
       statusOptions: [],
-      allowSelect: [],
       courseList:[],
       videoList:[],
       // 遮罩层
@@ -359,14 +326,6 @@ export default {
 
       sysFsSopWatchStatus: [],
 
-      //选择企业微信成员列表
-      userSelectList:[],
-      //选择成员列表
-      listUser:{
-        title:"",
-        open:false
-      },
-
       // 弹出层标题
       title: "",
       // 是否显示弹出层
@@ -401,16 +360,12 @@ export default {
     this.getList();
     getUserList().then(response => {
       this.userList =  response.data;
+      console.log("this.userList",this.userList)
     });
     this.getDicts("sys_company_status").then(response => {
       this.statusOptions = response.data;
     });
 
-    //复用一下
-    this.getDicts("sys_qw_allow_select").then(response => {
-      this.allowSelect = response.data;
-    });
-
     this.getDicts("sys_fs_sop_watch_status").then(response => {
       this.sysFsSopWatchStatus = response.data;
     });
@@ -422,51 +377,7 @@ export default {
       this.courseList = response.list;
     });
   },
-  watch:{
-    userSelectList(newList) {
-      this.form.companyUserIds =newList.map(item =>item.id);
-    }
-  },
   methods: {
-
-
-    // 切换某一行的展开状态
-    toggleRow(row) {
-      this.$set(this.expandedRows, row.id, !this.expandedRows[row.id]);
-    },
-
-    //选择群发的企业成员账号
-    handlelistUser(){
-      this.listUser.title="选择企业成员"
-      this.listUser.open=true;
-    },
-    //删除一些选择了的账号
-    handleClosegroupUser(list){
-
-      // 假设 list 对象具有一个 id 属性
-      const index = this.userSelectList.findIndex(t => t.id === list.id);
-      if (index !== -1) {
-        this.userSelectList.splice(index,1);
-      }
-    },
-
-    //选择的成员账号列表
-    selectUserList(list){
-
-      this.listUser.open=false;
-
-      // 3. 遍历要添加的 list,逐条判断是否存在重复
-      list.forEach(newItem => {
-        // some() 判断是否存在相同 id
-        const isExist = this.userSelectList.some(oldItem => oldItem.id === newItem.id);
-        if (!isExist) {
-          // 不存在重复的,才添加
-          this.userSelectList.push(newItem);
-        }
-      });
-
-    },
-
     courseChange() {
 
       videoList(this.form.courseId).then(response => {
@@ -628,10 +539,9 @@ export default {
         videoId: null,
         companyUserIds: null,
         updateTime: null,
-        isDel: null,
-        isAllCompanyUser:null,
+        isDel: null
       };
-      this.userSelectList=[]
+      this.companyUserIds=[]
       this.setting=[]
       this.resetForm("form");
     },
@@ -666,13 +576,10 @@ export default {
       this.reset();
       const id = row.id || this.ids
       getCourseFinishTemp(id).then(response => {
-        console.log("this.form222 ",response.data )
         this.form = response.data;
-
         this.setting=JSON.parse(this.form.setting)
-
         if (response.data.companyUserIds!=null){
-          this.userSelectList = this.form.companyUserIds;
+          this.companyUserIds = this.form.companyUserIds.split(",");
         }
 
         videoList(this.form.courseId).then(response => {
@@ -690,19 +597,16 @@ export default {
       this.reset();
       const id = row.id || this.ids
       getCourseFinishTemp(id).then(response => {
-
         this.form = response.data;
-
         this.setting=JSON.parse(this.form.setting)
-        if (response.data.userSelectList!=null){
-          this.userSelectList =  this.form.userSelectList
+        if (response.data.companyUserIds!=null){
+          this.companyUserIds = this.form.companyUserIds.split(",");
         }
 
         videoList(this.form.courseId).then(response => {
           this.videoList=response.list;
         });
 
-
         this.open = true;
         this.title = "修改完课模板";
 
@@ -712,24 +616,7 @@ export default {
     submitForm() {
       this.$refs["form"].validate(valid => {
         if (valid) {
-
-          if (this.form.isAllCompanyUser==null){
-            this.form.isAllCompanyUser=2;
-          }
-
-          if ((this.form.isAllCompanyUser==2 || this.form.isAllCompanyUser==null)  && (this.form.companyUserIds==null || this.form.companyUserIds.length==0) ){
-            return  this.$message.error("请选择企业微信员工")
-          }
-
-          console.log("sout",this.form)
-
-          if (this.form.companyUserIds!=null && this.form.companyUserIds.length>0){
-            this.form.companyUserIds = this.form.companyUserIds.join(",")
-          }else {
-            this.form.companyUserIds=null;
-          }
-
-
+          this.form.companyUserIds = this.companyUserIds.toString()
 
           this.form.setting=JSON.stringify(this.setting)
 
@@ -770,16 +657,14 @@ export default {
             updateCourseFinishTemp(this.form).then(response => {
               this.msgSuccess("修改成功");
               this.open = false;
-              this.setting=[];
-              this.userSelectList=[]
               this.getList();
+              this.setting=[];
             });
           } else {
             addCourseFinishTemp(this.form).then(response => {
               this.msgSuccess("新增成功");
               this.open = false;
               this.setting=[];
-              this.userSelectList=[]
               this.getList();
             });
           }

+ 2 - 12
src/views/course/courseRedPacketLog/myCourseRedPacketLog.vue

@@ -182,17 +182,7 @@
 </template>
 
 <script>
-import {
-  courseList,
-  videoList,
-  myListCourseRedPacketLog,
-  getCourseRedPacketLog,
-  delCourseRedPacketLog,
-  addCourseRedPacketLog,
-  updateCourseRedPacketLog,
-  exportCourseRedPacketLog,
-  exportCourseRedPacketLogMy
-} from "@/api/course/courseRedPacketLog";
+import { courseList,videoList,myListCourseRedPacketLog, getCourseRedPacketLog, delCourseRedPacketLog, addCourseRedPacketLog, updateCourseRedPacketLog, exportCourseRedPacketLog } from "@/api/course/courseRedPacketLog";
 import {getMyQwUserList} from "@/api/qw/user";
 
 export default {
@@ -419,7 +409,7 @@ export default {
         type: "warning"
       }).then(() => {
         this.exportLoading = true;
-        return exportCourseRedPacketLogMy(queryParams);
+        return exportCourseRedPacketLog(queryParams);
       }).then(response => {
         this.download(response.msg);
         this.exportLoading = false;

+ 178 - 236
src/views/course/courseWatchLog/index.vue

@@ -19,7 +19,7 @@
           @keyup.enter.native="handleQuery"
         />
       </el-form-item>
-      <el-form-item label="企微客户昵称" prop="nickName" >
+      <el-form-item label="企微客户昵称" prop="nickName">
         <el-input
           v-model="queryParams.externalUserName"
           placeholder="请输入企微客户昵称"
@@ -28,21 +28,19 @@
           @keyup.enter.native="handleQuery"
         />
       </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.value"
-            :label="item.label"
-            :value="item.value">
-          </el-option>
-        </el-select>
+      <el-form-item label="所属销售" prop="companyUserName">
+        <el-input
+          v-model="queryParams.companyUserName"
+          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-select filterable v-model="queryParams.courseId" placeholder="请选择课程" clearable size="small"
+                   @change="courseChange(queryParams.courseId)"
+        >
           <el-option
             v-for="dict in courseLists"
             :key="dict.dictValue"
@@ -52,7 +50,7 @@
         </el-select>
       </el-form-item>
       <el-form-item label="小节" prop="videoId">
-        <el-select filterable  v-model="queryParams.videoId" placeholder="请选择小节"  clearable size="small">
+        <el-select filterable v-model="queryParams.videoId" placeholder="请选择小节" clearable size="small">
           <el-option
             v-for="dict in videoList"
             :key="dict.dictValue"
@@ -61,33 +59,6 @@
           />
         </el-select>
       </el-form-item>
-      <el-form-item label="企微ID" prop="qwUserUserId">
-        <el-input
-          v-model="queryParams.qwUserUserId"
-          placeholder="请输入所属企微ID"
-          clearable
-          size="small"
-          @keyup.enter.native="handleQuery"
-        />
-      </el-form-item>
-      <el-form-item label="企微员工名称" prop="qwUserName">
-        <el-input
-          v-model="queryParams.qwUserName"
-          placeholder="请输入所属企微员工名称"
-          clearable
-          size="small"
-          @keyup.enter.native="handleQuery"
-        />
-      </el-form-item>
-      <el-form-item label="部门名称" prop="deptName">
-        <el-input
-          v-model="queryParams.deptName"
-          placeholder="请输入部门名称"
-          clearable
-          size="small"
-          @keyup.enter.native="handleQuery"
-        />
-      </el-form-item>
       <el-form-item label="营期时间" prop="scheduleTime">
         <el-date-picker
           v-model="scheduleTime"
@@ -98,16 +69,23 @@
           range-separator="-"
           start-placeholder="开始日期"
           end-placeholder="结束日期"
-          @change="handleScheduleTimeChange">
+          @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-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-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>
@@ -125,7 +103,8 @@
           :loading="exportLoading"
           @click="handleExport"
           v-hasPermi="['course:courseWatchLog:export']"
-        >导出</el-button>
+        >导出
+        </el-button>
       </el-col>
       <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
     </el-row>
@@ -135,42 +114,43 @@
       <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 type="selection" width="55" align="center"/>
+      <el-table-column label="记录编号" align="center" prop="logId"/>
       <el-table-column label="企微客户" align="center" prop="externalUserName"/>
-      <el-table-column label="会员ID" align="center" prop="userId" />
+      <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}}
+              {{ scope.row.fsNickName }}
             </div>
             <el-popover
               placement="right"
               title=""
-              trigger="hover">
+              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="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="companyName" />-->
-      <el-table-column label="企微员工名称" align="center" prop="qwUserName" />
-<!--      <el-table-column label="所属发送方式" align="center" prop="sendType" />-->
-      <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="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="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
@@ -185,19 +165,27 @@
 </template>
 
 <script>
-import { listCourseWatchLog, getCourseWatchLog, delCourseWatchLog, addCourseWatchLog, updateCourseWatchLog, exportCourseWatchLog } from "@/api/course/courseWatchLog";
-import { courseList,videoList } from '@/api/course/courseRedPacketLog'
-import { getCompanyUserListLikeName } from "@/api/company/companyUser";
+import {
+  listCourseWatchLog,
+  getCourseWatchLog,
+  delCourseWatchLog,
+  addCourseWatchLog,
+  updateCourseWatchLog,
+  exportCourseWatchLog
+} from '@/api/course/courseWatchLog'
+import { allList } from '@/api/company/company'
+import { courseList, videoList } from '@/api/course/courseRedPacketLog'
+
 export default {
-  name: "CourseWatchLog",
+  name: 'CourseWatchLog',
   data() {
     return {
-      activeName:"00",
-      createTime:null,
-      updateTime:null,
-      courseLists:[],
-      videoList:[],
-      logTypeOptions:[],
+      activeName: '00',
+      createTime: null,
+      updateTime: null,
+      courseLists: [],
+      videoList: [],
+      logTypeOptions: [],
       // 遮罩层
       loading: true,
       // 导出遮罩层
@@ -215,7 +203,7 @@ export default {
       // 短链课程看课记录表格数据
       courseWatchLogList: [],
       // 弹出层标题
-      title: "",
+      title: '',
       // 是否显示弹出层
       open: false,
       // 查询参数
@@ -227,104 +215,91 @@ export default {
         videoId: null,
         logType: null,
         qwExternalContactId: null,
-        externalUserName: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,
+        sTime: null,
+        eTime: null,
+        upSTime: null,
+        upETime: null,
         scheduleStartTime: null,
-        scheduleEndTime: null,
+        scheduleEndTime: null
       },
       // 表单参数
       form: {},
       // 表单校验
-      rules: {
-      },
-      scheduleTime: null,
-      // 员工选项列表
-      companyUserOptionsParams: {
-        name: undefined,
-        hasNextPage: false,
-        pageNum: 1,
-        pageSize: 10
-      },
-      companyUserOptionsLoading: false,
-      companyUserOptions: [],
-    };
+      rules: {},
+      scheduleTime: null
+    }
   },
   created() {
     courseList().then(response => {
-      this.courseLists = response.list;
-    });
-    this.getList();
-    this.getDicts("sys_course_watch_log_type").then(response => {
-      this.logTypeOptions = response.data;
-    });
+      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=[];
+    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];
+        this.queryParams.sTime = this.createTime[0]
+        this.queryParams.eTime = this.createTime[1]
       } else {
-        this.queryParams.sTime = null;
-        this.queryParams.eTime = null;
+        this.queryParams.sTime = null
+        this.queryParams.eTime = null
       }
     },
 
-    updateChange(){
+    updateChange() {
       if (this.updateTime != null) {
-        this.queryParams.upSTime = this.updateTime[0];
-        this.queryParams.upETime = this.updateTime[1];
+        this.queryParams.upSTime = this.updateTime[0]
+        this.queryParams.upETime = this.updateTime[1]
       } else {
-        this.queryParams.upSTime = null;
-        this.queryParams.upETime = null;
+        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;
+    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;
+      this.loading = true
+      if (this.queryParams.logType == '10') {
+        this.queryParams.logType = null
       }
 
       listCourseWatchLog(this.queryParams).then(response => {
-        this.courseWatchLogList = response.rows;
-        this.total = response.total;
-        this.loading = false;
-      });
+        this.courseWatchLogList = response.rows
+        this.total = response.total
+        this.loading = false
+      })
     },
     // 取消按钮
     cancel() {
-      this.open = false;
-      this.reset();
+      this.open = false
+      this.reset()
     },
     // 表单重置
     reset() {
@@ -336,154 +311,121 @@ export default {
         createTime: null,
         updateTime: null,
         qwExternalContactId: null,
-        externalUserName:null,
+        externalUserName: null,
         duration: null,
         qwUserId: null,
         companyUserId: null,
         companyId: null,
         courseId: null,
         scheduleStartTime: null,
-        scheduleEndTime: null,
-      };
-      this.scheduleTime=null;
-      this.resetForm("form");
+        scheduleEndTime: null
+      }
+      this.scheduleTime = null
+      this.resetForm('form')
     },
     /** 搜索按钮操作 */
     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.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.single = selection.length !== 1
       this.multiple = !selection.length
     },
     /** 新增按钮操作 */
     handleAdd() {
-      this.reset();
-      this.open = true;
-      this.title = "添加短链课程看课记录";
+      this.reset()
+      this.open = true
+      this.title = '添加短链课程看课记录'
     },
     /** 修改按钮操作 */
     handleUpdate(row) {
-      this.reset();
+      this.reset()
       const logId = row.logId || this.ids
       getCourseWatchLog(logId).then(response => {
-        this.form = response.data;
-        this.open = true;
-        this.title = "修改短链课程看课记录";
-      });
+        this.form = response.data
+        this.open = true
+        this.title = '修改短链课程看课记录'
+      })
     },
     /** 提交按钮 */
     submitForm() {
-      this.$refs["form"].validate(valid => {
+      this.$refs['form'].validate(valid => {
         if (valid) {
           if (this.form.logId != null) {
             updateCourseWatchLog(this.form).then(response => {
-              this.msgSuccess("修改成功");
-              this.open = false;
-              this.getList();
-            });
+              this.msgSuccess('修改成功')
+              this.open = false
+              this.getList()
+            })
           } else {
             addCourseWatchLog(this.form).then(response => {
-              this.msgSuccess("新增成功");
-              this.open = false;
-              this.getList();
-            });
+              this.msgSuccess('新增成功')
+              this.open = false
+              this.getList()
+            })
           }
         }
-      });
+      })
     },
     /** 删除按钮操作 */
     handleDelete(row) {
-      const logIds = row.logId || this.ids;
-      this.$confirm('是否确认删除短链课程看课记录编号为"' + logIds + '"的数据项?', "警告", {
-          confirmButtonText: "确定",
-          cancelButtonText: "取消",
-          type: "warning"
-        }).then(function() {
-          return delCourseWatchLog(logIds);
-        }).then(() => {
-          this.getList();
-          this.msgSuccess("删除成功");
-        }).catch(() => {});
+      const logIds = row.logId || this.ids
+      this.$confirm('是否确认删除短链课程看课记录编号为"' + logIds + '"的数据项?', '警告', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      }).then(function() {
+        return delCourseWatchLog(logIds)
+      }).then(() => {
+        this.getList()
+        this.msgSuccess('删除成功')
+      }).catch(() => {
+      })
     },
     /** 导出按钮操作 */
     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(() => {});
+      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(() => {
+        this.exportLoading = false
+      })
     },
     handleScheduleTimeChange(val) {
       if (val) {
-        this.queryParams.scheduleStartTime = val[0];
-        this.queryParams.scheduleEndTime = val[1];
+        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() {
-      getCompanyUserListLikeName(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.queryParams.scheduleStartTime = null
+        this.queryParams.scheduleEndTime = null
       }
-
-      this.companyUserOptionsParams.pageNum += 1
-      this.getCompanyUserListLikeName()
-    },
+    }
   }
-};
+}
 </script>

+ 4 - 12
src/views/course/courseWatchLog/myCourseWatchLog.vue

@@ -127,10 +127,10 @@
       </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="companyName" />
       <el-table-column label="企微员工名称" align="center" prop="qwUserName" />
       <el-table-column label="企微账号" align="center" prop="qwUserName" />
-<!--      <el-table-column label="所属发送方式" align="center" prop="sendType" />-->
+      <el-table-column label="所属发送方式" align="center" prop="sendType" />
       <el-table-column label="创建时间" align="center" prop="createTime" />
 <!--      <el-table-column label="更新时间" align="center" prop="updateTime" />-->
       <el-table-column label="完课时间" align="center" prop="lastHeartbeatTime" />
@@ -148,15 +148,7 @@
 </template>
 
 <script>
-import {
-  myListCourseWatchLog,
-  getCourseWatchLog,
-  delCourseWatchLog,
-  addCourseWatchLog,
-  updateCourseWatchLog,
-  exportCourseWatchLog,
-  exportCourseWatchLogMy
-} from "@/api/course/courseWatchLog";
+import { myListCourseWatchLog, getCourseWatchLog, delCourseWatchLog, addCourseWatchLog, updateCourseWatchLog, exportCourseWatchLog } from "@/api/course/courseWatchLog";
 import { courseList,videoList } from '@/api/course/courseRedPacketLog'
 import {getMyQwUserList} from "@/api/qw/user";
 import {allListTagGroup} from "@/api/qw/tagGroup";
@@ -385,7 +377,7 @@ export default {
           type: "warning"
         }).then(() => {
           this.exportLoading = true;
-          return exportCourseWatchLogMy(queryParams);
+          return exportCourseWatchLog(queryParams);
         }).then(response => {
           this.download(response.msg);
           this.exportLoading = false;

+ 4 - 4
src/views/course/courseWatchLog/watchLog.vue

@@ -148,10 +148,10 @@
       </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="companyName"/>
       <el-table-column label="企微员工名称" align="center" prop="qwUserName"/>
       <el-table-column label="企微账号" align="center" prop="qwUserName"/>
-<!--      <el-table-column label="所属发送方式" align="center" prop="sendType"/>-->
+      <el-table-column label="所属发送方式" align="center" prop="sendType"/>
       <el-table-column label="创建时间" align="center" prop="createTime" width="100px"/>
       <el-table-column label="更新时间" align="center" prop="updateTime" width="100px" />
       <el-table-column label="完课时间" align="center" prop="finishTime" width="100px" />
@@ -273,7 +273,7 @@
 import {
   addCourseWatchLog,
   delCourseWatchLog,
-  exportCourseWatchLog, exportCourseWatchLogMy,
+  exportCourseWatchLog,
   getCourseWatchLog,
   myListCourseWatchLog,
   updateCourseWatchLog
@@ -563,7 +563,7 @@ export default {
         type: "warning"
       }).then(() => {
         this.exportLoading = true;
-        return exportCourseWatchLogMy(queryParams);
+        return exportCourseWatchLog(queryParams);
       }).then(response => {
         this.download(response.msg);
         this.exportLoading = false;

+ 1 - 1
src/views/course/sop/SopDialog.vue

@@ -104,7 +104,7 @@
 
 <script>
 import { listSop, getSop, delSop, addSop, updateSop, exportSop } from "@/api/course/sop";
-import  Material  from "@/views/qw/materialQw/index.vue";
+import  Material  from "@/views/course/Material/index.vue";
 import sopLogsDetails from '@/views/course/sopLogs/sopLogsList.vue'
 import userCourseVideo from '@/views/course/sop/userCourseVideo.vue';
 export default {

+ 1 - 1
src/views/course/sop/index.vue

@@ -317,7 +317,7 @@
 
 <script>
 import { listSop, getSop, delSop, addSop, updateSop, exportSop } from "@/api/course/sop";
-import  Material  from "@/views/qw/materialQw/index.vue";
+import  Material  from "@/views/course/Material/index.vue";
 import sopLogsDetails from '@/views/course/sopLogs/sopLogsList.vue'
 import { listUserCourse } from '@/api/course/userCourse'
 import userCourseVideo from '@/views/course/sop/userCourseVideo.vue';

+ 126 - 0
src/views/course/userCoursePeriod/batchRedPacket.vue

@@ -0,0 +1,126 @@
+<template>
+  <el-dialog
+    title="批量设置红包"
+    :visible.sync="visible"
+    width="800px"
+    append-to-body
+  >
+    <el-table
+      v-loading="loading"
+      :data="tableData"
+      border
+      style="width: 100%"
+    >
+      <el-table-column
+        type="index"
+        label="序号"
+        width="80"
+        align="center"
+      />
+      <el-table-column
+        prop="periodName"
+        label="营期"
+        align="center"
+      />
+      <el-table-column
+        label="金额"
+        align="center"
+        width="200"
+      >
+        <template slot-scope="scope">
+          <el-input-number
+            v-model="scope.row.amount"
+            :min="0.01"
+            :precision="2"
+            :step="0.01"
+            size="small"
+            style="width: 150px"
+          />
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <div slot="footer" class="dialog-footer">
+      <el-button @click="handleClose">取 消</el-button>
+      <el-button type="primary" @click="handleSave">保 存</el-button>
+    </div>
+  </el-dialog>
+</template>
+
+<script>
+import { batchSaveRedPacketByPeriod } from "@/api/course/userCoursePeriod";
+
+export default {
+  name: 'BatchRedPacket',
+  props: {
+    visible: {
+      type: Boolean,
+      default: false
+    },
+    selectedData: {
+      type: Array,
+      default: () => []
+    }
+  },
+  data() {
+    return {
+      loading: false,
+      tableData: []
+    }
+  },
+  watch: {
+    visible(val) {
+      if (val) {
+        this.initTableData()
+      }
+    }
+  },
+  methods: {
+    // 初始化表格数据
+    initTableData() {
+      this.tableData = this.selectedData.map(item => ({
+        ...item,
+        amount: 0.01
+      }))
+    },
+    // 保存
+    handleSave() {
+      this.$confirm(`是否确定?确定后营期下的所有公司红包金额都将设置成对应值`, '提示', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      }).then(() => {
+        this.loading = true;
+        const saveData = this.tableData.map(item => ({
+          periodId: item.periodId,
+          redPacketMoney: item.amount
+        }));
+
+        batchSaveRedPacketByPeriod(saveData).then(response => {
+          if (response.code === 200) {
+            this.$message.success('设置成功');
+            this.$emit('success');
+            this.handleClose();
+          } else {
+            this.$message.error(response.msg || '批量设置失败');
+          }
+        }).catch(error => {
+          this.$message.error('批量设置失败:' + error.message);
+        }).finally(() => {
+          this.loading = false;
+        });
+      })
+    },
+    // 关闭
+    handleClose() {
+      this.$emit('update:visible', false)
+    }
+  }
+}
+</script>
+
+<style scoped>
+.el-input-number {
+  width: 100%;
+}
+</style>

+ 1495 - 0
src/views/course/userCoursePeriod/index.vue

@@ -0,0 +1,1495 @@
+<template>
+  <div class="app-container">
+    <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
+      <el-form-item label="营期名称" prop="periodName">
+        <el-input
+          v-model="queryParams.periodName"
+          placeholder="请输入营期名称"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="开营日期开始" prop="periodStartingTime" label-width="120px">
+        <el-date-picker clearable size="small" style="width: 200px"
+                        v-model="queryParams.periodStartingTime"
+                        type="date"
+                        value-format="yyyy-MM-dd"
+                        placeholder="请选择开营日期开始时间">
+        </el-date-picker>
+      </el-form-item>
+      <el-form-item label="开营日期结束" prop="periodEndTime" label-width="120px">
+        <el-date-picker clearable size="small" style="width: 300px"
+                        v-model="queryParams.periodEndTime"
+                        type="date"
+                        value-format="yyyy-MM-dd"
+                        placeholder="请选择开营日期结束时间">
+        </el-date-picker>
+      </el-form-item>
+      <el-form-item>
+        <el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
+      </el-form-item>
+    </el-form>
+
+    <el-row :gutter="10" class="mb8">
+<!--      <el-col :span="1.5">-->
+<!--        <el-button-->
+<!--          type="primary"-->
+<!--          plain-->
+<!--          icon="el-icon-plus"-->
+<!--          size="mini"-->
+<!--          @click="handleAdd"-->
+<!--          v-hasPermi="['course:period:add']"-->
+<!--        >新增-->
+<!--        </el-button>-->
+<!--      </el-col>-->
+<!--      <el-col :span="1.5">-->
+<!--        <el-button-->
+<!--          type="warning"-->
+<!--          plain-->
+<!--          icon="el-icon-download"-->
+<!--          size="mini"-->
+<!--          @click="handleExport"-->
+<!--          v-hasPermi="['course:period:export']"-->
+<!--        >导出-->
+<!--        </el-button>-->
+<!--      </el-col>-->
+<!--      <el-col :span="1.5">-->
+<!--        <el-button-->
+<!--          type="primary"-->
+<!--          plain-->
+<!--          icon="el-icon-edit"-->
+<!--          size="mini"-->
+<!--          @click="handleBatchSetRedPacket"-->
+<!--          v-hasPermi="['course:period:export']"-->
+<!--          :disabled="batchSetRedPacketDisabled"-->
+<!--        >批量设置红包-->
+<!--        </el-button>-->
+      </el-col>
+      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+
+    <el-table v-loading="loading" :data="periodList" @selection-change="handleSelectionChange">
+      <el-table-column type="selection" width="55" align="center"/>
+      <el-table-column label="营期名称" align="center" prop="periodName"/>
+      <el-table-column label="营期状态" align="center" prop="periodStatus" width="100"
+                       :formatter="periodStatusFormatter"/>
+      <el-table-column label="开营开始时间" align="center" prop="periodStartingTime" width="180"/>
+      <el-table-column label="开营结束时间" align="center" prop="periodEndTime" width="180"/>
+      <el-table-column label="创建时间" align="center" prop="createTime" width="180"/>
+      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+        <template slot-scope="scope">
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-edit"
+            @click="handleUpdate(scope.row)"
+            v-hasPermi="['course:period:edit']"
+          >详情
+          </el-button>
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-setting"
+            @click="handlePeriodSettings(scope.row)"
+          >营期相关设置
+          </el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <pagination
+      v-show="total>0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    />
+
+    <!-- 添加或修改会员营期对话框-->
+    <el-drawer :title="title" :visible.sync="open" size="700px" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+        <el-form-item label="营期名称" prop="periodName">
+          <el-input disabled v-model="form.periodName" placeholder="请输入营期名称"/>
+        </el-form-item>
+        <el-form-item label="课程风格" prop="courseStyle">
+          <image-upload disabled v-model="form.courseStyle" :limit="1"/>
+        </el-form-item>
+        <el-form-item label="直播间风格" prop="liveRoomStyle">
+          <image-upload disabled v-model="form.liveRoomStyle" :limit="1"/>
+        </el-form-item>
+        <el-form-item label="红包发放方式" prop="redPacketGrantMethod">
+          <el-radio-group disabled v-model="form.redPacketGrantMethod">
+            <el-radio :label="1">按课程</el-radio>
+            <el-radio :label="2">按营期</el-radio>
+          </el-radio-group>
+        </el-form-item>
+        <el-form-item label="营期类型" prop="periodType">
+          <el-radio-group disabled v-model="form.periodType">
+            <el-radio :label="1">多课程</el-radio>
+            <el-radio :label="2">单课程</el-radio>
+          </el-radio-group>
+        </el-form-item>
+        <el-form-item label="开营日期" prop="periodStartingTime">
+          <el-date-picker
+            disabled
+            :style="{display: form.periodType == 1 ? '' : 'none !important'}"
+            v-model="form.dateRange"
+            @change="timeChange(1)"
+            type="daterange"
+            range-separator="至"
+            start-placeholder="开始日期"
+            end-placeholder="结束日期"
+            value-format="yyyy-MM-dd">
+          </el-date-picker>
+          <el-date-picker
+            disabled
+            :style="{display: form.periodType == 2 ? '' : 'none !important'}"
+            @change="timeChange(2)"
+            v-model="form.date"
+            type="date"
+            value-format="yyyy-MM-dd"
+            placeholder="选择日期">
+          </el-date-picker>
+        </el-form-item>
+      </el-form>
+    </el-drawer>
+
+    <!-- 添加训练营对话框 -->
+    <el-dialog :title="campForm.trainingCampId ? '修改训练营' : '新建训练营'" :visible.sync="campDialogVisible"
+               width="500px" append-to-body>
+      <el-form ref="campForm" :model="campForm" :rules="campRules" label-width="100px">
+        <el-form-item label="训练营名称" prop="trainingCampName">
+          <el-input v-model="campForm.trainingCampName" placeholder="请输入训练营名称"/>
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitCampForm">确 定</el-button>
+        <el-button @click="cancelCampForm">取 消</el-button>
+      </div>
+    </el-dialog>
+
+    <!-- 添加课程对话框-->
+    <el-dialog title="添加课程" :visible.sync="course.addOpen" width="500px" append-to-body>
+      <el-form ref="courseAddForm" :model="course.form" label-width="100px">
+        <el-form-item label="课程" prop="courseId">
+          <el-select filterable v-model="course.form.courseId" placeholder="请选择课程" clearable size="small"
+                     @change="courseChange(course.form.courseId)" style="width: 100%" :value-key="'dictValue'">
+            <el-option
+              v-for="dict in courseList"
+              :key="dict.dictValue"
+              :label="dict.dictLabel"
+              :value="parseInt(dict.dictValue)"
+            />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="小节" prop="videoId">
+          <el-select filterable v-model="course.form.videoIds" placeholder="请选择小节"
+                     :multiple-limit="getDiff(course.row.periodStartingTime, course.row.periodEndTime) - course.total"
+                     multiple clearable size="small" style="width: 100%" :value-key="'dictValue'">
+            <el-option
+              v-for="dict in videoList"
+              :key="dict.dictValue"
+              :label="dict.dictLabel"
+              :value="parseInt(dict.dictValue)"
+            />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="看课时间" prop="timeRange">
+          <el-time-picker
+            is-range
+            v-model="course.form.timeRange"
+            range-separator="至"
+            start-placeholder="开始时间"
+            value-format="HH:mm:ss"
+            end-placeholder="结束时间"
+            placeholder="选择时间范围">
+          </el-time-picker>
+        </el-form-item>
+        <el-form-item label="领取红包时间" prop="lastJoinTime">
+          <el-time-picker
+            v-model="course.form.joinTime"
+            :selectableRange="course.form.timeRange"
+            value-format="HH:mm:ss"
+            placeholder="选择时间范围">
+          </el-time-picker>
+          <p style="color: red;margin: 0;font-size: 12px">超过领取红包时间,只允许看课,不允许领取红包</p>
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitCourseForm">确 定</el-button>
+        <el-button @click="closeAddCourse">取 消</el-button>
+      </div>
+    </el-dialog>
+    <el-dialog title="修改看课时间" :visible.sync="updateCourse.open" width="500px" append-to-body>
+      <el-form ref="courseUpdateForm" :model="updateCourse.form" label-width="100px">
+        <el-form-item label="看课时间" prop="timeRange">
+          <el-time-picker
+            is-range
+            v-model="updateCourse.form.timeRange"
+            range-separator="至"
+            start-placeholder="开始时间"
+            value-format="HH:mm:ss"
+            end-placeholder="结束时间"
+            placeholder="选择时间范围">
+          </el-time-picker>
+        </el-form-item>
+        <el-form-item label="领取红包时间" prop="lastJoinTime">
+          <el-time-picker
+            v-model="updateCourse.form.joinTime"
+            :selectableRange="updateCourse.form.timeRange"
+            value-format="HH:mm:ss"
+            placeholder="选择时间范围">
+          </el-time-picker>
+          <p style="color: red;margin: 0;font-size: 12px">超过领取红包时间,只允许看课,不允许领取红包</p>
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitUpdateCourseForm">确 定</el-button>
+        <el-button @click="closeUpdateCourse">取 消</el-button>
+      </div>
+    </el-dialog>
+    <el-dialog title="修改营期时间" :visible.sync="updateDateOpen" width="500px" append-to-body>
+      <el-form ref="courseUpdateForm" :model="form" label-width="100px">
+        <el-form-item label="营期时间" prop="dayDate">
+          <el-date-picker
+            v-model="form.dayDate"
+            :selectableRange="form.dayDate"
+            value-format="yyyy-MM-dd"
+            type="date"
+            placeholder="选择时间">
+          </el-date-picker>
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="updateDate">确 定</el-button>
+        <el-button @click="updateDateOpen = false">取 消</el-button>
+      </div>
+    </el-dialog>
+
+    <!--    <red-packet-->
+    <!--      :visible.sync="redPacketVisible"-->
+    <!--      :periodId="currentRedPacketData.periodId"-->
+    <!--      :videoId="currentRedPacketData.videoId"-->
+    <!--      @success="handleRedPacketSuccess"-->
+    <!--    />-->
+
+    <!-- 营期相关设置抽屉 -->
+    <el-drawer
+      title="营期相关设置"
+      :visible.sync="periodSettingsVisible"
+      direction="rtl"
+      size="70%"
+      :destroy-on-close="true"
+      append-to-body
+      custom-class="period-settings-drawer"
+    >
+      <div class="drawer-content" style="margin-left: 25px">
+        <el-tabs v-model="activeTab" @tab-click="handleTabClick">
+          <el-tab-pane label="课程管理" name="course">
+            <el-table v-loading="course.loading" :data="course.list" @selection-change="handleSelectionCourseChange">
+              <el-table-column label="课程" align="center" prop="courseName" width="180"/>
+              <el-table-column label="小节" align="center" prop="videoName"/>
+              <el-table-column label="营期时间" align="center" prop="dayDate"/>
+              <el-table-column label="开始时间" align="center" prop="startDateTime" width="100">
+                <template slot-scope="scope">
+                  <el-tag>{{ parseTime(scope.row.startDateTime, '{h}:{i}:{s}') }}</el-tag>
+                </template>
+              </el-table-column>
+              <el-table-column label="结束时间" align="center" prop="endDateTime" width="100">
+                <template slot-scope="scope">
+                  <el-tag type="success">{{ parseTime(scope.row.endDateTime, '{h}:{i}:{s}') }}</el-tag>
+                </template>
+              </el-table-column>
+              <el-table-column label="领取红包时间" align="center" prop="lastJoinTime" width="100">
+                <template slot-scope="scope">
+                  <el-tag type="danger">{{ parseTime(scope.row.lastJoinTime, '{h}:{i}:{s}') }}</el-tag>
+                </template>
+              </el-table-column>
+            </el-table>
+          </el-tab-pane>
+          <el-tab-pane label="课程统计" name="statistics">
+            <course-statistics
+              :periodId="periodSettingsData.periodId"
+              :active="activeTab === 'statistics'"
+            />
+          </el-tab-pane>
+        </el-tabs>
+      </div>
+    </el-drawer>
+
+    <batch-red-packet
+      :visible.sync="batchRedPacketVisible"
+      :selected-data="selectedPeriods"
+      @success="handleBatchRedPacketSuccess"
+    />
+
+  </div>
+</template>
+
+<script>
+import {
+  addPeriod,
+  delPeriod,
+  exportPeriod,
+  getPeriod,
+  pagePeriod,
+  updatePeriod,
+  getDays,
+  addCourse,
+  updateCourseTime,
+  updateCourseDate,
+  updateListCourseData,
+  periodCourseMove,
+  closePeriod
+} from "@/api/course/userCoursePeriod";
+import {getCompanyList} from "@/api/company/company";
+import {courseList, videoList} from '@/api/course/courseRedPacketLog'
+import RedPacket from './redPacket.vue'
+import BatchRedPacket from './batchRedPacket.vue'
+import CourseStatistics from './statistics.vue'
+
+export default {
+  name: "Period",
+  components: {
+    RedPacket,
+    BatchRedPacket,
+    CourseStatistics
+  },
+  data() {
+    return {
+      // 遮罩层
+      loading: true,
+      updateDateOpen: false,
+      // 左侧遮罩层
+      leftLoading: true,
+      // 选中数组
+      ids: [],
+      // 非单个禁用
+      single: true,
+      // 非多个禁用
+      multiple: true,
+      // 显示搜索条件
+      showSearch: true,
+      // 总条数
+      total: 0,
+      // 左侧总条数
+      leftTotal: 0,
+      // 会员营期表格数据
+      periodList: [],
+      // 左侧列表数据
+      leftList: [],
+      videoList: [],
+      // 弹出层标题
+      title: "",
+      isDisabledDateRange: false, //是否禁用开营日期
+      // 是否显示弹出层
+      open: false,
+      // 查询参数
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        periodName: null,
+        periodStartingTime: null,
+        periodEndTime: null,
+        companyIdList: []
+      },
+      // 左侧查询参数
+      leftQueryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        hasNextPage: false,
+        scs: 'order_number(desc),training_camp_id(desc)',
+        trainingCampName: null
+      },
+      // 表单参数
+      form: {},
+      course: {
+        open: false,
+        row: {},
+        list: [],
+        queryParams: {
+          pageNum: 1,
+          pageSize: 10,
+        },
+        loading: true,
+        total: 0,
+        addOpen: false,
+        form: {},
+      },
+      updateCourse: {
+        open: false,
+        loading: true,
+        ids: [],
+        form: {},
+      },
+      // 表单校验
+      rules: {},
+      // 公司选项
+      companyOptions: [],
+      // 训练营列表
+      campList: [],
+      // 激活的训练营索引
+      activeCampIndex: null,
+      // 训练营对话框是否显示
+      campDialogVisible: false,
+      courseList: false,
+      // 训练营表单
+      campForm: {
+        trainingCampId: null,
+        trainingCampName: ''
+      },
+      // 训练营表单校验
+      campRules: {
+        trainingCampName: [
+          {required: true, message: '训练营名称不能为空', trigger: 'blur'},
+          {min: 2, max: 50, message: '长度在 2 到 50 个字符', trigger: 'blur'}
+        ]
+      },
+      // 滚动节流标志
+      scrollThrottle: false,
+      // 加载更多状态
+      loadingMore: false,
+      // 设置红包对话框
+      redPacketVisible: false,
+      periodCompanyList: [],
+      currentRedPacketData: {
+        periodId: '',
+        videoId: ''
+      },
+      // 营期相关设置抽屉
+      periodSettingsVisible: false,
+      activeTab: 'course',
+      periodSettingsData: {},
+      companyList: [],
+      courseDialogVisible: false,
+      redPacketList: [],
+      currentCompany: null,
+      // 选中的营期数据
+      selectedPeriods: [],
+      // 批量设置红包按钮是否禁用
+      batchSetRedPacketDisabled: true,
+      // 批量设置红包弹出框
+      batchRedPacketVisible: false,
+    };
+  },
+  created() {
+
+    courseList().then(response => {
+      this.courseList = response.list;
+    });
+    this.getCompanyList();
+    this.getList();
+  },
+  methods: {
+    /** 查询会员营期列表 */
+    getList() {
+      this.loading = true;
+      const params = {...this.queryParams};
+      pagePeriod(params).then(response => {
+        this.periodList = response.rows;
+        this.total = response.total;
+        this.loading = false;
+      });
+    },
+    /** 查询左侧列表 */
+    getLeftList() {
+      this.leftLoading = true;
+      // 重置页码和加载更多状态
+      this.leftQueryParams.pageNum = 1;
+      this.loadingMore = false;
+
+      // 训练营数据
+      listCamp(this.leftQueryParams).then(response => {
+        if (response && response.code === 200) {
+          this.campList = response.data.list || [];
+          this.leftQueryParams.hasNextPage = response.data.hasNextPage;
+          this.activeCampIndex = this.campList.length > 0 ? 0 : null;
+          this.selectCamp(this.activeCampIndex);
+          // 如果当前显示的列表高度不足以触发滚动,但还有更多数据,自动加载下一页
+          this.$nextTick(() => {
+            const scrollEl = this.$refs.campList;
+            if (scrollEl && this.leftQueryParams.hasNextPage && scrollEl.scrollHeight <= scrollEl.clientHeight) {
+              this.loadMoreCamps();
+            }
+          });
+        } else {
+          this.$message.error(response.msg || '获取训练营列表失败');
+          this.campList = [];
+          this.leftQueryParams.hasNextPage = false;
+        }
+        this.leftLoading = false;
+      }).catch(error => {
+        console.error('获取训练营列表失败:', error);
+        this.$message.error('获取训练营列表失败');
+        this.campList = [];
+        this.leftQueryParams.hasNextPage = false;
+        this.leftLoading = false;
+      });
+    },
+    /** 搜索按钮操作 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 左侧搜索按钮操作 */
+    handleLeftQuery() {
+      // 重置页码和列表
+      this.leftQueryParams.pageNum = 1;
+      this.campList = [];
+      this.getLeftList();
+    },
+    /** 重置按钮操作 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.queryParams.companyIdList = [];
+      this.handleQuery();
+    },
+    /** 多选框选中数据 */
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.periodId)
+      this.single = selection.length !== 1
+      this.multiple = !selection.length
+      // 更新批量设置红包相关数据
+      this.selectedPeriods = selection;
+      this.batchSetRedPacketDisabled = selection.length === 0;
+    },
+    handleSelectionCourseChange(selection) {
+      this.updateCourse.ids = selection.map(item => item.id)
+    },
+    /** 新增按钮操作 */
+    handleAdd() {
+      this.reset();
+      this.open = true;
+      this.title = "添加会员营期";
+      this.isDisabledDateRange = false;
+    },
+    /** 修改按钮操作 */
+    handleUpdate(row) {
+      this.reset();
+      const periodId = row.periodId || this.ids
+      getPeriod(periodId).then(response => {
+        this.form = response.data;
+        if (this.form.companyId) {
+          this.form.companyId = this.form.companyId.split(',').map(id => Number(id));
+        }
+        // 设置看课时间范围(回显)
+        if (this.form.viewStartTime && this.form.viewEndTime) {
+          this.form.timeRange = [this.form.viewStartTime, this.form.viewEndTime];
+        }
+        if (this.form.periodType == 1) {
+          this.form.dateRange = [this.form.periodStartingTime, this.form.periodEndTime];
+        }
+        if (this.form.periodType == 1) {
+          this.form.date = this.form.periodStartingTime;
+        }
+        this.open = true;
+        this.title = "修改会员营期";
+        this.isDisabledDateRange = true;
+      });
+    },
+    /** 提交按钮 */
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          let data = JSON.parse(JSON.stringify(this.form));
+          // 处理看课时间范围
+          if (data.timeRange && data.timeRange.length === 2) {
+            data.viewStartTime = data.timeRange[0];
+            data.viewEndTime = data.timeRange[1];
+          }
+          data.companyId = data.companyId.join()
+          data.trainingCampId = this.queryParams.trainingCampId
+          if (data.periodId != null) {
+            updatePeriod(data).then(response => {
+              if (response.code === 200) {
+                this.msgSuccess("修改成功");
+                this.open = false;
+                this.getList();
+              }
+            });
+          } else {
+            addPeriod(data).then(response => {
+              if (response.code === 200) {
+                this.msgSuccess("新增成功");
+                this.open = false;
+                this.getList();
+              }
+            });
+          }
+        }
+      });
+    },
+    /** 删除按钮操作 */
+    handleDelete(row) {
+      //添加删除判断,只能删除未开始的营期
+      console.log(row.periodStatus)
+      if (row.periodStatus !== 1) {
+        this.$message.error('营期处于进行中或者结束,不能删除');
+        return;
+      }
+      const periodIds = row.periodId || this.ids;
+      this.$confirm('是否确认删除该营期?', "警告", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      }).then(function () {
+        return delPeriod(periodIds);
+      }).then(() => {
+        this.getList();
+        this.msgSuccess("删除成功");
+      }).catch(function () {
+      });
+    },
+    /** 导出按钮操作 */
+    handleExport() {
+      const queryParams = this.queryParams;
+      this.$confirm('是否确认导出所有会员营期数据项?', "警告", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      }).then(function () {
+        return exportPeriod(queryParams);
+      }).then(response => {
+        this.download(response.msg);
+      }).catch(function () {
+      });
+    },
+
+    /** 批量设置红包 */
+    handleBatchSetRedPacket() {
+      if (this.selectedPeriods.length === 0) {
+        this.$message.warning('请至少选择一个营期');
+        return;
+      }
+      this.batchRedPacketVisible = true;
+    },
+
+    /** 处理批量设置红包保存 */
+    // handleBatchRedPacketSave(data) {
+    //   // 这里等待接口提供后补充具体实现
+    //   // 示例代码:
+    //   // batchSetRedPacket(data).then(response => {
+    //   //   if (response.code === 200) {
+    //   //     this.$message.success('批量设置成功');
+    //   //     this.getList();
+    //   //   }
+    //   // });
+    //   this.batchRedPacketVisible = false;
+    // },
+
+    /** 获取公司下拉列表*/
+    getCompanyList() {
+      this.loading = true;
+      getCompanyList().then(response => {
+        this.companyOptions = response.data;
+        this.loading = false;
+      });
+    },
+    // 取消按钮
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 表单重置
+    reset() {
+      this.form = {
+        periodId: null,
+        periodName: null,
+        companyId: null,
+        courseId: null,
+        videoId: null,
+        trainingCampId: null,
+        createTime: null,
+        updateTime: null,
+        courseStyle: null,
+        liveRoomStyle: null,
+        redPacketGrantMethod: 1,
+        periodType: 1,
+        periodStartingTime: null,
+        dateRange: [],
+        date: null,
+        days: [],
+        periodEndTime: null,
+        timeRange: [], // 看课时间范围
+        viewStartTime: null, // 看课开始时间
+        viewEndTime: null, // 看课结束时间
+        lastJoinTime: null // 领取红包时间
+      };
+      this.resetForm("form");
+    },
+    // 处理训练营列表的逻辑
+    handleDeleteCamp(item) {
+      this.$confirm(`确定要删除训练营"${item.trainingCampName}"吗?`, '提示', {
+        confirmButtonText: '删除',
+        cancelButtonText: '取消',
+        type: 'warning'
+      }).then(() => {
+        // 调用删除训练营API
+        const trainingCampId = item.trainingCampId;
+        this.leftLoading = true;
+
+        delCamp(trainingCampId).then(response => {
+          if (response.code === 200) {
+            this.$message.success('删除成功');
+            // 从列表中移除
+            const index = this.campList.findIndex(camp => camp.trainingCampId === trainingCampId);
+            if (index !== -1) {
+              this.campList.splice(index, 1);
+            }
+            // 如果删除的是当前选中的训练营,则重置选中状态
+            if (this.activeCampIndex === index) {
+              this.activeCampIndex = this.campList.length > 0 ? 0 : null;
+              if (this.activeCampIndex !== null) {
+                // 更新右侧列表
+                this.selectCamp(this.activeCampIndex);
+              } else {
+                // 没有训练营了,清空右侧列表
+                this.periodList = [];
+              }
+            }
+          } else {
+            this.$message.error(response.msg || '删除失败');
+          }
+          this.leftLoading = false;
+        }).catch(error => {
+          this.$message.error('删除失败: ' + error.message);
+          this.leftLoading = false;
+        });
+      }).catch(() => {
+        this.$message.info('已取消删除');
+      });
+    },
+    /** 复制训练营 */
+    handleCopyCamp(item) {
+      // 调用添加训练营API
+      copyCamp(item.trainingCampId).then(response => {
+        if (response.code === 200) {
+          this.$message.success('复制成功');
+          // 重新加载训练营列表
+          this.getLeftList();
+        } else {
+          this.$message.error(response.msg || '复制训练营失败');
+        }
+      }).catch(error => {
+        this.$message.error('复制训练营失败: ' + error.message);
+      });
+    },
+    /** 修改训练营按钮操作 */
+    handleEditCamp(item) {
+      this.resetCampForm();
+      this.leftLoading = true;
+
+      // 获取最新的训练营数据
+      const trainingCampId = item.trainingCampId;
+      // 应该调用获取训练营详情的API
+      setTimeout(() => {
+        // 填充表单数据
+        this.campForm = {
+          trainingCampId: item.trainingCampId,
+          trainingCampName: item.trainingCampName,
+          orderNumber: item.orderNumber || 1,
+          status: item.status !== undefined ? item.status : 1
+        };
+        this.campDialogVisible = true;
+        this.leftLoading = false;
+      }, 300);
+    },
+    /** 新建训练营按钮操作 */
+    handleAddTrainingCamp() {
+      this.resetCampForm();
+      this.campDialogVisible = true;
+    },
+    /** 重置训练营表单 */
+    resetCampForm() {
+      this.campForm = {
+        trainingCampId: null,
+        trainingCampName: ''
+      };
+      // 如果表单已经创建,则重置校验结果
+      if (this.$refs.campForm) {
+        this.$refs.campForm.resetFields();
+      }
+    },
+    /** 取消训练营表单 */
+    cancelCampForm() {
+      this.campDialogVisible = false;
+      this.resetCampForm();
+    },
+    /** 提交训练营表单 */
+    submitCampForm() {
+      this.$refs.campForm.validate(valid => {
+        if (valid) {
+          // 显示加载中
+          this.leftLoading = true;
+
+          // 准备提交的数据
+          const submitData = JSON.parse(JSON.stringify(this.campForm));
+
+          // 判断是新增还是修改
+          if (submitData.trainingCampId) {
+            // 修改训练营
+            editCamp(submitData).then(response => {
+              if (response.code === 200) {
+                this.$message.success('修改训练营成功');
+                this.campDialogVisible = false;
+
+                // 更新列表中的数据
+                const index = this.campList.findIndex(camp => camp.trainingCampId === submitData.trainingCampId);
+                if (index !== -1) {
+                  this.campList[index] = {...this.campList[index], ...submitData};
+                  // 如果修改的是当前选中的训练营,更新右侧列表
+                  if (this.activeCampIndex === index) {
+                    this.selectCamp(index);
+                  }
+                }
+
+                // 重新加载训练营列表
+                this.getLeftList();
+              } else {
+                this.$message.error(response.msg || '修改训练营失败');
+                this.leftLoading = false;
+              }
+            }).catch(error => {
+              this.$message.error('修改训练营失败: ' + (error.message || '未知错误'));
+              this.leftLoading = false;
+            });
+          } else {
+            // 新增训练营
+            addCamp(submitData).then(response => {
+              if (response.code === 200) {
+                this.$message.success('新建训练营成功');
+                this.campDialogVisible = false;
+                // 重新加载训练营列表
+                this.getLeftList();
+              } else {
+                this.$message.error(response.msg || '新建训练营失败');
+                this.leftLoading = false;
+              }
+            }).catch(error => {
+              this.$message.error('新建训练营失败: ' + (error.message || '未知错误'));
+              this.leftLoading = false;
+            });
+          }
+        }
+      });
+    },
+    /** 排序方式改变 */
+    handleSortChange(value) {
+      this.leftQueryParams.scs = value;
+      // 重置页码和列表
+      this.leftQueryParams.pageNum = 1;
+      this.campList = [];
+      this.getLeftList();
+    },
+    /** 选中训练营 */
+    selectCamp(index) {
+      if (index == null || index == undefined) return;
+      this.activeCampIndex = index;
+      // 加载对应的训练营营期数据
+      const selectedCamp = this.campList[index];
+      this.queryParams.trainingCampId = selectedCamp.trainingCampId;
+      this.getList();
+    },
+    /** 处理滚动事件,实现滚动到底部加载更多 */
+    handleScroll() {
+      // 如果正在节流中或者正在加载中,则不处理
+      if (this.scrollThrottle || this.loadingMore) return;
+
+      // 设置节流,200ms内不再处理滚动事件
+      this.scrollThrottle = true;
+      setTimeout(() => {
+        this.scrollThrottle = false;
+      }, 200);
+
+      const scrollEl = this.$refs.campList;
+      if (!scrollEl) return;
+
+      // 判断是否滚动到底部:滚动高度 + 可视高度 >= 总高度 - 30(添加30px的容差,提前触发加载)
+      const isBottom = scrollEl.scrollTop + scrollEl.clientHeight >= scrollEl.scrollHeight - 30;
+
+      // 如果滚动到底部,且有下一页数据,且当前不在加载中,则加载更多
+      if (isBottom && this.leftQueryParams.hasNextPage && !this.leftLoading && !this.loadingMore) {
+        this.loadMoreCamps();
+      }
+    },
+    /** 加载更多训练营数据 */
+    loadMoreCamps() {
+      // 已在加载中,防止重复加载
+      if (this.leftLoading || this.loadingMore) return;
+
+      // 设置加载状态
+      this.loadingMore = true;
+
+      // 页码加1
+      this.leftQueryParams.pageNum += 1;
+
+      // 加载下一页数据
+      listCamp(this.leftQueryParams).then(response => {
+        if (response && response.code === 200) {
+          // 将新数据追加到列表中
+          const newList = response.data.list || [];
+          if (newList.length > 0) {
+            this.campList = [...this.campList, ...newList];
+          }
+
+          // 更新是否有下一页的标志
+          this.leftQueryParams.hasNextPage = response.data.hasNextPage;
+
+          // 如果当前显示的列表高度不足以触发滚动,但还有更多数据,自动加载下一页
+          this.$nextTick(() => {
+            const scrollEl = this.$refs.campList;
+            if (scrollEl && this.leftQueryParams.hasNextPage && scrollEl.scrollHeight <= scrollEl.clientHeight) {
+              // 延迟一点再加载下一页,避免过快加载
+              setTimeout(() => {
+                this.loadMoreCamps();
+              }, 300);
+            }
+          });
+        } else {
+          this.$message.error(response.msg || '加载更多训练营失败');
+        }
+        this.loadingMore = false;
+      }).catch(error => {
+        console.error('加载更多训练营失败:', error);
+        this.$message.error('加载更多训练营失败');
+        this.loadingMore = false;
+      });
+    },
+    timeChange(type) {
+      if (type == 1) {
+        this.form.periodStartingTime = this.form.dateRange[0];
+        this.form.periodEndTime = this.form.dateRange[1];
+
+
+        // 转换为天数
+        let days = this.getDiff(this.form.periodStartingTime, this.form.periodEndTime);
+        for (let i = 0; i < days; i++) {
+          this.form.days.push({lesson: i + 1});
+        }
+      }
+      if (type == 2) {
+        this.form.periodStartingTime = this.form.date;
+        this.form.periodEndTime = this.form.date;
+      }
+    },
+    getDiff(start, end) {
+      if (start == null || start == undefined || start == '') return 0;
+      if (end == null || end == undefined || end == '') return 0;
+      if (start == end) 1;
+      const startDate = this.getUTCDate(start);
+      const endDate = this.getUTCDate(end);
+
+      const timeDiff = endDate - startDate;
+      return (Math.floor(timeDiff / (1000 * 3600 * 24))) + 1; // 直接取整
+    },
+    getUTCDate(dateStr) {
+      const [year, month, day] = dateStr.split('-').map(Number);
+      return new Date(Date.UTC(year, month - 1, day)); // 月份从0开始
+    },
+    handleCourse(row) {
+      this.course = {
+        open: false,
+        row: {},
+        list: [],
+        queryParams: {
+          pageNum: 1,
+          pageSize: 9999,
+        },
+        loading: true,
+        total: 0,
+        addOpen: false,
+        form: {},
+      };
+      this.course.open = true;
+      this.course.row = row;
+      this.course.queryParams.periodId = row.periodId;
+      this.getCourseList();
+    },
+    getCourseList() {
+      this.course.loading = true;
+      getDays(this.course.queryParams).then(e => {
+        this.course.list = e.rows;
+        this.course.total = e.total;
+        this.course.loading = false;
+      });
+    },
+    handleAddCourse() {
+      this.course.addOpen = true;
+      this.course.form = {
+        periodId: this.course.queryParams.periodId,
+        courseId: null,
+        videoIds: []
+      };
+      // 重置表单
+      this.$nextTick(() => {
+        if (this.$refs.courseAddForm) {
+          this.$refs.courseAddForm.resetFields();
+        }
+      });
+    },
+    handleUpdateCourse() {
+      this.updateCourse.open = true;
+      this.updateCourse.form = {
+        ids: this.updateCourse.ids,
+        joinTime: [],
+      };
+    },
+    closeAddCourse() {
+      this.course.addOpen = false;
+      this.course.form = {
+        periodId: null,
+        courseId: null,
+        videoIds: []
+      };
+      // 重置表单
+      if (this.$refs.courseAddForm) {
+        this.$refs.courseAddForm.resetFields();
+      }
+    },
+    closeUpdateCourse() {
+      this.course.open = false;
+    },
+    courseChange(row) {
+      this.course.form.videoIds = [];
+      videoList(row).then(response => {
+        this.videoList = response.list
+      });
+    },
+    submitCourseForm() {
+      this.$refs.courseAddForm.validate(valid => {
+        if (valid) {
+          if (this.course.form.timeRange != null && this.course.form.timeRange.length === 2) {
+            this.course.form.startTime = this.course.form.timeRange[0];
+            this.course.form.endTime1 = this.course.form.timeRange[1];
+          }
+          // 提交数据
+          addCourse(this.course.form).then(response => {
+            this.$message.success('添加成功');
+            this.course.addOpen = false;
+            // 重新加载训练营列表
+            this.getCourseList();
+          });
+        }
+      });
+    },
+    submitUpdateCourseForm() {
+      this.$refs.courseUpdateForm.validate(valid => {
+        if (valid) {
+          if (this.updateCourse.form.timeRange != null && this.updateCourse.form.timeRange.length === 2) {
+            this.updateCourse.form.startTime = this.updateCourse.form.timeRange[0];
+            this.updateCourse.form.endTime1 = this.updateCourse.form.timeRange[1];
+          }
+          // 提交数据
+          updateCourseTime(this.updateCourse.form).then(response => {
+            this.$message.success('添加成功');
+            this.updateCourse.open = false;
+            // 重新加载训练营列表
+            this.getCourseList();
+          });
+        }
+      });
+    },
+    updateDate() {
+      updateCourseDate(this.form).then(response => {
+        this.$message.success('修改成功');
+        this.updateDateOpen = false;
+        // 重新加载训练营列表
+        this.getCourseList();
+      });
+    },
+    saveCourseData() {
+      updateListCourseData(this.course.list).then(response => {
+        this.$message.success('保存成功');
+        this.getCourseList();
+      });
+    },
+    setRedPacket(row) {
+      this.currentRedPacketData = {
+        periodId: row.periodId
+        // videoId: row.videoId
+      };
+      this.redPacketVisible = true;
+    },
+    handleRedPacketSuccess() {
+      this.getCourseList();
+    },
+    handlePeriodSettings(row) {
+      this.periodSettingsData = row;
+      this.periodSettingsVisible = true;
+      // 初始化课程列表
+      this.course.queryParams.periodId = row.periodId;
+      // 根据当前激活的tab加载对应数据
+      this.handleTabClick({name: this.activeTab});
+    },
+    // 结束营期
+    handleClosePeriod(row) {
+      const msg = `注: 1.确认结束营期,该营期的开营结束时间改为当天24点。2.当天正在播放中的课程不变。3.第二天如有未开始的课程,统一改为已结束。是否确认结束 ${row.periodName} 营期吗?`
+      this.$confirm(msg, "警告", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      }).then(() => {
+        closePeriod({id: row.periodId}).then(response => {
+          if (response.code === 200) {
+            this.getList()
+          } else {
+            this.$message.error(response.msg)
+          }
+        })
+      }).catch(() => {
+      })
+    },
+    handleBatchRedPacketSuccess() {
+      this.batchRedPacketVisible = false;
+      this.getCourseList();
+    },
+    /** 处理tab切换 */
+    handleTabClick(tab) {
+      if (tab.name === 'course') {
+        this.getCourseList();
+      } else if (tab.name === 'company') {
+        this.redPacketVisible = true;
+      }
+    },
+    /** 上移课程 */
+    handleTop(row) {
+      const currentIndex = this.course.list.findIndex(item => item.id === row.id);
+      if (currentIndex <= 0) {
+        this.$message.warning('已经是第一条数据');
+        return;
+      }
+
+      // 获取上一条数据
+      const prevRow = this.course.list[currentIndex - 1];
+      console.log({
+        id: row.id,
+        targetId: prevRow.id,
+        type: 1 //上移
+      })
+      periodCourseMove({
+        id: row.id,
+        targetId: prevRow.id,
+        type: 1 //上移
+      }).then(response => {
+        if (response.code === 200) {
+          this.$message.success('上移成功');
+          this.getCourseList();
+        } else {
+          this.$message.error(response.msg || '上移失败');
+        }
+      }).catch(() => {
+        this.$message.error('上移失败');
+      });
+    },
+    /** 下移课程 */
+    handleBottom(row) {
+      const currentIndex = this.course.list.findIndex(item => item.id === row.id);
+      if (currentIndex === -1 || currentIndex >= this.course.list.length - 1) {
+        this.$message.warning('已经是最后一条数据');
+        return;
+      }
+
+      // 获取下一条数据
+      const nextRow = this.course.list[currentIndex + 1];
+
+      periodCourseMove({
+        id: row.id,
+        targetId: nextRow.id,
+        type: 2 //下移
+      }).then(response => {
+        if (response.code === 200) {
+          this.$message.success('下移成功');
+          this.getCourseList(); // 重新加载列表
+        } else {
+          this.$message.error(response.msg || '下移失败');
+        }
+      }).catch(() => {
+        this.$message.error('下移失败');
+      });
+    },
+    /** 营期状态格式化 */
+    periodStatusFormatter(row) {
+      const statusMap = {
+        1: '未开始',
+        2: '进行中',
+        3: '已结束'
+      };
+      return statusMap[row.periodStatus] || '未知状态';
+    },
+    /** 开课状态格式化 */
+    courseStatusFormatter(row) {
+      const statusMap = {
+        0: '未开始',
+        1: '进行中',
+        2: '已结束'
+      };
+      return statusMap[row.status] || '未知状态';
+    },
+    /** 营期状态格式化 */
+    handleUpdateDate(row) {
+      this.form = {id: row.id, dayDate: row.dayDate};
+      this.updateDateOpen = true;
+    },
+  },
+};
+</script>
+
+<style scoped>
+.left-aside {
+  background-color: #fff;
+  border-right: 1px solid #EBEEF5;
+  padding: 0;
+  display: flex;
+  flex-direction: column;
+  height: 800px;
+}
+
+.left-header {
+  padding: 10px;
+  border-bottom: 1px solid #EBEEF5;
+}
+
+.left-header-top {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  margin-bottom: 10px;
+}
+
+.search-btn {
+  width: 50%;
+  height: 36px;
+  background-color: #409EFF;
+  color: white;
+  border: none;
+}
+
+.search-input-wrapper {
+  margin-bottom: 10px;
+}
+
+.sort-wrapper {
+  display: flex;
+  align-items: center;
+  margin-bottom: 10px;
+}
+
+.sort-label {
+  width: 70px;
+  font-size: 14px;
+  font-weight: 600;
+  color: #909399;
+}
+
+.sort-select {
+  margin-left: 10px;
+  width: 280px;
+}
+
+.color-wrapper {
+  display: flex;
+  align-items: center;
+  margin-bottom: 10px;
+}
+
+.color-label {
+  width: 70px;
+  color: #606266;
+}
+
+.color-hint {
+  margin-left: 10px;
+  color: #606266;
+  font-size: 12px;
+}
+
+.color-help {
+  margin-left: 5px;
+  color: #909399;
+  cursor: pointer;
+}
+
+.hint-text {
+  color: #606266;
+  font-size: 12px;
+  margin-top: 5px;
+}
+
+.camp-list {
+  flex: 1;
+  overflow-y: auto;
+  padding: 3px;
+}
+
+.camp-item {
+  margin-bottom: 5px;
+  padding: 15px;
+  background-color: #ffffff;
+  position: relative;
+  cursor: pointer;
+  display: flex;
+  justify-content: space-between;
+  border: 1px solid #eaedf2;
+}
+
+.camp-item:last-child {
+  margin-bottom: 0;
+}
+
+.camp-item:hover {
+  background-color: #f5f9ff;
+}
+
+.camp-item.active {
+  background-color: #eaf4ff;
+  border-left: 1px solid #75b8fc;
+}
+
+.camp-content {
+  flex: 1;
+  padding-right: 10px;
+}
+
+.camp-title {
+  font-weight: bold;
+  font-size: 16px;
+  margin-bottom: 8px;
+  color: #333;
+  display: flex;
+  align-items: center;
+}
+
+.camp-icon {
+  font-size: 16px;
+  margin-right: 6px;
+  color: #409EFF;
+}
+
+.camp-info {
+  display: flex;
+  justify-content: space-between;
+  margin-bottom: 8px;
+  font-size: 12px;
+  color: #c4c1c1;
+  line-height: 1.5;
+}
+
+.camp-stats {
+  display: flex;
+  justify-content: space-between;
+  font-size: 12px;
+  color: #666;
+  background-color: #f5f9ff;
+  padding: 6px 10px;
+  border-radius: 4px;
+  line-height: 1.5;
+}
+
+.stat-item {
+  display: flex;
+  align-items: center;
+}
+
+.stat-item i {
+  margin-right: 4px;
+  font-size: 14px;
+  color: #409EFF;
+}
+
+.camp-actions {
+  display: flex;
+  flex-direction: column;
+  justify-content: center;
+  align-items: flex-end;
+  gap: 8px;
+  border-left: 1px dashed #eaedf2;
+  padding-left: 12px;
+  min-width: 50px;
+}
+
+.action-btn {
+  padding: 2px 5px;
+  font-size: 12px;
+  border-radius: 4px;
+  transition: all 0.2s;
+}
+
+.action-btn:hover {
+  background-color: rgba(255, 255, 255, 0.8);
+}
+
+.delete-btn {
+  color: #f56c6c;
+}
+
+.delete-btn:hover {
+  background-color: rgba(245, 108, 108, 0.1);
+}
+
+.copy-btn {
+  color: #409EFF;
+}
+
+.copy-btn:hover {
+  background-color: rgba(64, 158, 255, 0.1);
+}
+
+.warning-icon {
+  color: #E6A23C;
+  font-size: 16px;
+  margin-left: 5px;
+}
+
+.el-main {
+  padding: 10px;
+}
+
+/* 添加训练营表单样式 */
+.drawer-footer {
+  position: absolute;
+  bottom: 0;
+  left: 0;
+  right: 0;
+  padding: 20px;
+  background: #fff;
+  text-align: right;
+  border-top: 1px solid #e8e8e8;
+}
+
+.el-input-number {
+  width: 100%;
+}
+
+/* 加载更多样式 */
+.loading-more {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  padding: 12px 0;
+  color: #909399;
+  font-size: 14px;
+}
+
+.loading-more i {
+  margin-right: 5px;
+  font-size: 16px;
+}
+
+/* 无更多数据提示 */
+.no-more-data {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  padding: 12px 0;
+  color: #c0c4cc;
+  font-size: 13px;
+}
+
+.no-more-data span {
+  position: relative;
+  display: flex;
+  align-items: center;
+}
+</style>

+ 173 - 0
src/views/course/userCoursePeriod/redPacket.vue

@@ -0,0 +1,173 @@
+<template>
+  <div>
+    <!-- 公司列表弹窗 -->
+<!--    <el-dialog title="设置红包" :visible.sync="companyDialogVisible" width="800px" append-to-body>-->
+      <el-table :data="companyList" border>
+        <el-table-column type="index" label="序号" width="60" align="center" />
+        <el-table-column label="公司名称" prop="companyName" align="center" />
+        <el-table-column label="操作" align="center" width="120">
+          <template slot-scope="scope">
+            <el-button
+              size="mini"
+              type="text"
+              @click="handleInputAmount(scope.row)"
+            >设置红包</el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+<!--      <div slot="footer" class="dialog-footer">-->
+<!--      </div>-->
+<!--    </el-dialog>-->
+
+    <!-- 课程红包设置弹窗 -->
+    <el-dialog title="设置红包金额" :visible.sync="courseDialogVisible" width="1200px" append-to-body>
+      <el-table :data="redPacketList" border>
+        <el-table-column type="index" label="序号" width="60" align="center" />
+        <el-table-column label="课程" prop="courseName" align="center" />
+        <el-table-column label="小节" prop="videoName" align="center" />
+        <el-table-column label="营期日期" prop="dayDate" align="center"/>
+        <el-table-column label="红包金额" width="200px" align="center">
+          <template slot-scope="scope">
+            <el-input-number
+              v-model="scope.row.amount"
+              :min="0"
+              :precision="2"
+              :step="0.01"
+              size="small"
+              style="width: 150px"
+            >
+              <template slot="append">元</template>
+            </el-input-number>
+          </template>
+        </el-table-column>
+      </el-table>
+      <div slot="footer" class="dialog-footer">
+        <el-button @click="courseDialogVisible = false">取 消</el-button>
+        <el-button type="primary" @click="handleSave">保 存</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { getPeriodCompanyList, getDays, batchSaveRedPacket, getPeriodRedPacketList } from "@/api/course/userCoursePeriod";
+import redPacket from "@/views/course/userCoursePeriod/redPacket.vue";
+
+export default {
+  name: "RedPacket",
+  computed: {
+    // redPacket() {
+    //   return redPacket
+    // }
+  },
+  props: {
+    visible: {
+      type: Boolean,
+      default: false
+    },
+    activeTab: {
+      type: String,
+      default: ''
+    },
+    periodId: {
+      type: [String, Number],
+      default: ''
+    },
+    // videoId: {
+    //   type: [String, Number],
+    //   default: ''
+    // }
+  },
+  data() {
+    return {
+      // companyDialogVisible: false,
+      // activeTab: '',
+      courseDialogVisible: false,
+      companyList: [],
+      redPacketList: [],
+      currentCompany: null
+    };
+  },
+  created() {
+    if(this.activeTab == "company"){
+      this.getCompanyList();
+    }
+  },
+  watch: {
+    activeTab(val) {
+      this.activeTab = val;
+      if (val == "company") {
+        this.getCompanyList();
+      }
+    },
+    companyDialogVisible(val) {
+      if (!val) {
+        this.$emit('update:visible', false);
+      }
+    }
+  },
+  methods: {
+    // 获取公司列表
+    getCompanyList() {
+      getPeriodCompanyList({
+        periodId: this.periodId
+      }).then(response => {
+        this.companyList = response.data || [];
+      });
+    },
+    // 点击录入金额
+    handleInputAmount(row) {
+      this.currentCompany = row;
+      this.courseDialogVisible = true;
+      this.getCourseList();
+    },
+    // 获取课程列表
+    getCourseList() {
+      getPeriodRedPacketList({
+        periodId: this.periodId,
+        companyId: this.currentCompany.companyId
+      }).then(response => {
+        this.redPacketList = (response.data || []).map(item => ({
+          ...item,
+          amount: item.amount || 0
+        }));
+      });
+    },
+    // 保存红包金额
+    handleSave() {
+      const saveData = this.redPacketList
+        .filter(item => item.amount > 0)
+        .map(item => ({
+          companyId: this.currentCompany.companyId,
+          redPacketMoney: item.amount,
+          videoId: item.videoId,
+          periodId: this.periodId,
+          dataType: 2
+        }));
+
+      if (saveData.length === 0) {
+        this.$message.warning('请至少设置一个红包金额');
+        return;
+      }
+
+      batchSaveRedPacket(saveData).then(response => {
+        if (response.code === 200) {
+          this.$message.success('保存成功');
+          this.courseDialogVisible = false;
+          this.$emit('success');
+        } else {
+          this.$message.error(response.msg || "保存失败");
+        }
+      }).catch(error => {
+        this.$message.error("保存失败:" + error.message);
+      });
+    }
+  }
+};
+</script>
+
+<style scoped>
+.el-input-number {
+  width: 100%;
+}
+</style>

+ 338 - 0
src/views/course/userCoursePeriod/statistics.vue

@@ -0,0 +1,338 @@
+<template>
+  <div class="statistics-container">
+    <!-- 营期课程选择 -->
+    <div class="fixed-header">
+      <el-form :inline="true" :model="queryParams" class="demo-form-inline">
+        <el-form-item label="营期课程">
+          <el-select
+            v-model="queryParams.videoIdList"
+            multiple
+            placeholder="请选择营期课程"
+            style="width: 400px"
+          >
+            <el-option
+              v-for="item in courseOptions"
+              :key="item.videoId"
+              :label="item.videoName"
+              :value="item.videoId"
+            />
+          </el-select>
+        </el-form-item>
+        <el-form-item>
+          <el-button type="primary" @click="handleQuery">查询</el-button>
+        </el-form-item>
+      </el-form>
+
+      <!-- 统计数据展示 -->
+      <el-row :gutter="20" class="statistics-row">
+        <el-col :span="3">
+          <div class="statistics-item">
+            <div class="statistics-title">完播人数</div>
+            <div class="statistics-value">{{ statistics.courseCompleteNum || 0 }}</div>
+          </div>
+        </el-col>
+        <el-col :span="3">
+          <div class="statistics-item">
+            <div class="statistics-title">观看人数</div>
+            <div class="statistics-value">{{ statistics.courseWatchNum || 0 }}</div>
+          </div>
+        </el-col>
+        <el-col :span="3">
+          <div class="statistics-item">
+            <div class="statistics-title">完播率</div>
+            <div class="statistics-value">{{ statistics.completeRate || '0%' }}</div>
+          </div>
+        </el-col>
+        <el-col :span="3">
+          <div class="statistics-item">
+            <div class="statistics-title">观看总次数</div>
+            <div class="statistics-value">{{ statistics.courseWatchTimes || 0 }}</div>
+          </div>
+        </el-col>
+        <el-col :span="3">
+          <div class="statistics-item">
+            <div class="statistics-title">答题总次数</div>
+            <div class="statistics-value">{{ statistics.answerTimes || 0 }}</div>
+          </div>
+        </el-col>
+        <el-col :span="3">
+          <div class="statistics-item">
+            <div class="statistics-title">答题正确总次数</div>
+            <div class="statistics-value">{{ statistics.answerRightTimes || 0 }}</div>
+          </div>
+        </el-col>
+        <el-col :span="3">
+          <div class="statistics-item">
+            <div class="statistics-title">奖励金额总计(元)</div>
+            <div class="statistics-value">{{ statistics.redPacketAmount || 0 }}</div>
+          </div>
+        </el-col>
+      </el-row>
+    </div>
+
+    <!-- 列表统计展示 -->
+    <div class="table-wrapper">
+      <el-table v-loading="loading" :data="list" border height="calc(100vh - 450px)">
+        <el-table-column type="index" label="序号" width="50" align="center" fixed/>
+        <el-table-column prop="title" label="课程名称" align="center" min-width="250" fixed/>
+        <el-table-column prop="dayDate" label="营期日期" align="center" min-width="120" fixed/>
+        <el-table-column prop="countDetailsVO.courseWatchTimes" label="观看次数" align="center" min-width="100"/>
+        <el-table-column prop="countDetailsVO.courseCompleteTimes" label="完播次数" align="center" min-width="100"/>
+        <el-table-column prop="countDetailsVO.courseWatchNum" label="观看人数" align="center" min-width="100"/>
+        <el-table-column prop="countDetailsVO.courseCompleteNum" label="完播人数" align="center" min-width="100"/>
+        <el-table-column prop="countDetailsVO.completeRate" label="完播率" align="center" min-width="100">
+          <template slot-scope="scope">
+            {{ scope.row.countDetailsVO.completeRate || 0 }}%
+          </template>
+        </el-table-column>
+        <el-table-column prop="countDetailsVO.answerTimes" label="答题次数" align="center" min-width="100"/>
+        <el-table-column prop="countDetailsVO.answerNum" label="答题人数" align="center" min-width="100"/>
+        <el-table-column prop="countDetailsVO.answerRightNum" label="正确人数" align="center" min-width="100"/>
+        <el-table-column prop="countDetailsVO.answerRightRate" label="正确率" align="center" min-width="100">
+          <template slot-scope="scope">
+            {{ scope.row.countDetailsVO.answerRightRate || 0 }}%
+          </template>
+        </el-table-column>
+        <el-table-column prop="countDetailsVO.redPacketNum" label="答题红包个数" align="center" min-width="120"/>
+        <el-table-column prop="countDetailsVO.redPacketAmount" label="答题红包金额(元)" align="center" min-width="150"/>
+      </el-table>
+
+      <!-- 分页 -->
+      <div class="custom-pagination-container">
+        <pagination
+          v-show="total > 0"
+          :total="total"
+          :page.sync="queryParams.pageNum"
+          :limit.sync="queryParams.pageSize"
+          @pagination="getCountList"
+        />
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import {getDays, periodCountSelect} from "@/api/course/userCoursePeriod";
+
+export default {
+  name: "CourseStatistics",
+  props: {
+    periodId: {
+      type: [String, Number],
+      default: ''
+    },
+    active: {
+      type: Boolean,
+      default: false
+    }
+  },
+  data() {
+    return {
+      // 遮罩层
+      loading: false,
+      // 总条数
+      total: 0,
+      // 课程选项
+      courseOptions: [],
+      // 统计数据
+      statistics: {
+        courseCompleteNum: 0,
+        courseWatchNum: 0,
+        completeRate: '0%',
+        courseWatchTimes: 0,
+        answerTimes: 0,
+        answerRightTimes: 0,
+        redPacketAmount: 0
+      },
+      // 列表数据
+      list: [],
+      // 查询参数
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        videoIdList: [],
+        // videoId: '',
+        periodId: ''
+      },
+      // 是否已初始化
+      initialized: false
+    };
+  },
+  watch: {
+    periodId: {
+      handler(newVal) {
+        this.queryParams.periodId = newVal;
+        if (this.active && !this.initialized) {
+          this.initializeData();
+        }
+      },
+      immediate: true
+    },
+    active: {
+      handler(newVal) {
+        if (newVal && !this.initialized) {
+          this.initializeData();
+        }
+      },
+      immediate: true
+    }
+  },
+  methods: {
+    /** 初始化数据 */
+    initializeData() {
+      this.getCourseOptions();
+      this.getCountList();
+      this.initialized = true;
+    },
+    /** 获取课程选项 */
+    getCourseOptions() {
+      this.loading = true;
+      getDays(this.queryParams).then(r => {
+        if (r.code === 200) {
+          this.courseOptions = r.rows;
+          this.loading = false;
+        } else {
+          this.$message.error(r.msg || '获取数据失败');
+        }
+        this.loading = false;
+      }).catch(() => {
+        this.loading = false;
+      });
+    },
+    /** 查询按钮操作 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getCountList();
+    },
+    /** 课程选择变化 */
+    handleCourseChange() {
+    },
+    /** 获取列表数据 */
+    getCountList() {
+      this.loading = true;
+      periodCountSelect(this.queryParams).then(response => {
+        if (response.code === 200) {
+          // 设置列表数据
+          this.list = response.rows;
+          this.total = response.total || 0;
+
+          // 计算总统计数据
+          this.calculateTotalStatistics();
+
+          console.log('列表数据:', this.list);
+        } else {
+          this.$message.error(response.msg || '获取数据失败');
+        }
+        this.loading = false;
+      }).catch(error => {
+        console.error('获取数据失败:', error);
+        this.$message.error('获取数据失败');
+        this.loading = false;
+      });
+    },
+    /** 计算总统计数据 */
+    calculateTotalStatistics() {
+      // 初始化统计数据
+      this.statistics = {
+        courseCompleteNum: 0,
+        courseWatchNum: 0,
+        completeRate: '0%',
+        courseWatchTimes: 0,
+        answerTimes: 0,
+        answerRightTimes: 0,
+        redPacketAmount: 0
+      };
+
+      // 如果没有数据,直接返回
+      if (!this.list || this.list.length === 0) {
+        return;
+      }
+
+      // 遍历列表数据,累加各项统计数据
+      this.list.forEach(item => {
+        const details = item.countDetailsVO || {};
+
+        // 累加各项数据
+        this.statistics.courseCompleteNum += details.courseCompleteNum || 0;
+        this.statistics.courseWatchNum += details.courseWatchNum || 0;
+        this.statistics.courseWatchTimes += details.courseWatchTimes || 0;
+        this.statistics.answerTimes += details.answerTimes || 0;
+        this.statistics.answerRightTimes += details.answerRightNum || 0;
+        this.statistics.redPacketAmount += details.redPacketAmount || 0;
+      });
+
+      // 计算完播率
+      if (this.statistics.courseWatchNum > 0) {
+        const rate = (this.statistics.courseCompleteNum / this.statistics.courseWatchNum * 100).toFixed(2);
+        this.statistics.completeRate = rate + '%';
+      }
+    }
+  }
+};
+</script>
+
+<style scoped>
+.statistics-container {
+  height: 100%;
+  overflow: hidden;
+  position: relative;
+}
+
+.fixed-header {
+  position: sticky;
+  top: 0;
+  z-index: 10;
+  background-color: #fff;
+  padding: 10px 0;
+  border-bottom: 1px solid #EBEEF5;
+}
+
+.table-wrapper {
+  height: calc(100% - 220px);
+  overflow: visible;
+  position: relative;
+}
+
+.custom-pagination-container {
+  padding: 10px 0 12px 0;
+  text-align: right;
+  background-color: #fff;
+  position: relative;
+  z-index: 1;
+}
+
+/* 覆盖原有的pagination-container样式 */
+:deep(.pagination-container) {
+  height: auto !important;
+  margin-bottom: 0 !important;
+  margin-top: 0 !important;
+  padding: 0 !important;
+}
+
+.statistics-row {
+  margin: 20px 0;
+}
+
+.statistics-item {
+  background-color: #f5f7fa;
+  border-radius: 4px;
+  padding: 15px;
+  text-align: center;
+  height: 100px;
+  display: flex;
+  flex-direction: column;
+  justify-content: center;
+}
+
+.statistics-title {
+  font-size: 14px;
+  color: #606266;
+  margin-bottom: 10px;
+}
+
+.statistics-value {
+  font-size: 20px;
+  font-weight: bold;
+  color: #303133;
+}
+</style>

+ 2 - 2
src/views/fastGpt/fastGptRole/fastGptRoleUpdate.vue

@@ -21,10 +21,10 @@
                 <ImageUpload v-model="form.avatar" type="image" :num="1" :width="150" :height="150" style="margin-top: 1%;" />
               </el-form-item>
               <el-form-item label="APPKey"  >
-                <el-input type="textarea" v-model="form.modeConfigJson.APPKey" placeholder="请输入APPKey(特定key)" />
+                <el-input type="textarea" v-model="form.modeConfigJson.APPKey" placeholder="请输入FastGPT的APPKey(特定key)" />
               </el-form-item>
               <el-form-item  label="提示词"  >
-                <el-input type="textarea" :rows="3" v-model="form.reminderWords" placeholder="请输入提示词" />
+                <el-input type="textarea" :rows="3" v-model="form.reminderWords" placeholder="请输入FastGPT的提示词" />
               </el-form-item>
 <!--              <el-form-item  label="标签人设"  >
                 <div v-if="tagsFormList.length > 0" style="display: flex; align-items: center; flex-wrap: wrap; width: 100%;">

+ 1 - 0
src/views/login.vue

@@ -53,6 +53,7 @@
     </div>
     <!--  底部  -->
     <div class="el-login-footer">
+      <span>弘珍医药医药有限公司 </span>
       <a href="https://beian.miit.gov.cn" target="_bank">蜀ICP备2023036719号-2</a>
     </div>
   </div>

+ 188 - 186
src/views/qw/QwWorkTask/index.vue

@@ -1,18 +1,36 @@
 <template>
   <div class="app-container">
     <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
-      <el-form-item label="企微账号" prop="qwUserId">
-              <el-select v-model="queryParams.qwUserId" placeholder="企微账号"  size="small" @change="updateQwuser()">
-                <el-option
-                  v-for="dict in myQwUserList"
-                  :key="dict.dictValue"
-                  :label="dict.dictLabel+'('+dict.corpName+')'"
-                  :value="dict.dictValue"
-                />
-              </el-select>
+      <el-form-item label="外部联系人id" prop="extId">
+        <el-input
+          v-model="queryParams.extId"
+          placeholder="请输入外部联系人id"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="企微用户id" prop="qwUserId">
+        <el-input
+          v-model="queryParams.qwUserId"
+          placeholder="请输入企微用户id"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="状态 0 待处理 1 已处理 3 过期" prop="status">
+        <el-select v-model="queryParams.status" placeholder="请选择状态 0 待处理 1 已处理 3 过期" clearable size="small">
+          <el-option
+            v-for="dict in statusOptions"
+            :key="dict.dictValue"
+            :label="dict.dictLabel"
+            :value="dict.dictValue"
+          />
+        </el-select>
       </el-form-item>
-      <el-form-item label="类别" prop="type">
-        <el-select v-model="queryParams.type" placeholder="请选择类别" clearable size="small">
+      <el-form-item label="类别 1先导 2 课程 3 大小转 4 转人工" prop="type">
+        <el-select v-model="queryParams.type" placeholder="请选择类别 1先导 2 课程 3 大小转 4 转人工" clearable size="small">
           <el-option
             v-for="dict in typeOptions"
             :key="dict.dictValue"
@@ -21,19 +39,25 @@
           />
         </el-select>
       </el-form-item>
-	  
-	  <el-form-item label="处理状态" prop="trackType">
-	    <el-select v-model="queryParams.trackType" placeholder="处理状态" clearable size="small">
-	      <el-option
-	        v-for="dict in trackTypeOptions"
-	        :key="dict.dictValue"
-	        :label="dict.dictLabel"
-	        :value="dict.dictValue"
-	      />
-	    </el-select>
-	  </el-form-item>
-	  
-      <el-form-item label="sop编号" prop="sopId">
+      <el-form-item label="标题" prop="title">
+        <el-input
+          v-model="queryParams.title"
+          placeholder="请输入标题"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="分值" prop="score">
+        <el-input
+          v-model="queryParams.score"
+          placeholder="请输入分值"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="sopid" prop="sopId">
         <el-input
           v-model="queryParams.sopId"
           placeholder="请输入sopid"
@@ -42,91 +66,114 @@
           @keyup.enter.native="handleQuery"
         />
       </el-form-item>
+      <el-form-item label="公司id" prop="companyId">
+        <el-input
+          v-model="queryParams.companyId"
+          placeholder="请输入公司id"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="用户id" prop="companyUserId">
+        <el-input
+          v-model="queryParams.companyUserId"
+          placeholder="请输入用户id"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
       <el-form-item>
         <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
         <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
       </el-form-item>
     </el-form>
 
+    <el-row :gutter="10" class="mb8">
+      <el-col :span="1.5">
+        <el-button
+          type="primary"
+          plain
+          icon="el-icon-plus"
+          size="mini"
+          @click="handleAdd"
+          v-hasPermi="['qw:QwWorkTask:add']"
+        >新增</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="success"
+          plain
+          icon="el-icon-edit"
+          size="mini"
+          :disabled="single"
+          @click="handleUpdate"
+          v-hasPermi="['qw:QwWorkTask:edit']"
+        >修改</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="danger"
+          plain
+          icon="el-icon-delete"
+          size="mini"
+          :disabled="multiple"
+          @click="handleDelete"
+          v-hasPermi="['qw:QwWorkTask:remove']"
+        >删除</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="warning"
+          plain
+          icon="el-icon-download"
+          size="mini"
+          :loading="exportLoading"
+          @click="handleExport"
+          v-hasPermi="['qw:QwWorkTask:export']"
+        >导出</el-button>
+      </el-col>
       <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
     </el-row>
-	<el-tabs type="card" v-model="actName" @tab-click="handleClickX">
-	  <el-tab-pane v-for="(item,index) in statusOptions" :label="item.dictLabel" :name="item.dictValue"></el-tab-pane>
-	</el-tabs>
+
     <el-table border v-loading="loading" :data="QwWorkTaskList" @selection-change="handleSelectionChange">
       <el-table-column type="selection" width="55" align="center" />
-      <el-table-column label="客户昵称" align="center" prop="name" />
-      <el-table-column label="企微账号" align="center" prop="qwUserName" />
-      <el-table-column label="状态" align="center" prop="status">
-		 <template slot-scope="scope">
-		   <dict-tag :options="statusOptions" :value="scope.row.status"/>
-		 </template>
-      </el-table-column>
-      <el-table-column label="类别" align="center" prop="type">
+      <el-table-column label="id" align="center" prop="id" />
+      <el-table-column label="外部联系人id" align="center" prop="extId" />
+      <el-table-column label="企微用户id" align="center" prop="qwUserId" />
+      <el-table-column label="状态 0 待处理 1 已处理 3 过期" align="center" prop="status">
         <template slot-scope="scope">
-          <dict-tag :options="typeOptions" :value="scope.row.type"/>
+          <dict-tag :options="statusOptions" :value="scope.row.status"/>
         </template>
       </el-table-column>
-	  <el-table-column label="处理状态" align="center" prop="trackType">
-	    <template slot-scope="scope">
-	      <dict-tag :options="trackTypeOptions" :value="scope.row.trackType"/>
-	    </template>
-	  </el-table-column>
-      <el-table-column label="标题" align="center" prop="title" />
-      <el-table-column label="描述" align="center" prop="description" />
-      <el-table-column label="分值" align="center" prop="score">
+      <el-table-column label="类别 1先导 2 课程 3 大小转 4 转人工" align="center" prop="type">
         <template slot-scope="scope">
-          <span :style="getScoreStyle(scope.row.score)">{{ scope.row.score }}</span>
+          <dict-tag :options="typeOptions" :value="scope.row.type"/>
         </template>
       </el-table-column>
-	  <el-table-column label="用户过往看课记录" align="center" width="200px">
-	    <template slot-scope="scope">
-	      <div style="display: flex; gap: 4px; justify-content: center;">
-	        <span 
-	          v-for="(log, index) in scope.row.logs" 
-	          :key="index"
-	          :style="{
-	            display: 'inline-block',
-	            width: '16px',
-	            height: '16px',
-	            borderRadius: '2px',
-	            backgroundColor: 
-	              log === 2 ? '#67C23A' : 
-				  log === 3 ? '#f55a4f' : 
-				  log === 4 ? '#FFD700' : 
-				  '#909399'
-	          }"
-	        ></span>
-	      </div>
-	    </template>
-	  </el-table-column>
-	    <el-table-column label="最晚看课时间" align="center">
-	        <template slot-scope="scope">
-	          {{ formatTime(scope.row.lastWatchTime) }}
-	        </template>
-	      </el-table-column>
-	  
-      <el-table-column label="sopId" align="center" prop="sopId" />
-      <el-table-column label="创建时间" align="center" prop="createTime" />
-      <el-table-column label="修改时间" align="center" prop="updateTime" />
+      <el-table-column label="标题" align="center" prop="title" />
+      <el-table-column label="备注" align="center" prop="remark" />
+      <el-table-column label="分值" align="center" prop="score" />
+      <el-table-column label="sopid" align="center" prop="sopId" />
+      <el-table-column label="公司id" align="center" prop="companyId" />
+      <el-table-column label="用户id" align="center" prop="companyUserId" />
       <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
         <template slot-scope="scope">
-          <el-button v-if="scope.row.status==0"
+          <el-button
             size="mini"
             type="text"
             icon="el-icon-edit"
             @click="handleUpdate(scope.row)"
-          >处理</el-button>
-		  <el-button v-if="scope.row.status==0"
-		    size="mini"
-		    type="text"
-		    @click="handleUpdate2(scope.row)"
-		  >未接通</el-button>
-		  <el-button v-if="scope.row.status==0"
-		    size="mini"
-		    type="text"
-		    @click="handleUpdate3(scope.row)"
-		  >接通</el-button>
+            v-hasPermi="['qw:QwWorkTask:edit']"
+          >修改</el-button>
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-delete"
+            @click="handleDelete(scope.row)"
+            v-hasPermi="['qw:QwWorkTask:remove']"
+          >删除</el-button>
         </template>
       </el-table-column>
     </el-table>
@@ -142,18 +189,49 @@
     <!-- 添加或修改企微任务看板对话框 -->
     <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
       <el-form ref="form" :model="form" :rules="rules" label-width="80px">
-		<el-form-item label="处理类型" prop="trackType">
-		  <el-select v-model="form.trackType" placeholder="状态" clearable size="small">
-			  <el-option
-				v-for="dict in trackTypeOptions"
-				:key="dict.dictValue"
-				:label="dict.dictLabel"
-				:value="dict.dictValue"
-			  />
-		  </el-select>
-		</el-form-item> 
-        <el-form-item label="描述" prop="description">
-          <el-input  v-model="form.description" placeholder="请输入描述"  type="textarea" :rows="3"/>
+        <el-form-item label="外部联系人id" prop="extId">
+          <el-input v-model="form.extId" placeholder="请输入外部联系人id" />
+        </el-form-item>
+        <el-form-item label="企微用户id" prop="qwUserId">
+          <el-input v-model="form.qwUserId" placeholder="请输入企微用户id" />
+        </el-form-item>
+        <el-form-item label="状态 0 待处理 1 已处理 3 过期" prop="status">
+          <el-select v-model="form.status" placeholder="请选择状态 0 待处理 1 已处理 3 过期">
+            <el-option
+              v-for="dict in statusOptions"
+              :key="dict.dictValue"
+              :label="dict.dictLabel"
+              :value="parseInt(dict.dictValue)"
+            ></el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item label="类别 1先导 2 课程 3 大小转 4 转人工" prop="type">
+          <el-select v-model="form.type" placeholder="请选择类别 1先导 2 课程 3 大小转 4 转人工">
+            <el-option
+              v-for="dict in typeOptions"
+              :key="dict.dictValue"
+              :label="dict.dictLabel"
+              :value="parseInt(dict.dictValue)"
+            ></el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item label="标题" prop="title">
+          <el-input v-model="form.title" placeholder="请输入标题" />
+        </el-form-item>
+        <el-form-item label="备注" prop="remark">
+          <el-input v-model="form.remark" placeholder="请输入备注" />
+        </el-form-item>
+        <el-form-item label="分值" prop="score">
+          <el-input v-model="form.score" placeholder="请输入分值" />
+        </el-form-item>
+        <el-form-item label="sopid" prop="sopId">
+          <el-input v-model="form.sopId" placeholder="请输入sopid" />
+        </el-form-item>
+        <el-form-item label="公司id" prop="companyId">
+          <el-input v-model="form.companyId" placeholder="请输入公司id" />
+        </el-form-item>
+        <el-form-item label="用户id" prop="companyUserId">
+          <el-input v-model="form.companyUserId" placeholder="请输入用户id" />
         </el-form-item>
       </el-form>
       <div slot="footer" class="dialog-footer">
@@ -165,20 +243,18 @@
 </template>
 
 <script>
-import { listQwWorkTask, getQwWorkTask, delQwWorkTask, addQwWorkTask, updateQwWorkTask, exportQwWorkTask,updateQwWorkTask2,updateQwWorkTask3 } from "@/api/qw/QwWorkTask";
-import {getMyQwUserList, getMyQwCompanyList, handleInputAuthAppKey, updateUser} from "@/api/qw/user";
+import { listQwWorkTask, getQwWorkTask, delQwWorkTask, addQwWorkTask, updateQwWorkTask, exportQwWorkTask } from "@/api/qw/QwWorkTask";
+
 export default {
   name: "QwWorkTask",
   data() {
     return {
-	  actName:"0",
       // 遮罩层
       loading: true,
       // 导出遮罩层
       exportLoading: false,
       // 选中数组
       ids: [],
-	  myQwUserList:[],
       // 非单个禁用
       single: true,
       // 非多个禁用
@@ -195,7 +271,6 @@ export default {
       open: false,
       // 状态 0 待处理 1 已处理 3 过期字典
       statusOptions: [],
-	  trackTypeOptions:[],
       // 类别 1先导 2 课程 3 大小转 4 转人工字典
       typeOptions: [],
       // 查询参数
@@ -204,7 +279,7 @@ export default {
         pageSize: 10,
         extId: null,
         qwUserId: null,
-        status: 0,
+        status: null,
         type: null,
         title: null,
         score: null,
@@ -216,59 +291,19 @@ export default {
       form: {},
       // 表单校验
       rules: {
-		   trackType: [
-		      { required: true, message: '请选择处理类型', trigger: 'change' }
-		    ]
       }
     };
   },
   created() {
-	this.handleGetMyQwUserList();
-    this.getDicts("sys_qw_work_task_status").then(response => {
+    this.getList();
+    this.getDicts("sys_company_status").then(response => {
       this.statusOptions = response.data;
     });
-    this.getDicts("sys_qw_work_task_type").then(response => {
+    this.getDicts("sys_company_status").then(response => {
       this.typeOptions = response.data;
     });
-	this.getDicts("sys_qw_work_task_track_type").then(response => {
-	  this.trackTypeOptions = response.data;
-	});
-	
-
   },
   methods: {
-	getScoreStyle(score) {
-	let backgroundColor = '';
-	  if (score >= 15) {
-		backgroundColor = '#ff4d4f';    // 红色
-	  } else if (score >= 9) {
-		backgroundColor = '#ff7d45';    // 橘红
-	  } else if (score >= 4) {
-		backgroundColor = '#ffec3d';    // 黄色
-	  } else {
-		backgroundColor = '#ffffff';    // 白色
-	  }
-	  return { 
-		'background-color': backgroundColor,
-		'padding': '5px 10px',
-		'border-radius': '4px'
-	  };
-	},
-	formatTime(timeStr) {
-	      if (!timeStr && timeStr !== 0) return '';
-	      
-	      // 处理数字和字符串输入
-	      const str = String(timeStr).padStart(4, '0');
-	      
-	      // 提取有效部分
-	      const hours = str.substring(0, 2);
-	      const minutes = str.substring(2, 4);
-	      
-	      // 简单验证
-	      if (hours > 23 || minutes > 59) return '无效时间';
-	      
-	      return `${hours}:${minutes}`;
-	    },
     /** 查询企微任务看板列表 */
     getList() {
       this.loading = true;
@@ -278,10 +313,6 @@ export default {
         this.loading = false;
       });
     },
-	handleClickX(tab, event) {
-	  this.queryParams.status=tab.name;
-	  this.handleQuery();
-	},
     // 取消按钮
     cancel() {
       this.open = false;
@@ -293,7 +324,7 @@ export default {
         id: null,
         extId: null,
         qwUserId: null,
-        status: 0,
+        status: null,
         type: null,
         title: null,
         remark: null,
@@ -311,18 +342,6 @@ export default {
       this.queryParams.pageNum = 1;
       this.getList();
     },
-	handleGetMyQwUserList(){
-	
-	  getMyQwUserList().then(response => {
-	    this.myQwUserList = response.data;
-	    if(this.myQwUserList!=null){
-	      this.queryParams.qwUserId=this.myQwUserList[0].dictValue
-	      this.queryParams.corpId=this.myQwUserList[0].corpId
-	      this.getList();
-	    }
-	  });
-	
-	},
     /** 重置按钮操作 */
     resetQuery() {
       this.resetForm("queryForm");
@@ -344,29 +363,12 @@ export default {
     handleUpdate(row) {
       this.reset();
       const id = row.id || this.ids
-        this.form = row;
+      getQwWorkTask(id).then(response => {
+        this.form = response.data;
         this.open = true;
-        this.title = "处理任务";
-
+        this.title = "修改企微任务看板";
+      });
     },
-	
-	handleUpdate2(row) {
-	  var from={id:row.id }
-	  	updateQwWorkTask2(from).then(response => {
-	    this.msgSuccess("修改成功");
-
-	    this.getList();
-	  });
-	
-	},
-	handleUpdate3(row) {
-	  var from={id:row.id }
-		updateQwWorkTask3(from).then(response => {
-	  this.msgSuccess("修改成功");
-	
-	  this.getList();
-	});
-	},
     /** 提交按钮 */
     submitForm() {
       this.$refs["form"].validate(valid => {

+ 73 - 35
src/views/qw/autoTags/dayPartingIndex.vue

@@ -64,12 +64,10 @@
               </span>
           </template>
         </el-table-column>
-        <el-table-column label="添加的标签" align="center" prop="rulesTags">
+        <el-table-column label="添加的标签" align="center" prop="tagIdsName">
           <template slot-scope="scope">
-            <div>
-              <div v-for="tagId in scope.row.tagsSet" :key="tagId" style="display: inline;">
-                <el-tag :disable-transitions="false"  v-for="list in tagList" :key="list.id" style="margin: 3px;" v-if="list.tagId==tagId">{{list.name}}</el-tag>
-              </div>
+            <div v-for="name in scope.row.tagIdsName" style="display: inline;">
+              <el-tag type="success">{{ name }}</el-tag>
             </div>
           </template>
         </el-table-column>
@@ -258,8 +256,8 @@
 
       <el-dialog title="添加标签" :visible.sync="tagChange.open" width="800px" append-to-body>
         <div>搜索标签:
-          <el-input v-model="tagChange.tagName" placeholder="请输入标签名称" clearable size="small" style="width: 200px;margin-right: 10px" />
-          <el-button type="primary" icon="el-icon-search" size="mini" @click="handleSearchTags(tagChange.tagName)">搜索</el-button>
+          <el-input v-model="queryTagParams.name" placeholder="请输入标签名称" clearable size="small" style="width: 200px;margin-right: 10px" />
+          <el-button type="primary" icon="el-icon-search" size="mini" @click="handleSearchTags">搜索</el-button>
           <el-button type="primary" icon="el-icon-plus" size="mini" @click="cancelSearchTags">重置</el-button>
         </div>
         <div v-for="item in tagGroupList" :key="item.id" >
@@ -277,6 +275,13 @@
             </a>
           </div>
         </div>
+        <pagination
+          v-show="tagTotal>0"
+          :total="tagTotal"
+          :page.sync="queryTagParams.pageNum"
+          :limit.sync="queryTagParams.pageSize"
+          @pagination="getPageListTagGroup"
+        />
         <div slot="footer" class="dialog-footer">
           <el-button type="primary" @click="addTagSubmitForm(tagChange.index)">确 定</el-button>
           <el-button @click="addTagCancel(tagChange.index)">重 置</el-button>
@@ -294,13 +299,13 @@
 </template>
 
 <script>
-import { listTags,delTags, addTags, updateTags } from "@/api/qw/autoTags";
+import { listTags,delTags, addTags, updateTags } from "../../../api/qw/autoTags";
 import qwUserList from '@/views/qw/user/qwUserList.vue'
 import {listTag, searchTags} from '@/api/qw/tag'
 import dayPartingIndexDetails from '@/views/qw/autoTags/dayPartingIndexDetails.vue'
 import { allListTagGroup } from '@/api/qw/tagGroup'
 import { listUser } from '@/api/qw/user'
-import { getMyQwUserList,getMyQwCompanyList } from "@/api/qw/user";
+import { getMyQwUserList,getMyQwCompanyList } from "../../../api/qw/user";
 export default {
   name: "autoTags",
   components: { dayPartingIndexDetails, qwUserList },
@@ -315,6 +320,7 @@ export default {
       showSearch: true,
       // 总条数
       total: 0,
+      tagTotal:0,
       // 自动打标签主表格数据
       dayPartingIndexList: [],
       // 弹出层标题
@@ -340,6 +346,13 @@ export default {
         index:null,
       },
 
+      queryTagParams: {
+        pageNum: 1,
+        pageSize: 10,
+        total:0,
+        name:null,
+        corpId:null,
+      },
       //选择成员列表
       listUser:{
         title:"",
@@ -478,6 +491,14 @@ export default {
       this.reset();
       this.open = true;
       this.title = "添加规则";
+
+      this.getPageListTagGroup()
+
+      //所有的标签
+      listTag(this.queryTagParams).then(response => {
+        this.tagList = response.rows;
+      });
+
     },
 
     /**
@@ -485,20 +506,24 @@ export default {
     */
     afreshData(value){
 
-      //所有的标签分组
-      allListTagGroup({corpId:value}).then(response => {
-        this.tagGroupList = response.rows;
-      });
-
-      //所有的标签
-      listTag({corpId:value}).then(response => {
-        this.tagList = response.rows;
-      });
+      this.resetSearchQueryTag()
+      this.queryTagParams.corpId=value;
 
       //所有的员工
       listUser({corpId:value}).then(res=>{
         this.userList=res.rows;
       })
+
+    },
+
+    resetSearchQueryTag(){
+
+      this.queryTagParams= {
+        pageNum: 1,
+        pageSize: 10,
+        total:0,
+        name:null,
+      };
     },
 
     //选择群发的企业成员账号
@@ -524,13 +549,27 @@ export default {
 
 
     },
-    handleSearchTags(name){
+    handleSearchTags(){
 
-      searchTags({name:name,corpId:this.queryParams.corpId}).then(response => {
+      this.queryTagParams.corpId=this.queryParams.corpId;
+      searchTags(this.queryTagParams).then(response => {
         this.tagGroupList = response.rows;
       });
 
     },
+
+    getPageListTagGroup(){
+
+      this.queryTagParams.corpId=this.queryParams.corpId;
+
+      allListTagGroup(this.queryTagParams).then(response => {
+        this.tagGroupList = response.rows;
+        this.tagTotal = response.total;
+      });
+    },
+
+
+
     cancelSearchTags(){
       this.afreshData(this.queryParams.corpId)
     },
@@ -550,20 +589,20 @@ export default {
       listTags(this.queryParams).then(response => {
 
         this.dayPartingIndexList = response.rows;
-        this.dayPartingIndexList.forEach(item => {
-          const tagsSet = new Set(); // 为每个项目创建一个新的 Set
-          try {
-            const data = JSON.parse(item.rulesTags); // 将每个 rulesTags JSON 字符串解析为 JavaScript 对象
-            data.forEach(entry => {
-              entry.tags.forEach(tag => {
-                tagsSet.add(tag); // 将每个 tag 添加到 Set 中
-              });
-            });
-          } catch (error) {
-            this.$message.error("Error parsing JSON:",error)
-          }
-          item.tagsSet = Array.from(tagsSet); // 将 Set 转换为数组并添加到当前项目
-        });
+        // this.dayPartingIndexList.forEach(item => {
+        //   const tagsSet = new Set(); // 为每个项目创建一个新的 Set
+        //   try {
+        //     const data = JSON.parse(item.rulesTags); // 将每个 rulesTags JSON 字符串解析为 JavaScript 对象
+        //     data.forEach(entry => {
+        //       entry.tags.forEach(tag => {
+        //         tagsSet.add(tag); // 将每个 tag 添加到 Set 中
+        //       });
+        //     });
+        //   } catch (error) {
+        //     this.$message.error("Error parsing JSON:",error)
+        //   }
+        //   item.tagsSet = Array.from(tagsSet); // 将 Set 转换为数组并添加到当前项目
+        // });
 
         this.total = response.total;
         this.loading = false;
@@ -702,7 +741,6 @@ export default {
     /** 详情按钮操作 */
     handleDetails(row) {
 
-      console.log("this.row",row)
       this.reset();
 
       // 深拷贝表单数据

+ 9 - 9
src/views/qw/autoTags/dayPartingIndexDetails.vue

@@ -24,11 +24,11 @@
                       <el-tag :disable-transitions="false"  v-for="list in userList" :key="list.id" style="margin: 3px;" v-if="list.id==userId">{{list.nickName}}</el-tag>
                 </span>
               </el-descriptions-item>
-              <el-descriptions-item label="添加的标签" labelStyle="width: 80px">
-                <span v-for="tagId in groupIndexFrom.tagsSet" :key="tagId" style="display: inline;width: 300px">
-                      <el-tag :disable-transitions="false"  v-for="list in tagList" :key="list.id" style="margin: 3px;" v-if="list.tagId==tagId">{{list.name}}</el-tag>
-                </span>
-              </el-descriptions-item>
+<!--              <el-descriptions-item label="添加的标签" labelStyle="width: 80px">-->
+<!--                <span v-for="tagId in groupIndexFrom.tagsSet" :key="tagId" style="display: inline;width: 300px">-->
+<!--                      <el-tag :disable-transitions="false"  v-for="list in tagList" :key="list.id" style="margin: 3px;" v-if="list.tagId==tagId">{{list.name}}</el-tag>-->
+<!--                </span>-->
+<!--              </el-descriptions-item>-->
               <el-descriptions-item label="创建时间">{{groupIndexFrom.createTime}}</el-descriptions-item>
               <el-descriptions-item label="规则状态">
                 <el-switch
@@ -145,11 +145,11 @@
             <el-table-column label="客户名称" align="center" prop="externalUserName" />
             <el-table-column label="所属企微员工" align="center" prop="qwUsername" />
             <el-table-column label="所属销售" align="center" prop="companyName" />
-            <el-table-column label="添加的标签" align="center" prop="effectiveRules" >
+            <el-table-column label="添加的标签" align="center" prop="tagIdsName" >
               <template slot-scope="scope">
-                   <span v-for="tagId in JSON.parse(scope.row.effectiveRules)" :key="tagId" style="display: inline;">
-                    <el-tag :disable-transitions="false"  v-for="list in tagList" :key="list.id" style="margin: 3px;" v-if="list.tagId==tagId">{{list.name}}</el-tag>
-                  </span>
+                <div v-for="name in scope.row.tagIdsName" style="display: inline;">
+                  <el-tag type="success">{{ name }}</el-tag>
+                </div>
               </template>
             </el-table-column>
             <el-table-column label="添加好友时间" align="center" prop="addTime" width="180"/>

+ 60 - 36
src/views/qw/autoTags/groupIndex.vue

@@ -59,12 +59,10 @@
 
         <el-table v-loading="loading" :data="groupIndexList" border  height="550px">
           <el-table-column label="规则名称" align="center" prop="ruleName" />
-          <el-table-column label="添加的标签" align="center" prop="rulesTags" width="300px">
+          <el-table-column label="添加的标签" align="center" prop="tagIdsName" width="300px">
             <template slot-scope="scope">
-              <div>
-                <div v-for="tagId in scope.row.tagsSet" :key="tagId" style="display: inline;">
-                  <el-tag :disable-transitions="false"  v-for="list in tagList" :key="list.id" style="margin: 3px;" v-if="list.tagId==tagId">{{list.name}}</el-tag>
-                </div>
+              <div v-for="name in scope.row.tagIdsName" style="display: inline;">
+                <el-tag type="success">{{ name }}</el-tag>
               </div>
             </template>
           </el-table-column>
@@ -216,8 +214,8 @@
 
     <el-dialog title="添加标签" :visible.sync="tagChange.open" width="800px" append-to-body>
       <div>搜索标签:
-        <el-input v-model="tagChange.tagName" placeholder="请输入标签名称" clearable size="small" style="width: 200px;margin-right: 10px" />
-        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleSearchTags(tagChange.tagName)">搜索</el-button>
+        <el-input v-model="queryTagParams.name" placeholder="请输入标签名称" clearable size="small" style="width: 200px;margin-right: 10px" />
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleSearchTags">搜索</el-button>
         <el-button type="primary" icon="el-icon-plus" size="mini" @click="cancelSearchTags">重置</el-button>
       </div>
       <div v-for="item in tagGroupList" :key="item.id" >
@@ -235,6 +233,13 @@
           </a>
         </div>
       </div>
+      <pagination
+        v-show="tagTotal>0"
+        :total="tagTotal"
+        :page.sync="queryTagParams.pageNum"
+        :limit.sync="queryTagParams.pageSize"
+        @pagination="getPageListTagGroup"
+      />
       <div slot="footer" class="dialog-footer">
         <el-button type="primary" @click="addTagSubmitForm(tagChange.index)">确 定</el-button>
         <el-button @click="addTagCancel(tagChange.index)">重 置</el-button>
@@ -275,6 +280,7 @@ export default {
       showSearch: true,
       // 总条数
       total: 0,
+      tagTotal:0,
       // 自动打标签主表格数据
       groupIndexList: [],
       // 弹出层标题
@@ -295,7 +301,7 @@ export default {
       tagGroupList:[],
 
       //所有的标签
-      tagList:[],
+      // tagList:[],
 
       //选择的标签
       tagListFormIndex:[],
@@ -310,6 +316,14 @@ export default {
         open:false,
         title:'',
       },
+
+      queryTagParams: {
+        pageNum: 1,
+        pageSize: 10,
+        total:0,
+        name:null,
+        corpId:null,
+      },
       // 查询参数
       queryParams: {
         pageNum: 1,
@@ -407,16 +421,22 @@ export default {
      * 重新获取 部分数据
      */
     afreshData(value){
-      //所有的标签组
-      allListTagGroup({corpId:value}).then(response => {
-        this.tagGroupList = response.rows;
-      });
 
-      //所有的标签
-      listTag({corpId:value}).then(response => {
-        this.tagList = response.rows;
-      });
+      this.resetSearchQueryTag()
+      this.queryTagParams.corpId=value;
+
     },
+
+    resetSearchQueryTag(){
+
+      this.queryTagParams= {
+        pageNum: 1,
+        pageSize: 10,
+        total:0,
+        name:null,
+      };
+    },
+
     //选择的标签页
     handleClick(tab, event) {
       this.queryParams.type=tab.name
@@ -485,13 +505,25 @@ export default {
 
     },
 
-    handleSearchTags(name){
-
-      searchTags({name:name,corpId:this.queryParams.corpId}).then(response => {
+    handleSearchTags(){
+      this.queryTagParams.corpId=this.queryParams.corpId;
+      searchTags(this.queryTagParams).then(response => {
         this.tagGroupList = response.rows;
       });
 
     },
+
+    getPageListTagGroup(){
+
+      this.queryTagParams.corpId=this.queryParams.corpId;
+
+      allListTagGroup(this.queryTagParams).then(response => {
+        this.tagGroupList = response.rows;
+        this.tagTotal = response.total;
+      });
+    },
+
+
     cancelSearchTags(){
       this.afreshData(this.queryParams.corpId)
     },
@@ -559,9 +591,6 @@ export default {
       if (this.form.rulesTags.length >=5) {
         return this.$message.error('当前规则已达上限,无法添加规则');
       }
-
-
-
       this.form.rulesTags.push({rules:[],tags:[]})
     },
 
@@ -572,20 +601,6 @@ export default {
       listTags(this.queryParams).then(response => {
 
         this.groupIndexList = response.rows;
-        this.groupIndexList.forEach(item => {
-          const tagsSet = new Set(); // 为每个项目创建一个新的 Set
-          try {
-            const data = JSON.parse(item.rulesTags); // 将每个 rulesTags JSON 字符串解析为 JavaScript 对象
-            data.forEach(entry => {
-              entry.tags.forEach(tag => {
-                tagsSet.add(tag); // 将每个 tag 添加到 Set 中
-              });
-            });
-          } catch (error) {
-            this.$message.error("Error parsing JSON:",error)
-          }
-          item.tagsSet = Array.from(tagsSet); // 将 Set 转换为数组并添加到当前项目
-        });
 
         this.total = response.total;
         this.loading = false;
@@ -638,6 +653,15 @@ export default {
       this.reset();
       this.open = true;
       this.title = "添加规则";
+
+
+      this.getPageListTagGroup();
+
+      //所有的标签
+      listTag({corpId:this.queryParams.corpId}).then(response => {
+        this.tagList = response.rows;
+      });
+
     },
     handleAddThree(){
 

+ 0 - 1
src/views/qw/autoTags/groupIndexDetails.vue

@@ -335,7 +335,6 @@ export default {
       listAutoTagsLogs(this.queryParams).then(response => {
 
         this.autoTagsLogsList = response.rows;
-        console.log("群-",this.autoTagsLogsList)
 
         this.total = response.total;
         this.loading = false;

+ 288 - 117
src/views/qw/externalContact/index.vue

@@ -21,25 +21,14 @@
         />
       </el-form-item>
 
-      <el-form-item label="销售企微昵称" prop="qwUserId">
-        <el-select v-model="queryParams.qwUserId" clearable filterable remote
-                   placeholder="请输入销售企微昵称" :remote-method="loadQwUserOptions"
-                   v-select-load-more="loadMoreQwUserOptions"
-                   :loading="qwUserOptionsLoading">
-          <el-option
-            v-for="item in qwUserOptions"
-            :key="item.value"
-            :label="item.label"
-            :value="item.value">
-          </el-option>
-        </el-select>
-<!--        <el-input-->
-<!--          v-model="queryParams.qwUserName"-->
-<!--          placeholder="请输入销售企微昵称"-->
-<!--          clearable-->
-<!--          size="small"-->
-<!--          @keyup.enter.native="handleQuery"-->
-<!--        />-->
+      <el-form-item label="销售企微昵称" prop="qwUserName">
+        <el-input
+          v-model="queryParams.qwUserName"
+          placeholder="请输入销售企微昵称"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
       </el-form-item>
       <el-form-item label="用户类别" prop="type">
         <el-select v-model="queryParams.type" placeholder="请选择用户类别" clearable size="small">
@@ -138,13 +127,28 @@
         </el-select>
       </el-form-item>
       <el-form-item label="标签" prop="tagIds">
-        <el-select v-model="selectTags" remote multiple placeholder="请选择" filterable  style="width: 100%;">
-          <el-option
-            v-for="dict in tagList"
-            :label="dict.name"
-            :value="dict.tagId">
-          </el-option>
-        </el-select>
+<!--        <el-select v-model="selectTags" remote multiple placeholder="请选择" filterable  style="width: 100%;">-->
+<!--          <el-option-->
+<!--            v-for="dict in tagList"-->
+<!--            :label="dict.name"-->
+<!--            :value="dict.tagId">-->
+<!--          </el-option>-->
+<!--        </el-select>-->
+
+        <div @click="hangleChangeTags()" style="cursor: pointer; border: 1px solid #e6e6e6; background-color: white; overflow: hidden; flex-grow: 1;width: 250px">
+          <div style="min-height: 35px; max-height: 200px; overflow-y: auto;">
+            <el-tag type="success"
+                    closable
+                    :disable-transitions="false"
+                    v-for="list in this.selectTags"
+                    :key="list.tagId"
+                    @close="handleCloseTags(list)"
+                    style="margin: 3px;"
+            >{{list.name}}
+            </el-tag>
+          </div>
+        </div>
+
 
       </el-form-item>
       <el-form-item label="备注" prop="remark">
@@ -259,8 +263,8 @@
 
     <el-tabs type="card" v-model="isBindActiveName" @tab-click="handleClickX">
       <el-tab-pane label="全部" name="all"></el-tab-pane>
-      <el-tab-pane label="已绑定CRM" name="isBind"></el-tab-pane>
-      <el-tab-pane label="未绑定CRM" name="noBind"></el-tab-pane>
+<!--      <el-tab-pane label="已绑定CRM" name="isBind"></el-tab-pane>-->
+<!--      <el-tab-pane label="未绑定CRM" name="noBind"></el-tab-pane>-->
     </el-tabs>
 
     <el-table v-loading="loading" :data="externalContactList" @selection-change="handleSelectionChange" border>
@@ -293,10 +297,10 @@
       </el-table-column>
       <el-table-column label="备注" align="center" prop="remark" />
       <el-table-column label="描述信息" align="center" prop="description" />
-      <el-table-column label="标签" align="center" prop="tagIds" width="250px">
+      <el-table-column label="标签" align="center" prop="tagIdsName" width="250px">
         <template slot-scope="scope">
-          <div v-for="i in JSON.parse(scope.row.tagIds)" :key="i" style="display: inline;">
-          <el-tag type="success" v-for="ii in tagList" :key="ii.id" style="margin: 3px;" v-if="ii.tagId==i">{{ii.name}}</el-tag>
+          <div v-for="name in scope.row.tagIdsName"  style="display: inline;">
+          <el-tag type="success">{{ name }}</el-tag>
           </div>
         </template>
       </el-table-column>
@@ -364,15 +368,15 @@
       </el-table-column>
       <el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="120px" fixed="right">
         <template slot-scope="scope">
-          <el-button
-            size="mini"
-            type="text"
-            icon="el-icon-edit-outline"
-            @click="handleUpdateCustomer(scope.row)"
-            >
-            <span v-if="scope.row.customerId">换绑CRM</span>
-            <span v-else>绑定CRM</span>
-          </el-button>
+<!--          <el-button-->
+<!--            size="mini"-->
+<!--            type="text"-->
+<!--            icon="el-icon-edit-outline"-->
+<!--            @click="handleUpdateCustomer(scope.row)"-->
+<!--            >-->
+<!--            <span v-if="scope.row.customerId">换绑CRM</span>-->
+<!--            <span v-else>绑定CRM</span>-->
+<!--          </el-button>-->
 
           <el-button
             size="mini"
@@ -380,8 +384,8 @@
             icon="el-icon-edit-outline"
             @click="handleUpdateUser(scope.row)"
             >
-            <span v-if="scope.row.fsUserId">换绑小程序用户</span>
-            <span v-else>绑定小程序用户</span>
+            <span v-if="scope.row.fsUserId">换绑会员</span>
+            <span v-else>绑定会员</span>
           </el-button>
 
           <el-button
@@ -391,22 +395,22 @@
             @click="handleUnBindUserId(scope.row)"
             v-hasPermi="['qw:externalContact:unBindUserId']"
           >
-            <span v-if="scope.row.fsUserId">解除小程序用户绑定</span>
+            <span v-if="scope.row.fsUserId">解除会员绑定</span>
           </el-button>
 
 
-          <el-button v-if="scope.row.customerId"
-            size="mini"
-            type="text"
-            icon="el-icon-paperclip"
-            @click="handleShow(scope.row)"
-          >CRM客户详情</el-button>
-		  <el-button
-		     size="mini"
-		     type="text"
-		     @click="handledetails(scope.row)"
-		     >用户信息
-		  </el-button>
+<!--          <el-button v-if="scope.row.customerId"-->
+<!--            size="mini"-->
+<!--            type="text"-->
+<!--            icon="el-icon-paperclip"-->
+<!--            @click="handleShow(scope.row)"-->
+<!--          >CRM客户详情</el-button>-->
+          <el-button
+             size="mini"
+             type="text"
+             @click="handledetails(scope.row)"
+             >AI获取用户信息
+          </el-button>
         </template>
       </el-table-column>
     </el-table>
@@ -423,6 +427,44 @@
       <customer-details  ref="customerDetails" @refreshList="refreshList"/>
     </el-drawer>
 
+
+    <!--  搜索标签   -->
+    <el-dialog :title="changeTagDialog.title" :visible.sync="changeTagDialog.open" style="width:100%;height: 100%" append-to-body>
+
+      <div>搜索标签:
+        <el-input v-model="queryTagParams.name" placeholder="请输入标签名称" clearable size="small" style="width: 200px;margin-right: 10px" />
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleSearchTags(queryTagParams.name)">搜索</el-button>
+        <el-button type="primary" icon="el-icon-plus" size="mini" @click="cancelSearchTags">重置</el-button>
+      </div>
+      <div v-for="item in tagGroupList" :key="item.id"  >
+        <div style="font-size: 20px;margin-top: 20px;margin-bottom: 20px;">
+          <span class="name-background">{{ item.name }}</span>
+        </div>
+        <div class="tag-container">
+          <a
+            v-for="tagItem in item.tag"
+            class="tag-box"
+            @click="tagSelection(tagItem)"
+            :class="{ 'tag-selected': tagItem.isSelected }"
+          >
+            {{ tagItem.name }}
+          </a>
+        </div>
+      </div>
+
+      <pagination
+        v-show="tagTotal>0"
+        :total="tagTotal"
+        :page.sync="queryTagParams.pageNum"
+        :limit.sync="queryTagParams.pageSize"
+        @pagination="getPageListTagGroup"
+      />
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="tagSubmitForm()">确 定</el-button>
+        <el-button @click="tagCancel()">取消</el-button>
+      </div>
+    </el-dialog>
+
     <el-dialog title="批量添加标签" :visible.sync="tagOpen" width="800px" append-to-body>
       <div>搜索标签:
         <el-input v-model="tagChange.tagName" placeholder="请输入标签名称" clearable size="small" style="width: 200px;margin-right: 10px" />
@@ -446,6 +488,13 @@
           </div>
         </div>
       </el-form>
+      <pagination
+        v-show="tagTotal>0"
+        :total="tagTotal"
+        :page.sync="queryTagParams.pageNum"
+        :limit.sync="queryTagParams.pageSize"
+        @pagination="getPageListTagGroup"
+      />
       <div slot="footer" class="dialog-footer">
         <el-button type="primary" @click="addTagSubmitForm()">确 定</el-button>
         <el-button @click="addTagCancel">取 消</el-button>
@@ -475,11 +524,19 @@
           </div>
         </div>
       </el-form>
+      <pagination
+        v-show="tagTotal>0"
+        :total="tagTotal"
+        :page.sync="queryTagParams.pageNum"
+        :limit.sync="queryTagParams.pageSize"
+        @pagination="getPageListTagGroup"
+      />
       <div slot="footer" class="dialog-footer">
         <el-button type="primary" @click="tagDelSubmitForm()">确 定</el-button>
         <el-button @click="DelTagCancel">取 消</el-button>
       </div>
     </el-dialog>
+
     <!-- 添加或修改企业微信客户对话框 -->
     <el-dialog :title="title" :visible.sync="open" width="700px" append-to-body>
       <el-form ref="form" :model="form" :rules="rules" label-width="100px">
@@ -577,8 +634,8 @@ import {
   setCustomerCourseSopList,
   unBindUserId, updateExternalContactCall
 } from '@/api/qw/externalContact'
-import { getMyQwCompanyList, getQwUserListLikeName} from "@/api/qw/user";
-import {listTag, searchTags,} from "@/api/qw/tag";
+import {getMyQwUserList, getMyQwCompanyList, updateUser} from "@/api/qw/user";
+import {listTag, getTag, searchTags,} from "@/api/qw/tag";
 import { allListTagGroup} from "@/api/qw/tagGroup";
 import mycustomer from '@/views/qw/externalContact/mycustomer'
 import customerDetails from '@/views/qw/externalContact/customerDetails'
@@ -698,6 +755,23 @@ export default {
       },
       // 来源字典
       addWayOptions: [],
+
+      //标签
+      changeTagDialog:{
+        title:"",
+        open:false,
+      },
+
+      queryTagParams:{
+        pageNum: 1,
+        pageSize: 10,
+        total:0,
+        name:null,
+        corpId:null,
+      },
+
+      tagTotal:0,
+
       // 查询参数
       queryParams: {
         pageNum: 1,
@@ -738,16 +812,7 @@ export default {
       statusOptions:[],
       // 表单校验
       rules: {
-      },
-      // 企微用户选项
-      qwUserOptionsParams: {
-        name: undefined,
-        hasNextPage: false,
-        pageNum: 1,
-        pageSize: 10
-      },
-      qwUserOptionsLoading: false,
-      qwUserOptions: [],
+      }
     };
   },
   created() {
@@ -768,14 +833,13 @@ export default {
             this.myQwCompanyList = response.data;
             if(this.myQwCompanyList!=null){
               this.queryParams.corpId=this.myQwCompanyList[0].dictValue
+
               var listTagFrom={corpId:this.queryParams.corpId}
-              allListTagGroup(listTagFrom).then(response => {
-                  this.tagGroupList = response.rows;
-              });
               listTag(listTagFrom).then(response => {
                 this.tagList = response.rows;
               });
               this.getList();
+
             }
     });
 
@@ -810,9 +874,6 @@ export default {
 		  },
     updateCorpId(){
       var listTagFrom={corpId:this.queryParams.corpId}
-        allListTagGroup(listTagFrom).then(response => {
-            this.tagGroupList = response.rows;
-        });
         listTag(listTagFrom).then(response => {
           this.tagList = response.rows;
         });
@@ -892,29 +953,106 @@ export default {
         return  this.$message('请选择需要添加标签的客户');
       }
 
-      for (let i = 0; i < this.tagGroupList.length; i++) {
-        for (let x = 0; x < this.tagGroupList[i].tag.length; x++) {
-          this.tagGroupList[i].tag[x].isSelected=false;
+      this.getPageListTagGroup();
+
+      setTimeout(() => {
+
+        for (let i = 0; i < this.tagGroupList.length; i++) {
+          for (let x = 0; x < this.tagGroupList[i].tag.length; x++) {
+            this.tagGroupList[i].tag[x].isSelected=false;
+          }
         }
-      }
+      }, 200);
+
+
       this.tagOpen = true;
 
     },
 
+
+    getPageListTagGroup(){
+      this.queryTagParams.corpId=this.queryParams.corpId
+      allListTagGroup(this.queryTagParams).then(response => {
+        this.tagGroupList = response.rows;
+        this.tagTotal = response.total;
+      });
+    },
+
     delUserTag(){
 
       if(this.ids==null||this.ids==""){
         return  this.$message('请选择需要移除标签的客户');
       }
-      for (let i = 0; i < this.tagGroupList.length; i++) {
-        for (let x = 0; x < this.tagGroupList[i].tag.length; x++) {
-          this.tagGroupList[i].tag[x].isSelected=false;
+      this.getPageListTagGroup();
+
+      setTimeout(() => {
+        for (let i = 0; i < this.tagGroupList.length; i++) {
+          for (let x = 0; x < this.tagGroupList[i].tag.length; x++) {
+            this.tagGroupList[i].tag[x].isSelected=false;
+          }
         }
-      }
+      }, 200);
+
       this.tagDelOpen = true;
 
     },
 
+
+    //搜索的标签
+    hangleChangeTags(){
+
+      this.changeTagDialog.title="搜索的标签"
+      this.changeTagDialog.open=true;
+
+      // 获取 tagListFormIndex 中的所有 tagId,用于快速查找
+      const selectedTagIds = new Set(
+        (this.selectTags || []).map(tagItem => tagItem?.tagId)
+      );
+
+      this.queryTagParams.name=null;
+
+      this.getPageListTagGroup();
+
+      setTimeout(() => {
+        for (let i = 0; i < this.tagGroupList.length; i++) {
+          for (let x = 0; x < this.tagGroupList[i].tag.length; x++) {
+            this.tagGroupList[i].tag[x].isSelected = selectedTagIds.has(this.tagGroupList[i].tag[x].tagId);
+          }
+        }
+      }, 200);
+
+
+    },
+
+    //删除一些选择的标签
+    handleCloseTags(list){
+      const ls = this.selectTags.findIndex(t => t.tagId === list.tagId);
+      if (ls !== -1) {
+        this.selectTags.splice(ls, 1);
+        this.selectTags = [...this.selectTags];
+      }
+
+      if (this.selectTags!=null && this.selectTags.length>0){
+        // 确保 this.form.tags 是数组
+        if (!this.queryParams.tagIds) {
+          this.queryParams.tagIds = []; // 如果未定义,初始化
+        } else {
+          this.queryParams.tagIds = []; // 清空已有数据
+        }
+
+        // 遍历并添加 tagId
+        this.selectTags.forEach(tag => {
+          if (tag.tagId) { // 确保 tagId 存在
+            this.queryParams.tagIds.push(tag.tagId);
+          }
+        });
+        this.queryParams.tagIds=this.queryParams.tagIds.join(",");
+      }else {
+        this.queryParams.tagIds=null;
+      }
+
+    },
+
     //重新获取页面数据
     refreshList(){
       this.getList();
@@ -1085,7 +1223,27 @@ export default {
     },
     /** 搜索按钮操作 */
     handleQuery() {
-      this.queryParams.tagIds=this.selectTags.join(',')
+
+      if (this.selectTags!=null && this.selectTags.length>0){
+        // 确保 this.form.tags 是数组
+        if (!this.queryParams.tagIds) {
+          this.queryParams.tagIds = []; // 如果未定义,初始化
+        } else {
+          this.queryParams.tagIds = []; // 清空已有数据
+        }
+
+        // 遍历并添加 tagId
+        this.selectTags.forEach(tag => {
+          if (tag.tagId) { // 确保 tagId 存在
+            this.queryParams.tagIds.push(tag.tagId);
+          }
+        });
+        this.queryParams.tagIds=this.queryParams.tagIds.join(",");
+      }else {
+        this.queryParams.tagIds=null;
+      }
+
+
       this.queryParams.pageNum = 1;
       this.getList();
     },
@@ -1098,7 +1256,54 @@ export default {
     },
 
     cancelSearchTags(){
-      this.updateCorpId()
+      this.resetSearchQueryTag()
+
+      this.getPageListTagGroup();
+    },
+    //确定选择标签
+    tagSubmitForm(){
+
+      for (let i = 0; i < this.tagGroupList.length; i++) {
+        for (let x = 0; x < this.tagGroupList[i].tag.length; x++) {
+          if (this.tagGroupList[i].tag[x].isSelected === true) {
+
+            if (!this.selectTags) {
+              this.selectTags = [];
+            }
+
+            // 检查当前 tag 是否已经存在于 tagListFormIndex[index] 中
+            let tagExists = this.selectTags.some(
+              tag => tag.id === this.tagGroupList[i].tag[x].id
+            );
+
+            // 如果 tag 不存在于 tagListFormIndex[index] 中,则新增
+            if (!tagExists) {
+              this.selectTags.push(this.tagGroupList[i].tag[x]);
+            }
+          }
+        }
+      }
+      if (!this.selectTags || this.selectTags.length === 0) {
+        return this.$message('请选择标签');
+      }
+
+      this.changeTagDialog.open = false;
+    },
+
+    //取消选择标签
+    tagCancel(){
+      this.changeTagDialog.open = false;
+    },
+
+
+    resetSearchQueryTag(){
+
+      this.queryTagParams= {
+        pageNum: 1,
+        pageSize: 10,
+        total:0,
+        name:null,
+      };
     },
     /** 重置按钮操作 */
     resetQuery() {
@@ -1393,40 +1598,6 @@ export default {
           this.download(response.msg);
           this.exportLoading = false;
         }).catch(() => {});
-    },
-    /**
-     * 加载企业微信用户下拉框数据
-     * @param query
-     */
-    loadQwUserOptions(query) {
-        this.qwUserOptions = [];
-        if (query === '') {
-          return
-        }
-
-        this.qwUserOptionsParams.pageNum = 1
-        this.qwUserOptionsParams.name = query
-        this.qwUserOptionsLoading = true
-        this.getQwUserListLikeName()
-    },
-    /**
-     * 获取企业微信用户下拉框数据
-     */
-    getQwUserListLikeName() {
-      getQwUserListLikeName(this.qwUserOptionsParams).then(response => {
-        this.qwUserOptions = [...this.qwUserOptions, ...response.data.list]
-        this.qwUserOptionsParams.hasNextPage = response.data.hasNextPage
-        this.qwUserOptionsLoading = false
-      })
-    },
-    /**
-     * 加载更多企业微信用户下拉框数据
-     */
-    loadMoreQwUserOptions() {
-      if (this.qwUserOptionsParams.hasNextPage) {
-        this.qwUserOptionsParams.pageNum++
-        this.getQwUserListLikeName()
-      }
     }
   }
 };

+ 256 - 29
src/views/qw/externalContact/myExternalContact.vue

@@ -120,13 +120,28 @@
         </el-select>
       </el-form-item>
       <el-form-item label="标签" prop="tagIds">
-        <el-select v-model="selectTags" remote multiple placeholder="请选择" filterable  style="width: 100%;">
-          <el-option
-            v-for="dict in tagList"
-            :label="dict.name"
-            :value="dict.tagId">
-          </el-option>
-          </el-select>
+<!--        <el-select v-model="selectTags" remote multiple placeholder="请选择" filterable  style="width: 100%;">-->
+<!--          <el-option-->
+<!--            v-for="dict in tagList"-->
+<!--            :label="dict.name"-->
+<!--            :value="dict.tagId">-->
+<!--          </el-option>-->
+<!--          </el-select>-->
+
+        <div @click="hangleChangeTags()" style="cursor: pointer; border: 1px solid #e6e6e6; background-color: white; overflow: hidden; flex-grow: 1;width: 250px">
+          <div style="min-height: 35px; max-height: 200px; overflow-y: auto;">
+            <el-tag type="success"
+                    closable
+                    :disable-transitions="false"
+                    v-for="list in this.selectTags"
+                    :key="list.tagId"
+                    @close="handleCloseTags(list)"
+                    style="margin: 3px;"
+            >{{list.name}}
+            </el-tag>
+          </div>
+        </div>
+
       </el-form-item>
       <el-form-item label="备注" prop="remark">
         <el-input
@@ -297,10 +312,10 @@
       </el-table-column>
       <el-table-column label="备注" align="center" prop="remark" />
       <el-table-column label="描述信息" align="center" prop="description" />
-      <el-table-column label="标签" align="center" prop="tagIds" width="250px">
+      <el-table-column label="标签" align="center" prop="tagIdsName" width="250px">
         <template slot-scope="scope">
-          <div v-for="i in JSON.parse(scope.row.tagIds)" :key="i" style="display: inline;">
-          <el-tag type="success" v-for="ii in tagList" :key="ii.id" style="margin: 3px;" v-if="ii.tagId==i">{{ii.name}}</el-tag>
+          <div v-for="name in scope.row.tagIdsName" style="display: inline;">
+            <el-tag type="success">{{ name }}</el-tag>
           </div>
         </template>
       </el-table-column>
@@ -430,6 +445,44 @@
       <customer-details  ref="customerDetails" @refreshList="refreshList"/>
     </el-drawer>
 
+
+    <!--  搜索标签   -->
+    <el-dialog :title="changeTagDialog.title" :visible.sync="changeTagDialog.open" style="width:100%;height: 100%" append-to-body>
+
+      <div>搜索标签:
+        <el-input v-model="queryTagParams.name" placeholder="请输入标签名称" clearable size="small" style="width: 200px;margin-right: 10px" />
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleSearchTags(queryTagParams.name)">搜索</el-button>
+        <el-button type="primary" icon="el-icon-plus" size="mini" @click="cancelSearchTags">重置</el-button>
+      </div>
+      <div v-for="item in tagGroupList" :key="item.id"  >
+        <div style="font-size: 20px;margin-top: 20px;margin-bottom: 20px;">
+          <span class="name-background">{{ item.name }}</span>
+        </div>
+        <div class="tag-container">
+          <a
+            v-for="tagItem in item.tag"
+            class="tag-box"
+            @click="tagSelection(tagItem)"
+            :class="{ 'tag-selected': tagItem.isSelected }"
+          >
+            {{ tagItem.name }}
+          </a>
+        </div>
+      </div>
+
+      <pagination
+        v-show="tagTotal>0"
+        :total="tagTotal"
+        :page.sync="queryTagParams.pageNum"
+        :limit.sync="queryTagParams.pageSize"
+        @pagination="getPageListTagGroup"
+      />
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="tagSubmitForm()">确 定</el-button>
+        <el-button @click="tagCancel()">取消</el-button>
+      </div>
+    </el-dialog>
+
     <el-dialog title="批量添加标签" :visible.sync="tagOpen" width="800px" append-to-body>
       <div>搜索标签:
         <el-input v-model="tagChange.tagName" placeholder="请输入标签名称" clearable size="small" style="width: 200px;margin-right: 10px" />
@@ -453,6 +506,13 @@
           </div>
         </div>
       </el-form>
+      <pagination
+        v-show="tagTotal>0"
+        :total="tagTotal"
+        :page.sync="queryTagParams.pageNum"
+        :limit.sync="queryTagParams.pageSize"
+        @pagination="getPageListTagGroup"
+      />
       <div slot="footer" class="dialog-footer">
         <el-button type="primary" @click="addTagSubmitForm()">确 定</el-button>
         <el-button @click="addTagCancel">取 消</el-button>
@@ -482,6 +542,13 @@
           </div>
         </div>
       </el-form>
+      <pagination
+        v-show="tagTotal>0"
+        :total="tagTotal"
+        :page.sync="queryTagParams.pageNum"
+        :limit.sync="queryTagParams.pageSize"
+        @pagination="getPageListTagGroup"
+      />
       <div slot="footer" class="dialog-footer">
         <el-button type="primary" @click="tagDelSubmitForm()">确 定</el-button>
         <el-button @click="DelTagCancel">取 消</el-button>
@@ -590,7 +657,7 @@ import {
 import info from "@/views/qw/externalContact/info.vue";
 import {getMyQwUserList, getMyQwCompanyList, handleInputAuthAppKey, updateUser} from "@/api/qw/user";
 import {listTag, getTag, searchTags,} from "@/api/qw/tag";
-import { allListTagGroup} from "@/api/qw/tagGroup";
+import { allListTagGroup} from "../../../api/qw/tagGroup";
 import mycustomer from '@/views/qw/externalContact/mycustomer'
 import customerDetails from '@/views/qw/externalContact/customerDetails'
 import SopDialog from '@/views/course/sop/SopDialog.vue'
@@ -644,6 +711,7 @@ export default {
       showSearch: true,
       // 总条数
       total: 0,
+
       // 企业微信客户表格数据
       externalContactList: [],
       // 弹出层标题
@@ -742,6 +810,22 @@ export default {
         level:null,
         levelType:null
       },
+
+      queryTagParams:{
+        pageNum: 1,
+        pageSize: 10,
+        total:0,
+        name:null,
+        corpId:null,
+      },
+
+      tagTotal:0,
+
+      //标签
+      changeTagDialog:{
+        title:"",
+        open:false,
+      },
       selectTags:[],
       // 表单参数
       form: {},
@@ -812,14 +896,103 @@ export default {
           }
       }
       var listTagFrom={corpId:this.queryParams.corpId}
-        allListTagGroup(listTagFrom).then(response => {
-            this.tagGroupList = response.rows;
-        });
+
         listTag(listTagFrom).then(response => {
           this.tagList = response.rows;
         });
+
         this.getList();
      },
+
+    //搜索的标签
+    hangleChangeTags(){
+
+      this.changeTagDialog.title="搜索的标签"
+      this.changeTagDialog.open=true;
+
+      // 获取 tagListFormIndex 中的所有 tagId,用于快速查找
+      const selectedTagIds = new Set(
+        (this.selectTags || []).map(tagItem => tagItem?.tagId)
+      );
+
+      this.queryTagParams.name=null;
+      this.getPageListTagGroup();
+
+      setTimeout(() => {
+        for (let i = 0; i < this.tagGroupList.length; i++) {
+          for (let x = 0; x < this.tagGroupList[i].tag.length; x++) {
+            this.tagGroupList[i].tag[x].isSelected = selectedTagIds.has(this.tagGroupList[i].tag[x].tagId);
+          }
+        }
+      }, 200);
+
+
+    },
+
+    //确定选择标签
+    tagSubmitForm(){
+
+        for (let i = 0; i < this.tagGroupList.length; i++) {
+          for (let x = 0; x < this.tagGroupList[i].tag.length; x++) {
+            if (this.tagGroupList[i].tag[x].isSelected === true) {
+
+              if (!this.selectTags) {
+                this.selectTags = [];
+              }
+
+              // 检查当前 tag 是否已经存在于 tagListFormIndex[index] 中
+              let tagExists = this.selectTags.some(
+                tag => tag.id === this.tagGroupList[i].tag[x].id
+              );
+
+              // 如果 tag 不存在于 tagListFormIndex[index] 中,则新增
+              if (!tagExists) {
+                this.selectTags.push(this.tagGroupList[i].tag[x]);
+              }
+            }
+          }
+        }
+        if (!this.selectTags || this.selectTags.length === 0) {
+          return this.$message('请选择标签');
+        }
+
+      this.changeTagDialog.open = false;
+    },
+
+    //取消选择标签
+    tagCancel(){
+      this.changeTagDialog.open = false;
+    },
+
+    //删除一些选择的标签
+    handleCloseTags(list){
+      const ls = this.selectTags.findIndex(t => t.tagId === list.tagId);
+      if (ls !== -1) {
+        this.selectTags.splice(ls, 1);
+        this.selectTags = [...this.selectTags];
+      }
+
+      if (this.selectTags!=null && this.selectTags.length>0){
+        // 确保 this.form.tags 是数组
+        if (!this.queryParams.tagIds) {
+          this.queryParams.tagIds = []; // 如果未定义,初始化
+        } else {
+          this.queryParams.tagIds = []; // 清空已有数据
+        }
+
+        // 遍历并添加 tagId
+        this.selectTags.forEach(tag => {
+          if (tag.tagId) { // 确保 tagId 存在
+            this.queryParams.tagIds.push(tag.tagId);
+          }
+        });
+        this.queryParams.tagIds=this.queryParams.tagIds.join(",");
+      }else {
+        this.queryParams.tagIds=null;
+      }
+
+    },
+
     /** 查询企业微信客户列表 */
     getList() {
       this.loading = true;
@@ -829,6 +1002,15 @@ export default {
         this.loading = false;
       });
     },
+
+    getPageListTagGroup(){
+      this.queryTagParams.corpId=this.queryParams.corpId
+      allListTagGroup(this.queryTagParams).then(response => {
+        this.tagGroupList = response.rows;
+        this.tagTotal = response.total;
+      });
+    },
+
     handleSearchTags(name){
 
       searchTags({name:name,corpId:this.queryParams.corpId}).then(response => {
@@ -852,18 +1034,31 @@ export default {
     },
 
     cancelSearchTags(){
-      this.handleGetTagsList()
+
+      this.resetSearchQueryTag()
+
+      this.getPageListTagGroup();
+
+    },
+
+    resetSearchQueryTag(){
+
+      this.queryTagParams= {
+        pageNum: 1,
+        pageSize: 10,
+        total:0,
+        name:null,
+      };
     },
 
+
     handleGetTagsList(){
       var listTagFrom={corpId:this.queryParams.corpId}
-      allListTagGroup(listTagFrom).then(response => {
-        this.tagGroupList = response.rows;
-      });
       listTag(listTagFrom).then(response => {
         this.tagList = response.rows;
       });
     },
+
     bindMiniCustomerId(row){
 
       this.userForm.fsUserId=row;
@@ -917,18 +1112,23 @@ export default {
 
     addUserTag(){
 
+
       if(this.ids==null||this.ids==""){
         return  this.$message('请选择需要添加标签的客户');
       }
 
-      for (let i = 0; i < this.tagGroupList.length; i++) {
-        for (let x = 0; x < this.tagGroupList[i].tag.length; x++) {
-          this.tagGroupList[i].tag[x].isSelected=false;
-        }
-      }
-      this.tagOpen = true;
+      this.getPageListTagGroup();
 
+      setTimeout(() => {
+
+        for (let i = 0; i < this.tagGroupList.length; i++) {
+          for (let x = 0; x < this.tagGroupList[i].tag.length; x++) {
+            this.tagGroupList[i].tag[x].isSelected=false;
+          }
+        }
+      }, 200);
 
+      this.tagOpen = true;
 
     },
 
@@ -937,11 +1137,17 @@ export default {
       if(this.ids==null||this.ids==""){
         return  this.$message('请选择需要移除标签的客户');
       }
-      for (let i = 0; i < this.tagGroupList.length; i++) {
-        for (let x = 0; x < this.tagGroupList[i].tag.length; x++) {
-          this.tagGroupList[i].tag[x].isSelected=false;
+
+      this.getPageListTagGroup();
+
+      setTimeout(() => {
+        for (let i = 0; i < this.tagGroupList.length; i++) {
+          for (let x = 0; x < this.tagGroupList[i].tag.length; x++) {
+            this.tagGroupList[i].tag[x].isSelected=false;
+          }
         }
-      }
+      }, 200);
+
       this.tagDelOpen = true;
 
     },
@@ -1114,7 +1320,28 @@ export default {
     },
     /** 搜索按钮操作 */
     handleQuery() {
-      this.queryParams.tagIds=this.selectTags.join(',')
+
+
+      if (this.selectTags!=null && this.selectTags.length>0){
+        // 确保 this.form.tags 是数组
+        if (!this.queryParams.tagIds) {
+          this.queryParams.tagIds = []; // 如果未定义,初始化
+        } else {
+          this.queryParams.tagIds = []; // 清空已有数据
+        }
+
+        // 遍历并添加 tagId
+        this.selectTags.forEach(tag => {
+          if (tag.tagId) { // 确保 tagId 存在
+            this.queryParams.tagIds.push(tag.tagId);
+          }
+        });
+        this.queryParams.tagIds=this.queryParams.tagIds.join(",");
+      }else {
+        this.queryParams.tagIds=null;
+      }
+
+
       this.queryParams.pageNum = 1;
       this.getList();
     },

+ 1 - 1
src/views/qw/friendWelcome/index.vue

@@ -96,7 +96,7 @@
       </el-table-column>
       <el-table-column label="创建时间" align="center" prop="createTime" width="180"/>
       <el-table-column label="更新时间" align="center" prop="updateTime" width="180"/>
-      <el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="120px" fixed="right">
+      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
         <template slot-scope="scope">
           <el-button
             size="mini"

+ 4 - 4
src/views/qw/friendWelcome/indexNew.vue

@@ -96,7 +96,7 @@
       </el-table-column>
       <el-table-column label="创建时间" align="center" prop="createTime" width="180"/>
       <el-table-column label="更新时间" align="center" prop="updateTime" width="180"/>
-      <el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="120px" fixed="right">
+      <el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="120px">
         <template slot-scope="scope">
           <el-button
             size="mini"
@@ -342,9 +342,9 @@
                               <el-dropdown-item command="link">
                                 <i class="el-icon-link" style="margin-right: 10px;"></i>链接
                               </el-dropdown-item>
-                              <el-dropdown-item command="miniprogram">
-                                <i class="el-icon-link" style="margin-right: 10px;"></i>小程序
-                              </el-dropdown-item>
+<!--                              <el-dropdown-item command="miniprogram">-->
+<!--                                <i class="el-icon-link" style="margin-right: 10px;"></i>小程序-->
+<!--                              </el-dropdown-item>-->
                             </el-dropdown-menu>
 
                             <span class="el-dropdown-link">

+ 1 - 1
src/views/qw/groupMsgUser/groupMsg.vue

@@ -220,7 +220,7 @@
     </el-dialog>
 
     <!--  选择的标签   -->
-    <el-dialog :title="changeTagDialog.title" :visible.sync="changeTagDialog.open" style="width: 1300px;height: 100%" append-to-body>
+    <el-dialog :title="changeTagDialog.title" :visible.sync="changeTagDialog.open"style="width: 1300px;height: 100%" append-to-body>
       <tag-group-list ref="TagGroupList" :change-type="changeTagDialog.type" @selectTagsList="selectTagsList"></tag-group-list>
     </el-dialog>
 

+ 8 - 0
src/views/qw/sop/ImageUpload.vue

@@ -6,6 +6,7 @@
       :on-success="handleUploadSuccess"
       :before-upload="handleBeforeUpload"
       :limit="limit"
+      :disabled="disabled"
       :on-error="handleUploadError"
       :on-exceed="handleExceed"
       name="file"
@@ -49,6 +50,11 @@ export default {
        type: Number,
        default: 1,
     },
+    // 大小限制(MB)
+    disabled: {
+      type: Boolean,
+      default: false,
+    },
     // 文件类型, 例如['png', 'jpg', 'jpeg']
     fileType: {
       type: Array,
@@ -112,12 +118,14 @@ export default {
       if(findex > -1) {
         this.fileList.splice(findex, 1);
         this.$emit("input", this.listToString(this.fileList));
+        this.$emit("change", this.listToString(this.fileList));    // 新增change事件触发
       }
     },
     // 上传成功回调
     handleUploadSuccess(res,file) {
       this.fileList.push({ name: res.url, url: res.url });
       this.$emit("input", this.listToString(this.fileList));
+      this.$emit("change", this.listToString(this.fileList));    // 新增change事件触发
       this.loading.close();
     },
     // 上传前loading加载

+ 1 - 1
src/views/qw/sop/addAiChatSop.vue

@@ -154,7 +154,7 @@
         </el-form-item>
         <el-form-item label="任务过期时间" prop="expiryTime">
           <el-row>
-            <el-input-number  v-model="form.expiryTime"  :min="1" :max="100" ></el-input-number>
+            <el-input-number  v-model="form.expiryTime"  :min="3" :max="100" ></el-input-number>
             (小时)
           </el-row>
         </el-form-item>

A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 372 - 248
src/views/qw/sop/addSop.vue


A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 347 - 357
src/views/qw/sop/sop.vue


+ 1 - 1
src/views/qw/sop/updateSop.vue

@@ -465,7 +465,7 @@ export default {
     //查询模板
     selectListSopTemp(type,isUpdate){
       this.tempListLoading = true; // 开始查询,显示加载提示
-      listSopTemp({sendType:type,status: 1}).then(response => {
+      listSopTemp({sendType:type}).then(response => {
         this.tempList = response.rows;
         this.tempListLoading = false;
       });

+ 14 - 11
src/views/qw/sopLogs/sopLogsList.vue

@@ -30,7 +30,7 @@
         />
       </el-form-item>
       <el-form-item label="发送类型" prop="sendType" >
-        <el-select v-model="queryParams.sendType" placeholder="请选择发送类型" clearable size="small"   @change="handleQuery">
+        <el-select v-model="queryParams.sendType" placeholder="请选择发送类型" clearable size="small">
           <el-option
             v-for="dict in sysQwSopType"
             :key="dict.dictValue"
@@ -105,9 +105,7 @@
           @click="handleDelete"
           v-hasPermi="['qw:sopLogs:remove']"
         >批量删除</el-button>
-
         <el-button
-          v-if="queryParams.sendType==3"
           type="success"
           plain
           icon="el-icon-edit"
@@ -115,7 +113,7 @@
           :disabled="multiple"
           @click="handleEditCourse"
           v-hasPermi="['qw:sopLogs:editCourse']"
-        >再次补发完课</el-button>
+        >再次发送记录</el-button>
       </el-col>
       <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
     </el-row>
@@ -129,7 +127,7 @@
         </template>
       </el-table-column>
       <el-table-column label="企微成员账号" align="center" prop="qwUserid" />
-<!--      <el-table-column label="企微成员昵称" align="center" prop="qwUserName" v-if="queryParams.type==2" />-->
+      <el-table-column label="企微成员昵称" align="center" prop="qwUserName"  v-if="queryParams.type==2" />
 <!--      <el-table-column label="系统后台昵称" align="center" prop="userName" />-->
       <el-table-column label="客户昵称" align="center" prop="externalUserName" />
       <el-table-column label="发送的消息" align="center" prop="contentJson" >
@@ -294,7 +292,13 @@
 </template>
 
 <script>
-import {listQwSopLogs, exportQwSopLogs, listQwSopLogsList, delQwSopLogs, editCourseQwSopLogs} from '@/api/qw/sopLogs'
+import {
+  listQwSopLogs,
+  exportQwSopLogs,
+  listQwSopLogsList,
+  delQwSopLogs,
+  editCourseQwSopLogs
+} from '../../../api/qw/sopLogs'
 import {delSopUserLogsInfo} from "@/api/qw/sopUserLogsInfo";
 
 export default {
@@ -526,13 +530,12 @@ export default {
         this.msgSuccess("删除成功");
       }).catch(() => {});
     },
-
     /**
-    * 批量修改完课的发送
-    */
+     * 批量修改发送记录
+     */
     handleEditCourse(row){
       const ids = row.id || this.ids;
-      this.$confirm('确认要再次发送【执行详情】编号为"【' + ids + '】"的【完课】记录?', "警告", {
+      this.$confirm('确认要再次发送【执行详情】编号为"【' + ids + '】"的记录?', "警告", {
         confirmButtonText: "确定",
         cancelButtonText: "取消",
         type: "warning"
@@ -540,7 +543,7 @@ export default {
         return editCourseQwSopLogs(ids);
       }).then(() => {
         this.getList(this.rowDetailFrom);
-        this.msgSuccess("已经 修改完课记录为 待发送~");
+        this.msgSuccess("已经 修改记录为 待发送~");
       }).catch(() => {});
     },
     /** 导出按钮操作 */

+ 264 - 227
src/views/qw/sopTemp/index.vue

@@ -39,15 +39,6 @@
           @keyup.enter.native="handleQuery"
         />
       </el-form-item>
-      <el-form-item label="公司id" prop="companyId">
-        <el-input
-          v-model="queryParams.companyId"
-          placeholder="请输入公司id"
-          clearable
-          size="small"
-          @keyup.enter.native="handleQuery"
-        />
-      </el-form-item>
       <el-form-item>
         <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>
@@ -55,19 +46,19 @@
     </el-form>
 
 
-
     <el-row :gutter="10" class="mb8">
       <el-col :span="1.5">
-<!--        <el-button-->
-<!--          type="primary"-->
-<!--          plain-->
-<!--          icon="el-icon-plus"-->
-<!--          size="mini"-->
-<!--          @click="handleAdd"-->
-<!--          v-hasPermi="['qw:sopTemp:add']"-->
-<!--        >新增</el-button>-->
+        <!--        <el-button-->
+        <!--          type="primary"-->
+        <!--          plain-->
+        <!--          icon="el-icon-plus"-->
+        <!--          size="mini"-->
+        <!--          @click="handleAdd"-->
+        <!--          v-hasPermi="['qw:sopTemp:add']"-->
+        <!--        >新增</el-button>-->
 
         <el-dropdown
+          v-if="roles.includes('add_sop_temp')"
           @command="handleCommand"
           trigger="click"
           placement="bottom-start"
@@ -82,8 +73,8 @@
               {{ option.dictLabel }}
             </el-dropdown-item>
           </el-dropdown-menu>
-          <span class="el-dropdown-link" >
-              <el-button  type="primary"  icon="el-icon-plus" plain  size="mini" >
+          <span class="el-dropdown-link">
+              <el-button type="primary" icon="el-icon-plus" plain size="mini">
                 新增模板
               </el-button>
             </span>
@@ -98,8 +89,10 @@
           size="mini"
           :disabled="multiple"
           @click="handleDelete"
+          v-if="roles.includes('del_sop_temp')"
           v-hasPermi="['qw:sopTemp:remove']"
-        >删除</el-button>
+        >删除
+        </el-button>
       </el-col>
       <el-col :span="1.5">
         <el-button
@@ -110,29 +103,35 @@
           :loading="exportLoading"
           @click="handleExport"
           v-hasPermi="['qw:sopTemp:export']"
-        >导出</el-button>
+        >导出
+        </el-button>
       </el-col>
       <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
     </el-row>
 
     <el-table v-loading="loading" border :data="sopTempList" @selection-change="handleSelectionChange">
-      <el-table-column type="selection" width="55" align="center" />
-      <el-table-column label="模板编号" align="center" prop="id" />
-      <el-table-column label="模板标题" align="center" prop="name" />
-      <el-table-column label="模板类型" align="center" prop="sendType" >
+      <el-table-column type="selection" width="55" align="center"/>
+      <el-table-column label="模板编号" align="center" prop="id"/>
+      <el-table-column label="模板编号" align="center">
+        <template slot-scope="scope">
+          <el-tag v-for="item in companys" v-if="scope.row.companyId == item.companyId">{{item.companyName}}</el-tag>
+        </template>
+      </el-table-column>
+      <el-table-column label="模板标题" align="center" prop="name"/>
+      <el-table-column label="模板类型" align="center" prop="sendType">
         <template slot-scope="scope">
           <dict-tag :options="sysQwSopType" :value="scope.row.sendType"/>
         </template>
       </el-table-column>
-      <el-table-column label="间隔天数" align="center" prop="gap" />
+      <el-table-column label="间隔天数" align="center" prop="gap"/>
       <el-table-column label="状态" align="center" prop="status">
         <template slot-scope="scope">
           <dict-tag :options="statusOptions" :value="scope.row.status"/>
         </template>
       </el-table-column>
-      <el-table-column label="创建时间" align="center" prop="createTime" />
-      <el-table-column label="修改时间" align="center" prop="updateTime" />
-      <el-table-column label="排序" align="center" prop="sort" />
+      <el-table-column label="创建时间" align="center" prop="createTime"/>
+      <el-table-column label="修改时间" align="center" prop="updateTime"/>
+      <el-table-column label="排序" align="center" prop="sort"/>
 
       <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
         <template slot-scope="scope">
@@ -140,51 +139,55 @@
             size="mini"
             type="text"
             icon="el-icon-connection"
+            v-if="roles.includes('update_sop_temp')"
             @click="copyTemplate(scope.row)"
             v-hasPermi="['qw:sopTemp:edit']"
-          >复制模板</el-button>
-          <el-button
-            size="mini"
-            type="text"
-            icon="el-icon-share"
-            @click="shareTemplate(scope.row)"
-            v-hasPermi="['qw:sopTemp:share']"
-          >分享模板</el-button>
+          >复制模板
+          </el-button>
           <el-button
             size="mini"
             type="text"
             icon="el-icon-s-promotion"
             @click="handleQueryDetails(scope.row)"
             v-hasPermi="['qw:sopTemp:list']"
-          >详情</el-button>
+          >详情
+          </el-button>
           <el-button
             size="mini"
             type="text"
             icon="el-icon-edit"
+            v-if="roles.includes('update_sop_temp')"
             @click="handleUpdate(scope.row)"
             v-hasPermi="['qw:sopTemp:edit']"
-          >修改</el-button>
+          >修改
+          </el-button>
           <el-button
             size="mini"
             type="text"
             icon="el-icon-edit"
             @click="handleUpdate2(scope.row)"
+            v-if="roles.includes('update_sop_temp')"
             v-hasPermi="['qw:sopTemp:edit']"
-          >管理规则</el-button>
+          >管理规则
+          </el-button>
           <el-button
             size="mini"
             type="text"
             icon="el-icon-edit"
-            @click="updateImageFun(scope.row.id)"
+            @click="handleUpdateRed(scope.row)"
+            v-if="scope.row.sendType == 5 && roles.includes('update_sop_temp_red')"
             v-hasPermi="['qw:sopTemp:edit']"
-          >更新图片</el-button>
+          >红包设置
+          </el-button>
           <el-button
             size="mini"
             type="text"
             icon="el-icon-delete"
             @click="handleDelete(scope.row)"
+            v-if="roles.includes('del_sop_temp')"
             v-hasPermi="['qw:sopTemp:remove']"
-          >删除</el-button>
+          >删除
+          </el-button>
         </template>
       </el-table-column>
     </el-table>
@@ -200,23 +203,58 @@
     <el-dialog :title="title" :visible.sync="open" width="800px" append-to-body>
       <el-form ref="form" :model="form" :rules="rules" label-width="80px">
         <el-form-item label="名称" prop="name">
-          <el-input v-model="form.name" placeholder="请输入模板标题" />
+          <el-input v-model="form.name" placeholder="请输入模板标题"/>
         </el-form-item>
-
         <el-form-item label="状态">
           <el-radio-group v-model="form.status">
             <el-radio
               v-for="dict in statusOptions"
               :key="dict.dictValue"
               :label="dict.dictValue"
-            >{{dict.dictLabel}}</el-radio>
+            >{{ dict.dictLabel }}
+            </el-radio>
           </el-radio-group>
         </el-form-item>
+        <el-form-item label="所属项目" prop="project" v-if="form.sendType != 5">
+          <el-select v-model="form.project" placeholder="请选择项目" filterable clearable size="small">
+            <el-option
+              v-for="dict in projectOptions"
+              :key="dict.dictValue"
+              :label="dict.dictLabel"
+              :value="dict.dictValue"
+            />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="课程" prop="courseId" v-if="form.sendType == 5 && !form.id">
+          <el-select v-model="form.courseId"placeholder="请选择课程" style=" margin-right: 10px;" size="mini" filterable>
+            <el-option
+              v-for="dict in courseList"
+              :key="dict.dictValue"
+              :label="dict.dictLabel"
+              :value="parseInt(dict.dictValue)"
+            />
+          </el-select>
+        </el-form-item>
         <el-form-item label="间隔天数" prop="gap">
-          <el-input-number v-model="form.gap"  :min="1" label="间隔天数"></el-input-number>
+          <el-input-number v-model="form.gap" :min="1" label="间隔天数"></el-input-number>
         </el-form-item>
         <el-form-item label="排序" prop="sort">
-          <el-input-number v-model="form.sort"  :min="0" label="排序"></el-input-number>
+          <el-input-number v-model="form.sort" :min="0" label="排序"></el-input-number>
+        </el-form-item>
+        <el-form-item label="每天发送次数" prop="num" v-if="form.sendType == 5 && !form.id">
+          <el-input-number v-model="form.num" :min="1" label="每天发送次数" @change="sendNumChange"></el-input-number>
+        </el-form-item>
+        <el-form-item label="发送时间" v-if="form.sendType == 5 && !form.id">
+          <el-time-picker
+            v-for="item in form.timeList"
+            class="custom-input"
+            v-model="item.value"
+            value-format="HH:mm"
+            format="HH:mm"
+            :picker-options="{ selectableRange: startTimeRange }"
+            placeholder="时间"
+            style="width: 100px;height: 20px;margin-left: 10px;margin-top: 10px">
+          </el-time-picker>
         </el-form-item>
       </el-form>
       <div slot="footer" class="dialog-footer" style="float: right;">
@@ -224,83 +262,40 @@
         <el-button @click="cancel">取 消</el-button>
       </div>
     </el-dialog>
-    <el-dialog :title="shareOptions.title" :visible.sync="shareOptions.open" width="800px" append-to-body>
 
-      <el-form :model="queryCompanyParams" ref="queryCompanyForm" :inline="true" v-show="showSearch" label-width="68px">
-        <el-form-item label="公司名称" prop="companyName">
-          <el-input
-            style="width: 220px"
-            v-model="queryCompanyParams.companyName"
-            placeholder="请输入企业名称"
-            clearable
-            size="small"
-            @keyup.enter.native="handleCompanyQuery"
-          />
-        </el-form-item>
-
-        <el-form-item label="状态" prop="status">
-          <el-select style="width: 220px" v-model="queryCompanyParams.status" placeholder="请选择状态" clearable size="small">
-            <el-option
-              v-for="dict in statusOptions"
-              :key="dict.dictValue"
-              :label="dict.dictLabel"
-              :value="dict.dictValue"
-            />
-          </el-select>
-        </el-form-item>
-        <el-form-item>
-          <el-button type="cyan" icon="el-icon-search" size="mini" @click="handleCompanyQuery">搜索</el-button>
-          <el-button icon="el-icon-refresh" size="mini" @click="resetCompanyQuery">重置</el-button>
-        </el-form-item>
-      </el-form>
-      <el-row :gutter="10" class="mb8">
-        <el-col :span="1.5">
-          <el-button
-            plain
-            type="primary"
-            icon="el-icon-connection"
-            size="mini"
-            :disabled="multiple"
-            @click="handleShareTemplate"
-            v-hasPermi="['qw:sopTemp:share']"
-          >分享模板</el-button>
-        </el-col>
-      </el-row>
-      <el-table v-loading="companysloading" border :data="companyList" @selection-change="handleSelectionCompany">
-        <el-table-column type="selection" width="55" align="center" />
-        <el-table-column label="公司编号" align="center" prop="companyId" />
-<!--        <el-table-column label="企业名" align="center" prop="companyName" />-->
-<!--        <el-table-column label="备注" align="center" prop="remark"/>-->
-        <el-table-column label="状态" align="center" prop="status" >
+    <el-dialog title="课程红包" :visible.sync="redData.open" width="900px" append-to-body>
+      <el-table v-loading="redData.loading" border :data="redData.list" height="500px">
+        <el-table-column label="小节" align="left" prop="videoName"/>
+        <el-table-column label="金额" align="center">
           <template slot-scope="scope">
-            <el-tag prop="status" v-for="(item, index) in statusOptions"  :type="scope.row.status==1?'success':'danger'"  v-if="scope.row.status==item.dictValue">{{item.dictLabel}}</el-tag>
+            <el-input-number v-model="scope.row.redPacketMoney" :min="0.01" step="0.01" label="红包金额"></el-input-number>
           </template>
         </el-table-column>
       </el-table>
-      <pagination
-        v-show="companyTotal>0"
-        :total="companyTotal"
-        :page.sync="queryCompanyParams.pageNum"
-        :limit.sync="queryCompanyParams.pageSize"
-        @pagination="getCompanyList"
-      />
+      <div slot="footer" class="dialog-footer" style="float: right;">
+        <el-button type="primary" @click="updateRedData" :disabled="redData.loading">保 存</el-button>
+      </div>
     </el-dialog>
   </div>
 </template>
 
 <script>
 import {
-  listSopTemp,
-  getSopTemp,
-  delSopTemp,
-  updateTemp,
-  copyTemplate,
   addTemp,
-  updateImage,
+  copyTemplate,
+  delSopTemp,
   exportSopTemp,
-  shareSopTemp
+  getSopTemp,
+  listSopTemp,
+  getSelectableRange,
+  redList,
+  shareSopTemp,
+  updateRedPackage,
+  updateTemp
 } from "@/api/qw/sopTemp";
-import {getCompanyList,listCompany} from "@/api/company/company";
+import {getCompanyList} from "@/api/company/company";
+import {courseList, getRoles} from "@/api/qw/sop";
+
 export default {
   name: "SopTemp",
   data() {
@@ -312,8 +307,10 @@ export default {
       exportLoading: false,
       // 选中数组
       ids: [],
+      courseList: [],
+      roles: [],
       //选中的公司
-      companys:[],
+      companys: [],
       // 非单个禁用
       single: true,
       // 非多个禁用
@@ -322,12 +319,14 @@ export default {
       showSearch: true,
       // 总条数
       companyTotal: 0,
-      total:0,
-      sendType:0,
+      total: 0,
+      sendType: 0,
       // sop模板表格数据
       sopTempList: [],
-      sysQwSopType:[],
-      companyList:[],
+      sysQwSopType: [],
+      companyList: [],
+      projectOptions: [],
+      startTimeRange: [],
       // 弹出层标题
       title: "",
       // 是否显示弹出层
@@ -336,10 +335,15 @@ export default {
       // 状态字典
       statusOptions: [],
 
-      shareOptions:{
-        title:'分享模板',
-        open:false,
-        templateId:null,
+      shareOptions: {
+        title: '分享模板',
+        open: false,
+        templateId: null,
+      },
+      redData: {
+        open: false,
+        loading: true,
+        list: [],
       },
       queryCompanyParams: {
         pageNum: 1,
@@ -362,55 +366,60 @@ export default {
       // 表单校验
       rules: {
         name: [
-          { required: true, message: '名称不能为空', trigger: 'blur' }
+          {required: true, message: '名称不能为空', trigger: 'blur'}
         ],
         status: [
-          { required: true, message: '状态不能为空', trigger: 'blur' }
+          {required: true, message: '状态不能为空', trigger: 'blur'}
         ],
         sort: [
-          { required: true, message: '排序不能为空', trigger: 'blur' }
+          {required: true, message: '排序不能为空', trigger: 'blur'}
         ],
         gap: [
-          { required: true, message: '间隔天数不能为空', trigger: 'blur' }
+          {required: true, message: '间隔天数不能为空', trigger: 'blur'}
         ],
       },
-      contentRules:{
-        time:[{ required: true, message: '时间不能为空', trigger: 'blur' }],
+      contentRules: {
+        time: [{required: true, message: '时间不能为空', trigger: 'blur'}],
       }
     };
   },
   created() {
     this.getList();
+    getRoles().then(res => {
+      this.roles = res.data;
+    })
     this.getDicts("sys_company_status").then(response => {
       this.statusOptions = response.data;
     });
 
-    this.getCompanyList();
+    getSelectableRange().then(e => {
+      this.startTimeRange = e.data;
+    })
+    this.getDicts("sys_course_project").then(response => {
+      this.projectOptions = response.data;
+    });
 
     this.getDicts("sys_qw_sop_type").then(response => {
       this.sysQwSopType = response.data;
     });
+
+    courseList().then(response => {
+      this.courseList = response.list;
+    });
+
+    getCompanyList().then(response => {
+      this.companys = response.data;
+    });
   },
   methods: {
-    updateImage,
 
-    handleCompanyQuery(){
+    handleCompanyQuery() {
       this.queryCompanyParams.pageNum = 1;
-      this.getCompanyList();
     },
-    resetCompanyQuery(){
+    resetCompanyQuery() {
       this.resetForm("queryCompanyForm");
       this.handleCompanyQuery();
     },
-    /** 查询企业列表 */
-    getCompanyList() {
-      this.companysloading = true;
-      listCompany(this.queryCompanyParams).then(response => {
-        this.companyList = response.rows;
-        this.companyTotal = response.total;
-        this.companysloading = false;
-      });
-    },
     /** 查询sop模板列表 */
     getList() {
       this.loading = true;
@@ -431,6 +440,8 @@ export default {
         gap: 1,
         sendType: this.sendType,
         sort: 0,
+        num: 1,
+        timeList: [{value: ""}],
         status: "1",
       };
       this.resetForm("form");
@@ -446,45 +457,27 @@ export default {
       this.handleQuery();
     },
 
-    updateImageFun(id){
-
-      let loadingRock = this.$loading({
-        lock: true,
-        text: '正在执行中请稍后~~请不要刷新页面!!',
-        spinner: 'el-icon-loading',
-        background: 'rgba(0, 0, 0, 0.7)'
-      });
-
-      updateImage(id).then(response => {
-        this.getList();
-        this.$message.success("更新图片 完成!");
-      }).finally(res=>{
-        loadingRock.close();
-      })
-
-
-    },
-    handleCommand(command){
+    handleCommand(command) {
       // if (command==4) {
       //   this.$router.push('/qw/sopTemp/addAiChatTemp')
       // }else{
-        this.sendType = command;
-        this.title = "新增";
-        this.reset();
-        this.open = true;
-        // this.$router.push('/qw/sopTemp/addTemp/'+command)
+      this.sendType = command;
+      this.title = "新增";
+      this.reset();
+      this.open = true;
+      // this.$router.push('/qw/sopTemp/addTemp/'+command)
       // }
     },
     // 多选框选中数据
     handleSelectionChange(selection) {
       this.ids = selection.map(item => item.id)
-      this.single = selection.length!==1
+      this.single = selection.length !== 1
       this.multiple = !selection.length
     },
     //销售公司多选
-    handleSelectionCompany(selection){
-      this.companys=selection.map(item => item.companyId)
-      this.single = selection.length!==1
+    handleSelectionCompany(selection) {
+      this.companys = selection.map(item => item.companyId)
+      this.single = selection.length !== 1
       this.multiple = !selection.length
     },
     /** 新增按钮操作 */
@@ -492,58 +485,77 @@ export default {
     //   this.$router.push('/qw/sopTemp/addSopTemp')
     // },
     /**
-    * 查看详情
-    */
-    handleQueryDetails(row){
+     * 查看详情
+     */
+    handleQueryDetails(row) {
       // if (row.sendType==4) {
       //   this.$router.push(`/qw/sopTemp/updateAiChatTemp/${row.id}/3`)
       // }else{
-        this.$router.push(`/qw/sopTemp/updateSopTemp/${row.id}/3`)
+      this.$router.push(`/qw/sopTemp/updateSopTemp/${row.id}/3`)
       // }
     },
     /** 修改按钮操作 */
     handleUpdate(row) {
-        // if (row.sendType==4) {
-        //   this.$router.push(`/qw/sopTemp/updateAiChatTemp/${row.id}/1`)
-        // }else{
-          this.getInfo(row.id, 1);
-          // this.$router.push(`/qw/sopTemp/updateTemp/${row.id}/1`)
-        // }
+      // if (row.sendType==4) {
+      //   this.$router.push(`/qw/sopTemp/updateAiChatTemp/${row.id}/1`)
+      // }else{
+      this.getInfo(row.id, 1);
+      // this.$router.push(`/qw/sopTemp/updateTemp/${row.id}/1`)
+      // }
 
     },
     /** 修改按钮操作 */
     handleUpdate2(row) {
-        // if (row.sendType==4) {
-        //   this.$router.push(`/qw/sopTemp/updateAiChatTemp/${row.id}/1`)
-        // }else{
-          this.$router.push(`/qw/sopTemp/updateSopTemp/${row.id}/1`)
-        // }
-
+      // if (row.sendType==4) {
+      //   this.$router.push(`/qw/sopTemp/updateAiChatTemp/${row.id}/1`)
+      // }else{
+      let url = `/qw/sopTemp/updateSopTemp/${row.id}/1`;
+      console.info(url)
+      this.$router.push(url)
+      // }
+    },
+    /** 修改按钮操作 */
+    handleUpdateRed(row) {
+      this.redData.open = true;
+      redList(row.id).then(e => {
+        this.redData.loading = false;
+        this.redData.list = e.data;
+      })
+    },
+    /** 修改按钮操作 */
+    updateRedData() {
+      this.redData.loading = true;
+      updateRedPackage({list: this.redData.list}).then(e => {
+        this.redData.open = false;
+        this.getList();
+      }).catch(() => {
+        this.redData.loading = false;
+      });
     },
 
     /** 分享模板 */
-    shareTemplate(row){
-      this.shareOptions.open=true;
-      this.shareOptions.templateId=row.id;
+    shareTemplate(row) {
+      this.shareOptions.open = true;
+      this.shareOptions.templateId = row.id;
     },
     /**
-    * 复制模板
-    */
-    copyTemplate(row){
-        // if(row.sendType==4){
-        //   this.$router.push(`/qw/sopTemp/updateAiChatTemp/${row.id}/2`)
-        // }else{
-          this.getInfo(row.id, 2);
-          // this.$router.push(`/qw/sopTemp/updateSopTemp/${row.id}/2`)
-        // }
+     * 复制模板
+     */
+    copyTemplate(row) {
+      // if(row.sendType==4){
+      //   this.$router.push(`/qw/sopTemp/updateAiChatTemp/${row.id}/2`)
+      // }else{
+      this.getInfo(row.id, 2);
+      // this.$router.push(`/qw/sopTemp/updateSopTemp/${row.id}/2`)
+      // }
     },
-    getInfo(id, command){
+    getInfo(id, command) {
       getSopTemp(id).then(response => {
         this.command = command;
-        if(command == 2){
+        if (command == 2) {
           this.title = "复制";
         }
-        if(command == 1){
+        if (command == 1) {
           this.title = "修改";
         }
         this.form = response.data;
@@ -555,23 +567,36 @@ export default {
       delete this.form.rules
       this.$refs["form"].validate(valid => {
         if (valid) {
-          if(this.command == 2){
-            copyTemplate(this.form).then(response => {
+          let f = JSON.parse(JSON.stringify(this.form));
+          if (f.timeList && f.timeList.length > 0) {
+            f.timeList = f.timeList.map(item => item.value);
+          }
+          const loading = this.$loading({
+            lock: true,
+            text: 'Loading',
+            spinner: 'el-icon-loading',
+            background: 'rgba(0, 0, 0, 0.7)'
+          });
+          if (this.command == 2) {
+            copyTemplate(f).then(response => {
               this.msgSuccess("复制成功");
               this.open = false;
+              loading.close();
               this.getList();
             });
-          }else{
-            if (this.form.id != null) {
-              updateTemp(this.form).then(response => {
+          } else {
+            if (f.id != null) {
+              updateTemp(f).then(response => {
                 this.msgSuccess("修改成功");
                 this.open = false;
+                loading.close();
                 this.getList();
               });
             } else {
-              addTemp(this.form).then(response => {
+              addTemp(f).then(response => {
                 this.msgSuccess("新增成功");
                 this.open = false;
+                loading.close();
                 this.getList();
               });
             }
@@ -590,8 +615,8 @@ export default {
       }).then(function () {
         return shareSopTemp({companyIds: companyIds, templeId: templateId});
       }).then(() => {
-        this.companys=[];
-        this.shareOptions.open=false;
+        this.companys = [];
+        this.shareOptions.open = false;
         this.getList();
         this.msgSuccess("分享成功");
       });
@@ -600,30 +625,42 @@ export default {
     handleDelete(row) {
       const ids = row.id || this.ids;
       this.$confirm('是否确认删除sop模板编号为"' + ids + '"的数据项?', "警告", {
-          confirmButtonText: "确定",
-          cancelButtonText: "取消",
-          type: "warning"
-        }).then(function() {
-          return delSopTemp(ids);
-        }).then(() => {
-          this.getList();
-          this.msgSuccess("删除成功");
-        }).catch(() => {});
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      }).then(function () {
+        return delSopTemp(ids);
+      }).then(() => {
+        this.getList();
+        this.msgSuccess("删除成功");
+      }).catch(() => {
+      });
     },
     /** 导出按钮操作 */
     handleExport() {
       const queryParams = this.queryParams;
       this.$confirm('是否确认导出所有sop模板数据项?', "警告", {
-          confirmButtonText: "确定",
-          cancelButtonText: "取消",
-          type: "warning"
-        }).then(() => {
-          this.exportLoading = true;
-          return exportSopTemp(queryParams);
-        }).then(response => {
-          this.download(response.msg);
-          this.exportLoading = false;
-        }).catch(() => {});
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      }).then(() => {
+        this.exportLoading = true;
+        return exportSopTemp(queryParams);
+      }).then(response => {
+        this.download(response.msg);
+        this.exportLoading = false;
+      }).catch(() => {
+      });
+    },
+    sendNumChange(val, old) {
+      if (val > old) {
+        for (let i = 0; i < val - old; i++) {
+          this.form.timeList.push({value: ""});
+        }
+      } else {
+        let len = old - val;
+        this.form.timeList.splice(Math.max(this.form.timeList.length - len, 0), len);
+      }
     }
   }
 };

+ 11 - 5
src/views/qw/sopTemp/sopTemp.vue

@@ -19,12 +19,13 @@
     <el-table v-loading="loading" :data="sopTempList" ref="sopTempList" >
       <el-table-column label="id" align="center" prop="id" />
       <el-table-column label="模板标题" align="center" prop="name" />
-      <el-table-column label="模板状态" align="center" prop="status">
+      <el-table-column label="每天首条消息是否发课" align="center" prop="name" v-if="cuoser">
         <template slot-scope="scope">
-          <el-tag v-if="scope.row.status == 1" type="success">启用</el-tag>
-          <el-tag v-else type="danger">停用</el-tag>
+          <el-tag v-if="scope.row.cuoser" type="success">是</el-tag>
+          <el-tag v-if="!scope.row.cuoser" type="danger">否</el-tag>
         </template>
       </el-table-column>
+
       <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
         <template slot-scope="scope">
           <el-button
@@ -78,6 +79,7 @@ export default {
       title: "",
       // 是否显示弹出层
       open: false,
+      cuoser: false,
       // 状态字典
       statusOptions: [],
       // 查询参数
@@ -107,12 +109,16 @@ export default {
   },
   methods: {
     /** 查询sop模板列表 */
-    getList(sendType,isUpdate) {
+    getList(sendType,isUpdate,cuoser) {
+      if(cuoser == null){
+        cuoser = false;
+      }
       console.log(isUpdate)
       this.isUpdateSop = isUpdate;
+      this.cuoser = cuoser;
       this.loading = true;
       this.queryParams.sendType= sendType;
-      this.queryParams.status=1;
+      this.queryParams.cuoser= cuoser;
       listSopTemp(this.queryParams).then(response => {
         this.sopTempList = response.rows;
         this.total = response.total;

A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 446 - 332
src/views/qw/sopTemp/updateSopTemp.vue


+ 5 - 0
src/views/qw/sopUserLogs/sopUserLogsSchedule.vue

@@ -56,6 +56,7 @@
       <el-table-column label="营期编号" align="center" prop="id" />
 <!--      <el-table-column label="模板编号" align="center" prop="sopTempId" />-->
       <el-table-column label="企微员工账号" align="center" prop="qwUserId" />
+      <el-table-column label="群聊" align="center" prop="chatName" v-if="filterMode == 2" />
       <el-table-column label="营期时间" align="center" prop="startTime" width="180">
         <template slot-scope="scope">
           <span>{{ parseTime(scope.row.startTime, '{y}-{m}-{d}') }}</span>
@@ -171,6 +172,7 @@ export default {
       sopUserLogsDelStatus:[],
       // 弹出层标题
       title: "",
+      filterMode: 1,
       // 是否显示弹出层
       open: false,
       // 查询参数
@@ -213,6 +215,8 @@ export default {
       this.sysQwSopAiContentType = response.data;
     });
     this.queryParams.sopId = this.$route.params.id;
+    this.filterMode = this.$route.query.filterMode;
+    console.info(this.$route.query)
     this.sopName = this.$route.query.name;
     this.tempId = this.$route.query.tempId;
     this.getList()
@@ -278,6 +282,7 @@ export default {
     },
 
     handleSelect(val){
+      val.filterMode = this.filterMode;
       this.logsInfoDetailsOpen.title='企微账号:'+val.qwUserId+'  '+'营期时间:'+val.startTime+'  '+'天数:' + val.countDays;
       this.logsInfoDetailsOpen.open=true;
       const externalUserName = this.queryParams.externalUserName;

+ 745 - 0
src/views/qw/sopUserLogsInfo/sendMsgOpenTool.vue

@@ -0,0 +1,745 @@
+<template>
+  <div class="app-container">
+    <el-dialog :title="sendMsgOpen.title" :visible.sync="sendMsgOpen.open"  width="1000px" append-to-body>
+      <el-alert
+        type="error"
+        :closable="false"
+        show-icon>
+        <template #title>
+                <span style="font-size: 25px; line-height: 1.5;">
+                    此功能用于给 选中的 营期 内【所有的】客户发送 消息
+                </span>
+        </template>
+      </el-alert>
+        <el-form ref="msgForm" :model="msgForm" :rules="msgRules" label-width="100px">
+          <el-form-item label="策略" prop="draftStrategy">
+            <el-radio-group v-model="msgForm.draftStrategy">
+              <el-radio :label="1">正常群发</el-radio>
+              <el-radio :label="2">清除草稿</el-radio>
+              <el-radio :label="3">发送草稿</el-radio>
+            </el-radio-group>
+          </el-form-item>
+
+          <el-form-item label="选择课程" v-if="msgForm.draftStrategy==1" >
+            <el-select  v-model="msgForm.courseId" placeholder="请选择课程" style=" margin-right: 10px;" size="mini"  @change="courseChange()">
+              <el-option
+                v-for="dict in courseList"
+                :key="dict.dictValue"
+                :label="dict.dictLabel"
+                :value="parseInt(dict.dictValue)"
+              />
+            </el-select>
+            <el-select  v-model="msgForm.videoId" placeholder="请选择小节" size="mini" style=" margin-right: 10px;" @change="videoIdChange()"  >
+              <el-option
+                v-for="dict in videoList"
+                :key="dict.dictValue"
+                :label="dict.dictLabel"
+                :value="parseInt(dict.dictValue)"
+              />
+            </el-select>
+            <el-select  v-model="msgForm.courseType" placeholder="请选择消息类型" size="mini" style=" margin-right: 10px;">
+              <el-option
+                v-for="dict in sysFsSopWatchStatus"
+                :key="dict.dictValue"
+                :label="dict.dictLabel"
+                :value="parseInt(dict.dictValue)"
+              />
+            </el-select>
+          </el-form-item>
+          <el-form-item label="规则" prop="setting" v-if="msgForm.draftStrategy==1"  >
+            <div v-for="(item, index) in setting" :key="index" style="background-color: #fdfdfd; border: 1px solid #e6e6e6; margin-bottom: 20px;">
+              <el-row>
+                <el-col :span="22">
+                  <el-form :model="item" label-width="70px">
+                    <el-form-item label="内容类别" style="margin: 2%">
+                      <el-radio-group  v-model="item.contentType">
+                        <el-radio   :label="item.dictValue" v-for="item in sysQwSopAiContentType"  @change="handleContentTypeChange()">{{item.dictLabel}}</el-radio>
+                      </el-radio-group>
+                    </el-form-item>
+                    <el-form-item label="内容" style="margin-bottom: 2%" >
+                      <el-input
+                        v-if="item.contentType == 1"
+                        v-model="item.value"
+                        type="textarea"
+                        :rows="3"
+                        placeholder="内容"
+                        style="width: 90%; margin-top: 10px;"
+                        @keydown.native="handleKeydown($event, index)"
+                        :ref="`textarea-${index}`"
+                      >
+                      </el-input>
+                      <el-link
+                        v-if="item.contentType == 1"
+                        type="primary"
+                        @click="toggleSalesCall(index)"
+                        style="margin-top: 10px;"
+                      >
+                        {{ item.isSalesCallAdded ? '移除#销售称呼#' : '添加#销售称呼#' }}
+                      </el-link>
+                      <el-link
+                        v-if="item.contentType == 1"
+                        type="primary"
+                        @click="toggleSalesCallCustomer(index)"
+                        style="margin-top: 10px;margin-left: 2%"
+                      >
+                        {{ item.isSalesCallCustomerAdded ? '移除#客户称呼#' : '添加#客户称呼#' }}
+                      </el-link>
+
+
+                      <ImageUpload v-if="item.contentType == 2 " v-model="item.imgUrl" type="image" :num="1"  :width="150" :height="150" />
+
+                      <div v-if="item.contentType == 3 || item.contentType ==9 ">
+                        <el-card class="box-card">
+                          <el-form-item label="链接标题:"  label-width="100px">
+                            <el-input v-model="item.linkTitle" placeholder="请输入链接标题" style="width: 90%;"/>
+                          </el-form-item>
+                          <el-form-item label="链接描述:"   label-width="100px" >
+                            <el-input type="textarea" :rows="3" v-model="item.linkDescribe" placeholder="请输入链接描述" style="width: 90%;margin-top: 1%;"/>
+                          </el-form-item>
+                          <el-form-item label="链接封面:"   label-width="100px">
+                            <ImageUpload v-model="item.linkImageUrl" type="image" :num="1" :file-size="2" :width="150" :height="150" style="margin-top: 1%;" />
+                          </el-form-item>
+                          <el-form-item label="链接地址:"  label-width="100px" >
+                            <el-tag type="warning" v-model="item.isBindUrl=1">选择的课程小节 即为卡片链接地址</el-tag>
+                          </el-form-item>
+                        </el-card>
+                      </div>
+                      <div v-if="item.contentType == 4">
+                        <el-card class="box-card">
+                          <el-form-item label="标题" prop="miniprogramTitle">
+                            <el-input v-model="item.miniprogramTitle" placeholder="请输入小程序消息标题,最长为64字"  />
+                          </el-form-item>
+                          <el-form-item label="封面" prop="miniprogramPicUrl">
+                            <ImageUpload v-model="item.miniprogramPicUrl"  type="image" :num="10" :width="150" :height="150" />
+                          </el-form-item>
+                          <el-form-item label="appid" prop="miniprogramAppid" v-show="false" >
+                            <el-input v-model="item.miniprogramAppid='wx73f85f8d62769119' " disabled />
+                          </el-form-item>
+                          <el-form-item label="page路径" prop="miniprogramPage" v-show="false" label-width="100px" style="margin-left: -30px" >
+                            <el-input v-model="item.miniprogramPage" placeholder="小程序消息打开后的路径"  disabled />
+                          </el-form-item>
+                        </el-card>
+                      </div>
+                      <div v-if="item.contentType == 5 ">
+
+                        <el-form-item label="上传文件:" prop="fileUrl" label-width="100px">
+                          <el-upload
+                            v-model="item.fileUrl"
+                            class="avatar-uploader"
+                            :action="uploadUrl"
+                            :show-file-list="false"
+                            :on-success="(res, file) => handleAvatarSuccessFile(res, file, item)"
+                            :before-upload="beforeAvatarUploadFile">
+                            <i class="el-icon-plus avatar-uploader-icon"></i>
+                          </el-upload>
+                          <el-link v-if="item.fileUrl" type="primary" :href="downloadUrl(item.fileUrl)" download>
+                            {{item.fileUrl}}
+                          </el-link>
+                        </el-form-item>
+
+                      </div>
+
+                      <div v-if="item.contentType == 6 ">
+                        <el-form-item label="上传视频:" prop="videoUrl" label-width="100px">
+                          <el-upload
+                            v-model="item.videoUrl"
+                            class="avatar-uploader"
+                            :action="uploadUrl"
+                            :show-file-list="false"
+                            :on-success="(res, file) => handleAvatarSuccessVideo(res, file, item)"
+                            :before-upload="beforeAvatarUploadVideo">
+                            <i class="el-icon-plus avatar-uploader-icon"></i>
+                          </el-upload>
+                          <video v-if="item.videoUrl"
+                                 :src="item.videoUrl"
+                                 controls style="width: 200px;height: 100px">
+                          </video>
+                        </el-form-item>
+                      </div>
+                      <div v-if="item.contentType == 7 ">
+                        <el-input
+                          v-model="item.value"
+                          type="textarea" :rows="3" maxlength="66" show-word-limit
+                          placeholder="输入要转为语音的内容" style="width: 90%;margin-top: 10px;"
+                          @input="handleInputVideoText(item.value,item)"/>
+                      </div>
+                      <div v-if="item.contentType == 8">
+
+                      </div>
+
+                    </el-form-item>
+
+                    <el-form-item label="添加短链" v-if="item.contentType == 1 "  >
+                      <el-tooltip content="请先根据课程选定课程小节之后再添加" effect="dark" :disabled="!!msgForm.videoId">
+                        <el-switch
+                          v-model="item.isBindUrl"
+                          :disabled="!msgForm.videoId"
+                          active-color="#13ce66"
+                          inactive-color="#DCDFE6"
+                          active-value="1"
+                          inactive-value="2">
+                        </el-switch>
+                      </el-tooltip>
+
+                      <span v-if="item.isBindUrl == '1'" style="margin-left: 10px; color: #13ce66">添加URL</span>
+                      <span v-if="item.isBindUrl == '2'" style="margin-left: 10px; color: #b1b4ba">不加URL</span>
+                    </el-form-item>
+                    <el-form-item label="课节过期时间" v-if="item.isBindUrl == '1'
+                                                          && item.contentType != 2
+                                                          && item.contentType != 5
+                                                          && item.contentType != 6
+                                                          && item.contentType != 8"
+                                  style="margin-top: 1%" label-width="100px">
+                      <el-row>
+                        <el-input-number  v-model="item.expiresDays"  :min="1" :max="100" ></el-input-number>
+                        (天)
+                      </el-row>
+                      <el-row>
+                        <span class="tip">填写0或不填时,默认为系统配置的默认时间</span>
+                      </el-row>
+                    </el-form-item>
+                  </el-form>
+                </el-col>
+                <el-col :span="1" :offset="1">
+                  <i class="el-icon-delete" @click="delSetList(index)" style="margin-top: 20px;" v-if="setting.length>1"></i>
+                </el-col>
+              </el-row>
+            </div>
+            <el-link type="primary" class="el-icon-plus" :underline="false" @click='addSetList()'  >添加内容</el-link>
+
+          </el-form-item>
+          <el-form-item label="发送时间" prop="sendTime" v-if="msgForm.draftStrategy==1" >
+            <el-time-picker
+              class="custom-input"
+              v-model="msgForm.sendTime"
+              value-format="HH:mm"
+              format="HH:mm"
+              placeholder="时间"
+              style="width: 100px;height: 20px;">
+            </el-time-picker>
+            <span class="tip" style="margin-left: 2%"> 不填时,默认为系统当前时间(立即发送)</span>
+          </el-form-item>
+
+        </el-form>
+        <div slot="footer" class="dialog-footer">
+          <el-button type="primary" @click="submitMsgForm">确 定</el-button>
+          <el-button @click="cancelMsgForm">取 消</el-button>
+        </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { sendMsgSopType,} from "../../../api/qw/sopUserLogsInfo";
+import ImageUpload from "@/views/qw/sop/ImageUpload.vue";
+import {courseList, videoList} from "@/api/qw/sop";
+
+
+export default {
+  name: "sendMsgOpenTool",
+  components: {ImageUpload},
+  data() {
+    return {
+      //上传语音的遮罩层
+      voiceLoading :false,
+      uploadUrl:process.env.VUE_APP_BASE_API+"/common/uploadOSS",
+      uploadUrlByVoice:process.env.VUE_APP_BASE_API+"/common/uploadOSSByHOOKVoice",
+      // 遮罩层
+      loading: true,
+      // 导出遮罩层
+      exportLoading: false,
+      // 选中数组
+      ids: [],
+      // 非单个禁用
+      single: true,
+      // 非多个禁用
+      multiple: true,
+      // 显示搜索条件
+      showSearch: true,
+      // 总条数
+      total: 0,
+      // sopUserLogsInfo表格数据
+      sopUserLogsInfoList: [],
+      sysFsSopWatchStatus: [],
+      isSalesCallAdded:false,
+      isSalesCallCustomerAdded:false,
+      tagList:[],
+      selectTags:[],
+      // 弹出层标题
+      title: "",
+      // 是否显示弹出层
+      open: false,
+      updateOpen:false,
+      // 查询参数
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        tagIds:null,
+        remark:null,
+        sopId: null,
+        userLogsId: null,
+        userIdParam:null,
+        startTimeParam:null,
+        externalContactId: null,
+        qwUserId: null,
+        corpId: null,
+        externalId: null,
+        fsUserId: null,
+        externalUserName: null,
+        createTime: null,
+      },
+
+      courseList:[],
+      videoList:[],
+      //插件版
+      sysQwSopAiContentType:[],
+
+      sendMsgOpen:{
+        title:'一键批量群发',
+        open:false,
+        ids:null,
+      },
+      // 表单参数
+      form: {},
+      setting:[{contentType:'1', value: '',}],
+      msgForm:{
+        videoId:null,
+        courseId:null,
+        courseType:null,
+        userIdParam:null,
+        setting:null,
+        ids:null,
+        type:null,
+        corpId:null,
+        sopId: null,
+        startTime: null,
+        sendTime: null,
+        draftStrategy:1,
+      },
+      // 表单校验
+      rules: {},
+      batchRules:{
+        paramTime: [
+          { required: true, message: '选择的时间不能为空', trigger: 'blur' }
+        ],
+      },
+      msgRules:{},
+    };
+  },
+
+  created() {
+    this.getDicts("sys_qwSopAi_contentType").then(response => {
+      this.sysQwSopAiContentType = response.data;
+    });
+    this.getDicts("sys_fs_sop_watch_status").then(response => {
+      this.sysFsSopWatchStatus = response.data;
+    });
+
+    courseList().then(response => {
+      this.courseList = response.list;
+    });
+  },
+  methods: {
+
+    oneClickGroupSending(val,type,corpId){
+
+      this.sendMsgOpen.open= true;
+      this.msgForm.ids = val;
+      this.msgForm.type = type;
+      this.msgForm.corpId = corpId;
+
+    },
+    courseChange() {
+      if (this.msgForm.courseId != null ) {
+        const selectedCourse = this.courseList.find(course => parseInt(course.dictValue) === this.msgForm.courseId);
+        for (let i = 0; i < this.setting.length; i++) {
+          //响应式直接给链接的标题/封面上值
+          if (selectedCourse && this.msgForm.courseId != null) {
+            if ( this.setting[i].contentType == 3 || this.setting[i].contentType == 9 ){
+              this.$set(this.setting[i], 'linkTitle', selectedCourse.dictLabel);
+              this.$set(this.setting[i], 'linkImageUrl', selectedCourse.dictImgUrl);
+            }
+
+            if ( this.setting[i].contentType == 4 ){
+              this.$set(this.setting[i], 'miniprogramPicUrl', selectedCourse.dictImgUrl);
+            }
+          }
+
+        }
+
+      }
+      videoList(this.msgForm.courseId).then(response => {
+        this.videoList=response.list;
+      });
+    },
+
+    videoIdChange() {
+      if (this.msgForm.videoId != null ) {
+        // 查找选中的课节对应的 label
+        const selectedVideo = this.videoList.find(course => parseInt(course.dictValue) === this.msgForm.videoId);
+
+        for (let i = 0; i < this.setting.length; i++) {
+          //响应式直接给链接的描述上值
+          if (selectedVideo && this.msgForm.videoId != null) {
+            if (this.setting[i].contentType == 3 || this.setting[i].contentType == 9 ){
+              this.$set(this.setting[i], 'linkDescribe', selectedVideo.dictLabel);
+            }
+
+            if (this.setting[i].contentType == 4){
+              this.$set(this.setting[i], 'miniprogramTitle', selectedVideo.dictLabel);
+            }
+
+
+          }
+        }
+      }
+    },
+    handleAvatarSuccessFile(res, file, item) {
+      if (res.code === 200) {
+        // 使用 $set 确保响应式更新
+        this.$set(item, 'fileUrl', res.url);
+      } else {
+        this.msgError(res.msg);
+      }
+    },
+    beforeAvatarUploadFile(file){
+      const isLt1M = file.size / 1024 / 1024 < 10;
+      if (!isLt1M) {
+        this.$message.error('上传大小不能超过 10MB!');
+      }
+      return isLt1M;
+    },
+    //下载文件
+    downloadUrl(materialUrl) {
+      // 直接返回文件 URL
+      return materialUrl;
+    },
+
+    handleAvatarSuccessVideo(res, file, item) {
+      if(res.code==200){
+        // 使用 $set 确保响应式更新
+        this.$set(item, 'videoUrl', res.url);
+      }
+      else{
+        this.msgError(res.msg);
+      }
+    },
+
+    beforeAvatarUploadVideo(file){
+      const isLt30M = file.size / 1024 / 1024 < 10;
+      const isMP4 = file.type === 'video/mp4';
+
+      if (!isMP4) {
+        this.$message.error('仅支持上传 MP4 格式的视频文件!');
+        return false;
+      }
+
+      if (!isLt30M) {
+        this.$message.error('上传大小不能超过 10MB!');
+        return false;
+      }
+
+      return true;
+    },
+
+    handleInputVideoText(value,content){
+      // 允许的字符:中文、英文(大小写)、数字和指定标点符号(,。!?)
+      const regex = /^[\u4e00-\u9fa5,。!?,!?]+$/;
+
+      // 删除不符合条件的字符
+      const filteredValue = value.split('').filter(char => regex.test(char)).join('');
+
+      this.$set(content, 'value', filteredValue);
+
+    },
+
+    delSetList(index){
+      this.setting.splice(index,1)
+    },
+    addSetList(){
+      const newSetting = {
+        contentType:'1',
+        value: '',
+      };
+      // 将新设置项添加到 content.setting 数组中
+      this.setting.push(newSetting);
+
+    },
+
+
+    handleKeydown(event, index) {
+      const item = this.setting[index];
+      const textarea = this.$refs[`textarea-${index}`][0].$refs.textarea;
+      const cursorPosition = textarea.selectionStart;
+
+      // 检查是否按下了 Backspace 或 Delete 键
+      if (event.key === 'Backspace' || event.key === 'Delete') {
+        const tags = ['#销售称呼#', '#客户称呼#']; // 需要检查的标签
+        const value = item.value;
+
+        // 遍历标签,检查是否需要删除
+        for (const tag of tags) {
+          let start, end;
+
+          if (event.key === 'Backspace') {
+            // 检查光标前是否是当前标签的一部分
+            start = cursorPosition - tag.length;
+            if (start >= 0 && value.slice(start, cursorPosition) === tag) {
+              // 删除整个标签
+              item.value = value.slice(0, start) + value.slice(cursorPosition);
+              // 更新光标位置
+              this.$nextTick(() => {
+                textarea.setSelectionRange(start, start);
+              });
+              // 更新状态
+              if (tag === '#销售称呼#') item.isSalesCallAdded = false;
+              if (tag === '#客户称呼#') item.isSalesCallCustomerAdded = false;
+              event.preventDefault(); // 阻止默认删除行为
+              break; // 找到匹配的标签后退出循环
+            }
+          } else if (event.key === 'Delete') {
+            // 检查光标后是否是当前标签的一部分
+            end = cursorPosition + tag.length;
+            if (end <= value.length && value.slice(cursorPosition, end) === tag) {
+              // 删除整个标签
+              item.value = value.slice(0, cursorPosition) + value.slice(end);
+              // 更新状态
+              if (tag === '#销售称呼#') item.isSalesCallAdded = false;
+              if (tag === '#客户称呼#') item.isSalesCallCustomerAdded = false;
+              event.preventDefault(); // 阻止默认删除行为
+              break; // 找到匹配的标签后退出循环
+            }
+          }
+
+          // 检查光标是否位于标签的中间
+          for (let i = 0; i <= tag.length; i++) {
+            const tagStart = cursorPosition - i;
+            const tagEnd = tagStart + tag.length;
+            if (
+              tagStart >= 0 &&
+              tagEnd <= value.length &&
+              value.slice(tagStart, tagEnd) === tag
+            ) {
+              // 删除整个标签
+              item.value = value.slice(0, tagStart) + value.slice(tagEnd);
+              // 更新光标位置
+              this.$nextTick(() => {
+                textarea.setSelectionRange(tagStart, tagStart);
+              });
+              // 更新状态
+              if (tag === '#销售称呼#') item.isSalesCallAdded = false;
+              if (tag === '#客户称呼#') item.isSalesCallCustomerAdded = false;
+              event.preventDefault(); // 阻止默认删除行为
+              break; // 找到匹配的标签后退出循环
+            }
+          }
+        }
+      }
+    },
+
+    // 切换添加销售称呼按钮点击事件
+    toggleSalesCall(index) {
+      const item = this.setting[index];
+      const salesCall = '#销售称呼#';
+      const textarea = this.$refs[`textarea-${index}`][0].$refs.textarea;
+
+      // 获取当前光标位置
+      const cursorPosition = textarea.selectionStart;
+
+      if (item.isSalesCallAdded) {
+        // 移除所有的 #销售称呼#
+        item.value = item.value.replace(new RegExp(salesCall, 'g'), '');
+      } else {
+        // 添加 #销售称呼#
+        item.value = item.value.slice(0, cursorPosition) + salesCall + item.value.slice(cursorPosition);
+      }
+
+      // 切换状态
+      item.isSalesCallAdded = !item.isSalesCallAdded;
+
+      // 保持光标位置
+      this.$nextTick(() => {
+        textarea.setSelectionRange(cursorPosition, cursorPosition);
+      });
+    },
+    toggleSalesCallCustomer(index) {
+      const item = this.setting[index];
+      const salesCall = '#客户称呼#';
+      const textarea = this.$refs[`textarea-${index}`][0].$refs.textarea;
+
+      // 获取当前光标位置
+      const cursorPosition = textarea.selectionStart;
+
+      if (item.isSalesCallCustomerAdded) {
+        // 移除所有的 #销售称呼#
+        item.value = item.value.replace(new RegExp(salesCall, 'g'), '');
+      } else {
+        // 添加 #客户称呼#
+        item.value = item.value.slice(0, cursorPosition) + salesCall + item.value.slice(cursorPosition);
+      }
+
+      // 切换状态
+      item.isSalesCallCustomerAdded = !item.isSalesCallCustomerAdded;
+
+      // 保持光标位置
+      this.$nextTick(() => {
+        textarea.setSelectionRange(cursorPosition, cursorPosition);
+      });
+    },
+
+    handleContentTypeChange() {
+
+      //如果是链接的才上
+      if (this.msgForm.courseId != null ) {
+        const selectedCourse = this.courseList.find(course => parseInt(course.dictValue) === this.msgForm.courseId);
+        for (let i = 0; i < this.setting.length; i++) {
+          //响应式直接给链接的标题/封面上值
+          if (selectedCourse  && this.msgForm.courseId != null) {
+
+            if (this.setting[i].contentType == 3 || this.setting[i].contentType == 9){
+              this.$set(this.setting[i], 'linkTitle', selectedCourse.dictLabel);
+              this.$set(this.setting[i], 'linkImageUrl', selectedCourse.dictImgUrl);
+            }
+            if (this.setting[i].contentType == 4){
+              this.$set(this.setting[i], 'miniprogramPicUrl', selectedCourse.dictImgUrl);
+            }
+
+
+          }
+
+        }
+
+      }
+      if (this.msgForm.videoId != null ) {
+        // 查找选中的课节对应的 label
+        const selectedVideo = this.videoList.find(course => parseInt(course.dictValue) === this.msgForm.videoId);
+
+        for (let i = 0; i < this.setting.length; i++) {
+          //响应式直接给链接的描述上值
+          if (selectedVideo  && this.msgForm.videoId != null) {
+
+            if (this.setting[i].contentType == 3 || this.setting[i].contentType == 9){
+              this.$set(this.setting[i], 'linkDescribe', selectedVideo.dictLabel);
+            }
+            if (this.setting[i].contentType == 4){
+              this.$set(this.setting[i], 'miniprogramTitle', selectedVideo.dictLabel);
+            }
+
+          }
+        }
+      }
+
+
+    },
+
+    resetSendMsgSop() {
+      this.msgForm = {
+        videoId:null,
+        courseId:null,
+        courseType:null,
+        setting:null,
+        sendTime:null,
+        draftStrategy:1,
+      };
+      this.resetForm("msgForm");
+    },
+    // 多选框选中数据
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.id)
+      this.single = selection.length!==1
+      this.multiple = !selection.length
+    },
+
+    submitMsgForm(){
+
+      this.$refs["msgForm"].validate(valid => {
+        if (valid) {
+
+          if (this.msgForm.draftStrategy==1){
+
+            this.msgForm.setting=JSON.stringify(this.setting)
+
+            if (this.setting.length <= 0) {
+              return this.$message.error("请添加规则")
+            }
+            if (this.msgForm.courseId===null || this.msgForm.courseId===''){
+              return this.$message.error("课程不能为空")
+            }
+
+            if (this.msgForm.videoId===null || this.msgForm.videoId===''){
+              return this.$message.error("课节不能为空")
+            }
+
+            if (this.msgForm.courseType===null || this.msgForm.courseType===''){
+              return this.$message.error("消息类型不能为空")
+            }
+
+            for (let i = 0; i < this.setting.length; i++) {
+              if (this.setting[i].contentType == 1 && (this.setting[i].value == null || this.setting[i].value == "")) {
+                return this.$message.error("内容不能为空")
+              }
+              if (this.setting[i].contentType == 2 && (this.setting[i].imgUrl == null || this.setting[i].imgUrl == "")) {
+                return this.$message.error("图片不能为空")
+              }
+              if ((this.setting[i].contentType == 3 || this.setting[i].contentType == 9  ) && (this.setting[i].linkTitle == null || this.setting[i].linkTitle == "")) {
+                return this.$message.error("链接标题不能为空")
+              }
+              if ((this.setting[i].contentType == 3 || this.setting[i].contentType == 9 ) && (this.setting[i].linkDescribe == null || this.setting[i].linkDescribe == "")) {
+                return this.$message.error("链接描述不能为空")
+              }
+              if ((this.setting[i].contentType == 3 || this.setting[i].contentType == 9 ) && (this.setting[i].linkImageUrl == null || this.setting[i].linkImageUrl == "")) {
+                return this.$message.error("链接图片不能为空")
+              }
+              if ((this.setting[i].contentType == 3 || this.setting[i].contentType == 9 )&& this.setting[i].type == 1 && (this.setting[i].linkUrl == null || this.setting[i].linkUrl == "")) {
+                return this.$message.error("链接地址不能为空")
+              }
+
+              if (this.setting[i].contentType == 4 && (this.setting[i].miniprogramTitle == null || this.setting[i].miniprogramTitle == "")) {
+                return this.$message.error("小程序消息标题不能为空")
+              }
+              if (this.setting[i].contentType == 4 && (this.setting[i].miniprogramPicUrl == null || this.setting[i].miniprogramPicUrl == "")) {
+                return this.$message.error("小程序封面地址不能为空")
+              }
+              if (this.setting[i].contentType == 5 && (this.setting[i].fileUrl == null || this.setting[i].fileUrl == "")) {
+                return this.$message.error("文件不能为空")
+              }
+              if (this.setting[i].contentType == 6 && (this.setting[i].videoUrl == null || this.setting[i].videoUrl == "")) {
+                return this.$message.error("视频不能为空")
+              }
+              if (this.setting[i].contentType == 7 && (this.setting[i].value == null || this.setting[i].value == "")) {
+                return this.$message.error("语音不能为空")
+              }
+            }
+          }
+
+
+
+          this.sendMsgOpen.open = false;
+
+          const loading = this.$loading({
+            lock: true,
+            text: '正在执行中请稍后~~请不要刷新页面!!',
+            spinner: 'el-icon-loading',
+            background: 'rgba(0, 0, 0, 0.7)'
+          });
+
+          sendMsgSopType(this.msgForm).then(response => {
+            this.msgSuccess("一键群发成功");
+            loading.close();
+            this.setting=[];
+            this.resetSendMsgSop();
+          }).finally(()=>{
+            loading.close();
+          });
+
+        }
+      });
+    },
+    cancelMsgForm(){
+      this.sendMsgOpen.open = false;
+      this.resetSendMsgSop();
+    },
+
+  }
+};
+</script>

+ 82 - 239
src/views/qw/sopUserLogsInfo/sopUserLogsInfoDetails.vue

@@ -54,7 +54,7 @@
       <el-col :span="1.5">
         <el-button
           type="warning"
-          icon="el-icon-s-promotion"
+          icon="el-icon-s-platform"
           size="medium"
           :disabled="multiple"
           @click="handleSendMsg"
@@ -69,10 +69,10 @@
           size="medium"
           :disabled="multiple"
           @click="handleUpdate"
+          v-if="queryParams.filterMode == 1"
           v-hasPermi="['qw:sopUserLogsInfo:edit']"
         >批量修改客户营期</el-button>
       </el-col>
-
 <!--      <el-col :span="1.5">-->
 <!--        <el-button-->
 <!--          type="success"-->
@@ -86,7 +86,7 @@
 <!--      </el-col>-->
     </el-row>
 
-    <el-table border v-loading="loading" :data="sopUserLogsInfoList" @selection-change="handleSelectionChange">
+    <el-table border v-loading="loading" :data="sopUserLogsInfoList" @selection-change="handleSelectionChange" v-if="queryParams.filterMode == 1">
       <el-table-column type="selection" width="55" align="center" />
       <el-table-column label="编号" align="center" prop="id" width="100"/>
 <!--      <el-table-column label="企微员工账号" align="center" prop="qwUserId" width="100"/>-->
@@ -144,7 +144,36 @@
       </el-table-column>
     </el-table>
 
-    <pagination-more
+    <el-table border v-loading="loading" :data="sopUserLogsInfoList" @selection-change="handleSelectionChange" v-if="queryParams.filterMode == 2">
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="编号" align="center" prop="id" width="100"/>
+      <el-table-column label="客户名称" align="center" prop="name" />
+      <el-table-column label="备注" align="center" prop="remark" />
+      <el-table-column label="客户标签" align="center" prop="tagIds" width="240">
+        <template slot-scope="scope">
+          <div v-if="scope.row.tagIds && scope.row.tagIds !== '无标签'">
+            <div v-for="i in JSON.parse(scope.row.tagIds)" :key="i" style="display: inline;">
+              <el-tag
+                type="success"
+                v-for="ii in tagList"
+                :key="ii.id"
+                style="margin: 3px;"
+                v-if="ii.tagId == i"
+              >
+                {{ ii.name }}
+              </el-tag>
+            </div>
+          </div>
+          <div v-else>
+            <span style="color: red;">无标签</span>
+          </div>
+        </template>
+      </el-table-column>
+      <el-table-column label="加群时间" align="center" prop="joinTime" width="180"/>
+      <el-table-column label="进线时间" align="center" prop="inComTime" width="180"/>
+    </el-table>
+
+    <pagination
       v-show="total>0"
       :total="total"
       :page.sync="queryParams.pageNum"
@@ -180,6 +209,12 @@
               />
             </el-select>
           </el-form-item>
+          <el-form-item label="只发送注册用户" prop="isRegister" label-width="120px" >
+                  <el-radio-group v-model="msgForm.isRegister">
+                     <el-radio v-model="msgForm.isRegister" :label="1">是</el-radio>
+                     <el-radio v-model="msgForm.isRegister" :label="2">否</el-radio>
+                  </el-radio-group>
+          </el-form-item>
           <el-form-item label="规则" prop="setting"  >
             <div v-for="(item, index) in setting" :key="index" style="background-color: #fdfdfd; border: 1px solid #e6e6e6; margin-bottom: 20px;">
               <el-row>
@@ -191,38 +226,11 @@
                       </el-radio-group>
                     </el-form-item>
                     <el-form-item label="内容" style="margin-bottom: 2%" >
-                      <el-input
-                        v-if="item.contentType == 1"
-                        v-model="item.value"
-                        type="textarea"
-                        :rows="3"
-                        placeholder="内容"
-                        style="width: 90%; margin-top: 10px;"
-                        @keydown.native="handleKeydown($event, index)"
-                        :ref="`textarea-${index}`"
-                      >
-                      </el-input>
-                      <el-link
-                        v-if="item.contentType == 1"
-                        type="primary"
-                        @click="toggleSalesCall(index)"
-                        style="margin-top: 10px;"
-                      >
-                        {{ item.isSalesCallAdded ? '移除#销售称呼#' : '添加#销售称呼#' }}
-                      </el-link>
-                      <el-link
-                        v-if="item.contentType == 1"
-                        type="primary"
-                        @click="toggleSalesCallCustomer(index)"
-                        style="margin-top: 10px;margin-left: 2%"
-                      >
-                        {{ item.isSalesCallCustomerAdded ? '移除#客户称呼#' : '添加#客户称呼#' }}
-                      </el-link>
-
+                      <el-input v-if="item.contentType == 1 " v-model="item.value" type="textarea" :rows="3" placeholder="内容" style="width: 90%;margin-top: 10px;"/>
 
                       <ImageUpload v-if="item.contentType == 2 " v-model="item.imgUrl" type="image" :num="1"  :width="150" :height="150" />
 
-                      <div v-if="item.contentType == 3 || item.contentType ==9 ">
+                      <div v-if="item.contentType == 3 ">
                         <el-card class="box-card">
                           <el-form-item label="链接标题:"  label-width="100px">
                             <el-input v-model="item.linkTitle" placeholder="请输入链接标题" style="width: 90%;"/>
@@ -239,20 +247,7 @@
                         </el-card>
                       </div>
                       <div v-if="item.contentType == 4">
-                        <el-card class="box-card">
-                          <el-form-item label="标题" prop="miniprogramTitle">
-                            <el-input v-model="item.miniprogramTitle" placeholder="请输入小程序消息标题,最长为64字"  />
-                          </el-form-item>
-                          <el-form-item label="封面" prop="miniprogramPicUrl">
-                            <ImageUpload v-model="item.miniprogramPicUrl"  type="image" :num="10" :width="150" :height="150" />
-                          </el-form-item>
-                          <el-form-item label="appid" prop="miniprogramAppid" v-show="false" >
-                            <el-input v-model="item.miniprogramAppid='wx73f85f8d62769119' " disabled />
-                          </el-form-item>
-                          <el-form-item label="page路径" prop="miniprogramPage" v-show="false" label-width="100px" style="margin-left: -30px" >
-                            <el-input v-model="item.miniprogramPage" placeholder="小程序消息打开后的路径"  disabled />
-                          </el-form-item>
-                        </el-card>
+
                       </div>
                       <div v-if="item.contentType == 5 ">
 
@@ -297,10 +292,23 @@
                           placeholder="输入要转为语音的内容" style="width: 90%;margin-top: 10px;"
                           @input="handleInputVideoText(item.value,item)"/>
                       </div>
-                      <div v-if="item.contentType == 8">
 
+                      <div v-if="item.contentType == 10 ">
+                        <el-card class="box-card">
+                          <el-form-item label="链接标题:"  label-width="100px">
+                            <el-input v-model="item.linkTitle" placeholder="请输入链接标题" style="width: 90%;"/>
+                          </el-form-item>
+                          <el-form-item label="链接描述:"   label-width="100px" >
+                            <el-input type="textarea" :rows="3" v-model="item.linkDescribe" placeholder="请输入链接描述" style="width: 90%;margin-top: 1%;"/>
+                          </el-form-item>
+                          <el-form-item label="链接封面:"   label-width="100px">
+                            <ImageUpload v-model="item.linkImageUrl" type="image" :num="1" :file-size="2" :width="150" :height="150" style="margin-top: 1%;" />
+                          </el-form-item>
+                          <el-form-item label="链接地址:"  label-width="100px" >
+                            <el-tag type="warning" >链接地址自动生成</el-tag>
+                          </el-form-item>
+                        </el-card>
                       </div>
-
                     </el-form-item>
 
                     <el-form-item label="添加短链" v-if="item.contentType == 1 "  >
@@ -322,7 +330,9 @@
                                                           && item.contentType != 2
                                                           && item.contentType != 5
                                                           && item.contentType != 6
-                                                          && item.contentType != 8"
+                                                          && item.contentType != 8
+                                                          && item.contentType != 9
+                                                          && item.contentType != 10"
                                   style="margin-top: 1%" label-width="100px">
                       <el-row>
                         <el-input-number  v-model="item.expiresDays"  :min="1" :max="100" ></el-input-number>
@@ -380,8 +390,6 @@ import {
 } from "@/api/qw/sopUserLogsInfo";
 import ImageUpload from "@/views/qw/sop/ImageUpload.vue";
 import {courseList, videoList} from "@/api/qw/sop";
-import {addCourseFinishTemp, updateCourseFinishTemp} from "@/api/course/courseFinishTemp";
-import {allListTagGroup} from "@/api/qw/tagGroup";
 import {listTag} from "@/api/qw/tag";
 
 export default {
@@ -410,8 +418,6 @@ export default {
       // sopUserLogsInfo表格数据
       sopUserLogsInfoList: [],
       sysFsSopWatchStatus: [],
-      isSalesCallAdded:false,
-      isSalesCallCustomerAdded:false,
       tagList:[],
       selectTags:[],
       // 弹出层标题
@@ -461,6 +467,7 @@ export default {
         ids:null,
         sopId: null,
         startTime: null,
+        isRegister:2
       },
       // 表单校验
       rules: {},
@@ -472,7 +479,6 @@ export default {
       msgRules:{},
     };
   },
-
   created() {
     this.getDicts("sys_qwSopAi_contentType").then(response => {
       this.sysQwSopAiContentType = response.data;
@@ -491,7 +497,9 @@ export default {
 
       this.loading = true;
       this.queryParams.sopId=val.sopId;
+      this.queryParams.filterMode=val.filterMode;
       this.queryParams.userLogsId=val.id;
+      this.queryParams.chatId=val.chatId;
       if (externalUserName!=null){
         this.queryParams.externalUserName = externalUserName;
       }
@@ -522,15 +530,9 @@ export default {
         const selectedCourse = this.courseList.find(course => parseInt(course.dictValue) === this.msgForm.courseId);
         for (let i = 0; i < this.setting.length; i++) {
           //响应式直接给链接的标题/封面上值
-          if (selectedCourse && this.msgForm.courseId != null) {
-            if ( this.setting[i].contentType == 3 || this.setting[i].contentType == 9 ){
-              this.$set(this.setting[i], 'linkTitle', selectedCourse.dictLabel);
-              this.$set(this.setting[i], 'linkImageUrl', selectedCourse.dictImgUrl);
-            }
-
-            if ( this.setting[i].contentType == 4 ){
-              this.$set(this.setting[i], 'miniprogramPicUrl', selectedCourse.dictImgUrl);
-            }
+          if (selectedCourse && this.setting[i].contentType == 3 && this.msgForm.courseId != null) {
+            this.$set(this.setting[i], 'linkTitle', selectedCourse.dictLabel);
+            this.$set(this.setting[i], 'linkImageUrl', selectedCourse.dictImgUrl);
           }
 
         }
@@ -548,16 +550,8 @@ export default {
 
         for (let i = 0; i < this.setting.length; i++) {
           //响应式直接给链接的描述上值
-          if (selectedVideo && this.msgForm.videoId != null) {
-            if (this.setting[i].contentType == 3 || this.setting[i].contentType == 9 ){
-              this.$set(this.setting[i], 'linkDescribe', selectedVideo.dictLabel);
-            }
-
-            if (this.setting[i].contentType == 4){
-              this.$set(this.setting[i], 'miniprogramTitle', selectedVideo.dictLabel);
-            }
-
-
+          if (selectedVideo && this.setting[i].contentType == 3  && this.msgForm.videoId != null) {
+            this.$set(this.setting[i], 'linkDescribe', selectedVideo.dictLabel);
           }
         }
       }
@@ -634,127 +628,6 @@ export default {
 
     },
 
-
-    handleKeydown(event, index) {
-      const item = this.setting[index];
-      const textarea = this.$refs[`textarea-${index}`][0].$refs.textarea;
-      const cursorPosition = textarea.selectionStart;
-
-      // 检查是否按下了 Backspace 或 Delete 键
-      if (event.key === 'Backspace' || event.key === 'Delete') {
-        const tags = ['#销售称呼#', '#客户称呼#']; // 需要检查的标签
-        const value = item.value;
-
-        // 遍历标签,检查是否需要删除
-        for (const tag of tags) {
-          let start, end;
-
-          if (event.key === 'Backspace') {
-            // 检查光标前是否是当前标签的一部分
-            start = cursorPosition - tag.length;
-            if (start >= 0 && value.slice(start, cursorPosition) === tag) {
-              // 删除整个标签
-              item.value = value.slice(0, start) + value.slice(cursorPosition);
-              // 更新光标位置
-              this.$nextTick(() => {
-                textarea.setSelectionRange(start, start);
-              });
-              // 更新状态
-              if (tag === '#销售称呼#') item.isSalesCallAdded = false;
-              if (tag === '#客户称呼#') item.isSalesCallCustomerAdded = false;
-              event.preventDefault(); // 阻止默认删除行为
-              break; // 找到匹配的标签后退出循环
-            }
-          } else if (event.key === 'Delete') {
-            // 检查光标后是否是当前标签的一部分
-            end = cursorPosition + tag.length;
-            if (end <= value.length && value.slice(cursorPosition, end) === tag) {
-              // 删除整个标签
-              item.value = value.slice(0, cursorPosition) + value.slice(end);
-              // 更新状态
-              if (tag === '#销售称呼#') item.isSalesCallAdded = false;
-              if (tag === '#客户称呼#') item.isSalesCallCustomerAdded = false;
-              event.preventDefault(); // 阻止默认删除行为
-              break; // 找到匹配的标签后退出循环
-            }
-          }
-
-          // 检查光标是否位于标签的中间
-          for (let i = 0; i <= tag.length; i++) {
-            const tagStart = cursorPosition - i;
-            const tagEnd = tagStart + tag.length;
-            if (
-              tagStart >= 0 &&
-              tagEnd <= value.length &&
-              value.slice(tagStart, tagEnd) === tag
-            ) {
-              // 删除整个标签
-              item.value = value.slice(0, tagStart) + value.slice(tagEnd);
-              // 更新光标位置
-              this.$nextTick(() => {
-                textarea.setSelectionRange(tagStart, tagStart);
-              });
-              // 更新状态
-              if (tag === '#销售称呼#') item.isSalesCallAdded = false;
-              if (tag === '#客户称呼#') item.isSalesCallCustomerAdded = false;
-              event.preventDefault(); // 阻止默认删除行为
-              break; // 找到匹配的标签后退出循环
-            }
-          }
-        }
-      }
-    },
-
-    // 切换添加销售称呼按钮点击事件
-    toggleSalesCall(index) {
-      const item = this.setting[index];
-      const salesCall = '#销售称呼#';
-      const textarea = this.$refs[`textarea-${index}`][0].$refs.textarea;
-
-      // 获取当前光标位置
-      const cursorPosition = textarea.selectionStart;
-
-      if (item.isSalesCallAdded) {
-        // 移除所有的 #销售称呼#
-        item.value = item.value.replace(new RegExp(salesCall, 'g'), '');
-      } else {
-        // 添加 #销售称呼#
-        item.value = item.value.slice(0, cursorPosition) + salesCall + item.value.slice(cursorPosition);
-      }
-
-      // 切换状态
-      item.isSalesCallAdded = !item.isSalesCallAdded;
-
-      // 保持光标位置
-      this.$nextTick(() => {
-        textarea.setSelectionRange(cursorPosition, cursorPosition);
-      });
-    },
-    toggleSalesCallCustomer(index) {
-      const item = this.setting[index];
-      const salesCall = '#客户称呼#';
-      const textarea = this.$refs[`textarea-${index}`][0].$refs.textarea;
-
-      // 获取当前光标位置
-      const cursorPosition = textarea.selectionStart;
-
-      if (item.isSalesCallCustomerAdded) {
-        // 移除所有的 #销售称呼#
-        item.value = item.value.replace(new RegExp(salesCall, 'g'), '');
-      } else {
-        // 添加 #客户称呼#
-        item.value = item.value.slice(0, cursorPosition) + salesCall + item.value.slice(cursorPosition);
-      }
-
-      // 切换状态
-      item.isSalesCallCustomerAdded = !item.isSalesCallCustomerAdded;
-
-      // 保持光标位置
-      this.$nextTick(() => {
-        textarea.setSelectionRange(cursorPosition, cursorPosition);
-      });
-    },
-
     handleContentTypeChange() {
 
       //如果是链接的才上
@@ -762,17 +635,9 @@ export default {
         const selectedCourse = this.courseList.find(course => parseInt(course.dictValue) === this.msgForm.courseId);
         for (let i = 0; i < this.setting.length; i++) {
           //响应式直接给链接的标题/封面上值
-          if (selectedCourse  && this.msgForm.courseId != null) {
-
-            if (this.setting[i].contentType == 3 || this.setting[i].contentType == 9){
-              this.$set(this.setting[i], 'linkTitle', selectedCourse.dictLabel);
-              this.$set(this.setting[i], 'linkImageUrl', selectedCourse.dictImgUrl);
-            }
-            if (this.setting[i].contentType == 4){
-              this.$set(this.setting[i], 'miniprogramPicUrl', selectedCourse.dictImgUrl);
-            }
-
-
+          if (selectedCourse && this.setting[i].contentType == 3 && this.msgForm.courseId != null) {
+            this.$set(this.setting[i], 'linkTitle', selectedCourse.dictLabel);
+            this.$set(this.setting[i], 'linkImageUrl', selectedCourse.dictImgUrl);
           }
 
         }
@@ -784,23 +649,14 @@ export default {
 
         for (let i = 0; i < this.setting.length; i++) {
           //响应式直接给链接的描述上值
-          if (selectedVideo  && this.msgForm.videoId != null) {
-
-            if (this.setting[i].contentType == 3 || this.setting[i].contentType == 9){
-              this.$set(this.setting[i], 'linkDescribe', selectedVideo.dictLabel);
-            }
-            if (this.setting[i].contentType == 4){
-              this.$set(this.setting[i], 'miniprogramTitle', selectedVideo.dictLabel);
-            }
-
+          if (selectedVideo && this.setting[i].contentType == 3  && this.msgForm.videoId != null) {
+            this.$set(this.setting[i], 'linkDescribe', selectedVideo.dictLabel);
           }
         }
       }
 
 
     },
-
-
     /** 查询sopUserLogsInfo列表 */
     getList() {
       this.loading = true;
@@ -892,6 +748,7 @@ export default {
           this.msgForm.userIdParam=this.queryParams.userIdParam;
           this.msgForm.startTime=this.queryParams.startTimeParam;
           this.msgForm.corpId=this.queryParams.corpIdParam;
+          this.msgForm.filterMode=this.queryParams.filterMode;
 
           if (this.setting.length <= 0) {
             return this.$message.error("请添加规则")
@@ -915,25 +772,18 @@ export default {
             if (this.setting[i].contentType == 2 && (this.setting[i].imgUrl == null || this.setting[i].imgUrl == "")) {
               return this.$message.error("图片不能为空")
             }
-            if ((this.setting[i].contentType == 3 || this.setting[i].contentType == 9  ) && (this.setting[i].linkTitle == null || this.setting[i].linkTitle == "")) {
+            if (this.setting[i].contentType == 3 && (this.setting[i].linkTitle == null || this.setting[i].linkTitle == "")) {
               return this.$message.error("链接标题不能为空")
             }
-            if ((this.setting[i].contentType == 3 || this.setting[i].contentType == 9 ) && (this.setting[i].linkDescribe == null || this.setting[i].linkDescribe == "")) {
+            if (this.setting[i].contentType == 3 && (this.setting[i].linkDescribe == null || this.setting[i].linkDescribe == "")) {
               return this.$message.error("链接描述不能为空")
             }
-            if ((this.setting[i].contentType == 3 || this.setting[i].contentType == 9 ) && (this.setting[i].linkImageUrl == null || this.setting[i].linkImageUrl == "")) {
+            if (this.setting[i].contentType == 3 && (this.setting[i].linkImageUrl == null || this.setting[i].linkImageUrl == "")) {
               return this.$message.error("链接图片不能为空")
             }
-            if ((this.setting[i].contentType == 3 || this.setting[i].contentType == 9 )&& this.setting[i].type == 1 && (this.setting[i].linkUrl == null || this.setting[i].linkUrl == "")) {
+            if (this.setting[i].contentType == 3 && this.setting[i].type == 1 && (this.setting[i].linkUrl == null || this.setting[i].linkUrl == "")) {
               return this.$message.error("链接地址不能为空")
             }
-
-            if (this.setting[i].contentType == 4 && (this.setting[i].miniprogramTitle == null || this.setting[i].miniprogramTitle == "")) {
-              return this.$message.error("小程序消息标题不能为空")
-            }
-            if (this.setting[i].contentType == 4 && (this.setting[i].miniprogramPicUrl == null || this.setting[i].miniprogramPicUrl == "")) {
-              return this.$message.error("小程序封面地址不能为空")
-            }
             if (this.setting[i].contentType == 5 && (this.setting[i].fileUrl == null || this.setting[i].fileUrl == "")) {
               return this.$message.error("文件不能为空")
             }
@@ -963,6 +813,8 @@ export default {
               courseId:null,
               courseType:null,
               setting:null,
+              isRegister:2,
+
             }
             this.getList();
           }).finally(()=>{
@@ -986,23 +838,14 @@ export default {
           this.updateLogsInfoFrom.qwUserId=this.queryParams.qwUserId
           this.updateLogsInfoFrom.corpId= this.queryParams.corpId
 
-          let loadingRock = this.$loading({
-            lock: true,
-            text: '正在执行中请稍后~~请不要刷新页面!!',
-            spinner: 'el-icon-loading',
-            background: 'rgba(0, 0, 0, 0.7)'
-          });
-
           batchUpdateSopUserLogsInfoToTime(this.updateLogsInfoFrom).then(response => {
             this.msgSuccess("修改成功");
             this.open = false;
             this.updateOpen=false;
             this.getList();
             this.$emit('flashNotify')
-            loadingRock.close();
-          }).finally(res=>{
-            loadingRock.close();
-          })
+          });
+
         }
       });
     },

+ 8 - 7
src/views/qw/tagGroup/tagGroupList.vue

@@ -1,7 +1,7 @@
 <template>
   <div class="app-container">
     <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="90px">
-      <el-form-item label="标签组名称" prop="name">
+      <el-form-item label="标签组名称111" prop="name">
         <el-input
           v-model="queryParams.name"
           placeholder="请输入标签组名称"
@@ -11,7 +11,7 @@
         />
       </el-form-item>
 
-      <el-form-item label="标签名称" prop="name">
+      <el-form-item label="标签名称111" prop="name">
         <el-input
           v-model="queryParams.tagName"
           placeholder="请输入标签名称"
@@ -211,7 +211,7 @@ export default {
   methods: {
 
     getTagGroupList(row) {
-      this.queryParams.corpId=row;
+      this.queryParams.corpId = row;
       this.getList();
     },
     /** 查询企微客户标签组列表 */
@@ -260,7 +260,7 @@ export default {
       this.getList();
     },
     addRow() {
-      this.form.tag.push({ name: "标签", order: 0 });
+      this.form.tag.push({name: "标签", order: 0});
     },
     deleteRow(index) {
       this.form.tag.splice(index, 1);
@@ -302,7 +302,7 @@ export default {
       this.reset();
       this.open = true;
       this.form.tag = [
-        { name: "标签", order: 0 },
+        {name: "标签", order: 0},
       ];
       this.title = "添加企微客户标签组";
     },
@@ -349,12 +349,13 @@ export default {
         confirmButtonText: "确定",
         cancelButtonText: "取消",
         type: "warning"
-      }).then(function() {
+      }).then(function () {
         return delTagGroup(ids);
       }).then(() => {
         this.getList();
         this.msgSuccess("删除成功");
-      }).catch(() => {});
+      }).catch(() => {
+      });
     },
   }
 };

+ 11 - 11
src/views/qw/user/index.vue

@@ -163,17 +163,17 @@
           >
             绑定主机
           </el-button>
-<!--          <el-button-->
-<!--            v-if="scope.row.loginCodeUrl!=null"-->
-<!--            size="mini"-->
-<!--            type="text"-->
-<!--            icon="el-icon-video-camera-solid"-->
-<!--            plain-->
-<!--            @click="handleCloudAP(scope.row.loginCodeUrl)"-->
-<!--            v-hasPermi="['qw:user:cloudAP']"-->
-<!--          >-->
-<!--            获取主机帐密-->
-<!--          </el-button>-->
+          <el-button
+            v-if="scope.row.loginCodeUrl!=null"
+            size="mini"
+            type="text"
+            icon="el-icon-video-camera-solid"
+            plain
+            @click="handleCloudAP(scope.row.loginCodeUrl)"
+            v-hasPermi="['qw:user:cloudAP']"
+          >
+            获取主机帐密
+          </el-button>
           <el-button
             v-if="scope.row.loginCodeUrl!=null"
             size="mini"

+ 2 - 2
src/views/qw/user/qwUserSelectOne.vue

@@ -19,10 +19,10 @@
 
     <el-table v-loading="loading" :data="userList" ref="userList">
         <el-table-column label="企微员工账号" align="center" prop="qwUserId" />
-		<el-table-column label="员工昵称" align="center" prop="qwUserName" />
+		    <el-table-column label="员工昵称" align="center" prop="qwUserName" />
         <el-table-column label="员工部门" align="center" prop="departmentName" />
         <el-table-column label="员工昵称" align="center" prop="nickName"/>
-      <el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="120px" fixed="right">
+      <el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="120px" >
         <template slot-scope="scope">
           <el-button
             size="mini"

+ 33 - 122
src/views/store/inquiryOrder/list.vue

@@ -13,40 +13,42 @@
           @keyup.enter.native="handleQuery"
         />
       </el-form-item>
-      <el-form-item label="病人名称" prop="patientName">
+     <el-form-item label="病人名称" prop="patientName">
+          <el-input
+            v-model="queryParams.patientName"
+            placeholder="请输入病人名称"
+            clearable
+            size="small"
+            @keyup.enter.native="handleQuery"
+          />
+      </el-form-item>
+      <el-form-item label="员工姓名" prop="companyUserNickName">
         <el-input
-          v-model="queryParams.patientName"
-          placeholder="请输入病人名称"
+        style="width:220px"
+          v-model="queryParams.companyUserNickName"
+          placeholder="请输入员工姓名"
           clearable
           size="small"
           @keyup.enter.native="handleQuery"
         />
       </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.value"
-            :label="item.label"
-            :value="item.value">
-          </el-option>
-        </el-select>
+           <el-form-item label="医生" prop="doctorName">
+                <el-input
+                  v-model="queryParams.doctorName"
+                  placeholder="请输入医生名称"
+                  clearable
+                  size="small"
+                  @keyup.enter.native="handleQuery"
+                />
       </el-form-item>
-      <el-form-item label="医生" prop="doctorId">
-        <el-select v-model="queryParams.doctorId" clearable filterable remote
-                   placeholder="请输入关键词" :remote-method="loadDoctorOptions"
-                   v-select-load-more="loadMoreDoctorOptions"
-                   :loading="doctorOptionsLoading">
-          <el-option
-            v-for="item in doctorOptions"
-            :key="item.value"
-            :label="item.label"
-            :value="item.value">
-          </el-option>
-        </el-select>
+      <el-form-item label="发卷人" prop="sendName">
+           <el-input
+             v-model="queryParams.sendName"
+             placeholder="请输入发卷人"
+             clearable
+             size="small"
+             @keyup.enter.native="handleQuery"
+           />
       </el-form-item>
       <el-form-item label="订单类型" prop="orderType">
          <el-select v-model="queryParams.orderType" placeholder="请选择" clearable size="small">
@@ -91,7 +93,7 @@
       <el-form-item label="支付时间" prop="payTimeRange">
         <el-date-picker style="width:205.4px" clearable size="small" v-model="payTimeRange" type="daterange" value-format="yyyy-MM-dd"  start-placeholder="开始日期"  end-placeholder="结束日期"> </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>
@@ -164,6 +166,7 @@
       <el-table-column label="订单金额" align="center" prop="money" />
       <el-table-column label="支付金额" align="center" prop="payMoney" />
       <el-table-column label="优惠金额" align="center" prop="discountMoney" />
+      <el-table-column label="优惠卷发送人" align="center" prop="sendName" width="120px"/>
       <el-table-column label="支付时间" align="center" prop="payTime" width="180"/>
       <el-table-column label="审核时间" align="center" prop="auditTime" width="180"/>
       <el-table-column label="审核人" align="center" prop="userName" width="180"/>
@@ -226,8 +229,6 @@ import { treeselect } from "@/api/company/companyDept";
 import Treeselect from "@riophae/vue-treeselect";
 import { getTask } from "@/api/common";
 import "@riophae/vue-treeselect/dist/vue-treeselect.css";
-import { getCompanyUserListLikeName } from "@/api/company/companyUser";
-import { getDoctorListLikeName } from "@/api/doctor/doctor";
 export default {
   watch: {
     // 根据名称筛选部门树
@@ -299,8 +300,8 @@ export default {
         inquiryType: null,
         doctorName:null,
         patientName:null,
+        sendName:null,
         phone:null,
-        companyUserId: null
       },
       // 表单参数
       form: {},
@@ -313,24 +314,6 @@ export default {
       inquiryOrderOptions:[],
       inquirySubTypeOptions:[],
       orOptions:[],
-      // 员工选项列表
-      companyUserOptionsParams: {
-        name: undefined,
-        hasNextPage: false,
-        pageNum: 1,
-        pageSize: 10
-      },
-      companyUserOptionsLoading: false,
-      companyUserOptions: [],
-      // 医生选项列表
-      doctorOptionsParams: {
-        name: undefined,
-        hasNextPage: false,
-        pageNum: 1,
-        pageSize: 10
-      },
-      doctorOptionsLoading: false,
-      doctorOptions: []
     };
   },
   created() {
@@ -606,79 +589,7 @@ export default {
           },10000);
         }
         }).catch(() => {});
-    },
-    /**
-     * 根据名称模糊查询用户列表
-     * @param query 参数
-     */
-    loadCompanyUserOptions(query) {
-      this.companyUserOptions = [];
-      if (query === '') {
-        return;
-      }
-
-      this.companyUserOptionsParams.pageNum = 1
-      this.companyUserOptionsParams.name = query
-      this.companyUserOptionsLoading = true;
-      this.getCompanyUserListLikeName()
-    },
-    /**
-     * 获取员工列表
-     */
-    getCompanyUserListLikeName() {
-      getCompanyUserListLikeName(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()
-    },
-    /**
-     * 根据名称模糊查询医生列表选项
-     * @param query 参数
-     */
-    loadDoctorOptions(query) {
-      this.doctorOptions = [];
-      if (query === '') {
-        return;
-      }
-
-      this.doctorOptionsParams.pageNum = 1
-      this.doctorOptionsParams.name = query
-      this.doctorOptionsLoading = true;
-      this.getDoctorListLikeName()
-    },
-    /**
-     * 获取医生列表选项
-     */
-    getDoctorListLikeName() {
-      getDoctorListLikeName(this.doctorOptionsParams).then(response => {
-        this.doctorOptions = [...this.doctorOptions, ...response.data.list]
-        this.doctorOptionsParams.hasNextPage = response.data.hasNextPage
-        this.doctorOptionsLoading = false;
-      });
-    },
-    /**
-     * 加载更多医生选项
-     */
-    loadMoreDoctorOptions() {
-      if (!this.doctorOptionsParams.hasNextPage) {
-        return;
-      }
-
-      this.doctorOptionsParams.pageNum += 1
-      this.getDoctorListLikeName()
-    },
+    }
   }
 };
 </script>

+ 18 - 119
src/views/store/packageOrder/list.vue

@@ -31,31 +31,23 @@
           @keyup.enter.native="handleQuery"
         />
       </el-form-item>
-      <el-form-item label="医生名称" prop="doctorId">
-        <el-select v-model="queryParams.doctorId" clearable filterable remote
-                   placeholder="请输入关键词" :remote-method="loadDoctorOptions"
-                   v-select-load-more="loadMoreDoctorOptions"
-                   :loading="doctorOptionsLoading">
-          <el-option
-            v-for="item in doctorOptions"
-            :key="item.value"
-            :label="item.label"
-            :value="item.value">
-          </el-option>
-        </el-select>
+      <el-form-item label="医生名称" prop="doctorName">
+        <el-input
+          v-model="queryParams.doctorName"
+          placeholder="请输入医生名称"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
       </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.value"
-            :label="item.label"
-            :value="item.value">
-          </el-option>
-        </el-select>
+      <el-form-item label="员工" prop="companyUserName">
+        <el-input
+          v-model="queryParams.companyUserName"
+          placeholder="员工"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
       </el-form-item>
       <el-form-item label="收货人" prop="userName">
         <el-input
@@ -407,9 +399,6 @@ import addUser from "../components/addUser";
 import addUserAddress from "../components/addUserAddress";
 import addPatient from "../components/addPatient";
 import { getTask } from "@/api/common";
-import { getCompanyUserListLikeName } from "@/api/company/companyUser";
-import { getDoctorListLikeName } from "@/api/doctor/doctor";
-import { getPackageListLikeName } from "@/api/store/package"
 export default {
   name: "PackageOrder",
   components: {packageOrderDetails ,Treeselect,addUser,addUserAddress ,addPatient },
@@ -424,24 +413,6 @@ export default {
 	  sourceOptions:[],
       package:[],
       packageTypeOptions:[],
-      // 员工选项列表
-      companyUserOptionsParams: {
-        name: undefined,
-        hasNextPage: false,
-        pageNum: 1,
-        pageSize: 10
-      },
-      companyUserOptionsLoading: false,
-      companyUserOptions: [],
-      // 医生选项列表
-      doctorOptionsParams: {
-        name: undefined,
-        hasNextPage: false,
-        pageNum: 1,
-        pageSize: 10
-      },
-      doctorOptionsLoading: false,
-      doctorOptions: [],
       actName:"10",
       // 遮罩层
       loading: true,
@@ -510,7 +481,7 @@ export default {
         endTime:null,
         endStartTime:null,
         endEndTime:null,
-        companyUserId:null,
+        companyUserName:null,
         companyName:null,
 		source:null,
       },
@@ -877,79 +848,7 @@ export default {
           },10000);
         }
         }).catch(() => {});
-    },
-    /**
-     * 根据名称模糊查询用户列表
-     * @param query 参数
-     */
-    loadCompanyUserOptions(query) {
-      this.companyUserOptions = [];
-      if (query === '') {
-        return;
-      }
-
-      this.companyUserOptionsParams.pageNum = 1
-      this.companyUserOptionsParams.name = query
-      this.companyUserOptionsLoading = true;
-      this.getCompanyUserListLikeName()
-    },
-    /**
-     * 获取员工列表
-     */
-    getCompanyUserListLikeName() {
-      getCompanyUserListLikeName(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()
-    },
-    /**
-     * 根据名称模糊查询医生列表选项
-     * @param query 参数
-     */
-    loadDoctorOptions(query) {
-      this.doctorOptions = [];
-      if (query === '') {
-        return;
-      }
-
-      this.doctorOptionsParams.pageNum = 1
-      this.doctorOptionsParams.name = query
-      this.doctorOptionsLoading = true;
-      this.getDoctorListLikeName()
-    },
-    /**
-     * 获取医生列表选项
-     */
-    getDoctorListLikeName() {
-      getDoctorListLikeName(this.doctorOptionsParams).then(response => {
-        this.doctorOptions = [...this.doctorOptions, ...response.data.list]
-        this.doctorOptionsParams.hasNextPage = response.data.hasNextPage
-        this.doctorOptionsLoading = false;
-      });
-    },
-    /**
-     * 加载更多医生选项
-     */
-    loadMoreDoctorOptions() {
-      if (!this.doctorOptionsParams.hasNextPage) {
-        return;
-      }
-
-      this.doctorOptionsParams.pageNum += 1
-      this.getDoctorListLikeName()
-    },
+    }
   }
 };
 </script>

+ 13 - 78
src/views/store/prescribe/list.vue

@@ -23,18 +23,14 @@
           @keyup.enter.native="handleQuery"
         />
       </el-form-item>
-      <el-form-item label="医生姓名" prop="doctorId">
-        <el-select v-model="queryParams.doctorId" clearable filterable remote
-                   placeholder="请输入关键词" :remote-method="loadDoctorOptions"
-                   v-select-load-more="loadMoreDoctorOptions"
-                   :loading="doctorOptionsLoading">
-          <el-option
-            v-for="item in doctorOptions"
-            :key="item.value"
-            :label="item.label"
-            :value="item.value">
-          </el-option>
-        </el-select>
+      <el-form-item label="医生姓名" prop="doctorName">
+        <el-input
+          v-model="queryParams.doctorName"
+          placeholder="请输入医生姓名"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
       </el-form-item>
       <el-form-item label="药品订单编号" prop="orderCode">
         <el-input
@@ -181,8 +177,6 @@
 <script>
 import { listPrescribe, getPrescribe, delPrescribe, addPrescribe, updatePrescribe, exportPrescribe,messageFeedbackExport } from "@/api/store/prescribe";
 import prescribeDetails from '../components/prescribeDetails.vue';
-import { getDoctorListLikeName } from "@/api/doctor/doctor";
-import { getTask } from "@/api/common";
 export default {
   name: "Prescribe",
   components: { prescribeDetails },
@@ -251,7 +245,7 @@ export default {
         auditSTime:null,
         auditETime:null,
         doctorName:null,
-        orderStatus:null,
+        orderStatus:null
       },
        actName:"10",
       // 表单参数
@@ -263,15 +257,6 @@ export default {
       prescribeType:[],
       orOptions:[],
       sexOptions:[],
-      // 医生选项列表
-      doctorOptionsParams: {
-        name: undefined,
-        hasNextPage: false,
-        pageNum: 1,
-        pageSize: 10
-      },
-      doctorOptionsLoading: false,
-      doctorOptions: [],
     };
   },
   created() {
@@ -371,7 +356,7 @@ export default {
         doctorId: null,
         createTime: null,
         status: 0,
-        auditTime: null,
+        auditTime: null
       };
       this.resetForm("form");
     },
@@ -449,7 +434,6 @@ export default {
     },
     /** 导出按钮操作 */
     handleExport() {
-      const that = this;
       const queryParams = this.queryParams;
       this.$confirm('是否确认导出所有处方数据项?', "警告", {
           confirmButtonText: "确定",
@@ -459,21 +443,8 @@ export default {
           this.exportLoading = true;
           return exportPrescribe(queryParams);
         }).then(response => {
-          if(response.code === 200){
-            that.msgSuccess(response.msg);
-            that.taskId = response.data;
-            that.time = setInterval(function(){
-              //查订单
-              getTask(that.taskId).then(res => {
-                if(res.data.status === 1) {
-                  that.exportLoading = false;
-                  clearTimeout(that.time)
-                  that.time = null;
-                  that.download(res.data.fileUrl);
-                }
-              });
-            },10000);
-          }
+          this.download(response.msg);
+          this.exportLoading = false;
         }).catch(() => {});
     },
      /** 导出按钮操作 */
@@ -490,43 +461,7 @@ export default {
           this.download(response.msg);
           this.exportLoading = false;
         }).catch(() => {});
-    },
-    /**
-     * 根据名称模糊查询医生列表选项
-     * @param query 参数
-     */
-    loadDoctorOptions(query) {
-      this.doctorOptions = [];
-      if (query === '') {
-        return;
-      }
-
-      this.doctorOptionsParams.pageNum = 1
-      this.doctorOptionsParams.name = query
-      this.doctorOptionsLoading = true;
-      this.getDoctorListLikeName()
-    },
-    /**
-     * 获取医生列表选项
-     */
-    getDoctorListLikeName() {
-      getDoctorListLikeName(this.doctorOptionsParams).then(response => {
-        this.doctorOptions = [...this.doctorOptions, ...response.data.list]
-        this.doctorOptionsParams.hasNextPage = response.data.hasNextPage
-        this.doctorOptionsLoading = false;
-      });
-    },
-    /**
-     * 加载更多医生选项
-     */
-    loadMoreDoctorOptions() {
-      if (!this.doctorOptionsParams.hasNextPage) {
-        return;
-      }
-
-      this.doctorOptionsParams.pageNum += 1
-      this.getDoctorListLikeName()
-    },
+    }
   }
 };
 </script>

+ 29 - 128
src/views/store/storeOrder/list.vue

@@ -32,18 +32,15 @@
           @keyup.enter.native="handleQuery"
         />
       </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.value"
-            :label="item.label"
-            :value="item.value">
-          </el-option>
-        </el-select>
+      <el-form-item label="员工姓名" prop="companyUserNickName">
+        <el-input
+        style="width:220px"
+          v-model="queryParams.companyUserNickName"
+          placeholder="请输入员工姓名"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
       </el-form-item>
       <el-form-item label="物流状态" prop="deliveryStatus">
         <el-select  style="width:220px" v-model="queryParams.deliveryStatus" placeholder="请选择物流状态" clearable size="small" >
@@ -55,7 +52,7 @@
               />
         </el-select>
       </el-form-item>
-
+		
       <el-form-item label="结算状态" prop="deliveryPayStatus">
         <el-select style="width:220px" v-model="queryParams.deliveryPayStatus" placeholder="请选择物流结算状态" clearable size="small" >
         <el-option
@@ -117,8 +114,8 @@
       <el-form-item label="渠道" prop="channel">
          <el-select multiple filterable style="width: 200px" v-model="channelArr" placeholder="请选择渠道" clearable size="small" >
           <el-option
-            v-for="(item,index) in channelOptions"
-            :key="'channel' + index +item.dictValue"
+            v-for="item in channelOptions"
+            :key="'channel'+item.dictValue"
             :label="item.dictLabel"
             :value="item.dictValue"
           />
@@ -143,7 +140,7 @@
           @keyup.enter.native="handleQuery"
         />
       </el-form-item>
-
+	
       <el-form-item label="加密电话" prop="userPhoneMk">
         <el-input
           v-model="queryParams.userPhoneMk"
@@ -153,18 +150,14 @@
           @keyup.enter.native="handleQuery"
         />
       </el-form-item>
-      <el-form-item label="医生姓名" prop="doctorId">
-        <el-select v-model="queryParams.doctorId" clearable filterable remote
-                   placeholder="请输入关键词" :remote-method="loadDoctorOptions"
-                   v-select-load-more="loadMoreDoctorOptions"
-                   :loading="doctorOptionsLoading">
-          <el-option
-            v-for="item in doctorOptions"
-            :key="item.value"
-            :label="item.label"
-            :value="item.value">
-          </el-option>
-        </el-select>
+      <el-form-item label="医生姓名" prop="doctorName">
+        <el-input
+          v-model="queryParams.doctorName"
+          placeholder="请输入医生姓名"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
       </el-form-item>
       <el-form-item label="患者姓名" prop="patientName">
         <el-input
@@ -228,8 +221,8 @@
 	<el-form-item label="入账时间" prop="tuiMoneyTime">
 	      <el-date-picker v-model="tuiMoneyTime" size="small" style="width: 220px" value-format="yyyy-MM-dd" type="daterange" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" @change="changeTime"></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>
@@ -325,13 +318,12 @@
 import { listOrder, getOrder, delOrder, addOrder, updateOrder, exportOrder,importTemplate } from "@/api/store/storeOrder";
 import storeOrderDetails from '../components/storeOrderDetails.vue';
 import { getTcmScheduleList } from "@/api/company/tcmScheduleReport";
+import { getToken } from "@/utils/auth";
 import {listStore} from "@/api/store/storeProduct";
 import { treeselect } from "@/api/company/companyDept";
 import Treeselect from "@riophae/vue-treeselect";
 import { getTask } from "@/api/common";
 import "@riophae/vue-treeselect/dist/vue-treeselect.css";
-import { getCompanyUserListLikeName } from "@/api/company/companyUser";
-import { getDoctorListLikeName } from "@/api/doctor/doctor";
 export default {
   name: "Order",
   components: { storeOrderDetails ,Treeselect},
@@ -344,24 +336,6 @@ export default {
       qwSubjectArr:[],
       // 部门树选项
       deptOptions: [],
-      // 员工选项列表
-      companyUserOptionsParams: {
-        name: undefined,
-        hasNextPage: false,
-        pageNum: 1,
-        pageSize: 10
-      },
-      companyUserOptionsLoading: false,
-      companyUserOptions: [],
-      // 医生选项列表
-      doctorOptionsParams: {
-        name: undefined,
-        hasNextPage: false,
-        pageNum: 1,
-        pageSize: 10
-      },
-      doctorOptionsLoading: false,
-      doctorOptions: [],
       deptName:undefined,
       actName:"10",
       show:{
@@ -432,7 +406,7 @@ export default {
         prescribeId: null,
         finishTime: null,
         patientName: null,
-        doctorId: null,
+        doctorName: null,
         sTime:null,
         eTime:null,
         paysTime:null,
@@ -444,11 +418,11 @@ export default {
         tuieTime:null,
         tuiUserId: null,
         orderCreateType: null,
-        companyUserId:null,
+        companyUserName:null,
         companyName:null,
+        packageSecondName:null,
         isFirst:null,
       		source:null,
-        packageSecondName:null
       },
       // 表单参数
       form: {},
@@ -677,8 +651,7 @@ export default {
         tuiMoney: null,
         tuiMoneyStatus: 0,
         tuiUserId: null,
-        orderCreateType: null,
-        packageSecondName: null
+        orderCreateType: null
       };
       this.resetForm("form");
     },
@@ -870,79 +843,7 @@ export default {
           },10000);
         }
         }).catch(() => {});
-    },
-    /**
-   * 根据名称模糊查询用户列表
-   * @param query 参数
-   */
-    loadCompanyUserOptions(query) {
-      this.companyUserOptions = [];
-      if (query === '') {
-        return;
-      }
-
-      this.companyUserOptionsParams.pageNum = 1
-      this.companyUserOptionsParams.name = query
-      this.companyUserOptionsLoading = true;
-      this.getCompanyUserListLikeName()
-    },
-    /**
-     * 获取员工列表
-     */
-    getCompanyUserListLikeName() {
-      getCompanyUserListLikeName(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()
-    },
-    /**
-     * 根据名称模糊查询医生列表选项
-     * @param query 参数
-     */
-    loadDoctorOptions(query) {
-      this.doctorOptions = [];
-      if (query === '') {
-        return;
-      }
-
-      this.doctorOptionsParams.pageNum = 1
-      this.doctorOptionsParams.name = query
-      this.doctorOptionsLoading = true;
-      this.getDoctorListLikeName()
-    },
-    /**
-     * 获取医生列表选项
-     */
-    getDoctorListLikeName() {
-      getDoctorListLikeName(this.doctorOptionsParams).then(response => {
-        this.doctorOptions = [...this.doctorOptions, ...response.data.list]
-        this.doctorOptionsParams.hasNextPage = response.data.hasNextPage
-        this.doctorOptionsLoading = false;
-      });
-    },
-    /**
-     * 加载更多医生选项
-     */
-    loadMoreDoctorOptions() {
-      if (!this.doctorOptionsParams.hasNextPage) {
-        return;
-      }
-
-      this.doctorOptionsParams.pageNum += 1
-      this.getDoctorListLikeName()
-    },
+    }
   }
 };
 </script>

+ 2 - 4
src/views/watch/deviceInfo/details.vue

@@ -64,7 +64,7 @@
           </div>
         </div>
         <div class="equipment-day">
-          <!-- 已绑定 <span>400</span> 天, 佩戴 <span>4365</span> 天 -->
+          已绑定 <span>400</span> 天, 佩戴 <span>4365</span> 天
         </div>
         <div class="equipment-btn">
           <el-button type="primary" size="small">一键上传</el-button>
@@ -342,9 +342,7 @@ export default {
      */
     async getUserinfo(deviceId) {
       try {
-        const userId = this.$route.params.userId;
-        const selectType = this.$route.params.selectType;
-        const response = await getUser({deviceId:deviceId,userId:userId,selectType});
+        const response = await getUser(deviceId);
         if (response && response.data) {
           this.userInfo = response.data; // 确保数据被正确赋值
           // console.log("用户信息:", this.userInfo);

+ 9 - 122
src/views/watch/deviceInfo/index.vue

@@ -5,17 +5,10 @@
         <el-input v-model="queryParams.doctorName" placeholder="请输入所属医生" clearable size="small"
           @keyup.enter.native="handleQuery" />
       </el-form-item>
-      <el-form-item label="所属员工" prop="companyUserId">
-        <el-select v-model="queryParams.companyUserId" placeholder="请选择所属员工" clearable size="small">
-          <el-option v-for="item in companyUserList" :key="item.userId" :label="item.nickName"
-            :value="item.userId">
-          </el-option>
-        </el-select>
-      </el-form-item>
-      <!-- <el-form-item label="绑定用户" prop="watchUserName">
+      <el-form-item label="绑定用户" prop="watchUserName">
         <el-input v-model="queryParams.watchUserName" placeholder="请输入绑定用户" clearable size="small"
           @keyup.enter.native="handleQuery" />
-      </el-form-item> -->
+      </el-form-item>
       <el-form-item label="设备编号" prop="deviceNumber">
         <el-input v-model="queryParams.deviceNumber" placeholder="请输入设备编号" clearable size="small"
           @keyup.enter.native="handleQuery" />
@@ -89,18 +82,8 @@
     <el-table v-loading="loading" :data="deviceInfoList" @selection-change="handleSelectionChange">
       <el-table-column type="selection" width="55" align="center" />
       <el-table-column label="设备id" align="center" prop="deviceId" />
-      <el-table-column label="所属员工" align="center" prop="companyUserName" />
       <el-table-column label="所属医生" align="center" prop="doctorName" />
-      <el-table-column  label="绑定用户"  align="center">
-          <template slot-scope="scope">
-              <el-link :underline="false" prop="item.userId" v-for="(item, index) in scope.row.users"  v-if="scope.row.users"  @click="handleDetails(scope.row.deviceId,item.userId,0)">{{item.nickName}}</el-link>
-          </template>
-      </el-table-column>
-      <el-table-column  label="绑定家人用户"  align="center">
-          <template slot-scope="scope">
-              <el-link :underline="false" prop="item.userId" v-for="(item, index) in scope.row.familyUsers"  v-if="scope.row.familyUsers"  @click="handleDetails(scope.row.deviceId,item.userId,1)">{{item.nickName}}</el-link>
-          </template>
-      </el-table-column>
+      <el-table-column label="绑定用户" align="center" prop="watchUserName" />
       <el-table-column label="设备编号" align="center" prop="deviceNumber" width="150"/>
       <el-table-column label="电量" align="center" prop="battery" />
       <el-table-column label="信号" align="center" prop="rssi" />
@@ -120,65 +103,14 @@
       </el-table-column>
       <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
         <template slot-scope="scope">
-          <el-button size="mini" type="text" icon="el-icon-view" @click="handleDetails(scope.row.deviceId,null,0)"
+          <el-button size="mini" type="text" icon="el-icon-view" @click="handleDetails(scope.row.deviceId)"
             v-hasPermi="['watchApi:deviceInfo:query']">查询详情</el-button>
           <el-button size="mini" type="text" icon="el-icon-phone-outline" @click="handleSoSPeople(scope.row.deviceNumber)"
             v-hasPermi="['watchApi:deviceInfo:query']">查看紧急联系人</el-button>
-          <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
-            v-hasPermi="['watchApi:deviceInfo:edit']">修改</el-button>  
         </template>
       </el-table-column>
     </el-table>
 
-    <!-- 添加或修改设备信息对话框 -->
-    <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
-      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
-        
-        <el-form-item label="所属员工" prop="companyUserId">
-          <template #label>
-            <span class="required-label">所属员工</span>
-          </template>
-          <el-select v-model="form.companyUserId" placeholder="请选择所属员工" clearable size="small">
-            <el-option v-for="item in companyUserList" :key="item.userId" :label="item.nickName"
-              :value="item.userId">
-            </el-option>
-          </el-select>
-        </el-form-item>
-        <el-form-item label="所属医生" prop="doctorId">
-          <template #label>
-            <span class="required-label">所属医生</span>
-          </template>
-          <el-select v-model="form.doctorId" placeholder="请选择所属医生" clearable size="small">
-            <el-option v-for="item in doctorList" :key="item.doctorId" :label="item.doctorName"
-              :value="item.doctorId">
-            </el-option>
-          </el-select>
-        </el-form-item>
-        <el-form-item label="设备编号" prop="deviceNumber">
-          <el-input v-model="form.deviceNumber" placeholder="请输入设备编号" disabled/>
-        </el-form-item>
-        <el-form-item label="电量" prop="battery">
-          <el-input v-model="form.battery" placeholder="请输入电量" disabled/>
-        </el-form-item>
-        <el-form-item label="信号" prop="rssi">
-          <el-input v-model="form.rssi" placeholder="请输入信号" disabled/>
-        </el-form-item>
-        <el-form-item label="设备状态">
-          <el-radio-group v-model="form.status">
-            <el-radio :label="0">OFFLINE</el-radio>
-            <el-radio :label="1">ONLINE</el-radio>
-            <el-radio :label="2">UNACTIVE</el-radio>
-            <el-radio :label="3">DISABLE</el-radio>
-            <el-radio :label="4">NOT EXIST</el-radio>
-          </el-radio-group>
-        </el-form-item>
-      </el-form>
-      <div slot="footer" class="dialog-footer">
-        <el-button type="primary" @click="submitForm">确 定</el-button>
-        <el-button @click="cancel">取 消</el-button>
-      </div>
-    </el-dialog>
-
     <!-- 弹窗展示紧急联系人列表 -->
     <el-dialog :visible.sync="sosVisible" title="紧急联系人" width="50%">
         <el-table v-loading="sosLoading" :data="sosPeopleList">
@@ -237,14 +169,14 @@
 
 <script>
 import { listDeviceInfo, getDeviceInfo, delDeviceInfo, addDeviceInfo, updateDeviceInfo, exportDeviceInfo, queryAlarm, setStatus, queryPageAlarm,queryLastHealthData,querySos} from "@/api/watch/deviceInfo";
-import { getSelectUserList } from "@/api/company/companyUser";
+import { getAllUserlist } from "@/api/company/companyUser";
 import { messageSend } from "@/api/watch/deviceInfoSet.js";
-import { listDoctor } from "@/api/doctor/doctor";
 import setUpUserInfoDialog from "@/components/DeviceInfo/SettingDialog/setUpUserInfoDialog.vue";
 import SetInfoDialog from "@/components/DeviceInfo/SettingDialog/SetInfoDialog.vue";
 import Phonebook from "@/components/DeviceInfo/SettingDialog/Phonebook.vue";
 import Clockalarm from "@/components/DeviceInfo/SettingDialog/Clockalarm.vue";
 import Sedentary from "@/components/DeviceInfo/SettingDialog/Sedentary.vue";
+// import {getInfo} from "@/api/login"
 
 export default {
   name: "DeviceInfo",
@@ -379,8 +311,6 @@ export default {
   },
   created() {
     this.getList();
-    this.getCompanyUserList();
-    this.getDoctorList();
   },
   computed: {
     // 计算属性来控制按钮的disabled状态
@@ -389,51 +319,8 @@ export default {
     }
   },
   methods: {
-    getDoctorList(){
-      listDoctor({ doctorType:1,isAudit:1 }).then(response => {
-        this.doctorList = response.rows;
-      });
-    },
-    getCompanyUserList(){
-      getSelectUserList().then(response => {
-          this.companyUserList = response.rows;
-        }).catch(error => {
-          console.error("获取员工列表失败:", error);
-        });
-    },
-    /** 修改按钮操作 */
-    handleUpdate(row) {
-      this.reset();
-      const deviceId = row.deviceId || this.ids
-      getDeviceInfo(deviceId).then(response => {
-        this.form = response.data;
-        this.open = true;
-        this.title = "修改设备信息";
-      });
-    },
-    /** 提交按钮 */
-    submitForm() {
-      this.$refs["form"].validate(valid => {
-        if (valid) {
-          if (this.form.deviceId != null) {
-            console.log("===============================" + JSON.stringify(this.form, null, 2))
-            updateDeviceInfo(this.form).then(response => {
-              this.msgSuccess("修改成功");
-              this.open = false;
-              this.getList();
-            });
-          } else {
-            addDeviceInfo(this.form).then(response => {
-              this.msgSuccess("新增成功");
-              this.open = false;
-              this.getList();
-            });
-          }
-        }
-      });
-    },
     rowClassName({row}) {
-      if (row.status && (row.status.includes('偏') || row.status.includes('重'))) {
+      if (row.status && row.status.includes('偏')) {
         // console.log("=============================" + JSON.stringify(row.status, null, 2))
         return 'text-red';
         // return true
@@ -517,8 +404,8 @@ export default {
       }
     },
     /** 处理查询详情按钮点击事件 */
-    handleDetails(deviceId,userId,type) {
-      this.$router.push({ name: 'details', params: { deviceId:deviceId,userId:userId,selectType:type } });
+    handleDetails(deviceId) {
+      this.$router.push({ name: 'details', params: { deviceId } });
     },
 
     /** 查询设备信息列表 */

Nem az összes módosított fájl került megjelenítésre, mert túl sok fájl változott