submit-order.vue 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170
  1. <template>
  2. <div class="submit-order">
  3. <div class="content">
  4. <div class="step-box">
  5. <div class="left">
  6. <span class="img"></span>
  7. <span class="text">{{$t('submitOrder.submitOrder')}}</span>
  8. </div>
  9. <div class="steps">
  10. <div class="item">
  11. <div class="number">step 01.</div>
  12. <div class="text">{{$t('submitOrder.selectProductToBuy')}}</div>
  13. </div>
  14. <div class="item active">
  15. <div class="number">step 02.</div>
  16. <div class="text">{{$t('submitOrder.confirmOrderInformation')}}</div>
  17. </div>
  18. <div class="item">
  19. <div class="number">step 03.</div>
  20. <div class="text">{{$t('submitOrder.payToCompleteTheOrder')}}</div>
  21. </div>
  22. </div>
  23. </div>
  24. <div class="submit-con">
  25. <!-- 收货地址 (mold=1虚拟商品不展示收货地址) -->
  26. <div v-if="mold !== 1" class="submit-box submit-box-border">
  27. <div class="tit">
  28. <span class="text">{{$t('address.receivingAddress')}}</span>
  29. <!-- <span class="action">显示全部地址</span> -->
  30. </div>
  31. <div class="con address-box">
  32. <div
  33. :class="[
  34. 'item',
  35. address.commonAddr ? 'default-address' : '',
  36. selectedAddrId == address.addrId ? 'active' : ''
  37. ]"
  38. v-for="address in addressList"
  39. :key="address.addrId"
  40. @click="changeAddress(address.addrId)"
  41. >
  42. <div class="name-phone">
  43. <span class="name">{{ address.receiver }}</span>
  44. <span class="phone">{{ address.mobile }}</span>
  45. <span
  46. class="set-default"
  47. v-if="!address.commonAddr"
  48. @click="setDefaultAddr(address.addrId)"
  49. >{{$t('address.setDefault')}}</span
  50. >
  51. <span class="default-tag" v-if="address.commonAddr">{{$t('address.default')}}</span>
  52. </div>
  53. <div class="address-detail">
  54. {{
  55. address.province + address.city + address.area + address.addr
  56. }}
  57. </div>
  58. <div class="del-edit">
  59. <span
  60. class="edit"
  61. @click.stop="editAddr(address.addrId)"
  62. ></span>
  63. <span
  64. class="del"
  65. @click.stop="toggleDelAddr(true, address.addrId)"
  66. ></span>
  67. </div>
  68. </div>
  69. <div class="item add-address" @click="toggleAddrPop(true)" v-if="addressList.length<10">
  70. <div class="add-box">
  71. <div class="img">+</div>
  72. <div class="text">{{$t('address.addAddress')}}</div>
  73. </div>
  74. </div>
  75. </div>
  76. <div class="popup-mask" v-if="showDelAddr"></div>
  77. <div class="fix-transform-blur">
  78. <div class="popup-box" v-if="showDelAddr">
  79. <div class="tit" style="padding:10px;">
  80. <div class="text">{{$t('tips')}}</div>
  81. <div class="close" @click="toggleDelAddr(false)"></div>
  82. </div>
  83. <div class="con">
  84. <div class="tip">
  85. <div class="tip-icon warning"></div>
  86. <div class="tip-info">
  87. <div class="result">{{$t('address.deleteShippingAddress')}}</div>
  88. <div class="date">{{$t('address.deleteShippingTips')}}</div>
  89. <div class="btns">
  90. <a
  91. href="javascript:void(0);"
  92. @click="delAddr()"
  93. class="btn-r"
  94. >{{$t('delete')}}</a
  95. >
  96. <a
  97. href="javascript:void(0);"
  98. @click="toggleDelAddr(flase)"
  99. class="btn-g"
  100. >{{$t('cancel')}}</a
  101. >
  102. </div>
  103. </div>
  104. </div>
  105. </div>
  106. </div>
  107. </div>
  108. </div>
  109. <!-- 收货地址 -->
  110. <!-- 支付方式 -->
  111. <div class="submit-box submit-box-border">
  112. <div class="tit">
  113. <span class="text">{{$t('commonFoot.paymentMethod')}}</span>
  114. </div>
  115. <div class="con pay-way">
  116. <div class="item active">{{$t('submitOrder.payOnline')}}</div>
  117. <!-- <div class="item">货到付款</div>
  118. <div class="item">线下支付</div>-->
  119. </div>
  120. </div>
  121. <!-- 支付方式 -->
  122. <!-- 积分抵扣 -->
  123. <div
  124. class="submit-box integral-box submit-box-border"
  125. v-if="orderInfo.maxUsableScore > 0"
  126. >
  127. <div class="tit">
  128. <span class="text">{{$t('submitOrder.pointsCredit')}}</span>
  129. </div>
  130. <!-- 积分抵现 -->
  131. <div class="integral-item">
  132. <label class="text">
  133. <el-checkbox
  134. v-model="checked"
  135. :disabled="isProhibit"
  136. class="item-group"
  137. @change="useMemberPoints"
  138. ></el-checkbox
  139. >{{$t('submitOrder.usePointsForCrediting')}}
  140. </label>
  141. <div class="con"></div>
  142. </div>
  143. <!-- 积分抵现 -->
  144. <div class="integral-item integral-input-box" v-if="isScorePay == 1">
  145. {{$t('submitOrder.accountTotal')}} {{ accountCanUseScore }}{{$t('submitOrder.pointThisUse')}}
  146. <input
  147. type="number"
  148. v-model="userUseScore"
  149. class="text"
  150. @input="inputComplete()"
  151. />
  152. <!-- @input="inputComplete()" -->
  153. {{$t('submitOrder.pcsCredit')}}
  154. <span class="integral-money">
  155. ¥{{
  156. userUseScore
  157. ? Number(orderInfo.totalScoreAmount).toFixed(2)
  158. : '0.00'
  159. }}
  160. </span>
  161. <span>
  162. ({{$t('submitOrder.theOrderIsAvailableUpTo')}} {{ orderInfo.maxUsableScore }} {{$t('submitOrder.points')}})
  163. <span v-if="shopUseScore > 100">{{($t('submitOrder.pleaseEnterAMultipleOf10'))}}</span>
  164. </span>
  165. </div>
  166. <div class="integral-item integral-text" v-if="isScorePay == 1">
  167. <span class="font-bold">
  168. {{$t('submitOrder.amountCredit')}}
  169. <span class="integral-money">
  170. ¥{{
  171. userUseScore
  172. ? Number(orderInfo.totalScoreAmount).toFixed(2)
  173. : '0.00'
  174. }}
  175. </span>
  176. </span>
  177. <span class="text-item font-bright">
  178. {{$t('submitOrder.use')}}¥
  179. {{
  180. userUseScore
  181. ? Number(orderInfo.totalScoreAmount).toFixed(2)
  182. : '0.00'
  183. }}
  184. </span>
  185. </div>
  186. </div>
  187. <!-- 积分抵扣 -->
  188. <!-- 全部留言(虚拟商品) -->
  189. <!-- <div v-if="mold === 1 && virtualRemarkList.length" class="submit-box all-msg-row">
  190. <div class="tit">
  191. <span class="text">{{$t('submitOrder.allMessages')}}</span>
  192. </div>
  193. <div class="con">
  194. <div v-for="(item,index) in virtualRemarkList" :key="index" class="msg-item">
  195. <span v-if="item.isRequired" class="red-stress">*</span>
  196. <input
  197. v-model="item.value"
  198. class="msg-int-item"
  199. type="text"
  200. :placeholder="$t('submitOrder.pleaseEnter') + `${item.name}`"
  201. @blur="handleInputBlur(item.value, index)"
  202. maxlength="20"
  203. >
  204. </div>
  205. </div>
  206. </div> -->
  207. <!-- 全部留言(虚拟商品)/ -->
  208. <!-- 配送方式 -->
  209. <div v-if="mold !== 1" class="submit-box submit-box-border">
  210. <div class="tit">
  211. <span class="text">{{$t('submitOrder.deliveryMethod')}}</span>
  212. </div>
  213. <div class="con delivery-way">
  214. <div class="item active">{{$t('submitOrder.courierDelivery')}}</div>
  215. <!-- <div class="item">到店自提</div> -->
  216. <!-- <div class="description">(该商品不支持自提)</div> -->
  217. </div>
  218. </div>
  219. <!-- /配送方式 -->
  220. <!-- 商品信息 -->
  221. <div class="submit-box goods-info" :class="{'last-box': !(platformCoupons && platformCoupons.canUseCoupons.length > 0) }">
  222. <div class="tit">
  223. <span class="text">{{$t('applyReturn.productInformation')}}</span>
  224. </div>
  225. <div class="goods-msg">
  226. <div class="msg-tab">
  227. <div class="img">&nbsp;</div>
  228. <div class="info">{{$t('products')}}</div>
  229. <div class="unit-price">{{$t('priceOne')}}</div>
  230. <div class="number">{{$t('quantity')}}</div>
  231. <div class="total">{{$t('subtotal')}}</div>
  232. </div>
  233. <div
  234. class="msg-con"
  235. :class="{'last-box': (platformCoupons && platformCoupons.canUseCoupons.length > 0) }"
  236. v-for="(shopCart, shopIndex) in shopCartOrders"
  237. :key="shopCart.shopId"
  238. >
  239. <!-- 店铺 -->
  240. <div class="shop-msg">
  241. <span class="shop-name">{{$t('index.shop')}}:</span>
  242. <nuxt-link
  243. :to="'/shopIndex?sid=' + shopCart.shopId"
  244. class="shop-name"
  245. >{{ shopCart.shopName }}</nuxt-link
  246. >
  247. <span class="self" v-if="shopCart.shopId == 1">{{$t('prodDetail.selfEmployed')}}</span>
  248. </div>
  249. <!-- 店铺中的商品 -->
  250. <div
  251. class
  252. v-for="(shopCartItemDiscount,
  253. discIndex) in shopCart.shopCartItemDiscounts"
  254. :key="discIndex"
  255. >
  256. <div
  257. class="goods-box"
  258. v-for="(prod,
  259. prodIndex) in shopCartItemDiscount.shopCartItems"
  260. :key="prodIndex"
  261. >
  262. <div class="prod-row">
  263. <div class="img">
  264. <nuxt-link :to="'/detail/' + prod.prodId" class="img-box">
  265. <img v-if="prod.pic" :src="prod.pic" alt />
  266. <img v-else src="~/assets/img/def.png" alt />
  267. </nuxt-link>
  268. </div>
  269. <div class="info">
  270. <nuxt-link :to="'/detail/' + prod.prodId" class="name">{{
  271. prod.prodName
  272. }}</nuxt-link>
  273. <span class="sku">{{ prod.skuName }}</span>
  274. </div>
  275. <div class="unit-price">
  276. ¥{{ parsePrice(prod.price)[0] }}.{{
  277. parsePrice(prod.price)[1]
  278. }}
  279. </div>
  280. <div class="number">×{{ prod.prodCount }}</div>
  281. <div class="total">
  282. ¥{{ parsePrice(prod.productTotalAmount)[0] }}.{{
  283. parsePrice(prod.productTotalAmount)[1]
  284. }}
  285. </div>
  286. </div>
  287. <!-- 赠品展示 -->
  288. <div v-if="prod.giveaway" class="gift-con">
  289. <div v-for="(giveawayItem, giveawayIndex) in prod.giveaway.giveawayProds" :key="giveawayIndex" class="gift-item">
  290. <nuxt-link class="gift-item-name" :to="'/detail/' + giveawayItem.prodId">
  291. {{$t('cart.giveaways')}} {{giveawayItem.prodName}}
  292. <span class="gift-item-sku-name">{{giveawayItem.skuName}} x{{giveawayItem.giveawayNum}}</span>
  293. </nuxt-link>
  294. </div>
  295. </div>
  296. <!-- 虚拟商品留言 start -->
  297. <div
  298. v-if="prod.virtualRemarkList && prod.virtualRemarkList.length"
  299. class="virtual-goods-msg"
  300. >
  301. <div :class="['msg-tit',$t('language')=='en' ? 'msg-tit-en' : '']">
  302. <span class="text">{{ $t('submitOrder.userMessage') }}:</span>
  303. </div>
  304. <div>
  305. <div v-for="(msgItem,msgIndex) in prod.virtualRemarkList" :key="msgIndex" class="msg-item">
  306. <span v-if="msgItem.isRequired" class="red-stress">*</span>
  307. <input
  308. v-model="msgItem.value"
  309. class="msg-int-item"
  310. type="text"
  311. :placeholder="$t('submitOrder.pleaseEnter') + `${msgItem.name}`"
  312. @blur="handleInputBlur(msgItem.value, msgIndex, prodIndex, discIndex, shopIndex)"
  313. maxlength="20"
  314. >
  315. </div>
  316. </div>
  317. </div>
  318. <!-- 虚拟商品留言 end -->
  319. </div>
  320. </div>
  321. <!-- 留言 -->
  322. <div class="remake-box">
  323. {{$t('orderDetails.orderRemarks')}}:
  324. <input
  325. type="text"
  326. class="text"
  327. v-model="shopCart.remarks"
  328. maxlength="100"
  329. :data-shopinde="shopIndex"
  330. :data-shopitem="shopCart"
  331. :placeholder="$t('submitOrder.numberLength100')"
  332. />
  333. <!-- 发票 -->
  334. <div class="invoice-title">{{ $t('invoice.invoiceInfo') }}</div>
  335. <div v-if="shopCart.invoiceDataFrom" class="invoice-box">
  336. <div v-if="shopCart.invoiceDataFrom.invoiceType === 1" class="invoice-box-item invoice-type">{{ $t('invoice.generalInvoice') }}</div>
  337. <div v-if="shopCart.invoiceDataFrom.invoiceType === 2 || !shopCart.invoiceDataFrom" class="invoice-box-item invoice-type">{{ $t('invoice.noInvoice') }}</div>
  338. <div v-if="shopCart.invoiceDataFrom.invoiceType === 1" class="invoice-box-item invoice-unit">{{ shopCart.invoiceDataFrom.headerName || $t('invoice.personal') }}</div>
  339. <div v-if="shopCart.invoiceDataFrom.invoiceType === 1" class="invoice-box-item invoice-contents">{{ $t('invoice.productDetails') }}</div>
  340. <div class="invoice-box-item invoice-operation" @click="showAddOrUpdateDialog(0,shopCart,shopCart.shopId)">{{ $t('invoice.update') }}</div>
  341. </div>
  342. <div v-else class="invoice-box">
  343. <div class="invoice-box-item invoice-type">{{ $t('invoice.noInvoice') }}</div>
  344. <div class="invoice-box-item invoice-operation" @click="showAddOrUpdateDialog(0,shopCart,shopCart.shopId)">{{ $t('invoice.update') }}</div>
  345. </div>
  346. <!-- 发票 -->
  347. </div>
  348. <!-- /留言 -->
  349. <!-- 优惠券选择框 -->
  350. <coupon-select
  351. :coupons="shopCart.shopCoupons"
  352. @checkCoupon="checkCoupon"
  353. v-if="
  354. shopCart.shopCoupons &&
  355. (shopCart.shopCoupons.canUseCoupons.length > 0 || shopCart.shopCoupons.unCanUseCoupons.length > 0)
  356. "
  357. ></coupon-select>
  358. <!-- 优惠券选择框 -->
  359. </div>
  360. </div>
  361. </div>
  362. <!-- 商品信息 -->
  363. <!-- 发票信息 -->
  364. <!-- <div class="submit-box">
  365. <div class="tit">
  366. <span class="text">发票信息</span>
  367. </div>
  368. <div class="con invoice-msg">
  369. <div class="invoice-text">电子普通发票</div>
  370. <div class="invoice-text">个人</div>
  371. <div class="invoice-text">商品明细</div>
  372. <a href=""
  373. class="invoice-btn">修改</a>
  374. </div>
  375. </div>-->
  376. <!-- /发票信息 -->
  377. <!-- 优惠券选择框 -->
  378. <div
  379. class="submit-box submit-box-border"
  380. v-if="platformCoupons && (platformCoupons.unCanUseCoupons.length > 0 || platformCoupons.canUseCoupons.length > 0)"
  381. >
  382. <div class="tit">
  383. <span class="text">{{$t('submitOrder.platformCoupons')}}</span>
  384. </div>
  385. <coupon-select
  386. :coupons="platformCoupons"
  387. :platform="true"
  388. :is-show-uncan="platformCoupons && platformCoupons.unCanUseCoupons.length > 0 && platformCoupons.canUseCoupons.length === 0 "
  389. @checkCoupon="checkCoupon"
  390. ></coupon-select>
  391. </div>
  392. </div>
  393. <!-- 金额明细 -->
  394. <div class="submit-bottom">
  395. <!-- 优惠明细 -->
  396. <div class="statistic-box">
  397. <!-- 商品总价 -->
  398. <div class="item">
  399. <div class="tit">
  400. <span class="number">{{ orderInfo.totalCount }}</span
  401. >{{$t('submitOrder.totalItems')}}:
  402. </div>
  403. <div class="con">
  404. ¥{{ parsePrice(orderInfo.total)[0] }}.{{
  405. parsePrice(orderInfo.total)[1]
  406. }}
  407. </div>
  408. </div>
  409. <!-- 应付运费 -->
  410. <div v-if="orderInfo.mold !== 1" class="item">
  411. <div class="tit">{{$t('submitOrder.freightPayable')}}:</div>
  412. <div class="con">
  413. <p>
  414. ¥{{ parsePrice(transfee)[0] }}.{{
  415. parsePrice(transfee)[1]
  416. }}
  417. </p>
  418. </div>
  419. </div>
  420. <!-- 平台开启会员包邮(运费减免) -->
  421. <div v-if="orderInfo.freeTransfee" class="item">
  422. <div class="tit">{{$t('submitOrder.memberPackage')}}:</div>
  423. <div class="con bright">
  424. <p>
  425. -¥{{ parsePrice(orderInfo.freeTransfee)[0] }}.{{
  426. parsePrice(orderInfo.freeTransfee)[1]
  427. }}
  428. </p>
  429. </div>
  430. </div>
  431. <!-- 积分抵扣 -->
  432. <div class="item" v-if="isScorePay == 1">
  433. <div class="tit red-font">{{$t('submitOrder.pointsCredit')}}:</div>
  434. <div class="con bright">
  435. -¥{{ parsePrice(orderInfo.totalScoreAmount)[0] }}.{{
  436. parsePrice(orderInfo.totalScoreAmount)[1]
  437. }}
  438. </div>
  439. </div>
  440. <!-- 平台优惠券 -->
  441. <div class="item" v-if="platformCoupons && platformCoupons.couponAmount">
  442. <div class="tit red-font">{{$t('submitOrder.platformCoupons')}}:</div>
  443. <div class="con bright">
  444. -¥{{ parsePrice(platformCoupons.couponAmount)[0] }}.{{
  445. parsePrice(platformCoupons.couponAmount)[1]
  446. }}
  447. </div>
  448. </div>
  449. <!-- 会员折扣 -->
  450. <div class="item" v-if="orderInfo.totalLevelAmount">
  451. <div class="tit">{{$t('submitOrder.memberDiscount')}}:</div>
  452. <div class="con bright">
  453. -¥{{ parsePrice(orderInfo.totalLevelAmount)[0] }}.{{
  454. parsePrice(orderInfo.totalLevelAmount)[1]
  455. }}
  456. </div>
  457. </div>
  458. <!-- 店铺优惠 -->
  459. <div class="item" v-if="orderInfo.orderShopReduce">
  460. <div class="tit red-font">{{$t('submitOrder.storeDiscount')}}:</div>
  461. <div class="con bright">
  462. -¥{{ parsePrice(orderInfo.orderShopReduce)[0] }}.{{
  463. parsePrice(orderInfo.orderShopReduce)[1]
  464. }}
  465. </div>
  466. </div>
  467. </div>
  468. <!-- 应付总额 -->
  469. <div class="detail-box">
  470. <div class="item">
  471. <div class="tit">{{$t('submitOrder.totalPayable')}}:</div>
  472. <div class="con">
  473. ¥{{ parsePrice(orderInfo.actualTotal)[0] }}.{{
  474. parsePrice(orderInfo.actualTotal)[1]
  475. }}
  476. </div>
  477. </div>
  478. <div class="item" v-if="currentAddr.addrId && mold !== 1">
  479. <span class="text">
  480. {{$t('submitOrder.sendTo')}}:{{
  481. currentAddr.province +
  482. ' ' +
  483. currentAddr.city +
  484. ' ' +
  485. currentAddr.area +
  486. ' ' +
  487. currentAddr.addr
  488. }}
  489. </span>
  490. <span class="text"
  491. >{{$t('submitOrder.consignee')}}:{{ currentAddr.receiver }} {{ currentAddr.mobile }}</span
  492. >
  493. </div>
  494. </div>
  495. <div class="btn-box">
  496. <a href="javascript:void(0)" class="btn" @click="submitOrder"
  497. >{{$t('submitOrder.submitOrder')}}</a
  498. >
  499. </div>
  500. </div>
  501. <!-- 金额明细 end -->
  502. </div>
  503. <!-- 地址弹窗 -->
  504. <AddressPop
  505. :editAddrId="editAddrId"
  506. v-if="showAddrPop"
  507. @getAddrList="getAddrList"
  508. @reloadOrderInfo="loadOrderInfo"
  509. @toggleAddrPop="toggleAddrPop"
  510. />
  511. <!-- /地址弹窗 -->
  512. <!-- 发票弹窗 -->
  513. <addOrEditInvoice
  514. v-if="showInvoiceAdd"
  515. ref="invoiceAddOrUpdate"
  516. @toggleAddrPop="refreshChange"
  517. @getInvoiceData="getInvoiceData"
  518. @hidePop="hideInvoicePop"
  519. />
  520. </div>
  521. </template>
  522. <script>
  523. import Cookie from 'js-cookie'
  524. import bus from '~/plugins/bus'
  525. import AddressPop from '~/components/add-or-edit-address'
  526. import CouponSelect from '~/components/coupon-select'
  527. import { _debounce, accuracyCount } from "~/plugins/util"; //防抖
  528. import addOrEditInvoice from '~/components/add-or-edit-invoice'
  529. export default {
  530. components: {
  531. AddressPop,
  532. CouponSelect,
  533. addOrEditInvoice
  534. },
  535. data () {
  536. return {
  537. addressList: [],
  538. selectedAddrId: 0,
  539. orderInfo: {},
  540. shopCartOrders: [],
  541. currentAddr: {}, // 当前选择的地址
  542. couponIds: [],
  543. couponUserIds: [],
  544. userChangeCoupon: 0, // 用户有没有对优惠券进行改变
  545. coupons: {
  546. totalLength: 0,
  547. canUseCoupons: [],
  548. unCanUseCoupons: []
  549. },
  550. totalScoreAmount: 0, // 积分抵扣金额
  551. totalUsableScore: 0, // 整个订单可以使用的积分数
  552. isScorePay: 0, // 用户是否选择积分抵现(0不使用 1使用 默认不使用)
  553. isChecked: true, // 是否选择会员积分抵现
  554. isProhibit: false, // (积分抵现)checkbox是否禁止
  555. showAddrPop: false, // 地址弹窗显隐
  556. // 地址数据
  557. editAddrId: 0, // 要修改的地址id
  558. showDelAddr: false,
  559. // 券
  560. showCanUse: true,
  561. orderEntry: 0, //订单入口 0购物车 1立即购买
  562. platformCoupons: {
  563. canUseCoupons: [],
  564. unCanUseCoupons: []
  565. },
  566. uuid: '',
  567. checked: false, //积分抵现选框
  568. userUseScore: '', // 使用多少积分抵扣
  569. accountCanUseScore: 0, // 账号可用积分
  570. maxUsableScore: 0,
  571. shopUseScore: '', // 积分抵扣比例
  572. // 发票弹窗
  573. showInvoiceAdd: false,
  574. invoiceId: '',
  575. invoiceDataFrom: '',
  576. // 应付运费
  577. transfee: 0,
  578. // 是否可提交订单
  579. canSubmitOrder: true,
  580. // 商品类型(1虚拟商品)
  581. mold: 0,
  582. // 全部留言列表
  583. // virtualRemarkList: [],
  584. allVirtualMsg: [],
  585. // 全部留言列表输入数据
  586. backupsVirtualRemarks: null
  587. }
  588. },
  589. mounted () {
  590. document.title = this.$t('submitOrder.submitOrder')
  591. //获取当前账号可用积分
  592. this.$axios.get('/p/score/scoreLevel/page?levelType=' + 0).then(({ data }) => {
  593. this.accountCanUseScore = data.score
  594. })
  595. if (this.$route.query.orderEntry) {
  596. this.orderEntry = this.$route.query.orderEntry
  597. }
  598. this.uuid = this.genUUID()
  599. this.getAddrList()
  600. this.loadOrderInfo(true)
  601. },
  602. beforeDestroy() {
  603. this.$store.commit('handleChangeErrMsg', '')
  604. },
  605. watch: {
  606. maxUsableScore (nv) {
  607. if (this.userUseScore > nv) {
  608. this.userUseScore = nv
  609. }
  610. }
  611. },
  612. methods: {
  613. showAddOrUpdateDialog(st, shopCart, shopId) {
  614. this.showInvoiceAdd = true
  615. const param = shopCart.invoiceDataFrom ? shopCart.invoiceDataFrom : ''
  616. this.$nextTick(() => {
  617. this.$refs.invoiceAddOrUpdate.init(st, param, '', shopId)
  618. })
  619. },
  620. /**
  621. * 刷新回调
  622. */
  623. refreshChange(visible) {
  624. this.showInvoiceAdd = visible
  625. // this.getUserAddr()
  626. },
  627. /**
  628. * 发票信息
  629. */
  630. getInvoiceData(invoiceDataFrom) {
  631. if(invoiceDataFrom.headerType === 2) {
  632. delete invoiceDataFrom.invoiceTaxNumber
  633. }
  634. this.shopCartOrders.forEach((item) => {
  635. if (item.shopId === invoiceDataFrom.shopId) {
  636. item.invoiceDataFrom = invoiceDataFrom
  637. }
  638. })
  639. this.showInvoiceAdd = false
  640. },
  641. hideInvoicePop(visible) {
  642. this.showInvoiceAdd = visible
  643. },
  644. /**
  645. * 积分输入
  646. */
  647. inputComplete: _debounce(function () {
  648. var userUseScore = this.userUseScore;
  649. userUseScore = userUseScore.replace(/[^\d]/g, ''); // 清除“数字”和“.”以外的字符
  650. if (userUseScore.indexOf('.') < 0 && userUseScore != '') {
  651. // 以上已经过滤,此处控制的是如果没有小数点,首位不能为类似于 01、02的金额
  652. userUseScore = parseInt(userUseScore);
  653. }
  654. this.userUseScore = userUseScore;
  655. if (this.shopUseScore > 100) {
  656. this.userUseScore = this.userUseScore - this.userUseScore % 10
  657. }
  658. if (this.userUseScore > this.maxUsableScore) {
  659. this.userUseScore = this.maxUsableScore
  660. }
  661. this.loadOrderInfo()
  662. },500),
  663. /**
  664. * 获取地址列表
  665. */
  666. getAddrList () {
  667. this.$axios.get('/p/address/list').then(({ data }) => {
  668. this.addressList = data
  669. })
  670. },
  671. /**
  672. * 选择地址
  673. */
  674. changeAddress (addrId) {
  675. this.addressList.forEach(element => {
  676. if (element.addrId == addrId) {
  677. this.currentAddr = element
  678. }
  679. })
  680. this.selectedAddrId = addrId
  681. this.loadOrderInfo()
  682. },
  683. /**
  684. * 改变优惠券选择
  685. */
  686. checkCoupon () {
  687. var couponIds = []
  688. var couponUserIds = []
  689. var shopCartOrders = this.shopCartOrders
  690. shopCartOrders.forEach(shopCart => {
  691. if (shopCart.shopCoupons) {
  692. shopCart.shopCoupons.canUseCoupons.forEach(coupon => {
  693. if (coupon.choose) {
  694. couponIds.push(coupon.couponId) // couponUserId
  695. couponUserIds.push(coupon.couponUserId)
  696. }
  697. })
  698. }
  699. })
  700. if (this.platformCoupons && this.platformCoupons.canUseCoupons.length) {
  701. this.platformCoupons.canUseCoupons.forEach(coupon => {
  702. if (coupon.choose) {
  703. couponIds.push(coupon.couponId)
  704. couponUserIds.push(coupon.couponUserId)
  705. }
  706. })
  707. }
  708. this.couponIds = couponIds
  709. this.couponUserIds = couponUserIds
  710. this.userChangeCoupon = 1
  711. this.loadOrderInfo()
  712. },
  713. /**
  714. * 设置为默认地址
  715. */
  716. setDefaultAddr (addrId) {
  717. this.$axios.put('/p/address/defaultAddr/' + addrId).then(({ data }) => {
  718. this.$message({
  719. message: data,
  720. type: 'success',
  721. duration: 1000
  722. })
  723. this.getAddrList()
  724. })
  725. },
  726. /**
  727. * 显示/隐藏确认删除弹窗
  728. */
  729. toggleDelAddr (sts, addrId) {
  730. this.showDelAddr = sts
  731. this.editAddrId = addrId
  732. },
  733. /**
  734. * 显示/隐藏地址弹窗
  735. */
  736. toggleAddrPop (sts) {
  737. if (Cookie.get('token')) {
  738. this.showAddrPop = sts
  739. this.editAddrId = 0
  740. } else {
  741. bus.$emit("showLogin", true)
  742. this.showAddrPop = false
  743. }
  744. },
  745. /**
  746. * 修改地址 (弹窗传地址id)
  747. */
  748. editAddr (addrId) {
  749. if (Cookie.get('token')) {
  750. this.showAddrPop = true
  751. this.editAddrId = addrId
  752. } else {
  753. bus.$emit("showLogin", true)
  754. this.showAddrPop = false
  755. }
  756. },
  757. /**
  758. * 删除地址
  759. */
  760. delAddr () {
  761. let reload = false
  762. if (this.selectedAddrId == this.editAddrId) {
  763. this.selectedAddrId = 0
  764. reload = true
  765. }
  766. this.$axios
  767. .delete('/p/address/deleteAddr/' + this.editAddrId)
  768. .then(({ data }) => {
  769. this.$message({
  770. message: data,
  771. type: 'success',
  772. duration: 1000
  773. })
  774. this.toggleDelAddr(false)
  775. this.getAddrList()
  776. if (reload) {
  777. this.loadOrderInfo()
  778. }
  779. })
  780. },
  781. /**
  782. * 价格处理
  783. */
  784. parsePrice: value => {
  785. var val = Number(value)
  786. if (!val) {
  787. val = 0
  788. }
  789. // 截取小数点后两位,并以小数点为切割点将val转化为数组
  790. return val.toFixed(2).split('.')
  791. },
  792. /**
  793. * 积分抵现选择
  794. */
  795. useMemberPoints() {
  796. this.userUseScore = ''
  797. var checked = !this.checked
  798. this.checked = !checked
  799. if (this.orderInfo.maxUsableScore > 0) {
  800. //maxUsableScore 整个订单可以使用的积分数
  801. this.isProhibit = false //(积分抵现)checkbox是否禁止
  802. // 如果积分可抵扣
  803. if (this.checked) {
  804. this.isScorePay = 1 //用户是否选择积分抵现(0不使用 1使用 默认不使用)
  805. } else if (!this.checked) {
  806. this.isScorePay = 0 //用户是否选择积分抵现(0不使用 1使用 默认不使用)
  807. }
  808. setTimeout(() => {
  809. this.loadOrderInfo() //加载订单数据
  810. },800)
  811. } else if (this.orderInfo.maxUsableScore <= 0) {
  812. this.isProhibit = true //(积分抵现)checkbox是否禁止
  813. }
  814. },
  815. /**
  816. * 加载订单数据
  817. */
  818. loadOrderInfo (isFirst) {
  819. // const loading = this.$loading({
  820. // lock: true,
  821. // text: '加载中...',
  822. // background: 'rgba(255, 255, 255, 0.8)
  823. // });
  824. var orderParam = {
  825. addrId: this.selectedAddrId,
  826. orderItem:
  827. this.orderEntry == 1
  828. ? JSON.parse(sessionStorage.getItem('orderItem'))
  829. : undefined,
  830. basketIds:
  831. this.orderEntry == 0
  832. ? JSON.parse(sessionStorage.getItem('basketIds'))
  833. : undefined,
  834. couponIds: this.couponIds,
  835. couponUserIds: this.couponUserIds,
  836. isScorePay: this.isScorePay,
  837. userChangeCoupon: this.userChangeCoupon,
  838. userUseScore: Number(this.userUseScore),
  839. uuid: this.uuid
  840. }
  841. this.$axios
  842. .post('/p/order/confirm', orderParam)
  843. .then(({ data }) => {
  844. var remarksList = []
  845. if (!isFirst) {
  846. this.shopCartOrders.forEach(el => {
  847. remarksList.push(el.remarks)
  848. })
  849. }
  850. var couponIds = []
  851. this.orderInfo = data
  852. this.maxUsableScore = data.maxUsableScore // 订单最大可用积分数量
  853. if (data.userAddr) {
  854. this.currentAddr = data.userAddr
  855. this.selectedAddrId = data.userAddr.addrId
  856. }
  857. this.platformCoupons = this.splitCouponAndPushCouponIds(
  858. data.coupons,
  859. couponIds
  860. ) //平台优惠券
  861. var shopCartOrders = data.shopCartOrders
  862. shopCartOrders.forEach((shopCart, index) => {
  863. if (isFirst) {
  864. shopCart.remarks = ''
  865. } else {
  866. shopCart.remarks = remarksList[index]
  867. }
  868. shopCart.shopCoupons = this.splitCouponAndPushCouponIds(
  869. shopCart.coupons,
  870. couponIds
  871. )
  872. })
  873. if(this.shopCartOrders.length === 0) {
  874. this.shopCartOrders = shopCartOrders
  875. }
  876. this.couponIds = couponIds
  877. this.shopUseScore = data.shopUseScore // 积分抵扣比例
  878. // 应付运费 = 商品总运费 - 会员包邮减免运费
  879. if (data.totalTransfee && data.freeTransfee) {
  880. this.transfee = accuracyCount(data.totalTransfee, data.freeTransfee, 1)
  881. } else {
  882. this.transfee = data.totalTransfee
  883. }
  884. // 商品类型(4虚拟商品)
  885. this.mold = data.mold || 0
  886. // 留言列表
  887. // if (this.backupsVirtualRemarks && this.backupsVirtualRemarks.length) {
  888. // this.virtualRemarkList = this.backupsVirtualRemarks
  889. // } else {
  890. // this.virtualRemarkList = data.virtualRemarkList
  891. // }
  892. this.handleAllVirtualMsg()
  893. })
  894. .catch((error) => {
  895. this.canSubmitOrder = false
  896. this.$router.push({path:'/cart'})
  897. })
  898. },
  899. /**
  900. * 分割优惠券成
  901. * 1. canUseCoupons 可使用优惠券列表
  902. * 2. unCanUseCoupons 不可使用优惠券列表
  903. * 3. couponAmount 选中的优惠券可优惠金额
  904. * 4. 将选中的优惠券ids保存起来
  905. * @param {*} coupons 优惠券列表
  906. * @param {*} couponIds 选中的优惠券id
  907. */
  908. splitCouponAndPushCouponIds (coupons, couponIds) {
  909. if (!coupons || !coupons.length) {
  910. return
  911. }
  912. let canUseCoupons = []
  913. let unCanUseCoupons = []
  914. let couponAmount = 0
  915. coupons.forEach(coupon => {
  916. if (coupon.canUse) {
  917. canUseCoupons.push(coupon)
  918. } else {
  919. unCanUseCoupons.push(coupon)
  920. }
  921. if (coupon.choose) {
  922. couponIds.push(coupon.couponId)
  923. couponAmount = coupon.reduceAmount
  924. }
  925. })
  926. return {
  927. canUseLength: canUseCoupons.length,
  928. couponAmount: couponAmount,
  929. canUseCoupons: canUseCoupons,
  930. unCanUseCoupons: unCanUseCoupons
  931. }
  932. },
  933. /**
  934. * 虚拟商品留言
  935. */
  936. handleAllVirtualMsg() {
  937. this.allVirtualMsg = this.getValueOfArr(this.shopCartOrders)
  938. },
  939. getValueOfArr(data) {
  940. const layers = ['shopCartItemDiscounts', 'shopCartItems', 'virtualRemarkList']
  941. const deepGet = (item, index) => {
  942. return item.map(la => {
  943. const children = la[layers[index]];
  944. if (Array.isArray(children)) {
  945. if (layers.length === index + 1) {
  946. return children.map((ch, idx) => {
  947. ch.id = la.prodId + '_' + idx
  948. return ch
  949. })
  950. }
  951. return deepGet(children, index + 1)
  952. }
  953. return []
  954. }).flat(Infinity)
  955. }
  956. return deepGet(data, 0)
  957. },
  958. /**
  959. * 虚拟商品留言输入框失焦
  960. */
  961. handleInputBlur (value, msgIndex, prodIndex, discIndex, shopIndex) {
  962. if (!value) {
  963. return
  964. }
  965. if (!value.trim()) {
  966. this.shopCartOrders[shopIndex].shopCartItemDiscounts[discIndex].shopCartItems[prodIndex].virtualRemarkList[msgIndex].value = value.trim()
  967. // this.virtualRemarkList[msgIndex].value = value.trim()
  968. return
  969. }
  970. const currentItem = this.shopCartOrders[shopIndex].shopCartItemDiscounts[discIndex].shopCartItems[prodIndex].virtualRemarkList[msgIndex]
  971. this.allVirtualMsg.forEach(msgItem => {
  972. if (currentItem.id === msgItem.id) {
  973. msgItem.value = value
  974. }
  975. })
  976. // this.backupsVirtualRemarks = this.virtualRemarkList
  977. },
  978. /**
  979. * 提交订单
  980. */
  981. submitOrder () {
  982. var shopCartOrders = this.shopCartOrders
  983. var orderShopParam = []
  984. var reg = /^\s+$/g
  985. shopCartOrders.forEach(shopCart => {
  986. orderShopParam.push({
  987. remarks: shopCart.remarks,
  988. shopId: shopCart.shopId
  989. })
  990. })
  991. let remarksFlag = orderShopParam.some(item=>{
  992. return reg.test(item.remarks)
  993. })
  994. if (remarksFlag) {
  995. this.$message({
  996. message: this.$t('inputAllSpace'),
  997. type: 'error',
  998. duration: 1000
  999. })
  1000. return;
  1001. }
  1002. let orderInvoiceList = [] // invoiceDataFrom
  1003. shopCartOrders.forEach((item) => {
  1004. if (item.invoiceDataFrom && item.invoiceDataFrom.invoiceType === 1) {
  1005. orderInvoiceList.push(item.invoiceDataFrom)
  1006. }
  1007. })
  1008. if (orderInvoiceList.length === 0) {
  1009. orderInvoiceList = null
  1010. }
  1011. if (this.mold !== 1 && !this.addressList.length) {
  1012. if (Cookie.get('token')) {
  1013. this.$message({
  1014. message: this.$t('submitOrder.pleaseAddTheAddressFirst'),
  1015. type: 'warning',
  1016. duration: 1000
  1017. })
  1018. this.showAddrPop = true
  1019. } else {
  1020. bus.$emit("showLogin", true)
  1021. this.showAddrPop = false
  1022. }
  1023. return
  1024. }
  1025. // if (!this.canSubmitOrder) {
  1026. // this.$message.warning(this.$store.state.errMsg)
  1027. // return
  1028. // }
  1029. if (this.mold !== 1 && this.selectedAddrId == 0) {
  1030. this.$message({
  1031. message: this.$t('submitOrder.pleaseSelectTheAddressFirst'),
  1032. type: 'warning',
  1033. duration: 1000
  1034. })
  1035. document.body.scrollTop = document.documentElement.scrollTop = 0
  1036. return
  1037. }
  1038. if (this.checked && !this.userUseScore) {
  1039. this.$message({
  1040. message: this.$t('submitOrder.pleaseEnterTheNumberOfPoints'),
  1041. type: 'warning',
  1042. duration: 1000
  1043. })
  1044. return
  1045. }
  1046. // 全部留言必填项空校验(虚拟商品)
  1047. // if (
  1048. // this.mold === 1 &&
  1049. // this.virtualRemarkList.length &&
  1050. // this.virtualRemarkList.find(el => el.isRequired && !el.value)
  1051. // ) {
  1052. // this.$message({
  1053. // message: this.$t('submitOrder.messageCannotBeEmpty'),
  1054. // type: 'warning',
  1055. // duration: 1000
  1056. // })
  1057. // return
  1058. // }
  1059. if (this.allVirtualMsg.length && this.allVirtualMsg.find(el => el.isRequired && !el.value)) {
  1060. this.$message({
  1061. message: this.$t('submitOrder.messageCannotBeEmpty'),
  1062. type: 'warning',
  1063. duration: 2000
  1064. })
  1065. return
  1066. }
  1067. this.allVirtualMsg.forEach(el => {
  1068. el.id = undefined
  1069. })
  1070. this.$axios
  1071. .post('/p/order/submit', {
  1072. orderShopParam: orderShopParam,
  1073. uuid: this.uuid,
  1074. orderInvoiceList: orderInvoiceList,
  1075. virtualRemarkList: this.allVirtualMsg
  1076. })
  1077. .then(({ data }) => {
  1078. console.log(data)
  1079. if (data.duplicateError === 1) {
  1080. // this.canSubmitOrder = false
  1081. this.$store.commit('handleChangeErrMsg', this.$t('submitOrder.duplicateErrorTips'))
  1082. return this.$message.warning(this.$t('submitOrder.duplicateErrorTips'))
  1083. }
  1084. sessionStorage.setItem('pay_total', this.orderInfo.actualTotal)
  1085. sessionStorage.setItem('pay_orderNumber', data.orderNumbers)
  1086. sessionStorage.setItem('pay_mold', this.mold)
  1087. this.$router.push({
  1088. path: '/payment'
  1089. })
  1090. this.getCartCount()
  1091. })
  1092. .catch(() => {
  1093. // this.canSubmitOrder = false
  1094. })
  1095. },
  1096. /**
  1097. * 获取购物车商品总数
  1098. */
  1099. getCartCount () {
  1100. this.$axios.get('/p/shopCart/prodCount').then(({ data }) => {
  1101. this.$store.commit('cartNumber/changeCartNumber', data)
  1102. })
  1103. },
  1104. /**
  1105. * 生成uuid
  1106. */
  1107. genUUID () {
  1108. var s = []
  1109. var hexDigits = '0123456789abcdef'
  1110. for (var i = 0; i < 36; i++) {
  1111. s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1)
  1112. }
  1113. s[14] = '4' // bits 12-15 of the time_hi_and_version field to 0010
  1114. s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1) // bits 6-7 of the clock_seq_hi_and_reserved to 01
  1115. s[8] = s[13] = s[18] = s[23] = '-'
  1116. var uuid = s.join('')
  1117. return uuid
  1118. }
  1119. }
  1120. }
  1121. </script>
  1122. <style scoped src="~/assets/css/submit-order.css"></style>
  1123. <style scoped>
  1124. .fix-transform-blur {
  1125. z-index: 10000;
  1126. position: fixed;
  1127. top: 40%;
  1128. left: 50%;
  1129. transform: translate(-50%, -40%);
  1130. }
  1131. .submit-order .statistic-box .item .tit {
  1132. display: flex;
  1133. justify-content: flex-end;
  1134. }
  1135. .submit-order .statistic-box .item .tit .text {
  1136. margin-left: 5px;
  1137. }
  1138. </style>