浏览代码

Merge branch 'master' of http://1.14.104.71:10880/root/ylrz_his_scrm_companyUI

caoliqin 2 天之前
父节点
当前提交
6e6f5b9c7b
共有 77 个文件被更改,包括 15145 次插入778 次删除
  1. 1 1
      .env.prod-hdt
  2. 22 0
      .env.prod-hyt
  3. 19 0
      .env.prod-ylrz
  4. 1 1
      .env.prod-zkzh
  5. 2 0
      package.json
  6. 47 0
      src/api/course/coursePlaySourceConfig.js
  7. 62 0
      src/api/fastGpt/fastGptKeywordSend.js
  8. 70 0
      src/api/fastGpt/fastgptEventLogTotal.js
  9. 62 0
      src/api/hisStore/city.js
  10. 33 0
      src/api/hisStore/statistics.js
  11. 88 0
      src/api/hisStore/storeAfterSales.js
  12. 155 0
      src/api/hisStore/storeOrder.js
  13. 19 0
      src/api/hisStore/storeOrderAudit.js
  14. 72 0
      src/api/hisStore/storeOrderOffline.js
  15. 71 0
      src/api/hisStore/storePayment.js
  16. 23 0
      src/api/hisStore/storeProduct.js
  17. 8 0
      src/api/hisStore/storeProductCategory.js
  18. 53 0
      src/api/hisStore/storeProductPackage.js
  19. 53 0
      src/api/hisStore/userOnlineState.js
  20. 10 0
      src/api/qw/externalContact.js
  21. 9 0
      src/api/qw/sopUserLogsInfo.js
  22. 6 6
      src/api/users/user.js
  23. 二进制
      src/assets/logo/hyt.png
  24. 130 0
      src/views/company/companyUser/index.vue
  25. 426 0
      src/views/course/coursePlaySourceConfig/index.vue
  26. 4 0
      src/views/course/courseUserStatistics/index.vue
  27. 531 151
      src/views/course/courseUserStatistics/qw/index.vue
  28. 4 0
      src/views/course/courseUserStatistics/qw/statistics.vue
  29. 4 0
      src/views/course/courseUserStatistics/statistics.vue
  30. 31 3
      src/views/course/courseWatchLog/index.vue
  31. 4 4
      src/views/course/courseWatchLog/statistics.vue
  32. 59 38
      src/views/course/courseWatchLog/watchLog.vue
  33. 113 0
      src/views/fastGpt/fastGptKeywordSend/fastGptKeyWordDetails.vue
  34. 532 0
      src/views/fastGpt/fastGptKeywordSend/index.vue
  35. 333 0
      src/views/fastGpt/fastgptEventLogTotal/index.vue
  36. 761 0
      src/views/hisStore/components/addOrder.vue
  37. 309 0
      src/views/hisStore/components/addOrderOffline.vue
  38. 72 0
      src/views/hisStore/components/addUser.vue
  39. 153 0
      src/views/hisStore/components/addUserAddress.vue
  40. 373 0
      src/views/hisStore/components/offlineOrder.vue
  41. 92 0
      src/views/hisStore/components/paymentSelect.vue
  42. 397 0
      src/views/hisStore/components/productAfterSalesOrder.vue
  43. 144 0
      src/views/hisStore/components/productDetails.vue
  44. 922 0
      src/views/hisStore/components/productOrder.vue
  45. 903 0
      src/views/hisStore/components/productOrder2.vue
  46. 135 0
      src/views/hisStore/components/productPackageDetails.vue
  47. 100 0
      src/views/hisStore/components/productSelect.vue
  48. 344 0
      src/views/hisStore/statistics/storeOrder.vue
  49. 344 0
      src/views/hisStore/statistics/storePayment.vue
  50. 403 0
      src/views/hisStore/storeAfterSales/list.vue
  51. 310 0
      src/views/hisStore/storeAfterSales/myList.vue
  52. 828 0
      src/views/hisStore/storeOrder/allList.vue
  53. 1000 0
      src/views/hisStore/storeOrder/list.vue
  54. 722 0
      src/views/hisStore/storeOrder/myList.vue
  55. 240 0
      src/views/hisStore/storeOrderAudit/index.vue
  56. 283 0
      src/views/hisStore/storeOrderOffline/index.vue
  57. 245 0
      src/views/hisStore/storeOrderOffline/myList.vue
  58. 409 0
      src/views/hisStore/storePayment/index.vue
  59. 216 0
      src/views/hisStore/storeProduct/index.vue
  60. 603 0
      src/views/hisStore/storeProductPackage/index.vue
  61. 393 0
      src/views/hisStore/userOnlineState/index.vue
  62. 389 364
      src/views/qw/QwWorkTask/qw/index.vue
  63. 4 4
      src/views/qw/qwUserDelLossStatistics/index.vue
  64. 148 133
      src/views/qw/qwUserVoiceLogTotal/index.vue
  65. 1 1
      src/views/qw/sop/addSop.vue
  66. 25 1
      src/views/qw/sop/sop.vue
  67. 0 1
      src/views/qw/sop/updateSop.vue
  68. 2 1
      src/views/qw/sopLogs/sopLogsList.vue
  69. 14 9
      src/views/qw/sopTemp/addSopTemp.vue
  70. 2 2
      src/views/qw/sopTemp/index.vue
  71. 17 37
      src/views/qw/sopTemp/updateSopTemp.vue
  72. 12 7
      src/views/qw/sopUserLogsInfo/sendMsgOpenTool.vue
  73. 751 0
      src/views/qw/sopUserLogsInfo/sendMsgSopOpenTool.vue
  74. 14 9
      src/views/qw/sopUserLogsInfo/sopUserLogsInfoDetails.vue
  75. 1 0
      src/views/qw/user/cuDeptIdIndex.vue
  76. 3 1
      src/views/qw/user/index.vue
  77. 4 4
      src/views/statistics/section/today.vue

+ 1 - 1
.env.prod-hdt

@@ -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

+ 22 - 0
.env.prod-hyt

@@ -0,0 +1,22 @@
+# 页面标题
+VUE_APP_TITLE =宏医堂SCRM销售端
+# 公司名称
+VUE_APP_COMPANY_NAME =易行健和泰(湖北)健康咨询有限公司
+# ICP备案号
+VUE_APP_ICP_RECORD =鄂ICP备2025116549号-1
+# ICP网站访问地址
+VUE_APP_ICP_URL =https://beian.miit.gov.cn
+# 网站LOG
+VUE_APP_LOG_URL =@/assets/logo/hyt.png
+
+# 生产环境配置
+ENV = 'production'
+
+# FS管理系统/开发环境
+VUE_APP_BASE_API = '/prod-api'
+
+#默认 1、会员 2、企微
+VUE_APP_COURSE_DEFAULT = 1
+
+# 路由懒加载
+VUE_CLI_BABEL_TRANSPILE_MODULES = true

+ 19 - 0
.env.prod-ylrz

@@ -0,0 +1,19 @@
+# 页面标题
+VUE_APP_TITLE =云联融智销售端
+# 公司名称
+VUE_APP_COMPANY_NAME =云联融智医药有限公司
+# ICP备案号
+VUE_APP_ICP_RECORD =
+# ICP网站访问地址
+VUE_APP_ICP_URL =https://beian.miit.gov.cn
+# 网站LOG
+VUE_APP_LOG_URL =@/assets/logo/ylrz.png
+
+# 生产环境配置
+ENV = 'production'
+
+# FS管理系统/开发环境
+VUE_APP_BASE_API = '/prod-api'
+
+# 路由懒加载
+VUE_CLI_BABEL_TRANSPILE_MODULES = true

+ 1 - 1
.env.prod-zkzh

@@ -19,4 +19,4 @@ VUE_APP_BASE_API = '/prod-api'
 VUE_CLI_BABEL_TRANSPILE_MODULES = true
 
 #默认 1、会员 2、企微
-VUE_APP_COURSE_DEFAULT = 2
+VUE_APP_COURSE_DEFAULT = 1

+ 2 - 0
package.json

@@ -7,6 +7,7 @@
   "scripts": {
     "dev": "vue-cli-service serve",
     "build:prod": "vue-cli-service build",
+    "build:prod-ylrz": "vue-cli-service build --mode prod-ylrz",
     "build:stage": "vue-cli-service build --mode staging",
     "build:prod-jz": "vue-cli-service build --mode prod-jz",
     "build:prod-hzyy": "vue-cli-service build --mode prod-hzyy",
@@ -35,6 +36,7 @@
     "build:prod-kyt": "vue-cli-service build --mode prod-kyt",
     "build:prod-fby": "vue-cli-service build --mode prod-fby",
     "build:prod-syysy": "vue-cli-service build --mode prod-syysy",
+    "build:prod-hyt": "vue-cli-service build --mode prod-hyt",
     "preview": "node build/index.js --preview",
     "lint": "eslint --ext .js,.vue src",
     "test:unit": "jest --clearCache && vue-cli-service test:unit",

+ 47 - 0
src/api/course/coursePlaySourceConfig.js

@@ -0,0 +1,47 @@
+import request from '@/utils/request'
+
+export function list(query) {
+  return request({
+    url: '/course/playSourceConfig/list',
+    method: 'get',
+    params: query
+  })
+}
+
+export function get(id) {
+  return request({
+    url: '/course/playSourceConfig/' + id,
+    method: 'get'
+  })
+}
+
+export function add(data) {
+  return request({
+    url: '/course/playSourceConfig',
+    method: 'post',
+    data: data
+  })
+}
+
+export function update(data) {
+  return request({
+    url: '/course/playSourceConfig',
+    method: 'put',
+    data: data
+  })
+}
+
+export function del(id) {
+  return request({
+    url: '/course/playSourceConfig/' + id,
+    method: 'delete'
+  })
+}
+
+export function updateIsTownOn(query) {
+  return request({
+    url: '/course/playSourceConfig/updateIsTownOn',
+    method: 'get',
+    params: query
+  })
+}

+ 62 - 0
src/api/fastGpt/fastGptKeywordSend.js

@@ -0,0 +1,62 @@
+import request from '@/utils/request'
+
+// 查询Ai指令关键字列表
+export function keywordList(query) {
+  return request({
+    url: '/fastGpt/fastGptKeywordSend/keywordList',
+    method: 'get',
+    params: query
+  })
+}
+
+// 查询Ai指令列表
+export function listFastGptKeywordSend(query) {
+  return request({
+    url: '/fastGpt/fastGptKeywordSend/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 查询Ai指令详细
+export function getFastGptKeywordSend(id) {
+  return request({
+    url: '/fastGpt/fastGptKeywordSend/' + id,
+    method: 'get'
+  })
+}
+
+// 新增Ai指令
+export function addFastGptKeywordSend(data) {
+  return request({
+    url: '/fastGpt/fastGptKeywordSend',
+    method: 'post',
+    data: data
+  })
+}
+
+// 修改Ai指令
+export function updateFastGptKeywordSend(data) {
+  return request({
+    url: '/fastGpt/fastGptKeywordSend',
+    method: 'put',
+    data: data
+  })
+}
+
+// 删除Ai指令
+export function delFastGptKeywordSend(id) {
+  return request({
+    url: '/fastGpt/fastGptKeywordSend/' + id,
+    method: 'delete'
+  })
+}
+
+// 导出Ai指令
+export function exportFastGptKeywordSend(query) {
+  return request({
+    url: '/fastGpt/fastGptKeywordSend/export',
+    method: 'get',
+    params: query
+  })
+}

+ 70 - 0
src/api/fastGpt/fastgptEventLogTotal.js

@@ -0,0 +1,70 @@
+import request from '@/utils/request'
+
+// 查询ai事件埋点统计列表
+/*export function listFastgptEventLogTotal(query) {
+  return request({
+    url: '/fastGpt/fastgptEventLogTotal/list',
+    method: 'get',
+    params: query
+  })
+}*/
+
+export function listFastgptEventLogTotal(data) {
+  return request({
+    url: '/fastGpt/fastgptEventLogTotal/list',
+    method: 'post',
+    data: data
+  })
+}
+
+
+// 查询ai事件埋点统计详细
+export function getFastgptEventLogTotal(id) {
+  return request({
+    url: '/fastGpt/fastgptEventLogTotal/' + id,
+    method: 'get'
+  })
+}
+
+// 新增ai事件埋点统计
+export function addFastgptEventLogTotal(data) {
+  return request({
+    url: '/fastGpt/fastgptEventLogTotal',
+    method: 'post',
+    data: data
+  })
+}
+
+// 修改ai事件埋点统计
+export function updateFastgptEventLogTotal(data) {
+  return request({
+    url: '/fastGpt/fastgptEventLogTotal',
+    method: 'put',
+    data: data
+  })
+}
+
+// 删除ai事件埋点统计
+export function delFastgptEventLogTotal(id) {
+  return request({
+    url: '/fastGpt/fastgptEventLogTotal/' + id,
+    method: 'delete'
+  })
+}
+
+// 导出ai事件埋点统计
+export function exportFastgptEventLogTotal(query) {
+  return request({
+    url: '/fastGpt/fastgptEventLogTotal/export',
+    method: 'get',
+    params: query
+  })
+}
+
+
+export function getFastGptRoleAppKeyList() {
+  return request({
+    url: '/fastGpt/fastgptEventLogTotal/getFastGptRoleAppKeyList',
+    method: 'get'
+  })
+}

+ 62 - 0
src/api/hisStore/city.js

@@ -0,0 +1,62 @@
+import request from '@/utils/request'
+
+// 查询城市列表
+export function listCity(query) {
+  return request({
+    url: '/store/city/list',
+    method: 'get',
+    params: query
+  })
+}
+export function getCitys(query) {
+  return request({
+    url: '/store/store/city/getCitys',
+    method: 'get',
+    params: query
+  })
+}
+
+
+
+// 查询城市详细
+export function getCity(id) {
+  return request({
+    url: '/store/city/' + id,
+    method: 'get'
+  })
+}
+
+// 新增城市
+export function addCity(data) {
+  return request({
+    url: '/store/city',
+    method: 'post',
+    data: data
+  })
+}
+
+// 修改城市
+export function updateCity(data) {
+  return request({
+    url: '/store/city',
+    method: 'put',
+    data: data
+  })
+}
+
+// 删除城市
+export function delCity(id) {
+  return request({
+    url: '/store/city/' + id,
+    method: 'delete'
+  })
+}
+
+// 导出城市
+export function exportCity(query) {
+  return request({
+    url: '/store/city/export',
+    method: 'get',
+    params: query
+  })
+}

+ 33 - 0
src/api/hisStore/statistics.js

@@ -0,0 +1,33 @@
+import request from '@/utils/request'
+
+
+export function storeOrder(query) {
+  return request({
+    url: '/store/store/statistics/storeOrder',
+    method: 'get',
+    params: query
+  })
+}
+export function exportStoreOrder(query) {
+  return request({
+    url: '/store/store/statistics/exportStoreOrder',
+    method: 'get',
+    params: query
+  })
+}
+
+export function storePayment(query) {
+  return request({
+    url: '/store/store/statistics/storePayment',
+    method: 'get',
+    params: query
+  })
+}
+export function exportStorePayment(query) {
+  return request({
+    url: '/store/store/statistics/exportStorePayment',
+    method: 'get',
+    params: query
+  })
+}
+

+ 88 - 0
src/api/hisStore/storeAfterSales.js

@@ -0,0 +1,88 @@
+import request from '@/utils/request'
+
+// 查询售后记录列表
+export function listStoreAfterSales(query) {
+  return request({
+    url: '/store/store/storeAfterSales/list',
+    method: 'get',
+    params: query
+  })
+}
+export function myListStoreAfterSales(query) {
+  return request({
+    url: '/store/store/storeAfterSales/myList',
+    method: 'get',
+    params: query
+  })
+}
+
+
+// 查询售后记录详细
+export function getStoreAfterSales(id) {
+  return request({
+    url: '/store/store/storeAfterSales/' + id,
+    method: 'get'
+  })
+}
+
+// 新增售后记录
+export function addStoreAfterSales(data) {
+  return request({
+    url: '/store/store/storeAfterSales',
+    method: 'post',
+    data: data
+  })
+}
+
+// 修改售后记录
+export function updateStoreAfterSales(data) {
+  return request({
+    url: '/store/store/storeAfterSales',
+    method: 'put',
+    data: data
+  })
+}
+
+// 删除售后记录
+export function delStoreAfterSales(id) {
+  return request({
+    url: '/store/store/storeAfterSales/' + id,
+    method: 'delete'
+  })
+}
+
+// 导出售后记录
+export function exportStoreAfterSales(query) {
+  return request({
+    url: '/store/store/storeAfterSales/export',
+    method: 'get',
+    params: 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
+  })
+}
+

+ 155 - 0
src/api/hisStore/storeOrder.js

@@ -0,0 +1,155 @@
+import request from '@/utils/request'
+
+// 查询订单列表
+export function listStoreOrder(query) {
+  return request({
+    url: '/store/store/storeOrder/list',
+    method: 'get',
+    params: query
+  })
+}
+
+
+export function listAllStoreOrder(query) {
+  return request({
+    url: '/store/store/storeOrder/allList',
+    method: 'get',
+    params: query
+  })
+}
+export function getCustomerOrderList(query) {
+  return request({
+    url: '/store/store/storeOrder/getCustomerOrderList',
+    method: 'get',
+    params: query
+  })
+}
+
+
+export function myListStoreOrder(query) {
+  return request({
+    url: '/store/store/storeOrder/myList',
+    method: 'get',
+    params: query
+  })
+}
+
+// 查询订单详细
+export function getStoreOrder(id) {
+  return request({
+    url: '/store/store/storeOrder/' + id,
+    method: 'get'
+  })
+}
+// 查询电话
+export function getUserPhone(id) {
+  return request({
+    url: '/store/store/storeOrder/queryPhone/' + id,
+    method: 'get'
+  })
+}
+
+// 查询订单详细
+export function getStoreOrderAddress(id) {
+  return request({
+    url: '/store/store/storeOrder/queryAddress/' + id,
+    method: 'get'
+  })
+}
+
+export function getExpress(id) {
+  return request({
+    url: '/store/store/storeOrder/getExpress/' + id,
+    method: 'get'
+  })
+}
+
+
+// 新增订单
+export function addStoreOrder(data) {
+  return request({
+    url: '/store/store/storeOrder',
+    method: 'post',
+    data: data
+  })
+}
+
+
+
+
+// 修改订单
+export function updateStoreOrder(data) {
+  return request({
+    url: '/store/store/storeOrder',
+    method: 'put',
+    data: data
+  })
+}
+
+// 删除订单
+export function delStoreOrder(id) {
+  return request({
+    url: '/store/store/storeOrder/' + id,
+    method: 'delete'
+  })
+}
+
+// 导出订单
+export function exportStoreOrder(query) {
+  return request({
+    url: '/store/store/storeOrder/export',
+    method: 'get',
+    params: query
+  })
+}
+
+export function exportStoreOrderItems(query) {
+  return request({
+    url: '/store/store/storeOrder/exportItems',
+    method: 'get',
+    params: query
+  })
+}
+
+
+export function createUserOrder(data) {
+  return request({
+    url: '/store/store/storeOrder/createUserOrder',
+    method: 'post',
+    data: data
+  })
+}
+
+export function editPayPrice(data) {
+  return request({
+    url: '/store/store/storeOrder/editPayPrice',
+    method: 'post',
+    data: data
+  })
+}
+
+
+export function bindCustomer(data) {
+  return request({
+    url: '/store/store/storeOrder/bindCustomer',
+    method: 'post',
+    data: data
+  })
+}
+
+export function uploadCredentials(data) {
+  return request({
+    url: '/store/store/storeOrder/uploadCredentials',
+    method: 'post',
+    data: data
+  })
+}
+
+//获取制单类型
+export function getCreateOrderType() {
+  return request({
+    url: '/store/store/storeOrder/getCreateOrderType',
+    method: 'get'
+  })
+}
+

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

@@ -0,0 +1,19 @@
+import request from '@/utils/request'
+
+// 获取审核列表
+export const list = (query) => {
+  return request({
+    url: '/store/store/storeOrderAudit/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 审核
+export const audit = (data) => {
+  return request({
+    url: '/store/store/storeOrderAudit/audit',
+    method: 'post',
+    data: data
+  })
+}

+ 72 - 0
src/api/hisStore/storeOrderOffline.js

@@ -0,0 +1,72 @@
+import request from '@/utils/request'
+
+// 查询线下订单列表
+export function listStoreOrderOffline(query) {
+  return request({
+    url: '/store/store/storeOrderOffline/list',
+    method: 'get',
+    params: query
+  })
+}
+
+
+// 查询线下订单列表
+export function myOrderList(query) {
+  return request({
+    url: '/store/store/storeOrderOffline/myList',
+    method: 'get',
+    params: query
+  })
+}
+
+// 查询线下订单详细
+export function getStoreOrderOffline(orderId) {
+  return request({
+    url: '/store/store/storeOrderOffline/' + orderId,
+    method: 'get'
+  })
+}
+
+// 新增线下订单
+export function createOrder(data) {
+  return request({
+    url: '/store/store/storeOrderOffline/createOrder',
+    method: 'post',
+    data: data
+  })
+}
+
+// 修改线下订单
+export function updateStoreOrderOffline(data) {
+  return request({
+    url: '/store/store/storeOrderOffline',
+    method: 'put',
+    data: data
+  })
+}
+
+// 删除线下订单
+export function delStoreOrderOffline(orderId) {
+  return request({
+    url: '/store/store/storeOrderOffline/' + orderId,
+    method: 'delete'
+  })
+}
+
+// 导出线下订单
+export function exportStoreOrderOffline(query) {
+  return request({
+    url: '/store/store/storeOrderOffline/export',
+    method: 'get',
+    params: query
+  })
+}
+
+// 上传凭证
+export function uploadCredentials(data) {
+  return request({
+    url: '/store/store/storeOrderOffline/uploadCredentials',
+    method: 'post',
+    data: data
+  })
+}

+ 71 - 0
src/api/hisStore/storePayment.js

@@ -0,0 +1,71 @@
+import request from '@/utils/request'
+
+// 查询支付明细列表
+export function listStorePayment(query) {
+  return request({
+    url: '/store/store/storePayment/list',
+    method: 'get',
+    params: query
+  })
+}
+export function getStorePaymentList(query) {
+  return request({
+    url: '/store/store/storePayment/getStorePaymentList',
+    method: 'get',
+    params: query
+  })
+}
+export function getMyPaymentList(query) {
+  return request({
+    url: '/store/store/storePayment/getMyPaymentList',
+    method: 'get',
+    params: query
+  })
+}
+
+
+
+
+
+// 查询支付明细详细
+export function getStorePayment(paymentId) {
+  return request({
+    url: '/store/store/storePayment/' + paymentId,
+    method: 'get'
+  })
+}
+
+// 新增支付明细
+export function addStorePayment(data) {
+  return request({
+    url: '/store/store/storePayment',
+    method: 'post',
+    data: data
+  })
+}
+
+// 修改支付明细
+export function updateStorePayment(data) {
+  return request({
+    url: '/store/store/storePayment',
+    method: 'put',
+    data: data
+  })
+}
+
+// 删除支付明细
+export function delStorePayment(paymentId) {
+  return request({
+    url: '/store/store/storePayment/' + paymentId,
+    method: 'delete'
+  })
+}
+
+// 导出支付明细
+export function exportStorePayment(query) {
+  return request({
+    url: '/store/store/storePayment/export',
+    method: 'get',
+    params: query
+  })
+}

+ 23 - 0
src/api/hisStore/storeProduct.js

@@ -0,0 +1,23 @@
+import request from '@/utils/request'
+
+// 查询商品列表
+export function listStoreProduct(query) {
+  return request({
+    url: '/store/store/storeProduct/list',
+    method: 'get',
+    params: query
+  })
+}
+export function getStoreProductAttrValueList(query) {
+  return request({
+    url: '/store/store/storeProduct/getStoreProductAttrValueList',
+    method: 'get',
+    params: query
+  })
+}
+export function getStoreProduct(productId) {
+  return request({
+    url: '/store/store/storeProduct/' + productId,
+    method: 'get'
+  })
+}

+ 8 - 0
src/api/hisStore/storeProductCategory.js

@@ -0,0 +1,8 @@
+import request from '@/utils/request'
+
+export function getAllStoreProductCategory() {
+  return request({
+    url: '/store/store/storeProductCategory/getAllList' ,
+    method: 'get'
+  })
+}

+ 53 - 0
src/api/hisStore/storeProductPackage.js

@@ -0,0 +1,53 @@
+import request from '@/utils/request'
+
+// 查询商品组合套餐列表
+export function listStoreProductPackage(query) {
+  return request({
+    url: '/store/store/storeProductPackage/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 查询商品组合套餐详细
+export function getStoreProductPackage(packageId) {
+  return request({
+    url: '/store/store/storeProductPackage/' + packageId,
+    method: 'get'
+  })
+}
+
+// 新增商品组合套餐
+export function addStoreProductPackage(data) {
+  return request({
+    url: '/store/store/storeProductPackage',
+    method: 'post',
+    data: data
+  })
+}
+
+// 修改商品组合套餐
+export function updateStoreProductPackage(data) {
+  return request({
+    url: '/store/store/storeProductPackage',
+    method: 'put',
+    data: data
+  })
+}
+
+// 删除商品组合套餐
+export function delStoreProductPackage(packageId) {
+  return request({
+    url: '/store/store/storeProductPackage/' + packageId,
+    method: 'delete'
+  })
+}
+
+// 导出商品组合套餐
+export function exportStoreProductPackage(query) {
+  return request({
+    url: '/store/store/storeProductPackage/export',
+    method: 'get',
+    params: query
+  })
+}

+ 53 - 0
src/api/hisStore/userOnlineState.js

@@ -0,0 +1,53 @@
+import request from '@/utils/request'
+
+// 查询用户上线情况列表
+export function listUserOnlineState(query) {
+  return request({
+    url: '/store/store/userOnlineState/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 查询用户上线情况详细
+export function getUserOnlineState(userId) {
+  return request({
+    url: '/store/store/userOnlineState/' + userId,
+    method: 'get'
+  })
+}
+
+// 新增用户上线情况
+export function addUserOnlineState(data) {
+  return request({
+    url: '/store/store/userOnlineState',
+    method: 'post',
+    data: data
+  })
+}
+
+// 修改用户上线情况
+export function updateUserOnlineState(data) {
+  return request({
+    url: '/store/store/userOnlineState',
+    method: 'put',
+    data: data
+  })
+}
+
+// 删除用户上线情况
+export function delUserOnlineState(userId) {
+  return request({
+    url: '/store/store/userOnlineState/' + userId,
+    method: 'delete'
+  })
+}
+
+// 导出用户上线情况
+export function exportUserOnlineState(query) {
+  return request({
+    url: '/store/store/userOnlineState/export',
+    method: 'get',
+    params: query
+  })
+}

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

@@ -286,4 +286,14 @@ export function delLossStatistics(query) {
     method: 'get',
     params: query
   })
+}
+
+
+// 导出企业微信客户
+export function delLossStatisticsExport(query) {
+  return request({
+    url: '/qw/externalContact/delLossStatisticsExport',
+    method: 'get',
+    params: query
+  })
 }

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

@@ -77,3 +77,12 @@ export function sendMsgSopType(data) {
     data: data
   })
 }
+
+//一键群发(最外层)
+export function sendMsg(data) {
+  return request({
+    url: '/qwSop/sopUserLogsInfo/sendUserLogsInfoMsgSop',
+    method: 'post',
+    data: data
+  })
+}

+ 6 - 6
src/api/users/user.js

@@ -2,21 +2,21 @@ import request from '@/utils/request'
 
 export function list(query) {
   return request({
-    url: '/users/user/list',
+    url: '/store/user/list',
     method: 'get',
     params: query
   })
 }
 export function myList(query) {
   return request({
-    url: '/users/user/myList',
+    url: '/store/user/myList',
     method: 'get',
     params: query
   })
 }
 export function getUser(userId) {
   return request({
-    url: '/users/user/' + userId,
+    url: '/store/user/' + userId,
     method: 'get'
   })
 }
@@ -40,7 +40,7 @@ export function transferUser(data) {
 }
 export function getUserList(query) {
   return request({
-    url: '/users/user/getUserList',
+    url: '/store/user/getUserList',
     method: 'get',
     params: query
   })
@@ -49,7 +49,7 @@ export function getUserList(query) {
 // 新增用户
 export function addUser(data) {
   return request({
-    url: '/users/user',
+    url: '/store/user',
     method: 'post',
     data: data
   })
@@ -58,7 +58,7 @@ export function addUser(data) {
 // 修改用户
 export function updateUser(data) {
   return request({
-    url: '/users/user',
+    url: '/store/user',
     method: 'put',
     data: data
   })

二进制
src/assets/logo/hyt.png


+ 130 - 0
src/views/company/companyUser/index.vue

@@ -110,6 +110,37 @@
           <el-table-column label="员工后台昵称" align="center" prop="nickName" :show-overflow-tooltip="true" 员工后台  width="100"/>
           <el-table-column label="部门" align="center" prop="deptName" :show-overflow-tooltip="true" />
           <el-table-column label="手机号码" align="center" prop="phonenumber" width="120" />
+          <el-table-column label="二维码" align="center" prop="qrCodeWeixin">
+            <template slot-scope="scope">
+              <!-- 显示已上传的二维码 -->
+              <el-image
+                v-if="scope.row.qrCodeWeixin"
+                style="width: 80px; height: 80px; margin-bottom: 5px; display: block; margin-left: auto; margin-right: auto;"
+                :src="scope.row.qrCodeWeixin"
+                :preview-src-list="[scope.row.qrCodeWeixin]"
+                fit="contain">
+                <div slot="error" class="image-slot">
+                  <i class="el-icon-picture-outline"></i>
+                </div>
+              </el-image>
+              <!-- 上传组件 -->
+              <el-upload
+                class="avatar-uploader"
+                action="#"
+                :show-file-list="false"
+                :http-request="(options) => handleCustomUpload(options, scope.row)"
+                :before-upload="(file) => beforeImageUpload(file, scope.row)"
+              >
+                <el-button size="small" type="primary" :loading="scope.row.uploading">
+                  {{ scope.row.qrCodeWeixin ? '更换图片' : '上传图片' }}
+                  <i class="el-icon-upload el-icon--right"></i>
+                </el-button>
+              </el-upload>
+              <div v-if="scope.row.uploadError" class="el-upload__tip" style="color: red;">
+                {{ scope.row.uploadError }}
+              </div>
+            </template>
+          </el-table-column>
           <el-table-column label="状态" align="center">
             <template slot-scope="scope">
               <el-switch v-model="scope.row.status" active-value="0" inactive-value="1" @change="handleStatusChange(scope.row)"></el-switch>
@@ -468,11 +499,13 @@ import { syncDept } from '@/api/qw/qwDept';
 import { getMyQwUserList,getMyQwCompanyList } from "@/api/qw/user";
 import  selectUser  from "@/views/company/components/selectQwUser.vue";
 import { getConfigByKey } from "@/api/company/companyConfig";
+import axios from "axios";
 export default {
   name: "User",
   components: { Treeselect ,selectUser},
   data() {
     return {
+      uploadUrl: process.env.VUE_APP_BASE_API+"/company/user/common/uploadOSS",
       // 遮罩层
       loading: false,
       qwUserList:[],
@@ -1108,7 +1141,104 @@ export default {
         }
       });
     },
+    /**
+     * 上传文件之前的钩子,参数为上传的文件,若返回 false 或者返回 Promise且被 reject,则停止上传。
+     * @param {File} file - 用户选择的文件对象
+     * @param {Object} row - 当前行的数据对象
+     */
+    beforeImageUpload(file, row) {
+      // 清除之前的错误信息
+      this.$set(row, 'uploadError', '');
+      const isJPG = file.type === 'image/jpeg';
+      const isPNG = file.type === 'image/png';
+      const isGIF = file.type === 'image/gif'; // 根据需要添加更多格式
+      const isValidFormat = isJPG || isPNG || isGIF;
+      const isLt2M = file.size / 1024 / 1024 < 2; // 限制图片大小为 2MB
+      if (!isValidFormat) {
+        const errorMsg = '上传二维码图片只能是 JPG/PNG/GIF 格式!';
+        this.$message.error(errorMsg);
+        this.$set(row, 'uploadError', errorMsg); // 在行内显示错误
+        return false;
+      }
+      if (!isLt2M) {
+        const errorMsg = '上传二维码图片大小不能超过 2MB!';
+        this.$message.error(errorMsg);
+        this.$set(row, 'uploadError', errorMsg); // 在行内显示错误
+        return false;
+      }
+      return true; // 校验通过,允许上传
+    },
+    /**
+     * 自定义上传方法
+     * @param {Object} options - Element UI upload 组件传递的参数,包含 file, onSuccess, onError, onProgress 等
+     * @param {Object} row - 当前行的数据对象
+     */
+    async handleCustomUpload(options, row) {
+
+      const file = options.file;
+      const formData = new FormData();
+      formData.append('file', file);
 
+      formData.append('userId',row.userId)
+
+      this.$set(row, 'uploading', true);
+      this.$set(row, 'uploadError', '');
+      try {
+        const response = await axios.post(this.uploadUrl, formData, {
+          headers: {
+            'Content-Type': 'multipart/form-data',
+          },
+          onUploadProgress: progressEvent => {
+            const percentCompleted = Math.round((progressEvent.loaded * 100) / progressEvent.total);
+            console.log(`上传进度: ${percentCompleted}%`);
+          }
+        });
+        if (response.data && (response.data.url || (response.data.data && response.data.data.url))) {
+          const imageUrl = response.data.url || response.data.data.url;
+          this.$set(row, 'qrCodeWeixin', imageUrl); // 更新行数据中的图片URL
+          this.$message.success('图片上传成功!');
+          options.onSuccess(response.data, file); // 通知el-upload上传成功 (虽然我们自定义了,但调用一下也无妨)
+        } else {
+          const errorMsg = response.data.message || '图片上传失败,服务器未返回有效URL';
+          this.$message.error(errorMsg);
+          this.$set(row, 'uploadError', errorMsg);
+          options.onError(new Error(errorMsg), file); // 通知el-upload上传失败
+        }
+      } catch (error) {
+        console.error('上传失败:', error);
+        let errorMsg = '图片上传失败';
+        if (error.response && error.response.data && error.response.data.message) {
+          errorMsg = error.response.data.message;
+        } else if (error.message) {
+          errorMsg = error.message;
+        }
+        this.$message.error(errorMsg);
+        this.$set(row, 'uploadError', errorMsg);
+        options.onError(error, file); // 通知el-upload上传失败
+      } finally {
+        this.$set(row, 'uploading', false); // 无论成功失败,结束上传状态
+      }
+    },
+    requestUpload() {
+    },
+    beforeUpload(){
+      console.log(file.type)
+      const isPic =
+        file.type === 'image/jpeg' ||
+        file.type === 'image/png' ||
+        file.type === 'image/gif' ||
+        file.type === 'image/jpg' ||
+        file.type === 'audio/mpeg'
+      const isLt2M = file.size / 1024 / 1024 < 2
+      if (!isPic) {
+        this.$message.error('上传图片只能是 JPG、JPEG、PNG、GIF 格式!')
+        return false
+      }
+      if (!isLt2M) {
+        this.$message.error('上传头像图片大小不能超过 2MB!')
+      }
+      return isPic && isLt2M
+    },
   },
 };
 </script>

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

@@ -0,0 +1,426 @@
+<template>
+  <div class="app-container">
+    <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
+      <el-form-item label="名称" prop="name">
+        <el-input
+          v-model="queryParams.name"
+          placeholder="请输入名称"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="appid" prop="appid">
+        <el-input
+          v-model="queryParams.appid"
+          placeholder="请输入appid"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item>
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
+      </el-form-item>
+    </el-form>
+
+    <el-row :gutter="10" class="mb8">
+      <el-col :span="1.5">
+        <el-button
+          type="primary"
+          plain
+          icon="el-icon-plus"
+          size="mini"
+          @click="handleAdd"
+          v-hasPermi="['course:playSourceConfig:add']"
+        >新增</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="success"
+          plain
+          icon="el-icon-edit"
+          size="mini"
+          :disabled="single"
+          @click="handleUpdate"
+          v-hasPermi="['course:playSourceConfig:edit']"
+        >修改</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="danger"
+          plain
+          icon="el-icon-delete"
+          size="mini"
+          :disabled="multiple"
+          @click="handleDelete"
+          v-hasPermi="['course:playSourceConfig:remove']"
+        >删除</el-button>
+      </el-col>
+      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+
+    <!-- 开关配置对话框 -->
+    <el-dialog title="开关配置" :visible.sync="switchDialogVisible" width="500px" class="switch-dialog">
+      <el-form :model="switchForm" label-width="100px">
+        <el-form-item label="AppId">
+          <el-input v-model="switchForm.appId" :disabled="true"></el-input>
+        </el-form-item>
+        <el-form-item label="开关状态">
+          <el-switch
+            v-model="switchForm.switchStatus"
+            active-text="开启"
+            inactive-text="关闭"
+            active-value="001"
+            inactive-value="002">
+          </el-switch>
+        </el-form-item>
+        <el-form-item label="配置信息" v-if="switchForm.configInfo">
+          <el-input
+            type="textarea"
+            :rows="4"
+            v-model="switchForm.configInfo"
+            :disabled="true">
+          </el-input>
+        </el-form-item>
+      </el-form>
+      <span slot="footer" class="dialog-footer">
+                <el-button @click="switchDialogVisible = false">取 消</el-button>
+                <el-button type="primary" @click="submitSwitchConfig">确 定</el-button>
+            </span>
+    </el-dialog>
+
+    <el-table v-loading="loading" :data="list" @selection-change="handleSelectionChange" border>
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="ID" align="center" prop="id" />
+      <el-table-column label="名称" align="center" prop="name" />
+      <el-table-column label="图标" align="center" prop="img">
+        <template slot-scope="scope">
+          <el-image
+            style="width: 80px; height: 80px"
+            :src="scope.row.img"
+            :preview-src-list="[scope.row.img]">
+          </el-image>
+        </template>
+      </el-table-column>
+      <el-table-column label="原始ID" align="center" prop="originalId" />
+      <el-table-column label="appId" align="center" prop="appid" />
+      <el-table-column label="secret" align="center" prop="secret" />
+      <el-table-column label="token" align="center" prop="token" />
+      <el-table-column label="aesKey" align="center" prop="aesKey" />
+      <el-table-column label="msgDataFormat" align="center" prop="msgDataFormat" />
+      <el-table-column label="类型" align="center" prop="type">
+        <template slot-scope="scope">
+          <dict-tag  :options="typesOptions" :value="scope.row.type"/>
+        </template>
+      </el-table-column>
+      <el-table-column label="创建时间" align="center" prop="createTime" />
+      <el-table-column label="修改时间" align="center" prop="updateTime" />
+      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+        <template slot-scope="scope">
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-edit"
+            @click="handleUpdate(scope.row)"
+            v-hasPermi="['course:playSourceConfig:edit']"
+          >修改</el-button>
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-delete"
+            @click="handleDelete(scope.row)"
+            v-hasPermi="['course:playSourceConfig:remove']"
+          >删除</el-button>
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-setting"
+            @click="handleSwitchConfig(scope.row)"
+          >是否展示销售</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <pagination
+      v-show="total>0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    />
+
+    <!-- 添加或修改点播配置对话框 -->
+    <el-dialog :title="title" :visible.sync="open" width="800px" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="130px">
+        <el-form-item label="名称" prop="name">
+          <el-input v-model="form.name" placeholder="请输入名称" />
+        </el-form-item>
+        <el-form-item label="图标" prop="img">
+          <image-upload v-model="form.img" :file-type='["png", "jpg", "jpeg"]' :limit="1"/>
+        </el-form-item>
+        <el-form-item label="类型" prop="type">
+          <el-select
+            v-model="form.type"
+            placeholder="请选择类型">
+            <el-option
+              v-for="item in typesOptions"
+              :key="item.dictValue"
+              :label="item.dictLabel"
+              :value="item.dictValue"/>
+          </el-select>
+        </el-form-item>
+        <el-form-item label="原始id" prop="originalId">
+          <el-input v-model="form.originalId" placeholder="请输入原始id" />
+        </el-form-item>
+        <el-form-item label="appid" prop="appid">
+          <el-input v-model="form.appid" placeholder="请输入appid" />
+        </el-form-item>
+        <el-form-item label="secret" prop="secret">
+          <el-input v-model="form.secret" placeholder="请输入secret" />
+        </el-form-item>
+        <el-form-item label="token" prop="token">
+          <el-input v-model="form.token" placeholder="请输入token" />
+        </el-form-item>
+        <el-form-item label="aesKey" prop="aesKey">
+          <el-input v-model="form.aesKey" placeholder="请输入aesKey" />
+        </el-form-item>
+        <el-form-item label="msgDataFormat" prop="msgDataFormat">
+          <el-input v-model="form.msgDataFormat" placeholder="请输入msgDataFormat" />
+        </el-form-item>
+
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">确 定</el-button>
+        <el-button @click="cancel">取 消</el-button>
+      </div>
+    </el-dialog>
+
+  </div>
+</template>
+
+<script>
+import {list, get, update, add, del, updateIsTownOn} from '@/api/course/coursePlaySourceConfig'
+
+export default {
+  name: 'CoursePlaySourceConfig',
+  data() {
+    return {
+      switchDialogVisible: false,
+      switchForm: {
+        appId: '',
+        switchStatus: '001',
+      },
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        name: null,
+        appid: null
+      },
+      showSearch: true,
+      single: true,
+      multiple: true,
+      ids: [],
+      loading: false,
+      list: [],
+      total: 0,
+      typesOptions: [],
+      title: null,
+      open: false,
+      form: {},
+      rules: {
+        name: [
+          { required: true, message: "名称不能为空", trigger: "blur" }
+        ],
+        appid: [
+          { required: true, message: "appid不能为空", trigger: "blur" }
+        ],
+        img: [
+          { required: true, message: "图标不能为空", trigger: "blur" }
+        ],
+        type: [
+          { required: true, message: "类型不能为空", trigger: "blur" }
+        ],
+        originalId: [
+          { required: true, message: "原始id不能为空", trigger: "blur" }
+        ],
+        secret: [
+          { required: true, message: "secret不能为空", trigger: "blur" }
+        ],
+        token: [
+          { required: true, message: "token不能为空", trigger: "blur" }
+        ],
+        aesKey: [
+          { required: true, message: "aesKey不能为空", trigger: "blur" }
+        ],
+        msgDataFormat: [
+          { required: true, message: "msgDataFormat不能为空", trigger: "blur" }
+        ]
+      }
+    }
+  },
+  created() {
+    this.getDicts("play_source_type").then(response => {
+      this.typesOptions = response.data.map(item =>  {
+        return {
+        ...item,
+        listClass: 'primary'}
+      })
+    });
+    this.getList();
+  },
+  methods: {
+
+
+    // 处理开关配置
+    handleSwitchConfig(row) {
+      this.switchForm.appId = row.appid;
+      this.switchForm.switchStatus = "001"; // 默认关闭状态
+
+      // 调用接口获取开关状态
+      this.getSwitchConfig(row.appid);
+      this.switchDialogVisible = true;
+    },
+
+    // 获取开关配置
+    getSwitchConfig(appId) {
+      const params = {
+        appId: this.switchForm.appId
+      };
+      updateIsTownOn(params).then(response=>{
+        if (response.code === 200) {
+          if ( response.date){
+            this.switchForm.switchStatus = response.date;
+          }
+        } else {
+          this.$message.error('获取配置失败: ' + response.msg);
+        }
+      }).catch(error => {
+        this.$message.error('请求失败: ' + error.message);
+      });
+    },
+
+    // 提交开关配置
+    submitSwitchConfig() {
+      const params = {
+        appId: this.switchForm.appId,
+        bock: this.switchForm.switchStatus
+      };
+      updateIsTownOn(params).then(response=>{
+        if (response.code === 200) {
+          this.$message.success('配置更新成功');
+          this.switchDialogVisible = false;
+        } else {
+          this.$message.error('更新失败: ' + response.msg);
+        }
+      })
+    },
+
+
+    getList() {
+      this.loading = true;
+      list(this.queryParams).then(response => {
+        this.list = response.rows;
+        this.total = response.total;
+        this.loading = false;
+      });
+    },
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.getList();
+    },
+    handleAdd() {
+      this.reset()
+      this.open = true
+      this.title = "添加点播配置"
+    },
+    handleUpdate(row) {
+      this.reset()
+      const id = row.id || this.ids
+      get(id).then(response => {
+        this.form = {
+          ...response.data,
+          type: response.data.type.toString()
+        }
+        this.open = true
+        this.title = "修改点播配置"
+      })
+    },
+    handleDelete(row) {
+      const id = row.id || this.ids
+      this.$confirm('是否确认删除点播配置编号为"' + id + '"的数据项?', "警告", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      }).then(function() {
+        return del(id);
+      }).then(() => {
+        this.getList();
+        this.msgSuccess("删除成功");
+      }).catch(() => {});
+    },
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.id)
+      this.single = selection.length!==1
+      this.multiple = !selection.length
+    },
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          if (this.form.id != null) {
+            update(this.form).then(response => {
+              const {code, msg} = response
+              if (code !== 200) {
+                this.msgError(msg)
+                return
+              }
+              this.msgSuccess("修改成功");
+              this.open = false;
+              this.getList();
+            });
+          } else {
+            add(this.form).then(response => {
+              const {code, msg} = response
+              if (code !== 200) {
+                this.msgError(msg)
+                return
+              }
+              this.msgSuccess("新增成功");
+              this.open = false;
+              this.getList();
+            });
+          }
+        }
+      });
+    },
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    reset() {
+      this.form = {
+        id: null,
+        name: null,
+        appid: null,
+        secret: null,
+        img: null,
+        originalId: null,
+        token: 'cbnd7lJvkripVOpyTFAna6NAWCxCrvC',
+        aesKey: 'HlEiBB55eaWUaeBVAQO3cWKWPYv1vOVQSq7nFNICw4E',
+        msgDataFormat: 'JSON',
+        type: '1'
+      }
+      this.resetForm("form");
+    }
+  },
+}
+</script>
+
+<style scoped>
+
+</style>

+ 4 - 0
src/views/course/courseUserStatistics/index.vue

@@ -311,6 +311,10 @@ export default {
     },
     /** 搜索按钮操作 */
     handleQuery() {
+      if (!this.queryParams.sTime || !this.queryParams.eTime) {
+        this.$message.warning("请选择添加时间");
+        return;
+      }
       this.queryParams.pageNum = 1;
       this.getList();
     },

+ 531 - 151
src/views/course/courseUserStatistics/qw/index.vue

@@ -1,6 +1,43 @@
 <template>
   <div class="app-container">
-    <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
+    <el-form
+      :model="queryParams"
+      ref="queryForm"
+      :inline="true"
+      v-show="showSearch"
+      label-width="68px"
+    >
+      <el-form-item label="部门" prop="type">
+        <treeselect
+          style="width: 220px"
+          :clearable="false"
+          v-model="queryParams.deptId"
+          :options="deptOptions"
+          clearable
+          :show-count="true"
+          placeholder="请选择归属部门"
+        />
+      </el-form-item>
+      <el-form-item label="所属客服" prop="companyUserId">
+        <el-select
+          v-model="queryParams.companyUserId"
+          clearable
+          filterable
+          remote
+          placeholder="请输入关键词"
+          :remote-method="loadCompanyUserOptions"
+          v-select-load-more="loadMoreCompanyUserOptions"
+          :loading="companyUserOptionsLoading"
+        >
+          <el-option
+            v-for="item in companyUserOptions"
+            :key="item.value"
+            :label="item.label"
+            :value="item.value"
+          >
+          </el-option>
+        </el-select>
+      </el-form-item>
       <el-form-item label="企微昵称" prop="nickName">
         <el-input
           v-model="queryParams.nickName"
@@ -10,144 +47,353 @@
           @keyup.enter.native="handleQuery"
         />
       </el-form-item>
+
       <el-form-item label="添加时间" prop="createTime">
-        <el-date-picker v-model="createTime" size="small" style="width: 220px" value-format="yyyy-MM-dd" type="daterange" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" @change="change"></el-date-picker>
+        <el-date-picker
+          v-model="createTime"
+          size="small"
+          style="width: 220px"
+          value-format="yyyy-MM-dd"
+          type="daterange"
+          range-separator="-"
+          start-placeholder="开始日期"
+          end-placeholder="结束日期"
+          @change="change"
+        ></el-date-picker>
       </el-form-item>
       <el-form-item>
-        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
-        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
+        <el-button
+          type="primary"
+          icon="el-icon-search"
+          size="mini"
+          @click="handleQuery"
+          >搜索</el-button
+        >
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery"
+          >重置</el-button
+        >
       </el-form-item>
     </el-form>
-
-    <el-table border v-loading="loading" :data="courseWatchLogList" @selection-change="handleSelectionChange"  show-summary height="600">
+    <el-row :gutter="10" class="mb8">
+      <el-col :span="1.5">
+        <el-button
+          type="warning"
+          plain
+          icon="el-icon-download"
+          size="mini"
+          :loading="exportLoading"
+          @click="handleExport"
+          v-hasPermi="['course:courseRedPacketLog: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
+      :summary-method="getSummaries"
+      ref="table1"
+    >
       <el-table-column type="selection" width="55" align="center" />
-        <el-table-column label="企微员工名称" align="center" prop="qwUserName" />
+      <el-table-column label="企微员工名称" align="center" prop="qwUserName" />
+
+      <!-- 发课时间 -->
+      <el-table-column label="进线时间" align="center" prop="createTime" />
+      <!-- 进线数 -->
+      <el-table-column label="进线数" align="center" prop="line" />
+
+      <!-- 先导课上线 -->
+      <el-table-column label="先导课上线" align="center" prop="firstOnline">
+        <template slot-scope="scope">
+          <span>{{ scope.row.firstOnline }}</span>
+          <span
+            :style="{
+              'font-size': '12px',
+              'margin-left': '5px',
+              color: getPercentageColor(
+                (scope.row.firstOnline / scope.row.line) * 100
+              ),
+            }"
+          >
+            ({{ ((scope.row.firstOnline / scope.row.line) * 100).toFixed(2) }}%)
+          </span>
+        </template>
+      </el-table-column>
 
-            <!-- 发课时间 -->
-            <el-table-column label="进线时间" align="center" prop="createTime"/>
-            <!-- 进线数 -->
-            <el-table-column label="进线数" align="center" prop="line" />
+      <!-- 先导课完课 -->
+      <el-table-column label="先导课完课" align="center" prop="firstOver">
+        <template slot-scope="scope">
+          <span>{{ scope.row.firstOver }}</span>
+          <span
+            :style="{
+              'font-size': '12px',
+              'margin-left': '5px',
+              color: getPercentageColor(
+                (scope.row.firstOver / scope.row.line) * 100
+              ),
+            }"
+          >
+            ({{ ((scope.row.firstOver / scope.row.line) * 100).toFixed(2) }}%)
+          </span>
+        </template>
+      </el-table-column>
 
-            <!-- 先导课上线 -->
-            <el-table-column label="先导课上线" align="center" prop="firstOnline">
-                <template slot-scope="scope">
-                    <span>{{ scope.row.firstOnline }}</span>
-                    <span style="font-size: 12px; color: #959595;margin-left: 5px;">({{ ((scope.row.firstOnline / scope.row.line) * 100).toFixed(2) }}%)</span>
-                </template>
-            </el-table-column>
+      <!-- 首日上线 -->
+      <el-table-column label="首日上线" align="center" prop="d1Online">
+        <template slot-scope="scope">
+          <span>{{ scope.row.d1Online }}</span>
+          <span
+            :style="{
+              'font-size': '12px',
+              'margin-left': '5px',
+              color: getPercentageColor(
+                (scope.row.d1Online / scope.row.line) * 100
+              ),
+            }"
+          >
+            ({{ ((scope.row.d1Online / scope.row.line) * 100).toFixed(2) }}%)
+          </span>
+        </template>
+      </el-table-column>
 
-            <!-- 先导课完课 -->
-            <el-table-column label="先导课完课" align="center" prop="firstOver">
-                <template slot-scope="scope">
-                    <span>{{ scope.row.firstOver }}</span>
-                    <span style="font-size: 12px; color: #959595;margin-left: 5px;">({{ ((scope.row.firstOver / scope.row.line) * 100).toFixed(2) }}%)</span>
-                </template>
-            </el-table-column>
+      <!-- 首日完课 -->
+      <el-table-column label="首日完课" align="center" prop="d1Over">
+        <template slot-scope="scope">
+          <span>{{ scope.row.d1Over }}</span>
+          <span
+            :style="{
+              'font-size': '12px',
+              'margin-left': '5px',
+              color: getPercentageColor(
+                (scope.row.d1Over / scope.row.line) * 100
+              ),
+            }"
+          >
+            ({{ ((scope.row.d1Over / scope.row.line) * 100).toFixed(2) }}%)
+          </span>
+        </template>
+      </el-table-column>
 
-            <!-- 首日上线 -->
-            <el-table-column label="首日上线" align="center" prop="d1Online">
-                <template slot-scope="scope">
-                    <span>{{ scope.row.d1Online }}</span>
-                    <span style="font-size: 12px; color: #959595;margin-left: 5px;">({{ ((scope.row.d1Online / scope.row.line) * 100).toFixed(2) }}%)</span>
-                </template>
-            </el-table-column>
+      <!-- 综合报名数 -->
+      <el-table-column label="综合报名数" align="center" prop="sign">
+        <template slot-scope="scope">
+          <span>{{ scope.row.sign }}</span>
+          <span
+            :style="{
+              'font-size': '12px',
+              'margin-left': '5px',
+              color: getPercentageColor(
+                (scope.row.sign / scope.row.line) * 100
+              ),
+            }"
+          >
+            ({{ ((scope.row.sign / scope.row.line) * 100).toFixed(2) }}%)
+          </span>
+        </template>
+      </el-table-column>
 
-            <!-- 首日完课 -->
-            <el-table-column label="首日完课" align="center" prop="d1Over">
-                <template slot-scope="scope">
-                    <span>{{ scope.row.d1Over }}</span>
-                    <span style="font-size: 12px; color: #959595;margin-left: 5px;">({{ ((scope.row.d1Over / scope.row.line) * 100).toFixed(2) }}%)</span>
-                </template>
-            </el-table-column>
+      <!-- 互动数 -->
+      <el-table-column label="互动数" align="center" prop="interact">
+        <template slot-scope="scope">
+          <span>{{ scope.row.interact }}</span>
+          <span
+            :style="{
+              'font-size': '12px',
+              'margin-left': '5px',
+              color: getPercentageColor(
+                (scope.row.interact / scope.row.line) * 100
+              ),
+            }"
+          >
+            ({{ ((scope.row.interact / scope.row.line) * 100).toFixed(2) }}%)
+          </span>
+        </template>
+      </el-table-column>
 
-            <!-- 综合报名数 -->
-            <el-table-column label="综合报名数" align="center" prop="sign">
-                <template slot-scope="scope">
-                    <span>{{ scope.row.sign }}</span>
-                    <span style="font-size: 12px; color: #959595;margin-left: 5px;">({{ ((scope.row.sign / scope.row.line) * 100).toFixed(2) }}%)</span>
-                </template>
-            </el-table-column>
+      <!-- A级客户 -->
+      <el-table-column label="A级客户" align="center" prop="a">
+        <template slot-scope="scope">
+          <span>{{ scope.row.a }}</span>
+          <span
+            :style="{
+              'font-size': '12px',
+              'margin-left': '5px',
+              color: getPercentageColor((scope.row.a / scope.row.line) * 100),
+            }"
+          >
+            ({{ ((scope.row.a / scope.row.line) * 100).toFixed(2) }}%)
+          </span>
+        </template>
+      </el-table-column>
 
-            <!-- 互动数 -->
-            <el-table-column label="互动数" align="center" prop="interact">
-                <template slot-scope="scope">
-                    <span>{{ scope.row.interact }}</span>
-                    <span style="font-size: 12px; color: #959595;margin-left: 5px;">({{ ((scope.row.interact / scope.row.line) * 100).toFixed(2) }}%)</span>
-                </template>
-            </el-table-column>
+      <!-- B级客户 -->
+      <el-table-column label="B级客户" align="center" prop="b">
+        <template slot-scope="scope">
+          <span>{{ scope.row.b }}</span>
 
-            <!-- A级客户 -->
-            <el-table-column label="A级客户" align="center" prop="a">
-                <template slot-scope="scope">
-                    <span>{{ scope.row.a }}</span>
-                    <span style="font-size: 12px; color: #959595;margin-left: 5px;">({{ ((scope.row.a / scope.row.line) * 100).toFixed(2) }}%)</span>
-                </template>
-            </el-table-column>
+          <span
+            :style="{
+              'font-size': '12px',
+              'margin-left': '5px',
+              color: getPercentageColor((scope.row.b / scope.row.line) * 100),
+            }"
+          >
+            ({{ ((scope.row.b / scope.row.line) * 100).toFixed(2) }}%)
+          </span>
+        </template>
+      </el-table-column>
 
-            <!-- B级客户 -->
-            <el-table-column label="B级客户" align="center" prop="b">
-                <template slot-scope="scope">
-                    <span>{{ scope.row.b }}</span>
-                    <span style="font-size: 12px; color: #959595;margin-left: 5px;">({{ ((scope.row.b / scope.row.line) * 100).toFixed(2) }}%)</span>
-                </template>
-            </el-table-column>
+      <!-- C级客户 -->
+      <el-table-column label="C级客户" align="center" prop="c">
+        <template slot-scope="scope">
+          <span>{{ scope.row.c }}</span>
 
-            <!-- C级客户 -->
-            <el-table-column label="C级客户" align="center" prop="c">
-                <template slot-scope="scope">
-                    <span>{{ scope.row.c }}</span>
-                    <span style="font-size: 12px; color: #959595;margin-left: 5px;">({{ ((scope.row.c / scope.row.line) * 100).toFixed(2) }}%)</span>
-                </template>
-            </el-table-column>
+          <span
+            :style="{
+              'font-size': '12px',
+              'margin-left': '5px',
+              color: getPercentageColor((scope.row.c / scope.row.line) * 100),
+            }"
+          >
+            ({{ ((scope.row.c / scope.row.line) * 100).toFixed(2) }}%)
+          </span>
+        </template>
+      </el-table-column>
 
-            <!-- D级客户 -->
-            <el-table-column label="D级客户" align="center" prop="d">
-                <template slot-scope="scope">
-                    <span>{{ scope.row.d }}</span>
-                    <span style="font-size: 12px; color: #959595;margin-left: 5px;">({{ ((scope.row.d / scope.row.line) * 100).toFixed(2) }}%)</span>
-                </template>
-            </el-table-column>
+      <!-- D级客户 -->
+      <el-table-column label="D级客户" align="center" prop="d">
+        <template slot-scope="scope">
+          <span>{{ scope.row.d }}</span>
+          <span
+            :style="{
+              'font-size': '12px',
+              'margin-left': '5px',
+              color: getPercentageColor((scope.row.d / scope.row.line) * 100),
+            }"
+          >
+            ({{ ((scope.row.d / scope.row.line) * 100).toFixed(2) }}%)
+          </span>
+        </template>
+      </el-table-column>
 
-            <!-- 流失数 -->
-            <el-table-column label="流失数" align="center" prop="los">
-                <template slot-scope="scope">
-                    <span>{{ scope.row.los }}</span>
-                    <span style="font-size: 12px; color: #959595;margin-left: 5px;">({{ ((scope.row.los / scope.row.line) * 100).toFixed(2) }}%)</span>
-                </template>
-            </el-table-column>
+      <!-- E级客户 -->
+      <el-table-column label="E级客户" align="center" prop="e">
+        <template slot-scope="scope">
+          <span>{{ scope.row.e }}</span>
+          <span
+            :style="{
+              'font-size': '12px',
+              'margin-left': '5px',
+              color: getPercentageColor((scope.row.e / scope.row.line) * 100),
+            }"
+          >
+            ({{ ((scope.row.e / scope.row.line) * 100).toFixed(2) }}%)
+          </span>
+        </template>
+      </el-table-column>
+      <!-- 流失数 -->
+      <el-table-column label="拉黑数" align="center" prop="black">
+        <template slot-scope="scope">
+          <span>{{ scope.row.black }}</span>
+          <span
+            :style="{
+              'font-size': '12px',
+              'margin-left': '5px',
+              color: getPercentageColor((scope.row.black / scope.row.line) * 100),
+            }"
+          >
+            ({{ ((scope.row.black / scope.row.line) * 100).toFixed(2) }}%)
+          </span>
+        </template>
+      </el-table-column>
 
-            <!-- 删除数 -->
-            <el-table-column label="删除数" align="center" prop="del">
-                <template slot-scope="scope">
-                    <span>{{ scope.row.del }}</span>
-                    <span style="font-size: 12px; color: #959595;margin-left: 5px;">({{ ((scope.row.del / scope.row.line) * 100).toFixed(2) }}%)</span>
-                </template>
-            </el-table-column>
+      <!-- 流失数 -->
+      <!--<el-table-column label="流失数" align="center" prop="los">
+        <template slot-scope="scope">
+          <span>{{ scope.row.los }}</span>
+          <span
+            :style="{
+              'font-size': '12px',
+              'margin-left': '5px',
+              color: getPercentageColor((scope.row.los / scope.row.line) * 100),
+            }"
+          >
+            ({{ ((scope.row.los / scope.row.line) * 100).toFixed(2) }}%)
+          </span>
+        </template>
+      </el-table-column>-->
+
+      <!-- 删除数 -->
+      <el-table-column label="删除数" align="center" prop="del">
+        <template slot-scope="scope">
+          <span>{{ scope.row.del }}</span>
+          <span
+            :style="{
+              'font-size': '12px',
+              'margin-left': '5px',
+              color: getPercentageColor((scope.row.del / scope.row.line) * 100),
+            }"
+          >
+            ({{ ((scope.row.del / scope.row.line) * 100).toFixed(2) }}%)
+          </span>
+        </template>
+      </el-table-column>
     </el-table>
 
-    <pagination
-      v-show="total>0"
+    <pagination-more
+      v-show="total > 0"
       :total="total"
       :page.sync="queryParams.pageNum"
       :limit.sync="queryParams.pageSize"
       @pagination="getList"
     />
-
   </div>
 </template>
 
 <script>
-import { listCourseWatchLog, getCourseWatchLog, delCourseWatchLog, addCourseWatchLog, updateCourseWatchLog, exportCourseWatchLog,statisticsList,qwWatchLogStatisticsList } from "@/api/course/qw/courseWatchLog";
-import { courseList,videoList } from '@/api/course/courseRedPacketLog'
+import {
+  listCourseWatchLog,
+  getCourseWatchLog,
+  delCourseWatchLog,
+  addCourseWatchLog,
+  updateCourseWatchLog,
+  exportCourseWatchLog,
+  statisticsList,
+  qwWatchLogStatisticsList,
+  exportWatchLogStatistics
+} from "@/api/course/qw/courseWatchLog";
+import { courseList, videoList } from "@/api/course/courseRedPacketLog";
+import { treeselect } from "@/api/company/companyDept";
+import Treeselect from "@riophae/vue-treeselect";
+import "@riophae/vue-treeselect/dist/vue-treeselect.css";
+import { getCompanyUserListLikeName } from "@/api/company/companyUser";
+import { getTask } from "@/api/common";
 export default {
   name: "CourseWatchLog",
+  components: { Treeselect },
   data() {
     return {
-      activeName:"00",
-      createTime:null,
-      courseLists:[],
-      videoList:[],
-      logTypeOptions:[],
+      activeName: "00",
+      createTime: null,
+      courseLists: [],
+      companyUserOptionsParams: {
+        name: undefined,
+        hasNextPage: false,
+        pageNum: 1,
+        pageSize: 10,
+      },
+      companyUserOptionsLoading: false,
+      companyUserOptions: [],
+      deptOptions: [],
+      videoList: [],
+      logTypeOptions: [],
       // 遮罩层
       loading: true,
       // 导出遮罩层
@@ -182,39 +428,136 @@ export default {
         companyUserId: null,
         companyId: null,
         courseId: null,
-        sTime:null,
-        eTime:null,
+        sTime: null,
+        eTime: null,
         scheduleStartTime: null,
         scheduleEndTime: null,
       },
       // 表单参数
       form: {},
       // 表单校验
-      rules: {
-      },
+      rules: {},
       scheduleTime: null,
     };
   },
   created() {
-    courseList().then(response => {
+    courseList().then((response) => {
       this.courseLists = response.list;
     });
-    this.getList();
-    this.getDicts("sys_course_watch_log_type").then(response => {
+
+    this.getDicts("sys_course_watch_log_type").then((response) => {
       this.logTypeOptions = response.data;
     });
+    this.getTreeselect();
+    this.getList();
   },
   methods: {
-    courseChange(row){
-      this.queryParams.videoId=null;
-      if(row === ''){
-        this.videoList=[];
-        return
+    getSummaries(param) {
+      const { columns, data } = param;
+      const sums = [];
+      columns.forEach((column, index) => {
+        if (index === 0) {
+          sums[index] = "总计";
+          return;
+        }
+
+        const values = data.map((item) => Number(item[column.property]));
+        if (!values.every((value) => isNaN(value))) {
+          sums[index] = values.reduce((prev, curr) => {
+            const value = Number(curr);
+            if (!isNaN(value)) {
+              return prev + curr;
+            } else {
+              return prev;
+            }
+          }, 0);
+
+          if (
+            column.property === "firstOnline" ||
+            column.property === "firstOver" ||
+            column.property === "d1Online" ||
+            column.property === "d1Over" ||
+            column.property === "sign" ||
+            column.property === "interact" ||
+            column.property === "a" ||
+            column.property === "b" ||
+            column.property === "c" ||
+            column.property === "d" ||
+            column.property === "e" ||
+            column.property === "black" ||
+            column.property === "los" ||
+            column.property === "del"
+          ) {
+          }
+        } else {
+          sums[index] = "";
+        }
+      });
+
+      return sums;
+    },
+    getPercentageColor(percentage) {
+      // HSL模式从黄色(60度)渐变到红色(0度)
+      const percent = Math.min(100, Math.max(0, parseFloat(percentage)));
+
+      // 调整色相范围:从深黄色(40°)渐变到红色(0°)
+      const hue = 40 - 40 * (percent / 100); // 初始 hue=40(深黄),终点 hue=0(红)
+
+      // 提高饱和度(100%),亮度保持 50%(鲜艳但不刺眼)
+      return `hsl(${hue}, 100%, 50%)`;
+    },
+    courseChange(row) {
+      this.queryParams.videoId = null;
+      if (row === "") {
+        this.videoList = [];
+        return;
       }
-      videoList(row).then(response => {
-        this.videoList=response.list
+      videoList(row).then((response) => {
+        this.videoList = response.list;
+      });
+    },
+    getTreeselect() {
+      var that = this;
+      var param = { companyId: this.companyId };
+      treeselect(param).then((response) => {
+        this.deptOptions = response.data;
+        console.log(this.deptOptions);
+        if (response.data != null && response.data.length > 0) {
+          //this.queryParams.deptId=response.data[0].id;
+        }
       });
     },
+    loadCompanyUserOptions(query) {
+      this.companyUserOptions = [];
+      if (query === "") {
+        return;
+      }
+
+      this.companyUserOptionsParams.pageNum = 1;
+      this.companyUserOptionsParams.name = query;
+      this.companyUserOptionsLoading = true;
+      this.getCompanyUserListLikeName();
+    },
+    getCompanyUserListLikeName() {
+      getCompanyUserListLikeName(this.companyUserOptionsParams).then(
+        (response) => {
+          this.companyUserOptions = [
+            ...this.companyUserOptions,
+            ...response.data.list,
+          ];
+          this.companyUserOptionsParams.hasNextPage = response.data.hasNextPage;
+          this.companyUserOptionsLoading = false;
+        }
+      );
+    },
+    loadMoreCompanyUserOptions() {
+      if (!this.companyUserOptionsParams.hasNextPage) {
+        return;
+      }
+
+      this.companyUserOptionsParams.pageNum += 1;
+      this.getCompanyUserListLikeName();
+    },
     change() {
       if (this.createTime != null) {
         this.queryParams.sTime = this.createTime[0];
@@ -224,23 +567,28 @@ export default {
         this.queryParams.eTime = null;
       }
     },
-    handleClickX(tab,event){
-      this.activeName=tab.name;
-      if(tab.name=="00"){
-        this.queryParams.logType=null;
-      }else{
-        this.queryParams.logType=tab.name;
+    handleClickX(tab, event) {
+      this.activeName = tab.name;
+      if (tab.name == "00") {
+        this.queryParams.logType = null;
+      } else {
+        this.queryParams.logType = tab.name;
       }
-      this.getList()
+      this.getList();
     },
     /** 查询短链课程看课记录列表 */
     getList() {
       this.loading = true;
-      qwWatchLogStatisticsList(this.queryParams).then(response => {
+      qwWatchLogStatisticsList(this.queryParams).then((response) => {
         this.courseWatchLogList = response.rows;
         this.total = response.total;
         this.loading = false;
       });
+      this.$nextTick(() => {
+        setTimeout(() => {
+          this.$refs.table1?.doLayout();
+        }, 2000);
+      });
     },
     // 取消按钮
     cancel() {
@@ -261,12 +609,16 @@ export default {
         qwUserId: null,
         companyUserId: null,
         companyId: null,
-        courseId: null
+        courseId: null,
       };
       this.resetForm("form");
     },
     /** 搜索按钮操作 */
     handleQuery() {
+      if (!this.queryParams.sTime || !this.queryParams.eTime) {
+        this.$message.warning("请选择添加时间");
+        return;
+      }
       this.queryParams.pageNum = 1;
       this.getList();
     },
@@ -283,9 +635,9 @@ export default {
     },
     // 多选框选中数据
     handleSelectionChange(selection) {
-      this.ids = selection.map(item => item.logId)
-      this.single = selection.length!==1
-      this.multiple = !selection.length
+      this.ids = selection.map((item) => item.logId);
+      this.single = selection.length !== 1;
+      this.multiple = !selection.length;
     },
     /** 新增按钮操作 */
     handleAdd() {
@@ -296,8 +648,8 @@ export default {
     /** 修改按钮操作 */
     handleUpdate(row) {
       this.reset();
-      const logId = row.logId || this.ids
-      getCourseWatchLog(logId).then(response => {
+      const logId = row.logId || this.ids;
+      getCourseWatchLog(logId).then((response) => {
         this.form = response.data;
         this.open = true;
         this.title = "修改短链课程看课记录";
@@ -305,16 +657,16 @@ export default {
     },
     /** 提交按钮 */
     submitForm() {
-      this.$refs["form"].validate(valid => {
+      this.$refs["form"].validate((valid) => {
         if (valid) {
           if (this.form.logId != null) {
-            updateCourseWatchLog(this.form).then(response => {
+            updateCourseWatchLog(this.form).then((response) => {
               this.msgSuccess("修改成功");
               this.open = false;
               this.getList();
             });
           } else {
-            addCourseWatchLog(this.form).then(response => {
+            addCourseWatchLog(this.form).then((response) => {
               this.msgSuccess("新增成功");
               this.open = false;
               this.getList();
@@ -326,31 +678,59 @@ export default {
     /** 删除按钮操作 */
     handleDelete(row) {
       const logIds = row.logId || this.ids;
-      this.$confirm('是否确认删除短链课程看课记录编号为"' + logIds + '"的数据项?', "警告", {
+      this.$confirm(
+        '是否确认删除短链课程看课记录编号为"' + logIds + '"的数据项?',
+        "警告",
+        {
           confirmButtonText: "确定",
           cancelButtonText: "取消",
-          type: "warning"
-        }).then(function() {
+          type: "warning",
+        }
+      )
+        .then(function () {
           return delCourseWatchLog(logIds);
-        }).then(() => {
+        })
+        .then(() => {
           this.getList();
           this.msgSuccess("删除成功");
-        }).catch(() => {});
+        })
+        .catch(() => {});
     },
     /** 导出按钮操作 */
     handleExport() {
+      let that = this;
       const queryParams = this.queryParams;
-      this.$confirm('是否确认导出所有短链课程看课记录数据项?', "警告", {
-          confirmButtonText: "确定",
-          cancelButtonText: "取消",
-          type: "warning"
-        }).then(() => {
+      this.$confirm("是否确认导出所有进线客户统计记录数据项?", "警告", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning",
+      })
+        .then(() => {
           this.exportLoading = true;
-          return exportCourseWatchLog(queryParams);
-        }).then(response => {
-          this.download(response.msg);
+          // return exportCourseWatchLog(queryParams);
+         return  exportWatchLogStatistics(queryParams);
+        })
+        .then((response) => {
+          console.log(response);
+          if (response.code == 200) {
+            that.msgSuccess(response.msg);
+            that.taskId = response.data;
+            that.time = setInterval(function () {
+              //查订单
+              getTask(that.taskId).then((res) => {
+                if (res.data.status == 1) {
+                  that.exportLoading = false;
+                  clearTimeout(that.time);
+                  that.time = null;
+                  that.download(res.data.fileUrl);
+                }
+              });
+            }, 10000);
+          }
+        })
+        .catch(() => {
           this.exportLoading = false;
-        }).catch(() => {});
+        });
     },
     handleScheduleTimeChange(val) {
       if (val) {
@@ -361,6 +741,6 @@ export default {
         this.queryParams.scheduleEndTime = null;
       }
     },
-  }
+  },
 };
 </script>

+ 4 - 0
src/views/course/courseUserStatistics/qw/statistics.vue

@@ -581,6 +581,10 @@ export default {
     },
     /** 搜索按钮操作 */
     handleQuery() {
+    if (!this.queryParams.sTime || !this.queryParams.eTime) {
+        this.$message.warning("请选择添加时间");
+        return;
+      }
       this.queryParams.pageNum = 1;
       this.getList();
     },

+ 4 - 0
src/views/course/courseUserStatistics/statistics.vue

@@ -626,6 +626,10 @@ export default {
     },
     /** 搜索按钮操作 */
     handleQuery() {
+      if (!this.queryParams.sTime || !this.queryParams.eTime) {
+        this.$message.warning("请选择添加时间");
+        return;
+      }
       this.queryParams.pageNum = 1;
       this.getList();
     },

+ 31 - 3
src/views/course/courseWatchLog/index.vue

@@ -11,7 +11,7 @@
           />
         </el-select>
       </el-form-item>
-      <el-form-item label="会员昵称" prop="nickName">
+      <el-form-item label="会员昵称" prop="nickName" v-if="queryParams.sendType == 1">
         <el-input
           v-model="queryParams.nickName"
           placeholder="请输入会员昵称"
@@ -20,7 +20,16 @@
           @keyup.enter.native="handleQuery"
         />
       </el-form-item>
-      <el-form-item label="企微客户昵称" prop="nickName" >
+      <el-form-item label="会员id" prop="userId" v-if="queryParams.sendType == 1">
+        <el-input
+          v-model="queryParams.userId"
+          placeholder="请输入会员昵称"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="企微客户昵称" prop="nickName" v-if="queryParams.sendType == 2">
         <el-input
           v-model="queryParams.externalUserName"
           placeholder="请输入企微客户昵称"
@@ -29,7 +38,7 @@
           @keyup.enter.native="handleQuery"
         />
       </el-form-item>
-      <el-form-item label="所属销售" prop="companyUserName">
+      <el-form-item label="所属销售" prop="companyUserName" v-if="queryParams.sendType == 1">
         <el-input
           v-model="queryParams.companyUserName"
           placeholder="请输入所属销售"
@@ -122,6 +131,20 @@
           :key="qecCalendarKey"
         />
       </el-form-item>
+      <el-form-item label="是否为会员" prop="isVip">
+        <el-select
+          filterable
+          v-model="queryParams.isVip"
+          placeholder="请选择是否为会员"
+          clearable size="small">
+          <el-option
+            v-for="dict in isVipList"
+            :key="dict.dictValue"
+            :label="dict.dictLabel"
+            :value="dict.dictValue"
+          />
+        </el-select>
+      </el-form-item>
 
       <el-form-item>
         <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
@@ -565,6 +588,10 @@ export default {
         pageSize: 10,
       },
 
+      isVipList: [
+        { dictLabel: '是', dictValue: 1 },
+        { dictLabel: '否', dictValue: 0 }
+      ],
       // 查询参数
       queryParams: {
         pageNum: 1,
@@ -589,6 +616,7 @@ export default {
         scheduleStartTime: null,
         scheduleEndTime: null,
         sendType:process.env.VUE_APP_COURSE_DEFAULT,
+        isVip: null,
       },
       // 表单参数
       form: {},

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

@@ -21,10 +21,10 @@
           />
         </el-select>
       </el-form-item>
-      <el-form-item label="企微昵称" prop="nickName">
+      <el-form-item label="销售昵称" prop="nickName">
         <el-input
           v-model="queryParams.nickName"
-          placeholder="请输入企微昵称"
+          placeholder="请输入销售昵称"
           clearable
           size="small"
           @keyup.enter.native="handleQuery"
@@ -41,7 +41,7 @@
 
     <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" />
+      <el-table-column label="销售昵称" align="center" prop="qwUserName" />
       <el-table-column label="发课时间" align="center" prop="createTime"/>
       <el-table-column label="课程名称" align="center" prop="courseName" />
       <el-table-column label="小节名称" align="center" prop="videoName" />
@@ -49,7 +49,7 @@
       <el-table-column label="看课中" align="center" prop="type1" />
       <el-table-column label="已完课" align="center" prop="type2" />
       <el-table-column label="看课中断" align="center" prop="type4" />
-
+      <el-table-column label="上线数" align="center" prop="onLineNum" />
 
     </el-table>
 

+ 59 - 38
src/views/course/courseWatchLog/watchLog.vue

@@ -11,7 +11,7 @@
           />
         </el-select>
       </el-form-item>
-      <el-form-item label="企微账号" prop="qwUserId">
+      <el-form-item label="企微账号" prop="qwUserId" v-if="queryParams.sendType == 2">
         <el-select v-model="queryParams.qwUserId" placeholder="企微账号" clearable size="small"
                    @change="updateQwuser()">
           <el-option
@@ -22,34 +22,34 @@
           />
         </el-select>
       </el-form-item>
-      <el-form-item label="客户ID" prop="qwExternalContactId">
+      <el-form-item label="客户ID" prop="qwExternalContactId" v-if="queryParams.sendType == 2">
         <el-input
           v-model="queryParams.qwExternalContactId"
-          placeholder="请输入会员ID"
+          placeholder="请输入客户ID"
           clearable
           size="small"
           @keyup.enter.native="handleQuery"
         />
       </el-form-item>
-<!--      <el-form-item label="会员ID" prop="userId">-->
-<!--        <el-input-->
-<!--          v-model="queryParams.userId"-->
-<!--          placeholder="请输入会员ID"-->
-<!--          clearable-->
-<!--          size="small"-->
-<!--          @keyup.enter.native="handleQuery"-->
-<!--        />-->
-<!--      </el-form-item>-->
-<!--      <el-form-item label="会员昵称" prop="nickName">-->
-<!--        <el-input-->
-<!--          v-model="queryParams.nickName"-->
-<!--          placeholder="请输入会员昵称"-->
-<!--          clearable-->
-<!--          size="small"-->
-<!--          @keyup.enter.native="handleQuery"-->
-<!--        />-->
-<!--      </el-form-item>-->
-      <el-form-item label="企微客户昵称" prop="nickName">
+     <el-form-item label="会员ID" prop="userId" v-if="queryParams.sendType == 1">
+       <el-input
+         v-model="queryParams.userId"
+         placeholder="请输入会员ID"
+         clearable
+         size="small"
+         @keyup.enter.native="handleQuery"
+       />
+     </el-form-item>
+     <el-form-item label="会员昵称" prop="nickName" v-if="queryParams.sendType == 1">
+       <el-input
+         v-model="queryParams.nickName"
+         placeholder="请输入会员昵称"
+         clearable
+         size="small"
+         @keyup.enter.native="handleQuery"
+       />
+     </el-form-item>
+      <el-form-item label="企微客户昵称" prop="nickName" v-if="queryParams.sendType == 2">
         <el-input
           v-model="queryParams.externalUserName"
           placeholder="请输入企微客户昵称"
@@ -143,6 +143,20 @@
           :key="qecCalendarKey"
         />
       </el-form-item>
+      <el-form-item label="是否为会员" prop="isVip">
+        <el-select
+          filterable
+          v-model="queryParams.isVip"
+          placeholder="请选择是否为会员"
+          clearable size="small">
+          <el-option
+            v-for="dict in isVipList"
+            :key="dict.dictValue"
+            :label="dict.dictLabel"
+            :value="dict.dictValue"
+          />
+        </el-select>
+      </el-form-item>
 
       <el-form-item>
         <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
@@ -191,26 +205,28 @@
     <el-table border v-loading="loading" :data="courseWatchLogList" @selection-change="handleSelectionChange">
       <el-table-column type="selection" width="55" align="center"/>
       <el-table-column label="记录编号" align="center" prop="logId"/>
-<!--      <el-table-column label="客户昵称" align="center" prop="externalUserName"/>-->
-
-<!--&lt;!&ndash;      <el-table-column label="会员ID" align="center" prop="userId"/>&ndash;&gt;-->
-<!--      <el-table-column label="客户头像" align="center" prop="externalUserAvatar">-->
-<!--        <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">
+     <el-table-column label="客户昵称" align="center" prop="externalUserName" v-if="queryParams.sendType == 2"/>
+
+      &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" v-if="queryParams.sendType == 1">
         <template slot-scope="scope">
           {{ queryParams.sendType=='1' ? scope.row.fsNickName : scope.row.externalUserName }}
         </template>
       </el-table-column>
-      <el-table-column label="头像" align="center">
+      <el-table-column label="头像" align="center" v-if="queryParams.sendType == 1">
         <template slot-scope="scope">
           <img v-if="queryParams.sendType=='1'" :src="scope.row.fsAvatar" style="width:50px;height:50px" />
           <img v-else :src="scope.row.externalUserAvatar" style="width:50px;height:50px" />
@@ -586,6 +602,10 @@ export default {
         corpId:null,
       },
 
+      isVipList: [
+        { dictLabel: '是', dictValue: 1 },
+        { dictLabel: '否', dictValue: 0 }
+      ],
       // 查询参数
       queryParams: {
         pageNum: 1,
@@ -610,6 +630,7 @@ export default {
         scheduleStartTime: null,
         scheduleEndTime: null,
         sendType:process.env.VUE_APP_COURSE_DEFAULT,
+        isVip: null,
       },
       // 表单参数
       form: {},

+ 113 - 0
src/views/fastGpt/fastGptKeywordSend/fastGptKeyWordDetails.vue

@@ -0,0 +1,113 @@
+<template>
+    <div style="background-color: #f0f2f5; padding-bottom: 20px; min-height: 100%; " >
+      <div style="padding: 20px; background-color: #fff;">
+        营销指令内容
+      </div>
+      <!-- 使用 el-form 包裹表单项 -->
+      <el-form label-width="120px" style="padding: 20px;">
+        <!-- 发送文字内容 -->
+        <el-form-item label="发送文字内容" >
+          <div class="el-form-item__content readonly-field" style="line-height: 28px;">
+            {{ form.content || '-' }}
+          </div>
+        </el-form-item>
+
+        <!-- 图片访问地址 -->
+        <el-form-item label="图片访问地址">
+          <div class="el-form-item__content readonly-field">
+            <div v-if="form.contentType !== 0 && form.imgUrl && form.imgUrl.trim()">
+              <el-image
+                v-for="(url, index) in form.imgUrl.split(',')"
+                :key="index"
+                :src="url"              style="width: 100px; height: 100px; margin-right: 10px;"
+                fit="cover"
+              >
+                <div slot="error" class="image-slot">
+                  <i class="el-icon-picture-outline"></i>
+                </div>
+              </el-image>
+            </div>
+            <div v-else class="el-form-item__content" style="line-height: 28px;">-</div>
+          </div>
+        </el-form-item>
+      </el-form>
+    </div>
+</template>
+
+<script>
+
+import {getFastGptKeywordSend} from "@/api/fastGpt/fastGptKeywordSend";
+
+  export default {
+    name: "fastGptChatMsgDetails",
+    data() {
+      return {
+        open:false,
+        logsOpen:false,
+        roles:[],
+        msgList:[],
+        item:null,
+        form: {
+          content: '',
+          imgUrl: ''
+        },
+        queryParams: {
+          pageNum: 1,
+          pageSize: 10,
+          keyword: null,
+          content: null,
+          contentType: null,
+          imgUrl: null,
+          status: null,
+          roleId: null,
+          createTime: null,
+        }
+      }
+    },
+
+    methods: {
+      getDetails(id) {
+        getFastGptKeywordSend(id).then(response => {
+          console.log(response);
+          this.form = response.data;
+        });
+      },
+
+      cancel(){
+          this.open = false;
+      }
+    }
+  }
+</script>
+<style>
+  .readonly-field {
+    background-color: #fafafa;
+    padding: 10px;
+    border-radius: 4px;
+  }
+  .contentx{
+      height: 100%;
+      background-color: #fff;
+      padding: 0px 20px 20px;
+
+
+      margin: 20px;
+  }
+  .el-descriptions-item__label.is-bordered-label{
+    font-weight: normal;
+  }
+  .el-descriptions-item__content {
+    max-width: 150px;
+    min-width: 100px;
+  }
+  .desct{
+      padding-top: 20px;
+      padding-bottom: 20px;
+      color: #524b4a;
+      font-weight: bold;
+    }
+  .padding-a{
+    padding-right: 10px;
+
+  }
+</style>

+ 532 - 0
src/views/fastGpt/fastGptKeywordSend/index.vue

@@ -0,0 +1,532 @@
+<template>
+  <div class="app-container">
+    <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="88px">
+<!--      <el-form-item label="营销关键字" prop="keyword" style="white-space: nowrap;">
+        <el-input
+          v-model="queryParams.keyword"
+          placeholder="请输入营销关键字"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>-->
+      <el-form-item label="营销关键字" prop="keyword"  style="white-space: nowrap;">
+        <el-select v-model="queryParams.keyword" clearable placeholder="请选择营销关键字">
+          <el-option
+            v-for="dict in keywordOptions"
+            :key="dict.keyword"
+            :label="dict.keyword"
+            :value="dict.keyword"
+          ></el-option>
+        </el-select>
+      </el-form-item>
+     <el-form-item label="发送文字内容" prop="content" style="white-space: nowrap;">
+        <el-input
+          v-model="queryParams.content"
+          placeholder="请输入发送文字内容"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="内容类型" prop="contentType">
+        <el-select v-model="queryParams.contentType" placeholder="请选择内容类型" clearable size="small">
+          <el-option
+            v-for="dict in contentTypeOptions"
+            :key="dict.dictValue"
+            :label="dict.dictLabel"
+            :value="dict.dictValue"
+          />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="状态" prop="status">
+        <el-select v-model="queryParams.status" placeholder="请选择状态" clearable size="small">
+          <el-option
+            v-for="dict in statusOptions"
+            :key="dict.dictValue"
+            :label="dict.dictLabel"
+            :value="dict.dictValue"
+          />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="客服角色" prop="roleIds">
+        <el-select v-model="queryParams.roleIds" placeholder="请选择客服角色" clearable size="small">
+          <el-option
+            v-for="item in roles"
+            :key="item.roleId"
+            :label="item.roleName"
+            :value="item.roleId"
+          />
+        </el-select>
+      </el-form-item>
+      <el-form-item>
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
+      </el-form-item>
+    </el-form>
+
+    <el-row :gutter="10" class="mb8">
+      <el-col :span="1.5">
+        <el-button
+          type="primary"
+          plain
+          icon="el-icon-plus"
+          size="mini"
+          @click="handleAdd"
+          v-hasPermi="['fastGpt:fastGptKeywordSend:add']"
+        >新增</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="success"
+          plain
+          icon="el-icon-edit"
+          size="mini"
+          :disabled="single"
+          @click="handleUpdate"
+          v-hasPermi="['fastGpt:fastGptKeywordSend:edit']"
+        >修改</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="danger"
+          plain
+          icon="el-icon-delete"
+          size="mini"
+          :disabled="multiple"
+          @click="handleDelete"
+          v-hasPermi="['fastGpt:fastGptKeywordSend:remove']"
+        >删除</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="warning"
+          plain
+          icon="el-icon-download"
+          size="mini"
+          :loading="exportLoading"
+          @click="handleExport"
+          v-hasPermi="['fastGpt:fastGptKeywordSend:export']"
+        >导出</el-button>
+      </el-col>
+      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+
+    <el-table border v-loading="loading" :data="fastGptKeywordSendList" @selection-change="handleSelectionChange">
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="id" align="center" prop="id" />
+      <el-table-column label="营销关键字" align="center" prop="keyword"/>
+      <el-table-column label="内容类型" align="center" prop="contentType">
+        <template slot-scope="scope">
+          <dict-tag :options="contentTypeOptions" :value="scope.row.contentType"/>
+        </template>
+      </el-table-column>
+<!--      <el-table-column label="图片访问地址" align="center" prop="imgUrl" />-->
+      <el-table-column label="状态" align="center" prop="status">
+        <template slot-scope="scope">
+          <dict-tag :options="statusOptions" :value="scope.row.status"/>
+        </template>
+      </el-table-column>
+      <el-table-column label="客服角色" align="center" prop="roleIds">
+        <template slot-scope="scope">
+          {{ getRoleNameById(scope.row.roleIds) }}
+        </template>
+      </el-table-column>
+
+      <el-table-column label="创建时间" align="center" prop="createTime" />
+      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+        <template slot-scope="scope">
+          <el-button
+            size="mini"
+            type="text"
+            @click="handleDetails(scope.row)"
+          >查看</el-button>
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-edit"
+            @click="handleUpdate(scope.row)"
+            v-hasPermi="['fastGpt:fastGptKeywordSend:edit']"
+          >修改</el-button>
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-delete"
+            @click="handleDelete(scope.row)"
+            v-hasPermi="['fastGpt:fastGptKeywordSend:remove']"
+          >删除</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <pagination
+      v-show="total>0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    />
+
+    <!-- 添加或修改Ai指令对话框 -->
+    <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="100px">
+
+        <el-form-item label="营销关键字" prop="keyword">
+          <el-select v-model="form.keyword" placeholder="请选择营销关键字">
+            <el-option
+              v-for="dict in keywordOptions"
+              :key="dict.keyword"
+              :label="dict.keyword"
+              :value="dict.keyword"
+            ></el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item label="发送内容" prop="content">
+          <el-input
+            type="textarea"
+            :autosize="{ minRows: 2, maxRows: 4}"
+            placeholder="请输入发送内容"
+            v-model="form.content">
+          </el-input>
+        </el-form-item>
+        <el-form-item label="内容类型" prop="contentType">
+          <el-select v-model="form.contentType" placeholder="请选择内容类型">
+            <el-option
+              v-for="dict in contentTypeOptions"
+              :key="dict.dictValue"
+              :label="dict.dictLabel"
+              :value="parseInt(dict.dictValue)"
+            ></el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item label="图片" prop="imgUrl" v-if="this.form.contentType !== 0">
+          <ImageUpload v-model="form.imgUrl"  type="image" :limit="1" :width="100" :height="100" />
+        </el-form-item>
+        <el-form-item label="状态">
+          <el-radio-group v-model="form.status">
+            <el-radio
+              v-for="dict in statusOptions"
+              :key="dict.dictValue"
+              :label="parseInt(dict.dictValue)"
+            >{{dict.dictLabel}}</el-radio>
+          </el-radio-group>
+        </el-form-item>
+        <el-form-item label="客服角色" prop="roleIds">
+          <el-select
+            v-model="form.roleIds"
+            placeholder="请选择客服角色"
+            size="small"
+            multiple
+            filterable
+            clearable
+            :filter-method="filterRoles"
+          >
+            <el-option
+              v-for="item in filteredRoles"
+              :key="item.roleId"
+              :label="item.roleName"
+              :value="item.roleId"/>
+          </el-select>
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">确 定</el-button>
+        <el-button @click="cancel">取 消</el-button>
+      </div>
+    </el-dialog>
+
+    <el-drawer
+      :with-header="false"
+      size="75%"  @close="handleDrawerClose"
+      :title="show.title" :visible.sync="show.open">
+      <fastGptKeyWordDetails  ref="Details" />
+    </el-drawer>
+  </div>
+</template>
+
+<script>
+import {
+  listFastGptKeywordSend,
+  getFastGptKeywordSend,
+  delFastGptKeywordSend,
+  addFastGptKeywordSend,
+  updateFastGptKeywordSend,
+  exportFastGptKeywordSend,
+  keywordList
+} from "@/api/fastGpt/fastGptKeywordSend";
+import ImageUpload from "@/components/ImageUpload/index.vue";
+import fastGptKeyWordDetails from "@/views/fastGpt/fastGptKeywordSend/fastGptKeyWordDetails.vue";
+import { getAllRoleList } from "@/api/fastGpt/fastGptRole";
+
+export default {
+  name: "FastGptKeywordSend",
+  components: {fastGptKeyWordDetails, ImageUpload},
+  data() {
+    return {
+      show:{
+        title:"指令内容",
+        open:false,
+      },
+      roleMap:{},
+      roles:[],
+      filteredRoles: [], // 过滤后的角色数据
+      // 遮罩层
+      loading: true,
+      // 导出遮罩层
+      exportLoading: false,
+      // 选中数组
+      ids: [],
+      // 非单个禁用
+      single: true,
+      // 非多个禁用
+      multiple: true,
+      // 显示搜索条件
+      showSearch: true,
+      // 总条数
+      total: 0,
+      // Ai指令表格数据
+      fastGptKeywordSendList: [],
+      // 弹出层标题
+      title: "",
+      // 是否显示弹出层
+      open: false,
+      // 关键字内容字典
+      keywordOptions: [],
+      // 内容类型字典
+      contentTypeOptions: [],
+      // 状态字典
+      statusOptions: [],
+      // 查询参数
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        keyword: null,
+        content: null,
+        contentType: null,
+        imgUrl: null,
+        status: null,
+        roleIds: [],
+        createTime: null,
+      },
+      // 表单参数
+      form: {roleIds: [],},
+      // 表单校验
+      rules: {
+        keyword: [
+          { required: true, message: "营销关键字不能为空", trigger: "change" }
+        ],
+        content: [
+          // 如果 contentType 不是纯文本类型(比如图文混合),可以动态设置校验规则
+          // 这里假设纯文本内容不需要上传图片
+          { validator: (rule, value, callback) => {
+              const { contentType } = this.form;
+              if (contentType === 0 && !value) {
+                callback(new Error("发送文字内容不能为空"));
+              } else {
+                callback();
+              }
+            },
+            trigger: "blur"
+          }
+        ],
+        imgUrl: [
+          { validator: (rule, value, callback) => {
+              const { contentType } = this.form;
+              if (contentType !== 0 && !value) {
+                callback(new Error("图片不能为空"));
+              } else {
+                callback();
+              }
+            },
+            trigger: "change"
+          }
+        ],
+        roleIds: [
+          { required: true, message: "至少选择一个客服角色", trigger: "change" }
+        ]
+      }
+    };
+  },
+  created() {
+    this.getList();
+    Promise.all([
+      keywordList().then(response => {
+        this.keywordOptions = response.data;
+      }),
+    this.getDicts("sys_fastgpt_keyword_file_type").then(response => {
+      this.contentTypeOptions = response.data;
+    }),
+    this.getDicts("sys_fastgpt_keyword_send_status").then(response => {
+      this.statusOptions = response.data;
+    }),
+      getAllRoleList().then(response => {
+        this.roles = response.data;
+        this.filteredRoles = response.data;
+        // 生成角色映射表
+        this.roleMap = response.data.reduce((map, role) => {
+          map[role.roleId] = role.roleName;
+          return map;
+        }, {});
+      })
+    ])
+  },
+  methods: {
+    /** 查询Ai指令列表 */
+    getList() {
+      this.loading = true;
+      listFastGptKeywordSend(this.queryParams).then(response => {
+        this.fastGptKeywordSendList = response.rows;
+        this.total = response.total;
+        this.loading = false;
+      });
+    },
+    // 添加过滤方法
+    filterRoles(query) {
+      this.filteredRoles = this.roles.filter(item =>
+        item.roleName.toLowerCase().includes(query.toLowerCase())
+      );
+    },
+    // 获取角色名
+    getRoleNameById(roleIds) {
+      if (!roleIds) return '-';
+
+      // 确保 roleIds 是数组
+      const idArray = Array.isArray(roleIds) ? roleIds : roleIds.split(',').map(id => id.trim());
+      return idArray
+        .map(id => this.roleMap[id])
+        .filter(name => name)
+        .join('、');
+    },
+    //查看按钮
+    handleDetails(row){
+      this.show.open=true;
+      setTimeout(() => {
+        this.$refs.Details.getDetails(row.id);
+      }, 500);
+    },
+
+    // 取消按钮
+    cancel() {
+      this.open = false;
+      getAllRoleList().then(response => {
+        this.roles = response.data;
+        this.filteredRoles = response.data;
+      });
+      this.reset();
+    },
+    // 表单重置
+    reset() {
+      this.form = {
+        id: null,
+        keyword: null,
+        content: null,
+        contentType: null,
+        imgUrl: null,
+        status: 0,
+        roleIds: [],
+        createTime: null
+      };
+      this.resetForm("form");
+
+    },
+    //关闭
+    handleDrawerClose(){
+      this.getList();
+    },
+    /** 搜索按钮操作 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 重置按钮操作 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    // 多选框选中数据
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.id)
+      this.single = selection.length!==1
+      this.multiple = !selection.length
+    },
+    /** 新增按钮操作 */
+    handleAdd() {
+      this.reset();
+      this.open = true;
+      this.title = "添加Ai指令";
+    },
+    /** 修改按钮操作 */
+    handleUpdate(row) {
+      this.reset();
+      const id = row.id || this.ids;
+      getFastGptKeywordSend(id).then(response => {
+        const data = response.data;
+        this.form = {
+          ...data,
+          roleIds: data.roleIds ? data.roleIds.split(',').map(Number) : [] // 确保转为 number[]
+        };
+        this.open = true;
+        this.title = "修改Ai指令";
+        this.$nextTick(() => {
+          this.$forceUpdate(); // 强制更新 el-select 的绑定
+        });
+      });
+    },
+    /** 提交按钮 */
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          // 提取 roleIds 数组中的 roleId 字段组成字符串
+          this.form.roleIds = this.form.roleIds.join(',');
+          if (this.form.id != null) {
+            updateFastGptKeywordSend(this.form).then(response => {
+              this.msgSuccess("修改成功");
+              this.open = false;
+              this.getList();
+            });
+          } else {
+            addFastGptKeywordSend(this.form).then(response => {
+              this.msgSuccess("新增成功");
+              this.open = false;
+              this.getList();
+            });
+          }
+        }
+      });
+    },
+    /** 删除按钮操作 */
+    handleDelete(row) {
+      const ids = row.id || this.ids;
+      this.$confirm('是否确认删除Ai指令编号为"' + ids + '"的数据项?', "警告", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      }).then(function() {
+        return delFastGptKeywordSend(ids);
+      }).then(() => {
+        this.getList();
+        this.msgSuccess("删除成功");
+      }).catch(() => {});
+    },
+    /** 导出按钮操作 */
+    handleExport() {
+      const queryParams = this.queryParams;
+      this.$confirm('是否确认导出所有Ai指令数据项?', "警告", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      }).then(() => {
+        this.exportLoading = true;
+        return exportFastGptKeywordSend(queryParams);
+      }).then(response => {
+        this.download(response.msg);
+        this.exportLoading = false;
+      }).catch(() => {});
+    }
+  }
+};
+</script>
+<style scoped>.el-form-item__content {
+  white-space: nowrap;
+}
+</style>

+ 333 - 0
src/views/fastGpt/fastgptEventLogTotal/index.vue

@@ -0,0 +1,333 @@
+<template>
+  <div class="app-container">
+    <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
+      <el-form-item label="公司名" prop="companyId">
+        <select-tree
+          v-model="selectedCompanyList"
+          :raw-data="deptList"
+          placeholder="请选择客服"
+          :parentSelectable="true"
+          :multiple="true"
+          component-width="300px"
+          :max-display-tags="3"
+          :check-strictly="false"
+          :return-leaf-only="false"
+          @change="handleMultiChange"
+        ></select-tree>
+      </el-form-item>
+      <el-form-item label="客服" prop="nickName" v-if="queryParams.companyId">
+        <el-select v-model="queryParams.companyUserId" remote
+                   placeholder="请选择"
+                   filterable clearable
+                   style="width: 100%;"
+                   @keyup.enter.native="handleQuery"
+                   @change="handleCompanyUserId"
+        >
+          <el-option
+            v-for="dict in companyUserList"
+            :key="`${dict.nickName} - ${dict.userName}`"
+            :label="`${dict.nickName} - ${dict.userName}`"
+            :value="dict.userId">
+          </el-option>
+        </el-select>
+      </el-form-item>
+
+      <el-form-item label="AppKey" prop="appKey">
+        <div style="display: flex; align-items: center;">
+          <tree-select
+            v-model="selectedAppKey"
+            :options="appKeyOptions"
+            :normalizer="normalizer"
+            :disable-branch-nodes="false"
+            placeholder="请选择 AppKey"      style="width: 300px;"
+            @input="handleAppKeyChange"
+          />
+        </div>
+      </el-form-item>
+
+      <el-form-item label="创建时间" prop="createTime">
+        <el-date-picker v-model="createTime" size="small" style="width: 220px" value-format="yyyy-MM-dd" type="daterange" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期"  @change="changeTime"></el-date-picker>
+      </el-form-item>
+      <el-form-item>
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
+      </el-form-item>
+    </el-form>
+
+    <el-row :gutter="10" class="mb8">
+      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+
+    <el-table border v-loading="loading" :data="fastgptEventLogTotalList" :row-class-name="() => 'fixed-bottom-row'"
+              @selection-change="handleSelectionChange" :max-height="600">
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="角色名称" align="center" prop="roleName" />
+      <el-table-column label="时间" align="center" prop="statTime" />
+      <el-table-column
+        v-for="dict in typeOptions"
+        :key="dict.dictValue"
+        :label="dict.dictLabel"
+        align="center">
+        <template slot-scope="scope">
+          <span>{{ scope.row.typeCountMap ? scope.row.typeCountMap[dict.dictValue] : '' }}</span>
+          <span v-if="dict.dictValue !== '11'"
+                :style="{ fontSize: '12px', marginLeft: '5px',
+                color: getPercentageColor((scope.row.typeCountMap[dict.dictValue] / scope.row.typeCountMap[2]) * 100) }">
+            ({{ ((scope.row.typeCountMap[dict.dictValue] / scope.row.typeCountMap[2]) * 100).toFixed(2) }}%)
+          </span>
+        </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 { listFastgptEventLogTotal, getFastgptEventLogTotal, delFastgptEventLogTotal, addFastgptEventLogTotal, updateFastgptEventLogTotal, exportFastgptEventLogTotal, getFastGptRoleAppKeyList} from "@/api/fastGpt/fastgptEventLogTotal";
+import SelectTree from "@/components/TreeSelect/index.vue";
+import {getDeptData} from "@/api/system/employeeStats";
+import TreeSelect from '@riophae/vue-treeselect'
+import '@riophae/vue-treeselect/dist/vue-treeselect.css'
+
+
+
+export default {
+  name: "FastgptEventLogTotal",
+  components: {SelectTree,TreeSelect},
+  data() {
+    return {
+      createTime:null,
+      // 遮罩层
+      loading: true,
+      // 导出遮罩层
+      exportLoading: false,
+      selectedCompanyList: [],
+      deptList: [],
+      companyUserList: [],
+      selectedAppKey: null,
+      selectedAppKeyLabel: '',
+      appKeyOptions: [],
+      // 选中数组
+      ids: [],
+      // 非单个禁用
+      single: true,
+      // 非多个禁用
+      multiple: true,
+      // 显示搜索条件
+      showSearch: true,
+      // 总条数
+      total: 0,
+      // ai事件埋点统计表格数据
+      fastgptEventLogTotalList: [],
+      // 弹出层标题
+      title: "",
+      // 是否显示弹出层
+      open: false,
+      typeCountMap: null,
+      // 日志类型字典
+      typeOptions: [],
+      // 查询参数
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        roleId: null,
+        count: null,
+        type: null,
+        companyId: null,
+        companyUserId: null,
+        qwUserId: null,
+        typeCountMap: null,
+        beginTime:null,
+        endTime:null,
+        appKey:null,
+      },
+      // 表单参数
+      form: {},
+      // 表单校验
+      rules: {
+      }
+    };
+  },
+  created() {
+    this.getList();
+    this.getDicts("sys_fastgpt_event_log_type").then(response => {
+      this.typeOptions = response.data;
+    });
+
+    getDeptData().then(response => {
+      this.deptList = response.data;
+    });
+    getFastGptRoleAppKeyList().then(res => {
+      this.appKeyOptions = res.data.map(item => ({
+        id: `p_${item.roleId}`,
+        label: item.roleName,
+        children: (item.roleList || []).map(child => ({
+          id: `c_${child.roleId}`,
+          label: child.roleName,
+          parentId: `p_${item.roleId}`, // 记录父节点 ID
+          parentLabel: item.roleName,   // 记录父节点 label
+          disabled: true
+        }))
+      }));
+    });
+
+  },
+  methods: {
+    /** 查询ai事件埋点统计列表 */
+    getList() {
+      this.loading = true;
+      if(this.selectedCompanyList != null && this.selectedCompanyList.length > 0) {
+        this.queryParams.userIds = this.selectedCompanyList;
+      }else {
+        this.queryParams.userIds = [];
+      }
+
+      listFastgptEventLogTotal(this.queryParams).then(response => {
+        console.log(response)
+        this.fastgptEventLogTotalList = response.data.list;
+        this.total = response.data.total;
+        this.loading = false;
+      });
+    },
+    normalizer(node) {
+      return {
+        id: node.id,
+        label: node.label,
+        children: node.children,
+        disabled: node.disabled
+      }
+    },
+    handleAppKeyChange(value) {
+      const node = this.findNodeById(this.appKeyOptions, value);
+      if (!node) {
+        this.selectedAppKeyLabel = '';
+        return;
+      }
+
+      // 如果是子节点,则找父节点 label
+      if (node.parentLabel) {
+        this.queryParams.appKey = node.parentLabel;
+        this.selectedAppKeyLabel = node.parentLabel;
+        this.selectedAppKey = this.selectedAppKeyLabel;
+      } else {
+        this.queryParams.appKey = node.label;
+        this.selectedAppKeyLabel = node.label;
+        this.selectedAppKey = this.selectedAppKeyLabel;
+      }
+    },
+    findNodeById(nodes, id) {
+      for (const node of nodes) {
+        if (node.id === id) return node;
+        if (node.children) {
+          const found = this.findNodeById(node.children, id);
+          if (found) return found;
+        }
+      }
+      return null;
+    },
+    changeTime(){
+      console.log(this.createTime);
+      if(this.createTime!=null){
+        this.queryParams.beginTime=this.createTime[0];
+        this.queryParams.endTime=this.createTime[1];
+      }else{
+        this.queryParams.beginTime=null;
+        this.queryParams.endTime=null;
+      }
+      console.log(this.queryParams.beginTime);
+      console.log(this.queryParams.endTime);
+    },
+    // 取消按钮
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    handleMultiChange(e){
+
+    },
+    handleCompanyUserId(val){
+      if(val == null || val === '') {
+        this.queryParams.companyUserId = null;
+        this.queryParams.userIds = [];
+      }
+      console.log(val);
+    },
+    // 表单重置
+    reset() {
+      this.form = {
+        id: null,
+        roleId: null,
+        count: null,
+        type: null,
+        companyId: null,
+        companyUserId: null,
+        qwUserId: null,
+        statTime: null
+      };
+      this.resetForm("form");
+    },
+    getPercentageColor(percentage) {
+      // HSL模式从黄色(60度)渐变到红色(0度)
+      const percent = Math.min(100, Math.max(0, parseFloat(percentage)));
+
+      // 调整色相范围:从深黄色(40°)渐变到红色(0°)
+      const hue = 40 - 40 * (percent / 100); // 初始 hue=40(深黄),终点 hue=0(红)
+
+      // 提高饱和度(100%),亮度保持 50%(鲜艳但不刺眼)
+      return `hsl(${hue}, 100%, 50%)`;
+    },
+    /** 搜索按钮操作 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      console.log(this.selectedAppKey)
+      if(this.selectedAppKey === null || typeof this.selectedAppKey === 'undefined'){
+        this.queryParams.appKey = null;
+      }
+      this.getList();
+    },
+    /** 重置按钮操作 */
+    resetQuery() {
+      this.selectedAppKey = null;
+      this.selectedAppKeyLabel = '';
+      this.selectedCompanyList = [];
+      this.queryParams.appKey = null;
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    // 多选框选中数据
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.id)
+      this.single = selection.length!==1
+      this.multiple = !selection.length
+    },
+    /** 导出按钮操作 */
+    handleExport() {
+      const queryParams = this.queryParams;
+
+      if(this.selectedCompanyList != null && this.selectedCompanyList.length > 0) {
+        this.queryParams.userIds = this.selectedCompanyList;
+      }else {
+        this.queryParams.userIds = [];
+      }
+      this.$confirm('是否确认导出所有ai事件埋点统计数据项?', "警告", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        }).then(() => {
+          this.exportLoading = true;
+          return exportFastgptEventLogTotal(queryParams);
+        }).then(response => {
+          this.download(response.msg);
+          this.exportLoading = false;
+        }).catch(() => {});
+    }
+  }
+};
+</script>

+ 761 - 0
src/views/hisStore/components/addOrder.vue

@@ -0,0 +1,761 @@
+<template>
+  <div class="app-container">
+    <!-- 添加一个加载状态,在获取createOrderType之前显示 -->
+    <div v-if="!formReady" style="text-align: center; padding: 50px;">
+      <i class="el-icon-loading"></i> 正在加载...
+    </div>
+
+    <!-- 只有在formReady为true时才显示表单 -->
+    <el-form v-if="formReady" ref="form" :model="form" :rules="rules" label-width="120px">
+      <el-form-item label="会员信息" prop="userId">
+        <el-row>
+          <el-col>
+            <el-input placeholder="请输入会员手机号" style="width:240px;cursor:pointer" v-model="phone">
+            </el-input>
+            <el-button plain style="margin-left:10px;" @click="searchUser()">查询</el-button>
+            <el-button plain style="margin-left:10px;" icon="el-icon-plus" type="primary" @click="handleAddUser()">添加会员</el-button>
+          </el-col>
+        </el-row>
+        <el-table border style="margin-top:5px;" v-loading="userloading" :data="users">
+          <el-table-column label="ID" align="center" prop="userId" />
+          <el-table-column label="会员头像" align="center" width="80">
+            <template slot-scope="scope">
+              <el-popover placement="right" title="" trigger="hover">
+                <img slot="reference" :src="scope.row.avatar" width="50">
+                <img :src="scope.row.avatar" style="max-width: 120px;">
+              </el-popover>
+            </template>
+          </el-table-column>
+          <el-table-column label="昵称" align="center" prop="nickname" />
+          <el-table-column label="手机号" align="center" prop="phone" />
+          <el-table-column label="状态" align="center" prop="status">
+            <template slot-scope="scope">
+              <el-tag prop="status" v-for="(item, index) in userStatusOptions" v-if="scope.row.status==item.dictValue">{{item.dictLabel}}</el-tag>
+            </template>
+          </el-table-column>
+        </el-table>
+      </el-form-item>
+
+      <el-form-item label="收货信息" prop="addressId">
+        <el-row>
+          <el-col>
+            <el-button plain type="primary" icon="el-icon-plus" @click="handleAddUserAddress()">添加收货地址</el-button>
+          </el-col>
+        </el-row>
+        <el-radio-group v-model="form.addressId" style="width:100%">
+          <el-table border style="margin-top:5px;" v-loading="addressloading" :data="address">
+            <el-table-column label="ID" align="center"  >
+              <template slot-scope="scope">
+                <el-radio :label="scope.row.addressId"></el-radio>
+              </template>
+            </el-table-column>
+            <el-table-column label="收货人姓名" align="center" prop="realName" />
+            <el-table-column label="收货人电话" align="center" prop="phone" />
+            <el-table-column label="地址" align="center" prop="detail">
+              <template slot-scope="scope">
+                {{scope.row.province}} {{scope.row.city}} {{scope.row.district}} {{scope.row.detail}}
+              </template>
+            </el-table-column>
+          </el-table>
+        </el-radio-group>
+      </el-form-item>
+
+      <el-form-item label="商品列表">
+        <el-row>
+          <el-col>
+            <el-button plain type="primary" icon="el-icon-plus" @click="handleAddProduct">添加商品</el-button>
+          </el-col>
+        </el-row>
+        <el-table border :key="tablekey" width="100%" style="margin-top:5px;" :data="products">
+          <el-table-column label="商品编号" align="center" prop="barCode" />
+          <el-table-column label="商品图片" align="center" width="100">
+            <template slot-scope="scope">
+              <el-popover placement="right" title="" trigger="hover">
+                <img slot="reference" :src="scope.row.image" width="50">
+                <img :src="scope.row.image" style="max-width: 50px;">
+              </el-popover>
+            </template>
+          </el-table-column>
+          <el-table-column label="商品名称" show-overflow-tooltip align="center" prop="productName" />
+          <el-table-column label="商品规格" align="center" prop="sku" />
+          <el-table-column label="库存" align="center" prop="stock" />
+          <el-table-column label="单价" align="center" prop="price" width="200px" v-if="createOrderType == 1">
+            <template slot-scope="scope">
+              <el-input-number v-model="scope.row.price" @change="handleProductCountChange(scope.row)" size="mini" :min="0.01"></el-input-number>
+            </template>
+          </el-table-column>
+          <el-table-column label="单价" align="center" prop="price" v-if="createOrderType == 2"/>
+          <el-table-column label="数量" align="center" prop="count" width="200px" :key="tablekey">
+            <template slot-scope="scope">
+              <div>
+                <el-input-number v-model="scope.row.count" @change="handleProductCountChange(scope.row)" size="mini" :min="1" :max="scope.row.stock"></el-input-number>
+              </div>
+            </template>
+          </el-table-column>
+          <el-table-column label="小计" align="center" prop="money" />
+          <el-table-column label="操作" align="center" width="100px">
+            <template slot-scope="scope">
+              <el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)">删除</el-button>
+            </template>
+          </el-table-column>
+        </el-table>
+        <el-row>
+          <el-col>
+            <span>商品合计:{{products.length}}</span><span style="margin-left:10px;">商品总价:{{totalMoney.toFixed(2)}}</span>
+          </el-col>
+        </el-row>
+      </el-form-item>
+
+      <el-form-item label="订单类型" prop="orderType">
+        <el-select v-model="form.orderType" placeholder="请选择订单类型" clearable size="small">
+          <el-option v-for="item in orderTypeOptions" :key="item.dictValue" :label="item.dictLabel" :value="item.dictValue" />
+        </el-select>
+      </el-form-item>
+
+      <el-form-item label="媒体来源" prop="orderMedium" v-if="orderMediumOptions.length>0">
+        <el-select v-model="form.orderMedium" placeholder="请选择媒体来源" clearable size="small">
+          <el-option v-for="item in orderMediumOptions" :key="item.dictValue" :label="item.dictLabel" :value="item.dictValue" />
+        </el-select>
+      </el-form-item>
+
+      <el-form-item label="支付方式" prop="payType">
+        <el-select v-model="form.payType" placeholder="请选择支付方式" clearable size="small">
+          <el-option v-for="item in payTypeOptions" :key="item.dictValue" :label="item.dictLabel" :value="item.dictValue" />
+        </el-select>
+      </el-form-item>
+
+      <el-form-item label="改价" prop="payPrice" v-if="createOrderType == 2">
+        <el-input-number v-model="form.payPrice" placeholder="修改商品总价" size="medium" :precision="2" :min="0.01" :step="0.1" />
+      </el-form-item>
+
+      <el-form-item label="物流代收" prop="amount" v-if="form.payType == '3'">
+        <el-input-number v-model="form.amount" placeholder="平台支付价格" size="medium" :precision="2" :min="0.01" :step="0.1" />
+      </el-form-item>
+
+      <el-form-item label="订单备注" prop="mark">
+        <el-input type="textarea" rows="2" v-model="form.mark" placeholder="" />
+      </el-form-item>
+    </el-form>
+
+    <div v-if="formReady" slot="footer" class="dialog-footer" style="float: right; margin-bottom: 20px;">
+      <el-button type="primary" @click="submitForm">确 定</el-button>
+      <el-button @click="cancel">取 消</el-button>
+    </div>
+
+    <!-- 对话框部分保持不变 -->
+    <el-dialog :title="product.title" v-if="product.open" :visible.sync="product.open" width="1000px" append-to-body>
+      <product-select @selectProduct="selectProduct" />
+    </el-dialog>
+    <el-dialog :title="user.title" v-if="user.open" :visible.sync="user.open" width="500px" append-to-body>
+      <add-user @addUser="addUser" />
+    </el-dialog>
+    <el-dialog :title="userAddress.title" v-if="userAddress.open" :visible.sync="userAddress.open" width="800px" append-to-body>
+      <add-user-address ref="addUserAddress" @addUserAddress="addUserAddress" />
+    </el-dialog>
+    <el-dialog :title="payQr.title" v-if="payQr.open" :visible.sync="payQr.open" width="240px" append-to-body>
+      <div style="padding-bottom:15px;">
+        <div class="qrcode" ref="qrCodeUrl"></div>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import {exportStoreOrderItems, createUserOrder,listStoreOrder, getStoreOrder, delStoreOrder, addStoreOrder, updateStoreOrder, exportStoreOrder,getCreateOrderType } from "@/api/hisStore/storeOrder";
+import { getUserList } from "@/api/users/user";
+import { getAddressList } from "@/api/users/userAddress";
+import { getTcmScheduleList } from "@/api/company/tcmScheduleReport";
+import productOrder from "@/views/hisStore/components/productOrder";
+import productSelect from "@/views/hisStore/components/productSelect";
+import addUser from "@/views/hisStore/components/addUser";
+import addUserAddress from "@/views/hisStore/components/addUserAddress";
+import config from "@/utils/config";
+import QRCode from 'qrcodejs2'
+import { treeselect } from "@/api/company/companyDept";
+import Treeselect from "@riophae/vue-treeselect";
+import "@riophae/vue-treeselect/dist/vue-treeselect.css";
+
+export default {
+  components: { Treeselect,productOrder,productSelect,addUser,addUserAddress },
+  name: "StoreOrder",
+  props: {
+    customerId: {
+      type: Number,
+      required: false
+    },
+    userId: {
+      type: Number,
+      required: false
+    }
+  },
+  data() {
+    return {
+      // 添加表单准备状态
+      formReady: false,
+      createOrderType: null,
+      // 部门树选项
+      deptOptions: undefined,
+      // 部门名称
+      deptName: undefined,
+      defaultProps: {
+        children: "children",
+        label: "label",
+      },
+      deliveryPayStatusOptions:[],
+      deliveryStatusOptions:[],
+      dateRange: [],
+      orderTypeOptions:[],
+      orderMediumOptions:[],
+      payTypeOptions:[],
+      payQr:{
+        open:false,
+        title:"付款二维码"
+      },
+      user:{
+        open:false,
+        title:"创建会员"
+      },
+      userAddress:{
+        open:false,
+        title:"创建收货地址"
+      },
+      tablekey:false,
+      totalMoney:0.00,
+      products:[],
+      product:{
+        open:false,
+        title:"商品选择"
+      },
+      phone:null,
+      address:[],
+      addressloading: false,
+      userloading: false,
+      users:[],
+      userStatusOptions:[],
+      show:{
+        open:false,
+        title:"订单详情"
+      },
+      activeName:"00",
+      statusOptions:[],
+      // 遮罩层
+      loading: true,
+      // 选中数组
+      ids: [],
+      // 非单个禁用
+      single: true,
+      // 非多个禁用
+      multiple: true,
+      // 显示搜索条件
+      showSearch: true,
+      // 总条数
+      total: 0,
+      // 订单表格数据
+      storeOrderList: [],
+      // 弹出层标题
+      title: "",
+      // 是否显示弹出层
+      open: false,
+      createTimeRange:[],
+      payTimeRange:[],
+      deliveryImportTimeRange:[],
+      scheduleOptions:[],
+      // 查询参数
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        orderCode: null,
+        extendOrderId: null,
+        userId: null,
+        realName: null,
+        userPhone: null,
+        userAddress: null,
+        cartId: null,
+        freightPrice: null,
+        totalNum: null,
+        totalPrice: null,
+        totalPostage: null,
+        payPrice: null,
+        payPostage: null,
+        deductionPrice: null,
+        couponId: null,
+        couponPrice: null,
+        paid: null,
+        payTime: null,
+        payType: null,
+        status: null,
+        refundStatus: null,
+        refundReasonWapImg: null,
+        refundReasonWapExplain: null,
+        refundReasonTime: null,
+        refundReasonWap: null,
+        refundReason: null,
+        refundPrice: null,
+        deliverySn: null,
+        deliveryName: null,
+        deliveryType: null,
+        deliveryId: null,
+        gainIntegral: null,
+        useIntegral: null,
+        payIntegral: null,
+        backIntegral: null,
+        mark: null,
+        isDel: null,
+        cost: null,
+        verifyCode: null,
+        storeId: null,
+        shippingType: null,
+        isChannel: null,
+        isRemind: null,
+        isSysDel: null
+      },
+      // 表单参数
+      form: {
+        addressId:null,
+        userId:null,
+        products:[],
+      },
+      // 表单校验
+      rules: {
+        userId: [
+          { required: true, message: "会员信息不能为空", trigger: "submit" }
+        ],
+        addressId: [
+          { required: true, message: "收货信息不能为空", trigger: "submit" }
+        ],
+        products: [
+          { required: true, message: "商品不能为空", trigger: "submit" }
+        ],
+      }
+    };
+  },
+  watch: {
+    // 根据名称筛选部门树
+    deptName(val) {
+      this.$refs.tree.filter(val);
+    },
+  },
+  created() {
+    // 先获取createOrderType,然后再初始化其他数据
+    this.initializeForm();
+  },
+  methods: {
+    // 初始化表单的方法
+    async initializeForm() {
+      try {
+        // 1. 首先获取createOrderType
+        const response = await getCreateOrderType();
+        this.createOrderType = response.createSalesOrderType;
+
+        // 2. 然后并行加载其他数据
+        await Promise.all([
+          this.loadDictionaries(),
+          this.loadOtherData(),
+          this.initUser()
+        ]);
+
+        // 3. 所有数据加载完成后,设置表单为准备状态
+        this.formReady = true;
+        console.log('Form is ready to display');
+
+      } catch (error) {
+        console.error('Error initializing form:', error);
+        this.$message.error('表单初始化失败');
+      }
+    },
+
+    // 加载字典数据
+    async loadDictionaries() {
+      const dictPromises = [
+        this.getDicts("crm_customer_source").then((response) => {
+          this.orderMediumOptions = response.data;
+        }),
+        this.getDicts("store_order_type").then((response) => {
+          this.orderTypeOptions = response.data;
+        }),
+        this.getDicts("store_pay_type").then((response) => {
+          this.payTypeOptions = response.data;
+        }),
+        this.getDicts("user_status").then((response) => {
+          this.userStatusOptions = response.data;
+        }),
+        this.getDicts("store_order_status").then((response) => {
+          this.statusOptions = response.data;
+        }),
+        this.getDicts("store_order_delivery_status").then((response) => {
+          this.deliveryStatusOptions = response.data;
+        }),
+        this.getDicts("store_delivery_pay_status").then((response) => {
+          this.deliveryPayStatusOptions = response.data;
+        })
+      ];
+
+      await Promise.all(dictPromises);
+    },
+
+    // 加载其他数据
+    async loadOtherData() {
+      await Promise.all([
+        this.getTreeselect(),
+        getTcmScheduleList().then(response => {
+          this.scheduleOptions = response.data;
+        })
+      ]);
+    },
+
+    initUser(){
+      return new Promise((resolve) => {
+        if(this.userId != null){
+          var data={userId:this.userId}
+          this.userloading = true;
+          this.users=[];
+          this.address=[];
+          getUserList(data).then(response => {
+            this.users = response.data;
+            this.userloading = false;
+            if(this.users!=null&&this.users.length==1){
+              this.form.userId=this.users[0].userId;
+              this.getAddressList(this.form.userId).then(() => {
+                resolve();
+              });
+            } else {
+              resolve();
+            }
+          }).catch(() => {
+            resolve();
+          });
+        } else {
+          resolve();
+        }
+      });
+    },
+
+    /** 查询部门下拉树结构 */
+    getTreeselect() {
+      return treeselect().then((response) => {
+        this.deptOptions = response.data;
+      });
+    },
+
+    // 修改getAddressList方法,返回Promise
+    getAddressList(userId){
+      var data={userId:userId}
+      this.addressloading = true;
+      this.address=[];
+      return getAddressList(data).then(response => {
+        this.address = response.data;
+        this.addressloading = false;
+      });
+    },
+
+    // 其他方法保持不变...
+    // 筛选节点
+    filterNode(value, data) {
+      if (!value) return true;
+      return data.label.indexOf(value) !== -1;
+    },
+    // 节点单击事件
+    handleNodeClick(data) {
+      this.queryParams.deptId = data.id;
+      this.getList();
+    },
+    handleGenPayUrl(row){
+      this.payQr.open=true;
+      setTimeout(() => {
+        var qrcode = new QRCode(this.$refs.qrCodeUrl, {
+            text: config.payQRUrl+row.id,
+            width: 200,
+            height: 200,
+            colorDark: '#000000',
+            colorLight: '#ffffff',
+            correctLevel: QRCode.CorrectLevel.H
+        })
+      }, 200);
+    },
+    handleAddUser(){
+      this.user.open=true;
+    },
+    handleAddUserAddress(){
+      if(this.form.userId==null){
+        this.msgError("请选择会员");
+        return;
+      }
+      this.userAddress.open=true;
+      setTimeout(() => {
+        this.$refs.addUserAddress.init(this.form.userId);
+      }, 500);
+    },
+    addUserAddress(){
+      this.userAddress.open=false;
+      //获取地址
+      this.getAddressList(this.form.userId);
+    },
+    addUser(){
+      this.user.open=false;
+    },
+    compute(){
+      this.totalMoney=0;
+      var that=this;
+      this.products.forEach (function (value) {
+          that.totalMoney += value.money;
+      });
+    },
+    handleProductCountChange(row){
+      this.tablekey = !this.tablekey
+      row.money=row.count*row.price;
+      this.$forceUpdate();
+      this.compute();
+    },
+    selectProduct(row){
+      for(var i=0;i<this.products.length;i++){
+        if(this.products[i].id==row.id){
+          return;
+        }
+      }
+      row.count=1;
+      row.money=row.count*row.price;
+      this.products.push(row);
+      this.$message.success("商品"+ row.productName + "添加成功")
+      this.compute();
+    },
+    handleAddProduct(){
+      this.product.open=true;
+    },
+    searchUser(){
+      if(this.phone==null||this.phone==""){
+        return;
+      }
+      var data={phone:this.phone}
+      this.userloading = true;
+      this.users=[];
+      this.address=[];
+      getUserList(data).then(response => {
+        this.users = response.data;
+        this.userloading = false;
+        if(this.users!=null&&this.users.length==1){
+          this.form.userId=this.users[0].userId;
+          this.getAddressList(this.form.userId)
+        }
+      });
+    },
+    handleDetails(row){
+      this.show.open=true;
+      const orderId = row.id ;
+      setTimeout(() => {
+        this.$refs.order.getOrder(orderId);
+      }, 500);
+    },
+    handleClick(tab, event) {
+       if(tab.name=="all"){
+        this.queryParams.status==null;
+      }
+      else{
+         this.queryParams.status=tab.name;
+      }
+      this.getList();
+    },
+    /** 查询订单列表 */
+    getList() {
+      if(this.queryParams.status=='00'){
+        this.queryParams.status=null;
+      }
+      if(this.createTimeRange!=null&&this.createTimeRange.length==2){
+        this.queryParams.createTimeRange=this.createTimeRange[0]+"--"+this.createTimeRange[1]
+      }
+      else{
+        this.queryParams.createTimeRange=null;
+      }
+      if(this.payTimeRange!=null&&this.payTimeRange.length==2){
+        this.queryParams.payTimeRange=this.payTimeRange[0]+"--"+this.payTimeRange[1]
+      }
+      else{
+        this.queryParams.payTimeRange=null;
+      }
+      if(this.deliveryImportTimeRange!=null&&this.deliveryImportTimeRange.length==2){
+        this.queryParams.deliveryImportTimeRange=this.deliveryImportTimeRange[0]+"--"+this.deliveryImportTimeRange[1]
+      }
+      else{
+        this.queryParams.deliveryImportTimeRange=null;
+      }
+      this.loading = true;
+      listStoreOrder(this.addDateRange(this.queryParams, this.dateRange)).then(response => {
+        this.storeOrderList = response.rows;
+        this.total = response.total;
+        this.loading = false;
+      });
+    },
+    // 取消按钮
+    cancel() {
+      this.open = false;
+      this.reset();
+      this.$emit("closePackage")
+    },
+    // 表单重置
+    reset() {
+      this.form = {
+        addressId:null,
+        userId:null,
+        products:null,
+      };
+      this.resetForm("form");
+    },
+    /** 搜索按钮操作 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 重置按钮操作 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+
+    /** 新增按钮操作 */
+    handleAdd() {
+      this.reset();
+      this.open = true;
+      this.title = "创建订单";
+    },
+    /** 修改按钮操作 */
+    handleUpdate(row) {
+      this.reset();
+      const id = row.id || this.ids
+      getStoreOrder(id).then(response => {
+        this.form = response.data;
+        this.open = true;
+        this.title = "修改订单";
+      });
+    },
+    /** 提交按钮 */
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        if(this.products.length==0){
+          this.msgError("请选择商品");
+          return;
+        }
+        this.form.products=this.products;
+        if (valid) {
+          this.form.customerId = this.customerId;
+          createUserOrder(this.form).then(response => {
+            if (response.code === 200) {
+              this.msgSuccess("创建成功");
+              this.$emit("closePackage")
+            }
+          });
+        }
+      });
+    },
+    /** 删除按钮操作 */
+    handleDelete(row) {
+       this.products.splice(this.products.findIndex(item => item.id === row.id), 1)
+       this.compute();
+    },
+    /** 导出按钮操作 */
+    handleExport() {
+      if(this.queryParams.status=='00'){
+        this.queryParams.status=null;
+      }
+      if(this.createTimeRange!=null&&this.createTimeRange.length==2){
+        this.queryParams.createTimeRange=this.createTimeRange[0]+"--"+this.createTimeRange[1]
+      }
+      else{
+        this.queryParams.createTimeRange=null;
+      }
+      if(this.payTimeRange!=null&&this.payTimeRange.length==2){
+        this.queryParams.payTimeRange=this.payTimeRange[0]+"--"+this.payTimeRange[1]
+      }
+      else{
+        this.queryParams.payTimeRange=null;
+      }
+      if(this.deliveryImportTimeRange!=null&&this.deliveryImportTimeRange.length==2){
+        this.queryParams.deliveryImportTimeRange=this.deliveryImportTimeRange[0]+"--"+this.deliveryImportTimeRange[1]
+      }
+      else{
+        this.queryParams.deliveryImportTimeRange=null;
+      }
+      const queryParams = this.addDateRange(this.queryParams, this.dateRange);
+      this.$confirm('是否确认导出所有订单数据项?', "警告", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        }).then(function() {
+          return exportStoreOrder(queryParams);
+        }).then(response => {
+          this.download(response.msg);
+        }).catch(function() {});
+    },
+    handleExportItems() {
+      if(this.queryParams.status=='00'){
+        this.queryParams.status=null;
+      }
+      if(this.createTimeRange!=null&&this.createTimeRange.length==2){
+        this.queryParams.createTimeRange=this.createTimeRange[0]+"--"+this.createTimeRange[1]
+      }
+      else{
+        this.queryParams.createTimeRange=null;
+      }
+      if(this.payTimeRange!=null&&this.payTimeRange.length==2){
+        this.queryParams.payTimeRange=this.payTimeRange[0]+"--"+this.payTimeRange[1]
+      }
+      else{
+        this.queryParams.payTimeRange=null;
+      }
+      if(this.deliveryImportTimeRange!=null&&this.deliveryImportTimeRange.length==2){
+        this.queryParams.deliveryImportTimeRange=this.deliveryImportTimeRange[0]+"--"+this.deliveryImportTimeRange[1]
+      }
+      else{
+        this.queryParams.deliveryImportTimeRange=null;
+      }
+      const queryParams = this.addDateRange(this.queryParams, this.dateRange);
+      this.$confirm('是否确认导出所有订单明细数据项?', "警告", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        }).then(function() {
+          return exportStoreOrderItems(queryParams);
+        }).then(response => {
+          this.download(response.msg);
+        }).catch(function() {});
+    }
+  }
+};
+</script>
+
+<style scoped lang="scss">
+.items{
+  margin: 5px 0px;
+  display: flex;
+  flex-direction: row;
+  align-items: center;
+  justify-content: flex-start;
+  .pic{
+    width:60px;
+    height:60px;
+  }
+  .goods-content{
+    margin-left: 10px;
+    max-width: 200px;
+    text-align: left;
+    .goods-title{
+      overflow:hidden;
+      white-space: nowrap;
+      text-overflow: ellipsis;
+      -o-text-overflow:ellipsis;
+    }
+  }
+}
+.el-message-box__message p{
+  max-height: 400px;
+  overflow:scroll;
+}
+.import-msg{
+  height: 500px;
+  overflow: auto;
+}
+</style>
+
+<style>
+.el-descriptions-item__label.is-bordered-label{
+  font-weight: normal;
+}
+</style>

+ 309 - 0
src/views/hisStore/components/addOrderOffline.vue

@@ -0,0 +1,309 @@
+<template>
+  <div class="app-container">
+        <el-form ref="form" :model="form" :rules="rules" label-width="100px">
+           <el-form-item label="客户信息" prop="crmId">
+                <el-row  >
+                  <el-col >
+                    <el-input placeholder="请输入客户手机号" clearable style="width:240px;cursor:pointer" v-model="phone">
+                    </el-input>
+                    <el-button plain style="margin-left:10px;"    @click="searchUser()">查询</el-button>
+                  </el-col>
+                </el-row>
+                <el-table border style="margin-top:5px;"  v-loading="userloading" :data="users">
+                  <el-table-column label="ID" align="center" prop="customerId" />
+                  <el-table-column label="客户编码" align="center" prop="customerCode" />
+                  <el-table-column label="客户名称" align="center" prop="customerName" />
+                  <el-table-column label="手机号" align="center" prop="mobile" />
+                  <el-table-column  label="客户来源" align="center" prop="source">
+                    <template slot-scope="scope">
+                      <el-tag prop="status" v-for="(item, index) in sourceOptions"    v-if="scope.row.source==item.dictValue">{{item.dictLabel}}</el-tag>
+                    </template>
+                  </el-table-column>
+                </el-table>
+            </el-form-item>
+            <el-form-item label="商品列表" >
+              <el-row  >
+                <el-col >
+                      <el-button plain  type="primary" icon="el-icon-plus" @click="handleAddProduct">添加商品</el-button>
+                </el-col>
+              </el-row>
+              <el-table border :key = "tablekey" width="100%" style="margin-top:5px;"  :data="products">
+                <el-table-column label="商品编号" align="center" prop="barCode" />
+                <el-table-column label="商品图片" align="center" width="100">
+                  <template slot-scope="scope">
+                    <el-popover
+                      placement="right"
+                      title=""
+                      trigger="hover"
+                    >
+                      <img slot="reference" :src="scope.row.image" width="50">
+                      <img :src="scope.row.image" style="max-width: 50px;">
+                    </el-popover>
+                  </template>
+                </el-table-column>
+                <el-table-column label="商品名称" show-overflow-tooltip align="center" prop="productName" />
+                <el-table-column label="商品规格" align="center" prop="sku" />
+                <el-table-column label="单价" align="center" prop="price" />
+                <el-table-column label="数量" align="center"  prop="count" width="200px" :key="tablekey">
+                   <template slot-scope="scope">
+                    <div>
+                        <el-input-number v-model="scope.row.count"  @change="handleProductCountChange(scope.row)"  size="mini" :min="1"   ></el-input-number>
+                    </div>
+                  </template>
+                </el-table-column>
+                <el-table-column label="小计" align="center" prop="money"   />
+                <el-table-column label="操作" align="center" width="100px" >
+                  <template slot-scope="scope">
+                    <el-button
+                      size="mini"
+                      type="text"
+                      icon="el-icon-delete"
+                      @click="handleDelete(scope.row)"
+                    >删除</el-button>
+                  </template>
+                </el-table-column>
+              </el-table>
+              <el-row>
+                <el-col>
+                      <span>商品合计:{{products.length}}</span><span style="margin-left:10px;">商品总价:{{totalMoney.toFixed(2)}}</span>
+                </el-col>
+              </el-row>
+            </el-form-item>
+            <el-form-item label="核实业务员" prop="uploadUserId">
+              <el-select style="width:220px" v-model="form.uploadUserId" placeholder="请选择" clearable size="small" >
+                <el-option
+                  v-for="item in salesmanList"
+                  :key="item.dictValue"
+                  :label="item.dictLabel"
+                  :value="item.dictValue"
+                />
+              </el-select>
+            </el-form-item>
+            <el-form-item label="价格" prop="payPrice">
+              <el-input-number v-model="form.payPrice"  size="mini"    ></el-input-number>
+            </el-form-item>
+            <el-form-item label="订单备注" prop="remark">
+              <el-input  type="textarea" rows="2" v-model="form.remark" placeholder="" />
+            </el-form-item>
+        </el-form>
+      <div slot="footer" class="dialog-footer" style="float: right; margin-bottom: 20px;">
+        <el-button type="primary" @click="submitForm">确 定</el-button>
+        <el-button @click="cancel">取 消</el-button>
+      </div>
+    <el-dialog :title="product.title" v-if="product.open"  :visible.sync="product.open" width="1000px" append-to-body>
+        <product-select  @selectProduct="selectProduct" />
+    </el-dialog>
+
+
+  </div>
+</template>
+
+<script>
+import { getMyCustomerList,recover,exportCustomer  } from "@/api/crm/customer";
+import {createOrder} from "@/api/hisStore/storeOrderOffline";
+import { getSalesman } from "@/api/company/companyUser";
+
+
+import productSelect from "@/views/hisStore/components/productSelect";
+
+export default {
+  components: { productSelect },
+  name: "AddOrderOffline",
+  data() {
+    return {
+      salesmanList:[],
+      tablekey:false,
+      totalMoney:0.00,
+      products:[],
+      product:{
+        open:false,
+        title:"商品选择"
+      },
+      phone:null,
+
+      userloading: false,
+      users:[],
+      sourceOptions:[],
+      userStatusOptions:[],
+      statusOptions:[],
+      // 遮罩层
+      loading: true,
+      // 选中数组
+      ids: [],
+      // 非单个禁用
+      single: true,
+      // 非多个禁用
+      multiple: true,
+
+      // 显示搜索条件
+      showSearch: true,
+      // 总条数
+      total: 0,
+      // 订单表格数据
+      storeOrderList: [],
+      // 弹出层标题
+      title: "",
+      // 是否显示弹出层
+      open: false,
+
+
+      // 表单参数
+      form: {
+        crmId:null,
+        uploadUserId:null,
+        products:[],
+      },
+      // 表单校验
+      rules: {
+        crmId: [
+          { required: true, message: "客户信息不能为空", trigger: "submit" }
+        ],
+        uploadUserId: [
+          { required: true, message: "核实业务员不能为空", trigger: "blur" }
+        ],
+
+        products: [
+          { required: true, message: "商品不能为空", trigger: "submit" }
+        ],
+
+      }
+    };
+  },
+  created() {
+    this.getDicts("crm_customer_source").then((response) => {
+      this.sourceOptions = response.data;
+    });
+    getSalesman().then((response) => {
+      this.salesmanList = response.data;
+    });
+  },
+  methods: {
+    handleAddProduct(){
+      this.product.open=true;
+    },
+    compute(){
+      this.totalMoney=0;
+      var that=this;
+      this.products.forEach (function (value) {
+          that.totalMoney += value.money;
+      });
+    },
+    handleProductCountChange(row){
+      this.tablekey = !this.tablekey
+      row.money=row.count*row.price;
+      this.$forceUpdate();
+      this.compute();
+    },
+    selectProduct(row){
+      for(var i=0;i<this.products.length;i++){
+        if(this.products[i].id===row.id){
+          this.$message.warning("商品已存在")
+          return;
+        }
+      }
+      row.count=1;
+      row.money=row.count*row.price;
+      this.products.push(row);
+      this.compute();
+      this.$message.success("商品添加成功")
+    },
+
+    searchUser(crmId){
+      if(this.phone==null||this.phone===""){
+        return;
+      }
+      var data={mobile:this.phone}
+      this.userloading = true;
+      this.users=[];
+      getMyCustomerList(data).then(response => {
+        this.users = response.rows;
+        this.userloading = false;
+        if(this.users!=null&&this.users.length===1){
+          this.form.crmId=this.users[0].customerId;
+        }
+      });
+    },
+
+    // 取消按钮
+    cancel() {
+      this.$emit("closeOrderOffline")
+    },
+    // 表单重置
+    reset() {
+      this.form = {
+
+        userId:null,
+        products:null,
+
+      };
+      this.resetForm("form");
+    },
+
+    /** 提交按钮 */
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        if(this.products.length==0){
+          this.msgError("请选择商品");
+          return;
+        }
+        this.form.products=this.products;
+        if (valid) {
+          createOrder(this.form).then(response => {
+            if (response.code === 200) {
+              this.msgSuccess("创建成功");
+              this.$emit("closeOrderOffline")
+            }
+          });
+
+        }
+      });
+    },
+    /** 删除按钮操作 */
+    handleDelete(row) {
+       this.products.splice(this.products.findIndex(item => item.id === row.id), 1)
+       this.compute();
+
+    },
+
+  }
+};
+</script>
+<style scoped lang="scss">
+.items{
+  margin: 5px 0px;
+  display: flex;
+  flex-direction: row;
+  align-items: center;
+  justify-content: flex-start;
+  .pic{
+    width:60px;
+    height:60px;
+  }
+  .goods-content{
+    margin-left: 10px;
+    max-width: 200px;
+    text-align: left;
+    .goods-title{
+
+      overflow:hidden;
+      white-space: nowrap;
+      text-overflow: ellipsis;
+      -o-text-overflow:ellipsis;
+    }
+  }
+}
+.el-message-box__message p{
+  max-height: 400px;
+  overflow:scroll;
+}
+.import-msg{
+  height: 500px;
+  overflow: auto;
+}
+</style>
+<style>
+  .el-descriptions-item__label.is-bordered-label{
+    font-weight: normal;
+  }
+
+</style>

+ 72 - 0
src/views/hisStore/components/addUser.vue

@@ -0,0 +1,72 @@
+<template>
+  <div >
+       <el-form ref="form" :model="form" :rules="rules" label-width="120px">
+        <el-form-item label="会员昵称" prop="nickname">
+          <el-input v-model="form.nickname" placeholder="请输入用户昵称" />
+        </el-form-item>
+        <el-form-item label="手机号码" prop="phone">
+          <el-input v-model="form.phone" placeholder="请输入手机号码" />
+        </el-form-item>
+        <el-form-item label="状态">
+            <el-radio-group v-model="form.status">
+              <el-radio :label="item.dictValue" v-for="item in statusOptions" >{{item.dictLabel}}</el-radio>
+            </el-radio-group>
+        </el-form-item>
+      </el-form>
+      <div    style="text-align:right;">
+        <el-button type="primary" @click="submitForm">确 定</el-button>
+      </div>
+  </div>
+</template>
+
+<script>
+import { listUser, getUser, delUser, addUser, updateUser, exportUser } from "@/api/users/user";
+
+export default {
+  name: "add",
+  data() {
+    return {
+      statusOptions:[],
+      // 表单参数
+      form: {
+        status:"1"
+      },
+      // 表单校验
+      rules: {
+        phone: [
+          { required: true, message: "手机号不能为空", trigger: "blur" }
+        ],
+        nickname: [
+          { required: true, message: "会员昵称不能为空", trigger: "blur" }
+        ],
+         
+      }
+    };
+  },
+  created() {
+    this.getDicts("user_status").then((response) => {
+      this.statusOptions = response.data;
+    });
+  },
+
+  methods: {
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          addUser(this.form).then(response => {
+            if (response.code === 200) {
+              this.msgSuccess("新增成功");
+              this.$emit("addUser",this.form.phone)
+              
+            }
+          });
+        }
+      });
+    },
+     
+  }
+};
+</script>
+<style scoped>
+ 
+</style>

+ 153 - 0
src/views/hisStore/components/addUserAddress.vue

@@ -0,0 +1,153 @@
+<template>
+  <div >
+      <el-form ref="form" :model="form" :rules="rules" label-width="120px">
+        <el-form-item label="收货人姓名" prop="realName">
+          <el-input v-model="form.realName" placeholder="请输入收货人姓名" />
+        </el-form-item>
+        <el-form-item label="收货人电话" prop="phone">
+          <el-input v-model="form.phone" placeholder="请输入收货人电话" />
+        </el-form-item>
+        <el-form-item label="收货地址" prop="district">
+          <el-row :gutter="20">
+          <el-col :span="6">
+             <el-select @change="provinceChange" v-model="form.province" placeholder="请选择">
+                <el-option
+                  v-for="item in province"
+                  :key="item.cityId"
+                  :label="item.name"
+                  :value="item.cityId">
+                </el-option>
+              </el-select>
+          </el-col>
+          <el-col :span="6">
+            <el-select @change="cityChange" v-model="form.city" placeholder="请选择">
+                <el-option
+                  v-for="item in city"
+                  :key="item.cityId"
+                  :label="item.name"
+                  :value="item.cityId">
+                </el-option>
+              </el-select>
+          </el-col>
+          <el-col :span="6">
+             <el-select @change="districtChange" v-model="form.district" placeholder="请选择">
+                <el-option
+                  v-for="item in district"
+                  :key="item.cityId"
+                  :label="item.name"
+                  :value="item.cityId">
+                </el-option>
+              </el-select>
+          </el-col>
+        </el-row>
+        </el-form-item>
+        <el-form-item label="详细地址" prop="detail">
+          <el-input v-model="form.detail" placeholder="请输入收货人详细地址" />
+        </el-form-item>
+      </el-form>
+      <div  style="text-align:right;">
+        <el-button type="primary" @click="submitForm">确 定</el-button>
+      </div>
+  </div>
+</template>
+
+<script>
+import { listUserAddress, getUserAddress, delUserAddress, addUserAddress, updateUserAddress, exportUserAddress } from "@/api/users/userAddress";
+import {getCitys} from "@/api/hisStore/city";
+export default {
+  name: "add",
+  data() {
+    return {
+      citys:[],
+      province:[],
+      city:[],
+      district:[],
+      // 表单参数
+      form: {
+        province:null,
+        city:null,
+        district:null,
+        cityId:null,
+      },
+      // 表单校验
+      rules: {
+        userId: [
+          { required: true, message: "会员不能为空", trigger: "blur" }
+        ],
+        realName: [
+          { required: true, message: "姓名不能为空", trigger: "blur" }
+        ],
+        phone: [
+          { required: true, message: "电话不能为空", trigger: "blur" }
+        ],
+        detail: [
+          { required: true, message: "详细地址不能为空", trigger: "blur" }
+        ],
+        district: [
+          { required: true, message: "收货地址不能为空", trigger: "blur" }
+        ],
+
+      }
+    };
+  },
+  created(){
+    this.getCityList();
+  },
+  methods: {
+    districtChange(val){
+      const item = this.district.find(i => i.cityId === val)
+      this.form.district=item.name;
+    },
+    cityChange(val){
+      const item = this.city.find(i => i.cityId === val)
+      this.district = item.children
+      this.form.district=null;
+      this.form.city=item.name;
+      this.form.cityId=val;
+    },
+    provinceChange(val){
+      const item = this.citys.find(i => i.cityId === val)
+      this.city = item.children
+      this.district=[];
+      this.form.city=null;
+      this.form.district=null;
+      this.form.province=item.name;
+    },
+    getCityList(){
+      getCitys().then(res => {
+          this.loading = false;
+          this.citys = this.convertCityData(res.data)
+          this.province=this.citys.filter(item => item.parentId===0 )
+        })
+    },
+    convertCityData(array) {
+      return array.map(item => {
+        return {
+          'cityId': item.value,
+          'name': item.label,
+          'parentId':  item.pid,
+          'children': item.children && this.convertCityData(item.children)
+        }
+      });
+    },
+    init(userId){
+      this.form.userId=userId;
+    },
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          addUserAddress(this.form).then(response => {
+            if (response.code === 200) {
+              this.msgSuccess("新增成功");
+              this.$emit("addUserAddress")
+            }
+          });
+        }
+      });
+    },
+  }
+};
+</script>
+<style scoped>
+
+</style>

+ 373 - 0
src/views/hisStore/components/offlineOrder.vue

@@ -0,0 +1,373 @@
+<template>
+  <div class="order-content">
+      <div class="order-status" v-if="order!=null" >
+          <el-steps  :active="order.status===3?order.status+1:order.status" align-center>
+            <el-step title="客服制单"></el-step>
+            <el-step title="待业务核实"></el-step>
+            <el-step title="待主管审核"></el-step>
+            <el-step title="内勤对流向"></el-step>
+          </el-steps>
+      </div>
+      <div>
+
+      <el-card shadow="never" style="margin-top: 15px">
+      <div class="operate-container"  v-if="order!=null">
+        <span  style="margin-left: 20px" class="color-danger">订单状态:
+           <el-tag prop="status" v-for="(item, index) in statusOptions"    v-if="order.status.toString()===item.dictValue">{{item.dictLabel}}</el-tag>
+        </span>
+
+        <div class="operate-button-container" >
+          <el-button size="mini" v-if="order.status ===1" @click="handleCertificates()"  v-hasPermi="['store:storeOrderOffline:uploadCredentials']" >上传凭证</el-button>
+          <el-button size="mini" v-if="order.crmId!=null&&order.crmId>0"  @click="handleCustomer()"    >查看客户详情</el-button>
+        </div>
+      </div>
+      <div style="margin: 20px 0px"  v-if="order!=null">
+        <span class="font-small">
+          基本信息
+        </span>
+      </div>
+      <el-descriptions :column="4" border  >
+        <el-descriptions-item label="订单ID"  >
+                <span v-if="order!=null">
+                  {{order.orderId}}
+                </span>
+        </el-descriptions-item>
+            <el-descriptions-item label="订单编号"  >
+                <span v-if="order!=null">
+                  {{order.orderCode}}
+                </span>
+            </el-descriptions-item>
+            <el-descriptions-item label="客户名称"  >
+                <span v-if="order!=null">
+                  {{order.customerName}}
+                </span>
+            </el-descriptions-item>
+
+
+            <el-descriptions-item label="客户电话"  >
+                <span v-if="order!=null ">
+                  {{order.mobile }}
+                </span>
+                <el-button icon="el-icon-search" size="mini" @click="handlePhone()" style="margin-left: 20px;" circle v-hasPermi="['store:storeOrder:queryPhone']"></el-button>
+              </el-descriptions-item>
+              <el-descriptions-item v-if="order!=null " label="应付金额"  >
+                <span >
+                  {{order.payPrice }}
+                </span>
+              </el-descriptions-item>
+              <el-descriptions-item v-if="order!=null " label="实付金额"  >
+                <span >
+                  {{order.payMoney }}
+                </span>
+              </el-descriptions-item>
+              <el-descriptions-item v-if="customerInfo!=null " label="客户编码"  >
+                <span >
+                  {{customerInfo.customerCode }}
+                </span>
+              </el-descriptions-item>
+            <el-descriptions-item label="创建时间"  >
+                <span v-if="order!=null ">
+                  {{order.createTime }}
+                </span>
+            </el-descriptions-item>
+            <el-descriptions-item label="所属客服"  >
+                <span v-if="order!=null ">
+                  {{order.companyUserName }}
+                </span>
+            </el-descriptions-item>
+            <el-descriptions-item label="所属部门"  >
+              <span v-if="order!=null ">
+                {{order.companyName }}
+              </span>
+            </el-descriptions-item>
+            <el-descriptions-item label="所属业务员"  >
+              <span v-if="order!=null ">
+                {{order.uploadUserName }}
+              </span>
+            </el-descriptions-item>
+            <el-descriptions-item label="凭证上传时间"  >
+                  <span v-if="order!=null ">
+                    {{order.uploadTime }}
+                  </span>
+            </el-descriptions-item>
+        <el-descriptions-item label="审核人"  >
+                  <span v-if="order!=null ">
+                    {{order.auditBy }}
+                  </span>
+        </el-descriptions-item>
+        <el-descriptions-item label="审核时间"  >
+                  <span v-if="order!=null ">
+                    {{order.auditTime }}
+                  </span>
+        </el-descriptions-item>
+            <el-descriptions-item label="备注"  >
+                <span v-if="order!=null ">
+                  {{order.remark }}
+                </span>
+            </el-descriptions-item>
+
+
+
+      </el-descriptions>
+      <div style="margin: 20px 0px"  v-if="certificates!=null">
+        <span class="font-small">
+          凭证信息
+        </span>
+      </div>
+      <el-image
+          v-if="this.certificates != null"
+          :src="certificates"
+          :preview-src-list="[certificates]"
+          :style="{ width: '100px', height: '100px' }"
+          @click.native="showImageDialog"
+        ></el-image>
+        <el-dialog :visible.sync="dialogVisibleImage" width="10%">
+          <img :src="certificates" style="width: 100%" alt="">
+        </el-dialog>
+
+      <div style="margin-top: 20px">
+        <span class="font-small">商品信息</span>
+      </div>
+      <el-table
+        border
+        v-if="items!=null"
+        :data="items"
+        size="small"
+        style="width: 100%;margin-top: 20px" >
+        <el-table-column label="商品图片" width="150" align="center">
+          <template slot-scope="scope">
+            <img :src="JSON.parse(scope.row.jsonInfo).image" style="height: 80px">
+          </template>
+        </el-table-column>
+        <el-table-column label="商品名称" width="300" align="center">
+          <template slot-scope="scope">
+            <p>{{JSON.parse(scope.row.jsonInfo).productName}}</p>
+          </template>
+        </el-table-column>
+        <el-table-column label="单价" width="240" align="center">
+          <template slot-scope="scope">
+            <p>¥{{JSON.parse(scope.row.jsonInfo).price.toFixed(2)}}</p>
+          </template>
+        </el-table-column>
+        <el-table-column label="规格" width="240" align="center">
+          <template slot-scope="scope">
+            {{JSON.parse(scope.row.jsonInfo).sku}}
+          </template>
+        </el-table-column>
+        <el-table-column label="数量" width="180" align="center">
+          <template slot-scope="scope">
+            {{scope.row.num}}
+          </template>
+        </el-table-column>
+<!--        <el-table-column label="小计"  align="center">-->
+<!--          <template slot-scope="scope" >-->
+<!--            ¥{{scope.row.num*JSON.parse(scope.row.jsonInfo).price.toFixed(2)}}-->
+<!--          </template>-->
+<!--        </el-table-column>-->
+      </el-table>
+<!--      <div style="float: right;margin: 20px" v-if="order!=null">-->
+<!--        合计:<span class="color-danger">¥{{order.totalPrice.toFixed(2)}}</span>-->
+<!--      </div>-->
+      </el-card>
+    </div>
+    <el-dialog :title="certificateDialig.title" :visible.sync="certificateDialig.open" append-to-body>
+      <el-form ref="certificateForm" :model="certificateForm" :rules="certificateRules" label-width="100px">
+        <el-form-item label="凭证" prop="certificates">
+          <ImageUpload v-model="photoArr" type="image" :limit="1" :width="150" :height="150" />
+        </el-form-item>
+        <el-form-item label="实付金额" prop="payPrice">
+          <el-input-number v-model="certificateForm.payMoney"  size="mini"    ></el-input-number>
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="handleConfirm">确 定</el-button>
+      </div>
+    </el-dialog>
+    <el-drawer
+      :append-to-body="true"
+      size="75%"
+      :title="customer.title" :visible.sync="customer.open" append-to-body
+      >
+        <customer-details  ref="customerDetails" />
+    </el-drawer>
+    <el-dialog :title="addSms.title" :visible.sync="addSms.open" width="800px" append-to-body>
+        <add-sms ref="sms" @close="closeSms()"></add-sms>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { listStoreOrderOffline, getStoreOrderOffline, uploadCredentials } from "@/api/hisStore/storeOrderOffline";
+import ImageUpload from '@/components/ImageUpload'
+import customerDetails from '../../crm/components/customerDetails.vue';
+import addSms from '../../crm/components/addSms.vue';
+export default {
+  name: "offlineOrder",
+  components: {customerDetails,
+    ImageUpload,addSms},
+  data() {
+    return {
+      customerUserStatusOptions:[],
+      scheduleOptions:[],
+      dialogVisibleImage: false,
+      customerInfo:null,
+      customer:{
+        title:"客户详情",
+        open:false,
+      },
+      photoArr:null,
+      certificateDialig:{
+        title:"上传凭证",
+        open:false,
+      },
+      certificateForm:{
+        payMoney:null,
+        certificates:null,
+      },
+      addSms:{
+        open:false,
+        title:"发短信"
+      },
+      certificateRules:{
+        certificates:[
+          { required: true, message: "凭证不能为空", trigger: "change" }
+        ]
+      },
+      customers:[],
+
+      orderId:null,
+      statusOptions:[],
+      certificates:null,
+      order:null,
+      user:{},
+      logs:[],
+      items:[],
+      express:[],
+      traces:[],
+      payments:[],
+    };
+  },
+  created() {
+    this.getDicts("crm_customer_user_status").then((response) => {
+            this.customerUserStatusOptions = response.data;
+        });
+    this.getDicts("sys_order_offline_status").then((response) => {
+      this.statusOptions = response.data;
+    });
+
+  },
+  computed: {
+    company(){
+      return this.$store.state.user.user;
+    }
+  },
+  methods: {
+
+    closeSms(){
+      this.addSms.open=false;
+    },
+    handleSms(mobile){
+      this.addSms.open=true;
+      var that=this;
+      setTimeout(() => {
+          that.$refs.sms.getOrderId(this.orderId,mobile,2);
+      }, 500);
+    },
+    handlePhone(){
+      const id = this.order.id;
+        getUserPhone(id).then(response =>{
+          this.order.userPhone = response.userPhone;
+        })
+      },
+
+    showImageDialog() {
+      this.dialogVisible = true;
+    },
+    handleCustomer(){
+      var that=this;
+      this.customer.open = true;
+      setTimeout(() => {
+          that.$refs.customerDetails.getDetails(this.order.crmId);
+      }, 200);
+    },
+    handleCertificates(){
+      this.certificateDialig.open = true;
+      this.photoArr = null;
+    },
+    handleConfirm(){
+      this.certificateForm.orderId = this.orderId;
+      this.certificateForm.certificates = this.photoArr;
+      uploadCredentials(this.certificateForm).then(response => {
+              if (response.code === 200) {
+                this.msgSuccess("上传成功");
+                this.certificateDialig.open = false;
+                this.getOfflineOrder(this.orderId);
+              }
+            });
+    },
+    getOfflineOrder(orderId){
+      this.order = null;
+      this.orderId=orderId;
+      this.certificates = null;
+      getStoreOrderOffline(orderId).then(response => {
+            this.order = response.order;
+            if(response.order.certificates != null){
+              this.certificates = response.order.certificates;
+            }
+            this.items = response.items;
+            this.customerInfo=response.customer;
+        });
+     }
+  }
+};
+</script>
+<style scoped>
+.order-content{
+  margin: 10px;
+}
+.detail-container {
+  width: 80%;
+  padding: 20px 20px 20px 20px;
+  margin: 20px auto;
+}
+
+.operate-container {
+  background: #F2F6FC;
+  height: 60px;
+  margin: -20px -20px 0;
+  line-height: 60px;
+}
+
+.operate-button-container {
+  float: right;
+  margin-right: 20px
+}
+
+.table-layout {
+  margin-top: 20px;
+  border-left: 1px solid #DCDFE6;
+  border-top: 1px solid #DCDFE6;
+}
+
+.table-cell {
+  height: 60px;
+  line-height: 40px;
+  border-right: 1px solid #DCDFE6;
+  border-bottom: 1px solid #DCDFE6;
+  padding: 10px;
+  font-size: 14px;
+  color: #606266;
+  text-align: center;
+  overflow: hidden;
+}
+
+.table-cell-title {
+  border-right: 1px solid #DCDFE6;
+  border-bottom: 1px solid #DCDFE6;
+  padding: 10px;
+  background: #F2F6FC;
+  text-align: center;
+  font-size: 14px;
+  color: #303133;
+}
+</style>

+ 92 - 0
src/views/hisStore/components/paymentSelect.vue

@@ -0,0 +1,92 @@
+<template>
+  <div >
+    <el-table border v-loading="loading" :data="list">
+      <el-table-column label="支付订单号" align="center" prop="payCode" width="120px" />
+      <el-table-column label="会员手机号" align="center" prop="userPhone" />
+      <el-table-column label="支付类型" align="center" prop="payTypeCode" />
+      <el-table-column label="支付金额" align="center" prop="payMoney" />
+      <el-table-column label="退款金额" align="center" prop="refundMoney" />
+      <el-table-column label="交易单号" align="center" prop="bankTransactionId" />
+      <el-table-column label="银行单号" align="center" prop="bankSerialNo" />
+      <el-table-column label="所属公司" align="center" prop="companyName" />
+      <el-table-column label="所属部门" align="center" prop="deptName" />
+      <el-table-column label="员工" align="center" prop="companyUserNickName" />
+      <el-table-column label="状态" align="center" prop="status" >
+          <template slot-scope="scope">
+              <el-tag prop="status" v-for="(item, index) in statusOptions"    v-if="scope.row.status==item.dictValue">{{item.dictLabel}}</el-tag>
+          </template>
+      </el-table-column>
+      <el-table-column label="提交时间" align="center" prop="createTime" width="180">
+      </el-table-column>
+      <el-table-column label="支付时间" align="center" prop="payTime" width="180">
+      </el-table-column>
+      <el-table-column label="操作" fixed="right" align="center" width="100px" >
+        <template slot-scope="scope">
+          <el-button
+            size="mini"
+            type="text"
+            @click="handleSelect(scope.row)"
+          >选择</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+    <pagination
+      style="padding-bottom:10px;"
+      v-show="total>0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    />
+  </div>
+</template>
+
+<script>
+import { getMyPaymentList, getStorePayment, delStorePayment, addStorePayment, updateStorePayment, exportStorePayment } from "@/api/hisStore/storePayment";
+
+export default {
+  name: "paymentSelect",
+  data() {
+    return {
+      statusOptions:[],
+      loading: true,
+      list:[],
+      total: 0,
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10
+      }
+    };
+  },
+  created() {
+    this.getDicts("store_payment_status").then((response) => {
+      this.statusOptions = response.data;
+    });
+  },
+  methods: {
+    getPaymentList(){
+      this.getList();
+    },
+    handleSelect(row){
+      this.$emit('selectPayment',row);
+
+    },
+    /** 搜索按钮操作 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    getList(){
+      this.loading = true;
+      getMyPaymentList(this.queryParams).then(response => {
+        this.list = response.rows;
+        this.total = response.total;
+        this.loading = false;
+      });
+    }
+  }
+};
+</script>
+<style scoped>
+
+</style>

+ 397 - 0
src/views/hisStore/components/productAfterSalesOrder.vue

@@ -0,0 +1,397 @@
+<template>
+  <div class="order-content">
+      <div class="order-status" v-if="afterSales!=null" >
+          <el-steps :active="afterSales.status==4?afterSales.status+1:afterSales.status" align-center>
+            <el-step title="待审核(24小时自动审核)"></el-step>
+            <el-step title="平台已审核等待用户发货"></el-step>
+            <el-step title="用户已发货待仓库审核"></el-step>
+            <el-step title="财务审核"></el-step>
+            <el-step title="退款成功"></el-step>
+          </el-steps>
+      </div>
+      <div v-if="afterSales!=null">
+      <el-card shadow="never"  style="margin-top: 15px">
+        <div class="operate-container">
+          <span style="margin-left: 20px" class="color-danger">售后状态:
+            <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"  @click="showOrder">查看订单</el-button>
+         </div>
+        </div>
+        <div style="margin: 20px 0px">
+          <span class="font-small">基本信息</span>
+        </div>
+        <el-descriptions :column="4" border  >
+            <el-descriptions-item label="订单单号"  >
+                <span v-if="afterSales!=null">
+                  {{afterSales.orderCode}}
+                </span>
+            </el-descriptions-item>
+            <el-descriptions-item label="会员"  >
+                <span v-if="user!=null">
+                  {{user.nickname}}({{user.phone}})
+                </span>
+            </el-descriptions-item>
+            <el-descriptions-item label="退款金额"  >
+                <span v-if="afterSales!=null">
+                  {{afterSales.refundAmount}}
+                </span>
+            </el-descriptions-item>
+            <el-descriptions-item label="申请类型"  >
+                <span v-if="afterSales!=null">
+                  <el-tag prop="serviceType" v-for="(item, index) in serviceTypeOptions"    v-if="afterSales.serviceType==item.dictValue">{{item.dictLabel}}</el-tag>
+                </span>
+            </el-descriptions-item>
+            <el-descriptions-item label="申请原因"  >
+                <span v-if="afterSales!=null">
+                  {{afterSales.reasons}}
+                </span>
+            </el-descriptions-item>
+            <el-descriptions-item label="说明"  >
+                <span v-if="afterSales!=null">
+                  {{afterSales.explains}}
+                </span>
+            </el-descriptions-item>
+            <el-descriptions-item label="状态"  >
+                <span v-if="afterSales!=null">
+                  <el-tag   v-for="(item, index) in statusOptions"    v-if="afterSales.status==item.dictValue" >{{item.dictLabel}}</el-tag>
+                </span>
+            </el-descriptions-item>
+            <el-descriptions-item label="售后状态"  >
+                <span v-if="afterSales!=null">
+                  <el-tag  v-for="(item, index) in salesStatusOptions"    v-if="afterSales.salesStatus==item.dictValue" >{{item.dictLabel}}</el-tag>
+                </span>
+            </el-descriptions-item>
+        </el-descriptions>
+        <div style="margin: 20px 0px">
+          <span class="font-small">收货信息</span>
+        </div>
+        <el-descriptions   :column="4" border  >
+            <el-descriptions-item label="收货人"  >
+                <span v-if="afterSales!=null">
+                  {{afterSales.consignee}}
+                </span>
+            </el-descriptions-item>
+            <el-descriptions-item label="收货人"  >
+                <span v-if="afterSales!=null">
+                  {{afterSales.consignee}}
+                </span>
+            </el-descriptions-item>
+            <el-descriptions-item label="手机号码"  >
+                <span v-if="afterSales!=null">
+                  {{afterSales.phoneNumber}}
+                </span>
+            </el-descriptions-item>
+            <el-descriptions-item label="收货地址"  >
+                <span v-if="afterSales!=null">
+                  {{afterSales.address}}
+                </span>
+            </el-descriptions-item>
+            <el-descriptions-item label="快递公司"  >
+                <span v-if="afterSales!=null">
+                  {{afterSales.deliveryName}}
+                </span>
+            </el-descriptions-item>
+            <el-descriptions-item label="运单号"  >
+                <span v-if="afterSales!=null">
+                  {{afterSales.deliverySn}}
+                </span>
+            </el-descriptions-item>
+        </el-descriptions>
+        <div style="margin-top: 20px">
+          <span class="font-small">商品信息</span>
+        </div>
+        <el-table
+          border
+          :data="items"
+          size="small"
+          style="width: 100%;margin-top: 20px" >
+          <el-table-column label="商品图片" width="150" align="center">
+            <template slot-scope="scope">
+              <img :src="JSON.parse(scope.row.jsonInfo).image" style="height: 80px">
+            </template>
+          </el-table-column>
+          <el-table-column label="商品名称" width="300" align="center">
+            <template slot-scope="scope">
+              <p>{{JSON.parse(scope.row.jsonInfo).productName}}</p>
+            </template>
+          </el-table-column>
+          <el-table-column label="价格" width="240" align="center">
+            <template slot-scope="scope">
+              <p>价格:¥{{JSON.parse(scope.row.jsonInfo).price}}</p>
+
+            </template>
+          </el-table-column>
+          <el-table-column label="属性" width="240" align="center">
+            <template slot-scope="scope">
+              {{JSON.parse(scope.row.jsonInfo).sku}}
+            </template>
+          </el-table-column>
+          <el-table-column label="数量" width="180" align="center">
+            <template slot-scope="scope">
+                {{JSON.parse(scope.row.jsonInfo).num}}
+            </template>
+          </el-table-column>
+          <el-table-column label="小计"  align="center">
+            <template slot-scope="scope">
+              ¥{{JSON.parse(scope.row.jsonInfo).num*JSON.parse(scope.row.jsonInfo).price}}
+            </template>
+          </el-table-column>
+        </el-table>
+        <div style="margin-top: 20px">
+          <span class="font-small">操作信息</span>
+        </div>
+        <el-table style="margin-top: 20px;width: 100%"
+                  ref="orderHistoryTable"
+                  :data="logs" border>
+          <el-table-column label="操作时间"  width="160" align="center">
+            <template slot-scope="scope">
+              {{scope.row.changeTime}}
+            </template>
+          </el-table-column>
+          <el-table-column label="备注" align="center">
+            <template slot-scope="scope">
+              {{scope.row.changeMessage}}
+            </template>
+          </el-table-column>
+        </el-table>
+      </el-card>
+
+    </div>
+    <el-dialog :title="audit.title" :visible.sync="audit.open" width="800px" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="100px">
+        <el-form-item label="退款金额" prop="refundAmount"  >
+          <el-input-number v-model="form.refundAmount"  />
+        </el-form-item>
+        <el-form-item label="退货联系人" prop="consignee"  v-if="form.serviceType==1" >
+          <el-input v-model="form.consignee" placeholder="请输入收货人" />
+        </el-form-item>
+        <el-form-item label="退货手机号" prop="phoneNumber"  v-if="form.serviceType==1">
+          <el-input v-model="form.phoneNumber" placeholder="请输入手机号" />
+        </el-form-item>
+        <el-form-item label="退货地址" prop="address" v-if="form.serviceType==1">
+          <el-input v-model="form.address" placeholder="请输入地址" />
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitAuditForm">确 定</el-button>
+      </div>
+    </el-dialog>
+    <el-dialog :title="show.title" v-if="show.open" :visible.sync="show.open" width="1000px" append-to-body>
+        <product-order  ref="productOrder" />
+    </el-dialog>
+    <el-dialog :title="add.title" :visible.sync="add.open" width="500px" append-to-body>
+
+    <div slot="footer" class="dialog-footer">
+      <el-form ref="addForm" :model="addForm" :rules="addRules" label-width="100px">
+          <el-form-item label="id" prop="id" v-if="false">
+            <el-input v-model="addForm.id" placeholder="请输入"  />
+          </el-form-item>
+          <el-form-item label="快递公司" prop="deliveryName">
+            <el-input v-model="addForm.deliveryName" placeholder="请输入"  />
+          </el-form-item>
+          <el-form-item label="运单号" prop="deliverySn">
+            <el-input v-model="addForm.deliverySn" placeholder="请输入"  />
+          </el-form-item>
+        </el-form>
+      <el-button type="primary" @click="submitForm">确 定</el-button>
+      <el-button @click="cancel1">取 消</el-button>
+    </div>
+  </el-dialog>
+  </div>
+</template>
+
+<script>
+import {getStoreAfterSales,cancel,refund,audit,updateStoreAfterSales } from "@/api/hisStore/storeAfterSales";
+
+import productOrder from "./productOrder";
+export default {
+  components: { productOrder },
+  name: "order",
+  data() {
+    return {
+      show:{
+        open:false,
+        title:"订单详情"
+      },
+      audit:{
+          title:"审核",
+          open:false,
+      },
+      add:{
+        open:false,
+        title:"添加物流"
+      },
+      addForm:{
+        id:null,
+        deliveryName:null,
+        deliverySn:null
+      },
+      addRules:{
+        deliveryName: [
+          { required: true, message: "物流名称不能为空", trigger: "blur" }
+        ],
+        deliverySn: [
+          { required: true, message: "物流单号不能为空", trigger: "blur" }
+        ],
+      },
+      order:null,
+      user:null,
+      serviceTypeOptions:[],
+      salesStatusOptions:[],
+      statusOptions:[],
+      afterSales:null,
+      items:[],
+      logs:[],
+      form:{
+        serviceType:1,
+        refundAmount:0,
+        consignee:null,
+        phoneNumber:null,
+        address:null,
+
+      },
+      rules:{
+        status: [
+          { required: true, message: "状态不能为空", trigger: "blur" }
+        ],
+        refundAmount: [
+          { required: true, message: "退款金额不能为空", trigger: "blur" }
+        ],
+         consignee: [
+          { required: true, message: "退货联系人不能为空", trigger: "blur" }
+        ],
+        phoneNumber: [
+          { required: true, message: "退货手机号不能为空", trigger: "blur" }
+        ],
+         address: [
+          { required: true, message: "退货地址不能为空", trigger: "blur" }
+        ],
+
+      }
+
+    };
+  },
+  created() {
+    this.getDicts("store_after_sales_sales_status").then((response) => {
+        this.salesStatusOptions = response.data;
+    });
+    this.getDicts("store_after_sales_status").then((response) => {
+        this.statusOptions = response.data;
+    });
+     this.getDicts("store_after_sales_service_type").then((response) => {
+        this.serviceTypeOptions = response.data;
+    });
+  },
+  methods: {
+    submitForm() {
+      var id=this.afterSales.id;
+      this.addForm.id = id;
+      updateStoreAfterSales(this.addForm).then(response => {
+              if (response.code === 200) {
+                this.msgSuccess("编辑成功");
+                this.add.open = false;
+                this.getStoreAfterSales(id);
+              }
+            });
+    },
+    cancel1(){
+      this.add.open = false;
+    },
+    addDelivery(){
+      this.add.open = true;
+      this.addForm.deliveryName = this.afterSales.deliveryName;
+      this.addForm.deliverySn = this.afterSales.deliverySn;
+    },
+    showOrder(){
+      this.show.open=true;
+      const orderId = this.order.id ;
+      setTimeout(() => {
+        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(){
+      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;
+            this.logs = response.logs;
+            this.items = response.items;
+            this.user=response.user;
+            this.order=response.order;
+        });
+     }
+  }
+};
+</script>
+<style scoped>
+.order-content{
+  margin: 10px;
+}
+.detail-container {
+  width: 80%;
+  padding: 20px 20px 20px 20px;
+  margin: 20px auto;
+}
+
+.operate-container {
+  background: #F2F6FC;
+  height: 80px;
+  margin: -20px -20px 0;
+  line-height: 80px;
+}
+
+.operate-button-container {
+  float: right;
+  margin-right: 20px
+}
+
+
+</style>

+ 144 - 0
src/views/hisStore/components/productDetails.vue

@@ -0,0 +1,144 @@
+<template>
+  <div class="content">
+    <el-descriptions :column="4" border  >
+      <el-descriptions-item label="商品图片"  >
+          <span v-if="product!=null">
+            <el-popover
+            placement="right"
+            title=""
+            trigger="hover"
+          >
+            <img slot="reference" :src="product.image" width="100">
+            <img :src="product.image" style="max-width: 150px;">
+          </el-popover>
+          </span>
+      </el-descriptions-item>
+      <el-descriptions-item label="商品名称"  >
+          <span v-if="product!=null">
+            {{product.productName}}
+          </span>
+      </el-descriptions-item>
+      <el-descriptions-item label="售价"  >
+          <span v-if="product!=null">
+            {{product.price}}
+          </span>
+      </el-descriptions-item>
+      <el-descriptions-item label="原价"  >
+          <span v-if="product!=null">
+            {{product.otPrice}}
+          </span>
+      </el-descriptions-item>
+      <el-descriptions-item label="销量"  >
+          <span v-if="product!=null">
+            {{product.sales}}
+          </span>
+      </el-descriptions-item>
+      <el-descriptions-item label="库存"  >
+          <span v-if="product!=null">
+            {{product.stock}}
+          </span>
+      </el-descriptions-item>
+      <el-descriptions-item label="类型"  >
+          <span v-if="product!=null">
+            <el-tag prop="productType" v-for="(item, index) in productTypeOptions"    v-if="product.productType==item.dictValue">{{item.dictLabel}}</el-tag>
+          </span>
+      </el-descriptions-item>
+      <el-descriptions-item label="状态"  >
+          <span v-if="product!=null">
+            <el-tag prop="productType" v-for="(item, index) in isShowOptions"    v-if="product.isShow==item.dictValue">{{item.dictLabel}}</el-tag>
+          </span>
+      </el-descriptions-item>
+    </el-descriptions>
+    <div style="margin: 20px 0px"  v-if="items!=null">
+        <span class="font-small">
+          规格列表
+        </span>
+    </div>
+    <el-table
+      border
+      v-if="items!=null"
+      :data="items"
+      size="small"
+      style="width: 100%;margin-top: 20px" >
+      <el-table-column label="ID"  align="center">
+        <template slot-scope="scope">
+          <p>{{scope.row.id}}</p>
+        </template>
+      </el-table-column>
+      <el-table-column label="商品图片"   align="center">
+          <template slot-scope="scope">
+            <img :src="scope.row.image" style="height: 80px">
+          </template>
+        </el-table-column>
+      <el-table-column label="规格"   align="center">
+        <template slot-scope="scope">
+          <p>{{scope.row.sku}}</p>
+        </template>
+      </el-table-column>
+      <el-table-column label="售价"   align="center">
+        <template slot-scope="scope">
+          <p>¥{{scope.row.price.toFixed(2)}}</p>
+        </template>
+      </el-table-column>
+      <el-table-column label="原价"   align="center">
+        <template slot-scope="scope">
+          <p>¥{{scope.row.otPrice.toFixed(2)}}</p>
+        </template>
+      </el-table-column>
+      <el-table-column label="商品编码"   align="center">
+        <template slot-scope="scope">
+          {{scope.row.barCode}}
+        </template>
+      </el-table-column>
+      <el-table-column label="库存"  align="center">
+        <template slot-scope="scope">
+          {{scope.row.stock}}
+        </template>
+      </el-table-column>
+      <el-table-column label="销量" width="180" align="center">
+        <template slot-scope="scope">
+          {{scope.row.sales}}
+        </template>
+      </el-table-column>
+    </el-table>
+    <div v-html="product.description"></div>
+  </div>
+</template>
+
+<script>
+import {  getStoreProduct  } from "@/api/hisStore/storeProduct";
+
+export default {
+  name: "product",
+  data() {
+    return {
+      product:null,
+      isShowOptions:[],
+      productTypeOptions:[],
+      items:[],
+    };
+  },
+  created() {
+    this.getDicts("store_product_type").then((response) => {
+      this.productTypeOptions = response.data;
+    });
+    this.getDicts("store_product_is_show").then((response) => {
+      this.isShowOptions = response.data;
+    });
+  },
+  methods: {
+    getStoreProduct(productId) {
+      getStoreProduct(productId).then(response => {
+        this.product = response.product;
+        this.items=response.values
+      });
+    },
+  }
+};
+</script>
+<style scoped>
+.content{
+  margin: 10px;
+}
+
+</style>

+ 922 - 0
src/views/hisStore/components/productOrder.vue

@@ -0,0 +1,922 @@
+<template>
+  <div class="order-content">
+      <div class="order-status" v-if="order!=null" >
+          <el-steps  :active="order.status==3?order.status+1:order.status" align-center>
+            <el-step title="待支付"></el-step>
+            <el-step title="待发货"></el-step>
+            <el-step title="待收货"></el-step>
+            <el-step title="交易完成"></el-step>
+          </el-steps>
+      </div>
+      <div>
+
+      <el-card shadow="never" style="margin-top: 15px">
+      <div class="operate-container"  v-if="order!=null">
+        <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>
+        </div>
+        <div class="operate-button-container"  v-hasPermi="['store:storeOrder:express']"  >
+          <el-button size="mini" @click="showExpress()" >查看物流</el-button>
+        </div>
+      </div>
+      <div style="margin: 20px 0px"  v-if="order!=null">
+        <span class="font-small">
+          基本信息
+        </span>
+      </div>
+      <el-descriptions :column="4" border  >
+            <el-descriptions-item label="订单编号"  >
+                <span v-if="order!=null">
+                  {{order.orderCode}}
+                </span>
+                <el-tag  v-for="(item, index) in createTypeOptions"    v-if="order!=null&&order.orderCreateType==item.dictValue">{{item.dictLabel}}
+                </el-tag>
+            </el-descriptions-item>
+            <el-descriptions-item label="会员"  >
+                <span v-if="user!=null">
+                  {{user.nickname}}({{user.phone}})
+                </span>
+            </el-descriptions-item>
+            <!-- <el-descriptions-item label="进线时间"  >
+                <span v-if="user!=null">
+                  {{user.registerDate}}
+                </span>
+            </el-descriptions-item>
+            <el-descriptions-item label="推线编码"  >
+                <span v-if="user!=null">
+                  {{user.registerCode}}
+                </span>
+            </el-descriptions-item> -->
+
+            <el-descriptions-item label="收货人"  >
+                <span v-if="order!=null ">
+                  {{order.realName }}
+                </span>
+            </el-descriptions-item>
+            <el-descriptions-item label="手机号码"  >
+                <span v-if="order!=null ">
+                  {{order.userPhone }}
+                </span>
+                <el-button type="text" size="mini" @click="callNumber(0,0,orderId)"  v-hasPermi="['store:storeOrder:callNumber']">拨号</el-button>
+                <el-button type="text" size="mini" @click="handleSms(order.userPhone)" v-hasPermi="['store:storeOrder:sendSms']">短信</el-button>
+                <el-button icon="el-icon-search" size="mini" @click="handlePhone()" style="margin-left: 20px;" circle v-hasPermi="['store:storeOrder:queryPhone']"></el-button>
+            </el-descriptions-item>
+            <el-descriptions-item label="收货地址"  >
+              <el-popover
+                v-if="order!=null"
+                placement="top-start"
+                title="收货地址"
+                width="300"
+                trigger="hover"
+                :content="order.userAddress">
+                <span slot="reference">{{order.userAddress}}</span>
+                <el-button icon="el-icon-search" size="mini" @click="handleAddress()" style="margin-left: 20px;" circle v-hasPermi="['store:storeOrder:queryAddress']"></el-button>
+              </el-popover>
+            </el-descriptions-item>
+            <el-descriptions-item label="支付方式"  >
+                <span v-if="order!=null ">
+                  <el-tag prop="orderType" v-for="(item, index) in payTypeOptions"    v-if="order.payType==item.dictValue">{{item.dictLabel}}</el-tag>
+                </span>
+            </el-descriptions-item>
+            <el-descriptions-item label="订单类型"  >
+                <span v-if="order!=null ">
+                  <el-tag prop="orderType" v-for="(item, index) in orderTypeOptions"    v-if="order.orderType==item.dictValue">{{item.dictLabel}}</el-tag>
+                </span>
+            </el-descriptions-item>
+            <el-descriptions-item label="物流公司编号"  >
+                <span v-if="order!=null ">
+                  {{order.deliverySn }}
+                </span>
+            </el-descriptions-item>
+            <el-descriptions-item label="物流公司名称"  >
+                <span v-if="order!=null ">
+                  {{order.deliveryName }}
+                </span>
+            </el-descriptions-item>
+            <el-descriptions-item label="快递单号"  >
+                <span v-if="order!=null ">
+                  {{order.deliveryId }}
+                </span>
+            </el-descriptions-item>
+            <el-descriptions-item label="档期归属"  >
+              <el-tag prop="scheduleId" v-for="(item, index) in scheduleOptions"    v-if="order!=null&&order.scheduleId==item.id">{{item.name}}
+              </el-tag>
+            </el-descriptions-item>
+            <el-descriptions-item label="用户备注"  >
+                <span v-if="order!=null ">
+                  {{order.mark }}
+                </span>
+            </el-descriptions-item>
+            <el-descriptions-item label="平台备注"  >
+                <span v-if="order!=null ">
+                  {{order.remark }}
+                </span>
+            </el-descriptions-item>
+            <el-descriptions-item label="跟随阶段"  v-if="company.companyId == 174">
+              <span v-if="order!=null ">
+                <el-tag prop="orderVisit" v-for="(item, index) in customerUserStatusOptions"    v-if="order.orderVisit==item.dictValue">{{item.dictLabel}}</el-tag>
+              </span>
+            </el-descriptions-item>
+            <el-descriptions-item v-if="customerInfo!=null " label="客户编码"  >
+                <span >
+                  {{customerInfo.customerCode }}
+                </span>
+            </el-descriptions-item>
+            <el-descriptions-item v-if="customerInfo!=null " label="进线时间"  >
+                <span >
+                  {{customerInfo.registerDate }}
+                </span>
+            </el-descriptions-item>
+
+      </el-descriptions>
+      <div style="margin: 20px 0px"  v-if="order!=null">
+        <span class="font-small">
+          凭证信息
+        </span>
+      </div>
+      <el-image
+          v-if="this.certificates != null"
+          :src="certificates"
+          :preview-src-list="[certificates]"
+          :style="{ width: '100px', height: '100px' }"
+          @click.native="showImageDialog"
+        ></el-image>
+        <el-dialog :visible.sync="dialogVisibleImage" width="10%">
+          <img :src="certificates" style="width: 100%" alt="">
+        </el-dialog>
+
+      <div style="margin-top: 20px">
+        <span class="font-small">商品信息</span>
+      </div>
+      <el-table
+        border
+        v-if="items!=null"
+        :data="items"
+        size="small"
+        style="width: 100%;margin-top: 20px" >
+        <el-table-column label="商品图片" width="150" align="center">
+          <template slot-scope="scope">
+            <img :src="JSON.parse(scope.row.jsonInfo).image" style="height: 80px">
+          </template>
+        </el-table-column>
+        <el-table-column label="商品名称" width="300" align="center">
+          <template slot-scope="scope">
+            <p>{{JSON.parse(scope.row.jsonInfo).productName}}</p>
+          </template>
+        </el-table-column>
+        <el-table-column label="单价" width="240" align="center">
+          <template slot-scope="scope">
+            <p>¥{{JSON.parse(scope.row.jsonInfo).price.toFixed(2)}}</p>
+          </template>
+        </el-table-column>
+        <el-table-column label="规格" width="240" align="center">
+          <template slot-scope="scope">
+            {{JSON.parse(scope.row.jsonInfo).sku}}
+          </template>
+        </el-table-column>
+        <el-table-column label="数量" width="180" align="center">
+          <template slot-scope="scope">
+            {{scope.row.num}}
+          </template>
+        </el-table-column>
+        <el-table-column label="小计"  align="center">
+          <template slot-scope="scope" >
+            ¥{{scope.row.num*JSON.parse(scope.row.jsonInfo).price.toFixed(2)}}
+          </template>
+        </el-table-column>
+      </el-table>
+      <div style="float: right;margin: 20px" v-if="order!=null">
+        合计:<span class="color-danger">¥{{order.totalPrice.toFixed(2)}}</span>
+      </div>
+
+      <div style="margin: 60px 0px 20px 0px">
+        <span class="font-small">费用信息</span>
+      </div>
+      <el-descriptions   :column="4" border  >
+          <el-descriptions-item label="商品合计"  >
+              <span v-if="order!=null">
+                ¥{{order.totalPrice.toFixed(2)}}
+              </span>
+          </el-descriptions-item>
+          <el-descriptions-item label="应付金额"  >
+              <span v-if="order!=null">
+                ¥{{order.payPrice.toFixed(2)}}
+              </span>
+          </el-descriptions-item>
+          <el-descriptions-item label="运费"  >
+              <span v-if="order!=null">
+                ¥{{order.payPostage.toFixed(2)}}
+              </span>
+          </el-descriptions-item>
+          <el-descriptions-item label="优惠券"  >
+              <span v-if="order!=null">
+                ¥{{order.couponPrice.toFixed(2)}}
+              </span>
+          </el-descriptions-item>
+          <el-descriptions-item label="积分抵扣"  >
+              <span v-if="order!=null">
+                ¥{{order.deductionPrice.toFixed(2)}}
+              </span>
+          </el-descriptions-item>
+          <el-descriptions-item label="实付金额"  >
+              <span v-if="order!=null">
+                ¥{{order.payMoney.toFixed(2)}}
+              </span>
+          </el-descriptions-item>
+          <el-descriptions-item label="代收金额"  >
+              <span v-if="order!=null">
+                ¥{{order.payDelivery.toFixed(2)}}
+              </span>
+          </el-descriptions-item>
+      </el-descriptions>
+
+      <div style="margin-top: 20px">
+        <svg-icon icon-class="marker" style="color: #606266"></svg-icon>
+        <span class="font-small">支付信息</span>
+      </div>
+      <el-table
+        border
+        :data="payments"
+        size="small"
+        style="width: 100%;margin-top: 20px" >
+          <el-table-column label="支付单号" align="center" prop="payCode" width="120px" />
+          <el-table-column label="支付金额" align="center" prop="payMoney" />
+          <el-table-column label="类型" align="center" prop="payTypeCode" />
+          <el-table-column label="交易单号" align="center" prop="bankTransactionId" />
+          <el-table-column label="银行单号" align="center" prop="bankSerialNo" />
+          <el-table-column label="创建时间" align="center" prop="createTime" />
+          <el-table-column label="支付时间" align="center" prop="payTime" />
+      </el-table>
+
+      <div style="margin-top: 20px">
+        <span class="font-small">操作信息</span>
+      </div>
+      <el-table style="margin-top: 20px;width: 100%"
+                ref="orderHistoryTable"
+                :data="logs" border>
+        <el-table-column label="操作时间"  width="160" align="center">
+          <template slot-scope="scope">
+            {{scope.row.changeTime}}
+          </template>
+        </el-table-column>
+        <el-table-column label="备注" align="center">
+          <template slot-scope="scope">
+            {{scope.row.changeMessage}}
+          </template>
+        </el-table-column>
+      </el-table>
+
+        <div style="margin-top: 20px">
+          <span class="font-small">审批信息</span>
+        </div>
+        <el-table style="margin-top: 20px;width: 100%"
+                  :data="auditLogs" border>
+          <el-table-column label="操作时间"  width="160" align="center">
+            <template slot-scope="scope">
+              {{scope.row.createTime}}
+            </template>
+          </el-table-column>
+          <el-table-column label="备注" align="center">
+            <template slot-scope="scope">
+              {{scope.row.content}}
+            </template>
+          </el-table-column>
+        </el-table>
+      </el-card>
+    </div>
+    <el-dialog :title="edit.title" :visible.sync="edit.open" width="600px" append-to-body>
+      <el-form ref="editForm" :model="editForm" :rules="editRules" label-width="100px">
+        <el-form-item label="订单类型" prop="orderType"  >
+            <el-select style="width: 200px" v-model="editForm.orderType" placeholder="请选择订单类型" clearable size="small" >
+              <el-option
+                      v-for="item in orderTypeOptions"
+                      :key="item.dictValue"
+                      :label="item.dictLabel"
+                      :value="item.dictValue"
+                    />
+            </el-select>
+        </el-form-item>
+        <el-form-item label="档期归属" prop="scheduleId"  >
+            <el-select filterable style="width: 200px" v-model="editForm.scheduleId" placeholder="请选择档期" clearable size="small" >
+              <el-option
+                      v-for="item in scheduleOptions"
+                      :key="item.id"
+                      :label="item.name"
+                      :value="item.id"
+                    />
+            </el-select>
+        </el-form-item>
+        <el-form-item label="跟随阶段" prop="orderVisit" v-if="company.companyId == 174" >
+          <el-select filterable style="width: 200px" v-model="editForm.orderVisit" placeholder="请选择跟随阶段" clearable size="small" >
+            <el-option
+                v-for="item in customerUserStatusOptions"
+                :key="item.dictValue"
+                :label="item.dictLabel"
+                :value="item.dictValue"
+              />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="备注" prop="mark"  >
+          <el-input v-model="editForm.mark" placeholder="请输入备注" />
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitEditForm">确 定</el-button>
+      </div>
+    </el-dialog>
+    <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"
+            v-model="editUserForm.registerDate"
+            type="date"
+            value-format="yyyy-MM-dd"
+            placeholder="选择进线时间">
+          </el-date-picker>
+        </el-form-item>
+        <el-form-item label="推线编码" prop="registerCode">
+          <el-input v-model="editUserForm.registerCode" placeholder="请输入推线编码" />
+        </el-form-item>
+          <el-form-item label="渠道来源" prop="source">
+          <el-input v-model="editUserForm.source" placeholder="请输入渠道来源" />
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitEditUserForm">确 定</el-button>
+      </div>
+    </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-input v-model="editAddressForm.realName" placeholder="请输入收件人" />
+        </el-form-item>
+          <el-form-item label="联系电话" prop="source">
+          <el-input v-model="editAddressForm.userPhone" placeholder="请输入联系电话" />
+        </el-form-item>
+        <el-form-item label="收货地址" prop="district">
+          <el-row :gutter="20">
+          <el-col :span="6">
+             <el-select @change="provinceChange" v-model="editAddressForm.provinceId" placeholder="请选择">
+                <el-option
+                  v-for="item in province"
+                  :key="item.cityId"
+                  :label="item.name"
+                  :value="item.cityId">
+                </el-option>
+              </el-select>
+          </el-col>
+          <el-col :span="6">
+            <el-select @change="cityChange" v-model="editAddressForm.cityId" placeholder="请选择">
+                <el-option
+                  v-for="item in city"
+                  :key="item.cityId"
+                  :label="item.name"
+                  :value="item.cityId">
+                </el-option>
+              </el-select>
+          </el-col>
+          <el-col :span="6">
+             <el-select @change="districtChange" v-model="editAddressForm.districtId" placeholder="请选择">
+                <el-option
+                  v-for="item in district"
+                  :key="item.cityId"
+                  :label="item.name"
+                  :value="item.cityId">
+                </el-option>
+              </el-select>
+          </el-col>
+        </el-row>
+        </el-form-item>
+        <el-form-item label="详细地址" prop="detail">
+          <el-input v-model="editAddressForm.detail" placeholder="请输入收货人详细地址" />
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitEditAddressForm">确 定</el-button>
+      </div>
+    </el-dialog>
+    <el-dialog :title="expressDialog.title" :visible.sync="expressDialog.open" width="600px" append-to-body>
+      <el-table style="margin-top: 20px;width: 100%"
+                ref="orderHistoryTable"
+                :data="traces" border>
+        <el-table-column label="操作时间"  width="160" align="center">
+          <template slot-scope="scope">
+            {{scope.row.AcceptTime}}
+          </template>
+        </el-table-column>
+         <el-table-column label="位置" align="center">
+          <template slot-scope="scope">
+            {{scope.row.Location}}
+          </template>
+        </el-table-column>
+        <el-table-column label="描述" align="center">
+          <template slot-scope="scope">
+            {{scope.row.AcceptStation}}
+          </template>
+        </el-table-column>
+      </el-table>
+    </el-dialog>
+    <el-dialog :title="bindCustomerDialog.title" :visible.sync="bindCustomerDialog.open" width="800px" append-to-body>
+      <el-form ref="bindCustomerForm" :model="bindCustomerForm" :rules="bindCustomerRules" label-width="100px">
+        <el-form-item label="客户查询">
+          <el-row :gutter="10" class="mb8">
+            <el-col :span="1.5">
+              <el-input v-model="bindCustomerForm.mobile"   placeholder="请输入客户手机号"/>
+            </el-col>
+            <el-col :span="1.5">
+              <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"
+                :data="customers" border>
+            <el-table-column type="selection" width="55" align="center" />
+            <el-table-column label="ID" align="center" prop="customerId" />
+            <el-table-column label="客户编号"  width="160" align="center">
+              <template slot-scope="scope">
+                {{scope.row.customerCode}}
+              </template>
+            </el-table-column>
+            <el-table-column label="客户名称"  width="160" align="center">
+              <template slot-scope="scope">
+                {{scope.row.customerName}}
+              </template>
+            </el-table-column>
+            <el-table-column label="客户手机号"  width="160" align="center">
+              <template slot-scope="scope">
+                {{scope.row.mobile}}
+              </template>
+            </el-table-column>
+          </el-table>
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitBindCustomerForm">确 定</el-button>
+      </div>
+    </el-dialog>
+    <el-dialog :title="certificateDialig.title" :visible.sync="certificateDialig.open" append-to-body>
+      <el-form ref="certificateForm" :model="certificateForm" :rules="certificateRules" label-width="100px">
+        <el-form-item label="凭证" prop="certificates">
+          <ImageUpload v-model="photoArr" type="image" :num="10" :width="150" :height="150" />
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="handleConfirm">确 定</el-button>
+      </div>
+    </el-dialog>
+    <el-drawer
+      :append-to-body="true"
+      size="75%"
+      :title="customer.title" :visible.sync="customer.open"
+      >
+        <customer-details  ref="customerDetails" />
+    </el-drawer>
+    <el-dialog :title="addSms.title" :visible.sync="addSms.open" width="800px" append-to-body>
+        <add-sms ref="sms" @close="closeSms()"></add-sms>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import {updateUser,getUser } from "@/api/users/user";
+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 {getCitys} from "@/api/hisStore/city";
+import customerDetails from '../../crm/components/customerDetails.vue';
+import addSms from '../../crm/components/addSms.vue';
+export default {
+  name: "order",
+  components: {customerDetails,
+    ImageUpload,Material ,addSms},
+  data() {
+    return {
+      customerUserStatusOptions:[],
+      scheduleOptions:[],
+      dialogVisibleImage: false,
+      customerInfo:null,
+      customer:{
+        title:"客户详情",
+        open:false,
+      },
+      photoArr:null,
+      certificateDialig:{
+        title:"上传凭证",
+        open:false,
+      },
+      certificateForm:{
+        orderCode:null,
+        certificates:null,
+      },
+      addSms:{
+        open:false,
+        title:"发短信"
+      },
+      certificateRules:{
+        certificates:[
+          { required: true, message: "凭证不能为空", trigger: "change" }
+        ]
+      },
+      customers:[],
+      bindCustomerDialog:{
+        title:"关联客户",
+        open:false,
+      },
+      bindCustomerForm:{
+        mobile:null,
+        customerIds:null,
+      },
+      bindCustomerRules:{
+        customerIds: [
+            { required: true, message: "客户不能为空", trigger: "change" }
+        ],
+
+      },
+      orderId:null,
+      expressDialog:{
+        title:"物流信息",
+        open:false,
+      },
+      citys:[],
+      province:[],
+      city:[],
+      district:[],
+      editAddress:{
+        title:"修改收货地址",
+        open:false,
+      },
+      editAddressForm:{
+        districtId:null,
+
+      },
+      editAddressRules:{
+
+      },
+      editUser:{
+        title:"修改会员信息",
+        open:false,
+      },
+      editUserForm:{
+        registerDate:null,
+        registerCode:"",
+        source:"",
+      },
+      editUserRules:{
+
+      },
+      edit:{
+        title:"",
+        open:false,
+      },
+      editForm:{
+        orderType:null,
+        scheduleId:null,
+        orderVisit:null,
+        mark:"",
+      },
+      editRules:{
+
+      },
+      createTypeOptions:[],
+      orderTypeOptions:[],
+      payTypeOptions:[],
+      statusOptions:[],
+      certificates:null,
+      order:null,
+      user:{},
+      logs:[],
+      items:[],
+      express:[],
+      traces:[],
+      payments:[],
+      auditLogs: []
+    };
+  },
+  created() {
+    this.getDicts("crm_customer_user_status").then((response) => {
+            this.customerUserStatusOptions = response.data;
+        });
+    this.getDicts("store_order_type").then((response) => {
+      this.orderTypeOptions = response.data;
+    });
+    this.getDicts("store_order_status").then((response) => {
+      this.statusOptions = response.data;
+    });
+    this.getDicts("store_pay_type").then((response) => {
+      this.payTypeOptions = response.data;
+    });
+    this.getDicts("store_order_create_type").then((response) => {
+      this.createTypeOptions = response.data;
+    });
+    getTcmScheduleList().then(response => {
+      this.scheduleOptions = response.data;
+    });
+  },
+  computed: {
+    company(){
+      return this.$store.state.user.user;
+    }
+  },
+  methods: {
+    closeSms(){
+      this.addSms.open=false;
+    },
+    handleSms(mobile){
+        this.addSms.open=true;
+        var that=this;
+        setTimeout(() => {
+            that.$refs.sms.getOrderId(this.orderId,mobile,2);
+        }, 500);
+
+    },
+    handlePhone(){
+      const id = this.order.id;
+        getUserPhone(id).then(response =>{
+          this.order.userPhone = response.userPhone;
+        })
+      },
+    handleAddress(){
+      const id = this.order.id;
+      getStoreOrderAddress(id).then(response =>{
+          this.order.userAddress = response.address;
+      })
+    },
+    showImageDialog() {
+      this.dialogVisible = true;
+    },
+    handleCustomer(){
+      var that=this;
+      this.customer.open = true;
+      setTimeout(() => {
+          that.$refs.customerDetails.getDetails(this.order.customerId);
+      }, 200);
+    },
+    handleSelectionChange(selection) {
+      this.bindCustomerForm.customerIds = selection.map(item => item.customerId)
+    },
+    searchCustomer(){
+      if(this.bindCustomerForm.mobile==null||this.bindCustomerForm.mobile==""){
+        this.msgError("请输入手机号");
+        return;
+      }
+      var data={mobile:this.bindCustomerForm.mobile};
+      getCustomerListBySearch(data).then(response => {
+          this.customers=response.data;
+      });
+    },
+    handleBindCustomer() {
+      this.customers=[];
+      this.bindCustomerDialog.open = true;
+      this.bindCustomerForm.mobile=null;
+      this.bindCustomerForm.orderId=this.orderId;
+      this.bindCustomerForm.customerIds=null;
+    },
+    /** 提交按钮 */
+    submitBindCustomerForm() {
+      this.$refs["bindCustomerForm"].validate(valid => {
+        if (valid) {
+          bindCustomer(this.bindCustomerForm).then(response => {
+              if (response.code === 200) {
+                this.msgSuccess("修改成功");
+                this.bindCustomerDialog.open = false;
+              }
+            });
+        }
+      });
+    },
+    handleCertificates(){
+      this.certificateDialig.open = true;
+      this.photoArr = null;
+    },
+    handleConfirm(){
+      this.certificateForm.id = this.orderId;
+      this.certificateForm.orderCode = this.order.orderCode;
+      this.certificateForm.certificates = this.photoArr;
+      uploadCredentials(this.certificateForm).then(response => {
+              if (response.code === 200) {
+                this.msgSuccess("上传成功");
+                this.certificateDialig.open = false;
+                this.getOrder(this.order.id);
+              }
+            });
+    },
+    showExpress(){
+      this.expressDialog.open=true;
+      getExpress(this.orderId).then(response => {
+          this.express = response.data;
+          if(this.express!=null&&this.express.Traces!=null){
+              this.traces=this.express.Traces
+          }
+
+      });
+
+    },
+    districtChange(val){
+      var item=this.citys.find((item)=>{
+        return item.cityId==val&&item.level==2;
+      })
+      this.editAddressForm.district=item.name;
+
+    },
+    cityChange(val){
+      this.district=this.citys.filter(item => item.parentId===val )
+      this.editAddressForm.districtId=null;
+      var item=this.citys.find((item)=>{
+        return item.cityId==val&&item.level==1;
+      })
+      this.editAddressForm.city=item.name;
+
+
+    },
+    provinceChange(val){
+      this.city=this.citys.filter(item => item.parentId===val )
+      this.district=[];
+      this.editAddressForm.cityId=null;
+      this.editAddressForm.districtId=null;
+      var item=this.citys.find((item)=>{
+        return item.cityId==val&&item.level==0;
+      })
+      this.editAddressForm.province=item.name;
+    },
+    getCityList(){
+      getCitys().then(res => {
+          this.citys=res.data;
+          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;
+        })
+
+        if(city!=null){
+          this.editAddressForm.cityId=city.cityId;
+          this.district=this.citys.filter(item => item.parentId===city.cityId&&item.level==2 )
+        }
+        var district=this.citys.find((item)=>{
+          return item.name==address[2]&&item.level==2;
+        })
+        if(district!=null){
+          this.editAddressForm.districtId=district.cityId;
+        }
+
+        this.editAddress.open = true;
+    },
+    /** 提交按钮 */
+    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 => {
+              if (response.code === 200) {
+                this.msgSuccess("修改成功");
+                this.editAddress.open = false;
+                this.getOrder(this.order.id);
+              }
+            });
+        }
+      });
+    },
+    handleEditUser() {
+      const userId = this.order.userId
+      getUser(userId).then(response => {
+        this.editUserForm.userId=response.data.userId;
+        this.editUserForm.registerDate=response.data.registerDate;
+        this.editUserForm.registerCode=response.data.registerCode;
+        this.editUserForm.source=response.data.source;
+        this.editUser.open = true;
+      });
+    },
+    /** 提交按钮 */
+    submitEditUserForm() {
+      this.$refs["editUserForm"].validate(valid => {
+        if (valid) {
+            updateUser(this.editUserForm).then(response => {
+              if (response.code === 200) {
+                this.msgSuccess("修改成功");
+                this.editUser.open = false;
+                this.getOrder(this.order.id);
+              }
+            });
+        }
+      });
+    },
+    submitEditForm(){
+        this.$refs["editForm"].validate(valid => {
+        if (valid) {
+          updateStoreOrder(this.editForm).then(response => {
+            if (response.code === 200) {
+              this.msgSuccess("操作成功");
+              this.edit.open = false;
+              this.getOrder(this.order.id);
+            }
+          });
+
+        }
+      });
+    },
+    editOrder(){
+        this.edit.open=true;
+        this.editForm.mark=this.order.mark
+        this.editForm.id=this.order.id;
+        if(this.order.orderType!=null){
+          this.editForm.orderType=this.order.orderType.toString();
+        }
+        this.editForm.scheduleId=this.order.scheduleId;
+        this.editForm.orderVisit = this.order.orderVisit;
+
+    },
+    getOrder(orderId){
+        this.orderId=orderId;
+        this.certificates = null;
+        getStoreOrder(orderId).then(response => {
+            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;
+            this.payments=response.payments;
+            this.customerInfo=response.customer;
+            this.auditLogs = response.auditLogs;
+        });
+     }
+  }
+};
+</script>
+<style scoped>
+.order-content{
+  margin: 10px;
+}
+.detail-container {
+  width: 80%;
+  padding: 20px 20px 20px 20px;
+  margin: 20px auto;
+}
+
+.operate-container {
+  background: #F2F6FC;
+  height: 60px;
+  margin: -20px -20px 0;
+  line-height: 60px;
+}
+
+.operate-button-container {
+  float: right;
+  margin-right: 20px
+}
+
+.table-layout {
+  margin-top: 20px;
+  border-left: 1px solid #DCDFE6;
+  border-top: 1px solid #DCDFE6;
+}
+
+.table-cell {
+  height: 60px;
+  line-height: 40px;
+  border-right: 1px solid #DCDFE6;
+  border-bottom: 1px solid #DCDFE6;
+  padding: 10px;
+  font-size: 14px;
+  color: #606266;
+  text-align: center;
+  overflow: hidden;
+}
+
+.table-cell-title {
+  border-right: 1px solid #DCDFE6;
+  border-bottom: 1px solid #DCDFE6;
+  padding: 10px;
+  background: #F2F6FC;
+  text-align: center;
+  font-size: 14px;
+  color: #303133;
+}
+</style>

+ 903 - 0
src/views/hisStore/components/productOrder2.vue

@@ -0,0 +1,903 @@
+<template>
+  <div class="order-content">
+      <div class="order-status" v-if="order!=null" >
+          <el-steps  :active="order.status==3?order.status+1:order.status" align-center>
+            <el-step title="待支付"></el-step>
+            <el-step title="待发货"></el-step>
+            <el-step title="待收货"></el-step>
+            <el-step title="交易完成"></el-step>
+          </el-steps>
+      </div>
+      <div>
+
+      <el-card shadow="never" style="margin-top: 15px">
+      <div class="operate-container"  v-if="order!=null">
+        <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>
+        </div>
+        <div class="operate-button-container"  v-hasPermi="['store:storeOrder:express']"  >
+          <el-button size="mini" @click="showExpress()" >查看物流</el-button>
+        </div>
+      </div>
+      <div style="margin: 20px 0px"  v-if="order!=null">
+        <span class="font-small">
+          基本信息
+        </span>
+      </div>
+      <el-descriptions :column="4" border  >
+            <el-descriptions-item label="订单编号"  >
+                <span v-if="order!=null">
+                  {{order.orderCode}}
+                </span>
+                <el-tag  v-for="(item, index) in createTypeOptions"    v-if="order!=null&&order.orderCreateType==item.dictValue">{{item.dictLabel}}
+                </el-tag>
+            </el-descriptions-item>
+            <el-descriptions-item label="会员"  >
+                <span v-if="user!=null">
+                  {{user.nickname}}({{user.phone}})
+                </span>
+            </el-descriptions-item>
+            <!-- <el-descriptions-item label="进线时间"  >
+                <span v-if="user!=null">
+                  {{user.registerDate}}
+                </span>
+            </el-descriptions-item>
+            <el-descriptions-item label="推线编码"  >
+                <span v-if="user!=null">
+                  {{user.registerCode}}
+                </span>
+            </el-descriptions-item> -->
+
+            <el-descriptions-item label="收货人"  >
+                <span v-if="order!=null ">
+                  {{order.realName }}
+                </span>
+            </el-descriptions-item>
+            <el-descriptions-item label="手机号码"  >
+                <span v-if="order!=null ">
+                  {{order.userPhone }}
+                </span>
+                <el-button type="text" size="mini" @click="callNumber(0,0,orderId)"  v-hasPermi="['store:storeOrder:callNumber']">拨号</el-button>
+                <el-button type="text" size="mini" @click="handleSms(order.userPhone)" v-hasPermi="['store:storeOrder:sendSms']">短信</el-button>
+                <el-button icon="el-icon-search" size="mini" @click="handlePhone()" style="margin-left: 20px;" circle v-hasPermi="['store:storeOrder:queryPhone']"></el-button>
+            </el-descriptions-item>
+            <el-descriptions-item label="收货地址"  >
+              <el-popover
+                v-if="order!=null"
+                placement="top-start"
+                title="收货地址"
+                width="300"
+                trigger="hover"
+                :content="order.userAddress">
+                <span slot="reference">{{order.userAddress}}</span>
+                <el-button icon="el-icon-search" size="mini" @click="handleAddress()" style="margin-left: 20px;" circle v-hasPermi="['store:storeOrder:queryAddress']"></el-button>
+              </el-popover>
+            </el-descriptions-item>
+            <el-descriptions-item label="支付方式"  >
+                <span v-if="order!=null ">
+                  <el-tag prop="orderType" v-for="(item, index) in payTypeOptions"    v-if="order.payType==item.dictValue">{{item.dictLabel}}</el-tag>
+                </span>
+            </el-descriptions-item>
+            <el-descriptions-item label="订单类型"  >
+                <span v-if="order!=null ">
+                  <el-tag prop="orderType" v-for="(item, index) in orderTypeOptions"    v-if="order.orderType==item.dictValue">{{item.dictLabel}}</el-tag>
+                </span>
+            </el-descriptions-item>
+            <el-descriptions-item label="物流公司编号"  >
+                <span v-if="order!=null ">
+                  {{order.deliverySn }}
+                </span>
+            </el-descriptions-item>
+            <el-descriptions-item label="物流公司名称"  >
+                <span v-if="order!=null ">
+                  {{order.deliveryName }}
+                </span>
+            </el-descriptions-item>
+            <el-descriptions-item label="快递单号"  >
+                <span v-if="order!=null ">
+                  {{order.deliveryId }}
+                </span>
+            </el-descriptions-item>
+            <el-descriptions-item label="档期归属"  >
+              <el-tag prop="scheduleId" v-for="(item, index) in scheduleOptions"    v-if="order!=null&&order.scheduleId==item.id">{{item.name}}
+              </el-tag>
+            </el-descriptions-item>
+            <el-descriptions-item label="用户备注"  >
+                <span v-if="order!=null ">
+                  {{order.mark }}
+                </span>
+            </el-descriptions-item>
+            <el-descriptions-item label="平台备注"  >
+                <span v-if="order!=null ">
+                  {{order.remark }}
+                </span>
+            </el-descriptions-item>
+            <el-descriptions-item label="跟随阶段"  v-if="company.companyId == 174">
+              <span v-if="order!=null ">
+                <el-tag prop="orderVisit" v-for="(item, index) in customerUserStatusOptions"    v-if="order.orderVisit==item.dictValue">{{item.dictLabel}}</el-tag>
+              </span>
+            </el-descriptions-item>
+            <el-descriptions-item v-if="customerInfo!=null " label="客户编码"  >
+                <span >
+                  {{customerInfo.customerCode }}
+                </span>
+            </el-descriptions-item>
+            <el-descriptions-item v-if="customerInfo!=null " label="进线时间"  >
+                <span >
+                  {{customerInfo.registerDate }}
+                </span>
+            </el-descriptions-item>
+
+      </el-descriptions>
+      <div style="margin: 20px 0px"  v-if="order!=null">
+        <span class="font-small">
+          凭证信息
+        </span>
+      </div>
+      <el-image
+          v-if="this.certificates != null"
+          :src="certificates"
+          :preview-src-list="[certificates]"
+          :style="{ width: '100px', height: '100px' }"
+          @click.native="showImageDialog"
+        ></el-image>
+        <el-dialog :visible.sync="dialogVisibleImage" width="10%">
+          <img :src="certificates" style="width: 100%" alt="">
+        </el-dialog>
+
+      <div style="margin-top: 20px">
+        <span class="font-small">商品信息</span>
+      </div>
+      <el-table
+        border
+        v-if="items!=null"
+        :data="items"
+        size="small"
+        style="width: 100%;margin-top: 20px" >
+        <el-table-column label="商品图片" width="150" align="center">
+          <template slot-scope="scope">
+            <img :src="JSON.parse(scope.row.jsonInfo).image" style="height: 80px">
+          </template>
+        </el-table-column>
+        <el-table-column label="商品名称" width="300" align="center">
+          <template slot-scope="scope">
+            <p>{{JSON.parse(scope.row.jsonInfo).productName}}</p>
+          </template>
+        </el-table-column>
+        <el-table-column label="单价" width="240" align="center">
+          <template slot-scope="scope">
+            <p>¥{{JSON.parse(scope.row.jsonInfo).price.toFixed(2)}}</p>
+          </template>
+        </el-table-column>
+        <el-table-column label="规格" width="240" align="center">
+          <template slot-scope="scope">
+            {{JSON.parse(scope.row.jsonInfo).sku}}
+          </template>
+        </el-table-column>
+        <el-table-column label="数量" width="180" align="center">
+          <template slot-scope="scope">
+            {{scope.row.num}}
+          </template>
+        </el-table-column>
+        <el-table-column label="小计"  align="center">
+          <template slot-scope="scope" >
+            ¥{{scope.row.num*JSON.parse(scope.row.jsonInfo).price.toFixed(2)}}
+          </template>
+        </el-table-column>
+      </el-table>
+      <div style="float: right;margin: 20px" v-if="order!=null">
+        合计:<span class="color-danger">¥{{order.totalPrice.toFixed(2)}}</span>
+      </div>
+
+      <div style="margin: 60px 0px 20px 0px">
+        <span class="font-small">费用信息</span>
+      </div>
+      <el-descriptions   :column="4" border  >
+          <el-descriptions-item label="商品合计"  >
+              <span v-if="order!=null">
+                ¥{{order.totalPrice.toFixed(2)}}
+              </span>
+          </el-descriptions-item>
+          <el-descriptions-item label="应付金额"  >
+              <span v-if="order!=null">
+                ¥{{order.payPrice.toFixed(2)}}
+              </span>
+          </el-descriptions-item>
+          <el-descriptions-item label="运费"  >
+              <span v-if="order!=null">
+                ¥{{order.payPostage.toFixed(2)}}
+              </span>
+          </el-descriptions-item>
+          <el-descriptions-item label="优惠券"  >
+              <span v-if="order!=null">
+                ¥{{order.couponPrice.toFixed(2)}}
+              </span>
+          </el-descriptions-item>
+          <el-descriptions-item label="积分抵扣"  >
+              <span v-if="order!=null">
+                ¥{{order.deductionPrice.toFixed(2)}}
+              </span>
+          </el-descriptions-item>
+          <el-descriptions-item label="实付金额"  >
+              <span v-if="order!=null">
+                ¥{{order.payMoney.toFixed(2)}}
+              </span>
+          </el-descriptions-item>
+          <el-descriptions-item label="代收金额"  >
+              <span v-if="order!=null">
+                ¥{{order.payDelivery.toFixed(2)}}
+              </span>
+          </el-descriptions-item>
+      </el-descriptions>
+
+      <div style="margin-top: 20px">
+        <svg-icon icon-class="marker" style="color: #606266"></svg-icon>
+        <span class="font-small">支付信息</span>
+      </div>
+      <el-table
+        border
+        :data="payments"
+        size="small"
+        style="width: 100%;margin-top: 20px" >
+          <el-table-column label="支付单号" align="center" prop="payCode" width="120px" />
+          <el-table-column label="支付金额" align="center" prop="payMoney" />
+          <el-table-column label="类型" align="center" prop="payTypeCode" />
+          <el-table-column label="交易单号" align="center" prop="bankTransactionId" />
+          <el-table-column label="银行单号" align="center" prop="bankSerialNo" />
+          <el-table-column label="创建时间" align="center" prop="createTime" />
+          <el-table-column label="支付时间" align="center" prop="payTime" />
+      </el-table>
+
+      <div style="margin-top: 20px">
+        <span class="font-small">操作信息</span>
+      </div>
+      <el-table style="margin-top: 20px;width: 100%"
+                ref="orderHistoryTable"
+                :data="logs" border>
+        <el-table-column label="操作时间"  width="160" align="center">
+          <template slot-scope="scope">
+            {{scope.row.changeTime}}
+          </template>
+        </el-table-column>
+        <el-table-column label="备注" align="center">
+          <template slot-scope="scope">
+            {{scope.row.changeMessage}}
+          </template>
+        </el-table-column>
+      </el-table>
+      </el-card>
+    </div>
+    <el-dialog :title="edit.title" :visible.sync="edit.open" width="600px" append-to-body>
+      <el-form ref="editForm" :model="editForm" :rules="editRules" label-width="100px">
+        <el-form-item label="订单类型" prop="orderType"  >
+            <el-select style="width: 200px" v-model="editForm.orderType" placeholder="请选择订单类型" clearable size="small" >
+              <el-option
+                      v-for="item in orderTypeOptions"
+                      :key="item.dictValue"
+                      :label="item.dictLabel"
+                      :value="item.dictValue"
+                    />
+            </el-select>
+        </el-form-item>
+        <el-form-item label="档期归属" prop="scheduleId"  >
+            <el-select filterable style="width: 200px" v-model="editForm.scheduleId" placeholder="请选择档期" clearable size="small" >
+              <el-option
+                      v-for="item in scheduleOptions"
+                      :key="item.id"
+                      :label="item.name"
+                      :value="item.id"
+                    />
+            </el-select>
+        </el-form-item>
+        <el-form-item label="跟随阶段" prop="orderVisit" v-if="company.companyId == 174" >
+          <el-select filterable style="width: 200px" v-model="editForm.orderVisit" placeholder="请选择跟随阶段" clearable size="small" >
+            <el-option
+                v-for="item in customerUserStatusOptions"
+                :key="item.dictValue"
+                :label="item.dictLabel"
+                :value="item.dictValue"
+              />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="备注" prop="mark"  >
+          <el-input v-model="editForm.mark" placeholder="请输入备注" />
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitEditForm">确 定</el-button>
+      </div>
+    </el-dialog>
+    <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"
+            v-model="editUserForm.registerDate"
+            type="date"
+            value-format="yyyy-MM-dd"
+            placeholder="选择进线时间">
+          </el-date-picker>
+        </el-form-item>
+        <el-form-item label="推线编码" prop="registerCode">
+          <el-input v-model="editUserForm.registerCode" placeholder="请输入推线编码" />
+        </el-form-item>
+          <el-form-item label="渠道来源" prop="source">
+          <el-input v-model="editUserForm.source" placeholder="请输入渠道来源" />
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitEditUserForm">确 定</el-button>
+      </div>
+    </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-input v-model="editAddressForm.realName" placeholder="请输入收件人" />
+        </el-form-item>
+          <el-form-item label="联系电话" prop="source">
+          <el-input v-model="editAddressForm.userPhone" placeholder="请输入联系电话" />
+        </el-form-item>
+        <el-form-item label="收货地址" prop="district">
+          <el-row :gutter="20">
+          <el-col :span="6">
+             <el-select @change="provinceChange" v-model="editAddressForm.provinceId" placeholder="请选择">
+                <el-option
+                  v-for="item in province"
+                  :key="item.cityId"
+                  :label="item.name"
+                  :value="item.cityId">
+                </el-option>
+              </el-select>
+          </el-col>
+          <el-col :span="6">
+            <el-select @change="cityChange" v-model="editAddressForm.cityId" placeholder="请选择">
+                <el-option
+                  v-for="item in city"
+                  :key="item.cityId"
+                  :label="item.name"
+                  :value="item.cityId">
+                </el-option>
+              </el-select>
+          </el-col>
+          <el-col :span="6">
+             <el-select @change="districtChange" v-model="editAddressForm.districtId" placeholder="请选择">
+                <el-option
+                  v-for="item in district"
+                  :key="item.cityId"
+                  :label="item.name"
+                  :value="item.cityId">
+                </el-option>
+              </el-select>
+          </el-col>
+        </el-row>
+        </el-form-item>
+        <el-form-item label="详细地址" prop="detail">
+          <el-input v-model="editAddressForm.detail" placeholder="请输入收货人详细地址" />
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitEditAddressForm">确 定</el-button>
+      </div>
+    </el-dialog>
+    <el-dialog :title="expressDialog.title" :visible.sync="expressDialog.open" width="600px" append-to-body>
+      <el-table style="margin-top: 20px;width: 100%"
+                ref="orderHistoryTable"
+                :data="traces" border>
+        <el-table-column label="操作时间"  width="160" align="center">
+          <template slot-scope="scope">
+            {{scope.row.AcceptTime}}
+          </template>
+        </el-table-column>
+         <el-table-column label="位置" align="center">
+          <template slot-scope="scope">
+            {{scope.row.Location}}
+          </template>
+        </el-table-column>
+        <el-table-column label="描述" align="center">
+          <template slot-scope="scope">
+            {{scope.row.AcceptStation}}
+          </template>
+        </el-table-column>
+      </el-table>
+    </el-dialog>
+    <el-dialog :title="bindCustomerDialog.title" :visible.sync="bindCustomerDialog.open" width="800px" append-to-body>
+      <el-form ref="bindCustomerForm" :model="bindCustomerForm" :rules="bindCustomerRules" label-width="100px">
+        <el-form-item label="客户查询">
+          <el-row :gutter="10" class="mb8">
+            <el-col :span="1.5">
+              <el-input v-model="bindCustomerForm.mobile"   placeholder="请输入客户手机号"/>
+            </el-col>
+            <el-col :span="1.5">
+              <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"
+                :data="customers" border>
+            <el-table-column type="selection" width="55" align="center" />
+            <el-table-column label="ID" align="center" prop="customerId" />
+            <el-table-column label="客户编号"  width="160" align="center">
+              <template slot-scope="scope">
+                {{scope.row.customerCode}}
+              </template>
+            </el-table-column>
+            <el-table-column label="客户名称"  width="160" align="center">
+              <template slot-scope="scope">
+                {{scope.row.customerName}}
+              </template>
+            </el-table-column>
+            <el-table-column label="客户手机号"  width="160" align="center">
+              <template slot-scope="scope">
+                {{scope.row.mobile}}
+              </template>
+            </el-table-column>
+          </el-table>
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitBindCustomerForm">确 定</el-button>
+      </div>
+    </el-dialog>
+    <el-dialog :title="certificateDialig.title" :visible.sync="certificateDialig.open" append-to-body>
+      <el-form ref="certificateForm" :model="certificateForm" :rules="certificateRules" label-width="100px">
+        <el-form-item label="凭证" prop="certificates">
+          <ImageUpload v-model="photoArr" type="image" :num="10" :width="150" :height="150" />
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="handleConfirm">确 定</el-button>
+      </div>
+    </el-dialog>
+    <el-drawer
+      :append-to-body="true"
+      size="75%"
+      :title="customer.title" :visible.sync="customer.open"
+      >
+        <customer-details  ref="customerDetails" />
+    </el-drawer>
+    <el-dialog :title="addSms.title" :visible.sync="addSms.open" width="800px" append-to-body>
+        <add-sms ref="sms" @close="closeSms()"></add-sms>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import {updateUser,getUser } from "@/api/users/user";
+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 {getCitys} from "@/api/hisStore/city";
+import customerDetails from '../../crm/components/customerDetails.vue';
+import addSms from '../../crm/components/addSms.vue';
+export default {
+  name: "order",
+  components: {customerDetails,
+    ImageUpload,Material ,addSms},
+  data() {
+    return {
+      customerUserStatusOptions:[],
+      scheduleOptions:[],
+      dialogVisibleImage: false,
+      customerInfo:null,
+      customer:{
+        title:"客户详情",
+        open:false,
+      },
+      photoArr:null,
+      certificateDialig:{
+        title:"上传凭证",
+        open:false,
+      },
+      certificateForm:{
+        orderCode:null,
+        certificates:null,
+      },
+      addSms:{
+        open:false,
+        title:"发短信"
+      },
+      certificateRules:{
+        certificates:[
+          { required: true, message: "凭证不能为空", trigger: "change" }
+        ]
+      },
+      customers:[],
+      bindCustomerDialog:{
+        title:"关联客户",
+        open:false,
+      },
+      bindCustomerForm:{
+        mobile:null,
+        customerIds:null,
+      },
+      bindCustomerRules:{
+        customerIds: [
+            { required: true, message: "客户不能为空", trigger: "change" }
+        ],
+
+      },
+      orderId:null,
+      expressDialog:{
+        title:"物流信息",
+        open:false,
+      },
+      citys:[],
+      province:[],
+      city:[],
+      district:[],
+      editAddress:{
+        title:"修改收货地址",
+        open:false,
+      },
+      editAddressForm:{
+        districtId:null,
+
+      },
+      editAddressRules:{
+
+      },
+      editUser:{
+        title:"修改会员信息",
+        open:false,
+      },
+      editUserForm:{
+        registerDate:null,
+        registerCode:"",
+        source:"",
+      },
+      editUserRules:{
+
+      },
+      edit:{
+        title:"",
+        open:false,
+      },
+      editForm:{
+        orderType:null,
+        scheduleId:null,
+        orderVisit:null,
+        mark:"",
+      },
+      editRules:{
+
+      },
+      createTypeOptions:[],
+      orderTypeOptions:[],
+      payTypeOptions:[],
+      statusOptions:[],
+      certificates:null,
+      order:null,
+      user:{},
+      logs:[],
+      items:[],
+      express:[],
+      traces:[],
+      payments:[],
+    };
+  },
+  created() {
+    this.getDicts("crm_customer_user_status").then((response) => {
+            this.customerUserStatusOptions = response.data;
+        });
+    this.getDicts("store_order_type").then((response) => {
+      this.orderTypeOptions = response.data;
+    });
+    this.getDicts("store_order_status").then((response) => {
+      this.statusOptions = response.data;
+    });
+    this.getDicts("store_pay_type").then((response) => {
+      this.payTypeOptions = response.data;
+    });
+    this.getDicts("store_order_create_type").then((response) => {
+      this.createTypeOptions = response.data;
+    });
+    getTcmScheduleList().then(response => {
+      this.scheduleOptions = response.data;
+    });
+  },
+  computed: {
+    company(){
+      return this.$store.state.user.user;
+    }
+  },
+  methods: {
+    closeSms(){
+      this.addSms.open=false;
+    },
+    handleSms(mobile){
+        this.addSms.open=true;
+        var that=this;
+        setTimeout(() => {
+            that.$refs.sms.getOrderId(this.orderId,mobile,2);
+        }, 500);
+
+    },
+    handlePhone(){
+      const id = this.order.id;
+        getUserPhone(id).then(response =>{
+          this.order.userPhone = response.userPhone;
+        })
+      },
+    handleAddress(){
+      const id = this.order.id;
+      getStoreOrderAddress(id).then(response =>{
+          this.order.userAddress = response.address;
+      })
+    },
+    showImageDialog() {
+      this.dialogVisible = true;
+    },
+    handleCustomer(){
+      var that=this;
+      this.customer.open = true;
+      setTimeout(() => {
+          that.$refs.customerDetails.getDetails(this.order.customerId);
+      }, 200);
+    },
+    handleSelectionChange(selection) {
+      this.bindCustomerForm.customerIds = selection.map(item => item.customerId)
+    },
+    searchCustomer(){
+      if(this.bindCustomerForm.mobile==null||this.bindCustomerForm.mobile==""){
+        this.msgError("请输入手机号");
+        return;
+      }
+      var data={mobile:this.bindCustomerForm.mobile};
+      getCustomerListBySearch(data).then(response => {
+          this.customers=response.data;
+      });
+    },
+    handleBindCustomer() {
+      this.customers=[];
+      this.bindCustomerDialog.open = true;
+      this.bindCustomerForm.mobile=null;
+      this.bindCustomerForm.orderId=this.orderId;
+      this.bindCustomerForm.customerIds=null;
+    },
+    /** 提交按钮 */
+    submitBindCustomerForm() {
+      this.$refs["bindCustomerForm"].validate(valid => {
+        if (valid) {
+          bindCustomer(this.bindCustomerForm).then(response => {
+              if (response.code === 200) {
+                this.msgSuccess("修改成功");
+                this.bindCustomerDialog.open = false;
+              }
+            });
+        }
+      });
+    },
+    handleCertificates(){
+      this.certificateDialig.open = true;
+      this.photoArr = null;
+    },
+    handleConfirm(){
+      this.certificateForm.id = this.orderId;
+      this.certificateForm.orderCode = this.order.orderCode;
+      this.certificateForm.certificates = this.photoArr;
+      uploadCredentials(this.certificateForm).then(response => {
+              if (response.code === 200) {
+                this.msgSuccess("上传成功");
+                this.certificateDialig.open = false;
+                this.getOrder(this.order.id);
+              }
+            });
+    },
+    showExpress(){
+      this.expressDialog.open=true;
+      getExpress(this.orderId).then(response => {
+          this.express = response.data;
+          if(this.express!=null&&this.express.Traces!=null){
+              this.traces=this.express.Traces
+          }
+
+      });
+
+    },
+    districtChange(val){
+      var item=this.citys.find((item)=>{
+        return item.cityId==val&&item.level==2;
+      })
+      this.editAddressForm.district=item.name;
+
+    },
+    cityChange(val){
+      this.district=this.citys.filter(item => item.parentId===val )
+      this.editAddressForm.districtId=null;
+      var item=this.citys.find((item)=>{
+        return item.cityId==val&&item.level==1;
+      })
+      this.editAddressForm.city=item.name;
+
+
+    },
+    provinceChange(val){
+      this.city=this.citys.filter(item => item.parentId===val )
+      this.district=[];
+      this.editAddressForm.cityId=null;
+      this.editAddressForm.districtId=null;
+      var item=this.citys.find((item)=>{
+        return item.cityId==val&&item.level==0;
+      })
+      this.editAddressForm.province=item.name;
+    },
+    getCityList(){
+      getCitys().then(res => {
+          this.citys=res.data;
+          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;
+        })
+
+        if(city!=null){
+          this.editAddressForm.cityId=city.cityId;
+          this.district=this.citys.filter(item => item.parentId===city.cityId&&item.level==2 )
+        }
+        var district=this.citys.find((item)=>{
+          return item.name==address[2]&&item.level==2;
+        })
+        if(district!=null){
+          this.editAddressForm.districtId=district.cityId;
+        }
+
+        this.editAddress.open = true;
+    },
+    /** 提交按钮 */
+    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 => {
+              if (response.code === 200) {
+                this.msgSuccess("修改成功");
+                this.editAddress.open = false;
+                this.getOrder(this.order.id);
+              }
+            });
+        }
+      });
+    },
+    handleEditUser() {
+      const userId = this.order.userId
+      getUser(userId).then(response => {
+        this.editUserForm.userId=response.data.userId;
+        this.editUserForm.registerDate=response.data.registerDate;
+        this.editUserForm.registerCode=response.data.registerCode;
+        this.editUserForm.source=response.data.source;
+        this.editUser.open = true;
+      });
+    },
+    /** 提交按钮 */
+    submitEditUserForm() {
+      this.$refs["editUserForm"].validate(valid => {
+        if (valid) {
+            updateUser(this.editUserForm).then(response => {
+              if (response.code === 200) {
+                this.msgSuccess("修改成功");
+                this.editUser.open = false;
+                this.getOrder(this.order.id);
+              }
+            });
+        }
+      });
+    },
+    submitEditForm(){
+        this.$refs["editForm"].validate(valid => {
+        if (valid) {
+          updateStoreOrder(this.editForm).then(response => {
+            if (response.code === 200) {
+              this.msgSuccess("操作成功");
+              this.edit.open = false;
+              this.getOrder(this.order.id);
+            }
+          });
+
+        }
+      });
+    },
+    editOrder(){
+        this.edit.open=true;
+        this.editForm.mark=this.order.mark
+        this.editForm.id=this.order.id;
+        if(this.order.orderType!=null){
+          this.editForm.orderType=this.order.orderType.toString();
+        }
+        this.editForm.scheduleId=this.order.scheduleId;
+        this.editForm.orderVisit = this.order.orderVisit;
+
+    },
+    getOrder(orderId){
+        this.orderId=orderId;
+        this.certificates = null;
+        getStoreOrder(orderId).then(response => {
+            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;
+            this.payments=response.payments;
+            this.customerInfo=response.customer;
+        });
+     }
+  }
+};
+</script>
+<style scoped>
+.order-content{
+  margin: 10px;
+}
+.detail-container {
+  width: 80%;
+  padding: 20px 20px 20px 20px;
+  margin: 20px auto;
+}
+
+.operate-container {
+  background: #F2F6FC;
+  height: 60px;
+  margin: -20px -20px 0;
+  line-height: 60px;
+}
+
+.operate-button-container {
+  float: right;
+  margin-right: 20px
+}
+
+.table-layout {
+  margin-top: 20px;
+  border-left: 1px solid #DCDFE6;
+  border-top: 1px solid #DCDFE6;
+}
+
+.table-cell {
+  height: 60px;
+  line-height: 40px;
+  border-right: 1px solid #DCDFE6;
+  border-bottom: 1px solid #DCDFE6;
+  padding: 10px;
+  font-size: 14px;
+  color: #606266;
+  text-align: center;
+  overflow: hidden;
+}
+
+.table-cell-title {
+  border-right: 1px solid #DCDFE6;
+  border-bottom: 1px solid #DCDFE6;
+  padding: 10px;
+  background: #F2F6FC;
+  text-align: center;
+  font-size: 14px;
+  color: #303133;
+}
+</style>

+ 135 - 0
src/views/hisStore/components/productPackageDetails.vue

@@ -0,0 +1,135 @@
+<template>
+  <div class="content">
+    <el-descriptions :column="4" border  >
+      <el-descriptions-item label="封面"  >
+          <span v-if="package!=null">
+            <el-popover
+            placement="right"
+            title=""
+            trigger="hover"
+          >
+            <img slot="reference" :src="package.imgUrl" width="100">
+            <img :src="package.imgUrl" style="max-width: 150px;">
+          </el-popover>
+          </span>
+      </el-descriptions-item>
+      <el-descriptions-item label="标题"  >
+          <span v-if="package!=null">
+            {{package.title}}
+          </span>
+      </el-descriptions-item>
+      <el-descriptions-item label="描述"  >
+          <span v-if="package!=null" >
+            {{package.descs}}
+          </span>
+      </el-descriptions-item>
+      <el-descriptions-item label="原价"  >
+          <span v-if="package!=null">
+            {{package.money.toFixed(2)}}
+          </span>
+      </el-descriptions-item>
+      <el-descriptions-item label="套餐价格"  >
+          <span v-if="package!=null">
+            {{package.payMoney.toFixed(2)}}
+          </span>
+      </el-descriptions-item>
+      <el-descriptions-item label="支付类型"  >
+          <span v-if="package!=null">
+            <el-tag prop="payType" v-for="(item, index) in storePayTypeOptions"    v-if="package.payType==item.dictValue">{{item.dictLabel}}</el-tag>
+          </span>
+      </el-descriptions-item>
+      <el-descriptions-item label="限购次数"  >
+          <span v-if="package!=null">
+            {{package.limitCount}}
+          </span>
+      </el-descriptions-item>
+
+    </el-descriptions>
+    <div style="margin: 20px 0px"  v-if="items!=null">
+        <span class="font-small">
+          商品列表
+        </span>
+    </div>
+    <el-table
+      border
+      v-if="items!=null"
+      :data="items"
+      size="small"
+      style="width: 100%;margin-top: 20px" >
+      <el-table-column label="ID"  align="center">
+        <template slot-scope="scope">
+          <p>{{scope.row.id}}</p>
+        </template>
+      </el-table-column>
+      <el-table-column label="商品图片"   align="center">
+          <template slot-scope="scope">
+            <img :src="scope.row.image" style="height: 80px">
+          </template>
+      </el-table-column>
+      <el-table-column label="商品名称"   align="center">
+        <template slot-scope="scope">
+          <p>{{scope.row.productName}}</p>
+        </template>
+      </el-table-column>
+      <el-table-column label="规格"   align="center">
+        <template slot-scope="scope">
+          <p>{{scope.row.sku}}</p>
+        </template>
+      </el-table-column>
+      <el-table-column label="售价"   align="center">
+        <template slot-scope="scope">
+          <p>¥{{scope.row.price.toFixed(2)}}</p>
+        </template>
+      </el-table-column>
+      <el-table-column label="商品编码"   align="center">
+        <template slot-scope="scope">
+          {{scope.row.barCode}}
+        </template>
+      </el-table-column>
+      <el-table-column label="数量" width="180" align="center">
+        <template slot-scope="scope">
+          {{scope.row.count}}
+        </template>
+      </el-table-column>
+    </el-table>
+    <div v-html="package.content"></div>
+  </div>
+</template>
+
+<script>
+import {  getStoreProductPackage  } from "@/api/hisStore/storeProductPackage";
+
+export default {
+  name: "product",
+  data() {
+    return {
+      cateOptions:[],
+      storePayTypeOptions:[],
+      package:null,
+      items:[],
+    };
+  },
+  created() {
+    this.getDicts("store_product_package_cate").then((response) => {
+      this.cateOptions = response.data;
+    });
+    this.getDicts("store_pay_type").then((response) => {
+      this.storePayTypeOptions = response.data;
+    });
+  },
+  methods: {
+    getStoreProductPackage(id) {
+      getStoreProductPackage(id).then(response => {
+        this.package = response.productPckage;
+        this.items = response.productList;
+      });
+    },
+  }
+};
+</script>
+<style scoped>
+.content{
+  margin: 10px;
+}
+
+</style>

+ 100 - 0
src/views/hisStore/components/productSelect.vue

@@ -0,0 +1,100 @@
+<template>
+  <div >
+    <el-form :model="queryParams" ref="queryForm" :inline="true" label-width="68px">
+      <el-form-item label="商品名称" prop="productName">
+        <el-input
+          style="width:200px"
+          v-model="queryParams.productName"
+          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-form-item>
+    </el-form>
+    <el-table border v-loading="loading" :data="list">
+      <el-table-column label="商品编号" align="center" prop="barCode" />
+      <el-table-column label="商品图片" align="center" width="100">
+        <template slot-scope="scope">
+          <el-popover
+            placement="right"
+            title=""
+            trigger="hover"
+          >
+            <img slot="reference" :src="scope.row.image" width="80">
+            <img :src="scope.row.image" style="max-width: 80px;">
+          </el-popover>
+        </template>
+      </el-table-column>
+      <el-table-column label="商品名称" show-overflow-tooltip align="center" prop="productName" />
+      <el-table-column label="商品规格" align="center" prop="sku" />
+      <el-table-column label="库存" align="center" prop="stock" />
+      <el-table-column label="售价" align="center" prop="price" />
+      <el-table-column label="代理价" align="center" prop="agentPrice" />
+      <el-table-column label="操作" align="center" width="100px" >
+        <template slot-scope="scope">
+          <el-button
+            size="mini"
+            type="text"
+            @click="handleSelect(scope.row)"
+          >选择</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+    <pagination
+      style="padding-bottom:10px;"
+      v-show="total>0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    />
+  </div>
+</template>
+
+<script>
+import { getStoreProductAttrValueList } from "@/api/hisStore/storeProduct";
+export default {
+  name: "selectProduct",
+  data() {
+    return {
+      loading: true,
+      list:[],
+      total: 0,
+      queryParams: {
+        productName:"",
+        pageNum: 1,
+        pageSize: 10
+      }
+    };
+  },
+  created() {
+     this.getList();
+  },
+
+  methods: {
+    handleSelect(row){
+      this.$emit('selectProduct',row);
+    },
+    /** 搜索按钮操作 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    getList(){
+      this.loading = true;
+      getStoreProductAttrValueList(this.queryParams).then(response => {
+        this.list = response.rows;
+        this.total = response.total;
+        this.loading = false;
+      });
+    }
+  }
+};
+</script>
+<style scoped>
+
+</style>

+ 344 - 0
src/views/hisStore/statistics/storeOrder.vue

@@ -0,0 +1,344 @@
+<template>
+  <div class="app-container">
+      <div class="app-content">
+           <div class="title">
+             商城订单统计
+          </div>
+         <el-form class="search-form" :inline="true" >
+          <el-form-item >
+            <el-select v-model="value" placeholder="请选择日期">
+              <el-option
+                v-for="item in options"
+                :key="item.value"
+                :label="item.label"
+                :value="item.value">
+              </el-option>
+            </el-select>
+          </el-form-item>
+          <el-form-item >
+            <treeselect :clearable="false"  v-model="deptId"  :options="deptOptions" :show-count="true" placeholder="请选择归属部门" />
+          </el-form-item>
+          <el-form-item>
+            <el-select filterable v-model="userIds" placeholder="请选择员工" clearable size="small">
+                <el-option
+                  v-for="item in users"
+                  :key="item.userId"
+                  :label="item.nickName"
+                  :value="item.userId">
+                </el-option>
+              </el-select>
+          </el-form-item>
+          <el-form-item label="筛选日期" prop="createTime">
+                  <el-date-picker clearable size="small" style="width: 205.4px"
+                    v-model="dateRange"
+                    type="daterange"
+                    value-format="yyyy-MM-dd"
+                    start-placeholder="开始日期" end-placeholder="结束日期"
+                    >
+                  </el-date-picker>
+                </el-form-item>
+          <el-form-item>
+              <el-button type="cyan" icon="el-icon-search"   @click="storeOrder">搜索</el-button>
+          </el-form-item>
+        </el-form>
+         <div class="data-box">
+            <div class="echart-box">
+              <div id="echart-customer"></div>
+            </div>
+            <div class="table-box">
+                  <el-button class="export" size="small"  @click="handleExport"   v-hasPermi="['statistics:customer:index']">导出</el-button>
+                  <el-table
+                  :data="list"
+                  border
+                  :summary-method="getSummaries"
+                  show-summary
+                  max-height="500"
+                  style="width: 100%;">
+                  <el-table-column
+                    prop="nickName"
+                    label="员工姓名">
+                  </el-table-column>
+                  <el-table-column
+                    prop="orderCount"
+                    label="订单数">
+                  </el-table-column>
+                  <el-table-column
+                    prop="payPrice"
+                    label="订单金额">
+                  </el-table-column>
+
+                </el-table>
+            </div>
+        </div>
+      </div>
+
+    </div>
+</template>
+
+<script>
+import { storeOrder,exportStoreOrder } from "@/api/hisStore/statistics";
+import { getUserListByDeptId} from "@/api/company/companyUser";
+import echarts from 'echarts'
+import resize from '../../dashboard/mixins/resize'
+import { treeselect } from "@/api/company/companyDept";
+import Treeselect from "@riophae/vue-treeselect";
+import "@riophae/vue-treeselect/dist/vue-treeselect.css";
+
+export default {
+name: 'Index',
+mixins: [resize],
+components: { Treeselect },
+watch: {
+// 监听deptId
+'deptId': 'currDeptChange'
+},
+data() {
+return {
+ deptOptions:[],
+ deptId:undefined,
+ userIds:undefined,
+ users:[],
+ dateRange:[],
+ chart: null,
+ options: [{
+    value: '1',
+    label: '今天'
+  }, {
+    value: '2',
+    label: '昨天'
+  }, {
+    value: '3',
+    label: '本周'
+  }, {
+    value: '4',
+    label: '上周'
+  }, {
+    value: '5',
+    label: '本月'
+  }
+  , {
+    value: '6',
+    label: '上月'
+  }
+  , {
+    value: '7',
+    label: '本季度'
+  }
+  , {
+    value: '8',
+    label: '上季度'
+  }
+  , {
+    value: '9',
+    label: '本年'
+  }
+  , {
+    value: '10',
+    label: '上年'
+  }],
+  value: '5',
+  list:[],
+  dates:[],
+  orderCount:[],
+  payPrice:[],
+
+}
+},
+created() {
+this.getTreeselect();
+},
+methods: {
+  currDeptChange(val){
+  this.deptId=val;
+  this.getUserListByDeptId();
+},
+/** 查询部门下拉树结构 */
+getTreeselect() {
+var that=this;
+treeselect().then((response) => {
+  this.deptOptions = response.data;
+  if(response.data!=null&&response.data.length>0){
+    this.deptId=response.data[0].id;
+    that.storeOrder()
+  }
+});
+},
+handleExport(){
+  var data;
+  if(this.userIds!=undefined){
+      data={type:this.value,userIds:this.userIds+"",deptId:this.deptId}
+  }
+  else{
+      data={type:this.value,deptId:this.deptId}
+  }
+  exportStoreOrder(data).then((response) => {
+     this.download(response.msg);
+  });
+
+},
+getUserListByDeptId() {
+  this.userIds=undefined;
+  var data={deptId:this.deptId};
+  getUserListByDeptId(data).then(response => {
+    this.users = response.data;
+
+  });
+},
+storeOrder(){
+    var data;
+    if(this.userIds!=undefined){
+        data={type:this.value,userIds:this.userIds+"",deptId:this.deptId}
+    }
+    else{
+        data={type:this.value,deptId:this.deptId}
+    }
+    storeOrder(data).then((response) => {
+     this.list=response.list;
+     this.dates=response.dates;
+     this.orderCount=response.orderCount;
+     this.payPrice=response.payPrice;
+      setTimeout(() => {
+        this.initEchart();
+      }, 500);
+  });
+},
+initEchart(){
+  var option = {
+    tooltip: {
+        trigger: 'axis',
+        axisPointer: {            // 坐标轴指示器,坐标轴触发有效
+            type: 'shadow'        // 默认为直线,可选为:'line' | 'shadow'
+        }
+    },
+    legend: {
+        data: ['订单数', '订单金额' ]
+    },
+    grid: {
+        left: '3%',
+        right: '4%',
+        bottom: '3%',
+        containLabel: true
+    },
+    xAxis: [
+        {
+            type: 'category',
+            data: this.dates
+        }
+    ],
+    yAxis: [
+        {
+            type: 'value',
+            axisLabel:{
+              formatter:'{value}'
+            }
+        }
+    ],
+    series: [
+        {
+
+            name: '订单数',
+            type: 'bar',
+            emphasis: {
+                focus: 'series'
+            },
+            data: this.orderCount
+        },
+        {
+
+            name: '订单金额',
+            type: 'bar',
+            emphasis: {
+                focus: 'series'
+            },
+            data: this.payPrice
+        }
+
+    ]
+  };
+  this.chart=echarts.init(document.getElementById("echart-customer"));
+  this.chart.setOption(option,true);
+},
+ getSummaries(param) {
+  const { columns, data } = param;
+  const sums = [];
+  columns.forEach((column, index) => {
+    if (index === 0) {
+      sums[index] = '总计';
+      return;
+    }
+    const values = data.map(item => Number(item[column.property]));
+    if (!values.every(value => isNaN(value))) {
+      sums[index] = values.reduce((prev, curr) => {
+        const value = Number(curr);
+        if (!isNaN(value)) {
+          return prev + curr;
+        } else {
+          return prev;
+        }
+      }, 0);
+      sums[index] += ' ';
+    } else {
+      sums[index] = '';
+    }
+  });
+
+  return sums;
+}
+}
+}
+</script>
+
+<style lang="scss" scoped>
+.app-container{
+border: 1px solid #e6e6e6;
+padding: 12px;
+
+.app-content{
+background-color: white;
+.title{
+  padding: 20px 30px 0px 30px;
+  font-size: 18px;
+  font-weight: bold;
+  color: black;
+
+}
+.search-form{
+  margin: 20px 30px 0px 30px;
+}
+.data-box{
+  padding: 30px;
+  background-color:  rgb(255, 255, 255);
+  height: 100%;
+
+  .echart-box{
+    margin: 0 auto;
+    text-align: center;
+  }
+  .el-select{
+    margin: 5px 10px;
+  }
+  .table-box{
+    margin-top: 15px;
+    .export{
+      float: right;
+      margin: 10px 0px;
+    }
+  }
+}
+}
+}
+#echart-customer{
+width:100%;
+height:320px
+}
+.vue-treeselect{
+width: 217px;
+height: 36px;
+}
+
+</style>
+<style>
+.vue-treeselect__control{
+display: block;
+}
+</style>

+ 344 - 0
src/views/hisStore/statistics/storePayment.vue

@@ -0,0 +1,344 @@
+<template>
+  <div class="app-container">
+      <div class="app-content">
+           <div class="title">
+             商城订单统计
+          </div>
+         <el-form class="search-form" :inline="true" >
+          <el-form-item >
+            <el-select v-model="value" placeholder="请选择日期">
+              <el-option
+                v-for="item in options"
+                :key="item.value"
+                :label="item.label"
+                :value="item.value">
+              </el-option>
+            </el-select>
+          </el-form-item>
+          <el-form-item >
+            <treeselect :clearable="false"  v-model="deptId"  :options="deptOptions" :show-count="true" placeholder="请选择归属部门" />
+          </el-form-item>
+          <el-form-item>
+            <el-select filterable v-model="userIds" placeholder="请选择员工" clearable size="small">
+                <el-option
+                  v-for="item in users"
+                  :key="item.userId"
+                  :label="item.nickName"
+                  :value="item.userId">
+                </el-option>
+              </el-select>
+          </el-form-item>
+          <el-form-item label="筛选日期" prop="createTime">
+                  <el-date-picker clearable size="small" style="width: 205.4px"
+                    v-model="dateRange"
+                    type="daterange"
+                    value-format="yyyy-MM-dd"
+                    start-placeholder="开始日期" end-placeholder="结束日期"
+                    >
+                  </el-date-picker>
+                </el-form-item>
+          <el-form-item>
+              <el-button type="cyan" icon="el-icon-search"   @click="storePayment">搜索</el-button>
+          </el-form-item>
+        </el-form>
+         <div class="data-box">
+            <div class="echart-box">
+              <div id="echart-customer"></div>
+            </div>
+            <div class="table-box">
+                  <el-button class="export" size="small"  @click="handleExport"   v-hasPermi="['statistics:customer:index']">导出</el-button>
+                  <el-table
+                  :data="list"
+                  border
+                  :summary-method="getSummaries"
+                  show-summary
+                  max-height="500"
+                  style="width: 100%;">
+                  <el-table-column
+                    prop="nickName"
+                    label="员工姓名">
+                  </el-table-column>
+                  <el-table-column
+                    prop="orderCount"
+                    label="订单数">
+                  </el-table-column>
+                  <el-table-column
+                    prop="payMoney"
+                    label="订单金额">
+                  </el-table-column>
+
+                </el-table>
+            </div>
+        </div>
+      </div>
+
+    </div>
+</template>
+
+<script>
+import { storePayment,exportStorePayment } from "@/api/hisStore/statistics";
+import { getUserListByDeptId} from "@/api/company/companyUser";
+import echarts from 'echarts'
+import resize from '../../dashboard/mixins/resize'
+import { treeselect } from "@/api/company/companyDept";
+import Treeselect from "@riophae/vue-treeselect";
+import "@riophae/vue-treeselect/dist/vue-treeselect.css";
+
+export default {
+name: 'Index',
+mixins: [resize],
+components: { Treeselect },
+watch: {
+// 监听deptId
+'deptId': 'currDeptChange'
+},
+data() {
+return {
+ deptOptions:[],
+ deptId:undefined,
+ userIds:undefined,
+ users:[],
+ dateRange:[],
+ chart: null,
+ options: [{
+    value: '1',
+    label: '今天'
+  }, {
+    value: '2',
+    label: '昨天'
+  }, {
+    value: '3',
+    label: '本周'
+  }, {
+    value: '4',
+    label: '上周'
+  }, {
+    value: '5',
+    label: '本月'
+  }
+  , {
+    value: '6',
+    label: '上月'
+  }
+  , {
+    value: '7',
+    label: '本季度'
+  }
+  , {
+    value: '8',
+    label: '上季度'
+  }
+  , {
+    value: '9',
+    label: '本年'
+  }
+  , {
+    value: '10',
+    label: '上年'
+  }],
+  value: '5',
+  list:[],
+  dates:[],
+  orderCount:[],
+  payMoney:[],
+
+}
+},
+created() {
+this.getTreeselect();
+},
+methods: {
+  currDeptChange(val){
+  this.deptId=val;
+  this.getUserListByDeptId();
+},
+/** 查询部门下拉树结构 */
+getTreeselect() {
+  var that=this;
+  treeselect().then((response) => {
+    this.deptOptions = response.data;
+    if(response.data!=null&&response.data.length>0){
+      this.deptId=response.data[0].id;
+      that.storePayment()
+    }
+  });
+},
+handleExport(){
+  var data;
+  if(this.userIds!=undefined){
+      data={type:this.value,userIds:this.userIds+"",deptId:this.deptId}
+  }
+  else{
+      data={type:this.value,deptId:this.deptId}
+  }
+  exportStorePayment(data).then((response) => {
+     this.download(response.msg);
+  });
+
+},
+getUserListByDeptId() {
+  this.userIds=undefined;
+  var data={deptId:this.deptId};
+  getUserListByDeptId(data).then(response => {
+    this.users = response.data;
+
+  });
+},
+storePayment(){
+    var data;
+    if(this.userIds!=undefined){
+        data={type:this.value,userIds:this.userIds+"",deptId:this.deptId}
+    }
+    else{
+        data={type:this.value,deptId:this.deptId}
+    }
+    storePayment(data).then((response) => {
+     this.list=response.list;
+     this.dates=response.dates;
+     this.orderCount=response.orderCount;
+     this.payMoney=response.payMoney;
+      setTimeout(() => {
+        this.initEchart();
+      }, 500);
+  });
+},
+initEchart(){
+  var option = {
+    tooltip: {
+        trigger: 'axis',
+        axisPointer: {            // 坐标轴指示器,坐标轴触发有效
+            type: 'shadow'        // 默认为直线,可选为:'line' | 'shadow'
+        }
+    },
+    legend: {
+        data: ['订单数', '订单金额' ]
+    },
+    grid: {
+        left: '3%',
+        right: '4%',
+        bottom: '3%',
+        containLabel: true
+    },
+    xAxis: [
+        {
+            type: 'category',
+            data: this.dates
+        }
+    ],
+    yAxis: [
+        {
+            type: 'value',
+            axisLabel:{
+              formatter:'{value}'
+            }
+        }
+    ],
+    series: [
+        {
+
+            name: '订单数',
+            type: 'bar',
+            emphasis: {
+                focus: 'series'
+            },
+            data: this.orderCount
+        },
+        {
+
+            name: '订单金额',
+            type: 'bar',
+            emphasis: {
+                focus: 'series'
+            },
+            data: this.payMoney
+        }
+
+    ]
+  };
+  this.chart=echarts.init(document.getElementById("echart-customer"));
+  this.chart.setOption(option,true);
+},
+ getSummaries(param) {
+  const { columns, data } = param;
+  const sums = [];
+  columns.forEach((column, index) => {
+    if (index === 0) {
+      sums[index] = '总计';
+      return;
+    }
+    const values = data.map(item => Number(item[column.property]));
+    if (!values.every(value => isNaN(value))) {
+      sums[index] = values.reduce((prev, curr) => {
+        const value = Number(curr);
+        if (!isNaN(value)) {
+          return prev + curr;
+        } else {
+          return prev;
+        }
+      }, 0);
+      sums[index] += ' ';
+    } else {
+      sums[index] = '';
+    }
+  });
+
+  return sums;
+}
+}
+}
+</script>
+
+<style lang="scss" scoped>
+.app-container{
+border: 1px solid #e6e6e6;
+padding: 12px;
+
+.app-content{
+background-color: white;
+.title{
+  padding: 20px 30px 0px 30px;
+  font-size: 18px;
+  font-weight: bold;
+  color: black;
+
+}
+.search-form{
+  margin: 20px 30px 0px 30px;
+}
+.data-box{
+  padding: 30px;
+  background-color:  rgb(255, 255, 255);
+  height: 100%;
+
+  .echart-box{
+    margin: 0 auto;
+    text-align: center;
+  }
+  .el-select{
+    margin: 5px 10px;
+  }
+  .table-box{
+    margin-top: 15px;
+    .export{
+      float: right;
+      margin: 10px 0px;
+    }
+  }
+}
+}
+}
+#echart-customer{
+width:100%;
+height:320px
+}
+.vue-treeselect{
+width: 217px;
+height: 36px;
+}
+
+</style>
+<style>
+.vue-treeselect__control{
+display: block;
+}
+</style>

+ 403 - 0
src/views/hisStore/storeAfterSales/list.vue

@@ -0,0 +1,403 @@
+<template>
+  <div class="app-container">
+    <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
+
+     <el-form-item label="所属部门" prop="deptId">
+        <treeselect style="width:220px" v-model="queryParams.deptId" :options="deptOptions" :show-count="true" placeholder="请选择所属部门" />
+     </el-form-item>
+
+      <el-form-item label="订单单号" prop="orderCode">
+        <el-input
+          v-model="queryParams.orderCode"
+          placeholder="请输入订单单号"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+
+      <el-form-item label="运单号" prop="deliverySn">
+            <el-input
+                style="width:220px"
+                v-model="queryParams.deliverySn"
+                placeholder="请输入运单号"
+                clearable
+                size="small"
+                @keyup.enter.native="handleQuery" />
+      </el-form-item>
+
+       <el-form-item label="员工姓名" prop="companyUserNickName">
+        <el-input
+
+          v-model="queryParams.companyUserNickName"
+          placeholder="请输入员工姓名"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="手机号" prop="consigneePhone">
+        <el-input
+          v-model="queryParams.consigneePhone"
+          placeholder="请输入手机号"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+
+       <el-form-item label="退款时间" prop="createTimeRange">
+            <el-date-picker
+            style="width:220px"
+              clearable size="small"
+              v-model="dateRange"
+              type="daterange"
+              value-format="yyyy-MM-dd"
+              start-placeholder="开始日期"
+              end-placeholder="结束日期">
+            </el-date-picker>
+          </el-form-item>
+
+
+      <el-form-item label="状态" prop="status">
+        <el-select  v-model="queryParams.status" placeholder="请选择状态" clearable size="small" >
+         <el-option
+                v-for="item in statusOptions"
+                :key="item.dictValue"
+                :label="item.dictLabel"
+                :value="item.dictValue"
+              />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="售后状态" prop="salesStatus">
+        <el-select   v-model="queryParams.salesStatus" placeholder="请选择状态" clearable size="small" >
+         <el-option
+                v-for="item in salesStatusOptions"
+                :key="item.dictValue"
+                :label="item.dictLabel"
+                :value="item.dictValue"
+              />
+        </el-select>
+      </el-form-item>
+
+      <el-form-item label="退款类型" prop="serviceType">
+        <el-select   v-model="queryParams.serviceType" placeholder="请选择类型" clearable size="small" >
+         <el-option
+                v-for="item in serviceTypeOptions"
+                :key="item.dictValue"
+                :label="item.dictLabel"
+                :value="item.dictValue"
+              />
+        </el-select>
+      </el-form-item>
+      <el-form-item>
+        <el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
+      </el-form-item>
+    </el-form>
+        <el-row :gutter="10" class="mb8">
+          <el-col :span="1.5">
+            <el-button
+                type="warning"
+              icon="el-icon-download"
+              size="mini"
+                @click="handleExport"
+
+            >导出</el-button>
+          </el-col>
+
+          <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+    <el-table  height="500" border v-loading="loading" :data="storeAfterSalesList" @selection-change="handleSelectionChange">
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="ID" align="center" prop="id" />
+      <el-table-column label="订单单号" align="center" prop="orderCode" />
+      <el-table-column label="所属公司" align="center" prop="companyName" />
+      <el-table-column label="所属员工" align="center" prop="companyUserNickName" />
+      <el-table-column label="会员手机号" align="center" prop="userPhone" />
+      <el-table-column label="退款金额" align="center" prop="refundAmount" />
+       <el-table-column label="退款类型" align="center" prop="serviceType" >
+          <template slot-scope="scope">
+              <div prop="serviceType" v-for="(item, index) in serviceTypeOptions"    v-if="scope.row.serviceType==item.dictValue">{{item.dictLabel}}</div>
+          </template>
+      </el-table-column>
+      <el-table-column label="申请原因" align="center" prop="reasons" />
+      <el-table-column label="说明" align="center" prop="explains" />
+      <el-table-column label="状态" align="center" prop="status" >
+          <template slot-scope="scope">
+              <div prop="status" v-for="(item, index) in statusOptions"    v-if="scope.row.status==item.dictValue">{{item.dictLabel}}</div>
+          </template>
+      </el-table-column>
+      <el-table-column label="售后状态" align="center" prop="salesStatus" >
+          <template slot-scope="scope">
+              <div prop="status" v-for="(item, index) in salesStatusOptions"    v-if="scope.row.salesStatus==item.dictValue">{{item.dictLabel}}</div>
+          </template>
+      </el-table-column>
+      <el-table-column label="提交时间" align="center" prop="createTime" />
+
+      <el-table-column label="操作" align="center"  fixed="right" width="120px" class-name="small-padding fixed-width">
+        <template slot-scope="scope">
+          <el-button
+            size="mini"
+            type="text"
+            @click="handleShow(scope.row)"
+            v-hasPermi="['store:storeAfterSales:query']"
+          >查看</el-button>
+
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <pagination
+      v-show="total>0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    />
+
+    <!-- 添加或修改售后记录对话框 -->
+    <el-drawer
+     size="75%"
+      :title="title" :visible.sync="open"
+      >
+      <product-after-sales-order  ref="afterSalesOrder" />
+    </el-drawer>
+  </div>
+</template>
+
+<script>
+import { listStoreAfterSales, getStoreAfterSales, delStoreAfterSales, addStoreAfterSales, updateStoreAfterSales, exportStoreAfterSales } from "@/api/hisStore/storeAfterSales";
+import productAfterSalesOrder from "../components/productAfterSalesOrder";
+import { treeselect } from "@/api/company/companyDept";
+import Treeselect from "@riophae/vue-treeselect";
+import "@riophae/vue-treeselect/dist/vue-treeselect.css";
+
+export default {
+  components: { productAfterSalesOrder,Treeselect },
+  name: "StoreAfterSales",
+  data() {
+    return {
+      // 部门树选项
+      deptOptions: undefined,
+      deptName: undefined,
+      serviceTypeOptions:[],
+      salesStatusOptions:[],
+      statusOptions:[],
+      // 遮罩层
+      loading: true,
+      // 选中数组
+      ids: [],
+      // 非单个禁用
+      single: true,
+      // 非多个禁用
+      multiple: true,
+      // 显示搜索条件
+      showSearch: true,
+      // 总条数
+      total: 0,
+      // 售后记录表格数据
+      storeAfterSalesList: [],
+      dateRange:[],
+      // 弹出层标题
+      title: "",
+      // 是否显示弹出层
+      open: false,
+      // 查询参数
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        orderCode: null,
+        refundAmount: null,
+        serviceType: null,
+        reasons: null,
+        explains: null,
+        explainImg: null,
+        shipperCode: null,
+        deliverySn: null,
+        deliveryName: null,
+        status: null,
+        salesStatus: null,
+        isDel: null,
+        userId: null,
+        consignee: null,
+        phoneNumber: null,
+        address: null,
+      },
+      // 表单参数
+      form: {},
+      // 表单校验
+      rules: {
+      }
+    };
+  },
+   watch: {
+    // 根据名称筛选部门树
+    deptName(val) {
+        this.$refs.tree.filter(val);
+      },
+  },
+  created() {
+    this.getTreeselect();
+    this.getDicts("store_after_sales_sales_status").then((response) => {
+        this.salesStatusOptions = response.data;
+    });
+    this.getDicts("store_after_sales_status").then((response) => {
+        this.statusOptions = response.data;
+    });
+     this.getDicts("store_after_sales_service_type").then((response) => {
+        this.serviceTypeOptions = response.data;
+    });
+
+    this.getList();
+  },
+  methods: {
+    /** 查询部门下拉树结构 */
+     getTreeselect() {
+      treeselect().then((response) => {
+        this.deptOptions = response.data;
+      });
+    },
+    // 筛选节点
+    filterNode(value, data) {
+      if (!value) return true;
+      return data.label.indexOf(value) !== -1;
+    },
+    // 节点单击事件
+    handleNodeClick(data) {
+      this.queryParams.deptId = data.id;
+      this.getList();
+    },
+    handleShow(row){
+      this.title="售后订单"
+      this.open=true;
+      setTimeout(() => {
+        this.$refs.afterSalesOrder.getStoreAfterSales(row.id);
+      }, 200);
+
+    },
+
+    /** 查询售后记录列表 */
+    getList() {
+      this.loading = true;
+      listStoreAfterSales(this.addDateRange(this.queryParams, this.dateRange)).then(response => {
+        this.storeAfterSalesList = response.rows;
+        this.total = response.total;
+        this.loading = false;
+      });
+    },
+    // 取消按钮
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 表单重置
+    reset() {
+      this.form = {
+        id: null,
+        orderCode: null,
+        refundAmount: null,
+        serviceType: null,
+        reasons: null,
+        explains: null,
+        explainImg: null,
+        shipperCode: null,
+        deliverySn: null,
+        deliveryName: null,
+        status: 0,
+        salesStatus: 0,
+        createTime: null,
+        isDel: null,
+        userId: null,
+        consignee: null,
+        phoneNumber: null,
+        address: null
+      };
+      this.resetForm("form");
+    },
+    /** 搜索按钮操作 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 重置按钮操作 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    // 多选框选中数据
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.id)
+      this.single = selection.length!==1
+      this.multiple = !selection.length
+    },
+    /** 新增按钮操作 */
+    handleAdd() {
+      this.reset();
+      this.open = true;
+      this.title = "添加售后记录";
+    },
+    /** 修改按钮操作 */
+    handleUpdate(row) {
+      this.reset();
+      const id = row.id || this.ids
+      getStoreAfterSales(id).then(response => {
+        this.form = response.data;
+        this.open = true;
+        this.title = "修改售后记录";
+      });
+    },
+    /** 提交按钮 */
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          if (this.form.id != null) {
+            updateStoreAfterSales(this.form).then(response => {
+              if (response.code === 200) {
+                this.msgSuccess("修改成功");
+                this.open = false;
+                this.getList();
+              }
+            });
+          } else {
+            addStoreAfterSales(this.form).then(response => {
+              if (response.code === 200) {
+                this.msgSuccess("新增成功");
+                this.open = false;
+                this.getList();
+              }
+            });
+          }
+        }
+      });
+    },
+    /** 删除按钮操作 */
+    handleDelete(row) {
+      const ids = row.id || this.ids;
+      this.$confirm('是否确认删除售后记录编号为"' + ids + '"的数据项?', "警告", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        }).then(function() {
+          return delStoreAfterSales(ids);
+        }).then(() => {
+          this.getList();
+          this.msgSuccess("删除成功");
+        }).catch(function() {});
+    },
+    /** 导出按钮操作 */
+    handleExport() {
+      const queryParams = this.queryParams;
+      this.$confirm('是否确认导出所有售后记录数据项?', "警告", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        }).then(function() {
+          return exportStoreAfterSales(queryParams);
+        }).then(response => {
+          this.download(response.msg);
+        }).catch(function() {});
+    }
+  }
+};
+</script>

+ 310 - 0
src/views/hisStore/storeAfterSales/myList.vue

@@ -0,0 +1,310 @@
+<template>
+  <div class="app-container">
+    <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
+      <el-form-item label="订单单号" prop="orderCode">
+        <el-input
+
+          v-model="queryParams.orderCode"
+          placeholder="请输入订单单号"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="员工姓名" prop="companyUserNickName">
+        <el-input
+
+          v-model="queryParams.companyUserNickName"
+          placeholder="请输入员工姓名"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="状态" prop="status">
+        <el-select  v-model="queryParams.status" placeholder="请选择状态" clearable size="small" >
+         <el-option
+                v-for="item in statusOptions"
+                :key="item.dictValue"
+                :label="item.dictLabel"
+                :value="item.dictValue"
+              />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="售后状态" prop="salesStatus">
+        <el-select   v-model="queryParams.salesStatus" placeholder="请选择状态" clearable size="small" >
+         <el-option
+                v-for="item in salesStatusOptions"
+                :key="item.dictValue"
+                :label="item.dictLabel"
+                :value="item.dictValue"
+              />
+        </el-select>
+      </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="storeAfterSalesList" @selection-change="handleSelectionChange">
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="ID" align="center" prop="id" />
+      <el-table-column label="订单单号" align="center" prop="orderCode" />
+      <el-table-column label="所属公司" align="center" prop="companyName" />
+      <el-table-column label="所属员工" align="center" prop="companyUserNickName" />
+      <el-table-column label="会员手机号" align="center" prop="userPhone" />
+      <el-table-column label="退款金额" align="center" prop="refundAmount" />
+       <el-table-column label="退款类型" align="center" prop="serviceType" >
+          <template slot-scope="scope">
+              <div prop="serviceType" v-for="(item, index) in serviceTypeOptions"    v-if="scope.row.serviceType==item.dictValue">{{item.dictLabel}}</div>
+          </template>
+      </el-table-column>
+      <el-table-column label="申请原因" align="center" prop="reasons" />
+      <el-table-column label="说明" align="center" prop="explains" />
+      <el-table-column label="状态" align="center" prop="status" >
+          <template slot-scope="scope">
+              <div prop="status" v-for="(item, index) in statusOptions"    v-if="scope.row.status==item.dictValue">{{item.dictLabel}}</div>
+          </template>
+      </el-table-column>
+      <el-table-column label="售后状态" align="center" prop="salesStatus" >
+          <template slot-scope="scope">
+              <div prop="status" v-for="(item, index) in salesStatusOptions"    v-if="scope.row.salesStatus==item.dictValue">{{item.dictLabel}}</div>
+          </template>
+      </el-table-column>
+      <el-table-column label="提交时间" align="center" prop="createTime" />
+      <el-table-column label="操作" align="center" fixed="right" width="120px" class-name="small-padding fixed-width">
+        <template slot-scope="scope">
+          <el-button
+            size="mini"
+            type="text"
+            @click="handleShow(scope.row)"
+            v-hasPermi="['store:storeAfterSales:query']"
+          >查看</el-button>
+
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <pagination
+      v-show="total>0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    />
+
+    <!-- 添加或修改售后记录对话框 -->
+    <el-drawer
+     size="75%"
+      :title="title" :visible.sync="open"
+      >
+      <product-after-sales-order  ref="afterSalesOrder" />
+    </el-drawer>
+  </div>
+</template>
+
+<script>
+import { myListStoreAfterSales, getStoreAfterSales, delStoreAfterSales, addStoreAfterSales, updateStoreAfterSales, exportStoreAfterSales } from "@/api/hisStore/storeAfterSales";
+import productAfterSalesOrder from "../components/productAfterSalesOrder";
+export default {
+  components: { productAfterSalesOrder },
+  name: "StoreAfterSales",
+  data() {
+    return {
+      serviceTypeOptions:[],
+      salesStatusOptions:[],
+      statusOptions:[],
+      // 遮罩层
+      loading: true,
+      // 选中数组
+      ids: [],
+      // 非单个禁用
+      single: true,
+      // 非多个禁用
+      multiple: true,
+      // 显示搜索条件
+      showSearch: true,
+      // 总条数
+      total: 0,
+      // 售后记录表格数据
+      storeAfterSalesList: [],
+      // 弹出层标题
+      title: "",
+      // 是否显示弹出层
+      open: false,
+      // 查询参数
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        orderCode: null,
+        refundAmount: null,
+        serviceType: null,
+        reasons: null,
+        explains: null,
+        explainImg: null,
+        shipperCode: null,
+        deliverySn: null,
+        deliveryName: null,
+        status: null,
+        salesStatus: null,
+        isDel: null,
+        userId: null,
+        consignee: null,
+        phoneNumber: null,
+        address: null
+      },
+      // 表单参数
+      form: {},
+      // 表单校验
+      rules: {
+      }
+    };
+  },
+  created() {
+    this.getDicts("store_after_sales_sales_status").then((response) => {
+        this.salesStatusOptions = response.data;
+    });
+    this.getDicts("store_after_sales_status").then((response) => {
+        this.statusOptions = response.data;
+    });
+     this.getDicts("store_after_sales_service_type").then((response) => {
+        this.serviceTypeOptions = response.data;
+    });
+
+    this.getList();
+  },
+  methods: {
+    handleShow(row){
+      this.title="售后订单"
+      this.open=true;
+      setTimeout(() => {
+        this.$refs.afterSalesOrder.getStoreAfterSales(row.id);
+      }, 200);
+
+    },
+
+    /** 查询售后记录列表 */
+    getList() {
+      this.loading = true;
+      myListStoreAfterSales(this.queryParams).then(response => {
+        this.storeAfterSalesList = response.rows;
+        this.total = response.total;
+        this.loading = false;
+      });
+    },
+    // 取消按钮
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 表单重置
+    reset() {
+      this.form = {
+        id: null,
+        orderCode: null,
+        refundAmount: null,
+        serviceType: null,
+        reasons: null,
+        explains: null,
+        explainImg: null,
+        shipperCode: null,
+        deliverySn: null,
+        deliveryName: null,
+        status: 0,
+        salesStatus: 0,
+        createTime: null,
+        isDel: null,
+        userId: null,
+        consignee: null,
+        phoneNumber: null,
+        address: null
+      };
+      this.resetForm("form");
+    },
+    /** 搜索按钮操作 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 重置按钮操作 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    // 多选框选中数据
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.id)
+      this.single = selection.length!==1
+      this.multiple = !selection.length
+    },
+    /** 新增按钮操作 */
+    handleAdd() {
+      this.reset();
+      this.open = true;
+      this.title = "添加售后记录";
+    },
+    /** 修改按钮操作 */
+    handleUpdate(row) {
+      this.reset();
+      const id = row.id || this.ids
+      getStoreAfterSales(id).then(response => {
+        this.form = response.data;
+        this.open = true;
+        this.title = "修改售后记录";
+      });
+    },
+    /** 提交按钮 */
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          if (this.form.id != null) {
+            updateStoreAfterSales(this.form).then(response => {
+              if (response.code === 200) {
+                this.msgSuccess("修改成功");
+                this.open = false;
+                this.getList();
+              }
+            });
+          } else {
+            addStoreAfterSales(this.form).then(response => {
+              if (response.code === 200) {
+                this.msgSuccess("新增成功");
+                this.open = false;
+                this.getList();
+              }
+            });
+          }
+        }
+      });
+    },
+    /** 删除按钮操作 */
+    handleDelete(row) {
+      const ids = row.id || this.ids;
+      this.$confirm('是否确认删除售后记录编号为"' + ids + '"的数据项?', "警告", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        }).then(function() {
+          return delStoreAfterSales(ids);
+        }).then(() => {
+          this.getList();
+          this.msgSuccess("删除成功");
+        }).catch(function() {});
+    },
+    /** 导出按钮操作 */
+    handleExport() {
+      const queryParams = this.queryParams;
+      this.$confirm('是否确认导出所有售后记录数据项?', "警告", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        }).then(function() {
+          return exportStoreAfterSales(queryParams);
+        }).then(response => {
+          this.download(response.msg);
+        }).catch(function() {});
+    }
+  }
+};
+</script>

+ 828 - 0
src/views/hisStore/storeOrder/allList.vue

@@ -0,0 +1,828 @@
+<template>
+  <div class="app-container">
+      <!--用户数据-->
+        <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
+          <el-form-item label="公司名" prop="companyId">
+            <el-select filterable  v-model="queryParams.companyId" placeholder="请选择公司名"  @change="companyChange" clearable size="small">
+                <el-option
+                  v-for="item in companys"
+                  :key="item.companyId"
+                  :label="item.companyName"
+                  :value="item.companyId"
+                />
+            </el-select>
+          </el-form-item>
+          <el-form-item label="所属部门" prop="deptId">
+              <treeselect style="width:220px" v-model="queryParams.deptId" :options="deptOptions" :show-count="true" placeholder="请选择所属部门" />
+          </el-form-item>
+          <el-form-item label="订单号" prop="orderCode">
+            <el-input
+            style="width:220px"
+              v-model="queryParams.orderCode"
+              placeholder="请输入订单号"
+              clearable
+              size="small"
+              @keyup.enter.native="handleQuery"
+            />
+          </el-form-item>
+          <el-form-item label="运单号" prop="deliveryId">
+            <el-input
+            style="width:220px"
+              v-model="queryParams.deliveryId"
+              placeholder="请输入运单号"
+              clearable
+              size="small"
+              @keyup.enter.native="handleQuery"
+            />
+          </el-form-item>
+          <el-form-item label="收件人" prop="realName">
+            <el-input
+            style="width:220px"
+              v-model="queryParams.realName"
+              placeholder="请输入收件人"
+              clearable
+              size="small"
+              @keyup.enter.native="handleQuery"
+            />
+          </el-form-item>
+          <el-form-item label="产品" prop="productName">
+        <el-input
+
+          v-model="queryParams.productName"
+          placeholder="请输入产品名"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+        <el-form-item label="支付方式" prop="payType">
+         <el-select style="width: 200px" v-model="queryParams.payType" placeholder="请选择支付方式" clearable size="small" >
+         <el-option
+                v-for="item in payTypeOptions"
+                :key="item.dictValue"
+                :label="item.dictLabel"
+                :value="item.dictValue"
+              />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="上传凭证" prop="isUpload">
+         <el-select   v-model="queryParams.isUpload" placeholder="请选择" clearable size="small" >
+          <el-option key="0"  label="未上传" value="0" />
+             <el-option key="1"  label="已上传" value="1" />
+        </el-select>
+      </el-form-item>
+          <el-form-item label="手机号" prop="userPhone">
+            <el-input
+            style="width:220px"
+              v-model="queryParams.userPhone"
+              placeholder="请输入收件人手机号"
+              clearable
+              size="small"
+              @keyup.enter.native="handleQuery"
+            />
+          </el-form-item>
+          <el-form-item label="员工姓名" prop="companyUserNickName">
+            <el-input
+            style="width:220px"
+              v-model="queryParams.companyUserNickName"
+              placeholder="请输入员工姓名"
+              clearable
+              size="small"
+              @keyup.enter.native="handleQuery"
+            />
+          </el-form-item>
+          <el-form-item label="订单类型" prop="orderType">
+            <el-select style="width:220px" v-model="queryParams.orderType" placeholder="请选择订单类型" clearable size="small" >
+            <el-option
+                    v-for="item in orderTypeOptions"
+                    :key="item.dictValue"
+                    :label="item.dictLabel"
+                    :value="item.dictValue"
+                  />
+            </el-select>
+          </el-form-item>
+          <el-form-item label="物流状态" prop="deliveryStatus">
+            <el-select  style="width:220px" v-model="queryParams.deliveryStatus" placeholder="请选择物流状态" clearable size="small" >
+            <el-option
+                    v-for="item in deliveryStatusOptions"
+                    :key="item.dictValue"
+                    :label="item.dictLabel"
+                    :value="item.dictValue"
+                  />
+            </el-select>
+          </el-form-item>
+          <el-form-item label="结算状态" prop="deliveryPayStatus">
+            <el-select style="width:220px" v-model="queryParams.deliveryPayStatus" placeholder="请选择物流结算状态" clearable size="small" >
+            <el-option
+                    v-for="item in deliveryPayStatusOptions"
+                    :key="item.dictValue"
+                    :label="item.dictLabel"
+                    :value="item.dictValue"
+                  />
+            </el-select>
+          </el-form-item>
+          <el-form-item label="下单时间" prop="createTimeRange">
+            <el-date-picker
+            style="width:220px"
+              clearable size="small"
+              v-model="createTimeRange"
+              type="daterange"
+              value-format="yyyy-MM-dd"
+              start-placeholder="开始日期"
+              end-placeholder="结束日期">
+            </el-date-picker>
+          </el-form-item>
+          <el-form-item label="支付时间" prop="payTimeRange">
+            <el-date-picker
+            style="width:220px"
+              clearable size="small"
+              v-model="payTimeRange"
+              type="daterange"
+              value-format="yyyy-MM-dd"
+              start-placeholder="开始日期"
+              end-placeholder="结束日期">
+            </el-date-picker>
+          </el-form-item>
+          <el-form-item label="回单时间" prop="deliveryImportTimeRange">
+            <el-date-picker
+            style="width:220px"
+              clearable size="small"
+              v-model="deliveryImportTimeRange"
+              type="daterange"
+              value-format="yyyy-MM-dd"
+              start-placeholder="开始日期"
+              end-placeholder="结束日期">
+            </el-date-picker>
+          </el-form-item>
+          <el-form-item label="档期归属" prop="scheduleId"  >
+            <el-select filterable style="width: 200px" v-model="queryParams.scheduleId" placeholder="请选择档期" clearable size="small" >
+              <el-option
+                      v-for="item in scheduleOptions"
+                      :key="item.id"
+                      :label="item.name"
+                      :value="item.id"
+                    />
+            </el-select>
+        </el-form-item>
+        <el-form-item label="跟随阶段" prop="orderVisit"  >
+          <el-select filterable style="width: 200px" v-model="queryParams.orderVisit" placeholder="请选择跟随阶段" clearable size="small" >
+            <el-option
+                v-for="item in customerUserStatusOptions"
+                :key="item.dictValue"
+                :label="item.dictLabel"
+                :value="item.dictValue"
+              />
+          </el-select>
+        </el-form-item>
+          <el-form-item>
+            <el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+            <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
+          </el-form-item>
+        </el-form>
+        <el-row :gutter="10" class="mb8">
+        <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+        </el-row>
+        <el-tabs type="card" v-model="activeName" @tab-click="handleClick">
+          <el-tab-pane label="全部订单" name="00"></el-tab-pane>
+          <el-tab-pane label="待支付" name="0"></el-tab-pane>
+          <el-tab-pane label="待发货" name="1"></el-tab-pane>
+          <el-tab-pane label="待收货" name="2"></el-tab-pane>
+          <el-tab-pane label="交易完成" name="3"></el-tab-pane>
+          <el-tab-pane label="退款中" name="-1"></el-tab-pane>
+          <el-tab-pane label="已退款" name="-2"></el-tab-pane>
+          <el-tab-pane label="已取消" name="-3"></el-tab-pane>
+        </el-tabs>
+        <el-table height="500" border v-loading="loading" :data="storeOrderList" @selection-change="handleSelectionChange">
+          <el-table-column type="selection" width="55" align="center" />
+          <el-table-column label="订单号" align="center" prop="orderCode" />
+          <el-table-column label="所属公司" align="center" prop="companyName" />
+          <el-table-column label="所属员工" align="center" prop="companyUserNickName" />
+          <el-table-column label="用户昵称" align="center" prop="nickname" width="150px" >
+              <template slot-scope="scope">
+                  <span>{{scope.row.nickname}}</span>
+              </template>
+          </el-table-column>
+          <el-table-column label="收件人" align="center" prop="realName" width="150px" >
+              <template slot-scope="scope">
+                  <span>{{scope.row.realName}} </span>
+              </template>
+          </el-table-column>
+          <el-table-column label="跟随阶段" align="center" prop="orderVisit" >
+            <template slot-scope="scope">
+                <el-tag prop="orderVisit" v-for="(item, index) in customerUserStatusOptions"    v-if="scope.row.orderVisit==item.dictValue">{{item.dictLabel}}</el-tag>
+            </template>
+          </el-table-column>
+          <el-table-column label="订单金额" align="center" prop="totalPrice" >
+              <template slot-scope="scope">
+                  <span v-if="scope.row.totalPrice!=null">{{scope.row.totalPrice.toFixed(2)}}</span>
+              </template>
+          </el-table-column>
+          <el-table-column label="应付金额" align="center" prop="payPrice" >
+              <template slot-scope="scope">
+                  <span v-if="scope.row.payPrice!=null">{{scope.row.payPrice.toFixed(2)}}</span>
+              </template>
+          </el-table-column>
+          <el-table-column label="下单时间" align="center" prop="createTime" />
+          <!-- <el-table-column label="支付状态" align="center" prop="paid" /> -->
+          <el-table-column label="支付时间" align="center" prop="payTime" width="180">
+          </el-table-column>
+          <el-table-column label="支付方式" align="center" prop="payType" >
+              <template slot-scope="scope">
+                  <span prop="payType" v-for="(item, index) in payTypeOptions"    v-if="scope.row.payType==item.dictValue">{{item.dictLabel}}</span>
+              </template>
+          </el-table-column>
+          <el-table-column label="订单类型" align="center" prop="orderType" >
+              <template slot-scope="scope">
+                  <el-tag prop="status" v-for="(item, index) in orderTypeOptions"    v-if="scope.row.orderType==item.dictValue">{{item.dictLabel}}</el-tag>
+              </template>
+          </el-table-column>
+          <el-table-column label="状态" align="center" prop="status" >
+              <template slot-scope="scope">
+                  <el-tag prop="status" v-for="(item, index) in statusOptions"    v-if="scope.row.status==item.dictValue">{{item.dictLabel}}</el-tag>
+              </template>
+          </el-table-column>
+          <el-table-column label="物流状态" align="center" prop="deliveryStatus" >
+              <template slot-scope="scope">
+                  <el-tag prop="status" v-for="(item, index) in deliveryStatusOptions"    v-if="scope.row.deliveryStatus==item.dictValue">{{item.dictLabel}}</el-tag>
+              </template>
+          </el-table-column>
+          <el-table-column label="物流结算状态" align="center" prop="deliveryPayStatus" >
+              <template slot-scope="scope">
+                  <el-tag prop="status" v-for="(item, index) in deliveryPayStatusOptions"    v-if="scope.row.deliveryPayStatus==item.dictValue">{{item.dictLabel}}</el-tag>
+              </template>
+          </el-table-column>
+          <el-table-column label="操作" fixed="right" width="100px" align="center" class-name="small-padding fixed-width">
+            <template slot-scope="scope">
+              <el-button
+                size="mini"
+                type="text"
+                @click="handleDetails(scope.row)"
+                v-hasPermi="['store:storeOrder:query']"
+              >查看</el-button>
+              <!-- <el-button
+                size="mini"
+                type="text"
+                @click="handleGenPayUrl(scope.row)"
+                v-hasPermi="['store:storeOrder:genPayUrl']"
+              >生成付款链接</el-button> -->
+            </template>
+          </el-table-column>
+        </el-table>
+
+        <pagination
+          v-show="total>0"
+          :total="total"
+          :page.sync="queryParams.pageNum"
+          :limit.sync="queryParams.pageSize"
+          @pagination="getList"
+        />
+    <el-drawer
+     size="75%"
+      :title="show.title" :visible.sync="show.open"
+      >
+      <product-order  ref="order" />
+    </el-drawer>
+
+  </div>
+</template>
+
+<script>
+import {exportStoreOrderItems, createUserOrder,listAllStoreOrder, getStoreOrder, delStoreOrder, addStoreOrder, updateStoreOrder, exportStoreOrder } from "@/api/hisStore/storeOrder";
+import { getUserList } from "@/api/users/user";
+import { getAddressList } from "@/api/users/userAddress";
+import { getTcmScheduleList } from "@/api/company/tcmScheduleReport";
+import productOrder from "../components/productOrder";
+import productSelect from "../components/productSelect";
+import addUser from "../components/addUser";
+import addUserAddress from "../components/addUserAddress";
+import config from "@/utils/config";
+import QRCode from 'qrcodejs2'
+import { treeselect } from "@/api/company/companyDept";
+import Treeselect from "@riophae/vue-treeselect";
+import { getCompanyList } from "@/api/company/company";
+import "@riophae/vue-treeselect/dist/vue-treeselect.css";
+export default {
+  components: { Treeselect,productOrder,productSelect,addUser,addUserAddress },
+  name: "StoreOrder",
+  data() {
+    return {
+      customerUserStatusOptions:[],
+      // 部门树选项
+      companys:[],
+      deptOptions:[],
+      companyId:undefined,
+      deptId:undefined,
+      // 是否显示弹出层
+      open: false,
+      // 部门名称
+      deptName: undefined,
+      defaultProps: {
+        children: "children",
+        label: "label",
+      },
+      deliveryPayStatusOptions:[],
+      deliveryStatusOptions:[],
+      dateRange: [],
+      orderTypeOptions:[],
+      payTypeOptions:[],
+      payQr:{
+        open:false,
+        title:"付款二维码"
+      },
+      user:{
+        open:false,
+        title:"创建会员"
+      },
+      userAddress:{
+        open:false,
+        title:"创建收货地址"
+      },
+      tablekey:false,
+      totalMoney:0.00,
+      products:[],
+      product:{
+        open:false,
+        title:"商品选择"
+      },
+      userStatusOptions:[],
+      phone:null,
+      address:[],
+      addressloading: false,
+      userloading: false,
+      users:[],
+      userStatusOptions:[],
+      show:{
+        open:false,
+        title:"订单详情"
+      },
+      activeName:"00",
+      statusOptions:[],
+      // 遮罩层
+      loading: true,
+      // 选中数组
+      ids: [],
+      // 非单个禁用
+      single: true,
+      // 非多个禁用
+      multiple: true,
+
+      // 显示搜索条件
+      showSearch: true,
+      // 总条数
+      total: 0,
+      // 订单表格数据
+      storeOrderList: [],
+      // 弹出层标题
+      title: "",
+      // 是否显示弹出层
+      open: false,
+      createTimeRange:[],
+      payTimeRange:[],
+      deliveryImportTimeRange:[],
+      scheduleOptions:[],
+      // 查询参数
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        orderCode: null,
+        extendOrderId: null,
+        userId: null,
+        realName: null,
+        userPhone: null,
+        userAddress: null,
+        cartId: null,
+        freightPrice: null,
+        totalNum: null,
+        totalPrice: null,
+        totalPostage: null,
+        payPrice: null,
+        payPostage: null,
+        deductionPrice: null,
+        couponId: null,
+        couponPrice: null,
+        paid: null,
+        payTime: null,
+        payType: null,
+        status: null,
+        refundStatus: null,
+        refundReasonWapImg: null,
+        refundReasonWapExplain: null,
+        refundReasonTime: null,
+        refundReasonWap: null,
+        refundReason: null,
+        refundPrice: null,
+        deliverySn: null,
+        deliveryName: null,
+        deliveryType: null,
+        deliveryId: null,
+        gainIntegral: null,
+        useIntegral: null,
+        payIntegral: null,
+        backIntegral: null,
+        mark: null,
+        isDel: null,
+        cost: null,
+        verifyCode: null,
+        storeId: null,
+        shippingType: null,
+        isChannel: null,
+        isRemind: null,
+        isSysDel: null
+      },
+      // 表单参数
+      form: {
+        addressId:null,
+        userId:null,
+        products:[],
+      },
+      // 表单校验
+      rules: {
+        userId: [
+          { required: true, message: "会员信息不能为空" }
+        ],
+        addressId: [
+          { required: true, message: "收货信息不能为空" }
+        ],
+        products: [
+          { required: true, message: "商品不能为空" }
+        ],
+
+      }
+    };
+  },
+  watch: {
+    // 根据名称筛选部门树
+    watch: {
+    // 监听deptId
+    'deptId': 'currDeptChange'
+    }
+  },
+  created() {
+    getCompanyList().then(response => {
+        this.companys = response.data;
+         if(this.companys!=null&&this.companys.length>0){
+          this.companyId=this.companys[0].companyId;
+          this.getTreeselect();
+        }
+    });
+    this.getDicts("crm_customer_user_status").then((response) => {
+        this.customerUserStatusOptions = response.data;
+    });
+    this.getDicts("store_order_type").then((response) => {
+      this.orderTypeOptions = response.data;
+    });
+    this.getDicts("store_pay_type").then((response) => {
+      this.payTypeOptions = response.data;
+    });
+    this.getDicts("user_status").then((response) => {
+      this.userStatusOptions = response.data;
+    });
+    this.getDicts("store_order_status").then((response) => {
+      this.statusOptions = response.data;
+    });
+    this.getDicts("store_order_delivery_status").then((response) => {
+      this.deliveryStatusOptions = response.data;
+    });
+    this.getDicts("store_delivery_pay_status").then((response) => {
+      this.deliveryPayStatusOptions = response.data;
+    });
+    getTcmScheduleList().then(response => {
+      this.scheduleOptions = response.data;
+    });
+    this.getList();
+  },
+  methods: {
+     /** 查询部门下拉树结构 */
+    getTreeselect() {
+      var that=this;
+      var param={companyId:this.companyId}
+      treeselect(param).then((response) => {
+        this.deptOptions = response.data;
+        if(response.data!=null&&response.data.length>0){
+          //this.queryParams.deptId=response.data[0].id;
+        }
+      });
+    },
+     companyChange(val){
+      this.companyId=val;
+      this.getTreeselect();
+    },
+     currDeptChange(val){
+      this.queryParams.deptId=val;
+      this.getList();
+    },
+    // 筛选节点
+    filterNode(value, data) {
+      if (!value) return true;
+      return data.label.indexOf(value) !== -1;
+    },
+    // 节点单击事件
+    handleNodeClick(data) {
+      this.queryParams.deptId = data.id;
+      this.getList();
+    },
+    handleGenPayUrl(row){
+      this.payQr.open=true;
+      setTimeout(() => {
+        var qrcode = new QRCode(this.$refs.qrCodeUrl, {
+            text: config.payQRUrl+row.id, // 需要转换为二维码的内容
+            width: 200,
+            height: 200,
+            colorDark: '#000000',
+            colorLight: '#ffffff',
+            correctLevel: QRCode.CorrectLevel.H
+        })
+      }, 200);
+
+
+    },
+    handleAddUser(){
+      this.user.open=true;
+    },
+    handleAddUserAddress(){
+      if(this.form.userId==null){
+        this.msgError("请选择会员");
+        return;
+      }
+      this.userAddress.open=true;
+      setTimeout(() => {
+        this.$refs.addUserAddress.init(this.form.userId);
+      }, 500);
+    },
+    addUser(){
+      this.user.open=false;
+    },
+    addUserAddress(){
+      this.userAddress.open=false;
+      //获取地址
+      this.getAddressList(this.form.userId);
+    },
+    compute(){
+      this.totalMoney=0;
+      var that=this;
+      this.products.forEach (function (value) {
+          that.totalMoney += value.money;
+      });
+    },
+    handleProductCountChange(row){
+      this.tablekey = !this.tablekey
+      row.money=row.count*row.price;
+      this.$forceUpdate();
+      this.compute();
+    },
+    selectProduct(row){
+      for(var i=0;i<this.products.length;i++){
+        if(this.products[i].id==row.id){
+          return;
+        }
+      }
+      row.count=1;
+      row.money=row.count*row.price;
+      this.products.push(row);
+      this.compute();
+    },
+    handleAddProduct(){
+      this.product.open=true;
+    },
+    searchUser(){
+      if(this.phone==null||this.phone==""){
+        return;
+      }
+      var data={phone:this.phone}
+      this.userloading = true;
+      this.users=[];
+      this.address=[];
+      getUserList(data).then(response => {
+        this.users = response.data;
+        this.userloading = false;
+        if(this.users!=null&&this.users.length==1){
+          this.form.userId=this.users[0].userId;
+          this.getAddressList(this.form.userId)
+        }
+      });
+    },
+    getAddressList(userId){
+      var data={userId:userId}
+      this.addressloading = true;
+      this.address=[];
+      getAddressList(data).then(response => {
+        this.address = response.data;
+        this.addressloading = false;
+      });
+    },
+    handleDetails(row){
+      this.show.open=true;
+      const orderId = row.id ;
+      setTimeout(() => {
+        this.$refs.order.getOrder(orderId);
+      }, 500);
+    },
+    handleClick(tab, event) {
+       if(tab.name=="all"){
+        this.queryParams.status==null;
+      }
+      else{
+         this.queryParams.status=tab.name;
+      }
+      this.getList();
+    },
+    /** 查询订单列表 */
+    getList() {
+      if(this.queryParams.status=='00'){
+        this.queryParams.status=null;
+      }
+      if(this.createTimeRange!=null&&this.createTimeRange.length==2){
+        this.queryParams.createTimeRange=this.createTimeRange[0]+"--"+this.createTimeRange[1]
+      }
+      else{
+        this.queryParams.createTimeRange=null;
+      }
+      if(this.payTimeRange!=null&&this.payTimeRange.length==2){
+        this.queryParams.payTimeRange=this.payTimeRange[0]+"--"+this.payTimeRange[1]
+      }
+      else{
+        this.queryParams.payTimeRange=null;
+      }
+      if(this.deliveryImportTimeRange!=null&&this.deliveryImportTimeRange.length==2){
+        this.queryParams.deliveryImportTimeRange=this.deliveryImportTimeRange[0]+"--"+this.deliveryImportTimeRange[1]
+      }
+      else{
+        this.queryParams.deliveryImportTimeRange=null;
+      }
+      this.loading = true;
+      listAllStoreOrder(this.addDateRange(this.queryParams, this.dateRange)).then(response => {
+        this.storeOrderList = response.rows;
+        this.total = response.total;
+        this.loading = false;
+      });
+    },
+    // 取消按钮
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 表单重置
+    reset() {
+      this.form = {
+        addressId:null,
+        userId:null,
+        products:null,
+
+      };
+      this.resetForm("form");
+    },
+    /** 搜索按钮操作 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 重置按钮操作 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    // 多选框选中数据
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.id)
+      this.single = selection.length!==1
+      this.multiple = !selection.length
+    },
+    /** 新增按钮操作 */
+    handleAdd() {
+      this.reset();
+      this.open = true;
+      this.title = "创建订单";
+    },
+    /** 修改按钮操作 */
+    handleUpdate(row) {
+      this.reset();
+      const id = row.id || this.ids
+      getStoreOrder(id).then(response => {
+        this.form = response.data;
+        this.open = true;
+        this.title = "修改订单";
+      });
+    },
+    /** 提交按钮 */
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        if(this.products.length==0){
+          this.msgError("请选择商品");
+          return;
+        }
+        this.form.products=this.products;
+        if (valid) {
+          createUserOrder(this.form).then(response => {
+            if (response.code === 200) {
+              this.msgSuccess("创建成功");
+              this.open = false;
+              this.getList();
+            }
+          });
+
+        }
+      });
+    },
+    /** 删除按钮操作 */
+    handleDelete(row) {
+       this.products.splice(this.products.findIndex(item => item.id === row.id), 1)
+       this.compute();
+
+    },
+    /** 导出按钮操作 */
+    handleExport() {
+
+      if(this.queryParams.status=='00'){
+        this.queryParams.status=null;
+      }
+      if(this.createTimeRange!=null&&this.createTimeRange.length==2){
+        this.queryParams.createTimeRange=this.createTimeRange[0]+"--"+this.createTimeRange[1]
+      }
+      else{
+        this.queryParams.createTimeRange=null;
+      }
+      if(this.payTimeRange!=null&&this.payTimeRange.length==2){
+        this.queryParams.payTimeRange=this.payTimeRange[0]+"--"+this.payTimeRange[1]
+      }
+      else{
+        this.queryParams.payTimeRange=null;
+      }
+      if(this.deliveryImportTimeRange!=null&&this.deliveryImportTimeRange.length==2){
+        this.queryParams.deliveryImportTimeRange=this.deliveryImportTimeRange[0]+"--"+this.deliveryImportTimeRange[1]
+      }
+      else{
+        this.queryParams.deliveryImportTimeRange=null;
+      }
+
+      const queryParams = this.addDateRange(this.queryParams, this.dateRange);
+      this.$confirm('是否确认导出所有订单数据项?', "警告", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        }).then(function() {
+          return exportStoreOrder(queryParams);
+        }).then(response => {
+          this.download(response.msg);
+        }).catch(function() {});
+    },
+    handleExportItems() {
+      if(this.queryParams.status=='00'){
+        this.queryParams.status=null;
+      }
+      if(this.createTimeRange!=null&&this.createTimeRange.length==2){
+        this.queryParams.createTimeRange=this.createTimeRange[0]+"--"+this.createTimeRange[1]
+      }
+      else{
+        this.queryParams.createTimeRange=null;
+      }
+      if(this.payTimeRange!=null&&this.payTimeRange.length==2){
+        this.queryParams.payTimeRange=this.payTimeRange[0]+"--"+this.payTimeRange[1]
+      }
+      else{
+        this.queryParams.payTimeRange=null;
+      }
+      if(this.deliveryImportTimeRange!=null&&this.deliveryImportTimeRange.length==2){
+        this.queryParams.deliveryImportTimeRange=this.deliveryImportTimeRange[0]+"--"+this.deliveryImportTimeRange[1]
+      }
+      else{
+        this.queryParams.deliveryImportTimeRange=null;
+      }
+      const queryParams = this.addDateRange(this.queryParams, this.dateRange);
+      this.$confirm('是否确认导出所有订单明细数据项?', "警告", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        }).then(function() {
+          return exportStoreOrderItems(queryParams);
+        }).then(response => {
+          this.download(response.msg);
+        }).catch(function() {});
+    }
+  }
+};
+</script>
+<style scoped lang="scss">
+.items{
+  margin: 5px 0px;
+  display: flex;
+  flex-direction: row;
+  align-items: center;
+  justify-content: flex-start;
+  .pic{
+    width:60px;
+    height:60px;
+  }
+  .goods-content{
+    margin-left: 10px;
+    max-width: 200px;
+    text-align: left;
+    .goods-title{
+
+      overflow:hidden;
+      white-space: nowrap;
+      text-overflow: ellipsis;
+      -o-text-overflow:ellipsis;
+    }
+  }
+}
+</style>

+ 1000 - 0
src/views/hisStore/storeOrder/list.vue

@@ -0,0 +1,1000 @@
+<template>
+  <div class="app-container">
+      <!--用户数据-->
+        <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
+          <el-form-item label="所属部门" prop="deptId">
+              <treeselect style="width:220px" v-model="queryParams.deptId" :options="deptOptions" :show-count="true" placeholder="请选择所属部门" />
+          </el-form-item>
+          <el-form-item label="订单号" prop="orderCode">
+            <el-input
+            style="width:220px"
+              v-model="queryParams.orderCode"
+              placeholder="请输入订单号"
+              clearable
+              size="small"
+              @keyup.enter.native="handleQuery"
+            />
+          </el-form-item>
+          <el-form-item label="运单号" prop="deliveryId">
+            <el-input
+            style="width:220px"
+              v-model="queryParams.deliveryId"
+              placeholder="请输入运单号"
+              clearable
+              size="small"
+              @keyup.enter.native="handleQuery"
+            />
+          </el-form-item>
+          <el-form-item label="收件人" prop="realName">
+            <el-input
+            style="width:220px"
+              v-model="queryParams.realName"
+              placeholder="请输入收件人"
+              clearable
+              size="small"
+              @keyup.enter.native="handleQuery"
+            />
+          </el-form-item>
+          <el-form-item label="产品" prop="productName">
+        <el-input
+
+          v-model="queryParams.productName"
+          placeholder="请输入产品名"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+        <el-form-item label="支付方式" prop="payType">
+         <el-select style="width: 200px" v-model="queryParams.payType" placeholder="请选择支付方式" clearable size="small" >
+         <el-option
+                v-for="item in payTypeOptions"
+                :key="item.dictValue"
+                :label="item.dictLabel"
+                :value="item.dictValue"
+              />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="上传凭证" prop="isUpload">
+         <el-select   v-model="queryParams.isUpload" placeholder="请选择" clearable size="small" >
+          <el-option key="0"  label="未上传" value="0" />
+             <el-option key="1"  label="已上传" value="1" />
+        </el-select>
+      </el-form-item>
+          <el-form-item label="手机号" prop="userPhone">
+            <el-input
+            style="width:220px"
+              v-model="queryParams.userPhone"
+              placeholder="请输入收件人手机号"
+              clearable
+              size="small"
+              @keyup.enter.native="handleQuery"
+            />
+          </el-form-item>
+          <el-form-item label="员工姓名" prop="companyUserNickName">
+            <el-input
+            style="width:220px"
+              v-model="queryParams.companyUserNickName"
+              placeholder="请输入员工姓名"
+              clearable
+              size="small"
+              @keyup.enter.native="handleQuery"
+            />
+          </el-form-item>
+          <el-form-item label="订单类型" prop="orderType">
+            <el-select style="width:220px" v-model="queryParams.orderType" placeholder="请选择订单类型" clearable size="small" >
+            <el-option
+             v-for="item in orderTypeOptions"
+               :key="item.dictValue"
+               :label="item.dictLabel"
+               :value="item.dictValue"
+             />
+            </el-select>
+          </el-form-item>
+          <el-form-item label="物流状态" prop="deliveryStatus">
+            <el-select  style="width:220px" v-model="queryParams.deliveryStatus" placeholder="请选择物流状态" clearable size="small" >
+            <el-option
+             v-for="item in deliveryStatusOptions"
+               :key="item.dictValue"
+               :label="item.dictLabel"
+               :value="item.dictValue"
+             />
+            </el-select>
+          </el-form-item>
+          <el-form-item label="结算状态" prop="deliveryPayStatus">
+            <el-select style="width:220px" v-model="queryParams.deliveryPayStatus" placeholder="请选择物流结算状态" clearable size="small" >
+                <el-option
+                 v-for="item in deliveryPayStatusOptions"
+                   :key="item.dictValue"
+                   :label="item.dictLabel"
+                   :value="item.dictValue"
+                 />
+            </el-select>
+          </el-form-item>
+          <el-form-item label="下单时间" prop="createTimeRange">
+            <el-date-picker
+            style="width:220px"
+              clearable size="small"
+              v-model="createTimeRange"
+              type="daterange"
+              value-format="yyyy-MM-dd"
+              start-placeholder="开始日期"
+              end-placeholder="结束日期">
+            </el-date-picker>
+          </el-form-item>
+          <el-form-item label="支付时间" prop="payTimeRange">
+            <el-date-picker
+            style="width:220px"
+              clearable size="small"
+              v-model="payTimeRange"
+              type="daterange"
+              value-format="yyyy-MM-dd"
+              start-placeholder="开始日期"
+              end-placeholder="结束日期">
+            </el-date-picker>
+          </el-form-item>
+          <el-form-item label="回单时间" prop="deliveryImportTimeRange">
+            <el-date-picker
+            style="width:220px"
+              clearable size="small"
+              v-model="deliveryImportTimeRange"
+              type="daterange"
+              value-format="yyyy-MM-dd"
+              start-placeholder="开始日期"
+              end-placeholder="结束日期">
+            </el-date-picker>
+          </el-form-item>
+          <el-form-item label="档期归属" prop="scheduleId"  >
+            <el-select filterable style="width: 200px" v-model="queryParams.scheduleId" placeholder="请选择档期" clearable size="small" >
+              <el-option
+                      v-for="item in scheduleOptions"
+                      :key="item.id"
+                      :label="item.name"
+                      :value="item.id"
+                    />
+            </el-select>
+        </el-form-item>
+          <el-form-item>
+            <el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+            <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
+          </el-form-item>
+        </el-form>
+        <el-row :gutter="10" class="mb8">
+          <el-col :span="1.5">
+            <el-button
+              type="primary"
+              icon="el-icon-plus"
+              size="mini"
+              @click="handleAdd"
+              v-hasPermi="['store:storeOrder:add']"
+            >创建订单</el-button>
+          </el-col>
+          <el-col :span="1.5">
+            <el-button
+              type="warning"
+              icon="el-icon-download"
+              size="mini"
+              @click="handleExport"
+            >导出订单</el-button>
+          </el-col>
+          <el-col :span="1.5">
+            <el-button
+              type="warning"
+              icon="el-icon-download"
+              size="mini"
+              @click="handleExportItems"
+              v-hasPermi="['store:storeOrder:exportItems']"
+            >导出订单明细</el-button>
+          </el-col>
+        <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+        </el-row>
+        <el-tabs type="card" v-model="activeName" @tab-click="handleClick">
+          <el-tab-pane label="全部订单" name="00"></el-tab-pane>
+          <el-tab-pane label="待支付" name="0"></el-tab-pane>
+          <el-tab-pane label="待发货" name="1"></el-tab-pane>
+          <el-tab-pane label="待收货" name="2"></el-tab-pane>
+          <el-tab-pane label="交易完成" name="3"></el-tab-pane>
+          <el-tab-pane label="退款中" name="-1"></el-tab-pane>
+          <el-tab-pane label="已退款" name="-2"></el-tab-pane>
+          <el-tab-pane label="已取消" name="-3"></el-tab-pane>
+        </el-tabs>
+        <el-table height="500" border v-loading="loading" :data="storeOrderList" @selection-change="handleSelectionChange">
+          <el-table-column type="selection" width="55" align="center" />
+          <el-table-column label="订单号" align="center" prop="orderCode" />
+          <el-table-column label="所属公司" align="center" prop="companyName" />
+          <el-table-column label="所属员工" align="center" prop="companyUserNickName" />
+          <el-table-column label="用户昵称" align="center" prop="nickname" width="150px" >
+              <template slot-scope="scope">
+                  <span>{{scope.row.nickname}}</span>
+              </template>
+          </el-table-column>
+          <el-table-column label="收件人" align="center" prop="realName" width="150px" >
+              <template slot-scope="scope">
+                  <span>{{scope.row.realName}} </span>
+              </template>
+          </el-table-column>
+          <!-- <el-table-column label="商品" align="center" width="300px" >
+              <template slot-scope="scope">
+                  <div  v-for="(item, index) in scope.row.items" class="items"  >
+                    <img class="pic" :src="JSON.parse(item.jsonInfo).image" />
+                    <div class="goods-content">
+                      <div class="goods-title">{{ JSON.parse(item.jsonInfo).productName}}</div>
+                      <div class="sku">{{ JSON.parse(item.jsonInfo).sku}}</div>
+                      <div class="price">¥{{JSON.parse(item.jsonInfo).price}}×{{item.num}}</div>
+                    </div>
+
+                  </div>
+              </template>
+          </el-table-column> -->
+          <el-table-column label="订单金额" align="center" prop="totalPrice" >
+              <template slot-scope="scope">
+                  <span v-if="scope.row.totalPrice!=null">{{scope.row.totalPrice.toFixed(2)}}</span>
+              </template>
+          </el-table-column>
+          <el-table-column label="应付金额" align="center" prop="payPrice" >
+              <template slot-scope="scope">
+                  <span v-if="scope.row.payPrice!=null">{{scope.row.payPrice.toFixed(2)}}</span>
+              </template>
+          </el-table-column>
+          <el-table-column label="下单时间" align="center" prop="createTime" />
+          <!-- <el-table-column label="支付状态" align="center" prop="paid" /> -->
+          <el-table-column label="支付时间" align="center" prop="payTime" width="180">
+          </el-table-column>
+          <el-table-column label="支付方式" align="center" prop="payType" >
+              <template slot-scope="scope">
+                  <span prop="payType" v-for="(item, index) in payTypeOptions"    v-if="scope.row.payType==item.dictValue">{{item.dictLabel}}</span>
+              </template>
+          </el-table-column>
+          <el-table-column label="订单类型" align="center" prop="orderType" >
+              <template slot-scope="scope">
+                  <el-tag prop="status" v-for="(item, index) in orderTypeOptions"    v-if="scope.row.orderType==item.dictValue">{{item.dictLabel}}</el-tag>
+              </template>
+          </el-table-column>
+          <el-table-column label="媒体来源" align="center" prop="orderMedium" >
+          <template slot-scope="scope">
+              <el-tag prop="orderMedium" v-for="(item, index) in orderMediumOptions"    v-if="scope.row.orderMedium==item.dictValue">{{item.dictLabel}}</el-tag>
+          </template>
+          </el-table-column>
+          <el-table-column label="订单产品" align="center" width="200px">
+            <template slot-scope="scope">
+              <div v-if="scope.row.items && scope.row.items.length > 0">
+                <el-tag
+                  v-for="(item, index) in scope.row.items"
+                  :key="index"
+                  size="mini"
+                  class="product-tag"
+                >
+                  {{ JSON.parse(item.jsonInfo).productName }} × {{ item.num }}
+                </el-tag>
+              </div>
+              <span v-else class="no-products">暂无商品</span>
+            </template>
+          </el-table-column>
+          <el-table-column label="状态" align="center" prop="status" >
+              <template slot-scope="scope">
+                  <el-tag prop="status" v-for="(item, index) in statusOptions"    v-if="scope.row.status==item.dictValue">{{item.dictLabel}}</el-tag>
+              </template>
+          </el-table-column>
+          <el-table-column label="运单号" align="center" prop="deliveryId" >
+          </el-table-column>
+          <el-table-column label="物流状态" align="center" prop="deliveryStatus" >
+              <template slot-scope="scope">
+                  <el-tag prop="status" v-for="(item, index) in deliveryStatusOptions"    v-if="scope.row.deliveryStatus==item.dictValue">{{item.dictLabel}}</el-tag>
+              </template>
+          </el-table-column>
+          <el-table-column label="物流结算状态" align="center" prop="deliveryPayStatus" >
+              <template slot-scope="scope">
+                  <el-tag prop="status" v-for="(item, index) in deliveryPayStatusOptions"    v-if="scope.row.deliveryPayStatus==item.dictValue">{{item.dictLabel}}</el-tag>
+              </template>
+          </el-table-column>
+          <el-table-column label="操作" fixed="right" width="100px" align="center" class-name="small-padding fixed-width">
+            <template slot-scope="scope">
+              <el-button
+                size="mini"
+                type="text"
+                @click="handleDetails(scope.row)"
+                v-hasPermi="['store:storeOrder:query']"
+              >查看</el-button>
+           <!--    <el-button
+                size="mini"
+                type="text"
+                @click="handleGenPayUrl(scope.row)"
+                v-hasPermi="['store:storeOrder:genPayUrl']"
+              >生成付款链接</el-button> -->
+            </template>
+          </el-table-column>
+        </el-table>
+
+        <pagination
+          v-show="total>0"
+          :total="total"
+          :page.sync="queryParams.pageNum"
+          :limit.sync="queryParams.pageSize"
+          @pagination="getList"
+        />
+    <el-drawer
+     size="75%"
+      :title="show.title" :visible.sync="show.open"
+      >
+      <product-order  ref="order" />
+    </el-drawer>
+    <el-dialog :title="title" v-if="open" :visible.sync="open" width="1000px" append-to-body :close-on-click-modal ="false">
+        <el-form ref="form" :model="form" :rules="rules" label-width="120px">
+           <el-form-item label="会员信息" >
+                <el-row  >
+                  <el-col >
+                      <el-input placeholder="请输入会员手机号" style="width:240px;cursor:pointer" v-model="phone">
+                      </el-input>
+                      <el-button plain style="margin-left:10px;"    @click="searchUser()">查询</el-button>
+                      <el-button plain style="margin-left:10px;" icon="el-icon-plus"  type="primary" @click="handleAddUser()">添加会员</el-button>
+                  </el-col>
+                </el-row>
+                <el-table border style="margin-top:5px;"  v-loading="userloading" :data="users">
+                  <el-table-column label="ID" align="center" prop="userId" />
+                  <el-table-column label="会员头像" align="center" width="80">
+                    <template slot-scope="scope">
+                      <el-popover
+                        placement="right"
+                        title=""
+                        trigger="hover"
+                      >
+                        <img slot="reference" :src="scope.row.avatar" width="50" >
+                        <img :src="scope.row.avatar" style="max-width: 120px;">
+                      </el-popover>
+                    </template>
+                  </el-table-column>
+                  <el-table-column label="昵称" align="center" prop="nickname" />
+                  <el-table-column label="手机号" align="center" prop="phone" />
+                  <el-table-column label="状态" align="center" prop="status" >
+                      <template slot-scope="scope">
+                          <el-tag prop="status" v-for="(item, index) in userStatusOptions"    v-if="scope.row.status==item.dictValue">{{item.dictLabel}}</el-tag>
+                      </template>
+                  </el-table-column>
+                </el-table>
+            </el-form-item>
+            <el-form-item label="收货信息" prop="addressId">
+              <el-row  >
+                <el-col >
+                      <el-button plain  type="primary" icon="el-icon-plus"  @click="handleAddUserAddress()">添加收货地址</el-button>
+                </el-col>
+              </el-row>
+              <el-radio-group v-model="form.addressId" style="width:100%">
+              <el-table border  style="margin-top:5px;"  v-loading="addressloading" :data="address">
+                <el-table-column label="ID" align="center"  >
+                    <template slot-scope="scope">
+                       <el-radio :label="scope.row.addressId"></el-radio>
+                    </template>
+                </el-table-column>
+                <el-table-column label="收货人姓名" align="center" prop="realName" />
+                <el-table-column label="收货人电话" align="center" prop="phone" />
+                <el-table-column label="地址" align="center" prop="detail" >
+                    <template slot-scope="scope">
+                       {{scope.row.province}} {{scope.row.city}} {{scope.row.district}} {{scope.row.detail}}
+                    </template>
+                </el-table-column>
+              </el-table>
+              </el-radio-group>
+            </el-form-item>
+            <el-form-item label="商品列表" >
+              <el-row  >
+                <el-col >
+                      <el-button plain  type="primary" icon="el-icon-plus" @click="handleAddProduct">添加商品</el-button>
+                </el-col>
+              </el-row>
+              <el-table border :key = "tablekey" width="100%" style="margin-top:5px;"  :data="products">
+                <el-table-column label="商品编号" align="center" prop="barCode" />
+                <el-table-column label="商品图片" align="center" width="100">
+                  <template slot-scope="scope">
+                    <el-popover
+                      placement="right"
+                      title=""
+                      trigger="hover"
+                    >
+                      <img slot="reference" :src="scope.row.image" width="50">
+                      <img :src="scope.row.image" style="max-width: 50px;">
+                    </el-popover>
+                  </template>
+                </el-table-column>
+                <el-table-column label="商品名称" show-overflow-tooltip align="center" prop="productName" />
+                <el-table-column label="商品规格" align="center" prop="sku" />
+                <el-table-column label="库存" align="center" prop="stock" />
+                <el-table-column label="单价" align="center" prop="price" />
+                <el-table-column label="数量" align="center"  prop="count" width="200px" :key="tablekey">
+                   <template slot-scope="scope">
+                    <div>
+                        <el-input-number v-model="scope.row.count"  @change="handleProductCountChange(scope.row)"  size="mini" :min="1" :max="scope.row.stock"  ></el-input-number>
+                    </div>
+                  </template>
+                </el-table-column>
+                <el-table-column label="小计" align="center" prop="money"   />
+                <el-table-column label="操作" align="center" width="100px" >
+                  <template slot-scope="scope">
+                    <el-button
+                      size="mini"
+                      type="text"
+                      icon="el-icon-delete"
+                      @click="handleDelete(scope.row)"
+                    >删除</el-button>
+                  </template>
+                </el-table-column>
+              </el-table>
+              <el-row>
+                <el-col>
+                      <span>商品合计:{{products.length}}</span><span style="margin-left:10px;">商品总价:{{totalMoney.toFixed(2)}}</span>
+                </el-col>
+              </el-row>
+            </el-form-item>
+            <el-form-item label="支付方式" prop="payType">
+              <el-select   v-model="form.payType" placeholder="请选择支付方式" clearable size="small" >
+              <el-option
+                      v-for="item in payTypeOptions"
+                      :key="item.dictValue"
+                      :label="item.dictLabel"
+                      :value="item.dictValue"
+                    />
+              </el-select>
+            </el-form-item>
+            <el-form-item label="改价" prop="payPrice">
+              <el-input-number  v-model="form.payPrice" placeholder="修改商品总价" size="medium" :precision="2" :min=0.01 :step="0.1" />
+            </el-form-item>
+            <el-form-item label="物流代收" prop="amount" v-if="form.payType == '3'">
+              <el-input-number  v-model="form.amount" placeholder="平台支付价格" size="medium" :precision="2" :min=0.01 :step="0.1" />
+            </el-form-item>
+            <el-form-item label="订单备注" prop="mark">
+              <el-input  type="textarea" rows="2" v-model="form.mark" placeholder="" />
+            </el-form-item>
+        </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">确 定</el-button>
+        <el-button @click="cancel">取 消</el-button>
+      </div>
+    </el-dialog>
+    <el-dialog :title="product.title" v-if="product.open"  :visible.sync="product.open" width="1000px" append-to-body>
+        <product-select  @selectProduct="selectProduct" />
+    </el-dialog>
+    <el-dialog :title="user.title" v-if="user.open"  :visible.sync="user.open" width="500px" append-to-body>
+        <add-user @addUser="addUser" />
+    </el-dialog>
+    <el-dialog :title="userAddress.title" v-if="userAddress.open"  :visible.sync="userAddress.open" width="800px" append-to-body>
+        <add-user-address ref="addUserAddress"   @addUserAddress="addUserAddress" />
+    </el-dialog>
+    <el-dialog :title="payQr.title" v-if="payQr.open"  :visible.sync="payQr.open" width="240px" append-to-body>
+        <div style="padding-bottom:15px;" >
+            <div  class="qrcode" ref="qrCodeUrl"></div>
+        </div>
+    </el-dialog>
+
+  </div>
+</template>
+
+<script>
+import {exportStoreOrderItems, createUserOrder,listStoreOrder, getStoreOrder, delStoreOrder, addStoreOrder, updateStoreOrder, exportStoreOrder } from "@/api/hisStore/storeOrder";
+import { getUserList } from "@/api/users/user";
+import { getAddressList } from "@/api/users/userAddress";
+import { getTcmScheduleList } from "@/api/company/tcmScheduleReport";
+import productOrder from "../components/productOrder";
+import productSelect from "../components/productSelect";
+import addUser from "../components/addUser";
+import addUserAddress from "../components/addUserAddress";
+import config from "@/utils/config";
+import QRCode from 'qrcodejs2'
+import { treeselect } from "@/api/company/companyDept";
+import Treeselect from "@riophae/vue-treeselect";
+import "@riophae/vue-treeselect/dist/vue-treeselect.css";
+export default {
+  components: { Treeselect,productOrder,productSelect,addUser,addUserAddress },
+  name: "StoreOrder",
+  data() {
+    return {
+      // 部门树选项
+      deptOptions: undefined,
+      // 是否显示弹出层
+      // 部门名称
+      deptName: undefined,
+      defaultProps: {
+        children: "children",
+        label: "label",
+      },
+      deliveryPayStatusOptions:[],
+      deliveryStatusOptions:[],
+      dateRange: [],
+      orderMediumOptions:[],
+      orderTypeOptions:[],
+      payTypeOptions:[],
+      payQr:{
+        open:false,
+        title:"付款二维码"
+      },
+      user:{
+        open:false,
+        title:"创建会员"
+      },
+      userAddress:{
+        open:false,
+        title:"创建收货地址"
+      },
+      tablekey:false,
+      totalMoney:0.00,
+      phone:null,
+      products:[],
+      product:{
+        open:false,
+        title:"商品选择"
+      },
+
+      address:[],
+      addressloading: false,
+      userloading: false,
+      users:[],
+      userStatusOptions:[],
+      show:{
+        open:false,
+        title:"订单详情"
+      },
+      activeName:"00",
+      statusOptions:[],
+      // 遮罩层
+      loading: true,
+      // 选中数组
+      ids: [],
+      // 非单个禁用
+      single: true,
+      // 非多个禁用
+      multiple: true,
+
+      // 显示搜索条件
+      showSearch: true,
+      // 总条数
+      total: 0,
+      // 订单表格数据
+      storeOrderList: [],
+      // 弹出层标题
+      title: "",
+      // 是否显示弹出层
+      open: false,
+      createTimeRange:[],
+      payTimeRange:[],
+      deliveryImportTimeRange:[],
+      scheduleOptions:[],
+      // 查询参数
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        orderCode: null,
+        extendOrderId: null,
+        userId: null,
+        realName: null,
+        userPhone: null,
+        userAddress: null,
+        cartId: null,
+        freightPrice: null,
+        totalNum: null,
+        totalPrice: null,
+        totalPostage: null,
+        payPrice: null,
+        payPostage: null,
+        deductionPrice: null,
+        couponId: null,
+        couponPrice: null,
+        paid: null,
+        payTime: null,
+        payType: null,
+        status: null,
+        refundStatus: null,
+        refundReasonWapImg: null,
+        refundReasonWapExplain: null,
+        refundReasonTime: null,
+        refundReasonWap: null,
+        refundReason: null,
+        refundPrice: null,
+        deliverySn: null,
+        deliveryName: null,
+        deliveryType: null,
+        deliveryId: null,
+        gainIntegral: null,
+        useIntegral: null,
+        payIntegral: null,
+        backIntegral: null,
+        mark: null,
+        isDel: null,
+        cost: null,
+        verifyCode: null,
+        storeId: null,
+        shippingType: null,
+        isChannel: null,
+        isRemind: null,
+        isSysDel: null
+      },
+      // 表单参数
+      form: {
+        addressId:null,
+        userId:null,
+        products:[],
+      },
+      // 表单校验
+      rules: {
+        userId: [
+          { required: true, message: "会员信息不能为空" }
+        ],
+        addressId: [
+          { required: true, message: "收货信息不能为空" }
+        ],
+        products: [
+          { required: true, message: "商品不能为空" }
+        ],
+
+      }
+    };
+  },
+  watch: {
+    // 根据名称筛选部门树
+    deptName(val) {
+        this.$refs.tree.filter(val);
+      },
+  },
+  created() {
+    this.getTreeselect();
+    this.getDicts("crm_customer_source").then((response) => {
+      this.orderMediumOptions = response.data;
+    });
+    this.getDicts("store_order_type").then((response) => {
+      this.orderTypeOptions = response.data;
+    });
+    this.getDicts("store_pay_type").then((response) => {
+      this.payTypeOptions = response.data;
+    });
+    this.getDicts("user_status").then((response) => {
+      this.userStatusOptions = response.data;
+    });
+    this.getDicts("store_order_status").then((response) => {
+      this.statusOptions = response.data;
+    });
+    this.getDicts("store_order_delivery_status").then((response) => {
+      this.deliveryStatusOptions = response.data;
+    });
+    this.getDicts("store_delivery_pay_status").then((response) => {
+      this.deliveryPayStatusOptions = response.data;
+    });
+    getTcmScheduleList().then(response => {
+      this.scheduleOptions = response.data;
+    });
+    this.getList();
+  },
+  methods: {
+     /** 查询部门下拉树结构 */
+     getTreeselect() {
+      treeselect().then((response) => {
+        this.deptOptions = response.data;
+      });
+    },
+    // 筛选节点
+    filterNode(value, data) {
+      if (!value) return true;
+      return data.label.indexOf(value) !== -1;
+    },
+    // 节点单击事件
+    handleNodeClick(data) {
+      this.queryParams.deptId = data.id;
+      this.getList();
+    },
+    handleGenPayUrl(row){
+      this.payQr.open=true;
+      setTimeout(() => {
+        var qrcode = new QRCode(this.$refs.qrCodeUrl, {
+            text: config.payQRUrl+row.id, // 需要转换为二维码的内容
+            width: 200,
+            height: 200,
+            colorDark: '#000000',
+            colorLight: '#ffffff',
+            correctLevel: QRCode.CorrectLevel.H
+        })
+      }, 200);
+
+
+    },
+    handleAddUser(){
+      this.user.open=true;
+    },
+    handleAddUserAddress(){
+      if(this.form.userId==null){
+        this.msgError("请选择会员");
+        return;
+      }
+      this.userAddress.open=true;
+      setTimeout(() => {
+        this.$refs.addUserAddress.init(this.form.userId);
+      }, 500);
+    },
+    addUserAddress(){
+      this.userAddress.open=false;
+      //获取地址
+      this.getAddressList(this.form.userId);
+    },
+    addUser(){
+      this.user.open=false;
+    },
+
+    compute(){
+      this.totalMoney=0;
+      var that=this;
+      this.products.forEach (function (value) {
+          that.totalMoney += value.money;
+      });
+    },
+    handleProductCountChange(row){
+      this.tablekey = !this.tablekey
+      row.money=row.count*row.price;
+      this.$forceUpdate();
+      this.compute();
+    },
+    selectProduct(row){
+      for(var i=0;i<this.products.length;i++){
+        if(this.products[i].id==row.id){
+          return;
+        }
+      }
+      row.count=1;
+      row.money=row.count*row.price;
+      this.products.push(row);
+      this.$message.success("商品"+ row.productName + "添加成功")
+      this.compute();
+    },
+    handleAddProduct(){
+      this.product.open=true;
+    },
+    searchUser(){
+      if(this.phone==null||this.phone==""){
+        return;
+      }
+      var data={phone:this.phone}
+      this.userloading = true;
+      this.users=[];
+      this.address=[];
+      getUserList(data).then(response => {
+        this.users = response.data;
+        this.userloading = false;
+        if(this.users!=null&&this.users.length==1){
+          this.form.userId=this.users[0].userId;
+          this.getAddressList(this.form.userId)
+        }
+      });
+    },
+    getAddressList(userId){
+      var data={userId:userId}
+      this.addressloading = true;
+      this.address=[];
+      getAddressList(data).then(response => {
+        this.address = response.data;
+        this.addressloading = false;
+      });
+    },
+    handleDetails(row){
+      this.show.open=true;
+      const orderId = row.id ;
+      setTimeout(() => {
+        this.$refs.order.getOrder(orderId);
+      }, 500);
+    },
+    handleClick(tab, event) {
+       if(tab.name=="all"){
+        this.queryParams.status==null;
+      }
+      else{
+         this.queryParams.status=tab.name;
+      }
+      this.getList();
+    },
+    /** 查询订单列表 */
+    getList() {
+      if(this.queryParams.status=='00'){
+        this.queryParams.status=null;
+      }
+      if(this.createTimeRange!=null&&this.createTimeRange.length==2){
+        this.queryParams.createTimeRange=this.createTimeRange[0]+"--"+this.createTimeRange[1]
+      }
+      else{
+        this.queryParams.createTimeRange=null;
+      }
+      if(this.payTimeRange!=null&&this.payTimeRange.length==2){
+        this.queryParams.payTimeRange=this.payTimeRange[0]+"--"+this.payTimeRange[1]
+      }
+      else{
+        this.queryParams.payTimeRange=null;
+      }
+      if(this.deliveryImportTimeRange!=null&&this.deliveryImportTimeRange.length==2){
+        this.queryParams.deliveryImportTimeRange=this.deliveryImportTimeRange[0]+"--"+this.deliveryImportTimeRange[1]
+      }
+      else{
+        this.queryParams.deliveryImportTimeRange=null;
+      }
+      this.loading = true;
+      listStoreOrder(this.addDateRange(this.queryParams, this.dateRange)).then(response => {
+        this.storeOrderList = response.rows;
+        this.total = response.total;
+        this.loading = false;
+      });
+    },
+    // 取消按钮
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 表单重置
+    reset() {
+      this.form = {
+        addressId:null,
+        userId:null,
+        products:null,
+
+      };
+      this.resetForm("form");
+    },
+    /** 搜索按钮操作 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 重置按钮操作 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    // 多选框选中数据
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.id)
+      this.single = selection.length!==1
+      this.multiple = !selection.length
+    },
+    /** 新增按钮操作 */
+    handleAdd() {
+      this.reset();
+      this.open = true;
+      this.title = "创建订单";
+    },
+    /** 修改按钮操作 */
+    handleUpdate(row) {
+      this.reset();
+      const id = row.id || this.ids
+      getStoreOrder(id).then(response => {
+        this.form = response.data;
+        this.open = true;
+        this.title = "修改订单";
+      });
+    },
+    /** 提交按钮 */
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        if(this.products.length==0){
+          this.msgError("请选择商品");
+          return;
+        }
+        this.form.products=this.products;
+        if (valid) {
+          createUserOrder(this.form).then(response => {
+            if (response.code === 200) {
+              this.msgSuccess("创建成功");
+              this.open = false;
+              this.getList();
+            }
+          });
+
+        }
+      });
+    },
+    /** 删除按钮操作 */
+    handleDelete(row) {
+       this.products.splice(this.products.findIndex(item => item.id === row.id), 1)
+       this.compute();
+
+    },
+    /** 导出按钮操作 */
+    handleExport() {
+
+      if(this.queryParams.status=='00'){
+        this.queryParams.status=null;
+      }
+      if(this.createTimeRange!=null&&this.createTimeRange.length==2){
+        this.queryParams.createTimeRange=this.createTimeRange[0]+"--"+this.createTimeRange[1]
+      }
+      else{
+        this.queryParams.createTimeRange=null;
+      }
+      if(this.payTimeRange!=null&&this.payTimeRange.length==2){
+        this.queryParams.payTimeRange=this.payTimeRange[0]+"--"+this.payTimeRange[1]
+      }
+      else{
+        this.queryParams.payTimeRange=null;
+      }
+      if(this.deliveryImportTimeRange!=null&&this.deliveryImportTimeRange.length==2){
+        this.queryParams.deliveryImportTimeRange=this.deliveryImportTimeRange[0]+"--"+this.deliveryImportTimeRange[1]
+      }
+      else{
+        this.queryParams.deliveryImportTimeRange=null;
+      }
+
+      const queryParams = this.addDateRange(this.queryParams, this.dateRange);
+      this.$confirm('是否确认导出所有订单数据项?', "警告", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        }).then(function() {
+          return exportStoreOrder(queryParams);
+        }).then(response => {
+          this.download(response.msg);
+        }).catch(function() {});
+    },
+    handleExportItems() {
+      if(this.queryParams.status=='00'){
+        this.queryParams.status=null;
+      }
+      if(this.createTimeRange!=null&&this.createTimeRange.length==2){
+        this.queryParams.createTimeRange=this.createTimeRange[0]+"--"+this.createTimeRange[1]
+      }
+      else{
+        this.queryParams.createTimeRange=null;
+      }
+      if(this.payTimeRange!=null&&this.payTimeRange.length==2){
+        this.queryParams.payTimeRange=this.payTimeRange[0]+"--"+this.payTimeRange[1]
+      }
+      else{
+        this.queryParams.payTimeRange=null;
+      }
+      if(this.deliveryImportTimeRange!=null&&this.deliveryImportTimeRange.length==2){
+        this.queryParams.deliveryImportTimeRange=this.deliveryImportTimeRange[0]+"--"+this.deliveryImportTimeRange[1]
+      }
+      else{
+        this.queryParams.deliveryImportTimeRange=null;
+      }
+      const queryParams = this.addDateRange(this.queryParams, this.dateRange);
+      this.$confirm('是否确认导出所有订单明细数据项?', "警告", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        }).then(function() {
+          return exportStoreOrderItems(queryParams);
+        }).then(response => {
+          this.download(response.msg);
+        }).catch(function() {});
+    }
+  }
+};
+</script>
+<style scoped lang="scss">
+.items{
+  margin: 5px 0px;
+  display: flex;
+  flex-direction: row;
+  align-items: center;
+  justify-content: flex-start;
+  .pic{
+    width:60px;
+    height:60px;
+  }
+  .goods-content{
+    margin-left: 10px;
+    max-width: 200px;
+    text-align: left;
+    .goods-title{
+
+      overflow:hidden;
+      white-space: nowrap;
+      text-overflow: ellipsis;
+      -o-text-overflow:ellipsis;
+    }
+  }
+}
+.el-message-box__message p{
+  max-height: 400px;
+  overflow:scroll;
+}
+.import-msg{
+  height: 500px;
+  overflow: auto;
+}
+</style>
+<style>
+  .el-descriptions-item__label.is-bordered-label{
+    font-weight: normal;
+  }
+
+</style>

+ 722 - 0
src/views/hisStore/storeOrder/myList.vue

@@ -0,0 +1,722 @@
+<template>
+  <div class="app-container">
+    <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
+      <el-form-item label="订单号" prop="orderCode">
+        <el-input
+        style="width:220px"
+          v-model="queryParams.orderCode"
+          placeholder="请输入订单号"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+       <el-form-item label="运单号" prop="deliveryId">
+        <el-input
+        style="width:220px"
+          v-model="queryParams.deliveryId"
+          placeholder="请输入运单号"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="收件人" prop="realName">
+            <el-input
+            style="width:220px"
+              v-model="queryParams.realName"
+              placeholder="请输入收件人"
+              clearable
+              size="small"
+              @keyup.enter.native="handleQuery"
+            />
+          </el-form-item>
+          <el-form-item label="手机号" prop="userPhone">
+            <el-input
+            style="width:220px"
+              v-model="queryParams.userPhone"
+              placeholder="请输入收件人手机号"
+              clearable
+              size="small"
+              @keyup.enter.native="handleQuery"
+            />
+          </el-form-item>
+       <el-form-item label="订单类型" prop="orderType">
+         <el-select style="width:220px"  v-model="queryParams.orderType" placeholder="请选择订单类型" clearable size="small" >
+         <el-option
+                v-for="item in orderTypeOptions"
+                :key="item.dictValue"
+                :label="item.dictLabel"
+                :value="item.dictValue"
+              />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="上传凭证" prop="isUpload">
+         <el-select   v-model="queryParams.isUpload" placeholder="请选择" clearable size="small" >
+          <el-option key="0"  label="未上传" value="0" />
+             <el-option key="1"  label="已上传" value="1" />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="物流状态" prop="deliveryStatus">
+         <el-select style="width:220px" v-model="queryParams.deliveryStatus" placeholder="请选择物流状态" clearable size="small" >
+         <el-option
+                v-for="item in deliveryStatusOptions"
+                :key="item.dictValue"
+                :label="item.dictLabel"
+                :value="item.dictValue"
+              />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="结算状态" prop="deliveryPayStatus">
+         <el-select style="width:220px" v-model="queryParams.deliveryPayStatus" placeholder="请选择物流结算状态" clearable size="small" >
+         <el-option
+                v-for="item in deliveryPayStatusOptions"
+                :key="item.dictValue"
+                :label="item.dictLabel"
+                :value="item.dictValue"
+              />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="下单时间" prop="createTimeRange">
+        <el-date-picker
+        style="width:220px"
+          clearable size="small"
+          v-model="createTimeRange"
+          type="daterange"
+          value-format="yyyy-MM-dd"
+          start-placeholder="开始日期"
+          end-placeholder="结束日期">
+        </el-date-picker>
+      </el-form-item>
+      <el-form-item label="支付时间" prop="payTimeRange">
+        <el-date-picker
+        style="width:220px"
+          clearable size="small"
+          v-model="payTimeRange"
+          type="daterange"
+          value-format="yyyy-MM-dd"
+          start-placeholder="开始日期"
+          end-placeholder="结束日期">
+        </el-date-picker>
+      </el-form-item>
+      <el-form-item label="回单时间" prop="deliveryImportTimeRange">
+        <el-date-picker
+        style="width:220px"
+          clearable size="small"
+          v-model="deliveryImportTimeRange"
+          type="daterange"
+          value-format="yyyy-MM-dd"
+          start-placeholder="开始日期"
+          end-placeholder="结束日期">
+        </el-date-picker>
+      </el-form-item>
+      <el-form-item>
+        <el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
+      </el-form-item>
+    </el-form>
+    <el-row :gutter="10" class="mb8">
+      <el-col :span="1.5">
+        <el-button
+            type="warning"
+          icon="el-icon-download"
+          size="mini"
+            @click="handleExport"
+          v-hasPermi="['store:storeOrder:export']"
+        >导出订单</el-button>
+      </el-col>
+       <el-col :span="1.5">
+        <el-button
+            type="warning"
+          icon="el-icon-download"
+          size="mini"
+            @click="handleExportItems"
+          v-hasPermi="['store:storeOrder:exportItems']"
+        >导出订单明细</el-button>
+      </el-col>
+	  <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+    <el-tabs type="card" v-model="activeName" @tab-click="handleClick">
+      <el-tab-pane label="全部订单" name="00"></el-tab-pane>
+      <el-tab-pane label="待支付" name="0"></el-tab-pane>
+      <el-tab-pane label="待发货" name="1"></el-tab-pane>
+      <el-tab-pane label="待收货" name="2"></el-tab-pane>
+      <el-tab-pane label="交易完成" name="3"></el-tab-pane>
+      <el-tab-pane label="退款中" name="-1"></el-tab-pane>
+      <el-tab-pane label="已退款" name="-2"></el-tab-pane>
+      <el-tab-pane label="已取消" name="-3"></el-tab-pane>
+    </el-tabs>
+    <el-table height="500" border v-loading="loading" :data="storeOrderList" @selection-change="handleSelectionChange">
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="订单号" align="center" prop="orderCode" />
+      <el-table-column label="所属公司" align="center" prop="companyName" />
+      <el-table-column label="所属员工" align="center" prop="companyUserNickName" />
+      <el-table-column label="用户昵称" align="center" prop="nickname" width="150px" >
+          <template slot-scope="scope">
+              <span>{{scope.row.nickname}}</span>
+          </template>
+      </el-table-column>
+      <el-table-column label="收件人" align="center" prop="realName" width="150px" >
+          <template slot-scope="scope">
+              <span>{{scope.row.realName}} </span>
+          </template>
+      </el-table-column>
+      <!-- <el-table-column label="商品" align="center" width="300px" >
+          <template slot-scope="scope">
+              <div  v-for="(item, index) in scope.row.items" class="items"  >
+                <img class="pic" :src="JSON.parse(item.jsonInfo).image" />
+                <div class="goods-content">
+                  <div class="goods-title">{{ JSON.parse(item.jsonInfo).productName}}</div>
+                  <div class="sku">{{ JSON.parse(item.jsonInfo).sku}}</div>
+                  <div class="price">¥{{JSON.parse(item.jsonInfo).price}}×{{item.num}}</div>
+                </div>
+
+              </div>
+          </template>
+      </el-table-column> -->
+      <el-table-column label="订单金额" align="center" prop="totalPrice" >
+          <template slot-scope="scope">
+              <span v-if="scope.row.totalPrice!=null">{{scope.row.totalPrice.toFixed(2)}}</span>
+          </template>
+      </el-table-column>
+       <el-table-column label="应付金额" align="center" prop="payPrice" >
+          <template slot-scope="scope">
+              <span v-if="scope.row.payPrice!=null">{{scope.row.payPrice.toFixed(2)}}</span>
+          </template>
+      </el-table-column>
+      <el-table-column label="下单时间" align="center" prop="createTime" />
+      <!-- <el-table-column label="支付状态" align="center" prop="paid" /> -->
+      <el-table-column label="支付时间" align="center" prop="payTime" width="180">
+      </el-table-column>
+      <el-table-column label="支付方式" align="center" prop="payType" >
+          <template slot-scope="scope">
+              <span prop="payType" v-for="(item, index) in payTypeOptions"    v-if="scope.row.payType==item.dictValue">{{item.dictLabel}}</span>
+          </template>
+      </el-table-column>
+      <el-table-column label="订单类型" align="center" prop="orderType" >
+          <template slot-scope="scope">
+              <el-tag prop="status" v-for="(item, index) in orderTypeOptions"    v-if="scope.row.orderType==item.dictValue">{{item.dictLabel}}</el-tag>
+          </template>
+      </el-table-column>
+      <el-table-column label="状态" align="center" prop="status" >
+          <template slot-scope="scope">
+              <el-tag prop="status" v-for="(item, index) in statusOptions"    v-if="scope.row.status==item.dictValue">{{item.dictLabel}}</el-tag>
+          </template>
+      </el-table-column>
+      <el-table-column label="物流状态" align="center" prop="deliveryStatus" >
+          <template slot-scope="scope">
+              <el-tag prop="status" v-for="(item, index) in deliveryStatusOptions"    v-if="scope.row.deliveryStatus==item.dictValue">{{item.dictLabel}}</el-tag>
+          </template>
+      </el-table-column>
+      <el-table-column label="物流结算状态" align="center" prop="deliveryPayStatus" >
+          <template slot-scope="scope">
+              <el-tag prop="status" v-for="(item, index) in deliveryPayStatusOptions"    v-if="scope.row.deliveryPayStatus==item.dictValue">{{item.dictLabel}}</el-tag>
+          </template>
+      </el-table-column>
+      <el-table-column label="操作" fixed="right" width="100px" align="center" class-name="small-padding fixed-width">
+        <template slot-scope="scope">
+          <el-button
+            size="mini"
+            type="text"
+            @click="handleDetails(scope.row)"
+            v-hasPermi="['store:storeOrder:query']"
+          >查看</el-button>
+          <!-- <el-button
+            size="mini"
+            type="text"
+            @click="handleGenPayUrl(scope.row)"
+            v-hasPermi="['store:storeOrder:genPayUrl']"
+          >生成付款链接</el-button> -->
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <pagination
+      v-show="total>0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    />
+    <el-drawer
+     size="75%"
+      :title="show.title" :visible.sync="show.open"
+      >
+      <product-order  ref="order" />
+    </el-drawer>
+  </div>
+</template>
+
+<script>
+import {myListStoreOrder,exportStoreOrderItems, createUserOrder,listStoreOrder, getStoreOrder, delStoreOrder, addStoreOrder, updateStoreOrder, exportStoreOrder } from "@/api/hisStore/storeOrder";
+import { getUserList } from "@/api/users/user";
+import { getAddressList } from "@/api/users/userAddress";
+
+import productOrder from "../components/productOrder";
+import productSelect from "../components/productSelect";
+import addUser from "../components/addUser";
+import addUserAddress from "../components/addUserAddress";
+import config from "@/utils/config";
+import QRCode from 'qrcodejs2'
+export default {
+  components: { productOrder,productSelect,addUser,addUserAddress },
+  name: "StoreOrder",
+  data() {
+    return {
+      deliveryPayStatusOptions:[],
+      deliveryStatusOptions:[],
+      dateRange: [],
+      orderTypeOptions:[],
+      payTypeOptions:[],
+      payQr:{
+        open:false,
+        title:"付款二维码"
+      },
+      user:{
+        open:false,
+        title:"创建会员"
+      },
+      userAddress:{
+        open:false,
+        title:"创建收货地址"
+      },
+      tablekey:false,
+      totalMoney:0.00,
+      products:[],
+      product:{
+        open:false,
+        title:"商品选择"
+      },
+      userStatusOptions:[],
+      phone:null,
+      address:[],
+      addressloading: false,
+      userloading: false,
+      users:[],
+      userStatusOptions:[],
+      show:{
+        open:false,
+        title:"订单详情"
+      },
+      activeName:"00",
+      statusOptions:[],
+      // 遮罩层
+      loading: true,
+      // 选中数组
+      ids: [],
+      // 非单个禁用
+      single: true,
+      // 非多个禁用
+      multiple: true,
+
+      // 显示搜索条件
+      showSearch: true,
+      // 总条数
+      total: 0,
+      // 订单表格数据
+      storeOrderList: [],
+      // 弹出层标题
+      title: "",
+      // 是否显示弹出层
+      open: false,
+      createTimeRange:[],
+      payTimeRange:[],
+      deliveryImportTimeRange:[],
+      // 查询参数
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        orderCode: null,
+        extendOrderId: null,
+        userId: null,
+        realName: null,
+        userPhone: null,
+        userAddress: null,
+        cartId: null,
+        freightPrice: null,
+        totalNum: null,
+        totalPrice: null,
+        totalPostage: null,
+        payPrice: null,
+        payPostage: null,
+        deductionPrice: null,
+        couponId: null,
+        couponPrice: null,
+        paid: null,
+        payTime: null,
+        payType: null,
+        status: null,
+        refundStatus: null,
+        refundReasonWapImg: null,
+        refundReasonWapExplain: null,
+        refundReasonTime: null,
+        refundReasonWap: null,
+        refundReason: null,
+        refundPrice: null,
+        deliverySn: null,
+        deliveryName: null,
+        deliveryType: null,
+        deliveryId: null,
+        gainIntegral: null,
+        useIntegral: null,
+        payIntegral: null,
+        backIntegral: null,
+        mark: null,
+        isDel: null,
+        cost: null,
+        verifyCode: null,
+        storeId: null,
+        shippingType: null,
+        isChannel: null,
+        isRemind: null,
+        isSysDel: null
+      },
+      // 表单参数
+      form: {
+        addressId:null,
+        userId:null,
+        products:[],
+      },
+      // 表单校验
+      rules: {
+        userId: [
+          { required: true, message: "会员信息不能为空" }
+        ],
+        addressId: [
+          { required: true, message: "收货信息不能为空" }
+        ],
+        products: [
+          { required: true, message: "商品不能为空" }
+        ],
+
+      }
+    };
+  },
+  created() {
+     this.getDicts("store_order_type").then((response) => {
+      this.orderTypeOptions = response.data;
+    });
+    this.getDicts("store_pay_type").then((response) => {
+      this.payTypeOptions = response.data;
+    });
+    this.getDicts("user_status").then((response) => {
+      this.userStatusOptions = response.data;
+    });
+    this.getDicts("store_order_status").then((response) => {
+      this.statusOptions = response.data;
+    });
+    this.getDicts("store_order_delivery_status").then((response) => {
+      this.deliveryStatusOptions = response.data;
+    });
+    this.getDicts("store_delivery_pay_status").then((response) => {
+      this.deliveryPayStatusOptions = response.data;
+    });
+
+    this.getList();
+  },
+  methods: {
+    handleGenPayUrl(row){
+      this.payQr.open=true;
+      setTimeout(() => {
+        var qrcode = new QRCode(this.$refs.qrCodeUrl, {
+            text: config.payQRUrl+row.id, // 需要转换为二维码的内容
+            width: 200,
+            height: 200,
+            colorDark: '#000000',
+            colorLight: '#ffffff',
+            correctLevel: QRCode.CorrectLevel.H
+        })
+      }, 200);
+
+
+    },
+    handleAddUser(){
+      this.user.open=true;
+    },
+    handleAddUserAddress(){
+      if(this.form.userId==null){
+        this.msgError("请选择会员");
+        return;
+      }
+      this.userAddress.open=true;
+      setTimeout(() => {
+        this.$refs.addUserAddress.init(this.form.userId);
+      }, 500);
+    },
+    addUser(){
+      this.user.open=false;
+    },
+    addUserAddress(){
+      this.userAddress.open=false;
+      //获取地址
+      this.getAddressList(this.form.userId);
+    },
+    compute(){
+      this.totalMoney=0;
+      var that=this;
+      this.products.forEach (function (value) {
+          that.totalMoney += value.money;
+      });
+    },
+    handleProductCountChange(row){
+      this.tablekey = !this.tablekey
+      row.money=row.count*row.price;
+      this.$forceUpdate();
+      this.compute();
+    },
+    selectProduct(row){
+      for(var i=0;i<this.products.length;i++){
+        if(this.products[i].id==row.id){
+          return;
+        }
+      }
+      row.count=1;
+      row.money=row.count*row.price;
+      this.products.push(row);
+      this.compute();
+    },
+    handleAddProduct(){
+      this.product.open=true;
+    },
+    searchUser(){
+      if(this.phone==null||this.phone==""){
+        return;
+      }
+      var data={phone:this.phone}
+      this.userloading = true;
+      this.users=[];
+      this.address=[];
+      getUserList(data).then(response => {
+        this.users = response.data;
+        this.userloading = false;
+        if(this.users!=null&&this.users.length==1){
+          this.form.userId=this.users[0].userId;
+          this.getAddressList(this.form.userId)
+        }
+      });
+    },
+    getAddressList(userId){
+      var data={userId:userId}
+      this.addressloading = true;
+      this.address=[];
+      getAddressList(data).then(response => {
+        this.address = response.data;
+        this.addressloading = false;
+      });
+    },
+    handleDetails(row){
+      this.show.open=true;
+      const orderId = row.id ;
+      setTimeout(() => {
+        this.$refs.order.getOrder(orderId);
+      }, 500);
+    },
+    handleClick(tab, event) {
+       if(tab.name=="all"){
+        this.queryParams.status==null;
+      }
+      else{
+         this.queryParams.status=tab.name;
+      }
+      this.getList();
+    },
+    /** 查询订单列表 */
+    getList() {
+      if(this.queryParams.status=='00'){
+        this.queryParams.status=null;
+      }
+      if(this.createTimeRange!=null&&this.createTimeRange.length==2){
+        this.queryParams.createTimeRange=this.createTimeRange[0]+"--"+this.createTimeRange[1]
+      }
+      else{
+        this.queryParams.createTimeRange=null;
+      }
+      if(this.payTimeRange!=null&this.payTimeRange.length==2){
+        this.queryParams.payTimeRange=this.payTimeRange[0]+"--"+this.payTimeRange[1]
+      }
+      else{
+        this.queryParams.payTimeRange=null;
+      }
+      if(this.deliveryImportTimeRange!=null&&this.deliveryImportTimeRange.length==2){
+        this.queryParams.deliveryImportTimeRange=this.deliveryImportTimeRange[0]+"--"+this.deliveryImportTimeRange[1]
+      }
+      else{
+        this.queryParams.deliveryImportTimeRange=null;
+      }
+      this.loading = true;
+      myListStoreOrder(this.addDateRange(this.queryParams, this.dateRange)).then(response => {
+        this.storeOrderList = response.rows;
+        this.total = response.total;
+        this.loading = false;
+      });
+    },
+    // 取消按钮
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 表单重置
+    reset() {
+      this.form = {
+        addressId:null,
+        userId:null,
+        products:null,
+
+      };
+      this.resetForm("form");
+    },
+    /** 搜索按钮操作 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 重置按钮操作 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    // 多选框选中数据
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.id)
+      this.single = selection.length!==1
+      this.multiple = !selection.length
+    },
+    /** 新增按钮操作 */
+    handleAdd() {
+      this.reset();
+      this.open = true;
+      this.title = "创建订单";
+    },
+    /** 修改按钮操作 */
+    handleUpdate(row) {
+      this.reset();
+      const id = row.id || this.ids
+      getStoreOrder(id).then(response => {
+        this.form = response.data;
+        this.open = true;
+        this.title = "修改订单";
+      });
+    },
+    /** 提交按钮 */
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        if(this.products.length==0){
+          this.msgError("请选择商品");
+          return;
+        }
+        this.form.products=this.products;
+        if (valid) {
+          createUserOrder(this.form).then(response => {
+            if (response.code === 200) {
+              this.msgSuccess("创建成功");
+              this.open = false;
+              this.getList();
+            }
+          });
+
+        }
+      });
+    },
+    /** 删除按钮操作 */
+    handleDelete(row) {
+       this.products.splice(this.products.findIndex(item => item.id === row.id), 1)
+       this.compute();
+
+    },
+    /** 导出按钮操作 */
+    handleExport() {
+
+      if(this.queryParams.status=='00'){
+        this.queryParams.status=null;
+      }
+      if(this.createTimeRange!=null&&this.createTimeRange.length==2){
+        this.queryParams.createTimeRange=this.createTimeRange[0]+"--"+this.createTimeRange[1]
+      }
+      else{
+        this.queryParams.createTimeRange=null;
+      }
+      if(this.payTimeRange!=null&this.payTimeRange.length==2){
+        this.queryParams.payTimeRange=this.payTimeRange[0]+"--"+this.payTimeRange[1]
+      }
+      else{
+        this.queryParams.payTimeRange=null;
+      }
+      if(this.deliveryImportTimeRange!=null&&this.deliveryImportTimeRange.length==2){
+        this.queryParams.deliveryImportTimeRange=this.deliveryImportTimeRange[0]+"--"+this.deliveryImportTimeRange[1]
+      }
+      else{
+        this.queryParams.deliveryImportTimeRange=null;
+      }
+
+      const queryParams = this.addDateRange(this.queryParams, this.dateRange);
+      this.$confirm('是否确认导出所有订单数据项?', "警告", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        }).then(function() {
+          return exportStoreOrder(queryParams);
+        }).then(response => {
+          this.download(response.msg);
+        }).catch(function() {});
+    },
+    handleExportItems() {
+      if(this.queryParams.status=='00'){
+        this.queryParams.status=null;
+      }
+      if(this.createTimeRange!=null&&this.createTimeRange.length==2){
+        this.queryParams.createTimeRange=this.createTimeRange[0]+"--"+this.createTimeRange[1]
+      }
+      else{
+        this.queryParams.createTimeRange=null;
+      }
+      if(this.payTimeRange!=null&this.payTimeRange.length==2){
+        this.queryParams.payTimeRange=this.payTimeRange[0]+"--"+this.payTimeRange[1]
+      }
+      else{
+        this.queryParams.payTimeRange=null;
+      }
+      if(this.deliveryImportTimeRange!=null&&this.deliveryImportTimeRange.length==2){
+        this.queryParams.deliveryImportTimeRange=this.deliveryImportTimeRange[0]+"--"+this.deliveryImportTimeRange[1]
+      }
+      else{
+        this.queryParams.deliveryImportTimeRange=null;
+      }
+      const queryParams = this.addDateRange(this.queryParams, this.dateRange);
+      this.$confirm('是否确认导出所有订单明细数据项?', "警告", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        }).then(function() {
+          return exportStoreOrderItems(queryParams);
+        }).then(response => {
+          this.download(response.msg);
+        }).catch(function() {});
+    }
+  }
+};
+</script>
+<style scoped lang="scss">
+.items{
+  margin: 5px 0px;
+  display: flex;
+  flex-direction: row;
+  align-items: center;
+  justify-content: flex-start;
+  .pic{
+    width:60px;
+    height:60px;
+  }
+  .goods-content{
+    margin-left: 10px;
+    max-width: 200px;
+    text-align: left;
+    .goods-title{
+
+      overflow:hidden;
+      white-space: nowrap;
+      text-overflow: ellipsis;
+      -o-text-overflow:ellipsis;
+    }
+  }
+}
+</style>

+ 240 - 0
src/views/hisStore/storeOrderAudit/index.vue

@@ -0,0 +1,240 @@
+<template>
+  <div class="app-container">
+    <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
+      <el-form-item label="所属员工" prop="companyUserName">
+        <el-input
+          v-model="queryParams.companyUserName"
+          placeholder="请输入所属员工昵称"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item>
+        <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-tabs type="card" v-model="activeName" @tab-click="handleClick">
+      <el-tab-pane label="全部" name="00"></el-tab-pane>
+      <el-tab-pane label="待销售审批" name="0"></el-tab-pane>
+      <el-tab-pane label="销售审批拒绝" name="1"></el-tab-pane>
+      <el-tab-pane label="待总后台审核" name="2"></el-tab-pane>
+      <el-tab-pane label="总后台审核拒绝" name="3"></el-tab-pane>
+      <el-tab-pane label="审核通过" name="4"></el-tab-pane>
+    </el-tabs>
+    <el-table height="500" border v-loading="loading" :data="storeOrderAuditList" :key="tableKey">
+      <el-table-column label="订单号" align="center" prop="orderCode" width="200" />
+      <el-table-column label="所属公司" align="center" prop="companyName" />
+      <el-table-column label="所属员工" align="center" prop="companyUserName" />
+      <el-table-column label="审核状态" align="center" prop="status" >
+        <template slot-scope="scope">
+          <el-tag prop="status" v-for="item in statusOptions"
+                  :type="item.type"
+                  v-if="scope.row.auditStatus === item.dictValue">
+            {{item.dictLabel}}
+          </el-tag>
+        </template>
+      </el-table-column>
+      <el-table-column label="销售审核时间" align="center" prop="companyAuditTime" />
+      <el-table-column label="销售审核人" align="center" prop="companyAuditUserName" />
+      <el-table-column label="总后台审核时间" align="center" prop="adminAuditTime" />
+      <el-table-column label="总后台审核人" align="center" prop="adminAuditUserName" />
+      <el-table-column label="被拒原因" align="center" prop="reason" show-overflow-tooltip />
+      <el-table-column label="提交时间" align="center" prop="createTime" />
+      <el-table-column label="操作" fixed="right" align="center" width="80" class-name="small-padding fixed-width">
+        <template slot-scope="scope">
+          <el-popover
+            v-if="scope.row.auditStatus === 0"
+            placement="right"
+            trigger="click"
+            :ref="'popover_' + scope.row.id">
+            <el-button size="mini" type="success" @click="handlePass(scope.row)">通过</el-button>
+            <el-button size="mini" type="danger" @click="handleAudit(scope.row)">拒绝</el-button>
+            <el-button
+              slot="reference"
+              size="mini"
+              type="text"
+              v-hasPermi="['store:storeOrderAudit:audit']"
+            >审核订单</el-button>
+          </el-popover>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <pagination
+      v-show="total>0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    />
+
+    <el-dialog :title="show.title" :visible.sync="show.open" width="500px" append-to-body>
+      <el-form ref="auditForm" :model="auditForm" :rules="auditRules" label-width="80px">
+        <el-form-item label="拒绝原因" prop="reviewContent">
+          <el-input
+            type="textarea"
+            v-model="auditForm.reviewContent"
+            placeholder="请输入拒绝原因"
+          />
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="handleReject">确定</el-button>
+        <el-button @click="cancelAudit">关闭</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { getCompanyList } from "@/api/company/company";
+import {list, audit} from "@/api/hisStore/storeOrderAudit";
+
+export default {
+  name: "StoreOrderAudit",
+  data() {
+    const statusOptions = [
+      {
+        dictLabel: "待销售审批",
+        dictValue: 0,
+        type: ''
+      },
+      {
+        dictLabel: "销售审批拒绝",
+        dictValue: 1,
+        type: 'danger'
+      },
+      {
+        dictLabel: "待总后台审核",
+        dictValue: 2,
+        type: ''
+      },
+      {
+        dictLabel: "总后台审核拒绝",
+        dictValue: 3,
+        type: 'danger'
+      },
+      {
+        dictLabel: "审核通过",
+        dictValue: 4,
+        type: 'success'
+      }
+    ]
+
+    return {
+      tableKey: 0,
+      showSearch: true,
+      companys: [],
+      total: 0,
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        companyUserName: null,
+        auditStatus: null
+      },
+      activeName: '00',
+      loading: false,
+      storeOrderAuditList: [],
+      statusOptions: statusOptions,
+      show: {
+        open: false,
+        title: "审核订单"
+      },
+      auditForm: {
+        auditId: null,
+        reviewType: null,
+        reviewContent: ''
+      },
+      auditRules: {
+        reviewContent: [
+          { required: true, message: "请输入拒绝原因", trigger: "blur" }
+        ]
+      },
+      currentRowId: null,
+    }
+  },
+  created() {
+    this.getCompanyOptions()
+    this.handleQuery()
+  },
+  activated() {
+    this.tableKey = Date.now()
+  },
+  methods: {
+    getCompanyOptions() {
+      getCompanyList().then(response => {
+        this.companys = response.data
+      })
+    },
+    handleQuery() {
+      this.queryParams.pageNum = 1
+      this.getList()
+    },
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    getList() {
+      this.loading = true
+      list(this.queryParams).then(response => {
+        const {rows, total} = response
+        this.storeOrderAuditList = rows
+        this.total = total
+        this.loading = false
+      })
+    },
+    handleClick(tab) {
+      this.queryParams.auditStatus = tab.name === '00' ? null : tab.name
+      this.handleQuery()
+    },
+    handleAudit(row) {
+      this.currentRowId = row.id
+      this.auditForm.auditId = row.id;
+      this.auditForm.reviewType = 0;
+      this.show.open = true;
+    },
+    handlePass(row) {
+      this.currentRowId = row.id
+      this.auditForm.auditId = row.id;
+      this.auditForm.reviewType = 1;
+      this.submitAudit();
+    },
+    handleReject() {
+      this.$refs["auditForm"].validate(valid => {
+        if (valid) {
+          this.submitAudit();
+        }
+      });
+    },
+    submitAudit() {
+      audit(this.auditForm).then(response => {
+        const {msg} = response
+        this.msgSuccess(msg);
+        this.show.open = false;
+        this.$refs['popover_' + this.currentRowId].doClose();
+        this.getList();
+        this.resetAuditForm();
+      });
+    },
+    cancelAudit() {
+      this.show.open = false;
+      this.resetAuditForm();
+    },
+    resetAuditForm() {
+      this.auditForm = {
+        auditId: null,
+        reviewType: null,
+        reviewContent: ''
+      };
+      this.$refs["auditForm"]?.resetFields();
+    }
+  }
+}
+</script>
+
+<style scoped>
+
+</style>

+ 283 - 0
src/views/hisStore/storeOrderOffline/index.vue

@@ -0,0 +1,283 @@
+<template>
+  <div class="app-container">
+    <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
+      <el-form-item label="订单号" prop="orderCode">
+        <el-input
+          v-model="queryParams.orderCode"
+          placeholder="请输入订单号"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="上传时间" prop="uploadTime">
+        <el-date-picker clearable size="small" style="width: 200px"
+          v-model="queryParams.uploadTime"
+          type="date"
+          value-format="yyyy-MM-dd"
+          placeholder="选择上传时间">
+        </el-date-picker>
+      </el-form-item>
+      <el-form-item>
+        <el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
+      </el-form-item>
+    </el-form>
+
+    <el-row :gutter="10" class="mb8">
+      <el-col :span="1.5">
+        <el-button
+          type="warning"
+          icon="el-icon-download"
+          size="mini"
+          @click="handleExport"
+          v-hasPermi="['store:storeOrderOffline:export']"
+        >导出</el-button>
+      </el-col>
+	  <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+
+    <el-tabs type="card" v-model="activeName" @tab-click="handleClick">
+      <el-tab-pane label="全部订单" name="00"></el-tab-pane>
+      <el-tab-pane v-for="(item,index) in statusOptions" :label="item.dictLabel" :name="item.dictValue"></el-tab-pane>
+    </el-tabs>
+    <el-table border v-loading="loading" :data="storeOrderOfflineList" @selection-change="handleSelectionChange">
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="订单ID" align="center" prop="orderId" />
+      <el-table-column label="订单号" align="center" prop="orderCode" />
+      <el-table-column label="客户名称" align="center" prop="customerName" />
+      <el-table-column label="客户电话" align="center" prop="mobile" />
+      <el-table-column label="状态" align="center" prop="status">
+        <template slot-scope="scope">
+          <dict-tag :options="statusOptions" :value="scope.row.status"/>
+        </template>
+      </el-table-column>
+      <el-table-column label="创建时间" align="center" prop="createTime" />
+      <el-table-column label="所属客服" align="center" prop="companyUserName" />
+      <el-table-column label="所属部门" align="center" prop="companyName" />
+      <el-table-column label="业务员" align="center" prop="uploadUserName" />
+      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+        <template slot-scope="scope">
+          <el-button
+            size="mini"
+            type="text"
+            @click="handleDetails(scope.row)"
+          >查看</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <pagination
+      v-show="total>0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    />
+    <el-drawer
+      size="75%"
+      :title="show.title" :visible.sync="show.open" append-to-body
+    >
+      <offline-order  ref="offlineOrder" />
+    </el-drawer>
+  </div>
+</template>
+
+<script>
+import { listStoreOrderOffline, getStoreOrderOffline, delStoreOrderOffline, addStoreOrderOffline, updateStoreOrderOffline, exportStoreOrderOffline } from "@/api/hisStore/storeOrderOffline";
+import offlineOrder from "../components/offlineOrder.vue";
+
+
+export default {
+  name: "StoreOrderOffline",
+  components: {offlineOrder},
+  data() {
+    return {
+      show:{
+        open:false,
+        title:"订单详情"
+      },
+      statusOptions:[],
+      activeName:"00",
+      // 遮罩层
+      loading: true,
+      // 选中数组
+      ids: [],
+      // 非单个禁用
+      single: true,
+      // 非多个禁用
+      multiple: true,
+      // 显示搜索条件
+      showSearch: true,
+      // 总条数
+      total: 0,
+      // 线下订单表格数据
+      storeOrderOfflineList: [],
+      // 弹出层标题
+      title: "",
+      // 是否显示弹出层
+      open: false,
+      // 查询参数
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        crmId: null,
+        orderCode: null,
+        status: null,
+        payPrice: null,
+        payMoney: null,
+        certificates: null,
+        uploadTime: null,
+        companyUserId: null,
+        uploadUserId: null
+      },
+      // 表单参数
+      form: {},
+      // 表单校验
+      rules: {
+        crmId: [
+          { required: true, message: "订单id不能为空", trigger: "blur" }
+        ],
+      }
+    };
+  },
+  created() {
+    this.getList();
+    this.getDicts("sys_order_offline_status").then((response) => {
+      this.statusOptions = response.data;
+    });
+  },
+  methods: {
+    handleDetails(row){
+      this.show.open=true;
+      const orderId = row.orderId ;
+      setTimeout(() => {
+        this.$refs.offlineOrder.getOfflineOrder(orderId);
+      }, 200);
+    },
+    handleClick(tab, event) {
+      if(tab.name==="00"){
+        this.queryParams.status=null;
+      }
+      else{
+        this.queryParams.status=tab.name;
+      }
+      this.getList();
+    },
+    /** 查询线下订单列表 */
+    getList() {
+      this.loading = true;
+      listStoreOrderOffline(this.queryParams).then(response => {
+        this.storeOrderOfflineList = response.rows;
+        this.total = response.total;
+        this.loading = false;
+      });
+    },
+    // 取消按钮
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 表单重置
+    reset() {
+      this.form = {
+        orderId: null,
+        crmId: null,
+        orderCode: null,
+        status: 0,
+        payPrice: null,
+        payMoney: null,
+        createTime: null,
+        certificates: null,
+        uploadTime: null,
+        companyUserId: null,
+        uploadUserId: null
+      };
+      this.resetForm("form");
+    },
+    /** 搜索按钮操作 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 重置按钮操作 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    // 多选框选中数据
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.orderId)
+      this.single = selection.length!==1
+      this.multiple = !selection.length
+    },
+    /** 新增按钮操作 */
+    handleAdd() {
+      this.reset();
+      this.open = true;
+      this.title = "添加线下订单";
+    },
+    /** 修改按钮操作 */
+    handleUpdate(row) {
+      this.reset();
+      const orderId = row.orderId || this.ids
+      getStoreOrderOffline(orderId).then(response => {
+        this.form = response.data;
+        this.open = true;
+        this.title = "修改线下订单";
+      });
+    },
+    /** 提交按钮 */
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          if (this.form.orderId != null) {
+            updateStoreOrderOffline(this.form).then(response => {
+              if (response.code === 200) {
+                this.msgSuccess("修改成功");
+                this.open = false;
+                this.getList();
+              }
+            });
+          } else {
+            addStoreOrderOffline(this.form).then(response => {
+              if (response.code === 200) {
+                this.msgSuccess("新增成功");
+                this.open = false;
+                this.getList();
+              }
+            });
+          }
+        }
+      });
+    },
+    /** 删除按钮操作 */
+    handleDelete(row) {
+      const orderIds = row.orderId || this.ids;
+      this.$confirm('是否确认删除线下订单编号为"' + orderIds + '"的数据项?', "警告", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        }).then(function() {
+          return delStoreOrderOffline(orderIds);
+        }).then(() => {
+          this.getList();
+          this.msgSuccess("删除成功");
+        }).catch(function() {});
+    },
+    /** 导出按钮操作 */
+    handleExport() {
+      const queryParams = this.queryParams;
+      this.$confirm('是否确认导出所有线下订单数据项?', "警告", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        }).then(function() {
+          return exportStoreOrderOffline(queryParams);
+        }).then(response => {
+          this.download(response.msg);
+        }).catch(function() {});
+    }
+  }
+};
+</script>

+ 245 - 0
src/views/hisStore/storeOrderOffline/myList.vue

@@ -0,0 +1,245 @@
+<template>
+  <div class="app-container">
+    <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
+      <el-form-item label="订单号" prop="orderCode">
+        <el-input
+          v-model="queryParams.orderCode"
+          placeholder="请输入订单号"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="上传时间" prop="uploadTime">
+        <el-date-picker clearable size="small" style="width: 200px"
+                        v-model="queryParams.uploadTime"
+                        type="date"
+                        value-format="yyyy-MM-dd"
+                        placeholder="选择上传时间">
+        </el-date-picker>
+      </el-form-item>
+      <el-form-item>
+        <el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
+      </el-form-item>
+    </el-form>
+
+    <el-row :gutter="10" class="mb8">
+      <el-col :span="1.5">
+        <el-button
+          type="warning"
+          icon="el-icon-download"
+          size="mini"
+          @click="handleExport"
+          v-hasPermi="['store:storeOrderOffline:export']"
+        >导出</el-button>
+      </el-col>
+      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+
+    <el-table border v-loading="loading" :data="storeOrderOfflineList" @selection-change="handleSelectionChange">
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="订单ID" align="center" prop="orderId" />
+      <el-table-column label="订单号" align="center" prop="orderCode" />
+      <el-table-column label="客户名称" align="center" prop="customerName" />
+      <el-table-column label="客户电话" align="center" prop="mobile" />
+      <el-table-column label="状态" align="center" prop="status" />
+      <el-table-column label="创建时间" align="center" prop="createTime" />
+      <el-table-column label="所属客服" align="center" prop="companyUserName" />
+      <el-table-column label="所属部门" align="center" prop="companyName" />
+      <el-table-column label="业务员" align="center" prop="uploadUserName" />
+      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+        <template slot-scope="scope">
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-edit"
+            @click="handleUpdate(scope.row)"
+          >查看</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 { listStoreOrderOffline, getStoreOrderOffline, delStoreOrderOffline, addStoreOrderOffline, updateStoreOrderOffline, exportStoreOrderOffline } from "@/api/hisStore/storeOrderOffline";
+
+export default {
+  name: "StoreOrderOffline",
+  data() {
+    return {
+      // 遮罩层
+      loading: true,
+      // 选中数组
+      ids: [],
+      // 非单个禁用
+      single: true,
+      // 非多个禁用
+      multiple: true,
+      // 显示搜索条件
+      showSearch: true,
+      // 总条数
+      total: 0,
+      // 线下订单表格数据
+      storeOrderOfflineList: [],
+      // 弹出层标题
+      title: "",
+      // 是否显示弹出层
+      open: false,
+      // 查询参数
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        crmId: null,
+        orderCode: null,
+        status: null,
+        payPrice: null,
+        payMoney: null,
+        certificates: null,
+        uploadTime: null,
+        companyUserId: null,
+        uploadUserId: null
+      },
+      // 表单参数
+      form: {},
+      // 表单校验
+      rules: {
+        crmId: [
+          {required: true, message: "订单id不能为空", trigger: "blur"}
+        ],
+      }
+    };
+  },
+  created() {
+    this.getList();
+  },
+  methods: {
+    /** 查询线下订单列表 */
+    getList() {
+      this.loading = true;
+      listStoreOrderOffline(this.queryParams).then(response => {
+        this.storeOrderOfflineList = response.rows;
+        this.total = response.total;
+        this.loading = false;
+      });
+    },
+    // 取消按钮
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 表单重置
+    reset() {
+      this.form = {
+        orderId: null,
+        crmId: null,
+        orderCode: null,
+        status: 0,
+        payPrice: null,
+        payMoney: null,
+        createTime: null,
+        certificates: null,
+        uploadTime: null,
+        companyUserId: null,
+        uploadUserId: null
+      };
+      this.resetForm("form");
+    },
+    /** 搜索按钮操作 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 重置按钮操作 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    // 多选框选中数据
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.orderId)
+      this.single = selection.length !== 1
+      this.multiple = !selection.length
+    },
+    /** 新增按钮操作 */
+    handleAdd() {
+      this.reset();
+      this.open = true;
+      this.title = "添加线下订单";
+    },
+    /** 修改按钮操作 */
+    handleUpdate(row) {
+      this.reset();
+      const orderId = row.orderId || this.ids
+      getStoreOrderOffline(orderId).then(response => {
+        this.form = response.data;
+        this.open = true;
+        this.title = "修改线下订单";
+      });
+    },
+    /** 提交按钮 */
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          if (this.form.orderId != null) {
+            updateStoreOrderOffline(this.form).then(response => {
+              if (response.code === 200) {
+                this.msgSuccess("修改成功");
+                this.open = false;
+                this.getList();
+              }
+            });
+          } else {
+            addStoreOrderOffline(this.form).then(response => {
+              if (response.code === 200) {
+                this.msgSuccess("新增成功");
+                this.open = false;
+                this.getList();
+              }
+            });
+          }
+        }
+      });
+    },
+    /** 删除按钮操作 */
+    handleDelete(row) {
+      const orderIds = row.orderId || this.ids;
+      this.$confirm('是否确认删除线下订单编号为"' + orderIds + '"的数据项?', "警告", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      }).then(function () {
+        return delStoreOrderOffline(orderIds);
+      }).then(() => {
+        this.getList();
+        this.msgSuccess("删除成功");
+      }).catch(function () {
+      });
+    },
+    /** 导出按钮操作 */
+    handleExport() {
+      const queryParams = this.queryParams;
+      this.$confirm('是否确认导出所有线下订单数据项?', "警告", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      }).then(function () {
+        return exportStoreOrderOffline(queryParams);
+      }).then(response => {
+        this.download(response.msg);
+      }).catch(function () {
+      });
+    }
+  }
+};
+</script>

+ 409 - 0
src/views/hisStore/storePayment/index.vue

@@ -0,0 +1,409 @@
+<template>
+  <div class="app-container">
+
+        <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
+          <el-form-item label="所属部门" prop="deptId">
+              <treeselect style="width:205.4px" v-model="queryParams.deptId" :options="deptOptions" :show-count="true" placeholder="请选择所属部门" />
+          </el-form-item>
+          <el-form-item label="付款单号" prop="payCode">
+            <el-input
+              v-model="queryParams.payCode"
+              placeholder="请输入付款单号"
+              clearable
+              size="small"
+              @keyup.enter.native="handleQuery"
+            />
+          </el-form-item>
+          <el-form-item label="手机号" prop="mobile">
+            <el-input
+              v-model="queryParams.mobile"
+              placeholder="请输入手机号"
+              clearable
+              size="small"
+              @keyup.enter.native="handleQuery"
+            />
+          </el-form-item>
+          <el-form-item label="交易单号" prop="bankTransactionId">
+            <el-input
+              v-model="queryParams.bankTransactionId"
+              placeholder="请输入交易单号"
+              clearable
+              size="small"
+              @keyup.enter.native="handleQuery"
+            />
+          </el-form-item>
+          <el-form-item label="银行单号" prop="bankSerialNo">
+            <el-input
+              v-model="queryParams.bankSerialNo"
+              placeholder="请输入银行单号"
+              clearable
+              size="small"
+              @keyup.enter.native="handleQuery"
+            />
+          </el-form-item>
+
+
+      <el-form-item label="员工姓名" prop="companyUserNickName">
+          <el-input
+            v-model="queryParams.companyUserNickName"
+            placeholder="请输入员工姓名"
+            clearable
+            size="small"
+            @keyup.enter.native="handleQuery"
+          />
+      </el-form-item>
+
+          <el-form-item label="提交时间" prop="createTime">
+            <el-date-picker clearable size="small" style="width: 205.4px"
+              v-model="queryParams.createTime"
+              type="date"
+              value-format="yyyy-MM-dd"
+              placeholder="选择提交时间">
+            </el-date-picker>
+          </el-form-item>
+
+          <el-form-item label="支付时间" prop="payTime">
+            <el-date-picker
+            style="width: 215.4px"
+              clearable size="small"
+              v-model="dateRange"
+              type="daterange"
+              value-format="yyyy-MM-dd"
+              start-placeholder="开始日期"
+              end-placeholder="结束日期">
+            </el-date-picker>
+          </el-form-item>
+
+          <el-form-item label="退款时间" prop="refundTime">
+              <el-date-picker
+                style="width: 215.4px"
+                clearable size="small"
+                v-model="refundDateRange"
+                type="daterange"
+                value-format="yyyy-MM-dd"
+                start-placeholder="开始日期"
+                end-placeholder="结束日期">
+              </el-date-picker>
+            </el-form-item>
+
+
+          <el-form-item label="状态" prop="status">
+            <el-select   v-model="queryParams.status" placeholder="请选择状态" clearable size="small" >
+            <el-option
+                    v-for="item in statusOptions"
+                    :key="item.dictValue"
+                    :label="item.dictLabel"
+                    :value="item.dictValue"
+                  />
+            </el-select>
+          </el-form-item>
+          <el-form-item>
+            <el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+            <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
+          </el-form-item>
+        </el-form>
+        <el-row :gutter="10" class="mb8">
+          <el-col :span="1.5">
+            <el-button
+              type="warning"
+              icon="el-icon-download"
+              size="mini"
+              @click="handleExport"
+              v-hasPermi="['store:storePayment:export']"
+            >导出</el-button>
+          </el-col>
+
+        </el-row>
+
+        <el-table height="500" border v-loading="loading" :data="storePaymentList" @selection-change="handleSelectionChange">
+          <el-table-column type="selection" width="55" align="center" />
+          <el-table-column label="ID" align="center" prop="paymentId" />
+          <el-table-column label="付款单号" align="center" prop="payCode" width="120px" />
+          <el-table-column label="会员手机号" align="center" prop="userPhone"  width="120px" />
+          <el-table-column label="支付类型" align="center" prop="payTypeCode" />
+          <el-table-column label="支付金额" align="center" prop="payMoney" />
+          <el-table-column label="退款金额" align="center" prop="refundMoney" />
+          <el-table-column label="交易单号" align="center" prop="bankTransactionId" />
+          <el-table-column label="银行单号" align="center" prop="bankSerialNo" />
+          <el-table-column label="所属公司" align="center" prop="companyName" />
+          <el-table-column label="所属部门" align="center" prop="deptName" />
+          <el-table-column label="员工" align="center" prop="companyUserNickName" />
+          <el-table-column label="状态" align="center" prop="status" >
+              <template slot-scope="scope">
+                  <el-tag prop="status" v-for="(item, index) in statusOptions"    v-if="scope.row.status==item.dictValue">{{item.dictLabel}}</el-tag>
+              </template>
+          </el-table-column>
+          <el-table-column label="提交时间" align="center" prop="createTime" width="180">
+          </el-table-column>
+          <el-table-column label="支付时间" align="center" prop="payTime" width="180">
+          </el-table-column>
+          <el-table-column label="退款时间" align="center" prop="refundTime" width="180">
+          </el-table-column>
+          <el-table-column label="备注" align="center" prop="remark" />
+          <el-table-column label="操作" fixed="right" align="center" class-name="small-padding fixed-width">
+            <template slot-scope="scope">
+              <el-button
+                size="mini"
+                type="text"
+                icon="el-icon-edit"
+                @click="handleUpdate(scope.row)"
+                v-hasPermi="['store:storePayment:edit']"
+              >修改</el-button>
+            </template>
+          </el-table-column>
+        </el-table>
+
+        <pagination
+          v-show="total>0"
+          :total="total"
+          :page.sync="queryParams.pageNum"
+          :limit.sync="queryParams.pageSize"
+          @pagination="getList"
+        />
+
+
+    <!-- 添加或修改支付明细对话框 -->
+    <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="100px">
+        <el-form-item label="支付订单号" prop="payCode">
+          <el-input v-model="form.payCode" disabled placeholder="请输入支付订单号" />
+        </el-form-item>
+        <el-form-item label="支付类型" prop="payTypeCode">
+          <el-input v-model="form.payTypeCode" disabled placeholder="请输入支付类型" />
+        </el-form-item>
+        <el-form-item label="支付金额" prop="payMoney">
+          <el-input v-model="form.payMoney" disabled placeholder="请输入支付金额" />
+        </el-form-item>
+          <el-form-item label="备注" prop="remark">
+          <el-input v-model="form.remark"  placeholder="请输入备注" />
+        </el-form-item>
+
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">确 定</el-button>
+        <el-button @click="cancel">取 消</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { listStorePayment, getStorePayment, delStorePayment, addStorePayment, updateStorePayment, exportStorePayment } from "@/api/hisStore/storePayment";
+import { treeselect } from "@/api/company/companyDept";
+import Treeselect from "@riophae/vue-treeselect";
+import "@riophae/vue-treeselect/dist/vue-treeselect.css";
+export default {
+  name: "StorePayment",
+  components: { Treeselect },
+  data() {
+    return {
+      // 部门树选项
+      deptOptions: undefined,
+      // 是否显示弹出层
+      open: false,
+      // 部门名称
+      deptName: undefined,
+      defaultProps: {
+        children: "children",
+        label: "label",
+      },
+
+      statusOptions:[],
+      // 遮罩层
+      loading: true,
+      // 选中数组
+      ids: [],
+      // 非单个禁用
+      single: true,
+      // 非多个禁用
+      multiple: true,
+      // 显示搜索条件
+      showSearch: true,
+      dateRange:[],
+      refundDateRange:[],
+      // 总条数
+      total: 0,
+      // 支付明细表格数据
+      storePaymentList: [],
+      // 弹出层标题
+      title: "",
+      // 是否显示弹出层
+      open: false,
+      // 查询参数
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        payCode: null,
+        payTypeCode: null,
+        payMoney: null,
+        payTime: null,
+        tradeNo: null,
+        userId: null,
+        openId: null,
+        businessType: null,
+        businessOrderId: null,
+        status: null
+      },
+      // 表单参数
+      form: {},
+      // 表单校验
+      rules: {
+      }
+    };
+  },
+  watch: {
+    // 根据名称筛选部门树
+    deptName(val) {
+        this.$refs.tree.filter(val);
+      },
+  },
+  created() {
+    this.getTreeselect();
+    this.getDicts("store_payment_status").then((response) => {
+      this.statusOptions = response.data;
+    });
+    this.getList();
+  },
+  methods: {
+    /** 查询部门下拉树结构 */
+    getTreeselect() {
+      treeselect().then((response) => {
+        this.deptOptions = response.data;
+      });
+    },
+    // 筛选节点
+    filterNode(value, data) {
+      if (!value) return true;
+      return data.label.indexOf(value) !== -1;
+    },
+    // 节点单击事件
+    handleNodeClick(data) {
+      this.queryParams.deptId = data.id;
+      this.getList();
+    },
+    /** 查询支付明细列表 */
+    getList() {
+      this.loading = true;
+      if(this.refundDateRange!=null&&this.refundDateRange.length==2){
+        this.queryParams.refundBeginTime=this.refundDateRange[0];
+        this.queryParams.refundEndTime=this.refundDateRange[1];
+      }
+      else{
+        this.queryParams.refundBeginTime=null;
+        this.queryParams.refundEndTime=null;
+      }
+      listStorePayment(this.addDateRange(this.queryParams, this.dateRange)).then(response => {
+        this.storePaymentList = response.rows;
+        this.total = response.total;
+        this.loading = false;
+      });
+    },
+    // 取消按钮
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 表单重置
+    reset() {
+      this.form = {
+        paymentId: null,
+        payCode: null,
+        payTypeCode: null,
+        payMoney: null,
+        payTime: null,
+        createTime: null,
+        tradeNo: null,
+        userId: null,
+        openId: null,
+        businessType: null,
+        businessOrderId: null,
+        status: 0
+      };
+      this.resetForm("form");
+    },
+    /** 搜索按钮操作 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 重置按钮操作 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    // 多选框选中数据
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.paymentId)
+      this.single = selection.length!==1
+      this.multiple = !selection.length
+    },
+    /** 新增按钮操作 */
+    handleAdd() {
+      this.reset();
+      this.open = true;
+      this.title = "添加支付明细";
+    },
+    /** 修改按钮操作 */
+    handleUpdate(row) {
+      this.reset();
+      const paymentId = row.paymentId || this.ids
+      getStorePayment(paymentId).then(response => {
+        this.form = response.data;
+        this.open = true;
+        this.title = "修改支付明细";
+      });
+    },
+    /** 提交按钮 */
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          if (this.form.paymentId != null) {
+            updateStorePayment(this.form).then(response => {
+              if (response.code === 200) {
+                this.msgSuccess("修改成功");
+                this.open = false;
+                this.getList();
+              }
+            });
+          } else {
+            addStorePayment(this.form).then(response => {
+              if (response.code === 200) {
+                this.msgSuccess("新增成功");
+                this.open = false;
+                this.getList();
+              }
+            });
+          }
+        }
+      });
+    },
+    /** 删除按钮操作 */
+    handleDelete(row) {
+      const paymentIds = row.paymentId || this.ids;
+      this.$confirm('是否确认删除支付明细编号为"' + paymentIds + '"的数据项?', "警告", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        }).then(function() {
+          return delStorePayment(paymentIds);
+        }).then(() => {
+          this.getList();
+          this.msgSuccess("删除成功");
+        }).catch(function() {});
+    },
+    /** 导出按钮操作 */
+    handleExport() {
+      const queryParams = this.queryParams;
+      this.$confirm('是否确认导出所有支付明细数据项?', "警告", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        }).then(function() {
+          return exportStorePayment(queryParams);
+        }).then(response => {
+          this.download(response.msg);
+        }).catch(function() {});
+    }
+  }
+};
+</script>

+ 216 - 0
src/views/hisStore/storeProduct/index.vue

@@ -0,0 +1,216 @@
+<template>
+  <div class="app-container">
+    <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
+
+      <el-form-item label="商品分类" prop="cateId">
+         <treeselect style="width:205.4px"  v-model="queryParams.cateId"   :options="categoryOptions" :normalizer="normalizer" placeholder="请选择分类" />
+      </el-form-item>
+      <el-form-item label="商品名称" prop="productName">
+        <el-input
+
+          v-model="queryParams.productName"
+          placeholder="请输入商品名称"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="商品类型" prop="productType">
+        <el-select  v-model="queryParams.productType" placeholder="请选择商品类型" clearable size="small" >
+         <el-option
+                v-for="item in productTypeOptions"
+                :key="item.dictValue"
+                :label="item.dictLabel"
+                :value="item.dictValue"
+              />
+        </el-select>
+      </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-tabs type="card" v-model="activeName" @tab-click="handleClick">
+      <el-tab-pane label="出售中" name="1"></el-tab-pane>
+      <el-tab-pane label="待上架" name="0"></el-tab-pane>
+    </el-tabs>
+    <el-table height="500" border  v-loading="loading" :data="storeProductList" @selection-change="handleSelectionChange">
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="ID" align="center" prop="productId" />
+      <el-table-column label="商品图片" align="center" width="120">
+        <template slot-scope="scope">
+          <el-popover
+            placement="right"
+            title=""
+            trigger="hover"
+          >
+            <img slot="reference" :src="scope.row.image" width="100">
+            <img :src="scope.row.image" style="max-width: 150px;">
+          </el-popover>
+        </template>
+      </el-table-column>
+      <el-table-column label="商品名称" show-overflow-tooltip align="center" prop="productName" />
+      <el-table-column label="分类" align="center" prop="cateName" />
+      <el-table-column label="售价" align="center" prop="price" >
+          <template slot-scope="scope" >
+              <span v-if="scope.row.price!=null">{{scope.row.price.toFixed(2)}}</span>
+          </template>
+      </el-table-column>
+      <el-table-column label="原价" align="center" prop="otPrice" >
+          <template slot-scope="scope" >
+              <span v-if="scope.row.otPrice!=null">{{scope.row.otPrice.toFixed(2)}}</span>
+          </template>
+      </el-table-column>
+      <el-table-column label="销量" align="center" prop="sales" />
+      <el-table-column label="库存" align="center" prop="stock" />
+      <el-table-column label="类型" align="center" prop="productType" >
+          <template slot-scope="scope">
+              <el-tag prop="productType" v-for="(item, index) in productTypeOptions"    v-if="scope.row.productType==item.dictValue">{{item.dictLabel}}</el-tag>
+          </template>
+      </el-table-column>
+      <el-table-column label="状态" align="center" prop="isShow" >
+          <template slot-scope="scope">
+              <el-tag prop="status" v-for="(item, index) in isShowOptions"    v-if="scope.row.isShow==item.dictValue">{{item.dictLabel}}</el-tag>
+          </template>
+      </el-table-column>
+      <el-table-column label="操作" align="center" fixed="right" width="120px" class-name="small-padding fixed-width">
+        <template slot-scope="scope">
+          <el-button
+            size="mini"
+            type="text"
+            @click="handleDetails(scope.row)"
+            v-hasPermi="['store:storeProduct:query']"
+          >查看</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+    <pagination
+      v-show="total>0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    />
+    <el-drawer
+     size="50%"
+      :title="title" :visible.sync="open"
+      >
+      <product-details  ref="productDetails" />
+    </el-drawer>
+  </div>
+</template>
+
+<script>
+import {  listStoreProduct  } from "@/api/hisStore/storeProduct";
+import { getAllStoreProductCategory } from "@/api/hisStore/storeProductCategory";
+import productDetails from "../components/productDetails";
+import Treeselect from "@riophae/vue-treeselect";
+import "@riophae/vue-treeselect/dist/vue-treeselect.css";
+export default {
+  name: "StoreProduct",
+  components: {
+    Treeselect,
+    productDetails
+  },
+  data() {
+    return {
+      activeName:"1",
+      isShowOptions:[],
+      productTypeOptions:[],
+      categoryOptions:[],
+      // 遮罩层
+      loading: true,
+      // 选中数组
+      ids: [],
+      // 非单个禁用
+      single: true,
+      // 非多个禁用
+      multiple: true,
+      // 显示搜索条件
+      showSearch: true,
+      // 总条数
+      total: 0,
+      // 商品表格数据
+      storeProductList: [],
+      // 弹出层标题
+      title: "商品详情",
+      // 是否显示弹出层
+      open: false,
+      // 查询参数
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        productName: null,
+        productType: null,
+        isShow: "1",
+
+      },
+    };
+  },
+  created() {
+    this.getDicts("store_product_type").then((response) => {
+      this.productTypeOptions = response.data;
+    });
+    this.getDicts("store_product_is_show").then((response) => {
+      this.isShowOptions = response.data;
+    });
+    this.getTreeselect();
+    this.getList();
+  },
+  methods: {
+    handleDetails(row){
+      this.open=true;
+      setTimeout(() => {
+        this.$refs.productDetails.getStoreProduct(row.productId );
+      }, 500);
+    },
+    handleClick(tab, event) {
+      this.queryParams.isShow=tab.name;
+      this.getList();
+    },
+    /** 转换商品分类数据结构 */
+    normalizer(node) {
+      if (node.children && !node.children.length) {
+        delete node.children;
+      }
+      return {
+        id: node.cateId,
+        label: node.cateName,
+        children: node.children
+      };
+    },
+    getTreeselect() {
+      getAllStoreProductCategory().then(response => {
+        this.categoryOptions = [];
+        const data = this.handleTree(response.data, "cateId", "pid");
+        this.categoryOptions=data;
+      });
+    },
+    /** 查询商品列表 */
+    getList() {
+      this.loading = true;
+      listStoreProduct(this.queryParams).then(response => {
+        this.storeProductList = response.rows;
+        this.total = response.total;
+        this.loading = false;
+      });
+    },
+    /** 搜索按钮操作 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 重置按钮操作 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    // 多选框选中数据
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.productId)
+      this.single = selection.length!==1
+      this.multiple = !selection.length
+    },
+  }
+};
+</script>

+ 603 - 0
src/views/hisStore/storeProductPackage/index.vue

@@ -0,0 +1,603 @@
+<template>
+  <div class="app-container">
+     <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
+     <el-form-item label="套餐分类" prop="cateId">
+        <el-select  v-model="queryParams.cateId" placeholder="请选择分类" clearable size="small" >
+         <el-option
+                v-for="item in cateOptions"
+                :key="item.dictValue"
+                :label="item.dictLabel"
+                :value="item.dictValue"
+              />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="套餐名称" prop="title">
+        <el-input
+          v-model="queryParams.title"
+          placeholder="请输入套餐名称"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+
+      <el-form-item>
+        <el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
+      </el-form-item>
+    </el-form>
+    <!-- <el-row :gutter="10" class="mb8">
+      <el-col :span="1.5">
+        <el-button
+          type="primary"
+          icon="el-icon-plus"
+          size="mini"
+          @click="handleAdd"
+          v-hasPermi="['store:storeProductPackage:add']"
+        >新增</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="success"
+          icon="el-icon-edit"
+          size="mini"
+          :disabled="single"
+          @click="handleUpdate"
+          v-hasPermi="['store:storeProductPackage:edit']"
+        >修改</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="danger"
+          icon="el-icon-delete"
+          size="mini"
+          :disabled="multiple"
+          @click="handleDelete"
+          v-hasPermi="['store:storeProductPackage:remove']"
+        >删除</el-button>
+      </el-col>
+	  <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row> -->
+    <el-table  height="500" border v-loading="loading" :data="storeProductPackageList" @selection-change="handleSelectionChange">
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="20" align="center" prop="packageId" />
+      <el-table-column label="封面" align="center" width="120">
+        <template slot-scope="scope">
+          <el-popover
+            placement="right"
+            title=""
+            trigger="hover"
+          >
+            <img slot="reference" :src="scope.row.imgUrl" width="100">
+            <img :src="scope.row.imgUrl" style="max-width: 150px;">
+          </el-popover>
+        </template>
+      </el-table-column>
+      <el-table-column label="所属分类" align="center" prop="cateId" width="150px" >
+          <template slot-scope="scope">
+              <el-tag prop="cateId" v-for="(item, index) in cateOptions"    v-if="scope.row.cateId==item.dictValue">{{item.dictLabel}}</el-tag>
+          </template>
+      </el-table-column>
+      <el-table-column label="标题" align="center" prop="title" show-overflow-tooltip />
+      <el-table-column label="描述" align="center" prop="descs" show-overflow-tooltip />
+      <el-table-column label="原价" align="center"  >
+          <template slot-scope="scope">
+              <div  v-if="scope.row.money!=null"  >
+                {{scope.row.money.toFixed(2)}}
+              </div>
+          </template>
+      </el-table-column>
+      <el-table-column label="套餐价格" align="center"  >
+          <template slot-scope="scope">
+              <div  v-if="scope.row.payMoney!=null"  >
+                {{scope.row.payMoney.toFixed(2)}}
+              </div>
+          </template>
+      </el-table-column>
+      <el-table-column label="支付类型" align="center" prop="payType" width="150px" >
+          <template slot-scope="scope">
+              <el-tag prop="payType" v-for="(item, index) in storePayTypeOptions"    v-if="scope.row.payType==item.dictValue">{{item.dictLabel}}</el-tag>
+          </template>
+      </el-table-column>
+      <el-table-column label="限购次数" align="center" prop="limitCount" />
+      <!-- <el-table-column label="所属公司" align="center" prop="companyName" /> -->
+      <!-- <el-table-column label="所属部门" align="center" prop="deptName" /> -->
+      <el-table-column label="操作" fixed="right" width="120px"  align="center" class-name="small-padding fixed-width">
+        <template slot-scope="scope">
+          <el-button
+            size="mini"
+            type="text"
+            @click="handleDetails(scope.row)"
+            v-hasPermi="['store:storeProductPackage:query']"
+          >查看</el-button>
+
+        </template>
+      </el-table-column>
+    </el-table>
+    <pagination
+      v-show="total>0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    />
+    <el-dialog :title="title" :visible.sync="open" width="800px" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+        <el-form-item label="套餐封面" prop="imgUrl">
+          <Material v-model="imageArr" type="image" :num="1" :width="150" :height="150" />
+        </el-form-item>
+        <el-form-item label="套餐组图" prop="images">
+           <Material v-model="photoArr" type="image" :num="5" :width="150" :height="150" />
+        </el-form-item>
+        <el-form-item label="套餐标题" prop="title">
+          <el-input v-model="form.title" placeholder="请输入套餐标题" />
+        </el-form-item>
+        <el-form-item label="所属分类" props="cateId">
+            <el-select style="width: 200px" v-model="form.cateId" placeholder="请选择分类" clearable size="small" >
+              <el-option
+                      v-for="item in cateOptions"
+                      :key="item.dictValue"
+                      :label="item.dictLabel"
+                      :value="item.dictValue"
+                    />
+            </el-select>
+        </el-form-item>
+        <el-form-item label="套餐描述" prop="descs">
+          <el-input type="textarea" v-model="form.descs" placeholder="请输入描述" />
+        </el-form-item>
+        <el-form-item label="套餐详情" prop="content">
+          <Editor ref="myeditor"   :min-height="192" @on-text-change="updateText" />
+        </el-form-item>
+        <el-form-item label="套餐商品" prop="productList"  >
+              <el-row  >
+                <el-col >
+                      <el-button plain  type="primary" icon="el-icon-plus" @click="handleAddProduct">添加商品</el-button>
+                </el-col>
+              </el-row>
+              <el-table border width="100%" style="margin-top:5px;"  :data="products">
+                <el-table-column label="商品编号" align="center" prop="barCode" />
+                <el-table-column label="商品图片" align="center" width="100">
+                  <template slot-scope="scope">
+                    <el-popover
+                      placement="right"
+                      title=""
+                      trigger="hover">
+                      <img slot="reference" :src="scope.row.image" width="50">
+                      <img :src="scope.row.image" style="max-width: 50px;">
+                    </el-popover>
+                  </template>
+                </el-table-column>
+                <el-table-column label="商品名称" show-overflow-tooltip align="center" prop="productName" />
+                <el-table-column label="商品规格" align="center" prop="sku" />
+                <!-- <el-table-column label="库存" align="center" prop="stock" /> -->
+                <el-table-column label="售价" align="center"  prop="price"  >
+                   <template slot-scope="scope">
+                    <div v-if="scope.row.price!=null">
+                         {{scope.row.price.toFixed(2)}}
+                    </div>
+                  </template>
+                </el-table-column>
+                <!-- <el-table-column label="代理价" align="center" prop="agentPrice" /> -->
+                <el-table-column label="数量" align="center"  prop="count" width="200px" >
+                   <template slot-scope="scope">
+                    <div>
+                        <el-input-number v-model="scope.row.count"  @change="handleProductCountChange(scope.row)"  size="mini" :min="1" :max="scope.row.stock"  ></el-input-number>
+                    </div>
+                  </template>
+                </el-table-column>
+                 <el-table-column label="小计" align="center"  prop="money"  >
+                   <template slot-scope="scope">
+                    <div v-if="scope.row.money!=null">
+                         {{scope.row.money.toFixed(2)}}
+                    </div>
+                  </template>
+                </el-table-column>
+                <el-table-column label="操作" align="center" width="100px" >
+                  <template slot-scope="scope">
+                    <el-button
+                      size="mini"
+                      type="text"
+                      icon="el-icon-delete"
+                      @click="handleProductDelete(scope.row)"
+                    >删除</el-button>
+                  </template>
+                </el-table-column>
+              </el-table>
+              <el-row  >
+                <el-col  >
+                      <span style="margin-left:10px;" v-if="totalMoney!=null">商品总价:{{totalMoney}}</span>
+                </el-col>
+              </el-row>
+        </el-form-item>
+        <el-form-item label="原价" prop="money">
+          <el-input-number v-model="form.money" :precision="2"  :min="0.00" placeholder="请输入原价" />
+        </el-form-item>
+        <el-form-item label="套餐价格" prop="payMoney">
+          <el-input-number v-model="form.payMoney" :precision="2"  :min="0.00" placeholder="请输入套餐价格" />
+        </el-form-item>
+        <el-form-item label="支付类型" props="payType">
+              <el-radio-group v-model="form.payType">
+                <el-radio  v-if="item.dictValue!=3" :label="item.dictValue" v-for="item in storePayTypeOptions" >{{item.dictLabel}}</el-radio>
+              </el-radio-group>
+        </el-form-item>
+         <el-form-item label="限购次数" prop="limitCount">
+              <el-input-number v-model="form.limitCount" :min="0" :step="1" placeholder="请输入限购次数" />
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">确 定</el-button>
+        <el-button @click="cancel">取 消</el-button>
+      </div>
+    </el-dialog>
+    <el-dialog :title="product.title" v-if="product.open"  :visible.sync="product.open" width="1000px" append-to-body>
+        <product-select  ref="product"  @selectProduct="selectProduct" />
+    </el-dialog>
+    <el-drawer
+     size="50%"
+      :title="show.title" :visible.sync="show.open"
+      >
+      <product-package-details  ref="productPackageDetails" />
+    </el-drawer>
+  </div>
+</template>
+
+<script>
+import { listStoreProductPackage, getStoreProductPackage, delStoreProductPackage, addStoreProductPackage, updateStoreProductPackage, exportStoreProductPackage } from "@/api/hisStore/storeProductPackage";
+import Editor from '@/components/Editor/wang';
+import productSelect from "../components/productSelect";
+import Material from '@/components/Material'
+import singleImg from '@/components/Material/single'
+import productPackageDetails from "../components/productPackageDetails";
+export default {
+  name: "StoreProductPackage",
+  components: {
+    Editor,
+    productSelect,
+    Material,
+    singleImg,
+    productPackageDetails
+  },
+  watch: {
+    imageArr: function(val) {
+      this.form.imgUrl = val.join(',')
+    },
+    photoArr: function(val) {
+      this.form.images = val.join(',')
+    }
+  },
+  data() {
+    return {
+      show:{
+        open:false,
+        title:"商品套餐信息"
+      },
+      photoArr:[],
+      imageArr:[],
+      cateOptions:[],
+      storePayTypeOptions:[],
+      totalMoney:0.00,
+      products:[],
+      product:{
+        open:false,
+        title:"商品选择"
+      },
+      // 遮罩层
+      loading: true,
+      // 选中数组
+      ids: [],
+      // 非单个禁用
+      single: true,
+      // 非多个禁用
+      multiple: true,
+      // 显示搜索条件
+      showSearch: true,
+      // 总条数
+      total: 0,
+      // 商品组合套餐表格数据
+      storeProductPackageList: [],
+      // 弹出层标题
+      title: "",
+      // 是否显示弹出层
+      open: false,
+      // 查询参数
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        title: null,
+        descs: null,
+        content: null,
+        imgUrl: null,
+        productIds: null,
+        productAttrValueIds: null,
+        money: null,
+        payMoney: null,
+        companyId: null,
+        companyUserId: null
+      },
+      // 表单参数
+      form: {},
+      // 表单校验
+      rules: {
+        title: [
+          { required: true, message: "标题不能为空" }
+        ],
+        descs: [
+          { required: true, message: "描述不能为空" }
+        ],
+        content: [
+          { required: true, message: "详情不能为空" }
+        ],
+        imgUrl: [
+          { required: true, message: "封面不能为空" }
+        ],
+        images: [
+          { required: true, message: "组图不能为空" }
+        ],
+        productList: [
+          { required: true, message: "商品不能为空" }
+        ],
+        payMoney: [
+          { required: true, message: "套餐价格不能为空" }
+        ],
+        payType: [
+          { required: true, message: "支付类型不能为空" }
+        ],
+        limitCount: [
+          { required: true, message: "限购次数不能为空" }
+        ],
+
+      }
+    };
+  },
+  created() {
+    this.getDicts("store_product_package_cate").then((response) => {
+      this.cateOptions = response.data;
+    });
+    this.getDicts("store_pay_type").then((response) => {
+      this.storePayTypeOptions = response.data;
+    });
+    this.getList();
+  },
+  methods: {
+    handleDetails(row){
+      this.show.open=true;
+      setTimeout(() => {
+        this.$refs.productPackageDetails.getStoreProductPackage(row.packageId );
+      }, 500);
+    },
+    handleProductCountChange(row){
+      row.money=row.count*row.price;
+      this.$forceUpdate();
+      this.compute();
+    },
+    handleProductDelete(row){
+       this.products.splice(this.products.findIndex(item => item.id === row.id), 1)
+       this.compute();
+    },
+    compute(){
+      this.totalMoney=0;
+      var that=this;
+      this.products.forEach (function (value) {
+          that.totalMoney += value.money;
+      });
+      that.totalMoney=that.totalMoney.toFixed(2);
+    },
+    selectProduct(row){
+      for(var i=0;i<this.products.length;i++){
+        if(this.products[i].id==row.id){
+          return;
+        }
+      }
+      row.count=1;
+      row.money=row.count*row.price;
+      this.products.push(row);
+      this.compute();
+    },
+    handleAddProduct(){
+      this.product.open=true;
+      // setTimeout(() => {
+      //   this.$refs.product.getData(1);
+      // }, 200);
+
+    },
+    handleAvatarSuccess(res, file) {
+        if(res.code==200){
+          this.form.imgUrl=res.url;
+        }
+        else{
+          this.msgError(res.msg);
+        }
+    },
+    beforeAvatarUpload(file) {
+      const isLt1M = file.size / 1024 / 1024 < 1;
+      if (!isLt1M) {
+        this.$message.error('上传图片大小不能超过 1MB!');
+      }
+      return   isLt1M;
+    },
+    updateText(text){
+      this.form.content=text;
+    },
+    /** 查询商品组合套餐列表 */
+    getList() {
+      this.loading = true;
+      listStoreProductPackage(this.queryParams).then(response => {
+        this.storeProductPackageList = response.rows;
+        this.total = response.total;
+        this.loading = false;
+      });
+    },
+    // 取消按钮
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 表单重置
+       // 表单重置
+       reset() {
+      this.form = {
+        packageId: null,
+        title: null,
+        descs: null,
+        content: null,
+        imgUrl: null,
+        images: null,
+        money: null,
+        payMoney: null,
+        companyId: null,
+        companyUserId: null,
+        payType:"1",
+        limitCount:0,
+        cateId:"0",
+        productList:null,
+      };
+      this.products=[];
+      this.photoArr=[];
+      this.imageArr=[];
+      this.resetForm("form");
+    },
+    /** 搜索按钮操作 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 重置按钮操作 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    // 多选框选中数据
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.packageId)
+      this.single = selection.length!==1
+      this.multiple = !selection.length
+    },
+    handleAdd() {
+      this.reset();
+      this.open = true;
+      this.title = "添加商品组合套餐";
+      setTimeout(() => {
+        this.$refs.myeditor.setText("");
+      }, 200);
+
+    },
+    /** 修改按钮操作 */
+    handleUpdate(row) {
+      this.reset();
+      const packageId = row.packageId || this.ids
+      getStoreProductPackage(packageId).then(response => {
+        this.form = response.data;
+        this.open = true;
+        this.title = "修改商品组合套餐";
+        this.products=this.form.productList;
+        for(var i=0;i<this.products.length;i++){
+          this.products[i].money=this.products[i].count*this.products[i].price;
+        }
+        this.compute();
+        setTimeout(() => {
+          if(this.form.content==null){
+            this.$refs.myeditor.setText("");
+          }
+          else{
+            this.$refs.myeditor.setText(this.form.content);
+          }
+        }, 200);
+        this.form.payType = response.data.payType.toString();
+        if(this.form.imgUrl!=null){
+          this.imageArr=this.form.imgUrl.split(",");
+        }
+        if(this.form.images!=null){
+          this.photoArr=this.form.images.split(",");
+        }
+         if(this.form.cateId!=null){
+          this.form.cateId = response.data.cateId.toString();
+        }
+        this.$forceUpdate();
+      });
+    },
+    /** 提交按钮 */
+    submitForm() {
+      this.form.productList=[];
+      this.products.forEach((item) => {
+        var data={id:item.id,count:item.count}
+        this.form.productList.push(data)
+      })
+      // return;
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          if (this.form.packageId != null) {
+            updateStoreProductPackage(this.form).then(response => {
+              if (response.code === 200) {
+                this.msgSuccess("修改成功");
+                this.open = false;
+                this.getList();
+              }
+            });
+          } else {
+            addStoreProductPackage(this.form).then(response => {
+              if (response.code === 200) {
+                this.msgSuccess("新增成功");
+                this.open = false;
+                this.getList();
+              }
+            });
+          }
+        }
+      });
+    },
+    /** 删除按钮操作 */
+    handleDelete(row) {
+      const packageIds = row.packageId || this.ids;
+      this.$confirm('是否确认删除商品组合套餐编号为"' + packageIds + '"的数据项?', "警告", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        }).then(function() {
+          return delStoreProductPackage(packageIds);
+        }).then(() => {
+          this.getList();
+          this.msgSuccess("删除成功");
+        }).catch(function() {});
+    },
+    /** 导出按钮操作 */
+    handleExport() {
+      const queryParams = this.queryParams;
+      this.$confirm('是否确认导出所有商品组合套餐数据项?', "警告", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        }).then(function() {
+          return exportStoreProductPackage(queryParams);
+        }).then(response => {
+          this.download(response.msg);
+        }).catch(function() {});
+    }
+  }
+};
+
+</script>
+<style scoped lang="scss">
+.items{
+  margin: 5px 0px;
+  display: flex;
+  flex-direction: row;
+  align-items: center;
+  justify-content: flex-start;
+  .pic{
+    width:60px;
+    height:60px;
+  }
+  .goods-content{
+    margin-left: 10px;
+    max-width: 200px;
+    text-align: left;
+    .goods-title{
+
+      overflow:hidden;
+      white-space: nowrap;
+      text-overflow: ellipsis;
+      -o-text-overflow:ellipsis;
+    }
+  }
+}
+</style>

+ 393 - 0
src/views/hisStore/userOnlineState/index.vue

@@ -0,0 +1,393 @@
+<template>
+  <div class="app-container">
+    <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
+      <el-form-item label="用户昵称" prop="nickname">
+        <el-input
+          v-model="queryParams.nickname"
+          placeholder="请输入用户昵称"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="手机号码" prop="phone">
+        <el-input
+          v-model="queryParams.phone"
+          placeholder="请输入手机号码"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="所属公司" prop="companyName">
+        <el-input
+          v-model="queryParams.companyName"
+          placeholder="请输入所属公司"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="所属销售" prop="companyUserNickName">
+        <el-input
+          v-model="queryParams.companyUserName"
+          placeholder="请输入所属销售"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item>
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
+      </el-form-item>
+
+    </el-form>
+
+    <el-row :gutter="10" class="mb8">
+<!--      <el-col :span="1.5">-->
+<!--        <el-button-->
+<!--          type="primary"-->
+<!--          plain-->
+<!--          icon="el-icon-plus"-->
+<!--          size="mini"-->
+<!--          @click="handleAdd"-->
+<!--          v-hasPermi="['store:userOnlineState:add']"-->
+<!--        >新增</el-button>-->
+<!--      </el-col>-->
+<!--      <el-col :span="1.5">-->
+<!--        <el-button-->
+<!--          type="success"-->
+<!--          plain-->
+<!--          icon="el-icon-edit"-->
+<!--          size="mini"-->
+<!--          :disabled="single"-->
+<!--          @click="handleUpdate"-->
+<!--          v-hasPermi="['store:userOnlineState:edit']"-->
+<!--        >修改</el-button>-->
+<!--      </el-col>-->
+<!--      <el-col :span="1.5">-->
+<!--        <el-button-->
+<!--          type="danger"-->
+<!--          plain-->
+<!--          icon="el-icon-delete"-->
+<!--          size="mini"-->
+<!--          :disabled="multiple"-->
+<!--          @click="handleDelete"-->
+<!--          v-hasPermi="['store:userOnlineState:remove']"-->
+<!--        >删除</el-button>-->
+<!--      </el-col>-->
+      <el-col :span="1.5">
+        <el-button
+          type="warning"
+          plain
+          icon="el-icon-download"
+          size="mini"
+          :loading="exportLoading"
+          @click="handleExport"
+          v-hasPermi="['store:userOnlineState:export']"
+        >导出</el-button>
+      </el-col>
+      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+
+    <el-table border v-loading="loading" :data="userOnlineStateList" @selection-change="handleSelectionChange">
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="用户id" align="center" prop="userId" />
+      <el-table-column label="用户昵称" align="center" prop="nickname" />
+      <el-table-column label="用户头像" align="center" width="80">
+        <template slot-scope="scope">
+          <el-popover
+            placement="right"
+            title=""
+            trigger="hover"
+          >
+            <img slot="reference" :src="scope.row.avatar" width="50" >
+            <img :src="scope.row.avatar" style="max-width: 120px;">
+          </el-popover>
+        </template>
+      </el-table-column>
+      <el-table-column label="手机号码" align="center" prop="phone" />
+      <el-table-column label="所属公司" align="center" prop="companyName" />
+      <el-table-column label="所属销售" align="center" prop="companyUserName" />
+      <el-table-column label="上线状态" align="center" prop="onlineStatus">
+      <template slot-scope="scope">
+        <el-tag prop="onlineStatus"  v-if="scope.row.onlineStatus === 1" type="success">已上线</el-tag>
+        <el-tag prop="onlineStatus"  v-if="scope.row.onlineStatus === 2" type="primary">未上线</el-tag>
+      </template>
+      </el-table-column>
+<!--      <el-table-column label="上线时间" align="center" prop="onlineTime" width="180">-->
+<!--        <template slot-scope="scope">-->
+<!--          <span>{{ parseTime(scope.row.onlineTime, '{y}-{m}-{d}') }}</span>-->
+<!--        </template>-->
+<!--      </el-table-column>-->
+<!--      <el-table-column label="看课数量" align="center" prop="watchCourseCount" />-->
+<!--      <el-table-column label="参与营期数量" align="center" prop="partCourseCount" />-->
+<!--      <el-table-column label="最后一次看课时间" align="center" prop="lastWatchDate" width="180">-->
+<!--        <template slot-scope="scope">-->
+<!--          <span>{{ parseTime(scope.row.lastWatchDate, '{y}-{m}-{d}') }}</span>-->
+<!--        </template>-->
+<!--      </el-table-column>-->
+<!--      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">-->
+<!--        <template slot-scope="scope">-->
+<!--          <el-button-->
+<!--            size="mini"-->
+<!--            type="text"-->
+<!--            icon="el-icon-edit"-->
+<!--            @click="handleUpdate(scope.row)"-->
+<!--            v-hasPermi="['store:userOnlineState:edit']"-->
+<!--          >修改</el-button>-->
+<!--          <el-button-->
+<!--            size="mini"-->
+<!--            type="text"-->
+<!--            icon="el-icon-delete"-->
+<!--            @click="handleDelete(scope.row)"-->
+<!--            v-hasPermi="['store:userOnlineState:remove']"-->
+<!--          >删除</el-button>-->
+<!--        </template>-->
+<!--      </el-table-column>-->
+    </el-table>
+
+    <pagination
+      v-show="total>0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    />
+
+<!--    &lt;!&ndash; 添加或修改用户上线情况对话框 &ndash;&gt;-->
+<!--    <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>-->
+<!--      <el-form ref="form" :model="form" :rules="rules" label-width="80px">-->
+<!--        <el-form-item label="用户昵称" prop="nickname">-->
+<!--          <el-input v-model="form.nickname" placeholder="请输入用户昵称" />-->
+<!--        </el-form-item>-->
+<!--        <el-form-item label="用户头像" prop="avatar">-->
+<!--          <el-input v-model="form.avatar" placeholder="请输入用户头像" />-->
+<!--        </el-form-item>-->
+<!--        <el-form-item label="微信小程序OPENID" prop="maOpenId">-->
+<!--          <el-input v-model="form.maOpenId" placeholder="请输入微信小程序OPENID" />-->
+<!--        </el-form-item>-->
+<!--        <el-form-item label="微信公众号OPENID" prop="mpOpenId">-->
+<!--          <el-input v-model="form.mpOpenId" placeholder="请输入微信公众号OPENID" />-->
+<!--        </el-form-item>-->
+<!--        <el-form-item label="关联ID" prop="unionId">-->
+<!--          <el-input v-model="form.unionId" placeholder="请输入关联ID" />-->
+<!--        </el-form-item>-->
+<!--        <el-form-item label="公司id" prop="companyId">-->
+<!--          <el-input v-model="form.companyId" placeholder="请输入公司id" />-->
+<!--        </el-form-item>-->
+<!--        <el-form-item label="销售id" prop="companyUserId">-->
+<!--          <el-input v-model="form.companyUserId" placeholder="请输入销售id" />-->
+<!--        </el-form-item>-->
+<!--        <el-form-item label="上线状态,1-已上线;2-未上线">-->
+<!--          <el-radio-group v-model="form.onlineStatus">-->
+<!--            <el-radio label="1">请选择字典生成</el-radio>-->
+<!--          </el-radio-group>-->
+<!--        </el-form-item>-->
+<!--        <el-form-item label="上线时间" prop="onlineTime">-->
+<!--          <el-date-picker clearable size="small"-->
+<!--            v-model="form.onlineTime"-->
+<!--            type="date"-->
+<!--            value-format="yyyy-MM-dd"-->
+<!--            placeholder="选择上线时间">-->
+<!--          </el-date-picker>-->
+<!--        </el-form-item>-->
+<!--        <el-form-item label="看课数量" prop="watchCourseCount">-->
+<!--          <el-input v-model="form.watchCourseCount" placeholder="请输入看课数量" />-->
+<!--        </el-form-item>-->
+<!--        <el-form-item label="参与营期数量" prop="partCourseCount">-->
+<!--          <el-input v-model="form.partCourseCount" placeholder="请输入参与营期数量" />-->
+<!--        </el-form-item>-->
+<!--        <el-form-item label="最后一次看课时间" prop="lastWatchDate">-->
+<!--          <el-date-picker clearable size="small"-->
+<!--            v-model="form.lastWatchDate"-->
+<!--            type="date"-->
+<!--            value-format="yyyy-MM-dd"-->
+<!--            placeholder="选择最后一次看课时间">-->
+<!--          </el-date-picker>-->
+<!--        </el-form-item>-->
+<!--      </el-form>-->
+<!--      <div slot="footer" class="dialog-footer">-->
+<!--        <el-button type="primary" @click="submitForm">确 定</el-button>-->
+<!--        <el-button @click="cancel">取 消</el-button>-->
+<!--      </div>-->
+<!--    </el-dialog>-->
+  </div>
+</template>
+
+<script>
+import { listUserOnlineState, getUserOnlineState, delUserOnlineState, addUserOnlineState, updateUserOnlineState, exportUserOnlineState } from "@/api/hisStore/userOnlineState";
+
+export default {
+  name: "UserOnlineState",
+  data() {
+    return {
+      // 遮罩层
+      loading: true,
+      // 导出遮罩层
+      exportLoading: false,
+      // 选中数组
+      ids: [],
+      // 非单个禁用
+      single: true,
+      // 非多个禁用
+      multiple: true,
+      // 显示搜索条件
+      showSearch: true,
+      // 总条数
+      total: 0,
+      // 用户上线情况表格数据
+      userOnlineStateList: [],
+      // 弹出层标题
+      title: "",
+      // 是否显示弹出层
+      open: false,
+      // 查询参数
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        nickname: null,
+        avatar: null,
+        phone: null,
+        maOpenId: null,
+        mpOpenId: null,
+        unionId: null,
+        companyId: null,
+        companyUserId: null,
+        onlineStatus: null,
+        onlineTime: null,
+        watchCourseCount: null,
+        partCourseCount: null,
+        lastWatchDate: null
+      },
+      // 表单参数
+      form: {},
+      // 表单校验
+      rules: {
+      }
+    };
+  },
+  created() {
+    this.getList();
+  },
+  methods: {
+    /** 查询用户上线情况列表 */
+    getList() {
+      this.loading = true;
+      listUserOnlineState(this.queryParams).then(response => {
+        this.userOnlineStateList = response.rows;
+        this.total = response.total;
+        this.loading = false;
+      });
+    },
+    // 取消按钮
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 表单重置
+    reset() {
+      this.form = {
+        userId: null,
+        nickname: null,
+        avatar: null,
+        phone: null,
+        createTime: null,
+        maOpenId: null,
+        mpOpenId: null,
+        unionId: null,
+        companyId: null,
+        companyUserId: null,
+        onlineStatus: 0,
+        onlineTime: null,
+        watchCourseCount: null,
+        partCourseCount: null,
+        lastWatchDate: null
+      };
+      this.resetForm("form");
+    },
+    /** 搜索按钮操作 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 重置按钮操作 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    // 多选框选中数据
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.userId)
+      this.single = selection.length!==1
+      this.multiple = !selection.length
+    },
+    /** 新增按钮操作 */
+    handleAdd() {
+      this.reset();
+      this.open = true;
+      this.title = "添加用户上线情况";
+    },
+    /** 修改按钮操作 */
+    handleUpdate(row) {
+      this.reset();
+      const userId = row.userId || this.ids
+      getUserOnlineState(userId).then(response => {
+        this.form = response.data;
+        this.open = true;
+        this.title = "修改用户上线情况";
+      });
+    },
+    /** 提交按钮 */
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          if (this.form.userId != null) {
+            updateUserOnlineState(this.form).then(response => {
+              this.msgSuccess("修改成功");
+              this.open = false;
+              this.getList();
+            });
+          } else {
+            addUserOnlineState(this.form).then(response => {
+              this.msgSuccess("新增成功");
+              this.open = false;
+              this.getList();
+            });
+          }
+        }
+      });
+    },
+    /** 删除按钮操作 */
+    handleDelete(row) {
+      const userIds = row.userId || this.ids;
+      this.$confirm('是否确认删除用户上线情况编号为"' + userIds + '"的数据项?', "警告", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        }).then(function() {
+          return delUserOnlineState(userIds);
+        }).then(() => {
+          this.getList();
+          this.msgSuccess("删除成功");
+        }).catch(() => {});
+    },
+    /** 导出按钮操作 */
+    handleExport() {
+      const queryParams = this.queryParams;
+      this.$confirm('是否确认导出所有用户上线情况数据项?', "警告", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        }).then(() => {
+          this.exportLoading = true;
+          return exportUserOnlineState(queryParams);
+        }).then(response => {
+          this.download(response.msg);
+          this.exportLoading = false;
+        }).catch(() => {});
+    }
+  }
+};
+</script>

+ 389 - 364
src/views/qw/QwWorkTask/qw/index.vue

@@ -1,16 +1,31 @@
 <template>
   <div class="app-container">
     <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
-      <el-form-item label="企微账号" prop="qwUserId">
-        <el-select v-model="queryParams.qwUserId" placeholder="企微账号"  size="small" @change="updateQwuser()">
-          <el-option
-            v-for="dict in myQwUserList"
-            :key="dict.dictValue"
-            :label="dict.dictLabel+'('+dict.corpName+')'"
-            :value="dict.dictValue"
-          />
-        </el-select>
+	 <el-form-item label="部门" prop="type">
+	    <treeselect style="width: 220px" :clearable="false"  v-model="queryParams.deptId"  :options="deptOptions" clearable :show-count="true" placeholder="请选择归属部门"  />
+	 </el-form-item>
+     <el-form-item label="企微账号" prop="qwUserName">
+             <el-input
+               v-model="queryParams.qwUserName"
+               placeholder="请输入企微昵称"
+               clearable
+               size="small"
+               @keyup.enter.native="handleQuery"
+             />
       </el-form-item>
+	  <el-form-item label="所属客服" prop="companyUserId">
+	    <el-select v-model="queryParams.companyUserId" clearable filterable remote
+	               placeholder="请输入关键词" :remote-method="loadCompanyUserOptions"
+	               v-select-load-more="loadMoreCompanyUserOptions"
+	               :loading="companyUserOptionsLoading">
+	      <el-option
+	        v-for="item in companyUserOptions"
+	        :key="item.dictValue"
+	        :label="item.dictLabel"
+	        :value="item.dictValue">
+	      </el-option>
+	    </el-select>
+	  </el-form-item>
       <el-form-item label="类别" prop="type">
         <el-select v-model="queryParams.type" placeholder="请选择类别" clearable size="small">
           <el-option
@@ -22,17 +37,16 @@
         </el-select>
       </el-form-item>
 
-      <el-form-item label="处理状态" prop="trackType">
-        <el-select v-model="queryParams.trackType" placeholder="处理状态" clearable size="small">
-          <el-option
-            v-for="dict in trackTypeOptions"
-            :key="dict.dictValue"
-            :label="dict.dictLabel"
-            :value="dict.dictValue"
-          />
-        </el-select>
-      </el-form-item>
-
+	  <el-form-item label="处理状态" prop="trackType">
+	    <el-select v-model="queryParams.trackType" placeholder="处理状态" clearable size="small">
+	      <el-option
+	        v-for="dict in trackTypeOptions"
+	        :key="dict.dictValue"
+	        :label="dict.dictLabel"
+	        :value="dict.dictValue"
+	      />
+	    </el-select>
+	  </el-form-item>
       <el-form-item label="sop编号" prop="sopId">
         <el-input
           v-model="queryParams.sopId"
@@ -42,37 +56,46 @@
           @keyup.enter.native="handleQuery"
         />
       </el-form-item>
+      <el-form-item label="标题" prop="title">
+        <el-input
+          v-model="queryParams.title"
+          placeholder="请输入标题"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
       <el-form-item>
         <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
         <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
-        <el-button icon="el-icon-refresh" size="mini" @click="sm()">色盲模式</el-button>
-
+		<el-button icon="el-icon-refresh" size="mini" @click="sm()">色盲模式</el-button>
       </el-form-item>
     </el-form>
 
-    <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
-    <el-tabs type="card" v-model="actName" @tab-click="handleClickX">
-      <el-tab-pane v-for="(item,index) in statusOptions" :label="item.dictLabel" :name="item.dictValue"></el-tab-pane>
-    </el-tabs>
+      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+	<el-tabs type="card" v-model="actName" @tab-click="handleClickX">
+	  <el-tab-pane v-for="(item,index) in statusOptions" :label="item.dictLabel" :name="item.dictValue"></el-tab-pane>
+	</el-tabs>
     <el-table border v-loading="loading" :data="QwWorkTaskList" @selection-change="handleSelectionChange">
       <el-table-column type="selection" width="55" align="center" />
       <el-table-column label="客户昵称" align="center" prop="name" />
       <el-table-column label="企微账号" align="center" prop="qwUserName" />
+	  <el-table-column label="企微昵称" align="center" prop="nickName" />
       <el-table-column label="状态" align="center" prop="status">
-        <template slot-scope="scope">
-          <dict-tag :options="statusOptions" :value="scope.row.status"/>
-        </template>
+		 <template slot-scope="scope">
+		   <dict-tag :options="statusOptions" :value="scope.row.status"/>
+		 </template>
       </el-table-column>
       <el-table-column label="类别" align="center" prop="type">
         <template slot-scope="scope">
           <dict-tag :options="typeOptions" :value="scope.row.type"/>
         </template>
       </el-table-column>
-      <el-table-column label="处理状态" align="center" prop="trackType">
-        <template slot-scope="scope">
-          <dict-tag :options="trackTypeOptions" :value="scope.row.trackType"/>
-        </template>
-      </el-table-column>
+	  <el-table-column label="处理状态" align="center" prop="trackType">
+	    <template slot-scope="scope">
+	      <dict-tag :options="trackTypeOptions" :value="scope.row.trackType"/>
+	    </template>
+	  </el-table-column>
       <el-table-column label="标题" align="center" prop="title" />
       <el-table-column label="描述" align="center" prop="description" />
       <el-table-column label="分值" align="center" prop="score">
@@ -80,32 +103,32 @@
           <span :style="getScoreStyle(scope.row.score)">{{ scope.row.score }}</span>
         </template>
       </el-table-column>
-      <el-table-column label="用户过往看课记录" align="center" width="200px">
-        <template slot-scope="scope">
-          <div style="display: flex; gap: 4px; justify-content: center;" v-if="!isSM">
-			  <span
-          v-for="(log, index) in scope.row.logs"
-          :key="index"
-          :style="{
-				  display: 'inline-block',
-				  width: '16px',
-				  height: '16px',
-				  borderRadius: '2px',
-				  backgroundColor:
-					log === 2 ? '#67C23A' :
-							  log === 3 ? '#f55a4f' :
-							  log === 4 ? '#FFD700' :
-							  log === 1 ? '#0bc6ff' :
-							  '#909399'
-				}"
-        ></span>
-          </div>
-
-          <div style="display: flex; gap: 4px; justify-content: center;" v-if="isSM">
+	  <el-table-column label="用户过往看课记录" align="center" width="200px">
+	    <template slot-scope="scope">
+	    	<div style="display: flex; gap: 4px; justify-content: center;" v-if="!isSM">
+	    	  <span
+	    		v-for="(log, index) in scope.row.logs"
+	    		:key="index"
+	    		:style="{
+	    		  display: 'inline-block',
+	    		  width: '16px',
+	    		  height: '16px',
+	    		  borderRadius: '2px',
+	    		  backgroundColor:
+	    			log === 2 ? '#67C23A' :
+	    					  log === 3 ? '#f55a4f' :
+	    					  log === 4 ? '#FFD700' :
+	    					  log === 1 ? '#0bc6ff' :
+	    					  '#909399'
+	    		}"
+	    	  ></span>
+	    	</div>
+
+	      <div style="display: flex; gap: 4px; justify-content: center;" v-if="isSM">
 	        <span
-            v-for="(log, index) in scope.row.logs"
-            :key="index"
-            :style="{
+	          v-for="(log, index) in scope.row.logs"
+	          :key="index"
+	          :style="{
 	            display: 'inline-block',
 	            width: '16px',
 	            height: '16px',
@@ -115,7 +138,7 @@
 	            position: 'relative',
 	            transform: log === 4 ? 'rotate(45deg)' : 'none'
 	          }"
-          >
+	        >
 	          <!-- 已完成 - 圆形 + 对勾 -->
 	          <span v-if="log === 2" style="
 	            position: absolute;
@@ -128,7 +151,7 @@
 	            transform: translate(-50%, -50%) rotate(-45deg);
 	          "></span>
 
-            <!-- 未完成 - 方框 + 叉 -->
+	          <!-- 未完成 - 方框 + 叉 -->
 	          <span v-if="log === 3" style="
 	            position: absolute;
 	            top: 50%;
@@ -136,7 +159,10 @@
 	            width: 8px;
 	            height: 2px;
 	            background: #666;
-	            transform: translate(-50%, -50%) rotate(45deg);"></span>
+	            transform: translate(-50%, -50%) rotate(45deg);">
+				</span>
+
+
 	          <span v-if="log === 1" style="
 	            position: absolute;
 	            top: 50%;
@@ -147,7 +173,7 @@
 	            transform: translate(-50%, -10%) rotate(-15deg);
 	          "></span>
 
-            <!-- 部分完成 - 菱形 -->
+	          <!-- 部分完成 - 菱形 -->
 	          <span v-if="log === 4" style="
 	            position: absolute;
 	            top: 50%;
@@ -158,7 +184,7 @@
 	            transform: translate(-50%, -50%) rotate(-45deg);
 	          "></span>
 
-            <!-- 未开始 - 减号 -->
+	          <!-- 未开始 - 减号 -->
 	          <span v-if="!log" style="
 	            position: absolute;
 	            top: 50%;
@@ -169,7 +195,7 @@
 	            transform: translate(-50%, -50%);
 	          "></span>
 
-            <!-- 图像 - 使用img标签 -->
+	          <!-- 图像 - 使用img标签 -->
 	          <img v-if="log === 5" src="/path/to/your-image.png" alt="Custom icon" style="
 	            position: absolute;
 	            top: 50%;
@@ -179,39 +205,28 @@
 	            transform: translate(-50%, -50%);
 	          ">
 	        </span>
-          </div>
-        </template>
-      </el-table-column>
-      <el-table-column label="最晚看课时间" align="center">
-        <template slot-scope="scope">
-          {{ formatTime(scope.row.lastWatchTime) }}
-        </template>
-      </el-table-column>
+	      </div>
+	    </template>
+	  </el-table-column>
+	    <el-table-column label="最晚看课时间" align="center">
+	        <template slot-scope="scope">
+	          {{ formatTime(scope.row.lastWatchTime) }}
+	        </template>
+	      </el-table-column>
 
       <el-table-column label="sopId" align="center" prop="sopId" />
-      <el-table-column label="通话时长" align="center" prop="duration" />
       <el-table-column label="创建时间" align="center" prop="createTime" />
       <el-table-column label="修改时间" align="center" prop="updateTime" />
-      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+<!--      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
         <template slot-scope="scope">
           <el-button v-if="scope.row.status==0"
-                     size="mini"
-                     type="text"
-                     icon="el-icon-edit"
-                     @click="handleUpdate(scope.row)"
+            size="mini"
+            type="text"
+            icon="el-icon-edit"
+            @click="handleUpdate(scope.row)"
           >处理</el-button>
-          <el-button v-if="scope.row.status==0"
-                     size="mini"
-                     type="text"
-                     @click="handleUpdate2(scope.row)"
-          >未接通</el-button>
-          <el-button v-if="scope.row.status==0"
-                     size="mini"
-                     type="text"
-                     @click="handleUpdate3(scope.row)"
-          >接通</el-button>
         </template>
-      </el-table-column>
+      </el-table-column> -->
     </el-table>
 
     <pagination
@@ -221,179 +236,167 @@
       :limit.sync="queryParams.pageSize"
       @pagination="getList"
     />
-    <div style="margin-top: 20px; padding: 12px; background: #f8f8f8; border-radius: 4px;" v-if="!isSM">
-      <div style="display: flex; gap: 20px; flex-wrap: wrap;">
-        <div style="display: flex; align-items: center; gap: 8px;">
-          <span style="display: inline-block; width: 16px; height: 16px; border-radius: 2px; background-color: #67C23A;"></span>
-          <span>完课</span>
-        </div>
-        <div style="display: flex; align-items: center; gap: 4px;">
-          <span style="display: inline-block; width: 16px; height: 16px; border-radius: 2px; background-color: #f55a4f;"></span>
-          <span>待看课</span>
-        </div>
-        <div style="display: flex; align-items: center; gap: 4px;">
-          <span style="display: inline-block; width: 16px; height: 16px; border-radius: 2px; background-color: #FFD700;"></span>
-          <span>看课中断</span>
-        </div>
-        <div style="display: flex; align-items: center; gap: 4px;">
-          <span style="display: inline-block; width: 16px; height: 16px; border-radius: 2px; background-color: #909399;"></span>
-          <span>没发课</span>
-        </div>
-        <div style="display: flex; align-items: center; gap: 4px;">
-          <span style="display: inline-block; width: 16px; height: 16px; border-radius: 2px; background-color: #0bc6ff;"></span>
-          <span>看课中</span>
-        </div>
-      </div>
-    </div>
-
-    <!-- 新增的解释说明区域 -->
-    <div style="margin-top: 20px; padding: 12px; background: #f8f8f8; border-radius: 4px;" v-if="isSM">
-      <div style="display: flex; gap: 20px; flex-wrap: wrap;">
-        <div style="display: flex; align-items: center; gap: 8px;">
-	            <span style="
-	              display: inline-block;
-	              width: 16px;
-	              height: 16px;
-	              border-radius: 50%;
-	              background-color: #f0f0f0;
-	              position: relative;
-	            ">
-	              <span style="
-	                position: absolute;
-	                top: 45%;
-	                left: 50%;
-	                width: 6px;
-	                height: 3px;
-	                border: solid #333;
-	                border-width: 0 0 2px 2px;
-	                transform: translate(-50%, -50%) rotate(-45deg);
-	              "></span>
-	            </span>
-          <span>完课</span>
-        </div>
-
-        <div style="display: flex; align-items: center; gap: 8px;">
-	            <span style="
-	              display: inline-block;
-	              width: 16px;
-	              height: 16px;
-	              border-radius: 2px;
-	              border: 2px solid #666;
-	              background-color: transparent;
-	              position: relative;
-	            ">
-	              <span style="
-	                position: absolute;
-	                top: 50%;
-	                left: 50%;
-	                width: 8px;
-	                height: 2px;
-	                background: #666;
-	                transform: translate(-50%, -50%) rotate(45deg);
-	              "></span>
-	              <span style="
-	                position: absolute;
-	                top: 50%;
-	                left: 50%;
-	                width: 8px;
-	                height: 2px;
-	                background: #666;
-	                transform: translate(-50%, -50%) rotate(-45deg);
-	              "></span>
-	            </span>
-          <span>待看课</span>
-        </div>
-
-        <div style="display: flex; align-items: center; gap: 8px;">
-	            <span style="
-	              display: inline-block;
-	              width: 16px;
-	              height: 16px;
-	              border-radius: 2px 8px;
-	              background-color: #f0f0f0;
-	              border: 1px solid #ddd;
-	              position: relative;
-	              transform: rotate(45deg);
-	            ">
-	              <span style="
-	                position: absolute;
-	                top: 50%;
-	                left: 50%;
-	                width: 6px;
-	                height: 6px;
-	                border: 2px solid #333;
-	                transform: translate(-50%, -50%) rotate(-45deg);
-	              "></span>
-	            </span>
-          <span>看课中断</span>
-        </div>
-
-        <div style="display: flex; align-items: center; gap: 8px;">
-	            <span style="
-	              display: inline-block;
-	              width: 16px;
-	              height: 16px;
-	              border-radius: 2px;
-	              background-color: #f0f0f0;
-	              border: 1px solid #ddd;
-	              position: relative;
-	            ">
-	              <span style="
-	                position: absolute;
-	                top: 50%;
-	                left: 50%;
-	                width: 8px;
-	                height: 2px;
-	                background: #999;
-	                transform: translate(-50%, -50%);
-	              "></span>
-	            </span>
-          <span>没发课</span>
-        </div>
-
-        <div style="display: flex; align-items: center; gap: 8px;">
-			    <span style="
-			      display: inline-block;
-			      width: 16px;
-			      height: 16px;
-			      border-radius: 2px;
-			      background-color: #f0f0f0;
-			      border: 1px solid #ddd;
-			      position: relative;
-			    ">
-			      <span  style="
-			        position: absolute;
-			        top: 50%;
-			        left: 50%;
-			        width: 8px;
-			        height: 2px;
-			        background: #666;
-			        transform: translate(-50%, -10%) rotate(-15deg);
-			      "></span>
-			    </span>
-          <span>看课中</span>
-        </div>
-
-
-      </div>
-    </div>
-
-
+	<div style="margin-top: 20px; padding: 12px; background: #f8f8f8; border-radius: 4px;" v-if="!isSM">
+	  <div style="display: flex; gap: 20px; flex-wrap: wrap;">
+	    <div style="display: flex; align-items: center; gap: 8px;">
+	      <span style="display: inline-block; width: 16px; height: 16px; border-radius: 2px; background-color: #67C23A;"></span>
+	      <span>完课</span>
+	    </div>
+	    <div style="display: flex; align-items: center; gap: 4px;">
+	      <span style="display: inline-block; width: 16px; height: 16px; border-radius: 2px; background-color: #f55a4f;"></span>
+	      <span>待看课</span>
+	    </div>
+	    <div style="display: flex; align-items: center; gap: 4px;">
+	      <span style="display: inline-block; width: 16px; height: 16px; border-radius: 2px; background-color: #FFD700;"></span>
+	      <span>看课中断</span>
+	    </div>
+	    <div style="display: flex; align-items: center; gap: 4px;">
+	      <span style="display: inline-block; width: 16px; height: 16px; border-radius: 2px; background-color: #909399;"></span>
+	      <span>没发课</span>
+	    </div>
+		<div style="display: flex; align-items: center; gap: 4px;">
+		  <span style="display: inline-block; width: 16px; height: 16px; border-radius: 2px; background-color: #0bc6ff;"></span>
+		  <span>看课中</span>
+		</div>
+	  </div>
+	</div>
+
+	<!-- 新增的解释说明区域 -->
+	<div style="margin-top: 20px; padding: 12px; background: #f8f8f8; border-radius: 4px;" v-if="isSM">
+	    <div style="display: flex; gap: 20px; flex-wrap: wrap;">
+	      <div style="display: flex; align-items: center; gap: 8px;">
+	        <span style="
+	          display: inline-block;
+	          width: 16px;
+	          height: 16px;
+	          border-radius: 50%;
+	          background-color: #f0f0f0;
+	          position: relative;
+	        ">
+	          <span style="
+	            position: absolute;
+	            top: 45%;
+	            left: 50%;
+	            width: 6px;
+	            height: 3px;
+	            border: solid #333;
+	            border-width: 0 0 2px 2px;
+	            transform: translate(-50%, -50%) rotate(-45deg);
+	          "></span>
+	        </span>
+	        <span>完课</span>
+	      </div>
+
+	      <div style="display: flex; align-items: center; gap: 8px;">
+	        <span style="
+	          display: inline-block;
+	          width: 16px;
+	          height: 16px;
+	          border-radius: 2px;
+	          border: 2px solid #666;
+	          background-color: transparent;
+	          position: relative;
+	        ">
+	          <span style="
+	            position: absolute;
+	            top: 50%;
+	            left: 50%;
+	            width: 8px;
+	            height: 2px;
+	            background: #666;
+	            transform: translate(-50%, -50%) rotate(45deg);
+	          "></span>
+	          <span style="
+	            position: absolute;
+	            top: 50%;
+	            left: 50%;
+	            width: 8px;
+	            height: 2px;
+	            background: #666;
+	            transform: translate(-50%, -50%) rotate(-45deg);
+	          "></span>
+	        </span>
+	        <span>待看课</span>
+	      </div>
+
+	      <div style="display: flex; align-items: center; gap: 8px;">
+	        <span style="
+	          display: inline-block;
+	          width: 16px;
+	          height: 16px;
+	          border-radius: 2px 8px;
+	          background-color: #f0f0f0;
+	          border: 1px solid #ddd;
+	          position: relative;
+	          transform: rotate(45deg);
+	        ">
+	          <span style="
+	            position: absolute;
+	            top: 50%;
+	            left: 50%;
+	            width: 6px;
+	            height: 6px;
+	            border: 2px solid #333;
+	            transform: translate(-50%, -50%) rotate(-45deg);
+	          "></span>
+	        </span>
+	        <span>看课中断</span>
+	      </div>
+
+	      <div style="display: flex; align-items: center; gap: 8px;">
+	        <span style="
+	          display: inline-block;
+	          width: 16px;
+	          height: 16px;
+	          border-radius: 2px;
+	          background-color: #f0f0f0;
+	          border: 1px solid #ddd;
+	          position: relative;
+	        ">
+	          <span style="
+	            position: absolute;
+	            top: 50%;
+	            left: 50%;
+	            width: 8px;
+	            height: 2px;
+	            background: #999;
+	            transform: translate(-50%, -50%);
+	          "></span>
+	        </span>
+	        <span>没发课</span>
+	      </div>
+
+		  <div style="display: flex; align-items: center; gap: 8px;">
+		    <span style="
+		      display: inline-block;
+		      width: 16px;
+		      height: 16px;
+		      border-radius: 2px;
+		      background-color: #f0f0f0;
+		      border: 1px solid #ddd;
+		      position: relative;
+		    ">
+		      <span  style="
+		        position: absolute;
+		        top: 50%;
+		        left: 50%;
+		        width: 8px;
+		        height: 2px;
+		        background: #666;
+		        transform: translate(-50%, -10%) rotate(-15deg);
+		      "></span>
+		    </span>
+		    <span>看课中</span>
+		  </div>
+
+
+	    </div>
+	  </div>
     <!-- 添加或修改企微任务看板对话框 -->
     <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
       <el-form ref="form" :model="form" :rules="rules" label-width="80px">
-        <el-form-item label="处理类型" prop="trackType">
-          <el-select v-model="form.trackType" placeholder="状态" clearable size="small">
-            <el-option
-              v-for="dict in trackTypeOptions"
-              :key="dict.dictValue"
-              :label="dict.dictLabel"
-              :value="dict.dictValue"
-            />
-          </el-select>
-        </el-form-item>
-        <el-form-item label="描述" prop="description">
-          <el-input  v-model="form.description" placeholder="请输入描述"  type="textarea" :rows="3"/>
+        <el-form-item label="备注" prop="remark">
+          <el-input  v-model="form.remark" placeholder="请输入备注"  type="textarea" :rows="3"/>
         </el-form-item>
       </el-form>
       <div slot="footer" class="dialog-footer">
@@ -407,19 +410,34 @@
 <script>
 import { listQwWorkTask, getQwWorkTask, delQwWorkTask, addQwWorkTask, updateQwWorkTask, exportQwWorkTask,updateQwWorkTask2,updateQwWorkTask3 } from "@/api/qw/QwWorkTask";
 import {getMyQwUserList, getMyQwCompanyList, handleInputAuthAppKey, updateUser} from "@/api/qw/user";
+import { treeselect } from "@/api/company/companyDept";
+import Treeselect from "@riophae/vue-treeselect";
+import "@riophae/vue-treeselect/dist/vue-treeselect.css";
+import { getCompanyUserListLikeName } from "@/api/company/companyUser";
 export default {
   name: "QwWorkTask",
+  components: { Treeselect  },
   data() {
     return {
-      actName:"0",
+	  actName:"0",
       // 遮罩层
       loading: true,
       // 导出遮罩层
       exportLoading: false,
+	  companyUserOptionsParams: {
+	    name: undefined,
+	    hasNextPage: false,
+	    pageNum: 1,
+	    pageSize: 10
+	  },
+	  isSM:false,
+
+	  companyUserOptionsLoading: false,
+	  companyUserOptions: [],
       // 选中数组
       ids: [],
-      isSM:false,
-      myQwUserList:[],
+	  deptOptions:[],
+	  myQwUserList:[],
       // 非单个禁用
       single: true,
       // 非多个禁用
@@ -436,9 +454,9 @@ export default {
       open: false,
       // 状态 0 待处理 1 已处理 3 过期字典
       statusOptions: [],
-      trackTypeOptions:[],
-      // 类别 1先导 2 课程 3 大小转 4 转人工字典
+      // 类别 1先导 2 课程 3 节点 4 转人工字典
       typeOptions: [],
+	  trackTypeOptions:[],
       // 查询参数
       queryParams: {
         pageNum: 1,
@@ -457,59 +475,92 @@ export default {
       form: {},
       // 表单校验
       rules: {
-        trackType: [
-          { required: true, message: '请选择处理类型', trigger: 'change' }
-        ]
       }
     };
   },
   created() {
-    this.handleGetMyQwUserList();
+	this.handleGetMyQwUserList();
     this.getDicts("sys_qw_work_task_status").then(response => {
       this.statusOptions = response.data;
     });
     this.getDicts("sys_qw_work_task_type").then(response => {
       this.typeOptions = response.data;
     });
-    this.getDicts("sys_qw_work_task_track_type").then(response => {
-      this.trackTypeOptions = response.data;
-    });
-
-
+	this.getDicts("sys_qw_work_task_track_type").then(response => {
+	  this.trackTypeOptions = response.data;
+	});
+	this.getTreeselect();
   },
   methods: {
-    getScoreStyle(score) {
-      let backgroundColor = '';
-      if (score >= 15) {
-        backgroundColor = '#ff4d4f';    // 红色
-      } else if (score >= 9) {
-        backgroundColor = '#ff7d45';    // 橘红
-      } else if (score >= 4) {
-        backgroundColor = '#ffec3d';    // 黄色
-      } else {
-        backgroundColor = '#ffffff';    // 白色
-      }
-      return {
-        'background-color': backgroundColor,
-        'padding': '5px 10px',
-        'border-radius': '4px'
-      };
-    },
-    formatTime(timeStr) {
-      if (!timeStr && timeStr !== 0) return '';
-
-      // 处理数字和字符串输入
-      const str = String(timeStr).padStart(4, '0');
-
-      // 提取有效部分
-      const hours = str.substring(0, 2);
-      const minutes = str.substring(2, 4);
-
-      // 简单验证
-      if (hours > 23 || minutes > 59) return '无效时间';
-
-      return `${hours}:${minutes}`;
-    },
+	getScoreStyle(score) {
+	let backgroundColor = '';
+	  if (score >= 15) {
+		backgroundColor = '#ff4d4f';    // 红色
+	  } else if (score >= 9) {
+		backgroundColor = '#ff7d45';    // 橘红
+	  } else if (score >= 4) {
+		backgroundColor = '#ffec3d';    // 黄色
+	  } else {
+		backgroundColor = '#ffffff';    // 白色
+	  }
+	  return {
+		'background-color': backgroundColor,
+		'padding': '5px 10px',
+		'border-radius': '4px'
+	  };
+	},
+	getTreeselect() {
+	  var that=this;
+	  var param={companyId:this.companyId}
+	  treeselect(param).then((response) => {
+	    this.deptOptions = response.data;
+	    console.log(this.deptOptions)
+	    if(response.data!=null&&response.data.length>0){
+	      //this.queryParams.deptId=response.data[0].id;
+	    }
+	  });
+	},
+	loadCompanyUserOptions(query) {
+	  this.companyUserOptions = [];
+	  if (query === '') {
+	    return;
+	  }
+
+	  this.companyUserOptionsParams.pageNum = 1
+	  this.companyUserOptionsParams.name = query
+	  this.companyUserOptionsLoading = true;
+	  this.getCompanyUserListLikeName()
+	},
+	getCompanyUserListLikeName() {
+	  getCompanyUserListLikeName(this.companyUserOptionsParams).then(response => {
+	    this.companyUserOptions = [...this.companyUserOptions, ...response.data.list]
+	    this.companyUserOptionsParams.hasNextPage = response.data.hasNextPage
+	    this.companyUserOptionsLoading = false;
+	  });
+	},
+	loadMoreCompanyUserOptions() {
+	  if (!this.companyUserOptionsParams.hasNextPage) {
+	    return;
+	  }
+
+	  this.companyUserOptionsParams.pageNum += 1
+	  this.getCompanyUserListLikeName()
+	},
+	formatTime(timeStr) {
+	      if (!timeStr && timeStr !== 0) return '';
+
+	      // 处理数字和字符串输入
+	      const str = String(timeStr).padStart(4, '0');
+
+	      // 提取有效部分
+	      const hours = str.substring(0, 2);
+	      const minutes = str.substring(2, 4);
+
+	      // 简单验证
+	      if (hours > 23 || minutes > 59) return '无效时间';
+
+	      return `${hours}:${minutes}`;
+	    },
     /** 查询企微任务看板列表 */
     getList() {
       this.loading = true;
@@ -519,13 +570,13 @@ export default {
         this.loading = false;
       });
     },
-    sm(){
-      this.isSM = this.isSM ? false : true;
-    },
-    handleClickX(tab, event) {
-      this.queryParams.status=tab.name;
-      this.handleQuery();
-    },
+	handleClickX(tab, event) {
+	  this.queryParams.status=tab.name;
+	  this.handleQuery();
+	},
+	sm(){
+		this.isSM = this.isSM ? false : true;
+	},
     // 取消按钮
     cancel() {
       this.open = false;
@@ -555,18 +606,10 @@ export default {
       this.queryParams.pageNum = 1;
       this.getList();
     },
-    handleGetMyQwUserList(){
+	handleGetMyQwUserList(){
 
-      getMyQwUserList().then(response => {
-        this.myQwUserList = response.data;
-        if(this.myQwUserList!=null){
-          this.queryParams.qwUserId=this.myQwUserList[0].dictValue
-          this.queryParams.corpId=this.myQwUserList[0].corpId
-          this.getList();
-        }
-      });
-
-    },
+		this.getList();
+	},
     /** 重置按钮操作 */
     resetQuery() {
       this.resetForm("queryForm");
@@ -588,29 +631,11 @@ export default {
     handleUpdate(row) {
       this.reset();
       const id = row.id || this.ids
-      this.form = row;
-      this.open = true;
-      this.title = "处理任务";
+        this.form = row;
+        this.open = true;
+        this.title = "处理任务";
 
     },
-
-    handleUpdate2(row) {
-      var from={id:row.id }
-      updateQwWorkTask2(from).then(response => {
-        this.msgSuccess("修改成功");
-
-        this.getList();
-      });
-
-    },
-    handleUpdate3(row) {
-      var from={id:row.id }
-      updateQwWorkTask3(from).then(response => {
-        this.msgSuccess("修改成功");
-
-        this.getList();
-      });
-    },
     /** 提交按钮 */
     submitForm() {
       this.$refs["form"].validate(valid => {
@@ -635,30 +660,30 @@ export default {
     handleDelete(row) {
       const ids = row.id || this.ids;
       this.$confirm('是否确认删除企微任务看板编号为"' + ids + '"的数据项?', "警告", {
-        confirmButtonText: "确定",
-        cancelButtonText: "取消",
-        type: "warning"
-      }).then(function() {
-        return delQwWorkTask(ids);
-      }).then(() => {
-        this.getList();
-        this.msgSuccess("删除成功");
-      }).catch(() => {});
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        }).then(function() {
+          return delQwWorkTask(ids);
+        }).then(() => {
+          this.getList();
+          this.msgSuccess("删除成功");
+        }).catch(() => {});
     },
     /** 导出按钮操作 */
     handleExport() {
       const queryParams = this.queryParams;
       this.$confirm('是否确认导出所有企微任务看板数据项?', "警告", {
-        confirmButtonText: "确定",
-        cancelButtonText: "取消",
-        type: "warning"
-      }).then(() => {
-        this.exportLoading = true;
-        return exportQwWorkTask(queryParams);
-      }).then(response => {
-        this.download(response.msg);
-        this.exportLoading = false;
-      }).catch(() => {});
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        }).then(() => {
+          this.exportLoading = true;
+          return exportQwWorkTask(queryParams);
+        }).then(response => {
+          this.download(response.msg);
+          this.exportLoading = false;
+        }).catch(() => {});
     }
   }
 };

+ 4 - 4
src/views/qw/qwUserDelLossStatistics/index.vue

@@ -36,7 +36,7 @@
         <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
       </el-form-item>
     </el-form>
-    <!-- <el-row :gutter="10" class="mb8">
+    <el-row :gutter="10" class="mb8">
       <el-col :span="1.5">
         <el-button
           type="warning"
@@ -49,7 +49,7 @@
         >导出</el-button>
       </el-col>
       <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
-    </el-row> -->
+    </el-row>
     
     
     <el-table v-loading="loading" :data="externalContactList" @selection-change="handleSelectionChange" border>
@@ -69,7 +69,7 @@
 </template>
 
 <script>
-import { exportExternalContact, delLossStatistics } from "@/api/qw/externalContact";
+import { delLossStatisticsExport, delLossStatistics } from "@/api/qw/externalContact";
 export default {
   name: "ExternalContact",
   data() {
@@ -153,7 +153,7 @@ export default {
           type: "warning"
         }).then(() => {
           this.exportLoading = true;
-          return exportExternalContact(queryParams);
+          return delLossStatisticsExport(queryParams);
         }).then(response => {
           this.download(response.msg);
           this.exportLoading = false;

+ 148 - 133
src/views/qw/qwUserVoiceLogTotal/index.vue

@@ -1,16 +1,18 @@
 <template>
   <div class="app-container">
     <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="148px">
-<!--      <el-form-item label="外部联系人名称" prop="extName">
-        <el-input
-          v-model="queryParams.extName"
-          placeholder="请输入外部联系人名称"
+      <el-form-item label="部门" prop="type">
+        <treeselect
+          style="width: 220px"
+          :clearable="false"
+          v-model="queryParams.deptId"
+          :options="deptOptions"
           clearable
-          size="small"
-          @keyup.enter.native="handleQuery"
+          :show-count="true"
+          placeholder="请选择归属部门"
         />
-      </el-form-item>-->
-      <el-form-item label="所属销售" prop="companyUserId">
+      </el-form-item>
+      <el-form-item label="所属客服" prop="companyUserId">
         <el-select v-model="queryParams.companyUserId" clearable filterable remote
                    placeholder="请输入关键词" :remote-method="loadCompanyUserOptions"
                    v-select-load-more="loadMoreCompanyUserOptions"
@@ -32,53 +34,53 @@
           @keyup.enter.native="handleQuery"
         />
       </el-form-item>
-<!--      <el-form-item label="标题" prop="title">
-        <el-input
-          v-model="queryParams.title"
-          placeholder="请输入标题"
-          clearable
-          size="small"
-          @keyup.enter.native="handleQuery"
-        />
-      </el-form-item>-->
-<!--      <el-form-item label="通话状态" prop="status">
-        <el-select v-model="queryParams.status" placeholder="请选择通话状态" clearable size="small">
-          <el-option
-            v-for="dict in statusOptions"
-            :key="dict.dictValue"
-            :label="dict.dictLabel"
-            :value="dict.dictValue"
-          />
-        </el-select>
-      </el-form-item>-->
-<!--      <el-form-item label="企微id" prop="corpId">
-        <el-input
-          v-model="queryParams.corpId"
-          placeholder="请输入企微id"
-          clearable
-          size="small"
-          @keyup.enter.native="handleQuery"
-        />
-      </el-form-item>-->
-<!--      <el-form-item label="公司名称" prop="companyName">
-        <el-input
-          v-model="queryParams.companyName"
-          placeholder="请输入公司名称"
-          clearable
-          size="small"
-          @keyup.enter.native="handleQuery"
-        />
-      </el-form-item>-->
+      <!--      <el-form-item label="标题" prop="title">
+              <el-input
+                v-model="queryParams.title"
+                placeholder="请输入标题"
+                clearable
+                size="small"
+                @keyup.enter.native="handleQuery"
+              />
+            </el-form-item>-->
+      <!--      <el-form-item label="通话状态" prop="status">
+              <el-select v-model="queryParams.status" placeholder="请选择通话状态" clearable size="small">
+                <el-option
+                  v-for="dict in statusOptions"
+                  :key="dict.dictValue"
+                  :label="dict.dictLabel"
+                  :value="dict.dictValue"
+                />
+              </el-select>
+            </el-form-item>-->
+      <!--      <el-form-item label="企微id" prop="corpId">
+              <el-input
+                v-model="queryParams.corpId"
+                placeholder="请输入企微id"
+                clearable
+                size="small"
+                @keyup.enter.native="handleQuery"
+              />
+            </el-form-item>-->
+      <!--      <el-form-item label="公司名称" prop="companyName">
+              <el-input
+                v-model="queryParams.companyName"
+                placeholder="请输入公司名称"
+                clearable
+                size="small"
+                @keyup.enter.native="handleQuery"
+              />
+            </el-form-item>-->
 
-<!--      <el-form-item label="时长秒" prop="duration">
-        <el-input
-          v-model="queryParams.duration"
-          placeholder="请输入时长秒"
-          clearable
-          size="small"
-          @keyup.enter.native="handleQuery"
-        />
-      </el-form-item>-->
+      <!--      <el-form-item label="时长秒" prop="duration">
+              <el-input
+                v-model="queryParams.duration"
+                placeholder="请输入时长秒"
+                clearable
+                size="small"
+                @keyup.enter.native="handleQuery"
+              />
+            </el-form-item>-->
       <el-form-item label="创建时间" prop="createTime">
         <el-date-picker v-model="createTime" size="small" style="width: 220px"
                         value-format="yyyy-MM-dd" type="daterange" range-separator="-"
@@ -94,38 +96,38 @@
     </el-form>
 
     <el-row :gutter="10" class="mb8">
-<!--      <el-col :span="1.5">
-        <el-button
-          type="primary"
-          plain
-          icon="el-icon-plus"
-          size="mini"
-          @click="handleAdd"
-          v-hasPermi="['qw:qwUserVoiceLog:add']"
-        >新增</el-button>
-      </el-col>
-      <el-col :span="1.5">
-        <el-button
-          type="success"
-          plain
-          icon="el-icon-edit"
-          size="mini"
-          :disabled="single"
-          @click="handleUpdate"
-          v-hasPermi="['qw:qwUserVoiceLog:edit']"
-        >修改</el-button>
-      </el-col>
-      <el-col :span="1.5">
-        <el-button
-          type="danger"
-          plain
-          icon="el-icon-delete"
-          size="mini"
-          :disabled="multiple"
-          @click="handleDelete"
-          v-hasPermi="['qw:qwUserVoiceLog:remove']"
-        >删除</el-button>
-      </el-col>-->
+      <!--      <el-col :span="1.5">
+              <el-button
+                type="primary"
+                plain
+                icon="el-icon-plus"
+                size="mini"
+                @click="handleAdd"
+                v-hasPermi="['qw:qwUserVoiceLog:add']"
+              >新增</el-button>
+            </el-col>
+            <el-col :span="1.5">
+              <el-button
+                type="success"
+                plain
+                icon="el-icon-edit"
+                size="mini"
+                :disabled="single"
+                @click="handleUpdate"
+                v-hasPermi="['qw:qwUserVoiceLog:edit']"
+              >修改</el-button>
+            </el-col>
+            <el-col :span="1.5">
+              <el-button
+                type="danger"
+                plain
+                icon="el-icon-delete"
+                size="mini"
+                :disabled="multiple"
+                @click="handleDelete"
+                v-hasPermi="['qw:qwUserVoiceLog:remove']"
+              >删除</el-button>
+            </el-col>-->
       <el-col :span="1.5">
         <el-button
           type="warning"
@@ -143,7 +145,7 @@
           plain
           size="mini"
           @click="getSellList"
-        >切换到销售统计</el-button>
+        >切换到客服统计</el-button>
       </el-col>
 
       <el-col :span="1.5">
@@ -160,42 +162,42 @@
 
     <el-table border v-loading="loading" :data="qwUserVoiceLogList" @selection-change="handleSelectionChange">
       <el-table-column type="selection" width="55" align="center" />
-<!--      <el-table-column label="id" align="center" width="80" prop="id" />-->
-<!--      <el-table-column label="外部联系人名称" align="center" prop="qwExternalContact.name" />-->
-      <el-table-column label="销售名称" align="center" prop="companyUserName" />
+      <!--      <el-table-column label="id" align="center" width="80" prop="id" />-->
+      <!--      <el-table-column label="外部联系人名称" align="center" prop="qwExternalContact.name" />-->
+      <el-table-column label="客服名称" align="center" prop="companyUserName" />
       <el-table-column label="企微用户名称" align="center" prop="qwUser.qwUserName" />
       <el-table-column label="企微主体名称" align="center" prop="corpName" />
       <el-table-column label="企微用户id" align="center" prop="qwUser.qwUserId" />
       <el-table-column label="时长秒" align="center"  prop="duration" />
       <el-table-column label="接通数量" align="center"  prop="connectCount" />
       <el-table-column label="未接通数量" align="center"  prop="noConnectCount" />
-<!--      <el-table-column label="标题" align="center" width="80" prop="title" />-->
-<!--      <el-table-column label="通话状态" align="center" prop="status">
-        <template slot-scope="scope">
-          <dict-tag :options="statusOptions" :value="scope.row.status"/>
-        </template>
-      </el-table-column>-->
+      <!--      <el-table-column label="标题" align="center" width="80" prop="title" />-->
+      <!--      <el-table-column label="通话状态" align="center" prop="status">
+              <template slot-scope="scope">
+                <dict-tag :options="statusOptions" :value="scope.row.status"/>
+              </template>
+            </el-table-column>-->
       <!--<el-table-column label="公司名称" align="center" prop="company.companyName" />
-      <el-table-column label="销售用户名称" align="center" prop="companyUser.userName" />
+      <el-table-column label="客服用户名称" align="center" prop="companyUser.userName" />
       <el-table-column label="创建时间" align="center" prop="createTime" />-->
-<!--      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
-        <template slot-scope="scope">
-          <el-button
-            size="mini"
-            type="text"
-            icon="el-icon-edit"
-            @click="handleUpdate(scope.row)"
-            v-hasPermi="['qw:qwUserVoiceLog:edit']"
-          >修改</el-button>
-          <el-button
-            size="mini"
-            type="text"
-            icon="el-icon-delete"
-            @click="handleDelete(scope.row)"
-            v-hasPermi="['qw:qwUserVoiceLog:remove']"
-          >删除</el-button>
-        </template>
-      </el-table-column>-->
+      <!--      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+              <template slot-scope="scope">
+                <el-button
+                  size="mini"
+                  type="text"
+                  icon="el-icon-edit"
+                  @click="handleUpdate(scope.row)"
+                  v-hasPermi="['qw:qwUserVoiceLog:edit']"
+                >修改</el-button>
+                <el-button
+                  size="mini"
+                  type="text"
+                  icon="el-icon-delete"
+                  @click="handleDelete(scope.row)"
+                  v-hasPermi="['qw:qwUserVoiceLog:remove']"
+                >删除</el-button>
+              </template>
+            </el-table-column>-->
     </el-table>
 
     <pagination
@@ -212,9 +214,13 @@
 import { listQwUserVoiceLog, getQwUserVoiceLog, delQwUserVoiceLog, addQwUserVoiceLog, updateQwUserVoiceLog, exportQwUserVoiceLog } from "@/api/qw/qwUserVoiceLog";
 import {listQwUserVoiceLogTotal,exportQwUserVoiceLogTotal,listQwUserVoiceLogSellTotal,exportQwUserVoiceLogSellTotal} from "@/api/qw/qwUserVoiceLogTotal";
 import {getCompanyUserListLikeName} from "@/api/company/companyUser";
+import Treeselect from "@riophae/vue-treeselect";
+import "@riophae/vue-treeselect/dist/vue-treeselect.css";
+import {treeselect} from "../../../api/company/companyDept";
 
 export default {
   name: "QwUserVoiceLog",
+  components: {Treeselect},
   data() {
     return {
       // 遮罩层
@@ -238,6 +244,7 @@ export default {
       total: 0,
       // 企微用户通话记录表格数据
       qwUserVoiceLogList: [],
+      deptOptions: [],
       // 弹出层标题
       title: "",
       // 是否显示弹出层
@@ -280,6 +287,7 @@ export default {
     };
   },
   created() {
+    this.getDeptTreeSelect();
     this.handlePagination();
     this.getDicts("sys_qw_user_voice_status").then(response => {
       this.statusOptions = response.data;
@@ -296,6 +304,12 @@ export default {
         this.loading = false;
       });
     },
+
+    getDeptTreeSelect() {
+      treeselect().then((response) => {
+        this.deptOptions = response.data;
+      });
+    },
     getSellList() {
       this.loading = true;
       this.status = 1;
@@ -375,6 +389,7 @@ export default {
         createTime: null,
         beginTime:null,
         endTime:null,
+        deptOption:null,
       };
       this.resetForm("form");
     },
@@ -437,35 +452,35 @@ export default {
     handleDelete(row) {
       const ids = row.id || this.ids;
       this.$confirm('是否确认删除企微用户通话记录编号为"' + ids + '"的数据项?', "警告", {
-          confirmButtonText: "确定",
-          cancelButtonText: "取消",
-          type: "warning"
-        }).then(function() {
-          return delQwUserVoiceLog(ids);
-        }).then(() => {
-          this.handlePagination();
-          this.msgSuccess("删除成功");
-        }).catch(() => {});
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      }).then(function() {
+        return delQwUserVoiceLog(ids);
+      }).then(() => {
+        this.handlePagination();
+        this.msgSuccess("删除成功");
+      }).catch(() => {});
     },
     /** 导出按钮操作 */
     handleExport() {
       const queryParams = this.queryParams;
       this.$confirm('是否确认导出所有企微用户通话记录数据项?', "警告", {
-          confirmButtonText: "确定",
-          cancelButtonText: "取消",
-          type: "warning"
-        }).then(() => {
-          this.exportLoading = true;
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      }).then(() => {
+        this.exportLoading = true;
         if(this.status === 0){
           return exportQwUserVoiceLogTotal(queryParams);
         }else{
           return exportQwUserVoiceLogSellTotal(queryParams);
         }
 
-        }).then(response => {
-          this.download(response.msg);
-          this.exportLoading = false;
-        }).catch(() => {});
+      }).then(response => {
+        this.download(response.msg);
+        this.exportLoading = false;
+      }).catch(() => {});
     }
   }
 };

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

@@ -34,7 +34,7 @@
 <!--            >群聊-->
 <!--            </el-radio>-->
           </el-radio-group>
-          <Tip :title="'标签:根据企微客户的标签筛选客户进入SOP\r\n群聊:选择企微用户所属的群聊,并且只能选择课程模板,课程模板里面第一条规则是发送到群聊,其他规则催课会发送到群里面的个人'" />
+          <Tip :title="'标签:根据企微客户的标签筛选客户进入SOP'" />
         </el-form-item>
         <el-form-item label="小转天数" prop="minConversionDay" v-if="form.filterMode == 1">
           <!--          <el-input class="el-input" type="" v-model="form.minConversionDay" placeholder="请输入" />-->

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

@@ -128,6 +128,18 @@
         >批量执行SOP
         </el-button>
       </el-col>
+      <el-col :span="1.5">
+        <el-tooltip class="item" effect="dark" content="此功能用于给 选中的 SOP任务营期 内【所有的】客户发送 消息【或者发送草稿-/-清楚草稿】" placement="top">
+          <el-button
+            type="warning"
+            icon="el-icon-s-promotion"
+            size="mini"
+            :disabled="multiple"
+            @click="handleCampSendMsg"
+            v-hasPermi="['qw:sopUserLogsInfo:msg']"
+          >SOP营期一键群发(或草稿)</el-button>
+        </el-tooltip>
+      </el-col>
       <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
     </el-row>
     <el-table v-loading="loading" border :data="sopList" @selection-change="handleSelectionChange">
@@ -313,6 +325,7 @@
       @pagination="getList"
     />
 
+    <send-msg-sop-open-tool ref="sendMsgSopOpenTool" ></send-msg-sop-open-tool>
     <!-- 添加或修改企微sop对话框 -->
     <el-dialog :title="title" :visible.sync="open" width="1000px" append-to-body>
       <el-form ref="form" :model="form" :rules="rules" label-width="100px">
@@ -873,10 +886,11 @@ import sopLogsDetails from '@/views/qw/sopLogs/sopLogsList.vue'
 import {listTag,} from "@/api/qw/tag";
 import {getMyQwCompanyList} from "@/api/qw/user";
 import {allList} from "@/api/qw/groupChat";
+import SendMsgSopOpenTool from '@/views/qw/sopUserLogsInfo/sendMsgSopOpenTool.vue'
 
 export default {
   name: "Sop",
-  components: {CustomerGroupDetails, qwUserList, ImageUpload, sopLogsDetails},
+  components: {CustomerGroupDetails, qwUserList, ImageUpload, sopLogsDetails, SendMsgSopOpenTool},
   data() {
     return {
       // 存储每一行的展开状态
@@ -1071,6 +1085,16 @@ export default {
     }
   },
   methods: {
+    /**
+     * SOP任务营期一键群发
+     */
+    handleCampSendMsg(){
+
+      setTimeout(() => {
+        this.$refs.sendMsgSopOpenTool.oneClickGroupSending(this.ids,2,this.queryParams.corpId);
+      }, 500);
+
+    },
     voice(id) {
       this.voiceForm.queryParams.id = id;
       getSopVoiceList(this.voiceForm.queryParams).then(res => {

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

@@ -588,7 +588,6 @@ export default {
     //删除员工
     handleClosegroupUser(id){
       // const index = this.userSelectList.findIndex(t => t === list);
-      console.log(id)
       // if (index !== -1) {
       //   this.userSelectList.splice(index, 1);
       // }

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

@@ -176,6 +176,7 @@
                 <span v-if="item.contentType == 6">视频</span>
                 <span v-if="item.contentType == 7">语音</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>
               </div>
               <div v-if="item.sendStatus">
@@ -209,7 +210,7 @@
                 </div>
               </div>
             </div>
-            <div v-if="item.contentType == 4" class="message-style">
+            <div v-if="item.contentType == 4 || item.contentType == 10" class="message-style">
                 <div style="display: flex; justify-content: space-between; width: 100%">
                   <span style="font-size: 13px; flex: 1">{{ item.miniprogramTitle }}</span>
                   <el-image

+ 14 - 9
src/views/qw/sopTemp/addSopTemp.vue

@@ -178,7 +178,7 @@
                                             </el-card>
                                           </div>
 
-                                          <div v-if="setList.contentType == 4">
+                                          <div v-if="setList.contentType == 4 || setList.contentType == 10 ">
                                             <el-card class="box-card">
                                               <el-form-item label="标题" prop="miniprogramTitle">
                                                 <el-input v-model="setList.miniprogramTitle" placeholder="请输入小程序消息标题,最长为64字"  />
@@ -189,8 +189,8 @@
                                               <el-form-item label="appid" prop="miniprogramAppid" v-show="false" >
                                                 <el-input v-model="setList.miniprogramAppid='wx73f85f8d62769119' " disabled />
                                               </el-form-item>
-                                              <el-form-item label="page路径" prop="miniprogramPage" v-show="false" label-width="100px" style="margin-left: -30px">
-                                                <el-input v-model="setList.miniprogramPage" placeholder="小程序消息打开后的路径" disabled />
+                                              <el-form-item label="page路径" prop="miniprogramPage" v-show="setList.contentType == 10" label-width="100px" style="margin-left: -30px">
+                                                <el-input v-model="setList.miniprogramPage" placeholder="小程序消息打开后的路径"  type="textarea" :rows="3" />
                                               </el-form-item>
                                             </el-card>
                                           </div>
@@ -694,7 +694,7 @@ export default {
               this.$set(content.setting[i], 'linkImageUrl', selectedCourse.dictImgUrl);
           }
 
-          if (content.setting[i].contentType == 4){
+          if (content.setting[i].contentType == 4 || content.setting[i].contentType == 10){
             this.$set(content.setting[i], 'miniprogramPicUrl', selectedCourse.dictImgUrl);
           }
 
@@ -721,7 +721,7 @@ export default {
               this.$set(content.setting[i], 'linkTitle', selectedCourse.dictLabel);
               this.$set(content.setting[i], 'linkImageUrl', selectedCourse.dictImgUrl);
             }
-            if (this.setting[i].contentType == 4){
+            if (this.setting[i].contentType == 4 || this.setting[i].contentType == 10 ){
               this.$set(content.setting[i], 'miniprogramPicUrl', selectedCourse.dictImgUrl);
             }
 
@@ -740,7 +740,7 @@ export default {
             if (content.setting[i].contentType == 3){
               this.$set(content.setting[i], 'linkDescribe', selectedVideo.dictLabel);
             }
-            if (this.setting[i].contentType == 4){
+            if (this.setting[i].contentType == 4 || this.setting[i].contentType == 10 ){
               this.$set(content.setting[i], 'miniprogramTitle', selectedVideo.dictLabel);
             }
           }
@@ -769,7 +769,7 @@ export default {
 
               this.$set(content.setting[i], 'linkDescribe', selectedVideo.dictLabel);
           }
-          if (content.setting[i].contentType == 4){
+          if (content.setting[i].contentType == 4 || content.setting[i].contentType == 10 ){
               this.$set(content.setting[i], 'miniprogramTitle', selectedVideo.dictLabel);
           }
 
@@ -881,12 +881,17 @@ export default {
                     return this.$message.error("链接地址不能为空")
                   }
 
-                  if (this.setting[i].content[j].setting[k].contentType == 4 && (this.setting[i].content[j].setting[k].miniprogramTitle == null || this.setting[i].content[j].setting[k].miniprogramTitle == "")) {
+                  if ((this.setting[i].content[j].setting[k].contentType == 4 || this.setting[i].content[j].setting[k].contentType == 10 ) && (this.setting[i].content[j].setting[k].miniprogramTitle == null || this.setting[i].content[j].setting[k].miniprogramTitle == "")) {
                     return this.$message.error("小程序消息标题不能为空")
                   }
-                  if (this.setting[i].content[j].setting[k].contentType == 4 && (this.setting[i].content[j].setting[k].miniprogramPicUrl == null || this.setting[i].content[j].setting[k].miniprogramPicUrl == "")) {
+                  if ((this.setting[i].content[j].setting[k].contentType == 4 || this.setting[i].content[j].setting[k].contentType == 10 )  && (this.setting[i].content[j].setting[k].miniprogramPicUrl == null || this.setting[i].content[j].setting[k].miniprogramPicUrl == "")) {
                     return this.$message.error("小程序封面地址不能为空")
                   }
+
+                  if (this.setting[i].content[j].setting[k].contentType == 10 && (this.setting[i].content[j].setting[k].miniprogramPage == null || this.setting[i].content[j].setting[k].miniprogramPage == "")) {
+                    return this.$message.error("小程序page地址不能为空")
+                  }
+
                   if (this.setting[i].content[j].setting[k].contentType == 5 && (this.setting[i].content[j].setting[k].fileUrl == null || this.setting[i].content[j].setting[k].fileUrl == "")) {
                     return this.$message.error("文件不能为空")
                   }

+ 2 - 2
src/views/qw/sopTemp/index.vue

@@ -268,9 +268,9 @@
           </el-time-picker>
         </el-form-item>
         <el-form-item label="每天催课次数" prop="num" v-if="form.sendType == 11 && !form.id">
-          <el-input-number v-model="form.num" :min="1" label="每天催课次数" @change="sendNumChange"></el-input-number>
+          <el-input-number v-model="form.num" :min="0" label="每天催课次数" @change="sendNumChange"></el-input-number>
         </el-form-item>
-        <el-form-item label="催课时间" v-if="form.sendType == 11 && !form.id">
+        <el-form-item label="催课时间" v-if="form.sendType == 11 && !form.id && form.num > 0">
           <div v-for="(item, index) in form.timeList" :key="index" style="margin-bottom: 10px;">
             <el-time-picker
               class="custom-input"

+ 17 - 37
src/views/qw/sopTemp/updateSopTemp.vue

@@ -284,7 +284,8 @@
                                                 :key="item.dictValue"
                                                 :label="item.dictValue"
                                                 :disabled="(content.type!=2 && item.dictValue === '9') || (content.isOfficial==1 && ['5','6','7','8','9'].includes(item.dictValue))"
-                                                v-for="item in sysQwSopAiContentType" v-if="setIndex == 0 ? courseTypeList.includes(item.dictValue) : !courseTypeList.includes(item.dictValue)">{{ item.dictLabel }}
+                                                v-for="item in sysQwSopAiContentType"
+                                                v-if="setIndex == 0 ? courseTypeList.includes(item.dictValue) : !courseTypeList.includes(item.dictValue)">{{ item.dictLabel }}
                                               </el-radio>
                                             </el-radio-group>
                                           </div>
@@ -352,7 +353,7 @@
                                             </el-card>
                                           </div>
 
-                                          <div v-if="setList.contentType == 4">
+                                          <div v-if="setList.contentType == 4 || setList.contentType == 10">
                                             <el-card class="box-card">
                                               <el-form-item label="标题" prop="miniprogramTitle">
                                                 <el-input v-model="setList.miniprogramTitle"
@@ -373,11 +374,11 @@
                                                 <el-input v-model="setList.miniprogramAppid='wx73f85f8d62769119' " :disabled="formType == 3 || !roles.includes('edit_sop_temp_content')"
                                                           disabled/>
                                               </el-form-item>
-                                              <el-form-item label="page路径" prop="miniprogramPage" v-show="false"
+                                              <el-form-item label="page路径" prop="miniprogramPage" v-show="setList.contentType == 10"
                                                             label-width="100px" style="margin-left: -30px">
                                                 <el-input v-model="setList.miniprogramPage"
                                                           :disabled="formType == 3 || !roles.includes('edit_sop_temp_content')"
-                                                          placeholder="小程序消息打开后的路径" disabled/>
+                                                          placeholder="小程序消息打开后的路径" type="textarea" :rows="3" />
                                               </el-form-item>
                                             </el-card>
                                           </div>
@@ -474,31 +475,6 @@
 
                                             </el-card>
                                           </div>
-                                          <div v-if="setList.contentType == 10 ">
-                                            <el-card class="box-card">
-                                              <el-form-item label="链接标题:" label-width="100px" required>
-                                                <el-input :disabled="formType == 3 || !roles.includes('edit_sop_temp_content')" v-model="setList.linkTitle"
-                                                          placeholder="请输入链接标题"
-                                                          style="width: 90%;"/>
-                                              </el-form-item>
-                                              <el-form-item label="链接描述:" label-width="100px" required>
-                                                <el-input :disabled="formType == 3 || !roles.includes('edit_sop_temp_content')" type="textarea" :rows="3"
-                                                          v-model="setList.linkDescribe"
-                                                          placeholder="请输入链接描述"
-                                                          style="width: 90%;margin-top: 1%;"/>
-                                              </el-form-item>
-                                              <el-form-item label="链接封面:" label-width="100px" required>
-                                                <ImageUpload :disabled="formType == 3 || !roles.includes('edit_sop_temp_content')" v-model="setList.linkImageUrl"
-                                                             type="image" :num="1"
-                                                             :file-size="2" :width="150" :height="150"
-                                                             style="margin-top: 1%;"/>
-                                              </el-form-item>
-                                              <el-form-item label="链接地址:" label-width="100px">
-                                                <el-tag type="warning"> 链接地址自动生成
-                                                </el-tag>
-                                              </el-form-item>
-                                            </el-card>
-                                          </div>
                                         </el-form-item>
                                         <el-form-item label="添加短链"
                                                       v-if="content.type == 2 && setList.contentType == 1  ">
@@ -738,7 +714,7 @@ export default {
       ruleList: [],
       ids: [],
       startTimeRange: [],
-      courseTypeList: ['3', '4', '9'],
+      courseTypeList: ['1','3', '4', '9','10'],
       sysFsSopWatchStatus: [],
       //消息内容类型 企微版
       sysQwSopContentType: [],
@@ -1140,15 +1116,20 @@ export default {
                 return false;
               }
 
-              if (data.content[j].setting[k].contentType == 4 && (data.content[j].setting[k].miniprogramTitle == null || data.content[j].setting[k].miniprogramTitle == "")) {
+              if ((data.content[j].setting[k].contentType == 4 || data.content[j].setting[k].contentType == 10) && (data.content[j].setting[k].miniprogramTitle == null || data.content[j].setting[k].miniprogramTitle == "")) {
                 this.$message.error("小程序消息标题不能为空")
                 return false;
               }
-              if (data.content[j].setting[k].contentType == 4 && data.content[j].isOfficial !== '1' && (data.content[j].setting[k].miniprogramPicUrl == null || data.content[j].setting[k].miniprogramPicUrl == "")) {
+              if ((data.content[j].setting[k].contentType == 4 || data.content[j].setting[k].contentType == 10) && data.content[j].isOfficial !== '1' && (data.content[j].setting[k].miniprogramPicUrl == null || data.content[j].setting[k].miniprogramPicUrl == "")) {
                 this.$message.error("小程序封面地址不能为空")
                 return false;
               }
 
+              if (data.content[j].setting[k].contentType == 10 && data.content[j].isOfficial !== '1' && (data.content[j].setting[k].miniprogramPage == null || data.content[j].setting[k].miniprogramPage == "")) {
+                this.$message.error("小程序page地址不能为空")
+                return false;
+              }
+
               if (data.content[j].setting[k].contentType == 5 && (data.content[j].setting[k].fileUrl == null || data.content[j].setting[k].fileUrl == "")) {
                 this.$message.error("文件不能为空")
                 return false;
@@ -1374,7 +1355,7 @@ export default {
             this.$set(content.setting[i], 'linkTitle', selectedCourse.dictLabel);
             this.$set(content.setting[i], 'linkImageUrl', selectedCourse.dictImgUrl);
           }
-          if (content.setting[i].contentType == 4) {
+          if (content.setting[i].contentType == 4 || content.setting[i].contentType == 10) {
             this.$set(content.setting[i], 'miniprogramPicUrl', selectedCourse.dictImgUrl);
           }
 
@@ -1486,8 +1467,7 @@ export default {
               this.$set(content.setting[i], 'linkTitle', selectedCourse.dictLabel);
               this.$set(content.setting[i], 'linkImageUrl', selectedCourse.dictImgUrl);
             }
-            if (content.setting[i].contentType == 4 && (content.isOfficial == '0' || content.isOfficial == null)) {
-              console.log(content.isOfficial);
+            if ((content.setting[i].contentType == 4 || content.setting[i].contentType == 10) && (content.isOfficial == '0' || content.isOfficial == null)) {
               this.$set(content.setting[i], 'miniprogramPicUrl', selectedCourse.dictImgUrl);
             }
 
@@ -1507,7 +1487,7 @@ export default {
             if (content.setting[i].contentType == 3 || content.setting[i].contentType == 9) {
               this.$set(content.setting[i], 'linkDescribe', selectedVideo.dictLabel);
             }
-            if (content.setting[i].contentType == 4) {
+            if (content.setting[i].contentType == 4 || content.setting[i].contentType == 10 ) {
               this.$set(content.setting[i], 'miniprogramTitle', this.truncateTextByByteLength(selectedVideo.dictLabel, 60));
             }
           }
@@ -1541,7 +1521,7 @@ export default {
           if (content.setting[i].contentType == 3 || content.setting[i].contentType == 9) {
             this.$set(content.setting[i], 'linkDescribe', selectedVideo.dictLabel);
           }
-          if (content.setting[i].contentType == 4) {
+          if (content.setting[i].contentType == 4 || content.setting[i].contentType == 10) {
             this.$set(content.setting[i], 'miniprogramTitle', this.truncateTextByByteLength(selectedVideo.dictLabel, 60));
           }
 

+ 12 - 7
src/views/qw/sopUserLogsInfo/sendMsgOpenTool.vue

@@ -104,7 +104,7 @@
                           </el-form-item>
                         </el-card>
                       </div>
-                      <div v-if="item.contentType == 4">
+                      <div v-if="item.contentType == 4 || item.contentType == 10 ">
                         <el-card class="box-card">
                           <el-form-item label="标题" prop="miniprogramTitle">
                             <el-input v-model="item.miniprogramTitle" placeholder="请输入小程序消息标题,最长为64字"  />
@@ -115,8 +115,8 @@
                           <el-form-item label="appid" prop="miniprogramAppid" v-show="false" >
                             <el-input v-model="item.miniprogramAppid='wx73f85f8d62769119' " disabled />
                           </el-form-item>
-                          <el-form-item label="page路径" prop="miniprogramPage" v-show="false" label-width="100px" style="margin-left: -30px" >
-                            <el-input v-model="item.miniprogramPage" placeholder="小程序消息打开后的路径"  disabled />
+                          <el-form-item label="page路径" prop="miniprogramPage" v-show="item.contentType == 10" label-width="100px" style="margin-left: -30px" >
+                            <el-input v-model="item.miniprogramPage" placeholder="小程序消息打开后的路径" type="textarea" :rows="3" />
                           </el-form-item>
                         </el-card>
                       </div>
@@ -600,7 +600,7 @@ export default {
               this.$set(this.setting[i], 'linkTitle', selectedCourse.dictLabel);
               this.$set(this.setting[i], 'linkImageUrl', selectedCourse.dictImgUrl);
             }
-            if (this.setting[i].contentType == 4){
+            if (this.setting[i].contentType == 4 || this.setting[i].contentType == 10 ){
               this.$set(this.setting[i], 'miniprogramPicUrl', selectedCourse.dictImgUrl);
             }
 
@@ -621,7 +621,7 @@ export default {
             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){
+            if (this.setting[i].contentType == 4 || this.setting[i].contentType == 10){
               this.$set(this.setting[i], 'miniprogramTitle', selectedVideo.dictLabel);
             }
 
@@ -694,12 +694,17 @@ export default {
                 return this.$message.error("链接地址不能为空")
               }
 
-              if (this.setting[i].contentType == 4 && (this.setting[i].miniprogramTitle == null || this.setting[i].miniprogramTitle == "")) {
+              if ((this.setting[i].contentType == 4 || this.setting[i].contentType == 10 ) && (this.setting[i].miniprogramTitle == null || this.setting[i].miniprogramTitle == "")) {
                 return this.$message.error("小程序消息标题不能为空")
               }
-              if (this.setting[i].contentType == 4 && (this.setting[i].miniprogramPicUrl == null || this.setting[i].miniprogramPicUrl == "")) {
+              if ((this.setting[i].contentType == 4 || this.setting[i].contentType == 10 ) && (this.setting[i].miniprogramPicUrl == null || this.setting[i].miniprogramPicUrl == "")) {
                 return this.$message.error("小程序封面地址不能为空")
               }
+
+              if (this.setting[i].contentType == 10 && (this.setting[i].miniprogramPage == null || this.setting[i].miniprogramPage == "")) {
+                return this.$message.error("小程序page地址不能为空")
+              }
+
               if (this.setting[i].contentType == 5 && (this.setting[i].fileUrl == null || this.setting[i].fileUrl == "")) {
                 return this.$message.error("文件不能为空")
               }

+ 751 - 0
src/views/qw/sopUserLogsInfo/sendMsgSopOpenTool.vue

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

+ 14 - 9
src/views/qw/sopUserLogsInfo/sopUserLogsInfoDetails.vue

@@ -317,7 +317,7 @@
                         </el-form-item>
                       </el-card>
                     </div>
-                    <div v-if="item.contentType == 4">
+                    <div v-if="item.contentType == 4 || item.contentType == 10">
                       <el-card class="box-card">
                         <el-form-item label="标题" prop="miniprogramTitle">
                           <el-input v-model="item.miniprogramTitle" placeholder="请输入小程序消息标题,最长为64字"  />
@@ -328,8 +328,8 @@
                         <el-form-item label="appid" prop="miniprogramAppid" v-show="false" >
                           <el-input v-model="item.miniprogramAppid='wx73f85f8d62769119' " disabled />
                         </el-form-item>
-                        <el-form-item label="page路径" prop="miniprogramPage" v-show="false" label-width="100px" style="margin-left: -30px" >
-                          <el-input v-model="item.miniprogramPage" placeholder="小程序消息打开后的路径"  disabled />
+                        <el-form-item label="page路径" prop="miniprogramPage" v-show="item.contentType == 10" label-width="100px" style="margin-left: -30px" >
+                          <el-input v-model="item.miniprogramPage" placeholder="小程序消息打开后的路径" type="textarea" :rows="3" />
                         </el-form-item>
                       </el-card>
                     </div>
@@ -800,7 +800,7 @@ export default {
               this.$set(this.setting[i], 'linkImageUrl', selectedCourse.dictImgUrl);
             }
 
-            if ( this.setting[i].contentType == 4 ){
+            if ( this.setting[i].contentType == 4 || this.setting[i].contentType == 10 ){
               this.$set(this.setting[i], 'miniprogramPicUrl', selectedCourse.dictImgUrl);
             }
           }
@@ -825,7 +825,7 @@ export default {
               this.$set(this.setting[i], 'linkDescribe', selectedVideo.dictLabel);
             }
 
-            if (this.setting[i].contentType == 4){
+            if (this.setting[i].contentType == 4 || this.setting[i].contentType == 10){
               this.$set(this.setting[i], 'miniprogramTitle', selectedVideo.dictLabel);
             }
 
@@ -1040,7 +1040,7 @@ export default {
               this.$set(this.setting[i], 'linkTitle', selectedCourse.dictLabel);
               this.$set(this.setting[i], 'linkImageUrl', selectedCourse.dictImgUrl);
             }
-            if (this.setting[i].contentType == 4){
+            if (this.setting[i].contentType == 4 || this.setting[i].contentType == 10){
               this.$set(this.setting[i], 'miniprogramPicUrl', selectedCourse.dictImgUrl);
             }
 
@@ -1061,7 +1061,7 @@ export default {
             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){
+            if (this.setting[i].contentType == 4 || this.setting[i].contentType == 10){
               this.$set(this.setting[i], 'miniprogramTitle', selectedVideo.dictLabel);
             }
 
@@ -1234,12 +1234,17 @@ export default {
               return this.$message.error("链接地址不能为空")
             }
 
-            if (this.setting[i].contentType == 4 && (this.setting[i].miniprogramTitle == null || this.setting[i].miniprogramTitle == "")) {
+            if ((this.setting[i].contentType == 4 || this.setting[i].contentType == 10 ) && (this.setting[i].miniprogramTitle == null || this.setting[i].miniprogramTitle == "")) {
               return this.$message.error("小程序消息标题不能为空")
             }
-            if (this.setting[i].contentType == 4 && (this.setting[i].miniprogramPicUrl == null || this.setting[i].miniprogramPicUrl == "")) {
+            if ((this.setting[i].contentType == 4 || this.setting[i].contentType == 10 )  && (this.setting[i].miniprogramPicUrl == null || this.setting[i].miniprogramPicUrl == "")) {
               return this.$message.error("小程序封面地址不能为空")
             }
+
+            if (this.setting[i].contentType == 10 && (this.setting[i].miniprogramPage == null || this.setting[i].miniprogramPage == "")) {
+              return this.$message.error("小程序page地址不能为空")
+            }
+
             if (this.setting[i].contentType == 5 && (this.setting[i].fileUrl == null || this.setting[i].fileUrl == "")) {
               return this.$message.error("文件不能为空")
             }

+ 1 - 0
src/views/qw/user/cuDeptIdIndex.vue

@@ -103,6 +103,7 @@
         </template>
       </el-table-column>
       <el-table-column label="vid" align="center" prop="vid" />
+      <el-table-column label="uid" align="center" prop="uid" />
       <el-table-column label="serverId" align="center" prop="serverId" />
      <el-table-column label="ai状态" align="center" prop="loginStatus">
         <template slot-scope="scope">

+ 3 - 1
src/views/qw/user/index.vue

@@ -114,7 +114,9 @@
           <el-tag v-if="scope.row.sendMsgType == 2" type="warning">掉线通知</el-tag>
         </template>
       </el-table-column>
-      <el-table-column label="UUID" align="center" prop="uid" />
+      <el-table-column label="vid" align="center" prop="vid" />
+      <el-table-column label="uid" align="center" prop="uid" />
+      <el-table-column label="serverId" align="center" prop="serverId" />
       <el-table-column label="ai状态" align="center" prop="loginStatus">
         <template slot-scope="scope">
           <el-tag v-if="scope.row.ipadStatus == 1" type="success">在线</el-tag>

+ 4 - 4
src/views/statistics/section/today.vue

@@ -5,7 +5,7 @@
         <select-tree
           v-model="selectedCompanyList"
           :raw-data="deptList"
-          placeholder="请选择销售"
+          placeholder="请选择客服"
           :parentSelectable="true"
           :multiple="true"
           component-width="300px"
@@ -15,7 +15,7 @@
           @change="handleMultiChange"
         ></select-tree>
       </el-form-item>
-      <el-form-item label="销售" prop="nickName" v-if="queryParams.companyId">
+      <el-form-item label="客服" prop="nickName" v-if="queryParams.companyId">
         <el-select v-model="queryParams.companyUserId" remote
                    placeholder="请选择"
                    filterable clearable
@@ -340,8 +340,8 @@ export default {
     },
     /** 搜索按钮操作 */
     handleQuery() {
-      if (!this.dateRange || this.dateRange.length !== 2) {
-        this.$message.warning("请选择时间范围");
+      if(this.selectedCompanyList == null || this.selectedCompanyList.length <= 0) {
+        this.$message.error("公司和时间为必选!");
         return;
       }
       this.queryParams.pageNum = 1;