Browse Source

新版采购单

lilei 2 years ago
parent
commit
8dd2e22574

BIN
public/templ/库存预警产品导入模板.xlsx


+ 1 - 1
public/version.json

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

+ 61 - 16
src/config/router.config.js

@@ -774,18 +774,65 @@ export const asyncRouterMap = [
                   permission: 'B_purchaseDetail'
                 }
               },
+            ]
+          },
+          {
+            path: '/purchasingManagement/purchaseOrderNew',
+            redirect: '/purchasingManagement/purchaseOrderNew/list',
+            name: 'purchaseOrderNew',
+            component: BlankLayout,
+            meta: {
+              title: '采购单管理(新版)',
+              icon: 'file-done',
+              permission: 'M_purchasingList'
+            },
+            hideChildrenInMenu: true,
+            children: [
+              {
+                path: 'list',
+                name: 'purchaseOrderNewList',
+                component: () => import(/* webpackChunkName: "purchasingManagement" */ '@/views/purchasingManagement/purchaseOrderNew/list.vue'),
+                meta: {
+                  title: '采购单列表',
+                  icon: 'file-done',
+                  hidden: true,
+                  permission: 'M_purchasingList'
+                }
+              },
+              {
+                path: 'add/:sn/:dealerSn',
+                name: 'purchaseOrderNewAdd',
+                component: () => import(/* webpackChunkName: "purchasingManagement" */ '@/views/purchasingManagement/purchaseOrderNew/edit.vue'),
+                meta: {
+                  title: '新增采购单',
+                  icon: 'file-done',
+                  hidden: true,
+                  permission: 'B_purchaseNew'
+                }
+              },
+              {
+                path: 'edit/:sn/:dealerSn',
+                name: 'purchaseOrderNewEdit',
+                component: () => import(/* webpackChunkName: "purchasingManagement" */ '@/views/purchasingManagement/purchaseOrderNew/edit.vue'),
+                meta: {
+                  title: '编辑采购单',
+                  icon: 'file-done',
+                  hidden: true,
+                  permission: 'B_purchaseEdit'
+                }
+              },
               {
-                path: 'warehousing/:sn',
-                name: 'purchaseOrderWarehousing',
-                component: () => import(/* webpackChunkName: "purchasingManagement" */ '@/views/purchasingManagement/purchaseOrder/warehousing.vue'),
+                path: 'detail/:sn',
+                name: 'purchaseOrderNewDetail',
+                component: () => import(/* webpackChunkName: "purchasingManagement" */ '@/views/purchasingManagement/purchaseOrderNew/detail.vue'),
                 meta: {
-                  title: '采购入库',
+                  title: '采购单详情',
                   icon: 'file-done',
                   hidden: true,
                   replaceTab: true,
-                  permission: 'B_purchaseReceiving'
+                  permission: 'B_purchaseDetail'
                 }
-              }
+              },
             ]
           },
           {
@@ -795,8 +842,8 @@ export const asyncRouterMap = [
             component: BlankLayout,
             meta: {
               title: '签收入库',
-              icon: 'money-collect'
-              // permission: 'M_signWarehousingList'
+              icon: 'money-collect',
+              permission: 'M_signWarehousingList'
             },
             hideChildrenInMenu: true,
             children: [
@@ -807,8 +854,8 @@ export const asyncRouterMap = [
                 meta: {
                   title: '签收入库列表',
                   icon: 'money-collect',
-                  hidden: true
-                  // permission: 'M_signWarehousingList'
+                  hidden: true,
+                  permission: 'M_signWarehousingList'
                 }
               },
               {
@@ -820,7 +867,6 @@ export const asyncRouterMap = [
                   icon: 'money-collect',
                   replaceTab: true,
                   hidden: true
-                  // permission: 'B_signWarehousingDetail'
                 }
               },
               {
@@ -832,7 +878,6 @@ export const asyncRouterMap = [
                   icon: 'money-collect',
                   replaceTab: true,
                   hidden: true
-                  // permission: 'B_signWarehousingStockOrderDetail'
                 }
               }
             ]
@@ -844,8 +889,8 @@ export const asyncRouterMap = [
             component: BlankLayout,
             meta: {
               title: '采购退货申请单',
-              icon: 'money-collect'
-              // permission: 'M_purchaseReturnApplyFormList'
+              icon: 'money-collect',
+              permission: 'M_purchaseReturnApplyFormList'
             },
             hideChildrenInMenu: true,
             children: [
@@ -856,8 +901,8 @@ export const asyncRouterMap = [
                 meta: {
                   title: '采购退货申请单列表',
                   icon: 'money-collect',
-                  hidden: true
-                  // permission: 'M_purchaseReturnApplyFormList'
+                  hidden: true,
+                  permission: 'M_purchaseReturnApplyFormList'
                 }
               },
               {

+ 252 - 0
src/views/common/receivingAddress/chooseAddressModal.vue

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

+ 265 - 0
src/views/common/receivingAddress/editAddressModal.vue

@@ -0,0 +1,265 @@
+<template>
+  <a-modal
+    centered
+    class="editAddress-modal"
+    :footer="null"
+    :maskClosable="false"
+    title="收货地址"
+    v-model="isShow"
+    @cancel="isShow=false"
+    :width="800">
+    <a-spin :spinning="spinning" tip="Loading...">
+      <a-form-model
+        id="editAddress-form"
+        ref="ruleForm"
+        :model="form"
+        :rules="rules"
+        :label-col="formItemLayout.labelCol"
+        :wrapper-col="formItemLayout.wrapperCol"
+      >
+        <a-form-model-item label="收货人" prop="consigneeName">
+          <a-input
+            id="editAddress-name"
+            :maxLength="30"
+            v-model.trim="form.consigneeName"
+            placeholder="请输入收货人(最多30个字符)"
+            allowClear />
+        </a-form-model-item>
+        <a-form-model-item label="联系电话" prop="consigneeTel">
+          <a-input
+            id="editAddress-phone"
+            :maxLength="30"
+            v-model.trim="form.consigneeTel"
+            placeholder="请输入联系电话(最多30个字符)"
+            allowClear />
+        </a-form-model-item>
+        <a-form-model-item label="所在地区" required style="margin: 0;">
+          <a-row :gutter="20">
+            <!-- 所在地区 -->
+            <a-col span="8">
+              <a-form-model-item prop="provinceSn">
+                <a-select id="editAddress-provinceSn" allowClear @change="getCityList" v-model="form.provinceSn" 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="citySn">
+                <a-select id="editAddress-citySn" allowClear @change="getAreaList" v-model="form.citySn" 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="countySn">
+                <a-select id="editAddress-countySn" allowClear @change="areaCharged" v-model="form.countySn" 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-form-model-item label="详细地址" prop="addr">
+          <a-input
+            id="editAddress-address"
+            :maxLength="60"
+            v-model.trim="form.addr"
+            placeholder="请输入详细地址(最多60个字符)"
+            allowClear />
+        </a-form-model-item>
+        <a-form-model-item :wrapper-col="{ span: 12, offset: 6 }" style="text-align: center;">
+          <a-button type="primary" @click="handleSubmit" id="editAddress-btn-submit">保存</a-button>
+          <a-button @click="isShow=false" style="margin-left: 15px" id="editAddress-btn-back">返回</a-button>
+        </a-form-model-item>
+      </a-form-model>
+    </a-spin>
+  </a-modal>
+</template>
+
+<script>
+import { commonMixin } from '@/utils/mixin'
+import { getArea } from '@/api/data'
+import { shippingAddressSave } from '@/api/shippingAddress.js'
+export default {
+  name: 'EditAddressModal',
+  mixins: [commonMixin],
+  props: {
+    openModal: { //  弹框显示状态
+      type: Boolean,
+      default: false
+    }
+  },
+  data () {
+    return {
+      spinning: false,
+      isShow: this.openModal, //  是否打开弹框
+      isEdit: false,
+      formItemLayout: {
+        labelCol: { span: 4 },
+        wrapperCol: { span: 18 }
+      },
+      form: {
+        consigneeName: '',
+        consigneeTel: '',
+        provinceSn: undefined,
+        provinceName: '',
+        citySn: undefined,
+        cityName: '',
+        countySn: undefined,
+        countyName: '',
+        addr: ''
+      },
+      rules: {
+        consigneeName: [
+          { required: true, message: '请输入收货人', trigger: 'change' }
+        ],
+        consigneeTel: [
+          { required: true, message: '请输入联系电话', trigger: 'change' }
+        ],
+        provinceSn: [
+          { required: true, message: '请选择省', trigger: 'change' }
+        ],
+        citySn: [
+          { required: true, message: '请选择市', trigger: 'change' }
+        ],
+        countySn: [
+          { required: true, message: '请选择区', trigger: 'change' }
+        ],
+        addr: [
+          { required: true, message: '请输入详细地址', trigger: 'change' }
+        ]
+      },
+      addrProvinceList: [], //  省下拉
+      addrCityList: [], //  市下拉
+      addrDistrictList: [] //  区下拉
+    }
+  },
+  methods: {
+    //  保存
+    handleSubmit () {
+      this.$refs.ruleForm.validate(valid => {
+        if (valid) {
+          this.spinning = true
+          shippingAddressSave(this.form).then(res => {
+            if (res.status == 200) {
+              this.isShow = false
+              this.$emit('ok')
+              this.$message.success(res.message)
+              this.spinning = false
+            } else {
+              this.spinning = false
+            }
+          })
+        } else {
+          console.log('error submit!!')
+          return false
+        }
+      })
+    },
+    // 获取城市列表
+    getCityList (val) {
+      this.addrCityList = []
+      this.addrDistrictList = []
+      this.form.citySn = undefined
+      this.form.countySn = undefined
+      if (val) {
+        this.getArea('city', val)
+        this.form.provinceName = this.addrProvinceList.find(item => item.areaSn == val).name
+      } else {
+        this.form.provinceName = ''
+      }
+    },
+    // 获取区县列表
+    getAreaList (val) {
+      this.addrDistrictList = []
+      this.form.countySn = undefined
+      if (val) {
+        this.getArea('district', val)
+        this.form.cityName = this.addrCityList.find(item => item.areaSn == val).name
+      } else {
+        this.form.cityName = ''
+      }
+    },
+    // 区县变更
+    areaCharged (val) {
+      if (val) {
+        this.form.countyName = this.addrDistrictList.find(item => item.areaSn == val).name
+      } else {
+        this.form.countyName = ''
+      }
+    },
+    //  省/市/区
+    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 = []
+          }
+        }
+      })
+    },
+    // 编辑数据
+    setData (data) {
+      this.isEdit = true
+      Promise.all([getArea({ type: '2' }), getArea({ parentId: data.provinceSn, type: '3' }), getArea({ parentId: data.citySn, type: '4' })]).then(res => {
+        console.log(res)
+        this.addrProvinceList = res[0].data
+        const provinceName = this.addrProvinceList.find(item => item.id == data.provinceSn)
+        if (provinceName && provinceName.name) {
+          this.form.provinceName = provinceName.name
+        }
+        this.addrCityList = res[1].data
+        const cityName = this.addrCityList.find(item => item.id == data.citySn)
+        if (cityName && cityName.name) {
+          this.form.cityName = cityName.name
+        }
+        this.addrDistrictList = res[2].data
+        const countyName = this.addrDistrictList.find(item => item.id == data.countySn)
+        if (countyName && countyName.name) {
+          this.form.countyName = countyName.name
+        }
+        this.form = Object.assign({}, this.form, data)
+      })
+    }
+  },
+  watch: {
+    //  父页面传过来的弹框状态
+    openModal (newValue, oldValue) {
+      this.isShow = newValue
+    },
+    //  重定义的弹框状态
+    isShow (newValue, oldValue) {
+      if (!newValue) {
+        this.$emit('close')
+        this.$refs.ruleForm.resetFields()
+        this.addrCityList = []
+        this.addrDistrictList = []
+        this.isEdit = false
+        delete this.form.id
+      } else {
+        if (!this.isEdit) {
+          this.getArea('province')
+        }
+      }
+    }
+  }
+}
+</script>

+ 3 - 14
src/views/purchasingManagement/purchaseOrder/list.vue

@@ -134,13 +134,6 @@
             v-if="(record.billStatus == 'WAIT_SUBMIT'||record.billStatus == 'AUDIT_REJECT') && $hasPermissions('B_purchaseEdit')"
             @click="handleEdit(record)"
           >编辑</a-button>
-          <!-- <a-button
-            size="small"
-            type="link"
-            class="button-warning"
-            v-if="record.billStatus == 'WAIT_PUT_WAREHOUSE'&&$hasPermissions('B_purchaseReceiving')"
-            @click="handleWarehouse(record)"
-          >签收入库</a-button> -->
           <a-button
             size="small"
             type="link"
@@ -171,7 +164,7 @@ export default {
   components: { STable, VSelect, basicInfoModal, rangeDate, stateIcon },
   mixins: [commonMixin],
   data () {
-    let _this=this
+    const _this = this
     return {
       spinning: false,
       advanced: true, //  高级搜索 展开/关闭
@@ -208,9 +201,9 @@ export default {
         { title: '供应商', dataIndex: 'purchaseTargetName', width: '10%', align: 'center', customRender: function (text) { return text || '--' }, ellipsis: true },
         { title: '产品款数', dataIndex: 'totalCategory', width: '6%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
         { title: '采购数量', dataIndex: 'totalQty', width: '6%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
-        { title: '采购金额', dataIndex: 'discountedAmount', width: '6%', align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text,2) : '--') } },
+        { title: '采购金额', dataIndex: 'discountedAmount', width: '6%', align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text, 2) : '--') } },
         { title: '审核数量', dataIndex: 'totalPushedQty', width: '6%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
-        { title: '审核金额', dataIndex: 'totalPushedAmount', width: '6%', align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text,2)  : '--') } },
+        { title: '审核金额', dataIndex: 'totalPushedAmount', width: '6%', align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text, 2) : '--') } },
         { title: '已取消数量', dataIndex: 'totalCancelQty', width: '7%', align: 'center', customRender: function (text) { return text || '--' } },
         { title: '采购状态', dataIndex: 'billStatusDictValue', width: '6%', align: 'center', customRender: function (text) { return text || '--' } },
         { title: '审核', scopedSlots: { customRender: 'audit' }, width: '3%', align: 'center' },
@@ -278,10 +271,6 @@ export default {
     handleDetail (row) {
       this.$router.push({ name: `purchaseOrderDetail`, params: { sn: row.purchaseBillSn } })
     },
-    //  签收入库
-    handleWarehouse (row) {
-      this.$router.push({ name: `purchaseOrderWarehousing`, params: { sn: row.purchaseBillSn } })
-    },
     //  删除
     handleDel (row) {
       const _this = this

+ 272 - 0
src/views/purchasingManagement/purchaseOrderNew/basicInfoModal.vue

@@ -0,0 +1,272 @@
+<template>
+  <a-modal
+    centered
+    class="purchaseOrder-basicInfo-modal"
+    :footer="null"
+    :maskClosable="false"
+    title="新增采购单"
+    v-model="isShow"
+    @cancel="isShow=false"
+    :width="800">
+    <a-spin :spinning="spinning" tip="Loading...">
+      <a-form-model
+        id="purchaseOrder-basicInfo-form"
+        ref="ruleForm"
+        :model="form"
+        :rules="rules"
+        :label-col="formItemLayout.labelCol"
+        :wrapper-col="formItemLayout.wrapperCol" >
+        <a-form-model-item label="供应商" prop="purchaseTargetSn">
+          <a-radio-group
+            name="radioGroup"
+            v-model="form.purchaseTargetSn"
+            @change="tragetTypeChange"
+            v-if="purchaseTragetType.length"
+            id="purchaseOrder-basicInfo-purchaseTargetSn" >
+            <a-radio v-for="item in purchaseTragetType" :key="item.purchaseTargetSn" :value="item.purchaseTargetSn" class="radio-s">{{ item.purchaseTargetName }}</a-radio>
+          </a-radio-group>
+          <span v-else>没有可选择的供应商</span>
+        </a-form-model-item>
+        <a-form-model-item label="支付方式" prop="settleStyleSn">
+          <v-select
+            code="SETTLE_STYLE"
+            id="purchaseOrder-basicInfo-settleStyleSn"
+            v-model="form.settleStyleSn"
+            allowClear
+            placeholder="请选择支付方式"
+          ></v-select>
+        </a-form-model-item>
+        <a-form-model-item label="收货地址" prop="consigneeTel">
+          {{ chooseAddr }}
+          <a-button type="link" id="purchaseOrder-basicInfo-chooseAddr" @click="handleChoose">{{ addressVal }} >></a-button>
+        </a-form-model-item>
+        <a-form-model-item :wrapper-col="{ span: 12, offset: 6 }" style="text-align: center;">
+          <a-button type="primary" :loading="confirmLoading" @click="handleSubmit" id="chooseCustom-btn-submit">保存</a-button>
+          <a-button @click="isShow=false" style="margin-left: 15px" id="chooseCustom-btn-back">取消</a-button>
+        </a-form-model-item>
+      </a-form-model>
+    </a-spin>
+    <!-- 选择地址 -->
+    <choose-address-modal :openModal="openAddrModal" @ok="handleOk" @verify="verifyFun" @close="openAddrModal=false" />
+  </a-modal>
+</template>
+
+<script>
+import { commonMixin } from '@/utils/mixin'
+import { VSelect } from '@/components'
+import chooseAddressModal from '@/views/common/receivingAddress/chooseAddressModal.vue'
+import { shippingAddressQuery } from '@/api/shippingAddress'
+import { purchaseSave, purchaseTargetList } from '@/api/purchase'
+export default {
+  name: 'BasicInfoModal',
+  components: { VSelect, chooseAddressModal },
+  mixins: [commonMixin],
+  props: {
+    openModal: { //  弹框显示状态
+      type: Boolean,
+      default: false
+    }
+  },
+  data () {
+    return {
+      spinning: false,
+      confirmLoading: false,
+      isShow: this.openModal, //  是否打开弹框
+      formItemLayout: {
+        labelCol: { span: 4 },
+        wrapperCol: { span: 18 }
+      },
+      form: {
+        purchaseTargetType: '', // 供应商
+        shippingAddressProvinceName: '', // 省
+        shippingAddressCityName: '', // 市
+        shippingAddressCountyName: '', // 区
+        shippingAddress: '', // 详细地址
+        consigneeTel: '', // 联系电话
+        consigneeName: '', // 联系人名称
+        settleStyleSn: undefined, //  支付方式
+        purchaseTargetSn: undefined,
+        purchaseTargetName: ''
+      },
+      rules: {
+        purchaseTargetSn: [
+          { required: true, message: '请选择供应商', trigger: 'change' }
+        ],
+        settleStyleSn: [
+          { required: true, message: '请选择支付方式', trigger: 'change' }
+        ],
+        consigneeTel: [
+          { required: true, message: '请选择收货地址(联系电话不能为空)', trigger: 'change' }
+        ]
+      },
+      purchaseTragetType: [],
+      addressVal: '选择地址', //  选择地址/更换地址
+      chooseAddr: '', //  当前已选地址信息
+      addressId: undefined,
+      openAddrModal: false // 选择地址弹框是否显示
+    }
+  },
+  methods: {
+    resetForm () {
+      this.$refs.ruleForm.resetFields()
+      this.chooseAddr = ''
+      this.addressVal = '选择地址'
+      this.form.shippingAddressProvinceName = ''// 省
+      this.form.shippingAddressCityName = '' // 市
+      this.form.shippingAddressCountyName = '' // 区
+      this.form.shippingAddress = ''// 详细地址
+      this.form.consigneeTel = '' // 联系电话
+      this.form.consigneeName = ''
+      this.form.purchaseTargetType = ''
+      this.form.purchaseTargetSn = undefined
+      this.form.purchaseTargetName = ''
+    },
+    // 供应商change
+    tragetTypeChange (e) {
+      const val = e.target.value
+      const ind = this.purchaseTragetType.findIndex(item => item.purchaseTargetSn == val)
+      if (ind != -1) {
+        this.form.purchaseTargetType = this.purchaseTragetType[ind].purchaseTargetType
+        this.form.purchaseTargetName = this.purchaseTragetType[ind].purchaseTargetName
+      }
+    },
+    //  保存
+    handleSubmit (e) {
+      e.preventDefault()
+      const _this = this
+      this.$refs.ruleForm.validate(valid => {
+        if (valid) {
+          if (_this.form.consigneeTel == '') {
+            _this.$message.info('请选择收货地址')
+            return false
+          }
+          _this.spinning = true
+          purchaseSave(_this.form).then(res => {
+            if (res.status == 200) {
+              _this.isShow = false
+              _this.$emit('ok', res.data)
+              _this.spinning = false
+              _this.$message.info(res.message)
+            } else {
+              _this.spinning = false
+            }
+          })
+        } else {
+          return false
+        }
+      })
+    },
+    //  选择地址
+    handleChoose () {
+      this.openAddrModal = true
+    },
+    //  地址保存
+    handleOk (data) {
+      this.chooseAddr = (data.consigneeName || '') + '(' + (data.consigneeTel || '--') + ')' + ' ' + (data.address || '')
+      this.addressVal = '更换地址'
+      this.form.shippingAddressProvinceName = data.provinceName // 省
+      this.form.shippingAddressCityName = data.cityName // 市
+      this.form.shippingAddressCountyName = data.countyName // 区
+      this.form.shippingAddress = data.addr// 详细地址
+      this.form.consigneeTel = data.consigneeTel // 联系电话
+      this.form.consigneeName = data.consigneeName
+      this.openAddrModal = false
+    },
+    // 编辑信息
+    setData (data) {
+      this.form = JSON.parse(JSON.stringify(data))
+      this.chooseAddr = data.consigneeName + '(' + (data.consigneeTel || '--') + ')' + ' ' + data.shippingAddressProvinceName + '-' + data.shippingAddressCityName + '-' + data.shippingAddressCountyName + ' ' + data.shippingAddress
+      this.addressVal = '更换地址'
+    },
+    getParentDealer () {
+      const zb = this.$hasPermissions('B_SUPPLIER_ZB')
+      const sj = this.$hasPermissions('B_SUPPLIER_SJ')
+      let params = {}
+      // 只能向上级采购
+      if (sj) {
+        params.purchaseTargetType = 'DEALER_UP'
+      }
+      // 只能向总部采购
+      if (zb) {
+        params.purchaseTargetType = 'SUPPLIER_SYS'
+      }
+      // 总部和上级都可以
+      if (sj && zb) {
+        params = {}
+      }
+      purchaseTargetList(params).then(res => {
+        if (res.status == 200 && res.data[0]) {
+          this.purchaseTragetType = res.data
+        } else {
+          this.purchaseTragetType = []
+        }
+      })
+    },
+    // 获取默认地址
+    getDefaultAddress () {
+      shippingAddressQuery({ defaultFlag: 1 }).then(res => {
+        if (res.status == 200) {
+          if (res.data.length == 1) {
+            res.data[0].address = ''
+            if (res.data[0].provinceName) {
+              res.data[0].address += res.data[0].provinceName + '-'
+            }
+            if (res.data[0].cityName) {
+              res.data[0].address += res.data[0].cityName + '-'
+            }
+            if (res.data[0].countyName) {
+              res.data[0].address += res.data[0].countyName + '-'
+            }
+            res.data[0].address += res.data[0].addr
+            this.addressId = res.data[0].id || undefined
+            this.handleOk(res.data[0])
+          }
+        }
+      })
+    },
+    verifyFun (id) {
+      if (id == this.addressId) {
+        this.chooseAddr = ''
+        this.addressVal = '选择地址'
+        this.form.shippingAddressProvinceName = ''// 省
+        this.form.shippingAddressCityName = '' // 市
+        this.form.shippingAddressCountyName = '' // 区
+        this.form.shippingAddress = ''// 详细地址
+        this.form.consigneeTel = '' // 联系电话
+        this.form.consigneeName = ''
+      }
+    }
+  },
+  watch: {
+    //  父页面传过来的弹框状态
+    openModal (newValue, oldValue) {
+      this.isShow = newValue
+    },
+    //  重定义的弹框状态
+    isShow (newValue, oldValue) {
+      if (!newValue) {
+        this.$emit('close')
+        this.resetForm()
+      } else {
+        this.getParentDealer()
+        this.getDefaultAddress()
+      }
+    }
+  }
+}
+</script>
+
+<style lang="less">
+  .purchaseOrder-basicInfo-modal{
+    .ant-modal-body {
+      padding: 40px 40px 24px;
+    }
+    .radio-s{
+      margin-bottom: 8px;
+    }
+    .btn-cont {
+      text-align: center;
+      margin: 35px 0 10px;
+    }
+  }
+</style>

+ 217 - 0
src/views/purchasingManagement/purchaseOrderNew/chooseImportModal.vue

@@ -0,0 +1,217 @@
+<template>
+  <a-modal
+    centered
+    class="chooseImport-modal"
+    :footer="null"
+    :maskClosable="false"
+    title="导入"
+    :closable="false"
+    v-model="isShow"
+    @cancel="isShow=false"
+    :width="900">
+    <a-spin :spinning="spinning" tip="Loading...">
+      <div class="chooseImport-con">
+        <!-- 可导入数据 -->
+        <p class="chooseImport-tit">可导入数据{{ loadData.length }}条</p>
+        <a-table
+          class="sTable"
+          ref="table"
+          size="small"
+          :rowKey="(record) => record.purchaseBillSn"
+          :columns="nowColumns"
+          :dataSource="loadData"
+          :loading="loading"
+          :scroll="{ y: 200 }"
+          :pagination="false"
+          bordered>
+        </a-table>
+        <a-divider />
+        <!-- 不可导入数据 -->
+        <p class="chooseImport-tit red">不可导入数据{{ unLoadData.length }}条</p>
+        <a-table
+          class="unTable sTable"
+          ref="unTable"
+          size="small"
+          :rowClassName="(record, index) => 'yellowBg-row'"
+          :rowKey="(record) => record.errorDesc"
+          :columns="nowUnColumns"
+          :dataSource="unLoadData"
+          :loading="loading"
+          :scroll="{ y: 200 }"
+          :pagination="false"
+          bordered>
+        </a-table>
+        <!-- 按钮 -->
+        <div class="btn-con">
+          <a-button
+            type="primary"
+            id="chooseImport-submit"
+            size="large"
+            :class="loadData.length==0?'button-grey':'button-primary'"
+            @click="handleSubmit"
+            style="padding: 0 60px;">确认导入</a-button>
+          <a-button
+            id="chooseImport-cancel"
+            size="large"
+            class="button-cancel"
+            @click="isShow=false"
+            style="padding: 0 60px;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-spin>
+  </a-modal>
+</template>
+
+<script>
+import { commonMixin } from '@/utils/mixin'
+import { hdPrint } from '@/libs/JGPrint'
+import { purchaseDetailParseProducts, purchaseDetailBatchInsert } from '@/api/purchase'
+import { purchaseDetailDownloadFail } from '@/api/purchaseDetail'
+export default {
+  name: 'ChooseImportModal',
+  mixins: [commonMixin],
+  props: {
+    openModal: { //  弹框显示状态
+      type: Boolean,
+      default: false
+    },
+    paramsData: {
+      type: Object,
+      default: () => {
+        return {}
+      }
+    }
+  },
+  data () {
+    return {
+      spinning: false,
+      isShow: this.openModal, //  是否打开弹框
+      nowColumns: [ //  正品
+        { title: '序号', dataIndex: 'no', width: '15%', align: 'center' },
+        { title: '产品编码', dataIndex: 'productCode', width: '27%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '产品名称', dataIndex: 'productName', width: '28%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '数量', dataIndex: 'qtyText', width: '15%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
+        { title: '单位', dataIndex: 'productUnit', width: '15%', align: 'center', customRender: function (text) { return text || '--' } }
+      ],
+      nowUnColumns: [ //  促销品
+        { title: '序号', dataIndex: 'no', width: '13%', align: 'center' },
+        { title: '产品编码', dataIndex: 'productCode', width: '26%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '产品名称', dataIndex: 'productName', width: '26%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '数量', dataIndex: 'qtyText', width: '15%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
+        { title: '单位', dataIndex: 'productUnit', width: '15%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '备注', dataIndex: 'errorDesc', width: '30%', align: 'center', customRender: function (text) { return text || '--' } }
+      ],
+      loadData: [],
+      unLoadData: [],
+      loading: false
+    }
+  },
+  methods: {
+    getData () {
+      const _this = this
+      this.loading = true
+      purchaseDetailParseProducts(this.paramsData).then(res => {
+        this.loading = false
+        if (res.status == 200) {
+          if (res.data.okList && res.data.okList.length > 0) {
+            res.data.okList.map((item, index) => {
+              item.no = index + 1
+            })
+          }
+          if (res.data.failList && res.data.failList.length > 0) {
+            res.data.failList.map((item, index) => {
+              item.no = index + 1
+            })
+          }
+          _this.loadData = res.data.okList || []
+          _this.unLoadData = res.data.failList || []
+        }
+      })
+    },
+    // 确认导入
+    handleSubmit () {
+      if (this.loadData.length == 0) {
+        this.$message.warning('无可导入产品!')
+      } else {
+        this.spinning = true
+        purchaseDetailBatchInsert(this.loadData).then(res => {
+          this.spinning = false
+          if (res.status == 200) {
+            this.$emit('ok', '')
+            this.isShow = false
+          }
+        })
+      }
+    },
+    // 导出
+    handleError () {
+      const _this = this
+      if (_this.unLoadData.length < 1) {
+        _this.$message.info('暂无可导出错误项~')
+        return
+      }
+      _this.spinning = true
+      // 导出
+      hdPrint('', 'export', purchaseDetailDownloadFail, _this.unLoadData, '产品导入错误项', function () {
+        _this.spinning = false
+      })
+    }
+  },
+  watch: {
+    //  父页面传过来的弹框状态
+    openModal (newValue, oldValue) {
+      this.isShow = newValue
+    },
+    //  重定义的弹框状态
+    isShow (newValue, oldValue) {
+      if (!newValue) {
+        this.$emit('close')
+        this.loadData = []
+        this.unLoadData = []
+      } else {
+        this.getData()
+      }
+    }
+  }
+}
+</script>
+
+<style lang="less">
+  .chooseImport-modal{
+    .chooseImport-con{
+      .chooseImport-tit{
+        font-size: 14px;
+        font-weight: bold;
+      }
+      .unTable{
+        box-shadow: 0px 0px 4px rgb(89,89,89,.9);
+        .ant-table-bordered .ant-table-tbody > tr > td, .ant-table-bordered .ant-table-thead > tr > th{
+          border-right: 1px solid #595959;
+        }
+        .ant-table-tbody > tr > td, .ant-table-thead > tr > th{
+          border-bottom: 1px solid #595959;
+        }
+      }
+      .red{
+        color: #f30;
+      }
+      .btn-con{
+        text-align: center;
+        margin: 30px 0 20px;
+        .button-cancel{
+          font-size: 12px;
+        }
+      }
+    }
+  }
+  .yellowBg-row{
+    background-color: #ffe58f;
+  }
+</style>

+ 303 - 0
src/views/purchasingManagement/purchaseOrderNew/detail.vue

@@ -0,0 +1,303 @@
+<template>
+  <div class="purchaseOrderDetail-wrap">
+    <a-spin :spinning="spinning" tip="Loading...">
+      <a-page-header :ghost="false" :backIcon="false" @back="handleBack" class="purchaseOrderDetail-cont" :style="{ padding: !outBizSn ? '16px 24px' : '0px 24px' }">
+        <!-- 自定义的二级文字标题 -->
+        <template slot="subTitle">
+          <a id="purchaseOrderDetail-back-btn" href="javascript:;" @click="handleBack" v-if="!outBizSn"><a-icon type="left" /> 返回列表</a>
+          <span class="billno">单号:{{ detail&&detail.purchaseBillNo }}</span>
+          <a-tag color="blue" v-if="detail&&detail.billStatusDictValue">{{ detail&&detail.billStatusDictValue }}</a-tag>
+          <a-tag color="orange" v-if="detail&&detail.financialStatusDictValue">{{ detail&&detail.financialStatusDictValue }}</a-tag>
+          <span class="billno" v-if="detail&&detail.purchaseBillNoSource" style="font-size: 14px;margin: 0;">(原:{{ detail&&detail.purchaseBillNoSource }})</span>
+        </template>
+        <!-- 操作区,位于 title 行的行尾 -->
+        <template slot="extra">
+          <Print v-if="$hasPermissions('B_purchasePrint')" :disabled="localDataSource.length==0" @handlePrint="handlePrint"></Print>
+          <a-button
+            key="1"
+            v-if="$hasPermissions('B_purchaseExportProduct') && (detail&&(detail.billStatus=='AUDIT_PASS' || detail.billStatus=='CANCEL' || detail.billStatus=='WAIT_PUT_WAREHOUSE' || detail.billStatus=='WAIT_PUT_WAREHOUSE_AUDIT' || detail.billStatus=='FINISH'))"
+            type="primary"
+            class="button-info"
+            id="purchaseOrderDetail-export-btn"
+            :disabled="localDataSource.length==0"
+            @click="handleExportProduct()">导出审核订单产品</a-button>
+        </template>
+      </a-page-header>
+      <!-- 基础信息 -->
+      <a-card size="small" :bordered="false" class="purchaseOrderDetail-cont">
+        <a-collapse :activeKey="['1']">
+          <a-collapse-panel key="1" header="基础信息">
+            <a-descriptions :column="3">
+              <a-descriptions-item label="供应商">{{ (detail&&detail.purchaseTargetName) || '--' }}</a-descriptions-item>
+              <a-descriptions-item label="支付方式">{{ (detail&&detail.settleStyleSnDictValue) || '--' }}</a-descriptions-item>
+              <a-descriptions-item label="采购员工" v-if="detail&&detail.purchaseBillSource=='PURCHASE'">{{ detail&&detail.operatorName || '--' }}</a-descriptions-item>
+              <a-descriptions-item label="收货人">{{ detail&&detail.consigneeName || '--' }}<span v-if="detail&&detail.consigneeTel">({{ detail&&detail.consigneeTel }})</span></a-descriptions-item>
+              <a-descriptions-item label="收货地址">
+                <div v-if="detail&&(detail.shippingAddressProvinceName || detail.shippingAddressCityName || detail.shippingAddressCountyName || detail.shippingAddress)">
+                  {{ detail&&detail.shippingAddressProvinceName || '' }}
+                  {{ detail&&detail.shippingAddressCityName || '' }}
+                  {{ detail&&detail.shippingAddressCountyName || '' }}
+                  {{ detail&&detail.shippingAddress || '' }}
+                </div>
+                <span v-else>--</span>
+              </a-descriptions-item>
+              <a-descriptions-item label="备注">{{ (detail&&detail.remarks) || '--' }}</a-descriptions-item>
+            </a-descriptions>
+          </a-collapse-panel>
+        </a-collapse>
+      </a-card>
+      <!-- 产品详情 -->
+      <a-card size="small" :bordered="false" class="purchaseOrderDetail-cont">
+        <a-collapse :activeKey="['1']">
+          <a-collapse-panel key="1" header="产品详情">
+            <!-- 总计 -->
+            <a-alert type="info" style="margin-bottom:10px">
+              <div slot="message">
+                产品款数:<strong>{{ detail && (detail.totalCategory || detail.totalCategory==0) ? detail.totalCategory : '--' }}</strong>,
+                采购数量合计:<strong>{{ detail && (detail.totalQty || detail.totalQty==0) ? detail.totalQty : '--' }}</strong>,
+                审核订单数量:<strong>{{ detail && (detail.totalPushedQty || detail.totalPushedQty==0) ? detail.totalPushedQty : '--' }}</strong>,
+                已取消数量:<strong>{{ detail && (detail.totalCancelQty || detail.totalCancelQty==0) ? detail.totalCancelQty : '--' }}</strong>,
+                <div style="display: inline-block;" v-if="$hasPermissions('M_ShowAllCost')">
+                  采购金额合计:<strong>{{ detail && (detail.discountedAmount || detail.discountedAmount==0) ? toThousands(detail.discountedAmount,2) : '--' }}</strong>,
+                  审核订单金额:<strong>{{ detail && (detail.totalPushedAmount || detail.totalPushedAmount==0) ? toThousands(detail.totalPushedAmount,2) : '--' }}</strong>,
+                  已取消金额:<strong>{{ detail && (detail.totalCancelAmount || detail.totalCancelAmount==0) ? toThousands(detail.totalCancelAmount,2) : '--' }}</strong>
+                </div>
+              </div>
+            </a-alert>
+            <!-- 列表 -->
+            <s-table
+              class="sTable"
+              ref="table"
+              size="small"
+              :rowKey="(record) => record.id"
+              :columns="columns"
+              :data="loadData"
+              :defaultLoadData="false"
+              bordered>
+              <!-- 采购数量 -->
+              <template slot="origqty" slot-scope="text, record">
+                <div>{{ text }}</div>
+                <div v-if="record.origqty">原采购数量:{{ record.origqty }}</div>
+              </template>
+              <!-- 已取消数量 -->
+              <template slot="outOfStockNum" slot-scope="text, record">
+                <span>{{ record.outOfStockNum }}</span>
+              </template>
+            </s-table>
+          </a-collapse-panel>
+        </a-collapse>
+      </a-card>
+      <!-- 促销品详情 -->
+      <a-card size="small" v-if="false" :bordered="false" class="purchaseOrderDetail-cont">
+        <a-collapse :activeKey="['1']">
+          <a-collapse-panel key="1" header="促销品详情">
+            <!-- 总计 -->
+            <a-alert type="info" style="margin-bottom:10px">
+              <div slot="message">产品款数 <strong>{{ detail&&(detail.totalCategory || detail.totalCategory==0) ? detail.totalCategory : '--' }}</strong> ,
+                采购数量合计 <strong>{{ detail&&(detail.totalQty || detail.totalQty==0) ? detail.totalQty : '--' }}</strong> ,
+                采购金额合计 <strong>{{ detail&&(detail.totalAmount || detail.totalAmount==0) ? toThousands(detail.totalAmount,2) : '--' }}</strong></div>
+            </a-alert>
+            <!-- 列表 -->
+            <s-table
+              class="sTable"
+              ref="table-1"
+              size="small"
+              :rowKey="(record) => record.id"
+              :columns="columns"
+              :data="loadData"
+              :scroll="{ x: 1060 }"
+              bordered>
+              <!-- 采购数量 -->
+              <template slot="origqty" slot-scope="text, record">
+                <div>{{ text }}</div>
+                <div v-if="record.origqty">原采购数量:{{ record.origqty }}</div>
+              </template>
+              <!-- 已取消数量 -->
+              <template slot="outOfStockNum" slot-scope="text, record">
+                <span>{{ record.outOfStockNum }}</span>
+              </template>
+            </s-table>
+          </a-collapse-panel>
+        </a-collapse>
+      </a-card>
+      <!-- 单据记录 -->
+      <a-card size="small" v-if="false" :bordered="false" class="purchaseOrderDetail-cont">
+        <a-collapse :activeKey="['1']">
+          <a-collapse-panel key="1" header="单据记录">
+            <a-timeline class="timeline-box">
+              <a-timeline-item>2021-02-01 15:22:38   王凯   审核通过</a-timeline-item>
+              <a-timeline-item>
+                <p>2021-02-01 15:22:38   王凯   审核通过</p>
+                <p class="auxiliary-txt">产品编号JA-11076P的采购数量,由【10】修改为【5】</p>
+                <p class="auxiliary-txt">产品编号JA-11076P的采购数量,由【10】修改为【5】</p>
+              </a-timeline-item>
+              <a-timeline-item>Technical testing 2015-09-01</a-timeline-item>
+              <a-timeline-item>Network problems being solved 2015-09-01</a-timeline-item>
+            </a-timeline>
+          </a-collapse-panel>
+        </a-collapse>
+      </a-card>
+    </a-spin>
+  </div>
+</template>
+
+<script>
+import { commonMixin } from '@/utils/mixin'
+import { STable, VSelect } from '@/components'
+import { purchaseDetailBySn, purchaseDetailPrint, purchaseDetailExport, purchaseExportDetail } from '@/api/purchase'
+import { purchaseDetailList } from '@/api/purchaseDetail'
+import Print from '@/views/common/print.vue'
+import { hdPrint, downloadExcel } from '@/libs/JGPrint'
+export default {
+  name: 'PurchaseDetail',
+  components: { STable, VSelect, Print },
+  mixins: [commonMixin],
+  props: {
+    outBizSn: { //  有值则为弹框,无值则为页面
+      type: [Number, String],
+      default: ''
+    }
+  },
+  data () {
+    return {
+      spinning: false,
+      // 加载数据方法 必须为 Promise 对象
+      loadData: parameter => {
+        this.disabled = true
+        return purchaseDetailList(Object.assign(parameter, { purchaseBillSn: this.outBizSn || this.$route.params.sn, orderBy: 'product_type.FIRST_CHAR,dealer_product.CODE' })).then(res => {
+          let data
+          if (res.status == 200) {
+            data = res.data
+            const no = (data.pageNo - 1) * data.pageSize
+            for (var i = 0; i < data.list.length; i++) {
+              data.list[i].no = no + i + 1
+            }
+            this.localDataSource = data.list
+            this.disabled = false
+          }
+          return data
+        })
+      },
+      detail: null, //  详情数据
+      localDataSource: [],
+      printerType: 'NEEDLE' //  打印机类型
+    }
+  },
+  computed: {
+    columns () {
+      let _this=this
+      const arr = [
+        { title: '序号', dataIndex: 'no', width: '4%', align: 'center' },
+        { title: '产品编码', dataIndex: 'dealerProductEntity.code', width: '16%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '产品名称', dataIndex: 'dealerProductEntity.name', width: '16%', align: 'center', customRender: function (text) { return text || '--' }, ellipsis: true },
+        { title: '原厂编码', dataIndex: 'dealerProductEntity.origCode', width: '15%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '单位', dataIndex: 'dealerProductEntity.unit', width: '5%', align: 'center', customRender: function (text) { return text || '--' } },
+        // { title: '采购单价', dataIndex: 'discountedPrice', width: '7%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
+        // { title: '采购金额', dataIndex: 'discountedAmount', width: '7%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
+        { title: '采购数量', dataIndex: 'qty', width: '7%', align: 'center', scopedSlots: { customRender: 'origqty' } },
+        // { title: '审核订单金额', dataIndex: 'pushedAmount', width: '8%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
+        { title: '审核订单数量', dataIndex: 'pushedQty', width: '8%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
+        { title: '已取消数量', dataIndex: 'cancelQty', width: '7%', align: 'center', customRender: function (text) { return text || '--' } }
+      ]
+      if (this.$hasPermissions('M_ShowAllCost')) {
+        arr.splice(5, 0, { title: '采购单价', dataIndex: 'discountedPrice', width: '7%', align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text,2) : '--') } })
+        arr.splice(6, 0, { title: '采购金额', dataIndex: 'discountedAmount', width: '7%', align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text,2) : '--') } })
+        arr.splice(8, 0, { title: '审核订单金额', dataIndex: 'pushedAmount', width: '8%', align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text,2) : '--') } })
+      }
+      return arr
+    }
+  },
+  methods: {
+    //  返回列表
+    handleBack () {
+      if (this.$route.query.pageType) {
+        this.$router.push({ name: this.$route.query.pageType })
+      } else {
+        this.$router.push({ name: 'purchaseOrderNewList' })
+      }
+    },
+    //  详情
+    getDetail () {
+      purchaseDetailBySn({ sn: this.outBizSn || this.$route.params.sn }).then(res => {
+        if (res.status == 200) {
+          this.detail = res.data
+        } else {
+          this.detail = null
+        }
+      })
+    },
+    // 打印预览/快捷打印
+    handlePrint (type, printerType) {
+      const _this = this
+      _this.spinning = true
+      let url = purchaseDetailPrint
+      let params = { sn: this.outBizSn || this.$route.params.sn, type: printerType }
+      if (type == 'export') { //  导出
+        url = purchaseDetailExport
+        params = { sn: this.outBizSn || this.$route.params.sn }
+      }
+      // 打印或导出
+      hdPrint(printerType, type, url, params, '采购单', function () {
+        _this.spinning = false
+      })
+    },
+    // 导出产品
+    handleExportProduct () {
+      const _this = this
+      _this.spinning = true
+      purchaseExportDetail({ sn: this.outBizSn || this.$route.params.sn }).then(res => {
+        _this.spinning = false
+        if (res.type == 'application/json') {
+          var reader = new FileReader()
+          reader.addEventListener('loadend', function () {
+            const obj = JSON.parse(reader.result)
+            _this.$notification.error({
+              message: '提示',
+              description: obj.message
+            })
+          })
+          reader.readAsText(res)
+        } else {
+          downloadExcel(res, '采购产品')
+        }
+      })
+    }
+  },
+  mounted () {
+    if (!this.$store.state.app.isNewTab || this.outBizSn) { // 页签刷新时调用
+      this.$refs.table.refresh(true)
+      this.getDetail()
+    }
+  },
+  activated () {
+    console.log(this.$store.state.app.isNewTab, !this.$store.state.app.isNewSubTab)
+    // 如果是新页签打开或者进入新的子页(例:存在列表第2条数据编辑页页签时再打开第4条数据的编辑页),则重置当前页面
+    if (this.$store.state.app.isNewTab || !this.$store.state.app.isNewSubTab) {
+      this.$refs.table.refresh(true)
+      this.getDetail()
+    }
+  },
+  beforeRouteEnter (to, from, next) {
+    next(vm => {})
+  }
+}
+</script>
+
+<style lang="less">
+  .purchaseOrderDetail-cont{
+    margin-bottom: 10px;
+    .timeline-box{
+      margin-top: 30px;
+      .auxiliary-txt{
+        color: #808695;
+      }
+    }
+  }
+  .purchaseOrderDetail-wrap{
+    .billno{
+      font-size: 16px;
+      font-weight: bold;
+      margin: 0 15px;
+    }
+  }
+</style>

+ 695 - 0
src/views/purchasingManagement/purchaseOrderNew/edit.vue

@@ -0,0 +1,695 @@
+<template>
+  <div v-if="showPage" class="purchaseOrderEdit-wrap">
+    <a-spin :spinning="spinning" tip="Loading...">
+      <a-page-header :ghost="false" :backIcon="false" class="purchaseOrderEdit-cont">
+        <!-- 自定义的二级文字标题 -->
+        <template slot="subTitle">
+          <a id="purchaseOrderEdit-back-btn" href="javascript:;" @click="handleBack"><a-icon type="left" /> 返回列表</a>
+          <p class="billno">单号:{{ detail&&detail.purchaseBillNo }}</p>
+          <a-button type="primary" ghost @click="isShowBisiceInfo=!isShowBisiceInfo" style="margin-left:30px;vertical-align:middle;">
+            基础信息
+            <a-icon :type="isShowBisiceInfo ? 'up' : 'down'"/>
+          </a-button>
+        </template>
+        <!-- 操作区,位于 title 行的行尾 -->
+        <template slot="extra" v-if="$hasPermissions('B_purchasePrint')">
+          <Print :disabled="localDataSource.length==0" @handlePrint="handlePrint"></Print>
+        </template>
+      </a-page-header>
+      <!-- 基础信息 -->
+      <div v-if="isShowBisiceInfo" class="purchaseOrderEdit-cont">
+        <a-collapse :activeKey="['1']">
+          <a-collapse-panel key="1" :show-arrow="false" :disabled="true">
+            <template slot="header">
+              基础信息
+            </template>
+            <a-row :gutter="16" type="flex" sjustify="center">
+              <a-col class="gutter-row" :span="12">
+                供应商:{{ detail&&detail.purchaseTargetName || '--' }}
+              </a-col>
+              <a-col class="gutter-row" :span="12">
+                支付方式:{{ detail&&detail.settleStyleSnDictValue || '--' }}
+              </a-col>
+              <a-col class="gutter-row" :span="12">
+                收货人:{{ detail&&detail.consigneeName || '--' }}({{ detail&&detail.consigneeTel || '--' }})
+              </a-col>
+              <a-col class="gutter-row" :span="12">
+                <span>收货地址:</span>
+                <div style="display: inline-block;width:90%;vertical-align: top;" v-if="detail&&(detail.shippingAddressProvinceName || detail.shippingAddressCityName || detail.shippingAddressCountyName || detail.shippingAddress)">
+                  {{ detail&&detail.shippingAddressProvinceName || '' }}
+                  {{ detail&&detail.shippingAddressCityName || '' }}
+                  {{ detail&&detail.shippingAddressCountyName || '' }}
+                  {{ detail&&detail.shippingAddress || '' }}
+                  <a-button type="link" @click="openAddrModal=true">更换地址 >></a-button>
+                </div>
+                <div v-else><a-button type="link" @click="openAddrModal=true">选择地址 >></a-button></div>
+              </a-col>
+            </a-row>
+          </a-collapse-panel>
+        </a-collapse>
+      </div>
+      <!-- 选择产品 -->
+      <div class="purchaseOrderEdit-cont">
+        <a-collapse :activeKey="['1']">
+          <a-collapse-panel key="1">
+            <template slot="header">
+              <div style="display: flex;">
+                选择产品<span class="sub-title">①输入查询条件--->②查找到需要采购的产品--->③录入采购数量--->④点击“添加”</span>
+                <p class="tag-txt">注意:仅限采购【箭冠】产品。自建产品的采购入库请使用“散件入库”功能</p>
+              </div>
+            </template>
+            <!-- 选择产品 -->
+            <div>
+              <!-- 搜索条件 -->
+              <div class="table-page-search-wrapper">
+                <a-form layout="inline" @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="purchaseOrderEdit-code" ref="searchProductCode" v-model.trim="queryParam.code" allowClear placeholder="请输入产品编码"/>
+                      </a-form-model-item>
+                    </a-col>
+                    <a-col :md="4" :sm="24">
+                      <a-form-model-item label="产品名称">
+                        <a-input id="purchaseOrderEdit-name" v-model.trim="queryParam.name" allowClear placeholder="请输入产品名称"/>
+                      </a-form-model-item>
+                    </a-col>
+                    <a-col :md="4" :sm="24">
+                      <a-form-model-item label="原厂编码">
+                        <a-input id="purchaseOrderEdit-origCode" v-model.trim="queryParam.origCode" allowClear placeholder="请输入原厂编码"/>
+                      </a-form-model-item>
+                    </a-col>
+                    <a-col :md="4" :sm="24">
+                      <a-form-item label="产品分类">
+                        <ProductType id="purchaseOrderEdit-productType" :isDealer="true" :tenantId="$route.params.dealerSn" @change="changeProductType" v-model="productType"></ProductType>
+                      </a-form-item>
+                    </a-col>
+                    <template v-if="advanced">
+                      <a-col :md="4" :sm="24">
+                        <a-form-item label="产品品牌">
+                          <ProductBrand id="purchaseOrderEdit-productBrand" :tenantId="$route.params.dealerSn" v-model="queryParam.productBrandSn"></ProductBrand>
+                        </a-form-item>
+                      </a-col>
+                    </template>
+                    <a-col :md="4" :sm="24" style="margin-bottom: 10px;">
+                      <a-button type="primary" @click="$refs.table.refresh(true)" :disabled="disabled" id="purchaseOrderEdit-refresh">查询</a-button>
+                      <a-button style="margin-left: 5px" @click="resetSearchForm" :disabled="disabled" id="purchaseOrderEdit-reset">重置</a-button>
+                      <a @click="advanced=!advanced" style="margin:0 30px 0 10px">
+                        {{ advanced ? '收起' : '展开' }}
+                        <a-icon :type="advanced ? 'up' : 'down'"/>
+                      </a>
+                    </a-col>
+                  </a-row>
+                </a-form>
+              </div>
+              <!-- 列表 -->
+              <s-table
+                class="sTable"
+                ref="table"
+                size="small"
+                :rowKey="(record) => record.id"
+                :columns="columns"
+                :data="loadData"
+                :defaultLoadData="false"
+                :scroll="{ y:176 }"
+                :pageSize="10"
+                bordered>
+                <!-- 产品图片 -->
+                <template slot="imageUrl" slot-scope="text, record">
+                  <img
+                    :src="record.productMainPic && record.productMainPic.imageUrl?(record.productMainPic.imageUrl+'?x-oss-process=image/resize,h_30,m_lfit'):defImg"
+                    width="30"
+                    height="30"
+                    style="cursor: pointer;"
+                    @click="handlePicDetail(record)" />
+                </template>
+                <!-- 包装数 -->
+                <template slot="baozh" slot-scope="text, record">
+                  {{ record.packQty||'--' }}/{{ record.packQtyUnit||'--' }}
+                </template>
+                <!-- 产品编码 -->
+                <template slot="code" slot-scope="text, record">
+                  <a-tooltip placement="top" v-if="record.stockState=='NOT_ENOUGH'">
+                    <template slot="title">
+                      该产品暂时缺货!
+                    </template>
+                    <span class="noStock">{{ record.code || '--' }}</span>
+                  </a-tooltip>
+                  <span v-else>{{ record.code || '--' }}</span>
+                </template>
+                <!-- 采购数量 -->
+                <template slot="storageQuantity" slot-scope="text, record">
+                  <a-input-number
+                    size="small"
+                    v-model="record.qty"
+                    :precision="0"
+                    :min="0"
+                    :max="999999"
+                    style="width: 100%;"
+                    placeholder="请输入数量" />
+                </template>
+                <!-- 操作 -->
+                <template slot="action" slot-scope="text, record">
+                  <a-button
+                    size="small"
+                    type="link"
+                    class="button-primary"
+                    :loading="addLoading"
+                    @click="handleAdd(record,0)"
+                    v-if="record.purchasePrice>0"
+                    id="purchaseOrderEdit-add-btn">添加</a-button>
+                  <span v-else>--</span>
+                </template>
+              </s-table>
+            </div>
+          </a-collapse-panel>
+        </a-collapse>
+      </div>
+      <!-- 已选产品 -->
+      <div class="purchaseOrderEdit-cont">
+        <a-collapse :activeKey="['1']">
+          <a-collapse-panel key="1">
+            <template slot="header">已选产品</template>
+            <div>
+              <!-- 总计 -->
+              <a-alert type="info" style="margin-bottom:10px">
+                <div slot="message">产品款数 <strong>{{ detail && (detail.totalCategory || detail.totalCategory==0) ? detail.totalCategory : '--' }}</strong> ,
+                  采购数量合计 <strong>{{ detail && (detail.totalQty || detail.totalQty==0) ? detail.totalQty : '--' }}</strong> ,
+                  <div style="display: inline-block;" v-if="$hasPermissions('M_ShowAllCost')">采购金额合计 <strong>{{ detail && (detail.discountedAmount || detail.discountedAmount==0) ?toThousands(detail.discountedAmount, 2) : '--' }}</strong></div>
+                </div>
+              </a-alert>
+              <!-- 搜索条件 -->
+              <div class="table-page-search-wrapper">
+                <a-row :gutter="15">
+                  <a-col :span="18">
+                    <a-form-model :model="productForm" layout="inline" @keyup.enter.native="$refs.purchaseTable.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.purchaseTable.refresh(true)" :disabled="purchaseDisabled" id="purchaseOrderEdit-refresh">查询</a-button>
+                            <a-button style="margin-left: 5px" @click="resetPurchaseForm" id="purchaseOrderEdit-reset">重置</a-button>
+                          </a-form-model-item>
+                        </a-col>
+                      </a-row>
+                    </a-form-model>
+                  </a-col>
+                  <a-col :span="6">
+                    <div style="float:right;overflow: hidden;">
+                      <a-button type="primary" class="button-primary" id="purchaseOrderEdit-import-btn" @click="handleOutStock">上次缺货</a-button>
+                      <a-button id="purchaseOrderEdit-import-btn" @click="openGuideModal=true">导入产品</a-button>
+                    </div>
+                  </a-col>
+                </a-row>
+              </div>
+              <!-- 列表 -->
+              <s-table
+                class="sTable"
+                ref="purchaseTable"
+                size="small"
+                :rowKey="(record) => record.id"
+                :columns="chooseColumns"
+                :data="chooseLoadData"
+                :defaultLoadData="false"
+                :showPagination="false"
+                bordered>
+                <!-- 采购数量 -->
+                <template slot="storageQuantity" slot-scope="text, record">
+                  <a-input-number
+                    size="small"
+                    id="purchaseOrderEdit-qty"
+                    v-model="record.qty"
+                    :precision="0"
+                    :min="1"
+                    :max="999999"
+                    @blur="e => qtyBlur(e.target.value, record)"
+                    style="width: 100%;"
+                    placeholder="请输入" />
+                </template>
+                <!-- 操作 -->
+                <template slot="action" slot-scope="text, record">
+                  <a-button
+                    size="small"
+                    type="link"
+                    class="button-error"
+                    :loading="delLoading"
+                    @click="handleDel(record)"
+                    id="purchaseOrderEdit-del-btn">删除</a-button>
+                </template>
+              </s-table>
+            </div>
+          </a-collapse-panel>
+        </a-collapse>
+      </div>
+    </a-spin>
+    <div class="affix-cont">
+      <a-button
+        type="primary"
+        id="purchaseOrderEdit-submit-btn"
+        size="large"
+        class="button-primary"
+        :loading="subLoading"
+        :disabled="spinning"
+        @click="handleSubmit"
+        style="padding: 0 60px;">提交</a-button>
+    </div>
+    <!-- 导入产品 -->
+    <importGuideModal :openModal="openGuideModal" :params="{purchaseBillSn: $route.params.sn}" @close="openGuideModal=false" @ok="hanldeOks" />
+    <!-- 上次缺货 -->
+    <outStockModal :openModal="openOutStockModal" :paramsData="paramsData" @close="openOutStockModal=false" @ok="hanldeOkOutStock" />
+    <!-- 选择地址 -->
+    <choose-address-modal :openModal="openAddrModal" @ok="handleAddrOk" @close="openAddrModal=false" />
+  </div>
+</template>
+
+<script>
+import { commonMixin } from '@/utils/mixin'
+import { STable, VSelect } from '@/components'
+import ImportGuideModal from './importGuideModal.vue'
+import outStockModal from './outStockModal.vue'
+import chooseAddressModal from '@/views/common/receivingAddress/chooseAddressModal.vue'
+import ProductType from '../../common/productType.js'
+import ProductBrand from '../../common/productBrand.js'
+import { purchaseDetailBySn, purchaseWriteSubmit, purchaseDetailPrint, purchaseDetailExport, purchaseDetailAddress } from '@/api/purchase'
+import { purchaseDetailList, purchaseDetailSave, purchaseDetailDel, purchaseDetailCount, purchaseDetailCancelList } from '@/api/purchaseDetail'
+import { productListPurchase } from '@/api/product'
+import defImg from '@/assets/def_img@2x.png'
+import Print from '@/views/common/print.vue'
+import { hdPrint } from '@/libs/JGPrint'
+export default {
+  name: 'PurchaseEdit',
+  components: { STable, VSelect, ProductType, ProductBrand, ImportGuideModal, outStockModal, Print, chooseAddressModal },
+  mixins: [commonMixin],
+  data () {
+    return {
+      isShowBisiceInfo: false,
+      showPage: false,
+      spinning: false,
+      detail: null, // 详细信息
+      subLoading: false,
+      defImg,
+      // 选择产品
+      addLoading: false,
+      productType: [],
+      queryParam: {
+        productBrandSn: undefined,
+        code: '', //  产品编码
+        name: '', //  产品名称
+        origCode: '', //  原厂编码
+        productTypeSn1: '', //  产品一级分类
+        productTypeSn2: '', //  产品二级分类
+        productTypeSn3: '' //  产品三级分类
+      },
+      typeData: [], //    下拉数据
+      advanced: false, //  高级搜索 展开/关闭
+      disabled: false, //  查询、重置按钮是否可操作
+      // 加载数据方法 必须为 Promise 对象
+      loadData: parameter => {
+        this.disabled = true
+        return productListPurchase(Object.assign(parameter, this.queryParam, { purchaseBillSn: this.$route.params.sn })).then(res => {
+          const data = res.data
+          const no = (data.pageNo - 1) * data.pageSize
+          for (var i = 0; i < data.list.length; i++) {
+            data.list[i].no = no + i + 1
+            data.list[i].qty = 1
+          }
+          this.disabled = false
+          return data
+        })
+      },
+      // -------已选产品-------------
+      orderCountData: null,
+      delLoading: false,
+      productForm: {
+        productName: '',
+        productCode: '',
+        orderBy: 'purchase_bill_detail.CREATE_DATE desc'
+      },
+      purchaseDisabled: false, //  查询、重置按钮是否可操作
+      // 加载数据方法 必须为 Promise 对象
+      chooseLoadData: parameter => {
+        this.disabled = true
+        // 查询总计
+        // const params = Object.assign(parameter, this.productForm, { purchaseBillSn: this.$route.params.sn })
+        const params = Object.assign({ pageNo: 1, pageSize: 5000 }, this.productForm, { purchaseBillSn: this.$route.params.sn })
+        // this.getCountQuery(params)
+        return purchaseDetailList(params).then(res => {
+          const data = res.data
+          const no = (data.pageNo - 1) * data.pageSize
+          for (var i = 0; i < data.list.length; i++) {
+            data.list[i].no = no + i + 1
+            data.list[i].qtyBackups = data.list[i].qty
+          }
+          this.localDataSource = data.list
+          this.disabled = false
+          return data
+        })
+      },
+      localDataSource: [],
+      openGuideModal: false, //  导入产品引导
+      openOutStockModal: false,
+      paramsData: null,
+      openAddrModal: false // 选择地址弹框是否显示
+    }
+  },
+  computed: {
+    isDealerUp () {
+      return this.detail && this.detail.purchaseTargetType == 'DEALER_UP'
+    },
+    columns () {
+      const _this = this
+      const arr = [
+        { title: '序号', dataIndex: 'no', width: '5%', align: 'center' },
+        { title: '产品编码', scopedSlots: { customRender: 'code' }, width: '15%', align: 'center', sorter: true },
+        { title: '产品名称', dataIndex: 'name', width: '23%', align: 'center', customRender: function (text) { return text || '--' }, ellipsis: true },
+        { title: '原厂编码', dataIndex: 'origCode', width: '14%', align: 'center', customRender: function (text) { return text && text != ' ' ? text : '--' } },
+        { title: '单位', dataIndex: 'unit', width: '5%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '包装数', scopedSlots: { customRender: 'baozh' }, width: '5%', align: 'center' },
+        // { title: '成本价', dataIndex: 'purchasePrice', width: '6%', align: 'center', customRender: function (text) { return ((text || text == 0) ? ('¥' + text) : '--') } },
+        { title: '终端会员价', dataIndex: 'terminalPrice', width: '6%', align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text, 2) : '--') } },
+        { title: '车主零售价', dataIndex: 'carOwnersPrice', width: '6%', align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text, 2) : '--') } },
+        { title: '采购数量', dataIndex: 'qty', scopedSlots: { customRender: 'storageQuantity' }, width: '6%', align: 'center' },
+        { title: '产品图片', scopedSlots: { customRender: 'imageUrl' }, width: '6%', align: 'center' },
+        { title: '操作', scopedSlots: { customRender: 'action' }, width: '8%', align: 'center' }
+      ]
+      // 产品来源
+      if (this.isDealerUp) {
+        arr.splice(6, 0, { title: '产品来源', dataIndex: 'sysFlagDictValue', width: '6%', align: 'center', customRender: function (text) { return text || '--' } })
+      }
+      if (this.$hasPermissions('M_ShowAllCost')) {
+        arr.splice(this.isDealerUp ? 7 : 6, 0, { title: '成本价', dataIndex: 'purchasePrice', width: '6%', align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text, 2) : '--') } })
+      }
+
+      return arr
+    },
+    chooseColumns () {
+      const _this = this
+      const arr = [
+        { title: '序号', dataIndex: 'no', width: '5%', align: 'center' },
+        { title: '产品编码', dataIndex: 'dealerProductEntity.code', width: '20%', align: 'center' },
+        { title: '产品名称', dataIndex: 'dealerProductEntity.name', width: '20%', align: 'center', customRender: function (text) { return text || '--' }, ellipsis: true },
+        // { title: '采购单价', dataIndex: 'discountedPrice', width: '20%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
+        { title: '采购数量', scopedSlots: { customRender: 'storageQuantity' }, width: '10%', align: 'center' },
+        { title: '单位', dataIndex: 'dealerProductEntity.unit', width: '8%', align: 'center', customRender: function (text) { return text || '--' } },
+        // { title: '采购金额', dataIndex: 'discountedAmount', width: '9%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
+        { title: '操作', scopedSlots: { customRender: 'action' }, width: '8%', align: 'center' }
+      ]
+      if (this.$hasPermissions('M_ShowAllCost')) {
+        arr.splice(3, 0, { title: '采购单价', dataIndex: 'discountedPrice', width: '20%', align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text, 2) : '--') } })
+        arr.splice(6, 0, { title: '采购金额', dataIndex: 'discountedAmount', width: '9%', align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text, 2) : '--') } })
+      }
+      return arr
+    }
+  },
+  methods: {
+    // 获取采购单明细统计
+    getCountQuery (params) {
+      purchaseDetailCount(params).then(res => {
+        this.orderCountData = res.data || null
+      })
+    },
+    // 获取采购单基本信息
+    getOrderDetail () {
+      purchaseDetailBySn({ sn: this.$route.params.sn }).then(res => {
+        if (res.status == 200) {
+          this.detail = res.data
+        }
+      })
+    },
+    // 删除产品
+    handleDel (row) {
+      const _this = this
+      this.$confirm({
+        title: '提示',
+        content: '确认要删除吗?',
+        centered: true,
+        closable: true,
+        onOk () {
+          _this.delLoading = true
+          _this.spinning = true
+          purchaseDetailDel({ id: row.id }).then(res => {
+            if (res.status == 200) {
+              _this.resetPurchaseDetail(true)
+              _this.$message.success(res.message)
+              _this.delLoading = false
+              _this.spinning = false
+            } else {
+              _this.delLoading = false
+              _this.spinning = false
+            }
+          })
+        }
+      })
+    },
+    // 重新查询已选产品
+    resetPurchaseDetail (flag) {
+      this.$refs.purchaseTable.refresh(!!flag)
+      this.getOrderDetail()
+    },
+    // 修改数量后
+    qtyBlur (val, record) {
+      //  光标移出,值发生改变再调用编辑接口
+      if (val != record.qtyBackups) {
+        this.handleAdd(record, 1)
+      }
+    },
+    filterOption (input, option) {
+      return (
+        option.componentOptions.children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0
+      )
+    },
+    //  产品分类  change
+    changeProductType (val, opt) {
+      this.queryParam.productTypeSn1 = val[0] ? val[0] : ''
+      this.queryParam.productTypeSn2 = val[1] ? val[1] : ''
+      this.queryParam.productTypeSn3 = val[2] ? val[2] : ''
+    },
+    //  重置产品库
+    resetSearchForm () {
+      this.queryParam = {
+        productBrandSn: undefined,
+        code: '', //  产品编码
+        name: '', //  产品名称
+        origCode: '', //  原厂编码
+        productTypeSn1: '', //  产品一级分类
+        productTypeSn2: '', //  产品二级分类
+        productTypeSn3: '' //  产品三级分类
+      }
+      this.productType = []
+      this.$refs.table.refresh(true)
+    },
+    resetPurchaseForm () {
+      this.productForm.productName = ''
+      this.productForm.productCode = ''
+      this.$refs.purchaseTable.refresh(true)
+    },
+    //  添加或修改
+    handleAdd (row, type) {
+      let params = {}
+      if (type == 0 && !row.qty) {
+        this.$message.warning('请输入数量后再添加!')
+        return
+      }
+      // 添加
+      if (type == 0) {
+        params.productSn = row.productSn
+        params.purchaseBillSn = this.detail.purchaseBillSn
+        params.purchaseBillNo = this.detail.purchaseBillNo
+        params.price = row.purchasePrice
+        params.qty = row.qty
+      } else { //  编辑
+        // 清空成本价或数量时,值应保持未清空前的值,因成本价和数量都不可为空
+        if (!row.qty) {
+          row.qty = row.qtyBackups
+          return
+        }
+        params = row
+      }
+      this.addLoading = true
+      this.spinning = true
+      purchaseDetailSave(params).then(res => {
+        if (res.status == 200) {
+          this.resetPurchaseDetail()
+          this.$message.success(res.message)
+          this.spinning = false
+        } else {
+          this.spinning = false
+        }
+        this.addLoading = false
+      })
+    },
+    //  提交
+    handleSubmit () {
+      const _this = this
+      this.subLoading = true
+      this.spinning = true
+      purchaseWriteSubmit({ id: this.detail.id }).then(res => {
+        if (res.status == 200) {
+          this.$message.success(res.message)
+          setTimeout(() => {
+            _this.handleBack()
+            _this.spinning = false
+          }, 1000)
+        } else {
+          _this.spinning = false
+        }
+        _this.subLoading = false
+      })
+    },
+    // 导入产品
+    hanldeOks () {
+      this.$refs.purchaseTable.refresh(true)
+      this.getOrderDetail()
+    },
+    // 上次缺货
+    handleOutStock () {
+      // 校验是否存在历史采购单,且上次采购存在缺货产品
+      purchaseDetailCancelList({ pageNo: 1, pageSize: 5 }).then(res => {
+        if (res.status == 200) {
+          this.paramsData = {
+            purchaseBillSn: this.$route.params.sn,
+            purchaseBillNo: this.detail && this.detail.purchaseBillNo ? this.detail.purchaseBillNo : undefined
+          }
+          this.openOutStockModal = true
+        }
+      })
+    },
+    //  地址保存
+    handleAddrOk (data) {
+      const params = {
+        purchaseBillSn: this.$route.params.sn,
+        shippingAddressProvinceName: data.provinceName,
+        shippingAddressCityName: data.cityName,
+        shippingAddressCountyName: data.countyName,
+        shippingAddress: data.addr,
+        consigneeName: data.consigneeName,
+        consigneeTel: data.consigneeTel
+      }
+      purchaseDetailAddress(params).then(res => {
+        if (res.status == 200) {
+          this.openAddrModal = false
+          this.getOrderDetail()
+        }
+      })
+    },
+    // 查看产品
+    handlePicDetail (row) {
+      this.$router.push({ name: 'viewProduct', params: { sn: row.productSn } })
+    },
+    // 上次缺货 导入成功
+    hanldeOkOutStock () {
+      this.$refs.purchaseTable.refresh(true)
+      this.paramsData = null
+      this.openOutStockModal = false
+    },
+    // 打印预览/快捷打印
+    handlePrint (type, printerType) {
+      const _this = this
+      _this.spinning = true
+      let url = purchaseDetailPrint
+      let params = { sn: this.$route.params.sn, type: printerType }
+      if (type == 'export') { //  导出
+        url = purchaseDetailExport
+        params = { sn: this.$route.params.sn }
+      }
+      // 打印或导出
+      hdPrint(printerType, type, url, params, '采购单', function () {
+        _this.spinning = false
+      })
+    },
+    //  返回列表
+    handleBack () {
+      this.$router.push({ name: 'purchaseOrderNewList' })
+    },
+    pageInit () {
+      this.$nextTick(() => {
+        this.getOrderDetail()
+        this.resetPurchaseForm()
+        this.resetSearchForm()
+        this.$refs.searchProductCode.focus()
+      })
+    }
+  },
+  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()
+    }
+  },
+  deactivated () {
+    // this.showPage = false
+  },
+  beforeRouteEnter (to, from, next) {
+    next(vm => {})
+  }
+}
+</script>
+
+<style lang="less">
+  .purchaseOrderEdit-wrap{
+    position: relative;
+    height: 100%;
+    padding-bottom: 51px;
+    box-sizing: border-box;
+    >.ant-spin-nested-loading{
+      overflow-y: auto;
+      height: 100%;
+    }
+    .noStock{
+      text-decoration: line-through;
+      color: red;
+    }
+    .billno{
+      margin: 0 0 0 30px;
+      font-size: 18px;
+      font-weight: 600;
+      display: inline-block;
+      vertical-align: middle;
+      color: #666;
+    }
+    .purchaseOrderEdit-cont{
+      margin-bottom: 10px;
+      .sub-title{
+        font-size: 12px;
+        color: #808695;
+        margin-left: 10px;
+      }
+      .tag-txt{
+        font-size: 12px;
+        color: #ed1c24;
+        margin: 0 15px;
+      }
+      .edit-circle-btn{
+        margin-left: 15px;
+        i{
+          vertical-align: text-bottom;
+        }
+      }
+      .import-btn{
+        margin-left: 15px;
+      }
+    }
+     .gutter-row:nth-child(1),.gutter-row:nth-child(2){
+          margin-bottom:10px;
+        }
+    .ant-collapse .ant-collapse-item-disabled > .ant-collapse-header{
+          color:#333;
+        }
+  }
+</style>

+ 209 - 0
src/views/purchasingManagement/purchaseOrderNew/importGuideModal.vue

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

+ 393 - 0
src/views/purchasingManagement/purchaseOrderNew/list.vue

@@ -0,0 +1,393 @@
+<template>
+  <a-card size="small" :bordered="false" class="purchaseOrderList-wrap">
+    <a-spin :spinning="spinning" tip="Loading...">
+      <!-- 搜索条件 -->
+      <div ref="tableSearch" class="table-page-search-wrapper">
+        <a-form layout="inline" @keyup.enter.native="$refs.table.refresh(true)">
+          <a-row :gutter="15">
+            <a-col :md="6" :sm="24">
+              <a-form-item label="创建时间">
+                <rangeDate ref="rangeDate" :value="time" @change="dateChange" />
+              </a-form-item>
+            </a-col>
+            <a-col :md="6" :sm="24">
+              <a-form-item label="采购单号">
+                <a-input id="purchaseOrderList-purchaseBillNo" v-model.trim="queryParam.purchaseBillNo" allowClear placeholder="请输入采购单号"/>
+              </a-form-item>
+            </a-col>
+            <a-col :md="6" :sm="24">
+              <a-form-item label="供应商" :label-col="{ span:7 }" :wrapper-col="{ span:17}">
+                <a-select
+                  id="purchaseOrderList-purchaseTargetSn"
+                  placeholder="请选择供应商"
+                  allowClear
+                  v-model="queryParam.purchaseTargetSn"
+                  :showSearch="true"
+                  option-filter-prop="children"
+                  :filter-option="filterOption"
+                  @change="tragetTypeChange">
+                  <a-select-option v-for="item in supplierList" :pyCode="item.pyCode" :key="item.purchaseTargetSn" :value="item.purchaseTargetSn">{{ item.purchaseTargetName }}</a-select-option>
+                </a-select>
+              </a-form-item>
+            </a-col>
+            <a-col :md="6" :sm="24" v-show="advanced">
+              <a-form-item label="业务状态">
+                <!-- <v-select
+                  v-model="queryParam.billStatus"
+                  ref="billStatus"
+                  id="purchaseOrderList-billStatus"
+                  code="PURCHASE_BILL_STATUS"
+                  placeholder="请选择业务状态"
+                  allowClear></v-select> -->
+                <a-select id="purchaseOrderList-billStatus" allowClear v-model="queryParam.billStatus" placeholder="请选择业务状态">
+                  <a-select-option value="">全部</a-select-option>
+                  <a-select-option value="WAIT_SUBMIT">待提交</a-select-option>
+                  <a-select-option value="SUBMIT">已提交</a-select-option>
+                </a-select>
+              </a-form-item>
+            </a-col>
+            <a-col :md="6" :sm="24" v-show="advanced">
+              <a-form-item label="财务状态">
+                <v-select
+                  v-model="queryParam.financialStatus"
+                  ref="financialStatus"
+                  id="purchaseOrderList-financialStatus"
+                  code="FINANCIAL_PAY_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.purchaseBillSource"
+                  ref="purchaseBillSource"
+                  id="purchaseOrderList-purchaseBillSource"
+                  code="PURCHASE_SOURCE"
+                  placeholder="请选择单据来源"
+                  allowClear></v-select>
+              </a-form-item>
+            </a-col>
+            <a-col :md="6" :sm="24">
+              <span class="table-page-search-submitButtons">
+                <a-button type="primary" @click="$refs.table.refresh(true)" :disabled="disabled" id="purchaseOrderList-refresh">查询</a-button>
+                <a-button style="margin-left: 8px" @click="resetSearchForm()" :disabled="disabled" id="purchaseOrderList-reset">重置</a-button>
+                <a @click="advanced=!advanced" style="margin-left: 8px">
+                  {{ advanced ? '收起' : '展开' }}
+                  <a-icon :type="advanced ? 'up' : 'down'"/>
+                </a>
+              </span>
+            </a-col>
+          </a-row>
+        </a-form>
+      </div>
+      <!-- 操作按钮 -->
+      <div class="table-operator">
+        <a-button id="purchaseOrderList-add" type="primary" v-if="$hasPermissions('B_purchaseNew')&&($hasPermissions('B_SUPPLIER_SJ')||$hasPermissions('B_SUPPLIER_ZB'))" class="button-error" @click="handleAdd">新增</a-button>
+      </div>
+      <!-- alert -->
+      <a-alert type="info" style="margin-bottom:10px">
+        <div slot="message">
+          共 <strong>{{ totalData&&(totalData.totalRecord || totalData.totalRecord==0) ? totalData.totalRecord : '--' }}</strong> 条记录,
+          采购数量合计 <strong>{{ totalData&&(totalData.totalQty || totalData.totalQty==0) ? totalData.totalQty : '--' }}</strong> ,
+          采购金额合计 <strong>{{ totalData&&(totalData.totalAmount || totalData.totalAmount==0) ? toThousands(totalData.totalAmount,2) : '--' }}</strong>,
+          审核金额合计 <strong>{{ totalData&&(totalData.totalAuthAmount || totalData.totalAuthAmount==0) ? toThousands(totalData.totalAuthAmount,2) : '--' }}</strong>
+        </div>
+      </a-alert>
+      <!-- 列表 -->
+      <s-table
+        class="sTable fixPagination"
+        ref="table"
+        :style="{ height: tableHeight+84.5+'px' }"
+        size="small"
+        :rowKey="(record) => record.id"
+        :columns="columns"
+        :data="loadData"
+        :scroll="{ y: tableHeight }"
+        :defaultLoadData="false"
+        bordered>
+        <!-- 采购单号 -->
+        <template slot="purchaseBillNo" slot-scope="text, record">
+          <span class="table-td-link" v-if="$hasPermissions('B_purchaseDetail')" @click="handleDetail(record)">{{ record.purchaseBillNo }}</span>
+          <span v-else>{{ record.purchaseBillNo }}</span>
+          <a-badge count="改" :offset="[10,0]" v-if="record.billStatus=='HQ_CHANGE'||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_PUT_WAREHOUSE'||record.billStatus=='AUDIT_PASS'||record.billStatus == 'FINISH'?'1':'2'"></stateIcon>
+          <stateIcon :title="record.billStatusDictValue" v-else :state="0"></stateIcon>
+        </template>
+        <!-- 付款 -->
+        <template slot="financial" slot-scope="text, record">
+          <stateIcon :title="record.financialStatusDictValue" :state="record.financialStatus == 'FINISH'?'1':'2'"></stateIcon>
+        </template>
+        <!-- 入库 -->
+        <template slot="waitOut" slot-scope="text, record">
+          <stateIcon :state="record.billStatus == '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_SUBMIT'||record.billStatus == 'AUDIT_REJECT') && $hasPermissions('B_purchaseEdit')"
+            @click="handleEdit(record)"
+          >编辑</a-button>
+          <a-button
+            size="small"
+            type="link"
+            class="button-error"
+            v-if="(record.billStatus == 'WAIT_SUBMIT'||record.billStatus == 'AUDIT_REJECT') &&$hasPermissions('B_purchaseDel')"
+            @click="handleDel(record)"
+          >删除</a-button>
+          <span v-if="!((record.billStatus == 'WAIT_SUBMIT'||record.billStatus == 'AUDIT_REJECT') && $hasPermissions('B_purchaseEdit')) && !((record.billStatus == 'WAIT_SUBMIT'||record.billStatus == 'AUDIT_REJECT') &&$hasPermissions('B_purchaseDel'))">--</span>
+        </template>
+      </s-table>
+    </a-spin>
+    <!-- 选择基本信息弹框 -->
+    <basic-info-modal :openModal="openModal" @ok="handleOk" @close="openModal=false" />
+  </a-card>
+</template>
+
+<script>
+import { commonMixin } from '@/utils/mixin'
+import { STable, VSelect } from '@/components'
+import rangeDate from '@/views/common/rangeDate.vue'
+import basicInfoModal from './basicInfoModal.vue'
+import stateIcon from '@/views/common/stateIcon'
+import getDate from '@/libs/getDate.js'
+import { purchaseList, purchaseDel, purchaseCount } from '@/api/purchase'
+import { queryReturnSupplierList } from '@/api/purchaseReturn'
+export default {
+  name: 'PurchaseOrderNewList',
+  components: { STable, VSelect, basicInfoModal, rangeDate, stateIcon },
+  mixins: [commonMixin],
+  data () {
+    const _this = this
+    return {
+      spinning: false,
+      advanced: true, //  高级搜索 展开/关闭
+      disabled: false, //  查询、重置按钮是否可操作
+      openModal: false, // 基本信息弹框是否显示
+      supplierList: [],
+      tableHeight: 0,
+      time: [
+        getDate.getCurrMonthDays().starttime,
+        getDate.getCurrMonthDays().endtime
+      ],
+      // 查询参数
+      queryParam: {
+        purchaseBillNo: '',
+        purchaseTargetSn: undefined,
+        purchaseTargetType: undefined,
+        billStatus: undefined,
+        financialStatus: undefined,
+        purchaseBillSource: undefined,
+        beginDate: getDate.getCurrMonthDays().starttime,
+        endDate: getDate.getCurrMonthDays().endtime
+      },
+      totalData: {
+        totalRecord: 0,
+        totalCategory: 0,
+        totalQty: 0,
+        totalAmount: 0
+      },
+      // 表头
+      columns: [
+        { title: '序号', dataIndex: 'no', width: '4%', align: 'center' },
+        { title: '采购单号', scopedSlots: { customRender: 'purchaseBillNo' }, width: '13%', align: 'center' },
+        { title: '创建时间', dataIndex: 'createDate', width: '10%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '供应商', dataIndex: 'purchaseTargetName', width: '10%', align: 'center', customRender: function (text) { return text || '--' }, ellipsis: true },
+        { title: '产品款数', dataIndex: 'totalCategory', width: '6%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
+        { title: '采购数量', dataIndex: 'totalQty', width: '6%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
+        { title: '采购金额', dataIndex: 'discountedAmount', width: '6%', align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text, 2) : '--') } },
+        { title: '审核数量', dataIndex: 'totalPushedQty', width: '6%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
+        { title: '审核金额', dataIndex: 'totalPushedAmount', width: '6%', align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text, 2) : '--') } },
+        { title: '已取消数量', dataIndex: 'totalCancelQty', width: '7%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '采购状态', dataIndex: 'billStatusDictValue', width: '6%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '审核', scopedSlots: { customRender: 'audit' }, width: '3%', align: 'center' },
+        { title: '入库', scopedSlots: { customRender: 'waitOut' }, width: '3%', align: 'center' },
+        { title: '付款', scopedSlots: { customRender: 'financial' }, width: '3%', align: 'center' },
+        { title: '操作', scopedSlots: { customRender: 'action' }, width: '9%', align: 'center' }
+      ],
+      // 加载数据方法 必须为 Promise 对象
+      loadData: parameter => {
+        this.disabled = true
+        this.spinning = true
+        // 获取统计数据
+        this.getTotalData(Object.assign(parameter, this.queryParam))
+        return purchaseList(Object.assign(parameter, this.queryParam)).then(res => {
+          let data
+          if (res.status == 200) {
+            data = res.data
+            const no = (data.pageNo - 1) * data.pageSize
+            for (var i = 0; i < data.list.length; i++) {
+              data.list[i].no = no + i + 1
+            }
+            this.disabled = false
+          }
+          this.spinning = false
+          return data
+        })
+      }
+    }
+  },
+  methods: {
+    getTotalData (params) {
+      purchaseCount(params).then(res => {
+        this.totalData = res.data || null
+      })
+    },
+    // 供应商change
+    tragetTypeChange (val) {
+      const ind = this.supplierList.findIndex(item => item.purchaseTargetSn == val)
+      if (ind != -1) {
+        this.queryParam.purchaseTargetType = this.supplierList[ind].purchaseTargetType
+      } else {
+        this.queryParam.purchaseTargetSn = undefined
+        this.queryParam.purchaseTargetType = undefined
+      }
+    },
+    //  时间  change
+    dateChange (date) {
+      this.queryParam.beginDate = date[0]
+      this.queryParam.endDate = date[1]
+    },
+    //  新增
+    handleAdd () {
+      this.openModal = true
+    },
+    //  基本信息  保存
+    handleOk (row) {
+      this.$router.push({ name: `purchaseOrderNewAdd`, params: { sn: row.purchaseBillSn, dealerSn: (row.purchaseTargetType == 'DEALER_UP' ? row.purchaseTargetSn : 'NONE') } })
+    },
+    //  编辑
+    handleEdit (row) {
+      this.$router.push({ name: `purchaseOrderNewEdit`, params: { sn: row.purchaseBillSn, dealerSn: (row.purchaseTargetType == 'DEALER_UP' ? row.purchaseTargetSn : 'NONE') } })
+    },
+    //  详情
+    handleDetail (row) {
+      this.$router.push({ name: `purchaseOrderNewDetail`, params: { sn: row.purchaseBillSn } })
+    },
+    //  删除
+    handleDel (row) {
+      const _this = this
+      this.$confirm({
+        title: '提示',
+        content: '删除后不可恢复,确定要进行删除吗?',
+        centered: true,
+        onOk () {
+          _this.spinning = true
+          purchaseDel({
+            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
+            }
+          })
+        }
+      })
+    },
+    //  重置
+    resetSearchForm (flag) {
+      this.$refs.rangeDate.resetDate(flag ? '' : this.time)
+      this.queryParam.beginDate = flag ? '' : getDate.getCurrMonthDays().starttime
+      this.queryParam.endDate = flag ? '' : getDate.getCurrMonthDays().endtime
+      this.queryParam.orderBundleNo = ''
+      this.queryParam.purchaseBillNo = ''
+      this.queryParam.purchaseTargetSn = undefined
+      this.queryParam.purchaseTargetType = undefined
+      this.queryParam.billStatus = undefined
+      this.queryParam.financialStatus = undefined
+      this.queryParam.purchaseBillSource = undefined
+      if (!flag) {
+        this.$refs.table.refresh(true)
+        this.setIsHomeNav(this.$route.name, null)
+      }
+    },
+    filterOption (input, option) {
+      return (
+        option.componentOptions.children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0
+      )
+    },
+    // 获取供应商数据
+    getSupperList () {
+      queryReturnSupplierList({}).then(res => {
+        if (res.status == 200) {
+          this.supplierList = res.data
+        } else {
+          this.supplierList = []
+        }
+      })
+    },
+    pageInit () {
+      const _this = this
+      this.$nextTick(() => { // 页面渲染完成后的回调
+        _this.setTableH()
+      })
+      this.openModal = false
+      this.getSupperList()
+
+      // 是否打开的页签
+      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, this.getIsHomeNav(), isHomeNav, this.$route.name)
+
+      // 从首页进入,判断式新建还式待办查询
+      if (isHomeNav) {
+        // 新增
+        if (isHomeNav.type == 'new') {
+          this.resetSearchForm()
+          this.openModal = true
+        }
+        // 待办
+        if (isHomeNav.type == 'todo') {
+          this.resetSearchForm(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()
+      }
+    },
+    setTableH () {
+      const tableSearchH = this.$refs.tableSearch.offsetHeight
+      this.tableHeight = window.innerHeight - tableSearchH - 275
+    }
+  },
+  watch: {
+    advanced (newValue, oldValue) {
+      const _this = this
+      this.$nextTick(() => { // 页面渲染完成后的回调
+        _this.setTableH()
+      })
+    },
+    '$store.state.app.winHeight' (newValue, oldValue) { //  窗口变更时,需同时更改表格高度
+      this.setTableH()
+    }
+  },
+  activated () {
+    this.pageInit()
+  },
+  beforeRouteEnter (to, from, next) {
+    next(vm => {
+    })
+  }
+}
+</script>

+ 213 - 0
src/views/purchasingManagement/purchaseOrderNew/outStockModal.vue

@@ -0,0 +1,213 @@
+<template>
+  <a-modal
+    centered
+    class="outStock-modal"
+    :footer="null"
+    :maskClosable="false"
+    title="上次采购缺货产品明细"
+    v-model="isShow"
+    @cancel="isShow=false"
+    :width="800">
+    <a-spin :spinning="spinning" tip="Loading...">
+      <div class="outStock-con">
+        <div>
+          <p style="font-weight: bold;">当前已选:{{ rowSelectionInfo&&rowSelectionInfo.selectedRowKeys.length }}个</p>
+          <!-- 列表 -->
+          <s-table
+            class="sTable"
+            ref="table"
+            size="small"
+            :rowKey="(record) => record.productSn"
+            rowKeyName="productSn"
+            :row-selection="{ columnWidth: 40 }"
+            @rowSelection="rowSelectionFun"
+            :data="loadData"
+            :columns="columns"
+            :scroll="{ y: 450 }"
+            bordered>
+          </s-table>
+        </div>
+        <!-- 按钮 -->
+        <div class="btn-con">
+          <a-button
+            type="primary"
+            id="outStock-save"
+            size="large"
+            class="button-primary"
+            @click="handleSave"
+            style="padding: 0 36px;">加入本次采购</a-button>
+          <a-button
+            id="outStock-cancel"
+            size="large"
+            class="button-cancel"
+            @click="isShow=false"
+            style="padding: 0 60px;margin-left: 15px;">取消</a-button>
+        </div>
+      </div>
+    </a-spin>
+  </a-modal>
+</template>
+
+<script>
+import { commonMixin } from '@/utils/mixin'
+import { STable } from '@/components'
+import { purchaseDetailCancelList, purchaseDetailCancelSave } from '@/api/purchaseDetail'
+export default {
+  name: 'OutStockModal',
+  components: { STable },
+  mixins: [commonMixin],
+  props: {
+    openModal: { //  弹框显示状态
+      type: Boolean,
+      default: false
+    },
+    chooseData: {
+      type: Array,
+      default: () => {
+        return []
+      }
+    },
+    paramsData: {
+      type: Object,
+      default: () => {
+        return {}
+      }
+    }
+  },
+  data () {
+    return {
+      isShow: this.openModal, //  是否打开弹框
+      formItemLayout: {
+        labelCol: { span: 4 },
+        wrapperCol: { span: 20 }
+      },
+      disabled: false, //  查询、重置按钮是否可操作
+      columns: [
+        { title: '产品编码', dataIndex: 'dealerProductEntity.code', width: '24%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '产品名称', dataIndex: 'dealerProductEntity.name', width: '32%', align: 'left', customRender: function (text) { return text || '--' }, ellipsis: true },
+        { title: '上次采购数量', dataIndex: 'qty', width: '18%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
+        { title: '上次缺货数量', dataIndex: 'cancelQty', width: '18%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
+        { title: '单位', dataIndex: 'dealerProductEntity.unit', width: '8%', align: 'center', customRender: function (text) { return text || '--' } }
+      ],
+      // 加载数据方法 必须为 Promise 对象
+      loadData: parameter => {
+        this.disabled = true
+        this.spinning = true
+        return purchaseDetailCancelList(parameter).then(res => {
+          let data
+          if (res.status == 200) {
+            data = res.data
+            this.disabled = false
+          }
+          this.spinning = false
+          return data
+        })
+      },
+      spinning: false,
+      rowSelectionInfo: null
+    }
+  },
+  methods: {
+    // 表格选中项
+    rowSelectionFun (obj) {
+      this.rowSelectionInfo = obj || null
+    },
+    // 保存
+    handleSave () {
+      const _this = this
+      if (!this.rowSelectionInfo || (this.rowSelectionInfo && this.rowSelectionInfo.selectedRowKeys.length < 1)) {
+        this.$message.warning('请在列表勾选后再进行操作!')
+        return
+      }
+      const params = {
+        confirm: false,
+        purchaseBillSn: this.paramsData.purchaseBillSn,
+        purchaseBillNo: this.paramsData.purchaseBillNo,
+        purchaseBillDetailEntityList: this.rowSelectionInfo && this.rowSelectionInfo.selectedRows
+      }
+      purchaseDetailCancelSave(params).then(res => {
+        if (res.status == 200 && res.data) {
+          let content = ''
+          if ((res.data.productSizeRepeat != res.data.productSize) && (res.data.productSizeRepeat != 0)) {
+            content = `您已经选择 ${res.data.productSize} 个产品,其中 ${res.data.productSizeRepeat} 个产品已经存在于采购单中。本次只会加入不重复的产品,上次缺货数量将作为本次采购数量。确认加入本次采购吗?`
+            this.confirmFun(content)
+          } else if (res.data.productSizeRepeat == res.data.productSize) {
+            content = `抱歉,您选择的 ${res.data.productSize} 个产品,采购单中已经全部存在,无需加入!`
+            this.$info({
+              title: '提示',
+              content: content,
+              okText: '好的',
+              centered: true,
+              onOk () {
+                _this.$refs.table.clearSelected() // 清空表格选中项
+              }
+            })
+          } else {
+            content = `您已经选择 ${res.data.productSize} 个产品,上次缺货数量将作为本次采购数量。确认加入本次采购吗?`
+            this.confirmFun(content)
+          }
+        }
+      })
+    },
+    confirmFun (content) {
+      const _this = this
+      this.$confirm({
+        title: '提示',
+        content: content,
+        okText: '确认加入',
+        cancelText: '重新选择',
+        centered: true,
+        closable: true,
+        onOk () {
+          _this.spinning = true
+          const params = {
+            confirm: true,
+            purchaseBillSn: _this.paramsData.purchaseBillSn,
+            purchaseBillNo: _this.paramsData.purchaseBillNo,
+            purchaseBillDetailEntityList: _this.rowSelectionInfo && _this.rowSelectionInfo.selectedRows
+          }
+          purchaseDetailCancelSave(params).then(res => {
+            if (res.status == 200) {
+              _this.$emit('ok')
+              _this.isShow = false
+              _this.spinning = false
+            } else {
+              _this.spinning = false
+            }
+          })
+        },
+        onCancel () {
+          _this.$refs.table.clearSelected() // 清空表格选中项
+        }
+      })
+    }
+  },
+  watch: {
+    //  父页面传过来的弹框状态
+    openModal (newValue, oldValue) {
+      this.isShow = newValue
+    },
+    //  重定义的弹框状态
+    isShow (newValue, oldValue) {
+      if (!newValue) {
+        this.$emit('close')
+        this.$refs.table.clearSelected() // 清空表格选中项
+      }
+    }
+  }
+}
+</script>
+
+<style lang="less" scoped>
+  .outStock-modal{
+    .outStock-con{
+      .btn-con{
+        text-align: center;
+        margin: 30px 0 20px;
+        .button-cancel{
+          font-size: 12px;
+        }
+      }
+    }
+  }
+</style>