HHE-5476 5 horas atrás
pai
commit
b7cd0a9e68
6 arquivos alterados com 410 adições e 20 exclusões
  1. 1 2
      api/user.js
  2. 2 2
      config/app.js
  3. 17 9
      pages.json
  4. 21 5
      pages/user/index.vue
  5. 1 2
      pages/users/login/index.vue
  6. 368 0
      pages/webview/WxPay.vue

+ 1 - 2
api/user.js

@@ -6,9 +6,8 @@ import { APP_CODE } from "@/config/app.js";
  *
  */
 export function getUserInfo() {
-  return request.get("user");
+  return request.get(`user?appCode=${APP_CODE}`);
 }
-
 /**
  * h5用户手机号登录
  * @param data object 用户手机号 也只能

+ 2 - 2
config/app.js

@@ -1,8 +1,8 @@
 // let domain = "https://www.shuibeibyg.com/front-api"; // 正式环境IP
-// let domain = "https://test.shuibeibyg.com/front-api"; // 测试环境IP
+let domain = "https://test.shuibeibyg.com/front-api"; // 测试环境IP
 // let domain = 'http://192.168.100.199:8081' // 晋守桦IP
 // let domain = 'http://192.168.100.246:8081' // 韩朝龙IP
-let domain = "http://192.168.3.29:8081"; // 宏广IP
+// let domain = "http://192.168.3.29:8081"; // 宏广IP
 let share = "https://www.shuibeibyg.com";
 
 let imgUrl =

+ 17 - 9
pages.json

@@ -115,6 +115,14 @@
         "navigationBarBackgroundColor": "#ffe079",
         "navigationBarTextStyle": "black"
       }
+    },
+    {
+      "path": "pages/webview/WxPay",
+      "style": {
+        "navigationBarTitleText": "微信支付",
+        "navigationBarBackgroundColor": "#ffe079",
+        "navigationBarTextStyle": "black"
+      }
     }
   ],
   "subPackages": [
@@ -344,15 +352,15 @@
             "navigationBarBackgroundColor": "#ffffff",
             "navigationBarTextStyle": "black"
           }
-		},
-		{
-			"path": "productCate/productCate",
-			"style": {
-				"navigationBarTitleText": "添加规格",
-				"navigationBarBackgroundColor": "#ffffff",
-				"navigationBarTextStyle": "black"
-			}
-		}
+        },
+        {
+          "path": "productCate/productCate",
+          "style": {
+            "navigationBarTitleText": "添加规格",
+            "navigationBarBackgroundColor": "#ffffff",
+            "navigationBarTextStyle": "black"
+          }
+        }
       ]
     },
     {

+ 21 - 5
pages/user/index.vue

@@ -166,7 +166,13 @@
         >
       </view> -->
 
-      <view class="functions" v-if="useList && useList.length > 0">
+      <view
+        class="functions-useList"
+        v-if="useList && useList.length > 0"
+        :style="{
+          gridTemplateColumns: `repeat(${useList.length <= 4 ? useList.length : 4},1fr`,
+        }"
+      >
         <view
           class="function-item"
           v-for="item in useList"
@@ -177,7 +183,10 @@
             <image
               :src="item.iconUrl"
               mode="widthFix"
-              :style="{ width: (item.iconSize || '60') + 'rpx',height: (item.iconSize || '60') + 'rpx' }"
+              :style="{
+                width: (item.iconSize || '60') + 'rpx',
+                height: (item.iconSize || '60') + 'rpx',
+              }"
             ></image>
           </view>
           <text class="function-name">{{ item.iconName }}</text>
@@ -516,7 +525,8 @@ watch(
     wxConfig.value = configDate;
     const list = JSON.parse(configDate.storeCommonTools || "[]");
     console.log("list", list);
-    useList.value = list;
+    // 过滤list中status为false的项
+    useList.value = list.filter((item) => item.status);
     // if (list[0].status == false) {
     //   showIcons.value = false;
     // } else {
@@ -544,7 +554,7 @@ watch(
     // ];
     console.log(tradeList.value);
   },
-  { deep: true, immediate: true }
+  { deep: true, immediate: true },
 );
 
 // 编辑资料
@@ -1007,7 +1017,13 @@ function handleFaceDetect() {
 
 .functions {
   display: grid;
-  grid-template-columns: repeat(4, 1fr);
+  // grid-template-columns: repeat(4, 1fr);
+  gap: 40rpx;
+  margin-top: 40rpx;
+}
+.functions-useList {
+  display: grid;
+  // grid-template-columns: repeat(4, 1fr);
   gap: 40rpx;
   margin-top: 40rpx;
 }

+ 1 - 2
pages/users/login/index.vue

@@ -529,12 +529,11 @@ const getUserInfoFn = async (data) => {
 
       await footprintScanFn(obj);
     } else {
-      console.log("============");
       appStore.UPDATE_MERCHANT_ID("");
       Toast({
         title: "登录成功",
       });
-      // backHome();
+      backHome();
     }
   } catch (err) {
     console.error(err);

+ 368 - 0
pages/webview/WxPay.vue

@@ -0,0 +1,368 @@
+<template>
+  <view class="pay-container">
+    <!-- 加载状态 -->
+    <view v-if="loading" class="loading-wrap flex-center">
+      <uni-load-more type="loading" color="#f8c008"></uni-load-more>
+      <text class="loading-text">正在初始化支付...</text>
+    </view>
+
+    <!-- 订单信息 & 支付区域 -->
+    <view v-else-if="orderInfo" class="pay-content">
+      <view class="order-card">
+        <view class="order-item price-highlight">
+          <text class="label">支付金额:</text>
+          <view class="value price">
+            <text class="currency">¥</text>
+            <text class="amount-text">{{ orderInfo.amount }}</text>
+            <text class="unit">元</text>
+          </view>
+        </view>
+
+        <view class="order-item" v-if="orderInfo.description">
+          <text class="label">订单描述:</text>
+          <text class="value">{{ orderInfo.description }}</text>
+        </view>
+
+        <view class="order-item" v-if="orderInfo.orderNo">
+          <text class="label">订单号:</text>
+          <text class="value">{{ orderInfo.orderNo }}</text>
+        </view>
+      </view>
+
+      <!-- 支付按钮 -->
+      <view class="pay-btn-wrap flex-center" @click="handlePay">
+        <button class="pay-btn" :disabled="paying">
+          <text v-if="!paying" class="btn-text">立即支付</text>
+          <text v-else class="btn-text">支付中...</text>
+        </button>
+      </view>
+    </view>
+
+    <!-- 异常提示 -->
+    <view v-else class="error-wrap flex-center">
+      <text class="error-text">{{ errorMsg }}</text>
+      <button class="back-btn" @click="goBackToWebview">返回上一页</button>
+    </view>
+
+    <!-- 微信支付组件-->
+    <WechatPayment ref="wechatPaymentRef" />
+  </view>
+</template>
+
+<script setup>
+import { ref } from "vue";
+import { onLoad } from "@dcloudio/uni-app";
+import { useAppStore } from "@/stores/app";
+import { getUserOpenId } from "@/api/user";
+import { Calc } from "@/utils/util";
+import { goldPrincipalCompleteOrder } from "@/api/payment";
+import { recyclePreOrderSuccessAPI } from "@/api/functions";
+import WechatPayment from "@/components/payment/WechatPayment.vue";
+
+// 状态管理
+const appStore = useAppStore();
+const wechatPaymentRef = ref(null);
+
+// 页面核心数据
+const loading = ref(true);
+const paying = ref(false);
+const amount = ref(0);
+const orderNo = ref(0);
+const description = ref("");
+const returnUrl = ref("");
+const orderPrefix = ref("");
+const orderInfo = ref(null);
+const errorMsg = ref("");
+
+onLoad(async (options) => {
+  try {
+    amount.value = Number(options.amount) || 0.01;
+    description.value = decodeURIComponent(options.description || "");
+    orderPrefix.value = options.orderPrefix || "H5";
+    orderNo.value = options.orderNo || "";
+    returnUrl.value = options.returnUrl || "";
+
+    if (isNaN(amount.value) || amount.value <= 0) {
+      throw new Error("支付金额异常(需大于0分)");
+    }
+    if (!description.value && !orderNo.value) {
+      throw new Error("订单描述或订单号其中一项不能为空");
+    }
+    if (!returnUrl.value) {
+      throw new Error("支付完成返回地址不能为空");
+    }
+
+    orderInfo.value = {
+      amount: Calc.div(amount.value, 100).truncate().valueOf(),
+      description: description.value,
+      orderNo: orderNo.value,
+    };
+    loading.value = false;
+  } catch (err) {
+    loading.value = false;
+    errorMsg.value = err.message || "页面参数异常";
+    console.error("页面初始化失败:", err);
+  }
+});
+
+const handlePay = async () => {
+  if (paying.value) return;
+  if (!appStore.isLogin) {
+    uni.showToast({ title: "请先登录", icon: "none" });
+    return;
+  }
+
+  const userOpenId = appStore.$userInfo?.openId;
+  if (!userOpenId) {
+    uni.showToast({ title: "用户信息异常,请重新登录", icon: "none" });
+    return;
+  }
+
+  paying.value = true;
+  try {
+    wechatPaymentRef.value.createUniPay({
+      amount: amount.value,
+      description: description.value,
+      openId: userOpenId,
+      orderPrefix: orderPrefix.value,
+      orderNo: orderNo.value,
+
+      onUniPayCreate: async (payRes) => {
+        console.log("支付订单创建成功:", payRes);
+      },
+
+      onUniPaySuccess: async (payStatusRes) => {
+        console.log("支付成功:", payStatusRes);
+        await processOrderBizChange(payStatusRes);
+        paying.value = false;
+        uni.showToast({
+          title: "您已支付成功,将返回订单列表",
+          icon: "success",
+        });
+        setTimeout(() => {
+          goBackToWebview();
+        }, 1300);
+      },
+
+      onUniPayCancel: () => {
+        paying.value = false;
+        uni.showToast({ title: "你已取消支付", icon: "none" });
+      },
+
+      onUniPayFail: (err) => {
+        paying.value = false;
+        const errMsg = err || "支付失败,请重试";
+        uni.showToast({ title: errMsg, icon: "none" });
+        console.error("支付失败:", err);
+      },
+    });
+  } catch (err) {
+    paying.value = false;
+    uni.showToast({ title: "支付接口调用失败", icon: "none" });
+    console.error("支付调用异常:", err);
+  }
+};
+
+const processOrderBizChange = async (payStatusRes) => {
+  try {
+    switch (payStatusRes.orderType) {
+      case "recyle":
+        await recyclePreOrderSuccessAPI({
+          orderNo: payStatusRes.outTradeNo,
+          payType: "routine",
+        });
+        break;
+      case "tl":
+        await goldPrincipalCompleteOrder({
+          orderNo: payStatusRes.outTradeNo,
+        });
+        break;
+      case "svip":
+        break;
+    }
+  } catch (error) {
+    uni.showToast({ title: error || "业务订单状态更改失败", icon: "none" });
+    console.error("业务订单状态更改失败:", error);
+  }
+};
+
+const goBackToWebview = () => {
+  if (!returnUrl.value) {
+    uni.showToast({ title: "返回地址异常", icon: "none" });
+    return;
+  }
+
+  let finalUrl = returnUrl.value;
+  try {
+    if (finalUrl.includes("%")) {
+      finalUrl = decodeURIComponent(finalUrl);
+    }
+  } catch (e) {
+    console.warn("URL解码失败,使用原始URL:", e);
+  }
+
+  uni.redirectTo({
+    url: `/pages/webview/index?path=${returnUrl.value}`,
+  });
+};
+</script>
+
+<style scoped lang="scss">
+$primary: #f8c008;
+$primary-dark: #e6b007;
+$primary-light: #fff5cc;
+$primary-disabled: #fad966;
+
+.pay-container {
+  min-height: 100vh;
+  background-color: #fafafa;
+  padding: 30rpx;
+}
+
+// 加载状态
+.loading-wrap {
+  flex-direction: column;
+  height: 60vh;
+  .loading-text {
+    margin-top: 20rpx;
+    font-size: 28rpx;
+    color: #666;
+  }
+}
+
+// 订单信息卡片
+.pay-content {
+  .order-card {
+    background-color: #fff;
+    border-radius: 20rpx;
+    padding: 40rpx 32rpx;
+    margin-bottom: 80rpx;
+    box-shadow: 0 6rpx 30rpx rgba(0, 0, 0, 0.04);
+    border: 1px solid $primary-light;
+
+    .order-item {
+      display: flex;
+      align-items: center;
+      margin-bottom: 28rpx;
+
+      &:last-child {
+        margin-bottom: 0;
+      }
+
+      .label {
+        font-size: 28rpx;
+        color: #777;
+        width: 160rpx;
+        font-weight: 500;
+      }
+
+      .value {
+        font-size: 28rpx;
+        color: #333;
+        flex: 1;
+        word-break: break-all;
+      }
+    }
+
+    // 🔥 高亮金额区域
+    .price-highlight {
+      padding: 12rpx 0;
+      margin: 12rpx 0 32rpx;
+
+      .value.price {
+        display: flex;
+        align-items: baseline;
+        gap: 6rpx;
+
+        .currency {
+          font-size: 32rpx;
+          color: $primary;
+          font-weight: 600;
+        }
+
+        // 核心金额数字(最大、最亮)
+        .amount-text {
+          font-size: 48rpx;
+          font-weight: 700;
+          color: $primary;
+          letter-spacing: 1rpx;
+        }
+
+        .unit {
+          font-size: 28rpx;
+          color: $primary;
+          font-weight: 500;
+          margin-left: 4rpx;
+        }
+      }
+    }
+  }
+}
+
+// 支付按钮
+.pay-btn-wrap {
+  .pay-btn {
+    width: 100%;
+    height: 96rpx;
+    line-height: 96rpx;
+    background-color: $primary;
+    border: none;
+    border-radius: 48rpx;
+    box-shadow: 0 8rpx 24rpx rgba($primary, 0.25);
+    transition: all 0.2s ease;
+
+    .btn-text {
+      font-size: 34rpx;
+      color: #fff;
+      font-weight: 600;
+      letter-spacing: 2rpx;
+    }
+
+    &:not(:disabled):active {
+      background-color: $primary-dark;
+      box-shadow: 0 4rpx 12rpx rgba($primary, 0.2);
+      transform: translateY(2rpx);
+    }
+
+    &:disabled {
+      background-color: $primary-disabled;
+      box-shadow: none;
+    }
+  }
+}
+
+// 异常提示
+.error-wrap {
+  flex-direction: column;
+  height: 60vh;
+  .error-text {
+    font-size: 30rpx;
+    color: #e64340;
+    margin-bottom: 40rpx;
+    text-align: center;
+    padding: 0 30rpx;
+    line-height: 44rpx;
+  }
+  .back-btn {
+    width: 280rpx;
+    height: 76rpx;
+    line-height: 76rpx;
+    background-color: #fff;
+    border: 1px solid $primary;
+    border-radius: 38rpx;
+    font-size: 28rpx;
+    color: $primary;
+    transition: all 0.2s ease;
+
+    &:active {
+      background-color: $primary-light;
+    }
+  }
+}
+
+.flex-center {
+  display: flex;
+  justify-content: center;
+  align-items: center;
+}
+</style>