index.vue 49 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696
  1. <template>
  2. <view>
  3. <view class="order-submission">
  4. <view class="order-submission-box">
  5. <view class="allAddress">
  6. <view
  7. class="address acea-row row-between-wrapper"
  8. @tap="onAddress"
  9. v-if="shippingType == 0"
  10. :style="
  11. store_self_mention
  12. ? ''
  13. : 'border-top-left-radius: 14rpx;border-top-right-radius: 14rpx;'
  14. "
  15. >
  16. <view class="addressCon" v-if="addressInfo.realName">
  17. <view class="selected-address">
  18. <text class="default" v-if="addressInfo.isDefault">默认</text>
  19. <view class="">
  20. <view class="acea-row">
  21. <text class="line2"
  22. >{{ addressInfo.province }}{{ addressInfo.city
  23. }}{{ addressInfo.district }}{{ addressInfo.detail }}</text
  24. >
  25. </view>
  26. <view class="name"
  27. >{{ addressInfo.realName }}
  28. <text class="phone">{{ addressInfo.phone }}</text>
  29. </view>
  30. </view>
  31. </view>
  32. </view>
  33. <view class="addressCon" v-else>
  34. <view class="setaddress">设置收货地址</view>
  35. </view>
  36. </view>
  37. <view
  38. class="address acea-row row-between-wrapper"
  39. v-else
  40. @tap="showStoreList"
  41. >
  42. <block v-if="storeList.length > 0">
  43. <view class="addressCon">
  44. <view class="name"
  45. >{{ system_store.name }}
  46. <text class="phone">{{ system_store.phone }}</text>
  47. </view>
  48. <view class="line1">
  49. {{ system_store.address
  50. }}{{ ", " + system_store.detailedAddress }}
  51. </view>
  52. </view>
  53. <view class="iconfont icon-jiantou"></view>
  54. </block>
  55. <block v-else>
  56. <view>暂无门店信息</view>
  57. </block>
  58. </view>
  59. <view class="line">
  60. <image src="/static/images/line.png"></image>
  61. </view>
  62. </view>
  63. <view class="goods">
  64. <orderGoods
  65. :mallType="orderInfoVo.mallType"
  66. :cartInfo="cartInfo"
  67. :orderProNum="orderProNum"
  68. >
  69. </orderGoods>
  70. <view
  71. class="line-item acea-row row-between-wrapper"
  72. @tap="couponTap"
  73. v-if="orderInfoVo.mallType === 0"
  74. >
  75. <view class="item-label">优惠券</view>
  76. <view
  77. class="discount none"
  78. :class="{ none: couponTitle == '请选择' }"
  79. >
  80. {{ couponTitle }}
  81. <image
  82. class="rt-arr"
  83. src="@/static/images/right.png"
  84. mode=""
  85. ></image>
  86. </view>
  87. </view>
  88. <view class="line-item acea-row row-between-wrapper">
  89. <view class="item-label">快递费用</view>
  90. <block v-if="orderInfoVo.mallType === 0">
  91. <view
  92. class="discount"
  93. v-if="
  94. parseFloat(orderInfoVo.freightFee) > 0 &&
  95. orderInfoVo.mallType === 0
  96. "
  97. >
  98. +¥{{ orderInfoVo.freightFee }}
  99. </view>
  100. <view class="discount" v-else>免运费</view>
  101. </block>
  102. <view class="discount" v-else>邮费到付</view>
  103. </view>
  104. </view>
  105. <view class="wrapper">
  106. <view class="item" v-if="textareaStatus">
  107. <view>备注信息</view>
  108. <textarea
  109. v-if="coupon.coupon === false"
  110. placeholder-class="placeholder"
  111. @input="bindHideKeyboard"
  112. value=""
  113. name="mark"
  114. placeholder="请输入备注(可选,如特殊定制需求)"
  115. ></textarea>
  116. </view>
  117. </view>
  118. <view v-if="orderInfoVo.mallType === 0" class="moneyList">
  119. <view class="item acea-row row-between-wrapper">
  120. <view>商品总价:</view>
  121. <view v-if="orderInfoVo.mallType === 0" class="money">
  122. ¥{{ orderInfoVo.payFee || 0 }}
  123. </view>
  124. <view v-else class="money">
  125. 贝币: {{ Number(orderInfoVo.proTotalFee) || 0 }}
  126. </view>
  127. </view>
  128. <view
  129. class="item acea-row row-between-wrapper"
  130. v-if="orderInfoVo.couponFee > 0"
  131. >
  132. <view>优惠券抵扣:</view>
  133. <view class="money">-¥{{ orderInfoVo.couponFee }}</view>
  134. </view>
  135. <!-- <view
  136. class="item acea-row row-between-wrapper"
  137. v-if="orderInfoVo.deductionPrice > 0"
  138. >
  139. <view>积分抵扣:</view>
  140. <view class="money">-¥{{ orderInfoVo.deductionPrice }}</view>
  141. </view> -->
  142. <view
  143. class="item acea-row row-between-wrapper"
  144. v-if="
  145. orderInfoVo?.proTotalWeight && orderInfoVo?.proTotalWeight > 0
  146. "
  147. >
  148. <view>总克重:</view>
  149. <view class="money">{{ orderInfoVo.proTotalWeight }} g</view>
  150. </view>
  151. <view
  152. class="item acea-row row-between-wrapper"
  153. v-if="orderInfoVo.mallType === 0"
  154. >
  155. <view>工费:</view>
  156. <view class="money">¥{{ orderInfoVo.totalLaborCost }}</view>
  157. </view>
  158. <view
  159. class="item acea-row row-between-wrapper"
  160. v-if="
  161. orderInfoVo.mallType === 0 && orderInfoVo?.totalAdditionalAmount
  162. "
  163. >
  164. <view>附加费:</view>
  165. <view class="money">¥{{ orderInfoVo.totalAdditionalAmount }}</view>
  166. </view>
  167. <view
  168. class="item acea-row row-between-wrapper"
  169. v-if="orderInfoVo.freightFee > 0"
  170. >
  171. <view>运费:</view>
  172. <view class="money">¥{{ orderInfoVo.freightFee }}</view>
  173. </view>
  174. <view
  175. v-if="
  176. orderInfoVo.mallType === 0 &&
  177. Number(orderInfoVo.vipLevelDis) !== 0
  178. "
  179. class="item acea-row row-between-wrapper"
  180. >
  181. <view>会员折扣:</view>
  182. <view class="money">-¥{{ orderInfoVo.vipLevelDis }}</view>
  183. </view>
  184. </view>
  185. <!-- 是否使用余料支付 -->
  186. <view class="pay-container">
  187. <view class="item">
  188. <view class="zf-box" v-if="orderInfoVo.mallType == 0">
  189. <view>余料支付方式</view>
  190. </view>
  191. <view class="list" v-if="orderInfoVo.mallType == 0">
  192. <view class="payItem">
  193. <view class="name acea-row row-center-wrapper">
  194. <image
  195. class="pay-icon"
  196. src="@/static/images/au_icon.png"
  197. ></image>
  198. 余料支付
  199. </view>
  200. <view class="tip">
  201. <text class="balance"
  202. >可用余料:
  203. {{ metalTypeMap[metalType].name }}
  204. :{{ metalTypeMap[metalType].balance || 0 }}g</text
  205. >
  206. </view>
  207. </view>
  208. </view>
  209. <view class="zf-box">
  210. <view>工费支付方式</view>
  211. </view>
  212. <view class="list">
  213. <view
  214. v-for="(item, index) in avaliablePayments"
  215. class="payItem"
  216. :class="active == index ? 'on' : ''"
  217. @tap="payItem(index)"
  218. :key="index"
  219. >
  220. <view class="name acea-row row-center-wrapper">
  221. <image
  222. class="pay-icon"
  223. src="https://my-go-easy-im.oss-cn-shenzhen.aliyuncs.com/goeasy-im-%E6%B0%B4%E8%B4%9D%E5%95%86%E5%9F%8E/%E5%BE%AE%E4%BF%A1%E5%9B%BE%E7%89%87_20260302114032_816_219.png"
  224. ></image>
  225. <image
  226. class="pay-icon"
  227. v-if="item.name == '余额支付'"
  228. src="@/static/images/balance-icon.png"
  229. ></image>
  230. {{ item.name }}
  231. </view>
  232. <view class="tip">
  233. <text class="balance">{{ item.title }}</text>
  234. <image
  235. class="select-icon"
  236. v-show="active == index"
  237. src="@/static/images/select-active@2x.png"
  238. mode=""
  239. ></image>
  240. <image
  241. class="select-icon"
  242. v-show="active != index"
  243. src="@/static/images/select@2x.png"
  244. mode=""
  245. >
  246. </image>
  247. </view>
  248. </view>
  249. </view>
  250. </view>
  251. </view>
  252. </view>
  253. <view class="kong"></view>
  254. <view class="footer acea-row row-between-wrapper">
  255. <view>
  256. 合计:
  257. <text class="price" v-if="orderInfoVo.mallType === 0">
  258. ¥{{ orderInfoVo.payFee || 0 }}
  259. </text>
  260. <text class="price" v-else>
  261. {{ Number(orderInfoVo.proTotalFee) || 0 }}贝币
  262. </text>
  263. </view>
  264. <view class="settlement" style="z-index: 100" @tap="SubOrder">
  265. 立即结算
  266. </view>
  267. </view>
  268. </view>
  269. <couponListWindow
  270. :coupon="coupon"
  271. @close="closeCouponPopup"
  272. :showPopup="showCouponPopup"
  273. :openType="openType"
  274. @ChangCoupons="ChangCoupons"
  275. :orderShow="orderShow"
  276. ></couponListWindow>
  277. <addressWindow
  278. ref="addressWindowRef"
  279. @changeTextareaStatus="changeTextareaStatus"
  280. :address="address"
  281. :pagesUrl="pagesUrl"
  282. @OnDefaultAddress="OnDefaultAddress"
  283. @OnChangeAddress="OnChangeAddress"
  284. @changeClose="changeClose"
  285. />
  286. <!-- 余额不足modal -->
  287. <up-modal
  288. :showCancelButton="true"
  289. :show="showModal"
  290. title="余额不足"
  291. confirmText="去充值"
  292. @cancel="showModal = false"
  293. @confirm="modalConfirm"
  294. ></up-modal>
  295. <WechatPayment ref="wechatPaymentRef" />
  296. </view>
  297. </template>
  298. <script setup>
  299. // 导入UniApp页面加载生命周期函数
  300. import { onLoad } from "@dcloudio/uni-app";
  301. // 导入Vue3响应式API(ref创建响应式变量、computed计算属性等)
  302. import { ref, computed, watch, onMounted, nextTick } from "vue";
  303. // 导入应用状态管理(全局状态,如登录状态、用户信息等)
  304. import { useAppStore } from "@/stores/app.js";
  305. // 导入提示框工具(封装的toast提示函数)
  306. import { useToast } from "@/hooks/useToast.js";
  307. // 导入支付相关工具(封装的支付逻辑,如提交支付、验证支付渠道等)
  308. import { usePayment } from "@/hooks/usePayment.js";
  309. import WechatPayment from "@/components/payment/WechatPayment.vue";
  310. // 导入订单相关API接口(优惠券、创建订单、计算价格等接口)
  311. import {
  312. getUserAvailableCoupons, // 根据用户和使用位置查询可用优惠券接口
  313. orderCreate, // 创建订单接口
  314. postOrderComputed, // 计算订单价格接口
  315. wechatOrderPay, // 微信支付接口
  316. wechatQueryPayResult, // 微信支付结果查询接口
  317. loadPreOrderApi, // 加载预订单接口
  318. alipayPaymentResult, // 支付宝支付结果查询接口
  319. } from "@/api/order.js";
  320. // 导入用户地址详情API接口
  321. import { getAddressDetail } from "@/api/user.js";
  322. // 导入门店列表API接口
  323. import { storeListApi } from "@/api/store.js";
  324. // 导入工具类(封装的通用工具函数)
  325. import util from "@/utils/util";
  326. // 导入优惠券弹窗组件
  327. import couponListWindow from "@/components/couponListWindow";
  328. // 导入地址选择组件
  329. import addressWindow from "@/components/addressWindow";
  330. // 导入订单商品列表组件
  331. import orderGoods from "@/components/orderGoods";
  332. // 导入登录工具(未登录时跳转登录页)
  333. import { toLogin } from "@/libs/login.js";
  334. import useRealGoldPrice from "@/hooks/useRealGoldPrice";
  335. const { realGoldprice, fetchGoldPrice } = useRealGoldPrice("RTJ_Au");
  336. // 初始化应用状态管理实例(用于获取全局状态)
  337. const appStore = useAppStore();
  338. // 初始化提示框工具(获取toast方法)
  339. const { Toast } = useToast();
  340. // 初始化支付工具(仅支付宝使用)
  341. const { submitPayment, paymentConfig, getAvailableChannels } = usePayment();
  342. // 微信支付状态文案
  343. const WX_PAY_STATUS = {
  344. SUCCESS: "支付成功",
  345. FAIL: "支付失败",
  346. CANCEL: "用户取消支付",
  347. };
  348. // 响应式变量:订单页面标识(用于优惠券组件,控制不显示tab切换)
  349. const orderShow = ref("orderShow");
  350. // 响应式变量:控制备注输入框是否显示
  351. const textareaStatus = ref(true);
  352. // 响应式变量:支付方式列表(包含支付宝、微信、余额等支付方式配置)
  353. const payments = ref([
  354. // {
  355. // name: "支付宝支付", // 支付方式名称
  356. // icon: "icon-zhifubao", // 图标类名
  357. // value: "alipay", // 支付标识值
  358. // title: "支付宝快捷支付", // 支付说明
  359. // payType: "alipay", // 支付类型
  360. // payStatus: 0, // 支付状态(1-可用,0-不可用)
  361. // payChannel: "appAliPay",
  362. // },
  363. {
  364. name: "微信支付",
  365. icon: "icon-wechat",
  366. value: "weixin",
  367. title: "微信快捷支付",
  368. payType: "weixin",
  369. payStatus: 0,
  370. payChannel: "routine",
  371. },
  372. // {
  373. // name: "余额支付",
  374. // icon: "icon-balance",
  375. // value: "yue",
  376. // title: "可用余额:",
  377. // payType: "yue",
  378. // payStatus: 1,
  379. // payChannel: "weixinh5",
  380. // },
  381. // {
  382. // name: "贝币支付",
  383. // icon: "icon-balance",
  384. // value: "yue",
  385. // title: "可用贝币:",
  386. // payType: "yue",
  387. // payStatus: 0,
  388. // payChannel: "weixinh5",
  389. // },
  390. ]);
  391. // 计算属性:过滤出可用的支付方式(只保留payStatus为1的项)
  392. const avaliablePayments = computed(() => {
  393. return payments.value.filter((item) => item.payStatus === 1);
  394. });
  395. // 响应式变量:当前选中的支付方式(默认余额支付)
  396. const payType = ref("alipay");
  397. // 响应式变量:优惠券打开方式(1表示"使用"场景)
  398. const openType = ref(1);
  399. // 响应式变量:当前选中的支付方式索引(用于UI高亮)
  400. const active = ref(0);
  401. // 响应式变量:优惠券相关配置(控制弹窗显示、列表数据等)
  402. const coupon = ref({
  403. coupon: false, // 是否显示优惠券弹窗
  404. list: [], // 优惠券列表数据
  405. statusTile: "立即使用", // 按钮文字
  406. });
  407. // 响应式变量:地址相关配置(控制弹窗显示、选中地址ID等)
  408. const address = ref({
  409. address: false,
  410. addressId: 0,
  411. }); // 地址组件
  412. const addressInfo = ref({}); // 地址信息
  413. const addressId = ref(0); // 地址id
  414. const couponId = ref(0); // 优惠券id
  415. const userInfo = ref({}); // 用户信息
  416. const mark = ref(""); // 备注信息
  417. const couponTitle = ref("请选择"); // 优惠券
  418. const useIntegral = ref(false); // 是否使用积分
  419. const status = ref(0);
  420. // 响应式变量:是否有地址(用于判断是否需要提示用户添加地址)
  421. const is_address = ref(false);
  422. // 响应式变量:支付页面刷新标识(修复支付页面隐藏后刷新问题)
  423. const toPay = ref(false);
  424. // 响应式变量:配送方式(0-快递配送,1-到店自提)
  425. const shippingType = ref(0);
  426. // 响应式变量:选中的门店信息(自提时使用)
  427. const system_store = ref({});
  428. const contacts = ref("");
  429. // 响应式变量:联系人电话(自提时可能需要)
  430. const contactsTel = ref("");
  431. const storeList = ref([]);
  432. // 响应式变量:是否支持门店自提(1-支持,0-不支持)
  433. const store_self_mention = ref(0);
  434. // 响应式变量:购物车商品信息(订单中的商品列表)
  435. const cartInfo = ref([]);
  436. const animated = ref(false);
  437. // 响应式变量:订单总价
  438. const totalPrice = ref(0);
  439. const pagesUrl = ref("");
  440. // const usableCoupon = ref({});
  441. const payChannel = ref("");
  442. // 响应式变量:订单信息详情(包含商品总价、运费、折扣等)
  443. const orderInfoVo = ref({});
  444. // 响应式变量:地址列表数据(用于地址选择组件)
  445. const addressList = ref([]);
  446. // 响应式变量:订单商品总数
  447. const orderProNum = ref(0);
  448. const preOrderNo = ref(""); // 预下单订单号
  449. const addressWindowRef = ref(null); // 地址组件引用
  450. const showCouponPopup = ref(false); // 显示优惠券弹窗
  451. const showModal = ref(false);
  452. const userSelectPayTypeItem = ref(null);
  453. const wechatPaymentRef = ref(null);
  454. // 监听 isLogin
  455. watch(
  456. () => appStore.isLogin, // 监听的数据源:全局登录状态
  457. (newV) => {
  458. // newV是登录状态的新值(true/false)
  459. if (newV) {
  460. // 若已登录
  461. getloadPreOrder(); // 加载预订单信息
  462. this.getaddressInfo(); // 获取地址信息(this指向当前组件实例)
  463. }
  464. },
  465. {
  466. deep: true,
  467. } // 深度监听(确保复杂数据类型变化也能触发)
  468. );
  469. // 商品总价
  470. // 页面加载时触发的生命周期函数
  471. onLoad((options) => {
  472. // options是页面跳转时传递的参数
  473. console.log(appStore.userInfo); // 打印用户信息(调试用)
  474. // #ifdef APP
  475. // 支付宝沙箱模式(测试环境用,正式环境注释)
  476. // var EnvUtils = plus.android.importClass("com.alipay.sdk.app.EnvUtils");
  477. // EnvUtils.setEnv(EnvUtils.EnvEnum.SANDBOX);
  478. // #endif
  479. // #ifdef H5
  480. payChannel.value = "weixinh5"; // H5环境支付渠道为微信H5支付
  481. // #endif
  482. // #ifdef APP
  483. payChannel.value = "appAliPay"; // APP环境支付渠道为支付宝APP支付
  484. // #endif
  485. // 从参数中获取预订单号(若没有则默认为0)
  486. preOrderNo.value = options.preOrderNo || 0;
  487. // 从参数中获取地址ID(若没有则默认为0)
  488. addressId.value = options.addressId || 0;
  489. // 从参数中获取是否有地址的标识
  490. is_address.value = options.is_address ? true : false;
  491. // 若已登录,则加载预订单信息;否则跳转到登录页
  492. if (appStore.isLogin) {
  493. getloadPreOrder(); // 加载预订单
  494. } else {
  495. toLogin(); // 跳登录
  496. }
  497. });
  498. // 组件挂载后触发的生命周期函数(DOM渲染完成后)
  499. onMounted(() => {
  500. textareaStatus.value = true; // 默认显示备注输入框
  501. // 若已登录且非支付页面,则获取地址信息(注释掉的逻辑,预留)
  502. if (appStore.isLogin && !toPay.value) {
  503. //this.getaddressInfo();
  504. }
  505. // 监听全局事件"handClick"(用于接收门店选择结果)
  506. uni.$on("handClick", (res) => {
  507. if (res) {
  508. // 若有结果
  509. system_store.value = res.address; // 更新选中的门店信息
  510. }
  511. // 清除监听(避免重复触发)
  512. uni.$off("handClick");
  513. });
  514. });
  515. // 是否选择余料支付
  516. const useGoldPay = (e) => {
  517. computedPrice();
  518. };
  519. const metalTypeMap = {
  520. 1: {
  521. name: "黄金",
  522. balance: 0,
  523. },
  524. 2: {
  525. name: "铂金",
  526. balance: 0,
  527. },
  528. 3: {
  529. name: "白银",
  530. balance: 0,
  531. },
  532. };
  533. const metalType = ref(1);
  534. // 加载预订单信息(核心函数:初始化订单数据)
  535. const getloadPreOrder = () => {
  536. // 调用加载预订单API,传入预订单号
  537. loadPreOrderApi(preOrderNo.value)
  538. .then((res) => {
  539. metalTypeMap[1].balance = res.data.auBalance || 0;
  540. metalTypeMap[2].balance = res.data.ptBalance || 0;
  541. metalTypeMap[3].balance = res.data.agBalance || 0;
  542. metalType.value = res.data.metalType || 1;
  543. // 接口成功回调
  544. let orderInfoVoData = res.data.orderInfoVo; // 订单基本信息
  545. orderInfoVo.value = orderInfoVoData; // 保存订单信息
  546. cartInfo.value = orderInfoVoData.orderDetailList; // 保存商品列表
  547. orderProNum.value = orderInfoVoData.orderProNum; // 保存商品总数
  548. // 设置地址ID(优先用参数传入的,没有则用订单默认的)
  549. address.value.addressId = addressId.value
  550. ? addressId.value
  551. : orderInfoVoData.addressId;
  552. // 判断是否支持门店自提(根据接口返回和全局状态)
  553. store_self_mention.value =
  554. res.data.storeSelfMention == "true" && // 接口返回支持自提
  555. appStore.productTypeComputed === "normal" // 全局状态为普通商品
  556. ? true
  557. : false;
  558. // 根据商城类型设置是否使用积分(mallType=1时默认使用)
  559. useIntegral.value = orderInfoVo.value.mallType === 1;
  560. // 根据商城类型设置默认支付方式(mallType=1时用贝币支付)
  561. payType.value = "yue";
  562. // 动态更新支付方式状态(根据接口返回的配置)
  563. payments.value.forEach((item) => {
  564. if (orderInfoVo.value.mallType === 1) {
  565. // 贝币商城:只开放贝币支付
  566. item.title = "可用贝币: " + orderInfoVoData.userIntegral;
  567. item.payStatus = item.name === "贝币支付" ? 1 : 0;
  568. } else {
  569. // 普通商城:根据各支付方式状态分别处理
  570. if (item.name === "余额支付") {
  571. item.title = "可用余额: " + orderInfoVoData.userBalance;
  572. item.payStatus = parseInt(res.data.yuePayStatus) === 1 ? 1 : 0;
  573. } else if (item.payType === "weixin") {
  574. // 微信支付:状态由接口返回的payWeixinOpen决定
  575. item.payStatus = parseInt(res.data.payWeixinOpen) === 1 ? 1 : 0;
  576. } else if (item.name === "贝币支付") {
  577. item.payStatus = 0;
  578. }
  579. }
  580. });
  581. // 初始化默认选中第一个可用支付方式
  582. const firstAvailable = payments.value.find(
  583. (item) => item.payStatus === 1
  584. );
  585. if (firstAvailable) {
  586. const idx = avaliablePayments.value.indexOf(firstAvailable);
  587. active.value = idx >= 0 ? idx : 0;
  588. payType.value = firstAvailable.value;
  589. userSelectPayTypeItem.value = firstAvailable;
  590. }
  591. if (addressId.value) {
  592. computedPrice();
  593. }
  594. // 调用子页面方法授权后执行获取地址列表
  595. nextTick(() => {
  596. addressWindowRef.value.fetchAddressList();
  597. });
  598. })
  599. .catch((err) => {
  600. // 接口失败回调
  601. console.error(err); // 打印错误
  602. uni.navigateTo({
  603. url: "/pages/order_list/index",
  604. }); // 跳转到订单列表
  605. Toast({
  606. title: err,
  607. }); // 提示错误信息
  608. });
  609. };
  610. // 授权回调事件(用户授权后触发,预留)
  611. const onLoadFun = () => {
  612. //this.getaddressInfo(); // 获取地址信息(注释掉的逻辑)
  613. // 调用子组件方法获取地址列表(注释掉的逻辑)
  614. // this.$scope.selectComponent('#address-window').getAddressList();
  615. };
  616. // 获取门店列表数据(自提时使用)
  617. const getList = () => {
  618. // 从本地存储获取用户经纬度(用于附近门店查询)
  619. let longitude = uni.getStorageSync("user_longitude");
  620. let latitude = uni.getStorageSync("user_latitude");
  621. // 构造请求参数
  622. let data = {
  623. latitude: latitude, // 纬度
  624. longitude: longitude, // 经度
  625. page: 1, // 页码
  626. limit: 10, // 每页条数
  627. };
  628. // 调用门店列表API
  629. storeListApi(data)
  630. .then((res) => {
  631. // 成功回调
  632. let list = res.data.list || []; // 门店列表
  633. storeList.value = list; // 保存门店列表
  634. system_store.value = list[0]; // 默认选中第一个门店
  635. })
  636. .catch((err) => {
  637. // 失败回调
  638. Toast({
  639. title: err,
  640. }); // 提示错误
  641. });
  642. };
  643. // 关闭地址弹窗
  644. const changeClose = () => {
  645. address.value.address = false; // 隐藏地址弹窗
  646. };
  647. // 跳转门店列表页面(自提时选择门店)
  648. const showStoreList = () => {
  649. // 若有门店列表数据,则跳转到门店详情页
  650. if (storeList.value.length > 0) {
  651. uni.navigateTo({
  652. url: "/pages/users/goods_details_store/index",
  653. });
  654. }
  655. };
  656. // 计算订单价格
  657. function computedPrice(couponTitleValue) {
  658. let shippingTypeValue = shippingType.value;
  659. postOrderComputed({
  660. mallType: orderInfoVo.value.mallType, // 商城类型
  661. addressId: address.value.addressId, // 地址ID
  662. useIntegral: useIntegral.value ? true : false, // 是否用积分
  663. couponId: couponId.value, // 优惠券ID
  664. shippingType: parseInt(shippingTypeValue) + 1, // 配送方式(后端要求+1)
  665. preOrderNo: preOrderNo.value, // 预订单号
  666. goldNum: appStore.userInfo.goldBalance, // 余料数量
  667. })
  668. .then((res) => {
  669. if (couponTitleValue) {
  670. couponTitle.value = couponTitleValue;
  671. }
  672. // 成功回调
  673. let data = res.data; // 计算后的价格数据
  674. // 更新订单费用信息
  675. orderInfoVo.value.couponFee = data.couponFee; // 优惠券抵扣
  676. orderInfoVo.value.userIntegral = data.surplusIntegral; // 剩余积分
  677. orderInfoVo.value.deductionPrice = data.deductionPrice; // 积分抵扣金额
  678. orderInfoVo.value.freightFee = data.freightFee; // 运费
  679. orderInfoVo.value.payFee = data.payFee; // 实付金额
  680. orderInfoVo.value.proTotalFee = data.proTotalFee; // 商品总价
  681. orderInfoVo.value.useIntegral = data.useIntegral; // 是否使用积分
  682. orderInfoVo.value.usedIntegral = data.usedIntegral; // 已用积分
  683. orderInfoVo.value.surplusIntegral = data.surplusIntegral; // 剩余积分
  684. orderInfoVo.value.vipLevelDis = data.vipLevelDis; // 会员折扣
  685. })
  686. .catch((err) => {
  687. // 失败回调
  688. Toast({ title: err }); // 提示错误
  689. });
  690. }
  691. // 切换配送方式(快递/自提)
  692. const addressType = (e) => {
  693. let index = e; // 0-快递,1-自提
  694. shippingType.value = parseInt(index); // 更新配送方式
  695. // 若为普通商城类型,重新计算价格
  696. if (orderInfoVo.value.mallType === 0) {
  697. computedPrice();
  698. }
  699. // if (index == 1) getList();
  700. };
  701. // 配送方式选择器变化事件(预留,用于下拉选择器)
  702. const bindPickerChange = (e) => {
  703. let value = e.detail.value; // 选择的索引
  704. shippingType.value = value; // 更新配送方式
  705. computedPrice(); // 重新计算价格
  706. };
  707. // 关闭优惠券弹窗
  708. const closeCouponPopup = () => {
  709. showCouponPopup.value = false; // 隐藏优惠券弹窗
  710. };
  711. // 改变备注框状态(优惠券选择后调用)
  712. const changeTextareaStatus = () => {
  713. // 重置所有优惠券的选中状态
  714. for (let i = 0, len = coupon.value.list.length; i < len; i++) {
  715. coupon.value.list[i].use_title = "";
  716. coupon.value.list[i].is_use = 0;
  717. }
  718. textareaStatus.value = true; // 显示备注框
  719. status.value = 0; // 重置状态
  720. coupon.value.list = coupon.value.list; // 触发响应式更新
  721. };
  722. // 选择优惠券后的处理事件
  723. const ChangCoupons = (e) => {
  724. // this.usableCoupon = e
  725. // this.coupon.coupon = false
  726. let index = e,
  727. list = coupon.value.list,
  728. couponTitleValue = "请选择",
  729. couponIdValue = 0;
  730. console.log("list", list);
  731. for (let i = 0, len = list.length; i < len; i++) {
  732. if (i != index) {
  733. list[i].use_title = "";
  734. list[i].isUse = 0;
  735. }
  736. }
  737. // 切换当前优惠券的选中状态
  738. if (list[index].isUse) {
  739. // 若已选中,则取消选择
  740. list[index].use_title = "";
  741. list[index].isUse = 0;
  742. } else {
  743. // 若未选中,则选中
  744. list[index].use_title = "不使用"; // 显示"不使用"按钮
  745. list[index].isUse = 1; // 标记为选中
  746. couponTitleValue = list[index].name; // 更新标题为优惠券名称
  747. couponIdValue = list[index].id; // 更新选中的优惠券ID
  748. }
  749. // 更新优惠券相关状态
  750. couponId.value = couponIdValue;
  751. coupon.value.coupon = false;
  752. // coupon.value.list = list;
  753. computedPrice(couponTitleValue);
  754. };
  755. // 首次进入页面时展示默认地址
  756. const OnDefaultAddress = (e) => {
  757. addressInfo.value = e; // 保存默认地址详情
  758. address.value.addressId = e.id; // 更新选中地址ID
  759. };
  760. // 选择地址后触发的事件
  761. const OnChangeAddress = (e) => {
  762. console.log("OnChangeAddress", e);
  763. addressInfo.value = e;
  764. address.value.addressId = e.id;
  765. textareaStatus.value = true;
  766. //orderInfoVo.value.addressId = e;
  767. address.value.address = false;
  768. //this.getaddressInfo();
  769. if (orderInfoVo.value.mallType === 0) {
  770. computedPrice();
  771. }
  772. };
  773. // 备注输入事件(实时保存输入内容)
  774. const bindHideKeyboard = (e) => {
  775. mark.value = e.detail.value; // 保存输入的备注信息
  776. };
  777. // 获取当前订单可用的优惠券列表
  778. const getCouponList = () => {
  779. // 调用获取优惠券API,传入预订单号
  780. getUserAvailableCoupons({ scenePositionId: 1 }).then((res) => {
  781. coupon.value.list = res.data; // 保存优惠券列表
  782. openType.value = 1; // 设置打开方式为"使用"
  783. });
  784. };
  785. // 获取默认地址或指定地址详情
  786. const getaddressInfo = () => {
  787. if (addressId.value) {
  788. // 若有指定地址ID,获取该地址详情
  789. getAddressDetail(addressId.value).then((res) => {
  790. if (res.data) {
  791. // 若地址存在
  792. res.data.isDefault = parseInt(res.data.isDefault); // 转换默认地址标识为数字
  793. addressInfo.value = res.data || {}; // 保存地址详情
  794. addressId.value = res.data.id || 0; // 更新地址ID
  795. address.value.addressId = res.data.id || 0; // 更新选中地址ID
  796. }
  797. });
  798. } else {
  799. // 若没有指定地址ID,获取默认地址
  800. getAddressDefault().then((res) => {
  801. // 注意:原代码中未导入getAddressDefault,可能是遗漏
  802. if (res.data) {
  803. // 若默认地址存在
  804. res.data.isDefault = parseInt(res.data.isDefault);
  805. addressInfo.value = res.data || {};
  806. addressId.value = res.data.id || 0;
  807. address.value.addressId = res.data.id || 0;
  808. }
  809. });
  810. }
  811. };
  812. // 选择支付方式
  813. const payItem = (e) => {
  814. let activeValue = e;
  815. active.value = activeValue;
  816. animated.value = true;
  817. payType.value = avaliablePayments.value[activeValue].value;
  818. userSelectPayTypeItem.value = avaliablePayments.value[activeValue];
  819. computedPrice();
  820. setTimeout(() => {
  821. car();
  822. }, 500);
  823. };
  824. // 打开优惠券弹窗
  825. const couponTap = () => {
  826. // coupon.value.coupon = true;
  827. showCouponPopup.value = true;
  828. if (!coupon.value.list.length) getCouponList();
  829. // getCouponList();
  830. };
  831. // 关闭支付方式选择动画
  832. const car = () => {
  833. animated.value = false; // 关闭动画
  834. };
  835. // 打开地址选择弹窗
  836. const onAddress = () => {
  837. textareaStatus.value = false; // 隐藏备注框
  838. address.value.address = true; // 显示地址弹窗
  839. // 设置地址页面跳转链接(携带预订单号)
  840. pagesUrl.value =
  841. "/pages/users/user_address_list/index?preOrderNo=" + preOrderNo.value;
  842. };
  843. // 联系人输入事件(保存联系人)
  844. const realName = (e) => {
  845. contacts.value = e.detail.value;
  846. };
  847. // 联系人电话输入事件(保存电话)
  848. const phone = (e) => {
  849. contactsTel.value = e.detail.value;
  850. };
  851. // 创建订单并发起支付
  852. const payment = (data) => {
  853. // 调用创建订单API
  854. orderCreate(data)
  855. .then((res) => {
  856. appStore.SET_CART_REFRESH(true);
  857. // 订单创建成功
  858. // 调用支付流程,传入订单号和成功提示
  859. getOrderPay(res.data.orderNo, "支付成功");
  860. })
  861. .catch((err) => {
  862. // 订单创建失败
  863. console.error("payment error", err); // 打印错误
  864. uni.hideLoading(); // 隐藏加载中
  865. Toast({
  866. title: err,
  867. }); // 提示错误
  868. });
  869. };
  870. // 处理支付流程(根据支付类型发起支付并处理结果)
  871. const getOrderPay = async (orderNo, message) => {
  872. // 支付结果页地址(携带订单号)
  873. const goPages = "/pages/order_pay_status/index?order_id=" + orderNo;
  874. try {
  875. // 调用微信支付配置API(获取支付参数)
  876. // const res = await wechatOrderPay({
  877. // mallType: orderInfoVo.value.mallType,
  878. // orderNo: orderNo,
  879. // // payChannel: payChannel.value,
  880. // payChannel: userSelectPayTypeItem.value.payChannel,
  881. // payType: payType.value,
  882. // scene: appStore.productTypeComputed === "normal" ? 0 : 1177, // 下单时小程序的场景值
  883. // });
  884. // console.log("res-------------", res.data);
  885. switch (payType.value) {
  886. case "alipay":
  887. // 发起支付宝支付
  888. const result = await submitPayment({
  889. type: res.data.payType, // 支付类型
  890. orderInfo: res.data.alipayRequest, // 支付宝支付参数
  891. });
  892. console.log("result", result); // 打印支付结果
  893. // 失败提示信息(默认"支付失败")
  894. let failMsg = result?.message || paymentConfig.PAYMENT_STATUS.FAIL;
  895. // 根据支付结果处理
  896. if (result.status === paymentConfig.PAYMENT_STATUS.SUCCESS) {
  897. // 支付成功:查询后端支付状态
  898. const params = {
  899. orderNo: orderNo,
  900. payType: "alipay",
  901. };
  902. console.log("进入成功判断", params);
  903. const res = await alipayPaymentResult(params); // 调用查询接口
  904. console.log("alipayPaymentResult", res);
  905. // 提示成功并跳转到结果页
  906. return Toast(
  907. {
  908. title: paymentConfig.PAYMENT_STATUS.SUCCESS,
  909. icon: "success",
  910. },
  911. {
  912. tab: 4,
  913. url: goPages,
  914. }
  915. );
  916. } else if (result.status === paymentConfig.PAYMENT_STATUS.FAIL) {
  917. // 支付失败:提示并跳转
  918. return Toast(
  919. {
  920. title: paymentConfig.PAYMENT_STATUS.FAIL,
  921. },
  922. {
  923. tab: 5,
  924. url: `${goPages}&msg=${failMsg}`,
  925. }
  926. );
  927. } else if (result.status === paymentConfig.PAYMENT_STATUS.CANCEL) {
  928. // 支付取消:提示并跳转
  929. return Toast(
  930. {
  931. title: paymentConfig.PAYMENT_STATUS.CANCEL,
  932. },
  933. {
  934. tab: 5,
  935. url: `${goPages}&msg=${paymentConfig.PAYMENT_STATUS.CANCEL}`,
  936. }
  937. );
  938. }
  939. break;
  940. case "yue":
  941. // 余额支付:直接提示成功并跳转
  942. console.log("余额支付");
  943. return Toast(
  944. {
  945. title: message,
  946. },
  947. {
  948. tab: 5,
  949. url: goPages + "&status=1",
  950. }
  951. );
  952. break;
  953. case "weixin": {
  954. try {
  955. await wechatPaymentRef.value.createUniPay({
  956. amount: Number(orderInfoVo.value.payFee) * 100,
  957. description: `商品(¥${orderInfoVo.value.payFee})`,
  958. openId: appStore.$userInfo.openId,
  959. orderNo: orderNo,
  960. orderPrefix: "SHOP", // 订单号前缀(与公共组件generateCustomId匹配)
  961. /**
  962. * 回调2:支付成功(核心逻辑)
  963. * 作用:通知后端标记用户为SVIP,刷新用户状态
  964. */
  965. onUniPaySuccess: async (payStatusRes) => {
  966. try {
  967. return Toast(
  968. {
  969. title: "支付成功",
  970. icon: "success",
  971. },
  972. {
  973. tab: 4,
  974. url: goPages,
  975. }
  976. );
  977. } catch (err) {
  978. console.error("支付失败:", err);
  979. uni.showToast({ title: "支付失败,请重试", icon: "none" });
  980. }
  981. },
  982. onUniPayCancel: () => {
  983. uni.showToast({ title: "用户取消支付", icon: "none" });
  984. return Toast(
  985. { title: WX_PAY_STATUS.CANCEL },
  986. {
  987. tab: 5,
  988. url: `${goPages}&msg=${WX_PAY_STATUS.CANCEL}`,
  989. }
  990. );
  991. },
  992. onUniPayFail: (err) => {
  993. uni.showToast({ title: "支付失败,请重试", icon: "none" });
  994. return Toast(
  995. { title: WX_PAY_STATUS.FAIL },
  996. {
  997. tab: 5,
  998. url: `${goPages}&msg=${errMsg || WX_PAY_STATUS.FAIL}`,
  999. }
  1000. );
  1001. },
  1002. });
  1003. uni.hideLoading();
  1004. } catch (wxErr) {
  1005. uni.hideLoading();
  1006. const errMsg = wxErr?.errMsg || "";
  1007. if (errMsg.includes("cancel") || errMsg.includes("取消")) {
  1008. return Toast(
  1009. { title: WX_PAY_STATUS.CANCEL },
  1010. { tab: 5, url: `${goPages}&msg=${WX_PAY_STATUS.CANCEL}` }
  1011. );
  1012. }
  1013. return Toast(
  1014. { title: WX_PAY_STATUS.FAIL },
  1015. { tab: 5, url: `${goPages}&msg=${errMsg || WX_PAY_STATUS.FAIL}` }
  1016. );
  1017. }
  1018. }
  1019. }
  1020. uni.hideLoading(); // 隐藏加载中
  1021. } catch (error) {
  1022. // 支付过程出错
  1023. console.error("getOrderPay error", error, typeof error);
  1024. let msg = "";
  1025. // 处理错误信息
  1026. if (typeof error === "string") {
  1027. msg = error;
  1028. } else if (typeof error === "object" && error.message) {
  1029. msg = error.message;
  1030. } else {
  1031. msg = "支付失败,请稍后再试";
  1032. }
  1033. uni.hideLoading(); // 隐藏加载中
  1034. // 跳转到结果页并携带错误信息
  1035. uni.navigateTo({
  1036. url: `/pages/order_pay_status/index?order_id=${orderNo}&msg=${msg}`,
  1037. });
  1038. return Toast({
  1039. title: msg,
  1040. }); // 提示错误
  1041. }
  1042. };
  1043. function modalConfirm() {
  1044. showModal.value = false;
  1045. const webviewPageUrl = `/pages/webview/index?path=/pages/users/vault/rechargeRmb`;
  1046. uni.navigateTo({
  1047. url: webviewPageUrl,
  1048. fail: (err) => {
  1049. console.error("跳转到webview页面失败:", err);
  1050. uni.showToast({
  1051. title: "跳转失败,请重试",
  1052. icon: "none",
  1053. duration: 1500,
  1054. });
  1055. },
  1056. });
  1057. }
  1058. const SubOrder = async (e) => {
  1059. console.log("SubOrder", payType.value);
  1060. // return;
  1061. // if (payType.value == "alipay") {
  1062. // return Toast({ title: "暂不支持支付宝支付,请使用余额支付" });
  1063. // }
  1064. let data = {}; // 订单提交数据
  1065. // 验证:必须选择支付方式
  1066. if (!payType.value || !userSelectPayTypeItem.value)
  1067. return Toast({
  1068. title: "请选择支付方式",
  1069. });
  1070. // 验证:快递配送时必须选择地址
  1071. if (!address.value.addressId && !shippingType.value) {
  1072. return Toast({
  1073. title: "请选择收货地址",
  1074. });
  1075. }
  1076. // #ifdef APP
  1077. try {
  1078. const channels = await getAvailableChannels();
  1079. if (payType.value === "alipay" && !channels.includes("alipay")) {
  1080. return Toast({
  1081. title: "设备不支持支付宝支付",
  1082. });
  1083. }
  1084. } catch (error) {
  1085. console.error("获取支付渠道失败", error);
  1086. return Toast({
  1087. title: "获取支付渠道失败",
  1088. });
  1089. }
  1090. // #endif
  1091. // 构造订单提交数据
  1092. data = {
  1093. mallType: orderInfoVo.value.mallType,
  1094. realName: contacts.value,
  1095. phone: contactsTel.value,
  1096. addressId: address.value.addressId,
  1097. couponId: couponId.value,
  1098. payType: payType.value,
  1099. useIntegral: useIntegral.value,
  1100. preOrderNo: preOrderNo.value,
  1101. mark: mark.value,
  1102. // storeId: system_store.value.id || 0,
  1103. shippingType: util.$h.Add(shippingType.value, 1),
  1104. // payChannel: payChannel.value || "weixinh5",
  1105. payChannel: userSelectPayTypeItem.value.payChannel,
  1106. };
  1107. console.log(" data.payType", data.payType);
  1108. // 验证:贝币支付时余额是否充足
  1109. if (
  1110. orderInfoVo.value.mallType === 1 &&
  1111. Number(orderInfoVo.value.proTotalFee) > orderInfoVo.value.userIntegral
  1112. ) {
  1113. return Toast({
  1114. title: "贝币余额不足!",
  1115. });
  1116. }
  1117. // 验证:余额支付时余额是否充足
  1118. else if (
  1119. data.payType == "yue" &&
  1120. parseFloat(appStore.$userInfo.nowMoney) <
  1121. parseFloat(orderInfoVo.value.payFee)
  1122. ) {
  1123. // 余额不足
  1124. showModal.value = true;
  1125. return;
  1126. }
  1127. // 验证余料是否充足(普通商城且有余料余量时校验)
  1128. // else if (orderInfoVo.value.mallType === 0 && metalTypeMap[metalType.value].balance > 0) {
  1129. // const totalNeedWeight = cartInfo.value.reduce((sum, item) => {
  1130. // return sum + Number(item.weight || 0) * Number(item.payNum || item.cartNum || 1);
  1131. // }, 0);
  1132. // if (totalNeedWeight > metalTypeMap[metalType.value].balance) {
  1133. // return Toast({
  1134. // title: `${metalTypeMap[metalType.value].name}余料不足,当前可用 ${metalTypeMap[metalType.value].balance}g,订单需要 ${totalNeedWeight.toFixed(2)}g`,
  1135. // });
  1136. // }
  1137. // }
  1138. uni.showLoading({
  1139. title: "订单支付中",
  1140. });
  1141. // 发起支付
  1142. payment(data);
  1143. };
  1144. </script>
  1145. <style>
  1146. page {
  1147. background: #f9f7f0;
  1148. }
  1149. </style>
  1150. <style lang="scss" scoped>
  1151. .order-submission {
  1152. .order-submission-box {
  1153. padding: 16rpx;
  1154. }
  1155. .line {
  1156. width: 100%;
  1157. height: 3rpx;
  1158. image {
  1159. width: 100%;
  1160. height: 100%;
  1161. display: block;
  1162. }
  1163. }
  1164. .goods {
  1165. background-color: #fff;
  1166. padding: 16rpx;
  1167. border-radius: 16rpx;
  1168. margin-top: 20rpx;
  1169. }
  1170. .allAddress {
  1171. .nav {
  1172. width: 100%;
  1173. margin: 0 auto;
  1174. .item {
  1175. width: 334rpx;
  1176. &.on {
  1177. position: relative;
  1178. width: 230rpx;
  1179. &::before {
  1180. position: absolute;
  1181. bottom: 0;
  1182. content: "快递配送";
  1183. font-size: 28rpx;
  1184. display: block;
  1185. height: 0;
  1186. width: 336rpx;
  1187. border-width: 0 20rpx 80rpx 0;
  1188. border-style: none solid solid;
  1189. border-color: transparent transparent #fff;
  1190. z-index: 2;
  1191. border-radius: 14rpx 36rpx 0 0;
  1192. text-align: center;
  1193. line-height: 80rpx;
  1194. }
  1195. }
  1196. &:nth-of-type(2).on::before {
  1197. content: "到店自提";
  1198. border-width: 0 0 80rpx 20rpx;
  1199. border-radius: 36rpx 14rpx 0 0;
  1200. }
  1201. &.on2 {
  1202. position: relative;
  1203. &::before {
  1204. position: absolute;
  1205. bottom: 0;
  1206. content: "到店自提";
  1207. font-size: 28rpx;
  1208. display: block;
  1209. height: 0;
  1210. width: 401rpx;
  1211. border-width: 0 0 60rpx 60rpx;
  1212. border-style: none solid solid;
  1213. border-color: transparent transparent #f7c1bd;
  1214. border-radius: 36rpx 14rpx 0 0;
  1215. text-align: center;
  1216. line-height: 60rpx;
  1217. }
  1218. }
  1219. &:nth-of-type(1).on2::before {
  1220. content: "快递配送";
  1221. border-width: 0 60rpx 60rpx 0;
  1222. border-radius: 14rpx 36rpx 0 0;
  1223. }
  1224. }
  1225. }
  1226. .address {
  1227. width: 100%;
  1228. margin: 0 auto;
  1229. padding: 20rpx 20rpx 16rpx;
  1230. background-color: #fff;
  1231. box-sizing: border-box;
  1232. .addressCon {
  1233. width: 100%;
  1234. font-size: 26rpx;
  1235. color: #666;
  1236. .selected-address {
  1237. display: flex;
  1238. justify-content: flex-start;
  1239. align-items: start;
  1240. .default {
  1241. min-width: 64rpx;
  1242. padding: 0 8rpx;
  1243. height: 40rpx;
  1244. line-height: 40rpx;
  1245. text-align: center;
  1246. color: #333;
  1247. background-color: #f8c008;
  1248. border-radius: 8rpx;
  1249. font-size: 24rpx;
  1250. margin-right: 8rpx;
  1251. position: relative;
  1252. top: 5rpx;
  1253. }
  1254. }
  1255. .name {
  1256. font-size: 28rpx;
  1257. color: #666;
  1258. margin-top: 16rpx;
  1259. line-height: 44rpx;
  1260. .phone {
  1261. margin-left: 50rpx;
  1262. }
  1263. }
  1264. .default {
  1265. margin-right: 12rpx;
  1266. }
  1267. .setaddress {
  1268. color: #333;
  1269. font-size: 28rpx;
  1270. }
  1271. }
  1272. .iconfont {
  1273. font-size: 35rpx;
  1274. color: #707070;
  1275. }
  1276. }
  1277. .line {
  1278. width: 100%;
  1279. margin: 0 auto;
  1280. }
  1281. }
  1282. .pay-container {
  1283. .zf-box {
  1284. font-size: 32rpx;
  1285. color: #333;
  1286. font-weight: bold;
  1287. line-height: 48rpx;
  1288. margin: 16rpx 0;
  1289. }
  1290. .list {
  1291. background-color: #fff;
  1292. border-radius: 16rpx;
  1293. .payItem {
  1294. border-radius: 14rpx;
  1295. width: 100%;
  1296. font-size: 28rpx;
  1297. color: #282828;
  1298. height: 108rpx;
  1299. display: flex;
  1300. justify-content: space-between;
  1301. align-items: center;
  1302. padding: 0 16rpx;
  1303. .name {
  1304. text-align: center;
  1305. justify-content: flex-start;
  1306. .pay-icon {
  1307. width: 60rpx;
  1308. height: 60rpx;
  1309. margin-right: 10rpx;
  1310. }
  1311. }
  1312. .tip {
  1313. font-size: 24rpx;
  1314. color: #f8c008;
  1315. display: flex;
  1316. align-items: center;
  1317. justify-content: end;
  1318. .select-icon {
  1319. width: 28rpx;
  1320. height: 28rpx;
  1321. margin-left: 20rpx;
  1322. }
  1323. }
  1324. }
  1325. }
  1326. }
  1327. .wrapper {
  1328. background-color: #fff;
  1329. margin-top: 15rpx;
  1330. border-radius: 16rpx;
  1331. .item {
  1332. padding: 16rpx;
  1333. font-size: 28rpx;
  1334. color: #333333;
  1335. font-weight: bold;
  1336. // border-bottom: 1px solid #f5f5f5;
  1337. .zf-box {
  1338. display: flex;
  1339. justify-content: space-between;
  1340. align-items: center;
  1341. }
  1342. .swicth-box {
  1343. display: flex;
  1344. justify-content: space-between;
  1345. align-items: center;
  1346. border: 2rpx solid #eee;
  1347. height: 86rpx;
  1348. font-size: 28rpx;
  1349. padding: 0 0 0 12%;
  1350. box-sizing: border-box;
  1351. margin: 20rpx 0;
  1352. border-radius: 14rpx;
  1353. .lable-box {
  1354. display: flex;
  1355. align-items: center;
  1356. .iconfont {
  1357. width: 44rpx;
  1358. height: 44rpx;
  1359. border-radius: 50%;
  1360. text-align: center;
  1361. line-height: 44rpx;
  1362. background-color: #fe960f;
  1363. color: #fff;
  1364. font-size: 30rpx;
  1365. margin-right: 15rpx;
  1366. &.icon-touzijintiao1 {
  1367. background-color: #f0cb88;
  1368. }
  1369. }
  1370. .lable-icon {
  1371. display: flex;
  1372. flex-direction: column;
  1373. justify-content: center;
  1374. }
  1375. .value {
  1376. font-size: 20rpx;
  1377. color: #fe960f;
  1378. }
  1379. }
  1380. }
  1381. .discount {
  1382. font-size: 28rpx;
  1383. color: #333;
  1384. .iconfont {
  1385. color: #515151;
  1386. font-size: 30rpx;
  1387. margin-left: 15rpx;
  1388. }
  1389. .num {
  1390. font-size: 32rpx;
  1391. margin-right: 20rpx;
  1392. }
  1393. .placeholder {
  1394. color: #ccc;
  1395. }
  1396. }
  1397. .shipping {
  1398. font-size: 30rpx;
  1399. color: #999;
  1400. position: relative;
  1401. padding-right: 58rpx;
  1402. .iconfont {
  1403. font-size: 35rpx;
  1404. color: #707070;
  1405. position: absolute;
  1406. right: 0;
  1407. top: 50%;
  1408. transform: translateY(-50%);
  1409. margin-left: 30rpx;
  1410. }
  1411. }
  1412. textarea {
  1413. font-size: 28rpx;
  1414. background-color: #f9f7f0;
  1415. width: auto !important;
  1416. height: 264rpx;
  1417. border-radius: 16rpx;
  1418. margin-top: 16rpx;
  1419. padding: 16rpx;
  1420. box-sizing: border-box;
  1421. font-weight: 400;
  1422. }
  1423. .placeholder {
  1424. color: #999;
  1425. }
  1426. .list {
  1427. margin-top: 35rpx;
  1428. .payItem {
  1429. border: 1px solid #eee;
  1430. border-radius: 14rpx;
  1431. height: 86rpx;
  1432. width: 100%;
  1433. box-sizing: border-box;
  1434. margin-top: 20rpx;
  1435. font-size: 28rpx;
  1436. color: #282828;
  1437. &.on {
  1438. border-color: #fc5445;
  1439. color: $theme-color;
  1440. }
  1441. .name {
  1442. flex: 1;
  1443. // width: 50%;
  1444. text-align: center;
  1445. border-right: 1px solid #eee;
  1446. justify-content: flex-start;
  1447. padding: 0 0 0 12%;
  1448. .iconfont {
  1449. width: 44rpx;
  1450. height: 44rpx;
  1451. border-radius: 50%;
  1452. text-align: center;
  1453. line-height: 44rpx;
  1454. background-color: #fe960f;
  1455. color: #fff;
  1456. font-size: 30rpx;
  1457. margin-right: 15rpx;
  1458. &.icon-wechat {
  1459. background-color: #41b035;
  1460. }
  1461. &.icon-zhifubao {
  1462. background-color: #06b4fd;
  1463. }
  1464. }
  1465. }
  1466. .tip {
  1467. width: 49%;
  1468. text-align: center;
  1469. font-size: 26rpx;
  1470. color: #aaa;
  1471. }
  1472. }
  1473. }
  1474. }
  1475. }
  1476. .moneyList {
  1477. margin-top: 16rpx;
  1478. background-color: #fff;
  1479. padding: 16rpx;
  1480. border-radius: 16rpx;
  1481. .item {
  1482. font-size: 28rpx;
  1483. color: #282828;
  1484. & ~ .item {
  1485. margin-top: 20rpx;
  1486. }
  1487. .money {
  1488. color: #333;
  1489. font-weight: bold;
  1490. }
  1491. }
  1492. }
  1493. .kong {
  1494. height: calc(132rpx + constant(safe-area-inset-bottom));
  1495. height: calc(132rpx + env(safe-area-inset-bottom));
  1496. }
  1497. .footer {
  1498. display: flex;
  1499. align-items: center;
  1500. padding: 22rpx 32rpx calc(22rpx + constant(safe-area-inset-bottom));
  1501. padding: 22rpx 32rpx calc(22rpx + env(safe-area-inset-bottom));
  1502. position: fixed;
  1503. bottom: 0;
  1504. width: 100%;
  1505. background-color: #fff;
  1506. z-index: 100;
  1507. box-shadow: inset 0rpx 1rpx 0rpx 0rpx #f1f3f8;
  1508. .price {
  1509. font-size: 36rpx;
  1510. line-height: 44rpx;
  1511. font-weight: bold;
  1512. color: #fd5f3c;
  1513. }
  1514. .settlement {
  1515. font-size: 32rpx;
  1516. font-weight: bold;
  1517. color: #333;
  1518. width: 410rpx;
  1519. height: 88rpx;
  1520. background-color: #f8c008;
  1521. border-radius: 16rpx;
  1522. text-align: center;
  1523. line-height: 88rpx;
  1524. z-index: 100;
  1525. }
  1526. .transparent {
  1527. opacity: 0;
  1528. }
  1529. }
  1530. }
  1531. .line2 {
  1532. color: #333;
  1533. font-weight: bold;
  1534. font-size: 32rpx;
  1535. }
  1536. .textR {
  1537. text-align: right;
  1538. }
  1539. .line-item {
  1540. margin-top: 16rpx;
  1541. .item-label {
  1542. font-size: 28rpx;
  1543. line-height: 44rpx;
  1544. color: #333;
  1545. }
  1546. .discount {
  1547. font-size: 28rpx;
  1548. color: #333;
  1549. font-weight: bold;
  1550. display: flex;
  1551. align-items: center;
  1552. &.none {
  1553. color: #999;
  1554. font-weight: normal;
  1555. }
  1556. .rt-arr {
  1557. width: 32rpx;
  1558. height: 32rpx;
  1559. margin-left: 8rpx;
  1560. }
  1561. }
  1562. }
  1563. </style>