| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416 |
- <template>
- <view>
- <view class="order-submission">
- <view
- class="allAddress"
- :style="store_self_mention ? '' : 'padding-top:10rpx;'"
- >
- <view class="nav acea-row">
- <view
- class="item font-color"
- :class="shippingType == 0 ? 'on' : 'on2'"
- @tap="addressType(0)"
- v-if="store_self_mention"
- ></view>
- <!-- <view class="item font-color" :class="shippingType == 1 ? 'on' : 'on2'" @tap="addressType(1)"
- v-if="store_self_mention"></view> -->
- </view>
- <view
- class="address acea-row row-between-wrapper"
- @tap="onAddress"
- v-if="shippingType == 0"
- :style="
- store_self_mention
- ? ''
- : 'border-top-left-radius: 14rpx;border-top-right-radius: 14rpx;'
- "
- >
- <view class="addressCon" v-if="addressInfo.realName">
- <view class="name"
- >{{ addressInfo.realName }}
- <text class="phone">{{ addressInfo.phone }}</text>
- </view>
- <view class="acea-row">
- <text class="default font-color" v-if="addressInfo.isDefault"
- >[默认]</text
- >
- <text class="line2"
- >{{ addressInfo.province }}{{ addressInfo.city
- }}{{ addressInfo.district }}{{ addressInfo.detail }}</text
- >
- </view>
- </view>
- <view class="addressCon" v-else>
- <view class="setaddress">设置收货地址</view>
- </view>
- <view class="iconfont icon-jiantou"></view>
- </view>
- <view
- class="address acea-row row-between-wrapper"
- v-else
- @tap="showStoreList"
- >
- <block v-if="storeList.length > 0">
- <view class="addressCon">
- <view class="name"
- >{{ system_store.name }}
- <text class="phone">{{ system_store.phone }}</text>
- </view>
- <view class="line1">
- {{ system_store.address
- }}{{ ", " + system_store.detailedAddress }}
- </view>
- </view>
- <view class="iconfont icon-jiantou"></view>
- </block>
- <block v-else>
- <view>暂无门店信息</view>
- </block>
- </view>
- <view class="line">
- <image src="/static/images/line.jpg"></image>
- </view>
- </view>
- <view class="pad30">
- <orderGoods
- :mallType="orderInfoVo.mallType"
- :cartInfo="cartInfo"
- :orderProNum="orderProNum"
- ></orderGoods>
- <view class="wrapper borRadius14">
- <view
- class="item acea-row row-between-wrapper"
- @tap="couponTap"
- v-if="orderInfoVo.mallType === 0"
- >
- <view>优惠券</view>
- <view class="discount"
- >{{ couponTitle }}
- <text class="iconfont icon-jiantou"></text>
- </view>
- </view>
- <view class="item acea-row row-between-wrapper">
- <view>快递费用</view>
- <block v-if="orderInfoVo.mallType === 0">
- <view
- class="discount"
- v-if="
- parseFloat(orderInfoVo.freightFee) > 0 &&
- orderInfoVo.mallType === 0
- "
- >
- +¥{{ orderInfoVo.freightFee }}
- </view>
- <view class="discount" v-else>免运费</view>
- </block>
- <view class="discount" v-else>邮费到付</view>
- </view>
- <view class="item" v-if="textareaStatus">
- <view>备注信息</view>
- <textarea
- v-if="coupon.coupon === false"
- placeholder-class="placeholder"
- @input="bindHideKeyboard"
- value=""
- name="mark"
- placeholder="请添加备注(150字以内)"
- ></textarea>
- </view>
- </view>
- <!-- 是否使用余料支付 -->
- <view class="wrapper borRadius14">
- <view class="item">
- <view class="zf-box" v-if="orderInfoVo.mallType == 0">
- <view>余料支付方式</view>
- </view>
- <view class="swicth-box" v-if="orderInfoVo.mallType == 0">
- <view class="lable-box">
- <view class="iconfont icon-touzijintiao1"></view>
- <view class="lable-icon">
- <view class="lable">余料支付</view>
- <view class="value">
- 可用余料:
- {{ metalTypeMap[metalType].name }}
- :{{ metalTypeMap[metalType].balance || 0 }}g
- </view>
- </view>
- </view>
- <!-- <switch
- color="#FFCC33"
- style="transform: scale(0.7)"
- @change="useGoldPay"
- ></switch> -->
- </view>
- <view class="zf-box">
- <view>工费支付方式</view>
- </view>
- <view class="list">
- <view
- v-for="(item, index) in avaliablePayments"
- class="payItem acea-row row-middle"
- :class="active == index ? 'on' : ''"
- @tap="payItem(index)"
- :key="index"
- >
- <view class="name acea-row row-center-wrapper">
- <view
- class="iconfont animated"
- :class="
- item.icon +
- ' ' +
- (animated == true && active == index ? 'bounceIn' : '')
- "
- >
- </view>
- {{ item.name }}
- </view>
- <view class="tip">{{ item.title }}</view>
- </view>
- </view>
- </view>
- </view>
- <view class="moneyList borRadius14">
- <view class="item acea-row row-between-wrapper">
- <view>商品总价:</view>
- <view v-if="orderInfoVo.mallType === 0" class="money">
- ¥{{ orderInfoVo.payFee || 0 }}
- </view>
- <view v-else class="money">
- 贝币: {{ Number(orderInfoVo.proTotalFee) || 0 }}
- </view>
- </view>
- <view
- class="item acea-row row-between-wrapper"
- v-if="orderInfoVo.couponFee > 0"
- >
- <view>优惠券抵扣:</view>
- <view class="money">-¥{{ orderInfoVo.couponFee }}</view>
- </view>
- <!-- <view
- class="item acea-row row-between-wrapper"
- v-if="orderInfoVo.deductionPrice > 0"
- >
- <view>积分抵扣:</view>
- <view class="money">-¥{{ orderInfoVo.deductionPrice }}</view>
- </view> -->
- <view
- class="item acea-row row-between-wrapper"
- v-if="orderInfoVo.mallType === 0"
- >
- <view>工费:</view>
- <view class="money">+¥{{ orderInfoVo.totalLaborCost }}</view>
- </view>
- <view
- class="item acea-row row-between-wrapper"
- v-if="
- orderInfoVo.mallType === 0 && orderInfoVo?.totalAdditionalAmount
- "
- >
- <view>附加费:</view>
- <view class="money"
- >+¥{{ orderInfoVo.totalAdditionalAmount }}</view
- >
- </view>
- <view
- class="item acea-row row-between-wrapper"
- v-if="orderInfoVo.freightFee > 0"
- >
- <view>运费:</view>
- <view class="money">+¥{{ orderInfoVo.freightFee }}</view>
- </view>
- <view
- v-if="
- orderInfoVo.mallType === 0 &&
- Number(orderInfoVo.vipLevelDis) !== 0
- "
- class="item acea-row row-between-wrapper"
- >
- <view>会员折扣:</view>
- <view class="money">-¥{{ orderInfoVo.vipLevelDis }}</view>
- </view>
- </view>
- <view style="height: 120rpx"></view>
- </view>
- <view class="footer acea-row row-between-wrapper">
- <view>
- 合计:
- <text class="font-color" v-if="orderInfoVo.mallType === 0">
- ¥{{ orderInfoVo.payFee || 0 }}
- </text>
- <text class="font-color" v-else>
- {{ Number(orderInfoVo.proTotalFee) || 0 }}
- </text>
- </view>
- <view class="settlement" style="z-index: 100" @tap="SubOrder">
- 立即结算
- </view>
- </view>
- </view>
- <couponListWindow
- :coupon="coupon"
- @close="closeCouponPopup"
- :showPopup="showCouponPopup"
- :openType="openType"
- @ChangCoupons="ChangCoupons"
- :orderShow="orderShow"
- ></couponListWindow>
- <addressWindow
- ref="addressWindowRef"
- @changeTextareaStatus="changeTextareaStatus"
- :address="address"
- :pagesUrl="pagesUrl"
- @OnDefaultAddress="OnDefaultAddress"
- @OnChangeAddress="OnChangeAddress"
- @changeClose="changeClose"
- />
- <!-- 余额不足modal -->
- <up-modal
- :showCancelButton="true"
- :show="showModal"
- title="余额不足"
- confirmText="去充值"
- @cancel="showModal = false"
- @confirm="modalConfirm"
- ></up-modal>
- </view>
- </template>
- <script setup>
- // 导入UniApp页面加载生命周期函数
- import { onLoad } from "@dcloudio/uni-app";
- // 导入Vue3响应式API(ref创建响应式变量、computed计算属性等)
- import { ref, computed, watch, onMounted, nextTick } from "vue";
- // 导入应用状态管理(全局状态,如登录状态、用户信息等)
- import { useAppStore } from "@/stores/app.js";
- // 导入提示框工具(封装的toast提示函数)
- import { useToast } from "@/hooks/useToast.js";
- // 导入支付相关工具(封装的支付逻辑,如提交支付、验证支付渠道等)
- import { usePayment } from "@/hooks/usePayment.js";
- // 导入订单相关API接口(优惠券、创建订单、计算价格等接口)
- import {
- getCouponsOrderPrice, // 获取可用优惠券接口
- orderCreate, // 创建订单接口
- postOrderComputed, // 计算订单价格接口
- wechatOrderPay, // 微信支付接口
- wechatQueryPayResult, // 微信支付结果查询接口
- loadPreOrderApi, // 加载预订单接口
- alipayPaymentResult, // 支付宝支付结果查询接口
- } from "@/api/order.js";
- // 导入用户地址详情API接口
- import { getAddressDetail } from "@/api/user.js";
- // 导入门店列表API接口
- import { storeListApi } from "@/api/store.js";
- // 导入工具类(封装的通用工具函数)
- import util from "@/utils/util";
- // 导入优惠券弹窗组件
- import couponListWindow from "@/components/couponListWindow";
- // 导入地址选择组件
- import addressWindow from "@/components/addressWindow";
- // 导入订单商品列表组件
- import orderGoods from "@/components/orderGoods";
- // 导入登录工具(未登录时跳转登录页)
- import { toLogin } from "@/libs/login.js";
- import useRealGoldPrice from "@/hooks/useRealGoldPrice";
- const { realGoldprice, fetchGoldPrice } = useRealGoldPrice("RTJ_Au");
- // 初始化应用状态管理实例(用于获取全局状态)
- const appStore = useAppStore();
- // 初始化提示框工具(获取toast方法)
- const { Toast } = useToast();
- // 初始化支付工具(获取支付相关方法)
- const { submitPayment, paymentConfig, getAvailableChannels } = usePayment();
- // 响应式变量:订单页面标识(用于优惠券组件,控制不显示tab切换)
- const orderShow = ref("orderShow");
- // 响应式变量:控制备注输入框是否显示
- const textareaStatus = ref(true);
- // 响应式变量:支付方式列表(包含支付宝、微信、余额等支付方式配置)
- const payments = ref([
- // {
- // name: "支付宝支付", // 支付方式名称
- // icon: "icon-zhifubao", // 图标类名
- // value: "alipay", // 支付标识值
- // title: "支付宝快捷支付", // 支付说明
- // payType: "alipay", // 支付类型
- // payStatus: 0, // 支付状态(1-可用,0-不可用)
- // payChannel: "appAliPay",
- // },
- // {
- // name: "微信支付",
- // icon: "icon-wechat",
- // value: "weixin",
- // title: "微信快捷支付",
- // payType: "weixin",
- // payStatus: 0,
- // payChannel: "weixinApp",
- // },
- {
- name: "余额支付",
- icon: "icon-balance",
- value: "yue",
- title: "可用余额:",
- payType: "yue",
- payStatus: 1,
- payChannel: "weixinh5",
- },
- // {
- // name: "贝币支付",
- // icon: "icon-balance",
- // value: "yue",
- // title: "可用贝币:",
- // payType: "yue",
- // payStatus: 0,
- // payChannel: "weixinh5",
- // },
- ]);
- // 计算属性:过滤出可用的支付方式(只保留payStatus为1的项)
- const avaliablePayments = computed(() => {
- console.log(payments.value)
- return payments.value.filter((item) => item.payStatus === 1);
- });
- console.log(avaliablePayments)
- // 响应式变量:当前选中的支付方式(默认余额支付)
- const payType = ref("yue");
- // 响应式变量:优惠券打开方式(1表示"使用"场景)
- const openType = ref(1);
- // 响应式变量:当前选中的支付方式索引(用于UI高亮)
- const active = ref(0);
- // 响应式变量:优惠券相关配置(控制弹窗显示、列表数据等)
- const coupon = ref({
- coupon: false, // 是否显示优惠券弹窗
- list: [], // 优惠券列表数据
- statusTile: "立即使用", // 按钮文字
- });
- // 响应式变量:地址相关配置(控制弹窗显示、选中地址ID等)
- const address = ref({
- address: false,
- addressId: 0,
- }); // 地址组件
- const addressInfo = ref({}); // 地址信息
- const addressId = ref(0); // 地址id
- const couponId = ref(0); // 优惠券id
- const userInfo = ref({}); // 用户信息
- const mark = ref(""); // 备注信息
- const couponTitle = ref("请选择"); // 优惠券
- const useIntegral = ref(false); // 是否使用积分
- const status = ref(0);
- // 响应式变量:是否有地址(用于判断是否需要提示用户添加地址)
- const is_address = ref(false);
- // 响应式变量:支付页面刷新标识(修复支付页面隐藏后刷新问题)
- const toPay = ref(false);
- // 响应式变量:配送方式(0-快递配送,1-到店自提)
- const shippingType = ref(0);
- // 响应式变量:选中的门店信息(自提时使用)
- const system_store = ref({});
- const contacts = ref("");
- // 响应式变量:联系人电话(自提时可能需要)
- const contactsTel = ref("");
- const storeList = ref([]);
- // 响应式变量:是否支持门店自提(1-支持,0-不支持)
- const store_self_mention = ref(0);
- // 响应式变量:购物车商品信息(订单中的商品列表)
- const cartInfo = ref([]);
- const animated = ref(false);
- // 响应式变量:订单总价
- const totalPrice = ref(0);
- const pagesUrl = ref("");
- // const usableCoupon = ref({});
- const payChannel = ref("");
- // 响应式变量:订单信息详情(包含商品总价、运费、折扣等)
- const orderInfoVo = ref({});
- // 响应式变量:地址列表数据(用于地址选择组件)
- const addressList = ref([]);
- // 响应式变量:订单商品总数
- const orderProNum = ref(0);
- const preOrderNo = ref(""); // 预下单订单号
- const addressWindowRef = ref(null); // 地址组件引用
- const showCouponPopup = ref(false); // 显示优惠券弹窗
- const showModal = ref(false);
- const userSelectPayTypeItem = ref(payments.value[0]);
- // 监听 isLogin
- watch(
- () => appStore.isLogin, // 监听的数据源:全局登录状态
- (newV) => {
- // newV是登录状态的新值(true/false)
- if (newV) {
- // 若已登录
- getloadPreOrder(); // 加载预订单信息
- this.getaddressInfo(); // 获取地址信息(this指向当前组件实例)
- }
- },
- { deep: true } // 深度监听(确保复杂数据类型变化也能触发)
- );
- // 商品总价
- // 页面加载时触发的生命周期函数
- onLoad((options) => {
- // options是页面跳转时传递的参数
- console.log(appStore.userInfo); // 打印用户信息(调试用)
- // #ifdef APP
- // 支付宝沙箱模式(测试环境用,正式环境注释)
- // var EnvUtils = plus.android.importClass("com.alipay.sdk.app.EnvUtils");
- // EnvUtils.setEnv(EnvUtils.EnvEnum.SANDBOX);
- // #endif
- // #ifdef H5
- payChannel.value = "weixinh5"; // H5环境支付渠道为微信H5支付
- // #endif
- // #ifdef APP
- payChannel.value = "appAliPay"; // APP环境支付渠道为支付宝APP支付
- // #endif
- // 从参数中获取预订单号(若没有则默认为0)
- preOrderNo.value = options.preOrderNo || 0;
- // 从参数中获取地址ID(若没有则默认为0)
- addressId.value = options.addressId || 0;
- // 从参数中获取是否有地址的标识
- is_address.value = options.is_address ? true : false;
- // 若已登录,则加载预订单信息;否则跳转到登录页
- if (appStore.isLogin) {
- getloadPreOrder(); // 加载预订单
- } else {
- toLogin(); // 跳登录
- }
- });
- // 组件挂载后触发的生命周期函数(DOM渲染完成后)
- onMounted(() => {
- textareaStatus.value = true; // 默认显示备注输入框
- // 若已登录且非支付页面,则获取地址信息(注释掉的逻辑,预留)
- if (appStore.isLogin && !toPay.value) {
- //this.getaddressInfo();
- }
- // 监听全局事件"handClick"(用于接收门店选择结果)
- uni.$on("handClick", (res) => {
- if (res) {
- // 若有结果
- system_store.value = res.address; // 更新选中的门店信息
- }
- // 清除监听(避免重复触发)
- uni.$off("handClick");
- });
- });
- // 是否选择余料支付
- const useGoldPay = (e) => {
- computedPrice();
- };
- const metalTypeMap = {
- 1: { name: "黄金", balance: 0 },
- 2: { name: "铂金", balance: 0 },
- 3: { name: "白银", balance: 0 },
- };
- const metalType = ref(1);
- // 加载预订单信息(核心函数:初始化订单数据)
- const getloadPreOrder = () => {
- console.log("preOrderNo.value", preOrderNo.value);
- // 调用加载预订单API,传入预订单号
- loadPreOrderApi(preOrderNo.value)
- .then((res) => {
- metalTypeMap[1].balance = res.data.auBalance || 0;
- metalTypeMap[2].balance = res.data.ptBalance || 0;
- metalTypeMap[3].balance = res.data.agBalance || 0;
- metalType.value = res.data.metalType;
- // 接口成功回调
- let orderInfoVoData = res.data.orderInfoVo; // 订单基本信息
- orderInfoVo.value = orderInfoVoData; // 保存订单信息
- cartInfo.value = orderInfoVoData.orderDetailList; // 保存商品列表
- orderProNum.value = orderInfoVoData.orderProNum; // 保存商品总数
- // 设置地址ID(优先用参数传入的,没有则用订单默认的)
- address.value.addressId = addressId.value
- ? addressId.value
- : orderInfoVoData.addressId;
- // 判断是否支持门店自提(根据接口返回和全局状态)
- store_self_mention.value =
- res.data.storeSelfMention == "true" && // 接口返回支持自提
- appStore.productTypeComputed === "normal" // 全局状态为普通商品
- ? true
- : false;
- // 根据商城类型设置是否使用积分(mallType=1时默认使用)
- useIntegral.value = orderInfoVo.value.mallType === 1;
- // 根据商城类型设置默认支付方式(mallType=1时用贝币支付)
- // payType.value = orderInfoVo.value.mallType === 1 ? "yue" : "alipay";
- payType.value = "yue";
- // 动态更新支付方式状态(根据接口返回的配置)
- payments.value.forEach((item) => {
- if (item.name === "余额支付") {
- // 余额支付:显示可用余额,状态由接口返回的yuePayStatus决定
- item.title = "可用余额: " + orderInfoVoData.userBalance;
- item.payStatus = parseInt(res.data.yuePayStatus) === 1 ? 1 : 2;
- } else if (item.payType === "weixin") {
- // 微信支付:状态由接口返回的payWeixinOpen决定
- item.payStatus = parseInt(res.data.payWeixinOpen) === 1 ? 1 : 0;
- }
- // 贝币支付:仅在mallType=1时可用
- if (orderInfoVo.value.mallType === 1) {
- item.title = "可用贝币: " + orderInfoVoData.userIntegral;
- item.payStatus = item.name === "贝币支付" ? 1 : 0;
- } else {
- item.payStatus = item.name === "贝币支付" ? 0 : 1;
- }
- });
- if (addressId.value) {
- computedPrice();
- }
- // 调用子页面方法授权后执行获取地址列表
- nextTick(() => {
- addressWindowRef.value.fetchAddressList();
- });
- })
- .catch((err) => {
- // 接口失败回调
- console.error(err); // 打印错误
- uni.navigateTo({ url: "/pages/order_list/index" }); // 跳转到订单列表
- Toast({ title: err }); // 提示错误信息
- });
- };
- // 授权回调事件(用户授权后触发,预留)
- const onLoadFun = () => {
- //this.getaddressInfo(); // 获取地址信息(注释掉的逻辑)
- // 调用子组件方法获取地址列表(注释掉的逻辑)
- // this.$scope.selectComponent('#address-window').getAddressList();
- };
- // 获取门店列表数据(自提时使用)
- const getList = () => {
- // 从本地存储获取用户经纬度(用于附近门店查询)
- let longitude = uni.getStorageSync("user_longitude");
- let latitude = uni.getStorageSync("user_latitude");
- // 构造请求参数
- let data = {
- latitude: latitude, // 纬度
- longitude: longitude, // 经度
- page: 1, // 页码
- limit: 10, // 每页条数
- };
- // 调用门店列表API
- storeListApi(data)
- .then((res) => {
- // 成功回调
- let list = res.data.list || []; // 门店列表
- storeList.value = list; // 保存门店列表
- system_store.value = list[0]; // 默认选中第一个门店
- })
- .catch((err) => {
- // 失败回调
- Toast({ title: err }); // 提示错误
- });
- };
- // 关闭地址弹窗
- const changeClose = () => {
- address.value.address = false; // 隐藏地址弹窗
- };
- // 跳转门店列表页面(自提时选择门店)
- const showStoreList = () => {
- // 若有门店列表数据,则跳转到门店详情页
- if (storeList.value.length > 0) {
- uni.navigateTo({
- url: "/pages/users/goods_details_store/index",
- });
- }
- };
- // 计算订单价格
- function computedPrice() {
- let shippingTypeValue = shippingType.value;
- postOrderComputed({
- mallType: orderInfoVo.value.mallType, // 商城类型
- addressId: address.value.addressId, // 地址ID
- useIntegral: useIntegral.value ? true : false, // 是否用积分
- couponId: couponId.value, // 优惠券ID
- shippingType: parseInt(shippingTypeValue) + 1, // 配送方式(后端要求+1)
- preOrderNo: preOrderNo.value, // 预订单号
- goldNum: appStore.userInfo.goldBalance, // 余料数量
- })
- .then((res) => {
- // 成功回调
- let data = res.data; // 计算后的价格数据
- // 更新订单费用信息
- orderInfoVo.value.couponFee = data.couponFee; // 优惠券抵扣
- orderInfoVo.value.userIntegral = data.surplusIntegral; // 剩余积分
- orderInfoVo.value.deductionPrice = data.deductionPrice; // 积分抵扣金额
- orderInfoVo.value.freightFee = data.freightFee; // 运费
- orderInfoVo.value.payFee = data.payFee; // 实付金额
- orderInfoVo.value.proTotalFee = data.proTotalFee; // 商品总价
- orderInfoVo.value.useIntegral = data.useIntegral; // 是否使用积分
- orderInfoVo.value.usedIntegral = data.usedIntegral; // 已用积分
- orderInfoVo.value.surplusIntegral = data.surplusIntegral; // 剩余积分
- })
- .catch((err) => {
- // 失败回调
- Toast({ title: err }); // 提示错误
- });
- }
- // 切换配送方式(快递/自提)
- const addressType = (e) => {
- let index = e; // 0-快递,1-自提
- shippingType.value = parseInt(index); // 更新配送方式
- // 若为普通商城类型,重新计算价格
- if (orderInfoVo.value.mallType === 0) {
- computedPrice();
- }
- // if (index == 1) getList();
- };
- // 配送方式选择器变化事件(预留,用于下拉选择器)
- const bindPickerChange = (e) => {
- let value = e.detail.value; // 选择的索引
- shippingType.value = value; // 更新配送方式
- computedPrice(); // 重新计算价格
- };
- // 关闭优惠券弹窗
- const closeCouponPopup = () => {
- showCouponPopup.value = false; // 隐藏优惠券弹窗
- };
- // 改变备注框状态(优惠券选择后调用)
- const changeTextareaStatus = () => {
- // 重置所有优惠券的选中状态
- for (let i = 0, len = coupon.value.list.length; i < len; i++) {
- coupon.value.list[i].use_title = "";
- coupon.value.list[i].is_use = 0;
- }
- textareaStatus.value = true; // 显示备注框
- status.value = 0; // 重置状态
- coupon.value.list = coupon.value.list; // 触发响应式更新
- };
- // 选择优惠券后的处理事件
- const ChangCoupons = (e) => {
- // this.usableCoupon = e
- // this.coupon.coupon = false
- let index = e,
- list = coupon.value.list,
- couponTitleValue = "请选择",
- couponIdValue = 0;
- console.log("list", list);
- for (let i = 0, len = list.length; i < len; i++) {
- if (i != index) {
- list[i].use_title = "";
- list[i].isUse = 0;
- }
- }
- // 切换当前优惠券的选中状态
- if (list[index].isUse) {
- // 若已选中,则取消选择
- list[index].use_title = "";
- list[index].isUse = 0;
- } else {
- // 若未选中,则选中
- list[index].use_title = "不使用"; // 显示"不使用"按钮
- list[index].isUse = 1; // 标记为选中
- couponTitleValue = list[index].name; // 更新标题为优惠券名称
- couponIdValue = list[index].id; // 更新选中的优惠券ID
- }
- // 更新优惠券相关状态
- couponTitle.value = couponTitleValue;
- couponId.value = couponIdValue;
- coupon.value.coupon = false;
- // coupon.value.list = list;
- computedPrice();
- };
- // 首次进入页面时展示默认地址
- const OnDefaultAddress = (e) => {
- addressInfo.value = e; // 保存默认地址详情
- address.value.addressId = e.id; // 更新选中地址ID
- };
- // 选择地址后触发的事件
- const OnChangeAddress = (e) => {
- console.log("OnChangeAddress", e);
- addressInfo.value = e;
- address.value.addressId = e.id;
- textareaStatus.value = true;
- //orderInfoVo.value.addressId = e;
- address.value.address = false;
- //this.getaddressInfo();
- if (orderInfoVo.value.mallType === 0) {
- computedPrice();
- }
- };
- // 备注输入事件(实时保存输入内容)
- const bindHideKeyboard = (e) => {
- mark.value = e.detail.value; // 保存输入的备注信息
- };
- // 获取当前订单可用的优惠券列表
- const getCouponList = () => {
- // 调用获取优惠券API,传入预订单号
- getCouponsOrderPrice(preOrderNo.value).then((res) => {
- coupon.value.list = res.data; // 保存优惠券列表
- openType.value = 1; // 设置打开方式为"使用"
- });
- };
- // 获取默认地址或指定地址详情
- const getaddressInfo = () => {
- if (addressId.value) {
- // 若有指定地址ID,获取该地址详情
- getAddressDetail(addressId.value).then((res) => {
- if (res.data) {
- // 若地址存在
- res.data.isDefault = parseInt(res.data.isDefault); // 转换默认地址标识为数字
- addressInfo.value = res.data || {}; // 保存地址详情
- addressId.value = res.data.id || 0; // 更新地址ID
- address.value.addressId = res.data.id || 0; // 更新选中地址ID
- }
- });
- } else {
- // 若没有指定地址ID,获取默认地址
- getAddressDefault().then((res) => {
- // 注意:原代码中未导入getAddressDefault,可能是遗漏
- if (res.data) {
- // 若默认地址存在
- res.data.isDefault = parseInt(res.data.isDefault);
- addressInfo.value = res.data || {};
- addressId.value = res.data.id || 0;
- address.value.addressId = res.data.id || 0;
- }
- });
- }
- };
- // 选择支付方式
- const payItem = (e) => {
- let activeValue = e;
- active.value = activeValue;
- animated.value = true;
- payType.value = payments.value[activeValue].value;
- userSelectPayTypeItem.value = payments.value[activeValue];
- computedPrice();
- setTimeout(() => {
- car();
- }, 500);
- };
- // 打开优惠券弹窗
- const couponTap = () => {
- // coupon.value.coupon = true;
- showCouponPopup.value = true;
- if (!coupon.value.list.length) getCouponList();
- // getCouponList();
- };
- // 关闭支付方式选择动画
- const car = () => {
- animated.value = false; // 关闭动画
- };
- // 打开地址选择弹窗
- const onAddress = () => {
- textareaStatus.value = false; // 隐藏备注框
- address.value.address = true; // 显示地址弹窗
- // 设置地址页面跳转链接(携带预订单号)
- pagesUrl.value =
- "/pages/users/user_address_list/index?preOrderNo=" + preOrderNo.value;
- };
- // 联系人输入事件(保存联系人)
- const realName = (e) => {
- contacts.value = e.detail.value;
- };
- // 联系人电话输入事件(保存电话)
- const phone = (e) => {
- contactsTel.value = e.detail.value;
- };
- // 创建订单并发起支付
- const payment = (data) => {
- // 调用创建订单API
- orderCreate(data)
- .then((res) => {
- // 订单创建成功
- // 调用支付流程,传入订单号和成功提示
- getOrderPay(res.data.orderNo, "支付成功");
- })
- .catch((err) => {
- // 订单创建失败
- console.error("payment error", err); // 打印错误
- uni.hideLoading(); // 隐藏加载中
- Toast({ title: err }); // 提示错误
- });
- };
- // 处理支付流程(根据支付类型发起支付并处理结果)
- const getOrderPay = async (orderNo, message) => {
- // 支付结果页地址(携带订单号)
- const goPages = "/pages/order_pay_status/index?order_id=" + orderNo;
- try {
- // 调用微信支付配置API(获取支付参数)
- const res = await wechatOrderPay({
- mallType: orderInfoVo.value.mallType,
- orderNo: orderNo,
- // payChannel: payChannel.value,
- payChannel: userSelectPayTypeItem.value.payChannel,
- payType: payType.value,
- scene: appStore.productTypeComputed === "normal" ? 0 : 1177, // 下单时小程序的场景值
- });
- console.log("res-------------", res.data);
- let jsConfig = res.data.prepayWithRequestPaymentResponse;
- switch (res.data.payType) {
- case "alipay":
- // 发起支付宝支付
- const result = await submitPayment({
- type: res.data.payType, // 支付类型
- orderInfo: res.data.alipayRequest, // 支付宝支付参数
- });
- console.log("result", result); // 打印支付结果
- // 失败提示信息(默认"支付失败")
- let failMsg = result?.message || paymentConfig.PAYMENT_STATUS.FAIL;
- // 根据支付结果处理
- if (result.status === paymentConfig.PAYMENT_STATUS.SUCCESS) {
- // 支付成功:查询后端支付状态
- const params = {
- orderNo: orderNo,
- payType: "alipay",
- };
- console.log("进入成功判断", params);
- const res = await alipayPaymentResult(params); // 调用查询接口
- console.log("alipayPaymentResult", res);
- // 提示成功并跳转到结果页
- return Toast(
- { title: paymentConfig.PAYMENT_STATUS.SUCCESS, icon: "success" },
- { tab: 4, url: goPages }
- );
- } else if (result.status === paymentConfig.PAYMENT_STATUS.FAIL) {
- // 支付失败:提示并跳转
- return Toast(
- { title: paymentConfig.PAYMENT_STATUS.FAIL },
- { tab: 5, url: `${goPages}&msg=${failMsg}` }
- );
- } else if (result.status === paymentConfig.PAYMENT_STATUS.CANCEL) {
- // 支付取消:提示并跳转
- return Toast(
- { title: paymentConfig.PAYMENT_STATUS.CANCEL },
- {
- tab: 5,
- url: `${goPages}&msg=${paymentConfig.PAYMENT_STATUS.CANCEL}`,
- }
- );
- }
- break;
- case "yue":
- // 余额支付:直接提示成功并跳转
- console.log("余额支付");
- return Toast(
- { title: message },
- { tab: 5, url: goPages + "&status=1" }
- );
- break;
- case "weixinApp":
- const wxPayResult = await submitPayment({
- type: res.data.payType,
- orderInfo: res.data.prepayWithRequestPaymentResponse,
- });
- let wxPayFailMsg =
- wxPayResult?.message || paymentConfig.PAYMENT_STATUS.FAIL;
- if (wxPayResult.status === paymentConfig.PAYMENT_STATUS.SUCCESS) {
- // 查询后端支付状态接口
- let params = {
- orderNo: orderNo,
- payType: "weixinApp",
- };
- let res = await alipayPaymentResult(params);
- return Toast(
- { title: paymentConfig.PAYMENT_STATUS.SUCCESS, icon: "success" },
- { tab: 4, url: goPages }
- );
- } else if (wxPayResult.status === paymentConfig.PAYMENT_STATUS.FAIL) {
- return Toast(
- { title: paymentConfig.PAYMENT_STATUS.FAIL },
- { tab: 5, url: `${goPages}&msg=${wxPayFailMsg}` }
- );
- } else if (wxPayResult.status === paymentConfig.PAYMENT_STATUS.CANCEL) {
- return Toast(
- { title: paymentConfig.PAYMENT_STATUS.CANCEL },
- {
- tab: 5,
- url: `${goPages}&msg=${paymentConfig.PAYMENT_STATUS.CANCEL}`,
- }
- );
- }
- break;
- }
- uni.hideLoading(); // 隐藏加载中
- } catch (error) {
- // 支付过程出错
- console.error("getOrderPay error", error, typeof error);
- let msg = "";
- // 处理错误信息
- if (typeof error === "string") {
- msg = error;
- } else if (typeof error === "object" && error.message) {
- msg = error.message;
- } else {
- msg = "支付失败,请稍后再试";
- }
- uni.hideLoading(); // 隐藏加载中
- // 跳转到结果页并携带错误信息
- uni.navigateTo({
- url: `/pages/order_pay_status/index?order_id=${orderNo}&msg=${msg}`,
- });
- return Toast({ title: msg }); // 提示错误
- }
- };
- function modalConfirm() {
- showModal.value = false;
- uni.navigateTo({
- url: "/pages/users/vault/recharge",
- });
- }
- const SubOrder = async (e) => {
- console.log("SubOrder", payType.value);
- // if (payType.value == "alipay") {
- // return Toast({ title: "暂不支持支付宝支付,请使用余额支付" });
- // }
- let data = {}; // 订单提交数据
- // 验证:必须选择支付方式
- if (!payType.value) return Toast({ title: "请选择支付方式" });
- // 验证:快递配送时必须选择地址
- if (!address.value.addressId && !shippingType.value) {
- return Toast({ title: "请选择收货地址" });
- }
- try {
- const channels = await getAvailableChannels();
- if (payType.value === "alipay" && !channels.includes("alipay")) {
- return Toast({ title: "设备不支持支付宝支付" });
- } else if (payType.value === "weixin" && !channels.includes("wxpay")) {
- return Toast({ title: "设备不支持微信支付" });
- }
- } catch (error) {
- console.error("获取支付渠道失败", error);
- return Toast({ title: "获取支付渠道失败" });
- }
- // 构造订单提交数据
- data = {
- mallType: orderInfoVo.value.mallType,
- realName: contacts.value,
- phone: contactsTel.value,
- addressId: address.value.addressId,
- couponId: couponId.value,
- payType: payType.value,
- useIntegral: useIntegral.value,
- preOrderNo: preOrderNo.value,
- mark: mark.value,
- // storeId: system_store.value.id || 0,
- shippingType: util.$h.Add(shippingType.value, 1),
- // payChannel: payChannel.value || "weixinh5",
- payChannel: userSelectPayTypeItem.value.payChannel,
- };
- console.log(" data.payType", data.payType);
- // 验证:贝币支付时余额是否充足
- if (
- orderInfoVo.value.mallType === 1 &&
- Number(orderInfoVo.value.proTotalFee) > orderInfoVo.value.userIntegral
- ) {
- return Toast({ title: "贝币余额不足!" });
- }
- // 验证:余额支付时余额是否充足
- else if (
- data.payType == "yue" &&
- parseFloat(appStore.$userInfo.nowMoney) <
- parseFloat(orderInfoVo.value.payFee)
- ) {
- // 余额不足
- showModal.value = true;
- return;
- }
- uni.showLoading({
- title: "订单支付中",
- });
- // 发起支付
- payment(data);
- };
- </script>
- <style lang="scss" scoped>
- .order-submission {
- .line {
- width: 100%;
- height: 3rpx;
- image {
- width: 100%;
- height: 100%;
- display: block;
- }
- }
- .allAddress {
- width: 100%;
- // background-image: linear-gradient(to bottom, #f0cb88 0%, transparent 100%);
- background: $uni-bg-primary;
- padding: 100rpx 30rpx 0 30rpx;
- .nav {
- width: 690rpx;
- margin: 0 auto;
- .item {
- width: 334rpx;
- &.on {
- position: relative;
- width: 230rpx;
- &::before {
- position: absolute;
- bottom: 0;
- content: "快递配送";
- font-size: 28rpx;
- display: block;
- height: 0;
- width: 336rpx;
- border-width: 0 20rpx 80rpx 0;
- border-style: none solid solid;
- border-color: transparent transparent #fff;
- z-index: 2;
- border-radius: 14rpx 36rpx 0 0;
- text-align: center;
- line-height: 80rpx;
- }
- }
- &:nth-of-type(2).on::before {
- content: "到店自提";
- border-width: 0 0 80rpx 20rpx;
- border-radius: 36rpx 14rpx 0 0;
- }
- &.on2 {
- position: relative;
- &::before {
- position: absolute;
- bottom: 0;
- content: "到店自提";
- font-size: 28rpx;
- display: block;
- height: 0;
- width: 401rpx;
- border-width: 0 0 60rpx 60rpx;
- border-style: none solid solid;
- border-color: transparent transparent #f7c1bd;
- border-radius: 36rpx 14rpx 0 0;
- text-align: center;
- line-height: 60rpx;
- }
- }
- &:nth-of-type(1).on2::before {
- content: "快递配送";
- border-width: 0 60rpx 60rpx 0;
- border-radius: 14rpx 36rpx 0 0;
- }
- }
- }
- .address {
- width: 690rpx;
- max-height: 180rpx;
- margin: 0 auto;
- padding: 28rpx;
- background-color: #fff;
- box-sizing: border-box;
- .addressCon {
- width: 596rpx;
- font-size: 26rpx;
- color: #666;
- .name {
- font-size: 30rpx;
- color: #282828;
- font-weight: bold;
- margin-bottom: 10rpx;
- .phone {
- margin-left: 50rpx;
- }
- }
- .default {
- margin-right: 12rpx;
- }
- .setaddress {
- color: #333;
- font-size: 28rpx;
- }
- }
- .iconfont {
- font-size: 35rpx;
- color: #707070;
- }
- }
- .line {
- width: 100%;
- margin: 0 auto;
- }
- }
- .wrapper {
- background-color: #fff;
- margin-top: 15rpx;
- .item {
- padding: 27rpx 24rpx;
- font-size: 30rpx;
- color: #333333;
- border-bottom: 1px solid #f5f5f5;
- .zf-box {
- display: flex;
- justify-content: space-between;
- align-items: center;
- }
- .swicth-box {
- display: flex;
- justify-content: space-between;
- align-items: center;
- border: 2rpx solid #eee;
- height: 86rpx;
- font-size: 28rpx;
- padding: 0 0 0 12%;
- box-sizing: border-box;
- margin: 20rpx 0;
- border-radius: 14rpx;
- .lable-box {
- display: flex;
- align-items: center;
- .iconfont {
- width: 44rpx;
- height: 44rpx;
- border-radius: 50%;
- text-align: center;
- line-height: 44rpx;
- background-color: #fe960f;
- color: #fff;
- font-size: 30rpx;
- margin-right: 15rpx;
- &.icon-touzijintiao1 {
- background-color: #f0cb88;
- }
- }
- .lable-icon {
- display: flex;
- flex-direction: column;
- justify-content: center;
- }
- .value {
- font-size: 20rpx;
- color: #fe960f;
- }
- }
- }
- .discount {
- font-size: 30rpx;
- color: #333;
- .iconfont {
- color: #515151;
- font-size: 30rpx;
- margin-left: 15rpx;
- }
- .num {
- font-size: 32rpx;
- margin-right: 20rpx;
- }
- .placeholder {
- color: #ccc;
- }
- }
- .shipping {
- font-size: 30rpx;
- color: #999;
- position: relative;
- padding-right: 58rpx;
- .iconfont {
- font-size: 35rpx;
- color: #707070;
- position: absolute;
- right: 0;
- top: 50%;
- transform: translateY(-50%);
- margin-left: 30rpx;
- }
- }
- textarea {
- background-color: #f9f9f9;
- width: auto !important;
- height: 140rpx;
- border-radius: 14rpx;
- margin-top: 30rpx;
- padding: 15rpx;
- box-sizing: border-box;
- font-weight: 400;
- }
- .placeholder {
- color: #ccc;
- }
- .list {
- margin-top: 35rpx;
- .payItem {
- border: 1px solid #eee;
- border-radius: 14rpx;
- height: 86rpx;
- width: 100%;
- box-sizing: border-box;
- margin-top: 20rpx;
- font-size: 28rpx;
- color: #282828;
- &.on {
- border-color: #fc5445;
- color: $theme-color;
- }
- .name {
- flex: 1;
- // width: 50%;
- text-align: center;
- border-right: 1px solid #eee;
- justify-content: flex-start;
- padding: 0 0 0 12%;
- .iconfont {
- width: 44rpx;
- height: 44rpx;
- border-radius: 50%;
- text-align: center;
- line-height: 44rpx;
- background-color: #fe960f;
- color: #fff;
- font-size: 30rpx;
- margin-right: 15rpx;
- &.icon-wechat {
- background-color: #41b035;
- }
- &.icon-zhifubao {
- background-color: #06b4fd;
- }
- }
- }
- .tip {
- width: 49%;
- text-align: center;
- font-size: 26rpx;
- color: #aaa;
- }
- }
- }
- }
- }
- .moneyList {
- margin-top: 15rpx;
- background-color: #fff;
- padding: 30rpx;
- .item {
- font-size: 28rpx;
- color: #282828;
- & ~ .item {
- margin-top: 20rpx;
- }
- .money {
- color: #666666;
- }
- }
- }
- .footer {
- width: 100%;
- height: 100rpx;
- background-color: #fff;
- padding: 0 30rpx;
- font-size: 28rpx;
- color: #333;
- box-sizing: border-box;
- position: fixed;
- bottom: 0;
- left: 0;
- .settlement {
- font-size: 30rpx;
- color: #fff;
- width: 240rpx;
- height: 70rpx;
- background-color: $theme-color;
- border-radius: 50rpx;
- text-align: center;
- line-height: 70rpx;
- z-index: 100;
- }
- .transparent {
- opacity: 0;
- }
- }
- }
- .line2 {
- width: 504rpx;
- }
- .textR {
- text-align: right;
- }
- </style>
|