checking.vue 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487
  1. <template>
  2. <div class="salesReturnCheck-wrap">
  3. <a-spin :spinning="spinning" tip="Loading...">
  4. <a-page-header :ghost="false" :backIcon="false" class="salesReturnCheck-back" >
  5. <!-- 自定义的二级文字标题 -->
  6. <template slot="subTitle">
  7. <a id="salesReturnCheck-back-btn" href="javascript:;" @click="handleBack"><a-icon type="left" /> 返回列表</a>
  8. <span style="margin: 0 15px;color: #666;">客户名称:{{ ordeDetail&&ordeDetail.buyerName || '--' }}</span>
  9. </template>
  10. </a-page-header>
  11. <a-card size="small" :bordered="false" class="salesReturnCheck-cont">
  12. <a-form layout="inline" style="margin-bottom:10px;" @keyup.enter.native="searchForm">
  13. <a-form-item label="产品编码" prop="productCode">
  14. <a-input id="salesReturnCheck-productCode" v-model.trim="queryParam.productCode" placeholder="请输入产品编码" allowClear />
  15. </a-form-item>
  16. <a-form-item label="产品名称" prop="productName">
  17. <a-input id="salesReturnCheck-productName" v-model.trim="queryParam.productName" placeholder="请输入产品名称" allowClear />
  18. </a-form-item>
  19. <a-form-item>
  20. <a-button type="primary" class="button-info" @click="searchForm" :disabled="disabled" id="salesReturnCheck-refresh">查询</a-button>
  21. <a-button style="margin-left: 5px" @click="resetSearchForm" :disabled="disabled" id="salesReturnCheck-reset">重置</a-button>
  22. </a-form-item>
  23. </a-form>
  24. <div style="border-top:1px solid #eee;padding-top:10px;">
  25. <a-button type="primary" :loading="loading" class="button-info" @click="plSetQty(1)">批量设置良品数量</a-button>
  26. <a-button type="primary" :loading="loading" class="button-error" @click="plSetQty(2)">批量设置返库数量</a-button>
  27. <a-button style="margin-left:5px;" :loading="loading" @click="openPlSetReason">批量设置退货原因</a-button>
  28. <span style="margin-left:10px;" v-if="selNums">已选{{ selNums }}项</span>
  29. <div style="float:right;color:#999;margin-top:8px;">说明:红色行表示收货时新增的产品</div>
  30. </div>
  31. <!-- 已选配件列表 -->
  32. <s-table
  33. class="sTable"
  34. ref="table"
  35. :style="{ height: tableHeight+84.5+'px' }"
  36. :rowClassName="(record, index) => record.addFlag == '1' ? (record.addType == 'WAREHOUSE_RECEIVE'?'redBg-row':'orgBg-row'):''"
  37. size="small"
  38. :rowKey="(record) => record.id"
  39. :row-selection="{ columnWidth: 40 }"
  40. @rowSelection="rowSelectionFun"
  41. :columns="columns"
  42. :data="loadData"
  43. :scroll="{ y: tableHeight }"
  44. :defaultLoadData="false"
  45. bordered>
  46. <!-- 良品数量 -->
  47. <template slot="goodQty" slot-scope="text, record">
  48. <a-input-number
  49. id="salesReturn-goodQty"
  50. size="small"
  51. v-model="record.goodQty"
  52. :precision="0"
  53. :min="0"
  54. :max="record.receiveQty"
  55. placeholder="请输入"
  56. @blur="e => updateGoodQty(e.target.value, record)"
  57. style="width: 100%;" />
  58. </template>
  59. <!-- 返库数量 -->
  60. <template slot="backStockQty" slot-scope="text, record">
  61. <a-input-number
  62. id="salesReturn-backStockQty"
  63. size="small"
  64. v-model="record.backStockQty"
  65. :precision="0"
  66. :min="0"
  67. placeholder="请输入"
  68. @blur="e => updateBackStockQty(e.target.value, record)"
  69. style="width: 100%;" />
  70. </template>
  71. <!-- 退货原因 -->
  72. <template slot="returnReason" slot-scope="text, record">
  73. <returnReason v-model="record.returnReason" @blur="updateReason(record)"></returnReason>
  74. </template>
  75. </s-table>
  76. <div class="footer-btn">
  77. <a-button
  78. size="large"
  79. style="padding: 0 60px;"
  80. :disabled="spinning"
  81. type="primary"
  82. class="button-primary"
  83. @click="handleSubmit()"
  84. id="salesReturn-handleSubmit">提交</a-button>
  85. </div>
  86. </a-card>
  87. </a-spin>
  88. <!-- 选中批量操作 -->
  89. <chooseTypeModal :openModal="openTypeModal" :type="actionType" @close="openTypeModal=false" @confirm="plconfirm"></chooseTypeModal>
  90. <!-- 批量设置退货原因 -->
  91. <commonModal modalTit="批量设置退货原因" :openModal="showPlModal" @cancel="showPlModal=false" @ok="setPlReturnReason">
  92. <div style="text-align: center;">
  93. <div style="margin-bottom: 15px;font-size: 14px;"><strong>请输入退货原因</strong></div>
  94. <div style="line-height: 24px;">
  95. <div><returnReason size="large" v-model="plReturnReason"></returnReason></div>
  96. </div>
  97. </div>
  98. </commonModal>
  99. </div>
  100. </template>
  101. <script>
  102. import { commonMixin } from '@/utils/mixin'
  103. import { STable, VSelect } from '@/components'
  104. import commonModal from '@/views/common/commonModal.vue'
  105. import returnReason from '@/views/common/returnReason'
  106. import { salesReturnDetail, salesReturnCheck } from '@/api/salesReturn'
  107. import { salesReturnDetailList, updateBatchBackStockQty, updateBatchGoodQty, salesReturnDetailSetReason, salesReturnDetailUpdateReason } from '@/api/salesReturnDetail'
  108. import chooseTypeModal from './chooseTypeModal.vue'
  109. export default {
  110. name: 'SalesReturnCheck',
  111. mixins: [commonMixin],
  112. components: {
  113. STable,
  114. VSelect,
  115. chooseTypeModal,
  116. returnReason,
  117. commonModal
  118. },
  119. data () {
  120. return {
  121. spinning: false,
  122. tableHeight: 0, // 表格高度
  123. orderSn: null,
  124. openTypeModal: false,
  125. actionType: '',
  126. disabled: false,
  127. isInster: false, // 是否正在添加产品
  128. ordeDetail: { discountAmount: 0 },
  129. loading: false,
  130. // 已选产品
  131. dataSource: [],
  132. productForm: {
  133. salesReturnBillSn: ''
  134. },
  135. queryParam: {
  136. productCode: '',
  137. productName: ''
  138. },
  139. chooseLoadData: [],
  140. // 加载数据方法 必须为 Promise 对象
  141. loadData: parameter => {
  142. this.disabled = true
  143. // 查询总计
  144. this.productForm.salesReturnBillSn = this.$route.params.sn
  145. return salesReturnDetailList(Object.assign(parameter, this.productForm, this.queryParam)).then(res => {
  146. let data
  147. if (res.status == 200) {
  148. data = res.data
  149. const no = (data.pageNo - 1) * data.pageSize
  150. for (var i = 0; i < data.list.length; i++) {
  151. data.list[i].no = no + i + 1
  152. data.list[i].goodQty = data.list[i].goodQty || 0
  153. data.list[i].backStockQty = data.list[i].backStockQty || 0
  154. data.list[i].goodQtyBackups = data.list[i].goodQty
  155. data.list[i].backStockQtyBackups = data.list[i].backStockQty
  156. data.list[i].returnReasonBackups = data.list[i].returnReason
  157. }
  158. this.disabled = false
  159. this.chooseLoadData = data.list
  160. }
  161. return data
  162. })
  163. },
  164. rowSelectionInfo: null,
  165. plReturnReason: '',
  166. showPlModal: false
  167. }
  168. },
  169. watch: {
  170. showPlModal (newValue, oldValue) {
  171. if (!newValue) {
  172. this.plReturnReason = ''
  173. }
  174. }
  175. },
  176. computed: {
  177. selNums () {
  178. return this.rowSelectionInfo && this.rowSelectionInfo.selectedRowKeys.length || 0
  179. },
  180. columns () {
  181. const arr = [
  182. { title: '序号', dataIndex: 'no', width: '6%', align: 'center' },
  183. { title: '产品编码', dataIndex: 'productEntity.code', align: 'center', width: '20%', customRender: function (text) { return text || '--' } },
  184. { title: '产品名称', dataIndex: 'productEntity.name', width: '28%', align: 'left', customRender: function (text) { return text || '--' } },
  185. { title: '单位', dataIndex: 'productEntity.unit', width: '10%', align: 'center', customRender: function (text) { return text || '--' } },
  186. { title: '申请退货数量', dataIndex: 'initialQty', align: 'center', width: '10%', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
  187. { title: '仓库实收数量', dataIndex: 'receiveQty', align: 'center', width: '10%', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
  188. { title: '坏件数量', dataIndex: 'badQty', align: 'center', width: '10%', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
  189. { title: '良品数量', dataIndex: 'goodQty', width: '10%', align: 'center', scopedSlots: { customRender: 'goodQty' } },
  190. { title: '返库数量', dataIndex: 'backStockQty', width: '10%', align: 'center', scopedSlots: { customRender: 'backStockQty' } },
  191. { title: '退货原因', dataIndex: 'returnReason', width: '20%', align: 'center', scopedSlots: { customRender: 'returnReason' } }
  192. ]
  193. return arr
  194. }
  195. },
  196. methods: {
  197. // 表格选中项
  198. rowSelectionFun (obj) {
  199. this.rowSelectionInfo = obj || null
  200. },
  201. // 返回
  202. handleBack () {
  203. this.$router.push({ name: 'receiveCheckList' })
  204. },
  205. // 批量设置
  206. plSetQty (type) {
  207. const _this = this
  208. if (!this.selNums) {
  209. _this.$message.warning('请先选择产品!')
  210. return
  211. }
  212. this.actionType = type
  213. this.openTypeModal = true
  214. },
  215. // 批量修改数量
  216. plconfirm (val) {
  217. const _this = this
  218. const obj = []
  219. const hasError = _this.rowSelectionInfo.selectedRows.filter(item => item.backStockQty > 0)
  220. _this.rowSelectionInfo && _this.rowSelectionInfo.selectedRows.map(item => {
  221. // 批量设置良品
  222. if (this.actionType == 1) {
  223. const pa = {
  224. salesReturnDetailSn: item.salesReturnDetailSn,
  225. goodQty: val == 1 ? item.receiveQty : 0
  226. }
  227. // 如果批量修改良品数量为0,且返库数量又不是0的情况
  228. if (hasError.length && val == 0) {
  229. pa.backStockQty = 0
  230. }
  231. obj.push(pa)
  232. } else {
  233. // 批量设置返库
  234. obj.push({
  235. salesReturnDetailSn: item.salesReturnDetailSn,
  236. backStockQty: val == 1 ? item.goodQty : 0
  237. })
  238. }
  239. })
  240. console.log(obj)
  241. // 如果批量修改良品数量为0
  242. if (val == 0 && this.actionType == 1 && hasError.length) {
  243. this.$confirm({
  244. title: '提示',
  245. content: '是否将返库数量同样设置为0?',
  246. centered: true,
  247. closable: true,
  248. onOk () {
  249. _this.plSave(obj)
  250. }
  251. })
  252. } else {
  253. _this.plSave(obj)
  254. }
  255. },
  256. plSave (obj) {
  257. const fun = this.actionType == 1 ? updateBatchGoodQty : updateBatchBackStockQty
  258. this.spinning = true
  259. fun(obj).then(res => {
  260. if (res.status == 200) {
  261. this.$refs.table.clearSelected()
  262. this.$refs.table.refresh()
  263. this.$message.success(res.message)
  264. }
  265. this.spinning = false
  266. this.openTypeModal = false
  267. })
  268. },
  269. // 批量设置退货原因
  270. openPlSetReason () {
  271. if (this.selNums) {
  272. this.showPlModal = true
  273. } else {
  274. this.$message.warning('请先选择产品!')
  275. }
  276. },
  277. setPlReturnReason () {
  278. if (this.plReturnReason == '') {
  279. this.$message.warning('请输入退货原因!')
  280. } else {
  281. this.spinning = true
  282. const snList = []
  283. const arr = this.rowSelectionInfo && this.rowSelectionInfo.selectedRows || []
  284. arr.map(item => {
  285. snList.push(item.salesReturnDetailSn)
  286. })
  287. salesReturnDetailSetReason({
  288. salesReturnBillDetailSnList: snList,
  289. returnReason: this.plReturnReason
  290. }).then(res => {
  291. if (res.status == 200) {
  292. this.showPlModal = false
  293. this.$refs.table.clearSelected()
  294. this.$refs.table.refresh()
  295. }
  296. this.spinning = false
  297. })
  298. }
  299. },
  300. // 修改退货原因
  301. updateReason (row) {
  302. // 空或没有改变时不保存数据
  303. if (!row.returnReason || row.returnReason == row.returnReasonBackups) {
  304. row.returnReason = row.returnReasonBackups
  305. return
  306. }
  307. this.spinning = true
  308. salesReturnDetailUpdateReason({
  309. salesReturnDetailSn: row.salesReturnDetailSn,
  310. returnReason: row.returnReason
  311. }).then(res => {
  312. if (res.status == 200) {
  313. this.$refs.table.refresh()
  314. this.$message.success(res.message)
  315. } else {
  316. row.returnReason = row.returnReasonBackups
  317. }
  318. this.spinning = false
  319. })
  320. },
  321. // 修改良品数量
  322. updateGoodQty (val, record) {
  323. if (record.backStockQty > record.goodQty) {
  324. this.$message.info('返库数量不能大于良品数量')
  325. record.goodQty = record.goodQtyBackups
  326. return
  327. }
  328. // 光标移出,值发生改变再调用编辑接口
  329. if (val && val != record.goodQtyBackups) {
  330. this.spinning = true
  331. updateBatchGoodQty([{
  332. salesReturnDetailSn: record.salesReturnDetailSn,
  333. goodQty: record.goodQty
  334. }]).then(res => {
  335. if (res.status == 200) {
  336. this.resetSearchForm(false)
  337. this.$message.success(res.message)
  338. record.goodQtyBackups = record.goodQty
  339. } else {
  340. record.goodQty = record.goodQtyBackups
  341. }
  342. this.spinning = false
  343. })
  344. } else {
  345. record.goodQty = record.goodQtyBackups
  346. }
  347. },
  348. // 修改返库数量
  349. updateBackStockQty (val, record) {
  350. if (record.backStockQty > record.goodQty) {
  351. this.$message.info('返库数量不能大于良品数量')
  352. record.backStockQty = record.backStockQtyBackups
  353. return
  354. }
  355. // 光标移出,值发生改变再调用编辑接口
  356. if (val && val != record.backStockQtyBackups) {
  357. this.spinning = true
  358. updateBatchBackStockQty([{
  359. salesReturnDetailSn: record.salesReturnDetailSn,
  360. backStockQty: record.backStockQty
  361. }]).then(res => {
  362. if (res.status == 200) {
  363. this.resetSearchForm(false)
  364. this.$message.success(res.message)
  365. } else {
  366. record.backStockQty = record.backStockQtyBackups
  367. }
  368. this.spinning = false
  369. })
  370. } else {
  371. record.backStockQty = record.backStockQtyBackups
  372. }
  373. },
  374. // 获取单据详细
  375. getOrderDetail () {
  376. salesReturnDetail({ sn: this.orderSn }).then(res => {
  377. this.ordeDetail = res.data || null
  378. })
  379. },
  380. // 重置
  381. resetSearchForm (flag) {
  382. if (flag) {
  383. this.rowSelectionInfo = null
  384. this.$refs.table.clearSelected()
  385. this.queryParam = {
  386. productCode: '',
  387. productName: ''
  388. }
  389. }
  390. this.$refs.table.refresh(!!flag)
  391. },
  392. searchForm () {
  393. this.$refs.table.refresh(true)
  394. this.$refs.table.clearSelected()
  395. },
  396. // 提交品检
  397. handleSubmit () {
  398. const _this = this
  399. this.$confirm({
  400. title: '提示',
  401. content: '提交后将无法修改,确认提交吗?',
  402. centered: true,
  403. closable: true,
  404. onOk () {
  405. _this.spinning = true
  406. salesReturnCheck({ salesReturnBillSn: _this.orderSn }).then(res => {
  407. if (res.status == 200) {
  408. _this.handleBack()
  409. _this.$message.success(res.message)
  410. _this.spinning = false
  411. } else {
  412. _this.spinning = false
  413. }
  414. })
  415. }
  416. })
  417. },
  418. pageInit () {
  419. const _this = this
  420. this.$nextTick(() => { // 页面渲染完成后的回调
  421. _this.setTableH()
  422. })
  423. this.orderSn = this.$route.params.sn
  424. this.getOrderDetail()
  425. },
  426. setTableH () {
  427. this.tableHeight = window.innerHeight - 390
  428. }
  429. },
  430. mounted () {
  431. if (!this.$store.state.app.isNewTab) { // 页签刷新时调用
  432. this.$refs.table.refresh(true)
  433. this.pageInit()
  434. }
  435. },
  436. activated () {
  437. this.$refs.table.refresh()
  438. this.pageInit()
  439. },
  440. beforeRouteEnter (to, from, next) {
  441. next(vm => {})
  442. }
  443. }
  444. </script>
  445. <style lang="less">
  446. .salesReturnCheck-wrap{
  447. position: relative;
  448. height: 100%;
  449. padding-bottom: 51px;
  450. box-sizing: border-box;
  451. >.ant-spin-nested-loading{
  452. height: 100%;
  453. }
  454. .footer-btn{
  455. text-align: center;
  456. }
  457. .salesReturnCheck-cont{
  458. margin-top: 10px;
  459. .sTable{
  460. margin-top: 10px;
  461. }
  462. .total-bar{
  463. display: flex;
  464. align-items: center;
  465. justify-content: space-between;
  466. > div{
  467. &:last-child{
  468. display: flex;
  469. align-items: center;
  470. justify-content: space-between;
  471. > div{
  472. padding: 0 10px;
  473. }
  474. }
  475. }
  476. }
  477. }
  478. .redBg-row{
  479. background-color: #f5beb4;
  480. }
  481. .orgBg-row{
  482. background-color: #fffca2;
  483. }
  484. }
  485. </style>