소스 검색

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

李磊 2 년 전
부모
커밋
3219ffec4b
100개의 변경된 파일5812개의 추가작업 그리고 1640개의 파일을 삭제
  1. 208 5
      package-lock.json
  2. 8 5
      package.json
  3. BIN
      public/templ/费用明细模板.xlsx
  4. 1 1
      public/version.json
  5. 164 0
      src/api/bizuser.js
  6. 22 1
      src/api/data.js
  7. 13 2
      src/api/dealer.js
  8. 24 1
      src/api/dealerRelation.js
  9. 9 0
      src/api/expenseManagement.js
  10. 24 1
      src/api/financeBook.js
  11. 21 0
      src/api/mqmsg.js
  12. 258 25
      src/api/reportData.js
  13. 30 7
      src/api/salesBillReport.js
  14. 61 16
      src/api/subarea.js
  15. 0 82
      src/components/Editor/QuillEditor.vue
  16. 0 57
      src/components/Editor/WangEditor.vue
  17. 121 123
      src/components/WEeditor/editor.vue
  18. 39 21
      src/components/index.less
  19. 287 55
      src/config/router.config.js
  20. 17 6
      src/layouts/BasicLayout.vue
  21. 1 3
      src/layouts/BigScreen.vue
  22. 2 2
      src/layouts/PageView.vue
  23. 1 0
      src/layouts/index.js
  24. 60 25
      src/libs/JGPrint.js
  25. 1 1
      src/libs/getDate.js
  26. 10 0
      src/libs/tools.js
  27. 0 2
      src/libs/types.js
  28. 0 1
      src/main.js
  29. 1 1
      src/permission.js
  30. 4 1
      src/store/getters.js
  31. 1 1
      src/store/index.js
  32. 13 2
      src/store/modules/app.js
  33. 1 1
      src/utils/domUtil.js
  34. 1 1
      src/utils/filter.js
  35. 3 0
      src/utils/mixin.js
  36. 17 5
      src/utils/request.js
  37. 104 0
      src/utils/util.js
  38. 22 55
      src/views/Home.vue
  39. 34 10
      src/views/allocationManagement/matchSendOutOrder/list.vue
  40. 15 7
      src/views/allocationManagement/transferOut/basicInfoModal.vue
  41. 18 15
      src/views/allocationManagement/transferOut/detail.vue
  42. 10 1
      src/views/allocationManagement/transferOut/dsModal.vue
  43. 20 22
      src/views/allocationManagement/transferOut/edit.vue
  44. 22 12
      src/views/allocationManagement/transferOut/list.vue
  45. 23 5
      src/views/allocationManagement/transferOut/printModal.vue
  46. 11 2
      src/views/allocationManagement/transferReturn/basicInfoModal.vue
  47. 5 2
      src/views/allocationManagement/transferReturn/check.vue
  48. 15 7
      src/views/allocationManagement/transferReturn/detail.vue
  49. 33 21
      src/views/allocationManagement/transferReturn/edit.vue
  50. 6 8
      src/views/allocationManagement/transferReturn/editGrp.vue
  51. 5 2
      src/views/allocationManagement/transferReturn/list.vue
  52. 8 2
      src/views/allocationManagement/transferReturn/print.vue
  53. 7 2
      src/views/allocationManagement/transferReturn/printModal.vue
  54. 66 32
      src/views/allocationManagement/transfersPrint/list.vue
  55. 1 1
      src/views/basicData/warehouse/list.vue
  56. 1 1
      src/views/basicData/warehouse/storingLocation/list.vue
  57. 1 1
      src/views/bigScreen/realTimeSalesReport/center-map.vue
  58. 100 90
      src/views/bnSetting/menu/adminMenus.vue
  59. 0 1
      src/views/bnSetting/menu/storeMenus.vue
  60. 88 0
      src/views/common/areaList.js
  61. 13 83
      src/views/common/chooseCustomerModal.vue
  62. 267 0
      src/views/common/chooseDealer.vue
  63. 16 73
      src/views/common/chooseProductsModal.vue
  64. 1 1
      src/views/common/chooseTypeModal.vue
  65. 4 1
      src/views/common/dingDepartUser.js
  66. 303 0
      src/views/common/pdfViewModal.vue
  67. 5 1
      src/views/common/productType.js
  68. 24 10
      src/views/common/productTypeAll.js
  69. 7 6
      src/views/common/returnReason.js
  70. 2 2
      src/views/common/settleStyle.js
  71. 103 52
      src/views/common/subarea.js
  72. 121 0
      src/views/common/userName.vue
  73. 173 0
      src/views/dealerManagement/businessOwnerSettings/addModal.vue
  74. 322 0
      src/views/dealerManagement/businessOwnerSettings/categorySet.vue
  75. 160 0
      src/views/dealerManagement/businessOwnerSettings/chooseAreaModal.vue
  76. 280 0
      src/views/dealerManagement/businessOwnerSettings/chooseDealer.vue
  77. 211 0
      src/views/dealerManagement/businessOwnerSettings/list.vue
  78. 357 0
      src/views/dealerManagement/businessOwnerSettings/settingsIndex.vue
  79. 221 0
      src/views/dealerManagement/dealerZoneSearch/list.vue
  80. 0 354
      src/views/dealerManagement/marketingDivisionSet/editModal.vue
  81. 185 0
      src/views/dealerManagement/marketingDivisionSetNew/addAreaModal.vue
  82. 177 0
      src/views/dealerManagement/marketingDivisionSetNew/addZoneModal.vue
  83. 84 55
      src/views/dealerManagement/marketingDivisionSetNew/list.vue
  84. 298 0
      src/views/dealerManagement/marketingDivisionSetNew/viewDealers.vue
  85. 17 12
      src/views/dealerManagement/merchantInfoManagement/list.vue
  86. 1 1
      src/views/dealerManagement/merchantInfoManagement/permissionSetting.vue
  87. 2 1
      src/views/dealerManagement/rebateSettings/list.vue
  88. 6 4
      src/views/expenseManagement/expenseReimbursement/add.vue
  89. 32 0
      src/views/expenseManagement/expenseReimbursement/chooseDepartUserModal.vue
  90. 6 4
      src/views/expenseManagement/expenseReimbursement/chooseImportModal.vue
  91. 2 1
      src/views/expenseManagement/expenseReimbursement/department.js
  92. 63 19
      src/views/expenseManagement/expenseReimbursement/detail.vue
  93. 32 24
      src/views/expenseManagement/expenseReimbursement/epenseDetailModal.vue
  94. 5 16
      src/views/expenseManagement/expenseReimbursement/importGuideModal.vue
  95. 128 24
      src/views/expenseManagement/expenseReimbursement/list.vue
  96. 101 119
      src/views/expenseManagement/expenseReimbursement/previewModal.vue
  97. 22 9
      src/views/expenseManagement/expenseReimbursementDetail/list.vue
  98. 4 1
      src/views/financialManagement/allocateReturnConfirmation/detailModal.vue
  99. 5 5
      src/views/financialManagement/allocateReturnConfirmation/list.vue
  100. 14 9
      src/views/financialManagement/collectionDetailStatic/invoiceModal.vue

+ 208 - 5
package-lock.json

@@ -1024,6 +1024,22 @@
         }
       }
     },
+    "@babel/runtime-corejs3": {
+      "version": "7.20.13",
+      "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.20.13.tgz",
+      "integrity": "sha512-p39/6rmY9uvlzRiLZBIB3G9/EBr66LBMcYm7fIDeSBNdRjF2AGD3rFZucUyAgGHC2N+7DdLvVi33uTjSE44FIw==",
+      "requires": {
+        "core-js-pure": "^3.25.1",
+        "regenerator-runtime": "^0.13.11"
+      },
+      "dependencies": {
+        "regenerator-runtime": {
+          "version": "0.13.11",
+          "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz",
+          "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg=="
+        }
+      }
+    },
     "@babel/template": {
       "version": "7.6.0",
       "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.6.0.tgz",
@@ -1251,6 +1267,11 @@
         "@types/node": "*"
       }
     },
+    "@types/json-schema": {
+      "version": "7.0.11",
+      "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz",
+      "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ=="
+    },
     "@types/loader-utils": {
       "version": "1.1.3",
       "resolved": "https://registry.npmjs.org/@types/loader-utils/-/loader-utils-1.1.3.tgz",
@@ -2354,8 +2375,7 @@
     "ajv-keywords": {
       "version": "3.4.1",
       "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.4.1.tgz",
-      "integrity": "sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ==",
-      "dev": true
+      "integrity": "sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ=="
     },
     "align-text": {
       "version": "0.1.4",
@@ -2944,6 +2964,11 @@
         "resolve": "^1.4.0"
       }
     },
+    "babel-plugin-syntax-dynamic-import": {
+      "version": "6.18.0",
+      "resolved": "https://registry.npmjs.org/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz",
+      "integrity": "sha512-MioUE+LfjCEz65Wf7Z/Rm4XCP5k2c+TbMd2Z2JKc7U9uwjBhAfNPE48KC4GTGKhppMeYVepwDBNO/nGY6NYHBA=="
+    },
     "babel-plugin-syntax-object-rest-spread": {
       "version": "6.13.0",
       "resolved": "https://registry.npmjs.org/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz",
@@ -4309,6 +4334,11 @@
         }
       }
     },
+    "comutils": {
+      "version": "1.1.19",
+      "resolved": "https://registry.npmjs.org/comutils/-/comutils-1.1.19.tgz",
+      "integrity": "sha512-JxXB67juILiwhdLwOsYyjUqwWEhHdObI0EClOPk+JDtEuTbac59s0pxGpfCBnNNQ5JommifmcMGneW/4Cg7YWw=="
+    },
     "concat-map": {
       "version": "0.0.1",
       "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
@@ -4612,6 +4642,11 @@
       "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.9.tgz",
       "integrity": "sha512-HOpZf6eXmnl7la+cUdMnLvUxKNqLUzJvgIziQ0DiF3JwSImNphIqdGqzj6hIKyX04MmV0poclQ7+wjWvxQyR2A=="
     },
+    "core-js-pure": {
+      "version": "3.28.0",
+      "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.28.0.tgz",
+      "integrity": "sha512-DSOVleA9/v3LNj/vFxAPfUHttKTzrB2RXhAPvR5TPXn4vrra3Z2ssytvRyt8eruJwAfwAiFADEbrjcRdcvPLQQ=="
+    },
     "core-util-is": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
@@ -13152,6 +13187,16 @@
         "sha.js": "^2.4.8"
       }
     },
+    "pdfjs-dist": {
+      "version": "2.5.207",
+      "resolved": "https://registry.npmjs.org/pdfjs-dist/-/pdfjs-dist-2.5.207.tgz",
+      "integrity": "sha512-xGDUhnCYPfHy+unMXCLCJtlpZaaZ17Ew3WIL0tnSgKFUZXHAPD49GO9xScyszSsQMoutNDgRb+rfBXIaX/lJbw=="
+    },
+    "pdfjs-dist-sign": {
+      "version": "2.5.208",
+      "resolved": "https://registry.npmjs.org/pdfjs-dist-sign/-/pdfjs-dist-sign-2.5.208.tgz",
+      "integrity": "sha512-/bOZqdVkq1vQzCJY0qH/d6vO739VJ6X9mF7UWEWJ2WoZJij1+NOl+qTQxNgpXACp07/fhxC3GE/1+IgeDq40kQ=="
+    },
     "performance-now": {
       "version": "2.1.0",
       "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
@@ -14341,6 +14386,68 @@
         "unpipe": "1.0.0"
       }
     },
+    "raw-loader": {
+      "version": "4.0.2",
+      "resolved": "https://registry.npmjs.org/raw-loader/-/raw-loader-4.0.2.tgz",
+      "integrity": "sha512-ZnScIV3ag9A4wPX/ZayxL/jZH+euYb6FcUinPcgiQW0+UBtEv0O6Q3lGd3cqJ+GHH+rksEv3Pj99oxJ3u3VIKA==",
+      "requires": {
+        "loader-utils": "^2.0.0",
+        "schema-utils": "^3.0.0"
+      },
+      "dependencies": {
+        "ajv": {
+          "version": "6.12.6",
+          "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+          "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+          "requires": {
+            "fast-deep-equal": "^3.1.1",
+            "fast-json-stable-stringify": "^2.0.0",
+            "json-schema-traverse": "^0.4.1",
+            "uri-js": "^4.2.2"
+          }
+        },
+        "ajv-keywords": {
+          "version": "3.5.2",
+          "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz",
+          "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ=="
+        },
+        "emojis-list": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz",
+          "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q=="
+        },
+        "fast-deep-equal": {
+          "version": "3.1.3",
+          "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+          "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
+        },
+        "json5": {
+          "version": "2.2.3",
+          "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
+          "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg=="
+        },
+        "loader-utils": {
+          "version": "2.0.4",
+          "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz",
+          "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==",
+          "requires": {
+            "big.js": "^5.2.2",
+            "emojis-list": "^3.0.0",
+            "json5": "^2.1.2"
+          }
+        },
+        "schema-utils": {
+          "version": "3.1.1",
+          "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz",
+          "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==",
+          "requires": {
+            "@types/json-schema": "^7.0.8",
+            "ajv": "^6.12.5",
+            "ajv-keywords": "^3.5.2"
+          }
+        }
+      }
+    },
     "read-pkg": {
       "version": "1.1.0",
       "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz",
@@ -17254,6 +17361,44 @@
       "resolved": "https://registry.npmjs.org/vue-ls/-/vue-ls-3.2.1.tgz",
       "integrity": "sha512-JoZDpSu0qV5AM50vspEzOut2lcm8R0tr5WG99jMHh14qFXkUes3ZdmDMG/p8iSQVQpg0pd/svGwM9Nd7OI2oaw=="
     },
+    "vue-pdf-signature": {
+      "version": "4.2.7",
+      "resolved": "https://registry.npmjs.org/vue-pdf-signature/-/vue-pdf-signature-4.2.7.tgz",
+      "integrity": "sha512-JPyd46wkY3E8OQZ0VklIco4J2Zo2YsEUz1bfyheDtLd9NaJS0+YYRrfxCotQMLvR1QHNJZmcOsPBZ+5mosHiqQ==",
+      "requires": {
+        "babel-plugin-syntax-dynamic-import": "^6.18.0",
+        "loader-utils": "^1.4.0",
+        "pdfjs-dist-sign": "^2.5.208",
+        "raw-loader": "^4.0.1",
+        "vue-resize-sensor": "^2.0.0",
+        "worker-loader": "^2.0.0"
+      },
+      "dependencies": {
+        "emojis-list": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz",
+          "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q=="
+        },
+        "json5": {
+          "version": "1.0.2",
+          "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz",
+          "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==",
+          "requires": {
+            "minimist": "^1.2.0"
+          }
+        },
+        "loader-utils": {
+          "version": "1.4.2",
+          "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.2.tgz",
+          "integrity": "sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg==",
+          "requires": {
+            "big.js": "^5.2.2",
+            "emojis-list": "^3.0.0",
+            "json5": "^1.0.1"
+          }
+        }
+      }
+    },
     "vue-piczoom": {
       "version": "1.0.6",
       "resolved": "https://registry.npmjs.org/vue-piczoom/-/vue-piczoom-1.0.6.tgz",
@@ -17278,11 +17423,24 @@
       "resolved": "https://registry.npmjs.org/vue-ref/-/vue-ref-2.0.0.tgz",
       "integrity": "sha512-uKNKpFOVeWNqS2mrBZqnpLyXJo5Q+vnkex6JvpENvhXHFNBW/SJTP8vJywLuVT3DpxwXcF9N0dyIiZ4/NpTexQ=="
     },
+    "vue-resize-sensor": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/vue-resize-sensor/-/vue-resize-sensor-2.0.0.tgz",
+      "integrity": "sha512-W+y2EAI/BxS4Vlcca9scQv8ifeBFck56DRtSwWJ2H4Cw1GLNUYxiZxUHHkuzuI5JPW/cYtL1bPO5xPyEXx4LmQ=="
+    },
     "vue-router": {
       "version": "3.1.3",
       "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-3.1.3.tgz",
       "integrity": "sha512-8iSa4mGNXBjyuSZFCCO4fiKfvzqk+mhL0lnKuGcQtO1eoj8nq3CmbEG8FwK5QqoqwDgsjsf1GDuisDX4cdb/aQ=="
     },
+    "vue-seamless-scroll": {
+      "version": "1.1.23",
+      "resolved": "https://registry.npmjs.org/vue-seamless-scroll/-/vue-seamless-scroll-1.1.23.tgz",
+      "integrity": "sha512-HBjUub8WwsKJzbFCrwKPDrZn4e+SSbkKgwWtjKtfLwesiFGwSsVxP44/Z6d3kpXy94qIFOiflJH6l0/9pj7SGA==",
+      "requires": {
+        "comutils": "^1.1.9"
+      }
+    },
     "vue-style-loader": {
       "version": "4.1.2",
       "resolved": "https://registry.npmjs.org/vue-style-loader/-/vue-style-loader-4.1.2.tgz",
@@ -17408,9 +17566,34 @@
       }
     },
     "wangeditor": {
-      "version": "3.1.1",
-      "resolved": "https://registry.npmjs.org/wangeditor/-/wangeditor-3.1.1.tgz",
-      "integrity": "sha1-+9PB1JdpI8nt67hbKdMLNVEq0Dk="
+      "version": "4.7.15",
+      "resolved": "https://registry.npmjs.org/wangeditor/-/wangeditor-4.7.15.tgz",
+      "integrity": "sha512-aPTdREd8BxXVyJ5MI+LU83FQ7u1EPd341iXIorRNYSOvoimNoZ4nPg+yn3FGbB93/owEa6buLw8wdhYnMCJQLg==",
+      "requires": {
+        "@babel/runtime": "^7.11.2",
+        "@babel/runtime-corejs3": "^7.11.2",
+        "tslib": "^2.1.0"
+      },
+      "dependencies": {
+        "@babel/runtime": {
+          "version": "7.20.13",
+          "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.20.13.tgz",
+          "integrity": "sha512-gt3PKXs0DBoL9xCvOIIZ2NEqAGZqHjAnmVbfQtB620V0uReIQutpel14KcneZuer7UioY8ALKZ7iocavvzTNFA==",
+          "requires": {
+            "regenerator-runtime": "^0.13.11"
+          }
+        },
+        "regenerator-runtime": {
+          "version": "0.13.11",
+          "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz",
+          "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg=="
+        },
+        "tslib": {
+          "version": "2.5.0",
+          "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz",
+          "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg=="
+        }
+      }
     },
     "warning": {
       "version": "4.0.3",
@@ -17916,6 +18099,26 @@
         "errno": "~0.1.7"
       }
     },
+    "worker-loader": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/worker-loader/-/worker-loader-2.0.0.tgz",
+      "integrity": "sha512-tnvNp4K3KQOpfRnD20m8xltE3eWh89Ye+5oj7wXEEHKac1P4oZ6p9oTj8/8ExqoSBnk9nu5Pr4nKfQ1hn2APJw==",
+      "requires": {
+        "loader-utils": "^1.0.0",
+        "schema-utils": "^0.4.0"
+      },
+      "dependencies": {
+        "schema-utils": {
+          "version": "0.4.7",
+          "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.4.7.tgz",
+          "integrity": "sha512-v/iwU6wvwGK8HbU9yi3/nhGzP0yGSuhQMzL6ySiec1FSrZZDkhm4noOSWzrNFo/jEc+SJY6jRTwuwbSXJPDUnQ==",
+          "requires": {
+            "ajv": "^6.1.0",
+            "ajv-keywords": "^3.1.0"
+          }
+        }
+      }
+    },
     "wrap-ansi": {
       "version": "2.1.0",
       "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz",

+ 8 - 5
package.json

@@ -15,9 +15,11 @@
   },
   "dependencies": {
     "@antv/data-set": "^0.10.2",
+    "@jiaminghi/data-view": "^2.10.0",
     "ant-design-vue": "^1.7.8",
     "axios": "^0.19.0",
     "core-js": "2.6.9",
+    "echarts": "^5.4.0",
     "enquire.js": "^2.1.6",
     "lodash.get": "^4.4.2",
     "lodash.pick": "^4.4.0",
@@ -33,19 +35,20 @@
     "vue-clipboard2": "^0.2.1",
     "vue-cookies": "^1.6.1",
     "vue-cropper": "0.4.9",
+    "vue-easytable": "^2.24.0",
     "vue-ls": "^3.2.1",
+    "pdfjs-dist": "2.5.207",
+    "vue-pdf-signature": "^4.2.6",
     "vue-piczoom": "^1.0.6",
     "vue-quill-editor": "^3.0.6",
     "vue-router": "^3.1.2",
+    "vue-seamless-scroll": "^1.1.23",
     "vue-svg-component-runtime": "^1.0.1",
+    "vue-tv-focusable": "^2.0.1",
     "vue2.0-zoom": "^2.1.1",
     "vuescroll": "^4.17.3",
     "vuex": "^3.1.1",
-    "wangeditor": "^3.1.1",
-    "@jiaminghi/data-view": "^2.10.0",
-    "echarts": "^5.4.0",
-    "vue-easytable": "^2.24.0",
-    "vue-tv-focusable": "^2.0.1"
+    "wangeditor": "^4.7.15"
   },
   "devDependencies": {
     "@ant-design/colors": "^3.2.1",

BIN
public/templ/费用明细模板.xlsx


+ 1 - 1
public/version.json

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

+ 164 - 0
src/api/bizuser.js

@@ -0,0 +1,164 @@
+import { axios } from '@/utils/request'
+
+//  人员 列表  分页
+export const queryUserList = (params) => {
+  const url = `/bizuser/queryUserList/${params.pageNo}/${params.pageSize}`
+  delete params.pageNo
+  delete params.pageSize
+  return axios({
+    url: url,
+    data: params,
+    method: 'post'
+  })
+}
+// 业务负责人配置列表  分页
+export const queryPage = (params) => {
+  const url = `/bizuser/queryPage/${params.pageNo}/${params.pageSize}`
+  delete params.pageNo
+  delete params.pageSize
+  return axios({
+    url: url,
+    data: params,
+    method: 'post'
+  })
+}
+
+// 业务负责人配置列表   新增/编辑
+export const bizuserSave = params => {
+  return axios({
+    url: '/bizuser/save',
+    data: params,
+    method: 'post'
+  })
+}
+
+// 业务负责人配置列表 删除
+export const bizuserDelete = params => {
+  return axios({
+    url: `/bizuser/delete/${params.id}`,
+    data: {},
+    method: 'get'
+  })
+}
+
+/*
+****  设置管辖范围
+*/
+
+// 设置管辖品类  新增(生成sn)
+export const getNewScopeSn = params => {
+  return axios({
+    url: '/bizuser/scope/getNewScopeSn',
+    data: {},
+    method: 'get'
+  })
+}
+
+// 设置管辖品类
+export const saveProductBrandList = params => {
+  return axios({
+    url: '/bizuser/scope/saveProductBrandList',
+    data: params,
+    method: 'post'
+  })
+}
+
+// 设置管辖品类
+export const saveProductTypeList = params => {
+  return axios({
+    url: '/bizuser/scope/saveProductTypeList',
+    data: params,
+    method: 'post'
+  })
+}
+// 设置管辖品类
+export const bizuserScopeQueryPage = params => {
+  const url = `/bizuser/scope/queryPage/${params.pageNo}/${params.pageSize}`
+  delete params.pageNo
+  delete params.pageSize
+  return axios({
+    url: url,
+    data: params,
+    method: 'post'
+  })
+}
+// 设置管辖品类  删除整列
+export const bizuserScopeDelete = params => {
+  return axios({
+    url: `/bizuser/scope/delete/${params.id}`,
+    data: {},
+    method: 'get'
+  })
+}
+// 设置管辖品类  删除产品品牌
+export const deleteProductBrand = params => {
+  return axios({
+    url: `/bizuser/scope/detail/deleteProductBrand/${params.id}`,
+    data: {},
+    method: 'get'
+  })
+}
+// 设置管辖品类  删除产品分类
+export const deleteProductType = params => {
+  return axios({
+    url: `/bizuser/scope/detail/deleteProductType/${params.id}`,
+    data: {},
+    method: 'get'
+  })
+}
+
+// 查询用户信息
+export const findById = params => {
+  return axios({
+    url: `/bizuser/findById/${params.id}`,
+    data: {},
+    method: 'get'
+  })
+}
+
+// 查询区域回显列表
+export const queryAreaScope = params => {
+  return axios({
+    url: '/bizuser/scope/queryAreaScope',
+    data: params,
+    method: 'post'
+  })
+}
+
+// 保存区域
+export const saveAreaScope = params => {
+  return axios({
+    url: '/bizuser/scope/saveAreaScope',
+    data: params,
+    method: 'post'
+  })
+}
+
+// 查询经销商回显列表
+export const queryDealerScope = params => {
+  return axios({
+    url: '/bizuser/scope/queryDealerScope',
+    data: params,
+    method: 'post'
+  })
+}
+// 保存经销商
+export const saveDealerScope = params => {
+  return axios({
+    url: '/bizuser/scope/saveDealerScope',
+    data: params,
+    method: 'post'
+  })
+}
+
+// 经销商列表  (选择过的优先显示)
+export const bizuserScopeQueryDealer = (params) => {
+  const url = `/bizuser/scope/queryDealer/${params.pageNo}/${params.pageSize}`
+  delete params.pageNo
+  delete params.pageSize
+  return axios({
+    url: url,
+    data: params,
+    method: 'post'
+  })
+}

+ 22 - 1
src/api/data.js

@@ -8,6 +8,16 @@ export function login (parameter) {
   })
 }
 
+// 默认参数 
+export const getDefaultCofig = (params) => {
+  const url = `/sysParamsConfig/findByCode/${params.code}`
+  return axios({
+    url: url,
+    data: params,
+    method: 'post'
+  })
+}
+
 export const listLookUp = params => {
   const url = `/lookup/queryLike`
   return axios({
@@ -32,7 +42,18 @@ export const getAreaAll = () => {
   return axios({
     url: '/area/findAll',
     method: 'get'
-  }).then(res => res.data)
+  })
+}
+
+export const uploadFile = (params) => {
+  return axios({
+    url: '/upload',
+    method: 'post',
+    data: params,
+    headers: {
+      'Content-Type': 'multipart/form-data'
+    }
+  })
 }
 
 /**

+ 13 - 2
src/api/dealer.js

@@ -16,7 +16,18 @@ export const dealerFindUpdateInfoBySn = (params) => {
     method: 'get'
   })
 }
-//  经销商列表有分页
+// 为分区绑定经销商查询经销商列表
+export const queryDealerPageList = (params) => {
+  const url = `/dealer/queryDealerPage/${params.pageNo}/${params.pageSize}`
+  delete params.pageNo
+  delete params.pageSize
+  return axios({
+    url: url,
+    data: params,
+    method: 'post'
+  })
+}
+//  经销商列表有分页,不受权限控制
 export const dealerQueryList = (params) => {
   const url = `/dealer/queryPage/${params.pageNo}/${params.pageSize}`
   delete params.pageNo
@@ -27,7 +38,7 @@ export const dealerQueryList = (params) => {
     method: 'post'
   })
 }
-//  经销商 列表 有分页
+//  经销商 列表 有分页, 有权限控制
 export const dealerSubareaScopeList = (params) => {
   const url = `/dealer/queryBySubareaScope/${params.pageNo}/${params.pageSize}`
   delete params.pageNo

+ 24 - 1
src/api/dealerRelation.js

@@ -54,4 +54,27 @@ export const updateRebate = (params) => {
     url: `/dealerRelation/updateRebate/${params.dealerSn}/${params.rebateDealerSn}`,
     method: 'get'
   })
-}
+}
+
+// 经销商所属分区  列表
+export const queryDealerWithBizuser = (params) => {
+  const url = `/subareaAreaDealer/queryDealerWithBizuser/${params.pageNo}/${params.pageSize}`
+  delete params.pageNo
+  delete params.pageSize
+  return axios({
+    url: url,
+    data: params,
+    method: 'post'
+  })
+}
+
+// 经销商所属分区  导出
+export const exportDealerWithBizuser = params => {
+  const url = `/subareaAreaDealer/exportDealerWithBizuser`
+  return axios.request({
+    url: url,
+    data: params,
+    method: 'post',
+    responseType: 'blob'
+  })
+}

+ 9 - 0
src/api/expenseManagement.js

@@ -28,6 +28,15 @@ export const expenseAccountList = (params) => {
     method: 'post'
   })
 }
+// 批量更新打印状态
+export const expenseAccountUpdateBatch = (params) => {
+  const url = `/expenseAccount/updateBatch`
+  return axios({
+    url: url,
+    data: params,
+    method: 'post'
+  })
+}
 // 新增再次编辑
 export const expenseAccountAgainEdit = (params) => {
   const url = `/expenseAccount/againEdit/${params.expenseAccountSn} `

+ 24 - 1
src/api/financeBook.js

@@ -11,7 +11,22 @@ export const financeBookQueryPage = (params) => {
     method: 'post'
   })
 }
-
+// 检查是否已打印
+export const checkPrintStatus = (params) => {
+  return axios({
+    url: `/financeBook/detail/checkPrintStatus `,
+    data: params,
+    method: 'post'
+  })
+}
+// 获取最新一次钉钉审核人员信息
+export const queryLastFinishDingUser = (params) => {
+  return axios({
+    url: `/financeBook/queryLastFinishDingUser`,
+    data: params,
+    method: 'post'
+  })
+}
 // 统计
 export const financeBookQueryCount = (params) => {
   return axios({
@@ -20,6 +35,14 @@ export const financeBookQueryCount = (params) => {
     method: 'post'
   })
 }
+// 批量修改打印状态
+export const financeBookDetailUpdateBatch = (params) => {
+  return axios({
+    url: `/financeBook/detail/updateBatch`,
+    data: params,
+    method: 'post'
+  })
+}
 // 财务收款明细-分页列表
 export const financeBookDetailList = (params) => {
   const url = `/financeBook/detail/queryPage/${params.pageNo}/${params.pageSize}`

+ 21 - 0
src/api/mqmsg.js

@@ -0,0 +1,21 @@
+import { axios } from '@/utils/request'
+
+//  erp数据同步记录 列表  有分页
+export const queryReceivePage = (params) => {
+  const url = `/mqmsg/queryReceivePage/${params.pageNo}/${params.pageSize}`
+  delete params.pageNo
+  delete params.pageSize
+  return axios({
+    url: url,
+    data: params,
+    method: 'post'
+  })
+}
+//  erp数据同步记录 重新同步
+export const handle = (params) => {
+  const url = `/mqmsg/handle/${params.id}`
+  return axios({
+    url: url,
+    method: 'get'
+  })
+}

+ 258 - 25
src/api/reportData.js

@@ -1,8 +1,15 @@
 import { axios } from '@/utils/request'
-
+// 获取开单退货单表头
+export const salesReportReturnTitle = (params) => {
+  return axios({
+    url: '/report/salesReturnBillReport/reportTitle',
+    data: params,
+    method: 'get'
+  })
+}
 //  开单退货单报表
 export const salesReportReturnBillList = (params) => {
-  const url = `/report/salesReturnBillReport/returnBillQueryPage/${params.pageNo}/${params.pageSize}`
+  const url = `/report/salesReturnBillReport/reportPage/${params.pageNo}/${params.pageSize}`
   delete params.pageNo
   delete params.pageSize
   return axios({
@@ -14,14 +21,23 @@ export const salesReportReturnBillList = (params) => {
 //  开单退货单报表  合计
 export const salesReportReturnBillCount = (params) => {
   return axios({
-    url: '/report/salesReturnBillReport/returnBillQuerySum',
+    url: '/report/salesReturnBillReport/reportCount',
     data: params,
     method: 'post'
   })
 }
-//  开单退货报表
+
+// 获取开单退货表头
+export const salesReturnReportTitle = (params) => {
+  return axios({
+    url: '/report/salesReturnReport/reportTitle',
+    data: params,
+    method: 'get'
+  })
+}
+//  开单退货报表 列表
 export const salesReportReturnList = (params) => {
-  const url = `/report/salesReturnBillReport/returnQueryPage/${params.pageNo}/${params.pageSize}`
+  const url = `/report/salesReturnReport/reportPage/${params.pageNo}/${params.pageSize}`
   delete params.pageNo
   delete params.pageSize
   return axios({
@@ -33,14 +49,23 @@ export const salesReportReturnList = (params) => {
 //  开单退货报表  合计
 export const salesReportReturnCount = (params) => {
   return axios({
-    url: '/report/salesReturnBillReport/returnQuerySum',
+    url: '/report/salesReturnReport/reportCount',
     data: params,
     method: 'post'
   })
 }
+
+// 实售退货报表 biao题
+export const salesReportReturnRebateTitle = (params) => {
+  return axios({
+    url: '/report/returnSsthReport/reportTitle',
+    data: params,
+    method: 'get'
+  })
+}
 //  实售退货报表
 export const salesReportReturnRebateList = (params) => {
-  const url = `/report/salesReturnBillReport/returnRebateQueryPage/${params.pageNo}/${params.pageSize}`
+  const url = `/report/returnSsthReport/reportPage/${params.pageNo}/${params.pageSize}`
   delete params.pageNo
   delete params.pageSize
   return axios({
@@ -52,7 +77,7 @@ export const salesReportReturnRebateList = (params) => {
 //  实售退货报表  合计
 export const salesReportReturnRebateCount = (params) => {
   return axios({
-    url: '/report/salesReturnBillReport/returnRebateQuerySum',
+    url: '/report/returnSsthReport/reportCount',
     data: params,
     method: 'post'
   })
@@ -181,7 +206,7 @@ export const salesReturnDetailExport = (params) => {
 // 开单销售单 导出
 export const salesSlipExport = (params) => {
   return axios({
-    url: '/report/salesBillReport/export',
+    url: '/report/salesKdxxd/reportExport',
     data: params,
     method: 'post',
     responseType: 'blob'
@@ -190,7 +215,7 @@ export const salesSlipExport = (params) => {
 // 开单退货单 导出
 export const returnSlipExport = (params) => {
   return axios({
-    url: 'report/salesReturnBillReport/returnBillExportExcel',
+    url: 'report/salesReturnBillReport/reportExport',
     data: params,
     method: 'post',
     responseType: 'blob'
@@ -199,7 +224,7 @@ export const returnSlipExport = (params) => {
 // 开单销售 导出
 export const salesAmountExport = (params) => {
   return axios({
-    url: '/report/salesBillReport/queryGroupByBuyerExportExcel',
+    url: '/report/salesKdxx/reportExport',
     data: params,
     method: 'post',
     responseType: 'blob'
@@ -208,7 +233,7 @@ export const salesAmountExport = (params) => {
 // 实售销售 导出
 export const actualSalesExport = (params) => {
   return axios({
-    url: '/report/salesBillReport/totalRealExportExcel',
+    url: '/report/salesSsxs/reportExport',
     data: params,
     method: 'post',
     responseType: 'blob'
@@ -217,7 +242,7 @@ export const actualSalesExport = (params) => {
 // 开单退货 导出
 export const billingReturnExport = (params) => {
   return axios({
-    url: '/report/salesReturnBillReport/returnExportExcel',
+    url: '/report/salesReturnReport/reportExport',
     data: params,
     method: 'post',
     responseType: 'blob'
@@ -226,7 +251,7 @@ export const billingReturnExport = (params) => {
 // 实售退货 导出
 export const salesReturnExport = (params) => {
   return axios({
-    url: '/report/salesReturnBillReport/returnRebateExportExcel',
+    url: '/report/returnSsthReport/reportExport',
     data: params,
     method: 'post',
     responseType: 'blob'
@@ -344,9 +369,17 @@ export const reportStockPutDetailExport = (params) => {
     responseType: 'blob'
   })
 }
+// 获取销售交单报表 表头
+export const salesXsjdReportTitle = (params) => {
+  return axios({
+    url: '/report/salesXsjd/reportTitle',
+    data: params,
+    method: 'get'
+  })
+}
 //  销售交单报表
 export const reportDispatchReportList = (params) => {
-  const url = `/report/dispatchReport/xsjd/queryPage/${params.pageNo}/${params.pageSize}`
+  const url = `/report/salesXsjd/reportPage/${params.pageNo}/${params.pageSize}`
   delete params.pageNo
   delete params.pageSize
   return axios({
@@ -358,7 +391,7 @@ export const reportDispatchReportList = (params) => {
 //  销售交单报表  合计
 export const reportDispatchReportCount = (params) => {
   return axios({
-    url: '/report/dispatchReport/xsjd/total',
+    url: '/report/salesXsjd/reportCount',
     data: params,
     method: 'post'
   })
@@ -366,7 +399,7 @@ export const reportDispatchReportCount = (params) => {
 // 销售交单报表 导出
 export const reportDispatchReportExport = (params) => {
   return axios({
-    url: '/report/dispatchReport/xsjd/export',
+    url: '/report/salesXsjd/reportExport',
     data: params,
     method: 'post',
     responseType: 'blob'
@@ -400,9 +433,17 @@ export const reportAllocateDbjdReportExport = (params) => {
     responseType: 'blob'
   })
 }
-//  退货交单报表
+// 获取退货交单报表 表头
+export const returnDocReportTitle = (params) => {
+  return axios({
+    url: '/report/returnDocReport/reportTitle',
+    data: params,
+    method: 'get'
+  })
+}
+//  退货交单报表 列表
 export const reportSalesReturnThjdReportList = (params) => {
-  const url = `/report/salesReturnBillReport/thjd/queryPage/${params.pageNo}/${params.pageSize}`
+  const url = `/report/returnDocReport/reportPage/${params.pageNo}/${params.pageSize}`
   delete params.pageNo
   delete params.pageSize
   return axios({
@@ -414,7 +455,7 @@ export const reportSalesReturnThjdReportList = (params) => {
 //  退货交单报表  合计
 export const reportSalesReturnThjdReportCount = (params) => {
   return axios({
-    url: '/report/salesReturnBillReport/thjd/querySum',
+    url: '/report/returnDocReport/reportCount',
     data: params,
     method: 'post'
   })
@@ -422,7 +463,7 @@ export const reportSalesReturnThjdReportCount = (params) => {
 // 退货交单报表 导出
 export const reportSalesReturnThjdReportExport = (params) => {
   return axios({
-    url: '/report/salesReturnBillReport/thjd/export',
+    url: '/report/returnDocReport/reportExport',
     data: params,
     method: 'post',
     responseType: 'blob'
@@ -431,15 +472,24 @@ export const reportSalesReturnThjdReportExport = (params) => {
 // 全国各省类销售明细报表
 export const realReportSalesByProvince = (params) => {
   return axios({
-    url: '/report/realReportSales/queryListByProvince',
+    url: '/report/realReportSales/subareaArea/reportList',
     data: params,
     method: 'post'
   })
 }
+// 标题
+export const subareaAreaReportTitle = (params) => {
+  const url = `/report/realReportSales/subareaArea/reportTitle `
+  return axios({
+    url: url,
+    data: params,
+    method: 'get'
+  })
+}
 // 导出
 export const realReportSalesByProvinceExport = (params) => {
   return axios({
-    url: '/report/realReportSales/exportByProvince',
+    url: '/report/realReportSales/subareaArea/reportExport',
     data: params,
     method: 'post',
     responseType: 'blob'
@@ -448,20 +498,30 @@ export const realReportSalesByProvinceExport = (params) => {
 // 全国各区类销售明细报表
 export const realReportSalesBySubArea = (params) => {
   return axios({
-    url: '/report/realReportSales/queryListBySubArea',
+    url: '/report/realReportSales/subarea/reportList',
     data: params,
     method: 'post'
   })
 }
+// 标题
+export const subareaReportTitle = (params) => {
+  const url = `/report/realReportSales/subarea/reportTitle`
+  return axios({
+    url: url,
+    data: params,
+    method: 'get'
+  })
+}
 // 导出
 export const realReportSalesBySubAreaExport = (params) => {
   return axios({
-    url: '/report/realReportSales/exportBySubArea',
+    url: '/report/realReportSales/subarea/reportExport',
     data: params,
     method: 'post',
     responseType: 'blob'
   })
 }
+
 // 调拨退货单报表
 export const allocateReturnReportQueryPage = (params) => {
   const url = `/report/allocateReturnReport/queryPage/${params.pageNo}/${params.pageSize}`
@@ -646,3 +706,176 @@ export const sparePartsReturnReportExportDetail = (params) => {
     responseType: 'blob'
   })
 }
+
+// 返利报表
+export const rebateQueryList = (params) => {
+  const url = `/rebate/queryPage/${params.pageNo}/${params.pageSize}`
+  delete params.pageNo
+  delete params.pageSize
+  return axios({
+    url: url,
+    data: params,
+    method: 'post'
+  })
+}
+// 合计
+export const rebateQueryCount = (params) => {
+  const url = `/rebate/queryCount`
+  return axios({
+    url: url,
+    data: params,
+    method: 'post'
+  })
+}
+// 返利明细报表
+export const rebateDetailQueryList = (params) => {
+  const url = `/rebate/detail/queryPage/${params.pageNo}/${params.pageSize}`
+  delete params.pageNo
+  delete params.pageSize
+  return axios({
+    url: url,
+    data: params,
+    method: 'post'
+  })
+}
+// 返利明细报表统计
+export const rebateDetailQueryCount = (params) => {
+  const url = `/rebate/detail/queryCount`
+  return axios({
+    url: url,
+    data: params,
+    method: 'post'
+  })
+}
+
+/*
+** 开单采退报表
+*/
+
+// 开单采退报表 列表
+export const querySupplierPage = (params) => {
+  const url = `/report/sparePartsReturn/querySupplierPage/${params.pageNo}/${params.pageSize}`
+  delete params.pageNo
+  delete params.pageSize
+  return axios({
+    url: url,
+    data: params,
+    method: 'post'
+  })
+}
+// 开单采退报表 合计
+export const querySupplierCount = (params) => {
+  const url = `/report/sparePartsReturn/querySupplierCount`
+  return axios({
+    url: url,
+    data: params,
+    method: 'post'
+  })
+}
+// 开单采退报表 标题
+export const querySupplierTitle = (params) => {
+  const url = `/report/sparePartsReturn/querySupplierTitle`
+  return axios({
+    url: url,
+    data: params,
+    method: 'get'
+  })
+}
+// 开单采退报表 导出
+export const supplierExport = (params) => {
+  return axios({
+    url: '/report/sparePartsReturn/supplierExport',
+    data: params,
+    method: 'post',
+    responseType: 'blob'
+  })
+}
+// 开单采退dan报表 列表
+export const queryBillNoPage = (params) => {
+  const url = `/report/sparePartsReturn/queryBillNoPage/${params.pageNo}/${params.pageSize}`
+  delete params.pageNo
+  delete params.pageSize
+  return axios({
+    url: url,
+    data: params,
+    method: 'post'
+  })
+}
+// 开单采退dan报表 合计
+export const queryBillNoCount = (params) => {
+  const url = `/report/sparePartsReturn/queryBillNoCount`
+  return axios({
+    url: url,
+    data: params,
+    method: 'post'
+  })
+}
+// 开单采退dan报表 标题
+export const queryBillNoTitle = (params) => {
+  const url = `/report/sparePartsReturn/queryBillNoTitle`
+  return axios({
+    url: url,
+    data: params,
+    method: 'get'
+  })
+}
+// 开单采退dan报表 导出
+export const billNoExport = (params) => {
+  return axios({
+    url: '/report/sparePartsReturn/BillNoExport',
+    data: params,
+    method: 'post',
+    responseType: 'blob'
+  })
+}
+
+/*
+**   收发存报表
+*/
+// 收发存报表  明细列表
+export const queryDetailReportPage = (params) => {
+  const url = `/report/reportStockPsi/queryDetailReportPage/${params.pageNo}/${params.pageSize}`
+  delete params.pageNo
+  delete params.pageSize
+  return axios({
+    url: url,
+    data: params,
+    method: 'post'
+  })
+}
+// 收发存报表  导出
+export const exportDetailReport = (params) => {
+  return axios({
+    url: '/report/reportStockPsi/exportReport',
+    data: params,
+    method: 'post',
+    responseType: 'blob'
+  })
+}
+// 收发存报表  汇总列表
+export const queryGroupByprodTypeReportPage = (params) => {
+  const url = `/report/reportStockPsi/queryGroupByProdTypeReport`
+  return axios({
+    url: url,
+    data: params,
+    method: 'post'
+  })
+}
+// 收发存报表  进销存合计统计
+export const queryReportCount = (params) => {
+  const url = `/report/reportStockPsi/queryReportCount`
+  return axios({
+    url: url,
+    data: params,
+    method: 'post'
+  })
+}
+// // 收发存报表  汇总导出
+// export const exportGroupByProductTypeReport = (params) => {
+//   return axios({
+//     url: '/report/reportStockPsi/exportGroupByProductTypeReport',
+//     data: params,
+//     method: 'post',
+//     responseType: 'blob'
+//   })
+// }

+ 30 - 7
src/api/salesBillReport.js

@@ -9,9 +9,25 @@ export const salesDetailExport = (params) => {
     responseType: 'blob'
   })
 }
+// 获取开单销售dan报表 表头
+export const salesKdxxdReportTitle = (params) => {
+  return axios({
+    url: '/report/salesKdxxd/reportTitle',
+    data: params,
+    method: 'get'
+  })
+}
+// 获取开单销售报表 表头
+export const salesKdxxReportTitle = (params) => {
+  return axios({
+    url: '/report/salesKdxx/reportTitle',
+    data: params,
+    method: 'get'
+  })
+}
 //  开单销售单报表   列表  有分页
 export const salesBillReportList = (params) => {
-  const url = `/report/salesBillReport/queryPage/${params.pageNo}/${params.pageSize}`
+  const url = `/report/salesKdxxd/reportPage/${params.pageNo}/${params.pageSize}`
   delete params.pageNo
   delete params.pageSize
   return axios({
@@ -23,7 +39,7 @@ export const salesBillReportList = (params) => {
 
 //  开单销售报表   列表  有分页
 export const salesBillReportGroupByBuyerList = (params) => {
-  const url = `/report/salesBillReport/queryPageGroupByBuyer/${params.pageNo}/${params.pageSize}`
+  const url = `/report/salesKdxx/reportPage/${params.pageNo}/${params.pageSize}`
   delete params.pageNo
   delete params.pageSize
   return axios({
@@ -36,7 +52,7 @@ export const salesBillReportGroupByBuyerList = (params) => {
 //  开单销售单报表合计
 export const salesBillReportCount = (params) => {
   return axios({
-    url: '/report/salesBillReport/totalSaleAmount',
+    url: '/report/salesKdxxd/reportCount',
     data: params,
     method: 'post'
   })
@@ -45,15 +61,22 @@ export const salesBillReportCount = (params) => {
 //  开单销售报表合计
 export const salesBillReportCountByBuyer = (params) => {
   return axios({
-    url: '/report/salesBillReport/totalGroupByBuyer',
+    url: '/report/salesKdxx/reportCount',
     data: params,
     method: 'post'
   })
 }
-
+// 实售销售报表 biao头
+export const salesBillRealReportTitle = (params) => {
+  return axios({
+    url: '/report/salesSsxs/reportTitle',
+    data: params,
+    method: 'get'
+  })
+}
 // 实售销售报表
 export const salesBillRealAmountQueryPageList = (params) => {
-  const url = `/report/salesBillReport/realAmountQueryPageGroupByBuyer/${params.pageNo}/${params.pageSize}`
+  const url = `/report/salesSsxs/reportPage/${params.pageNo}/${params.pageSize}`
   delete params.pageNo
   delete params.pageSize
   return axios({
@@ -66,7 +89,7 @@ export const salesBillRealAmountQueryPageList = (params) => {
 //  实售销售报表   合计
 export const salesBillRealReportCount = (params) => {
   return axios({
-    url: '/report/salesBillReport/totalRealAmount',
+    url: '/report/salesSsxs/reportCount',
     data: params,
     method: 'post'
   })

+ 61 - 16
src/api/subarea.js

@@ -1,41 +1,86 @@
 import { axios } from '@/utils/request'
 
-//  查询所有分区
+//  查询区域分区信息
 export const subareaQueryAll = (params) => {
   return axios({
     url: `/subarea/queryAll`,
     method: 'get'
   })
 }
-
-// 查询包含区域的所有分区
-export const subareaQueryIncludeAreaAll = (params) => {
+// 查询区域
+export const subareaQuerySubarea = (params) => {
+  return axios({
+    url: `/subarea/querySubarea`,
+    data: params,
+    method: 'post'
+  })
+}
+// 保存区域信息
+export const subareaSaveSubarea = (params) => {
   return axios({
-    url: `/subarea/queryIncludeAreaAll`,
+    url: `/subarea/saveSubarea`,
+    data: params,
+    method: 'post'
+  })
+}
+// 查询区域下分区信息
+export const subareaQuerySubareaArea = (params) => {
+  return axios({
+    url: `/subarea/querySubareaArea`,
+    data: params,
+    method: 'post'
+  })
+}
+// 保存分区信息
+export const subareaSaveSubareaArea = (params) => {
+  return axios({
+    url: `/subarea/saveSubareaArea`,
+    data: params,
+    method: 'post'
+  })
+}
+// 根据sn删除区域信息
+export const deleteSubareaBySn = (params) => {
+  return axios({
+    url: `/subarea/deleteSubarea/${params.sn}`,
     method: 'get'
   })
 }
-
-// 根据sn删除分区信息
-export const subareaDeleteBySn = (params) => {
+//  根据sn删除分区信息
+export const deleteSubareaAreaBySn = (params) => {
   return axios({
-    url: `/subarea/deleteBySn/${params.sn}`,
+    url: `/subarea/deleteSubareaArea/${params.sn}`,
     method: 'get'
   })
 }
 
-// 根据分区sn查询选中分区
-export const subareaFindBySn = (params) => {
+// 分区批量绑定经销商
+export const batchBindDealer = (params) => {
+  return axios({
+    url: `/subareaAreaDealer/batchBind`,
+    data: params,
+    method: 'post'
+  })
+}
+// 分区绑定经销商
+export const bindDealer = (params) => {
   return axios({
-    url: `/subarea/findBySn/${params.sn}`,
+    url: `/subareaAreaDealer/bind`,
+    data: params,
+    method: 'post'
+  })
+}
+// 删除绑定关系
+export const deleteBindDealer = (params) => {
+  return axios({
+    url: `/subareaAreaDealer/deleteBind/${params.sn}`,
     method: 'get'
   })
 }
-
-// 保存选中省市区
-export const subareaSaveSubareaArea = (params) => {
+// 查询绑定经销商列表
+export const queryPageAreaDealer = (params) => {
   return axios({
-    url: `/subarea/saveSubareaArea`,
+    url: `/subareaAreaDealer/queryPage/${params.pageNo}/${params.pageSize}`,
     data: params,
     method: 'post'
   })

+ 0 - 82
src/components/Editor/QuillEditor.vue

@@ -1,82 +0,0 @@
-<template>
-  <div :class="prefixCls">
-    <quill-editor
-      v-model="content"
-      ref="myQuillEditor"
-      :options="editorOption"
-      @blur="onEditorBlur($event)"
-      @focus="onEditorFocus($event)"
-      @ready="onEditorReady($event)"
-      @change="onEditorChange($event)">
-    </quill-editor>
-
-  </div>
-</template>
-
-<script>
-import 'quill/dist/quill.core.css'
-import 'quill/dist/quill.snow.css'
-import 'quill/dist/quill.bubble.css'
-
-import { quillEditor } from 'vue-quill-editor'
-
-export default {
-  name: 'QuillEditor',
-  components: {
-    quillEditor
-  },
-  props: {
-    prefixCls: {
-      type: String,
-      default: 'ant-editor-quill'
-    },
-    // 表单校验用字段
-    // eslint-disable-next-line
-    value: {
-      type: String
-    }
-  },
-  data () {
-    return {
-      content: null,
-      editorOption: {
-        // some quill options
-      }
-    }
-  },
-  methods: {
-    onEditorBlur (quill) {
-      console.log('editor blur!', quill)
-    },
-    onEditorFocus (quill) {
-      console.log('editor focus!', quill)
-    },
-    onEditorReady (quill) {
-      console.log('editor ready!', quill)
-    },
-    onEditorChange ({ quill, html, text }) {
-      console.log('editor change!', quill, html, text)
-      this.$emit('change', html)
-    }
-  },
-  watch: {
-    value (val) {
-      this.content = val
-    }
-  }
-}
-</script>
-
-<style lang="less" scoped>
-@import url('../index.less');
-
-/* 覆盖 quill 默认边框圆角为 ant 默认圆角,用于统一 ant 组件风格 */
-.ant-editor-quill {
-  /deep/ .ql-toolbar.ql-snow {
-    border-radius: @border-radius-base @border-radius-base 0 0;
-  }
-  /deep/ .ql-container.ql-snow {
-    border-radius: 0 0 @border-radius-base @border-radius-base;
-  }
-}
-</style>

+ 0 - 57
src/components/Editor/WangEditor.vue

@@ -1,57 +0,0 @@
-<template>
-  <div :class="prefixCls">
-    <div ref="editor" class="editor-wrapper"></div>
-  </div>
-</template>
-
-<script>
-import WEditor from 'wangeditor'
-
-export default {
-  name: 'WangEditor',
-  props: {
-    prefixCls: {
-      type: String,
-      default: 'ant-editor-wang'
-    },
-    // eslint-disable-next-line
-    value: {
-      type: String
-    }
-  },
-  data () {
-    return {
-      editor: null,
-      editorContent: null
-    }
-  },
-  watch: {
-    value (val) {
-      this.editorContent = val
-      this.editor.txt.html(val)
-    }
-  },
-  mounted () {
-    this.initEditor()
-  },
-  methods: {
-    initEditor () {
-      this.editor = new WEditor(this.$refs.editor)
-      // this.editor.onchangeTimeout = 200
-      this.editor.customConfig.onchange = (html) => {
-        this.editorContent = html
-        this.$emit('change', this.editorContent)
-      }
-      this.editor.create()
-    }
-  }
-}
-</script>
-
-<style lang="less" scoped>
-.ant-editor-wang {
-  .editor-wrapper {
-    text-align: left;
-  }
-}
-</style>

+ 121 - 123
src/components/WEeditor/editor.vue

@@ -6,146 +6,144 @@
 </template>
 
 <script>
-  import Editor from 'wangeditor'
-  import 'wangeditor/release/wangEditor.min.css'
-  import { uploadImgOnce } from '@/api/data'
-  import { oneOf } from '@/utils/util'
+import Editor from 'wangeditor'
+import { oneOf } from '@/utils/util'
+import { uploadFile } from '@/api/data'
+export default {
+  name: 'Editor',
 
-  export default {
-    name: 'Editor',
-
-    props: {
-      value: {
-        type: String,
-        default: ''
-      },
-      /**
+  props: {
+    value: {
+      type: String,
+      default: ''
+    },
+    /**
        * 绑定的值的类型, enum: ['html', 'text']
        */
-      valueType: {
-        type: String,
-        default: 'html',
-        validator: (val) => {
-          return oneOf(val, ['html', 'text'])
-        }
-      },
-      /**
+    valueType: {
+      type: String,
+      default: 'html',
+      validator: (val) => {
+        return oneOf(val, ['html', 'text'])
+      }
+    },
+    /**
        * @description 设置change事件触发时间间隔
        */
-      changeInterval: {
-        type: Number,
-        default: 200
-      },
-      /**
+    changeInterval: {
+      type: Number,
+      default: 200
+    },
+    /**
        * @description 是否开启本地存储
        */
-      cache: {
-        type: Boolean,
-        default: true
-      }
+    cache: {
+      type: Boolean,
+      default: true
+    }
+  },
+  computed: {
+    editorId () {
+      return `editor${this._uid}`
+    }
+  },
+  methods: {
+    setHtml (val) {
+      this.editor.txt.html(val)
+    },
+	  getTxt () {
+      return this.editor.txt.text()
+	  },
+    getEdior () {
+      return new Editor(`#${this.editorId}`)
+    },
+    clearText () {
+      this.editor.txt.clear()
     },
-    computed: {
-      editorId () {
-        return `editor${this._uid}`
+    randomStr (len) {
+      len = len || 32
+      const chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678'
+      const maxPos = chars.length
+      let pwd = ''
+      for (let i = 0; i < len; i++) {
+        pwd += chars.charAt(Math.floor(Math.random() * maxPos))
       }
+      return pwd
     },
-    methods: {
-      setHtml (val) {
-        this.editor.txt.html(val)
+    createFileName (filename) {
+      const pos = filename.lastIndexOf('.')
+      const suffix = filename.substring(pos)
+      return this.randomStr(20) + suffix
+    }
+
+  },
+  mounted () {
+    const _this = this
+    this.editor = new Editor(`#${this.editorId}`)
+    this.editor.config.zIndex = 100
+    this.editor.config.onchange = (html) => {
+      const text = this.editor.txt.text()
+      if (this.cache) localStorage.editorCache = html
+      this.$emit('input', this.valueType === 'html' ? html : text)
+      this.$emit('on-change', html, text)
+    }
+    this.editor.config.onchangeTimeout = this.changeInterval
+    this.editor.config.uploadImgServer = process.env.VUE_APP_API_BASE_URL + '/upload'
+    this.editor.config.uploadFileName = 'file'
+    this.editor.config.uploadImgMaxLength = 10
+    this.editor.config.uploadImgParams = {
+      savePathType: 'ali'
+    }
+    this.editor.config.uploadImgHooks = {
+      before: function (xhr, editor, files) {
+        console.log(xhr, editor, files)
+        // 图片上传之前触发
+        // xhr 是 XMLHttpRequst 对象,editor 是编辑器对象,files 是选择的图片文件
+
+        // 如果返回的结果是 {prevent: true, msg: 'xxxx'} 则表示用户放弃上传
+        // return {
+        //     prevent: true,
+        //     msg: '放弃上传'
+        // }
       },
-	  getTxt () {
-		return this.editor.txt.text()
-	  },
-      getEdior () {
-        return new Editor(`#${this.editorId}`)
+      success: function (xhr, editor, result) {
+        console.log(xhr, editor, result)
+        // 图片上传并返回结果,图片插入成功之后触发
+        // xhr 是 XMLHttpRequst 对象,editor 是编辑器对象,result 是服务器端返回的结果
       },
-      clearText () {
-        this.editor.txt.clear()
+      fail: function (xhr, editor, result) {
+        console.log(xhr, editor, result)
+        // 图片上传并返回结果,但图片插入错误时触发
+        // xhr 是 XMLHttpRequst 对象,editor 是编辑器对象,result 是服务器端返回的结果
       },
-      randomStr (len) {
-        len = len || 32
-        let chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678'
-        let maxPos = chars.length
-        let pwd = ''
-        for (let i = 0; i < len; i++) {
-          pwd += chars.charAt(Math.floor(Math.random() * maxPos))
-        }
-        return pwd
+      error: function (xhr, editor) {
+        console.log(xhr, editor)
+        // 图片上传出错时触发
+        // xhr 是 XMLHttpRequst 对象,editor 是编辑器对象
       },
-      createFileName (filename) {
-        let pos = filename.lastIndexOf('.')
-        let suffix = filename.substring(pos)
-        return this.randomStr(20) + suffix
-      }
-
-    },
-    mounted () {
-      let _this = this
-      this.editor = new Editor(`#${this.editorId}`)
-      this.editor.customConfig.zIndex = 100
-      this.editor.customConfig.onchange = (html) => {
-        let text = this.editor.txt.text()
-        if (this.cache) localStorage.editorCache = html
-        this.$emit('input', this.valueType === 'html' ? html : text)
-        this.$emit('on-change', html, text)
-      }
-      this.editor.customConfig.onchangeTimeout = this.changeInterval
-      this.editor.customConfig.uploadImgServer = process.env.VUE_APP_API_BASE_URL + '/upload'
-      this.editor.customConfig.uploadFileName = 'file'
-      this.editor.customConfig.uploadImgParams = {
-          savePathType: 'ali'
+      timeout: function (xhr, editor) {
+        // 图片上传超时时触发
+        // xhr 是 XMLHttpRequst 对象,editor 是编辑器对象
+      },
+      // 如果服务器端返回的不是 {errno:0, data: [...]} 这种格式,可使用该配置
+      // (但是,服务器端返回的必须是一个 JSON 格式字符串!!!否则会报错)
+      customInsert: function (insertImg, result, editor) {
+        // console.log(insertImg, result, editor)
+        // 图片上传并返回结果,自定义插入图片的事件(而不是编辑器自动插入图片!!!)
+        // insertImg 是插入图片的函数,editor 是编辑器对象,result 是服务器端返回的结果
+        // 举例:假如上传图片成功后,服务器端返回的是 {url:'....'} 这种格式,即可这样插入图片:
+        insertImg(result.data)
+        // result 必须是一个 JSON 格式字符串!!!否则报错
       }
-      this.editor.customConfig.uploadImgHooks = {
-          before: function (xhr, editor, files) {
-              console.log(xhr, editor, files)
-              // 图片上传之前触发
-              // xhr 是 XMLHttpRequst 对象,editor 是编辑器对象,files 是选择的图片文件
-              
-              // 如果返回的结果是 {prevent: true, msg: 'xxxx'} 则表示用户放弃上传
-              // return {
-              //     prevent: true,
-              //     msg: '放弃上传'
-              // }
-          },
-          success: function (xhr, editor, result) {
-            console.log(xhr, editor, result)
-              // 图片上传并返回结果,图片插入成功之后触发
-              // xhr 是 XMLHttpRequst 对象,editor 是编辑器对象,result 是服务器端返回的结果
-          },
-          fail: function (xhr, editor, result) {
-              console.log(xhr, editor, result)
-              // 图片上传并返回结果,但图片插入错误时触发
-              // xhr 是 XMLHttpRequst 对象,editor 是编辑器对象,result 是服务器端返回的结果
-          },
-          error: function (xhr, editor) {
-               console.log(xhr, editor)
-              // 图片上传出错时触发
-              // xhr 是 XMLHttpRequst 对象,editor 是编辑器对象
-          },
-          timeout: function (xhr, editor) {
-              // 图片上传超时时触发
-              // xhr 是 XMLHttpRequst 对象,editor 是编辑器对象
-          },
-          // 如果服务器端返回的不是 {errno:0, data: [...]} 这种格式,可使用该配置
-          // (但是,服务器端返回的必须是一个 JSON 格式字符串!!!否则会报错)
-          customInsert: function (insertImg, result, editor) {
-              // console.log(insertImg, result, editor)
-              // 图片上传并返回结果,自定义插入图片的事件(而不是编辑器自动插入图片!!!)
-              // insertImg 是插入图片的函数,editor 是编辑器对象,result 是服务器端返回的结果
-              // 举例:假如上传图片成功后,服务器端返回的是 {url:'....'} 这种格式,即可这样插入图片:
-              insertImg(result.data)
-              // result 必须是一个 JSON 格式字符串!!!否则报错
-          }
-        }
-
-      // create这个方法一定要在所有配置项之后调用
-      this.editor.create()
-      this.editor.txt.clear()
-      // 如果本地有存储加载本地存储内容
-      let html = this.value || localStorage.editorCache
-      if (html) this.editor.txt.html(html)
     }
+    // create这个方法一定要在所有配置项之后调用
+    this.editor.create()
+    this.editor.txt.clear()
+    // 如果本地有存储加载本地存储内容
+    const html = this.value || localStorage.editorCache
+    if (html) this.editor.txt.html(html)
   }
+}
 </script>
 
 <style lang="less">

+ 39 - 21
src/components/index.less

@@ -157,28 +157,24 @@
 }
 // 查询条件样式
 .table-page-search-wrapper {
-  .ant-form.ant-form-inline{
-    .ant-form-item {
-      margin-bottom: 10px!important;
-      .ant-input,.ant-select-selection{
-        border-radius: 2px;
-        padding: 0px 11px;
-        font-size: 12px;
-      }
-      .ant-form-item-label{
-        line-height: 32px!important;
-        padding-right: 8px!important;
-      }
-      .ant-form-item-control{
-        line-height: 31px!important;
-      }
-      .ant-form-item-control-wrapper{
-        .ant-select-selection__rendered{
-          margin: 0!important;
-        }
-      }
+  margin-bottom: 6px;
+  .ant-form.ant-form-inline .ant-form-item .ant-input, .ant-form.ant-form-inline .ant-form-item .ant-select-selection{
+    border:0;
+    box-shadow: none !important;
+  }
+  .ant-form.ant-form-inline .ant-form-item{
+    border:1px solid #dadada;
+    border-radius: 3px;
+    overflow: hidden;
+    margin-bottom: 10px!important;
+    .ant-form-item-label{
+      padding-left: 11px;
+      padding-right: 0!important;
     }
   }
+  .ant-input-group-addon{
+    border: 0;
+  }
   .form-model-con.ant-form.ant-form-inline{  // a-form-model  有必选条件(因校验提示信息原因,因此边距需高于无必选条件边距)
     .ant-form-item {
       margin-bottom: 16px!important;
@@ -364,4 +360,26 @@
 }
 .ant-select-disabled .ant-select-selection,.ant-cascader-picker-disabled{
   color: #999!important;
-}
+}
+
+
+//头部样式
+.header-bar{
+  margin:6px auto;
+  .subTitle-word{
+    font-size: 16px;
+    font-weight: 600;
+    display: inline-block;
+    vertical-align: middle;
+    color: #333 !important;
+  }
+}
+
+
+// 数据汇总样式
+.gatherMessage {
+  margin:10px 0;
+  strong{
+    color: #ed1c24;
+  }
+}

+ 287 - 55
src/config/router.config.js

@@ -3,8 +3,8 @@ import {
   UserLayout,
   BasicLayout,
   BlankLayout,
-  PageView,
-  BigScreen
+  BigScreen,
+  PageView
 } from '@/layouts'
 
 export const asyncRouterMap = [
@@ -148,8 +148,20 @@ export const asyncRouterMap = [
                   title: '销售单详情',
                   icon: 'monitor',
                   hidden: true,
-                  replaceTab: true
-                  // permission: 'M_salesDetail'
+                  replaceTab: true,
+                  permission: 'B_salesDetail'
+                }
+              },
+              {
+                path: 'detail/:sn',
+                name: 'salesDetailAudit',
+                component: () => import(/* webpackChunkName: "salesManagement" */ '@/views/salesManagement/salesQuery/detail.vue'),
+                meta: {
+                  title: '销售单审核',
+                  icon: 'monitor',
+                  hidden: true,
+                  replaceTab: true,
+                  permission: 'B_salesAudit'
                 }
               },
               {
@@ -159,8 +171,8 @@ export const asyncRouterMap = [
                 meta: {
                   title: '新增销售单',
                   icon: 'monitor',
-                  hidden: true
-                  // permission: 'M_salesNew'
+                  hidden: true,
+                  permission: 'B_salesEdit'
                 }
               },
               {
@@ -170,8 +182,8 @@ export const asyncRouterMap = [
                 meta: {
                   title: '编辑销售单',
                   icon: 'monitor',
-                  hidden: true
-                  // permission: 'M_salesNew'
+                  hidden: true,
+                  permission: 'B_salesEdit'
                 }
               },
               {
@@ -182,8 +194,8 @@ export const asyncRouterMap = [
                   title: '下推销售单',
                   icon: 'monitor',
                   replaceTab: true,
-                  hidden: true
-                  // permission: 'M_salesNew'
+                  hidden: true,
+                  permission: 'B_salesDispatch'
                 }
               }
             ]
@@ -219,8 +231,8 @@ export const asyncRouterMap = [
                   title: '下推订单详情',
                   icon: 'vertical-align-bottom',
                   replaceTab: true,
-                  hidden: true
-                  // permission: 'M_outboundList'
+                  hidden: true,
+                  permission: 'B_dispatchDetail'
                 }
               }
             ]
@@ -543,7 +555,8 @@ export const asyncRouterMap = [
                 meta: {
                   title: '销售退货详情',
                   icon: 'fund',
-                  hidden: true
+                  hidden: true,
+                  permission: 'B_salesReturnDetail'
                 }
               },
               {
@@ -553,7 +566,8 @@ export const asyncRouterMap = [
                 meta: {
                   title: '编辑销售退货',
                   icon: 'fund',
-                  hidden: true
+                  hidden: true,
+                  permission: 'B_salesReturnEdit'
                 }
               },
               {
@@ -564,7 +578,8 @@ export const asyncRouterMap = [
                   title: '客服确认',
                   icon: 'fund',
                   replaceTab: true,
-                  hidden: true
+                  hidden: true,
+                  permission: 'B_salesReturnConfirm'
                 }
               }
             ]
@@ -599,7 +614,8 @@ export const asyncRouterMap = [
                 meta: {
                   title: '提货单详情',
                   icon: 'fund',
-                  hidden: true
+                  hidden: true,
+                  permission: 'M_detailPickUp'
                 }
               },
               {
@@ -609,7 +625,8 @@ export const asyncRouterMap = [
                 meta: {
                   title: '新增提货单',
                   icon: 'fund',
-                  hidden: true
+                  hidden: true,
+                  permission: 'B_editPickUp'
                 }
               },
               {
@@ -619,7 +636,8 @@ export const asyncRouterMap = [
                 meta: {
                   title: '编辑提货单',
                   icon: 'fund',
-                  hidden: true
+                  hidden: true,
+                  permission: 'B_editPickUp'
                 }
               }
             ]
@@ -680,7 +698,8 @@ export const asyncRouterMap = [
                   title: '收货',
                   icon: 'fund',
                   hidden: true,
-                  replaceTab: true
+                  replaceTab: true,
+                  permission: 'B_salesReturnReceiving'
                 }
               },
               {
@@ -691,7 +710,8 @@ export const asyncRouterMap = [
                   title: '品检',
                   icon: 'fund',
                   hidden: true,
-                  replaceTab: true
+                  replaceTab: true,
+                  permission: 'B_salesReturnCheck'
                 }
               }
             ]
@@ -739,7 +759,8 @@ export const asyncRouterMap = [
                 meta: {
                   title: '新增散件入库单',
                   icon: 'gold',
-                  hidden: true
+                  hidden: true,
+                  permission: 'B_sparePartsEdit'
                 }
               },
               {
@@ -749,7 +770,8 @@ export const asyncRouterMap = [
                 meta: {
                   title: '编辑散件入库单',
                   icon: 'gold',
-                  hidden: true
+                  hidden: true,
+                  permission: 'B_sparePartsEdit'
                 }
               }
             ]
@@ -784,7 +806,8 @@ export const asyncRouterMap = [
                 meta: {
                   title: '新增采购退货',
                   icon: 'gold',
-                  hidden: true
+                  hidden: true,
+                  permission: 'B_purchaseReturnEdit'
                 }
               },
               {
@@ -794,7 +817,8 @@ export const asyncRouterMap = [
                 meta: {
                   title: '编辑采购退货',
                   icon: 'gold',
-                  hidden: true
+                  hidden: true,
+                  permission: 'B_purchaseReturnEdit'
                 }
               }
             ]
@@ -953,7 +977,8 @@ export const asyncRouterMap = [
                 meta: {
                   title: '财务收款详情',
                   icon: 'monitor',
-                  hidden: true
+                  hidden: true,
+                  permission: 'B_fc_detail'
                 }
               },
               {
@@ -963,7 +988,8 @@ export const asyncRouterMap = [
                 meta: {
                   title: '编辑财务收款',
                   icon: 'monitor',
-                  hidden: true
+                  hidden: true,
+                  permission: 'B_fc_edit'
                 }
               }
             ]
@@ -1036,7 +1062,8 @@ export const asyncRouterMap = [
                 meta: {
                   title: '费用报销单详情',
                   icon: 'monitor',
-                  hidden: true
+                  hidden: true,
+                  permission: 'B_eRdetail'
                 }
               },
               {
@@ -1046,7 +1073,8 @@ export const asyncRouterMap = [
                 meta: {
                   title: '新增费用报销单',
                   icon: 'monitor',
-                  hidden: true
+                  hidden: true,
+                  permission: 'B_ERtEdit'
                 }
               },
               {
@@ -1056,7 +1084,8 @@ export const asyncRouterMap = [
                 meta: {
                   title: '编辑费用报销单',
                   icon: 'monitor',
-                  hidden: true
+                  hidden: true,
+                  permission: 'B_ERtEdit'
                 }
               }
             ]
@@ -1130,8 +1159,8 @@ export const asyncRouterMap = [
                   title: '出入库明细',
                   icon: 'monitor',
                   replaceTab: true,
-                  hidden: true
-                  // permission: 'B_goodsManage_edit'
+                  hidden: true,
+                  permission: 'B_inventoryQuery_rkDetail'
                 }
               }
             ]
@@ -1301,7 +1330,8 @@ export const asyncRouterMap = [
                 meta: {
                   title: '新增智能补货',
                   icon: 'monitor',
-                  hidden: true
+                  hidden: true,
+                  permission: 'B_intelligentReplenishment_edit'
                 }
               },
               {
@@ -1311,7 +1341,8 @@ export const asyncRouterMap = [
                 meta: {
                   title: '编辑智能补货',
                   icon: 'monitor',
-                  hidden: true
+                  hidden: true,
+                  permission: 'B_intelligentReplenishment_edit'
                 }
               },
               {
@@ -1321,6 +1352,7 @@ export const asyncRouterMap = [
                 meta: {
                   title: '基础信息设置',
                   icon: 'monitor',
+                  permission: 'B_intelligentReplenishment_set',
                   replaceTab: true,
                   hidden: true
                 }
@@ -1381,8 +1413,8 @@ export const asyncRouterMap = [
                 meta: {
                   title: '新增调拨单',
                   icon: 'pull-request',
-                  hidden: true
-                  // permission: 'B_goodsManage_edit'
+                  hidden: true,
+                  permission: 'M_transferOut_edit'
                 }
               },
               {
@@ -1392,8 +1424,8 @@ export const asyncRouterMap = [
                 meta: {
                   title: '编辑调拨单',
                   icon: 'pull-request',
-                  hidden: true
-                  // permission: 'B_goodsManage_edit'
+                  hidden: true,
+                  permission: 'M_transferOut_edit'
                 }
               },
               {
@@ -1403,8 +1435,9 @@ export const asyncRouterMap = [
                 meta: {
                   title: '调拨单详情',
                   icon: 'pull-request',
-                  hidden: true
-                  // permission: 'B_goodsManage_edit'
+                  hidden: true,
+                  replaceTab: true,
+                  permission: 'M_transferOut_detail'
                 }
               }
             ]
@@ -1489,7 +1522,8 @@ export const asyncRouterMap = [
                 meta: {
                   title: '编辑调拨退货单(抓单)',
                   icon: 'pull-request',
-                  hidden: true
+                  hidden: true,
+                  permission: 'B_transferReturnEdit'
                 }
               },
               {
@@ -1499,7 +1533,8 @@ export const asyncRouterMap = [
                 meta: {
                   title: '编辑调拨退货单(不抓单)',
                   icon: 'pull-request',
-                  hidden: true
+                  hidden: true,
+                  permission: 'B_transferReturnEdit'
                 }
               },
               {
@@ -1510,7 +1545,8 @@ export const asyncRouterMap = [
                   title: '调拨退货单详情',
                   icon: 'pull-request',
                   replaceTab: true,
-                  hidden: true
+                  hidden: true,
+                  permission: 'M_transferReturnDetail'
                 }
               },
               {
@@ -1521,7 +1557,8 @@ export const asyncRouterMap = [
                   title: '调拨退货品检',
                   icon: 'fund',
                   replaceTab: true,
-                  hidden: true
+                  hidden: true,
+                  permission: 'M_transferReturnCheck'
                 }
               }
             ]
@@ -1931,6 +1968,52 @@ export const asyncRouterMap = [
               }
             }]
           },
+          {
+            path: '/reportData/billingBackReport',
+            redirect: '/reportData/billingBackReport/list',
+            name: 'billingBackReport',
+            component: BlankLayout,
+            meta: {
+              title: '开单采退报表',
+              icon: 'profile',
+              permission: 'M_billingBackReport'
+            },
+            hideChildrenInMenu: true,
+            children: [{
+              path: 'list',
+              name: 'billingBackReportList',
+              component: () => import(/* webpackChunkName: "reportData" */ '@/views/reportData/billingBackReport/list.vue'),
+              meta: {
+                title: '开单采退报表列表',
+                icon: 'profile',
+                hidden: true,
+                permission: 'M_billingBackReportList'
+              }
+            }]
+          },
+          {
+            path: '/reportData/billingOrderReport',
+            redirect: '/reportData/billingOrderReport/list',
+            name: 'billingOrderReport',
+            component: BlankLayout,
+            meta: {
+              title: '开单采退单报表',
+              icon: 'profile',
+              permission: 'M_billingOrderReport'
+            },
+            hideChildrenInMenu: true,
+            children: [{
+              path: 'list',
+              name: 'billingOrderReportList',
+              component: () => import(/* webpackChunkName: "reportData" */ '@/views/reportData/billingOrderReport/list.vue'),
+              meta: {
+                title: '开单采退单报表列表',
+                icon: 'profile',
+                hidden: true,
+                permission: 'M_billingOrderReportList'
+              }
+            }]
+          },
           {
             path: '/reportData/hPriceDifferenceDetailReport',
             redirect: '/reportData/hPriceDifferenceDetailReport/list',
@@ -1987,7 +2070,7 @@ export const asyncRouterMap = [
             name: 'regionTypeSalesReport',
             component: BlankLayout,
             meta: {
-              title: '各品类实售明细',
+              title: '各分区品类实售明细',
               icon: 'profile',
               permission: 'M_regionTypeSalesReportList'
             },
@@ -1998,7 +2081,7 @@ export const asyncRouterMap = [
                 name: 'regionTypeSalesReportList',
                 component: () => import(/* webpackChunkName: "reportData" */ '@/views/reportData/regionTypeSalesReport/list.vue'),
                 meta: {
-                  title: '各品类实售明细',
+                  title: '各分区品类实售明细',
                   icon: 'profile',
                   hidden: true,
                   permission: 'M_regionTypeSalesReportList'
@@ -2180,6 +2263,31 @@ export const asyncRouterMap = [
                 }
               }
             ]
+          },
+          {
+            path: '/reportData/receivedSendStorageReport',
+            redirect: '/reportData/receivedSendStorageReport/index',
+            name: 'receivedSendStorageReport',
+            component: BlankLayout,
+            meta: {
+              title: '收发存报表',
+              icon: 'profile',
+              permission: 'M_receivedSendStorageReport'
+            },
+            hideChildrenInMenu: true,
+            children: [
+              {
+                path: 'index',
+                name: 'receivedSendStorageReportIndex',
+                component: () => import(/* webpackChunkName: "reportData" */ '@/views/reportData/receivedSendStorageReport/index.vue'),
+                meta: {
+                  title: '收发存报表',
+                  icon: 'profile',
+                  hidden: true,
+                  permission: 'M_receivedSendStorageReportList'
+                }
+              }
+            ]
           }
           // {
           //   path: '/reportData/allCountryCostReport',
@@ -2208,14 +2316,52 @@ export const asyncRouterMap = [
           // }
         ]
       },
+      // 产品返利明细表
+      {
+        path: '/productRebateReport',
+        redirect: '/productRebateReport/index',
+        component: PageView,
+        meta: {
+          title: '产品返利表',
+          icon: 'profile'
+          // permission: 'M_productRebateReport'
+        },
+        children: [
+          {
+            path: '/productRebateReport/index',
+            redirect: '/productRebateReport/index/list',
+            name: 'productRebateReportList',
+            component: BlankLayout,
+            meta: {
+              title: '产品返利明细表',
+              icon: 'profile'
+              // permission: 'M_productRebateReportList'
+            },
+            hideChildrenInMenu: true,
+            children: [
+              {
+                path: 'list',
+                name: 'productRebateReportList',
+                component: () => import(/* webpackChunkName: "reportData" */ '@/views/reportData/productRebateReport/index.vue'),
+                meta: {
+                  title: '产品返利明细表',
+                  icon: 'profile',
+                  hidden: true
+                  // permission: 'M_productRebateReportList'
+                }
+              }
+            ]
+          }
+        ]
+      },
       // 数据导出
       {
         path: '/dataExport',
-        redirect: '/dataExport/exportCheck',
+        redirect: '/dataExport/exportSales',
         component: PageView,
         meta: {
           title: '数据导出',
-          icon: 'money-collect',
+          icon: 'database',
           permission: 'M_dataExport'
         },
         children: [
@@ -2702,9 +2848,9 @@ export const asyncRouterMap = [
             ]
           },
           {
-            path: '/dealerManagement/marketingDivisionSet',
-            redirect: '/dealerManagement/marketingDivisionSet/list',
-            name: 'marketingDivisionSet',
+            path: '/dealerManagement/marketingDivisionSetNew',
+            redirect: '/dealerManagement/marketingDivisionSetNew/list',
+            name: 'marketingDivisionSetNew',
             component: BlankLayout,
             meta: {
               title: '营销分区设置',
@@ -2715,8 +2861,8 @@ export const asyncRouterMap = [
             children: [
               {
                 path: 'list',
-                name: 'marketingDivisionSetList',
-                component: () => import(/* webpackChunkName: "dealerManagement" */ '@/views/dealerManagement/marketingDivisionSet/list.vue'),
+                name: 'marketingDivisionSetNewList',
+                component: () => import(/* webpackChunkName: "dealerManagement" */ '@/views/dealerManagement/marketingDivisionSetNew/list.vue'),
                 meta: {
                   title: '营销分区列表',
                   icon: 'setting',
@@ -2725,6 +2871,68 @@ export const asyncRouterMap = [
                 }
               }
             ]
+          },
+          {
+            path: '/dealerManagement/businessOwnerSettings',
+            redirect: '/dealerManagement/businessOwnerSettings/list',
+            name: 'businessOwnerSettings',
+            component: BlankLayout,
+            meta: {
+              title: '业务负责人配置',
+              icon: 'stock',
+              permission: 'M_businessOwnerSettings'
+            },
+            hideChildrenInMenu: true,
+            children: [
+              {
+                path: 'list',
+                name: 'businessOwnerSettingsList',
+                component: () => import(/* webpackChunkName: "dealerManagement" */ '@/views/dealerManagement/businessOwnerSettings/list.vue'),
+                meta: {
+                  title: '业务负责人配置列表',
+                  icon: 'stock',
+                  hidden: true,
+                  permission: 'M_businessOwnerSettingsList'
+                }
+              },
+              {
+                path: 'settingsIndex',
+                name: 'categorySet',
+                component: () => import(/* webpackChunkName: "salesManagement" */ '@/views/dealerManagement/businessOwnerSettings/settingsIndex.vue'),
+                meta: {
+                  title: '管辖品类权限设置',
+                  icon: 'user',
+                  hidden: true,
+                  replaceTab: true,
+                  permission: 'M_settingsIndex'
+                }
+              }
+            ]
+          },
+          {
+            path: '/dealerManagement/dealerZoneSearch',
+            redirect: '/dealerManagement/dealerZoneSearch/list',
+            name: 'dealerZoneSearch',
+            component: BlankLayout,
+            meta: {
+              title: '经销商所属分区查询',
+              icon: 'setting',
+              permission: 'M_dealerZoneSearch'
+            },
+            hideChildrenInMenu: true,
+            children: [
+              {
+                path: 'list',
+                name: 'dealerZoneSearchList',
+                component: () => import(/* webpackChunkName: "dealerManagement" */ '@/views/dealerManagement/dealerZoneSearch/list.vue'),
+                meta: {
+                  title: '经销商所属分区查询',
+                  icon: 'setting',
+                  hidden: true,
+                  permission: 'M_dealerZoneSearchList'
+                }
+              }
+            ]
           }
         ]
       },
@@ -3246,8 +3454,7 @@ export const asyncRouterMap = [
             children: [{
               path: 'index',
               name: 'bigScreenSetIndex',
-              component: () => import(/* webpackChunkName: "setting" */
-                '@/views/setting/bigScreenSet/index.vue'),
+              component: () => import(/* webpackChunkName: "setting" */'@/views/setting/bigScreenSet/index.vue'),
               meta: {
                 title: '大屏参数设置',
                 icon: 'sketch',
@@ -3255,6 +3462,31 @@ export const asyncRouterMap = [
                 permission: 'M_bigScreenSetIndex'
               }
             }]
+          },
+          {
+            path: '/setting/erpMessageManagement',
+            redirect: '/setting/erpMessageManagement/list',
+            name: 'erpMessageManagement',
+            component: BlankLayout,
+            meta: {
+              title: 'ERP数据同步记录',
+              icon: 'sketch'
+              // permission: 'M_erpMessageList'
+            },
+            hideChildrenInMenu: true,
+            children: [
+              {
+                path: 'list',
+                name: 'M_erpMessageList',
+                component: () => import(/* webpackChunkName: "setting" */ '@/views/setting/erpMessageManagement/list.vue'),
+                meta: {
+                  title: 'ERP数据同步列表',
+                  icon: 'sketch',
+                  hidden: true
+                  // permission: 'M_erpMessageList'
+                }
+              }
+            ]
           }
         ]
       }
@@ -3328,4 +3560,4 @@ export const constantRouterMap = [
     path: '/404',
     component: () => import(/* webpackChunkName: "fail" */ '@/views/exception/404')
   }
-]
+]

+ 17 - 6
src/layouts/BasicLayout.vue

@@ -45,14 +45,15 @@
           <router-view ></router-view>
         </transition>
       </a-layout-content>
-
+      <!-- pdf 预览 -->
+      <pdfViewModal ref="pdfview" :openModal="showPdfView" @cancel="showPdfView=false"></pdfViewModal>
       <!-- layout footer -->
       <a-layout-footer>
         <!-- <global-footer /> -->
       </a-layout-footer>
-
+      <div id="print"></div>
       <!-- Setting Drawer (show in development mode) -->
-      <setting-drawer v-if="!production"></setting-drawer>
+      <!-- <setting-drawer v-if="!production"></setting-drawer> -->
     </a-layout>
   </a-layout>
 
@@ -68,7 +69,8 @@ import RouteView from './RouteView'
 import SideMenu from '@/components/Menu/SideMenu'
 import GlobalHeader from '@/components/GlobalHeader'
 import GlobalFooter from '@/components/GlobalFooter'
-import SettingDrawer from '@/components/SettingDrawer'
+// import SettingDrawer from '@/components/SettingDrawer'
+import pdfViewModal from '@/views/common/pdfViewModal.vue'
 import { asyncRouterMap } from '@/config/router.config'
 
 export default {
@@ -84,14 +86,16 @@ export default {
     SideMenu,
     GlobalHeader,
     GlobalFooter,
-    SettingDrawer
+    // SettingDrawer,
+    pdfViewModal
   },
   data () {
     return {
       production: config.production,
       collapsed: false,
       menus: [],
-      isRouterAlive: true
+      isRouterAlive: true,
+      showPdfView: false
     }
   },
   computed: {
@@ -114,6 +118,13 @@ export default {
   watch: {
     sidebarOpened (val) {
       this.collapsed = !val
+    },
+    // 打印预览
+    '$store.state.app.showPdfPrintView' (newValue, oldValue) {
+      console.log(newValue)
+      if (newValue) {
+        this.showPdfView = newValue
+      }
     }
   },
   created () {

+ 1 - 3
src/layouts/BigScreen.vue

@@ -1,4 +1,3 @@
-<!--大屏模板-->
 <template>
   <div class="screen-page">
     <ScaleScreen
@@ -277,7 +276,6 @@ export default {
   @keyframes yh-setting-fade-out {
       0% {
           opacity: 1;
-
       }
 
       100% {
@@ -305,4 +303,4 @@ export default {
           transform: translate(100%, 0)
       }
   }
-</style>
+</style>

+ 2 - 2
src/layouts/PageView.vue

@@ -70,7 +70,7 @@ export default {
     setpageH () {
       this.$nextTick(() => {
         this.$store.dispatch('SetWinHeight', window.innerHeight)
-        this.pageHeight = window.innerHeight - 85
+        this.pageHeight = window.innerHeight - 80
       })
     }
   }
@@ -79,7 +79,7 @@ export default {
 
 <style lang="less" scoped>
   .content {
-    margin: 8px 12px 0;
+    margin: 12px 12px 0;
     .page-header-index-wide{
       height: 100%;
       >div{

+ 1 - 0
src/layouts/index.js

@@ -4,4 +4,5 @@ import BasicLayout from './BasicLayout'
 import RouteView from './RouteView'
 import PageView from './PageView'
 import BigScreen from './BigScreen'
+
 export { UserLayout, BasicLayout, BlankLayout, RouteView, PageView, BigScreen }

+ 60 - 25
src/libs/JGPrint.js

@@ -110,26 +110,31 @@ export const jGPrint = function (data, type, callback, printLogParams, printPage
   }
   LODOP.SET_SHOW_MODE('HIDE_PAPER_BOARD', 1) //  隐藏底图上有模拟走纸板的条纹线
   // 执行该语句之后,PRINT指令不再返回那个所谓“打印成功”,才能获取到打印状态
-  LODOP.SET_PRINT_MODE('CATCH_PRINT_STATUS', true)
+  // LODOP.SET_PRINT_MODE('CATCH_PRINT_STATUS', true)
   // TaskID:任务id,Value:job代码
   LODOP.On_Return = function (TaskID, Value) {
-    console.log(TaskID, Value)
+    console.log(TaskID, Value, printLogParams)
     // 已打印
-    if (Value && printLogParams) {
-      console.log('已打印,统计打印次数')
-      printLog(printLogParams, callback)
+    if (Value) {
+      if(printLogParams){
+        console.log('已打印,统计打印次数')
+        printLog(printLogParams, callback)
+      }else{
+        callback({status:200,message:'已打印'})
+      }
     } else {
+      // 取消打印
       callback()
     }
   }
   if (printPageSize) {
-    LODOP.ADD_PRINT_HTM(0, 0, '100%', '99%', data)
     LODOP.SET_PRINT_PAGESIZE(3, '210mm', 100, '')
   } else {
-    LODOP.SET_PRINT_PAGESIZE(1,'210mm','297mm',"");
-    LODOP.ADD_PRINT_HTM(0, 0, '100%', '99%', data)
     LODOP.SET_SHOW_MODE('BKIMG_PRINT', 0)
+    LODOP.SET_PRINT_PAGESIZE(1,'210mm','297mm',"");
   }
+  LODOP.ADD_PRINT_HTM(0, 0, '100%', '99%', data)
+
   if (type == 'preview') { //  预览
     LODOP.PREVIEW()
   } else if (type == 'print') { //  打印
@@ -137,8 +142,25 @@ export const jGPrint = function (data, type, callback, printLogParams, printPage
   }
 }
 
+// 自动排版, 遍历数组,将数组中每一个数值加起来,如果和小于某个数,则将这些数值存放到一个新数组中。
+export const groupLessThan = function(numbers, targetSum) {
+  let currentSum = 0;
+  let result = [];
+  for (let i = 0; i < numbers.length; i++) {
+    currentSum += numbers[i].h;
+    if (currentSum <= targetSum) {
+      result.push(numbers[i].t);
+    } else {
+      result.push('&-NEWPAGE-&'); // 用'&-NEWPAGE-&'作为分页符
+      currentSum = numbers[i].h; // 重新计算当前总和
+      result.push(numbers[i].t);
+    }
+  }
+  return result;
+}
+
 // 批量打印销售收款单html
-export const jGPlPrint = function (data, type, callback, printLogParams, orginData) {
+export const jGPlPrint = function (data, type, callback, printLogParams, taskName) {
   if (!data) {
     return
   }
@@ -161,28 +183,37 @@ export const jGPlPrint = function (data, type, callback, printLogParams, orginDa
     })
     return
   }
+  LODOP.PRINT_INIT(taskName)
   LODOP.SET_SHOW_MODE('HIDE_PAPER_BOARD', 1) //  隐藏底图上有模拟走纸板的条纹线
   // 执行该语句之后,PRINT指令不再返回那个所谓“打印成功”,才能获取到打印状态
-  LODOP.SET_PRINT_MODE('CATCH_PRINT_STATUS', true)
+  // LODOP.SET_PRINT_MODE('CATCH_PRINT_STATUS', true)
   // TaskID:任务id,Value:job代码
   LODOP.On_Return = function (TaskID, Value) {
-    console.log(TaskID, Value)
+    console.log(TaskID, Value, printLogParams)
     // 已打印
-    if (Value && printLogParams) {
-      console.log('已打印,统计打印次数')
-      printLog(printLogParams, callback)
+    if (Value) {
+      if(printLogParams){
+        console.log('已打印,统计打印次数')
+        printLog(printLogParams, callback)
+      }else{
+        callback({status:200,message:'已打印'})
+      }
     } else {
+      // 取消打印
       callback()
     }
   }
   LODOP.SET_PRINT_PAGESIZE(1,'210mm','297mm',"");
   LODOP.SET_SHOW_MODE('BKIMG_PRINT', 0)
-  // 循环页
-  for(var i=0;i<data.length;i=i+2){
-     if(i%2==0){
-       LODOP.NewPageA();
-     }
-     LODOP.ADD_PRINT_HTM(0, 0, '100%', '99%', data[i]+(data[i+1]||''))
+
+  if(data.length>1){
+    // 循环页
+    for(var i=0;i<data.length;i++){
+      LODOP.NewPage();
+      LODOP.ADD_PRINT_HTM(0, 0, '100%', '99%', data[i])
+    }
+  }else{
+    LODOP.ADD_PRINT_HTM(0, 0, '100%', '99%', data[0])
   }
   
   if (type == 'preview') { //  预览
@@ -287,18 +318,22 @@ export const jGPrintPdf = function (data, type, taskName, printLogParams, callba
     LODOP.PRINT_INIT(taskName)
     LODOP.SET_SHOW_MODE('HIDE_PAPER_BOARD', 1) //  隐藏底图上有模拟走纸板的条纹线
     // 执行该语句之后,PRINT指令不再返回那个所谓“打印成功”,才能获取到打印状态
-    LODOP.SET_PRINT_MODE('CATCH_PRINT_STATUS', true)
+    // LODOP.SET_PRINT_MODE('CATCH_PRINT_STATUS', true)
     // 隐藏打印按钮
     if (hidePrint) {
       LODOP.SET_SHOW_MODE('HIDE_PBUTTIN_PREVIEW', true)
     }
     // TaskID:任务id,Value:job代码
     LODOP.On_Return = function (TaskID, Value) {
-      console.log(TaskID, Value)
+      console.log(TaskID, Value!=0, printLogParams)
       // 已打印
-      if (Value && printLogParams) {
-        console.log('已打印,统计打印次数')
-        printLog(printLogParams, callback)
+      if (Value!=0) {
+        if(printLogParams){
+          console.log('已打印,统计打印次数')
+          printLog(printLogParams, callback)
+        }else{
+          callback({status:200,message:'打印已完成'})
+        }
       } else {
         callback()
       }

+ 1 - 1
src/libs/getDate.js

@@ -143,4 +143,4 @@ export default {
       	endDate: moment(year.toString()).endOf('year').format('YYYY-MM-DD 23:59:59')
     }
   }
-}
+}

+ 10 - 0
src/libs/tools.js

@@ -481,3 +481,13 @@ export const checkIdNumberValid = (tex) => {
   }
   return true
 }
+// 清除空格和特殊字符
+export const removeEmptyStr = function(str){
+  if(str){
+    var strs=str.toString()
+    strs= strs.replace(/^\s+|\s+$/gm,'');
+    strs=strs.replace(/[`~!@#$%^&*()_\-+=<>?:"{}|,.\/;'\\[\]·~!@#¥%……&*()——\-+={}|《》?:“”【】、;‘',。、]/im,'');
+    return strs;
+  }
+  return '';
+}

+ 0 - 2
src/libs/types.js

@@ -42,5 +42,3 @@ export function isHtmlElement(node) {
 export const isUndefined = (val) => {
     return val === void 0;
 };
-
-

+ 0 - 1
src/main.js

@@ -72,7 +72,6 @@ Vue.prototype.$hasPermissions = function (value) {
   let isExist = false
   const roles = store.getters.roles
   const permissionList = roles.permissionList
-  // console.log(permissionsStr,'permissionsStr')
   if (permissionList == undefined || permissionList == null) {
     return false
   }

+ 1 - 1
src/permission.js

@@ -98,4 +98,4 @@ router.beforeEach((to, from, next) => {
 
 router.afterEach(() => {
   NProgress.done() // finish progress bar
-})
+})

+ 4 - 1
src/store/getters.js

@@ -19,7 +19,10 @@ const getters = {
   employeeList: state => state.app.employeeList,
   tempBillOfData: state => state.app.tempBillOfData,
   returnReason: state => state.app.returnReason,
-  echartsAutoTime: state => state.setting.echartsAutoTime
+  echartsAutoTime: state => state.setting.echartsAutoTime,
+  authMenusList: state => state.app.authMenusList,
+  priceAuthOptions: state => state.app.priceAuthOptions,
+  curActionPermission: state => state.app.curActionPermission
 }
 
 export default getters

+ 1 - 1
src/store/index.js

@@ -32,4 +32,4 @@ export default new Vuex.Store({
 
   },
   getters
-})
+})

+ 13 - 2
src/store/modules/app.js

@@ -36,6 +36,11 @@ const app = {
     employeeList: [], // 申请人列表
     returnReason: [], // 申请退货原因列表
     tempBillOfData: null, // 临时存储收货单数据
+    authMenusList: [], // 权限菜单数据
+    priceAuthOptions:[], // 价格权限选项
+    curActionPermission: '', // 当前激活状态的权限码
+    showPdfPrintView: false, // pdf 打印预览
+    pdfUrl: ''
   },
   mutations: {
     SET_SIDEBAR_TYPE: (state, type) => {
@@ -98,6 +103,12 @@ const app = {
     SET_returnReason:(state, val) => {
       state.returnReason = val
     },
+    SET_showPdfPrint: (state, val) => {
+      state.showPdfPrintView = val
+    },
+    SET_PdfUrl: (state, val) => {
+      state.pdfUrl = val
+    },
   },
   actions: {
     setSidebar ({ commit }, type) {
@@ -151,12 +162,12 @@ const app = {
         }
       })
     },
-    getReturnReasonData({ commit }, code, isEnable) {
+    getReturnReasonData({ commit }, code) {
       getLookUpData({
         pageNo: 1,
         pageSize: 1000,
         lookupCode: code,
-        isEnable: isEnable ? 1 : undefined
+        isEnable: 1
       }).then(res => {
         if (res.status == 200) {
           commit('SET_returnReason', res.data.list)

+ 1 - 1
src/utils/domUtil.js

@@ -52,4 +52,4 @@ export const addKeyFrames = function (id,y,dur){
     }';
     style.innerHTML = keyFrames.replace(/A_ID/g, id).replace(/A_DYNAMIC_VALUE/g, y).replace(/A_DUR/g,dur);
     document.getElementsByTagName('head')[0].appendChild(style);
-}
+}

+ 1 - 1
src/utils/filter.js

@@ -20,5 +20,5 @@ Vue.filter('moment', function (dataStr, pattern = 'YYYY-MM-DD HH:mm:ss') {
 })
 
 Vue.filter('montionFilter', function (val) {
-    return val ? Number(val).toFixed(2) : '0.00'
+    return val ? Number(val).toFixed(2) : '--'
 })

+ 3 - 0
src/utils/mixin.js

@@ -101,6 +101,9 @@ const commonMixin = {
         if(this.addMoreLoading != undefined){
           this.addMoreLoading = a
         }
+        if(this.confirmLoading != undefined){
+          this.confirmLoading = a
+        }
       }
     }
   },

+ 17 - 5
src/utils/request.js

@@ -1,8 +1,10 @@
 import Vue from 'vue'
 import axios from 'axios'
 import store from '@/store'
+import router from '@/router'
 import notification from 'ant-design-vue/es/notification'
 import modal from 'ant-design-vue/es/modal'
+import { getAuthPriceCode } from './util'
 import { VueAxios } from './axios'
 
 //没有基地址 访问根目录下文件
@@ -24,7 +26,7 @@ const service = axios.create({
 })
 
 const err = (error) => {
-  console.log(error, error.response.data,error.message,'error')
+  console.log(error.response)
   const config = error.config
   // 网络连接出错
   if (error.message.indexOf('Network Error') >= 0) {
@@ -33,6 +35,7 @@ const err = (error) => {
       message: '提示',
       description: '无网络连接,请检查网络是否连接正常'
     })
+    store.state.app.curActionPermission = ''
     store.commit('SET_loadingStatus', false)
     return Promise.reject(err)
   }
@@ -41,9 +44,10 @@ const err = (error) => {
   if (error.response) {
     const status = error.response.status
     const resData = error.response.data
-    console.log(resData)
+    console.log(status,resData)
     if ((status == 503 || status == 500 || status == 404)) {
       notification.destroy()
+      store.state.app.curActionPermission = ''
       if(resData instanceof Blob){
         resData.text().then(data => {
           const res = JSON.parse(data)
@@ -55,7 +59,7 @@ const err = (error) => {
       }else{
         notification.error({
           message: '提示',
-          description: resData.message
+          description: resData.message || error.response.statusText || '服务器出错,请稍后再试!'
         })
       }
     }
@@ -106,10 +110,12 @@ const err = (error) => {
 
 // request interceptor
 service.interceptors.request.use(config => {
+  const authPrice = getAuthPriceCode(config, router, store)
   const token = store.getters.token
   if (token) {
     config.headers['access-token'] = token // 让每个请求携带自定义 token 请根据实际情况自行修改
   }
+  config.headers['auth-price'] = authPrice.join(',') // 价格权限
   config.retry = 3
   config.retryDelay = 1000
   store.commit('SET_loadingStatus', true)
@@ -118,7 +124,7 @@ service.interceptors.request.use(config => {
 
 // response interceptor
 service.interceptors.response.use((response) => {
-  console.log(response, 'response.data.status')
+  // console.log(response, 'response.data.status')
   const et = sessionStorage.getItem('errorTips')
   if ((response.data.status == '1001' || response.data.status == '1099') && !et) {
     sessionStorage.setItem('errorTips', 1)
@@ -128,6 +134,7 @@ service.interceptors.response.use((response) => {
       content: response.data.message,
       onOk () {
         sessionStorage.setItem('errorTips', 0)
+        store.state.app.curActionPermission = ''
         store.dispatch('Logout').then(() => {
           window.location.reload()
         })
@@ -135,6 +142,7 @@ service.interceptors.response.use((response) => {
     })
   }
   if ((response.data.status == '401' || response.data.status == '500') && window.location.pathname != '/user/login') {
+    store.state.app.curActionPermission = ''
     notification.destroy()
     notification.error({
       message: '提示',
@@ -142,13 +150,17 @@ service.interceptors.response.use((response) => {
     })
   }
   if (response.data.status == '900' && window.location.pathname != '/user/login') {
+    store.state.app.curActionPermission = ''
     notification.destroy()
     notification.error({
       message: response.data.message,
       description: response.data.code
     })
   }
-  store.commit('SET_loadingStatus', false)
+  if(response.data.status!='200'){
+    store.state.app.curActionPermission = ''
+    store.commit('SET_loadingStatus', false)
+  }
   return response.data
 }, err)
 

+ 104 - 0
src/utils/util.js

@@ -133,4 +133,108 @@ export function formatThousands (number) {
   while (numbers.length) segs.push(numbers.splice(0, 3).join(''))
 
   return segs.join(',').split('').reverse().join('') + (arr.length>1 ? ("."+arr[1]) : '')
+}
+/**
+ * 数组转树形结构
+ * @param {array} list 被转换的数组
+ * @param {number|string} root 根节点(最外层节点)的 id
+ * @return array
+ */
+export function arrayToTree(list, root) {
+  const result = [] // 用于存放结果
+  const map = {} // 用于存放 list 下的节点
+
+  // 1. 遍历 list,将 list 下的所有节点以 id 作为索引存入 map
+  for (const item of list) {
+    map[item.id] = { ...item } // 浅拷贝
+  }
+
+  // 2. 再次遍历,将根节点放入最外层,子节点放入父节点
+  for (const item of list) {
+    // 3. 获取节点的 id 和 父 id
+    const { id, parentId } = item // ES6 解构赋值
+    // 4. 如果是根节点,存入 result
+    if (item.parentId == root) {
+      result.push(map[id])
+    } else {
+      // 5. 反之,存入到父节点
+      map[parentId].children
+        ? map[parentId].children.push(map[id])
+        : (map[parentId].children = [map[id]])
+    }
+  }
+
+  // 将结果返回
+  return result
+}
+// 树查找
+export function treeFind (tree, func) {
+  for (const data of tree) {
+    if (func(data)) return data
+    if (data.children) {
+      const res = treeFind(data.children, func)
+      if (res) return res
+    }
+  }
+  return null
+}
+// 是否有价格权限
+export function hasPriceAuth(authNode, priceOptions, userAuthCode){
+  const codes = []
+  const ret = []
+  // 过滤当前节点下的非价格权限菜单
+  authNode.map(item=>{
+    const a = item.code.split('_')
+    const hasCode = priceOptions.find(k => k.value == a[a.length-1])
+    const hasRoles = userAuthCode.includes(item.code)
+    // 获取当前用户的角色拥有的价格权限
+    if(hasCode && hasRoles){
+      codes.push(a[a.length-1])
+    }
+  })
+  // 根据拥有的价格权限生成数组标记[1,0,1,0,0],每一位对应一个价格权限
+  // 有权限标记1,否则标记0
+  priceOptions.map(item => {
+    ret.push(codes.includes(item.value)?1:0)
+  })
+  return ret
+}
+// 获取接口对应的价格权限code
+export function getAuthPriceCode (config, router, store) {
+  // 通过路由打开的页面的权限code
+  const permission = router.history.current.meta.permission 
+  // 手动指定的权限code,如打开的弹框页面或导出、打印
+  // 手动指定的权限在使用完后需要清空,如在关闭弹框或导出、打印接口调用完成后清空
+  const curActionPermission = store.state.app.curActionPermission
+  // 价格权限的所有选项,销售价、成本价、省、市、特约价
+  const priceOptions = store.state.app.priceAuthOptions
+  // 最终获取的权限code,手动指定的优先级高于路由打开的页面权限code
+  const authCode = curActionPermission || permission
+  // 当前角色的分配的价格权限,这里过滤非价格权限code
+  const roles = store.state.user.roles
+  const userAuthCode = roles.permissionList.filter(item => {
+    const a = item.split('_')
+    return priceOptions.find(k => k.value == a[a.length-1])
+  })
+  // console.log(userAuthCode)
+  console.log(authCode)
+  // 如果有权限code
+  if(authCode){
+    // 当前正在调用的接口url
+    const url = config.url
+    // 所有的权限菜单数据
+    const authTree = store.state.app.authMenusList
+    // 从所有的权限菜单中查找当前权限code对应的权限菜单数据
+    const authNode = treeFind(authTree,(item)=>item.code == authCode)
+    console.log(authNode)
+    if(!authNode.permission){return []}
+    // 从找到的对应权限菜单数据中判断当前调用接口的url是否存在,这里和权限菜单中的后台权限code比较
+    const hasReqUrl = authNode.permission.split(',').find(item => url.replace(/\//g,'_').indexOf(item)>=0)
+    // 如果存在则返回一个如 [1,0,1,0,0] 的格式的价格权限字符串给后台接口
+    if(hasReqUrl&&authNode.children&&authNode.children.length){
+      return hasPriceAuth(authNode.children,priceOptions,userAuthCode)
+    }
+    return []
+  }
+  return []
 }

+ 22 - 55
src/views/Home.vue

@@ -1,21 +1,6 @@
 <template>
   <div class="home">
-    <div class="home-body">
-      <h1>{{ message }}</h1>
-      <!-- <div class="navBox">
-        <div class="navTitle">大屏数据</div>
-        <div class="navList">
-          <div @click="topage('realTimeSalesReport')">
-            <div><a-icon style="font-size: 30px;color: #00aaff;" type="fund" /></div>
-            <div>实时销售看板</div>
-          </div>
-          <div @click="topage('fPanalysisReport')">
-            <div><a-icon style="font-size: 30px;color: #ffaa00;" type="bar-chart" /></div>
-            <div>加盟商/产品分析</div>
-          </div>
-        </div>
-      </div> -->
-    </div>
+    <a-alert :message="message" type="info" />
     <!-- 重置密码 -->
     <a-modal
       class="resetPwdModal"
@@ -52,6 +37,7 @@ import { mapGetters, mapActions } from 'vuex'
 import ResetPwd from '@/views/user/ResetPwd.vue'
 import newProduct from '@/views/productManagement/newProduct/modal.vue'
 import { queryNewProductPage } from '@/api/product'
+import { getYyMenuList } from '@/api/menu.js'
 export default {
   name: 'Home',
   mixins: [commonMixin],
@@ -71,6 +57,14 @@ export default {
   },
   methods: {
     ...mapActions(['GetEmployeeList', 'getReturnReasonData']),
+    // 获取菜单树列表
+    getYyMenuList () {
+      getYyMenuList().then(res => {
+        if (res.status == 200) {
+          this.$store.state.app.authMenusList = res.data
+        }
+      })
+    },
     hasNewProduct () {
       this.GetEmployeeList()
       queryNewProductPage({ pageNo: 1, pageSize: 20, onlineFalg: this.onlineFalg }).then(res => {
@@ -99,9 +93,6 @@ export default {
         this.onlineFalg = '0'
         setTimeout(() => { _this.hasNewProduct() }, 100)
       }
-    },
-    topage (page) {
-      this.$router.push({ name: page })
     }
   },
   beforeRouteEnter (to, from, next) {
@@ -117,46 +108,22 @@ export default {
         vm.openResetPwd = true
       }
       vm.getReturnReasonData('RETURN_REASON')
+      vm.getYyMenuList()
+      vm.$store.state.app.priceAuthOptions = [
+        { label: '售价', value: 'salesPrice' },
+        { label: '成本价', value: 'costPrice' },
+        { label: '省级价', value: 'provincePrice' },
+        { label: '市级价', value: 'cityPrice' },
+        { label: '特约价', value: 'specialPrice' }
+      ]
     })
   }
 }
 </script>
-<style lang="less" scoped>
+<style scoped>
   .home {
-    .home-body{
-      background: #fff;
-      padding: 10px;
-      margin-top:10px;
-      border-radius: 5px;
-      h1{
-        font-size: 24px;
-      }
-      .navBox{
-        .navTitle{
-          font-size: 16px;
-          border-bottom: 1px solid #eee;
-          padding: 10px  0;
-        }
-        .navList{
-          display: flex;
-          align-items: center;
-          padding: 10px;
-          > div{
-            border:1px solid #eee;
-            margin: 10px;
-            padding: 10px;
-            border-radius: 5px;
-            text-align: center;
-            cursor: pointer;
-            &:hover{
-              border-color: #00aaff;
-            }
-            > div:first-child{
-              padding-bottom: 8px;
-            }
-          }
-        }
-      }
-    }
+    /* width: 900px;
+    margin: 0 auto;
+    padding: 25px 0; */
   }
 </style>

+ 34 - 10
src/views/allocationManagement/matchSendOutOrder/list.vue

@@ -17,7 +17,7 @@
             </a-col>
             <a-col :md="6" :sm="24">
               <a-form-item label="收货客户名称">
-                <dealerSubareaScopeList ref="receiverSn" defValKey="buyerSn" @change="custChange" v-model="queryParam.receiverSn" />
+                <dealerSearchList ref="receiverSn" @change="custChange" />
               </a-form-item>
             </a-col>
             <template v-if="advanced">
@@ -76,7 +76,7 @@
         bordered>
         <!-- 单号 -->
         <template slot="allocateNo" slot-scope="text, record">
-          <span v-if="$hasPermissions('M_mso_detail')" class="link-bule" @click="handleDetail(record)">{{ record.allocateNo }}</span>
+          <span v-if="$hasPermissions('M_transferOut_detail')" class="link-bule" @click="handleDetail(record)">{{ record.allocateNo }}</span>
           <span v-else>{{ record.allocateNo }}</span>
         </template>
         <!-- 操作 -->
@@ -92,6 +92,16 @@
         </template>
       </s-table>
     </a-spin>
+    <!-- 查看详情 -->
+    <commonModal
+      modalTit="调拨单详情"
+      bodyPadding="10px"
+      width="70%"
+      :showFooter="false"
+      :openModal="showDetailModal"
+      @cancel="cancelDetail">
+      <allocationDetailModal v-if="showDetailModal" :outBizSn="bizSn" />
+    </commonModal>
   </a-card>
 </template>
 
@@ -101,12 +111,14 @@ import moment from 'moment'
 import getDate from '@/libs/getDate.js'
 import { STable, VSelect } from '@/components'
 import rangeDate from '@/views/common/rangeDate.vue'
-import dealerSubareaScopeList from '@/views/common/dealerSubareaScopeList.vue'
+import commonModal from '@/views/common/commonModal.vue'
+import dealerSearchList from '@/views/common/dealerSearchList.vue'
+import allocationDetailModal from '@/views/allocationManagement/transferOut/detail.vue'
 import { allocateBillList, allocateBillCheck } from '@/api/allocateBill'
 export default {
   name: 'MatchSendOutOrderAllocationList',
   mixins: [commonMixin],
-  components: { STable, VSelect, rangeDate, dealerSubareaScopeList },
+  components: { STable, VSelect, rangeDate, dealerSearchList, commonModal, allocationDetailModal },
   data () {
     return {
       spinning: false,
@@ -126,6 +138,7 @@ export default {
         checkStatus: undefined,
         printState: undefined
       },
+      showDetailModal: false,
       disabled: false, //  查询、重置按钮是否可操作
       exportLoading: false,
       // 加载数据方法 必须为 Promise 对象
@@ -148,6 +161,7 @@ export default {
       },
       visibleAudit: false,
       auditInfo: null,
+      bizSn: '',
       spinningAudit: false,
       openModal: false //  新增编辑  弹框
     }
@@ -173,8 +187,13 @@ export default {
   },
   methods: {
     custChange (val) {
-      this.queryParam.receiverSn = val.key || ''
-      this.queryParam.receiverName = val.name || ''
+      if (val.row) {
+        this.queryParam.receiverSn = val.row.dealerSn
+        this.queryParam.receiverName = undefined
+      } else {
+        this.queryParam.receiverSn = undefined
+        this.queryParam.receiverName = val.key
+      }
     },
     //  创建时间  change
     dateChange (date) {
@@ -218,9 +237,14 @@ export default {
     },
     //  详情
     handleDetail (row) {
-      if (this.$hasPermissions('M_transferOut_detail')) {
-        this.$router.push({ path: `/allocationManagement/transferOut/detail/${row.allocateSn}` })
-      }
+      this.$store.state.app.curActionPermission = 'M_transferOut_detail'
+      this.bizSn = row.allocateSn
+      this.showDetailModal = true
+    },
+    cancelDetail () {
+      this.$store.state.app.curActionPermission = ''
+      this.showDetailModal = false
+      this.bizSn = null
     },
     pageInit () {
       const _this = this
@@ -231,7 +255,7 @@ export default {
     },
     setTableH () {
       const tableSearchH = this.$refs.tableSearch.offsetHeight
-      this.tableHeight = window.innerHeight - tableSearchH - 195
+      this.tableHeight = window.innerHeight - tableSearchH - 200
     }
   },
   watch: {

+ 15 - 7
src/views/allocationManagement/transferOut/basicInfoModal.vue

@@ -7,7 +7,7 @@
     :title="isEdit?'编辑':'新增'"
     v-model="isShow"
     @cancel="isShow = false"
-    :width="800">
+    :width="900">
     <a-spin :spinning="spinning" tip="Loading...">
       <a-form-model
         id="allocateBill-basicInfo-form"
@@ -26,7 +26,7 @@
             </a-form-model-item>
           </a-col>
           <a-col :md="12" :sm="24" v-if="!isEdit">
-            <a-form-model-item label="调往对象名称" :prop="isDealer ? 'targetSn' : 'targetName'">
+            <a-form-model-item label="调往对象名称" :prop="isDealer||isDepartment ? 'targetSn' : 'targetName'">
               <a-select
                 v-if="isDealer"
                 show-search
@@ -41,7 +41,8 @@
                 <a-spin v-if="fetching" slot="notFoundContent" size="small" />
                 <a-select-option v-for="item in dealerData" :key="item.dealerSn" :value="item.dealerSn">{{ item.dealerName }}</a-select-option>
               </a-select>
-              <a-input v-if="!isDealer" v-model.trim="form.targetName" placeholder="请输入调往对象名称(最多30个字符)" allowClear :maxLength="30" />
+              <department v-else-if="isDepartment" style="width: 100%;" placeholder="请选择部门" @change="departementChange" v-model="form.targetSn"></department>
+              <a-input v-else v-model="form.targetName" placeholder="请输入调往对象名称(最多30个字符)" :maxLength="30"></a-input>
             </a-form-model-item>
           </a-col>
           <a-col :md="12" :sm="24">
@@ -110,10 +111,11 @@ import { getLookUpData } from '@/api/data'
 import ProductBrand from '@/views/common/productBrand.js'
 import productTypeAll from '@/views/common/productTypeAll.js'
 import AllocateType from '@/views/common/allocateType.js'
+import department from '@/views/expenseManagement/expenseReimbursement/department.js'
 export default {
   name: 'TransferOutBasicInfoModal',
   mixins: [commonMixin],
-  components: { VSelect, Upload, ProductBrand, productTypeAll, AllocateType },
+  components: { VSelect, Upload, ProductBrand, productTypeAll, AllocateType, department },
   props: {
     openModal: {
       //  弹框显示状态
@@ -169,6 +171,9 @@ export default {
     // 当前所选调往对象是否为经销商
     isDealer () {
       return this.form.targetType == 'DEALER'
+    },
+    isDepartment () {
+      return this.form.targetType == 'DEPARTMENT'
     }
   },
   methods: {
@@ -186,6 +191,10 @@ export default {
         item.fileType = item.extName
       })
     },
+    departementChange (v, row) {
+       console.log(v,row)
+       this.form.targetName = row.name
+    },
     // 调拨类别 change
     allocateTypeChange (val, opt) {
       console.log(val, opt, '------------')
@@ -249,12 +258,11 @@ export default {
               _this.$message.success(res.message)
               _this.isShow = false
               _this.$emit('ok', res.data)
-            } else {
-              _this.spinning = false
             }
+            _this.spinning = false
           })
         } else {
-          console.log('error submit!!')
+          _this.spinning = false
           return false
         }
       })

+ 18 - 15
src/views/allocationManagement/transferOut/detail.vue

@@ -106,9 +106,9 @@
         <!-- 总计 -->
         <a-alert type="info" style="margin-bottom:10px">
           <div slot="message">
-            总数量:<strong>{{ (productTotal&&(productTotal.totalQty || productTotal.totalQty==0)) ? productTotal.totalQty : '--' }}</strong> 
-            <span v-if="$hasPermissions('B_isShowCost')">总成本(¥):<strong>{{ (productTotal&&(productTotal.totalCost || productTotal.totalCost==0)) ? productTotal.totalCost : '--' }}</strong> ,</span>
-            <span v-if="$hasPermissions('B_isShowPrice')">总售价(¥):<strong>{{ (productTotal&&(productTotal.totalPrice || productTotal.totalPrice==0)) ? productTotal.totalPrice : '--' }}</strong></span>
+            总数量:<strong>{{ (productTotal&&(productTotal.totalQty || productTotal.totalQty==0)) ? productTotal.totalQty : '--' }}</strong> 
+            <span v-if="$hasPermissions('M_transferOut_detail_costPrice')||$hasPermissions('M_tfoPrint_detail_costPrice')||$hasPermissions('M_mso_detail_costPrice')">总成本:<strong>{{ (productTotal&&(productTotal.totalCost || productTotal.totalCost==0)) ? toThousands(productTotal.totalCost) : '--' }}</strong> ;</span>
+            <span v-if="$hasPermissions('M_transferOut_detail_salesPrice')||$hasPermissions('M_tfoPrint_detail_salesPrice')||$hasPermissions('M_mso_detail_salesPrice')">总售价:<strong>{{ (productTotal&&(productTotal.totalPrice || productTotal.totalPrice==0)) ? toThousands(productTotal.totalPrice) : '--' }}</strong></span>
           </div>
         </a-alert>
         <!-- 列表 -->
@@ -183,6 +183,7 @@ export default {
       return this.basicInfoData && ((this.basicInfoData.state == 'WAIT_SUBMIT') || (this.basicInfoData.state == 'WAIT_AUDIT') || (this.basicInfoData.state == 'AUDIT_REJECT')) && this.$hasPermissions('M_transferOut_edit')
     },
     columns () {
+      const _this = this
       const arr = [
         { title: '序号', dataIndex: 'no', width: '4%', align: 'center' },
         { title: '产品编码', dataIndex: 'productEntity.code', width: '10%', align: 'center', customRender: function (text) { return text || '--' } },
@@ -191,14 +192,14 @@ export default {
         { title: '单位', dataIndex: 'productEntity.unit', width: '5%', align: 'center', customRender: function (text) { return text || '--' } },
         { title: '调出数量', dataIndex: 'qty', width: '8%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } }
       ]
-      if (this.$hasPermissions('B_isShowCost')) { // 成本价权限
-        arr.splice(5, 0, { title: '成本价', dataIndex: 'cost', width: '9%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } })
-        arr.splice(8, 0, { title: '成本小计(¥)', dataIndex: 'totalCost', width: '9%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } })
+      if (this.$hasPermissions('M_transferOut_detail_costPrice')||this.$hasPermissions('M_tfoPrint_detail_salesPrice')||this.$hasPermissions('M_mso_detail_costPrice')) { // 成本价权限
+        arr.splice(5, 0, { title: '成本价', dataIndex: 'cost', width: '9%', align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } })
+        arr.splice(8, 0, { title: '成本小计', dataIndex: 'totalCost', width: '9%', align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } })
       }
-      if (this.$hasPermissions('B_isShowPrice')) { //  售价权限
-        const ind = this.$hasPermissions('B_isShowCost') ? 6 : 5
-        arr.splice(ind, 0, { title: '售价', dataIndex: 'price', width: '8%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } })
-        arr.splice(ind + 3, 0, { title: '售价小计(¥)', dataIndex: 'totalPrice', width: '9%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } })
+      if (this.$hasPermissions('M_transferOut_detail_salesPrice')||this.$hasPermissions('M_tfoPrint_detail_salesPrice')||this.$hasPermissions('M_mso_detail_salesPrice')) { //  售价权限
+        const ind = this.$hasPermissions('M_transferOut_detail_costPrice')||this.$hasPermissions('M_tfoPrint_detail_costPrice') ? 6 : 5
+        arr.splice(ind, 0, { title: '售价', dataIndex: 'price', width: '8%', align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } })
+        arr.splice(ind + 3, 0, { title: '售价小计', dataIndex: 'totalPrice', width: '9%', align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } })
       }
       arr.push({ title: '费用归属部门', dataIndex: 'departmentName', width: '8%', align: 'center', customRender: function (text) { return text || '--' } })
       return arr
@@ -207,7 +208,7 @@ export default {
   methods: {
     //  返回列表
     handleBack () {
-      this.$router.push({ path: '/allocationManagement/transferOut/list', query: { closeLastOldTab: true } })
+      this.$router.push({ name: 'transferOutList', query: { closeLastOldTab: true } })
     },
     // 基本信息
     getDetail () {
@@ -244,10 +245,9 @@ export default {
       const filename = this.nowType == 'dbflExport' ? '调拨分类' : '调拨'
       this.spinning = true
       const params = { allocateSn: this.outBizSn || this.$route.params.sn, ...data }
-      params.showCostFlag = this.$hasPermissions('B_isShowCost')
-      params.showAmountFlag = this.$hasPermissions('B_isShowPrice')
       exportExcel(allocateBillDetailExcel, params, filename, function () {
         _this.spinning = false
+        _this.$store.state.app.curActionPermission = ''
       })
     },
     // 打印成功
@@ -262,9 +262,9 @@ export default {
         params,
         objs.isPreview ? 'preview' : 'print',
         taskName,
-        (res) => {
-          _this.$message.info(res.message)
+        () => {
           _this.spinning = false
+          _this.$store.state.app.curActionPermission = ''
         },
         {
           billType: 'ALLOCATE',
@@ -290,6 +290,9 @@ export default {
       this.pageInit()
     }
   },
+  deactivated(){
+    this.$store.state.app.curActionPermission = ''
+  },
   beforeRouteEnter (to, from, next) {
     next(vm => {})
   }

+ 10 - 1
src/views/allocationManagement/transferOut/dsModal.vue

@@ -41,6 +41,14 @@
               常用:<a-button size="small" v-for="i in 5" @click="setSendNo(i)" type="link">{{ i }}</a-button>
             </div>
           </a-form-model-item>
+          <a-form-model-item label="发货说明">
+            <a-input
+              id="dealerAccountEdit-explainInfo"
+              type="textarea"
+              :maxLength="630"
+              v-model.trim="form.explainInfo"
+              placeholder="请输入发货说明"/>
+          </a-form-model-item>
           <a-form-model-item label="备货打印" prop="printState">
             <a-radio-group v-model="form.printState">
               <a-radio value="NO_PRINT">
@@ -93,7 +101,8 @@ export default {
         sendNo: '',
         printState: '',
         receiverSn: '',
-        receiverName: ''
+        receiverName: '',
+        explainInfo: ''
       },
       rules: {
         sendNo: [{ required: true, message: '请输入发货编号', trigger: 'change' }],

+ 20 - 22
src/views/allocationManagement/transferOut/edit.vue

@@ -175,9 +175,9 @@
             <!-- 总计 -->
             <a-alert type="info" style="margin-bottom:10px">
               <div slot="message">
-                总数量:<strong>{{ (productTotal&&(productTotal.totalQty || productTotal.totalQty==0)) ? productTotal.totalQty : '--' }}</strong> 
-                <span v-if="$hasPermissions('B_isShowCost')">总成本(¥):<strong>{{ (productTotal&&(productTotal.totalCost || productTotal.totalCost==0)) ? productTotal.totalCost : '--' }}</strong> ,</span>
-                <span v-if="$hasPermissions('B_isShowPrice')">总售价(¥):<strong>{{ (productTotal&&(productTotal.totalPrice || productTotal.totalPrice==0)) ? productTotal.totalPrice : '--' }}</strong></span>
+                总数量:<strong>{{ (productTotal&&(productTotal.totalQty || productTotal.totalQty==0)) ? productTotal.totalQty : '--' }}</strong> 
+                <span v-if="$hasPermissions('M_transferOut_edit_costPrice')">总成本:<strong>{{ (productTotal&&(productTotal.totalCost || productTotal.totalCost==0)) ? toThousands(productTotal.totalCost) : '--' }}</strong> ;</span>
+                <span v-if="$hasPermissions('M_transferOut_edit_salesPrice')">总售价:<strong>{{ (productTotal&&(productTotal.totalPrice || productTotal.totalPrice==0)) ? toThousands(productTotal.totalPrice) : '--' }}</strong></span>
               </div>
             </a-alert>
             <!-- 筛选条件 -->
@@ -248,7 +248,7 @@
                     <a-select-option v-if="loadDataSource&&loadDataSource[index]&&loadDataSource[index].specialPrice" :value="loadDataSource[index].specialPrice" :key="'C-'+loadDataSource[index].productSn" :label="loadDataSource[index].specialPrice">C价 {{ loadDataSource[index].specialPrice }}</a-select-option>
                   </a-select>
                 </div>
-                <span v-else>{{ record.price }}</span>
+                <span v-else>{{ toThousands(record.price) }}</span>
               </template>
               <!-- 调出数量 -->
               <template slot="qty" slot-scope="text, record">
@@ -377,10 +377,6 @@ export default {
       loading: false,
       chooseDisabled: false, //  查询、重置按钮是否可操作
       advanced: false, // 高级搜索 展开/关闭
-      productBrandList: [], //  产品品牌  下拉数据
-      productTypeList: [], //  产品分类  下拉数据
-      productType: [],
-      warehouseList: [], //  仓库  下拉数据
       departmentList: [], // 部门列表
       // 加载数据方法 必须为 Promise 对象
       loadData: parameter => {
@@ -433,6 +429,7 @@ export default {
       return this.rowSelectionInfo && this.rowSelectionInfo.selectedRowKeys.length || 0
     },
     columns () {
+      const _this = this
       const arr = [
         { title: '序号', dataIndex: 'no', width: '4%', align: 'center' },
         { title: '产品编码', dataIndex: 'productCode', width: '10%', align: 'center', customRender: function (text) { return text || '--' } },
@@ -445,16 +442,17 @@ export default {
         { title: '单位', dataIndex: 'productUnit', width: '6%', align: 'center', customRender: function (text) { return text || '--' } },
         { title: '操作', scopedSlots: { customRender: 'action1' }, width: '10%', align: 'center' }
       ]
-      if (this.$hasPermissions('B_isShowCost')) { //  成本价权限
-        arr.splice(4, 0, { title: '成本价', dataIndex: 'lastStockCost', width: '10%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } })
+      if (this.$hasPermissions('M_transferOut_edit_costPrice')) { //  成本价权限
+        arr.splice(4, 0, { title: '成本价', dataIndex: 'lastStockCost', width: '10%', align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } })
       }
-      if (this.$hasPermissions('B_isShowPrice')) { //  售价权限
-        const ind = this.$hasPermissions('B_isShowCost') ? 5 : 4
-        arr.splice(ind, 0, { title: '售价', dataIndex: 'productPrice', width: '10%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } })
+      if (this.$hasPermissions('M_transferOut_edit_salesPrice')) { //  售价权限
+        const ind = this.$hasPermissions('M_transferOut_edit_costPrice') ? 5 : 4
+        arr.splice(ind, 0, { title: '售价', dataIndex: 'productPrice', width: '10%', align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } })
       }
       return arr
     },
     chooseColumns () {
+      const _this = this
       const arr = [
         { title: '序号', dataIndex: 'no', width: '4%', align: 'center' },
         { title: '产品编码', dataIndex: 'productEntity.code', width: '10%', align: 'center', customRender: function (text) { return text || '--' } },
@@ -468,12 +466,12 @@ export default {
         { title: '单位', dataIndex: 'productEntity.unit', width: '6%', align: 'center', customRender: function (text) { return text || '--' } },
         { title: '操作', scopedSlots: { customRender: 'action' }, width: '6%', align: 'center' }
       ]
-      if (this.$hasPermissions('B_isShowCost')) { //  成本价权限
-        arr.splice(4, 0, { title: '成本价', dataIndex: 'cost', width: '10%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } })
+      if (this.$hasPermissions('M_transferOut_edit_costPrice')) { //  成本价权限
+        arr.splice(4, 0, { title: '成本价', dataIndex: 'cost', width: '10%', align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } })
       }
-      if (this.$hasPermissions('B_isShowPrice')) { //  售价权限
-        const ind = this.$hasPermissions('B_isShowCost') ? 5 : 4
-        arr.splice(ind, 0, { title: '售价', scopedSlots: { customRender: 'price' }, width: '10%', align: 'center' })
+      if (this.$hasPermissions('M_transferOut_edit_salesPrice')) { //  售价权限
+        const ind = this.$hasPermissions('M_transferOut_edit_costPrice') ? 5 : 4
+        arr.splice(ind, 0, { title: '售价', scopedSlots: { customRender: 'price' }, width: '10%', align: 'right' })
       }
       return arr
     }
@@ -739,10 +737,10 @@ export default {
       const _this = this
       this.spinning = true
       const params = { allocateSn: this.outBizSn || this.$route.params.sn, printType: printType, ...data }
-      params.showCostFlag = this.$hasPermissions('B_isShowCost')
-      params.showAmountFlag = this.$hasPermissions('B_isShowPrice')
+      
       exportExcel(allocateBillDetailExcel, params, filename, function () {
         _this.spinning = false
+        _this.$store.state.app.curActionPermission = ''
       })
     },
     exportFl (data) {
@@ -757,16 +755,16 @@ export default {
       const _this = this
       const params = JSON.parse(JSON.stringify(objs))
       delete params.type
-      _this.spinning = true
       const taskName = this.nowType == 'dbPrint' ? '调拨' : '调拨分类'
+      _this.spinning = true
       printFun(
         allocateBillDetailPrint,
         params,
         objs.isPreview ? 'preview' : 'print',
         taskName,
         (res) => {
-          _this.$message.info(res.message)
           _this.spinning = false
+          _this.$store.state.app.curActionPermission = ''
         },
         {
           billType: 'ALLOCATE',

+ 22 - 12
src/views/allocationManagement/transferOut/list.vue

@@ -23,7 +23,7 @@
             <template v-if="advanced">
               <a-col :md="6" :sm="24">
                 <a-form-item label="收货客户名称">
-                  <dealerSubareaScopeList ref="receiverSn" defValKey="buyerSn" @change="custChange" v-model="queryParam.receiverSn" />
+                  <dealerSearchList ref="receiverSn" @change="custChange" />
                 </a-form-item>
               </a-col>
               <a-col :md="4" :sm="24">
@@ -187,7 +187,7 @@ import { STable, VSelect } from '@/components'
 import basicInfoModal from './basicInfoModal.vue'
 import rangeDate from '@/views/common/rangeDate.vue'
 import auditModal from '@/views/common/auditModal.vue'
-import dealerSubareaScopeList from '@/views/common/dealerSubareaScopeList.vue'
+import dealerSearchList from '@/views/common/dealerSearchList.vue'
 import { allocateBillList, allocateBillDel, allocateBillAudit, allocateBillExport, allocateBillAblePrint } from '@/api/allocateBill'
 import AllocateType from '@/views/common/allocateType.js'
 import { hdExportExcel } from '@/libs/exportExcel'
@@ -195,7 +195,7 @@ import printModal from './printStatusModal.vue'
 export default {
   name: 'TransferOutList',
   mixins: [commonMixin],
-  components: { STable, VSelect, basicInfoModal, printModal, rangeDate, auditModal, AllocateType, dealerSubareaScopeList },
+  components: { STable, VSelect, basicInfoModal, printModal, rangeDate, auditModal, AllocateType, dealerSearchList },
   data () {
     return {
       spinning: false,
@@ -250,6 +250,7 @@ export default {
   computed: {
     // dataIndex: 'printStateDictValue',
     columns () {
+      const _this = this
       const arr = [
         { title: '序号', dataIndex: 'no', width: '3.5%', align: 'center' },
         { title: '创建时间', dataIndex: 'createDate', width: '6%', align: 'center', customRender: function (text) { return text || '--' } },
@@ -257,7 +258,8 @@ export default {
         { title: '起止时间', scopedSlots: { customRender: 'promoDate' }, align: 'center', width: '6%' },
         { title: '调往对象', dataIndex: 'targetName', width: '8%', align: 'left', customRender: function (text) { return text || '--' }, ellipsis: true },
         { title: '客户类型', dataIndex: 'dealerLevelDictValue', width: '6%', align: 'center', customRender: function (text) { return text || '--' } },
-        { title: '发货编号', dataIndex: 'sendNo', width: '5%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
+        { title: '发货编号', dataIndex: 'sendNo', width: '6%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '发货说明', dataIndex: 'explainInfo', width: '14%', align: 'center', customRender: function (text) { return text || '--' }, ellipsis: true },
         { title: '收货客户名称', dataIndex: 'receiverName', width: '8%', align: 'left', customRender: function (text) { return text || '--' }, ellipsis: true },
         { title: '总数量', dataIndex: 'totalQty', width: '5%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
         // { title: '总售价', dataIndex: 'totalPrice', width: '5%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
@@ -270,12 +272,12 @@ export default {
         { title: '对单状态', dataIndex: 'checkStatusDictValue', width: '6%', align: 'center', customRender: function (text) { return text || '--' } },
         { title: '操作', scopedSlots: { customRender: 'action' }, width: '10%', align: 'center' }
       ]
-      if (this.$hasPermissions('B_isShowCost')) { //  成本价权限
-        arr.splice(8, 0, { title: '总成本', dataIndex: 'totalCost', width: '5%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } })
+      if (this.$hasPermissions('M_transferOutList_costPrice')) { //  成本价权限
+        arr.splice(8, 0, { title: '总成本', dataIndex: 'totalCost', width: '5%', align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } })
       }
-      if (this.$hasPermissions('B_isShowPrice')) { //  售价权限
-        const ind = this.$hasPermissions('B_isShowCost') ? 10 : 9
-        arr.splice(ind, 0, { title: '总售价', dataIndex: 'totalPrice', width: '5%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } })
+      if (this.$hasPermissions('M_transferOutList_salesPrice')) { //  售价权限
+        const ind = this.$hasPermissions('M_transferOutList_costPrice') ? 10 : 9
+        arr.splice(ind, 0, { title: '总售价', dataIndex: 'totalPrice', width: '5%', align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } })
       }
       return arr
     }
@@ -287,8 +289,13 @@ export default {
       this.$refs.table.refresh(true)
     },
     custChange (val) {
-      this.queryParam.receiverSn = val.key || ''
-      // this.queryParam.receiverName = val.name || ''
+      if (val.row) {
+        this.queryParam.receiverSn = val.row.dealerSn
+        this.queryParam.receiverName = undefined
+      } else {
+        this.queryParam.receiverSn = undefined
+        this.queryParam.receiverName = val.key
+      }
     },
     //  创建时间  change
     dateChange (date) {
@@ -314,6 +321,7 @@ export default {
       this.queryParam.checkStatus = undefined
       this.queryParam.printState = undefined
       this.queryParam.allocateNo = ''
+      this.queryParam.receiverName = ''
       this.queryParam.receiverSn = undefined
       this.allocateTypeVal = []
       this.$refs.receiverSn.resetForm()
@@ -399,12 +407,14 @@ export default {
     //  导出
     handleExport () {
       const _this = this
+      this.$store.state.app.curActionPermission = 'B_transferOut_export'
       const params = this.queryParam
       this.exportLoading = true
       this.spinning = true
       hdExportExcel(allocateBillExport, params, '调拨列表', function () {
         _this.exportLoading = false
         _this.spinning = false
+        _this.$store.state.app.curActionPermission = ''
       })
     },
     pageInit () {
@@ -416,7 +426,7 @@ export default {
     },
     setTableH () {
       const tableSearchH = this.$refs.tableSearch.offsetHeight
-      this.tableHeight = window.innerHeight - tableSearchH - 238
+      this.tableHeight = window.innerHeight - tableSearchH - 242
     },
     handlePrint (item) {
       const obj = {

+ 23 - 5
src/views/allocationManagement/transferOut/printModal.vue

@@ -36,13 +36,20 @@
             <a-radio value="-1">不打印</a-radio>
           </a-radio-group>
         </a-form-model-item>
-        <a-form-model-item label="产品价格" prop="priceType" v-if="nowType=='dbPrint'||nowType=='dbExport'">
+        <a-form-model-item label="产品价格" prop="priceType" v-if="nowType=='dbPrint'">
           <a-radio-group v-model="form.priceType">
-            <a-radio value="ALLOCATE_BILL_PRICE">销售价</a-radio>
-            <a-radio value="ALLOCATE_BILL_COST">成本价</a-radio>
+            <a-radio value="ALLOCATE_BILL_PRICE" v-if="$hasPermissions('B_transferOut_print_salesPrice')">销售价</a-radio>
+            <a-radio value="ALLOCATE_BILL_COST" v-if="$hasPermissions('B_transferOut_print_costPrice')">成本价</a-radio>
             <a-radio value="ALLOCATE_BILL">不打印</a-radio>
           </a-radio-group>
         </a-form-model-item>
+        <a-form-model-item label="产品价格" prop="priceType" v-if="nowType=='dbExport'">
+          <a-radio-group v-model="form.priceType">
+            <a-radio value="ALLOCATE_BILL_PRICE" v-if="$hasPermissions('B_transferOut_detail_export_salesPrice')">销售价</a-radio>
+            <a-radio value="ALLOCATE_BILL_COST" v-if="$hasPermissions('B_transferOut_detail_export_costPrice')">成本价</a-radio>
+            <a-radio value="ALLOCATE_BILL">不导出</a-radio>
+          </a-radio-group>
+        </a-form-model-item>
       </a-form-model>
       <div class="btn-cont">
         <a-button id="allocateBill-print-close" @click="handleClose('preview')">取消</a-button>
@@ -94,7 +101,7 @@ export default {
       isShow: this.openModal, //  是否打开弹框
       form: {
         id: 'all',
-        priceType: undefined,
+        priceType: 'ALLOCATE_BILL',
         orderBy: undefined
       },
       rules: {
@@ -134,6 +141,17 @@ export default {
       const _this = this
       this.$refs.ruleForm.validate(valid => {
         if (valid) {
+          let authCode = ''
+          if (this.nowType == 'dbPrint') {
+            authCode = 'B_transferOut_print'
+          } else if (this.nowType == 'dbflPrint') {
+            authCode = 'B_transferOutType_print'
+          } else if (this.nowType == 'dbflExport') {
+            authCode = 'B_transferOutType_export'
+          } else if (this.nowType == 'dbExport') {
+            authCode = 'B_transferOut_detail_export'
+          }
+          this.$store.state.app.curActionPermission = authCode
           // 普通打印/导出
           const obj = {
             allocateSn: _this.itemData.allocateSn,
@@ -186,7 +204,7 @@ export default {
       this.$refs.ruleForm.resetFields()
       this.form = {
         id: 'all',
-        priceType: undefined
+        priceType: 'ALLOCATE_BILL'
       }
     }
   },

+ 11 - 2
src/views/allocationManagement/transferReturn/basicInfoModal.vue

@@ -42,7 +42,8 @@
             <a-spin v-if="fetching" slot="notFoundContent" size="small" />
             <a-select-option v-for="item in dealerData" :key="item.dealerSn" :value="item.dealerSn">{{ item.dealerName }}</a-select-option>
           </a-select>
-          <a-input v-if="!isDealer" v-model.trim="form.targetName" placeholder="请输入调拨退货对象名称(最多30个字符)" allowClear :maxLength="30" />
+          <department v-else-if="isDepartment" style="width: 100%;" placeholder="请选择部门" @change="departementChange" v-model="form.targetSn"></department>
+          <a-input v-else v-model.trim="form.targetName" placeholder="请输入调拨退货对象名称(最多30个字符)" allowClear :maxLength="30" />
         </a-form-model-item>
         <a-form-model-item label="费用/调拨退货类型" prop="costTypeSn">
           <AllocateType id="allocateBill-basicInfo-allocateTypeSn" v-model="allocateTypeVal" placeholder="请选择费用/调拨退货类型" @change="allocateTypeChange"></AllocateType>
@@ -74,11 +75,12 @@ import { commonMixin } from '@/utils/mixin'
 import debounce from 'lodash/debounce'
 import { VSelect } from '@/components'
 import { allocateReturnSave, allocateReturnQueryBySn } from '@/api/allocateReturn'
+import department from '@/views/expenseManagement/expenseReimbursement/department.js'
 import { dealerSubareaScopeList } from '@/api/dealer'
 import AllocateType from '@/views/common/allocateType.js'
 export default {
   name: 'TransferOutBasicInfoModal',
-  components: { VSelect, AllocateType },
+  components: { VSelect, AllocateType, department },
   mixins: [commonMixin],
   props: {
     openModal: {
@@ -122,6 +124,9 @@ export default {
     // 当前所选调往对象是否为经销商
     isDealer () {
       return this.form.targetType == 'DEALER'
+    },
+    isDepartment () {
+      return this.form.targetType == 'DEPARTMENT'
     }
   },
   methods: {
@@ -144,6 +149,10 @@ export default {
       const ind = this.dealerData.findIndex(item => item.dealerSn == value)
       this.form.targetName = this.dealerData[ind].dealerName
     },
+    departementChange (v, row) {
+       console.log(v,row)
+       this.form.targetName = row.name
+    },
     // 调拨类别 change
     allocateTypeChange (val, opt) {
       console.log(val, opt, '------------')

+ 5 - 2
src/views/allocationManagement/transferReturn/check.vue

@@ -119,6 +119,7 @@ export default {
   },
   computed: {
     columns () {
+      const _this = this
       const arr = [
         { title: '序号', dataIndex: 'no', width: '4%', align: 'center' },
         { title: '产品编码', dataIndex: 'product.code', align: 'center', width: '23%', customRender: function (text) { return text || '--' } },
@@ -126,13 +127,15 @@ export default {
         { title: '退货数量', dataIndex: 'returnQty', align: 'center', width: '10%', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
         { title: '坏件数量', dataIndex: 'badQty', align: 'center', width: '10%', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
         { title: '返库数量', dataIndex: 'backStockQty', width: '10%', align: 'center', scopedSlots: { customRender: 'backStockQty' } },
-        { title: '单位', dataIndex: 'product.unit', width: '8%', align: 'center', customRender: function (text) { return text || '--' } },
-        { title: '退货单价', dataIndex: 'price', align: 'center', width: '10%', customRender: function (text) { return ((text || text == 0) ? text : '--') } }
+        { title: '单位', dataIndex: 'product.unit', width: '8%', align: 'center', customRender: function (text) { return text || '--' } }
       ]
       console.log(this.grabFlag)
       if (this.grabFlag == 1) { //  抓单
         arr.splice(1, 0, { title: '调拨单号', dataIndex: 'allocateNo', width: '12%', align: 'center', customRender: function (text) { return text || '--' } })
       }
+      if(this.$hasPermissions('M_transferReturnCheck_salesPrice')){
+        arr.splice(this.grabFlag == 1?8:7,0,{ title: '退货单价', dataIndex: 'price', align: 'right', width: '10%', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } })
+      }
       return arr
     }
   },

+ 15 - 7
src/views/allocationManagement/transferReturn/detail.vue

@@ -45,10 +45,10 @@
         <!-- 总计 -->
         <a-alert type="info" style="margin-bottom:10px">
           <div slot="message">
-            退货总数量:<strong>{{ (basicInfoData&&(basicInfoData.totalQty || basicInfoData.totalQty==0)) ? basicInfoData.totalQty : '--' }}</strong> 
-            坏件总数量:<strong>{{ (basicInfoData&&(basicInfoData.totalBadQty || basicInfoData.totalBadQty==0)) ? basicInfoData.totalBadQty : '--' }}</strong> 
-            返库总数量:<strong>{{ (basicInfoData&&(basicInfoData.totalBackStockQty || basicInfoData.totalBackStockQty==0)) ? basicInfoData.totalBackStockQty : '--' }}</strong> 
-            <span>退货总金额(¥):<strong>{{ (basicInfoData&&(basicInfoData.totalPrice || basicInfoData.totalPrice==0)) ? basicInfoData.totalPrice : '--' }}</strong></span>
+            退货总数量:<strong>{{ (basicInfoData&&(basicInfoData.totalQty || basicInfoData.totalQty==0)) ? basicInfoData.totalQty : '--' }}</strong> 
+            坏件总数量:<strong>{{ (basicInfoData&&(basicInfoData.totalBadQty || basicInfoData.totalBadQty==0)) ? basicInfoData.totalBadQty : '--' }}</strong> 
+            返库总数量:<strong>{{ (basicInfoData&&(basicInfoData.totalBackStockQty || basicInfoData.totalBackStockQty==0)) ? basicInfoData.totalBackStockQty : '--' }}</strong> 
+            <span v-if="showPrice||$hasPermissions('M_transferReturnDetail_salesPrice')">退货总金额:<strong>{{ (basicInfoData&&(basicInfoData.totalPrice || basicInfoData.totalPrice==0)) ? toThousands(basicInfoData.totalPrice) : '--' }}</strong></span>
           </div>
         </a-alert>
         <!-- 列表 -->
@@ -81,6 +81,10 @@ export default {
       type: [Number, String],
       default: ''
     },
+    showPrice:{
+      type: Boolean,
+      default: false
+    },
     pageType: {
       type: String,
       default: 'pages'
@@ -117,21 +121,25 @@ export default {
       return this.basicInfoData && ((this.basicInfoData.state == 'WAIT_SUBMIT') || (this.basicInfoData.state == 'FINANCIAL_REJECT') || (this.basicInfoData.state == 'AUDIT_REJECT')) && this.$hasPermissions('B_transferReturnEdit')
     },
     columns () {
+      const _this = this
       const arr = [
         { title: '序号', dataIndex: 'no', width: '4%', align: 'center' },
         { title: '产品编码', dataIndex: 'product.code', width: '10%', align: 'center', customRender: function (text) { return text || '--' } },
         { title: '产品名称', dataIndex: 'product.name', width: '27%', align: 'center', customRender: function (text) { return text || '--' }, ellipsis: true },
         { title: '单位', dataIndex: 'product.unit', width: '5%', align: 'center', customRender: function (text) { return text || '--' } },
-        { title: '退货单价(¥)', dataIndex: 'price', width: '9%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
         { title: '退货数量', dataIndex: 'returnQty', width: '9%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
         { title: '坏件数量', dataIndex: 'badQty', width: '9%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
-        { title: '返库数量', dataIndex: 'backStockQty', width: '9%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
-        { title: '退货金额(¥)', dataIndex: 'totalReturnPrice', width: '9%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } }
+        { title: '返库数量', dataIndex: 'backStockQty', width: '9%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } }
       ]
 
       if (this.basicInfoData && this.basicInfoData.grabFlag == '1') {
         arr.splice(1, 0, { title: '调拨单号', dataIndex: 'allocateNo', width: '10%', align: 'center', customRender: function (text) { return text || '--' } })
       }
+      if(this.showPrice||this.$hasPermissions('M_transferReturnDetail_salesPrice')){
+        const ind = this.basicInfoData && this.basicInfoData.grabFlag == '1' ? 1 : 0
+        arr.splice(4+ind,0,{ title: '退货单价', dataIndex: 'price', width: '9%', align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } })
+        arr.splice(8+ind,0,{ title: '退货金额', dataIndex: 'totalReturnPrice', width: '9%', align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } })
+      }
       return arr
     }
   },

+ 33 - 21
src/views/allocationManagement/transferReturn/edit.vue

@@ -125,8 +125,8 @@
             <!-- 总计 -->
             <a-alert type="info" style="margin-bottom:10px">
               <div slot="message">
-                退货总数量:<strong>{{ (basicInfoData&&(basicInfoData.totalQty || basicInfoData.totalQty==0)) ? basicInfoData.totalQty : '--' }}</strong> 
-                <span>退货总金额(¥):<strong>{{ (basicInfoData&&(basicInfoData.totalPrice || basicInfoData.totalPrice==0)) ? basicInfoData.totalPrice : '--' }}</strong></span>
+                退货总数量:<strong>{{ (basicInfoData&&(basicInfoData.totalQty || basicInfoData.totalQty==0)) ? basicInfoData.totalQty : '--' }}</strong> 
+                <span>退货总金额:<strong>{{ (basicInfoData&&(basicInfoData.totalPrice || basicInfoData.totalPrice==0)) ? toThousands(basicInfoData.totalPrice) : '--' }}</strong></span>
               </div>
             </a-alert>
             <!-- 筛选条件 -->
@@ -265,6 +265,7 @@ export default {
   mixins: [commonMixin],
   components: { STable, VSelect, print, AllocateType },
   data () {
+    const _this = this
     return {
       spinning: false,
       queryParam: {
@@ -299,25 +300,6 @@ export default {
       },
       loadDataSource: [],
       localDataSource: [],
-      columns: [
-        { title: '序号', dataIndex: 'no', width: '4%', align: 'center' },
-        { title: '产品编码', dataIndex: 'productCode', width: '10%', align: 'center', customRender: function (text) { return text || '--' } },
-        { title: '产品名称', dataIndex: 'productName', align: 'center', width: '29%', customRender: function (text) { return text || '--' }, ellipsis: true },
-        { title: '单位', dataIndex: 'productUnit', width: '10%', align: 'center', customRender: function (text) { return text || '--' } },
-        { title: '退货单价', scopedSlots: { customRender: 'returnPrice' }, width: '10%', align: 'center' },
-        { title: '退货数量', scopedSlots: { customRender: 'returnQty' }, width: '10%', align: 'center' },
-        { title: '操作', scopedSlots: { customRender: 'action' }, width: '10%', align: 'center' }
-      ],
-      chooseColumns: [
-        { title: '序号', dataIndex: 'no', width: '4%', align: 'center' },
-        { title: '产品编码', dataIndex: 'product.code', width: '10%', align: 'center', customRender: function (text) { return text || '--' } },
-        { title: '产品名称', dataIndex: 'product.name', align: 'center', width: '29%', customRender: function (text) { return text || '--' }, ellipsis: true },
-        { title: '单位', dataIndex: 'product.unit', width: '10%', align: 'center', customRender: function (text) { return text || '--' } },
-        { title: '退货单价', scopedSlots: { customRender: 'returnPrice' }, width: '10%', align: 'center' },
-        { title: '退货数量', scopedSlots: { customRender: 'returnQty' }, width: '10%', align: 'center' },
-        { title: '退货金额', dataIndex: 'totalReturnPrice', width: '10%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
-        { title: '操作', scopedSlots: { customRender: 'action' }, width: '10%', align: 'center' }
-      ],
       // 加载数据方法 必须为 Promise 对象
       chooseLoadData: parameter => {
         this.chooseDisabled = true
@@ -342,6 +324,36 @@ export default {
       allocateTypeVal: []
     }
   },
+  computed:{
+    columns(){
+      const arr = [
+        { title: '序号', dataIndex: 'no', width: '4%', align: 'center' },
+        { title: '产品编码', dataIndex: 'productCode', width: '10%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '产品名称', dataIndex: 'productName', align: 'center', width: '29%', customRender: function (text) { return text || '--' }, ellipsis: true },
+        { title: '单位', dataIndex: 'productUnit', width: '10%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '退货单价', scopedSlots: { customRender: 'returnPrice' }, width: '10%', align: 'right' },
+        { title: '退货数量', scopedSlots: { customRender: 'returnQty' }, width: '10%', align: 'center' },
+        { title: '操作', scopedSlots: { customRender: 'action' }, width: '10%', align: 'center' }
+      ]
+      return arr
+    },
+    chooseColumns(){
+      const _this = this
+      const arr = [
+        { title: '序号', dataIndex: 'no', width: '4%', align: 'center' },
+        { title: '产品编码', dataIndex: 'product.code', width: '10%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '产品名称', dataIndex: 'product.name', align: 'center', width: '29%', customRender: function (text) { return text || '--' }, ellipsis: true },
+        { title: '单位', dataIndex: 'product.unit', width: '10%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '退货单价', scopedSlots: { customRender: 'returnPrice' }, width: '10%', align: 'right' },
+        { title: '退货数量', scopedSlots: { customRender: 'returnQty' }, width: '10%', align: 'center' },
+        { title: '操作', scopedSlots: { customRender: 'action' }, width: '10%', align: 'center' }
+      ]
+      
+      arr.splice(6,0,{ title: '退货金额', dataIndex: 'totalReturnPrice', width: '10%', align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } })
+     
+      return arr
+    }
+  },
   methods: {
     // 修改备注
     handleEditRemark () {

+ 6 - 8
src/views/allocationManagement/transferReturn/editGrp.vue

@@ -128,8 +128,8 @@
             <!-- 总计 -->
             <a-alert type="info" style="margin-bottom:10px">
               <div slot="message">
-                退货总数量:<strong>{{ (basicInfoData&&(basicInfoData.totalQty || basicInfoData.totalQty==0)) ? basicInfoData.totalQty : '--' }}</strong> 
-                <span>退货总金额(¥):<strong>{{ (basicInfoData&&(basicInfoData.totalPrice || basicInfoData.totalPrice==0)) ? basicInfoData.totalPrice : '--' }}</strong></span>
+                退货总数量:<strong>{{ (basicInfoData&&(basicInfoData.totalQty || basicInfoData.totalQty==0)) ? basicInfoData.totalQty : '--' }}</strong> 
+                <span>退货总金额:<strong>{{ (basicInfoData&&(basicInfoData.totalPrice || basicInfoData.totalPrice==0)) ? toThousands(basicInfoData.totalPrice) : '--' }}</strong></span>
               </div>
             </a-alert>
             <!-- 筛选条件 -->
@@ -272,10 +272,6 @@ export default {
       loading: false,
       chooseDisabled: false, //  查询、重置按钮是否可操作
       advanced: false, // 高级搜索 展开/关闭
-      productBrandList: [], //  产品品牌  下拉数据
-      productTypeList: [], //  产品分类  下拉数据
-      productType: [],
-      warehouseList: [], //  仓库  下拉数据
       // 加载数据方法 必须为 Promise 对象
       loadData: parameter => {
         this.disabled = true
@@ -322,22 +318,24 @@ export default {
       return this.rowSelectionInfo && this.rowSelectionInfo.selectedRowKeys.length || 0
     },
     columns () {
+      const _this = this
       const arr = [
         { title: '序号', dataIndex: 'no', width: '4%', align: 'center' },
         { title: '调拨单号', dataIndex: 'allocateNo', width: '12%', align: 'center', customRender: function (text) { return text || '--' } },
         { title: '产品编码', dataIndex: 'productCode', width: '10%', align: 'center', customRender: function (text) { return text || '--' } },
         { title: '产品名称', dataIndex: 'productName', align: 'center', width: '29%', customRender: function (text) { return text || '--' }, ellipsis: true },
         { title: '单位', dataIndex: 'productUnit', width: '10%', align: 'center', customRender: function (text) { return text || '--' } },
-        { title: '调拨单价', dataIndex: 'price', width: '10%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
         { title: '调拨数量', dataIndex: 'qty', width: '10%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
         { title: '剩余可退数量', dataIndex: 'refundableQty', width: '10%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
         { title: '退货单价', scopedSlots: { customRender: 'returnPrice' }, width: '10%', align: 'center' },
         { title: '退货数量', dataIndex: 'returnQty', width: '10%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
         { title: '操作', scopedSlots: { customRender: 'action' }, width: '10%', align: 'center' }
       ]
+        arr.splice(5,0,{ title: '调拨单价', dataIndex: 'price', width: '10%', align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } })
       return arr
     },
     chooseColumns () {
+      const _this = this
       const arr = [
         { title: '序号', dataIndex: 'no', width: '4%', align: 'center' },
         { title: '调拨单号', dataIndex: 'allocateNo', width: '10%', align: 'center', customRender: function (text) { return text || '--' } },
@@ -346,9 +344,9 @@ export default {
         { title: '单位', dataIndex: 'product.unit', width: '10%', align: 'center', customRender: function (text) { return text || '--' } },
         { title: '退货单价', scopedSlots: { customRender: 'returnPrice' }, width: '10%', align: 'center' },
         { title: '退货数量', dataIndex: 'returnQty', width: '10%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
-        { title: '退货金额', dataIndex: 'totalReturnPrice', width: '10%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
         { title: '操作', scopedSlots: { customRender: 'action' }, width: '10%', align: 'center' }
       ]
+        arr.splice(7,0,{ title: '退货金额', dataIndex: 'totalReturnPrice', width: '10%', align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') }})
       return arr
     }
   },

+ 5 - 2
src/views/allocationManagement/transferReturn/list.vue

@@ -201,6 +201,7 @@ export default {
   },
   computed: {
     columns () {
+      const _this = this
       const arr = [
         { title: '序号', dataIndex: 'no', width: '3.5%', align: 'center' },
         { title: '创建时间', dataIndex: 'createDate', width: '7%', align: 'center', customRender: function (text) { return text || '--' } },
@@ -213,11 +214,13 @@ export default {
         { title: '退货总数量', dataIndex: 'totalQty', width: '5%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
         { title: '坏件数量', dataIndex: 'totalBadQty', width: '6%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
         { title: '返库数量', dataIndex: 'totalBackStockQty', width: '6%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
-        { title: '退货总金额', dataIndex: 'totalPrice', width: '5%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
         { title: '审核时间', dataIndex: 'auditTime', width: '7%', align: 'center', customRender: function (text) { return text || '--' } },
         { title: '业务状态', dataIndex: 'stateDictValue', width: '6%', align: 'center', customRender: function (text) { return text || '--' } },
         { title: '操作', scopedSlots: { customRender: 'action' }, width: '8%', align: 'center' }
       ]
+      if(this.$hasPermissions('M_transferReturnList_salesPrice')){
+        arr.splice(11,0,{ title: '退货总金额', dataIndex: 'totalPrice', width: '5%', align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } })
+      }
       return arr
     }
   },
@@ -323,7 +326,7 @@ export default {
     },
     setTableH () {
       const tableSearchH = this.$refs.tableSearch.offsetHeight
-      this.tableHeight = window.innerHeight - tableSearchH - 238
+      this.tableHeight = window.innerHeight - tableSearchH - 242
     }
   },
   watch: {

+ 8 - 2
src/views/allocationManagement/transferReturn/print.vue

@@ -78,14 +78,20 @@ export default {
         params.orderBy = obj.orderBy
       }
       _this.$emit('loading')
-      printFun(allocateReturnPrint, params, obj.isPreview, '调拨退货单', () => { _this.$emit('unloading') })
+      printFun(allocateReturnPrint, params, obj.isPreview, '调拨退货单', () => { 
+        _this.$emit('unloading')
+        _this.$store.state.app.curActionPermission = ''
+     })
     },
     // 导出
     handleExcel () {
       const _this = this
       _this.$emit('loading')
-      exportExcel(allocateReturnExcel, { allocateReturnSn: this.params.allocateReturnSn || '' }, '调拨退货单明细', function () {
+      const params = { allocateReturnSn: this.params.allocateReturnSn || '' }
+      _this.$store.state.app.curActionPermission = 'B_transferReturnExport'
+      exportExcel(allocateReturnExcel, params, '调拨退货单明细', function () {
         _this.$emit('unloading')
+        _this.$store.state.app.curActionPermission = ''
       })
     }
   }

+ 7 - 2
src/views/allocationManagement/transferReturn/printModal.vue

@@ -21,8 +21,8 @@
         <a-form-model-item style="margin:0" label="调拨退货对象">{{ itemData&&itemData.targetName || '--' }}</a-form-model-item>
         <a-form-model-item label="产品价格" prop="priceType">
           <a-radio-group v-model="form.priceType">
-            <a-radio value="thj">退货价</a-radio>
-            <a-radio value="cbj">成本价</a-radio>
+            <a-radio value="thj" v-if="$hasPermissions('B_transferReturnPrint_salesPrice')">退货价</a-radio>
+            <a-radio value="cbj" v-if="$hasPermissions('B_transferReturnPrint_costPrice')">成本价</a-radio>
             <a-radio value="bdy">不打印</a-radio>
           </a-radio-group>
         </a-form-model-item>
@@ -99,6 +99,7 @@ export default {
             if (_this.form.orderBy != '-1') {
               obj.orderBy = _this.form.orderBy
             }
+            _this.$store.state.app.curActionPermission = 'B_transferReturnPrint'
             _this.$emit('ok', obj)
           }
           _this.isShow = false
@@ -119,6 +120,10 @@ export default {
       if (!newValue) {
         this.$emit('close')
         this.$refs.ruleForm.resetFields()
+      }else{
+        if(!this.$hasPermissions('B_transferReturnPrint_salesPrice')&&!this.$hasPermissions('B_transferReturnPrint_costPrice')){
+          this.form.priceType = "bdy"
+        }
       }
     }
   }

+ 66 - 32
src/views/allocationManagement/transfersPrint/list.vue

@@ -27,7 +27,7 @@
               <template v-if="advanced">
                 <a-col :md="6" :sm="24">
                   <a-form-item label="收货客户名称">
-                    <dealerSubareaScopeList ref="receiverSn" defValKey="buyerSn" @change="custChange" v-model="queryParam.receiverSn" />
+                    <dealerSearchList ref="receiverSn" @change="custChange"/>
                   </a-form-item>
                 </a-col>
                 <a-col :md="4" :sm="24">
@@ -59,21 +59,15 @@
                     ></v-select>
                   </a-form-item>
                 </a-col>
-                <a-col :md="3" :sm="24">
+                <a-col :md="4" :sm="24">
                   <a-form-item label="所在区域">
-                    <subarea id="allocateBillList-subarea" v-model="queryParam.subareaSn"></subarea>
+                    <subarea id="allocateBillList-subarea" ref="subarea" @change="subareaChange"></subarea>
                   </a-form-item>
                 </a-col>
-                <a-col :md="3" :sm="24">
-                  <a-row>
-                    <a-form-item label="地区">
-                      <a-col span="24">
-                        <a-form-item style="margin: 0;">
-                          <Area id="allocateBillList-shippingAddrProvinceSn" v-model="queryParam.shippingAddrProvinceSn" placeholder="请选择省"></Area>
-                        </a-form-item>
-                      </a-col>
-                    </a-form-item>
-                  </a-row>
+                <a-col :md="4" :sm="24">
+                  <a-form-item label="地区">
+                    <Area id="allocateBillList-shippingAddrProvinceSn" v-model="queryParam.shippingAddrProvinceSn" placeholder="请选择省"></Area>
+                  </a-form-item>
                 </a-col>
               </template>
               <a-col :md="6" :sm="24">
@@ -101,7 +95,7 @@
           bordered>
           <!-- 单号 -->
           <template slot="allocateNo" slot-scope="text, record">
-            <span v-if="$hasPermissions('M_tfoPrint_detail')" class="link-bule" @click="handleDetail(record)">{{ record.allocateNo }}</span>
+            <span v-if="$hasPermissions('M_transferOut_detail')" class="link-bule" @click="handleDetail(record)">{{ record.allocateNo }}</span>
             <span v-else>{{ record.allocateNo }}</span>
           </template>
           <!-- 打印状态 -->
@@ -158,6 +152,16 @@
         </div>
       </div>
     </commonModal>
+    <!-- 查看详情 -->
+    <commonModal
+      modalTit="调拨单详情"
+      bodyPadding="10px"
+      width="70%"
+      :showFooter="false"
+      :openModal="showDetailModal"
+      @cancel="cancelDetail">
+      <allocationDetailModal v-if="showDetailModal" :outBizSn="bizSn" />
+    </commonModal>
   </div>
 </template>
 
@@ -169,24 +173,27 @@ import { STable, VSelect } from '@/components'
 import subarea from '@/views/common/subarea.js'
 import Area from '@/views/common/area.js'
 import rangeDate from '@/views/common/rangeDate.vue'
-import dealerSubareaScopeList from '@/views/common/dealerSubareaScopeList.vue'
+import dealerSearchList from '@/views/common/dealerSearchList.vue'
 import printModal from '@/views/allocationManagement/transferOut/printModal.vue'
-import recordModal from './recordModal.vue'
 import commonModal from '@/views/common/commonModal.vue'
+import allocationDetailModal from '@/views/allocationManagement/transferOut/detail.vue'
+import recordModal from './recordModal.vue'
 import { allocateBillList, allocateBillDetailPrint, updatePrintState } from '@/api/allocateBill'
 import { printFun } from '@/libs/JGPrint.js'
 export default {
   name: 'TransfersPrintList',
   mixins: [commonMixin],
-  components: { STable, VSelect, rangeDate, dealerSubareaScopeList, printModal, commonModal, recordModal, subarea, Area },
+  components: { STable, VSelect, rangeDate, dealerSearchList, printModal, commonModal, recordModal, subarea, Area, commonModal, allocationDetailModal },
   data () {
     return {
       spinning: false,
       advanced: true, // 高级搜索 展开/关闭
       tableHeight: 0,
       itemData: null,
+      bizSn: '',
       showRecordModal: false,
       showPrintModal: false,
+      showDetailModal: false,
       time: [
         moment(getDate.getThreeMonthDays().starttime, 'YYYY-MM-DD'),
         moment(getDate.getCurrMonthDays().endtime, 'YYYY-MM-DD')
@@ -200,7 +207,10 @@ export default {
         receiverSn: undefined,
         checkStatus: undefined,
         printState: 'NO_PRINT',
-        subareaSn: undefined,
+        subareaArea:{
+          subareaSn: undefined,
+          subareaAreaSn: undefined
+        },
         shippingAddrProvinceSn: undefined
       },
       currentTab: 2,
@@ -231,6 +241,7 @@ export default {
   },
   computed: {
     columns () {
+      const _this = this
       const arr = [
         { title: '序号', dataIndex: 'no', width: '4%', align: 'center' },
         { title: '创建时间', dataIndex: 'createDate', width: '7%', align: 'center', customRender: function (text) { return text || '--' } },
@@ -249,18 +260,24 @@ export default {
         { title: '打印次数', dataIndex: 'printCount', width: '5%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
         { title: '操作', scopedSlots: { customRender: 'action' }, width: '8%', align: 'center' }
       ]
-      if (this.$hasPermissions('B_isShowPrice')) { //  售价权限
-        arr.splice(7, 0, { slots: { title: 'costTitle' }, dataIndex: 'receiveTotalAmount', width: '90px', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } })
-        arr.splice(8, 0, { title: '易损件售价', dataIndex: 'receiveYsjTotalAmount', width: '80px', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } })
-        arr.splice(9, 0, { title: '电池售价', dataIndex: 'receiveDcTotalAmount', width: '70px', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } })
-        arr.splice(10, 0, { title: '机油售价', dataIndex: 'receiveJyTotalAmount', width: '70px', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } })
+      if (this.$hasPermissions('M_transfersPrintList_salesPrice')) { //  售价权限
+        arr.splice(7, 0, { slots: { title: 'costTitle' }, dataIndex: 'receiveTotalAmount', width: '90px', align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } })
+        arr.splice(8, 0, { title: '易损件售价', dataIndex: 'receiveYsjTotalAmount', width: '80px', align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } })
+        arr.splice(9, 0, { title: '电池售价', dataIndex: 'receiveDcTotalAmount', width: '70px', align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } })
+        arr.splice(10, 0, { title: '机油售价', dataIndex: 'receiveJyTotalAmount', width: '70px', align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } })
       }
       return arr
     }
   },
   methods: {
     custChange (val) {
-      this.queryParam.receiverSn = val.key || ''
+      if (val.row) {
+        this.queryParam.receiverSn = val.row.dealerSn
+        this.queryParam.receiverName = undefined
+      } else {
+        this.queryParam.receiverSn = undefined
+        this.queryParam.receiverName = val.key
+      }
     },
     changeTab (v) {
       this.currentTab = v
@@ -271,6 +288,12 @@ export default {
       this.queryParam.beginDate = date[0]
       this.queryParam.endDate = date[1]
     },
+    subareaChange(val){
+      this.queryParam.subareaArea={
+        subareaSn: val[0] ? val[0] : undefined,
+        subareaAreaSn: val[1] ? val[1] : undefined
+      }
+    },
     //  重置
     resetSearchForm () {
       this.$refs.rangeDate.resetDate(this.time)
@@ -281,9 +304,13 @@ export default {
       this.queryParam.allocateNo = ''
       this.queryParam.receiverName = ''
       this.queryParam.receiverSn = undefined
-      this.queryParam.subareaSn = undefined
+      this.queryParam.subareaArea.subareaSn = undefined
+      this.queryParam.subareaArea.subareaAreaSn = undefined
       this.queryParam.shippingAddrProvinceSn = undefined
       this.$refs.receiverSn.resetForm()
+      if(this.advanced){
+        this.$refs.subarea.clearData()
+      }
       this.queryParam.printState = this.currentTab == 2 ? 'NO_PRINT' : undefined
       this.$refs.table.refresh(true)
     },
@@ -305,6 +332,7 @@ export default {
       const _this = this
       const params = JSON.parse(JSON.stringify(objs))
       delete params.type
+      _this.$store.state.app.curActionPermission = 'B_transferOut_type_print'
       _this.spinning = true
       printFun(
         allocateBillDetailPrint,
@@ -313,10 +341,11 @@ export default {
         '调拨分类',
         (res) => {
           _this.spinning = false
-          if (res.status == 200) {
+          _this.$store.state.app.curActionPermission = ''
+          if (res&&res.status == 200) {
             _this.$refs.table.refresh()
-          }
-          _this.$message.info(res.message)
+            _this.$message.info(res.message)
+          }          
         }, {
           billType: 'ALLOCATE',
           billSn: objs.allocateSn,
@@ -326,9 +355,14 @@ export default {
     },
     //  详情
     handleDetail (row) {
-      if (this.$hasPermissions('M_tfoPrint_detail')) {
-        this.$router.push({ path: `/allocationManagement/transferOut/detail/${row.allocateSn}` })
-      }
+      this.$store.state.app.curActionPermission = 'M_transferOut_detail'
+      this.bizSn = row.allocateSn
+      this.showDetailModal = true
+    },
+    cancelDetail () {
+      this.$store.state.app.curActionPermission = ''
+      this.showDetailModal = false
+      this.bizSn = null
     },
     pageInit () {
       const _this = this
@@ -339,7 +373,7 @@ export default {
     },
     setTableH () {
       const tableSearchH = this.$refs.tableSearch.offsetHeight
-      this.tableHeight = window.innerHeight - tableSearchH - 240
+      this.tableHeight = window.innerHeight - tableSearchH - 246
     },
     // 状态打印弹窗
     editPrintStatus (item) {

+ 1 - 1
src/views/basicData/warehouse/list.vue

@@ -166,7 +166,7 @@ export default {
     },
     setTableH () {
       const tableSearchH = this.$refs.tableSearch.offsetHeight
-      this.tableHeight = window.innerHeight - tableSearchH - 235
+      this.tableHeight = window.innerHeight - tableSearchH - 240
     }
   },
   watch: {

+ 1 - 1
src/views/basicData/warehouse/storingLocation/list.vue

@@ -176,7 +176,7 @@ export default {
     },
     setTableH () {
       const tableSearchH = this.$refs.tableSearch.offsetHeight
-      this.tableHeight = window.innerHeight - tableSearchH - 285
+      this.tableHeight = window.innerHeight - tableSearchH - 295
     }
   },
   watch: {

+ 1 - 1
src/views/bigScreen/realTimeSalesReport/center-map.vue

@@ -62,7 +62,7 @@ export default {
       this.timer = setInterval(looper, 30000)
     },
     getData (code) {
-      this.loading = !this.timer ? true : false
+      this.loading = !this.timer
       queryMapSaleData(getDate.getBeDateByYear(this.curYear)).then((res) => {
         console.log('地图', res)
         if (res.status == 200) {

+ 100 - 90
src/views/bnSetting/menu/adminMenus.vue

@@ -73,33 +73,7 @@
                 rules: [{ required: true, message: '请输入名称!' }] }]"
             />
           </a-form-item>
-          <!-- 路由英文名 -->
-          <!-- <a-form-item v-if="!formData.type||formData.type=='0'" label="路由英文名" :label-col="{ span: 5 }" :wrapper-col="{ span: 14 }">
-            <a-input
-              placeholder="请输入路由英文名"
-              v-decorator="['formData.routeName', {
-                initialValue: formData.routeName,
-                rules: [{ required: true, message: '请输入路由英文名!' }] }]"
-            />
-          </a-form-item> -->
-          <!-- 路径 -->
-          <!-- <a-form-item v-if="!formData.type||formData.type=='0'" label="路径" :label-col="{ span: 5 }" :wrapper-col="{ span: 14 }">
-            <a-input
-              placeholder="请输入路径"
-              v-decorator="['formData.routePath', {
-                initialValue: formData.routePath,
-                rules: [{ required: true, message: '请输入路径!' }] }]"
-            />
-          </a-form-item> -->
-          <!-- 请求路径 -->
-          <!-- <a-form-item v-if="formData.type==1" label="请求路径" :label-col="{ span: 5 }" :wrapper-col="{ span: 14 }">
-            <a-input
-              placeholder="请输入请求路径"
-              v-decorator="['formData.urlPath', {
-                initialValue: formData.urlPath,
-                rules: [{ required: true, message: '请输入请求路径!' }] }]"
-            />
-          </a-form-item> -->
+
           <!-- 前端权限编码 -->
           <a-form-item label="前端权限编码" :label-col="{ span: 5 }" :wrapper-col="{ span: 14 }">
             <a-input
@@ -125,35 +99,9 @@
               ]"
             />
           </a-form-item>
-          <!-- 图标 -->
-          <!-- <a-form-item v-if="!formData.type ||formData.type=='0' " label="图标" :label-col="{ span: 5 }" :wrapper-col="{ span: 14 }">
-            <a-input
-              placeholder="请输入图标名称"
-              v-decorator="['formData.icon', {
-                initialValue: formData.icon,
-                rules: [] }]"
-            />
-          </a-form-item> -->
-          <!-- 前端组件 -->
-          <!-- <a-form-item v-if="!formData.type ||formData.type=='0'" label="前端组件" :label-col="{ span: 5 }" :wrapper-col="{ span: 14 }">
-            <a-input
-              placeholder="请输入前端组件路径"
-              v-decorator="['formData.componentPath', {
-                initialValue: formData.componentPath,
-                rules: [{ required: true, message: '请输入前端组件路径!' }] }]"
-            />
-          </a-form-item> -->
-
-          <!-- 第三方链接 -->
-          <!-- <a-form-item v-if="!formData.type ||formData.type=='0'" label="第三方链接" :label-col="{ span: 5 }" :wrapper-col="{ span: 14 }">
-            <a-input
-              placeholder="请输入第三方链接地址"
-              v-decorator="['formData.urlPath', {
-                initialValue: formData.urlPath,
-                rules: [] }]"
-            />
-          </a-form-item> -->
-
+          <a-form-item label="价格权限" :label-col="{ span: 5 }" :wrapper-col="{ span: 14 }">
+            <a-checkbox-group v-model="authPrice" :options="priceOptions" @change="onPriceChange" />
+          </a-form-item>
           <!-- 排序值 -->
           <a-form-item label="排序值" :label-col="{ span: 5 }" :wrapper-col="{ span: 14 }">
             <a-input-number
@@ -184,12 +132,9 @@
           </a-form-item>
 
           <a-form-item :wrapper-col="{ span: 12, offset: 5 }">
-            <a-button type="primary" @click="handleSubmit()">
+            <a-button size="large" type="primary" @click="handleSubmit()">
               保存
             </a-button>
-            <a-button :style="{ marginLeft: '8px' }" @click="clear">
-              重置
-            </a-button>
           </a-form-item>
         </a-form>
 
@@ -214,6 +159,8 @@ export default {
   props: {},
   data () {
     return {
+      priceOptions:[],
+      authPrice: [],
       treeData: [],
       dataList: [],
       searchValue: '',
@@ -225,6 +172,7 @@ export default {
       form: this.$form.createForm(this, { name: 'menu' }),
       showChildModal: false,
       parentData: {}, // 父级菜单
+      currMenusData:null,
       formData: {
         id: '',
         name: '',
@@ -249,18 +197,75 @@ export default {
     }
   },
   methods: {
+    onPriceChange(val){
+      console.log(val,this.authPrice,this.currMenusData)
+      
+      const data = this.currMenusData
+      if(!data){
+        this.$message.warning('请选择一个父级菜单')
+        this.authPrice = []
+        return false
+      }
+
+      // 当前选中节点的价格code
+      const child = data&&data.dataRef&&data.dataRef.children ? data.dataRef.children : []
+      data.dataRef.children = child
+      const curAuth = []
+      child.map(item=>{
+        const a = item.code.split('_')
+        const b = a[a.length-1]
+        const c = this.priceOptions.find(item => item.value == b)
+        if(c){
+          curAuth.push(a[a.length-1])
+        }
+      })
+ 
+      // 添加
+      if(val.length > curAuth.length){
+        const diff = val.filter(item => !new Set(curAuth).has(item))
+        console.log(diff)
+        const n = this.priceOptions.find(item=>item.value == diff[0])
+        this.addChildPrice({
+          parentId: data.id,
+          name: n.label,
+          code: data.code +'_'+diff[0],
+          status: 1,
+          sort: curAuth.length
+        },function(ret){
+          ret.title = ret.name
+          child.push(ret)
+        })
+      }else{
+        // 删除
+        const diff = curAuth.filter(item => !new Set(val).has(item))
+        const idx = child.findIndex(item => {
+          const a = item.code.split('_')
+          return a[a.length-1] == diff[0]
+        })
+        console.log(child[idx])
+        this.delChildPrice(child[idx].id,function(){
+          child.splice(idx,1)
+        })
+      }
+    },
     onExpand (expandedKeys) {
       // console.log('onExpand', expandedKeys)
       this.expandedKeys = expandedKeys
       this.autoExpandParent = false
     },
     onSelect (selectedKeys, info) {
-      console.log('onSelect', info)
       this.selectedKeys = selectedKeys
       if (info.selected) {
+        this.clear()
         const data = info.selectedNodes[0].data.props
-        const isLeaf = data.dataRef.children
-        // this.formData = Object.assign({}, this.formData, info.selectedNodes[0].data.props)
+        const isLeaf = data.dataRef.children || []
+        console.log('onSelect', isLeaf)
+        this.currMenusData = data // 当前节点的子级
+        // 价格权限回显
+        isLeaf.map(item => {
+          const a = item.code.split('_')
+          this.authPrice.push(a[a.length-1])
+        })
         this.formData = {
           id: data.id,
           parentId: data.parentId,
@@ -331,10 +336,9 @@ export default {
     // 获取菜单树列表
     getYyMenuList () {
       getYyMenuList().then(res => {
-        console.log(res, 'res1111111')
         if (res.status == 200) {
           this.treeData = res.data
-          console.log(this.treeData, 'this.treeData')
+          this.$store.state.app.authMenusList = res.data
         }
       })
     },
@@ -353,7 +357,6 @@ export default {
       this.showChildModal = true
       this.parentData = {}
     },
-
     //  取消选择
     cancelSel () {
       this.selectedKeys = []
@@ -364,6 +367,7 @@ export default {
     clear () {
       this.form.resetFields()
       this.formData.id = ''
+      this.formData.parentId = ''
       this.formData.name = ''
       this.formData.routePath = ''
       this.formData.icon = ''
@@ -376,8 +380,9 @@ export default {
       this.formData.code = ''
       this.formData.permission = ''
       this.formData.isLeaf = true
+      this.currMenusData = null
+      this.authPrice = []
     },
-
     // 删除数据
     delect () {
       if (!this.selectedKeys.length) {
@@ -391,48 +396,53 @@ export default {
         okText: '确定',
         cancelText: '取消',
         onOk () {
-          deleteYyMenu({
-            id: _this.formData.id
-          }).then(res => {
-            if (res.status == 200) {
-              _this.$message.success('删除成功')
-              _this.getYyMenuList()
-            }
-          }).catch(() => {
-            _this.$message.success('删除失败, 请稍后重试')
-          })
+          _this.delChildPrice(_this.formData.id)
         }
       })
     },
-
+    // 删除子级
+    delChildPrice(id,callback){
+      const _this = this
+      deleteYyMenu({
+        id: id
+      }).then(res => {
+        if (res.status == 200) {
+          _this.$message.success('删除成功')
+          _this.getYyMenuList()
+          callback&&callback()
+        }
+      }).catch(() => {
+        _this.$message.success('删除失败, 请稍后重试')
+      })
+    },
     // 保存提交
     handleSubmit () {
       const _this = this
       this.form.validateFields((err, values) => {
         if (!err) {
-          console.log(values.formData, ' formData.type222222222')
           if (values.formData.permission) {
             values.formData.permission = values.formData.permission.replace(/\//g, '_')
           }
-          saveYyMenu(Object.assign({ id: this.formData.id }, values.formData)).then(res => {
-            console.log(res, 'res--save')
-            if (res.status + '' === '200') {
-              this.$message.success(res.message ? res.message : '保存成功')
-              _this.getYyMenuList()
-              _this.clear()
-            } else {
-              // this.$message.warning(res.message)
-            }
-          })
+          this.addChildPrice(Object.assign({ id: this.formData.id }, values.formData))
+        }
+      })
+    },
+    // 新增子级
+    addChildPrice(data,callback){
+      saveYyMenu(data).then(res => {
+        if (res.status + '' === '200') {
+          this.$message.success(res.message ? res.message : '保存成功')
+          this.getYyMenuList()
+          callback&&callback(res.data)
         }
       })
     },
     handleCancel () {
       this.clear()
     }
-
   },
   mounted () {
+    this.priceOptions = this.$store.state.app.priceAuthOptions
   },
   beforeCreate () {
     this.form = this.$form.createForm(this, { name: 'menu' })

+ 0 - 1
src/views/bnSetting/menu/storeMenus.vue

@@ -405,7 +405,6 @@ export default {
         return this.$message.warning('您还未选择要删除的数据')
       }
       const _this = this
-      console.log(_this.formData.id, '_this.formData.id')
       this.$confirm({
         title: '警告',
         content: `确定要删除您选择的 ${_this.formData.name} 的数据吗?`,

+ 88 - 0
src/views/common/areaList.js

@@ -0,0 +1,88 @@
+import { getAreaAll } from '@/api/data'
+import { arrayToTree } from '@/utils/util'
+const AreaList = {
+  template: `
+     <a-cascader
+          :size="size"
+          :changeOnSelect="changeOnSelect"
+          :show-search="{ filter }"
+          @change="handleChange"
+          :value="defaultVal"
+          expand-trigger="hover"
+          :allowClear="allowClear"
+          :options="list"
+          :field-names="{ label: 'name', value: defValKey, children: 'children' }" 
+          :id="id"
+          :placeholder="placeholder" 
+          style="width: 100%;" />
+    `,
+  props: {
+    value: {
+      type: Array,
+      defatut: function(){
+        return []
+      }
+    },
+    id: {
+      type: String,
+      default: ''
+    },
+    defValKey: {
+      type: String,
+      default: 'areaSn'
+    },
+    placeholder: {
+      type: String,
+      default: '请选择省/市/区'
+    },
+    allowClear: {
+        type: Boolean,
+        default: true
+    },
+    size: {
+        type: String,
+        default: 'default'
+    },
+    changeOnSelect:{
+        type: Boolean,
+        default: false
+    }
+  },
+  data() {
+    return {
+      defaultVal: this.value,
+      list: []
+    };
+  },
+  watch: {
+    value(newValue, oldValue) {
+      this.defaultVal = newValue
+    },
+  },
+  mounted() {
+    this.getArea()
+  },
+  methods: {
+    filter(inputValue, path) {
+        return path.some(option => option.name.toLowerCase().indexOf(inputValue.toLowerCase()) > -1);
+    },
+    handleChange (value, selectedOptions) {
+        this.defaultVal = value
+        this.$emit('input', this.defaultVal)
+        this.$emit('change', this.defaultVal, selectedOptions)
+    },
+    //  省/市/区
+    getArea () {
+        getAreaAll().then(res => {
+            if (res.status == 200) {
+                this.list = arrayToTree(res.data,0)
+            }
+        })
+    },
+    clearData(){
+       this.handleChange([],null)
+    }
+  },
+};
+
+export default AreaList

+ 13 - 83
src/views/common/chooseCustomerModal.vue

@@ -14,37 +14,15 @@
         <div class="table-page-search-wrapper">
           <a-form layout="inline" @keyup.enter.native="$refs.table.refresh(true)">
             <a-row :gutter="15">
-              <a-col :md="6" :sm="24">
+              <a-col :md="8" :sm="24">
                 <a-form-item label="客户名称">
                   <a-input id="chooseCustomer-dealerName" v-model.trim="queryParam.dealerName" allowClear placeholder="请输入客户名称"/>
                 </a-form-item>
               </a-col>
-              <a-col :md="12" :sm="24">
-                <a-row>
-                  <a-form-item label="地区">
-                    <a-col span="7">
-                      <a-form-item prop="provinceSn" style="margin: 0;">
-                        <a-select v-model="queryParam.provinceSn" allowClear @change="getCityList" placeholder="请选择省">
-                          <a-select-option v-for="item in addrProvinceList" :value="item.id" :key="item.id + 'a'">{{ item.name }}</a-select-option>
-                        </a-select>
-                      </a-form-item>
-                    </a-col>
-                    <a-col span="7" offset="1">
-                      <a-form-item prop="citySn" style="margin: 0;">
-                        <a-select v-model="queryParam.citySn" allowClear @change="getAreaList" placeholder="请选择市">
-                          <a-select-option v-for="item in addrCityList" :value="item.id" :key="item.id + 'b'">{{ item.name }}</a-select-option>
-                        </a-select>
-                      </a-form-item>
-                    </a-col>
-                    <a-col span="7" offset="1">
-                      <a-form-item prop="districtSn" style="margin: 0;">
-                        <a-select v-model="queryParam.districtSn" allowClear placeholder="请选择区/县">
-                          <a-select-option v-for="item in addrDistrictList" :value="item.id" :key="item.id + 'c'">{{ item.name }}</a-select-option>
-                        </a-select>
-                      </a-form-item>
-                    </a-col>
-                  </a-form-item>
-                </a-row>
+              <a-col :md="8" :sm="24">
+                <a-form-model-item label="地区">
+                    <AreaList id="chooseCustomer-areaList" changeOnSelect ref="areaList" @change="areaChange" defValKey="id"></AreaList>
+                </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="promotionRulesList-refresh">查询</a-button>
@@ -91,11 +69,11 @@
 
 <script>
 import { STable } from '@/components'
-import { getArea } from '@/api/data'
+import AreaList from '@/views/common/areaList.js'
 import { dealerQueryList } from '@/api/dealer'
 export default {
   name: 'ChooseCustomerModal',
-  components: { STable },
+  components: { STable, AreaList },
   props: {
     openModal: { //  弹框显示状态
       type: Boolean,
@@ -141,9 +119,6 @@ export default {
           return data
         })
       },
-      addrProvinceList: [], //  省下拉
-      addrCityList: [], //  市下拉
-      addrDistrictList: [], //  区下拉
       rowSelectionInfo: null
     }
   },
@@ -162,8 +137,12 @@ export default {
       this.queryParam.provinceSn = undefined
       this.queryParam.citySn = undefined
       this.queryParam.districtSn = undefined
-      this.addrCityList = []
-      this.addrDistrictList = []
+      this.$refs.areaList.clearData()
+    },
+    areaChange(val){
+      this.queryParam.provinceSn = val[0] ? val[0] : ''
+      this.queryParam.citySn = val[1] ? val[1] : ''
+      this.queryParam.districtSn = val[2] ? val[2] : ''
     },
     //  确定
     handleSubmit () {
@@ -174,52 +153,6 @@ export default {
       this.$emit('ok', this.rowSelectionInfo && this.rowSelectionInfo.selectedRowKeys)
       this.isShow = false
     },
-    // 获取城市列表
-    getCityList (val) {
-      this.addrCityList = []
-      this.addrDistrictList = []
-      this.queryParam.citySn = undefined
-      this.queryParam.districtSn = undefined
-      if (val) {
-        this.getArea('city', val)
-      }
-    },
-    // 获取区县列表
-    getAreaList (val) {
-      this.addrDistrictList = []
-      this.queryParam.districtSn = undefined
-      if (val) {
-        this.getArea('district', val)
-      }
-    },
-    //  省/市/区
-    getArea (leve, sn) {
-      let params
-      if (leve == 'province') {
-        params = { type: '2' }
-      } else {
-        params = { parentId: sn, type: leve == 'city' ? '3' : '4' }
-      }
-      getArea(params).then(res => {
-        if (res.status == 200) {
-          if (leve == 'province') {
-            this.addrProvinceList = res.data || []
-          } else if (leve == 'city') {
-            this.addrCityList = res.data || []
-          } else if (leve == 'district') {
-            this.addrDistrictList = res.data || []
-          }
-        } else {
-          if (leve == 'province') {
-            this.addrProvinceList = []
-          } else if (leve == 'city') {
-            this.addrCityList = []
-          } else if (leve == 'district') {
-            this.addrDistrictList = []
-          }
-        }
-      })
-    }
   },
   watch: {
     //  父页面传过来的弹框状态
@@ -232,9 +165,6 @@ export default {
         this.$emit('close')
         this.resetData()
       } else {
-        if (this.addrProvinceList.length == 0) {
-          this.getArea('province')
-        }
         const _this = this
         this.$nextTick(() => { // 页面渲染完成后的回调
           _this.$refs.table.refresh(true)

+ 267 - 0
src/views/common/chooseDealer.vue

@@ -0,0 +1,267 @@
+<template>
+  <a-spin :spinning="spinning" tip="Loading...">
+    <!-- 搜索条件 -->
+    <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">
+            <a-form-item label="经销商名称/别名">
+              <a-input id="chooseDealer-nameLike" v-model.trim="queryParam.nameLike" allowClear placeholder="请输入经销商名称/别名"/>
+            </a-form-item>
+          </a-col>
+          <a-col :md="8" :sm="24">
+            <a-form-item label="商户类型">
+              <v-select code="DEALER_TYPE" id="chooseDealer-dealerType" v-model="queryParam.dealerType" allowClear placeholder="请选择商户类型"></v-select>
+            </a-form-item>
+          </a-col>
+          <a-col :md="8" :sm="24">
+            <a-form-model-item label="商户级别" prop="dealerLevel">
+              <v-select code="DEALER_LEVEL" id="ucModal-dealerLevel" v-model="queryParam.dealerLevel" allowClear placeholder="请选择商户级别"></v-select>
+            </a-form-model-item>
+          </a-col>
+          <a-col :md="8" :sm="24" v-if="pageType!='viewDealers'">
+            <a-form-item label="所在区域/分区">
+              <subarea id="chooseDealer-subarea" ref="subarea" @change="subareaChange"></subarea>
+            </a-form-item>
+          </a-col>
+          <div v-else>
+            <a-col :md="8" :sm="24">
+              <a-form-item label="审核状态">
+                <v-select code="AUDIT_STATE" id="viewDealers-auditState" v-model="queryParam.auditState" allowClear placeholder="请选择审核状态"></v-select>
+              </a-form-item>
+            </a-col>
+            <a-col :md="8" :sm="24">
+              <a-form-model-item label="地区">
+                <AreaList id="viewDealers-areaList" changeOnSelect ref="areaList" @change="areaChange" defValKey="id"></AreaList>
+              </a-form-model-item>
+            </a-col>
+          </div>
+          <a-col :md="pageType!='viewDealers'?8:6" :sm="24" style="margin-bottom: 10px;">
+            <a-button type="primary" @click="searchForm(true)" :disabled="disabled" id="chooseDealer-refresh">查询</a-button>
+            <a-button style="margin-left: 5px" @click="resetSearchForm" :disabled="disabled" id="chooseDealer-reset">重置</a-button>
+          </a-col>
+        </a-row>
+      </a-form>
+      <!-- 列表 -->
+      <div style="margin-bottom: 10px">
+        <a-button type="primary" ghost :loading="loading" @click="handleBatchAudit">批量添加</a-button>
+        <span style="margin-left: 5px">
+          <template v-if="selectCount"> {{ `已选 ${selectCount} 项` }} </template>
+        </span>
+      </div>
+    </div>
+    <s-table
+      class="sTable"
+      ref="table"
+      size="small"
+      :rowKey="(record) => record.dealerSn"
+      rowKeyName="dealerSn"
+      :row-selection="{ columnWidth: 40, getCheckboxProps: record => ({ props: { disabled: pageType=='viewDealers'?!!record.subareaAreaSn: !!record.chooseId} }) }"
+      @rowSelection="rowSelectionFun"
+      :columns="columns"
+      :data="loadData"
+      :style="{ height:pageType=='viewDealers'? tableHeight+84.5+'px':tableHeight-15+'px' }"
+      :scroll="{ y: pageType=='viewDealers'?tableHeight:tableHeight+80 }"
+      :defaultLoadData="false"
+      bordered>
+      <template slot="areas" slot-scope="text, record">
+        <span v-if="record.subareaArea">{{ record.subareaArea.subareaName }}>{{ record.subareaArea.subareaAreaName }}</span>
+        <span v-else>--</span>
+      </template>
+      <template slot="action" slot-scope="text, record">
+        <a-button
+          size="small"
+          type="link"
+          class="button-error"
+          @click="handleAdd(record)"
+          v-if="record.subareaAreaSn != parentData.subareaAreaSn"
+          id="marketingDivisionSetNew-del-btn">添加</a-button>
+        <span style="color:#666" v-else>已添加</span>
+      </template>
+    </s-table>
+  </a-spin>
+</template>
+
+<script>
+import { commonMixin } from '@/utils/mixin'
+import { STable, VSelect } from '@/components'
+import AreaList from '@/views/common/areaList.js'
+import { queryDealerPageList } from '@/api/dealer'
+import subarea from '@/views/common/subarea.js'
+export default {
+  name: 'ChooseDealer',
+  mixins: [commonMixin],
+  components: { STable, VSelect, subarea, AreaList },
+  props: {
+    pageType: {
+      type: String,
+      default: ''
+    },
+    parentData: {
+      type: Object,
+      default: function () {
+        return null
+      }
+    }
+  },
+  data () {
+    return {
+      spinning: false,
+      queryParam: { //  查询条件
+        nameLike: '',
+        dealerType: null,
+        dealerLevel: null,
+        auditState: undefined,
+        provinceSn: undefined,
+        citySn: undefined,
+        districtSn: undefined,
+        subareaArea: {
+          subareaSn: undefined,
+          subareaAreaSn: undefined
+        }
+      },
+      tableHeight: 0,
+      disabled: false, //  查询、重置按钮是否可操作
+      loading: false, // 批量添加loading
+      // 加载数据方法 必须为 Promise 对象
+      loadData: parameter => {
+        this.spinning = true
+        return queryDealerPageList(Object.assign(parameter, this.queryParam)).then(res => {
+          let data
+          const _this = this
+          if (res.status == 200) {
+            data = res.data
+            const no = 0
+            for (var i = 0; i < data.list.length; i++) {
+              data.list[i].no = no + i + 1
+            }
+          }
+          this.spinning = false
+          return data
+        })
+      },
+      rowSelectionInfo: null
+    }
+  },
+  computed: {
+    columns () {
+      const _this = this
+      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 || '--' } }
+      ]
+      if (_this.pageType == 'viewDealers') {
+        arr.splice(4, 0, { title: '审核状态', dataIndex: 'auditStateDictValue', width: '20%', align: 'center', customRender: function (text) { return text || '--' } })
+        arr.splice(5, 0, { title: '当前所属区域', scopedSlots: { customRender: 'areas' }, width: '30%', align: 'center' })
+        arr.splice(6, 0, { title: '操作', scopedSlots: { customRender: 'action' }, width: '20%', align: 'center' })
+      } else {
+        arr.splice(4, 0, { title: '所在区域', dataIndex: 'subareaArea.subareaName', width: '20%', align: 'center', customRender: function (text) { return text || '--' } })
+        arr.splice(5, 0, { title: '所在分区', dataIndex: 'subareaArea.subareaAreaName', width: '20%', align: 'center', customRender: function (text) { return text || '--' } })
+      }
+      return arr
+    },
+    selectCount () {
+      return this.rowSelectionInfo && this.rowSelectionInfo.selectedRowKeys.length
+    }
+  },
+  methods: {
+    // 表格选中项
+    rowSelectionFun (obj) {
+      this.rowSelectionInfo = obj || null
+    },
+    areaChange (val) {
+      this.queryParam.provinceSn = val[0] ? val[0] : ''
+      this.queryParam.citySn = val[1] ? val[1] : ''
+      this.queryParam.districtSn = val[2] ? val[2] : ''
+    },
+    searchForm (flag) {
+      this.$refs.table.refresh(flag)
+      this.$refs.table.clearSelected()
+      this.spinning = false
+    },
+    subareaChange (val) {
+      this.queryParam.subareaArea.subareaSn = val[0] ? val[0] : undefined
+      this.queryParam.subareaArea.subareaAreaSn = val[1] ? val[1] : undefined
+    },
+    //  重置
+    resetSearchForm () {
+      this.queryParam = {
+        nameLike: '',
+        dealerType: null,
+        dealerLevel: null,
+        auditState: undefined,
+        provinceSn: undefined,
+        citySn: undefined,
+        districtSn: undefined,
+        subareaArea: {
+          subareaSn: undefined,
+          subareaAreaSn: undefined
+        }
+      }
+      if (this.pageType != 'viewDealers') {
+        this.$refs.subarea.clearData()
+      } else {
+        this.$refs.areaList.clearData()
+      }
+      this.$refs.table.refresh(true)
+      this.$refs.table.clearSelected()
+    },
+    clearTable () {
+      this.rowSelectionInfo = null
+      this.$refs.table.clearTable()
+    },
+    // 批量添加
+    handleBatchAudit () {
+      const _this = this
+      if (!_this.rowSelectionInfo || (_this.rowSelectionInfo && _this.rowSelectionInfo.selectedRowKeys.length < 1)) {
+        _this.$message.warning('请在列表勾选后再进行批量操作!')
+        return
+      }
+      const dealerSnList = _this.rowSelectionInfo.selectedRowKeys
+      this.spinning = false
+      this.$emit('plAdd', dealerSnList)
+    },
+    handleAdd (row) {
+      if (row.subareaArea) {
+        const _this = this
+        this.$confirm({
+          title: '提示',
+          content: '当前经销商已被其他区域分区绑定,确定要更新绑定关系吗?',
+          centered: true,
+          onOk () {
+            _this.spinning = true
+            _this.$emit('add', row)
+          }
+        })
+      } else {
+        this.spinning = true
+        this.$emit('add', row)
+      }
+    },
+    pageInit () {
+      const _this = this
+      this.$nextTick(() => { // 页面渲染完成后的回调
+        _this.setTableH()
+      })
+      this.resetSearchForm()
+    },
+    setTableH () {
+      const tableSearchH = this.$refs.tableSearch.offsetHeight
+      this.tableHeight = window.innerHeight - tableSearchH - 285
+    }
+  },
+  mounted () {
+    this.pageInit()
+  },
+  activated () {
+    this.pageInit()
+  },
+  watch: {
+    '$store.state.app.winHeight' (newValue, oldValue) { //  窗口变更时,需同时更改表格高度
+      this.setTableH()
+    }
+  }
+}
+</script>

+ 16 - 73
src/views/common/chooseProductsModal.vue

@@ -24,36 +24,18 @@
               :wrapper-col="formItemLayout.wrapperCol">
               <a-row :gutter="15">
                 <a-col :md="6" :sm="24">
-                  <a-form-model-item label="产品编码" prop="code">
+                  <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="产品品牌" :prop="type=='dealership'?'productBrandSn':''">
-                    <a-select
-                      placeholder="请选择产品品牌"
-                      id="chooseProducts-productBrandSn"
-                      allowClear
-                      v-model="queryParam.productBrandSn"
-                      :showSearch="true"
-                      option-filter-prop="children"
-                      :filter-option="filterOption">
-                      <a-select-option v-for="item in productBrandList" :key="item.brandSn" :value="item.brandSn">{{ item.brandName }}</a-select-option>
-                    </a-select>
+                  <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">
-                  <a-form-model-item label="产品分类" :prop="type=='dealership'?'productType':''">
-                    <a-cascader
-                      @change="changeProductType"
-                      change-on-select
-                      v-model="queryParam.productType"
-                      expand-trigger="hover"
-                      :options="productTypeList"
-                      :fieldNames="{ label: 'productTypeName', value: 'productTypeSn', children: 'children' }"
-                      id="chooseProducts-productType"
-                      placeholder="请选择产品分类"
-                      allowClear />
+                  <a-form-model-item  label="产品分类">
+                    <productTypeAll :isAll="type!='default'" placeholder="请选择产品分类" @change="changeProductType" v-model="queryParam.productType" id="chooseProducts-productType"></productTypeAll>
                   </a-form-model-item>
                 </a-col>
                 <a-col :md="6" :sm="24" style="margin-bottom: 10px;">
@@ -61,7 +43,7 @@
                   <a-button style="margin-left: 5px" @click="resetSearchForm" :disabled="disabled" id="chooseProducts-reset">重置</a-button>
                 </a-col>
               </a-row>
-            </a-form-model></a-form>
+            </a-form-model>
           </div>
           <p style="font-weight: bold;">当前已选:{{ rowSelectionInfo&&rowSelectionInfo.selectedRowKeys.length }}个</p>
           <!-- 列表 -->
@@ -103,13 +85,13 @@
 <script>
 import { STable } from '@/components'
 import tablePagination from '@/views/common/tablePagination.vue'
-import { productBrandQuery } from '@/api/productBrand'
-import { productTypeQuery, productTypeQueryAll } from '@/api/productType'
+import ProductBrand from '@/views/common/productBrand.js'
+import productTypeAll from '@/views/common/productTypeAll.js'
 import { dealerScopeValidProduct } from '@/api/dealerScope'
 import { productPricedList, productPricingList } from '@/api/product'
 export default {
   name: 'ChooseProductsModal',
-  components: { STable, tablePagination },
+  components: { STable, tablePagination, ProductBrand, productTypeAll },
   props: {
     openModal: { //  弹框显示状态
       type: Boolean,
@@ -123,7 +105,7 @@ export default {
     },
     type: { //  类型,经销权设置dealership,  供应商添加产品supplier
       type: String,
-      default: ''
+      default: 'default'
     },
     dealerSn: {
       type: String || Number,
@@ -183,8 +165,6 @@ export default {
           return data
         })
       },
-      productBrandList: [], //  品牌下拉数据
-      productTypeList: [], //  分类下拉数据
       rowSelectionInfo: null
     }
   },
@@ -199,6 +179,11 @@ export default {
       _this.$refs.ruleForm.validate(valid => {
         if (valid) {
           if (_this.type == 'dealership') { //  设置经销权时选择产品
+            if(!_this.queryParam.productBrandSn && !_this.queryParam.productTypeSn1){
+              _this.$message.info("请选择产品品牌或产品分类")
+              return
+            }
+             
             // 校验产品是否被包含在品牌分类中
             const params = []
             if (_this.queryParam.productBrandSn) {
@@ -254,8 +239,7 @@ export default {
     //  重置
     resetSearchForm () {
       this.resetData()
-      // this.$refs.table.clearTable()
-      this.$refs.table.refresh(true)
+      this.$refs.table.clearTable()
     },
     // 保存
     handleSave () {
@@ -282,41 +266,6 @@ export default {
       this.queryParam.productTypeSn1 = val[0] ? val[0] : ''
       this.queryParam.productTypeSn2 = val[1] ? val[1] : ''
       this.queryParam.productTypeSn3 = val[2] ? val[2] : ''
-    },
-    filterOption (input, option) {
-      return (
-        option.componentOptions.children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0
-      )
-    },
-    //  产品品牌  列表
-    getProductBrand () {
-      productBrandQuery({}).then(res => {
-        if (res.status == 200) {
-          this.productBrandList = res.data
-        } else {
-          this.productBrandList = []
-        }
-      })
-    },
-    //  产品分类  列表
-    getProductType () {
-      if (this.type != 'supplier' && this.type != 'dealership') { //  促销
-        productTypeQueryAll({}).then(res => {
-          if (res.status == 200) {
-            this.productTypeList = res.data
-          } else {
-            this.productTypeList = []
-          }
-        })
-      } else {
-        productTypeQuery({}).then(res => {
-          if (res.status == 200) {
-            this.productTypeList = res.data
-          } else {
-            this.productTypeList = []
-          }
-        })
-      }
     }
   },
   watch: {
@@ -347,12 +296,6 @@ export default {
         this.$nextTick(() => { // 页面渲染完成后的回调
           _this.$refs.table.setTableSelected(selectedRowKeys, selectedRows) // 设置表格选中项
         })
-        if (this.productBrandList.length == 0) {
-          this.getProductBrand()
-        }
-        if (this.productTypeList.length == 0) {
-          this.getProductType()
-        }
       }
     }
   }

+ 1 - 1
src/views/common/chooseTypeModal.vue

@@ -100,7 +100,7 @@ export default {
     },
     // 保存
     handleSave () {
-      if (this.checkedKeys.length < 1) {
+      if (this.checkedKeys.checked && this.checkedKeys.checked.length < 1) {
         this.$message.warning('请在列表勾选后再进行操作!')
         return
       }

+ 4 - 1
src/views/common/dingDepartUser.js

@@ -37,7 +37,7 @@ const DingDepartUser = {
   },
   data() {
     return {
-      defaultVal: this.value,
+      defaultVal: [],
       treeData: []
     };
   },
@@ -71,6 +71,7 @@ const DingDepartUser = {
             title: item.name,
             id:item.deptId,
             value: item.deptId,
+            key: item.deptId,
             pId: item.parentId,
             autoAddUser: item.autoAddUser,
             createDeptGroup: item.createDeptGroup,
@@ -91,6 +92,7 @@ const DingDepartUser = {
             title: item.name,
             id: item.userid,
             value: item.userid,
+            key:item.userid,
             pId: item.parentId,
             avatar: item.avatar,
             leader: item.leader,
@@ -112,6 +114,7 @@ const DingDepartUser = {
        const res2 = ret.deptUserList||[]
        this.treeData = this.treeData = this.formatData(res1.concat(res2));
        console.log(this.treeData,'----')
+       this.defaultVal = this.value
     },
     // 更新人员数据
     updateDeptUser(){

+ 303 - 0
src/views/common/pdfViewModal.vue

@@ -0,0 +1,303 @@
+<template>
+    <a-modal
+      centered
+      v-drag
+      class="common-pdfView-modal"
+      :footer="null"
+      :maskClosable="false"
+      v-model="isShow"
+      :title="modalTit"
+      :zIndex="1001"
+      :destroyOnClose="true"
+      @cancel="handleCommonCancel"
+      width="1000px">
+      <a-spin :spinning="spinning" tip="Loading...">
+        <div class="common-main">
+          <div id="canvas"></div>
+          <div class="tools">
+            <div>
+              调整比例:{{ Math.round(scalVal*100) }}%
+              <div>
+                <a-button :disabled="scalLoading" style="margin-right: 10px;" size="small" @click="setScalVal(0)"><a-icon type="minus" /> 缩小</a-button>
+                <a-button :disabled="scalLoading" size="small" @click="setScalVal(1)"><a-icon type="plus" /> 放大</a-button>
+              </div>
+            </div>
+            <div>
+              <div v-if="hasClipboard">
+                <a-button :disabled="scalLoading" size="small" @click="handleCapture('export')"><a-icon type="export" /> 导出图片</a-button>
+              </div>
+            </div>
+          </div>
+          <vue-scroll :ops="ops" :style="{width: '100%',height: '70vh',margin:'0 auto',padding: '10px 0'}">
+            <div v-if="loadedRatio > 0 && loadedRatio < 1" style="background-color: green; color: white; text-align: center" :style="{ width: loadedRatio * 100 + '%' }">{{ Math.floor(loadedRatio * 100) }}%</div>
+            <pdf
+                v-for="i in numPages"
+                :key="i"
+                :src="src"
+                :page="i"
+                style="display: inline-block; width: 25%"
+            ></pdf>
+          </vue-scroll>
+        </div>
+        <div class="btn-box">
+          <a-button size="large" style="margin-right: 25px;" @click="handleCommonCancel" v-if="isCancel">{{ cancelText }}</a-button>
+          <a-button size="large" style="margin-right: 25px;" type="default" @click="handleCapture(hasClipboard?'copy':'export')">
+            {{ hasClipboard?'复制截图':'导出图片' }}
+          </a-button>
+          <a-button size="large" type="primary" :loading="$store.state.app.printLoading" @click="handleCommonOk">
+            {{ $store.state.app.printLoading?'打印中...':okText }}
+          </a-button>
+        </div>
+      </a-spin>
+    </a-modal>
+  </template>
+  
+  <script>
+  import moment from 'moment'
+  import pdf from 'vue-pdf-signature'
+  import CMapReaderFactory from 'vue-pdf-signature/src/CMapReaderFactory.js'
+  import { pdfPrint } from '@/libs/JGPrint'
+  export default {
+    components: {
+      pdf
+    },
+    name: 'PdfViewModal',
+    props: {
+      openModal: { //  弹框显示状态
+        type: Boolean,
+        default: false
+      },
+      modalTit: { // 弹框标题
+        type: String,
+        default: '打印预览'
+      },
+      okText: { // 确定 按钮文字
+        type: String,
+        default: '打印'
+      },
+      cancelText: { // 取消 按钮文字
+        type: String,
+        default: '取消'
+      },
+      isCancel: { // 是否显示  取消 按钮
+        type: Boolean,
+        default: true
+      },
+      spinning: { // 加载中
+        type: Boolean,
+        default: false
+      }
+    },
+    data () {
+      return {
+        scalLoading: false,
+        pdfAllLoad: 0,
+        scalVal: 0.75,
+        isShow: this.openModal, //  是否打开弹框
+        show: true,
+        src: '',
+        loadedRatio: 0,
+        page: 1,
+        numPages: undefined,
+        rotate: 0,
+        curpage: 1,
+        total: 3,
+        ops: {
+          vuescroll: {},
+          scrollPanel: {},
+          rail: {
+            keepShow: true
+          },
+          bar: {
+            hoverStyle: true,
+            onlyShowBarOnScroll: false, // 是否只有滚动的时候才显示滚动条
+            background: '#9d9d9d', // 滚动条颜色
+            opacity: 0.5, // 滚动条透明度
+            size: '10px',
+            'overflow-x': 'hidden'
+          }
+        },
+        printIndex: undefined,
+        printList: []
+      }
+    },
+    computed: {
+      hasClipboard () {
+        return typeof ClipboardItem !== 'undefined'
+      }
+    },
+    methods: {
+      // 选择打印机
+      changePrint (v) {
+        this.printIndex = v
+        this.$store.commit('SET_printDefNeedle', this.printIndex)
+        this.$store.state.app.printTaskID = undefined
+      },
+      // 缩放
+      setScalVal (t) {
+        if (!this.scalLoading) {
+          this.scalLoading = true
+          this.scalVal = this.scalVal + (t ? 0.05 : -0.05)
+          if (this.scalVal > 1) {
+            this.scalVal = 1
+          }
+          if (this.scalVal < 0.5) {
+            this.scalVal = 0.5
+          }
+          setTimeout(() => {
+            this.scalLoading = false
+          }, 1000)
+        }
+      },
+      getUrl (item) {
+        const src = pdf.createLoadingTask({ url: item, CMapReaderFactory })
+        return src
+      },
+      setData (data) {
+        // console.log(data)
+        this.curpage = 1
+        this.total = data.length
+ 
+        const defPrint = this.$store.state.app.printDefNeedle
+        this.printIndex = defPrint ? (defPrint == 'undefined' ? undefined : defPrint) : undefined
+      },
+      error: function (err) {
+        console.log(err)
+      },
+      // 确定
+      handleCommonOk () {
+        const _this = this
+        const hasPrint = this.printList.find(item => item.name == this.printIndex)
+        // 已选择打印机
+        if (hasPrint) {
+           pdfPrint(_this.$store.state.app.pdfPrintList, 0)
+        } else {
+          this.$message.info('请选择打印机')
+        }
+        _this.$emit('ok')
+      },
+      // 取消
+      handleCommonCancel () {
+        this.isShow = false
+        this.$store.commit('SET_pdfPrintList', [])
+        this.$store.commit('SET_showPdfPrint', false)
+        this.$emit('cancel')
+        this.scalVal = 0.75
+      },
+      // 截图
+      handleCapture (type) {
+        if (this.scalLoading) { return }
+        const pdf = this.$refs.pdf
+        const len = pdf.length
+        const imgsList = []
+        const canvas = document.createElement('canvas')
+        let maxHeight = 0
+        const maxWidth = pdf[0].$refs.canvas.width
+        for (let i = 0; i < len; i++) {
+          const imgs = pdf[i].$refs.canvas
+          maxHeight = maxHeight + imgs.height
+          imgsList.push(imgs)
+        }
+        // 设置画布宽度和高度
+        canvas.width = maxWidth
+        canvas.height = maxHeight
+        const ctx = canvas.getContext('2d')
+        // 开始合并
+        let y = 0
+        imgsList.map(item => {
+          ctx.drawImage(item, 0, y, item.width, item.height)
+          y = y + item.height
+        })
+        const base64Str = canvas.toDataURL('image/png')
+        // 复制图片
+        if (type == 'copy') {
+          this.copyImgBtn(base64Str)
+        }
+        // 下载图片
+        if (type == 'export') {
+          const fileName = moment().format('YYYYMMDDHHmmss')
+          this.downloadFile(fileName, base64Str)
+        }
+        // 清除画布
+        ctx.clearRect(0, 0, maxWidth, maxHeight)
+      },
+      downloadFile (fileName, base64Data) {
+        const aLink = document.createElement('a')
+        const blob = this.convertBase64ToBlob(base64Data.split(',')[1], 'image/png')
+        const evt = document.createEvent('HTMLEvents')
+        // initEvent 不加后两个参数在FF下会报错  事件类型,是否冒泡,是否阻止浏览器的默认行为
+        evt.initEvent('click', true, true)
+        aLink.download = fileName
+        aLink.href = URL.createObjectURL(blob)
+        aLink.click()
+      },
+      // 将照片复制到剪贴版
+      copyImgBtn (base64Data) {
+        const blobInput = this.convertBase64ToBlob(base64Data.split(',')[1], 'image/png')
+        if (navigator.clipboard) {
+          const clipboardItemInput = new ClipboardItem({ 'image/png': blobInput })
+          navigator.clipboard.write([clipboardItemInput])
+          this.$message.success('截图成功,可以右键去粘贴图片!')
+        } else {
+          const image = nativeImageElectron.createFromDataURL(base64Data)
+          clipboardElectron.writeImage(image)
+          this.$message.success('截图成功,可以右键去粘贴图片!')
+        }
+      },
+      convertBase64ToBlob (base64, type) {
+        var bytes = window.atob(base64)
+        var ab = new ArrayBuffer(bytes.length)
+        var ua = new Uint8Array(ab)
+        for (var i = 0; i < bytes.length; i++) {
+          ua[i] = bytes.charCodeAt(i)
+        }
+        return new Blob([ab], { type: type })
+      }
+    },
+    watch: {
+      //  父页面传过来的弹框状态
+      openModal (newValue, oldValue) {
+        this.isShow = newValue
+      },
+      //  重定义的弹框状态
+      isShow (newValue, oldValue) {
+        if (!newValue) {
+          this.$emit('cancel')
+        }else{
+            this.setData()
+        }
+      }
+    }
+  }
+  </script>
+  
+  <style lang="less">
+    .common-pdfView-modal{
+      .ant-modal-body{
+        padding: 0 0 20px 0;
+      }
+      .common-main{
+        background-color: #666;
+        .tools{
+          padding: 10px;
+          display: flex;
+          align-items: center;
+          border-bottom: 1px solid #eee;
+          background-color: #f8f8f8;
+          justify-content: space-between;
+          > div{
+            display: flex;
+            align-items: center;
+            >div{
+              padding: 0 10px;
+            }
+          }
+        }
+      }
+      .btn-box{
+        text-align: center;
+        margin-top: 20px;
+      }
+    }
+  </style>
+  

+ 5 - 1
src/views/common/productType.js

@@ -3,7 +3,7 @@ const ProductType = {
   template: `
       <a-cascader
         @change="handleChange"
-        change-on-select
+        :change-on-select="changeOnSelect"
         :value="defaultVal"
         expand-trigger="hover"
         :options="productTypeList"
@@ -28,6 +28,10 @@ const ProductType = {
       type: [String,Number],
       default: ''
     },
+    changeOnSelect:{
+      type: Boolean,
+      default: true
+    }
   },
   data () {
     return {

+ 24 - 10
src/views/common/productTypeAll.js

@@ -1,4 +1,4 @@
-import { productTypeQueryAll } from '@/api/productType'
+import { productTypeQueryAll, productTypeQuery } from '@/api/productType'
 const ProductType = {
   template: `
       <a-cascader
@@ -32,6 +32,10 @@ const ProductType = {
     disabled: {
       type: Boolean,
       default: false
+    },
+    isAll: {
+      type: Boolean,
+      default: true
     }
   },
   data () {
@@ -63,19 +67,29 @@ const ProductType = {
     },
     //  产品分类  列表
     getProductType () {
-      productTypeQueryAll({}).then(res => {
-        if (res.status == 200) {
-          if (res.data && res.data.length > 0) {
-            //  递归处理disabled禁用
-            this.recursionFun(res.data, false)
+      if(this.isAll){
+        productTypeQueryAll({}).then(res => {
+          if (res.status == 200) {
+            if (res.data && res.data.length > 0) {
+              //  递归处理disabled禁用
+              this.recursionFun(res.data, false)
+              this.productTypeList = res.data
+            } else {
+              this.productTypeList = []
+            }
+          } else {
+            this.productTypeList = []
+          }
+        })
+      }else{
+        productTypeQuery({}).then(res => {
+          if (res.status == 200) {
             this.productTypeList = res.data
           } else {
             this.productTypeList = []
           }
-        } else {
-          this.productTypeList = []
-        }
-      })
+        })
+      }
     },
     //  递归函数
     recursionFun (data, state) {

+ 7 - 6
src/views/common/returnReason.js

@@ -1,3 +1,4 @@
+import { removeEmptyStr } from '@/libs/tools'
 const ReturnReason = {
   template: `
         <a-select
@@ -52,7 +53,7 @@ const ReturnReason = {
   },
   watch: {
     value(newValue, oldValue) {
-      this.defaultVal = newValue
+      this.defaultVal = removeEmptyStr(newValue)
     },
   },
   methods: {
@@ -64,14 +65,14 @@ const ReturnReason = {
     onChange(value) {
       console.log(value,'----')
       this.open = true;
-      const ret = value?value.substr(0,50):''
-      this.defaultVal = ret;
-      this.$emit('change', ret);
-      this.$emit('input', ret);
+      const ret = value?value.substr(0,50):'';
+      this.defaultVal = removeEmptyStr(ret);
+      this.$emit('input', this.defaultVal);
+      this.$emit('change', this.defaultVal);
     },
     onBlur(value){
       this.open = false;
-      this.$emit('blur', value);
+      this.$emit('blur', removeEmptyStr(value));
     }
   },
 };

+ 2 - 2
src/views/common/settleStyle.js

@@ -1,5 +1,5 @@
 import { settleStyleQueryAll } from '@/api/settleStyle'
-const CustList = {
+const SettleStyle = {
   template: `
         <a-select
           :id="id"
@@ -67,4 +67,4 @@ const CustList = {
   },
 };
 
-export default CustList
+export default SettleStyle

+ 103 - 52
src/views/common/subarea.js

@@ -1,26 +1,26 @@
 import { subareaQueryAll } from '@/api/subarea'
-const Subarea = {
+const AreaList = {
   template: `
-        <a-select
-          :id="id"
-          :placeholder="placeholder"
-          allowClear
-          :value="defaultVal"
-          :mode="mode"
-          :showSearch="true"
+     <a-cascader
+          :size="size"
+          :changeOnSelect="changeOnSelect"
+          :show-search="{ filter }"
           @change="handleChange"
-          :filter-option="filterOption">
-          <a-select-option v-for="item in list" :key="item[defValKey]" :value="item[defValKey]">{{ item.subareaName }}</a-select-option>
-        </a-select>
+          :value="defaultVal"
+          expand-trigger="hover"
+          :allowClear="allowClear"
+          :options="list"
+          :field-names="{ label: 'name', value: defValKey, children: 'subareaAreaList' }" 
+          :id="id"
+          :placeholder="placeholder" 
+          style="width: 100%;" />
     `,
   props: {
     value: {
-      type: [String,Array],
-      defatut: ''
-    },
-    mode: {
-      type: String,
-      default:'default'
+      type: Array,
+      defatut: function(){
+        return []
+      }
     },
     id: {
       type: String,
@@ -28,11 +28,34 @@ const Subarea = {
     },
     defValKey: {
       type: String,
-      default: 'subareaSn'
+      default: 'areaSn'
     },
     placeholder: {
       type: String,
-      default: '请选择分区'
+      default: '请选择区域/分区'
+    },
+    allowClear: {
+        type: Boolean,
+        default: true
+    },
+    size: {
+        type: String,
+        default: 'default'
+    },
+    // 只能选择分区,如果区域下无分区不能选择
+    onlySubarea:{
+      type: Boolean,
+      default: false
+    },
+    // true可选择一级、二级,false只能选择叶子节点
+    changeOnSelect:{
+        type: Boolean,
+        default: true
+    },
+    // 只显示那一级数据,空全部显示
+    showLeve:{
+      type: String,
+      default: ''
     }
   },
   data() {
@@ -44,48 +67,76 @@ const Subarea = {
   watch: {
     value(newValue, oldValue) {
       this.defaultVal = newValue
-    }
+    },
   },
   mounted() {
-    this.getList()
+    this.getArea()
   },
   methods: {
-    filterOption (input, option) {
-      return (
-        option.componentOptions.children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0
-      )
+    filter(inputValue, path) {
+        return path.some(option => option.name.toLowerCase().indexOf(inputValue.toLowerCase()) > -1);
     },
-    handleChange(value) {
-      console.log(value)
-      this.defaultVal = value;
-      const item = this.list.filter(item =>{
-        if(this.mode !== 'multiple'){
-          return item[this.defValKey] == value
-        }else{
-          return value.includes(item[this.defValKey])
-        }
-      })
-      this.$emit('change', value, item);
-      this.$emit('input', value);
+    handleChange (value, selectedOptions) {
+        this.defaultVal = value
+        this.$emit('input', this.defaultVal)
+        this.$emit('change', this.defaultVal, selectedOptions)
     },
-    // 列表数据
-    getList () {
-      const _this = this
+    getArea () {
       subareaQueryAll().then(res => {
-        if (res.status == 200) {
-          _this.list = res.data.reverse() || []
-        } else {
-          _this.list = []
-        }
-      })
+            if (res.status == 200) {
+                // 显示一级二级
+                if(this.showLeve == ''){
+                  res.data&&res.data.map(item => {
+                    item.name = item.subareaName
+                    item.areaSn = item.subareaSn
+                    if(item.subareaAreaList){
+                      item.subareaAreaList.map(cd => {
+                        cd.name = cd.subareaAreaName
+                        cd.areaSn = cd.subareaAreaSn
+                      })
+                    }else{
+                      if(this.onlySubarea){
+                        item.disabled = true
+                      }
+                    }
+                  })
+                  this.list = res.data
+                }
+                
+                // 只显示一级
+                if(this.showLeve == 1){
+                  const ret = []
+                  res.data&&res.data.map(item => {
+                    item.name = item.subareaName
+                    item.areaSn = item.subareaSn
+                    delete item.subareaAreaList
+                    ret.push(item)
+                  })
+                  this.list = ret
+                }
+
+                // 只显示二级
+                if(this.showLeve == 2){
+                  const ret = []
+                  res.data&&res.data.map(item => {
+                    if(item.subareaAreaList){
+                      item.subareaAreaList.map(cd => {
+                        cd.name = cd.subareaAreaName
+                        cd.areaSn = cd.subareaAreaSn
+                        ret.push(cd)
+                      })
+                    }
+                  })
+                  this.list = ret
+                }
+                
+            }
+        })
     },
-    // 根据名称数组 返回对应的 sn 数组
-    getValByName(data){
-      let ret = []
-      this.list.filter(item => data.includes(item.subareaName)).map(item => ret.push(item.subareaSn))
-      return ret
+    clearData(){
+       this.handleChange([],null)
     }
   },
 };
 
-export default Subarea
+export default AreaList

+ 121 - 0
src/views/common/userName.vue

@@ -0,0 +1,121 @@
+<template>
+  <a-select
+    show-search
+    label-in-value
+    :size="size"
+    :value="userName"
+    :placeholder="placeholder"
+    style="width: 100%"
+    :filter-option="false"
+    :not-found-content="fetching ? undefined : null"
+    :dropdownMatchSelectWidth="false"
+    @search="fetchUser"
+    @change="handleChange"
+    allowClear
+  >
+    <a-spin v-if="fetching" slot="notFoundContent" size="small" />
+    <a-select-option v-for="item in data" :key="item.userSn" :value="item.userSn">
+      {{ item.userName }}
+    </a-select-option>
+  </a-select>
+</template>
+<script>
+import debounce from 'lodash/debounce'
+import { queryUserList } from '@/api/bizuser'
+export default {
+  props: {
+    id: {
+      type: String,
+      default: ''
+    },
+    size: {
+      type: String,
+      default: 'default'
+    },
+    itemSn: {
+      type: String || Number,
+      default: undefined
+    },
+    placeholder: {
+      type: String,
+      default: '请输入名称搜索'
+    },
+    cooperateFlag: {
+      type: String,
+      default: undefined
+    }
+  },
+  data () {
+    this.lastFetchId = 0
+    this.fetchUser = debounce(this.fetchUser, 800)
+    return {
+      data: [],
+      userName: [],
+      fetching: false
+    }
+  },
+  methods: {
+    fetchUser (userName) {
+      console.log('fetching user', userName)
+      if (userName == '') return
+      this.lastFetchId += 1
+      const fetchId = this.lastFetchId
+      this.data = []
+      this.fetching = true
+      const params = { pageNo: 1, pageSize: 20 }
+      if (this.itemSn) {
+        params.dealerSn = this.itemSn
+      } else {
+        params.userName = userName
+        if (this.cooperateFlag) {
+          params.cooperateFlag = this.cooperateFlag
+        }
+      }
+      queryUserList(params).then(res => {
+        if (fetchId !== this.lastFetchId) {
+          return
+        }
+        this.data = res.data && res.data.list ? res.data.list : []
+        this.fetching = false
+      })
+    },
+    handleChange (value) {
+      if (value) {
+        const row = this.data.filter(item => item.userSn == value.key)
+        Object.assign(this, {
+          userName: value,
+          data: [],
+          fetching: false
+        })
+        this.$emit('change', value || { key: undefined }, row[0], this.id)
+        // this.$emit('input', value.key)
+      } else {
+        this.setDufaultVal('')
+        this.resetForm()
+        this.$emit('change', value || { key: undefined }, undefined, this.id)
+        // this.$emit('input', value.key)
+      }
+    },
+    resetForm () {
+      this.userName = []
+    },
+    setData (value) {
+      Object.assign(this, {
+        userName: value,
+        data: [],
+        fetching: false
+      })
+    },
+    setDufaultVal (itemSn) {
+      this.fetchUser(itemSn)
+      this.setData({ key: itemSn })
+    }
+  },
+  mounted () {
+    if (this.itemSn) {
+      this.fetchUser(this.itemSn)
+      this.setData({ key: this.itemSn })
+    }
+  }
+}
+</script>

+ 173 - 0
src/views/dealerManagement/businessOwnerSettings/addModal.vue

@@ -0,0 +1,173 @@
+<template>
+  <a-modal
+    centered
+    class="businessOwnerSettings-modal"
+    :footer="null"
+    :maskClosable="false"
+    :title="itemId ?'编辑人员':'新增人员'"
+    v-model="isShow"
+    @cancel="isShow=false"
+    :width="600">
+    <a-spin :spinning="spinning" tip="Loading...">
+      <a-form-model
+        ref="ruleForm"
+        :model="form"
+        :label-col="labelCol"
+        :wrapper-col="wrapperCol"
+        :rules="rules"
+      >
+        <a-form-model-item label="人员名称" prop="userSn">
+          <userName ref="userName" id="businessOwnerSettings-userSn" @change="userChange"></userName>
+        </a-form-model-item>
+        <a-form-model-item label="人员类型" prop="bizUserType">
+          <v-select
+            v-model="form.bizUserType"
+            ref="printStatus"
+            id="businessOwnerSettings-printStatus"
+            code="BIZ_USER_TYPE"
+            placeholder="请选择人员类型"
+            allowClear></v-select>
+        </a-form-model-item>
+        <a-form-model-item label="管辖经销商" prop="allDealerFlag">
+          <a-radio-group v-model="form.allDealerFlag">
+            <a-radio value="1">
+              全部经销商
+            </a-radio>
+            <a-radio value="0">
+              部分经销商
+            </a-radio>
+          </a-radio-group>
+        </a-form-model-item>
+        <a-form-model-item label="管辖品类" prop="allProductFlag">
+          <a-radio-group v-model="form.allProductFlag">
+            <a-radio value="1">
+              全部品类
+            </a-radio>
+            <a-radio value="0">
+              部分品类
+            </a-radio>
+          </a-radio-group>
+        </a-form-model-item>
+        <div style="display: flex;justify-content: center;padding: 30px 0;">
+          <a-button type="primary" @click="handleSave">{{ itemId?'保存':'确定' }}</a-button>
+          <a-button style="margin-left: 15px;" @click="isShow=false">取消</a-button>
+        </div>
+      </a-form-model>
+    </a-spin>
+  </a-modal>
+</template>
+
+<script>
+
+import userName from '@/views/common/userName'
+import { VSelect } from '@/components'
+import { bizuserSave } from '@/api/bizuser.js'
+export default {
+  name: 'ProductInfoDetailModal',
+  components: { VSelect, userName },
+  props: {
+    openModal: { //  弹框显示状态
+      type: Boolean,
+      default: false
+    },
+    itemId: {
+      type: String,
+      default: ''
+    }
+  },
+  data () {
+    return {
+      spinning: false,
+      isShow: this.openModal, //  是否打开弹框
+      form: {
+        userSn: '',
+        bizUserType: undefined, // 人员类型
+        allDealerFlag: undefined,
+        allProductFlag: undefined
+      },
+      user_name: '',
+      labelCol: { span: 5 },
+      wrapperCol: { span: 16 },
+      rules: {
+        userSn: [{ required: true, message: '请输入人员名称', trigger: 'change' }],
+        bizUserType: [{ required: true, message: '请选择人员类型', trigger: 'change' }],
+        allDealerFlag: [{ required: true, message: '请选择管辖经销商', trigger: 'change' }],
+        allProductFlag: [{ required: true, message: '请选择管辖产品', trigger: 'change' }]
+      }
+    }
+  },
+  methods: {
+    handleSave () {
+      const _this = this
+      this.$refs.ruleForm.validate(valid => {
+        if (valid) {
+          _this.spinning = true
+          _this.form.id = _this.itemId ? _this.itemId : ''
+          bizuserSave(_this.form).then(res => {
+            _this.spinning = false
+            if (res.status == 200) {
+              _this.$emit('ok', res.data)
+              _this.isShow = false
+            }
+          }).catch(err => {
+            _this.spinning = false
+          })
+        } else {
+          console.log('error submit!!')
+          return false
+        }
+      })
+    },
+    resetSearchForm () {
+      this.$refs.userName.resetForm()
+      this.user_name = ''
+      this.$refs.ruleForm.resetFields()
+    },
+    userChange (val) {
+      this.form.userSn = val.key
+    },
+    getEditInfo (obj) {
+      this.$refs.userName.setDufaultVal(obj.userName)
+      this.form = {
+        userSn: obj.userSn,
+        bizUserType: obj.bizUserType, // 人员类型
+        allDealerFlag: obj.allDealerFlag,
+        allProductFlag: obj.allProductFlag
+      }
+    }
+  },
+  watch: {
+    //  父页面传过来的弹框状态
+    openModal (newValue, oldValue) {
+      this.isShow = newValue
+    },
+    //  重定义的弹框状态
+    isShow (newValue, oldValue) {
+      if (!newValue) {
+        this.resetSearchForm()
+        this.$emit('close')
+      }
+    }
+  }
+}
+</script>
+
+<style lang="less">
+  .inventoryCheckAddModal-modal{
+    .ant-modal-body {
+      padding: 30px 40px 24px;
+    }
+    .inventoryCheckAddModal-con{
+      text-align: center;
+      h3{
+        font-size: 16px;
+        font-weight: bold;
+        margin-bottom: 25px;
+      }
+    }
+    .btn-cont {
+      text-align: center;
+      margin: 35px 0 10px;
+    }
+  }
+</style>

+ 322 - 0
src/views/dealerManagement/businessOwnerSettings/categorySet.vue

@@ -0,0 +1,322 @@
+<template>
+  <div class="categorySet-wrap">
+    <a-spin :spinning="spinning" tip="Loading...">
+      <a-card size="small" :bordered="false" class="categorySet-cont">
+        <div class="table-operator" ref="categorySetAddBtn">
+          <a-button type="primary" class="button-error" @click="addCategory" :disabled="disabled">+新增管辖品类</a-button>
+        </div>
+        <s-table
+          class="sTable fixPagination"
+          ref="table"
+          :style="{ height: tableHeight+84.5+'px' }"
+          size="small"
+          :rowKey="(record) => record.bizUserScopeSn"
+          rowKeyName="bizUserScopeSn"
+          :columns="columns"
+          :data="loadData"
+          :scroll="{ y: tableHeight }"
+          :defaultLoadData="false"
+          bordered>
+          <!-- 产品分类 -->
+          <template slot="classify" slot-scope="text,record,index">
+            <div style="max-height:64px;overflow-y:scroll;">
+              <a-row v-if="record.productTypeList && record.productTypeList.length>0">
+                <a-col :span="20">
+                  <a-tag style="margin-bottom:10px;" closable @close.prevent="delLabel(record.bizUserScopeSn,con,'typeList')" v-for="(con,i) in record.productTypeList" :key="i">
+                    {{ con.dataName }}
+                  </a-tag>
+                </a-col>
+                <a-col :span="4" 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>
+          </template>
+          <!-- 产品品牌 -->
+          <template slot="brand" slot-scope="text,record,index">
+            <div style="max-height:64px;overflow-y:scroll;">
+              <a-row v-if="record.productBrandList && record.productBrandList.length>0">
+                <a-col :span="20">
+                  <a-tag style="margin-bottom:10px;" closable @close.prevent="delLabel(record.bizUserScopeSn,item,'brandList')" v-for="(item,j) in record.productBrandList" :key="j">
+                    {{ item.dataName }}
+                  </a-tag>
+                </a-col>
+                <a-col :span="4" 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>
+          </template>
+          <span slot="action" slot-scope="text,record">
+            <a-button
+              size="small"
+              type="link"
+              class="button-error"
+              @click="handleDel(record)"
+            >
+              删除
+            </a-button>
+          </span>
+        </s-table>
+      </a-card>
+    </a-spin>
+    <!-- 选择产品品牌 -->
+    <chooseBrandModal :openModal="openBrandModal" :chooseData="chooseBrand" @close="openBrandModal=false" @ok="handleBrandOk" />
+    <!-- 选择产品分类 -->
+    <chooseTypeModal :openModal="openTypeModal" :chooseData="chooseType" @close="openTypeModal=false" @ok="handleTypeOk" />
+  </div>
+</template>
+
+<script>
+import { commonMixin } from '@/utils/mixin'
+import ChooseBrandModal from '@/views/common/chooseBrandModal.vue'
+import ChooseTypeModal from '@/views/common/chooseTypeModal.vue'
+import { STable } from '@/components'
+import { getNewScopeSn, bizuserScopeQueryPage, saveProductBrandList, saveProductTypeList, bizuserScopeDelete, deleteProductBrand, deleteProductType } from '@/api/bizuser'
+export default {
+  name: 'CategorySet',
+  mixins: [commonMixin],
+  components: { ChooseBrandModal, ChooseTypeModal, STable },
+  props: {
+    bizUserSn: {
+      type: String,
+      default: ''
+    }
+  },
+  data () {
+    return {
+      spinning: false,
+      tableHeight: 0,
+      disabled: false, //  查询、重置按钮是否可操作
+      columns: [
+        { title: '分类', dataIndex: 'no', width: '42%', align: 'center', scopedSlots: { customRender: 'classify' } },
+        { title: '品牌', dataIndex: 'name', width: '42%', align: 'center', scopedSlots: { customRender: 'brand' } },
+        { title: '操作', scopedSlots: { customRender: 'action' }, width: '16%', align: 'center' }
+      ],
+      queryParam: {
+        hasDetail: 1
+      },
+      dataSource: [],
+      openModal: false, //  新增编辑产品品牌  弹框
+      itemSn: '', //  当前sn
+      nowData: null, //  当前记录数据
+      openBrandModal: false,
+      openTypeModal: false,
+      chooseBrand: [],
+      chooseType: [],
+      chooseObj: null, // 选择品牌 内容
+      // 加载数据方法 必须为 Promise 对象
+      loadData: parameter => {
+        this.disabled = true
+        this.spinning = true
+        this.queryParam.userSn = this.$route.query.sn
+        this.queryParam.bizUserSn = this.bizUserSn
+        return bizuserScopeQueryPage(Object.assign(parameter, this.queryParam)).then(res => {
+          let data
+          data = res.data
+          const no = (data.pageNo - 1) * data.pageSize
+          this.total = data.count || 0
+          for (var i = 0; i < data.list.length; i++) {
+            data.list[i].no = no + i + 1
+          }
+          this.dataSource = data.list
+          this.disabled = false
+          this.spinning = false
+          return data
+        })
+      }
+    }
+  },
+  methods: {
+    //  返回
+    handleBack () {
+      this.$router.push({ name: 'powerUserList' })
+    },
+    // 新增管辖品类
+    addCategory () {
+      const _this = this
+      _this.spinning = true
+      _this.disabled = true
+      getNewScopeSn({}).then(res => {
+        if (res.status == 200) {
+          const newData = {
+            bizUserScopeSn: res.data,
+            productTypeList: [],
+            productBrandList: []
+          }
+          _this.dataSource.unshift(newData)
+        }
+        _this.spinning = false
+        _this.disabled = false
+      })
+    },
+    // 删除分类、品牌标签
+    delLabel (bigRow, row, type) {
+      const _this = this
+      const bigPos = _this.dataSource.findIndex(con => { return bigRow == con.bizUserScopeSn })
+      if (type == 'typeList') {
+        const typePos = _this.dataSource[bigPos].productTypeList.findIndex(item => { return item.id == row.id })
+        deleteProductType({ id: _this.dataSource[bigPos].productTypeList[typePos].id }).then(res => {
+          if (res.status == 200) {
+            _this.dataSource[bigPos].productTypeList.splice(typePos, 1)
+          }
+        })
+      } else {
+        const brandPos = _this.dataSource[bigPos].productBrandList.findIndex(obj => { return obj.id == row.id })
+        deleteProductBrand({ id: _this.dataSource[bigPos].productBrandList[brandPos].id }).then(res => {
+          if (res.status == 200) {
+            _this.dataSource[bigPos].productBrandList.splice(brandPos, 1)
+          }
+        })
+      }
+    },
+    // 添加分类标签
+    addClassifyTag (pos, row) {
+      const newData = []
+      row.productTypeList.forEach(item => {
+        const obj = {}
+        obj.productTypeSn = item.dataSn
+        obj.goodsSn = item.dataSn
+        obj.productTypeName = item.dataName
+        newData.push(obj)
+      })
+      this.chooseType = newData
+      this.chooseObj = row
+      this.openTypeModal = true
+    },
+    handleClassifyModal (con) {
+      const chooseList = con
+      this.openTypeModal = false
+      this.dataSource[this.ChooseClassifyPos].productTypeList = [...this.dataSource[this.ChooseClassifyPos].productTypeList, ...chooseList]
+    },
+    // 分类
+    handleTypeOk (obj) {
+      this.chooseType = obj
+      this.saveChangeData('CATEGORY')
+    },
+    // 添加品牌标签
+    addBrandTag (pos, row) {
+      const newData = []
+      row.productBrandList.forEach(item => {
+        const obj = {}
+        obj.goodsSn = item.dataSn
+        newData.push(obj)
+      })
+      this.chooseBrand = newData
+      this.chooseObj = row
+      this.openBrandModal = true
+    },
+    // 品牌
+    handleBrandOk (obj) {
+      this.chooseBrand = obj
+      this.saveChangeData('BRAND')
+    },
+    saveChangeData (type) {
+      const _this = this
+      if (type == 'BRAND') { //  选择品牌
+        if (_this.chooseBrand.length > 0) {
+          const snList = []
+          _this.chooseBrand.map(item => {
+            const newObj = {}
+            newObj.dataSn = item.brandSn
+            snList.push(newObj)
+          })
+          this.save(snList, type)
+        }
+      } else if (type == 'CATEGORY') { //  选择分类
+        if (_this.chooseType.length > 0) {
+          const snList = []
+          _this.chooseType.map(item => {
+            const newObj = {}
+            newObj.dataSn = item.productTypeSn
+            snList.push(newObj)
+          })
+          this.save(snList, type)
+        }
+      }
+    },
+    save (list, type) {
+      const ajaxdata = { userSn: this.$route.query.sn, bizUserScopeSn: this.chooseObj.bizUserScopeSn, bizUserSn: this.bizUserSn }
+      if (type == 'BRAND') {
+        ajaxdata.productBrandList = list
+        saveProductBrandList(ajaxdata).then(res => {
+          if (res.status == 200) {
+            this.openBrandModal = false
+            this.$refs.table.refresh()
+          }
+        })
+      } else if (type == 'CATEGORY') {
+        ajaxdata.productTypeList = list
+        saveProductTypeList(ajaxdata).then(res => {
+          if (res.status == 200) {
+            this.openTypeModal = false
+            this.$refs.table.refresh()
+          }
+        })
+      }
+    },
+    // 整行删除 删除
+    handleDel (row) {
+      const _this = this
+      this.$confirm({
+        title: '提示',
+        content: '确认要删除吗?删除后当前用户权限以最新权限为准',
+        centered: true,
+        onOk () {
+          bizuserScopeDelete({ id: row.bizUserScopeSn }).then(res => {
+            if (res.status == 200) {
+              const pos = _this.dataSource.findIndex(item => { return item.bizUserScopeSn == row.bizUserScopeSn })
+              _this.dataSource.splice(pos, 1)
+            }
+          })
+        }
+      })
+    },
+    pageInit () {
+      const _this = this
+      this.$nextTick(() => { // 页面渲染完成后的回调
+        _this.setTableH()
+      })
+      this.$refs.table.refresh()
+    },
+    setTableH () {
+      const addBtnHeight = this.$refs.categorySetAddBtn.offsetHeight
+      this.tableHeight = window.innerHeight - addBtnHeight - 385
+    }
+  },
+  watch: {
+    '$store.state.app.winHeight' (newValue, oldValue) { //  窗口变更时,需同时更改表格高度
+      this.setTableH()
+    }
+  },
+  beforeRouteEnter (to, from, next) {
+    next(vm => {})
+  }
+}
+</script>
+
+<style lang="less">
+  .categorySet-wrap{
+    .table-operator{
+    text-align:right;
+    }
+  }
+</style>

+ 160 - 0
src/views/dealerManagement/businessOwnerSettings/chooseAreaModal.vue

@@ -0,0 +1,160 @@
+<template>
+  <a-drawer
+    title="选择区域"
+    width="50%"
+    :zIndex="100"
+    :visible="visible"
+    :get-container="false"
+    :wrap-style="{ position: 'absolute' }"
+    @close="visible = false">
+    <div class="areaSetModal">
+      <div :style="{ height: tableHeight+84.5+'px' }">
+        <div>
+          <a-checkbox :checked="checkAll" @change="onCheckAllChange">全选</a-checkbox>
+        </div>
+        <div :style="{ height: tableHeight+30+'px' }" style="overflow-y:scroll;">
+          <a-tree
+            v-model="checkedKeys"
+            checkable
+            :auto-expand-parent="autoExpandParent"
+            :tree-data="subregionData"
+            :checkStrictly="true"
+            :expanded-keys="parentArr"
+            @check="onCheck"
+            @expand="onExpand"
+            :replaceFields="{children:'subareaAreaList', title:'name', key:'areaSn'}"
+          />
+        </div>
+      </div>
+      <div class="areaFooter">
+        <a-button type="primary" @click="save" :disabled="disabled" id="areaSet-refresh">保存</a-button>
+        <a-button style="margin-left: 5px" @click="visible = false" :disabled="disabled" id="areaSet-reset">取消</a-button>
+      </div>
+    </div>
+  </a-drawer>
+</template>
+
+<script>
+import { commonMixin } from '@/utils/mixin'
+import { subareaQueryAll } from '@/api/subarea'
+export default {
+  mixins: [commonMixin],
+  props: {
+    showModal: {
+      type: Boolean,
+      default: false
+    },
+    chooseData: {
+      type: Object,
+      default: () => {
+        return {}
+      }
+    }
+  },
+  watch: {
+    showModal (newValue, oldValue) {
+      this.visible = newValue
+    },
+    visible (newValue, oldValue) {
+      if (!newValue) {
+        this.checkedKeys = { checked: [], halfChecked: [] }
+        this.checkAll = false
+        this.$emit('close')
+      }
+    }
+  },
+  data () {
+    return {
+      autoExpandParent: true,
+      checkAll: false, //  全选
+      checkedKeys: {
+        checked: [], halfChecked: []
+      },
+      subregionData: null,
+      tableHeight: 0,
+      visible: false,
+      disabled: false,
+      parentArr: []
+    }
+  },
+  methods: {
+    // 树  默认展开被选子级的父级
+    onExpand (expandedKeys) {
+      console.log('onExpand', expandedKeys)
+      this.parentArr = expandedKeys
+      this.autoExpandParent = false
+    },
+    getArea () {
+      subareaQueryAll().then(res => {
+        if (res.status == 200) {
+          res.data && res.data.map(item => {
+            item.name = item.subareaName
+            item.areaSn = item.subareaSn
+            if (item.subareaAreaList) {
+              item.subareaAreaList.map(cd => {
+                cd.name = cd.subareaAreaName
+                cd.areaSn = cd.subareaAreaSn + '_'
+                const falg = this.chooseData.checked.length > 0 ? this.chooseData.checked.includes(cd.subareaAreaSn + '_') : false
+                if (falg) {
+                  this.parentArr.push(cd.subareaSn)
+                }
+              })
+            }
+          })
+          this.subregionData = res.data
+          this.checkedKeys = this.chooseData ? this.chooseData : []
+        }
+      })
+    },
+
+    save () {
+      this.$emit('ok', this.checkedKeys)
+    },
+    // 全选
+    onCheckAllChange (e) {
+      this.checkAll = e.target.checked
+      if (e.target.checked) {
+        this.checkedKeys.checked = []
+        this.checkedKeys.halfChecked = []
+        this.getAllFun(this.subregionData)
+      } else {
+        this.checkedKeys.checked = []
+        this.checkedKeys.halfChecked = []
+      }
+    },
+    // 递归完成全选
+    getAllFun (data) {
+      if (data) {
+        data.map((item, index) => {
+          this.checkedKeys.checked.push(item.areaSn)
+          if (item.subareaAreaList && item.subareaAreaList.length > 0) {
+            this.getAllFun(item.subareaAreaList)
+          }
+        })
+      }
+    },
+    onCheck (checkedKeys) {
+      this.checkedKeys = checkedKeys
+    },
+    pageInit () {
+      const _this = this
+      this.$nextTick(() => { // 页面渲染完成后的回调
+        _this.setTableH()
+      })
+      this.getArea()
+    },
+    setTableH () {
+      this.tableHeight = window.innerHeight - 345
+    }
+  }
+}
+</script>
+
+<style lang="less" scoped>
+.areaSetModal {
+  width: 100%;
+  .areaFooter {
+    text-align:center;
+  }
+}
+</style>

+ 280 - 0
src/views/dealerManagement/businessOwnerSettings/chooseDealer.vue

@@ -0,0 +1,280 @@
+<template>
+  <a-spin :spinning="spinning" tip="Loading...">
+    <!-- 搜索条件 -->
+    <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">
+            <a-form-item label="经销商名称/别名">
+              <a-input id="chooseDealer-nameLike" v-model.trim="queryParam.dealer.nameLike" allowClear placeholder="请输入经销商名称/别名"/>
+            </a-form-item>
+          </a-col>
+          <a-col :md="8" :sm="24">
+            <a-form-item label="商户类型">
+              <v-select code="DEALER_TYPE" id="chooseDealer-dealerType" v-model="queryParam.dealer.dealerType" allowClear placeholder="请选择商户类型"></v-select>
+            </a-form-item>
+          </a-col>
+          <a-col :md="8" :sm="24">
+            <a-form-model-item label="商户级别" prop="dealerLevel">
+              <v-select code="DEALER_LEVEL" id="ucModal-dealerLevel" v-model="queryParam.dealer.dealerLevel" allowClear placeholder="请选择商户级别"></v-select>
+            </a-form-model-item>
+          </a-col>
+          <a-col :md="8" :sm="24" v-if="pageType!='viewDealers'">
+            <a-form-item label="所在区域/分区">
+              <subarea id="chooseDealer-subarea" ref="subarea" @change="subareaChange"></subarea>
+            </a-form-item>
+          </a-col>
+          <div v-else>
+            <a-col :md="8" :sm="24">
+              <a-form-item label="审核状态">
+                <v-select code="AUDIT_STATE" id="viewDealers-auditState" v-model="queryParam.auditState" allowClear placeholder="请选择审核状态"></v-select>
+              </a-form-item>
+            </a-col>
+            <a-col :md="8" :sm="24">
+              <a-form-model-item label="地区">
+                <AreaList id="viewDealers-areaList" changeOnSelect ref="areaList" @change="areaChange" defValKey="id"></AreaList>
+              </a-form-model-item>
+            </a-col>
+          </div>
+          <a-col :md="pageType!='viewDealers'?8:6" :sm="24" style="margin-bottom: 10px;">
+            <a-button type="primary" @click="searchForm(true)" :disabled="disabled" id="chooseDealer-refresh">查询</a-button>
+            <a-button style="margin-left: 5px" @click="resetSearchForm" :disabled="disabled" id="chooseDealer-reset">重置</a-button>
+          </a-col>
+        </a-row>
+      </a-form>
+      <!-- 列表 -->
+      <div style="margin-bottom: 10px">
+        <a-button type="primary" ghost :loading="loading" @click="handleBatchAudit">批量添加</a-button>
+        <span style="margin-left: 5px">
+          <template v-if="selectCount"> {{ `已选 ${selectCount} 项` }} </template>
+        </span>
+      </div>
+    </div>
+    <s-table
+      class="sTable"
+      ref="table"
+      size="small"
+      :rowKey="(record) => record.dealerSn"
+      rowKeyName="dealerSn"
+      :row-selection="{ columnWidth: 40, getCheckboxProps: record => ({ props: { disabled: pageType=='viewDealers'?!!record.subareaAreaSn: !!record.chooseId} }) }"
+      @rowSelection="rowSelectionFun"
+      :columns="columns"
+      :data="loadData"
+      :style="{ height:pageType=='viewDealers'? tableHeight+84.5+'px':tableHeight-15+'px' }"
+      :scroll="{ y: pageType=='viewDealers'?tableHeight:tableHeight+80 }"
+      :defaultLoadData="false"
+      bordered>
+      <template slot="areas" slot-scope="text, record">
+        <span v-if="record.subareaArea">{{ record.subareaArea.subareaName }}>{{ record.subareaArea.subareaAreaName }}</span>
+        <span v-else>--</span>
+      </template>
+      <template slot="action" slot-scope="text, record">
+        <a-button
+          size="small"
+          type="link"
+          class="button-error"
+          @click="handleAdd(record)"
+          v-if="record.subareaAreaSn != parentData.subareaAreaSn"
+          id="marketingDivisionSetNew-del-btn">添加</a-button>
+        <span style="color:#666" v-else>已添加</span>
+      </template>
+    </s-table>
+  </a-spin>
+</template>
+
+<script>
+import { commonMixin } from '@/utils/mixin'
+import { STable, VSelect } from '@/components'
+import AreaList from '@/views/common/areaList.js'
+import { bizuserScopeQueryDealer } from '@/api/bizuser'
+import subarea from '@/views/common/subarea.js'
+export default {
+  name: 'ChooseDealer',
+  mixins: [commonMixin],
+  components: { STable, VSelect, subarea, AreaList },
+  props: {
+    pageType: {
+      type: String,
+      default: ''
+    },
+    parentData: {
+      type: Object,
+      default: function () {
+        return null
+      }
+    }
+  },
+  data () {
+    return {
+      spinning: false,
+      queryParam: { //  查询条件
+        dealer: {
+          nameLike: '',
+          dealerType: null,
+          dealerLevel: null
+        },
+        auditState: undefined,
+        provinceSn: undefined,
+        citySn: undefined,
+        districtSn: undefined,
+        subareaSn: undefined,
+        subareaAreaSn: undefined
+      },
+      userSn: '',
+      pageFlag: false,
+      chooseInfo: [],
+      tableHeight: 0,
+      disabled: false, //  查询、重置按钮是否可操作
+      loading: false, // 批量添加loading
+      // 加载数据方法 必须为 Promise 对象
+      loadData: parameter => {
+        this.spinning = true
+        this.queryParam.userSn = this.userSn
+        return bizuserScopeQueryDealer(Object.assign(parameter, this.queryParam)).then(res => {
+          let data
+          const _this = this
+          if (res.status == 200) {
+            data = res.data
+            const no = 0
+            const chooseData = []
+            for (var i = 0; i < data.list.length; i++) {
+              data.list[i].no = no + i + 1
+              data.list[i].dealerSn = data.list[i].dealer.dealerSn
+              if (!_this.pageType && _this.chooseInfo && _this.chooseInfo.length > 0) {
+                // 回显选中数据
+                const flag = _this.chooseInfo.includes(data.list[i].dealer.dealerSn)
+                if (flag) {
+                  chooseData.push(data.list[i])
+                }
+              }
+            }
+            if (!this.pageFlag) {
+              this.pageFlag = true
+              _this.$refs.table.setTableSelected(_this.chooseInfo, chooseData) // 设置表格选中项
+            }
+          }
+          this.spinning = false
+          return data
+        })
+      },
+      rowSelectionInfo: null
+    }
+  },
+  computed: {
+    columns () {
+      const _this = this
+      const arr = [
+        { title: '经销商名称', dataIndex: 'dealer.dealerName', width: '30%', align: 'center', customRender: function (text) { return text || '--' }, ellipsis: true },
+        { title: '商户别名', dataIndex: 'dealer.dealerAlias', align: 'left', width: '30%', customRender: function (text) { return text || '--' }, ellipsis: true },
+        { title: '商户类型', dataIndex: 'dealer.dealerTypeDictValue', width: '15%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '商户级别', dataIndex: 'dealer.dealerLevelDictValue', width: '15%', align: 'center', customRender: function (text) { return text || '--' } }
+      ]
+      if (_this.pageType == 'viewDealers') {
+        arr.splice(4, 0, { title: '审核状态', dataIndex: 'auditStateDictValue', width: '20%', align: 'center', customRender: function (text) { return text || '--' } })
+        arr.splice(5, 0, { title: '当前所属区域', scopedSlots: { customRender: 'areas' }, width: '30%', align: 'center' })
+        arr.splice(6, 0, { title: '操作', scopedSlots: { customRender: 'action' }, width: '20%', align: 'center' })
+      } else {
+        arr.splice(4, 0, { title: '所在区域', dataIndex: 'subareaName', width: '20%', align: 'center', customRender: function (text) { return text || '--' } })
+        arr.splice(5, 0, { title: '所在分区', dataIndex: 'subareaAreaName', width: '20%', align: 'center', customRender: function (text) { return text || '--' } })
+      }
+      return arr
+    },
+    selectCount () {
+      return this.rowSelectionInfo && this.rowSelectionInfo.selectedRowKeys.length
+    }
+  },
+  methods: {
+    // 表格选中项
+    rowSelectionFun (obj) {
+      this.rowSelectionInfo = obj || null
+    },
+    areaChange (val) {
+      this.queryParam.provinceSn = val[0] ? val[0] : ''
+      this.queryParam.citySn = val[1] ? val[1] : ''
+      this.queryParam.districtSn = val[2] ? val[2] : ''
+    },
+    searchForm (flag) {
+      this.$refs.table.refresh(flag)
+      this.spinning = false
+    },
+    subareaChange (val) {
+      this.queryParam.subareaSn = val[0] ? val[0] : undefined
+      this.queryParam.subareaAreaSn = val[1] ? val[1] : undefined
+    },
+    //  重置
+    resetSearchForm () {
+      this.queryParam = {
+        dealer: {
+          nameLike: '',
+          dealerType: null,
+          dealerLevel: null
+        },
+        auditState: undefined,
+        provinceSn: undefined,
+        citySn: undefined,
+        districtSn: undefined,
+        subareaSn: undefined,
+        subareaAreaSn: undefined
+      }
+      if (this.pageType != 'viewDealers') {
+        this.$refs.subarea.clearData()
+      } else {
+        this.$refs.areaList.clearData()
+      }
+      this.$refs.table.clearSelected()
+      this.$refs.table.refresh(true)
+      this.pageFlag = false
+    },
+    clearTable () {
+      this.rowSelectionInfo = null
+      this.$refs.table.clearTable()
+    },
+    // 批量添加
+    handleBatchAudit () {
+      const _this = this
+      if (!_this.rowSelectionInfo || (_this.rowSelectionInfo && _this.rowSelectionInfo.selectedRowKeys.length < 1)) {
+        _this.$message.warning('请在列表勾选后再进行批量操作!')
+        return
+      }
+      const dealerSnList = _this.rowSelectionInfo.selectedRowKeys
+      this.spinning = false
+      this.$emit('plAdd', dealerSnList)
+    },
+    handleAdd (row) {
+      if (row.subareaArea) {
+        const _this = this
+        this.$confirm({
+          title: '提示',
+          content: '当前经销商已被其他区域分区绑定,确定要更新绑定关系吗?',
+          centered: true,
+          onOk () {
+            _this.spinning = true
+            _this.$emit('add', row)
+          }
+        })
+      } else {
+        this.spinning = true
+        this.$emit('add', row)
+      }
+    },
+    pageInit (data) {
+      const _this = this
+      this.$nextTick(() => { // 页面渲染完成后的回调
+        _this.setTableH()
+      })
+      this.chooseInfo = data.list ? data.list :[]
+      this.userSn = data.sn
+      this.resetSearchForm()
+    },
+    setTableH () {
+      const tableSearchH = this.$refs.tableSearch.offsetHeight
+      this.tableHeight = window.innerHeight - tableSearchH - 285
+    }
+  },
+  watch: {
+    '$store.state.app.winHeight' (newValue, oldValue) { //  窗口变更时,需同时更改表格高度
+      this.setTableH()
+    }
+  }
+}
+</script>

+ 211 - 0
src/views/dealerManagement/businessOwnerSettings/list.vue

@@ -0,0 +1,211 @@
+<template>
+  <div>
+    <a-card size="small" :bordered="false">
+      <!-- 搜索条件 -->
+      <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="6" :sm="24">
+              <a-form-model-item label="人员类型">
+                <v-select
+                  v-model="queryParam.bizUserType"
+                  ref="printStatus"
+                  id="businessOwnerSettings-printStatus"
+                  code="BIZ_USER_TYPE"
+                  placeholder="请选择人员类型"
+                  allowClear></v-select>
+              </a-form-model-item>
+            </a-col>
+            <a-col :md="6" :sm="24">
+              <a-form-item label="人员姓名">
+                <a-input id="businessOwnerSettings-name" v-model.trim="queryParam.userName" allowClear placeholder="请输入人员姓名"/>
+              </a-form-item>
+            </a-col>
+            <a-col :md="24" :sm="24" style="margin-top: 10px;text-align:center;">
+              <a-button type="primary" @click="$refs.table.refresh(true)" :disabled="disabled" id="businessOwnerSettings-refresh">查询</a-button>
+              <a-button style="margin-left: 5px" @click="resetSearchForm" :disabled="disabled" id="businessOwnerSettings-reset">重置</a-button>
+            </a-col>
+          </a-row>
+        </a-form>
+      </div>
+    </a-card>
+    <a-card size="small" :bordered="false" class="dealerZoneSearch-wrap">
+      <a-spin :spinning="spinning" tip="Loading...">
+        <div class="table-operator">
+          <a-button id="businessOwnerSettings-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.id"
+          :columns="columns"
+          :data="loadData"
+          :scroll="{ y: tableHeight }"
+          :defaultLoadData="false"
+          bordered>
+          <!-- 操作 -->
+          <template slot="action" slot-scope="text, record">
+            <a-button size="small" type="link" class="button-warning" v-if="record.allDealerFlag!=1 || record.allProductFlag!=1" @click="handleSetCategory(record)">设置管辖范围</a-button>
+            <a-button size="small" type="link" class="button-info" @click="handleEdit(record)">编辑</a-button>
+            <a-button size="small" type="link" class="button-error" @click="handleDelete(record)">删除</a-button>
+          </template>
+        </s-table>
+      </a-spin>
+    </a-card>
+    <!-- 新增 -->
+    <addModal :itemId="itemId" ref="addUser" :openModal="openAddModal" @close="closeModal" @ok="$refs.table.refresh(true)"></addModal>
+  </div>
+</template>
+
+<script>
+import { commonMixin } from '@/utils/mixin'
+import { STable, VSelect } from '@/components'
+import { queryPage, bizuserDelete } from '@/api/bizuser'
+import addModal from './addModal'
+export default {
+  name: 'BusinessOwnerSettings',
+  mixins: [commonMixin],
+  components: { STable, VSelect, addModal },
+  data () {
+    return {
+      spinning: false,
+      disabled: false, //  查询、重置按钮是否可操作
+      tableHeight: 0,
+      queryParam: {
+        bizUserType: '',
+        userName: undefined
+      },
+      columns: [
+        { title: '创建时间', dataIndex: 'createDate', width: '15%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '人员姓名', dataIndex: 'userName', width: '15%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '人员类型', dataIndex: 'bizUserTypeDictValue', width: '15%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '管辖经销商', dataIndex: 'allDealerFlagDictValue', width: '18%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '管辖品类', dataIndex: 'allProductFlagDictValue', width: '18%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '操作', scopedSlots: { customRender: 'action' }, width: '20%', align: 'center' }
+      ],
+      // 加载数据方法 必须为 Promise 对象
+      loadData: parameter => {
+        this.disabled = true
+        this.spinning = true
+        return queryPage(Object.assign(parameter, this.queryParam)).then(res => {
+          let data
+          data = res.data
+          const no = (data.pageNo - 1) * data.pageSize
+          this.total = data.count || 0
+          for (var i = 0; i < data.list.length; i++) {
+            data.list[i].no = no + i + 1
+          }
+          this.disabled = false
+          this.spinning = false
+          return data
+        })
+      },
+      openAddModal: false, //  编辑  弹框
+      itemId: ''
+    }
+  },
+  methods: {
+    userChange (val) {
+      this.queryParam.userSn = val.key
+    },
+    handleSetCategory (row) {
+      this.$router.push({ name: 'categorySet', query: { sn: row.userSn, id: row.id } })
+    },
+    // 新增
+    handleAdd () {
+      this.itemId = ''
+      this.openAddModal = true
+    },
+    //  重置
+    resetSearchForm () {
+      this.queryParam = {
+        bizUserType: '',
+        userName: ''
+      }
+      this.itemId = ''
+      this.$refs.table.refresh(true)
+    },
+    // 删除
+    handleDelete (row) {
+      const _this = this
+      this.$confirm({
+        title: '提示',
+        content: '确定要删除吗?',
+        centered: true,
+        onOk () {
+          _this.spinning = true
+          bizuserDelete({ id: row.id }).then(res => {
+            if (res.status == 200) {
+              _this.$message.success(res.message)
+              _this.$refs.table.refresh()
+              _this.spinning = false
+            } else {
+              _this.spinning = false
+            }
+          })
+        }
+      })
+    },
+    //  编辑
+    handleEdit (row) {
+      this.itemId = row.id
+      this.openAddModal = true
+      const _this = this
+      this.$nextTick(() => {
+        _this.$refs.addUser.getEditInfo(row)
+      })
+    },
+    //  关闭弹框
+    closeModal () {
+      this.itemId = ''
+      this.openAddModal = false
+    },
+    pageInit () {
+      const _this = this
+      this.$nextTick(() => { // 页面渲染完成后的回调
+        _this.setTableH()
+      })
+      this.resetSearchForm()
+    },
+    setTableH () {
+      const tableSearchH = this.$refs.tableSearch.offsetHeight
+      this.tableHeight = window.innerHeight - tableSearchH - 275
+    }
+  },
+  watch: {
+    '$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()
+    }
+    // 仅刷新列表,不重置页面
+    if (this.$store.state.app.updateList) {
+      this.pageInit()
+    }
+  },
+  beforeRouteEnter (to, from, next) {
+    next(vm => {})
+  }
+}
+</script>
+<style lang="less">
+  .dealerZoneSearch-wrap{
+    height: 100%;
+    margin-top:6px;
+    .table-operator{
+      text-align:right;
+    }
+  }
+</style>

+ 357 - 0
src/views/dealerManagement/businessOwnerSettings/settingsIndex.vue

@@ -0,0 +1,357 @@
+<template>
+  <div class="categorySet-wrap">
+    <a-spin :spinning="spinning" tip="Loading...">
+      <div ref="headerBar">
+        <a-page-header :ghost="false" :backIcon="false" class="header-bar">
+          <!-- 自定义的二级文字标题 -->
+          <template slot="subTitle">
+            <span class="subTitle-word text-overflow" style="max-width:300px;">用户姓名:{{ infoObj.userName?infoObj.userName:'--' }}</span>
+            <a-button id="purchaseNewOrderEdit-back-btn" type="link" @click="handleBack" class="button-default"> <a-icon type="rollback" /> 返回列表</a-button>
+          </template>
+        </a-page-header>
+      </div>
+      <a-card size="small" :bordered="false" class="categorySet-cont">
+        <div :style="{ height: tableHeight+84.5+'px' }">
+          <a-tabs v-model="activeKeyVal" @change="handleTabs">
+            <a-tab-pane key="1" tab="设置管辖区域" v-if="infoObj.allDealerFlag && infoObj.allDealerFlag!=1">
+              <div class="areaSet-wrap">
+                <div class="table-page-search-wrapper newTableSearchName" >
+                  <div class="areaSet-btnGroup" style="margin-bottom:20px;">
+                    <a-button type="primary" class="button-error" @click="openAreaModal" ghost>选择区域</a-button>
+                    <a-button type="primary" class="button-error" @click="openDealerModal" ghost>选择经销商</a-button>
+                  </div>
+                  <a-form layout="inline" @keyup.enter.native="$refs.table.refresh(true)">
+                    <a-row :gutter="15">
+                      <a-col :md="6" :sm="24">
+                        <a-form-model-item label="所在区域/分区">
+                          <subarea id="chooseDealer-subarea" ref="subarea" @change="subareaChange"></subarea>
+                        </a-form-model-item>
+                      </a-col>
+                      <a-col :md="6" :sm="24">
+                        <a-form-item label="经销商名称">
+                          <a-input id="areaSet-dealerName" v-model.trim="queryParam.dealerName" allowClear placeholder="请输入经销商名称"/>
+                        </a-form-item>
+                      </a-col>
+                      <a-col :md="6" :sm="24">
+                        <a-button type="primary" @click="$refs.table.refresh(true)" :disabled="disabled" id="areaSet-refresh">查询</a-button>
+                        <a-button style="margin-left: 5px" @click="resetSearchForm" :disabled="disabled" id="areaSet-reset">重置</a-button>
+                      </a-col>
+                    </a-row>
+                  </a-form>
+                </div>
+                <a-spin :spinning="spinning" tip="Loading...">
+                  <!-- 列表 -->
+                  <s-table
+                    class="sTable fixPagination"
+                    ref="table"
+                    size="small"
+                    :rowKey="(record) => record.no"
+                    rowKeyName="no"
+                    :columns="columns"
+                    :data="loadData"
+                    :defaultLoadData="false"
+                    :style="{ height: tableHeight-100+'px' }"
+                    :scroll="{ y: tableHeight-180 }"
+                    bordered>
+                    <!-- 操作 -->
+                    <template slot="action" slot-scope="text, record">
+                      <a-button
+                        size="small"
+                        type="link"
+                        class="button-error"
+                        @click="handleDel(record)"
+                      >
+                        删除
+                      </a-button>
+                    </template>
+                  </s-table>
+                </a-spin>
+              </div>
+            </a-tab-pane>
+            <a-tab-pane key="2" tab="设置管辖品类" force-render v-if="infoObj.allProductFlag&&infoObj.allProductFlag!=1">
+              <categorySet ref="setCategory" :bizUserSn="infoObj.bizUserSn"></categorySet>
+            </a-tab-pane>
+          </a-tabs>
+        </div>
+      </a-card>
+      <!-- 选择区域 -->
+      <chooseAreaModal
+        ref="partQuery"
+        :showModal="openChooseArea"
+        :chooseData="newChooseData"
+        @ok="handleArea"
+        @close="openChooseArea=false">
+      </chooseAreaModal>
+      <!-- 选择经销商 -->
+      <a-drawer
+        title="选择经销商"
+        width="80%"
+        :zIndex="100"
+        :visible="openChooseDealer"
+        :get-container="false"
+        :wrap-style="{ position: 'absolute' }"
+        @close="openChooseDealer = false">
+        <div class="dealerModalCon">
+          <chooseDealer ref="dealerChoose" @plAdd="handleAddDealer"></chooseDealer>
+        </div>
+      </a-drawer>
+    </a-spin>
+  </div>
+</template>
+
+<script>
+import { commonMixin } from '@/utils/mixin'
+import { STable } from '@/components'
+import categorySet from './categorySet'
+import chooseAreaModal from './chooseAreaModal'
+import chooseDealer from './chooseDealer.vue'
+import { bizuserScopeQueryPage, bizuserScopeDelete, findById, queryAreaScope, queryDealerScope, saveAreaScope, saveDealerScope } from '@/api/bizuser'
+import subarea from '@/views/common/subarea.js'
+export default {
+  name: 'SettingsIndex',
+  mixins: [commonMixin],
+  components: { STable, categorySet, chooseAreaModal, chooseDealer, subarea },
+  data () {
+    return {
+      openChooseArea: false,
+      openChooseDealer: false,
+      spinning: false,
+      tableHeight: 0,
+      queryParam: {
+        hasDetail: 0,
+        bizType: undefined,
+        bizSn: undefined,
+        dealerName: ''
+      },
+      activeKeyVal: '1',
+      infoObj: {},
+      newChooseData: {// 区域分区回显
+        checked: [],
+        halfChecked: []
+      },
+      columns: [
+        { title: '序号', dataIndex: 'no', width: '4%', align: 'center' },
+        { title: '添加时间', dataIndex: 'createDate', width: '16%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '区域', dataIndex: 'subareaName', width: '10%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '分区', dataIndex: 'subareaAreaName', width: '10%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '经销商', dataIndex: 'dealerName', width: '16%', align: 'center', customRender: function (text) { return text || '--' }, ellipsis: true },
+        { title: '操作', scopedSlots: { customRender: 'action' }, width: '8%', align: 'center' }
+      ],
+      disabled: false, //  查询、重置按钮是否可操作
+      chooseInfo: [], // 回显选中经销商信息
+      loadData: parameter => {
+        this.disabled = true
+        this.spinning = true
+        this.queryParam.userSn = this.$route.query.sn
+        return bizuserScopeQueryPage(Object.assign(parameter, this.queryParam)).then(res => {
+          let data
+          if (res.status == 200) {
+            data = res.data
+            const no = (data.pageNo - 1) * data.pageSize
+            this.total = data.count || 0
+            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: {
+    // 获取用户基本信息
+    getBaseInfo () {
+      const _this = this
+      findById({ id: _this.$route.query.id }).then(res => {
+        if (res.status == 200) {
+          _this.infoObj = res.data
+          _this.activeKeyVal = '1'
+          _this.$nextTick(() => {
+            _this.$refs.table.refresh()
+          })
+        }
+      })
+    },
+    // 选择区域>分区
+    handleArea (con) {
+      const chooseData = con.checked
+      const newData = []
+      chooseData.forEach(item => {
+        const obj = {}
+        obj.userSn = this.$route.query.sn
+        obj.bizUserSn = this.infoObj.bizUserSn
+        if (item.indexOf('_') != -1) { // 分区获取数据带_    区域不带下划线
+          obj.bizType = 'subarea_area'
+          obj.bizSn = item.replace('_', '')
+          newData.push(obj)
+        } else {
+          obj.bizType = 'subarea'
+          obj.bizSn = item
+          newData.push(obj)
+        }
+      })
+      this.saveChooseArea(newData)
+    },
+    saveChooseArea (list) {
+      const _this = this
+      const newAjaxData = {}
+      newAjaxData.userSn = _this.$route.query.sn
+      newAjaxData.bizUserScopeList = list
+      saveAreaScope(newAjaxData).then(res => {
+        if (res.status == 200) {
+          _this.openChooseArea = false
+          _this.resetSearchForm()
+        }
+      })
+    },
+    handleTabs (val) {
+      this.activeKeyVal = val
+      if (val == 2) {
+        this.$refs.setCategory.pageInit()
+      }
+    },
+    // 所在区域分区查询
+    subareaChange (val) {
+      if (val.length == 1) {
+        this.queryParam.bizSn = val[0]
+        this.queryParam.bizType = 'subarea'
+      } else if (val.length == 2) {
+        this.queryParam.bizSn = val[1]
+        this.queryParam.bizType = 'subarea_area'
+      } else {
+        this.queryParam.bizSn = undefined
+        this.queryParam.bizType = undefined
+      }
+    },
+    resetSearchForm () {
+      this.queryParam = {
+        bizSn: undefined,
+        bizType: undefined,
+        dealerName: '',
+        hasDetail: 0
+      }
+      if (this.infoObj && this.infoObj.allDealerFlag != 1) {
+        this.$refs.subarea.clearData()
+        this.$refs.table.refresh(true)
+      }
+    },
+    // 选择区域
+    async openAreaModal () {
+      const _this = this
+      const checkedArr = []
+      const dataList = await queryAreaScope({ userSn: this.$route.query.sn, hasDetail: 0 })
+      if (dataList.data && dataList.data.length > 0) {
+        dataList.data.forEach(item => {
+          if (item.bizType == 'subarea_area') {
+            item.bizSn = item.bizSn + '_'
+          }
+          checkedArr.push(item.bizSn)
+        })
+        const newCheckedArr = [...new Set(checkedArr)]
+        console.log('end choose:', newCheckedArr)
+        this.newChooseData.checked = newCheckedArr
+      } else {
+        this.newChooseData.checked = []
+      }
+      this.$refs.partQuery.pageInit()
+      _this.$nextTick(() => {
+        _this.openChooseArea = true
+      })
+    },
+    // 打开经销商弹窗
+    async openDealerModal (params = {}) {
+      const _this = this
+      const arr = []
+      const dataList = await queryDealerScope({ userSn: this.$route.query.sn, hasDetail: 0 })
+      if (dataList.data && dataList.data.length > 0) {
+        dataList.data.forEach(con => {
+          arr.push(con.bizSn)
+        })
+        _this.chooseInfo = [...new Set(arr)]
+      } else {
+        _this.chooseInfo = []
+      }
+      const dataInfo = {
+        list: _this.chooseInfo,
+        sn: _this.$route.query.sn
+      }
+      _this.openChooseDealer = true
+      if (_this.openChooseDealer) {
+        _this.$refs.dealerChoose.pageInit(dataInfo)
+      }
+    },
+    // 经销商
+    handleAddDealer (list) {
      const newData = []
      list.forEach(con => {
        const obj = {}
+        obj.userSn = this.$route.query.sn
+        obj.bizUserSn = this.infoObj.bizUserSn
        obj.bizType = 'dealer'
        obj.bizSn = con
        newData.push(obj)
      })
      this.saveChooseDealer(newData)
    },
+    // 保存所选区域或经销商
+    saveChooseDealer (list) {
+      const _this = this
+      const ajaxData = {}
+      ajaxData.userSn = _this.$route.query.sn
+      ajaxData.bizUserScopeList = list
+      saveDealerScope(ajaxData).then(res => {
+        if (res.status == 200) {
+          _this.openChooseDealer = false
+          _this.resetSearchForm()
+        }
+      })
+    },
+    //  删除
+    handleDel (row) {
+      const _this = this
+      this.$confirm({
+        title: '提示',
+        content: '确认要删除吗?删除后当前用户权限以最新权限为准',
+        centered: true,
+        onOk () {
+          bizuserScopeDelete({ id: row.bizUserScopeSn }).then(res => {
+            if (res.status == 200) {
+              _this.resetSearchForm()
+            }
+          })
+        }
+      })
+    },
+    //  返回
+    handleBack () {
+      this.$router.push({ name: 'businessOwnerSettings' })
+    },
+    pageInit () {
+      const _this = this
+      this.$nextTick(() => { // 页面渲染完成后的回调
+        _this.setTableH()
+      })
+      _this.getBaseInfo()
+    },
+    setTableH () {
+      const headHeight = this.$refs.headerBar.offsetHeight
+      this.tableHeight = window.innerHeight - headHeight - 230
+    }
+  },
+  watch: {
+    '$store.state.app.winHeight' (newValue, oldValue) { //  窗口变更时,需同时更改表格高度
+      this.setTableH()
+    }
+  },
+  mounted () {
+    this.pageInit()
+  },
+  activated () {
+    this.pageInit()
+  },
+  beforeRouteEnter (to, from, next) {
+    next(vm => {})
+  }
+}
+</script>
+
+<style lang="less" scoped>
+  .categorySet-wrap{
+    .table-operator{
+    text-align:right;
+    }
+  }
+</style>

+ 221 - 0
src/views/dealerManagement/dealerZoneSearch/list.vue

@@ -0,0 +1,221 @@
+<template>
+  <div>
+    <a-card size="small" :bordered="false">
+      <!-- 搜索条件 -->
+      <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="6" :sm="24">
+              <a-form-model-item label="所属区域/分区">
+                <subarea id="dealerZoneSearch-subareaSn" ref="subarea" @change="subareaChange"></subarea>
+              </a-form-model-item>
+            </a-col>
+            <a-col :md="6" :sm="24">
+              <a-form-item label="经销商">
+                <custList id="dealerZoneSearch-dealerName" placeholder="请输入经销商名称搜索" ref="indirectDealer" @change="dealerChange" />
+              </a-form-item>
+            </a-col>
+            <a-col :md="8" :sm="24">
+              <a-form-item label="客服/区域负责人/销售总监">
+                <a-input id="dealerZoneSearch-dealerName" v-model.trim="queryParam.bizUserName" allowClear placeholder="请输入客服/区域负责人/销售总监"/>
+              </a-form-item>
+            </a-col>
+            <a-col :md="24" :sm="24" style="margin-top: 10px;text-align:center;">
+              <a-button type="primary" @click="$refs.table.refresh(true)" :disabled="disabled" id="dealerZoneSearch-refresh">查询</a-button>
+              <a-button style="margin-left: 5px" @click="resetSearchForm" :disabled="disabled" id="dealerZoneSearch-reset">重置</a-button>
+              <a-button
+                style="margin-left: 5px"
+                type="primary"
+                class="button-warning"
+                @click="handleExport"
+                :loading="exportLoading"
+                id="dealerZoneSearch-export">导出</a-button>
+            </a-col>
+          </a-row>
+        </a-form>
+      </div>
+    </a-card>
+    <a-card size="small" :bordered="false" class="dealerZoneSearch-wrap">
+      <a-spin :spinning="spinning" tip="Loading...">
+        <!-- 列表 -->
+        <s-table
+          class="sTable fixPagination"
+          ref="table"
+          :style="{ height: tableHeight+84.5+'px' }"
+          size="small"
+          :rowKey="(record) => record.no"
+          rowKeyName="no"
+          :columns="columns"
+          :data="loadData"
+          :scroll="{ y: tableHeight }"
+          :defaultLoadData="false"
+          bordered>
+          <template slot="kf" slot-scope="text, record">
+            <a-tooltip placement="top" v-if="record.userNameKfs">
+              <template slot="title">
+                {{ record.userNameKfs }}
+              </template>
+              <div class="line-2">{{ record.userNameKfs }}</div>
+            </a-tooltip>
+            <span v-else>--</span>
+          </template>
+          <template slot="qyfzr" slot-scope="text, record">
+            <a-tooltip placement="top" v-if="record.userNameQyfzrs">
+              <template slot="title">
+                {{ record.userNameQyfzrs }}
+              </template>
+              <div class="line-2">{{ record.userNameQyfzrs }}</div>
+            </a-tooltip>
+            <span v-else>--</span>
+          </template>
+          <template slot="xszj" slot-scope="text, record">
+            <a-tooltip placement="top" v-if="record.userNameXszjs">
+              <template slot="title">
+                {{ record.userNameXszjs }}
+              </template>
+              <div class="line-2">{{ record.userNameXszjs }}</div>
+            </a-tooltip>
+            <span v-else>--</span>
+          </template>
+        </s-table>
+      </a-spin>
+    </a-card>
+  </div>
+</template>
+
+<script>
+import { commonMixin } from '@/utils/mixin'
+import { STable } from '@/components'
+import subarea from '@/views/common/subarea.js'
+import { exportExcel } from '@/libs/JGPrint.js'
+import { queryDealerWithBizuser, exportDealerWithBizuser } from '@/api/dealerRelation'
+import custList from '@/views/common/custList.vue'
+export default {
+  name: 'DealerZoneSearch',
+  mixins: [commonMixin],
+  components: { STable, subarea, custList },
+  data () {
+    return {
+      spinning: false,
+      disabled: false, //  查询、重置按钮是否可操作
+      tableHeight: 0,
+      queryParam: {
+        subareaSn: undefined,
+        subareaAreaSn: undefined,
+        dealer: {
+          dealerSn: '',
+          dealerName: ''
+        },
+        bizUserName: ''
+      },
+      exportLoading: false, // 导出loading
+      columns: [
+        { title: '经销商名称', dataIndex: 'dealer.dealerName', width: '20%', align: 'center', customRender: function (text) { return text || '--' }, ellipsis: true },
+        { title: '所属区域', dataIndex: 'subareaName', width: '10%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '所属分区', dataIndex: 'subareaAreaName', width: '10%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '客服', scopedSlots: { customRender: 'kf' }, dataIndex: 'userNameKfs', width: '18%', align: 'center' },
+        { title: '区域负责人', scopedSlots: { customRender: 'qyfzr' }, dataIndex: 'userNameQyfzrs', width: '18%', align: 'center' },
+        { title: '销售总监', scopedSlots: { customRender: 'xszj' }, dataIndex: 'userNameXszjs', width: '18%', align: 'center' }
+      ],
+      // 加载数据方法 必须为 Promise 对象
+      loadData: parameter => {
+        this.disabled = true
+        this.spinning = true
+        return queryDealerWithBizuser(Object.assign(parameter, this.queryParam)).then(res => {
+          let data
+          if (res.status == 200) {
+            data = res.data
+            const no = 0
+            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: {
+    // 导出
+    handleExport () {
+      const _this = this
+      const params = this.queryParam
+      this.spinning = true
+      this.exportLoading = true
+      exportExcel(exportDealerWithBizuser, params, '经销商所属分区导出', function () {
+        _this.spinning = false
+        _this.exportLoading = false
+      })
+    },
+    subareaChange (val) {
+      this.queryParam.subareaSn = val[0] ? val[0] : undefined
+      this.queryParam.subareaAreaSn = val[1] ? val[1] : undefined
+    },
+    //  重置
+    resetSearchForm () {
+      this.queryParam.subareaSn = undefined
+      this.queryParam.subareaAreaSn = undefined
+      this.queryParam.dealer.dealerSn = ''
+      this.queryParam.dealer.dealerName = ''
+      this.queryParam.bizUserName = ''
+      this.$refs.indirectDealer.resetForm()
+      this.$refs.subarea.clearData()
+      this.$refs.table.refresh(true)
+    },
+    // 选择经销商
+    dealerChange (val) {
+      this.queryParam.dealer.dealerSn = val.key
+      this.queryParam.dealer.dealerName = (val.label.replace('\n', '')).trim()
+    },
+    pageInit () {
+      const _this = this
+      this.$nextTick(() => { // 页面渲染完成后的回调
+        _this.setTableH()
+      })
+      this.$refs.table.refresh()
+    },
+    setTableH () {
+      const tableSearchH = this.$refs.tableSearch.offsetHeight
+      this.tableHeight = window.innerHeight - tableSearchH - 235
+    }
+  },
+  watch: {
+    '$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()
+    }
+  },
+  beforeRouteEnter (to, from, next) {
+    next(vm => {})
+  }
+}
+</script>
+<style lang="less" scoped>
+  .dealerZoneSearch-wrap{
+    height: 100%;
+    margin-top:6px;
+  }
+  /deep/.ant-select-combobox .ant-select-arrow{
+    display:inline-block !important;
+  }
+  .line-2{
+    width: 100%;
+    overflow:hidden;
+    text-overflow: ellipsis;
+    -webkit-line-clamp: 2;
+    display: -webkit-box;
+    -webkit-box-orient: vertical;
+  }
+</style>

+ 0 - 354
src/views/dealerManagement/marketingDivisionSet/editModal.vue

@@ -1,354 +0,0 @@
-<template>
-  <a-modal
-    centered
-    class="marketingDivisionSetEdit-modal"
-    :footer="null"
-    :maskClosable="false"
-    :title="modalTit"
-    v-model="isShow"
-    @cancel="isShow=false"
-    :width="800">
-    <!-- 表单 -->
-    <div>
-      <a-spin :spinning="spinning" tip="Loading...">
-        <a-form-model
-          id="marketingDivisionSetEdit-form"
-          ref="ruleForm"
-          :model="form"
-          :rules="rules"
-          :label-col="formItemLayout.labelCol"
-          :wrapper-col="formItemLayout.wrapperCol"
-        >
-          <a-form-model-item label="分区名称" prop="subareaName">
-            <a-input
-              id="marketingDivisionSetEdit-subareaName"
-              :maxLength="30"
-              v-model.trim="form.subareaName"
-              @change="filterEmpty"
-              placeholder="请输入分区名称(最多30个字符)"
-              allowClear />
-          </a-form-model-item>
-          <a-form-model-item label="省份/市" required>
-            <div class="tree-node" id="treeNode">
-              <div class="tree-box" v-for="item in addrProvinceList" :key="item.id">
-                <div class="tree-parent">
-                  <span>
-                    <a-checkbox style="width: 100%;" :indeterminate="item.indeterminate" v-model="item.checked" @change="onChange(item,$event)">
-                      {{ item.name }}
-                      <!-- <i style="font-size: 12px;color: #999;font-style: normal;">(已选 {{ item.children | hasCheckChild }} 个市区)</i> -->
-                    </a-checkbox>
-                  </span>
-                  <span @click="expend(item)"><a-icon :title="item.isOpen==0?'展开':'收起'" :type="item.isOpen==0?'plus-square':'minus-square'" /></span>
-                </div>
-
-                <!-- 子级 -->
-                <div v-show="item.isOpen==1" class="tree-child">
-                  <div v-for="child in item.children" :key="child.id">
-                    <a-checkbox v-model="child.checked" style="width: 100%;" @change="onChange(child,$event,item)">
-                      {{ child.name }}
-                    </a-checkbox>
-                  </div>
-                </div>
-              </div>
-            </div>
-          </a-form-model-item>
-        </a-form-model>
-        <div class="btn-cont">
-          <a-button type="primary" id="marketingDivisionSetEdit-modal-save" @click="handleSave">保存</a-button>
-          <a-button id="marketingDivisionSetEdit-modal-back" @click="isShow = false" style="margin-left: 15px;">返回列表</a-button>
-        </div>
-      </a-spin>
-    </div>
-  </a-modal>
-</template>
-
-<script>
-import { STable, Upload } from '@/components'
-import Editor from '@/components/WEeditor'
-import { getArea } from '@/api/data'
-import { subareaSaveSubareaArea, subareaFindBySn } from '@/api/subarea'
-export default {
-  name: 'MarketingDivisionSetEditModal',
-  components: { STable, Upload, Editor },
-  props: {
-    openModal: { //  弹框显示状态
-      type: Boolean,
-      default: false
-    },
-    itemId: {
-      type: [Number, String],
-      default: ''
-    },
-    nowData: {
-      type: Object,
-      default: null
-    }
-  },
-  computed: {
-    modalTit () {
-      return (this.itemId ? '编辑' : '新增') + '分区'
-    }
-  },
-  filters: {
-    hasCheckChild: function (value) {
-      return value.filter(item => item.checked).length
-    }
-  },
-  data () {
-    return {
-      isShow: this.openModal, //  是否打开弹框
-      spinning: false,
-      formItemLayout: {
-        labelCol: { span: 4 },
-        wrapperCol: { span: 18 }
-      },
-      form: {
-        subareaName: '' // 分区名称
-      },
-      rules: {
-        subareaName: [
-          { required: true, message: '请输入分区名称', trigger: 'blur' }
-        ]
-      },
-      addrProvinceList: [], //  省下拉
-      subareaAreaList: []
-    }
-  },
-  methods: {
-    filterEmpty () {
-      let str = this.form.subareaName
-      str = str.replace(/\ +/g, '')
-      str = str.replace(/[ ]/g, '')
-      str = str.replace(/[\r\n]/g, '')
-      this.form.subareaName = str
-    },
-    onChange (item, e, parent) {
-      // console.log(item, `checked = ${e.target.checked}`)
-      item.checked = e.target.checked
-      item.noSave = false
-      // 父级
-      if (item.type == 2) {
-        item.children && item.children.map(d => {
-          d.checked = item.checked
-        })
-        item.indeterminate = false
-      }
-      // 子级
-      if (item.type == 3) {
-        // 父级节点
-        const hasCheckd = parent.children.filter(k => k.checked)
-        // 是否全选
-        parent.checked = hasCheckd.length == parent.children.length
-        parent.children.map(d => d.noSave = parent.checked)
-        // indeterminate为true,则为全选,false则为部分选择或者空
-        parent.indeterminate = ((hasCheckd.length < parent.children.length) && (hasCheckd.length != 0))
-      }
-      this.addrProvinceList = JSON.parse(JSON.stringify(this.addrProvinceList))
-    },
-    // 展开收起
-    expend (item) {
-      if (item.children && item.children.length == 0) {
-        item.isOpen = 1
-        this.getArea('city', item, 1)
-      } else {
-        item.isOpen = !item.isOpen
-      }
-    },
-    //  省/市/区
-    getArea (leve, item, openType) {
-      let params
-      if (leve == 'province') {
-        params = { type: '2' }
-      } else {
-        params = { parentId: item.areaSn, type: leve == 'city' ? '3' : '4' }
-      }
-      getArea(params).then(res => {
-        if (res.status == 200) {
-          if (leve == 'province') {
-            this.addrProvinceList = res.data || []
-            this.addrProvinceList.map(item => {
-              item.noSave = true
-              item.checked = false
-              item.children = []
-              item.indeterminate = false
-            })
-            // 编辑时获取已选数据
-            if (this.itemId) {
-              this.getChecked()
-            }
-            document.getElementById('treeNode').scrollTop = 0
-          } else if (leve == 'city') {
-            item.children = res.data || []
-            item.children.map(d => {
-              // 编辑时回显
-              if (this.itemId && openType == 0) {
-                d.checked = !!this.subareaAreaList.find(o => o.areaSn == d.areaSn)
-                d.noSave = false
-              } else {
-                d.checked = item.checked
-                d.noSave = true
-              }
-            })
-
-            // 首次加载子级
-            if (openType == 1) {
-              this.addrProvinceList = JSON.parse(JSON.stringify(this.addrProvinceList))
-            } else {
-              item.isOpen = 1
-              item.indeterminate = true
-            }
-          }
-        } else {
-          if (leve == 'province') {
-            this.addrProvinceList = []
-          } else if (leve == 'city') {
-            item.children = []
-            item.isOpen = 0
-          }
-        }
-      })
-    },
-    // 过滤数据
-    filterData (list) {
-      list.map(item => {
-        if (item.checked && !item.noSave) {
-          this.subareaAreaList.push({
-            areaSn: item.areaSn,
-            areaName: item.name,
-            areaType: item.type,
-            areaParentSn: item.parentId
-          })
-        } else {
-          if (item.children && item.children.length) {
-            this.filterData(item.children)
-          }
-        }
-      })
-    },
-    //  保存
-    handleSave () {
-      const _this = this
-      _this.$refs.ruleForm.validate(valid => {
-        if (valid) {
-          const formData = JSON.parse(JSON.stringify(_this.form))
-          this.subareaAreaList = []
-          this.filterData(this.addrProvinceList)
-          // console.log(this.subareaAreaList)
-          if (this.subareaAreaList.length == 0) {
-            this.$message.info('请先选择省份/市')
-            return
-          }
-          // 编辑
-          if (this.itemId) {
-            formData.subareaSn = this.itemId
-          }
-          formData.subareaAreaList = this.subareaAreaList
-          // console.log(formData, 'formData')
-          _this.spinning = true
-          subareaSaveSubareaArea(formData).then(res => {
-            if (res.status == 200) {
-              _this.$message.success(res.message)
-              _this.$emit('ok')
-              _this.isShow = false
-              _this.spinning = false
-            } else {
-              _this.spinning = false
-            }
-          })
-        } else {
-          return false
-        }
-      })
-    },
-    // 编辑
-    getChecked () {
-      subareaFindBySn({ sn: this.itemId }).then(res => {
-        // console.log(res.data)
-        this.form.subareaName = res.data.subareaName
-        this.subareaAreaList = res.data.subareaAreaList
-        this.form.subareaSn = res.data.subareaSn
-        this.form.id = res.data.id
-        // 回显数据
-        this.showChecked()
-      })
-    },
-    showChecked () {
-      // 省回显
-      this.addrProvinceList.map(item => {
-        item.checked = !!this.subareaAreaList.find(d => d.areaSn == item.areaSn)
-        item.noSave = false
-        item.indeterminate = false
-      })
-      // 市回显
-      const hasCity = this.nowData.subareaAreaList.filter(item => item.citySubareaAreaList && item.citySubareaAreaList.length)
-      // console.log(hasCity, 'hasCity.nowData')
-      hasCity.map(item => {
-        // 省
-        const pre = this.addrProvinceList.find(k => k.areaSn == item.areaSn)
-        // 获取子级
-        this.getArea('city', pre, 0)
-      })
-    }
-  },
-  watch: {
-    //  父页面传过来的弹框状态
-    openModal (newValue, oldValue) {
-      this.isShow = newValue
-    },
-    //  重定义的弹框状态
-    isShow (newValue, oldValue) {
-      if (!newValue) {
-        this.$emit('close')
-        this.form.subareaName = ''
-        this.form.subareaSn = ''
-        delete this.form.id
-      } else {
-        this.getArea('province')
-      }
-    }
-  }
-}
-</script>
-
-<style lang="less">
-  .marketingDivisionSetEdit-modal{
-    .ant-modal-body {
-      padding: 40px 40px 24px;
-    }
-    .btn-cont {
-      text-align: center;
-      margin: 35px 0 10px;
-    }
-    .tree-node{
-      height: 300px;
-      overflow: auto;
-      .tree-box{
-        .tree-parent{
-          display: flex;
-          align-items: center;
-          border-bottom: 1px solid #eee;
-          padding: 0 10px;
-          > span{
-            margin:0 5px;
-            &:first-child{
-              flex-grow: 1;
-            }
-            &:last-child{
-              cursor: pointer;
-            }
-          }
-        }
-        .tree-child{
-          padding: 10px 10px 10px 35px;
-          display: flex;
-          align-items: center;
-          flex-wrap:wrap ;
-          > div{
-            margin:0 5px;
-          }
-        }
-      }
-
-    }
-  }
-</style>

+ 185 - 0
src/views/dealerManagement/marketingDivisionSetNew/addAreaModal.vue

@@ -0,0 +1,185 @@
+<template>
+  <a-modal
+    centered
+    class="marketingDivisionSetEdit-modal"
+    :footer="null"
+    :maskClosable="false"
+    :title="modalTit"
+    v-model="isShow"
+    @cancel="isShow=false"
+    :width="500">
+    <!-- 表单 -->
+    <div>
+      <a-spin :spinning="spinning" tip="Loading...">
+        <a-form-model
+          id="marketingDivisionSetEdit-form"
+          ref="ruleForm"
+          :model="form"
+          :rules="rules"
+          :label-col="formItemLayout.labelCol"
+          :wrapper-col="formItemLayout.wrapperCol"
+        >
+          <a-form-model-item label="区域名称" prop="subareaName">
+            <a-input
+              id="marketingDivisionSetEdit-subareaName"
+              :maxLength="30"
+              v-model.trim="form.subareaName"
+              @change="filterEmpty"
+              placeholder="请输入区域名称(最多30个字符)"
+              allowClear />
+          </a-form-model-item>
+        </a-form-model>
+        <div class="btn-cont">
+          <a-button id="marketingDivisionSetEdit-modal-back" @click="isShow = false" >取消</a-button>
+          <a-button type="primary" style="margin-left: 15px;" id="marketingDivisionSetEdit-modal-save" @click="handleSave">保存</a-button>
+        </div>
+      </a-spin>
+    </div>
+  </a-modal>
+</template>
+
+<script>
+import { subareaSaveSubarea, subareaQuerySubarea } from '@/api/subarea'
+export default {
+  name: 'MarketingDivisionSetEditModal',
+  components: { },
+  props: {
+    openModal: { //  弹框显示状态
+      type: Boolean,
+      default: false
+    },
+    itemId: {
+      type: String,
+      default: ''
+    }
+  },
+  computed: {
+    modalTit () {
+      return (this.itemId ? '编辑' : '新增') + '区域'
+    }
+  },
+  data () {
+    return {
+      isShow: this.openModal, //  是否打开弹框
+      spinning: false,
+      formItemLayout: {
+        labelCol: { span: 4 },
+        wrapperCol: { span: 18 }
+      },
+      form: {
+        subareaName: '' // 区域名称
+      },
+      rules: {
+        subareaName: [
+          { required: true, message: '请输入区域名称', trigger: 'blur' }
+        ]
+      }
+    }
+  },
+  methods: {
+    filterEmpty () {
+      let str = this.form.subareaName
+      str = str.replace(/\ +/g, '')
+      str = str.replace(/[ ]/g, '')
+      str = str.replace(/[\r\n]/g, '')
+      this.form.subareaName = str
+    },
+    getDetail(){
+      this.spinning = true
+      subareaQuerySubarea({subareaSn: this.itemId}).then(res=>{
+        if(res.status == 200){
+          this.form.subareaName = res.data[0].subareaName
+        }
+        this.spinning = false
+      })
+    },
+    //  保存
+    handleSave () {
+      const _this = this
+      _this.$refs.ruleForm.validate(valid => {
+        if (valid) {
+          const formData = JSON.parse(JSON.stringify(_this.form))
+          // 编辑
+          if (this.itemId) {
+            formData.subareaSn = this.itemId
+          }
+          _this.spinning = true
+          subareaSaveSubarea(formData).then(res => {
+            if (res.status == 200) {
+              _this.$message.success(res.message)
+              _this.$emit('ok')
+              _this.isShow = false
+              _this.spinning = false
+            } else {
+              _this.spinning = false
+            }
+          })
+        } else {
+          return false
+        }
+      })
+    }
+  },
+  watch: {
+    //  父页面传过来的弹框状态
+    openModal (newValue, oldValue) {
+      this.isShow = newValue
+    },
+    //  重定义的弹框状态
+    isShow (newValue, oldValue) {
+      if (!newValue) {
+        this.$emit('close')
+        this.$refs.ruleForm.resetFields()
+        this.form.subareaName = ''
+      }else{
+        if(this.itemId){
+          this.getDetail()
+        }
+      }
+    }
+  }
+}
+</script>
+
+<style lang="less">
+  .marketingDivisionSetEdit-modal{
+    .ant-modal-body {
+      padding: 40px 40px 24px;
+    }
+    .btn-cont {
+      text-align: center;
+      margin: 35px 0 10px;
+    }
+    .tree-node{
+      height: 300px;
+      overflow: auto;
+      .tree-box{
+        .tree-parent{
+          display: flex;
+          align-items: center;
+          border-bottom: 1px solid #eee;
+          padding: 0 10px;
+          > span{
+            margin:0 5px;
+            &:first-child{
+              flex-grow: 1;
+            }
+            &:last-child{
+              cursor: pointer;
+            }
+          }
+        }
+        .tree-child{
+          padding: 10px 10px 10px 35px;
+          display: flex;
+          align-items: center;
+          flex-wrap:wrap ;
+          > div{
+            margin:0 5px;
+          }
+        }
+      }
+
+    }
+  }
+</style>

+ 177 - 0
src/views/dealerManagement/marketingDivisionSetNew/addZoneModal.vue

@@ -0,0 +1,177 @@
+<template>
+  <a-modal
+    centered
+    class="marketingDivisionSetEdit-modal"
+    :footer="null"
+    :maskClosable="false"
+    :title="modalTit"
+    v-model="isShow"
+    @cancel="isShow=false"
+    :width="500">
+    <!-- 表单 -->
+    <a-form-model
+      ref="ruleForm"
+      :model="form"
+      :rules="zoneRules"
+      :label-col="formItemLayout.labelCol"
+      :wrapper-col="formItemLayout.wrapperCol"
+    >
+      <a-form-model-item label="所属区域">
+        {{ parentData&&parentData.subareaName }}
+      </a-form-model-item>
+      <a-form-model-item label="分区名称" prop="subareaAreaName">
+        <a-input
+          :maxLength="30"
+          v-model.trim="form.subareaAreaName"
+          @change="filterEmpty"
+          placeholder="请输入分区名称(最多30个字符)"
+          allowClear />
+      </a-form-model-item>
+    </a-form-model>
+    <div class="btn-cont">
+      <a-button id="marketingDivisionSetEdit-modal-back" @click="isShow = false" >取消</a-button>
+      <a-button type="primary" style="margin-left: 15px;" id="marketingDivisionSetEdit-modal-save" @click="handleSave">保存</a-button>
+    </div>
+  </a-modal>
+</template>
+
+<script>
+import { subareaSaveSubareaArea, subareaQuerySubareaArea } from '@/api/subarea'
+export default {
+  name: 'MarketingDivisionSetEditModal',
+  components: { },
+  props: {
+    openModal: { //  弹框显示状态
+      type: Boolean,
+      default: false
+    },
+    parentData: {
+      type: Object,
+      default: function(){
+        return null
+      }
+    }
+  },
+  computed: {
+    modalTit () {
+      return (this.parentData&&this.parentData.subareaAreaSn ? '编辑' : '新增') + '分区'
+    }
+  },
+  data () {
+    return {
+      isShow: this.openModal, //  是否打开弹框
+      spinning: false,
+      formItemLayout: {
+        labelCol: { span: 4 },
+        wrapperCol: { span: 18 }
+      },
+      form: {
+        subareaAreaName: '' // 分区名称
+      },
+      zoneRules: {
+        subareaAreaName: [
+          { required: true, message: '请输入分区名称', trigger: 'blur' }
+        ]
+      }
+    }
+  },
+  methods: {
+    filterEmpty () {
+      let str = this.form.subareaAreaName
+      str = str.replace(/\ +/g, '')
+      str = str.replace(/[ ]/g, '')
+      str = str.replace(/[\r\n]/g, '')
+      this.form.subareaAreaName = str
+    },
+    //  保存
+    handleSave () {
+      const _this = this
+      _this.$refs.ruleForm.validate(valid => {
+        if (valid) {
+          const formData = JSON.parse(JSON.stringify(_this.form))
+          // 编辑
+          if (this.parentData.subareaAreaSn) {
+            formData.subareaAreaSn = this.parentData.subareaAreaSn
+          }
+          formData.subareaSn = this.parentData.subareaSn
+          // console.log(formData, 'formData')
+          _this.spinning = true
+          subareaSaveSubareaArea(formData).then(res => {
+            if (res.status == 200) {
+              _this.$message.success(res.message)
+              _this.$emit('ok')
+              _this.isShow = false
+              _this.spinning = false
+            } else {
+              _this.spinning = false
+            }
+          })
+        } else {
+          return false
+        }
+      })
+    }
+  },
+  watch: {
+    //  父页面传过来的弹框状态
+    openModal (newValue, oldValue) {
+      this.isShow = newValue
+    },
+    //  重定义的弹框状态
+    isShow (newValue, oldValue) {
+      if (!newValue) {
+        this.$emit('close')
+        this.$refs.ruleForm.resetFields()
+        this.form.subareaAreaName = ''
+      }else{
+        if (this.parentData.subareaAreaSn) {
+          this.form.subareaAreaName = this.parentData.subareaAreaName
+        }
+      }
+    }
+  }
+}
+</script>
+
+<style lang="less">
+  .marketingDivisionSetEdit-modal{
+    .ant-modal-body {
+      padding: 40px 40px 24px;
+    }
+    .btn-cont {
+      text-align: center;
+      margin: 35px 0 10px;
+    }
+    .tree-node{
+      height: 300px;
+      overflow: auto;
+      .tree-box{
+        .tree-parent{
+          display: flex;
+          align-items: center;
+          border-bottom: 1px solid #eee;
+          padding: 0 10px;
+          > span{
+            margin:0 5px;
+            &:first-child{
+              flex-grow: 1;
+            }
+            &:last-child{
+              cursor: pointer;
+            }
+          }
+        }
+        .tree-child{
+          padding: 10px 10px 10px 35px;
+          display: flex;
+          align-items: center;
+          flex-wrap:wrap ;
+          > div{
+            margin:0 5px;
+          }
+        }
+      }
+
+    }
+  }
+</style>

+ 84 - 55
src/views/dealerManagement/marketingDivisionSet/list.vue → src/views/dealerManagement/marketingDivisionSetNew/list.vue

@@ -1,9 +1,9 @@
 <template>
-  <a-card size="small" :bordered="false" class="marketingDivisionSetList-wrap">
+  <a-card size="small" :bordered="false" class="marketingDivisionSetNew-wrap">
     <a-spin :spinning="spinning" tip="Loading...">
       <!-- 操作按钮 -->
-      <div ref="tableSearch" class="table-operator" style="border: 0;">
-        <a-button id="marketingDivisionSetList-add" type="primary" v-if="$hasPermissions('B_marketingDivisionSet_add')" class="button-error" @click="handleEdit()">新增</a-button>
+      <div ref="tableSearch" class="table-operator" style="border: 0;text-align:right;">
+        <a-button id="marketingDivisionSetNew-add" type="primary" class="button-error" @click="addArea">+新增区域</a-button>
       </div>
       <!-- 列表 -->
       <s-table
@@ -18,106 +18,130 @@
         :scroll="{ y: tableHeight }"
         :defaultLoadData="false"
         bordered>
-        <!-- 市区 -->
-        <template slot="cityArea" slot-scope="text, record">
-          <div style="display: inline-block;margin-right: 15px;" v-for="item in record.subareaAreaList" :key="item.id">
-            {{ item.areaName }}
-            <span v-if="item.citySubareaAreaList">(</span>
-            <span style="color: #999;margin:0 3px;" v-for="area in item.citySubareaAreaList" :key="area.id">
-              {{ area.areaName }}
-            </span>
-            <span v-if="item.citySubareaAreaList">)</span>
-          </div>
+        <template slot="titles" slot-scope="text, record">
+          {{ record.type && record.type == 'root' ? record.subareaName : record.subareaAreaName }}
         </template>
         <!-- 操作 -->
         <template slot="action" slot-scope="text, record">
           <a-button
             size="small"
             type="link"
-            v-if="$hasPermissions('B_marketingDivisionSet_edit')"
+            class="button-info"
+            v-if="record.type && record.type == 'root'"
+            @click="addZone(record)"
+            id="marketingDivisionSetNew-edit-btn">新增分区</a-button>
+          <a-button
+            size="small"
+            type="link"
+            class="button-success"
+            v-else
+            @click="handleView(record)"
+            id="marketingDivisionSetNew-edit-btn">查看经销商</a-button>
+          <a-button
+            size="small"
+            type="link"
             class="button-info"
             @click="handleEdit(record)"
-            id="marketingDivisionSetList-edit-btn">编辑</a-button>
+            id="marketingDivisionSetNew-edit-btn">编辑</a-button>
           <a-button
             size="small"
             type="link"
-            v-if="$hasPermissions('B_marketingDivisionSet_del')"
             class="button-error"
             @click="handleDel(record)"
-            id="marketingDivisionSetList-del-btn">删除</a-button>
-          <span v-if="!$hasPermissions('B_marketingDivisionSet_edit') && !$hasPermissions('B_marketingDivisionSet_del')">--</span>
+            id="marketingDivisionSetNew-del-btn">删除</a-button>
         </template>
       </s-table>
     </a-spin>
-    <!-- 编辑分区 -->
-    <marketing-division-set-edit-modal
+    <!-- 新增区域 -->
+    <addAreaModal
       v-drag
-      :nowData="nowData"
-      :openModal="openModal"
+      :openModal="openAreaModal"
       :itemId="itemId"
       @ok="$refs.table.refresh()"
-      @close="closeModal" />
+      @close="openAreaModal=false"></addAreaModal>
+    <!-- 新增分区 -->
+    <addZoneModal
+      v-drag
+      :openModal="openZoneModal"
+      :parentData="parentData"
+      @ok="$refs.table.refresh()"
+      @close="openZoneModal=false"></addZoneModal>
+    <!-- 查看经销商 -->
+    <viewDealers
+      :showModal="openDealerModal"
+      :parentData="parentData"
+      @close="openDealerModal=false"></viewDealers>
   </a-card>
 </template>
 
 <script>
 import { commonMixin } from '@/utils/mixin'
 import { STable, VSelect } from '@/components'
-import marketingDivisionSetEditModal from './editModal.vue'
-import { subareaQueryIncludeAreaAll, subareaDeleteBySn } from '@/api/subarea'
+import addAreaModal from './addAreaModal.vue'
+import addZoneModal from './addZoneModal.vue'
+import viewDealers from './viewDealers.vue'
+import { subareaQueryAll, deleteSubareaBySn, deleteSubareaAreaBySn } from '@/api/subarea'
 export default {
-  name: 'MarketingDivisionSetList',
+  name: 'MarketingDivisionSetNew',
   mixins: [commonMixin],
-  components: { STable, VSelect, marketingDivisionSetEditModal },
+  components: { STable, VSelect, addAreaModal, addZoneModal, viewDealers },
   data () {
     return {
       spinning: false,
-      disabled: false, //  查询、重置按钮是否可操作
       tableHeight: 0,
+      openAreaModal: false,
+      openZoneModal: false,
+      openDealerModal: false,
       columns: [
-        { title: '序号', dataIndex: 'no', width: '5%', align: 'center' },
-        { title: '分区名', dataIndex: 'subareaName', width: '30%', align: 'center', customRender: function (text) { return text || '--' } },
-        { title: '省份/市', scopedSlots: { customRender: 'cityArea' }, align: 'left', width: '55%' },
-        { title: '操作', scopedSlots: { customRender: 'action' }, width: '10%', align: 'center' }
+        { title: '区域分区', scopedSlots: { customRender: 'titles' }, width: '70%', align: 'left' },
+        { title: '操作', scopedSlots: { customRender: 'action' }, width: '30%', align: 'center' }
       ],
       // 加载数据方法 必须为 Promise 对象
       loadData: parameter => {
-        this.disabled = true
         this.spinning = true
-        return subareaQueryIncludeAreaAll(parameter).then(res => {
+        return subareaQueryAll(parameter).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
+              data[i].children = data[i].subareaAreaList || undefined
+              data[i].type = 'root'
             }
-            this.disabled = false
           }
           this.spinning = false
           return data
         })
       },
-      openModal: false, //  编辑  弹框
-      nowData: null,
-      itemId: null //  当前产品id
+      itemId: null,
+      parentData: null
     }
   },
   methods: {
-    //  重置
-    resetSearchForm () {
-      this.$refs.table.refresh(true)
+    // 新增区域
+    addArea () {
+      this.itemId = null
+      this.openAreaModal = true
+    },
+    // 新增分区
+    addZone (row) {
+      console.log(row)
+      this.openZoneModal = true
+      this.parentData = row
     },
     // 删除
     handleDel (row) {
       const _this = this
       this.$confirm({
         title: '提示',
-        content: '确认要删除吗?',
+        content: '确定要删除吗?删除后相关用户权限自动解绑。',
         centered: true,
         onOk () {
           _this.spinning = true
-          subareaDeleteBySn({ sn: row.subareaSn }).then(res => {
+          const delFun = row.type && row.type == 'root' ? deleteSubareaBySn : deleteSubareaAreaBySn
+          const params = { sn: row.type && row.type == 'root' ? row.subareaSn : row.subareaAreaSn }
+          delFun(params).then(res => {
             if (res.status == 200) {
               _this.$message.success(res.message)
               _this.$refs.table.refresh()
@@ -131,15 +155,20 @@ export default {
     },
     //  编辑
     handleEdit (row) {
-      this.itemId = row && row.subareaSn ? row.subareaSn : null
-      this.nowData = row
-      this.openModal = true
+      // 大区
+      if(row.type && row.type == 'root'){
+        this.itemId = row && row.subareaSn ? row.subareaSn : null
+        this.openAreaModal = true
+      }else{
+        // 分区
+        this.parentData = row
+        this.openZoneModal = true
+      }
     },
-    //  关闭弹框
-    closeModal () {
-      this.itemId = null
-      this.nowData = null
-      this.openModal = false
+    // 查看经销商
+    handleView(row){
+      this.parentData = row
+      this.openDealerModal=true
     },
     pageInit () {
       const _this = this
@@ -149,7 +178,7 @@ export default {
     },
     setTableH () {
       const tableSearchH = this.$refs.tableSearch.offsetHeight
-      this.tableHeight = window.innerHeight - tableSearchH - 195
+      this.tableHeight = window.innerHeight - tableSearchH - 230
     }
   },
   watch: {
@@ -160,14 +189,14 @@ export default {
   mounted () {
     if (!this.$store.state.app.isNewTab) { // 页签刷新时调用
       this.pageInit()
-      this.resetSearchForm()
+      this.$refs.table.refresh()
     }
   },
   activated () {
     // 如果是新页签打开,则重置当前页面
     if (this.$store.state.app.isNewTab) {
       this.pageInit()
-      this.resetSearchForm()
+      this.$refs.table.refresh()
     }
     // 仅刷新列表,不重置页面
     if (this.$store.state.app.updateList) {
@@ -181,7 +210,7 @@ export default {
 }
 </script>
 <style lang="less">
-  .marketingDivisionSetList-wrap{
+  .marketingDivisionSetNew-wrap{
     height: 100%;
   }
 </style>

+ 298 - 0
src/views/dealerManagement/marketingDivisionSetNew/viewDealers.vue

@@ -0,0 +1,298 @@
+<template>
+  <div>
+    <a-drawer
+      title="查看经销商"
+      width="80%"
+      :zIndex="100"
+      :visible="visible"
+      :get-container="false"
+      class="viewsDealer"
+      :wrap-style="{ position: 'absolute' }"
+      @close="visible = false">
+      <a-spin :spinning="spinning" tip="Loading...">
+        <!-- 搜索条件 -->
+        <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">
+                <a-form-item label="经销商名称/别名">
+                  <a-input id="viewDealers-nameLike" v-model.trim="queryParam.dealer.nameLike" allowClear placeholder="请输入经销商名称/别名"/>
+                </a-form-item>
+              </a-col>
+              <a-col :md="8" :sm="24">
+                <a-form-item label="商户类型">
+                  <v-select code="DEALER_TYPE" id="viewDealers-dealerType" v-model="queryParam.dealer.dealerType" allowClear placeholder="请选择商户类型"></v-select>
+                </a-form-item>
+              </a-col>
+              <a-col :md="8" :sm="24">
+                <a-form-model-item label="商户级别">
+                  <v-select code="DEALER_LEVEL" id="viewDealers-dealerLevel" v-model="queryParam.dealer.dealerLevel" allowClear placeholder="请选择商户级别"></v-select>
+                </a-form-model-item>
+              </a-col>
+              <a-col :md="8" :sm="24">
+                <a-form-item label="审核状态">
+                  <v-select code="AUDIT_STATE" id="viewDealers-auditState" v-model="queryParam.dealer.auditState" allowClear placeholder="请选择审核状态"></v-select>
+                </a-form-item>
+              </a-col>
+              <a-col :md="8" :sm="24">
+              <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="6" :sm="24" style="margin-bottom: 10px;">
+                <a-button type="primary" @click="searchForm" :disabled="disabled" id="viewDealers-refresh">查询</a-button>
+                <a-button style="margin-left: 5px" @click="resetSearchForm" :disabled="disabled" id="viewDealers-reset">重置</a-button>
+              </a-col>
+            </a-row>
+          </a-form>
+        </div>
+        <div style="margin-top:200px;" v-if="flag">
+          <a-empty
+            :image="simpleImage"
+            :image-style="{
+              height: '60px',
+            }"
+          >
+            <span slot="description"> 暂无数据 </span>
+            <a-button type="primary" class="button-error" @click="openAddDealer=true"><a-icon type="plus" />立即绑定经销商</a-button>
+          </a-empty>
+        </div>
+        <div class="tableCon" v-else>
+          <div style="text-align:right;margin-bottom:10px;"><a-button type="primary" class="button-error" @click="openAddDealer=true"><a-icon type="plus" />绑定经销商</a-button></div>
+          <s-table
+            class="sTable"
+            ref="table"
+            size="small"
+            :rowKey="(record) => record.id"
+            :columns="columns"
+            :data="loadData"
+            :style="{ height: tableHeight+84.5+'px' }"
+            :scroll="{ y: tableHeight }"
+            bordered>
+            <template slot="action" slot-scope="text, record">
+            <a-button
+              size="small"
+              type="link"
+              class="button-error"
+              @click="handleDel(record)"
+              >删除</a-button>
+          </template>
+          </s-table>
+        </div>
+      </a-spin>
+    </a-drawer>
+
+    <!-- 绑定经销商 -->
+    <a-drawer
+      title="绑定经销商"
+      width="68%"
+      :zIndex="200"
+      :visible="openAddDealer"
+      :get-container="false"
+      :wrap-style="{ position: 'absolute' }"
+      class="deraw-bindDealer"
+      @close="openAddDealer = false">
+      <div class="dealerModalCon">
+        <chooseDealer ref="chooseDealer" v-if="openAddDealer" :parentData="parentData" pageType="viewDealers" @add="hanldAdd" @plAdd="hanldPlAdd"></chooseDealer>
+      </div>
+    </a-drawer>
+  </div>
+</template>
+
+<script>
+import { commonMixin } from '@/utils/mixin'
+import { STable, VSelect } from '@/components'
+import chooseDealer from '@/views/common/chooseDealer.vue'
+import AreaList from '@/views/common/areaList.js'
+import { Empty } from 'ant-design-vue'
+import { queryPageAreaDealer, batchBindDealer, bindDealer, deleteBindDealer } from '@/api/subarea'
+export default {
+  mixins: [commonMixin],
+  components: { STable, VSelect, chooseDealer, AreaList },
+  props: {
+    showModal: {
+      type: Boolean,
+      default: false
+    },
+    parentData: {
+      type: Object,
+      default: function(){
+        return null
+      }
+    }
+  },
+  watch: {
+    showModal (newValue, oldValue) {
+      this.visible = newValue
+    },
+    visible (newValue, oldValue) {
+      if (!newValue) {
+        this.$emit('close')
+        this.resetData()
+      }else{
+        this.pageInit()
+      }
+    },
+    '$store.state.app.winHeight' (newValue, oldValue) { //  窗口变更时,需同时更改表格高度
+      this.setTableH()
+    }
+  },
+  data () {
+    return {
+      simpleImage: Empty.PRESENTED_IMAGE_SIMPLE,
+      spinning: false,
+      visible: this.showModal,
+      openAddDealer: false,
+      flag: true,
+      queryParam: { //  查询条件
+        dealer:{
+          nameLike: '',
+          dealerType: null,
+          dealerLevel: null,
+          auditState: undefined,
+          provinceSn: undefined,
+          citySn: undefined,
+          districtSn: undefined
+        }
+      },
+      addrProvinceList: [], //  省下拉
+      addrCityList: [], //  市下拉
+      addrDistrictList: [], //  区下拉
+      disabled: false,
+      tableHeight: 0,
+      columns: [
+        { title: '经销商名称', dataIndex: 'dealer.dealerName', width: '30%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '商户别名', dataIndex: 'dealer.dealerAlias', width: '30%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '商户类型', dataIndex: 'dealer.dealerTypeDictValue', width: '10%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '商户级别', dataIndex: 'dealer.dealerLevelDictValue', width: '10%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '审核状态', dataIndex: 'dealer.auditStateDictValue', width: '10%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '操作', scopedSlots: { customRender: 'action' }, width: '10%', align: 'center' }
+      ],
+      loadData: parameter => {
+        this.disabled = true
+        this.spinning = true
+        return queryPageAreaDealer(Object.assign(parameter, this.queryParam, {subareaSn: this.parentData.subareaSn, subareaAreaSn: this.parentData.subareaAreaSn})).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
+            }
+          }
+          this.disabled = false
+          this.spinning = false
+          this.setTableH()
+          return data
+        })
+      },
+    }
+  },
+  methods: {
+    // 绑定
+    hanldAdd(row){
+      console.log(row)
+      bindDealer({subareaAreaSn: this.parentData.subareaAreaSn,dealerSn:row.dealerSn}).then(res => {
+        if(res.status == 200){
+          this.resetSearchForm()
+          this.$refs.chooseDealer.searchForm(false)
+        }
+        this.$refs.chooseDealer.searchForm
+      })
+    },
+    // 批量绑定
+    hanldPlAdd(rows){
+      console.log(rows)
+      batchBindDealer({subareaAreaSn: this.parentData.subareaAreaSn,dealerSnSet:rows}).then(res => {
+        if(res.status == 200){
+          this.resetSearchForm()
+          this.$refs.chooseDealer.searchForm(false)
+        }
+        this.$refs.chooseDealer.spinning = false
+      })
+    },
+    // 删除
+    handleDel(row){
+      const _this = this
+      this.$confirm({
+        title: '提示',
+        content: '确定要删除当前经销商绑定关系吗?',
+        centered: true,
+        onOk () {
+          _this.spinning = true
+          deleteBindDealer({sn: row.subareaAreaDealerSn}).then(res => {
+            if(res.status == 200){
+              _this.resetSearchForm()
+            }
+            _this.spinning = false
+          })
+        }
+      })
+    },
+    searchForm(){
+      if(this.flag){
+        this.hasData()
+      }else{
+        this.$refs.table.refresh(true)
+      }
+    },
+    resetData(){
+      this.queryParam = {
+          dealer:{
+            nameLike: '',
+            dealerType: null,
+            dealerLevel: null,
+            auditState: undefined,
+            provinceSn: undefined,
+            citySn: undefined,
+            districtSn: undefined
+          }
+        }
+      this.$refs.areaList.clearData()
+    },
+    resetSearchForm () {
+      if(this.flag){
+        this.hasData()
+      }else{
+        this.resetData()
+        this.$refs.table.refresh(true)
+      }
+    },
+    areaChange(val){
+      this.queryParam.dealer.provinceSn = val[0] ? val[0] : ''
+      this.queryParam.dealer.citySn = val[1] ? val[1] : ''
+      this.queryParam.dealer.districtSn = val[2] ? val[2] : ''
+    },
+   async hasData(){
+      const ret = await queryPageAreaDealer({pageNo:1,pageSize:10,subareaSn: this.parentData.subareaSn, subareaAreaSn: this.parentData.subareaAreaSn}).then(res => res.data)
+      this.flag = ret.count == 0
+    },
+    pageInit () {
+      const _this = this
+      this.$nextTick(() => { // 页面渲染完成后的回调
+        _this.setTableH()
+      })
+      this.flag = true
+      // 判断是已绑定数据
+      this.hasData()
+    },
+    setTableH () {
+      const tableSearchH = this.$refs.tableSearch.offsetHeight
+      this.tableHeight = window.innerHeight - tableSearchH - 290
+    }
+  },
+}
+</script>
+
+<style lang="less">
+.viewsDealer{
+  .ant-drawer-body{
+    padding:10px 20px 0;
+  }
+}
+.deraw-bindDealer {
+  .ant-drawer-body{
+    padding:10px 20px 0;
+  }
+}
+</style>

+ 17 - 12
src/views/dealerManagement/merchantInfoManagement/list.vue

@@ -7,7 +7,7 @@
           <a-row :gutter="15">
             <a-col :md="6" :sm="24">
               <a-form-item label="区域">
-                <subarea id="merchantInfoManagementList-subarea" v-model="queryParam.subareaSn"></subarea>
+                <subarea id="merchantInfoManagementList-subarea" ref="subarea" @change="subareaChange"></subarea>
               </a-form-item>
             </a-col>
             <a-col :md="6" :sm="24">
@@ -73,13 +73,6 @@
           <span v-if="$hasPermissions('B_merchantInfo_detail')" style="color: #ed1c24;cursor: pointer;" @click="handleDetail(record)">{{ record.dealerName }}</span>
           <span v-else>{{ record.dealerName }}</span>
         </template>
-        <!-- 区域 -->
-        <template slot="area" slot-scope="text, record">
-          <div v-if="record.subareaNameSet&&record.subareaNameSet.length!=0">
-            <span v-for="(item, index) in record.subareaNameSet" :key="index">{{ item }}{{ index+1 == record.subareaNameSet.length ? '' : ',' }}</span>
-          </div>
-          <span v-else>--</span>
-        </template>
         <!-- 操作 -->
         <template slot="action" slot-scope="text, record">
           <a-button size="small" type="link" class="button-warning" v-if="record.auditState == 'WAIT' && $hasPermissions('B_merchantInfo_audit')" @click="handleAudit(record)" >审核</a-button>
@@ -127,7 +120,10 @@ export default {
       queryParam: { //  查询条件
         nameLike: '', //  商户名称、别名
         dealerType: undefined, //  商户类型
-        subareaSn: undefined, //  区域
+        subareaArea:{
+          subareaSn: undefined, //  区域
+          subareaAreaSn: undefined, // 分区
+        },
         auditState: undefined, // 审核状态
         cooperateFlag: undefined //  合作状态
       },
@@ -138,7 +134,8 @@ export default {
       columns: [
         { title: '序号', dataIndex: 'no', width: '4%', align: 'center' },
         { title: '创建时间', dataIndex: 'createDate', width: '7%', align: 'center', customRender: function (text) { return text || '--' } },
-        { title: '区域', scopedSlots: { customRender: 'area' }, width: '7%', align: 'center' },
+        { title: '区域', dataIndex: 'subareaArea.subareaName', width: '5%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '分区', dataIndex: 'subareaArea.subareaAreaName', width: '5%', align: 'center', customRender: function (text) { return text || '--' } },
         { title: '商户名称', scopedSlots: { customRender: 'dealerName' }, width: '10%', align: 'center', ellipsis: true },
         { title: '商户别名', dataIndex: 'dealerAlias', width: '10%', align: 'center', customRender: function (text) { return text || '--' }, ellipsis: true },
         { title: '商户类型', dataIndex: 'dealerTypeDictValue', width: '7%', align: 'center', customRender: function (text) { return text || '--' } },
@@ -149,7 +146,7 @@ export default {
         { title: '审核状态', dataIndex: 'auditStateDictValue', width: '7%', align: 'center', customRender: function (text) { return text || '--' } },
         { title: '合作状态', dataIndex: 'cooperateFlagDictValue', width: '7%', align: 'center', customRender: function (text) { return text || '--' } },
         { title: '生效时间', dataIndex: 'cooperateEffectiveTime', width: '7%', align: 'center', customRender: function (text) { return text || '--' } },
-        { title: '操作', scopedSlots: { customRender: 'action' }, width: '15%', align: 'center' }
+        { title: '操作', scopedSlots: { customRender: 'action' }, width: '12%', align: 'center' }
       ],
       loading: false,
       // 加载数据方法 必须为 Promise 对象
@@ -179,15 +176,23 @@ export default {
     }
   },
   methods: {
+    subareaChange(val){
+      this.queryParam.subareaArea.subareaSn = val[0] ? val[0] : undefined
+      this.queryParam.subareaArea.subareaAreaSn = val[1] ? val[1] : undefined
+    },
     //  重置列表
     resetSearchForm () {
       this.queryParam = {
         nameLike: '', //  商户名称、别名
         dealerType: undefined, //  商户类型
-        subareaSn: undefined, //  区域
+        subareaArea:{
+          subareaSn: undefined,
+          subareaAreaSn: undefined
+        },
         auditState: undefined, // 审核状态
         cooperateFlag: undefined //  合作状态
       }
+      this.$refs.subarea.clearData()
       this.$refs.table.refresh(true)
     },
     // 刷新当前列表

+ 1 - 1
src/views/dealerManagement/merchantInfoManagement/permissionSetting.vue

@@ -102,7 +102,7 @@ export default {
         goodsCode: ''
       },
       rules: {
-        goodsType: [ { required: true, message: '请选择类型', trigger: 'change' } ]
+        // goodsType: [ { required: true, message: '请选择类型', trigger: 'change' } ]
       },
       disabled: false, //  查询、重置按钮是否可操作
       loading: false, //  表格加载中

+ 2 - 1
src/views/dealerManagement/rebateSettings/list.vue

@@ -23,7 +23,8 @@
         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 }"

+ 6 - 4
src/views/expenseManagement/expenseReimbursement/add.vue

@@ -18,7 +18,7 @@
             <a-descriptions-item label="申请部门">{{ detailData&&detailData.applyDepartmentName || '--' }}</a-descriptions-item>
             <a-descriptions-item label="费用类型">{{ detailData&&detailData.expenseTypeName || '--' }}<span v-if="detailData&&detailData.expenseType2">/{{ detailData&&detailData.expenseTypeName2 || '--' }}</span></a-descriptions-item>
             <a-descriptions-item label="费用发生月份">{{ detailData&&detailData.expenseDate?detailData.expenseDate.substring(0, 7) : '--' }}</a-descriptions-item>
-            <a-descriptions-item label="合计金额">{{ (detailData.applyExpenseTotal || detailData.applyExpenseTotal == 0) ? detailData.applyExpenseTotal+' 元' : '--' }}</a-descriptions-item>
+            <a-descriptions-item label="合计金额">{{ (detailData.applyExpenseTotal || detailData.applyExpenseTotal == 0) ? toThousands(detailData.applyExpenseTotal)+' 元' : '--' }}</a-descriptions-item>
             <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>
@@ -45,7 +45,7 @@
         </div>
         <a-alert type="info" style="margin-bottom:10px">
           <div slot="message">
-            共{{ total }}条费用明细,合计金额¥{{ detailData&&detailData.applyExpenseTotal||0 }}元
+            共{{ total }}条费用明细,合计金额{{ detailData&&detailData.applyExpenseTotal?toThousands(detailData.applyExpenseTotal) :'¥0.00' }}元
           </div>
         </a-alert>
         <!-- 列表 -->
@@ -159,6 +159,7 @@ export default {
   mixins: [commonMixin],
   components: { VSelect, Upload, STable, epenseDetailModal, productInfoModal, baseDataModal, ImportGuideModal, chooseDepartUserModal },
   data () {
+    const _this = this
     return {
       spinning: false,
       detailData: null,
@@ -197,10 +198,11 @@ export default {
         { title: '序号', dataIndex: 'no', width: '5%', align: 'center' },
         { title: '记账类型', dataIndex: 'accountTypeDictValue', align: 'center', width: '8%', customRender: function (text) { return text || '--' } },
         { title: '记账名称', dataIndex: 'accountName', scopedSlots: { customRender: 'jzname' }, align: 'center', width: '10%' },
-        { title: '所属区域', dataIndex: 'subareaNames', align: 'center', width: '8%', customRender: function (text) { return text || '--' } },
+        { title: '所属区域', dataIndex: 'subareaNames', width: '6%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '所属分区', dataIndex: 'subareaAreaName', width: '6%', align: 'center', customRender: function (text) { return text || '--' } },
         { title: '所属省份', dataIndex: 'provinceName', align: 'center', width: '8%', customRender: function (text) { return text || '--' } },
         { title: '所属城市', dataIndex: 'cityName', align: 'center', width: '8%', customRender: function (text) { return text || '--' } },
-        { title: '记账费用', dataIndex: 'expense', align: 'center', width: '10%', customRender: function (text) { return (text == 0 || text) ? text : '--' } },
+        { title: '记账费用', dataIndex: 'expense', align: 'center', width: '10%', customRender: function (text) { return (text == 0 || text) ? _this.toThousands(text) : '--' } },
         { title: '费用承担方', scopedSlots: { customRender: 'fycdf' }, align: 'center', width: '20%' },
         { title: '产品信息', scopedSlots: { customRender: 'cpxx' }, align: 'center', width: '15%' },
         { title: '备注', dataIndex: 'remarks', align: 'center', width: '10%', customRender: function (text) { return text || '--' } },

+ 32 - 0
src/views/expenseManagement/expenseReimbursement/chooseDepartUserModal.vue

@@ -56,6 +56,8 @@
 
 <script>
 import dingDepartUser from '@/views/common/dingDepartUser.js'
+import { getDefaultCofig } from '@/api/data.js'
+import { queryLastFinishDingUser } from '@/api/financeBook.js'
 export default {
   name: 'ChooseDepartUserModal',
   components: { dingDepartUser },
@@ -63,6 +65,10 @@ export default {
     openModal: { //  弹框显示状态
       type: Boolean,
       default: false
+    },
+    useDingDefUser: { // 是否使用最新一次申请人员
+      type: Boolean,
+      default: false
     }
   },
   data () {
@@ -100,6 +106,7 @@ export default {
       this.$refs.ruleForm.clearValidate()
     },
     getTreeVal (data) {
+      console.log(data)
       const ret = []
       data.map(item => {
         ret.push(item.value)
@@ -127,6 +134,29 @@ export default {
         }
       })
     },
+    getFormatUser(list){
+      const ret = []
+      list.map(item => {
+        ret.push({label: item.userName, value: item.userId||item.userid})
+      })
+      return ret
+    },
+    async getDefAudit(){
+      if(!this.useDingDefUser){
+        const data = await getDefaultCofig({code:'EXPENSE_ACCOUNT_DING_USER'}).then(res => res.data)
+        const ret = JSON.parse(data.value)
+        this.form.approvers = this.getFormatUser(ret.approvers)
+        this.form.ccList = this.getFormatUser(ret.ccList)
+      }else{
+        const data = await queryLastFinishDingUser().then(res => res.data)
+        if(data.approversTaskList){
+          this.form.approvers = this.getFormatUser(data.approversTaskList)
+        }
+        if(data.ccTaskList){
+          this.form.ccList = this.getFormatUser(data.ccTaskList)
+        }
+      }
+    },
     resetForm () {
       this.$nextTick(() => {
         this.$refs.ruleForm.resetFields()
@@ -147,6 +177,8 @@ export default {
       if (!newValue) {
         this.$emit('close')
         this.resetForm()
+      }else{
+        this.getDefAudit()
       }
     }
   }

+ 6 - 4
src/views/expenseManagement/expenseReimbursement/chooseImportModal.vue

@@ -129,8 +129,9 @@ export default {
         { title: '序号', dataIndex: 'no', width: '8%', align: 'center' },
         { title: '记账类型', dataIndex: 'importAccountType', width: '25%', align: 'center', customRender: function (text) { return text || '--' } },
         { title: '记账名称', dataIndex: 'importAccountName', width: '25%', align: 'center', customRender: function (text) { return text || '--' } },
-        { title: '所属区域', dataIndex: 'subareaNames', width: '14%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
-        { title: '所属省份', dataIndex: 'provinceName', width: '14%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
+        { title: '所属区域', dataIndex: 'subareaArea.subareaName', width: '5%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '所属分区', dataIndex: 'subareaArea.subareaAreaName', width: '5%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '所属省份', dataIndex: 'provinceName', width: '14%', align: 'center', customRender: function (text) { return text || '--' } },
         { title: '所属城市', dataIndex: 'cityName', width: '14%', align: 'center', customRender: function (text) { return text || '--' } },
         { title: '备注', dataIndex: 'remarks', width: '14%', align: 'center', customRender: function (text) { return text || '--' } },
         { title: '费用承担方', scopedSlots: { customRender: 'fycdf' }, align: 'center', width: '15%' },
@@ -141,8 +142,9 @@ export default {
         { title: '序号', dataIndex: 'no', width: '9%', align: 'center' },
         { title: '记账类型', dataIndex: 'importAccountType', width: '20%', align: 'center', customRender: function (text) { return text || '--' } },
         { title: '记账名称', dataIndex: 'importAccountName', width: '21%', align: 'center', customRender: function (text) { return text || '--' } },
-        { title: '所属区域', dataIndex: 'subareaNames', width: '10%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
-        { title: '所属省份', dataIndex: 'provinceName', width: '10%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
+        { title: '所属区域', dataIndex: 'subareaArea.subareaName', width: '5%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '所属分区', dataIndex: 'subareaArea.subareaAreaName', width: '5%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '所属省份', dataIndex: 'provinceName', width: '10%', align: 'center', customRender: function (text) { return text || '--' } },
         { title: '所属城市', dataIndex: 'cityName', width: '10%', align: 'center', customRender: function (text) { return text || '--' } },
         { title: '备注', dataIndex: 'remarks', width: '20%', align: 'center', customRender: function (text) { return text || '--' } },
         { title: '费用承担方', scopedSlots: { customRender: 'fycdf' }, align: 'center', width: '15%' },

+ 2 - 1
src/views/expenseManagement/expenseReimbursement/department.js

@@ -53,8 +53,9 @@ const Department = {
     },
     handleChange(value) {
       this.defaultVal = value;
+      const row = this.list.find(item => item.departmentSn == value)
       this.$emit('input', value);
-      this.$emit('change', value);
+      this.$emit('change', value, row);
     },
     getList () {
       departmentQueryList({}).then(res => {

+ 63 - 19
src/views/expenseManagement/expenseReimbursement/detail.vue

@@ -11,14 +11,14 @@
         <!-- 操作区,位于 title 行的行尾 -->
         <template slot="extra">
           <a-button
-            :disabled="!printContent"
+            :disabled="detailData==null"
             key="1"
             type="default"
             v-if="$hasPermissions('B_eRPrint')"
             id="expenseManagementDetail-print-btn"
             @click="handlePrint('preview')">打印预览</a-button>
           <a-button
-            :disabled="!printContent"
+            :disabled="detailData==null"
             key="2"
             type="primary"
             class="button-error"
@@ -37,8 +37,9 @@
               <a-descriptions-item label="申请部门">{{ detailData&&detailData.applyDepartmentName || '--' }}</a-descriptions-item>
               <a-descriptions-item label="费用类型">{{ detailData&&detailData.expenseTypeName || '--' }}<span v-if="detailData&&detailData.expenseType2">/{{ detailData&&detailData.expenseTypeName2 || '--' }}</span></a-descriptions-item>
               <a-descriptions-item label="费用发生月份">{{ detailData&&detailData.expenseDate?detailData.expenseDate.substring(0, 7) : '--' }}</a-descriptions-item>
-              <a-descriptions-item label="合计金额">{{ (detailData.applyExpenseTotal || detailData.applyExpenseTotal == 0) ? detailData.applyExpenseTotal+' 元' : '--' }}</a-descriptions-item>
+              <a-descriptions-item label="合计金额">{{ (detailData.applyExpenseTotal || detailData.applyExpenseTotal == 0) ? toThousands(detailData.applyExpenseTotal)+' 元' : '--' }}</a-descriptions-item>
               <a-descriptions-item label="状态">{{ detailData&&detailData.stateDictValue || '--' }}</a-descriptions-item>
+              <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="主题" :span="3">{{ detailData&&detailData.title || '--' }}</a-descriptions-item>
@@ -57,7 +58,7 @@
       <a-card size="small" :bordered="false" class="pages-wrap">
         <a-alert type="info" style="margin-bottom:10px">
           <div slot="message">
-            共<strong> {{ count }} </strong> 条费用明细,合计金额¥<strong v-if="detailData"> {{ (detailData.applyExpenseTotal || detailData.applyExpenseTotal == 0) ? detailData.applyExpenseTotal+' 元' : '--' }} </strong>
+            共<strong> {{ count }} </strong> 条费用明细,合计金额¥<strong v-if="detailData"> {{ (detailData.applyExpenseTotal || detailData.applyExpenseTotal == 0) ? toThousands(detailData.applyExpenseTotal)+' 元' : '--' }} </strong>
           </div>
         </a-alert>
         <!-- 列表 -->
@@ -98,28 +99,35 @@
       </a-card>
     </a-spin>
     <!-- 打印预览 -->
-    <previewModal :showModal="showModal" @close="showModal=false" @loaded="printLoaded" :detailSn="$route.params.sn" :detailData="detailData"></previewModal>
-    <iframe id="printfsqd" name="printfsqd" hidden></iframe>
+    <commonModal modalTit="费用报销单打印预览" width="700pt" okText="立即打印" :openModal="showTipModal" @cancel="showTipModal=false" @ok="$refs.printModal.prints()">
+      <previewModal v-if="printType=='preview'" ref="printModal" @printOk="printOk"></previewModal>
+    </commonModal>
+    <!-- 快捷打印 -->
+    <div style="height:0;overflow: hidden;">
+      <previewModal v-if="printType=='print'" ref="printModal" @printOk="printOk"></previewModal>
+    </div>
   </div>
 </template>
 
 <script>
 import { commonMixin } from '@/utils/mixin'
 import { STable } from '@/components'
-import { expenseAccountDetail, expenseAcctDetailFindList } from '@/api/expenseManagement'
+import commonModal from '@/views/common/commonModal.vue'
+import { expenseAccountDetail, expenseAcctDetailFindList, getProcessInstance, expenseAccountUpdateBatch } from '@/api/expenseManagement'
 import previewModal from './previewModal.vue'
-import { jGPrint } from '@/libs/JGPrint.js'
+
 export default {
   name: 'ExpenseReimbursementListDetail',
   mixins: [commonMixin],
-  components: { STable, previewModal },
+  components: { STable, previewModal, commonModal },
   data () {
+    let _this=this
     return {
       spinning: false,
       disabled: false,
-      showModal: false, // 打印弹窗初始状态
-      printContent: false,
       baseData: null,
+      showTipModal: false,
+      printType:'',
       count: 0,
       // 加载数据方法 必须为 Promise 对象
       loadData: parameter => {
@@ -143,10 +151,11 @@ export default {
         { title: '序号', dataIndex: 'no', width: '5%', align: 'center' },
         { title: '记账类型', dataIndex: 'accountTypeDictValue', align: 'center', width: '8%', customRender: function (text) { return text || '--' } },
         { title: '记账名称', dataIndex: 'accountName', scopedSlots: { customRender: 'jzname' }, align: 'center', width: '14%' },
-        { title: '所属区域', dataIndex: 'subareaNames', align: 'center', width: '8%', customRender: function (text) { return text || '--' } },
+        { title: '所属区域', dataIndex: 'subareaNames', width: '6%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '所属分区', dataIndex: 'subareaAreaName', width: '6%', align: 'center', customRender: function (text) { return text || '--' } },
         { title: '所属省份', dataIndex: 'provinceName', align: 'center', width: '8%', customRender: function (text) { return text || '--' } },
         { title: '所属城市', dataIndex: 'cityName', align: 'center', width: '8%', customRender: function (text) { return text || '--' } },
-        { title: '记账费用', dataIndex: 'expense', align: 'center', width: '10%', customRender: function (text) { return text || '--' } },
+        { title: '记账费用', dataIndex: 'expense', align: 'right', width: '10%', customRender: function (text) { return (text||text==0)?_this.toThousands(text):'--' } },
         { title: '费用承担方', scopedSlots: { customRender: 'fycdf' }, align: 'center', width: '15%' },
         { title: '产品信息', scopedSlots: { customRender: 'cpxx' }, align: 'center', width: '15%' },
         { title: '备注', dataIndex: 'remarks', align: 'center', width: '10%', customRender: function (text) { return text || '--' } }
@@ -162,9 +171,47 @@ export default {
       this.$router.push({ name: 'expenseReimbursementList' })
     },
     // 打印
-    handlePrint (type) {
-      const html = document.getElementById('printTest').innerHTML
-      jGPrint(html, type)
+    async handlePrint (type) {
+      this.printType = type
+      this.spinning = true
+      // 费用明细
+      const fyListData = await expenseAcctDetailFindList({ expenseAccountSn: this.$route.params.sn }).then(res => res.data)
+      // 审核明细,待提交状态不获取
+      const spListData = this.detailData.state != 'WAIT_SUBMIT' ? await getProcessInstance({ businessType: 'EXPENSES', businessSn: this.$route.params.sn }).then(res => res.data) : null
+      // 打印预览弹框
+      if(type == 'preview'){
+        this.showTipModal = true
+      } 
+      this.$nextTick(()=>{
+        this.$refs.printModal.setData([{
+          expenseInfo: this.detailData,
+          fyListData,
+          spListData:spListData||[]
+        }])
+        // 立即打印
+        if(type == 'print'){
+          setTimeout(()=>{
+            this.$refs.printModal.prints()
+          },500)
+        }
+        this.spinning = false
+      })
+    },
+    printOk(data){
+      if(data&&data.status == 200){
+        expenseAccountUpdateBatch([{
+            id: this.detailData.id,
+            printStatus:"PRINT"
+          }]).then(res => {
+          if(res.status == 200){
+             this.getDetail()
+          }
+          this.spinning = false
+          this.showTipModal = false
+        })
+      }else{
+        this.spinning = false
+      }
     },
     //  详情
     getDetail () {
@@ -180,9 +227,6 @@ export default {
           this.detailData = null
         }
       })
-    },
-    printLoaded (val) {
-      this.printContent = val
     }
   },
   mounted () {

+ 32 - 24
src/views/expenseManagement/expenseReimbursement/epenseDetailModal.vue

@@ -48,13 +48,17 @@
                 </a-form-model-item>
               </a-col>
               <a-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
-                <a-form-model-item label="所属区域" prop="subareaSn">
+                <a-form-model-item label="所属区域">
                   <subarea
                     id="epenseDetailModal-subarea"
                     ref="subareaBox"
+                    defValKey="name"
+                    :onlySubarea="true"
+                    :changeOnSelect="false"
                     @change="subareaChange"
+                    v-model="subareaList"
                     placeholder="请选择所属区域"
-                    v-model="form.subareaSnList"></subarea>
+                  ></subarea>
                 </a-form-model-item>
               </a-col>
               <a-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
@@ -146,12 +150,15 @@ export default {
         labelCol: { span: 4 },
         wrapperCol: { span: 16 }
       },
+      subareaList: [],
       form: {
         id: undefined,
         accountType: undefined, // 记帐类型
         accountNameSn: undefined, //  记账名称
-        subareaSnList: undefined, //  所属区域
-        subareaNameList: undefined,
+        subareaArea:{
+          subareaName: undefined, //  所属区域
+          subareaAreaName: undefined, // 分区
+        },
         provinceSn: undefined, // 省份
         provinceName: '',
         citySn: undefined, // 市
@@ -188,19 +195,19 @@ export default {
           this.form.citySn = row.citySn
           this.form.provinceName = row.provinceName
           this.form.cityName = row.cityName
-          if (row.subareaNameSet) {
-            const a = row.subareaNameSet.filter(item => item !== '中国')
-            this.form.subareaNameList = [a[0]]
-            this.form.subareaSnList = [this.$refs.subareaBox.getValByName(this.form.subareaNameList)[0]]
-          }
+          this.form.subareaArea.subareaName = row.subareaArea.subareaName
+          this.form.subareaArea.subareaAreaName = row.subareaArea.subareaAreaName
+          this.subareaList = [row.subareaArea.subareaName,row.subareaArea.subareaAreaName]
         } else {
           this.form.accountNameSn = ''
           this.form.provinceSn = ''
           this.form.citySn = ''
           this.form.provinceName = ''
           this.form.cityName = ''
-          this.form.subareaNameList = ''
-          this.form.subareaSnList = ''
+          this.form.subareaArea.subareaName = ''
+          this.form.subareaArea.subareaAreaName = ''
+          this.$refs.subareaBox.clearData()
+          this.subareaList = []
         }
       }
       this.$nextTick(() => {
@@ -208,11 +215,9 @@ export default {
       })
     },
     // 分区
-    subareaChange (v, row) {
-      const arr = []
-      console.log(v, row)
-      row.map(item => arr.push(item.subareaName))
-      this.form.subareaNameList = arr
+    subareaChange(val, row){
+      this.form.subareaArea.subareaName = val[0] ? val[0] : ''
+      this.form.subareaArea.subareaAreaName = val[1] ? val[1] : ''
     },
     // 省
     provinceChange (v, row) {
@@ -241,6 +246,9 @@ export default {
             if (res.data.accountType == 'CUSTOMER') {
               this.$refs.custList.setDufaultVal(res.data.accountName)
             }
+            this.form.subareaArea.subareaName = res.data.subareaNames||''
+            this.form.subareaArea.subareaAreaName = res.data.subareaAreaName||''
+            this.subareaList = res.data.subareaNames ?  [res.data.subareaNames,res.data.subareaAreaName] : undefined
           }, 200)
           this.spinning = false
         })
@@ -285,13 +293,9 @@ export default {
           form.citySn = form.citySn ? form.citySn : ''
           form.cityName = form.cityName ? form.cityName : ''
           form.expense = Math.abs(form.expense)
-          // 不是数组
-          if (!Array.isArray(form.subareaSnList)) {
-            form.subareaSnList = [form.subareaSnList]
-          }
+          
           console.log(form)
-          delete form.subareaNames
-          delete form.subareaSns
+        
           _this.spinning = true
           expenseAcctDetailSave(form).then(res => {
             if (res.status == 200) {
@@ -313,13 +317,16 @@ export default {
       this.$nextTick(() => {
         this.$refs.ruleForm.resetFields()
         this.$refs.city.clearData()
+        this.$refs.subareaBox.clearData()
       })
       this.form = {
         id: undefined,
         accountType: undefined, // 记帐类型
         accountNameSn: undefined, //  记账名称
-        subareaSnList: undefined, //  所属区域
-        subareaNameList: undefined,
+        subareaArea:{
+          subareaName: undefined, //  所属区域
+          subareaAreaName: undefined, // 分区
+        },
         provinceSn: undefined, // 省份
         provinceName: '',
         citySn: undefined, // 市
@@ -337,6 +344,7 @@ export default {
       this.form.cityName = ''
       this.form.expenseAccountSn = this.expenseAccountSn
       this.form.expenseAccountNo = this.expenseAccountNo
+      this.subareaList = []
     }
   },
   watch: {

+ 5 - 16
src/views/expenseManagement/expenseReimbursement/importGuideModal.vue

@@ -17,8 +17,10 @@
           <ul>
             <li>1) 导入的Excel文件中必须包含名为“记账类型”、“记账名称”、“费用承担方类型”、“费用承担方”、“费用承担金额”的列,且名称必须相同</li>
             <li>2) 其他列可根据实际情况填写,如果符合规则,系统会一起导入</li>
+            <li><a :href="filePath" style="margin: 5px 0 0 15px;display: block;">
+            <a-icon type="download" style="padding-right: 5px;" />下载导入模板
+          </a></li>
           </ul>
-          <a-button type="link" icon="download" style="padding: 0 0 0 23px;" :loading="exportLoading" @click="handleExport">下载导入模板</a-button>
         </div>
         <div class="explain-item">
           <div class="explain-tit">
@@ -87,7 +89,8 @@ export default {
       uploadParams: {
         savePathType: 'local'
       },
-      exportLoading: false
+      exportLoading: false,
+      filePath: location.protocol + '//' +location.host + '/templ/费用明细模板.xlsx'
     }
   },
   methods: {
@@ -125,20 +128,6 @@ export default {
     handleClose () {
       this.openImportModal = false
       this.isShow = false
-    },
-    // 下载模板
-    handleExport () {
-      this.exportLoading = true
-      setTimeout(() => {
-        this.exportLoading = false
-      }, 1000)
-      const link = document.createElement('a')
-      link.style.display = 'none'
-      link.href = 'https://jg-ocs.oss-cn-beijing.aliyuncs.com/templ/promo/expenseAccountDetailImport.xlsx?t=' + new Date().getTime()
-      link.setAttribute('download', '费用明细模板' + '.xlsx')
-      document.body.appendChild(link)
-      link.click()
-      document.body.removeChild(link)
     }
   },
   watch: {

+ 128 - 24
src/views/expenseManagement/expenseReimbursement/list.vue

@@ -10,12 +10,12 @@
                 <a-input id="salesManagementList-expenseAccountNo" v-model.trim="queryParam.expenseAccountNo" allowClear placeholder="请输入销售单号"/>
               </a-form-item>
             </a-col>
-            <a-col :md="6" :sm="24">
+            <a-col :md="4" :sm="24">
               <a-form-item label="申请人" :label-col="{ span:7 }" :wrapper-col="{ span:17}">
                 <employee style="width: 100%;" id="salesManagementList-Employee" v-model="queryParam.applyPersonSn"></employee>
               </a-form-item>
             </a-col>
-            <a-col :md="6" :sm="24">
+            <a-col :md="4" :sm="24">
               <a-form-item label="费用类型">
                 <expenseType
                   id="salesManagementList-expenseType"
@@ -26,8 +26,7 @@
                 ></expenseType>
               </a-form-item>
             </a-col>
-            <template v-if="advanced">
-              <a-col :md="6" :sm="24">
+            <a-col :md="4" :sm="24">
                 <a-form-item label="费用发生月份">
                   <a-month-picker
                     placeholder="请选择月份"
@@ -38,12 +37,24 @@
                     style="width: 100%;"/>
                 </a-form-item>
               </a-col>
+            <template v-if="advanced">
               <a-col :md="6" :sm="24">
                 <a-form-item label="主题">
                   <a-input id="salesManagementList-title" v-model.trim="queryParam.title" allowClear placeholder="请输入主题"/>
                 </a-form-item>
               </a-col>
-              <a-col :md="6" :sm="24">
+              <a-col :md="4" :sm="24">
+                <a-form-item label="打印状态">
+                  <v-select
+                    v-model="queryParam.printStatus"
+                    ref="printStatus"
+                    id="pushOrder-printStatus"
+                    code="EXPENSE_ACCOUNT_PRINT_STATUS"
+                    placeholder="请选择打印状态"
+                    allowClear></v-select>
+                </a-form-item>
+              </a-col>
+              <a-col :md="4" :sm="24">
                 <a-form-item label="状态">
                   <v-select
                     v-model="queryParam.state"
@@ -57,7 +68,7 @@
             </template>
             <a-col :md="6" :sm="24">
               <span class="table-page-search-submitButtons">
-                <a-button type="primary" :disabled="disabled" @click="$refs.table.refresh(true)">查询</a-button>
+                <a-button type="primary" :disabled="disabled" @click="searchForm">查询</a-button>
                 <a-button style="margin-left: 8px" :disabled="disabled" @click="resetSearchForm()">重置</a-button>
                 <a @click="advanced=!advanced" style="margin-left: 8px">
                   {{ advanced ? '收起' : '展开' }}
@@ -71,11 +82,17 @@
       <!-- 操作按钮 -->
       <div class="table-operator">
         <a-button type="primary" class="button-error" v-if="$hasPermissions('B_eRNew')" @click="handleEdit()">新增</a-button>
+        <a-button type="primary" :loading="spinning" @click="handlePlPrint()" ghost>批量打印</a-button>
+        <span style="margin-left: 8px">
+          <template v-if="rowSelectionInfo && rowSelectionInfo.selectedRowKeys.length>0">{{ `已选 ${rowSelectionInfo.selectedRowKeys.length} 项` }}</template>
+        </span>
       </div>
       <!-- 列表 -->
       <s-table
         class="sTable fixPagination"
         ref="table"
+        :row-selection="$hasPermissions('B_eRPrint')?{ columnWidth: '4%', getCheckboxProps: record => ({ props: { disabled: false } })}:null"
+        @rowSelection="rowSelectionFun"
         :style="{ height: tableHeight+70.5+'px' }"
         size="small"
         :rowKey="(record) => record.id"
@@ -143,6 +160,10 @@
     <verifyModal v-drag :openModal="openModal" :itemSn="itemSn" @close="openModal=false"></verifyModal>
     <!-- 新增 -->
     <baseDataModal :show="openBaseModal" @close="openBaseModal=false"></baseDataModal>
+    <!-- 打印预览 -->
+    <commonModal modalTit="费用报销单打印预览" width="700pt" okText="立即打印" :openModal="showTipModal" @cancel="showTipModal=false" @ok="$refs.printModal.prints()">
+      <previewModal v-if="showTipModal" ref="printModal" @printOk="printOk"></previewModal>
+    </commonModal>
   </a-card>
 </template>
 
@@ -154,21 +175,26 @@ import subarea from '@/views/common/subarea.js'
 import employee from './employee.js'
 import { STable, VSelect } from '@/components'
 import verifyModal from './verifyModal.vue'
+import previewModal from './previewModal.vue'
+import commonModal from '@/views/common/commonModal.vue'
 import expenseType from '@/views/common/expenseType.js'
-import { expenseAccountList, expenseAccountDelete, expenseAccountAgainEdit } from '@/api/expenseManagement'
+import { getBatchLastProcessInstance } from '@/api/financeBook'
+import { expenseAccountList, expenseAccountDelete, expenseAccountAgainEdit, expenseAcctDetailFindList, expenseAccountUpdateBatch } from '@/api/expenseManagement'
 import baseDataModal from './baseDataModal.vue'
 export default {
   name: 'ExpenseReimbursementList',
   mixins: [commonMixin],
-  components: { STable, VSelect, subarea, verifyModal, baseDataModal, employee, expenseType },
+  components: { STable, VSelect, subarea, verifyModal, baseDataModal, employee, expenseType, previewModal, commonModal },
   data () {
+    let _this=this
     return {
       locale,
       spinning: false,
-      advanced: false, // 高级搜索 展开/关闭
+      advanced: true, // 高级搜索 展开/关闭
       disabled: false, //  查询、重置按钮是否可操作
       openModal: false, // 审核进度弹框是否显示
       openBaseModal: false, // 基础信息新建
+      showTipModal: false,
       itemSn: '', // 费用单sn
       tableHeight: 0,
       expenseTypes: [],
@@ -179,8 +205,24 @@ export default {
         title: '', //  主题
         expenseType: undefined, // 费用类型
         expenseType2: undefined, // 费用类型2
+        printStatus: undefined, // 打印状态
         state: undefined // 状态
       },
+      columns: [
+        { title: '序号', dataIndex: 'no', width: '4%', align: 'center' },
+        { title: '费用单号', width: '8%', align: 'center', scopedSlots: { customRender: 'expenseAccountNo' } },
+        { title: '申请人', dataIndex: 'applyPersonName', width: '6%', align: 'center', customRender: function (text) { return text || '--' }, ellipsis: true },
+        { title: '申请部门', dataIndex: 'applyDepartmentName', width: '8%', align: 'left', customRender: function (text) { return text || '--' } },
+        { title: '费用类型', scopedSlots: { customRender: 'expenseType' }, width: '8%', align: 'left' },
+        { title: '费用发生月份', dataIndex: 'expenseDate', width: '6%', align: 'center', customRender: function (text) { return moment(text).format('YYYY年MM月') || '--' } },
+        { title: '主题', dataIndex: 'title', width: '10%', align: 'left', customRender: function (text) { return text || '--' }, ellipsis: true },
+        { title: '合计金额', dataIndex: 'applyExpenseTotal', width: '6%', align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } },
+        { title: '创建时间', dataIndex: 'createDate', width: '8%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '审核时间', dataIndex: 'finishDate', width: '8%', align: 'center', customRender: function (text, record) { return record.state == 'AUDIT_REJECT' || record.state == 'AUDIT_PASS' ? text : '--' } },
+        { title: '打印状态', dataIndex: 'printStatusDictValue', width: '6%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '状态', dataIndex: 'stateDictValue', width: '6%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '操作', scopedSlots: { customRender: 'action' }, width: '10%', align: 'center' }
+      ],
       // 加载数据方法 必须为 Promise 对象
       loadData: parameter => {
         this.disabled = true
@@ -198,6 +240,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].content = data.list[i].content ? data.list[i].content.replace(/\n+/, '\n').split('\n') : ''
             }
             this.disabled = false
           }
@@ -205,21 +248,78 @@ export default {
           return data
         })
       },
-      columns: [{ title: '序号', dataIndex: 'no', width: '4%', align: 'center' },
-        { title: '费用单号', width: '12%', align: 'center', scopedSlots: { customRender: 'expenseAccountNo' } },
-        { title: '申请人', dataIndex: 'applyPersonName', width: '8%', align: 'left', customRender: function (text) { return text || '--' }, ellipsis: true },
-        { title: '申请部门', dataIndex: 'applyDepartmentName', width: '8%', align: 'left', customRender: function (text) { return text || '--' } },
-        { title: '费用类型', scopedSlots: { customRender: 'expenseType' }, width: '6%', align: 'center' },
-        { title: '费用发生月份', dataIndex: 'expenseDate', width: '6%', align: 'center', customRender: function (text) { return moment(text).format('YYYY年MM月') || '--' } },
-        { title: '主题', dataIndex: 'title', width: '10%', align: 'left', customRender: function (text) { return text || '--' }, ellipsis: true },
-        { title: '合计金额', dataIndex: 'applyExpenseTotal', width: '8%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
-        { title: '创建时间', dataIndex: 'createDate', width: '8%', align: 'center', customRender: function (text) { return text || '--' } },
-        { title: '审核时间', dataIndex: 'finishDate', width: '8%', align: 'center', customRender: function (text, record) { return record.state == 'AUDIT_REJECT' || record.state == 'AUDIT_PASS' ? text : '--' } },
-        { title: '状态', dataIndex: 'stateDictValue', width: '6%', align: 'center', customRender: function (text) { return text || '--' } },
-        { title: '操作', scopedSlots: { customRender: 'action' }, width: '10%', align: 'center' }]
+      rowSelectionInfo: null // 批量选择的数据
     }
   },
   methods: {
+    // 表格选中项
+    rowSelectionFun (obj) {
+      this.rowSelectionInfo = obj || null
+    },
+    printOk(data){
+      if(data&&data.status == 200){
+        const rows = this.rowSelectionInfo && this.rowSelectionInfo.selectedRows || []
+        const ret = []
+        rows.map(item => {
+          ret.push({
+            id: item.id,
+            printStatus:"PRINT"
+          })
+        })
+        expenseAccountUpdateBatch(ret).then(res => {
+          if(res.status == 200){
+            this.$refs.table.refresh()
+            this.$refs.table.clearSelected()
+          }
+          this.spinning = false
+          this.showTipModal = false
+        })
+      }else{
+        this.spinning = false
+      }
+    },
+    // 批量打印
+    async handlePlPrint () {
+      const _this = this
+      const rows = _this.rowSelectionInfo && _this.rowSelectionInfo.selectedRows || []
+      const slen = rows.length
+      if (!_this.rowSelectionInfo || (_this.rowSelectionInfo && slen < 1)) {
+        _this.$message.warning('请在列表勾选后再进行批量操作!')
+        return false
+      }
+      this.spinning = true
+      const pageData = []
+      const businessSnList = []
+      
+      for(let i=0;i<rows.length;i++){
+        // 费用明细
+        const fyListData = await expenseAcctDetailFindList({ expenseAccountSn: rows[i].expenseAccountSn }).then(res => res.data)
+        // 审核明细,待提交状态不获取
+        if(rows[i].state != 'WAIT_SUBMIT'){
+          businessSnList.push(rows[i].expenseAccountSn)
+        }
+        pageData.push({
+          expenseInfo: rows[i],
+          fyListData: fyListData,
+          spListData: []
+        })
+      }
+      // 获取审核进度信息
+      const spListData = await getBatchLastProcessInstance({ 'businessType': 'EXPENSES', 'businessSnList': businessSnList }).then(res => res.data)
+      pageData.map(item => {
+        if(spListData){
+          const sp = spListData[item.expenseInfo.expenseAccountSn]
+          item.spListData = sp ? sp.taskVOList : []
+        }
+      })
+      console.log(pageData)
+      // 打开预览弹框
+      this.showTipModal = true
+      this.$nextTick(()=>{
+        this.$refs.printModal.setData(pageData)
+        this.spinning = false
+      })
+    },
     onChange (date, dateString) {
       this.queryParam.expenseDate = dateString
     },
@@ -291,6 +391,10 @@ export default {
         }
       })
     },
+    searchForm(){
+      this.$refs.table.refresh(true)
+      this.$refs.table.clearSelected()
+    },
     // 重置
     resetSearchForm () {
       this.queryParam = {
@@ -300,10 +404,11 @@ export default {
         expenseType: undefined, // 费用类型
         expenseType2: undefined, // 费用类型2
         state: undefined, // 状态
+        printStatus:undefined,
         applyPersonSn: undefined
       }
       this.expenseTypes = []
-      this.$refs.table.refresh(true)
+      this.searchForm()
     },
     pageInit () {
       const _this = this
@@ -313,7 +418,7 @@ export default {
     },
     setTableH () {
       const tableSearchH = this.$refs.tableSearch.offsetHeight
-      this.tableHeight = window.innerHeight - tableSearchH - 235
+      this.tableHeight = window.innerHeight - tableSearchH - 228
     }
   },
   watch: {
@@ -353,7 +458,6 @@ export default {
 <style lang="less">
   .salesManagementList-wrap{
     .sTable{
-      margin-top: 10px;
       .badge-con-t{
         .ant-badge-count{
           transform: scale(0.8);

+ 101 - 119
src/views/expenseManagement/expenseReimbursement/previewModal.vue

@@ -1,88 +1,90 @@
 <template>
-  <!-- <a-modal :footer="null" v-model="isShow" width="850px"> -->
-  <div class="container-print-view" style="width:100%;font-size: 12pt;position: fixed;font-family: auto;left:10000000px;padding:0;margin:0 auto;" id="printTest">
-    <p class="container-title" style="text-align: center;font-size: 24px;font-weight: 600;">箭冠汽配企业费用报销单</p>
-    <div class="container-info" style="width: 100%;border: 1px solid #000000;">
-      <div class="container-info-basics" v-if="expenseInfo">
+  <div class="container-print-view" 
+  style="width:100%;font-size: 12pt;height: 600px;overflow: auto;" 
+  >
+  <div class="expense-detail-print" style="width:564pt;margin:0 auto;" v-for="item in list" :key="item.expenseInfo.expenseAccountSn">
+    <div class="container-title" style="text-align: center;font-size: 24px;font-weight: 600;margin: 20px 0;">箭冠汽配企业费用报销单</div>
+    <div class="container-info" style="width:564pt;border: 1px solid #000000;">
+      <div class="container-info-basics" v-if="item.expenseInfo">
         <div class="basics-item" style="width: 100%;border-bottom: 1px solid #000000;padding:0;margin:0;">
-          <span style="display: inline-block;width: 50%;padding: 10px;border-right: 1px solid #000000;">申请人:{{ expenseInfo&&expenseInfo.applyPersonName?expenseInfo.applyPersonName:'' }}</span>
-          <span style="display: inline-block;border-right: none;padding: 10px;">申请部门:{{ expenseInfo&&expenseInfo.applyDepartmentName?expenseInfo.applyDepartmentName:'' }}</span>
+          <span style="display: inline-block;width: 50%;padding: 10px;border-right: 1px solid #000000;">申请人:{{ item.expenseInfo.applyPersonName?item.expenseInfo.applyPersonName:'' }}</span>
+          <span style="display: inline-block;border-right: none;padding: 10px;">申请部门:{{ item.expenseInfo.applyDepartmentName?item.expenseInfo.applyDepartmentName:'' }}</span>
         </div>
         <div class="basics-item" style="width: 100%;border-bottom: 1px solid #000000;padding:0;margin:0;">
-          <span style="display: inline-block;width: 50%;padding: 10px;border-right: 1px solid #000000;">费用类型:{{ expenseInfo&&expenseInfo.expenseTypeDictValue?expenseInfo.expenseTypeDictValue:'' }}</span>
-          <span style="display: inline-block;border-right: none;padding: 10px;">费用发生月份:{{ expenseInfo&&expenseInfo.expenseDate?expenseInfo.expenseDate.substring(0, 7):'' }}</span>
+          <span style="display: inline-block;width: 50%;padding: 10px;border-right: 1px solid #000000;">费用类型:{{ item.expenseInfo.expenseTypeName?item.expenseInfo.expenseTypeName:'' }}</span>
+          <span style="display: inline-block;border-right: none;padding: 10px;">费用发生月份:{{ item.expenseInfo.expenseDate?item.expenseInfo.expenseDate.substring(0, 7):'' }}</span>
         </div>
         <div class="basics-item" style="width: 100%;border-bottom: 1px solid #000000;padding:0;margin:0;">
-          <span style="display: inline-block;width: 50%;padding: 10px;border-right: 1px solid #000000;">费用单号:{{ expenseInfo&&expenseInfo.expenseAccountNo?expenseInfo.expenseAccountNo:'' }}{{ expenseInfo&&expenseInfo.stateDictValue?'('+expenseInfo.stateDictValue+')':'' }}</span>
-          <span style="display: inline-block;border-right: none;padding: 10px;">合计金额:{{ (expenseInfo&&expenseInfo.applyExpenseTotal ||expenseInfo&&expenseInfo.applyExpenseTotal==0)?expenseInfo.applyExpenseTotal+'元':'' }}</span>
+          <span style="display: inline-block;width: 50%;padding: 10px;border-right: 1px solid #000000;">费用单号:{{ item.expenseInfo.expenseAccountNo?item.expenseInfo.expenseAccountNo:'' }}{{ item.expenseInfo.stateDictValue?'('+item.expenseInfo.stateDictValue+')':'' }}</span>
+          <span style="display: inline-block;border-right: none;padding: 10px;">合计金额:{{ (item.expenseInfo.applyExpenseTotal ||item.expenseInfo.applyExpenseTotal==0)?item.expenseInfo.applyExpenseTotal+'元':'' }}</span>
         </div>
         <div class="basics-item" style="width: 100%;border-bottom: 1px solid #000000;overflow: hidden;">
           <div style="border-right: none;float: left;padding: 10px 0 10px 10px;">主题:</div>
-          <div style="padding: 10px;text-align: center;font-weight: bold;">
-            {{ expenseInfo&&expenseInfo.title?expenseInfo.title:'' }}
+          <div style="padding: 10px 10px 10px 50px;text-align: center;font-weight: bold;">
+            {{ item.expenseInfo.title?item.expenseInfo.title:'' }}
           </div>
         </div>
         <div class="basics-item" style="width: 100%;border-bottom: 1px solid #000000;padding:0;margin:0;">
-          <span style="display: inline-block;width: 50%;padding: 10px;border-right: 1px solid #000000;border-right: none;">详细说明:</span>
-          <div style="padding:0 20px 20px;">
-            <div v-for="(item,index) in expenseInfo.content" :key="index+'-content'">
-              {{ item || '--' }}
+          <span style="display: inline-block;width: 100%;padding: 10px 10px 5px;border-right: 1px solid #000000;border-right: none;">详细说明:</span>
+          <div style="padding:0 20px 10px 40px;">
+            <div v-for="(ditem,index) in item.expenseInfo.content" :key="index+'-content'">
+              {{ ditem || '--' }}
             </div>
           </div>
         </div>
       </div>
-      <div class="container-fytable" style="padding:0 10px;" v-if="fyListData">
-        <p class="table-title">费用明细:</p>
+      <div class="container-fytable" style="padding:0 10px;" v-if="item.fyListData">
+        <div class="table-title" style="padding: 10px 0;">费用明细:</div>
         <table
           border="1"
           cellspacing="0"
           cellpadding="0"
-          style="width: 100%;border-collapse: collapse;border: 1px solid black;font-size:10pt;text-align: center;"
+          style="width: 100%;border-collapse: collapse;font-size:10pt;text-align: center;"
           align="center">
           <thead>
             <tr>
-              <th style="padding:5px 10px;width:8%;">序号</th>
-              <th style="padding:5px 10px;width:26%;">记账方</th>
-              <!-- <th style="padding:5px 10px;width:15%;">区域/省/市</th> -->
-              <th style="padding:5px 10px;width:10%;">记账费用</th>
-              <th style="padding:5px 10px;width:26%;">费用承担方</th>
-              <th style="padding:5px 10px;width:20%;">产品信息</th>
+              <th style="padding:5px 0;width:6%;">序号</th>
+              <th style="padding:5px 0;width:22%;">记账方</th>
+              <!-- <th style="padding:5px 0;width:15%;">区域/省/市</th> -->
+              <th style="padding:5px 0;width:10%;">记账费用</th>
+              <th style="padding:5px 0;width:30%;">费用承担方</th>
+              <th style="padding:5px 0;width:22%;">产品信息</th>
             </tr>
           </thead>
           <tbody>
-            <tr v-for="(item,index) in fyListData" :key="index">
-              <td style="text-align: center;width:8%;">{{ index+1 }}</td>
-              <td style="text-align: left;width:26%;padding:5px 10px;">
-                <div>{{ item.accountTypeDictValue }}</div>
-                <div>{{ item.accountName||'' }}</div>
-                <div v-if="item.accountNameFnumber">({{ item.accountNameFnumber }})</div>
+            <tr v-for="(fyItem,index) in item.fyListData" :key="index">
+              <td style="text-align: center;width:6%;">{{ index+1 }}</td>
+              <td style="text-align: left;width:22%;padding:0 5px;">
+                <div>{{ fyItem.accountTypeDictValue }}</div>
+                <div>{{ fyItem.accountName||'' }}</div>
+                <div v-if="fyItem.accountNameFnumber">({{ fyItem.accountNameFnumber }})</div>
               </td>
-              <!-- <td style="text-align: left;width:15%;padding:5px 10px;">
-                <div>{{ item.subareaNames }}</div>
-                <div>{{ item.provinceName }}</div>
-                <div>{{ item.cityName }}</div>
+              <!-- <td style="text-align: left;width:15%;padding:5px 5px;">
+                <div>{{ fyItem.subareaNames }}</div>
+                <div>{{ fyItem.provinceName }}</div>
+                <div>{{ fyItem.cityName }}</div>
               </td> -->
-              <td style="text-align: right;width:10%;padding:5px 10px;">{{ item.expense||item.expense==0?item.expense.toFixed(2):'' }}</td>
-              <td style="text-align: left;width:26%;padding:5px 10px;vertical-align: top;">
-                <div v-for="(ditem,index) in item.detailSplitList" :key="ditem.id+'-'+index" style="padding: 3px 0;" >
+              <td style="text-align: right;width:10%;padding:0 5px;">{{ fyItem.expense||fyItem.expense==0?toThousands(fyItem.expense):'' }}</td>
+              <td style="text-align: left;width:30%;padding:0 5px;vertical-align: top;">
+                <div v-for="(ditem,index) in fyItem.detailSplitList" :key="ditem.id+'-'+index" style="padding: 3px 0;" >
                   {{ ditem.splitObjName }}
                   <span v-if="ditem.splitObjFnumber">({{ ditem.splitObjFnumber }})</span>
                   <span v-if="ditem.childDetailSplit&&ditem.childDetailSplit.splitObjName">/</span>
-                  {{ ditem.childDetailSplit?ditem.childDetailSplit.splitObjName:'' }}: {{ ditem.childDetailSplit?ditem.childDetailSplit.splitAmount:ditem.splitAmount }}
+                  {{ ditem.childDetailSplit?ditem.childDetailSplit.splitObjName:'' }}: {{ ditem.childDetailSplit?toThousands(ditem.childDetailSplit.splitAmount):toThousands(ditem.splitAmount) }}
                 </div>
               </td>
-              <td style="text-align: left;width:20%;padding:5px 10px;vertical-align: top;">
-                <div v-for="ditem in item.detailProductsList" :key="ditem.id" style="padding: 3px 0;">
-                  <div v-if="ditem.productCode">{{ ditem.productCode }}: {{ ditem.expense }}</div>
-                  <div v-else-if="ditem.productBrandName">{{ ditem.productBrandName }}<span v-if="ditem.productTypeShowName">/</span>{{ ditem.productTypeShowName }}: {{ ditem.expense.toFixed(2) }}</div>
-                  <div v-else>{{ ditem.productTypeShowName }}: {{ ditem.expense }}</div>
+              <td style="text-align: left;width:22%;padding:0 5px;vertical-align: top;">
+                <div v-for="ditem in fyItem.detailProductsList" :key="ditem.id" style="padding: 3px 0;">
+                  <div v-if="ditem.productCode">{{ ditem.productCode }}: {{ toThousands(ditem.expense) }}</div>
+                  <div v-else-if="ditem.productBrandName">{{ ditem.productBrandName }}<span v-if="ditem.productTypeShowName">/</span>{{ ditem.productTypeShowName }}: {{ toThousands(ditem.expense) }}</div>
+                  <div v-else>{{ ditem.productTypeShowName }}: {{ toThousands(ditem.expense) }}</div>
                 </div>
               </td>
             </tr>
           </tbody>
         </table>
       </div>
-      <div class="container-fytable" style="padding:0 10px 10px;" v-if="spListData">
+      <div class="container-fytable" style="padding:0 10px 5px;" v-if="item.spListData&&item.spListData.length">
         <p class="table-title">审批信息:</p>
         <table
           border="1"
@@ -92,98 +94,78 @@
           align="center">
           <thead>
             <tr style="height: 30px;padding: 5px;">
-              <th style="padding:5px 10px;width:8%;">序号</th>
-              <th style="padding:5px 10px;width:15%;text-align: left;">人员姓名</th>
-              <th style="padding:5px 10px;width:15%;">人员类型</th>
-              <th style="padding:5px 10px;width:10%;">状态</th>
-              <th style="padding:5px 10px;width:17%;">审批意见</th>
-              <th style="padding:5px 10px;width:15%;">附件</th>
-              <th style="padding:5px 10px;width:20%;">时间</th>
+              <th style="padding:5px 0;width:8%;">序号</th>
+              <th style="padding:5px 0;width:15%;">人员姓名</th>
+              <th style="padding:5px 0;width:15%;">人员类型</th>
+              <th style="padding:5px 0;width:10%;">状态</th>
+              <th style="padding:5px 0;width:17%;">审批意见</th>
+              <th style="padding:5px 0;width:15%;">附件</th>
+              <th style="padding:5px 0;width:20%;">时间</th>
             </tr>
           </thead>
           <tbody>
-            <tr style="height: 30px;padding: 5px;" v-for="(item,index) in spListData" :key="index">
-              <td style="padding:5px 10px;">{{ index+1||'' }}</td>
-              <td style="padding:5px 10px;text-align: left;">{{ item.userName||'' }}</td>
-              <td style="padding:5px 10px;">{{ item.userType||'' }}</td>
-              <td style="padding:5px 10px;">{{ item.state||'' }}</td>
-              <td style="padding:5px 10px;">{{ item.remark||'' }}</td>
-              <td style="padding:5px 10px;">{{ item.hasAttachments!= '0' ? '请在钉钉中查看附件内容' : '--' }}</td>
-              <td style="padding:5px 10px;">{{ item.date||'' }}</td>
+            <tr style="height: 30px;padding: 5px;" v-for="(spitem,index) in item.spListData" :key="index">
+              <td style="padding:5px 0;">{{ index+1||'' }}</td>
+              <td style="padding:5px 0;">{{ spitem.userName||'' }}</td>
+              <td style="padding:5px 0;">{{ spitem.userType||'' }}</td>
+              <td style="padding:5px 0;">{{ spitem.state||'' }}</td>
+              <td style="padding:5px 0;">{{ spitem.remark||'' }}</td>
+              <td style="padding:5px 0;">{{ spitem.hasAttachments!= '0' ? '请在钉钉中查看附件内容' : '--' }}</td>
+              <td style="padding:5px 0;">{{ spitem.date||'' }}</td>
             </tr></tbody>
         </table>
       </div>
+      <div class="container-fytable" style="padding:0 10px;" v-else>
+        <p class="table-title">审批信息:暂无</p>
+      </div>
     </div>
   </div>
-  <!-- </a-modal> -->
+  </div>
 </template>
 
 <script>
-import { expenseAcctDetailFindList, getProcessInstance } from '@/api/expenseManagement'
+import { commonMixin } from '@/utils/mixin'
+import { jGPlPrint, groupLessThan } from '@/libs/JGPrint.js'
+
 export default {
-  props: {
-    showModal: {
-      type: Boolean,
-      default: false
-    },
-    detailSn: {
-      type: [Number, String],
-      default: ''
-    },
-    detailData: {
-      type: Object,
-      default: () => { return null }
-    }
-  },
+  mixins: [commonMixin],
   data () {
     return {
-      isShow: this.showModal,
-      fyListData: [],
-      spListData: [],
-      expenseInfo: null
+      list: [],
+      printNums: []
     }
   },
   methods: {
-    pageInfo () {
-      this.getFyList()
-    },
-    getFyList () {
-      expenseAcctDetailFindList({ expenseAccountSn: this.detailSn }).then(res => {
-        if (res.status == 200) {
-          this.fyListData = res.data
-          if (this.expenseInfo.state != 'WAIT_SUBMIT') {
-            this.getSpList()
-          } else {
-            this.$emit('loaded', true)
-          }
-        } else {
-          this.fyListData = []
-          this.$emit('loaded', false)
-        }
-      })
+    setData (list) {
+      this.list = list
     },
-    getSpList () {
-      getProcessInstance({ businessType: 'EXPENSES', businessSn: this.detailSn }).then(res => {
-        if (res.status == 200) {
-          this.spListData = res.data
-        } else {
-          this.spListData = []
-        }
-        this.$emit('loaded', true)
-      })
-    }
-  },
-  // mounted () {
-  //   this.pageInfo()
-  // },
-  watch: {
-    detailData (nVal, oVal) {
-      if (nVal) {
-        this.expenseInfo = nVal
-        this.fyListData = []
-        this.spListData = []
-        this.pageInfo()
+    // 打印
+    prints(){
+      const _this = this
+      const html = document.getElementsByClassName('expense-detail-print')
+      const pageHeight = 535
+      const printCons = []
+      for (let i = 0; i < html.length; i++) {
+        const h = html[i].clientHeight
+        printCons.push({
+          h: h<=pageHeight?pageHeight:h,
+          t: '<div style="height:'+(h<=pageHeight?(pageHeight+'px'):'auto')+';border:1px solid #fff;">'+html[i].innerHTML+'</div>'
+        })
       }
+      // 排序从小到大
+      printCons.sort((a, b) => {
+        return a['h'] - b['h']
+      })
+      console.log(printCons)
+      // 自动排版
+      const htmlStr = groupLessThan(printCons, pageHeight*2)
+      this.$store.state.app.curActionPermission = 'B_eRPrint'
+      // html, type, callback, printLogParams
+      // console.log(htmlStr)
+      jGPlPrint(htmlStr.join('').split('&-NEWPAGE-&'), 'print', function (res) {
+        _this.$store.state.app.curActionPermission = ''
+        _this.$emit('printOk', res)
+      },null,'费用报销单')
     }
   }
 }

+ 22 - 9
src/views/expenseManagement/expenseReimbursementDetail/list.vue

@@ -75,7 +75,12 @@
               </a-col>
               <a-col :md="6" :sm="24">
                 <a-form-item label="所属区域">
-                  <subarea id="expenseReimbursementDetailList-subarea" v-model="queryParam.subareaSn"></subarea>
+                  <a-input id="expenseReimbursementDetailList-subarea" v-model.trim="queryParam.subareaArea.subareaName" allowClear placeholder="请输入所属区域"/>
+                </a-form-item>
+              </a-col>
+              <a-col :md="6" :sm="24">
+                <a-form-item label="所属分区">
+                  <a-input id="expenseReimbursementDetailList-subareaArea" v-model.trim="queryParam.subareaArea.subareaAreaName" allowClear placeholder="请输入所属分区"/>
                 </a-form-item>
               </a-col>
               <a-col :md="6" :sm="24">
@@ -155,7 +160,7 @@
         <div slot="message">
           <div>
             总单数:<strong>{{ countData&&(countData.detailNum || countData.detailNum==0) ? countData.detailNum : '--' }}</strong>;
-            总费用金额:<strong>{{ countData&&(countData.expense || countData.expense==0) ? countData.expense : '--' }}</strong>;
+            总费用金额:<strong>{{ countData&&(countData.expense || countData.expense==0) ? toThousands(countData.expense) : '--' }}</strong>;
           </div>
         </div>
       </a-alert>
@@ -199,6 +204,7 @@ export default {
   mixins: [commonMixin],
   components: { STable, VSelect, department, employee, subarea, rangeDate, Area, custList, supplier, expenseType },
   data () {
+    const _this = this
     return {
       spinning: false,
       advanced: true, // 高级搜索 展开/关闭
@@ -227,7 +233,10 @@ export default {
         splitObjType: undefined, // 费用承担方类型
         splitObjSn: undefined, //  费用承担方
         childSplitObjSn: undefined, // 费用承担人
-        subareaSn: undefined,
+        subareaArea:{
+          subareaName: '',
+          subareaAreaName: ''
+        },
         provinceName: '',
         cityName: '',
         provinceSn: undefined,
@@ -274,15 +283,16 @@ export default {
         { title: '记账类型', dataIndex: 'accountTypeDictValue', width: 90, align: 'center', customRender: function (text) { return text || '--' } },
         { title: '记账名称', dataIndex: 'accountName', width: 120, align: 'center', customRender: function (text) { return text || '--' }, ellipsis: true },
         { title: '财务编码', dataIndex: 'accountNameFnumber', width: 120, align: 'center', customRender: function (text) { return text || '--' } },
-        { title: '所属区域', dataIndex: 'subareaNames', width: 120, align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '所属区域', dataIndex: 'subareaArea.subareaName', width: 60, align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '所属分区', dataIndex: 'subareaArea.subareaAreaName', width: 60, align: 'center', customRender: function (text) { return text || '--' } },
         { title: '所属省份', dataIndex: 'provinceName', width: 90, align: 'center', customRender: function (text) { return text || '--' } },
         { title: '所属城市', dataIndex: 'cityName', width: 90, align: 'center', customRender: function (text) { return text || '--' } },
-        { title: '记账费用', dataIndex: 'expense', width: 120, align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
+        { title: '记账费用', dataIndex: 'expense', width: 120, align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } },
         { title: '费用承担方', dataIndex: 'splitObjName', width: 120, align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
         { title: '财务编码', dataIndex: 'splitObjFnumber', width: 120, align: 'center', customRender: function (text) { return text || '--' } },
-        { title: '费用承担金额', dataIndex: 'splitAmount', width: 120, align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
+        { title: '费用承担金额', dataIndex: 'splitAmount', width: 120, align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } },
         { title: '费用承担人', dataIndex: 'childSplitObjName', width: 120, align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
-        { title: '人员平摊费用', dataIndex: 'childSplitAmount', width: 120, align: 'center', customRender: function (text) { return text || '--' } }
+        { title: '人员平摊费用', dataIndex: 'childSplitAmount', width: 120, align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } }
       ]
     }
   },
@@ -363,7 +373,10 @@ export default {
         splitObjType: undefined, // 费用承担方类型
         splitObjSn: undefined, //  费用承担方
         childSplitObjSn: undefined, // 费用承担人
-        subareaSn: undefined,
+        subareaArea:{
+          subareaName: '',
+          subareaAreaName: ''
+        },
         provinceName: '',
         cityName: '',
         provinceSn: undefined,
@@ -380,7 +393,7 @@ export default {
     },
     setTableH () {
       const tableSearchH = this.$refs.tableSearch.offsetHeight
-      this.tableHeight = window.innerHeight - tableSearchH - 215
+      this.tableHeight = window.innerHeight - tableSearchH - 226
     }
   },
   watch: {

+ 4 - 1
src/views/financialManagement/allocateReturnConfirmation/detailModal.vue

@@ -9,7 +9,7 @@
     @cancel="isShow=false"
     :width="960">
     <div>
-      <detail :outBizSn="itemSn" pageType="modal" ref="detail"></detail>
+      <detail :outBizSn="itemSn" :showPrice="$hasPermissions('M_allocateReturnConfirmationDetail_salesPrice')" pageType="modal" ref="detail"></detail>
       <div class="btn-cont"><a-button id="confirmationDetail-modal-back" @click="isShow = false">返回列表</a-button></div>
     </div>
   </a-modal>
@@ -46,6 +46,9 @@ export default {
     isShow (newValue, oldValue) {
       if (!newValue) {
         this.$emit('close')
+        this.$store.state.app.curActionPermission = ''
+      }else{
+        this.$store.state.app.curActionPermission = 'M_allocateReturnConfirmationDetail'
       }
     }
   }

+ 5 - 5
src/views/financialManagement/allocateReturnConfirmation/list.vue

@@ -148,14 +148,14 @@ export default {
         { title: '退货总数量', dataIndex: 'totalQty', width: '7%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
         { title: '坏件数量', dataIndex: 'totalBadQty', width: '7%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
         { title: '返库数量', dataIndex: 'totalBackStockQty', width: '7%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
-        { title: '退货总金额', dataIndex: 'totalPrice', width: '7%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
+        // { title: '退货总金额', dataIndex: 'totalPrice', width: '7%', align: 'right', customRender: text => ((text || text == 0) ? this.toThousands(text) : '--') },
         { title: '确认时间', dataIndex: 'financeAuditTime', width: '11%', align: 'center', customRender: function (text) { return text || '--' } },
         { title: '状态', dataIndex: 'stateDictValue', width: '6%', align: 'center', customRender: function (text) { return text || '--' } },
         { title: '操作', scopedSlots: { customRender: 'action' }, width: '8%', align: 'center' }
       ]
-      // if (this.$hasPermissions('B_isShowPrice')) { //  售价权限
-      //   arr.splice(8, 0, { title: '退货总金额', dataIndex: 'totalPrice', width: '7%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } })
-      // }
+      if (this.$hasPermissions('M_allocateReturnConfirmationList_salesPrice')) { //  售价权限
+        arr.splice(8, 0, { title: '退货总金额', dataIndex: 'totalPrice', width: '7%', align: 'right', customRender: text => ((text || text == 0) ? this.toThousands(text) : '--') })
+      }
       return arr
     }
   },
@@ -230,7 +230,7 @@ export default {
     },
     setTableH () {
       const tableSearchH = this.$refs.tableSearch.offsetHeight
-      this.tableHeight = window.innerHeight - tableSearchH - 195
+      this.tableHeight = window.innerHeight - tableSearchH - 200
     }
   },
   watch: {

+ 14 - 9
src/views/financialManagement/collectionDetailStatic/invoiceModal.vue

@@ -6,7 +6,7 @@
     :maskClosable="false"
     :footer="null"
     @cancel="cancel"
-    width="40%">
+    width="600px">
     <a-spin :spinning="spinning" tip="Loading...">
       <a-form-model
         id="chooseCustom-form"
@@ -26,6 +26,9 @@
             v-model="form.invoiceDate"/>
           <div style="color:#999">如果没有开票,则不填写即可</div>
         </a-form-model-item>
+        <!-- <a-form-model-item label="备注:">
+          <a-textarea id="noticeEdit-remarks" rows="4" v-model="form.remarks" :maxlenght="100" placeholder="请输入备注(最多100字符)"></a-textarea>
+        </a-form-model-item> -->
         <a-form-model-item :wrapper-col="{ span: 12, offset: 6 }" style="text-align: center;margin-top: 50px;">
           <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">确定
@@ -64,14 +67,15 @@ export default {
           span: 6
         },
         wrapperCol: {
-          span: 18
+          span: 14
         }
       },
       form: {
         no: undefined,
         payerName: undefined,
         invoiceDate: undefined,
-        bookDetailSn: ''
+        bookDetailSn: '',
+        remarks: ''
       }
     }
   },
@@ -138,23 +142,24 @@ export default {
       const _this = this
       const invoiceDate = moment(this.form.invoiceDate).format('YYYY-MM-DD')
       const ajax_form = {
-        'bookDetailSn': this.form.bookDetailSn,
-        'invoiceDate': this.form.invoiceDate ? invoiceDate : ''
+        bookDetailSn: this.form.bookDetailSn,
+        invoiceDate: this.form.invoiceDate ? invoiceDate : '',
+        remarks: this.form.remarks
       }
       _this.spinning = true
       updateDetailInvoiceDate(ajax_form).then(res => {
         if (res.status == 200) {
           _this.$message.success(res.message)
-          _this.cancel()
+          _this.cancel(1)
           _this.spinning = false
         } else {
           _this.spinning = false
         }
       })
     },
-    cancel () {
+    cancel (flag) {
       this.opened = false
-      this.$emit('cancel')
+      this.$emit('cancel',flag)
       this.$refs.ruleForm.resetFields()
     }
   },
@@ -162,7 +167,7 @@ export default {
     show (newValue, oldValue) {
       this.opened = newValue
       if (!newValue) {
-        this.cancel()
+        this.$refs.ruleForm.resetFields()
       } else {
         this.form = this.info
       }

이 변경점에서 너무 많은 파일들이 변경되어 몇몇 파일들은 표시되지 않았습니다.