edit.vue 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561
  1. <template>
  2. <div class="salesReturnEdit-wrap">
  3. <a-spin :spinning="spinning" tip="Loading...">
  4. <a-page-header :ghost="false" :backIcon="false" class="salesReturnEdit-back">
  5. <!-- 自定义的二级文字标题 -->
  6. <template slot="subTitle">
  7. <a id="salesReturnEdit-back-btn" href="javascript:;" @click="handleBack">
  8. <a-icon type="left" />
  9. 返回列表
  10. </a>
  11. <span style="margin: 0 15px;color: #666;font-weight: bold;">单号:{{ detailsData&&detailsData.sparePartsReturnNo }}</span>
  12. <span style="margin: 0 10px;color: #666;">供应商:{{ detailsData && detailsData.supplier && detailsData.supplier.supplierName }}</span>
  13. <a-button type="link" size="small" class="button-default" @click="showDetail=!showDetail">
  14. <a-icon :type="showDetail ? 'eye-invisible' : 'eye'"/> {{ showDetail?'隐藏':'查看' }}信息
  15. </a-button>
  16. </template>
  17. </a-page-header>
  18. <a-card size="small" :bordered="false" class="salesReturnEdit-cont" v-show="showDetail">
  19. <div slot="title">
  20. <span>基础信息</span>
  21. <div style="cursor:pointer;color: #00aaff;float:right;" @click.stop="handleEditBase" >
  22. <a-icon type="edit" /> 编辑基础信息
  23. </div>
  24. </div>
  25. <a-descriptions size="small" :column="4" style="margin-bottom: 10px;">
  26. <a-descriptions-item label="客户名称">{{ (detailsData && detailsData.sparePartsReturnNo) || '--' }}</a-descriptions-item>
  27. <a-descriptions-item label="收货地址">{{ (detailsData && detailsData.sparePartsReturnNo) || '--' }}</a-descriptions-item>
  28. <a-descriptions-item label="收货人">{{ (detailsData && detailsData.supplier && detailsData.supplier.supplierName) || '--' }}</a-descriptions-item>
  29. <a-descriptions-item label="收货电话">{{ (detailsData && detailsData.returnReasonDictValue) || '--' }}</a-descriptions-item>
  30. <a-descriptions-item label="业务状态">{{ detailsData&&detailsData.warehouseName || '--' }}</a-descriptions-item>
  31. <a-descriptions-item label="备注">{{ detailsData&&detailsData.grabFlag =='0'?'否':'是' }}</a-descriptions-item>
  32. <a-descriptions-item label="关联单号">{{ (detailsData && detailsData.explainInfo) || '--' }}</a-descriptions-item>
  33. <a-descriptions-item label="销售类型">{{ (detailsData && detailsData.explainInfo) || '--' }}</a-descriptions-item>
  34. </a-descriptions>
  35. </a-card>
  36. <a-card size="small" :bordered="false" class="salesReturnEdit-cont">
  37. <div class="table-page-search-wrapper" style="display:flex;align-items: center;justify-content: space-between;">
  38. <div style="flex-grow:1;">
  39. <a-form layout="inline" @keyup.enter.native="$refs.table.refresh(true)">
  40. <a-row :gutter="15">
  41. <a-col :md="6" :sm="24">
  42. <a-form-item label="产品编码"><a-input v-model.trim="productForm.productCode" allowClear placeholder="请输入产品编码" /></a-form-item>
  43. </a-col>
  44. <a-col :md="6" :sm="24">
  45. <a-form-item label="产品名称"><a-input v-model.trim="productForm.productName" allowClear placeholder="请输入产品名称" /></a-form-item>
  46. </a-col>
  47. <a-col :md="6" :sm="24" style="margin-bottom: 10px;">
  48. <a-button type="primary" @click="$refs.table.refresh(true)">查询</a-button>
  49. <a-button style="margin-left: 5px" @click="resetSearchForm">重置</a-button>
  50. </a-col>
  51. </a-row>
  52. </a-form>
  53. </div>
  54. </div>
  55. <div class="showBtn">
  56. <a-button id="bulkWarehousingOrderList-add" type="primary" class="button-warning" @click="handleAdd">新增产品</a-button>
  57. <a-button id="bulkWarehousingOrderList-ex" class="button-warning" @click="handleAdd">导入产品</a-button>
  58. <a-button
  59. v-if="$hasPermissions('B_sparePartsBatchAudit')"
  60. id="bulkWarehousingOrderList-batchAudit"
  61. type="primary"
  62. class="button-warning"
  63. :loading="loading"
  64. @click="handleBatchAudit">查询库存</a-button>
  65. <a-alert type="info">
  66. <div slot="message" class="total-bar">
  67. <span>采购数量:{{ statisticsObj && (statisticsObj.qty || statisticsObj.qty == 0) ? statisticsObj.qty : '--' }};</span>
  68. <span v-if="$hasPermissions('B_purchaseReturnEdit_costPrice')">采购金额:{{ statisticsObj && statisticsObj.totalCost || statisticsObj.totalCost == 0 ? statisticsObj.totalCost : '--' }};</span>
  69. </div>
  70. </a-alert>
  71. </div>
  72. <s-table
  73. class="sTable"
  74. ref="table"
  75. size="small"
  76. :rowKey="(record) => record.id"
  77. :columns="columns"
  78. :data="loadData"
  79. :defaultLoadData="false"
  80. bordered>
  81. <!--申请退货数量 -->
  82. <template slot="qty" slot-scope="text, record">
  83. <a-input-number
  84. id="salesReturn-qty"
  85. size="small"
  86. v-model="record.qty"
  87. :precision="0"
  88. :min="1"
  89. :max="record.qty"
  90. placeholder="请输入"
  91. style="width: 100%;"
  92. @blur="e => onCellBlur(e.target.value, record)"
  93. />
  94. </template>
  95. <!-- 操作 -->
  96. <template slot="action" slot-scope="text, record">
  97. <a-button
  98. size="small"
  99. type="link"
  100. v-if="$hasPermissions('B_purchaseReturnEdit')"
  101. @click="handleEdit(record)"
  102. class="button-info"
  103. id="purchaseReceiptList-edit-btn">编辑</a-button>
  104. <a-button
  105. size="small"
  106. type="link"
  107. :loading="delLoading"
  108. class="button-error"
  109. @click="handleDel(record)"
  110. id="salesReturn-Del">删除</a-button>
  111. </template>
  112. </s-table>
  113. </a-card>
  114. </a-spin>
  115. <div class="affix-cont">
  116. <a-button
  117. size="large"
  118. style="padding: 0 60px;"
  119. :disabled="spinning"
  120. type="primary"
  121. class="button-primary"
  122. @click="beforeSubmit"
  123. id="salesReturn-handleSubmit">提交</a-button>
  124. </div>
  125. <!-- 新增弹窗-->
  126. <add-modal v-drag :openModal="openModal" @ok="handleOk" @close="openModal=false" />
  127. <!-- 选择审核人员 -->
  128. <chooseDepartUserModal ref="chooseDepart" :openModal="openDepartUserModal" @close="openDepartUserModal = false" @submit="handleSubmit"></chooseDepartUserModal>
  129. <!-- 编辑基础信息弹窗 -->
  130. <basic-info-modal v-drag :openModal="openBasicInfoModal" :itemSn="sparePartsReturnSn" @ok="getBasicsData" @close="openModal = false" />
  131. </div>
  132. </template>
  133. <script>
  134. import { commonMixin } from '@/utils/mixin'
  135. import { STable, VSelect } from '@/components'
  136. import addModal from './addModal.vue'
  137. // import queryPart from './queryPart.vue'
  138. import basicInfoModal from './basicInfoModal.vue'
  139. // import chooseDepartUserModal from './chooseDepartUserModal.vue'
  140. import {
  141. sparePartsReturnQueryPage,
  142. queryPageCount,
  143. sparePartsReturnDetailDelete,
  144. sparePartsReturnDetailSave,
  145. sparePartsReturnSubmit,
  146. sparePartsReturnInfo,
  147. sparePartsReturnDetailSaveBatch
  148. } from '@/api/sparePartsReturn'
  149. export default {
  150. name: 'PurchaseReturnEdit',
  151. mixins: [commonMixin],
  152. components: { STable, VSelect, basicInfoModal, addModal },
  153. data () {
  154. return {
  155. spinning: false,
  156. isInster: false, // 是否正在添加产品
  157. openDepartUserModal: false, // 审核人员弹窗
  158. delLoading: false,
  159. showDetail: false,
  160. productForm: {
  161. productName: '',
  162. productCode: '',
  163. sparePartsNo: '',
  164. orderBy: 'sprd.CREATE_DATE DESC'
  165. },
  166. sparePartsReturnSn: null,
  167. sparePartsReturnNo: null,
  168. chooseList: [],
  169. // 加载数据方法 必须为 Promise 对象
  170. loadData: parameter => {
  171. this.productForm.sparePartsReturnSn = this.sparePartsReturnSn
  172. return sparePartsReturnQueryPage(Object.assign(parameter, this.productForm)).then(res => {
  173. let data
  174. if (res.status == 200) {
  175. data = res.data
  176. const no = (data.pageNo - 1) * data.pageSize
  177. for (var i = 0; i < data.list.length; i++) {
  178. data.list[i].no = no + i + 1
  179. }
  180. }
  181. this.chooseList = data.list
  182. return data
  183. })
  184. },
  185. openBasicInfoModal: false, // 修改基础信息弹窗
  186. statisticsObj: null, // 统计明细
  187. detailsData: null, // 基础信息数据
  188. addMoreLoading: false, // 批量添加动画
  189. grabFlag: undefined
  190. }
  191. },
  192. computed: {
  193. columns () {
  194. const _this = this
  195. const arr = [
  196. { title: '序号', dataIndex: 'no', align: 'center', width: '4%' },
  197. {
  198. title: '产品编码',
  199. dataIndex: 'product.code',
  200. width: '18%',
  201. align: 'center',
  202. customRender: function (text) {
  203. return text || '--'
  204. }
  205. },
  206. {
  207. title: '产品名称',
  208. dataIndex: 'product.name',
  209. width: '25%',
  210. align: 'left',
  211. customRender: function (text) {
  212. return text || '--'
  213. },
  214. ellipsis: true
  215. },
  216. {
  217. title: '单位',
  218. dataIndex: 'product.unit',
  219. align: 'center',
  220. width: '6%',
  221. customRender: function (text) {
  222. return text || '--'
  223. }
  224. },
  225. { title: '采购数量', align: 'center', width: '13%', scopedSlots: { customRender: 'qty' } },
  226. {
  227. title: '库存数量',
  228. dataIndex: 'stockBatchNo',
  229. align: 'center',
  230. width: '10%',
  231. customRender: function (text) {
  232. return text || '--'
  233. }
  234. },
  235. {
  236. title: '采购单价',
  237. dataIndex: 'cost',
  238. width: '8%',
  239. align: 'right',
  240. customRender: function (text) {
  241. return text || text == 0 ? _this.toThousands(text, 2) : '--'
  242. }
  243. },
  244. {
  245. title: '采购金额',
  246. dataIndex: 'totalCost',
  247. width: '8%',
  248. align: 'right',
  249. customRender: function (text) {
  250. return text || text == 0 ? _this.toThousands(text, 2) : '--'
  251. }
  252. },
  253. { title: '操作', scopedSlots: { customRender: 'action' }, width: '10%', align: 'center' }
  254. ]
  255. if (this.$hasPermissions('B_purchaseReturnEdit_costPrice')) {
  256. arr.splice(6, 0, {
  257. title: '退货单价',
  258. dataIndex: 'cost',
  259. width: '8%',
  260. align: 'right',
  261. customRender: function (text) {
  262. return text || text == 0 ? _this.toThousands(text, 2) : '--'
  263. }
  264. })
  265. arr.splice(8, 0, {
  266. title: '采购金额',
  267. dataIndex: 'totalCost',
  268. width: '8%',
  269. align: 'right',
  270. customRender: function (text) {
  271. return text || text == 0 ? _this.toThousands(text, 2) : '--'
  272. }
  273. })
  274. }
  275. return arr
  276. }
  277. },
  278. methods: {
  279. // 编辑基础信息
  280. handleEditBase () {
  281. this.openBasicInfoModal = true
  282. },
  283. // 返回
  284. handleBack () {
  285. this.$router.push({ path: `/purchasingManagement/purchaseReturn/list`, query: { closeLastOldTab: true } })
  286. },
  287. // 删除所选产品
  288. handleDel (row) {
  289. const _this = this
  290. this.$confirm({
  291. title: '提示',
  292. content: '确认要删除吗?',
  293. centered: true,
  294. closable: true,
  295. onOk () {
  296. _this.delLoading = true
  297. _this.spinning = true
  298. sparePartsReturnDetailDelete({ detailSn: row.sparePartsReturnDetailSn })
  299. .then(res => {
  300. if (res.status == 200) {
  301. _this.resetTable(false)
  302. _this.getStatisticsData()
  303. _this.getChooseList()
  304. _this.$refs.partQuery.refreshLength()
  305. }
  306. _this.$message.info(res.message)
  307. _this.delLoading = false
  308. _this.spinning = false
  309. })
  310. .catch(err => {
  311. _this.delLoading = false
  312. })
  313. }
  314. })
  315. },
  316. resetTable (flag) {
  317. this.$refs.table.refresh(flag)
  318. },
  319. // 重置
  320. resetSearchForm (flag) {
  321. this.productForm.productName = ''
  322. this.productForm.productCode = ''
  323. this.productForm.sparePartsNo = ''
  324. this.$refs.table.refresh(!!flag)
  325. },
  326. // 已选产品 blur
  327. onCellBlur (val, record) {
  328. if (val * 1 > record.putQty * 1) {
  329. this.$message.warning('申请退货数量不能大于入库数量!')
  330. this.$refs.table.refresh(true)
  331. return
  332. }
  333. const ajax_data = {
  334. sparePartsReturnSn: this.sparePartsReturnSn,
  335. sparePartsReturnNo: this.sparePartsReturnNo,
  336. sparePartsDetailSn: record.sparePartsDetailSn,
  337. productSn: record.productSn,
  338. sparePartsReturnDetailSn: record.sparePartsReturnDetailSn,
  339. stockDetailSn: record.stockDetailSn,
  340. productCode: record.productCode,
  341. putQty: record.putQty, // 入库数量
  342. returnedQty: record.returnedQty, // 已退数量
  343. qty: val, // 申退数量
  344. cost: record.cost, // 成本
  345. stockBatchNo: record.stockBatchNo, // 批次号
  346. warehouseSn: record.warehouseSn, // 仓库sn
  347. warehouseLocationSn: record.warehouseLocationSn, // 仓位sn
  348. sparePartsNo: record.sparePartsNo,
  349. sparePartsSn: record.sparePartsSn
  350. }
  351. this.saveEdit(ajax_data)
  352. },
  353. // 添加或修改产品
  354. saveProduct (row) {
  355. if (this.isInster) {
  356. // 防止多次添加产品
  357. return
  358. }
  359. this.isInster = true
  360. const paramsData = {
  361. sparePartsReturnSn: this.sparePartsReturnSn,
  362. sparePartsReturnNo: this.sparePartsReturnNo,
  363. sparePartsDetailSn: row.sparePartsDetailSn,
  364. productSn: row.productSn,
  365. stockDetailSn: row.stockDetailSn,
  366. productCode: row.productCode,
  367. putQty: row.productQty, // 入库数量
  368. returnedQty: row.returnedQty, // 已退数量
  369. qty: row.qty, // 申退数量
  370. cost: row.productCost, // 成本
  371. stockBatchNo: row.sparePartsBatchNo, // 批次号
  372. warehouseSn: row.warehouseSn, // 仓库sn
  373. warehouseLocationSn: row.warehouseLocationSn, // 仓位sn
  374. sparePartsNo: row.sparePartsNo,
  375. sparePartsSn: row.sparePartsSn
  376. }
  377. this.saveEdit(paramsData)
  378. },
  379. saveMoreProduct (data) {
  380. if (this.addMoreLoading) {
  381. // 防止多次添加产品
  382. return
  383. }
  384. this.addMoreLoading = true
  385. var ajax_data = []
  386. data.forEach(item => {
  387. const obj = {
  388. sparePartsReturnSn: this.sparePartsReturnSn,
  389. sparePartsReturnNo: this.sparePartsReturnNo,
  390. sparePartsDetailSn: item.sparePartsDetailSn,
  391. productSn: item.productSn,
  392. stockDetailSn: item.stockDetailSn,
  393. productCode: item.productCode,
  394. putQty: item.productQty, // 入库数量
  395. returnedQty: item.returnedQty, // 已退数量
  396. qty: item.qty, // 申退数量
  397. cost: item.productCost, // 成本
  398. stockBatchNo: item.sparePartsBatchNo, // 批次号
  399. warehouseSn: item.warehouseSn, // 仓库sn
  400. warehouseLocationSn: item.warehouseLocationSn, // 仓位sn
  401. sparePartsNo: item.sparePartsNo,
  402. sparePartsSn: item.sparePartsSn
  403. }
  404. ajax_data.push(obj)
  405. })
  406. this.saveMore(ajax_data)
  407. },
  408. saveEdit (params) {
  409. this.spinning = true
  410. sparePartsReturnDetailSave(params).then(res => {
  411. if (res.status == 200) {
  412. this.getStatisticsData()
  413. this.$refs.table.refresh(true)
  414. this.getChooseList()
  415. }
  416. this.isInster = false
  417. this.spinning = false
  418. this.addMoreLoading = false
  419. }).catch(err => {
  420. this.isInster = false
  421. })
  422. },
  423. saveMore (params) {
  424. this.spinning = true
  425. sparePartsReturnDetailSaveBatch(params)
  426. .then(res => {
  427. if (res.status == 200) {
  428. this.getStatisticsData()
  429. this.getChooseList()
  430. this.$refs.table.refresh(true)
  431. this.$refs.partQuery.refreshLength()
  432. }
  433. this.isInster = false
  434. this.spinning = false
  435. this.addMoreLoading = false
  436. })
  437. .catch(err => {
  438. this.isInster = false
  439. this.addMoreLoading = false
  440. this.spinning = false
  441. })
  442. },
  443. beforeSubmit () {
  444. if (this.chooseList.length > 0) {
  445. this.openDepartUserModal = true
  446. } else {
  447. this.$message.warning('请先添加要退货的产品!')
  448. }
  449. },
  450. // 提交采购退货
  451. handleSubmit (data) {
  452. this.spinning = true
  453. sparePartsReturnSubmit({ sparePartsReturnSn: this.sparePartsReturnSn, ...data }).then(res => {
  454. if (res.status == 200) {
  455. this.handleBack()
  456. this.$message.success(res.message)
  457. }
  458. this.spinning = false
  459. })
  460. },
  461. pageInit () {
  462. this.supplierSn = this.$route.query.sn
  463. this.sparePartsReturnSn = this.$route.query.returnSn
  464. this.sparePartsReturnNo = this.$route.query.no
  465. this.getStatisticsData()
  466. this.getBasicsData()
  467. this.resetSearchForm(true)
  468. },
  469. getChooseList () {
  470. this.$refs.partQuery.pageInit(this.supplierSn, this.sparePartsReturnSn, this.detailsData ? this.detailsData.warehouseSn : undefined, this.detailsData.grabFlag)
  471. },
  472. // 获取页面统计数据
  473. getStatisticsData () {
  474. this.getBasicsData(true)
  475. queryPageCount({ sparePartsReturnSn: this.sparePartsReturnSn }).then(res => {
  476. if (res.status == 200) {
  477. if (res.data) {
  478. res.data.totalCost = res.data && (res.data.totalCost || res.data.totalCost == 0) ? this.toThousands(res.data.totalCost, 2) : '--'
  479. this.statisticsObj = res.data
  480. } else {
  481. this.statisticsObj = null
  482. }
  483. } else {
  484. this.statisticsObj = null
  485. }
  486. })
  487. },
  488. // 获取基础信息
  489. getBasicsData (flag) {
  490. sparePartsReturnInfo({ sn: this.sparePartsReturnSn }).then(res => {
  491. if (res.status == 200) {
  492. this.detailsData = res.data
  493. } else {
  494. this.detailsData = null
  495. }
  496. const _this = this
  497. if (!flag) {
  498. this.$nextTick(() => {
  499. _this.getChooseList()
  500. })
  501. }
  502. })
  503. }
  504. },
  505. mounted () {
  506. if (!this.$store.state.app.isNewTab) {
  507. // 页签刷新时调用
  508. this.pageInit()
  509. }
  510. },
  511. activated () {
  512. // 如果是新页签打开或者进入新的子页(例:存在列表第2条数据编辑页页签时再打开第4条数据的编辑页),则重置当前页面
  513. if (this.$store.state.app.isNewTab || !this.$store.state.app.isNewSubTab) {
  514. this.pageInit()
  515. }
  516. },
  517. beforeRouteEnter (to, from, next) {
  518. next(vm => {})
  519. }
  520. }
  521. </script>
  522. <style lang="less">
  523. .salesReturnEdit-wrap {
  524. position: relative;
  525. height: 100%;
  526. padding-bottom: 51px;
  527. box-sizing: border-box;
  528. > .ant-spin-nested-loading {
  529. overflow-y: scroll;
  530. height: 100%;
  531. }
  532. .showBtn{
  533. display:flex;
  534. align-items:center;
  535. margin-bottom:10px;
  536. }
  537. .salesReturnEdit-cont {
  538. margin-top: 6px;
  539. .ant-divider-horizontal {
  540. margin: 10px 0 24px;
  541. }
  542. .total-bar {
  543. display: flex;
  544. align-items: center;
  545. justify-content: space-between;
  546. > div {
  547. &:last-child {
  548. display: flex;
  549. align-items: center;
  550. justify-content: space-between;
  551. > div {
  552. padding: 0 10px;
  553. }
  554. }
  555. }
  556. }
  557. }
  558. }
  559. </style>