Browse Source

Merge remote-tracking branch 'origin/master' into 转接增加清空标签配置

ct 2 days ago
parent
commit
29d7fcf4ca
51 changed files with 3640 additions and 546 deletions
  1. 3 0
      .env.development
  2. 1 1
      .env.prod-ddgy
  3. 0 28
      .env.prod-fcky
  4. 4 1
      .env.prod-sft
  5. 22 0
      dev.prod-czt
  6. 1 0
      package.json
  7. 9 0
      src/api/company/companyUser.js
  8. 7 0
      src/api/course/qw/courseWatchLog.js
  9. 19 0
      src/api/hisStore/answer.js
  10. 70 0
      src/api/hisStore/collection.js
  11. 33 2
      src/api/hisStore/storeAfterSales.js
  12. 7 1
      src/api/hisStore/storeOrder.js
  13. 8 0
      src/api/qw/QwWorkTask.js
  14. 18 0
      src/api/qw/externalContact.js
  15. 9 0
      src/api/qw/qwUser.js
  16. 3 1
      src/api/qw/sop.js
  17. 7 0
      src/api/store/package.js
  18. 7 1
      src/api/store/storeOrder.js
  19. BIN
      src/assets/logo/czt.png
  20. BIN
      src/assets/logo/img.png
  21. 139 44
      src/views/company/companyConfig/index.vue
  22. 221 131
      src/views/company/companyUser/index.vue
  23. 125 56
      src/views/company/components/selectQwUser.vue
  24. 184 0
      src/views/company/components/selectQwUserOlder.vue
  25. 305 4
      src/views/course/courseFinishTemp/index.vue
  26. 295 4
      src/views/course/courseFinishTempParent/index.vue
  27. 194 27
      src/views/course/courseWatchLog/deptWatchLog.vue
  28. 265 34
      src/views/course/courseWatchLog/index.vue
  29. 3 3
      src/views/course/courseWatchLog/myCourseWatchLog.vue
  30. 23 3
      src/views/course/courseWatchLog/qw/statistics.vue
  31. 232 42
      src/views/course/courseWatchLog/watchLog.vue
  32. 94 27
      src/views/hisStore/components/productAfterSalesOrder.vue
  33. 156 28
      src/views/hisStore/components/productOrder.vue
  34. 192 0
      src/views/qw/externalContact/collection.vue
  35. 251 5
      src/views/qw/externalContact/index.vue
  36. 280 3
      src/views/qw/externalContact/myExternalContact.vue
  37. 13 1
      src/views/qw/friendWelcome/deptFriendWelcome.vue
  38. 12 0
      src/views/qw/friendWelcome/indexNew.vue
  39. 13 2
      src/views/qw/friendWelcome/myWelcome.vue
  40. 8 8
      src/views/qw/sop/addSop.vue
  41. 43 9
      src/views/qw/sop/sop.vue
  42. 32 1
      src/views/qw/sopLogs/sopLogsList.vue
  43. 44 1
      src/views/qw/sopTemp/updateSopTemp.vue
  44. 72 1
      src/views/qw/sopUserLogsInfo/sendMsgOpenTool.vue
  45. 72 1
      src/views/qw/sopUserLogsInfo/sendMsgSopOpenTool.vue
  46. 2 1
      src/views/qw/user/qwUserList.vue
  47. 31 20
      src/views/store/components/productOrder.vue
  48. 7 2
      src/views/store/components/storeAfterSalesDetails.vue
  49. 76 43
      src/views/store/components/storeOrderDetails.vue
  50. 12 5
      src/views/store/user/list.vue
  51. 16 5
      src/views/store/user/myList.vue

+ 3 - 0
.env.development

@@ -25,3 +25,6 @@ VUE_CLI_BABEL_TRANSPILE_MODULES = true
 VUE_APP_PATIENT_INFO = '客户信息'
 # 添加病人
 VUE_APP_ADD_PATIENT = '添加信息'
+
+#1、正常搜索下拉框 2、查询出200条数据,然后搜索这200条以内的
+VUE_APP_COURSE_COMPANY_NAME = 2

+ 1 - 1
.env.prod-ddgy

@@ -16,7 +16,7 @@ ENV = 'production'
 VUE_APP_BASE_API = '/prod-api'
 
 #默认 1、会员 2、企微
-VUE_APP_COURSE_DEFAULT = 2
+VUE_APP_COURSE_DEFAULT = 1
 
 # 路由懒加载
 VUE_CLI_BABEL_TRANSPILE_MODULES = true

+ 0 - 28
.env.prod-fcky

@@ -1,28 +0,0 @@
-# 页面标题
-VUE_APP_TITLE =客户管理系统
-# 公司名称
-VUE_APP_COMPANY_NAME =蜂巢快药(北京)医药连锁有限公司
-# ICP备案号
-VUE_APP_ICP_RECORD =京ICP备2025120013号
-# ICP网站访问地址
-VUE_APP_ICP_URL =https://beian.miit.gov.cn
-# 网站LOG
-VUE_APP_LOG_URL =@/assets/logo/fcky.png
-
-# 生产环境配置
-ENV = 'production'
-
-# FS管理系统/开发环境
-VUE_APP_BASE_API = '/prod-api'
-
-
-#默认 1、会员 2、企微
-VUE_APP_COURSE_DEFAULT = 1
-
-# 路由懒加载
-VUE_CLI_BABEL_TRANSPILE_MODULES = true
-
-# 患者信息
-VUE_APP_PATIENT_INFO = '客户信息'
-# 添加病人
-VUE_APP_ADD_PATIENT = '添加信息'

+ 4 - 1
.env.prod-sft

@@ -16,7 +16,10 @@ ENV = 'production'
 VUE_APP_BASE_API = '/prod-api'
 
 #默认 1、会员 2、企微
-VUE_APP_COURSE_DEFAULT = 2
+VUE_APP_COURSE_DEFAULT = 1
 
 # 路由懒加载
 VUE_CLI_BABEL_TRANSPILE_MODULES = true
+
+#1、正常搜索下拉框 2、查询出200条数据,然后搜索这200条以内的
+VUE_APP_COURSE_COMPANY_NAME = 2

+ 22 - 0
dev.prod-czt

@@ -0,0 +1,22 @@
+# 页面标题
+VUE_APP_TITLE =内蒙古纯正堂SCRM销售端
+# 公司名称
+VUE_APP_COMPANY_NAME =内蒙古纯正堂大药房有限公司
+# ICP备案号
+VUE_APP_ICP_RECORD =京ICP备2024053040号-5
+# ICP网站访问地址
+VUE_APP_ICP_URL =https://beian.miit.gov.cn
+# 网站LOG
+VUE_APP_LOG_URL =@/assets/logo/czt.png
+
+# 生产环境配置
+ENV = 'production'
+
+# FS管理系统/开发环境
+VUE_APP_BASE_API = '/prod-api'
+
+#默认 1、会员 2、企微
+VUE_APP_COURSE_DEFAULT = 2
+
+# 路由懒加载
+VUE_CLI_BABEL_TRANSPILE_MODULES = true

+ 1 - 0
package.json

@@ -45,6 +45,7 @@
     "build:prod-hst": "vue-cli-service build --mode prod-hst",
     "build:prod-hat": "vue-cli-service build --mode prod-hat",
     "build:prod-ddgy": "vue-cli-service build --mode prod-ddgy",
+    "build:prod-czt": "vue-cli-service build --mode prod-czt",
     "preview": "node build/index.js --preview",
     "lint": "eslint --ext .js,.vue src",
     "test:unit": "jest --clearCache && vue-cli-service test:unit",

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

@@ -298,3 +298,12 @@ export function unBindDoctorId(userId) {
     method: 'get'
   })
 }
+
+//批量修改用户的角色
+export function updateBatchUserRoles(data) {
+  return request({
+    url: '/company/user/updateBatchUserRoles',
+    method: 'post',
+    data: data
+  })
+}

+ 7 - 0
src/api/course/qw/courseWatchLog.js

@@ -23,6 +23,13 @@ export function statisticsList(query) {
     params: query
   })
 }
+export function statisticsExport(query) {
+  return request({
+    url: '/qw/course/courseWatchLog/statisticsExport',
+    method: 'get',
+    params: query
+  })
+}
 export function qwWatchLogStatisticsList(query) {
   return request({
     url: '/qw/course/courseWatchLog/qwWatchLogStatisticsList',

+ 19 - 0
src/api/hisStore/answer.js

@@ -0,0 +1,19 @@
+import request from '@/utils/request'
+
+
+
+// 查询问答详细
+export function getAnswer(id) {
+  return request({
+    url: '/store/answer/' + id,
+    method: 'get'
+  })
+}
+
+// 问答列表选项
+export function questionOptions() {
+  return request({
+    url: '/store/answer/allList',
+    method: 'get',
+  })
+}

+ 70 - 0
src/api/hisStore/collection.js

@@ -0,0 +1,70 @@
+import request from '@/utils/request'
+
+// 查询用户信息采集列表
+export function listCollection(query) {
+  return request({
+    url: '/hisStore/collection/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 查询用户信息采集详细
+export function getCollection(id) {
+  return request({
+    url: '/hisStore/collection/' + id,
+    method: 'get'
+  })
+}
+
+// 查询用户信息采集详细
+export function getInfo(query) {
+  return request({
+    url: '/hisStore/collection/getInfo',
+    method: 'get',
+    params: query
+  })
+}
+
+// 新增用户信息采集
+export function addCollection(data) {
+  return request({
+    url: '/hisStore/collection',
+    method: 'post',
+    data: data
+  })
+}
+
+// 修改用户信息采集
+export function updateCollection(data) {
+  return request({
+    url: '/hisStore/collection',
+    method: 'put',
+    data: data
+  })
+}
+
+// 删除用户信息采集
+export function delCollection(id) {
+  return request({
+    url: '/hisStore/collection/' + id,
+    method: 'delete'
+  })
+}
+
+// 导出用户信息采集
+export function exportCollection(query) {
+  return request({
+    url: '/hisStore/collection/export',
+    method: 'get',
+    params: query
+  })
+}
+
+
+export function getWxaCodeCollectionUnLimit(collectionId) {
+  return request({
+    url: '/hisStore/collection/getWxaCodeCollectionUnLimit/'+collectionId,
+    method: 'get',
+  })
+}

+ 33 - 2
src/api/hisStore/storeAfterSales.js

@@ -62,6 +62,30 @@ export function exportStoreAfterSales(query) {
 
 
 
+// export function cancel(data) {
+//   return request({
+//     url: '/store/store/storeAfterSales/cancel',
+//     method: 'post',
+//     data: data
+//   })
+// }
+
+// export function refund(data) {
+//   return request({
+//     url: '/store/store/storeAfterSales/refund',
+//     method: 'post',
+//     data: data
+//   })
+// }
+
+export function audit(data) {
+  return request({
+    url: '/store/store/storeAfterSales/audit',
+    method: 'post',
+    data: data
+  })
+}
+
 export function cancel(data) {
   return request({
     url: '/store/store/storeAfterSales/cancel',
@@ -78,9 +102,16 @@ export function refund(data) {
   })
 }
 
-export function audit(data) {
+export function audit1(data) {
   return request({
-    url: '/store/store/storeAfterSales/audit',
+    url: '/store/store/storeAfterSales/audit1',
+    method: 'post',
+    data: data
+  })
+}
+export function audit2(data) {
+  return request({
+    url: '/store/store/storeAfterSales/audit2',
     method: 'post',
     data: data
   })

+ 7 - 1
src/api/hisStore/storeOrder.js

@@ -85,7 +85,13 @@ export function updateStoreOrder(data) {
     data: data
   })
 }
-
+export function updateAddressErpFsStoreOrder(data) {
+  return request({
+    url: '/store/store/storeOrder/updateAddressErpFsStoreOrder',
+    method: 'put',
+    data: data
+  })
+}
 // 删除订单
 export function delStoreOrder(id) {
   return request({

+ 8 - 0
src/api/qw/QwWorkTask.js

@@ -59,3 +59,11 @@ export function allListQwWorkTask(query) {
     params: query
   })
 }
+
+export function glList(query) {
+  return request({
+    url: '/qw/QwWorkTaskNew/glList',
+    method: 'get',
+    params: query
+  })
+}

+ 18 - 0
src/api/qw/externalContact.js

@@ -9,6 +9,15 @@ export function listExternalContact(query) {
   })
 }
 
+// 查询重粉用户看课记录
+export function getWatchLogList(query) {
+  return request({
+    url: '/qw/externalContact/getWatchLogList',
+    method: 'get',
+    params: query
+  })
+}
+
 // 查询企业微信客户列表
 export function getRepeat(query) {
   return request({
@@ -158,6 +167,15 @@ export function updateExternalContactCall(data) {
     data: data
   })
 }
+
+//修改用户的状态
+export function updateExternalContactStatus(query) {
+  return request({
+    url: '/qw/externalContact/status',
+    method: 'get',
+    params: query
+  })
+}
 // 修改企业微信客户
 export function editStatus(data) {
   return request({

+ 9 - 0
src/api/qw/qwUser.js

@@ -7,3 +7,12 @@ export function getQwUserAll() {
     method: 'get'
   })
 }
+
+// 根据条件查询企微用户列表
+export function getQwList(params) {
+  return request({
+    url: '/qw/user/qwList',
+    method: 'get',
+    params: params
+  })
+}

+ 3 - 1
src/api/qw/sop.js

@@ -49,9 +49,11 @@ export function courseList() {
     method: 'get',
   })
 }
-export function videoList(id) {
+export function videoList(id,query) {
+
   return request({
     url: '/qw/sop/videoList/' + id,
+    params: query,
     method: 'get'
   })
 }

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

@@ -63,3 +63,10 @@ export function exportPackage(query) {
     params: query
   })
 }
+
+export function allPrivatePackage() {
+  return request({
+    url: '/store/package/privatePackageList',
+    method: 'get'
+  })
+}

+ 7 - 1
src/api/store/storeOrder.js

@@ -138,7 +138,13 @@ export function updateStoreOrder(data) {
     data: data
   })
 }
-
+export function updateAddressErpFsStoreOrder(data) {
+  return request({
+    url: '/store/storeOrder/updateAddressErpFsStoreOrder',
+    method: 'put',
+    data: data
+  })
+}
 export function bindCustomer(data) {
   return request({
     url: '/store/storeOrder/bindCustomer',

BIN
src/assets/logo/czt.png


BIN
src/assets/logo/img.png


+ 139 - 44
src/views/company/companyConfig/index.vue

@@ -82,56 +82,103 @@
               <el-button type="primary" @click="onSubmit2">提交</el-button>
             </div>
         </el-tab-pane>
-        <el-tab-pane label="企微配置" name="qwConfig">
-          <el-form ref="qwConfig" :model="qwConfig" label-width="200px">
-            <el-form-item label="企业CoripID">
-              <el-input v-model="qwConfig.corpId" style="width:400px"   ></el-input>
+<!--        <el-tab-pane label="企微配置" name="qwConfig">-->
+<!--          <el-form ref="qwConfig" :model="qwConfig" label-width="200px">-->
+<!--            <el-form-item label="企业CoripID">-->
+<!--              <el-input v-model="qwConfig.corpId" style="width:400px"   ></el-input>-->
+<!--            </el-form-item>-->
+<!--            <el-form-item label="通讯录Secret">-->
+<!--              <el-input v-model="qwConfig.bookSecret" style="width:400px"   ></el-input>-->
+<!--            </el-form-item>-->
+
+<!--            <el-form-item label="应用Secret">-->
+<!--              <el-input v-model="qwConfig.appSecret" style="width:400px"   ></el-input>-->
+<!--            </el-form-item>-->
+<!--            <el-form-item label="应用AgentId">-->
+<!--              <el-input v-model="qwConfig.AgentId" style="width:400px"   ></el-input>-->
+<!--            </el-form-item>-->
+<!--            <el-form-item label="Token">-->
+<!--              <el-input v-model="qwConfig.token" style="width:400px"   :readonly="true"></el-input>-->
+<!--            </el-form-item>-->
+<!--            <el-form-item label="EncodingAESKey">-->
+<!--              <el-input v-model="qwConfig.encodingAESKey" style="width:400px"   :readonly="true"></el-input>-->
+<!--            </el-form-item>-->
+<!--            <el-form-item label="域名地址">-->
+<!--              <el-input v-model="qwConfig.realmNameURL" style="width:600px"></el-input>-->
+<!--            </el-form-item>-->
+<!--            <el-form-item label="回调地接">-->
+<!--              <el-input v-model="qwConfig.notifyUrl" style="width:600px"   :readonly="true"></el-input>-->
+<!--            </el-form-item>-->
+<!--            <el-form-item label="聊天工具栏跳转地址">-->
+<!--              <el-input v-model="qwConfig.chatToolbar" style="width:600px"   :readonly="true"></el-input>-->
+<!--            </el-form-item>-->
+<!--            <el-form-item label="聊天工具栏实际运用地址">-->
+<!--              <el-input v-model="qwConfig.chatToolbarOAuth2" :rows="2"  type="textarea" style="width:1000px;"   :readonly="true"></el-input>-->
+<!--            </el-form-item>-->
+<!--            <div class="line"></div>-->
+<!--            <div style="float:right;margin-right:20px">-->
+<!--              <el-button type="primary" @click="onSubmit4">提交</el-button>-->
+<!--            </div>-->
+<!--          </el-form>-->
+<!--        </el-tab-pane>-->
+        <el-tab-pane label="AI客服配置" name="AiKfConfig">
+          <el-form ref="AiKfConfig" :model="AiKfConfig" label-width="120px">
+            <el-form-item label="通用Key">
+              <el-input  v-model="AiKfConfig.Key" style="width:600px"   ></el-input>
             </el-form-item>
-            <el-form-item label="通讯录Secret">
-              <el-input v-model="qwConfig.bookSecret" style="width:400px"   ></el-input>
+            <el-form-item label="调用地址">
+              <el-input  v-model="AiKfConfig.url" style="width:600px"   ></el-input>
             </el-form-item>
-
-            <el-form-item label="应用Secret">
-              <el-input v-model="qwConfig.appSecret" style="width:400px"   ></el-input>
+            <div class="line"></div>
+            <div style="float:right;margin-right:20px">
+              <el-button type="primary" @click="onSubmit5">提交</el-button>
+            </div>
+          </el-form>
+        </el-tab-pane>
+        <el-tab-pane label="红包商户配置" name="redPacketConfig" >
+          <el-form ref="redPacketConfig" :model="redPacketConfig"  label-width="150px">
+            <el-form-item   label="红包接口类型" prop="isNew">
+              <el-radio-group v-model="redPacketConfig.isNew">
+                <el-radio label="0">商家转账到零钱(旧)</el-radio>
+                <el-radio label="1">商家转账(新)</el-radio>
+              </el-radio-group>
             </el-form-item>
-            <el-form-item label="应用AgentId">
-              <el-input v-model="qwConfig.AgentId" style="width:400px"   ></el-input>
+            <el-form-item   label="公众号appid" prop="appId">
+              <el-input   v-model="redPacketConfig.appId"  label="请输入appId"></el-input>
             </el-form-item>
-            <el-form-item label="Token">
-              <el-input v-model="qwConfig.token" style="width:400px"   :readonly="true"></el-input>
+            <el-form-item   label="小程序appid" prop="appId">
+              <el-input   v-model="redPacketConfig.miniappId"  label="请输入appId"></el-input>
             </el-form-item>
-            <el-form-item label="EncodingAESKey">
-              <el-input v-model="qwConfig.encodingAESKey" style="width:400px"   :readonly="true"></el-input>
+            <el-form-item   label="商户号" prop="mchId">
+              <el-input   v-model="redPacketConfig.mchId"  label="请输入mchId"></el-input>
             </el-form-item>
-            <el-form-item label="域名地址">
-              <el-input v-model="qwConfig.realmNameURL" style="width:600px"></el-input>
+            <el-form-item   label="商户密钥" prop="mchKey">
+              <el-input   v-model="redPacketConfig.mchKey"  label="mchKey"></el-input>
             </el-form-item>
-            <el-form-item label="回调地接">
-              <el-input v-model="qwConfig.notifyUrl" style="width:600px"   :readonly="true"></el-input>
+            <el-form-item   label="p12证书路径" prop="keyPath">
+              <el-input   v-model="redPacketConfig.keyPath"  label="请输入keyPath"></el-input>
             </el-form-item>
-            <el-form-item label="聊天工具栏跳转地址">
-              <el-input v-model="qwConfig.chatToolbar" style="width:600px"   :readonly="true"></el-input>
+            <el-form-item   label="apiV3密钥" prop="apiV3Key">
+              <el-input   v-model="redPacketConfig.apiV3Key"  label="请输入apiV3Key"></el-input>
             </el-form-item>
-            <el-form-item label="聊天工具栏实际运用地址">
-              <el-input v-model="qwConfig.chatToolbarOAuth2" :rows="2"  type="textarea" style="width:1000px;"   :readonly="true"></el-input>
+            <el-form-item   label="公钥ID" prop="publicKeyId">
+              <el-input   v-model="redPacketConfig.publicKeyId"  label="请输入公钥ID"></el-input>
             </el-form-item>
-            <div class="line"></div>
-            <div style="float:right;margin-right:20px">
-              <el-button type="primary" @click="onSubmit4">提交</el-button>
-            </div>
-          </el-form>
-        </el-tab-pane>
-        <el-tab-pane label="AI客服配置" name="AiKfConfig">
-          <el-form ref="AiKfConfig" :model="AiKfConfig" label-width="120px">
-            <el-form-item label="通用Key">
-              <el-input  v-model="AiKfConfig.Key" style="width:600px"   ></el-input>
+            <el-form-item   label="公钥证书" prop="publicKeyPath">
+              <el-input   v-model="redPacketConfig.publicKeyPath"  label="请输入publicKeyPath"></el-input>
             </el-form-item>
-            <el-form-item label="调用地址">
-              <el-input  v-model="AiKfConfig.url" style="width:600px"   ></el-input>
+            <el-form-item   label="key路径" prop="privateKeyPath">
+              <el-input   v-model="redPacketConfig.privateKeyPath"  label="请输入"></el-input>
             </el-form-item>
-            <div class="line"></div>
+            <el-form-item   label="cert路径" prop="privateCertPath">
+              <el-input   v-model="redPacketConfig.privateCertPath"  label="请输入"></el-input>
+            </el-form-item>
+            <el-form-item   label="回调地址" prop="notifyUrl">
+              <el-input   v-model="redPacketConfig.notifyUrl"  label="请输入"></el-input>
+            </el-form-item>
+
             <div style="float:right;margin-right:20px">
-              <el-button type="primary" @click="onSubmit5">提交</el-button>
+              <el-button type="primary" @click="onSubmit4">提交</el-button>
             </div>
           </el-form>
         </el-tab-pane>
@@ -147,6 +194,23 @@
             </div>
           </el-form>
         </el-tab-pane>
+        <el-tab-pane label="配置销售端隐藏总账号" name="adminIsShowForm">
+          <el-form ref="adminIsShowForm" label-width="140px">
+            <el-form-item label="账号是否显示">
+              <el-row>
+                <el-switch v-model="adminIsShow"></el-switch>
+                <span style="margin-left: 10px;">
+                  <el-tag :type="adminIsShow ? 'success' : 'info'" size="mini">
+                    {{ adminIsShow ? '当前显示' : '当前隐藏' }}
+                  </el-tag>
+                </span>
+              </el-row>
+            </el-form-item>
+            <div style="float:right;margin-right:20px">
+              <el-button type="primary" @click="onSubmit7">提交</el-button>
+            </div>
+          </el-form>
+        </el-tab-pane>
       </el-tabs>
 
       <el-dialog :title="customerExt.title" :visible.sync="customerExt.open" width="500px" append-to-body>
@@ -198,6 +262,7 @@ export default {
   },
   data() {
     return {
+      adminIsShow: false,
       company:null,
       statusOptions:[],
       customerExt:{
@@ -238,7 +303,11 @@ export default {
       qwConfigForm:{},
       qwkfConfigForm:{},
       companyUserConfig: {},
+      adminIsShowForm:{},
       userIsDefaultBlack: null,
+      redPacketConfig:{},
+
+      redPacketConfigForm:{}
     };
   },
   created() {
@@ -248,6 +317,7 @@ export default {
     this.getConfigKey("sys:qw:config");
     this.getConfigKey("customer:config");
     this.getConfigKey("sys:AiKf:config");
+    this.getConfigKey("company:admin:show");
     this.getDicts("sys_company_status").then((response) => {
       this.statusOptions = response.data;
     });
@@ -379,13 +449,21 @@ export default {
                 this.AiKfConfig=JSON.parse(response.data.configValue);
               }
             }else if (key=="companyUser:config"){
-              console.log(response.data)
               this.companyUserConfig=response.data;
               if(response.data.configValue != null){
                 this.userIsDefaultBlack = JSON.parse(response.data.configValue);
               }
+            }else if(key == "company:admin:show"){
+              this.adminIsShowForm = response.data;
+              if(response.data.configValue != null){
+                this.adminIsShow = JSON.parse(response.data.configValue);
+              }
+            }else if(key=="redPacket:config"){
+              this.redPacketConfigForm=response.data;
+              if(response.data.configValue!=null){
+                this.redPacketConfig=JSON.parse(response.data.configValue);
+              }
             }
-
         });
     },
     onSubmit1() {
@@ -415,12 +493,21 @@ export default {
         }
       });
     },
+    // onSubmit4() {
+    //   this.qwConfigForm.configValue=JSON.stringify(this.qwConfig);
+    //   updateConfig(this.qwConfigForm).then(response => {
+    //     if (response.code === 200) {
+    //       this.msgSuccess("修改成功");
+    //       this.getConfigKey("sys:qw:config");
+    //     }
+    //   });
+    // },
     onSubmit4() {
-      this.qwConfigForm.configValue=JSON.stringify(this.qwConfig);
-      updateConfig(this.qwConfigForm).then(response => {
+      this.redPacketConfigForm.configValue=JSON.stringify(this.redPacketConfig);
+      updateConfig(this.redPacketConfigForm).then(response => {
         if (response.code === 200) {
           this.msgSuccess("修改成功");
-          this.getConfigKey("sys:qw:config");
+          this.getConfigKey("redPacket:config");
         }
       });
     },
@@ -435,8 +522,6 @@ export default {
     },
     onSubmit6() {
       this.companyUserConfig.configValue=JSON.stringify(this.userIsDefaultBlack);
-      console.log(this.companyUserConfig)
-      console.log(this.userIsDefaultBlack)
       configUserCheck({userIsDefaultBlack: this.userIsDefaultBlack}).then(response => {
         if (response.code === 200) {
           this.msgSuccess("修改成功");
@@ -444,6 +529,16 @@ export default {
         }
       });
     },
+    onSubmit7() {
+      // 实现提交逻辑
+      this.adminIsShowForm.configValue=JSON.stringify(this.adminIsShow);
+      updateConfig(this.adminIsShowForm).then(response => {
+        if (response.code === 200) {
+          this.msgSuccess("修改成功");
+          this.getConfigKey("company:admin:show");
+        }
+      })
+    },
   }
 };
 </script>

+ 221 - 131
src/views/company/companyUser/index.vue

@@ -2,7 +2,7 @@
   <div class="app-container">
     <el-row :gutter="20">
       <!--部门数据-->
-      <el-col :span="4" :xs="24">
+      <el-col :span="2" :xs="24">
         <div class="head-container">
           <el-input v-model="deptName" placeholder="请输入部门名称" clearable size="small" prefix-icon="el-icon-search" style="margin-bottom: 20px" />
         </div>
@@ -11,7 +11,7 @@
         </div>
       </el-col>
       <!--用户数据-->
-      <el-col :span="20" :xs="24">
+      <el-col :span="22" :xs="24">
         <el-form  :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="100px">
           <el-form-item label="员工后台昵称" prop="nickName">
             <el-input v-model="queryParams.nickName" placeholder="请输入员工后台昵称" clearable size="small" style="width: 240px" @keyup.enter.native="handleQuery" />
@@ -46,6 +46,9 @@
           <el-col :span="1.5">
             <el-button  plain type="success" icon="el-icon-edit" size="mini" :disabled="single" @click="handleUpdate" v-hasPermi="['company:user:edit']">修改</el-button>
           </el-col>
+          <el-col :span="1.5">
+            <el-button  plain type="success" icon="el-icon-edit" size="mini" :disabled="multiple" @click="batchEditRole"v-hasPermi="['company:user:edit']">批量修改角色</el-button>
+          </el-col>
           <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>
@@ -167,6 +170,18 @@
               <dict-tag :options="qwStatusOptions" :value="scope.row.qwStatus"/>
             </template>
           </el-table-column>
+          <el-table-column label="绑定的企微号" align="center">
+            <template slot-scope="scope">
+              <div v-if="scope.row.qwUsers && scope.row.qwUsers.length > 0">
+                <div v-for="user in scope.row.qwUsers" :key="user.id">
+                  <el-tag size="mini">{{ user.qwUserName }}</el-tag>
+                </div>
+              </div>
+              <div v-else>
+                <dict-tag :options="qwStatusOptions" :value="scope.row.qwStatus"/>
+              </div>
+            </template>
+          </el-table-column>
           <el-table-column label="区域" align="center" prop="addressId">
           </el-table-column>
           <el-table-column label="创建时间"  sortable align="center" prop="createTime" width="160">
@@ -240,14 +255,34 @@
         <pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" @pagination="getList" />
       </el-col>
     </el-row>
-    <el-dialog title="绑定企微账号"  :visible.sync="qwOpen" width="800px" append-to-body >
 
+    <!-- 批量修改角色对话框 -->
+    <el-dialog title="批量修改角色" :visible.sync="batchRoleDialogVisible" width="500px" append-to-body>
+      <el-form :model="batchRoleForm" label-width="80px">
+        <el-form-item label="选择角色">
+          <el-select v-model="selectedRoleIds" multiple placeholder="请选择角色" style="width: 100%;">
+            <el-option
+              v-for="item in roleOptions"
+              :key="item.roleId"
+              :label="item.roleName"
+              :value="item.roleId">
+            </el-option>
+          </el-select>
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button @click="batchRoleDialogVisible = false">取 消</el-button>
+        <el-button type="primary" @click="submitBatchRoles">确 定</el-button>
+      </div>
+    </el-dialog>
+
+    <!--当点击查或换绑微信时候弹出此框-->
+    <el-dialog title="绑定企微账号"  :visible.sync="qwOpen" width="800px" append-to-body >
       <el-form ref="form" :model="form"  label-width="80px" >
         <el-form-item label="查询"  prop="companyUserId">
           <el-button type="primary" icon="el-icon-search"  @click="selectQwUser()"  size="mini">搜索账号</el-button>
         </el-form-item>
         <el-form-item label="企微账号"  prop="companyUserId">
-
           <el-tag
             style="margin-left: 5px"
             size="medium"
@@ -260,15 +295,14 @@
             </span>
           </el-tag>
         </el-form-item>
-
       </el-form>
       <div slot="footer" class="dialog-footer">
         <el-button type="primary" @click="qwSubmitForm">绑 定</el-button>
         <el-button @click="qwCancel">取 消</el-button>
       </div>
     </el-dialog>
-    <el-dialog title="选择企微主体" :visible.sync="synOpen" width="800px" append-to-body>
 
+    <el-dialog title="选择企微主体" :visible.sync="synOpen" width="800px" append-to-body>
       <el-form   label-width="80px">
         <el-form-item label="企微公司" prop="corpId">
           <el-select v-model="synform.corpId" placeholder="企微公司"  >
@@ -280,8 +314,6 @@
             />
           </el-select>
         </el-form-item>
-
-
       </el-form>
       <div slot="footer" class="dialog-footer">
         <el-button type="primary" @click="synSubmitForm">确 定</el-button>
@@ -290,7 +322,6 @@
     </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="企微公司"  >
@@ -495,11 +526,11 @@
       </div>
     </el-dialog>
 
+    <!-- 修改 selectUser 组件的引用 -->
     <el-dialog :title="user.title" :visible.sync="user.open" width="1000px" append-to-body>
-      <selectUser ref="selectUser" @bindQwUser="bindQwUser"></selectUser>
+      <selectUser ref="selectUser" @bindQwUser="bindQwUser" @close="handleSelectUserClose"/>
     </el-dialog>
 
-
     <el-dialog :title="companyUserArea.title" :visible.sync="companyUserArea.open" width="300px" append-to-body>
       <el-select v-model="addressId"  filterable placeholder="请选择所属销售的区域" style="width: 200px;">
         <el-option
@@ -600,7 +631,7 @@ import {
   generateSubDomain,
   setIsRegisterMember,
   updateCompanyUserAreaList,
-  isAllowedAllRegister, unBindDoctorId, bindDoctorId
+  isAllowedAllRegister, unBindDoctorId, bindDoctorId,updateBatchUserRoles
 } from "@/api/company/companyUser";
 import { getToken } from "@/utils/auth";
 import { treeselect } from "@/api/company/companyDept";
@@ -798,6 +829,13 @@ export default {
       allowedAllRegisterForm: {
         status: true
       },
+      // 在 data() 中添加
+      batchRoleDialogVisible: false,
+      selectedRoleIds: [],
+      batchRoleForm: {
+        userIds: [],
+        roleIds: []
+      },
     };
   },
   watch: {
@@ -830,7 +868,7 @@ export default {
   },
   methods: {
     onDomainBlur() {
-      if (this.form.domain!=null){
+      if (this.form.domain != null) {
         let value = this.form.domain.trim();
 
         // 强制只保留第一个 http://
@@ -849,11 +887,98 @@ export default {
         // 正则校验最终格式,提醒用户
         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');
+          return this.$message.error('请输入正确格式的域名,如:http://xxx.xxx.com');
+        }
+      }
+    },
+
+    // 添加处理 selectUser 关闭的方法
+    handleSelectUserClose() {
+      this.user.open = false
+      // 如果 selectUser 组件有 clearSelection 方法,也可以调用
+      if (this.$refs.selectUser && typeof this.$refs.selectUser.clearSelection === 'function') {
+        this.$refs.selectUser.clearSelection()
+      }
+    },
+
+    // edit G start
+    // 修改 selectQwUser 方法
+    selectQwUser() {
+      this.user.open = true;
+      // 在下次DOM更新后设置已选中的项
+      this.$nextTick(() => {
+        if (this.$refs.selectUser && this.qwUserList.length > 0) {
+          // 将已选中的用户传递给子组件
+          this.$refs.selectUser.setSelectedUsers(this.qwUserList);
+        }
+      });
+    },
+
+    // 修改 bindQwUser 方法
+    bindQwUser(row) {
+      // this.user.open = false; // 暂时注释掉这行,改为在 handleBatchBind 中处理
+      if (!this.qwUserList.some(item => item.id == row.id)) {
+        this.qwUserList.push(row)
+      }
+      if (!this.qwUser.some(item => item == row.id)) {
+        this.qwUser.push(row.id)
+      }
+    },
+
+    // 修改 qwBind 方法
+    qwBind(row) {
+      this.qwUser = [];
+      this.qwUserList = [];
+      this.qwForm.companyUserId = row.userId;
+      getUser(row.userId).then((response) => {
+        if (response.data.qwUserId != null) {
+          // 保存已绑定的企微用户ID列表
+          this.qwUser = ((response.data.qwUserId).split(",").map(Number));
+          getQwUserByIds(this.qwUser).then(res => {
+            this.qwUserList = res.data;
+          });
         }
+        // 先打开"绑定企微账号"对话框
+        this.qwOpen = true;
+      });
+    },
+
+    // 在 methods 中添加批量修改角色的方法
+    batchEditRole() {
+      if (this.ids.length === 0) {
+        this.$message.warning("请至少选择一个用户");
+        return;
       }
+      // 获取角色列表数据
+      getUser().then((response) => {
+        this.roleOptions = response.roles;
+        this.batchRoleDialogVisible = true;
+        this.selectedRoleIds = []; // 清空之前的选择
+      });
+    },
 
+    // 添加批量角色更新提交方法
+    submitBatchRoles() {
+      // 验证选择的角色
+      if (!this.selectedRoleIds || this.selectedRoleIds.length === 0) {
+        this.$message.warning("请至少选择一个角色");
+        return;
+      }
+      console.log(this.ids)
+      console.log(this.selectedRoleIds)
+
+      // 调用API批量更新用户角色
+      updateBatchUserRoles({ userIds: this.ids, roleIds: this.selectedRoleIds })
+        .then(response => {
+          if (response.code === 200) {
+            this.$message.success("批量修改角色成功");
+            this.batchRoleDialogVisible = false;
+            this.getList(); // 刷新列表
+          }
+        });
     },
+    // edit G end
+
     /** 查询用户列表 */
     getList() {
       this.loading = true;
@@ -862,14 +987,12 @@ export default {
           this.userList = response.rows;
           this.total = response.total;
           this.loading = false;
-          console.log(" this.userList ", this.userList )
+          console.log(" this.userList ", this.userList)
         }
       );
     },
-    selectQwUser(){
-      this.user.open=true;
-    },
-    handleClosegroupUser(list){
+
+    handleClosegroupUser(list) {
       const index = this.qwUser.findIndex(t => t === list);
       if (index !== -1) {
         this.qwUser.splice(index, 1);
@@ -903,13 +1026,13 @@ export default {
           type: "warning",
         }
       )
-        .then(function () {
+        .then(function() {
           return changeUserStatus(row.userId, row.status);
         })
         .then(() => {
           this.msgSuccess(text + "成功");
         })
-        .catch(function () {
+        .catch(function() {
           row.status = row.status === "0" ? "1" : "0";
         });
     },
@@ -918,37 +1041,37 @@ export default {
       this.open = false;
       this.reset();
     },
-    cancelBind(){
-      this.bindCompanyOpen=false;
+    cancelBind() {
+      this.bindCompanyOpen = false;
       this.resetBindCompany();
     },
 
-    submitFormArea(address){
+    submitFormArea(address) {
       const uIds = this.ids;
 
-      if (address == null){
+      if (address == null) {
         this.$message.error("请选择地区");
         return;
       }
-      updateCompanyUserAreaList({userIds:uIds,addressId:address}).then(res=>{
-        this.companyUserArea.open=false;
+      updateCompanyUserAreaList({ userIds: uIds, addressId: address }).then(res => {
+        this.companyUserArea.open = false;
         this.getList();
         this.msgSuccess("操作成功");
 
       })
 
     },
-    cancelArea(){
-      this.companyUserArea.open=false;
-      this.addressId=null;
+    cancelArea() {
+      this.companyUserArea.open = false;
+      this.addressId = null;
     },
     qwCancel() {
       this.qwOpen = false;
-      this.qwUserId=null;
+      this.qwUserId = null;
     },
 
-    handerCompanyUserAreaList(){
-      this.companyUserArea.open=true;
+    handerCompanyUserAreaList() {
+      this.companyUserArea.open = true;
     },
     // 表单重置
     reset() {
@@ -1011,7 +1134,7 @@ export default {
       });
     },
 
-    handleBindCompanyUserCode(){
+    handleBindCompanyUserCode() {
       this.reset();
       this.getTreeselect();
       getUser().then((response) => {
@@ -1021,40 +1144,7 @@ export default {
         this.title = "创建 新增/绑定销售 的二维码";
       });
     },
-    qwBind(row){
-      this.qwUser=[];
-      this.qwUserList=[];
-      this.qwForm.companyUserId=row.userId
-      getUser(row.userId).then((response) => {
-        if(response.data.qwUserId!=null){
-           this.qwUser=((response.data.qwUserId).split(",").map(Number))
-          getQwUserByIds(this.qwUser).then(res => {
-            this.qwUserList=res.data;
-          })
-           // this.qwUser.forEach(item => {
-           //     getQwUser(item).then(response => {
-           //         this.qwUserList.push(response.data);
-           //     });
-           // });
-        }
-        this.qwOpen = true;
-      });
-
-    },
 
-    bindQwUser(row){
-      this.user.open=false;
-
-
-        if (!this.qwUserList.some(item => item.id == row.id)) {
-          this.qwUserList.push(row)
-        }
-
-        if (!this.qwUser.some(item => item == row.id)) {
-          this.qwUser.push(row.id);
-        }
-
-    },
     /** 修改按钮操作 */
     handleUpdate(row) {
       this.reset();
@@ -1096,10 +1186,11 @@ export default {
             }
           });
         })
-        .catch(() => {});
+        .catch(() => {
+        });
     },
     /** 提交按钮 */
-    submitForm: function () {
+    submitForm: function() {
 
       // this.onDomainBlur();
 
@@ -1141,7 +1232,7 @@ export default {
       document.body.removeChild(link);
     },
 
-    submitBingCompanyForm: function () {
+    submitBingCompanyForm: function() {
 
       this.$refs["formBindCompany"].validate((valid) => {
         if (valid) {
@@ -1153,23 +1244,23 @@ export default {
             background: 'rgba(0, 0, 0, 0.7)'
           });
 
-            addCodeUrl(this.formBindCompany).then((response) => {
-              this.bindCompanyOpen=false;
-              this.bindCompanyUrl.url=response.data.url
-              this.bindCompanyUrl.open=true;
-              this.bindCompanyUrl.name="绑定或新增 销售二维码";
-            }).finally(res=>{
-              loadingRock.close();
-            })
+          addCodeUrl(this.formBindCompany).then((response) => {
+            this.bindCompanyOpen = false;
+            this.bindCompanyUrl.url = response.data.url
+            this.bindCompanyUrl.open = true;
+            this.bindCompanyUrl.name = "绑定或新增 销售二维码";
+          }).finally(res => {
+            loadingRock.close();
+          })
         }
       });
     },
     /**
-    * 同步企业微信员工
-    */
+     * 同步企业微信员工
+     */
     synSubmitForm() {
-      this.synOpen=false;
-      this.loading=true;
+      this.synOpen = false;
+      this.loading = true;
       /*this.msgSuccess("");
 
       let loadingRock = this.$loading({
@@ -1179,63 +1270,60 @@ export default {
         background: 'rgba(0, 0, 0, 0.7)'
       });*/
 
-
       addQwUser(this.synform.corpId).then(response => {
         //this.msgSuccess("同步成功");
         this.msgSuccess("正在同步中...");
         this.getList();
-        this.synOpen=false;
-      }).finally(()=>{
-        this.loading=false;
-        this.synOpen=false;
+        this.synOpen = false;
+      }).finally(() => {
+        this.loading = false;
+        this.synOpen = false;
         //loadingRock.close();
       });
     },
 
     synNameSubmitForm() {
-      this.synNameOpen=false;
-      this.loading=true;
+      this.synNameOpen = false;
+      this.loading = true;
 
       addQwUserName(this.synNameform.corpId).then(response => {
         // this.msgSuccess("同步成功");
         this.msgSuccess("正在同步中...");
         this.getList();
-        this.synNameOpen=false;
-      }).finally(()=>{
-        this.loading=false;
-        this.synNameOpen=false;
+        this.synNameOpen = false;
+      }).finally(() => {
+        this.loading = false;
+        this.synNameOpen = false;
         //loadingRock.close();
       });
     },
     /**
-    * 同步企业微信部门
-    */
-    qwSyncDept(){
+     * 同步企业微信部门
+     */
+    qwSyncDept() {
       syncDept().then(response => {
         this.msgSuccess("同步成功");
         this.getList();
-      }).catch(()=>{
-        this.msgError("同步失败:"+response.msg);
+      }).catch(() => {
+        this.msgError("同步失败:" + response.msg);
       })
     },
-    qwSubmitForm(){
 
+    qwSubmitForm() {
       let loadingRock = this.$loading({
         lock: true,
         text: '绑定中.....同步客户信息中.....',
         spinner: 'el-icon-loading',
         background: 'rgba(0, 0, 0, 0.7)'
       });
-
       this.qwForm.id = (this.qwUser).join(',');
-
       bindQwUser(this.qwForm).then(response => {
         this.msgSuccess("绑定成功");
         this.qwOpen = false;
         this.getList();
-        this.qwUserId=null;
-        this.qwUser=[];
-      }).finally(res=>{
+        this.qwUserId = null;
+        this.qwUser = [];
+      }).finally(res => {
         loadingRock.close()
       });
     },
@@ -1251,14 +1339,15 @@ export default {
           type: "warning",
         }
       )
-        .then(function () {
+        .then(function() {
           return delUser(userIds);
         })
         .then(() => {
           this.getList();
           this.msgSuccess("删除成功");
         })
-        .catch(function () {});
+        .catch(function() {
+        });
     },
     /** 导出按钮操作 */
     handleExport() {
@@ -1268,13 +1357,14 @@ export default {
         cancelButtonText: "取消",
         type: "warning",
       })
-        .then(function () {
+        .then(function() {
           return exportUser(queryParams);
         })
         .then((response) => {
           this.download(response.msg);
         })
-        .catch(function () {});
+        .catch(function() {
+        });
     },
     /** 导入按钮操作 */
     handleImport() {
@@ -1303,15 +1393,15 @@ export default {
     submitFileForm() {
       this.$refs.upload.submit();
     },
-    generateDomain(){
+    generateDomain() {
       let queryParams;
-      if(this.form.userId){
-        queryParams= {
+      if (this.form.userId) {
+        queryParams = {
           'userId': this.form.userId,
         }
       }
       generateSubDomain(queryParams).then(response => {
-        this.form.domain=response.data
+        this.form.domain = response.data
       });
     },
     /** 设置单独注册会员按钮操作 */
@@ -1321,7 +1411,7 @@ export default {
     },
     /** 提交设置单独注册会员 */
     submitRegisterForm() {
-      setIsRegisterMember({status: this.registerForm.status}, this.ids).then(response => {
+      setIsRegisterMember({ status: this.registerForm.status }, this.ids).then(response => {
         if (response.code === 200) {
           this.msgSuccess("设置成功");
           this.registerOpen = false;
@@ -1336,8 +1426,8 @@ export default {
       // this.allowedAllRegisterForm.status = true;
     },
     // 提交
-    submitAllowedAllRegisterForm(){
-      isAllowedAllRegister({status: this.allowedAllRegisterForm.status}, this.ids).then(response => {
+    submitAllowedAllRegisterForm() {
+      isAllowedAllRegister({ status: this.allowedAllRegisterForm.status }, this.ids).then(response => {
         if (response.code === 200) {
           this.msgSuccess("操作成功");
           this.allowedAllRegisterOpen = false;
@@ -1383,7 +1473,7 @@ export default {
       const formData = new FormData();
       formData.append('file', file);
 
-      formData.append('userId',row.userId)
+      formData.append('userId', row.userId)
 
       this.$set(row, 'uploading', true);
       this.$set(row, 'uploadError', '');
@@ -1425,7 +1515,7 @@ export default {
     },
     requestUpload() {
     },
-    beforeUpload(){
+    beforeUpload() {
       console.log(file.type)
       const isPic =
         file.type === 'image/jpeg' ||
@@ -1443,25 +1533,25 @@ export default {
       }
       return isPic && isLt2M
     },
-    handleUpdateDoctor(row){
-      this.doctor.title="绑定医生"
-      this.doctor.open=true;
-      this.doctorForm.userId=row.userId;
+    handleUpdateDoctor(row) {
+      this.doctor.title = "绑定医生"
+      this.doctor.open = true;
+      this.doctorForm.userId = row.userId;
     },
-    bindCompanyUserDoctorId(row){
+    bindCompanyUserDoctorId(row) {
       console.log(row)
-      this.doctorForm.doctorId=row;
-      bindDoctorId(this.doctorForm).then(res=>{
-        if (res.code==200){
+      this.doctorForm.doctorId = row;
+      bindDoctorId(this.doctorForm).then(res => {
+        if (res.code == 200) {
           this.$message.success('绑定成功')
-        }else {
-          this.$message.error('绑定失败:',res.msg)
+        } else {
+          this.$message.error('绑定失败:', res.msg)
         }
         this.getList()
-        this.doctor.open=false;
+        this.doctor.open = false;
       })
     },
-    handleUnBindUserId(val){
+    handleUnBindUserId(val) {
       this.$confirm(
         '确认解绑医生:<span style="color: green;">' + val.nickName + '' +
         '</span> 的医生?',
@@ -1476,10 +1566,10 @@ export default {
       }).then(response => {
         this.getList();
         this.msgSuccess("解绑成功");
-      }).finally(res=>{
+      }).finally(res => {
         this.getList();
       })
     },
   },
-};
+}
 </script>

+ 125 - 56
src/views/company/components/selectQwUser.vue

@@ -1,6 +1,7 @@
 <template>
   <div class="app-container">
     <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
+      <!-- 现有表单内容保持不变 -->
       <el-form-item label="企微主体" prop="corpId">
         <el-select v-model="queryParams.corpId" placeholder="企微主体" size="small" @change="updateCorpId()">
           <el-option
@@ -36,27 +37,32 @@
       </el-form-item>
     </el-form>
 
-    <el-table  height="500" border v-loading="loading" :data="customerList" ref="customerList" >
-       <el-table-column label="企微昵称" align="center" prop="qwUserName" />
+    <el-table
+      height="500"
+      border
+      v-loading="loading"
+      :data="customerList"
+      ref="customerList"
+      @selection-change="handleSelectionChange"
+    >
+      <!-- 添加多选列 -->
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="企微昵称" align="center" prop="qwUserName" />
       <el-table-column label="企微账号" align="center" prop="qwUserId" />
       <el-table-column label="企微所属部门" align="center" prop="departmentName" />
-	  <el-table-column label="状态" align="center" prop="status" >
-	    <template slot-scope="scope">
-	      <dict-tag :options="qwStatusOptions" :value="scope.row.status"/>
-	    </template>
-	   </el-table-column>
-      <el-table-column label="企微主体" align="center" prop="corpName" />
-      <el-table-column label="操作"   align="center" fixed="right" width="100px" class-name="small-padding fixed-width">
+      <el-table-column label="状态" align="center" prop="status" >
         <template slot-scope="scope">
-          <el-button
-            size="medium"
-            type="primary"
-            plain
-            @click="handleBind(scope.row)"
-          >选择</el-button>
+          <dict-tag :options="qwStatusOptions" :value="scope.row.status"/>
         </template>
       </el-table-column>
+      <el-table-column label="企微主体" align="center" prop="corpName" />
     </el-table>
+
+    <div style="margin-top: 10px; text-align: right;">
+      <el-button type="primary" @click="handleBatchBind">确定</el-button>
+      <el-button @click="cancelSelect">取消选择</el-button>
+    </div>
+
     <pagination
       v-show="total>0"
       :total="total"
@@ -64,8 +70,6 @@
       :limit.sync="queryParams.pageSize"
       @pagination="getList"
     />
-
-
   </div>
 </template>
 
@@ -80,7 +84,7 @@ export default {
       // 遮罩层
       loading: true,
       myQwCompanyList:[],
-	  qwStatusOptions:[],
+      qwStatusOptions:[],
       // 显示搜索条件
       showSearch: true,
       // 总条数
@@ -100,29 +104,31 @@ export default {
         qwUserName: null,
       },
       // 表单参数
-      form: {
-      },
+      form: {},
       // 表单校验
-      rules: {
-      },
+      rules: {},
+      // 多选数据
+      selectedUsers: [],
+      // 已选中的用户ID列表(用于初始化选中状态)
+      preSelectedUserIds: []
     };
   },
   created() {
-	  this.getDicts("sys_qw_user_status").then(response => {
-	        this.qwStatusOptions = response.data;
-	  });
+    this.getDicts("sys_qw_user_status").then(response => {
+      this.qwStatusOptions = response.data;
+    });
     getMyQwCompanyList().then(response => {
-           this.myQwCompanyList = response.data;
-           if(this.myQwCompanyList!=null){
-             this.queryParams.corpId=this.myQwCompanyList[0].dictValue
-             this.getList();
-           }
+      this.myQwCompanyList = response.data;
+      if(this.myQwCompanyList!=null){
+        this.queryParams.corpId=this.myQwCompanyList[0].dictValue
+        this.getList();
+      }
     });
   },
   methods: {
     updateCorpId(){
-           this.getList();
-     },
+      this.getList();
+    },
     /** 查询客户列表 */
     getList() {
       this.loading = true;
@@ -131,25 +137,88 @@ export default {
         this.customerList = response.rows;
         this.total = response.total;
         this.loading = false;
+
+        // 在数据加载完成后设置已选中项
+        this.$nextTick(() => {
+          this.setPreSelectedItems();
+        });
+      });
+    },
+
+    // 设置预选中的项
+    setPreSelectedItems() {
+      if (this.preSelectedUserIds.length > 0 && this.customerList.length > 0) {
+        // 找到需要预选中的行
+        const selectedRows = this.customerList.filter(row =>
+          this.preSelectedUserIds.includes(row.id)
+        );
+
+        // 设置选中状态
+        this.$nextTick(() => {
+          selectedRows.forEach(row => {
+            this.$refs.customerList.toggleRowSelection(row, true);
+          });
+        });
+      }
+    },
+
+    // 多选处理
+    handleSelectionChange(selection) {
+      this.selectedUsers = selection;
+    },
+
+    // 批量绑定选择
+    handleBatchBind() {
+      if (this.selectedUsers.length === 0) {
+        this.$message.warning("请至少选择一个用户");
+        return;
+      }
+
+      // 发送所有选中的用户数据
+      this.selectedUsers.forEach(user => {
+        this.$emit("bindQwUser", user);
       });
+
+      // 清空选择
+      this.clearSelection();
+      this.$emit('close'); // 通知父组件关闭对话框
     },
 
-    //绑定选择
-    handleBind(row){
+    // 添加一个新的方法用于清除选择
+    clearSelection() {
+      this.selectedUsers = [];
+      this.preSelectedUserIds = [];
+      if (this.$refs.customerList) {
+        this.$refs.customerList.clearSelection();
+      }
+    },
+
+    // 设置已选中的用户(由父组件调用)
+    setSelectedUsers(users) {
+      this.preSelectedUserIds = users.map(user => user.id);
+      this.selectedUsers = [...users];
+
+      // 如果数据已经加载,直接设置选中状态
+      if (this.customerList.length > 0) {
+        this.setPreSelectedItems();
+      }
+    },
 
-      this.$emit("bindQwUser",row)
-      this.resetQuery();
+    // 取消选择
+    cancelSelect() {
       this.$refs.customerList.clearSelection();
+      this.selectedUsers = [];
     },
+
     // 取消按钮
     cancel() {
       this.open = false;
       this.reset();
+      this.clearSelection(); // 清除选择
     },
     /** 搜索按钮操作 */
     handleQuery() {
       this.queryParams.pageNum = 1;
-
       this.getList();
     },
     /** 重置按钮操作 */
@@ -158,27 +227,27 @@ export default {
       this.queryParams.corpId= this.myQwCompanyList[0].dictValue;
       this.handleQuery();
     },
-
   }
 };
 </script>
+
 <style>
-  .el-tag + .el-tag {
-    margin-left: 10px;
-  }
-  .button-new-tag {
-    margin-left: 10px;
-    height: 32px;
-    line-height: 30px;
-    padding-top: 0;
-    padding-bottom: 0;
-  }
-  .input-new-tag {
-    width: 90px;
-    margin-left: 10px;
-    vertical-align: bottom;
-  }
-  .el-dialog__wrapper{
-    z-index: 100000;
-  }
+.el-tag + .el-tag {
+  margin-left: 10px;
+}
+.button-new-tag {
+  margin-left: 10px;
+  height: 32px;
+  line-height: 30px;
+  padding-top: 0;
+  padding-bottom: 0;
+}
+.input-new-tag {
+  width: 90px;
+  margin-left: 10px;
+  vertical-align: bottom;
+}
+.el-dialog__wrapper{
+  z-index: 100000;
+}
 </style>

+ 184 - 0
src/views/company/components/selectQwUserOlder.vue

@@ -0,0 +1,184 @@
+<!--<template>-->
+<!--  <div class="app-container">-->
+<!--    <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">-->
+<!--      <el-form-item label="企微主体" prop="corpId">-->
+<!--        <el-select v-model="queryParams.corpId" placeholder="企微主体" size="small" @change="updateCorpId()">-->
+<!--          <el-option-->
+<!--            v-for="dict in myQwCompanyList"-->
+<!--            :key="dict.dictValue"-->
+<!--            :label="dict.dictLabel"-->
+<!--            :value="dict.dictValue"-->
+<!--          />-->
+<!--        </el-select>-->
+<!--      </el-form-item>-->
+<!--      <el-form-item label="企微账号" prop="qwUserId">-->
+<!--        <el-input-->
+<!--          v-model="queryParams.qwUserId"-->
+<!--          placeholder="请输入企微账号"-->
+<!--          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>-->
+<!--        <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-table  height="500" border v-loading="loading" :data="customerList" ref="customerList" >-->
+<!--       <el-table-column label="企微昵称" align="center" prop="qwUserName" />-->
+<!--      <el-table-column label="企微账号" align="center" prop="qwUserId" />-->
+<!--      <el-table-column label="企微所属部门" align="center" prop="departmentName" />-->
+<!--	  <el-table-column label="状态" align="center" prop="status" >-->
+<!--	    <template slot-scope="scope">-->
+<!--	      <dict-tag :options="qwStatusOptions" :value="scope.row.status"/>-->
+<!--	    </template>-->
+<!--	   </el-table-column>-->
+<!--      <el-table-column label="企微主体" align="center" prop="corpName" />-->
+<!--      <el-table-column label="操作"   align="center" fixed="right" width="100px" class-name="small-padding fixed-width">-->
+<!--        <template slot-scope="scope">-->
+<!--          <el-button-->
+<!--            size="medium"-->
+<!--            type="primary"-->
+<!--            plain-->
+<!--            @click="handleBind(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"-->
+<!--    />-->
+
+
+<!--  </div>-->
+<!--</template>-->
+
+<!--<script>-->
+<!--import { userList,listUser, getUser, delUser, addUser, updateUser, exportUser, updateUserWeclome,getMyQwCompanyList,getMyQwUserList,relieveFastGptRoleById,staffListUser } from '@/api/qw/user'-->
+
+<!--export default {-->
+<!--  name: "miniCustomer",-->
+<!--  components: {},-->
+<!--  data() {-->
+<!--    return {-->
+<!--      // 遮罩层-->
+<!--      loading: true,-->
+<!--      myQwCompanyList:[],-->
+<!--	  qwStatusOptions:[],-->
+<!--      // 显示搜索条件-->
+<!--      showSearch: true,-->
+<!--      // 总条数-->
+<!--      total: 0,-->
+<!--      // 员工表格数据-->
+<!--      customerList: [],-->
+<!--      // 弹出层标题-->
+<!--      title: "",-->
+<!--      // 是否显示弹出层-->
+<!--      open: false,-->
+<!--      // 查询参数-->
+<!--      queryParams: {-->
+<!--        pageNum: 1,-->
+<!--        pageSize: 10,-->
+<!--        qwUserId: null,-->
+<!--        corpId: null,-->
+<!--        qwUserName: null,-->
+<!--      },-->
+<!--      // 表单参数-->
+<!--      form: {-->
+<!--      },-->
+<!--      // 表单校验-->
+<!--      rules: {-->
+<!--      },-->
+<!--    };-->
+<!--  },-->
+<!--  created() {-->
+<!--	  this.getDicts("sys_qw_user_status").then(response => {-->
+<!--	        this.qwStatusOptions = response.data;-->
+<!--	  });-->
+<!--    getMyQwCompanyList().then(response => {-->
+<!--           this.myQwCompanyList = response.data;-->
+<!--           if(this.myQwCompanyList!=null){-->
+<!--             this.queryParams.corpId=this.myQwCompanyList[0].dictValue-->
+<!--             this.getList();-->
+<!--           }-->
+<!--    });-->
+<!--  },-->
+<!--  methods: {-->
+<!--    updateCorpId(){-->
+<!--           this.getList();-->
+<!--     },-->
+<!--    /** 查询客户列表 */-->
+<!--    getList() {-->
+<!--      this.loading = true;-->
+
+<!--      userList(this.queryParams).then(response => {-->
+<!--        this.customerList = response.rows;-->
+<!--        this.total = response.total;-->
+<!--        this.loading = false;-->
+<!--      });-->
+<!--    },-->
+
+<!--    //绑定选择-->
+<!--    handleBind(row){-->
+
+<!--      this.$emit("bindQwUser",row)-->
+<!--      this.resetQuery();-->
+<!--      this.$refs.customerList.clearSelection();-->
+<!--    },-->
+<!--    // 取消按钮-->
+<!--    cancel() {-->
+<!--      this.open = false;-->
+<!--      this.reset();-->
+<!--    },-->
+<!--    /** 搜索按钮操作 */-->
+<!--    handleQuery() {-->
+<!--      this.queryParams.pageNum = 1;-->
+
+<!--      this.getList();-->
+<!--    },-->
+<!--    /** 重置按钮操作 */-->
+<!--    resetQuery() {-->
+<!--      this.resetForm("queryForm");-->
+<!--      this.queryParams.corpId= this.myQwCompanyList[0].dictValue;-->
+<!--      this.handleQuery();-->
+<!--    },-->
+
+<!--  }-->
+<!--};-->
+<!--</script>-->
+<!--<style>-->
+<!--  .el-tag + .el-tag {-->
+<!--    margin-left: 10px;-->
+<!--  }-->
+<!--  .button-new-tag {-->
+<!--    margin-left: 10px;-->
+<!--    height: 32px;-->
+<!--    line-height: 30px;-->
+<!--    padding-top: 0;-->
+<!--    padding-bottom: 0;-->
+<!--  }-->
+<!--  .input-new-tag {-->
+<!--    width: 90px;-->
+<!--    margin-left: 10px;-->
+<!--    vertical-align: bottom;-->
+<!--  }-->
+<!--  .el-dialog__wrapper{-->
+<!--    z-index: 100000;-->
+<!--  }-->
+<!--</style>-->

+ 305 - 4
src/views/course/courseFinishTemp/index.vue

@@ -224,7 +224,52 @@
                       </el-card>
                     </div>
                     <div v-if="item.contentType == 4">
+                      <el-card class="box-card">
+
+                        <el-form-item label="选择课程">
+                          <el-select
+                            v-model="item.courseId"
+                            placeholder="请选择课程"
+                            style="margin-right: 10px"
+                            size="mini"
+                            @change="handleRuleCourseChange(item)"
+                          >
+                            <el-option
+                              v-for="dict in courseList"
+                              :key="dict.dictValue"
+                              :label="dict.dictLabel"
+                              :value="parseInt(dict.dictValue)"
+                            />
+                          </el-select>
+                          <el-select
+                            v-model="item.videoId"
+                            placeholder="请选择小节"
+                            size="mini"
+                            style="margin-right: 10px"
+                            filterable
+                            remote
+                            :remote-method="(query) => remoteMethodRuleVideo(query, item)"
+                            :loading="videoOptionsLoading"
+                            @change="handleRuleVideoChange(item)"
+                          >
+                            <el-option
+                              v-for="dict in videoOptions || []"
+                              :key="dict.dictValue"
+                              :label="dict.dictLabel"
+                              :value="parseInt(dict.dictValue)"
+                            />
+                          </el-select>
+                        </el-form-item>
 
+                        <el-card class="box-card" style="margin-top: 10px">
+                          <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-card>
+                      </el-card>
                     </div>
                     <div v-if="item.contentType == 5 ">
 
@@ -270,7 +315,44 @@
                         @input="handleInputVideoText(item.value,item)"/>
                     </div>
                     <div v-if="item.contentType == 8">
+                      <el-button type="primary"
+                                 style="margin-bottom: 1%"
+                                 @click="hanldeSelectVideoNum(setting,index)">
+                        选择视频号
+                      </el-button>
+                      <el-card class="box-card" v-if="item.coverUrl">
+                        <el-form-item label="封面标题:" label-width="100px">
+                          <el-input v-model="item.nickname"
+                                    style="width: 90%;margin-bottom: 1%" disabled/>
+                        </el-form-item>
+                        <el-form-item label="头像:" label-width="100px">
+                          <el-image
+                            v-if="item.avatar != null"
+                            :src="item.avatar"
+                            :preview-src-list="[item.avatar]"
+                            :style="{ width: '50px', height: '50px' }"
+                          ></el-image>
+                        </el-form-item>
+                        <el-form-item label="封面:" label-width="100px">
+                          <el-image
+                            v-if="item.coverUrl != null"
+                            :src="item.coverUrl"
+                            :preview-src-list="[item.coverUrl]"
+                            :style="{ width: '200px', height: '200px' }"
+                          ></el-image>
 
+                        </el-form-item>
+                        <el-form-item label="简介:" label-width="100px">
+                          <el-input type="textarea" :rows="3"
+                                    v-model="item.desc"
+                                    style="width: 90%;margin-top: 1%;" disabled/>
+                        </el-form-item>
+                        <el-form-item label="视频地址:" label-width="100px"
+                                      style="margin-top: 1%">
+                          <el-input v-model="item.url"
+                                    style="width: 90%;" disabled/>
+                        </el-form-item>
+                      </el-card>
                     </div>
 
                   </el-form-item>
@@ -324,7 +406,52 @@
                       </el-card>
                     </div>
                     <div v-if="item.contentType == 4">
+                      <el-card class="box-card">
+
+                        <el-form-item label="选择课程">
+                          <el-select
+                            v-model="item.courseId"
+                            placeholder="请选择课程"
+                            style="margin-right: 10px"
+                            size="mini"
+                            @change="handleRuleCourseChange(item)"
+                          >
+                            <el-option
+                              v-for="dict in courseList"
+                              :key="dict.dictValue"
+                              :label="dict.dictLabel"
+                              :value="parseInt(dict.dictValue)"
+                            />
+                          </el-select>
+                          <el-select
+                            v-model="item.videoId"
+                            placeholder="请选择小节"
+                            size="mini"
+                            style="margin-right: 10px"
+                            filterable
+                            remote
+                            :remote-method="(query) => remoteMethodRuleVideo(query, item)"
+                            :loading="videoOptionsLoading"
+                            @change="handleRuleVideoChange(item)"
+                          >
+                            <el-option
+                              v-for="dict in videoOptions || []"
+                              :key="dict.dictValue"
+                              :label="dict.dictLabel"
+                              :value="parseInt(dict.dictValue)"
+                            />
+                          </el-select>
+                        </el-form-item>
 
+                        <el-card class="box-card" style="margin-top: 10px">
+                          <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-card>
+                      </el-card>
                     </div>
                     <div v-if="item.contentType == 5 ">
 
@@ -370,7 +497,44 @@
                         @input="handleInputVideoText(item.value,item)"/>
                     </div>
                     <div v-if="item.contentType == 8">
+                      <el-button type="primary"
+                                 style="margin-bottom: 1%"
+                                 @click="hanldeSelectVideoNum(setting,index)">
+                        选择视频号
+                      </el-button>
+                      <el-card class="box-card" v-if="item.coverUrl">
+                        <el-form-item label="封面标题:" label-width="100px">
+                          <el-input v-model="item.nickname"
+                                    style="width: 90%;margin-bottom: 1%" disabled/>
+                        </el-form-item>
+                        <el-form-item label="头像:" label-width="100px">
+                          <el-image
+                            v-if="item.avatar != null"
+                            :src="item.avatar"
+                            :preview-src-list="[item.avatar]"
+                            :style="{ width: '50px', height: '50px' }"
+                          ></el-image>
+                        </el-form-item>
+                        <el-form-item label="封面:" label-width="100px">
+                          <el-image
+                            v-if="item.coverUrl != null"
+                            :src="item.coverUrl"
+                            :preview-src-list="[item.coverUrl]"
+                            :style="{ width: '200px', height: '200px' }"
+                          ></el-image>
 
+                        </el-form-item>
+                        <el-form-item label="简介:" label-width="100px">
+                          <el-input type="textarea" :rows="3"
+                                    v-model="item.desc"
+                                    style="width: 90%;margin-top: 1%;" disabled/>
+                        </el-form-item>
+                        <el-form-item label="视频地址:" label-width="100px"
+                                      style="margin-top: 1%">
+                          <el-input v-model="item.url"
+                                    style="width: 90%;" disabled/>
+                        </el-form-item>
+                      </el-card>
                     </div>
 
                   </el-form-item>
@@ -414,6 +578,9 @@
         <el-button @click="cancel">取 消</el-button>
       </div>
     </el-dialog>
+    <el-dialog :title="videoNumOptions.title" :visible.sync="videoNumOptions.open" width="1500px" append-to-body>
+      <userVideo ref="QwUserVideo" @videoResult="qwUserVideoResult"></userVideo>
+    </el-dialog>
   </div>
 </template>
 
@@ -430,12 +597,21 @@ import { getUserList } from '@/api/company/companyUser'
 import { courseList, videoList } from '@/api/qw/sop'
 import ImageUpload from '@/views/qw/sop/ImageUpload.vue'
 import Tip from "../../../components/Tip/index.vue";
-
+import userVideo from "@/views/qw/userVideo/userVideo.vue";
 export default {
   name: "CourseFinishTemp",
-  components: {Tip, ImageUpload},
+  components: {Tip, ImageUpload,userVideo},
   data() {
     return {
+      videoOptionsLoading: false,
+      videoOptions: [],
+      videoLoading: false,
+      videoNumOptions: {
+        title: '选择视频号',
+        open: false,
+        content: null,
+        contentIndex: null,
+      },
       //上传语音的遮罩层
       voiceLoading: false,
       uploadUrl: process.env.VUE_APP_BASE_API + "/common/uploadOSS2",
@@ -493,6 +669,7 @@ export default {
       chatSetting: [],
       // 表单参数
       form: {
+        companyUserIds: [],
         setting: null,
         chatSetting: null,
         videoIdSet: null,
@@ -531,6 +708,101 @@ export default {
     this.getList();
   },
   methods: {
+    // 处理规则中课程变化
+    handleRuleCourseChange(item) {
+      // 为当前规则项单独加载视频列表
+      videoList(item.courseId).then((response) => {
+        // 只保存视频列表,不保存整个响应对象
+        this.videoOptions = response.list;
+
+        this.$set(item, 'videoId', null); // Reset video selection when course changes
+
+        // 自动设置封面为课程封面
+        const selectedCourse = this.courseList.find(
+          course => parseInt(course.dictValue) === item.courseId
+        );
+        if (selectedCourse) {
+          this.$set(item, 'miniprogramPicUrl', selectedCourse.dictImgUrl);
+        }
+      });
+    },
+
+
+    // 处理规则中视频变化
+    handleRuleVideoChange(item) {
+      if (!item.videoId) return;
+
+      // 自动设置标题为视频标题
+      const selectedVideo = (this.videoOptions || []).find(
+        video => parseInt(video.dictValue) === item.videoId
+      );
+      if (selectedVideo) {
+        this.$set(item, 'miniprogramTitle', selectedVideo.dictLabel);
+      }
+    },
+
+    // 远程搜索规则中的视频
+    remoteMethodRuleVideo(query, item) {
+      if (!item.courseId) {
+        this.$message.warning('请先选择课程');
+        this.videoOptions = [];
+        reject();
+        return;
+      }
+
+      this.videoOptionsLoading = true;
+      const data = query ? { title: query } : {};
+
+      videoList(item.courseId, data).then((response) => {
+        this.videoOptions =  response.list;
+        this.videoOptionsLoading =  false;
+        resolve(response);
+      }).catch((error) => {
+        this.videoOptionsLoading = false;
+        reject(error);
+      });
+    },
+    remoteMethodVideo(query) {
+      if (!this.form.courseId) {
+        this.$message.warning('请先选择课程');
+        this.videoList = []; // 清空小节列表
+        return;
+      }
+      if (query !== '') {
+        this.videoLoading = true;
+        // 这里调用接口搜索小节,假设 videoList 方法支持搜索参数
+        var data = {
+          title:query
+        }
+        videoList(this.form.courseId, data).then((response) => {
+          this.videoList = response.list;
+          this.videoLoading = false;
+        });
+      } else {
+        // 如果查询为空,则加载全部
+        videoList(this.form.courseId).then((response) => {
+          this.videoList = response.list;
+        });
+      }
+    },
+    qwUserVideoResult(val) {
+
+      // 根据选中的内容,将返回的数据更新到相应的表单项
+      const content = this.videoNumOptions.content;
+      const setList = content[this.videoNumOptions.contentIndex];
+      setList.nickname = val.nickname;
+      setList.avatar = val.avatar;
+      setList.coverUrl = val.coverUrl;
+      setList.thumbUrl = val.thumbUrl;
+      setList.desc = val.desc;
+      setList.url = val.url;
+      setList.extras = val.extras;
+      setList.videoId = val.id;
+      console.info(setList)
+
+      this.videoNumOptions.open = false;
+
+    },
     courseChange() {
 
       videoList(this.form.courseId).then(response => {
@@ -674,6 +946,12 @@ export default {
       this.open = true;
       this.title = "添加完课模板";
     },
+    //选择视频号
+    hanldeSelectVideoNum(content, index) {
+      this.videoNumOptions.content = content;
+      this.videoNumOptions.contentIndex = index;
+      this.videoNumOptions.open = true;
+    },
 
     /**
      * 查看完课模板
@@ -719,11 +997,22 @@ export default {
         videoList(this.form.courseId).then(response => {
           this.videoList = response.list;
         });
+        this.setting.forEach(item => {
+          if (item.contentType == 4 && item.courseId) {
+            // 初始化 videoOptions
+            this.videoOptions = [];
+            this.videoOptionsLoading = false;
 
+            // 获取课程对应的小节列表
+            videoList(item.courseId).then((videoResponse) => {
+              this.videoOptions = videoResponse.list;
+            });
+          }
+        });
 
         this.open = true;
         this.title = "修改完课模板";
-
+        this.formType = 1;
       });
     },
     /** 提交按钮 */
@@ -737,7 +1026,19 @@ export default {
           this.form.companyUserIds = this.companyUserIds.toString()
           this.form.parentId = this.parentId
 
-          this.form.setting = JSON.stringify(this.setting)
+
+          const processedSetting = this.setting.map(item => {
+            const newItem = {...item};
+            if (newItem.videoOptions) {
+              delete newItem.videoOptions;
+            }
+            if (newItem.videoLoading !== undefined) {
+              delete newItem.videoLoading;
+            }
+            return newItem;
+          });
+
+          this.form.setting = JSON.stringify(processedSetting);
           this.form.chatSetting = JSON.stringify(this.chatSetting)
 
           if (this.setting.length <= 0) {

+ 295 - 4
src/views/course/courseFinishTempParent/index.vue

@@ -178,7 +178,52 @@
                       </el-card>
                     </div>
                     <div v-if="item.contentType == 4">
+                      <el-card class="box-card">
+
+                        <el-form-item label="选择课程">
+                          <el-select
+                            v-model="item.courseId"
+                            placeholder="请选择课程"
+                            style="margin-right: 10px"
+                            size="mini"
+                            @change="handleRuleCourseChange(item)"
+                          >
+                            <el-option
+                              v-for="dict in courseList"
+                              :key="dict.dictValue"
+                              :label="dict.dictLabel"
+                              :value="parseInt(dict.dictValue)"
+                            />
+                          </el-select>
+                          <el-select
+                            v-model="item.videoId"
+                            placeholder="请选择小节"
+                            size="mini"
+                            style="margin-right: 10px"
+                            filterable
+                            remote
+                            :remote-method="(query) => remoteMethodRuleVideo(query, item)"
+                            :loading="videoOptionsLoading"
+                            @change="handleRuleVideoChange(item)"
+                          >
+                            <el-option
+                              v-for="dict in videoOptions || []"
+                              :key="dict.dictValue"
+                              :label="dict.dictLabel"
+                              :value="parseInt(dict.dictValue)"
+                            />
+                          </el-select>
+                        </el-form-item>
 
+                        <el-card class="box-card" style="margin-top: 10px">
+                          <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-card>
+                      </el-card>
                     </div>
                     <div v-if="item.contentType == 5 ">
 
@@ -224,7 +269,44 @@
                         @input="handleInputVideoText(item.value,item)"/>
                     </div>
                     <div v-if="item.contentType == 8">
+                      <el-button type="primary"
+                                 style="margin-bottom: 1%"
+                                 @click="hanldeSelectVideoNum(setting,index)">
+                        选择视频号
+                      </el-button>
+                      <el-card class="box-card" v-if="item.coverUrl">
+                        <el-form-item label="封面标题:" label-width="100px">
+                          <el-input v-model="item.nickname"
+                                    style="width: 90%;margin-bottom: 1%" disabled/>
+                        </el-form-item>
+                        <el-form-item label="头像:" label-width="100px">
+                          <el-image
+                            v-if="item.avatar != null"
+                            :src="item.avatar"
+                            :preview-src-list="[item.avatar]"
+                            :style="{ width: '50px', height: '50px' }"
+                          ></el-image>
+                        </el-form-item>
+                        <el-form-item label="封面:" label-width="100px">
+                          <el-image
+                            v-if="item.coverUrl != null"
+                            :src="item.coverUrl"
+                            :preview-src-list="[item.coverUrl]"
+                            :style="{ width: '200px', height: '200px' }"
+                          ></el-image>
 
+                        </el-form-item>
+                        <el-form-item label="简介:" label-width="100px">
+                          <el-input type="textarea" :rows="3"
+                                    v-model="item.desc"
+                                    style="width: 90%;margin-top: 1%;" disabled/>
+                        </el-form-item>
+                        <el-form-item label="视频地址:" label-width="100px"
+                                      style="margin-top: 1%">
+                          <el-input v-model="item.url"
+                                    style="width: 90%;" disabled/>
+                        </el-form-item>
+                      </el-card>
                     </div>
 
                   </el-form-item>
@@ -278,7 +360,52 @@
                       </el-card>
                     </div>
                     <div v-if="item.contentType == 4">
+                      <el-card class="box-card">
+
+                        <el-form-item label="选择课程">
+                          <el-select
+                            v-model="item.courseId"
+                            placeholder="请选择课程"
+                            style="margin-right: 10px"
+                            size="mini"
+                            @change="handleRuleCourseChange(item)"
+                          >
+                            <el-option
+                              v-for="dict in courseList"
+                              :key="dict.dictValue"
+                              :label="dict.dictLabel"
+                              :value="parseInt(dict.dictValue)"
+                            />
+                          </el-select>
+                          <el-select
+                            v-model="item.videoId"
+                            placeholder="请选择小节"
+                            size="mini"
+                            style="margin-right: 10px"
+                            filterable
+                            remote
+                            :remote-method="(query) => remoteMethodRuleVideo(query, item)"
+                            :loading="videoOptionsLoading"
+                            @change="handleRuleVideoChange(item)"
+                          >
+                            <el-option
+                              v-for="dict in videoOptions || []"
+                              :key="dict.dictValue"
+                              :label="dict.dictLabel"
+                              :value="parseInt(dict.dictValue)"
+                            />
+                          </el-select>
+                        </el-form-item>
 
+                        <el-card class="box-card" style="margin-top: 10px">
+                          <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-card>
+                      </el-card>
                     </div>
                     <div v-if="item.contentType == 5 ">
 
@@ -324,7 +451,44 @@
                         @input="handleInputVideoText(item.value,item)"/>
                     </div>
                     <div v-if="item.contentType == 8">
+                      <el-button type="primary"
+                                 style="margin-bottom: 1%"
+                                 @click="hanldeSelectVideoNum(setting,index)">
+                        选择视频号
+                      </el-button>
+                      <el-card class="box-card" v-if="item.coverUrl">
+                        <el-form-item label="封面标题:" label-width="100px">
+                          <el-input v-model="item.nickname"
+                                    style="width: 90%;margin-bottom: 1%" disabled/>
+                        </el-form-item>
+                        <el-form-item label="头像:" label-width="100px">
+                          <el-image
+                            v-if="item.avatar != null"
+                            :src="item.avatar"
+                            :preview-src-list="[item.avatar]"
+                            :style="{ width: '50px', height: '50px' }"
+                          ></el-image>
+                        </el-form-item>
+                        <el-form-item label="封面:" label-width="100px">
+                          <el-image
+                            v-if="item.coverUrl != null"
+                            :src="item.coverUrl"
+                            :preview-src-list="[item.coverUrl]"
+                            :style="{ width: '200px', height: '200px' }"
+                          ></el-image>
 
+                        </el-form-item>
+                        <el-form-item label="简介:" label-width="100px">
+                          <el-input type="textarea" :rows="3"
+                                    v-model="item.desc"
+                                    style="width: 90%;margin-top: 1%;" disabled/>
+                        </el-form-item>
+                        <el-form-item label="视频地址:" label-width="100px"
+                                      style="margin-top: 1%">
+                          <el-input v-model="item.url"
+                                    style="width: 90%;" disabled/>
+                        </el-form-item>
+                      </el-card>
                     </div>
 
                   </el-form-item>
@@ -367,21 +531,34 @@
         <el-button @click="cancel">取 消</el-button>
       </div>
     </el-dialog>
+    <el-dialog :title="videoNumOptions.title" :visible.sync="videoNumOptions.open" width="1500px" append-to-body>
+      <userVideo ref="QwUserVideo" @videoResult="qwUserVideoResult"></userVideo>
+    </el-dialog>
   </div>
 </template>
 
 <script>
 import { listCourseFinishTempParent, getCourseFinishTempParent, delCourseFinishTempParent, addCourseFinishTempParent, updateCourseFinishTempParent, exportCourseFinishTempParent } from "@/api/course/courseFinishTempParent";
-import {courseList} from '@/api/qw/sop'
+import {courseList, videoList} from '@/api/qw/sop'
 import ImageUpload from '@/views/qw/sop/ImageUpload.vue'
 import { getUserList } from '@/api/company/companyUser'
+import userVideo from "@/views/qw/userVideo/userVideo.vue";
 
 
 export default {
   name: "CourseFinishTempParent",
-  components: { ImageUpload },
+  components: { ImageUpload ,userVideo},
   data() {
     return {
+      videoOptionsLoading: false,
+      videoOptions: [],
+      videoLoading: false,
+      videoNumOptions: {
+        title: '选择视频号',
+        open: false,
+        content: null,
+        contentIndex: null,
+      },
       voiceLoading: false,
       uploadUrl: process.env.VUE_APP_BASE_API + "/common/uploadOSS2",
       uploadUrlByVoice: process.env.VUE_APP_BASE_API + "/common/uploadOSSByHOOKVoice",
@@ -424,7 +601,7 @@ export default {
         courseId: null,
       },
       // 表单参数
-      form: {},
+      form: {companyUserIds: [],},
       // 表单校验
       rules: {
         name:[
@@ -460,6 +637,83 @@ export default {
     this.getList();
   },
   methods: {
+    // 处理规则中课程变化
+    handleRuleCourseChange(item) {
+      // 为当前规则项单独加载视频列表
+      videoList(item.courseId).then((response) => {
+        // 只保存视频列表,不保存整个响应对象
+        this.videoOptions = response.list;
+
+        this.$set(item, 'videoId', null); // Reset video selection when course changes
+
+        // 自动设置封面为课程封面
+        const selectedCourse = this.courseList.find(
+          course => parseInt(course.dictValue) === item.courseId
+        );
+        if (selectedCourse) {
+          this.$set(item, 'miniprogramPicUrl', selectedCourse.dictImgUrl);
+        }
+      });
+    },
+
+
+    // 处理规则中视频变化
+    handleRuleVideoChange(item) {
+      if (!item.videoId) return;
+
+      // 自动设置标题为视频标题
+      const selectedVideo = (this.videoOptions || []).find(
+        video => parseInt(video.dictValue) === item.videoId
+      );
+      if (selectedVideo) {
+        this.$set(item, 'miniprogramTitle', selectedVideo.dictLabel);
+      }
+    },
+
+    // 远程搜索规则中的视频
+    remoteMethodRuleVideo(query, item) {
+      if (!item.courseId) {
+        this.$message.warning('请先选择课程');
+        this.videoOptions = [];
+        reject();
+        return;
+      }
+
+      this.videoOptionsLoading = true;
+      const data = query ? { title: query } : {};
+
+      videoList(item.courseId, data).then((response) => {
+        this.videoOptions =  response.list;
+        this.videoOptionsLoading =  false;
+        resolve(response);
+      }).catch((error) => {
+        this.videoOptionsLoading = false;
+        reject(error);
+      });
+    },
+    remoteMethodVideo(query) {
+      if (!this.form.courseId) {
+        this.$message.warning('请先选择课程');
+        this.videoList = []; // 清空小节列表
+        return;
+      }
+      if (query !== '') {
+        this.videoLoading = true;
+        // 这里调用接口搜索小节,假设 videoList 方法支持搜索参数
+        var data = {
+          title:query
+        }
+        videoList(this.form.courseId, data).then((response) => {
+          this.videoList = response.list;
+          this.videoLoading = false;
+        });
+      } else {
+        // 如果查询为空,则加载全部
+        videoList(this.form.courseId).then((response) => {
+          this.videoList = response.list;
+        });
+      }
+    },
     /** 查询完课模板列表 */
     getList() {
       this.loading = true;
@@ -515,6 +769,31 @@ export default {
       this.open = true;
       this.title = "添加完课模板";
     },
+    //选择视频号
+    hanldeSelectVideoNum(content, index) {
+      this.videoNumOptions.content = content;
+      this.videoNumOptions.contentIndex = index;
+      this.videoNumOptions.open = true;
+    },
+
+    qwUserVideoResult(val) {
+
+      // 根据选中的内容,将返回的数据更新到相应的表单项
+      const content = this.videoNumOptions.content;
+      const setList = content[this.videoNumOptions.contentIndex];
+      setList.nickname = val.nickname;
+      setList.avatar = val.avatar;
+      setList.coverUrl = val.coverUrl;
+      setList.thumbUrl = val.thumbUrl;
+      setList.desc = val.desc;
+      setList.url = val.url;
+      setList.extras = val.extras;
+      setList.videoId = val.id;
+      console.info(setList)
+
+      this.videoNumOptions.open = false;
+
+    },
     /** 修改按钮操作 */
     handleUpdate(row) {
       this.reset();
@@ -541,7 +820,19 @@ export default {
             }
             this.form.companyUserIds = this.companyUserIds.toString()
 
-            this.form.setting = JSON.stringify(this.setting)
+
+            const processedSetting = this.setting.map(item => {
+              const newItem = {...item};
+              if (newItem.videoOptions) {
+                delete newItem.videoOptions;
+              }
+              if (newItem.videoLoading !== undefined) {
+                delete newItem.videoLoading;
+              }
+              return newItem;
+            });
+
+            this.form.setting = JSON.stringify(processedSetting);
             this.form.chatSetting = JSON.stringify(this.chatSetting)
 
             if (this.setting.length <= 0) {

+ 194 - 27
src/views/course/courseWatchLog/deptWatchLog.vue

@@ -38,7 +38,7 @@
           @keyup.enter.native="handleQuery"
         />
       </el-form-item>
-      <el-form-item label="所属销售" prop="companyUserId">
+      <el-form-item v-if="companyName === undefined || companyName === 1" label="所属销售" prop="companyUserId">
         <el-select v-model="queryParams.companyUserId" clearable filterable remote
                    placeholder="请输入关键词" :remote-method="loadCompanyUserOptions"
                    v-select-load-more="loadMoreCompanyUserOptions"
@@ -51,6 +51,19 @@
           </el-option>
         </el-select>
       </el-form-item>
+      <el-form-item v-if="companyName==2" label="所属销售" prop="companyUserId">
+        <el-select v-model="queryParams.companyUserId" clearable filterable remote
+                   placeholder="请输入关键词"
+                   v-select-load-more="loadMoreCompanyUserOptions"
+                   :loading="companyUserOptionsLoading">
+          <el-option
+            v-for="item in companyUserOptionsByAll"
+            :key="item.dictValue"
+            :label="item.dictLabel"
+            :value="item.dictValue">
+          </el-option>
+        </el-select>
+      </el-form-item>
       <el-form-item label="课程" prop="courseId">
         <el-select filterable  v-model="queryParams.courseId" placeholder="请选择课程"  clearable size="small" @change="courseChange(queryParams.courseId)">
           <el-option
@@ -119,7 +132,7 @@
 <!--        />-->
 <!--      </el-form-item>-->
       <!-- 营期时间 -->
-      <el-form-item label="营期时间" prop="scheduleTime">
+      <!-- <el-form-item label="营期时间" prop="scheduleTime">
         <el-input
           v-model="scheduleTimeText"
           placeholder="请选择营期时间"
@@ -133,9 +146,21 @@
           @change="handleScheduleTimeChange"
           :key="scheduleCalendarKey"
         />
+      </el-form-item> -->
+       <el-form-item label="营期时间" prop="scheduleTime">
+        <el-date-picker
+          v-model="scheduleTimeText"
+          type="daterange"
+          range-separator="至"
+          start-placeholder="开始日期"
+          end-placeholder="结束日期"
+          value-format="yyyy-MM-dd"
+          style="width: 240px"
+           @change="handleScheduleTimeChange"
+        />
       </el-form-item>
       <!-- 创建时间 -->
-      <el-form-item label="创建时间" prop="createTime">
+      <!-- <el-form-item label="创建时间" prop="createTime">
         <el-input
           v-model="createTimeText"
           placeholder="请选择创建时间"
@@ -149,9 +174,21 @@
           @change="createChange"
           :key="createCalendarKey"
         />
+      </el-form-item> -->
+        <el-form-item label="创建时间" prop="createTime">
+        <el-date-picker
+          v-model="createTimeText"
+          type="daterange"
+          range-separator="至"
+          start-placeholder="开始日期"
+          end-placeholder="结束日期"
+          value-format="yyyy-MM-dd"
+          style="width: 240px"
+           @change="createChange"
+        />
       </el-form-item>
       <!-- 最新更新时间 -->
-      <el-form-item label="最新更新时间" prop="updateTime">
+      <!-- <el-form-item label="最新更新时间" prop="updateTime">
         <el-input
           v-model="updateTimeText"
           placeholder="请选择更新时间"
@@ -165,9 +202,21 @@
           @change="updateChange"
           :key="updateCalendarKey"
         />
+      </el-form-item> -->
+       <el-form-item label="最新更新时间" prop="updateTime">
+        <el-date-picker
+          v-model="updateTimeText"
+          type="daterange"
+          range-separator="至"
+          start-placeholder="开始日期"
+          end-placeholder="结束日期"
+          value-format="yyyy-MM-dd"
+          style="width: 240px"
+           @change="updateChange"
+        />
       </el-form-item>
       <!-- 进线时间 -->
-      <el-form-item label="进线时间" prop="qecCreateTime">
+      <!-- <el-form-item label="进线时间" prop="qecCreateTime">
         <el-input
           v-model="qecCreateTimeText"
           placeholder="请选择进线时间"
@@ -181,6 +230,35 @@
           @change="qecCreateTimeChange"
           :key="qecCalendarKey"
         />
+      </el-form-item> -->
+      <el-form-item label="进线时间" prop="qecCreateTime">
+        <el-date-picker
+          v-model="qecCreateTimeText"
+          type="daterange"
+          range-separator="至"
+          start-placeholder="开始日期"
+          end-placeholder="结束日期"
+          value-format="yyyy-MM-dd"
+          style="width: 240px"
+          @change="qecCreateTimeChange"
+        />
+      </el-form-item>
+
+
+      <el-form-item label="营期课程时间" prop="periodTime" v-if="queryParams.sendType==1">
+        <el-date-picker
+          v-model="periodTimeText"
+          type="datetimerange"
+          align="right"
+          unlink-panels
+          value-format="yyyy-MM-dd HH:mm:ss"
+          range-separator="至"
+          start-placeholder="开始日期"
+          end-placeholder="结束日期"
+          :picker-options="pickerOptions"
+          @change="qecPeriodTimeChange"
+          :default-time="['00:00:00', '23:59:59']">
+        </el-date-picker>
       </el-form-item>
 
       <el-form-item>
@@ -391,6 +469,7 @@ export default {
   name: "CourseWatchLog",
   data() {
     return {
+      companyName:process.env.VUE_APP_COURSE_COMPANY_NAME,
       sopSearchText: '', // SOP搜索框显示的文本
       selectedSopId: null, // 选中的SOP ID
       sendTypeOptions:[{
@@ -405,16 +484,19 @@ export default {
       createCalendarKey: 0,
       updateCalendarKey: 0,
       qecCalendarKey: 0,
+      periodTimeKey: 0,
 
       createTimeText: '',
       scheduleTimeText: '',  // 新增
       updateTimeText: '',    // 新增
       qecCreateTimeText: '', // 新增
+      periodTimeText: '', // 营期课程时间
 
       scheduleTime: [],  // 改为数组
       createTime: [],    // 改为数组
       updateTime: [],    // 改为数组
       qecCreateTime: [], // 改为数组
+      periodTime: [], // 改为数组
 
       // 控制日历显隐
       showScheduleCalendar: false,
@@ -470,9 +552,9 @@ export default {
 
       pickerOptions: {
         disabledDate(time) {
-          // 获取6天前的日期(加上今天就是7天)
+          // 获取13天前的日期(加上今天就是14天)
           const sixDaysAgo = new Date();
-          sixDaysAgo.setDate(sixDaysAgo.getDate() - 6);
+          sixDaysAgo.setDate(sixDaysAgo.getDate() - 13);
           sixDaysAgo.setHours(0, 0, 0, 0);
 
           // 获取明天的日期(不包括今天)
@@ -507,6 +589,8 @@ export default {
         upETime:null,
         qecSTime:null,
         qecETime:null,
+        periodSTime:null,
+        periodETime:null,
         scheduleStartTime: null,
         scheduleEndTime: null,
         sendType:process.env.VUE_APP_COURSE_DEFAULT,
@@ -522,10 +606,11 @@ export default {
         name: undefined,
         hasNextPage: false,
         pageNum: 1,
-        pageSize: 10
+        pageSize: 200
       },
       companyUserOptionsLoading: false,
       companyUserOptions: [],
+      companyUserOptionsByAll: [],
     };
   },
   created() {
@@ -536,6 +621,7 @@ export default {
     this.getDicts("sys_course_watch_log_type").then(response => {
       this.logTypeOptions = response.data;
     });
+    this.getCompanyUserListLikeName(true);
   },
   methods: {
     handleSendTypeChange() {
@@ -548,17 +634,20 @@ export default {
       this.createTime = [];
       this.updateTime = [];
       this.qecCreateTime = [];
+      this.periodTime = [];
 
       this.scheduleTimeText = '';
       this.createTimeText = '';
       this.updateTimeText = '';
       this.qecCreateTimeText = '';
+      this.periodTimeText = [];
 
       // 强制刷新日历组件
       this.scheduleCalendarKey++;
       this.createCalendarKey++;
       this.updateCalendarKey++;
       this.qecCalendarKey++;
+      this.periodTimeKey++;
     },
     formatDateRange(dates) {
       if (!dates || dates.length < 2) return '';
@@ -640,6 +729,8 @@ export default {
       this.queryParams.upETime = null;
       this.queryParams.qecSTime = null;
       this.queryParams.qecETime = null;
+      this.queryParams.periodSTime = null;
+      this.queryParams.periodDTime = null;
       this.queryParams.scheduleStartTime = null;
       this.queryParams.scheduleEndTime = null;
       this.queryParams.sopId = null; // 重置SOP ID
@@ -774,11 +865,11 @@ export default {
     // 营期时间
     handleScheduleTimeChange(scheduleTime) {
       if (scheduleTime && scheduleTime.length >= 2) {
-        this.scheduleTimeText = this.formatDateRange(scheduleTime);
-        this.queryParams.scheduleStartTime = scheduleTime.map(date => date.format('YYYY-MM-DD'))[0] || null;
-        this.queryParams.scheduleEndTime = scheduleTime.map(date => date.format('YYYY-MM-DD'))[1] || null;
+        // this.scheduleTimeText = this.formatDateRange(scheduleTime);
+        this.queryParams.scheduleStartTime = scheduleTime[0] || null;
+        this.queryParams.scheduleEndTime = scheduleTime[1] || null;
       } else {
-        this.scheduleTimeText = '';
+        this.scheduleTimeText = [];
         this.queryParams.scheduleStartTime = null;
         this.queryParams.scheduleEndTime = null;
       }
@@ -786,9 +877,9 @@ export default {
     // 创建时间
     createChange(createTime) {
       if (createTime && createTime.length >= 2) {
-        this.createTimeText = this.formatDateRange(createTime);
-        this.queryParams.sTime = createTime.map(date => date.format('YYYY-MM-DD'))[0] || null;
-        this.queryParams.eTime = createTime.map(date => date.format('YYYY-MM-DD'))[1] || null;
+        // this.createTimeText = this.formatDateRange(createTime);
+        this.queryParams.sTime = createTime[0] || null;
+        this.queryParams.eTime = createTime[1] || null;
       } else {
         this.createTimeText = '';
         this.queryParams.sTime = null;
@@ -800,8 +891,8 @@ export default {
     updateChange(updateTime) {
       if (updateTime && updateTime.length >= 2) {
         this.updateTimeText = this.formatDateRange(updateTime);
-        this.queryParams.upSTime = updateTime.map(date => date.format('YYYY-MM-DD'))[0] || null;
-        this.queryParams.upETime = updateTime.map(date => date.format('YYYY-MM-DD'))[1] || null;
+        this.queryParams.upSTime = updateTime[0] || null;
+        this.queryParams.upETime = updateTime[1] || null;
       } else {
         this.updateTimeText = '';
         this.queryParams.upSTime = null;
@@ -828,22 +919,87 @@ export default {
           this.$message.error('进线时间选择范围不能超过7天');
           // 清空选择
           this.qecCreateTime = [];
-          this.qecCreateTimeText = '';
+          this.qecCreateTimeText = [];
           this.queryParams.qecSTime = null;
           this.queryParams.qecETime = null;
           this.qecCalendarKey++;
           return;
         }
 
-        this.qecCreateTimeText = this.formatDateRange(qecCreateTime);
-        this.queryParams.qecSTime = qecCreateTime.map(date => date.format('YYYY-MM-DD'))[0] || null;
-        this.queryParams.qecETime = qecCreateTime.map(date => date.format('YYYY-MM-DD'))[1] || null;
+        // this.qecCreateTimeText = this.formatDateRange(qecCreateTime);
+        this.queryParams.qecSTime = qecCreateTime[0] || null;
+        this.queryParams.qecETime = qecCreateTime[1] || null;
       } else {
         this.qecCreateTimeText = '';
         this.queryParams.qecSTime = null;
         this.queryParams.qecETime = null;
       }
     },
+
+    //营期课程时间
+    qecPeriodTimeChange(periodTime){
+
+      if (periodTime && periodTime.length >= 2) {
+        // 检查选择的日期范围是否超过7天(包括起始和结束日期)
+        const startDate = new Date(periodTime[0]);
+        const endDate = new Date(periodTime[1]);
+
+        // 设置时间为当天开始,避免时间部分影响计算
+        startDate.setHours(0, 0, 0, 0);
+        endDate.setHours(0, 0, 0, 0);
+
+        const timeDiff = Math.abs(endDate - startDate);
+        const diffDays = Math.ceil(timeDiff / (1000 * 60 * 60 * 24));
+
+        // 如果超过6天的范围(总共7天,包括起始日)
+        if (diffDays > 13) {
+          this.$message.error('时间选择范围不能超过14天');
+          // 清空选择
+          this.periodTime = [];
+          this.periodTimeText = [];
+          this.queryParams.periodSTime = null;
+          this.queryParams.periodETime = null;
+          this.periodTimeKey++;
+          return;
+        }
+
+        this.queryParams.periodSTime = this.formatDate(periodTime[0]) || null;
+        this.queryParams.periodETime = this.formatDate(periodTime[1]) || null;
+
+      } else {
+
+        this.periodTimeText = '';
+        this.queryParams.periodSTime = null;
+        this.queryParams.periodETime = null;
+      }
+
+    },
+
+    formatDate(date) {
+      if (!date) return ''
+
+      // 确保 date 是 Date 对象
+      let dateObj = date
+      if (typeof date === 'string') {
+        dateObj = new Date(date)
+      }
+
+      // 如果转换失败,返回空字符串
+      if (!(dateObj instanceof Date) || isNaN(dateObj.getTime())) {
+        return ''
+      }
+
+      // 使用更安全的格式化方法
+      const year = dateObj.getFullYear()
+      const month = String(dateObj.getMonth() + 1).padStart(2, '0')
+      const day = String(dateObj.getDate()).padStart(2, '0')
+      const hours = String(dateObj.getHours()).padStart(2, '0')
+      const minutes = String(dateObj.getMinutes()).padStart(2, '0')
+      const seconds = String(dateObj.getSeconds()).padStart(2, '0')
+
+      return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`
+    },
+
     /**
      * 根据名称模糊查询用户列表
      * @param query 参数
@@ -862,12 +1018,23 @@ export default {
     /**
      * 获取员工列表
      */
-    getCompanyUserListLikeName() {
-      getCompanyUserListLikeName(this.companyUserOptionsParams).then(response => {
-        this.companyUserOptions = [...this.companyUserOptions, ...response.data.list]
-        this.companyUserOptionsParams.hasNextPage = response.data.hasNextPage
-        this.companyUserOptionsLoading = false;
-      });
+    getCompanyUserListLikeName(isAll) {
+
+      if (isAll){
+
+        getCompanyUserListLikeName(this.companyUserOptionsParams).then(response => {
+          this.companyUserOptionsByAll = [...this.companyUserOptions, ...response.data.list]
+          this.companyUserOptionsParams.hasNextPage = response.data.hasNextPage
+          this.companyUserOptionsLoading = false;
+        });
+      }else {
+        getCompanyUserListLikeName(this.companyUserOptionsParams).then(response => {
+          this.companyUserOptions = [...this.companyUserOptions, ...response.data.list]
+          this.companyUserOptionsParams.hasNextPage = response.data.hasNextPage
+          this.companyUserOptionsLoading = false;
+        });
+      }
+
     },
     /**
      * 加载更多员工选项

+ 265 - 34
src/views/course/courseWatchLog/index.vue

@@ -68,7 +68,7 @@
           />
         </el-select>
       </el-form-item>
-      <el-form-item label="所属销售" prop="companyUserId">
+      <el-form-item v-if="companyName === undefined || companyName === 1" label="所属销售" prop="companyUserId">
         <el-select v-model="queryParams.companyUserId" clearable filterable remote
                    placeholder="请输入关键词" :remote-method="loadCompanyUserOptions"
                    v-select-load-more="loadMoreCompanyUserOptions"
@@ -81,6 +81,32 @@
           </el-option>
         </el-select>
       </el-form-item>
+      <el-form-item v-if="companyName==2" label="所属销售" prop="companyUserId">
+        <el-select v-model="queryParams.companyUserId" clearable filterable remote
+                   placeholder="请输入关键词"
+                   v-select-load-more="loadMoreCompanyUserOptions"
+                   :loading="companyUserOptionsLoading">
+          <el-option
+            v-for="item in companyUserOptionsByAll"
+            :key="item.dictValue"
+            :label="item.dictLabel"
+            :value="item.dictValue">
+          </el-option>
+        </el-select>
+      </el-form-item>
+      <el-form-item label="所属企微" prop="qwUserName">
+        <el-select v-model="queryParams.qwUserName" clearable filterable remote
+                   placeholder="请输入关键词" :remote-method="loadQwUserOptions"
+                   v-select-load-more="loadMoreQwUserOptions"
+                   :loading="qwUserOptionsLoading">
+          <el-option
+            v-for="item in qwUserOptions"
+            :key="item.qwUserId"
+            :label="item.qwUserName"
+            :value="item.qwUserName">
+          </el-option>
+        </el-select>
+      </el-form-item>
     <!-- sop名称 -->
     <el-form-item label="SOP名称" prop="sopId" v-if="queryParams.sendType == 2">
       <el-autocomplete
@@ -103,7 +129,7 @@
     </el-form-item>
 
       <!-- 营期时间 -->
-      <el-form-item label="营期时间" prop="scheduleTime">
+      <!-- <el-form-item label="营期时间" prop="scheduleTime">
         <el-input
           v-model="scheduleTimeText"
           placeholder="请选择营期时间"
@@ -117,9 +143,21 @@
           @change="handleScheduleTimeChange"
           :key="scheduleCalendarKey"
         />
+      </el-form-item>-->
+      <el-form-item label="营期时间" prop="scheduleTime">
+        <el-date-picker
+          v-model="scheduleTimeText"
+          type="daterange"
+          range-separator="至"
+          start-placeholder="开始日期"
+          end-placeholder="结束日期"
+          value-format="yyyy-MM-dd"
+          style="width: 240px"
+           @change="handleScheduleTimeChange"
+        />
       </el-form-item>
       <!-- 创建时间 -->
-      <el-form-item label="创建时间" prop="createTime">
+      <!-- <el-form-item label="创建时间" prop="createTime">
         <el-input
           v-model="createTimeText"
           placeholder="请选择创建时间"
@@ -133,9 +171,22 @@
           @change="createChange"
           :key="createCalendarKey"
         />
+      </el-form-item> -->
+
+      <el-form-item label="创建时间" prop="createTime">
+        <el-date-picker
+          v-model="createTimeText"
+          type="daterange"
+          range-separator="至"
+          start-placeholder="开始日期"
+          end-placeholder="结束日期"
+          value-format="yyyy-MM-dd"
+          style="width: 240px"
+           @change="createChange"
+        />
       </el-form-item>
       <!-- 最新更新时间 -->
-      <el-form-item label="最新更新时间" prop="updateTime">
+      <!-- <el-form-item label="最新更新时间" prop="updateTime">
         <el-input
           v-model="updateTimeText"
           placeholder="请选择更新时间"
@@ -149,9 +200,21 @@
           @change="updateChange"
           :key="updateCalendarKey"
         />
+      </el-form-item> -->
+       <el-form-item label="最新更新时间" prop="updateTime">
+        <el-date-picker
+          v-model="updateTimeText"
+          type="daterange"
+          range-separator="至"
+          start-placeholder="开始日期"
+          end-placeholder="结束日期"
+          value-format="yyyy-MM-dd"
+          style="width: 240px"
+           @change="updateChange"
+        />
       </el-form-item>
       <!-- 进线时间 -->
-      <el-form-item label="进线时间" prop="qecCreateTime">
+      <!-- <el-form-item label="进线时间" prop="qecCreateTime">
         <el-input
           v-model="qecCreateTimeText"
           placeholder="请选择进线时间"
@@ -165,12 +228,42 @@
           @change="qecCreateTimeChange"
           :key="qecCalendarKey"
         />
+      </el-form-item> -->
+       <el-form-item label="进线时间" prop="qecCreateTime">
+        <el-date-picker
+          v-model="qecCreateTimeText"
+          type="daterange"
+          range-separator="至"
+          start-placeholder="开始日期"
+          end-placeholder="结束日期"
+          value-format="yyyy-MM-dd"
+          style="width: 240px"
+           @change="qecCreateTimeChange"
+        />
       </el-form-item>
-      <el-form-item label="是否为会员" prop="isVip">
+
+
+      <el-form-item label="营期课程时间" prop="periodTime" v-if="queryParams.sendType==1">
+        <el-date-picker
+          v-model="periodTimeText"
+          type="datetimerange"
+          align="right"
+          unlink-panels
+          value-format="yyyy-MM-dd HH:mm:ss"
+          range-separator="至"
+          start-placeholder="开始日期"
+          end-placeholder="结束日期"
+          :picker-options="pickerOptions"
+          @change="qecPeriodTimeChange"
+          :default-time="['00:00:00', '23:59:59']">
+        </el-date-picker>
+      </el-form-item>
+
+      <el-form-item label="是否注册" prop="isVip">
         <el-select
           filterable
           v-model="queryParams.isVip"
-          placeholder="请选择是否为会员"
+          placeholder="请选择是否注册"
           clearable size="small">
           <el-option
             v-for="dict in isVipList"
@@ -198,7 +291,7 @@
           @click="handleExport"
           v-hasPermi="['course:courseWatchLog:export']"
         >导出</el-button>
-        <el-col :span="1.5">
+        <el-col :span="1.5" v-if="queryParams.sendType == 2">
           <el-button
             type="primary"
             plain
@@ -207,7 +300,7 @@
             v-hasPermi="['qw:externalContact:addTag']"
           >批量添加标签</el-button>
         </el-col>
-        <el-col :span="1.5">
+        <el-col :span="1.5" v-if="queryParams.sendType == 2" >
           <el-button
             type="primary"
             plain
@@ -255,6 +348,7 @@
           </div>
         </template>
       </el-table-column>
+      <el-table-column label="营期名称" align="center" prop="periodIdName" v-if="this.queryParams.sendType==1" />
       <el-table-column label="课程名称" align="center" prop="courseName" />
       <el-table-column label="小节名称" align="center" prop="videoName" />
       <el-table-column label="记录类型" align="center" prop="logType">
@@ -502,27 +596,32 @@ import Vue from 'vue'
 import Calendar from 'vue-mobile-calendar'
 import {infoSop} from "@/api/qw/sop";
 import {getCompanyUserListLikeName} from "../../../api/company/companyUser";
+import {getQwList} from "@/api/qw/qwUser";
 Vue.use(Calendar)
 
 export default {
   name: "CourseWatchLog",
   data() {
     return {
+      companyName:process.env.VUE_APP_COURSE_COMPANY_NAME,
       // 日历 key 控制刷新
       scheduleCalendarKey: 0,
       createCalendarKey: 0,
       updateCalendarKey: 0,
       qecCalendarKey: 0,
+      periodTimeKey: 0,
 
       createTimeText: '',
       scheduleTimeText: '',  // 新增
       updateTimeText: '',    // 新增
       qecCreateTimeText: '', // 新增
+      periodTimeText: '', // 营期课程时间
 
       scheduleTime: [],  // 改为数组
       createTime: [],    // 改为数组
       updateTime: [],    // 改为数组
       qecCreateTime: [], // 改为数组
+      periodTime: [], // 改为数组
 
       // 控制日历显隐
       showScheduleCalendar: false,
@@ -537,9 +636,9 @@ export default {
       activeName:"2",
       pickerOptions: {
         disabledDate(time) {
-          // 获取6天前的日期(加上今天就是7天)
+          // 获取13天前的日期(加上今天就是14天)
           const sixDaysAgo = new Date();
-          sixDaysAgo.setDate(sixDaysAgo.getDate() - 6);
+          sixDaysAgo.setDate(sixDaysAgo.getDate() - 13);
           sixDaysAgo.setHours(0, 0, 0, 0);
 
           // 获取明天的日期(不包括今天)
@@ -647,6 +746,7 @@ export default {
         externalUserName:null,
         duration: null,
         qwUserId: null,
+        qwUserName: null,
         companyUserId: null,
         companyId: null,
         courseId: null,
@@ -656,6 +756,8 @@ export default {
         upETime:null,
         qecSTime:null,
         qecETime:null,
+        periodSTime:null,
+        periodETime:null,
         scheduleStartTime: null,
         scheduleEndTime: null,
         sendType:process.env.VUE_APP_COURSE_DEFAULT,
@@ -672,10 +774,21 @@ export default {
         name: undefined,
         hasNextPage: false,
         pageNum: 1,
-        pageSize: 10
+        pageSize: 200
       },
       companyUserOptions: [],
+      companyUserOptionsByAll: [],
       companyUserOptionsLoading: false,
+      // 企微信息
+      qwUserOptions: [],
+      // 员工选项列表
+      qwUserOptionsParams: {
+        name: undefined,
+        hasNextPage: false,
+        pageNum: 1,
+        pageSize: 10
+      },
+      qwUserOptionsLoading: false,
     };
   },
   created() {
@@ -689,6 +802,7 @@ export default {
     this.getDicts("sys_course_project").then(response => {
       this.projectOptions = response.data;
     });
+    this.getCompanyUserListLikeName(true);
   },
   methods: {
     /**
@@ -706,6 +820,21 @@ export default {
       this.companyUserOptionsLoading = true;
       this.getCompanyUserListLikeName()
     },
+    /**
+     * 根据条件查询企微列表
+     * @param query 参数
+     */
+    loadQwUserOptions(query) {
+      this.qwUserOptions = [];
+      if (query === '') {
+        return;
+      }
+      this.qwUserOptionsParams.pageNum = 1
+      // 将搜索关键词设置到queryParams中
+      this.queryParams.qwUserName = query
+      this.qwUserOptionsLoading = true;
+      this.getQwList()
+    },
     /**
      * 加载更多员工选项
      */
@@ -721,31 +850,66 @@ export default {
     /**
      * 获取员工列表
      */
-    getCompanyUserListLikeName() {
-      getCompanyUserListLikeName(this.companyUserOptionsParams).then(response => {
-        this.companyUserOptions = [...this.companyUserOptions, ...response.data.list]
-        this.companyUserOptionsParams.hasNextPage = response.data.hasNextPage
-        this.companyUserOptionsLoading = false;
+    getCompanyUserListLikeName(isAll) {
+
+      if (isAll){
+
+        getCompanyUserListLikeName(this.companyUserOptionsParams).then(response => {
+          this.companyUserOptionsByAll = [...this.companyUserOptions, ...response.data.list]
+          this.companyUserOptionsParams.hasNextPage = response.data.hasNextPage
+          this.companyUserOptionsLoading = false;
+        });
+      }else {
+        getCompanyUserListLikeName(this.companyUserOptionsParams).then(response => {
+          this.companyUserOptions = [...this.companyUserOptions, ...response.data.list]
+          this.companyUserOptionsParams.hasNextPage = response.data.hasNextPage
+          this.companyUserOptionsLoading = false;
+        });
+      }
+
+    },
+    getQwList() {
+      console.log("企微参数", this.queryParams);
+      getQwList(this.queryParams).then(response => {
+        this.qwUserOptions = [...this.qwUserOptions, ...response.rows]
+        // 根据实际返回的数据结构设置hasNextPage
+        this.qwUserOptionsParams.hasNextPage = response.rows && response.rows.length >= this.qwUserOptionsParams.pageSize
+        this.qwUserOptionsLoading = false;
       });
     },
 
+    /**
+     * 加载更多员工选项
+     */
+    loadMoreQwUserOptions() {
+      if (!this.qwUserOptionsParams.hasNextPage) {
+        return;
+      }
+
+      this.qwUserOptionsParams.pageNum += 1
+      this.getQwList()
+    },
+
     // 重置日历组件
     resetCalendars() {
       this.scheduleTime = [];
       this.createTime = [];
       this.updateTime = [];
       this.qecCreateTime = [];
+      this.periodTime = [];
 
-      this.scheduleTimeText = '';
-      this.createTimeText = '';
-      this.updateTimeText = '';
-      this.qecCreateTimeText = '';
+      this.scheduleTimeText = [];
+      this.createTimeText = [];
+      this.updateTimeText = [];
+      this.qecCreateTimeText = [];
+      this.periodTimeText = [];
 
       // 强制刷新日历组件
       this.scheduleCalendarKey++;
       this.createCalendarKey++;
       this.updateCalendarKey++;
       this.qecCalendarKey++;
+      this.periodTimeKey++;
     },
     formatDateRange(dates) {
       if (!dates || dates.length < 2) return '';
@@ -765,9 +929,9 @@ export default {
     // 营期时间
     handleScheduleTimeChange(scheduleTime) {
       if (scheduleTime && scheduleTime.length >= 2) {
-        this.scheduleTimeText = this.formatDateRange(scheduleTime);
-        this.queryParams.scheduleStartTime = scheduleTime.map(date => date.format('YYYY-MM-DD'))[0] || null;
-        this.queryParams.scheduleEndTime = scheduleTime.map(date => date.format('YYYY-MM-DD'))[1] || null;
+        // this.scheduleTimeText = this.formatDateRange(scheduleTime);
+        this.queryParams.scheduleStartTime = scheduleTime[0] || null;
+        this.queryParams.scheduleEndTime = scheduleTime[1] || null;
         console.log(this.queryParams.scheduleStartTime)
         console.log(this.queryParams.scheduleEndTime)
       } else {
@@ -779,9 +943,9 @@ export default {
     // 创建时间
     createChange(createTime) {
       if (createTime && createTime.length >= 2) {
-        this.createTimeText = this.formatDateRange(createTime);
-        this.queryParams.sTime = createTime.map(date => date.format('YYYY-MM-DD'))[0] || null;
-        this.queryParams.eTime = createTime.map(date => date.format('YYYY-MM-DD'))[1] || null;
+        // this.createTimeText = this.formatDateRange(createTime);
+        this.queryParams.sTime = createTime[0] || null;
+        this.queryParams.eTime = createTime[1] || null;
       } else {
         this.createTimeText = '';
         this.queryParams.sTime = null;
@@ -792,9 +956,9 @@ export default {
     // 更新时间
     updateChange(updateTime) {
       if (updateTime && updateTime.length >= 2) {
-        this.updateTimeText = this.formatDateRange(updateTime);
-        this.queryParams.upSTime = updateTime.map(date => date.format('YYYY-MM-DD'))[0] || null;
-        this.queryParams.upETime = updateTime.map(date => date.format('YYYY-MM-DD'))[1] || null;
+        // this.updateTimeText = this.formatDateRange(updateTime);
+        this.queryParams.upSTime = updateTime[0] || null;
+        this.queryParams.upETime = updateTime[1] || null;
       } else {
         this.updateTimeText = '';
         this.queryParams.upSTime = null;
@@ -821,16 +985,18 @@ export default {
           this.$message.error('进线时间选择范围不能超过7天');
           // 清空选择
           this.qecCreateTime = [];
-          this.qecCreateTimeText = '';
+          this.qecCreateTimeText = [];
           this.queryParams.qecSTime = null;
           this.queryParams.qecETime = null;
           this.qecCalendarKey++;
           return;
         }
 
-        this.qecCreateTimeText = this.formatDateRange(qecCreateTime);
-        this.queryParams.qecSTime = qecCreateTime.map(date => date.format('YYYY-MM-DD'))[0] || null;
-        this.queryParams.qecETime = qecCreateTime.map(date => date.format('YYYY-MM-DD'))[1] || null;
+        // this.qecCreateTimeText = this.formatDateRange(qecCreateTime);
+        this.queryParams.qecSTime = qecCreateTime[0] || null;
+        this.queryParams.qecETime = qecCreateTime[1] || null;
+        console.log(this.queryParams.qecSTime);
+        console.log(this.queryParams.qecETime);
       } else {
         this.qecCreateTimeText = '';
         this.queryParams.qecSTime = null;
@@ -838,6 +1004,69 @@ export default {
       }
     },
 
+    //营期课程时间
+    qecPeriodTimeChange(periodTime){
+
+      if (periodTime && periodTime.length >= 2) {
+        // 检查选择的日期范围是否超过7天(包括起始和结束日期)
+        const startDate = new Date(periodTime[0]);
+        const endDate = new Date(periodTime[1]);
+
+        // 设置时间为当天开始,避免时间部分影响计算
+        startDate.setHours(0, 0, 0, 0);
+        endDate.setHours(0, 0, 0, 0);
+
+        const timeDiff = Math.abs(endDate - startDate);
+        const diffDays = Math.ceil(timeDiff / (1000 * 60 * 60 * 24));
+
+        // 如果超过6天的范围(总共7天,包括起始日)
+        if (diffDays > 13) {
+          this.$message.error('时间选择范围不能超过14天');
+          // 清空选择
+          this.periodTime = [];
+          this.periodTimeText = [];
+          this.queryParams.periodSTime = null;
+          this.queryParams.periodETime = null;
+          this.periodTimeKey++;
+          return;
+        }
+
+        this.queryParams.periodSTime = this.formatDate(periodTime[0]) || null;
+        this.queryParams.periodETime = this.formatDate(periodTime[1]) || null;
+
+      } else {
+
+        this.periodTimeText = '';
+        this.queryParams.periodSTime = null;
+        this.queryParams.periodETime = null;
+      }
+
+    },
+
+    formatDate(date) {
+      if (!date) return ''
+
+      // 确保 date 是 Date 对象
+      let dateObj = date
+      if (typeof date === 'string') {
+        dateObj = new Date(date)
+      }
+
+      // 如果转换失败,返回空字符串
+      if (!(dateObj instanceof Date) || isNaN(dateObj.getTime())) {
+        return ''
+      }
+
+      // 使用更安全的格式化方法
+      const year = dateObj.getFullYear()
+      const month = String(dateObj.getMonth() + 1).padStart(2, '0')
+      const day = String(dateObj.getDate()).padStart(2, '0')
+      const hours = String(dateObj.getHours()).padStart(2, '0')
+      const minutes = String(dateObj.getMinutes()).padStart(2, '0')
+      const seconds = String(dateObj.getSeconds()).padStart(2, '0')
+
+      return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`
+    },
 
 
     handleClickX(tab,event){
@@ -911,6 +1140,8 @@ export default {
       this.queryParams.upETime = null;
       this.queryParams.qecSTime = null;
       this.queryParams.qecETime = null;
+      this.queryParams.periodSTime = null;
+      this.queryParams.periodDTime = null;
       this.queryParams.scheduleStartTime = null;
       this.queryParams.scheduleEndTime = null;
       this.queryParams.sopId = null; // 重置SOP ID

+ 3 - 3
src/views/course/courseWatchLog/myCourseWatchLog.vue

@@ -92,7 +92,7 @@
     </el-form>
 
     <el-row :gutter="10" class="mb8">
-      <el-col :span="1.5">
+      <el-col :span="1.5" >
         <el-button
           type="warning"
           plain
@@ -103,7 +103,7 @@
           v-hasPermi="['course:courseWatchLog:myExport']"
         >导出</el-button>
       </el-col>
-      <el-col :span="1.5">
+      <el-col :span="1.5" v-if="queryParams.sendType == 2">
         <el-button
           type="primary"
           plain
@@ -112,7 +112,7 @@
           v-hasPermi="['qw:externalContact:addTag']"
         >批量添加标签</el-button>
       </el-col>
-      <el-col :span="1.5">
+      <el-col :span="1.5" v-if="queryParams.sendType == 2">
         <el-button
           type="primary"
           plain

+ 23 - 3
src/views/course/courseWatchLog/qw/statistics.vue

@@ -39,6 +39,21 @@
       </el-form-item>
     </el-form>
 
+    <el-row :gutter="10" class="mb8">
+      <el-col :span="1.5">
+        <el-button
+          type="warning"
+          plain
+          icon="el-icon-download"
+          size="mini"
+          :loading="exportLoading"
+          @click="handleExport"
+          v-hasPermi="['qw:user:export']"
+        >导出</el-button>
+      </el-col>
+      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+
     <el-table border v-loading="loading" :data="courseWatchLogList" @selection-change="handleSelectionChange"  show-summary>
       <el-table-column type="selection" width="55" align="center" />
       <el-table-column label="企微员工名称" align="center" prop="qwUserName" />
@@ -65,7 +80,7 @@
 </template>
 
 <script>
-import { listCourseWatchLog, getCourseWatchLog, delCourseWatchLog, addCourseWatchLog, updateCourseWatchLog, exportCourseWatchLog,statisticsList } from "@/api/course/qw/courseWatchLog";
+import { listCourseWatchLog, getCourseWatchLog, delCourseWatchLog, addCourseWatchLog, updateCourseWatchLog, exportCourseWatchLog,statisticsList,statisticsExport } from "@/api/course/qw/courseWatchLog";
 import { courseList,videoList } from '@/api/course/courseRedPacketLog'
 import { getDateRange } from '@/utils/common'
 export default {
@@ -278,14 +293,19 @@ export default {
     },
     /** 导出按钮操作 */
     handleExport() {
+      // 检查是否选择了时间范围
+      if (!this.queryParams.sTime || !this.queryParams.eTime) {
+        this.$message.warning("请选择创建时间后才能导出");
+        return;
+      }
       const queryParams = this.queryParams;
-      this.$confirm('是否确认导出所有短链课程看课记录数据项?', "警告", {
+      this.$confirm('是否确认导出所有企微看课记录数据项?', "警告", {
           confirmButtonText: "确定",
           cancelButtonText: "取消",
           type: "warning"
         }).then(() => {
           this.exportLoading = true;
-          return exportCourseWatchLog(queryParams);
+          return statisticsExport(queryParams);
         }).then(response => {
           this.download(response.msg);
           this.exportLoading = false;

+ 232 - 42
src/views/course/courseWatchLog/watchLog.vue

@@ -111,7 +111,7 @@
         </el-autocomplete>
       </el-form-item>
       <!-- 营期时间 -->
-      <el-form-item label="营期时间" prop="scheduleTime">
+      <!-- <el-form-item label="营期时间" prop="scheduleTime">
         <el-input
           v-model="scheduleTimeText"
           placeholder="请选择营期时间"
@@ -125,9 +125,21 @@
           @change="handleScheduleTimeChange"
           :key="scheduleCalendarKey"
         />
+      </el-form-item> -->
+      <el-form-item label="营期时间" prop="scheduleTime">
+        <el-date-picker
+          v-model="scheduleTimeText"
+          type="daterange"
+          range-separator="至"
+          start-placeholder="开始日期"
+          end-placeholder="结束日期"
+          value-format="yyyy-MM-dd"
+          style="width: 240px"
+           @change="handleScheduleTimeChange"
+        />
       </el-form-item>
       <!-- 创建时间 -->
-      <el-form-item label="创建时间" prop="createTime">
+      <!-- <el-form-item label="创建时间" prop="createTime">
         <el-input
           v-model="createTimeText"
           placeholder="请选择创建时间"
@@ -141,9 +153,21 @@
           @change="createChange"
           :key="createCalendarKey"
         />
+      </el-form-item> -->
+        <el-form-item label="创建时间" prop="createTime">
+        <el-date-picker
+          v-model="createTimeText"
+          type="daterange"
+          range-separator="至"
+          start-placeholder="开始日期"
+          end-placeholder="结束日期"
+          value-format="yyyy-MM-dd"
+          style="width: 240px"
+           @change="createChange"
+        />
       </el-form-item>
       <!-- 最新更新时间 -->
-      <el-form-item label="最新更新时间" prop="updateTime">
+      <!-- <el-form-item label="最新更新时间" prop="updateTime">
         <el-input
           v-model="updateTimeText"
           placeholder="请选择更新时间"
@@ -157,9 +181,21 @@
           @change="updateChange"
           :key="updateCalendarKey"
         />
+      </el-form-item> -->
+        <el-form-item label="最新更新时间" prop="updateTime">
+        <el-date-picker
+          v-model="updateTimeText"
+          type="daterange"
+          range-separator="至"
+          start-placeholder="开始日期"
+          end-placeholder="结束日期"
+          value-format="yyyy-MM-dd"
+          style="width: 240px"
+           @change="updateChange"
+        />
       </el-form-item>
       <!-- 进线时间 -->
-      <el-form-item label="进线时间" prop="qecCreateTime">
+      <!-- <el-form-item label="进线时间" prop="qecCreateTime">
         <el-input
           v-model="qecCreateTimeText"
           placeholder="请选择进线时间"
@@ -173,12 +209,41 @@
           @change="qecCreateTimeChange"
           :key="qecCalendarKey"
         />
+      </el-form-item> -->
+       <el-form-item label="进线时间" prop="qecCreateTime">
+        <el-date-picker
+          v-model="qecCreateTimeText"
+          type="daterange"
+          range-separator="至"
+          start-placeholder="开始日期"
+          end-placeholder="结束日期"
+          value-format="yyyy-MM-dd"
+          style="width: 240px"
+          @change="qecCreateTimeChange"
+        />
       </el-form-item>
-      <el-form-item label="是否为会员" prop="isVip">
+
+      <el-form-item label="营期课程时间" prop="periodTime" v-if="queryParams.sendType==1">
+        <el-date-picker
+          v-model="periodTimeText"
+          type="datetimerange"
+          align="right"
+          unlink-panels
+          value-format="yyyy-MM-dd HH:mm:ss"
+          range-separator="至"
+          start-placeholder="开始日期"
+          end-placeholder="结束日期"
+          :picker-options="pickerOptions"
+          @change="qecPeriodTimeChange"
+          :default-time="['00:00:00', '23:59:59']">
+        </el-date-picker>
+      </el-form-item>
+
+      <el-form-item label="是否注册" prop="isVip">
         <el-select
           filterable
           v-model="queryParams.isVip"
-          placeholder="请选择是否为会员"
+          placeholder="请选择是否注册"
           clearable size="small">
           <el-option
             v-for="dict in isVipList"
@@ -207,7 +272,7 @@
           v-hasPermi="['course:courseWatchLog:myExport']"
         >导出
         </el-button>
-        <el-col :span="1.5">
+        <el-col :span="1.5" v-if="queryParams.sendType == 2">
           <el-button
             type="primary"
             plain
@@ -216,7 +281,7 @@
             v-hasPermi="['qw:externalContact:addTag']"
           >批量添加标签</el-button>
         </el-col>
-        <el-col :span="1.5">
+        <el-col :span="1.5" v-if="queryParams.sendType == 2">
           <el-button
             type="primary"
             plain
@@ -233,7 +298,13 @@
       <el-tab-pane label="全部" name="00"></el-tab-pane>
       <el-tab-pane v-for="(item,index) in logTypeOptions" :label="item.dictLabel" :name="item.dictValue"></el-tab-pane>
     </el-tabs>
-    <el-table border v-loading="loading" :data="courseWatchLogList" @selection-change="handleSelectionChange">
+<!--    <el-table border v-loading="loading" :data="courseWatchLogList" @selection-change="handleSelectionChange">-->
+    <el-table
+      border
+      v-loading="loading"
+      :data="courseWatchLogList"
+      @selection-change="handleSelectionChange"
+      :key="tableKey">
       <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" v-if="queryParams.sendType == 2"/>
@@ -241,17 +312,31 @@
       &lt;!&ndash;
       <el-table-column label="会员ID" align="center" prop="userId" v-if="queryParams.sendType == 1"/>
       &ndash;&gt;
-     <el-table-column label="客户头像" align="center" prop="externalUserAvatar" v-if="queryParams.sendType == 2">
-       <template slot-scope="scope">
-         <el-popover
-           placement="right"
-           title=""
-           trigger="hover">
-           <img slot="reference" :src="scope.row.externalUserAvatar" style="width: 50px;height: 50px">
-           <img :src="scope.row.externalUserAvatar" style="max-width: 200px;max-height: 200px">
-         </el-popover>
-       </template>
-     </el-table-column>
+<!--     <el-table-column label="客户头像" align="center" prop="externalUserAvatar" v-if="queryParams.sendType == 2">-->
+<!--       <template slot-scope="scope">-->
+<!--         <el-popover-->
+<!--           placement="right"-->
+<!--           title=""-->
+<!--           trigger="hover">-->
+<!--           <img slot="reference" :src="scope.row.externalUserAvatar" style="width: 50px;height: 50px">-->
+<!--           <img :src="scope.row.externalUserAvatar" style="max-width: 200px;max-height: 200px">-->
+<!--         </el-popover>-->
+<!--       </template>-->
+<!--     </el-table-column>-->
+      <el-table-column label="头像" align="center">
+        <template slot-scope="scope">
+          <img
+            v-if="queryParams.sendType == 1"
+            :src="scope.row.fsAvatar"
+            style="width:50px;height:50px"
+          />
+          <img
+            v-else-if="queryParams.sendType == 2"
+            :src="scope.row.externalUserAvatar"
+            style="width:50px;height:50px"
+          />
+        </template>
+      </el-table-column>
       <el-table-column label="用户昵称" align="center" v-if="queryParams.sendType == 1">
         <template slot-scope="scope">
           {{ queryParams.sendType=='1' ? scope.row.fsNickName : scope.row.externalUserName }}
@@ -274,7 +359,13 @@
 <!--      <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="qwUserName" v-if="queryParams.sendType==2" />
+      <!-- 所属企微列 -->
+      <el-table-column
+        label="所属企微"
+        align="center"
+        prop="qwUserName"
+        v-if="queryParams.sendType == 2"
+      />
       <!--      <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" />
@@ -515,21 +606,25 @@ export default {
   name: "CourseWatchLog",
   data() {
     return {
+      tableKey: 0,
       // 日历 key 控制刷新
       scheduleCalendarKey: 0,
       createCalendarKey: 0,
       updateCalendarKey: 0,
       qecCalendarKey: 0,
+      periodTimeKey: 0,
 
       createTimeText: '',
       scheduleTimeText: '',  // 新增
       updateTimeText: '',    // 新增
       qecCreateTimeText: '', // 新增
+      periodTimeText: '', // 营期课程时间
 
       scheduleTime: [],  // 改为数组
       createTime: [],    // 改为数组
       updateTime: [],    // 改为数组
       qecCreateTime: [], // 改为数组
+      periodTime: [], // 改为数组
 
       // 控制日历显隐
       showScheduleCalendar: false,
@@ -544,9 +639,9 @@ export default {
       activeName:"2",
       pickerOptions: {
         disabledDate(time) {
-          // 获取6天前的日期(加上今天就是7天)
+          // 获取13天前的日期(加上今天就是14天)
           const sixDaysAgo = new Date();
-          sixDaysAgo.setDate(sixDaysAgo.getDate() - 6);
+          sixDaysAgo.setDate(sixDaysAgo.getDate() - 13);
           sixDaysAgo.setHours(0, 0, 0, 0);
 
           // 获取明天的日期(不包括今天)
@@ -590,10 +685,10 @@ export default {
       },
       projectOptions:[],
       sendTypeOptions:[{
-        dictLabel:"会员",dictValue:'1'
+        dictLabel:'会员',dictValue:'1'
       },
         {
-          dictLabel:"企微",dictValue:'2'
+          dictLabel:'企微',dictValue:'2'
         }
       ],
 
@@ -665,6 +760,8 @@ export default {
         upETime:null,
         qecSTime:null,
         qecETime:null,
+        periodSTime:null,
+        periodETime:null,
         scheduleStartTime: null,
         scheduleEndTime: null,
         sendType:process.env.VUE_APP_COURSE_DEFAULT,
@@ -699,7 +796,28 @@ export default {
   methods: {
 
     handleSendTypeChange() {
-      this.handleQuery(); // 重新查询列表
+      // 重置相关参数
+      this.queryParams.qwUserId = null;
+      this.queryParams.qwExternalContactId = null;
+      this.queryParams.userId = null;
+      this.queryParams.nickName = null;
+      this.queryParams.externalUserName = null;
+      this.queryParams.corpId = null;
+      this.queryParams.project = null;
+      this.queryParams.courseId = null;
+      this.queryParams.videoId = null;
+
+      // 重置选择
+      this.ids = [];
+      this.courseWatchLogList = []; // 清空表格数据
+
+      // 重置分页
+      this.queryParams.pageNum = 1;
+
+      // 强制重新渲染表格
+      this.tableKey += 1;
+
+      this.getList();
     },
 
     // 重置日历组件
@@ -708,17 +826,20 @@ export default {
       this.createTime = [];
       this.updateTime = [];
       this.qecCreateTime = [];
+      this.periodTime = [];
 
       this.scheduleTimeText = '';
       this.createTimeText = '';
       this.updateTimeText = '';
       this.qecCreateTimeText = '';
+      this.periodTimeText = [];
 
       // 强制刷新日历组件
       this.scheduleCalendarKey++;
       this.createCalendarKey++;
       this.updateCalendarKey++;
       this.qecCalendarKey++;
+      this.periodTimeKey++;
     },
     formatDateRange(dates) {
       if (!dates || dates.length < 2) return '';
@@ -757,13 +878,13 @@ export default {
     // 营期时间
     handleScheduleTimeChange(scheduleTime) {
       if (scheduleTime && scheduleTime.length >= 2) {
-        this.scheduleTimeText = this.formatDateRange(scheduleTime);
-        this.queryParams.scheduleStartTime = scheduleTime.map(date => date.format('YYYY-MM-DD'))[0] || null;
-        this.queryParams.scheduleEndTime = scheduleTime.map(date => date.format('YYYY-MM-DD'))[1] || null;
+        // this.scheduleTimeText = this.formatDateRange(scheduleTime);
+        this.queryParams.scheduleStartTime = scheduleTime[0] || null;
+        this.queryParams.scheduleEndTime = scheduleTime[1] || null;
         console.log(this.queryParams.scheduleStartTime)
         console.log(this.queryParams.scheduleEndTime)
       } else {
-        this.scheduleTimeText = '';
+        this.scheduleTimeText = [];
         this.queryParams.scheduleStartTime = null;
         this.queryParams.scheduleEndTime = null;
       }
@@ -771,11 +892,11 @@ export default {
     // 创建时间
     createChange(createTime) {
       if (createTime && createTime.length >= 2) {
-        this.createTimeText = this.formatDateRange(createTime);
-        this.queryParams.sTime = createTime.map(date => date.format('YYYY-MM-DD'))[0] || null;
-        this.queryParams.eTime = createTime.map(date => date.format('YYYY-MM-DD'))[1] || null;
+        // this.createTimeText = this.formatDateRange(createTime);
+        this.queryParams.sTime = createTime[0] || null;
+        this.queryParams.eTime = createTime[1] || null;
       } else {
-        this.createTimeText = '';
+        this.createTimeText = [];
         this.queryParams.sTime = null;
         this.queryParams.eTime = null;
       }
@@ -784,11 +905,11 @@ export default {
     // 更新时间
     updateChange(updateTime) {
       if (updateTime && updateTime.length >= 2) {
-        this.updateTimeText = this.formatDateRange(updateTime);
-        this.queryParams.upSTime = updateTime.map(date => date.format('YYYY-MM-DD'))[0] || null;
-        this.queryParams.upETime = updateTime.map(date => date.format('YYYY-MM-DD'))[1] || null;
+        // this.updateTimeText = this.formatDateRange(updateTime);
+        this.queryParams.upSTime = updateTime[0] || null;
+        this.queryParams.upETime = updateTime[1] || null;
       } else {
-        this.updateTimeText = '';
+        this.updateTimeText = [];
         this.queryParams.upSTime = null;
         this.queryParams.upETime = null;
       }
@@ -813,7 +934,7 @@ export default {
           this.$message.error('进线时间选择范围不能超过7天');
           // 清空选择
           this.qecCreateTime = [];
-          this.qecCreateTimeText = '';
+          this.qecCreateTimeText = [];
           this.queryParams.qecSTime = null;
           this.queryParams.qecETime = null;
           this.qecCalendarKey++;
@@ -821,14 +942,79 @@ export default {
         }
 
         this.qecCreateTimeText = this.formatDateRange(qecCreateTime);
-        this.queryParams.qecSTime = qecCreateTime.map(date => date.format('YYYY-MM-DD'))[0] || null;
-        this.queryParams.qecETime = qecCreateTime.map(date => date.format('YYYY-MM-DD'))[1] || null;
+        this.queryParams.qecSTime = qecCreateTime[0] || null;
+        this.queryParams.qecETime = qecCreateTime[1] || null;
       } else {
-        this.qecCreateTimeText = '';
+        this.qecCreateTimeText = [];
         this.queryParams.qecSTime = null;
         this.queryParams.qecETime = null;
       }
     },
+
+    //营期课程时间
+    qecPeriodTimeChange(periodTime){
+
+      if (periodTime && periodTime.length >= 2) {
+        // 检查选择的日期范围是否超过7天(包括起始和结束日期)
+        const startDate = new Date(periodTime[0]);
+        const endDate = new Date(periodTime[1]);
+
+        // 设置时间为当天开始,避免时间部分影响计算
+        startDate.setHours(0, 0, 0, 0);
+        endDate.setHours(0, 0, 0, 0);
+
+        const timeDiff = Math.abs(endDate - startDate);
+        const diffDays = Math.ceil(timeDiff / (1000 * 60 * 60 * 24));
+
+        // 如果超过6天的范围(总共7天,包括起始日)
+        if (diffDays > 13) {
+          this.$message.error('时间选择范围不能超过14天');
+          // 清空选择
+          this.periodTime = [];
+          this.periodTimeText = [];
+          this.queryParams.periodSTime = null;
+          this.queryParams.periodETime = null;
+          this.periodTimeKey++;
+          return;
+        }
+
+        this.queryParams.periodSTime = this.formatDate(periodTime[0]) || null;
+        this.queryParams.periodETime = this.formatDate(periodTime[1]) || null;
+
+      } else {
+
+        this.periodTimeText = '';
+        this.queryParams.periodSTime = null;
+        this.queryParams.periodETime = null;
+      }
+
+    },
+
+    formatDate(date) {
+      if (!date) return ''
+
+      // 确保 date 是 Date 对象
+      let dateObj = date
+      if (typeof date === 'string') {
+        dateObj = new Date(date)
+      }
+
+      // 如果转换失败,返回空字符串
+      if (!(dateObj instanceof Date) || isNaN(dateObj.getTime())) {
+        return ''
+      }
+
+      // 使用更安全的格式化方法
+      const year = dateObj.getFullYear()
+      const month = String(dateObj.getMonth() + 1).padStart(2, '0')
+      const day = String(dateObj.getDate()).padStart(2, '0')
+      const hours = String(dateObj.getHours()).padStart(2, '0')
+      const minutes = String(dateObj.getMinutes()).padStart(2, '0')
+      const seconds = String(dateObj.getSeconds()).padStart(2, '0')
+
+      return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`
+    },
+
     /** 查询短链课程看课记录列表 */
     getList() {
       this.loading = true;
@@ -891,9 +1077,13 @@ export default {
       this.queryParams.upETime = null;
       this.queryParams.qecSTime = null;
       this.queryParams.qecETime = null;
+      this.queryParams.periodSTime = null;
+      this.queryParams.periodDTime = null;
       this.queryParams.scheduleStartTime = null;
       this.queryParams.scheduleEndTime = null;
       this.queryParams.sopId = null; // 重置SOP ID
+      this.queryParams.isVip = null; // 重置 isVip 状态
+      this.queryParams.qwUserId = null; // 重置 qwUserId
 
       // 重置SOP搜索
       this.handleSopClear();

+ 94 - 27
src/views/hisStore/components/productAfterSalesOrder.vue

@@ -16,7 +16,11 @@
             <el-tag prop="status" v-for="(item, index) in salesStatusOptions"    v-if="afterSales.salesStatus==item.dictValue">{{item.dictLabel}}</el-tag>
           </span>
           <div class="operate-button-container"  >
-            <el-button size="mini" v-hasPermi="['store:storeAfterSales:edit']" v-show="afterSales.salesStatus==0&&afterSales.status===1"  @click="addDelivery">编辑物流</el-button>
+            <el-button size="mini"  v-hasPermi="['store:storeAfterSales:edit']" v-show="afterSales.salesStatus==0&&afterSales.status===1"  @click="addDelivery">编辑物流</el-button>
+            <el-button size="mini"  v-hasPermi="['store:storeAfterSales:audit1']" v-show="afterSales.salesStatus==0&&afterSales.status===0" @click="handleAudit1">平台审核</el-button>
+            <el-button size="mini"  v-hasPermi="['store:storeAfterSales:audit2']" v-show="afterSales.salesStatus==0&&afterSales.status===2" @click="handleAudit2">仓库审核</el-button>
+            <el-button size="mini"  v-hasPermi="['store:storeAfterSales:refund']" @click="handleRefund"  v-show="afterSales.salesStatus==0&&afterSales.status===3">财务审核</el-button>
+            <el-button size="mini"  v-hasPermi="['store:storeAfterSales:cancel']" @click="cancel"  v-show="afterSales.salesStatus==0">撤销</el-button>
             <el-button size="mini"  @click="showOrder">查看订单</el-button>
          </div>
         </div>
@@ -204,7 +208,7 @@
 </template>
 
 <script>
-import {getStoreAfterSales,cancel,refund,audit,updateStoreAfterSales } from "@/api/hisStore/storeAfterSales";
+import {getStoreAfterSales,cancel,refund,audit1,audit2,updateStoreAfterSales} from "@/api/hisStore/storeAfterSales";
 
 import productOrder from "./productOrder";
 export default {
@@ -312,53 +316,116 @@ export default {
         this.$refs.productOrder.getOrder(orderId);
       }, 500);
     },
-    handleAudit(){
-        this.audit.open=true;
-        this.form.serviceType=this.afterSales.serviceType;
-        this.form.salesId=this.afterSales.id;
-        this.form.refundAmount=this.afterSales.refundAmount;
-    },
-    submitAuditForm() {
-      this.$refs["form"].validate(valid => {
-        if (valid) {
-           audit(this.form).then(response => {
-              if (response.code === 200) {
-                this.audit.open = false;
-                this.getStoreAfterSales(this.afterSales.id);
-                this.msgSuccess("操作成功");
-              }
-            });
-        }
-      });
-    },
-    cancel(){
+    handleAudit1(){
       var id=this.afterSales.id;
-      this.$confirm('是否确认取消订单?', "警告", {
+      this.$confirm('确定审请通过?', "警告", {
           confirmButtonText: "确定",
           cancelButtonText: "取消",
           type: "warning"
         }).then(function() {
           var data={salesId:id}
-          return cancel(data);
+          return audit1(data);
         }).then(() => {
           this.getStoreAfterSales(id);
           this.msgSuccess("操作成功");
         }).catch(function() {});
+
     },
-    refund(){
+    handleAudit2(){
       var id=this.afterSales.id;
-      this.$confirm('是否确认收货,确认后将自动退款给客户', "警告", {
+      this.$confirm('确定审请通过?', "警告", {
           confirmButtonText: "确定",
           cancelButtonText: "取消",
           type: "warning"
         }).then(function() {
           var data={salesId:id}
-          return refund(data);
+          return audit2(data);
         }).then(() => {
           this.getStoreAfterSales(id);
           this.msgSuccess("操作成功");
         }).catch(function() {});
+
+    },
+    handleRefund(){
+        this.audit.open=true;
+        this.form.salesId=this.afterSales.id;
+        this.form.refundAmount=this.afterSales.refundAmount;
+    },
+    submitAuditForm() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          refund(this.form).then(response => {
+              if (response.code === 200) {
+                this.audit.open = false;
+                this.getStoreAfterSales(this.afterSales.id);
+                this.msgSuccess("操作成功");
+              }
+            });
+        }
+      });
+    },
+    cancel(){
+      var id=this.afterSales.id;
+      this.$prompt('是否确定取消订单?', '提示', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+      }).then(({ value }) => {
+        var data={salesId:id,remark:value};
+        return cancel(data);
+      }).then(() => {
+        this.getStoreAfterSales(id);
+        this.msgSuccess("操作成功");
+      }).catch(() => {
+
+      });
     },
+    // handleAudit(){
+    //     this.audit.open=true;
+    //     this.form.serviceType=this.afterSales.serviceType;
+    //     this.form.salesId=this.afterSales.id;
+    //     this.form.refundAmount=this.afterSales.refundAmount;
+    // },
+    // submitAuditForm() {
+    //   this.$refs["form"].validate(valid => {
+    //     if (valid) {
+    //        audit(this.form).then(response => {
+    //           if (response.code === 200) {
+    //             this.audit.open = false;
+    //             this.getStoreAfterSales(this.afterSales.id);
+    //             this.msgSuccess("操作成功");
+    //           }
+    //         });
+    //     }
+    //   });
+    // },
+    // cancel(){
+    //   var id=this.afterSales.id;
+    //   this.$confirm('是否确认取消订单?', "警告", {
+    //       confirmButtonText: "确定",
+    //       cancelButtonText: "取消",
+    //       type: "warning"
+    //     }).then(function() {
+    //       var data={salesId:id}
+    //       return cancel(data);
+    //     }).then(() => {
+    //       this.getStoreAfterSales(id);
+    //       this.msgSuccess("操作成功");
+    //     }).catch(function() {});
+    // },
+    // refund(){
+    //   var id=this.afterSales.id;
+    //   this.$confirm('是否确认收货,确认后将自动退款给客户', "警告", {
+    //       confirmButtonText: "确定",
+    //       cancelButtonText: "取消",
+    //       type: "warning"
+    //     }).then(function() {
+    //       var data={salesId:id}
+    //       return refund(data);
+    //     }).then(() => {
+    //       this.getStoreAfterSales(id);
+    //       this.msgSuccess("操作成功");
+    //     }).catch(function() {});
+    // },
     getStoreAfterSales(id){
         getStoreAfterSales(id).then(response => {
             this.afterSales = response.afterSales;

+ 156 - 28
src/views/hisStore/components/productOrder.vue

@@ -356,10 +356,10 @@
     </el-dialog>
     <el-dialog :title="editAddress.title" :visible.sync="editAddress.open" width="600px" append-to-body>
       <el-form ref="editAddressForm" :model="editAddressForm" :rules="editAddressRules" label-width="100px">
-        <el-form-item label="收件人" prop="realName">
+        <el-form-item label="收件人" prop="realName" required>
           <el-input v-model="editAddressForm.realName" placeholder="请输入收件人" />
         </el-form-item>
-          <el-form-item label="联系电话" prop="source">
+          <el-form-item label="联系电话" prop="userPhone" required>
           <el-input v-model="editAddressForm.userPhone" placeholder="请输入联系电话" />
         </el-form-item>
         <el-form-item label="收货地址" prop="district">
@@ -396,7 +396,7 @@
           </el-col>
         </el-row>
         </el-form-item>
-        <el-form-item label="详细地址" prop="detail">
+        <el-form-item label="详细地址" prop="detail" required>
           <el-input v-model="editAddressForm.detail" placeholder="请输入收货人详细地址" />
         </el-form-item>
       </el-form>
@@ -494,7 +494,20 @@ import { getTcmScheduleList } from "@/api/company/tcmScheduleReport";
 import {getCustomerListBySearch } from "@/api/crm/customer";
 import ImageUpload from '@/components/ImageUpload'
 import Material from '@/components/Material'
-import {bindCustomer,getExpress, listStoreOrder, getStoreOrder, delStoreOrder, addStoreOrder, updateStoreOrder, exportStoreOrder,uploadCredentials, getStoreOrderAddress,getUserPhone} from "@/api/hisStore/storeOrder";
+import {
+  bindCustomer,
+  getExpress,
+  listStoreOrder,
+  getStoreOrder,
+  delStoreOrder,
+  addStoreOrder,
+  updateStoreOrder,
+  exportStoreOrder,
+  uploadCredentials,
+  getStoreOrderAddress,
+  getUserPhone,
+  updateAddressErpFsStoreOrder
+} from "@/api/hisStore/storeOrder";
 import {getCitys} from "@/api/hisStore/city";
 import customerDetails from '../../crm/components/customerDetails.vue';
 import addSms from '../../crm/components/addSms.vue';
@@ -757,42 +770,157 @@ export default {
           this.province=res.data.filter(item => item.level===0 )
         })
     },
-    handleEditAddress() {
-        this.getCityList();
-        this.editAddressForm.id=this.order.id;
-        this.editAddressForm.realName=this.order.realName;
-        this.editAddressForm.userPhone=this.order.userPhone;
-        var address=this.order.userAddress.split(' ')
-        var province=this.citys.find((item)=>{
-          return item.name==address[0]&&item.level==0;
-        })
-        if(province!=null){
-          this.editAddressForm.provinceId=province.cityId;
-          this.city=this.citys.filter(item => item.parentId===province.cityId&&item.level==1 )
-        }
-        var city=this.citys.find((item)=>{
-          return item.name==address[1]&&item.level==1;
-        })
+    flattenCityData(data, level = 0) {
+      let result = [];
+      data.forEach(item => {
+        // 转换字段名
+        const cityItem = {
+          cityId: item.value,
+          name: item.label,
+          parentId: item.pid,
+          level: level
+        };
+        result.push(cityItem);
 
-        if(city!=null){
-          this.editAddressForm.cityId=city.cityId;
-          this.district=this.citys.filter(item => item.parentId===city.cityId&&item.level==2 )
+        // 递归处理子节点
+        if (item.children && item.children.length > 0) {
+          result = result.concat(this.flattenCityData(item.children, level + 1));
         }
-        var district=this.citys.find((item)=>{
-          return item.name==address[2]&&item.level==2;
+      });
+      return result;
+    },
+    handleEditAddress() {
+      let loading = this.$loading({
+        lock: true,
+        text: "请求中...",
+        background: "rgba(0, 0, 0, 0.7)",
+      });
+      const orderId = this.order.id;
+
+      getStoreOrderAddress(orderId).then(addressResponse => {
+        // 更新解密后的地址
+        this.order.userAddress = addressResponse.address;
+
+      }).then(res=>{
+        const id = this.order.id;
+        return getUserPhone(id).then(response =>{
+          this.order.userPhone = response.userPhone;
         })
-        if(district!=null){
-          this.editAddressForm.districtId=district.cityId;
+      }).then(res=>{
+        return getCitys();
+      }).then(res => {
+        this.citys = this.flattenCityData(res.data);
+        this.province = this.citys.filter(item => item.level === 0);
+
+        this.editAddressForm = {
+          id: this.order.id,
+          realName: this.order.realName,
+          userPhone: this.order.userPhone,
+          provinceId: null,
+          cityId: null,
+          districtId: null,
+          province: '',
+          city: '',
+          district: '',
+          detail: ''
+        };
+
+        // 解析地址
+        if (this.order.userAddress) {
+          var addressParts = this.order.userAddress.split(' ');
+
+          // 查找省份
+          if (addressParts.length > 0) {
+            var province = this.citys.find((item) => {
+              return item.name === addressParts[0] && item.level === 0;
+            });
+            if (province != null) {
+              this.editAddressForm.provinceId = province.cityId;
+              this.editAddressForm.province = province.name;
+
+              // 检查是否为直辖市(北京、上海、天津、重庆)
+              const isDirectMunicipality = ['北京市', '上海市', '天津市', '重庆市'].includes(province.name);
+
+              if (isDirectMunicipality) {
+                // 直辖市处理:先找到市级节点(市辖区)
+                if (addressParts.length > 1) {
+                  // 查找市级节点(第2部分,如"市辖区")
+                  var cityLevel = this.citys.find((item) => {
+                    return item.name === addressParts[1] && item.level === 1 && item.parentId === province.cityId;
+                  });
+
+                  if (cityLevel != null) {
+                    this.editAddressForm.cityId = cityLevel.cityId;
+                    this.editAddressForm.city = cityLevel.name;
+                    this.city = this.citys.filter(item => item.parentId === province.cityId && item.level === 1);
+
+                    // 使用市级节点的cityId作为parentId查找区县
+                    if (addressParts.length > 2) {
+                      var district = this.citys.find((item) => {
+                        return item.name === addressParts[2] && item.level === 2 && item.parentId === cityLevel.cityId;
+                      });
+
+                      if (district != null) {
+                        this.editAddressForm.districtId = district.cityId;
+                        this.editAddressForm.district = district.name;
+                        this.district = this.citys.filter(item => item.parentId === cityLevel.cityId && item.level === 2);
+                      }
+                    }
+
+                    // 提取详细地址(第4部分及之后)
+                    if (addressParts.length > 3) {
+                      this.editAddressForm.detail = addressParts.slice(3).join(' ');
+                    }
+                  }
+                }
+              } else {
+                // 普通省份处理:正常匹配市、区
+                this.city = this.citys.filter(item => item.parentId === province.cityId && item.level === 1);
+
+                // 查找城市
+                if (addressParts.length > 1) {
+                  var city = this.citys.find((item) => {
+                    return item.name === addressParts[1] && item.level === 1;
+                  });
+                  if (city != null) {
+                    this.editAddressForm.cityId = city.cityId;
+                    this.editAddressForm.city = city.name;
+                    this.district = this.citys.filter(item => item.parentId === city.cityId && item.level === 2);
+                  }
+                }
+                // 查找区县
+                if (addressParts.length > 2) {
+                  var district = this.citys.find((item) => {
+                    return item.name === addressParts[2] && item.level === 2;
+                  });
+                  if (district != null) {
+                    this.editAddressForm.districtId = district.cityId;
+                    this.editAddressForm.district = district.name;
+                  }
+                }
+                // 提取详细地址(第4部分及之后)
+                if (addressParts.length > 3) {
+                  this.editAddressForm.detail = addressParts.slice(3).join(' ');
+                }
+              }
+            }
+          }
         }
 
         this.editAddress.open = true;
+      }).catch(error => {
+        this.msgError("加载数据失败");
+        console.error(error);
+      }).finally(()=>{
+        loading.close();
+      })
     },
     /** 提交按钮 */
     submitEditAddressForm() {
       this.$refs["editAddressForm"].validate(valid => {
         if (valid) {
            this.editAddressForm.userAddress=this.editAddressForm.province+" "+this.editAddressForm.city+" "+this.editAddressForm.district+" "+this.editAddressForm.detail;
-            updateStoreOrder(this.editAddressForm).then(response => {
+            updateAddressErpFsStoreOrder(this.editAddressForm).then(response => {
               if (response.code === 200) {
                 this.msgSuccess("修改成功");
                 this.editAddress.open = false;

+ 192 - 0
src/views/qw/externalContact/collection.vue

@@ -0,0 +1,192 @@
+<template>
+    <div class="app-container">
+        <el-form ref="form" :model="form" label-width="140px">
+            <el-button v-if="form.id" size="mini" type="text" @click="handleShare" icon="el-icon-coin"
+                v-hasPermi="['hisStore:collection:WxaCodeCollectionUnLimit']">分享
+            </el-button>
+            <el-form-item label="信息模板" prop="questionId">
+                <el-select @change="selectQuestion" v-model="form.questionId" placeholder="请选择问答">
+                    <el-option v-for="dict in questionOptions" :key="dict.dictValue" :label="dict.dictLabel"
+                        :value="parseInt(dict.dictValue)" />
+                </el-select>
+            </el-form-item>
+            <div v-for="(answer, index) in form.answers">
+                <div style="margin-bottom: 20px;margin-top: 20px;">
+                    <span style="font-size: 15px;font-weight: bold;    margin-left: 31px">{{ answer.title }}</span>
+                </div>
+                <div style="margin-left: 31px;">
+                    <el-checkbox-group :disabled="form.answers[index].flag" v-model="form.answers[index].value" size="mini" >
+                        <el-checkbox v-for="dict in answer.options" :label="dict.value" >{{ dict.name }}</el-checkbox>
+                    </el-checkbox-group>
+                    <!-- <el-radio-group :disabled="form.answers[index].flag" v-model="form.answers[index].value">
+                        <el-radio v-for="dict in answer.options" :label="dict.value">{{ dict.name }}</el-radio>
+                    </el-radio-group> -->
+                </div>
+
+            </div>
+            <el-form-item label="是否关联套餐包" prop="isPackage">
+                <el-radio-group v-model="form.isPackage">
+                    <el-radio :label="0">否</el-radio>
+                    <el-radio :label="1">是</el-radio>
+                </el-radio-group>
+            </el-form-item>
+            <el-form-item v-if="form.isPackage == 1" label="套餐包" prop="packageId">
+                <el-select filterable v-model="form.packageId" placeholder="请选择套餐包">
+                    <el-option v-for="dict in privatePackageOptions" :key="dict.dictValue" :label="dict.dictLabel"
+                        :value="parseInt(dict.dictValue)" />
+                </el-select>
+            </el-form-item>
+            <el-form-item v-if="form.packageId && form.isPackage && form.isPackage == 1" label="支付类型" prop="payType">
+                <el-radio-group v-model="form.payType">
+                    <el-radio :label="1">全款</el-radio>
+                    <el-radio :label="2">物流代收</el-radio>
+                </el-radio-group>
+            </el-form-item>
+            <el-form-item v-if="form.packageId && form.payType == 2 && form.isPackage &&   form.isPackage == 1" label="物流代收金额" prop="amount">
+                <el-input v-model="form.amount" placeholder="请输入物流代收金额" type="number" />
+            </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 :title="collectionForm.title" v-if="collectionForm.open" :visible.sync="collectionForm.open"
+            width="450px" append-to-body>
+            <div style="padding-bottom:15px;">
+                <img :src="codeImage" width="400px">
+            </div>
+            <div slot="footer" class="dialog-footer">
+                <el-button @click="downloadImage(codeImage, collectionForm.name + '.png')">下载二维码</el-button>
+            </div>
+        </el-dialog>
+    </div>
+</template>
+
+<script>
+import { questionOptions, getAnswer } from "@/api/hisStore/answer";
+import { allPrivatePackage } from "@/api/store/package";
+import { getInfo, addCollection, updateCollection, getWxaCodeCollectionUnLimit } from "@/api/hisStore/collection";
+export default {
+    name: "collection",
+    components: {},
+    data() {
+        return {
+            form: {
+                answers: []
+            },
+            userId: null,
+            questionOptions: [],
+            privatePackageOptions: [],
+            collectionForm: {
+                open: false,
+                title: "用户信息采集分享",
+                name: null,
+            },
+            codeImage: null,
+        };
+    },
+    created() {
+        this.getQuestionOptions();
+        this.getAllPrivatePackge();
+    },
+    methods: {
+        downloadImage(imageSrc, fileName) {
+            const link = document.createElement('a');
+            link.href = imageSrc;
+            link.download = fileName || '付款二维码.png';
+            document.body.appendChild(link);
+            link.click();
+            document.body.removeChild(link);
+        },
+        handleShare() {
+            let loadingRock = this.$loading({
+                lock: true,
+                text: '生成二维码中~~请不要刷新页面!!',
+                spinner: 'el-icon-loading',
+                background: 'rgba(0, 0, 0, 0.7)'
+            });
+
+            getWxaCodeCollectionUnLimit(this.form.id).then(response => {
+                this.codeImage = response.url
+                this.collectionForm.open = true;
+                this.collectionForm.name = this.form.id;
+                loadingRock.close();
+            }).finally(res => {
+                loadingRock.close();
+            })
+        },
+        //获取问答模板
+        getQuestionOptions() {
+            console.log("this.userId", this.userId)
+            questionOptions().then(response => {
+                this.questionOptions = response.rows;
+            })
+        },
+        getAllPrivatePackge() {
+            allPrivatePackage().then(res => {
+                this.privatePackageOptions = res.rows;
+            })
+        },
+        getCollectionInfo(userId) {
+            const queryParams = {
+                userId: userId,
+            }
+            this.userId = userId;
+            getInfo(queryParams).then(res => {
+                this.form = res.data;
+            })
+        },
+        //选择问答模板
+        selectQuestion(val) {
+            console.log(val)
+            this.form = {
+                answers: []
+            };
+            const queryParams = {
+                userId: this.userId,
+                questionId: val
+            }
+            getInfo(queryParams).then(res => {
+                this.form = res.data;
+            })
+            // getAnswer(val).then(response =>{
+
+            //     this.form.answers = response.data.answers;
+            //     console.log(this.form)
+            // })
+        },
+
+        submitForm() {
+            console.log(this.form)
+            this.form.userId = this.userId;
+            this.$refs["form"].validate(valid => {
+                if (valid) {
+                    if (this.form.id != null) {
+                        updateCollection(this.form).then(res => {
+                            this.msgSuccess("修改成功");
+                            this.open = false;
+                            this.$parent.$parent.closeCollection();
+                        })
+
+                    } else {
+                        addCollection(this.form).then(res => {
+                            this.msgSuccess("添加成功");
+                            this.open = false;
+                            this.$parent.$parent.closeCollection();
+                        })
+                    }
+                }
+            });
+
+        },
+        cancel() {
+
+        },
+    },
+};
+
+
+
+</script>

+ 251 - 5
src/views/qw/externalContact/index.vue

@@ -83,6 +83,12 @@
           />
         </el-select>
       </el-form-item>
+      <el-form-item label="是否重粉" prop="userRepeat">
+        <el-select v-model="queryParams.userRepeat" placeholder="重粉" clearable size="small">
+          <el-option label="否" :value="0"/>
+          <el-option label="是" :value="1"/>
+        </el-select>
+      </el-form-item>
       <el-form-item label="客户等级" prop="level">
         <el-select v-model="queryParams.level" placeholder="客户等级" clearable size="small">
           <el-option
@@ -422,6 +428,20 @@
         </template>
       </el-table-column>
       <el-table-column label="企业id" align="center" prop="corpId" />
+      <el-table-column label="重粉看课历史" width="100px" align="center" fixed="right">
+        <template slot-scope="scope">
+          <div v-if="scope.row.fsUserId">
+            <el-tag type="success" v-if="scope.row.userRepeat == 0">正常</el-tag>
+            <el-tag type="danger" v-if="scope.row.userRepeat == 1">重粉</el-tag>
+            <el-button
+              size="mini"
+              type="text"
+              @click="showLog(scope.row)"
+            >重粉看课历史
+            </el-button>
+          </div>
+        </template>
+      </el-table-column>
       <el-table-column label="是否绑定会员" width="100px" align="center" fixed="right">
         <template slot-scope="scope">
           <el-tag v-if="scope.row.fsUserId" >已绑定</el-tag>
@@ -498,7 +518,24 @@
              @click="handleMemberdetails(scope.row)"
              v-if="scope.row.fsUserId"
              >
-             <span>会员详细</span>
+             <span>会员详情</span>
+          </el-button>
+          <el-button
+             size="mini"
+             type="text"
+             @click="handleInfoCollection(scope.row)"
+             v-if="scope.row.fsUserId"
+             >
+             <span>信息采集</span>
+          </el-button>
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-edit"
+            @click="handleChangeStatus(scope.row)"
+            v-hasPermi="['qw:externalContact:changeStatus']"
+          >
+            修改状态
           </el-button>
         </template>
       </el-table-column>
@@ -754,6 +791,70 @@
       <mycustomer ref="mycustomer"  @bindCustomerId="bindCustomerId"></mycustomer>
     </el-dialog>
 
+    <!-- 重粉看课记录   -->
+    <el-drawer title="重粉看课历史" :visible.sync="log.open" size="75%" append-to-body>
+      <div style="padding: 10px">
+        <el-form :model="log.queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="100px">
+          <el-form-item label="所属项目" prop="project">
+            <el-select v-model="log.queryParams.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">
+            <el-select filterable v-model="log.queryParams.courseId" placeholder="请选择课程" clearable size="small"
+                       @change="courseChange(log.queryParams.courseId)">
+              <el-option
+                v-for="dict in courseLists"
+                :key="dict.dictValue"
+                :label="dict.dictLabel"
+                :value="dict.dictValue"
+              />
+            </el-select>
+          </el-form-item>
+          <el-form-item label="小节" prop="videoId">
+            <el-select filterable v-model="log.queryParams.videoId" placeholder="请选择小节" clearable size="small">
+              <el-option
+                v-for="dict in videoList"
+                :key="dict.dictValue"
+                :label="dict.dictLabel"
+                :value="dict.dictValue"
+              />
+            </el-select>
+          </el-form-item>
+          <el-form-item>
+            <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQueryWatchLog">搜索</el-button>
+          </el-form-item>
+        </el-form>
+        <el-table v-loading="log.loading" :data="log.list">
+          <!--          <el-table-column label="企微" align="center" prop="qwUserName"/>-->
+          <el-table-column label="项目" align="center" prop="projectName"/>
+          <el-table-column label="课程" align="center" prop="courseName"/>
+          <el-table-column label="小节" align="aligner" prop="videoName"/>
+          <el-table-column label="记录时间" align="center" prop="createTime"/>
+          <el-table-column label="是否完课" align="center" prop="logType">
+            <template slot-scope="scope">
+              <el-tag v-if="scope.row.logType == 2" type="success">已完课</el-tag>
+              <el-tag v-else type="success">未完课</el-tag>
+            </template>
+          </el-table-column>
+          <el-table-column label="完课时间" align="center" prop="finishTime"/>
+        </el-table>
+
+        <pagination
+          v-show="log.total>0"
+          :total="log.total"
+          :page.sync="log.queryParams.pageNum"
+          :limit.sync="log.queryParams.pageSize"
+          @pagination="logList"
+        />
+      </div>
+    </el-drawer>
+
 <!--    设置一个课程sop-->
     <el-dialog :title="setSop.title" :visible.sync="setSop.open"  width="1200px" append-to-body>
       <SopDialog ref="SopDialog"  @bindCourseSop="bindCourseSop"></SopDialog>
@@ -766,6 +867,29 @@
 	<el-dialog :title="info.title" :visible.sync="info.open"   width="1100px" append-to-body>
 	  <info  ref="Details" />
 	</el-dialog>
+
+  <el-dialog :title="collection.title" :visible.sync="collection.open"   width="1100px" append-to-body>
+	  <collection   ref="collection" />
+	</el-dialog>
+
+  <el-dialog title="修改客户状态" :visible.sync="statusDialog.open" width="500px" append-to-body>
+    <el-form ref="statusForm" :model="statusForm" :rules="statusRules" label-width="100px">
+      <el-form-item label="状态" prop="status">
+        <el-select v-model="statusForm.status" placeholder="请选择状态" 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>
+    <div slot="footer" class="dialog-footer">
+      <el-button @click="statusDialog.open = false">取 消</el-button>
+      <el-button type="primary" @click="submitStatusForm">提 交</el-button>
+    </div>
+  </el-dialog>
   </div>
 </template>
 
@@ -785,7 +909,7 @@ import {
   setCustomerCourseSop,
   getCustomerCourseSop,
   setCustomerCourseSopList,
-  unBindUserId, updateExternalContactCall
+  unBindUserId, updateExternalContactCall,updateExternalContactStatus,getWatchLogList
 } from '@/api/qw/externalContact'
 import {getMyQwUserList, getMyQwCompanyList, updateUser,getQwUserListLikeName} from "@/api/qw/user";
 import {listTag, getTag, searchTags,} from "@/api/qw/tag";
@@ -794,15 +918,50 @@ import mycustomer from '@/views/qw/externalContact/mycustomer'
 import customerDetails from '@/views/qw/externalContact/customerDetails'
 import SopDialog from '@/views/course/sop/SopDialog.vue'
 import  selectUser  from "@/views/qw/externalContact/selectUser.vue";
+import  collection  from "@/views/qw/externalContact/collection.vue";
 import info from "@/views/qw/externalContact/info.vue";
 import { editTalk } from "@/api/qw/externalContactInfo";
 import PaginationMore from "../../../components/PaginationMore/index.vue";
 import userDetails from '@/views/store/components/userDetails.vue';
+import {courseList, videoList} from "@/api/course/courseRedPacketLog";
+import Collection from './collection.vue';
 export default {
   name: "ExternalContact",
-  components:{PaginationMore, mycustomer,customerDetails,SopDialog,selectUser,info,userDetails},
+  components:{PaginationMore, mycustomer,customerDetails,SopDialog,selectUser,info,userDetails,collection},
   data() {
     return {
+      projectOptions: [],
+      courseLists: [],
+      videoList: [],
+      //重粉记录的参数
+      log: {
+        open: false,
+        loading: true,
+        list: [],
+        total: 0,
+        queryParams: {
+          pageNum: 1,
+          pageSize: 10,
+          externalUserId: null,
+          fsUserId: null,
+          projectId: null,
+          courseId: null,
+          videoId: null,
+        },
+      },
+      statusDialog: {
+        open: false,
+        title: "修改客户状态"
+      },
+      statusForm: {
+        id: null,
+        status: null
+      },
+      statusRules: {
+        status: [
+          {required: true, message: '状态不能为空', trigger: 'change'}
+        ]
+      },
       notesOpen: {
         type: 1,
         nameType: 3,
@@ -823,6 +982,10 @@ export default {
         title:"用户信息",
         open:false,
       },
+      collection:{
+        titile:"信息采集",
+        open:false,
+      },
       // ...其他已有数据
       qwUserSuggestions: [],       // 已展示的数据
       showQwUserDropdown: false,   // 控制下拉框显示
@@ -974,7 +1137,8 @@ export default {
         level:null,
         wayId:null,
         levelType:null,
-        companyUser:null
+        companyUser:null,
+        userRepeat: null
       },
       selectTags:[],
       // 表单参数
@@ -984,10 +1148,14 @@ export default {
       statusOptions:[],
       // 表单校验
       rules: {
-      }
+      },
+      userId:null,
     };
   },
   created() {
+    this.getDicts("sys_course_project").then(response => {
+      this.projectOptions = response.data;
+    });
 
     this.getDicts("sys_qw_externalContact_type").then(response => {
       this.typeOptions = response.data;
@@ -1034,12 +1202,55 @@ export default {
 
   },
   methods: {
+    /** 重粉查看操作 */
+    showLog(row) {
+      this.log.queryParams.fsUserId = row.fsUserId;
+      this.log.open = true;
+      this.log.loading = true;
+      courseList().then(response => {
+        this.courseLists = response.list;
+        this.logList();
+      })
+    },
+    handleQueryWatchLog() {
+      this.log.queryParams.pageNum = 1;
+      this.log.queryParams.pageSize = 10;
+      this.logList();
+    },
+    logList() {
+      getWatchLogList(this.log.queryParams).then(e => {
+        this.log.loading = false;
+        this.log.list = e.rows;
+        this.log.total = e.total;
+      });
+    },
+    courseChange(row) {
+      this.log.queryParams.videoId = null;
+      if (row === '') {
+        this.videoList = [];
+        return
+      }
+      videoList(row).then(response => {
+        this.videoList = response.list
+      });
+    },
     handleMemberdetails(row){
             this.show.open=true;
             setTimeout(() => {
                  this.$refs.userDetails.getDetails(row.fsUserId);
             }, 1);
     },
+    handleInfoCollection(row){
+      this.collection.title = "信息采集";
+      this.collection.open = true;
+      this.userId = row.fsUserId;
+      setTimeout(() => {
+                 this.$refs.collection.getCollectionInfo(row.fsUserId);
+            }, 1);
+    },
+    closeCollection(){
+      this.collection.open = false;
+    },
     onQwUserNameClear() {
       this.queryParams.qwUserId = null;  // 同时清空 qwUserId
     },
@@ -1132,6 +1343,33 @@ export default {
         });
         this.getList();
      },
+     handleChangeStatus(row) {
+      this.statusForm = {
+        id: row.id,
+        status: String(row.status) // 保证与 dictValue 类型一致
+      };
+      this.statusDialog.open = true;
+    },
+    submitStatusForm() {
+      this.$refs["statusForm"].validate(valid => {
+        if (valid) {
+          const params = {
+            id: this.statusForm.id,
+            status: this.statusForm.status
+          };
+
+          // 调用接口更新状态
+          updateExternalContactStatus(params).then(response => {
+            this.msgSuccess("状态修改成功");
+            this.statusDialog.open = false;
+            this.getList(); // 刷新列表
+          }).catch(error => {
+            console.error('状态修改失败:', error);
+            this.$message.error('状态修改失败');
+          });
+        }
+      });
+    },
     /** 查询企业微信客户列表 */
     getList() {
       this.loading = true;
@@ -1874,6 +2112,14 @@ export default {
       this.notesOpen.filter = false;
 
     },
+    notesCancel(){
+      this.notesOpen={
+        open: false,
+        notes: null,
+        type: 1,
+        nameType:3,
+      }
+    },
     notesSubmitForm() {
 
       if (this.notesOpen.notes == null || this.notesOpen.notes == "") {

+ 280 - 3
src/views/qw/externalContact/myExternalContact.vue

@@ -76,6 +76,12 @@
           />
         </el-select>
       </el-form-item>
+      <el-form-item label="是否重粉" prop="userRepeat">
+        <el-select v-model="queryParams.userRepeat" placeholder="重粉" clearable size="small">
+          <el-option label="否" :value="0"/>
+          <el-option label="是" :value="1"/>
+        </el-select>
+      </el-form-item>
       <el-form-item label="客户等级" prop="level">
         <el-select v-model="queryParams.level" placeholder="客户等级" clearable size="small">
           <el-option
@@ -369,6 +375,11 @@
           <dict-tag :options="ratingType" :value="scope.row.level"/>
         </template>
       </el-table-column>
+      <el-table-column label="下单次数" align="center" width="100px">
+        <template #default="scope">
+          {{ scope.row.orderCount && scope.row.orderCount !== 0 ? scope.row.orderCount : '' }}
+        </template>
+      </el-table-column>
       <el-table-column label="state参数" align="center" prop="state" width="100px" />
       <el-table-column label="等级状态" align="center" prop="levelType" width="120px" >
         <template slot-scope="scope">
@@ -397,6 +408,20 @@
         </template>
       </el-table-column>
       <el-table-column label="企业id" align="center" prop="corpId" />
+      <el-table-column label="重粉看课历史" width="100px" align="center" fixed="right">
+        <template slot-scope="scope">
+          <div v-if="scope.row.fsUserId">
+            <el-tag type="success" v-if="scope.row.userRepeat == 0">正常</el-tag>
+            <el-tag type="danger" v-if="scope.row.userRepeat == 1">重粉</el-tag>
+            <el-button
+              size="mini"
+              type="text"
+              @click="showLog(scope.row)"
+            >重粉看课历史
+            </el-button>
+          </div>
+        </template>
+      </el-table-column>
       <el-table-column label="是否绑定会员" width="100px" align="center" fixed="right">
         <template slot-scope="scope">
           <el-tag v-if="scope.row.fsUserId" >已绑定</el-tag>
@@ -459,6 +484,22 @@
           >
             <span>初诊单</span>
           </el-button>
+          <el-button
+             size="mini"
+             type="text"
+             @click="handleMemberdetails(scope.row)"
+             v-if="scope.row.fsUserId"
+             >
+             <span>会员详情</span>
+          </el-button>
+          <el-button
+             size="mini"
+             type="text"
+             @click="handleInfoCollection(scope.row)"
+             v-if="scope.row.fsUserId"
+             >
+             <span>信息采集</span>
+          </el-button>
 
 <!--          <el-button v-if="scope.row.customerId"-->
 <!--            size="mini"-->
@@ -478,6 +519,15 @@
                      icon="el-icon-setting"
                      @click="setCourseSOP(scope.row)"
           >设置课程SOP</el-button> -->
+        <el-button
+          size="mini"
+          type="text"
+          icon="el-icon-edit"
+          @click="handleChangeStatus(scope.row)"
+          v-hasPermi="['qw:externalContact:changeStatus']"
+        >
+          修改状态
+        </el-button>
         </template>
       </el-table-column>
     </el-table>
@@ -808,6 +858,77 @@
       </div>
     </el-dialog>
 
+    <!-- 重粉看课记录   -->
+    <el-drawer title="重粉看课历史" :visible.sync="log.open" size="75%" append-to-body>
+      <div style="padding: 10px">
+        <el-form :model="log.queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="100px">
+          <el-form-item label="所属项目" prop="project">
+            <el-select v-model="log.queryParams.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">
+            <el-select filterable v-model="log.queryParams.courseId" placeholder="请选择课程" clearable size="small"
+                       @change="courseChange(log.queryParams.courseId)">
+              <el-option
+                v-for="dict in courseLists"
+                :key="dict.dictValue"
+                :label="dict.dictLabel"
+                :value="dict.dictValue"
+              />
+            </el-select>
+          </el-form-item>
+          <el-form-item label="小节" prop="videoId">
+            <el-select filterable v-model="log.queryParams.videoId" placeholder="请选择小节" clearable size="small">
+              <el-option
+                v-for="dict in videoList"
+                :key="dict.dictValue"
+                :label="dict.dictLabel"
+                :value="dict.dictValue"
+              />
+            </el-select>
+          </el-form-item>
+          <el-form-item>
+            <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQueryWatchLog">搜索</el-button>
+          </el-form-item>
+        </el-form>
+        <el-table v-loading="log.loading" :data="log.list">
+          <!--          <el-table-column label="企微" align="center" prop="qwUserName"/>-->
+          <el-table-column label="项目" align="center" prop="projectName"/>
+          <el-table-column label="课程" align="center" prop="courseName"/>
+          <el-table-column label="小节" align="aligner" prop="videoName"/>
+          <el-table-column label="记录时间" align="center" prop="createTime"/>
+          <el-table-column label="是否完课" align="center" prop="logType">
+            <template slot-scope="scope">
+              <el-tag v-if="scope.row.logType == 2" type="success">已完课</el-tag>
+              <el-tag v-else type="success">未完课</el-tag>
+            </template>
+          </el-table-column>
+          <el-table-column label="完课时间" align="center" prop="finishTime"/>
+        </el-table>
+
+        <pagination
+          v-show="log.total>0"
+          :total="log.total"
+          :page.sync="log.queryParams.pageNum"
+          :limit.sync="log.queryParams.pageSize"
+          @pagination="logList"
+        />
+      </div>
+    </el-drawer>
+    
+    <el-drawer
+        :with-header="false"
+        size="75%"
+          :title="member.title" :visible.sync="member.open">
+      <userDetails  ref="userDetails" />
+    </el-drawer>
+
     <!-- 绑定客户   -->
     <el-dialog :title="bindCustomer.title" :visible.sync="bindCustomer.open"  width="1200px" append-to-body>
       <mycustomer ref="mycustomer"  @bindCustomerId="bindCustomerId"></mycustomer>
@@ -826,6 +947,27 @@
     <el-dialog :title="user.title" :visible.sync="user.open" width="800px" append-to-body>
       <selectUser ref="selectUser" @bindMiniCustomerId="bindMiniCustomerId"></selectUser>
     </el-dialog>
+    <el-dialog :title="collection.title" :visible.sync="collection.open"   width="1100px" append-to-body>
+	  <collection   ref="collection" />
+	</el-dialog>
+  <el-dialog title="修改客户状态" :visible.sync="statusDialog.open" width="500px" append-to-body>
+    <el-form ref="statusForm" :model="statusForm" :rules="statusRules" label-width="100px">
+      <el-form-item label="状态" prop="status">
+        <el-select v-model="statusForm.status" placeholder="请选择状态" 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>
+    <div slot="footer" class="dialog-footer">
+      <el-button @click="statusDialog.open = false">取 消</el-button>
+      <el-button type="primary" @click="submitStatusForm">提 交</el-button>
+    </div>
+  </el-dialog>
   </div>
 </template>
 
@@ -847,7 +989,7 @@ import {
   setCustomerCourseSop,
   getCustomerCourseSop,
   setCustomerCourseSopList,
-  syncMyExternalContact, unBindUserId, updateExternalContactCall,exportMyExternalContact
+  syncMyExternalContact, unBindUserId, updateExternalContactCall,exportMyExternalContact,updateExternalContactStatus,getWatchLogList
 } from '@/api/qw/externalContact'
 import info from "@/views/qw/externalContact/info.vue";
 import {getMyQwUserList, getMyQwCompanyList, handleInputAuthAppKey, updateUser} from "@/api/qw/user";
@@ -862,11 +1004,54 @@ import { editTalk,editAllTalk } from "@/api/qw/externalContactInfo";
 import {createLinkUrl} from "@/api/course/sopCourseLink";
 import {docList} from "@/api/doctor/doctor";
 import PaginationMore from "../../../components/PaginationMore/index.vue";
+import Collection from './collection.vue';
+import {courseList, videoList} from "@/api/course/courseRedPacketLog";
+import userDetails from '@/views/store/components/userDetails.vue';
 export default {
   name: "ExternalContact",
-  components:{PaginationMore, mycustomer,customerDetails,SopDialog,selectUser,info},
+  components:{PaginationMore, mycustomer,customerDetails,SopDialog,selectUser,info,Collection,userDetails},
   data() {
     return {
+      member:{
+        title:"客户详情",
+        open:false,
+      },
+      projectOptions: [],
+      courseLists: [],
+      videoList: [],
+      //重粉记录的参数
+      log: {
+        open: false,
+        loading: true,
+        list: [],
+        total: 0,
+        queryParams: {
+          pageNum: 1,
+          pageSize: 10,
+          externalUserId: null,
+          fsUserId: null,
+          projectId: null,
+          courseId: null,
+          videoId: null,
+        },
+      },
+      statusDialog: {
+        open: false,
+        title: "修改客户状态"
+      },
+      statusForm: {
+        id: null,
+        status: null
+      },
+      statusRules: {
+        status: [
+          {required: true, message: '状态不能为空', trigger: 'change'}
+        ]
+      },
+      collection:{
+        titile:"信息采集",
+        open:false,
+      },
       doctorList:[],
       diagnosisForm:{},
       diagnosisOpen:false,
@@ -1018,7 +1203,9 @@ export default {
         lossTime:null,
         createTime:null,
         level:null,
-        levelType:null
+        levelType:null,
+        companyUser:null,
+        userRepeat: null
       },
 
       queryTagParams:{
@@ -1049,6 +1236,9 @@ export default {
     };
   },
   created() {
+    this.getDicts("sys_course_project").then(response => {
+      this.projectOptions = response.data;
+    });
 
     this.getDicts("sys_qw_externalContact_type").then(response => {
       this.typeOptions = response.data;
@@ -1083,6 +1273,57 @@ export default {
 
   },
   methods: {
+    /** 重粉查看操作 */
+    showLog(row) {
+      this.log.queryParams.fsUserId = row.fsUserId;
+      this.log.open = true;
+      this.log.loading = true;
+      courseList().then(response => {
+        this.courseLists = response.list;
+        this.logList();
+      })
+    },
+    handleQueryWatchLog() {
+      this.log.queryParams.pageNum = 1;
+      this.log.queryParams.pageSize = 10;
+      this.logList();
+    },
+    logList() {
+      getWatchLogList(this.log.queryParams).then(e => {
+        this.log.loading = false;
+        this.log.list = e.rows;
+        this.log.total = e.total;
+      });
+    },
+    courseChange(row) {
+      this.log.queryParams.videoId = null;
+      if (row === '') {
+        this.videoList = [];
+        return
+      }
+      videoList(row).then(response => {
+        this.videoList = response.list
+      });
+    },
+
+    handleMemberdetails(row){
+            this.member.open=true;
+            setTimeout(() => {
+                 this.$refs.userDetails.getDetails(row.fsUserId);
+            }, 1);
+    },
+
+    handleInfoCollection(row){
+      this.collection.title = "信息采集";
+      this.collection.open = true;
+      this.userId = row.fsUserId;
+      setTimeout(() => {
+                 this.$refs.collection.getCollectionInfo(row.fsUserId);
+            }, 1);
+    },
+    closeCollection(){
+      this.collection.open = false;
+    },
     doctorChange(val){
       for(const doctor of this.doctorList) {
         if(doctor.id == val) {
@@ -1250,6 +1491,34 @@ export default {
 
     },
 
+    handleChangeStatus(row) {
+      this.statusForm = {
+        id: row.id,
+        status: String(row.status) // 保证与 dictValue 类型一致
+      };
+      this.statusDialog.open = true;
+    },
+    submitStatusForm() {
+      this.$refs["statusForm"].validate(valid => {
+        if (valid) {
+          const params = {
+            id: this.statusForm.id,
+            status: this.statusForm.status
+          };
+
+          // 调用接口更新状态
+          updateExternalContactStatus(params).then(response => {
+            this.msgSuccess("状态修改成功");
+            this.statusDialog.open = false;
+            this.getList(); // 刷新列表
+          }).catch(error => {
+            console.error('状态修改失败:', error);
+            this.$message.error('状态修改失败');
+          });
+        }
+      });
+    },
+
     /** 查询企业微信客户列表 */
     getList() {
       this.loading = true;
@@ -1980,6 +2249,14 @@ export default {
       this.notesOpen.filter = false;
 
     },
+    notesCancel(){
+      this.notesOpen={
+        open: false,
+        notes: null,
+        type: 1,
+        nameType:3,
+      }
+    },
     notesSubmitForm() {
 
       if (this.notesOpen.notes == null || this.notesOpen.notes == "") {

+ 13 - 1
src/views/qw/friendWelcome/deptFriendWelcome.vue

@@ -66,6 +66,8 @@
 
 
     <el-table v-loading="loading" :data="friendWelcomeList" @selection-change="handleSelectionChange" border>
+      <el-table-column label="id" align="center" prop="id" width="180"/>
+      <el-table-column label="标题" align="center" prop="welcomeTitle"/>
       <el-table-column label="消息内容" align="left" prop="welcomeText"  width="400px" >
         <template slot-scope="scope">
           <span style="color:rgb(19, 154, 50);" v-if="scope.row.isDayparting==='1'">[共 {{JSON.parse(scope.row.daypartingItemlist).length+1}} 时段]</span>
@@ -160,6 +162,16 @@
               </el-tag>
             </div>
           </el-form-item>
+          <!-- 新增整体标题 -->
+          <el-form-item label="标题:" prop="welcomeTitle">
+            <el-input v-model="form.welcomeTitle" placeholder="请输入欢迎语标题"/>
+            <el-alert style="margin-top: 8px;height: 30px"
+                      title="此标题仅用于欢迎语的用途区分"
+                      type="info"
+                      :closable="false"
+                      show-icon>
+            </el-alert>
+          </el-form-item>
           <el-form-item label="是否发送欢迎语">
             <el-switch
               v-model="form.isSendMsg"
@@ -731,7 +743,7 @@ export default {
     //选择群发的企业成员账号
     handlelistUser(){
       setTimeout(() => {
-        this.$refs.QwUserList.getDetails(this.queryParams.corpId);
+        this.$refs.QwUserList.getDetails(this.queryParams.corpId,null,null,"2");
       }, 1);
       this.listUser.title="选择企业成员"
       this.listUser.open=true;

+ 12 - 0
src/views/qw/friendWelcome/indexNew.vue

@@ -66,6 +66,8 @@
 
 
     <el-table v-loading="loading" :data="friendWelcomeList" @selection-change="handleSelectionChange" border>
+      <el-table-column label="id" align="center" prop="id" width="180"/>
+      <el-table-column label="标题" align="center" prop="welcomeTitle"/>
       <el-table-column label="消息内容" align="left" prop="welcomeText"  width="400px" >
         <template slot-scope="scope">
           <span style="color:rgb(19, 154, 50);" v-if="scope.row.isDayparting==='1'">[共 {{JSON.parse(scope.row.daypartingItemlist).length+1}} 时段]</span>
@@ -161,6 +163,16 @@
               </el-tag>
             </div>
           </el-form-item>
+          <!-- 新增整体标题 -->
+          <el-form-item label="标题:" prop="welcomeTitle">
+            <el-input v-model="form.welcomeTitle" placeholder="请输入欢迎语标题"/>
+            <el-alert style="margin-top: 8px;height: 30px"
+                      title="此标题仅用于欢迎语的用途区分"
+                      type="info"
+                      :closable="false"
+                      show-icon>
+            </el-alert>
+          </el-form-item>
           <el-form-item label="是否发送欢迎语">
             <el-switch
               v-model="form.isSendMsg"

+ 13 - 2
src/views/qw/friendWelcome/myWelcome.vue

@@ -66,6 +66,8 @@
 
 
     <el-table v-loading="loading" :data="friendWelcomeList" @selection-change="handleSelectionChange" border>
+      <el-table-column label="id" align="center" prop="id" width="180"/>
+      <el-table-column label="标题" align="center" prop="welcomeTitle"/>
       <el-table-column label="消息内容" align="left" prop="welcomeText"  width="400px" >
         <template slot-scope="scope">
           <span style="color:rgb(19, 154, 50);" v-if="scope.row.isDayparting==='1'">[共 {{JSON.parse(scope.row.daypartingItemlist).length+1}} 时段]</span>
@@ -138,7 +140,6 @@
           </el-alert>
         </div>
         <el-form ref="form" :model="form" :rules="rules" label-width="120px">
-
           <el-form-item label="选择使用成员:" prop="qwUserIds" style="margin-top: 2%">
             <div>
               <el-button
@@ -160,6 +161,16 @@
               </el-tag>
             </div>
           </el-form-item>
+          <!-- 新增整体标题 -->
+          <el-form-item label="标题:" prop="welcomeTitle">
+            <el-input v-model="form.welcomeTitle" placeholder="请输入欢迎语标题"/>
+            <el-alert style="margin-top: 8px;height: 30px"
+                      title="此标题仅用于欢迎语的用途区分"
+                      type="info"
+                      :closable="false"
+                      show-icon>
+            </el-alert>
+          </el-form-item>
           <el-form-item label="是否发送欢迎语">
             <el-switch
               v-model="form.isSendMsg"
@@ -731,7 +742,7 @@ export default {
     //选择群发的企业成员账号
     handlelistUser(){
       setTimeout(() => {
-        this.$refs.QwUserList.getDetails(this.queryParams.corpId);
+        this.$refs.QwUserList.getDetails(this.queryParams.corpId,null,null,"1");
       }, 1);
       this.listUser.title="选择企业成员"
       this.listUser.open=true;

+ 8 - 8
src/views/qw/sop/addSop.vue

@@ -29,10 +29,10 @@
               :label="1"
             >标签
             </el-radio>
-<!--            <el-radio-->
-<!--              :label="2"-->
-<!--            >群聊-->
-<!--            </el-radio>-->
+            <el-radio
+              :label="2"
+            >群聊
+            </el-radio>
           </el-radio-group>
           <Tip :title="'标签:根据企微客户的标签筛选客户进入SOP'" />
         </el-form-item>
@@ -76,7 +76,7 @@
           </el-select>
           <Tip title="选择的企业微信员工下面的群聊" />
         </el-form-item>
-        <el-form-item label="客户评级" prop="isRating" style="margin-top: 2%">
+        <el-form-item label="客户评级" prop="isRating" style="margin-top: 2%" v-if="form.filterMode == 1">
           <el-switch
             v-model="form.isRating"
             active-color="#13ce66"
@@ -235,7 +235,7 @@
 
           </el-form-item>
         </div>
-        <el-form-item label="是否固定营期" prop="isFixed" v-if="form.type != 3">
+        <el-form-item label="是否固定营期" prop="isFixed" v-if="form.type != 3 && form.filterMode == 1">
           <el-radio-group v-model="form.isFixed">
             <el-radio
               :label="1"
@@ -265,7 +265,7 @@
           </el-row>
           <Tip title="任务生成的代发送消息,如果超过此设置的时间还未发送,自动作废" />
         </el-form-item>
-        <el-form-item v-if="(form.sendType==2 || form.sendType==4 || form.sendType==11) && form.type != 3 && form.isFixed == 0" label="自动添加SOP"
+        <el-form-item v-if="(form.sendType==2 || form.sendType==4 || form.sendType==11) && form.type != 3 && form.isFixed == 0 && form.filterMode == 1" label="自动添加SOP"
                       prop="autoSopTime.autoSopType">
           <el-radio-group v-model="form.autoSopTime.autoSopType">
             <el-radio
@@ -332,7 +332,7 @@
 <!--        </el-form-item>-->
 
 
-        <el-form-item label="是否只发送注册用户" prop="isRegister" v-if="form.type != 3">
+        <el-form-item label="是否只发送注册用户" prop="isRegister" v-if="form.type != 3 && form.filterMode == 1">
           <el-radio-group v-model="form.isRegister">
             <el-radio
               :label="1"

+ 43 - 9
src/views/qw/sop/sop.vue

@@ -760,7 +760,20 @@
                       </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" 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 ">
 
@@ -1401,18 +1414,28 @@ export default {
             this.$set(this.setting[i], 'linkTitle', selectedCourse.dictLabel);
             this.$set(this.setting[i], 'linkImageUrl', selectedCourse.dictImgUrl);
           }
+          if (selectedCourse && this.setting[i].contentType == 4 && this.msgForm.courseId != null) {
+            this.$set(this.setting[i], 'miniprogramPicUrl', selectedCourse.dictImgUrl);
+          }
 
         }
 
       }
-      if (this.msgForm.videoId != null ) {
+      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.setting[i].contentType == 3  && this.msgForm.videoId != null) {
-            this.$set(this.setting[i], 'linkDescribe', selectedVideo.dictLabel);
+          if (selectedVideo && this.msgForm.videoId != null) {
+            console.log(2, this.setting[i].contentType)
+            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);
+            }
+
           }
         }
       }
@@ -1420,14 +1443,22 @@ export default {
 
     },
     videoIdChange() {
-      if (this.msgForm.videoId != null ) {
+      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.setting[i].contentType == 3  && this.msgForm.videoId != null) {
-            this.$set(this.setting[i], 'linkDescribe', selectedVideo.dictLabel);
+          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);
+            }
+
+
           }
         }
       }
@@ -1851,7 +1882,7 @@ export default {
       });
     },
     courseChange() {
-      if (this.msgForm.courseId != null ) {
+      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++) {
           //响应式直接给链接的标题/封面上值
@@ -1859,12 +1890,15 @@ export default {
             this.$set(this.setting[i], 'linkTitle', selectedCourse.dictLabel);
             this.$set(this.setting[i], 'linkImageUrl', selectedCourse.dictImgUrl);
           }
+          if (selectedCourse && this.setting[i].contentType == 4 && this.msgForm.courseId != null) {
+            this.$set(this.setting[i], 'miniprogramPicUrl', selectedCourse.dictImgUrl);
+          }
 
         }
 
       }
       videoList(this.msgForm.courseId).then(response => {
-        this.videoList=response.list;
+        this.videoList = response.list;
       });
     },
     cancelMsgForm(){

+ 32 - 1
src/views/qw/sopLogs/sopLogsList.vue

@@ -175,6 +175,7 @@
                 <span v-if="item.contentType == 5">文件</span>
                 <span v-if="item.contentType == 6">视频</span>
                 <span v-if="item.contentType == 7">语音</span>
+                <span v-if="item.contentType == 8">视频号</span>
                 <span v-if="item.contentType == 9">APP</span>
                 <span v-if="item.contentType == 10">自定义小程序</span>
                 <span v-if="item.contentType == 4"><el-button size="mini" type="primary" @click="generateShortLink(item)" style="margin-left: 330px;">生成短链</el-button></span>
@@ -314,7 +315,11 @@
       :limit.sync="queryParams.pageSize"
       @pagination="getList"
     />
+    <el-dialog :title="videoNumOptions.title" :visible.sync="videoNumOptions.open" width="1500px" append-to-body>
+      <userVideo ref="QwUserVideo" @videoResult="qwUserVideoResult"></userVideo>
+    </el-dialog>
   </div>
+
 </template>
 
 <script>
@@ -327,11 +332,12 @@ import {
   generateShortLink
 } from '../../../api/qw/sopLogs'
 import {delSopUserLogsInfo} from "@/api/qw/sopUserLogsInfo";
+import userVideo from "@/views/qw/userVideo/userVideo";
 
 export default {
   name: "sopLogsList",
   props:{
-    rowDetailFrom:{},
+    rowDetailFrom:{userVideo},
   },
 
   watch:{
@@ -345,6 +351,12 @@ export default {
   },
   data() {
     return {
+      videoNumOptions: {
+        title: '选择视频号',
+        open: false,
+        content: null,
+        contentIndex: null,
+      },
       copyText:"",
       shortLoading:false,
       shortLinkDialogVisible:false,
@@ -432,6 +444,25 @@ export default {
 
   },
   methods: {
+
+    qwUserVideoResult(val) {
+
+      // 根据选中的内容,将返回的数据更新到相应的表单项
+      const content = this.videoNumOptions.content;
+      const setList = content[this.videoNumOptions.contentIndex];
+      setList.nickname = val.nickname;
+      setList.avatar = val.avatar;
+      setList.coverUrl = val.coverUrl;
+      setList.thumbUrl = val.thumbUrl;
+      setList.desc = val.desc;
+      setList.url = val.url;
+      setList.extras = val.extras;
+      setList.videoId = val.id;
+      console.info(setList)
+
+      this.videoNumOptions.open = false;
+
+    },
     /** 查询企业微信SOP  定时任务列表 */
     getList(val) {
       this.queryParams.sopId = val.id || this.rowDetailFrom.id;

+ 44 - 1
src/views/qw/sopTemp/updateSopTemp.vue

@@ -320,6 +320,14 @@
                                           >
                                             {{ setList.isSalesCallAdded ? '移除#销售称呼#' : '添加#销售称呼#' }}
                                           </el-link>
+                                          <el-link
+                                            v-if="setList.contentType == 1 && roles.includes('edit_sop_temp_content')"
+                                            type="primary"
+                                            @click="toggleUserNameCall(index, contentIndex, setIndex)"
+                                            style="margin-top: 10px; margin-left: 20px"
+                                          >
+                                            {{ setList.isUserNameCallAdded ? '移除#客户称呼#' : '添加#客户称呼#' }}
+                                          </el-link>
 
                                           <ImageUpload :disabled="formType == 3 || !roles.includes('edit_sop_temp_content')" v-if="setList.contentType == 2 "
                                                        v-model="setList.imgUrl"
@@ -726,7 +734,7 @@ export default {
       ruleList: [],
       ids: [],
       startTimeRange: [],
-      courseTypeList: ['1','3', '4', '9','10'],
+      courseTypeList: ['1','2', '4','5','6', '7','8','9','10'],
       sysFsSopWatchStatus: [],
       //消息内容类型 企微版
       sysQwSopContentType: [],
@@ -1483,6 +1491,38 @@ export default {
         textarea.setSelectionRange(newCursorPos, newCursorPos);
       });
     },
+    toggleUserNameCall(itemIndex, contentIndex, setIndex) {
+      // 获取目标对象
+      const setItem = this.setting[itemIndex].content[contentIndex].setting[setIndex];
+      const salesCall = '#客户称呼#';
+      const refKey = `textarea-${itemIndex}-${contentIndex}-${setIndex}`;
+      const textarea = this.$refs[refKey][0]?.$refs?.textarea;
+
+      if (!textarea) return;
+
+      // 获取光标位置
+      const cursorPosition = textarea.selectionStart;
+
+      if (setItem.isUserNameCallAdded) {
+        // 移除所有标签
+        setItem.value = setItem.value.replace(new RegExp(salesCall, 'g'), '');
+      } else {
+        // 插入到光标位置
+        setItem.value =
+          setItem.value.slice(0, cursorPosition) +
+          salesCall +
+          setItem.value.slice(cursorPosition);
+      }
+
+      // 切换状态
+      setItem.isUserNameCallAdded = !setItem.isUserNameCallAdded;
+
+      // 保持光标位置
+      this.$nextTick(() => {
+        const newCursorPos = cursorPosition + (setItem.isUserNameCallAdded ? salesCall.length : 0);
+        textarea.setSelectionRange(newCursorPos, newCursorPos);
+      });
+    },
     handleKeydown(event, itemIndex, contentIndex, setIndex) {
 
       const setItem = this.setting[itemIndex].content[contentIndex].setting[setIndex];
@@ -1756,6 +1796,9 @@ export default {
                     if (setList && !Object.hasOwn(setList, 'isSalesCallAdded')) {
                       this.$set(setList, 'isSalesCallAdded', false);
                     }
+                    if (setList && !Object.hasOwn(setList, 'isUserNameCallAdded')) {
+                      this.$set(setList, 'isUserNameCallAdded', false);
+                    }
                   });
                 }
               });

+ 72 - 1
src/views/qw/sopUserLogsInfo/sendMsgOpenTool.vue

@@ -164,7 +164,44 @@
                           @input="handleInputVideoText(item.value,item)"/>
                       </div>
                       <div v-if="item.contentType == 8">
+                        <el-button type="primary"
+                                   style="margin-bottom: 1%"
+                                   @click="hanldeSelectVideoNum(setting,index)">
+                          选择视频号
+                        </el-button>
+                        <el-card class="box-card" v-if="item.coverUrl">
+                          <el-form-item label="封面标题:" label-width="100px">
+                            <el-input v-model="item.nickname"
+                                      style="width: 90%;margin-bottom: 1%" disabled/>
+                          </el-form-item>
+                          <el-form-item label="头像:" label-width="100px">
+                            <el-image
+                              v-if="item.avatar != null"
+                              :src="item.avatar"
+                              :preview-src-list="[item.avatar]"
+                              :style="{ width: '50px', height: '50px' }"
+                            ></el-image>
+                          </el-form-item>
+                          <el-form-item label="封面:" label-width="100px">
+                            <el-image
+                              v-if="item.coverUrl != null"
+                              :src="item.coverUrl"
+                              :preview-src-list="[item.coverUrl]"
+                              :style="{ width: '200px', height: '200px' }"
+                            ></el-image>
 
+                          </el-form-item>
+                          <el-form-item label="简介:" label-width="100px">
+                            <el-input type="textarea" :rows="3"
+                                      v-model="item.desc"
+                                      style="width: 90%;margin-top: 1%;" disabled/>
+                          </el-form-item>
+                          <el-form-item label="视频地址:" label-width="100px"
+                                        style="margin-top: 1%">
+                            <el-input v-model="item.url"
+                                      style="width: 90%;" disabled/>
+                          </el-form-item>
+                        </el-card>
                       </div>
 
                     </el-form-item>
@@ -226,6 +263,9 @@
           <el-button @click="cancelMsgForm">取 消</el-button>
         </div>
     </el-dialog>
+    <el-dialog :title="videoNumOptions.title" :visible.sync="videoNumOptions.open" width="1500px" append-to-body>
+      <userVideo ref="QwUserVideo" @videoResult="qwUserVideoResult"></userVideo>
+    </el-dialog>
   </div>
 </template>
 
@@ -233,13 +273,20 @@
 import { sendMsgSopType,} from "../../../api/qw/sopUserLogsInfo";
 import ImageUpload from "@/views/qw/sop/ImageUpload.vue";
 import {courseList, videoList} from "@/api/qw/sop";
+import userVideo from "@/views/qw/userVideo/userVideo";
 
 
 export default {
   name: "sendMsgOpenTool",
-  components: {ImageUpload},
+  components: {ImageUpload,userVideo},
   data() {
     return {
+      videoNumOptions: {
+        title: '选择视频号',
+        open: false,
+        content: null,
+        contentIndex: null,
+      },
       //上传语音的遮罩层
       voiceLoading :false,
       uploadUrl:process.env.VUE_APP_BASE_API+"/common/uploadOSS",
@@ -341,6 +388,24 @@ export default {
   },
   methods: {
 
+    qwUserVideoResult(val) {
+
+      // 根据选中的内容,将返回的数据更新到相应的表单项
+      const content = this.videoNumOptions.content;
+      const setList = content[this.videoNumOptions.contentIndex];
+      setList.nickname = val.nickname;
+      setList.avatar = val.avatar;
+      setList.coverUrl = val.coverUrl;
+      setList.thumbUrl = val.thumbUrl;
+      setList.desc = val.desc;
+      setList.url = val.url;
+      setList.extras = val.extras;
+      setList.videoId = val.id;
+      console.info(setList)
+
+      this.videoNumOptions.open = false;
+
+    },
     oneClickGroupSending(val,type,corpId){
 
       this.sendMsgOpen.open= true;
@@ -452,6 +517,12 @@ export default {
       this.$set(content, 'value', filteredValue);
 
     },
+    //选择视频号
+    hanldeSelectVideoNum(content, index) {
+      this.videoNumOptions.content = content;
+      this.videoNumOptions.contentIndex = index;
+      this.videoNumOptions.open = true;
+    },
 
     delSetList(index){
       this.setting.splice(index,1)

+ 72 - 1
src/views/qw/sopUserLogsInfo/sendMsgSopOpenTool.vue

@@ -164,7 +164,44 @@
                           @input="handleInputVideoText(item.value,item)"/>
                       </div>
                       <div v-if="item.contentType == 8">
+                        <el-button type="primary"
+                                   style="margin-bottom: 1%"
+                                   @click="hanldeSelectVideoNum(setting,index)">
+                          选择视频号
+                        </el-button>
+                        <el-card class="box-card" v-if="item.coverUrl">
+                          <el-form-item label="封面标题:" label-width="100px">
+                            <el-input v-model="item.nickname"
+                                      style="width: 90%;margin-bottom: 1%" disabled/>
+                          </el-form-item>
+                          <el-form-item label="头像:" label-width="100px">
+                            <el-image
+                              v-if="item.avatar != null"
+                              :src="item.avatar"
+                              :preview-src-list="[item.avatar]"
+                              :style="{ width: '50px', height: '50px' }"
+                            ></el-image>
+                          </el-form-item>
+                          <el-form-item label="封面:" label-width="100px">
+                            <el-image
+                              v-if="item.coverUrl != null"
+                              :src="item.coverUrl"
+                              :preview-src-list="[item.coverUrl]"
+                              :style="{ width: '200px', height: '200px' }"
+                            ></el-image>
 
+                          </el-form-item>
+                          <el-form-item label="简介:" label-width="100px">
+                            <el-input type="textarea" :rows="3"
+                                      v-model="item.desc"
+                                      style="width: 90%;margin-top: 1%;" disabled/>
+                          </el-form-item>
+                          <el-form-item label="视频地址:" label-width="100px"
+                                        style="margin-top: 1%">
+                            <el-input v-model="item.url"
+                                      style="width: 90%;" disabled/>
+                          </el-form-item>
+                        </el-card>
                       </div>
 
                     </el-form-item>
@@ -226,6 +263,9 @@
           <el-button @click="cancelMsgForm">取 消</el-button>
         </div>
     </el-dialog>
+    <el-dialog :title="videoNumOptions.title" :visible.sync="videoNumOptions.open" width="1500px" append-to-body>
+      <userVideo ref="QwUserVideo" @videoResult="qwUserVideoResult"></userVideo>
+    </el-dialog>
   </div>
 </template>
 
@@ -233,13 +273,20 @@
 import { sendMsg,} from "../../../api/qw/sopUserLogsInfo";
 import ImageUpload from "@/views/qw/sop/ImageUpload.vue";
 import {courseList, videoList} from "@/api/qw/sop";
+import userVideo from "@/views/qw/userVideo/userVideo";
 
 
 export default {
   name: "sendMsgSopOpenTool",
-  components: {ImageUpload},
+  components: {ImageUpload,userVideo},
   data() {
     return {
+      videoNumOptions: {
+        title: '选择视频号',
+        open: false,
+        content: null,
+        contentIndex: null,
+      },
       //上传语音的遮罩层
       voiceLoading :false,
       uploadUrl:process.env.VUE_APP_BASE_API+"/common/uploadOSS",
@@ -342,6 +389,24 @@ export default {
   },
   methods: {
 
+    qwUserVideoResult(val) {
+
+      // 根据选中的内容,将返回的数据更新到相应的表单项
+      const content = this.videoNumOptions.content;
+      const setList = content[this.videoNumOptions.contentIndex];
+      setList.nickname = val.nickname;
+      setList.avatar = val.avatar;
+      setList.coverUrl = val.coverUrl;
+      setList.thumbUrl = val.thumbUrl;
+      setList.desc = val.desc;
+      setList.url = val.url;
+      setList.extras = val.extras;
+      setList.videoId = val.id;
+      console.info(setList)
+
+      this.videoNumOptions.open = false;
+
+    },
     oneClickGroupSending(val,type,corpId){
 
       this.sendMsgOpen.open= true;
@@ -467,6 +532,12 @@ export default {
 
     },
 
+    //选择视频号
+    hanldeSelectVideoNum(content, index) {
+      this.videoNumOptions.content = content;
+      this.videoNumOptions.contentIndex = index;
+      this.videoNumOptions.open = true;
+    },
 
     handleKeydown(event, index) {
       const item = this.setting[index];

+ 2 - 1
src/views/qw/user/qwUserList.vue

@@ -102,7 +102,7 @@ export default {
   },
   methods: {
 
-    getDetails(corpId,type,sendType){
+    getDetails(corpId,type,sendType,isRemark){
       this.type=type;
       this.sendType=sendType;
       if (type!=null&&sendType!=null){
@@ -110,6 +110,7 @@ export default {
         this.queryParams.sendType=sendType;
       }
       this.queryParams.corpId=corpId;
+      this.queryParams.isRemark=isRemark;
       this.getList();
     },
     /** 查询企微用户列表 */

+ 31 - 20
src/views/store/components/productOrder.vue

@@ -15,14 +15,14 @@
         <span  style="margin-left: 20px" class="color-danger">订单状态:
            <el-tag prop="status" v-for="(item, index) in statusOptions"    v-if="order.status==item.dictValue">{{item.dictLabel}}</el-tag>
         </span>
-       
+
         <div class="operate-button-container" >
           <el-button size="mini" @click="handleCertificates()"  v-hasPermi="['store:storeOrder:uploadCredentials']" >上传凭证</el-button>
           <el-button size="mini" @click="handleEditAddress()" v-if="order.status==0||order.status==1"  v-hasPermi="['store:storeOrder:editAddress']" >修改收货地址</el-button>
           <el-button size="mini" @click="handleBindCustomer()"  v-hasPermi="['store:storeOrder:bindCustomer']" >关联客户</el-button>
           <el-button size="mini" @click="editOrder()"  v-hasPermi="['store:storeOrder:edit']" >修改订单</el-button>
           <!-- <el-button size="mini" @click="handleEditUser()"  v-hasPermi="['users:user:edit']" >修改会员修改</el-button> -->
-          <el-button size="mini" v-if="order.customerId!=null&&order.customerId>0"  @click="handleCustomer()"    >查看客户详情</el-button>         
+          <el-button size="mini" v-if="order.customerId!=null&&order.customerId>0"  @click="handleCustomer()"    >查看客户详情</el-button>
         </div>
         <div class="operate-button-container"  v-hasPermi="['store:storeOrder:express']"  >
           <el-button size="mini" @click="showExpress()" >查看物流</el-button>
@@ -48,7 +48,7 @@
             </el-descriptions-item>
             <!-- <el-descriptions-item label="进线时间"  >
                 <span v-if="user!=null">
-                  {{user.registerDate}} 
+                  {{user.registerDate}}
                 </span>
             </el-descriptions-item>
             <el-descriptions-item label="推线编码"  >
@@ -56,7 +56,7 @@
                   {{user.registerCode}}
                 </span>
             </el-descriptions-item> -->
-             
+
             <el-descriptions-item label="收货人"  >
                 <span v-if="order!=null ">
                   {{order.realName }}
@@ -123,7 +123,7 @@
                   {{customerInfo.registerDate }}
                 </span>
             </el-descriptions-item>
-        
+
       </el-descriptions>
       <div style="margin: 20px 0px"  v-if="order!=null">
         <span class="font-small">
@@ -286,7 +286,7 @@
     <el-dialog :title="editUser.title" :visible.sync="editUser.open" width="600px" append-to-body>
       <el-form ref="editUserForm" :model="editUserForm" :rules="editUserRules" label-width="100px">
          <el-form-item label="进线时间" prop="registerDate">
-          <el-date-picker clearable size="small"  
+          <el-date-picker clearable size="small"
             v-model="editUserForm.registerDate"
             type="date"
             value-format="yyyy-MM-dd"
@@ -386,7 +386,7 @@
               <el-button type="primary" @click="searchCustomer">查看</el-button>
             </el-col>
           </el-row>
-          
+
         </el-form-item>
         <el-form-item label="客户选择"  prop="customerIds">
           <el-table   @selection-change="handleSelectionChange"
@@ -440,12 +440,23 @@ import {updateUser,getUser } from "@/api/users/user";
 
 import {getCustomerListBySearch } from "@/api/crm/customer";
 import ImageUpload from '@/components/ImageUpload'
-import {bindCustomer,getExpress, listStoreOrder, getStoreOrder, delStoreOrder, addStoreOrder, updateStoreOrder, exportStoreOrder,uploadCredentials } from "@/api/store/storeOrder";
+import {
+  bindCustomer,
+  getExpress,
+  listStoreOrder,
+  getStoreOrder,
+  delStoreOrder,
+  addStoreOrder,
+  updateStoreOrder,
+  exportStoreOrder,
+  uploadCredentials,
+  updateAddressErpFsStoreOrder
+} from "@/api/store/storeOrder";
 import {getAllList} from "@/api/store/city";
 import customerDetails from '../../crm/components/customerDetails.vue';
 export default {
   name: "order",
-  components: {customerDetails, 
+  components: {customerDetails,
     ImageUpload },
   data() {
     return {
@@ -498,7 +509,7 @@ export default {
       },
       editAddressForm:{
         districtId:null,
-        
+
       },
       editAddressRules:{
 
@@ -553,7 +564,7 @@ export default {
     this.getDicts("store_order_create_type").then((response) => {
       this.createTypeOptions = response.data;
     });
-   
+
   },
   methods: {
     showImageDialog() {
@@ -576,7 +587,7 @@ export default {
       }
       var data={mobile:this.bindCustomerForm.mobile};
       getCustomerListBySearch(data).then(response => {
-          this.customers=response.data;        
+          this.customers=response.data;
       });
     },
     handleBindCustomer() {
@@ -621,7 +632,7 @@ export default {
           if(this.express!=null&&this.express.Traces!=null){
               this.traces=this.express.Traces
           }
-          
+
       });
 
     },
@@ -640,8 +651,8 @@ export default {
       })
       console.log(item)
       this.editAddressForm.city=item.name;
- 
-        
+
+
     },
     provinceChange(val){
       this.city=this.citys.filter(item => item.parentId===val )
@@ -675,7 +686,7 @@ export default {
         var city=this.citys.find((item)=>{
           return item.name==address[1]&&item.level==1;
         })
-        
+
         if(city!=null){
           this.editAddressForm.cityId=city.cityId;
           this.district=this.citys.filter(item => item.parentId===city.cityId&&item.level==2 )
@@ -686,7 +697,7 @@ export default {
         if(district!=null){
           this.editAddressForm.districtId=district.cityId;
         }
-        
+
         this.editAddress.open = true;
     },
     /** 提交按钮 */
@@ -694,7 +705,7 @@ export default {
       this.$refs["editAddressForm"].validate(valid => {
         if (valid) {
            this.editAddressForm.userAddress=this.editAddressForm.province+" "+this.editAddressForm.city+" "+this.editAddressForm.district+" "+this.editAddressForm.detail;
-            updateStoreOrder(this.editAddressForm).then(response => {
+            updateAddressErpFsStoreOrder(this.editAddressForm).then(response => {
               if (response.code === 200) {
                 this.msgSuccess("修改成功");
                 this.editAddress.open = false;
@@ -738,7 +749,7 @@ export default {
               this.getOrder(this.order.id);
             }
           });
-       
+
         }
       });
     },
@@ -757,7 +768,7 @@ export default {
             this.order = response.order;
             if(response.order.certificates != null){
               this.certificates = response.order.certificates;
-            }  
+            }
             this.user = response.user;
             this.logs = response.logs;
             this.items = response.items;

+ 7 - 2
src/views/store/components/storeAfterSalesDetails.vue

@@ -21,10 +21,15 @@
                </span>
                <div class="operate-button-container"  >
                  <el-button size="mini"  @click="showOrder">查看订单</el-button>
+                 <el-button size="mini" @click="editDelivery()" v-show="item.salesStatus==0&&item.status===1" v-hasPermi="['store:storeAfterSales:edit']">编辑物流</el-button>
+                 <el-button size="mini" @click="goAuditing(1)"  v-show="item.status==0 && item.salesStatus==0 " v-hasPermi="['store:storeAfterSales:audit']">平台审核</el-button>
+                 <el-button size="mini" @click="depotAuditing(3)"  v-show="item.status==2 && item.salesStatus==0" v-hasPermi="['store:storeAfterSales:depot']">仓库审核</el-button>
+                 <el-button size="mini" @click="tuimoney(4)"  v-show="item.status==3 && item.salesStatus==0" v-hasPermi="['store:storeAfterSales:finance']">财务审核</el-button>
+                 <el-button size="mini" @click="NoAuditing(5)"  v-show="item.salesStatus==0  &&item.status<4 " v-hasPermi="['store:storeAfterSales:revoke']">驳回</el-button>
                </div>
-               <div class="operate-button-container"  >
+               <!-- <div class="operate-button-container"  >
                   <el-button size="mini" @click="editDelivery()" v-show="item.salesStatus==0&&item.status===1" v-hasPermi="['his:storeAfterSales:edit']">编辑物流</el-button>
-               </div>
+               </div> -->
              </div>
 
      <div style="margin: 20px 0px">

+ 76 - 43
src/views/store/components/storeOrderDetails.vue

@@ -411,7 +411,36 @@
 </template>
 
 <script>
-import {bindCustomer, msgList,getMsgFollow,updateMoney,getGoods,getEroOrder,editTuiMoney,updateDelivery,createErpOrder,updateExpress, afterSales,sendgoods,logList,listOrder,getExpress,syncExpress, listOrderitem,getOrder,getOrderAddress,getUserPhone, delOrder, addOrder, updateStoreOrder, exportOrder,payment,tuiOrder ,getPrescribe} from "@/api/store/storeOrder";
+import {
+  bindCustomer,
+  msgList,
+  getMsgFollow,
+  updateMoney,
+  getGoods,
+  getEroOrder,
+  editTuiMoney,
+  updateDelivery,
+  createErpOrder,
+  updateExpress,
+  afterSales,
+  sendgoods,
+  logList,
+  listOrder,
+  getExpress,
+  syncExpress,
+  listOrderitem,
+  getOrder,
+  getOrderAddress,
+  getUserPhone,
+  delOrder,
+  addOrder,
+  updateStoreOrder,
+  exportOrder,
+  payment,
+  tuiOrder,
+  getPrescribe,
+  updateAddressErpFsStoreOrder
+} from "@/api/store/storeOrder";
 import packageOrderDetails from '../components/packageOrderDetails2.vue';
 import {getCustomerListBySearch } from "@/api/crm/customer";
 import { getTcmScheduleList } from "@/api/company/tcmScheduleReport";
@@ -712,13 +741,13 @@ import {getCitys} from "@/api/store/city";
       },
       handlePhone(){
         const orderId = this.item.orderId;
-        getUserPhone(orderId).then(response =>{
+        return getUserPhone(orderId).then(response =>{
             this.item.userPhone = response.userPhone;
         })
       },
       handleAddress(){
         const orderId = this.item.orderId;
-        getOrderAddress(orderId).then(response =>{
+        return getOrderAddress(orderId).then(response =>{
             this.item.userAddress = response.address;
         })
       },
@@ -778,7 +807,7 @@ import {getCitys} from "@/api/store/city";
           userAddress: addressModified ? this.buildFullAddress() : (this.originalAddress || this.item.userAddress || ''),
         };
 
-        updateStoreOrder(payload).then(response => {
+        updateAddressErpFsStoreOrder(payload).then(response => {
           if (response.code === 200) {
             this.msgSuccess("操作成功");
             this.edit.open = false;
@@ -792,48 +821,52 @@ import {getCitys} from "@/api/store/city";
       });
     },
     editOrder() {
-      this.edit.open = true;
-      this.editForm.orderId = this.item.orderId;
-      this.editForm.remark = this.item.remark;
-      this.editForm.userPhone = this.item.userPhone != null ? this.item.userPhone.toString() : "";
-      if (this.item.orderBuyType != null) {
-        this.editForm.orderBuyType = this.item.orderBuyType.toString();
-      }
-      this.editForm.orderChannel = this.item.orderChannel;
-      this.editForm.qwSubject = this.item.qwSubject;
-      this.editForm.scheduleId = this.item.scheduleId;
+      this.handlePhone().then(res=>{
+        return this.handleAddress()
+      }).then(res=>{
+        this.edit.open = true;
+        this.editForm.orderId = this.item.orderId;
+        this.editForm.remark = this.item.remark;
+        this.editForm.userPhone = this.item.userPhone != null ? this.item.userPhone.toString() : "";
+        if (this.item.orderBuyType != null) {
+          this.editForm.orderBuyType = this.item.orderBuyType.toString();
+        }
+        this.editForm.orderChannel = this.item.orderChannel;
+        this.editForm.qwSubject = this.item.qwSubject;
+        this.editForm.scheduleId = this.item.scheduleId;
 
-      const currentAddress = (this.item.userAddress || "").toString().trim();
-      // 记录原始完整地址
-      this.originalAddress = currentAddress;
+        const currentAddress = (this.item.userAddress || "").toString().trim();
+        // 记录原始完整地址
+        this.originalAddress = currentAddress;
 
-      this.getCitys().then(() => {
-        if (!currentAddress) {
-          this.cityIds = [];
-          this.editForm.userAddress = "";
-          this.originalDetail = "";
-          return;
-        }
-        // 按“省 市 区 详细地址(空格分隔)”进行拆分。若无区或无市也不报错。
-        const parts = currentAddress.split(/\s+/);
-        const detail = parts.pop() || "";           // 末尾作为详细地址
-        const provLabel = parts[0];
-        const cityLabel = parts[1];
-        const areaLabel = parts[2];
+        this.getCitys().then(() => {
+          if (!currentAddress) {
+            this.cityIds = [];
+            this.editForm.userAddress = "";
+            this.originalDetail = "";
+            return;
+          }
+          // 按“省 市 区 详细地址(空格分隔)”进行拆分。若无区或无市也不报错。
+          const parts = currentAddress.split(/\s+/);
+          const detail = parts.pop() || "";           // 末尾作为详细地址
+          const provLabel = parts[0];
+          const cityLabel = parts[1];
+          const areaLabel = parts[2];
 
-        const province = this.citys.find(p => p.label === provLabel);
-        if (province) {
-          // 只回显省,不预选市/区
-          this.cityIds = [province.value];
-        } else {
-          console.warn("未匹配到省:", { provLabel });
-          this.cityIds = [];
-        }
-        // 输入框只放“详细地址(不含省市区)”
-        this.editForm.userAddress = detail;
-        // 记录原始详细地址(用于判断有无修改)
-        this.originalDetail = detail;
-      });
+          const province = this.citys.find(p => p.label === provLabel);
+          if (province) {
+            // 只回显省,不预选市/区
+            this.cityIds = [province.value];
+          } else {
+            console.warn("未匹配到省:", { provLabel });
+            this.cityIds = [];
+          }
+          // 输入框只放“详细地址(不含省市区)”
+          this.editForm.userAddress = detail;
+          // 记录原始详细地址(用于判断有无修改)
+          this.originalDetail = detail;
+        });
+      })
     },
     updateExpress(){
       var that=this;

+ 12 - 5
src/views/store/user/list.vue

@@ -84,7 +84,7 @@
     <el-table v-loading="loading" border :data="userList" @selection-change="handleSelectionChange" >
       <el-table-column type="selection" width="55" align="center" />
 
-      <el-table-column label="用户昵称" align="center" prop="nickName" width="150px"/>
+      <el-table-column label="用户昵称" align="center" prop="nickname" width="150px"/>
       <el-table-column label="用户头像" align="center" prop="avatar" >
          <template slot-scope="scope">
                  <el-image v-if="scope.row.avatar!=null"
@@ -110,6 +110,11 @@
             type="text"
             @click="handledetails(scope.row)"
           >详情</el-button>
+          <el-button
+            size="mini"
+            type="text"
+            @click="handleNickName(scope.row)"
+          >修改昵称</el-button>
         </template>
       </el-table-column>
     </el-table>
@@ -128,7 +133,7 @@
         <el-form-item label="用户昵称" prop="nickName">
           <el-input v-model="form.nickName" placeholder="请输入用户昵称" />
         </el-form-item>
-        <el-form-item label="用户状态" prop="status">
+        <!-- <el-form-item label="用户状态" prop="status">
             <el-select v-model="form.status" placeholder="请选择状态" clearable size="small">
                   <el-option
                     v-for="dict in userOptions"
@@ -140,7 +145,7 @@
         </el-form-item>
         <el-form-item label="用户备注" prop="remark" >
           <el-input v-model="form.remark" placeholder="请输入用户备注" type="textarea"/>
-        </el-form-item>
+        </el-form-item> -->
       </el-form>
       <div slot="footer" class="dialog-footer">
         <el-button type="primary" @click="submitForm">确 定</el-button>
@@ -317,10 +322,12 @@ export default {
       this.multiple = !selection.length
     },
     /** 新增按钮操作 */
-    handleAdd() {
+    handleNickName(row) {
       this.reset();
       this.open = true;
-      this.title = "添加用户";
+      this.form.nickName = row.nickname;
+      this.form.userId = row.userId;
+      this.title = "修改用户昵称";
     },
     /** 修改按钮操作 */
     handleUpdate(row) {

+ 16 - 5
src/views/store/user/myList.vue

@@ -84,7 +84,7 @@
     <el-table v-loading="loading" border :data="userList" @selection-change="handleSelectionChange" >
       <el-table-column type="selection" width="55" align="center" />
 
-      <el-table-column label="用户昵称" align="center" prop="nickName" width="150px"/>
+      <el-table-column label="用户昵称" align="center" prop="nickname" width="150px"/>
       <el-table-column label="用户头像" align="center" prop="avatar" >
          <template slot-scope="scope">
                  <el-image v-if="scope.row.avatar!=null"
@@ -110,6 +110,11 @@
             type="text"
             @click="handledetails(scope.row)"
           >详情</el-button>
+          <el-button
+            size="mini"
+            type="text"
+            @click="handleNickName(scope.row)"
+          >修改昵称</el-button>
         </template>
       </el-table-column>
     </el-table>
@@ -128,7 +133,7 @@
         <el-form-item label="用户昵称" prop="nickName">
           <el-input v-model="form.nickName" placeholder="请输入用户昵称" />
         </el-form-item>
-        <el-form-item label="用户状态" prop="status">
+        <!-- <el-form-item label="用户状态" prop="status">
             <el-select v-model="form.status" placeholder="请选择状态" clearable size="small">
                   <el-option
                     v-for="dict in userOptions"
@@ -140,7 +145,7 @@
         </el-form-item>
         <el-form-item label="用户备注" prop="remark" >
           <el-input v-model="form.remark" placeholder="请输入用户备注" type="textarea"/>
-        </el-form-item>
+        </el-form-item> -->
       </el-form>
       <div slot="footer" class="dialog-footer">
         <el-button type="primary" @click="submitForm">确 定</el-button>
@@ -261,6 +266,10 @@ export default {
                  this.$refs.userDetails.getDetails(row.userId);
             }, 1);
      },
+     /**修改昵称 */
+    //  handleNickName(row){
+    //     console.log(row);
+    //  },
     /** 查询用户列表 */
     getList() {
       this.loading = true;
@@ -320,10 +329,12 @@ export default {
       this.multiple = !selection.length
     },
     /** 新增按钮操作 */
-    handleAdd() {
+    handleNickName(row) {
       this.reset();
       this.open = true;
-      this.title = "添加用户";
+      this.form.nickName = row.nickname;
+      this.form.userId = row.userId;
+      this.title = "修改用户昵称";
     },
     /** 修改按钮操作 */
     handleUpdate(row) {