瀏覽代碼

销售单新版

lilei 2 年之前
父節點
當前提交
5ed3a586d3

+ 1 - 1
public/version.json

@@ -1,5 +1,5 @@
 {
   "message": "发现有新版本发布,确定更新系统?",
   "vendorJsVersion": "",
-  "version": 1677477194999
+  "version": 1677479105133
 }

+ 18 - 0
src/components/index.less

@@ -334,6 +334,24 @@
     padding: 7px 0 4px;
     box-shadow: 0 0 20px #dcdee2;
   }
+
+  .jg-page-wrap{
+    .table-page-search-wrapper{
+      margin-bottom: 6px;
+      .ant-form.ant-form-inline .ant-form-item .ant-input, .ant-form.ant-form-inline .ant-form-item .ant-select-selection{
+        border:0;
+      }
+      .ant-form.ant-form-inline .ant-form-item{
+        border:1px solid #dadada;
+        border-radius: 3px;
+        overflow: hidden;
+        .ant-form-item-label{
+          padding-left: 11px;
+          padding-right: 0!important;
+        }
+      }
+    }
+  }
 }
 // 确认框居中
 .confirm-center{

+ 3 - 3
src/components/tools/UserMenu.vue

@@ -63,9 +63,9 @@
       <p class="help-cont" @click="screen">
         <a-popover placement="bottom">
         <template slot="content">
-          <span>{{ isFullscreen?'全屏':'取消全屏' }}</span>
+          <span>{{ isFullscreen?'取消全屏':'全屏' }}</span>
         </template>
-        <a-icon :type="isFullscreen?'fullscreen':'fullscreen-exit'" style="font-size:14px;margin: 0 5px;color: #666;"/>
+        <a-icon :type="isFullscreen?'fullscreen-exit':'fullscreen'" style="font-size:14px;margin: 0 5px;color: #666;"/>
       </a-popover>
       </p>
 
@@ -183,7 +183,7 @@ export default {
         return false
       }
       screenfull.toggle()
-      this.isFullscreen = screenfull.isFullscreen
+      this.isFullscreen = !this.isFullscreen
     },
     // 切换角色
     changeRoles (sn) {

+ 58 - 0
src/config/router.config.js

@@ -153,6 +153,64 @@ export const asyncRouterMap = [
               }
             ]
           },
+          {
+            path: '/salesManagement/salesQueryNew',
+            redirect: '/salesManagement/salesQueryNew/list',
+            name: 'salesQueryNew',
+            component: BlankLayout,
+            meta: {
+              title: '销售单(新版)',
+              icon: 'monitor',
+              permission: 'M_salesQueryList'
+            },
+            hideChildrenInMenu: true,
+            children: [
+              {
+                path: 'list',
+                name: 'salesNewList',
+                component: () => import(/* webpackChunkName: "salesManagement" */ '@/views/salesManagement/salesQueryNew/list.vue'),
+                meta: {
+                  title: '销售单列表',
+                  icon: 'monitor',
+                  hidden: true,
+                  permission: 'M_salesQueryList'
+                }
+              },
+              {
+                path: 'detail/:sn',
+                name: 'salesNewDetail',
+                component: () => import(/* webpackChunkName: "salesManagement" */ '@/views/salesManagement/salesQueryNew/detail.vue'),
+                meta: {
+                  title: '销售单详情',
+                  icon: 'monitor',
+                  hidden: true,
+                  permission: 'B_salesDetail'
+                }
+              },
+              {
+                path: 'add/:id/:sn/:priceType',
+                name: 'salesNewAdd',
+                component: () => import(/* webpackChunkName: "salesManagement" */ '@/views/salesManagement/salesQueryNew/edit.vue'),
+                meta: {
+                  title: '新增销售单',
+                  icon: 'monitor',
+                  hidden: true,
+                  permission: 'B_salesNews'
+                }
+              },
+              {
+                path: 'edit/:id/:sn/:priceType',
+                name: 'salesNewEdit',
+                component: () => import(/* webpackChunkName: "salesManagement" */ '@/views/salesManagement/salesQuery/edit.vue'),
+                meta: {
+                  title: '编辑销售单',
+                  icon: 'monitor',
+                  hidden: true,
+                  permission: 'B_salesEdit'
+                }
+              }
+            ]
+          },
           {
             path: '/salesManagement/urgentItemsOffset',
             redirect: '/salesManagement/urgentItemsOffset/list',

+ 4 - 19
src/views/purchasingManagement/purchaseOrderNew/list.vue

@@ -1,8 +1,8 @@
 <template>
-  <div class="purchaseNewOrderList-wrap">
-    <a-card size="small" :bordered="false" style="margin-bottom: 6px;">
+  <div class="purchaseNewOrderList-wrap jg-page-wrap">
+    <a-card size="small" :bordered="false" class="table-page-search-wrapper">
         <!-- 搜索条件 -->
-      <div ref="tableSearch" class="table-page-search-wrapper">
+      <div ref="tableSearch">
         <a-form layout="inline" @keyup.enter.native="$refs.table.refresh(true)">
           <a-row type="flex" justify="start" :gutter="15">
             <a-col flex="350px">
@@ -386,20 +386,5 @@ export default {
 }
 </script>
 <style lang="less">
-  .purchaseNewOrderList-wrap{
-    .table-page-search-wrapper{
-      .ant-form.ant-form-inline .ant-form-item .ant-input, .ant-form.ant-form-inline .ant-form-item .ant-select-selection{
-        border:0;
-      }
-      .ant-form.ant-form-inline .ant-form-item{
-        border:1px solid #dadada;
-        border-radius: 3px;
-        overflow: hidden;
-        .ant-form-item-label{
-          padding-left: 11px;
-          padding-right: 0!important;
-        }
-      }
-    }
-  }
+   
 </style>

+ 121 - 0
src/views/salesManagement/salesQueryNew/carInfoModal.vue

@@ -0,0 +1,121 @@
+<template>
+  <div v-if="isShow">
+    <a-modal
+      centered
+      class="carInfoDetail-modal"
+      :footer="null"
+      :maskClosable="false"
+      v-model="isShow"
+      @cancel="isShow=false"
+      :width="800">
+      <div>
+        <div class="head-info-con">
+          <p class="head-info-title">车型信息</p>
+          <a-divider style="margin: 12px 0;" />
+        </div>
+        <a-descriptions bordered :column="2" size="small" class="head-info-main">
+          <a-descriptions-item label="车型信息:">{{ infoData&&infoData.text || '--' }}</a-descriptions-item>
+          <a-descriptions-item label="品牌:">{{ infoData&&infoData.brand_name || '--' }}</a-descriptions-item>
+          <a-descriptions-item label="车型:">{{ infoData&&infoData.model_name || '--' }}</a-descriptions-item>
+          <a-descriptions-item label="品牌LOGO:">
+            <img :src="infoData&&infoData.icon?infoData.icon:defImg" width="30" height="30" style="border-radius: 50%;" />
+          </a-descriptions-item>
+          <a-descriptions-item label="排量:">{{ infoData&&infoData.sub_name || '--' }}</a-descriptions-item>
+          <a-descriptions-item label="年款:">{{ infoData&&infoData.year || '--' }}</a-descriptions-item>
+          <a-descriptions-item label="车型图:">
+            <div v-if="infoData&&infoData.images.length>0">
+              <img :src="infoData.images[0] || defImg" width="30" height="30" class="imageUrl" @click="inited(infoData.images)" />
+            </div>
+            <span v-else>--</span>
+          </a-descriptions-item>
+          <a-descriptions-item label="车系:">{{ infoData&&infoData.series_name || '--' }}</a-descriptions-item>
+        </a-descriptions>
+        <div class="head-info-con" v-if="infoData&&infoData.params">
+          <p class="head-info-title">配置信息</p>
+          <a-divider style="margin: 12px 0;" />
+        </div>
+        <a-descriptions bordered :column="2" size="small" v-if="infoData&&infoData.params" class="head-info-main">
+          <a-descriptions-item v-for="item in infoData.params" :label="item.type_name+':'">{{ item.value || '--' }}</a-descriptions-item>
+        </a-descriptions>
+        <div class="btn-cont"><a-button id="carInfoDetail-modal-back" @click="isShow = false">返回</a-button></div>
+      </div>
+    </a-modal>
+  </div>
+</template>
+
+<script>
+import defImg from '@/assets/def_img@2x.png'
+export default {
+  name: 'CarInfoDetailModal',
+  props: {
+    openModal: { //  弹框显示状态
+      type: Boolean,
+      default: false
+    },
+    infoData: {
+      type: Object,
+      default: () => {
+        return {}
+      }
+    }
+  },
+  data () {
+    return {
+      isShow: this.openModal, //  是否打开弹框
+      defImg
+    }
+  },
+  methods: {
+    inited (viewer) {
+      if (viewer) {
+        const imageUrl = []
+        viewer.map(item => {
+          imageUrl.push(item)
+        })
+        this.$viewerApi({
+          images: imageUrl
+        })
+      }
+    }
+  },
+  watch: {
+    //  父页面传过来的弹框状态
+    openModal (newValue, oldValue) {
+      this.isShow = newValue
+    },
+    //  重定义的弹框状态
+    isShow (newValue, oldValue) {
+      if (!newValue) {
+        this.$emit('close')
+      }
+    }
+  }
+}
+</script>
+
+<style lang="less">
+  .carInfoDetail-modal{
+    .ant-modal-body {
+      padding: 40px 40px 24px;
+    }
+    .ant-descriptions-item-label.ant-descriptions-item-colon{
+      width: 117px;
+    }
+    .btn-cont {
+      text-align: center;
+      margin: 35px 0 10px;
+    }
+    .head-info-con{
+      .head-info-title{
+        font-size: 16px;
+        margin: 0;
+      }
+    }
+    .head-info-main{
+      margin-bottom: 20px;
+    }
+    .imageUrl{
+      cursor: pointer;
+    }
+  }
+</style>

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

@@ -0,0 +1,578 @@
+<template>
+  <div v-if="opened">
+    <a-modal
+      v-model="opened"
+      :title="title"
+      centered
+      :maskClosable="false"
+      :confirmLoading="confirmLoading"
+      :width="960"
+      :footer="null"
+      @cancel="cancel"
+    >
+      <a-spin :spinning="spinning" tip="Loading...">
+        <a-form-model
+          id="chooseCustom-form"
+          ref="ruleForm"
+          :model="form"
+          :rules="rules"
+          :label-col="formItemLayout.labelCol"
+          :wrapper-col="formItemLayout.wrapperCol"
+        >
+          <a-row :gutter="15">
+            <a-col :span="16">
+              <a-form-model-item label="客户名称" prop="buyerSn" :labelCol="{ span: 3 }" :wrapperCol="{ span: 20 }">
+                <selectCust ref="custList" :isValidateEnabled="true" id="chooseCustom-buyerSn" @change="custChange" v-model="form.buyerSn"></selectCust>
+              </a-form-model-item>
+            </a-col>
+            <a-col :span="8" v-if="$hasPermissions('B_customer_customerInfo_add')">
+              <a-form-model-item :labelCol="{ span: 0 }" :wrapperCol="{ span: 24 }">
+                <a-button type="primary" class="button-primary" @click="openNewCust" icon="plus">新增</a-button>
+                (点击新增按钮新增客户)
+              </a-form-model-item>
+            </a-col>
+          </a-row>
+          <a-row :gutter="15">
+            <a-col :span="24">
+              <a-form-model-item label="客户地址" required style="margin: 0;" :labelCol="{ span: 2 }" :wrapperCol="{ span: 22 }">
+                <a-row :gutter="15">
+                  <!-- 客户地址 -->
+                  <a-col span="8">
+                    <a-form-model-item prop="shippingAddressProvinceSn">
+                      <a-select id="chooseCustom-provinceSn" allowClear @change="getCityList" v-model="form.shippingAddressProvinceSn" placeholder="请选择省">
+                        <a-select-option v-for="item in addrProvinceList" :value="item.areaSn" :key="item.areaSn + 'a'">{{ item.name }}</a-select-option>
+                      </a-select>
+                    </a-form-model-item>
+                  </a-col>
+                  <a-col span="8">
+                    <a-form-model-item prop="shippingAddressCitySn">
+                      <a-select id="chooseCustom-citySn" allowClear @change="getAreaList" v-model="form.shippingAddressCitySn" placeholder="请选择市">
+                        <a-select-option v-for="item in addrCityList" :value="item.areaSn" :key="item.areaSn + 'b'">{{ item.name }}</a-select-option>
+                      </a-select>
+                    </a-form-model-item>
+                  </a-col>
+                  <a-col span="8">
+                    <a-form-model-item prop="shippingAddressCountySn">
+                      <a-select id="chooseCustom-countySn" allowClear @change="areaCharged" v-model="form.shippingAddressCountySn" placeholder="请选择区/县">
+                        <a-select-option v-for="item in addrDistrictList" :value="item.areaSn" :key="item.areaSn + 'c'">{{ item.name }}</a-select-option>
+                      </a-select>
+                    </a-form-model-item>
+                  </a-col>
+                </a-row>
+              </a-form-model-item>
+            </a-col>
+            <a-col :span="24">
+              <a-form-model-item label="详细地址" prop="shippingAddress" :labelCol="{ span: 2 }" :wrapperCol="{ span: 22 }">
+                <a-input
+                  id="chooseCustom-shippingAddress"
+                  :maxLength="60"
+                  v-model.trim="form.shippingAddress"
+                  placeholder="请输入详细地址(最多60个字符)"
+                  allowClear />
+              </a-form-model-item>
+            </a-col>
+          </a-row>
+          <a-row :gutter="15">
+            <a-col :span="8">
+              <a-form-model-item label="联系人" prop="consigneeName">
+                <a-input
+                  id="chooseCustom-consigneeName"
+                  :maxLength="30"
+                  v-model.trim="form.consigneeName"
+                  placeholder="请输入联系人(最多30个字符)"
+                  allowClear />
+              </a-form-model-item>
+            </a-col>
+            <a-col :span="8">
+              <a-form-model-item label="联系电话" prop="consigneeTel">
+                <a-input
+                  id="chooseCustom-consigneeTel"
+                  :maxLength="15"
+                  v-model.trim="form.consigneeTel"
+                  placeholder="请输入联系电话(最多15个字符)"
+                  allowClear />
+              </a-form-model-item>
+            </a-col>
+            <a-col :span="8">
+              <a-form-model-item label="联系手机" prop="consigneeMobile">
+                <a-input
+                  id="chooseCustom-consigneeMobile"
+                  :maxLength="11"
+                  v-model.trim="form.consigneeMobile"
+                  placeholder="请输入联系电话(最多11个字符)"
+                  allowClear />
+              </a-form-model-item>
+            </a-col>
+          </a-row>
+          <a-row :gutter="15">
+            <a-col :span="8">
+              <a-form-model-item label="价格类型" prop="priceType">
+                <a-row :gutter="15">
+                  <a-col :span="20">
+                    <v-select
+                      code="PRICE_TYPE"
+                      :disabled="priceTypeDisabled"
+                      id="chooseCustom-priceType"
+                      v-model="form.priceType"
+                      @change="changePriceType"
+                      allowClear
+                      placeholder="请选择价格类型" ></v-select>
+                  </a-col>
+                  <a-col :span="4">
+                    <a-popover>
+                      <template slot="content">(选择后在当前工单不可修改)</template>
+                      <a-icon type="question-circle" />
+                    </a-popover>
+                  </a-col>
+                </a-row>
+              </a-form-model-item>
+            </a-col>
+            <a-col :span="8">
+              <a-form-model-item label="收款方式" prop="settleStyleSn">
+                <settleStyle
+                  v-model="form.settleStyleSn"
+                  placeholder="请选择收款方式">
+                </settleStyle>
+              </a-form-model-item>
+            </a-col>
+            <a-col :span="8">
+              <a-form-model-item label="配送方式" prop="dispatchType">
+                <v-select code="DISPATCH_TYPE" id="chooseCustom-dispatchType" v-model="form.dispatchType" allowClear placeholder="请选择配送方式"></v-select>
+              </a-form-model-item>
+            </a-col>
+          </a-row>
+          <a-row :gutter="15">
+            <a-col :span="8">
+              <a-form-model-item label="业务员" prop="salesManSn">
+                <a-select id="chooseCustom-salesManSn" allowClear @change="salesManChange" v-model="form.salesManSn" placeholder="请选择业务员">
+                  <a-select-option v-for="item in userList" :value="item.employeeSn" :key="item.id + 'c'">{{ item.name }}</a-select-option>
+                </a-select>
+              </a-form-model-item>
+            </a-col>
+            <a-col :span="8">
+              <a-form-model-item label="铺货出库" prop="distributionFlag">
+                <v-select code="FLAG" id="chooseCustom-distributionFlag" v-model="form.distributionFlag" allowClear placeholder="请选择是否铺货出库"></v-select>
+              </a-form-model-item>
+            </a-col>
+          </a-row>
+          <a-row :gutter="15">
+            <a-col :span="8">
+              <a-form-model-item label="备注" prop="remarks">
+                <a-input
+                  id="chooseCustom-remarks"
+                  type="textarea"
+                  :maxLength="100"
+                  v-model.trim="form.remarks"
+                  placeholder="请输入备注(最多100个字符)"
+                  allowClear />
+              </a-form-model-item>
+            </a-col>
+            <a-col :span="8">
+              <a-form-model-item label="开单人">{{ $store.state.user.info.userNameCN }}</a-form-model-item>
+            </a-col>
+          </a-row>
+          <a-form-model-item :wrapper-col="{ span: 12, offset: 6 }" style="text-align: center;">
+            <a-button type="primary" size="large" :loading="confirmLoading" @click="handleSubmit" id="chooseCustom-btn-submit">保存</a-button>
+            <a-button @click="cancel" size="large" style="margin-left: 15px" id="chooseCustom-btn-back">取消</a-button>
+          </a-form-model-item>
+        </a-form-model>
+        <!-- 新增客户 -->
+        <a-modal
+          v-model="isNewCust"
+          title="新增客户"
+          centered
+          :width="960"
+          :maskClosable="false"
+          @cancel="cancelNewCust"
+          :footer="null"
+        >
+          <CustomerManagementEdit ref="newCust" model="modal" @ok="newCustFun"></CustomerManagementEdit>
+        </a-modal>
+      </a-spin>
+    </a-modal>
+  </div>
+</template>
+
+<script>
+import { getArea } from '@/api/data'
+import { custFindById, updateByCustomerSn } from '@/api/customer'
+import { salesSave } from '@/api/sales'
+import { employeeAllList } from '@/api/salesman'
+import settleStyle from '@/views/common/settleStyle'
+import { VSelect } from '@/components'
+import selectCust from '@/views/common/selectCust.vue'
+import CustomerManagementEdit from '@/views/customerManagement/customerInfo/edit.vue'
+export default {
+  name: 'ChooseCustomModal',
+  components: { VSelect, CustomerManagementEdit, selectCust, settleStyle },
+  props: {
+    show: [Boolean],
+    distributionFlag: {
+      type: [String, Number],
+      default: '0'
+    }
+  },
+  data () {
+    return {
+      spinning: false,
+      opened: this.show,
+      title: '选择客户',
+      confirmLoading: false,
+      formItemLayout: {
+        labelCol: { span: 6 },
+        wrapperCol: { span: 18 }
+      },
+      buyerSnBak: '', // 更改前客户sn备份
+      priceTypeBak: '', // 更改前客户价格类型备份
+      form: {
+        buyerName: '', // 客户名称
+        buyerSn: undefined, // 客户sn
+        consigneeTel: '', //  联系电话
+        consigneeMobile: '',
+        consigneeName: '', //  联系人
+        shippingAddressProvinceSn: undefined, //  省
+        shippingAddressProvinceName: '',
+        shippingAddressCitySn: undefined, // 市
+        shippingAddressCityName: '',
+        shippingAddressCountySn: undefined, // 区
+        shippingAddressCountyName: '',
+        shippingAddress: '', //  详细地址
+        fax: '', //  客户传真
+        dispatchType: undefined, //  配送方式
+        satelliteFlag: 0, //  是否卫星仓客户
+        priceType: undefined, //  价格类型
+        settleStyleSn: undefined, //  收款方式
+        salesManSn: undefined, //  业务员
+        salesManName: '',
+        distributionFlag: undefined, // 铺货出库
+        salesTragetType: 'CUSTOMER',
+        remarks: '' //  备注
+      },
+      rules: {
+        buyerSn: [
+          { required: true, message: '请选择客户', trigger: ['change', 'blur'] }
+        ],
+        consigneeMobile: [{ required: false, pattern: /^\d{11}$/, message: '请输入正确的手机号', trigger: 'blur' }],
+        shippingAddressProvinceSn: [
+          { required: true, message: '请选择省', trigger: 'change' }
+        ],
+        shippingAddressCitySn: [
+          { required: true, message: '请选择市', trigger: 'change' }
+        ],
+        shippingAddressCountySn: [
+          { required: true, message: '请选择区/县', trigger: 'change' }
+        ],
+        priceType: [
+          { required: true, message: '请选择价格类型', trigger: ['change', 'blur'] }
+        ],
+        settleStyleSn: [
+          { required: true, message: '请选择收款方式', trigger: ['change', 'blur'] }
+        ],
+        distributionFlag: [
+          { required: true, message: '请选择是否铺货出库', trigger: 'change' }
+        ]
+        // salesManSn: [
+        //   { required: true, message: '请选择业务员', trigger: 'change' }
+        // ]
+      },
+      addrProvinceList: [], //  省下拉
+      addrCityList: [], //  市下拉
+      addrDistrictList: [], //  区下拉
+      userList: [], // 业务员 下拉
+      custId: undefined, // 客户id
+      isEdit: false, //  是否编辑状态
+      priceTypeDisabled: false, // 价格类型可编辑
+      isChangeCust: false, // 是否更换客户
+      interId: null,
+      isNewCust: false // 是否新增客户
+    }
+  },
+  methods: {
+    changePriceType (v) {
+      this.form.priceType = v
+      this.$refs.ruleForm.clearValidate('priceType')
+    },
+    openNewCust () {
+      this.isNewCust = true
+      setTimeout(() => {
+        this.$refs.newCust.getBaseData()
+      }, 500)
+    },
+    // 新建客户
+    newCustFun (data) {
+      console.log(data, this.isEdit)
+      this.isNewCust = false
+      // 更新客户信息
+      this.$refs.custList.setData({ key: data.customerSn, label: data.customerName, row: data })
+      this.custChange({ key: data.customerSn, label: data.customerName, row: data })
+    },
+    // 业务员
+    salesManChange (employeeSn) {
+      if (employeeSn) {
+        this.form.salesManName = this.userList.find(item => item.employeeSn == employeeSn).name
+      } else {
+        this.form.salesManName = ''
+      }
+    },
+    // 客户 change
+    custChange (obj) {
+      const _this = this
+      if (obj && obj.key) {
+        const cust = obj.row
+        this.form.buyerSn = cust.customerSn
+        // 编辑
+        if (this.isEdit) {
+          this.$confirm({
+            title: '提示',
+            content: '更换客户后信息需要重新完善,确认要更换吗?',
+            centered: true,
+            onOk () {
+              _this.custId = cust.id
+              _this.form.buyerName = cust.customerName
+              _this.priceTypeDisabled = false
+              _this.getDetail()
+            },
+            onCancel () {
+              _this.form.buyerSn = _this.buyerSnBak
+            }
+          })
+        } else {
+          _this.custId = cust.id
+          _this.form.buyerName = cust.customerName
+          _this.getDetail()
+        }
+      } else {
+        this.$refs.ruleForm.resetFields()
+        this.$refs.custList.resetForm()
+      }
+    },
+    // 编辑客户信息
+    editCust (data) {
+      console.log(data)
+      this.title = '编辑客户信息'
+      this.isEdit = true
+      this.priceTypeDisabled = true
+      if (data.shippingAddressProvinceSn) { this.getArea('city', data.shippingAddressProvinceSn) }
+      if (data.shippingAddressCitySn) { this.getArea('district', data.shippingAddressCitySn) }
+      this.form = Object.assign(this.form, data)
+      this.buyerSnBak = this.form.buyerSn
+      this.priceTypeBak = this.form.priceType
+      this.$nextTick(() => {
+        this.$refs.custList.setData({ key: data.buyerSn, label: data.buyerName, row: data })
+      })
+    },
+    //  获取详情
+    getDetail () {
+      this.spinning = true
+      custFindById({ id: this.custId }).then(res => {
+        const data = res.data
+        console.log(res)
+        if (res.status == 200 && data) {
+          if (data.provinceSn) { this.getArea('city', data.provinceSn) }
+          if (data.citySn) { this.getArea('district', data.citySn) }
+          this.form = Object.assign(this.form, {
+            buyerName: data.customerName, // 客户名称
+            buyerSn: data.customerSn, // 客户sn
+            consigneeTel: data.contactTel, //  联系电话
+            consigneeMobile: data.contactMobile,
+            consigneeName: data.contactName, //  联系人
+            shippingAddressProvinceSn: data.provinceSn, //  省
+            shippingAddressProvinceName: data.provinceName,
+            shippingAddressCitySn: data.citySn, // 市
+            shippingAddressCityName: data.cityName,
+            shippingAddressCountySn: data.countySn, // 区
+            shippingAddressCountyName: data.countyName,
+            shippingAddress: data.customerAddr, //  详细地址
+            fax: data.fax, //  客户传真
+            dispatchType: data.dispatchType, //  配送方式
+            satelliteFlag: data.satelliteFlag, //  是否卫星仓客户
+            priceType: data.priceType, //  价格类型
+            settleStyleSn: data.settleStyleSn //  收款方式
+          })
+          // this.buyerSnBak = this.form.buyerSn
+          // this.priceTypeBak = this.form.priceType
+        } else {
+          this.$message.error('获取客户信息失败')
+          this.$refs.ruleForm.resetFields()
+        }
+        this.$refs.ruleForm.clearValidate()
+        this.spinning = false
+      })
+    },
+    // 保存客户信息
+    handleSaveCust () {
+      const params = {
+        customerName: this.form.buyerName,
+        customerSn: this.form.buyerSn,
+        contactTel: this.form.consigneeTel, //  联系电话
+        contactMobile: this.form.consigneeMobile,
+        contactName: this.form.consigneeName, //  联系人
+        provinceSn: this.form.shippingAddressProvinceSn, //  省
+        provinceName: this.form.shippingAddressProvinceName,
+        citySn: this.form.shippingAddressCitySn, // 市
+        cityName: this.form.shippingAddressCityName,
+        countySn: this.form.shippingAddressCountySn, // 区
+        countyName: this.form.shippingAddressCountyName,
+        customerAddr: this.form.shippingAddress, //  详细地址
+        dispatchType: this.form.dispatchType, //  配送方式
+        priceType: this.form.priceType, //  价格类型
+        settleStyleSn: this.form.settleStyleSn //  收款方式
+      }
+      this.spinning = true
+      updateByCustomerSn(params).then(res => {
+        this.spinning = false
+        if (res.status == 200) {
+          // 保存销售单
+          this.salesSaveFun()
+          this.spinning = false
+        } else {
+          this.spinning = false
+        }
+      })
+    },
+    //  保存
+    handleSubmit (e) {
+      e.preventDefault()
+      const _this = this
+      console.log(_this.form, '------save')
+      this.$refs.ruleForm.validate(valid => {
+        if (valid) {
+          // 如果价格类型改变,提示
+          if (_this.priceTypeBak != _this.form.priceType && this.isEdit) {
+            this.$confirm({
+              title: '提示',
+              content: '价格类型变更,确认提交吗?',
+              centered: true,
+              onOk () {
+                // 保存客户信息
+                _this.handleSaveCust()
+              }
+            })
+          } else {
+            // 保存客户信息
+            _this.handleSaveCust()
+          }
+        } else {
+          console.log('error submit!!')
+          return false
+        }
+      })
+    },
+    // 新建或编辑销售单
+    salesSaveFun () {
+      const _this = this
+      const form = this.form
+      _this.spinning = true
+      salesSave(form).then(res => {
+        if (res.status == 200) {
+          _this.$message.success(res.message)
+          _this.$emit('ok', res.data)
+          if (_this.form.id) {
+            _this.$emit('updateData', form.priceType)
+          }
+          _this.cancel()
+          _this.spinning = false
+        } else {
+          _this.spinning = false
+        }
+      })
+    },
+    cancel () {
+      this.opened = false
+      this.$emit('cancel')
+      this.$refs.ruleForm.resetFields()
+      this.$refs.custList.resetForm()
+    },
+    cancelNewCust () {
+      this.isNewCust = false
+      this.$refs.newCust.getBaseData()
+    },
+    // 获取业务员列表数据
+    getUserAllList () {
+      employeeAllList({}).then(res => {
+        if (res.status == 200) {
+          this.userList = res.data || []
+        } else {
+          this.userList = []
+        }
+      })
+    },
+    // 获取城市列表
+    getCityList (val) {
+      this.addrCityList = []
+      this.addrDistrictList = []
+      this.form.shippingAddressCitySn = undefined
+      this.form.shippingAddressCityName = ''
+      this.form.shippingAddressCountySn = undefined
+      this.form.shippingAddressCountyName = ''
+      if (val) {
+        this.getArea('city', val)
+        this.form.shippingAddressProvinceName = this.addrProvinceList.find(item => item.areaSn == val).name
+      } else {
+        this.form.shippingAddressProvinceName = ''
+      }
+    },
+    // 获取区县列表
+    getAreaList (val) {
+      this.addrDistrictList = []
+      this.form.shippingAddressCountySn = undefined
+      this.form.shippingAddressCountyName = ''
+      if (val) {
+        this.getArea('district', val)
+        this.form.shippingAddressCityName = this.addrCityList.find(item => item.areaSn == val).name
+      } else {
+        this.form.shippingAddressCityName = ''
+      }
+    },
+    // 区县变更
+    areaCharged (val) {
+      if (val) {
+        this.form.shippingAddressCountyName = this.addrDistrictList.find(item => item.areaSn == val).name
+      } else {
+        this.form.shippingAddressCountyName = ''
+      }
+    },
+    //  省/市/区
+    getArea (leve, sn) {
+      let params
+      if (leve == 'province') {
+        params = { type: '2' }
+      } else {
+        params = { parentId: sn, type: leve == 'city' ? '3' : '4' }
+      }
+      getArea(params).then(res => {
+        if (res.status == 200) {
+          if (leve == 'province') {
+            this.addrProvinceList = res.data || []
+          } else if (leve == 'city') {
+            this.addrCityList = res.data || []
+          } else if (leve == 'district') {
+            this.addrDistrictList = res.data || []
+          }
+        } else {
+          if (leve == 'province') {
+            this.addrProvinceList = []
+          } else if (leve == 'city') {
+            this.addrCityList = []
+          } else if (leve == 'district') {
+            this.addrDistrictList = []
+          }
+        }
+      })
+    }
+  },
+  watch: {
+    show (newValue, oldValue) {
+      this.opened = newValue
+      if (newValue) {
+        this.getArea('province')
+        this.getUserAllList()
+      }
+    },
+    distributionFlag (newValue, oldValue) {
+      console.log(newValue, oldValue)
+      this.form.distributionFlag = newValue.toString()
+    }
+  }
+}
+</script>

+ 202 - 0
src/views/salesManagement/salesQueryNew/chooseImportModal.vue

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

+ 433 - 0
src/views/salesManagement/salesQueryNew/chooseShelfProduct.vue

@@ -0,0 +1,433 @@
+<template>
+  <a-modal
+    centered
+    class="chooseShelf-modal"
+    :footer="null"
+    :maskClosable="false"
+    :title="mtitle"
+    v-model="isShow"
+    @cancel="isShow = false"
+    width="80%">
+    <a-spin :spinning="spinning" tip="Loading...">
+      <a-tabs type="card">
+        <a-tab-pane :defaultActiveKey="curTab" v-model="curTab" :key="1" tab="待补货产品">
+          <!-- 搜索条件 -->
+          <div class="table-page-search-wrapper">
+            <a-form-model
+              ref="ruleForm"
+              class="form-model-con"
+              layout="inline"
+              :model="queryParam"
+              @keyup.enter.native="$refs.table.refresh(true)" >
+              <a-row :gutter="15">
+                <a-col :md="4" :sm="24">
+                  <a-form-model-item label="产品编码">
+                    <a-input id="chooseShelf-code" ref="searchProductCode" v-model.trim="queryParam.productCode" allowClear placeholder="请输入产品编码"/>
+                  </a-form-model-item>
+                </a-col>
+                <a-col :md="4" :sm="24">
+                  <a-form-model-item label="产品名称">
+                    <a-input id="chooseShelf-name" v-model.trim="queryParam.productName" allowClear placeholder="请输入产品名称"/>
+                  </a-form-model-item>
+                </a-col>
+                <a-col :md="6" :sm="24">
+                  <a-form-model-item label="产品分类">
+                    <ProductType id="chooseShelf-productType" :isDealer="true" @change="changeProductType" v-model="productType"></ProductType>
+                  </a-form-model-item>
+                </a-col>
+                <a-col :md="6" :sm="24">
+                  <a-form-model-item label="库存情况">
+                    <a-checkbox-group v-model.trim="queryParam.stockStateList" :options="options" />
+                  </a-form-model-item>
+                </a-col>
+                <a-col :md="4" :sm="12" style="margin-bottom: 10px;">
+                  <a-button type="primary" @click="$refs.table.refresh(true)" id="chooseShelf-refresh">查询</a-button>
+                  <a-button style="margin-left: 5px" @click="resetSearchForm" id="chooseShelf-reset">重置</a-button>
+                </a-col>
+              </a-row>
+            </a-form-model>
+          </div>
+          <div class="chooseShelf-modal-table">
+            <div class="table-operator">
+              <div>
+                <a-button type="primary" @click="handlePlAdd">批量添加</a-button>
+                <span style="margin-left: 10px;" v-if="selectTotal">已选{{ selectTotal }}项</span>
+              </div>
+              <div>
+                <a-icon type="info-circle" />
+                此界面仅显示货架上需要补货的产品
+              </div>
+            </div>
+            <!-- 列表 -->
+            <s-table
+              class="sTable"
+              ref="table"
+              size="small"
+              :rowKey="(record) => record.id"
+              :row-selection="{columnWidth: 40, getCheckboxProps: record => ({ props: { disabled: record.includeFlag == 1 } })}"
+              @rowSelection="rowSelectionFun"
+              :columns="columns"
+              :data="loadData"
+              :style="{ height: '500px' }"
+              :scroll="{ y: 450 }"
+              :showPagination="false"
+              bordered>
+              <!-- 售价 -->
+              <template slot="salePrice" slot-scope="text, record">
+                <div style="display: flex;align-items: center;" @dblclick.stop>
+                  <a-input-number
+                    size="small"
+                    v-model="record.price"
+                    :precision="2"
+                    :min="0"
+                    :max="999999"
+                    style="width: 100%;"
+                    placeholder="请输入" />
+                  <span style="color: red;margin: 0 2px;font-size: 14px;" v-if="record.origSalePriceFlag == 1">原</span>
+                  <span v-else>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
+                </div>
+              </template>
+              <!-- 销售数量 -->
+              <template slot="nums" slot-scope="text, record">
+                <div @dblclick.stop>
+                  <a-input-number
+                    size="small"
+                    v-model="record.salesNums"
+                    :precision="0"
+                    :min="0"
+                    :max="999999"
+                    style="width: 100%;"
+                    placeholder="请输入" />
+                </div>
+              </template>
+              <!-- 操作 -->
+              <template slot="action" slot-scope="text, record">
+                <a-button
+                  size="small"
+                  type="link"
+                  class="button-primary"
+                  @click.stop="handleAdd(record)"
+                  v-if="record.includeFlag != 1"
+                  id="productInfoList-edit-btn">添加</a-button>
+                <span style="color:#999;" v-else>已添加</span>
+                <a-button
+                  size="small"
+                  type="link"
+                  class="button-primary"
+                  @click.stop="handleDetail(record)"
+                  id="productInfoList-detail-btn"
+                  style="margin-left: 5px;">销售记录</a-button>
+              </template>
+            </s-table>
+          </div>
+        </a-tab-pane>
+        <a-tab-pane :key="2" tab="全部货架产品">
+          <!-- 搜索条件 -->
+          <div class="table-page-search-wrapper">
+            <a-form-model
+              ref="ruleForm1"
+              class="form-model-con"
+              layout="inline"
+              :model="queryParam1"
+              @keyup.enter.native="$refs.table1.refresh(true)" >
+              <a-row :gutter="15">
+                <a-col :md="6" :sm="24">
+                  <a-form-model-item label="产品编码">
+                    <a-input id="chooseShelf-code1" v-model.trim="queryParam1.productCode" allowClear placeholder="请输入产品编码"/>
+                  </a-form-model-item>
+                </a-col>
+                <a-col :md="6" :sm="24">
+                  <a-form-model-item label="产品名称">
+                    <a-input id="chooseShelf-name1" v-model.trim="queryParam1.productName" allowClear placeholder="请输入产品名称"/>
+                  </a-form-model-item>
+                </a-col>
+                <a-col :md="6" :sm="24">
+                  <a-form-model-item label="产品分类">
+                    <ProductType id="chooseShelf-productType1" :isDealer="true" @change="changeProductType1" v-model="productType1"></ProductType>
+                  </a-form-model-item>
+                </a-col>
+                <a-col :md="6" :sm="12" style="margin-bottom: 10px;">
+                  <a-button type="primary" @click="$refs.table1.refresh(true)" id="chooseShelf-refresh">查询</a-button>
+                  <a-button style="margin-left: 5px" @click="resetSearchForm1" id="chooseShelf-reset">重置</a-button>
+                </a-col>
+              </a-row>
+            </a-form-model>
+          </div>
+          <div class="chooseShelf-modal-table">
+            <!-- 列表 -->
+            <s-table
+              class="sTable"
+              ref="table1"
+              size="small"
+              :rowKey="(record) => record.id"
+              :columns="columns1"
+              :data="loadData1"
+              :style="{ height: '500px' }"
+              :scroll="{ y: 450 }"
+              :showPagination="false"
+              bordered>
+            </s-table>
+          </div>
+        </a-tab-pane>
+      </a-tabs>
+    </a-spin>
+    <!-- 销售记录 -->
+    <product-salesRecord-modal ref="salseRecord" :openModal="showRecord" @close="showRecord=false" />
+  </a-modal>
+</template>
+
+<script>
+import { commonMixin } from '@/utils/mixin'
+import { STable } from '@/components'
+import ProductType from '../../common/productType.js'
+import productSalesRecordModal from './productSalesRecordModal.vue'
+import { queryWaitReplenish, queryShelfProduct } from '@/api/shelfReplenish'
+export default {
+  name: 'OutinDetailModal',
+  components: { STable, ProductType, productSalesRecordModal },
+  mixins: [commonMixin],
+  props: {
+    openModal: {
+      //  弹框显示状态
+      type: Boolean,
+      default: false
+    },
+    baseData: {
+      type: Object,
+      default: function () {
+        return null
+      }
+    }
+  },
+  data () {
+    return {
+      spinning: false,
+      advanced: false,
+      showRecord: false,
+      isShow: this.openModal, //  是否打开弹框
+      options: [
+        { label: '库存充足', value: 'stockEnough' },
+        { label: '部分缺货', value: 'portionStockout' },
+        { label: '全部缺货', value: 'allStockout' }
+      ],
+      curTab: 1,
+      productType: [],
+      queryParam: {
+        productCode: '', //  产品编码
+        productName: '', //  产品名称
+        productTypeSn1: '', //  产品一级分类
+        productTypeSn2: '', //  产品二级分类
+        productTypeSn3: '', //  产品三级分类
+        stockStateList: []
+      },
+      // 加载数据方法 必须为 Promise 对象
+      loadData: parameter => {
+        this.spinning = true
+        this.queryParam.shelfSn = this.baseData.shelfSn
+        this.queryParam.customerSn = this.baseData.customerSn
+        this.queryParam.salePriceType = this.baseData.salePriceType
+        this.queryParam.salesBillSn = this.baseData.salesBillSn
+
+        return queryWaitReplenish(Object.assign(parameter, this.queryParam)).then(res => {
+          let data
+          if (res.status == 200) {
+            data = res.data
+            const no = 0
+            for (var i = 0; i < data.length; i++) {
+              data[i] = data[i].shelfProductApi
+              data[i].no = no + i + 1
+              data[i].salesNums = data[i].replenishBillWaitQty
+              data[i].putCost = data[i].cost
+            }
+          }
+          this.spinning = false
+          return data
+        })
+      },
+      rowSelectionInfo: null,
+      // -------- 全部产品 --------
+      productType1: [],
+      queryParam1: {
+        productCode: '', //  产品编码
+        productName: '', //  产品名称
+        productTypeSn1: '', //  产品一级分类
+        productTypeSn2: '', //  产品二级分类
+        productTypeSn3: '' //  产品三级分类
+      },
+      // 加载数据方法 必须为 Promise 对象
+      loadData1: parameter => {
+        this.spinning = true
+        this.queryParam1.shelfSn = this.baseData.shelfSn
+        this.queryParam1.customerSn = this.baseData.customerSn
+        this.queryParam1.salePriceType = this.baseData.salePriceType
+        this.queryParam1.salesBillSn = this.baseData.salesBillSn
+        return queryShelfProduct(Object.assign(parameter, this.queryParam1)).then(res => {
+          let data
+          if (res.status == 200) {
+            data = res.data
+            const no = 0
+            for (var i = 0; i < data.length; i++) {
+              data[i].no = no + i + 1
+            }
+          }
+          this.spinning = false
+          return data
+        })
+      }
+    }
+  },
+  computed: {
+    mtitle () {
+      return '货架产品' + (this.baseData && this.baseData.shelfName ? this.baseData.shelfName : '')
+    },
+    selectTotal () {
+      return this.rowSelectionInfo && this.rowSelectionInfo.selectedRows.length
+    },
+    columns () {
+      const arr = [
+        { title: '序号', dataIndex: 'no', width: '4%', align: 'center' },
+        { title: '货位号', dataIndex: 'shelfPlaceCode', width: '5%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '产品编码', dataIndex: 'productCode', width: '6%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '产品名称', dataIndex: 'productName', width: '15%', align: 'center', customRender: function (text) { return text || '--' }, ellipsis: true },
+        { title: '最大库容', dataIndex: 'maxQty', width: '6%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
+        { title: '货架库存', dataIndex: 'qty', width: '6%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
+        { title: '补货在途', dataIndex: 'replenishBillQty', width: '6%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
+        { title: '调回在途', dataIndex: 'recallBillQty', width: '6%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
+        { title: '待补货数量', dataIndex: 'replenishBillWaitQty', width: '8%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
+        { title: '门店库存数量', dataIndex: 'qplsStockQty', width: '8%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
+        { title: '单位', dataIndex: 'productUnit', width: '4%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '售价', dataIndex: 'price', scopedSlots: { customRender: 'salePrice' }, width: '8%', align: 'center' },
+        { title: '销售数量', dataIndex: 'salesNums', scopedSlots: { customRender: 'nums' }, width: '8%', align: 'center' },
+        { title: '操作', dataIndex: 'action', scopedSlots: { customRender: 'action' }, width: '10%', align: 'center' }
+      ]
+      return arr
+    },
+    columns1 () {
+      const arr = [
+        { title: '序号', dataIndex: 'no', width: '4%', align: 'center' },
+        { title: '货位号', dataIndex: 'shelfPlaceCode', width: '5%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '产品编码', dataIndex: 'productCode', width: '16%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '产品名称', dataIndex: 'productName', width: '25%', align: 'center', customRender: function (text) { return text || '--' }, ellipsis: true },
+        { title: '最大库容', dataIndex: 'maxQty', width: '10%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
+        { title: '货架库存', dataIndex: 'qty', width: '10%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
+        { title: '补货在途', dataIndex: 'replenishBillQty', width: '10%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
+        { title: '调回在途', dataIndex: 'recallBillQty', width: '10%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
+        { title: '单位', dataIndex: 'productUnit', width: '10%', align: 'center', customRender: function (text) { return text || '--' } }
+      ]
+      return arr
+    }
+  },
+  methods: {
+    cansel () {
+      this.isShow = false
+    },
+    // 销售记录
+    handleDetail (row) {
+      this.showRecord = true
+      this.$refs.salseRecord.getDetail(this.baseData.customerSn, row.productSn, row)
+    },
+    // 表格选中项
+    rowSelectionFun (obj) {
+      this.rowSelectionInfo = obj || null
+    },
+    //  产品分类  change
+    changeProductType (val, opt) {
+      this.queryParam.productTypeSn1 = val[0] ? val[0] : ''
+      this.queryParam.productTypeSn2 = val[1] ? val[1] : ''
+      this.queryParam.productTypeSn3 = val[2] ? val[2] : ''
+    },
+    // 添加
+    handleAdd (row) {
+      const clist = this.rowSelectionInfo && this.rowSelectionInfo.selectedRows || []
+      const blist = this.rowSelectionInfo && this.rowSelectionInfo.selectedRowKeys || []
+      const i = clist.findIndex(item => item.id == row.id)
+      const k = blist.findIndex(item => item == row.id)
+      console.log(i, k)
+      if (i >= 0) {
+        clist.splice(i, 1)
+      }
+      if (k >= 0) {
+        blist.splice(k, 1)
+      }
+      this.$emit('add', row)
+    },
+    // 批量添加
+    handlePlAdd () {
+      if (this.selectTotal) {
+        this.$emit('plAdd', this.rowSelectionInfo && this.rowSelectionInfo.selectedRows || [])
+      } else {
+        this.$message.info('请选择产品')
+      }
+    },
+    resetSearchForm () {
+      this.queryParam.productCode = ''
+      this.queryParam.productName = ''
+      this.queryParam.productTypeSn1 = ''
+      this.queryParam.productTypeSn2 = ''
+      this.queryParam.productTypeSn3 = ''
+      this.productType = []
+      this.queryParam.stockStateList = []
+      this.$refs.ruleForm.resetFields()
+      this.$refs.table.clearSelected()
+      this.$refs.table.refresh(true)
+    },
+    reload () {
+      // this.$refs.table.clearSelected()
+      this.$refs.table.refresh()
+    },
+    // ---------- 全部产品----------
+    //  产品分类  change
+    changeProductType1 (val, opt) {
+      this.queryParam1.productTypeSn1 = val[0] ? val[0] : ''
+      this.queryParam1.productTypeSn2 = val[1] ? val[1] : ''
+      this.queryParam1.productTypeSn3 = val[2] ? val[2] : ''
+    },
+    resetSearchForm1 () {
+      this.queryParam1.productCode = ''
+      this.queryParam1.productName = ''
+      this.queryParam1.productTypeSn1 = ''
+      this.queryParam1.productTypeSn2 = ''
+      this.queryParam1.productTypeSn3 = ''
+      this.productType1 = []
+      this.$refs.ruleForm1.resetFields()
+      this.$refs.table1.refresh(true)
+    }
+  },
+  watch: {
+    //  父页面传过来的弹框状态
+    openModal (newValue, oldValue) {
+      this.isShow = newValue
+    },
+    //  重定义的弹框状态
+    isShow (newValue, oldValue) {
+      if (!newValue) {
+        this.$emit('close')
+      } else {
+        this.$nextTick(() => {
+          this.curTab = 1
+        })
+      }
+    }
+  }
+}
+</script>
+
+<style lang="less">
+.chooseShelf-modal {
+	.ant-modal-body {
+		padding: 0;
+    .chooseShelf-modal-table{
+      padding: 0 20px 10px;
+      .table-operator{
+        padding:0 10px 10px 0;
+        display:flex;
+        justify-content: space-between;
+        align-items: center;
+      }
+    }
+    .table-page-search-wrapper{
+      padding: 5px 20px 0;
+    }
+	}
+}
+</style>

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

@@ -0,0 +1,313 @@
+<template>
+  <div v-if="showPage" class="salesDetail-wrap">
+    <a-spin :spinning="spinning" tip="Loading...">
+      <a-page-header :ghost="false" :backIcon="false" class="salesDetail-cont" :style="{ padding: !outBizSn ? '16px 24px' : '0px 24px' }">
+        <template slot="subTitle" v-if="!outBizSn">
+          <a href="javascript:;" @click="handleBack"><a-icon type="left"></a-icon> 返回列表</a>
+          <a-button
+            v-if="(detailData&&detailData.billStatus !== 'CANCEL' && detailData.billStatus !== 'FINISH' && detailData.billStatus != 'WAIT_OUT_WAREHOUSE')&&$hasPermissions('B_salesEdit')"
+            type="primary"
+            size="small"
+            style="background-color: #1890ff;margin-left: 20px;border: #1890ff;"
+            id="salesDetail-edit-btn"
+            @click.stop="handleEdit">编辑</a-button>
+        </template>
+        <template slot="extra" v-if="outBizSn ? $hasPermissions('B_outboundOrderDetail') : $hasPermissions('B_salesPrint')">
+          <a-checkbox v-model="printAllName" :checked="printAllName" id="salesQuery-printAllName">打印完整产品名称</a-checkbox>
+          <a-checkbox v-model="printOrgCode" :checked="printOrgCode" id="salesQuery-printOrgCode">打印原厂编码</a-checkbox>
+          <Print :disabled="localDataSource.length==0" @handlePrint="handlePrint"></Print>
+        </template>
+      </a-page-header>
+      <!-- 基础信息 -->
+      <a-card size="small" :bordered="false" class="salesDetail-cont">
+        <a-collapse :activeKey="['1']">
+          <a-collapse-panel key="1" header="基础信息">
+            <a-descriptions size="small" :column="3">
+              <a-descriptions-item label="客户名称">{{ detailData&&detailData.buyerNameCurrent?detailData.buyerName?detailData.buyerName==detailData.buyerNameCurrent?detailData.buyerNameCurrent:detailData.buyerNameCurrent+'('+detailData.buyerName+')':detailData.buyerNameCurrent:'--' }}</a-descriptions-item>
+              <a-descriptions-item label="客户地址" :span="2">
+                <div v-if="detailData&&(detailData.shippingAddressProvinceName || detailData.shippingAddressCityName || detailData.shippingAddressCountyName || detailData.shippingAddress)">
+                  {{ detailData&&detailData.shippingAddressProvinceName || '' }}
+                  {{ detailData&&detailData.shippingAddressCityName || '' }}
+                  {{ detailData&&detailData.shippingAddressCountyName || '' }}
+                  {{ detailData&&detailData.shippingAddress || '' }}
+                </div>
+                <span v-else>--</span>
+              </a-descriptions-item>
+              <a-descriptions-item label="收款方式">{{ detailData&&detailData.settleStyleSnDictValue || '--' }}</a-descriptions-item>
+              <a-descriptions-item label="联系电话">{{ detailData&&detailData.consigneeTel || '--' }}</a-descriptions-item>
+              <a-descriptions-item label="备注">{{ detailData&&detailData.remarks || '--' }}</a-descriptions-item>
+              <a-descriptions-item label="销售单号">{{ detailData&&detailData.salesBillNo || '--' }}</a-descriptions-item>
+              <a-descriptions-item label="制单人">{{ detailData&&detailData.operatorName || '--' }}</a-descriptions-item>
+              <a-descriptions-item label="业务员">{{ detailData&&detailData.salesManName || '--' }}</a-descriptions-item>
+              <a-descriptions-item label="来源">{{ detailData&&detailData.sourceTypeDictValue || '--' }}</a-descriptions-item>
+              <a-descriptions-item label="下级采购单号" v-if="detailData&&detailData.sourceType=='PURCHASE'">{{ detailData&&detailData.purchaseBillNo || '--' }}</a-descriptions-item>
+              <a-descriptions-item label="业务状态">{{ detailData&&detailData.billStatusDictValue || '--' }}</a-descriptions-item>
+              <a-descriptions-item label="财务状态">{{ detailData&&detailData.financialStatusDictValue || '--' }}</a-descriptions-item>
+            </a-descriptions>
+          </a-collapse-panel>
+        </a-collapse>
+      </a-card>
+      <a-card size="small" :bordered="false" class="pages-wrap">
+        <!-- alert -->
+        <a-alert type="info" style="margin-bottom: 10px;">
+          <div style="display: flex;align-items: center;justify-content: space-between;" slot="message">
+            <div>
+              总款数:<strong>{{ detailData&&(detailData.totalCategory || detailData.totalCategory==0) ? detailData.totalCategory : '--' }}</strong>;
+              总数量:<strong>{{ detailData&&(detailData.totalQty || detailData.totalQty==0) ? detailData.totalQty : '--' }}</strong>;
+              总赠品数量:<strong>{{ detailData&&(detailData.giftQty || detailData.giftQty==0) ? detailData.giftQty : '--' }}</strong>;
+              急件总款数:<strong>{{ detailData&&(detailData.oosCategory || detailData.oosCategory==0) ? detailData.oosCategory : '--' }}</strong>;
+              急件总数量:<strong>{{ detailData&&(detailData.oosQty || detailData.oosQty==0) ? detailData.oosQty : '--' }}</strong>;<br/>
+              总售价:<strong>{{ detailData&&(detailData.totalAmount || detailData.totalAmount==0) ? toThousands(detailData.totalAmount) : '--' }}</strong>;
+              <template v-if="showCost">
+                总成本:<strong>{{ detailData&&(detailData.totalCost || detailData.totalCost==0) ? toThousands(detailData.totalCost) : '--' }}</strong>;
+                总毛利:<strong>{{ detailData&&(detailData.grossProfit || detailData.grossProfit==0) ? toThousands(detailData.grossProfit) : '--' }}</strong>;
+              </template>
+              折后总售价:<strong>{{ detailData&&(detailData.discountedAmount || detailData.discountedAmount==0) ? toThousands(detailData.discountedAmount) : '--' }}</strong>;
+              折扣:<strong>{{ detailData&&(detailData.discountRate || detailData.discountRate==0) ? detailData.discountRate+'%' : '--' }}</strong>;
+              折扣金额:<strong>{{ detailData&&(detailData.discountAmount || detailData.discountAmount==0) ? toThousands(detailData.discountAmount) : '--' }}</strong>;
+            </div>
+            <div>
+              <a-checkbox v-model="showCost" v-if="$hasPermissions('M_ShowAllCost')" id="salesQuery-cost">成本价</a-checkbox>
+            </div>
+          </div>
+        </a-alert>
+        <!-- 列表 -->
+        <s-table
+          class="sTable"
+          ref="table"
+          size="small"
+          :rowKey="(record) => record.id"
+          :columns="columns"
+          :data="loadData"
+          :defaultLoadData="false"
+          bordered>
+          <div slot="costTitle">
+            <a-tooltip placement="top">
+              <template slot="title">
+                系统中不同批次的产品,成本价可能不同,此值是按照实际出库批次的成本计算得到。
+              </template>
+              <span style="margin-right: 5px;">实际总成本</span> <a-icon type="question-circle" />
+            </a-tooltip>
+          </div>
+          <!-- 产品编码 -->
+          <template slot="productCode" slot-scope="text, record">
+            <div v-if="detailData">
+              <div v-if="isOwerEdit">
+                <a-badge count="急" v-if="record.oosFlag == 1">
+                  <div style="padding-right: 15px;">{{ text }}</div>
+                </a-badge>
+                <span v-else>{{ text }}</span>
+              </div>
+              <div v-else>
+                <a-badge count="急" v-if="isAudit&&record.oosFlag == 1">
+                  <div style="padding-right: 15px;">{{ text }}</div>
+                </a-badge>
+                <a-badge count="缺" v-else-if="!isAudit&&(!record.currentStockQty || record.currentStockQty < record.qty)">
+                  <div style="padding-right: 15px;">{{ text }}</div>
+                </a-badge>
+                <span v-else>{{ text }}</span>
+              </div>
+            </div>
+          </template>
+          <!-- 操作 -->
+          <template slot="action" slot-scope="text, record">
+            <a-button size="small" type="link" v-if="record.oosFlag == 0" class="button-primary" @click="handleViewDetail(record)">出库明细</a-button>
+            <span v-else>--</span>
+          </template>
+        </s-table>
+        <!-- 出入库明细 -->
+        <outInDetialModal ref="outInDetialModal" outBizType="SALES" :openModal="showOutInModal" @close="showOutInModal=false"></outInDetialModal>
+      </a-card>
+    </a-spin>
+  </div>
+</template>
+
+<script>
+import { commonMixin } from '@/utils/mixin'
+import { getOperationalPrecision } from '@/libs/tools.js'
+import { STable, VSelect } from '@/components'
+import { salesDetailBySn, salesDetailPrint, salesDetailExport } from '@/api/sales'
+import { salesDetailList } from '@/api/salesDetail'
+import outInDetialModal from '@/views/common/outInDetialModal.vue'
+import Print from '@/views/common/print.vue'
+import { hdPrint } from '@/libs/JGPrint'
+export default {
+  name: 'SalesDetail',
+  components: { STable, VSelect, Print, outInDetialModal },
+  mixins: [commonMixin],
+  props: {
+    outBizSn: { //  有值则为弹框,无值则为页面
+      type: [Number, String],
+      default: ''
+    }
+  },
+  data () {
+    return {
+      showPage: false,
+      spinning: false,
+      disabled: false,
+      showCost: false,
+      printOrgCode: false, // 打印原创编码
+      printAllName: false, // 打印全部名称
+      showOutInModal: false,
+      // 加载数据方法 必须为 Promise 对象
+      loadData: parameter => {
+        this.disabled = true
+        return salesDetailList(Object.assign(parameter, { salesBillSn: this.outBizSn || this.$route.params.sn })).then(res => {
+          let data
+          if (res.status == 200) {
+            data = res.data
+            const no = (data.pageNo - 1) * data.pageSize
+            for (var i = 0; i < data.list.length; i++) {
+              data.list[i].no = no + i + 1
+              const productCode = (data.list[i].productEntity && data.list[i].productEntity.code) || (data.list[i].dealerProductEntity && data.list[i].dealerProductEntity.code)
+              const productName = (data.list[i].productEntity && data.list[i].productEntity.name) || (data.list[i].dealerProductEntity && data.list[i].dealerProductEntity.name)
+              const productOrigCode = (data.list[i].productEntity && data.list[i].productEntity.origCode) || (data.list[i].dealerProductEntity && data.list[i].dealerProductEntity.origCode) || '--'
+              const productOrigUnit = (data.list[i].productEntity && data.list[i].productEntity.unit) || (data.list[i].dealerProductEntity && data.list[i].dealerProductEntity.unit)
+              data.list[i].productCode = productCode || '--'
+              data.list[i].productName = productName || '--'
+              data.list[i].productOrigCode = productOrigCode || '--'
+              data.list[i].productOrigUnit = productOrigUnit || '--'
+              data.list[i].warehouseName = data.list[i].warehouseEntity && data.list[i].warehouseEntity.name || '--'
+              data.list[i].warehouseLocationName = data.list[i].warehouseLocationEntity && data.list[i].warehouseLocationEntity.name || '--'
+              // 售价小计  由于数据库内小数位数为4位,页面则需显示2位。因此会做小数运算精度处理
+              data.list[i].salePriceSubtotal = getOperationalPrecision(data.list[i].price, data.list[i].qty)
+            }
+            this.localDataSource = data.list
+            this.disabled = false
+          }
+          return data
+        })
+      },
+      localDataSource: [],
+      detailData: null //  详情数据
+    }
+  },
+  computed: {
+    // 是否自建单据
+    isOwerEdit () {
+      return this.detailData && this.detailData.sourceType == 'SALES'
+    },
+    // 是否审核通过
+    isAudit () {
+      return this.detailData ? (this.detailData.billStatus == 'WAIT_OUT_WAREHOUSE' || this.detailData.billStatus == 'FINISH') : false
+    },
+    columns () {
+      const _this = this
+      const arr = [
+        { title: '序号', dataIndex: 'no', width: '4%', align: 'center' },
+        { title: '产品编码', dataIndex: 'dealerProductEntity.code', width: '11%', scopedSlots: { customRender: 'productCode' }, align: 'center' },
+        { title: '产品名称', dataIndex: 'productName', width: '11%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '原厂编码', dataIndex: 'productOrigCode', width: '9%', align: 'center', customRender: function (text) { return text && text != ' ' ? text : '--' } },
+        { title: '售价', dataIndex: 'price', width: '5%', align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } },
+        { title: '折后售价', dataIndex: 'discountedPrice', width: '6%', align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } },
+        { title: '销售数量', dataIndex: 'qty', width: '6%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
+        { title: '单位', dataIndex: 'productOrigUnit', width: '4%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '售价小计', dataIndex: 'totalAmount', width: '6%', align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } },
+        { title: '折后小计', dataIndex: 'discountedAmount', width: '6%', align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } },
+        { title: '折扣金额', dataIndex: 'discountAmount', width: '6%', align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } },
+        // { title: '仓库', dataIndex: 'warehouseName', width: '7%', align: 'center', customRender: function (text) { return text || '--' } },
+        // { title: '仓位', dataIndex: 'warehouseLocationName', width: '7%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '是否急件', dataIndex: 'oosFlagDictValue', width: '6%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '操作', scopedSlots: { customRender: 'action' }, width: '7%', align: 'center' }
+      ]
+      // 实际总成本
+      if (this.showCost) {
+        arr.splice(11, 0, { slots: { title: 'costTitle' }, dataIndex: 'totalCost', width: '6%', align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } })
+      } else {
+        arr.splice(11, 1)
+      }
+      // 下级创建,不显示仓库仓位
+      if (!this.isOwerEdit) {
+        arr.splice(this.showCost ? 12 : 11, 0, { title: '库存数量', dataIndex: 'currentStockQty', width: '6%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } })
+      } else {
+        arr.splice(this.showCost ? 12 : 11, 0, { title: '仓库', dataIndex: 'warehouseName', width: '7%', align: 'center', customRender: function (text) { return text || '--' } })
+        arr.splice(this.showCost ? 13 : 12, 0, { title: '仓位', dataIndex: 'warehouseLocationName', width: '7%', align: 'center', customRender: function (text) { return text || '--' } })
+      }
+      return arr
+    }
+  },
+  methods: {
+    // 打印预览/快捷打印
+    handlePrint (type, printerType) {
+      const _this = this
+      _this.spinning = true
+      let url = salesDetailPrint
+      const params = { sn: this.outBizSn || this.$route.params.sn, printOrgCode: this.printOrgCode ? 1 : 0, printAllName: this.printAllName ? 1 : 0 }
+      if (type == 'export') { //  导出
+        url = salesDetailExport
+      }
+      // 打印或导出
+      hdPrint(printerType, type, url, params, '销售单', function () {
+        _this.spinning = false
+      })
+    },
+    //  返回
+    handleBack () {
+      this.$router.push({ name: 'salesNewList' })
+    },
+    // 编辑
+    handleEdit () {
+      const row = this.detailData
+      this.$router.push({ name: 'salesNewEdit', params: { id: row.id, sn: row.salesBillSn, priceType: row.priceType } })
+    },
+    //  详情
+    getDetail () {
+      salesDetailBySn({ salesBillSn: this.outBizSn || this.$route.params.sn }).then(res => {
+        if (res.status == 200) {
+          this.detailData = res.data
+        } else {
+          this.detailData = null
+        }
+      })
+    },
+    // 出入库明细
+    handleViewDetail (row) {
+      this.showOutInModal = true
+      this.$refs.outInDetialModal.getData(row)
+    },
+    pageInit () {
+      const vm = this
+      vm.$nextTick(() => {
+        vm.spinning = false
+        vm.disabled = false
+        // 是否默认打印原厂编码
+        vm.printOrgCode = localStorage.getItem('printOrgCode-' + this.$store.state.user.info.orgId) == 'true'
+        vm.printAllName = localStorage.getItem('printAllName-' + this.$store.state.user.info.orgId) == 'true'
+        vm.$refs.table.refresh(true)
+        vm.getDetail()
+      })
+    }
+  },
+  watch: {
+    printOrgCode (newValue, oldValue) {
+      localStorage.setItem('printOrgCode-' + this.$store.state.user.info.orgId, newValue)
+    },
+    printAllName (newValue, oldValue) {
+      localStorage.setItem('printAllName-' + this.$store.state.user.info.orgId, newValue)
+    }
+  },
+  mounted () {
+    if (!this.$store.state.app.isNewTab || this.outBizSn) { // 页签刷新时调用
+      this.showPage = true
+      this.pageInit()
+    }
+  },
+  activated () {
+    this.showPage = true
+    this.pageInit()
+  },
+  beforeRouteEnter (to, from, next) {
+    next(vm => {
+    })
+  }
+}
+</script>
+
+<style lang="less">
+  .salesDetail-wrap{
+    .salesDetail-cont{
+      margin-bottom: 10px;
+    }
+  }
+</style>

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

@@ -0,0 +1,860 @@
+<template>
+  <div v-if="showPage" class="salesEdit-wrap">
+    <a-spin :spinning="spinning" tip="Loading...">
+      <a-page-header :ghost="false" :backIcon="false" @back="handleBack" >
+        <!-- 自定义的二级文字标题 -->
+        <template slot="subTitle">
+          <a id="salesEdit-back-btn" href="javascript:;" @click="handleBack"><a-icon type="left" /> 返回列表</a>
+          <a style="margin: 0 15px;color: #666;font-size: 18px;font-weight: 600;">单号:{{ detailData&&detailData.salesBillNo || '--' }}</a>
+          <span style="margin: 0 10px;color: #666;">客户名称:{{ detailData&&detailData.buyerName || '--' }}</span>
+          <a-button
+            id="salesEdit-edit-btn"
+            v-if="detailData&&detailData.salesTragetType != 'DEALER'"
+            size="small"
+            @click="handleEdit"
+            style="margin-left:10px"
+            key="0">编辑</a-button>
+        </template>
+        <!-- 操作区,位于 title 行的行尾 -->
+        <template slot="extra" v-if="$hasPermissions('B_salesPrint')">
+          <a-checkbox v-model="printAllName" :checked="printAllName" id="salesQuery-printAllName">打印完整产品名称</a-checkbox>
+          <a-checkbox v-model="printOrgCode" :checked="printOrgCode" id="salesQuery-printOrgCode">打印原厂编码</a-checkbox>
+          <Print :disabled="dataSource.length==0" @handlePrint="handlePrint"></Print>
+        </template>
+      </a-page-header>
+      <a-card size="small" :bordered="false" class="salesEdit-cont">
+        <!-- 查询配件列表 -->
+        <queryPart
+          ref="partQuery"
+          :newLoading="isInster"
+          @add="insterProduct"
+          @isCost="isCost"></queryPart>
+      </a-card>
+      <a-card size="small" :bordered="false" class="salesEdit-cont">
+        <!-- 总计 -->
+        <a-alert v-if="detailData" style="margin-bottom: 10px;" type="info">
+          <div slot="message" class="total-bar">
+            <div>
+              总售价:<strong>{{ detailData&&(detailData.totalAmount || detailData.totalAmount==0) ? toThousands(detailData.totalAmount) : '--' }}</strong>;
+              总款数:<strong>{{ detailData&&(detailData.totalCategory || detailData.totalCategory==0) ? detailData.totalCategory : '--' }}</strong>;
+              总数量:<strong>{{ detailData&&(detailData.totalQty || detailData.totalQty==0) ? detailData.totalQty : '--' }}</strong>;
+              赠品总数量:<strong>{{ detailData&&(detailData.giftQty || detailData.giftQty==0) ? detailData.giftQty : '--' }}</strong>;
+              <span v-if="isCosts">
+                总成本价:<strong>{{ detailData&&(detailData.totalCost || detailData.totalCost==0) ? toThousands(detailData.totalCost) : '--' }}</strong>;
+                毛利:<strong>{{ detailData&&(detailData.grossProfit || detailData.grossProfit==0) ? toThousands(detailData.grossProfit) : '--' }}</strong>;
+              </span>
+            </div>
+            <div>
+              <div>
+                折扣金额:
+                <a-input-number
+                  id="discount"
+                  size="small"
+                  v-model.trim="detailData.discountAmount"
+                  :min="0"
+                  :precision="2"
+                  :max="999999"/>
+                <a-button size="small" type="primary" class="button-primary" @click="salesDiscount">打折</a-button>
+              </div>
+              <div>
+                折扣:<strong>{{ detailData&&(detailData.discountRate || detailData.discountRate==0) ? detailData.discountRate+'%' : '--' }}</strong>;
+                折后总售价:<strong>{{ detailData&&(detailData.discountedAmount || detailData.discountedAmount==0) ? toThousands(detailData.discountedAmount) : '--' }}</strong>;
+              </div>
+            </div>
+          </div>
+        </a-alert>
+        <!-- 搜索条件 -->
+        <div class="table-page-search-wrapper">
+          <a-row :gutter="15">
+            <a-col :md="24" :lg="12">
+              <a-form-model :model="productForm" ref="ruleForm" 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.trim="productForm.productCode" allowClear placeholder="输入产品编码" />
+                    </a-form-model-item>
+                  </a-col>
+                  <a-col :md="8" :sm="24">
+                    <a-form-model-item label="产品名称">
+                      <a-input v-model.trim="productForm.productName" 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="salesEdit-refresh">查询</a-button>
+                      <a-button style="margin-left: 5px" @click="resetForm" id="salesEdit-reset">重置</a-button>
+                    </a-form-model-item>
+                  </a-col>
+                </a-row>
+              </a-form-model>
+            </a-col>
+            <a-col :md="24" :lg="12">
+              <div style="float:right;overflow: hidden;margin-bottom:10px;">
+                <a-checkbox :value="0" :checked="tbForm.indexOf('AUDIT')>=0" @change="(e)=>{tbFormChange(e,0)}" id="salesQuery-tbsh">同步审核</a-checkbox>
+                <a-checkbox :value="1" :checked="tbForm.indexOf('STOCK_OUT')>=0" @change="(e)=>{tbFormChange(e,1)}" id="salesQuery-tbck">同步出库</a-checkbox>
+                <a-checkbox :value="2" :checked="tbForm.indexOf('SETTLE')>=0" @change="(e)=>{tbFormChange(e,2)}" id="salesQuery-tbsk">同步收款</a-checkbox>
+                <a-button
+                  style="padding: 0 25px;"
+                  type="primary"
+                  :disabled="spinning"
+                  class="button-primary"
+                  @click="enableFundAccount && tbForm.length == 3 ? handleSettleAcountPay(null,0) : handleSubmit({})"
+                  id="productInfoList-handleSubmit">提交</a-button>
+                <a-button
+                  type="default"
+                  @click="openGuideModal=true"
+                  style="margin-right:5px;"
+                  id="salesEdit-import">导入产品</a-button>
+                <a-button
+                  type="default"
+                  v-if="shelfInfo&&shelfInfo.state=='ENABLE'"
+                  @click="showShelfModal=true"
+                  style="margin-right:5px;"
+                  id="salesEdit-shelf">货架产品</a-button>
+                <a-button
+                  type="primary"
+                  ghost
+                  @click="delSalerOrder"
+                  :loading="delLoading"
+                  id="salesEdit-del-all">清空列表</a-button>
+              </div>
+            </a-col>
+          </a-row>
+        </div>
+        <!-- 已选配件列表 -->
+        <s-table
+          class="sTable"
+          ref="table"
+          size="small"
+          :rowKey="(record) => record.id"
+          :columns="columns"
+          :data="loadData"
+          :defaultLoadData="false"
+          :pageSize="5"
+          :rowClassName="(record, index) => record.cost > record.price ? 'redBg-row':''"
+          bordered>
+          <div slot="costTitle">
+            <a-tooltip placement="top">
+              <template slot="title">
+                系统中不同批次的产品,成本价可能不同,此值是按照实际出库批次的成本计算得到。
+              </template>
+              <span style="margin-right: 5px;">实际总成本</span> <a-icon type="question-circle" />
+            </a-tooltip>
+          </div>
+          <!-- 产品名称 -->
+          <template slot="productName" slot-scope="text, record">
+            <a-tag color="blue" v-if="record.shelfPlaceCode">{{ record.shelfPlaceCode }}</a-tag>
+            <span>{{ text }}</span>
+          </template>
+          <!-- 产品编码 -->
+          <template slot="productCode" slot-scope="text, record">
+            <div v-if="detailData">
+              <div v-if="isOwerEdit">
+                <a-badge count="急" v-if="record.oosFlag == 1">
+                  <div style="padding-right: 15px;">{{ text }}</div>
+                </a-badge>
+                <span v-else>{{ text }}</span>
+              </div>
+              <div v-else>
+                <a-badge count="急" v-if="isAudit&&record.oosFlag == 1">
+                  <div style="padding-right: 15px;">{{ text }}</div>
+                </a-badge>
+                <a-badge count="缺" v-else-if="!isAudit&&(!record.currentStockQty || record.currentStockQty < record.qty)">
+                  <div style="padding-right: 15px;">{{ text }}</div>
+                </a-badge>
+                <span v-else>{{ text }}</span>
+              </div>
+            </div>
+          </template>
+          <!-- 售价 -->
+          <template slot="price" slot-scope="text, record">
+            <a-input-number
+              id="salesEdit-price"
+              size="small"
+              v-model="record.price"
+              :precision="2"
+              :min="0"
+              :max="999999"
+              placeholder="请输入"
+              @blur="e => priceBlur(e.target.value, record)"
+              style="width: 100%;" />
+          </template>
+          <!-- 销售数量 -->
+          <template slot="salesNums" slot-scope="text, record">
+            <a-input-number
+              id="salesEdit-salesNums"
+              size="small"
+              v-model="record.qty"
+              :precision="0"
+              :min="1"
+              :max="999999"
+              placeholder="请输入"
+              @blur="e => qtyBlur(e.target.value, record)"
+              style="width: 100%;" />
+          </template>
+          <!-- 操作 -->
+          <template slot="action" slot-scope="text, record">
+            <a-button size="small" v-if="record.oosFlag == 0" type="link" class="button-primary" @click="handleViewDetail(record)">出库明细</a-button>
+            <a-button
+              size="small"
+              type="link"
+              :loading="delLoading"
+              class="button-error"
+              @click="handleDel(record)"
+              id="productInfoList-Del">删除</a-button>
+          </template>
+        </s-table>
+      </a-card>
+    </a-spin>
+    <!-- <div class="affix-cont"></div> -->
+    <!-- 选择客户弹框 -->
+    <choose-custom-modal ref="custModal" :show="openModal" @updateData="updateData" @cancel="openModal=false" />
+    <!-- 导入产品 -->
+    <importGuideModal :openModal="openGuideModal" :params="{salesBillSn: $route.params.sn, salesBillNo:detailData?detailData.salesBillNo:''}" @close="openGuideModal=false" @ok="hanldeImprotOk" />
+    <!-- 收付款弹框 -->
+    <settleModal ref="settleModal" @ok="settleAcountPay" :openModal="openSettleModal" @close="openSettleModal=false"></settleModal>
+    <!-- 出库明细 -->
+    <outInDetialModal ref="outInDetialModal" outBizType="SALES" :openModal="showOutInModal" @close="showOutInModal=false"></outInDetialModal>
+    <!-- 选择货架产品 -->
+    <chooseShelfProduct
+      v-if="showShelfModal"
+      ref="chooseShelfProduct"
+      @add="insterProduct"
+      @plAdd="plInsterProduct"
+      :baseData="shelfInfo"
+      :openModal="showShelfModal"
+      @close="showShelfModal=false"></chooseShelfProduct>
+  </div>
+</template>
+<script>
+import { commonMixin } from '@/utils/mixin'
+import { mapActions } from 'vuex'
+import { STable, VSelect } from '@/components'
+import queryPart from './queryPart.vue'
+import chooseCustomModal from './chooseCustomModal.vue'
+import importGuideModal from './importGuideModal.vue'
+import settleModal from '@/views/financialManagement/settleModal/settleModal.vue'
+import { stockByProductSn } from '@/api/stock'
+import { queryByCustomerSn } from '@/api/shelf'
+import { salesDetail, salesWriteSubmit, salesWriteDiscount, salesDetailPrint, salesDetailExport, salesDel } from '@/api/sales'
+import { salesDetailList, salesDetailInsert, salesDetailInsertBatch, salesDetailUpdatePrice, salesDetailUpdateQty, salesDetailDel, salesDetailDelAll, salesDetailInsertImport } from '@/api/salesDetail'
+import outInDetialModal from '@/views/common/outInDetialModal.vue'
+import chooseShelfProduct from './chooseShelfProduct.vue'
+import Print from '@/views/common/print.vue'
+import { hdPrint } from '@/libs/JGPrint'
+export default {
+  name: 'SalesEdit',
+  components: { STable, VSelect, queryPart, chooseCustomModal, Print, importGuideModal, settleModal, outInDetialModal, chooseShelfProduct },
+  mixins: [commonMixin],
+  data () {
+    return {
+      showOutInModal: false, // 出入库明细
+      showPage: false,
+      spinning: false,
+      orderId: null, // 销售单id
+      salesBillSn: null, // 销售单sn
+      disabled: false, //  查询、重置按钮是否可操作
+      isInster: false, // 是否正在添加产品
+      openModal: false, // 客户弹框
+      openGuideModal: false, // 导入产品弹框
+      openSettleModal: false, // 打开收款弹框
+      enableFundAccount: false, // 是否开启资金账户管理
+      showShelfModal: false, // 货架产品弹框
+      delLoading: false,
+      detailData: { discountAmount: 0, id: null, salesBillSn: '' }, // 订单基础数据
+      dataSource: [],
+      productForm: {
+        productName: '',
+        productCode: '',
+        orderBy: 'sales_bill_detail.CREATE_DATE desc'
+      },
+      tbForm: [], // 同步操作
+      printOrgCode: false, // 打印原创编码
+      printAllName: false, // 打印全部名称
+      // 加载数据方法 必须为 Promise 对象
+      loadData: parameter => {
+        this.disabled = true
+        this.productForm.salesBillSn = this.$route.params.sn
+        return salesDetailList(Object.assign(parameter, this.productForm)).then(res => {
+          let data
+          if (res.status == 200) {
+            data = res.data
+            const no = (data.pageNo - 1) * data.pageSize
+            for (var i = 0; i < data.list.length; i++) {
+              data.list[i].no = no + i + 1
+              data.list[i].qtyBackups = data.list[i].qty
+              data.list[i].priceBackups = data.list[i].price
+            }
+            this.disabled = false
+            this.dataSource = data.list || []
+          }
+          return data
+        })
+      },
+      printerType: 'NEEDLE', //  打印机类型
+      isCosts: false, // 是否显示成本价
+      shelfInfo: null // 是否有货架
+    }
+  },
+  computed: {
+    // 是否自建单据
+    isOwerEdit () {
+      return this.detailData && this.detailData.sourceType == 'SALES'
+    },
+    // 是否审核通过
+    isAudit () {
+      return this.detailData && (this.detailData.billStatus == 'WAIT_OUT_WAREHOUSE' || this.detailData.billStatus == 'FINISH')
+    },
+    columns () {
+      const _this = this
+      const arr = [
+        { title: '序号', dataIndex: 'no', width: '4%', align: 'center' },
+        { title: '产品编码', dataIndex: 'dealerProductEntity.code', width: '13%', scopedSlots: { customRender: 'productCode' }, align: 'center' },
+        { title: '产品名称', dataIndex: 'dealerProductEntity.name', width: '13%', align: 'center', scopedSlots: { customRender: 'productName' }, ellipsis: true },
+        { title: '原厂编码', dataIndex: 'dealerProductEntity.origCode', width: '11%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '品牌', dataIndex: 'dealerProductEntity.productBrandName', width: '8%', align: 'center', sorter: true, customRender: function (text) { return text || '--' } },
+        // { title: '仓库', dataIndex: 'warehouseEntity.name', width: '8%', align: 'center', sorter: true, customRender: function (text) { return text || '--' } },
+        // { title: '仓位', dataIndex: 'warehouseLocationEntity.name', width: '8%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '售价', dataIndex: 'price', scopedSlots: { customRender: 'price' }, width: '7%', align: 'center' },
+        { title: '销售数量', scopedSlots: { customRender: 'salesNums' }, width: '7%', align: 'center' },
+        { title: '单位', dataIndex: 'dealerProductEntity.unit', width: '4%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '售价小计', dataIndex: 'totalAmount', width: '5%', align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } },
+        { title: '折后小计', dataIndex: 'discountedAmount', width: '5%', align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } },
+        { title: '操作', scopedSlots: { customRender: 'action' }, width: '7%', align: 'center' }
+      ]
+      // 下级创建,不显示仓库仓位
+      if (!this.isOwerEdit) {
+        arr.splice(7, 0, { title: '库存数量', dataIndex: 'currentStockQty', width: '6%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } })
+      } else {
+        arr.splice(5, 0, { title: '仓库', dataIndex: 'warehouseEntity.name', width: '8%', align: 'center', sorter: true, customRender: function (text) { return text || '--' } })
+        arr.splice(6, 0, { title: '仓位', dataIndex: 'warehouseLocationEntity.name', width: '8%', align: 'center', customRender: function (text) { return text || '--' } })
+      }
+      // 实际总成本
+      if (this.isCosts) {
+        arr.splice(!this.isOwerEdit ? 11 : 12, 0, { slots: { title: 'costTitle' }, dataIndex: 'totalCost', width: '8%', align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } })
+      }
+      return arr
+    }
+  },
+  methods: {
+    ...mapActions(['GetSettleAccountState']),
+    // 打印预览/快捷打印
+    handlePrint (type, printerType) {
+      const _this = this
+      _this.spinning = true
+      let url = salesDetailPrint
+      const params = { sn: this.outBizSn || this.$route.params.sn, printOrgCode: this.printOrgCode ? 1 : 0, printAllName: this.printAllName ? 1 : 0 }
+      if (type == 'export') { //  导出
+        url = salesDetailExport
+      }
+      // 打印或导出
+      hdPrint(printerType, type, url, params, '销售单', function () {
+        _this.spinning = false
+      })
+    },
+    tbFormChange (e, val) {
+      this.tbForm = []
+      const tbTypes = ['AUDIT', 'STOCK_OUT', 'SETTLE']
+      if (e.target.checked) {
+        for (let i = val; i >= 0; i--) {
+          this.tbForm.push(tbTypes[i])
+        }
+      } else {
+        this.tbForm = []
+      }
+    },
+    // 编辑客户信息
+    handleEdit () {
+      this.openModal = true
+      this.$refs.custModal.editCust(this.detailData)
+    },
+    // 更新产品列表
+    updateData (priceType) {
+      // 价格类型变更
+      if (priceType != this.$route.params.priceType) {
+        this.getOrderDetail(true)
+        this.$router.push({ name: 'salesNewEdit', params: { id: this.orderId, sn: this.salesBillSn, priceType: priceType } })
+      } else {
+        this.getOrderDetail(true)
+      }
+    },
+    // 非下级创建的单据,修改数量时校验库存
+    validStock (val, record) {
+      const _this = this
+      this.spinning = true
+      //  校验库存
+      stockByProductSn({ productSn: record.productSn }).then(res => {
+        if (res.status == 200) {
+          if (res.data && (!res.data.currentStockQty || val <= res.data.currentStockQty)) {
+            _this.changeQty(record)
+          } else {
+            this.$confirm({
+              title: '提示',
+              content: '库存不足,确认添加为急件吗?',
+              centered: true,
+              closable: true,
+              onOk () {
+                _this.changeQty(record)
+              },
+              onCancel () {
+                record.qty = record.qtyBackups
+                _this.spinning = false
+              }
+            })
+          }
+        } else {
+          this.spinning = false
+          record.qty = record.qtyBackups
+        }
+      })
+    },
+    // 修改已选产品数量
+    changeQty (record) {
+      salesDetailUpdateQty({
+        id: record.id,
+        salesBillSn: record.salesBillSn,
+        productSn: record.productSn,
+        salesBillDetailSn: record.salesBillDetailSn,
+        qty: record.qty,
+        price: record.price
+      }).then(res => {
+        this.resetSearchForm(false)
+        if (res.status == 200) {
+          this.$message.info(res.message)
+        }
+        this.spinning = false
+      })
+    },
+    // 已选产品 销售数量 input 输入框 blur
+    qtyBlur (val, record) {
+      this.dataSource = record || []
+      if (val && val != record.qtyBackups) {
+        // 自建的单据,修改数量时校验库存
+        if (this.isOwerEdit) {
+          this.validStock(val, record)
+        } else {
+          this.changeQty(record)
+        }
+      } else {
+        record.qty = record.qtyBackups
+      }
+    },
+    // 已选产品 售价 input 输入框 blur
+    priceBlur (val, record) {
+      this.dataSource = record || []
+      //  光标移出,值发生改变再调用编辑接口
+      if (val && val != record.priceBackups) {
+        this.spinning = true
+        salesDetailUpdatePrice({
+          id: record.id,
+          salesBillSn: record.salesBillSn,
+          productSn: record.productSn,
+          salesBillDetailSn: record.salesBillDetailSn,
+          qty: record.qty,
+          price: record.price
+        }).then(res => {
+          this.resetSearchForm(false)
+          if (res.status == 200) {
+            this.$message.info(res.message)
+            this.spinning = false
+          } else {
+            this.spinning = false
+          }
+        })
+      } else {
+        record.price = record.priceBackups
+      }
+    },
+    isCost (val) {
+      this.isCosts = val
+    },
+    //  重置
+    resetSearchForm (flag) {
+      if (flag) { this.$refs.partQuery.onlyList = true }
+      this.$refs.table.refresh(!!flag)
+      this.getOrderDetail(false)
+    },
+    // 重置列表
+    resetForm () {
+      this.productForm = {
+        productName: '',
+        productCode: '',
+        orderBy: 'sales_bill_detail.CREATE_DATE desc'
+      }
+      this.$refs.table.refresh()
+    },
+    //  返回
+    handleBack () {
+      this.$router.push({ name: 'salesNewList' })
+    },
+    // 打折
+    salesDiscount () {
+      this.spinning = true
+      salesWriteDiscount({
+        discountAmount: this.detailData.discountAmount || 0,
+        salesBillSn: this.detailData.salesBillSn,
+        id: this.detailData.id
+      }).then(res => {
+        if (res.status == 200) {
+          this.resetSearchForm(true)
+          this.spinning = false
+        } else {
+          this.spinning = false
+        }
+      })
+    },
+    // 删除销售单
+    delSalerOrder () {
+      const _this = this
+      this.$confirm({
+        title: '提示',
+        content: '确认要清空已选产品列表吗?',
+        centered: true,
+        closable: true,
+        onOk () {
+          _this.spinning = true
+          salesDel({ id: _this.orderId }).then(res => {
+            if (res.status == 200) {
+              _this.$message.success(res.message)
+              _this.handleBack()
+            }
+            _this.spinning = false
+          })
+        }
+      })
+    },
+    // 删除已选产品
+    delSalerDetailAll () {
+      const _this = this
+      this.$confirm({
+        title: '提示',
+        content: '确认要整单删除吗?',
+        centered: true,
+        closable: true,
+        onOk () {
+          _this.delLoading = true
+          _this.spinning = true
+          salesDetailDelAll({ salesBillSn: _this.detailData.salesBillSn }).then(res => {
+            if (res.status == 200) {
+              _this.resetSearchForm(true)
+              _this.productForm = {
+                productName: '',
+                productCode: '',
+                orderBy: 'sales_bill_detail.CREATE_DATE desc'
+              }
+            }
+            _this.$message.info(res.message)
+            _this.delLoading = false
+            _this.spinning = false
+          })
+        }
+      })
+    },
+    // 出入库明细
+    handleViewDetail (row) {
+      this.showOutInModal = true
+      this.$refs.outInDetialModal.getData(row)
+    },
+    // 删除产品
+    handleDel (row) {
+      const _this = this
+      this.$confirm({
+        title: '提示',
+        content: '确认要删除吗?',
+        centered: true,
+        closable: true,
+        onOk () {
+          _this.delLoading = true
+          _this.spinning = true
+          salesDetailDel({ id: row.id }).then(res => {
+            if (res.status == 200) {
+              _this.resetSearchForm(false)
+            }
+            _this.$message.info(res.message)
+            _this.delLoading = false
+            _this.spinning = false
+          })
+        }
+      })
+    },
+    // 添加产品
+    insterProduct (row) {
+      // 防止多次添加产品
+      if (this.isInster) { return }
+      const _this = this
+      // 判断是否已添加此产品
+      // if (this.dataSource && this.dataSource.length > 0) {
+      //   const hasRow = this.dataSource.find(item => item.productSn == row.productSn)
+      //   if (hasRow) {
+      //     this.$message.info('该产品已在当前销售单中存在!')
+      //     this.productForm = {
+      //       productName: '',
+      //       productCode: hasRow.dealerProductEntity && hasRow.dealerProductEntity.code || '',
+      //       orderBy: 'sales_bill_detail.CREATE_DATE desc'
+      //     }
+      //     this.$refs.table.refresh(true)
+      //   } else {
+      //     this.productForm = {
+      //       productName: '',
+      //       productCode: '',
+      //       orderBy: 'sales_bill_detail.CREATE_DATE desc'
+      //     }
+      //   }
+      // }
+      // 自建的单据显示库存不足时
+      if (row.currentQty < row.salesNums && this.isOwerEdit) {
+        _this.$confirm({
+          title: '提示',
+          content: '库存不足,确认添加为急件吗?',
+          centered: true,
+          closable: true,
+          onOk () {
+            _this.isPutCostDyPrice(row)
+          }
+        })
+      } else {
+        _this.isPutCostDyPrice(row)
+      }
+    },
+    // 判断售价低于成本价
+    isPutCostDyPrice (row) {
+      const _this = this
+      if (row.putCost > row.price) {
+        // 销售价低于成本价
+        _this.$confirm({
+          title: '提示',
+          content: '售价低于成本价,确认要添加吗?',
+          centered: true,
+          closable: true,
+          onOk () {
+            _this.saveNewProduct(row)
+          }
+        })
+      } else {
+        _this.saveNewProduct(row)
+      }
+    },
+    // 保存添加的产品到销售列表
+    saveNewProduct (row) {
+      this.$message.loading('正在添加产品...', 1)
+      this.isInster = true
+      // this.spinning = true
+      salesDetailInsert({
+        buyerSn: this.detailData.buyerSn,
+        productSn: row.productSn,
+        cost: row.putCost,
+        // productCode: row.productCode,
+        // productOrigCode: row.productOrigCode,
+        price: row.price,
+        qty: row.salesNums,
+        salesBillSn: this.detailData.salesBillSn,
+        salesBillNo: this.detailData.salesBillNo,
+        warehouseSn: row.warehouseSn,
+        warehouseLocationSn: row.warehouseLocationSn,
+        stockSn: row.stockSn
+      }).then(res => {
+        if (res.status == 200) {
+          // this.resetSearchForm(true)  //  不刷新库存
+          this.$refs.table.refresh(true)
+          this.getOrderDetail(false)
+          if (this.showShelfModal) {
+            this.$refs.chooseShelfProduct.reload()
+          }
+        } else {
+          if (res.errCode == 'VALID_F_00001') {
+            this.productForm = {
+              productName: '',
+              productCode: row.productCode || '',
+              orderBy: 'sales_bill_detail.CREATE_DATE desc'
+            }
+            this.$refs.table.refresh(true)
+          }
+        }
+        this.isInster = false
+        // this.spinning = false
+      })
+    },
+    // 批量添加接口
+    plInsterProduct (list) {
+      const params = []
+      list.map(item => {
+        params.push({
+          buyerSn: this.detailData.buyerSn,
+          productSn: item.productSn,
+          cost: item.putCost,
+          price: item.price,
+          qty: item.salesNums,
+          salesBillSn: this.detailData.salesBillSn,
+          salesBillNo: this.detailData.salesBillNo,
+          stockSn: item.stockSn
+        })
+      })
+      this.$message.loading('正在批量添加产品...', 1)
+      salesDetailInsertBatch(params).then(res => {
+        if (res.status == 200) {
+          this.$refs.table.refresh(true)
+          this.getOrderDetail(false)
+          if (this.showShelfModal) {
+            this.$refs.chooseShelfProduct.reload()
+          }
+        }
+      })
+    },
+    //  销售单详情
+    getOrderDetail (flag) {
+      salesDetail({ id: this.$route.params.id }).then(res => {
+        if (res.status == 200) {
+          this.detailData = res.data
+          if (flag) {
+            const vm = this
+            const buyerSn = (vm.detailData && vm.detailData.buyerSn && vm.detailData.sourceType && vm.detailData.sourceType == 'PURCHASE') ? '' : vm.detailData.buyerSn
+            const priceType = vm.$route.params.priceType
+            vm.$refs.partQuery.pageInit(buyerSn, priceType, vm.salesBillSn)
+            // 查询关联的客户
+            if (vm.detailData && vm.detailData.buyerSn) {
+              this.getShelfQueryByCustomer()
+            }
+          }
+        }
+      })
+    },
+    getShelfQueryByCustomer () {
+      queryByCustomerSn({ sn: this.detailData.buyerSn }).then(res => {
+        if (res.data) {
+          this.shelfInfo = Object.assign(res.data, { salePriceType: this.$route.params.priceType, salesBillSn: this.salesBillSn })
+        } else {
+          this.shelfInfo = null
+        }
+      })
+    },
+    // 提交销售单
+    handleSubmit (params) {
+      this.spinning = true
+      const submitTypes = this.tbForm.join(',')
+      salesWriteSubmit({ id: this.orderId, submitTypes: submitTypes, ...params }).then(res => {
+        console.log(res)
+        if (res.status == 200) {
+          this.handleBack()
+          this.$message.success(res.message)
+          // this.spinning = false
+        } else {
+          this.spinning = false
+        }
+      })
+    },
+    // 开启结算账户功能收款, type:0 单条收款,1 批量收款
+    handleSettleAcountPay (row, type) {
+      this.openSettleModal = true
+      const data = {
+        totalAmount: this.detailData.discountedAmount,
+        settleClientName: '',
+        title: '收款',
+        type,
+        row
+      }
+      this.$nextTick(() => {
+        this.$refs.settleModal.setData(data)
+      })
+    },
+    // 去收款
+    settleAcountPay (form, data) {
+      const params = {}
+      // 资金管理开启
+      if (this.enableFundAccount) {
+        params.settleStyleSn = form.settleStyleSn
+        params.settleAccountSn = form.settleAccountSn
+      }
+      this.spinning = true
+      this.handleSubmit(params)
+    },
+    // 确认导入明细
+    hanldeImprotOk (obj) {
+      this.spinning = true
+      salesDetailInsertImport(obj).then(res => {
+        if (res.status == 200) {
+          this.$refs.table.refresh(true)
+          this.getOrderDetail(false)
+        }
+        this.spinning = false
+      })
+    },
+    pageInit () {
+      const vm = this
+      vm.$nextTick(() => {
+        vm.orderId = vm.$route.params.id
+        vm.salesBillSn = vm.$route.params.sn
+        // 是否默认打印原厂编码
+        vm.printOrgCode = localStorage.getItem('printOrgCode-' + this.$store.state.user.info.orgId) == 'true'
+        vm.printAllName = localStorage.getItem('printAllName-' + this.$store.state.user.info.orgId) == 'true'
+        vm.getOrderDetail(true)
+        vm.$refs.table.refresh(true)
+      })
+    }
+  },
+  watch: {
+    printOrgCode (newValue, oldValue) {
+      localStorage.setItem('printOrgCode-' + this.$store.state.user.info.orgId, newValue)
+    },
+    printAllName (newValue, oldValue) {
+      localStorage.setItem('printAllName-' + this.$store.state.user.info.orgId, newValue)
+    }
+  },
+  mounted () {
+    this.showPage = true
+    if (!this.$store.state.app.isNewTab) { // 页签刷新时调用
+      this.pageInit()
+    }
+  },
+  activated () {
+    this.showPage = true
+    // 如果是新页签打开或者进入新的子页(例:存在列表第2条数据编辑页页签时再打开第4条数据的编辑页),则重置当前页面
+    if (this.$store.state.app.isNewTab || !this.$store.state.app.isNewSubTab) {
+      this.pageInit()
+    }
+    // 结算账户状态查询
+    if (this.$hasPermissions('M_fundAccountList') && this.$hasPermissions('B_fundAccountEnable')) {
+    	this.GetSettleAccountState().then(res => {
+    	  if (res.status == 200) {
+    		this.enableFundAccount = res.data.functionEnableFlag == 1
+    	  }
+    	})
+    }
+  },
+  beforeRouteEnter (to, from, next) {
+    next(vm => {})
+  }
+}
+</script>
+
+<style lang="less">
+  .salesEdit-wrap{
+    position: relative;
+    height: 100%;
+    box-sizing: border-box;
+    >.ant-spin-nested-loading{
+      overflow-y: auto;
+      height: 100%;
+    }
+    .salesEdit-cont{
+      margin-top: 10px;
+    }
+    .total-bar{
+      display: flex;
+      align-items: center;
+      justify-content: space-between;
+      > div{
+        &:last-child{
+          display: flex;
+          align-items: center;
+          justify-content: space-between;
+          > div{
+            padding: 0 10px;
+          }
+        }
+      }
+    }
+    .redBg-row{
+      background-color: #f5cdc8;
+    }
+  }
+</style>

+ 196 - 0
src/views/salesManagement/salesQueryNew/importGuideModal.vue

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

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

@@ -0,0 +1,602 @@
+<template>
+  <div class="jg-page-wrap salesManagementList-wrap">
+    <a-card size="small" :bordered="false" class="table-page-search-wrapper">
+      <!-- 搜索条件 -->
+      <div ref="tableSearch">
+        <a-form layout="inline" @keyup.enter.native="searchForm">
+          <a-row :gutter="15">
+            <a-col :md="6" :sm="24">
+              <a-form-item label="创建时间">
+                <rangeDate :allowClear="isByCustQuery" :hasDisabledAreaTime="false" ref="rangeDate" :value="time" @change="dateChange" />
+              </a-form-item>
+            </a-col>
+            <a-col :md="6" :sm="24">
+              <a-form-item label="客户名称" :label-col="{ span:7 }" :wrapper-col="{ span:17}" :required="isByCustQuery">
+                <custList ref="custList" @change="custChange"></custList>
+              </a-form-item>
+            </a-col>
+            <a-col :md="6" :sm="24">
+              <a-form-item label="销售单号">
+                <a-input id="salesManagementList-salesBillNo" v-model.trim="queryParam.salesBillNo" allowClear placeholder="请输入销售单号"/>
+              </a-form-item>
+            </a-col>
+            <a-col :md="6" :sm="24">
+                <a-form-item label="审核时间">
+                  <rangeDate ref="auditRangeDate" v-model="auditTime" @change="auditDateChange" />
+                </a-form-item>
+              </a-col>
+            <template v-if="advanced">
+              <a-col :md="6" :sm="24">
+                <a-form-item label="出库时间">
+                  <rangeDate ref="outWareRangeDate" v-model="outWareTime" @change="outWareDateChange" />
+                </a-form-item>
+              </a-col>
+              <a-col :md="6" :sm="24">
+                <a-form-item label="单据来源">
+                  <v-select
+                    v-model="queryParam.sourceType"
+                    ref="sourceType"
+                    id="salesManagementList-sourceType"
+                    code="SALES_SOURCE"
+                    placeholder="请选择单据来源"
+                    allowClear></v-select>
+                </a-form-item>
+              </a-col>
+              <a-col :md="6" :sm="24">
+                <a-form-item label="收款方式">
+                  <v-select
+                    code="SETTLE_STYLE"
+                    id="salesManagementList-settleStyleSn"
+                    v-model="queryParam.settleStyleSn"
+                    allowClear
+                    placeholder="请选择收款方式"
+                  ></v-select>
+                </a-form-item>
+              </a-col>
+              <a-col :md="6" :sm="24">
+                <a-form-item label="业务状态">
+                  <v-select
+                    v-model="queryParam.billStatus"
+                    ref="billStatus"
+                    id="salesManagementList-billStatus"
+                    code="SALES_BILL_STATUS"
+                    placeholder="请选择业务状态"
+                    allowClear></v-select>
+                </a-form-item>
+              </a-col>
+              <a-col :md="6" :sm="24">
+                <a-form-item label="财务状态">
+                  <v-select
+                    v-model="queryParam.financialStatus"
+                    ref="financialStatus"
+                    id="salesManagementList-financialStatus"
+                    code="FINANCIAL_RECEIVE_STATUS"
+                    placeholder="请选择财务状态"
+                    allowClear></v-select>
+                </a-form-item>
+              </a-col>
+              <a-col :md="6" :sm="24">
+                <a-form-item label="采购单号">
+                  <a-input id="salesManagementList-purchaseBillNo" v-model.trim="queryParam.purchaseBillNo" allowClear placeholder="请输入采购单号"/>
+                </a-form-item>
+              </a-col>
+              <a-col :span="6">
+                <a-form-model-item label="铺货出库">
+                  <v-select code="FLAG" id="salesManagementList-distributionFlag" v-model="queryParam.distributionFlag" allowClear placeholder="请选择是否铺货出库"></v-select>
+                </a-form-model-item>
+              </a-col>
+            </template>
+            <a-col :span="24" style="display:flex;justify-content: center;align-items: center;">
+              <a-button type="primary" :disabled="disabled" @click="searchForm">查询</a-button>
+                <a-button style="margin-left: 5px" :disabled="disabled" @click="resetSearchForm()">重置</a-button>
+                <a-button
+                  type="primary"
+                  v-if="$hasPermissions('B_salesExport')"
+                  class="button-warning"
+                  @click="handleExport"
+                  :disabled="disabled"
+                  :loading="exportLoading"
+                  id="salesManagementList-export">导出</a-button>
+                <a @click="advanced=!advanced" style="margin-left: 5px">
+                  {{ advanced ? '收起' : '展开' }}
+                  <a-icon :type="advanced ? 'up' : 'down'"/>
+                </a>
+            </a-col>
+          </a-row>
+        </a-form>
+      </div>
+    </a-card>
+ 
+  <a-card size="small" :bordered="false">
+    <a-spin :spinning="spinning" tip="Loading...">
+      <!-- 操作按钮 -->
+      <div class="table-operator">
+        <a-button type="primary" class="button-error" v-if="$hasPermissions('B_salesNews')" @click="handleAdd(0)">新增(零售)</a-button>
+        <a-button type="primary" class="button-warning" v-if="$hasPermissions('B_salesNews')" @click="handleAdd(1)">新增(铺货)</a-button>
+        <a-checkbox style="margin-left:10px;" v-model="isByCustQuery" id="sales-byCustQuery">按客户查询</a-checkbox>
+        <a-popover placement="right">
+          <template slot="content">
+            使用此查询时,时间可清空,必须选择一个客户
+          </template>
+          <a-icon type="question-circle" />
+        </a-popover>
+
+      </div>
+      <a-alert type="info" style="margin-bottom:10px">
+        <div slot="message">
+          总售价:<strong>{{ totalData&&(totalData.totalAmount || totalData.totalAmount==0) ? toThousands(totalData.totalAmount) : '--' }}</strong>元;
+          总单数:<strong>{{ totalData&&(totalData.totalRecord || totalData.totalRecord==0) ? totalData.totalRecord : '--' }}</strong>;
+          总款数:<strong>{{ totalData&&(totalData.totalCategory || totalData.totalCategory==0) ? totalData.totalCategory : '--' }}</strong>;
+          总数量:<strong>{{ totalData&&(totalData.totalQty || totalData.totalQty==0) ? totalData.totalQty : '--' }}</strong>;
+        </div>
+      </a-alert>
+      <!-- 列表 -->
+      <s-table
+        class="sTable fixPagination"
+        ref="table"
+        :style="{ height: tableHeight+77+'px' }"
+        size="small"
+        :rowKey="(record) => record.id"
+        :columns="columns"
+        :data="loadData"
+        :scroll="{ y:tableHeight }"
+        :defaultLoadData="false"
+        bordered>
+        <!-- 销售单号 -->
+        <template slot="salesBillNo" slot-scope="text, record">
+          <span class="table-td-link" v-if="$hasPermissions('B_salesDetail')" @click="handleDetail(record)">{{ record.salesBillNo }}</span>
+          <span v-else>{{ record.salesBillNo }}</span>
+          <a-badge count="改" :offset="[10,0]" v-if="record.billStatus=='SUPERIOR_CHANGE'"></a-badge>
+        </template>
+        <!-- 审核 -->
+        <template slot="audit" slot-scope="text, record">
+          <stateIcon :title="record.billStatusDictValue" v-if="record.billStatus!='AUDIT_REJECT'" :state="record.billStatus == 'WAIT_OUT_WAREHOUSE'||record.billStatus == 'FINISH'?'1':'2'"></stateIcon>
+          <stateIcon :title="record.billStatusDictValue" v-else :state="0"></stateIcon>
+        </template>
+        <!-- 急件 -->
+        <template slot="oosFlag" slot-scope="text, record">
+          <stateIcon :state="record.oosFlag==1?'1':'2'"></stateIcon>
+        </template>
+        <!-- 出库 -->
+        <template slot="waitOut" slot-scope="text, record">
+          <stateIcon :state="record.billStatus == 'FINISH'?'1':'2'"></stateIcon>
+        </template>
+        <!-- 收款 -->
+        <template slot="financial" slot-scope="text, record">
+          <stateIcon :title="record.financialStatusDictValue" :state="record.financialStatus == 'FINISH'?'1':'2'"></stateIcon>
+        </template>
+        <!-- 操作 -->
+        <template slot="action" slot-scope="text, record">
+          <a-button
+            size="small"
+            type="link"
+            class="button-primary"
+            v-if="record.billStatus == 'WAIT_AUDIT' && $hasPermissions('B_salesAudit')"
+            @click="handleEexamine(record)"
+          >审核</a-button>
+          <a-button
+            size="small"
+            type="link"
+            v-if="record.billStatus == 'WAIT_OUT_WAREHOUSE' && $hasPermissions('B_salesStockOut')"
+            class="button-primary"
+            @click="handleSend(record)"
+          >出库</a-button>
+          <a-button
+            size="small"
+            type="link"
+            class="button-primary"
+            v-if="((record.sourceType == 'SATELLITE' || record.sourceType == 'SALES' || record.sourceType == 'TEMPORARY_DISPATCHING') && (record.billStatus == 'WAIT_AUDIT' || record.billStatus == 'WAIT_SUBMIT' || record.billStatus == 'AUDIT_REJECT')) && $hasPermissions('B_salesEdit')"
+            @click="handleEdit(record)"
+          >
+            编辑
+          </a-button>
+          <a-button
+            size="small"
+            type="link"
+            class="button-error"
+            v-if="((record.sourceType == 'SATELLITE' || record.sourceType == 'SALES' || record.sourceType == 'TEMPORARY_DISPATCHING') && record.billStatus != 'FINISH') && $hasPermissions('B_salesDel')"
+            @click="handleDel(record)"
+          >
+            删除
+          </a-button>
+          <a-button
+            size="small"
+            type="link"
+            class="button-primary"
+            v-if="(record.sourceType == 'PURCHASE' && (record.billStatus == 'WAIT_AUDIT' || record.billStatus == 'SUPERIOR_CHANGE')) && $hasPermissions('B_salesEdit')"
+            @click="handleEdit(record)"
+          >
+            改单
+          </a-button>
+          <a-button
+            size="small"
+            type="link"
+            class="button-error"
+            v-if="(record.sourceType == 'PURCHASE' && (record.billStatus == 'WAIT_AUDIT' || record.billStatus == 'SUPERIOR_CHANGE')) && $hasPermissions('B_salesDel')"
+            @click="handleDel(record, 'cancel')"
+          >
+            取消
+          </a-button>
+          <span v-if="!(record.billStatus == 'WAIT_AUDIT' && $hasPermissions('B_salesAudit')) && !(record.billStatus == 'WAIT_OUT_WAREHOUSE' && $hasPermissions('B_salesStockOut')) && !(((record.sourceType == 'SATELLITE' || record.sourceType == 'SALES' || record.sourceType == 'TEMPORARY_DISPATCHING') && (record.billStatus == 'WAIT_AUDIT' || record.billStatus == 'WAIT_SUBMIT' || record.billStatus == 'AUDIT_REJECT')) && $hasPermissions('B_salesEdit')) && !(((record.sourceType == 'SATELLITE' || record.sourceType == 'SALES' || record.sourceType == 'TEMPORARY_DISPATCHING') && record.billStatus != 'FINISH') && $hasPermissions('B_salesDel')) && !((record.sourceType == 'PURCHASE' && (record.billStatus == 'WAIT_AUDIT' || record.billStatus == 'SUPERIOR_CHANGE')) && $hasPermissions('B_salesEdit')) && !((record.sourceType == 'PURCHASE' && (record.billStatus == 'WAIT_AUDIT' || record.billStatus == 'SUPERIOR_CHANGE')) && $hasPermissions('B_salesDel'))">--</span>
+        </template>
+      </s-table>
+    </a-spin>
+    <!-- 选择客户弹框 -->
+    <choose-custom-modal :show="openModal" :distributionFlag="distributionFlag" @ok="chooseCustomOk" @cancel="openModal=false"></choose-custom-modal>
+    <!-- 审核 -->
+    <auditModal :openModal="visibleAudit" :spinning="spinningAudit" @close="visibleAudit=false" @ok="auditOrder('WAIT_OUT_WAREHOUSE')" @fail="auditOrder('AUDIT_REJECT')" />
+  </a-card>
+</div>
+</template>
+
+<script>
+import { commonMixin } from '@/utils/mixin'
+import getDate from '@/libs/getDate.js'
+import { STable, VSelect } from '@/components'
+import chooseCustomModal from './chooseCustomModal.vue'
+import auditModal from '@/views/common/auditModal.vue'
+import { salesList, salesDel, salesWriteAudit, salesWriteStockOut, salesCount, salesExport } from '@/api/sales'
+import rangeDate from '@/views/common/rangeDate.vue'
+import custList from '@/views/common/custList.vue'
+import { downloadExcel } from '@/libs/JGPrint.js'
+import stateIcon from '@/views/common/stateIcon'
+import moment from 'moment'
+export default {
+  name: 'SalesList',
+  components: { STable, VSelect, chooseCustomModal, rangeDate, auditModal, custList, stateIcon },
+  mixins: [commonMixin],
+  data () {
+    const _this = this
+    return {
+      spinning: false,
+      tableHeight: 0,
+      advanced: true, // 高级搜索 展开/关闭
+      disabled: false, //  查询、重置按钮是否可操作
+      exportLoading: false, // 导出loading
+      openModal: false, // 选择客户弹框是否显示
+      isByCustQuery: false, // 是否按客户查询
+      time: [
+        getDate.getMonthDays(12).starttime,
+        getDate.getMonthDays(12).endtime
+      ],
+      auditTime: [],
+      outWareTime: [],
+      // 查询参数
+      queryParam: {
+        beginDate: getDate.getMonthDays(12).starttime,
+        endDate: getDate.getMonthDays(12).endtime,
+        auditBeginDate: '',
+        auditEndDate: '',
+        outWarehouseBeginDate: '',
+        outWarehouseEndDate: '',
+        buyerNameCurrent: undefined, //  客户名称
+        buyerSn: undefined,
+        salesBillNo: '', //  销售单号
+        purchaseBillNo: '', //  采购单号
+        payType: undefined, //  支付方式
+        settleStyleSn: undefined, //  收款方式
+        billStatus: undefined, //  业务状态
+        financialStatus: undefined, //  财务状态
+        sourceType: undefined,
+        distributionFlag: undefined
+      },
+      totalData: {
+        totalAmount: 0,
+        totalCategory: 0,
+        totalQty: 0,
+        totalRecord: 0
+      },
+      selType: '0', // 0零售 1铺货
+      // 表头
+      columns: [
+        { title: '序号', dataIndex: 'no', align: 'center', width: '4%' },
+        { title: '来源', dataIndex: 'sourceTypeDictValue', width: '6%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '销售单号', scopedSlots: { customRender: 'salesBillNo' }, width: '9%', align: 'center' },
+        { title: '客户名称', dataIndex: 'buyerNameCurrent', align: 'center', width: '15%', customRender: function (text) { return text || '--' } },
+        { title: '总款数', dataIndex: 'totalCategory', align: 'center', width: '5%', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
+        { title: '总数量', dataIndex: 'totalQty', align: 'center', width: '5%', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
+        { title: '总售价', dataIndex: 'totalAmount', align: 'right', width: '5%', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } },
+        { title: '折后总售价', dataIndex: 'discountedAmount', align: 'right', width: '5%', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } },
+        { title: '收款方式', dataIndex: 'settleStyleSnDictValue', width: '5%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '创建时间', dataIndex: 'createDate', width: '8%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '审核时间', dataIndex: 'auditDate', width: '8%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '业务状态', dataIndex: 'billStatusDictValue', width: '5%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '审核', scopedSlots: { customRender: 'audit' }, width: '2%', align: 'center' },
+        { title: '急件', scopedSlots: { customRender: 'oosFlag' }, width: '2%', align: 'center' },
+        { title: '出库', scopedSlots: { customRender: 'waitOut' }, width: '2%', align: 'center' },
+        { title: '收款', scopedSlots: { customRender: 'financial' }, width: '2%', align: 'center' },
+        // { title: '财务状态', dataIndex: 'financialStatusDictValue', width: '5%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '操作', scopedSlots: { customRender: 'action' }, width: '8%', align: 'center' }
+      ],
+      // 加载数据方法 必须为 Promise 对象
+      loadData: parameter => {
+        this.disabled = true
+        this.spinning = true
+        // 查询总计
+        salesCount(Object.assign(parameter, this.queryParam)).then(res => {
+          console.log(res, 'res')
+          this.totalData = Object.assign(this.totalData, res.data || {})
+        })
+        return salesList(Object.assign(parameter, this.queryParam)).then(res => {
+          let data
+          if (res.status == 200) {
+            data = res.data
+            const no = (data.pageNo - 1) * data.pageSize
+            for (var i = 0; i < data.list.length; i++) {
+              data.list[i].no = no + i + 1
+            }
+            this.disabled = false
+          }
+          console.log(res, 'res')
+          this.spinning = false
+          return data
+        })
+      },
+      visibleAudit: false,
+      auditInfo: null,
+      spinningAudit: false,
+      distributionFlag: '0'
+    }
+  },
+  methods: {
+    //  时间  change
+    dateChange (date) {
+      this.queryParam.beginDate = date[0]
+      this.queryParam.endDate = date[1]
+    },
+    auditDateChange (date) {
+      this.auditTime = date
+      this.queryParam.auditBeginDate = date[0]
+      this.queryParam.auditEndDate = date[1]
+    },
+    outWareDateChange (date) {
+      this.outWareTime = date
+      this.queryParam.outWarehouseBeginDate = date[0]
+      this.queryParam.outWarehouseEndDate = date[1]
+    },
+    custChange (v, row) {
+      console.log(v, row)
+      if (row && row.customerSn) {
+        this.queryParam.buyerSn = row.customerSn
+        this.queryParam.buyerNameCurrent = undefined
+      } else {
+        this.queryParam.buyerNameCurrent = v
+        this.queryParam.buyerSn = undefined
+      }
+    },
+    // 新增
+    handleAdd (flag) {
+      this.openModal = true
+      this.distributionFlag = flag
+    },
+    //  审核
+    handleEexamine (row) {
+      this.auditInfo = row
+      this.visibleAudit = true
+    },
+    auditOrder (billStatus) {
+      this.spinningAudit = true
+      salesWriteAudit({
+        id: this.auditInfo.id,
+        billStatus: billStatus
+      }).then(res => {
+        if (res.status == 200) {
+          this.visibleAudit = false
+          this.$message.success(res.message)
+          this.$refs.table.refresh()
+          this.spinningAudit = false
+        } else {
+          this.visibleAudit = false
+          this.spinningAudit = false
+        }
+      })
+    },
+    //  出库
+    handleSend (row) {
+      const _this = this
+      this.$confirm({
+        title: '提示',
+        content: '确认要出库吗?',
+        centered: true,
+        closable: true,
+        onOk () {
+          _this.spinning = true
+          salesWriteStockOut({
+            salesBillSn: row.salesBillSn
+          }).then(res => {
+            if (res.status == 200) {
+              _this.$message.success(res.message)
+              _this.$refs.table.refresh()
+              _this.spinning = false
+            } else {
+              _this.spinning = false
+            }
+          })
+        }
+      })
+    },
+    // 详情
+    handleDetail (row) {
+      this.$router.push({ name: 'salesNewDetail', params: { sn: row.salesBillSn } })
+    },
+    // 编辑
+    handleEdit (row) {
+      this.$router.push({ name: 'salesNewEdit', params: { id: row.id, sn: row.salesBillSn, priceType: row.priceType } })
+    },
+    // 选择客户成功
+    chooseCustomOk (data) {
+      this.$router.push({ name: 'salesNewAdd', params: { id: data.id, sn: data.salesBillSn, priceType: data.priceType } })
+    },
+    // 删除
+    handleDel (row, type) {
+      const _this = this
+      let content = '确认要删除吗?'
+      if (type == 'cancel') {
+        content = '确认要取消吗?'
+      }
+      this.$confirm({
+        title: '提示',
+        content: <div><div style='font-size:16px;margin-bottom:10px;'>{content}</div><div>销售单号:{row.salesBillNo}</div><div>客户名称:{row.buyerNameCurrent}</div></div>,
+        centered: true,
+        closable: true,
+        onOk () {
+          _this.spinning = true
+          salesDel({ id: row.id }).then(res => {
+            if (res.status == 200) {
+              _this.$message.success(res.message)
+              _this.$refs.table.refresh()
+              _this.spinning = false
+            } else {
+              _this.spinning = false
+            }
+          })
+        }
+      })
+    },
+    searchForm () {
+      if (!this.isByCustQuery) {
+        const a = moment(this.queryParam.beginDate)
+        const b = moment(this.queryParam.endDate)
+        if (b.diff(a, 'days') > 730) {
+          this.$message.info('最多只能选择2年的时间区间')
+          return false
+        }
+        this.$refs.table.refresh(true)
+      } else {
+        if (this.queryParam.buyerSn) {
+          this.$refs.table.refresh(true)
+        } else {
+          this.$message.info('请选择客户')
+          return false
+        }
+      }
+    },
+    // 重置
+    resetSearchForm () {
+      this.resetData()
+      this.$refs.table.refresh(true)
+    },
+    // 重置数据
+    resetData (flag) {
+      this.$refs.rangeDate.resetDate(flag ? '' : this.time)
+      this.queryParam.beginDate = flag ? '' : getDate.getMonthDays(12).starttime
+      this.queryParam.endDate = flag ? '' : getDate.getMonthDays(12).endtime
+
+      this.queryParam.auditBeginDate = ''
+      this.queryParam.auditEndDate = ''
+      this.queryParam.outWarehouseBeginDate = ''
+      this.queryParam.outWarehouseEndDate = ''
+      this.auditTime = []
+      this.outWareTime = []
+      if (this.advanced) {
+        this.$refs.auditRangeDate.resetDate('')
+        this.$refs.outWareRangeDate.resetDate('')
+      }
+
+      this.queryParam.buyerNameCurrent = undefined
+      this.queryParam.buyerSn = undefined
+      this.queryParam.salesBillNo = ''
+      this.queryParam.purchaseBillNo = ''
+      this.queryParam.payType = undefined
+      this.queryParam.settleStyleSn = undefined
+      this.queryParam.billStatus = undefined
+      this.queryParam.financialStatus = undefined
+      this.queryParam.sourceType = undefined
+      this.queryParam.distributionFlag = undefined
+      this.$refs.custList.resetForm()
+      if (!flag) {
+        this.setIsHomeNav(this.$route.name, null)
+      }
+    },
+    //  导出
+    handleExport () {
+      const _this = this
+      const params = this.queryParam
+      this.exportLoading = true
+      _this.spinning = true
+      salesExport(params).then(res => {
+        this.exportLoading = false
+        _this.spinning = false
+        if (res.type == 'application/json') {
+          var reader = new FileReader()
+          reader.addEventListener('loadend', function () {
+            const obj = JSON.parse(reader.result)
+            _this.$notification.error({
+              message: '提示',
+              description: obj.message
+            })
+          })
+          reader.readAsText(res)
+        } else {
+          downloadExcel(res, '销售列表')
+        }
+      })
+    },
+    setTableH () {
+      const tableSearchH = this.$refs.tableSearch.offsetHeight
+      this.tableHeight = window.innerHeight - tableSearchH - 265
+    },
+    pageInit () {
+      const _this = this
+      this.$nextTick(() => { // 页面渲染完成后的回调
+        _this.setTableH()
+      })
+      // 是否打开的页签
+      const a = this.$store.state.app.isNewTab
+      // 是否要刷新列表
+      const b = this.$store.state.app.updateList
+      // 是否从首页点击进入
+      const isHomeNav = this.getIsHomeNav()[this.$route.name]
+      console.log(a, b)
+
+      // 从首页进入,判断式新建还式待办查询
+      if (isHomeNav) {
+        // 新增
+        if (isHomeNav.type == 'new') {
+          this.resetSearchForm()
+          this.openModal = true
+        }
+        // 待办
+        if (isHomeNav.type == 'todo') {
+          this.resetData(true)
+          this.queryParam = Object.assign(this.queryParam, isHomeNav.pageParams)
+          this.$refs.rangeDate.resetDate([this.queryParam.beginDate, this.queryParam.endDate])
+          this.$refs.table.refresh(true)
+        }
+      } else {
+        // 如果是新页签打开,则重置当前页面
+        if (a && !b) {
+          this.resetSearchForm()
+        }
+      }
+      // 仅刷新列表,不重置页面
+      if (b || a == b) {
+        this.$refs.table.refresh()
+      }
+    }
+  },
+  watch: {
+    advanced (newValue, oldValue) {
+      const _this = this
+      this.$nextTick(() => { // 页面渲染完成后的回调
+        _this.setTableH()
+      })
+    },
+    '$store.state.app.winHeight' (newValue, oldValue) { //  窗口变更时,需同时更改表格高度
+      this.setTableH()
+    },
+    isByCustQuery (newValue, oldValue) {
+      if (!newValue) {
+        this.resetSearchForm()
+      }
+    }
+  },
+  activated () {
+    this.pageInit()
+  },
+  beforeRouteEnter (to, from, next) {
+    next(vm => {
+    })
+  }
+}
+</script>

+ 178 - 0
src/views/salesManagement/salesQueryNew/productSalesRecordModal.vue

@@ -0,0 +1,178 @@
+<template>
+  <div v-if="isShow">
+    <a-modal
+      centered
+      class="salesRecord-modal"
+      :footer="null"
+      :maskClosable="false"
+      :title="modalTit"
+      v-drag
+      v-model="isShow"
+      @cancel="isShow=false"
+      :width="960">
+      <div>
+        <div style="padding: 0 0 10px 0;line-height: 24px;" v-if="baseData">
+          <div>产品名称:{{ baseData.productName }}</div>
+          <div>产品编码:{{ baseData.productCode }}</div>
+        </div>
+        <a-tabs size="small" type="card" v-model="curTab" @change="callback">
+          <a-tab-pane key="1" tab="当前客户">
+          </a-tab-pane>
+          <a-tab-pane key="2" tab="全部客户">
+          </a-tab-pane>
+        </a-tabs>
+        <!-- 表格 -->
+        <a-table
+          class="sTable"
+          ref="table"
+          size="small"
+          :rowKey="(record) => record.id"
+          :columns="columns"
+          :dataSource="list"
+          :loading="loading"
+          :pagination="false"
+          bordered>
+        </a-table>
+        <!-- 分页 -->
+        <tablePagination
+          ref="tablePagination"
+          :total="paginationProps.total"
+          :current="paginationProps.current"
+          :pageSize="paginationProps.pageSize"
+          @changePageSize="changePageSize"
+          @changePage="changePage" />
+      </div>
+    </a-modal>
+  </div>
+</template>
+
+<script>
+import { commonMixin } from '@/utils/mixin'
+import { salesRecordlList } from '@/api/salesDetail.js'
+import { STable } from '@/components'
+import tablePagination from '@/views/common/tablePagination.vue'
+export default {
+  name: 'SalesRecordModal',
+  mixins: [commonMixin],
+  components: { STable, tablePagination },
+  props: {
+    openModal: { //  弹框显示状态
+      type: Boolean,
+      default: false
+    },
+    itemId: {
+      type: [Number, String],
+      default: ''
+    }
+  },
+  computed: {
+    modalTit () {
+      return '销售记录'
+    }
+  },
+  data () {
+    const _this = this
+    return {
+      isShow: this.openModal, //  是否打开弹框
+      buyerSn: null,
+      queryParam: {
+        productSn: null
+      },
+      // 表头
+      columns: [
+        { title: '销售时间', dataIndex: 'salesBillEntity.createDate', width: 250, align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '销售价', dataIndex: 'price', width: 150, align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } },
+        { title: '销售数量', dataIndex: 'qty', width: 150, align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
+        { title: '客户名称', dataIndex: 'salesBillEntity.buyerName', align: 'center', customRender: function (text) { return text || '--' }, ellipsis: true }
+      ],
+      list: [],
+      loading: false,
+      curTab: '1',
+      paginationProps: {
+        total: 0, //  分页总条数
+        current: 1,
+        pageSize: 20
+      },
+      baseData: null
+    }
+  },
+  methods: {
+    //  获取详情
+    getDetail (buyerSn, productSn, row) {
+      this.buyerSn = buyerSn
+      if (this.curTab == 1) {
+        this.queryParam.buyerSn = buyerSn
+      } else {
+        delete this.queryParam.buyerSn
+      }
+      this.queryParam.productSn = productSn
+      this.handelSearch(1)
+      this.baseData = row
+    },
+    // 查询列表
+    handelSearch (pageNo) {
+      this.paginationProps.current = pageNo || this.paginationProps.current
+      const params = {
+        pageNo: this.paginationProps.current,
+        pageSize: this.paginationProps.pageSize
+      }
+      // 开始查询
+      this.loading = true
+      salesRecordlList({ ...params, ...this.queryParam }).then(res => {
+        this.loading = false
+        if (res.status == 200) {
+          const data = res.data
+          this.paginationProps.total = Number(res.data.count) || 0
+          this.paginationProps.current = data.pageNo
+          this.list = data.list
+        } else {
+          this.paginationProps.total = 0
+          this.paginationProps.current = 1
+          this.paginationProps.pageSize = 20
+          this.list = []
+        }
+      })
+    },
+    //  分页  一页多少条change
+    changePageSize (current, pageSize) {
+      this.paginationProps.current = current
+      this.paginationProps.pageSize = pageSize
+      this.handelSearch()
+    },
+    //  分页 页码change
+    changePage (current) {
+      this.paginationProps.current = current
+      this.handelSearch()
+    },
+    callback (key) {
+      this.curTab = key
+      this.getDetail(this.buyerSn, this.queryParam.productSn, this.baseData)
+    }
+  },
+  watch: {
+    //  父页面传过来的弹框状态
+    openModal (newValue, oldValue) {
+      this.isShow = newValue
+    },
+    //  重定义的弹框状态
+    isShow (newValue, oldValue) {
+      if (!newValue) {
+        this.$emit('close')
+        this.paginationProps.total = 0
+        this.paginationProps.current = 1
+        this.paginationProps.pageSize = 20
+        this.curTab = '1'
+        this.list = []
+      }
+    }
+  }
+}
+</script>
+
+<style lang="less">
+  .salesRecord-modal{
+    .ant-modal-body {
+      padding: 10px;
+    }
+  }
+</style>

+ 507 - 0
src/views/salesManagement/salesQueryNew/queryPart.vue

@@ -0,0 +1,507 @@
+<template>
+  <div class="productInfoList-wrap">
+    <!-- 搜索条件 -->
+    <div class="table-page-search-wrapper">
+      <a-form-model
+        ref="ruleForm"
+        class="form-model-con"
+        layout="inline"
+        :rules="rules"
+        :model="queryParam"
+        @keyup.enter.native="$refs.table.refresh(true)" >
+        <a-row type="flex" :gutter="5">
+          <a-col :lg="4" :md="6" :sm="12">
+            <a-form-model-item label="产品编码">
+              <a-input id="productInfoList-code" ref="searchProductCode" v-model.trim="queryParam.productCode" allowClear placeholder="请输入产品编码"/>
+            </a-form-model-item>
+          </a-col>
+          <a-col :lg="4" :md="6" :sm="12">
+            <a-form-model-item label="产品名称">
+              <a-input id="productInfoList-name" v-model.trim="queryParam.productName" allowClear placeholder="请输入产品名称"/>
+            </a-form-model-item>
+          </a-col>
+          <a-col :lg="4" :md="6" :sm="12">
+            <a-form-model-item label="原厂编码">
+              <a-input id="productInfoList-origCode" v-model.trim="queryParam.productOrigCode" allowClear placeholder="请输入原厂编码"/>
+            </a-form-model-item>
+          </a-col>
+          <a-col :lg="4" :md="6" :sm="12">
+            <a-form-model-item label="产品分类">
+              <ProductType id="productInfoList-productType" :isDealer="true" @change="changeProductType" v-model="productType"></ProductType>
+            </a-form-model-item>
+          </a-col>
+          <template v-if="advanced">
+            <a-col :lg="4" :md="6" :sm="12">
+              <a-form-model-item label="产品品牌">
+                <ProductBrand id="productInfoList-productBrandSn" v-model="queryParam.brandSn"></ProductBrand>
+              </a-form-model-item>
+            </a-col>
+            <a-col :lg="4" :md="6" :sm="12">
+              <a-form-model-item label="仓库">
+                <a-select
+                  placeholder="请选择仓库"
+                  id="productInfoList-warehouseSn"
+                  allowClear
+                  v-model="queryParam.warehouseSn"
+                  :showSearch="true"
+                  option-filter-prop="children"
+                  :filter-option="filterOption">
+                  <a-select-option v-for="item in warehouseList" :key="item.warehouseSn" :value="item.warehouseSn">{{ item.name }}</a-select-option>
+                </a-select>
+              </a-form-model-item>
+            </a-col>
+            <a-col :lg="6" :md="8" :sm="12" v-if="$hasPermissions('B_salerVinFindProduct')">
+              <a-form-model-item label="车架号(VIN)" prop="vinCode">
+                <a-input id="productInfoList-vinCode" v-model.trim="queryParam.vinCode" allowClear placeholder="请输入车架号(VIN)">
+                  <a-icon @click="uploadFun" :type="vinLoading?'loading':'camera'" slot="addonAfter" :style="{ fontSize: '18px', verticalAlign: 'bottom' }" />
+                </a-input>
+                <input type="file" id="filed" accept="image/jpeg,image/png" hidden="" @change="filePreview">
+              </a-form-model-item>
+            </a-col>
+            <a-col :md="6" :sm="24">
+              <a-form-item label="是否有库存">
+                <a-select @change="handleHasQty" allowClear :value="queryParam.existStockFlag" placeholder="请选择查看是否有库存">
+                  <a-select-option value="1">
+                    是
+                  </a-select-option>
+                  <a-select-option value="0">
+                    否
+                  </a-select-option>
+                </a-select>
+              </a-form-item>
+            </a-col>
+          </template>
+          <a-col flex="200px" style="margin-bottom: 10px;">
+            <a-button type="primary" @click="$refs.table.refresh(true)" :disabled="disabled" id="productInfoList-refresh">查询</a-button>
+            <a-button style="margin-left: 5px" @click="resetSearchForm" id="productInfoList-reset">重置</a-button>
+            <a @click="advanced=!advanced" style="margin:0 0 0 10px">
+              {{ advanced ? '收起' : '展开' }}
+              <a-icon :type="advanced ? 'up' : 'down'"/>
+            </a>
+          </a-col>
+          <a-col flex="auto" style="margin-bottom: 15px;display:flex;align-items:center;">
+            <a-checkbox v-model="cost" v-if="$hasPermissions('M_ShowAllCost')" id="salesQuery-cost">成本价</a-checkbox>
+            <a-checkbox v-model="cityPrice" id="salesQuery-cityPrice">市级价</a-checkbox>
+            <a-checkbox v-model="tyuePrice" v-if="$store.state.user.isShowSpecialPrice==1" id="salesQuery-tyuePrice">特约价</a-checkbox>
+            <a-checkbox v-model="zdPrice" id="salesQuery-zdPrice">终端价</a-checkbox>
+          </a-col>
+        </a-row>
+      </a-form-model>
+    </div>
+    <a-alert type="error" style="margin-bottom: 10px;" v-if="vinInfoData&&!vinInfoData.vinInfo">
+      <template slot="message"><a-icon type="exclamation-circle" theme="filled" :style="{ color: '#E70012', fontSize: '15px', verticalAlign: 'sub', marginRight: '3px' }" />抱歉!暂未找到匹配VIN码的车型!</template>
+    </a-alert>
+    <a-alert type="warning" style="margin-bottom: 10px;cursor: pointer;" v-if="vinInfoData&&vinInfoData.vinInfo" @click="openCarInfoModal=true">
+      <template slot="message">
+        <div style="display: flex;justify-content: space-between;align-items: center;" @click="openCarInfoModal=true">
+          <div>
+            <img :src="vinInfoData.vinInfo && vinInfoData.vinInfo.icon?(vinInfoData.vinInfo.icon+'?x-oss-process=image/resize,h_30,m_lfit'):defImg" width="30" height="30" class="imageUrl" style="border-radius: 50%;vertical-align: middle;margin-right: 3px;" />
+            <span style="vertical-align: middle;">{{ vinInfoData.vinInfo.text }}</span>
+          </div>
+          <div style="color: #f90;">
+            <span>查看更多</span> >
+          </div>
+        </div>
+      </template>
+    </a-alert>
+    <!-- 列表 -->
+    <s-table
+      class="sTable"
+      ref="table"
+      size="small"
+      :rowKey="(record) => record.no"
+      rowKeyName="no"
+      :columns="columns"
+      :data="loadData"
+      @dblclick="handleClickRow"
+      :defaultLoadData="false"
+      :pageSize="10"
+      :scroll="{ y: 149 }"
+      bordered>
+      <div slot="costTitle">
+        <a-tooltip placement="top">
+          <template slot="title">
+            产品所在仓库仓位的最近一次入库成本,不包含盘盈入库和仓库调拨入库。
+          </template>
+          <span style="margin-right: 5px;">参考成本价</span> <a-icon type="question-circle" />
+        </a-tooltip>
+      </div>
+      <!-- 售价 -->
+      <template slot="salePrice" slot-scope="text, record">
+        <div style="display: flex;align-items: center;" @dblclick.stop>
+          <a-input-number
+            size="small"
+            v-model="record.price"
+            :precision="2"
+            :min="0"
+            :max="999999"
+            style="width: 100%;"
+            placeholder="请输入" />
+          <span style="color: red;margin: 0 2px;font-size: 14px;" v-if="record.origSalePriceFlag == 1">原</span>
+          <span v-else>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
+        </div>
+      </template>
+      <!-- 销售数量 -->
+      <template slot="nums" slot-scope="text, record">
+        <div @dblclick.stop>
+          <a-input-number
+            size="small"
+            v-model="record.salesNums"
+            :precision="0"
+            :min="0"
+            :max="999999"
+            style="width: 100%;"
+            placeholder="请输入" />
+        </div>
+      </template>
+      <!-- 操作 -->
+      <template slot="action" slot-scope="text, record">
+        <a-button
+          size="small"
+          type="link"
+          class="button-primary"
+          @click="handleAdd(record)"
+          id="productInfoList-edit-btn">添加</a-button>
+        <a-button
+          size="small"
+          type="link"
+          class="button-primary"
+          @click="handleDetail(record)"
+          id="productInfoList-detail-btn"
+          style="margin-left: 5px;">销售记录</a-button>
+      </template>
+    </s-table>
+    <!-- 销售记录 -->
+    <product-salesRecord-modal ref="salseRecord" :openModal="openModal" @close="closeModal" />
+    <!-- 查看车辆信息 -->
+    <car-info-modal ref="carInfoModal" :openModal="openCarInfoModal" :infoData="vinInfoData&&vinInfoData.vinInfo" @close="openCarInfoModal=false" />
+  </div>
+</template>
+
+<script>
+import { commonMixin } from '@/utils/mixin'
+import { querySumByProductLocation } from '@/api/stock'
+import { warehouseAllList } from '@/api/warehouse'
+import productSalesRecordModal from './productSalesRecordModal.vue'
+import carInfoModal from './carInfoModal.vue'
+import ProductType from '../../common/productType.js'
+import ProductBrand from '../../common/productBrand.js'
+import { STable, VSelect, Upload } from '@/components'
+import { supperCodeByVin, vinCodeParse } from '@/api/sales'
+import defImg from '@/assets/def_img@2x.png'
+export default {
+  name: 'QueryPart',
+  components: { STable, VSelect, Upload, productSalesRecordModal, carInfoModal, ProductType, ProductBrand },
+  mixins: [commonMixin],
+  props: {
+    newLoading: Boolean
+  },
+  data () {
+    return {
+      advanced: false, // 高级搜索 展开/关闭
+      vinLoading: false,
+      productType: [],
+      defImg,
+      queryParam: { //  查询条件
+        customerSn: '',
+        salesBillSn: '',
+        salePriceType: '',
+        productCode: '', //  产品编码
+        productName: '', //  产品名称
+        productOrigCode: '', //  原厂编码
+        vinCode: '',
+        productCodeList: undefined, //  车架号
+        brandSn: undefined, //  产品品牌
+        productTypeSn1: '', //  产品一级分类
+        productTypeSn2: '', //  产品二级分类
+        productTypeSn3: '', //  产品三级分类
+        warehouseSn: undefined, //  仓库、
+        enableFlag: '1',
+        existStockFlag: undefined
+      },
+      priceType: '',
+      buyerSn: '',
+      rules: {
+        vinCode: [ { len: 17, message: '请输入正确的车架号(VIN)', trigger: 'change' } ]
+      },
+      disabled: false, //  查询、重置按钮是否可操作
+      warehouseList: [], // 仓库列表
+      vinInfoData: null,
+      // 加载数据方法 必须为 Promise 对象
+      loadData: parameter => {
+        const _this = this
+        _this.queryParam.salePriceType = _this.priceType
+        _this.queryParam.customerSn = _this.buyerSn
+        // 排序
+        if (parameter.sortField == 'productCode') {
+          parameter.sortField = 'code'
+          parameter.sortAlias = 'product '
+        }
+        if (parameter.sortField == 'brandName') {
+          parameter.sortField = 'firstChar'
+          parameter.sortAlias = 'brand'
+        }
+        if (parameter.sortField == 'warehouseName') {
+          parameter.sortField = 'warehouseSn'
+          parameter.sortAlias = 'sd'
+        }
+        const params = Object.assign(parameter, _this.queryParam)
+        if (_this.queryParam.vinCode && _this.queryParam.vinCode.length == 17 && !this.onlyList) { //  输入vin,查出vin码信息后请求列表数据
+          _this.disabled = true
+          return supperCodeByVin({ vin: _this.queryParam.vinCode }).then(res => {
+            if (res.status == 200) {
+              _this.vinInfoData = res.data
+              params.productCodeList = res.data.partCodeList || []
+              return _this.getList(params)
+            } else {
+              _this.vinInfoData = null
+              _this.$refs.table.localLoading = false
+              _this.$refs.table.clearTable()
+            }
+          })
+        } else if (_this.queryParam.vinCode && _this.queryParam.vinCode.length < 17 && !this.onlyList) { // 输入vin,但vin码不符合标准,不查vin码信息,不请求列表数据
+          _this.$refs.table.localLoading = false
+          _this.$refs.table.clearTable()
+        } else if (this.onlyList) {
+          _this.disabled = true
+          if (_this.queryParam.vinCode && _this.vinInfoData) {
+            return _this.getList(Object.assign(params, { productCodeList: _this.vinInfoData.partCodeList }))
+          } else {
+            return _this.getList(params)
+          }
+        } else { //  未输入vin码信息,只查列表数据
+          _this.disabled = true
+          return _this.getList(params)
+        }
+      },
+      openModal: false, //  查看客户详情  弹框
+      cost: false, // 成本价
+      cityPrice: false, // 城市价
+      tyuePrice: false, // 特约价
+      zdPrice: false, // 终端价
+      openCarInfoModal: false,
+      onlyList: false
+    }
+  },
+  computed: {
+    columns () {
+      const _this = this
+      const arr = [
+        { title: '产品编码', dataIndex: 'productCode', width: '15%', align: 'center', sorter: true, customRender: function (text) { return text || '--' } },
+        { title: '产品名称', dataIndex: 'productName', width: '18%', align: 'center', customRender: function (text) { return text || '--' }, ellipsis: true },
+        { title: '原厂编码', dataIndex: 'productOrigCode', width: '10%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '品牌', dataIndex: 'brandName', width: '11%', align: 'center', sorter: true, customRender: function (text) { return text || '--' } },
+        { title: '仓库', dataIndex: 'warehouseName', width: '8%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '仓位', dataIndex: 'warehouseLocationName', width: '8%', align: 'center', customRender: function (text) { return text || '--' } }
+      ]
+      if (this.cost) {
+        arr.push({ slots: { title: 'costTitle' }, dataIndex: 'putCost', width: '8%', align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } })
+      }
+      if (this.cityPrice) {
+        arr.push({ title: '市级价', dataIndex: 'dealerProduct.cityPrice', width: '5%', align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } })
+      }
+      if (this.tyuePrice) {
+        arr.push({ title: '特约价', dataIndex: 'dealerProduct.specialPrice', width: '5%', align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } })
+      }
+      if (this.zdPrice) {
+        arr.push({ title: '终端价', dataIndex: 'dealerProduct.terminalPrice', width: '5%', align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } })
+      }
+
+      return arr.concat([
+        { title: '单位', dataIndex: 'unit', width: '4%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '售价', dataIndex: 'salePrice', scopedSlots: { customRender: 'salePrice' }, width: '7%', align: 'center' },
+        { title: '销售数量', dataIndex: 'salesNums', scopedSlots: { customRender: 'nums' }, width: '6%', align: 'center' },
+        { title: '库存数量', dataIndex: 'currentQty', width: '6%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
+        { title: '操作', dataIndex: 'action', scopedSlots: { customRender: 'action' }, width: '10%', align: 'center' }
+      ])
+    }
+  },
+  created () {
+    // 仓库
+    if (this.warehouseList.length == 0) {
+      this.getWarehouse()
+    }
+  },
+  methods: {
+    getList (params) {
+      const _this = this
+      return querySumByProductLocation(params).then(res => {
+        let data
+        this.onlyList = false
+        if (res.status == 200) {
+          data = res.data
+          data.list = data.list.filter(item => item != null)
+          const no = (data.pageNo - 1) * data.pageSize
+          for (var i = 0; i < data.list.length; i++) {
+            data.list[i].no = data.list[i].productSn + '_' + (no + i + 1)
+            data.list[i].salesNums = 1
+            data.list[i].currentQty = data.list[i].currentQty || 0
+            data.list[i].price = data.list[i].origSalePriceFlag == 0 ? data.list[i].lastSalePrice : data.list[i].origSalePriceFlag == 1 ? data.list[i].salePrice : data.list[i].selfSaleprice
+            data.list[i].productOrigCode = data.list[i].productOrigCode ? data.list[i].productOrigCode.trim() : ''
+          }
+          if (!params.vinCode) {
+            _this.vinInfoData = null
+          }
+        } else {
+          data = {
+            list: [],
+            pageNo: 1,
+            pageSize: 10
+          }
+        }
+        _this.disabled = false
+        console.log(data)
+        return data
+      })
+    },
+    // vin  change
+    vinCodeChange (e) {
+      if (e.target.value.length == 17) {
+        supperCodeByVin({ vin: e.target.value }).then(res => {
+          if (res.status == 200) {
+            this.queryParam.productCodeList = res.data
+          } else {
+            this.queryParam.productCodeList = undefined
+          }
+        })
+      } else {
+        this.queryParam.productCodeList = undefined
+      }
+    },
+    // 双击列表
+    handleClickRow (record) {
+      this.$emit('add', record)
+    },
+    //  重置
+    resetSearchForm () {
+      this.queryParam.productCode = ''
+      this.queryParam.productName = ''
+      this.queryParam.productOrigCode = ''
+      this.queryParam.brandSn = undefined
+      this.queryParam.productTypeSn1 = ''
+      this.queryParam.productTypeSn2 = ''
+      this.queryParam.productTypeSn3 = ''
+      this.queryParam.warehouseSn = undefined
+      this.queryParam.productCodeList = undefined
+      this.queryParam.existStockFlag = undefined
+      this.queryParam.vinCode = ''
+      this.productType = []
+      this.$refs.ruleForm.resetFields()
+      this.$refs.table.refresh(true)
+      this.vinInfoData = null
+    },
+    pageInit (buyerSn, priceType, salesBillSn) {
+      this.priceType = priceType || ''
+      this.buyerSn = buyerSn || ''
+      this.queryParam.salesBillSn = salesBillSn || ''
+      if (this.onlyList) { // 不清空查询条件
+        this.$refs.table.refresh()
+      } else {
+        this.resetSearchForm()
+      }
+      this.$refs.searchProductCode.focus()
+    },
+    // 刷新当前页面
+    resetCurForm () {
+      this.$refs.table.refresh()
+    },
+    // 清空数据
+    clearTable () {
+      this.vinInfoData = null
+      this.$refs.ruleForm.resetFields()
+      this.$refs.table.clearTable()
+    },
+    filterOption (input, option) {
+      return (
+        option.componentOptions.children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0
+      )
+    },
+    // 选择配件
+    handleAdd (row) {
+      const _this = this
+      console.log(row.price, row.lastSalePrice, row.salePrice, row.lastSalePrice < row.salePrice)
+      if (row.lastSalePrice && (row.price < row.salePrice)) {
+        _this.$confirm({
+          title: '提示',
+          content: '售价低于定价,是否仍继续添加?',
+          centered: true,
+          closable: true,
+          onOk () {
+            _this.$emit('add', row)
+          }
+        })
+      } else {
+        _this.$emit('add', row)
+      }
+    },
+    // 销售记录
+    handleDetail (row) {
+      this.openModal = true
+      this.$refs.salseRecord.getDetail(this.buyerSn, row.productSn, row)
+    },
+    //  关闭弹框
+    closeModal () {
+      this.openModal = false
+    },
+    uploadFun () {
+      document.getElementById('filed').click()
+    },
+    filePreview (e) {
+      const _this = this
+      var files = e.target.files[0]
+      const formData = new FormData()
+      formData.append('savePathType', 'local')
+      formData.append('file', files)
+      this.vinLoading = true
+      vinCodeParse(formData).then(res => {
+        if (res.type == 'application/json') {
+          var reader = new FileReader()
+          reader.addEventListener('loadend', function () {
+            const obj = JSON.parse(reader.result)
+            if (obj.status == 200) {
+              _this.queryParam.vinCode = obj.data || ''
+              // 移除表单项的校验结果
+              _this.$refs.ruleForm.clearValidate('vinCode')
+            } else {
+              _this.$notification.error({
+                message: '提示',
+                description: obj.message
+              })
+            }
+            _this.vinLoading = false
+            document.getElementById('filed').value = ''
+          })
+          reader.readAsText(res)
+        } else {
+          _this.vinLoading = false
+        }
+      })
+    },
+    // 仓库
+    getWarehouse () {
+      warehouseAllList({}).then(res => {
+        if (res.status == 200) {
+          this.warehouseList = res.data
+        } else {
+          this.warehouseList = []
+        }
+      })
+    },
+    //  产品分类  change
+    changeProductType (val, opt) {
+      this.queryParam.productTypeSn1 = val[0] ? val[0] : ''
+      this.queryParam.productTypeSn2 = val[1] ? val[1] : ''
+      this.queryParam.productTypeSn3 = val[2] ? val[2] : ''
+    },
+    // 查看是否有库存、
+    handleHasQty (val) {
+      this.queryParam.existStockFlag = val
+    }
+  },
+  watch: {
+    cost (newValue, oldValue) {
+      this.$emit('isCost', newValue)
+    }
+  }
+}
+</script>