batchbyOneModal.vue 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503
  1. <template>
  2. <el-drawer
  3. v-loading="load"
  4. :title="data.length <= 1 ? '订单发货' : '订单发货(批量逐一发货)'"
  5. :visible.sync="drawer"
  6. @close="close"
  7. :direction="direction"
  8. size="50%">
  9. <div class="content">
  10. <div class="order-top" v-if="data.length > 1">
  11. <el-pagination
  12. background
  13. :page-size="1"
  14. :current-page="currentOrder + 1"
  15. layout="prev, pager, next"
  16. @current-change="currentChange"
  17. :total="data.length">
  18. </el-pagination>
  19. </div>
  20. <deliveryGoodsInfo :hideOrderCode="true" @editState="editState" @editResult="editResult" ref="info" />
  21. <deliveryPrice :data="priceObj[data[currentOrder].omsOrderIds]" ref="price" v-if="data[currentOrder] && priceObj[data[currentOrder].omsOrderIds]"
  22. @prichChange="prichChange" :currentValue="currentPrice[data[currentOrder].omsOrderIds]" />
  23. </div>
  24. <div class="space"></div>
  25. <div class="deli-footer">
  26. <div class="d-left">
  27. <div class="estimate-total">
  28. 订单小计<span class="total">¥{{data[currentOrder] && currentPrice[data[currentOrder].omsOrderIds]?currentPrice[data[currentOrder].omsOrderIds].estimateFreight:'0.00'}}</span>
  29. <!-- <span class="detail">明细></span> -->
  30. </div>
  31. <!-- <div class="estimate-total">
  32. 预计总价<span class="total">¥48.00</span>
  33. </div> -->
  34. <div class="agreement">
  35. <el-checkbox v-model="checked">已读并同意《XXX电子运单协议》</el-checkbox>
  36. </div>
  37. </div>
  38. <div class="btn-box">
  39. <div class="send-btn" @click="nextBtn" :class="{'stopBtn':stopHandle}" v-if="data.length > 1">确认,下一单</div>
  40. <div class="send-btn" @click="btn" :class="{'stopBtn':stopHandle}">一键发货</div>
  41. </div>
  42. </div>
  43. </el-drawer>
  44. </template>
  45. <script lang="ts">
  46. import { Component, Prop, Vue, Watch } from "vue-property-decorator";
  47. import DeliveryGoodsInfo from "./deliveryGoodsInfo.vue";
  48. import DeliveryPrice from "./deliveryPrice.vue";
  49. import { add,multiply,subtract,divide } from '@/benyun/utils/accuracy'
  50. import { queryPricePackage,addmultiple,getInventoryByStoreHouseIdAndSkuids } from '@/api/delivery'
  51. import Format from '@/benyun/utils/dateFormat'
  52. @Component({components:{DeliveryGoodsInfo,DeliveryPrice}})
  53. export default class BatchbyOneModal extends Vue {
  54. drawer=false;
  55. direction='rtl'
  56. checked=false;
  57. data:Array<any>=[];
  58. currentOrder=0;
  59. isSuccess=false;
  60. stopHandle=false;
  61. load = false;
  62. priceObj:any={};
  63. currentPrice:any={};
  64. setShow(v:boolean){
  65. this.drawer=v;
  66. this.priceObj={};
  67. this.currentPrice={};
  68. this.isSuccess = false;
  69. this.stopHandle = false;
  70. this.currentOrder = 0;
  71. this.checked = false;
  72. }
  73. close(){
  74. if(this.isSuccess){
  75. this.$emit('handleSuccess');
  76. }
  77. }
  78. editResult(v:any){
  79. this.data[this.currentOrder] = v;
  80. this.getStoreCount(v);
  81. this.getPriceInfo(v);
  82. }
  83. prichChange(index:number){
  84. this.currentPrice[this.data[this.currentOrder].omsOrderIds] = this.priceObj[this.data[this.currentOrder].omsOrderIds][index];
  85. this.$forceUpdate();
  86. }
  87. currentChange(v:number){
  88. this.currentOrder = v-1;
  89. this.$forceUpdate();
  90. this.$nextTick(()=>{
  91. this.setInfo();
  92. })
  93. }
  94. setInfo(){
  95. (this.$refs.info as any).setValue(this.data[this.currentOrder]);
  96. }
  97. setValue(data:Array<any>){
  98. this.data = [];
  99. if(data && data.length > 0){
  100. for(const item of data){
  101. const requestId = new Date().getTime() + this.getUuid()
  102. let obj:any={
  103. tmsTransportMethod:'零担',
  104. tmsBusinessMan: (this as any).$store.getters.userInfo.userName,
  105. tmsBusinessPhone: (this as any).$store.getters.userInfo.phonenumber,
  106. requestId:requestId,
  107. omsOrderIds:item.id,
  108. tmsUnloadingProvince:item.receiverProvince,
  109. tmsUnloadingProvinceNo:item.receiverProvinceCode,
  110. tmsUnloadingCity:item.receiverCity,
  111. tmsUnloadingCityNo:item.receiverCityCode,
  112. tmsUnloadingRegion:item.receiverDistrict,
  113. tmsUnloadingRegionNo:item.receiverDistrictCode,
  114. tmsUnloadingStreet:item.receiverTown,
  115. tmsUnloadingStreetNo:item.receiverTownCode,
  116. tmsUnloadingAddress:item.receiverAddress,
  117. tmsUnloadingConsignor:item.receiverName,
  118. tmsUnloadingContacts:item.receiverMobile
  119. };
  120. obj.subItem=[];
  121. if(item.items && item.items.length > 0){
  122. for(const i of item.items){
  123. let total:any = 0;
  124. if(Number(i.qty) && Number(i.price)){
  125. total = multiply(Number(i.qty),Number(i.price))
  126. }
  127. obj.subItem.push({
  128. requestId:requestId,
  129. omsOrderId:item.id,
  130. omsOrderItemId:i.itemId,
  131. // omsOrderItemSkuId:i.itemId,
  132. tmsGoodsModel:i.styleId,
  133. tmsGoodsCode:i.skuId,
  134. tmsQuantity:i.qty,
  135. tmsGoodsTotalPrice:total,
  136. name:i.name,
  137. price:i.price,
  138. weight:i.weight
  139. })
  140. }
  141. }
  142. this.data.push(obj)
  143. }
  144. }else{
  145. this.data = []
  146. }
  147. this.$nextTick(()=>{
  148. (this.$refs.info as any).setValue(this.data[this.currentOrder])
  149. })
  150. }
  151. getUuid(){
  152. return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
  153. }
  154. btn(){
  155. this.noSentOrder();
  156. if(!this.data[this.currentOrder]){
  157. this.$message('没有需要发货的订单!')
  158. return
  159. }
  160. if(this.stopHandle){
  161. this.$message('库存不足!')
  162. return
  163. }
  164. if(!this.checked){
  165. this.$message('请阅读并同意运单协议!')
  166. return
  167. }
  168. if(!this.data[this.currentOrder].tmsShipmentConsignor || !this.data[this.currentOrder].tmsUnloadingAddress || !this.data[this.currentOrder].tmsUnloadingConsignor){
  169. this.$message("订单信息不完善,请前往编辑!");
  170. return
  171. }
  172. if(!this.currentPrice[this.data[this.currentOrder].omsOrderIds]){
  173. this.$message("请选择价格!");
  174. return
  175. }
  176. if(this.data.length > 1){
  177. let ids='';
  178. for(const item of this.data){
  179. if(!item.tmsShipmentConsignor || !item.tmsUnloadingAddress || !item.tmsUnloadingConsignor){
  180. ids = ids ? ids + ',' + item.omsOrderIds : String(item.omsOrderIds)
  181. }
  182. }
  183. if(ids){
  184. this.$confirm('订单'+ids + '未编辑,是否以第一条订单为基准', '提示', {
  185. confirmButtonText: '确定',
  186. cancelButtonText: '取消',
  187. type: 'warning'
  188. }).then(() => {
  189. this.setOnEditOrderInfo(ids);
  190. this.sendGoods(this.data[this.currentOrder]);
  191. }).catch(() => {});
  192. }else{
  193. this.sendGoods(this.data[this.currentOrder]);
  194. }
  195. }else{
  196. if(this.data[0].isSuccess){
  197. this.$message('订单:'+this.data[0].omsOrderIds+'已执行过发货操作!');
  198. return
  199. }
  200. this.sendGoods(this.data[0]);
  201. }
  202. }
  203. nextBtn(){
  204. if(this.currentOrder >= this.data.length){
  205. this.$message('已经是最后一单!')
  206. return
  207. }
  208. if(this.stopHandle){
  209. this.$message('库存不足!')
  210. return
  211. }
  212. if(!this.checked){
  213. this.$message('请阅读并同意运单协议!')
  214. return
  215. }
  216. const _value = this.data[this.currentOrder];
  217. if(!_value.tmsBusinessMan || !_value.tmsBusinessPhone || !_value.tmsShipmentConsignor || !_value.tmsShipmentContacts || !_value.tmsUnloadingConsignor || !_value.tmsUnloadingContacts || !_value.tmsUnloadingProvince || !_value.tmsUnloadingAddress || !_value.storeHouseId){
  218. this.$message("请编辑订单信息");
  219. return
  220. }
  221. if(!this.currentPrice[_value.omsOrderIds]){
  222. this.$message('请选择价格!')
  223. return
  224. }
  225. if(_value.isSuccess){
  226. this.$message('订单:'+_value.omsOrderIds+'已执行过发货操作!');
  227. return
  228. }
  229. this.sendGoods(_value,true);
  230. }
  231. //查库存
  232. getStoreCount(item:any,callback?:Function){
  233. if(!item){
  234. return
  235. }
  236. let params:any={};
  237. params.storeHouseId = item.storeHouseId;
  238. params.skuIds=[];
  239. if(item.subItem){
  240. for(const i of item.subItem){
  241. if(params.skuIds.indexOf(i.omsOrderItemId) == -1){
  242. params.skuIds.push(i.omsOrderItemId);
  243. }
  244. }
  245. }
  246. this.load = true;
  247. getInventoryByStoreHouseIdAndSkuids(params).then((res:any) => {
  248. this.load = false;
  249. let m='';
  250. for(const i of item.subItem){
  251. for(const d of res.data){
  252. let s = Number(d.inventory) - Number(d.useInventory) - Number(i.tmsQuantity);
  253. if(i.omsOrderItemId == d.skuid && s < 0){
  254. m = m ? m + ',' + i.name : i.name;
  255. }else{
  256. d.inventory = subtract(d.inventory, i.tmsQuantity);
  257. }
  258. }
  259. }
  260. if(m){
  261. this.$message({
  262. message:'商品“'+m+'”库存不足!',
  263. type:'error'
  264. })
  265. this.stopHandle = true;
  266. return
  267. }
  268. if(callback) callback(item,this.sendGoods)
  269. }).catch(()=>{
  270. this.load = false;
  271. })
  272. }
  273. //发货
  274. sendGoods(item:any,isNext?:boolean){
  275. if(!item){
  276. this.$message('订单不存在!')
  277. return
  278. }
  279. let params:any=(this as any).$lodash.cloneDeep(item);
  280. if(this.priceObj[item.omsOrderIds]){
  281. try{
  282. params.pricePlan = JSON.stringify(this.priceObj[item.omsOrderIds])
  283. }catch(e){}
  284. }
  285. if(this.currentPrice[item.omsOrderIds]){
  286. params.priceId = this.currentPrice[item.omsOrderIds].id;
  287. }
  288. params.omsOrderIds = [item.omsOrderIds];
  289. params.tmsMaterials=[];
  290. if(item.subItem){
  291. for(const i of item.subItem){
  292. params.tmsMaterials.push({
  293. storeHouseId:item.storeHouseId,
  294. materialSkuId:i.omsOrderItemId
  295. })
  296. }
  297. }
  298. delete params.subItem;
  299. this.load = true;
  300. addmultiple(params).then((res:any) => {
  301. this.load = false;
  302. if(res.code == 200){
  303. this.isSuccess = true;
  304. this.$message({
  305. message:'订单:'+item.omsOrderIds+'发货成功!',
  306. type:'success'
  307. })
  308. for(let it of this.data){
  309. if(it.omsOrderIds == item.omsOrderIds){
  310. it.isSuccess=true;
  311. break;
  312. }
  313. }
  314. if(!isNext){
  315. //寻找未发货的订单
  316. this.noSentOrder();
  317. let _item:any = this.data[this.currentOrder];
  318. //是否是最后一单
  319. if(this.currentOrder >= this.data.length){
  320. this.drawer = false;
  321. }else{
  322. if(this.currentPrice[_item.omsOrderIds]){
  323. this.sendGoods(_item);
  324. }else{
  325. this.getStoreCount(_item,this.getPriceInfo);
  326. }
  327. }
  328. }else{
  329. if(this.currentOrder < this.data.length - 1) {
  330. this.currentOrder ++;
  331. this.setInfo();
  332. }
  333. }
  334. this.$forceUpdate();
  335. }
  336. }).catch(() => {
  337. this.load = false;
  338. })
  339. }
  340. //寻找未发货订单
  341. noSentOrder(){
  342. this.currentOrder = this.data.length;
  343. for(let i = 0; i < this.data.length; i++){
  344. if(!this.data[i].isSuccess){
  345. this.currentOrder = i;
  346. break
  347. }
  348. }
  349. // if(this.data[this.currentOrder]){
  350. this.setInfo();
  351. // }
  352. }
  353. setOnEditOrderInfo(ids:string){
  354. let _value = this.data[0]
  355. for(const item of this.data){
  356. if(ids.indexOf(item.omsOrderIds) > -1 && !item.isSuccess){
  357. item.orderType = _value.orderType;
  358. item.storeHouseId = _value.storeHouseId;
  359. item.tmsArrivalDate = _value.tmsArrivalDate;
  360. item.tmsDeliveryDate =_value.tmsDeliveryDate;
  361. item.tmsTransportMethod = _value.tmsTransportMethod;
  362. item.tmsBusinessMan = _value.tmsBusinessMan;
  363. item.tmsBusinessPhone = _value.tmsBusinessPhone;
  364. item.tmsShipmentConsignor = _value.tmsShipmentConsignor;
  365. item.tmsShipmentContacts = _value.tmsShipmentContacts;
  366. item.tmsShipmentProvince = _value.tmsShipmentProvince;
  367. item.tmsShipmentProvinceNo = _value.tmsShipmentProvinceNo;
  368. item.tmsShipmentCity = _value.tmsShipmentCity;
  369. item.tmsShipmentCityNo = _value.tmsShipmentCityNo;
  370. item.tmsShipmentRegion = _value.tmsShipmentRegion;
  371. item.tmsShipmentRegionNo = _value.tmsShipmentRegionNo;
  372. item.tmsShipmentStreetNo = _value.tmsShipmentStreetNo;
  373. item.tmsShipmentStreet = _value.tmsShipmentStreet;
  374. item.tmsShipmentAddress = _value.tmsShipmentAddress;
  375. item.tmsUnloadingConsignor = _value.tmsUnloadingConsignor;
  376. item.tmsUnloadingContacts = _value.tmsUnloadingContacts;
  377. item.tmsUnloadingProvince = _value.tmsUnloadingProvince;
  378. item.tmsUnloadingProvinceNo = _value.tmsUnloadingProvinceNo;
  379. item.tmsUnloadingCity = _value.tmsUnloadingCity;
  380. item.tmsUnloadingCityNo = _value.tmsUnloadingCityNo;
  381. item.tmsUnloadingRegion = _value.tmsUnloadingRegion;
  382. item.tmsUnloadingRegionNo = _value.tmsUnloadingRegionNo;
  383. item.tmsUnloadingStreetNo = _value.tmsUnloadingStreetNo;
  384. item.tmsUnloadingStreet = _value.tmsUnloadingStreet;
  385. item.tmsUnloadingAddress = _value.tmsUnloadingAddress;
  386. }
  387. }
  388. }
  389. //获取价格
  390. getPriceInfo(data:any,callback?:Function){
  391. let params:any={};
  392. params.startStoreHouseId = data.storeHouseId;
  393. // params.startAddressCode = data.tmsShipmentCityNo + '00000';
  394. params.endAddressCode = data.tmsUnloadingCityNo + '00000';
  395. params.omsIds=[this.data[0].omsOrderIds];
  396. params.planType = data.tmsTransportMethod;
  397. this.load = true;
  398. queryPricePackage(params).then((res:any) => {
  399. this.load=false;
  400. let current=null;
  401. for(let item of res.data[0].data){
  402. let d = new Date().getTime() + item.duration*60*60*1000;
  403. item.endTime=Format(new Date(d),'MM月dd日 HH:mm');
  404. if(!current) current = item;
  405. if(Number(current.estimateFreight) > Number(item.estimateFreight)){
  406. current = item
  407. }
  408. }
  409. this.priceObj[data.omsOrderIds] = res.data[0].data;
  410. this.currentPrice[data.omsOrderIds] = current;
  411. this.$forceUpdate();
  412. if(callback){
  413. callback(data)
  414. }
  415. }).catch((err:any)=>{
  416. this.load = false;
  417. })
  418. }
  419. editState(v:boolean){
  420. this.drawer = v
  421. }
  422. }
  423. </script>
  424. <style lang="scss" scoped>
  425. .content{
  426. width: 100%;
  427. box-sizing: border-box;
  428. padding: 0 16px;
  429. background-color: #FFF;
  430. .order-top{
  431. padding-bottom: 16px;
  432. display: flex;
  433. justify-content: center;
  434. }
  435. }
  436. .deli-footer{
  437. height: 80px;
  438. width: 100%;
  439. box-shadow: 0 -5px 10px #EEE;
  440. padding: 0 16px 8px;
  441. box-sizing: border-box;
  442. display: flex;
  443. justify-content: space-between;
  444. align-items:flex-end;
  445. position: absolute;
  446. background-color: #FFF;
  447. left: 0;
  448. bottom: 0;
  449. z-index: 10;
  450. .d-left{
  451. width: 50%;
  452. .estimate-total{
  453. font-size: 14px;
  454. padding-bottom: 4px;
  455. .total{
  456. font-size: 16px;
  457. color: #F00;
  458. }
  459. .detail{
  460. color: #1684FC;
  461. padding-left: 16px;
  462. cursor: pointer;
  463. }
  464. }
  465. }
  466. .send-btn{
  467. width: 120px;
  468. height: 40px;
  469. line-height: 40px;
  470. margin-left: 16px;
  471. border-radius: 8px;
  472. background: linear-gradient(129.2deg, rgba(22,132,252,1) 9.81%,rgba(93,167,249,1) 97.4%);
  473. color: rgba(255, 255, 255, 100);
  474. font-size: 14px;
  475. text-align: center;
  476. box-shadow: 0px 2px 6px 0px rgba(93, 167, 249, 100);
  477. cursor: pointer;
  478. }
  479. .stopBtn{
  480. opacity: 0.7;
  481. }
  482. .btn-box{
  483. width: 50%;
  484. display: flex;
  485. justify-content: flex-end;
  486. align-items: center;
  487. }
  488. }
  489. .space{
  490. height: 80px;
  491. width: 100%;
  492. margin-top: 16px;
  493. }
  494. </style>