Prechádzať zdrojové kódy

Merge branch 'develop_cuxiao' of jianguan-web/jg-ocs-html into pre-release

李磊 1 rok pred
rodič
commit
df8c8dcf26
100 zmenil súbory, kde vykonal 15512 pridanie a 841 odobranie
  1. 17 17
      package-lock.json
  2. 3 2
      package.json
  3. BIN
      public/templ/产品批量导入模板.xlsx
  4. BIN
      public/templ/促销规则导入产品.xlsx
  5. BIN
      public/templ/促销规则导入特价产品.xlsx
  6. 1 1
      public/version.json
  7. 11 0
      src/api/dispatch.js
  8. 8 0
      src/api/product.js
  9. 149 0
      src/api/promotion.js
  10. 62 0
      src/api/reportData.js
  11. 10 217
      src/api/sales.js
  12. 0 187
      src/api/salesDetail.js
  13. 209 0
      src/api/salesDetailNew.js
  14. 313 0
      src/api/salesNew.js
  15. 17 0
      src/api/salesReturn.js
  16. 22 0
      src/api/stock.js
  17. 1 1
      src/api/waitDispatchDetail.js
  18. 4 1
      src/components/Table/index.js
  19. 20 10
      src/components/UploadFile/index.vue
  20. 3 3
      src/components/custom.less
  21. 51 1
      src/components/index.less
  22. 2 2
      src/components/newThem.less
  23. 78 116
      src/config/router.config.js
  24. 2 1
      src/libs/JGPrint.js
  25. 16 1
      src/libs/tools.js
  26. 4 0
      src/store/modules/app.js
  27. 3 2
      src/utils/mixin.js
  28. 1 1
      src/utils/util.js
  29. 3 2
      src/views/allocationManagement/transferOut/edit.vue
  30. 178 38
      src/views/common/chooseBrandModal.vue
  31. 35 10
      src/views/common/chooseTypeModal.vue
  32. 48 16
      src/views/common/chooseWarehouse.js
  33. 30 10
      src/views/common/productBrand.js
  34. 9 1
      src/views/common/productTypeAll.js
  35. 8 5
      src/views/expenseManagement/expenseReimbursement/add.vue
  36. 47 16
      src/views/expenseManagement/expenseReimbursement/baseDataModal.vue
  37. 2 0
      src/views/expenseManagement/expenseReimbursement/detail.vue
  38. 1 1
      src/views/financialManagement/financialCollection/selectGlSalesModal.vue
  39. 1 22
      src/views/inventoryManagement/inventoryCheck/list.vue
  40. 3 3
      src/views/productManagement/productInfo/edit.vue
  41. 2 1
      src/views/productManagement/productInfo/importGuideModal.vue
  42. 39 2
      src/views/productManagement/productInfo/list.vue
  43. 311 0
      src/views/promotionRulesManagement/dealerPromotions/addModal.vue
  44. 113 0
      src/views/promotionRulesManagement/dealerPromotions/brandCategoryModal.vue
  45. 214 0
      src/views/promotionRulesManagement/dealerPromotions/chooseImportModal.vue
  46. 259 0
      src/views/promotionRulesManagement/dealerPromotions/chooseProductsModal.vue
  47. 341 0
      src/views/promotionRulesManagement/dealerPromotions/detail.vue
  48. 406 0
      src/views/promotionRulesManagement/dealerPromotions/detailModal.vue
  49. 138 0
      src/views/promotionRulesManagement/dealerPromotions/editActiveEndTime.vue
  50. 199 0
      src/views/promotionRulesManagement/dealerPromotions/importGuideModal.vue
  51. 449 0
      src/views/promotionRulesManagement/dealerPromotions/list.vue
  52. 607 0
      src/views/promotionRulesManagement/dealerPromotions/sendAmountModal.vue
  53. 637 0
      src/views/promotionRulesManagement/dealerPromotions/sendProductsModal.vue
  54. 680 0
      src/views/promotionRulesManagement/dealerPromotions/specialOfferModal.vue
  55. 638 0
      src/views/promotionRulesManagement/dealerPromotions/tableType1.vue
  56. 608 0
      src/views/promotionRulesManagement/dealerPromotions/tableType2.vue
  57. 675 0
      src/views/promotionRulesManagement/dealerPromotions/tableType3.vue
  58. 31 16
      src/views/promotionRulesManagement/promotionManagement/chooseDealer.vue
  59. 1 1
      src/views/promotionRulesManagement/promotionManagement/lookUpCustomersModal.vue
  60. 437 0
      src/views/reportData/promotionSalesRealTimeReport/index.vue
  61. 602 0
      src/views/reportData/promotionSalesRealTimeReport/list.vue
  62. 51 35
      src/views/reportData/salesDetails/list.vue
  63. 23 19
      src/views/reportData/salesOrderTotal/list.vue
  64. 5 1
      src/views/reportData/salesReturnDetailReport/list.vue
  65. 23 6
      src/views/salesManagement/backorder/detailModal.vue
  66. 7 2
      src/views/salesManagement/backorder/list.vue
  67. 1 1
      src/views/salesManagement/examineVerify/list.vue
  68. 1 1
      src/views/salesManagement/matchSendOutOrder/list.vue
  69. 1 1
      src/views/salesManagement/outboundOrder/list.vue
  70. 11 6
      src/views/salesManagement/pushOrderManagement/detail.vue
  71. 342 0
      src/views/salesManagement/pushOrderManagement/detailForOut.vue
  72. 1 1
      src/views/salesManagement/pushOrderManagement/list.vue
  73. 2 2
      src/views/salesManagement/pushOrderManagement/sendTypeModal.vue
  74. 1 1
      src/views/salesManagement/salesCollection/list.vue
  75. 2 2
      src/views/salesManagement/salesList/list.vue
  76. 6 6
      src/views/salesManagement/salesOrderWarehouse/detail.vue
  77. 4 3
      src/views/salesManagement/salesOrderWarehouse/list.vue
  78. 0 1
      src/views/salesManagement/salesOrderWarehouse/printModal.vue
  79. 3 3
      src/views/salesManagement/salesQuery/detail.vue
  80. 1 24
      src/views/salesManagement/salesQuery/edit.vue
  81. 0 15
      src/views/salesManagement/salesQuery/importGuideModal.vue
  82. 4 4
      src/views/salesManagement/salesQuery/list.vue
  83. 217 0
      src/views/salesManagement/salesQueryNew/chooseCustomModal.vue
  84. 309 0
      src/views/salesManagement/salesQueryNew/comps/activeQueryPart.vue
  85. 186 0
      src/views/salesManagement/salesQueryNew/comps/chooseImportModal.vue
  86. 105 0
      src/views/salesManagement/salesQueryNew/comps/chooseProduct.vue
  87. 392 0
      src/views/salesManagement/salesQueryNew/comps/detailProductList.vue
  88. 203 0
      src/views/salesManagement/salesQueryNew/comps/importGuideModal.vue
  89. 808 0
      src/views/salesManagement/salesQueryNew/comps/productList.vue
  90. 565 0
      src/views/salesManagement/salesQueryNew/comps/productNormalList.vue
  91. 272 0
      src/views/salesManagement/salesQueryNew/comps/queryPart.vue
  92. 91 0
      src/views/salesManagement/salesQueryNew/comps/setWarehouse.vue
  93. 104 0
      src/views/salesManagement/salesQueryNew/comps/updateActiveModal.vue
  94. 471 0
      src/views/salesManagement/salesQueryNew/detail.vue
  95. 545 0
      src/views/salesManagement/salesQueryNew/detailAll.vue
  96. 691 0
      src/views/salesManagement/salesQueryNew/edit.vue
  97. 721 0
      src/views/salesManagement/salesQueryNew/list.vue
  98. 90 0
      src/views/salesManagement/salesQueryNew/newPromoModal.vue
  99. 245 0
      src/views/salesManagement/salesQueryNew/printModal.vue
  100. 249 0
      src/views/salesManagement/salesQueryNew/receivingAddress/chooseAddressModal.vue

+ 17 - 17
package-lock.json

@@ -1,5 +1,5 @@
 {
-  "name": "chelingzhu",
+  "name": "jg-ocs",
   "version": "2.0.0",
   "lockfileVersion": 1,
   "requires": true,
@@ -1989,16 +1989,16 @@
       },
       "dependencies": {
         "@babel/parser": {
-          "version": "7.21.3",
-          "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.21.3.tgz",
-          "integrity": "sha512-lobG0d7aOfQRXh8AyklEAgZGvA4FShxo6xQbUrrT/cNBPUdIDojlokwJsQyCC/eKia7ifqM0yP+2DRZ4WKw2RQ=="
+          "version": "7.23.0",
+          "resolved": "https://registry.npmmirror.com/@babel/parser/-/parser-7.23.0.tgz",
+          "integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw=="
         },
         "postcss": {
-          "version": "8.4.21",
-          "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.21.tgz",
-          "integrity": "sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg==",
+          "version": "8.4.31",
+          "resolved": "https://registry.npmmirror.com/postcss/-/postcss-8.4.31.tgz",
+          "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==",
           "requires": {
-            "nanoid": "^3.3.4",
+            "nanoid": "^3.3.6",
             "picocolors": "^1.0.0",
             "source-map-js": "^1.0.2"
           }
@@ -5085,9 +5085,9 @@
       }
     },
     "csstype": {
-      "version": "3.1.1",
-      "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.1.tgz",
-      "integrity": "sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw=="
+      "version": "3.1.2",
+      "resolved": "https://registry.npmmirror.com/csstype/-/csstype-3.1.2.tgz",
+      "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ=="
     },
     "cuint": {
       "version": "0.2.2",
@@ -11580,9 +11580,9 @@
       }
     },
     "lodash": {
-      "version": "4.17.15",
-      "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
-      "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A=="
+      "version": "4.17.21",
+      "resolved": "https://registry.npmmirror.com/lodash/-/lodash-4.17.21.tgz",
+      "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
     },
     "lodash.defaultsdeep": {
       "version": "4.6.1",
@@ -17219,9 +17219,9 @@
       "integrity": "sha512-Uf1i/sCh+ZqSM9hb2YTGRENzJFH+mvDuv8N2brGLjK7UBuF7XDP7zbis8g/dcqZiMojAcBDtObFCn4ERFbRMxQ=="
     },
     "vue-easytable": {
-      "version": "2.24.0",
-      "resolved": "https://registry.npmjs.org/vue-easytable/-/vue-easytable-2.24.0.tgz",
-      "integrity": "sha512-5OcCw3EMLEb/cBLV/pMqRIhAmwt3FadXpoZvWhdE+SynthdNtTrQhxFKyjgpAmX6OPEMb9/XFNX86gDuIVnlxg==",
+      "version": "2.27.1",
+      "resolved": "https://registry.npmmirror.com/vue-easytable/-/vue-easytable-2.27.1.tgz",
+      "integrity": "sha512-Rs2cqaPYamH8zXQo/f90AyM/ROGMsB5Njb74GpooWacAKEXbHU0wXYvEjSBZ7CcS6TVqliA/ZbgVqOoA/o9bHQ==",
       "requires": {
         "lodash": "^4.17.20",
         "resize-observer-polyfill": "^1.5.1",

+ 3 - 2
package.json

@@ -1,5 +1,5 @@
 {
-  "name": "chelingzhu",
+  "name": "jg-ocs",
   "version": "2.0.0",
   "private": true,
   "scripts": {
@@ -21,6 +21,7 @@
     "core-js": "2.6.9",
     "echarts": "^5.4.0",
     "enquire.js": "^2.1.6",
+    "lodash": "^4.17.20",
     "lodash.get": "^4.4.2",
     "lodash.pick": "^4.4.0",
     "md5": "^2.2.1",
@@ -35,7 +36,7 @@
     "vue-clipboard2": "^0.2.1",
     "vue-cookies": "^1.6.1",
     "vue-cropper": "0.4.9",
-    "vue-easytable": "^2.24.0",
+    "vue-easytable": "^2.27.1",
     "vue-ls": "^3.2.1",
     "pdfjs-dist": "2.5.207",
     "vue-pdf-signature": "^4.2.6",

BIN
public/templ/产品批量导入模板.xlsx


BIN
public/templ/促销规则导入产品.xlsx


BIN
public/templ/促销规则导入特价产品.xlsx


+ 1 - 1
public/version.json

@@ -1,4 +1,4 @@
 {
-    "version": "2.2.49",
+    "version": "2.2.62",
     "message": "发现有新版本发布,确定更新系统?"
 }

+ 11 - 0
src/api/dispatch.js

@@ -23,6 +23,17 @@ export const dispatchDetaillList = (params) => {
     method: 'post'
   })
 }
+// 出库详情列表
+export const dispatchDetaillListForOut = (params) => {
+  const url = `/dispatch/detail/queryPageForOut/${params.pageNo}/${params.pageSize}`
+  delete params.pageNo
+  delete params.pageSize
+  return axios({
+    url: url,
+    data: params,
+    method: 'post'
+  })
+}
 // 根据销售单sn查询关联的所有发货单
 export const queryBySalesBillSn = (params) => {
   return axios({

+ 8 - 0
src/api/product.js

@@ -500,3 +500,11 @@ export const updateShowFlag = (params) => {
     method: 'post'
   })
 }
+// 修改停产状态
+export const updateHaltProdFlag = (params) => {
+  return axios({
+    url: '/product/updateHaltProdFlag',
+    data: params,
+    method: 'post'
+  })
+}

+ 149 - 0
src/api/promotion.js

@@ -0,0 +1,149 @@
+import { axios } from '@/utils/request'
+
+// 经销商促销列表  分页
+export const dealerPromotionList = (params) => {
+  const url = `/promotion/queryPage/${params.pageNo}/${params.pageSize}`
+  delete params.pageNo
+  delete params.pageSize
+  return axios({
+    url: url,
+    data: params,
+    method: 'post'
+  })
+}
+// 新增促销活动
+export const dealerPromotionSave = params => {
+  return axios({
+    url: '/promotion/create',
+    data: params,
+    method: 'post'
+  })
+}
+// 获取促销活动详情
+export const dealerPromotionInfo = params => {
+  return axios({
+    url: `/promotion/findBySn/${params.sn}`,
+    data: {},
+    method: 'get'
+  })
+}
+// 修改促销活动
+export const dealerPromotionEdit = params => {
+  return axios({
+    url: '/promotion/modify',
+    data: params,
+    method: 'post'
+  })
+}
+
+// 删除促销活动
+export const dealerPromotionDel = params => {
+  return axios({
+    url: `/promotion/delete/${params.sn}`,
+    data: {},
+    method: 'get'
+  })
+}
+// 规则设置页面  详情
+export const getRuleDetail = (params) => {
+  return axios({
+    url: `/promotion/rule/findBySn/${params.sn}`,
+    data: {},
+    method: 'get'
+  })
+}
+// 规则设置 列表
+export const getRuleQueryList = (params) => {
+  return axios({
+    url: '/promotion/rule/queryList',
+    data: params,
+    method: 'post'
+  })
+}
+
+// 新增一行
+export const getNewScopeSn = (params) => {
+  return axios({
+    url: '/promotion/rule/getNewScopeSn',
+    data: params,
+    method: 'get'
+  })
+}
+// 规则保存/修改
+export const promotionSave = (params) => {
+  return axios({
+    url: '/promotion/rule/save',
+    data: params,
+    method: 'post'
+  })
+}
+// 删除规则列表
+export const promotionRulesDel = (params) => {
+  return axios({
+    url: '/promotion/rule/delete',
+    data: params,
+    method: 'post'
+  })
+}
+// 提交
+export const promotionSubmit = (params) => {
+  return axios({
+    url: `/promotion/submit/${params.sn}`,
+    data: {},
+    method: 'get'
+  })
+}
+
+// 改变发布状态
+export const modifyEnabledFlag = (params) => {
+  return axios({
+    url: '/promotion/modifyEnabledFlag',
+    data: params,
+    method: 'post'
+  })
+}
+// 审核
+export const promotionAudit = (params) => {
+  return axios({
+    url: '/promotion/audit',
+    data: params,
+    method: 'post'
+  })
+}
+// 变更促销时间
+export const promotionDateModify = (params) => {
+  return axios({
+    url: '/promotion/promotionDateModify',
+    data: params,
+    method: 'post'
+  })
+}
+// 中止
+export const promotionIsOver = (params) => {
+  return axios({
+    url: `/promotion/isOver/${params.sn}`,
+    data: {},
+    method: 'get'
+  })
+}
+
+// 导出门槛产品错误项
+export const downNormalFail = (params) => {
+  const url = `/promotion/downNormalFail`
+  return axios.request({
+    url: url,
+    method: 'post',
+    data: params,
+    responseType: 'blob'
+  })
+}
+// 导出促销产品错误项
+export const downSpecialFail = (params) => {
+  const url = `/promotion/downSpecialFail`
+  return axios.request({
+    url: url,
+    method: 'post',
+    data: params,
+    responseType: 'blob'
+  })
+}

+ 62 - 0
src/api/reportData.js

@@ -879,3 +879,65 @@ export const queryReportCount = (params) => {
 //     responseType: 'blob'
 //   })
 // }
+
+/*
+**   促销销售
+*/
+// 促销销售单报表  列表
+export const salesPromoReportList = (params) => {
+  const url = `/report/salesPromoReport/queryPage/${params.pageNo}/${params.pageSize}`
+  delete params.pageNo
+  delete params.pageSize
+  return axios({
+    url: url,
+    data: params,
+    method: 'post'
+  })
+}
+// 促销销售单报表  统计
+export const salesPromoReportQueryCount = (params) => {
+  const url = `/report/salesPromoReport/queryCount`
+  return axios({
+    url: url,
+    data: params,
+    method: 'post'
+  })
+}
+// 促销销售单报表  导出
+export const exportSalesPromoReport = (params) => {
+  return axios({
+    url: '/report/salesPromoReport/reportExport',
+    data: params,
+    method: 'post',
+    responseType: 'blob'
+  })
+}
+// 促销销售单实时报表  列表
+export const salesPromoRealReportList = (params) => {
+  const url = `/report/salesPromoRealReport/queryPage/${params.pageNo}/${params.pageSize}`
+  delete params.pageNo
+  delete params.pageSize
+  return axios({
+    url: url,
+    data: params,
+    method: 'post'
+  })
+}
+// 促销销售单实时报表  统计
+export const salesPromoRealReportCount = (params) => {
+  const url = `/report/salesPromoRealReport/queryCount`
+  return axios({
+    url: url,
+    data: params,
+    method: 'post'
+  })
+}
+// 促销销售单实时报表  导出
+export const exportSalesPromoRealReport = (params) => {
+  return axios({
+    url: '/report/salesPromoRealReport/reportExport',
+    data: params,
+    method: 'post',
+    responseType: 'blob'
+  })
+}

+ 10 - 217
src/api/sales.js

@@ -1,59 +1,19 @@
 import { axios } from '@/utils/request'
 
-//  销售 审核
-export const salesWriteAudit = (params) => {
-  return axios({
-    url: '/sales/audit',
-    data: params,
-    method: 'post'
-  })
-}
-
-//  销售 一键审核
-export const salesWriteAuditPush = (params) => {
-  return axios({
-    url: '/sales/auditPush',
-    data: params,
-    method: 'post'
-  })
-}
-
-//  销售 删除
-export const salesDel = (params) => {
-  return axios({
-    url: `/sales/delete/${params.salesBillSn}`,
-    method: 'get'
-  })
-}
-
-//  销售 详情bysn
-export const salesDetailBySn = (params) => {
-  return axios({
-    url: `/sales/findBySn/${params.salesBillSn}`,
-    method: 'get'
-  })
-}
-// 查询客户名称
-export const salesDetailByNo = (params) => {
+// 车架号
+export const supperCodeByVin = (params) => {
   return axios({
-    url: `/sales/findBySaleBillNo/${params.salesBillNo}`,
+    url: `/vinIdentify/queryPartCodeByVin/${params.vin}`,
     method: 'get'
   })
 }
-//  销售 新增
-export const salesSave = (params) => {
-  return axios({
-    url: '/sales/insert',
-    data: params,
-    method: 'post'
-  })
-}
-// 销售 编辑
-export const salesModify = (params) => {
-  return axios({
-    url: '/sales/modifyWarehouse',
+// 车架号  识别图片内容
+export const vinCodeParse = params => {
+  return axios.request({
+    url: `/vinIdentify/ocr`,
+    method: 'post',
     data: params,
-    method: 'post'
+    responseType: 'blob'
   })
 }
 
@@ -75,55 +35,6 @@ export const salesPrintPreview = (params) => {
   })
 }
 
-// 销售 统计查询
-export const salesCount = (params) => {
-  return axios({
-    url: `/sales/queryCount`,
-    data: params,
-    method: 'post'
-  })
-}
-
-//  销售 列表  有分页
-export const salesList = (params) => {
-  const url = `/sales/queryPage/${params.pageNo}/${params.pageSize}`
-  delete params.pageNo
-  delete params.pageSize
-  return axios({
-    url: url,
-    data: params,
-    method: 'post'
-  })
-}
-
-//  销售 提交
-export const salesWriteSubmit = (params) => {
-  return axios({
-    url: '/sales/submit',
-    data: params,
-    method: 'post'
-  })
-}
-//  财务收款 列表 分页
-export const salesReceiptList = (params) => {
-  const url = `/sales/queryPageByReceipt/${params.pageNo}/${params.pageSize}`
-  delete params.pageNo
-  delete params.pageSize
-  return axios({
-    url: url,
-    data: params,
-    method: 'post'
-  })
-}
-//  财务收款
-export const salesReceipt = (params) => {
-  return axios({
-    url: `/sales/receipt/${params.sn}`,
-    data: params,
-    method: 'get'
-  })
-}
-
 // 获取促销活动
 export const getPromoacActiveList = (params) => {
   return axios({
@@ -151,13 +62,7 @@ export const salesPromoCount = (params) => {
     method: 'post'
   })
 }
-// 销售  详情  该销售单的产品二级分类
-export const salesDetailProductType = (params) => {
-  return axios({
-    url: `/sales/detail/queryProductType/${params.sn}`,
-    method: 'get'
-  })
-}
+ 
 // 销售 详情  打印
 export const salesDetailPrint = params => {
   const url = `/sales/print/${params.priceType}`
@@ -190,115 +95,3 @@ export const salesDetailTypeExcel = params => {
     responseType: 'blob'
   })
 }
-// 删除全部已选产品
-export const deleteAll = (params) => {
-  return axios({
-    url: `/sales/detail/delete/all `,
-    method: 'post',
-    data: params
-  })
-}
-// 车架号
-export const supperCodeByVin = (params) => {
-  return axios({
-    url: `/vinIdentify/queryPartCodeByVin/${params.vin}`,
-    method: 'get'
-  })
-}
-// 车架号  识别图片内容
-export const vinCodeParse = params => {
-  return axios.request({
-    url: `/vinIdentify/ocr`,
-    method: 'post',
-    data: params,
-    responseType: 'blob'
-  })
-}
-// 是否更新价格判断
-export const submitCheck = (params) => {
-  return axios({
-    url: '/sales/submitCheck',
-    method: 'post',
-    data: params
-  })
-}
-// 当前价格  提交
-export const updateBatch = (params) => {
-  return axios({
-    url: '/sales/detail/updateBatch',
-    method: 'post',
-    data: params
-  })
-}
-
-// 仓库设置
-export const updateWarehouse = (params) => {
-  return axios({
-    url: '/sales/detail/updateWarehouse',
-    method: 'post',
-    data: params
-  })
-}
-
-//  按仓库查询销售单 列表  有分页
-export const queryPageForWarehouse = (params) => {
-  const url = `/sales/queryPageForWarehouse/${params.pageNo}/${params.pageSize}`
-  delete params.pageNo
-  delete params.pageSize
-  return axios({
-    url: url,
-    data: params,
-    method: 'post'
-  })
-}
-// 获取按仓库查询销售单数量
-export const queryCountForWarehouse = (params) => {
-  return axios({
-    url: '/sales/queryCountForWarehouse',
-    method: 'post',
-    data: params
-  })
-}
-// 按仓库查询销售明细 列表
-export const queryPageForWarehouseDetail = (params) => {
-  const url = `/sales/detail/queryPageForWarehouse/${params.pageNo}/${params.pageSize}`
-  delete params.pageNo
-  delete params.pageSize
-  return axios({
-    url: url,
-    data: params,
-    method: 'post'
-  })
-}
-
-// 获取按仓库查询销售单明细数量
-export const queryCountForWarehouseDetail = (params) => {
-  return axios({
-    url: '/sales/detail/queryCountForWarehouse',
-    method: 'post',
-    data: params
-  })
-}
-// 按仓库导出销售单
-
-export const exportForWarehouse = params => {
-  const url = `/sales/exportForWarehouse`
-  return axios.request({
-    url: url,
-    data: params,
-    method: 'post',
-    responseType: 'blob'
-  })
-}
-
-// 销售一览表 列表
-export const salesOverviewQueryPage = (params) => {
-  const url = `/salesOverview/queryPage/${params.pageNo}/${params.pageSize}`
-  delete params.pageNo
-  delete params.pageSize
-  return axios({
-    url: url,
-    data: params,
-    method: 'post'
-  })
-}

+ 0 - 187
src/api/salesDetail.js

@@ -1,136 +1,5 @@
 import { axios } from '@/utils/request'
 
-//  销售详情 删除
-export const salesDetailDel = (params) => {
-  return axios({
-    url: `/sales/detail/delete`,
-    data: params,
-    method: 'post'
-  })
-}
-
-// 批量删除
-export const salesDetailBatchDel = (params) => {
-  return axios({
-    url: `/sales/detail/delete/batch`,
-    data: params,
-    method: 'post'
-  })
-}
-
-// 一键发货
-export const salesDetailDispatchByOneKey = (params) => {
-  return axios({
-    url: `/sales/detail/dispatchByOneKey/${params.salesBillSn}`,
-    data: params,
-    method: 'post'
-  })
-}
-
-// 新增销售明细
-export const salesDetailInsert = (params) => {
-  return axios({
-    url: '/sales/detail/insert',
-    data: params,
-    method: 'post'
-  })
-}
-
-// 批量新增代发货信息
-export const insertBatchOfWaitDispatch = (params) => {
-  return axios({
-    url: '/sales/detail/insertBatchOfWaitDispatch',
-    data: params,
-    method: 'post'
-  })
-}
-
-// 销售详情列表分页
-export const salesDetailList = (params) => {
-  const url = `/sales/detail/queryPage/${params.pageNo}/${params.pageSize}`
-  delete params.pageNo
-  delete params.pageSize
-  return axios({
-    url: url,
-    data: params,
-    method: 'post'
-  })
-}
-
-// 销售详情列表不分页  不带库存
-export const salesDetailAllList = (params) => {
-  const url = `/sales/detail/query`
-  delete params.pageNo
-  delete params.pageSize
-  return axios({
-    url: url,
-    data: params,
-    method: 'post'
-  })
-}
-
-// 销售详情列表不分页  带库存
-export const salesDetailAllStockList = (params) => {
-  const url = `/sales/detail/queryStock`
-  delete params.pageNo
-  delete params.pageSize
-  return axios({
-    url: url,
-    data: params,
-    method: 'post'
-  })
-}
-
-// 缺货明细
-export const salesStockoutDetail = (params) => {
-  const url = `/sales/detail/queryPageStock`
-  delete params.pageNo
-  delete params.pageSize
-  return axios({
-    url: url,
-    data: params,
-    method: 'post'
-  })
-}
-
-// 销售列表  分页  带库存
-export const salesDetailStockList = (params) => {
-  const url = `/sales/detail/queryPageStock/${params.pageNo}/${params.pageSize}`
-  delete params.pageNo
-  delete params.pageSize
-  return axios({
-    url: url,
-    data: params,
-    method: 'post'
-  })
-}
-// 修改销售明细取消数量
-export const salesDetailUpdateCancelQty = (params) => {
-  return axios({
-    url: '/sales/detail/updateBatchCancelQty',
-    data: params,
-    method: 'post'
-  })
-}
-
-//  修改销售明细数量
-export const salesDetailUpdateQty = (params) => {
-  return axios({
-    url: '/sales/detail/updateQty',
-    data: params,
-    method: 'post'
-  })
-}
-
-//  销售详情 整单删除
-export const salesDetailDelAll = (params) => {
-  return axios({
-    url: `/sales/detail/deleteAll`,
-    data: params,
-    method: 'post'
-  })
-}
-
 // 获取产品适用活动的促销产品列表
 export const getPromoGoodsList = (params) => {
   const url = `/sales/detail/getPromoGoodsList/${params.pageNo}/${params.pageSize}`
@@ -181,60 +50,4 @@ export const salesDetailPromoProductList = (params) => {
     method: 'post'
   })
 }
-// 销售 下载模板
-export const salesDownload = params => {
-  return axios.request({
-    url: `/sales/detail/downloadExcel`,
-    method: 'post',
-    responseType: 'blob'
-  })
-}
-// 销售  解析导入的文件
-export const salesParseProducts = params => {
-  return axios({
-    url: '/sales/detail/parseProducts',
-    data: params,
-    method: 'post'
-  })
-}
-// 销售  批量插入
-export const salesBatchInsert = params => {
-  return axios({
-    url: '/sales/detail/batchInsert',
-    data: params,
-    method: 'post'
-  })
-}
-//  销售 导入产品 导出错误项
-export const salesFailExcel = (params) => {
-  const url = `/sales/detail/downloadFailExcel`
-  return axios.request({
-    url: url,
-    method: 'post',
-    data: params.list,
-    responseType: 'blob'
-  })
-}
 
-// 导出缺货明细
-export const exportStockout = params => {
-  const url = `/sales/detail/exportStockout`
-  delete params.priceType
-  return axios.request({
-    url: url,
-    data: params,
-    method: 'post',
-    responseType: 'blob'
-  })
-}
-// 导出分组缺货明细
-export const exportGroupStockout = params => {
-  const url = `/sales/detail/exportGroupStockout`
-  delete params.priceType
-  return axios.request({
-    url: url,
-    data: params,
-    method: 'post',
-    responseType: 'blob'
-  })
-}

+ 209 - 0
src/api/salesDetailNew.js

@@ -0,0 +1,209 @@
+import { axios } from '@/utils/request'
+
+//  销售详情 删除
+export const salesDetailDel = (params) => {
+  return axios({
+    url: `/sales/detail/delete`,
+    data: params,
+    method: 'post'
+  })
+}
+// 销售详情 统计 正常产品
+export const salesDetaiCount = (params) => {
+  return axios({
+    url: `/sales/detail/queryCount`,
+    data: params,
+    method: 'post'
+  })
+}
+// 活动产品统计
+export const salesPromoDetailCount = (params) => {
+  return axios({
+    url: `/salesPromo/detail/queryCount`,
+    data: params,
+    method: 'post'
+  })
+}
+// 批量删除
+export const salesDetailBatchDel = (params) => {
+  return axios({
+    url: `/sales/detail/delete/batch`,
+    data: params,
+    method: 'post'
+  })
+}
+// 仓库设置
+export const updateWarehouse = (params) => {
+    return axios({
+      url: '/sales/detail/updateWarehouse',
+      method: 'post',
+      data: params
+    })
+}
+// 删除全部已选产品
+export const deleteAll = (params) => {
+    return axios({
+      url: `/sales/detail/delete/all`,
+      method: 'post',
+      data: params
+    })
+  }
+
+// 新增销售明细
+export const salesDetailInsert = (params) => {
+  return axios({
+    url: '/sales/detail/insert',
+    data: params,
+    method: 'post'
+  })
+}
+// 批量新增销售明细
+export const salesBatchInsert = (params) => {
+  return axios({
+    url: `/sales/detail/insertBatch`,
+    data: params,
+    method: 'post'
+  })
+}
+//  销售 导入产品 导出错误项
+export const salesFailExcel = (params) => {
+  const url = `/sales/detail/exportImportError`
+  return axios.request({
+    url: url,
+    method: 'post',
+    data: params.list,
+    responseType: 'blob'
+  })
+} 
+// 销售详情列表分页
+export const salesDetailList = (params) => {
+  const url = `/sales/detail/queryPage/${params.pageNo}/${params.pageSize}`
+  delete params.pageNo
+  delete params.pageSize
+  return axios({
+    url: url,
+    data: params,
+    method: 'post'
+  })
+}
+
+// 销售详情列表不分页
+export const salesDetailAllList = (params) => {
+  const url = `/sales/detail/query`
+  delete params.pageNo
+  delete params.pageSize
+  return axios({
+    url: url,
+    data: params,
+    method: 'post'
+  })
+}
+
+//  修改销售明细数量
+export const salesDetailUpdateQty = (params) => {
+    return axios({
+        url: '/sales/detail/updateQty',
+        data: params,
+        method: 'post'
+    })
+}
+// 销售  解析导入的文件
+export const salesParseProducts = params => {
+    return axios({
+      url: '/sales/detail/importParse',
+      data: params,
+      method: 'post'
+    })
+  }
+// 禁用活动信息
+export const salesDisablePromo = params => {
+    return axios({
+      url: '/sales/detail/disablePromo',
+      data: params,
+      method: 'post'
+    })
+  }
+// 启用活动
+export const salesEnablePromoPromo = params => {
+  return axios({
+    url: '/sales/detail/enablePromo',
+    data: params,
+    method: 'post'
+  })
+}
+ // 更换活动
+ export const salesChangePromo = params => {
+  return axios({
+    url: '/sales/detail/changePromo',
+    data: params,
+    method: 'post'
+  })
+}
+// 新活动是否参与
+export const salesDetailAddPromo = (params) => {
+  return axios({
+    url: '/sales/detail/addPromo',
+    data: params,
+    method: 'post'
+  })
+}
+// 修改销售明细取消数量
+export const salesDetailUpdateCancelQty = (params) => {
+  return axios({
+    url: '/sales/detail/cancleOfBatch',
+    data: params,
+    method: 'post'
+  })
+}
+// 整单取消待下推
+export const salesDetailCancleOfAll = (params) => {
+  return axios({
+    url: '/sales/detail/cancelAll',
+    data: params,
+    method: 'post'
+  })
+}
+// 批量新增代发货信息
+export const insertBatchOfWaitDispatch = (params) => {
+    return axios({
+      url: '/sales/detail/pushOfBatch',
+      data: params,
+      method: 'post'
+    })
+  }
+
+// 缺货明细
+export const salesStockoutDetail = (params) => {
+  const url = `/oos/detail/queryBySales`
+  delete params.pageNo
+  delete params.pageSize
+  return axios({
+    url: url,
+    data: params,
+    method: 'post'
+  })
+}
+ 
+// 导出缺货明细
+export const exportStockout = params => {
+  const url = `/oos/detail/exportSalesOos`
+  delete params.priceType
+  return axios.request({
+    url: url,
+    data: params,
+    method: 'post',
+    responseType: 'blob'
+  })
+}
+// 导出分组缺货明细
+export const exportGroupStockout = params => {
+  const url = `/oos/detail/exportSalesOosByBrandType`
+  delete params.priceType
+  return axios.request({
+    url: url,
+    data: params,
+    method: 'post',
+    responseType: 'blob'
+  })
+}
+

+ 313 - 0
src/api/salesNew.js

@@ -0,0 +1,313 @@
+import { axios } from '@/utils/request'
+
+// 销售 统计查询
+export const salesCount = (params) => {
+    return axios({
+      url: `/sales/queryCount`,
+      data: params,
+      method: 'post'
+    })
+  }
+//  销售 列表  有分页
+export const salesList = (params) => {
+    const url = `/sales/queryPage/${params.pageNo}/${params.pageSize}`
+    delete params.pageNo
+    delete params.pageSize
+    return axios({
+        url: url,
+        data: params,
+        method: 'post'
+    })
+}
+//  销售 新增
+export const salesSave = (params) => {
+    return axios({
+      url: '/sales/insert',
+      data: params,
+      method: 'post'
+    })
+}
+// 销售 编辑
+export const salesModify = (params) => {
+    return axios({
+      url: '/sales/modifyWarehouse',
+      data: params,
+      method: 'post'
+    })
+  }
+//  销售 详情bysn
+export const salesDetailBySn = (params) => {
+    return axios({
+      url: `/sales/findBySn/${params.salesBillSn}`,
+      method: 'get'
+    })
+  }
+// 查询客户名称
+export const salesDetailByNo = (params) => {
+    return axios({
+      url: `/sales/findBySaleBillNo/${params.salesBillNo}`,
+      method: 'get'
+    })
+  }
+//  销售 删除
+export const salesDel = (params) => {
+    return axios({
+      url: `/sales/delete/${params.salesBillSn}`,
+      method: 'get'
+    })
+  }
+//  销售 取消
+export const salesCancle = (params) => {
+    return axios({
+      url: `/sales/cancle/${params.salesBillSn}`,
+      method: 'get'
+    })
+  }
+
+// 根据销售单sn查询参加的活动
+export const salesPromoQueryList = (params) => {
+    return axios({
+        url: `/salesPromo/queryExtList`,
+        data: params,
+        method: 'post'
+    })
+}
+// 更换促销,可更换活动列表
+export const salesPromoMatchProduct = (params) => {
+  return axios({
+      url: `/salesPromo/queryMatchProduct`,
+      data: params,
+      method: 'post'
+  })
+}
+// 判断是否有新的活动
+export const salesQueryUnPartPromo = (params) => {
+  return axios({
+      url: `/salesPromo/queryUnPartPromo/${params.salesBillSn}`,
+      data: params,
+      method: 'post'
+  })
+}
+// 活动优惠明细接口
+export const salesPromoQueryCount = (params) => {
+  return axios({
+      url: `/salesPromo/queryCount`,
+      data: params,
+      method: 'post'
+  })
+}
+
+// 更换促销活动
+export const queryMatchPromoProduct = (params) => {
+  return axios({
+      url: `/promotion/queryMatchProduct`,
+      data: params,
+      method: 'post'
+  })
+}
+
+// 提交时活动规则校验
+export const salesPromoValidaSubmit = (params) => {
+  return axios({
+      url: `/salesPromo/validationSubmit/${params.salesBillSn}`,
+      data: params,
+      method: 'post'
+  })
+}
+
+//  销售 审核通过
+export const salesWriteAuditPass = (params) => {
+  return axios({
+    url: '/sales/auditPass',
+    data: params,
+    method: 'post'
+  })
+}
+//  销售 审核驳回
+export const salesWriteAuditReject = (params) => {
+  return axios({
+    url: '/sales/auditReject',
+    data: params,
+    method: 'post'
+  })
+}
+//  销售 一键审核下推
+export const salesWriteAuditPush = (params) => {
+  return axios({
+    url: '/sales/auditPush',
+    data: params,
+    method: 'post'
+  })
+}
+//  销售 提交
+export const salesWriteSubmit = (params) => {
+  return axios({
+    url: '/sales/submit',
+    data: params,
+    method: 'post'
+  })
+}
+
+// 是否更新价格判断
+export const submitCheck = (params) => {
+  return axios({
+    url: '/sales/submitCheck',
+    method: 'post',
+    data: params
+  })
+}
+// 当前价格  提交
+export const updateBatch = (params) => {
+  return axios({
+    url: '/sales/detail/updateBatch',
+    method: 'post',
+    data: params
+  })
+}
+
+// 销售详情列表所有包括活动产品不分页
+export const salesDetailAllList = (params) => {
+  const url = `/sales/detail/queryAll`
+  return axios({
+    url: url,
+    data: params,
+    method: 'post'
+  })
+}
+
+// 查询可生成的费用报销单
+export const queryCreateBySalesBillSn = (params) => {
+  return axios({
+    url: `/expenseAccount/queryCreateBySalesBillSn/${params.salesBillSn}`,
+    data: params,
+    method: 'post'
+  })
+}
+// 保存费用报销单
+export const expenseAccountSave = (params) => {
+  return axios({
+    url: `/expenseAccount/saveCreate`,
+    data: params,
+    method: 'post'
+  })
+}
+
+
+//  销售 打印
+export const salesPrint = (params) => {
+  return axios({
+    url: '/sales/print',
+    data: params,
+    method: 'post'
+  })
+}
+//  销售 打印预览
+export const salesPrintPreview = (params) => {
+  return axios({
+    url: '/sales/printPreview',
+    data: params,
+    method: 'post'
+  })
+}
+// 销售  详情  该销售单的产品二级分类
+export const salesDetailProductType = (params) => {
+  return axios({
+    url: `/sales/detail/queryProductType/${params.sn}`,
+    method: 'get'
+  })
+}
+// 销售 详情  打印
+export const salesDetailPrint = params => {
+  const url = `/sales/print/${params.priceType}`
+  delete params.priceType
+  return axios.request({
+    url: url,
+    data: params,
+    method: 'post',
+    responseType: 'blob'
+  })
+}
+// 销售 详情  导出
+export const salesDetailExcel = params => {
+  const url = `/sales/excel/${params.priceType}`
+  delete params.priceType
+  return axios.request({
+    url: url,
+    data: params,
+    method: 'post',
+    responseType: 'blob'
+  })
+}
+// 销售 详情  分类导出
+export const salesDetailTypeExcel = params => {
+  const url = `/sales/detail/typeExcel`
+  return axios.request({
+    url: url,
+    data: params,
+    method: 'post',
+    responseType: 'blob'
+  })
+}
+
+
+// 仓库销售单
+//  按仓库查询销售单 列表  有分页
+export const queryPageForWarehouse = (params) => {
+  const url = `/sales/queryPageForWarehouse/${params.pageNo}/${params.pageSize}`
+  delete params.pageNo
+  delete params.pageSize
+  return axios({
+    url: url,
+    data: params,
+    method: 'post'
+  })
+}
+// 获取按仓库查询销售单数量
+export const queryCountForWarehouse = (params) => {
+  return axios({
+    url: '/sales/queryCountForWarehouse',
+    method: 'post',
+    data: params
+  })
+}
+// 按仓库查询销售明细 列表
+export const queryPageForWarehouseDetail = (params) => {
+  const url = `/sales/detail/queryPageForWarehouse/${params.pageNo}/${params.pageSize}`
+  delete params.pageNo
+  delete params.pageSize
+  return axios({
+    url: url,
+    data: params,
+    method: 'post'
+  })
+}
+
+// 获取按仓库查询销售单明细数量
+export const queryCountForWarehouseDetail = (params) => {
+  return axios({
+    url: '/sales/detail/queryCountForWarehouse',
+    method: 'post',
+    data: params
+  })
+}
+// 按仓库导出销售单
+export const exportForWarehouse = params => {
+  const url = `/sales/exportForWarehouse`
+  return axios.request({
+    url: url,
+    data: params,
+    method: 'post',
+    responseType: 'blob'
+  })
+}
+// 销售一览表 列表
+export const salesOverviewQueryPage = (params) => {
+  const url = `/salesOverview/queryPage/${params.pageNo}/${params.pageSize}`
+  delete params.pageNo
+  delete params.pageSize
+  return axios({
+    url: url,
+    data: params,
+    method: 'post'
+  })
+}

+ 17 - 0
src/api/salesReturn.js

@@ -291,3 +291,20 @@ export const queryOverviewPage = (params) => {
     method: 'post'
   })
 }
+
+// 抓单  设置退货单价
+export const grabSalesBill = (params) => {
+  return axios({
+    url: '/salesReturn/detail/grabSalesBill',
+    data: params,
+    method: 'post'
+  })
+}
+// 判断 各级别价格不完整,不让提交
+export const submitVerify = (params) => {
+  return axios({
+    url: '/salesReturn/submitVerify',
+    data: params,
+    method: 'post'
+  })
+}

+ 22 - 0
src/api/stock.js

@@ -59,6 +59,28 @@ export const queryStockProductPage = (params) => {
     method: 'post'
   })
 }
+// 非经销商产品库存列表
+export const queryStockProductForOtherPage = (params) => {
+  const url = `/stock/queryStockProductForOtherPage/${params.pageNo}/${params.pageSize}`
+  delete params.pageNo
+  delete params.pageSize
+  return axios({
+    url: url,
+    data: params,
+    method: 'post'
+  })
+}
+// 分页查询促销产品
+export const queryPromoProductPage = (params) => {
+  const url = `/stock/queryPromoProductPage/${params.pageNo}/${params.pageSize}`
+  delete params.pageNo
+  delete params.pageSize
+  return axios({
+    url: url,
+    data: params,
+    method: 'post'
+  })
+}
 
 //  出入库明细 列表  有分页
 export const stockFlowList = (params) => {

+ 1 - 1
src/api/waitDispatchDetail.js

@@ -48,7 +48,7 @@ export const waitDispatchDetailList = (params) => {
 
 // 列表  不分页
 export const waitDispatchDetailAllList = (params) => {
-  const url = `/dispatch/detail/query`
+  const url = `/dispatch/detail/queryPushing`
   delete params.pageNo
   delete params.pageSize
   return axios({

+ 4 - 1
src/components/Table/index.js

@@ -235,6 +235,9 @@ export default {
         })
       }
     },
+    addRowData(data){
+      this.localDataSource.push(data)
+    },
     initTotalList (columns) {
       const totalList = []
       columns && columns instanceof Array && columns.forEach(column => {
@@ -361,7 +364,7 @@ export default {
         // 自定义属性,也就是官方文档中的props,可通过条件来控制样式
         style: {
           //  设置行背景色
-          'background-color': record[this.rowKeyName] === this.leftAlignId ? '#fff1c5' : ''
+          'background-color': record[this.rowKeyName] === this.leftAlignId ? '#ffedeb' : ''
         },
         on: {
           // 鼠标单击行

+ 20 - 10
src/components/UploadFile/index.vue

@@ -7,6 +7,7 @@
       :disabled="disabled"
       @preview="handlePreview"
       @change="handleChange"
+      :headers="headers"
       :remove="handleRemove"
       :beforeUpload="beforeUpload"
       :data="params"
@@ -94,7 +95,10 @@ export default {
       previewImage: '',
       fileList: [],
       comVal: this.value,
-      params: this.uploadParams
+      params: this.uploadParams,
+      headers: {
+        'access-token': this.$store.state.user.token
+      }
     }
   },
   methods: {
@@ -139,16 +143,22 @@ export default {
       this.previewVisible = false
     },
     handlePreview (file) {
-      // if (this.listType == 'text') {
-      //   return
-      // }
-      // console.log(file)
-      if (file.response.status == 200) {
-        this.previewImage = file.response.data
-      } else {
-        this.previewImage = file.url || file.thumbUrl
+      console.log(file)
+      if (file.type && (file.type.indexOf('image') >= 0 || file.type.indexOf('video') >= 0)) {
+        if (file.response && file.response.status && file.response.status == 200) {
+          const src = file.response.data
+          this.previewImage = src && Array.isArray(src) ? src[0] && src[0].filePath : src
+        } else {
+          this.previewImage = file.url || file.thumbUrl
+        }
+        this.previewVisible = true
+      }else{
+        const src = file.response.data
+        if(!Array.isArray(src)){
+          this.previewImage = file.url || file.thumbUrl
+          this.previewVisible = true
+        }
       }
-      this.previewVisible = true
     },
     handleRemove (file) {
       this.$emit('remove')

+ 3 - 3
src/components/custom.less

@@ -151,18 +151,18 @@ body{
     }
     &:hover{
       td{
-        background: #ffb60a!important;
+        background: #fff2f0!important;
       }
     }
   }
   .ant-pagination.ant-table-pagination{
     margin: 10px 0 0;
   }
-  .ant-table-small > .ant-table-content .ant-table-body,.ant-table-fixed-right{
+  .ant-table-small > .ant-table-content .ant-table-body,.ant-table-fixed-right,.ant-table-fixed-left{
     margin: 0;
     tr:hover{
       td{
-        background: #ffb60a;
+        background: #fff2f0!important;
       }
     }
   }

+ 51 - 1
src/components/index.less

@@ -11,12 +11,18 @@
     text-overflow:ellipsis;    
     white-space: nowrap;
 }
-.text-overflows{
+.text-overflows3{
     display: -webkit-box;    
     -webkit-box-orient: vertical;    
     -webkit-line-clamp: 3;    
     overflow: hidden;
 }
+.text-overflows2{
+    display: -webkit-box;    
+    -webkit-box-orient: vertical;    
+    -webkit-line-clamp: 2;    
+    overflow: hidden;
+}
 
 
 /* 扩展ant design pro按钮组件颜色 */
@@ -93,6 +99,24 @@
     border-color: #c8c9cc;
   }
 }
+.ant-btn-primary.button-gray {
+  background-color: #eee;
+  border-color: #eee;
+  color:#39f;
+  margin: 0 5px;
+  font-size: 12px;
+  &:hover, &:focus {
+    background-color: #e0e0e0;
+     color:#39f;
+    border-color: #e0e0e0;
+  }
+ 
+  &:active, &.active {
+  background-color: #e0e0e0;
+   color:#39f;
+  border-color: #e0e0e0;
+  }
+}
 
 // btn-link
 .ant-btn-link.button-primary,.ant-btn-link.button-info,.ant-btn-link.button-warning,.ant-btn-link.button-purple,.ant-btn-link.button-geekblue {
@@ -134,6 +158,21 @@
     color: #8e8f91;
   }
 }
+.ant-btn-primary.button-warn {
+  background-color: #f90;
+  border-color: #f90;
+  margin: 0 5px;
+  font-size: 12px;
+  &:hover, &:focus {
+    background-color: #ffb60a;
+    border-color: #ffb60a;
+  }
+ 
+  &:active, &.active {
+    background-color: #dd8500;
+    border-color: #dd8500;
+  }
+}
 .ant-btn-link.button-grey {
   color: #82848a;
   &:hover, &:focus {
@@ -383,3 +422,14 @@
     color: #ed1c24;
   }
 }
+
+// 确认框居中
+.confirm-center{
+  .ant-modal-confirm-body > .anticon + .ant-modal-confirm-title + .ant-modal-confirm-content{
+    margin-left:0;
+  }
+  .ant-modal-confirm-btns{
+    float: none;
+    text-align: center;
+  }
+}

+ 2 - 2
src/components/newThem.less

@@ -1,5 +1,5 @@
 @font-size-base: 12px;
-@table-row-hover-bg: color(~`colorPalette('@{warning-color}', 3) `);
+@table-row-hover-bg: color(~`colorPalette('@{primary-color}', 0.5) `);
 @text-color: fade(@black, 100%);
 @disabled-bg: #fafafa;
 @modal-body-padding: 15px;
@@ -24,7 +24,7 @@
 @ve-table-body-row-highlight-background-color: color(~`colorPalette('@{primary-color}', 1) `);
  
 .ve-table .ve-table-container .ve-table-content-wrapper table.ve-table-content{
-    // border-bottom: 1px solid #ddd;
+    border-bottom: 1px solid #ddd;
 }
 .ve-table .ve-table-container .ve-table-content-wrapper table.ve-table-content thead.ve-table-header tr.ve-table-header-tr th.ve-table-header-th{
     font-weight: 900;

+ 78 - 116
src/config/router.config.js

@@ -119,7 +119,7 @@ export const asyncRouterMap = [
       // 销售管理
       {
         path: '/salesManagement',
-        redirect: '/salesManagement/salesQuery',
+        redirect: '/salesManagement/salesQueryNew',
         component: PageView,
         meta: {
           title: '销售管理',
@@ -128,9 +128,9 @@ export const asyncRouterMap = [
         },
         children: [
           {
-            path: '/salesManagement/salesQuery',
-            redirect: '/salesManagement/salesQuery/list',
-            name: 'salesQuery',
+            path: '/salesManagement/salesQueryNew',
+            redirect: '/salesManagement/salesQueryNew/list',
+            name: 'salesQueryNew',
             component: BlankLayout,
             meta: {
               title: '销售单查询',
@@ -141,8 +141,8 @@ export const asyncRouterMap = [
             children: [
               {
                 path: 'list',
-                name: 'salesQueryList',
-                component: () => import(/* webpackChunkName: "salesManagement" */ '@/views/salesManagement/salesQuery/list.vue'),
+                name: 'salesQueryNewList',
+                component: () => import(/* webpackChunkName: "salesManagement" */ '@/views/salesManagement/salesQueryNew/list.vue'),
                 meta: {
                   title: '销售单列表',
                   icon: 'monitor',
@@ -152,8 +152,8 @@ export const asyncRouterMap = [
               },
               {
                 path: 'detail/:sn',
-                name: 'salesDetail',
-                component: () => import(/* webpackChunkName: "salesManagement" */ '@/views/salesManagement/salesQuery/detail.vue'),
+                name: 'salesNewDetail',
+                component: () => import(/* webpackChunkName: "salesManagement" */ '@/views/salesManagement/salesQueryNew/detail.vue'),
                 meta: {
                   title: '销售单详情',
                   icon: 'monitor',
@@ -164,8 +164,8 @@ export const asyncRouterMap = [
               },
               {
                 path: 'detail/:sn',
-                name: 'salesDetailAudit',
-                component: () => import(/* webpackChunkName: "salesManagement" */ '@/views/salesManagement/salesQuery/detail.vue'),
+                name: 'salesNewDetailAudit',
+                component: () => import(/* webpackChunkName: "salesManagement" */ '@/views/salesManagement/salesQueryNew/detail.vue'),
                 meta: {
                   title: '销售单审核',
                   icon: 'monitor',
@@ -176,8 +176,8 @@ export const asyncRouterMap = [
               },
               {
                 path: 'add/:sn',
-                name: 'salesAdd',
-                component: () => import(/* webpackChunkName: "salesManagement" */ '@/views/salesManagement/salesQuery/edit.vue'),
+                name: 'salesNewAdd',
+                component: () => import(/* webpackChunkName: "salesManagement" */ '@/views/salesManagement/salesQueryNew/edit.vue'),
                 meta: {
                   title: '新增销售单',
                   icon: 'monitor',
@@ -187,8 +187,8 @@ export const asyncRouterMap = [
               },
               {
                 path: 'edit/:sn',
-                name: 'salesEdit',
-                component: () => import(/* webpackChunkName: "salesManagement" */ '@/views/salesManagement/salesQuery/edit.vue'),
+                name: 'salesNewEdit',
+                component: () => import(/* webpackChunkName: "salesManagement" */ '@/views/salesManagement/salesQueryNew/edit.vue'),
                 meta: {
                   title: '编辑销售单',
                   icon: 'monitor',
@@ -198,8 +198,8 @@ export const asyncRouterMap = [
               },
               {
                 path: 'waitDispatch/:salesBillSn',
-                name: 'waitDispatch',
-                component: () => import(/* webpackChunkName: "salesManagement" */ '@/views/salesManagement/waitDispatch/edit.vue'),
+                name: 'waitDispatchNew',
+                component: () => import(/* webpackChunkName: "salesManagement" */ '@/views/salesManagement/waitDispatchNew/edit.vue'),
                 meta: {
                   title: '下推销售单',
                   icon: 'monitor',
@@ -1102,17 +1102,6 @@ export const asyncRouterMap = [
                   permission: 'B_eRdetail'
                 }
               },
-              {
-                path: 'add',
-                name: 'expenseReimbursementAdd',
-                component: () => import(/* webpackChunkName: "expenseManagement" */ '@/views/expenseManagement/expenseReimbursement/add.vue'),
-                meta: {
-                  title: '新增费用报销单',
-                  icon: 'monitor',
-                  hidden: true,
-                  permission: 'B_ERtEdit'
-                }
-              },
               {
                 path: 'edit/:sn',
                 name: 'expenseReimbursementEdit',
@@ -1819,6 +1808,31 @@ export const asyncRouterMap = [
               }
             }]
           },
+          {
+            path: '/reportData/promotionSalesRealTimeReport',
+            redirect: '/reportData/promotionSalesRealTimeReport/index',
+            name: 'promotionSalesRealTimeReport',
+            component: BlankLayout,
+            meta: {
+              title: '促销销售单报表',
+              icon: 'profile',
+              permission: 'M_promotionSalesRealTimeReportList'
+            },
+            hideChildrenInMenu: true,
+            children: [
+              {
+                path: 'index',
+                name: 'promotionSalesRealTimeReportIndex',
+                component: () => import(/* webpackChunkName: "reportData" */ '@/views/reportData/promotionSalesRealTimeReport/index.vue'),
+                meta: {
+                  title: '促销销售单报表',
+                  icon: 'profile',
+                  hidden: true,
+                  permission: 'M_promotionSalesRealTimeReportList'
+                }
+              }
+            ]
+          },
           {
             path: '/reportData/allocationOrderTotal',
             redirect: '/reportData/allocationOrderTotal/list',
@@ -3227,124 +3241,72 @@ export const asyncRouterMap = [
         },
         children: [
           {
-            path: '/promotionRulesManagement/promotionRules',
-            redirect: '/promotionRulesManagement/promotionRules/list',
-            name: 'promotionRules',
+            path: '/promotionRulesManagement/promotionManagement',
+            redirect: '/promotionRulesManagement/promotionManagement/list',
+            name: 'promotionManagement',
             component: BlankLayout,
             meta: {
-              title: '促销规则管理',
-              icon: 'thunderbolt',
-              permission: 'M_promotionRulesList'
+              title: '修理厂促销',
+              icon: 'file-ppt',
+              permission: 'M_promotionManagementList'
             },
             hideChildrenInMenu: true,
             children: [
               {
                 path: 'list',
-                name: 'promotionRulesManagementList',
-                component: () => import(/* webpackChunkName: "promotionRulesManagement" */ '@/views/promotionRulesManagement/promotionRules/list.vue'),
+                name: 'promotionManagementList',
+                component: () => import(/* webpackChunkName: "promotionRulesManagement" */ '@/views/promotionRulesManagement/promotionManagement/list.vue'),
                 meta: {
-                  title: '促销规则列表',
-                  icon: 'thunderbolt',
+                  title: '修理厂促销列表',
+                  icon: 'file-ppt',
                   hidden: true,
-                  permission: 'M_promotionRulesList'
-                }
-              },
-              {
-                path: 'detail/:id/:sn',
-                name: 'promotionRulesManagementDetail',
-                component: () => import(/* webpackChunkName: "promotionRulesManagement" */ '@/views/promotionRulesManagement/promotionRules/detail.vue'),
-                meta: {
-                  title: '促销规则详情',
-                  icon: 'thunderbolt',
-                  hidden: true
-                  // permission: 'B_goodsManage_edit'
-                }
-              },
-              {
-                path: 'rule/:id/:sn',
-                name: 'promotionRulesManagementRule',
-                component: () => import(/* webpackChunkName: "promotionRulesManagement" */ '@/views/promotionRulesManagement/promotionRules/rule.vue'),
-                meta: {
-                  title: '促销规则设置',
-                  icon: 'thunderbolt',
-                  replaceTab: true,
-                  hidden: true
-                  // permission: 'B_goodsManage_edit'
+                  permission: 'M_promotionManagementList'
                 }
               }
             ]
           },
           {
-            path: '/promotionRulesManagement/orderStatistics',
-            redirect: '/promotionRulesManagement/orderStatistics/list',
-            name: 'orderStatistics',
+            path: '/promotionRulesManagement/dealerPromotions',
+            redirect: '/promotionRulesManagement/dealerPromotions/list',
+            name: 'dealerPromotionManagement',
             component: BlankLayout,
             meta: {
-              title: '促销订单统计',
-              icon: 'contacts',
-              permission: 'M_orderStatisticsList'
+              title: '经销商促销',
+              icon: 'setting',
+              permission: 'M_dealerPromotionManagementList'
             },
             hideChildrenInMenu: true,
             children: [
               {
                 path: 'list',
-                name: 'orderStatisticsList',
-                component: () => import(/* webpackChunkName: "promotionRulesManagement" */ '@/views/promotionRulesManagement/orderStatistics/list.vue'),
+                name: 'dealerPromotionManagementList',
+                component: () => import(/* webpackChunkName: "dealerManagement" */ '@/views/promotionRulesManagement/dealerPromotions/list.vue'),
                 meta: {
-                  title: '订单统计列表',
-                  icon: 'contacts',
+                  title: '经销商促销',
+                  icon: 'setting',
                   hidden: true,
-                  permission: 'M_orderStatisticsList'
+                  permission: 'M_dealerPromotionManagementList'
                 }
-              }
-            ]
-          },
-          {
-            path: '/promotionRulesManagement/productStatistics',
-            redirect: '/promotionRulesManagement/productStatistics/list',
-            name: 'productStatistics',
-            component: BlankLayout,
-            meta: {
-              title: '促销产品统计',
-              icon: 'file-ppt',
-              permission: 'M_productStatisticsList'
-            },
-            hideChildrenInMenu: true,
-            children: [
+              },
               {
-                path: 'list',
-                name: 'productStatisticsList',
-                component: () => import(/* webpackChunkName: "promotionRulesManagement" */ '@/views/promotionRulesManagement/productStatistics/list.vue'),
+                path: 'detail',
+                name: 'dealerPromotionManagementDetail',
+                component: () => import(/* webpackChunkName: "promotionRulesManagement" */ '@/views/promotionRulesManagement/dealerPromotions/detail.vue'),
                 meta: {
-                  title: '产品统计列表',
-                  icon: 'file-ppt',
-                  hidden: true,
-                  permission: 'M_productStatisticsList'
+                  title: '促销活动详情',
+                  icon: 'thunderbolt',
+                  hidden: true
                 }
-              }
-            ]
-          },
-          {
-            path: '/promotionRulesManagement/promotionManagement',
-            redirect: '/promotionRulesManagement/promotionManagement/list',
-            name: 'promotionManagement',
-            component: BlankLayout,
-            meta: {
-              title: '修理厂促销',
-              icon: 'file-ppt',
-              permission: 'M_promotionManagementList'
-            },
-            hideChildrenInMenu: true,
-            children: [
+              },
               {
-                path: 'list',
-                name: 'promotionManagementList',
-                component: () => import(/* webpackChunkName: "promotionRulesManagement" */ '@/views/promotionRulesManagement/promotionManagement/list.vue'),
+                path: 'ruleSet',
+                name: 'dealerPromotionManagementRule',
+                component: () => import(/* webpackChunkName: "promotionRulesManagement" */ '@/views/promotionRulesManagement/dealerPromotions/detail.vue'),
                 meta: {
-                  title: '促销列表',
-                  icon: 'file-ppt',
-                  hidden: true,
-                  permission: 'M_promotionManagementList'
+                  title: '促销规则设置',
+                  icon: 'thunderbolt',
+                  replaceTab: true,
+                  hidden: true
                 }
               }
             ]

+ 2 - 1
src/libs/JGPrint.js

@@ -397,6 +397,7 @@ export const jGPrintPdf = function (data, type, taskName, printLogParams, callba
       }
     }
     LODOP.ADD_PRINT_PDF(0, 0, '100%', '100%', dataurl.replace('data:application/pdf;base64,', ''))
+
     if (type == 'preview') { //  预览
       LODOP.PREVIEW()
     } else if (type == 'print') { //  打印
@@ -481,7 +482,7 @@ export const jGPrintBase64Pdf = function (dataurl, type, taskName, printLogParam
      LODOP.NewPageA()
      LODOP.ADD_PRINT_PDF(0, 0, '100%', '100%', dataurl[i])
   }
- 
+
   if (type == 'preview') { //  预览
     LODOP.PREVIEW()
   } else if (type == 'print') { //  打印

+ 16 - 1
src/libs/tools.js

@@ -3,7 +3,22 @@ export const getOperationalPrecision = (num1, num2) => {
   const val = ((num1 * 10000) * (num2 * 10000) / 100000000).toFixed(2) || 0
   return val != 0 ? val : 0
 }
-
+// 加粗替换字符串中的金额
+export const boldAmounts = (text) => {
+    let regex = /(\d+\.?\d*)元/g;
+    let regex5 = /(\d+\.?\d*)件/g;
+    let regex1 = /再满(\d+\.?\d*)元,可享受优惠/g;
+    let regex4 = /再满(\d+\.?\d*)件产品可享受优惠/g;
+    let regex2 = /(\d+\.?\d*)(/g
+    let regex3 = /选择(\d+\.?\d*)个/g
+    let rext = text.replace(regex1, '<b>再满$1元,可享受优惠</b>');
+    rext = rext.replace(regex4, '<b>再满$1件产品可享受优惠</b>');
+    rext = rext.replace(regex, '<span>$1</span>元');
+    rext = rext.replace(regex5, '<span>$1</span>件');
+    rext = rext.replace(regex2, '<span>$1</span>(');
+    rext = rext.replace(regex3, '选择<span>$1</span>个');
+    return rext;
+}
 // 金额转大写
 export const dealBigMoney = (n) => {
   if (!/^(0|[1-9]\d*)(\.\d+)?$/.test(n)) { return '数据非法' }

+ 4 - 0
src/store/modules/app.js

@@ -42,6 +42,10 @@ const app = {
     curActionPermission: '', // 当前激活状态的权限码
     showPdfPrintView: false, // pdf 打印预览
     pdfUrl: '',
+    productBrandAllList: null, // 产品品牌列表
+    productTypeAllList: null, // 产品分类列表
+    warehouseAuthList: null, // 有权限的仓库列表
+    warehouseAllList: null, // 无权限所有仓库列表
     defWarehouse: null, // 默认仓库
     isWarehouse: false// 仓库管理权限
   },

+ 3 - 2
src/utils/mixin.js

@@ -1,6 +1,6 @@
 // import Vue from 'vue'
 import { deviceEnquire, DEVICE_TYPE } from '@/utils/device'
-import { toThousands } from '@/libs/tools'
+import { toThousands, boldAmounts } from '@/libs/tools'
 import { mapState } from 'vuex'
 
 // const mixinsComputed = Vue.config.optionMergeStrategies.computed
@@ -80,7 +80,8 @@ const AppDeviceEnquire = {
 const commonMixin = {
   data(){
     return {
-      toThousands
+      toThousands,
+      boldAmounts
     }
   },
   computed:{

+ 1 - 1
src/utils/util.js

@@ -228,7 +228,7 @@ export function getAuthPriceCode (config, router, store) {
     
     // 从所有的权限菜单中查找当前权限code对应的权限菜单数据
     const authNode = treeFind(authTree,(item)=>item.code == authCode)
-    console.log(authNode)
+    // console.log(authNode)
     if(!authNode.permission){return []}
     // 从找到的对应权限菜单数据中判断当前调用接口的url是否存在,这里和权限菜单中的后台权限code比较
     const hasReqUrl = authNode.permission.split(',').find(item => url.replace(/\//g,'_').indexOf(item)>=0)

+ 3 - 2
src/views/allocationManagement/transferOut/edit.vue

@@ -353,7 +353,7 @@ import printModal from './printModal.vue'
 import dsModal from './dsModal.vue'
 import commonModal from '@/views/common/commonModal.vue'
 import { printBase64Fun, exportExcel } from '@/libs/JGPrint.js'
-import { queryStockProductPage } from '@/api/stock'
+import { queryStockProductPage, queryStockProductForOtherPage } from '@/api/stock'
 import { productPriceInfo } from '@/api/product'
 import { departmentQueryList } from '@/api/expenseManagement'
 import { allocateBillDetailList, allocateBillDetailCount, allocateBillDetail, allocateBillDetailSave, allocateBillSubmit, allocateBillDetailDel, allocateBillDetailDelAll, allocateBillDetailPrint, allocateBillBatchInsert, allocateBillDetailExcel, updateBatchDepartment } from '@/api/allocateBill'
@@ -387,7 +387,8 @@ export default {
         this.disabled = true
         const dealerLevel = this.$route.params.dealerLevel == 'OTHER' ? undefined : this.$route.params.dealerLevel
         const warehouseSn = this.basicInfoData.warehouseSn
-        return queryStockProductPage(Object.assign(parameter, this.queryParam, { zeroQtyFlag: '0', dealerLevel: dealerLevel, warehouseSn: warehouseSn })).then(res => {
+        const fun = this.$route.params.dealerLevel == 'OTHER' ? queryStockProductForOtherPage : queryStockProductPage
+        return fun(Object.assign(parameter, this.queryParam, { zeroQtyFlag: '0', dealerLevel: dealerLevel, warehouseSn: warehouseSn })).then(res => {
           const data = res.data
           const no = (data.pageNo - 1) * data.pageSize
           for (var i = 0; i < data.list.length; i++) {

+ 178 - 38
src/views/common/chooseBrandModal.vue

@@ -10,18 +10,20 @@
     :width="800">
     <div class="chooseBrand-con">
       <div>
-        <a-checkbox :checked="checkAll" @change="onCheckAllChange">全选</a-checkbox>
+        <a-checkbox :checked="checkAll" :disabled="disabledList.length>0" @change="onCheckAllChange">全选</a-checkbox>
+        <span v-if="pageType==='1'">
+          <a-checkbox :checked="checkOwn" @change="onCheckOwnChange">自主品牌</a-checkbox>
+          <a-checkbox :checked="checkAgent" @change="onCheckAgentChange">代理品牌</a-checkbox>
+        </span>
       </div>
       <a-divider />
-      <a-checkbox-group v-model="checkedList" @change="onChange" style="width: 100%;">
-        <a-row style="height: 400px;overflow-y: scroll;">
-          <a-col :span="6" v-for="item in brandList" :key="item.brandSn">
-            <a-checkbox :value="item.brandSn">
-              {{ item.brandName }}
-            </a-checkbox>
-          </a-col>
-        </a-row>
-      </a-checkbox-group>
+      <a-row style="height: 400px;overflow-y: scroll;">
+        <a-col :span="6" v-for="(item,index) in brandList" :key="item.brandSn">
+          <a-checkbox :checked="item.checked" :disabled="item.isDisabled" @change="e=>onChange(e,index)">
+            {{ item.brandName }}
+          </a-checkbox>
+        </a-col>
+      </a-row>
       <!-- 按钮 -->
       <div class="btn-con">
         <a-button
@@ -56,69 +58,209 @@ export default {
       default: () => {
         return []
       }
+    },
+    pageType: { //  弹框显示状态
+      type: [String, Number],
+      default: ''
     }
   },
   data () {
     return {
       isShow: this.openModal, //  是否打开弹框
       checkAll: false, //  全选
+      checkOwn: false, // 自主品牌
+      checkAgent: false, // 代理品牌
       checkedList: [], //  选中项
       checkedRowList: [], //  选中项
-      brandList: [] //  品牌数据
+      brandList: [], //  品牌数据
+      brandOwnList: [],
+      brandAgentList: [],
+      disabledList: []
     }
   },
   methods: {
     // 保存
     handleSave () {
       const _this = this
-      if (this.checkedList.length < 1) {
-        this.$message.warning('请在列表勾选后再进行操作!')
-        return
-      }
       this.checkedRowList = []
       _this.brandList.map(item => {
-        if (_this.checkedList.indexOf(item.brandSn) != -1) {
+        if (item.checked) {
           _this.checkedRowList.push(item)
         }
       })
+      if (this.checkedRowList.length < 1) {
+        this.$message.warning('请在列表勾选后再进行操作!')
+        return
+      }
       this.$emit('ok', this.checkedRowList)
       this.isShow = false
     },
     // change
-    onChange (checkedList) {
-      const _this = this
-      this.checkAll = checkedList.length === this.brandList.length
-      this.brandList.map(item => {
-        if (_this.checkedList.indexOf(item.brandSn) != -1) {
-          _this.checkedRowList.push(item)
+    onChange (e, pos) {
+      this.brandList[pos].checked = e.target.checked
+      // 全选
+      const isCheckAllFlag = this.brandList.every(item => item.checked)
+      if (isCheckAllFlag) {
+        this.checkAll = true
+      } else {
+        this.checkAll = false
+      }
+      // 自主
+      const isCheckOwnFlag = this.brandList.every(item => {
+        if (item.brandType == 1) {
+          return item.checked
+        }
+      })
+      if (isCheckOwnFlag) {
+        this.checkOwn = true
+      } else {
+        this.checkOwn = false
+      }
+      // 代理
+      const isCheckAgentFlag = this.brandList.every(item => {
+        if (item.brandType == 2) {
+          return item.checked
         }
       })
+      if (isCheckAgentFlag) {
+        this.checkAgent = true
+      } else {
+        this.checkAgent = false
+      }
+      this.$forceUpdate()
     },
     // 全选
     onCheckAllChange (e) {
       const _this = this
       this.checkAll = e.target.checked
+      this.checkOwn = false
+      this.checkAgent = false
       if (e.target.checked) {
-        this.checkedList = []
-        this.checkedRowList = []
-        this.brandList.map(item => {
-          _this.checkedList.push(item.brandSn)
-          _this.checkedRowList.push(item)
+        this.brandList.forEach(item => {
+          item.checked = true
+        })
+      } else {
+        this.brandList.map(con => {
+          con.checked = false
+        })
+      }
+    },
+    onCheckOwnChange (e) {
+      const _this = this
+      this.checkAll = false
+      this.checkOwn = e.target.checked
+      this.checkAgent = false
+      const disArr = _this.chooseData.map(item => item.goodsSn)
+      if (e.target.checked) {
+        this.brandList.forEach(item => {
+          item.checked = false
+          if (item.brandType == 1) {
+            item.checked = true
+          }
+          if (this.disabledList && this.disabledList.length > 0) {
+            if (this.disabledList.includes(item.brandSn)) {
+              item.checked = false
+            }
+          }
+          if (this.chooseData && this.chooseData.length > 0) {
+            if (disArr.includes(item.brandSn)) {
+              item.checked = true
+            }
+          }
         })
       } else {
-        this.checkedList = []
-        this.checkedRowList = []
+        this.brandList.forEach(con => {
+          if (con.brandType == 1) {
+            con.checked = false
+          }
+          if (this.disabledList && this.disabledList.length > 0) {
+            if (this.disabledList.includes(con.brandSn)) {
+              con.checked = false
+            }
+          }
+          if (this.chooseData && this.chooseData.length > 0) {
+            if (disArr.includes(con.brandSn)) {
+              con.checked = true
+            }
+          }
+        })
+      }
+    },
+    onCheckAgentChange (e) {
+      const _this = this
+      this.checkAll = false
+      this.checkOwn = false
+      this.checkAgent = e.target.checked
+      const disArr = _this.chooseData.map(item => item.goodsSn)
+      if (e.target.checked) {
+        this.brandList.forEach(item => {
+          item.checked = false
+          if (item.brandType == 2) {
+            item.checked = true
+          }
+          if (this.disabledList && this.disabledList.length > 0) {
+            if (this.disabledList.includes(item.brandSn)) {
+              item.checked = false
+            }
+          }
+          if (this.chooseData && this.chooseData.length > 0) {
+            if (disArr.includes(item.brandSn)) {
+              item.checked = true
+            }
+          }
+        })
+      } else {
+        this.brandList.forEach(con => {
+          if (con.brandType == 2) {
+            con.checked = false
+          }
+          if (this.disabledList && this.disabledList.length > 0) {
+            if (this.disabledList.includes(con.brandSn)) {
+              con.checked = false
+            }
+          }
+          if (this.chooseData && this.chooseData.length > 0) {
+            if (disArr.includes(con.brandSn)) {
+              con.checked = true
+            }
+          }
+        })
       }
     },
     // 获取品牌数据
     getBrandList () {
+      const _this = this
       productBrandQuery({}).then(res => {
         if (res.status == 200) {
-          this.brandList = res.data
+          _this.brandList = res.data
+          if (_this.chooseData && _this.chooseData.length > 0) {
+            const checkedList = []
+            _this.chooseData.map(item => {
+              checkedList.push(item.goodsSn)
+            })
+            this.brandList.map(item => {
+              if (checkedList.includes(item.brandSn)) {
+                item.checked = true
+              } else {
+                item.checked = false
+              }
+            })
+          }
         } else {
           this.brandList = []
         }
       })
+    },
+    // 禁用
+    handleDisabled (list) {
+      this.disabledList = list
+      this.brandList.map(item => {
+        if (list.includes(item.brandSn)) {
+          item.isDisabled = true
+        } else {
+          item.isDisabled = false
+        }
+      })
     }
   },
   watch: {
@@ -131,16 +273,14 @@ export default {
       if (!newValue) {
         this.$emit('close')
         this.checkAll = false
+        this.checkOwn = false
+        this.checkAgent = false
+        this.brandList.map(item => {
+          item.checked = false
+        })
       } else {
         const _this = this
-        this.checkedRowList = this.chooseData
-        this.checkedList = []
-        this.chooseData.map(item => {
-          _this.checkedList.push(item.goodsSn)
-        })
-        if (this.brandList.length == 0) {
-          this.getBrandList()
-        }
+        _this.getBrandList()
       }
     }
   }

+ 35 - 10
src/views/common/chooseTypeModal.vue

@@ -10,14 +10,14 @@
     width="50%">
     <div class="chooseType-con">
       <div>
-        <a-checkbox :checked="checkAll" @change="onCheckAllChange">全选</a-checkbox>
+        <a-checkbox :checked="checkAll" :disabled="!linkageStatus&&chooseList.length>0 " @change="onCheckAllChange">全选</a-checkbox>
       </div>
       <a-divider />
       <a-tree
         style="height: 400px;overflow-y: scroll;"
         checkable
         @check="onCheck"
-        :checkStrictly="true"
+        :checkStrictly="linkageStatus"
         v-model="checkedKeys"
         :treeData="productTypeList"
         :replaceFields="replaceFields"
@@ -60,6 +60,10 @@ export default {
     type: { //  类型,促销规则promo
       type: String,
       default: ''
+    },
+    linkageStatus: { // 父子是否联动
+      type: Boolean,
+      default: true
     }
   },
   data () {
@@ -74,7 +78,8 @@ export default {
         title: 'productTypeName',
         key: 'productTypeSn'
       },
-      productTypeList: []
+      productTypeList: [],
+      chooseList: []
     }
   },
   methods: {
@@ -91,6 +96,12 @@ export default {
       } else {
         productTypeQuery({}).then(res => {
           if (res.status == 200) {
+            if (!this.linkageStatus && this.chooseData.length > 0) {
+              this.handleDisabled(res.data, this.chooseData)
+            }
+            if (!this.linkageStatus && this.chooseList.length > 0) {
+              this.handleDisabled(res.data, this.chooseList)
+            }
             this.productTypeList = res.data
           } else {
             this.productTypeList = []
@@ -131,10 +142,25 @@ export default {
         })
       }
     },
+    handleAllDisabled (list) {
+      console.log('111111111:', list)
+      this.chooseList = list
+    },
+    // 禁用递归
+    handleDisabled (data, selectData) {
+      if (data) {
+        data.map(item => {
+          const posNum = selectData.findIndex(con => con.goodsSn == item.productTypeSn)
+          if (posNum != -1) {
+            item = Object.assign(item, selectData[posNum])
+          }
+          if (item.children && item.children.length > 0) {
+            this.handleDisabled(item.children, selectData)
+          }
+        })
+      }
+    },
     onCheck (checkedKeys, info) {
-      // console.log('onCheck', checkedKeys, info)
-      // this.checkedData = [...checkedKeys, ...info.halfCheckedKeys]
-      this.checkedKeys = checkedKeys
       this.checkedRows = []
       info.checkedNodes.map((item, index) => {
         this.checkedRows.push(item.data.props)
@@ -152,17 +178,16 @@ export default {
         this.$emit('close')
         this.checkAll = false
       } else {
+        this.getProductType()
         const _this = this
         this.checkedRows = this.chooseData
         this.checkedKeys = []
-        this.chooseData.map(item => {
+        this.chooseData.forEach(item => {
           _this.checkedKeys.push(item.goodsSn)
         })
-        if (this.productTypeList.length == 0) {
-          this.getProductType()
-        }
       }
     }
+
   }
 }
 </script>

+ 48 - 16
src/views/common/chooseWarehouse.js

@@ -57,11 +57,28 @@ const warehouse = {
     }
   },
   mounted () {
+    // 如果已经存在仓库数据
+    const a = this.$store.state.app.warehouseAuthList 
+    const b = this.$store.state.app.warehouseAllList
+
     if (this.isPermission) {
       this.$store.state.app.defWarehouse = null
       this.$store.state.app.isWarehouse = true
+      if(a){
+        this.setWarehouseData(a)
+      }else{
+        // 不存在,远程获取
+        this.getWarehouse()
+      }
+    }else{
+      if(b){
+        this.setWarehouseData(b)
+      }else{
+        // 不存在,远程获取
+        this.getWarehouse()
+      }
     }
-    this.getWarehouse()
+    
   },
   watch: {
     value (newValue, oldValue) {
@@ -79,26 +96,36 @@ const warehouse = {
       this.$emit('input', value)
       this.$emit('change', value)
     },
+    // 设置仓库数据
+    setWarehouseData(data){
+      // 有权限控制的
+      if (this.isPermission) {
+        this.$store.state.app.isWarehouse = true
+        this.$store.state.app.defWarehouse = data && data[0]
+      }
+      this.warehouseData = data || []
+      let defaultWarehouseVal = {}
+      if (this.isDefault) {
+        defaultWarehouseVal = data.find(con => {
+          return con.defaultFlag == 1 ? con.warehouseSn : ''
+        })
+        this.defaultVal = defaultWarehouseVal.warehouseSn
+        this.$emit('load', defaultWarehouseVal.warehouseSn, this.warehouseData)
+      } else {
+        this.$emit('load', null, this.warehouseData)
+      }
+    },
     //  获取仓库列表
     getWarehouse () {
       const ajaxName = this.isPermission ? queryAuthWarehouse : warehouseAllList
       ajaxName({}).then(res => {
         if (res.status == 200) {
-          // 有权限控制的
-          if (this.isPermission) {
-            this.$store.state.app.isWarehouse = true
-            this.$store.state.app.defWarehouse = res.data && res.data[0]
-          }
-          this.warehouseData = res.data || []
-          let defaultWarehouseVal = {}
-          if (this.isDefault) {
-            defaultWarehouseVal = res.data.find(con => {
-              return con.defaultFlag == 1 ? con.warehouseSn : ''
-            })
-            this.defaultVal = defaultWarehouseVal.warehouseSn
-            this.$emit('load', defaultWarehouseVal.warehouseSn, this.warehouseData)
-          } else {
-            this.$emit('load', null, this.warehouseData)
+          this.setWarehouseData(res.data)
+          // 存储仓库数据本地
+          if(this.isPermission){
+            this.$store.state.app.warehouseAuthList = this.warehouseData
+          }else{
+            this.$store.state.app.warehouseAllList = this.warehouseData
           }
         } else {
           if (this.isPermission) {
@@ -114,6 +141,11 @@ const warehouse = {
     },
     clearData () {
       this.handleChange([])
+    },
+    // 清空缓存的数据
+    clearCacheData(){
+      this.$store.state.app.warehouseAuthList = null
+      this.$store.state.app.warehouseAllList = null
     }
   }
 }

+ 30 - 10
src/views/common/productBrand.js

@@ -27,10 +27,6 @@ const ProductBrand = {
       type: String,
       default: '请选择产品品牌'
     },
-    sysFlag: {
-      type: String,
-      default: ''
-    },
     brandType: {
       type: String,
       default: ''
@@ -47,7 +43,13 @@ const ProductBrand = {
     };
   },
   mounted() {
-    this.getProductBrand()
+    const a = this.$store.state.app.productBrandAllList
+    // 有缓存
+    if(a){
+      this.setBrandData(a||[])
+    }else{
+      this.getProductBrand()
+    }
   },
   watch: {
     value(newValue, oldValue) {
@@ -55,7 +57,13 @@ const ProductBrand = {
     },
     brandType(newValue,oldValue){
       this.handleChange(undefined)
-      this.getProductBrand()
+      const a = this.$store.state.app.productBrandAllList
+      // 有缓存
+      if(a){
+        this.setBrandData(a||[])
+      }else{
+        this.getProductBrand()
+      }
     }
   },
   methods: {
@@ -70,14 +78,26 @@ const ProductBrand = {
       this.$emit('input', value);
       this.$emit('change', value, this.id, row);
     },
-    //  产品品牌列表, sysFlag: 1 箭冠 0 自建
+    setBrandData(data){
+      // brandType: 1 自主品牌 2 代理品牌
+      if(this.brandType!=''){
+        this.productBrandList = data.filter(item => item.brandType == this.brandType)
+      }else{
+        this.productBrandList = data
+      }
+    },
+    //  产品品牌列表,
     getProductBrand () {
-      productBrandQuery({ 'sysFlag': this.sysFlag, 'brandType': this.brandType }).then(res => {
+      productBrandQuery({}).then(res => {
+        let ret = []
         if (res.status == 200) {
-          this.productBrandList = res.data
+          ret = res.data
         } else {
-          this.productBrandList = []
+          ret = []
         }
+        // 缓存数据
+        this.$store.state.app.productBrandAllList = ret
+        this.setBrandData(ret)
       })
     },
   },

+ 9 - 1
src/views/common/productTypeAll.js

@@ -50,7 +50,13 @@ const ProductType = {
     }
   },
   mounted () {
-    this.getProductType()
+    const a = this.$store.state.app.productTypeAllList
+    // 如果有缓存
+    if(this.isAll && a){
+      this.productTypeList = a || []
+    }else{
+      this.getProductType()
+    }
   },
   methods: {
     filter(inputValue, path) {
@@ -80,6 +86,8 @@ const ProductType = {
           } else {
             this.productTypeList = []
           }
+          // 缓存数据
+          this.$store.state.app.productTypeAllList = this.productTypeList
         })
       }else{
         productTypeQuery({}).then(res => {

+ 8 - 5
src/views/expenseManagement/expenseReimbursement/add.vue

@@ -22,6 +22,7 @@
             <a-descriptions-item label="状态">{{ detailData&&detailData.stateDictValue || '--' }}</a-descriptions-item>
             <a-descriptions-item label="创建时间">{{ detailData&&detailData.createDate || '--' }}</a-descriptions-item>
             <a-descriptions-item label="审核时间">{{ detailData&&detailData.finishDate || '--' }}</a-descriptions-item>
+            <a-descriptions-item label="关联单号" v-if="detailData&&detailData.bizNo">{{ detailData&&detailData.bizNo || '--' }}</a-descriptions-item>
             <a-descriptions-item label="主题" :span="3">{{ detailData&&detailData.title || '--' }}</a-descriptions-item>
             <a-descriptions-item label="详细说明" :span="3">{{ detailData&&detailData.content.join(',')||'' }}</a-descriptions-item>
             <a-descriptions-item label="附件" :span="3">
@@ -33,7 +34,7 @@
         </a-collapse-panel>
       </a-collapse>
       <!-- 费用明细 -->
-      <a-card :bordered="false" size="small" class="expenseReimbursementAddcont" v-if="$route.params.sn">
+      <a-card :bordered="false" size="small" class="expenseReimbursementAddcont">
         <div slot="title">
           <div style="display: flex;justify-content: space-between;align-items: center;">
             <div>费用明细</div>
@@ -50,7 +51,7 @@
         </a-alert>
         <!-- 列表 -->
         <s-table
-          class="sTable fixPagination"
+          class="sTable"
           ref="table"
           size="small"
           :rowKey="(record) => record.id"
@@ -155,7 +156,7 @@ import ImportGuideModal from './importGuideModal.vue'
 import chooseDepartUserModal from './chooseDepartUserModal.vue'
 import { expenseAccountDetail, expenseAcctDetailDelete, expenseAcctDetailFindList, expenseAccountSubmit, expenseInsertImport } from '@/api/expenseManagement.js'
 export default {
-  name: 'ExpenseReimbursementEdit',
+  name: 'expenseReimbursementEdit',
   mixins: [commonMixin],
   components: { VSelect, Upload, STable, epenseDetailModal, productInfoModal, baseDataModal, ImportGuideModal, chooseDepartUserModal },
   data () {
@@ -216,7 +217,7 @@ export default {
       this.openBaseModal = true
     },
     refashData () {
-      this.getDetail(1)
+      this.getDetail(true)
     },
     //  费用单基础详情
     getDetail (type) {
@@ -321,8 +322,10 @@ export default {
       this.$router.push({ name: 'expenseReimbursementList' })
     },
     pageInit () {
+      console.log(1)
       if (this.$route.params.sn) { //  编辑页
-        this.getDetail()
+        console.log(2)
+        this.getDetail(false)
       }
     }
   },

+ 47 - 16
src/views/expenseManagement/expenseReimbursement/baseDataModal.vue

@@ -125,6 +125,7 @@ export default {
         labelCol: { span: 6 },
         wrapperCol: { span: 14 }
       },
+      fromPage: null,
       attachList: [],
       attachAction: process.env.VUE_APP_API_BASE_URL + '/uploadGetFileInfo',
       expenseTypes: [],
@@ -163,21 +164,37 @@ export default {
   },
   methods: {
     cancel () {
+      this.spinning = false
       this.$emit('close')
     },
     pageInit () {
       this.$nextTick(() => {
-        this.attachList = []
-        this.form.expenseAccountFilesList = ''
-        this.$refs.attachList.setFileList('')
-        this.$refs.ruleForm.resetFields()
-        this.expenseTypes = []
         if (this.expenseAccountSn) { //  编辑页
           this.getDetail()
           this.title = '编辑费用报销单'
+        }else{
+          this.title = '新增费用报销单'
         }
       })
     },
+    retsetForm(){
+      this.form = {
+        applyPersonSn: undefined, // 申请人
+        applyDepartmentSn: undefined, //  申请部门
+        expenseType: undefined, //  费用类型1
+        expenseType2: undefined, //  费用类型2
+        expenseTypeName: undefined, //  费用类型1
+        expenseTypeName2: undefined, //  费用类型2
+        expenseDate: moment().locale('zh-cn').format('YYYY-MM'), //  费用产生月
+        title: '', // 主题
+        content: '' // 费用说明
+      }
+      this.attachList = []
+      this.form.expenseAccountFilesList = ''
+      this.$refs.attachList.setFileList('')
+      this.$refs.ruleForm.resetFields()
+      this.expenseTypes = []
+    },
     // 申请人员
     employeeChange (v, r) {
       if (r.departmentSn) {
@@ -214,23 +231,30 @@ export default {
         item.fileType = item.extName
       })
     },
+    // 设置数据
+    setDetail(data, from){
+      console.log(data)
+      this.spinning = false
+      this.disabled = false
+      this.fromPage = from
+      this.form = Object.assign(this.form, data)
+      // 获取附件列表
+      if(this.$refs.attachList){
+        this.form.expenseAccountFilesList = ''
+        this.attachList = data.expenseAccountFilesList
+        this.$refs.attachList.setFileList(this.attachList)
+      }
+      setTimeout(()=>{
+        this.expenseTypes = data.expenseType ? [this.form.expenseType, this.form.expenseType2] : []
+      }, 500)
+    },
     //  详情
     getDetail () {
       this.spinning = true
       this.disabled = true
       expenseAccountDetail({ expenseAccountSn: this.expenseAccountSn }).then(res => {
         if (res.status == 200) {
-          const data = res.data
-          this.form = Object.assign(this.form, data)
-          // 获取附件列表
-          this.form.expenseAccountFilesList = ''
-          this.attachList = res.data.expenseAccountFilesList
-          this.$refs.attachList.setFileList(this.attachList)
-          if (this.form.expenseType) {
-            this.expenseTypes = [this.form.expenseType, this.form.expenseType2]
-          } else {
-            this.expenseTypes = []
-          }
+          this.setDetail(res.data)
         } else {
           this.$refs.ruleForm.resetFields()
         }
@@ -249,6 +273,11 @@ export default {
           form.expenseAccountFilesList = this.attachList
           _this.spinning = true
           console.log(form)
+          // 从销售单转的费用
+          if(_this.fromPage=='sales'){
+            _this.$emit('expenseSaveOk',form)
+            return false
+          }
           expenseAccountSave(form).then(res => {
             if (res.status == 200) {
               _this.$message.success(res.message)
@@ -276,6 +305,8 @@ export default {
       this.opened = newValue
       if (newValue) {
         this.pageInit()
+      }else{
+        this.retsetForm()
       }
     },
     itemSn (a, b) {

+ 2 - 0
src/views/expenseManagement/expenseReimbursement/detail.vue

@@ -42,7 +42,9 @@
               <a-descriptions-item label="打印状态">{{ detailData&&detailData.printStatusDictValue || '--' }}</a-descriptions-item>
               <a-descriptions-item label="创建时间">{{ detailData&&detailData.createDate || '--' }}</a-descriptions-item>
               <a-descriptions-item label="审核时间">{{ detailData&&detailData.finishDate || '--' }}</a-descriptions-item>
+              <a-descriptions-item label="关联单号" v-if="detailData&&detailData.bizNo">{{ detailData&&detailData.bizNo || '--' }}</a-descriptions-item>
               <a-descriptions-item label="主题" :span="3">{{ detailData&&detailData.title || '--' }}</a-descriptions-item>
+              
               <a-descriptions-item label="详细说明" :span="4">
                 {{ detailData.content.join(',')||'' }}
               </a-descriptions-item>

+ 1 - 1
src/views/financialManagement/financialCollection/selectGlSalesModal.vue

@@ -105,7 +105,7 @@ import { commonMixin } from '@/utils/mixin'
 import { STable, VSelect } from '@/components'
 import { dispatchlList } from '@/api/dispatch'
 import commonModal from '@/views/common/commonModal.vue'
-import salesDetail from '@/views/salesManagement/salesQuery/detail.vue'
+import salesDetail from '@/views/salesManagement/salesQueryNew/detailAll.vue'
 import dispatchDetail from '@/views/salesManagement/pushOrderManagement/detail.vue'
 import dealerSubareaScopeList from '@/views/common/dealerSubareaScopeList.vue'
 export default {

+ 1 - 22
src/views/inventoryManagement/inventoryCheck/list.vue

@@ -188,28 +188,7 @@ export default {
   methods: {
     // 新增
     handleAdd () {
-      this.spinning = true
-      checkWarehouseStartCheck({}).then(res => {
-        this.spinning = false
-        if (res.status == 200) {
-          if (res.data && res.data.length > 0) {
-            // this.modalHtml = `<div style="width: 100%">
-            //   <h3 style="font-size: 15px;font-weight: bold;margin: 20px 0 5px;text-align: center;">存在以下状态的销售单,无法盘点。</h3>
-            //   <h3 style="font-size: 15px;font-weight: bold;margin-bottom: 25px;text-align: center;">请先检查并处理完以下单据再试。</h3>
-            //   ${res.data.indexOf('WAIT_AUDIT') != -1 ? '<p>销售单-待审核(总部自建)</p>' : ''}
-            //   ${res.data.indexOf('AUDIT_REJECT') != -1 ? '<p>销售单-审核不通过(总部自建)</p>' : ''}
-            //   ${res.data.indexOf('HQ_CHANGE') != -1 ? '<p>销售单-总公司改单</p>' : ''}
-            //   ${res.data.indexOf('WAIT_PUSH') != -1 ? '<p>销售单-待下推</p>' : ''}
-            // </div>`
-            this.modalHtml = `<div style="width: 100%">
-              ${res.data.indexOf('WAIT_PUSH') != -1 ? '<p>存在“待下推”状态的销售单,无法盘点。</p>' : ''}
-            </div>`
-            this.openCommonModal = true
-          } else {
-            this.openAddModal = true
-          }
-        }
-      })
+      this.openAddModal = true
     },
     // 新增 成功
     handleAddOk (data) {

+ 3 - 3
src/views/productManagement/productInfo/edit.vue

@@ -273,9 +273,9 @@ export default {
         unit: [
           { required: true, message: '请选择单位', trigger: 'change' }
         ],
-        // packQty: [
-        //   { required: true, message: '请输入包装数', trigger: 'blur' }
-        // ],
+        packQty: [
+          { required: true, message: '请输入包装数', trigger: 'blur' }
+        ],
         arrowFalg: [
           { required: true, message: '请选择是否为箭冠产品', trigger: 'change' }
         ],

+ 2 - 1
src/views/productManagement/productInfo/importGuideModal.vue

@@ -152,7 +152,8 @@ export default {
       }, 1000)
       const link = document.createElement('a')
       link.style.display = 'none'
-      link.href = 'https://jg-ocs.oss-cn-beijing.aliyuncs.com/templ/promo/productImport.xlsx?t=' + new Date().getTime()
+      // link.href = 'https://jg-ocs.oss-cn-beijing.aliyuncs.com/templ/promo/productImport.xlsx?t=' + new Date().getTime()
+      link.href = location.protocol + '//' + location.host + '/templ/产品批量导入模板.xlsx'
       link.setAttribute('download', '产品批量导入模板' + '.xlsx')
       document.body.appendChild(link)
       link.click()

+ 39 - 2
src/views/productManagement/productInfo/list.vue

@@ -53,8 +53,20 @@
                   <rangeDate ref="rangeDate" @change="dateChange" />
                 </a-form-model-item>
               </a-col>
+              <a-col :md="4" :sm="24">
+                <a-form-item label="停产状态">
+                  <a-select v-model="queryParam.haltProdFlag" placeholder="请选择停产状态" allowClear>
+                    <a-select-option value="0">
+                      启用
+                    </a-select-option>
+                    <a-select-option value="1">
+                      停产
+                    </a-select-option>
+                  </a-select>
+                </a-form-item>
+              </a-col>
             </template>
-            <a-col :md="7" :sm="24" style="margin-bottom: 10px;">
+            <a-col :md="6" :sm="24" style="margin-bottom: 10px;">
               <a-button type="primary" @click="$refs.table.refresh(true)" :disabled="disabled" id="productInfoList-refresh">查询</a-button>
               <a-button style="margin-left: 5px" @click="resetSearchForm" :disabled="disabled" id="productInfoList-reset">重置</a-button>
               <a-button
@@ -138,6 +150,15 @@
           <span v-if="record.productTypeName2 || record.productTypeName3">{{ record.productTypeName2 }} {{ record.productTypeName3 ? '>' : '' }} {{ record.productTypeName3 }}</span>
           <span v-else>--</span>
         </template>
+        <!-- 停产状态 -->
+        <template slot="stopStatus" slot-scope="text, record">
+          <a-switch
+            checkedChildren="启用"
+            unCheckedChildren="停产"
+            id="roleList-isEnable"
+            v-model="record.stopFlag"
+            @change="changeFlagHandle(record)" />
+        </template>
         <!-- 产品图片 -->
         <template slot="imageUrl" slot-scope="text, record">
           <div v-if="record.productPicList && record.productPicList.length>0">
@@ -212,7 +233,7 @@ import productTypeAll from '@/views/common/productTypeAll.js'
 import { exportExcel } from '@/libs/JGPrint.js'
 import rangeDate from '@/views/common/rangeDate.vue'
 import importGuideModal from './importGuideModal.vue'
-import { productList, productAudit, productBatchAudit, productDel, productOnline, productBatchOnline, productExport, saveBatchImportProduct, importSaveBatch } from '@/api/product'
+import { productList, productAudit, productBatchAudit, productDel, productOnline, productBatchOnline, productExport, saveBatchImportProduct, importSaveBatch, updateHaltProdFlag } from '@/api/product'
 export default {
   name: 'ProductInfoList',
   mixins: [commonMixin],
@@ -223,6 +244,7 @@ export default {
       advanced: true, // 高级搜索 展开/关闭
       tableHeight: 0,
       queryParam: { //  查询条件
+        haltProdFlag: undefined, // 停产状态
         updateBeginDate: '',
         updateEndDate: '',
         name: '', //  产品名称
@@ -252,6 +274,7 @@ export default {
         { title: '最新定价时间', dataIndex: 'pricingTime', width: '8%', align: 'center', customRender: function (text) { return text || '--' } },
         { title: '产品状态', dataIndex: 'stateDictValue', width: '6%', align: 'center', customRender: function (text) { return text || '--' } },
         { title: '定价状态', dataIndex: 'pricingStateDictValue', width: '6%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '停产状态', width: '6%', align: 'center', scopedSlots: { customRender: 'stopStatus' } },
         { title: '产品图片', scopedSlots: { customRender: 'imageUrl' }, width: '7%', align: 'center' },
         { title: '操作', scopedSlots: { customRender: 'action' }, width: '10%', align: 'center' }
       ],
@@ -269,6 +292,7 @@ export default {
             const no = (data.pageNo - 1) * data.pageSize
             for (var i = 0; i < data.list.length; i++) {
               data.list[i].no = no + i + 1
+              data.list[i].stopFlag = data.list[i].haltProdFlag == 0
             }
             this.disabled = false
           }
@@ -398,6 +422,18 @@ export default {
         })
       }
     },
+    // 改变停产状态
+    changeFlagHandle (row) {
+      const _this = this
+      _this.spinning = true
+      updateHaltProdFlag({ productSn: row.productSn, haltProdFlag: row.stopFlag ? 0 : 1 }).then(res => {
+        if (res.status == 200) {
+          _this.$message.success(res.message)
+          _this.$refs.table.refresh()
+        }
+        _this.spinning = false
+      })
+    },
     // 批量上线
     handleBatchLaunch () {
       const _this = this
@@ -470,6 +506,7 @@ export default {
       this.queryParam.state = undefined
       this.queryParam.pricingState = undefined
       this.queryParam.picFlag = undefined
+      this.queryParam.haltProdFlag = undefined
       this.productType = []
       if (this.advanced) {
         this.$refs.rangeDate.resetDate()

+ 311 - 0
src/views/promotionRulesManagement/dealerPromotions/addModal.vue

@@ -0,0 +1,311 @@
+<template>
+  <a-modal
+    centered
+    class="promotionList-basicInfo-modal"
+    :footer="null"
+    :maskClosable="false"
+    :title="itemSn?'编辑':'新增'"
+    v-model="isShow"
+    @cancel="isShow=false"
+    :width="800">
+    <a-spin :spinning="spinning" tip="Loading...">
+      <a-form-model
+        style="max-height:650px;overflow-y: scroll;"
+        id="promotionList-basicInfo-form"
+        ref="ruleForm"
+        :model="form"
+        :rules="rules"
+        :label-col="formItemLayout.labelCol"
+        :wrapper-col="formItemLayout.wrapperCol" >
+        <a-form-model-item label="促销名称" prop="title">
+          <a-input id="promotionList-promotionName" v-model.trim="form.title" allowClear placeholder="请输入促销名称(最多30个字符)" :maxLength="30"></a-input>
+        </a-form-model-item>
+        <a-form-model-item label="促销简称" prop="description">
+          <a-input id="promotionList-description" v-model.trim="form.description" allowClear placeholder="请输入促销简称(最多20个字符)" :maxLength="20"></a-input>
+        </a-form-model-item>
+        <a-form-model-item label="促销时间" prop="activeDate">
+          <a-range-picker
+            style="width:100%"
+            id="promotionList-basicInfo-activeDate"
+            :disabledDate="disabledDate"
+            v-model="form.activeDate"
+            :format="dateFormat"
+            :placeholder="['开始时间', '结束时间']"
+            @change="onChangeDate"></a-range-picker>
+        </a-form-model-item>
+        <a-form-model-item label="费用所属部门" prop="expenseDepartmentSn">
+          <department style="width: 100%;" @change="departementChange" id="promotionList-basicInfo-activeDate" v-model="form.expenseDepartmentSn"></department>
+        </a-form-model-item>
+        <a-form-model-item label="参与客户" prop="dealerSnList">
+          <a-row :gutter="15">
+            <a-col :md="3" :sm="24">
+              <a-button type="primary" :loading="spinning" @click="handleDealerModal">选择</a-button>
+            </a-col>
+            <a-col :md="6" :sm="24" v-show="chooseDealerList && chooseDealerList.length>0">
+              已{{ chooseDealerList.length }}选项
+            </a-col>
+            <a-col :md="24" :sm="24" v-show="chooseDealerList && chooseDealerList.length>0">
+              <div class="buyerBox">
+                <a-tag closable v-for="con in chooseDealerList" :key="con.dealerSn" @close="delBuyerName(con)">
+                  {{ con.dealerName }}
+                </a-tag>
+              </div>
+            </a-col>
+          </a-row>
+        </a-form-model-item>
+        <a-form-model-item label="促销描述" prop="content">
+          <a-textarea
+            id="promotionList-content"
+            :maxLength="500"
+            :rows="5"
+            v-model="form.content"
+            placeholder="请输入促销描述"
+            allowClear />
+        </a-form-model-item>
+        <a-form-model-item label="附件" help="(支持图片、word、excel、PDF等格式,最多10个附件)">
+          <Upload
+            style="height: 100%;"
+            id="allocateBill-attachList"
+            v-model="form.attachmentList"
+            ref="attachList"
+            :fileSize="10"
+            :maxNums="10"
+            fileType="*"
+            uploadType="attach"
+            :action="attachAction"
+            @change="changeAttach"
+            upText="上传附件"></Upload>
+        </a-form-model-item>
+      </a-form-model>
+      <div class="btn-cont">
+        <a-button id="promotionList-basicInfo-modal-back" @click="isShow = false">取消</a-button>
+        <a-button style="margin-left: 15px;" type="primary" id="promotionList-modal-save" @click="handleSave">确定</a-button>
+      </div>
+    </a-spin>
+    <!-- 选择参与客户 -->
+    <a-modal
+      title="选择经销商"
+      :visible="openDealerModal"
+      :footer="null"
+      centered
+      class="lookUpCustomers-modal"
+      @cancel="openDealerModal = false"
+      width="60%"
+    >
+      <div class="dealerModalCon">
+        <chooseDealer ref="dealerChoose" pageType="dealerPromotion" @plAdd="handleAddDealer"></chooseDealer>
+      </div>
+    </a-modal>
+  </a-modal>
+</template>
+
+<script>
+import { commonMixin } from '@/utils/mixin'
+import { Upload } from '@/components'
+import department from '@/views/expenseManagement/expenseReimbursement/department.js'
+import warehouse from '@/views/common/chooseWarehouse.js'
+import moment from 'moment'
+import chooseDealer from '../promotionManagement/chooseDealer'
+import { dealerPromotionSave, dealerPromotionInfo, dealerPromotionEdit } from '@/api/promotion'
+export default {
+  name: 'PromotionListBasicInfoModal',
+  mixins: [commonMixin],
+  components: { Upload, department, warehouse, chooseDealer },
+  props: {
+    openModal: { //  弹框显示状态
+      type: Boolean,
+      default: false
+    },
+    itemSn: {
+      type: [Number, String],
+      default: ''
+    }
+  },
+  data () {
+    return {
+      isShow: this.openModal, //  是否打开弹框
+      spinning: false,
+      formItemLayout: {
+        labelCol: { span: 5 },
+        wrapperCol: { span: 16 }
+      },
+      form: {
+        title: '',
+        activeDate: undefined,
+        expenseDepartmentSn: undefined, // 费用所属部门
+        description: '', // 活动简称
+        content: '', // 活动描述
+        attachmentList: '', // 附件
+        dealerSnList: []// 参与客户
+      },
+      openDealerModal: false,
+      chooseDealerList: [],
+      attachList: [], // 附件
+      dateFormat: 'YYYY-MM-DD',
+      rules: {
+        title: [{ required: true, message: '请输入促销名称', trigger: 'blur' }],
+        activeDate: [{ required: true, message: '请选择促销时间', trigger: 'change' } ],
+        expenseDepartmentSn: [{ required: true, message: '请选择费用所属部门', trigger: 'change' }],
+        dealerSnList: [{ required: true, message: '请选择参与客户', trigger: 'change' }],
+        description: [{ required: true, message: '请输入促销简称', trigger: 'blur' }],
+        content: [{ required: true, message: '请输入促销描述', trigger: 'blur' }]
+      },
+      attachAction: process.env.VUE_APP_API_BASE_URL + '/uploadGetFileInfo'
+    }
+  },
+  methods: {
+    // 选择活动时间
+    onChangeDate (date, dateString) {
+      this.form.activeDate = date
+      if (dateString[0] != '' && dateString[1] != '') {
+        this.form.promotionDateStart = dateString[0] + ' 00:00:00'
+        this.form.promotionDateEnd = dateString[1] + ' 23:59:59'
+      }
+    },
+    // 费用所属部门
+    departementChange () {
+      this.$nextTick(() => {
+        this.$refs.ruleForm.validateField('expenseDepartmentSn')
+      })
+    },
+    //  附件上传
+    changeAttach (file) {
+      this.attachList = JSON.parse(file)
+      this.attachList.map(item => {
+        item.fileType = item.extName
+      })
+    },
+    // 选择参与客户
+    handleDealerModal () {
+      this.openDealerModal = true
+      const _this = this
+      if (_this.chooseDealerList.length == 0) {
+        _this.form.dealerSnList = []
+      }
+      const arr = _this.chooseDealerList.map(item => {
+        return item.dealerSn
+      })
+      // 选择参与客户回显
+      _this.$nextTick(() => {
+        _this.$refs.dealerChoose.pageInit(arr)
+      })
+    },
+    // 删除所选参与客户
+    delBuyerName (row) {
+      const pot = this.chooseDealerList.findIndex(con => { return con.dealerSn == row.dealerSn })
+      this.chooseDealerList.splice(pot, 1)
+    },
+    // 添加经销商
+    handleAddDealer (list) {
+      this.chooseDealerList = list
+      this.openDealerModal = false
+      // 移除表单必填项
+      this.$refs.ruleForm.clearValidate('dealerSnList')
+    },
+    //  新增/编辑
+    handleSave () {
+      const _this = this
+      const newArr = this.chooseDealerList.map(item => {
+        return item.dealerSn
+      })
+      _this.form.dealerSnList = newArr
+      this.$refs.ruleForm.validate(valid => {
+        if (valid) {
+          const form = JSON.parse(JSON.stringify(_this.form))
+          form.attachmentList = _this.attachList
+          delete form.activeDate
+          _this.spinning = true
+          const ajaxName = _this.itemSn ? dealerPromotionEdit : dealerPromotionSave
+          ajaxName(form).then(res => {
+            if (res.status == 200) {
+              _this.$message.success(res.message)
+              setTimeout(() => {
+                _this.isShow = false
+                _this.$emit('ok', res.data)
+                _this.spinning = false
+              }, 1000)
+            } else {
+              _this.spinning = false
+            }
+          })
+        } else {
+          return false
+        }
+      })
+    },
+    // 重置
+    resetSearchForm () {
+      this.form = {
+        title: '',
+        activeDate: undefined,
+        expenseDepartmentSn: undefined, // 费用所属部门
+        description: '', // 活动简称
+        content: '', // 活动描述
+        attachmentList: '', // 附件
+        dealerSnList: []// 参与客户
+      }
+      this.attachList = []
+      this.chooseDealerList = []
+      this.$nextTick(() => {
+        this.$refs.attachList.setFileList('')
+        this.$refs.ruleForm.resetFields()
+      })
+    },
+    // 获取编辑详情
+    getDetail () {
+      dealerPromotionInfo({ sn: this.itemSn }).then(res => {
+        if (res.status == 200) {
+          const data = res.data
+          this.chooseDealerList = data.dealerList
+          data.dealerSnList = data.dealerSnList
+          data.activeDate = [data.promotionDateStart, data.promotionDateEnd]
+          if (data.attachmentList) {
+            this.attachList = data.attachmentList
+            this.$nextTick(() => {
+              this.$refs.attachList.setFileList(this.attachList)
+            })
+          }
+          this.form = data
+        }
+      })
+    },
+    // 不可选日期
+    disabledDate (date, dateStrings) {
+      return date && date.valueOf('day') < moment().subtract(1, 'day') // 今天以后,包含今天
+    }
+  },
+  watch: {
+    //  父页面传过来的弹框状态
+    openModal (newValue, oldValue) {
+      this.isShow = newValue
+    },
+    //  重定义的弹框状态
+    isShow (newValue, oldValue) {
+      if (!newValue) {
+        this.$emit('close')
+        this.resetSearchForm()
+      } else {
+        if (this.itemSn) {
+          this.getDetail()
+        }
+      }
+    }
+  }
+}
+</script>
+
+<style lang="less" scoped>
+  .promotionList-basicInfo-modal{
+    .ant-modal-body {
+      padding: 40px 40px 24px;
+    }
+    .buyerBox{
+      border:1px solid #d9d9d9;margin-top:10px;border-radius:4px;padding:4px 10px;background:#f2f2f2;max-height:130px;overflow-y:scroll;
+    }
+    .btn-cont {
+      text-align: center;
+      margin: 35px 0 10px;
+    }
+  }
+
+</style>

+ 113 - 0
src/views/promotionRulesManagement/dealerPromotions/brandCategoryModal.vue

@@ -0,0 +1,113 @@
+<template>
+  <a-modal
+    centered
+    class="brand-category-modal"
+    :footer="null"
+    :maskClosable="false"
+    :title="openType=='brand'?'促销品费用归属品牌':'促销品费用归属品类'"
+    v-model="isShow"
+    @cancel="isShow=false"
+    :width="520">
+    <a-spin :spinning="spinning" tip="Loading...">
+      <div class="con">
+        <div class="con-list">
+          品{{ openType=='brand'?'牌':'类' }}数量:17
+        </div>
+        <div class="con-list">
+          <span v-for="con in 30" :key="con">霍尼韦尔</span>
+        </div>
+      </div>
+      <div class="btn-cont">
+        <a-button id="brand-category-modal-back" @click="isShow = false">关闭</a-button>
+      </div>
+    </a-spin>
+  </a-modal>
+</template>
+
+<script>
+import { commonMixin } from '@/utils/mixin'
+import { VSelect, Upload } from '@/components'
+import supplier from '@/views/common/supplier.js'
+import warehouse from '@/views/common/chooseWarehouse.js'
+import { sparePartsReturnSave, sparePartsReturnInfo } from '@/api/sparePartsReturn'
+export default {
+  name: 'PurchaseReturnBasicInfoModal',
+  mixins: [commonMixin],
+  components: { VSelect, Upload, supplier, warehouse },
+  props: {
+    openModal: { //  弹框显示状态
+      type: Boolean,
+      default: false
+    },
+    openType: {
+      type: String,
+      default: ''
+    }
+  },
+  data () {
+    return {
+      isShow: this.openModal, //  是否打开弹框
+      spinning: false
+    }
+  },
+  methods: {
+    // 获取编辑详情
+    getDetail () {
+      sparePartsReturnInfo({ sn: this.itemSn }).then(res => {
+        if (res.status == 200) {
+          const resultObj = res.data
+          this.attachList = resultObj.attachmentList
+          const obj = {
+            supplierSn: resultObj.supplierSn,
+            returnReason: resultObj.returnReason, // 退货原因
+            explainInfo: resultObj.explainInfo, // 补充说明
+            warehouseSn: resultObj.warehouseSn,
+            sparePartsReturnSn: this.itemSn
+          }
+          this.$nextTick(() => {
+            this.$refs.attachList.setFileList(this.attachList)
+          })
+          this.form = { ...this.form, ...obj }
+        } else {
+          this.detailsData = null
+        }
+      })
+    }
+  },
+  watch: {
+    //  父页面传过来的弹框状态
+    openModal (newValue, oldValue) {
+      this.isShow = newValue
+    },
+    //  重定义的弹框状态
+    isShow (newValue, oldValue) {
+      if (!newValue) {
+        this.$emit('close')
+      }
+    }
+  }
+}
+</script>
+
+<style lang="less" scoped>
+  .brand-category-modal{
+    .ant-modal-body {
+      padding: 40px 40px 24px;
+    }
+    .con-list{
+      margin-bottom:8px;
+      span{
+        display: inline-block;
+        margin:5px 10px 5px 0;
+      }
+    }
+    .btn-cont {
+      text-align: center;
+      margin: 35px 0 10px;
+    }
+    .ant-form-item:nth-child(4){
+      margin-bottom: 0px !important;
+    }
+  }
+
+</style>

+ 214 - 0
src/views/promotionRulesManagement/dealerPromotions/chooseImportModal.vue

@@ -0,0 +1,214 @@
+<template>
+  <a-modal
+    centered
+    class="chooseImport-modal"
+    :footer="null"
+    :maskClosable="false"
+    title="确认导入"
+    v-model="isShow"
+    @cancel="isShow=false"
+    width="80%">
+    <div class="chooseImport-con">
+      <!-- 可导入数据 -->
+      <p class="">可导入数据{{ loadData.length }}条</p>
+      <a-table
+        class="sTable"
+        ref="table"
+        size="small"
+        :rowKey="(record) => record.allocateSn"
+        :columns="nowColumns"
+        :dataSource="loadData"
+        :loading="loading"
+        :scroll="{ y: 200 }"
+        :pagination="false"
+        bordered>
+      </a-table>
+      <a-divider />
+      <!-- 不可导入数据 -->
+      <p class="red">不可导入数据{{ unLoadData.length }}条</p>
+      <a-table
+        class="unTable"
+        ref="unTable"
+        size="small"
+        :rowKey="(record) => record.errorDesc"
+        :columns="nowUnColumns"
+        :dataSource="unLoadData"
+        :loading="loading"
+        :scroll="{ y: 200 }"
+        :pagination="false"
+        bordered>
+        <template slot="errorMsg" slot-scope="text,record">
+          <a-popover placement="topRight">
+            <template slot="content">
+              <p v-for="d in record.importErrorMsgSet">{{ d }}</p>
+            </template>
+            <a-button type="link">
+              查看
+            </a-button>
+          </a-popover>
+        </template>
+      </a-table>
+      <!-- 按钮 -->
+      <div class="btn-con">
+        <a-button
+          type="primary"
+          id="chooseImport-submit"
+          size="large"
+          class="button-primary"
+          @click="handleSubmit"
+          style="padding: 0 40px;">确认导入</a-button>
+        <a-button
+          id="chooseImport-cancel"
+          size="large"
+          class="button-cancel"
+          @click="isShow=false"
+          style="padding: 0 40px;margin-left: 15px;">取消</a-button>
+        <a-button
+          type="primary"
+          id="chooseImport-error"
+          size="large"
+          class="button-error"
+          @click="handleError"
+          style="padding: 0 40px;margin-left: 15px;">导出错误项</a-button>
+      </div>
+    </div>
+  </a-modal>
+</template>
+
+<script>
+import { commonMixin } from '@/utils/mixin'
+import { hdExportExcel } from '@/libs/exportExcel'
+import { downNormalFail, downSpecialFail } from '@/api/promotion'
+export default {
+  name: 'ChooseImportModal',
+  mixins: [commonMixin],
+  props: {
+    openModal: { //  弹框显示状态
+      type: Boolean,
+      default: false
+    },
+    paramsData: {
+      type: Object,
+      default: () => {
+        return {}
+      }
+    }
+  },
+  data () {
+    return {
+      isShow: this.openModal, //  是否打开弹框
+      loadData: [],
+      unLoadData: [],
+      loading: false,
+      goodsFlag: ''
+    }
+  },
+  computed: {
+    nowColumns () {
+      const _this = this
+      let columnsArr = [
+        { title: '序号', dataIndex: 'no', width: '10%', align: 'center' },
+        { title: '产品编码', dataIndex: 'productCode', width: '20%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '产品名称', dataIndex: 'product.name', width: '50%', align: 'center', customRender: function (text) { return text || '--' } }
+      ]
+      if (_this.goodsFlag == '0') {
+        const arr = [
+          { title: '省级特价', dataIndex: 'provinceDiscountPriceText', width: '10%', align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } },
+          { title: '市级特价', dataIndex: 'cityDiscountPriceText', width: '10%', align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } },
+          { title: '特约特价', dataIndex: 'specialDiscountPriceText', width: '10%', align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } }
+        ]
+        columnsArr = columnsArr.concat(arr)
+      }
+      return columnsArr
+    },
+    nowUnColumns () {
+      const _this = this
+      const unColumnsArr = [
+        { title: '序号', dataIndex: 'no', width: '10%', align: 'center' },
+        { title: '产品编码', dataIndex: 'productCode', width: '20%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '产品名称', dataIndex: 'product.name', width: '50%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '错误说明', scopedSlots: { customRender: 'errorMsg' }, width: '20%', align: 'center' }
+      ]
+      if (_this.goodsFlag == '0') {
+        unColumnsArr.splice(3, 0, { title: '省级特价', dataIndex: 'provinceDiscountPriceText', width: '10%', align: 'right', customRender: function (text) { return text || '--' } },
+          { title: '市级特价', dataIndex: 'cityDiscountPriceText', width: '10%', align: 'right', customRender: function (text) { return text || '--' } },
+          { title: '特约特价', dataIndex: 'specialDiscountPriceText', width: '10%', align: 'right', customRender: function (text) { return text || '--' } })
+      }
+      return unColumnsArr
+    }
+  },
+  methods: {
+    setFlag (val) {
+      this.goodsFlag = val
+    },
+    getData () {
+      const paramsData = JSON.parse(JSON.stringify(this.paramsData))
+      this.loadData = paramsData.rightList || []
+      this.unLoadData = paramsData.errorList || []
+      this.loadData.map((item, index) => {
+        item.no = index + 1
+      })
+      this.unLoadData.map((item, index) => {
+        item.no = index + 1
+        item.importErrorMsgSet = item.remarks.split(',')
+      })
+    },
+    // 确认导入
+    handleSubmit () {
+      if (this.loadData.length == 0) {
+        this.$message.warning('没有可导入的数据!')
+      } else {
+        const data = this.paramsData.rightList
+        this.$emit('ok', data)
+        this.isShow = false
+      }
+    },
+    // 导出错误项
+    handleError () {
+      const _this = this
+      if (_this.unLoadData.length < 1) {
+        _this.$message.info('暂无可导出的错误项~')
+        return
+      }
+      _this.spinning = true
+      const ajaxName = _this.goodsFlag == '0' ? downSpecialFail : downNormalFail
+      hdExportExcel(ajaxName, _this.unLoadData, '导出产品错误项', function () {
+        _this.spinning = false
+      })
+    }
+  },
+  watch: {
+    //  父页面传过来的弹框状态
+    openModal (newValue, oldValue) {
+      this.isShow = newValue
+    },
+    //  重定义的弹框状态
+    isShow (newValue, oldValue) {
+      if (!newValue) {
+        this.$emit('close')
+        this.loadData = []
+        this.unLoadData = []
+      } else {
+        this.getData()
+      }
+    }
+  }
+}
+</script>
+
+<style lang="less" scoped>
+  .chooseImport-modal{
+    .chooseImport-con{
+      .red{
+        color: #f30;
+      }
+      .btn-con{
+        text-align: center;
+        margin: 30px 0 20px;
+        .button-cancel,.button-error{
+          font-size: 12px;
+        }
+      }
+    }
+  }
+</style>

+ 259 - 0
src/views/promotionRulesManagement/dealerPromotions/chooseProductsModal.vue

@@ -0,0 +1,259 @@
+<template>
+  <a-modal
+    centered
+    class="chooseProducts-modal"
+    :footer="null"
+    :maskClosable="false"
+    title="选择产品"
+    v-model="isShow"
+    @cancel="isShow=false"
+    width="70%">
+    <a-spin :spinning="spinning" tip="Loading...">
+      <div class="products-con">
+        <!-- 搜索条件 -->
+        <div class="table-page-search-wrapper">
+          <a-form-model
+            ref="ruleForm"
+            class="form-model-con"
+            layout="inline"
+            :model="queryParam"
+            :label-col="formItemLayout.labelCol"
+            :wrapper-col="formItemLayout.wrapperCol">
+            <a-row :gutter="15">
+              <a-col :md="6" :sm="24">
+                <a-form-model-item label="产品编码">
+                  <a-input id="chooseProducts-code" v-model.trim="queryParam.code" allowClear placeholder="请输入产品编码"/>
+                </a-form-model-item>
+              </a-col>
+              <a-col :md="6" :sm="24">
+                <a-form-model-item label="产品名称">
+                  <a-input id="chooseProducts-name" v-model.trim="queryParam.name" allowClear placeholder="请输入产品名称"/>
+                </a-form-model-item>
+              </a-col>
+              <a-col :md="6" :sm="24">
+                <a-form-model-item label="产品分类">
+                  <productTypeAll placeholder="请选择产品分类" @change="changeProductType" v-model="queryParam.productType" id="chooseProducts-productType"></productTypeAll>
+                </a-form-model-item>
+              </a-col>
+              <a-col :md="6" :sm="24">
+                <a-form-model-item label="产品品牌">
+                  <ProductBrand id="chooseProducts-productBrandSn" v-model="queryParam.productBrandSn"></ProductBrand>
+                </a-form-model-item>
+              </a-col>
+              <a-col :md="6" :sm="24" style="margin-bottom: 10px;">
+                <a-button type="primary" @click="$refs.table.refresh(true)" :disabled="disabled" id="chooseProducts-refresh">查询</a-button>
+                <a-button style="margin-left: 5px" @click="resetData" :disabled="disabled" id="chooseProducts-reset">重置</a-button>
+              </a-col>
+            </a-row>
+          </a-form-model>
+        </div>
+        <div style="margin-bottom: 10px">
+          <a-button type="primary" ghost :loading="loading" @click="handleSave">批量添加</a-button>
+          <span style="margin-left: 5px">
+            <template v-if="selectCount"> {{ `已选 ${selectCount} 项` }} </template>
+          </span>
+        </div>
+        <!-- 列表 -->
+        <s-table
+          class="sTable"
+          ref="table"
+          size="small"
+          :rowKey="(record) => record.productSn"
+          rowKeyName="productSn"
+          :row-selection="{ columnWidth: 40, getCheckboxProps:record =>({props: { disabled: this.chooseDataList && this.chooseDataList.indexOf(record.productSn) > -1 } })}"
+          @rowSelection="rowSelectionFun"
+          :columns="columns"
+          :pagination="{pageSizeOptions: ['20','50','100','200','500']}"
+          :data="loadData"
+          :defaultLoadData="false"
+          style="max-height:460px;"
+          :scroll="{ y: 400 }"
+          bordered>
+          <!-- 产品分类 -->
+          <template slot="productType" slot-scope="text, record">
+            <span v-if="record.productTypeName2 || record.productTypeName3">{{ record.productTypeName2 }} {{ record.productTypeName3 ? '>' : '' }} {{ record.productTypeName3 }}</span>
+            <span v-else>--</span>
+          </template>
+          <!-- 包装数 -->
+          <template slot="productQty" slot-scope="text, record">
+            <span v-if="record.packQty">
+              {{ record.packQty }}{{ record.unit }}/{{ record.packQtyUnit?record.packQtyUnit:'--' }}
+            </span>
+            <span v-else>--</span>
+          </template>
+        </s-table>
+      </div>
+    </a-spin>
+  </a-modal>
+</template>
+
+<script>
+import { commonMixin } from '@/utils/mixin'
+import { STable } from '@/components'
+import { productList } from '@/api/product'
+import ProductBrand from '@/views/common/productBrand.js'
+import productTypeAll from '@/views/common/productTypeAll.js'
+export default {
+  name: 'ChooseProductsModal',
+  components: { STable, ProductBrand, productTypeAll },
+  mixins: [commonMixin],
+  props: {
+    openModal: { //  弹框显示状态
+      type: Boolean,
+      default: false
+    },
+    chooseData: {
+      type: Array,
+      default: () => {
+        return []
+      }
+    }
+  },
+  data () {
+    const _this = this
+    return {
+      spinning: false,
+      isShow: this.openModal, //  是否打开弹框
+      formItemLayout: {
+        labelCol: { span: 4 },
+        wrapperCol: { span: 20 }
+      },
+      queryParam: { //  查询条件
+        name: '', // 产品名称
+        code: '', //  产品编码
+        productBrandSn: undefined, //  产品品牌
+        productType: [],
+        productTypeSn1: '', //  产品一级分类
+        productTypeSn2: '', //  产品二级分类
+        productTypeSn3: '' //  产品三级分类
+      },
+      chooseDataList: [],
+      disabled: false, //  查询、重置按钮是否可操作
+      loading: false, //  表格加载中
+      columns: [
+        { title: '序号', dataIndex: 'no', width: 60, align: 'center' },
+        { title: '产品编码', dataIndex: 'code', align: 'center' },
+        { title: '产品名称', dataIndex: 'name', align: 'center', width: '18%', ellipsis: true, customRender: function (text) { return text || '--' } },
+        { title: '原厂编码', dataIndex: 'origCode', align: 'center', ellipsis: true, customRender: function (text) { return text || '--' } },
+        { title: '省级价', dataIndex: 'provincePrice', width: '6%', align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } },
+        { title: '市级价', dataIndex: 'cityPrice', width: '6%', align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } },
+        { title: '特约价', dataIndex: 'specialPrice', width: '6%', align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } },
+        { title: '品牌', dataIndex: 'productBrandName', align: 'center', ellipsis: true, customRender: function (text) { return text || '--' } },
+        { title: '产品分类', scopedSlots: { customRender: 'productType' }, width: '10%', align: 'center' },
+        { title: '包装数', scopedSlots: { customRender: 'productQty' }, align: 'center' },
+        { title: '单位', dataIndex: 'unit', align: 'center', ellipsis: true, customRender: function (text) { return text || '--' } }
+      ],
+      // 加载数据方法 必须为 Promise 对象
+      loadData: parameter => {
+        this.disabled = true
+        this.spinning = true
+        const params = Object.assign(parameter, this.queryParam)
+        return productList(params).then(res => {
+          let data
+          if (res.status == 200) {
+            data = res.data
+            const no = (data.pageNo - 1) * data.pageSize
+            for (var i = 0; i < data.list.length; i++) {
+              data.list[i].no = no + i + 1
+            }
+            this.disabled = false
+          }
+          this.spinning = false
+          return data
+        })
+      },
+      rowSelectionInfo: null
+    }
+  },
+  computed: {
+    selectCount () {
+      return this.rowSelectionInfo && this.rowSelectionInfo.selectedRowKeys.length
+    }
+  },
+  methods: {
+    // 表格选中项
+    rowSelectionFun (obj) {
+      this.rowSelectionInfo = obj || null
+    },
+    // 重置数据
+    resetData () {
+      this.queryParam.code = ''
+      this.queryParam.name = ''
+      this.queryParam.productBrandSn = undefined
+      this.queryParam.productTypeSn1 = ''
+      this.queryParam.productTypeSn2 = ''
+      this.queryParam.productTypeSn3 = ''
+      this.queryParam.productType = []
+      this.$nextTick(() => {
+        this.$refs.table.refresh()
+      })
+    },
+    //  清空选项
+    resetSearchForm () {
+      this.rowSelectionInfo = null
+      this.$refs.table.clearSelected()
+    },
+    // 保存
+    handleSave () {
+      if (!this.rowSelectionInfo || (this.rowSelectionInfo && this.rowSelectionInfo.selectedRowKeys.length < 1)) {
+        this.$message.warning('请在列表勾选后再进行操作!')
+        return
+      }
+      const resultList = JSON.parse(JSON.stringify(this.rowSelectionInfo && this.rowSelectionInfo.selectedRows))
+      this.$emit('ok', resultList)
+      this.isShow = false
+    },
+    //  产品分类  change
+    changeProductType (val, opt) {
+      this.queryParam.productTypeSn1 = val[0] ? val[0] : ''
+      this.queryParam.productTypeSn2 = val[1] ? val[1] : ''
+      this.queryParam.productTypeSn3 = val[2] ? val[2] : ''
+    },
+    // 禁用
+    handleDisabled (list) {
+      this.chooseDataList = list
+    }
+  },
+  watch: {
+    //  父页面传过来的弹框状态
+    openModal (newValue, oldValue) {
+      this.isShow = newValue
+    },
+    //  重定义的弹框状态
+    isShow (newValue, oldValue) {
+      if (!newValue) {
+        this.resetSearchForm()
+        this.$emit('close')
+      } else {
+        const _this = this
+        _this.resetData()
+        if (_this.chooseData && _this.chooseData.length > 0) {
+          let selectedRows = []
+          const selectedRowKeys = []
+          _this.chooseData.forEach(item => {
+            selectedRowKeys.push(item.goodsSn)
+          })
+          selectedRows = _this.chooseData
+          this.$nextTick(() => { // 页面渲染完成后的回调
+            _this.$refs.table.setTableSelected(selectedRowKeys, selectedRows) // 设置表格选中项
+          })
+        }
+      }
+    }
+  }
+}
+</script>
+
+<style lang="less" scoped>
+  .chooseProducts-modal{
+    .products-con{
+      .btn-con{
+        text-align: center;
+        margin: 30px 0 20px;
+        .button-cancel{
+          font-size: 12px;
+        }
+      }
+    }
+  }
+</style>

+ 341 - 0
src/views/promotionRulesManagement/dealerPromotions/detail.vue

@@ -0,0 +1,341 @@
+<template>
+  <div class="salesDetail-wrap">
+    <a-spin :spinning="spinning" tip="Loading...">
+      <a-page-header :ghost="false" :backIcon="false" class="salesDetail-cont" style="padding:16px 24px;">
+        <template slot="subTitle">
+          <a href="javascript:;" @click="handleBack"><a-icon type="left"></a-icon> 返回列表</a>
+          <span style="margin: 0 10px 0 20px;color: #666;font-size: 14px;font-weight: 600;">促销名称:{{ detailData&&detailData.title||'--' }}</span>
+          <a-button type="link" class="button-default" @click="isShowBisiceInfo=!isShowBisiceInfo">
+            <a-icon :type="isShowBisiceInfo ? 'eye-invisible' : 'eye'"/> {{ isShowBisiceInfo?'隐藏':'查看' }}信息
+          </a-button>
+        </template>
+      </a-page-header>
+      <!-- 基础信息 -->
+      <a-card size="small" title="基础信息" :bordered="false" v-show="!isShowBisiceInfo" class="salesDetail-cont">
+        <a-descriptions size="small" :column="2" v-if="detailData">
+          <a-descriptions-item label="促销名称">{{ detailData.title || '--' }}</a-descriptions-item>
+          <a-descriptions-item label="促销简称">{{ detailData.description || '--' }}</a-descriptions-item>
+          <a-descriptions-item label="促销时间" v-if="detailData.promotionDateStart&& detailData.promotionDateEnd">{{ detailData.promotionDateStart }}-{{ detailData.promotionDateEnd }}</a-descriptions-item>
+          <a-descriptions-item label="促销时间" v-else>--</a-descriptions-item>
+          <a-descriptions-item label="审核通过时间">{{ detailData.auditDate||'--' }}</a-descriptions-item>
+          <a-descriptions-item label="费用所属部门">{{ detailData.expenseDepartmentName || '--' }}</a-descriptions-item>
+          <a-descriptions-item label="参与客户"><div @click="handleSee">共<span class="link-bule">{{ detailData.dealerQty }}</span>个</div></a-descriptions-item>
+          <a-descriptions-item label="促销描述" :span="2">
+            <div class="descItem">{{ detailData.content || '' }}</div>
+          </a-descriptions-item>
+          <a-descriptions-item label="附件" :span="2">
+            <div class="attachmentBox" v-if="detailData.attachmentList&&detailData.attachmentList.length>0">
+              <a
+                class="link-bule"
+                target="downloadFile"
+                :href="item.filePath"
+                v-for="item in detailData.attachmentList"
+                :key="item.id"
+                download>{{ item.fileName }}</a>
+            </div>
+            <span v-else>--</span>
+          </a-descriptions-item>
+        </a-descriptions>
+      </a-card>
+      <a-card size="small" title="规则设置" :bordered="false" class="pages-wrap">
+        <div class="btnGroup" v-if="$hasPermissions('B_rulesAddEdit')&&$route.query.type=='rule'">
+          <a-button type="primary" class="button-warning" @click="openBtnModal('SendProducts')" :disabled="disabled">买产品送产品</a-button>
+          <a-button style="margin:0 10px" type="primary" class="button-warn" @click="openBtnModal('SendAmount')" :disabled="disabled">买产品送采购额</a-button>
+          <a-button type="primary" @click="openBtnModal('SpecialOffer')" :disabled="disabled">特价产品</a-button>
+        </div>
+        <!-- 列表 -->
+        <s-table
+          class="sTable"
+          ref="table"
+          size="small"
+          :rowKey="(record) => record.id"
+          :columns="columns"
+          :data="loadData"
+          :defaultLoadData="false"
+          :showPagination="false"
+          bordered>
+          <!-- 门槛规则 -->
+          <template slot="cillProduct" slot-scope="text, record">
+            <div v-if="record.gateFlag === '1'">
+              <span v-if="record.gateType==='RATIO_AMOUNT'">
+                购买门槛产品金额{{ record.gateAmount*100 }}%作为配额
+              </span>
+              <span v-else-if="record.gateType==='MIN_AMOUNT'">
+                购买门槛产品满最低金额{{ record.gateAmount }}元,不限制配额
+              </span>
+              <span v-else>购买满{{ record.gateAmount }}元门槛产品,可使用 {{ record.quotaAmount }}元配额,采购规则中的{{ record.promotionRuleType!='PROMO_PROD'?'正价':'特价' }}商品</span>
+            </div>
+            <span v-else>--</span>
+          </template>
+          <!-- 规则 -->
+          <template slot="ruleProduct" slot-scope="text, record">
+            <div v-if="record.promotionRuleType == 'BUY_PROD_GIVE_PROD'">
+              {{ record.regularSameFlag==1?'同款':'不同款' }}产品,购买满{{ record.regularQty }}个正价产品,送{{ record.promotionQty }}个促销产品{{ (record.accrualFlag&&record.accrualFlag==1)?',数量叠加':',数量不叠加' }}
+            </div>
+            <div v-else-if="record.promotionRuleType == 'BUY_PROD_GIVE_MONEY'">
+              购买满{{ record.regularAmount }}元正价产品,送{{ record.giveAmount }}元促销品采购额{{ record.promotionRuleType ==='BUY_PROD_GIVE_MONEY'?(record.accrualFlag&&record.accrualFlag==1)?',金额叠加':',金额不叠加':'' }}
+            </div>
+            <div v-else>
+              特价产品
+            </div>
+          </template>
+          <!-- 操作 -->
+          <template slot="action" slot-scope="text, record">
+            <a-button
+              v-if="$hasPermissions('B_rulesAddEdit')&&$route.query.type=='rule'"
+              size="small"
+              type="link"
+              @click="handleEdit(record)"
+              class="button-info"
+              id="promotionList-edit-btn">编辑</a-button>
+            <a-button
+              v-if="$hasPermissions('B_rulesDel')&&$route.query.type=='rule'"
+              size="small"
+              type="link"
+              @click="handleDel(record)"
+              class="button-error"
+              id="promotionList-del-btn">删除</a-button>
+            <a-button
+              v-if="$hasPermissions('B_dealerPromotionDetail')&&!$route.query.type"
+              size="small"
+              type="link"
+              @click="handleDetail(record)"
+              class="button-info"
+              id="promotionList-edit-btn">详情</a-button>
+          </template>
+        </s-table>
+        <div style="text-align:center;margin-top:20px;" v-if="$route.query.type=='rule'">
+          <a-button
+            type="primary"
+            size="large"
+            style="padding:0 30px;"
+            @click="handleSubmit"
+            :disabled="disabled"
+            v-if="$hasPermissions('B_rulesSubmit')&&(mainContentList&&mainContentList.length>0)">提交</a-button>
+        </div>
+      </a-card>
+    </a-spin>
+    <!-- 查看参与客户 -->
+    <lookUp-customers-modal ref="lookUpCustomers" :openModal="openCustomerModal" @close="openCustomerModal = false"></lookUp-customers-modal>
+    <!-- 促销品费用归属品牌/促销品费用归属品类 -->
+    <brandCategoryModal :openType="openType" :openModal="openModal" @close="openModal = false"></brandCategoryModal>
+    <!-- 详情 -->
+    <detailModal :openModal="openDetailModal" :itemSn="detailSn" @close="closeDetailModal"></detailModal>
+    <!-- 买产品送产品  弹窗 -->
+    <sendProductsModal :openModal="openSendProductsModal" :itemSn="detailSn" :promotionSn="$route.query.sn" @ok="$refs.table.refresh()" @close="openSendProductsModal = false"></sendProductsModal>
+    <!-- 买产品送采购额 弹窗 -->
+    <sendAmountModal :openModal="openSendAmountModal" :itemSn="detailSn" :promotionSn="$route.query.sn" @ok="$refs.table.refresh()" @close="openSendAmountModal = false"></sendAmountModal>
+    <!-- 特价产品  弹窗 -->
+    <specialOfferModal :openModal="openSpecialOfferModal" :itemSn="detailSn" :promotionSn="$route.query.sn" @ok="$refs.table.refresh()" @close="openSpecialOfferModal = false"></specialOfferModal>
+  </div>
+</template>
+
+<script>
+import { commonMixin } from '@/utils/mixin'
+import { STable } from '@/components'
+import lookUpCustomersModal from '../promotionManagement/lookUpCustomersModal'
+import brandCategoryModal from './brandCategoryModal'
+import detailModal from './detailModal'
+import sendProductsModal from './sendProductsModal'
+import sendAmountModal from './sendAmountModal'
+import specialOfferModal from './specialOfferModal'
+import { getRuleQueryList, dealerPromotionInfo, promotionRulesDel, promotionSubmit } from '@/api/promotion'
+export default {
+  name: 'SalesOrderWarehouseDetail',
+  mixins: [commonMixin],
+  components: { STable, lookUpCustomersModal, brandCategoryModal, detailModal, sendProductsModal, sendAmountModal, specialOfferModal },
+  data () {
+    return {
+      disabled: false,
+      spinning: false,
+      detailData: null, //  详情数据
+      countData: null, // 数量数据
+      fromRouter: null,
+      openModal: false,
+      isShowBisiceInfo: false,
+      openCustomerModal: false,
+      openType: undefined,
+      openDetailModal: false,
+      openSendProductsModal: false,
+      openSendAmountModal: false,
+      openSpecialOfferModal: false,
+      // 加载数据方法 必须为 Promise 对象
+      loadData: parameter => {
+        this.disabled = true
+        this.spinning = true
+        const dataAjax = Object.assign(parameter, { promotionSn: this.$route.query.sn })
+        return getRuleQueryList(dataAjax).then(res => {
+          let data
+          if (res.status == 200) {
+            data = res.data
+            for (var i = 0; i < data.length; i++) {
+              data[i].no = i + 1
+            }
+            this.disabled = false
+          }
+          this.spinning = false
+          this.mainContentList = data
+          return data
+        })
+      },
+      detailSn: null,
+      mainContentList: []
+    }
+  },
+  computed: {
+    columns () {
+      const _this = this
+      const arr = [
+        { title: '序号', dataIndex: 'no', width: '6%', align: 'center' },
+        { title: '促销类型', dataIndex: 'promotionRuleTypeDictValue', width: '13%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '规则简称', dataIndex: 'description', width: '10%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '规则门槛', scopedSlots: { customRender: 'cillProduct' }, width: '20%', align: 'center' },
+        { title: '规则', scopedSlots: { customRender: 'ruleProduct' }, width: '20%', align: 'center' },
+        { title: '订单起订金额(元)', dataIndex: 'minOrderAmount', width: '10%', align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } },
+        { title: '活动经费上限(元)', dataIndex: 'upperLimitAmount', width: '10%', align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } },
+        { title: '操作', scopedSlots: { customRender: 'action' }, width: '20%', align: 'center' }
+      ]
+      return arr
+    }
+  },
+  methods: {
+    // 打开详情弹窗
+    handleDetail (row) {
+      this.detailSn = row.promotionRuleSn
+      this.openDetailModal = true
+    },
+    // 关闭详情弹窗
+    closeDetailModal () {
+      this.detailSn = null
+      this.openDetailModal = false
+    },
+    //  返回
+    handleBack () {
+      this.$router.push({ name: 'dealerPromotionManagement' })
+    },
+    //  基础信息详情
+    getDetail () {
+      dealerPromotionInfo({ sn: this.$route.query.sn }).then(res => {
+        if (res.status == 200) {
+          this.$refs.table.refresh(true)
+          if (res.data && res.data.attachmentList) {
+            res.data.attachmentList.forEach(item => {
+              item.filePath = item.filePath.replace(/^http:\/\//i, 'https://')
+            })
+          }
+          this.detailData = res.data || null
+        } else {
+          this.detailData = null
+        }
+      })
+    },
+    // 买产品送产品、买产品送采购额、特价产品   弹窗
+    openBtnModal (str) {
+      this.detailSn = null
+      const name = 'open' + str + 'Modal'
+      this[name] = true
+    },
+    // 查看客户
+    handleSee () {
+      this.openCustomerModal = true
+      this.$nextTick(() => {
+        this.$refs.lookUpCustomers.pageInit({ dealerSnList: this.detailData.dealerSnList ? this.detailData.dealerSnList : undefined })
+      })
+    },
+    // 删除规则
+    handleDel (row) {
+      const _this = this
+      this.$confirm({
+        title: '提示',
+        content: '确认要该规则吗?',
+        centered: true,
+        onOk () {
+          _this.spinning = true
+          promotionRulesDel({ promotionSn: _this.$route.query.sn, promotionRuleSn: row.promotionRuleSn }).then(res => {
+            if (res.status == 200) {
+              _this.$message.success(res.message)
+              _this.$refs.table.refresh()
+              _this.spinning = false
+            } else {
+              _this.spinning = false
+            }
+          })
+        }
+      })
+    },
+    // 提交
+    handleSubmit () {
+      const _this = this
+      _this.disabled = true
+      promotionSubmit({ sn: _this.$route.query.sn }).then(res => {
+        if (res.status == 200) {
+          _this.$message.success(res.message)
+          _this.handleBack()
+        }
+        _this.disabled = false
+      })
+    },
+    handleEdit (row) {
+      this.detailSn = row.promotionRuleSn
+      if (row.promotionRuleType === 'BUY_PROD_GIVE_PROD') {
+        this.openSendProductsModal = true
+      } else if (row.promotionRuleType === 'BUY_PROD_GIVE_MONEY') {
+        this.openSendAmountModal = true
+      } else {
+        this.openSpecialOfferModal = true
+      }
+    }
+  },
+  mounted () {
+    if (!this.$store.state.app.isNewTab || this.outBizSubSn || this.bizSn) { // 页签刷新 或 为弹框时调用
+      this.getDetail()
+    }
+  },
+  activated () {
+    // 如果是新页签打开或者进入新的子页(例:存在列表第2条数据编辑页页签时再打开第4条数据的编辑页),则重置当前页面
+    if (this.$store.state.app.isNewTab || !this.$store.state.app.isNewSubTab) {
+      this.getDetail()
+    }
+  },
+  beforeRouteEnter (to, from, next) {
+    next(vm => {
+      vm.fromRouter = from
+    })
+  }
+}
+</script>
+
+<style lang="less" scoped>
+  .salesDetail-wrap{
+    .salesDetail-cont{
+      margin-bottom: 10px;
+    }
+    .btnGroup{
+      margin-bottom:15px;
+    }
+    .flex{
+      display:flex;
+      align-items: center;
+    }
+    .footer-cont{
+      margin-top: 5px;
+      text-align: center;
+    }
+    .attachmentBox>a::after{
+      content:','
+    }
+    .attachmentBox>a:last-child::after{
+      content:''
+    }
+    /deep/.ant-descriptions-item-label .ant-descriptions-item-colon{
+       display:inline-block !important;
+       vertical-align: top;
+       max-width:10%;
+    }
+     /deep/.ant-descriptions-item-content{
+      display:inline-block !important;
+      max-width:89%;
+      vertical-align: top;
+    }
+  }
+</style>

+ 406 - 0
src/views/promotionRulesManagement/dealerPromotions/detailModal.vue

@@ -0,0 +1,406 @@
+<template>
+  <a-modal
+    centered
+    class="dealerPromotions-basicInfo-modal"
+    :footer="null"
+    :maskClosable="false"
+    title="详情"
+    v-model="isShow"
+    @cancel="isShow=false"
+    width="80%">
+    <a-spin :spinning="spinning" tip="Loading...">
+      <a-form-model
+        id="dealerPromotions-basicInfo-form"
+        ref="ruleForm"
+        :model="form"
+        :label-col="formItemLayout.labelCol"
+        :wrapper-col="formItemLayout.wrapperCol" >
+        <a-form-model-item label="规则简称" v-if="form.description">
+          <a-input
+            size="small"
+            disabled="true"
+            v-model.trim="form.description"></a-input>
+        </a-form-model-item>
+        <a-form-model-item label="规则门槛" v-if="form.gateFlag">
+          <a-radio-group v-model="form.gateFlag" button-style="solid" size="small" disabled="true">
+            <a-radio-button value="1">
+              有
+            </a-radio-button>
+            <a-radio-button value="0">
+              无
+            </a-radio-button>
+          </a-radio-group>
+          <div v-if="form.gateFlag==='1'">
+            <span v-if="form.gateType==='RATIO_AMOUNT'">购买门槛产品金额{{ form.gateAmount*100 }}%作为配额 </span>
+            <span v-if="form.gateType==='MIN_AMOUNT'">购买门槛产品满最低金额{{ form.gateAmount }}元,不限制配额。</span>
+            <span v-if="form.gateType==='FIXED_AMOUNT'">购买满{{ form.gateAmount }}元门槛产品,可使用{{ form.quotaAmount }}元配额,采购规则中的{{ form.promotionRuleType!='PROMO_PROD'?'正价':'特价' }}商品(配额算销售额)</span>
+          </div>
+        </a-form-model-item>
+        <!-- 买产品送产品 -->
+        <a-form-model-item label="满赠规则" prop="regularSameFlag" v-if="form.promotionRuleType ==='BUY_PROD_GIVE_PROD'">
+          <span>{{ form.regularSameFlag==='1'?'同款':'不同款' }}产品购买满{{ form.regularQty }}个正价产品,送{{ form.promotionQty }}个促销产品</span>
+          <span v-if="form.restrictFlag&&form.restrictFlag==1">,限制正价产品款数{{ form.restrictCategory }}</span>
+        </a-form-model-item>
+        <a-form-model-item label="满赠规则" prop="regularSameFlag" v-if="form.promotionRuleType ==='BUY_PROD_GIVE_MONEY'">
+          购买满{{ form.regularAmount }}元正价产品,送{{ form.giveAmount }}元({{ perCentNum }}%促销品采购额)
+        </a-form-model-item>
+        <a-form-model-item label="数量叠加" prop="accrualFlag" v-if="form.promotionRuleType ==='BUY_PROD_GIVE_PROD'&&form.accrualFlag">
+          <a-radio-group v-model="form.accrualFlag" button-style="solid" size="small" disabled="true">
+            <a-radio-button value="1">
+              是
+            </a-radio-button>
+            <a-radio-button value="0">
+              否
+            </a-radio-button>
+          </a-radio-group>
+        </a-form-model-item>
+        <a-form-model-item label="金额叠加" prop="accrualFlag" v-if="form.promotionRuleType ==='BUY_PROD_GIVE_MONEY'&&form.accrualFlag">
+          <a-radio-group v-model="form.accrualFlag" button-style="solid" size="small" disabled="true">
+            <a-radio-button value="1">
+              是
+            </a-radio-button>
+            <a-radio-button value="0">
+              否
+            </a-radio-button>
+          </a-radio-group>
+        </a-form-model-item>
+        <a-form-model-item prop="minOrderFlag" label="订单起订金额">
+          <a-select v-model="form.minOrderFlag" style="width: 160px" size="small" disabled="true">
+            <a-select-option value="0">
+              不限
+            </a-select-option>
+            <a-select-option value="1">
+              限制
+            </a-select-option>
+          </a-select>
+          <a-input
+            disabled="true"
+            v-if="form.minOrderAmount"
+            size="small"
+            style="margin-left:10px;width:100px;"
+            v-model="form.minOrderAmount"/>
+          {{ form.minOrderAmount?'元':'' }}
+        </a-form-model-item>
+        <a-form-model-item prop="upperLimitFlag" label="活动经费上限">
+          <a-select v-model="form.upperLimitFlag" style="width: 160px" size="small" disabled="true">
+            <a-select-option value="0">
+              不限
+            </a-select-option>
+            <a-select-option value="1">
+              限制
+            </a-select-option>
+          </a-select>
+          <a-input
+            disabled="true"
+            v-if="form.upperLimitAmount"
+            size="small"
+            style="margin-left:10px;width:100px;"
+            v-model="form.upperLimitAmount"/>
+          {{ form.upperLimitAmount?'元':'' }}
+        </a-form-model-item>
+        <a-form-model-item label="促销品是否与正品一致" v-if="form.regularPromotionSameFlag" prop="regularPromotionSameFlag">
+          <a-radio-group v-model="form.regularPromotionSameFlag" button-style="solid" size="small" disabled="true">
+            <a-radio-button value="1">
+              是
+            </a-radio-button>
+            <a-radio-button value="0">
+              否
+            </a-radio-button>
+          </a-radio-group>
+        </a-form-model-item>
+        <a-form-model-item label="采购额适用范围" v-if="form.scopeFlag" prop="scopeFlag" >
+          <a-radio-group v-model="form.scopeFlag" button-style="solid" size="small" disabled="true">
+            <a-radio-button value="0">
+              部分产品
+            </a-radio-button>
+            <a-radio-button value="1">
+              全部产品
+            </a-radio-button>
+          </a-radio-group>
+        </a-form-model-item></a-form-model>
+      <a-card size="small" :bordered="false" class="pages-wrap">
+        <a-radio-group v-model="chooseVal" button-style="solid">
+          <a-radio-button value="a" v-show="form.gateFlag==='1'">
+            门槛产品
+          </a-radio-button>
+          <a-radio-button value="b" v-show="form.promotionRuleType!='PROMO_PROD'">
+            正价产品
+          </a-radio-button>
+          <a-radio-button value="c" v-show="form.regularPromotionSameFlag==='0'||form.scopeFlag==='0'">
+            促销产品
+          </a-radio-button>
+          <a-radio-button value="d" v-show="form.promotionRuleType=='PROMO_PROD'">
+            特价产品
+          </a-radio-button>
+        </a-radio-group>
+        <!-- 列表 -->
+        <div v-show="chooseVal!='d'">
+          <a-table
+            class="sTable"
+            style="margin-top:10px;max-height:340px;"
+            ref="table"
+            size="small"
+            :rowKey="(record) => record.productScopeSn"
+            :columns="columns"
+            :data-source="chooseVal==='a'?form.gateProductList:chooseVal==='b'?form.regularProductList:form.giftProductList"
+            :scroll="{ y: 330 }"
+            :pagination="false"
+            bordered
+          >
+            <!-- 产品分类 -->
+            <template slot="productType" slot-scope="text, record">
+              <div class="tabBox" v-if="record.productTypeList && record.productTypeList.length>0">
+                <a-tag style="margin-bottom:5px;" v-for="item in record.productTypeList" :key="item.id">{{ item.productTypeName3? item.productTypeName2+'/'+item.productTypeName3:(item.productTypeName2&&!item.productTypeName3)?item.productTypeName2:item.productTypeName1 }}</a-tag>
+              </div>
+            </template>
+            <!-- 品牌 -->
+            <template slot="productBrand" slot-scope="text, record">
+              <div class="tabBox" v-if="record.productBrandList && record.productBrandList.length>0">
+                <a-tag style="margin-bottom:5px;" v-for="item in record.productBrandList" :key="item.id">{{ item.productBrandName }}</a-tag>
+              </div>
+            </template>
+            <!-- 产品 -->
+            <template slot="product" slot-scope="text, record">
+              <div class="tabBox" v-if="record.productThisList && record.productThisList.length>0">
+                <a-tag style="margin-bottom:5px;" v-for="item in record.productThisList" :key="item.id">{{ item.productCode }}</a-tag>
+              </div>
+            </template>
+            <!-- 设置起订量 -->
+            <template slot="setNum" slot-scope="text, record">
+              <a-tag style="width:60%;margin-bottom:5px;margin-right:0;">{{ record.unitTypeDictValue }}</a-tag>
+              <a-tag style="width:60%;margin-right:0;">{{ record.unitQty }}</a-tag>
+            </template>
+          </a-table>
+        </div>
+        <!-- 特价产品 -->
+        <div v-show="chooseVal=='d'">
+          <a-table
+            class="sTable"
+            style="margin-top:10px;max-height:340px;"
+            ref="table"
+            size="small"
+            :rowKey="(record) => record.productScopeSn"
+            :columns="specialColumns"
+            :data-source="form.specialProductList"
+            :scroll="{ y: 330 }"
+            :pagination="false"
+            bordered
+          >
+            <!-- 产品分类 -->
+            <template slot="productType" slot-scope="text, record">
+              <div class="tabBox" v-if="record.productTypeList && record.productTypeList.length>0">
+                <a-tag style="margin-bottom:5px;" v-for="item in record.productTypeList" :key="item.id">{{ item.productTypeName3? item.productTypeName2+'/'+item.productTypeName3:(item.productTypeName2&&!item.productTypeName3)?item.productTypeName2:item.productTypeName1 }}</a-tag>
+              </div>
+            </template>
+            <!-- 品牌 -->
+            <template slot="productBrand" slot-scope="text, record">
+              <div class="tabBox" v-if="record.productBrandList && record.productBrandList.length>0">
+                <a-tag style="margin-bottom:5px;" v-for="item in record.productBrandList" :key="item.id">{{ item.productBrandName }}</a-tag>
+              </div>
+            </template>
+            <!-- 产品 -->
+            <template slot="product" slot-scope="text, record">
+              <div class="tabBox" v-if="record.productThisList && record.productThisList.length>0">
+                <a-tag style="margin-bottom:5px;" v-for="item in record.productThisList" :key="item.id">{{ item.productCode }}</a-tag>
+              </div>
+              <span v-else>--</span>
+            </template>
+            <!-- 设置起订量 -->
+            <template slot="setNum" slot-scope="text, record">
+              <a-tag style="width:90%;margin-bottom:5px;margin-right:0;">{{ record.unitTypeDictValue }}</a-tag>
+              <a-tag style="width:90%;margin-right:0;">{{ record.unitQty }}</a-tag>
+            </template>
+          </a-table>
+        </div>
+      </a-card>
+      <div class="btn-cont">
+        <a-button id="dealerPromotions-basicInfo-modal-back" @click="isShow = false">关闭</a-button>
+      </div>
+    </a-spin>
+  </a-modal>
+</template>
+
+<script>
+import { commonMixin } from '@/utils/mixin'
+import { STable } from '@/components'
+import { getRuleDetail } from '@/api/promotion'
+export default {
+  name: 'DetailModal',
+  mixins: [commonMixin],
+  components: { STable },
+  props: {
+    openModal: { //  弹框显示状态
+      type: Boolean,
+      default: false
+    },
+    itemSn: {
+      type: String,
+      default: ''
+    }
+  },
+  data () {
+    const _this = this
+    return {
+      isShow: this.openModal, //  是否打开弹框
+      spinning: false,
+      formItemLayout: {
+        labelCol: { span: 4 },
+        wrapperCol: { span: 20 }
+      },
+      form: {
+        promotionRuleType: undefined,
+        gateFlag: undefined, // 门槛
+        gateAmount: undefined,
+        quotaAmount: undefined,
+        regularSameFlag: undefined, // 满赠规则  不同款商品
+        regularQty: undefined,
+        promotionQty: undefined,
+        regularAmount: undefined,
+        giveAmount: undefined,
+        restrictFlag: undefined, // 限制正价产品款数
+        restrictCategory: undefined,
+        accrualFlag: undefined, // 数量叠加
+        minOrderFlag: undefined, // 起订金额
+        minOrderAmount: undefined,
+        upperLimitFlag: undefined, // 活动经费上限
+        upperLimitAmount: undefined,
+        regularPromotionSameFlag: undefined,
+        productTypeArr: [],
+        productTypeList: [],
+        productBrandArr: [],
+        productBrandList: [],
+        productThisList: []
+      },
+      chooseVal: 'a',
+      specialColumns: [
+        { title: '产品分类', width: '11%', scopedSlots: { customRender: 'productType' }, align: 'center' },
+        { title: '品牌', width: '11%', scopedSlots: { customRender: 'productBrand' }, align: 'center' },
+        { title: '产品', scopedSlots: { customRender: 'product' }, width: '11%', align: 'center' },
+        { title: '省价原价', dataIndex: 'provincePrice', width: '6%', align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } },
+        { title: '省价特价', dataIndex: 'provinceDiscountPrice', width: '6%', align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } },
+        { title: '省价折扣', dataIndex: 'provinceDiscountRate', width: '6%', align: 'center', customRender: function (text) { return ((text || text == 0) ? (text + '%') : '--') } },
+        { title: '市价原价', dataIndex: 'cityPrice', width: '6%', align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } },
+        { title: '市价特价', dataIndex: 'cityDiscountPrice', width: '6%', align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } },
+        { title: '市价折扣', dataIndex: 'cityDiscountRate', width: '6%', align: 'center', customRender: function (text) { return ((text || text == 0) ? (text + '%') : '--') } },
+        { title: '特约原价', dataIndex: 'specialPrice', width: '6%', align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } },
+        { title: '特约特价', dataIndex: 'specialDiscountPrice', width: '6%', align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } },
+        { title: '特约折扣', dataIndex: 'specialDiscountRate', width: '6%', align: 'center', customRender: function (text) { return ((text || text == 0) ? (text + '%') : '--') } },
+        { title: '设置起订量', width: '7%', scopedSlots: { customRender: 'setNum' }, align: 'center' }
+      ]
+    }
+  },
+  computed: {
+    columns () {
+      const _this = this
+      const arr = [
+        { title: '产品分类', width: '30%', scopedSlots: { customRender: 'productType' }, align: 'center' },
+        { title: '品牌', width: '35%', scopedSlots: { customRender: 'productBrand' }, align: 'center' },
+        { title: '产品', width: '35%', scopedSlots: { customRender: 'product' }, align: 'center' },
+        { title: '设置起订量', width: '20%', scopedSlots: { customRender: 'setNum' }, align: 'center' }
+      ]
+      if (_this.chooseVal == 'c') {
+        arr.pop()
+      }
+      return arr
+    },
+    perCentNum () {
+      return Math.floor(((this.form.giveAmount / this.form.regularAmount) * 100).toFixed(2))
+    }
+  },
+  methods: {
+    // 重置
+    resetSearchForm () {
+      this.form = {
+        promotionRuleType: undefined,
+        gateFlag: undefined, // 门槛
+        gateAmount: undefined,
+        quotaAmount: undefined,
+        regularSameFlag: undefined, // 满赠规则  不同款商品
+        regularQty: undefined,
+        promotionQty: undefined,
+        regularAmount: undefined,
+        giveAmount: undefined,
+        restrictFlag: undefined, // 限制正价产品款数
+        restrictCategory: undefined,
+        accrualFlag: undefined, // 数量叠加
+        minOrderFlag: undefined, // 起订金额
+        minOrderAmount: undefined,
+        upperLimitFlag: undefined, // 活动经费上限
+        upperLimitAmount: undefined,
+        regularPromotionSameFlag: undefined
+      }
+    },
+    // 获取列表详情
+    getDetail () {
+      getRuleDetail({ sn: this.itemSn }).then(res => {
+        if (res.status == 200) {
+          const resultObj = res.data
+          this.chooseVal = resultObj.gateFlag == '1' ? 'a' : resultObj.promotionRuleType == 'PROMO_PROD' ? 'd' : 'b'
+          this.form = { ...this.form, ...resultObj }
+        }
+      })
+    }
+  },
+  watch: {
+    //  父页面传过来的弹框状态
+    openModal (newValue, oldValue) {
+      this.isShow = newValue
+    },
+    //  重定义的弹框状态
+    isShow (newValue, oldValue) {
+      if (!newValue) {
+        this.$emit('close')
+        this.resetSearchForm()
+      } else {
+        this.getDetail()
+      }
+    }
+  }
+}
+</script>
+
+<style lang="less" scoped>
+  .dealerPromotions-basicInfo-modal{
+    .ant-modal-body {
+      padding: 40px 40px 24px;
+    }
+    .dealerPromotions-basicInfo-con{
+      margin-top:10px;
+    }
+    .ant-form-item{
+      margin-bottom:0 !important;
+    }
+    .buyerBox{
+      border:1px solid #d9d9d9;margin-top:10px;border-radius:4px;padding:4px 10px;background:#f2f2f2;max-height:130px;overflow-y:scroll;
+    }
+    .btn-cont {
+      text-align: center;
+      margin: 35px 0 10px;
+    }
+    .tabBox{
+       max-height:100px;
+       overflow-y:scroll;
+    }
+   .tabBox::-webkit-scrollbar {
+       width: 0px;
+    }
+    .ant-form-item-control .ant-input[disabled]{
+      color:#333333;
+      background:#ffffff;
+    }
+   .ant-radio-button-wrapper-disabled{
+     color:#333333;
+     padding:0 16px;
+   }
+   .ant-radio-button-wrapper-disabled.ant-radio-button-wrapper-checked{
+   background-color: #ed1c24 !important;
+   color:#ffffff;
+    padding:0 16px;
+   }
+   /deep/.ant-select-disabled .ant-select-selection, .ant-cascader-picker-disabled{
+      color:#333 !important;
+      background:#fff;
+   }
+  }
+
+</style>

+ 138 - 0
src/views/promotionRulesManagement/dealerPromotions/editActiveEndTime.vue

@@ -0,0 +1,138 @@
+<template>
+  <a-modal
+    centered
+    class="editActiveEndTime-basicInfo-modal"
+    :footer="null"
+    :maskClosable="false"
+    title="促销时间变更"
+    v-model="isShow"
+    @cancel="isShow=false"
+    :width="500">
+    <a-spin :spinning="spinning" tip="Loading...">
+      <a-form-model
+        id="editActiveEndTime-basicInfo-form"
+        ref="ruleForm"
+        :model="form"
+        :rules="rules"
+        :label-col="formItemLayout.labelCol"
+        :wrapper-col="formItemLayout.wrapperCol" >
+        <a-form-model-item label="" prop="name">
+          <div style="margin-left:40px;">确定要变更{{ form.name }}的促销时间吗?</div>
+        </a-form-model-item>
+        <a-form-model-item label="原结束日期" prop="time">
+          <span>{{ form.timeEnd }}</span>
+        </a-form-model-item>
+        <a-form-model-item label="变更后结束日期" prop="newTimeEnd">
+          <a-date-picker style="width:90%" v-model="form.newTimeEnd" @change="onChange" :format="dateFormat" :disabled-date="disabledDate"/>
+        </a-form-model-item>
+      </a-form-model>
+      <div class="btn-cont">
+        <a-button id="editActiveEndTime-basicInfo-modal-back" @click="isShow = false">取消</a-button>
+        <a-button style="margin-left: 15px;" type="primary" id="editActiveEndTime-modal-save" @click="handleSave">确定</a-button>
+      </div>
+    </a-spin>
+  </a-modal>
+</template>
+
+<script>
+import { commonMixin } from '@/utils/mixin'
+import moment from 'moment'
+import { promotionDateModify } from '@/api/promotion'
+export default {
+  name: 'EditActiveEndTimeModal',
+  mixins: [commonMixin],
+  props: {
+    openModal: { //  弹框显示状态
+      type: Boolean,
+      default: false
+    } },
+  data () {
+    return {
+      isShow: this.openModal, //  是否打开弹框
+      spinning: false,
+      formItemLayout: {
+        labelCol: { span: 6 },
+        wrapperCol: { span: 16 }
+      },
+      form: {
+        name: '',
+        timeStart: '',
+        timeEnd: '',
+        newTimeEnd: ''
+      },
+      dateFormat: 'YYYY-MM-DD',
+      rules: {
+        newTimeEnd: [
+          { required: true, message: '请选择变更的结束时间', trigger: 'change' }
+        ]
+      }
+    }
+  },
+  methods: {
+    onChange (date, dateString) {
+      this.form.newTimeEnd = dateString + ' 23:59:59'
+    },
+    //  保存
+    handleSave () {
+      const _this = this
+      this.$refs.ruleForm.validate(valid => {
+        if (valid) {
+          promotionDateModify({ promotionSn: _this.form.sn, promotionDateStart: _this.form.timeStart, promotionDateEnd: _this.form.newTimeEnd }).then(res => {
+            if (res.status == 200) {
+              _this.$message.success(res.message)
+              setTimeout(() => {
+                _this.isShow = false
+                _this.$emit('ok', res.data)
+                _this.spinning = false
+              }, 1000)
+            } else {
+              _this.spinning = false
+            }
+          })
+        } else {
+          return false
+        }
+      })
+    },
+    // 获取显示内容
+    setData (obj) {
+      this.form = { ...this.form, ...obj }
+    },
+    // 不可选日期
+    disabledDate (date, dateStrings) {
+      return date && date.valueOf('day') < moment().subtract(1, 'day') // 今天以后,包含今天
+    }
+  },
+  watch: {
+    //  父页面传过来的弹框状态
+    openModal (newValue, oldValue) {
+      this.isShow = newValue
+    },
+    //  重定义的弹框状态
+    isShow (newValue, oldValue) {
+      if (!newValue) {
+        this.$emit('close')
+        this.form = {
+          name: '',
+          timeStart: '',
+          timeEnd: '',
+          newTimeEnd: ''
+        }
+      }
+    }
+  }
+}
+</script>
+
+<style lang="less" scoped>
+  .editActiveEndTime-basicInfo-modal{
+    .ant-modal-body {
+      padding: 40px 40px 24px;
+    }
+    .btn-cont {
+      text-align: center;
+      margin: 35px 0 10px;
+    }
+  }
+
+</style>

+ 199 - 0
src/views/promotionRulesManagement/dealerPromotions/importGuideModal.vue

@@ -0,0 +1,199 @@
+<template>
+  <a-modal
+    centered
+    class="importGuide-modal"
+    :footer="null"
+    :maskClosable="false"
+    title="导入产品"
+    v-model="isShow"
+    @cancel="isShow=false"
+    :width="800">
+    <div class="importGuide-con">
+      <div class="explain-con">
+        <div class="explain-item">
+          <div class="explain-tit">
+            <span>1</span>准备导入
+          </div>
+          <ul>
+            <li v-if="goodFlag==='1'">1) 导入的Excel文件中必须包含名为“产品编码”的列,“产品编码”必填</li>
+            <li v-else>1) 导入的Excel文件中必须包含名为“产品编码”、“省级特价”、“市级特价”和“特约特价”的列,都为必填</li>
+            <li>2) 如果导入的产品已经存在,则不会导入该行</li>
+            <li>
+              <a :href="filePath" style="margin: 5px 0 0;display: block;">
+                <a-icon type="download" style="padding-right: 5px;" />下载导入模板
+              </a>
+            </li>
+          </ul>
+        </div>
+        <div class="explain-item">
+          <div class="explain-tit">
+            <span>2</span>上传数据文件
+          </div>
+          <p>目前支持的文件类型*.xls,*.xlsx.</p>
+          <div style="overflow: hidden;padding-left: 23px;">
+            <Upload
+              id="importGuide-attachList"
+              ref="importUpload"
+              :maxNums="1"
+              fileType="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/vnd.ms-excel"
+              uploadType="attach"
+              :action="goodFlag==='1'?attachAction:attachAction1"
+              upText="选择导入文件"
+              @remove="resetSearchForm"
+              @change="changeImport"></Upload>
+          </div>
+        </div>
+      </div>
+      <!-- 按钮 -->
+      <div class="btn-con">
+        <a-button
+          type="primary"
+          id="importGuide-nextStep"
+          size="large"
+          class="button-primary"
+          @click="handlerNextStep"
+          style="padding: 0 60px;">下一步</a-button>
+        <a-button
+          id="importGuide-cancel"
+          size="large"
+          class="button-cancel"
+          @click="isShow=false"
+          style="padding: 0 60px;margin-left: 15px;">取消</a-button>
+      </div>
+    </div>
+    <!-- 导入 -->
+    <chooseImportModal ref="chooseImportBox" :openModal="openImportModal" :paramsData="paramsData" @close="handleClose" @ok="hanldeOk" />
+  </a-modal>
+</template>
+
+<script>
+import ChooseImportModal from './chooseImportModal.vue'
+import { Upload } from '@/components'
+export default {
+  name: 'ImportGuideModal',
+  components: { ChooseImportModal, Upload },
+  props: {
+    openModal: { //  弹框显示状态
+      type: Boolean,
+      default: false
+    },
+    params: {
+      type: Object,
+      default: null
+    },
+    goodFlag: {
+      type: [String, Number],
+      default: '0'
+    }
+  },
+  data () {
+    return {
+      isShow: this.openModal, //  是否打开弹框
+      openImportModal: false, //  导入
+      attachAction: process.env.VUE_APP_API_BASE_URL + '/promotion/importNormalProduct', // 导入门槛、正价、促销产品
+      attachAction1: process.env.VUE_APP_API_BASE_URL + '/promotion/importSpecialProduct', // 导入特价产品
+      paramsData: null,
+      filePath: ''
+    }
+  },
+  methods: {
+    // 清空数据
+    resetSearchForm () {
+      this.$refs.importUpload.setFileList() //  清空导入文件
+      this.paramsData = null //  清空上传数据
+    },
+    // 下一步
+    handlerNextStep () {
+      if (this.paramsData) {
+        this.openImportModal = true
+        this.$refs.chooseImportBox.setFlag(this.goodFlag)
+      } else {
+        this.$message.warning('添加文件后再进行下一步操作!')
+      }
+    },
+    // 上传文件  change
+    changeImport (file) {
+      if (file && JSON.parse(file).length > 0) {
+        this.paramsData = Object.assign({}, JSON.parse(file)[0] || null, this.params)
+      } else {
+        this.paramsData = null
+      }
+    },
+    // 导入
+    hanldeOk (obj) {
+      if (obj && obj.length > 0) {
+        this.$emit('ok', obj)
+        this.isShow = false
+      }
+    },
+    // 关闭
+    handleClose () {
+      this.openImportModal = false
+      this.isShow = false
+    }
+  },
+  watch: {
+    //  父页面传过来的弹框状态
+    openModal (newValue, oldValue) {
+      this.isShow = newValue
+    },
+    //  重定义的弹框状态
+    isShow (newValue, oldValue) {
+      if (!newValue) {
+        this.$emit('close')
+        this.resetSearchForm()
+      } else {
+        this.filePath = location.protocol + '//' + location.host + (this.goodFlag === '1' ? '/templ/促销规则导入产品.xlsx' : '/templ/促销规则导入特价产品.xlsx')
+      }
+    }
+  }
+}
+</script>
+
+<style lang="less" scoped>
+  .importGuide-modal{
+    .importGuide-con{
+      .explain-con{
+        .explain-item{
+          margin-bottom: 10px;
+          .explain-tit{
+            font-weight: bold;
+            span{
+              display: inline-block;
+              width: 18px;
+              height: 18px;
+              line-height: 16px;
+              text-align: center;
+              margin-right: 5px;
+              border-radius: 50%;
+              border: 1px solid rgba(0, 0, 0, 0.3);
+            }
+          }
+          p{
+            margin: 8px 0;
+            padding-left: 23px;
+          }
+          ul{
+            list-style: none;
+            padding: 0;
+            padding-left: 23px;
+            margin: 0;
+            li{
+              line-height: 26px;
+            }
+          }
+        }
+        #importGuide-attachList{
+          width: 100%;
+        }
+      }
+      .btn-con{
+        margin: 10px 0 20px;
+        text-align: center;
+        .button-cancel{
+          font-size: 12px;
+        }
+      }
+    }
+  }
+</style>

+ 449 - 0
src/views/promotionRulesManagement/dealerPromotions/list.vue

@@ -0,0 +1,449 @@
+<template>
+  <a-card size="small" :bordered="false" class="promotionList-wrap">
+    <a-spin :spinning="spinning" tip="Loading...">
+      <!-- 搜索条件 -->
+      <div ref="tableSearch" class="table-page-search-wrapper">
+        <a-form layout="inline" @keyup.enter.native="$refs.table.refresh(true)">
+          <a-row :gutter="15">
+            <a-col :md="5" :sm="24">
+              <a-form-item label="创建时间">
+                <rangeDate ref="rangeDate" @change="dateChange" />
+              </a-form-item>
+            </a-col>
+            <a-col :md="5" :sm="24">
+              <a-form-item label="促销名称/简称">
+                <a-input id="promotionList-queryWord" v-model.trim="queryParam.queryWord" allowClear placeholder="请输入促销名称/简称"/>
+              </a-form-item>
+            </a-col>
+            <a-col :md="5" :sm="24">
+              <a-form-item label="发布状态">
+                <v-select
+                  v-model="queryParam.enabledFlag"
+                  ref="enabledFlag"
+                  id="promotionList-enabledFlag"
+                  code="PUBLISH_STATE"
+                  placeholder="请选择发布状态"
+                  allowClear></v-select>
+              </a-form-item>
+            </a-col>
+            <a-col :md="5" :sm="24">
+              <a-form-item label="活动状态">
+                <v-select
+                  v-model="queryParam.state"
+                  ref="state"
+                  id="promotionList-state"
+                  code="PROMOTION_STATE"
+                  placeholder="请选择活动状态"
+                  allowClear
+                ></v-select>
+              </a-form-item>
+            </a-col>
+            <a-col :md="4" :sm="24">
+              <span class="table-page-search-submitButtons">
+                <a-button type="primary" @click="$refs.table.refresh(true)" :disabled="disabled" id="promotionList-refresh">查询</a-button>
+                <a-button style="margin-left: 5px" @click="resetSearchForm()" :disabled="disabled" id="promotionList-reset">重置</a-button>
+                <!-- <a-button
+                  style="margin-left: 10px"
+                  type="primary"
+                  class="button-warning"
+                  @click="handleExport"
+                  :disabled="disabled"
+                  :loading="exportLoading"
+                >导出</a-button> -->
+                <!-- v-if="$hasPermissions('B_promotionListExport')" -->
+              </span>
+            </a-col>
+          </a-row>
+        </a-form>
+      </div>
+      <!-- 操作按钮 -->
+      <div class="table-operator" v-if="$hasPermissions('B_dealerPromotionAdd')">
+        <a-button id="promotionList-add" type="primary" class="button-error" @click="handleAdd">新增</a-button>
+      </div>
+      <!-- 列表 -->
+      <s-table
+        class="sTable fixPagination"
+        ref="table"
+        :style="{ height: tableHeight+84.5+'px' }"
+        size="small"
+        :rowKey="(record) => record.sparePartsReturnNo"
+        :columns="columns"
+        :data="loadData"
+        :scroll="{ y: tableHeight }"
+        :defaultLoadData="false"
+        bordered>
+        <!-- 促销名称 -->
+        <template slot="promotionName" slot-scope="text, record">
+          <div v-if="$hasPermissions('B_dealerPromotionDetail')" class="link-bule nameBox text-overflows2" @click="handleDetail(record)">{{ record.title }}</div>
+          <div v-else class="nameBox text-overflows2">{{ record.title }}</div>
+        </template>
+        <!-- 促销时间-->
+        <template slot="promotionTime" slot-scope="text, record">
+          <div>{{ record.promotionDateStart }}-{{ record.promotionDateEnd }}</div>
+        </template>
+        <!-- 参与客户 -->
+        <template slot="joinCustomers" slot-scope="text, record">
+          <div @click="handleCustomers(record)">共有<span style="color:#39f;vertical-align:top;">{{ record.dealerSnList?record.dealerSnList.length:0 }}</span>个客户</div>
+        </template>
+        <!-- 发布状态 -->
+        <template slot="releaseStatus" slot-scope="text, record">
+          <a-switch
+            v-if="$hasPermissions('B_dealerPromotionStatus')"
+            id="promotionList-enable"
+            @change="changeStatus(record)"
+            :disabled="record.state!='NOT_START' && record.state!='RUNNING'"
+            :checked="record.enabledFlag == 1 ? true : false"></a-switch>
+          <span v-else>--</span>
+        </template>
+        <!-- 操作 -->
+        <!--  state 待提交:WAIT_SUBMIT 待审核:WAIT_AUDIT 未开始:NOT_START 进行中:RUNNING 审核不通过:AUDIT_REJECT 已结束:IS_OVER -->
+        <template slot="action" slot-scope="text, record">
+          <a-button
+            size="small"
+            type="link"
+            class="button-warning"
+            @click="handleSetRules(record)"
+            v-if="$hasPermissions('B_dealerPromotionRules')&&(record.state =='WAIT_SUBMIT'||record.state == 'AUDIT_REJECT')"
+            id="allocateBillList-examine-btn">规则设置</a-button>
+          <a-button
+            size="small"
+            type="link"
+            v-if="$hasPermissions('B_dealerPromotionEdit')&&(record.state == 'WAIT_SUBMIT' ||record.state == 'AUDIT_REJECT')"
+            @click="handleEdit(record)"
+            class="button-info"
+            id="promotionList-edit-btn">编辑</a-button>
+          <a-button
+            size="small"
+            type="link"
+            v-if="$hasPermissions('B_dealerPromotionAudit')&&record.state == 'WAIT_AUDIT'"
+            @click="handleCheck(record)"
+            class="button-info"
+            id="promotionList-edit-btn">审核</a-button>
+          <a-button
+            size="small"
+            type="link"
+            v-if="$hasPermissions('B_editTime')&&(record.state == 'NOT_START' || record.state=='RUNNING')"
+            @click="handleTime(record)"
+            class="button-info"
+            id="promotionList-edit-btn">促销时间变更</a-button>
+          <a-button
+            size="small"
+            type="link"
+            v-if="$hasPermissions('B_overActive')&&(record.state == 'NO_START' || record.state=='RUNNING')"
+            @click="handleEnd(record)"
+            class="button-info"
+            id="promotionList-edit-btn">终止</a-button>
+          <a-button
+            size="small"
+            type="link"
+            v-if="$hasPermissions('B_dealerPromotionDel')&&(record.state == 'WAIT_SUBMIT'||record.state == 'AUDIT_REJECT')"
+            @click="handleDel(record)"
+            class="button-error"
+            id="promotionList-del-btn">删除</a-button>
+          <div v-if="record.state == 'IS_OVER'">--</div>
+        </template>
+      </s-table>
+    </a-spin>
+    <!-- 参与客户 -->
+    <lookUp-customers-modal ref="lookUpCustomers" :openModal="openCustomerModal" @close="openCustomerModal = false"></lookUp-customers-modal>
+    <!-- 新增/编辑弹窗-->
+    <add-modal v-drag :itemSn="itemSn" :openModal="openModal" @ok="handleOk" @close="openModal=false" />
+    <!-- 促销时间变更 -->
+    <edit-active-end-time ref="editTime" v-drag :openModal="editEndModal" @ok="$refs.table.refresh()" @close="editEndModal=false" />
+    <!-- 审核弹窗 -->
+    <a-modal
+      closable
+      v-model="openAuditModal"
+      :footer="null"
+      width="416px"
+      centered>
+      <div style="display:flex;margin:30px 0 20px 20px;">
+        <a-icon type="question-circle" :style="{fontSize:'23px',color:'#faad14'}"/>
+        <div style="margin-left:10px;">
+          <p style="font-size:16px;font-wight:bold;">提示</p>
+          <p>请点击下方按钮确认操作?</p>
+        </div>
+      </div>
+      <!-- 按钮 -->
+      <div style="text-align: right;">
+        <a-button
+          id="auditModal-cancel"
+          class="button-cancel"
+          @click="closeAuditModal"
+          style="margin-right: 15px;">审核不通过</a-button>
+        <a-button
+          type="primary"
+          id="auditModal-save"
+          class="button-primary"
+          @click="handleAuditModal"
+        >审核通过</a-button>
+      </div>
+    </a-modal>
+  </a-card>
+</template>
+
+<script>
+import { commonMixin } from '@/utils/mixin'
+import { STable, VSelect } from '@/components'
+import addModal from './addModal.vue'
+import lookUpCustomersModal from '../promotionManagement/lookUpCustomersModal'
+import rangeDate from '@/views/common/rangeDate.vue'
+import editActiveEndTime from './editActiveEndTime.vue'
+import supplier from '@/views/common/supplier.js'
+import warehouse from '@/views/common/chooseWarehouse.js'
+import { dealerPromotionList, dealerPromotionDel, modifyEnabledFlag, promotionAudit, promotionIsOver } from '@/api/promotion'
+export default {
+  name: 'PromotionManagementList',
+  mixins: [commonMixin],
+  components: { STable, supplier, VSelect, rangeDate, warehouse, lookUpCustomersModal, addModal, editActiveEndTime },
+  data () {
+    return {
+      spinning: false,
+      disabled: false, //  查询、重置按钮是否可操作
+      openModal: false, // 新增弹框是否显示
+      openCustomerModal: false, // 参与客户弹窗
+      editEndModal: false, // 更改促销时间
+      openDetailModal: false, // 详情弹窗
+      tableHeight: 0,
+      // 查询参数
+      queryParam: {
+        beginDate: undefined,
+        endDate: undefined,
+        queryWord: '',
+        enabledFlag: undefined, // 发布状态
+        state: undefined
+      },
+      columns: [
+        { title: '序号', dataIndex: 'no', width: '5%', align: 'center' },
+        { title: '创建时间', dataIndex: 'createDate', width: '8%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '促销名称', scopedSlots: { customRender: 'promotionName' }, width: '18%', align: 'center' },
+        { title: '促销简称', dataIndex: 'description', width: '14%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '促销时间', scopedSlots: { customRender: 'promotionTime' }, width: '13%', align: 'center' },
+        { title: '参与客户', scopedSlots: { customRender: 'joinCustomers' }, width: '7%', align: 'center', ellipsis: true },
+        { title: '促销描述', dataIndex: 'content', width: '15%', align: 'center', customRender: function (text) { return text || '--' }, ellipsis: true },
+        { title: '活动状态', dataIndex: 'stateDictValue', width: '7%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '发布状态', scopedSlots: { customRender: 'releaseStatus' }, width: '7%', align: 'center', ellipsis: true },
+        { title: '操作', scopedSlots: { customRender: 'action' }, width: '10%', align: 'center' }
+      ],
+      // 加载数据方法 必须为 Promise 对象
+      loadData: parameter => {
+        this.disabled = true
+        this.spinning = true
+        return dealerPromotionList(Object.assign(parameter, this.queryParam)).then(res => {
+          let data
+          if (res.status == 200) {
+            data = res.data
+            const no = (data.pageNo - 1) * data.pageSize
+            for (var i = 0; i < data.list.length; i++) {
+              data.list[i].no = no + i + 1
+            }
+            this.disabled = false
+          }
+          this.spinning = false
+          return data
+        })
+      },
+      itemSn: null, // 经销商促销活动SN
+      openAuditModal: false // 审核弹窗
+    }
+  },
+  methods: {
+    //  详情
+    handleDetail (row) {
+      this.$router.push({ name: 'dealerPromotionManagementDetail', query: { sn: row.promotionSn } })
+    },
+    // 创建时间
+    dateChange (date) {
+      this.queryParam.beginDate = date[0]
+      this.queryParam.endDate = date[1]
+    },
+    //  新增
+    handleAdd () {
+      this.itemSn = null
+      this.openModal = true
+    },
+    // 参与客户
+    handleCustomers (row) {
+      this.openCustomerModal = true
+      this.$nextTick(() => {
+        this.$refs.lookUpCustomers.pageInit({ dealerSnList: row.dealerSnList })
+      })
+    },
+    //  基本信息  保存
+    handleOk () {
+      this.itemSn = null
+      this.resetSearchForm()
+    },
+    //  编辑
+    handleEdit (row) {
+      this.openModal = true
+      this.itemSn = row.promotionSn
+    },
+    // 发布状态
+    changeStatus (record) {
+      const params = {
+        promotionSn: record.promotionSn,
+        enabledFlag: record.enabledFlag == 1 ? '0' : '1'
+      }
+      this.spinning = true
+      modifyEnabledFlag(params).then(res => {
+        if (res.status == 200) {
+          this.$message.success(res.message)
+          this.$refs.table.refresh()
+          this.spinning = false
+        } else {
+          this.$refs.table.refresh()
+          this.spinning = false
+        }
+      })
+    },
+    // 规则设置
+    handleSetRules (row) {
+      this.$router.push({ name: 'dealerPromotionManagementRule', query: { type: 'rule', sn: row.promotionSn } })
+    },
+    // 审核
+    handleCheck (row) {
+      const _this = this
+      _this.itemSn = row.promotionSn
+      _this.openAuditModal = true
+    },
+    handleAuditModal () {
+      this.handleAudit({ promotionSn: this.itemSn, auditFlag: 1 })
+    },
+    closeAuditModal () {
+      this.handleAudit({ promotionSn: this.itemSn, auditFlag: 0 })
+    },
+    handleAudit (ajaxData) {
+      const _this = this
+      _this.spinning = true
+      promotionAudit(ajaxData).then(res => {
+        if (res.status == 200) {
+          _this.$message.success(res.message)
+          _this.$refs.table.refresh()
+        }
+        _this.itemSn = null
+        _this.openAuditModal = false
+        _this.spinning = false
+      })
+    },
+    // 促销时间变更
+    handleTime (row) {
+      this.editEndModal = true
+      const showData = {
+        sn: row.promotionSn,
+        name: row.title,
+        timeStart: row.promotionDateStart,
+        timeEnd: row.promotionDateEnd
+      }
+      this.$refs.editTime.setData(showData)
+    },
+    // 终止
+    handleEnd (row) {
+      const _this = this
+      this.$confirm({
+        title: '提示',
+        content: '确定要终止该促销?',
+        centered: true,
+        onOk () {
+          _this.spinning = true
+          promotionIsOver({ sn: row.promotionSn }).then(res => {
+            if (res.status == 200) {
+              _this.$message.success(res.message)
+              _this.$refs.table.refresh()
+              _this.spinning = false
+            } else {
+              _this.spinning = false
+            }
+          })
+        }
+      })
+    },
+    // 关闭采购退货详情弹框
+    closeDetailModal () {
+      this.itemSn = null
+      this.openDetailModal = false
+    },
+    //  删除
+    handleDel (row) {
+      const _this = this
+      this.$confirm({
+        title: '提示',
+        content: '确认要删除该活动吗?',
+        centered: true,
+        onOk () {
+          _this.spinning = true
+          dealerPromotionDel({ sn: row.promotionSn }).then(res => {
+            if (res.status == 200) {
+              _this.$message.success(res.message)
+              _this.$refs.table.refresh()
+              _this.spinning = false
+            } else {
+              _this.spinning = false
+            }
+          })
+        }
+      })
+    },
+    //  重置
+    resetSearchForm () {
+      this.queryParam = {
+        beginDate: undefined,
+        endDate: undefined,
+        queryWord: '',
+        enabledFlag: undefined, // 发布状态
+        state: undefined
+      }
+      this.$refs.rangeDate.resetDate()
+      this.$refs.table.refresh(true)
+    },
+    pageInit () {
+      const _this = this
+      this.$nextTick(() => { // 页面渲染完成后的回调
+        _this.setTableH()
+      })
+      this.openModal = false
+      this.openDetailModal = false
+      this.itemSn = null
+      this.rowSelectionInfo = null
+      this.$refs.table.clearTable()
+    },
+    setTableH () {
+      const tableSearchH = this.$refs.tableSearch.offsetHeight
+      this.tableHeight = window.innerHeight - tableSearchH - 240
+    }
+  },
+  watch: {
+    '$store.state.app.winHeight' (newValue, oldValue) { //  窗口变更时,需同时更改表格高度
+      this.setTableH()
+    }
+  },
+  mounted () {
+    if (!this.$store.state.app.isNewTab) { // 页签刷新时调用
+      this.pageInit()
+      this.resetSearchForm()
+    }
+  },
+  activated () {
+    // 如果是新页签打开,则重置当前页面
+    if (this.$store.state.app.isNewTab) {
+      this.pageInit()
+      this.resetSearchForm()
+    }
+    // 仅刷新列表,不重置页面
+    if (this.$store.state.app.updateList) {
+      this.pageInit()
+      this.$refs.table.refresh()
+    }
+  },
+  beforeRouteEnter (to, from, next) {
+    next(vm => {})
+  }
+}
+</script>
+<style lang="less" scoped>
+  .promotionList-wrap{
+    .nameBox{
+     padding:0 5px;
+    }
+  }
+</style>

+ 607 - 0
src/views/promotionRulesManagement/dealerPromotions/sendAmountModal.vue

@@ -0,0 +1,607 @@
+<template>
+  <a-modal
+    centered
+    class="promotionList-basicInfo-modal"
+    :footer="null"
+    :maskClosable="false"
+    title="规则设置"
+    v-model="isShow"
+    @cancel="isShow=false"
+    width="70%">
+    <a-spin :spinning="spinning" tip="Loading...">
+      <a-form-model
+        id="promotionList-basicInfo-form"
+        ref="ruleForm"
+        :model="form"
+        :rules="rules"
+        :label-col="formItemLayout.labelCol"
+        :wrapper-col="formItemLayout.wrapperCol" >
+        <a-form-model-item label="规则简称" prop="description">
+          <a-input
+            size="small"
+            id="promotionList-description"
+            v-model.trim="form.description"
+            allowClear
+            placeholder="请输入规则简称(最多20个字符)"
+            :maxLength="20"></a-input>
+        </a-form-model-item>
+        <a-form-model-item label="规则门槛" prop="gateFlag">
+          <a-radio-group v-model="form.gateFlag" button-style="solid" size="small" @change="changeGateFlag">
+            <a-radio-button value="1">
+              有
+            </a-radio-button>
+            <a-radio-button value="0">
+              无
+            </a-radio-button>
+          </a-radio-group>
+          <div v-if="form.gateFlag && form.gateFlag === '1'">
+            <v-select
+              size="small"
+              style="width:60%;"
+              v-model="form.gateType"
+              id="promotionList-gateType"
+              code="PROMOTION_GATE_TYPE"
+              placeholder="请选择"
+              @change="changeGateTypeFlag"
+              allowClear></v-select>
+            <div v-if="form.gateType==='RATIO_AMOUNT'">
+              购买门槛产品金额 <a-input-number v-model="form.gateAmount" :min="0" :max="999999" :precision="2" size="small"/> %作为配额
+              <a-tooltip title="如:填写100%,则购买10000元门槛产品,可享受10000配额购买正价产品,根据门槛金额动态调整配额">
+                <a-icon type="question-circle" theme="filled" :style="{ fontSize: '14px', color: 'gray' }"/>
+              </a-tooltip>
+            </div>
+            <div v-if="form.gateType==='MIN_AMOUNT'">
+              购买门槛产品满最低金额 <a-input-number v-model="form.gateAmount" :max="999999" :min="0" :precision="2" size="small"/>元,不限制配额。
+            </div>
+            <div class="ruleDescList" v-if="form.gateType==='FIXED_AMOUNT'">
+              购买满
+              <a-input-number v-model="form.gateAmount" :min="0" :max="999999" :precision="2" size="small"/>
+              元门槛产品,可使用
+              <a-input-number v-model="form.quotaAmount" :min="0" :max="999999" :precision="2" size="small"/>
+              元配额,采购规则中的正价商品(配额算销售额)
+            </div>
+          </div>
+        </a-form-model-item>
+        <a-form-model-item label="满赠规则" prop="regularAmount">
+          <div class="ruleDescList">
+            <!-- <a-select default-value="1" v-model="form.regularSameFlag" style="width: 100px" size="small">
+              <a-select-option value="1">
+                同款
+              </a-select-option>
+              <a-select-option value="0">
+                不同款
+              </a-select-option>
+            </a-select> -->
+            购买满
+            <a-input-number
+              v-model="form.regularAmount"
+              @blur="calculatePrice"
+              :max="999999"
+              :step="1"
+              :precision="2"
+              :min="0"
+              size="small"/>
+            元正价产品,送
+            <a-input-number
+              v-model="form.giveAmount"
+              @blur="calculatePrice"
+              :min="0"
+              :step="1"
+              :max="999999"
+              :precision="2"
+              size="small"/>
+            元({{ scaleNum }}%促销品采购额)
+          </div>
+        </a-form-model-item>
+        <a-form-model-item label="金额叠加" prop="accrualFlag">
+          <a-radio-group v-model="form.accrualFlag" button-style="solid" size="small">
+            <a-radio-button value="1">
+              是
+            </a-radio-button>
+            <a-radio-button value="0">
+              否
+            </a-radio-button>
+          </a-radio-group>
+          <span style="color:gray;">(如:满1000送200,金额叠加则:满2000送400,以此类推)</span>
+        </a-form-model-item>
+        <a-form-model-item prop="minOrderFlag" label="订单起订金额">
+          <a-select default-value="1" v-model="form.minOrderFlag" style="width: 160px" size="small">
+            <a-select-option value="0">
+              不限
+            </a-select-option>
+            <a-select-option value="1">
+              限制
+            </a-select-option>
+          </a-select>
+          <a-input-number
+            v-show="form.minOrderFlag && form.minOrderFlag=='1'"
+            size="small"
+            style="margin-left:10px;width:300px;"
+            v-model="form.minOrderAmount"
+            :min="0"
+            :step="1"
+            :max="999999"
+            :precision="2"
+            placeholder="请输入金额"/>
+        </a-form-model-item>
+        <a-form-model-item prop="upperLimitFlag" label="活动经费上限">
+          <a-select default-value="1" v-model="form.upperLimitFlag" style="width: 160px" size="small">
+            <a-select-option value="0">
+              不限
+            </a-select-option>
+            <a-select-option value="1">
+              限制
+            </a-select-option>
+          </a-select>
+          <a-input-number
+            v-show="form.upperLimitFlag&&form.upperLimitFlag=='1'"
+            size="small"
+            style="margin-left:10px;width:300px;"
+            v-model="form.upperLimitAmount"
+            :min="0"
+            :step="1"
+            :max="999999"
+            :precision="2"
+            placeholder="请输入金额"/>
+        </a-form-model-item>
+        <a-form-model-item label="采购额适用范围" prop="scopeFlag">
+          <a-radio-group v-model="form.scopeFlag" button-style="solid" size="small">
+            <a-radio-button value="0">
+              部分产品
+            </a-radio-button>
+            <a-radio-button value="1">
+              全部产品
+            </a-radio-button>
+          </a-radio-group>
+        </a-form-model-item>
+      </a-form-model>
+      <a-card size="small" :bordered="false" class="pages-wrap">
+        <div class="flex">
+          <a-radio-group v-model="chooseVal" button-style="solid" size="small">
+            <a-radio-button value="a" v-show="form.gateFlag==='1'">
+              门槛产品
+            </a-radio-button>
+            <a-radio-button value="b">
+              正价产品
+            </a-radio-button>
+            <a-radio-button value="c" v-show="form.scopeFlag==='0'">
+              促销产品
+            </a-radio-button>
+          </a-radio-group>
+          <a-button
+            size="small"
+            type="link"
+            class="button-info"
+            @click="openGuideModal=true"
+            id="promotionList-edit-btn">+导入产品</a-button>
+        </div>
+        <div v-show="chooseVal=='a'"><tableType1 ref="cillProduct"></tableType1></div>
+        <div v-show="chooseVal=='b'"><tableType1 ref="normalPriceProduct"></tableType1></div>
+        <div v-show="chooseVal=='c'"><tableType2 ref="offerProduct"></tableType2></div>
+      </a-card>
+      <div class="btn-cont">
+        <a-button id="promotionList-basicInfo-modal-back" @click="isShow = false">取消</a-button>
+        <a-button style="margin-left: 15px;" type="primary" id="promotionList-modal-save" @click="handleSave">确定</a-button>
+      </div>
+    </a-spin>
+    <!-- 导入产品 -->
+    <importGuideModal goodFlag="1" :openModal="openGuideModal" @close="closeGuideModel" @ok="hanldeOk" />
+  </a-modal>
+</template>
+
+<script>
+import { commonMixin } from '@/utils/mixin'
+import { VSelect } from '@/components'
+import tableType1 from './tableType1.vue'
+import tableType2 from './tableType2.vue'
+import { promotionSave, getRuleDetail } from '@/api/promotion'
+import ImportGuideModal from './importGuideModal.vue'
+export default {
+  name: 'PromotionListBasicInfoModal',
+  mixins: [commonMixin],
+  components: { VSelect, tableType1, tableType2, ImportGuideModal },
+  props: {
+    openModal: { //  弹框显示状态
+      type: Boolean,
+      default: false
+    },
+    promotionSn: {
+      type: [Number, String],
+      default: ''
+    },
+    itemSn: {
+      type: [Number, String],
+      default: ''
+    }
+  },
+  data () {
+    return {
+      isShow: this.openModal, //  是否打开弹框
+      spinning: false,
+      formItemLayout: {
+        labelCol: { span: 4 },
+        wrapperCol: { span: 17 }
+      },
+      form: {
+        promotionRuleType: 'BUY_PROD_GIVE_MONEY', // 买产品送采购额
+        description: '',
+        gateFlag: '0', // 门槛
+        gateType: undefined,
+        gateAmount: undefined,
+        quotaAmount: undefined,
+        regularSameFlag: '0', // 满赠规则  不同款商品
+        regularAmount: undefined,
+        giveAmount: undefined,
+        restrictCategory: '',
+        accrualFlag: '1', // 数量叠加
+        minOrderFlag: '0', // 起订金额
+        minOrderAmount: undefined,
+        upperLimitFlag: '0', // 活动经费上限
+        upperLimitAmount: undefined,
+        scopeFlag: '1'
+      },
+      rules: {
+        description: [ { required: true, message: '请输入规则简称', trigger: 'blur' } ],
+        gateFlag: [ { required: true, message: '请选择规则门槛', trigger: 'change' } ],
+        regularAmount: [{ required: true, message: '请输入满赠规则', trigger: 'blur' }],
+        accrualFlag: [{ required: true, message: '请选择数量是否叠加', trigger: 'change' }],
+        minOrderFlag: [{ required: true, message: '请选择订单起订金额', trigger: 'change' }],
+        upperLimitFlag: [{ required: true, message: '请选择活动经费上限', trigger: 'change' }],
+        scopeFlag: [{ required: true, message: '请选择采购额适用范围', trigger: 'change' }]
+      },
+      chooseVal: 'a',
+      scaleNum: 0,
+      openGuideModal: false
+    }
+  },
+  methods: {
+    // 导入
+    closeGuideModel () {
+      this.openGuideModal = false
+    },
+    hanldeOk (arr) {
+      const resultArr = []
+      arr.forEach(item => {
+        const obj = {
+          productCode: item.productCode,
+          productSn: item.product.productSn
+        }
+        resultArr.push(obj)
+      })
+      const name = this.chooseVal == 'a' ? 'cill' : this.chooseVal == 'b' ? 'normalPrice' : 'offer'
+      this.$refs[name + 'Product'].importRow(resultArr)
+    },
+    // 计算百分比
+    calculatePrice () {
+      const _this = this
+      if (_this.form.regularAmount && _this.form.giveAmount) {
+        _this.scaleNum = ((_this.form.giveAmount / _this.form.regularAmount) * 100).toFixed(2)
+      } else {
+        _this.scaleNum = 0
+      }
+    },
+    // 门槛切换  tab 按钮默认显示问题
+    changeGateFlag (e) {
+      if (this.chooseVal != 'c') {
+        if (e.target.value == '0') {
+          this.chooseVal = 'b'
+          this.form.gateType = undefined
+          this.form.gateAmount = undefined
+          this.form.quotaAmount = undefined
+        } else {
+          this.chooseVal = 'a'
+        }
+      }
+    },
+    changeGateTypeFlag (val) {
+      this.form.gateType = val
+      this.form.gateAmount = undefined
+      this.form.quotaAmount = undefined
+    },
+    //  保存
+    handleSave () {
+      const _this = this
+      this.$refs.ruleForm.validate(valid => {
+        if (valid) {
+          // 验证必填
+          if (_this.form.gateFlag == '1') {
+            if (!_this.form.gateType) {
+              _this.$message.warning('请选择规则门槛设置类型!')
+              return
+            }
+            if (!_this.form.gateAmount) {
+              _this.$message.warning('规则门槛条件不能为空!')
+              return
+            }
+            if (_this.form.gateType === 'FIXED_AMOUNT' && !_this.form.quotaAmount) {
+              _this.$message.warning('规则门槛条件不能为空!')
+              return
+            }
+          }
+          if (!_this.form.regularAmount || !_this.form.giveAmount) {
+            _this.$message.warning('满赠规则条件不能为空!')
+            return
+          }
+          if (_this.form.gateType === 'FIXED_AMOUNT' && _this.form.regularAmount) {
+            if (_this.form.quotaAmount * 1 < _this.form.regularAmount * 1) {
+              _this.$message.warning('可使用配额必须大于购买正价产品金额!')
+              return
+            }
+          }
+
+          if (_this.form.minOrderFlag == 1 && !_this.form.minOrderAmount) {
+            _this.$message.warning('请输入订单起订限制金额数!')
+            return
+          }
+          if (_this.form.minOrderFlag == 0) {
+            _this.form.minOrderAmount = undefined
+          }
+          if (_this.form.upperLimitFlag == 1 && !_this.form.upperLimitAmount) {
+            _this.$message.warning('请输入活动经费上限金额!')
+            return
+          }
+          if (_this.form.upperLimitFlag == 0) {
+            _this.form.upperLimitAmount = undefined
+          }
+          const form = JSON.parse(JSON.stringify(_this.form))
+          let rowFlag1, rowFlag2, rowFlag3
+          if (form.gateFlag == '1') {
+            form.gateProductList = this.$refs.cillProduct.getResultVal()
+            form.gateAmount = form.gateType === 'RATIO_AMOUNT' ? form.gateAmount / 100 : form.gateAmount
+            if (form.gateProductList.length == 0) {
+              _this.$message.warning('请添加门槛产品!')
+              return
+            } else {
+              const qtyFlag = form.gateProductList.some(newCon => { return (!newCon.unitType || !newCon.unitQty) })
+              if (qtyFlag) {
+                _this.$message.warning('订单起订量设置不能为空!')
+                return
+              }
+              rowFlag1 = _this.isJudge(form.gateProductList)
+            }
+          } else {
+            form.gateProductList = []
+            form.gateAmount = ''
+            form.quotaAmount = ''
+            form.gateType = undefined
+          }
+
+          form.regularProductList = this.$refs.normalPriceProduct.getResultVal()
+          // 判断表格必填
+          if (form.regularProductList.length == 0) {
+            _this.$message.warning('请添加正价产品!')
+            return
+          } else {
+            const qtyFlag = form.regularProductList.some(newCon => { return (!newCon.unitType || !newCon.unitQty) })
+            if (qtyFlag) {
+              _this.$message.warning('订单起订量设置不能为空!')
+              return
+            }
+            rowFlag3 = _this.isJudge(form.regularProductList)
+          }
+
+          if (form.scopeFlag == '0') {
+            form.giftProductList = this.$refs.offerProduct.getResultVal()
+            if (form.giftProductList.length == 0) {
+              _this.$message.warning('请添加促销产品!')
+              return
+            }
+            rowFlag2 = _this.isJudge(form.giftProductList)
+          } else {
+            form.giftProductList = []
+          }
+
+          if (rowFlag1 || rowFlag2 || rowFlag3) {
+            _this.$message.warning('请选择产品分类、品牌或产品!')
+            return
+          }
+          form.promotionSn = _this.promotionSn
+          _this.spinning = true
+          promotionSave(form).then(res => {
+            if (res.status == 200) {
+              _this.$message.success(res.message)
+              setTimeout(() => {
+                _this.isShow = false
+                _this.$emit('ok')
+                _this.spinning = false
+              }, 1000)
+            } else {
+              _this.spinning = false
+            }
+          })
+        } else {
+          return false
+        }
+      })
+    },
+    // 判断品牌,分类,产品其中一个必填
+    isJudge (list) {
+      let flag = null
+      list.forEach(con => {
+        if (con.productThisList) {
+          if (con.productThisList.length > 0) {
+            flag = false
+          } else {
+            if ((con.productTypeList && con.productTypeList.length > 0) || (con.productBrandList && con.productBrandList.length > 0)) {
+              flag = false
+            } else {
+              flag = true
+            }
+          }
+        } else {
+          if ((con.productTypeList && con.productTypeList.length > 0) || (con.productBrandList && con.productBrandList.length > 0)) {
+            flag = false
+          } else {
+            flag = true
+          }
+        }
+      })
+      return flag
+    },
+    // 重置表格
+    resetSearchForm () {
+      this.form = {
+        promotionRuleType: 'BUY_PROD_GIVE_MONEY', // 买产品送采购额
+        description: '',
+        gateFlag: '0', // 门槛
+        gateType: undefined,
+        gateAmount: undefined,
+        quotaAmount: undefined,
+        regularSameFlag: '0', // 满赠规则  不同款商品
+        regularAmount: undefined,
+        giveAmount: undefined,
+        restrictCategory: '',
+        accrualFlag: '1', // 数量叠加
+        minOrderFlag: '1', // 起订金额
+        minOrderAmount: undefined,
+        upperLimitFlag: '1', // 活动经费上限
+        upperLimitAmount: undefined,
+        scopeFlag: undefined,
+        gateProductList: undefined,
+        giftProductList: undefined,
+        regularProductList: undefined
+      }
+      this.$nextTick(() => {
+        this.$refs.ruleForm.resetFields()
+        this.$refs.cillProduct.reSetTableData()
+        this.$refs.normalPriceProduct.reSetTableData()
+        this.$refs.offerProduct.reSetTableData()
+        this.scaleNum = 0
+      })
+    },
+    // 获取编辑详情
+    getDetail () {
+      const _this = this
+      getRuleDetail({ sn: this.itemSn }).then(res => {
+        if (res.status == 200) {
+          this.chooseVal = res.data.gateFlag == '0' ? 'b' : 'a'
+          const resultObj = res.data
+          if (resultObj.gateFlag === '1') {
+            resultObj.gateAmount = resultObj.gateType === 'RATIO_AMOUNT' ? resultObj.gateAmount * 100 : resultObj.gateAmount
+          }
+          // 重新组成保存数据
+          if (resultObj.gateProductList && resultObj.gateProductList.length > 0) {
+            resultObj.gateProductList = _this.newData(resultObj.gateProductList)
+            this.$refs.cillProduct.setTabVal(resultObj.gateProductList)
+          }
+          if (resultObj.regularProductList && resultObj.regularProductList.length > 0) {
+            resultObj.regularProductList = _this.newData(resultObj.regularProductList)
+            this.$refs.normalPriceProduct.setTabVal(resultObj.regularProductList)
+          }
+          if (resultObj.giftProductList && resultObj.giftProductList.length > 0) {
+            resultObj.giftProductList = _this.newData(resultObj.giftProductList)
+            this.$refs.offerProduct.setTabVal(resultObj.giftProductList)
+          }
+          this.form = { ...this.form, ...resultObj }
+        }
+      })
+    },
+    newData (list) {
+      list.forEach(con => {
+        // 品牌
+        if (con.productBrandList) {
+          const brandList = []
+          con.productBrandList.forEach(item => {
+            item.brandName = item.productBrandName
+            const brandObj = {
+              productBrandSn: item.productBrandSn
+            }
+            brandList.push(brandObj)
+          })
+          con.productBrandArr = con.productBrandList
+          con.productBrandList = brandList
+        }
+        // 分类
+        if (con.productTypeList) {
+          const typeList = []
+          con.productTypeList.forEach(item => {
+            const typeObj = {}
+            item.title = ''
+            const num = 3
+            for (var i = 0; i < num; i++) {
+              if (item['productTypeName' + (i + 1)]) {
+                // item.title += item['productTypeName' + (i + 1)] + (item['productTypeName' + (i + 1)] ? '/' : '')
+                typeObj['productTypeSn' + (i + 1)] = item['productTypeSn' + (i + 1)] ? item['productTypeSn' + (i + 1)] : ''
+              }
+            }
+            // item.title = item.title.slice(0, item.title.length - 1)
+            if (item.productTypeName3) {
+              item.title = item.productTypeName2 + '/' + item.productTypeName3
+            } else if (!item.productTypeName3 && item.productTypeName2) {
+              item.title = item.productTypeName2
+            } else {
+              item.title = item.productTypeName1
+            }
+            item.id = item.productTypeSn3 ? item.productTypeSn3 : item.productTypeSn2 ? item.productTypeSn2 : item.productTypeSn1
+            typeList.push(typeObj)
+          })
+          con.productTypeArr = con.productTypeList
+          con.productTypeList = typeList
+        }
+        // 产品
+        if (con.productThisList) {
+          const productList = []
+          con.productThisList.forEach(item => {
+            const productObj = {
+              productCode: item.productCode,
+              productSn: item.productSn
+            }
+            productList.push(productObj)
+          })
+          con.productThisList = productList
+        }
+      })
+      return list
+    }
+  },
+  watch: {
+    //  父页面传过来的弹框状态
+    openModal (newValue, oldValue) {
+      this.isShow = newValue
+    },
+    //  重定义的弹框状态
+    isShow (newValue, oldValue) {
+      if (!newValue) {
+        this.$emit('close')
+        this.resetSearchForm()
+      } else {
+        if (this.itemSn) {
+          this.getDetail()
+        } else {
+          this.chooseVal = this.form.gateFlag == '0' ? 'b' : 'a'
+        }
+      }
+    }
+  }
+}
+</script>
+
+<style lang="less" scoped>
+  .promotionList-basicInfo-modal{
+    /deep/.ant-modal-body {
+      padding: 40px 40px 24px;
+      max-height: 745px !important;
+      overflow-y: scroll !important;
+    }
+    .ant-radio-button-wrapper{
+      width:80px;
+      text-align: center;
+    }
+    .ant-form-item{
+      margin-bottom:5px;
+    }
+    .buyerBox{
+      border:1px solid #d9d9d9;margin-top:10px;border-radius:4px;padding:4px 10px;background:#f2f2f2;max-height:130px;overflow-y:scroll;
+    }
+    .btn-cont {
+      text-align: center;
+      margin: 35px 0 10px;
+    }
+    .flex{
+      display:flex;
+      align-items:center;
+      justify-content:space-between;
+    }
+  }
+
+</style>

+ 637 - 0
src/views/promotionRulesManagement/dealerPromotions/sendProductsModal.vue

@@ -0,0 +1,637 @@
+<template>
+  <a-modal
+    centered
+    class="promotionList-basicInfo-modal"
+    :footer="null"
+    :maskClosable="false"
+    title="规则设置"
+    v-model="isShow"
+    @cancel="isShow=false"
+    width="70%">
+    <a-spin :spinning="spinning" tip="Loading...">
+      <a-form-model
+        id="promotionList-basicInfo-form"
+        ref="ruleForm"
+        :model="form"
+        :rules="rules"
+        :label-col="formItemLayout.labelCol"
+        :wrapper-col="formItemLayout.wrapperCol" >
+        <a-form-model-item label="规则简称" prop="description">
+          <a-input
+            size="small"
+            id="promotionList-description"
+            v-model.trim="form.description"
+            allowClear
+            placeholder="请输入规则简称(最多20个字符)"
+            :maxLength="20"></a-input>
+        </a-form-model-item>
+        <a-form-model-item label="规则门槛" prop="gateFlag">
+          <a-radio-group v-model="form.gateFlag" button-style="solid" size="small" @change="changeGateFlag">
+            <a-radio-button value="1">
+              有
+            </a-radio-button>
+            <a-radio-button value="0">
+              无
+            </a-radio-button>
+          </a-radio-group>
+          <div v-if="form.gateFlag && form.gateFlag === '1'">
+            <v-select
+              size="small"
+              style="width:60%;"
+              v-model="form.gateType"
+              id="promotionList-gateType"
+              code="PROMOTION_GATE_TYPE"
+              placeholder="请选择"
+              @change="changeGateTypeFlag"
+              allowClear></v-select>
+            <div v-if="form.gateType==='RATIO_AMOUNT'">
+              购买门槛产品金额 <a-input-number v-model="form.gateAmount" :min="0" :max="999999" :precision="2" size="small"/> %作为配额
+              <a-tooltip title="如:填写100%,则购买10000元门槛产品,可享受10000配额购买正价产品,根据门槛金额动态调整配额">
+                <a-icon type="question-circle" theme="filled" :style="{ fontSize: '14px', color: 'gray' }"/>
+              </a-tooltip>
+            </div>
+            <div v-if="form.gateType==='MIN_AMOUNT'">
+              购买门槛产品满最低金额 <a-input-number v-model="form.gateAmount" :min="0" :max="999999" :precision="2" size="small"/>元,不限制配额。
+            </div>
+            <div class="ruleDescList" v-if="form.gateType==='FIXED_AMOUNT'">
+              购买满
+              <a-input-number v-model="form.gateAmount" :min="0" :max="999999" :precision="2" size="small"/>
+              元门槛产品,可使用
+              <a-input-number v-model="form.quotaAmount" :min="0" :max="999999" :precision="2" size="small"/>
+              元配额,采购规则中的正价商品(配额算销售额)
+            </div>
+          </div>
+        </a-form-model-item>
+        <a-form-model-item label="满赠规则" prop="regularSameFlag">
+          <div class="ruleDescList">
+            <a-select default-value="1" v-model="form.regularSameFlag" style="width: 100px" size="small" @change="handleFullGift">
+              <a-select-option value="1">
+                同款
+              </a-select-option>
+              <a-select-option value="0">
+                不同款
+              </a-select-option>
+            </a-select>
+            产品购买满
+            <a-input-number
+              v-model="form.regularQty"
+              :min="0"
+              :step="1"
+              :max="999999"
+              :precision="0"
+              size="small"/>
+            个正价产品,送
+            <a-input-number
+              v-model="form.promotionQty"
+              :min="0"
+              :step="1"
+              :precision="0"
+              :max="999999"
+              size="small"/>
+            个促销产品
+          </div>
+          <div class="ruleDescList">
+            <a-checkbox :checked="form.restrictFlag === '1'" size="small" @change="onChange">
+              限制正价产品款数
+            </a-checkbox>
+            <a-input-number
+              v-if="form.restrictFlag==='1'"
+              v-model="form.restrictCategory"
+              :min="0"
+              :step="1"
+              :max="999999"
+              :precision="0"
+              size="small"/>
+          </div>
+        </a-form-model-item>
+        <a-form-model-item label="数量叠加" prop="accrualFlag">
+          <a-radio-group v-model="form.accrualFlag" button-style="solid" size="small">
+            <a-radio-button value="1">
+              是
+            </a-radio-button>
+            <a-radio-button value="0">
+              否
+            </a-radio-button>
+          </a-radio-group>
+          <span style="color:gray;">(如:满10送2,数量叠加则:满20送4,满30送6)</span>
+        </a-form-model-item>
+        <a-form-model-item prop="minOrderFlag">
+          <span slot="label">
+            <!-- <a-tooltip title="What do you want others to call you?">
+              <a-icon type="info-circle" />
+            </a-tooltip> -->
+            订单起订金额
+          </span>
+          <a-select v-model="form.minOrderFlag" style="width: 160px" size="small">
+            <a-select-option value="0">
+              不限
+            </a-select-option>
+            <a-select-option value="1">
+              限制
+            </a-select-option>
+          </a-select>
+          <a-input-number
+            v-show="form.minOrderFlag && form.minOrderFlag=='1'"
+            size="small"
+            style="margin-left:10px;width:300px;"
+            v-model="form.minOrderAmount"
+            :min="0"
+            :max="999999"
+            :step="1"
+            :precision="2"
+            placeholder="请输入金额"/>
+        </a-form-model-item>
+        <a-form-model-item prop="upperLimitFlag">
+          <span slot="label">
+            <!-- <a-tooltip title="What do you want others to call you?">
+              <a-icon type="info-circle" />
+            </a-tooltip> -->
+            活动经费上限
+          </span>
+          <a-select v-model="form.upperLimitFlag" style="width: 160px" size="small">
+            <a-select-option value="0">
+              不限
+            </a-select-option>
+            <a-select-option value="1">
+              限制
+            </a-select-option>
+          </a-select>
+          <a-input-number
+            v-show="form.upperLimitFlag&&form.upperLimitFlag=='1'"
+            size="small"
+            style="margin-left:10px;width:300px;"
+            v-model="form.upperLimitAmount"
+            :min="0"
+            :step="1"
+            :max="999999"
+            :precision="2"
+            placeholder="请输入金额"/>
+        </a-form-model-item>
+        <a-form-model-item label="促销品与正品一致" prop="regularPromotionSameFlag">
+          <a-radio-group v-model="form.regularPromotionSameFlag" button-style="solid" size="small" :disabled="form.regularSameFlag==0">
+            <a-radio-button value="1">
+              是
+            </a-radio-button>
+            <a-radio-button value="0">
+              否
+            </a-radio-button>
+          </a-radio-group>
+        </a-form-model-item>
+      </a-form-model>
+      <a-card size="small" :bordered="false" class="pages-wrap">
+        <div class="flex">
+          <a-radio-group v-model="chooseVal" button-style="solid" size="small">
+            <a-radio-button value="a" v-show="form.gateFlag==='1'">
+              门槛产品
+            </a-radio-button>
+            <a-radio-button value="b">
+              正价产品
+            </a-radio-button>
+            <a-radio-button value="c" v-show="form.regularPromotionSameFlag==='0'">
+              促销产品
+            </a-radio-button>
+          </a-radio-group>
+          <a-button
+            size="small"
+            type="link"
+            class="button-info"
+            @click="openGuideModal=true"
+            id="promotionList-edit-btn">+导入产品</a-button>
+        </div>
+        <div v-show="chooseVal=='a'"><tableType1 ref="cillProduct"></tableType1></div>
+        <div v-show="chooseVal=='b'"><tableType1 ref="normalPriceProduct"></tableType1></div>
+        <div v-show="chooseVal=='c'"><tableType2 ref="offerProduct"></tableType2></div>
+      </a-card>
+      <div class="btn-cont">
+        <a-button id="promotionList-basicInfo-modal-back" @click="isShow = false">取消</a-button>
+        <a-button style="margin-left: 15px;" type="primary" id="promotionList-modal-save" @click="handleSave">确定</a-button>
+      </div>
+    </a-spin>
+    <!-- 导入产品 -->
+    <importGuideModal goodFlag="1" :openModal="openGuideModal" @close="closeGuideModel" @ok="hanldeOk" />
+  </a-modal>
+</template>
+
+<script>
+import { commonMixin } from '@/utils/mixin'
+import { VSelect } from '@/components'
+import tableType1 from './tableType1.vue'
+import tableType2 from './tableType2.vue'
+import { promotionSave, getRuleDetail } from '@/api/promotion'
+import ImportGuideModal from './importGuideModal.vue'
+export default {
+  name: 'PromotionListBasicInfoModal',
+  mixins: [commonMixin],
+  components: { VSelect, tableType1, tableType2, ImportGuideModal },
+  props: {
+    openModal: { //  弹框显示状态
+      type: Boolean,
+      default: false
+    },
+    promotionSn: {
+      type: [Number, String],
+      default: ''
+    },
+    itemSn: {
+      type: [Number, String],
+      default: ''
+    }
+  },
+  data () {
+    return {
+      isShow: this.openModal, //  是否打开弹框
+      spinning: false,
+      formItemLayout: {
+        labelCol: { span: 4 },
+        wrapperCol: { span: 17 }
+      },
+      form: {
+        promotionRuleType: 'BUY_PROD_GIVE_PROD', // 买产品送产品
+        description: '', // 简称
+        gateFlag: '0', // 门槛
+        gateType: undefined,
+        gateAmount: undefined,
+        quotaAmount: undefined,
+        regularSameFlag: '1', // 满赠规则  不同款商品
+        regularQty: undefined,
+        promotionQty: undefined,
+        restrictFlag: '0', // 限制正价产品款数
+        restrictCategory: '',
+        accrualFlag: '1', // 数量叠加
+        minOrderFlag: '0', // 起订金额
+        minOrderAmount: undefined,
+        upperLimitFlag: '0', // 活动经费上限
+        upperLimitAmount: undefined,
+        regularPromotionSameFlag: '1'
+      },
+      rules: {
+        description: [ { required: true, message: '请输入规则简称', trigger: 'blur' } ],
+        gateFlag: [ { required: true, message: '请选择规则门槛', trigger: 'change' } ],
+        regularSameFlag: [{ required: true, message: '请选择满赠规则', trigger: 'change' }],
+        accrualFlag: [{ required: true, message: '请选择数量是否叠加', trigger: 'change' }],
+        minOrderFlag: [{ required: true, message: '请选择订单起订金额', trigger: 'change' }],
+        upperLimitFlag: [{ required: true, message: '请选择活动经费上限', trigger: 'change' }],
+        regularPromotionSameFlag: [{ required: true, message: '请选择促销品与正品是否一致', trigger: 'change' }]
+      },
+      chooseVal: 'a',
+      openGuideModal: false// 导入弹窗
+    }
+  },
+  methods: {
+    // 满赠  同款    促销品与正品一致  默认是 可修改
+    //     不同款                   默认否 不可修改
+    handleFullGift (e) {
+      if (e === '0') {
+        this.form.regularPromotionSameFlag = '0'
+      } else {
+        this.form.regularPromotionSameFlag = '1'
+      }
+    },
+    // 导入
+    closeGuideModel () {
+      this.openGuideModal = false
+    },
+    hanldeOk (arr) {
+      const resultArr = []
+      arr.forEach(item => {
+        const obj = {
+          productCode: item.productCode,
+          productSn: item.product.productSn
+        }
+        resultArr.push(obj)
+      })
+      const name = this.chooseVal == 'a' ? 'cill' : this.chooseVal == 'b' ? 'normalPrice' : 'offer'
+      this.$refs[name + 'Product'].importRow(resultArr)
+    },
+    // 限制正价产品款数
+    onChange (e) {
+      this.form.restrictFlag = e.target.checked ? '1' : '0'
+    },
+    // 门槛切换  tab 按钮默认显示问题
+    changeGateFlag (e) {
+      if (this.chooseVal != 'c') {
+        if (e.target.value == '0') {
+          this.chooseVal = 'b'
+          this.form.gateType = undefined
+          this.form.gateAmount = undefined
+          this.form.quotaAmount = undefined
+        } else {
+          this.chooseVal = 'a'
+        }
+      }
+    },
+    changeGateTypeFlag (val) {
+      this.form.gateType = val
+      this.form.gateAmount = undefined
+      this.form.quotaAmount = undefined
+    },
+    //  保存
+    handleSave () {
+      const _this = this
+      this.$refs.ruleForm.validate(valid => {
+        if (valid) {
+          // 验证必填
+          if (_this.form.gateFlag == '1') {
+            if (!_this.form.gateType) {
+              _this.$message.warning('请选择规则门槛设置类型!')
+              return
+            }
+            if (!_this.form.gateAmount) {
+              _this.$message.warning('规则门槛条件不能为空!')
+              return
+            }
+            if (_this.form.gateType === 'FIXED_AMOUNT' && !_this.form.quotaAmount) {
+              _this.$message.warning('规则门槛条件不能为空!')
+              return
+            }
+          }
+          if (!_this.form.regularQty || !_this.form.promotionQty) {
+            _this.$message.warning('满赠规则条件不能为空!')
+            return
+          }
+          if (_this.form.restrictFlag === '1' && !_this.form.restrictCategory) {
+            _this.$message.warning('请输入限制正价产品款数个数!')
+            return
+          }
+
+          if (_this.form.minOrderFlag == 1 && !_this.form.minOrderAmount) {
+            _this.$message.warning('请输入订单起订限制金额数!')
+            return
+          }
+          if (_this.form.minOrderFlag == 0) {
+            _this.form.minOrderAmount = undefined
+          }
+
+          if (_this.form.upperLimitFlag == 1 && !_this.form.upperLimitAmount) {
+            _this.$message.warning('请输入活动经费上限金额!')
+            return
+          }
+          if (_this.form.upperLimitFlag == 0) {
+            _this.form.upperLimitAmount = undefined
+          }
+
+          const form = JSON.parse(JSON.stringify(_this.form))
+          let rowFlag1 = null
+          let rowFlag2 = null
+          let rowFlag3 = null
+          if (form.gateFlag == '1') {
+            form.gateProductList = this.$refs.cillProduct.getResultVal()
+            form.gateAmount = form.gateType === 'RATIO_AMOUNT' ? form.gateAmount / 100 : form.gateAmount
+            if (form.gateProductList.length == 0) {
+              _this.$message.warning('请添加门槛产品!')
+              return
+            } else {
+              const qtyFlag = form.gateProductList.some(newCon => { return (!newCon.unitType || !newCon.unitQty) })
+              if (qtyFlag) {
+                _this.$message.warning('订单起订量设置不能为空!')
+                return
+              }
+              rowFlag1 = _this.isJudge(form.gateProductList)
+            }
+          } else {
+            form.gateProductList = []
+            form.gateAmount = ''
+            form.quotaAmount = ''
+            form.gateType = undefined
+          }
+
+          form.regularProductList = this.$refs.normalPriceProduct.getResultVal()
+          // 判断表格必填
+          if (form.regularProductList.length == 0) {
+            _this.$message.warning('请添加正价产品!')
+            return
+          } else {
+            const qtyFlag = form.regularProductList.some(newCon => { return (!newCon.unitType || !newCon.unitQty) })
+            if (qtyFlag) {
+              _this.$message.warning('订单起订量设置不能为空!')
+              return
+            }
+            rowFlag3 = _this.isJudge(form.regularProductList)
+          }
+          if (form.regularPromotionSameFlag == '0') {
+            form.giftProductList = this.$refs.offerProduct.getResultVal()
+            if (form.giftProductList.length == 0) {
+              _this.$message.warning('请添加促销产品!')
+              return
+            }
+            rowFlag2 = _this.isJudge(form.giftProductList)
+          } else {
+            form.giftProductList = []
+          }
+
+          if (rowFlag1 || rowFlag2 || rowFlag3) {
+            _this.$message.warning('请选择产品分类、品牌或产品!')
+            return
+          }
+          form.promotionSn = _this.promotionSn
+          _this.spinning = true
+          promotionSave(form).then(res => {
+            if (res.status == 200) {
+              _this.$message.success(res.message)
+              setTimeout(() => {
+                _this.isShow = false
+                _this.$emit('ok')
+                _this.spinning = false
+              }, 1000)
+            } else {
+              _this.spinning = false
+            }
+          })
+        } else {
+          return false
+        }
+      })
+    },
+    // 判断品牌,分类,产品其中一个必填
+    isJudge (list) {
+      let flag = null
+      list.forEach(con => {
+        if (con.productThisList) {
+          if (con.productThisList.length > 0) {
+            flag = false
+          } else {
+            if ((con.productTypeList && con.productTypeList.length > 0) || (con.productBrandList && con.productBrandList.length > 0)) {
+              flag = false
+            } else {
+              flag = true
+            }
+          }
+        } else {
+          if ((con.productTypeList && con.productTypeList.length > 0) || (con.productBrandList && con.productBrandList.length > 0)) {
+            flag = false
+          } else {
+            flag = true
+          }
+        }
+      })
+      return flag
+    },
+    // 重置表格
+    resetSearchForm () {
+      this.form = {
+        promotionRuleType: 'BUY_PROD_GIVE_PROD', // 买产品送产品
+        description: '', // 简称
+        gateFlag: '0', // 门槛
+        gateType: undefined,
+        gateAmount: undefined,
+        quotaAmount: undefined,
+        regularSameFlag: '1', // 满赠规则  不同款商品
+        regularQty: undefined,
+        promotionQty: undefined,
+        restrictFlag: '0', // 限制正价产品款数
+        restrictCategory: '',
+        accrualFlag: '1', // 数量叠加
+        minOrderFlag: '0', // 起订金额
+        minOrderAmount: undefined,
+        upperLimitFlag: '0', // 活动经费上限
+        upperLimitAmount: undefined,
+        regularPromotionSameFlag: '1',
+        gateProductList: undefined,
+        giftProductList: undefined,
+        regularProductList: undefined
+      }
+      this.$nextTick(() => {
+        this.$refs.ruleForm.resetFields()
+        this.$refs.cillProduct.reSetTableData()
+        this.$refs.normalPriceProduct.reSetTableData()
+        this.$refs.offerProduct.reSetTableData()
+      })
+    },
+    // 获取编辑详情
+    getDetail () {
+      const _this = this
+      getRuleDetail({ sn: this.itemSn }).then(res => {
+        if (res.status == 200) {
+          const resultObj = res.data
+          _this.chooseVal = resultObj.gateFlag == '0' ? 'b' : 'a'
+          if (resultObj.gateFlag === '1') {
+            resultObj.gateAmount = resultObj.gateType === 'RATIO_AMOUNT' ? resultObj.gateAmount * 100 : resultObj.gateAmount
+          }
+          // 重新组成保存数据
+          if (resultObj.gateProductList && resultObj.gateProductList.length > 0) {
+            resultObj.gateProductList = _this.newData(resultObj.gateProductList)
+            this.$refs.cillProduct.setTabVal(resultObj.gateProductList)
+          }
+          if (resultObj.regularProductList && resultObj.regularProductList.length > 0) {
+            resultObj.regularProductList = _this.newData(resultObj.regularProductList)
+            this.$refs.normalPriceProduct.setTabVal(resultObj.regularProductList)
+          }
+          if (resultObj.giftProductList && resultObj.giftProductList.length > 0) {
+            resultObj.giftProductList = _this.newData(resultObj.giftProductList)
+            this.$refs.offerProduct.setTabVal(resultObj.giftProductList)
+          }
+          this.form = { ...this.form, ...resultObj }
+        }
+      })
+    },
+    newData (list) {
+      list.forEach(con => {
+        // 品牌
+        if (con.productBrandList) {
+          const brandList = []
+          con.productBrandList.forEach(item => {
+            item.brandName = item.productBrandName
+            const brandObj = {
+              productBrandSn: item.productBrandSn
+            }
+            brandList.push(brandObj)
+          })
+          con.productBrandArr = con.productBrandList
+          con.productBrandList = brandList
+        }
+        // 分类
+        if (con.productTypeList) {
+          const typeList = []
+          con.productTypeList.forEach(item => {
+            const typeObj = {}
+            const num = 3
+            for (var i = 0; i < num; i++) {
+              if (item['productTypeName' + (i + 1)]) {
+                // item.title += item['productTypeName' + (i + 1)] + (item['productTypeName' + (i + 1)] ? '/' : '')
+                typeObj['productTypeSn' + (i + 1)] = item['productTypeSn' + (i + 1)] ? item['productTypeSn' + (i + 1)] : ''
+              }
+            }
+            // item.title = item.title.slice(0, item.title.length - 1)
+            if (item.productTypeName3) {
+              item.title = item.productTypeName2 + '/' + item.productTypeName3
+            } else if (!item.productTypeName3 && item.productTypeName2) {
+              item.title = item.productTypeName2
+            } else {
+              item.title = item.productTypeName1
+            }
+            item.id = item.productTypeSn3 ? item.productTypeSn3 : item.productTypeSn2 ? item.productTypeSn2 : item.productTypeSn1
+            typeList.push(typeObj)
+          })
+          con.productTypeArr = con.productTypeList
+          con.productTypeList = typeList
+        }
+        // 产品
+        if (con.productThisList) {
+          const productList = []
+          con.productThisList.forEach(item => {
+            const productObj = {
+              productCode: item.productCode,
+              productSn: item.productSn
+            }
+            productList.push(productObj)
+          })
+          con.productThisList = productList
+        }
+      })
+      return list
+    }
+  },
+  watch: {
+    //  父页面传过来的弹框状态
+    openModal (newValue, oldValue) {
+      this.isShow = newValue
+    },
+    //  重定义的弹框状态
+    isShow (newValue, oldValue) {
+      if (!newValue) {
+        this.$emit('close')
+        this.resetSearchForm()
+      } else {
+        if (this.itemSn) {
+          this.getDetail()
+        } else {
+          this.chooseVal = this.form.gateFlag == '0' ? 'b' : 'a'
+        }
+      }
+    }
+  }
+}
+</script>
+
+<style lang="less" scoped>
+  .promotionList-basicInfo-modal{
+    /deep/.ant-modal-body {
+      padding: 40px 40px 24px;
+      max-height: 745px !important;
+      overflow-y: scroll !important;
+    }
+    .ant-radio-button-wrapper{
+      width:80px;
+      text-align: center;
+    }
+    .ant-form-item{
+      margin-bottom:5px;
+    }
+    .buyerBox{
+      border:1px solid #d9d9d9;margin-top:10px;border-radius:4px;padding:4px 10px;background:#f2f2f2;max-height:130px;overflow-y:scroll;
+    }
+    .btn-cont {
+      text-align: center;
+      margin: 35px 0 10px;
+    }
+    .flex{
+      display:flex;
+      align-items:center;
+      justify-content:space-between;
+    }
+    .ant-radio-button-wrapper-disabled.ant-radio-button-wrapper-checked{
+      background-color: #ed1c24 !important;
+    }
+  }
+
+</style>

+ 680 - 0
src/views/promotionRulesManagement/dealerPromotions/specialOfferModal.vue

@@ -0,0 +1,680 @@
+<template>
+  <a-modal
+    centered
+    class="promotionList-basicInfo-modal"
+    :footer="null"
+    :maskClosable="false"
+    title="规则设置"
+    v-model="isShow"
+    @cancel="isShow=false"
+    width="83%">
+    <a-spin :spinning="spinning" tip="Loading...">
+      <a-form-model
+        id="promotionList-basicInfo-form"
+        ref="ruleForm"
+        :model="form"
+        :rules="rules"
+        :label-col="formItemLayout.labelCol"
+        :wrapper-col="formItemLayout.wrapperCol" >
+        <a-form-model-item label="规则简称" prop="description">
+          <a-input
+            size="small"
+            id="promotionList-description"
+            v-model.trim="form.description"
+            allowClear
+            placeholder="请输入规则简称(最多20个字符)"
+            :maxLength="20"></a-input>
+        </a-form-model-item>
+        <a-form-model-item label="规则门槛" prop="gateFlag">
+          <a-radio-group v-model="form.gateFlag" button-style="solid" size="small" @change="handleChange">
+            <a-radio-button value="1">
+              有
+            </a-radio-button>
+            <a-radio-button value="0">
+              无
+            </a-radio-button>
+          </a-radio-group>
+          <div v-if="form.gateFlag && form.gateFlag === '1'">
+            <v-select
+              size="small"
+              style="width:60%;"
+              v-model="form.gateType"
+              id="promotionList-gateType"
+              code="PROMOTION_GATE_TYPE"
+              placeholder="请选择"
+              @change="changeGateTypeFlag"
+              allowClear></v-select>
+            <div v-if="form.gateType==='RATIO_AMOUNT'">
+              购买门槛产品金额 <a-input-number v-model="form.gateAmount" :min="0" :max="999999" :precision="2" size="small"/> %作为配额
+              <a-tooltip title="如:填写100%,则购买10000元门槛产品,可享受10000配额购买特价产品,根据门槛金额动态调整配额">
+                <a-icon type="question-circle" theme="filled" :style="{ fontSize: '14px', color: 'gray' }"/>
+              </a-tooltip>
+            </div>
+            <div v-if="form.gateType==='MIN_AMOUNT'">
+              购买门槛产品满最低金额 <a-input-number v-model="form.gateAmount" :min="0" :max="999999" :precision="2" size="small"/>元,不限制配额。
+            </div>
+            <div class="ruleDescList" v-if="form.gateType==='FIXED_AMOUNT'">
+              购买满
+              <a-input-number v-model="form.gateAmount" :max="999999" :min="0" :precision="2" size="small"/>
+              元门槛产品,可使用
+              <a-input-number v-model="form.quotaAmount" :max="999999" :min="0" :precision="2" size="small"/>
+              元配额,采购规则中的特价商品(配额算销售额)
+            </div>
+          </div>
+        </a-form-model-item>
+        <a-form-model-item prop="minOrderFlag" label="订单起订金额">
+          <a-select default-value="1" v-model="form.minOrderFlag" style="width: 160px" size="small">
+            <a-select-option value="0">
+              不限
+            </a-select-option>
+            <a-select-option value="1">
+              限制
+            </a-select-option>
+          </a-select>
+          <a-input-number
+            v-show="form.minOrderFlag && form.minOrderFlag=='1'"
+            size="small"
+            style="margin-left:10px;width:300px;"
+            v-model="form.minOrderAmount"
+            :min="0"
+            :step="1"
+            :max="999999"
+            :precision="2"
+            placeholder="请输入金额"/>
+        </a-form-model-item>
+        <a-form-model-item prop="upperLimitFlag" label="活动经费上限">
+          <a-select default-value="1" v-model="form.upperLimitFlag" style="width: 160px" size="small">
+            <a-select-option value="0">
+              不限
+            </a-select-option>
+            <a-select-option value="1">
+              限制
+            </a-select-option>
+          </a-select>
+          <a-input-number
+            v-show="form.upperLimitFlag&&form.upperLimitFlag=='1'"
+            size="small"
+            style="margin-left:10px;width:300px;"
+            v-model="form.upperLimitAmount"
+            :min="0"
+            :step="1"
+            :max="999999"
+            :precision="2"
+            placeholder="请输入金额"/>
+        </a-form-model-item>
+      </a-form-model>
+      <a-card size="small" :bordered="false" class="pages-wrap">
+        <div class="flex">
+          <a-radio-group v-model="chooseVal" button-style="solid" size="small">
+            <a-radio-button value="a" v-show="form.gateFlag==='1'">
+              门槛产品
+            </a-radio-button>
+            <a-radio-button value="d">
+              特价产品
+            </a-radio-button>
+          </a-radio-group>
+          <div>
+            <a-button
+              size="small"
+              type="link"
+              class="button-info"
+              id="promotionList-edit-btn"
+              @click="openGuideModal=true"
+            >+导入产品</a-button>
+            <a-button
+              v-show="chooseVal==='d'"
+              style="margin-left:10px;"
+              size="small"
+              type="link"
+              class="button-error"
+              id="promotionList-edit-btn"
+              @click="addProducts">+新增产品</a-button>
+          </div>
+        </div>
+        <div v-show="chooseVal=='a'"><tableType1 ref="cillProduct"></tableType1></div>
+        <div v-show="chooseVal=='d'"><tableType3 ref="specialProduct"></tableType3></div>
+      </a-card>
+      <div class="btn-cont">
+        <a-button id="promotionList-basicInfo-modal-back" @click="isShow = false">取消</a-button>
+        <a-button style="margin-left: 15px;" type="primary" id="promotionList-modal-save" @click="handleSave">确定</a-button>
+      </div>
+    </a-spin>
+    <!-- 选择产品 -->
+    <chooseProductsModal
+      type="dealership"
+      ref="productBox"
+      :openModal="openProductsModal"
+      :chooseData="chooseProducts"
+      @close="openProductsModal=false"
+      @ok="handleProductsAdd" />
+    <!-- 导入产品 -->
+    <importGuideModal :goodFlag="chooseVal=='a'?'1':'0'" :openModal="openGuideModal" @close="closeGuideModel" @ok="hanldeOk" />
+  </a-modal>
+</template>
+
+<script>
+import { commonMixin } from '@/utils/mixin'
+import { VSelect } from '@/components'
+import tableType1 from './tableType1.vue'
+import tableType3 from './tableType3.vue'
+import { promotionSave, getRuleDetail, getNewScopeSn } from '@/api/promotion'
+import chooseProductsModal from './chooseProductsModal.vue'
+import ImportGuideModal from './importGuideModal.vue'
+export default {
+  name: 'PromotionListBasicInfoModal',
+  mixins: [commonMixin],
+  components: { VSelect, tableType1, tableType3, chooseProductsModal, ImportGuideModal },
+  props: {
+    openModal: { //  弹框显示状态
+      type: Boolean,
+      default: false
+    },
+    promotionSn: {
+      type: [Number, String],
+      default: ''
+    },
+    itemSn: {
+      type: [Number, String],
+      default: ''
+    }
+  },
+  data () {
+    return {
+      isShow: this.openModal, //  是否打开弹框
+      spinning: false,
+      formItemLayout: {
+        labelCol: { span: 4 },
+        wrapperCol: { span: 17 }
+      },
+      form: {
+        promotionRuleType: 'PROMO_PROD', // 特价产品
+        description: '',
+        gateFlag: '0', // 门槛
+        gateType: undefined,
+        gateAmount: undefined,
+        quotaAmount: undefined,
+        minOrderFlag: '0', // 起订金额
+        minOrderAmount: undefined,
+        upperLimitFlag: '0', // 活动经费上限
+        upperLimitAmount: undefined
+      },
+      rules: {
+        description: [ { required: true, message: '请输入规则简称', trigger: 'blur' } ],
+        gateFlag: [ { required: true, message: '请选择规则门槛', trigger: 'change' } ],
+        minOrderFlag: [{ required: true, message: '请选择订单起订金额', trigger: 'change' }],
+        upperLimitFlag: [{ required: true, message: '请选择活动经费上限', trigger: 'change' }]
+      },
+      chooseVal: 'a',
+      openProductsModal: false,
+      chooseProducts: [],
+      openGuideModal: false// 导入弹窗
+    }
+  },
+  methods: {
+    // 导入
+    closeGuideModel () {
+      this.openGuideModal = false
+    },
+    // 门槛产品
+    handleChange (e) {
+      if (e.target.value == '1') {
+        this.chooseVal = 'a'
+      } else {
+        this.chooseVal = 'd'
+        this.form.gateType = undefined
+        this.form.gateAmount = undefined
+        this.form.quotaAmount = undefined
+      }
+    },
+    changeGateTypeFlag (val) {
+      this.form.gateType = val
+      this.form.gateAmount = undefined
+      this.form.quotaAmount = undefined
+    },
+    //  保存
+    handleSave () {
+      const _this = this
+      this.$refs.ruleForm.validate(valid => {
+        if (valid) {
+          // 验证必填
+          if (_this.form.gateFlag == '1') {
+            if (!_this.form.gateType) {
+              _this.$message.warning('请选择规则门槛设置类型!')
+              return
+            }
+            if (!_this.form.gateAmount) {
+              _this.$message.warning('规则门槛条件不能为空!')
+              return
+            }
+            if (_this.form.gateType === 'FIXED_AMOUNT' && !_this.form.quotaAmount) {
+              _this.$message.warning('规则门槛条件不能为空!')
+              return
+            }
+          }
+          if (_this.form.minOrderFlag == 1 && !_this.form.minOrderAmount) {
+            _this.$message.warning('请输入订单起订限制金额数!')
+            return
+          }
+          if (_this.form.minOrderFlag == 0) {
+            _this.form.minOrderAmount = undefined
+          }
+          if (_this.form.upperLimitFlag == 1 && !_this.form.upperLimitAmount) {
+            _this.$message.warning('请输入活动经费上限金额!')
+            return
+          }
+          if (_this.form.upperLimitFlag == 0) {
+            _this.form.upperLimitAmount = undefined
+          }
+          const form = JSON.parse(JSON.stringify(_this.form))
+          if (form.gateFlag == '1') {
+            form.gateProductList = _this.$refs.cillProduct.getResultVal()
+            form.gateAmount = form.gateType === 'RATIO_AMOUNT' ? form.gateAmount / 100 : form.gateAmount
+            if (form.gateProductList.length == 0) {
+              _this.$message.warning('请添加门槛产品!')
+              return
+            } else {
+              const qtyFlag = form.gateProductList.some(newCon => { return (!newCon.unitType || !newCon.unitQty) })
+              if (qtyFlag) {
+                _this.$message.warning('订单起订量设置不能为空!')
+                return
+              }
+              const rowFlag = _this.isJudge(form.gateProductList)
+              if (rowFlag) {
+                _this.$message.warning('请选择产品分类、品牌或产品!')
+                return
+              }
+            }
+          } else {
+            form.gateProductList = []
+            form.gateAmount = ''
+            form.quotaAmount = ''
+            form.gateType = undefined
+          }
+          form.specialProductList = _this.$refs.specialProduct.getResultVal()
+          if (form.specialProductList.length == 0) {
+            _this.$message.warning('请添加特价产品!')
+            return
+          } else {
+            // 为空判断
+            const isTypeEmpty = form.specialProductList.some(item => (item.productTypeList && item.productTypeList.length == 0) && (item.productBrandList && item.productBrandList.length == 0))
+            if (isTypeEmpty) {
+              _this.$message.warning('产品分类或品牌不能为空!')
+              return
+            }
+            const isNumEmpty = form.specialProductList.some(item => (!item.unitType || !item.unitQty))
+            if (isNumEmpty) {
+              _this.$message.warning('订单起订量设置不能为空!')
+              return
+            }
+            const isCountEmpty = _this.isNumEmpty(form.specialProductList)
+            const isMoneyEmpty = _this.isNumEmpty(form.specialProductList)
+            if (isCountEmpty.flag) {
+              _this.$message.warning('折扣不能为空!')
+              return
+            }
+            if (isCountEmpty.flag1) {
+              _this.$message.warning('折扣金额不能为空!')
+              return
+            }
+          }
+          form.promotionSn = _this.promotionSn
+          _this.spinning = true
+          promotionSave(form).then(res => {
+            if (res.status == 200) {
+              _this.$message.success(res.message)
+              setTimeout(() => {
+                _this.isShow = false
+                _this.$emit('ok')
+                _this.spinning = false
+              }, 1000)
+            } else {
+              _this.spinning = false
+            }
+          })
+        } else {
+          return false
+        }
+      })
+    },
+    isNumEmpty (dataList) {
+      const arr = []
+      const arr1 = []
+      dataList.forEach(item => {
+        if (item.dataSourceOrigin === '0') { // 判断分类品牌
+          if (!item.provinceDiscountRate || !item.cityDiscountRate || !item.specialDiscountRate) {
+            arr.push(item.productScopeSn)
+          }
+        } else {
+          if (!item.cityDiscountPrice || !item.provinceDiscountPrice || !item.specialDiscountPrice) {
+            arr1.push(item.productScopeSn)
+          }
+        }
+      })
+      return { flag: arr.length > 0, flag1: arr1.length > 0 }
+    },
+    // 判断门槛产品中品牌,分类,产品其中一个必填
+    isJudge (list) {
+      const flag = list.some(con => {
+        if (con.productThisList) {
+          if (con.productThisList.length > 0) {
+            return false
+          } else {
+            if ((con.productTypeList && con.productTypeList.length > 0) || (con.productBrandList && con.productBrandList.length > 0)) {
+              return false
+            } else {
+              return true
+            }
+          }
+        } else {
+          if ((con.productTypeList && con.productTypeList.length > 0) || (con.productBrandList && con.productBrandList.length > 0)) {
+            return false
+          } else {
+            return true
+          }
+        }
+      })
+      return flag
+    },
+    // 重置表格
+    resetSearchForm () {
+      this.form = {
+        promotionRuleType: 'PROMO_PROD', // 特价产品
+        description: '',
+        gateFlag: '0', // 门槛
+        gateType: undefined,
+        gateAmount: undefined,
+        quotaAmount: undefined,
+        minOrderFlag: '1', // 起订金额
+        minOrderAmount: undefined,
+        upperLimitFlag: '1', // 活动经费上限
+        upperLimitAmount: undefined,
+        gateProductList: undefined,
+        specialProductList: undefined
+      }
+      this.$nextTick(() => {
+        this.$refs.ruleForm.resetFields()
+        this.$refs.cillProduct.reSetTableData()
+        this.$refs.specialProduct.reSetTableData()
+      })
+    },
+    // 获取编辑详情
+    getDetail () {
+      const _this = this
+      getRuleDetail({ sn: this.itemSn }).then(res => {
+        if (res.status == 200) {
+          this.chooseVal = res.data.gateFlag == '0' ? 'd' : 'a'
+          const resultObj = res.data
+          if (resultObj.gateFlag === '1') {
+            resultObj.gateAmount = resultObj.gateType === 'RATIO_AMOUNT' ? resultObj.gateAmount * 100 : resultObj.gateAmount
+          }
+          // 重新组成保存数据
+          if (resultObj.gateProductList && resultObj.gateProductList.length > 0) {
+            resultObj.gateProductList = _this.newData(resultObj.gateProductList)
+            this.$refs.cillProduct.setTabVal(resultObj.gateProductList)
+          }
+          if (resultObj.specialProductList && resultObj.specialProductList.length > 0) {
+            resultObj.specialProductList = _this.newData(resultObj.specialProductList)
+            this.$refs.specialProduct.setSourceData(resultObj.specialProductList)
+          }
+          this.form = { ...this.form, ...resultObj }
+        }
+      })
+    },
+    newData (list) {
+      list.forEach(con => {
+        // 品牌
+        if (con.productBrandList) {
+          const brandList = []
+          con.productBrandList.forEach(item => {
+            item.brandName = item.productBrandName
+            const brandObj = {
+              productBrandSn: item.productBrandSn
+            }
+            brandList.push(brandObj)
+          })
+          con.productBrandArr = con.productBrandList
+          con.productBrandList = brandList
+        }
+        // 分类
+        if (con.productTypeList) {
+          const typeList = []
+          con.productTypeList.forEach(item => {
+            const typeObj = {}
+            item.title = ''
+            const num = 3
+            for (var i = 0; i < num; i++) {
+              if (item['productTypeName' + (i + 1)]) {
+                // item.title += item['productTypeName' + (i + 1)] + (item['productTypeName' + (i + 1)] ? '/' : '')
+                typeObj['productTypeSn' + (i + 1)] = item['productTypeSn' + (i + 1)] ? item['productTypeSn' + (i + 1)] : ''
+              }
+            }
+            // item.title = item.title.slice(0, item.title.length - 1)
+            if (item.productTypeName3) {
+              item.title = item.productTypeName2 + '/' + item.productTypeName3
+            } else if (!item.productTypeName3 && item.productTypeName2) {
+              item.title = item.productTypeName2
+            } else {
+              item.title = item.productTypeName1
+            }
+            item.id = item.productTypeSn3 ? item.productTypeSn3 : item.productTypeSn2 ? item.productTypeSn2 : item.productTypeSn1
+            typeList.push(typeObj)
+          })
+          con.productTypeArr = con.productTypeList
+          con.productTypeList = typeList
+        }
+        // 产品
+        if (con.productThisList) {
+          const productList = []
+          con.productThisList.forEach(item => {
+            const productObj = {
+              productCode: item.productCode,
+              productSn: item.productSn
+            }
+            productList.push(productObj)
+          })
+          con.productThisList = productList
+        }
+      })
+      return list
+    },
+    // 导入
+    hanldeOk (arr) {
+      // 门槛产品导入
+      const resultArr = []
+      if (this.chooseVal == 'a') {
+        arr.forEach(item => {
+          const obj = {
+            productCode: item.productCode,
+            productSn: item.product.productSn
+          }
+          resultArr.push(obj)
+        })
+        const name = this.chooseVal == 'a' ? 'cill' : this.chooseVal == 'b' ? 'normalPrice' : 'offer'
+        this.$refs[name + 'Product'].importRow(resultArr)
+      } else {
+        // 特价产品导入
+        const dataList = this.setShowData('This')
+        arr.forEach(item => {
+          item = { ...item, ...item.product }
+          item.code = item.productCode
+          if (item.provincePrice) {
+            item.provinceDiscountRate = Math.floor(((item.provinceDiscountPriceText / item.provincePrice) * 100).toFixed(2))
+          }
+          if (item.cityPrice) {
+            item.cityDiscountRate = Math.floor(((item.cityDiscountPriceText / item.cityPrice) * 100).toFixed(2))
+          }
+          if (item.specialPrice) {
+            item.specialDiscountRate = Math.floor(((item.specialDiscountPriceText / item.specialPrice) * 100).toFixed(2))
+          }
+          const flag = dataList.includes(item.productSn)
+          if (!flag) {
+            resultArr.push(item)
+          }
+        })
+        if (resultArr.length > 0) {
+          this.handleProductsOk(resultArr)
+        } else {
+          this.$message.warning('请勿添加重复数据!')
+        }
+      }
+    },
+    // 打开新增产品弹窗(禁用已选)
+    addProducts () {
+      this.chooseProducts = []
+      this.openProductsModal = true
+      const dataList = this.setShowData('This')
+      this.$refs.productBox.handleDisabled(dataList)
+    },
+    // 获取回显禁用数据
+    setShowData (name) {
+      const _this = this
+      const snArr = []
+      const valList = _this.$refs.specialProduct.getResultVal()
+      valList.forEach(item => {
+        if (item['product' + name + 'List'] && item['product' + name + 'List'].length > 0) {
+          item['product' + name + 'List'].forEach(con => {
+            const newName = name === 'This' ? '' : name
+            snArr.push(con['product' + newName + 'Sn'])
+          })
+        }
+      })
+      return snArr
+    },
+    handleProductsAdd (con) {
+      debugger
+      const newArr = []
+      con.forEach(newCon => {
+        if (!newCon.provincePrice || !newCon.cityPrice || !newCon.specialPrice) {
+          newArr.push(newCon.code)
+        }
+      })
+      con.map((list, pos) => {
+        if (!list.provincePrice || !list.cityPrice || !list.specialPrice) {
+          con.splice(pos, 1)
+        }
+      })
+      const _this = this
+      if (newArr && newArr.length > 0) {
+        _this.$info({
+          title: '提示',
+          content: newArr.toString() + '(产品编码),没有定价,不可添加',
+          closable: true,
+          centered: true,
+          onOk () {
+            _this.handleProductsOk(con)
+          }
+        })
+      } else {
+        _this.handleProductsOk(con)
+      }
+    },
+    // +新增产品
+    handleProductsOk (con) {
+      const _this = this
+      con.forEach(async (item) => {
+        const chooseProductsList = []
+        const getSn = await getNewScopeSn({})
+        if (getSn.status == 200) {
+          const newData = {
+            productScopeSn: getSn.data,
+            dataSourceOrigin: '1',
+            productTypeArr: [],
+            productTypeList: [],
+            productBrandArr: [{ productBrandSn: item.productBrandSn, brandName: item.productBrandName }],
+            productBrandList: [{ productBrandSn: item.productBrandSn }],
+            productThisList: [{
+              productSn: item.productSn,
+              productCode: item.code
+            }],
+            provincePrice: item.provincePrice,
+            cityPrice: item.cityPrice,
+            specialPrice: item.specialPrice,
+            provinceDiscountPrice: item.provinceDiscountPriceText,
+            cityDiscountPrice: item.cityDiscountPriceText,
+            specialDiscountPrice: item.specialDiscountPriceText,
+            unitType: 'SL',
+            unitQty: 1,
+            provinceDiscountRate: item.provinceDiscountRate ? item.provinceDiscountRate : undefined,
+            cityDiscountRate: item.cityDiscountRate ? item.cityDiscountRate : undefined,
+            specialDiscountRate: item.specialDiscountRate ? item.specialDiscountRate : undefined
+          }
+          const obj = {}
+          if (item.productTypeSn1) {
+            obj.productTypeSn1 = item.productTypeSn1
+          }
+          if (item.productTypeSn2) {
+            obj.productTypeSn2 = item.productTypeSn2
+          }
+          if (item.productTypeSn3) {
+            obj.productTypeSn3 = item.productTypeSn3
+          }
+          const newObj = { ...obj, ...{} }
+          if (Object.keys(obj).length == 1) {
+            newObj.title = item.productTypeName1
+            newObj.id = item.productTypeSn1
+          } else if (Object.keys(obj).length == 2) {
+            newObj.title = item.productTypeName2
+            newObj.id = item.productTypeSn2
+          } else {
+            newObj.title = item.productTypeName2 + '/' + item.productTypeName3
+            newObj.id = item.productTypeSn3
+          }
+          newData.productTypeList[0] = obj
+          newData.productTypeArr[0] = newObj
+          chooseProductsList.push(newData)
+        }
+        _this.$refs.specialProduct.setSourceData(chooseProductsList)
+      })
+    }
+  },
+  watch: {
+    //  父页面传过来的弹框状态
+    openModal (newValue, oldValue) {
+      this.isShow = newValue
+    },
+    //  重定义的弹框状态
+    isShow (newValue, oldValue) {
+      if (!newValue) {
+        this.$emit('close')
+        this.resetSearchForm()
+      } else {
+        if (this.itemSn) {
+          this.getDetail()
+        } else {
+          this.chooseVal = this.form.gateFlag == '0' ? 'd' : 'a'
+        }
+      }
+    }
+  }
+}
+</script>
+
+<style lang="less" scoped>
+  .promotionList-basicInfo-modal{
+    /deep/.ant-modal-body {
+      padding: 40px 40px 24px;
+      max-height: 745px !important;
+      overflow-y: scroll !important;
+    }
+    .ant-radio-button-wrapper{
+      width:80px;
+      text-align: center;
+    }
+    .ant-form-item{
+      margin-bottom:5px;
+    }
+    .buyerBox{
+      border:1px solid #d9d9d9;margin-top:10px;border-radius:4px;padding:4px 10px;background:#f2f2f2;max-height:130px;overflow-y:scroll;
+    }
+    .btn-cont {
+      text-align: center;
+      margin: 35px 0 10px;
+    }
+    .flex{
+      display:flex;
+      align-items:center;
+      justify-content:space-between;
+    }
+  }
+
+</style>

+ 638 - 0
src/views/promotionRulesManagement/dealerPromotions/tableType1.vue

@@ -0,0 +1,638 @@
+<template>
+  <div class="pages-wrap">
+    <!-- 列表 -->
+    <a-table
+      class="sTable"
+      style="margin-top:10px;"
+      ref="table"
+      size="small"
+      :pagination="false"
+      :rowKey="(record) => record.productScopeSn"
+      :columns="columns"
+      :data-source="dataSource"
+      bordered>
+      <!-- 产品分类 -->
+      <template slot="productType" slot-scope="text, record,index">
+        <div style="max-height:126px;width:100%;overflow-y:scroll;" v-if="!record.productThisList || record.productThisList.length==0">
+          <a-row v-if="record.productTypeArr && record.productTypeArr.length>0">
+            <a-col :span="18">
+              <div v-for="con in record.productTypeArr" :key="con.id">
+                <a-tooltip v-if="con.title&&con.title.length > 12" :title="con.title">
+                  <a-tag style="margin-bottom:10px;" closable @close.prevent="delLabel(record.productScopeSn,con,'typeList')">
+                    {{ `${con.title.slice(0, 12)}...` }}
+                  </a-tag>
+                </a-tooltip>
+                <a-tag v-else style="margin-bottom:10px;" closable @close.prevent="delLabel(record.productScopeSn,con,'typeList')">
+                  {{ con.title }}
+                </a-tag>
+              </div>
+            </a-col>
+            <a-col :span="6" style="text-align:right;">
+              <a-tag style="background: #fff; borderStyle: dashed;" @click="addClassifyTag(index, record)" color="blue">
+                <a-icon type="plus" />
+              </a-tag>
+            </a-col>
+          </a-row>
+          <a-row v-else>
+            <a-col :span="24">
+              <a-tag style="background: #fff; borderStyle: dashed;" @click="addClassifyTag(index, record)" color="blue">
+                <a-icon type="plus" />
+              </a-tag>
+            </a-col>
+          </a-row>
+        </div>
+        <div v-else>
+          <a-tag style="background: #fff; borderStyle: dashed;" :style="{color:'grey',cursor:'not-allowed'}">
+            <a-icon type="plus" />
+          </a-tag>
+        </div>
+      </template>
+      <!-- 品牌 -->
+      <template slot="productBrand" slot-scope="text, record,index">
+        <div style="max-height:126px;overflow-y:scroll;" v-if="!record.productThisList || record.productThisList.length==0">
+          <a-row v-if="record.productBrandArr && record.productBrandArr.length>0">
+            <a-col :span="18">
+              <a-tag v-for="item in record.productBrandArr" :key="item.brandSn" style="margin-bottom:10px;" closable @close.prevent="delLabel(record.productScopeSn,item,'brandList')">
+                {{ item.brandName }}
+              </a-tag>
+            </a-col>
+            <a-col :span="6" style="text-align:right;">
+              <a-tag style="background: #fff; borderStyle: dashed;" @click="addBrandTag(index, record)" color="blue">
+                <a-icon type="plus" />
+              </a-tag>
+            </a-col>
+          </a-row>
+          <a-row v-else>
+            <a-col :span="24">
+              <a-tag style="background: #fff; borderStyle: dashed;" @click="addBrandTag(index, record)" color="blue">
+                <a-icon type="plus" />
+              </a-tag>
+            </a-col>
+          </a-row>
+        </div>
+        <div v-else>
+          <a-tag style="background: #fff; borderStyle: dashed;" :style="{color:'grey',cursor:'not-allowed'}">
+            <a-icon type="plus" />
+          </a-tag>
+        </div>
+      </template>
+      <!-- 产品 -->
+      <template slot="product" slot-scope="text, record,index">
+        <div v-if="(record.productBrandArr && record.productBrandArr.length>0)||(record.productTypeArr && record.productTypeArr.length>0)">
+          <a-tag style="background: #fff; borderStyle: dashed;" :style="{color:'grey',cursor:'not-allowed'}">
+            <a-icon type="plus" />
+          </a-tag>
+        </div>
+        <div style="max-height:126px;overflow-y:scroll;" v-else>
+          <a-row v-if="record.productThisList && record.productThisList.length>0">
+            <a-col :span="18">
+              <a-tag style="margin-bottom:10px;" closable @close.prevent="delLabel(record.productScopeSn,item,'productList')" v-for="item in record.productThisList" :key="item.productSn">
+                {{ item.productCode }}
+              </a-tag>
+            </a-col>
+            <a-col :span="6" style="text-align:right;">
+              <a-tag style="background: #fff; borderStyle: dashed;" @click="addProductTag(index, record)" color="blue">
+                <a-icon type="plus" />
+              </a-tag>
+            </a-col>
+          </a-row>
+          <a-row v-else>
+            <a-col :span="24">
+              <a-tag style="background: #fff; borderStyle: dashed;" @click="addProductTag(index, record)" color="blue">
+                <a-icon type="plus" />
+              </a-tag>
+            </a-col>
+          </a-row>
+        </div>
+      </template>
+      <!-- 设置起订量 -->
+      <template slot="setNum" slot-scope="text, record">
+        <v-select
+          v-model="record.unitType"
+          size="small"
+          ref="returnReason"
+          code="SCOPE_UNIT_TYPE"
+          placeholder="请选择"
+          style="width:100%;"
+          allowClear></v-select>
+        <a-input-number
+          size="small"
+          style="margin-top:8px;width:100%;"
+          v-model="record.unitQty"
+          :min="0"
+          :step="1"
+          :max="999999"
+          :precision="0"
+          placeholder="请输入"/>
+      </template>
+      <span slot="action" slot-scope="text,record">
+        <a-button
+          size="small"
+          type="link"
+          class="button-error"
+          @click="handleDel(record)"
+        >
+          删除
+        </a-button>
+      </span>
+    </a-table>
+    <div class="btn-cont">
+      <a-button id="tableType1-add" type="primary" class="button-gray" @click="handleAddRow">+新增一行</a-button>
+    </div>
+    <!-- 选择产品品牌 -->
+    <chooseBrandModal
+      pageType="1"
+      ref="brandBox"
+      :openModal="openBrandModal"
+      :chooseData="chooseBrand"
+      @close="openBrandModal=false"
+      @ok="handleBrandOk" />
+    <!-- 选择产品分类 -->
+    <chooseTypeModal
+      ref="typeBox"
+      :openModal="openTypeModal"
+      :linkageStatus="false"
+      :chooseData="chooseType"
+      @close="openTypeModal=false"
+      @ok="handleTypeOk" />
+    <!-- 选择产品 -->
+    <chooseProductsModal
+      type="dealership"
+      ref="productBox"
+      :openModal="openProductsModal"
+      :chooseData="chooseProducts"
+      @close="closeProductModal"
+      @ok="handleProductsOk" />
+  </div>
+</template>
+
+<script>
+import { commonMixin } from '@/utils/mixin'
+import { VSelect } from '@/components'
+import ChooseBrandModal from '@/views/common/chooseBrandModal.vue'
+import ChooseTypeModal from '@/views/common/chooseTypeModal.vue'
+import chooseProductsModal from './chooseProductsModal.vue'
+import { getNewScopeSn } from '@/api/promotion'
+export default {
+  name: 'TableType1',
+  mixins: [commonMixin],
+  components: { VSelect, ChooseBrandModal, ChooseTypeModal, chooseProductsModal },
+  data () {
+    return {
+      spinning: false,
+      columns: [
+        { title: '产品分类', width: '27%', scopedSlots: { customRender: 'productType' }, align: 'center' },
+        { title: '品牌', width: '27%', scopedSlots: { customRender: 'productBrand' }, align: 'center' },
+        { title: '产品', width: '27%', scopedSlots: { customRender: 'product' }, align: 'center' },
+        { title: '设置起订量', width: '11%', scopedSlots: { customRender: 'setNum' }, align: 'center' },
+        { title: '操作', scopedSlots: { customRender: 'action' }, width: '8%', align: 'center' }
+      ],
+      dataSource: [],
+      openBrandModal: false,
+      openTypeModal: false,
+      openProductsModal: false,
+      chooseBrand: [],
+      chooseType: [],
+      brandTagIndex: null, // 所选品牌位置
+      classifyTagIndex: null, // 所选分类位置
+      productTagIndex: null, // 所选产品位置
+      chooseProducts: []
+    }
+  },
+  methods: {
+    closeProductModal () {
+      this.chooseProducts = []
+      this.openProductsModal = false
+    },
+    // 新增一行
+    handleAddRow () {
+      const _this = this
+      _this.spinning = false
+      getNewScopeSn({}).then(res => {
+        if (res.status == 200) {
+          const newData = {
+            productScopeSn: res.data,
+            productTypeArr: [],
+            productTypeList: [],
+            productBrandArr: [],
+            productBrandList: [],
+            productThisList: [],
+            unitType: 'SL',
+            unitQty: 1
+          }
+          _this.dataSource.push(newData)
+        } else {
+          _this.spinning = false
+        }
+      })
+    },
+    // 导入新增一行
+    importRow (list) {
+      const _this = this
+      const dataList = _this.setShowData('This')
+      dataList.forEach(item => {
+        const pos = list.indexOf(con => con.productSn == item.goodsSn)
+        list.splice(pos, 1)
+      })
+      if (list.length > 0) {
+        _this.spinning = true
+        getNewScopeSn({}).then(res => {
+          if (res.status == 200) {
+            const newData = {
+              productScopeSn: res.data,
+              productThisList: list,
+              unitType: 'SL',
+              unitQty: 1
+            }
+            _this.dataSource.push(newData)
+          } else {
+            _this.spinning = false
+          }
+        })
+      } else {
+        _this.$message.warning('请勿导入重复数据!')
+      }
+    },
+    // 删除一行
+    handleDel (row) {
+      const pos = this.dataSource.findIndex(con => con.productScopeSn == row.productScopeSn)
+      this.dataSource.splice(pos, 1)
+    },
+    // 添加产品分类
+    addClassifyTag (pos, row) {
+      this.classifyTagIndex = pos
+      this.openTypeModal = true
+      this.chooseType = this.handleRowData(row)
+      const getArr = this.setTypeShowData()
+      // 无品牌有分类的选择数据
+      const onlyTypeData = this.onlyType()
+      // 获取品牌重复数据
+      var flag = false
+      var c_typeArr = []
+      this.dataSource.forEach(item => {
+        if ((item.productTypeArr && item.productTypeArr.length > 0) && (item.productBrandList && item.productBrandList.length > 0)) {
+          item.productBrandList.forEach((con) => {
+            row.productBrandList.forEach(newCon => {
+              if (newCon.productBrandSn == con.productBrandSn) {
+                flag = true
+                c_typeArr = c_typeArr.concat(item.productTypeList)
+              }
+            })
+          })
+        }
+      })
+      const disTypeList = []
+      getArr.forEach(con => {
+        c_typeArr.forEach(item => {
+          for (const i in item) {
+            if (item[i] == con.goodsSn) {
+              disTypeList.push(con)
+            }
+          }
+        })
+      })
+      var uniqueArr = [...new Set(disTypeList)]
+
+      if (row.productBrandArr && row.productBrandArr.length == 0) {
+        this.$refs.typeBox.handleAllDisabled(onlyTypeData)
+      } else {
+        if (flag) {
+          this.$refs.typeBox.handleAllDisabled(uniqueArr)
+        } else {
+          this.chooseType = []
+          this.$refs.typeBox.handleAllDisabled([])
+        }
+      }
+    },
+    handleTypeOk (mainArr) {
+      const classifyArr = []
+      const newClassifyArr = []
+      mainArr.forEach(item => {
+        if (item.productTypeLevel == 1) {
+          if ((item.dataRef&&!item.dataRef.children)||(!item.dataRef &&!item.children)) {
+            const objType1 = {
+              productTypeSn1: item.snPaths
+            }
+            newClassifyArr.push(objType1)
+            const obj = JSON.parse(JSON.stringify(objType1))
+            obj.title = item.title
+            obj.id = item.snPaths
+            classifyArr.push(obj)
+          }
+        }
+        if (item.productTypeLevel == 2) {
+          if ((item.dataRef&&!item.dataRef.children)||(!item.dataRef &&!item.children)) {
+            const typeArr1 = item.snPaths ? item.snPaths.split(',') : []
+            const objType2 = {
+              productTypeSn1: typeArr1[0],
+              productTypeSn2: typeArr1[1]
+            }
+            newClassifyArr.push(objType2)
+            const obj = JSON.parse(JSON.stringify(objType2))
+            const newName = item.namePaths.split(',')
+            obj.title = newName[1]
+            obj.id = typeArr1[1]
+            classifyArr.push(obj)
+          }
+        }
+        if (item.productTypeLevel == 3) {
+          const typeArr2 = item.snPaths ? item.snPaths.split(',') : []
+          const objType3 = {
+            productTypeSn1: typeArr2[0],
+            productTypeSn2: typeArr2[1],
+            productTypeSn3: typeArr2[2]
+          }
+          newClassifyArr.push(objType3)
+          const obj = JSON.parse(JSON.stringify(objType3))
+          const newName = item.namePaths.split(',')
+          obj.title = newName[1] + '/' + newName[2]
+          obj.id = typeArr2[2]
+          classifyArr.push(obj)
+        }
+      })
+      this.dataSource[this.classifyTagIndex].productTypeList = newClassifyArr
+      this.dataSource[this.classifyTagIndex].productTypeArr = classifyArr
+    },
+    // 添加产品品牌
+    addBrandTag (pos, row) {
+      const _this = this
+      _this.brandTagIndex = pos
+      // 选中的所有品牌
+      const dataList = _this.setShowData('Brand')
+      _this.openBrandModal = true
+      // 回显当前行选中
+      const echoData = _this.handleEchoData('Brand', row.productBrandList)
+      _this.chooseBrand = echoData
+      // 只有品牌没有分类
+      const onlyBrandData = this.onlyBrand()
+      // 同行中分类是否与所选分类相同   已选分类
+      var flag = false
+      var c_brandArr = []
+      this.dataSource.forEach(item => {
+        if ((item.productTypeArr && item.productTypeArr.length > 0) && (item.productBrandList && item.productBrandList.length > 0)) {
+          item.productTypeArr.forEach((con) => {
+            row.productTypeArr.forEach(newCon => {
+              if (newCon.id == con.id) {
+                flag = true
+                c_brandArr = c_brandArr.concat(item.productBrandList)
+              }
+            })
+          })
+        }
+      })
+      const reBrandArr = c_brandArr.map(list => {
+        return list.productBrandSn
+      })
+      if (row.productTypeArr && row.productTypeArr.length == 0) {
+        _this.$refs.brandBox.handleDisabled(onlyBrandData)
+      } else {
+        if (flag) { // 当前行有重复分类
+          _this.$refs.brandBox.handleDisabled(reBrandArr)
+        } else {
+          _this.chooseBrand = []
+          _this.$refs.brandBox.handleDisabled([])
+        }
+      }
+    },
+    handleBrandOk (conList) {
+      const newConList = conList.map(con => {
+        return {
+          productBrandSn: con.brandSn
+        }
+      })
+      this.dataSource[this.brandTagIndex].productBrandArr = conList
+      this.dataSource[this.brandTagIndex].productBrandList = newConList
+    },
+    // 添加产品
+    addProductTag (pos, row) {
+      this.productTagIndex = pos
+      this.openProductsModal = true
+      const dataList = this.setShowData('This')
+      const echoData = this.handleEchoData('This', row.productThisList)
+      this.chooseProducts = echoData
+      this.$refs.productBox.handleDisabled(dataList)
+    },
+    handleProductsOk (arr) {
+      const newArr = []
+      arr.forEach(item => {
+        const obj = {
+          productCode: item.code,
+          productSn: item.productSn
+        }
+        newArr.push(obj)
+      })
+      this.dataSource[this.productTagIndex].productThisList = newArr
+    },
+    // 获取回显禁用数据
+    setShowData (name) {
+      const _this = this
+      const snArr = []
+      _this.dataSource.forEach(item => {
+        if (item['product' + name + 'List'] && item['product' + name + 'List'].length > 0) {
+          item['product' + name + 'List'].forEach(con => {
+            const newName = name === 'This' ? '' : name
+            snArr.push(con['product' + newName + 'Sn'])
+          })
+        }
+      })
+      return snArr
+    },
+    // 只有分类
+    onlyType (name, onlyName) {
+      const _this = this
+      const snArr = []
+      _this.dataSource.forEach(item => {
+        if (item.productTypeList && item.productTypeList.length > 0) {
+          if (!item.productBrandList || (item.productBrandList && item.productBrandList.length == 0)) {
+            item.productTypeList.forEach(con => {
+              for (const i in con) {
+                const newObj = {
+                  goodsSn: con[i]
+                }
+                if (i === 'productTypeSn1') {
+                  newObj.disabled = true
+                } else {
+                  newObj.disableCheckbox = true
+                }
+                snArr.push(newObj)
+              }
+            })
+          }
+        }
+      })
+      return snArr
+    },
+    // 只有品牌
+    onlyBrand () {
+      const _this = this
+      var snArr = []
+      _this.dataSource.forEach(item => {
+        if (item.productBrandList && item.productBrandList.length > 0) {
+          if (!item.productTypeArr || (item.productTypeArr && item.productTypeArr.length == 0)) {
+            item.productBrandList.forEach(con => {
+              snArr.push(con.productBrandSn)
+            })
+          }
+        }
+      })
+      return snArr
+    },
+    handleEchoData (name, conArr) {
+      if (conArr) {
+        conArr.map(item => {
+          if (name === 'This') {
+            item.code = item.productCode
+            item.goodsSn = item.productSn
+          } else {
+            item.goodsSn = item['product' + name + 'Sn']
+          }
+        })
+      } else {
+        conArr = []
+      }
+      return conArr
+    },
+    handleRowData (row) {
+      const echoData = []
+      row.productTypeList.forEach(item => {
+        for (const i in item) {
+          const newObj = {
+            goodsSn: item[i]
+          }
+          if (i === 'productTypeSn1') {
+            newObj.disabled = true
+          } else {
+            newObj.disableCheckbox = true
+          }
+          echoData.push(newObj)
+        }
+      })
+      return echoData
+    },
+    setTypeShowData () {
+      const _this = this
+      const snArr = []
+      _this.dataSource.forEach(item => {
+        if (item.productTypeList && item.productTypeList.length > 0) {
+          item.productTypeList.forEach(con => {
+            for (const i in con) {
+              const newObj = {
+                goodsSn: con[i]
+              }
+              if (i === 'productTypeSn1') {
+                newObj.disabled = true
+              } else {
+                newObj.disableCheckbox = true
+              }
+              snArr.push(newObj)
+            }
+          })
+        }
+      })
+      return snArr
+    },
+    // 获取表格数据
+    getResultVal () {
+      const resultObj = JSON.parse(JSON.stringify(this.dataSource))
+      resultObj.map(item => {
+        delete item.productTypeArr
+        delete item.productBrandArr
+        return item
+      })
+      return resultObj
+    },
+    setTabVal (formData) {
+      this.dataSource = formData
+    },
+    // 关闭时清空表格数据
+    reSetTableData () {
+      this.dataSource = []
+    },
+    // 删除标签
+    delLabel (sn, row, type) {
+      const pos = this.dataSource.findIndex(con => con.productScopeSn == sn)
+      if (type === 'typeList') {
+        // 判断品牌是否有重复 重复值有无分类
+        const isRepeatBrandFlag = this.isRepeatBrand(this.dataSource[pos])
+        const uniqueArr1 = this.dataSource[pos].productTypeList && this.dataSource[pos].productTypeList.length > 0 ? this.dataSource[pos].productTypeList : []
+        if (isRepeatBrandFlag.flag && isRepeatBrandFlag.noTypeFlag && uniqueArr1.length == 1) {
+          this.dataSource.splice(pos, 1)
+        } else {
+          const i = this.dataSource[pos].productTypeArr.findIndex(con => con.id == row.id)
+          this.dataSource[pos].productTypeArr.splice(i, 1)
+          this.dataSource[pos].productTypeList.splice(i, 1)
+        }
+      } else if (type === 'brandList') {
+        const isRepeatTypeFlag = this.isRepeatType(this.dataSource[pos])
+        const uniqueArr = this.dataSource[pos].productBrandList && this.dataSource[pos].productBrandList.length > 0 ? this.dataSource[pos].productBrandList : []
+        if (isRepeatTypeFlag.flag && isRepeatTypeFlag.noTypeFlag && uniqueArr.length == 1) {
+          this.dataSource.splice(pos, 1)
+        } else {
+          const j = this.dataSource[pos].productBrandArr.findIndex(con => con.brandSn == row.brandSn)
+          this.dataSource[pos].productBrandArr.splice(j, 1)
+          this.dataSource[pos].productBrandList.splice(j, 1)
+        }
+      } else {
+        const k = this.dataSource[pos].productThisList.findIndex(con => con.productSn == row.productSn)
+        this.dataSource[pos].productThisList.splice(k, 1)
+      }
+      this.$forceUpdate()
+    },
+    // 判断当前行是否有重复品牌
+    isRepeatBrand (row) {
+      var flag = false
+      var noTypeFlag = false
+      var c_typeArr = []
+      this.dataSource.forEach(item => {
+        if (item.productBrandList && item.productBrandList.length > 0) {
+          item.productBrandList.forEach((con) => {
+            row.productBrandList.forEach(newCon => {
+              if (newCon.productBrandSn == con.productBrandSn) {
+                flag = true
+                if (item.productTypeList && item.productTypeList.length == 0) {
+                  noTypeFlag = true
+                } else {
+                  c_typeArr = c_typeArr.concat(item.productTypeList)
+                }
+              }
+            })
+          })
+        }
+      })
+      return { list: c_typeArr, flag: flag, noTypeFlag: noTypeFlag }
+    },
+    isRepeatType (row) {
+      var flag = false
+      var noTypeFlag = false
+      var c_brandArr = []
+      this.dataSource.forEach(item => {
+        if (item.productTypeArr && item.productTypeArr.length > 0) {
+          item.productTypeArr.forEach((con) => {
+            row.productTypeArr.forEach(newCon => {
+              if (newCon.id == con.id) {
+                flag = true
+                if (item.productBrandList && item.productBrandList.length == 0) {
+                  noTypeFlag = true
+                } else {
+                  c_brandArr = c_brandArr.concat(item.productBrandList)
+                }
+              }
+            })
+          })
+        }
+      })
+      return { list: c_brandArr, flag: flag, noTypeFlag: noTypeFlag }
+    }
+  }
+}
+</script>
+
+<style lang="less" scoped>
+  .pages-wrap{
+    .btn-cont {
+      text-align: center;
+      margin: 10px 0;
+    }
+  }
+
+</style>

+ 608 - 0
src/views/promotionRulesManagement/dealerPromotions/tableType2.vue

@@ -0,0 +1,608 @@
+<template>
+  <div class="pages-wrap">
+    <!-- 列表 -->
+    <a-table
+      class="sTable"
+      style="margin-top:10px;"
+      ref="table"
+      size="small"
+      :pagination="false"
+      :rowKey="(record) => record.productScopeSn"
+      :columns="columns"
+      :data-source="dataSource"
+      bordered>
+      <!-- 产品分类 -->
+      <template slot="productType" slot-scope="text, record,index">
+        <div style="max-height:126px;width:100%;overflow-y:scroll;" v-if="!record.productThisList || record.productThisList.length==0">
+          <a-row v-if="record.productTypeArr && record.productTypeArr.length>0">
+            <a-col :span="18">
+              <div v-for="con in record.productTypeArr" :key="con.id">
+                <a-tooltip v-if="con.title&&con.title.length > 12" :title="con.title">
+                  <a-tag style="margin-bottom:10px;" closable @close.prevent="delLabel(record.productScopeSn,con,'typeList')">
+                    {{ `${con.title.slice(0, 12)}...` }}
+                  </a-tag>
+                </a-tooltip>
+                <a-tag v-else style="margin-bottom:10px;" closable @close.prevent="delLabel(record.productScopeSn,con,'typeList')">
+                  {{ con.title }}
+                </a-tag>
+              </div>
+            </a-col>
+            <a-col :span="6" style="text-align:right;">
+              <a-tag style="background: #fff; borderStyle: dashed;" @click="addClassifyTag(index, record)" color="blue">
+                <a-icon type="plus" />
+              </a-tag>
+            </a-col>
+          </a-row>
+          <a-row v-else>
+            <a-col :span="24">
+              <a-tag style="background: #fff; borderStyle: dashed;" @click="addClassifyTag(index, record)" color="blue">
+                <a-icon type="plus" />
+              </a-tag>
+            </a-col>
+          </a-row>
+        </div>
+        <div v-else>
+          <a-tag style="background: #fff; borderStyle: dashed;" :style="{color:'grey',cursor:'not-allowed'}">
+            <a-icon type="plus" />
+          </a-tag>
+        </div>
+      </template>
+      <!-- 品牌 -->
+      <template slot="productBrand" slot-scope="text, record,index">
+        <div style="max-height:126px;overflow-y:scroll;" v-if="!record.productThisList || record.productThisList.length==0">
+          <a-row v-if="record.productBrandArr && record.productBrandArr.length>0">
+            <a-col :span="18">
+              <a-tag v-for="item in record.productBrandArr" :key="item.brandSn" style="margin-bottom:10px;" closable @close.prevent="delLabel(record.productScopeSn,item,'brandList')">
+                {{ item.brandName }}
+              </a-tag>
+            </a-col>
+            <a-col :span="6" style="text-align:right;">
+              <a-tag style="background: #fff; borderStyle: dashed;" @click="addBrandTag(index, record)" color="blue">
+                <a-icon type="plus" />
+              </a-tag>
+            </a-col>
+          </a-row>
+          <a-row v-else>
+            <a-col :span="24">
+              <a-tag style="background: #fff; borderStyle: dashed;" @click="addBrandTag(index, record)" color="blue">
+                <a-icon type="plus" />
+              </a-tag>
+            </a-col>
+          </a-row>
+        </div>
+        <div v-else>
+          <a-tag style="background: #fff; borderStyle: dashed;" :style="{color:'grey',cursor:'not-allowed'}">
+            <a-icon type="plus" />
+          </a-tag>
+        </div>
+      </template>
+      <!-- 产品 -->
+      <template slot="product" slot-scope="text, record,index">
+        <div v-if="(record.productBrandArr && record.productBrandArr.length>0)||(record.productTypeArr && record.productTypeArr.length>0)">
+          <a-tag style="background: #fff; borderStyle: dashed;" :style="{color:'grey',cursor:'not-allowed'}">
+            <a-icon type="plus" />
+          </a-tag>
+        </div>
+        <div style="max-height:126px;overflow-y:scroll;" v-else>
+          <a-row v-if="record.productThisList && record.productThisList.length>0">
+            <a-col :span="18">
+              <a-tag style="margin-bottom:10px;" closable @close.prevent="delLabel(record.productScopeSn,item,'productList')" v-for="item in record.productThisList" :key="item.productSn">
+                {{ item.productCode }}
+              </a-tag>
+            </a-col>
+            <a-col :span="6" style="text-align:right;">
+              <a-tag style="background: #fff; borderStyle: dashed;" @click="addProductTag(index, record)" color="blue">
+                <a-icon type="plus" />
+              </a-tag>
+            </a-col>
+          </a-row>
+          <a-row v-else>
+            <a-col :span="24">
+              <a-tag style="background: #fff; borderStyle: dashed;" @click="addProductTag(index, record)" color="blue">
+                <a-icon type="plus" />
+              </a-tag>
+            </a-col>
+          </a-row>
+        </div>
+      </template>
+      <!-- 操作 -->
+      <span slot="action" slot-scope="text,record">
+        <a-button
+          size="small"
+          type="link"
+          class="button-error"
+          @click="handleDel(record)"
+        >
+          删除
+        </a-button>
+      </span>
+    </a-table>
+    <div class="btn-cont">
+      <a-button id="tableType1-add" type="primary" class="button-gray" @click="handleAddRow">+新增一行</a-button>
+    </div>
+    <!-- 选择产品品牌 -->
+    <chooseBrandModal
+      pageType="1"
+      ref="brandBox"
+      :openModal="openBrandModal"
+      :chooseData="chooseBrand"
+      @close="openBrandModal=false"
+      @ok="handleBrandOk" />
+    <!-- 选择产品分类 -->
+    <chooseTypeModal
+      ref="typeBox"
+      :openModal="openTypeModal"
+      :linkageStatus="false"
+      :chooseData="chooseType"
+      @close="openTypeModal=false"
+      @ok="handleTypeOk" />
+    <!-- 选择产品 -->
+    <chooseProductsModal
+      ref="productBox"
+      type="dealership"
+      :openModal="openProductsModal"
+      :chooseData="chooseProducts"
+      @close="openProductsModal=false"
+      @ok="handleProductsOk" />
+  </div>
+</template>
+
+<script>
+import { commonMixin } from '@/utils/mixin'
+import { VSelect } from '@/components'
+import ChooseBrandModal from '@/views/common/chooseBrandModal.vue'
+import ChooseTypeModal from '@/views/common/chooseTypeModal.vue'
+import chooseProductsModal from './chooseProductsModal.vue'
+import { getNewScopeSn } from '@/api/promotion'
+export default {
+  name: 'TableType1',
+  mixins: [commonMixin],
+  components: { VSelect, ChooseBrandModal, ChooseTypeModal, chooseProductsModal },
+  data () {
+    return {
+      spinning: false,
+      columns: [
+        { title: '产品分类', width: '30%', scopedSlots: { customRender: 'productType' }, align: 'center' },
+        { title: '品牌', width: '30%', scopedSlots: { customRender: 'productBrand' }, align: 'center' },
+        { title: '产品', width: '30%', scopedSlots: { customRender: 'product' }, align: 'center' },
+        { title: '操作', scopedSlots: { customRender: 'action' }, width: '10%', align: 'center' }
+      ],
+      dataSource: [],
+      openBrandModal: false,
+      openTypeModal: false,
+      openProductsModal: false,
+      chooseBrand: [],
+      chooseType: [],
+      brandTagIndex: null, // 所选品牌位置
+      classifyTagIndex: null, // 所选分类位置
+      productTagIndex: null, // 所选产品位置
+      chooseProducts: []
+    }
+  },
+  methods: {
+    // 新增一行
+    handleAddRow () {
+      const _this = this
+      _this.spinning = false
+      getNewScopeSn({}).then(res => {
+        if (res.status == 200) {
+          const newData = {
+            productScopeSn: res.data,
+            productTypeArr: [],
+            productTypeList: [],
+            productBrandArr: [],
+            productBrandList: [],
+            productThisList: []
+          }
+          _this.dataSource.push(newData)
+        } else {
+          _this.spinning = false
+        }
+      })
+    },
+    // 导入新增一行
+    importRow (list) {
+      const _this = this
+      const dataList = _this.setShowData('This')
+      dataList.forEach(item => {
+        const pos = list.indexOf(con => con.productSn == item.goodsSn)
+        list.splice(pos, 1)
+      })
+      if (list.length > 0) {
+        getNewScopeSn({}).then(res => {
+          if (res.status == 200) {
+            const newData = {
+              productScopeSn: res.data,
+              productThisList: list
+            }
+            _this.dataSource.push(newData)
+          } else {
+            _this.spinning = false
+          }
+        })
+      } else {
+        _this.$message.warning('请勿导入重复数据!')
+      }
+    },
+    // 删除一行
+    handleDel (row) {
+      const pos = this.dataSource.findIndex(con => con.productScopeSn == row.productScopeSn)
+      this.dataSource.splice(pos, 1)
+    },
+    // 添加产品分类
+    addClassifyTag (pos, row) {
+      this.classifyTagIndex = pos
+      this.openTypeModal = true
+      this.chooseType = this.handleRowData(row)
+      const getArr = this.setTypeShowData()
+      // 无品牌有分类的选择数据
+      const onlyTypeData = this.onlyType()
+      // 获取品牌重复数据
+      var flag = false
+      var c_typeArr = []
+      this.dataSource.forEach(item => {
+        if ((item.productTypeArr && item.productTypeArr.length > 0) && (item.productBrandList && item.productBrandList.length > 0)) {
+          item.productBrandList.forEach((con) => {
+            row.productBrandList.forEach(newCon => {
+              if (newCon.productBrandSn == con.productBrandSn) {
+                flag = true
+                c_typeArr = c_typeArr.concat(item.productTypeList)
+              }
+            })
+          })
+        }
+      })
+      const disTypeList = []
+      getArr.forEach(con => {
+        c_typeArr.forEach(item => {
+          for (const i in item) {
+            if (item[i] == con.goodsSn) {
+              disTypeList.push(con)
+            }
+          }
+        })
+      })
+      var uniqueArr = [...new Set(disTypeList)]
+
+      if (row.productBrandArr && row.productBrandArr.length == 0) {
+        this.$refs.typeBox.handleAllDisabled(onlyTypeData)
+      } else {
+        if (flag) {
+          this.$refs.typeBox.handleAllDisabled(uniqueArr)
+        } else {
+          this.chooseType = []
+          this.$refs.typeBox.handleAllDisabled([])
+        }
+      }
+    },
+    handleTypeOk (mainArr) {
+      const classifyArr = []
+      const newClassifyArr = []
+      mainArr.forEach(item => {
+        if (item.productTypeLevel == 1) {
+          if ((item.dataRef && !item.dataRef.children) || (!item.dataRef && !item.children)) {
+            const objType1 = {
+              productTypeSn1: item.snPaths
+            }
+            newClassifyArr.push(objType1)
+            const obj = JSON.parse(JSON.stringify(objType1))
+            obj.title = item.title
+            classifyArr.push(obj)
+          }
+        }
+        if (item.productTypeLevel == 2) {
+          if ((item.dataRef && !item.dataRef.children) || (!item.dataRef && !item.children)) {
+            const typeArr1 = item.snPaths ? item.snPaths.split(',') : []
+            const objType2 = {
+              productTypeSn1: typeArr1[0],
+              productTypeSn2: typeArr1[1]
+            }
+            newClassifyArr.push(objType2)
+            const obj = JSON.parse(JSON.stringify(objType2))
+            const newName = item.namePaths.split(',')
+            obj.title = newName[1]
+            classifyArr.push(obj)
+          }
+        }
+        if (item.productTypeLevel == 3) {
+          const typeArr2 = item.snPaths ? item.snPaths.split(',') : []
+          const objType3 = {
+            productTypeSn1: typeArr2[0],
+            productTypeSn2: typeArr2[1],
+            productTypeSn3: typeArr2[2]
+          }
+          newClassifyArr.push(objType3)
+          const obj = JSON.parse(JSON.stringify(objType3))
+          const newName = item.namePaths.split(',')
+          obj.title = newName[1] + '/' + newName[2]
+          obj.id = typeArr2[2]
+          classifyArr.push(obj)
+        }
+      })
+      this.dataSource[this.classifyTagIndex].productTypeList = newClassifyArr
+      this.dataSource[this.classifyTagIndex].productTypeArr = classifyArr
+    },
+    // 添加产品品牌
+    addBrandTag (pos, row) {
+      const _this = this
+      _this.brandTagIndex = pos
+      // 选中的所有品牌
+      const dataList = _this.setShowData('Brand')
+      _this.openBrandModal = true
+      // 回显当前行选中
+      const echoData = _this.handleEchoData('Brand', row.productBrandList)
+      _this.chooseBrand = echoData
+      // 只有品牌没有分类
+      const onlyBrandData = this.onlyBrand()
+      // 同行中分类是否与所选分类相同   已选分类
+      var flag = false
+      var c_brandArr = []
+      this.dataSource.forEach(item => {
+        if ((item.productTypeArr && item.productTypeArr.length > 0) && (item.productBrandList && item.productBrandList.length > 0)) {
+          item.productTypeArr.forEach((con) => {
+            row.productTypeArr.forEach(newCon => {
+              if (newCon.id == con.id) {
+                flag = true
+                c_brandArr = c_brandArr.concat(item.productBrandList)
+              }
+            })
+          })
+        }
+      })
+
+      const reBrandArr = c_brandArr.map(list => {
+        return list.productBrandSn
+      })
+      if (row.productTypeArr && row.productTypeArr.length == 0) {
+        _this.$refs.brandBox.handleDisabled(onlyBrandData)
+      } else {
+        if (flag) { // 当前行有重复分类
+          _this.$refs.brandBox.handleDisabled(reBrandArr)
+        } else {
+          _this.chooseBrand = []
+          _this.$refs.brandBox.handleDisabled([])
+        }
+      }
+    },
+    handleBrandOk (conList) {
+      const newConList = conList.map(con => {
+        return {
+          productBrandSn: con.brandSn
+        }
+      })
+      this.dataSource[this.brandTagIndex].productBrandArr = conList
+      this.dataSource[this.brandTagIndex].productBrandList = newConList
+    },
+    // 添加产品
+    addProductTag (pos, row) {
+      this.productTagIndex = pos
+      this.openProductsModal = true
+      const dataList = this.setShowData('This')
+      const echoData = this.handleEchoData('This', row.productThisList)
+      this.chooseProducts = echoData
+      this.$refs.productBox.handleDisabled(dataList)
+    },
+    handleProductsOk (arr) {
+      const newArr = []
+      arr.forEach(item => {
+        const obj = {
+          productCode: item.code,
+          productSn: item.productSn
+        }
+        newArr.push(obj)
+      })
+      this.dataSource[this.productTagIndex].productThisList = newArr
+    },
+    // 获取回显禁用数据
+    setShowData (name) {
+      const _this = this
+      const snArr = []
+      _this.dataSource.forEach(item => {
+        if (item['product' + name + 'List'] && item['product' + name + 'List'].length > 0) {
+          item['product' + name + 'List'].forEach(con => {
+            const newName = name === 'This' ? '' : name
+            snArr.push(con['product' + newName + 'Sn'])
+          })
+        }
+      })
+      return snArr
+    },
+    // 只有分类
+    onlyType (name, onlyName) {
+      const _this = this
+      const snArr = []
+      _this.dataSource.forEach(item => {
+        if (item.productTypeList && item.productTypeList.length > 0) {
+          if (!item.productBrandList || (item.productBrandList && item.productBrandList.length == 0)) {
+            item.productTypeList.forEach(con => {
+              for (const i in con) {
+                const newObj = {
+                  goodsSn: con[i]
+                }
+                if (i === 'productTypeSn1') {
+                  newObj.disabled = true
+                } else {
+                  newObj.disableCheckbox = true
+                }
+                snArr.push(newObj)
+              }
+            })
+          }
+        }
+      })
+      return snArr
+    },
+    // 只有品牌
+    onlyBrand () {
+      const _this = this
+      var snArr = []
+      _this.dataSource.forEach(item => {
+        if (item.productBrandList && item.productBrandList.length > 0) {
+          if (!item.productTypeArr || (item.productTypeArr && item.productTypeArr.length == 0)) {
+            item.productBrandList.forEach(con => {
+              snArr.push(con.productBrandSn)
+            })
+          }
+        }
+      })
+      return snArr
+    },
+    handleEchoData (name, conArr) {
+      if (conArr) {
+        conArr.map(item => {
+          if (name === 'This') {
+            item.code = item.productCode
+            item.goodsSn = item.productSn
+          } else {
+            item.goodsSn = item['product' + name + 'Sn']
+          }
+        })
+      } else {
+        conArr = []
+      }
+      return conArr
+    },
+    handleRowData (row) {
+      const echoData = []
+      row.productTypeList.forEach(item => {
+        for (const i in item) {
+          const newObj = {
+            goodsSn: item[i]
+          }
+          if (i === 'productTypeSn1') {
+            newObj.disabled = true
+          } else {
+            newObj.disableCheckbox = true
+          }
+          echoData.push(newObj)
+        }
+      })
+      return echoData
+    },
+    setTypeShowData () {
+      const _this = this
+      const snArr = []
+      _this.dataSource.forEach(item => {
+        if (item.productTypeList && item.productTypeList.length > 0) {
+          item.productTypeList.forEach(con => {
+            for (const i in con) {
+              const newObj = {
+                goodsSn: con[i]
+              }
+              if (i === 'productTypeSn1') {
+                newObj.disabled = true
+              } else {
+                newObj.disableCheckbox = true
+              }
+              snArr.push(newObj)
+            }
+          })
+        }
+      })
+      return snArr
+    },
+    // 获取表格数据
+    getResultVal () {
+      const resultObj = JSON.parse(JSON.stringify(this.dataSource))
+      resultObj.map(item => {
+        delete item.productTypeArr
+        delete item.productBrandArr
+        return item
+      })
+      return resultObj
+    },
+    setTabVal (formData) {
+      this.dataSource = formData
+    },
+    // 关闭时清空表格数据
+    reSetTableData () {
+      this.dataSource = []
+    },
+    // 删除标签
+    delLabel (sn, row, type) {
+      const pos = this.dataSource.findIndex(con => con.productScopeSn == sn)
+      if (type === 'typeList') {
+      // 判断品牌是否有重复 重复值有无分类
+        const isRepeatBrandFlag = this.isRepeatBrand(this.dataSource[pos])
+        const uniqueArr1 = this.dataSource[pos].productTypeList && this.dataSource[pos].productTypeList.length > 0 ? this.dataSource[pos].productTypeList : []
+        if (isRepeatBrandFlag.flag && isRepeatBrandFlag.noTypeFlag && uniqueArr1.length == 1) {
+          this.dataSource.splice(pos, 1)
+        } else {
+          const i = this.dataSource[pos].productTypeArr.findIndex(con => con.id == row.id)
+          this.dataSource[pos].productTypeArr.splice(i, 1)
+          this.dataSource[pos].productTypeList.splice(i, 1)
+        }
+      } else if (type === 'brandList') {
+        const isRepeatTypeFlag = this.isRepeatType(this.dataSource[pos])
+        const uniqueArr = this.dataSource[pos].productBrandList && this.dataSource[pos].productBrandList.length > 0 ? this.dataSource[pos].productBrandList : []
+        if (isRepeatTypeFlag.flag && isRepeatTypeFlag.noTypeFlag && uniqueArr.length == 1) {
+          this.dataSource.splice(pos, 1)
+        } else {
+          const j = this.dataSource[pos].productBrandArr.findIndex(con => con.brandSn == row.brandSn)
+          this.dataSource[pos].productBrandArr.splice(j, 1)
+          this.dataSource[pos].productBrandList.splice(j, 1)
+        }
+      } else {
+        const k = this.dataSource[pos].productThisList.findIndex(con => con.productSn == row.productSn)
+        this.dataSource[pos].productThisList.splice(k, 1)
+      }
+      this.$forceUpdate()
+    },
+    // 判断当前行是否有重复品牌
+    isRepeatBrand (row) {
+      var flag = false
+      var noTypeFlag = false
+      var c_typeArr = []
+      this.dataSource.forEach(item => {
+        if (item.productBrandList && item.productBrandList.length > 0) {
+          item.productBrandList.forEach((con) => {
+            row.productBrandList.forEach(newCon => {
+              if (newCon.productBrandSn == con.productBrandSn) {
+                flag = true
+                if (item.productTypeList && item.productTypeList.length == 0) {
+                  noTypeFlag = true
+                } else {
+                  c_typeArr = c_typeArr.concat(item.productTypeList)
+                }
+              }
+            })
+          })
+        }
+      })
+      return { list: c_typeArr, flag: flag, noTypeFlag: noTypeFlag }
+    },
+    isRepeatType (row) {
+      var flag = false
+      var noTypeFlag = false
+      var c_brandArr = []
+      this.dataSource.forEach(item => {
+        if (item.productTypeArr && item.productTypeArr.length > 0) {
+          item.productTypeArr.forEach((con) => {
+            row.productTypeArr.forEach(newCon => {
+              if (newCon.id == con.id) {
+                flag = true
+                if (item.productBrandList && item.productBrandList.length == 0) {
+                  noTypeFlag = true
+                } else {
+                  c_brandArr = c_brandArr.concat(item.productBrandList)
+                }
+              }
+            })
+          })
+        }
+      })
+      return { list: c_brandArr, flag: flag, noTypeFlag: noTypeFlag }
+    }
+  }
+}
+</script>
+
+<style lang="less" scoped>
+  .pages-wrap{
+    .btn-cont {
+      text-align: center;
+      margin: 10px 0;
+    }
+  }
+
+</style>

+ 675 - 0
src/views/promotionRulesManagement/dealerPromotions/tableType3.vue

@@ -0,0 +1,675 @@
+<template>
+  <div class="pages-wrap">
+    <!-- 列表 -->
+    <a-table
+      class="sTable"
+      style="margin-top:10px;width:100%;"
+      ref="table"
+      size="small"
+      :pagination="false"
+      :rowKey="(record) => record.productScopeSn"
+      :columns="columns"
+      :data-source="dataSource"
+      bordered>
+      <!-- 产品分类 -->
+      <template slot="productType" slot-scope="text, record,index">
+        <div style="max-height:126px;width:100%;overflow-y:scroll;" v-if="record.dataSourceOrigin=='0'">
+          <a-row v-if="record.productTypeArr && record.productTypeArr.length>0">
+            <a-col :span="17">
+              <div v-for="con in record.productTypeArr" :key="con.id">
+                <a-tooltip v-if="con.title&&con.title.length > 7" :title="con.title">
+                  <a-tag style="margin-bottom:10px;" closable @close.prevent="delLabel(record.productScopeSn,con,'typeList')">
+                    {{ `${con.title.slice(0, 7)}...` }}
+                  </a-tag>
+                </a-tooltip>
+                <a-tag v-else style="margin-bottom:10px;" closable @close.prevent="delLabel(record.productScopeSn,con,'typeList')">
+                  {{ con.title }}
+                </a-tag>
+              </div>
+            </a-col>
+            <a-col :span="6" style="text-align:right;">
+              <a-tag style="background: #fff; borderStyle: dashed;" @click="addClassifyTag(index, record)" color="blue">
+                <a-icon type="plus" />
+              </a-tag>
+            </a-col>
+          </a-row>
+          <a-row v-else>
+            <a-col :span="24">
+              <a-tag style="background: #fff; borderStyle: dashed;" @click="addClassifyTag(index, record)" color="blue">
+                <a-icon type="plus" />
+              </a-tag>
+            </a-col>
+          </a-row>
+        </div>
+        <span v-else v-for="con in record.productTypeArr" :key="con.id">{{ con.title }}</span>
+      </template>
+      <!-- 品牌 -->
+      <template slot="productBrand" slot-scope="text, record,index">
+        <div style="max-height:126px;overflow-y:scroll;" v-if="record.dataSourceOrigin=='0'">
+          <a-row v-if="record.productBrandArr && record.productBrandArr.length>0">
+            <a-col :span="17">
+              <div v-for="item in record.productBrandArr" :key="item.brandSn">
+                <a-tooltip v-if="item.brandName&&item.brandName.length > 7" :title="item.brandName">
+                  <a-tag style="margin-bottom:10px;" closable @close.prevent="delLabel(record.productScopeSn,item,'brandList')">
+                    {{ `${item.brandName.slice(0, 7)}...` }}
+                  </a-tag>
+                </a-tooltip>
+                <a-tag v-else style="margin-bottom:10px;" closable @close.prevent="delLabel(record.productScopeSn,item,'brandList')">
+                  {{ item.brandName }}
+                </a-tag>
+              </div>
+            </a-col>
+
+            <a-col :span="6" style="text-align:right;">
+              <a-tag style="background: #fff; borderStyle: dashed;" @click="addBrandTag(index, record)" color="blue">
+                <a-icon type="plus" />
+              </a-tag>
+            </a-col>
+          </a-row>
+          <a-row v-else>
+            <a-col :span="24">
+              <a-tag style="background: #fff; borderStyle: dashed;" @click="addBrandTag(index, record)" color="blue">
+                <a-icon type="plus" />
+              </a-tag>
+            </a-col>
+          </a-row>
+        </div>
+        <span v-else v-for="item in record.productBrandArr" :key="item.brandSn">{{ item.brandName }}</span>
+      </template>
+      <!-- 产品 -->
+      <template slot="product" slot-scope="text, record">
+        <span v-if="record.dataSourceOrigin=='1'" v-for="item in record.productThisList" :key="item.productSn">{{ item.productCode }}</span>
+        <span v-else>--</span>
+      </template>
+      <!-- 省价特价 -->
+      <template slot="provincePrice" slot-scope="text, record">
+        <div v-if="record.dataSourceOrigin=='1'">
+          <a-input-number
+            size="small"
+            style="width:90%;"
+            v-model="record.provinceDiscountPrice"
+            :min="0"
+            :step="1"
+            :precision="2"
+            placeholder="请输入"
+            :max="999999"
+            @blur="e=>calculatePrice(e.target.value,record.productScopeSn,'province')"/>
+        </div>
+        <span v-else>--</span>
+      </template>
+      <!-- 省价折扣 -->
+      <template slot="provinceDiscount" slot-scope="text, record">
+        <div v-if="record.dataSourceOrigin=='0'">
+          <a-input
+            v-model="record.provinceDiscountRate"
+            style="width:80%;"
+            type="number"
+            @input="record.provinceDiscountRate=record.provinceDiscountRate.match(/^\d{1,4}(\.?\d{0,2})/g) ? record.provinceDiscountRate.match(/^\d{1,4}(\.?\d{0,2})/g)[0] : ''"
+            :min="0"
+            placeholder="请输入"
+            size="small"/>%
+        </div>
+        <span v-else>{{ (record.provinceDiscountRate||record.provinceDiscountRate==0)?record.provinceDiscountRate+'%':'--' }}</span>
+      </template>
+      <!-- 市价特价 -->
+      <template slot="cityPrice" slot-scope="text, record">
+        <div v-if="record.dataSourceOrigin=='1'">
+          <a-input-number
+            size="small"
+            style="width:90%;"
+            v-model="record.cityDiscountPrice"
+            :min="0"
+            :step="1"
+            :precision="2"
+            placeholder="请输入"
+            :max="999999"
+            @blur="e=>calculatePrice(e.target.value,record.productScopeSn,'city')"/>
+        </div>
+        <span v-else>--</span>
+      </template>
+      <!-- 市价折扣 -->
+      <template slot="cityDiscount" slot-scope="text, record">
+        <div v-if="record.dataSourceOrigin=='0'">
+          <a-input
+            v-model="record.cityDiscountRate"
+            style="width:80%;"
+            type="number"
+            placeholder="请输入"
+            @input="record.cityDiscountRate=record.cityDiscountRate.match(/^\d{1,4}(\.?\d{0,2})/g) ? record.cityDiscountRate.match(/^\d{1,4}(\.?\d{0,2})/g)[0] : ''"
+            :min="0"
+            size="small"/>%
+        </div>
+        <span v-else>{{ (record.cityDiscountRate||record.cityDiscountRate==0)?record.cityDiscountRate+'%':'--' }}</span>
+      </template>
+      <!-- 特约特价 -->
+      <template slot="specialPrice" slot-scope="text, record">
+        <div v-if="record.dataSourceOrigin=='1'">
+          <a-input-number
+            size="small"
+            style="width:90%;"
+            v-model="record.specialDiscountPrice"
+            :min="0"
+            :step="1"
+            :precision="2"
+            placeholder="请输入"
+            :max="999999"
+            @blur="e=>calculatePrice(e.target.value,record.productScopeSn,'special')"/>
+        </div>
+        <span v-else>--</span>
+      </template>
+      <!-- 特约折扣 -->
+      <template slot="specialDiscount" slot-scope="text, record">
+        <div v-if="record.dataSourceOrigin=='0'">
+          <a-input
+            v-model="record.specialDiscountRate"
+            style="width:80%;"
+            type="number"
+            @input="record.specialDiscountRate=record.specialDiscountRate.match(/^\d{1,4}(\.?\d{0,2})/g) ? record.specialDiscountRate.match(/^\d{1,4}(\.?\d{0,2})/g)[0] : ''"
+            :min="0"
+            placeholder="请输入"
+            step="0.01"
+            size="small"/>%
+        </div>
+        <span v-else>{{ (record.specialDiscountRate||record.specialDiscountRate==0) ? record.specialDiscountRate+'%':'--' }}</span>
+      </template>
+      <!-- 设置起订量 -->
+      <template slot="setNum" slot-scope="text, record">
+        <v-select
+          v-model="record.unitType"
+          size="small"
+          ref="returnReason"
+          code="SCOPE_UNIT_TYPE"
+          style="width:100%;"
+          placeholder="请选择"
+          allowClear></v-select>
+        <a-input-number
+          size="small"
+          style="margin-top:8px;width:100%;"
+          v-model="record.unitQty"
+          :min="0"
+          :step="1"
+          :precision="0"
+          :max="999999"
+          placeholder="请输入"/>
+      </template>
+      <span slot="action" slot-scope="text,record">
+        <a-button
+          size="small"
+          type="link"
+          class="button-error"
+          @click="handleDel(record)"
+        >
+          删除
+        </a-button>
+      </span>
+    </a-table>
+    <div class="btn-cont">
+      <a-button id="tableType1-add" type="primary" class="button-gray" @click="handleAddRow">+新增一行</a-button>
+    </div>
+    <!-- 选择产品品牌 -->
+    <chooseBrandModal
+      pageType="1"
+      ref="brandBox"
+      :openModal="openBrandModal"
+      :chooseData="chooseBrand"
+      @close="openBrandModal=false"
+      @ok="handleBrandOk" />
+    <!-- 选择产品分类 -->
+    <chooseTypeModal
+      ref="typeBox"
+      :openModal="openTypeModal"
+      :linkageStatus="false"
+      :chooseData="chooseType"
+      @close="openTypeModal=false"
+      @ok="handleTypeOk" />
+  </div>
+</template>
+
+<script>
+import { commonMixin } from '@/utils/mixin'
+import { VSelect } from '@/components'
+import ChooseBrandModal from '@/views/common/chooseBrandModal.vue'
+import ChooseTypeModal from '@/views/common/chooseTypeModal.vue'
+import { getNewScopeSn } from '@/api/promotion'
+export default {
+  name: 'TableType3',
+  mixins: [commonMixin],
+  components: { VSelect, ChooseBrandModal, ChooseTypeModal },
+  props: {
+    itemSn: {
+      type: [Number, String],
+      default: ''
+    }
+  },
+  data () {
+    const _this = this
+    return {
+      spinning: false,
+      columns: [
+        { title: '产品分类', width: '16%', scopedSlots: { customRender: 'productType' }, align: 'center' },
+        { title: '品牌', width: '16%', scopedSlots: { customRender: 'productBrand' }, align: 'center' },
+        { title: '产品', scopedSlots: { customRender: 'product' }, width: '10%', align: 'center' },
+        { title: '省级原价', dataIndex: 'provincePrice', width: '5%', align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } },
+        { title: '省级特价', scopedSlots: { customRender: 'provincePrice' }, width: '5%', align: 'center' },
+        { title: '省级折扣', scopedSlots: { customRender: 'provinceDiscount' }, width: '5%', align: 'center' },
+        { title: '市级原价', dataIndex: 'cityPrice', width: '5%', align: 'center', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } },
+        { title: '市级特价', scopedSlots: { customRender: 'cityPrice' }, width: '5%', align: 'center' },
+        { title: '市级折扣', scopedSlots: { customRender: 'cityDiscount' }, width: '5%', align: 'center' },
+        { title: '特约原价', dataIndex: 'specialPrice', width: '5%', align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } },
+        { title: '特约特价', scopedSlots: { customRender: 'specialPrice' }, width: '5%', align: 'center' },
+        { title: '特约折扣', scopedSlots: { customRender: 'specialDiscount' }, width: '5%', align: 'center' },
+        { title: '设置起订量', width: '7%', scopedSlots: { customRender: 'setNum' }, align: 'center' },
+        { title: '操作', scopedSlots: { customRender: 'action' }, width: '6%', align: 'center' }
+      ],
+      dataSource: [],
+      openBrandModal: false,
+      openTypeModal: false,
+      chooseBrand: [],
+      chooseType: [],
+      val: '',
+      brandTagIndex: null, // 所选品牌位置
+      classifyTagIndex: null, // 所选分类位置
+      dataSourceOrigin: 0 // 数据来源  1  选择产品  0 新增一行品类
+    }
+  },
+  methods: {
+    // 计算百分比
+    calculatePrice (val, sn, typePrice) {
+      const _this = this
+      const pos = _this.dataSource.findIndex(con => con.productScopeSn == sn)
+      const oldPrice = typePrice + 'Price'
+      const str = ((val / _this.dataSource[pos][oldPrice]) * 100).toFixed(2)
+      const name = typePrice + 'DiscountRate'
+      _this.dataSource[pos][name] = str
+      _this.$forceUpdate()
+    },
+    // 新增产品 数据
+    setSourceData (list) {
+      this.dataSource = this.dataSource.concat(list)
+    },
+    // 新增一行
+    handleAddRow () {
+      const _this = this
+      _this.spinning = false
+      getNewScopeSn({}).then(res => {
+        if (res.status == 200) {
+          const newData = {
+            productScopeSn: res.data,
+            dataSourceOrigin: '0',
+            productTypeArr: [],
+            productTypeList: [],
+            productBrandArr: [],
+            productBrandList: [],
+            unitType: 'SL',
+            unitQty: 1
+          }
+          _this.dataSource.push(newData)
+        } else {
+          _this.spinning = false
+        }
+      })
+    },
+    // 删除一行
+    handleDel (row) {
+      const pos = this.dataSource.findIndex(con => con.productScopeSn == row.productScopeSn)
+      this.dataSource.splice(pos, 1)
+    },
+    // 添加产品分类
+    addClassifyTag (pos, row) {
+      this.classifyTagIndex = pos
+      this.openTypeModal = true
+      this.chooseType = this.handleRowData(row)
+      const getArr = this.setTypeShowData()
+      // 无品牌有分类的选择数据
+      const onlyTypeData = this.onlyType()
+      // 获取品牌重复数据
+      var flag = false
+      var c_typeArr = []
+      this.dataSource.forEach(item => {
+        if (item.dataSourceOrigin === '0') {
+          if ((item.productTypeArr && item.productTypeArr.length > 0) && (item.productBrandList && item.productBrandList.length > 0)) {
+            item.productBrandList.forEach((con) => {
+              row.productBrandList.forEach(newCon => {
+                if (newCon.productBrandSn == con.productBrandSn) {
+                  flag = true
+                  c_typeArr = c_typeArr.concat(item.productTypeList)
+                }
+              })
+            })
+          }
+        }
+      })
+      const disTypeList = []
+      getArr.forEach(con => {
+        c_typeArr.forEach(item => {
+          for (const i in item) {
+            if (item[i] == con.goodsSn) {
+              disTypeList.push(con)
+            }
+          }
+        })
+      })
+      var uniqueArr = [...new Set(disTypeList)]
+
+      if (row.productBrandArr && row.productBrandArr.length == 0) {
+        this.$refs.typeBox.handleAllDisabled(onlyTypeData)
+      } else {
+        if (flag) {
+          this.$refs.typeBox.handleAllDisabled(uniqueArr)
+        } else {
+          this.chooseType = []
+          this.$refs.typeBox.handleAllDisabled([])
+        }
+      }
+    },
+    handleTypeOk (mainArr) {
+      const classifyArr = []
+      const newClassifyArr = []
+      mainArr.forEach(item => {
+        if (item.productTypeLevel == 1) {
+          if ((item.dataRef && !item.dataRef.children) || (!item.dataRef && !item.children)) {
+            const objType1 = {
+              productTypeSn1: item.snPaths
+            }
+            newClassifyArr.push(objType1)
+            const obj = JSON.parse(JSON.stringify(objType1))
+            obj.title = item.title
+            obj.id = item.snPaths
+            classifyArr.push(obj)
+          }
+        }
+        if (item.productTypeLevel == 2) {
+          if ((item.dataRef && !item.dataRef.children) || (!item.dataRef && !item.children)) {
+            const typeArr1 = item.snPaths ? item.snPaths.split(',') : []
+            const objType2 = {
+              productTypeSn1: typeArr1[0],
+              productTypeSn2: typeArr1[1]
+            }
+            newClassifyArr.push(objType2)
+            const obj = JSON.parse(JSON.stringify(objType2))
+            const newName = item.namePaths.split(',')
+            obj.title = newName[1]
+            obj.id = typeArr1[1]
+            classifyArr.push(obj)
+          }
+        }
+        if (item.productTypeLevel == 3) {
+          const typeArr2 = item.snPaths ? item.snPaths.split(',') : []
+          const objType3 = {
+            productTypeSn1: typeArr2[0],
+            productTypeSn2: typeArr2[1],
+            productTypeSn3: typeArr2[2]
+          }
+          newClassifyArr.push(objType3)
+          const obj = JSON.parse(JSON.stringify(objType3))
+          const newName = item.namePaths.split(',')
+          obj.title = newName[1] + '/' + newName[2]
+          obj.id = typeArr2[2]
+          classifyArr.push(obj)
+        }
+      })
+      this.dataSource[this.classifyTagIndex].productTypeList = newClassifyArr
+      this.dataSource[this.classifyTagIndex].productTypeArr = classifyArr
+    },
+    // 添加产品品牌
+    addBrandTag (pos, row) {
+      const _this = this
+      _this.brandTagIndex = pos
+      _this.openBrandModal = true
+      // 回显当前行选中
+      const echoData = _this.handleEchoData('Brand', row.productBrandList)
+      _this.chooseBrand = echoData
+      // 只有品牌没有分类
+      const onlyBrandData = this.onlyBrand()
+      // 同行中分类是否与所选分类相同   已选分类
+      var flag = false
+      var c_brandArr = []
+      this.dataSource.forEach(item => {
+        if (item.dataSourceOrigin === '0') {
+          if ((item.productTypeArr && item.productTypeArr.length > 0) && (item.productBrandList && item.productBrandList.length > 0)) {
+            item.productTypeArr.forEach((con) => {
+              row.productTypeArr.forEach(newCon => {
+                if (newCon.id == con.id) {
+                  flag = true
+                  c_brandArr = c_brandArr.concat(item.productBrandList)
+                }
+              })
+            })
+          }
+        }
+      })
+      const reBrandArr = c_brandArr.map(list => {
+        return list.productBrandSn
+      })
+      if (row.productTypeArr && row.productTypeArr.length == 0) {
+        _this.$refs.brandBox.handleDisabled(onlyBrandData)
+      } else {
+        if (flag) { // 当前行有重复分类
+          _this.$refs.brandBox.handleDisabled(reBrandArr)
+        } else {
+          _this.chooseBrand = []
+          _this.$refs.brandBox.handleDisabled([])
+        }
+      }
+    },
+    handleBrandOk (conList) {
+      const newConList = conList.map(con => {
+        return {
+          productBrandSn: con.brandSn
+        }
+      })
+      this.dataSource[this.brandTagIndex].productBrandArr = conList
+      this.dataSource[this.brandTagIndex].productBrandList = newConList
+    },
+    // 获取回显禁用数据
+    setShowData (name) {
+      const _this = this
+      const snArr = []
+      _this.dataSource.forEach(item => {
+        if (item['product' + name + 'List'] && item['product' + name + 'List'].length > 0) {
+          item['product' + name + 'List'].forEach(con => {
+            const newName = name === 'This' ? '' : name
+            snArr.push(con['product' + newName + 'Sn'])
+          })
+        }
+      })
+      return snArr
+    },
+    // 只有分类
+    onlyType (name, onlyName) {
+      const _this = this
+      const snArr = []
+      _this.dataSource.forEach(item => {
+        if (item.dataSourceOrigin === '0') {
+          if (item.productTypeList && item.productTypeList.length > 0) {
+            if (!item.productBrandList || (item.productBrandList && item.productBrandList.length == 0)) {
+              item.productTypeList.forEach(con => {
+                for (const i in con) {
+                  const newObj = {
+                    goodsSn: con[i]
+                  }
+                  if (i === 'productTypeSn1') {
+                    newObj.disabled = true
+                  } else {
+                    newObj.disableCheckbox = true
+                  }
+                  snArr.push(newObj)
+                }
+              })
+            }
+          }
+        }
+      })
+      return snArr
+    },
+    // 只有品牌
+    onlyBrand () {
+      const _this = this
+      var snArr = []
+      _this.dataSource.forEach(item => {
+        if (item.dataSourceOrigin === '0') {
+          if (item.productBrandList && item.productBrandList.length > 0) {
+            if (!item.productTypeArr || (item.productTypeArr && item.productTypeArr.length == 0)) {
+              item.productBrandList.forEach(con => {
+                snArr.push(con.productBrandSn)
+              })
+            }
+          }
+        }
+      })
+      return snArr
+    },
+    handleEchoData (name, conArr) {
+      conArr.map(item => {
+        if (name === 'This') {
+          item.code = item.productCode
+          item.goodsSn = item.productSn
+        } else {
+          item.goodsSn = item['product' + name + 'Sn']
+        }
+      })
+      return conArr
+    },
+    handleRowData (row) {
+      const echoData = []
+      row.productTypeList.forEach(item => {
+        for (const i in item) {
+          const newObj = {
+            goodsSn: item[i]
+          }
+          if (i === 'productTypeSn1') {
+            newObj.disabled = true
+          } else {
+            newObj.disableCheckbox = true
+          }
+          echoData.push(newObj)
+        }
+      })
+      return echoData
+    },
+    setTypeShowData () {
+      const _this = this
+      const snArr = []
+      _this.dataSource.forEach(item => {
+        if (item.dataSourceOrigin === '0') {
+          if (item.productTypeList && item.productTypeList.length > 0) {
+            item.productTypeList.forEach(con => {
+              for (const i in con) {
+                const newObj = {
+                  goodsSn: con[i]
+                }
+                if (i === 'productTypeSn1') {
+                  newObj.disabled = true
+                } else {
+                  newObj.disableCheckbox = true
+                }
+                snArr.push(newObj)
+              }
+            })
+          }
+        }
+      })
+      return snArr
+    },
+    // 获取最后结果
+    getResultVal () {
+      const resultObj = JSON.parse(JSON.stringify(this.dataSource))
+      resultObj.map(item => {
+        delete item.productTypeArr
+        delete item.productBrandArr
+        return item
+      })
+      return resultObj
+    },
+    // 关闭时清空表格数据
+    reSetTableData () {
+      this.dataSource = []
+    },
+    // 删除标签
+    delLabel (sn, row, type) {
+      const pos = this.dataSource.findIndex(con => con.productScopeSn == sn)
+      if (type === 'typeList') {
+        // 判断品牌是否有重复 重复值有无分类
+        const isRepeatBrandFlag = this.isRepeatBrand(this.dataSource[pos])
+        const uniqueArr1 = this.dataSource[pos].productTypeList && this.dataSource[pos].productTypeList.length > 0 ? this.dataSource[pos].productTypeList : []
+        if (isRepeatBrandFlag.flag && isRepeatBrandFlag.noTypeFlag && uniqueArr1.length == 1) {
+          this.dataSource.splice(pos, 1)
+        } else {
+          const i = this.dataSource[pos].productTypeArr.findIndex(con => con.id == row.id)
+          this.dataSource[pos].productTypeArr.splice(i, 1)
+          this.dataSource[pos].productTypeList.splice(i, 1)
+        }
+      } else if (type === 'brandList') {
+        const isRepeatTypeFlag = this.isRepeatType(this.dataSource[pos])
+        const uniqueArr = this.dataSource[pos].productBrandList && this.dataSource[pos].productBrandList.length > 0 ? this.dataSource[pos].productBrandList : []
+        if (isRepeatTypeFlag.flag && isRepeatTypeFlag.noTypeFlag && uniqueArr.length == 1) {
+          this.dataSource.splice(pos, 1)
+        } else {
+          const j = this.dataSource[pos].productBrandArr.findIndex(con => con.brandSn == row.brandSn)
+          this.dataSource[pos].productBrandArr.splice(j, 1)
+          this.dataSource[pos].productBrandList.splice(j, 1)
+        }
+      } else {
+        const k = this.dataSource[pos].productThisList.findIndex(con => con.productSn == row.productSn)
+        this.dataSource[pos].productThisList.splice(k, 1)
+      }
+      this.$forceUpdate()
+    },
+    // 判断当前行是否有重复品牌
+    isRepeatBrand (row) {
+      var flag = false
+      var noTypeFlag = false
+      var c_typeArr = []
+      this.dataSource.forEach(item => {
+        if (item.productBrandList && item.productBrandList.length > 0) {
+          item.productBrandList.forEach((con) => {
+            row.productBrandList.forEach(newCon => {
+              if (newCon.productBrandSn == con.productBrandSn) {
+                flag = true
+                if (item.productTypeList && item.productTypeList.length == 0) {
+                  noTypeFlag = true
+                } else {
+                  c_typeArr = c_typeArr.concat(item.productTypeList)
+                }
+              }
+            })
+          })
+        }
+      })
+      return { list: c_typeArr, flag: flag, noTypeFlag: noTypeFlag }
+    },
+    isRepeatType (row) {
+      var flag = false
+      var noTypeFlag = false
+      var c_brandArr = []
+      this.dataSource.forEach(item => {
+        if (item.productTypeArr && item.productTypeArr.length > 0) {
+          item.productTypeArr.forEach((con) => {
+            row.productTypeArr.forEach(newCon => {
+              if (newCon.id == con.id) {
+                flag = true
+                if (item.productBrandList && item.productBrandList.length == 0) {
+                  noTypeFlag = true
+                } else {
+                  c_brandArr = c_brandArr.concat(item.productBrandList)
+                }
+              }
+            })
+          })
+        }
+      })
+      return { list: c_brandArr, flag: flag, noTypeFlag: noTypeFlag }
+    }
+  }
+}
+</script>
+
+<style lang="less" scoped>
+  .pages-wrap{
+    .btn-cont {
+      text-align: center;
+      margin: 10px 0;
+    }
+  }
+
+</style>

+ 31 - 16
src/views/promotionRulesManagement/promotionManagement/chooseDealer.vue

@@ -4,6 +4,11 @@
     <div ref="tableSearch" class="table-page-search-wrapper newTableSearchName">
       <a-form layout="inline" @keyup.enter.native="$refs.table.refresh(true)">
         <a-row :gutter="15">
+          <a-col :md="8" :sm="24" v-if="pageType=='dealerPromotion'">
+            <a-form-model-item label="地区">
+              <AreaList id="viewDealers-areaList" changeOnSelect ref="areaList" @change="areaChange" defValKey="id"></AreaList>
+            </a-form-model-item>
+          </a-col>
           <a-col :md="8" :sm="24">
             <a-form-item label="经销商名称/别名">
               <a-input id="chooseDealer-nameLike" v-model.trim="queryParam.nameLike" allowClear placeholder="请输入经销商名称/别名"/>
@@ -60,7 +65,11 @@
       :columns="columns"
       :data-source="dealerList"
       @change="handlePage"
-    ></a-table>
+    >
+      <template slot="addressInfo" slot-scope="text, record">
+        {{ record.provinceName }}{{ '-'+ record.cityName }}{{ '-'+ record.districtName }}
+      </template>
+    </a-table>
   </a-spin>
 </template>
 
@@ -104,19 +113,12 @@ export default {
       },
       pagination: {
         pageSize: 20,
-        showSizeChanger: true
+        showSizeChanger: true,
+        pageSizeOptions: ['20','50','100','200','500']
       },
       pageFlag: false,
       chooseInfo: [],
       selectedRowKeys: [],
-      columns: [
-        { title: '经销商名称', dataIndex: 'dealerName', width: '30%', align: 'center', customRender: function (text) { return text || '--' }, ellipsis: true },
-        { title: '商户别名', dataIndex: 'dealerAlias', align: 'left', width: '30%', customRender: function (text) { return text || '--' }, ellipsis: true },
-        { title: '商户类型', dataIndex: 'dealerTypeDictValue', width: '15%', align: 'center', customRender: function (text) { return text || '--' } },
-        { title: '商户级别', dataIndex: 'dealerLevelDictValue', width: '15%', align: 'center', customRender: function (text) { return text || '--' } },
-        { title: '所在区域', dataIndex: 'subareaArea.subareaName', width: '20%', align: 'center', customRender: function (text) { return text || '--' } },
-        { title: '所在分区', dataIndex: 'subareaArea.subareaAreaName', width: '20%', align: 'center', customRender: function (text) { return text || '--' } }
-      ],
       dealerList: [],
       tableHeight: 0,
       disabled: false, //  查询、重置按钮是否可操作
@@ -126,6 +128,20 @@ export default {
   computed: {
     selectCount () {
       return this.selectedRowKeys && this.selectedRowKeys.length
+    },
+    columns () {
+      const arr = [
+        { title: '经销商名称', dataIndex: 'dealerName', width: '30%', align: 'center', customRender: function (text) { return text || '--' }, ellipsis: true },
+        { title: '商户别名', dataIndex: 'dealerAlias', align: 'left', width: '30%', customRender: function (text) { return text || '--' }, ellipsis: true },
+        { title: '商户类型', dataIndex: 'dealerTypeDictValue', width: '15%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '商户级别', dataIndex: 'dealerLevelDictValue', width: '15%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '所在区域', dataIndex: 'subareaArea.subareaName', width: '20%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '所在分区', dataIndex: 'subareaArea.subareaAreaName', width: '20%', align: 'center', customRender: function (text) { return text || '--' } }
+      ]
+      if (this.pageType === 'dealerPromotion') {
+        arr.unshift({ title: '地区', scopedSlots: { customRender: 'addressInfo' }, width: '30%', align: 'center', ellipsis: true })
+      }
+      return arr
     }
   },
   methods: {
@@ -155,7 +171,7 @@ export default {
           }
           this.dealerList = data.list
           this.pagination = pagination
-          if (this.chooseInfo && !this.pageFlag) {
+          if (this.chooseInfo.length > 0 && !this.pageFlag) {
             this.pageFlag = true
             this.selectedRowKeys = this.chooseInfo
           }
@@ -197,6 +213,9 @@ export default {
       }
       if (this.pageType != 'viewDealers') {
         this.$refs.subarea.clearData()
+        if (this.pageType == 'dealerPromotion') {
+          this.$refs.areaList.clearData()
+        }
       } else {
         this.$refs.areaList.clearData()
       }
@@ -205,14 +224,9 @@ export default {
         showSizeChanger: true,
         current: 1
       }
-      this.selectedRowKeys = []
       this.loadData()
       this.pageFlag = false
     },
-    clearTable () {
-      this.rowSelectionInfo = null
-      this.$refs.table.clearTable()
-    },
     // 批量添加
     async handleBatchAudit () {
       const _this = this
@@ -246,6 +260,7 @@ export default {
       this.$nextTick(() => { // 页面渲染完成后的回调
         _this.setTableH()
       })
+      this.selectedRowKeys = []
       this.chooseInfo = data || []
       this.resetSearchForm()
     },

+ 1 - 1
src/views/promotionRulesManagement/promotionManagement/lookUpCustomersModal.vue

@@ -136,7 +136,7 @@ export default {
       nowType: null,
       printerType: 'NEEDLE', //  打印机类型
       columns: [
-        { title: '序号', dataIndex: 'no', width: '4%', align: 'center' },
+        { title: '序号', dataIndex: 'no', width: '8%', align: 'center' },
         { title: '地区', scopedSlots: { customRender: 'address' }, width: '20%', align: 'center', ellipsis: true },
         { title: '区域', dataIndex: 'subareaArea.subareaName', width: '15%', align: 'center', customRender: function (text) { return text || '--' } },
         { title: '分区', dataIndex: 'subareaArea.subareaAreaName', width: '15%', align: 'center', customRender: function (text) { return text || '--' } },

+ 437 - 0
src/views/reportData/promotionSalesRealTimeReport/index.vue

@@ -0,0 +1,437 @@
+<template>
+  <a-card size="small" :bordered="false" class="promotionSalesRealTimeReport-wrap">
+    <a-spin :spinning="spinning" tip="Loading...">
+      <a-tabs default-active-key="1" @change="handleChange">
+        <a-tab-pane key="1" tab="促销销售单报表">
+          <div ref="tableSearch" class="table-page-search-wrapper newTableSearchName">
+            <a-form-model
+              layout="inline"
+              ref="ruleForm"
+              :rules="rules"
+              :model="queryParam">
+              <a-row :gutter="15">
+                <a-col :md="6" :sm="24">
+                  <a-form-model-item label="销售审核日期" prop="salesDate">
+                    <rangeDate ref="rangeDate" :value="queryParam.salesDate" @change="salesDateChange" />
+                  </a-form-model-item>
+                </a-col>
+                <a-col :md="6" :sm="24">
+                  <!-- :disabledDate="disabledDate" -->
+                  <a-form-model-item label="促销开始时间">
+                    <a-range-picker
+                      style="width:100%"
+                      v-model="time"
+                      :format="dateFormat"
+                      :placeholder="['开始时间', '结束时间']"
+                      @change="dateChange"></a-range-picker>
+                  </a-form-model-item>
+                </a-col>
+                <a-col :md="6" :sm="24">
+                  <a-form-model-item label="促销名称">
+                    <a-input id="promotionSalesRealTimeReport-title" v-model.trim="queryParam.promoRuleReport.title" allowClear placeholder="请输入促销名称"/>
+                  </a-form-model-item>
+                </a-col>
+                <template v-if="advanced">
+                  <a-col :md="6" :sm="24">
+                    <a-form-model-item label="促销类型">
+                      <v-select
+                        v-model="queryParam.promoRuleReport.promotionRuleType"
+                        ref="ruleType"
+                        id="promotionSalesRealTimeReport-ruleType"
+                        code="PROMOTION_RULE_TYPE"
+                        placeholder="请选择促销类型"
+                        allowClear></v-select>
+                    </a-form-model-item>
+                  </a-col>
+                  <a-col :md="6" :sm="24">
+                    <a-form-model-item label="规则">
+                      <a-input id="promotionSalesRealTimeReport-ruleInfo" v-model.trim="queryParam.promoRuleReport.ruleInfo" allowClear placeholder="请输入规则关键字"/>
+                    </a-form-model-item>
+                  </a-col>
+                  <a-col :md="6" :sm="24">
+                    <a-form-model-item label="销售单号">
+                      <a-input id="promotionSalesRealTimeReport-salesBillNo" v-model.trim="queryParam.salesBillNo" allowClear placeholder="请输入销售单号"/>
+                    </a-form-model-item>
+                  </a-col>
+                  <a-col :md="6" :sm="24">
+                    <a-form-model-item label="客户级别">
+                      <v-select
+                        v-model="queryParam.buyerLevel"
+                        ref="buyerLevel"
+                        id="promotionSalesRealTimeReport-buyerLevel"
+                        code="DEALER_LEVEL"
+                        placeholder="请选择客户级别"
+                        allowClear></v-select>
+                    </a-form-model-item>
+                  </a-col>
+                  <a-col :md="6" :sm="24">
+                    <a-form-model-item label="客户名称">
+                      <a-input id="promotionSalesRealTimeReport-buyerName" v-model.trim="queryParam.buyerName" allowClear placeholder="请输入客户名称"/>
+                    </a-form-model-item>
+                  </a-col>
+                  <a-col :md="6" :sm="24">
+                    <a-form-model-item label="所在区域">
+                      <subarea ref="subarea" id="promotionSalesRealTimeReport-subarea" @change="subareaChange"></subarea>
+                    </a-form-model-item>
+                  </a-col>
+                  <a-col :md="6" :sm="24">
+                    <a-form-model-item label="地区">
+                      <AreaList id="promotionSalesRealTimeReport-areaList" changeOnSelect ref="areaList" @change="areaChange" defValKey="id"></AreaList>
+                    </a-form-model-item>
+                  </a-col>
+                </template>
+                <a-col :md="6" :sm="24">
+                  <span class="table-page-search-submitButtons">
+                    <a-button type="primary" :disabled="disabled" @click="testForm('search')" >查询</a-button>
+                    <a-button style="margin-left: 8px" :disabled="disabled" @click="resetSearchForm">重置</a-button>
+                    <a-button
+                      style="margin-left: 10px"
+                      type="primary"
+                      class="button-warning"
+                      @click="testForm('export')"
+                      :disabled="disabled"
+                      :loading="exportLoading"
+                      v-if="$hasPermissions('B_promotionSalesExport')"
+                    >导出</a-button>
+                    <a @click="advanced=!advanced" style="margin-left: 8px">
+                      {{ advanced ? '收起' : '展开' }}
+                      <a-icon :type="advanced ? 'up' : 'down'"/>
+                    </a>
+                  </span>
+                </a-col>
+              </a-row>
+            </a-form-model>
+          </div>
+          <!-- 列表 -->
+          <s-table
+            class="sTable"
+            ref="table"
+            size="small"
+            :rowKey="(record) => record.no"
+            rowKeyName="no"
+            :columns="columns"
+            :data="loadData"
+            :style="{ height: tableHeight+84.5+'px' }"
+            :scroll="{ y: tableHeight-40,x:1890}"
+            :defaultLoadData="false"
+            bordered>
+            <!-- 促销时间 -->
+            <template slot="promotionTime" slot-scope="text, record">
+              <span>{{ record.promotion.promotionDateStart }}-{{ record.promotion.promotionDateEnd }}</span>
+            </template>
+            <!-- 规则 -->
+            <!-- <template slot="promotionDesc" slot-scope="text, record">
+              <span v-if="record.promotionRule.promotionRuleType=='PROMO_PROD'">{{ record.promotionRule.promotionRuleTypeDictValue }}</span>
+              <span v-else-if="record.promotionRule.promotionRuleType=='RATIO_AMOUNT'">{{ record.promotionRule.regularSameFlag==1?'同款':'不同款' }}产品购买满{{ record.promotionRule.regularQty }}个正价产品,送{{ record.promotionQty }}个促销产品</span>
+              <span v-else>购买满{{ record.promotionRule.regularAmount }}元正价产品,送{{ record.promotionRule.giveAmount }}元促销品采购额{{ record.promotionRule.accrualFlag&&record.promotionRule.accrualFlag==1?'(金额叠加)':'(金额不叠加)' }}</span>
+            </template> -->
+            <!-- 地区 -->
+            <template slot="addressInfo" slot-scope="text, record">
+              <span>{{ record.provinceName }}{{ record.cityName?'/'+record.cityName:'' }}{{ record.districtName?'/'+record.districtName :'' }}</span>
+            </template>
+            <template slot="footer">
+              <a-row>
+                <a-col span="24">
+                  <a-row>
+                    <a-col span="4">数量(非促):{{ (totalData && (totalData.notGiftQty || totalData.notGiftQty==0)) ? totalData.notGiftQty : '--' }}</a-col>
+                    <a-col span="4">数量(促):{{ (totalData && (totalData.giftQty || totalData.giftQty==0)) ? totalData.giftQty: '--' }}</a-col>
+                    <a-col span="4">实售金额:{{ (totalData && (totalData.totalRealAmount || totalData.totalRealAmount==0)) ? toThousands(totalData.totalRealAmount) : '--' }}</a-col>
+                    <a-col span="4">开单金额:{{ (totalData && (totalData.totalAmount || totalData.totalAmount==0)) ? toThousands(totalData.totalAmount) : '--' }}</a-col>
+                    <a-col span="4">成本金额:{{ (totalData && (totalData.totalRealCost || totalData.totalRealCost==0)) ? totalData.totalRealCost : '--' }}</a-col>
+                    <a-col span="4">损失成本:{{ (totalData && (totalData.lossCost || totalData.lossCost==0)) ? toThousands(totalData.lossCost) : '--' }}</a-col>
+                    <a-col span="4">损失费用:{{ (totalData && (totalData.lossAmount || totalData.lossAmount==0)) ? toThousands(totalData.lossAmount) : '--' }}</a-col>
+                    <a-col span="4">采购额结余:{{ (totalData && (totalData.surplusPromoGiftsAmount || totalData.surplusPromoGiftsAmount==0)) ? toThousands(totalData.surplusPromoGiftsAmount) : '--' }}</a-col>
+                    <a-col span="4">采购额超出:{{ (totalData && (totalData.outPromoGiftsAmount || totalData.outPromoGiftsAmount==0)) ? toThousands(totalData.outPromoGiftsAmount) : '--' }}</a-col>
+                  </a-row>
+                </a-col>
+              </a-row>
+            </template>
+          </s-table>
+        </a-tab-pane>
+        <a-tab-pane key="2" tab="促销销售单实时报表" force-render>
+          <gatherList></gatherList>
+        </a-tab-pane>
+      </a-tabs>
+      <!-- 导出提示框 -->
+      <reportModal :visible="showExport" @close="showExport=false"></reportModal>
+    </a-spin>
+  </a-card>
+</template>
+
+<script>
+import { commonMixin } from '@/utils/mixin'
+import { STable, VSelect } from '@/components'
+import reportModal from '@/views/common/reportModal.vue'
+import { salesPromoReportList, salesPromoReportQueryCount, exportSalesPromoReport } from '@/api/reportData'
+import { hdExportExcel } from '@/libs/exportExcel'
+import gatherList from './list'
+import rangeDate from '@/views/common/rangeDate.vue'
+import getDate from '@/libs/getDate.js'
+import subarea from '@/views/common/subarea.js'
+import AreaList from '@/views/common/areaList.js'
+import moment from 'moment'
+export default {
+  name: 'PriceDifferenceDetailReportList',
+  mixins: [commonMixin],
+  components: { STable, VSelect, gatherList, reportModal, AreaList, rangeDate, subarea },
+  data () {
+    const _this = this
+    return {
+      advanced: true, // 高级搜索 展开/关闭
+      time: undefined,
+      spinning: false,
+      queryParam: {
+        salesDate: [
+          getDate.getCurrMonthDays().starttime,
+          getDate.getCurrMonthDays().endtime
+        ],
+        beginAuditDate: getDate.getCurrMonthDays().starttime, // 审核开始时间
+        endAuditDate: getDate.getCurrMonthDays().endtime, // 审核结束时间
+        promoRuleReport: {
+          promotionDateStart: undefined, // 促销时间-开始
+          promotionDateEnd: undefined, // 促销时间-结束
+          title: '', // 促销名称
+          promotionRuleType: undefined, // 促销类型
+          ruleInfo: ''// 规则
+        },
+        salesBillNo: '', // 销售单号
+        buyerLevel: undefined, // 客户级别
+        buyerName: '', // 客户名称
+        subareaArea: {
+          subareaSn: '',
+          subareaAreaSn: ''
+        },
+        dealerProvinceSn: undefined, // 省份编码
+        dealerCitySn: undefined, // 城市编码
+        dealerDistrictSn: undefined // 区域编码
+      },
+      rules: {
+        salesDate: [{ required: true, message: '请选择销售审核日期', trigger: 'change' }]
+      },
+      dateFormat: 'YYYY-MM-DD',
+      tabVal: 1,
+      disabled: false,
+      tableHeight: 0,
+      totalData: null, //  合计
+      exportLoading: false,
+      showExport: false,
+      columns: [
+        { title: '促销名称', dataIndex: 'promotion.title', width: '160px', align: 'center', customRender: function (text) { return text || '--' }, fixed: 'left', ellipsis: true },
+        { title: '促销时间', scopedSlots: { customRender: 'promotionTime' }, width: '130px', align: 'center', fixed: 'left' },
+        { title: '费用所属部门', dataIndex: 'departmentName', width: '160px', align: 'center', customRender: function (text) { return text || '--' }, ellipsis: true, fixed: 'left' },
+        { title: '促销类型', dataIndex: 'promotionRule.promotionRuleTypeDictValue', width: '100px', align: 'center', customRender: function (text) { return text || '--' }, fixed: 'left' },
+        { title: '规则', dataIndex: 'promotionRule.ruleInfo', width: '180px', align: 'center', customRender: function (text) { return text || '--' }, fixed: 'left' },
+        { title: '销售单号', dataIndex: 'salesBillNo', width: '120px', align: 'center', customRender: function (text) { return text || '--' }, fixed: 'left' },
+        { title: '区域', dataIndex: 'subareaArea.subareaName', width: '80px', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '分区', dataIndex: 'subareaArea.subareaAreaName', width: '80px', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '地区', dataIndex: 'provinceName', width: '160px', align: 'center', scopedSlots: { customRender: 'addressInfo' } },
+        { title: '客户名称', dataIndex: 'buyerName', width: '140px', align: 'center', customRender: function (text) { return text || '--' }, ellipsis: true },
+        { title: '客户级别', dataIndex: 'buyerLevelDictValue', width: '80px', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '销售审核日期', dataIndex: 'auditDate', width: '120px', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '数量(非促)', dataIndex: 'notGiftQty', width: '100px', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
+        { title: '数量(促)', dataIndex: 'giftQty', width: '100px', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
+        { title: '实售金额', dataIndex: 'totalRealAmount', width: '100px', align: 'center', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } },
+        { title: '开单金额', dataIndex: 'totalAmount', width: '100px', align: 'center', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } },
+        { title: '成本金额', dataIndex: 'totalRealCost', width: '100px', align: 'center', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } },
+        { title: '损失成本', dataIndex: 'lossCost', width: '100px', align: 'center', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } },
+        { title: '损失费用', dataIndex: 'lossAmount', width: '100px', align: 'center', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } },
+        { title: '采购额结余', dataIndex: 'surplusPromoGiftsAmount', width: '100px', align: 'center', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } },
+        { title: '采购额超出', dataIndex: 'outPromoGiftsAmount', width: '100px', align: 'center', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } },
+        { title: '促销品费用归属品牌', dataIndex: 'promoProductBrandName', width: '120px', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '促销品费用归属分类', dataIndex: 'promoProductTypeName', width: '120px', align: 'center', customRender: function (text) { return text || '--' } }
+      ],
+      // 加载数据方法 必须为 Promise 对象
+      loadData: parameter => {
+        this.disabled = true
+        const params = Object.assign(parameter, this.queryParam)
+        const newParams = JSON.parse(JSON.stringify(params))
+        delete newParams.salesDate
+        this.spinning = true
+        return salesPromoReportList(newParams).then(res => {
+          let data
+          if (res.status == 200) {
+            data = res.data
+            const no = (data.pageNo - 1) * data.pageSize
+            for (var i = 0; i < data.list.length; i++) {
+              data.list[i].no = no + i + 1
+            }
+            this.disabled = false
+          }
+          this.spinning = false
+          return data
+        })
+      }
+    }
+  },
+  methods: {
+    salesDateChange (date) {
+      if (date[0] && date[1]) {
+        this.queryParam.salesDate = date
+      } else {
+        this.queryParam.salesDate = []
+      }
+      this.queryParam.beginAuditDate = date[0] || ''
+      this.queryParam.endAuditDate = date[1] || ''
+    },
+    dateChange (date, dateString) {
+      this.time = date
+      if (dateString[0] != '' && dateString[1] != '') {
+        this.queryParam.promoRuleReport.promotionDateStart = dateString[0] + ' 00:00:00'
+        this.queryParam.promoRuleReport.promotionDateEnd = dateString[1] + ' 23:59:59'
+      } else {
+        this.$set(this.queryParam.promoRuleReport, 'promotionDateStart', undefined)
+        this.$set(this.queryParam.promoRuleReport, 'promotionDateEnd', undefined)
+      }
+    },
+    // // 不可选日期
+    // disabledDate (date, dateStrings) {
+    //   return date && date.valueOf('day') < moment().subtract(1, 'day') // 今天以后,包含今天
+    // },
+    // 统计
+    getCount (params) {
+      salesPromoReportQueryCount(params).then(res => {
+        if (res.status == 200) {
+          this.totalData = res.data
+        } else {
+          this.totalData = null
+        }
+      })
+    },
+    subareaChange (val) {
+      this.queryParam.subareaArea.subareaSn = val[0] ? val[0] : undefined
+      this.queryParam.subareaArea.subareaAreaSn = val[1] ? val[1] : undefined
+    },
+    // tab
+    handleChange (val) {
+      this.tabVal = val
+    },
+    // 导出
+    handleExport () {
+      const _this = this
+      const params = this.queryParam
+      _this.exportLoading = true
+      _this.spinning = true
+      const ajaxUrl = _this.tabVal == 1 ? exportSalesPromoReport : exportSalesPromoRealReport
+      const ajaxName = _this.tabVal == 1 ? '促销销售单报表导出' : '促销销售单实时报表导出'
+      hdExportExcel(ajaxUrl, params, ajaxName, function () {
+        _this.exportLoading = false
+        _this.spinning = false
+        _this.showExport = true
+      })
+    },
+    // 验证表单 type值  search查询 export导出
+    testForm (type) {
+      const _this = this
+      if (!_this.queryParam.salesDate[0] || !_this.queryParam.salesDate[1]) {
+        _this.$message.error('请选择销售审核日期')
+        return
+      }
+      _this.$refs.ruleForm.validate(valid => {
+        if (valid) {
+          if (type == 'search') {
+            _this.handleSearch()
+          } else {
+            _this.handleExport()
+          }
+        } else {
+          _this.$message.error('请选择销售审核日期')
+          return false
+        }
+      })
+    },
+    areaChange (val) {
+      this.queryParam.dealerProvinceSn = val[0] ? val[0] : ''
+      this.queryParam.dealerCitySn = val[1] ? val[1] : ''
+      this.queryParam.dealerDistrictSn = val[2] ? val[2] : ''
+    },
+    // 查询
+    handleSearch () {
+      const _this = this
+      // 总计
+      const paramData = JSON.parse(JSON.stringify(this.queryParam))
+      delete paramData.salesDate
+      _this.getCount(paramData)
+      _this.$refs.table.refresh(true)
+    },
+    // 重置
+    resetSearchForm () {
+      this.$refs.ruleForm.resetFields()
+      this.queryParam = {
+        salesDate: [
+          getDate.getCurrMonthDays().starttime,
+          getDate.getCurrMonthDays().endtime
+        ],
+        beginAuditDate: getDate.getCurrMonthDays().starttime, // 审核开始时间
+        endAuditDate: getDate.getCurrMonthDays().endtime, // 审核结束时间
+        promoRuleReport: {
+          promotionDateStart: undefined, // 促销时间-开始
+          promotionDateEnd: undefined, // 促销时间-结束
+          title: '', // 促销名称
+          promotionRuleType: undefined, // 促销类型
+          ruleInfo: ''// 规则
+        },
+        salesBillNo: '', // 销售单号
+        buyerLevel: undefined, // 客户级别
+        buyerName: '', // 客户名称
+        subareaArea: {
+          subareaSn: '',
+          subareaAreaSn: ''
+        },
+        dealerProvinceSn: undefined, // 省份编码
+        dealerCitySn: undefined, // 城市编码
+        dealerDistrictSn: undefined // 区域编码
+      }
+      this.time = undefined
+      this.$refs.subarea.clearData()
+      this.$refs.areaList.clearData()
+      this.$refs.rangeDate.resetDate(this.queryParam.salesDate)
+      this.$refs.table.clearTable()
+      this.totalData = null
+    },
+    pageInit () {
+      const _this = this
+      this.$nextTick(() => { // 页面渲染完成后的回调
+        _this.setTableH()
+      })
+    },
+    setTableH () {
+      const tableSearchH = this.$refs.tableSearch.offsetHeight
+      this.tableHeight = window.innerHeight - tableSearchH - 260
+    }
+  },
+  watch: {
+    advanced (newValue, oldValue) {
+      const _this = this
+      this.$nextTick(() => { // 页面渲染完成后的回调
+        _this.setTableH()
+      })
+    },
+    '$store.state.app.winHeight' (newValue, oldValue) { //  窗口变更时,需同时更改表格高度
+      this.setTableH()
+    }
+  },
+  mounted () {
+    if (!this.$store.state.app.isNewTab) { // 页签刷新时调用
+      this.pageInit()
+    }
+  },
+  activated () {
+    // 如果是新页签打开,则重置当前页面
+    if (this.$store.state.app.isNewTab) {
+      this.pageInit()
+    }
+  }
+}
+
+</script>
+
+<style lang="less" scoped>
+  .monthBox{
+    /deep/.ant-calendar-picker-icon{
+      display:none !important;
+    }
+    /deep/.ant-calendar-picker input{
+      text-align:center;
+    }
+  }
+</style>

+ 602 - 0
src/views/reportData/promotionSalesRealTimeReport/list.vue

@@ -0,0 +1,602 @@
+<template>
+  <a-spin :spinning="spinning" tip="Loading...">
+    <div class="productInfoList-wrap">
+      <div ref="tableSearch" class="table-page-search-wrapper newTableSearchName">
+        <a-form-model layout="inline" ref="ruleForm" :rules="rules" :model="newQueryParam">
+          <a-row :gutter="15">
+            <a-col :md="6" :sm="24">
+              <a-form-model-item label="销售审核日期" prop="salesDate">
+                <rangeDate ref="rangeDate" :value="newQueryParam.salesDate" @change="salesDateChange" />
+              </a-form-model-item>
+            </a-col>
+            <a-col :md="6" :sm="24">
+              <!-- :disabledDate="disabledDate" -->
+              <a-form-model-item label="促销开始时间">
+                <a-range-picker
+                  style="width:100%"
+                  v-model="time"
+                  :format="dateFormat"
+                  :placeholder="['开始时间', '结束时间']"
+                  @change="dateChange"></a-range-picker>
+              </a-form-model-item>
+            </a-col>
+            <a-col :md="6" :sm="24">
+              <a-form-model-item label="促销名称">
+                <a-input
+                  id="promotionSalesRealTimeReport-title"
+                  v-model.trim="newQueryParam.promoRuleReport.title"
+                  allowClear
+                  placeholder="请输入促销名称" />
+              </a-form-model-item>
+            </a-col>
+            <template v-if="advanced">
+              <a-col :md="6" :sm="24">
+                <a-form-model-item label="促销类型">
+                  <v-select
+                    v-model="newQueryParam.promoRuleReport.promotionRuleType"
+                    ref="ruleType"
+                    id="promotionSalesRealTimeReport-ruleType"
+                    code="PROMOTION_RULE_TYPE"
+                    placeholder="请选择促销类型"
+                    allowClear></v-select>
+                </a-form-model-item>
+              </a-col>
+              <a-col :md="6" :sm="24">
+                <a-form-model-item label="规则">
+                  <a-input
+                    id="promotionSalesRealTimeReport-ruleInfo"
+                    v-model.trim="newQueryParam.promoRuleReport.ruleInfo"
+                    allowClear
+                    placeholder="请输入规则关键字" />
+                </a-form-model-item>
+              </a-col>
+              <a-col :md="6" :sm="24">
+                <a-form-model-item label="销售单号">
+                  <a-input
+                    id="promotionSalesRealTimeReport-salesBillNo"
+                    v-model.trim="newQueryParam.salesBillNo"
+                    allowClear
+                    placeholder="请输入销售单号" />
+                </a-form-model-item>
+              </a-col>
+              <a-col :md="6" :sm="24">
+                <a-form-model-item label="客户级别">
+                  <v-select
+                    v-model="newQueryParam.buyerLevel"
+                    ref="buyerLevel"
+                    id="promotionSalesRealTimeReport-buyerLevel"
+                    code="DEALER_LEVEL"
+                    placeholder="请选择客户级别"
+                    allowClear></v-select>
+                </a-form-model-item>
+              </a-col>
+              <a-col :md="6" :sm="24">
+                <a-form-model-item label="客户名称">
+                  <a-input
+                    id="promotionSalesRealTimeReport-buyerName"
+                    v-model.trim="newQueryParam.buyerName"
+                    allowClear
+                    placeholder="请输入客户名称" />
+                </a-form-model-item>
+              </a-col>
+              <a-col :md="6" :sm="24">
+                <a-form-model-item label="所在区域">
+                  <subarea ref="subarea" id="promotionSalesRealTimeReport-subarea" @change="subareaChange"></subarea>
+                </a-form-model-item>
+              </a-col>
+              <a-col :md="6" :sm="24">
+                <a-form-model-item label="地区">
+                  <AreaList id="promotionSalesRealTimeReport-areaList" changeOnSelect ref="areaList" @change="areaChange" defValKey="id"></AreaList>
+                </a-form-model-item>
+              </a-col>
+            </template>
+            <a-col :md="6" :sm="24">
+              <span class="table-page-search-submitButtons">
+                <a-button type="primary" :disabled="disabled" @click="testForm('search')">查询</a-button>
+                <a-button style="margin-left: 8px" :disabled="disabled" @click="resetSearchForm">重置</a-button>
+                <a-button
+                  style="margin-left: 10px"
+                  type="primary"
+                  class="button-warning"
+                  @click="testForm('export')"
+                  :disabled="disabled"
+                  :loading="exportLoading"
+                  v-if="$hasPermissions('B_promotionSalesExport')">导出</a-button>
+                <a @click="advanced=!advanced" style="margin-left: 8px">
+                  {{ advanced ? '收起' : '展开' }}
+                  <a-icon :type="advanced ? 'up' : 'down'" />
+                </a>
+              </span>
+            </a-col>
+          </a-row>
+        </a-form-model>
+      </div>
+      <!-- 列表 -->
+      <s-table
+        class="sTable"
+        ref="table"
+        size="small"
+        :rowKey="(record) => record.no"
+        rowKeyName="no"
+        :columns="columns"
+        :data="loadData"
+        :style="{ height: tableHeight+84.5+'px' }"
+        :scroll="{ y: tableHeight-40,x:1890}"
+        :defaultLoadData="false"
+        bordered>
+        <!-- 促销时间 -->
+        <template slot="promotionTime" slot-scope="text, record">
+          <span>{{ record.promotion.promotionDateStart }}-{{ record.promotion.promotionDateEnd }}</span>
+        </template>
+        <!-- 规则 -->
+        <!-- <template slot="promotionDesc" slot-scope="text, record">
+          <span v-if="record.promotionRule.promotionRuleType=='PROMO_PROD'">{{ record.promotionRule.promotionRuleTypeDictValue }}</span>
+          <span v-else-if="record.promotionRule.promotionRuleType=='RATIO_AMOUNT'">{{ record.promotionRule.regularSameFlag==1?'同款':'不同款' }}产品购买满{{ record.promotionRule.regularQty }}个正价产品,送{{ record.promotionQty }}个促销产品</span>
+          <span v-else>购买满{{ record.promotionRule.regularAmount }}元正价产品,送{{ record.promotionRule.giveAmount }}元促销品采购额{{ record.promotionRule.accrualFlag&&record.promotionRule.accrualFlag==1?'(金额叠加)':'(金额不叠加)' }}</span>
+        </template> -->
+        <!-- 地区 -->
+        <template slot="addressInfo" slot-scope="text, record">
+          <span>{{ record.provinceName }}{{ record.cityName?'/'+record.cityName:'' }}{{ record.districtName?'/'+record.districtName :'' }}</span>
+        </template>
+        <template slot="footer">
+          <a-row>
+            <a-col span="24">
+              <a-row>
+                <a-col
+                  span="3">实时数量(非促):{{ (totalData && (totalData.notGiftQty || totalData.notGiftQty==0)) ? totalData.notGiftQty : '--' }}</a-col>
+                <a-col
+                  span="3">实时数量(促):{{ (totalData && (totalData.giftQty || totalData.giftQty==0)) ? totalData.giftQty : '--' }}</a-col>
+                <a-col
+                  span="3">实时实售金额:{{ (totalData && (totalData.totalRealAmount || totalData.totalRealAmount==0)) ? toThousands(totalData.totalRealAmount) : '--' }}</a-col>
+                <a-col
+                  span="3">实时开单金额:{{ (totalData && (totalData.totalAmount || totalData.totalAmount==0)) ? toThousands(totalData.totalAmount) : '--' }}</a-col>
+                <a-col
+                  span="3">实时成本金额:{{ (totalData && (totalData.totalRealCost || totalData.totalRealCost==0)) ? toThousands(totalData.totalRealCost) : '--' }}</a-col>
+                <a-col
+                  span="4">实时损失成本:{{ (totalData && (totalData.lossCost || totalData.lossCost==0)) ? toThousands(totalData.lossCost) : '--' }}</a-col>
+                <a-col
+                  span="5">实时损失费用:{{ (totalData && (totalData.lossAmount || totalData.lossAmount==0)) ? toThousands(totalData.lossAmount) : '--' }}</a-col>
+              </a-row>
+            </a-col>
+          </a-row>
+        </template>
+      </s-table>
+    </div>
+    <!-- 导出提示框 -->
+    <reportModal :visible="showExport" @close="showExport=false"></reportModal>
+  </a-spin>
+</template>
+
+<script>
+import {
+  commonMixin
+} from '@/utils/mixin'
+import {
+  salesPromoRealReportList,
+  salesPromoRealReportCount,
+  exportSalesPromoRealReport
+} from '@/api/reportData'
+import {
+  hdExportExcel
+} from '@/libs/exportExcel'
+import {
+  STable,
+  VSelect
+} from '@/components'
+import reportModal from '@/views/common/reportModal.vue'
+import rangeDate from '@/views/common/rangeDate.vue'
+import subarea from '@/views/common/subarea.js'
+import AreaList from '@/views/common/areaList.js'
+import getDate from '@/libs/getDate.js'
+export default {
+  name: 'QueryPart',
+  mixins: [commonMixin],
+  components: {
+    STable,
+    VSelect,
+    reportModal,
+    AreaList,
+    rangeDate,
+    subarea
+  },
+  data () {
+    const _this = this
+    return {
+      advanced: true, // 高级搜索 展开/关闭
+      time: undefined,
+      spinning: false,
+      disabled: false,
+      tableHeight: 0,
+      newQueryParam: { // 查询条件
+        salesDate: [
+          getDate.getCurrMonthDays().starttime,
+          getDate.getCurrMonthDays().endtime
+        ],
+        beginAuditDate: getDate.getCurrMonthDays().starttime, // 审核开始时间
+        endAuditDate: getDate.getCurrMonthDays().endtime, // 审核结束时间
+        promoRuleReport: {
+          promotionDateStart: undefined, // 促销时间-开始
+          promotionDateEnd: undefined, // 促销时间-结束
+          title: '', // 促销名称
+          promotionRuleType: undefined, // 促销类型
+          ruleInfo: '' // 规则
+        },
+        salesBillNo: '', // 销售单号
+        buyerLevel: undefined, // 客户级别
+        buyerName: '', // 客户名称
+        subareaArea: {
+          subareaSn: '',
+          subareaAreaSn: ''
+        },
+        dealerProvinceSn: undefined, // 省份编码
+        dealerCitySn: undefined, // 城市编码
+        dealerDistrictSn: undefined // 区域编码
+      },
+      rules: {
+        salesDate: [{
+          required: true,
+          message: '请选择销售审核日期',
+          trigger: 'change'
+        }]
+      },
+      dateFormat: 'YYYY-MM-DD',
+      totalData: null, //  合计
+      exportLoading: false,
+      showExport: false,
+      columns: [{
+        title: '促销名称',
+        dataIndex: 'promotion.title',
+        width: '160px',
+        align: 'center',
+        customRender: function (text) {
+          return text || '--'
+        },
+        fixed: 'left',
+        ellipsis: true
+      },
+      {
+        title: '促销时间',
+        scopedSlots: {
+          customRender: 'promotionTime'
+        },
+        width: '130px',
+        align: 'center',
+        fixed: 'left'
+      },
+      {
+        title: '费用所属部门',
+        dataIndex: 'departmentName',
+        width: '160px',
+        align: 'center',
+        customRender: function (text) {
+          return text || '--'
+        },
+        ellipsis: true,
+        fixed: 'left'
+      },
+      {
+        title: '促销类型',
+        dataIndex: 'promotionRule.promotionRuleTypeDictValue',
+        width: '100px',
+        align: 'center',
+        customRender: function (text) {
+          return text || '--'
+        },
+        fixed: 'left'
+      },
+      { title: '规则', dataIndex: 'promotionRule.ruleInfo', width: '180px', align: 'center', customRender: function (text) { return text || '--' }, fixed: 'left' },
+      {
+        title: '销售单号',
+        dataIndex: 'salesBillNo',
+        width: '120px',
+        align: 'center',
+        customRender: function (text) {
+          return text || '--'
+        },
+        fixed: 'left'
+      },
+      {
+        title: '区域',
+        dataIndex: 'subareaArea.subareaName',
+        width: '80px',
+        align: 'center',
+        customRender: function (text) {
+          return text || '--'
+        }
+      },
+      {
+        title: '分区',
+        dataIndex: 'subareaArea.subareaAreaName',
+        width: '80px',
+        align: 'center',
+        customRender: function (text) {
+          return text || '--'
+        }
+      },
+      {
+        title: '地区',
+        dataIndex: 'provinceName',
+        width: '160px',
+        align: 'center',
+        scopedSlots: { customRender: 'addressInfo' }
+      },
+      {
+        title: '客户名称',
+        dataIndex: 'buyerName',
+        width: '140px',
+        align: 'center',
+        customRender: function (text) {
+          return text || '--'
+        },
+        ellipsis: true
+      },
+      {
+        title: '客户级别',
+        dataIndex: 'buyerLevelDictValue',
+        width: '80px',
+        align: 'center',
+        customRender: function (text) {
+          return text || '--'
+        }
+      },
+      {
+        title: '销售审核日期',
+        dataIndex: 'auditDate',
+        width: '120px',
+        align: 'center',
+        customRender: function (text) {
+          return text || '--'
+        }
+      },
+      {
+        title: '实时数量(非促)',
+        dataIndex: 'notGiftQty',
+        width: '100px',
+        align: 'center',
+        customRender: function (text) {
+          return ((text || text == 0) ? text : '--')
+        }
+      },
+      {
+        title: '实时数量(促)',
+        dataIndex: 'giftQty',
+        width: '100px',
+        align: 'center',
+        customRender: function (text) {
+          return ((text || text == 0) ? text : '--')
+        }
+      },
+      {
+        title: '实时实售金额',
+        dataIndex: 'totalRealAmount',
+        width: '100px',
+        align: 'center',
+        customRender: function (text) {
+          return ((text || text == 0) ? _this.toThousands(text) : '--')
+        }
+      },
+      {
+        title: '实时开单金额',
+        dataIndex: 'totalAmount',
+        width: '100px',
+        align: 'center',
+        customRender: function (text) {
+          return ((text || text == 0) ? _this.toThousands(text) : '--')
+        }
+      },
+      {
+        title: '实时成本金额',
+        dataIndex: 'totalRealCost',
+        width: '100px',
+        align: 'center',
+        customRender: function (text) {
+          return ((text || text == 0) ? _this.toThousands(text) : '--')
+        }
+      },
+      {
+        title: '实时损失成本',
+        dataIndex: 'lossCost',
+        width: '100px',
+        align: 'center',
+        customRender: function (text) {
+          return ((text || text == 0) ? _this.toThousands(text) : '--')
+        }
+      },
+      {
+        title: '实时损失费用',
+        dataIndex: 'lossAmount',
+        width: '100px',
+        align: 'center',
+        customRender: function (text) {
+          return ((text || text == 0) ? _this.toThousands(text) : '--')
+        }
+      }
+      ],
+      // 加载数据方法 必须为 Promise 对象
+      loadData: parameter => {
+        this.spinning = true
+        this.disabled = true
+        const params = Object.assign(parameter, this.newQueryParam)
+        return salesPromoRealReportList(params).then(res => {
+          let data
+          if (res.status == 200) {
+            data = res.data
+            for (var i = 0; i < data.length; i++) {
+              data[i].no = i + 1
+            }
+            this.disabled = false
+          }
+          this.spinning = false
+          return data
+        })
+      }
+    }
+  },
+  watch: {
+    advanced (newValue, oldValue) {
+      const _this = this
+      this.$nextTick(() => { // 页面渲染完成后的回调
+        _this.setTableH()
+      })
+    },
+    '$store.state.app.winHeight' (newValue, oldValue) { //  窗口变更时,需同时更改表格高度
+      this.setTableH()
+    }
+  },
+  methods: {
+    salesDateChange (date) {
+      if (date[0] && date[1]) {
+        this.newQueryParam.salesDate = date
+      } else {
+        this.newQueryParam.salesDate = []
+      }
+      this.newQueryParam.beginAuditDate = date[0] || ''
+      this.newQueryParam.endAuditDate = date[1] || ''
+    },
+    areaChange (val) {
+      this.newQueryParam.dealerProvinceSn = val[0] ? val[0] : ''
+      this.newQueryParam.dealerCitySn = val[1] ? val[1] : ''
+      this.newQueryParam.dealerDistrictSn = val[2] ? val[2] : ''
+    },
+    dateChange (date, dateString) {
+      this.time = date
+      if (dateString[0] != '' && dateString[1] != '') {
+        this.newQueryParam.promoRuleReport.promotionDateStart = dateString[0] + ' 00:00:00'
+        this.newQueryParam.promoRuleReport.promotionDateEnd = dateString[1] + ' 23:59:59'
+      } else {
+        this.$set(this.newQueryParam.promoRuleReport, 'promotionDateStart', undefined)
+        this.$set(this.newQueryParam.promoRuleReport, 'promotionDateEnd', undefined)
+      }
+    },
+    subareaChange (val) {
+      this.newQueryParam.subareaArea.subareaSn = val[0] ? val[0] : undefined
+      this.newQueryParam.subareaArea.subareaAreaSn = val[1] ? val[1] : undefined
+    },
+    // 查询
+    testForm (type) {
+      const _this = this
+      if (!_this.newQueryParam.salesDate && (!_this.newQueryParam.salesDate[0] || !_this.newQueryParam.salesDate[1])) {
+        _this.$message.error('请选择销售审核日期')
+        return
+      }
+      _this.$refs.ruleForm.validate(valid => {
+        if (valid) {
+          if (type == 'search') {
+            _this.resetCurForm()
+          } else {
+            _this.handleExport()
+          }
+        } else {
+          _this.$message.error('请选择销售审核日期')
+          return false
+        }
+      })
+    },
+    // 统计
+    getCount (params) {
+      salesPromoRealReportCount(params).then(res => {
+        if (res.status == 200) {
+          this.totalData = res.data
+        } else {
+          this.totalData = null
+        }
+      })
+    },
+    // 刷新当前页面
+    resetCurForm () {
+      const params = JSON.parse(JSON.stringify(this.newQueryParam))
+      delete params.salesDate
+      this.$nextTick(() => {
+        this.getCount(params)
+        this.$refs.table.refresh()
+      })
+    },
+    // 导出
+    handleExport () {
+      const _this = this
+      const params = this.newQueryParam
+      _this.exportLoading = true
+      _this.spinning = true
+      hdExportExcel(exportSalesPromoRealReport, params, '促销销售单实时报表导出', function () {
+        _this.exportLoading = false
+        _this.spinning = false
+        _this.showExport = true
+      })
+    },
+    resetSearchForm () {
+      this.$refs.ruleForm.resetFields()
+      this.newQueryParam = {
+        beginAuditDate: getDate.getCurrMonthDays().starttime, // 审核开始时间
+        endAuditDate: getDate.getCurrMonthDays().endtime, // 审核结束时间
+        promoRuleReport: {
+          promotionDateStart: undefined, // 促销时间-开始
+          promotionDateEnd: undefined, // 促销时间-结束
+          title: '', // 促销名称
+          promotionRuleType: undefined, // 促销类型
+          ruleInfo: '' // 规则
+        },
+        salesBillNo: '', // 销售单号
+        buyerLevel: undefined, // 客户级别
+        buyerName: '', // 客户名称
+        subareaArea: {
+          subareaSn: '',
+          subareaAreaSn: ''
+        },
+        dealerProvinceSn: undefined, // 省份编码
+        dealerCitySn: undefined, // 城市编码
+        dealerDistrictSn: undefined // 区域编码
+      }
+      this.$set(this.newQueryParam, 'salesDate', [
+        getDate.getCurrMonthDays().starttime,
+        getDate.getCurrMonthDays().endtime
+      ])
+      this.time = undefined
+      this.$refs.subarea.clearData()
+      this.$refs.areaList.clearData()
+      this.$refs.rangeDate.resetDate(this.newQueryParam.salesDate)
+      this.$refs.table.clearTable()
+      this.totalData = null
+    },
+    pageInit () {
+      const _this = this
+      this.$nextTick(() => { // 页面渲染完成后的回调
+        _this.setTableH()
+      })
+    },
+    setTableH () {
+      const tableSearchH = this.$refs.tableSearch.offsetHeight
+      this.tableHeight = window.innerHeight - tableSearchH - 260
+    }
+  },
+  mounted () {
+    if (!this.$store.state.app.isNewTab) { // 页签刷新时调用
+      this.pageInit()
+    }
+  },
+  activated () {
+    // 如果是新页签打开,则重置当前页面
+    if (this.$store.state.app.isNewTab) {
+      this.pageInit()
+    }
+  }
+}
+</script>
+<style lang="less" scoped>
+  .productInfoList-wrap {
+    .ellipsisCon {
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+
+      .ellipsisText {
+        width: 100%;
+        overflow: hidden;
+        text-overflow: ellipsis;
+        display: box;
+        display: -webkit-box;
+        -webkit-line-clamp: 1;
+        -webkit-box-orient: vertical;
+      }
+    }
+  }
+</style>

+ 51 - 35
src/views/reportData/salesDetails/list.vue

@@ -28,26 +28,26 @@
               </a-form-model-item>
             </a-col>
             <a-col :md="6" :sm="24">
-                <a-form-model-item label="产品名称">
-                  <a-input id="salesDetailsList-productName" v-model.trim="queryParam.productName" allowClear placeholder="请输入产品名称"/>
-                </a-form-model-item>
-              </a-col>
-              <a-col :md="6" :sm="24">
-                <a-form-model-item label="客户名称">
-                  <a-input id="salesDetailsList-dealerName" v-model.trim="queryParam.dealerName" allowClear placeholder="请输入客户名称"/>
-                </a-form-model-item>
-              </a-col>
-              <a-col :md="6" :sm="24">
-                <a-form-model-item label="客户级别">
-                  <v-select
-                    v-model="queryParam.dealerLevel"
-                    ref="dealerLevel"
-                    id="salesDetailsList-dealerLevel"
-                    code="DEALER_LEVEL"
-                    placeholder="请选择客户级别"
-                    allowClear></v-select>
-                </a-form-model-item>
-              </a-col>
+              <a-form-model-item label="产品名称">
+                <a-input id="salesDetailsList-productName" v-model.trim="queryParam.productName" allowClear placeholder="请输入产品名称"/>
+              </a-form-model-item>
+            </a-col>
+            <a-col :md="6" :sm="24">
+              <a-form-model-item label="客户名称">
+                <a-input id="salesDetailsList-dealerName" v-model.trim="queryParam.dealerName" allowClear placeholder="请输入客户名称"/>
+              </a-form-model-item>
+            </a-col>
+            <a-col :md="6" :sm="24">
+              <a-form-model-item label="客户级别">
+                <v-select
+                  v-model="queryParam.dealerLevel"
+                  ref="dealerLevel"
+                  id="salesDetailsList-dealerLevel"
+                  code="DEALER_LEVEL"
+                  placeholder="请选择客户级别"
+                  allowClear></v-select>
+              </a-form-model-item>
+            </a-col>
             <template v-if="advanced">
               <a-col :md="6" :sm="24">
                 <a-form-model-item label="品牌分类">
@@ -76,12 +76,24 @@
               </a-col>
               <a-col :md="6" :sm="24">
                 <a-form-model-item label="区域负责人">
-                    <BizUser v-model="queryParam.subareaArea.bizUserSn"></BizUser>
+                  <BizUser v-model="queryParam.subareaArea.bizUserSn"></BizUser>
                 </a-form-model-item>
               </a-col>
               <a-col :md="6" :sm="24">
                 <a-form-model-item label="地区">
-                    <AreaList id="salesDetailsList-areaList" changeOnSelect ref="areaList" @change="areaChange" defValKey="id"></AreaList>
+                  <AreaList id="salesDetailsList-areaList" changeOnSelect ref="areaList" @change="areaChange" defValKey="id"></AreaList>
+                </a-form-model-item>
+              </a-col>
+              <a-col :md="6" :sm="24">
+                <a-form-model-item label="促销产品">
+                  <a-select v-model="queryParam.giftFLag" placeholder="请选择促销产品" allowClear>
+                    <a-select-option value="1">
+                      是
+                    </a-select-option>
+                    <a-select-option value="0">
+                      否
+                    </a-select-option>
+                  </a-select>
                 </a-form-model-item>
               </a-col>
             </template>
@@ -129,8 +141,9 @@
             <a-col :md="4" :sm="24" v-if="$hasPermissions('M_salesDetailsList_salesPrice')">实售价:{{ (totalData && (totalData.totalRealSaleAmount || totalData.totalRealSaleAmount==0)) ? toThousands(totalData.totalRealSaleAmount) : '--' }}</a-col>
             <a-col :md="4" :sm="24" v-if="$hasPermissions('M_salesDetailsList_salesPrice')">开单价:{{ (totalData && (totalData.totalAmount || totalData.totalAmount==0)) ? toThousands(totalData.totalAmount) : '--' }}</a-col>
             <a-col :md="4" :sm="24" v-if="$hasPermissions('M_salesDetailsList_costPrice')">成本:{{ (totalData && (totalData.totalRealCost || totalData.totalRealCost==0)) ? toThousands(totalData.totalRealCost) : '--' }}</a-col>
-            <a-col :md="4" :sm="24" v-if="$hasPermissions('M_salesDetailsList_salesPrice')">折后金额:{{ (totalData && (totalData.discountedAmount || totalData.discountedAmount==0)) ? toThousands(totalData.discountedAmount) : '--' }}</a-col>
-            <a-col :md="4" :sm="24" v-if="$hasPermissions('M_salesDetailsList_salesPrice')">折扣金额:{{ (totalData && (totalData.discountAmount || totalData.discountAmount==0)) ? toThousands(totalData.discountAmount) : '--' }}</a-col>
+            <a-col :md="4" :sm="24" v-if="$hasPermissions('M_salesDetailsList_salesPrice')">优惠金额:{{ (totalData && (totalData.discountAmount || totalData.discountAmount==0)) ? toThousands(totalData.discountAmount) : '--' }}</a-col>
+          <!--  <a-col :md="4" :sm="24" v-if="$hasPermissions('M_salesDetailsList_salesPrice')">折后金额:{{ (totalData && (totalData.discountedAmount || totalData.discountedAmount==0)) ? toThousands(totalData.discountedAmount) : '--' }}</a-col>
+            <a-col :md="4" :sm="24" v-if="$hasPermissions('M_salesDetailsList_salesPrice')">折扣金额:{{ (totalData && (totalData.discountAmount || totalData.discountAmount==0)) ? toThousands(totalData.discountAmount) : '--' }}</a-col> -->
           </a-row>
         </template>
       </s-table>
@@ -182,7 +195,7 @@ export default {
         productTypeSn1: '', //  产品一级分类
         productTypeSn2: '', //  产品二级分类
         productTypeSn3: '', //  产品三级分类
-        subareaArea:{
+        subareaArea: {
           subareaSn: undefined,
           subareaAreaSn: undefined,
           bizUserSn: undefined
@@ -190,7 +203,8 @@ export default {
         dealerProvinceSn: undefined,
         dealerCitySn: undefined,
         dealerCountySn: undefined,
-        warehouseSn: undefined
+        warehouseSn: undefined,
+        giftFLag: undefined
       },
       productType: [],
       rules: {
@@ -242,7 +256,7 @@ export default {
         { title: '产品名称', dataIndex: 'productName', align: 'left', customRender: function (text) { return text || '--' }, ellipsis: true },
         { title: '产品编码', dataIndex: 'productCode', width: 150, align: 'center', customRender: function (text) { return text || '--' } },
         { title: '单位', dataIndex: 'productUnit', width: 50, align: 'center', customRender: function (text) { return text || '--' } },
-        { title: '销售数量', dataIndex: 'qty', width: 70, align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
+        { title: '销售数量', dataIndex: 'qty', width: 70, align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } }
         // { title: '成本价', dataIndex: 'totalRealCost', width: 70, align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
         // { title: '实售价', dataIndex: 'totalRealSaleAmount', width: 70, align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
         // { title: '开单价', dataIndex: 'totalAmount', width: 70, align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
@@ -258,15 +272,16 @@ export default {
       if (this.$hasPermissions('M_salesDetailsList_salesPrice')) { //  售价权限
         arr.push({ title: '实售价', dataIndex: 'totalRealSaleAmount', width: 70, align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } })
         arr.push({ title: '开单价', dataIndex: 'totalAmount', width: 70, align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } })
-      } 
+      }
       if (this.$hasPermissions('M_salesDetailsList_cityPrice')) { //  市级价权限
         arr.push({ title: '市级价', dataIndex: 'totalCityAmount', width: 70, align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } })
       }
-      if (this.$hasPermissions('M_salesDetailsList_salesPrice')) { //  售价权限  
+      if (this.$hasPermissions('M_salesDetailsList_salesPrice')) { //  售价权限
         arr.push({ title: '直接差价', dataIndex: 'directRebateAmount', width: 70, align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } })
         arr.push({ title: '间接差价', dataIndex: 'indirectRebateAmount', width: 70, align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } })
-        arr.push({ title: '折后单价', dataIndex: 'discountedPrice', width: 70, align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } })
-        arr.push({ title: '折扣金额', dataIndex: 'discountAmount', width: 70, align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } })
+        arr.push({ title: '优惠金额', dataIndex: 'discountAmount', width: 70, align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } })
+        // arr.push({ title: '折后单价', dataIndex: 'discountedPrice', width: 70, align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } })
+        // arr.push({ title: '折扣金额', dataIndex: 'discountAmount', width: 70, align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } })
       }
       arr.push({ title: '操作员', dataIndex: 'operatorName', width: 150, align: 'center', customRender: function (text) { return text || '--' }, ellipsis: true })
       return arr
@@ -293,7 +308,7 @@ export default {
         if (valid) {
           _this.$refs.table.refresh(true)
         } else {
-          _this.$message.error("请选择销售日期")
+          _this.$message.error('请选择销售日期')
           return false
         }
       })
@@ -311,7 +326,7 @@ export default {
     custChange (val) {
       this.queryParam.dealerSn = val.key
     },
-    subareaChange(val){
+    subareaChange (val) {
       this.queryParam.subareaArea.subareaSn = val[0] ? val[0] : undefined
       this.queryParam.subareaArea.subareaAreaSn = val[1] ? val[1] : undefined
     },
@@ -341,7 +356,8 @@ export default {
       this.queryParam.dealerCitySn = undefined
       this.queryParam.dealerCountySn = undefined
       this.queryParam.warehouseSn = undefined
-      if(this.advanced){
+      this.queryParam.giftFLag = undefined
+      if (this.advanced) {
         this.$refs.subarea.clearData()
         this.$refs.areaList.clearData()
       }
@@ -376,7 +392,7 @@ export default {
       this.queryParam.productTypeSn2 = val[1] ? val[1] : ''
       this.queryParam.productTypeSn3 = val[2] ? val[2] : ''
     },
-    areaChange(val){
+    areaChange (val) {
       this.queryParam.dealerProvinceSn = val[0] ? val[0] : ''
       this.queryParam.dealerCitySn = val[1] ? val[1] : ''
       this.queryParam.dealerCountySn = val[2] ? val[2] : ''

+ 23 - 19
src/views/reportData/salesOrderTotal/list.vue

@@ -110,8 +110,9 @@
             <a-col :md="4" :sm="24" v-if="$hasPermissions('M_salesOrderTotalList_costPrice')">成本:{{ (totalData && (totalData.totalCost || totalData.totalCost==0)) ? toThousands(totalData.totalCost) : '--' }}</a-col>
             <a-col :md="4" :sm="24" v-if="$hasPermissions('M_salesOrderTotalList_costPrice')&&$hasPermissions('M_salesOrderTotalList_salesPrice')">毛利:{{ (totalData && (totalData.grossProfit || totalData.grossProfit==0)) ? toThousands(totalData.grossProfit) : '--' }}</a-col>
             <a-col :md="4" :sm="24" v-if="$hasPermissions('M_salesOrderTotalList_salesPrice')">返利:{{ (totalData && (totalData.rebateAmount || totalData.rebateAmount==0)) ? toThousands(totalData.rebateAmount) : '--' }}</a-col>
-            <a-col :md="4" :sm="24" v-if="$hasPermissions('M_salesOrderTotalList_salesPrice')">折扣金额:{{ (totalData && (totalData.totalDiscountAmount || totalData.totalDiscountAmount==0)) ? toThousands(totalData.totalDiscountAmount) : '--' }}</a-col>
-            <a-col :md="4" :sm="24" v-if="$hasPermissions('M_salesOrderTotalList_salesPrice')">折后金额:{{ (totalData && (totalData.totalDiscountedAmount || totalData.totalDiscountedAmount==0)) ? toThousands(totalData.totalDiscountedAmount) : '--' }}</a-col>
+            <a-col :md="4" :sm="24" v-if="$hasPermissions('M_salesOrderTotalList_salesPrice')">优惠金额:{{ (totalData && (totalData.discountAmount || totalData.discountAmount==0)) ? toThousands(totalData.discountAmount) : '--' }}</a-col>
+            <!-- <a-col :md="4" :sm="24" v-if="$hasPermissions('M_salesOrderTotalList_salesPrice')">折扣金额:{{ (totalData && (totalData.totalDiscountAmount || totalData.totalDiscountAmount==0)) ? toThousands(totalData.totalDiscountAmount) : '--' }}</a-col>
+            <a-col :md="4" :sm="24" v-if="$hasPermissions('M_salesOrderTotalList_salesPrice')">折后金额:{{ (totalData && (totalData.totalDiscountedAmount || totalData.totalDiscountedAmount==0)) ? toThousands(totalData.totalDiscountedAmount) : '--' }}</a-col> -->
           </a-row>
         </template>
       </s-table>
@@ -129,7 +130,7 @@ import rangeDate from '@/views/common/rangeDate.vue'
 import subarea from '@/views/common/subarea.js'
 import custList from '@/views/common/custList.vue'
 import reportModal from '@/views/common/reportModal.vue'
-import Area  from '@/views/common/area.js'
+import Area from '@/views/common/area.js'
 import { hdExportExcel } from '@/libs/exportExcel'
 import { userQueryList } from '@/api/power-user'
 import { reportSalesBillList, reportSalesBillCount, reportSalesBillExport } from '@/api/reportData'
@@ -154,7 +155,7 @@ export default {
         dealerName: '',
         dealerLevel: undefined,
         operatorSn: undefined,
-        subareaArea:{
+        subareaArea: {
           subareaSn: undefined,
           subareaAreaSn: undefined
         },
@@ -202,6 +203,7 @@ export default {
         { title: '直接绑定客户名称', dataIndex: 'directDealerName', width: 120, align: 'center', customRender: function (text) { return text || '--' }, ellipsis: true },
         { title: '间接绑定客户名称', dataIndex: 'indirectDealerName', width: 120, align: 'center', customRender: function (text) { return text || '--' }, ellipsis: true },
         { title: '总数量', dataIndex: 'totalQty', width: 70, align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
+        { title: '数量(促)', dataIndex: 'giftQty', width: 70, align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } }
         // { title: '实售价', dataIndex: 'totalRealSaleAmount', width: 70, align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
         // { title: '开单价', dataIndex: 'totalAmount', width: 70, align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
         // { title: '成本价', dataIndex: 'totalCost', width: 70, align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
@@ -214,33 +216,35 @@ export default {
         // { title: '返利', dataIndex: 'rebateAmount', width: 70, align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
         // { title: '折扣金额', dataIndex: 'totalDiscountAmount', width: 70, align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
         // { title: '折后金额', dataIndex: 'totalDiscountedAmount', width: 70, align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
-        
+
       ]
-      if(this.$hasPermissions('M_salesOrderTotalList_salesPrice')){
-          arr.push({ title: '实售价', dataIndex: 'totalRealSaleAmount', width: 70, align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } })
-          arr.push({ title: '开单价', dataIndex: 'totalAmount', width: 70, align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } })
+      if (this.$hasPermissions('M_salesOrderTotalList_salesPrice')) {
+        arr.push({ title: '实售价', dataIndex: 'totalRealSaleAmount', width: 70, align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } })
+        arr.push({ title: '开单价', dataIndex: 'totalAmount', width: 70, align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } })
       }
       if (this.$hasPermissions('M_salesOrderTotalList_costPrice')) { //  成本价权限
         arr.push({ title: '成本价', dataIndex: 'totalCost', width: 70, align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } })
-        if(this.$hasPermissions('M_salesOrderTotalList_salesPrice')){
-           arr.push({ title: '毛利', dataIndex: 'grossProfit', width: 70, align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } })
+        arr.push({ title: '成本价(促)', dataIndex: 'totalGiftCost', width: 90, align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } })
+        if (this.$hasPermissions('M_salesOrderTotalList_salesPrice')) {
+          arr.push({ title: '毛利', dataIndex: 'grossProfit', width: 70, align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } })
         }
       }
-      if(this.$hasPermissions('M_salesOrderTotalList_provincePrice')){
+      if (this.$hasPermissions('M_salesOrderTotalList_provincePrice')) {
         arr.push({ title: '省级价', dataIndex: 'totalProvinceAmount', width: 70, align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } })
       }
-      if(this.$hasPermissions('M_salesOrderTotalList_cityPrice')){
+      if (this.$hasPermissions('M_salesOrderTotalList_cityPrice')) {
         arr.push({ title: '市级价', dataIndex: 'totalCityAmount', width: 70, align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } })
       }
-      if(this.$hasPermissions('M_salesOrderTotalList_specialPrice')){
+      if (this.$hasPermissions('M_salesOrderTotalList_specialPrice')) {
         arr.push({ title: '特约加盟店价', dataIndex: 'totalSpecialAmount', width: 90, align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } })
       }
-      if(this.$hasPermissions('M_salesOrderTotalList_salesPrice')){
+      if (this.$hasPermissions('M_salesOrderTotalList_salesPrice')) {
         arr.push({ title: '直接差价', dataIndex: 'directRebateAmount', width: 70, align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } })
         arr.push({ title: '间接差价', dataIndex: 'indirectRebateAmount', width: 70, align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } })
         arr.push({ title: '返利', dataIndex: 'rebateAmount', width: 70, align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } })
-        arr.push({ title: '折扣金额', dataIndex: 'totalDiscountAmount', width: 70, align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } })
-        arr.push({ title: '折后金额', dataIndex: 'totalDiscountedAmount', width: 70, align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } })
+        arr.push({ title: '优惠金额', dataIndex: 'discountAmount', width: 70, align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } })
+        // arr.push({ title: '折扣金额', dataIndex: 'totalDiscountAmount', width: 70, align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } })
+        // arr.push({ title: '折后金额', dataIndex: 'totalDiscountedAmount', width: 70, align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } })
       }
       arr.push({ title: '操作员', dataIndex: 'operatorName', width: 100, align: 'center', customRender: function (text) { return text || '--' }, ellipsis: true })
       return arr
@@ -267,7 +271,7 @@ export default {
         if (valid) {
           _this.$refs.table.refresh(true)
         } else {
-          _this.$message.error("请选择销售日期")
+          _this.$message.error('请选择销售日期')
           return false
         }
       })
@@ -285,7 +289,7 @@ export default {
     custChange (val) {
       this.queryParam.dealerSn = val.key
     },
-    subareaChange(val){
+    subareaChange (val) {
       this.queryParam.subareaArea.subareaSn = val[0] ? val[0] : undefined
       this.queryParam.subareaArea.subareaAreaSn = val[1] ? val[1] : undefined
     },
@@ -306,7 +310,7 @@ export default {
       this.queryParam.subareaArea.subareaAreaSn = undefined
       this.queryParam.dealerProvinceSn = undefined
       this.totalData = null
-      if(this.advanced){
+      if (this.advanced) {
         this.$refs.subarea.clearData()
       }
       this.$refs.ruleForm.resetFields()

+ 5 - 1
src/views/reportData/salesReturnDetailReport/list.vue

@@ -153,6 +153,7 @@
             <a-col :md="4" :sm="24">良品数量:{{ (totalData && (totalData.goodQty || totalData.goodQty==0)) ? totalData.goodQty : '--' }}</a-col>
             <a-col :md="4" :sm="24">返库数量:{{ (totalData && (totalData.totalBackStockQty || totalData.totalBackStockQty==0)) ? totalData.totalBackStockQty : '--' }}</a-col>
             <a-col :md="4" :sm="24">正常退货数量:{{ (totalData && (totalData.totalNormalQty || totalData.totalNormalQty==0)) ? totalData.totalNormalQty : '--' }}</a-col>
+            <a-col :md="4" :sm="24" v-if="$hasPermissions('M_salesReturnDetailReportList_salesPrice')">成本金额:{{ (totalData && (totalData.totalCost || totalData.totalCost==0)) ? toThousands(totalData.totalCost) : '--' }}</a-col>
             <a-col :md="4" :sm="24" v-if="$hasPermissions('M_salesReturnDetailReportList_salesPrice')">正常退货金额:{{ (totalData && (totalData.totalNormalPrice || totalData.totalNormalPrice==0)) ? toThousands(totalData.totalNormalPrice) : '--' }}</a-col>
             <a-col :md="4" :sm="24" v-if="$hasPermissions('M_salesReturnDetailReportList_salesPrice')">正常再入库金额:{{ (totalData && (totalData.totalNormalCost || totalData.totalNormalCost==0)) ? toThousands(totalData.totalNormalCost) : '--' }}</a-col>
             <a-col :md="4" :sm="24" v-if="$hasPermissions('M_salesReturnDetailReportList_salesPrice')">正常退货入库差额:{{ (totalData && (totalData.totalNormalBalance || totalData.totalNormalBalance==0)) ? toThousands(totalData.totalNormalBalance) : '--' }}</a-col>
@@ -269,6 +270,7 @@ export default {
         { title: '二级分类', dataIndex: 'productTypeName2', width: 130, align: 'center', customRender: function (text) { return text || '--' } },
         { title: '产品名称', dataIndex: 'productName', align: 'center', customRender: function (text) { return text || '--' }, ellipsis: true },
         { title: '产品编码', dataIndex: 'productCode', width: 150, align: 'center', customRender: function (text) { return text || '--' } },
+
         { title: '单位', dataIndex: 'productUnit', width: 50, align: 'center', customRender: function (text) { return text || '--' } },
         { title: '退货原因', dataIndex: 'returnReason', width: 100, align: 'center', customRender: function (text) { return text || '--' } },
         { title: '申请退货数量', dataIndex: 'initialQty', width: 80, align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
@@ -289,7 +291,9 @@ export default {
         // { title: '正常再入库金额', dataIndex: 'totalNormalCost', width: 100, align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
         // { title: '正常退货入库差额', dataIndex: 'totalNormalBalance', width: 110, align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } }
       ]
-
+      if (this.$hasPermissions('M_salesReturnDetailReportList_costPrice')) {
+        arr.splice(17, 0, { title: '成本金额', dataIndex: 'totalCost', width: 80, align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } })
+      }
       if (this.$hasPermissions('M_salesReturnDetailReportList_salesPrice')) { //  售价权限
         arr.push({ title: '退货开单价', dataIndex: 'price', width: 80, align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } })
         arr.push({ title: '退货开单金额', dataIndex: 'totalPrice', width: 90, align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } })

+ 23 - 6
src/views/salesManagement/backorder/detailModal.vue

@@ -7,7 +7,7 @@
     title="详情"
     v-model="isShow"
     @cancel="isShow=false"
-    :width="960">
+    width="80%">
     <a-spin :spinning="spinning" tip="Loading...">
       <div style="padding: 0 12px;text-align: right;" v-if="$hasPermissions('B_oosPrint')">
         <a-button id="backorderDetail-preview-btn" :disabled="localDataSource.length==0" @click="handlePrint('preview')" style="margin-right: 15px;">打印预览</a-button>
@@ -18,7 +18,10 @@
         <a-collapse :activeKey="['1']">
           <a-collapse-panel key="1" header="基础信息">
             <a-descriptions size="small" :column="2">
-              <a-descriptions-item label="销售单号">{{ detailData&&detailData.salesBillNo || '--' }}</a-descriptions-item>
+              <a-descriptions-item label="销售单号">
+                {{ detailData&&detailData.salesBillNo || '--' }}
+                <a-badge count="促" v-if="detailData&&detailData.promoFlag==1" :number-style="{ backgroundColor: '#52c41a', zoom:'80%' }"></a-badge>
+              </a-descriptions-item>
             </a-descriptions>
           </a-collapse-panel>
         </a-collapse>
@@ -42,6 +45,17 @@
           :defaultLoadData="false"
           :scroll="{ y: 500 }"
           bordered>
+          <template slot="productCode" slot-scope="text, record">
+            <span style="padding-right: 15px;">{{ text }}</span>
+            <a-badge count="促" v-if="record.promotionFlag=='GIFT'" :number-style="{ backgroundColor: '#52c41a', zoom:'80%' }"></a-badge>
+            <!-- <a-badge count="正" v-if="record.promotionFlag=='REGULAR'" :number-style="{ backgroundColor: '#108ee9', zoom:'80%' }"></a-badge> -->
+            <a-badge count="特" v-if="record.promotionFlag=='DISCOUNT'" :number-style="{ backgroundColor: '#faad14', zoom:'80%' }"></a-badge>
+          </template>
+          <!-- 销售价 -->
+          <template slot="price" slot-scope="text, record">
+            {{ toThousands(text) }}
+            <span v-if="record.promotionFlag=='GIFT'||record.promotionFlag=='DISCOUNT'" title="原价">({{ toThousands(record.origPrice) }})</span>
+          </template>
         </s-table>
       </a-card>
     </a-spin>
@@ -98,16 +112,19 @@ export default {
     columns () {
       const arr = [
         { title: '序号', dataIndex: 'no', width: '4%', align: 'center' },
-        { title: '产品编码', dataIndex: 'productEntity.code', width: '15%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '产品编码', dataIndex: 'productEntity.code', width: '15%', align: 'center', scopedSlots: { customRender: 'productCode' } },
         { title: '产品名称', dataIndex: 'productEntity.name', width: '24%', align: 'left', customRender: function (text) { return text || '--' }, ellipsis: true },
-        { title: '仓库', dataIndex: 'warehouseName', width: '20%', align: 'center', customRender: function (text) { return text || '--' }, ellipsis: true },
+        { title: '仓库', dataIndex: 'warehouseName', width: '15%', align: 'center', customRender: function (text) { return text || '--' }, ellipsis: true },
         { title: '原厂编码', dataIndex: 'productEntity.origCode', width: '15%', align: 'center', customRender: function (text) { return text || '--' } },
         { title: '缺货数量', dataIndex: 'qty', width: '10%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
         { title: '单位', dataIndex: 'productEntity.unit', width: '8%', align: 'center', customRender: function (text) { return text || '--' } }
-        // { title: '缺货金额', dataIndex: 'totalAmount', width: '10%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } }
       ]
+      if (this.$hasPermissions('B_oosDetail_costPrice')) { //  成本
+        arr.push({ title: '缺货成本金额', dataIndex: 'totalShowCostAmount', width: '10%', align: 'right', customRender: text => ((text || text == 0) ? this.toThousands(text) : '--') })
+      }
       if (this.$hasPermissions('B_oosDetail_salesPrice')) { //  售价权限
-        arr.splice(6, 0, { title: '缺货金额', dataIndex: 'totalAmount', width: '10%', align: 'right', customRender: text => ((text || text == 0) ? this.toThousands(text) : '--') })
+        arr.push({ title: '售价', dataIndex: 'price', width: '15%', align: 'right', scopedSlots: { customRender: 'price' }})
+        arr.push({ title: '缺货金额', dataIndex: 'totalAmount', width: '10%', align: 'right', customRender: text => ((text || text == 0) ? this.toThousands(text) : '--') })
       }
       return arr
     }

+ 7 - 2
src/views/salesManagement/backorder/list.vue

@@ -33,12 +33,17 @@
         ref="table"
         :style="{ height: tableHeight+84.5+'px' }"
         size="small"
-        :rowKey="(record) => record.id"
+        :rowKey="(record) => record.no"
+        rowKeyName="no"
         :columns="columns"
         :data="loadData"
         :scroll="{ y: tableHeight }"
         :defaultLoadData="false"
         bordered>
+        <template slot="salesBillNo" slot-scope="text, record">
+          <span style="padding-right: 15px;">{{ text }}</span>
+          <a-badge count="促" v-if="record.promoFlag==1" :number-style="{ backgroundColor: '#52c41a', zoom:'80%' }"></a-badge>
+        </template>
         <!-- 操作 -->
         <template slot="action" slot-scope="text, record">
           <a-button
@@ -107,7 +112,7 @@ export default {
       const arr = [
         { title: '序号', dataIndex: 'no', width: '4%', align: 'center' },
         { title: '创建时间', dataIndex: 'createDate', width: '12%', align: 'center', customRender: function (text) { return text || '--' } },
-        { title: '销售单号', dataIndex: 'salesBillNo', width: '20%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '销售单号', dataIndex: 'salesBillNo', width: '20%', align: 'center', scopedSlots: { customRender: 'salesBillNo' }},
         { title: '客户名称', dataIndex: 'dealerName', width: '20%', align: 'left', customRender: function (text) { return text || '--' }, ellipsis: true },
         // { title: '仓库', dataIndex: 'warehouseName', width: '15%', align: 'left', customRender: function (text) { return text || '--' }, ellipsis: true },
         { title: '缺货款数', dataIndex: 'totalCategory', width: '11%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },

+ 1 - 1
src/views/salesManagement/examineVerify/list.vue

@@ -158,7 +158,7 @@
 import { commonMixin } from '@/utils/mixin'
 import moment from 'moment'
 import commonModal from '@/views/common/commonModal.vue'
-import salesDetail from '@/views/salesManagement/salesQuery/detail.vue'
+import salesDetail from '@/views/salesManagement/salesQueryNew/detailAll.vue'
 import dispatchDetail from '@/views/salesManagement/pushOrderManagement/detail.vue'
 import getDate from '@/libs/getDate.js'
 import subarea from '@/views/common/subarea.js'

+ 1 - 1
src/views/salesManagement/matchSendOutOrder/list.vue

@@ -158,7 +158,7 @@ import dealerSubareaScopeList from '@/views/common/dealerSubareaScopeList.vue'
 import Area from '@/views/common/area.js'
 import { dispatchlList, dispatchCheck } from '@/api/dispatch'
 import commonModal from '@/views/common/commonModal.vue'
-import salesDetail from '@/views/salesManagement/salesQuery/detail.vue'
+import salesDetail from '@/views/salesManagement/salesQueryNew/detailAll.vue'
 import chooseWarehouse from '@/views/common/chooseWarehouse'
 import dispatchDetail from '@/views/salesManagement/pushOrderManagement/detail.vue'
 export default {

+ 1 - 1
src/views/salesManagement/outboundOrder/list.vue

@@ -181,7 +181,7 @@ import rangeDate from '@/views/common/rangeDate.vue'
 import getDate from '@/libs/getDate.js'
 import subarea from '@/views/common/subarea.js'
 import Area from '@/views/common/area.js'
-import pushOrderDetailModal from '@/views/salesManagement/pushOrderManagement/detail.vue'
+import pushOrderDetailModal from '@/views/salesManagement/pushOrderManagement/detailForOut.vue'
 import allocationDetailModal from '@/views/allocationManagement/transferOut/detail.vue'
 import sendGoodModal from './sendGoodModal.vue'
 import { STable, VSelect } from '@/components'

+ 11 - 6
src/views/salesManagement/pushOrderManagement/detail.vue

@@ -84,7 +84,8 @@
           class="sTable"
           ref="table"
           size="small"
-          :rowKey="(record) => record.id"
+          :rowKey="(record) => record.no"
+          rowKeyName="no"
           :columns="($route.params.type=='stockOut' || outBizSubSn) ? outColumns : columns"
           :data="loadData"
           :scroll="{ y: 500 }"
@@ -92,10 +93,14 @@
           bordered>
           <!-- 产品编码 -->
           <template slot="productCode" slot-scope="text, record">
-            <a-badge count="促" v-if="record.promotionFlag == 1">
-              <div style="padding-right: 15px;">{{ text }}</div>
-            </a-badge>
-            <span v-else>{{ text }}</span>
+            <span>{{ text }}</span>
+            <a-badge count="促" v-if="record.promotionFlag=='GIFT'" :number-style="{ backgroundColor: '#52c41a', zoom:'80%' }"></a-badge>
+            <a-badge count="特" v-if="record.promotionFlag=='DISCOUNT'" :number-style="{ backgroundColor: '#faad14', zoom:'80%' }"></a-badge>
+          </template>
+           <!-- 销售价 -->
+          <template slot="price" slot-scope="text, record">
+            {{ toThousands(text) }}
+            <span v-if="record.promotionFlag=='GIFT'||record.promotionFlag=='DISCOUNT'" title="原价">({{ toThousands(record.origPrice) }})</span>
           </template>
         </s-table>
       </a-card>
@@ -200,7 +205,7 @@ export default {
         // { title: '本次下推金额', dataIndex: 'totalAmount', width: '8%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } }
       ]
       if (this.$hasPermissions('B_dispatchDetail_salesPrice')) { //  售价权限
-        arr.splice(5, 0, { title: '销售价格', dataIndex: 'price', width: '8%', align: 'right', customRender: text => ((text || text == 0) ? this.toThousands(text) : '--') })
+        arr.splice(5, 0, { title: '销售价格', dataIndex: 'price', width: '8%', align: 'right', scopedSlots: { customRender: 'price' }, })
         arr.splice(9, 0, { title: '本次下推金额', dataIndex: 'totalAmount', width: '8%', align: 'right', customRender: text => ((text || text == 0) ? this.toThousands(text) : '--') })
       }
       if (this.$hasPermissions('B_dispatchDetail_cityPrice')) { //  市级权限

+ 342 - 0
src/views/salesManagement/pushOrderManagement/detailForOut.vue

@@ -0,0 +1,342 @@
+<template>
+  <div class="salesDetail-wrap">
+    <a-spin :spinning="spinning" tip="Loading...">
+      <a-page-header :ghost="false" :backIcon="false" class="salesDetail-cont" :style="{ padding: !outBizSubSn ? '16px 24px' : '0px 24px' }">
+        <template slot="subTitle" v-if="!outBizSubSn&&!bizSn">
+          <a href="javascript:;" @click="handleBack"><a-icon type="left"></a-icon> 返回列表</a>
+        </template>
+        <template slot="extra">
+          <a-button
+            key="4"
+            type="primary"
+            class="button-info"
+            id="salesDetail-fhdy-print-btn"
+            :disabled="localDataSource.length==0"
+            v-if="$hasPermissions('B_dispatchPrint')"
+            @click="handlePrint('DISPATCH_BILL')">发货打印</a-button>
+          <a-button
+            key="3"
+            type="default"
+            class="button-info"
+            id="salesDetail-fhfl-print-btn"
+            :disabled="localDataSource.length==0"
+            @click="handlePrint('DISPATCH_BILL_TYPE')">发货分类打印</a-button>
+          <a-divider type="vertical" />
+          <a-button
+            key="2"
+            type="primary"
+            class="button-info"
+            id="purchaseOrderDetail-export-btn"
+            :disabled="localDataSource.length==0"
+            v-if="$hasPermissions('B_dispatchExport')"
+            @click="openExcelModal=true">导出Excel</a-button>
+          <a-button
+            key="1"
+            type="default"
+            class="button-info"
+            id="salesDetail-fhfl-print-btn"
+            :disabled="localDataSource.length==0"
+            v-if="$hasPermissions('B_dispatchTypeExport')"
+            @click="handleFlExport('DISPATCH_BILL_TYPE')">发货分类导出</a-button>
+        </template>
+      </a-page-header>
+      <!-- 基础信息 -->
+      <a-card size="small" :bordered="false" class="salesDetail-cont">
+        <a-collapse :activeKey="['1']">
+          <a-collapse-panel key="1" header="基础信息">
+            <a-descriptions size="small" :column="3">
+              <a-descriptions-item label="客户名称">{{ detailData&&detailData.buyerName || '--' }}</a-descriptions-item>
+              <a-descriptions-item label="销售单号">{{ detailData&&detailData.salesBillNo || '--' }}</a-descriptions-item>
+              <a-descriptions-item label="备货单号">{{ detailData&&detailData.dispatchBillNo || '--' }}</a-descriptions-item>
+              <a-descriptions-item label="收货客户名称">{{ detailData&&detailData.receiverName || '--' }}</a-descriptions-item>
+              <a-descriptions-item label="发货编号">{{ detailData&&detailData.sendNo || '--' }}</a-descriptions-item>
+              <a-descriptions-item label="收款方式">{{ detailData&&detailData.settleStyleSnDictValue || '--' }}</a-descriptions-item>
+              <a-descriptions-item label="收货人" v-if="detailData&&detailData.salesBillExtEntity">{{ detailData&&detailData.salesBillExtEntity&&detailData.salesBillExtEntity.consigneeName || '--' }}</a-descriptions-item>
+              <a-descriptions-item label="收货电话" v-if="detailData&&detailData.salesBillExtEntity">{{ detailData&&detailData.salesBillExtEntity&&detailData.salesBillExtEntity.consigneeTel || '--' }}</a-descriptions-item>
+              <a-descriptions-item label="收货地址" :span="2" v-if="detailData&&detailData.salesBillExtEntity">
+                {{ detailData&&detailData.salesBillExtEntity&&detailData.salesBillExtEntity.shippingAddrProvinceName || '' }}
+                {{ detailData&&detailData.salesBillExtEntity&&detailData.salesBillExtEntity.shippingAddrCityName || '' }}
+                {{ detailData&&detailData.salesBillExtEntity&&detailData.salesBillExtEntity.shippingAddrCountyName || '' }}
+                {{ detailData&&detailData.salesBillExtEntity&&detailData.salesBillExtEntity.shippingAddr || '' }}
+              </a-descriptions-item>
+              <a-descriptions-item label="业务状态">{{ detailData&&detailData.billStatusDictValue || '--' }}</a-descriptions-item>
+              <a-descriptions-item label="备注">{{ detailData&&detailData.remarks || '--' }}</a-descriptions-item>
+            </a-descriptions>
+          </a-collapse-panel>
+        </a-collapse>
+      </a-card>
+      <a-card size="small" :bordered="false" class="pages-wrap">
+        <!-- alert -->
+        <a-alert type="info" style="margin-bottom: 10px;" v-if="detailData!=null">
+          <div slot="message">
+            <span v-if="$route.params.type!='stockOut'">
+              总销售数量:<strong>{{ detailData&&(detailData.totalSalesQty || detailData.totalSalesQty==0) ? detailData.totalSalesQty : '--' }}</strong>;
+            </span>
+            本次下推数量:<strong>{{ detailData&&(detailData.totalQty || detailData.totalQty==0) ? detailData.totalQty : '--' }}</strong>;
+            <span v-if="$hasPermissions('B_dispatchDetail_salesPrice')">本次下推金额:<strong>{{ detailData&&(detailData.totalAmount || detailData.totalAmount==0) ? toThousands(detailData.totalAmount) : '--' }}</strong>;</span>
+            <span v-if="$route.params.type!='stockOut'&&$hasPermissions('B_dispatchDetail_cityPrice')">
+              本次下推市级价金额:<strong>{{ detailData&&(detailData.totalCityAmount || detailData.totalCityAmount==0) ? toThousands(detailData.totalCityAmount) : '--' }}</strong>;
+            </span>
+          </div>
+        </a-alert>
+        <!-- 列表 -->
+        <s-table
+          class="sTable"
+          ref="table"
+          size="small"
+          :rowKey="(record) => record.no"
+          rowKeyName="no"
+          :columns="($route.params.type=='stockOut' || outBizSubSn) ? outColumns : columns"
+          :data="loadData"
+          :scroll="{ y: 500 }"
+          :defaultLoadData="false"
+          bordered>
+          <!-- 产品编码 -->
+          <template slot="productCode" slot-scope="text, record">
+            <span>{{ text }}</span>
+            <a-badge count="促" v-if="record.promotionFlag=='GIFT'" :number-style="{ backgroundColor: '#52c41a', zoom:'80%' }"></a-badge>
+            <a-badge count="特" v-if="record.promotionFlag=='DISCOUNT'" :number-style="{ backgroundColor: '#faad14', zoom:'80%' }"></a-badge>
+          </template>
+           <!-- 销售价 -->
+          <template slot="price" slot-scope="text, record">
+            {{ toThousands(text) }}
+            <span v-if="record.promotionFlag=='GIFT'||record.promotionFlag=='DISCOUNT'" title="原价">({{ toThousands(record.origPrice) }})</span>
+          </template>
+        </s-table>
+      </a-card>
+    </a-spin>
+    <!-- 发货分类打印 -->
+    <sendTypeModal
+      ref="typePrint"
+      :hasNoPrint="hasNoPrint"
+      :nowType="nowType"
+      :openModal="openModal"
+      @ok="handlePrintOk"
+      @close="openModal=false" />
+    <!-- 导出Excel -->
+    <export-excel-modal :openModal="openExcelModal" :itemData="detailData" @ok="handleExcelOk" @close="openExcelModal=false" />
+    <!-- 打印 -->
+    <div id="print"></div>
+  </div>
+</template>
+
+<script>
+import { commonMixin } from '@/utils/mixin'
+import { STable, VSelect } from '@/components'
+import sendTypeModal from './sendTypeModal.vue'
+import exportExcelModal from './exportExcelModal.vue'
+import { printBase64Fun, exportExcel } from '@/libs/JGPrint.js'
+import { dispatchDetaillListForOut, dispatchFindBySn, dispatchDetailPrint, dispatchDetailExcel } from '@/api/dispatch'
+export default {
+  name: 'detailForOut',
+  mixins: [commonMixin],
+  components: { STable, VSelect, sendTypeModal, exportExcelModal },
+  props: {
+    outBizSubSn: { //  有值则为弹框,无值则为页面
+      type: [Number, String],
+      default: ''
+    },
+    bizSn: { //  有值则为弹框,无值则为页面
+      type: [Number, String],
+      default: ''
+    }
+  },
+  data () {
+    return {
+      disabled: false,
+      spinning: false,
+      outColumns: [
+        { title: '序号', dataIndex: 'no', width: '6%', align: 'center' },
+        { title: '产品编码', dataIndex: 'productCode', width: '25%', scopedSlots: { customRender: 'productCode' }, align: 'center' },
+        { title: '产品名称', dataIndex: 'productName', width: '33%', align: 'center', customRender: function (text) { return text || '--' }, ellipsis: true },
+        { title: '原厂编码', dataIndex: 'productOrigCode', width: '20%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '单位', dataIndex: 'productOrigUnit', width: '6%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '本次出库数', dataIndex: 'qty', width: '10%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } }
+      ],
+      // 加载数据方法 必须为 Promise 对象
+      loadData: parameter => {
+        this.disabled = true
+        return dispatchDetaillListForOut(Object.assign(parameter, { dispatchBillSn: this.outBizSubSn || this.bizSn || this.$route.params.sn })).then(res => {
+          let data
+          if (res.status == 200) {
+            data = res.data
+            const no = (data.pageNo - 1) * data.pageSize
+            for (var i = 0; i < data.list.length; i++) {
+              data.list[i].no = no + i + 1
+              const productCode = (data.list[i].productEntity && data.list[i].productEntity.code) || (data.list[i].dealerProductEntity && data.list[i].dealerProductEntity.code)
+              const productName = (data.list[i].productEntity && data.list[i].productEntity.name) || (data.list[i].dealerProductEntity && data.list[i].dealerProductEntity.name)
+              const productOrigCode = (data.list[i].productEntity && data.list[i].productEntity.origCode) || (data.list[i].dealerProductEntity && data.list[i].dealerProductEntity.origCode)
+              const productOrigUnit = (data.list[i].productEntity && data.list[i].productEntity.unit) || (data.list[i].dealerProductEntity && data.list[i].dealerProductEntity.unit)
+              data.list[i].productCode = productCode || '--'
+              data.list[i].productName = productName || '--'
+              data.list[i].productOrigCode = productOrigCode == ' ' ? '--' : productOrigCode
+              data.list[i].productOrigUnit = productOrigUnit || '--'
+            }
+            this.localDataSource = data.list
+            this.disabled = false
+          }
+          return data
+        })
+      },
+      detailData: null, //  详情数据
+      openModal: false,
+      localDataSource: [],
+      nowPrintType: '', //  当前打印类型
+      openExcelModal: false,
+      fromRouter: null,
+      nowType: 'print'
+    }
+  },
+  computed: {
+    hasNoPrint () {
+      return this.detailData && (this.detailData.printStatus == 'UNABLE_PRINT' || this.detailData.printStatus == 'CANCEL_PRINT')
+    },
+    columns () {
+      const arr = [
+        { title: '序号', dataIndex: 'no', width: '4%', align: 'center' },
+        { title: '产品编码', dataIndex: 'productCode', width: '19%', scopedSlots: { customRender: 'productCode' }, align: 'center' },
+        { title: '产品名称', dataIndex: 'productName', width: '10%', align: 'center', customRender: function (text) { return text || '--' }, ellipsis: true },
+        { title: '原厂编码', dataIndex: 'productOrigCode', width: '19%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '单位', dataIndex: 'productOrigUnit', width: '6%', align: 'center', customRender: function (text) { return text || '--' } },
+        // { title: '销售价格', dataIndex: 'price', width: '8%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
+        // { title: '市级销售价格', dataIndex: 'cityPrice', width: '10%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
+        { title: '销售数量', dataIndex: 'salesQty', width: '8%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
+        { title: '本次下推数', dataIndex: 'qty', width: '8%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } }
+        // { title: '本次下推金额', dataIndex: 'totalAmount', width: '8%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } }
+      ]
+      if (this.$hasPermissions('B_dispatchDetail_salesPrice')) { //  售价权限
+        arr.splice(5, 0, { title: '销售价格', dataIndex: 'price', width: '8%', align: 'right', scopedSlots: { customRender: 'price' }, })
+        arr.splice(9, 0, { title: '本次下推金额', dataIndex: 'totalAmount', width: '8%', align: 'right', customRender: text => ((text || text == 0) ? this.toThousands(text) : '--') })
+      }
+      if (this.$hasPermissions('B_dispatchDetail_cityPrice')) { //  市级权限
+        arr.splice(6, 0, { title: '市级销售价格', dataIndex: 'cityPrice', width: '10%', align: 'right', customRender: text => ((text || text == 0) ? this.toThousands(text) : '--') })
+      }
+      return arr
+    }
+  },
+  methods: {
+    //  返回
+    handleBack () {
+      this.$router.push({ name: 'pushOrderManagementList' })
+    },
+    //  详情
+    getDetail () {
+      dispatchFindBySn({ dispatchBillSn: this.outBizSubSn || this.bizSn || this.$route.params.sn }).then(res => {
+        if (res.status == 200) {
+          this.detailData = res.data
+        } else {
+          this.detailData = null
+        }
+      })
+    },
+    // 导出Excel
+    handleExcelOk (priceType, data, fileName) {
+      const _this = this
+      const params = {
+        dispatchBillSn: this.outBizSubSn || this.bizSn || this.$route.params.sn,
+        printType: priceType,
+        ...data
+      }
+      this.spinning = true
+      exportExcel(dispatchDetailExcel, params, fileName, function () {
+        _this.spinning = false
+        _this.$store.state.app.curActionPermission = ''
+      })
+    },
+    // 发货分类导出
+    handleFlExport () {
+      this.openModal = true
+      this.nowType = 'export'
+      this.$refs.typePrint.setData(this.detailData, this.outBizSubSn || this.bizSn || this.$route.params.sn)
+    },
+    // 打印预览/快捷打印
+    handlePrint (type) {
+      this.nowPrintType = type
+      if (type == 'DISPATCH_BILL') { // 发货打印
+        const params = {
+          dispatchBillSn: this.detailData.dispatchBillSn,
+          dispatchBillNo: this.detailData.dispatchBillNo
+        }
+        this.$store.state.app.curActionPermission = 'B_dispatchPrint'
+        this.handlePrintOk(params, '发货', 'preview')
+      } else if (type == 'DISPATCH_BILL_TYPE') { // 发货分类打印
+        this.openModal = true
+        this.nowType = 'print'
+        this.$refs.typePrint.setData(this.detailData, this.outBizSubSn || this.bizSn || this.$route.params.sn)
+      }
+    },
+    // 发货分类打印,导出
+    handlePrintOk (obj, taskName, type) {
+      const _this = this
+      const params = {
+        type: this.nowPrintType,
+        dispatchBillSn: this.outBizSubSn || this.bizSn || this.$route.params.sn
+      }
+      // 打印
+      if (type != 'export') {
+        _this.spinning = true
+
+        // 货位编号
+        if (obj.orderBy) {
+          params.type = params.type + '_STACK_PLACE'
+        }
+        // 原厂编码
+        if(obj.origCode == 1){
+          params.type = params.type + '_ORIG_CODE'
+        }
+        // 装箱号
+        if(obj.packNo == 1){
+          params.type = params.type + '_PACK_NUM'
+        }
+        printBase64Fun(
+          dispatchDetailPrint,
+          Object.assign(params, obj || {}),
+          type,
+          taskName,
+          () => { 
+            _this.spinning = false
+            _this.$store.state.app.curActionPermission = ''
+          },
+          {
+            billType: 'DISPATCH',
+            billSn: obj.dispatchBillSn,
+            billNo: obj.dispatchBillNo,
+            printType: taskName + '打印'
+          }, this.hasNoPrint)
+      } else {
+        this.handleExcelOk('DISPATCH_BILL_TYPE', obj, taskName)
+      }
+    }
+  },
+  mounted () {
+    if (!this.$store.state.app.isNewTab || this.outBizSubSn || this.bizSn) { // 页签刷新 或 为弹框时调用
+      this.$refs.table.refresh(true)
+      this.getDetail()
+    }
+  },
+  activated () {
+    // 如果是新页签打开或者进入新的子页(例:存在列表第2条数据编辑页页签时再打开第4条数据的编辑页),则重置当前页面
+    if (this.$store.state.app.isNewTab || !this.$store.state.app.isNewSubTab) {
+      this.$refs.table.refresh(true)
+      this.getDetail()
+    }
+  },
+  beforeRouteEnter (to, from, next) {
+    next(vm => {
+      vm.fromRouter = from
+    })
+  }
+}
+</script>
+
+<style lang="less">
+  .salesDetail-wrap{
+    .salesDetail-cont{
+      margin-bottom: 10px;
+    }
+    .footer-cont{
+      margin-top: 5px;
+      text-align: center;
+    }
+  }
+</style>

+ 1 - 1
src/views/salesManagement/pushOrderManagement/list.vue

@@ -199,7 +199,7 @@ import Area from '@/views/common/area.js'
 import chooseWarehouse from '@/views/common/chooseWarehouse'
 import dealerSubareaScopeList from '@/views/common/dealerSubareaScopeList.vue'
 import commonModal from '@/views/common/commonModal.vue'
-import salesDetail from '@/views/salesManagement/salesQuery/detail.vue'
+import salesDetail from '@/views/salesManagement/salesQueryNew/detailAll.vue'
 import explainInfoModal from './explainInfoModal.vue'
 import { dispatchlList, dispatchQueryCount, dispatchPrintStatus } from '@/api/dispatch'
 export default {

+ 2 - 2
src/views/salesManagement/pushOrderManagement/sendTypeModal.vue

@@ -42,8 +42,8 @@
         </a-form-model-item>
         <a-form-model-item label="货位编号" prop="orderBy" v-if="nowType=='print'">
           <a-radio-group v-model="form.orderBy">
-            <a-radio value="dispatch_bill_detail.STACK_PLACE_CODE ASC">打印(↑升序)</a-radio>
-            <a-radio value="dispatch_bill_detail.STACK_PLACE_CODE DESC">打印(↓降序)</a-radio>
+            <a-radio value="dispDet.STACK_PLACE_CODE ASC">打印(↑升序)</a-radio>
+            <a-radio value="dispDet.STACK_PLACE_CODE DESC">打印(↓降序)</a-radio>
             <a-radio value="-1">不打印</a-radio>
           </a-radio-group>
         </a-form-model-item>

+ 1 - 1
src/views/salesManagement/salesCollection/list.vue

@@ -213,7 +213,7 @@ import rangeDate from '@/views/common/rangeDate.vue'
 import subarea from '@/views/common/subarea.js'
 import Area from '@/views/common/area.js'
 import commonModal from '@/views/common/commonModal.vue'
-import salesDetail from '@/views/salesManagement/salesQuery/detail.vue'
+import salesDetail from '@/views/salesManagement/salesQueryNew/detailAll.vue'
 import dispatchDetail from '@/views/salesManagement/pushOrderManagement/detail.vue'
 import voucherModal from './voucherModal.vue'
 import dealerSubareaScopeList from '@/views/common/dealerSubareaScopeList.vue'

+ 2 - 2
src/views/salesManagement/salesList/list.vue

@@ -180,10 +180,10 @@ import subarea from '@/views/common/subarea.js'
 import Area from '@/views/common/area.js'
 import dealerSubareaScopeList from '@/views/common/dealerSubareaScopeList.vue'
 import commonModal from '@/views/common/commonModal.vue'
-import salesDetail from '@/views/salesManagement/salesQuery/detail.vue'
+import salesDetail from '@/views/salesManagement/salesQueryNew/detailAll.vue'
 import dispatchDetail from '@/views/salesManagement/pushOrderManagement/detail.vue'
 import detailModal from '@/views/salesManagement/sendOutOrder/detailModal.vue'
-import { salesOverviewQueryPage } from '@/api/sales'
+import { salesOverviewQueryPage } from '@/api/salesNew'
 export default {
   name: 'SalesListManagementList',
   mixins: [commonMixin],

+ 6 - 6
src/views/salesManagement/salesOrderWarehouse/detail.vue

@@ -50,7 +50,8 @@
           class="sTable"
           ref="table"
           size="small"
-          :rowKey="(record) => record.id"
+          :rowKey="(record) => record.no"
+          rowKeyName="no"
           :columns="columns"
           :data="loadData"
           :scroll="{ y: 500 }"
@@ -58,10 +59,9 @@
           bordered>
           <!-- 产品编码 -->
           <template slot="productCode" slot-scope="text, record">
-            <a-badge count="促" v-if="record.promotionFlag == 1">
-              <div style="padding-right: 15px;">{{ text }}</div>
-            </a-badge>
-            <span v-else>{{ text }}</span>
+            <span>{{ text }}</span>
+            <a-badge count="促" v-if="record.promotionFlag=='GIFT'" :number-style="{ backgroundColor: '#52c41a', zoom:'80%' }"></a-badge>
+            <a-badge count="特" v-if="record.promotionFlag=='DISCOUNT'" :number-style="{ backgroundColor: '#faad14', zoom:'80%' }"></a-badge>
           </template>
         </s-table>
       </a-card>
@@ -76,7 +76,7 @@ import { commonMixin } from '@/utils/mixin'
 import { STable, VSelect } from '@/components'
 import moment from 'moment'
 import { exportExcel } from '@/libs/JGPrint.js'
-import { queryPageForWarehouseDetail, queryCountForWarehouseDetail, salesDetailBySn, salesDetailExcel } from '@/api/sales'
+import { queryPageForWarehouseDetail, queryCountForWarehouseDetail, salesDetailBySn, salesDetailExcel } from '@/api/salesNew'
 import printModal from './printModal.vue'
 export default {
   name: 'SalesOrderWarehouseDetail',

+ 4 - 3
src/views/salesManagement/salesOrderWarehouse/list.vue

@@ -62,8 +62,8 @@
               >导出</a-button>
             </a-col>
           </a-row>
-          </a-form>
-        </a-form-model></div>
+        </a-form-model>
+      </div>
       <!-- alert -->
       <a-alert type="info" style="margin-bottom:10px">
         <div slot="message">
@@ -87,6 +87,7 @@
         <!-- 单号 -->
         <template slot="stockOutNo" slot-scope="text, record" v-if="$hasPermissions('B_salesOrderWarehouseDetail')">
           <span class="link-bule" @click="handleDetail(record)">{{ record.salesBillNo }}</span>
+          <a-badge count="促" v-if="record.promoFlag==1" :number-style="{ backgroundColor: '#52c41a', zoom:'80%' }"></a-badge>
         </template>
       </s-table>
     </a-spin>
@@ -104,7 +105,7 @@ import Area from '@/views/common/area.js'
 import reportModal from '@/views/common/reportModal.vue'
 import { STable, VSelect } from '@/components'
 import chooseWarehouse from '@/views/common/chooseWarehouse'
-import { queryPageForWarehouse, queryCountForWarehouse, exportForWarehouse } from '@/api/sales'
+import { queryPageForWarehouse, queryCountForWarehouse, exportForWarehouse } from '@/api/salesNew'
 import dealerSubareaScopeList from '@/views/common/dealerSubareaScopeList.vue'
 import { hdExportExcel } from '@/libs/exportExcel'
 export default {

+ 0 - 1
src/views/salesManagement/salesOrderWarehouse/printModal.vue

@@ -42,7 +42,6 @@
 </template>
 
 <script>
-import { salesDetailProductType } from '@/api/sales'
 export default {
   props: {
     openModal: { //  弹框显示状态

+ 3 - 3
src/views/salesManagement/salesQuery/detail.vue

@@ -121,14 +121,14 @@
           bordered>
           <!-- 产品编码 -->
           <template slot="productCode" slot-scope="text, record">
-            <div v-if="(record.promotionFlag == 1) || (Number(record.stockQty) < Number(record.unpushedQty)) && (detailData&&(detailData.billStatus == 'WAIT_AUDIT'||detailData.billStatus == 'HQ_CHANGE')&&$hasPermissions('B_salesAudit'))">
+            <div>
               <span>{{ text }}</span>
-              <a-badge count="促" :number-style="{ backgroundColor: '#f90' }" v-if="record.promotionFlag == 1"></a-badge>
+              <a-badge count="促" v-if="record.promotionFlag=='GIFT'" :number-style="{ backgroundColor: '#52c41a', zoom:'80%' }"></a-badge>
+              <a-badge count="特" v-if="record.promotionFlag=='DISCOUNT'" :number-style="{ backgroundColor: '#faad14', zoom:'80%' }"></a-badge>
               <!-- 可审核时才可显示“缺”货产品 -->
               <a-badge count="缺" v-if="(Number(record.stockQty) < Number(record.unpushedQty)) && (detailData&&(detailData.billStatus == 'WAIT_AUDIT'||detailData.billStatus == 'HQ_CHANGE')&&$hasPermissions('B_salesAudit'))">
               </a-badge>
             </div>
-            <span v-if="!(record.promotionFlag == 1 || ((Number(record.stockQty) < Number(record.unpushedQty)) && (detailData&&(detailData.billStatus == 'WAIT_AUDIT'||detailData.billStatus == 'HQ_CHANGE')&&$hasPermissions('B_salesAudit'))))">{{ text }}</span>
           </template>
           <!-- 当前库存 -->
           <template slot="stockQty" slot-scope="text, record">

+ 1 - 24
src/views/salesManagement/salesQuery/edit.vue

@@ -243,7 +243,7 @@ import chooseWarehouse from '@/views/common/chooseWarehouse'
 import ProductBrand from '@/views/common/productBrand.js'
 import productTypeAll from '@/views/common/productTypeAll.js'
 import { salesModify, salesDetailBySn, salesWriteSubmit, getPromoacActiveList, deleteAll, submitCheck, updateBatch, updateWarehouse } from '@/api/sales'
-import { salesDetailStockList, salesDetailInsert, salesDetailUpdateQty, salesDetailDel, salesDetailBatchDel, salesDetailDelAll, addPromoGoods, salesBatchInsert } from '@/api/salesDetail'
+import { salesDetailStockList, salesDetailInsert, salesDetailUpdateQty, salesDetailDel, salesDetailBatchDel, addPromoGoods, salesBatchInsert } from '@/api/salesDetail'
 export default {
   name: 'SalesEdit',
   mixins: [commonMixin],
@@ -522,29 +522,6 @@ export default {
     handleBack () {
       this.$router.push({ path: '/salesManagement/salesQuery/list', query: { closeLastOldTab: true } })
     },
-    // 整单删除
-    delSalerDetailAll () {
-      const _this = this
-      this.$confirm({
-        title: '提示',
-        content: '确认要整单删除吗?',
-        centered: true,
-        closable: true,
-        onOk () {
-          _this.delLoading = true
-          _this.spinning = true
-          salesDetailDelAll({ salesBillSn: _this.salesBillSn }).then(res => {
-            if (res.status == 200) {
-              _this.resetSearchForm()
-              _this.$refs.promotable.resetCurForm()
-              _this.$message.success(res.message)
-            }
-            _this.delLoading = false
-            _this.spinning = false
-          })
-        }
-      })
-    },
     // 删除产品
     handleDel (row) {
       const _this = this

+ 0 - 15
src/views/salesManagement/salesQuery/importGuideModal.vue

@@ -71,8 +71,6 @@
 import { commonMixin } from '@/utils/mixin'
 import ChooseImportModal from './chooseImportModal.vue'
 import { Upload } from '@/components'
-import { hdExportExcel } from '@/libs/exportExcel'
-import { salesDownload } from '@/api/salesDetail'
 export default {
   name: 'SalesImportGuideModal',
   mixins: [commonMixin],
@@ -130,19 +128,6 @@ export default {
       this.openImportModal = false
       this.isShow = false
     }
-    //  导出
-    // handleExport () {
-    //   const _this = this
-    //   const params = { grabFlag: this.params.grabFlag }
-    //   this.exportLoading = true
-    //   this.spinning = true
-    //   setTimeout(() => {
-    //     _this.exportLoading = false
-    //   }, 1000)
-    //   hdExportExcel(salesDownload, params, '销售导入模板', function () {
-    //     _this.spinning = false
-    //   })
-    // }
   },
   watch: {
     //  父页面传过来的弹框状态

+ 4 - 4
src/views/salesManagement/salesQuery/list.vue

@@ -399,15 +399,15 @@ export default {
         { title: '备货打印状态', dataIndex: 'printStatusDictValue', width: '5%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
         { title: '操作', scopedSlots: { customRender: 'action' }, width: '7%', align: 'center' }
       ]
+      if (this.$hasPermissions('M_salesQueryList_salesPrice')) { // 售价权限
+        arr.splice(6, 0, { title: '总售价', dataIndex: 'totalAmount', width: '4%', align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } })
+        arr.splice(8, 0, { title: '下推总金额', dataIndex: 'totalPushedAmount', width: '4%', align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } })
+      }
       if (this.showCancelNum) {
         const ind = this.$hasPermissions('M_salesQueryList_salesPrice') ? 10 : 8
         arr.splice(ind, 0, { title: '已取消数量', dataIndex: 'totalCancelQty', width: '4%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } })
         arr.splice(ind + 1, 0, { title: '待下推数量', dataIndex: 'totalUnpushedQty', width: '4%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } })
       }
-      if (this.$hasPermissions('M_salesQueryList_salesPrice')) { // 售价权限
-        arr.splice(6, 0, { title: '总售价', dataIndex: 'totalAmount', width: '4%', align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } })
-        arr.splice(8, 0, { title: '下推总金额', dataIndex: 'totalPushedAmount', width: '4%', align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } })
-      }
       return arr
     }
   },

+ 217 - 0
src/views/salesManagement/salesQueryNew/chooseCustomModal.vue

@@ -0,0 +1,217 @@
+<template>
+  <a-modal
+    v-model="opened"
+    :title="title"
+    centered
+    :maskClosable="false"
+    :confirmLoading="confirmLoading"
+    :width="800"
+    :footer="null"
+    @cancel="cancel"
+  >
+    <a-spin :spinning="spinning" tip="Loading...">
+      <a-form-model
+        id="chooseCustom-form"
+        ref="ruleForm"
+        :model="form"
+        :rules="rules"
+        :label-col="formItemLayout.labelCol"
+        :wrapper-col="formItemLayout.wrapperCol">
+        <a-form-model-item label="客户名称" prop="buyerSn">
+          <dealerSubareaScopeList ref="dealerSubareaScopeList" id="chooseCustom-buyerSn" defValKey="buyerSn" @change="custChange" v-model="form.buyerSn" />
+        </a-form-model-item>
+        <a-form-model-item label="支付方式" prop="settleStyleSn">
+          <v-select
+            code="SETTLE_STYLE"
+            id="chooseCustom-settleStyleSn"
+            v-model="form.settleStyleSn"
+            allowClear
+            placeholder="请选择支付方式"></v-select>
+        </a-form-model-item>
+        <a-form-model-item prop="consigneeTel">
+          <span slot="label">收货地址</span>
+          {{ chooseAddr }}
+          <a-button type="link" :disabled="!form.buyerSn" id="chooseCustom-chooseAddr" @click="handleChoose">{{ addressVal }} >></a-button>
+        </a-form-model-item>
+        <a-form-model-item :wrapper-col="{ span: 12, offset: 6 }" style="text-align: center;">
+          <a-button type="primary" :loading="confirmLoading" @click="handleSubmit" id="chooseCustom-btn-submit">保存</a-button>
+          <a-button @click="cancel" style="margin-left: 15px" id="chooseCustom-btn-back">取消</a-button>
+        </a-form-model-item>
+      </a-form-model>
+    </a-spin>
+    <!-- 选择地址 -->
+    <choose-address-modal :openModal="openAddrModal" :paramsData="form.buyerSn" @ok="handleOk" @verify="verifyFun" @close="openAddrModal=false" />
+  </a-modal>
+</template>
+
+<script>
+import { commonMixin } from '@/utils/mixin'
+import { VSelect } from '@/components'
+import dealerSubareaScopeList from '@/views/common/dealerSubareaScopeList.vue'
+import chooseAddressModal from './receivingAddress/chooseAddressModal.vue'
+import { dealerRecevieAddrQuery } from '@/api/dealerRecevieAddr'
+import chooseWarehouse from '@/views/common/chooseWarehouse'
+import { salesSave } from '@/api/salesNew'
+export default {
+  name: 'SalesChooseCustomModal',
+  mixins: [commonMixin],
+  components: { VSelect, dealerSubareaScopeList, chooseAddressModal, chooseWarehouse },
+  props: {
+    show: [Boolean]
+  },
+  data () {
+    return {
+      opened: this.show,
+      spinning: false,
+      title: '选择客户',
+      confirmLoading: false,
+      formItemLayout: {
+        labelCol: { span: 4 },
+        wrapperCol: { span: 18 }
+      },
+      form: {
+        buyerSn: undefined, // 客户sn
+        buyerName: '',
+        settleStyleSn: undefined,
+        shippingAddrProvinceSn: '',
+        shippingAddrProvinceName: '', // 省
+        shippingAddrCitySn: '',
+        shippingAddrCityName: '', // 市
+        shippingAddrCountySn: '',
+        shippingAddrCountyName: '', // 区
+        shippingAddr: '', // 详细地址
+        consigneeTel: '', // 联系电话
+        consigneeName: '', // 联系人名称
+        warehouseSn: undefined
+      },
+      rules: {
+        buyerSn: [ { required: true, message: '请选择客户', trigger: ['change', 'blur'] } ],
+        settleStyleSn: [ { required: true, message: '请选择支付方式', trigger: ['change', 'blur'] } ],
+        consigneeTel: [ { required: true, message: '请选择收货地址', trigger: ['change', 'blur'] } ]
+      },
+      addressVal: '选择地址', //  选择地址/更换地址
+      chooseAddr: '', //  当前已选地址信息
+      openAddrModal: false // 选择地址弹框是否显示
+    }
+  },
+  methods: {
+
+    // 客户 change
+    custChange (val) {
+      if (val && val.key) {
+        this.form.buyerSn = val.key || undefined
+        this.form.buyerName = val.name || ''
+        this.$refs.ruleForm.clearValidate()
+        this.getDefaultAddress()
+        if (val.row) {
+          // this.form.warehouseSn = val.row.defaultWarehouseSn
+        }
+      } else {
+        this.form.buyerName = ''
+        this.form.buyerSn = undefined
+        this.form.warehouseSn = undefined
+        this.verifyFun(this.addressId)
+      }
+    },
+    //  选择地址
+    handleChoose () {
+      this.openAddrModal = true
+    },
+    //  保存
+    handleSubmit (e) {
+      e.preventDefault()
+      const _this = this
+      this.$refs.ruleForm.validate(valid => {
+        if (valid) {
+          _this.salesSaveFun()
+        } else {
+          console.log('error submit!!')
+          return false
+        }
+      })
+    },
+    // 新建或编辑销售单
+    salesSaveFun () {
+      const _this = this
+      const form = this.form
+      _this.spinning = true
+      salesSave(form).then(res => {
+        if (res.status == 200) {
+          _this.$message.success(res.message)
+          _this.$emit('ok', res.data)
+          if (_this.form.id) {
+            _this.$emit('updateData')
+          }
+          _this.cancel()
+          _this.spinning = false
+        } else {
+          _this.spinning = false
+        }
+      })
+    },
+    cancel () {
+      this.opened = false
+      this.$emit('cancel')
+      this.$refs.ruleForm.resetFields()
+    },
+    //  地址保存
+    handleOk (data) {
+      this.chooseAddr = (data.consigneeName || '') + '(' + (data.consigneeTel || '-') + ')' + ' ' + (data.address || '')
+      this.addressVal = '更换地址'
+      this.form.shippingAddrProvinceSn = data.provinceSn || ''
+      this.form.shippingAddrProvinceName = data.provinceName || '' // 省
+      this.form.shippingAddrCitySn = data.citySn || ''
+      this.form.shippingAddrCityName = data.cityName || '' // 市
+      this.form.shippingAddrCountySn = data.countySn || ''
+      this.form.shippingAddrCountyName = data.countyName || '' // 区
+      this.form.shippingAddr = data.addr || ''// 详细地址
+      this.form.consigneeTel = data.consigneeTel || '' // 联系电话
+      this.form.consigneeName = data.consigneeName || ''
+      this.addressId = data.id || undefined
+      this.openAddrModal = false
+      // 移除表单项的校验结果
+      this.$refs.ruleForm.clearValidate('consigneeTel')
+    },
+    verifyFun (id) {
+      if (id == this.addressId) {
+        this.chooseAddr = ''
+        this.addressVal = '选择地址'
+        this.form.shippingAddrProvinceSn = ''
+        this.form.shippingAddrProvinceName = ''// 省
+        this.form.shippingAddrCitySn = ''
+        this.form.shippingAddrCityName = '' // 市
+        this.form.shippingAddrCountySn = ''
+        this.form.shippingAddrCountyName = '' // 区
+        this.form.shippingAddr = ''// 详细地址
+        this.form.consigneeTel = '' // 联系电话
+        this.form.consigneeName = ''
+      }
+    },
+    // 获取默认地址
+    getDefaultAddress () {
+      dealerRecevieAddrQuery({ defaultFlag: 1, dealerSn: this.form.buyerSn }).then(res => {
+        if (res.status == 200) {
+          if (res.data.length == 1) {
+            const ret = res.data[0]
+            ret.address = (ret.provinceName ? (ret.provinceName + '-') : '') + (ret.cityName ? (ret.cityName + '-') : '') + (ret.countyName ? (ret.countyName + '-') : '') + ret.addr
+            this.addressId = ret.id || undefined
+            this.handleOk(ret)
+          } else {
+            this.verifyFun(this.addressId)
+          }
+        }
+      })
+    }
+  },
+  watch: {
+    show (newValue, oldValue) {
+      this.opened = newValue
+      if (!newValue) {
+        this.$refs.dealerSubareaScopeList.resetForm()
+        this.$refs.ruleForm.resetFields()
+        this.verifyFun(this.addressId)
+      }
+    }
+  }
+}
+</script>

+ 309 - 0
src/views/salesManagement/salesQueryNew/comps/activeQueryPart.vue

@@ -0,0 +1,309 @@
+<template>
+  <div class="productInfoList-wrap">
+    <!-- 搜索条件 -->
+    <div class="table-page-search-wrapper">
+      <a-form layout="inline" @keyup.enter.native="searchForm">
+        <a-row :gutter="15">
+          <a-col :md="6" :sm="24">
+            <a-form-item label="出库仓库" prop="warehouseSn" required>
+              <chooseWarehouse ref="warehouse" :allowClear="false" v-model="queryParam.warehouseSn" :isDefault="true" @load="loadWarehouse"></chooseWarehouse>
+            </a-form-item>
+          </a-col>
+          <a-col :md="6" :sm="24">
+            <a-form-item label="产品编码">
+              <a-input id="productInfoList-code" v-model.trim="queryParam.productCode" allowClear placeholder="请输入产品编码"/>
+            </a-form-item>
+          </a-col>
+          <a-col :md="6" :sm="24">
+            <a-form-item label="产品名称">
+              <a-input id="productInfoList-name" v-model.trim="queryParam.productName" allowClear placeholder="请输入产品名称"/>
+            </a-form-item>
+          </a-col>
+          <template v-if="advanced">
+            <a-col :md="6" :sm="24">
+              <a-form-item label="原厂编码">
+                <a-input id="productInfoList-origCode" v-model.trim="queryParam.productOrigCode" allowClear placeholder="请输入原厂编码"/>
+              </a-form-item>
+            </a-col>
+            <a-col :md="6" :sm="24">
+              <a-form-item label="产品品牌">
+                <ProductBrand id="productInfoList-productBrandSn" v-model="queryParam.productBrandSn"></ProductBrand>
+              </a-form-item>
+            </a-col>
+            <a-col :md="6" :sm="24">
+              <a-form-item label="产品分类">
+                <ProductType id="productInfoList-productType" v-model="productType" @change="changeProductType"></ProductType>
+              </a-form-item>
+            </a-col>
+          </template>
+          <a-col :md="6" :sm="24" style="margin-bottom: 10px;">
+            <a-button type="primary" @click="searchForm" :disabled="disabled" id="productInfoList-refresh">查询</a-button>
+            <a-button style="margin-left: 5px" @click="resetSearchForm" id="productInfoList-reset">重置</a-button>
+            <a @click="advanced=!advanced" style="margin: 0 5px">
+              {{ advanced ? '收起' : '展开' }}
+              <a-icon :type="advanced ? 'up' : 'down'"/>
+            </a>
+          </a-col>
+        </a-row>
+      </a-form>
+    </div>
+    <a-tabs type="card" @change="changeTab">
+      <a-tab-pane v-for="item in tabList" :key="item.val" :tab="item.text"></a-tab-pane>
+    </a-tabs>
+    <!-- 列表 -->
+    <s-table
+      class="sTable"
+      ref="table"
+      size="small"
+      :rowKey="(record) => record.id"
+      :columns="columns"
+      :data="loadData"
+      :customRow="handleClickRow"
+      :scroll="{ y: tableHeight, x: 1040 }"
+      :defaultLoadData="false"
+      :pageSize="50"
+      bordered>
+      <!-- 销售数量 -->
+      <template slot="nums" slot-scope="text, record">
+        <div @dblclick.stop>
+          <a-input-number
+            size="small"
+            v-model="record.salesNums"
+            :precision="0"
+            :min="1"
+            :max="999999"
+            style="width: 100%;"
+            placeholder="请输入" />
+        </div>
+      </template>
+      <!-- 价格 -->
+      <template slot="productPrice" slot-scope="text, record">
+         {{ text||text==0 ? toThousands(text) : '--' }} <span title="原价" v-if="promoProductClz == 'GIFT' || promoProductClz == 'DISCOUNT'">({{ record.origPrice||record.origPrice==0 ? toThousands(record.origPrice) : '--' }})</span>
+      </template>
+      <!-- 产品名称 -->
+      <template slot="productName" slot-scope="text, record">
+        <div class="ellipsisCon">
+          <a-tooltip placement="rightBottom">
+            <template slot="title">
+              <span>{{ text }}</span>
+            </template>
+            <span class="ellipsisText">{{ text }}</span>
+          </a-tooltip>
+          <!-- <a-badge :number-style="{ backgroundColor: '#52c41a' }" count="活动" v-if="record.isJoinActivityProduct == 1"></a-badge> -->
+        </div>
+      </template>
+      <!-- 操作 -->
+      <template slot="action" slot-scope="text, record">
+        <a-button
+          size="small"
+          type="link"
+          class="button-info"
+          :loading="newLoading"
+          @click="handleAdd(record)"
+          v-if="promoProductClz!='GIFT' ? record.productPrice : record.origPrice"
+          id="productInfoList-edit-btn">添加</a-button>
+        <span v-else>--</span>
+      </template>
+    </s-table>
+  </div>
+</template>
+
+<script>
+import { commonMixin } from '@/utils/mixin'
+import { queryPromoProductPage } from '@/api/stock'
+import ProductType from '@/views/common/productType.js'
+import ProductBrand from '@/views/common/productBrand.js'
+import chooseWarehouse from '@/views/common/chooseWarehouse'
+import { STable, VSelect } from '@/components'
+export default {
+  name: 'ActiveQueryPart',
+  mixins: [commonMixin],
+  components: { STable, VSelect, ProductBrand, ProductType, chooseWarehouse },
+  props: {
+    newLoading: Boolean
+  },
+  data () {
+    return {
+      advanced: false, // 高级搜索 展开/关闭
+      showSetting: false, // 设置弹框
+      productType: [],
+      buyerSn: '',
+      queryParam: { //  查询条件
+        productCode: '', //  产品编码
+        productName: '', //  产品名称
+        productOrigCode: '', //  原厂编码
+        productBrandSn: undefined, //  产品品牌
+        productTypeSn1: '', //  产品一级分类
+        productTypeSn2: '', //  产品二级分类
+        productTypeSn3: '', //  产品三级分类
+        warehouseSn: undefined
+      },
+      defaultWarehouseSn: undefined, // 默认仓库sn
+      tableHeight: 300,
+      disabled: false, //  查询、重置按钮是否可操作
+      promoProductClz: 'GATE',
+      promoRuleData: null,
+      tabList:[],
+      // 加载数据方法 必须为 Promise 对象
+      loadData: parameter => {
+        this.disabled = true
+        this.queryParam.dealerSn = this.buyerSn
+        this.queryParam.promoProductClz = this.promoProductClz
+        return queryPromoProductPage(Object.assign(parameter, this.queryParam, { onlineFalg: '1', pricingState: 'PRICED' })).then(res => {
+          let data
+          if (res.status == 200) {
+            data = res.data
+            data.list = data.list.filter(item => item != null)
+            const no = (data.pageNo - 1) * data.pageSize
+            for (var i = 0; i < data.list.length; i++) {
+              data.list[i].no = no + i + 1
+              data.list[i].salesNums = 1
+              data.list[i].currentStockQty = data.list[i].currentStockQty || 0
+              const productPackQty = (data.list[i].productPackQty || data.list[i].productPackQty == 0) ? data.list[i].productPackQty : '--'
+              const productUnit = data.list[i].productUnit || '--'
+              const productPackQtyUnit = data.list[i].productPackQtyUnit || '--'
+              data.list[i].packQtyV = productPackQty + productUnit + '/' + productPackQtyUnit
+              if(data.list[i].unitType=='SL'){
+                data.list[i].unitQtyV = data.list[i].unitQty ? (data.list[i].unitQty + data.list[i].productUnit) : '--'
+              }else{
+                data.list[i].unitQtyV = data.list[i].productPackQty&&data.list[i].unitQty ? ((data.list[i].productPackQty*data.list[i].unitQty) + data.list[i].productUnit) : '--'
+              }
+            }
+            this.disabled = false
+          }
+          return data
+        })
+      }
+    }
+  },
+  computed: {
+    columns () {
+      const arr = [
+        { title: '产品编码', dataIndex: 'productCode', width: '150px', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '产品名称', dataIndex: 'productName', scopedSlots: { customRender: 'productName' }, align: 'left' },
+        { title: '原厂编码', dataIndex: 'productOrigCode', width: '150px', align: 'center', customRender: function (text) { return text || '--' }, ellipsis: true },
+        { title: '品牌', dataIndex: 'productBrandName', width: '100px', align: 'center', customRender: function (text) { return text || '--' }, ellipsis: true },
+        { title: '出库仓库', dataIndex: 'warehouseName', width: '80px', align: 'center', customRender: function (text) { return text || '--' }, ellipsis: true },
+        { title: '库存数量', dataIndex: 'currentStockQty', width: '80px', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
+        { title: '单位', dataIndex: 'productUnit', width: '60px', align: 'center', customRender: function (text) { return text || '--' } },
+        // { title: '售价', dataIndex: 'productPrice', width: '8%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
+        { title: '包装数', dataIndex: 'packQtyV', width: '60px', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
+        // { title: '起订量', dataIndex: 'unitQtyV', width: '8%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
+        { title: '下单数量', dataIndex: 'salesNums', scopedSlots: { customRender: 'nums' }, width: '80px', align: 'center', fixed: 'right' },
+        { title: '操作', dataIndex: 'action', scopedSlots: { customRender: 'action' }, width: '60px', align: 'center', fixed: 'right' }
+      ]
+      let idx = 7
+      if (this.$hasPermissions('B_salesEdit_salesPrice')) { // 售价权限
+        arr.splice(idx, 0, { title: '售价', dataIndex: 'productPrice', width: '100px', align: 'right', scopedSlots: { customRender: 'productPrice' } })
+        idx = idx + 1
+      }
+      // 促销品没有起订量
+      if(this.promoProductClz != 'GIFT'){
+        arr.splice(idx+1, 0,{ title: '起订量', dataIndex: 'unitQtyV', width: '60px', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } })
+      }
+      return arr
+    }
+  },
+  watch:{
+    advanced(a,b){
+      this.tableHeight = window.innerHeight - (a ? 395 : 350)
+    }
+  },
+  methods: {
+    loadWarehouse (sn) {
+      this.defaultWarehouseSn = sn
+      this.queryParam.warehouseSn = sn
+      if(this.buyerSn){
+        this.resetSearchForm()
+      }
+    },
+    // 切换tab
+    changeTab(e){ 
+      this.promoProductClz = e
+      this.resetSearchForm()
+    },
+    // 双击列表
+    handleClickRow (record) {
+      const _this = this
+      return {
+        on: {
+          dblclick: (event) => {
+            _this.handleAdd(record)
+          }
+        }
+      }
+    },
+    // 查询
+    searchForm () {
+      if (this.queryParam.warehouseSn) {
+        this.$refs.table.refresh(true)
+      } else {
+        this.$message.info('请选择仓库')
+      }
+    },
+    //  重置
+    resetSearchForm () {
+      this.queryParam.productCode = ''
+      this.queryParam.productName = ''
+      this.queryParam.productOrigCode = ''
+      this.queryParam.productBrandSn = undefined
+      this.queryParam.productTypeSn1 = ''
+      this.queryParam.productTypeSn2 = ''
+      this.queryParam.productTypeSn3 = ''
+      this.productType = []
+      this.queryParam.warehouseSn = this.defaultWarehouseSn
+      this.$refs.table.refresh(true)
+    },
+    pageInit (data, promo) {
+      this.buyerSn = data.buyerSn
+      this.promoRuleData = promo.promotionRule
+      this.queryParam.dealerLevel = data.buyerLevel
+      this.queryParam.promoRuleSn = promo.promoRuleSn
+      const tabList = []
+      if(this.promoRuleData){ 
+        if(this.promoRuleData.gateFlag==='1'){
+          tabList.push({text:'门槛产品',val:'GATE'})
+        }
+        if(this.promoRuleData.promotionRuleType!='PROMO_PROD'){
+          tabList.push({text:'正价产品',val:'REGULAR'})
+        }
+        if(this.promoRuleData.regularPromotionSameFlag==='0'||this.promoRuleData.scopeFlag==='0'||(this.promoRuleData.promotionRuleType=='BUY_PROD_GIVE_MONEY'&&this.promoRuleData.scopeFlag==='1')){
+          tabList.push({text:'促销产品',val:'GIFT'})
+        }
+        if(this.promoRuleData.promotionRuleType=='PROMO_PROD'){
+          tabList.push({text:'特价产品',val:'DISCOUNT'})
+        }
+      }
+      this.tabList = tabList
+      this.promoProductClz = tabList[0].val
+      this.tableHeight = window.innerHeight - 350
+
+      this.resetSearchForm()
+    },
+    // 刷新当前页面
+    resetCurForm () {
+      const _this = this
+      _this.$nextTick(() => {
+        _this.$refs.table.refresh()
+      })
+    },
+    // 选择配件
+    handleAdd (row) {
+      this.$emit('add', row, 0, this.promoProductClz)
+    },
+    //  产品分类  change
+    changeProductType (val, opt) {
+      this.queryParam.productTypeSn1 = val[0] ? val[0] : ''
+      this.queryParam.productTypeSn2 = val[1] ? val[1] : ''
+      this.queryParam.productTypeSn3 = val[2] ? val[2] : ''
+    }
+  }
+}
+</script>
+<style lang="less" scoped>
+  .productInfoList-wrap{
+    /deep/ .ant-tabs-bar{
+      margin-bottom: 5px!important;
+    }
+  }
+</style>

+ 186 - 0
src/views/salesManagement/salesQueryNew/comps/chooseImportModal.vue

@@ -0,0 +1,186 @@
+<template>
+  <a-modal
+    centered
+    class="chooseImport-modal"
+    :footer="null"
+    :maskClosable="false"
+    title="导入"
+    v-model="isShow"
+    @cancel="isShow=false"
+    :width="900">
+    <div class="chooseImport-con">
+      <!-- 可导入数据 -->
+      <p class="">可导入数据{{ loadData.length }}条</p>
+      <a-table
+        class="sTable"
+        ref="table"
+        size="small"
+        :rowKey="(record) => record.productCode"
+        :columns="nowColumns"
+        :dataSource="loadData"
+        :loading="loading"
+        :scroll="{ y: 200 }"
+        :pagination="false"
+        bordered>
+      </a-table>
+      <a-divider />
+      <!-- 不可导入数据 -->
+      <p class="red">不可导入数据{{ unLoadData.length }}条</p>
+      <a-table
+        class="unTable"
+        ref="unTable"
+        size="small"
+        :rowKey="(record) => record.productCode"
+        :columns="nowUnColumns"
+        :dataSource="unLoadData"
+        :loading="loading"
+        :scroll="{ y: 200 }"
+        :pagination="false"
+        bordered>
+      </a-table>
+      <!-- 按钮 -->
+      <div class="btn-con">
+        <a-button
+          type="primary"
+          id="chooseImport-submit"
+          size="large"
+          :class="loadData.length==0?'button-grey':'button-primary'"
+          @click="handleSubmit"
+          style="padding: 0 40px;">确认导入</a-button>
+        <a-button
+          id="chooseImport-cancel"
+          size="large"
+          class="button-cancel"
+          @click="isShow=false"
+          style="padding: 0 40px;margin-left: 15px;">取消</a-button>
+        <a-button
+          type="primary"
+          id="chooseImport-error"
+          size="large"
+          class="button-error"
+          @click="handleError"
+          style="padding: 0 40px;margin-left: 15px;">导出错误项</a-button>
+      </div>
+    </div>
+  </a-modal>
+</template>
+
+<script>
+import { commonMixin } from '@/utils/mixin'
+import { hdExportExcel } from '@/libs/exportExcel'
+import { salesFailExcel } from '@/api/salesDetailNew'
+export default {
+  name: 'SalesChooseImportModal',
+  mixins: [commonMixin],
+  props: {
+    openModal: { //  弹框显示状态
+      type: Boolean,
+      default: false
+    },
+    paramsData: {
+      type: Object,
+      default: () => {
+        return {}
+      }
+    }
+  },
+  data () {
+    return {
+      isShow: this.openModal, //  是否打开弹框
+      nowColumns: [
+        { title: '序号', dataIndex: 'no', width: '8%', align: 'center' },
+        { title: '产品编码', dataIndex: 'productCode', width: '25%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '产品名称', dataIndex: 'productName', width: '25%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '出库仓库', dataIndex: 'warehouseName', width: '20%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '数量', dataIndex: 'qty', width: '14%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
+        { title: '库存', dataIndex: 'stockQty', width: '14%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
+        { title: '单位', dataIndex: 'productUnit', width: '14%', align: 'center', customRender: function (text) { return text || '--' } }
+      ],
+      loadData: [],
+      nowUnColumns: [
+        { title: '序号', dataIndex: 'no', width: '9%', align: 'center' },
+        { title: '产品编码', dataIndex: 'productCode', width: '20%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '产品名称', dataIndex: 'productName', width: '21%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '出库仓库', dataIndex: 'warehouseName', width: '21%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '数量', dataIndex: 'importQty', width: '10%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
+        { title: '库存', dataIndex: 'stockQty', width: '10%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
+        { title: '单位', dataIndex: 'productUnit', width: '10%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '备注', dataIndex: 'errorDescSet', width: '20%', align: 'center', customRender: function (text) { return text || '--' } }
+      ],
+      unLoadData: [],
+      loading: false
+    }
+  },
+  methods: {
+    getData () {
+      const paramsData = JSON.parse(JSON.stringify(this.paramsData))
+      console.log(paramsData)
+      this.loadData = paramsData.rightList || []
+      this.unLoadData = paramsData.errorList || []
+      this.loadData.map((item, index) => {
+        item.no = index + 1
+      })
+      this.unLoadData.map((item, index) => {
+        item.no = index + 1
+      })
+    },
+    // 确认导入
+    handleSubmit () {
+      if (this.loadData.length == 0) {
+        this.$message.warning('无可导入产品!')
+      } else {
+        this.$emit('ok', this.loadData)
+        this.isShow = false
+      }
+    },
+    // 导出
+    handleError () {
+      const _this = this
+      if (_this.unLoadData.length < 1) {
+        _this.$message.info('暂无可导出错误项~')
+        return
+      }
+      _this.spinning = true
+      const params = {
+        list: _this.unLoadData
+      }
+      hdExportExcel(salesFailExcel, params, '产品导入错误项', function () {
+        _this.spinning = false
+      })
+    }
+  },
+  watch: {
+    //  父页面传过来的弹框状态
+    openModal (newValue, oldValue) {
+      this.isShow = newValue
+    },
+    //  重定义的弹框状态
+    isShow (newValue, oldValue) {
+      if (!newValue) {
+        this.$emit('close')
+        this.loadData = []
+        this.unLoadData = []
+      } else {
+        this.getData()
+      }
+    }
+  }
+}
+</script>
+
+<style lang="less" scoped>
+  .chooseImport-modal{
+    .chooseImport-con{
+      .red{
+        color: #f30;
+      }
+      .btn-con{
+        text-align: center;
+        margin: 30px 0 20px;
+        .button-cancel,.button-error{
+          font-size: 12px;
+        }
+      }
+    }
+  }
+</style>

+ 105 - 0
src/views/salesManagement/salesQueryNew/comps/chooseProduct.vue

@@ -0,0 +1,105 @@
+<template>
+  <a-drawer
+    :zIndex="zIndex"
+    title="选择产品"
+    placement="right"
+    :visible="isShow"
+    width="80%"
+    :get-container="false"
+    :wrap-style="{ position: 'absolute' }"
+    :headerStyle="{ padding: '10px' }"
+    @close="onClose"
+    wrapClassName="chooseProducts-modal">
+      <a-spin :spinning="spinning" tip="Loading...">
+        <div class="products-con">
+          <div>
+            <!-- 查询配件列表 -->
+            <queryPart v-if="cptype==0" ref="partQuery" :newLoading="isInster" @add="insterProduct"></queryPart>
+            <activeQueryPart v-if="cptype==1" ref="partQuery" :newLoading="isInster" @add="insterProduct"></activeQueryPart>
+          </div>
+        </div>
+      </a-spin>
+  </a-drawer>
+</template>
+
+<script>
+import queryPart from './queryPart.vue'
+import activeQueryPart from './activeQueryPart.vue'
+export default {
+  name: 'ChooseProductsModal',
+  components: { queryPart, activeQueryPart },
+  props: {
+    openModal: { //  弹框显示状态
+      type: Boolean,
+      default: false
+    },
+    chooseData: {
+      type: Array,
+      default: () => {
+        return []
+      }
+    },
+    isInster: { //  弹框显示状态
+      type: Boolean,
+      default: false
+    },
+    zIndex:{
+      type: [String,Number],
+      default: 1000
+    }
+  },
+  data () {
+    return {
+      spinning: false,
+      cptype: 3,
+      isShow: this.openModal, //  是否打开弹框
+      orderData: null
+    }
+  },
+  
+  methods: {
+    onClose () {
+      this.$emit('close')
+    },
+    // 添加产品
+    insterProduct (row, promotionFlag, promoProductClz) {
+      this.$emit('addProduct', row, promotionFlag, promoProductClz)
+    },
+    pageInit(data, promo, type){
+      console.log(data, promo, type)
+      this.cptype = type
+      this.orderData = data
+      this.$nextTick(()=>{
+        this.$refs.partQuery.pageInit(data, promo)
+      })
+    }
+  },
+  watch: {
+    //  父页面传过来的弹框状态
+    openModal (newValue, oldValue) {
+      this.isShow = newValue
+    },
+    //  重定义的弹框状态
+    isShow (newValue, oldValue) {
+      if (!newValue) {
+        this.$emit('close',this.cptype)
+        this.cptype = 3
+      }
+    }
+  }
+}
+</script>
+
+<style lang="less" scoped>
+  .chooseProducts-modal{
+    .products-con{
+      .btn-con{
+        text-align: center;
+        margin: 30px 0 20px;
+        .button-cancel{
+          font-size: 12px;
+        }
+      }
+    }
+  }
+</style>

+ 392 - 0
src/views/salesManagement/salesQueryNew/comps/detailProductList.vue

@@ -0,0 +1,392 @@
+<template>
+    <!-- 已选配件列表 -->
+    <a-spin :spinning="spinning" tip="Loading...">
+          <ve-table
+            border-y
+            v-show="!showEmpty"
+            :scroll-width="0"
+            :max-height="tableHeight"
+            :show-header="showTableHead"
+            :row-style-option="{clickHighlight: true}"
+            :cellSelectionOption="{enable: false}"
+            :virtual-scroll-option="{enable: true}"
+            :columns="columns"
+            :table-data="dataSource"
+            row-key-field-name="id"
+            :cell-style-option="cellStyleOption"
+            :cell-span-option="cellSpanOption"
+            :column-width-resize-option="columnWidthResizeOption"
+          />
+        <div v-show="showEmpty" class="empty-data"><a-empty description="暂无产品" :image="simpleImage"/></div>
+        <!-- 活动规则详情 -->
+        <detailModal :openModal="openDetailModal" :itemSn="detailSn" @close="closeDetailModal"></detailModal>
+    </a-spin>
+  </template>
+  
+  <script>
+    import { commonMixin } from '@/utils/mixin'
+    import { Empty } from 'ant-design-vue';
+    import detailModal from '@/views/promotionRulesManagement/dealerPromotions/detailModal.vue'
+    import { salesPromoQueryList } from '@/api/salesNew'
+    import { salesDetailAllList, salesPromoDetailCount, salesDetaiCount } from '@/api/salesDetailNew'
+    export default {
+      name: 'DetailProductList',
+      mixins: [commonMixin],
+      components: { detailModal },
+      props: {
+        newLoading: Boolean,
+        detailData: {
+          type: Object,
+          default: function(){return null}
+        },
+        promo: {
+          type: Object,
+          default: function(){return null}
+        },
+        id: {
+          type: String,
+          default: ''
+        },
+        warehouseSn: {
+          type: String,
+          default: ''
+        },
+        salesBillSn: {
+          type: String,
+          default: ''
+        },
+        showCityPrice: {
+            type: Boolean,
+            default: false
+        },
+        authCode: {
+          type: String,
+          default: ''
+        },
+        maxHeight:{
+          type: [String,Number],
+          default: '300'
+        },
+        showHeader: {
+            type: Boolean,
+            default: true
+        }
+      },
+      data () {
+        return {
+          spinning: false,
+          openDetailModal: false,
+          detailSn: null,
+          activeList: [], // 活动列表
+          dataSource: [],
+          tableHeight: this.maxHeight,
+          cellStyleOption: {
+            bodyCellClass: ({ row, column, rowIndex }) => {
+                if (row.id.indexOf('promo-')>=0 && column.field === "no") {
+                    return "table-body-cell-no";
+                }
+            },
+          },
+          columnWidthResizeOption: {
+              // default false
+              enable: true,
+              // column resize min width
+              minWidth: 50
+          },
+          cellSpanOption: {
+              bodyCellSpan: this.bodyCellSpan,
+          },
+          isCityPrice: false,
+          outStockStr: '',
+          showEmpty: false,
+          showTableHead: true,
+          colspanNums: 13,
+          simpleImage: Empty.PRESENTED_IMAGE_SIMPLE
+        }
+      },
+      computed: {
+        columns () {
+          const _this = this
+          const priceFormat = function(data){
+            return _this.toThousands(data) || '--'
+          }
+          const numsFormat = function(data){
+            return data || data == 0 ? data : '--'
+          }
+          const codeFormat = function(record,data,h){
+            let ftext = ''
+            let fcolor = ''
+            if(record.promotionFlag == 'GIFT'){
+              ftext = '促'
+              fcolor = '#52c41a'
+            }
+            if(record.promotionFlag == 'GATE'){
+              ftext = '槛'
+              fcolor = '#108ee9'
+            }
+             
+            return (
+                    <div>
+                        <span style="padding-right: 15px;">{data}</span>
+                        {ftext?(<a-badge count={ftext} number-style={{ backgroundColor: fcolor, zoom:'80%' }}></a-badge>):''}
+                        {(Number(record.stockQty||0) < Number(record.unpushedQty||0)) && _this.showStock?(<a-badge count="缺" number-style={{ zoom:'80%' }}></a-badge>):''}
+                    </div>
+                )
+          }
+          // 编号,并且格式化活动分类行
+          const noFormat = function(record,data,h){
+            return (
+              <div>
+                {record.id.indexOf('promo-')>=0 ? (
+                  <div class="active-title">
+                    {record.promo?(
+                      <div>
+                        <strong style="font-size:14px;">{record.promo.promotion.description}</strong>
+                        <span>({record.promo.promotionRule.description})</span>
+                        <span style="margin-left:20px;color:#00aaff;cursor: pointer;" onClick={()=>_this.showDesc(record.promo)}>
+                          <a-icon title="查看活动详情" type="eye"/> 活动详情
+                        </span>
+                      </div>
+                    ):(<div></div>)}
+                    <div>
+                        款数:<strong>{record.total&&record.total.totalCategory||'--'}</strong>;
+                        数量:<strong>{record.total&&record.total.totalQty||'--'}</strong>;
+                        {_this.$hasPermissions('B_salesEdit_salesPrice') ? (<span>总金额:<strong>{record.total&&record.total.totalAmount||'--'}</strong>;</span>):('')}
+                        {_this.$hasPermissions('B_salesEdit_salesPrice')&&record.promo&&record.total&&record.total.lossAmount ? (<span>优惠金额:<strong>{record.total.lossAmount}</strong>;</span>):('')}
+                        {_this.$hasPermissions('B_salesEdit_salesPrice')&&record.promo&&record.total&&record.total.cgejyAmount>0 ? (<span>采购额结余:<strong>{_this.toThousands(record.total.cgejyAmount)}</strong>;</span>):('')}
+                        {_this.$hasPermissions('B_salesEdit_salesPrice')&&record.promo&&record.total&&record.total.cgejyAmount<0 ? (<span>采购额超出:<strong>{_this.toThousands(record.total.cgeccAmount)}</strong>;</span>):('')}
+                        {record.total&&record.total.expenseAccountFlag!='WAIT' ? (<span style="color:red;">{record.total.expenseAccountFlagDictValue}</span>) : ''}
+                    </div>
+                  </div>
+                ):(<span>{data}</span>)}
+              </div>
+            )
+          }
+          // 显示折扣价
+          const discountPriceFormat = function(record,data,h) {
+            return (
+              <div>
+                {_this.toThousands(data)}
+                {record.promotionFlag == 'GIFT' || record.promotionFlag == 'DISCOUNT' ? (
+                  <span title="原价">({ _this.toThousands(record.origPrice)})</span>
+                ):''}
+              </div>
+            )
+          }
+
+          let arr= [
+                { title: '序号', field: 'no',key: "a", width: 50, align: 'center',operationColumn: false, renderBodyCell: ({ row, column, rowIndex }, h) => { return noFormat(row,row[column.field],h)} },
+                { title: '产品编码', field: 'productCode',key: "b", width: 150, align: 'center',operationColumn: false,renderBodyCell: ({ row, column, rowIndex }, h) => { return codeFormat(row,row[column.field],h)} },
+                { title: '产品名称', field: 'productName',key: "c", width: 250, align: 'center',operationColumn: false , ellipsis: { showTitle: true },renderBodyCell: ({ row, column, rowIndex }, h) => { return row[column.field] || '--'}},
+                { title: '原厂编码', field: 'productOrigCode',key: "d", width: 150, align: 'center',operationColumn: false,ellipsis: { showTitle: true },renderBodyCell: ({ row, column, rowIndex }, h) => { return row[column.field] || '--'} },
+                { title: '出库仓库', field: 'warehouseName',key: "e", width: 100, align: 'center',operationColumn: false,renderBodyCell: ({ row, column, rowIndex }, h) => { return row[column.field] || '--'}}
+            ]
+            this.colspanNums = 5
+            if (this.$hasPermissions(this.authCode + '_costPrice')) { //  成本价权限
+              this.colspanNums = this.colspanNums + 1
+              arr.push({ title: '成本价', field: 'showCost', width: 80,key: "f", align: 'right',operationColumn: false, renderBodyCell: ({ row, column, rowIndex }, h) => { return priceFormat(row[column.field])} })
+            }
+            this.colspanNums = this.colspanNums + 2
+            arr = arr.concat([
+                { title: '单位', field: 'productOrigUnit',key: "g", width: 80, align: 'center',operationColumn: false, renderBodyCell: ({ row, column, rowIndex }, h) => { return row[column.field] || '--'}},
+                { title: '销售数量', field: 'qty', width: 80,key: "h", align: 'center',operationColumn: false, renderBodyCell: ({ row, column, rowIndex }, h) => { return numsFormat(row[column.field])} }
+            ])
+
+            if (this.$hasPermissions(this.authCode + '_provincePrice')) {
+              this.colspanNums = this.colspanNums + 1
+              arr.push({ title: '省级价', field: 'provincePrice', width: 80,key: "i", align: 'right',operationColumn: false, renderBodyCell: ({ row, column, rowIndex }, h) => { return priceFormat(row[column.field])} })
+            }
+            // 是否勾选市级价格
+            if (this.isCityPrice) {
+              this.colspanNums = this.colspanNums + 1
+                arr.push({ title: '市级价', field: 'cityPrice', width: 80,key: "j", align: 'right',operationColumn: false, renderBodyCell: ({ row, column, rowIndex }, h) => { return priceFormat(row[column.field])} })
+                if (this.$hasPermissions(this.authCode + '_salesPrice')) { //  售价权限
+                  this.colspanNums = this.colspanNums + 1
+                    arr.push({ title: '销售价', field: 'price', width: 100,key: "k", align: 'right',operationColumn: false, renderBodyCell: ({ row, column, rowIndex }, h) => { return discountPriceFormat(row,row[column.field],h)} })
+                }
+            } else {
+                if (this.$hasPermissions(this.authCode + '_salesPrice')) { //  售价权限
+                  this.colspanNums = this.colspanNums + 1
+                    arr.push({ title: '销售价', field: 'price', width: 100,key: "l", align: 'right',operationColumn: false, renderBodyCell: ({ row, column, rowIndex }, h) => { return discountPriceFormat(row,row[column.field],h)} })
+                }
+            }
+
+            if (this.showStock) { //  审核,需用到库存
+              this.colspanNums = this.colspanNums + 1
+                arr.push({ title: '库存', field: 'stockQty', width: 80,key: "m", align: 'center',operationColumn: false, renderBodyCell: ({ row, column, rowIndex }, h) => { return numsFormat(row[column.field])} })
+            }
+            this.colspanNums = this.colspanNums + 3
+            arr = arr.concat([
+                { title: '待下推数', field: 'unpushedQty', width: 80,key: "o", align: 'center',operationColumn: false, renderBodyCell: ({ row, column, rowIndex }, h) => { return numsFormat(row[column.field])} },
+                { title: '已下推数', field: 'pushedQty', width: 80,key: "p", align: 'center',operationColumn: false, renderBodyCell: ({ row, column, rowIndex }, h) => { return numsFormat(row[column.field])} },
+                { title: '已取消数', field: 'cancelQty', width: 80,key: "q", align: 'center',operationColumn: false, renderBodyCell: ({ row, column, rowIndex }, h) => { return numsFormat(row[column.field])} }
+            ])
+          return arr
+        },
+        showStock(){
+            return this.detailData && (this.detailData.billStatus == 'WAIT_AUDIT' || this.detailData.billStatus == 'HQ_CHANGE') && this.$hasPermissions('B_salesAudit')
+        }
+      },
+      watch: {
+        showCityPrice(newValue, oldValue){
+            this.isCityPrice = newValue
+        }
+      },
+      methods: {
+        // 关闭详情弹窗
+        closeDetailModal () {
+          this.detailSn = null
+          this.openDetailModal = false
+        },
+         // 合并活动分类单元格
+        bodyCellSpan({ row, column, rowIndex }) {
+          if (row.id.indexOf('promo-')>=0) {
+            if(column.field=='no'){
+              return {
+                        rowspan: 1,
+                        colspan: this.colspanNums,
+                    };
+            }else{
+              return {
+                    rowspan: 0,
+                    colspan: 0,
+                }
+            }
+          }
+        },
+         // 查看活动详情
+        showDesc(row){
+          this.detailSn = row.promoRuleSn
+          this.openDetailModal = true
+        },
+        // 获取销售单参与的活动列表
+        pageInit(){
+          salesPromoQueryList({ salesBillSn: this.salesBillSn }).then(res => {
+            if(res.status == 200){
+              this.activeList = res.data || []
+            }
+            this.$nextTick(()=>{
+              this.searchTable()
+            })
+          })
+        },
+        async searchTable(){
+            this.dataSource = []
+            this.disabled = true
+            this.spinning = true
+            // 参数
+            const params = {
+                salesBillSn: this.salesBillSn,
+                showStock: this.showStock,
+                warehouseSn: this.warehouseSn
+            }
+            const active = this.activeList.filter(item => item.enabledFlag == 1)
+
+            // 正常产品
+            const proList = await salesDetailAllList(params).then(res => res.data)
+            const norTotal = await salesDetaiCount(params).then(res => res.data)
+            // 没有活动时,表格不显示统计数据
+            let listData = active.length ? (proList.length ? [{
+                id: 'promo-normal',
+                total: norTotal
+              },...proList] : []) : proList
+            
+            // 循环获取活动产品
+            for(let i=0;i<active.length;i++){
+              const promo = active[i]
+              const activeParams = {
+                promoRuleSn: promo.promoRuleSn,
+                promoSn: promo.promoSn,
+                salesPromoSn: promo.salesPromoSn,
+                ...params
+              }
+              
+              // 获取活动产品统计
+              const acTotal = await salesPromoDetailCount(activeParams).then(res => res.data)
+              if(acTotal){
+                // 采购额结余
+                acTotal.cgejyAmount = Number(acTotal.totalPromoGiftsAmount||0) - Number(acTotal.totalUsePromoGiftsAmount||0)
+                // 采购额超出
+                acTotal.cgeccAmount = Number(acTotal.totalUsePromoGiftsAmount||0) - Number(acTotal.totalPromoGiftsAmount||0)
+              }
+              // 有数据时才调用接口,避免做无用的调用
+              if(acTotal&&acTotal.totalQty){
+                // 获取活动产品列表
+                const aclist = await salesDetailAllList(activeParams).then(res => res.data)
+                const retList = aclist.length ? [{
+                  id: 'promo-'+i,
+                  promo: promo,
+                  total: acTotal
+                },...aclist] : []
+                // 将活动产品数据拼接
+                listData = aclist&&aclist.length ? listData.concat(retList) : listData
+              }
+            }
+            console.log(listData)
+            // 如果活动没有任何产品,不显示统计一行
+            if(active.length){
+              const hasAcp = listData.filter(item => item.id!='promo-normal').filter(item => item.id.indexOf("promo-")>=0)
+              if(hasAcp && hasAcp.length==0){
+                listData = listData.filter(item => item.id.indexOf("promo-")<0) || []
+              }
+            }
+
+            console.log(listData)
+            this.dataSource = listData
+
+            // 格式化数据
+            let f = 0
+            this.outStockStr = ''
+            let str = ''
+            this.dataSource.map((item,i) => {
+              if(item.id.indexOf('promo-')>=0){f = f - 1}
+              item.no = i + 1 + f
+              const productCode = (item.productEntity && item.productEntity.code) || (item.dealerProductEntity && item.dealerProductEntity.code)
+              const productName = (item.productEntity && item.productEntity.name) || (item.dealerProductEntity && item.dealerProductEntity.name)
+              const productOrigCode = (item.productEntity && item.productEntity.origCode) || (item.dealerProductEntity && item.dealerProductEntity.origCode)
+              const productOrigUnit = (item.productEntity && item.productEntity.unit) || (item.dealerProductEntity && item.dealerProductEntity.unit)
+              item.productCode = productCode || '--'
+              item.productName = productName || '--'
+              item.productOrigCode = productOrigCode == ' ' ? '--' : productOrigCode
+              item.productOrigUnit = productOrigUnit || '--'
+              item.epushedQty = Number(item.pushedQty) - Number(item.pushQty)
+              if (item.unpushedQty && (Number(item.stockQty) < Number(item.unpushedQty))) {
+                  str += item.productCode + '、'
+              }
+            })
+            if (str.length > 0) {
+                str = str.substr(0, str.length - 1)
+                this.outStockStr = '产品编号为:' + str + '的产品库存不足;'
+            }
+            this.showEmpty = this.dataSource.length <= 0
+            this.tableHeight = (this.showEmpty ? 200 : this.maxHeight) + 'px'
+            this.spinning = false
+            this.disabled = false
+        },
+      }
+    }
+  </script>
+  
+  <style lang="less">
+    .empty-data{
+        color: #999;
+        text-align: center;
+        padding: 20px;
+    }
+    .ve-table-body-td{
+      .active-title{
+        display: flex;
+        align-items: center;
+        justify-content: space-between;
+        padding: 10px;
+        background: #f3f8fa;
+      }
+    }
+    .ve-table .ve-table-container .ve-table-content-wrapper table.ve-table-content tbody.ve-table-body tr.ve-table-body-tr td.table-body-cell-no, 
+    .ve-table .ve-table-container .ve-table-content-wrapper table.ve-table-content tbody.ve-table-body tr.ve-table-expand-tr td.table-body-cell-no{
+      padding: 0;
+    } 
+    .ve-table .ve-table-container .ve-table-content-wrapper{
+      border-bottom: 1px solid #ddd;
+    }
+  </style>

+ 203 - 0
src/views/salesManagement/salesQueryNew/comps/importGuideModal.vue

@@ -0,0 +1,203 @@
+<template>
+  <a-modal
+    centered
+    class="importGuide-modal"
+    :footer="null"
+    :maskClosable="false"
+    title="导入产品"
+    v-model="isShow"
+    @cancel="isShow=false"
+    :width="750">
+    <div class="importGuide-con">
+      <div class="explain-con">
+        <div class="explain-item">
+          <div class="explain-tit">
+            <span>1</span>准备导入
+          </div>
+          <ul>
+            <li>1) 导入的Excel文件中必须包含名为“产品编码”、“数量”、“出库仓库”的列,且名称必须相同</li>
+            <li>2) 除了“产品编码”、“数量”、“出库仓库”三列,其他列可自定义,不影响数据导入</li>
+            <li>3) 如果导入的产品已经存在,则不会导入该行</li>
+            <li v-if="params&&params.salesPromoSn">4) 导入的活动产品必须是活动规则中的产品 </li>
+            <li>
+              <a :href="filePath" style="margin: 5px 0 0;display: block;">
+                <a-icon type="download" style="padding-right: 5px;" />下载导入模板
+              </a>
+            </li>
+          </ul>
+        </div>
+        <div class="explain-item">
+          <div class="explain-tit">
+            <span>2</span>上传数据文件
+          </div>
+          <p>目前支持的文件类型*.xls,*.xlsx.</p>
+          <div style="overflow: hidden;padding-left: 23px;">
+            <Upload
+              id="importGuide-attachList"
+              ref="importUpload"
+              :maxNums="1"
+              fileType="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/vnd.ms-excel"
+              uploadType="attach"
+              :action="attachAction"
+              :uploadParams="uploadParams"
+              upText="添加文件"
+              @change="changeImport"></Upload>
+          </div>
+        </div>
+      </div>
+      <!-- 按钮 -->
+      <div class="btn-con">
+        <a-button
+          type="primary"
+          id="importGuide-nextStep"
+          size="large"
+          class="button-primary"
+          @click="handlerNextStep"
+          style="padding: 0 60px;">下一步</a-button>
+        <a-button
+          id="importGuide-cancel"
+          size="large"
+          class="button-cancel"
+          @click="isShow=false"
+          style="padding: 0 60px;margin-left: 15px;">取消</a-button>
+      </div>
+    </div>
+    <!-- 导入 -->
+    <chooseImportModal :openModal="openImportModal" :paramsData="paramsData" @close="handleClose" @ok="hanldeOk" />
+  </a-modal>
+</template>
+
+<script>
+import { commonMixin } from '@/utils/mixin'
+import ChooseImportModal from './chooseImportModal.vue'
+import { Upload } from '@/components'
+export default {
+  name: 'SalesImportGuideModal',
+  mixins: [commonMixin],
+  components: { ChooseImportModal, Upload },
+  props: {
+    openModal: { //  弹框显示状态
+      type: Boolean,
+      default: false
+    },
+    params: {
+      type: Object,
+      default: null
+    },
+    promoProductClz:{
+      type: String,
+      default: ''
+    }
+  },
+  data () {
+    return {
+      isShow: this.openModal, //  是否打开弹框
+      openImportModal: false, //  导入
+      attachAction: process.env.VUE_APP_API_BASE_URL + '/sales/detail/importParse',
+      paramsData: null,
+      uploadParams: {
+        salesBillSn: this.params.salesBillSn,
+        salesPromoSn: this.params.salesPromoSn||'', 
+        promoProductClz: this.promoProductClz||''
+      },
+      exportLoading: false,
+      filePath: location.protocol + '//' + location.host + '/templ/销售导入产品模板.xlsx'
+    }
+  },
+  methods: {
+    // 下一步
+    handlerNextStep () {
+      if (this.paramsData) {
+        this.openImportModal = true
+      } else {
+        this.$message.warning('添加文件后再进行下一步操作!')
+      }
+    },
+    // 上传文件  change
+    changeImport (file) {
+      // console.log(file, JSON.parse(file))
+      if (file && JSON.parse(file).length > 0) {
+        this.paramsData = Object.assign({}, JSON.parse(file)[0] || null, this.params)
+      } else {
+        this.paramsData = null
+      }
+    },
+    // 导入
+    hanldeOk (obj) {
+      if (obj && obj.length > 0) {
+        this.$emit('ok', obj, this.paramsData.salesPromoSn)
+        this.isShow = false
+      }
+    },
+    // 关闭
+    handleClose () {
+      this.openImportModal = false
+      this.isShow = false
+    }
+  },
+  watch: {
+    //  父页面传过来的弹框状态
+    openModal (newValue, oldValue) {
+      this.isShow = newValue
+    },
+    //  重定义的弹框状态
+    isShow (newValue, oldValue) {
+      if (!newValue) {
+        this.$emit('close')
+        this.paramsData = null
+        this.$refs.importUpload.setFileList('')
+      }else{
+        this.uploadParams.promoProductClz = this.promoProductClz
+      }
+    }
+  }
+}
+</script>
+
+<style lang="less" scoped>
+  .importGuide-modal{
+    .importGuide-con{
+      .explain-con{
+        .explain-item{
+          margin-bottom: 10px;
+          .explain-tit{
+            font-weight: bold;
+            span{
+              display: inline-block;
+              width: 18px;
+              height: 18px;
+              line-height: 16px;
+              text-align: center;
+              margin-right: 5px;
+              border-radius: 50%;
+              border: 1px solid rgba(0, 0, 0, 0.3);
+            }
+          }
+          p{
+            margin: 8px 0;
+            padding-left: 23px;
+          }
+          ul{
+            list-style: none;
+            padding: 0;
+            padding-left: 23px;
+            margin: 0;
+            li{
+              line-height: 26px;
+            }
+          }
+        }
+        #importGuide-attachList{
+          width: 100%;
+        }
+      }
+      .btn-con{
+        margin: 10px 0 20px;
+        text-align: center;
+        .button-cancel{
+          font-size: 12px;
+        }
+      }
+    }
+  }
+</style>

+ 808 - 0
src/views/salesManagement/salesQueryNew/comps/productList.vue

@@ -0,0 +1,808 @@
+<template>
+  <div>
+    <div class="table-page-search-wrapper" v-show="showDescBox">
+      <a-row v-if="descDetail" type="flex" justify="start">
+          <a-col span="6" style="padding: 6px;">
+            <span>促销类型:</span>
+            {{ descDetail.promotionRuleTypeDictValue||'--' }}
+          </a-col>
+          <a-col span="18" style="padding: 6px;">
+            <div style="display: flex;">
+              <span>促销门槛:</span>
+              <div v-if="descDetail.gateFlag === '1'">
+                <span v-if="descDetail.gateType==='RATIO_AMOUNT'">
+                  购买门槛产品金额{{ descDetail.gateAmount*100 }}%作为配额
+                </span>
+                <span v-else-if="descDetail.gateType==='MIN_AMOUNT'">
+                  购买门槛产品满最低金额{{ descDetail.gateAmount }}不限制配额。
+                </span>
+                <span v-else>购买满{{ descDetail.gateAmount }}元门槛产品,可使用 {{ descDetail.quotaAmount }}元配额,采购规则中的{{descDetail.promotionRuleType == 'PROMO_PROD'?'特价':'正价'}}商品</span>
+              </div>
+              <span v-else>无</span>
+            </div>
+          </a-col>
+          <a-col span="24" style="padding: 6px;">
+            <div style="display: flex;">
+              <div style="display: flex;">
+                <span>促销规则:</span>
+                <span v-if="descDetail.promotionRuleType == 'BUY_PROD_GIVE_PROD'">
+                  {{ descDetail.regularSameFlag==='1'?'同款产品,':'不同款产品,' }}
+                  购买满{{ descDetail.regularQty }}个正价产品,送{{ descDetail.promotionQty }}个促销产品
+                  {{ descDetail.accrualFlag == 1 ? ',数量叠加':',数量不叠加' }}
+                </span>
+                <span v-else-if="descDetail.promotionRuleType == 'BUY_PROD_GIVE_MONEY'">
+                  <!-- {{ descDetail.regularSameFlag==='1'?'同款产品,':'不同款产品,' }} -->
+                  购买满{{ descDetail.regularAmount }}元正价产品,送{{ descDetail.giveAmount }}元促销品采购额
+                  {{ descDetail.accrualFlag == 1 ? ',金额叠加':',金额不叠加' }}
+                </span>
+                <span v-else>
+                  特价产品
+                </span>
+              </div>
+              <div style="display: flex;flex-grow: 1;">
+                <div v-if="descDetail.promotionRuleType!='PROMO_PROD'&&descDetail.promotionRuleType!='BUY_PROD_GIVE_MONEY'">
+                  <span style="margin-left: 50px;">限制正价产品款数:</span>{{ descDetail.restrictCategory||'无' }}
+                </div>
+                <div>
+                  <span style="margin-left: 50px;">订单起订金额(元):</span>{{ descDetail.minOrderAmount||'无' }}
+                  <span style="margin-left: 50px;">活动经费上限(元):</span>{{ descDetail.upperLimitAmount||'无' }}
+                </div>
+              </div>
+            </div>
+          </a-col>
+        </a-row>
+    </div>
+    <!-- 筛选条件 -->
+   <div class="table-page-search-wrapper" style="margin:0" v-show="showSearchBox">
+     <a-form layout="inline" @keyup.enter.native="$refs.table.refresh(true)">
+       <a-row :gutter="15">
+         <a-col :md="4" :sm="24">
+           <a-form-item label="出库仓库" prop="warehouseSn">
+             <chooseWarehouse ref="warehouse" v-model="queryParam.warehouseSn" @load="warehouseLoad"></chooseWarehouse>
+           </a-form-item>
+         </a-col>
+         <a-col :md="4" :sm="24">
+           <a-form-item label="产品编码" prop="productCode">
+             <a-input id="salesEdit-productCode" v-model.trim="queryParam.productCode" placeholder="请输入产品编码" allowClear />
+           </a-form-item>
+         </a-col>
+         <a-col :md="4" :sm="24">
+           <a-form-item label="产品名称" prop="productName">
+             <a-input id="salesEdit-productName" v-model.trim="queryParam.productName" placeholder="请输入产品名称" allowClear />
+           </a-form-item>
+         </a-col>
+         <a-col :md="4" :sm="24">
+           <a-form-item label="品牌">
+             <ProductBrand id="salesEdit-productBrandSn" v-model="queryParam.productBrandSn"></ProductBrand>
+           </a-form-item>
+         </a-col>
+         <a-col :md="4" :sm="24">
+           <a-form-item label="产品分类">
+             <productTypeAll placeholder="请选择产品分类" @change="changeProductType" v-model="productType" id="salesEdit-productType"></productTypeAll>
+           </a-form-item>
+         </a-col>
+         <a-col :md="4" :sm="24" style="margin-bottom: 10px;">
+           <a-button type="primary" @click="$refs.table.refresh(true)" :disabled="disabled" id="salesEdit-refresh">查询</a-button>
+           <a-button style="margin-left: 5px" @click="resetSearchForm" :disabled="disabled" id="salesEdit-reset">重置</a-button>
+         </a-col>
+       </a-row>
+     </a-form>
+   </div>
+ 
+    <div class="table-page-search-wrapper">
+      <a-row :gutter="15" type="flex" justify="space-between" align="middle">
+        <a-col :md="8" :sm="24" style="text-align:left;">
+          <span v-if="selectTotal" style="margin-right:5px;">已选{{ selectTotal }}项</span>
+        </a-col>
+        <a-col :md="12" :sm="24" style="text-align:right;">
+          <a-button
+            type="link"
+            class="button-info"
+             @click="showSearchBox=!showSearchBox" ><a-icon :type="showSearchBox?'close':'search'"/> 筛选</a-button>
+
+          <a-dropdown>
+            <a-menu slot="overlay" @click="handleMenuClick">
+              <a-menu-item key="0" :disabled="disablePromo">
+                仓库设置
+              </a-menu-item>
+              <a-menu-item key="1">
+                删除已选项
+              </a-menu-item>
+              <a-menu-item key="2">
+                全部删除
+              </a-menu-item>
+            </a-menu>
+            <a-button
+              type="link"
+              class="button-info"
+            > 批量操作 <a-icon type="down" /> </a-button>
+          </a-dropdown>
+          
+          <a-dropdown :disabled="disablePromo">
+            <a-menu slot="overlay" @click="handleImportClick">
+              <a-menu-item key="GATE" v-if="promo&&promo.promotionRule&&promo.promotionRule.gateFlag==='1'">
+                导入门槛产品
+              </a-menu-item>
+              <a-menu-item key="REGULAR" v-if="promo&&promo.promotionRule&&promo.promotionRule.promotionRuleType!='PROMO_PROD'">
+                导入正价产品
+              </a-menu-item>
+              <a-menu-item key="GIFT" v-if="promo&&promo.promotionRule&&(promo.promotionRule.regularPromotionSameFlag==='0'||promo.promotionRule.scopeFlag==='0'||(promo.promotionRule.promotionRuleType=='BUY_PROD_GIVE_MONEY'&&promo.promotionRule.scopeFlag==='1'))">
+                导入促销产品
+              </a-menu-item>
+              <a-menu-item key="DISCOUNT" v-if="promo&&promo.promotionRule&&promo.promotionRule.promotionRuleType=='PROMO_PROD'">
+                导入特价产品
+              </a-menu-item>
+            </a-menu>
+            <a-button
+              type="link"
+              :class="disablePromo?'button-gray':'button-info'"
+            > 导入产品 <a-icon type="down" /> </a-button>
+          </a-dropdown>
+          <a-button
+            type="link"
+            :class="disablePromo?'button-gray':'button-info'"
+            :disabled="disablePromo"
+            @click="openCpModal"><a-icon type="plus" /> 添加产品</a-button>
+        </a-col>
+      </a-row>
+    </div>
+   
+    <!-- 已选配件列表 -->
+    <s-table
+      class="sTable"
+      ref="table"
+      size="small"
+      :rowKey="(record) => record.id"
+      :columns="columns"
+      :data="loadData"
+      :row-selection="{ columnWidth: 40, getCheckboxProps: record => ({ props: { disabled: record.promotionFlag == 'GIFT'&&!!record.salesPromoDetailParentSn } }) }"
+      @rowSelection="rowSelectionFun"
+      :defaultLoadData="false"
+      :pageSize="10"
+      bordered>
+      <!-- 产品编码 -->
+      <template slot="productCode" slot-scope="text, record">
+        <span style="padding-right: 15px;">{{ text }}</span>
+        <a-badge count="促" v-if="record.promotionFlag=='GIFT'" :number-style="{ backgroundColor: '#52c41a', zoom:'80%' }"></a-badge>
+        <!-- <a-badge count="特" v-if="record.promotionFlag=='DISCOUNT'" :number-style="{ backgroundColor: '#faad14', zoom:'80%' }"></a-badge> -->
+        <a-badge count="槛" v-if="record.promotionFlag=='GATE'" :number-style="{ backgroundColor: '#108ee9', zoom:'80%' }"></a-badge>
+        <a-badge count="缺" v-if="Number(record.stockQty||0) < Number(record.unpushedQty||0)" :number-style="{ zoom:'80%' }"></a-badge>
+      </template>
+      <!-- 产品名称 -->
+      <template slot="productName" slot-scope="text, record">
+        <div class="ellipsisCon">
+          <a-tooltip placement="rightBottom">
+            <template slot="title">
+              <span>{{ text }}</span>
+            </template>
+            <span class="ellipsisText">{{ text }}</span>
+          </a-tooltip>
+          <a-badge :number-style="{ backgroundColor: '#52c41a' }" count="活动" v-if="record.promotableFlag == 1"></a-badge>
+        </div>
+      </template>
+       <!-- 销售价 -->
+       <template slot="price" slot-scope="text, record">
+        {{ toThousands(text) }}
+        <span v-if="record.promotionFlag=='GIFT'||record.promotionFlag=='DISCOUNT'" title="原价">({{ toThousands(record.origPrice) }})</span>
+      </template>
+      <!-- 折扣 -->
+      <template slot="discountPrice" slot-scope="text, record">
+        <div v-if="record.promotionFlag=='DISCOUNT'&&detailData">
+          <span v-if="detailData.buyerLevel=='PROVINCE'">{{ record.provinceDiscount*100 }}%</span>
+          <span v-if="detailData.buyerLevel=='CITY'">{{ record.cityDiscount*100 }}%</span>
+          <span v-if="detailData.buyerLevel=='SPECIAL'">{{ record.specialDiscount*100 }}%</span>
+        </div>
+        <div v-else>--</div>
+      </template>
+      <!-- 销售数量 -->
+      <template slot="salesNums" slot-scope="text, record">
+        <a-input-number
+          id="salesEdit-qty"
+          v-if="!(record.promotionFlag == 'GIFT'&&record.salesPromoDetailParentSn)"
+          size="small"
+          v-model="record.qty"
+          :precision="0"
+          :min="1"
+          :max="999999"
+          placeholder="请输入"
+          @blur="e => onCellBlur(e.target.value, record)"
+          :style="{width:'100%',color:record.qty>=record.unitQtyR?'':'red'}" />
+          <span v-else>{{ record.qty }}</span>
+      </template>
+      <!-- 当前库存 -->
+      <template slot="stockQty" slot-scope="text, record">
+        <div v-if="record.stockQty || record.stockQty==0">
+          <p style="margin: 0;" v-if="Number(record.stockQty) < Number(record.unpushedQty)">{{ record.stockQty }}(<span class="redStyle">缺{{ Number(record.unpushedQty||0) - Number(record.stockQty||0) }}</span>)</p>
+          <p style="margin: 0;" v-else>{{ record.stockQty }}</p>
+        </div>
+        <span v-else>--</span>
+      </template>
+      <!-- 出库仓库 -->
+      <template slot="warehouseBox" slot-scope="text, record">
+        <a-select
+          size="small"
+          style="width:100%;" 
+          placeholder="请选择仓库"
+          v-model="record.warehouseSn"
+          :showSearch="true"
+          @change="handleWarehouseBox(record)"
+          mode="default"
+          :filter-option="filterOption">
+          <a-select-option v-for="item in warehouseDataList" :key="item.warehouseSn" :value="item.warehouseSn">{{ item.name }}</a-select-option>
+        </a-select>
+      </template>
+      <!-- 操作 -->
+      <template slot="action" slot-scope="text, record">
+        <div>
+          <a-button
+          size="small"
+          type="link"
+          :loading="delLoading"
+          class="button-error"
+          v-if="!(record.promotionFlag == 'GIFT'&&record.salesPromoDetailParentSn)"
+          @click="handleDel(record)"
+        >删除</a-button>
+
+        <a-button
+          size="small"
+          type="link"
+          :loading="delLoading"
+          class="button-primary"
+          v-if="record.promotionFlag != 'GIFT'"
+          @click="handleUpdateActive(record)"
+        >换促销</a-button>
+        </div>
+      </template>
+      <template slot="footer" slot-scope="currentPageData">
+        <!-- 总计 -->
+        <a-alert type="info" banner :showIcon="false">
+            <div slot="message" class="alert-bar">
+              <div class="countData" v-html="boldAmounts(countData&&countData.remarks||'')"></div>
+              <div style="display: flex;">
+                <div>
+                  款数:<strong>{{ countData&&(countData.totalCategory || countData.totalCategory==0) ? countData.totalCategory : 0 }}</strong>
+                </div>
+                <div style="padding: 0 10px;">
+                  数量:<strong>{{ countData&&(countData.totalQty || countData.totalQty==0) ? countData.totalQty : 0 }}</strong>
+                </div>
+                <div>
+                  <div v-if="$hasPermissions('B_salesEdit_salesPrice')">总金额:<strong>{{ countData&&(countData.totalAmount || countData.totalAmount==0) ? toThousands(countData.totalAmount) : '0.00' }}</strong></div>
+                  <div v-if="$hasPermissions('B_salesEdit_salesPrice')&&countData&&countData.lossAmount">优惠金额:<strong>{{ toThousands(countData.lossAmount) }}</strong></div>
+                </div>
+              </div>
+            </div>
+          </a-alert>
+      </template>
+    </s-table>
+    
+      <!-- 导入产品 -->
+      <importGuideModal 
+      :openModal="openGuideModal" 
+      :params="{salesBillSn: $route.params.sn, salesPromoSn: promo.salesPromoSn}" 
+      :promoProductClz="promoProductClz"
+      @close="closeGuideModel" 
+      @ok="hanldeImportOk" />
+      <!-- 仓库设置 -->
+      <setWarehouse :show="openWarehouseModal" @ok="chooseWarehouseOk" @cancel="openWarehouseModal=false"></setWarehouse>
+      <!-- 换促销 -->
+      <updateActiveModal ref="updateActive" :show="openUpActiveModal" @ok="upActiveOk" @cancel="openUpActiveModal=false"></updateActiveModal>
+  </div>
+</template>
+
+<script>
+  import { commonMixin } from '@/utils/mixin'
+  import { STable, VSelect } from '@/components'
+  import ImportGuideModal from './importGuideModal.vue'
+  import setWarehouse from './setWarehouse.vue'
+  import updateActiveModal from './updateActiveModal.vue'
+  import chooseWarehouse from '@/views/common/chooseWarehouse'
+  import ProductBrand from '@/views/common/productBrand.js'
+  import productTypeAll from '@/views/common/productTypeAll.js'
+  import { 
+    salesDetailList, 
+    salesPromoDetailCount, 
+    salesDetailInsert, 
+    salesDetailUpdateQty, 
+    salesDetailDel, 
+    salesDetailBatchDel, 
+    deleteAll, 
+    updateWarehouse, 
+    salesBatchInsert,
+     } from '@/api/salesDetailNew'
+  export default {
+    name: 'ProductList',
+    mixins: [commonMixin],
+    components: { 
+      STable,
+      VSelect,
+      ImportGuideModal,
+      chooseWarehouse,
+      setWarehouse,
+      ProductBrand,
+      productTypeAll,
+      updateActiveModal
+    },
+    props: {
+      openModal: { //  弹框显示状态
+        type: Boolean,
+        default: false
+      },
+      newLoading: Boolean,
+      detailData: {
+        type: Object,
+        default: function(){return null}
+      },
+      promo: {
+        type: Object,
+        default: function(){return null}
+      },
+      id: {
+        type: String,
+        default: ''
+      },
+      warehouseSn: {
+        type: String,
+        default: ''
+      },
+      salesBillSn: {
+        type: String,
+        default: ''
+      }
+    },
+    data () {
+      return {
+        spinning: false,
+        // 加载数据方法 必须为 Promise 对象
+        loadData: parameter => {
+          this.disabled = true
+          this.disablePromo = this.promo.disabled
+          this.queryParam.salesBillSn = this.salesBillSn || ''
+          this.getCount()
+          return salesDetailList(Object.assign(parameter, this.queryParam, {
+            showStock: true, 
+            promoRuleSn: this.promo.promoRuleSn,
+            promoSn: this.promo.promoSn,
+            salesPromoSn: this.promo.salesPromoSn
+          })).then(res => {
+            let data
+            if (res.status == 200) {
+              data = res.data
+              const no = (data.pageNo - 1) * data.pageSize
+              for (var i = 0; i < data.list.length; i++) {
+                data.list[i].no = no + i + 1
+                data.list[i].qtyBackups = data.list[i].qty
+                data.list[i].productUnit = data.list[i].productEntity&&data.list[i].productEntity.unit
+                // 按数量设置
+                if(data.list[i].unitType=='SL'){
+                  data.list[i].unitQtyV = data.list[i].unitQty ? (data.list[i].unitQty + data.list[i].productUnit) : '--'
+                  data.list[i].unitQtyR = data.list[i].unitQty
+                }else{
+                  data.list[i].unitQtyV = data.list[i].packQty&&data.list[i].unitQty ? ((data.list[i].unitQty+'*'+data.list[i].packQty) + data.list[i].productUnit) : '--'
+                  data.list[i].unitQtyR = data.list[i].packQty*data.list[i].unitQty
+                }
+              }
+              this.dataSource = data.list
+            }
+            this.disabled = false
+            return data
+          })
+        },
+        showSearchBox: false,
+        showDescBox: false,
+        openWarehouseModal: false, // 打开仓库设置
+        openGuideModal: false, //  导入产品引导
+        delLoading: false,
+        chooseDisabled: false,
+        disabled: false, //  查询、重置按钮是否可操作
+        queryParam: {
+          warehouseSn: undefined,
+          productCode: '',
+          productName: '',
+          productBrandSn: undefined,
+          productTypeSn1: '', //  产品一级分类
+          productTypeSn2: '', //  产品二级分类
+          productTypeSn3: '' //  产品三级分类
+        },
+        productType: [],
+        rowSelectionInfo: null,
+        warehouseDataList: [],
+        openUpActiveModal: false,
+        descDetail: null,
+        promoProductClz: null, // 活动产品分类
+        disablePromo: false,
+        countData: null
+      }
+    },
+    computed: {
+      selectTotal () {
+        return this.rowSelectionInfo && this.rowSelectionInfo.selectedRowKeys.length || 0
+      },
+      columns () {
+        const arr = [
+          { title: '序号', dataIndex: 'no', width: '4%', align: 'center' },
+          { title: '产品编码', dataIndex: 'productEntity.code', scopedSlots: { customRender: 'productCode' }, width: '13%', align: 'center' },
+          { title: '产品名称', dataIndex: 'productEntity.name', scopedSlots: { customRender: 'productName' }, width: this.promo.promotionRule.promotionRuleType=='PROMO_PROD' ? '20%' : '26%', align: 'left' },
+          { title: '起订量', dataIndex: 'unitQtyV', width: '6%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
+          { title: '销售数量', scopedSlots: { customRender: 'salesNums' }, width: '6%', align: 'center' },
+          { title: '库存', dataIndex: 'stockQty', scopedSlots: { customRender: 'stockQty' }, width: '6%', align: 'center' },
+          { title: '出库仓库', scopedSlots: { customRender: 'warehouseBox' }, width: '10%', align: 'center' },
+          { title: '单位', dataIndex: 'productEntity.unit', width: '4%', align: 'center', customRender: function (text) { return text || '--' } },
+          // { title: '售价小计', dataIndex: 'totalAmount', width: '8%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
+          { title: '操作', scopedSlots: { customRender: 'action' }, width: '12%', align: 'center' }
+        ]
+        if (this.$hasPermissions('B_salesEdit_salesPrice')) { // 售价权限
+          arr.splice(3, 0, { title: '售价', dataIndex: 'price', width: '6%', align: 'right', scopedSlots: { customRender: 'price' } })
+          let idx = 0
+          // 如果是特价活动
+          if(this.promo.promotionRule.promotionRuleType=='PROMO_PROD'){
+            idx = idx + 1
+            arr.splice(4, 0, { title: '折扣', dataIndex: 'discountPrice', width: '6%', align: 'right', scopedSlots: { customRender: 'discountPrice' }})
+          }
+          arr.splice(8+idx, 0, { title: '售价小计', dataIndex: 'totalAmount', width: '6%', align: 'right', customRender: text => ((text || text == 0) ? this.toThousands(text) : '--') })
+        }
+        return arr
+      }
+    },
+    watch: {
+      salesBillSn(newValue, oldValue) {
+        this.resetSearchForm()
+      }
+    },
+    methods: {
+      filterOption (input, option) {
+        return (
+          option.componentOptions.children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0
+        )
+      },
+      warehouseLoad(sn,list){
+        this.warehouseDataList = list
+      },
+      showSearch(){
+        this.showSearchBox = !this.showSearchBox
+      },
+      showDesc(descDetail){
+        this.showDescBox = !this.showDescBox
+        this.descDetail = descDetail
+        this.$emit("showDesc",this.showDescBox)
+      },
+      openCpModal(){
+        this.$emit('openCpModal', 1, this.id)
+      },
+      // 表格选中项
+      rowSelectionFun (obj) {
+        this.rowSelectionInfo = obj || null
+      },
+      //  产品分类  change
+      changeProductType (val, opt) {
+        this.queryParam.productTypeSn1 = val[0] ? val[0] : ''
+        this.queryParam.productTypeSn2 = val[1] ? val[1] : ''
+        this.queryParam.productTypeSn3 = val[2] ? val[2] : ''
+      },
+      // 禁用活动
+      disableActive(flag){
+        console.log(flag,'------')
+        this.disablePromo = flag
+      },
+      // 统计
+      getCount(){
+        salesPromoDetailCount(Object.assign(this.queryParam, {
+            salesBillSn: this.salesBillSn,
+            promoRuleSn: this.promo.promoRuleSn,
+            promoSn: this.promo.promoSn,
+            salesPromoSn: this.promo.salesPromoSn
+          })).then(res => {
+          if(res.status == 200){
+            this.countData = res.data
+          }
+        })
+      },
+      //  重置
+      resetSearchForm (flag) {
+        this.queryParam.productCode = ''
+        this.queryParam.productName = ''
+        this.queryParam.warehouseSn = undefined
+        this.queryParam.productBrandSn = undefined
+        this.queryParam.productTypeSn1 = ''
+        this.queryParam.productTypeSn2 = ''
+        this.queryParam.productTypeSn3 = ''
+        this.productType = []
+        this.rowSelectionInfo = null
+        this.$refs.table.clearSelected()
+        this.$refs.table.refresh(!!flag)
+      },
+      // 删除全部产品
+      handleBatchDelAll () {
+        const _this = this
+        if (_this.dataSource.length == 0) {
+          _this.$message.warning('暂无可删除的已选产品!')
+          return
+        }
+        this.$confirm({
+          title: '提示',
+          content: '确认要删除全部已选产品吗?',
+          centered: true,
+          onOk () {
+            _this.spinning = true
+            deleteAll({ salesBillSn: _this.salesBillSn, salesPromoSn: _this.promo.salesPromoSn }).then(res => {
+              if (res.status == 200) {
+                _this.$refs.table.refresh(true)
+                _this.$emit('insterOk','promo')
+                _this.$message.success(res.message)
+              }
+              _this.spinning = false
+            })
+          }
+        })
+      },
+      // 批量删除已选产品
+      handleBatchDel () {
+        const _this = this
+        if (!_this.rowSelectionInfo || (_this.rowSelectionInfo && _this.rowSelectionInfo.selectedRowKeys.length < 1)) {
+          _this.$message.warning('请先选择要删除的产品后再进行批量操作!')
+          return
+        }
+        const obj = []
+        _this.rowSelectionInfo && _this.rowSelectionInfo.selectedRows.map(item => {
+          obj.push(item.salesBillDetailSn)
+        })
+        this.$confirm({
+          title: '提示',
+          content: '已选产品' + obj.length + '项,确认要批量删除吗?',
+          centered: true,
+          onOk () {
+            _this.spinning = true
+            salesDetailBatchDel({
+              salesBillSn: _this.salesBillSn,
+              salesPromoSn: _this.promo.salesPromoSn,
+              salesBillDetailSnList: obj
+            }).then(res => {
+              if (res.status == 200) {
+                _this.$refs.table.refresh(false)
+                _this.$emit('insterOk','promo')
+                _this.$message.success(res.message)
+              }
+              _this.spinning = false
+            })
+          }
+        })
+      },
+      // 设置单个出库仓库
+      handleWarehouseBox (row) {
+        const snArr = [row.salesBillDetailSn]
+        const ajax_data = {
+          warehouseSn: row.warehouseSn,
+          salesBillDetailSnList: snArr,
+          salesBillSn: this.salesBillSn,
+          salesPromoSn: this.promo.salesPromoSn
+        }
+        this.setWarehouseInfo(ajax_data)
+      },
+      chooseWarehouseOk (sn) {
+        const _this = this
+        const snArr = []
+        _this.rowSelectionInfo.selectedRows.forEach(item => {
+          snArr.push(item.salesBillDetailSn)
+        })
+        const ajax_data = {
+          warehouseSn: sn,
+          salesBillDetailSnList: snArr,
+          salesBillSn: _this.salesBillSn,
+          salesPromoSn: _this.promo.salesPromoSn
+        }
+        _this.setWarehouseInfo(ajax_data)
+      },
+      setWarehouseInfo (data) {
+        const _this = this
+        _this.spinning = true
+        updateWarehouse(data).then(res => {
+          console.log(res)
+          if (res.status == 200) {
+            _this.$message.success(res.message)
+          }
+          _this.openWarehouseModal = false
+          _this.$refs.table.refresh(false)
+          _this.spinning = false
+        })
+      },
+      handleMenuClick (e) {
+        const _this = this
+        if (e.key == 0) { // 仓库设置
+          if (!_this.rowSelectionInfo || (_this.rowSelectionInfo && _this.rowSelectionInfo.selectedRowKeys.length < 1)) {
+            _this.$message.warning('请先选择要设置的产品!')
+          } else {
+            _this.openWarehouseModal = true
+          }
+        } else if (e.key == 1) { // 删除已选项
+          this.handleBatchDel()
+        } else {
+          this.handleBatchDelAll()
+        }
+      },
+      // 打开换促销活动列表选项
+      handleUpdateActive(record){
+        this.$refs.updateActive.getActiveList({
+          productSn: record.productSn, 
+          salesBillSn: this.salesBillSn, 
+          promoRuleSn: this.promo.promoRuleSn
+        },record)
+        this.openUpActiveModal = true
+      },
+      // 已选产品  blur
+      onCellBlur (val, record) {
+        const _this = this
+        //  光标移出,值发生改变再调用编辑接口
+        if (val && val != record.qtyBackups) {
+          _this.spinning = true
+          salesDetailUpdateQty({
+            salesBillDetailSn: record.salesBillDetailSn,
+            qty: record.qty,
+            salesBillSn: _this.salesBillSn,
+            salesPromoSn: _this.promo.salesPromoSn
+          }).then(res => {
+            if (res.status == 200) {
+              _this.$emit('insterOk','promo')
+              _this.$message.success(res.message)
+            }
+            _this.$refs.table.refresh(false)
+            _this.spinning = false
+          })
+        } else {
+          record.qty = record.qtyBackups
+        }
+      },
+    
+      // 删除产品
+      handleDel (row) {
+        const _this = this
+        this.$confirm({
+          title: '提示',
+          content: '确认要删除吗?',
+          centered: true,
+          closable: true,
+          onOk () {
+            _this.delLoading = true
+            _this.spinning = true
+            salesDetailDel({ salesBillDetailSn: row.salesBillDetailSn, salesBillSn: _this.salesBillSn, salesPromoSn: _this.promo.salesPromoSn }).then(res => {
+              if (res.status == 200) {
+                _this.$refs.table.refresh(false)
+                _this.$emit('insterOk','promo')
+                _this.$message.success(res.message)
+              }
+              _this.delLoading = false
+              _this.spinning = false
+            })
+          }
+        })
+      },
+      // 确定更换促销活动
+      async upActiveOk(data, editRow){
+        this.spinning = true
+        const params = { 
+          salesBillDetailSn: editRow.salesBillDetailSn, 
+          salesBillSn: this.salesBillSn, 
+          oldSalesPromoSn: this.promo.salesPromoSn
+        }
+        // 更换活动
+        this.$emit("upActive",this.promo, data, params)
+      },
+      upAcitveSuccess(){
+        this.spinning = false
+        this.openUpActiveModal = false
+        this.$refs.table.refresh(false)
+      },
+      // 添加产品
+      insterProduct (row, promotionFlag, promoProductClz) {
+        console.log(row, promotionFlag, promoProductClz)
+        // 防止多次添加产品
+        if (this.isInster) { return }
+        this.saveNewProduct(row, promotionFlag, promoProductClz)
+      },
+      // 保存添加的产品到销售列表
+      saveNewProduct (row, promotionFlag, promoProductClz) {
+        this.$message.loading('正在添加产品...', 1)
+        this.isInster = true
+        this.spinning = true
+        console.log(row)
+        const params = {
+          salesPromoSn: this.promo.salesPromoSn,
+          promoRuleSn: this.promo.promoRuleSn,
+          promoSn: this.promo.promoSn,
+          promoProductClz: promoProductClz,
+          packQty: row.productPackQty,
+          productSn: row.productSn,
+          showCost: row.lastStockCost,
+          price: row.productPrice,
+          origPrice: row.origPrice,
+          promotionGiftsAmount: 0,
+          usePromotionGiftsAmount: 0,
+          qty: row.salesNums,
+          salesBillSn: this.detailData.salesBillSn,
+          salesBillNo: this.detailData.salesBillNo,
+          purchaseBillSn: this.detailData.purchaseBillSn,
+          purchaseBillNo: this.detailData.purchaseBillNo,
+          stockSn: row.stockSn,
+          promotableFlag: row.isJoinActivityProduct || 0, // 可促销标记 有活动的传1,没活动的传0
+          promotionFlag: promotionFlag, // 促销标记 正品传0,促销品传1
+          warehouseSn: row.warehouseSn
+        }
+        salesDetailInsert(params).then(res => {
+          if (res.status == 200) {
+            this.$message.success('产品添加成功', 2.5)
+            this.resetSearchForm(true)
+            this.$emit('insterOk','promo')
+          }
+          this.spinning = false
+          this.isInster = false
+        }).catch(err => {
+          this.isInster = false
+          this.spinning = false
+        })
+      },
+      // 导入产品
+      handleImportClick(e){
+        console.log(e)
+        this.openGuideModal = true
+        this.promoProductClz = e.key
+      },
+      closeGuideModel () {
+        this.openGuideModal = false
+        this.promoProductClz = ''
+      },
+      // 批量导入产品
+      hanldeImportOk (data, salesPromoSn) {
+        const params = {
+          salesBillSn: this.detailData.salesBillSn,
+          salesBillDetailList: data
+        }
+        // 活动导入
+        if (salesPromoSn) {
+          params.salesPromoSn = salesPromoSn
+          params.promoRuleSn = this.promo.promoRuleSn
+          params.promoProductClz = this.promoProductClz
+        }
+        
+        salesBatchInsert(params).then(res => {
+          if (res.status == 200) {
+            this.$message.success('产品导入成功', 2.5)
+            this.resetSearchForm(true)
+            this.$emit('insterOk','promo')
+          }
+        })
+      },
+    }
+  }
+</script>
+
+<style lang="less">
+   .ant-input-number-sm input{
+    text-align: center;
+   }
+   .alert-bar{
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    .countData{
+      span{
+        margin: 0 2px;
+        color: rgb(0, 153, 255);
+      }
+      span.cor1{
+        color: rgb(248, 132, 0);
+      }
+      b{
+        font-weight: bold;
+        span{
+          color: red;
+          font-weight: normal;
+        }
+      }
+    }
+    > div{
+      &:first-child{
+        flex-grow: 1;
+        width:70%;
+        padding-right: 100px;
+      }
+    }
+   }
+</style>

+ 565 - 0
src/views/salesManagement/salesQueryNew/comps/productNormalList.vue

@@ -0,0 +1,565 @@
+<template>
+  <div>
+    <!-- 筛选条件 -->
+    <div class="table-page-search-wrapper" style="margin:0">
+      <a-form layout="inline" @keyup.enter.native="$refs.table.refresh(true)">
+        <a-row :gutter="15">
+          <a-col :md="4" :sm="24">
+            <a-form-item label="出库仓库" prop="warehouseSn">
+              <chooseWarehouse ref="warehouse" v-model="queryParam.warehouseSn" @load="warehouseLoad"></chooseWarehouse>
+            </a-form-item>
+          </a-col>
+          <a-col :md="4" :sm="24">
+            <a-form-item label="产品编码" prop="productCode">
+              <a-input id="salesEdit-productCode" v-model.trim="queryParam.productCode" placeholder="请输入产品编码" allowClear />
+            </a-form-item>
+          </a-col>
+          <a-col :md="4" :sm="24">
+            <a-form-item label="产品名称" prop="productName">
+              <a-input id="salesEdit-productName" v-model.trim="queryParam.productName" placeholder="请输入产品名称" allowClear />
+            </a-form-item>
+          </a-col>
+          <a-col :md="4" :sm="24">
+            <a-form-item label="品牌">
+              <ProductBrand id="salesEdit-productBrandSn" v-model="queryParam.productBrandSn"></ProductBrand>
+            </a-form-item>
+          </a-col>
+          <a-col :md="4" :sm="24">
+            <a-form-item label="产品分类">
+              <productTypeAll placeholder="请选择产品分类" @change="changeProductType" v-model="productType" id="salesEdit-productType"></productTypeAll>
+            </a-form-item>
+          </a-col>
+          <a-col :md="4" :sm="24" style="margin-bottom: 10px;">
+            <a-button type="primary" @click="$refs.table.refresh(true)" :disabled="disabled" id="salesEdit-refresh">查询</a-button>
+            <a-button style="margin-left: 5px" @click="resetSearchForm" :disabled="disabled" id="salesEdit-reset">重置</a-button>
+          </a-col>
+        </a-row>
+      </a-form>
+    </div>
+    
+    <div class="table-page-search-wrapper">
+      <a-row :gutter="15" type="flex" justify="space-between" align="middle">
+        <a-col :md="8" :sm="24" style="text-align:left;">
+          <span v-if="selectTotal" style="margin-right:5px;">已选{{ selectTotal }}项</span>
+        </a-col>
+        <a-col :md="16" :sm="24" style="text-align:right;">
+          <a-dropdown>
+            <a-menu slot="overlay" @click="handleMenuClick">
+              <a-menu-item key="0">
+                仓库设置
+              </a-menu-item>
+              <a-menu-item key="1">
+                删除已选项
+              </a-menu-item>
+              <a-menu-item key="2">
+                全部删除
+              </a-menu-item>
+            </a-menu>
+            <a-button
+              type="link"
+              class="button-info"
+            > 批量操作 <a-icon type="down" /> </a-button>
+          </a-dropdown>
+          <!-- <a-button
+            type="link"
+            class="button-info"
+             @click="showSearch=!showSearch" ><a-icon type="search"/> 筛选</a-button> -->
+          <a-button
+            type="link"
+            class="button-info"
+            @click="openGuideModal=true"><a-icon type="login" /> 导入产品</a-button>
+          <a-button
+            type="link"
+            class="button-info"
+            @click="openCpModal"><a-icon type="plus" /> 添加产品</a-button>
+        </a-col>
+      </a-row>
+    </div>
+    
+    <!-- 已选配件列表 -->
+    <s-table
+      class="sTable" 
+      ref="table" 
+      size="small" 
+      :scroll="showTotal ? null :{ y: tableHeight }" 
+      :rowKey="(record) => record.id" 
+      :columns="columns" 
+      :data="loadData" 
+      :row-selection="{ columnWidth: 40 }" 
+      @rowSelection="rowSelectionFun" 
+      :pageSize="showTotal?10:30" 
+      :defaultLoadData="false"
+      bordered>
+      <!-- 产品编码 -->
+      <template slot="productCode" slot-scope="text, record">
+        <a-badge count="缺" v-if="Number(record.stockQty||0) < Number(record.unpushedQty||0)" :number-style="{ zoom:'80%' }">
+          <div style="padding-right: 15px;">{{ text }}</div>
+        </a-badge>
+        <span v-if="!(Number(record.stockQty||0) < Number(record.unpushedQty||0))">{{ text }}</span>
+      </template>
+      <!-- 产品名称 -->
+      <template slot="productName" slot-scope="text, record">
+        <div class="ellipsisCon">
+          <a-tooltip placement="rightBottom">
+            <template slot="title">
+              <span>{{ text }}</span>
+            </template>
+            <span class="ellipsisText">{{ text }}</span>
+          </a-tooltip>
+          <a-badge :number-style="{ backgroundColor: '#52c41a' }" count="活动" v-if="record.promotableFlag == 1"></a-badge>
+        </div>
+      </template>
+      <!-- 销售数量 -->
+      <template slot="salesNums" slot-scope="text, record">
+        <a-input-number
+          id="salesEdit-qty"
+          size="small"
+          v-model="record.qty"
+          :precision="0"
+          :min="1"
+          :max="999999"
+          placeholder="请输入"
+          @blur="e => onCellBlur(e.target.value, record)"
+          style="width: 100%;" />
+      </template>
+      <!-- 当前库存 -->
+      <template slot="stockQty" slot-scope="text, record">
+        <div v-if="record.stockQty || record.stockQty==0">
+          <p style="margin: 0;" v-if="Number(record.stockQty) < Number(record.unpushedQty)">{{ record.stockQty }}(<span class="redStyle">缺{{ Number(record.unpushedQty||0) - Number(record.stockQty||0) }}</span>)</p>
+          <p style="margin: 0;" v-else>{{ record.stockQty }}</p>
+        </div>
+        <span v-else>--</span>
+      </template>
+      <!-- 出库仓库 -->
+      <template slot="warehouseBox" slot-scope="text, record">
+        <a-select
+          size="small"
+          style="width:100%;" 
+          placeholder="请选择仓库"
+          v-model="record.warehouseSn"
+          :showSearch="true"
+          @change="handleWarehouseBox(record)"
+          mode="default"
+          :filter-option="filterOption">
+          <a-select-option v-for="item in warehouseDataList" :key="item.warehouseSn" :value="item.warehouseSn">{{ item.name }}</a-select-option>
+        </a-select>
+      </template>
+      <!-- 操作 -->
+      <template slot="action" slot-scope="text, record">
+        <a-button
+          size="small"
+          type="link"
+          :loading="delLoading"
+          class="button-error"
+          @click="handleDel(record)"
+        >删除</a-button>
+      </template>
+      <template slot="footer">
+        <!-- 总计 -->
+        <a-alert type="info" v-if="showTotal" banner :showIcon="false">
+          <div slot="message" style="text-align: right;">
+              款数:<strong>{{ countData&&(countData.totalCategory || countData.totalCategory==0) ? countData.totalCategory : 0 }}</strong>;
+              数量:<strong>{{ countData&&(countData.totalQty || countData.totalQty==0) ? countData.totalQty : 0 }}</strong>;
+              <span v-if="$hasPermissions('B_salesEdit_salesPrice')">总金额:<strong>{{ countData&&(countData.totalAmount || countData.totalAmount==0) ? toThousands(countData.totalAmount) : '0.00' }}</strong>;</span>
+          </div>
+        </a-alert>
+      </template>
+    </s-table>
+
+    <!-- 导入产品 -->
+    <importGuideModal :openModal="openGuideModal" :params="{salesBillSn: salesBillSn}" @close="closeGuideModel" @ok="hanldeOk" />
+    <!-- 仓库设置 -->
+    <setWarehouse :show="openWarehouseModal" @ok="chooseWarehouseOk" @cancel="openWarehouseModal=false"></setWarehouse>
+  </div>
+</template>
+
+<script>
+  import { commonMixin } from '@/utils/mixin'
+  import { STable, VSelect } from '@/components'
+  import ImportGuideModal from './importGuideModal.vue'
+  import setWarehouse from './setWarehouse.vue'
+  import chooseWarehouse from '@/views/common/chooseWarehouse'
+  import ProductBrand from '@/views/common/productBrand.js'
+  import productTypeAll from '@/views/common/productTypeAll.js'
+  import { 
+    salesDetailList, 
+    salesDetailInsert, 
+    salesDetailUpdateQty, 
+    salesDetailDel, 
+    salesDetailBatchDel, 
+    deleteAll, 
+    updateWarehouse, 
+    salesDetaiCount, 
+    salesBatchInsert } from '@/api/salesDetailNew'
+  export default {
+    name: 'ProductList',
+    mixins: [commonMixin],
+    components: { 
+      STable,
+      VSelect,
+      ImportGuideModal,
+      chooseWarehouse,
+      setWarehouse,
+      ProductBrand,
+      productTypeAll
+    },
+    props: {
+      openModal: { //  弹框显示状态
+        type: Boolean,
+        default: false
+      },
+      newLoading: Boolean,
+      detailData: {
+        type: Object,
+        default: function(){return null}
+      },
+      warehouseSn: {
+        type: String,
+        default: ''
+      },
+      salesBillSn: {
+        type: String,
+        default: ''
+      },
+      showTotal:{
+        type: Boolean,
+        default: true
+      }
+    },
+    data () {
+      return {
+        spinning: false,
+        // 加载数据方法 必须为 Promise 对象
+        loadData: parameter => {
+          this.disabled = true
+          this.queryParam.salesBillSn = this.salesBillSn || ''
+          this.getCount()
+          return salesDetailList(Object.assign(parameter, this.queryParam, {showStock: true})).then(res => {
+            let data
+            if (res.status == 200) {
+              data = res.data
+              const no = (data.pageNo - 1) * data.pageSize
+              for (var i = 0; i < data.list.length; i++) {
+                data.list[i].no = no + i + 1
+                data.list[i].qtyBackups = data.list[i].qty
+                data.list[i].warehouseBackups = data.list[i].warehouseSn
+              }
+              this.dataSource = data.list
+            }
+            this.disabled = false
+            return data
+          })
+        },
+        showSearch: false,
+        openWarehouseModal: false, // 打开仓库设置
+        openGuideModal: false, //  导入产品引导
+        delLoading: false,
+        chooseDisabled: false,
+        disabled: false, //  查询、重置按钮是否可操作
+        queryParam: {
+          warehouseSn: undefined,
+          productCode: '',
+          productName: '',
+          productBrandSn: undefined,
+          productTypeSn1: '', //  产品一级分类
+          productTypeSn2: '', //  产品二级分类
+          productTypeSn3: '' //  产品三级分类
+        },
+        productType: [],
+        rowSelectionInfo: null,
+        warehouseDataList: [],
+        countData: null,
+        isInster: false
+      }
+    },
+    computed: {
+      selectTotal () {
+        return this.rowSelectionInfo && this.rowSelectionInfo.selectedRowKeys.length || 0
+      },
+      tableHeight(){
+        return window.innerHeight - 395
+      },
+      columns () {
+        const arr = [
+          { title: '序号', dataIndex: 'no', width: '4%', align: 'center' },
+          { title: '产品编码', dataIndex: 'productEntity.code', scopedSlots: { customRender: 'productCode' }, width: '13%', align: 'center' },
+          { title: '产品名称', dataIndex: 'productEntity.name', scopedSlots: { customRender: 'productName' }, width: '20%', align: 'left' },
+          // { title: '售价', dataIndex: 'price', width: '8%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
+          { title: '销售数量', scopedSlots: { customRender: 'salesNums' }, width: '8%', align: 'center' },
+          { title: '库存', dataIndex: 'stockQty', scopedSlots: { customRender: 'stockQty' }, width: '8%', align: 'center' },
+          { title: '出库仓库', scopedSlots: { customRender: 'warehouseBox' }, width: '15%', align: 'center' },
+          { title: '单位', dataIndex: 'productEntity.unit', width: '6%', align: 'center', customRender: function (text) { return text || '--' } },
+          // { title: '售价小计', dataIndex: 'totalAmount', width: '8%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
+          { title: '操作', scopedSlots: { customRender: 'action' }, width: '10%', align: 'center' }
+        ]
+        if (this.$hasPermissions('B_salesEdit_salesPrice')) { // 售价权限
+          arr.splice(3, 0, { title: '售价', dataIndex: 'price', width: '8%', align: 'right', customRender: text => ((text || text == 0) ? this.toThousands(text) : '--') })
+          arr.splice(7, 0, { title: '售价小计', dataIndex: 'totalAmount', width: '8%', align: 'right', customRender: text => ((text || text == 0) ? this.toThousands(text) : '--') })
+        }
+        return arr
+      }
+    },
+    methods: {
+      filterOption (input, option) {
+        return (
+          option.componentOptions.children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0
+        )
+      },
+      warehouseLoad(sn,list){
+        this.warehouseDataList = list
+      },
+      // 表格选中项
+      rowSelectionFun (obj) {
+        this.rowSelectionInfo = obj || null
+      },
+      openCpModal(){
+        this.$emit('openCpModal', 0, 'productNormalList')
+      },
+      // 统计
+      getCount(){
+        salesDetaiCount(Object.assign(this.queryParam, {showStock: true})).then(res => {
+          if(res.status == 200){
+            this.countData = res.data
+          }
+        })
+      },
+      handleBatchDelAll () {
+        const _this = this
+        if (_this.dataSource.length == 0) {
+          _this.$message.warning('暂无可删除的已选产品!')
+          return
+        }
+        this.$confirm({
+          title: '提示',
+          content: '确认要删除全部已选产品吗?',
+          centered: true,
+          onOk () {
+            _this.spinning = true
+            deleteAll({ salesBillSn: _this.salesBillSn }).then(res => {
+              if (res.status == 200) {
+                _this.$refs.table.refresh(false)
+                _this.$emit('insterOk','normal')
+                _this.$message.success(res.message)
+              }
+              _this.spinning = false
+            })
+          }
+        })
+      },
+      // 批量删除已选产品
+      handleBatchDel () {
+        const _this = this
+        if (!_this.rowSelectionInfo || (_this.rowSelectionInfo && _this.rowSelectionInfo.selectedRowKeys.length < 1)) {
+          _this.$message.warning('请先选择要删除的产品后再进行批量操作!')
+          return
+        }
+        const obj = []
+        _this.rowSelectionInfo && _this.rowSelectionInfo.selectedRows.map(item => {
+          obj.push(item.salesBillDetailSn)
+        })
+        this.$confirm({
+          title: '提示',
+          content: '已选产品' + obj.length + '项,确认要批量删除吗?',
+          centered: true,
+          onOk () {
+            _this.spinning = true
+            salesDetailBatchDel({
+              salesBillSn: _this.salesBillSn,
+              salesBillDetailSnList: obj
+            }).then(res => {
+              if (res.status == 200) {
+                _this.$refs.table.refresh(false)
+                _this.$emit('insterOk','normal')
+                _this.$message.success(res.message)
+              }
+              _this.spinning = false
+            })
+          }
+        })
+      },
+      // 设置单个出库仓库
+      handleWarehouseBox (row) {
+        const snArr = [row.salesBillDetailSn]
+        const ajax_data = {
+          warehouseSn: row.warehouseSn,
+          salesBillDetailSnList: snArr,
+          salesBillSn: this.salesBillSn
+        }
+        this.setWarehouseInfo(ajax_data)
+      },
+      chooseWarehouseOk (sn) {
+        const _this = this
+        const snArr = []
+        _this.rowSelectionInfo.selectedRows.forEach(item => {
+          snArr.push(item.salesBillDetailSn)
+        })
+        const ajax_data = {
+          warehouseSn: sn,
+          salesBillDetailSnList: snArr,
+          salesBillSn: _this.salesBillSn
+        }
+        _this.setWarehouseInfo(ajax_data)
+      },
+      setWarehouseInfo (data) {
+        const _this = this
+        _this.spinning = true
+        updateWarehouse(data).then(res => {
+          if (res.status == 200) {
+            _this.$message.success(res.message)
+          }
+          _this.$refs.table.refresh(false)
+          _this.openWarehouseModal = false
+          _this.spinning = false
+        })
+      },
+      //  产品分类  change
+      changeProductType (val, opt) {
+        this.queryParam.productTypeSn1 = val[0] ? val[0] : ''
+        this.queryParam.productTypeSn2 = val[1] ? val[1] : ''
+        this.queryParam.productTypeSn3 = val[2] ? val[2] : ''
+      },
+      handleMenuClick (e) {
+        const _this = this
+        if (e.key == 0) { // 仓库设置
+          if (!_this.rowSelectionInfo || (_this.rowSelectionInfo && _this.rowSelectionInfo.selectedRowKeys.length < 1)) {
+            _this.$message.warning('请先选择要设置的产品!')
+          } else {
+            _this.openWarehouseModal = true
+          }
+        } else if (e.key == 1) { // 删除已选项
+          this.handleBatchDel()
+        } else {
+          this.handleBatchDelAll()
+        }
+      },
+      // 已选产品  blur
+      onCellBlur (val, record) {
+        const _this = this
+        //  光标移出,值发生改变再调用编辑接口
+        if (val && val != record.qtyBackups) {
+          _this.spinning = true
+          salesDetailUpdateQty({
+            salesBillDetailSn: record.salesBillDetailSn,
+            qty: record.qty,
+            salesBillSn: _this.salesBillSn
+          }).then(res => {
+            if (res.status == 200) {
+              _this.$emit('insterOk','normal')
+              _this.$message.success(res.message)
+            }
+            _this.$refs.table.refresh(false)
+            _this.spinning = false
+          })
+        } else {
+          record.qty = record.qtyBackups
+        }
+      },
+      // 重置
+      resetSearchForm (flag) {
+        this.queryParam.productCode = ''
+        this.queryParam.productName = ''
+        this.queryParam.warehouseSn = undefined
+        this.queryParam.productBrandSn = undefined
+        this.queryParam.productTypeSn1 = ''
+        this.queryParam.productTypeSn2 = ''
+        this.queryParam.productTypeSn3 = ''
+        this.productType = []
+        this.$refs.table.clearSelected()
+        this.$refs.table.refresh(!!flag)
+      },
+      // 删除产品
+      handleDel (row) {
+        const _this = this
+        this.$confirm({
+          title: '提示',
+          content: '确认要删除吗?',
+          centered: true,
+          closable: true,
+          onOk () {
+            _this.delLoading = true
+            _this.spinning = true
+            salesDetailDel({ salesBillDetailSn: row.salesBillDetailSn, salesBillSn: _this.salesBillSn }).then(res => {
+              if (res.status == 200) {
+                _this.$message.success(res.message)
+                _this.$refs.table.refresh(false)
+                _this.$emit('insterOk','normal')
+              }
+              _this.delLoading = false
+              _this.spinning = false
+            })
+          }
+        })
+      },
+      // 添加产品
+      insterProduct (row, promotionFlag) {
+        console.log(row, promotionFlag)
+        // 防止多次添加产品
+        if (this.isInster) { return }
+        this.saveNewProduct(row, promotionFlag)
+      },
+      // 保存添加的产品到销售列表
+      saveNewProduct (row, promotionFlag) {
+        this.$message.loading('正在添加产品...', 1)
+        this.isInster = true
+        this.spinning = true
+        salesDetailInsert({
+          packQty: row.productPackQty,
+          productSn: row.productSn,
+          showCost: row.lastStockCost,
+          price: row.productPrice,
+          origPrice: row.productPrice,
+          promotionGiftsAmount: 0,
+          usePromotionGiftsAmount: 0,
+          qty: row.salesNums,
+          salesBillSn: this.detailData.salesBillSn,
+          salesBillNo: this.detailData.salesBillNo,
+          purchaseBillSn: this.detailData.purchaseBillSn,
+          purchaseBillNo: this.detailData.purchaseBillNo,
+          stockSn: row.stockSn,
+          promotableFlag: row.isJoinActivityProduct || 0, // 可促销标记 有活动的传1,没活动的传0
+          promotionFlag: promotionFlag, // 促销标记 正品传0,促销品传1
+          warehouseSn: row.warehouseSn
+        }).then(res => {
+          if (res.status == 200) {
+            this.$message.success('产品添加成功', 2.5)
+            this.resetSearchForm(true)
+            this.$emit('insterOk','normal')
+          }
+          this.spinning = false
+          this.isInster = false
+        }).catch(err => {
+          this.spinning = false
+          this.isInster = false
+        })
+      },
+      closeGuideModel () {
+        this.openGuideModal = false
+      },
+      // 批量导入产品
+      hanldeOk (data, salesPromoSn) {
+        const params = {
+          salesBillSn: this.detailData.salesBillSn,
+          salesBillDetailList: data
+        }
+       
+        salesBatchInsert(params).then(res => {
+          if (res.status == 200) {
+            this.$message.success('产品导入成功', 2.5)
+            this.resetSearchForm(true)
+            this.$emit('insterOk','normal')
+          }
+        })
+      },
+    }
+  }
+</script>
+
+<style lang="less">
+  .ant-input-number-sm input{
+    text-align: center;
+   }
+  .total-bar{
+    display:flex;
+    justify-content: space-between;
+  }
+</style>

+ 272 - 0
src/views/salesManagement/salesQueryNew/comps/queryPart.vue

@@ -0,0 +1,272 @@
+<template>
+  <div class="productInfoList-wrap">
+    <!-- 搜索条件 -->
+    <div class="table-page-search-wrapper">
+      <a-form layout="inline" @keyup.enter.native="searchForm">
+        <a-row :gutter="15">
+          <a-col :md="6" :sm="24">
+            <a-form-item label="出库仓库" prop="warehouseSn" required>
+              <chooseWarehouse ref="warehouse" :allowClear="false" v-model="queryParam.warehouseSn" :isDefault="true" @load="loadWarehouse"></chooseWarehouse>
+            </a-form-item>
+          </a-col>
+          <a-col :md="6" :sm="24">
+            <a-form-item label="产品编码">
+              <a-input id="productInfoList-code" v-model.trim="queryParam.productCode" allowClear placeholder="请输入产品编码"/>
+            </a-form-item>
+          </a-col>
+          <a-col :md="6" :sm="24">
+            <a-form-item label="产品名称">
+              <a-input id="productInfoList-name" v-model.trim="queryParam.productName" allowClear placeholder="请输入产品名称"/>
+            </a-form-item>
+          </a-col>
+          <template v-if="advanced">
+            <a-col :md="6" :sm="24">
+              <a-form-item label="原厂编码">
+                <a-input id="productInfoList-origCode" v-model.trim="queryParam.productOrigCode" allowClear placeholder="请输入原厂编码"/>
+              </a-form-item>
+            </a-col>
+            <a-col :md="6" :sm="24">
+              <a-form-item label="产品品牌">
+                <ProductBrand id="productInfoList-productBrandSn" v-model="queryParam.productBrandSn"></ProductBrand>
+              </a-form-item>
+            </a-col>
+            <a-col :md="6" :sm="24">
+              <a-form-item label="产品分类">
+                <ProductType id="productInfoList-productType" v-model="productType" @change="changeProductType"></ProductType>
+              </a-form-item>
+            </a-col>
+          </template>
+          <a-col :md="6" :sm="24" style="margin-bottom: 10px;">
+            <a-button type="primary" @click="searchForm" :disabled="disabled" id="productInfoList-refresh">查询</a-button>
+            <a-button style="margin-left: 5px" @click="resetSearchForm" id="productInfoList-reset">重置</a-button>
+            <a @click="advanced=!advanced" style="margin: 0 5px">
+              {{ advanced ? '收起' : '展开' }}
+              <a-icon :type="advanced ? 'up' : 'down'"/>
+            </a>
+          </a-col>
+        </a-row>
+      </a-form>
+    </div>
+    <!-- 列表 -->
+    <s-table
+      class="sTable"
+      ref="table"
+      size="small"
+      :rowKey="(record) => record.id"
+      :columns="columns"
+      :data="loadData"
+      :customRow="handleClickRow"
+      :scroll="{ y: tableHeight, x: 1050 }"
+      :pageSize="50"
+      :defaultLoadData="false"
+      bordered>
+      <!-- 销售数量 -->
+      <template slot="nums" slot-scope="text, record">
+        <div @dblclick.stop>
+          <a-input-number
+            size="small"
+            v-model="record.salesNums"
+            :precision="0"
+            :min="1"
+            :max="999999"
+            style="width: 100%;"
+            placeholder="请输入" />
+        </div>
+      </template>
+      <!-- 产品名称 -->
+      <template slot="productName" slot-scope="text, record">
+        <div class="ellipsisCon">
+          <a-tooltip placement="rightBottom">
+            <template slot="title">
+              <span>{{ text }}</span>
+            </template>
+            <span class="ellipsisText">{{ text }}</span>
+          </a-tooltip>
+          <a-badge :number-style="{ backgroundColor: '#52c41a' }" count="活动" v-if="record.isJoinActivityProduct == 1"></a-badge>
+        </div>
+      </template>
+      <!-- 操作 -->
+      <template slot="action" slot-scope="text, record">
+        <a-button
+          size="small"
+          type="link"
+          class="button-info"
+          :loading="newLoading"
+          @click="handleAdd(record)"
+          :disabled="!record.productPrice || record.productPrice<=0"
+          id="productInfoList-edit-btn">添加</a-button>
+      </template>
+    </s-table>
+  </div>
+</template>
+
+<script>
+import { commonMixin } from '@/utils/mixin'
+import { queryStockProductPage } from '@/api/stock'
+import ProductType from '@/views/common/productType.js'
+import ProductBrand from '@/views/common/productBrand.js'
+import chooseWarehouse from '@/views/common/chooseWarehouse'
+import { STable, VSelect } from '@/components'
+export default {
+  name: 'QueryPart',
+  mixins: [commonMixin],
+  components: { STable, VSelect, ProductBrand, ProductType, chooseWarehouse },
+  props: {
+    newLoading: Boolean
+  },
+  data () {
+    return {
+      advanced: false, // 高级搜索 展开/关闭
+      showSetting: false, // 设置弹框
+      productType: [],
+      buyerSn: '',
+      queryParam: { //  查询条件
+        productCode: '', //  产品编码
+        productName: '', //  产品名称
+        productOrigCode: '', //  原厂编码
+        productBrandSn: undefined, //  产品品牌
+        productTypeSn1: '', //  产品一级分类
+        productTypeSn2: '', //  产品二级分类
+        productTypeSn3: '', //  产品三级分类
+        warehouseSn: undefined
+      },
+      defaultWarehouseSn: undefined, // 默认仓库sn
+      disabled: false, //  查询、重置按钮是否可操作
+      tableHeight: 300,
+      // 加载数据方法 必须为 Promise 对象
+      loadData: parameter => {
+        this.disabled = true
+        this.queryParam.dealerSn = this.buyerSn
+        return queryStockProductPage(Object.assign(parameter, this.queryParam, { onlineFalg: '1', pricingState: 'PRICED' })).then(res => {
+          let data
+          if (res.status == 200) {
+            data = res.data
+            data.list = data.list.filter(item => item != null)
+            const no = (data.pageNo - 1) * data.pageSize
+            for (var i = 0; i < data.list.length; i++) {
+              data.list[i].no = no + i + 1
+              data.list[i].salesNums = 1
+              data.list[i].currentStockQty = data.list[i].currentStockQty || 0
+              const productPackQty = (data.list[i].productPackQty || data.list[i].productPackQty == 0) ? data.list[i].productPackQty : '--'
+              const productUnit = data.list[i].productUnit || '--'
+              const productPackQtyUnit = data.list[i].productPackQtyUnit || '--'
+              data.list[i].packQtyV = productPackQty + productUnit + '/' + productPackQtyUnit
+            }
+            this.disabled = false
+          }
+          return data
+        })
+      }
+    }
+  },
+  computed: {
+    columns () {
+      const arr = [
+        { title: '产品编码', dataIndex: 'productCode', width: '150px', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '产品名称', dataIndex: 'productName', scopedSlots: { customRender: 'productName' }, align: 'left' },
+        { title: '原厂编码', dataIndex: 'productOrigCode', width: '100px', align: 'center', customRender: function (text) { return text || '--' }, ellipsis: true },
+        { title: '品牌', dataIndex: 'productBrandName', width: '80px', align: 'center', customRender: function (text) { return text || '--' }, ellipsis: true },
+        { title: '出库仓库', dataIndex: 'warehouseName', width: '80px', align: 'center', customRender: function (text) { return text || '--' }, ellipsis: true },
+        { title: '库存数量', dataIndex: 'currentStockQty', width: '80px', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
+        { title: '单位', dataIndex: 'productUnit', width: '60px', align: 'center', customRender: function (text) { return text || '--' } },
+        // { title: '售价', dataIndex: 'productPrice', width: '8%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
+        { title: '包装数', dataIndex: 'packQtyV', width: '60px', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
+        { title: '销售数量', dataIndex: 'salesNums', scopedSlots: { customRender: 'nums' }, width: '80px', align: 'center', fixed: 'right' },
+        { title: '操作', dataIndex: 'action', scopedSlots: { customRender: 'action' }, width: '60px', align: 'center', fixed: 'right' }
+      ]
+      if (this.$hasPermissions('B_salesEdit_salesPrice')) { // 售价权限
+        arr.splice(6, 0, { title: '售价', dataIndex: 'productPrice', width: '80px', align: 'right', customRender: text => ((text || text == 0) ? this.toThousands(text) : '--') })
+      }
+      return arr
+    }
+  },
+  watch:{
+    advanced(a,b){
+      console.log(a,b)
+      this.tableHeight = window.innerHeight - (a ? 355 : 310)
+    }
+  },
+  methods: {
+    loadWarehouse (sn) {
+      this.defaultWarehouseSn = sn
+      this.queryParam.warehouseSn = sn
+      if(this.buyerSn){
+        this.resetSearchForm()
+      }
+    },
+    // 双击列表
+    handleClickRow (record) {
+      const _this = this
+      return {
+        on: {
+          dblclick: (event) => {
+            event.stopPropagation()
+            this.$emit('add', record, 0, 0)
+          }
+        }
+      }
+    },
+    // 查询
+    searchForm () {
+      if (this.queryParam.warehouseSn) {
+        this.$refs.table.refresh(true)
+      } else {
+        this.$message.info('请选择仓库')
+      }
+    },
+    //  重置
+    resetSearchForm () {
+      this.queryParam.productCode = ''
+      this.queryParam.productName = ''
+      this.queryParam.productOrigCode = ''
+      this.queryParam.productBrandSn = undefined
+      this.queryParam.productTypeSn1 = ''
+      this.queryParam.productTypeSn2 = ''
+      this.queryParam.productTypeSn3 = ''
+      this.productType = []
+      this.queryParam.warehouseSn = this.defaultWarehouseSn
+      this.$refs.table.refresh(true)
+    },
+    pageInit (data, promo) {
+      this.buyerSn = data.buyerSn
+      this.tableHeight = window.innerHeight - 310
+      this.resetSearchForm()
+    },
+    // 刷新当前页面
+    resetCurForm () {
+      const _this = this
+      _this.$nextTick(() => {
+        _this.$refs.table.refresh()
+      })
+    },
+    // 选择配件
+    handleAdd (row) {
+      this.$emit('add', row, 0, 0)
+    },
+    //  产品分类  change
+    changeProductType (val, opt) {
+      this.queryParam.productTypeSn1 = val[0] ? val[0] : ''
+      this.queryParam.productTypeSn2 = val[1] ? val[1] : ''
+      this.queryParam.productTypeSn3 = val[2] ? val[2] : ''
+    }
+  }
+}
+</script>
+<style lang="less" scoped>
+  .productInfoList-wrap{
+    .ellipsisCon{
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+      .ellipsisText{
+        width: 100%;
+        overflow: hidden;
+        text-overflow: ellipsis;
+        display: box;
+        display: -webkit-box;
+        -webkit-line-clamp: 1;
+        -webkit-box-orient: vertical;
+      }
+    }
+  }
+</style>

+ 91 - 0
src/views/salesManagement/salesQueryNew/comps/setWarehouse.vue

@@ -0,0 +1,91 @@
+<template>
+  <a-modal
+    v-model="opened"
+    :title="title"
+    centered
+    :maskClosable="false"
+    :confirmLoading="confirmLoading"
+    width="36%"
+    :footer="null"
+    @cancel="cancel"
+  >
+    <a-spin :spinning="spinning" tip="Loading...">
+      <a-form-model
+        id="chooseCustom-form"
+        ref="ruleForm"
+        :model="form"
+        :rules="rules"
+        :label-col="formItemLayout.labelCol"
+        :wrapper-col="formItemLayout.wrapperCol">
+        <a-form-model-item label="出库仓库" prop="warehouseSn">
+          <chooseWarehouse ref="warehouse" v-model="form.warehouseSn"></chooseWarehouse>
+        </a-form-model-item>
+        <a-form-model-item :wrapper-col="{ span: 12, offset: 6 }" style="text-align: center;margin-top:60px;">
+          <a-button @click="cancel" style="margin-right: 15px" id="chooseCustom-btn-back">取消</a-button>
+          <a-button type="primary" :loading="confirmLoading" @click="handleSubmit" id="chooseCustom-btn-submit">确定</a-button>
+        </a-form-model-item>
+      </a-form-model>
+    </a-spin>
+  </a-modal>
+</template>
+
+<script>
+import { commonMixin } from '@/utils/mixin'
+import { VSelect } from '@/components'
+import chooseWarehouse from '@/views/common/chooseWarehouse'
+export default {
+  name: 'SetWarehouse',
+  mixins: [commonMixin],
+  components: { VSelect, chooseWarehouse },
+  props: {
+    show: [Boolean]
+  },
+  data () {
+    return {
+      opened: this.show,
+      spinning: false,
+      title: '批量设置出库仓库',
+      confirmLoading: false,
+      formItemLayout: {
+        labelCol: { span: 4 },
+        wrapperCol: { span: 18 }
+      },
+      form: {
+        warehouseSn: undefined
+      },
+      rules: {
+        warehouseSn: [ { required: true, message: '请选择出库仓库', trigger: ['change', 'blur'] } ]
+      }
+    }
+  },
+  methods: {
+    //  保存
+    handleSubmit (e) {
+      e.preventDefault()
+      const _this = this
+      this.$refs.ruleForm.validate(valid => {
+        if (valid) {
+          _this.$emit('ok', this.form.warehouseSn)
+        } else {
+          console.log('error submit!!')
+          return false
+        }
+      })
+    },
+    cancel () {
+      this.opened = false
+      this.$emit('cancel')
+      this.$refs.ruleForm.resetFields()
+    }
+  },
+  watch: {
+    show (newValue, oldValue) {
+      this.opened = newValue
+      if (!newValue) {
+        this.form.warehouseSn = undefined
+        this.$refs.ruleForm.resetFields()
+      }
+    }
+  }
+}
+</script>

+ 104 - 0
src/views/salesManagement/salesQueryNew/comps/updateActiveModal.vue

@@ -0,0 +1,104 @@
+<template>
+  <a-modal
+    v-model="opened"
+    :title="title"
+    centered
+    :maskClosable="false"
+    :confirmLoading="confirmLoading"
+    width="450px"
+    :footer="null"
+    @cancel="cancel"
+  >
+    <a-spin :spinning="spinning" tip="Loading...">
+      <div style="padding: 0 30px;">
+        <aRadioGroup v-model="upActiveVal">
+          <aRadio :style="radioStyle" value="0">
+            不参加促销
+          </aRadio>
+          <div v-for="(item,idx) in activeList" :key="idx">
+            <div>
+              <strong>{{ item.title }}</strong> 
+              <!-- <a-popover title="活动详情">
+                <div slot="content">
+                  <ul class="active-li">
+                    <li><strong>促销类型:</strong> 买产品送产品</li>
+                    <li><strong>促销门槛:</strong> 购买1000元门槛产品,可使用200元配额,采购正价产品</li>
+                    <li><strong>促销规则:</strong> 购买满10个正价产品,送10个促销产品</li>
+                    <li><strong>限制正价产品款数</strong> 40</li>
+                    <li><strong>订单起订金额:</strong> 20000</li>
+                    <li><strong>活动经费上线:</strong> 5000</li>
+                  </ul>
+                </div>
+                <a-button type="link">详情</a-button>
+              </a-popover> -->
+            </div>
+            <aRadio :style="radioStyle" v-for="(sitem,sindex) in item.promotionRuleList" :key="sindex" :value="item.promotionSn+'-'+sitem.promotionRuleSn+'-'+sitem.promotionProductType">
+              {{sindex+1}}、{{ sitem.description }}
+            </aRadio>
+          </div>
+        </aRadioGroup>
+      </div>
+        <div style="padding: 30px 0 0;text-align: center;">
+          <a-button @click="cancel" style="margin-right: 15px" id="chooseCustom-btn-back">取消</a-button>
+          <a-button type="primary" :loading="confirmLoading" @click="handleSubmit" id="chooseCustom-btn-submit">确定</a-button>
+        </div>
+    </a-spin>
+  </a-modal>
+</template>
+
+<script>
+import { commonMixin } from '@/utils/mixin'
+import { salesPromoMatchProduct } from '@/api/salesNew'
+export default {
+  name: 'SetWarehouse',
+  mixins: [commonMixin],
+  props: {
+    show: [Boolean]
+  },
+  data () {
+    return {
+      opened: this.show,
+      spinning: false,
+      title: '确定换促销活动?',
+      confirmLoading: false,
+      upActiveVal: null,
+      radioStyle:"display:block;height: '30px';lineHeight: '30px';padding:5px 0;",
+      activeList: null,
+      editRow: null
+    }
+  },
+  methods: {
+    getActiveList(data, record){
+      this.editRow = record
+      this.spinning = true
+      salesPromoMatchProduct(data).then(res => {
+        this.activeList = res.data
+        this.spinning = false
+      })
+    },
+    //  保存
+    handleSubmit (e) {
+      e.preventDefault()
+      const _this = this
+      if(_this.upActiveVal){
+        _this.$emit('ok', _this.upActiveVal, _this.editRow)
+      }else{
+        _this.$message.info("请选择活动规则!")
+      }
+    },
+    cancel () {
+      this.opened = false
+      this.upActiveVal = null
+      this.$emit('cancel')
+    }
+  },
+  watch: {
+    show (newValue, oldValue) {
+      this.opened = newValue
+      if (!newValue) {
+        this.upActiveVal = null
+      }
+    }
+  }
+}
+</script>

+ 471 - 0
src/views/salesManagement/salesQueryNew/detail.vue

@@ -0,0 +1,471 @@
+<template>
+  <div class="salesDetail-wrap">
+    <a-spin :spinning="spinning" tip="Loading...">
+      <a-page-header :ghost="false" :backIcon="false" class="salesDetail-cont">
+        <template slot="subTitle" v-if="!bizSn">
+          <a id="salesEdit-back-btn" href="javascript:;" @click="handleBack"><a-icon type="left" /> 返回列表</a>
+          <span style="margin: 0 15px;color: #666;font-weight: bold;">单号:{{ detailData&&detailData.salesBillNo }}</span>
+          <span v-if="detailData&&detailData.salesBillNoSource">(原:{{ detailData&&detailData.salesBillNoSource || '--' }})</span>
+          <a-button type="link" class="button-default" @click="showDetail=!showDetail">
+            <a-icon :type="showDetail ? 'eye-invisible' : 'eye'"/> {{ showDetail?'隐藏':'查看' }}信息
+          </a-button>
+        </template>
+        <template slot="extra">
+          <a-button
+            key="1"
+            type="primary"
+            class="button-info"
+            id="salesDetail-xs-print-btn"
+            v-if="$hasPermissions('B_salesPrint')"
+            :disabled="hasData"
+            @click="handlePrint('SALES_BILL','B_salesPrint')">销售打印</a-button>
+          <a-button
+            key="2"
+            type="default"
+            class="button-info"
+            id="salesDetail-xsfl-print-btn"
+            v-if="$hasPermissions('B_salesTypePrint')"
+            :disabled="hasData"
+            @click="handlePrint('SALES_BILL_TYPE','B_salesTypePrint')">销售分类打印</a-button>
+          <a-divider type="vertical" />
+          <a-button
+            key="3"
+            type="primary"
+            class="button-info"
+            id="salesDetail-export-btn"
+            v-if="$hasPermissions('B_salesDetailExport')"
+            :disabled="hasData"
+            @click="handlePrint('export','B_salesDetailExport')">导出Excel</a-button>
+          <a-button
+            key="4"
+            type="default"
+            class="button-info"
+            id="salesDetail-export-btn"
+            v-if="$hasPermissions('B_salesTypeExport')"
+            :disabled="hasData"
+            @click="handlePrint('typeExport','B_salesTypeExport')">销售分类导出</a-button>
+        </template>
+      </a-page-header>
+      <!-- 基础信息 -->
+      <a-card size="small" :bordered="false" class="pages-wrap" style="margin-bottom: 8px;" v-show="showDetail">
+        <div style="padding: 0;">
+          <a-descriptions size="small" :column="3">
+            <a-descriptions-item label="客户名称">{{ detailData&&detailData.buyerName || '--' }}</a-descriptions-item>
+            <a-descriptions-item label="收货地址" :span="2">{{ shippingAddress||'--' }}</a-descriptions-item>
+            <a-descriptions-item label="收货人">{{ detailData&&detailData.salesBillExtEntity&&detailData.salesBillExtEntity.consigneeName || '--' }}</a-descriptions-item>
+            <a-descriptions-item label="收货电话">{{ detailData&&detailData.salesBillExtEntity&&detailData.salesBillExtEntity.consigneeTel || '--' }}</a-descriptions-item>
+            <a-descriptions-item label="收款方式">{{ detailData&&detailData.settleStyleSnDictValue || '--' }}</a-descriptions-item>
+            <a-descriptions-item label="审核时间">{{ detailData&&detailData.auditDate || '--' }}</a-descriptions-item>
+            <a-descriptions-item label="业务状态">{{ detailData&&detailData.billStatusDictValue || '--' }}</a-descriptions-item>
+            <a-descriptions-item label="财务状态">{{ detailData&&detailData.financialStatusDictValue || '--' }}</a-descriptions-item>
+            <a-descriptions-item label="备注" :span="3">{{ detailData&&detailData.remarks || '--' }}</a-descriptions-item>
+          </a-descriptions>
+        </div>
+      </a-card>
+      <a-card size="small" :bordered="false" class="pages-wrap">
+        <!-- alert -->
+        <a-alert type="info" style="margin-bottom: 10px;">
+          <div slot="message">
+            <div>
+              总销售数量:<strong>{{ detailData&&(detailData.totalQty || detailData.totalQty==0) ? detailData.totalQty : '--' }}</strong>;
+              已取消数量:<strong>{{ detailData&&(detailData.totalCancelQty || detailData.totalCancelQty==0) ? detailData.totalCancelQty : '--' }}</strong>;
+              已下推数量:<strong>{{ detailData&&(detailData.totalPushedQty || detailData.totalPushedQty==0) ? detailData.totalPushedQty : '--' }}</strong>;
+              待下推数量:<strong>{{ detailData&&(detailData.totalUnpushedQty || detailData.totalUnpushedQty==0) ? detailData.totalUnpushedQty : '--' }}</strong>;
+              已发货数量:<strong>{{ detailData&&(detailData.totalDispatchQty || detailData.totalDispatchQty==0) ? detailData.totalDispatchQty : '--' }}</strong>;
+              待发货数量:<strong>{{ detailData&&(detailData.totalUndispatchQty || detailData.totalUndispatchQty==0) ? detailData.totalUndispatchQty : '--' }}</strong>;<br/>
+              <span v-if="$hasPermissions(authCode + '_salesPrice')">总售价:<strong>{{ detailData&&(detailData.totalAmount || detailData.totalAmount==0) ? toThousands(detailData.totalAmount) : '--' }}</strong>;</span>
+              <span v-if="$hasPermissions(authCode + '_costPrice')">总成本:<strong>{{ detailData&&(detailData.totalCost || detailData.totalCost==0) ? toThousands(detailData.totalCost) : '--' }}</strong>;</span>
+              <span v-if="$hasPermissions(authCode + '_costPrice')">总毛利:<strong>{{ detailData&&(detailData.grossProfit || detailData.grossProfit==0) ? toThousands(detailData.grossProfit) : '--' }}</strong>;</span>
+              <span v-if="$hasPermissions(authCode + '_salesPrice')">已取消金额:<strong>{{ detailData&&(detailData.totalCancelAmount || detailData.totalCancelAmount==0) ? toThousands(detailData.totalCancelAmount) : '--' }}</strong>;</span>
+              <span v-if="$hasPermissions(authCode + '_salesPrice')">已下推金额:<strong>{{ detailData&&(detailData.totalPushedAmount || detailData.totalPushedAmount==0) ? toThousands(detailData.totalPushedAmount) : '--' }}</strong>;</span>
+              <span v-if="$hasPermissions(authCode + '_salesPrice')">待下推金额:<strong>{{ detailData&&(detailData.totalUnpushedAmount || detailData.totalUnpushedAmount==0) ? toThousands(detailData.totalUnpushedAmount) : '--' }}</strong>;</span>
+              <span v-if="$hasPermissions(authCode + '_salesPrice')">已发货金额:<strong>{{ detailData&&(detailData.totalDispatchAmount || detailData.totalDispatchAmount==0) ? toThousands(detailData.totalDispatchAmount) : '--' }}</strong>;</span>
+              <span v-if="$hasPermissions(authCode + '_salesPrice')">待发货金额:<strong>{{ detailData&&(detailData.totalUndispatchAmount || detailData.totalUndispatchAmount==0) ? toThousands(detailData.totalUndispatchAmount) : '--' }}</strong>;</span>
+              <span v-if="isCityPrice">市级总售价:<strong>{{ detailData&&(detailData.totalCityAmount || detailData.totalCityAmount==0) ? toThousands(detailData.totalCityAmount) : '--' }}</strong>;</span>
+              <span v-if="$hasPermissions(authCode + '_salesPrice')&&detailData&&detailData.totalDiscountAmount" style="color: red;">优惠金额:<strong>{{ Number(detailData.totalDiscountAmount).toFixed(2) }}</strong>;</span>
+            </div>
+          </div>
+        </a-alert>
+        <!-- 查询 -->
+        <div class="table-page-search-wrapper">
+          <div style="display: flex;justify-content: space-between;align-items: center;">
+            <div style="flex-grow: 1;width: 60%;">
+              <a-form layout="inline" @keyup.enter.native="searchTable">
+                <a-row :gutter="15" type="flex">
+                  <a-col flex="350px">
+                    <a-form-item label="出库仓库">
+                      <chooseWarehouse ref="warehouse" v-model="warehouseSn"></chooseWarehouse>
+                    </a-form-item>
+                  </a-col>
+                  <a-col :md="6" :sm="24" style="margin-bottom: 10px;">
+                    <a-button type="primary" @click="searchTable" :disabled="disabled" id="productInfoList-refresh">查询</a-button>
+                    <a-button style="margin-left: 5px" @click="resetSearchForm" id="productInfoList-reset">重置</a-button>
+                  </a-col>
+                </a-row>
+              </a-form>
+            </div>
+            <div>
+              <a-button v-if="detailData && (detailData.billStatus == 'WAIT_AUDIT' || detailData.billStatus == 'HQ_CHANGE')" type="link" @click="openStockOut">缺货明细</a-button>
+              <a-checkbox v-model="isCityPrice" v-if="$hasPermissions(authCode + '_cityPrice')"><span style="display: inline-block;margin-top: 1px;">市级价</span></a-checkbox>
+            </div>
+          </div>
+        </div>
+        <!-- 产品列表 -->
+        <div>
+          <detailProductList 
+          ref="productList" 
+          :detailData="detailData" 
+          :warehouseSn="warehouseSn"
+          :salesBillSn="$route.params.sn || bizSn" 
+          :authCode="authCode"
+          :maxHeight="pageHeight"
+          :showCityPrice="isCityPrice">
+        </detailProductList> 
+        </div>
+      </a-card>
+    </a-spin>
+    <div class="affix-cont">
+      <a-button
+        size="large"
+        style="width: 100px;"
+        :disabled="spinning"
+        type="primary"
+        class="button-info"
+        id="salesDetail-audit-btn"
+        v-if="detailData&&detailData.billStatus == 'WAIT_AUDIT'&&$hasPermissions('B_salesAudit')"
+        @click="handleAudit()"
+      >
+        审核
+      </a-button>
+      <a-button
+        type="default"
+        :disabled="spinning"
+        class="button-info"
+        size="large"
+        style="width: 100px;margin: 0 20px;"
+        id="salesDetail-edit-btn"
+        v-if="detailData&&detailData.salesBillSource != 'PURCHASE' && (detailData.billStatus == 'WAIT_SUBMIT' || detailData.billStatus == 'WAIT_AUDIT' || detailData.billStatus == 'AUDIT_REJECT')&&$hasPermissions('B_salesEdit')"
+        @click="handleEdit()"
+      >
+        编辑
+      </a-button>
+      <a-button
+        size="large"
+        style="width: 100px;margin: 0 20px;"
+        :disabled="spinning"
+        type="default"
+        class="button-info"
+        id="salesDetail-edit-btn"
+        v-if="detailData&&detailData.salesBillSource == 'PURCHASE' && (detailData.billStatus == 'WAIT_AUDIT'||detailData.billStatus == 'HQ_CHANGE')&&$hasPermissions('B_salesEdit')"
+        @click="handleEdit()"
+      >
+        改单
+      </a-button>
+      <a-button
+        size="large"
+        style="width: 100px;"
+        :disabled="spinning"
+        type="primary"
+        class="button-success"
+        id="salesDetail-batchAudit-btn"
+        v-if="detailData&&detailData.billStatus == 'WAIT_AUDIT'&&$hasPermissions('B_salesAudit')"
+        @click="handleAudit('batch')"
+      >
+        一键审核
+      </a-button>
+    </div>
+    <!-- 打印导出 -->
+    <print-modal :openModal="openModal" :itemData="detailData" :nowType="nowType" @ok="handleOk" @close="closePrint" />
+    <!-- 审核 -->
+    <auditModal
+      :openModal="visibleAudit"
+      :content="auditText"
+      :spinning="spinningAudit"
+      @close="visibleAudit=false"
+      @ok="auditOrder('AUDIT_PASS')"
+      @fail="auditOrder('AUDIT_REJECT')" />
+    <!-- 审核加下推 -->
+    <dsModal ref="dsModal" title="销售单一键审核" :openModal="showDsModal" @close="showDsModal=false" @ok="handleOnceAudit" />
+    <!-- 缺货明细 -->
+    <stockOutDetail :openModal="showStockOut" :detailData="detailData" :salesBillSn="$route.params.sn || bizSn" @close="showStockOut=false"></stockOutDetail>
+  </div>
+</template>
+
+<script>
+import { printFun, exportExcel } from '@/libs/JGPrint.js'
+import { commonMixin } from '@/utils/mixin'
+import moment from 'moment'
+import { VSelect } from '@/components'
+import printModal from './printModal.vue'
+import auditModal from '@/views/common/auditModal.vue'
+import dsModal from '@/views/salesManagement/waitDispatchNew/dsModal.vue'
+import stockOutDetail from './stockOutDetailModal.vue'
+import chooseWarehouse from '@/views/common/chooseWarehouse'
+import detailProductList from './comps/detailProductList.vue'
+// 接口
+import { 
+  salesDetailBySn, 
+  salesDetailPrint, 
+  salesDetailExcel, 
+  salesDetailTypeExcel, 
+  salesWriteAuditPass, 
+  salesWriteAuditReject, 
+  salesWriteAuditPush 
+} from '@/api/salesNew'
+ 
+export default {
+  name: 'SalesDetailNew',
+  mixins: [commonMixin],
+  components: { VSelect, printModal, auditModal, dsModal, stockOutDetail, chooseWarehouse, detailProductList },
+  props: {
+    bizSn: { //  有值则为弹框,无值则为页面
+      type: [Number, String],
+      default: ''
+    }
+  },
+  data () {
+    return {
+      spinning: false,
+      disabled: false,
+      showDsModal: false,
+      showStockOut: false,
+      authCode: '',  // 权限码
+      hasData: false, // 是否有数据
+      showDetail: false,
+      openModal: false,
+      detailData: null, //  详情数据
+      nowType: null,
+      isCityPrice: false, //  是否显示市级价
+      visibleAudit: false,
+      auditInfo: null,
+      spinningAudit: false,
+      auditText: null,
+      fromRouter: null,
+      warehouseSn: undefined
+    }
+  },
+  computed: {
+    // 地址
+    shippingAddress () {
+      const shippingAddrProvinceName = this.detailData && this.detailData.salesBillExtEntity && this.detailData.salesBillExtEntity.shippingAddrProvinceName ? this.detailData.salesBillExtEntity.shippingAddrProvinceName : ''
+      const shippingAddrCityName = this.detailData && this.detailData.salesBillExtEntity && this.detailData.salesBillExtEntity.shippingAddrCityName ? this.detailData.salesBillExtEntity.shippingAddrCityName : ''
+      const shippingAddrCountyName = this.detailData && this.detailData.salesBillExtEntity && this.detailData.salesBillExtEntity.shippingAddrCountyName ? this.detailData.salesBillExtEntity.shippingAddrCountyName : ''
+      const shippingAddr = this.detailData && this.detailData.salesBillExtEntity && this.detailData.salesBillExtEntity.shippingAddr ? this.detailData.salesBillExtEntity.shippingAddr : ''
+      if (!shippingAddrProvinceName && !shippingAddrCityName && !shippingAddrCountyName && !shippingAddr) {
+        return '--'
+      } else {
+        return shippingAddrProvinceName + shippingAddrCityName + shippingAddrCountyName + shippingAddr
+      }
+    },
+    pageHeight(){
+      return window.innerHeight - 330
+    }
+  },
+  methods: {
+    //  返回
+    handleBack () {
+      this.$router.push({ name: 'salesQueryNewList' })
+    },
+    // 编辑
+    handleEdit () {
+      const row = this.detailData
+      this.$router.push({ name: 'salesNewEdit', params: { sn: row.salesBillSn, wSn: row.warehouseSn } })
+    },
+    //  重置
+    resetSearchForm () {
+      this.warehouseSn = undefined
+      setTimeout(()=>{
+        this.searchTable()
+      },100)
+    },
+    // 查询数据
+    searchTable(){
+      this.$refs.productList.searchTable()
+    },
+    //  详情
+    getDetail () {
+      salesDetailBySn({ salesBillSn: this.bizSn || this.$route.params.sn }).then(res => {
+        if (res.status == 200) {
+          this.detailData = res.data || null
+          this.detailData.totalDiscountAmount = Number(this.detailData.totalOrigAmount||0) - Number(this.detailData.totalAmount||0)
+        }
+        this.$refs.productList.pageInit()
+      })
+    },
+    // 打开缺货明细
+    openStockOut () {
+      if (this.$refs.productList.outStockStr != '') {
+        this.showStockOut = true
+      } else {
+        this.$info({
+          title: '提示',
+          content: '此销售单暂无缺货产品!',
+          centered: true
+        })
+      }
+    },
+    // 打开审核/一键审核弹框
+    handleAudit (isBatch) {
+      if (isBatch) { // 一键审核
+        if(this.detailData&&this.detailData.promoFlag==1&&this.$refs.productList.outStockStr != ''){
+          this.$info({
+            title: '提示',
+            content: '参加促销活动的销售单,有缺货产品,不可一键审核!',
+            centered: true
+          })
+          return
+        }
+        this.showDsModal = true
+        this.$refs.dsModal.setDetail(this.detailData)
+      } else {
+        this.auditText = null
+        this.visibleAudit = true
+      }
+    },
+    // 一键审核
+    handleOnceAudit (data) {
+      const params = {
+        salesBillSn: this.bizSn || this.$route.params.sn,
+        billStatus: 'AUDIT_PASS',
+        dispatchBill: data
+      }
+      this.spinningAudit = true
+      this.spinning = true
+      salesWriteAuditPush(params).then(res => {
+        if (res.status == 200) {
+          this.$message.success(res.message)
+          //  关闭详情跳列表
+          this.handleBack()
+        }
+        this.spinningAudit = false
+        this.spinning = false
+      })
+    },
+    // 审核
+    auditOrder (billStatus) {
+      this.spinningAudit = true
+      const auditFun = billStatus =='AUDIT_PASS' ? salesWriteAuditPass : salesWriteAuditReject
+      auditFun({
+        salesBillSn: this.bizSn || this.$route.params.sn,
+        billStatus: billStatus
+      }).then(res => {
+        if (res.status == 200) {
+          this.visibleAudit = false
+          this.$message.success(res.message)
+          this.spinningAudit = false
+          const _this = this
+          this.$nextTick(() => {
+            if (billStatus == 'AUDIT_PASS' && !_this.auditText) {
+              _this.$router.push({ name: 'waitDispatchNew', params: { salesBillSn: _this.bizSn || _this.$route.params.sn } })
+            } else {
+              //  关闭详情跳列表
+              _this.handleBack()
+            }
+          })
+        } else {
+          this.visibleAudit = false
+          this.spinningAudit = false
+        }
+      })
+    },
+    // 打印导出
+    handlePrint (type, authCode) {
+      const _this = this
+      _this.$store.state.app.curActionPermission = authCode
+      // 销售分类导出
+      if (type == 'typeExport') {
+        const params = {
+          salesBillSn: this.bizSn || this.$route.params.sn
+        }
+        _this.spinning = true
+        exportExcel(salesDetailTypeExcel, params, '销售分类' + moment().format('YYYYMMDDHHmmss'), () => {
+          _this.spinning = false
+          _this.$store.state.app.curActionPermission = ''
+        })
+      } else {
+        this.detailData.authCode = authCode
+        this.nowType = type
+        this.openModal = true
+      }
+    },
+    closePrint () {
+      console.log(9)
+      this.$store.state.app.curActionPermission = ''
+      this.openModal = false
+    },
+    // 确定打印或预览,导出
+    handleOk (objs) {
+      const _this = this
+      const params = JSON.parse(JSON.stringify(objs))
+      _this.$store.state.app.curActionPermission = this.detailData.authCode
+      delete params.type
+      _this.spinning = true
+      if (this.nowType == 'export') { //  导出
+        exportExcel(salesDetailExcel, params, '销售' + moment().format('YYYYMMDDHHmmss'), () => {
+          _this.spinning = false
+          _this.$store.state.app.curActionPermission = ''
+        })
+      } else { //  打印
+        const taskName = this.nowType == 'SALES_BILL' ? '销售单' : '销售分类'
+        printFun(salesDetailPrint, params, objs.type, taskName, () => {
+          _this.spinning = false
+          _this.$store.state.app.curActionPermission = ''
+        })
+      }
+    }
+  },
+  mounted () {
+    if (!this.$store.state.app.isNewTab || this.bizSn) { // 页签刷新时调用
+      this.getDetail()
+    }
+  },
+  activated () {
+    // 如果是新页签打开或者进入新的子页(例:存在列表第2条数据编辑页页签时再打开第4条数据的编辑页),则重置当前页面
+    if (this.$store.state.app.isNewTab || !this.$store.state.app.isNewSubTab) {
+      this.getDetail()
+    }
+  },
+  beforeRouteEnter (to, from, next) {
+    next(vm => {
+      vm.fromRouter = from
+      vm.authCode = to.meta.permission
+    })
+  }
+}
+</script>
+
+<style lang="less">
+  .salesDetail-wrap{
+    position: relative;
+    height: 100%;
+    padding-bottom: 51px;
+    box-sizing: border-box;
+    >.ant-spin-nested-loading{
+      overflow-y: auto;
+      height: 100%;
+    }
+    .salesDetail-cont{
+      margin-bottom: 10px;
+    }
+    .active-title{
+      display: flex;
+      align-items: center;
+      justify-content: space-between;
+      padding: 10px;
+      background: #f3f8fa;
+    }
+    .flexBox{
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+    }
+    .footer-cont{
+      margin-top: 5px;
+      text-align: center;
+    }
+    .redStyle{
+      font-weight: bold;
+      color: red;
+    }
+  }
+</style>

+ 545 - 0
src/views/salesManagement/salesQueryNew/detailAll.vue

@@ -0,0 +1,545 @@
+<template>
+    <div class="salesDetail-All-wrap">
+      <a-spin :spinning="spinning" tip="Loading...">
+        <a-page-header :ghost="false" :backIcon="false" class="salesDetail-cont">
+          <template slot="subTitle" v-if="!bizSn">
+            <a href="javascript:;" @click="handleBack"><a-icon type="left"></a-icon> 返回列表</a>
+          </template>
+          <template slot="extra">
+            <a-button
+              key="1"
+              type="primary"
+              class="button-info"
+              id="salesDetail-xs-print-btn"
+              v-if="$hasPermissions('B_salesPrint')"
+              :disabled="localDataSource.length==0"
+              @click="handlePrint('SALES_BILL','B_salesPrint')">销售打印</a-button>
+            <a-button
+              key="2"
+              type="default"
+              class="button-info"
+              id="salesDetail-xsfl-print-btn"
+              v-if="$hasPermissions('B_salesTypePrint')"
+              :disabled="localDataSource.length==0"
+              @click="handlePrint('SALES_BILL_TYPE','B_salesTypePrint')">销售分类打印</a-button>
+            <a-divider type="vertical" />
+            <a-button
+              key="3"
+              type="primary"
+              class="button-info"
+              id="salesDetail-export-btn"
+              v-if="$hasPermissions('B_salesDetailExport')"
+              :disabled="localDataSource.length==0"
+              @click="handlePrint('export','B_salesDetailExport')">导出Excel</a-button>
+            <a-button
+              key="4"
+              type="default"
+              class="button-info"
+              id="salesDetail-export-btn"
+              v-if="$hasPermissions('B_salesTypeExport')"
+              :disabled="localDataSource.length==0"
+              @click="handlePrint('typeExport','B_salesTypeExport')">销售分类导出</a-button>
+          </template>
+        </a-page-header>
+        
+        <a-card size="small" :bordered="false" class="pages-wrap">
+         <!-- 基础信息 -->
+         <a-collapse :activeKey="['1']">
+            <a-collapse-panel key="1" header="基础信息">
+              <a-descriptions size="small" :column="3">
+                <a-descriptions-item label="销售单号" :span="2">
+                  {{ detailData&&detailData.salesBillNo || '--' }}
+                  <span v-if="detailData&&detailData.salesBillNoSource">(原:{{ detailData&&detailData.salesBillNoSource || '--' }})</span>
+                </a-descriptions-item>
+                <a-descriptions-item label="客户名称">{{ detailData&&detailData.buyerName || '--' }}</a-descriptions-item>
+                <a-descriptions-item label="收货地址" :span="2">{{ shippingAddress }}</a-descriptions-item>
+                <a-descriptions-item label="收款方式">{{ detailData&&detailData.settleStyleSnDictValue || '--' }}</a-descriptions-item>
+                <a-descriptions-item label="收货人">{{ detailData&&detailData.salesBillExtEntity&&detailData.salesBillExtEntity.consigneeName || '--' }}</a-descriptions-item>
+                <a-descriptions-item label="收货电话">{{ detailData&&detailData.salesBillExtEntity&&detailData.salesBillExtEntity.consigneeTel || '--' }}</a-descriptions-item>
+                <a-descriptions-item label="审核时间">{{ detailData&&detailData.auditDate || '--' }}</a-descriptions-item>
+                <a-descriptions-item label="业务状态">{{ detailData&&detailData.billStatusDictValue || '--' }}</a-descriptions-item>
+                <a-descriptions-item label="财务状态">{{ detailData&&detailData.financialStatusDictValue || '--' }}</a-descriptions-item>
+                <a-descriptions-item label="备注" :span="3">{{ detailData&&detailData.remarks || '--' }}</a-descriptions-item>
+              </a-descriptions>
+            </a-collapse-panel>
+          </a-collapse>
+          <!-- alert -->
+          <a-alert type="info" style="margin: 10px 0;">
+            <div slot="message">
+                <div>
+                  总销售数量:<strong>{{ detailData&&(detailData.totalQty || detailData.totalQty==0) ? detailData.totalQty : '--' }}</strong>;
+                  已取消数量:<strong>{{ detailData&&(detailData.totalCancelQty || detailData.totalCancelQty==0) ? detailData.totalCancelQty : '--' }}</strong>;
+                  已下推数量:<strong>{{ detailData&&(detailData.totalPushedQty || detailData.totalPushedQty==0) ? detailData.totalPushedQty : '--' }}</strong>;
+                  待下推数量:<strong>{{ detailData&&(detailData.totalUnpushedQty || detailData.totalUnpushedQty==0) ? detailData.totalUnpushedQty : '--' }}</strong>;
+                  已发货数量:<strong>{{ detailData&&(detailData.totalDispatchQty || detailData.totalDispatchQty==0) ? detailData.totalDispatchQty : '--' }}</strong>;
+                  待发货数量:<strong>{{ detailData&&(detailData.totalUndispatchQty || detailData.totalUndispatchQty==0) ? detailData.totalUndispatchQty : '--' }}</strong>;<br/>
+                  <span v-if="$hasPermissions(authCode + '_salesPrice')">总售价:<strong>{{ detailData&&(detailData.totalAmount || detailData.totalAmount==0) ? toThousands(detailData.totalAmount) : '--' }}</strong>;</span>
+                  <span v-if="$hasPermissions(authCode + '_costPrice')">总成本:<strong>{{ detailData&&(detailData.totalCost || detailData.totalCost==0) ? toThousands(detailData.totalCost) : '--' }}</strong>;</span>
+                  <span v-if="$hasPermissions(authCode + '_costPrice')">总毛利:<strong>{{ detailData&&(detailData.grossProfit || detailData.grossProfit==0) ? toThousands(detailData.grossProfit) : '--' }}</strong>;</span>
+                  <span v-if="$hasPermissions(authCode + '_salesPrice')">已取消金额:<strong>{{ detailData&&(detailData.totalCancelAmount || detailData.totalCancelAmount==0) ? toThousands(detailData.totalCancelAmount) : '--' }}</strong>;</span>
+                  <span v-if="$hasPermissions(authCode + '_salesPrice')">已下推金额:<strong>{{ detailData&&(detailData.totalPushedAmount || detailData.totalPushedAmount==0) ? toThousands(detailData.totalPushedAmount) : '--' }}</strong>;</span>
+                  <span v-if="$hasPermissions(authCode + '_salesPrice')">待下推金额:<strong>{{ detailData&&(detailData.totalUnpushedAmount || detailData.totalUnpushedAmount==0) ? toThousands(detailData.totalUnpushedAmount) : '--' }}</strong>;</span>
+                  <span v-if="$hasPermissions(authCode + '_salesPrice')">已发货金额:<strong>{{ detailData&&(detailData.totalDispatchAmount || detailData.totalDispatchAmount==0) ? toThousands(detailData.totalDispatchAmount) : '--' }}</strong>;</span>
+                  <span v-if="$hasPermissions(authCode + '_salesPrice')">待发货金额:<strong>{{ detailData&&(detailData.totalUndispatchAmount || detailData.totalUndispatchAmount==0) ? toThousands(detailData.totalUndispatchAmount) : '--' }}</strong>;</span>
+                  <span v-if="isCityPrice">市级总售价:<strong>{{ detailData&&(detailData.totalCityAmount || detailData.totalCityAmount==0) ? toThousands(detailData.totalCityAmount) : '--' }}</strong>;</span>
+                  <span v-if="$hasPermissions(authCode + '_salesPrice')&&detailData&&detailData.totalDiscountAmount" style="color: red;">优惠金额:<strong>{{ toThousands(detailData.totalDiscountAmount) }}</strong>;</span>
+                </div>
+            </div>
+          </a-alert>
+          <!-- 查询 -->
+          <div class="table-page-search-wrapper">
+            <div style="display: flex;justify-content: space-between;align-items: center;">
+            <div style="flex-grow: 1;width: 60%;">
+                <a-form layout="inline" @keyup.enter.native="$refs.table.refresh(true)">
+                <a-row :gutter="15" type="flex">
+                    <a-col :md="6" :sm="24" flex="350px">
+                    <a-form-item label="出库仓库">
+                        <chooseWarehouse ref="warehouse" v-model="queryParam.warehouseSn"></chooseWarehouse>
+                    </a-form-item>
+                    </a-col>
+                    <a-col :md="6" :sm="24" style="margin-bottom: 10px;">
+                    <a-button type="primary" @click="$refs.table.refresh(true)" :disabled="disabled" id="productInfoList-refresh">查询</a-button>
+                    <a-button style="margin-left: 5px" @click="resetSearchForm" id="productInfoList-reset">重置</a-button>
+                    </a-col>
+                </a-row>
+                </a-form>
+            </div>
+            <div>
+                <a-button v-if="detailData && (detailData.billStatus == 'WAIT_AUDIT' || detailData.billStatus == 'HQ_CHANGE')" type="link" @click="openStockOut">缺货明细</a-button>
+                <a-checkbox v-model="isCityPrice" v-if="$hasPermissions(authCode + '_cityPrice')"><span style="display: inline-block;margin-top: 1px;">市级价</span></a-checkbox>
+            </div>
+            </div>
+          </div>
+          <!-- 列表 -->
+          <s-table
+            class="sTable"
+            ref="table"
+            size="small"
+            :rowKey="(record) => record.no"
+            rowKeyName="no"
+            :columns="columns"
+            :data="loadData"
+            :defaultLoadData="false"
+            :showPagination="false"
+            bordered>
+            <!-- 产品编码 -->
+            <template slot="productCode" slot-scope="text, record">
+              <div>
+                <span>{{ text }}</span>
+                <a-badge count="促" v-if="record.promotionFlag=='GIFT'" :number-style="{ backgroundColor: '#52c41a', zoom:'80%' }"></a-badge>
+                <a-badge count="特" v-if="record.promotionFlag=='DISCOUNT'" :number-style="{ backgroundColor: '#faad14', zoom:'80%' }"></a-badge>
+                <!-- 可审核时才可显示“缺”货产品 -->
+                <a-badge count="缺" v-if="(Number(record.stockQty) < Number(record.unpushedQty)) && (detailData&&(detailData.billStatus == 'WAIT_AUDIT'||detailData.billStatus == 'HQ_CHANGE')&&$hasPermissions('B_salesAudit'))">
+                </a-badge>
+              </div>
+            </template>
+            <!-- 当前库存 -->
+            <template slot="stockQty" slot-scope="text, record">
+              <div v-if="record.stockQty || record.stockQty==0">
+                <p style="margin: 0;" v-if="Number(record.stockQty) < Number(record.unpushedQty)">{{ record.stockQty }}(<span class="redStyle">缺{{ Number(record.unpushedQty) - Number(record.stockQty) }}</span>)</p>
+                <p style="margin: 0;" v-else>{{ record.stockQty }}</p>
+              </div>
+              <span v-else>--</span>
+            </template>
+          </s-table>
+        </a-card>
+      </a-spin>
+      <div class="affix-cont">
+        <a-button
+          size="large"
+          style="width: 100px;"
+          :disabled="spinning"
+          type="primary"
+          class="button-info"
+          id="salesDetail-audit-btn"
+          v-if="detailData&&detailData.billStatus == 'WAIT_AUDIT'&&$hasPermissions('B_salesAudit')"
+          @click="handleAudit()"
+        >
+          审核
+        </a-button>
+        <a-button
+          type="default"
+          :disabled="spinning"
+          class="button-info"
+          size="large"
+          style="width: 100px;margin: 0 20px;"
+          id="salesDetail-edit-btn"
+          v-if="detailData&&detailData.salesBillSource != 'PURCHASE' && (detailData.billStatus == 'WAIT_SUBMIT' || detailData.billStatus == 'WAIT_AUDIT' || detailData.billStatus == 'AUDIT_REJECT')&&$hasPermissions('B_salesEdit')"
+          @click="handleEdit()"
+        >
+          编辑
+        </a-button>
+        <a-button
+          size="large"
+          style="width: 100px;margin: 0 20px;"
+          :disabled="spinning"
+          type="default"
+          class="button-info"
+          id="salesDetail-edit-btn"
+          v-if="detailData&&detailData.salesBillSource == 'PURCHASE' && (detailData.billStatus == 'WAIT_AUDIT'||detailData.billStatus == 'HQ_CHANGE')&&$hasPermissions('B_salesEdit')"
+          @click="handleEdit()"
+        >
+          改单
+        </a-button>
+        <a-button
+          size="large"
+          style="width: 100px;"
+          :disabled="spinning"
+          type="primary"
+          class="button-success"
+          id="salesDetail-batchAudit-btn"
+          v-if="detailData&&detailData.billStatus == 'WAIT_AUDIT'&&$hasPermissions('B_salesAudit')"
+          @click="handleAudit('batch')"
+        >
+          一键审核
+        </a-button>
+      </div>
+      <!-- 打印导出 -->
+      <print-modal :openModal="openModal" :itemData="detailData" :nowType="nowType" @ok="handleOk" @close="closePrint" />
+      <!-- 审核 -->
+      <auditModal
+        :openModal="visibleAudit"
+        :content="auditText"
+        :spinning="spinningAudit"
+        @close="visibleAudit=false"
+        @ok="auditOrder('AUDIT_PASS')"
+        @fail="auditOrder('AUDIT_REJECT')" />
+      <!-- 审核加下推 -->
+      <dsModal ref="dsModal" title="销售单一键审核" :openModal="showDsModal" @close="showDsModal=false" @ok="handleOnceAudit" />
+      <!-- 缺货明细 -->
+      <stockOutDetail :openModal="showStockOut" :detailData="detailData" :salesBillSn="$route.params.sn || bizSn" @close="showStockOut=false"></stockOutDetail>
+    </div>
+  </template>
+  
+  <script>
+  import { printFun, exportExcel } from '@/libs/JGPrint.js'
+  import { commonMixin } from '@/utils/mixin'
+  import moment from 'moment'
+  import { STable, VSelect } from '@/components'
+  import printModal from './printModal.vue'
+  import auditModal from '@/views/common/auditModal.vue'
+  import dsModal from '@/views/salesManagement/waitDispatch/dsModal.vue'
+  import stockOutDetail from './stockOutDetailModal.vue'
+  import chooseWarehouse from '@/views/common/chooseWarehouse'
+  import { salesDetailBySn,salesDetailAllList, salesDetailPrint, salesDetailExcel, salesDetailTypeExcel, salesWriteAuditReject, salesWriteAuditPass, salesWriteAuditPush } from '@/api/salesNew'
+  export default {
+    name: 'SalesDetail',
+    mixins: [commonMixin],
+    components: { STable, VSelect, printModal, auditModal, dsModal, stockOutDetail, chooseWarehouse },
+    props: {
+      bizSn: { //  有值则为弹框,无值则为页面
+        type: [Number, String],
+        default: ''
+      }
+    },
+    data () {
+      return {
+        spinning: false,
+        disabled: false,
+        showDsModal: false,
+        showStockOut: false,
+        authCode: '',
+        queryParam: {
+          warehouseSn: undefined
+        },
+        // 加载数据方法 必须为 Promise 对象
+        loadData: parameter => {
+          this.disabled = true
+          this.$store.state.app.curActionPermission = this.authCode
+          const params = Object.assign(parameter, { salesBillSn: this.bizSn || this.$route.params.sn, warehouseSn: this.queryParam.warehouseSn })
+          if (this.detailData && (this.detailData.billStatus == 'WAIT_AUDIT' || this.detailData.billStatus == 'HQ_CHANGE') && this.$hasPermissions('B_salesAudit')) { //  审核,需用到库存
+            params.showStock = true
+          } else { // 非审核
+            params.showStock = false
+          }
+          return salesDetailAllList(params).then(res => {
+            let data
+            if (res.status == 200) {
+              data = res.data
+              const no = 0
+              this.outStockStr = ''
+              let str = ''
+              for (var i = 0; i < data.length; i++) {
+                data[i].no = no + i + 1
+                const productCode = (data[i].productEntity && data[i].productEntity.code) || (data[i].dealerProductEntity && data[i].dealerProductEntity.code)
+                const productName = (data[i].productEntity && data[i].productEntity.name) || (data[i].dealerProductEntity && data[i].dealerProductEntity.name)
+                const productOrigCode = (data[i].productEntity && data[i].productEntity.origCode) || (data[i].dealerProductEntity && data[i].dealerProductEntity.origCode)
+                const productOrigUnit = (data[i].productEntity && data[i].productEntity.unit) || (data[i].dealerProductEntity && data[i].dealerProductEntity.unit)
+                data[i].productCode = productCode || '--'
+                data[i].productName = productName || '--'
+                data[i].productOrigCode = productOrigCode == ' ' ? '--' : productOrigCode
+                data[i].productOrigUnit = productOrigUnit || '--'
+                if (data[i].unpushedQty && (Number(data[i].stockQty) < Number(data[i].unpushedQty))) {
+                  str += data[i].productCode + '、'
+                }
+              }
+              if (str.length > 0) {
+                str = str.substr(0, str.length - 1)
+                this.outStockStr = '产品编号为:' + str + '的产品库存不足;'
+              }
+              this.localDataSource = data
+              this.disabled = false
+            }
+            return data
+          })
+        },
+        localDataSource: [],
+        openModal: false,
+        detailData: null, //  详情数据
+        nowType: null,
+        isCityPrice: false, //  是否显示市级价
+        visibleAudit: false,
+        auditInfo: null,
+        spinningAudit: false,
+        outStockStr: '', // 缺货产品信息说明
+        auditText: null,
+        authCode: ""
+      }
+    },
+    computed: {
+      shippingAddress () {
+        const shippingAddrProvinceName = this.detailData && this.detailData.salesBillExtEntity && this.detailData.salesBillExtEntity.shippingAddrProvinceName ? this.detailData.salesBillExtEntity.shippingAddrProvinceName : ''
+        const shippingAddrCityName = this.detailData && this.detailData.salesBillExtEntity && this.detailData.salesBillExtEntity.shippingAddrCityName ? this.detailData.salesBillExtEntity.shippingAddrCityName : ''
+        const shippingAddrCountyName = this.detailData && this.detailData.salesBillExtEntity && this.detailData.salesBillExtEntity.shippingAddrCountyName ? this.detailData.salesBillExtEntity.shippingAddrCountyName : ''
+        const shippingAddr = this.detailData && this.detailData.salesBillExtEntity && this.detailData.salesBillExtEntity.shippingAddr ? this.detailData.salesBillExtEntity.shippingAddr : ''
+        if (!shippingAddrProvinceName && !shippingAddrCityName && !shippingAddrCountyName && !shippingAddr) {
+          return '--'
+        } else {
+          return shippingAddrProvinceName + shippingAddrCityName + shippingAddrCountyName + shippingAddr
+        }
+      },
+      columns () {
+        const _this = this
+        const arr = [
+          { title: '序号', dataIndex: 'no', width: '4%', align: 'center' },
+          { title: '产品编码', dataIndex: 'productCode', width: '13%', scopedSlots: { customRender: 'productCode' }, align: 'center' },
+          { title: '产品名称', dataIndex: 'productName', width: '15%', align: 'center', customRender: function (text) { return text || '--' }, ellipsis: true },
+          { title: '原厂编码', dataIndex: 'productOrigCode', width: '10%', align: 'center', customRender: function (text) { return text || '--' } },
+          { title: '出库仓库', dataIndex: 'warehouseName', width: '10%', align: 'center', customRender: function (text) { return text || '--' }, ellipsis: true },
+          // { title: '成本价', dataIndex: 'showCost', width: '6%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
+          // { title: '省级价', dataIndex: 'provincePrice', width: '6%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
+          // { title: '市级价', dataIndex: 'cityPrice', width: '6%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
+          // { title: '销售价', dataIndex: 'price', width: '6%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
+          { title: '单位', dataIndex: 'productOrigUnit', width: '4%', align: 'center', customRender: function (text) { return text || '--' } },
+          { title: '销售数量', dataIndex: 'qty', width: '6%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
+          // { title: '库存', dataIndex: 'stockQty', scopedSlots: { customRender: 'stockQty' }, width: '6%', align: 'center' },
+          { title: '待下推数', dataIndex: 'unpushedQty', width: '6%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
+          { title: '已下推数', dataIndex: 'pushedQty', width: '6%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
+          { title: '已取消数', dataIndex: 'cancelQty', width: '6%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } }
+        ]
+        if (this.$hasPermissions(this.authCode + '_costPrice')) { //  成本价权限
+          arr.splice(5, 0, { title: '成本价', dataIndex: 'showCost', width: '6%', align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } })
+        }
+  
+        const ind = this.$hasPermissions(this.authCode + '_costPrice') ? 6 : 5
+        if (this.$hasPermissions(this.authCode + '_provincePrice')) {
+          arr.splice(ind, 0, { title: '省级价', dataIndex: 'provincePrice', width: '6%', align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } })
+        }
+        // 是否勾选市级价格
+        if (this.isCityPrice) {
+          arr.splice(ind + 1, 0, { title: '市级价', dataIndex: 'cityPrice', width: '6%', align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } })
+          if (this.$hasPermissions(this.authCode + '_salesPrice')) { //  售价权限
+            arr.splice(ind + 2, 0, { title: '销售价', dataIndex: 'price', width: '6%', align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } })
+          }
+        } else {
+          if (this.$hasPermissions(this.authCode + '_salesPrice')) { //  售价权限
+            arr.splice(ind + 1, 0, { title: '销售价', dataIndex: 'price', width: '6%', align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } })
+          }
+        }
+  
+        if (this.detailData && (this.detailData.billStatus == 'WAIT_AUDIT' || this.detailData.billStatus == 'HQ_CHANGE') && this.$hasPermissions('B_salesAudit')) { //  审核,需用到库存
+          arr.splice(arr.length - 3, 0, { title: '库存', dataIndex: 'stockQty', scopedSlots: { customRender: 'stockQty' }, width: '6%', align: 'center' })
+        }
+        return arr
+      }
+    },
+    methods: {
+      //  返回
+      handleBack () {
+        this.$router.push({ name: 'salesQueryList' })
+      },
+      // 编辑
+      handleEdit () {
+        const row = this.detailData
+        this.$router.push({ name: 'salesEdit', params: { sn: row.salesBillSn, wSn: row.warehouseSn } })
+      },
+      //  重置
+      resetSearchForm () {
+        this.queryParam.warehouseSn = undefined
+        this.$refs.table.refresh()
+      },
+      // 打开缺货明细
+      openStockOut () {
+        if (this.outStockStr != '') {
+          this.showStockOut = true
+        } else {
+          this.$info({
+            title: '提示',
+            content: '此销售单暂无缺货产品!',
+            centered: true
+          })
+        }
+      },
+      //  详情
+      getDetail () {
+        salesDetailBySn({ salesBillSn: this.bizSn || this.$route.params.sn }).then(res => {
+          if (res.status == 200) {
+            this.detailData = res.data || null
+            this.detailData.totalDiscountAmount = Number(this.detailData.totalOrigAmount||0) - Number(this.detailData.totalAmount||0)
+            this.$refs.table.refresh(true)
+          } else {
+            this.detailData = null
+          }
+        })
+      },
+      // 打开审核/一键审核弹框
+      handleAudit (isBatch) {
+        if (isBatch) { // 一键审核
+          if(this.detailData&&this.detailData.promoFlag==1&&this.outStockStr != ''){
+            this.$info({
+                title: '提示',
+                content: '参加促销活动的销售单,有缺货产品,不可一键审核!',
+                centered: true
+            })
+            return
+          }
+          this.showDsModal = true
+          this.$refs.dsModal.setDetail(this.detailData)
+        } else {
+          this.auditText = null
+          this.visibleAudit = true
+        }
+      },
+      // 一键审核
+      handleOnceAudit (data) {
+        const params = {
+          salesBillSn: this.bizSn || this.$route.params.sn,
+          billStatus: 'AUDIT_PASS',
+          dispatchBill: data
+        }
+        this.spinningAudit = true
+        this.spinning = true
+        salesWriteAuditPush(params).then(res => {
+          if (res.status == 200) {
+            this.$message.success(res.message)
+            //  关闭详情跳列表
+            this.handleBack()
+          }
+          this.spinningAudit = false
+          this.spinning = false
+        })
+      },
+    // 审核
+    auditOrder (billStatus) {
+        this.spinningAudit = true
+        const auditFun = billStatus =='AUDIT_PASS' ? salesWriteAuditPass : salesWriteAuditReject
+        auditFun({
+            salesBillSn: this.bizSn || this.$route.params.sn,
+            billStatus: billStatus
+        }).then(res => {
+            if (res.status == 200) {
+            this.visibleAudit = false
+            this.$message.success(res.message)
+            this.spinningAudit = false
+            const _this = this
+            this.$nextTick(() => {
+                if (billStatus == 'AUDIT_PASS' && !_this.auditText) {
+                _this.$router.push({ name: 'waitDispatchNew', params: { salesBillSn: _this.bizSn || _this.$route.params.sn } })
+                } else {
+                //  关闭详情跳列表
+                _this.handleBack()
+                }
+            })
+            } else {
+            this.visibleAudit = false
+            this.spinningAudit = false
+            }
+        })
+     },
+      // 打印导出
+      handlePrint (type, authCode) {
+        const _this = this
+        _this.$store.state.app.curActionPermission = authCode
+        // 销售分类导出
+        if (type == 'typeExport') {
+          const params = {
+            salesBillSn: this.bizSn || this.$route.params.sn
+          }
+          _this.spinning = true
+          exportExcel(salesDetailTypeExcel, params, '销售分类' + moment().format('YYYYMMDDHHmmss'), () => {
+            _this.spinning = false
+            _this.$store.state.app.curActionPermission = ''
+          })
+        } else {
+          this.detailData.authCode = authCode
+          this.nowType = type
+          this.openModal = true
+        }
+      },
+      closePrint () {
+        console.log(9)
+        this.$store.state.app.curActionPermission = ''
+        this.openModal = false
+      },
+      // 确定打印或预览,导出
+      handleOk (objs) {
+        const _this = this
+        const params = JSON.parse(JSON.stringify(objs))
+        _this.$store.state.app.curActionPermission = this.detailData.authCode
+        delete params.type
+        _this.spinning = true
+        if (this.nowType == 'export') { //  导出
+          exportExcel(salesDetailExcel, params, '销售' + moment().format('YYYYMMDDHHmmss'), () => {
+            _this.spinning = false
+            _this.$store.state.app.curActionPermission = ''
+          })
+        } else { //  打印
+          const taskName = this.nowType == 'SALES_BILL' ? '销售单' : '销售分类'
+          printFun(salesDetailPrint, params, objs.type, taskName, () => {
+            _this.spinning = false
+            _this.$store.state.app.curActionPermission = ''
+          })
+        }
+      }
+    },
+    mounted () {
+      if (!this.$store.state.app.isNewTab || this.bizSn) { // 页签刷新时调用
+        this.getDetail()
+      }
+    },
+    activated () {
+      // 如果是新页签打开或者进入新的子页(例:存在列表第2条数据编辑页页签时再打开第4条数据的编辑页),则重置当前页面
+      if (this.$store.state.app.isNewTab || !this.$store.state.app.isNewSubTab) {
+        this.getDetail()
+      }
+    }
+  }
+  </script>
+  
+  <style lang="less">
+    .salesDetail-All-wrap{
+      position: relative;
+      height: 100%;
+      padding-bottom: 51px;
+      box-sizing: border-box;
+      >.ant-spin-nested-loading{
+        overflow-y: auto;
+        height: 100%;
+      }
+      
+      .flexBox{
+        display: flex;
+        justify-content: space-between;
+        align-items: center;
+      }
+      .footer-cont{
+        margin-top: 5px;
+        text-align: center;
+      }
+      .redStyle{
+        font-weight: bold;
+        color: red;
+      }
+    }
+  </style>
+  

+ 691 - 0
src/views/salesManagement/salesQueryNew/edit.vue

@@ -0,0 +1,691 @@
+<template>
+  <div class="salesNewEdit-wrap">
+    <a-spin :spinning="spinning" tip="Loading...">
+      <a-page-header :ghost="false" :backIcon="false" @back="handleBack" >
+        <!-- 自定义的二级文字标题 -->
+        <template slot="subTitle">
+          <a id="salesEdit-back-btn" href="javascript:;" @click="handleBack"><a-icon type="left" /> 返回列表</a>
+          <span style="margin: 0 15px;color: #666;font-weight: bold;">单号:{{ detailData&&detailData.salesBillNo }}</span>
+          <span v-if="detailData&&detailData.salesBillNoSource">(原:{{ detailData&&detailData.salesBillNoSource || '--' }})</span>
+          <a-button type="link" class="button-default" @click="showDetail=!showDetail">
+            <a-icon :type="showDetail ? 'eye-invisible' : 'eye'"/> {{ showDetail?'隐藏':'查看' }}信息
+          </a-button>
+        </template>
+      </a-page-header>
+      <!-- 单据详情 -->
+      <a-card size="small" :bordered="false" class="salesEdit-cont" v-show="showDetail">
+        <div style="padding: 10px;">
+          <a-descriptions size="small" :column="3">
+            <a-descriptions-item label="客户名称">{{ detailData&&detailData.buyerName || '--' }}</a-descriptions-item>
+            <a-descriptions-item label="收货地址" :span="2">{{ shippingAddress||'--' }}</a-descriptions-item>
+            <a-descriptions-item label="收货人">{{ detailData&&detailData.salesBillExtEntity&&detailData.salesBillExtEntity.consigneeName || '--' }}</a-descriptions-item>
+            <a-descriptions-item label="收货电话">{{ detailData&&detailData.salesBillExtEntity&&detailData.salesBillExtEntity.consigneeTel || '--' }}</a-descriptions-item>
+            <a-descriptions-item label="收款方式">{{ detailData&&detailData.settleStyleSnDictValue || '--' }}</a-descriptions-item>
+            <a-descriptions-item label="审核时间">{{ detailData&&detailData.auditDate || '--' }}</a-descriptions-item>
+            <a-descriptions-item label="业务状态">{{ detailData&&detailData.billStatusDictValue || '--' }}</a-descriptions-item>
+            <a-descriptions-item label="财务状态">{{ detailData&&detailData.financialStatusDictValue || '--' }}</a-descriptions-item>
+            <a-descriptions-item label="备注" :span="3">{{ detailData&&detailData.remarks || '--' }}</a-descriptions-item>
+          </a-descriptions>
+        </div>
+      </a-card>
+      <!-- 正常产品 -->
+      <a-card size="small" :bordered="false" class="salesEdit-cont" v-if="salesBillSn">
+        <div style="padding: 10px;">
+          <productNormalList 
+          ref="productNormalList" 
+          @insterOk="insterActiveOk"
+          @openCpModal="openProductModal" 
+          :showTotal="showTotal"
+          :detailData="detailData" 
+          :warehouseSn="warehouseSn" 
+          :salesBillSn="salesBillSn"></productNormalList>
+        </div>
+      </a-card>
+      <!-- 活动产品 -->
+      <a-card 
+      size="small" 
+      :bordered="false" 
+      class="salesEdit-cont" 
+      v-for="item in activeList" 
+      :key="item.promoRuleSn" 
+      v-if="activeList.length"
+      >
+        <div slot="title" style="display: inline-block;width:100%;">
+          <strong style="margin-right:10px;font-size:14px;">{{item.promotion.description}}</strong> ({{item.promotionRule.description}})
+          <span style="margin-left:20px;color:#00aaff;cursor: pointer;"  @click="(event) => {showDesc(event, item)}">
+            <a-icon :type="item.showDesc ? 'eye-invisible' : 'eye'"/> 活动详情
+          </span>
+          <span :style="{margin:'0 20px',color:item.disabled?'#14b900':'#ff0800',cursor: 'pointer'}" @click="(event) => {disenablePromp(event, item)}">
+            <a-icon title="禁用规则" :type="item.disabled?'link':'disconnect'"/> {{item.disabled ? '启用规则' : '禁用规则'}}
+          </span>
+        </div>
+        <div slot="extra" @click="tooglePanel(item)" style="cursor: pointer;">{{ item.isActive ? '收起' : '展开' }} <a-icon type="caret-right" :rotate="item.isActive ? 90 : 0"/> </div>
+        <div v-show="item.isActive" style="padding: 10px;">
+          <productList 
+          :ref="'productList-'+item.promoRuleSn" 
+          :id="item.promoRuleSn" 
+          @openCpModal="openProductModal" 
+          @insterOk="insterActiveOk"
+          @showDesc="v => showDescOk(v,item)"
+          @upActive="upActive"
+          :promo="item"
+          :detailData="detailData" 
+          :warehouseSn="warehouseSn" 
+          :salesBillSn="salesBillSn"></productList>
+        </div>
+      </a-card>
+    </a-spin>
+    <div class="affix-cont">
+      <div class="footer-price">
+        <div></div>
+        <div v-if="detailData">
+          <div class="totalPrice">总售价:¥<span>{{ toThousands(detailData.totalAmount) }}</span></div>
+          <div>
+            产品总款数:<strong style="margin-right: 10px;"> {{ detailData.totalCategory }} </strong>
+            总数量:<strong style="margin-right: 10px;"> {{ detailData.totalQty }} </strong>
+            <!-- 总售价:¥<strong> {{ toThousands(detailData.totalOrigAmount) }}</strong> -->
+            <span style="margin:0 10px;" v-if="detailData.totalDiscountAmount">优惠金额:¥-<strong>{{ Number(detailData.totalDiscountAmount).toFixed(2) }}</strong></span>
+            <a-popover title="优惠明细" @visibleChange="(visible)=>{visible&&getPromYhDetail()}">
+              <a-button shape="round" size="small" v-if="detailData.totalDiscountAmount">优惠明细</a-button>
+              <div slot="content">
+                <div v-if="yhDetail">
+                    <div 
+                    class="yhdetail" 
+                    style="min-width:300px;margin-bottom: 5px;" 
+                    v-for="(item,index) in yhDetail.promoMapList" 
+                    :key="index">
+                      <div class="yhdetail-h" style="font-weight: bold;font-size:14px;">{{ item.description }}</div>
+                      <div style="padding-left:10px;" 
+                      v-for="(sitem,sindex) in item.promoRuleMapList" 
+                      :key="sindex" 
+                      v-if="sitem.lossAmount"
+                      >
+                        <div style="display: flex;justify-content: space-between;">
+                          <span>{{sitem.promotionRuleTypeDictValue}}:</span>
+                          <strong>¥{{ toThousands(sitem.lossAmount) }}</strong>
+                        </div>
+                        <div class="yhdetail-d" style="color:#999;">{{ sitem.description }}</div>
+                      </div>
+                    </div>
+                    <div class="yhdetail" style="display: flex;justify-content: space-between;">
+                      <span style="font-weight: bold;font-size:14px;">优惠金额:</span>
+                      <span style="font-weight: bold;font-size:18px;">¥{{ Number(yhDetail.totalLossAmount).toFixed(2) }}</span>
+                    </div>
+                </div>
+                <div style="text-align: center;padding: 20px;" v-else>
+                   正在加载...
+                </div>
+              </div>
+            </a-popover>
+          </div>
+        </div>
+      </div>
+      <div>
+        <a-button
+          size="large"
+          style="padding: 0 60px;"
+          :disabled="spinning"
+          type="primary"
+          class="button-primary"
+          @click="handleSubmit()"
+          id="productInfoList-handleSubmit">提交</a-button>
+      </div>
+    </div>
+    <!-- 添加产品 -->
+    <chooseProduct
+    ref="chooseProduct"
+    :openModal="showCpModal"
+    @close="closeProductModal"
+    @addProduct="insterProduct"></chooseProduct>
+    <!-- 价格更新弹窗 -->
+    <setPriceModal 
+    :show="priceUpdateModal" 
+    :totalRealAmount="updataData.totalRealAmount" 
+    :totalAmount="updataData.totalAmount" 
+    @ok="updatePrice" 
+    @cancel="priceUpdateModal=false"></setPriceModal>
+    <!-- 新活动窗口 -->
+    <newPromoModal
+    :show="showNewActiveModal"
+    :salesBillSn="salesBillSn"
+    :newActiveList="newActiveList"
+    @ok="showNewActiveOk"
+    ></newPromoModal>
+ </div>
+</template>
+
+<script>
+import { commonMixin } from '@/utils/mixin'
+import productList from './comps/productList.vue'
+import productNormalList from './comps/productNormalList.vue'
+import chooseProduct from './comps/chooseProduct.vue'
+import setPriceModal from './setPriceModal.vue'
+import newPromoModal from './newPromoModal.vue'
+import { salesDisablePromo,salesEnablePromoPromo, salesChangePromo } from '@/api/salesDetailNew'
+import { salesDetailBySn,salesPromoQueryCount, salesWriteSubmit, submitCheck, updateBatch, salesPromoQueryList, salesQueryUnPartPromo,salesPromoValidaSubmit } from '@/api/salesNew'
+export default {
+  name: 'SalesNewEdit',
+  mixins: [commonMixin],
+  components:{
+    setPriceModal,
+    productList,
+    chooseProduct,
+    productNormalList,
+    newPromoModal
+  },
+  data () {
+    return {
+      spinning: false,
+      activeList:[], // 活动列表
+      newActiveList: [], // 新活动列表
+      activeDesKey: {},
+      salesBillSn: null, // 销售单sn
+      detailData: { discountAmount: 0, id: null, salesBillSn: '' }, // 订单基础数据
+      warehouseSn: undefined,
+      updataData: {
+        totalRealAmount: '',
+        totalAmount: ''
+      },
+      priceUpdateModal: false, // 价格更新弹窗
+      showDetail: false,
+      showCpModal: false,
+      cpCurRefId: '',
+      disabledActiveOption: null,
+      yhDetail: null,
+      showNewActiveModal: false
+    }
+  },
+  computed: {
+    showTotal(){
+      return this.activeList.length > 0
+    },
+    shippingAddress () {
+      const shippingAddrProvinceName = this.detailData && this.detailData.salesBillExtEntity && this.detailData.salesBillExtEntity.shippingAddrProvinceName ? this.detailData.salesBillExtEntity.shippingAddrProvinceName : ''
+      const shippingAddrCityName = this.detailData && this.detailData.salesBillExtEntity && this.detailData.salesBillExtEntity.shippingAddrCityName ? this.detailData.salesBillExtEntity.shippingAddrCityName : ''
+      const shippingAddrCountyName = this.detailData && this.detailData.salesBillExtEntity && this.detailData.salesBillExtEntity.shippingAddrCountyName ? this.detailData.salesBillExtEntity.shippingAddrCountyName : ''
+      const shippingAddr = this.detailData && this.detailData.salesBillExtEntity && this.detailData.salesBillExtEntity.shippingAddr ? this.detailData.salesBillExtEntity.shippingAddr : ''
+      if (!shippingAddrProvinceName && !shippingAddrCityName && !shippingAddrCountyName && !shippingAddr) {
+        return '--'
+      } else {
+        return shippingAddrProvinceName + shippingAddrCityName + shippingAddrCountyName + shippingAddr
+      }
+    }
+  },
+  methods: {
+    //  返回
+    handleBack () {
+      this.$router.push({ name: 'salesQueryNewList', query: { closeLastOldTab: true } })
+    },
+    tooglePanel(item){
+      item.isActive=!item.isActive
+      this.activeList.splice()
+      // 刷新当前表格
+      if(item.isActive){
+        const row = this.$refs['productList-'+item.promoRuleSn][0]
+        row&&row.resetSearchForm()
+      }
+    },
+    //  销售单详情
+    getOrderDetail (flag) {
+      salesDetailBySn({ salesBillSn: this.$route.params.sn }).then(res => {
+        if (res.status == 200) {
+          this.detailData = res.data
+          this.detailData.totalDiscountAmount = Number(this.detailData.totalOrigAmount||0) - Number(this.detailData.totalAmount||0)
+        }
+        if(flag){
+          this.getActiveList()
+        }
+      })
+    },
+    // 优惠明细查看
+    getPromYhDetail(){
+      salesPromoQueryCount({salesBillSn: this.$route.params.sn }).then(res => {
+        if (res.status == 200) {
+          this.yhDetail = res.data
+        }
+      })
+    },
+    // 判断是否全部调用完
+    isAllLoadFinish(mlist){
+      const nid = setInterval(()=>{
+        const ret = []
+        mlist.map(item => {
+          const da = item.disabled
+          ret.push(da)
+        })
+        // 加载完了
+        if(!ret.includes(true)){
+          clearInterval(nid)
+          this.spinning = false
+        }
+        console.log(ret)
+      }, 50)
+    },
+    // 刷新所有表格数据
+    updateAllTable(flag){
+      const activeList = this.activeList.filter(item=>item.isActive)
+      const mlist = []
+      this.spinning = true
+      // 加载正常产品列表
+      this.$refs.productNormalList.resetSearchForm()
+      mlist.push(this.$refs.productNormalList)
+      // 刷新所有活动产品列表
+      activeList.map(item => {
+        const row = this.$refs['productList-' + item.promoRuleSn][0]
+        row&&row.resetSearchForm()
+        mlist.push(row)
+      })
+
+      // 判断是否全部调用完
+      this.isAllLoadFinish(mlist)
+
+      // 是否刷新详情
+      if(flag){
+        this.getOrderDetail()
+      }
+    },
+    // 获取销售单参与的活动列表
+    async getActiveList(){
+      // 已参与活动列表
+      this.activeList = await salesPromoQueryList({ salesBillSn: this.$route.params.sn }).then(res => res.data || [])
+      this.activeList.map(item => {
+        item.isActive = item.enabledFlag == 1
+        item.showDesc = false
+        item.disabled = item.enabledFlag == 0
+        this.activeDesKey['search-'+item.promoRuleSn] = false
+      })
+      
+      setTimeout(()=> {
+        this.updateAllTable()
+      }, 500)
+    },
+    // 获取是否有新活动
+    async getNewActive(){
+      const hasNewActive = await salesQueryUnPartPromo({ salesBillSn: this.$route.params.sn, enabledFlag: "1" }).then(res => res.data)
+      if(hasNewActive.length){
+        this.newActiveList = hasNewActive
+        this.showNewActiveModal=true
+      }
+    },
+    showNewActiveOk(){
+      this.showNewActiveModal = false
+      this.getOrderDetail(true)
+    },
+    // 添加产品,包括正常和活动的产品
+    closeProductModal(type){
+        this.cpCurRefId = ''
+        this.showCpModal = false
+        // 刷新表格
+        // this.insterActiveOk(['normal','promo'][type])
+    },
+    // 打开选择产品弹框
+    openProductModal(type, refId){
+        console.log(type, refId)
+        const promo = this.activeList.find(item => item.promoRuleSn == refId)
+        this.$refs.chooseProduct.pageInit(this.detailData, promo, type)
+        this.cpCurRefId = 'productList-' + refId
+        this.showCpModal = true
+    },
+    // 添加活动产品成功的回调
+    insterActiveOk(type){
+      console.log(type)
+      const mlist = []
+      this.spinning = true
+      if(type == 'promo'){
+        // 刷新正常产品列表
+        this.$refs.productNormalList.resetSearchForm()
+        mlist.push(this.$refs.productNormalList)
+      }
+      if(type == 'normal'){
+        // 刷新活动产品列表
+        const activeList = this.activeList.filter(item=>item.isActive)
+        activeList.map(item => {
+          const row = this.$refs['productList-' + item.promoRuleSn][0]
+          row&&row.resetSearchForm()
+          mlist.push(row)
+        })
+      }
+      // 判断是否全部调用完
+      this.isAllLoadFinish(mlist)
+      this.getOrderDetail()
+    },
+    // 新增产品
+    insterProduct(row, promotionFlag, type){
+      // 正常产品
+      if(type == 0){
+        this.$refs.productNormalList.insterProduct(row, promotionFlag)
+      }else{
+        // 活动产品
+        this.$refs[this.cpCurRefId][0].insterProduct(row, promotionFlag, type)
+      }
+    },
+    // 更换活动
+    upActive(oldPromo,data,params){
+      const promo = data.split('-')
+      const newSn = this.activeList.find(item => item.promoRuleSn == promo[1])
+      const newSalesPromoSn = newSn && newSn.salesPromoSn || ''
+      salesChangePromo({
+        salesPromoSn: data != 0 ? newSalesPromoSn : '',
+        promoRuleSn: promo[1],
+        promotionFlag: promo[2]||'',
+        ...params
+      }).then(res => {
+        if(res.status == 200){
+          const mlist = []
+          this.spinning = true
+          // 刷新新参与活动
+          if(data != 0){
+            const nt = this.$refs['productList-'+promo[1]][0]
+            nt&&nt.resetSearchForm()
+            mlist.push(nt)
+          }
+          // 刷新正常活动
+          const pnt = this.$refs.productNormalList
+          pnt&&pnt.resetSearchForm()
+          mlist.push(pnt)
+          // 刷新当前活动
+          const ot = this.$refs['productList-'+oldPromo.promoRuleSn][0]
+          ot&&ot.upAcitveSuccess()
+          mlist.push(ot)
+
+          // 判断是否全部调用完
+          this.isAllLoadFinish(mlist)
+
+          // 刷新详情统计
+          this.getOrderDetail()
+        }
+      })
+    },
+    // 选择价格类型  并更新
+    updatePrice (type) {
+      const ajax_data = {
+        salesBillSn: this.salesBillSn,
+        productPriceChangeFlag: type
+      }
+      if (type == 0) {
+        this.submitResult(ajax_data)
+      } else {
+        updateBatch(this.updataData.detailList).then(res => {
+          if (res.status == 200) {
+            this.submitResult(ajax_data)
+          }
+        })
+      }
+    },
+    // 提交销售单
+    handleSubmit () {
+      // 先不提交,先判断是否有价格更新  (下级创建时判断)
+      if (this.detailData&&this.detailData.salesBillSource == 'PURCHASE') {
+        submitCheck({ salesBillSn: this.salesBillSn }).then(res => {
+          if (res.status == 200) {
+            if (res.data.detailList.length > 0) {
+              this.updataData = res.data
+              this.$nextTick(() => {
+                this.priceUpdateModal = true
+              })
+            } else {
+              this.submitResult({ salesBillSn: this.salesBillSn })
+            }
+          }
+        })
+      } else {
+        this.submitResult({ salesBillSn: this.salesBillSn })
+      }
+    },
+    // 提交销售单
+    async submitResult (data) {
+      const _this = this
+      // 校验活动规则
+      const vaildActive = await salesPromoValidaSubmit({salesBillSn: this.salesBillSn}).then(res => res.data)
+      // console.log(vaildActive)
+      const a = vaildActive.filter(item => item.type == 1) // 不可提交
+      const b = vaildActive.filter(item => item.type == 0) // 可跳过继续提交
+      // 弹出不符合规则弹框,不可提交
+      if(a.length){
+        this.$info({
+          title: '提示',
+          centered: true,
+          class:'confirm-center',
+          okText:'关闭',
+          width: 600,
+          content: <div style="padding-top:15px;">
+            <ol>
+            {a.map(item => (
+              <li style="padding:3px 0;">{item.message}</li>
+            ))}
+            </ol>
+            <div style="padding:10px 0;text-align:center"><strong>请按照以上提示修改后再提交</strong></div>
+          </div>
+        });
+      }else{
+        // 弹出确认提示信息,可跳过继续提交
+        if(b.length){
+          this.$confirm({
+            title: '提示',
+            centered: true,
+            class:'confirm-center',
+            okText:'提交',
+            width: 600,
+            content: <div style="padding-top:15px;">
+              <ol>
+              {b.map(item => (
+                <li style="padding:3px 0;">{item.message}</li>
+              ))}
+              </ol>
+            </div>,
+            onOk() {
+              _this.submitOrder(data)
+            }
+          });
+        }else{
+          _this.submitOrder(data)
+        }
+      }
+    },
+    async submitOrder(data){
+      this.spinning = true
+      const res = await salesWriteSubmit(data)
+      if (res.status == 200) {
+        this.handleBack()
+        this.$message.success(res.message)
+      }
+      this.spinning = false
+    },
+    // 展开收缩活动详情
+    showDesc(e,item){
+      e.stopPropagation()
+      const row = this.$refs['productList-'+item.promoRuleSn][0]
+      row&&row.showDesc(item.promotionRule)
+    },
+    showDescOk(v,item){
+      item.showDesc = v
+      if(!item.isActive){
+        const row = this.$refs['productList-'+item.promoRuleSn][0]
+        row&&row.resetSearchForm()
+        item.isActive = true
+      }
+      this.activeList.splice()
+    },
+    // 启用规则
+    enabledActive(e,item){
+      const _this = this
+      this.spinning = true
+      salesEnablePromoPromo({
+        salesBillSn: _this.salesBillSn,
+        salesPromoSn: item.salesPromoSn
+      }).then(res => {
+        if(res.status == 200){
+          item.disabled = false
+          item.isActive = true
+          _this.activeList.splice()
+          // 禁用按钮
+          _this.$refs['productList-'+item.promoRuleSn][0].disableActive(false)
+
+          // 刷新所有表格
+          _this.updateAllTable(true)
+          
+          _this.spinning = false
+          _this.$message.success("操作成功,请添加产品")
+        }
+      })
+    },
+    // 禁用规则
+    disabledActive(e,item){
+      const _this = this
+      _this.spinning = true
+      salesDisablePromo({
+        salesBillSn: _this.salesBillSn,
+        salesPromoSn: item.salesPromoSn,
+        promoRuleSn: item.promoRuleSn,
+        salesDisableType: _this.disabledActiveOption
+      }).then(res => {
+        if(res.status == 200){
+          item.disabled = true
+          item.isActive = false
+          _this.activeList.splice()
+          // 启用按钮
+          _this.$refs['productList-'+item.promoRuleSn][0].disableActive(true)
+
+          // 刷新所有表格
+          _this.updateAllTable(true)
+
+          _this.disabledActiveOption = null
+          _this.spinning = false
+          _this.$message.success("操作成功")
+        }
+      })
+    },
+    // 禁用启用活动规则
+    disenablePromp(e,item){
+      const _this = this
+      const table = _this.$refs['productList-'+item.promoRuleSn][0]
+
+      // 是否启用规则
+      if(item.disabled){
+        this.enabledActive(e,item)
+        return
+      }
+      // 如果没有活动产品,直接禁用无需弹框提示
+      if(table.countData&&!table.countData.totalQty){
+        _this.disabledActiveOption = 'DELETE'
+        _this.disabledActive(e,item)
+        return
+      }
+      // 弹框提示禁用方式
+      this.$confirm({
+        title: '确定禁用规则?',
+        centered: true,
+        class:'confirm-center',
+        content: <div>
+          <div style="padding:10px 0;text-align:center;">禁用规则后,将无法享受该活动规则优惠</div>
+          <div style="padding:0 0 10px 0;text-align:center;">
+            <aRadioGroup onChange={_this.changeDaOpt}>
+              <aRadio style="display:block;height: '30px';lineHeight: '30px';padding:5px 0;" value="DELETE">
+                删除规则中相关产品
+              </aRadio>
+              <aRadio style="display:block;height: '30px';lineHeight: '30px';padding:5px 0;" value="REMOVE">
+                移出规则中相关产品
+              </aRadio>
+            </aRadioGroup>
+          </div>
+        </div>,
+        onOk() {
+          if(_this.disabledActiveOption){
+            _this.disabledActive(e,item)
+          }else{
+            _this.$message.info("请选择禁用方式!")
+            return true
+          }
+        },
+        onCancel() {
+          _this.disabledActiveOption = null
+        },
+      });
+    },
+    changeDaOpt(e){
+      this.disabledActiveOption = e.target.value
+    },
+    pageInit () {
+      this.salesBillSn = this.$route.params.sn
+      this.warehouseSn = this.$route.params.sn ? this.$route.params.wSn : ''
+      this.getOrderDetail(true)
+      this.getNewActive()
+    }
+  },
+  mounted () {
+    if (!this.$store.state.app.isNewTab) { // 页签刷新时调用
+      this.pageInit()
+    }
+  },
+  activated () {
+    // 如果是新页签打开或者进入新的子页(例:存在列表第2条数据编辑页页签时再打开第4条数据的编辑页),则重置当前页面
+    if (this.$store.state.app.isNewTab || !this.$store.state.app.isNewSubTab) {
+      this.pageInit()
+    }
+  },
+  beforeRouteEnter (to, from, next) {
+    next(vm => {})
+  }
+}
+</script>
+
+<style lang="less">
+  .salesNewEdit-wrap{
+    position: relative;
+    height: 100%;
+    padding-bottom: 75px;
+    box-sizing: border-box;
+    >.ant-spin-nested-loading{
+      overflow-y: auto;
+      height: 100%;
+    }
+    .salesEdit-cont{
+      margin: 10px 0;
+    }
+    .redStyle{
+      font-weight: bold;
+      color: red;
+    }
+    .ellipsisCon{
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+      .ellipsisText{
+        width: 100%;
+        overflow: hidden;
+        text-overflow: ellipsis;
+        display: box;
+        display: -webkit-box;
+        -webkit-line-clamp: 1;
+        -webkit-box-orient: vertical;
+      }
+    }
+    .ant-card-small > .ant-card-body {
+        padding: 0!important;
+    }
+    .affix-cont{
+      padding: 10px 15px;
+      text-align: right;
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+      .footer-price{
+        flex-grow:1;
+        display: flex;
+        justify-content: flex-end;
+        align-items: center;
+        > div{
+          padding: 0 15px;
+        }
+        .totalPrice{
+          span{
+            font-weight: bold;
+            color: red;
+            font-size: 20px;
+          }
+        }
+      }
+    }
+  }
+
+</style>

+ 721 - 0
src/views/salesManagement/salesQueryNew/list.vue

@@ -0,0 +1,721 @@
+<template>
+  <div>
+    <a-card size="small" :bordered="false" class="salesManagementList-wrap">
+      <!-- 搜索条件 -->
+      <div ref="tableSearch" class="table-page-search-wrapper" style="margin: 0;">
+        <a-form layout="inline">
+          <a-row :gutter="15">
+            <a-col :md="6" :sm="24">
+              <a-form-item label="创建时间">
+                <rangeDate ref="rangeDate" :value="time" @change="dateChange" />
+              </a-form-item>
+            </a-col>
+            <a-col :md="6" :sm="24">
+              <a-form-item label="客户名称">
+                <dealerSubareaScopeList ref="dealerSubareaScopeList" id="salesManagementList-buyerName" @change="custChange" />
+              </a-form-item>
+            </a-col>
+            <a-col :md="6" :sm="24">
+              <a-form-item label="销售单号">
+                <a-input id="salesManagementList-salesBillNo" v-model.trim="queryParam.salesBillNo" allowClear placeholder="请输入销售单号"/>
+              </a-form-item>
+            </a-col>
+            <a-col :md="6" :sm="24">
+              <a-form-item label="采购单号">
+                <a-input id="salesManagementList-purchaseBillNo" v-model.trim="queryParam.purchaseBillNo" allowClear placeholder="请输入采购单号"/>
+              </a-form-item>
+            </a-col>
+            <template v-if="advanced">
+              <a-col :md="6" :sm="24">
+                <a-form-item label="备货打印状态">
+                  <v-select
+                    v-model="queryParam.printStatus"
+                    ref="printStatus"
+                    id="salesManagementList-printStatus"
+                    code="PRINT_STATUS"
+                    placeholder="请选择打印状态"
+                    allowClear></v-select>
+                </a-form-item>
+              </a-col>
+              <a-col :md="6" :sm="24">
+                <a-form-item label="业务状态">
+                  <v-select
+                    v-model="queryParam.billStatus"
+                    ref="billStatus"
+                    id="salesManagementList-billStatus"
+                    code="SALES_BILL_STATUS"
+                    placeholder="请选择业务状态"
+                    allowClear></v-select>
+                </a-form-item>
+              </a-col>
+              <a-col :md="6" :sm="24">
+                <a-form-item label="财务状态">
+                  <v-select
+                    v-model="queryParam.financialStatus"
+                    ref="financialStatus"
+                    id="salesManagementList-financialStatus"
+                    code="FINANCIAL_RECEIVE_STATUS"
+                    placeholder="请选择财务状态"
+                    allowClear></v-select>
+                </a-form-item>
+              </a-col>
+              <a-col :md="6" :sm="24">
+                <a-form-item label="单据来源">
+                  <v-select
+                    v-model="queryParam.salesBillSource"
+                    ref="salesBillSource"
+                    id="salesManagementList-salesBillSource"
+                    code="SALES_SOURCE"
+                    placeholder="请选择单据来源"
+                    allowClear></v-select>
+                </a-form-item>
+              </a-col>
+              <a-col :md="6" :sm="24">
+                <a-form-model-item label="所在区域">
+                  <subarea ref="subarea" id="salesManagementList-subarea" @change="subareaChange"></subarea>
+                </a-form-model-item>
+              </a-col>
+              <a-col :md="6" :sm="24">
+                <a-form-model-item label="地区" prop="shippingAddrProvinceSn">
+                  <Area id="salesManagementList-shippingAddrProvinceSn" v-model="queryParam.shippingAddrProvinceSn" placeholder="请选择省"></Area>
+                </a-form-model-item>
+              </a-col>
+              <a-col :md="6" :sm="24">
+                <a-form-model-item label="出库仓库">
+                  <chooseWarehouse ref="warehouse" v-model="queryParam.warehouseSn"></chooseWarehouse>
+                </a-form-model-item>
+              </a-col>
+              <a-col :md="6" :sm="24">
+                <a-form-item label="促销单">
+                  <v-select
+                    v-model="queryParam.promoFlag"
+                    ref="cxFlag"
+                    code="FLAG"
+                    placeholder="请选择是否促销单"
+                    allowClear></v-select>
+                </a-form-item>
+              </a-col>
+            </template>
+            <a-col :md="24" :sm="24" style="text-align: center;">
+              <a-button type="primary" :disabled="disabled" @click="$refs.table.refresh(true)">查询</a-button>
+              <a-button style="margin-left: 8px" :disabled="disabled" @click="resetSearchForm()">重置</a-button>
+              <a-button
+                style="margin-left: 10px"
+                type="primary"
+                class="button-warning"
+                @click="handleExport"
+                :disabled="disabled"
+                :loading="exportLoading"
+                v-if="$hasPermissions('B_sales_export')"
+              >导出</a-button>
+              <a @click="advanced=!advanced" style="margin-left: 8px">
+                {{ advanced ? '收起' : '展开' }}
+                <a-icon :type="advanced ? 'up' : 'down'"/>
+              </a>
+            </a-col>
+          </a-row>
+        </a-form>
+      </div>
+    </a-card>
+    <a-card size="small" :bordered="false" class="salesManagementList-wrap">
+      <a-spin :spinning="spinning" tip="Loading...">
+        <!-- 操作按钮 -->
+        <div class="table-operator" style="display: flex;justify-content: space-between;align-items: center;">
+          <div style="padding-right: 15px;"><a-button type="primary" class="button-error" v-if="$hasPermissions('B_salesAdd')" @click="handleAdd">新增</a-button></div>
+          <div style="flex-grow: 1;display: flex;justify-content: space-between;align-items: center;">
+            <div>
+              <div>
+                总单数:<strong>{{ totalData&&(totalData.totalRecord || totalData.totalRecord==0) ? totalData.totalRecord : '--' }}</strong>;
+                总款数:<strong>{{ totalData&&(totalData.totalCategory || totalData.totalCategory==0) ? totalData.totalCategory : '--' }}</strong>;
+                总数量:<strong>{{ totalData&&(totalData.totalQty || totalData.totalQty==0) ? totalData.totalQty : '--' }}</strong>;
+                已下推数量:<strong>{{ totalData&&(totalData.totalPushedQty || totalData.totalPushedQty==0) ? totalData.totalPushedQty : '--' }}</strong>;
+                已发货数量:<strong>{{ totalData&&(totalData.totalDispatchQty || totalData.totalDispatchQty==0) ? totalData.totalDispatchQty : '--' }}</strong>;
+                已取消数量:<strong>{{ totalData&&(totalData.totalCancelQty || totalData.totalCancelQty==0) ? totalData.totalCancelQty : '--' }}</strong>;
+                待下推数量:<strong>{{ totalData&&(totalData.totalUnpushedQty || totalData.totalUnpushedQty==0) ? totalData.totalUnpushedQty : '--' }}</strong>;
+              </div>
+              <div v-if="$hasPermissions('M_salesQueryList_salesPrice')">
+                总售价:<strong>{{ totalData&&(totalData.totalAmount || totalData.totalAmount==0) ? toThousands(totalData.totalAmount) : '--' }}</strong>;
+                已下推金额:<strong>{{ totalData&&(totalData.totalPushedAmount || totalData.totalPushedAmount==0) ? toThousands(totalData.totalPushedAmount) : '--' }}</strong>;
+                已取消金额:<strong>{{ totalData&&(totalData.totalCancelAmount || totalData.totalCancelAmount==0) ? toThousands(totalData.totalCancelAmount) : '--' }}</strong>;
+                待下推金额:<strong>{{ totalData&&(totalData.totalUnpushedAmount || totalData.totalUnpushedAmount==0) ? toThousands(totalData.totalUnpushedAmount) : '--' }}</strong>;
+                已发货金额:<strong>{{ totalData&&(totalData.totalDispatchAmount || totalData.totalDispatchAmount==0) ? toThousands(totalData.totalDispatchAmount) : '--' }}</strong>;
+              </div>
+            </div>
+            <div>
+              <a-checkbox v-model="showCancelNum"><span style="display: inline-block;margin-top: 1px;">显示取消数量</span></a-checkbox>
+            </div>
+          </div>
+        </div>
+
+        <!-- 列表 -->
+        <s-table
+          class="sTable fixPagination"
+          ref="table"
+          :style="{ height: tableHeight+75+'px' }"
+          size="small"
+          :rowKey="(record) => record.id"
+          :columns="columns"
+          :data="loadData"
+          :scroll="{ y: tableHeight }"
+          :defaultLoadData="false"
+          bordered>
+          <!-- 销售单号 -->
+          <template slot="salesBillNo" slot-scope="text, record">
+            <span v-if="$hasPermissions('B_salesDetail')" class="link-bule" @click="handleDetail(record)">{{ record.salesBillNo }}</span>
+            <span v-else>{{ record.salesBillNo }}</span>
+            <a-badge :count="'改'+record.changeTimes" :number-style="{ zoom:'80%' }" v-if="record.changeTimes>0"></a-badge>
+            <a-badge count="促" v-if="record.promoFlag==1" :number-style="{ backgroundColor: '#52c41a', zoom:'80%' }"></a-badge>
+          </template>
+          <!-- 出库仓库 -->
+          <template slot="warehouseBox" slot-scope="text, record">
+            <a-tooltip placement="right" v-if="record.newWarehouseNameSet && record.newWarehouseNameSet.length>0">
+              <template slot="title">
+                <span>{{ record.newWarehouseNameSet.toString() }}</span>
+              </template>
+              <div class="warehouse_box">
+                <span>{{ record.newWarehouseNameSet.toString() }}</span>
+              </div>
+            </a-tooltip>
+            <div v-else>--</div>
+          </template>
+          <!-- 总数量 -->
+          <template slot="totalQty" slot-scope="text, record">
+            {{ record.totalQty }}
+          </template>
+          <!-- 操作 -->
+          <template slot="action" slot-scope="text, record">
+            <div>
+              <a-button
+                size="small"
+                type="link"
+                class="button-warning"
+                v-if="record.billStatus == 'WAIT_AUDIT'&&$hasPermissions('B_salesAudit')"
+                @click="handleDetailAudit(record)"
+              >审核</a-button>
+              <a-button
+                size="small"
+                type="link"
+                class="button-warning"
+                v-if="record.billStatus == 'WAIT_PUSH'&&$hasPermissions('B_salesDispatch')"
+                @click="handleDispatch(record)"
+              >下推</a-button>
+              <a-button
+                size="small"
+                type="link"
+                class="button-info"
+                v-if="(record.salesBillSource == 'SALES' && (record.billStatus == 'WAIT_SUBMIT' || record.billStatus == 'WAIT_AUDIT' || record.billStatus == 'AUDIT_REJECT' || record.billStatus == 'HQ_CHANGE'))&&$hasPermissions('B_salesEdit')"
+                @click="handleEdit(record)"
+              >
+                编辑
+              </a-button>
+              <a-button
+                size="small"
+                type="link"
+                class="button-info"
+                v-if="record.salesBillSource == 'PURCHASE' && (record.billStatus == 'WAIT_AUDIT' || record.billStatus == 'HQ_CHANGE') && $hasPermissions('B_salesEdit')"
+                @click="handleEdit(record)"
+              >
+                改单
+              </a-button>
+              <a-button
+                size="small"
+                type="link"
+                class="button-error"
+                v-if="(record.salesBillSource == 'SALES' && (record.billStatus == 'WAIT_SUBMIT' || record.billStatus == 'WAIT_AUDIT' || record.billStatus == 'AUDIT_REJECT' || record.billStatus == 'HQ_CHANGE'))&&$hasPermissions('B_salesDel')"
+                @click="handleDel(record)"
+              >
+                删除
+              </a-button>
+              <a-button
+                size="small"
+                type="link"
+                class="button-error"
+                v-if="record.salesBillSource == 'PURCHASE' && (record.billStatus == 'WAIT_AUDIT' || record.billStatus == 'HQ_CHANGE') && $hasPermissions('B_salesDel')"
+                @click="handleDel(record)"
+              >
+                取消
+              </a-button>
+              <a-button
+                size="small"
+                type="link"
+                class="button-warning"
+                v-if="record.printStatus=='UNABLE_PRINT'&&$hasPermissions('B_Sales_UNABLE_PRINT')"
+                @click="handlePrint(record)"
+              >允许备货打印</a-button>
+              <a-button
+                size="small"
+                type="link"
+                class="button-warning"
+                v-if="record.billStatus=='FINISH' && record.expenseClainFlag == 'N'"
+                @click="handleExpense(record)"
+              >转费用报销单</a-button>
+            </div>
+          </template>
+        </s-table>
+      </a-spin>
+      <!-- 选择客户弹框 -->
+      <choose-custom-modal :show="openModal" @ok="chooseCustomOk" @cancel="openModal=false"></choose-custom-modal>
+      <!-- 操作提示 -->
+      <commonModal modalTit="操作提示" :width="this.tipData&&this.tipData.length == 1?'500px':'800px'" :openModal="showTipModal" @cancel="canselModal" @ok="updatePrintStatus">
+        <div style="text-align: center;" v-if="this.tipData&&this.tipData.length">
+          <div style="margin-bottom: 15px;font-size: 14px;"><strong>确认允许此单进行备货打印吗?</strong></div>
+          <div style="line-height: 24px;" v-if="this.tipData.length == 1">
+            <div>备货单号:{{ tipData[0]&&tipData[0].dispatchBillNo }}</div>
+            <div>客户名称:{{ tipData[0]&&tipData[0].buyerName }}</div>
+          </div>
+          <div v-else>
+            <a-table
+              :row-selection="{ selectedRowKeys: selectedRowKeys,onChange: onSelectChange, getCheckboxProps: record => ({ props: { disabled: record.printStatus!=='UNABLE_PRINT' }})}"
+              :columns="bhColumns"
+              :data-source="tipData"
+              :pagination="false"
+            />
+          </div>
+        </div>
+      </commonModal>
+      <!-- 新增费用单 -->
+      <baseDataModal ref="expenseModal" @expenseSaveOk="expenseSaveOk" :show="openBaseModal" @close="openBaseModal=false"></baseDataModal>
+      <!-- 导出提示框 -->
+      <reportModal :visible="showExport" @close="showExport=false"></reportModal>
+    </a-card>
+  </div>
+</template>
+
+<script>
+import { commonMixin } from '@/utils/mixin'
+import moment from 'moment'
+import getDate from '@/libs/getDate.js'
+import subarea from '@/views/common/subarea.js'
+import Area from '@/views/common/area.js'
+import rangeDate from '@/views/common/rangeDate.vue'
+import { STable, VSelect } from '@/components'
+import commonModal from '@/views/common/commonModal.vue'
+import chooseCustomModal from './chooseCustomModal.vue'
+import dealerSubareaScopeList from '@/views/common/dealerSubareaScopeList.vue'
+import baseDataModal from '@/views/expenseManagement/expenseReimbursement/baseDataModal.vue'
+import reportModal from '@/views/common/reportModal.vue'
+import { salesList, salesDel, salesCancle, salesCount, queryCreateBySalesBillSn, expenseAccountSave } from '@/api/salesNew'
+import { hdExportExcel } from '@/libs/exportExcel'
+import chooseWarehouse from '@/views/common/chooseWarehouse'
+import { dispatchBatchPrintStatus, queryBySalesBillSn } from '@/api/dispatch'
+import { salesDetailExport } from '@/api/salesBillReport'
+export default {
+  name: 'SalesQueryList',
+  mixins: [commonMixin],
+  components: { STable, VSelect, chooseCustomModal, dealerSubareaScopeList, Area, rangeDate, subarea, commonModal, reportModal, chooseWarehouse, baseDataModal },
+  data () {
+    return {
+      spinning: false,
+      advanced: true, // 高级搜索 展开/关闭
+      disabled: false, //  查询、重置按钮是否可操作
+      openModal: false, // 选择客户弹框是否显示
+      openBaseModal: false, // 费用弹框
+      showTipModal: false, // 备货打印弹框
+      showExport: false,
+      exportLoading: false,
+      expenseOption: false,
+      tableHeight: 0,
+      time: [
+        moment(getDate.getThreeMonthDays().starttime, 'YYYY-MM-DD'),
+        moment(getDate.getCurrMonthDays().endtime, 'YYYY-MM-DD')
+      ],
+      // 查询参数
+      queryParam: {
+        beginDate: getDate.getThreeMonthDays().starttime,
+        endDate: getDate.getCurrMonthDays().endtime,
+        buyerSn: undefined, //  客户名称
+        salesBillNo: '', //  销售单号
+        purchaseBillNo: '',
+        printStatus: undefined,
+        billStatus: undefined, //  业务状态
+        financialStatus: undefined, //  财务状态
+        salesBillSource: undefined,
+        subareaArea: {
+          subareaSn: undefined,
+          subareaAreaSn: undefined
+        },
+        shippingAddrProvinceSn: undefined,
+        warehouseSn: undefined,
+        promoFlag: undefined
+      },
+      totalData: {
+        totalAmount: 0,
+        totalCategory: 0,
+        totalQty: 0,
+        totalRecord: 0,
+        totalPushedQty: 0,
+        totalDispatchQty: 0,
+        totalCancelQty: 0,
+        totalUnpushedQty: 0,
+        totalPushedAmount: 0,
+        totalCancelAmount: 0,
+        totalUnpushedAmount: 0,
+        totalDispatchAmount: 0
+      },
+      // 加载数据方法 必须为 Promise 对象
+      loadData: parameter => {
+        this.disabled = true
+        this.spinning = true
+        delete parameter.tableId
+        delete parameter.index
+        // 查询总计
+        salesCount(Object.assign(parameter, this.queryParam)).then(res => {
+          this.totalData = Object.assign(this.totalData, res.data || {})
+        })
+        return salesList(Object.assign(parameter, this.queryParam)).then(res => {
+          let data
+          if (res.status == 200) {
+            data = res.data
+            const no = (data.pageNo - 1) * data.pageSize
+            data.list.forEach((con, i) => {
+              con.no = no + i + 1
+              const newWarehouseName = []
+              if (con.warehouseNameSet) {
+                con.warehouseNameSet.forEach(item => {
+                  if (item) {
+                    newWarehouseName.push(item)
+                  }
+                })
+                con.newWarehouseNameSet = newWarehouseName
+              }
+            })
+            this.disabled = false
+          }
+          this.spinning = false
+          return data
+        })
+      },
+      showCancelNum: false, //  是否显示取消数量和待下推数量
+      tipData: null, // 备货单信息
+      tempSalesBillSn: null,
+      // 允许备货打印
+      selectedRowKeys: [],
+      bhColumns: [
+        {
+          title: '备货单号',
+          dataIndex: 'dispatchBillNo'
+        },
+        {
+          title: '客户名称',
+          dataIndex: 'buyerName'
+        },
+        {
+          title: '备货打印状态',
+          dataIndex: 'printStatusDictValue'
+        }
+      ]
+    }
+  },
+  computed: {
+    columns () {
+      const _this = this
+      const arr = [
+        { title: '创建时间', dataIndex: 'createDate', width: '6%', align: 'center', customRender: function (text) { return text || '--' }, sorter: true },
+        { title: '销售单号', scopedSlots: { customRender: 'salesBillNo' }, width: '7%', align: 'center' },
+        { title: '提交时间', dataIndex: 'submitDate', width: '6%', align: 'center', customRender: function (text) { return text || '--' }, sorter: true },
+        { title: '客户名称', dataIndex: 'buyerName', width: '8%', align: 'left', customRender: function (text) { return text || '--' }, ellipsis: true },
+        { title: '出库仓库', scopedSlots: { customRender: 'warehouseBox' }, width: '8%', align: 'center', ellipsis: true },
+        { title: '总数量', dataIndex: 'totalQty', scopedSlots: { customRender: 'totalQty' }, width: '4%', align: 'center' },
+        { title: '已下推数量', dataIndex: 'totalPushedQty', width: '4%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
+        { title: '已发货数量', dataIndex: 'totalDispatchQty', width: '4%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
+        { title: '收款方式', dataIndex: 'settleStyleSnDictValue', width: '5%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '审核时间', dataIndex: 'auditDate', width: '6%', align: 'center', customRender: function (text) { return text || '--' }, sorter: true },
+        { title: '最近备货时间', dataIndex: 'lastStockUpDate', width: '6%', align: 'center', customRender: function (text) { return text || '--' }, sorter: true },
+        { title: '业务状态', dataIndex: 'billStatusDictValue', width: '6%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '财务状态', dataIndex: 'financialStatusDictValue', width: '5%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '备货打印状态', dataIndex: 'printStatusDictValue', width: '5%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
+        { title: '操作', scopedSlots: { customRender: 'action' }, width: '7%', align: 'center' }
+      ]
+
+      if (this.$hasPermissions('M_salesQueryList_salesPrice')) { // 售价权限
+        arr.splice(6, 0, { title: '总售价', dataIndex: 'totalAmount', width: '4%', align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } })
+        arr.splice(8, 0, { title: '下推总金额', dataIndex: 'totalPushedAmount', width: '4%', align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } })
+      }
+      if (this.showCancelNum) {
+        const ind = this.$hasPermissions('M_salesQueryList_salesPrice') ? 10 : 8
+        arr.splice(ind, 0, { title: '已取消数量', dataIndex: 'totalCancelQty', width: '4%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } })
+        arr.splice(ind + 1, 0, { title: '待下推数量', dataIndex: 'totalUnpushedQty', width: '4%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } })
+      }
+      return arr
+    }
+  },
+  methods: {
+    //  导出
+    handleExport () {
+      const _this = this
+      _this.$store.state.app.curActionPermission = 'B_sales_export'
+      _this.exportLoading = true
+      _this.spinning = true
+      hdExportExcel(salesDetailExport, _this.queryParam, '销售明细', function () {
+        _this.exportLoading = false
+        _this.spinning = false
+        _this.showExport = true
+        _this.$store.state.app.curActionPermission = ''
+      })
+    },
+    //  时间  change
+    dateChange (date) {
+      this.queryParam.beginDate = date[0]
+      this.queryParam.endDate = date[1]
+    },
+    custChange (val) {
+      this.queryParam.buyerSn = val.key
+    },
+    subareaChange (val) {
+      this.queryParam.subareaArea.subareaSn = val[0] ? val[0] : undefined
+      this.queryParam.subareaArea.subareaAreaSn = val[1] ? val[1] : undefined
+    },
+    // 新增
+    handleAdd () {
+      this.openModal = true
+    },
+    // 选择客户成功
+    chooseCustomOk (data) {
+      this.$router.push({ name: 'salesNewAdd', params: { sn: data.salesBillSn } })
+    },
+    // 下推
+    handleDispatch (row) {
+      this.$router.push({ name: 'waitDispatchNew', params: { salesBillSn: row.salesBillSn } })
+    },
+    // 详情
+    handleDetail (row) {
+      this.$router.push({ name: 'salesNewDetail', params: { sn: row.salesBillSn } })
+    },
+    // 审核
+    handleDetailAudit (row) {
+      this.$router.push({ name: 'salesNewDetailAudit', params: { sn: row.salesBillSn } })
+    },
+    // 编辑
+    handleEdit (row) {
+      this.$router.push({ name: 'salesNewEdit', params: { sn: row.salesBillSn } })
+    },
+    // 删除
+    handleDel (row) {
+      const _this = this
+      this.$confirm({
+        title: '提示',
+        content: row.salesBillSource == 'PURCHASE' ? '确认要取消吗?' : '确认要删除吗?',
+        centered: true,
+        closable: true,
+        onOk () {
+          _this.spinning = true
+          const fun = row.salesBillSource == 'PURCHASE' ? salesCancle : salesDel
+          fun({ salesBillSn: row.salesBillSn }).then(res => {
+            if (res.status == 200) {
+              _this.$message.success(res.message)
+              _this.$refs.table.refresh()
+              _this.spinning = false
+            } else {
+              _this.spinning = false
+            }
+          })
+        }
+      })
+    },
+    // 转费用单
+    async handleExpense (row) {
+      const _this = this
+      const hasExpense = await queryCreateBySalesBillSn({ salesBillSn: row.salesBillSn }).then(res => res.data || [])
+      console.log(hasExpense)
+      // 有2个以上采购额时
+      if (hasExpense && hasExpense.exceed && hasExpense.balance) {
+        _this.$confirm({
+          title: '转费用报销单?',
+          centered: true,
+          class: 'confirm-center',
+          content: <div>
+            <div style="padding:10px 0;text-align:center;">请选择费用报销单类型</div>
+            <div style="padding:0 0 10px 0;text-align:center;">
+              <aRadioGroup onChange={_this.changeDaOpt}>
+                <aRadio style="height: '30px';lineHeight: '30px';padding:5px 0;" value="balance">
+                  采购额结余
+                </aRadio>
+                <aRadio style="height: '30px';lineHeight: '30px';padding:5px 0;" value="exceed">
+                  采购额超出
+                </aRadio>
+              </aRadioGroup>
+            </div>
+          </div>,
+          onOk () {
+            if (_this.expenseOption) {
+              _this.expenseSave(hasExpense, _this.expenseOption)
+            } else {
+              _this.$message.info('请选择费用报销单类型!')
+              return true
+            }
+          },
+          onCancel () {
+            _this.expenseOption = null
+          }
+        })
+      } else {
+        // 直接转费用单
+        _this.expenseSave(hasExpense, null)
+      }
+    },
+    // 转费用单
+    expenseSave (data, type) {
+      console.log(data, type)
+      const params = type ? data[type] : (data.balance || data.exceed)
+      if (params) {
+        this.openBaseModal = true
+        this.$refs.expenseModal.setDetail(params, 'sales')
+      }
+    },
+    expenseSaveOk (params) {
+      expenseAccountSave(params).then(res => {
+        if (res.status == 200) {
+          this.$message.info(res.message)
+          this.$refs.table.refresh()
+          this.openBaseModal = false
+          this.expenseOption = null
+          this.$router.push({ name: 'expenseReimbursementEdit', params: { sn: res.data.expenseAccountSn } })
+        }
+      })
+    },
+    changeDaOpt (e) {
+      this.expenseOption = e.target.value
+    },
+    // 允许备货打印
+    handlePrint (row) {
+      // 获取关联的下推单
+      this.tempSalesBillSn = row.salesBillSn
+      queryBySalesBillSn({ salesBillSn: row.salesBillSn }).then(res => {
+        this.tipData = res.data || []
+        this.tipData.map(item => {
+          item.key = item.dispatchBillSn
+          if (item.printStatus == 'UNABLE_PRINT') {
+            this.selectedRowKeys.push(item.dispatchBillSn)
+          }
+        })
+        this.showTipModal = true
+      })
+    },
+    canselModal () {
+      this.tipData = null
+      this.showTipModal = false
+      this.tempSalesBillSn = null
+      this.selectedRowKeys = []
+    },
+    onSelectChange (selectedRowKeys) {
+      this.selectedRowKeys = selectedRowKeys
+    },
+    // 允许备货打印状态
+    updatePrintStatus () {
+      const isOne = this.tipData.length
+      if (isOne > 1 && this.selectedRowKeys.length == 0) {
+        this.$message.info('请选择备货单!')
+        return
+      }
+      const dispatchBillSnList = []
+      this.tipData.map(item => {
+        dispatchBillSnList.push(item.dispatchBillSn)
+      })
+
+      const params = {
+        'salesBillSn': this.tempSalesBillSn,
+        'dispatchBillSnList': isOne > 1 ? this.selectedRowKeys : dispatchBillSnList,
+        'printStatus': 'NO_PRINT'
+      }
+      dispatchBatchPrintStatus(params).then(res => {
+        if (res.status == 200) {
+          this.canselModal()
+          this.$message.info(res.message)
+          this.$refs.table.refresh()
+        }
+      })
+    },
+    // 重置
+    resetSearchForm () {
+      this.$refs.rangeDate.resetDate(this.time)
+      this.queryParam.beginDate = getDate.getThreeMonthDays().starttime
+      this.queryParam.endDate = getDate.getCurrMonthDays().endtime
+      this.$refs.dealerSubareaScopeList.resetForm()
+      this.queryParam.buyerSn = undefined
+      this.queryParam.salesBillNo = ''
+      this.queryParam.purchaseBillNo = ''
+      this.queryParam.printStatus = undefined
+      this.queryParam.billStatus = undefined
+      this.queryParam.financialStatus = undefined
+      this.queryParam.salesBillSource = undefined
+      this.queryParam.subareaArea.subareaSn = undefined
+      this.queryParam.subareaArea.subareaAreaSn = undefined
+      this.queryParam.shippingAddrProvinceSn = undefined
+      this.queryParam.warehouseSn = undefined
+      this.queryParam.promoFlag = undefined
+      if (this.advanced) {
+        this.$refs.subarea.clearData()
+      }
+      this.$refs.table.refresh(true)
+    },
+    pageInit () {
+      const _this = this
+      this.$nextTick(() => { // 页面渲染完成后的回调
+        _this.setTableH()
+      })
+    },
+    setTableH () {
+      const tableSearchH = this.$refs.tableSearch.offsetHeight
+      this.tableHeight = window.innerHeight - tableSearchH - 265
+    }
+  },
+  watch: {
+    advanced (newValue, oldValue) {
+      const _this = this
+      this.$nextTick(() => { // 页面渲染完成后的回调
+        _this.setTableH()
+      })
+    },
+    '$store.state.app.winHeight' (newValue, oldValue) { //  窗口变更时,需同时更改表格高度
+      console.log(newValue)
+      this.setTableH()
+    }
+  },
+  mounted () {
+    if (!this.$store.state.app.isNewTab) { // 页签刷新时调用
+      this.pageInit()
+      this.resetSearchForm()
+    }
+  },
+  activated () {
+    // 如果是新页签打开,则重置当前页面
+    if (this.$store.state.app.isNewTab) {
+      this.pageInit()
+      this.resetSearchForm()
+    }
+    // 仅刷新列表,不重置页面
+    if (this.$store.state.app.updateList) {
+      this.pageInit()
+      this.$refs.table.refresh()
+    }
+  },
+  beforeRouteEnter (to, from, next) {
+    next(vm => {})
+  }
+}
+</script>
+<style lang="less" scoped>
+  .salesManagementList-wrap{
+    margin-bottom: 6px;
+    .sTable{
+      .badge-con-t{
+        .ant-badge-count{
+          transform: scale(0.8);
+          font-size: 13px;
+        }
+      }
+      .warehouse_box{
+        width: 100%;
+        overflow: hidden;
+        white-space: nowrap;
+        text-overflow: ellipsis;
+      }
+      // .warehouse_box>span::after{
+      //   content:',';
+      // }
+      // .warehouse_box>span:last-child::after{
+      //   content:'';
+      // }
+    }
+  }
+</style>

+ 90 - 0
src/views/salesManagement/salesQueryNew/newPromoModal.vue

@@ -0,0 +1,90 @@
+<template>
+    <a-modal
+      v-model="opened"
+      title="新活动提醒"
+      centered
+      :maskClosable="false"
+      :confirmLoading="confirmLoading"
+      width="30%"
+      :footer="null"
+      @cancel="cancel"
+    >
+      <a-spin :spinning="spinning" tip="Loading...">
+        <div style="padding: 0 50px;">
+          <div style="padding:10px 0;text-align:left;">
+            系统发布新的促销活动,是否要参与?
+          </div>
+          <div style="text-align:left;color:#00aaff;">
+            <a-checkbox-group v-model="newPromoSnList">
+              <a-row v-for="item in newActiveList" :key="item.promotionSn">
+                <a-col :span="24"><a-checkbox :value="item.promotionSn">{{ item.description }}</a-checkbox></a-col>
+              </a-row>
+            </a-checkbox-group>
+          </div>
+        </div>
+        <div style="margin-top:36px;text-align:center;">
+          <a-button @click="cancel" style="margin-right: 15px" id="chooseCustom-btn-back">取消</a-button>
+          <a-button type="primary" :loading="confirmLoading" @click="handleSubmit" id="chooseCustom-btn-submit">确定</a-button>
+        </div>
+      </a-spin>
+    </a-modal>
+  </template>
+  
+  <script>
+  import { commonMixin } from '@/utils/mixin'
+  import { salesDetailAddPromo } from '@/api/salesDetailNew'
+  export default {
+    name: 'newPromoModal',
+    mixins: [commonMixin],
+    props: {
+      show: [Boolean],
+      newActiveList: [Array],
+      salesBillSn: [String]
+    },
+    data () {
+      return {
+        opened: this.show,
+        spinning: false,
+        newPromoSnList: [],
+        confirmLoading: false
+      }
+    },
+    methods: {
+      //  保存
+      handleSubmit () {
+        const _this = this
+        if(_this.newPromoSnList.length){
+            salesDetailAddPromo({
+              "salesBillSn": _this.salesBillSn,
+              "promoSnList": _this.newPromoSnList
+            }).then(res => {
+              if(res.status == 200){
+                _this.$emit('ok')
+              }
+            })
+          }else{
+            _this.$message.info("请选择要参与的新活动")
+            return true
+          }
+      },
+      cancel () {
+        this.opened = false
+        this.$emit('cancel')
+      }
+    },
+    watch: {
+      show (newValue, oldValue) {
+        this.opened = newValue
+        if (!newValue) {
+          this.newPromoSnList = []
+        }else{
+            // 默认全选
+            this.newActiveList.map(item => {
+               this.newPromoSnList.push(item.promotionSn)
+            })
+        }
+      }
+    }
+  }
+  </script>
+  

+ 245 - 0
src/views/salesManagement/salesQueryNew/printModal.vue

@@ -0,0 +1,245 @@
+<template>
+  <a-modal
+    centered
+    :footer="null"
+    :maskClosable="false"
+    class="sales-print-type-modal"
+    :title="modalTit"
+    v-model="isShow"
+    @cancel="isShow=false"
+    :width="600">
+    <a-spin :spinning="spinning" tip="Loading...">
+      <a-form-model
+        id="sales-print-form"
+        ref="ruleForm"
+        :model="form"
+        :rules="rules"
+        :label-col="formItemLayout.labelCol"
+        :wrapper-col="formItemLayout.wrapperCol"
+      >
+        <a-form-model-item label="销售单号">{{ itemData&&itemData.salesBillNo || '--' }}</a-form-model-item>
+        <a-form-model-item label="客户名称">{{ itemData&&itemData.buyerName || '--' }}</a-form-model-item>
+        <a-form-model-item label="产品分类" prop="id" v-if="nowType=='SALES_BILL_TYPE'">
+          <a-select id="sales-print-form" v-model="form.id" placeholder="请选择产品分类">
+            <a-select-option v-for="item in typeList" :value="item.id" :key="item.id">
+              <span v-if="item.id != 'all'">{{ item.productBrandName }} - {{ item.productTypeName3 }}</span>
+              <span v-else>全部</span>
+            </a-select-option>
+          </a-select>
+        </a-form-model-item>
+        <a-form-model-item label="是否缺货产品" prop="dataScope" v-if="nowType=='export'">
+          <a-radio-group v-model="form.dataScope">
+            <a-radio value="all">全部</a-radio>
+            <a-radio value="ENOUGH" :disabled="isDisabled">有库存</a-radio>
+            <a-radio value="LESS" :disabled="isDisabled">缺货</a-radio>
+          </a-radio-group>
+        </a-form-model-item>
+        <a-form-model-item label="产品售价" prop="priceType" v-if="nowType=='SALES_BILL_TYPE'&&$hasPermissions('B_salesTypePrint_salesPrice')">
+          <!-- 销售分类打印 -->
+          <a-radio-group v-model="form.priceType">
+            <a-radio value="SALES_BILL_TYPE_COST">打印</a-radio>
+            <a-radio value="SALES_BILL_TYPE">不打印</a-radio>
+          </a-radio-group>
+        </a-form-model-item>
+        <a-form-model-item label="产品售价" prop="priceType" v-if="nowType=='SALES_BILL'&&$hasPermissions('B_salesPrint_salesPrice')">
+          <!-- 销售打印 -->
+          <a-radio-group v-model="form.priceType">
+            <a-radio value="SALES_BILL_COST">打印</a-radio>
+            <a-radio value="SALES_BILL">不打印</a-radio>
+          </a-radio-group>
+        </a-form-model-item>
+        <a-form-model-item label="产品售价" prop="priceType" v-if="nowType=='export'&&$hasPermissions('B_salesDetailExport_salesPrice')">
+          <!-- 销售导出 -->
+          <a-radio-group v-model="form.priceType">
+            <a-radio :value="form.dataScope == 'ENOUGH' ? 'SALES_BILL_COST_NOT_LACK':'SALES_BILL_COST'">导出</a-radio>
+            <a-radio :value="form.dataScope == 'ENOUGH' ? 'SALES_BILL_NOT_LACK':'SALES_BILL'">不导出</a-radio>
+          </a-radio-group>
+        </a-form-model-item>
+        <a-form-model-item label="货位编号" prop="orderBy" v-if="nowType=='SALES_BILL_TYPE'">
+          <a-radio-group v-model="form.orderBy">
+            <a-radio value="sbd.STACK_PLACE_CODE ASC">打印(↑升序)</a-radio>
+            <a-radio value="sbd.STACK_PLACE_CODE DESC">打印(↓降序)</a-radio>
+            <a-radio value="-1">不打印</a-radio>
+          </a-radio-group>
+        </a-form-model-item>
+      </a-form-model>
+      <div class="btn-cont">
+        <a-button :type="nowType=='export'?'primary':''" id="sales-print-save" @click="handleSave()">{{ nowType=='export' ? '导出' : '打印预览' }}</a-button>
+        <a-button :type="nowType=='export'?'':'primary'" id="sales-print-back" @click="handleCancel" style="margin-left: 15px;">{{ nowType=='export' ? '取消' : '快捷打印' }}</a-button>
+      </div>
+    </a-spin>
+  </a-modal>
+</template>
+
+<script>
+import { salesDetailProductType } from '@/api/salesNew'
+export default {
+  props: {
+    openModal: { //  弹框显示状态
+      type: Boolean,
+      default: false
+    },
+    itemData: {
+      type: Object,
+      default: () => {
+        return null
+      }
+    },
+    nowType: {
+      type: String,
+      default: ''
+    }
+  },
+  data () {
+    return {
+      isShow: this.openModal, //  是否打开弹框
+      form: {
+        id: 'all',
+        dataScope: 'all',
+        priceType: undefined,
+        orderBy: undefined
+      },
+      rules: {
+        id: [{ required: true, message: '请选择产品分类', trigger: 'change' }],
+        dataScope: [{ required: true, message: '请选择是否缺货产品', trigger: 'change' }],
+        priceType: [{ required: true, message: '请选择产品售价', trigger: 'change' }],
+        orderBy: [{ required: true, message: '请选择货位编号', trigger: 'change' }]
+      },
+      formItemLayout: {
+        labelCol: { span: 6 },
+        wrapperCol: { span: 15 }
+      },
+      spinning: false,
+      typeList: []
+    }
+  },
+  computed: {
+    modalTit () {
+      let title = ''
+      if (this.nowType == 'SALES_BILL') {
+        title = '销售打印'
+      } else if (this.nowType == 'SALES_BILL_TYPE') {
+        title = '销售分类打印'
+      } else if (this.nowType == 'export') {
+        title = '导出Excel'
+      }
+      return title
+    },
+    isDisabled () {
+      const states = ['WAIT_SUBMIT', 'WAIT_AUDIT', 'AUDIT_REJECT']
+      return this.itemData && states.includes(this.itemData.billStatus)
+    }
+  },
+  methods: {
+    // 确认
+    handleSave (isPrint) {
+      const _this = this
+      this.$refs.ruleForm.validate(valid => {
+        if (valid) {
+          // 分类打印
+          if (_this.nowType == 'SALES_BILL_TYPE') {
+            // 销售分类无权限不打印
+            if (!_this.$hasPermissions('B_salesTypePrint_salesPrice')) {
+              _this.form.priceType = 'SALES_BILL_TYPE'
+            }
+            const item = _this.typeList.find(item => item.id == _this.form.id)
+            if (item) {
+              const obj = {
+                salesBillSn: _this.itemData.salesBillSn,
+                productBrandSn: item.productBrandSn,
+                productTypeSn3: item.productTypeSn3,
+                priceType: _this.form.priceType,
+                type: isPrint || 'preview'
+              }
+              // 打印货位编号
+              if (_this.form.orderBy != '-1') {
+                obj.orderBy = _this.form.orderBy
+                obj.priceType = obj.priceType + '_STACK_PLACE'
+              }
+              _this.$emit('ok', obj)
+            }
+          } else if (_this.nowType == 'SALES_BILL') {
+            // 销售打印无权限不打印
+            if (!_this.$hasPermissions('B_salesPrint_salesPrice')) {
+              _this.form.priceType = 'SALES_BILL'
+            }
+            const obj = {
+              salesBillSn: _this.itemData.salesBillSn,
+              priceType: _this.form.priceType,
+              type: isPrint || 'preview'
+            }
+            _this.$emit('ok', obj)
+          } else if (_this.nowType == 'export') {
+            // 销售导出无权限不导出
+            if (!_this.$hasPermissions('B_salesDetailExport_salesPrice')) {
+              _this.form.priceType = _this.form.dataScope == 'ENOUGH' ? 'SALES_BILL_NOT_LACK' : 'SALES_BILL'
+            }
+            const obj = {
+              salesBillSn: _this.itemData.salesBillSn,
+              priceType: _this.form.priceType,
+              dataScope: _this.form.dataScope == 'all' ? '' : _this.form.dataScope,
+              type: isPrint || 'preview'
+            }
+            _this.$emit('ok', obj)
+          }
+          _this.isShow = false
+        } else {
+          console.log('error submit!!')
+          return false
+        }
+      })
+    },
+    // 取消选择分类
+    handleCancel () {
+      if (this.nowType == 'export') {
+        this.isShow = false
+      } else {
+        this.handleSave('print')
+      }
+    },
+    // 获取该销售单产品二级分类
+    getTypeData () {
+      this.typeList = [{ id: 'all' }]
+      salesDetailProductType({ sn: this.itemData.salesBillSn || null }).then(res => {
+        if (res.status == 200) {
+          if (res.data && res.data.length > 0) {
+            this.typeList = [...this.typeList, ...res.data]
+          }
+        }
+      })
+    }
+  },
+  watch: {
+    //  父页面传过来的弹框状态
+    openModal (newValue, oldValue) {
+      this.isShow = newValue
+    },
+    //  重定义的弹框状态
+    isShow (newValue, oldValue) {
+      if (!newValue) {
+        this.$emit('close')
+        this.form = {
+          id: 'all',
+          dataScope: 'all',
+          priceType: undefined,
+          orderBy: undefined
+        }
+        this.$refs.ruleForm.resetFields()
+      } else {
+        if (this.nowType == 'SALES_BILL_TYPE') {
+          this.getTypeData()
+        }
+      }
+    }
+  }
+}
+</script>
+
+<style lang="less">
+  .sales-print-type-modal{
+    .btn-cont {
+      text-align: center;
+      margin: 35px 0 10px;
+    }
+  }
+</style>

+ 249 - 0
src/views/salesManagement/salesQueryNew/receivingAddress/chooseAddressModal.vue

@@ -0,0 +1,249 @@
+<template>
+  <a-modal
+    centered
+    class="chooseAddressList-modal"
+    :footer="null"
+    :maskClosable="false"
+    title="收货地址"
+    v-model="isShow"
+    @cancel="isShow=false"
+    :width="960">
+    <a-spin :spinning="spinning" tip="Loading...">
+      <!-- 操作按钮 -->
+      <div class="table-operator">
+        <a-button id="chooseAddressList-add" type="primary" class="button-error" @click="handleEdit()">新增</a-button>
+      </div>
+      <!-- 列表 -->
+      <s-table
+        class="sTable"
+        ref="table"
+        size="small"
+        :rowKey="(record) => record.id"
+        :columns="columns"
+        :data="loadData"
+        :scroll="{ y: 500 }"
+        :showPagination="false"
+        :defaultLoadData="false"
+        bordered>
+        <!-- 收货人 -->
+        <template slot="consignee" slot-scope="text, record">
+          <div class="item-box">
+            <a-tooltip placement="top">
+              <template slot="title">
+                <span>{{ record.consigneeName }}</span>
+              </template>
+              <p class="ellipsis-txt">{{ record.consigneeName }}</p>
+            </a-tooltip>
+            <span v-if="record.defaultFlag==1" class="badge-txt">默认</span>
+          </div>
+        </template>
+        <!-- 操作 -->
+        <template slot="action" slot-scope="text, record">
+          <a-button
+            size="small"
+            type="primary"
+            class="button-success"
+            v-if="record.defaultFlag!=1"
+            @click="handleDefault(record)"
+            id="chooseAddressList-default-btn">设为默认</a-button>
+          <a-button
+            size="small"
+            type="primary"
+            class="button-info"
+            @click="handleEdit(record)"
+            id="chooseAddressList-edit-btn"
+          >编辑</a-button>
+          <a-button
+            size="small"
+            type="primary"
+            class="button-error"
+            @click="handleDel(record)"
+            id="chooseAddressList-del-btn"
+          >删除</a-button>
+        </template>
+        <!-- 选择 -->
+        <template slot="choose" slot-scope="text, record">
+          <a-button
+            size="small"
+            type="primary"
+            class="button-primary"
+            @click="handleChoose(record)"
+            id="chooseAddressList-choose-btn">选择</a-button>
+        </template>
+      </s-table>
+    </a-spin>
+    <!-- 新增/编辑地址 -->
+    <edit-address-modal ref="addrModal" :openModal="openAddrModal" :paramsData="paramsData" @ok="handleOk" @close="openAddrModal=false" />
+  </a-modal>
+</template>
+
+<script>
+import { commonMixin } from '@/utils/mixin'
+import { STable, VSelect } from '@/components'
+import editAddressModal from './editAddressModal'
+import { dealerRecevieAddrQuery, dealerRecevieAddrSet, dealerRecevieAddrDel } from '@/api/dealerRecevieAddr'
+export default {
+  name: 'ChooseAddressModal',
+  mixins: [commonMixin],
+  components: { STable, VSelect, editAddressModal },
+  props: {
+    openModal: { //  弹框显示状态
+      type: Boolean,
+      default: false
+    },
+    paramsData: {
+      type: String || Number,
+      default: ''
+    }
+  },
+  data () {
+    return {
+      spinning: false,
+      isShow: this.openModal, //  是否打开弹框
+      // 表头
+      columns: [
+        { title: '序号', dataIndex: 'no', width: 50, align: 'center' },
+        { title: '收货人', scopedSlots: { customRender: 'consignee' }, align: 'center', ellipsis: true },
+        { title: '手机号码', dataIndex: 'consigneeTel', width: 230, align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '收货地址', dataIndex: 'address', width: 400, align: 'center', customRender: function (text) { return text || '--' }, ellipsis: true },
+        // { title: '操作', scopedSlots: { customRender: 'action' }, width: 200, align: 'center', fixed: 'right' },
+        { title: '选择', scopedSlots: { customRender: 'choose' }, width: 80, align: 'center', fixed: 'right' }
+      ],
+      // 加载数据方法 必须为 Promise 对象
+      loadData: parameter => {
+        this.disabled = true
+        return dealerRecevieAddrQuery({ dealerSn: this.paramsData }).then(res => {
+          let data
+          if (res.status == 200) {
+            data = res.data
+            const no = 0
+            for (var i = 0; i < data.length; i++) {
+              data[i].no = no + i + 1
+              const provinceName = data[i].provinceName ? (data[i].provinceName + '-') : ''
+              const cityName = data[i].cityName ? (data[i].cityName + '-') : ''
+              const countyName = data[i].countyName ? (data[i].countyName + '-') : ''
+              const addr = data[i].addr || ''
+              data[i].address = provinceName + cityName + countyName + addr
+            }
+            this.disabled = false
+          }
+          return data
+        })
+      },
+      openAddrModal: false // 选择地址弹框是否显示
+    }
+  },
+  methods: {
+    //  设为默认
+    handleDefault (row) {
+      this.spinning = true
+      dealerRecevieAddrSet({ id: row.id }).then(res => {
+        if (res.status == 200) {
+          this.$message.success(res.message)
+          this.$refs.table.refresh(true)
+          this.spinning = false
+        } else {
+          this.spinning = false
+        }
+      })
+    },
+    //  新增/编辑收货地址
+    handleEdit (row) {
+      if (row) {
+        this.$refs.addrModal.setData({
+          id: row.id,
+          consigneeName: row.consigneeName,
+          consigneeTel: row.consigneeTel,
+          provinceSn: row.provinceSn,
+          provinceName: row.provinceName,
+          citySn: row.citySn,
+          cityName: row.cityName,
+          countySn: row.countySn,
+          countyName: row.countyName,
+          addr: row.addr
+        })
+      }
+      this.openAddrModal = true
+    },
+    //  选择
+    handleChoose (row) {
+      this.$emit('ok', row)
+    },
+    //  删除
+    handleDel (row) {
+      const _this = this
+      this.$confirm({
+        title: '提示',
+        content: '删除后不可恢复,确定要进行删除吗?',
+        centered: true,
+        onOk () {
+          _this.spinning = true
+          dealerRecevieAddrDel({
+            id: row.id
+          }).then(res => {
+            if (res.status == 200) {
+              _this.$message.success(res.message)
+              _this.$emit('verify', row.id)
+              _this.$refs.table.refresh(true)
+              _this.spinning = false
+            } else {
+              _this.spinning = false
+            }
+          })
+        }
+      })
+    },
+    //  地址保存成功
+    handleOk (data) {
+      this.$refs.table.refresh(true)
+    }
+  },
+  watch: {
+    //  父页面传过来的弹框状态
+    openModal (newValue, oldValue) {
+      this.isShow = newValue
+    },
+    //  重定义的弹框状态
+    isShow (newValue, oldValue) {
+      if (!newValue) {
+        this.$emit('close')
+      } else {
+        const _this = this
+        setTimeout(() => {
+          _this.$refs.table.refresh(true)
+        }, 300)
+      }
+    }
+  }
+}
+</script>
+
+<style lang="less" scoped>
+  .chooseAddressList-modal{
+    .table-operator{
+      margin-bottom: 10px;
+    }
+    .item-box{
+      position: relative;
+      display: flex;
+      align-items: center;
+      .ellipsis-txt{
+        margin: 0;
+        width: 100%;
+        overflow: hidden;
+        text-overflow:ellipsis;
+        whitewhite-space: nowrap;
+      }
+      .badge-txt{
+        line-height: 20px;
+        padding: 0 7px;
+        font-size: 12px;
+        background-color: #fff;
+        color: #ed1c24;
+        border-color: #ed1c24;
+        border-radius: 20px;
+        box-shadow: 0 0 0 1px #d9d9d9 inset;
+      }
+    }
+  }
+</style>

Niektoré súbory nie sú zobrazené, pretože je v týchto rozdielových dátach zmenené mnoho súborov