index.vue 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461
  1. <template>
  2. <view>
  3. <view class="p-content">
  4. <view class="p-head" v-if="baseData">
  5. <view>
  6. <view>
  7. <text>采购单号:</text>
  8. <text style="color: crimson;">{{baseData.purchaseBillNo}}</text>
  9. </view>
  10. <view>
  11. <button :disabled="loading" size="mini" style="padding:0 10px;height: 28px;line-height: 28px;" type="primary" @click="toOut"> 入库 <text class="iconfont icon-icon-test43"></text></button>
  12. </view>
  13. </view>
  14. <view>
  15. <view>
  16. <text>发货单号:</text>
  17. <text style="color: crimson;">{{baseData.sendBillNo}}</text>
  18. </view>
  19. </view>
  20. <view>
  21. <view>
  22. <text>条码:</text>
  23. <view>
  24. <input
  25. @blur="pickFun(true)"
  26. style="width: 100%;text-align: left;"
  27. class="uni-input"
  28. placeholder="扫描或输入条码"
  29. border="surround"
  30. v-model="code">
  31. </view>
  32. <view>
  33. <button size="mini" style="padding:0 10px;height: 30px;line-height: 30px;margin-left: 10px;margin-top: 3px;" :style="{color:'#aa0000'}" @click="resetInput">重置</button>
  34. </view>
  35. </view>
  36. </view>
  37. <view style="justify-content: flex-start;flex-wrap: wrap;" v-if="baseData">
  38. <view>总款数:{{ baseData.totalPutCategory }}</view>
  39. <view>发货数量: {{ baseData.totalPutQty }}</view>
  40. <view>发货金额: {{ baseData.totalPutAmount?toThousands(baseData.totalPutAmount,2):'0.00' }}</view>
  41. <view>入库数量: {{ baseData && (baseData.totalRealPutQty || baseData.totalRealPutQty==0) ? baseData.totalRealPutQty : '--' }}</view>
  42. <view>入库金额: {{ baseData && (baseData.totalRealPutAmount || baseData.totalRealPutAmount==0) ? toThousands(baseData.totalRealPutAmount, 2) : '--' }}</view>
  43. </view>
  44. </view>
  45. <view class="p-body">
  46. <scroll-view :scroll-top="scrollTop" :scroll-y="true" class="scrollView">
  47. <uni-table style="width: 100%;" border emptyText="暂无数据" :loading="loading" >
  48. <!-- 表头行 -->
  49. <uni-tr>
  50. <uni-td align="center">产品编码</uni-td>
  51. <uni-td align="center">仓库仓位</uni-td>
  52. <uni-td align="center">入库/发货数量</uni-td>
  53. </uni-tr>
  54. <!-- 表格数据行 -->
  55. <uni-tr
  56. v-for="item in detailList"
  57. :key="item.id"
  58. :id="item.id"
  59. :checkedRow="hasCheck(item)"
  60. @click="selRow(item)"
  61. >
  62. <uni-td width="30%" align="center">
  63. <view>{{item.dealerProductEntity&&item.dealerProductEntity.code||'--'}}</view>
  64. </uni-td>
  65. <uni-td width="35%" align="center">
  66. <view>
  67. {{item.warehouseEntity&&item.warehouseEntity.name||defWarehouseName[0]}}/{{item.warehouseLocationEntity&&item.warehouseLocationEntity.name||defWarehouseName[1]}}
  68. </view>
  69. </uni-td>
  70. <uni-td width="35%" align="center">
  71. <view @click="editRow(item)">
  72. <text style="color: red;">{{item.realPutQty||'0'}}</text>/{{item.putQty}}
  73. </view>
  74. </uni-td>
  75. </uni-tr>
  76. </uni-table>
  77. </scroll-view>
  78. </view>
  79. <view class="p-footer">
  80. <button size="mini" type="warn" @click="pickFun(false)"> <text class="iconfont icon-reduce-btn"> 减 </text></button>
  81. <button size="mini" type="primary" @click="pickFun(true)"> <text class="iconfont icon-add-btn"> 加 </text></button>
  82. </view>
  83. </view>
  84. <scanCode @onKeyDown="keyDown"></scanCode>
  85. <!-- 选择仓库 -->
  86. <chooseWarehouse ref="chooseWarehouse" :openPick="showPick" :value="warehouseVal" @close="showPick=false" @change="confirmWarehouse"></chooseWarehouse>
  87. <!-- 左键扫描,修改包装数 -->
  88. <uni-popup ref="popup" :mask-click="false" type="dialog">
  89. <view style="background-color: #fff;padding: 30rpx 50rpx;border-radius: 30rpx;width: 75%;margin: 0 auto;">
  90. <view v-if="tempProduct">
  91. <view style="padding: 30rpx 0;">
  92. 产品编码:{{tempProduct.dealerProductEntity.code}}
  93. </view>
  94. <view style="display: flex;align-items: center;">
  95. 数量:
  96. <u--input
  97. placeholder="请输入数量"
  98. border="surround"
  99. v-model="tempProduct.packQty"
  100. :min="0"
  101. type="digit"
  102. ></u--input>
  103. {{tempProduct.dealerProductEntity.unit}}
  104. {{tempProduct.dealerProductEntity.packQtyUnit?("/"+tempProduct.dealerProductEntity.packQtyUnit):''}}
  105. </view>
  106. </view>
  107. <view style="display: flex;padding: 60rpx 15rpx 10rpx;justify-content: space-between;">
  108. <button size="mini" @click="closePop">取消</button>
  109. <button size="mini" type="primary" @click="okPop">确定</button>
  110. </view>
  111. </view>
  112. </uni-popup>
  113. <u-modal :show="showModal" :title="msg.title" :confirmText="msg.confirmText" showCancelButton :content='msg.content' @cancel="showModal=false" @confirm="confirmModal"></u-modal>
  114. </view>
  115. </template>
  116. <script>
  117. import scanCode from '@/libs/scan-code.vue';
  118. import { purchaseWriteStockIn, receivingQuery, receivingDetail, purchaseUpdateWarehouse, updateRealPutQty, receivingStockInVerify } from '@/config/api.js'
  119. import { playAudio, toThousands } from '@/libs/tools.js'
  120. import clipboard from "@/js_sdk/dc-clipboard/clipboard.js"
  121. import chooseWarehouse from './chooseWarehouse.vue'
  122. export default {
  123. components: { scanCode, chooseWarehouse },
  124. data() {
  125. return {
  126. loading: false,
  127. showModal: false,
  128. msg:{title:'提示',content:''},
  129. showPick: false,
  130. baseData: null,
  131. detailList:[],
  132. code:'',
  133. receivingBillSn: null,
  134. salesId: null,
  135. curProductIndex: 0,
  136. curProductArr: [],
  137. tempProduct:null,
  138. toThousands,
  139. defWarehouse: [],
  140. defWarehouseName:[],
  141. keyName: '',
  142. warehouseVal: [],
  143. scrollTop: 0,
  144. };
  145. },
  146. onLoad(opts) {
  147. var _this = this
  148. this.receivingBillSn = opts.receivingBillSn
  149. this.salesId = opts.id
  150. // 默认仓库仓位
  151. this.defWarehouse = this.$store.state.vuex_tempData
  152. // 调用数据
  153. this.getDetail()
  154. this.getDetailList()
  155. uni.$on('scancodedate', function(content) {
  156. console.log("扫描到的内容为:", content, _this.keyName)
  157. _this.code = content||''
  158. _this.curProductIndex = 0
  159. if(_this.keyName == 'rightKey' || _this.keyName == 'midKey'){
  160. _this.pickFun(true)
  161. }
  162. if(_this.keyName == 'leftKey'){
  163. _this.openPack()
  164. }
  165. })
  166. },
  167. onShow() {
  168. this.hideKeyborder()
  169. const list = this.$store.state.vuex_warehouseList
  170. const an =list.find(item => item.warehouseSn==this.defWarehouse[0])
  171. const cn = an&&an.warehouseLocationList&&an.warehouseLocationList.find(item => item.warehouseLocationSn == this.defWarehouse[1])
  172. this.defWarehouseName = [an&&an.name,cn&&cn.name]
  173. console.log(this.defWarehouseName)
  174. },
  175. onUnload() {
  176. uni.$off('scancodedate')
  177. },
  178. methods: {
  179. hideKeyborder(){
  180. uni.hideKeyboard()
  181. },
  182. // 复制
  183. copyText(text){
  184. clipboard.setText(text);
  185. uni.showToast({
  186. icon: 'none',
  187. title: '编码已复制成功'
  188. })
  189. },
  190. hasCheck(item){
  191. const curProduct = this.curProductArr[this.curProductIndex]
  192. return curProduct&&curProduct.id == item.id
  193. },
  194. // 获取所有可操作商品
  195. getCurProduct(flag){
  196. const curProduct = this.detailList.filter(item => item.dealerProductEntity&&item.dealerProductEntity.qrCode == this.code)
  197. this.curProductArr = curProduct || []
  198. // 滚动到指定位置
  199. if(this.curProductArr.length&&!flag){
  200. const cur = this.curProductArr[0]
  201. this.scrollToRow(cur)
  202. }
  203. },
  204. // 选择行
  205. selRow(item){
  206. this.code = item.dealerProductEntity&&item.dealerProductEntity.qrCode||''
  207. this.getCurProduct(true)
  208. const idx = this.curProductArr.findIndex(k => k.id == item.id)
  209. this.curProductIndex = idx || 0
  210. },
  211. // 获取当前操作行
  212. getCurRow(){
  213. console.log(this.curProductArr, this.curProductIndex)
  214. const curProduct = this.curProductArr[this.curProductIndex]
  215. if(curProduct){
  216. curProduct.packQty = curProduct.dealerProductEntity&&curProduct.dealerProductEntity.packQty || 0
  217. }
  218. return curProduct
  219. },
  220. // 滚动到指定行
  221. scrollToRow(cur){
  222. const idx = this.detailList.findIndex(item => item.id == cur.id)
  223. this.scrollTop = idx * 60
  224. },
  225. // 清空输入框
  226. resetInput(){
  227. this.code = ''
  228. this.curProductIndex = 0
  229. this.getCurProduct()
  230. this.scrollTop = 0
  231. },
  232. pickFun(flag){
  233. playAudio('info')
  234. this.getCurProduct()
  235. this.addQty(flag)
  236. },
  237. addQty(flag){
  238. const curProduct = this.getCurRow()
  239. if(curProduct){
  240. curProduct.realPutQty = curProduct.realPutQty || 0
  241. this.loading = true
  242. // 加
  243. if(flag){
  244. // 如果入库数量与发货数量不相等
  245. if(curProduct.realPutQty < curProduct.putQty){
  246. this.changePutQty(curProduct,(curProduct.realPutQty||0) + 1)
  247. }else{
  248. // 当前入库数量与发货数量相等时
  249. // 切换到下一个商品
  250. if(this.curProductIndex<this.curProductArr.length-1){
  251. this.curProductIndex = this.curProductIndex + 1
  252. this.pickFun(flag)
  253. }else{
  254. // 直到最后一条数据,扫描数量无上线增加
  255. this.changePutQty(curProduct,(curProduct.realPutQty||0) + 1)
  256. }
  257. }
  258. }else{
  259. // 减
  260. // 如果入库数量不是0
  261. if(curProduct.realPutQty != 0){
  262. this.changePutQty(curProduct,(curProduct.realPutQty||0) - 1)
  263. }else{
  264. // 入库数量等于0
  265. // 切换到上一个商品
  266. if(this.curProductIndex){
  267. this.curProductIndex = this.curProductIndex - 1
  268. this.pickFun(flag)
  269. }else{
  270. this.loading = false
  271. playAudio('warn')
  272. }
  273. }
  274. }
  275. }else{
  276. this.curProductIndex = 0
  277. if(this.code == ''){
  278. uni.$u.toast("请扫描条形码")
  279. playAudio('warn')
  280. }else{
  281. uni.$u.toast("此商品不存在")
  282. playAudio('error')
  283. }
  284. }
  285. },
  286. // 关闭弹框
  287. closePop(){
  288. this.$refs.popup.close()
  289. },
  290. okPop(){
  291. const curProduct = this.tempProduct
  292. if(curProduct.packQty){
  293. this.changePutQty(curProduct,Number(curProduct.realPutQty||0) + Number(curProduct.packQty))
  294. this.closePop()
  295. }else{
  296. uni.$u.toast("请输入数量!")
  297. playAudio('warn')
  298. }
  299. },
  300. // 修改入库数量
  301. changePutQty(record, realPutQty){
  302. if(realPutQty>=0){
  303. this.loading = true
  304. updateRealPutQty({id:record.id,realPutQty:realPutQty}).then(res => {
  305. if(res.status == 200){
  306. uni.$u.toast(res.message)
  307. this.getDetail()
  308. this.getDetailList()
  309. }
  310. this.loading = false
  311. })
  312. }else{
  313. this.loading = false
  314. uni.$u.toast("入库数量不能小于0")
  315. playAudio('warn')
  316. }
  317. },
  318. keyDown(e){
  319. this.keyName = e
  320. },
  321. // 确定选择仓库
  322. confirmWarehouse(data){
  323. console.log(data)
  324. const curProduct = this.tempProduct
  325. this.updateWarehouse({id:curProduct.id,warehouseSn:data[0],warehouseLocationSn:data[1]})
  326. },
  327. // 修改仓库
  328. editRow(item){
  329. this.warehouseVal = item.warehouseSn ? [item.warehouseSn,item.warehouseLocationSn] : this.defWarehouse
  330. this.showPick = true
  331. this.tempProduct = item
  332. },
  333. // 修改仓库
  334. updateWarehouse (row) {
  335. console.log(row)
  336. this.loading = true
  337. purchaseUpdateWarehouse({
  338. id: row.id,
  339. warehouseSn: row.warehouseSn,
  340. warehouseLocationSn: row.warehouseLocationSn
  341. }).then(res => {
  342. if (res.status == 200) {
  343. this.showPick = false
  344. this.getDetailList()
  345. }
  346. this.loading = false
  347. })
  348. },
  349. // 详情
  350. getDetail(){
  351. receivingQuery({receivingBillSn: this.receivingBillSn, source : "PDA"}).then(res => {
  352. console.log(res,'详情')
  353. if(res.status == 200){
  354. this.baseData = res.data
  355. }
  356. })
  357. },
  358. // 产品明细列表
  359. getDetailList(){
  360. receivingDetail({pageNo:1,pageSize:1000,receivingBillSn:this.receivingBillSn}).then(res => {
  361. console.log(res,'明细列表')
  362. if(res.status == 200){
  363. this.detailList = res.data.list
  364. this.getCurRow()
  365. }
  366. })
  367. },
  368. // 打开包装数弹框
  369. openPack(){
  370. this.getCurProduct()
  371. const curProduct = this.getCurRow()
  372. this.tempProduct = curProduct
  373. if(curProduct.realPutQty < curProduct.putQty){
  374. this.$refs.popup.open()
  375. }else{
  376. // 切换到下一个商品
  377. if(this.curProductIndex<this.curProductArr.length-1){
  378. this.curProductIndex = this.curProductIndex + 1
  379. this.openPack()
  380. }else{
  381. // 直到最后一条数据,扫描数量无上线增加
  382. this.$refs.popup.open()
  383. }
  384. }
  385. },
  386. // 入库
  387. async toOut(){
  388. const isOk = await receivingStockInVerify({receivingBillSn:this.receivingBillSn})
  389. if(!isOk.data){
  390. this.submitForm()
  391. }else{
  392. this.showModal = true
  393. this.msg = {
  394. title: '提示',
  395. content: '有产品入库数量与发货数量不一致,确定入库?',
  396. confirmText: '确定'
  397. }
  398. }
  399. },
  400. confirmModal(e){
  401. this.submitForm()
  402. },
  403. async submitForm(){
  404. const a = this.defWarehouse
  405. const ret = await purchaseWriteStockIn({id: this.baseData.id,warehouseSn:a[0], warehouseLocationSn:a[1]})
  406. if(ret.status == 200){
  407. this.$store.state.vuex_isRefash = true
  408. uni.navigateBack()
  409. }
  410. this.showModal = false
  411. }
  412. },
  413. }
  414. </script>
  415. <style lang="scss">
  416. .p-content{
  417. .p-head{
  418. font-size: 32upx;
  419. color: $uni-text-color;
  420. >view{
  421. display: flex;
  422. align-items: center;
  423. padding: 10upx 20upx;
  424. border-bottom: 1px solid #eee;
  425. justify-content: space-between;
  426. > view{
  427. display: flex;
  428. padding: 0 10upx;
  429. align-items: center;
  430. }
  431. }
  432. .uni-input{
  433. border: 1px solid #eee;
  434. width: 150upx;
  435. text-align: center;
  436. padding: 8upx;
  437. }
  438. }
  439. .p-body{
  440. flex-grow: 1;
  441. height: calc(100vh - 240px);
  442. .scrollView{
  443. height: 100%;
  444. }
  445. }
  446. .p-footer{
  447. padding: 20upx;
  448. display: flex;
  449. > button{
  450. width: 40%;
  451. height: 32px;
  452. line-height: 32px;
  453. }
  454. }
  455. }
  456. </style>