order-submit.vue 62 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484
  1. <template>
  2. <app-layout>
  3. <view class="safe-area-inset-bottom">
  4. <!-- 地址、商户、配送、商品、优惠、费用信息 -->
  5. <view class="page" v-if="previewData">
  6. <view v-if="!previewData.hasCity && previewData.show_address !== false && previewData.hasRecipient" class="group">
  7. <app-address-bar :address="previewData.address" :has-ziti="previewData.has_ziti" :all-ziti="previewData.allZiti" @address-input="handleAddressInput"></app-address-bar>
  8. </view>
  9. <template v-for="(mch, mchIndex) in previewData.mch_list" >
  10. <view v-if="previewData.hasCity && mchIndex === 0" class="group">
  11. <app-address-bar :address="mch.city.error ? null : mch.address" :has-city="true" :city="mch.city"></app-address-bar>
  12. </view>
  13. <view v-if="previewData.hasCity && mchIndex === 1" class="group">
  14. <app-address-bar :address="previewData.address" :has-ziti="previewData.has_ziti" :all-ziti="previewData.allZiti" :city="mch.city"></app-address-bar>
  15. </view>
  16. <!-- 循环商户列表start -->
  17. <view :key="mchIndex" class="group">
  18. <!-- 商铺名 -->
  19. <view style="padding: 26rpx 32rpx;">
  20. <view class="dir-left-nowrap cross-center" style="padding: 10rpx 0;line-height: 1.2;">
  21. <!-- 商户名start -->
  22. <view class="box-grow-0">
  23. <image src="/static/image/icon/store-black.png" class="title-icon mr-12"></image>
  24. </view>
  25. <view class="box-grow-1 font-bold ellipsis-1">{{mch.mch.name}}</view>
  26. <view v-if="mch.mch.id > 0 && mch.delivery && mch.delivery.send_type === 'offline' && mch.store && mch.store.distance != '-m'" class="box-grow-0 dir-left-nowrap cross-center">
  27. <image src="/static/image/icon/location.png" class="mr-12" style="display: block; width: 22rpx;height: 26rpx;"></image>
  28. <view>距您{{mch.store.distance}}</view>
  29. </view>
  30. </view><!-- 商户名end -->
  31. <template v-if="mch.delivery && mch.delivery.send_type === 'offline'">
  32. <!-- 自提门店信息start -->
  33. <view v-if="mch.no_store && mch.no_store === true" :class="[themeTextClass]" :style="{'color': !is_gift ? theme.color : '', 'paddding': '10rpx 0'}">暂无门店,请选择其他配送方式
  34. </view>
  35. <template v-else>
  36. <template v-if="mch.store">
  37. <view v-if="mch.mch.id == 0" class="dir-left-nowrap" style="padding: 10rpx 0;line-height: 1.2;">
  38. <view @click="navigateStore(mchIndex)" class="box-grow-1 dir-left-nowrap cross-center">
  39. <view>
  40. <image src="/static/image/icon/navigation-black.png" class="title-icon mr-12"></image>
  41. </view>
  42. <view class="font-bold ellipsis-1 mr-12">
  43. {{mch.store.name}}
  44. </view>
  45. <view class="mr-12">
  46. <image src="/static/image/icon/right.png" class="mr-12" style="width: 12rpx; height: 22rpx;"></image>
  47. </view>
  48. </view>
  49. <view v-if="mch.store.distance != '-m' || getLocationFail" class="box-grow-0 dir-left-nowrap cross-center">
  50. <view>
  51. <image src="/static/image/icon/location.png" class="mr-12" style="display: block; width: 22rpx;height: 26rpx;"></image>
  52. </view>
  53. <view v-if="getLocationFail" @click.stop="openLocationSetting" :class="[`${theme}-color`, `${theme}-border`]" :style="{'color': !is_gift ? theme.color : '', 'border-color': !is_gift ? theme.border : ''}">获取位置
  54. </view>
  55. <view v-else-if="mch.store.distance != '-m'">距您{{mch.store.distance}}</view>
  56. </view>
  57. </view>
  58. <view style="padding: 10rpx 0;line-height: 1.2;">
  59. <view class="font-gray ellipsis-2" style="line-height: 30rpx; max-height: 60rpx;">
  60. {{mch.store.address}}
  61. </view>
  62. </view>
  63. </template>
  64. <view v-else class="dir-left-nowrap cross-center" @click="navigateStore(mchIndex)" style="padding: 10rpx 0;">
  65. <view class="box-grow-1 dir-left-nowrap">
  66. <image src="/static/image/icon/navigation-black.png" class="title-icon mr-12"></image>
  67. <view class="mr-12 font-bold">选择门店</view>
  68. </view>
  69. <view class="box-grow-0 dir-left-nowrap cross-center">
  70. <view class="mr-12 font-gray">请选择门店</view>
  71. <image src="/static/image/icon/arrow-right.png" class="mr-12" style="width: 12rpx; height: 22rpx;"></image>
  72. </view>
  73. </view>
  74. </template>
  75. </template><!-- 自提门店信息end -->
  76. </view>
  77. <view class="line"></view>
  78. <!-- 配送方式 -->
  79. <view v-if="mch.show_delivery !== false" style="padding: 18rpx 32rpx;">
  80. <!-- 选择配送方式start -->
  81. <view class="dir-left-nowrap cross-center" style="padding: 18rpx 0;">
  82. <view class="box-grow-0">
  83. <image src="/static/image/icon/delivery.png" class="title-icon mr-12"></image>
  84. </view>
  85. <view class="box-grow-1 font-bold">配送方式</view>
  86. </view>
  87. <view class="dir-left-nowrap" style="padding: 18rpx 0;">
  88. <view v-for="(sendType, sendTypeIndex) in mch.delivery.send_type_list" :key="sendTypeIndex" class="send-type"
  89. :style="{'background-color': sendType.value == mch.delivery.send_type && !userTheme ? theme.background : ''}"
  90. :class="sendType.value == mch.delivery.send_type && userTheme ? `${theme}-background theme-color`: sendType.value == mch.delivery.send_type && !userTheme ? 'theme-color' : 'app-light-gray-back' "
  91. @click="changeSendType(mchIndex,sendType.value)">
  92. {{sendType.name}}
  93. </view>
  94. </view>
  95. </view><!-- 选择配送方式end -->
  96. <!-- 同城配送 -->
  97. <template v-if="mch.delivery && mch.delivery.send_type === 'city' && mch.city">
  98. <!-- 同城配送信息start -->
  99. <view class="line"></view>
  100. <view v-if="mch.city.error" class="dir-left-nowrap cross-center" style="padding: 36rpx 32rpx;">
  101. <view class="box-grow-1">{{mch.city.error}}</view>
  102. <view class="box-grow-0 dir-left-nowrap delivery-coverage-btn" @click="jump(mchIndex)" style="margin: -12rpx 0;">查看配送范围
  103. </view>
  104. </view>
  105. <view v-else style="padding: 36rpx 32rpx;">
  106. <view style="padding: 10rpx 0;">发货地址:{{mch.city.address}}</view>
  107. <view class="dir-left-nowrap cross-center" style="padding: 10rpx 0;">
  108. <view class="box-grow-1">
  109. <view v-if="mch.city.explain">{{mch.city.explain}}</view>
  110. </view>
  111. <view class="box-grow-0 dir-left-nowrap delivery-coverage-btn" @click="jump(mchIndex)">查看配送范围
  112. </view>
  113. </view>
  114. </view>
  115. </template><!-- 同城配送信息end -->
  116. <view class="line"></view>
  117. <view v-if="!mch.pick_up_enable" style="height: 80rpx;line-height: 80rpx; background: #fff4f3;padding: 0 24rpx;">
  118. <view>以下商品满{{mch.pick_up_price}}元起送</view>
  119. </view>
  120. <!-- 商品循环 -->
  121. <app-submit-goods :theme="theme" v-on:updateList="updateList" :index="mchIndex" :plugin="plugin" :list="mch"></app-submit-goods>
  122. <view class="line"></view>
  123. <!-- 优惠券 -->
  124. <template v-if="(mch.coupon && mch.coupon.enabled) ||
  125. (mch.member_discount > 0 || mch.member_discount < 0) ||
  126. (mch.integral && mch.integral.can_use) ||
  127. mch.temp_vip_discount ||
  128. (mch.insert_rows && mch.insert_rows.length) ||
  129. (mch.full_reduce_discount > 0 || mch.full_reduce_discount < 0)">
  130. <view style="padding: 20rpx 32rpx;">
  131. <template v-if="mch.coupon && mch.coupon.enabled">
  132. <view @click="showCouponPicker(mchIndex)" style="padding: 16rpx 0;">
  133. <view class="dir-left-nowrap cross-center">
  134. <view class="box-grow-1">优惠券</view>
  135. <view class="box-grow-0 mr-12" v-if="mch.coupon.use" :class="[themeTextClass]" :style="{'color': !is_gift ? theme.color : ''}">
  136. -¥{{mch.coupon.coupon_discount}}
  137. </view>
  138. <view class="box-grow-0 mr-12 font-gray" v-else-if="noCouponStatus(mchIndex)">
  139. 暂无优惠券可用
  140. </view>
  141. <view class="box-grow-0 mr-12 font-gray" v-else>选择优惠券</view>
  142. <view class="box-grow-0">
  143. <image src="/static/image/icon/arrow-right.png" style="width: 12rpx; height: 22rpx; margin-bottom: -2rpx;"></image>
  144. </view>
  145. </view>
  146. </view>
  147. <app-bottom-modal :visible.sync="mch.showCouponPicker" title="优惠券">
  148. <app-coupon-pick :plugin="plugin" :mch-index="mchIndex" @change="loadPreviewData" :no-coupons.sync="mch.noCoupons" :theme="theme"></app-coupon-pick>
  149. </app-bottom-modal>
  150. </template>
  151. <view v-if="mch.member_discount > 0 || mch.member_discount < 0" class="dir-left-nowrap" style="padding: 16rpx 0;">
  152. <view class="box-grow-1">会员价总优惠</view>
  153. <view class="box-grow-0" :class="[themeTextClass]" :style="{'color': !is_gift ? theme.color : ''}">
  154. <template v-if="mch.member_discount>0">-¥{{mch.member_discount}}</template>
  155. <template v-else-if="mch.member_discount<0">+¥{{0-mch.member_discount}}</template>
  156. <template v-else>¥0.00</template>
  157. </view>
  158. </view>
  159. <view v-if="mch.full_reduce_discount > 0 || mch.full_reduce_discount < 0" class="dir-left-nowrap" style="padding: 16rpx 0;">
  160. <view class="box-grow-1">满减总优惠</view>
  161. <view class="box-grow-0" :class="[themeTextClass]" :style="{'color': !is_gift ? theme.color : ''}">
  162. <template v-if="mch.full_reduce_discount>0">-¥{{mch.full_reduce_discount}}</template>
  163. <template v-else-if="mch.full_reduce_discount<0">+¥{{0-mch.full_reduce_discount}}</template>
  164. </view>
  165. </view>
  166. <view v-if="mch.integral && mch.integral.can_use" class="dir-left-nowrap" style="padding: 16rpx 0;">
  167. <view class="box-grow-1 dir-left-nowrap cross-center">
  168. 积分抵扣(使用 {{mch.integral.use_num}}积分)
  169. <image @click="showIntegralTip" style="width: 36rpx;height: 36rpx; margin: -12rpx 0;" src="/static/image/icon/warning.png"></image>
  170. </view>
  171. <view class="box-grow-0 dir-left-nowrap cross-center">
  172. <view class="mr-12" :class="[themeTextClass]" :style="{'color': !is_gift ? theme.color : ''}">
  173. -¥{{mch.integral.deduction_price}}
  174. </view>
  175. <view style="margin: -6rpx 0">
  176. <app-submit-checkbox :round="true" :theme="theme" :value="mch.integral.use" border-color="#999999" @input="changeIntegral(mchIndex)"></app-submit-checkbox>
  177. </view>
  178. </view>
  179. </view>
  180. <view v-if="mch.temp_vip_discount" style="padding: 16rpx 0;">
  181. <view :style="{
  182. backgroundImage: `url(${appImg.order_submit.svip_bg})`,
  183. }" class="svip dir-left-nowrap cross-center">
  184. <view class="box-grow-1">
  185. <view v-if="mch.vip_card_detail">SVIP用户,本单优惠
  186. <text style="color: #ff4544;">{{mch.temp_vip_discount}}</text>
  187. </view>
  188. <template v-else>
  189. <view style="margin-bottom: 10rpx;">现在开卡,本单立减
  190. <text style="color: #ff4544;">{{mch.temp_vip_discount}}
  191. </text>
  192. </view>
  193. <view @click="navigateVipCardPrivilege" class="dir-left-nowrap cross-center">
  194. <view style="margin-right: 10rpx; font-size: 22rpx;">查看权益</view>
  195. <image src="/static/image/icon/order-submit/arrow-right-b.png" style="width: 12rpx;height: 22rpx; display: block;"></image>
  196. </view>
  197. </template>
  198. </view>
  199. <view class="box-grow-0 dir-left-nowrap cross-center" style="padding: 12rpx 22rpx 12rpx 0;" @click="navigateSvip(mchIndex)">
  200. <view class="vip-card-name" style="margin-right: 10rpx; line-height: 1.05;">
  201. <template v-if="mch.vip_card_detail">{{mch.vip_card_detail.name}}</template>
  202. <template v-else>请选择</template>
  203. </view>
  204. <image src="/static/image/icon/order-submit/arrow-right-a.png" style="width: 12rpx;height: 22rpx; display: block;"></image>
  205. </view>
  206. </view>
  207. </view>
  208. <view v-if="mch.insert_rows && mch.insert_rows.length" :class="[mch.showInsertRows?'show':'',]">
  209. <view class="dir-left-nowrap cross-center" @click="reversalShowInsertRows(mchIndex)" style="padding: 16rpx 0;">
  210. <view class="box-grow-1 dir-left-nowrap cross-center">
  211. <view class="mr-12">活动优惠</view>
  212. <image style="width: 22rpx; height: 12rpx;" class="bottom-icon" src="/static/image/icon/bottom.png"></image>
  213. </view>
  214. <view class="box-grow-0" :class="[themeTextClass]" :style="{'color': !is_gift ? theme.color : ''}">
  215. {{mch.insert_total_discount}}
  216. </view>
  217. </view>
  218. <view class="insert-rows">
  219. <view class="font-small more-discount-info">
  220. <view v-for="(insertRow, insertRowIndex) in mch.insert_rows" :key="insertRowIndex" class="row dir-left-nowrap no-px">
  221. <view class="box-grow-1" style="color: #999;">{{insertRow.title}}</view>
  222. <view class="box-grow-0" :class="[themeTextClass]" :style="{'color': !is_gift ? theme.color : ''}">
  223. {{insertRow.value}}
  224. </view>
  225. </view>
  226. </view>
  227. </view>
  228. </view>
  229. </view>
  230. <view class="line"></view>
  231. </template>
  232. <!-- 运费 -->
  233. <template v-if="mch.show_express_price !== false">
  234. <!-- 运费信息start -->
  235. <view class="dir-left-nowrap cross-center" style="height: 84rpx; padding: 0 32rpx;">
  236. <view class="box-grow-1">运费</view>
  237. <view class="box-grow-0" :class="[themeTextClass]" :style="{'color': !is_gift ? theme.color : '','text-align':'right'}">
  238. <template v-if="mch.express_price_origin && mch.express_price_desc">
  239. <view :style="{'color': theme.color}">¥{{mch.express_price_origin}}</view>
  240. <view class="express-price-desc" :style="{'color': theme.color}">{{mch.express_price_desc}}
  241. </view>
  242. </template>
  243. <template v-else>¥{{mch.express_price}}</template>
  244. </view>
  245. </view>
  246. </template><!-- 运费信息end -->
  247. <template v-if="mch.total_sku_tax_amount >0">
  248. <!-- 综合税费start -->
  249. <view class="dir-left-nowrap cross-center" style="height: 84rpx; padding: 0 32rpx;">
  250. <view class="box-grow-1">综合税费</view>
  251. <view class="box-grow-0" :class="[themeTextClass]" :style="{'color': !is_gift ? theme.color : '','text-align':'right'}">
  252. <template>¥{{mch.total_sku_tax_amount}}</template>
  253. </view>
  254. </view>
  255. </template><!-- 综合税费end -->
  256. <!-- 买家留言 -->
  257. <template v-if="
  258. !(mch.order_form && mch.order_form.status == '1')
  259. && mch.show_remark !== false
  260. && mch.has_goods_form !== true">
  261. <view class="line"></view>
  262. <view class="row" style="padding-top: 0;padding-bottom: 0;">
  263. <app-input @input="inputRemark(mchIndex)" v-model="mch.remark" placeholder="买家留言" padding-left="0" height="100"></app-input>
  264. </view>
  265. </template>
  266. <view class="line"></view>
  267. <!-- 小计 -->
  268. <view class="dir-right-nowrap cross-center" style="height: 84rpx; padding: 0 32rpx;">
  269. <view class="box-grow-0 dir-left-nowrap">
  270. <view>小计:</view>
  271. <view :class="[themeTextClass]" :style="{'color': !is_gift ? theme.color : ''}">¥{{mch.total_price}}</view>
  272. </view>
  273. <view class="box-grow-0 font-gray mr-12">共{{mch.goods_count}}件</view>
  274. </view>
  275. </view>
  276. <!-- 循环商户列表end -->
  277. </template>
  278. <view v-for="(mch, mchIndex) in previewData.mch_list" :key="mchIndex">
  279. <view v-if="mch.order_form && mch.order_form.status == '1'" class="group">
  280. <view style="padding: 0 12rpx">
  281. <app-diy-form :title="mch.order_form.name" :list="mch.order_form.value" @input="handleOrderFormInput" @validate="handleOrderFormValidate" :sign="mchIndex" label-position="top" :show-scroll-btn="mch.order_form.show_scroll"></app-diy-form>
  282. </view>
  283. </view>
  284. <template v-if="mch.has_goods_form">
  285. <view v-for="(goodsItem, goodsIndex) in mch.goods_list" :key="goodsIndex" v-if="goodsItem.form && !goodsItem.form.same_form" class="group goods-form">
  286. <view style="padding: 36rpx 32rpx;" class="font-bold">{{goodsItem.form.name}}</view>
  287. <view class="line"></view>
  288. <view class="row goods-list" v-if="mch.diff_goods_form_count !== 1 || previewData.mch_list.length > 1">
  289. <view v-for="(subGoodsItem, subGoodsIndex) in mch.goods_list" :key="subGoodsIndex" v-if="subGoodsItem.form && subGoodsItem.form.id == goodsItem.form.id" class="dir-left-nowrap goods-item">
  290. <view class="box-grow-0">
  291. <image class="goods-image" :src="subGoodsItem.goods_attr.pic_url ? subGoodsItem.goods_attr.pic_url : subGoodsItem.cover_pic"></image>
  292. </view>
  293. <view class="box-grow-1">
  294. <view class="goods-name ellipsis-2">
  295. {{subGoodsItem.name}}
  296. </view>
  297. <view class="dir-left-wrap">
  298. <view v-for="(attrItem,attrIndex) in subGoodsItem.attr_list" :key="attrIndex" class="mr-12 font-gray font-small">
  299. {{attrItem.attr_group_name}}:{{attrItem.attr_name}}
  300. </view>
  301. </view>
  302. <view class="dir-left-nowrap">
  303. <view class="box-grow-1 font-gray font-small">×{{subGoodsItem.num}}</view>
  304. <view class="box-grow-0">
  305. <view class="font-small" style="text-align: right" :style="{'color': theme.color}">
  306. <text v-for="(customCurrency,customCurrencyIndex) in subGoodsItem.custom_currency" :key="customCurrencyIndex">
  307. {{customCurrency}}+
  308. </text>
  309. ¥{{subGoodsItem.total_original_price}}
  310. </view>
  311. <view v-for="(discount,discountIndex) in subGoodsItem.discounts" :key="discountIndex" style="text-align: right" :style="{'color': theme.color}">
  312. {{discount.name}}: {{discount.value}}
  313. </view>
  314. </view>
  315. </view>
  316. </view>
  317. </view>
  318. </view>
  319. <view style="padding: 0 12rpx">
  320. <app-diy-form :showRequiredIcon="true" :list="goodsItem.form.value" @input="handleGoodsFormInput" @validate="handleGoodsFormValidate" label-position="top" :label-fs28="true" :sign="`${mchIndex},${goodsIndex},${goodsItem.form.id}`"></app-diy-form>
  321. </view>
  322. </view>
  323. </template>
  324. </view>
  325. </view>
  326. <view class="full-tip" v-if="previewData.next_full_reduce"></view>
  327. </view>
  328. <!-- 结算底栏 -->
  329. <view class="submit-bar u-bottom-fixed dir-top-nowrap safe-area-inset-bottom" v-if="previewData">
  330. <view class="full-tip full-tip-show" v-if="previewData.next_full_reduce">
  331. 还差<span class="full-tip-text">{{previewData.next_full_reduce.diff}}</span>元<span class="full-tip-text">{{previewData.next_full_reduce.text}}</span>
  332. </view>
  333. <view class="bd-bottom dir-left-nowrap">
  334. <view class="box-grow-1 cross-center u-submit-bar-height">
  335. <view class="price-info">
  336. <view :class="[themeTextClass]" :style="{'color': !is_gift ? theme.color : '','font-size': '26rpx'}">
  337. {{totalTitle}}:
  338. <text v-for="(custom_currency, ccIndex) in previewData.custom_currency_all" :key="ccIndex">
  339. {{custom_currency}}+
  340. </text>
  341. <template v-if="previewData.vip_card_discount_total_price">
  342. ¥{{previewData.vip_card_discount_total_price}}
  343. </template>
  344. <template v-else>¥{{previewData.total_price}}</template>
  345. </view>
  346. <view v-if="previewData.vip_card_price > 0" :class="[themeTextClass]" :style="{'color': !is_gift ? theme.color : '','font-size': '20rpx'}">包含SVIP费用:
  347. ¥{{previewData.vip_card_price}}
  348. </view>
  349. </view>
  350. </view>
  351. <template v-if="previewData.address_enable && previewData.price_enable">
  352. <view @click="subscribe" class="submit-btn u-submit-bar-height box-grow-0 main-center cross-center" :class="[ submitLock? ' lock' : '', themeBgClass]" :style="{'background-color': !is_gift ? theme.background : ''}">
  353. <view style="background-color: transparent;color:#ffffff; text-align: center;">提交订单</view>
  354. </view>
  355. </template>
  356. <template v-else>
  357. <view class="submit-btn u-submit-bar-height box-grow-0 main-center cross-center disabled" :class="[themeTextClass]" :style="{'color': !is_gift ? theme.color : ''}">
  358. <view style="background-color: transparent;color: #ffffff; text-align: center;">提交订单</view>
  359. </view>
  360. </template>
  361. </view>
  362. </view>
  363. <app-close v-if="showClose && mchList.length > 0" :toBack="true" :mch_list="mchList" @update="getMall"></app-close>
  364. </app-layout>
  365. </template>
  366. <script>
  367. import {mapGetters, mapState} from 'vuex';
  368. import AppDiyForm from "../../components/page-component/app-diy-form/app-diy-form.vue";
  369. import appSubmitGoods from './app-submit-goods.vue';
  370. import AppCouponPick from "./app-coupon-pick";
  371. import AppBottomModal from "./app-bottom-modal";
  372. import AppAddressBar from "./app-address-bar";
  373. import AppSubmitCheckbox from "./app-submit-checkbox";
  374. import AppClose from '../../components/basic-component/app-close/app-close.vue';
  375. import deepClone from '@/core/deepClone.js'
  376. export default {
  377. name: 'order-submit',
  378. components: {
  379. AppSubmitCheckbox,
  380. AppAddressBar,
  381. AppBottomModal,
  382. AppCouponPick,
  383. AppDiyForm,
  384. appSubmitGoods,
  385. AppClose
  386. },
  387. data() {
  388. return {
  389. totalTitle: '合计',
  390. check: false,
  391. previewData: {
  392. mch_list: [],
  393. total_price: 0,
  394. vip_card_discount_total_price: null,
  395. custom_currency_all: []
  396. },
  397. getLocationFail: false,
  398. previewUrl: null,
  399. submitUrl: null,
  400. plugin: null,
  401. orderPageUrl: null,
  402. submitLock: false,
  403. getPayDataTimer: null,
  404. userTheme: null,
  405. is_gift: false,
  406. payDataUrl: null,
  407. showPayResult: true,
  408. payCancelUrl: null,
  409. loadingPreviewData: true,
  410. showClose: false,
  411. is_open: false,
  412. mchList: '',
  413. p_pay_id: '',//重新提交处理
  414. };
  415. },
  416. computed: {
  417. ...mapState({
  418. appImg: state => state.mallConfig.__wxapp_img,
  419. }),
  420. theme() {
  421. return this.userTheme ? this.userTheme : this.getTheme;
  422. },
  423. ...mapGetters('mallConfig', {
  424. getTheme: 'getTheme',
  425. }),
  426. themeBgClass() {
  427. if (this.userTheme && this.userTheme.indexOf('gift') >= 0) {
  428. return `${this.theme} ${this.theme}-background`;
  429. }
  430. },
  431. themeTextClass() {
  432. if (this.userTheme && this.userTheme.indexOf('gift') >= 0) {
  433. return `${this.theme} ${this.theme}-color`;
  434. }
  435. },
  436. },
  437. onLoad(options) {
  438. this.$commonLoad.onload(options);
  439. let mchList = JSON.parse(options.mch_list);
  440. let list = [];
  441. for(let item of mchList) {
  442. if(item.mch_id > 0) {
  443. list.push(item.mch_id)
  444. }
  445. }
  446. this.is_gift = this.userTheme && this.userTheme.indexOf('gift') >= 0 ? true : false;
  447. this.mchList = list.length > 0 ? JSON.stringify(list) : '0';
  448. if (this.submitLock) return;
  449. this.setFormData(options);
  450. this.$event.on(this.$const.EVENT_USER_LOGIN).then(() => {
  451. this.loadPreviewData();
  452. });
  453. // #ifdef H5
  454. let { hash } = window.location;
  455. if (hash.indexOf('pay_id_weChart') > 0 && hash.indexOf('isWechat=true') > 0) {
  456. let _this = this;
  457. uni.showModal({
  458. content: '确定已完成支付?',
  459. confirmText: '确定',
  460. cancelText: '返回支付',
  461. success(res) {
  462. if (res.confirm) {
  463. let search = hash.split('?')[1];
  464. if (search) {
  465. let str = search.substr(0).match(new RegExp('(^|&)' + 'pay_id_weChart' + '=([^&]*)(&|$)'))
  466. if (unescape(str[2])) {
  467. _this.weChartPay(unescape(str[2]));
  468. }
  469. }
  470. } else if (res.cancel) {
  471. uni.redirectTo({
  472. url: `/pages/order/index/index`
  473. });
  474. }
  475. },
  476. fail() {
  477. }
  478. });
  479. }
  480. // #endif
  481. },
  482. onShow() {
  483. this.showClose = false;
  484. setTimeout(()=>{
  485. this.showClose = true;
  486. // #ifdef H5
  487. document.getElementsByClassName('uni-page-head__title')[0].innerHTML = '确认订单';
  488. // #endif
  489. });
  490. },
  491. onUnload() {
  492. if (this.getPayDataTimer) {
  493. clearTimeout(this.getPayDataTimer);
  494. }
  495. },
  496. watch: {
  497. 'previewData.address.name': {
  498. handler() {
  499. this.changeZitiAddress();
  500. },
  501. },
  502. 'previewData.address.mobile': {
  503. handler() {
  504. this.changeZitiAddress();
  505. },
  506. },
  507. },
  508. methods: {
  509. getMall(e) {
  510. console.log(e)
  511. if(e != undefined) {
  512. this.is_open = e && e.is_open == 1 ? true : false;
  513. if(this.is_open) {
  514. if (this.submitLock) return;
  515. // #ifdef MP-BAIDU
  516. setTimeout(() => {
  517. this.loadPreviewData();
  518. }, 50);
  519. // #endif
  520. // #ifndef MP-BAIDU
  521. this.loadPreviewData();
  522. // #endif
  523. }
  524. }
  525. },
  526. noCouponStatus(mchIndex) {
  527. const mchNoCouponStatusList = this.$store.getters['orderSubmit/getMchNoCouponStatusList'];
  528. if (mchNoCouponStatusList[mchIndex])
  529. return true;
  530. else
  531. return false;
  532. },
  533. navigateVipCardPrivilege() {
  534. uni.navigateTo({
  535. url: '/plugins/vip_card/rights/rights?id=1',
  536. });
  537. },
  538. showCouponPicker(index) {
  539. this.previewData.mch_list[index].showCouponPicker = true;
  540. },
  541. reversalShowInsertRows(index) {
  542. this.previewData.mch_list[index].showInsertRows = !this.previewData.mch_list[index].showInsertRows;
  543. },
  544. updateList(e, index) {
  545. this.previewData.mch_list[index] = e;
  546. this.$forceUpdate();
  547. },
  548. setParams(options) {
  549. if (options.total_title) {
  550. this.totalTitle = options.total_title;
  551. }
  552. },
  553. handleOrderFormInput({data, sign}) {
  554. const result = [];
  555. for (let i in data) {
  556. result[i] = {
  557. key: data[i].key,
  558. label: data[i].name,
  559. value: data[i].value,
  560. required: data[i].is_required,
  561. };
  562. }
  563. const formData = this.$store.state.orderSubmit.formData;
  564. formData.list[sign].order_form = result;
  565. this.$store.commit('orderSubmit/mutSetFormData', formData);
  566. },
  567. handleOrderFormValidate({result, sign}) {
  568. const formData = this.$store.state.orderSubmit.formData;
  569. formData.list[sign].order_form_validate_result = result;
  570. this.$store.commit('orderSubmit/mutSetFormData', formData);
  571. },
  572. setFormData(options) {
  573. console.log(options.preview_url)
  574. this.previewUrl = decodeURIComponent(options.preview_url || this.$api.order.preview);
  575. this.submitUrl = decodeURIComponent(options.submit_url || this.$api.order.submit);
  576. this.plugin = options.plugin || null;
  577. this.orderPageUrl = decodeURIComponent(options.order_page_url || '/pages/order/index/index?status=0');
  578. this.userTheme = options.theme || null;
  579. this.payDataUrl = decodeURIComponent(options.pay_data_url || this.$api.order.pay_data);
  580. this.payCancelUrl = options.pay_cancel_url ? decodeURIComponent(options.pay_cancel_url) : null;
  581. this.showPayResult = options.show_pay_result || true;
  582. if (this.showPayResult === 'true') this.showPayResult = true;
  583. if (this.showPayResult === 'false') this.showPayResult = false;
  584. let list = JSON.parse(options.mch_list);
  585. // console.log('================123===============')
  586. // console.log(list)
  587. // let tempGoods = []
  588. // for (let i = 0; i < list.length; i ++) {
  589. // const goods_list = list[i].goods_list
  590. // if (i === 0) {
  591. // goods_list.forEach(item => { item['is_jingwai'] = 0 })
  592. // } else if (i === 1) {
  593. // goods_list.forEach(item => { item['is_jingwai'] = 1 })
  594. // }
  595. // tempGoods = [...tempGoods, ...goods_list]
  596. // }
  597. // const tempList = [list[0]]
  598. // tempList[0].mch_id = 0
  599. // tempList[0].goods_list = tempGoods
  600. // list = deepClone(tempList)
  601. // 商户列表先做下排序,主商城必须在最前
  602. for (let i in list) {
  603. if (parseInt(list[i].mch_id) === 0) {
  604. const _mchItem = list[i];
  605. list.splice(i, 1);
  606. list.unshift(_mchItem);
  607. break;
  608. }
  609. }
  610. for (let i in list) {
  611. list[i].distance = 0;
  612. list[i].remark = '';
  613. list[i].order_form = [];
  614. list[i].use_integral = 0;
  615. list[i].user_coupon_id = 0;
  616. for (let j in list[i].goods_list) {
  617. list[i].goods_list[j].cart_id = list[i].goods_list[j].cart_id || 0;
  618. }
  619. if (this.plugin === 'booking') {
  620. let store_id = this.bookStorage('get');
  621. list[i]['store_id'] = store_id ? store_id : '';
  622. }
  623. }
  624. this.$store.commit('orderSubmit/mutSetFormData', {
  625. list: list,
  626. address_id: 0,
  627. send_type: options.send_type || ''
  628. });
  629. },
  630. bookStorage(type, store_id = '') {
  631. let key = '_book_storage_order_preview';
  632. if (type === 'get') {
  633. return this.$storage.getStorageSync(key);
  634. }
  635. if (type === 'save') {
  636. this.$storage.setStorageSync(key, store_id ? store_id : 0);
  637. }
  638. },
  639. loadPreviewData() {
  640. this.loadingPreviewData = true;
  641. uni.showLoading({
  642. mask: true,
  643. title: '加载中',
  644. });
  645. this.$request({
  646. url: this.previewUrl,
  647. method: 'post',
  648. data: {
  649. form_data: JSON.stringify(this.$store.state.orderSubmit.formData),
  650. },
  651. }).then(response => {
  652. this.loadingPreviewData = false;
  653. uni.hideLoading();
  654. if (response.code === 0) {
  655. if (response.data.allZiti && !response.data.address) {
  656. response.data.address = {
  657. name: '',
  658. mobile: '',
  659. };
  660. }
  661. for (let i in response.data.mch_list) {
  662. response.data.mch_list[i].showCouponPicker = false;
  663. response.data.mch_list[i].noCoupons = false;
  664. response.data.mch_list[i].showInsertRows = false;
  665. }
  666. this.previewData = response.data;
  667. // const arr = this.$store.state.orderSubmit.formData.list[0].goods_list
  668. // // 添加境内外信息
  669. // console.log(arr)
  670. // this.previewData.mch_list[0].goods_list.forEach(item => {
  671. // const t = arr.find(i => i.id === item.id)
  672. // item.is_jingwai = t.is_jingwai
  673. // })
  674. // console.log('====================================')
  675. // console.log(this.previewData.mch_list[0].goods_list)
  676. this.setDiyFormScrollStatus();
  677. this.checkCouponError();
  678. this.updateStoreDistance();
  679. this.updateGoodsCount();
  680. } else {
  681. uni.showModal({
  682. title: '提示',
  683. content: response.msg,
  684. showCancel: false,
  685. success: () => {
  686. uni.navigateBack();
  687. },
  688. });
  689. }
  690. }).catch(() => {
  691. this.loadingPreviewData = false;
  692. uni.hideLoading();
  693. });
  694. },
  695. navigateStore(mchIndex) {
  696. if (this.previewData.mch_list[mchIndex].mch.id != 0) {
  697. return;
  698. }
  699. let firstGoodsId = '';
  700. if (this.plugin === 'booking') {
  701. firstGoodsId = this.previewData.mch_list[0].goods_list[0].id;
  702. }
  703. let plugin = this.plugin || '';
  704. uni.navigateTo({
  705. url: `/pages/order-submit/store-pick?mchIndex=${mchIndex}&plugin=${plugin}&firstGoodsId=${firstGoodsId}`,
  706. });
  707. },
  708. navigateCoupon(mchIndex) {
  709. uni.navigateTo({
  710. url: `/pages/order-submit/coupon-pick?mchIndex=${mchIndex}`,
  711. });
  712. },
  713. navigateSvip(mchIndex) {
  714. uni.navigateTo({
  715. url: `/pages/order-submit/vip-card?mchIndex=${mchIndex}`,
  716. });
  717. },
  718. changeZitiAddress() {
  719. const formData = this.$store.state.orderSubmit.formData;
  720. formData.address = {
  721. name: this.previewData.address ? this.previewData.address.name : '',
  722. mobile: this.previewData.address ? this.previewData.address.mobile : '',
  723. };
  724. this.$store.commit('orderSubmit/mutSetFormData', formData);
  725. },
  726. changeSendType(mchIndex, value) {
  727. if (this.previewData.mch_list[mchIndex].delivery.send_type == value) return;
  728. const formData = this.$store.state.orderSubmit.formData;
  729. formData.list[mchIndex].send_type = value;
  730. this.$store.commit('orderSubmit/mutSetFormData', formData);
  731. this.previewData.mch_list[mchIndex].delivery.send_type = value;
  732. this.loadPreviewData();
  733. },
  734. updateStoreDistance() {
  735. if (!this.previewData) return;
  736. if (!this.previewData.has_ziti && this.plugin != 'booking') {
  737. return;
  738. }
  739. // #ifdef MP
  740. uni.getLocation({
  741. success: (res) => {
  742. for (let i in this.previewData.mch_list) {
  743. if (!this.previewData.mch_list[i].store) {
  744. continue;
  745. }
  746. if (this.previewData.mch_list[i].store.distance &&
  747. this.previewData.mch_list[i].store.distance != '-m') {
  748. continue;
  749. }
  750. if (
  751. this.previewData.mch_list[i].store.latitude == '' ||
  752. this.previewData.mch_list[i].store.longitude == '' ||
  753. isNaN(this.previewData.mch_list[i].store.latitude) ||
  754. isNaN(this.previewData.mch_list[i].store.longitude)
  755. ) {
  756. continue;
  757. }
  758. const distance = this.$utils.earthDistance({
  759. lat: res.latitude,
  760. lng: res.longitude
  761. }, {
  762. lat: this.previewData.mch_list[i].store.latitude,
  763. lng: this.previewData.mch_list[i].store.longitude
  764. });
  765. let distanceStr = '-m';
  766. if (distance > 1000) {
  767. distanceStr = (distance / 1000).toFixed(2) + 'km';
  768. } else {
  769. distanceStr = distance.toFixed(0) + 'm';
  770. }
  771. this.previewData.mch_list[i].store.distance = distanceStr;
  772. }
  773. },
  774. fail: () => {
  775. this.getLocationFail = true;
  776. },
  777. });
  778. // #endif
  779. // #ifdef H5
  780. if (this.$jwx.isWechat()) {
  781. this.$jwx.getLocation({
  782. success: (res) => {
  783. for (let i in this.previewData.mch_list) {
  784. if (!this.previewData.mch_list[i].store) {
  785. continue;
  786. }
  787. if (this.previewData.mch_list[i].store.distance &&
  788. this.previewData.mch_list[i].store.distance != '-m') {
  789. continue;
  790. }
  791. if (
  792. this.previewData.mch_list[i].store.latitude == '' ||
  793. this.previewData.mch_list[i].store.longitude == '' ||
  794. isNaN(this.previewData.mch_list[i].store.latitude) ||
  795. isNaN(this.previewData.mch_list[i].store.longitude)
  796. ) {
  797. continue;
  798. }
  799. const distance = this.$utils.earthDistance({
  800. lat: res.latitude,
  801. lng: res.longitude
  802. }, {
  803. lat: this.previewData.mch_list[i].store.latitude,
  804. lng: this.previewData.mch_list[i].store.longitude
  805. });
  806. let distanceStr = '-m';
  807. if (distance > 1000) {
  808. distanceStr = (distance / 1000).toFixed(2) + 'km';
  809. } else {
  810. distanceStr = distance.toFixed(0) + 'm';
  811. }
  812. this.previewData.mch_list[i].store.distance = distanceStr;
  813. }
  814. },
  815. fail: () => {
  816. this.getLocationFail = true;
  817. },
  818. });
  819. } else {
  820. uni.getLocation({
  821. success: (res) => {
  822. for (let i in this.previewData.mch_list) {
  823. if (!this.previewData.mch_list[i].store) {
  824. continue;
  825. }
  826. if (this.previewData.mch_list[i].store.distance &&
  827. this.previewData.mch_list[i].store.distance != '-m') {
  828. continue;
  829. }
  830. if (
  831. this.previewData.mch_list[i].store.latitude == '' ||
  832. this.previewData.mch_list[i].store.longitude == '' ||
  833. isNaN(this.previewData.mch_list[i].store.latitude) ||
  834. isNaN(this.previewData.mch_list[i].store.longitude)
  835. ) {
  836. continue;
  837. }
  838. const distance = this.$utils.earthDistance({
  839. lat: res.latitude,
  840. lng: res.longitude
  841. }, {
  842. lat: this.previewData.mch_list[i].store.latitude,
  843. lng: this.previewData.mch_list[i].store.longitude
  844. });
  845. let distanceStr = '-m';
  846. if (distance > 1000) {
  847. distanceStr = (distance / 1000).toFixed(2) + 'km';
  848. } else {
  849. distanceStr = distance.toFixed(0) + 'm';
  850. }
  851. this.previewData.mch_list[i].store.distance = distanceStr;
  852. }
  853. },
  854. fail: () => {
  855. this.getLocationFail = true;
  856. },
  857. });
  858. }
  859. // #endif
  860. },
  861. openLocationSetting() {
  862. this.getLocationFail = false;
  863. uni.openSetting({});
  864. },
  865. showIntegralTip() {
  866. uni.showModal({
  867. title: '积分抵扣说明',
  868. content: this.$store.state.mallConfig.mall.setting.member_integral_rule,
  869. showCancel: false,
  870. });
  871. },
  872. changeIntegral(mchIndex) {
  873. const formData = this.$store.state.orderSubmit.formData;
  874. const use = !this.previewData.mch_list[mchIndex].integral.use;
  875. formData.list[mchIndex].use_integral = use ? 1 : 0;
  876. this.previewData.mch_list[mchIndex].integral.use = use;
  877. this.loadPreviewData();
  878. },
  879. inputRemark(mchIndex) {
  880. const formData = this.$store.state.orderSubmit.formData;
  881. formData.list[mchIndex].remark = this.previewData.mch_list[mchIndex].remark;
  882. this.$store.commit('orderSubmit/mutSetFormData', formData);
  883. },
  884. submit() {
  885. uni.showLoading({
  886. mask: true,
  887. title: '提交中',
  888. });
  889. this.$request({
  890. url: this.submitUrl,
  891. method: 'post',
  892. data: {
  893. form_data: JSON.stringify(this.$store.state.orderSubmit.formData),
  894. },
  895. }).then(response => {
  896. if (response.code === 99) {
  897. // 未实名认证,需要使命认证
  898. uni.hideLoading()
  899. this.submitLock = false;
  900. const _this = this
  901. uni.showModal({
  902. title: '提示',
  903. content: '您的账号尚未实名认证,请前往认证',
  904. success: function (res) {
  905. if (res.confirm) {
  906. _this.$jump({
  907. open_type: 'navigate',
  908. url: '/pages/identify/identify'
  909. })
  910. }
  911. }
  912. })
  913. return
  914. }
  915. if (response.code === 0) {
  916. this.getPayOrderId(response.data.queue_id, response.data.token);
  917. } else {
  918. this.submitLock = false;
  919. uni.hideLoading();
  920. uni.showModal({
  921. title: '',
  922. content: response.msg,
  923. showCancel: false,
  924. });
  925. }
  926. }).catch(e => {
  927. this.submitLock = false;
  928. uni.hideLoading();
  929. uni.showModal({
  930. title: '提示',
  931. content: e.errMsg,
  932. showCancel: false,
  933. });
  934. });
  935. },
  936. getPayOrderId(queue_id, token) {
  937. this.$request({
  938. url: this.payDataUrl,
  939. method: 'post',
  940. data: {
  941. queue_id: queue_id,
  942. token: token,
  943. },
  944. }).then(response => {
  945. if (response.code === 0) {
  946. if (response.data.retry && response.data.retry === 1) {
  947. this.getPayDataTimer = setTimeout(() => {
  948. this.getPayOrderId(queue_id, token);
  949. }, 1000);
  950. } else {
  951. uni.hideLoading();
  952. this.pay(response.data);
  953. }
  954. } else {
  955. this.submitLock = false;
  956. uni.hideLoading();
  957. uni.showModal({
  958. title: '提示',
  959. content: response.msg,
  960. showCancel: false,
  961. });
  962. }
  963. }).catch(e => {
  964. this.submitLock = false;
  965. uni.hideLoading();
  966. uni.showModal({
  967. title: '提示',
  968. content: e.errMsg,
  969. showCancel: false,
  970. });
  971. });
  972. },
  973. pay(data) {
  974. this.p_pay_id = data.id;
  975. this.$payment.pay(data.id).then(res => {
  976. if (this.showPayResult) {
  977. uni.redirectTo({
  978. url: `/pages/order-submit/pay-result?payment_order_union_id=${data.id}&order_page_url=${encodeURIComponent(this.orderPageUrl)}`,
  979. });
  980. } else {
  981. let page_url = this.orderPageUrl;
  982. if (page_url.indexOf('?') === -1) {
  983. page_url += '?'
  984. } else {
  985. page_url += '&';
  986. }
  987. delete data.id;
  988. page_url += `pay_data=${JSON.stringify(data)}`;
  989. uni.redirectTo({
  990. url: page_url,
  991. });
  992. }
  993. }).catch(e => {
  994. if (this.payCancelUrl) {
  995. let page_url = this.payCancelUrl;
  996. if (page_url.indexOf('?') === -1) {
  997. page_url += '?'
  998. } else {
  999. page_url += '&';
  1000. }
  1001. page_url += `pay_data=${JSON.stringify(data)}`;
  1002. uni.redirectTo({
  1003. url: page_url,
  1004. });
  1005. } else {
  1006. if (e.errMsg === '5b03b6e009796c698d132908cb635fca') {
  1007. //重新发起支付
  1008. this.submitLock = false;
  1009. } else {
  1010. uni.showModal({
  1011. title: '提交失败',
  1012. content: e.errMsg,
  1013. showCancel: false,
  1014. success: () => {
  1015. uni.redirectTo({
  1016. url: this.orderPageUrl,
  1017. });
  1018. },
  1019. });
  1020. }
  1021. }
  1022. });
  1023. },
  1024. jump() {
  1025. uni.navigateTo({
  1026. url: `/pages/order-submit/map`,
  1027. });
  1028. },
  1029. checkCouponError() {
  1030. for (let i in this.previewData.mch_list) {
  1031. if (this.previewData.mch_list[i].coupon && this.previewData.mch_list[i].coupon.coupon_error) {
  1032. uni.showModal({
  1033. title: '',
  1034. content: this.previewData.mch_list[i].coupon.coupon_error,
  1035. showCancel: false,
  1036. });
  1037. return;
  1038. }
  1039. }
  1040. },
  1041. setDiyFormScrollStatus() {
  1042. for (let i in this.previewData.mch_list) {
  1043. let order_form = this.previewData.mch_list[i].order_form;
  1044. if (order_form) {
  1045. if (order_form.value && order_form.value.length && order_form.value.length >= 5) {
  1046. order_form.show_scroll = true;
  1047. } else {
  1048. order_form.show_scroll = false;
  1049. }
  1050. }
  1051. }
  1052. },
  1053. subscribe() {
  1054. if (this.p_pay_id) {
  1055. this.pay({
  1056. id: this.p_pay_id
  1057. });
  1058. return true;
  1059. } else {
  1060. this.p_pay_id = '';
  1061. }
  1062. for (let i in this.$store.state.orderSubmit.formData.list) {
  1063. const item = this.$store.state.orderSubmit.formData.list[i];
  1064. if (!item.order_form_validate_result) continue;
  1065. if (item.order_form_validate_result.hasError) {
  1066. uni.showModal({
  1067. title: '提示',
  1068. content: item.order_form_validate_result.errors[0].msg,
  1069. showCancel: false,
  1070. });
  1071. return;
  1072. }
  1073. }
  1074. for (let i in this.$store.state.orderSubmit.formData.list) {
  1075. for (let j in this.$store.state.orderSubmit.formData.list[i].goods_list) {
  1076. const item = this.$store.state.orderSubmit.formData.list[i].goods_list[j];
  1077. if (!item.goods_form_validate_result) continue;
  1078. if (item.goods_form_validate_result.hasError) {
  1079. uni.showModal({
  1080. title: '提示',
  1081. content: item.goods_form_validate_result.errors[0].msg,
  1082. showCancel: false,
  1083. });
  1084. return;
  1085. }
  1086. }
  1087. if (this.plugin === 'booking' && this.$store.state.orderSubmit.formData.list[i]) {
  1088. this.bookStorage('save', this.$store.state.orderSubmit.formData.list[i].store_id);
  1089. }
  1090. }
  1091. if (this.submitLock) return;
  1092. this.submitLock = true;
  1093. this.$subscribe(this.previewData.template_message_list).then(res => {
  1094. this.submit();
  1095. }).catch(() => {
  1096. this.submit();
  1097. });
  1098. },
  1099. handleGoodsFormInput({data, sign}) {
  1100. const signArr = sign.split(',');
  1101. const mchIndex = parseInt(signArr[0]);
  1102. const goodsIndex = parseInt(signArr[1]);
  1103. // const formId = parseInt(signArr[2]);
  1104. const result = [];
  1105. for (let i in data) {
  1106. result[i] = {
  1107. key: data[i].key,
  1108. label: data[i].name,
  1109. value: data[i].value,
  1110. required: data[i].is_required,
  1111. };
  1112. }
  1113. const formData = this.$store.state.orderSubmit.formData;
  1114. formData.list[mchIndex].goods_list[goodsIndex].form_data = result;
  1115. this.$store.commit('orderSubmit/mutSetFormData', formData);
  1116. },
  1117. handleGoodsFormValidate({result, sign}) {
  1118. if (!sign) return;
  1119. const signArr = sign.split(',');
  1120. const mchIndex = parseInt(signArr[0]);
  1121. const goodsIndex = parseInt(signArr[1]);
  1122. const formData = this.$store.state.orderSubmit.formData;
  1123. formData.list[mchIndex].goods_list[goodsIndex].goods_form_validate_result = result;
  1124. this.$store.commit('orderSubmit/mutSetFormData', formData);
  1125. },
  1126. updateGoodsCount() {
  1127. for (let i in this.previewData.mch_list) {
  1128. let count = 0;
  1129. for (let j in this.previewData.mch_list[i].goods_list) {
  1130. count += parseInt(this.previewData.mch_list[i].goods_list[j].num);
  1131. }
  1132. this.previewData.mch_list[i].goods_count = count;
  1133. }
  1134. },
  1135. handleAddressInput(e) {
  1136. if (typeof e.name !== 'undefined') this.previewData.address.name = e.name;
  1137. if (typeof e.mobile !== 'undefined') this.previewData.address.mobile = e.mobile;
  1138. },
  1139. // #ifdef H5
  1140. weChartPay(id) {
  1141. this.$request({
  1142. url: this.$api.registered.pay,
  1143. method: 'get',
  1144. data: {
  1145. payment_order_union_id: id
  1146. }
  1147. }).then((res) => {
  1148. if (res.code === 0) {
  1149. if (res.data.status === 1) {
  1150. uni.redirectTo({
  1151. url: `/pages/order-submit/pay-result?payment_order_union_id=${id}&order_page_url=${encodeURIComponent(this.orderPageUrl)}`,
  1152. });
  1153. } else {
  1154. if (this.orderPageUrl) {
  1155. uni.redirectTo({
  1156. url: this.orderPageUrl
  1157. });
  1158. } else {
  1159. uni.redirectTo({
  1160. url: '/pages/order/index/index'
  1161. });
  1162. }
  1163. }
  1164. }
  1165. })
  1166. }
  1167. // #endif
  1168. },
  1169. }
  1170. </script>
  1171. <style scoped lang="scss">
  1172. $submitBarHeight: #{110rpx};
  1173. $borderColor: $uni-weak-color-one;
  1174. $xWidth: #{24rpx};
  1175. $yWidth: #{24rpx};
  1176. .page {
  1177. padding-bottom: $submitBarHeight;
  1178. font-size: #{28rpx};
  1179. line-height: 1;
  1180. color: #353535;
  1181. }
  1182. .u-submit-bar-height {
  1183. height: 82upx;
  1184. }
  1185. .group {
  1186. margin: #{20rpx} #{26rpx};
  1187. background: #fff;
  1188. border-radius: #{16rpx};
  1189. overflow: hidden;
  1190. box-shadow: 0 0 #{5rpx} rgba(0, 0, 0, 0.025);
  1191. }
  1192. .row {
  1193. padding: #{12rpx} #{32rpx};
  1194. }
  1195. .row.no-px {
  1196. padding-left: 0;
  1197. padding-right: 0;
  1198. }
  1199. .line {
  1200. height: 0;
  1201. width: 100%;
  1202. background: #e2e2e2;
  1203. border-bottom: #{1rpx} solid #e2e2e2;
  1204. }
  1205. .font-bold {
  1206. font-weight: bold;
  1207. }
  1208. .font-small {
  1209. font-size: #{24rpx};
  1210. }
  1211. .font-gray {
  1212. color: #999999;
  1213. }
  1214. .title-icon {
  1215. width: #{28rpx};
  1216. height: #{25rpx};
  1217. display: block;
  1218. }
  1219. .mr-12 {
  1220. margin-right: #{12rpx};
  1221. }
  1222. .ellipsis-1 {
  1223. white-space: nowrap;
  1224. text-overflow: ellipsis;
  1225. overflow: hidden;
  1226. }
  1227. .ellipsis-2 {
  1228. display: -webkit-box;
  1229. -webkit-box-orient: vertical;
  1230. -webkit-line-clamp: 2;
  1231. text-overflow: ellipsis;
  1232. overflow: hidden;
  1233. }
  1234. .send-type {
  1235. display: inline-block;
  1236. padding: 0 0;
  1237. height: #{56rpx};
  1238. line-height: #{56rpx};
  1239. width: #{190rpx};
  1240. text-align: center;
  1241. border-radius: #{100rpx};
  1242. margin: 0 #{32rpx} 0 0;
  1243. font-size: #{28rpx};
  1244. }
  1245. .send-type:last-child {
  1246. margin-right: 0;
  1247. }
  1248. .delivery-coverage-btn {
  1249. display: inline-block;
  1250. padding: 0 #{20rpx};
  1251. height: #{56rpx};
  1252. line-height: #{56rpx};
  1253. text-align: center;
  1254. border-radius: #{100rpx};
  1255. font-size: #{24rpx};
  1256. border: #{1rpx} solid #e5e5e5;
  1257. color: #666;
  1258. }
  1259. .more-discount-info {
  1260. background: #f7f7f7;
  1261. padding: #{6rpx} #{14rpx};
  1262. position: relative;
  1263. border-radius: #{8rpx};
  1264. }
  1265. .more-discount-info:before {
  1266. display: block;
  1267. content: " ";
  1268. width: 0;
  1269. height: 0;
  1270. position: absolute;
  1271. right: #{30rpx};
  1272. top: -#{39rpx};
  1273. border: #{20rpx} solid transparent;
  1274. border-bottom-color: #f7f7f7;
  1275. }
  1276. .insert-rows {
  1277. height: 0;
  1278. overflow: hidden;
  1279. transition: 200ms;
  1280. padding: 0 0;
  1281. visibility: hidden;
  1282. view {
  1283. font-size: #{24rpx};
  1284. }
  1285. }
  1286. .show .insert-rows {
  1287. height: auto;
  1288. padding: #{24rpx} 0;
  1289. visibility: visible;
  1290. }
  1291. .show .bottom-icon,
  1292. .bottom-icon.show {
  1293. transform: rotate(180deg);
  1294. transition: 200ms;
  1295. }
  1296. .svip {
  1297. view {
  1298. color: #e4cdbb;
  1299. }
  1300. height: #{120rpx};
  1301. background-size: 100% 100%;
  1302. background-color: #3c352e;
  1303. padding-left: #{110rpx};
  1304. border-radius: #{12rpx};
  1305. .vip-card-name {
  1306. max-width: #{90rpx};
  1307. overflow: hidden;
  1308. white-space: nowrap;
  1309. text-overflow: ellipsis;
  1310. font-size: #{24rpx};
  1311. color: #f3be94;
  1312. }
  1313. }
  1314. .goods-form {
  1315. .goods-list {
  1316. padding-top: #{12rpx};
  1317. padding-bottom: #{12rpx};
  1318. }
  1319. .goods-item {
  1320. margin: #{12rpx} 0;
  1321. }
  1322. .goods-image {
  1323. width: #{200rpx};
  1324. height: #{200rpx};
  1325. margin-right: #{24rpx};
  1326. }
  1327. .goods-name {
  1328. line-height: #{35rpx};
  1329. height: #{70rpx};
  1330. margin-bottom: #{32rpx};
  1331. }
  1332. }
  1333. /* ---------- */
  1334. .submit-bar {
  1335. //background: #fff;
  1336. //border-top: #{1rpx} solid $uni-weak-color-two;
  1337. //position: fixed;
  1338. //left: 0;
  1339. //bottom: 0;
  1340. //width: 100%;
  1341. //z-index: 1000;
  1342. .price-info {
  1343. padding: 0 0;
  1344. >view {
  1345. margin: #{16rpx} 0;
  1346. }
  1347. }
  1348. .submit-btn {
  1349. width: 240upx;
  1350. text-align: center;
  1351. border-radius: 41upx;
  1352. }
  1353. .submit-btn:active {
  1354. box-shadow: inset 0 0 #{500rpx} rgba(0, 0, 0, .15);
  1355. }
  1356. .submit-btn.lock {
  1357. box-shadow: inset 0 0 #{500rpx} rgba(255, 255, 255, 0.35);
  1358. }
  1359. .submit-btn.disabled {
  1360. background: $uni-general-color-two;
  1361. }
  1362. }
  1363. .theme-color {
  1364. color: #ffffff;
  1365. }
  1366. .u-bottom-fixed {
  1367. position: fixed;
  1368. bottom: 0;
  1369. left: 0;
  1370. width: 100%;
  1371. z-index: 997;
  1372. background-color: #ffffff;
  1373. box-shadow: 0 -1rpx 20rpx -15rpx #353535;
  1374. }
  1375. .bd-bottom {
  1376. width: 750upx;
  1377. height: 110upx;
  1378. padding: 14upx 24upx;
  1379. }
  1380. .full-tip {
  1381. width: 750upx;
  1382. height: 58upx;
  1383. line-height: 58upx;
  1384. }
  1385. .full-tip-show {
  1386. background-color: #ffecec;
  1387. font-size: #{24rpx};
  1388. text-align: center;
  1389. .full-tip-text {
  1390. color: #FF4544;
  1391. }
  1392. }
  1393. .collapse-item-titlebar {
  1394. display: flex;
  1395. align-items: center;
  1396. height: 80rpx;
  1397. .collapse-item-titlebar-txt {
  1398. padding-left: 24rpx;
  1399. font-weight: bold;
  1400. font-size: 30rpx;
  1401. }
  1402. }
  1403. ::v-deep .uni-collapse {
  1404. background-color: transparent !important;
  1405. }
  1406. </style>