Browse Source

对账单

lilei 1 month ago
parent
commit
747efabba4

+ 97 - 0
src/config/financialManagement.js

@@ -112,6 +112,103 @@ export default {
                 }
               }
             ]
+          },
+          {
+            path: '/financialManagement/accountStatement',
+            redirect: '/financialManagement/accountStatement/list',
+            name: 'accountStatement',
+            component: BlankLayout,
+            meta: {
+              title: '对账单管理',
+              icon: 'vertical-align-top',
+              permission: 'M_FC_Details_list'
+            },
+            hideChildrenInMenu: true,
+            children: [
+              {
+                path: 'list',
+                name: 'accountStatementList',
+                component: () => import(/* webpackChunkName: "financialManagement" */ '@/views/financialManagement/accountStatement/list.vue'),
+                meta: {
+                  title: '对账单列表',
+                  icon: 'vertical-align-top',
+                  hidden: true,
+                  permission: 'M_FC_Details_list'
+                }
+              },
+              {
+                path: 'edit/:sn',
+                name: 'accountStatementEdit',
+                component: () => import(/* webpackChunkName: "financialManagement" */ '@/views/financialManagement/accountStatement/edit.vue'),
+                meta: {
+                  title: '编辑对账单',
+                  icon: 'vertical-align-top',
+                  hidden: true,
+                  permission: 'M_FC_Details_list'
+                }
+              }
+            ]
+          },
+          {
+            path: '/financialManagement/accountStatementBill',
+            redirect: '/financialManagement/accountStatementBill/list',
+            name: 'accountStatementBill',
+            component: BlankLayout,
+            meta: {
+              title: '对账单据管理',
+              icon: 'vertical-align-top',
+              permission: 'M_FC_Details_list'
+            },
+            hideChildrenInMenu: true,
+            children: [
+              {
+                path: 'list',
+                name: 'accountStatementBillList',
+                component: () => import(/* webpackChunkName: "financialManagement" */ '@/views/financialManagement/accountStatementBill/list.vue'),
+                meta: {
+                  title: '待对单单据列表',
+                  icon: 'vertical-align-top',
+                  hidden: true,
+                  permission: 'M_FC_Details_list'
+                }
+              },
+              {
+                path: 'detail/:sn',
+                name: 'accountStatementBillDetail',
+                component: () => import(/* webpackChunkName: "financialManagement" */ '@/views/financialManagement/accountStatementBill/detail.vue'),
+                meta: {
+                  title: '待对单单据明细',
+                  icon: 'vertical-align-top',
+                  hidden: true,
+                  permission: 'M_FC_Details_list'
+                }
+              },
+            ]
+          },
+          {
+            path: '/financialManagement/manualEntryForm',
+            redirect: '/financialManagement/manualEntryForm/list',
+            name: 'manualEntryForm',
+            component: BlankLayout,
+            meta: {
+              title: '人工录入单管理',
+              icon: 'vertical-align-top',
+              permission: 'M_FC_Details_list'
+            },
+            hideChildrenInMenu: true,
+            children: [
+              {
+                path: 'list',
+                name: 'manualEntryFormList',
+                component: () => import(/* webpackChunkName: "financialManagement" */ '@/views/financialManagement/manualEntryForm/list.vue'),
+                meta: {
+                  title: '人工录入单列表',
+                  icon: 'vertical-align-top',
+                  hidden: true,
+                  permission: 'M_FC_Details_list'
+                }
+              }
+            ]
           }
         ]
       }

+ 172 - 0
src/views/financialManagement/accountStatement/baseModal.vue

@@ -0,0 +1,172 @@
+<template>
+  <a-modal
+    v-model="opened"
+    :title="title"
+    centered
+    :maskClosable="false"
+    :width="600"
+    :footer="null"
+    @cancel="cancel"
+  >
+    <a-spin :spinning="spinning" tip="Loading...">
+      <a-form-model
+        id="chooseCustom-form"
+        ref="ruleForm"
+        :model="form"
+        :rules="rules"
+        :label-col="formItemLayout.labelCol"
+        :wrapper-col="formItemLayout.wrapperCol">
+        <a-form-model-item label="客户名称" prop="dealerSn">
+          <dealerSubareaScopeList :disabled="!!bookSn" ref="settleClientName" @change="custChange" />
+        </a-form-model-item>
+        <a-form-model-item label="备注">
+          <a-textarea :rows="4" :maxLength="300" placeholder="请输入备注(最多300个字符)" v-model="form.remarks"></a-textarea>
+        </a-form-model-item>
+        <a-form-model-item :wrapper-col="{ span: 12, offset: 6 }" style="text-align: center;margin-top: 50px;">
+          <a-button @click="cancel" style="margin-right: 15px" id="chooseCustom-btn-back">取消</a-button>
+          <a-button type="primary" :loading="confirmLoading" @click="handleSubmit" id="chooseCustom-btn-submit">保存</a-button>
+        </a-form-model-item>
+      </a-form-model>
+    </a-spin>
+  </a-modal>
+</template>
+
+<script>
+import { commonMixin } from '@/utils/mixin'
+import { VSelect, Upload } from '@/components'
+import employee from '../../expenseManagement/expenseReimbursement/employee.js'
+import dealerSubareaScopeList from '@/views/common/dealerSubareaScopeList.vue'
+import bookReason from '@/views/common/bookReason'
+import { financeBookSave, financeBookFindBySn } from '@/api/financeBook.js'
+export default {
+  name: 'ASBaseModal',
+  mixins: [commonMixin],
+  components: { VSelect, Upload, employee, dealerSubareaScopeList, bookReason },
+  props: {
+    show: [Boolean],
+    bookSn: {
+      type: String,
+      default: ''
+    }
+  },
+  data () {
+    return {
+      opened: this.show,
+      spinning: false,
+      disabled: false,
+      title: '新增对账单',
+      confirmLoading: false,
+      formItemLayout: {
+        labelCol: { span: 4 },
+        wrapperCol: { span: 18 }
+      },
+      form: {
+        dealerSn: undefined,
+        dealerName: undefined,
+        remarks: ''
+      },
+      rules: {
+        dealerSn: [ { required: true, message: '请选择客户', trigger: ['change', 'blur'] } ]
+      }
+    }
+  },
+  methods: {
+    // 客户
+    custChange (v) {
+      if (v && v.key) {
+        this.form.dealerSn = v.key
+        this.form.dealerName = v.row ? v.row.dealerName : ''
+      } else {
+        this.form.dealerSn = ''
+        this.form.dealerName = ''
+      }
+    },
+    //  保存
+    handleSubmit (e) {
+      e.preventDefault()
+      const _this = this
+      this.$refs.ruleForm.validate(valid => {
+        if (valid) {
+          _this.salesSaveFun()
+        } else {
+          return false
+        }
+      })
+    },
+    // 新建或编辑销售单
+    salesSaveFun () {
+      const _this = this
+      const form = JSON.parse(JSON.stringify(_this.form))
+      _this.spinning = true
+      financeBookSave(form).then(res => {
+        if (res.status == 200) {
+          _this.$message.success(res.message)
+          // 编辑
+          if (this.bookSn) {
+            _this.$emit('refashData')
+          } else {
+            // 新增
+            _this.$router.push({ name: 'accountStatementEdit', params: { sn: res.data.bookSn } })
+          }
+          _this.cancel()
+          _this.spinning = false
+        } else {
+          _this.spinning = false
+        }
+      })
+    },
+    //  详情
+    getDetail () {
+      this.title = '编辑对账单'
+      this.spinning = true
+      this.confirmLoading = true
+      financeBookFindBySn({ bookSn: this.bookSn }).then(res => {
+        if (res.status == 200) {
+          const data = res.data
+          this.form = Object.assign(this.form, data)
+          // 回显客户
+          if (this.form.dealerSn) {
+            this.$nextTick(() => {
+              this.$refs.settleClientName.getDetail(this.form.dealerSn)
+            })
+          }
+        } else {
+          this.$refs.ruleForm.resetFields()
+        }
+        this.spinning = false
+        this.confirmLoading = false
+      })
+    },
+    cancel () {
+      this.opened = false
+      this.$emit('cancel')
+      this.$refs.ruleForm.resetFields()
+    },
+    async pageInit () {
+      this.$nextTick(() => {
+        this.$refs.ruleForm.resetFields()
+        if (this.$refs.settleClientName) {
+          this.$refs.settleClientName.resetForm()
+        }
+      })
+      this.form = {
+        dealerSn: undefined,
+        dealerName: undefined,
+        remarks: ''
+      }
+      //  编辑页
+      if (this.bookSn) {
+        this.getDetail()
+      }
+    }
+  },
+  watch: {
+    show (newValue, oldValue) {
+      this.opened = newValue
+      if (newValue) {
+        this.pageInit()
+      }
+    }
+  }
+}
+</script>

+ 516 - 0
src/views/financialManagement/accountStatement/edit.vue

@@ -0,0 +1,516 @@
+<template>
+  <div class="salesReturnEdit-wrap">
+    <a-spin :spinning="spinning" tip="Loading...">
+      <a-page-header :ghost="false" :backIcon="false" class="salesReturnEdit-back">
+        <!-- 自定义的二级文字标题 -->
+        <template slot="subTitle">
+          <a id="salesReturnEdit-back-btn" href="javascript:;" @click="handleBack">
+            <a-icon type="left" />
+            返回列表
+          </a>
+          <span style="margin: 0 15px;color: #666;font-weight: bold;">单号:{{ detailsData&&detailsData.sparePartsReturnNo }}</span>
+          <span style="margin: 0 10px;color: #666;">供应商:{{ detailsData && detailsData.supplier && detailsData.supplier.supplierName }}</span>
+          <a-button type="link" size="small" class="button-default" @click.stop="handleEditBase" >
+            <a-icon type="edit" /> 编辑备注
+          </a-button>
+        </template>
+      </a-page-header>
+      <a-card size="small" :bordered="false" class="salesReturnEdit-cont">
+        <queryPart
+          ref="partQuery"
+          :newLoading="isInster"
+          :addMoreLoading="addMoreLoading"
+          @add="saveProduct"
+          @bachAdd="saveMoreProduct"></queryPart>
+      </a-card>
+      <a-card size="small" :bordered="false" class="salesReturnEdit-cont">
+        <a-alert style="margin-bottom: 10px;" type="info">
+          <div slot="message" class="total-bar">
+            <div v-if="statisticsObj">
+              <span>申请退货数量:{{ statisticsObj && (statisticsObj.qty || statisticsObj.qty == 0) ? statisticsObj.qty : '--' }};</span>
+              <span v-if="$hasPermissions('B_purchaseReturnEdit_costPrice')">退货金额:{{ statisticsObj && statisticsObj.totalCost || statisticsObj.totalCost == 0 ? statisticsObj.totalCost : '--' }};</span>
+            </div>
+          </div>
+        </a-alert>
+        <div class="table-page-search-wrapper" style="display:flex;align-items: center;justify-content: space-between;">
+          <div style="flex-grow:1;">
+            <a-form layout="inline" @keyup.enter.native="$refs.table.refresh(true)">
+              <a-row :gutter="15">
+                <a-col :md="6" :sm="24">
+                  <a-form-item label="入库单号"><a-input v-model.trim="productForm.sparePartsNo" allowClear placeholder="请输入入库单号" /></a-form-item>
+                </a-col>
+                <a-col :md="6" :sm="24">
+                  <a-form-item label="产品编码"><a-input v-model.trim="productForm.productCode" allowClear placeholder="请输入产品编码" /></a-form-item>
+                </a-col>
+                <a-col :md="6" :sm="24">
+                  <a-form-item label="产品名称"><a-input v-model.trim="productForm.productName" allowClear placeholder="请输入产品名称" /></a-form-item>
+                </a-col>
+                <a-col :md="6" :sm="24" style="margin-bottom: 10px;">
+                  <a-button type="primary" @click="$refs.table.refresh(true)">查询</a-button>
+                  <a-button style="margin-left: 5px" @click="resetSearchForm">重置</a-button>
+                </a-col>
+              </a-row>
+            </a-form>
+          </div>
+        </div>
+        <!-- 已选配件列表 -->
+        <s-table
+          class="sTable"
+          ref="table"
+          size="small"
+          :rowKey="(record) => record.id"
+          :columns="columns"
+          :data="loadData"
+          :defaultLoadData="false"
+          :scroll="{ y: 300 }"
+          bordered>
+          <!--申请退货数量 -->
+          <template slot="qty" slot-scope="text, record">
+            <a-input-number
+              id="salesReturn-qty"
+              size="small"
+              v-model="record.qty"
+              :precision="0"
+              :min="1"
+              :max="record.qty"
+              placeholder="请输入"
+              style="width: 100%;"
+              @blur="e => onCellBlur(e.target.value, record)"
+            />
+          </template>
+
+          <!-- 操作 -->
+          <template slot="action" slot-scope="text, record">
+            <a-button
+              size="small"
+              type="link"
+              :loading="delLoading"
+              class="button-error"
+              @click="handleDel(record)"
+              id="salesReturn-Del">删除</a-button>
+          </template>
+        </s-table>
+      </a-card>
+    </a-spin>
+    <div class="affix-cont">
+      <a-button
+        size="large"
+        style="padding: 0 60px;"
+        :disabled="spinning"
+        type="primary"
+        class="button-primary"
+        @click="handleSubmit"
+        id="salesReturn-handleSubmit">提交</a-button>
+    </div>
+    <!-- 编辑基础信息弹窗 -->
+    <baseModal v-drag :show="openModal" @cancel="openModal=false" @refashData="getBasicsData"></baseModal>
+  </div>
+</template>
+
+<script>
+import { commonMixin } from '@/utils/mixin'
+import { STable, VSelect } from '@/components'
+import queryPart from './queryPart.vue'
+import baseModal from './baseModal.vue'
+import {
+  sparePartsReturnQueryPage,
+  queryPageCount,
+  sparePartsReturnDetailDelete,
+  sparePartsReturnDetailSave,
+  sparePartsReturnSubmit,
+  sparePartsReturnInfo,
+  sparePartsReturnDetailSaveBatch
+} from '@/api/sparePartsReturn'
+export default {
+  name: 'AccountStatementEdit',
+  mixins: [commonMixin],
+  components: {
+    STable,
+    VSelect,
+    queryPart,
+    baseModal
+  },
+  data () {
+    return {
+      spinning: false,
+      isInster: false, // 是否正在添加产品
+      delLoading: false,
+      productForm: {
+        productName: '',
+        productCode: '',
+        sparePartsNo: '',
+        orderBy: 'sprd.CREATE_DATE DESC'
+      },
+      bookSn: null,
+      sparePartsReturnNo: null,
+      chooseList: [],
+      // 加载数据方法 必须为 Promise 对象
+      loadData: parameter => {
+        this.productForm.bookSn = this.bookSn
+        return sparePartsReturnQueryPage(Object.assign(parameter, this.productForm)).then(res => {
+          let data
+          if (res.status == 200) {
+            data = res.data
+            const no = (data.pageNo - 1) * data.pageSize
+            for (var i = 0; i < data.list.length; i++) {
+              data.list[i].no = no + i + 1
+            }
+          }
+          this.chooseList = data.list
+          return data
+        })
+      },
+      openModal: false, // 修改信息弹窗
+      statisticsObj: null, // 统计明细
+      detailsData: null, // 基础信息数据
+      addMoreLoading: false, // 批量添加动画
+      grabFlag: undefined
+    }
+  },
+  computed: {
+    columns () {
+      const _this = this
+      const arr = [
+        { title: '序号', dataIndex: 'no', align: 'center', width: '4%' },
+        {
+          title: '入库单号',
+          dataIndex: 'sparePartsNo',
+          width: '18%',
+          align: 'center',
+          customRender: function (text) {
+            return text || '--'
+          }
+        },
+        {
+          title: '产品编码',
+          dataIndex: 'product.code',
+          width: '18%',
+          align: 'center',
+          customRender: function (text) {
+            return text || '--'
+          }
+        },
+        {
+          title: '产品名称',
+          dataIndex: 'product.name',
+          width: '25%',
+          align: 'left',
+          customRender: function (text) {
+            return text || '--'
+          },
+          ellipsis: true
+        },
+        {
+          title: '单位',
+          dataIndex: 'product.unit',
+          align: 'center',
+          width: '6%',
+          customRender: function (text) {
+            return text || '--'
+          }
+        },
+        {
+          title: '批次号',
+          dataIndex: 'stockBatchNo',
+          align: 'center',
+          width: '10%',
+          customRender: function (text) {
+            return text || '--'
+          }
+        },
+        { title: '申请退货数量', align: 'center', width: '13%', scopedSlots: { customRender: 'qty' } },
+        { title: '操作', scopedSlots: { customRender: 'action' }, width: '10%', align: 'center' }
+      ]
+      if (this.$hasPermissions('B_purchaseReturnEdit_costPrice')) {
+        arr.splice(6, 0, {
+          title: '退货单价',
+          dataIndex: 'cost',
+          width: '8%',
+          align: 'right',
+          customRender: function (text) {
+            return text || text == 0 ? _this.toThousands(text, 2) : '--'
+          }
+        })
+        arr.splice(8, 0, {
+          title: '退款金额',
+          dataIndex: 'totalCost',
+          width: '8%',
+          align: 'right',
+          customRender: function (text) {
+            return text || text == 0 ? _this.toThousands(text, 2) : '--'
+          }
+        })
+      }
+      return arr
+    }
+  },
+  methods: {
+    // 编辑基础信息
+    handleEditBase () {
+      this.openModal = true
+    },
+    //  返回列表
+    handleBack () {
+      this.$router.push({ name: `accountStatementList` })
+    },
+    // 删除所选产品
+    handleDel (row) {
+      const _this = this
+      this.$confirm({
+        title: '提示',
+        content: '确认要删除吗?',
+        centered: true,
+        closable: true,
+        onOk () {
+          _this.delLoading = true
+          _this.spinning = true
+          sparePartsReturnDetailDelete({ detailSn: row.sparePartsReturnDetailSn })
+            .then(res => {
+              if (res.status == 200) {
+                _this.resetTable(false)
+                _this.getStatisticsData()
+                _this.getChooseList()
+                _this.$refs.partQuery.refreshLength()
+              }
+              _this.$message.info(res.message)
+              _this.delLoading = false
+              _this.spinning = false
+            })
+            .catch(err => {
+              _this.delLoading = false
+            })
+        }
+      })
+    },
+    // 刷新已选表格
+    resetTable (flag) {
+      this.$refs.table.refresh(flag)
+    },
+    //  重置
+    resetSearchForm (flag) {
+      this.productForm.productName = ''
+      this.productForm.productCode = ''
+      this.productForm.sparePartsNo = ''
+      this.$refs.table.refresh(!!flag)
+    },
+    // 已选产品  blur
+    onCellBlur (val, record) {
+      if (val * 1 > record.putQty * 1) {
+        this.$message.warning('申请退货数量不能大于入库数量!')
+        this.$refs.table.refresh(true)
+        return
+      }
+      const ajax_data = {
+        bookSn: this.bookSn,
+        sparePartsReturnNo: this.sparePartsReturnNo,
+        sparePartsDetailSn: record.sparePartsDetailSn,
+        productSn: record.productSn,
+        sparePartsReturnDetailSn: record.sparePartsReturnDetailSn,
+        stockDetailSn: record.stockDetailSn,
+        productCode: record.productCode,
+        putQty: record.putQty, // 入库数量
+        returnedQty: record.returnedQty, // 已退数量
+        qty: val, // 申退数量
+        cost: record.cost, // 成本
+        stockBatchNo: record.stockBatchNo, // 批次号
+        warehouseSn: record.warehouseSn, // 仓库sn
+        warehouseLocationSn: record.warehouseLocationSn, // 仓位sn
+        sparePartsNo: record.sparePartsNo,
+        sparePartsSn: record.sparePartsSn
+      }
+      this.saveEdit(ajax_data)
+    },
+    // 添加或修改产品
+    saveProduct (row) {
+      if (this.isInster) {
+        // 防止多次添加产品
+        return
+      }
+      this.isInster = true
+      const paramsData = {
+        bookSn: this.bookSn,
+        sparePartsReturnNo: this.sparePartsReturnNo,
+        sparePartsDetailSn: row.sparePartsDetailSn,
+        productSn: row.productSn,
+        stockDetailSn: row.stockDetailSn,
+        productCode: row.productCode,
+        putQty: row.productQty, // 入库数量
+        returnedQty: row.returnedQty, // 已退数量
+        qty: row.qty, // 申退数量
+        cost: row.productCost, // 成本
+        stockBatchNo: row.sparePartsBatchNo, // 批次号
+        warehouseSn: row.warehouseSn, // 仓库sn
+        warehouseLocationSn: row.warehouseLocationSn, // 仓位sn
+        sparePartsNo: row.sparePartsNo,
+        sparePartsSn: row.sparePartsSn
+      }
+      this.saveEdit(paramsData)
+    },
+    saveMoreProduct (data) {
+      if (this.addMoreLoading) {
+        // 防止多次添加产品
+        return
+      }
+      this.addMoreLoading = true
+      var ajax_data = []
+      data.forEach(item => {
+        const obj = {
+          bookSn: this.bookSn,
+          sparePartsReturnNo: this.sparePartsReturnNo,
+          sparePartsDetailSn: item.sparePartsDetailSn,
+          productSn: item.productSn,
+          stockDetailSn: item.stockDetailSn,
+          productCode: item.productCode,
+          putQty: item.productQty, // 入库数量
+          returnedQty: item.returnedQty, // 已退数量
+          qty: item.qty, // 申退数量
+          cost: item.productCost, // 成本
+          stockBatchNo: item.sparePartsBatchNo, // 批次号
+          warehouseSn: item.warehouseSn, // 仓库sn
+          warehouseLocationSn: item.warehouseLocationSn, // 仓位sn
+          sparePartsNo: item.sparePartsNo,
+          sparePartsSn: item.sparePartsSn
+        }
+        ajax_data.push(obj)
+      })
+      this.saveMore(ajax_data)
+    },
+    saveEdit (params) {
+      this.spinning = true
+      sparePartsReturnDetailSave(params).then(res => {
+        if (res.status == 200) {
+          this.getStatisticsData()
+          this.$refs.table.refresh(true)
+          this.getChooseList()
+        }
+        this.isInster = false
+        this.spinning = false
+        this.addMoreLoading = false
+      }).catch(err => {
+        this.isInster = false
+      })
+    },
+    saveMore (params) {
+      this.spinning = true
+      sparePartsReturnDetailSaveBatch(params)
+        .then(res => {
+          if (res.status == 200) {
+            this.getStatisticsData()
+            this.getChooseList()
+            this.$refs.table.refresh(true)
+            this.$refs.partQuery.refreshLength()
+          }
+          this.isInster = false
+          this.spinning = false
+          this.addMoreLoading = false
+        })
+        .catch(err => {
+          this.isInster = false
+          this.addMoreLoading = false
+          this.spinning = false
+        })
+    },
+    // 提交采购退货
+    handleSubmit (data) {
+      this.spinning = true
+      sparePartsReturnSubmit({ bookSn: this.bookSn, ...data }).then(res => {
+        if (res.status == 200) {
+          this.handleBack()
+          this.$message.success(res.message)
+        }
+        this.spinning = false
+      })
+    },
+    pageInit () {
+      this.bookSn = this.$route.query.sn
+      this.getStatisticsData()
+      this.getBasicsData()
+      this.resetSearchForm(true)
+    },
+    getChooseList () {
+      this.$refs.partQuery.pageInit(this.supplierSn, this.bookSn, this.detailsData ? this.detailsData.warehouseSn : undefined, this.detailsData.grabFlag)
+    },
+    // 获取页面统计数据
+    getStatisticsData () {
+      this.getBasicsData(true)
+      queryPageCount({ bookSn: this.bookSn }).then(res => {
+        if (res.status == 200) {
+          if (res.data) {
+            res.data.totalCost = res.data && (res.data.totalCost || res.data.totalCost == 0) ? this.toThousands(res.data.totalCost, 2) : '--'
+            this.statisticsObj = res.data
+          } else {
+            this.statisticsObj = null
+          }
+        } else {
+          this.statisticsObj = null
+        }
+      })
+    },
+    // 获取基础信息
+    getBasicsData (flag) {
+      sparePartsReturnInfo({ sn: this.bookSn }).then(res => {
+        if (res.status == 200) {
+          this.detailsData = res.data
+        } else {
+          this.detailsData = null
+        }
+        const _this = this
+        if (!flag) {
+          this.$nextTick(() => {
+            _this.getChooseList()
+          })
+        }
+      })
+    }
+  },
+  mounted () {
+    if (!this.$store.state.app.isNewTab) {
+      // 页签刷新时调用
+      this.pageInit()
+    }
+  },
+  activated () {
+    // 如果是新页签打开或者进入新的子页(例:存在列表第2条数据编辑页页签时再打开第4条数据的编辑页),则重置当前页面
+    if (this.$store.state.app.isNewTab || !this.$store.state.app.isNewSubTab) {
+      this.pageInit()
+    }
+  },
+  beforeRouteEnter (to, from, next) {
+    next(vm => {})
+  }
+}
+</script>
+
+<style lang="less">
+.salesReturnEdit-wrap {
+  position: relative;
+  height: 100%;
+  padding-bottom: 51px;
+  box-sizing: border-box;
+  > .ant-spin-nested-loading {
+    overflow-y: scroll;
+    height: 100%;
+  }
+  .salesReturnEdit-cont {
+    margin-top: 6px;
+    .ant-divider-horizontal {
+      margin: 10px 0 24px;
+    }
+    .total-bar {
+      display: flex;
+      align-items: center;
+      justify-content: space-between;
+      > div {
+        &:last-child {
+          display: flex;
+          align-items: center;
+          justify-content: space-between;
+          > div {
+            padding: 0 10px;
+          }
+        }
+      }
+    }
+  }
+}
+</style>

+ 299 - 0
src/views/financialManagement/accountStatement/list.vue

@@ -0,0 +1,299 @@
+<template>
+  <div>
+    <a-card size="small" :bordered="false" class="searchBoxNormal">
+      <!-- 搜索条件 -->
+      <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 id="accountStatement-rangeDate" ref="rangeDate" :value="creatDate" @change="dateChange" />
+              </a-form-item>
+            </a-col>
+            <a-col :md="6" :sm="24">
+              <a-form-item label="客户名称">
+                <a-input id="accountStatement-dealerName" v-model.trim="queryParam.dealerName" allowClear placeholder="请输入客户名称"/>
+              </a-form-item>
+            </a-col>
+            <a-col :md="6" :sm="24">
+              <a-form-item label="对账单号">
+                <a-input id="accountStatement-bookNo" v-model.trim="queryParam.bookNo" allowClear placeholder="请输入收款单号"/>
+              </a-form-item>
+            </a-col>
+            <a-col :md="6" :sm="24">
+              <a-form-item label="业务状态">
+                <v-select
+                  v-model="queryParam.status"
+                  ref="status"
+                  id="accountStatement-status"
+                  code="FINANCE_BOOK_STATE"
+                  placeholder="请选择状态"
+                  allowClear></v-select>
+              </a-form-item>
+            </a-col>
+            <a-col :md="24" :sm="24" style="margin-bottom: 10px;text-align: center;">
+              <a-button type="primary" @click="$refs.table.refresh(true)" :disabled="disabled" id="accountStatement-refresh">查询</a-button>
+              <a-button style="margin-left: 5px" @click="resetSearchForm" :disabled="disabled" id="accountStatement-reset">重置</a-button>
+            </a-col>
+          </a-row>
+        </a-form>
+      </div>
+    </a-card>
+    <a-card size="small" :bordered="false" class="accountStatement-wrap">
+      <a-spin :spinning="spinning" tip="Loading...">
+        <!-- 操作按钮 -->
+        <div class="table-operator">
+          <div class="flex-center">
+            <a-button type="primary" v-if="$hasPermissions('B_fc_new')" @click="handleAdd">新增</a-button>
+            <div class="tongji-bar"></div>
+          </div>
+          <div></div>
+        </div>
+        <!-- 列表 -->
+        <s-table
+          class="sTable fixPagination"
+          ref="table"
+          :style="{ height: tableHeight+80+'px' }"
+          size="small"
+          :rowKey="(record) => record.id"
+          :columns="columns"
+          :data="loadData"
+          :scroll="{ y: tableHeight }"
+          :pageSize="30"
+          :defaultLoadData="false"
+          bordered>
+          <!-- 单号 -->
+          <template slot="bookNo" slot-scope="text, record">
+            <span v-if="$hasPermissions('B_fc_detail')" class="link-bule" @click="handleDetail(record)">{{ record.bookNo }}</span>
+            <span v-else>{{ record.bookNo }}</span>
+          </template>
+          <!-- 操作 -->
+          <template slot="action" slot-scope="text, record">
+            <a-button
+              v-if="record.status=='WAIT_SUBMIT'"
+              size="small"
+              type="link"
+              class="button-info"
+              @click="handleEdit(record)"
+            >
+              编辑
+            </a-button>
+            <a-button
+              v-if="record.status=='WAIT_SUBMIT'"
+              size="small"
+              type="link"
+              class="button-error"
+              @click="handleDel(record)"
+            >
+              删除
+            </a-button>
+            <a-button
+              v-if="record.status=='AUDIT_REJECT'"
+              size="small"
+              type="link"
+              class="button-info"
+              @click="confront(record)"
+            >
+              对单
+            </a-button>
+            <a-button
+              v-if="record.status=='AUDIT_PASS'"
+              size="small"
+              type="link"
+              class="button-info"
+              @click="checkAcount(record)"
+            >
+              对账
+            </a-button>
+          </template>
+        </s-table>
+      </a-spin>
+      <!-- 基础信息 -->
+      <baseModal v-drag :show="baseModal" :bookSn="itemSn" @cancel="baseModal=false"></baseModal>
+    </a-card>
+  </div>
+</template>
+
+<script>
+import { commonMixin } from '@/utils/mixin'
+import { STable, VSelect } from '@/components'
+import rangeDate from '@/views/common/rangeDate.vue'
+import baseModal from './baseModal.vue'
+import { financeBookQueryPage, financeBookDeleteBySn } from '@/api/financeBook.js'
+export default {
+  name: 'AccountStatementList',
+  mixins: [commonMixin],
+  components: { STable, VSelect, rangeDate, baseModal },
+  data () {
+    return {
+      spinning: false,
+      openModal: false,
+      baseModal: false,
+      tableHeight: 0,
+      queryParam: { //  查询条件
+        beginDate: '',
+        endDate: '',
+        bookNo: '',
+        dealerName: '',
+        status: undefined
+      },
+      disabled: false, //  查询、重置按钮是否可操作
+      creatDate: [], //  创建时间
+      auditDate: [], // 审核时间
+      advanced: true,
+      itemSn: null,
+      itemId: null,
+      // 加载数据方法 必须为 Promise 对象
+      loadData: parameter => {
+        this.disabled = true
+        this.spinning = true
+        const params = Object.assign(parameter, this.queryParam)
+        return financeBookQueryPage(params).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.total = data.count || 0
+            this.disabled = false
+          }
+          this.spinning = false
+          return data
+        })
+      },
+      total: 0, // 合计
+      countData: null
+    }
+  },
+  // 根据权限显示列表字段
+  computed: {
+    columns () {
+      const arr = [
+        { title: '序号', dataIndex: 'no', width: '4%', align: 'center' },
+        { title: '创建时间', dataIndex: 'createDate', width: '8%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '对账单号', scopedSlots: { customRender: 'bookNo' }, width: '8%', align: 'center' },
+        { title: '客户名称', dataIndex: 'payerName', width: '20%', align: 'left', customRender: function (text) { return text || '--' }, ellipsis: true },
+        { title: '余额', dataIndex: 'orderTotalAmount', width: '8%', align: 'right', customRender: text => ((text || text == 0) ? this.toThousands(text) : '--') },
+        { title: '对单时间', dataIndex: 'auditDate', width: '8%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '对账时间', dataIndex: 'updateDate', width: '8%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '业务状态', dataIndex: 'statusDictValue', width: '8%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '操作', scopedSlots: { customRender: 'action' }, width: '10%', align: 'center' }
+      ]
+      return arr
+    }
+  },
+  methods: {
+    //  创建时间  change
+    dateChange (date) {
+      this.queryParam.beginDate = date[0] ? date[0] : ''
+      this.queryParam.endDate = date[1] ? date[1] : ''
+    },
+    //  重置
+    resetSearchForm () {
+      this.creatDate = []
+      this.$refs.rangeDate.resetDate(this.creatDate)
+      this.queryParam.beginDate = ''
+      this.queryParam.endDate = ''
+      this.queryParam.dealerName = ''
+      this.queryParam.bookNo = ''
+      this.queryParam.status = undefined
+      this.$refs.table.refresh(true)
+    },
+    // 新增
+    handleAdd () {
+      this.baseModal = true
+    },
+    // 编辑
+    handleEdit (row) {
+      this.$router.push({ name: 'accountStatementEdit', params: { sn: row.bookSn, type: 0 } })
+    },
+    // 删除
+    handleDel (row) {
+      const _this = this
+      this.$confirm({
+        title: '提示',
+        content: '确认要删除吗?',
+        centered: true,
+        closable: true,
+        onOk () {
+          _this.spinning = true
+          financeBookDeleteBySn({ bookSn: row.bookSn }).then(res => {
+            if (res.status == 200) {
+              _this.$message.success(res.message)
+              _this.$refs.table.refresh()
+              _this.spinning = false
+            } else {
+              _this.spinning = false
+            }
+          })
+        }
+      })
+    },
+    // 详情
+    handleDetail (row) {
+    },
+    // 对账
+    checkAcount (row) {
+    },
+    // 对单
+    confront (row) {
+    },
+    pageInit () {
+      const _this = this
+      this.$nextTick(() => { // 页面渲染完成后的回调
+        _this.setTableH()
+      })
+    },
+    setTableH () {
+      const tableSearchH = this.$refs.tableSearch.offsetHeight
+      this.tableHeight = window.innerHeight - tableSearchH - 250
+    }
+  },
+  watch: {
+    advanced (newValue, oldValue) {
+      const _this = this
+      this.$nextTick(() => { // 页面渲染完成后的回调
+        _this.setTableH()
+      })
+    },
+    '$store.state.app.winHeight' (newValue, oldValue) { //  窗口变更时,需同时更改表格高度
+      this.setTableH()
+    }
+  },
+  mounted () {
+    if (!this.$store.state.app.isNewTab) { // 页签刷新时调用
+      this.pageInit()
+      this.resetSearchForm()
+    }
+  },
+  activated () {
+    // 如果是新页签打开,则重置当前页面
+    if (this.$store.state.app.isNewTab) {
+      this.pageInit()
+      this.resetSearchForm()
+    }
+    // 仅刷新列表,不重置页面
+    if (this.$store.state.app.updateList) {
+      this.pageInit()
+      this.$refs.table.refresh()
+    }
+  },
+  beforeRouteEnter (to, from, next) {
+    next(vm => {})
+  }
+}
+</script>
+
+<style lang="less">
+  .accountStatement-wrap{
+    .active{
+      color: #ed1c24;
+      cursor: pointer;
+    }
+    .common{
+      color: rgba(0, 0, 0);
+    }
+  }
+</style>

+ 263 - 0
src/views/financialManagement/accountStatement/queryPart.vue

@@ -0,0 +1,263 @@
+<template>
+  <div class="salesReturnList-wrap">
+    <!-- 搜索条件 -->
+    <div class="table-page-search-wrapper">
+      <div style="width:100%">
+        <a-form layout="inline" @keyup.enter.native="$refs.chooseTable.refresh(true)">
+          <a-row :gutter="15">
+            <a-col :md="5" :sm="24">
+              <a-form-item label="入库单号">
+                <a-input id="salesReturnList-productCode" v-model.trim="queryParam.sparePartsNo" allowClear placeholder="请输入入库单号"/>
+              </a-form-item>
+            </a-col>
+            <a-col :md="5" :sm="24">
+              <a-form-item label="财务审核时间">
+                <rangeDate ref="rangeDate" :value="warehousingDate" @change="dateChange" />
+              </a-form-item>
+            </a-col>
+            <a-col :md="5" :sm="24">
+              <a-form-item label="产品编码">
+                <a-input id="salesReturnList-productCode" v-model.trim="queryParam.productCode" allowClear placeholder="请输入产品编码"/>
+              </a-form-item>
+            </a-col>
+            <a-col :md="5" :sm="24">
+              <a-form-item label="产品名称">
+                <a-input id="salesReturnList-productName" v-model.trim="queryParam.productName" allowClear placeholder="请输入产品名称"/>
+              </a-form-item>
+            </a-col>
+            <a-col :md="4" :sm="24">
+              <a-button type="primary" @click="$refs.chooseTable.refresh(true)" id="salesReturnList-refresh">查询</a-button>
+              <a-button style="margin-left: 5px" @click="resetSearchForm" id="salesReturnList-reset">重置</a-button>
+            </a-col>
+            <a-col :md="24" :sm="24" style="margin-bottom: 10px;display: flex;align-items: center;justify-content: space-between;">
+              <div>
+                <a-button type="primary" style="margin-right: 5px" @click="handleBatchAdd" :loading="addMoreLoading">批量添加</a-button>
+                <span v-if="selNums&&selNums!=0" style="margin:0 10px;">已选中{{ selNums }}项</span>
+              </div>
+              <div v-if="queryParam.grabFlag==1">
+                <a-checkbox @change="onChange" :checked="isChecked">
+                  显示最大可退数量为0的产品
+                </a-checkbox>
+              </div>
+            </a-col>
+          </a-row>
+        </a-form>
+      </div>
+    </div>
+    <!-- 列表 -->
+    <s-table
+      class="sTable"
+      ref="chooseTable"
+      size="small"
+      :rowKey="(record) => record.no"
+      rowKeyName="no"
+      :row-selection="{ columnWidth: 40,getCheckboxProps: record => ({ props: { disabled: record.currentStockQty == 0 || record.isCheckedFlag} }) }"
+      @rowSelection="rowSelectionFun"
+      :columns="columns"
+      :data="loadData"
+      :defaultLoadData="false"
+      :scroll="{ y: 300 }"
+      bordered>
+      <!-- 申请退货数量 -->
+      <template slot="qty" slot-scope="text, record">
+        <div @dblclick.stop>
+          <a-input-number
+            size="small"
+            v-model="record.qty"
+            :precision="0"
+            :min="1"
+            :disabled="record.currentStockQty == 0"
+            :max="record.currentStockQty"
+            style="width: 100%;"
+            placeholder="请输入"/>
+        </div>
+      </template>
+      <!-- 操作 -->
+      <template slot="action" slot-scope="text, record">
+        <a-button
+          size="small"
+          type="link"
+          class="button-info"
+          :loading="newLoading"
+          v-if="record.currentStockQty != 0 && !record.isCheckedFlag"
+          @click="handleAdd(record)"
+        >添加</a-button>
+        <span v-else>--</span>
+      </template>
+    </s-table>
+  </div>
+</template>
+
+<script>
+import { queryDetailStockPage } from '@/api/spareParts'
+import { queryDetailSnListBySn } from '@/api/sparePartsReturn'
+import { STable, VSelect } from '@/components'
+import rangeDate from '@/views/common/rangeDate.vue'
+import { toThousands } from '@/libs/tools.js'
+export default {
+  name: 'QueryPart',
+  components: { STable, VSelect, rangeDate },
+  props: {
+    newLoading: Boolean,
+    isShowPrice: {
+      type: Boolean,
+      default: true
+    },
+    // 是否显示仓库实收数量
+    showReceiveQty: {
+      type: Boolean,
+      default: false
+    },
+    addMoreLoading: {
+      type: Boolean,
+      default: false
+    }
+  },
+  data () {
+    return {
+      buyerSn: '',
+      queryParam: { //  查询条件
+        productName: '', // 产品名称
+        productCode: '', //  产品编码
+        beginDate: '',
+        endDate: '',
+        sparePartsNo: '',
+        isZero: 0,
+        createDate: undefined,
+        grabFlag: ''
+      },
+      warehousingDate: [], // 入库时间
+      rowSelectionInfo: null,
+      isChecked: false,
+      repeatList: null,
+      warehouseSn: null,
+      // 加载数据方法 必须为 Promise 对象
+      loadData: parameter => {
+        this.queryParam.supplierSn = this.buyerSn
+        this.queryParam.createDate = '2023-01-01 00:00:00'
+        this.queryParam.warehouseSn = this.warehouseSn
+        return queryDetailStockPage(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
+              data.list[i].qty = data.list[i].currentStockQty
+              data.list[i].isCheckedFlag = this.repeatList.findIndex(item => { return item == data.list[i].sparePartsDetailSn }) > -1
+            }
+          }
+          return data
+        })
+      }
+    }
+  },
+  computed: {
+    columns () {
+      const arr = [
+        { title: '序号', dataIndex: 'no', width: '6%', align: 'center' },
+        { title: '入库单号', dataIndex: 'sparePartsNo', width: '24%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '产品编码', dataIndex: 'product.code', width: '24%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '产品名称', dataIndex: 'product.name', width: '24%', align: 'left', customRender: function (text) { return text || '--' }, ellipsis: true },
+        { title: '单位', dataIndex: 'product.unit', width: '6%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '批次号', dataIndex: 'sparePartsBatchNo', width: '13%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '入库数量', dataIndex: 'productQty', width: '9%', align: 'center', customRender: function (text) { return (text || text == 0) ? text : '--' } },
+        // { title: '已退数量', dataIndex: 'returnedQty', width: '9%', align: 'center', customRender: function (text) { return (text || text == 0) ? text : '--' } },
+        { title: '最大可退数量', dataIndex: 'currentStockQty', width: '9%', align: 'center', customRender: function (text) { return (text || text == 0) ? text : '--' } },
+        { title: '申请退货数量', width: '10%', align: 'center', scopedSlots: { customRender: 'qty' } },
+        { title: '操作', scopedSlots: { customRender: 'action' }, width: '10%', align: 'center' }
+      ]
+      if (this.$hasPermissions('B_purchaseReturnEdit_costPrice')) {
+        arr.splice(6, 0, { title: '入库单价', dataIndex: 'productCost', width: '8%', align: 'right', customRender: function (text) { return ((text || text == 0) ? toThousands(text, 2) : '--') } })
+      }
+      if (this.queryParam.grabFlag == 1) { // 抓单
+        const pos = this.$hasPermissions('B_purchaseReturnEdit_costPrice') ? 8 : 7
+        arr.splice(pos, 0, { title: '已退数量', dataIndex: 'returnedQty', width: '9%', align: 'center', customRender: function (text) { return (text || text == 0) ? text : '--' } })
+      }
+      return arr
+    },
+    selNums () {
+      return this.rowSelectionInfo && this.rowSelectionInfo.selectedRowKeys.length || 0
+    }
+  },
+  methods: {
+    //  重置
+    resetSearchForm () {
+      this.queryParam.productName = ''
+      this.queryParam.productCode = ''
+      this.queryParam.sparePartsNo = ''
+      this.warehousingDate = []
+      this.$refs.rangeDate.resetDate(this.warehousingDate)
+      this.$refs.chooseTable.refresh(true)
+    },
+    onChange (e) {
+      this.isChecked = !this.isChecked
+      this.queryParam.isZero = e.target.checked ? 1 : 0
+      this.$refs.chooseTable.refresh()
+    },
+    //  入库时间  change
+    dateChange (date) {
+      this.queryParam.beginDate = date[0] ? date[0] : ''
+      this.queryParam.endDate = date[1] ? date[1] : ''
+    },
+    pageInit (buyerSn, returnSn, warehouseSn, grabFlag) {
+      this.buyerSn = buyerSn
+      this.queryParam.grabFlag = grabFlag
+      this.warehouseSn = warehouseSn
+      this.getRepeatResult(returnSn)
+      this.$refs.chooseTable.refresh()
+      // this.$refs.chooseTable.clearSelected()
+    },
+    // 添加
+    handleAdd (row) {
+      const selectArr = this.rowSelectionInfo ? this.rowSelectionInfo.selectedRowKeys : null
+      if (selectArr && selectArr.length > 0) {
+        const pot = selectArr.findIndex(item => { return item == row.id })
+        selectArr.splice(pot, 1)
+        const index = this.rowSelectionInfo.selectedRows.findIndex(item => { return item.sparePartsDetailSn == row.sparePartsDetailSn })
+        this.rowSelectionInfo.selectedRows.splice(index, 1)
+        this.$nextTick(() => { // 页面渲染完成后的回调
+          this.$refs.chooseTable.setTableSelected(selectArr, this.rowSelectionInfo.selectedRows) // 设置表格选中项
+        })
+      }
+      this.$emit('add', row)
+    },
+    // 删除后选中长度恢复
+    refreshLength (row) {
+      this.$refs.chooseTable.clearSelected()
+    },
+    // 表格选中项
+    rowSelectionFun (obj) {
+      this.rowSelectionInfo = obj || null
+    },
+    // 批量添加
+    handleBatchAdd () {
+      console.log(this.rowSelectionInfo)
+      const row = this.rowSelectionInfo && this.rowSelectionInfo.selectedRowKeys
+      if (!row || row.length == 0) {
+        this.$message.warning('请先选择要添加的产品!')
+        return
+      }
+      this.$emit('bachAdd', this.rowSelectionInfo.selectedRows)
+    },
+    getRepeatResult (sn) {
+      queryDetailSnListBySn({ sn }).then(res => {
+        if (res.status == 200) {
+          this.repeatList = res.data
+        }
+      })
+    }
+  }
+}
+</script>
+<style lang="less" scoped>
+  .salesReturnList-wrap{
+    .redBg-row{
+      background-color: #f5cdc8;
+    }
+  }
+  /deep/.sTable input:disabled{
+    color:gray !important;
+    -webkit-text-fill-color:gray !important;
+  }
+</style>

+ 8 - 0
src/views/financialManagement/accountStatementBill/detail.vue

@@ -0,0 +1,8 @@
+<template>
+</template>
+
+<script>
+</script>
+
+<style>
+</style>

+ 8 - 0
src/views/financialManagement/accountStatementBill/list.vue

@@ -0,0 +1,8 @@
+<template>
+</template>
+
+<script>
+</script>
+
+<style>
+</style>

+ 8 - 0
src/views/financialManagement/manualEntryForm/list.vue

@@ -0,0 +1,8 @@
+<template>
+</template>
+
+<script>
+</script>
+
+<style>
+</style>