Переглянути джерело

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

李磊 3 роки тому
батько
коміт
95367eac27
100 змінених файлів з 4698 додано та 500 видалено
  1. 1 1
      public/version.json
  2. 11 0
      src/api/allocateBill.js
  3. 139 0
      src/api/allocateReturn.js
  4. 58 0
      src/api/reportData.js
  5. 2 1
      src/components/MultiTab/MultiTab.vue
  6. 17 0
      src/components/Select/index.js
  7. 5 9
      src/components/Table/index.js
  8. 6 1
      src/components/UploadFile/index.vue
  9. 22 119
      src/components/index.less
  10. 334 104
      src/config/router.config.js
  11. 2 1
      src/layouts/BasicLayout.vue
  12. 3 1
      src/layouts/BlankLayout.vue
  13. 17 78
      src/layouts/PageView.vue
  14. 454 0
      src/libs/tools.js
  15. 3 1
      src/store/getters.js
  16. 7 2
      src/store/modules/app.js
  17. 77 1
      src/utils/mixin.js
  18. 58 9
      src/utils/request.js
  19. 2 0
      src/views/Home.vue
  20. 13 1
      src/views/allocationManagement/transferOut/basicInfoModal.vue
  21. 3 1
      src/views/allocationManagement/transferOut/chooseImportModal.vue
  22. 7 3
      src/views/allocationManagement/transferOut/detail.vue
  23. 16 9
      src/views/allocationManagement/transferOut/edit.vue
  24. 3 1
      src/views/allocationManagement/transferOut/importGuideModal.vue
  25. 5 1
      src/views/allocationManagement/transferOut/list.vue
  26. 2 2
      src/views/allocationManagement/transferOut/printModal.vue
  27. 243 0
      src/views/allocationManagement/transferReturn/basicInfoModal.vue
  28. 298 0
      src/views/allocationManagement/transferReturn/check.vue
  29. 190 0
      src/views/allocationManagement/transferReturn/chooseImportModal.vue
  30. 190 0
      src/views/allocationManagement/transferReturn/detail.vue
  31. 590 0
      src/views/allocationManagement/transferReturn/edit.vue
  32. 578 0
      src/views/allocationManagement/transferReturn/editGrp.vue
  33. 221 0
      src/views/allocationManagement/transferReturn/importGuideModal.vue
  34. 344 0
      src/views/allocationManagement/transferReturn/list.vue
  35. 100 0
      src/views/allocationManagement/transferReturn/print.vue
  36. 2 0
      src/views/basicData/transferTypeManagement/editModal.vue
  37. 3 0
      src/views/basicData/transferTypeManagement/list.vue
  38. 2 0
      src/views/basicData/warehouse/editModal.vue
  39. 3 0
      src/views/basicData/warehouse/list.vue
  40. 2 0
      src/views/basicData/warehouse/storingLocation/editModal.vue
  41. 3 0
      src/views/basicData/warehouse/storingLocation/list.vue
  42. 25 20
      src/views/bnSetting/menu/adminMenus.vue
  43. 1 1
      src/views/common/auditModal.vue
  44. 3 0
      src/views/dataExport/exportCheck/list.vue
  45. 3 0
      src/views/dataExport/exportSales/list.vue
  46. 2 0
      src/views/dealerManagement/dealerAccountManagement/editModal.vue
  47. 3 0
      src/views/dealerManagement/dealerAccountManagement/list.vue
  48. 2 0
      src/views/dealerManagement/dealerRelationshipBinding/associateModal.vue
  49. 3 0
      src/views/dealerManagement/dealerRelationshipBinding/list.vue
  50. 3 0
      src/views/dealerManagement/marketingDivisionSet/list.vue
  51. 69 72
      src/views/dealerManagement/merchantInfoManagement/detailModal.vue
  52. 7 1
      src/views/dealerManagement/merchantInfoManagement/edit.vue
  53. 4 1
      src/views/dealerManagement/merchantInfoManagement/list.vue
  54. 3 0
      src/views/dealerManagement/merchantInfoManagement/permissionSetting.vue
  55. 2 0
      src/views/dealerManagement/merchantInfoManagement/updateCooperate.vue
  56. 2 0
      src/views/dealerManagement/merchantInfoManagement/updateDealerLevel.vue
  57. 2 0
      src/views/dealerManagement/rebateSettings/associateModal.vue
  58. 3 0
      src/views/dealerManagement/rebateSettings/list.vue
  59. 12 9
      src/views/dowloadFile/list.vue
  60. 3 0
      src/views/expenseManagement/expenseReimbursement/add.vue
  61. 3 1
      src/views/expenseManagement/expenseReimbursement/detail.vue
  62. 25 16
      src/views/expenseManagement/expenseReimbursement/list.vue
  63. 3 1
      src/views/expenseManagement/expenseReimbursementDetail/list.vue
  64. 65 0
      src/views/financialManagement/allocateReturnConfirmation/detailModal.vue
  65. 281 0
      src/views/financialManagement/allocateReturnConfirmation/list.vue
  66. 6 2
      src/views/financialManagement/financialCollection/list.vue
  67. 3 0
      src/views/financialManagement/inventoryConfirmation/detail.vue
  68. 5 1
      src/views/financialManagement/inventoryConfirmation/list.vue
  69. 5 1
      src/views/financialManagement/returnConfirmation/list.vue
  70. 7 3
      src/views/financialManagement/warehousingConfirmation/list.vue
  71. 5 3
      src/views/inventoryManagement/intelligentReplenishment/detailModal.vue
  72. 3 0
      src/views/inventoryManagement/intelligentReplenishment/edit.vue
  73. 3 0
      src/views/inventoryManagement/intelligentReplenishment/import.vue
  74. 3 0
      src/views/inventoryManagement/intelligentReplenishment/list.vue
  75. 3 0
      src/views/inventoryManagement/intelligentReplenishment/productRange.vue
  76. 3 0
      src/views/inventoryManagement/intelligentReplenishment/set.vue
  77. 3 0
      src/views/inventoryManagement/inventoryCheck/detail.vue
  78. 4 1
      src/views/inventoryManagement/inventoryCheck/list.vue
  79. 3 1
      src/views/inventoryManagement/inventoryQuery/list.vue
  80. 3 0
      src/views/inventoryManagement/inventoryQuery/warehouseDetail.vue
  81. 4 1
      src/views/inventoryManagement/inventoryWarning/list.vue
  82. 3 0
      src/views/inventoryManagement/makeInventory/check.vue
  83. 3 0
      src/views/inventoryManagement/makeInventory/list.vue
  84. 3 0
      src/views/inventoryManagement/supervisionDisk/check.vue
  85. 3 0
      src/views/inventoryManagement/supervisionDisk/list.vue
  86. 3 1
      src/views/power/OperateJournal/OperateJournal.vue
  87. 3 1
      src/views/power/dataDictionary/dataDictionary.vue
  88. 2 0
      src/views/power/menu/menu.vue
  89. 2 0
      src/views/power/role/menuModal.vue
  90. 8 2
      src/views/power/role/roleList.vue
  91. 10 5
      src/views/power/role/roleModal.vue
  92. 2 0
      src/views/power/user/updateAreal.vue
  93. 3 1
      src/views/power/user/userList.vue
  94. 2 0
      src/views/power/user/userModal.vue
  95. 5 6
      src/views/productManagement/newProduct/detail.vue
  96. 3 0
      src/views/productManagement/newProduct/list.vue
  97. 7 3
      src/views/productManagement/newProduct/modal.vue
  98. 3 0
      src/views/productManagement/priceChangeRecord/list.vue
  99. 2 0
      src/views/productManagement/productBrand/editModal.vue
  100. 3 0
      src/views/productManagement/productBrand/list.vue

+ 1 - 1
public/version.json

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

+ 11 - 0
src/api/allocateBill.js

@@ -11,6 +11,17 @@ export const allocateBillList = (params) => {
     method: 'post'
   })
 }
+// 调拨退货抓单-选产品列表
+export const allocDetailQueryPageForReturn = (params) => {
+  const url = `/allocateBill/detail/queryPageForReturn/${params.pageNo}/${params.pageSize}`
+  delete params.pageNo
+  delete params.pageSize
+  return axios({
+    url: url,
+    data: params,
+    method: 'post'
+  })
+}
 // 调拨管理  新增
 export const allocateBillSave = params => {
   return axios({

+ 139 - 0
src/api/allocateReturn.js

@@ -0,0 +1,139 @@
+import { axios } from '@/utils/request'
+// 审核调拨退货
+export const allocateReturnAudit = params => {
+  return axios({
+    url: '/allocateReturn/audit',
+    data: params,
+    method: 'post'
+  })
+}
+// 删除调拨退货
+export const allocateReturnDelete = params => {
+  return axios({
+    url: `/allocateReturn/delete/${params.allocateReturnSn}`,
+    data: params,
+    method: 'post'
+  })
+}
+// 品检 提交
+export const allocateReturnCheckSubmit = params => {
+  return axios({
+    url: '/allocateReturn/check',
+    data: params,
+    method: 'post'
+  })
+}
+// 财务审核调拨退货
+export const allocateReturnFinanceAudit = params => {
+  return axios({
+    url: '/allocateReturn/financeAudit',
+    data: params,
+    method: 'post'
+  })
+}
+// 导出excel
+export const allocateReturnExcel = params => {
+  return axios({
+    url: `/allocateReturn/excel/${params.allocateReturnSn}`,
+    method: 'get',
+    responseType: 'blob'
+  })
+}
+// 打印
+export const allocateReturnPrint = params => {
+  return axios({
+    url: `/allocateReturn/print/${params.allocateReturnSn}`,
+    method: 'get',
+    responseType: 'blob'
+  })
+}
+// 查询调拨退货详情
+export const allocateReturnQueryBySn = params => {
+  return axios({
+    url: `/allocateReturn/queryBySn/${params.allocateReturnSn}`,
+    method: 'get'
+  })
+}
+// 分页查询调拨退货列表
+export const allocateReturnQueryPage = (params) => {
+  const url = `/allocateReturn/queryPage/${params.pageNo}/${params.pageSize}`
+  delete params.pageNo
+  delete params.pageSize
+  return axios({
+    url: url,
+    data: params,
+    method: 'post'
+  })
+}
+// 分页查询调拨退货确认列表
+export const allocateReturnQueryConfirmPage = (params) => {
+  const url = `/allocateReturn/queryConfirmPage/${params.pageNo}/${params.pageSize}`
+  delete params.pageNo
+  delete params.pageSize
+  return axios({
+    url: url,
+    data: params,
+    method: 'post'
+  })
+}
+// 保存调拨退货
+export const allocateReturnSave = params => {
+  return axios({
+    url: '/allocateReturn/save',
+    data: params,
+    method: 'post'
+  })
+}
+// 提交调拨退货
+export const allocateReturnSubmit = params => {
+  return axios({
+    url: '/allocateReturn/submit',
+    data: params,
+    method: 'post'
+  })
+}
+
+// 调拨退货品检批量处理
+export const allocateReturnCheck = params => {
+  return axios({
+    url: `/allocReturnDetail/check/${params.allocateReturnSn}/${params.allocateCheckType}`,
+    data: params.list,
+    method: 'post'
+  })
+}
+
+// 删除调拨退货明细
+export const allocReturnDetailDelete = params => {
+  return axios({
+    url: '/allocReturnDetail/delete',
+    data: params,
+    method: 'post'
+  })
+}
+// 新增调拨退货明细
+export const allocReturnDetailInsert = params => {
+  return axios({
+    url: '/allocReturnDetail/insert',
+    data: params,
+    method: 'post'
+  })
+}
+// 分页查询调拨退货明细列表
+export const allocReturnDetailQueryPage = (params) => {
+  const url = `/allocReturnDetail/queryPage/${params.pageNo}/${params.pageSize}`
+  delete params.pageNo
+  delete params.pageSize
+  return axios({
+    url: url,
+    data: params,
+    method: 'post'
+  })
+}
+// 更新调拨退货明细
+export const allocReturnDetailUpdate = params => {
+  return axios({
+    url: '/allocReturnDetail/update',
+    data: params,
+    method: 'post'
+  })
+}

+ 58 - 0
src/api/reportData.js

@@ -462,3 +462,61 @@ export const realReportSalesBySubAreaExport = (params) => {
     responseType: 'blob'
   })
 }
+// 调拨退货单报表
+export const allocateReturnReportQueryPage = (params) => {
+  const url = `/report/allocateReturnReport/queryPage/${params.pageNo}/${params.pageSize}`
+  delete params.pageNo
+  delete params.pageSize
+  return axios({
+    url: url,
+    data: params,
+    method: 'post'
+  })
+}
+// 查询调拨退货统计信息
+export const allocateReturnReportQueryCount = (params) => {
+  const url = `/report/allocateReturnReport/queryCount`
+  return axios({
+    url: url,
+    data: params,
+    method: 'post'
+  })
+}
+// 导出
+export const allocateReturnReportExport = (params) => {
+  return axios({
+    url: '/report/allocateReturnReport/exportExcel',
+    data: params,
+    method: 'post',
+    responseType: 'blob'
+  })
+}
+// 分页查询调拨退货明细报表
+export const allocateReturnReportDetailQueryPage = (params) => {
+  const url = `/report/allocateReturnReport/detail/queryPage/${params.pageNo}/${params.pageSize}`
+  delete params.pageNo
+  delete params.pageSize
+  return axios({
+    url: url,
+    data: params,
+    method: 'post'
+  })
+}
+// 查询调拨退货明细统计信息
+export const allocateReturnReportDetailQueryCount = (params) => {
+  const url = `/report/allocateReturnReport/detail/queryCount`
+  return axios({
+    url: url,
+    data: params,
+    method: 'post'
+  })
+}
+// 导出
+export const allocateReturnReportDetailExport = (params) => {
+  return axios({
+    url: '/report/allocateReturnReport/detail/exportExcel',
+    data: params,
+    method: 'post',
+    responseType: 'blob'
+  })
+}

+ 2 - 1
src/components/MultiTab/MultiTab.vue

@@ -1,6 +1,5 @@
 <script>
 import events from './events'
-
 export default {
   name: 'MultiTab',
   data () {
@@ -65,6 +64,7 @@ export default {
       if (!this.tabsList.includes(this.activeKey)) {
         this.selectedLastPath()
       }
+      this.$store.state.app.closeTabPages.push(targetKey)
     },
     selectedLastPath () {
       this.activeKey = this.tabsList[this.tabsList.length - 1]
@@ -202,6 +202,7 @@ export default {
           } else {
             // this.$message.info('您当前打开窗口太多,请关闭一些,窗口不能超过' + this.maxTabNums + '个')
             const _this = this
+            this.$store.state.app.closeTabPages.push(newVal.name)
             this.$warning({
               title: '提示',
               content: '您当前打开窗口太多,请关闭一些,窗口不能超过' + this.maxTabNums + '个',

+ 17 - 0
src/components/Select/index.js

@@ -83,6 +83,23 @@ export default {
         this.$emit('change', obj, _.find(this.dataList, ['code', obj]))
       }
     }
+    const radioOn = {
+      change: obj => {
+        this.$emit('input', obj.target.value)
+        this.$emit('change', obj.target.value, _.find(this.dataList, ['code', obj.target.value]))
+      }
+    }
+    if(this.showType === 'radio'){
+      return (
+        <a-radio-group vModel={props.value} {...{ props, on: radioOn }} >
+          {
+            this.dataList.map(item => {
+              return (<a-radio value={item.code} key={item.code}>{item['dispName']}</a-radio>)
+            })
+          }
+        </a-radio-group>
+      )
+    }
     if (this.showType === 'tabs') {
       return (
         <a-tabs vModel={props.value} {...{ props, on: on }}>

+ 5 - 9
src/components/Table/index.js

@@ -277,17 +277,13 @@ export default {
       if (selected) { //  选择
         this.selectedRows = [...this.selectedRows, ...changeRows]
       } else { //  取消
-        const arrId = []
+        const selectedRowsArr = []
         this.selectedRows.map((item, index) => {
-          this.selectedRows.map((subItem, ind) => {
-            if (item[this.rowKeyName] == subItem[this.rowKeyName]) {
-              arrId.push(index)
-            }
-          })
-        })
-        arrId.map((item, index) => {
-          _this.selectedRows = _this.selectedRows.slice(item, item + 1)
+          if(!changeRows.find(subItem => subItem[this.rowKeyName] == item[this.rowKeyName])){
+            selectedRowsArr.push(item)
+          }
         })
+        this.selectedRows = selectedRowsArr
       }
       this.updateSelect()
     },

+ 6 - 1
src/components/UploadFile/index.vue

@@ -142,7 +142,12 @@ export default {
       if (this.listType == 'text') {
         return
       }
-      this.previewImage = file.url || file.thumbUrl
+      console.log(file)
+      if (file.response.status == 200) {
+        this.previewImage = file.response.data
+      } else {
+        this.previewImage = file.url || file.thumbUrl
+      }
       this.previewVisible = true
     },
     handleRemove (file) {

+ 22 - 119
src/components/index.less

@@ -19,7 +19,7 @@
 }
 
 /* 扩展ant design pro按钮组件颜色 */
-.ant-btn-primary.button-primary {
+.ant-btn-primary.button-primary,.ant-btn-primary.button-info,.ant-btn-primary.button-warning,.ant-btn-primary.button-geekblue,.ant-btn-primary.button-purple {
   background-color: #39f;
   border-color: #39f;
   margin: 0 5px;
@@ -35,25 +35,9 @@
   }
 }
  
-.ant-btn-primary.button-info {
-  background-color: #2db7f5;
-  border-color: #2db7f5;
-  margin: 0 5px;
-  font-size: 12px;
-  &:hover, &:focus {
-    background-color: #32c8f5;
-    border-color: #32c8f5;
-  }
- 
-  &:active, &.active {
-    background-color: #27a3d8;
-    border-color: #27a3d8;
-  }
-}
- 
 .ant-btn-primary.button-success {
-  background-color: #0c6;
-  border-color: #0c6;
+  background-color: #11b116;
+  border-color: #00af54;
   margin: 0 5px;
   font-size: 12px;
   &:hover, &:focus {
@@ -67,22 +51,6 @@
   }
 }
  
-.ant-btn-primary.button-warning {
-  background-color: #f90;
-  border-color: #f90;
-  margin: 0 5px;
-  font-size: 12px;
-  &:hover, &:focus {
-    background-color: #ffb60a;
-    border-color: #ffb60a;
-  }
- 
-  &:active, &.active {
-    background-color: #dd8500;
-    border-color: #dd8500;
-  }
-}
- 
 .ant-btn-primary.button-error {
   background-color: #f30;
   border-color: #f30;
@@ -98,38 +66,6 @@
     border-color: #d62a00;
   }
 }
- 
-.ant-btn-primary.button-geekblue {
-  background-color: #2F54EB;
-  border-color: #2F54EB;
-  margin: 0 5px;
-  font-size: 12px;
-  &:hover, &:focus {
-    background-color: #1d39c4;
-    border-color: #1d39c4;
-  }
- 
-  &:active, &.active {
-    background-color: #597ef7;
-    border-color: #597ef7;
-  }
-}
- 
-.ant-btn-primary.button-purple {
-  background-color: #722ED1;
-  border-color: #722ED1;
-  margin: 0 5px;
-  font-size: 12px;
-  &:hover, &:focus {
-    background-color: #9254de;
-    border-color: #9254de;
-  }
- 
-  &:active, &.active {
-    background-color: #531dab;
-    border-color: #531dab;
-  }
-}
 .ant-btn-primary.button-grey {
   background-color: #82848a;
   border-color: #82848a;
@@ -147,38 +83,15 @@
 }
 
 // btn-link
-.ant-btn-link.button-default {
-  color: #1b1b1b;
-  &:hover, &:focus {
-    color: #66696d;
-  }
- 
-  &:active, &.active {
-    color: #8e8f91;
-  }
-}
-.ant-btn-link.button-primary {
+.ant-btn-link.button-primary,.ant-btn-link.button-info,.ant-btn-link.button-warning,.ant-btn-link.button-purple,.ant-btn-link.button-geekblue {
   color: #39f;
   &:hover, &:focus {
-    color: #52a6fb;
+    color: #48b7fb;
   }
- 
   &:active, &.active {
     color: #3d80bf;
   }
 }
- 
-.ant-btn-link.button-info {
-  color: #2db7f5;
-  &:hover, &:focus {
-    color: #32c8f5;
-  }
- 
-  &:active, &.active {
-    color: #27a3d8;
-  }
-}
- 
 .ant-btn-link.button-success {
   color: #0c6;
   &:hover, &:focus {
@@ -189,18 +102,6 @@
     color: #00af57;
   }
 }
- 
-.ant-btn-link.button-warning {
-  color: #aa6a02;
-  &:hover, &:focus {
-    color: #c68d07;
-  }
- 
-  &:active, &.active {
-    color: #dd8500;
-  }
-}
- 
 .ant-btn-link.button-error {
   color: #f30;
   &:hover, &:focus {
@@ -211,36 +112,35 @@
     color: #d62a00;
   }
 }
- 
-.ant-btn-link.button-geekblue {
-  color: #2F54EB;
+.ant-btn-link.button-default {
+  color: #1b1b1b;
   &:hover, &:focus {
-    color: #1d39c4;
+    color: #66696d;
   }
  
   &:active, &.active {
-    color: #597ef7;
+    color: #8e8f91;
   }
 }
- 
-.ant-btn-link.button-purple {
-  color: #722ED1;
+.ant-btn-link.button-grey {
+  color: #82848a;
   &:hover, &:focus {
-    color: #9254de;
+    color: #909399;
   }
  
   &:active, &.active {
-    color: #531dab;
+    color: #c8c9cc;
   }
 }
-.ant-btn-link.button-grey {
-  color: #82848a;
+.link-bule{
+  color: #39f;
+  cursor: pointer;
   &:hover, &:focus {
-    color: #909399;
+    color: #4bc3fb;
+    text-decoration: underline;
   }
- 
   &:active, &.active {
-    color: #c8c9cc;
+    color: #3d80bf;
   }
 }
 // 查询条件样式
@@ -379,6 +279,9 @@
   }
   .ant-table-small > .ant-table-content .ant-table-body{
     margin: 0;
+    .ant-btn{
+      user-select: auto !important;
+    }
   }
   input:disabled{
     opacity: 1!important;

+ 334 - 104
src/config/router.config.js

@@ -27,48 +27,84 @@ export const asyncRouterMap = [
           icon: 'home'
         },
         hideChildrenInMenu: true,
-        children: [{
-          path: '/home',
-          name: 'home',
-          component: () => import(/* webpackChunkName: "home" */ '@/views/Home'),
-          meta: {
-            title: '首页',
-            icon: 'home',
-            hide: true
+        children: [
+          {
+            path: '/home',
+            name: 'home',
+            redirect: '/home',
+            component: BlankLayout,
+            meta: {
+              title: '首页',
+              icon: 'home',
+              hidden: true
+            },
+            hideChildrenInMenu: true,
+            children: [
+              {
+                path: '/home',
+                name: 'home',
+                component: () => import(/* webpackChunkName: "home" */ '@/views/Home'),
+                meta: {
+                  title: '首页',
+                  icon: 'home',
+                  hidden: true
+                }
+              },
+              {
+                path: '/changePwd',
+                name: 'changePwd',
+                component: () => import(/* webpackChunkName: "home" */ '@/views/user/ChangePwd'),
+                meta: {
+                  title: '修改密码',
+                  icon: 'home'
+                },
+                hidden: true
+              },
+              {
+                path: '/notice',
+                name: 'notice',
+                component: () => import(/* webpackChunkName: "home" */ '@/views/setting/notice/list'),
+                meta: {
+                  title: '公告',
+                  icon: 'bell'
+                },
+                hidden: true
+              },
+              {
+                path: '/dowloadFile',
+                name: 'dowloadFile',
+                component: () => import(/* webpackChunkName: "home" */ '@/views/dowloadFile/list'),
+                meta: {
+                  title: '下载中心',
+                  icon: 'bell'
+                },
+                hidden: true
+              },
+              // 新品列表
+              {
+                path: '/newProduct/list/:onlineFalg',
+                name: 'newProductList',
+                component: () => import(/* webpackChunkName: "home" */ '@/views/productManagement/newProduct/list'),
+                meta: {
+                  title: '新品信息',
+                  icon: 'home'
+                },
+                hidden: true
+              },
+              // 产品详情
+              {
+                path: '/viewProduct/:sn',
+                name: 'viewProduct',
+                component: () => import(/* webpackChunkName: "home" */ '@/views/productManagement/newProduct/detail'),
+                meta: {
+                  title: '产品详情',
+                  icon: 'home'
+                },
+                hidden: true
+              },
+            ]
           }
-        }]
-      },
-      {
-        path: '/changePwd',
-        name: 'changePwd',
-        component: () => import(/* webpackChunkName: "home" */ '@/views/user/ChangePwd'),
-        meta: {
-          title: '修改密码',
-          icon: 'home'
-        },
-        hidden: true
-      },
-      // 新品列表
-      {
-        path: '/newProduct/list/:onlineFalg',
-        name: 'newProductList',
-        component: () => import(/* webpackChunkName: "home" */ '@/views/productManagement/newProduct/list'),
-        meta: {
-          title: '新品信息',
-          icon: 'home'
-        },
-        hidden: true
-      },
-      // 产品详情
-      {
-        path: '/viewProduct/:sn',
-        name: 'viewProduct',
-        component: () => import(/* webpackChunkName: "home" */ '@/views/productManagement/newProduct/detail'),
-        meta: {
-          title: '产品详情',
-          icon: 'home'
-        },
-        hidden: true
+        ]
       },
       // 销售管理
       {
@@ -111,7 +147,8 @@ export const asyncRouterMap = [
                 meta: {
                   title: '销售单详情',
                   icon: 'monitor',
-                  hidden: true
+                  hidden: true,
+                  replaceTab: true,
                   // permission: 'M_salesDetail'
                 }
               },
@@ -509,7 +546,7 @@ export const asyncRouterMap = [
             name: 'returnConfirmation',
             component: BlankLayout,
             meta: {
-              title: '退货确认',
+              title: '销售退货确认',
               icon: 'vertical-align-top',
               permission: 'M_returnConfirmationList'
             },
@@ -520,7 +557,7 @@ export const asyncRouterMap = [
                 name: 'returnConfirmationList',
                 component: () => import(/* webpackChunkName: "financialManagement" */ '@/views/financialManagement/returnConfirmation/list.vue'),
                 meta: {
-                  title: '退货确认列表',
+                  title: '销售退货确认列表',
                   icon: 'vertical-align-top',
                   hidden: true,
                   permission: 'M_returnConfirmationList'
@@ -528,6 +565,31 @@ export const asyncRouterMap = [
               }
             ]
           },
+          {
+            path: '/financialManagement/allocateReturnConfirmation',
+            redirect: '/financialManagement/allocateReturnConfirmation/list',
+            name: 'allocateReturnConfirmation',
+            component: BlankLayout,
+            meta: {
+              title: '调拨退货确认',
+              icon: 'vertical-align-top',
+              permission: 'M_allocateReturnConfirmationList'
+            },
+            hideChildrenInMenu: true,
+            children: [
+              {
+                path: 'list',
+                name: 'allocateReturnConfirmationList',
+                component: () => import(/* webpackChunkName: "financialManagement" */ '@/views/financialManagement/allocateReturnConfirmation/list.vue'),
+                meta: {
+                  title: '调拨退货确认列表',
+                  icon: 'vertical-align-top',
+                  hidden: true,
+                  permission: 'M_allocateReturnConfirmationList'
+                }
+              }
+            ]
+          },
           {
             path: '/financialManagement/inventoryConfirmation',
             redirect: '/financialManagement/inventoryConfirmation/list',
@@ -845,13 +907,27 @@ export const asyncRouterMap = [
           },
           {
             path: '/inventoryManagement/inventoryWarning',
-            name: 'inventoryWarningList',
-            component: () => import(/* webpackChunkName: "inventoryManagement" */ '@/views/inventoryManagement/inventoryWarning/list.vue'),
+            redirect: '/inventoryManagement/inventoryWarning/list',
+            name: 'inventoryWarning',
+            component: BlankLayout,
             meta: {
               title: '库存预警',
-              icon: 'alert',
+              icon: 'monitor',
               permission: 'M_inventoryWarningList'
-            }
+            },
+            hideChildrenInMenu: true,
+            children: [
+              {
+                path: 'list',
+                name: 'inventoryWarningList',
+                component: () => import(/* webpackChunkName: "inventoryManagement" */ '@/views/inventoryManagement/inventoryWarning/list.vue'),
+                meta: {
+                  title: '库存预警列表',
+                  icon: 'alert',
+                  permission: 'M_inventoryWarningList'
+                }
+              },
+            ]
           },
           {
             path: '/inventoryManagement/intelligentReplenishment',
@@ -1008,6 +1084,73 @@ export const asyncRouterMap = [
                 }
               }
             ]
+          },
+          {
+            path: '/allocationManagement/transferReturn',
+            redirect: '/allocationManagement/transferReturn/list',
+            name: 'transferReturn',
+            component: BlankLayout,
+            meta: {
+              title: '调拨退货列表',
+              icon: 'pull-request',
+              permission: 'M_transferReturnList'
+            },
+            hideChildrenInMenu: true,
+            children: [
+              {
+                path: 'list',
+                name: 'transferReturnList',
+                component: () => import(/* webpackChunkName: "allocationManagement" */ '@/views/allocationManagement/transferReturn/list.vue'),
+                meta: {
+                  title: '调拨退货列表',
+                  icon: 'pull-request',
+                  hidden: true,
+                  permission: 'M_transferReturnList'
+                }
+              },
+              {
+                path: 'editGrap/:sn/:targetType',
+                name: 'transferReturnGrpEdit',
+                component: () => import(/* webpackChunkName: "allocationManagement" */ '@/views/allocationManagement/transferReturn/editGrp.vue'),
+                meta: {
+                  title: '编辑调拨退货单(抓单)',
+                  icon: 'pull-request',
+                  hidden: true
+                }
+              },
+              {
+                path: 'edit/:sn/:targetType/:dealerLevel',
+                name: 'transferReturnEdit',
+                component: () => import(/* webpackChunkName: "allocationManagement" */ '@/views/allocationManagement/transferReturn/edit.vue'),
+                meta: {
+                  title: '编辑调拨退货单(不抓单)',
+                  icon: 'pull-request',
+                  hidden: true
+                }
+              },
+              {
+                path: 'detail/:sn',
+                name: 'transferReturnDetail',
+                component: () => import(/* webpackChunkName: "allocationManagement" */ '@/views/allocationManagement/transferReturn/detail.vue'),
+                meta: {
+                  title: '调拨退货单详情',
+                  icon: 'pull-request',
+                  replaceTab: true,
+                  hidden: true
+                }
+              },
+              {
+                path: 'check/:sn/:grabFlag',
+                name: 'transferReturnCheck',
+                component: () => import(/* webpackChunkName: "allocationManagement" */ '@/views/allocationManagement/transferReturn/check.vue'),
+                meta: {
+                  title: '调拨退货品检',
+                  icon: 'fund',
+                  replaceTab: true,
+                  hidden: true
+                }
+              }
+            ]
           }
         ]
       },
@@ -1111,8 +1254,7 @@ export const asyncRouterMap = [
             children: [{
               path: 'list',
               name: 'salesAmountReportList',
-              component: () => import(/* webpackChunkName: "reportData" */
-                '@/views/reportData/salesAmountReport/list.vue'),
+              component: () => import(/* webpackChunkName: "reportData" */ '@/views/reportData/salesAmountReport/list.vue'),
               meta: {
                 title: '开单销售报表列表',
                 icon: 'profile',
@@ -1135,8 +1277,7 @@ export const asyncRouterMap = [
             children: [{
               path: 'list',
               name: 'salesSlipReportList',
-              component: () => import(/* webpackChunkName: "reportData" */
-                '@/views/reportData/salesSlipReport/list.vue'),
+              component: () => import(/* webpackChunkName: "reportData" */ '@/views/reportData/salesSlipReport/list.vue'),
               meta: {
                 title: '开单销售单报表列表',
                 icon: 'profile',
@@ -1244,6 +1385,54 @@ export const asyncRouterMap = [
               }
             }]
           },
+          {
+            path: '/reportData/transferReturnReport',
+            redirect: '/reportData/transferReturnReport/list',
+            name: 'transferReturnReport',
+            component: BlankLayout,
+            meta: {
+              title: '调拨退货单报表',
+              icon: 'profile',
+              permission: 'M_transferReturnReportList'
+            },
+            hideChildrenInMenu: true,
+            children: [
+              {
+                path: 'list',
+                name: 'transferReturnReportList',
+                component: () => import(/* webpackChunkName: "reportData" */ '@/views/reportData/transferReturnReport/list.vue'),
+                meta: {
+                  title: '调拨退货单报表列表',
+                  icon: 'profile',
+                  hidden: true,
+                  permission: 'M_transferReturnReportList'
+                }
+              }
+            ]
+          },
+          {
+            path: '/reportData/transferReturnDetailReport',
+            redirect: '/reportData/transferReturnDetailReport/list',
+            name: 'transferReturnDetailReport',
+            component: BlankLayout,
+            meta: {
+              title: '调拨退货单明细报表',
+              icon: 'profile',
+              permission: 'M_transferReturnDetailReportList'
+            },
+            hideChildrenInMenu: true,
+            children: [{
+              path: 'list',
+              name: 'transferReturnDetailReportList',
+              component: () => import(/* webpackChunkName: "reportData" */ '@/views/reportData/transferReturnDetailReport/list.vue'),
+              meta: {
+                title: '调拨退货单明细报表列表',
+                icon: 'profile',
+                hidden: true,
+                permission: 'M_transferReturnDetailReportList'
+              }
+            }]
+          },
           {
             path: '/reportData/salesReturnReport',
             redirect: '/reportData/salesReturnReport/list',
@@ -2326,7 +2515,7 @@ export const asyncRouterMap = [
       // 权限管理
       {
         path: '/auth',
-        redirect: '/auth/userList',
+        redirect: '/auth/user',
         component: PageView,
         meta: {
           title: '权限管理',
@@ -2335,41 +2524,86 @@ export const asyncRouterMap = [
         },
         children: [
           {
-            path: '/auth/userList',
-            name: 'powerUserList',
-            component: () => import(/* webpackChunkName: "auth" */ '@/views/power/user/userList.vue'),
+            path: '/auth/user',
+            redirect: '/auth/user/list',
+            name: 'powerUser',
+            component: BlankLayout,
             meta: {
               title: '用户管理',
               icon: 'user',
               permission: 'M_userList'
-            }
+            },
+            hideChildrenInMenu: true,
+            children: [
+              {
+                path: 'list',
+                name: 'powerUserList',
+                component: () => import(/* webpackChunkName: "auth" */ '@/views/power/user/userList.vue'),
+                meta: {
+                  title: '用户管理',
+                  icon: 'user',
+                  hidden: true,
+                  permission: 'M_userList'
+                }
+              },
+            ]
           },
           {
-            path: '/auth/roleList',
-            name: 'powerRoleList',
-            component: () => import(/* webpackChunkName: "auth" */ '@/views/power/role/roleList.vue'),
+            path: '/auth/role',
+            redirect: '/auth/role/list',
+            name: 'powerRole',
+            component: BlankLayout,
             meta: {
               title: '角色管理',
               icon: 'solution',
               permission: 'M_roleList'
-            }
+            },
+            hideChildrenInMenu: true,
+            children: [
+              {
+                path: 'list',
+                name: 'powerRoleList',
+                component: () => import(/* webpackChunkName: "auth" */ '@/views/power/role/roleList.vue'),
+                meta: {
+                  title: '角色管理',
+                  icon: 'solution',
+                  hidden: true,
+                  permission: 'M_roleList'
+                }
+              },
+            ]
           },
           {
-            path: '/menusAuth/adminMenus',
+            path: '/auth/adminMenus',
+            redirect: '/auth/adminMenus/list',
             name: 'adminMenus',
-            component: () => import(/* webpackChunkName: "auth" */ '@/views/bnSetting/menu/adminMenus.vue'),
+            component: BlankLayout,
             meta: {
               title: '菜单管理',
               icon: 'appstore',
               permission: 'M_menuList'
-            }
+            },
+            hideChildrenInMenu: true,
+            children: [
+              {
+                path: 'list',
+                name: 'adminMenusList',
+                component: () => import(/* webpackChunkName: "auth" */ '@/views/bnSetting/menu/adminMenus.vue'),
+                meta: {
+                  title: '菜单管理',
+                  icon: 'appstore',
+                  hidden: true,
+                  permission: 'M_menuList'
+                }
+              }
+            ]
           }
         ]
       },
       // 系统设置
       {
         path: '/setting',
-        redirect: '/setting/userList',
+        redirect: '/setting/dataDictionary',
         component: PageView,
         meta: {
           title: '系统设置',
@@ -2379,35 +2613,52 @@ export const asyncRouterMap = [
         children: [
           {
             path: '/setting/dataDictionary',
-            name: 'powerDD',
-            component: () => import(/* webpackChunkName: "setting" */
-              '@/views/power/dataDictionary/dataDictionary.vue'),
+            redirect: '/setting/dataDictionary/list',
+            name: 'dataDictionary',
+            component: BlankLayout,
             meta: {
               title: '数据字典管理',
               icon: 'database',
               permission: 'M_dataD_lookup'
-            }
+            },
+            hideChildrenInMenu: true,
+            children: [
+              {
+                path: 'list',
+                name: 'powerDD',
+                component: () => import(/* webpackChunkName: "setting" */ '@/views/power/dataDictionary/dataDictionary.vue'),
+                meta: {
+                  title: '数据字典管理',
+                  icon: 'database',
+                  hidden: true,
+                  permission: 'M_dataD_lookup'
+                }
+              }
+            ]
           },
-          // {
-          //   path: '/setting/register',
-          //   name: 'powerRegister',
-          //   component: () => import(/* webpackChunkName: "setting" */ '@/views/power/register/register.vue'),
-          //   meta: {
-          //     title: '参数管理',
-          //     icon: 'key',
-          //     permission: 'M_sys_register'
-          //   }
-          // },
           {
             path: '/setting/OperateJournal',
-            name: 'powerOperateJournal',
-            component: () => import(/* webpackChunkName: "setting" */
-              '@/views/power/OperateJournal/OperateJournal.vue'),
+            redirect: '/setting/OperateJournal/list',
+            name: 'OperateJournal',
+            component: BlankLayout,
             meta: {
               title: '操作日志',
               icon: 'read',
               permission: 'M_OperateJournalList'
-            }
+            },
+            hideChildrenInMenu: true,
+            children: [
+              {
+                path: 'list',
+                name: 'powerOperateJournal',
+                component: () => import(/* webpackChunkName: "setting" */ '@/views/power/OperateJournal/OperateJournal.vue'),
+                meta: {
+                  title: '操作日志',
+                  icon: 'read',
+                  permission: 'M_OperateJournalList'
+                }
+              },
+            ]
           },
           {
             path: '/setting/noticeManagement',
@@ -2436,27 +2687,6 @@ export const asyncRouterMap = [
           }
         ]
       },
-      // 公告
-      {
-        path: '/notice',
-        name: 'notice',
-        component: () => import(/* webpackChunkName: "home" */ '@/views/setting/notice/list'),
-        meta: {
-          title: '公告',
-          icon: 'bell'
-        },
-        hidden: true
-      },
-      {
-        path: '/dowloadFile',
-        name: 'dowloadFile',
-        component: () => import(/* webpackChunkName: "home" */ '@/views/dowloadFile/list'),
-        meta: {
-          title: '下载中心',
-          icon: 'bell'
-        },
-        hidden: true
-      }
     ]
   },
   {

+ 2 - 1
src/layouts/BasicLayout.vue

@@ -41,7 +41,8 @@
       <!-- layout content -->
       <a-layout-content :style="{ height: '100%', margin: '31px 20px 0', paddingTop: multiTab&&fixedHeader ? '61px' : (!multiTab&&fixedHeader?'33px':'0') }">
         <transition name="page-transition">
-          <route-view v-if="isRouterAlive"/>
+          <!-- <route-view v-if="isRouterAlive"/> -->
+          <router-view ></router-view>
         </transition>
       </a-layout-content>
 

+ 3 - 1
src/layouts/BlankLayout.vue

@@ -1,6 +1,8 @@
 <template>
   <div>
-    <router-view />
+    <keep-alive>
+      <router-view :key="$route.name"></router-view>
+    </keep-alive>
   </div>
 </template>
 

+ 17 - 78
src/layouts/PageView.vue

@@ -1,51 +1,10 @@
 <template>
   <div :style="!$route.meta.hiddenHeaderContent ? 'margin: -24px -24px 0px;' : null">
-    <!-- pageHeader , route meta :true on hide -->
-    <!-- <page-header v-if="!$route.meta.hiddenHeaderContent" :title="pageTitle" :logo="logo" :avatar="avatar"> -->
-    <page-header v-if="false" :title="pageTitle" :logo="logo" :avatar="avatar">
-      <slot slot="action" name="action"></slot>
-      <slot slot="content" name="headerContent"></slot>
-      <div slot="content" v-if="!this.$slots.headerContent && description">
-        <p style="font-size: 14px;color: rgba(0,0,0,.65)">{{ description }}</p>
-        <div class="link">
-          <template v-for="(link, index) in linkList">
-            <a :key="index" :href="link.href">
-              <a-icon :type="link.icon" />
-              <span>{{ link.title }}</span>
-            </a>
-          </template>
-        </div>
-      </div>
-      <slot slot="extra" name="extra">
-        <div class="extra-img">
-          <img v-if="typeof extraImage !== 'undefined'" :src="extraImage"/>
-        </div>
-      </slot>
-      <div slot="pageMenu">
-        <div class="page-menu-search" v-if="search">
-          <a-input-search
-            style="width: 80%; max-width: 522px;"
-            placeholder="请输入..."
-            size="large"
-            enterButton="搜索"
-          />
-        </div>
-        <div class="page-menu-tabs" v-if="tabs && tabs.items">
-          <!-- @change="callback" :activeKey="activeKey" -->
-          <a-tabs :tabBarStyle="{margin: 0}" :activeKey="tabs.active()" @change="tabs.callback">
-            <a-tab-pane v-for="item in tabs.items" :tab="item.title" :key="item.key"></a-tab-pane>
-          </a-tabs>
-        </div>
-      </div>
-    </page-header>
+    <PageHeader v-if="!multiTab"></PageHeader>
     <div class="content" :style="{ height: pageHeight+'px' }">
       <div class="page-header-index-wide">
         <slot>
-          <!-- keep-alive  -->
-          <keep-alive v-if="multiTab">
-            <router-view ref="content" />
-          </keep-alive>
-          <router-view v-else ref="content" />
+          <router-view ref="content" />
         </slot>
       </div>
     </div>
@@ -53,9 +12,9 @@
 </template>
 
 <script>
+import PageHeader from '@/components/PageHeader/PageHeader.vue'
 import { mapState } from 'vuex'
-import PageHeader from '@/components/PageHeader'
-
+import { on, off } from '@/libs/tools'
 export default {
   name: 'PageView',
   components: {
@@ -92,47 +51,27 @@ export default {
   },
   computed: {
     ...mapState({
-      multiTab: state => state.app.multiTab
+      multiTab: state => state.app.multiTab,
+      closeTabPages: state => state.app.closeTabPages
     })
-    // contHeight () {
-    //   return window.innerHeight - 80
-    // }
   },
   mounted () {
     this.tabs = this.directTabs
-    this.getPageMeta()
     this.setpageH()
-    const _this = this
-    window.onresize = () => {
-      return (() => {
-        _this.$store.dispatch('SetWinHeight', window.innerHeight)
-        _this.setpageH()
-      })()
-    }
+    on(window, 'resize', this.setpageH)
+  },
+  beforeDestroy () {
+    off(window, 'resize', this.setpageH)
   },
-  updated () {
-    this.getPageMeta()
+  activated () {
+    this.setpageH()
   },
   methods: {
     setpageH () {
-      this.pageHeight = window.innerHeight - 80
-    },
-    getPageMeta () {
-      // eslint-disable-next-line
-      this.pageTitle = (typeof(this.title) === 'string' || !this.title) ? this.title : this.$route.meta.title
-
-      const content = this.$refs.content
-      if (content) {
-        if (content.pageMeta) {
-          Object.assign(this, content.pageMeta)
-        } else {
-          this.description = content.description
-          this.linkList = content.linkList
-          this.extraImage = content.extraImage
-          this.search = content.search === true
-          this.tabs = content.tabs
-        }
-      }
+      this.$nextTick(() => {
+        this.$store.dispatch('SetWinHeight', window.innerHeight)
+        this.pageHeight = window.innerHeight - 85
+      })
     }
   }
 }
@@ -140,7 +79,7 @@ export default {
 
 <style lang="less" scoped>
   .content {
-    margin: 12px 12px 0;
+    margin: 8px 12px 0;
     .page-header-index-wide{
       height: 100%;
       >div{

+ 454 - 0
src/libs/tools.js

@@ -3,3 +3,457 @@ export const getOperationalPrecision = (num1, num2) => {
   const val = ((num1 * 10000) * (num2 * 10000) / 100000000).toFixed(2) || 0
   return val != 0 ? val : 0
 }
+export const forEach = (arr, fn) => {
+  if (!arr.length || !fn) return
+  let i = -1
+  const len = arr.length
+  while (++i < len) {
+    const item = arr[i]
+    fn(item, i, arr)
+  }
+}
+
+/**
+ * @param {Array} arr1
+ * @param {Array} arr2
+ * @description 得到两个数组的交集, 两个数组的元素为数值或字符串
+ */
+export const getIntersection = (arr1, arr2) => {
+  const len = Math.min(arr1.length, arr2.length)
+  let i = -1
+  const res = []
+  while (++i < len) {
+    const item = arr2[i]
+    if (arr1.indexOf(item) > -1) res.push(item)
+  }
+  return res
+}
+
+/**
+ * @param {Array} arr1
+ * @param {Array} arr2
+ * @description 得到两个数组的并集, 两个数组的元素为数值或字符串
+ */
+export const getUnion = (arr1, arr2) => {
+  return Array.from(new Set([...arr1, ...arr2]))
+}
+
+/**
+ * @param {Array} target 目标数组
+ * @param {Array} arr 需要查询的数组
+ * @description 判断要查询的数组是否至少有一个元素包含在目标数组中
+ */
+export const hasOneOf = (targetarr, arr) => {
+  if (!targetarr) return true
+  if (!arr) return true
+  return targetarr.some(_ => arr.indexOf(_) > -1)
+}
+
+/**
+ * @param {String|Number} value 要验证的字符串或数值
+ * @param {*} validList 用来验证的列表
+ */
+export function oneOf (value, validList) {
+  for (let i = 0; i < validList.length; i++) {
+    if (value === validList[i]) {
+      return true
+    }
+  }
+  return false
+}
+
+/**
+ * @param {Number} timeStamp 判断时间戳格式是否是毫秒
+ * @returns {Boolean}
+ */
+const isMillisecond = timeStamp => {
+  const timeStr = String(timeStamp)
+  return timeStr.length > 10
+}
+
+/**
+ * @param {Number} timeStamp 传入的时间戳
+ * @param {Number} currentTime 当前时间时间戳
+ * @returns {Boolean} 传入的时间戳是否早于当前时间戳
+ */
+const isEarly = (timeStamp, currentTime) => {
+  return timeStamp < currentTime
+}
+
+/**
+ * @param {Number} num 数值
+ * @returns {String} 处理后的字符串
+ * @description 如果传入的数值小于10,即位数只有1位,则在前面补充0
+ */
+const getHandledValue = num => {
+  return num < 10 ? '0' + num : num
+}
+
+/**
+ * @param {Number} timeStamp 传入的时间戳
+ * @param {Number} startType 要返回的时间字符串的格式类型,传入'year'则返回年开头的完整时间
+ */
+const getDate = (timeStamp, startType) => {
+  const d = new Date(timeStamp * 1000)
+  const year = d.getFullYear()
+  const month = getHandledValue(d.getMonth() + 1)
+  const date = getHandledValue(d.getDate())
+  const hours = getHandledValue(d.getHours())
+  const minutes = getHandledValue(d.getMinutes())
+  const second = getHandledValue(d.getSeconds())
+  let resStr = ''
+  if (startType === 'year') resStr = year + '-' + month + '-' + date + ' ' + hours + ':' + minutes + ':' + second
+  else resStr = month + '-' + date + ' ' + hours + ':' + minutes
+  return resStr
+}
+/**
+ * @param {Number} timeStamp 传入的时间戳
+ * @param {Number} fmt 格式化字符串
+ */
+export const formtDate = (timeStamp, fmt) => {
+  const d = new Date(timeStamp)
+  var o = {
+    'M+': d.getMonth() + 1, // 月份
+    'd+': d.getDate(), // 日
+    'h+': d.getHours(), // 小时
+    'm+': d.getMinutes(), // 分
+    's+': d.getSeconds(), // 秒
+    'q+': Math.floor((d.getMonth() + 3) / 3), // 季度
+    'S': d.getMilliseconds() // 毫秒
+  }
+  if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (d.getFullYear() + '').substr(4 - RegExp.$1.length))
+  for (var k in o) { if (new RegExp('(' + k + ')').test(fmt)) fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (('00' + o[k]).substr(('' + o[k]).length))) }
+  return fmt
+}
+//  获取三个月后的时间戳
+export const getThreeMonthsAfter = (dtstr) => {
+  var s = dtstr.split('-')
+  var yy = parseInt(s[0])
+  var mm = parseInt(s[1])
+  var dd = parseInt(s[2])
+  var dt = new Date(yy, mm + 2, dd)
+  return dt.valueOf()
+}
+/**
+ * @param {String|Number} timeStamp 时间戳
+ * @returns {String} 相对时间字符串
+ */
+export const getRelativeTime = timeStamp => {
+  // 判断当前传入的时间戳是秒格式还是毫秒
+  const IS_MILLISECOND = isMillisecond(timeStamp)
+  // 如果是毫秒格式则转为秒格式
+  if (IS_MILLISECOND) Math.floor(timeStamp /= 1000)
+  // 传入的时间戳可以是数值或字符串类型,这里统一转为数值类型
+  timeStamp = Number(timeStamp)
+  // 获取当前时间时间戳
+  const currentTime = Math.floor(Date.parse(new Date()) / 1000)
+  // 判断传入时间戳是否早于当前时间戳
+  const IS_EARLY = isEarly(timeStamp, currentTime)
+  // 获取两个时间戳差值
+  let diff = currentTime - timeStamp
+  // 如果IS_EARLY为false则差值取反
+  if (!IS_EARLY) diff = -diff
+  let resStr = ''
+  const dirStr = IS_EARLY ? '前' : '后'
+  // 少于等于59秒
+  if (diff <= 59) resStr = diff + '秒' + dirStr
+  // 多于59秒,少于等于59分钟59秒
+  else if (diff > 59 && diff <= 3599) resStr = Math.floor(diff / 60) + '分钟' + dirStr
+  // 多于59分钟59秒,少于等于23小时59分钟59秒
+  else if (diff > 3599 && diff <= 86399) resStr = Math.floor(diff / 3600) + '小时' + dirStr
+  // 多于23小时59分钟59秒,少于等于29天59分钟59秒
+  else if (diff > 86399 && diff <= 2623859) resStr = Math.floor(diff / 86400) + '天' + dirStr
+  // 多于29天59分钟59秒,少于364天23小时59分钟59秒,且传入的时间戳早于当前
+  else if (diff > 2623859 && diff <= 31567859 && IS_EARLY) resStr = getDate(timeStamp)
+  else resStr = getDate(timeStamp, 'year')
+  return resStr
+}
+
+// 日期格式化
+export const formatSubmitDate = (val, type) => {
+  if (val == null || val == '' || val == undefined) {
+    return ''
+  } else {
+    const _date = new Date(val)
+    const _year = _date.getFullYear()
+    const _montn = (_date.getMonth() + 1) < 10 ? '0' + (_date.getMonth() + 1) : (_date.getMonth() + 1)
+    const _day = _date.getDate() < 10 ? '0' + _date.getDate() : _date.getDate()
+    const _hour = _date.getHours() < 10 ? '0' + _date.getHours() : _date.getHours()
+    const _minutes = _date.getMinutes() < 10 ? '0' + _date.getMinutes() : _date.getMinutes()
+    const _seconds = _date.getSeconds() < 10 ? '0' + _date.getSeconds() : _date.getSeconds()
+
+    if (type == 'minutes') return _year + '-' + _montn + '-' + _day + ' ' + _hour + ':' + _minutes
+    else if (type == 'seconds') return _year + '-' + _montn + '-' + _day + ' ' + _hour + ':' + _minutes + ':' + _seconds
+    else return _year + '-' + _montn + '-' + _day
+  }
+}
+// 正则验证车牌,验证通过返回true,不通过返回false
+export const isLicensePlate = function (str) {
+  return /^(([京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领][A-Z](([0-9]{5}[DF])|([DF]([A-HJ-NP-Z0-9])[0-9]{4})))|([京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领][A-Z][A-HJ-NP-Z0-9]{4}[A-HJ-NP-Z0-9挂学警港澳使领]))$/.test(str)
+}
+// 车牌可输入字符
+export const isCarNumber = function (str) {
+  let _value = str + ''
+  _value = _value.replace(/[^\w\.挂学警港澳使领]/ig, '')
+
+  return _value
+}
+// 小数点后两位
+export const numberToFixed = function (val, num) {
+  let _value = val + ''
+  _value = _value.replace(/[^\d.]/g, '')// 清楚数字和.以外的字数
+  _value = _value.replace(/^\./g, '')
+  _value = _value.replace(/\.{2,}/g, '')// 保留第一个,清楚多余的
+
+  if (num == 1)_value = _value.replace(/^(\-)*(\d+)\.(\d).*$/, '$1$2.$3')
+  else if (num == 3)_value = _value.replace(/^(\-)*(\d+)\.(\d\d\d).*$/, '$1$2.$3')
+  else if (num == 4)_value = _value.replace(/^(\-)*(\d+)\.(\d\d\d\d).*$/, '$1$2.$3')
+  else if (num == 5)_value = _value.replace(/^(\-)*(\d+)\.(\d\d\d\d\d).*$/, '$1$2.$3')
+  else if (num == 0)_value = _value.replace(/^(\-)*(\d+)\.*$/, '$1$2')
+  else _value = _value.replace(/^(\-)*(\d+)\.(\d\d).*$/, '$1$2.$3')
+
+  return _value
+}
+// 保留decimal位小数(不四舍五入)  num 数值,decimal要保留的小数位数
+export const formatDecimal = function (num, decimal) {
+  num = num.toString()
+  const index = num.indexOf('.')
+  if (index !== -1) {
+    num = num.substring(0, decimal + index + 1)
+  } else {
+    num = num.substring(0)
+  }
+  return parseFloat(num).toFixed(decimal)
+}
+// 处理数字千位分隔符  num 数值,decimal要保留的小数位数
+export const toThousands = (num, decimal) => {
+  if (num == undefined) {
+    return '--'
+  }
+  if (decimal) {
+    num = formatDecimal(num, decimal)
+  }
+  return num.toString().replace(/\d+/, function (n) { // 先提取整数部分
+    return n.replace(/(\d)(?=(\d{3})+$)/g, function ($1) {
+      return $1 + ','
+    })
+  })
+}
+// 只能输入数字
+export const justNumber = function (val) {
+  let _value = val + ''
+  _value = _value.replace(/\D/g, '')
+
+  return _value
+}
+
+/**
+ * @returns {String} 当前浏览器名称
+ */
+export const getExplorer = () => {
+  const ua = window.navigator.userAgent
+  const isExplorer = (exp) => {
+    return ua.indexOf(exp) > -1
+  }
+  if (isExplorer('MSIE')) return 'IE'
+  else if (isExplorer('Firefox')) return 'Firefox'
+  else if (isExplorer('Chrome')) return 'Chrome'
+  else if (isExplorer('Opera')) return 'Opera'
+  else if (isExplorer('Safari')) return 'Safari'
+}
+
+/**
+ * @description 绑定事件 on(element, event, handler)
+ */
+export const on = (function () {
+  if (document.addEventListener) {
+    return function (element, event, handler) {
+      if (element && event && handler) {
+        element.addEventListener(event, handler, false)
+      }
+    }
+  } else {
+    return function (element, event, handler) {
+      if (element && event && handler) {
+        element.attachEvent('on' + event, handler)
+      }
+    }
+  }
+})()
+
+/**
+ * @description 解绑事件 off(element, event, handler)
+ */
+export const off = (function () {
+  if (document.removeEventListener) {
+    return function (element, event, handler) {
+      if (element && event) {
+        element.removeEventListener(event, handler, false)
+      }
+    }
+  } else {
+    return function (element, event, handler) {
+      if (element && event) {
+        element.detachEvent('on' + event, handler)
+      }
+    }
+  }
+})()
+
+/**
+ * 判断一个对象是否存在key,如果传入第二个参数key,则是判断这个obj对象是否存在key这个属性
+ * 如果没有传入key这个参数,则判断obj对象是否有键值对
+ */
+export const hasKey = (obj, key) => {
+  if (key) return key in obj
+  else {
+    const keysArr = Object.keys(obj)
+    return keysArr.length
+  }
+}
+
+/**
+ * @param {*} obj1 对象
+ * @param {*} obj2 对象
+ * @description 判断两个对象是否相等,这两个对象的值只能是数字或字符串
+ */
+export const objEqual = (obj1, obj2) => {
+  const keysArr1 = Object.keys(obj1)
+  const keysArr2 = Object.keys(obj2)
+  if (keysArr1.length !== keysArr2.length) return false
+  else if (keysArr1.length === 0 && keysArr2.length === 0) return true
+  /* eslint-disable-next-line */
+  else return !keysArr1.some(key => obj1[key] != obj2[key])
+}
+
+/*
+ * @param {*} id 数字
+ * @param {*} list 数组
+ * @description 根据id从数组列表中删除某一项
+*/
+export const removeListById = (id, list) => {
+  list.splice(list.findIndex(item => item.id === id), 1)
+}
+
+/**
+ * @param {*} obj1 对象
+ * @param {*} obj2 对象
+ * @description 遍历赋值
+*/
+export const objExtend = (obj1, obj2) => {
+  for (var a in obj1) {
+    obj2[a] = obj1[a]
+  }
+  return obj2
+}
+/**
+ * @param {*} obj 对象
+ * @description 浅拷贝
+*/
+export const cloneObj = (obj) => {
+  const ret = {}
+  for (var a in obj) {
+    ret[a] = obj[a]
+  }
+  return ret
+}
+
+/**
+ * 校验身份证号合法性
+ */
+export const checkIdNumberValid = (tex) => {
+  // var tip = '输入的身份证号有误,请检查后重新输入!'
+  let num = tex
+  num = num.toUpperCase()
+
+  const len = num.length
+  let re
+  if (len == 0) return true
+
+  // 身份证号码为15位或者18位,15位时全为数字,18位前17位为数字,最后一位是校验位,可能为数字或字符X。
+  if (!(/(^\d{15}$)|(^\d{17}([0-9]|X)$)/.test(num))) {
+    return false
+  }
+
+  // 验证前两位地区是否有效
+  const aCity = { 11: '北京',
+    12: '天津',
+    13: '河北',
+    14: '山西',
+    15: '内蒙古',
+    21: '辽宁',
+    22: '吉林',
+    23: '黑龙江',
+    31: '上海',
+    32: '江苏',
+    33: '浙江',
+    34: '安徽',
+    35: '福建',
+    36: '江西',
+    37: '山东',
+    41: '河南',
+    42: '湖北',
+    43: '湖南',
+    44: '广东',
+    45: '广西',
+    46: '海南',
+    50: '重庆',
+    51: '四川',
+    52: '贵州',
+    53: '云南',
+    54: '西藏',
+    61: '陕西',
+    62: '甘肃',
+    63: '青海',
+    64: '宁夏',
+    65: '新疆',
+    71: '台湾',
+    81: '香港',
+    82: '澳门',
+    91: '国外' }
+
+  if (aCity[parseInt(num.substr(0, 2))] == null) {
+    return false
+  }
+
+  // 当身份证为15位时的验证出生日期。
+  if (len == 15) {
+    re = new RegExp(/^(\d{6})(\d{2})(\d{2})(\d{2})(\d{3})$/)
+    const arrSplit = num.match(re)
+
+    // 检查生日日期是否正确
+    const dtmBirth = new Date('19' + arrSplit[2] + '/' + arrSplit[3] + '/' + arrSplit[4])
+    const bGoodDay = (dtmBirth.getYear() == Number(arrSplit[2])) && ((dtmBirth.getMonth() + 1) == Number(arrSplit[3])) && (dtmBirth.getDate() == Number(arrSplit[4]))
+    if (!bGoodDay) {
+      return false
+    }
+  }
+
+  // 当身份证号为18位时,校验出生日期和校验位。
+  if (len == 18) {
+    re = new RegExp(/^(\d{6})(\d{4})(\d{2})(\d{2})(\d{3})([0-9]|X)$/)
+    const arrSplit = num.match(re)
+    // 检查生日日期是否正确
+    const dtmBirth = new Date(arrSplit[2] + '/' + arrSplit[3] + '/' + arrSplit[4])
+    const bGoodDay = (dtmBirth.getFullYear() == Number(arrSplit[2])) && ((dtmBirth.getMonth() + 1) == Number(arrSplit[3])) && (dtmBirth.getDate() == Number(arrSplit[4]))
+    if (!bGoodDay) {
+      return false
+    } else {
+      // 检验18位身份证的校验码是否正确。
+      // 校验位按照ISO 7064:1983.MOD 11-2的规定生成,X可以认为是数字10。
+      let valnum
+      const arrInt = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2]
+      const arrCh = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2']
+      let nTemp = 0
+      let i
+      for (i = 0; i < 17; i++) {
+        nTemp += num.substr(i, 1) * arrInt[i]
+      }
+      valnum = arrCh[nTemp % 11]
+      if (valnum != num.substr(17, 1)) {
+        return false
+      }
+    }
+  }
+  return true
+}

+ 3 - 1
src/store/getters.js

@@ -13,7 +13,9 @@ const getters = {
   multiTab: state => state.app.multiTab,
   lang: state => state.i18n.lang,
   isNewTab: state => state.app.isNewTab,
-  isNewSubTab: state => state.app.isNewSubTab
+  isNewSubTab: state => state.app.isNewSubTab,
+  closeTabPages: state => state.app.closeTabPages,
+  loadingStatus: state => state.app.loadingStatus
 }
 
 export default getters

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

@@ -28,7 +28,9 @@ const app = {
     isNewTab: false,
     isNewSubTab: false,
     updateList: false,
-    winHeight: 0 //  窗口高度
+    winHeight: 0 ,//  窗口高度
+    loadingStatus: false,
+    closeTabPages: [], // 已关闭的页面
   },
   mutations: {
     SET_SIDEBAR_TYPE: (state, type) => {
@@ -81,7 +83,10 @@ const app = {
     },
     SET_WIN_HEIGHT: (state, val) => {
       state.winHeight = val
-    }
+    },
+    SET_loadingStatus: (state, val) => {
+      state.loadingStatus = val
+    },
   },
   actions: {
     setSidebar ({ commit }, type) {

+ 77 - 1
src/utils/mixin.js

@@ -75,4 +75,80 @@ const AppDeviceEnquire = {
   }
 }
 
-export { mixin, AppDeviceEnquire, mixinDevice }
+// 所有页
+const commonMixin = {
+  watch: {
+    '$store.state.app.loadingStatus': function (a, b) {
+      if (!a) {
+        if (this.disabled !== undefined) {
+          this.disabled = a
+        }
+        if (this.spinning !== undefined) {
+          this.spinning = a
+        }
+      }
+    }
+  },
+  methods: {
+    // 清除组件缓存
+    clearCompCache (cache, keys, key) {
+      if (cache[key] && cache[key].componentInstance) {
+        cache[key].componentInstance.$destroy()
+        if (keys.length) {
+          var index = keys.indexOf(key)
+          if (index > -1) {
+            keys.splice(index, 1)
+          }
+        }
+        delete cache[key]
+      }
+    }
+  },
+  beforeRouteLeave (to, from, next) {
+    const newVal = to
+    const oldVal = from
+    // 是否时同一个父级菜单下的页面
+    const mnlen = newVal.matched.length < 3
+    const newMatched = newVal.matched[mnlen ? 1 : 2]
+    const molen = oldVal.matched.length < 3
+    const oldMatched = oldVal.matched[molen ? 1 : 2]
+    const hasChildren = newMatched.name == oldMatched.name
+    // 判断是否是新增,编辑,详情页
+    const oa = oldVal.meta.title.indexOf('详情') >= 0
+    const ob = oldVal.meta.title.indexOf('新增') >= 0
+    const oc = oldVal.meta.title.indexOf('编辑') >= 0
+    const oxt = oldVal.meta.replaceTab
+    // console.log(hasChildren,oa||ob||oc||oxt)
+    const key = this.$vnode.key
+    const parentNode = this.$vnode.parent
+    const cache = parentNode && parentNode.componentInstance ? parentNode.componentInstance.cache : null
+    const keys = parentNode && parentNode.componentInstance ? parentNode.componentInstance.keys : null
+    const closeTabPages = this.$store.state.app.closeTabPages
+    const multiTab = this.$store.state.app.multiTab
+    // console.log(closeTabPages,key)
+    // 清空同级路由的组件缓存
+    if (hasChildren && (oa || ob || oc || oxt) && cache && keys) {
+      this.clearCompCache(cache, keys, key)
+      // 单页签模式
+      if (!multiTab) {
+        this.$store.state.app.isNewTab = false
+        this.$store.state.app.updateList = true
+      }
+    }
+    // 单页签模式,并且不是同级菜单的清空组件
+    if (!multiTab && !hasChildren) {
+      this.clearCompCache(cache, keys, key)
+    }
+    // 批量清空组件缓存
+    if (closeTabPages && closeTabPages.length && cache && keys) {
+      for (let i = 0; i < closeTabPages.length; i++) {
+        this.clearCompCache(cache, keys, closeTabPages[i])
+      }
+      this.$store.state.app.closeTabPages = []
+    }
+    // console.log(cache,keys)
+    next()
+  }
+}
+
+export { mixin, AppDeviceEnquire, mixinDevice, commonMixin }

+ 58 - 9
src/utils/request.js

@@ -1,38 +1,83 @@
-// import Vue from 'vue'
+import Vue from 'vue'
 import axios from 'axios'
 import store from '@/store'
 import notification from 'ant-design-vue/es/notification'
 import modal from 'ant-design-vue/es/modal'
 import { VueAxios } from './axios'
-// import { ACCESS_TOKEN } from '@/store/mutation-types'
-// console.log(process.env.VUE_APP_PRO_NAME)
+ 
 // 创建 axios 实例
 const service = axios.create({
   baseURL: process.env.VUE_APP_API_BASE_URL, // api base_url
-  timeout: 60000 // 请求超时时间
+  timeout: 1000000 // 请求超时时间
 })
 
 const err = (error) => {
-  console.log(error, 'error')
+  console.log(error, error.response,error.message,'error')
+  const config = error.config
+  // 网络连接出错
+  if (error.message.indexOf('Network Error') >= 0 || error.message.indexOf('Request failed') >= 0) {
+    notification.destroy()
+    notification.error({
+      message: '提示',
+      description: '无网络连接,请检查网络是否连接正常'
+    })
+    store.commit('SET_loadingStatus', false)
+    return Promise.reject(err)
+  }
+  
+  // 业务错误提示
   if (error.response) {
     const status = error.response.status
-    if ((status == 503 || status == 500) && window.location.pathname != '/user/login') {
+    if ((status == 503 || status == 500 || status == 404)) {
       notification.destroy()
       notification.error({
         message: '提示',
         description: error.response.data.message
       })
     }
+    store.commit('SET_loadingStatus', false)
+    return Promise.reject(err)
   }
+  
   // 超时无法访问服务
-  if (error.message.indexOf('timeout') >= 0 && window.location.pathname != '/user/login') {
+  if (error.message.indexOf('timeout') >= 0) {
     notification.destroy()
     notification.error({
       message: '提示',
-      description: '请求超时'
+      description: '网络连接超时,正在重连...'
+    })
+    // If config does not exist or the retry option is not set, reject
+    if (!config || !config.retry) return Promise.reject(err)
+    // Set the variable for keeping track of the retry count
+    config.__retryCount = Vue.ls.get(config.url + '__retryCount') || 0
+    // Check if we've maxed out the total number of retries
+    if (config.__retryCount >= config.retry) {
+      Vue.ls.remove(config.url + '__retryCount')
+      notification.destroy()
+      notification.error({
+        message: '提示',
+        description: '网络重连失败,请检测网络连接是否正常'
+      })
+      store.commit('SET_loadingStatus', false)
+      // Reject with the error
+      return Promise.reject(err)
+    }
+    // Increase the retry count
+    config.__retryCount += 1
+    Vue.ls.set(config.url + '__retryCount', config.__retryCount)
+    // Create new promise to handle exponential backoff
+    config.url = config.url.replace('/api', '')
+    const backoff = new Promise(function (resolve) {
+      setTimeout(function () {
+        resolve()
+      }, config.retryDelay || 1)
+    })
+  
+    // Return the promise in which recalls axios to retry the request
+    return backoff.then(function () {
+      return service(config)
     })
   }
-  return Promise.reject(error)
 }
 
 // request interceptor
@@ -41,6 +86,9 @@ service.interceptors.request.use(config => {
   if (token) {
     config.headers['access-token'] = token // 让每个请求携带自定义 token 请根据实际情况自行修改
   }
+  config.retry = 3
+  config.retryDelay = 1000
+  store.commit('SET_loadingStatus', true)
   return config
 }, err)
 
@@ -76,6 +124,7 @@ service.interceptors.response.use((response) => {
       description: response.data.code
     })
   }
+  store.commit('SET_loadingStatus', false)
   return response.data
 }, err)
 

+ 2 - 0
src/views/Home.vue

@@ -32,12 +32,14 @@
 </template>
 
 <script>
+import { commonMixin } from '@/utils/mixin'
 import { mapGetters } from 'vuex'
 import ResetPwd from '@/views/user/ResetPwd.vue'
 import newProduct from '@/views/productManagement/newProduct/modal.vue'
 import { queryNewProductPage } from '@/api/product'
 export default {
   name: 'Home',
+  mixins: [commonMixin],
   components: { ResetPwd, newProduct },
   data () {
     return {

+ 13 - 1
src/views/allocationManagement/transferOut/basicInfoModal.vue

@@ -67,6 +67,7 @@
 </template>
 
 <script>
+import { commonMixin } from '@/utils/mixin'
 import moment from 'moment'
 import debounce from 'lodash/debounce'
 import { VSelect } from '@/components'
@@ -75,7 +76,8 @@ import { dealerSubareaScopeList } from '@/api/dealer'
 import { getLookUpData } from '@/api/data'
 import { allocateTypeAllList } from '@/api/allocateType'
 export default {
-  name: 'StoreTransferOutBasicInfoModal',
+  name: 'TransferOutBasicInfoModal',
+  mixins: [commonMixin],
   components: { VSelect },
   props: {
     openModal: {
@@ -233,6 +235,16 @@ export default {
       if (!newValue) {
         this.$emit('close')
         this.$refs.ruleForm.resetFields()
+        this.form = {
+          targetType: 'DEALER',
+          targetSn: undefined,
+          targetName: '',
+          allocateTypeSn: undefined,
+          time: [],
+          promoStartDate: '',
+          promoEndDate: '',
+          remark: ''
+        }
       } else {
         this.getTargetTypeList()
         this.getAllocateTypeAllList()

+ 3 - 1
src/views/allocationManagement/transferOut/chooseImportModal.vue

@@ -66,10 +66,12 @@
 </template>
 
 <script>
+import { commonMixin } from '@/utils/mixin'
 import { hdExportExcel } from '@/libs/exportExcel'
 import { allocateBillParseProducts, allocateBillFailExcel } from '@/api/allocateBill'
 export default {
-  name: 'ChooseImportModal',
+  name: 'TransferOutChooseImportModal',
+  mixins: [commonMixin],
   props: {
     openModal: { //  弹框显示状态
       type: Boolean,

+ 7 - 3
src/views/allocationManagement/transferOut/detail.vue

@@ -18,22 +18,23 @@
           <a-button
             key="3"
             type="primary"
-            class="button-warning"
+            class="button-info"
             v-if="$hasPermissions('B_transferOut_detail_export')"
             id="allocateBillDetail-export-btn"
             :disabled="localDataSource.length==0"
             @click="handleExcel">导出Excel</a-button>
+          <a-divider type="vertical" />
           <a-button
             key="2"
             type="primary"
-            class="button-error"
+            class="button-info"
             v-if="$hasPermissions('B_transferOut_print')"
             id="allocateBillDetail-db-print-btn"
             :disabled="localDataSource.length==0"
             @click="handlePrint('dbPrint')">调拨打印</a-button>
           <a-button
             key="1"
-            type="primary"
+            type="default"
             class="button-info"
             v-if="$hasPermissions('B_transferOut_print')"
             id="allocateBillDetail-dbfl-print-btn"
@@ -88,11 +89,14 @@
 </template>
 
 <script>
+import { commonMixin } from '@/utils/mixin'
 import { STable, VSelect } from '@/components'
 import printModal from './printModal.vue'
 import { hdExportExcel } from '@/libs/exportExcel'
 import { allocateBillDetailList, allocateBillDetail, allocateBillDetailCount, allocateBillDetailPrint, allocateBillDetailExcel } from '@/api/allocateBill'
 export default {
+  name: 'TransferOutDetail',
+  mixins: [commonMixin],
   components: { STable, VSelect, printModal },
   props: {
     outBizSn: { //  有值则为弹框,无值则为页面

+ 16 - 9
src/views/allocationManagement/transferOut/edit.vue

@@ -12,22 +12,23 @@
           <a-button
             key="3"
             type="primary"
-            class="button-warning"
+            class="button-info"
             v-if="$hasPermissions('B_transferOut_detail_export')"
             id="allocateBillEdit-export-btn"
             :disabled="localDataSource.length==0"
             @click="handleExcel">导出Excel</a-button>
+          <a-divider type="vertical" />
           <a-button
             key="2"
             type="primary"
-            class="button-error"
+            class="button-info"
             v-if="$hasPermissions('B_transferOut_print')"
             id="allocateBillEdit-db-print-btn"
             :disabled="localDataSource.length==0"
             @click="handlePrint('dbPrint')">调拨打印</a-button>
           <a-button
             key="1"
-            type="primary"
+            type="default"
             class="button-info"
             v-if="$hasPermissions('B_transferOut_print')"
             id="allocateBillEdit-dbfl-print-btn"
@@ -100,7 +101,7 @@
               bordered>
               <!-- 操作 -->
               <template slot="action1" slot-scope="text, record">
-                <a-button size="small" type="primary" class="button-primary" @click="handleAdd(record)" id="allocateBillEdit-add-btn">添加</a-button>
+                <a-button size="small" type="link" class="button-primary" @click="handleAdd(record)" id="allocateBillEdit-add-btn">添加</a-button>
               </template>
             </s-table>
           </a-collapse-panel>
@@ -173,10 +174,10 @@
                     @change="e => priceChange(e, record)"
                     @focus="e => priceFocus(record, index)"
                     style="width: 100%;">
-                    <a-select-option v-if="record.cost" :value="record.cost" :label="record.cost">成本 {{ record.cost }}</a-select-option>
-                    <a-select-option v-if="loadDataSource&&loadDataSource[index]&&loadDataSource[index].provincePrice" :value="loadDataSource[index].provincePrice" :label="loadDataSource[index].provincePrice">A价 {{ loadDataSource[index].provincePrice }}</a-select-option>
-                    <a-select-option v-if="loadDataSource&&loadDataSource[index]&&loadDataSource[index].cityPrice" :value="loadDataSource[index].cityPrice" :label="loadDataSource[index].cityPrice">B价 {{ loadDataSource[index].cityPrice }}</a-select-option>
-                    <a-select-option v-if="loadDataSource&&loadDataSource[index]&&loadDataSource[index].specialPrice" :value="loadDataSource[index].specialPrice" :label="loadDataSource[index].specialPrice">C价 {{ loadDataSource[index].specialPrice }}</a-select-option>
+                    <a-select-option v-if="record.cost" :value="record.cost" :key="'cb-'+record.cost" :label="record.cost">成本 {{ record.cost }}</a-select-option>
+                    <a-select-option v-if="loadDataSource&&loadDataSource[index]&&loadDataSource[index].provincePrice" :value="loadDataSource[index].provincePrice" :key="'A-'+loadDataSource[index].productSn" :label="loadDataSource[index].provincePrice">A价 {{ loadDataSource[index].provincePrice }}</a-select-option>
+                    <a-select-option v-if="loadDataSource&&loadDataSource[index]&&loadDataSource[index].cityPrice" :value="loadDataSource[index].cityPrice" :key="'B-'+loadDataSource[index].productSn" :label="loadDataSource[index].cityPrice">B价 {{ loadDataSource[index].cityPrice }}</a-select-option>
+                    <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>
@@ -196,7 +197,7 @@
               </template>
               <!-- 操作 -->
               <template slot="action" slot-scope="text, record">
-                <a-button size="small" type="primary" class="button-error" @click="handleDel(record)" id="allocateBillEdit-del-btn">删除</a-button>
+                <a-button size="small" type="link" class="button-error" @click="handleDel(record)" id="allocateBillEdit-del-btn">删除</a-button>
               </template>
             </s-table>
           </a-collapse-panel>
@@ -224,6 +225,7 @@
 </template>
 
 <script>
+import { commonMixin } from '@/utils/mixin'
 import { STable, VSelect } from '@/components'
 import ImportGuideModal from './importGuideModal.vue'
 import printModal from './printModal.vue'
@@ -234,6 +236,8 @@ import AllocateType from '@/views/common/allocateType.js'
 import { allocateBillSave, allocateBillDetailList, allocateBillDetailCount, allocateBillDetail, allocateBillDetailSave, allocateBillSubmit, allocateBillDetailDel, allocateBillDetailDelAll, allocateBillDetailPrint, allocateBillBatchInsert, allocateBillDetailExcel } from '@/api/allocateBill'
 
 export default {
+  name: 'TransferOutEdit',
+  mixins: [commonMixin],
   components: { STable, VSelect, ImportGuideModal, AllocateType, printModal },
   data () {
     return {
@@ -367,6 +371,9 @@ export default {
               _this.spinning = false
             }
           })
+        },
+        onCancel () {
+          _this.getDetail()
         }
       })
     },

+ 3 - 1
src/views/allocationManagement/transferOut/importGuideModal.vue

@@ -63,11 +63,13 @@
 </template>
 
 <script>
+import { commonMixin } from '@/utils/mixin'
 import ChooseImportModal from './chooseImportModal.vue'
 import { Upload } from '@/components'
 import { allocateBillDownload } from '@/api/allocateBill'
 export default {
-  name: 'ImportGuideModal',
+  name: 'TransferOutImportGuideModal',
+  mixins: [commonMixin],
   components: { ChooseImportModal, Upload },
   props: {
     openModal: { //  弹框显示状态

+ 5 - 1
src/views/allocationManagement/transferOut/list.vue

@@ -77,7 +77,8 @@
         bordered>
         <!-- 单号 -->
         <template slot="allocateNo" slot-scope="text, record">
-          <span :class="$hasPermissions('M_transferOut_detail')?'active':'common'" @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>
         <!-- 起止时间 -->
         <template slot="promoDate" slot-scope="text, record">
@@ -119,6 +120,7 @@
 </template>
 
 <script>
+import { commonMixin } from '@/utils/mixin'
 import moment from 'moment'
 import getDate from '@/libs/getDate.js'
 import { STable, VSelect } from '@/components'
@@ -129,6 +131,8 @@ import { allocateBillList, allocateBillDel, allocateBillAudit, allocateBillExpor
 import AllocateType from '@/views/common/allocateType.js'
 import { hdExportExcel } from '@/libs/exportExcel'
 export default {
+  name: 'TransferOutList',
+  mixins: [commonMixin],
   components: { STable, VSelect, basicInfoModal, rangeDate, auditModal, AllocateType },
   data () {
     return {

+ 2 - 2
src/views/allocationManagement/transferOut/printModal.vue

@@ -36,8 +36,8 @@
         </a-form-model-item>
       </a-form-model>
       <div class="btn-cont">
-        <a-button type="primary" id="allocateBill-print-save" @click="handleSave('preview')">打印预览</a-button>
-        <a-button id="allocateBill-print-back" @click="handleSave('print')" style="margin-left: 15px;">快捷打印</a-button>
+        <a-button id="allocateBill-print-save" @click="handleSave('preview')">打印预览</a-button>
+        <a-button type="primary" id="allocateBill-print-back" @click="handleSave('print')" style="margin-left: 15px;">快捷打印</a-button>
       </div>
     </a-spin>
   </a-modal>

+ 243 - 0
src/views/allocationManagement/transferReturn/basicInfoModal.vue

@@ -0,0 +1,243 @@
+<template>
+  <a-modal
+    centered
+    class="allocateBill-basicInfo-modal"
+    :footer="null"
+    :maskClosable="false"
+    title="新增调拨退货"
+    v-model="isShow"
+    @cancle="isShow = false"
+    :width="800">
+    <a-spin :spinning="spinning" tip="Loading...">
+      <a-form-model
+        id="allocateBill-basicInfo-form"
+        ref="ruleForm"
+        :model="form"
+        :rules="rules"
+        :label-col="formItemLayout.labelCol"
+        :wrapper-col="formItemLayout.wrapperCol"
+      >
+        <a-form-model-item label="调拨退货对象" prop="targetType">
+          <v-select
+            code="TARGET_TYPE"
+            showType="radio"
+            id="allocateBill-basicInfo-targetType"
+            v-model="form.targetType"
+            @change="targetTypeChange"
+            allowClear
+            placeholder="请选择调拨退货对象"></v-select>
+        </a-form-model-item>
+        <a-form-model-item label="调拨退货对象名称" :prop="isDealer ? 'targetSn' : 'targetName'">
+          <a-select
+            v-if="isDealer"
+            show-search
+            id="allocateBill-basicInfo-dealerName"
+            v-model="form.targetSn"
+            placeholder="请输入名称搜索经销商"
+            :filter-option="false"
+            :not-found-content="fetching ? undefined : null"
+            @search="fetchUser"
+            @change="handleChange"
+          >
+            <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" />
+        </a-form-model-item>
+        <a-form-model-item label="调拨退货类型" prop="allocateReturnTypeSn">
+          <a-select id="allocateBill-basicInfo-allocateReturnTypeSn" v-model="form.allocateReturnTypeSn" placeholder="请选择调拨退货类型" allowClear >
+            <a-select-option v-for="item in allocateTypeList" :key="item.allocateTypeSn" :value="item.allocateTypeSn">{{ item.name }}</a-select-option>
+          </a-select>
+        </a-form-model-item>
+        <a-form-model-item label="是否抓单" prop="grabFlag">
+          <v-select
+            code="FLAG"
+            showType="radio"
+            :disabled="form.targetType !== 'DEALER'"
+            id="allocateBill-basicInfo-grabFlag"
+            v-model="form.grabFlag"
+            allowClear
+            placeholder="请选择"></v-select>
+        </a-form-model-item>
+        <a-form-model-item label="备注" prop="remark">
+          <a-textarea id="allocateBill-basicInfo-remark" :maxLength="120" v-model="form.remarks" placeholder="请输入备注(最多120个字符)" allowClear />
+        </a-form-model-item>
+      </a-form-model>
+      <div class="btn-cont">
+        <a-button type="primary" id="allocateBill-basicInfo-modal-save" @click="handleSave">保存</a-button>
+        <a-button id="allocateBill-basicInfo-modal-back" @click="isShow = false" style="margin-left: 15px;">取消</a-button>
+      </div>
+    </a-spin>
+  </a-modal>
+</template>
+
+<script>
+import { commonMixin } from '@/utils/mixin'
+import debounce from 'lodash/debounce'
+import { VSelect } from '@/components'
+import { allocateReturnSave, allocateReturnQueryBySn } from '@/api/allocateReturn'
+import { dealerSubareaScopeList } from '@/api/dealer'
+import { allocateTypeAllList } from '@/api/allocateType'
+export default {
+  name: 'TransferOutBasicInfoModal',
+  components: { VSelect },
+  mixins: [commonMixin],
+  props: {
+    openModal: {
+      //  弹框显示状态
+      type: Boolean,
+      default: false
+    }
+  },
+  data () {
+    this.fetchUser = debounce(this.fetchUser, 800)
+    return {
+      isShow: this.openModal, //  是否打开弹框
+      spinning: false,
+      formItemLayout: {
+        labelCol: { span: 4 },
+        wrapperCol: { span: 20 }
+      },
+      form: {
+        targetType: 'DEALER',
+        targetSn: undefined,
+        targetName: '',
+        allocateReturnTypeSn: undefined,
+        grabFlag: '1',
+        remarks: ''
+      },
+      rules: {
+        targetType: [{ required: true, message: '请选择调往对象', trigger: 'change' }],
+        targetSn: [{ required: true, message: '请选择调往对象名称', trigger: 'change' }],
+        targetName: [{ required: true, message: '请输入调往对象名称', trigger: 'blur' }],
+        allocateReturnTypeSn: [{ required: true, message: '请选择调拨类型', trigger: 'change' }],
+        grabFlag: [{ required: true, message: '请选择是否抓单', trigger: 'change' }]
+      },
+      fetching: false,
+      dealerData: [], //  经销商  下拉数据
+      allocateTypeList: [] //  调拨类型
+    }
+  },
+  computed: {
+    // 当前所选调往对象是否为经销商
+    isDealer () {
+      return this.form.targetType == 'DEALER'
+    }
+  },
+  methods: {
+    // 搜索经销商
+    fetchUser (value) {
+      console.log('fetching user', value)
+      this.fetching = true
+      dealerSubareaScopeList({ nameLike: value, pageNo: 1, pageSize: 20 }).then(res => {
+        if (res.status == 200) {
+          this.dealerData = res.data && res.data.list ? res.data.list : []
+          this.fetching = false
+        } else {
+          this.dealerData = []
+          this.fetching = false
+        }
+      })
+    },
+    // 调往对象名称  change
+    handleChange (value) {
+      const ind = this.dealerData.findIndex(item => item.dealerSn == value)
+      this.form.targetName = this.dealerData[ind].dealerName
+    },
+    // 基本信息
+    getDetail (data, flag) {
+      const _this = this
+      this.spinning = true
+      allocateReturnQueryBySn({ allocateReturnSn: data.allocateReturnSn }).then(res => {
+        if (res.status == 200) {
+          if (flag) {
+            _this.isShow = false
+            _this.$emit('ok', res.data)
+          }
+        }
+        this.spinning = false
+      })
+    },
+    //  保存
+    handleSave () {
+      const _this = this
+      this.$refs.ruleForm.validate(valid => {
+        if (valid) {
+          const form = JSON.parse(JSON.stringify(_this.form))
+          _this.spinning = true
+          allocateReturnSave(form).then(res => {
+            if (res.status == 200) {
+              _this.$message.success(res.message)
+              _this.getDetail(res.data, true)
+            } else {
+              _this.spinning = false
+            }
+          })
+        } else {
+          console.log('error submit!!')
+          return false
+        }
+      })
+    },
+    // 调往对象  change
+    targetTypeChange (val) {
+      console.log(val)
+      this.$refs.ruleForm.resetFields()
+      this.form.targetSn = undefined
+      this.form.targetName = ''
+      this.form.targetType = val
+      if (val !== 'DEALER') {
+        this.form.grabFlag = '0'
+      }
+    },
+    //  调拨类型
+    getAllocateTypeAllList () {
+      allocateTypeAllList().then(res => {
+        if (res.status == 200) {
+          this.allocateTypeList = res.data
+        } else {
+          this.allocateTypeList = []
+        }
+      })
+    },
+    resetForm () {
+      this.$refs.ruleForm.resetFields()
+      this.form = {
+        targetType: 'DEALER',
+        targetSn: undefined,
+        targetName: '',
+        allocateReturnTypeSn: undefined,
+        grabFlag: '1',
+        remarks: ''
+      }
+    }
+  },
+  watch: {
+    //  父页面传过来的弹框状态
+    openModal (newValue, oldValue) {
+      this.isShow = newValue
+    },
+    //  重定义的弹框状态
+    isShow (newValue, oldValue) {
+      if (!newValue) {
+        this.resetForm()
+        this.$emit('close')
+      } else {
+        this.getAllocateTypeAllList()
+      }
+    }
+  }
+}
+</script>
+
+<style lang="less">
+.allocateBill-basicInfo-modal {
+	.ant-modal-body {
+		padding: 40px 40px 24px;
+	}
+	.btn-cont {
+		text-align: center;
+		margin: 35px 0 10px;
+	}
+}
+</style>

+ 298 - 0
src/views/allocationManagement/transferReturn/check.vue

@@ -0,0 +1,298 @@
+<template>
+  <div class="salesReturnCheck-wrap">
+    <a-spin :spinning="spinning" tip="Loading...">
+      <a-page-header :ghost="false" :backIcon="false" class="salesReturnCheck-back" >
+        <!-- 自定义的二级文字标题 -->
+        <template slot="subTitle">
+          <a id="salesReturnCheck-back-btn" href="javascript:;" @click="handleBack"><a-icon type="left" /> 返回列表</a>
+          <span style="margin: 0 15px;color: #666;">调拨退货对象名称:{{ ordeDetail&&ordeDetail.targetName || '--' }} ({{ ordeDetail&&ordeDetail.grabFlag==1 ? '抓单' : '不抓单' }})</span>
+        </template>
+      </a-page-header>
+      <a-card size="small" :bordered="false" class="salesReturnCheck-cont">
+        <div>
+          <a-button type="primary" :loading="loading" class="button-info" @click="backStock('BATCH_BACK','批量返库')">批量返库</a-button>
+          <a-button v-if="grabFlag==1" type="default" :loading="loading" style="margin-right: 15px;" @click="backStock('BATCH_BAD','批量坏件')">批量坏件</a-button>
+          <span>已选 {{ rowSelectionInfo&&rowSelectionInfo.selectedRows.length }} 项</span>
+        </div>
+        <!-- 已选配件列表 -->
+        <s-table
+          class="sTable"
+          ref="table"
+          :style="{ height: tableHeight+84.5+'px' }"
+          size="small"
+          rowKeyName="ids"
+          :rowKey="record => record.ids"
+          :row-selection="{ columnWidth: 40 }"
+          @rowSelection="rowSelectionFun"
+          :columns="columns"
+          :data="loadData"
+          :scroll="{ y: tableHeight }"
+          :defaultLoadData="false"
+          bordered>
+          <!-- 返库数量 -->
+          <template slot="backStockQty" slot-scope="text, record">
+            <a-input-number
+              v-if="grabFlag==0"
+              size="small"
+              v-model="record.backStockQty"
+              :precision="0"
+              :min="0"
+              :max="record.returnQty"
+              placeholder="请输入"
+              @blur="e => onCellBlur(e.target.value, record)"
+              style="width: 100%;" />
+            <span v-else>{{ record.backStockQty }}</span>
+          </template>
+        </s-table>
+      </a-card>
+    </a-spin>
+    <div class="affix-cont">
+      <a-button
+        size="large"
+        style="padding: 0 60px;"
+        :disabled="spinning"
+        type="primary"
+        class="button-primary"
+        @click="handleSubmit()"
+        id="salesReturn-handleSubmit">提交</a-button>
+    </div>
+  </div>
+</template>
+
+<script>
+import { commonMixin } from '@/utils/mixin'
+import { STable, VSelect } from '@/components'
+import {
+  allocReturnDetailQueryPage,
+  allocateReturnQueryBySn,
+  allocateReturnCheckSubmit,
+  allocateReturnCheck
+} from '@/api/allocateReturn'
+export default {
+  name: 'TransferReturnCheck',
+  mixins: [commonMixin],
+  components: {
+    STable,
+    VSelect
+  },
+  data () {
+    return {
+      spinning: false,
+      tableHeight: 0, // 表格高度
+      orderSn: null,
+      grabFlag: null,
+      disabled: false,
+      isInster: false, // 是否正在添加产品
+      ordeDetail: { discountAmount: 0 },
+      loading: false,
+      // 已选产品
+      dataSource: [],
+      productForm: {
+        allocateReturnSn: ''
+      },
+      chooseLoadData: [],
+      // 加载数据方法 必须为 Promise 对象
+      loadData: parameter => {
+        this.disabled = true
+        // 查询总计
+        this.productForm.allocateReturnSn = this.$route.params.sn
+        return allocReturnDetailQueryPage(Object.assign(parameter, this.productForm)).then(res => {
+          let data
+          if (res.status == 200) {
+            data = res.data
+            const no = (data.pageNo - 1) * data.pageSize
+            for (var i = 0; i < data.list.length; i++) {
+              data.list[i].no = no + i + 1
+              data.list[i].ids = data.list[i].no + '-' + data.list[i].productSn
+              data.list[i].badQty = (data.list[i].badQty || data.list[i].badQty == 0) ? data.list[i].badQty : data.list[i].returnQty
+              data.list[i].backStockQty = data.list[i].backStockQty || 0
+              data.list[i].backStockQtyBackups = data.list[i].backStockQty
+            }
+            this.disabled = false
+            this.chooseLoadData = data.list
+          }
+          return data
+        })
+      },
+      rowSelectionInfo: null
+    }
+  },
+  computed: {
+    columns () {
+      const arr = [
+        { title: '序号', dataIndex: 'no', width: '4%', align: 'center' },
+        { title: '产品编码', dataIndex: 'product.code', align: 'center', width: '23%', customRender: function (text) { return text || '--' } },
+        { title: '产品名称', dataIndex: 'product.name', width: '25%', align: 'left', customRender: function (text) { return text || '--' }, ellipsis: true },
+        { 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 : '--') } }
+      ]
+      console.log(this.grabFlag)
+      if (this.grabFlag == 1) { //  抓单
+        arr.splice(1, 0, { title: '调拨单号', dataIndex: 'allocateNo', width: '12%', align: 'center', customRender: function (text) { return text || '--' } })
+      }
+      return arr
+    }
+  },
+  methods: {
+    // 表格选中项
+    rowSelectionFun (obj) {
+      this.rowSelectionInfo = obj || null
+    },
+    //  返回列表
+    handleBack () {
+      this.$router.push({ name: 'transferReturnList', query: { closeLastOldTab: true } })
+    },
+    // 批量返库
+    backStock (type, msg) {
+      const _this = this
+      if (!_this.rowSelectionInfo || (_this.rowSelectionInfo && _this.rowSelectionInfo.selectedRowKeys.length < 1)) {
+        _this.$message.warning('请先选择产品!')
+        return
+      }
+      this.$confirm({
+        title: '提示',
+        content: '确认要' + msg + '吗?',
+        centered: true,
+        onOk () {
+          const obj = []
+          _this.rowSelectionInfo && _this.rowSelectionInfo.selectedRows.map(item => {
+            // 抓单
+            if (_this.grabFlag == 1) {
+              obj.push({
+                allocateSn: item.allocateSn,
+                productSn: item.productSn,
+                price: item.price
+              })
+            } else {
+              obj.push({
+                allocateReturnDetailSn: item.allocateReturnDetailSn
+              })
+            }
+          })
+          _this.submitCheck(obj, type)
+        }
+      })
+    },
+    // 不抓单,修改返库数量
+    onCellBlur (val, record) {
+      //  光标移出,值发生改变再调用编辑接口
+      if (val && val != record.backStockQtyBackups) {
+        this.submitCheck([{
+          allocateReturnDetailSn: record.allocateReturnDetailSn,
+          backStockQty: record.backStockQty
+        }], 'CUSTOM')
+      } else {
+        record.backStockQty = record.backStockQtyBackups
+      }
+    },
+    // 修改坏件或退货数量
+    submitCheck (data, allocateCheckType) {
+      this.loading = true
+      this.spinning = true
+      allocateReturnCheck({
+        allocateReturnSn: this.orderSn,
+        allocateCheckType: allocateCheckType,
+        list: data
+      }).then(res => {
+        if (res.status == 200) {
+          this.$refs.table.clearSelected()
+          this.resetSearchForm(false)
+          this.$message.success(res.message)
+        }
+        this.loading = false
+        this.spinning = false
+      })
+    },
+    // 获取单据详细
+    getOrderDetail () {
+      allocateReturnQueryBySn({ allocateReturnSn: this.orderSn }).then(res => {
+        this.ordeDetail = res.data || null
+      })
+    },
+    //  重置
+    resetSearchForm (flag) {
+      this.$refs.table.refresh(!!flag)
+      this.getOrderDetail()
+    },
+    // 品检提交
+    handleSubmit () {
+      this.spinning = true
+      allocateReturnCheckSubmit({ allocateReturnSn: this.orderSn }).then(res => {
+        if (res.status == 200) {
+          this.handleBack()
+          this.$message.success(res.message)
+          this.spinning = false
+        } else {
+          this.spinning = false
+        }
+      })
+    },
+    pageInit () {
+      const _this = this
+      this.$nextTick(() => { // 页面渲染完成后的回调
+        _this.setTableH()
+      })
+      this.orderSn = this.$route.params.sn
+      this.grabFlag = this.$route.params.grabFlag
+      this.$refs.table.clearTable()
+      this.getOrderDetail()
+    },
+    setTableH () {
+      this.tableHeight = window.innerHeight - 340
+    }
+  },
+  mounted () {
+    if (!this.$store.state.app.isNewTab) { // 页签刷新时调用
+      this.$refs.table.refresh(true)
+      this.pageInit()
+    }
+  },
+  activated () {
+    // 如果是新页签打开或者进入新的子页(例:存在列表第2条数据编辑页页签时再打开第4条数据的编辑页),则重置当前页面
+    if (this.$store.state.app.isNewTab || !this.$store.state.app.isNewSubTab) {
+      this.$refs.table.refresh(true)
+      this.pageInit()
+    }
+  },
+  beforeRouteEnter (to, from, next) {
+    next(vm => {})
+  }
+}
+</script>
+
+<style lang="less">
+  .salesReturnCheck-wrap{
+    position: relative;
+    height: 100%;
+    padding-bottom: 51px;
+    box-sizing: border-box;
+    >.ant-spin-nested-loading{
+      overflow-y: scroll;
+      height: 100%;
+    }
+    .salesReturnCheck-cont{
+      margin-top: 10px;
+      .sTable{
+        margin-top: 10px;
+      }
+      .total-bar{
+        display: flex;
+        align-items: center;
+        justify-content: space-between;
+        > div{
+          &:last-child{
+            display: flex;
+            align-items: center;
+            justify-content: space-between;
+            > div{
+              padding: 0 10px;
+            }
+          }
+        }
+      }
+    }
+  }
+</style>

+ 190 - 0
src/views/allocationManagement/transferReturn/chooseImportModal.vue

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

+ 190 - 0
src/views/allocationManagement/transferReturn/detail.vue

@@ -0,0 +1,190 @@
+<template>
+  <div class="allocateBillDetail-wrap">
+    <a-spin :spinning="spinning" tip="Loading...">
+      <a-page-header :ghost="false" :backIcon="false" class="allocateBillDetail-back" :style="{ padding: pageType=='pages' ? '16px 24px' : '0px 24px' }" >
+        <!-- 自定义的二级文字标题 -->
+        <template slot="subTitle" v-if="pageType=='pages'">
+          <a id="allocateBillDetail-back-btn" href="javascript:;" @click="handleBack"><a-icon type="left" /> 返回列表</a>
+          <a-button
+            v-if="isEdit"
+            type="primary"
+            size="small"
+            style="background-color: #1890ff;margin-left: 20px;border: #1890ff;"
+            id="allocateBillDetail-edit-btn"
+            @click.stop="handleEdit">编辑</a-button>
+        </template>
+        <!-- 操作区,位于 title 行的行尾 -->
+        <template slot="extra" v-if="pageType=='pages'">
+          <print :params="{allocateReturnSn: $route.params.sn || outBizSn}" :disabled="localDataSource.length==0" @loading="spinning=true" @unloading="spinning=false"></print>
+        </template>
+      </a-page-header>
+      <a-card size="small" :bordered="false" class="allocateBillDetail-cont">
+        <a-collapse :activeKey="['1']">
+          <a-collapse-panel key="1" header="基础信息">
+            <a-descriptions :column="3">
+              <a-descriptions-item label="调拨退货单号">{{ (basicInfoData&&basicInfoData.allocateReturnNo) || '--' }}</a-descriptions-item>
+              <a-descriptions-item label="调拨退货对象">{{ (basicInfoData&&basicInfoData.targetTypeDictValue) || '--' }}</a-descriptions-item>
+              <a-descriptions-item label="调拨退货对象名称">{{ (basicInfoData&&basicInfoData.targetName) || '--' }}</a-descriptions-item>
+              <a-descriptions-item label="调拨退货类型">{{ (basicInfoData&&basicInfoData.allocateReturnTypeName) || '--' }}</a-descriptions-item>
+              <a-descriptions-item label="是否抓单">{{ basicInfoData&&basicInfoData.grabFlagDictValue || '--' }}</a-descriptions-item>
+              <a-descriptions-item label="业务状态">{{ (basicInfoData&&basicInfoData.stateDictValue) || '--' }}</a-descriptions-item>
+              <a-descriptions-item label="备注">{{ (basicInfoData&&basicInfoData.remarks) || '--' }}</a-descriptions-item>
+            </a-descriptions>
+          </a-collapse-panel>
+        </a-collapse>
+      </a-card>
+      <a-card size="small" :bordered="false" class="allocateBillDetail-cont">
+        <!-- 总计 -->
+        <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>;
+          </div>
+        </a-alert>
+        <!-- 列表 -->
+        <s-table
+          class="sTable"
+          ref="table"
+          size="small"
+          :rowKey="(record) => record.id"
+          :columns="columns"
+          :data="loadData"
+          :defaultLoadData="false"
+          bordered>
+        </s-table>
+      </a-card>
+    </a-spin>
+  </div>
+</template>
+
+<script>
+import { commonMixin } from '@/utils/mixin'
+import { STable, VSelect } from '@/components'
+import print from './print.vue'
+import { allocReturnDetailQueryPage, allocateReturnQueryBySn } from '@/api/allocateReturn'
+export default {
+  name: 'TransferReturnDetail',
+  mixins: [commonMixin],
+  components: { STable, VSelect, print },
+  props: {
+    outBizSn: { //  有值则为弹框,无值则为页面
+      type: [Number, String],
+      default: ''
+    },
+    pageType: {
+      type: String,
+      default: 'pages'
+    }
+  },
+  data () {
+    return {
+      spinning: false,
+      // 加载数据方法 必须为 Promise 对象
+      loadData: parameter => {
+        this.spinning = true
+        return allocReturnDetailQueryPage(Object.assign(parameter, { allocateReturnSn: this.outBizSn || this.$route.params.sn })).then(res => {
+          let data
+          if (res.status == 200) {
+            data = res.data
+            const no = (data.pageNo - 1) * data.pageSize
+            for (var i = 0; i < data.list.length; i++) {
+              data.list[i].no = no + i + 1
+            }
+            this.localDataSource = data.list
+          }
+          this.spinning = false
+          return data
+        })
+      },
+      basicInfoData: null, //  基本信息
+      localDataSource: [],
+      openModal: false,
+      nowType: null
+    }
+  },
+  computed: {
+    isEdit () {
+      return this.basicInfoData && ((this.basicInfoData.state == 'WAIT_SUBMIT') || (this.basicInfoData.state == 'FINANCIAL_REJECT') || (this.basicInfoData.state == 'AUDIT_REJECT')) && this.$hasPermissions('B_transferReturnEdit')
+    },
+    columns () {
+      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 : '--') } }
+      ]
+
+      if (this.basicInfoData && this.basicInfoData.grabFlag == '1') {
+        arr.splice(1, 0, { title: '调拨单号', dataIndex: 'allocateNo', width: '10%', align: 'center', customRender: function (text) { return text || '--' } })
+      }
+      return arr
+    }
+  },
+  methods: {
+    //  返回列表
+    handleBack () {
+      this.$router.push({ name: 'transferReturnList', query: { closeLastOldTab: true } })
+    },
+    // 基本信息
+    getDetail () {
+      allocateReturnQueryBySn({ allocateReturnSn: this.outBizSn || this.$route.params.sn }).then(res => {
+        if (res.status == 200) {
+          this.basicInfoData = res.data
+        } else {
+          this.basicInfoData = null
+        }
+      })
+    },
+    //  编辑
+    handleEdit () {
+      const row = this.basicInfoData
+      this.$router.push({ name: row.grabFlag == 1 ? 'transferReturnGrpEdit' : 'transferReturnEdit', params: { sn: row.allocateReturnSn, targetType: row.targetType, dealerLevel: row.dealerLevel } })
+    },
+    pageInit () {
+      if (this.outBizSn || this.$route.params.sn) {
+        this.$refs.table.refresh(true)
+        this.getDetail()
+      }
+    }
+  },
+  mounted () {
+    if (!this.$store.state.app.isNewTab || this.outBizSn) { // 页签刷新 或 为弹框时调用
+      this.pageInit()
+    }
+  },
+  activated () {
+    // 如果是新页签打开或者进入新的子页(例:存在列表第2条数据编辑页页签时再打开第4条数据的编辑页),则重置当前页面
+    if (this.$store.state.app.isNewTab || !this.$store.state.app.isNewSubTab) {
+      this.pageInit()
+    }
+  },
+  watch: {
+    outBizSn (newValue, oldValue) {
+      if (newValue) {
+        this.pageInit()
+      }
+    }
+  },
+  beforeRouteEnter (to, from, next) {
+    next(vm => {})
+  }
+}
+</script>
+
+<style lang="less">
+  .allocateBillDetail-wrap{
+    .allocateBillDetail-back{
+      margin-bottom: 10px;
+    }
+    .allocateBillDetail-cont{
+      margin-bottom: 10px;
+    }
+  }
+</style>

+ 590 - 0
src/views/allocationManagement/transferReturn/edit.vue

@@ -0,0 +1,590 @@
+<template>
+  <div class="allocateBillEdit-wrap">
+    <!-- <a-spin :spinning="spinning" tip="Loading..."> -->
+    <div class="ant-spin-nested-loading">
+      <a-page-header :ghost="false" :backIcon="false" class="allocateBillEdit-back" >
+        <!-- 自定义的二级文字标题 -->
+        <template slot="subTitle">
+          <a id="allocateBillEdit-back-btn" href="javascript:;" @click="handleBack"><a-icon type="left" /> 返回列表</a>
+        </template>
+        <!-- 操作区,位于 title 行的行尾 -->
+        <template slot="extra">
+          <print :params="{allocateReturnSn: $route.params.sn}" :disabled="localDataSource.length==0" @loading="spinning=true" @unloading="spinning=false"></print>
+        </template>
+      </a-page-header>
+      <a-card size="small" :bordered="false" v-if="basicInfoData" class="allocateBillEdit-cont">
+        <a-collapse :activeKey="['0']">
+          <a-collapse-panel key="0" header="基础信息">
+            <a-descriptions :column="3">
+              <a-descriptions-item label="调拨退货单号">{{ (basicInfoData&&basicInfoData.allocateReturnNo) || '--' }}</a-descriptions-item>
+              <a-descriptions-item label="调拨退货对象">{{ (basicInfoData&&basicInfoData.targetTypeDictValue) || '--' }}</a-descriptions-item>
+              <a-descriptions-item label="调拨退货对象名称">{{ (basicInfoData&&basicInfoData.targetName) || '--' }}</a-descriptions-item>
+              <a-descriptions-item label="调拨退货类型">
+                <AllocateType id="allocateEdit-allocateReturnTypeSn" style="width: 200px;" @change="changeAllocateType" v-model="basicInfoData.allocateReturnTypeSn"></AllocateType>
+              </a-descriptions-item>
+              <a-descriptions-item label="是否抓单">{{ (basicInfoData&&basicInfoData.grabFlagDictValue) || '--' }}</a-descriptions-item>
+              <a-descriptions-item label="业务状态">{{ (basicInfoData&&basicInfoData.stateDictValue) || '--' }}</a-descriptions-item>
+              <a-descriptions-item label="备注">
+                {{ (basicInfoData&&basicInfoData.remarks) }}
+                <a-icon type="form" title="编辑备注" @click="editRemark = true" style="color: dodgerblue;font-size: 14px;" />
+              </a-descriptions-item>
+            </a-descriptions>
+          </a-collapse-panel>
+        </a-collapse>
+      </a-card>
+      <!-- 选择产品 -->
+      <a-card size="small" :bordered="false" class="allocateBillEdit-cont">
+        <a-collapse :activeKey="['1']">
+          <a-collapse-panel key="1" :forceRender="true" header="选择产品">
+            <!-- 筛选条件 -->
+            <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-form-item label="产品编码" prop="productCode">
+                      <a-input id="allocateBillEdit-productCode" v-model.trim="queryParam.productCode" placeholder="请输入产品编码" allowClear />
+                    </a-form-item>
+                  </a-col>
+                  <a-col :md="6" :sm="24">
+                    <a-form-item label="产品名称" prop="productName">
+                      <a-input id="allocateBillEdit-productName" v-model.trim="queryParam.productName" placeholder="请输入产品名称" allowClear />
+                    </a-form-item>
+                  </a-col>
+                  <a-col :md="6" :sm="24" style="margin-bottom: 10px;">
+                    <a-button type="primary" @click="$refs.table.refresh(true)" :disabled="disabled" id="storeTransferOutList-refresh">查询</a-button>
+                    <a-button style="margin-left: 8px" @click="resetSearchForm" :disabled="disabled" id="storeTransferOutList-reset">重置</a-button>
+                  </a-col>
+                </a-row>
+              </a-form>
+            </div>
+            <!-- 列表 -->
+            <s-table
+              class="sTable"
+              ref="table"
+              size="small"
+              index="0"
+              tableId="table1"
+              :rowKey="(record) => record.stockSn"
+              :columns="columns"
+              :customRow="handleClickRow"
+              :data="loadData"
+              :scroll="{ y: 300 }"
+              :defaultLoadData="false"
+              bordered>
+              <!-- 退货单价 -->
+              <template slot="returnPrice" slot-scope="text, record">
+                <div @dblclick.stop>
+                  <a-input-number
+                    size="small"
+                    v-model="record.productPrice"
+                    :precision="2"
+                    :min="0"
+                    :max="999999"
+                    placeholder="请输入"
+                    style="width: 100%;" />
+                </div>
+              </template>
+              <!-- 退货数量 -->
+              <template slot="returnQty" slot-scope="text, record">
+                <div @dblclick.stop>
+                  <a-input-number
+                    size="small"
+                    v-model="record.qty"
+                    :precision="0"
+                    :min="1"
+                    :max="999999"
+                    placeholder="请输入"
+                    style="width: 100%;" />
+                </div>
+              </template>
+              <!-- 操作 -->
+              <template slot="action" slot-scope="text, record">
+                <a-button
+                  size="small"
+                  type="link"
+                  v-if="record.lastStockCost"
+                  class="button-primary"
+                  @click="handleAdd(record)"
+                  id="allocateBillEdit-add-btn">添加</a-button>
+                <span v-else>--</span>
+              </template>
+            </s-table>
+          </a-collapse-panel>
+        </a-collapse>
+      </a-card>
+      <!-- 已选产品 -->
+      <a-card size="small" :bordered="false" class="allocateBillEdit-cont">
+        <a-collapse :activeKey="['2']">
+          <a-collapse-panel key="2" :forceRender="true" header="已选产品">
+            <!-- 总计 -->
+            <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>
+              </div>
+            </a-alert>
+            <!-- 筛选条件 -->
+            <a-row :gutter="15">
+              <a-col :span="17">
+                <div class="table-page-search-wrapper">
+                  <a-form layout="inline" @keyup.enter.native="$refs.chooseTable.refresh(true)">
+                    <a-row :gutter="15">
+                      <a-col :md="9" :sm="24">
+                        <a-form-item label="产品编码" prop="productCode">
+                          <a-input id="editGrap-productCode" v-model.trim="chooseQueryParam.productCode" placeholder="请输入产品编码" allowClear />
+                        </a-form-item>
+                      </a-col>
+                      <a-col :md="9" :sm="24">
+                        <a-form-item label="产品名称" prop="productName">
+                          <a-input id="editGrap-productName" v-model.trim="chooseQueryParam.productName" placeholder="请输入产品名称" allowClear />
+                        </a-form-item>
+                      </a-col>
+                      <a-col :md="6" :sm="24" style="margin-bottom: 10px;">
+                        <a-button type="primary" @click="$refs.chooseTable.refresh(true)" :disabled="chooseDisabled" id="storeTransferOutList-refresh">查询</a-button>
+                        <a-button style="margin-left: 8px" @click="chooseResetSearchForm" :disabled="chooseDisabled" id="storeTransferOutList-reset">重置</a-button>
+                      </a-col>
+                    </a-row>
+                  </a-form>
+                </div>
+              </a-col>
+              <a-col :span="7" style="text-align: right;">
+                <!-- <a-button size="small" id="editGrap-import-btn" @click="openGuideModal=true">导入产品</a-button> -->
+                <!-- <a-button size="small" type="danger" style="margin-left: 5px" @click.stop="handleDel('', 'all')" id="chainTransferOutEdit-del-all-btn">整单删除</a-button> -->
+              </a-col>
+            </a-row>
+            <!-- 列表 -->
+            <s-table
+              class="sTable"
+              ref="chooseTable"
+              size="small"
+              index="1"
+              tableId="table2"
+              :rowKey="(record) => record.id"
+              :columns="chooseColumns"
+              :data="chooseLoadData"
+              :scroll="{ y: 300 }"
+              :defaultLoadData="false"
+              bordered>
+              <!-- 退货单价 -->
+              <template slot="returnPrice" slot-scope="text, record">
+                <a-input-number
+                  size="small"
+                  v-model="record.price"
+                  :precision="2"
+                  :min="0"
+                  :max="999999"
+                  @blur="e => priceChange(e.target.value, record)"
+                  placeholder="请输入"
+                  style="width: 100%;" />
+              </template>
+              <!-- 退货数量 -->
+              <template slot="returnQty" slot-scope="text, record">
+                <a-input-number
+                  size="small"
+                  v-model="record.returnQty"
+                  :precision="0"
+                  :min="1"
+                  :max="999999"
+                  @blur="e => qtyBlur(e.target.value, record)"
+                  placeholder="请输入"
+                  style="width: 100%;" />
+              </template>
+              <!-- 操作 -->
+              <template slot="action" slot-scope="text, record">
+                <a-button size="small" type="link" class="button-error" @click="handleDel(record)" id="allocateBillEdit-del-btn">删除</a-button>
+              </template>
+            </s-table>
+          </a-collapse-panel>
+        </a-collapse>
+      </a-card>
+    <!-- </a-spin> -->
+    </div>
+    <div class="affix-cont">
+      <a-button
+        type="primary"
+        id="allocateBillEdit-submit"
+        size="large"
+        :disabled="spinning"
+        class="button-primary"
+        @click="handleSubmit"
+        style="padding: 0 60px;">提交</a-button>
+    </div>
+    <!-- 导入产品 -->
+    <!-- <importGuideModal :openModal="openGuideModal" :params="{allocateReturnSn: $route.params.sn}" @close="openGuideModal=false" @ok="handleGuideOk" /> -->
+    <!-- 修改基础信息 -->
+    <a-modal
+      centered
+      wrapClassName="allocateBill-editRemark-modal"
+      v-if="basicInfoData"
+      :footer="null"
+      :maskClosable="false"
+      title="修改备注"
+      v-model="editRemark"
+      @cancle="editRemark = false"
+      :width="600">
+      <a-textarea
+        v-model="basicInfoData.remarks"
+        placeholder="请输入备注(最多120个字符)"
+        :maxLength="120"
+        :auto-size="{ minRows: 3, maxRows: 5 }"
+      />
+      <div class="btn-cont">
+        <a-button type="primary" id="allocateBill-basicInfo-modal-save" @click="handleEditRemark">保存</a-button>
+        <a-button id="allocateBill-basicInfo-modal-back" @click="editRemark = false" style="margin-left: 15px;">取消</a-button>
+      </div>
+    </a-modal>
+  </div>
+</template>
+
+<script>
+import { commonMixin } from '@/utils/mixin'
+import { STable, VSelect } from '@/components'
+// import ImportGuideModal from './importGuideModal.vue'
+import print from './print.vue'
+import { queryStockProductPage } from '@/api/stock'
+import AllocateType from '@/views/common/allocateType.js'
+import {
+  allocateReturnSave,
+  allocReturnDetailQueryPage,
+  allocateReturnQueryBySn,
+  allocReturnDetailInsert,
+  allocReturnDetailUpdate,
+  allocateReturnSubmit,
+  allocReturnDetailDelete
+  // allocateBillBatchInsert
+} from '@/api/allocateReturn'
+
+export default {
+  name: 'TransferReturnEdit',
+  mixins: [commonMixin],
+  components: { STable, VSelect, print, AllocateType },
+  data () {
+    return {
+      spinning: false,
+      queryParam: {
+        productCode: '',
+        productName: '',
+        productOrigCode: ''
+      },
+      chooseQueryParam: {
+        productCode: '',
+        productName: ''
+      },
+      editRemark: false,
+      disabled: false, //  查询、重置按钮是否可操作
+      loading: false,
+      chooseDisabled: false, //  查询、重置按钮是否可操作
+      advanced: false, // 高级搜索 展开/关闭
+      // 加载数据方法 必须为 Promise 对象
+      loadData: parameter => {
+        this.disabled = true
+        const dealerLevel = this.$route.params.dealerLevel == 'OTHER' ? undefined : this.$route.params.dealerLevel
+        return queryStockProductPage(Object.assign(parameter, this.queryParam, { dealerLevel: dealerLevel == 0 ? '' : dealerLevel })).then(res => {
+          const data = res.data
+          const no = (data.pageNo - 1) * data.pageSize
+          for (var i = 0; i < data.list.length; i++) {
+            data.list[i].no = no + i + 1
+            data.list[i].qty = 1
+          }
+          this.loadDataSource = data.list || []
+          this.disabled = false
+          return data
+        })
+      },
+      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
+        const params = Object.assign(parameter, { product: { name: this.chooseQueryParam.productName, code: this.chooseQueryParam.productCode }, allocateReturnSn: this.$route.params.sn })
+        return allocReturnDetailQueryPage(params).then(res => {
+          const data = res.data
+          const no = (data.pageNo - 1) * data.pageSize
+          for (var i = 0; i < data.list.length; i++) {
+            data.list[i].no = no + i + 1
+            data.list[i].qtyBackups = data.list[i].returnQty
+            data.list[i].oldPrice = data.list[i].price
+          }
+          this.localDataSource = data.list || []
+          this.chooseDisabled = false
+          return data
+        })
+      },
+      basicInfoData: null, // 基本信息
+      openGuideModal: false, //  导入产品引导
+      openModal: false,
+      nowType: null
+    }
+  },
+  methods: {
+    // 修改备注
+    handleEditRemark () {
+      const _this = this
+      const params = _this.basicInfoData
+      allocateReturnSave(params).then(res => {
+        if (res.status == 200) {
+          _this.$message.success(res.message)
+          _this.getDetail(true)
+        } else {
+          _this.spinning = false
+        }
+      })
+      _this.editRemark = false
+    },
+    // 修改调拨类型
+    changeAllocateType (val) {
+      const _this = this
+      this.$confirm({
+        title: '提示',
+        content: '确定要更改调拨退货类型吗?',
+        centered: true,
+        onOk () {
+          _this.handleEditRemark()
+        },
+        onCancel () {
+          _this.getDetail(true)
+        }
+      })
+    },
+    //  重置
+    resetSearchForm () {
+      this.queryParam.productCode = ''
+      this.queryParam.productName = ''
+      this.queryParam.productOrigCode = ''
+      this.$refs.table.refresh(true)
+    },
+    // 双击快速添加
+    handleClickRow (record) {
+      return {
+        on: {
+          dblclick: (event) => {
+            this.handleAdd(record)
+          }
+        }
+      }
+    },
+    // 导入产品
+    // handleGuideOk (obj) {
+    //   allocateBillBatchInsert(obj).then(res => {
+    //     if (res.status == 200) {
+    //       this.$refs.chooseTable.refresh(true)
+    //     }
+    //   })
+    // },
+    // 已选产品  重置
+    chooseResetSearchForm () {
+      this.chooseQueryParam.productCode = ''
+      this.chooseQueryParam.productName = ''
+      this.$refs.chooseTable.refresh(true)
+    },
+    //  添加/编辑
+    handleAdd (row, isEdit, isRefresh) {
+      const params = {
+        allocateReturnSn: this.$route.params.sn,
+        productSn: row.productSn,
+        price: isEdit ? row.price : row.productPrice,
+        returnQty: isEdit ? row.returnQty : row.qty,
+        cost: isEdit ? row.cost : row.lastStockCost
+      }
+      const fun = isEdit ? allocReturnDetailUpdate : allocReturnDetailInsert
+      if (isEdit) { // 编辑
+        // 清空数量时,值应保持未清空前的值,因数量不可为空
+        if (!row.returnQty) {
+          row.returnQty = row.qtyBackups
+          return
+        }
+        if (!row.price) {
+          row.price = row.oldPrice
+          return
+        }
+        params.oldPrice = row.oldPrice
+        params.allocateReturnDetailSn = row.allocateReturnDetailSn
+      }
+      this.spinning = true
+      fun(params).then(res => {
+        if (res.status == 200) {
+          this.getDetail(true)
+          this.$message.success(res.message)
+          if (isRefresh != 'noRefresh') {
+            this.$refs.table.refresh()
+          }
+          this.$refs.chooseTable.refresh()
+          this.spinning = false
+        } else {
+          this.spinning = false
+        }
+      })
+    },
+    //  删除
+    handleDel (row, isAll) {
+      const _this = this
+      const content = isAll ? '删除后不可恢复,确定要进行整单删除吗?' : '删除后不可恢复,确定要进行删除吗?'
+      this.$confirm({
+        title: '提示',
+        content: content,
+        centered: true,
+        onOk () {
+          if (isAll) { //  整单删除
+            // allocateBillDetailDelAll({ sn: _this.$route.params.sn }).then(res => {
+            //   if (res.status == 200) {
+            //     _this.$message.success(res.message)
+            //     _this.refashPage()
+            //   }
+            // })
+          } else { //  单个删除
+            allocReturnDetailDelete({
+              allocateReturnSn: _this.$route.params.sn,
+              allocateDetailSn: row.allocateDetailSn,
+              price: row.price,
+              productSn: row.productSn
+            }).then(res => {
+              if (res.status == 200) {
+                _this.$message.success(res.message)
+                _this.refashPage()
+              }
+            })
+          }
+        }
+      })
+    },
+    //  提交
+    handleSubmit () {
+      const _this = this
+      if (this.localDataSource.length == 0) {
+        _this.$message.error('请先选择产品!')
+        return
+      }
+      _this.spinning = true
+      allocateReturnSubmit({ allocateReturnSn: this.$route.params.sn }).then(res => {
+        if (res.status == 200) {
+          this.$message.success(res.message)
+          setTimeout(() => {
+            _this.handleBack()
+            _this.spinning = false
+          }, 1000)
+        } else {
+          _this.spinning = false
+        }
+      })
+    },
+    // 基本信息
+    getDetail (flag) {
+      this.spinning = true
+      allocateReturnQueryBySn({ allocateReturnSn: this.$route.params.sn }).then(res => {
+        if (res.status == 200) {
+          this.basicInfoData = res.data
+          if (!flag) {
+            this.resetSearchForm()
+          }
+        } else {
+          this.basicInfoData = null
+        }
+        this.spinning = false
+      })
+    },
+    //  返回列表
+    handleBack () {
+      this.$router.push({ name: 'transferReturnList', query: { closeLastOldTab: true } })
+    },
+    // 已选产品 退货数量  blur
+    qtyBlur (val, record) {
+      //  光标移出,值发生改变再调用编辑接口
+      if (val != record.qtyBackups) {
+        this.handleAdd(record, 'edit')
+      }
+    },
+    // 已选产品 退货单价  change
+    priceChange (val, record) {
+      //  光标移出,值发生改变再调用编辑接口
+      if (val != record.oldPrice) {
+        this.handleAdd(record, 'edit', 'noRefresh')
+      }
+    },
+    // 刷新当前页面
+    refashPage () {
+      this.getDetail(true)
+      this.$refs.table.refresh()
+      this.$refs.chooseTable.refresh()
+    },
+    pageInit () {
+      this.refashPage()
+    }
+  },
+  mounted () {
+    if (!this.$store.state.app.isNewTab) { // 页签刷新时调用
+      this.pageInit()
+    }
+  },
+  activated () {
+    // 如果是新页签打开或者进入新的子页(例:存在列表第2条数据编辑页页签时再打开第4条数据的编辑页),则重置当前页面
+    if (this.$store.state.app.isNewTab || !this.$store.state.app.isNewSubTab) {
+      this.pageInit()
+    }
+  },
+  beforeRouteEnter (to, from, next) {
+    next(vm => {})
+  }
+}
+</script>
+
+<style lang="less">
+  .allocateBillEdit-wrap{
+    position: relative;
+    height: 100%;
+    box-sizing: border-box;
+    >.ant-spin-nested-loading{
+      overflow-y: scroll;
+      height: 100%;
+      padding-bottom: 51px;
+    }
+    .allocateBillEdit-back{
+      margin-bottom: 10px;
+    }
+    .allocateBillEdit-cont{
+      margin-bottom: 10px;
+      .sub-title{
+        font-size: 12px;
+        color: #808695;
+        margin-left: 10px;
+      }
+      .tag-txt{
+        font-size: 12px;
+        color: #ed1c24;
+      }
+      .edit-circle-btn{
+        margin-left: 15px;
+        i{
+          vertical-align: text-bottom;
+        }
+      }
+      .import-btn{
+        margin-left: 15px;
+      }
+    }
+  }
+  .allocateBill-editRemark-modal{
+    .btn-cont{
+      text-align: center;
+      padding-top: 20px;
+    }
+  }
+</style>

+ 578 - 0
src/views/allocationManagement/transferReturn/editGrp.vue

@@ -0,0 +1,578 @@
+<template>
+  <div class="editGrap-wrap">
+    <!-- <a-spin :spinning="spinning" tip="Loading..."> -->
+    <div class="ant-spin-nested-loading">
+      <a-page-header :ghost="false" :backIcon="false" class="editGrap-back" >
+        <!-- 自定义的二级文字标题 -->
+        <template slot="subTitle">
+          <a id="editGrap-back-btn" href="javascript:;" @click="handleBack"><a-icon type="left" /> 返回列表</a>
+        </template>
+        <!-- 操作区,位于 title 行的行尾 -->
+        <template slot="extra">
+          <print :params="{allocateReturnSn: $route.params.sn}" :disabled="localDataSource.length==0" @loading="spinning=true" @unloading="spinning=false"></print>
+        </template>
+      </a-page-header>
+      <a-card size="small" :bordered="false" v-if="basicInfoData" class="editGrap-cont">
+        <a-collapse :activeKey="['0']">
+          <a-collapse-panel key="0" header="基础信息">
+            <a-descriptions :column="3">
+              <a-descriptions-item label="调拨退货单号">{{ (basicInfoData&&basicInfoData.allocateReturnNo) || '--' }}</a-descriptions-item>
+              <a-descriptions-item label="调拨退货对象">{{ (basicInfoData&&basicInfoData.targetTypeDictValue) || '--' }}</a-descriptions-item>
+              <a-descriptions-item label="调拨退货对象名称">{{ (basicInfoData&&basicInfoData.targetName) || '--' }}</a-descriptions-item>
+              <a-descriptions-item label="调拨退货类型">
+                <AllocateType id="allocateEdit-allocateReturnTypeSn" style="width: 200px;" @change="changeAllocateType" v-model="basicInfoData.allocateReturnTypeSn"></AllocateType>
+              </a-descriptions-item>
+              <a-descriptions-item label="是否抓单">{{ (basicInfoData&&basicInfoData.grabFlagDictValue) || '--' }}</a-descriptions-item>
+              <a-descriptions-item label="业务状态">{{ (basicInfoData&&basicInfoData.stateDictValue) || '--' }}</a-descriptions-item>
+              <a-descriptions-item label="备注">
+                {{ (basicInfoData&&basicInfoData.remarks) }}
+                <a-icon type="form" title="编辑备注" @click="editRemark = true" style="color: dodgerblue;font-size: 14px;" />
+              </a-descriptions-item>
+            </a-descriptions>
+          </a-collapse-panel>
+        </a-collapse>
+      </a-card>
+      <!-- 选择产品 -->
+      <a-card size="small" :bordered="false" class="editGrap-cont">
+        <a-collapse :activeKey="['1']">
+          <a-collapse-panel key="1" :forceRender="true" header="选择产品">
+            <!-- 筛选条件 -->
+            <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-form-item label="调拨单号" prop="allocateNo">
+                      <a-input id="editGrap-allocateNo" v-model.trim="queryParam.allocateNo" placeholder="请输入调拨单号" allowClear />
+                    </a-form-item>
+                  </a-col>
+                  <a-col :md="6" :sm="24">
+                    <a-form-item label="产品编码" prop="productCode">
+                      <a-input id="editGrap-productCode" v-model.trim="queryParam.productCode" placeholder="请输入产品编码" allowClear />
+                    </a-form-item>
+                  </a-col>
+                  <a-col :md="6" :sm="24">
+                    <a-form-item label="产品名称" prop="productName">
+                      <a-input id="editGrap-productName" v-model.trim="queryParam.productName" placeholder="请输入产品名称" allowClear />
+                    </a-form-item>
+                  </a-col>
+                  <a-col :md="6" :sm="24" style="margin-bottom: 10px;">
+                    <a-button type="primary" @click="$refs.table.refresh(true)" :disabled="disabled" id="storeTransferOutList-refresh">查询</a-button>
+                    <a-button style="margin-left: 8px" @click="resetSearchForm" :disabled="disabled" id="storeTransferOutList-reset">重置</a-button>
+                  </a-col>
+                </a-row>
+              </a-form>
+            </div>
+            <!-- 列表 -->
+            <s-table
+              class="sTable"
+              ref="table"
+              size="small"
+              index="0"
+              tableId="table1"
+              :rowKey="(record) => record.allocateNo +'-'+ record.productSn"
+              :columns="columns"
+              :customRow="handleClickRow"
+              :data="loadData"
+              :scroll="{ y: 300 }"
+              :defaultLoadData="false"
+              bordered>
+              <!-- 退货单价 -->
+              <template slot="returnPrice" slot-scope="text, record">
+                <div @dblclick.stop>
+                  <a-input-number
+                    size="small"
+                    v-model="record.returnPrice"
+                    :precision="2"
+                    :min="0"
+                    :max="999999"
+                    placeholder="请输入"
+                    style="width: 100%;" />
+                </div>
+              </template>
+              <!-- 操作 -->
+              <template slot="action" slot-scope="text, record">
+                <a-button
+                  size="small"
+                  v-if="record.refundableQty"
+                  type="link"
+                  class="button-primary"
+                  @click="handleAdd(record)"
+                  id="editGrap-add-btn">添加</a-button>
+                <span v-else>--</span>
+              </template>
+            </s-table>
+          </a-collapse-panel>
+        </a-collapse>
+      </a-card>
+      <!-- 已选产品 -->
+      <a-card size="small" :bordered="false" class="editGrap-cont">
+        <a-collapse :activeKey="['2']">
+          <a-collapse-panel key="2" :forceRender="true" header="已选产品">
+            <!-- 总计 -->
+            <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>
+              </div>
+            </a-alert>
+            <!-- 筛选条件 -->
+            <a-row :gutter="15">
+              <a-col :span="17">
+                <div class="table-page-search-wrapper">
+                  <a-form layout="inline" @keyup.enter.native="$refs.chooseTable.refresh(true)">
+                    <a-row :gutter="15">
+                      <a-col :md="9" :sm="24">
+                        <a-form-item label="产品编码" prop="productCode">
+                          <a-input id="editGrap-productCode" v-model.trim="chooseQueryParam.productCode" placeholder="请输入产品编码" allowClear />
+                        </a-form-item>
+                      </a-col>
+                      <a-col :md="9" :sm="24">
+                        <a-form-item label="产品名称" prop="productName">
+                          <a-input id="editGrap-productName" v-model.trim="chooseQueryParam.productName" placeholder="请输入产品名称" allowClear />
+                        </a-form-item>
+                      </a-col>
+                      <a-col :md="6" :sm="24" style="margin-bottom: 10px;">
+                        <a-button type="primary" @click="$refs.chooseTable.refresh(true)" :disabled="chooseDisabled" id="storeTransferOutList-refresh">查询</a-button>
+                        <a-button style="margin-left: 8px" @click="chooseResetSearchForm" :disabled="chooseDisabled" id="storeTransferOutList-reset">重置</a-button>
+                      </a-col>
+                    </a-row>
+                  </a-form>
+                </div>
+              </a-col>
+              <a-col :span="7" style="text-align: right;">
+                <!-- <a-button size="small" id="editGrap-import-btn" @click="openGuideModal=true">导入产品</a-button> -->
+                <!-- <a-button size="small" type="danger" style="margin-left: 5px" @click.stop="handleDel('', 'all')" id="chainTransferOutEdit-del-all-btn">整单删除</a-button> -->
+              </a-col>
+            </a-row>
+            <!-- 列表 -->
+            <s-table
+              class="sTable"
+              ref="chooseTable"
+              size="small"
+              index="1"
+              tableId="table2"
+              :rowKey="(record) => record.id"
+              :columns="chooseColumns"
+              :data="chooseLoadData"
+              :scroll="{ y: 300 }"
+              :defaultLoadData="false"
+              bordered>
+              <!-- 退货单价 -->
+              <template slot="returnPrice" slot-scope="text, record">
+                <a-input-number
+                  size="small"
+                  v-model="record.price"
+                  @blur="e => priceChange(e.target.value, record)"
+                  :precision="2"
+                  :min="0"
+                  :max="999999"
+                  placeholder="请输入"
+                  style="width: 100%;" />
+              </template>
+              <!-- 操作 -->
+              <template slot="action" slot-scope="text, record">
+                <a-button size="small" type="link" class="button-error" @click="handleDel(record)" id="editGrap-del-btn">删除</a-button>
+              </template>
+            </s-table>
+          </a-collapse-panel>
+        </a-collapse>
+      </a-card>
+    <!-- </a-spin> -->
+    </div>
+    <div class="affix-cont">
+      <a-button
+        type="primary"
+        id="editGrap-submit"
+        size="large"
+        :disabled="spinning"
+        class="button-primary"
+        @click="handleSubmit"
+        style="padding: 0 60px;">提交</a-button>
+    </div>
+    <!-- 导入产品 -->
+    <!-- <importGuideModal :openModal="openGuideModal" :params="{allocateReturnSn: $route.params.sn}" @close="openGuideModal=false" @ok="handleGuideOk" /> -->
+    <!-- 修改基础信息 -->
+    <a-modal
+      centered
+      wrapClassName="allocateBill-editRemark-modal"
+      v-if="basicInfoData"
+      :footer="null"
+      :maskClosable="false"
+      title="修改备注"
+      v-model="editRemark"
+      @cancle="editRemark = false"
+      :width="600">
+      <a-textarea
+        v-model="basicInfoData.remarks"
+        placeholder="请输入备注(最多120个字符)"
+        :maxLength="120"
+        :auto-size="{ minRows: 3, maxRows: 5 }"
+      />
+      <div class="btn-cont">
+        <a-button type="primary" id="allocateBill-basicInfo-modal-save" @click="handleEditRemark">保存</a-button>
+        <a-button id="allocateBill-basicInfo-modal-back" @click="editRemark = false" style="margin-left: 15px;">取消</a-button>
+      </div>
+    </a-modal>
+  </div>
+</template>
+
+<script>
+import { commonMixin } from '@/utils/mixin'
+import { STable, VSelect } from '@/components'
+// import ImportGuideModal from './importGuideModal.vue'
+import print from './print.vue'
+import { allocDetailQueryPageForReturn } from '@/api/allocateBill'
+import AllocateType from '@/views/common/allocateType.js'
+import {
+  allocateReturnSave,
+  allocReturnDetailQueryPage,
+  allocateReturnQueryBySn,
+  allocReturnDetailInsert,
+  allocReturnDetailUpdate,
+  allocateReturnSubmit,
+  allocReturnDetailDelete
+  // allocateBillBatchInsert
+} from '@/api/allocateReturn'
+
+export default {
+  name: 'TransferReturnGrpEdit',
+  mixins: [commonMixin],
+  components: { STable, VSelect, AllocateType, print },
+  data () {
+    return {
+      spinning: false,
+      queryParam: {
+        productCode: '',
+        productName: '',
+        allocateNo: ''
+      },
+      chooseQueryParam: {
+        productCode: '',
+        productName: ''
+      },
+      editRemark: false,
+      disabled: false, //  查询、重置按钮是否可操作
+      loading: false,
+      chooseDisabled: false, //  查询、重置按钮是否可操作
+      advanced: false, // 高级搜索 展开/关闭
+      productBrandList: [], //  产品品牌  下拉数据
+      productTypeList: [], //  产品分类  下拉数据
+      productType: [],
+      warehouseList: [], //  仓库  下拉数据
+      // 加载数据方法 必须为 Promise 对象
+      loadData: parameter => {
+        this.disabled = true
+        const otherParams = { allocateBill: { targetType: this.$route.params.targetType, targetSn: this.basicInfoData.targetSn, allocateNo: this.queryParam.allocateNo } }
+        return allocDetailQueryPageForReturn(Object.assign(parameter, this.queryParam, otherParams)).then(res => {
+          const data = res.data
+          const no = (data.pageNo - 1) * data.pageSize
+          for (var i = 0; i < data.list.length; i++) {
+            data.list[i].no = no + i + 1
+            data.list[i].returnPrice = data.list[i].price
+            data.list[i].oldPrice = data.list[i].price
+          }
+          this.loadDataSource = data.list || []
+          this.disabled = false
+          return data
+        })
+      },
+      loadDataSource: [],
+      localDataSource: [],
+      // 加载数据方法 必须为 Promise 对象
+      chooseLoadData: parameter => {
+        this.chooseDisabled = true
+        const params = Object.assign(parameter, { product: { name: this.chooseQueryParam.productName, code: this.chooseQueryParam.productCode }, allocateReturnSn: this.$route.params.sn })
+        return allocReturnDetailQueryPage(params).then(res => {
+          const data = res.data
+          const no = (data.pageNo - 1) * data.pageSize
+          for (var i = 0; i < data.list.length; i++) {
+            data.list[i].no = no + i + 1
+            data.list[i].oldPrice = data.list[i].price
+          }
+          this.localDataSource = data.list || []
+          this.chooseDisabled = false
+          return data
+        })
+      },
+      basicInfoData: null, // 基本信息
+      openGuideModal: false //  导入产品引导
+    }
+  },
+  computed: {
+    columns () {
+      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' }
+      ]
+      return arr
+    },
+    chooseColumns () {
+      const arr = [
+        { title: '序号', dataIndex: 'no', width: '4%', align: 'center' },
+        { title: '调拨单号', dataIndex: 'allocateNo', width: '10%', align: 'center', customRender: function (text) { return text || '--' } },
+        { 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: '退货数量', 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' }
+      ]
+      return arr
+    }
+  },
+  methods: {
+    // 修改备注
+    handleEditRemark () {
+      const _this = this
+      const params = _this.basicInfoData
+      allocateReturnSave(params).then(res => {
+        if (res.status == 200) {
+          _this.$message.success(res.message)
+          _this.getDetail(true)
+        } else {
+          _this.spinning = false
+        }
+      })
+      _this.editRemark = false
+    },
+    // 修改调拨类型
+    changeAllocateType (val) {
+      const _this = this
+      this.$confirm({
+        title: '提示',
+        content: '确定要更改调拨退货类型吗?',
+        centered: true,
+        onOk () {
+          _this.handleEditRemark()
+        },
+        onCancel () {
+          _this.getDetail(true)
+        }
+      })
+    },
+    //  重置
+    resetSearchForm () {
+      this.queryParam.productCode = ''
+      this.queryParam.productName = ''
+      this.queryParam.allocateNo = ''
+      this.$refs.table.refresh(true)
+    },
+    // 双击快速添加
+    handleClickRow (record) {
+      return {
+        on: {
+          dblclick: (event) => {
+            if (record.refundableQty) {
+              this.handleAdd(record)
+            }
+          }
+        }
+      }
+    },
+    // // 导入产品
+    // handleGuideOk (obj) {
+    //   allocateBillBatchInsert(obj).then(res => {
+    //     if (res.status == 200) {
+    //       this.$refs.chooseTable.refresh(true)
+    //     }
+    //   })
+    // },
+    // 已选产品  重置
+    chooseResetSearchForm () {
+      this.chooseQueryParam.productCode = ''
+      this.chooseQueryParam.productName = ''
+      this.$refs.chooseTable.refresh(true)
+    },
+    //  添加/编辑
+    handleAdd (row, isEdit, isRefresh) {
+      const params = {
+        allocateReturnSn: this.$route.params.sn,
+        productSn: row.productSn,
+        price: isEdit ? row.price : row.returnPrice,
+        allocateNo: row.allocateNo,
+        allocateSn: row.allocateSn
+      }
+      const fun = isEdit ? allocReturnDetailUpdate : allocReturnDetailInsert
+      if (isEdit) { // 编辑
+        if (!row.price) {
+          row.price = row.oldPrice
+          return
+        }
+        params.oldPrice = row.oldPrice
+      } else {
+        params.oldPrice = row.oldPrice
+      }
+
+      this.spinning = true
+      fun(params).then(res => {
+        if (res.status == 200) {
+          this.getDetail(true)
+          this.$message.success(res.message)
+          if (isRefresh != 'noRefresh') {
+            this.$refs.table.refresh()
+          }
+          this.$refs.chooseTable.refresh()
+          this.spinning = false
+        } else {
+          this.spinning = false
+          row.price = row.oldPrice
+        }
+      })
+    },
+    //  删除
+    handleDel (row, isAll) {
+      const _this = this
+      const content = isAll ? '删除后不可恢复,确定要进行整单删除吗?' : '删除后不可恢复,确定要进行删除吗?'
+      this.$confirm({
+        title: '提示',
+        content: content,
+        centered: true,
+        onOk () {
+          if (isAll) { //  整单删除
+            // allocReturnDetailDeleteAll({ sn: _this.$route.params.sn }).then(res => {
+            //   if (res.status == 200) {
+            //     _this.$message.success(res.message)
+            //     _this.refashPage()
+            //   }
+            // })
+          } else { //  单个删除
+            allocReturnDetailDelete({
+              allocateReturnSn: _this.$route.params.sn,
+              allocateDetailSn: row.allocateDetailSn,
+              price: row.price,
+              productSn: row.productSn }).then(res => {
+              if (res.status == 200) {
+                _this.$message.success(res.message)
+                _this.refashPage()
+              }
+            })
+          }
+        }
+      })
+    },
+    //  提交
+    handleSubmit () {
+      const _this = this
+      if (this.localDataSource.length == 0) {
+        _this.$message.error('请先选择产品!')
+        return
+      }
+      _this.spinning = true
+      allocateReturnSubmit({ allocateReturnSn: this.$route.params.sn }).then(res => {
+        if (res.status == 200) {
+          this.$message.success(res.message)
+          setTimeout(() => {
+            _this.handleBack()
+            _this.spinning = false
+          }, 1000)
+        } else {
+          _this.spinning = false
+        }
+      })
+    },
+    // 基本信息
+    getDetail (flag) {
+      this.spinning = true
+      allocateReturnQueryBySn({ allocateReturnSn: this.$route.params.sn }).then(res => {
+        if (res.status == 200) {
+          this.basicInfoData = res.data
+          if (!flag) {
+            this.resetSearchForm()
+          }
+        } else {
+          this.basicInfoData = null
+        }
+        this.spinning = false
+      })
+    },
+    //  返回列表
+    handleBack () {
+      this.$router.push({ name: 'transferReturnList', query: { closeLastOldTab: true } })
+    },
+    // 已选产品 退货单价  change
+    priceChange (val, record) {
+      //  光标移出,值发生改变再调用编辑接口
+      if (Number(val) != Number(record.oldPrice)) {
+        this.handleAdd(record, true, 'noRefresh')
+      }
+    },
+    // 刷新当前页面
+    refashPage () {
+      this.getDetail(true)
+      this.$refs.table.refresh()
+      this.$refs.chooseTable.refresh()
+    },
+    pageInit () {
+      this.getDetail()
+      this.chooseResetSearchForm()
+    }
+  },
+  mounted () {
+    if (!this.$store.state.app.isNewTab) { // 页签刷新时调用
+      this.pageInit()
+    }
+  },
+  activated () {
+    // 如果是新页签打开或者进入新的子页(例:存在列表第2条数据编辑页页签时再打开第4条数据的编辑页),则重置当前页面
+    if (this.$store.state.app.isNewTab || !this.$store.state.app.isNewSubTab) {
+      this.pageInit()
+    }
+  },
+  beforeRouteEnter (to, from, next) {
+    next(vm => {})
+  }
+}
+</script>
+
+<style lang="less">
+  .editGrap-wrap{
+    position: relative;
+    height: 100%;
+    box-sizing: border-box;
+    >.ant-spin-nested-loading{
+      overflow-y: scroll;
+      height: 100%;
+      padding-bottom: 51px;
+    }
+    .editGrap-back{
+      margin-bottom: 10px;
+    }
+    .editGrap-cont{
+      margin-bottom: 10px;
+      .sub-title{
+        font-size: 12px;
+        color: #808695;
+        margin-left: 10px;
+      }
+      .tag-txt{
+        font-size: 12px;
+        color: #ed1c24;
+      }
+      .edit-circle-btn{
+        margin-left: 15px;
+        i{
+          vertical-align: text-bottom;
+        }
+      }
+      .import-btn{
+        margin-left: 15px;
+      }
+    }
+  }
+  .allocateBill-editRemark-modal{
+    .btn-cont{
+      text-align: center;
+      padding-top: 20px;
+    }
+  }
+</style>

+ 221 - 0
src/views/allocationManagement/transferReturn/importGuideModal.vue

@@ -0,0 +1,221 @@
+<template>
+  <a-modal
+    centered
+    class="importGuide-modal"
+    :footer="null"
+    :maskClosable="false"
+    title="导入"
+    v-model="isShow"
+    @cancle="isShow=false"
+    :width="750">
+    <div class="importGuide-con">
+      <div class="explain-con">
+        <div class="explain-item">
+          <div class="explain-tit">
+            <span>1</span>准备导入
+          </div>
+          <ul>
+            <li>1) 导入的Excel文件中必须包含名为“产品编码”、“数量”的列,且名称必须相同</li>
+            <li>2) 除了“产品编码”、“数量”两列,其他列可自定义,不影响数据导入</li>
+            <li>3) 如果导入的产品已经存在,则不会导入该行</li>
+          </ul>
+          <a-button type="link" icon="download" style="padding: 0 0 0 23px;" @click="handleExport">下载导入模板</a-button>
+        </div>
+        <div class="explain-item">
+          <div class="explain-tit">
+            <span>2</span>上传数据文件
+          </div>
+          <p>目前支持的文件类型*.xls,*.xlsx.</p>
+          <div style="overflow: hidden;padding-left: 23px;">
+            <Upload
+              id="importGuide-attachList"
+              ref="importUpload"
+              :maxNums="1"
+              fileType="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/vnd.ms-excel"
+              uploadType="import"
+              :action="attachAction"
+              :uploadParams="uploadParams"
+              upText="添加文件"
+              @change="changeImport"></Upload>
+          </div>
+        </div>
+      </div>
+      <!-- 按钮 -->
+      <div class="btn-con">
+        <a-button
+          type="primary"
+          id="importGuide-nextStep"
+          size="large"
+          class="button-primary"
+          @click="handlerNextStep"
+          style="padding: 0 60px;">下一步</a-button>
+        <a-button
+          id="importGuide-cancel"
+          size="large"
+          class="button-cancel"
+          @click="isShow=false"
+          style="padding: 0 60px;margin-left: 15px;">取消</a-button>
+      </div>
+    </div>
+    <!-- 导入 -->
+    <chooseImportModal :openModal="openImportModal" :paramsData="paramsData" @close="handleClose" @ok="hanldeOk" />
+  </a-modal>
+</template>
+
+<script>
+import { commonMixin } from '@/utils/mixin'
+import ChooseImportModal from './chooseImportModal.vue'
+import { Upload } from '@/components'
+import { allocateBillDownload } from '@/api/allocateBill'
+export default {
+  name: 'TransferReturnImportGuideModal',
+  mixins: [commonMixin],
+  components: { ChooseImportModal, Upload },
+  props: {
+    openModal: { //  弹框显示状态
+      type: Boolean,
+      default: false
+    },
+    params: {
+      type: Object,
+      default: null
+    }
+  },
+  data () {
+    return {
+      isShow: this.openModal, //  是否打开弹框
+      openImportModal: false, //  导入
+      attachAction: process.env.VUE_APP_API_BASE_URL + '/upload',
+      paramsData: null,
+      uploadParams: {
+        savePathType: 'local'
+      }
+    }
+  },
+  methods: {
+    // 下一步
+    handlerNextStep () {
+      if (this.paramsData) {
+        this.openImportModal = true
+      } else {
+        this.$message.warning('添加文件后再进行下一步操作!')
+      }
+    },
+    // 上传文件  change
+    changeImport (file) {
+      if (file) {
+        this.paramsData = {
+          allocateSn: this.params.allocateSn || '',
+          path: file
+        }
+      }
+    },
+    // 导入
+    hanldeOk (obj) {
+      if (obj && obj.length > 0) {
+        this.$emit('ok', obj)
+        this.isShow = false
+      }
+    },
+    // 关闭
+    handleClose () {
+      this.openImportModal = false
+      this.isShow = false
+    },
+    //  导出
+    handleExport () {
+      const _this = this
+      _this.spinning = true
+      allocateBillDownload({}).then(res => {
+        _this.spinning = false
+        if (res.type == 'application/json') {
+          var reader = new FileReader()
+          reader.addEventListener('loadend', function () {
+            const obj = JSON.parse(reader.result)
+            _this.$notification.error({
+              message: '提示',
+              description: obj.message
+            })
+          })
+          reader.readAsText(res)
+        } else {
+          this.download(res)
+        }
+      })
+    },
+    download (data) {
+      if (!data) { return }
+      const url = window.URL.createObjectURL(new Blob([data]))
+      const link = document.createElement('a')
+      link.style.display = 'none'
+      link.href = url
+      const fname = '调拨单产品导入模板'
+      link.setAttribute('download', fname + '.xlsx')
+      document.body.appendChild(link)
+      link.click()
+    }
+  },
+  watch: {
+    //  父页面传过来的弹框状态
+    openModal (newValue, oldValue) {
+      this.isShow = newValue
+    },
+    //  重定义的弹框状态
+    isShow (newValue, oldValue) {
+      if (!newValue) {
+        this.$emit('close')
+        this.paramsData = null
+        this.$refs.importUpload.setFileList('')
+      }
+    }
+  }
+}
+</script>
+
+<style lang="less" scoped>
+  .importGuide-modal{
+    .importGuide-con{
+      .explain-con{
+        .explain-item{
+          margin-bottom: 10px;
+          .explain-tit{
+            font-weight: bold;
+            span{
+              display: inline-block;
+              width: 18px;
+              height: 18px;
+              line-height: 16px;
+              text-align: center;
+              margin-right: 5px;
+              border-radius: 50%;
+              border: 1px solid rgba(0, 0, 0, 0.3);
+            }
+          }
+          p{
+            margin: 8px 0;
+            padding-left: 23px;
+          }
+          ul{
+            list-style: none;
+            padding: 0;
+            padding-left: 23px;
+            margin: 0;
+            li{
+              line-height: 26px;
+            }
+          }
+        }
+        #importGuide-attachList{
+          width: 100%;
+        }
+      }
+      .btn-con{
+        margin: 10px 0 20px;
+        text-align: center;
+        .button-cancel{
+          font-size: 12px;
+        }
+      }
+    }
+  }
+</style>

+ 344 - 0
src/views/allocationManagement/transferReturn/list.vue

@@ -0,0 +1,344 @@
+<template>
+  <a-card size="small" :bordered="false" class="transferReturn-wrap">
+    <a-spin :spinning="spinning" tip="Loading...">
+      <!-- 搜索条件 -->
+      <div ref="tableSearch" class="table-page-search-wrapper">
+        <a-form layout="inline" @keyup.enter.native="$refs.table.refresh(true)">
+          <a-row :gutter="15">
+            <a-col :md="6" :sm="24">
+              <a-form-item label="创建时间">
+                <rangeDate ref="rangeDate" :value="time" @change="dateChange" />
+              </a-form-item>
+            </a-col>
+            <a-col :md="6" :sm="24">
+              <a-form-item label="调拨退货单号">
+                <a-input id="transferReturn-allocateReturnNo" v-model.trim="queryParam.allocateReturnNo" allowClear placeholder="请输入调拨退货单号"/>
+              </a-form-item>
+            </a-col>
+            <a-col :md="6" :sm="24">
+              <a-form-item label="调拨退货对象名称">
+                <a-input id="transferReturn-targetName" v-model.trim="queryParam.targetName" allowClear placeholder="请输入调拨退货对象名称"/>
+              </a-form-item>
+            </a-col>
+            <a-col :md="6" :sm="24">
+              <a-form-item label="调拨退货类型">
+                <AllocateType id="transferReturn-allocateReturnTypeSn" v-model="queryParam.allocateReturnTypeSn"></AllocateType>
+              </a-form-item>
+            </a-col>
+            <template v-if="advanced">
+              <a-col :md="6" :sm="24">
+                <a-form-item label="业务状态">
+                  <v-select
+                    v-model="queryParam.state"
+                    ref="state"
+                    id="transferReturn-state"
+                    code="ALLOCATE_RETURN_STATE"
+                    placeholder="请选择业务状态"
+                    allowClear
+                  ></v-select>
+                </a-form-item>
+              </a-col>
+            </template>
+            <a-col :md="6" :sm="24">
+              <a-button type="primary" @click="$refs.table.refresh(true)" :disabled="disabled" id="transferReturn-refresh">查询</a-button>
+              <a-button style="margin-left: 5px" @click="resetSearchForm" :disabled="disabled" id="transferReturn-reset">重置</a-button>
+              <!-- <a-button
+                style="margin-left: 5px"
+                type="primary"
+                class="button-warning"
+                v-if="$hasPermissions('B_transferOut_export')"
+                @click="handleExport"
+                :disabled="disabled"
+                :loading="exportLoading"
+                id="transferReturn-export">导出</a-button> -->
+              <a @click="advanced=!advanced" style="margin-left: 5px">
+                {{ advanced ? '收起' : '展开' }}
+                <a-icon :type="advanced ? 'up' : 'down'"/>
+              </a>
+            </a-col>
+          </a-row>
+        </a-form>
+      </div>
+      <!-- 操作按钮 -->
+      <div class="table-operator">
+        <a-button v-if="$hasPermissions('B_transferReturnNew')" id="transferReturn-add" type="primary" class="button-error" @click="openModal=true">新增</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"
+        :defaultLoadData="false"
+        :scroll="{ y: tableHeight }"
+        bordered>
+        <!-- 单号 -->
+        <template slot="allocateReturnNo" slot-scope="text, record">
+          <span v-if="$hasPermissions('M_transferReturnDetail')" class="link-bule" @click="handleDetail(record)">{{ record.allocateReturnNo }}</span>
+          <span v-else>{{ record.allocateReturnNo }}</span>
+        </template>
+        <!-- 操作 -->
+        <template slot="action" slot-scope="text, record">
+          <a-button
+            size="small"
+            type="link"
+            v-if="record.state == 'WAIT_AUDIT' && $hasPermissions('B_transferReturnAudit')"
+            class="button-warning"
+            @click="handleExamine(record)"
+            id="transferReturn-examine-btn">审核</a-button>
+          <a-button
+            size="small"
+            type="link"
+            class="button-warning"
+            v-if="record.state=='WAIT_CHECK' && $hasPermissions('M_transferReturnCheck')"
+            @click="handleCheck(record)"
+            id="transferReturn-examine-btn">品检</a-button>
+          <a-button
+            size="small"
+            type="link"
+            v-if="((record.state == 'WAIT_SUBMIT') || (record.state == 'FINANCIAL_REJECT') || (record.state == 'AUDIT_REJECT')) && $hasPermissions('B_transferReturnEdit')"
+            class="button-info"
+            @click="handleEdit(record)"
+            id="transferReturn-edit-btn">编辑</a-button>
+          <a-button
+            size="small"
+            type="link"
+            v-if="((record.state == 'WAIT_SUBMIT') || (record.state == 'FINANCIAL_REJECT') || (record.state == 'AUDIT_REJECT')) && $hasPermissions('B_transferReturnDel')"
+            class="button-error"
+            @click="handleDel(record)"
+            id="transferReturn-del-btn">删除</a-button>
+          <!-- 带财务确认或已完结 -->
+          <span v-if="record.state == 'WAIT_FINANCIAL_AUDIT'||record.state == 'FINISH'">--</span>
+        </template>
+      </s-table>
+    </a-spin>
+    <!-- 新增 -->
+    <basic-info-modal :openModal="openModal" @ok="handleEdit" @close="openModal=false" />
+    <!-- 审核 -->
+    <auditModal :openModal="visibleAudit" :spinning="spinningAudit" @close="visibleAudit=false" @ok="auditOrder('WAIT_CHECK')" @fail="auditOrder('AUDIT_REJECT')" />
+  </a-card>
+</template>
+
+<script>
+// import moment from 'moment'
+// import getDate from '@/libs/getDate.js'
+import { commonMixin } from '@/utils/mixin'
+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 { allocateReturnQueryPage, allocateReturnAudit, allocateReturnDelete, allocateReturnExport } from '@/api/allocateReturn'
+import AllocateType from '@/views/common/allocateType.js'
+import { hdExportExcel } from '@/libs/exportExcel'
+export default {
+  name: 'TransferReturnList',
+  mixins: [commonMixin],
+  components: { STable, VSelect, basicInfoModal, rangeDate, auditModal, AllocateType },
+  data () {
+    return {
+      spinning: false,
+      advanced: true, // 高级搜索 展开/关闭
+      tableHeight: 0,
+      time: [
+        // moment(getDate.getThreeMonthDays().starttime, 'YYYY-MM-DD'),
+        // moment(getDate.getCurrMonthDays().endtime, 'YYYY-MM-DD')
+      ],
+      queryParam: { //  查询条件
+        // beginDate: getDate.getThreeMonthDays().starttime,
+        // endDate: getDate.getCurrMonthDays().endtime,
+        beginDate: '',
+        endDate: '',
+        targetName: '', //  调往对象
+        allocateReturnTypeSn: undefined, //  调拨退货类型
+        state: undefined, //  业务状态
+        allocateReturnNo: '' //  调拨单号
+      },
+      disabled: false, //  查询、重置按钮是否可操作
+      exportLoading: false,
+      // 加载数据方法 必须为 Promise 对象
+      loadData: parameter => {
+        this.disabled = true
+        this.spinning = true
+        return allocateReturnQueryPage(Object.assign(parameter, this.queryParam)).then(res => {
+          let data
+          if (res.status == 200) {
+            data = res.data
+            const no = (data.pageNo - 1) * data.pageSize
+            for (var i = 0; i < data.list.length; i++) {
+              data.list[i].no = no + i + 1
+            }
+            this.disabled = false
+          }
+          this.spinning = false
+          return data
+        })
+      },
+      visibleAudit: false,
+      auditInfo: null,
+      spinningAudit: false,
+      openModal: false //  新增编辑  弹框
+    }
+  },
+  computed: {
+    columns () {
+      const arr = [
+        { title: '序号', dataIndex: 'no', width: '3.5%', align: 'center' },
+        { title: '创建时间', dataIndex: 'createDate', width: '7%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '调拨退货单号', scopedSlots: { customRender: 'allocateReturnNo' }, align: 'center', width: '8%' },
+        { title: '调拨退货对象类型', dataIndex: 'targetTypeDictValue', width: '6%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '调拨退货对象名称', dataIndex: 'targetName', width: '10%', align: 'left', customRender: function (text) { return text || '--' }, ellipsis: true },
+        { title: '调拨退货类型', dataIndex: 'allocateReturnTypeName', width: '10%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '是否抓单', dataIndex: 'grabFlagDictValue', width: '5%', align: 'center', customRender: function (text) { return text || '--' } },
+        { 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' }
+      ]
+      return arr
+    }
+  },
+  methods: {
+    //  创建时间  change
+    dateChange (date) {
+      this.queryParam.beginDate = date[0]
+      this.queryParam.endDate = date[1]
+    },
+    //  重置
+    resetSearchForm () {
+      this.$refs.rangeDate.resetDate('')
+      // this.queryParam.beginDate = getDate.getThreeMonthDays().starttime
+      // this.queryParam.endDate = getDate.getCurrMonthDays().endtime
+      this.queryParam.beginDate = ''
+      this.queryParam.endDate = ''
+      this.queryParam.targetName = ''
+      this.queryParam.state = undefined
+      this.queryParam.allocateReturnNo = ''
+      this.queryParam.allocateReturnTypeSn = undefined
+      this.$refs.table.refresh(true)
+    },
+    //  删除
+    handleDel (row) {
+      const _this = this
+      this.$confirm({
+        title: '提示',
+        content: '删除后不可恢复,确定要进行删除吗?',
+        centered: true,
+        onOk () {
+          _this.spinning = true
+          allocateReturnDelete({ allocateReturnSn: row.allocateReturnSn }).then(res => {
+            if (res.status == 200) {
+              _this.$message.success(res.message)
+              _this.$refs.table.refresh()
+              _this.spinning = false
+            } else {
+              _this.spinning = false
+            }
+          })
+        }
+      })
+    },
+    //  审核
+    handleExamine (row) {
+      this.auditInfo = row
+      this.visibleAudit = true
+    },
+    // 审核
+    auditOrder (state) {
+      const _this = this
+      _this.spinningAudit = true
+      allocateReturnAudit({ allocateReturnSn: this.auditInfo.allocateReturnSn, state: state }).then(res => {
+        if (res.status == 200) {
+          _this.visibleAudit = false
+          _this.$message.success(res.message)
+          _this.$refs.table.refresh()
+          _this.spinningAudit = false
+        } else {
+          _this.visibleAudit = false
+          _this.spinningAudit = false
+        }
+      })
+    },
+    //  详情
+    handleDetail (row) {
+      this.$router.push({ name: 'transferReturnDetail', params: { sn: row.allocateReturnSn } })
+    },
+    //  编辑
+    handleEdit (row) {
+      this.$router.push({ name: row.grabFlag == 1 ? 'transferReturnGrpEdit' : 'transferReturnEdit', params: { sn: row.allocateReturnSn, targetType: row.targetType, dealerLevel: row.dealerLevel || '0' } })
+    },
+    // 品检
+    handleCheck (row) {
+      this.$router.push({ name: 'transferReturnCheck', params: { sn: row.allocateReturnSn, grabFlag: row.grabFlag } })
+    },
+    //  导出
+    handleExport () {
+      const _this = this
+      const params = this.queryParam
+      this.exportLoading = true
+      this.spinning = true
+      hdExportExcel(allocateReturnExport, params, '调拨退货列表', function () {
+        _this.exportLoading = false
+        _this.spinning = false
+      })
+    },
+    pageInit () {
+      const _this = this
+      this.$nextTick(() => { // 页面渲染完成后的回调
+        _this.setTableH()
+      })
+      this.openModal = false
+    },
+    setTableH () {
+      const tableSearchH = this.$refs.tableSearch.offsetHeight
+      this.tableHeight = window.innerHeight - tableSearchH - 238
+    }
+  },
+  watch: {
+    advanced (newValue, oldValue) {
+      const _this = this
+      this.$nextTick(() => { // 页面渲染完成后的回调
+        _this.setTableH()
+      })
+    },
+    '$store.state.app.winHeight' (newValue, oldValue) { //  窗口变更时,需同时更改表格高度
+      this.setTableH()
+    }
+  },
+  mounted () {
+    if (!this.$store.state.app.isNewTab) { // 页签刷新时调用
+      this.pageInit()
+      this.resetSearchForm()
+    }
+  },
+  activated () {
+    // 如果是新页签打开,则重置当前页面
+    if (this.$store.state.app.isNewTab) {
+      this.pageInit()
+      this.resetSearchForm()
+    }
+    // 仅刷新列表,不重置页面
+    if (this.$store.state.app.updateList) {
+      this.pageInit()
+      this.$refs.table.refresh()
+    }
+  },
+  beforeRouteEnter (to, from, next) {
+    next(vm => {})
+  }
+}
+</script>
+<style lang="less">
+	.active{
+		color: #ed1c24;
+		cursor: pointer;
+	}
+	.common{
+		color: rgba(0, 0, 0);
+	}
+</style>

+ 100 - 0
src/views/allocationManagement/transferReturn/print.vue

@@ -0,0 +1,100 @@
+<template>
+  <div>
+    <a-button
+      key="1"
+      type="default"
+      v-if="$hasPermissions('B_transferReturnPrint')"
+      id="editGrap-db-print-btn"
+      :disabled="disabled"
+      @click="handlePrint('views')">打印预览</a-button>
+    <a-button
+      key="2"
+      type="primary"
+      class="button-info"
+      v-if="$hasPermissions('B_transferReturnPrint')"
+      id="editGrap-dbfl-print-btn"
+      :disabled="disabled"
+      @click="handlePrint('print')">快捷打印</a-button>
+    <a-divider type="vertical" />
+    <a-button
+      key="3"
+      type="primary"
+      class="button-warning"
+      v-if="$hasPermissions('B_transferReturnExport')"
+      id="editGrap-export-btn"
+      :disabled="disabled"
+      @click="handleExcel">导出Excel</a-button>
+    <!-- 打印 -->
+    <div id="print"></div>
+  </div>
+</template>
+
+<script>
+import { hdExportExcel } from '@/libs/exportExcel'
+import { allocateReturnExcel, allocateReturnPrint } from '@/api/allocateReturn'
+export default {
+  props: {
+    params: {
+      type: Object,
+      default: function () {
+        return {}
+      }
+    },
+    disabled: {
+      type: Boolean,
+      default: false
+    }
+  },
+  methods: {
+    handlePrint (type) {
+      const _this = this
+      const params = {
+        allocateReturnSn: this.params.allocateReturnSn || ''
+      }
+      this.$emit('loading')
+      allocateReturnPrint(params).then(res => {
+        _this.spinning = false
+        if (res.type == 'application/json') {
+          var reader = new FileReader()
+          reader.addEventListener('loadend', function () {
+            const obj = JSON.parse(reader.result)
+            _this.$notification.error({
+              message: '提示',
+              description: obj.message
+            })
+          })
+          reader.readAsText(res)
+        } else {
+          this.print(res, type)
+        }
+        _this.$emit('unloading')
+      })
+    },
+    print (data, type) {
+      if (!data) {
+        return
+      }
+      const url = window.URL.createObjectURL(new Blob([data], { type: 'application/pdf' }))
+      console.log(url)
+      document.getElementById('print').innerHTML = '<iframe id="printftoe" name="printftoe" src="' + url + '" hidden></iframe>'
+      if (type == 'views') { //  预览
+        window.open(url)
+      } else if (type == 'print') { //  打印
+        window.frames['printftoe'].focus()
+        window.frames['printftoe'].print()
+      }
+    },
+    // 导出
+    handleExcel () {
+      const _this = this
+      this.$emit('loading')
+      hdExportExcel(allocateReturnExcel, { allocateReturnSn: this.params.allocateReturnSn || '' }, '调拨退货单明细', function () {
+        _this.$emit('unloading')
+      })
+    }
+  }
+}
+</script>
+
+<style>
+</style>

+ 2 - 0
src/views/basicData/transferTypeManagement/editModal.vue

@@ -42,10 +42,12 @@
 </template>
 
 <script>
+import { commonMixin } from '@/utils/mixin'
 import { VSelect } from '@/components'
 import { allocateTypeSave } from '@/api/allocateType'
 export default {
   name: 'TransferTypeManagementEditModal',
+  mixins: [commonMixin],
   components: { VSelect },
   props: {
     openModal: { //  弹框显示状态

+ 3 - 0
src/views/basicData/transferTypeManagement/list.vue

@@ -48,10 +48,13 @@
 </template>
 
 <script>
+import { commonMixin } from '@/utils/mixin'
 import { STable, VSelect } from '@/components'
 import transferTypeManagementEditModal from './editModal.vue'
 import { allocateTypeList, allocateTypeDel } from '@/api/allocateType'
 export default {
+  name: 'TransferTypeManagementList',
+  mixins: [commonMixin],
   components: { STable, VSelect, transferTypeManagementEditModal },
   data () {
     return {

+ 2 - 0
src/views/basicData/warehouse/editModal.vue

@@ -39,10 +39,12 @@
 </template>
 
 <script>
+import { commonMixin } from '@/utils/mixin'
 import { STable } from '@/components'
 import { warehouseSave } from '@/api/warehouse'
 export default {
   name: 'WarehouseEditModal',
+  mixins: [commonMixin],
   components: { STable },
   props: {
     openModal: { //  弹框显示状态

+ 3 - 0
src/views/basicData/warehouse/list.vue

@@ -66,10 +66,13 @@
 </template>
 
 <script>
+import { commonMixin } from '@/utils/mixin'
 import { warehouseList, warehouseDel } from '@/api/warehouse'
 import { STable } from '@/components'
 import warehouseEditModal from './editModal.vue'
 export default {
+  name: 'WarehouseList',
+  mixins: [commonMixin],
   components: { STable, warehouseEditModal },
   data () {
     return {

+ 2 - 0
src/views/basicData/warehouse/storingLocation/editModal.vue

@@ -43,10 +43,12 @@
 </template>
 
 <script>
+import { commonMixin } from '@/utils/mixin'
 import { STable } from '@/components'
 import { warehouseLocSave, warehouseAllList } from '@/api/warehouse'
 export default {
   name: 'StoringLocationEditModal',
+  mixins: [commonMixin],
   components: { STable },
   props: {
     openModal: { //  弹框显示状态

+ 3 - 0
src/views/basicData/warehouse/storingLocation/list.vue

@@ -68,10 +68,13 @@
 </template>
 
 <script>
+import { commonMixin } from '@/utils/mixin'
 import { warehouseLocList, warehouseLocDel } from '@/api/warehouse'
 import { STable } from '@/components'
 import storingLocationEditModal from './editModal.vue'
 export default {
+  name: 'StoringLocationList',
+  mixins: [commonMixin],
   components: { STable, storingLocationEditModal },
   data () {
     return {

+ 25 - 20
src/views/bnSetting/menu/adminMenus.vue

@@ -14,25 +14,28 @@
         </a-row>
         <a-row :gutter="24" >
           <a-input-search placeholder="输入搜索菜单名搜索" style="width: 100%" @change="onChange" />
-          <a-tree
-            @expand="onExpand"
-            :treeData="getMenus"
-            :expandedKeys="expandedKeys"
-            :autoExpandParent="autoExpandParent"
-            @select="onSelect"
-            :selectedKeys="selectedKeys"
-          >
-            <template slot="title" slot-scope="{title}">
-              <span v-if="title.indexOf(searchValue) > -1">
-                {{ title.substr(0, title.indexOf(searchValue)) }}
-                <span style="color: #f50">{{ searchValue }}</span>
-                {{ title.substr(title.indexOf(searchValue) + searchValue.length) }}
-              </span>
-              <span v-else>{{ title }}</span>
-            </template>
-            <a-icon slot="file" type="file" />
-            <a-icon slot="pushpin" type="pushpin" />
-          </a-tree>
+          <div style="max-height: 600px;overflow: auto;">
+            <a-tree
+              @expand="onExpand"
+              :treeData="getMenus"
+              :expandedKeys="expandedKeys"
+              :autoExpandParent="autoExpandParent"
+              @select="onSelect"
+              :selectedKeys="selectedKeys"
+              showIcon
+            >
+              <template slot="title" slot-scope="{title}">
+                <span v-if="title.indexOf(searchValue) > -1">
+                  {{ title.substr(0, title.indexOf(searchValue)) }}
+                  <span style="color: #f50">{{ searchValue }}</span>
+                  {{ title.substr(title.indexOf(searchValue) + searchValue.length) }}
+                </span>
+                <span v-else>{{ title }}</span>
+              </template>
+              <a-icon slot="file" type="file" />
+              <a-icon slot="pushpin" type="pushpin" />
+            </a-tree>
+          </div>
         </a-row>
       </a-col>
       <!-- 右侧 -->
@@ -184,12 +187,14 @@
 </template>
 
 <script>
+import { commonMixin } from '@/utils/mixin'
 import { STable, VSelect } from '@/components'
 import childModal from './childModal.vue'
 import { getYyMenuList, saveYyMenu, deleteYyMenu } from '@/api/menu.js'
 
 export default {
-  name: 'Menu',
+  name: 'AdminMenus',
+  mixins: [commonMixin],
   components: {
     STable, VSelect, childModal
   },

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

@@ -16,7 +16,7 @@
         </div>
       </div>
       <div class="btn-box">
-        <a-button type="primary" class="button-warning" @click="handleAuditFail" v-if="isCancel">{{ cancelText || '审核不通过' }}</a-button>
+        <a-button type="primary" class="button-error" @click="handleAuditFail" v-if="isCancel">{{ cancelText || '审核不通过' }}</a-button>
         <a-button type="primary" class="button-info" @click="handleAuditOk">{{ okText || '审核通过' }}</a-button>
       </div>
     </a-spin>

+ 3 - 0
src/views/dataExport/exportCheck/list.vue

@@ -40,10 +40,13 @@
 </template>
 
 <script>
+import { commonMixin } from '@/utils/mixin'
 import { STable, VSelect } from '@/components'
 import { checkWarehouseExcelList, checkWarehouseExport } from '@/api/checkWarehouse'
 import { hdExportExcel } from '@/libs/exportExcel'
 export default {
+  name: 'ExportCheckList',
+  mixins: [commonMixin],
   components: { STable, VSelect },
   data () {
     return {

+ 3 - 0
src/views/dataExport/exportSales/list.vue

@@ -40,11 +40,14 @@
 </template>
 
 <script>
+import { commonMixin } from '@/utils/mixin'
 import { STable, VSelect } from '@/components'
 import { checkWarehouseExcelList } from '@/api/checkWarehouse'
 import { exportSalesOutProduct } from '@/api/stockOut.js'
 import { hdExportExcel } from '@/libs/exportExcel'
 export default {
+  name: 'ExportSalesList',
+  mixins: [commonMixin],
   components: { STable, VSelect },
   data () {
     return {

+ 2 - 0
src/views/dealerManagement/dealerAccountManagement/editModal.vue

@@ -78,10 +78,12 @@
 </template>
 
 <script>
+import { commonMixin } from '@/utils/mixin'
 import custList from '@/views/common/custList.vue'
 import { dealerUserSave, dealerUserDetail } from '@/api/dealer'
 export default {
   name: 'DealerAccountEditModal',
+  mixins: [commonMixin],
   components: { custList },
   props: {
     openModal: { //  弹框显示状态

+ 3 - 0
src/views/dealerManagement/dealerAccountManagement/list.vue

@@ -89,11 +89,14 @@
 </template>
 
 <script>
+import { commonMixin } from '@/utils/mixin'
 import { STable, VSelect } from '@/components'
 import dealerAccountEditModal from './editModal.vue'
 import dealerAccountDetailModal from './detailModal.vue'
 import { dealerUserList, dealerUserEnable, dealerUserResetP } from '@/api/dealer'
 export default {
+  name: 'DealerAccountManagementList',
+  mixins: [commonMixin],
   components: { STable, VSelect, dealerAccountEditModal, dealerAccountDetailModal },
   data () {
     return {

+ 2 - 0
src/views/dealerManagement/dealerRelationshipBinding/associateModal.vue

@@ -36,10 +36,12 @@
 </template>
 
 <script>
+import { commonMixin } from '@/utils/mixin'
 import { bindRelation } from '@/api/dealerRelation'
 import queryChild from './queryChild.vue'
 export default {
   name: 'RelationshipBindingModal',
+  mixins: [commonMixin],
   components: { queryChild },
   props: {
     openModal: { //  弹框显示状态

+ 3 - 0
src/views/dealerManagement/dealerRelationshipBinding/list.vue

@@ -82,11 +82,14 @@
 </template>
 I
 <script>
+import { commonMixin } from '@/utils/mixin'
 import { STable, VSelect } from '@/components'
 import tablePagination from '@/views/common/tablePagination.vue'
 import associateModal from './associateModal.vue'
 import { dealerRelationList, querySubList, unbindRelation } from '@/api/dealerRelation'
 export default {
+  name: 'DealerRelationshipBindingList',
+  mixins: [commonMixin],
   components: { STable, VSelect, associateModal, tablePagination },
   data () {
     return {

+ 3 - 0
src/views/dealerManagement/marketingDivisionSet/list.vue

@@ -55,10 +55,13 @@
 </template>
 
 <script>
+import { commonMixin } from '@/utils/mixin'
 import { STable, VSelect } from '@/components'
 import marketingDivisionSetEditModal from './editModal.vue'
 import { subareaQueryIncludeAreaAll, subareaDeleteBySn } from '@/api/subarea'
 export default {
+  name: 'MarketingDivisionSetList',
+  mixins: [commonMixin],
   components: { STable, VSelect, marketingDivisionSetEditModal },
   data () {
     return {

+ 69 - 72
src/views/dealerManagement/merchantInfoManagement/detailModal.vue

@@ -9,78 +9,72 @@
     @cancle="isShow=false"
     :width="960">
     <a-spin :spinning="spinning" tip="Loading...">
-      <div style="max-height: 400px;overflow: auto;">
-        <a-collapse :activeKey="['1','2','3']" class="merchantInfoManagement-cont-m">
-          <a-collapse-panel key="1" header="基础信息">
-            <a-descriptions :column="2" bordered size="small">
-              <a-descriptions-item label="经销商名称">{{ form&&form.dealerName ? form.dealerName : '--' }}</a-descriptions-item>
-              <a-descriptions-item label="经销商别名">{{ form&&form.dealerAlias ? form.dealerAlias : '--' }}</a-descriptions-item>
-              <a-descriptions-item label="商户类型">{{ form&&form.dealerTypeDictValue ? form.dealerTypeDictValue : '--' }}</a-descriptions-item>
-              <a-descriptions-item label="联系人1">{{ form&&form.contact ? form.contact : '--' }}</a-descriptions-item>
-              <a-descriptions-item label="联系手机1">{{ form&&form.contactMobile ? form.contactMobile : '--' }}</a-descriptions-item>
-              <a-descriptions-item label="联系角色1">{{ form&&form.contactRole ? form.contactRole : '--' }}</a-descriptions-item>
-              <a-descriptions-item label="联系电话">{{ form&&form.dealerTelephone ? form.dealerTelephone : '--' }}</a-descriptions-item>
-              <a-descriptions-item label="地址">
-                <span v-if="form&&(form.provinceName || form.cityName || form.districtName || form.address)">
-                  {{ form&&form.provinceName ? form.provinceName : '' }}
-                  {{ form&&form.cityName ? form.cityName : '' }}
-                  {{ form&&form.districtName ? form.districtName : '' }}
-                  {{ form&&form.address ? form.address : '' }}
-                </span>
-                <span v-else>--</span>
-              </a-descriptions-item>
-            </a-descriptions>
-          </a-collapse-panel>
-        </a-collapse>
-        <a-collapse class="merchantInfoManagement-cont-m">
-          <a-collapse-panel key="2" header="公司信息">
-            <a-descriptions :column="2" bordered size="small">
-              <a-descriptions-item label="经营方式">{{ form&&form.busniessMode ? form.busniessMode : '--' }}</a-descriptions-item>
-              <a-descriptions-item label="经营项目">{{ form&&form.busniessItmes ? form.busniessItmes : '--' }}</a-descriptions-item>
-              <a-descriptions-item label="公司规模">{{ form&&form.busniessScope ? form.busniessScope : '--' }}</a-descriptions-item>
-              <a-descriptions-item label="成立时间">{{ form&&form.buildDate ? form.buildDate : '--' }}</a-descriptions-item>
-              <a-descriptions-item label="一般纳税人">
-                <span v-if="form&&form.isTaxpayer">{{ form&&form.isTaxpayer == 1 ? '是':'否' }}</span>
-                <span v-else>--</span>
-              </a-descriptions-item>
-              <a-descriptions-item label="身份证号码">{{ form&&form.indentityCard ? form.indentityCard : '--' }}</a-descriptions-item>
-              <a-descriptions-item label="生日">{{ form&&form.brithday ? form.brithday : '--' }}</a-descriptions-item>
-              <a-descriptions-item label="籍贯">{{ form&&form.nativePlace ? form.nativePlace : '--' }}</a-descriptions-item>
-              <a-descriptions-item label="邮箱">{{ form&&form.mail ? form.mail : '--' }}</a-descriptions-item>
-              <a-descriptions-item label="联系人2">{{ form&&form.contact2 ? form.contact2 : '--' }}</a-descriptions-item>
-              <a-descriptions-item label="联系角色2">{{ form&&form.contractRole2 ? form.contractRole2 : '--' }}</a-descriptions-item>
-              <a-descriptions-item label="联系手机2">{{ form&&form.contactMobile2 ? form.contactMobile2 : '--' }}</a-descriptions-item>
-              <a-descriptions-item label="邮政编码">{{ form&&form.zipCode ? form.zipCode : '--' }}</a-descriptions-item>
-              <a-descriptions-item label="收货人">{{ form&&form.receiveContact ? form.receiveContact : '--' }}</a-descriptions-item>
-              <a-descriptions-item label="收货人电话">{{ form&&form.receiveMobile ? form.receiveMobile : '--' }}</a-descriptions-item>
-              <a-descriptions-item label="收货地址">
-                <span v-if="form&&(form.receiveProvinceName || form.receiveCityName || form.receiveDistrictName || form.receiveAddress)">
-                  {{ form&&form.receiveProvinceName ? form.receiveProvinceName : '' }}
-                  {{ form&&form.receiveCityName ? form.receiveCityName : '' }}
-                  {{ form&&form.receiveDistrictName ? form.receiveDistrictName : '' }}
-                  {{ form&&form.receiveAddress ? form.receiveAddress : '' }}
-                </span>
-                <span v-else>--</span>
-              </a-descriptions-item>
-              <a-descriptions-item label="银行账户">{{ form&&form.tradeAccountName ? form.tradeAccountName : '--' }}</a-descriptions-item>
-              <a-descriptions-item label="开户行">{{ form&&form.tradeBankName ? form.tradeBankName : '--' }}</a-descriptions-item>
-              <a-descriptions-item label="银行账号">{{ form&&form.tradeBankAccount ? form.tradeBankAccount : '--' }}</a-descriptions-item>
-            </a-descriptions>
-          </a-collapse-panel>
-        </a-collapse>
-        <a-collapse class="merchantInfoManagement-cont-m">
-          <a-collapse-panel key="3" header="总部信息">
-            <a-descriptions :column="2" bordered size="small">
-              <a-descriptions-item label="箭冠汽配代码">{{ form&&form.jgAutoPartsCode ? form.jgAutoPartsCode : '--' }}</a-descriptions-item>
-              <a-descriptions-item label="门头更换日期">{{ form&&form.jgDoorHeaderChangeTime ? form.jgDoorHeaderChangeTime : '--' }}</a-descriptions-item>
-              <a-descriptions-item label="特约价是否可见">
-                <span v-if="form&&form.isShowSpecialPrice">{{ form&&form.isShowSpecialPrice == 1 ? '是':'否' }}</span>
-                <span v-else>--</span>
-              </a-descriptions-item>
-              <a-descriptions-item label="备注">{{ form&&form.remark ? form.remark : '--' }}</a-descriptions-item>
-            </a-descriptions>
-          </a-collapse-panel>
-        </a-collapse>
+      <div style="max-height: 400px;overflow: auto;" ref="merchantInfoDetail">
+        <a-card title="基础信息" size="small" style="margin-bottom: 15px;">
+          <a-descriptions :column="2" bordered size="small">
+            <a-descriptions-item label="经销商名称">{{ form&&form.dealerName ? form.dealerName : '--' }}</a-descriptions-item>
+            <a-descriptions-item label="经销商别名">{{ form&&form.dealerAlias ? form.dealerAlias : '--' }}</a-descriptions-item>
+            <a-descriptions-item label="商户类型">{{ form&&form.dealerTypeDictValue ? form.dealerTypeDictValue : '--' }}</a-descriptions-item>
+            <a-descriptions-item label="联系人1">{{ form&&form.contact ? form.contact : '--' }}</a-descriptions-item>
+            <a-descriptions-item label="联系手机1">{{ form&&form.contactMobile ? form.contactMobile : '--' }}</a-descriptions-item>
+            <a-descriptions-item label="联系角色1">{{ form&&form.contactRole ? form.contactRole : '--' }}</a-descriptions-item>
+            <a-descriptions-item label="联系电话">{{ form&&form.dealerTelephone ? form.dealerTelephone : '--' }}</a-descriptions-item>
+            <a-descriptions-item label="地址">
+              <span v-if="form&&(form.provinceName || form.cityName || form.districtName || form.address)">
+                {{ form&&form.provinceName ? form.provinceName : '' }}
+                {{ form&&form.cityName ? form.cityName : '' }}
+                {{ form&&form.districtName ? form.districtName : '' }}
+                {{ form&&form.address ? form.address : '' }}
+              </span>
+              <span v-else>--</span>
+            </a-descriptions-item>
+          </a-descriptions>
+        </a-card>
+        <a-card title="公司信息" size="small" style="margin-bottom: 15px;">
+          <a-descriptions :column="2" bordered size="small">
+            <a-descriptions-item label="经营方式">{{ form&&form.busniessMode ? form.busniessMode : '--' }}</a-descriptions-item>
+            <a-descriptions-item label="经营项目">{{ form&&form.busniessItmes ? form.busniessItmes : '--' }}</a-descriptions-item>
+            <a-descriptions-item label="公司规模">{{ form&&form.busniessScope ? form.busniessScope : '--' }}</a-descriptions-item>
+            <a-descriptions-item label="成立时间">{{ form&&form.buildDate ? form.buildDate : '--' }}</a-descriptions-item>
+            <a-descriptions-item label="一般纳税人">
+              <span v-if="form&&form.isTaxpayer">{{ form&&form.isTaxpayer == 1 ? '是':'否' }}</span>
+              <span v-else>--</span>
+            </a-descriptions-item>
+            <a-descriptions-item label="身份证号码">{{ form&&form.indentityCard ? form.indentityCard : '--' }}</a-descriptions-item>
+            <a-descriptions-item label="生日">{{ form&&form.brithday ? form.brithday : '--' }}</a-descriptions-item>
+            <a-descriptions-item label="籍贯">{{ form&&form.nativePlace ? form.nativePlace : '--' }}</a-descriptions-item>
+            <a-descriptions-item label="邮箱">{{ form&&form.mail ? form.mail : '--' }}</a-descriptions-item>
+            <a-descriptions-item label="联系人2">{{ form&&form.contact2 ? form.contact2 : '--' }}</a-descriptions-item>
+            <a-descriptions-item label="联系角色2">{{ form&&form.contractRole2 ? form.contractRole2 : '--' }}</a-descriptions-item>
+            <a-descriptions-item label="联系手机2">{{ form&&form.contactMobile2 ? form.contactMobile2 : '--' }}</a-descriptions-item>
+            <a-descriptions-item label="邮政编码">{{ form&&form.zipCode ? form.zipCode : '--' }}</a-descriptions-item>
+            <a-descriptions-item label="收货人">{{ form&&form.receiveContact ? form.receiveContact : '--' }}</a-descriptions-item>
+            <a-descriptions-item label="收货人电话">{{ form&&form.receiveMobile ? form.receiveMobile : '--' }}</a-descriptions-item>
+            <a-descriptions-item label="收货地址">
+              <span v-if="form&&(form.receiveProvinceName || form.receiveCityName || form.receiveDistrictName || form.receiveAddress)">
+                {{ form&&form.receiveProvinceName ? form.receiveProvinceName : '' }}
+                {{ form&&form.receiveCityName ? form.receiveCityName : '' }}
+                {{ form&&form.receiveDistrictName ? form.receiveDistrictName : '' }}
+                {{ form&&form.receiveAddress ? form.receiveAddress : '' }}
+              </span>
+              <span v-else>--</span>
+            </a-descriptions-item>
+            <a-descriptions-item label="银行账户">{{ form&&form.tradeAccountName ? form.tradeAccountName : '--' }}</a-descriptions-item>
+            <a-descriptions-item label="开户行">{{ form&&form.tradeBankName ? form.tradeBankName : '--' }}</a-descriptions-item>
+            <a-descriptions-item label="银行账号">{{ form&&form.tradeBankAccount ? form.tradeBankAccount : '--' }}</a-descriptions-item>
+          </a-descriptions>
+        </a-card>
+        <a-card title="总部信息" size="small">
+          <a-descriptions :column="2" bordered size="small">
+            <a-descriptions-item label="箭冠汽配代码">{{ form&&form.jgAutoPartsCode ? form.jgAutoPartsCode : '--' }}</a-descriptions-item>
+            <a-descriptions-item label="门头更换日期">{{ form&&form.jgDoorHeaderChangeTime ? form.jgDoorHeaderChangeTime : '--' }}</a-descriptions-item>
+            <a-descriptions-item label="特约价是否可见">
+              <span v-if="form&&form.isShowSpecialPrice">{{ form&&form.isShowSpecialPrice == 1 ? '是':'否' }}</span>
+              <span v-else>--</span>
+            </a-descriptions-item>
+            <a-descriptions-item label="备注">{{ form&&form.remark ? form.remark : '--' }}</a-descriptions-item>
+          </a-descriptions>
+        </a-card>
       </div>
       <div class="btn-cont">
         <a-button
@@ -181,6 +175,9 @@ export default {
         this.form = null
       } else {
         this.title = this.isAudit ? '审核资料' : '查看详细'
+        this.$nextTick(() => {
+          this.$refs.merchantInfoDetail.scrollTop = 0
+        })
       }
     },
     itemId (newValue, oldValue) {

+ 7 - 1
src/views/dealerManagement/merchantInfoManagement/edit.vue

@@ -388,17 +388,20 @@
         id="merchantInfoManagementEdit-submit-btn"
         size="large"
         @click="handleSubmit"
-        style="padding: 0 60px;">提交</a-button>
+        style="padding: 0 60px;">保存</a-button>
     </div>
   </div>
 </template>
 
 <script>
+import { commonMixin } from '@/utils/mixin'
 import { getArea } from '@/api/data'
 import { VSelect } from '@/components'
 import { dealerSave, dealerFindUpdateInfoBySn } from '@/api/dealer'
 import moment from 'moment'
 export default {
+  name: 'MerchantInfoManagementEdit',
+  mixins: [commonMixin],
   components: { VSelect },
   data () {
     return {
@@ -523,6 +526,7 @@ export default {
     },
     // 详情编辑
     getDetail () {
+      this.spinning = true
       dealerFindUpdateInfoBySn({ sn: this.$route.params.id }).then(res => {
         if (res.status == 200) {
           this.detailData = res.data
@@ -541,6 +545,7 @@ export default {
             this.getArea('district', this.form.receiveCitySn, 1)
           }
         }
+        this.spinning = false
       })
     },
     // 提交
@@ -600,6 +605,7 @@ export default {
     },
     // 区县变更
     areaCharged (val) {
+      console.log(val)
       if (val) {
         this.form.districtName = this.addrDistrictList.find(item => item.areaSn == val).name
       } else {

+ 4 - 1
src/views/dealerManagement/merchantInfoManagement/list.vue

@@ -83,7 +83,7 @@
         <!-- 操作 -->
         <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>
-          <a-button size="small" type="link" class="button-success" v-if="$hasPermissions('B_merchantInfo_cooperation')" @click="handleCooperation(record)" >合作设置</a-button>
+          <a-button size="small" type="link" class="button-info" v-if="$hasPermissions('B_merchantInfo_cooperation')" @click="handleCooperation(record)" >合作设置</a-button>
           <a-button size="small" type="link" class="button-error" v-if="record.auditState != 'WAIT' && $hasPermissions('B_merchantInfo_distribution')" @click="handleDistribution(record)">经销权</a-button>
           <a-button size="small" type="link" class="button-primary" v-if="$hasPermissions('B_merchantInfo_level')" @click="handleLevel(record)">级别设置</a-button>
           <a-button size="small" type="link" class="button-info" v-if="$hasPermissions('B_merchantInfo_edit')" @click="handleEdit(record)">编辑</a-button>
@@ -101,6 +101,7 @@
 </template>
 
 <script>
+import { commonMixin } from '@/utils/mixin'
 import moment from 'moment'
 import { dealerQueryList, dealerExport } from '@/api/dealer'
 import { STable, VSelect } from '@/components'
@@ -109,6 +110,8 @@ import merchantInfoManagementDetailModal from './detailModal.vue'
 import UpdateCooperate from './updateCooperate.vue'
 import UpdateDealerLeve from './updateDealerLevel.vue'
 export default {
+  name: 'MerchantInfoManagementList',
+  mixins: [commonMixin],
   components: { STable, VSelect, merchantInfoManagementDetailModal, subarea, UpdateCooperate, UpdateDealerLeve },
   data () {
     return {

+ 3 - 0
src/views/dealerManagement/merchantInfoManagement/permissionSetting.vue

@@ -82,12 +82,15 @@
 </template>
 
 <script>
+import { commonMixin } from '@/utils/mixin'
 import { STable, VSelect } from '@/components'
 import ChooseProductsModal from '@/views/common/chooseProductsModal.vue'
 import ChooseBrandModal from '@/views/common/chooseBrandModal.vue'
 import ChooseTypeModal from '@/views/common/chooseTypeModal.vue'
 import { dealerScopeList, dealerScopeSave, dealerScopeDel, dealerScopeQueryList } from '@/api/dealerScope'
 export default {
+  name: 'MerchantInfoManagementSet',
+  mixins: [commonMixin],
   components: { STable, VSelect, ChooseProductsModal, ChooseBrandModal, ChooseTypeModal },
   data () {
     return {

+ 2 - 0
src/views/dealerManagement/merchantInfoManagement/updateCooperate.vue

@@ -42,11 +42,13 @@
 </template>
 
 <script>
+import { commonMixin } from '@/utils/mixin'
 import { VSelect } from '@/components'
 import { updateCooperate } from '@/api/dealer'
 import moment from 'moment'
 export default {
   name: 'UpdateCooperate',
+  mixins: [commonMixin],
   components: { VSelect },
   props: {
     openUcModal: { //  弹框显示状态

+ 2 - 0
src/views/dealerManagement/merchantInfoManagement/updateDealerLevel.vue

@@ -34,10 +34,12 @@
 </template>
 
 <script>
+import { commonMixin } from '@/utils/mixin'
 import { VSelect } from '@/components'
 import { updateDealerLevel } from '@/api/dealer'
 export default {
   name: 'UpdateDealerLevel',
+  mixins: [commonMixin],
   components: { VSelect },
   props: {
     openUdModal: { //  弹框显示状态

+ 2 - 0
src/views/dealerManagement/rebateSettings/associateModal.vue

@@ -36,10 +36,12 @@
 </template>
 
 <script>
+import { commonMixin } from '@/utils/mixin'
 import { updateRebate } from '@/api/dealerRelation'
 import queryChild from './queryChild.vue'
 export default {
   name: 'AssociateModal',
+  mixins: [commonMixin],
   components: { queryChild },
   props: {
     openModal: { //  弹框显示状态

+ 3 - 0
src/views/dealerManagement/rebateSettings/list.vue

@@ -68,10 +68,13 @@
 </template>
 
 <script>
+import { commonMixin } from '@/utils/mixin'
 import { STable, VSelect } from '@/components'
 import associateModal from './associateModal.vue'
 import { queryRebatePage } from '@/api/dealerRelation'
 export default {
+  name: 'RebateSettingsList',
+  mixins: [commonMixin],
   components: { STable, VSelect, associateModal },
   data () {
     return {

+ 12 - 9
src/views/dowloadFile/list.vue

@@ -45,7 +45,7 @@
         bordered>
         <!-- 操作 -->
         <template slot="action" slot-scope="text, record">
-          <a href="javascript:void(0)" @click="dowloadExcel(record.fileUrl)" style="padding: 5px 0 0 23px;display: block;" v-if="record.taskState=='SUCCESS'">下载文件</a>
+          <a :href="record.fileUrl" style="padding: 5px 0 0 23px;display: block;" v-if="record.taskState=='SUCCESS'">下载文件</a>
           <span v-else>--</span>
         </template>
       </s-table>
@@ -54,10 +54,13 @@
 </template>
 
 <script>
+import { commonMixin } from '@/utils/mixin'
 import { STable, VSelect } from '@/components'
 import { taskList, dowloadFile } from '@/api/dowloadFile'
 import rangeDate from '@/views/common/rangeDate.vue'
 export default {
+  name: 'DowloadFile',
+  mixins: [commonMixin],
   components: { STable, VSelect, rangeDate },
   data () {
     return {
@@ -104,14 +107,14 @@ export default {
   },
   methods: {
     dowloadExcel (url) {
-      // dowloadFile(url, '')
-      const elt = document.createElement('a')
-      elt.setAttribute('href', url)
-      elt.setAttribute('download', '')
-      elt.style.display = 'none'
-      document.body.appendChild(elt)
-      elt.click()
-      document.body.removeChild(elt)
+      dowloadFile(url, '')
+      // const elt = document.createElement('a')
+      // elt.setAttribute('href', url)
+      // elt.setAttribute('download', '')
+      // elt.style.display = 'none'
+      // document.body.appendChild(elt)
+      // elt.click()
+      // document.body.removeChild(elt)
     },
     //  时间  change
     dateChange (date) {

+ 3 - 0
src/views/expenseManagement/expenseReimbursement/add.vue

@@ -142,6 +142,7 @@
 </template>
 
 <script>
+import { commonMixin } from '@/utils/mixin'
 import { VSelect, Upload, STable } from '@/components'
 import epenseDetailModal from './epenseDetailModal.vue'
 import productInfoModal from './productInfoModal.vue'
@@ -150,6 +151,8 @@ import ImportGuideModal from './importGuideModal.vue'
 import chooseDepartUserModal from './chooseDepartUserModal.vue'
 import { expenseAccountDetail, expenseAcctDetailDelete, expenseAcctDetailFindList, expenseAccountSubmit, expenseInsertImport } from '@/api/expenseManagement.js'
 export default {
+  name: 'ExpenseReimbursementEdit',
+  mixins: [commonMixin],
   components: { VSelect, Upload, STable, epenseDetailModal, productInfoModal, baseDataModal, ImportGuideModal, chooseDepartUserModal },
   data () {
     return {

+ 3 - 1
src/views/expenseManagement/expenseReimbursement/detail.vue

@@ -104,12 +104,14 @@
 </template>
 
 <script>
+import { commonMixin } from '@/utils/mixin'
 import { STable } from '@/components'
 import { expenseAccountDetail, expenseAcctDetailFindList } from '@/api/expenseManagement'
 import previewModal from './previewModal.vue'
 import { jGPrint } from '@/libs/JGPrint.js'
 export default {
-  name: 'ExpenseReimbursementDetail',
+  name: 'ExpenseReimbursementListDetail',
+  mixins: [commonMixin],
   components: { STable, previewModal },
   data () {
     return {

+ 25 - 16
src/views/expenseManagement/expenseReimbursement/list.vue

@@ -10,6 +10,11 @@
                 <a-input id="salesManagementList-expenseAccountNo" v-model.trim="queryParam.expenseAccountNo" allowClear placeholder="请输入销售单号"/>
               </a-form-item>
             </a-col>
+            <a-col :md="6" :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-form-item label="费用类型">
                 <v-select
@@ -21,18 +26,18 @@
                   allowClear></v-select>
               </a-form-item>
             </a-col>
-            <a-col :md="6" :sm="24">
-              <a-form-item label="费用发生月份">
-                <a-month-picker
-                  placeholder="请选择月份"
-                  locale="zh-cn"
-                  v-model="queryParam.expenseDate"
-                  @change="onChange"
-                  :disabled-date="disabledDate"
-                  style="width: 100%;"/>
-              </a-form-item>
-            </a-col>
             <template v-if="advanced">
+              <a-col :md="6" :sm="24">
+                <a-form-item label="费用发生月份">
+                  <a-month-picker
+                    placeholder="请选择月份"
+                    locale="zh-cn"
+                    v-model="queryParam.expenseDate"
+                    @change="onChange"
+                    :disabled-date="disabledDate"
+                    style="width: 100%;"/>
+                </a-form-item>
+              </a-col>
               <a-col :md="6" :sm="24">
                 <a-form-item label="主题">
                   <a-input id="salesManagementList-title" v-model.trim="queryParam.title" allowClear placeholder="请输入主题"/>
@@ -81,7 +86,7 @@
         bordered>
         <!-- 单号 -->
         <template slot="expenseAccountNo" slot-scope="text, record">
-          <div v-if="$hasPermissions('B_eRdetail')" style="color: #00aaff;cursor: pointer;" @click="handleDetail(record)">{{ record.expenseAccountNo||'--' }}</div>
+          <span v-if="$hasPermissions('B_eRdetail')" class="link-bule" @click="handleDetail(record)">{{ record.expenseAccountNo }}</span>
           <div v-else>{{ record.expenseAccountNo||'--' }}</div>
         </template>
         <!-- 总数量 -->
@@ -112,7 +117,7 @@
             v-if="record.state!='WAIT_SUBMIT'&&$hasPermissions('B_ERAudit')"
             size="small"
             type="link"
-            class="button-success"
+            class="button-info"
             @click="handleSH(record)"
           >
             审核进度
@@ -129,16 +134,19 @@
 </template>
 
 <script>
+import { commonMixin } from '@/utils/mixin'
 import locale from 'ant-design-vue/es/date-picker/locale/zh_CN'
 import moment from 'moment'
 import subarea from '@/views/common/subarea.js'
+import employee from './employee.js'
 import { STable, VSelect } from '@/components'
 import verifyModal from './verifyModal.vue'
 import { expenseAccountList, expenseAccountDelete } from '@/api/expenseManagement'
 import baseDataModal from './baseDataModal.vue'
 export default {
-  name: 'TableList',
-  components: { STable, VSelect, subarea, verifyModal, baseDataModal },
+  name: 'ExpenseReimbursementList',
+  mixins: [commonMixin],
+  components: { STable, VSelect, subarea, verifyModal, baseDataModal, employee },
   data () {
     return {
       locale,
@@ -248,7 +256,8 @@ export default {
         expenseAccountNo: '', // 费用单号
         title: '', //  主题
         expenseType: undefined, // 费用类型
-        state: undefined // 状态
+        state: undefined, // 状态
+        applyPersonSn: undefined
       }
       this.$refs.table.refresh(true)
     },

+ 3 - 1
src/views/expenseManagement/expenseReimbursementDetail/list.vue

@@ -168,6 +168,7 @@
 </template>
 
 <script>
+import { commonMixin } from '@/utils/mixin'
 import moment from 'moment'
 import 'moment/locale/zh-cn'
 import getDate from '@/libs/getDate.js'
@@ -183,7 +184,8 @@ import { expenseAccountDetailList, expenseAcctDetailReport } from '@/api/expense
 import { hdExportExcel } from '@/libs/exportExcel'
 moment.locale('zh-cn')
 export default {
-  name: 'TableList',
+  name: 'ExpenseReimbursementDetailList',
+  mixins: [commonMixin],
   components: { STable, VSelect, department, employee, subarea, rangeDate, Area, custList, supplier },
   data () {
     return {

+ 65 - 0
src/views/financialManagement/allocateReturnConfirmation/detailModal.vue

@@ -0,0 +1,65 @@
+<template>
+  <a-modal
+    centered
+    class="confirmationDetail-modal"
+    :footer="null"
+    :maskClosable="false"
+    title="详情"
+    v-model="isShow"
+    @cancle="isShow=false"
+    :width="960">
+    <div>
+      <detail :outBizSn="itemSn" pageType="modal" ref="detail"></detail>
+      <div class="btn-cont"><a-button id="confirmationDetail-modal-back" @click="isShow = false">返回列表</a-button></div>
+    </div>
+  </a-modal>
+</template>
+
+<script>
+import detail from '@/views/allocationManagement/transferReturn/detail'
+export default {
+  name: 'AllocateReturnDetailModal',
+  components: { detail },
+  props: {
+    openModal: { //  弹框显示状态
+      type: Boolean,
+      default: false
+    },
+    itemSn: {
+      type: [Number, String],
+      default: ''
+    }
+  },
+  data () {
+    return {
+      isShow: this.openModal //  是否打开弹框
+    }
+  },
+  methods: {
+  },
+  watch: {
+    //  父页面传过来的弹框状态
+    openModal (newValue, oldValue) {
+      this.isShow = newValue
+    },
+    //  重定义的弹框状态
+    isShow (newValue, oldValue) {
+      if (!newValue) {
+        this.$emit('close')
+      }
+    }
+  }
+}
+</script>
+
+<style lang="less">
+  .confirmationDetail-modal{
+    .ant-modal-body {
+      padding: 10px 10px 20px;
+    }
+    .btn-cont {
+      text-align: center;
+      margin: 5px 0 10px;
+    }
+  }
+</style>

+ 281 - 0
src/views/financialManagement/allocateReturnConfirmation/list.vue

@@ -0,0 +1,281 @@
+<template>
+  <a-card size="small" :bordered="false" class="transferReturnConfirmation-wrap">
+    <a-spin :spinning="spinning" tip="Loading...">
+      <!-- 搜索条件 -->
+      <div ref="tableSearch" class="table-page-search-wrapper">
+        <a-form layout="inline" @keyup.enter.native="$refs.table.refresh(true)">
+          <a-row :gutter="15">
+            <a-col :md="6" :sm="24">
+              <a-form-item label="创建时间">
+                <rangeDate ref="rangeDate" @change="dateChange" />
+              </a-form-item>
+            </a-col>
+            <a-col :md="6" :sm="24">
+              <a-form-item label="调拨退货单号">
+                <a-input id="transferReturnConfirmation-allocateReturnNo" v-model.trim="queryParam.allocateReturnNo" allowClear placeholder="请输入调拨退货单号"/>
+              </a-form-item>
+            </a-col>
+            <a-col :md="6" :sm="24">
+              <a-form-item label="客户名称" :label-col="{ span:7 }" :wrapper-col="{ span:17}">
+                <a-input id="transferReturnConfirmation-targetName" v-model.trim="queryParam.targetName" allowClear placeholder="请输入客户名称"/>
+              </a-form-item>
+            </a-col>
+            <template v-if="advanced">
+              <a-col :md="6" :sm="24">
+                <a-form-item label="是否抓单">
+                  <v-select
+                    v-model="queryParam.grabFlag"
+                    ref="grabFlag"
+                    id="transferReturnConfirmation-grabFlag"
+                    code="FLAG"
+                    placeholder="请选择"
+                    allowClear></v-select>
+                </a-form-item>
+              </a-col>
+              <a-col :md="6" :sm="24">
+                <a-form-item label="状态">
+                  <v-select
+                    v-model="queryParam.state"
+                    ref="state"
+                    id="transferReturnConfirmation-state"
+                    code="ALLOCATE_RETURN_STATE_CONFIRM"
+                    placeholder="请选择状态"
+                    allowClear></v-select>
+                </a-form-item>
+              </a-col>
+            </template>
+            <a-col :md="6" :sm="24" style="margin-bottom: 10px;">
+              <a-button type="primary" @click="$refs.table.refresh(true)" :disabled="disabled" id="transferReturnConfirmation-refresh">查询</a-button>
+              <a-button style="margin-left: 5px" @click="resetSearchForm" :disabled="disabled" id="transferReturnConfirmation-reset">重置</a-button>
+              <a @click="advanced=!advanced" style="margin-left: 5px">
+                {{ advanced ? '收起' : '展开' }}
+                <a-icon :type="advanced ? 'up' : 'down'"/>
+              </a>
+            </a-col>
+          </a-row>
+        </a-form>
+      </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="allocateReturnNo" slot-scope="text, record">
+          <span v-if="$hasPermissions('M_allocateReturnConfirmationDetail')" class="link-bule" @click="handleDetail(record)">{{ record.allocateReturnNo }}</span>
+          <span v-else>{{ record.allocateReturnNo }}</span>
+        </template>
+        <!-- 操作 -->
+        <template slot="action" slot-scope="text, record">
+          <a-button
+            size="small"
+            type="link"
+            v-if="record.state=='WAIT_FINANCIAL_AUDIT' && $hasPermissions('B_allocateReturnConfirmationAudit')"
+            class="button-warning"
+            @click="handleAudit(record)"
+            id="transferReturnConfirmation-audit-btn">退货确认</a-button>
+          <span v-else>--</span>
+        </template>
+      </s-table>
+    </a-spin>
+    <!-- 查看 -->
+    <AllocateReturnDetailModal :openModal="openModal" :itemSn="itemSn" @close="closeModal" />
+  </a-card>
+</template>
+
+<script>
+import { commonMixin } from '@/utils/mixin'
+import rangeDate from '@/views/common/rangeDate.vue'
+import { STable, VSelect } from '@/components'
+import AllocateReturnDetailModal from './detailModal.vue'
+import { allocateReturnQueryConfirmPage, allocateReturnFinanceAudit } from '@/api/allocateReturn'
+export default {
+  name: 'AllocateReturnConfirmationList',
+  mixins: [commonMixin],
+  components: { STable, VSelect, AllocateReturnDetailModal, rangeDate },
+  data () {
+    return {
+      spinning: false,
+      tableHeight: 0,
+      queryParam: { //  查询条件
+        beginDate: '',
+        endDate: '',
+        allocateReturnNo: '', //  单号
+        targetName: '',
+        grabFlag: undefined,
+        state: undefined //  状态
+      },
+      disabled: false, //  查询、重置按钮是否可操作
+      advanced: true,
+      // 加载数据方法 必须为 Promise 对象
+      loadData: parameter => {
+        this.disabled = true
+        this.spinning = true
+        return allocateReturnQueryConfirmPage(Object.assign(parameter, this.queryParam)).then(res => {
+          let data
+          if (res.status == 200) {
+            data = res.data
+            const no = (data.pageNo - 1) * data.pageSize
+            for (var i = 0; i < data.list.length; i++) {
+              data.list[i].no = no + i + 1
+            }
+            this.disabled = false
+          }
+          this.spinning = false
+          return data
+        })
+      },
+      openModal: false,
+      itemSn: ''
+    }
+  },
+  // 根据权限显示列表字段
+  computed: {
+    columns () {
+      const arr = [
+        { title: '序号', dataIndex: 'no', width: '4%', align: 'center' },
+        { title: '创建时间', dataIndex: 'createDate', width: '11%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '退货单号', scopedSlots: { customRender: 'allocateReturnNo' }, width: '16%', align: 'center' },
+        { title: '调拨退货客户', dataIndex: 'targetName', align: 'center', width: '15%', customRender: function (text) { return text || '--' }, ellipsis: true },
+        { title: '是否抓单', dataIndex: 'grabFlagDictValue', width: '7%', align: 'center', customRender: function (text) { return text || '--' } },
+        { 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: '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 : '--') } })
+      // }
+      return arr
+    }
+  },
+  methods: {
+    //  创建时间  change
+    dateChange (date) {
+      this.queryParam.beginDate = date[0]
+      this.queryParam.endDate = date[1]
+    },
+    custChange (val) {
+      this.queryParam.buyerSn = val.key
+    },
+    //  重置
+    resetSearchForm () {
+      this.$refs.rangeDate.resetDate()
+      this.queryParam.beginDate = ''
+      this.queryParam.endDate = ''
+      this.queryParam.allocateReturnNo = ''
+      this.queryParam.targetName = ''
+      this.queryParam.grabFlag = undefined
+      this.queryParam.state = undefined
+      this.$refs.table.refresh(true)
+    },
+    // 详情
+    handleDetail (row) {
+      this.itemSn = row.allocateReturnSn
+      this.openModal = true
+    },
+    closeModal () {
+      this.itemSn = ''
+      this.openModal = false
+    },
+    // 单个审核
+    handleAudit (row) {
+      const _this = this
+      this.$confirm({
+        title: '提示',
+        content: '请点击下方按钮确认操作',
+        centered: true,
+        closable: true,
+        okText: '通过',
+        cancelText: '不通过',
+        onOk () {
+          _this.auditOrder(row.allocateReturnSn, 'FINISH')
+        },
+        onCancel (e) {
+          if (!e.triggerCancel) {
+            _this.auditOrder(row.allocateReturnSn, 'FINANCIAL_REJECT')
+          }
+          _this.$destroyAll()
+        }
+      })
+    },
+    auditOrder (sn, flag) {
+      const _this = this
+      _this.spinning = true
+      allocateReturnFinanceAudit({ allocateReturnSn: sn, state: flag }).then(res => {
+        if (res.status == 200) {
+          _this.$message.success(res.message)
+          _this.$refs.table.refresh()
+          _this.spinning = false
+        } else {
+          _this.spinning = false
+        }
+      })
+    },
+    pageInit () {
+      const _this = this
+      this.$nextTick(() => { // 页面渲染完成后的回调
+        _this.setTableH()
+      })
+    },
+    setTableH () {
+      const tableSearchH = this.$refs.tableSearch.offsetHeight
+      this.tableHeight = window.innerHeight - tableSearchH - 195
+    }
+  },
+  watch: {
+    advanced (newValue, oldValue) {
+      const _this = this
+      this.$nextTick(() => { // 页面渲染完成后的回调
+        _this.setTableH()
+      })
+    },
+    '$store.state.app.winHeight' (newValue, oldValue) { //  窗口变更时,需同时更改表格高度
+      this.setTableH()
+    }
+  },
+  mounted () {
+    if (!this.$store.state.app.isNewTab) { // 页签刷新时调用
+      this.pageInit()
+      this.resetSearchForm()
+    }
+  },
+  activated () {
+    // 如果是新页签打开,则重置当前页面
+    if (this.$store.state.app.isNewTab) {
+      this.pageInit()
+      this.resetSearchForm()
+    }
+    // 仅刷新列表,不重置页面
+    if (this.$store.state.app.updateList) {
+      this.pageInit()
+      this.$refs.table.refresh()
+    }
+  },
+  beforeRouteEnter (to, from, next) {
+    next(vm => {})
+  }
+}
+</script>
+
+<style lang="less">
+  .transferReturnConfirmation-wrap{
+    .active{
+      color: #ed1c24;
+      cursor: pointer;
+    }
+    .common{
+      color: rgba(0, 0, 0);
+    }
+  }
+</style>

+ 6 - 2
src/views/financialManagement/financialCollection/list.vue

@@ -144,11 +144,12 @@
         bordered>
         <!-- 单号 -->
         <template slot="bizNo" slot-scope="text, record">
-          <span :class="$hasPermissions('B_salesDetail')?'active':'common'"v-if="$hasPermissions('B_salesDetail')" @click="handleDetail(record)">{{ record.bizNo }}</span>
+          <span v-if="$hasPermissions('B_salesDetail')" class="link-bule" @click="handleDetail(record)">{{ record.bizNo }}</span>
+          <span v-else>{{ record.bizNo }}</span>
         </template>
         <!-- 下推单号 -->
         <template slot="dispatchBillNo" slot-scope="text, record">
-          <span :class="$hasPermissions('B_dispatchDetail')?'active':'common'" v-if="$hasPermissions('B_dispatchDetail')" @click="handleBhDetail(record)">{{ record.dispatchBillNo || '--' }}</span>
+          <span v-if="$hasPermissions('B_dispatchDetail')" class="link-bule" @click="handleBhDetail(record)">{{ record.dispatchBillNo }}</span>
           <span v-else>{{ record.dispatchBillNo || '--' }}</span>
         </template>
         <!-- 操作 -->
@@ -168,6 +169,7 @@
 </template>
 
 <script>
+import { commonMixin } from '@/utils/mixin'
 import moment from 'moment'
 import getDate from '@/libs/getDate.js'
 import { STable, VSelect } from '@/components'
@@ -176,6 +178,8 @@ import subarea from '@/views/common/subarea.js'
 import { getArea } from '@/api/data'
 import { settleReceiptList, settleReceipt } from '@/api/settleReceipt'
 export default {
+  name: 'FinancialCollectionList',
+  mixins: [commonMixin],
   components: { STable, VSelect, subarea, rangeDate },
   data () {
     return {

+ 3 - 0
src/views/financialManagement/inventoryConfirmation/detail.vue

@@ -102,9 +102,12 @@
 </template>
 
 <script>
+import { commonMixin } from '@/utils/mixin'
 import { STable, VSelect } from '@/components'
 import { checkWarehouseDetail, checkWarehouseDetailFinanceList, checkWarehouseDetailCount } from '@/api/checkWarehouse'
 export default {
+  name: 'InventoryConfirmationDetail',
+  mixins: [commonMixin],
   components: { STable, VSelect },
   data () {
     return {

+ 5 - 1
src/views/financialManagement/inventoryConfirmation/list.vue

@@ -37,7 +37,8 @@
         bordered>
         <!-- 单号 -->
         <template slot="checkWarehouseNo" slot-scope="text, record">
-          <span :class="$hasPermissions('B_inventoryConfirmationDetail')?'active':'common'" @click="handleDetail(record)">{{ record.checkWarehouseNo }}</span>
+          <span v-if="$hasPermissions('B_inventoryConfirmationDetail')" class="link-bule" @click="handleDetail(record)">{{ record.checkWarehouseNo }}</span>
+          <span v-else>{{ record.checkWarehouseNo }}</span>
         </template>
         <!-- 操作 -->
         <template slot="action" slot-scope="text, record">
@@ -63,9 +64,12 @@
 </template>
 
 <script>
+import { commonMixin } from '@/utils/mixin'
 import { STable, VSelect } from '@/components'
 import { checkWarehouseList, checkWarehouseReCheck, checkWarehouseFinanceAudit } from '@/api/checkWarehouse'
 export default {
+  name: 'InventoryConfirmationList',
+  mixins: [commonMixin],
   components: { STable, VSelect },
   data () {
     return {

+ 5 - 1
src/views/financialManagement/returnConfirmation/list.vue

@@ -69,7 +69,8 @@
         bordered>
         <!-- 销退单号 -->
         <template slot="salesReturnBillNo" slot-scope="text, record">
-          <span :class="$hasPermissions('B_returnConfirmation_detail')?'active':'common'" @click="handleDetail(record)">{{ record.salesReturnBillNo }}</span>
+          <span v-if="$hasPermissions('B_returnConfirmation_detail')" class="link-bule" @click="handleDetail(record)">{{ record.salesReturnBillNo }}</span>
+          <span v-else>{{ record.salesReturnBillNo }}</span>
         </template>
         <!-- 操作 -->
         <template slot="action" slot-scope="text, record">
@@ -90,12 +91,15 @@
 </template>
 
 <script>
+import { commonMixin } from '@/utils/mixin'
 import rangeDate from '@/views/common/rangeDate.vue'
 import { STable, VSelect } from '@/components'
 import dealerSubareaScopeList from '@/views/common/dealerSubareaScopeList.vue'
 import confirmationDetailModal from './detailModal.vue'
 import { salesReturnFinancialList, salesReturnFinancial } from '@/api/salesReturn'
 export default {
+  name: 'ReturnConfirmationList',
+  mixins: [commonMixin],
   components: { STable, VSelect, confirmationDetailModal, dealerSubareaScopeList, rangeDate },
   data () {
     return {

+ 7 - 3
src/views/financialManagement/warehousingConfirmation/list.vue

@@ -30,7 +30,7 @@
       </div>
       <!-- 列表 -->
       <div v-if="$hasPermissions('B_warehousingConfirmationpl')" style="margin-bottom: 10px">
-        <a-button type="primary" class="button-error" id="warehousingConfirmationList-export" :loading="loading" @click="handleBatchAudit">批量确认</a-button>
+        <a-button type="primary" class="button-info" id="warehousingConfirmationList-export" :loading="loading" @click="handleBatchAudit">批量确认</a-button>
         <span style="margin-left: 5px">
           <template v-if="rowSelectionInfo&&rowSelectionInfo.selectedRowKeys.length>0"> {{ `已选 ${rowSelectionInfo.selectedRowKeys.length} 项` }} </template>
         </span>
@@ -51,7 +51,8 @@
         bordered>
         <!-- 入库单号 -->
         <template slot="stockPutNo" slot-scope="text, record">
-          <span :class="$hasPermissions('B_warehousingConfirmationDetail')?'active':'common'" @click="handleDetail(record)">{{ record.stockPutNo }}</span>
+          <span v-if="$hasPermissions('B_warehousingConfirmationDetail')" class="link-bule" @click="handleDetail(record)">{{ record.stockPutNo }}</span>
+          <span v-else>{{ record.stockPutNo }}</span>
         </template>
         <!-- 操作 -->
         <template slot="action" slot-scope="text, record">
@@ -59,7 +60,7 @@
             size="small"
             type="link"
             v-if="record.auditState=='WAIT' && $hasPermissions('B_warehousingConfirmationAlone')"
-            class="button-warning"
+            class="button-info"
             @click="handleAudit(record)"
             id="warehousingConfirmationList-audit-btn">入库确认</a-button>
           <span v-else>--</span>
@@ -93,10 +94,13 @@
 </template>
 
 <script>
+import { commonMixin } from '@/utils/mixin'
 import { STable, VSelect } from '@/components'
 import confirmationDetailModal from './detailModal.vue'
 import { stockPutList, stockPutConfirm } from '@/api/stockPut'
 export default {
+  name: 'WarehousingConfirmationList',
+  mixins: [commonMixin],
   components: { STable, VSelect, confirmationDetailModal },
   data () {
     return {

+ 5 - 3
src/views/inventoryManagement/intelligentReplenishment/detailModal.vue

@@ -51,11 +51,13 @@
 </template>
 
 <script>
+import { commonMixin } from '@/utils/mixin'
 import moment from 'moment'
 import { STable } from '@/components'
 import { predictDetail, predictRangeList, predictstockPredictExport } from '@/api/predict'
 export default {
   name: 'IntelligentReplenishmentDetailModal',
+  mixins: [commonMixin],
   components: { STable },
   props: {
     openModal: { //  弹框显示状态
@@ -73,9 +75,9 @@ export default {
       spinning: false,
       detailsData: null, //  详情数据
       columns: [
-        { title: '序号', dataIndex: 'no', width:'10%', align: 'center' },
-        { title: '类型', dataIndex: 'rangeTypeName',width:'45%', align: 'center', customRender: function (text) { return text || '--' } },
-        { title: '类型名称', dataIndex: 'rangeDataName',width:'45%', align: 'center', customRender: function (text) { return text || '--' } }
+        { title: '序号', dataIndex: 'no', width: '10%', align: 'center' },
+        { title: '类型', dataIndex: 'rangeTypeName', width: '45%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '类型名称', dataIndex: 'rangeDataName', width: '45%', align: 'center', customRender: function (text) { return text || '--' } }
       ],
       loadData: [],
       detailData: null,

+ 3 - 0
src/views/inventoryManagement/intelligentReplenishment/edit.vue

@@ -83,10 +83,13 @@
 </template>
 
 <script>
+import { commonMixin } from '@/utils/mixin'
 import ReplenishmentServiceLevelModal from './serviceLevelModal.vue'
 import productRange from './productRange.vue'
 import { predictDetail, predictRangeSave, predictSave, predictTrendList, predictRun } from '@/api/predict'
 export default {
+  name: 'IntelligentReplenishmentEdit',
+  mixins: [commonMixin],
   components: { ReplenishmentServiceLevelModal, productRange },
   data () {
     return {

+ 3 - 0
src/views/inventoryManagement/intelligentReplenishment/import.vue

@@ -54,9 +54,12 @@
 </template>
 
 <script>
+import { commonMixin } from '@/utils/mixin'
 import { STable } from '@/components'
 import { predictProductInfoGoods, predictProductInfoInsert } from '@/api/predict'
 export default {
+  name: 'IntelligentReplenishmentImport',
+  mixins: [commonMixin],
   components: { STable },
   data () {
     return {

+ 3 - 0
src/views/inventoryManagement/intelligentReplenishment/list.vue

@@ -62,11 +62,14 @@
 </template>
 
 <script>
+import { commonMixin } from '@/utils/mixin'
 import moment from 'moment'
 import { STable, VSelect } from '@/components'
 import intelligentReplenishmentDetailModal from './detailModal.vue'
 import { predictList, predictSave, predictDel, predictstockPredictExport } from '@/api/predict'
 export default {
+  name: 'IntelligentReplenishmentList',
+  mixins: [commonMixin],
   components: { STable, VSelect, intelligentReplenishmentDetailModal },
   data () {
     return {

+ 3 - 0
src/views/inventoryManagement/intelligentReplenishment/productRange.vue

@@ -39,12 +39,15 @@
 </template>
 
 <script>
+import { commonMixin } from '@/utils/mixin'
 import { STable } from '@/components'
 import ChooseBrandModal from '@/views/common/chooseBrandModal.vue'
 import ChooseTypeModal from '@/views/common/chooseTypeModal.vue'
 import ChooseSupplierModal from '@/views/common/chooseSupplierModal.vue'
 import { predictRangeList, predictRangeDel } from '@/api/predict'
 export default {
+  name: 'ProductRange',
+  mixins: [commonMixin],
   components: { STable, ChooseBrandModal, ChooseTypeModal, ChooseSupplierModal },
   props: {
     itemSn: {

+ 3 - 0
src/views/inventoryManagement/intelligentReplenishment/set.vue

@@ -67,11 +67,14 @@
 </template>
 
 <script>
+import { commonMixin } from '@/utils/mixin'
 import moment from 'moment'
 import VueCookies from 'vue-cookies'
 import { Upload } from '@/components'
 import { predictProductInfoExport } from '@/api/predict'
 export default {
+  name: 'IntelligentReplenishmentSet',
+  mixins: [commonMixin],
   components: { Upload },
   data () {
     return {

+ 3 - 0
src/views/inventoryManagement/inventoryCheck/detail.vue

@@ -106,10 +106,13 @@
 </template>
 
 <script>
+import { commonMixin } from '@/utils/mixin'
 import { STable, VSelect } from '@/components'
 import tablePagination from '@/views/common/tablePagination.vue'
 import { checkWarehouseDetail, checkWarehouseDetailList, checkWarehouseDetailCount, checkWarehouseDelete } from '@/api/checkWarehouse'
 export default {
+  name: 'InventoryCheckDetail',
+  mixins: [commonMixin],
   components: { STable, VSelect, tablePagination },
   data () {
     return {

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

@@ -69,7 +69,7 @@
             size="small"
             type="link"
             v-if="$hasPermissions('B_inventoryCheckDetail')"
-            class="button-info"
+            class="button-success"
             @click="handleDetail(record)"
             id="inventoryCheckList-audit-btn">详情</a-button>
           <span v-else>--</span>
@@ -90,11 +90,14 @@
 </template>
 
 <script>
+import { commonMixin } from '@/utils/mixin'
 import { STable, VSelect } from '@/components'
 import inventoryCheckAddModal from './addModal.vue'
 import commonModal from '@/views/common/commonModal.vue'
 import { checkWarehouseList, checkWarehouseStartCheck } from '@/api/checkWarehouse'
 export default {
+  name: 'InventoryCheckList',
+  mixins: [commonMixin],
   components: { STable, VSelect, inventoryCheckAddModal, commonModal },
   data () {
     return {

+ 3 - 1
src/views/inventoryManagement/inventoryQuery/list.vue

@@ -114,7 +114,7 @@
 </template>
 
 <script>
-import moment from 'moment'
+import { commonMixin } from '@/utils/mixin'
 import { STable, VSelect } from '@/components'
 import inventoryQueryDetailModal from './detailModal.vue'
 import exportExcelModal from './exportExcelModal.vue'
@@ -124,6 +124,8 @@ import { hdExportExcel } from '@/libs/exportExcel'
 import ProductBrand from '@/views/common/productBrand.js'
 import { stockList, stockCount, stockExport } from '@/api/stock'
 export default {
+  name: 'InventoryQueryList',
+  mixins: [commonMixin],
   components: { STable, VSelect, inventoryQueryDetailModal, exportExcelModal, ProductBrand },
   data () {
     return {

+ 3 - 0
src/views/inventoryManagement/inventoryQuery/warehouseDetail.vue

@@ -129,12 +129,15 @@
 </template>
 
 <script>
+import { commonMixin } from '@/utils/mixin'
 import { STable, VSelect } from '@/components'
 import rangeDate from '@/views/common/rangeDate.vue'
 import { hdExportExcel } from '@/libs/exportExcel'
 import { stockFlowCount, stockFlowList, stockFlowExport } from '@/api/stock'
 import { warehouseAllList } from '@/api/warehouse'
 export default {
+  name: 'InventoryQueryWarehouseDetail',
+  mixins: [commonMixin],
   components: { STable, VSelect, rangeDate },
   data () {
     return {

+ 4 - 1
src/views/inventoryManagement/inventoryWarning/list.vue

@@ -149,7 +149,7 @@
         <template slot="action" slot-scope="text, record">
           <a-button
             v-if="$hasPermissions('B_inventoryWarning_save')"
-            type="primary"
+            type="link"
             size="small"
             class="button-info"
             @click="handleSave(record)"
@@ -162,12 +162,15 @@
 </template>
 
 <script>
+import { commonMixin } from '@/utils/mixin'
 import { STable, VSelect } from '@/components'
 import { productBrandQuery } from '@/api/productBrand'
 import { productTypeQuery } from '@/api/productType'
 import { stockWarnList, stockWarnSaveBatch } from '@/api/stock'
 import ProductBrand from '@/views/common/productBrand.js'
 export default {
+  name: 'InventoryWarningList',
+  mixins: [commonMixin],
   components: { STable, VSelect, ProductBrand },
   data () {
     return {

+ 3 - 0
src/views/inventoryManagement/makeInventory/check.vue

@@ -156,11 +156,14 @@
 </template>
 
 <script>
+import { commonMixin } from '@/utils/mixin'
 import { STable, VSelect } from '@/components'
 import tablePagination from '@/views/common/tablePagination.vue'
 import printModal from '@/views/common/auditModal.vue'
 import { checkWarehouseDetail, checkWarehouseDetailList, checkWarehouseDetailCount, checkWarehouseDetailPrint, checkWarehousePrintCheck, checkWarehouseDetailSave, checkWarehouseCheck } from '@/api/checkWarehouse'
 export default {
+  name: 'MakeInventoryCheck',
+  mixins: [commonMixin],
   components: { STable, VSelect, tablePagination, printModal },
   data () {
     return {

+ 3 - 0
src/views/inventoryManagement/makeInventory/list.vue

@@ -46,9 +46,12 @@
 </template>
 
 <script>
+import { commonMixin } from '@/utils/mixin'
 import { STable, VSelect } from '@/components'
 import { checkWarehouseList } from '@/api/checkWarehouse'
 export default {
+  name: 'MakeInventoryList',
+  mixins: [commonMixin],
   components: { STable, VSelect },
   data () {
     return {

+ 3 - 0
src/views/inventoryManagement/supervisionDisk/check.vue

@@ -165,11 +165,14 @@
 </template>
 
 <script>
+import { commonMixin } from '@/utils/mixin'
 import { STable, VSelect } from '@/components'
 import tablePagination from '@/views/common/tablePagination.vue'
 import printModal from '@/views/common/auditModal.vue'
 import { checkWarehouseDetail, checkWarehouseDetailList, checkWarehouseDetailCount, checkWarehouseDetailPrint, checkWarehousePrintCheck, checkWarehouseDetailSave, checkWarehouseSupervise, checkWarehouseReCheck } from '@/api/checkWarehouse'
 export default {
+  name: 'SupervisionDiskCheck',
+  mixins: [commonMixin],
   components: { STable, VSelect, tablePagination, printModal },
   data () {
     return {

+ 3 - 0
src/views/inventoryManagement/supervisionDisk/list.vue

@@ -46,9 +46,12 @@
 </template>
 
 <script>
+import { commonMixin } from '@/utils/mixin'
 import { STable, VSelect } from '@/components'
 import { checkWarehouseList } from '@/api/checkWarehouse'
 export default {
+  name: 'SupervisionDiskList',
+  mixins: [commonMixin],
   components: { STable, VSelect },
   data () {
     return {

+ 3 - 1
src/views/power/OperateJournal/OperateJournal.vue

@@ -47,12 +47,14 @@
 </template>
 
 <script>
+import { commonMixin } from '@/utils/mixin'
 import getDate from '@/libs/getDate'
 import { STable } from '@/components'
 import { journalList } from '@/api/OperateJournal.js'
 import rangeDate from '@/views/common/rangeDate.vue'
 export default {
-  name: 'OperateJournal',
+  name: 'PowerOperateJournal',
+  mixins: [commonMixin],
   components: { STable, rangeDate },
   data () {
     return {

+ 3 - 1
src/views/power/dataDictionary/dataDictionary.vue

@@ -99,12 +99,14 @@
 </template>
 
 <script>
+import { commonMixin } from '@/utils/mixin'
 import { STable, VSelect } from '@/components'
 import codeModal from './codeModal.vue'
 import codeItemModal from './codeItemModal.vue'
 import { listLookUp, delLookUp, getLookUpItem, delLookUpItem } from '@/api/lookup.js'
 export default {
-  name: 'DataDictionary',
+  name: 'PowerDD',
+  mixins: [commonMixin],
   components: {
     STable, VSelect, codeModal, codeItemModal
   },

+ 2 - 0
src/views/power/menu/menu.vue

@@ -187,12 +187,14 @@
 </template>
 
 <script>
+import { commonMixin } from '@/utils/mixin'
 import { STable, VSelect } from '@/components'
 import childModal from './childModal.vue'
 import { getMenuList, saveMenu, deleteMenu } from '@/api/menu.js'
 
 export default {
   name: 'Menu',
+  mixins: [commonMixin],
   components: {
     STable, VSelect, childModal
   },

+ 2 - 0
src/views/power/role/menuModal.vue

@@ -40,10 +40,12 @@
 </template>
 
 <script>
+import { commonMixin } from '@/utils/mixin'
 import { STable, VSelect } from '@/components'
 import { addMenuPower } from '@/api/power-role.js'
 export default {
   name: 'RoleModal',
+  mixins: [commonMixin],
   components: {
     STable, VSelect
   },

+ 8 - 2
src/views/power/role/roleList.vue

@@ -71,12 +71,13 @@
         </span>
       </s-table>
     </a-spin>
-    <roleModal :visible="showModal" @refresh="$refs.table.refresh(true)" :nowData="itemData" @close="showModal = false"></roleModal>
+    <roleModal :visible="showModal" @refresh="$refs.table.refresh(true)" :nowData="itemData" @close="closeRole"></roleModal>
     <menuModal :visible="showMenuModal" @refresh="$refs.table.refresh(true)" :nowData="menuData" @close="showMenuModal = false"></menuModal>
   </a-card>
 </template>
 
 <script>
+import { commonMixin } from '@/utils/mixin'
 import {
   STable,
   VSelect
@@ -90,7 +91,8 @@ import {
   getMenuList
 } from '@/api/power-role.js'
 export default {
-  name: 'RoleList',
+  name: 'PowerRoleList',
+  mixins: [commonMixin],
   components: {
     STable,
     VSelect,
@@ -146,6 +148,10 @@ export default {
     })
   },
   methods: {
+    closeRole () {
+      this.showModal = false
+      this.itemData = {}
+    },
     // 刷新列表
     refreshTable () {
       this.$refs.table.refresh(true)

+ 10 - 5
src/views/power/role/roleModal.vue

@@ -54,10 +54,12 @@
 </template>
 
 <script>
+import { commonMixin } from '@/utils/mixin'
 import { STable, VSelect } from '@/components'
 import { saveRolePower } from '@/api/power-role.js'
 export default {
   name: 'RoleModal',
+  mixins: [commonMixin],
   components: {
     STable, VSelect
   },
@@ -127,6 +129,13 @@ export default {
           return false
         }
       })
+    },
+    resetForm () {
+      this.$refs.ruleForm.resetFields()
+      this.form.name = ''
+      this.form.isEnable = undefined
+      this.form.remarks = ''
+      this.titleText = '新增角色'
     }
   },
   watch: {
@@ -136,11 +145,7 @@ export default {
     isshow (newValue, oldValue) {
       if (!newValue) {
         this.$emit('close')
-        this.$refs.ruleForm.resetFields()
-        this.form.name = ''
-        this.form.isEnable = undefined
-        this.form.remarks = ''
-        this.titleText = '新增角色'
+        this.resetForm()
       }
     },
     nowData: {

+ 2 - 0
src/views/power/user/updateAreal.vue

@@ -43,12 +43,14 @@
 </template>
 
 <script>
+import { commonMixin } from '@/utils/mixin'
 import { VSelect } from '@/components'
 import { userSubareaSave } from '@/api/power-user'
 import { subareaQueryAll } from '@/api/subarea'
 import subarea from '@/views/common/subarea.js'
 export default {
   name: 'UpdateArea',
+  mixins: [commonMixin],
   components: { VSelect, subarea },
   props: {
     openUdModal: { //  弹框显示状态

+ 3 - 1
src/views/power/user/userList.vue

@@ -83,12 +83,14 @@
 </template>
 
 <script>
+import { commonMixin } from '@/utils/mixin'
 import { STable, VSelect } from '@/components'
 import userModal from './userModal.vue'
 import { resetPSD, updateEnableStatus, getPowerUserList, delectUserPower } from '@/api/power-user.js'
 import UpdateArea from './updateAreal.vue'
 export default {
-  name: 'UserList',
+  name: 'PowerUserList',
+  mixins: [commonMixin],
   components: {
     STable, VSelect, userModal, UpdateArea
   },

+ 2 - 0
src/views/power/user/userModal.vue

@@ -104,10 +104,12 @@
 </template>
 
 <script>
+import { commonMixin } from '@/utils/mixin'
 import { STable, VSelect } from '@/components'
 import { getRoleList, saveUserPower } from '@/api/power-user.js'
 export default {
   name: 'UserModal',
+  mixins: [commonMixin],
   components: {
     STable, VSelect
   },

+ 5 - 6
src/views/productManagement/newProduct/detail.vue

@@ -48,10 +48,12 @@
 </template>
 
 <script>
+import { commonMixin } from '@/utils/mixin'
 import imgZoom from 'vue2.0-zoom'
 import { productSnDetail } from '@/api/product.js'
 export default {
-  name: 'ProductInfoDetail',
+  name: 'ViewProduct',
+  mixins: [commonMixin],
   components: { imgZoom },
   computed: {
     productTypeName () {
@@ -100,11 +102,8 @@ export default {
     }
   },
   activated () {
-    // 如果是新页签打开或者进入新的子页(例:存在列表第2条数据编辑页页签时再打开第4条数据的编辑页),则重置当前页面
-    if (this.$store.state.app.isNewTab || !this.$store.state.app.isNewSubTab) {
-      this.itemId = this.$route.params.sn
-      this.getDetail()
-    }
+    this.itemId = this.$route.params.sn
+    this.getDetail()
   },
   beforeRouteEnter (to, from, next) {
     next(vm => {

+ 3 - 0
src/views/productManagement/newProduct/list.vue

@@ -97,6 +97,7 @@
 </template>
 
 <script>
+import { commonMixin } from '@/utils/mixin'
 import { productBrandQuery } from '@/api/productBrand'
 import { productTypeQueryAll } from '@/api/productType'
 import { queryNewProductPage } from '@/api/product'
@@ -104,6 +105,8 @@ import { STable, VSelect } from '@/components'
 import ProductBrand from '@/views/common/productBrand.js'
 import rangeDate from '@/views/common/rangeDate.vue'
 export default {
+  name: 'NewProductList',
+  mixins: [commonMixin],
   components: { STable, VSelect, rangeDate, ProductBrand },
   data () {
     return {

+ 7 - 3
src/views/productManagement/newProduct/modal.vue

@@ -22,10 +22,12 @@
 </template>
 
 <script>
+import { commonMixin } from '@/utils/mixin'
 import { STable } from '@/components'
 import { queryNewProductPage } from '@/api/product'
 export default {
-  name: 'NewProduct',
+  name: 'NewProductListModal',
+  mixins: [commonMixin],
   components: { STable },
   props: {
     onlineFalg: { // 上下线标识  1为上线,0为下线
@@ -78,13 +80,15 @@ export default {
     }
   },
   mounted () {
-    this.$refs.table.refresh(true)
+    this.$nextTick(() => {
+      this.$refs.table.refresh(true)
+    })
   },
   watch: {
     onlineFalg (newValue, oldValue) {
       const _this = this
       setTimeout(() => {
-        _this.$refs.table.refresh(true)
+        _this.$refs.table && _this.$refs.table.refresh(true)
       }, 400)
     }
   }

+ 3 - 0
src/views/productManagement/priceChangeRecord/list.vue

@@ -108,6 +108,7 @@
 </template>
 
 <script>
+import { commonMixin } from '@/utils/mixin'
 import moment from 'moment'
 import getDate from '@/libs/getDate.js'
 import { STable, VSelect } from '@/components'
@@ -117,6 +118,8 @@ import { productTypeQuery } from '@/api/productType'
 import ProductBrand from '@/views/common/productBrand.js'
 import { productPriceChangeList, productPriceChangeExport } from '@/api/product'
 export default {
+  name: 'PriceChangeRecordList',
+  mixins: [commonMixin],
   components: { STable, VSelect, rangeDate, ProductBrand },
   data () {
     return {

+ 2 - 0
src/views/productManagement/productBrand/editModal.vue

@@ -59,12 +59,14 @@
 </template>
 
 <script>
+import { commonMixin } from '@/utils/mixin'
 import { VSelect, Upload } from '@/components'
 import Editor from '@/components/WEeditor'
 import dataList from '@/libs/commonData'
 import { productBrandSnDetail, productBrandSave } from '@/api/productBrand'
 export default {
   name: 'ProductBrandEditModal',
+  mixins: [commonMixin],
   components: { VSelect, Upload, Editor },
   props: {
     openModal: { //  弹框显示状态

+ 3 - 0
src/views/productManagement/productBrand/list.vue

@@ -95,12 +95,15 @@
 </template>
 
 <script>
+import { commonMixin } from '@/utils/mixin'
 import { STable, VSelect } from '@/components'
 import dataList from '@/libs/commonData'
 import productBrandEditModal from './editModal.vue'
 import productBrandDetailModal from './detailModal.vue'
 import { productBrandList, productBrandDel } from '@/api/productBrand'
 export default {
+  name: 'ProductBrandList',
+  mixins: [commonMixin],
   components: { STable, VSelect, productBrandEditModal, productBrandDetailModal },
   data () {
     return {

Деякі файли не було показано, через те що забагато файлів було змінено