chenrui 3 gadi atpakaļ
vecāks
revīzija
cacdd75d1f

+ 136 - 0
src/api/checkWarehouse.js

@@ -0,0 +1,136 @@
+import { axios } from '@/utils/request'
+
+//  库存盘点  列表  分页
+export const checkWarehouseList = (params) => {
+  const url = `/checkWarehouse/queryPage/${params.pageNo}/${params.pageSize}`
+  delete params.pageNo
+  delete params.pageSize
+  return axios({
+    url: url,
+    data: params,
+    method: 'post'
+  })
+}
+//  库存盘点  保存
+export const checkWarehouseSave = (params) => {
+  return axios({
+    url: '/checkWarehouse/save',
+    data: params,
+    method: 'post'
+  })
+}
+//  库存盘点  详情
+export const checkWarehouseDetail = (params) => {
+  return axios({
+    url: `/checkWarehouse/queryBySn/${params.sn}`,
+    method: 'get'
+  })
+}
+//  库存盘点  详情  分页
+export const checkWarehouseDetailList = (params) => {
+  const url = `/checkWarehouse/detail/queryPage/${params.pageNo}/${params.pageSize}`
+  delete params.pageNo
+  delete params.pageSize
+  return axios({
+    url: url,
+    data: params,
+    method: 'post'
+  })
+}
+//  库存盘点  详情  合计
+export const checkWarehouseDetailCount = (params) => {
+  return axios({
+    url: '/checkWarehouse/detail/queryCount',
+    data: params,
+    method: 'post'
+  })
+}
+// 盘点人盘点/监盘人监盘 盘点  打印
+export const checkWarehouseDetailPrint = params => {
+  const url = `/checkWarehouse/detail/print/${params.checkWarehouseSn}/${params.type}`
+  delete params.checkWarehouseSn
+  delete params.type
+  return axios.request({
+    url: url,
+    data: params,
+    method: 'post',
+    responseType: 'blob'
+  })
+}
+//  库存盘点  新增盘点  检查是否有未完结
+export const checkWarehouseStartCheck = (params) => {
+  return axios({
+    url: '/checkWarehouse/startCheck',
+    method: 'get'
+  })
+}
+//  盘点人盘点/监盘人监盘  盘点  打印检查产品
+export const checkWarehousePrintCheck = (params) => {
+  const url = `/checkWarehouse/detail/printCheck/${params.checkWarehouseSn}/${params.type}`
+  delete params.checkWarehouseSn
+  delete params.type
+  return axios({
+    url: url,
+    data: {},
+    method: 'get'
+  })
+}
+//  盘点人盘点/监盘人监盘  详情  保存
+export const checkWarehouseDetailSave = (params) => {
+  return axios({
+    url: '/checkWarehouse/detail/save',
+    data: params,
+    method: 'post'
+  })
+}
+//  盘点人盘点  盘点
+export const checkWarehouseCheck = (params) => {
+  return axios({
+    url: '/checkWarehouse/checkWarehouse',
+    data: params,
+    method: 'post'
+  })
+}
+//  库存盘点  作废
+export const checkWarehouseDelete = (params) => {
+  return axios({
+    url: '/checkWarehouse/delete',
+    data: params,
+    method: 'post'
+  })
+}
+//  盘点人盘点  监盘
+export const checkWarehouseSupervise = (params) => {
+  return axios({
+    url: '/checkWarehouse/checkSupervise',
+    data: params,
+    method: 'post'
+  })
+}
+//  盘点人盘点  重盘
+export const checkWarehouseReCheck = (params) => {
+  return axios({
+    url: '/checkWarehouse/reCheckWarehouse',
+    data: params,
+    method: 'post'
+  })
+}
+//  盘点人盘点  财务确认
+export const checkWarehouseFinanceAudit = (params) => {
+  return axios({
+    url: '/checkWarehouse/financeAudit',
+    data: params,
+    method: 'post'
+  })
+}
+//  财务盘点确认  详情  列表  分页
+export const checkWarehouseDetailFinanceList = (params) => {
+  const url = `/checkWarehouse/detail/queryFinanceAuditPage/${params.pageNo}/${params.pageSize}`
+  delete params.pageNo
+  delete params.pageSize
+  return axios({
+    url: url,
+    data: params,
+    method: 'post'
+  })
+}

+ 144 - 36
src/config/router.config.js

@@ -526,6 +526,42 @@ export const asyncRouterMap = [
               }
               }
             ]
             ]
           },
           },
+          {
+            path: '/financialManagement/inventoryConfirmation',
+            redirect: '/financialManagement/inventoryConfirmation/list',
+            name: 'inventoryConfirmation',
+            component: BlankLayout,
+            meta: {
+              title: '盘点确认',
+              icon: 'monitor',
+              permission: 'M_inventoryConfirmationList'
+            },
+            hideChildrenInMenu: true,
+            children: [
+              {
+                path: 'list',
+                name: 'inventoryConfirmationList',
+                component: () => import(/* webpackChunkName: "financialManagement" */ '@/views/financialManagement/inventoryConfirmation/list.vue'),
+                meta: {
+                  title: '盘点确认列表',
+                  icon: 'monitor',
+                  hidden: true,
+                  permission: 'M_inventoryConfirmationList'
+                }
+              },
+              {
+                path: 'detail/:sn',
+                name: 'inventoryConfirmationDetail',
+                component: () => import(/* webpackChunkName: "financialManagement" */ '@/views/financialManagement/inventoryConfirmation/detail.vue'),
+                meta: {
+                  title: '盘点确认详情',
+                  icon: 'monitor',
+                  hidden: true,
+                  permission: 'B_inventoryConfirmationDetail'
+                }
+              }
+            ]
+          },
           {
           {
             path: '/financialManagement/financialCollection',
             path: '/financialManagement/financialCollection',
             redirect: '/financialManagement/financialCollection/list',
             redirect: '/financialManagement/financialCollection/list',
@@ -600,42 +636,114 @@ export const asyncRouterMap = [
               }
               }
             ]
             ]
           },
           },
-          // {
-          //   path: '/inventoryManagement/inventoryCheck',
-          //   redirect: '/inventoryManagement/inventoryCheck/list',
-          //   name: 'inventoryCheck',
-          //   component: BlankLayout,
-          //   meta: {
-          //     title: '库存盘点',
-          //     icon: 'monitor'
-          //     // permission: 'M_inventoryCheckList'
-          //   },
-          //   hideChildrenInMenu: true,
-          //   children: [
-          //     {
-          //       path: 'list',
-          //       name: 'inventoryCheckList',
-          //       component: () => import(/* webpackChunkName: "inventoryManagement" */ '@/views/inventoryManagement/inventoryCheck/list.vue'),
-          //       meta: {
-          //         title: '库存盘点列表',
-          //         icon: 'monitor',
-          //         hidden: true
-          //         // permission: 'M_inventoryCheckList'
-          //       }
-          //     },
-          //     {
-          //       path: 'detail/:sn',
-          //       name: 'inventoryCheckDetail',
-          //       component: () => import(/* webpackChunkName: "inventoryManagement" */ '@/views/inventoryManagement/inventoryCheck/detail.vue'),
-          //       meta: {
-          //         title: '库存盘点详情',
-          //         icon: 'monitor',
-          //         hidden: true
-          //         // permission: 'B_goodsManage_edit'
-          //       }
-          //     }
-          //   ]
-          // },
+          {
+            path: '/inventoryManagement/inventoryCheck',
+            redirect: '/inventoryManagement/inventoryCheck/list/0',
+            name: 'inventoryCheck',
+            component: BlankLayout,
+            meta: {
+              title: '库存盘点',
+              icon: 'monitor',
+              permission: 'M_inventoryCheckList'
+            },
+            hideChildrenInMenu: true,
+            children: [
+              {
+                path: 'list/:type',
+                name: 'inventoryCheckList',
+                component: () => import(/* webpackChunkName: "inventoryManagement" */ '@/views/inventoryManagement/inventoryCheck/list.vue'),
+                meta: {
+                  title: '库存盘点列表',
+                  icon: 'monitor',
+                  hidden: true,
+                  permission: 'M_inventoryCheckList'
+                }
+              },
+              {
+                path: 'detail/:sn',
+                name: 'inventoryCheckDetail',
+                component: () => import(/* webpackChunkName: "inventoryManagement" */ '@/views/inventoryManagement/inventoryCheck/detail.vue'),
+                meta: {
+                  title: '库存盘点详情',
+                  icon: 'monitor',
+                  hidden: true,
+                  permission: 'B_inventoryCheckDetail'
+                }
+              }
+            ]
+          },
+          {
+            path: '/inventoryManagement/makeInventory',
+            redirect: '/inventoryManagement/makeInventory/list',
+            name: 'makeInventory',
+            component: BlankLayout,
+            meta: {
+              title: '盘点人盘点',
+              icon: 'monitor',
+              permission: 'M_inventoryMakeInventoryList'
+            },
+            hideChildrenInMenu: true,
+            children: [
+              {
+                path: 'list',
+                name: 'makeInventoryList',
+                component: () => import(/* webpackChunkName: "inventoryManagement" */ '@/views/inventoryManagement/makeInventory/list.vue'),
+                meta: {
+                  title: '盘点人盘点列表',
+                  icon: 'monitor',
+                  hidden: true,
+                  permission: 'M_inventoryMakeInventoryList'
+                }
+              },
+              {
+                path: 'check/:sn',
+                name: 'makeInventoryCheck',
+                component: () => import(/* webpackChunkName: "inventoryManagement" */ '@/views/inventoryManagement/makeInventory/check.vue'),
+                meta: {
+                  title: '盘点人盘点',
+                  icon: 'monitor',
+                  hidden: true,
+                  permission: 'B_inventoryMakeInventoryCheck'
+                }
+              }
+            ]
+          },
+          {
+            path: '/inventoryManagement/supervisionDisk',
+            redirect: '/inventoryManagement/supervisionDisk/list',
+            name: 'supervisionDisk',
+            component: BlankLayout,
+            meta: {
+              title: '监盘人盘点',
+              icon: 'monitor',
+              permission: 'M_supervisionDiskList'
+            },
+            hideChildrenInMenu: true,
+            children: [
+              {
+                path: 'list',
+                name: 'supervisionDiskList',
+                component: () => import(/* webpackChunkName: "inventoryManagement" */ '@/views/inventoryManagement/supervisionDisk/list.vue'),
+                meta: {
+                  title: '监盘人盘点列表',
+                  icon: 'monitor',
+                  hidden: true,
+                  permission: 'M_supervisionDiskList'
+                }
+              },
+              {
+                path: 'check/:sn',
+                name: 'supervisionDiskCheck',
+                component: () => import(/* webpackChunkName: "inventoryManagement" */ '@/views/inventoryManagement/supervisionDisk/check.vue'),
+                meta: {
+                  title: '监盘人监盘',
+                  icon: 'monitor',
+                  hidden: true,
+                  permission: 'B_supervisionDiskCheck'
+                }
+              }
+            ]
+          },
           {
           {
             path: '/inventoryManagement/inventoryWarning',
             path: '/inventoryManagement/inventoryWarning',
             name: 'inventoryWarningList',
             name: 'inventoryWarningList',

+ 14 - 2
src/views/common/auditModal.vue

@@ -16,8 +16,8 @@
         </div>
         </div>
       </div>
       </div>
       <div class="btn-box">
       <div class="btn-box">
-        <a-button type="primary" class="button-error" @click="handleAuditFail">审核不通过</a-button>
-        <a-button type="primary" class="button-info" @click="handleAuditOk">审核通过</a-button>
+        <a-button type="primary" class="button-warning" @click="handleAuditFail" v-if="isCancel">{{ cancelText || '审核不通过' }}</a-button>
+        <a-button type="primary" class="button-info" @click="handleAuditOk">{{ okText || '审核通过' }}</a-button>
       </div>
       </div>
     </a-spin>
     </a-spin>
   </a-modal>
   </a-modal>
@@ -35,6 +35,18 @@ export default {
       type: String,
       type: String,
       default: '请点击下方按钮确认操作?'
       default: '请点击下方按钮确认操作?'
     },
     },
+    okText: {
+      type: String,
+      default: '审核通过'
+    },
+    cancelText: {
+      type: String,
+      default: '审核不通过'
+    },
+    isCancel: {
+      type: Boolean,
+      default: true
+    },
     spinning: {
     spinning: {
       type: Boolean,
       type: Boolean,
       default: false
       default: false

+ 112 - 0
src/views/common/commonModal.vue

@@ -0,0 +1,112 @@
+<template>
+  <a-modal
+    centered
+    class="common-modal"
+    :footer="null"
+    :maskClosable="false"
+    v-model="isShow"
+    :title="modalTit"
+    @cancle="isShow=false"
+    :width="416">
+    <a-spin :spinning="spinning" tip="Loading...">
+      <div class="common-main" v-html="modalHtml"></div>
+      <div class="btn-box">
+        <a-button type="primary" class="button-warning" @click="handleCommonCancel" v-if="isCancel">{{ cancelText }}</a-button>
+        <a-button type="primary" class="button-info" @click="handleCommonOk">{{ okText }}</a-button>
+      </div>
+    </a-spin>
+  </a-modal>
+</template>
+
+<script>
+export default {
+  name: 'CommonModal',
+  props: {
+    openModal: { //  弹框显示状态
+      type: Boolean,
+      default: false
+    },
+    modalTit: { // 弹框标题
+      type: String,
+      default: null
+    },
+    modalHtml: {
+      type: String,
+      default: ''
+    },
+    okText: { // 确定 按钮文字
+      type: String,
+      default: '确定'
+    },
+    cancelText: { // 取消 按钮文字
+      type: String,
+      default: '取消'
+    },
+    isCancel: { // 是否显示  取消 按钮
+      type: Boolean,
+      default: true
+    },
+    spinning: { // 加载中
+      type: Boolean,
+      default: false
+    }
+  },
+  data () {
+    return {
+      isShow: this.openModal //  是否打开弹框
+    }
+  },
+  methods: {
+    // 确定
+    handleCommonOk () {
+      this.$emit('ok')
+    },
+    // 取消
+    handleCommonCancel () {
+      this.$emit('cancel')
+    }
+  },
+  watch: {
+    //  父页面传过来的弹框状态
+    openModal (newValue, oldValue) {
+      this.isShow = newValue
+    },
+    //  重定义的弹框状态
+    isShow (newValue, oldValue) {
+      if (!newValue) {
+        this.$emit('close')
+      }
+    }
+  }
+}
+</script>
+
+<style lang="less">
+  .common-modal{
+    .ant-modal-body{
+      padding: 32px 32px 24px;
+    }
+    .common-main{
+      display: flex;
+      .common-cont{
+        .common-tit{
+          color: rgba(0, 0, 0, 0.85);
+          font-weight: 500;
+          font-size: 16px;
+          line-height: 1.4;
+          margin: 0;
+        }
+        .common-txt{
+          margin: 8px 0 0;
+          color: rgba(0, 0, 0, 0.65);
+          font-size: 14px;
+          line-height: 1.5;
+        }
+      }
+    }
+    .btn-box{
+      text-align: right;
+      margin-top: 24px;
+    }
+  }
+</style>

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

@@ -0,0 +1,225 @@
+<template>
+  <div class="inventoryConfirmationDetail-wrap">
+    <a-spin :spinning="spinning" tip="Loading...">
+      <a-page-header :ghost="false" :backIcon="false" @back="handleBack" class="inventoryConfirmationDetail-cont" >
+        <!-- 自定义的二级文字标题 -->
+        <template slot="subTitle">
+          <a id="inventoryConfirmationDetail-back-btn" href="javascript:;" @click="handleBack"><a-icon type="left" /> 返回列表</a>
+          <span class="billno">单号:{{ detail&&detail.checkWarehouseNo }}</span>
+        </template>
+      </a-page-header>
+      <!-- 基础信息 -->
+      <a-card size="small" :bordered="false" class="inventoryConfirmationDetail-cont">
+        <a-collapse>
+          <a-collapse-panel key="1" header="基础信息">
+            <a-descriptions :column="3">
+              <a-descriptions-item label="创建人">{{ (detail&&detail.creatorName) || '--' }}</a-descriptions-item>
+              <a-descriptions-item label="创建时间">{{ (detail&&detail.createDate) || '--' }}</a-descriptions-item>
+              <a-descriptions-item label="盘点类型">{{ (detail&&detail.checkTypeDictValue) || '--' }}</a-descriptions-item>
+              <a-descriptions-item label="盘点状态">{{ (detail&&detail.checkStateDictValue) || '--' }}</a-descriptions-item>
+              <a-descriptions-item label="盘点人">{{ (detail&&detail.checkPersonName) || '--' }}</a-descriptions-item>
+              <a-descriptions-item label="盘点时间">{{ (detail&&detail.checkTime) || '--' }}</a-descriptions-item>
+              <a-descriptions-item label="监盘状态">{{ (detail&&detail.checkSuperviseStateDictValue) || '--' }}</a-descriptions-item>
+              <a-descriptions-item label="监盘人">{{ (detail&&detail.checkSupervisePersonName) || '--' }}</a-descriptions-item>
+              <a-descriptions-item label="监盘时间">{{ (detail&&detail.checkSuperviseTime) || '--' }}</a-descriptions-item>
+              <a-descriptions-item label="财务确认时间">{{ (detail&&detail.financeAuditTime) || '--' }}</a-descriptions-item>
+            </a-descriptions>
+          </a-collapse-panel>
+        </a-collapse>
+      </a-card>
+      <!-- 产品详情 -->
+      <a-card size="small" :bordered="false" class="inventoryConfirmationDetail-cont">
+        <!-- 总计 -->
+        <a-alert type="info" style="margin-bottom:10px">
+          <div slot="message">
+            盘盈数量:<strong :style="{ color: productTotal && productTotal.profitQty>0?'red':productTotal && productTotal.profitQty<0?'green':'' }">{{ productTotal && (productTotal.profitQty || productTotal.profitQty==0) ? productTotal.profitQty : '--' }}</strong>,
+            盘盈金额:<strong :style="{ color: productTotal && productTotal.profitCost>0?'red':productTotal && productTotal.profitCost<0?'green':'' }">{{ productTotal && (productTotal.profitCost || productTotal.profitCost==0) ? productTotal.profitCost : '--' }}</strong>,
+            盘亏数量:<strong :style="{ color: productTotal && productTotal.lossQty>0?'red':productTotal && productTotal.lossQty<0?'green':'' }">{{ productTotal && (productTotal.lossQty || productTotal.lossQty==0) ? productTotal.lossQty : '--' }}</strong>,
+            盘亏金额:<strong :style="{ color: productTotal && productTotal.lossCost>0?'red':productTotal && productTotal.lossCost<0?'green':'' }">{{ productTotal && (productTotal.lossCost || productTotal.lossCost==0) ? productTotal.lossCost : '--' }}</strong>,
+            盈亏总数量:<strong :style="{ color: productTotal && productTotal.profitLossQty>0?'red':productTotal && productTotal.profitLossQty<0?'green':'' }">{{ productTotal && (productTotal.profitLossQty	|| productTotal.profitLossQty ==0) ? productTotal.profitLossQty : '--' }}</strong>,
+            盈亏总金额:<strong :style="{ color: productTotal && productTotal.profitLossCost>0?'red':productTotal && productTotal.profitLossCost<0?'green':'' }">{{ productTotal && (productTotal.profitLossCost || productTotal.profitLossCost==0) ? productTotal.profitLossCost : '--' }}</strong>
+          </div>
+        </a-alert>
+        <!-- 搜索条件 -->
+        <div class="table-page-search-wrapper">
+          <a-row :gutter="15">
+            <a-col :span="18">
+              <a-form-model :model="queryParam" layout="inline" @keyup.enter.native="$refs.table.refresh(true)" >
+                <a-row :gutter="15">
+                  <a-col :md="8" :sm="24">
+                    <a-form-model-item label="产品编码">
+                      <a-input v-model="queryParam.productCode" allowClear placeholder="输入产品编码" />
+                    </a-form-model-item>
+                  </a-col>
+                  <a-col :md="8" :sm="24">
+                    <a-form-model-item style="margin-bottom: 10px;">
+                      <a-button type="primary" @click="$refs.table.refresh(true)" :disabled="disabled" id="inventoryConfirmationDetail-refresh">查询</a-button>
+                      <a-button style="margin-left: 5px" @click="resetSearchForm" id="inventoryConfirmationDetail-reset">重置</a-button>
+                    </a-form-model-item>
+                  </a-col>
+                </a-row>
+              </a-form-model>
+            </a-col>
+            <a-col :span="6">
+              <div style="float:right;overflow: hidden;">
+                <a-checkbox v-model="foldState" @change="foldStateChange"><span style="display: inline-block;margin-top: 1px;">仅显示盈亏</span></a-checkbox>
+              </div>
+            </a-col>
+          </a-row>
+        </div>
+        <!-- 列表 -->
+        <s-table
+          class="sTable"
+          ref="table"
+          size="small"
+          :rowKey="(record) => record.id"
+          :columns="columns"
+          :data="loadData"
+          :defaultLoadData="false"
+          bordered>
+          <!-- 盈亏数量 -->
+          <template slot="profitLossQty" slot-scope="text, record">
+            <span :style="{ color: record.profitLossQty>0?'red':record.profitLossQty<0?'green':'', fontWeight: record.profitLossQty!=0?'bold':'' }">
+              {{ (record.profitLossQty || record.profitLossQty==0) ? record.profitLossQty : '--' }}
+            </span>
+          </template>
+          <!-- 盈亏金额 -->
+          <template slot="profitLossCost" slot-scope="text, record">
+            <span :style="{ color: record.profitLossCost>0?'red':record.profitLossCost<0?'green':'', fontWeight: record.profitLossCost!=0?'bold':'' }">
+              {{ (record.profitLossCost || record.profitLossCost==0) ? record.profitLossCost : '--' }}
+            </span>
+          </template>
+        </s-table>
+      </a-card>
+    </a-spin>
+  </div>
+</template>
+
+<script>
+import { STable, VSelect } from '@/components'
+import { checkWarehouseDetail, checkWarehouseDetailFinanceList, checkWarehouseDetailCount } from '@/api/checkWarehouse'
+export default {
+  components: { STable, VSelect },
+  data () {
+    return {
+      spinning: false,
+      disabled: false,
+      queryParam: {
+        profitLossFlag: undefined,
+        productCode: ''
+      },
+      // 表头
+      columns: [
+        { title: '序号', dataIndex: 'no', width: '4%', align: 'center' },
+        { title: '产品名称', dataIndex: 'productName', width: '11%', align: 'left', customRender: function (text) { return text || '--' }, ellipsis: true },
+        { title: '单位', dataIndex: 'productUnit', width: '4%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '仓库', dataIndex: 'warehouseName', width: '10%', align: 'center', customRender: function (text) { return text || '--' }, ellipsis: true },
+        { title: '仓位', dataIndex: 'warehouseLocationName', width: '10%', align: 'center', customRender: function (text) { return text || '--' }, ellipsis: true },
+        { title: '入库时间', dataIndex: 'lastStockTime', width: '10%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '批次', dataIndex: 'stockBatchNo', width: '6%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '产品编码', dataIndex: 'productCode', width: '10%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '库存数量', dataIndex: 'stockQty', width: '6%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
+        { title: '盘点数量', dataIndex: 'checkQty', width: '6%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
+        { title: '监盘数量', dataIndex: 'checkSuperviseQty', width: '6%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
+        { title: '单价', dataIndex: 'checkCost', width: '5%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
+        { title: '盈亏数量', dataIndex: 'profitLossQty', scopedSlots: { customRender: 'profitLossQty' }, width: '6%', align: 'center' },
+        { title: '盈亏金额', dataIndex: 'profitLossCost', scopedSlots: { customRender: 'profitLossCost' }, width: '6%', align: 'center' }
+      ],
+      // 加载数据方法 必须为 Promise 对象
+      loadData: parameter => {
+        this.disabled = true
+        this.spinning = true
+        const params = Object.assign(parameter, this.queryParam, { checkWarehouseSn: this.$route.params.sn })
+        return checkWarehouseDetailFinanceList(params).then(res => {
+          this.getCount(params)
+          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
+          }
+          this.disabled = false
+          this.spinning = false
+          return data
+        })
+      },
+      detail: null, //  详情数据
+      foldState: false, //  是否仅显示盈亏
+      productTotal: null //  合计
+    }
+  },
+  methods: {
+    //  返回列表
+    handleBack () {
+      this.$router.push({ path: '/financialManagement/inventoryConfirmation/list', query: { closeLastOldTab: true } })
+    },
+    // 重置
+    resetSearchForm () {
+      this.queryParam.productCode = ''
+      this.$refs.table.refresh(true)
+    },
+    getCount (params) {
+      checkWarehouseDetailCount(params).then(res => {
+        if (res.status == 200) {
+          this.productTotal = res.data
+        } else {
+          this.productTotal = null
+        }
+      })
+    },
+    //  详情
+    getDetail () {
+      checkWarehouseDetail({ sn: this.$route.params.sn }).then(res => {
+        if (res.status == 200) {
+          this.detail = res.data
+        } else {
+          this.detail = null
+        }
+      })
+    },
+    // 折叠列表
+    foldStateChange (e) {
+      if (e.target.checked) {
+        this.queryParam.profitLossFlag = 1
+        this.$refs.table.refresh(true)
+      } else {
+        this.queryParam.profitLossFlag = undefined
+        this.$refs.table.refresh(true)
+      }
+    }
+  },
+  mounted () {
+    if (!this.$store.state.app.isNewTab) { // 页签刷新时调用
+      this.$refs.table.refresh(true)
+      this.getDetail()
+    }
+  },
+  activated () {
+    // 如果是新页签打开或者进入新的子页(例:存在列表第2条数据编辑页页签时再打开第4条数据的编辑页),则重置当前页面
+    if (this.$store.state.app.isNewTab || !this.$store.state.app.isNewSubTab) {
+      this.$refs.table.refresh(true)
+      this.getDetail()
+    }
+  },
+  beforeRouteEnter (to, from, next) {
+    next(vm => {})
+  }
+}
+</script>
+
+<style lang="less">
+  .inventoryConfirmationDetail-wrap{
+    .inventoryConfirmationDetail-cont{
+      margin-bottom: 10px;
+      .billno{
+        font-size: 16px;
+        font-weight: bold;
+        margin: 0 15px;
+      }
+      .state-c{
+        color: #ed1c24;
+        font-size: 13px;
+        font-weight: bold;
+      }
+    }
+  }
+</style>

+ 236 - 0
src/views/financialManagement/inventoryConfirmation/list.vue

@@ -0,0 +1,236 @@
+<template>
+  <a-card size="small" :bordered="false" class="inventoryConfirmationList-wrap">
+    <a-spin :spinning="spinning" tip="Loading...">
+      <!-- 标签页 -->
+      <a-tabs type="card" :default-active-key="queryParam.state" @change="handleTabChange" class="inventoryConfirmationList-tabs ">
+        <a-tab-pane v-for="item in tabPaneData" :key="item.type">
+          <span slot="tab">{{ item.name }}</span>
+        </a-tab-pane>
+      </a-tabs>
+      <!-- 搜索条件 -->
+      <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="盘点单号">
+                <a-input id="inventoryConfirmationList-checkWarehouseNo" v-model.trim="queryParam.checkWarehouseNo" allowClear placeholder="请输入盘点单号"/>
+              </a-form-item>
+            </a-col>
+            <a-col :md="6" :sm="24">
+              <a-button type="primary" @click="$refs.table.refresh(true)" :disabled="disabled" id="inventoryConfirmationList-refresh">查询</a-button>
+              <a-button style="margin-left: 5px" @click="resetSearchForm" :disabled="disabled" id="inventoryConfirmationList-reset">重置</a-button>
+            </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="checkWarehouseNo" slot-scope="text, record">
+          <span :class="$hasPermissions('B_inventoryConfirmationDetail')?'active':'common'" @click="handleDetail(record)">{{ record.checkWarehouseNo }}</span>
+        </template>
+        <!-- 操作 -->
+        <template slot="action" slot-scope="text, record">
+          <a-button
+            size="small"
+            type="link"
+            class="button-info"
+            v-if="$hasPermissions('B_inventoryConfirmationConfirm')"
+            @click="handleConfirm(record)"
+            id="inventoryConfirmationList-audit-btn">盘点确认</a-button>
+          <a-button
+            size="small"
+            type="link"
+            class="button-success"
+            v-if="$hasPermissions('B_inventoryConfirmationCheck')"
+            @click="handleCheck(record)"
+            id="inventoryConfirmationList-audit-btn">重新盘点</a-button>
+          <span v-if="!($hasPermissions('B_inventoryConfirmationConfirm') && $hasPermissions('B_inventoryConfirmationCheck'))">--</span>
+        </template>
+      </s-table>
+    </a-spin>
+  </a-card>
+</template>
+
+<script>
+import { STable, VSelect } from '@/components'
+import { checkWarehouseList, checkWarehouseReCheck, checkWarehouseFinanceAudit } from '@/api/checkWarehouse'
+export default {
+  components: { STable, VSelect },
+  data () {
+    return {
+      spinning: false,
+      tableHeight: 0,
+      queryParam: { //  查询条件
+        state: 'WAIT_FINANCE_AUDIT',
+        checkWarehouseNo: ''
+      },
+      disabled: false, //  查询、重置按钮是否可操作
+      tabPaneData: [
+        { name: '未完结', type: 'WAIT_FINANCE_AUDIT' },
+        { name: '已完结', type: 'FINISH' }
+      ],
+      // 加载数据方法 必须为 Promise 对象
+      loadData: parameter => {
+        this.disabled = true
+        this.spinning = true
+        return checkWarehouseList(Object.assign(parameter, this.queryParam)).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
+          }
+          this.disabled = false
+          this.spinning = false
+          return data
+        })
+      }
+    }
+  },
+  computed: {
+    columns () {
+      let arr = []
+      if (this.queryParam.state == 'WAIT_FINANCE_AUDIT') { // 未完结
+        arr = [
+          { title: '序号', dataIndex: 'no', width: '4%', align: 'center' },
+          { title: '盘点单号', dataIndex: 'checkWarehouseNo', scopedSlots: { customRender: 'checkWarehouseNo' }, width: '15%', align: 'center' },
+          { title: '盘点状态', dataIndex: 'checkStateDictValue', width: '9%', align: 'center', customRender: function (text) { return text || '--' } },
+          { title: '监盘状态', dataIndex: 'checkSuperviseStateDictValue', width: '9%', align: 'center', customRender: function (text) { return text || '--' } },
+          { title: '盘点人', dataIndex: 'checkPersonName', align: 'center', width: '14%', customRender: function (text) { return text || '--' }, ellipsis: true },
+          { title: '盘点时间', dataIndex: 'checkTime', width: '10%', align: 'center', customRender: function (text) { return text || '--' } },
+          { title: '监盘人', dataIndex: 'checkSupervisePersonName', align: 'center', width: '14%', customRender: function (text) { return text || '--' }, ellipsis: true },
+          { title: '监盘时间', dataIndex: 'checkSuperviseTime', width: '10%', align: 'center', customRender: function (text) { return text || '--' } },
+          { title: '操作', scopedSlots: { customRender: 'action' }, width: '15%', align: 'center' }
+        ]
+      } else if (this.queryParam.state == 'FINISH') { // 已完结
+        arr = [
+          { title: '序号', dataIndex: 'no', width: '4%', align: 'center' },
+          { title: '盘点单号', dataIndex: 'checkWarehouseNo', scopedSlots: { customRender: 'checkWarehouseNo' }, width: '14%', align: 'center' },
+          { title: '盘点状态', dataIndex: 'checkStateDictValue', width: '10%', align: 'center', customRender: function (text) { return text || '--' } },
+          { title: '监盘状态', dataIndex: 'checkSuperviseStateDictValue', width: '10%', align: 'center', customRender: function (text) { return text || '--' } },
+          { title: '盘点人', dataIndex: 'checkPersonName', align: 'center', width: '16%', customRender: function (text) { return text || '--' }, ellipsis: true },
+          { title: '盘点时间', dataIndex: 'checkTime', width: '10%', align: 'center', customRender: function (text) { return text || '--' } },
+          { title: '监盘人', dataIndex: 'checkSupervisePersonName', align: 'center', width: '16%', customRender: function (text) { return text || '--' }, ellipsis: true },
+          { title: '监盘时间', dataIndex: 'checkSuperviseTime', width: '10%', align: 'center', customRender: function (text) { return text || '--' } },
+          { title: '财务确认时间', dataIndex: 'financeAuditTime', width: '10%', align: 'center', customRender: function (text) { return text || '--' } }
+        ]
+      }
+      return arr
+    }
+  },
+  methods: {
+    // 选择类型
+    handleTabChange (key) {
+      this.queryParam.state = key
+      this.$refs.table.refresh(true)
+    },
+    // 详情
+    handleDetail (row) {
+      if (this.$hasPermissions('B_inventoryConfirmationDetail')) {
+        this.$router.push({ path: `/financialManagement/inventoryConfirmation/detail/${row.checkWarehouseSn}` })
+      }
+    },
+    // 盘点确认
+    handleConfirm (row) {
+      const _this = this
+      this.$confirm({
+        title: '提示',
+        content: '确认盘点结果正确无误吗?',
+        centered: true,
+        closable: true,
+        onOk () {
+          _this.spinning = true
+          checkWarehouseFinanceAudit({ checkWarehouseSn: row.checkWarehouseSn }).then(res => {
+            if (res.status == 200) {
+              _this.$message.success(res.message)
+              _this.$refs.table.refresh(true)
+              _this.spinning = false
+            } else {
+              _this.spinning = false
+            }
+          })
+        }
+      })
+    },
+    // 重新盘点
+    handleCheck (row) {
+      const _this = this
+      this.$confirm({
+        title: '提示',
+        content: '确认要重新盘点吗?',
+        centered: true,
+        closable: true,
+        onOk () {
+          _this.spinning = true
+          checkWarehouseReCheck({ checkWarehouseSn: row.checkWarehouseSn }).then(res => {
+            if (res.status == 200) {
+              _this.$message.success(res.message)
+              _this.$refs.table.refresh(true)
+              _this.spinning = false
+            } else {
+              _this.spinning = false
+            }
+          })
+        }
+      })
+    },
+    resetSearchForm () {
+      this.queryParam.state = 'WAIT_FINANCE_AUDIT'
+      this.queryParam.checkWarehouseNo = ''
+      this.$refs.table.refresh(true)
+    },
+    pageInit () {
+      const _this = this
+      this.$nextTick(() => { // 页面渲染完成后的回调
+        _this.setTableH()
+      })
+    },
+    setTableH () {
+      this.tableHeight = window.innerHeight - 295
+    }
+  },
+  mounted () {
+    if (!this.$store.state.app.isNewTab) { // 页签刷新时调用
+      this.pageInit()
+      this.$refs.table.refresh(true)
+    }
+  },
+  activated () {
+    // 如果是新页签打开,则重置当前页面
+    if (this.$store.state.app.isNewTab) {
+      this.pageInit()
+      this.$refs.table.refresh(true)
+    }
+    // 仅刷新列表,不重置页面
+    if (this.$store.state.app.updateList) {
+      this.pageInit()
+      this.$refs.table.refresh()
+    }
+  },
+  beforeRouteEnter (to, from, next) {
+    next(vm => {})
+  }
+}
+</script>
+
+<style lang="less">
+  .inventoryConfirmationList-wrap{
+    .active{
+      color: #ed1c24;
+      cursor: pointer;
+    }
+    .common{
+      color: rgba(0, 0, 0, 0.65);
+    }
+  }
+</style>

+ 91 - 0
src/views/inventoryManagement/inventoryCheck/addModal.vue

@@ -0,0 +1,91 @@
+<template>
+  <a-modal
+    centered
+    class="inventoryCheckAddModal-modal"
+    :footer="null"
+    :maskClosable="false"
+    :closable="false"
+    title="新增盘点单"
+    v-model="isShow"
+    @cancle="isShow=false"
+    :width="600">
+    <a-spin :spinning="spinning" tip="Loading...">
+      <div>
+        <div class="inventoryCheckAddModal-con">
+          <h3>全盘盘点</h3>
+          <p>全盘是指所有有过入库记录的产品都参与盘点</p>
+          <p>确定创建新的盘点单吗?</p>
+        </div>
+        <div class="btn-cont">
+          <a-button type="primary" id="inventoryCheckAddModal-save" @click="handleSave">确定</a-button>
+          <a-button id="inventoryCheckAddModal-back" @click="isShow = false" style="margin-left: 15px;">取消</a-button>
+        </div>
+      </div>
+    </a-spin>
+  </a-modal>
+</template>
+
+<script>
+import { checkWarehouseSave } from '@/api/checkWarehouse'
+export default {
+  name: 'ProductInfoDetailModal',
+  props: {
+    openModal: { //  弹框显示状态
+      type: Boolean,
+      default: false
+    }
+  },
+  data () {
+    return {
+      spinning: false,
+      isShow: this.openModal //  是否打开弹框
+    }
+  },
+  methods: {
+    // 确定
+    handleSave () {
+      this.spinning = true
+      checkWarehouseSave({}).then(res => {
+        this.spinning = false
+        if (res.status == 200) {
+          this.$message.success('盘点单新增成功')
+          this.$emit('ok', res.data)
+          this.isShow = false
+        }
+      })
+    }
+  },
+  watch: {
+    //  父页面传过来的弹框状态
+    openModal (newValue, oldValue) {
+      this.isShow = newValue
+    },
+    //  重定义的弹框状态
+    isShow (newValue, oldValue) {
+      if (!newValue) {
+        this.$emit('close')
+      }
+    }
+  }
+}
+</script>
+
+<style lang="less">
+  .inventoryCheckAddModal-modal{
+    .ant-modal-body {
+      padding: 30px 40px 24px;
+    }
+    .inventoryCheckAddModal-con{
+      text-align: center;
+      h3{
+        font-size: 16px;
+        font-weight: bold;
+        margin-bottom: 25px;
+      }
+    }
+    .btn-cont {
+      text-align: center;
+      margin: 35px 0 10px;
+    }
+  }
+</style>

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

@@ -0,0 +1,313 @@
+<template>
+  <div class="inventoryCheckDetail-wrap">
+    <a-spin :spinning="spinning" tip="Loading...">
+      <a-page-header :ghost="false" :backIcon="false" @back="handleBack" class="inventoryCheckDetail-cont" >
+        <!-- 自定义的二级文字标题 -->
+        <template slot="subTitle">
+          <a id="inventoryCheckDetail-back-btn" href="javascript:;" @click="handleBack"><a-icon type="left" /> 返回列表</a>
+          <span class="billno">单号:{{ detail&&detail.checkWarehouseNo }}</span>
+          <span class="state-c" v-if="detail&&detail.state=='DELETE'">已作废</span>
+        </template>
+      </a-page-header>
+      <!-- 基础信息 -->
+      <a-card size="small" :bordered="false" class="inventoryCheckDetail-cont">
+        <a-collapse>
+          <a-collapse-panel key="1" header="基础信息">
+            <a-descriptions :column="3">
+              <a-descriptions-item label="创建人">{{ (detail&&detail.creatorName) || '--' }}</a-descriptions-item>
+              <a-descriptions-item label="创建时间">{{ (detail&&detail.createDate) || '--' }}</a-descriptions-item>
+              <a-descriptions-item label="盘点类型">{{ (detail&&detail.checkTypeDictValue) || '--' }}</a-descriptions-item>
+              <a-descriptions-item label="盘点状态">{{ (detail&&detail.checkStateDictValue) || '--' }}</a-descriptions-item>
+              <a-descriptions-item label="盘点人">{{ (detail&&detail.checkPersonName) || '--' }}</a-descriptions-item>
+              <a-descriptions-item label="盘点时间">{{ (detail&&detail.checkTime) || '--' }}</a-descriptions-item>
+              <a-descriptions-item label="监盘状态">{{ (detail&&detail.checkSuperviseStateDictValue) || '--' }}</a-descriptions-item>
+              <a-descriptions-item label="监盘人">{{ (detail&&detail.checkSupervisePersonName) || '--' }}</a-descriptions-item>
+              <a-descriptions-item label="监盘时间">{{ (detail&&detail.checkSuperviseTime) || '--' }}</a-descriptions-item>
+              <a-descriptions-item label="财务确认时间">{{ (detail&&detail.financeAuditTime) || '--' }}</a-descriptions-item>
+              <a-descriptions-item label="作废时间" v-if="detail&&detail.state=='DELETE'">{{ (detail&&detail.deleteTime) || '--' }}</a-descriptions-item>
+            </a-descriptions>
+          </a-collapse-panel>
+        </a-collapse>
+      </a-card>
+      <!-- 产品详情 -->
+      <a-card size="small" :bordered="false" class="inventoryCheckDetail-cont">
+        <!-- 总计 -->
+        <a-alert type="info" style="margin-bottom:10px">
+          <div slot="message">
+            库存数量:<strong>{{ productTotal && (productTotal.stockQty || productTotal.stockQty==0) ? productTotal.stockQty : '--' }}</strong>,
+            盘点数量:<strong>{{ productTotal && (productTotal.checkQty || productTotal.checkQty==0) ? productTotal.checkQty : '--' }}</strong>,
+            监盘数量:<strong>{{ productTotal && (productTotal.checkSuperviseQty || productTotal.checkSuperviseQty==0) ? productTotal.checkSuperviseQty : '--' }}</strong>
+          </div>
+        </a-alert>
+        <!-- 搜索条件 -->
+        <div class="table-page-search-wrapper">
+          <a-row :gutter="15">
+            <a-col :span="18">
+              <a-form-model :model="queryParam" layout="inline" @keyup.enter.native="getList(1)" >
+                <a-row :gutter="15">
+                  <a-col :md="8" :sm="24">
+                    <a-form-model-item label="产品编码">
+                      <a-input v-model="queryParam.productCode" allowClear placeholder="输入产品编码" />
+                    </a-form-model-item>
+                  </a-col>
+                  <a-col :md="8" :sm="24">
+                    <a-form-model-item style="margin-bottom: 10px;">
+                      <a-button type="primary" @click="getList(1)" :disabled="disabled" id="inventoryCheckDetail-refresh">查询</a-button>
+                      <a-button style="margin-left: 5px" @click="resetSearchForm" id="inventoryCheckDetail-reset">重置</a-button>
+                    </a-form-model-item>
+                  </a-col>
+                </a-row>
+              </a-form-model>
+            </a-col>
+            <a-col :span="6">
+              <div style="float:right;overflow: hidden;">
+                <a-checkbox v-model="foldState" @change="foldStateChange"><span style="display: inline-block;margin-top: 1px;">折叠列表</span></a-checkbox>
+              </div>
+            </a-col>
+          </a-row>
+        </div>
+        <!-- 列表 -->
+        <a-table
+          class="sTable"
+          ref="table"
+          size="small"
+          :rowKey="(record) => record.id + record.type"
+          :columns="columns"
+          :pagination="false"
+          :data-source="list"
+          :loading="loading"
+          @expand="handleExpand"
+          :expandedRowKeys="expandedRowKeys"
+          :expandRowByClick="true"
+          bordered>
+        </a-table>
+        <!-- 分页 -->
+        <tablePagination
+          ref="tablePagination"
+          :total="paginationProps.total"
+          :current="paginationProps.current"
+          :pageSize="paginationProps.pageSize"
+          @changePageSize="changePageSize"
+          @changePage="changePage" />
+      </a-card>
+    </a-spin>
+    <div class="affix-cont">
+      <a-button
+        type="primary"
+        id="inventoryCheckDetail-submit-btn"
+        v-if="detail&&(detail.state!='FINSH' && detail.state!='DELETE') && $hasPermissions('B_inventoryCheckVoid')"
+        size="large"
+        class="button-primary"
+        :disabled="spinning"
+        @click="handleSubmit"
+        style="padding: 0 60px;">作废盘点单</a-button>
+    </div>
+  </div>
+</template>
+
+<script>
+import { STable, VSelect } from '@/components'
+import tablePagination from '@/views/common/tablePagination.vue'
+import { checkWarehouseDetail, checkWarehouseDetailList, checkWarehouseDetailCount, checkWarehouseDelete } from '@/api/checkWarehouse'
+export default {
+  components: { STable, VSelect, tablePagination },
+  data () {
+    return {
+      spinning: false,
+      disabled: false,
+      loading: false,
+      queryParam: {
+        productCode: ''
+      },
+      // 表头
+      columns: [
+        { title: '序号', dataIndex: 'no', width: '6%', align: 'center' },
+        { title: '产品名称', dataIndex: 'productName', width: '16%', align: 'left', customRender: function (text) { return text || '--' }, ellipsis: true },
+        { title: '单位', dataIndex: 'productUnit', width: '5%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '仓库', dataIndex: 'warehouseName', width: '12%', align: 'center', customRender: function (text) { return text || '--' }, ellipsis: true },
+        { title: '仓位', dataIndex: 'warehouseLocationName', width: '11%', align: 'center', customRender: function (text) { return text || '--' }, ellipsis: true },
+        { title: '入库时间', dataIndex: 'lastStockTime', width: '12%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '批次', dataIndex: 'stockBatchNo', width: '6%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '产品编码', dataIndex: 'productCode', width: '14%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '库存数量', dataIndex: 'stockQty', width: '6%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
+        { title: '盘点数量', dataIndex: 'checkQty', width: '6%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
+        { title: '监盘数量', dataIndex: 'checkSuperviseQty', width: '6%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } }
+      ],
+      list: [],
+      paginationProps: {
+        total: 0, //  分页总条数
+        current: 1,
+        pageSize: 20
+      },
+      expandedRowKeys: [],
+      detail: null, //  详情数据
+      foldState: false, //  是否折叠列表
+      productTotal: null //  合计
+    }
+  },
+  methods: {
+    //  返回列表
+    handleBack () {
+      this.$router.push({ path: '/inventoryManagement/inventoryCheck/list/0', query: { closeLastOldTab: true } })
+    },
+    // 重置
+    resetSearchForm () {
+      this.queryParam.productCode = ''
+      this.getList()
+    },
+    // 作废盘点单
+    handleSubmit () {
+      const _this = this
+      this.$confirm({
+        title: '提示',
+        content: '作废后数据无法恢复,确认作废吗?',
+        centered: true,
+        closable: true,
+        onOk () {
+          _this.spinning = true
+          checkWarehouseDelete({ checkWarehouseSn: _this.$route.params.sn }).then(res => {
+            if (res.status == 200) {
+              _this.$message.success(res.message)
+              _this.spinning = false
+              _this.$router.push({ path: '/inventoryManagement/inventoryCheck/list/1', query: { closeLastOldTab: true } })
+            } else {
+              _this.spinning = false
+            }
+          })
+        }
+      })
+    },
+    // 获取列表数据
+    getList (pageNo) {
+      this.disabled = true
+      this.paginationProps.current = pageNo || this.paginationProps.current
+      const params = {
+        pageNo: this.paginationProps.current,
+        pageSize: this.paginationProps.pageSize,
+        checkWarehouseSn: this.$route.params.sn,
+        productCode: this.queryParam.productCode
+      }
+      this.loading = true
+      checkWarehouseDetailList(params).then(res => {
+        this.loading = false
+        if (res.status == 200) {
+          this.getCount(params)
+          const data = res.data
+          this.paginationProps.total = Number(res.data.count) || 0
+          this.paginationProps.current = data.pageNo
+          const no = (data.pageNo - 1) * data.pageSize
+          for (var i = 0; i < data.list.length; i++) {
+            data.list[i].no = no + i + 1
+            if (!this.foldState) {
+              this.expandedRowKeys.push(data.list[i].id + data.list[i].type)
+            }
+          }
+          this.list = data.list
+          this.disabled = false
+        } else {
+          this.paginationProps.total = 0
+          this.paginationProps.current = 1
+          this.paginationProps.pageSize = 20
+          this.list = []
+        }
+      })
+    },
+    getCount (params) {
+      checkWarehouseDetailCount(params).then(res => {
+        if (res.status == 200) {
+          this.productTotal = res.data
+        } else {
+          this.productTotal = null
+        }
+      })
+    },
+    //  分页  一页多少条change
+    changePageSize (current, pageSize) {
+      this.paginationProps.current = current
+      this.paginationProps.pageSize = pageSize
+      this.getList()
+    },
+    //  分页 页码change
+    changePage (current) {
+      this.paginationProps.current = current
+      this.getList()
+    },
+    //  详情
+    getDetail () {
+      checkWarehouseDetail({ sn: this.$route.params.sn }).then(res => {
+        if (res.status == 200) {
+          this.detail = res.data
+        } else {
+          this.detail = null
+        }
+      })
+    },
+    // 展开收起
+    handleExpand (expanded, record) {
+      if (record.type == 'superior') { // 只处理父级
+        if (expanded) {
+          this.expandedRowKeys.push(record.id + record.type)
+        } else {
+          if (this.expandedRowKeys.length > 0) {
+            const expandedRowKeys = this.expandedRowKeys.filter(RowKey => RowKey !== (record.id + record.type))
+            this.expandedRowKeys = expandedRowKeys
+          }
+        }
+      }
+    },
+    // 折叠列表
+    foldStateChange (e) {
+      if (e.target.checked) {
+        this.expandedRowKeys = []
+      } else {
+        this.expandedRowKeys = []
+        this.list.map(item => {
+          this.expandedRowKeys.push(item.id + item.type)
+        })
+      }
+    }
+  },
+  mounted () {
+    if (!this.$store.state.app.isNewTab) { // 页签刷新时调用
+      this.getList(1)
+      this.getDetail()
+    }
+  },
+  activated () {
+    // 如果是新页签打开或者进入新的子页(例:存在列表第2条数据编辑页页签时再打开第4条数据的编辑页),则重置当前页面
+    if (this.$store.state.app.isNewTab || !this.$store.state.app.isNewSubTab) {
+      this.getList(1)
+      this.getDetail()
+    }
+  },
+  beforeRouteEnter (to, from, next) {
+    next(vm => {})
+  }
+}
+</script>
+
+<style lang="less">
+  .inventoryCheckDetail-wrap{
+    position: relative;
+    height: 100%;
+    padding-bottom: 51px;
+    box-sizing: border-box;
+    >.ant-spin-nested-loading{
+      overflow-y: scroll;
+      height: 100%;
+    }
+    .inventoryCheckDetail-cont{
+      margin-bottom: 10px;
+      .billno{
+        font-size: 16px;
+        font-weight: bold;
+        margin: 0 15px;
+      }
+      .state-c{
+        color: #ed1c24;
+        font-size: 13px;
+        font-weight: bold;
+      }
+    }
+  }
+</style>

+ 265 - 0
src/views/inventoryManagement/inventoryCheck/list.vue

@@ -0,0 +1,265 @@
+<template>
+  <a-card size="small" :bordered="false" class="inventoryCheckList-wrap">
+    <a-spin :spinning="spinning" tip="Loading...">
+      <!-- 标签页 -->
+      <a-tabs type="card" :default-active-key="queryParam.deleteFlag" @change="handleTabChange" class="inventoryCheckList-tabs ">
+        <a-tab-pane v-for="item in tabPaneData" :key="item.type">
+          <span slot="tab">{{ item.name }}</span>
+        </a-tab-pane>
+      </a-tabs>
+      <!-- 搜索条件 -->
+      <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="盘点单号">
+                <a-input id="inventoryCheckList-checkWarehouseNo" v-model.trim="queryParam.checkWarehouseNo" allowClear placeholder="请输入盘点单号"/>
+              </a-form-item>
+            </a-col>
+            <a-col :md="6" :sm="24">
+              <a-form-item label="盘点状态">
+                <v-select
+                  v-model="queryParam.checkState"
+                  ref="checkState"
+                  id="inventoryCheckList-checkState"
+                  code="CHECK_WAREHOUSE_STATE"
+                  placeholder="请选择盘点状态"
+                  allowClear
+                ></v-select>
+              </a-form-item>
+            </a-col>
+            <a-col :md="6" :sm="24">
+              <a-form-item label="监盘状态">
+                <v-select
+                  v-model="queryParam.checkSuperviseState"
+                  ref="checkSuperviseState"
+                  id="inventoryCheckList-checkSuperviseState"
+                  code="CHECK_WAREHOUSE_SUPERVISE_STATE"
+                  placeholder="请选择监盘状态"
+                  allowClear
+                ></v-select>
+              </a-form-item>
+            </a-col>
+            <a-col :md="6" :sm="24">
+              <a-button type="primary" @click="$refs.table.refresh(true)" :disabled="disabled" id="inventoryCheckList-refresh">查询</a-button>
+              <a-button style="margin-left: 5px" @click="resetSearchForm" :disabled="disabled" id="inventoryCheckList-reset">重置</a-button>
+            </a-col>
+          </a-row>
+        </a-form>
+      </div>
+      <!-- 操作按钮 -->
+      <div class="table-operator">
+        <a-button v-if="$hasPermissions('B_inventoryCheckAdd')" id="inventoryCheckList-add" type="primary" class="button-error" @click="handleAdd">新增</a-button>
+      </div>
+      <!-- 列表 -->
+      <s-table
+        class="sTable fixPagination"
+        ref="table"
+        :style="{ height: tableHeight+84.5+'px' }"
+        size="small"
+        :rowKey="(record) => record.id"
+        :columns="columns"
+        :data="loadData"
+        :scroll="{ y: tableHeight }"
+        :defaultLoadData="false"
+        bordered>
+        <!-- 操作 -->
+        <template slot="action" slot-scope="text, record">
+          <a-button
+            size="small"
+            type="link"
+            v-if="$hasPermissions('B_inventoryCheckDetail')"
+            class="button-info"
+            @click="handleDetail(record)"
+            id="inventoryCheckList-audit-btn">详情</a-button>
+          <span v-else>--</span>
+        </template>
+      </s-table>
+    </a-spin>
+    <!-- 新增盘点单 -->
+    <inventory-check-add-modal :openModal="openAddModal" @ok="handleAddOk" @close="openAddModal=false" />
+    <!-- 盘点校验 -->
+    <common-modal :openModal="openCommonModal" :modalHtml="modalHtml" okText="好的" :isCancel="false" @ok="openCommonModal=false" />
+  </a-card>
+</template>
+
+<script>
+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 {
+  components: { STable, VSelect, inventoryCheckAddModal, commonModal },
+  data () {
+    return {
+      spinning: false,
+      tableHeight: 0,
+      queryParam: { //  查询条件
+        deleteFlag: this.$route.params.type == '0' ? '' : '1',
+        checkWarehouseNo: '',
+        checkState: undefined,
+        checkSuperviseState: undefined
+      },
+      disabled: false, //  查询、重置按钮是否可操作
+      tabPaneData: [
+        { name: '正常', type: '' },
+        { name: '已作废', type: '1' }
+      ],
+      // 加载数据方法 必须为 Promise 对象
+      loadData: parameter => {
+        this.disabled = true
+        this.spinning = true
+        return checkWarehouseList(Object.assign(parameter, this.queryParam)).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
+          }
+          this.disabled = false
+          this.spinning = false
+          return data
+        })
+      },
+      openModal: false,
+      itemSn: '',
+      openAddModal: false,
+      openCommonModal: false,
+      modalHtml: ''
+    }
+  },
+  computed: {
+    columns () {
+      let arr = []
+      if (this.queryParam.deleteFlag == '') { // 正常
+        arr = [
+          { title: '序号', dataIndex: 'no', width: '4%', align: 'center' },
+          { title: '盘点单号', dataIndex: 'checkWarehouseNo', width: '14%', align: 'center' },
+          { title: '盘点状态', dataIndex: 'checkStateDictValue', width: '6%', align: 'center', customRender: function (text) { return text || '--' } },
+          { title: '监盘状态', dataIndex: 'checkSuperviseStateDictValue', width: '6%', align: 'center', customRender: function (text) { return text || '--' } },
+          { title: '盘点人', dataIndex: 'checkPersonName', align: 'center', width: '12%', customRender: function (text) { return text || '--' }, ellipsis: true },
+          { title: '盘点提交时间', dataIndex: 'checkTime', width: '10%', align: 'center', customRender: function (text) { return text || '--' } },
+          { title: '监盘人', dataIndex: 'checkSupervisePersonName', align: 'center', width: '12%', customRender: function (text) { return text || '--' }, ellipsis: true },
+          { title: '监盘提交时间', dataIndex: 'checkSuperviseTime', width: '10%', align: 'center', customRender: function (text) { return text || '--' } },
+          { title: '财务确认时间', dataIndex: 'financeAuditTime', width: '10%', align: 'center', customRender: function (text) { return text || '--' } },
+          { title: '盘点单创建时间', dataIndex: 'createDate', width: '10%', align: 'center', customRender: function (text) { return text || '--' } },
+          { title: '操作', scopedSlots: { customRender: 'action' }, width: '6%', align: 'center' }
+        ]
+      } else if (this.queryParam.deleteFlag == '1') { // 已作废
+        arr = [
+          { title: '序号', dataIndex: 'no', width: '4%', align: 'center' },
+          { title: '盘点单号', dataIndex: 'checkWarehouseNo', width: '14%', align: 'center' },
+          { title: '盘点状态', dataIndex: 'checkStateDictValue', width: '6%', align: 'center', customRender: function (text) { return text || '--' } },
+          { title: '监盘状态', dataIndex: 'checkSuperviseStateDictValue', width: '6%', align: 'center', customRender: function (text) { return text || '--' } },
+          { title: '盘点人', dataIndex: 'checkPersonName', align: 'center', width: '12%', customRender: function (text) { return text || '--' }, ellipsis: true },
+          { title: '盘点提交时间', dataIndex: 'checkTime', width: '10%', align: 'center', customRender: function (text) { return text || '--' } },
+          { title: '监盘人', dataIndex: 'checkSupervisePersonName', align: 'center', width: '12%', customRender: function (text) { return text || '--' }, ellipsis: true },
+          { title: '监盘提交时间', dataIndex: 'checkSuperviseTime', width: '10%', align: 'center', customRender: function (text) { return text || '--' } },
+          { title: '盘点单创建时间', dataIndex: 'createDate', width: '10%', align: 'center', customRender: function (text) { return text || '--' } },
+          { title: '盘点单作废时间', dataIndex: 'deleteTime', width: '10%', align: 'center', customRender: function (text) { return text || '--' } },
+          { title: '操作', scopedSlots: { customRender: 'action' }, width: '6%', align: 'center' }
+        ]
+      }
+      return arr
+    }
+  },
+  methods: {
+    // 新增
+    handleAdd () {
+      this.spinning = true
+      checkWarehouseStartCheck({}).then(res => {
+        this.spinning = false
+        if (res.status == 200) {
+          if (res.data && res.data.length > 0) {
+            this.modalHtml = `<div style="width: 100%">
+              <h3 style="font-size: 15px;font-weight: bold;margin: 20px 0 5px;text-align: center;">存在以下状态的销售单,无法盘点。</h3>
+              <h3 style="font-size: 15px;font-weight: bold;margin-bottom: 25px;text-align: center;">请先检查并处理完以下单据再试。</h3>
+              ${res.data.indexOf('WAIT_AUDIT') != -1 ? '<p>销售单-待审核(总部自建)</p>' : ''}
+              ${res.data.indexOf('AUDIT_REJECT') != -1 ? '<p>销售单-审核不通过(总部自建)</p>' : ''}
+              ${res.data.indexOf('HQ_CHANGE') != -1 ? '<p>销售单-总公司改单</p>' : ''}
+              ${res.data.indexOf('WAIT_PUSH') != -1 ? '<p>销售单-待下推</p>' : ''}
+            </div>`
+            this.openCommonModal = true
+          } else {
+            this.openAddModal = true
+          }
+        }
+      })
+    },
+    // 新增 成功
+    handleAddOk (data) {
+      this.$router.push({ path: `/inventoryManagement/inventoryCheck/detail/${data.checkWarehouseSn}` })
+    },
+    // 选择类型
+    handleTabChange (key) {
+      this.queryParam.deleteFlag = key
+      this.$refs.table.refresh(true)
+    },
+    // 详情
+    handleDetail (row) {
+      if (this.$hasPermissions('B_inventoryCheckDetail')) {
+        this.$router.push({ path: `/inventoryManagement/inventoryCheck/detail/${row.checkWarehouseSn}` })
+      }
+    },
+    resetSearchForm () {
+      this.queryParam.deleteFlag = ''
+      this.queryParam.checkWarehouseNo = ''
+      this.queryParam.checkState = undefined
+      this.queryParam.checkSuperviseState = undefined
+      this.$refs.table.refresh(true)
+    },
+    closeModal () {
+      this.itemSn = ''
+      this.openModal = false
+    },
+    pageInit () {
+      const _this = this
+      this.$nextTick(() => { // 页面渲染完成后的回调
+        _this.setTableH()
+      })
+    },
+    setTableH () {
+      this.tableHeight = window.innerHeight - 338
+    }
+  },
+  mounted () {
+    if (!this.$store.state.app.isNewTab) { // 页签刷新时调用
+      this.pageInit()
+      this.$refs.table.refresh(true)
+    }
+  },
+  activated () {
+    // 如果是新页签打开,则重置当前页面
+    if (this.$store.state.app.isNewTab) {
+      this.pageInit()
+      this.$refs.table.refresh(true)
+    }
+    // 仅刷新列表,不重置页面
+    if (this.$store.state.app.updateList) {
+      this.pageInit()
+      this.$refs.table.refresh()
+    }
+  },
+  beforeRouteEnter (to, from, next) {
+    next(vm => {
+      const _this = vm
+      if (_this.$route.params.type == '1') {
+        setTimeout(() => {
+          _this.$refs.table.refresh(true)
+        }, 300)
+      }
+    })
+  }
+}
+</script>
+
+<style lang="less">
+  .inventoryCheckList-wrap{
+    .active{
+      color: #ed1c24;
+      cursor: pointer;
+    }
+    .common{
+      color: rgba(0, 0, 0, 0.65);
+    }
+  }
+</style>

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

@@ -0,0 +1,460 @@
+<template>
+  <div class="makeInventoryCheck-wrap">
+    <a-spin :spinning="spinning" tip="Loading...">
+      <a-page-header :ghost="false" :backIcon="false" @back="handleBack" class="makeInventoryCheck-cont" >
+        <!-- 自定义的二级文字标题 -->
+        <template slot="subTitle">
+          <a id="makeInventoryCheck-back-btn" href="javascript:;" @click="handleBack"><a-icon type="left" /> 返回列表</a>
+          <span class="billno">单号:{{ detail&&detail.checkWarehouseNo }}</span>
+        </template>
+        <!-- 操作区,位于 title 行的行尾 -->
+        <template slot="extra">
+          <a-button
+            key="1"
+            type="primary"
+            class="button-info"
+            id="makeInventoryCheck-print-btn"
+            :disabled="list.length==0"
+            v-if="$hasPermissions('B_inventoryMakeInventoryPrint')"
+            @click="handlePdPrint">盘点打印</a-button>
+        </template></a-page-header>
+      <!-- 基础信息 -->
+      <a-card size="small" :bordered="false" class="makeInventoryCheck-cont">
+        <a-collapse>
+          <a-collapse-panel key="1" header="基础信息">
+            <a-descriptions :column="3">
+              <a-descriptions-item label="创建人">{{ (detail&&detail.creatorName) || '--' }}</a-descriptions-item>
+              <a-descriptions-item label="创建时间">{{ (detail&&detail.createDate) || '--' }}</a-descriptions-item>
+              <a-descriptions-item label="盘点类型">{{ (detail&&detail.checkTypeDictValue) || '--' }}</a-descriptions-item>
+              <a-descriptions-item label="盘点状态">{{ (detail&&detail.checkStateDictValue) || '--' }}</a-descriptions-item>
+              <a-descriptions-item label="盘点人">{{ (detail&&detail.checkPersonName) || '--' }}</a-descriptions-item>
+              <a-descriptions-item label="盘点时间">{{ (detail&&detail.checkTime) || '--' }}</a-descriptions-item>
+              <a-descriptions-item label="监盘状态">{{ (detail&&detail.checkSuperviseStateDictValue) || '--' }}</a-descriptions-item>
+              <a-descriptions-item label="监盘人">{{ (detail&&detail.checkSupervisePersonName) || '--' }}</a-descriptions-item>
+              <a-descriptions-item label="监盘时间">{{ (detail&&detail.checkSuperviseTime) || '--' }}</a-descriptions-item>
+              <a-descriptions-item label="财务确认时间">{{ (detail&&detail.financeAuditTime) || '--' }}</a-descriptions-item>
+            </a-descriptions>
+          </a-collapse-panel>
+        </a-collapse>
+      </a-card>
+      <!-- 产品详情 -->
+      <a-card size="small" :bordered="false" class="makeInventoryCheck-cont">
+        <!-- 总计 -->
+        <a-alert type="info" style="margin-bottom:10px">
+          <div slot="message">
+            <div style="display: flex;justify-content: space-between;align-items: center;">
+              <div>
+                库存数量:<strong>{{ productTotal && (productTotal.stockQty || productTotal.stockQty==0) ? productTotal.stockQty : '--' }}</strong>,
+                盘点数量:<strong>{{ productTotal && (productTotal.checkQty || productTotal.checkQty==0) ? productTotal.checkQty : '--' }}</strong>,
+                盘点盈亏数量:<strong>{{ productTotal && (productTotal.profitLossQty || productTotal.profitLossQty==0) ? productTotal.profitLossQty : '--' }}</strong>
+              </div>
+              <div>
+                <span style="color: red;display: inline-block;margin-right: 8px;">红色代表盘盈</span>
+                <span style="color: green;">绿色代表盘亏</span>
+              </div>
+            </div>
+          </div></a-alert>
+        <!-- 搜索条件 -->
+        <div class="table-page-search-wrapper">
+          <a-row :gutter="15">
+            <a-col :span="18">
+              <a-form-model :model="queryParam" layout="inline" @keyup.enter.native="getList(1)" >
+                <a-row :gutter="15">
+                  <a-col :md="8" :sm="24">
+                    <a-form-model-item label="产品编码">
+                      <a-input v-model="queryParam.productCode" allowClear placeholder="输入产品编码" />
+                    </a-form-model-item>
+                  </a-col>
+                  <a-col :md="8" :sm="24">
+                    <a-form-model-item style="margin-bottom: 10px;">
+                      <a-button type="primary" @click="getList(1)" :disabled="disabled" id="makeInventoryCheck-refresh">查询</a-button>
+                      <a-button style="margin-left: 5px" @click="resetSearchForm" id="makeInventoryCheck-reset">重置</a-button>
+                    </a-form-model-item>
+                  </a-col>
+                </a-row>
+              </a-form-model>
+            </a-col>
+            <a-col :span="6">
+              <div style="float:right;overflow: hidden;">
+                <a-checkbox v-model="foldState" @change="foldStateChange"><span style="display: inline-block;margin-top: 1px;">折叠列表</span></a-checkbox>
+              </div>
+            </a-col>
+          </a-row>
+        </div>
+        <!-- 列表 -->
+        <a-table
+          class="sTable"
+          ref="table"
+          size="small"
+          :rowKey="(record) => record.id + record.type"
+          :columns="columns"
+          :pagination="false"
+          :data-source="list"
+          :loading="loading"
+          @expand="handleExpand"
+          :expandedRowKeys="expandedRowKeys"
+          bordered>
+          <!-- 数量 -->
+          <template slot="checkQty" slot-scope="text, record">
+            <a-input-number
+              size="small"
+              id="makeInventoryCheck-checkQty"
+              v-model="record.checkQty"
+              :precision="0"
+              :min="0"
+              :max="999999"
+              placeholder="请输入"
+              v-if="record.type=='superior'"
+              @blur="e => checkQtyBlur(e.target.value, record)"
+              class="input-number"
+              style="width: 100%;text-align: center;" />
+            <span v-else>{{ record.checkQty }}</span>
+          </template>
+          <!-- 盈亏数量 -->
+          <template slot="profitLossQty" slot-scope="text, record">
+            <span v-if="record.type=='superior'" :style="{ color: record.profitLossQty>0?'red':record.profitLossQty<0?'green':'', fontWeight: record.profitLossQty!=0?'bold':'' }">
+              {{ record.profitLossQty>0?'盘盈':record.profitLossQty<0?'盘亏':'' }}
+              {{ (record.profitLossQty || record.profitLossQty==0) ? Math.abs(record.profitLossQty) : '--' }}
+            </span>
+            <span v-else></span>
+          </template>
+        </a-table>
+        <!-- 分页 -->
+        <tablePagination
+          ref="tablePagination"
+          :total="paginationProps.total"
+          :current="paginationProps.current"
+          :pageSize="paginationProps.pageSize"
+          @changePageSize="changePageSize"
+          @changePage="changePage" />
+      </a-card>
+    </a-spin>
+    <div class="affix-cont">
+      <a-button
+        type="primary"
+        id="makeInventoryCheck-submit-btn"
+        size="large"
+        class="button-primary"
+        :disabled="spinning"
+        @click="handleSubmit"
+        style="padding: 0 60px;">提交盘点</a-button>
+    </div>
+    <!-- 盘点打印确认 -->
+    <printModal
+      :openModal="visiblePrint"
+      :content="printContent"
+      :okText="printOkText"
+      cancelText="打印预览"
+      :isCancel="isPrintCancel"
+      :spinning="spinningPrint"
+      @close="visiblePrint=false"
+      @ok="printOkText == '好的' ? visiblePrint=false : handlePrint('print')"
+      @fail="handlePrint('preview')" />
+    <!-- 打印 -->
+    <div id="print"></div>
+  </div>
+</template>
+
+<script>
+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 {
+  components: { STable, VSelect, tablePagination, printModal },
+  data () {
+    return {
+      spinning: false,
+      disabled: false,
+      loading: false,
+      queryParam: {
+        productCode: ''
+      },
+      // 表头
+      columns: [
+        { title: '序号', dataIndex: 'no', width: '6%', align: 'center' },
+        { title: '产品名称', dataIndex: 'productName', width: '16%', align: 'left', customRender: function (text) { return text || '--' }, ellipsis: true },
+        { title: '单位', dataIndex: 'productUnit', width: '5%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '仓库', dataIndex: 'warehouseName', width: '12%', align: 'center', customRender: function (text) { return text || '--' }, ellipsis: true },
+        { title: '仓位', dataIndex: 'warehouseLocationName', width: '11%', align: 'center', customRender: function (text) { return text || '--' }, ellipsis: true },
+        { title: '入库时间', dataIndex: 'lastStockTime', width: '12%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '批次', dataIndex: 'stockBatchNo', width: '6%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '产品编码', dataIndex: 'productCode', width: '14%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '库存数量', dataIndex: 'stockQty', width: '6%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
+        { title: '盘点数量', dataIndex: 'checkQty', scopedSlots: { customRender: 'checkQty' }, width: '6%', align: 'center' },
+        { title: '盈亏数量', dataIndex: 'profitLossQty', scopedSlots: { customRender: 'profitLossQty' }, width: '6%', align: 'center' }
+      ],
+      list: [],
+      paginationProps: {
+        total: 0, //  分页总条数
+        current: 1,
+        pageSize: 20
+      },
+      expandedRowKeys: [],
+      detail: null, //  详情数据
+      foldState: false, //  是否折叠列表
+      productTotal: null, //  合计
+      spinningPrint: false,
+      visiblePrint: false,
+      printContent: '',
+      printOkText: '',
+      isPrintCancel: false
+    }
+  },
+  methods: {
+    //  返回列表
+    handleBack () {
+      this.$router.push({ path: '/inventoryManagement/makeInventory/list', query: { closeLastOldTab: true, isRefresh: true } })
+    },
+    // 重置
+    resetSearchForm () {
+      this.queryParam.productCode = ''
+      this.getList()
+    },
+    // 盘点数量  blur
+    checkQtyBlur (val, record) {
+      //  光标移出,值发生改变再调用编辑接口
+      if (val != record.checkQtyBackups) {
+        this.handleEdit(record)
+      }
+    },
+    //  编辑
+    handleEdit (row) {
+      const params = {
+        checkWarehouseSn: this.$route.params.sn,
+        productSn: row.productSn,
+        reCheckQty: row.checkQty,
+        stockQty: row.stockQty
+      }
+      // 清空数量时,值应保持未清空前的值,因数量不可为空
+      if (!(row.checkQty || row.checkQty == 0)) {
+        row.checkQty = row.checkQtyBackups
+        return
+      }
+      this.spinning = true
+      checkWarehouseDetailSave(params).then(res => {
+        if (res.status == 200) {
+          this.$message.success(res.message)
+          this.getList()
+          this.spinning = false
+        } else {
+          this.spinning = false
+        }
+      })
+    },
+    // 提交盘点
+    handleSubmit () {
+      const _this = this
+      this.$confirm({
+        title: '提示',
+        content: '确认提交盘点吗?',
+        centered: true,
+        closable: true,
+        onOk () {
+          _this.spinning = true
+          checkWarehouseCheck({ checkWarehouseSn: _this.$route.params.sn }).then(res => {
+            if (res.status == 200) {
+              _this.$message.success(res.message)
+              _this.handleBack()
+              _this.spinning = false
+            } else {
+              _this.spinning = false
+            }
+          })
+        }
+      })
+    },
+    // 获取列表数据
+    getList (pageNo) {
+      this.disabled = true
+      this.paginationProps.current = pageNo || this.paginationProps.current
+      const params = {
+        pageNo: this.paginationProps.current,
+        pageSize: this.paginationProps.pageSize,
+        checkWarehouseSn: this.$route.params.sn,
+        productCode: this.queryParam.productCode
+      }
+      this.loading = true
+      checkWarehouseDetailList(params).then(res => {
+        this.loading = false
+        if (res.status == 200) {
+          this.getCount(params)
+          const data = res.data
+          this.paginationProps.total = Number(res.data.count) || 0
+          this.paginationProps.current = data.pageNo
+          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].checkQtyBackups = data.list[i].checkQty
+            if (!this.foldState) {
+              this.expandedRowKeys.push(data.list[i].id + data.list[i].type)
+            }
+          }
+          this.list = data.list
+          this.disabled = false
+        } else {
+          this.paginationProps.total = 0
+          this.paginationProps.current = 1
+          this.paginationProps.pageSize = 20
+          this.list = []
+        }
+      })
+    },
+    getCount (params) {
+      checkWarehouseDetailCount(params).then(res => {
+        if (res.status == 200) {
+          this.productTotal = res.data
+        } else {
+          this.productTotal = null
+        }
+      })
+    },
+    //  分页  一页多少条change
+    changePageSize (current, pageSize) {
+      this.paginationProps.current = current
+      this.paginationProps.pageSize = pageSize
+      this.getList()
+    },
+    //  分页 页码change
+    changePage (current) {
+      this.paginationProps.current = current
+      this.getList()
+    },
+    //  详情
+    getDetail () {
+      checkWarehouseDetail({ sn: this.$route.params.sn }).then(res => {
+        if (res.status == 200) {
+          this.detail = res.data
+        } else {
+          this.detail = null
+        }
+      })
+    },
+    // 展开收起
+    handleExpand (expanded, record) {
+      if (record.type == 'superior') { // 只处理父级
+        if (expanded) {
+          this.expandedRowKeys.push(record.id + record.type)
+        } else {
+          if (this.expandedRowKeys.length > 0) {
+            const expandedRowKeys = this.expandedRowKeys.filter(RowKey => RowKey !== (record.id + record.type))
+            this.expandedRowKeys = expandedRowKeys
+          }
+        }
+      }
+    },
+    // 折叠列表
+    foldStateChange (e) {
+      if (e.target.checked) {
+        this.expandedRowKeys = []
+      } else {
+        this.expandedRowKeys = []
+        this.list.map(item => {
+          this.expandedRowKeys.push(item.id + item.type)
+        })
+      }
+    },
+    // 盘点打印
+    handlePdPrint () {
+      this.spinning = true
+      checkWarehousePrintCheck({ checkWarehouseSn: this.$route.params.sn, type: 'CHECK_WAREHOUSE' }).then(res => {
+        this.spinning = false
+        if (res.status == 200) {
+          if (res.data && res.data == 0) { // 无产品
+            this.printContent = '此盘点单没有产品,无法打印'
+            this.printOkText = '好的'
+            this.isPrintCancel = false
+            this.visiblePrint = true
+          } else { // 有产品
+            this.printContent = '打印范围 —— 所有盘点产品(批次合并)'
+            this.printOkText = '立即打印'
+            this.isPrintCancel = true
+            this.visiblePrint = true
+          }
+        }
+      })
+    },
+    // 打印预览/快捷打印
+    handlePrint (type) {
+      const _this = this
+      _this.spinningPrint = true
+      checkWarehouseDetailPrint({ checkWarehouseSn: this.$route.params.sn, type: 'CHECK_WAREHOUSE' }).then(res => {
+        _this.spinningPrint = 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)
+        }
+      })
+    },
+    print (data, type) {
+      if (!data) {
+        return
+      }
+      const url = window.URL.createObjectURL(new Blob([data], { type: 'application/pdf' }))
+      document.getElementById('print').innerHTML = '<iframe id="printfbod" name="printfbod" src="' + url + '" hidden></iframe>'
+      if (type == 'preview') { //  预览
+        window.open(url)
+      } else if (type == 'print') { //  打印
+        window.frames['printfbod'].focus()
+        window.frames['printfbod'].print()
+      }
+    }
+  },
+  mounted () {
+    if (!this.$store.state.app.isNewTab) { // 页签刷新时调用
+      this.getList(1)
+      this.getDetail()
+    }
+  },
+  activated () {
+    // 如果是新页签打开或者进入新的子页(例:存在列表第2条数据编辑页页签时再打开第4条数据的编辑页),则重置当前页面
+    if (this.$store.state.app.isNewTab || !this.$store.state.app.isNewSubTab) {
+      this.getList(1)
+      this.getDetail()
+    }
+  },
+  beforeRouteEnter (to, from, next) {
+    next(vm => {})
+  }
+}
+</script>
+
+<style lang="less">
+  .makeInventoryCheck-wrap{
+    position: relative;
+    height: 100%;
+    padding-bottom: 51px;
+    box-sizing: border-box;
+    >.ant-spin-nested-loading{
+      overflow-y: scroll;
+      height: 100%;
+    }
+    .makeInventoryCheck-cont{
+      margin-bottom: 10px;
+      .billno{
+        font-size: 16px;
+        font-weight: bold;
+        margin: 0 15px;
+      }
+      .state-c{
+        color: #ed1c24;
+        font-size: 13px;
+        font-weight: bold;
+      }
+    }
+    .input-number{
+      .ant-input-number-input{
+        text-align: center;
+      }
+    }
+  }
+</style>

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

@@ -0,0 +1,149 @@
+<template>
+  <a-card size="small" :bordered="false" class="makeInventoryList-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="盘点单号">
+                <a-input id="makeInventoryList-checkWarehouseNo" v-model.trim="queryParam.checkWarehouseNo" allowClear placeholder="请输入盘点单号"/>
+              </a-form-item>
+            </a-col>
+            <a-col :md="6" :sm="24">
+              <a-button type="primary" @click="$refs.table.refresh(true)" :disabled="disabled" id="makeInventoryList-refresh">查询</a-button>
+              <a-button style="margin-left: 5px" @click="resetSearchForm" :disabled="disabled" id="makeInventoryList-reset">重置</a-button>
+            </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="action" slot-scope="text, record">
+          <a-button
+            size="small"
+            type="link"
+            v-if="$hasPermissions('B_inventoryMakeInventoryCheck')"
+            class="button-info"
+            @click="handleCheck(record)"
+            id="makeInventoryList-audit-btn">盘点</a-button>
+          <span v-else>--</span>
+        </template>
+      </s-table>
+    </a-spin>
+  </a-card>
+</template>
+
+<script>
+import { STable, VSelect } from '@/components'
+import { checkWarehouseList } from '@/api/checkWarehouse'
+export default {
+  components: { STable, VSelect },
+  data () {
+    return {
+      spinning: false,
+      tableHeight: 0,
+      disabled: false, //  查询、重置按钮是否可操作
+      queryParam: { //  查询条件
+        checkWarehouseNo: ''
+      },
+      columns: [
+        { title: '序号', dataIndex: 'no', width: '6%', align: 'center' },
+        { title: '盘点单号', dataIndex: 'checkWarehouseNo', width: '18%', align: 'center' },
+        { title: '盘点状态', dataIndex: 'checkStateDictValue', width: '9%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '产品款数', dataIndex: 'productTotalCategory', width: '11%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
+        { title: '库存数量', dataIndex: 'totalStockQty', width: '11%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
+        { title: '盘点数量', dataIndex: 'checkTotalQty', width: '11%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
+        { title: '盘点盘亏数量', dataIndex: 'totalProfitLossQty', width: '11%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
+        { title: '盘点单创建时间', dataIndex: 'createDate', width: '13%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '操作', scopedSlots: { customRender: 'action' }, width: '10%', align: 'center' }
+      ],
+      // 加载数据方法 必须为 Promise 对象
+      loadData: parameter => {
+        this.disabled = true
+        this.spinning = true
+        return checkWarehouseList(Object.assign(parameter, this.queryParam, { state: 'WAIT_CHECK' })).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
+          }
+          this.disabled = false
+          this.spinning = false
+          return data
+        })
+      }
+    }
+  },
+  methods: {
+    // 盘点
+    handleCheck (row) {
+      this.$router.push({ path: `/inventoryManagement/makeInventory/check/${row.checkWarehouseSn}` })
+    },
+    resetSearchForm () {
+      this.queryParam.checkWarehouseNo = ''
+      this.$refs.table.refresh(true)
+    },
+    pageInit () {
+      const _this = this
+      this.$nextTick(() => { // 页面渲染完成后的回调
+        _this.setTableH()
+      })
+    },
+    setTableH () {
+      this.tableHeight = window.innerHeight - 240
+    }
+  },
+  mounted () {
+    if (!this.$store.state.app.isNewTab) { // 页签刷新时调用
+      this.pageInit()
+      this.$refs.table.refresh(true)
+    }
+  },
+  activated () {
+    // 如果是新页签打开,则重置当前页面
+    if (this.$store.state.app.isNewTab) {
+      this.pageInit()
+      this.$refs.table.refresh(true)
+    }
+    // 仅刷新列表,不重置页面
+    if (this.$store.state.app.updateList) {
+      this.pageInit()
+      this.$refs.table.refresh()
+    }
+  },
+  beforeRouteEnter (to, from, next) {
+    next(vm => {
+      const _this = vm
+      if (vm.$route.query.isRefresh) {
+        setTimeout(() => {
+          _this.$refs.table.refresh(true)
+        }, 300)
+      }
+    })
+  }
+}
+</script>
+
+<style lang="less">
+  .makeInventoryList-wrap{
+    .active{
+      color: #ed1c24;
+      cursor: pointer;
+    }
+    .common{
+      color: rgba(0, 0, 0, 0.65);
+    }
+  }
+</style>

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

@@ -0,0 +1,494 @@
+<template>
+  <div class="supervisionDiskCheck-wrap">
+    <a-spin :spinning="spinning" tip="Loading...">
+      <a-page-header :ghost="false" :backIcon="false" @back="handleBack" class="supervisionDiskCheck-cont" >
+        <!-- 自定义的二级文字标题 -->
+        <template slot="subTitle">
+          <a id="supervisionDiskCheck-back-btn" href="javascript:;" @click="handleBack"><a-icon type="left" /> 返回列表</a>
+          <span class="billno">单号:{{ detail&&detail.checkWarehouseNo }}</span>
+        </template>
+        <!-- 操作区,位于 title 行的行尾 -->
+        <template slot="extra">
+          <a-button
+            key="1"
+            type="primary"
+            class="button-info"
+            id="supervisionDiskCheck-print-btn"
+            :disabled="list.length==0"
+            v-if="$hasPermissions('B_supervisionDiskPrint')"
+            @click="handlePdPrint">监盘打印</a-button>
+        </template></a-page-header>
+      <!-- 基础信息 -->
+      <a-card size="small" :bordered="false" class="supervisionDiskCheck-cont">
+        <a-collapse>
+          <a-collapse-panel key="1" header="基础信息">
+            <a-descriptions :column="3">
+              <a-descriptions-item label="创建人">{{ (detail&&detail.creatorName) || '--' }}</a-descriptions-item>
+              <a-descriptions-item label="创建时间">{{ (detail&&detail.createDate) || '--' }}</a-descriptions-item>
+              <a-descriptions-item label="盘点类型">{{ (detail&&detail.checkTypeDictValue) || '--' }}</a-descriptions-item>
+              <a-descriptions-item label="盘点状态">{{ (detail&&detail.checkStateDictValue) || '--' }}</a-descriptions-item>
+              <a-descriptions-item label="盘点人">{{ (detail&&detail.checkPersonName) || '--' }}</a-descriptions-item>
+              <a-descriptions-item label="盘点时间">{{ (detail&&detail.checkTime) || '--' }}</a-descriptions-item>
+              <a-descriptions-item label="监盘状态">{{ (detail&&detail.checkSuperviseStateDictValue) || '--' }}</a-descriptions-item>
+              <a-descriptions-item label="监盘人">{{ (detail&&detail.checkSupervisePersonName) || '--' }}</a-descriptions-item>
+              <a-descriptions-item label="监盘时间">{{ (detail&&detail.checkSuperviseTime) || '--' }}</a-descriptions-item>
+              <a-descriptions-item label="财务确认时间">{{ (detail&&detail.financeAuditTime) || '--' }}</a-descriptions-item>
+            </a-descriptions>
+          </a-collapse-panel>
+        </a-collapse>
+      </a-card>
+      <!-- 产品详情 -->
+      <a-card size="small" :bordered="false" class="supervisionDiskCheck-cont">
+        <!-- 总计 -->
+        <a-alert type="info" style="margin-bottom:10px">
+          <div slot="message">
+            <div style="display: flex;justify-content: space-between;align-items: center;">
+              <div>
+                库存数量:<strong>{{ productTotal && (productTotal.stockQty || productTotal.stockQty==0) ? productTotal.stockQty : '--' }}</strong>,
+                盘点数量:<strong>{{ productTotal && (productTotal.checkQty || productTotal.checkQty==0) ? productTotal.checkQty : '--' }}</strong>,
+                监盘数量:<strong>{{ productTotal && (productTotal.checkSuperviseQty || productTotal.checkSuperviseQty==0) ? productTotal.checkSuperviseQty : '--' }}</strong>,
+                监盘盈亏数量:<strong :style="{ color: productTotal && productTotal.profitLossQty>0?'red':productTotal && productTotal.profitLossQty<0?'green':'' }">{{ productTotal && (productTotal.profitLossQty || productTotal.profitLossQty==0) ? productTotal.profitLossQty : '--' }}</strong>
+              </div>
+              <div>
+                <span style="color: red;display: inline-block;margin-right: 8px;">红色代表盘盈</span>
+                <span style="color: green;">绿色代表盘亏</span>
+              </div>
+            </div>
+          </div></a-alert>
+        <!-- 搜索条件 -->
+        <div class="table-page-search-wrapper">
+          <a-row :gutter="15">
+            <a-col :span="18">
+              <a-form-model :model="queryParam" layout="inline" @keyup.enter.native="getList(1)" >
+                <a-row :gutter="15">
+                  <a-col :md="8" :sm="24">
+                    <a-form-model-item label="产品编码">
+                      <a-input v-model="queryParam.productCode" allowClear placeholder="输入产品编码" />
+                    </a-form-model-item>
+                  </a-col>
+                  <a-col :md="8" :sm="24">
+                    <a-form-model-item style="margin-bottom: 10px;">
+                      <a-button type="primary" @click="getList(1)" :disabled="disabled" id="supervisionDiskCheck-refresh">查询</a-button>
+                      <a-button style="margin-left: 5px" @click="resetSearchForm" id="supervisionDiskCheck-reset">重置</a-button>
+                    </a-form-model-item>
+                  </a-col>
+                </a-row>
+              </a-form-model>
+            </a-col>
+            <a-col :span="6">
+              <div style="float:right;overflow: hidden;">
+                <a-checkbox v-model="foldState" @change="foldStateChange"><span style="display: inline-block;margin-top: 1px;">折叠列表</span></a-checkbox>
+              </div>
+            </a-col>
+          </a-row>
+        </div>
+        <!-- 列表 -->
+        <a-table
+          class="sTable"
+          ref="table"
+          size="small"
+          :rowKey="(record) => record.id + record.type"
+          :columns="columns"
+          :pagination="false"
+          :data-source="list"
+          :loading="loading"
+          @expand="handleExpand"
+          :expandedRowKeys="expandedRowKeys"
+          bordered>
+          <!-- 数量 -->
+          <template slot="checkSuperviseQty" slot-scope="text, record">
+            <a-input-number
+              size="small"
+              id="supervisionDiskCheck-checkSuperviseQty"
+              v-model="record.checkSuperviseQty"
+              :precision="0"
+              :min="0"
+              :max="999999"
+              placeholder="请输入"
+              v-if="record.type=='superior'"
+              @blur="e => checkSuperviseQtyBlur(e.target.value, record)"
+              class="input-number"
+              style="width: 100%;text-align: center;" />
+            <span v-else>{{ record.checkSuperviseQty }}</span>
+          </template>
+          <!-- 盈亏数量 -->
+          <template slot="profitLossQty" slot-scope="text, record">
+            <span v-if="record.type=='superior'" :style="{ color: record.profitLossQty>0?'red':record.profitLossQty<0?'green':'', fontWeight: record.profitLossQty!=0?'bold':'' }">
+              {{ record.profitLossQty>0?'盘盈':record.profitLossQty<0?'盘亏':'' }}
+              {{ (record.profitLossQty || record.profitLossQty==0) ? Math.abs(record.profitLossQty) : '--' }}
+            </span>
+            <span v-else></span>
+          </template>
+        </a-table>
+        <!-- 分页 -->
+        <tablePagination
+          ref="tablePagination"
+          :total="paginationProps.total"
+          :current="paginationProps.current"
+          :pageSize="paginationProps.pageSize"
+          @changePageSize="changePageSize"
+          @changePage="changePage" />
+      </a-card>
+    </a-spin>
+    <div class="affix-cont">
+      <a-button
+        type="primary"
+        id="supervisionDiskCheck-check-btn"
+        size="large"
+        class="button-primary"
+        :disabled="spinning"
+        @click="handleCheck"
+        style="padding: 0 50px;">重新盘点</a-button>
+      <a-button
+        type="primary"
+        id="supervisionDiskCheck-submit-btn"
+        size="large"
+        class="button-primary"
+        :disabled="spinning"
+        @click="handleSubmit"
+        style="padding: 0 60px;margin-left: 15px">提交监盘</a-button>
+    </div>
+    <!-- 盘点打印确认 -->
+    <printModal
+      :openModal="visiblePrint"
+      :content="printContent"
+      :okText="printOkText"
+      cancelText="打印预览"
+      :isCancel="isPrintCancel"
+      :spinning="spinningPrint"
+      @close="visiblePrint=false"
+      @ok="printOkText == '好的' ? visiblePrint=false : handlePrint('print')"
+      @fail="handlePrint('preview')" />
+    <!-- 打印 -->
+    <div id="print"></div>
+  </div>
+</template>
+
+<script>
+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 {
+  components: { STable, VSelect, tablePagination, printModal },
+  data () {
+    return {
+      spinning: false,
+      disabled: false,
+      loading: false,
+      queryParam: {
+        productCode: ''
+      },
+      // 表头
+      columns: [
+        { title: '序号', dataIndex: 'no', width: '6%', align: 'center' },
+        { title: '产品名称', dataIndex: 'productName', width: '16%', align: 'left', customRender: function (text) { return text || '--' }, ellipsis: true },
+        { title: '单位', dataIndex: 'productUnit', width: '5%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '仓库', dataIndex: 'warehouseName', width: '12%', align: 'center', customRender: function (text) { return text || '--' }, ellipsis: true },
+        { title: '仓位', dataIndex: 'warehouseLocationName', width: '11%', align: 'center', customRender: function (text) { return text || '--' }, ellipsis: true },
+        { title: '入库时间', dataIndex: 'lastStockTime', width: '12%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '批次', dataIndex: 'stockBatchNo', width: '6%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '产品编码', dataIndex: 'productCode', width: '14%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '库存数量', dataIndex: 'stockQty', width: '6%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
+        { title: '盘点数量', dataIndex: 'checkQty', width: '6%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
+        { title: '监盘数量', dataIndex: 'checkSuperviseQty', width: '8%', scopedSlots: { customRender: 'checkSuperviseQty' }, align: 'center' },
+        { title: '盈亏数量', dataIndex: 'profitLossQty', scopedSlots: { customRender: 'profitLossQty' }, width: '6%', align: 'center' }
+      ],
+      list: [],
+      paginationProps: {
+        total: 0, //  分页总条数
+        current: 1,
+        pageSize: 20
+      },
+      expandedRowKeys: [],
+      detail: null, //  详情数据
+      foldState: false, //  是否折叠列表
+      productTotal: null, //  合计
+      spinningPrint: false,
+      visiblePrint: false,
+      printContent: '',
+      printOkText: '',
+      isPrintCancel: false
+    }
+  },
+  methods: {
+    //  返回列表
+    handleBack () {
+      this.$router.push({ path: '/inventoryManagement/supervisionDisk/list', query: { closeLastOldTab: true, isRefresh: true } })
+    },
+    // 重置
+    resetSearchForm () {
+      this.queryParam.productCode = ''
+      this.getList()
+    },
+    // 盘点数量  blur
+    checkSuperviseQtyBlur (val, record) {
+      //  光标移出,值发生改变再调用编辑接口
+      if (val != record.checkSuperviseQtyBackups) {
+        this.handleEdit(record)
+      }
+    },
+    //  编辑
+    handleEdit (row) {
+      const params = {
+        checkWarehouseSn: this.$route.params.sn,
+        productSn: row.productSn,
+        reCheckSuperviseQty: row.checkSuperviseQty,
+        stockQty: row.stockQty
+      }
+      // 清空数量时,值应保持未清空前的值,因数量不可为空
+      if (!(row.checkSuperviseQty || row.checkSuperviseQty == 0)) {
+        row.checkSuperviseQty = row.checkSuperviseQtyBackups
+        return
+      }
+      this.spinning = true
+      checkWarehouseDetailSave(params).then(res => {
+        if (res.status == 200) {
+          this.$message.success(res.message)
+          this.getList()
+          this.spinning = false
+        } else {
+          this.spinning = false
+        }
+      })
+    },
+    // 提交监盘
+    handleSubmit () {
+      const _this = this
+      this.$confirm({
+        title: '提示',
+        content: '确认提交盘点吗?',
+        centered: true,
+        closable: true,
+        onOk () {
+          _this.spinning = true
+          checkWarehouseSupervise({ checkWarehouseSn: _this.$route.params.sn }).then(res => {
+            if (res.status == 200) {
+              _this.$message.success(res.message)
+              _this.handleBack()
+              _this.spinning = false
+            } else {
+              _this.spinning = false
+            }
+          })
+        }
+      })
+    },
+    // 重新盘点
+    handleCheck () {
+      const _this = this
+      this.$confirm({
+        title: '提示',
+        content: '确认要重新盘点吗?',
+        centered: true,
+        closable: true,
+        onOk () {
+          _this.spinning = true
+          checkWarehouseReCheck({ checkWarehouseSn: _this.$route.params.sn }).then(res => {
+            if (res.status == 200) {
+              _this.$message.success(res.message)
+              _this.handleBack()
+              _this.spinning = false
+            } else {
+              _this.spinning = false
+            }
+          })
+        }
+      })
+    },
+    // 获取列表数据
+    getList (pageNo) {
+      this.disabled = true
+      this.paginationProps.current = pageNo || this.paginationProps.current
+      const params = {
+        pageNo: this.paginationProps.current,
+        pageSize: this.paginationProps.pageSize,
+        checkWarehouseSn: this.$route.params.sn,
+        productCode: this.queryParam.productCode
+      }
+      this.loading = true
+      checkWarehouseDetailList(params).then(res => {
+        this.loading = false
+        if (res.status == 200) {
+          this.getCount(params)
+          const data = res.data
+          this.paginationProps.total = Number(res.data.count) || 0
+          this.paginationProps.current = data.pageNo
+          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].checkSuperviseQtyBackups = data.list[i].checkSuperviseQty
+            if (!this.foldState) {
+              this.expandedRowKeys.push(data.list[i].id + data.list[i].type)
+            }
+          }
+          this.list = data.list
+          this.disabled = false
+        } else {
+          this.paginationProps.total = 0
+          this.paginationProps.current = 1
+          this.paginationProps.pageSize = 20
+          this.list = []
+        }
+      })
+    },
+    getCount (params) {
+      checkWarehouseDetailCount(params).then(res => {
+        if (res.status == 200) {
+          this.productTotal = res.data
+        } else {
+          this.productTotal = null
+        }
+      })
+    },
+    //  分页  一页多少条change
+    changePageSize (current, pageSize) {
+      this.paginationProps.current = current
+      this.paginationProps.pageSize = pageSize
+      this.getList()
+    },
+    //  分页 页码change
+    changePage (current) {
+      this.paginationProps.current = current
+      this.getList()
+    },
+    //  详情
+    getDetail () {
+      checkWarehouseDetail({ sn: this.$route.params.sn }).then(res => {
+        if (res.status == 200) {
+          this.detail = res.data
+        } else {
+          this.detail = null
+        }
+      })
+    },
+    // 展开收起
+    handleExpand (expanded, record) {
+      if (record.type == 'superior') { // 只处理父级
+        if (expanded) {
+          this.expandedRowKeys.push(record.id + record.type)
+        } else {
+          if (this.expandedRowKeys.length > 0) {
+            const expandedRowKeys = this.expandedRowKeys.filter(RowKey => RowKey !== (record.id + record.type))
+            this.expandedRowKeys = expandedRowKeys
+          }
+        }
+      }
+    },
+    // 折叠列表
+    foldStateChange (e) {
+      if (e.target.checked) {
+        this.expandedRowKeys = []
+      } else {
+        this.expandedRowKeys = []
+        this.list.map(item => {
+          this.expandedRowKeys.push(item.id + item.type)
+        })
+      }
+    },
+    // 盘点打印
+    handlePdPrint () {
+      this.spinning = true
+      checkWarehousePrintCheck({ checkWarehouseSn: this.$route.params.sn, type: 'CHECK_WAREHOUSE_SUPERVISE' }).then(res => {
+        this.spinning = false
+        if (res.status == 200) {
+          if (res.data && res.data == 0) { // 无产品
+            this.printContent = '打印模板内容是所有有盈亏的产品,此单盘点人盘点无盈亏记录,无法打印'
+            this.printOkText = '好的'
+            this.isPrintCancel = false
+            this.visiblePrint = true
+          } else { // 有产品
+            this.printContent = '打印范围 —— 有盈亏(批次合并)'
+            this.printOkText = '立即打印'
+            this.isPrintCancel = true
+            this.visiblePrint = true
+          }
+        }
+      })
+    },
+    // 打印预览/快捷打印
+    handlePrint (type) {
+      const _this = this
+      _this.spinningPrint = true
+      checkWarehouseDetailPrint({ checkWarehouseSn: this.$route.params.sn, type: 'CHECK_WAREHOUSE_SUPERVISE' }).then(res => {
+        _this.spinningPrint = 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)
+        }
+      })
+    },
+    print (data, type) {
+      if (!data) {
+        return
+      }
+      const url = window.URL.createObjectURL(new Blob([data], { type: 'application/pdf' }))
+      document.getElementById('print').innerHTML = '<iframe id="printfbod" name="printfbod" src="' + url + '" hidden></iframe>'
+      if (type == 'preview') { //  预览
+        window.open(url)
+      } else if (type == 'print') { //  打印
+        window.frames['printfbod'].focus()
+        window.frames['printfbod'].print()
+      }
+    }
+  },
+  mounted () {
+    if (!this.$store.state.app.isNewTab) { // 页签刷新时调用
+      console.log(111)
+      this.resetSearchForm()
+      this.getDetail()
+    }
+  },
+  activated () {
+    // 如果是新页签打开或者进入新的子页(例:存在列表第2条数据编辑页页签时再打开第4条数据的编辑页),则重置当前页面
+    if (this.$store.state.app.isNewTab || !this.$store.state.app.isNewSubTab) {
+      console.log(222)
+      this.resetSearchForm()
+      this.getDetail()
+    }
+  },
+  beforeRouteEnter (to, from, next) {
+    next(vm => {})
+  }
+}
+</script>
+
+<style lang="less">
+  .supervisionDiskCheck-wrap{
+    position: relative;
+    height: 100%;
+    padding-bottom: 51px;
+    box-sizing: border-box;
+    >.ant-spin-nested-loading{
+      overflow-y: scroll;
+      height: 100%;
+    }
+    .supervisionDiskCheck-cont{
+      margin-bottom: 10px;
+      .billno{
+        font-size: 16px;
+        font-weight: bold;
+        margin: 0 15px;
+      }
+      .state-c{
+        color: #ed1c24;
+        font-size: 13px;
+        font-weight: bold;
+      }
+    }
+    .input-number{
+      .ant-input-number-input{
+        text-align: center;
+      }
+    }
+  }
+</style>

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

@@ -0,0 +1,152 @@
+<template>
+  <a-card size="small" :bordered="false" class="supervisionDiskList-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="盘点单号">
+                <a-input id="supervisionDiskList-checkWarehouseNo" v-model.trim="queryParam.checkWarehouseNo" allowClear placeholder="请输入盘点单号"/>
+              </a-form-item>
+            </a-col>
+            <a-col :md="6" :sm="24">
+              <a-button type="primary" @click="$refs.table.refresh(true)" :disabled="disabled" id="supervisionDiskList-refresh">查询</a-button>
+              <a-button style="margin-left: 5px" @click="resetSearchForm" :disabled="disabled" id="supervisionDiskList-reset">重置</a-button>
+            </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="action" slot-scope="text, record">
+          <a-button
+            size="small"
+            type="link"
+            v-if="$hasPermissions('B_supervisionDiskCheck')"
+            class="button-info"
+            @click="handleCheck(record)"
+            id="supervisionDiskList-audit-btn">监盘</a-button>
+          <span v-else>--</span>
+        </template>
+      </s-table>
+    </a-spin>
+  </a-card>
+</template>
+
+<script>
+import { STable, VSelect } from '@/components'
+import { checkWarehouseList } from '@/api/checkWarehouse'
+export default {
+  components: { STable, VSelect },
+  data () {
+    return {
+      spinning: false,
+      tableHeight: 0,
+      disabled: false, //  查询、重置按钮是否可操作
+      queryParam: { //  查询条件
+        checkWarehouseNo: ''
+      },
+      columns: [
+        { title: '序号', dataIndex: 'no', width: '4%', align: 'center' },
+        { title: '盘点单号', dataIndex: 'checkWarehouseNo', width: '15%', align: 'center' },
+        { title: '盘点状态', dataIndex: 'checkStateDictValue', width: '6%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '盘点人', dataIndex: 'checkPersonName', align: 'center', width: '12%', customRender: function (text) { return text || '--' }, ellipsis: true },
+        { title: '盘点时间', dataIndex: 'checkTime', width: '11%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '监盘状态', dataIndex: 'checkSuperviseStateDictValue', width: '6%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '产品款数', dataIndex: 'productTotalCategory', width: '8%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
+        { title: '库存数量', dataIndex: 'totalStockQty', width: '8%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
+        { title: '盘点数量', dataIndex: 'checkTotalQty', width: '8%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
+        { title: '监盘数量', dataIndex: 'checkSuperviseTotalQty', width: '8%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
+        { title: '监盘盈亏数量', dataIndex: 'totalProfitLossQty', width: '8%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
+        { title: '操作', scopedSlots: { customRender: 'action' }, width: '6%', align: 'center' }
+      ],
+      // 加载数据方法 必须为 Promise 对象
+      loadData: parameter => {
+        this.disabled = true
+        this.spinning = true
+        return checkWarehouseList(Object.assign(parameter, this.queryParam, { state: 'WAIT_SUPERVISE_CHECK' })).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
+          }
+          this.disabled = false
+          this.spinning = false
+          return data
+        })
+      }
+    }
+  },
+  methods: {
+    // 监盘
+    handleCheck (row) {
+      this.$router.push({ path: `/inventoryManagement/supervisionDisk/check/${row.checkWarehouseSn}` })
+    },
+    resetSearchForm () {
+      this.queryParam.checkWarehouseNo = ''
+      this.$refs.table.refresh(true)
+    },
+    pageInit () {
+      const _this = this
+      this.$nextTick(() => { // 页面渲染完成后的回调
+        _this.setTableH()
+      })
+    },
+    setTableH () {
+      this.tableHeight = window.innerHeight - 240
+    }
+  },
+  mounted () {
+    if (!this.$store.state.app.isNewTab) { // 页签刷新时调用
+      this.pageInit()
+      this.$refs.table.refresh(true)
+    }
+  },
+  activated () {
+    // 如果是新页签打开,则重置当前页面
+    if (this.$store.state.app.isNewTab) {
+      this.pageInit()
+      this.$refs.table.refresh(true)
+    }
+    // 仅刷新列表,不重置页面
+    if (this.$store.state.app.updateList) {
+      this.pageInit()
+      this.$refs.table.refresh()
+    }
+  },
+  beforeRouteEnter (to, from, next) {
+    next(vm => {
+      const _this = vm
+      if (vm.$route.query.isRefresh) {
+        setTimeout(() => {
+          _this.$refs.table.refresh(true)
+        }, 300)
+      }
+    })
+  }
+}
+</script>
+
+<style lang="less">
+  .supervisionDiskList-wrap{
+    .active{
+      color: #ed1c24;
+      cursor: pointer;
+    }
+    .common{
+      color: rgba(0, 0, 0, 0.65);
+    }
+  }
+</style>