Parcourir la source

Merge branch 'dev_v3' of http://git.dgtis.com/armg/wxapp_shuibei into dev_v3

calm il y a 1 mois
Parent
commit
7fbf075b19
44 fichiers modifiés avec 7660 ajouts et 5877 suppressions
  1. 17 0
      api/faceVerify.js
  2. 21 0
      api/user.js
  3. 18 11
      components/productWindow/index.vue
  4. 5 3
      config/app.js
  5. 1 1
      hooks/useSendCode.js
  6. 33 85
      pages.json
  7. 2219 2127
      pages/goods/goods_details/index.vue
  8. 201 11
      pages/goods/goods_search/index.vue
  9. 3 2
      pages/goods_cate/goods_cate.vue
  10. 1588 1441
      pages/index/index.vue
  11. 453 500
      pages/mall/dapan.vue
  12. 780 601
      pages/merchantCenter/index.vue
  13. 2 2
      pages/merchantCenters/components/merchant_cate.vue
  14. 26 17
      pages/merchantCenters/merchant.vue
  15. 4 3
      pages/merchantCenters/productCenter.vue
  16. 4 3
      pages/merchantCenters/productManagement.vue
  17. 4 4
      pages/merchantCenters/releaseProduct.vue
  18. 191 117
      pages/order_addcart/order_addcart.vue
  19. 98 32
      pages/user/index.vue
  20. 9 5
      pages/users/browsing_history/index.vue
  21. 631 0
      pages/users/face_detect/index.vue
  22. 233 65
      pages/users/login/index.vue
  23. 4 4
      pages/users/my_merchant/index.vue
  24. 1 0
      pages/users/order_confirm/index.vue
  25. 372 351
      pages/users/personal_info/personal_info.vue
  26. 0 0
      pages/users/personal_info/personal_info_bf.vue
  27. 0 2
      pages/users/share/index.vue
  28. 2 0
      pages/users/user_address/index.vue
  29. 1 0
      pages/users/user_address_list/index.vue
  30. 547 488
      pages/users/user_goods_collection/index.vue
  31. 1 1
      pages/webview/index.vue
  32. 122 0
      pages/webview/privacy.vue
  33. 22 0
      static/css/base.css
  34. BIN
      static/images/edit@2x.png
  35. BIN
      static/images/login_ip.png
  36. BIN
      static/images/notice@2x.png
  37. BIN
      static/images/shou@2x.png
  38. BIN
      static/images/time@2x.png
  39. BIN
      static/images/wxLogin.png
  40. BIN
      static/img/IDFront.png
  41. BIN
      static/img/IDReverse.png
  42. BIN
      static/img/tips@2x.png
  43. 7 1
      stores/app.js
  44. 40 0
      utils/util.js

+ 17 - 0
api/faceVerify.js

@@ -0,0 +1,17 @@
+import request from "@/utils/request.js";
+
+/**
+ * 发起认证
+ * 
+ */
+export function init(data) {
+  return request.post('faceVerify/init', data);
+}
+
+/**
+ * 获取认证结果
+ * 
+ */
+export function query(data) {
+  return request.get('faceVerify/query', data);
+}

+ 21 - 0
api/user.js

@@ -198,3 +198,24 @@ export function withdrawToCard(data) {
 export function getCustomerServiceList(data) {
   return request.get("customer-service/list", data);
 }
+
+/**
+ * 实名认证
+ */
+export function faceVerify(data) {
+  return request.post(`faceVerify/hminit`, data);
+}
+
+/**
+ * 获取实名认证状态
+ */
+export function getFaceVerify(data) {
+  return request.post(`faceVerify/list`, data);
+}
+/**
+ * 微信登录
+ *
+ */
+export function wxLogin(data) {
+  return request.post('login/loginAuthorize', data, {noAuth:true,noVerify:true});
+}

+ 18 - 11
components/productWindow/index.vue

@@ -217,6 +217,7 @@ const calcNumPrice = computed(() => {
 
   const { price, cart_num, additionalAmount, weight } =
     props.attr.productSelect;
+	console.log("calcNumberPrice=======>",{ price, cart_num, additionalAmount, weight })
   // 计算总价并保留两位小数
   const total =
     (Number(price) * Number(weight) + Number(additionalAmount || 0)) *
@@ -224,13 +225,13 @@ const calcNumPrice = computed(() => {
   return total.toFixed(2);
 });
 
-// 监听 calcNumPrice 变化并传递给父组件
-watch(calcNumPrice, (newPrice) => {
-  emit("updatePrice", newPrice);
-}, { immediate: true });
-function goCat() {
-  emit("goCat");
-}
+// // 监听 calcNumPrice 变化并传递给父组件
+// watch(calcNumPrice, (newPrice) => {
+//   emit("updatePrice", newPrice);
+// }, { immediate: true });
+// function goCat() {
+//   emit("goCat");
+// }
 
 function bindCode() {
   emit("iptCartNum", props.attr.productSelect.cart_num);
@@ -241,6 +242,7 @@ function close() {
 }
 
 function submit() {
+  emit("updatePrice", calcNumPrice);
   emit("submit");
 }
 
@@ -318,6 +320,7 @@ function getCheckedValue() {
 
       .money {
         font-size: 24rpx;
+		font-weight: bold;
         //margin-top: 40rpx;
       }
       .num {
@@ -351,6 +354,8 @@ function getCheckedValue() {
     .confirm-btn {
       height: 88rpx;
       line-height: 88rpx;
+	  font-weight: bold;
+	  font-size: 32rpx;
       color: #333;
       border-radius: 16rpx;
       background-color: #F8C008;
@@ -367,6 +372,7 @@ function getCheckedValue() {
         font-size: 28rpx;
         color: #333;
         padding: 0 30rpx;
+		font-weight: bold;
       }
       .listn {
         padding: 0 30rpx 0 16rpx;
@@ -427,7 +433,7 @@ function getCheckedValue() {
       width: 58rpx;
       border: 0;
       //border-radius: 4rpx 0 0 4rpx;
-      line-height: 48rpx;
+      line-height: 46rpx;
       background: #F5F7FA;
 
       &.on {
@@ -441,7 +447,7 @@ function getCheckedValue() {
       width: 58rpx;
       border: 0;
       //border-radius: 0 4rpx 4rpx 0;
-      line-height: 48rpx;
+      line-height: 46rpx;
       background: #F5F7FA;
       &.on {
         border-color: #e3e3e3;
@@ -455,8 +461,8 @@ function getCheckedValue() {
       color: #333;
       font-size: 24rpx;
       //border-radius: 12rpx;
-      line-height: 29px;
-      height: 50rpx;
+      line-height: 46rpx;
+      height: 100%;
 
       input {
         display: -webkit-inline-box;
@@ -482,6 +488,7 @@ function getCheckedValue() {
 .popup-title{
   height: 100rpx;
   line-height: 100rpx;
+  font-weight: bold;
   font-size: 36rpx;
   color: #333;
   text-align: center;

+ 5 - 3
config/app.js

@@ -1,5 +1,5 @@
-// let domain = "https://www.shuibeibyg.com/front-api"; // 正式环境IP
-let domain = "https://test.shuibeibyg.com/front-api"; // 测试环境IP
+let domain = "https://www.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 share = "https://www.shuibeibyg.com";
@@ -8,7 +8,8 @@ let imgUrl = "https://sb-admin.oss-cn-shenzhen.aliyuncs.com/shuibei-mini/new-min
 
 // export const H5_BASE_URL = "http://192.168.3.10:5174"; // 本地测试
 // export const H5_BASE_URL = "http://192.168.100.35:5175"; // 本地测试
-export const H5_BASE_URL = "https://test.shuibeibyg.com/web-h5/"; // 正式环境H5地址
+// export const H5_BASE_URL = "https://test.shuibeibyg.com/web-h5/"; // 测试环境H5地址
+export const H5_BASE_URL = "https://www.shuibeibyg.com/web-h5/"; // 正式环境H5地址
 
 // PC 后台 API 地址(用于上传图片)
 export const HTTP_ADMIN_URL = domain;
@@ -52,6 +53,7 @@ export const WHITELIST = [
   "/pages/users/VIP/VIP",
   "/pages/order_addcart/order_addcart",
   "/pages/mall/dapan",
+  // "/pages/merchantCenters/merchant",
 ];
 
 // oss对象存储地址

+ 1 - 1
hooks/useSendCode.js

@@ -3,7 +3,7 @@ import { ref, onUnmounted } from 'vue'
 
 export function useSendCode() {
   const disabled = ref(false)
-  const text = ref('获取验证码')
+  const text = ref('发送验证码')
   let timer = null
   let count = 60
 

+ 33 - 85
pages.json

@@ -14,7 +14,8 @@
         "navigationBarTitleText": "首页",
         "navigationBarBackgroundColor": "#ffe079",
         "navigationBarTextStyle": "black",
-        "navigationStyle": "custom"
+        "navigationStyle": "custom",
+        "enablePullDownRefresh": true
       }
     },
     {
@@ -22,7 +23,7 @@
       "style": {
         "navigationBarBackgroundColor": "#ffe079",
         "navigationBarTextStyle": "white",
-        "navigationBarTitleText": "大盘"
+        "navigationBarTitleText": "实时金价"
       }
     },
     {
@@ -47,7 +48,8 @@
       "style": {
         "navigationBarTitleText": "购物车",
         "navigationBarBackgroundColor": "#fff",
-        "navigationBarTextStyle": "black"
+        "navigationBarTextStyle": "black",
+        "enablePullDownRefresh": true
       }
     },
     {
@@ -105,6 +107,14 @@
         "navigationBarBackgroundColor": "#ffe079",
         "navigationBarTextStyle": "black"
       }
+    },
+    {
+      "path": "pages/webview/privacy",
+      "style": {
+        "navigationBarTitleText": "政策协议",
+        "navigationBarBackgroundColor": "#ffe079",
+        "navigationBarTextStyle": "black"
+      }
     }
   ],
   "subPackages": [
@@ -117,7 +127,8 @@
           "style": {
             "navigationBarTitleText": "登录",
             "navigationBarBackgroundColor": "#ffe079",
-            "navigationBarTextStyle": "black"
+            "navigationBarTextStyle": "black",
+            "navigationStyle": "custom"
           }
         },
         {
@@ -149,36 +160,6 @@
             "navigationBarTextStyle": "black"
           }
         },
-        {
-          "path": "card_page/index",
-          "style": {
-            "navigationBarTitleText": "卡包管理",
-            "navigationBarBackgroundColor": "#ffe079",
-            "navigationBarTextStyle": "black",
-            "app-plus": {
-              // #ifdef APP-PLUS
-              "titleNView": {
-                "type": "default"
-              }
-              // #endif
-            }
-          }
-        },
-        {
-          "path": "card_page/create",
-          "style": {
-            "navigationBarTitleText": "卡包编辑",
-            "navigationBarBackgroundColor": "#ffe079",
-            "navigationBarTextStyle": "black",
-            "app-plus": {
-              // #ifdef APP-PLUS
-              "titleNView": {
-                "type": "default"
-              }
-              // #endif
-            }
-          }
-        },
         {
           "path": "user_address_list/index",
           "style": {
@@ -225,30 +206,6 @@
             "navigationBarTextStyle": "black"
           }
         },
-        {
-          "path": "user_asset/stock_in/stock_in",
-          "style": {
-            "navigationBarTitleText": "补仓",
-            "navigationBarBackgroundColor": "#fff",
-            "navigationBarTextStyle": "black"
-          }
-        },
-        {
-          "path": "user_asset/asset_info/asset_info",
-          "style": {
-            "navigationBarTitleText": "资产明细",
-            "navigationBarBackgroundColor": "#fff",
-            "navigationBarTextStyle": "black"
-          }
-        },
-        {
-          "path": "user_asset/record_list/record_list",
-          "style": {
-            "navigationBarTitleText": "交易明细",
-            "navigationBarBackgroundColor": "#fff",
-            "navigationBarTextStyle": "black"
-          }
-        },
         {
           "path": "user_return_list/index",
           "style": {
@@ -264,45 +221,36 @@
             }
           }
         },
-        {
-          "path": "vault/index",
-          "style": {
-            "navigationBarTitleText": "钱包",
-            "navigationBarBackgroundColor": "#ffe079",
-            "navigationBarTextStyle": "black"
-          }
-        },
         {
           "path": "user_goods_collection/index",
           "style": {
-            "navigationBarTitleText": "收藏商品",
-            "navigationBarBackgroundColor": "#ffe079",
+            "navigationBarTitleText": "我的收藏",
+            "navigationBarBackgroundColor": "#ffffff",
             "navigationBarTextStyle": "black"
           }
         },
         {
-          "path": "VIP/VIP",
-          "style": {
-            "navigationBarTitleText": "VIP权益",
-            "navigationBarBackgroundColor": "#2f2e3e",
-            "navigationBarTextStyle": "white"
-          }
-        },
-        {
-          "path": "SVIP/SVIP",
+          "path": "personal_info/personal_info",
           "style": {
-            "navigationBarTitleText": "SVIP权益",
-            "navigationBarBackgroundColor": "#212121",
-            "navigationBarTextStyle": "white"
+            "navigationBarTitleText": "个人资料",
+            "navigationBarBackgroundColor": "#F9F7F0",
+            "navigationBarTextStyle": "black",
+            "enablePullDownRefresh": false
           }
         },
         {
-          "path": "personal_info/personal_info",
+          "path": "face_detect/index",
           "style": {
-            "navigationBarTitleText": "个人资料",
-            "navigationBarBackgroundColor": "#ffe079",
+            "navigationBarTitleText": "实名认证",
+            "navigationBarBackgroundColor": "#FFFFFF",
             "navigationBarTextStyle": "black",
-            "enablePullDownRefresh": false
+            "app-plus": {
+              // #ifdef APP-PLUS
+              "titleNView": {
+                "type": "default"
+              }
+              // #endif
+            }
           }
         },
         {
@@ -398,7 +346,7 @@
         {
           "path": "goods_search/index",
           "style": {
-            "navigationBarBackgroundColor": "#FFE079",
+            "navigationBarBackgroundColor": "#ffffff",
             "navigationBarTitleText": "搜索商品",
             "navigationBarTextStyle": "black"
           }

Fichier diff supprimé car celui-ci est trop grand
+ 2219 - 2127
pages/goods/goods_details/index.vue


+ 201 - 11
pages/goods/goods_search/index.vue

@@ -1,9 +1,9 @@
 <template>
-  <view>
+  <view style="padding-bottom: 32rpx;">
     <view class='searchGood'>
       <view class='search acea-row row-between-wrapper'>
         <view class='input acea-row row-between-wrapper'>
-          <text class='iconfont icon-sousuo'></text>
+          <text class='iconfont icon-sousuo' style="color:#999;"></text>
           <input type='text' confirm-type="search" :value='searchValue' :focus="focus" placeholder='点击搜索商品' placeholder-class='placeholder'
             @input="setValue" @confirm="searchBut" />
         </view>
@@ -16,7 +16,53 @@
 <!--        </block>-->
 <!--      </view>-->
       <view class='line'></view>
-      <goodList :bastList="calculatedProducts" v-if="bastList.length > 0"></goodList>
+      <!-- <goodList :bastList="calculatedProducts" v-if="bastList.length > 0"></goodList> -->
+	  <view class="index-product-wrapper">
+	    <view
+	        class="list-box animated"
+	        :class="bastList.length > 0 ? 'fadeIn on' : ''"
+	    >
+	      <view
+	          class="item"
+	          v-for="(item, index) in calculatedProducts"
+	          :key="index"
+	          @click="goDetail(item)"
+	      >
+	        <view class="pictrue">
+	          <image :src="item.image" mode=""></image>
+	        </view>
+	        <view class="text-info">
+	          <view class="title" >
+	            <view class="text line1">{{ item.storeName }}</view>
+	            <view class="weight">{{ item.weight }}g</view>
+	          </view>
+	          <view class="bottom-row">
+	            <!-- <text class="price">工费: {{ item.price }}/克</text> -->
+	            <text class="price">¥ {{ item.totalPrice }}</text>
+	            <text class="sales" style="color:#666;">
+	              销量:{{ Number(item.sales || 0) + Number(item.ficti || 0) }}件
+	            </text>
+	            <!-- <view class="txt">券</view> -->
+	          </view>
+	          <view class="bottom-row">
+	            <!-- <text class="price">工费: {{ item.price }}/克</text> -->
+	            <text class="sales">工费:¥{{ item.totalLaborCost }}</text>
+	            <text class="sales">
+	              附加费:¥{{ item.additionalAmount }}
+	            </text>
+	            <!-- <view class="txt">券</view> -->
+	          </view>
+	          <template v-if="item?.merchant?.id && merchantNameShow()">
+	            <view class="merchantInfo" @click.stop="toMerchant(item.merchant.id)">
+	              <image class="merchantLogo" :src="item.merchant.merchantLogo" mode="scaleToFill"></image>
+	              <text class="merchantName">{{item.merchant.merchantName}}</text>
+	              <uni-icons style="margin-left: 10rpx;" type="right" size="16" color="#999999"></uni-icons>
+	            </view>
+	          </template>
+	        </view>
+	      </view>
+	    </view>
+	  </view>
       <view class='loadingicon acea-row row-center-wrapper' v-if="bastList.length > 0">
         <text class='loading iconfont icon-jiazai' :hidden='loading == false'></text>{{ loadTitle }}
       </view>
@@ -66,6 +112,28 @@ const {
   realAgprice, // 白银实时销售价(基础)
 } = useRealGoldPrice({});
 
+// Navigation to detail page
+const goDetail = async (item) => {
+  try {
+    uni.navigateTo({
+      url: `/pages/goods/goods_details/index?id=${item.id}`,
+    });
+  } catch (err) {
+    console.error('Navigation error:', err);
+  }
+};
+
+const merchantNameShow = () => {
+  if(!appStore.userInfo ||(appStore.userInfo && !appStore.userInfo.merchant && !appStore.merchantId && !appStore.userInfo.lastVisitedMerchantId)){
+    return true;
+  }else{
+    return false;
+  }
+}
+const toMerchant = (merchantId) => {
+  uni.navigateTo({ url:"/pages/merchantCenters/merchant?merchantId="+merchantId });
+}
+
 const calculatedProducts = computed(() => {
   // 计算逻辑与原代码一致,但基于响应式数据 products
   return bastList.value.map((product) => {
@@ -189,8 +257,9 @@ onReachBottom(() => {
 
 <style lang="scss">
 page {
-  margin-top: var(--status-bar-height);
-  background-color: #fff !important;
+  // margin-top: var(--status-bar-height);
+  background-color: #F9F7F0;
+  height: 100%;
 }
 
 .searchGood .search {
@@ -199,12 +268,12 @@ page {
 }
 
 .searchGood .search {
-  padding-top: 20rpx;
+  padding: 16rpx;
 }
 
 .searchGood .search .input {
   width: 598rpx;
-  background-color: #f7f7f7;
+  background-color: #F9F7F0;
   border-radius: 16rpx;
   padding: 0 35rpx;
   box-sizing: border-box;
@@ -235,9 +304,9 @@ page {
 }
 
 .searchGood .title {
-  font-size: 28rpx;
-  color: #999;
-  margin: 50rpx 30rpx 25rpx 30rpx;
+  // font-size: 28rpx;
+  // color: #999;
+  // margin: 50rpx 30rpx 25rpx 30rpx;
 }
 
 .searchGood .list {
@@ -256,7 +325,128 @@ page {
 }
 
 .searchGood .line {
-  border-bottom: 1rpx solid #eee;
+  // border-bottom: 1rpx solid #eee;
   margin: 20rpx 30rpx 0 30rpx;
 }
+
+.index-product-wrapper {
+  padding: 0 16rpx;
+  margin-bottom: 72rpx; /* 为自定义 tabBar 留出空间 */
+  // min-height: 700rpx;
+  //background: #fff;
+
+  &.on {
+    min-height: 1500rpx;
+  }
+
+  .list-box {
+    display: flex;
+    flex-wrap: wrap;
+    justify-content: space-between;
+
+    .item {
+      width: 48.99%;
+      //height: 490rpx;
+      background-color: #ffffff;
+      // box-shadow: 0rpx 3rpx 13rpx 0rpx rgba(0, 0, 0, 0.13);
+      border-radius: 16rpx;
+      margin-bottom: 16rpx;
+
+      overflow: hidden;
+      display: flex;
+      flex-direction: column;
+      justify-content: space-between;
+
+      .pictrue {
+        position: relative;
+
+        image {
+          width: 100%;
+          height: 330rpx;
+        }
+      }
+
+      .text-info {
+        padding: 16rpx 8rpx;
+
+        .title {
+          color: #333;
+          display: flex;
+          align-items: center;
+          justify-content: space-between;
+          .tip {
+            width: 61rpx;
+            height: auto;
+            font-size: 22rpx;
+            display: flex;
+            justify-content: center;
+            align-items: center;
+            color: #ffffff;
+            position: relative;
+            margin-right: 5rpx;
+            background-color: #ef4800;
+            border-radius: 5rpx;
+          }
+          .text{
+            width: 80%;
+			font-weight: bold;
+          }
+          .weight{
+            background-color: rgba(197, 128, 3, 0.10);
+            color: #C58003;
+            font-size: 24rpx;
+            padding: 8rpx 16rpx;
+            border-radius: 8rpx;
+            float: right;
+          }
+        }
+
+        .bottom-row {
+          color: $theme-color;
+          display: flex;
+          justify-content: space-between;
+          align-items: center;
+          font-size: 28rpx;
+          margin: 10rpx 0 0;
+
+          .price {
+            padding-bottom: 4rpx;
+            font-weight: 800;
+            white-space: nowrap;
+            font-size: 28rpx;
+            color: #f16327;
+          }
+
+          .sales {
+            font-size: 22rpx;
+            white-space: nowrap;
+			flex-shrink: 0;
+            color: #999999;
+          }
+
+        }
+        .merchantInfo{
+          display: flex;
+          align-items: center;
+          height: 40rpx;
+		  margin-top: 16rpx;
+        }
+        .merchantLogo{
+          width: 40rpx;
+          height: 40rpx;
+          border-radius: 50%;
+          margin-right: 8rpx;
+        }
+        .merchantName{
+          font-size: 24rpx;
+          color: #333;
+        }
+      }
+    }
+
+    &.on {
+      display: flex;
+    }
+  }
+}
 </style>

+ 3 - 2
pages/goods_cate/goods_cate.vue

@@ -4,7 +4,7 @@
       <view class='acea-row row-between-wrapper input'>
         <text class='iconfont icon-sousuo'></text>
         <input type='text' placeholder='点击搜索商品信息' @confirm="searchSubmitValue" confirm-type='search' name="search"
-               placeholder-class='placeholder' @focus="searchSubmitValue"></input>
+               placeholder-class='placeholder' @focus="searchSubmitValue"/>
       </view>
     </view>
     <view class='aside' :style="{bottom: tabbarH + 'px',height: height + 'rpx'}">
@@ -77,6 +77,7 @@ const getAllCategory = async () => {
     const { data }= await productCategory(obj);
     const newArr = []
     data.forEach((value, index) => {
+      if(value.name === '折扣券') return
       newArr[index] = value
       if (value.child) newArr[index].child = value.child.filter(item => item.status === true)
     })
@@ -109,7 +110,7 @@ const infoScroll = () => {
   // 设置商品列表高度
   uni.getSystemInfo({
     success: (res) => {
-      height.value = (res.windowHeight) * (750 / res.windowWidth) - 98;
+      height.value = (res.windowHeight) * (750 / res.windowWidth) - 188;
     },
   });
 

Fichier diff supprimé car celui-ci est trop grand
+ 1588 - 1441
pages/index/index.vue


Fichier diff supprimé car celui-ci est trop grand
+ 453 - 500
pages/mall/dapan.vue


Fichier diff supprimé car celui-ci est trop grand
+ 780 - 601
pages/merchantCenter/index.vue


+ 2 - 2
pages/merchantCenters/components/merchant_cate.vue

@@ -172,7 +172,7 @@ defineExpose({
 
 <style scoped lang="scss">
 .productSort{
-  padding-right: 30rpx;
+  // padding-right: 30rpx;
 }
 .productSort .aside {
   position: absolute;
@@ -203,7 +203,7 @@ defineExpose({
 }
 
 .productSort .conter {
-  margin: 0rpx 0 0 200rpx;
+  margin: 0rpx 0 0 180rpx;
   padding: 0 14rpx;
   background-color: #fff;
   border-radius: 16rpx;

+ 26 - 17
pages/merchantCenters/merchant.vue

@@ -3,11 +3,11 @@
 <template>
   <view class="container">
 <!--    商家信息-->
-    <view class="padding20">
+    <view class="merchant-info">
       <view class="store-card">
         <view class="info-top">
           <view class="left">
-            <image class="storeImg" :src="merchantInfo.merchantLogo" mode="aspectFit"></image>
+            <image class="storeImg" :src="merchantInfo.merchantLogo" mode="aspectFill"></image>
           </view>
           <view class="center">
             <view class="name">{{merchantInfo.merchantName}}</view>
@@ -40,7 +40,7 @@
               transform: 'scale(1)'
         }"></up-tabs>
       <!--    商品列表-->
-    <view class="index-product-wrapper padding30" v-if="tabActive == '0'">
+    <view class="index-product-wrapper" v-if="tabActive == '0'">
       <view
           class="list-box animated"
           :class="goodsList.length > 0 ? 'fadeIn on' : ''"
@@ -62,16 +62,16 @@
             <view class="bottom-row">
               <!-- <text class="price">工费: {{ item.price }}/克</text> -->
               <text class="price">¥ {{ item.totalPrice }}</text>
-              <text class="sales">
+              <text class="sales" style="color:#666;">
                 销量:{{ Number(item.sales || 0) + Number(item.ficti || 0) }}件
               </text>
               <!-- <view class="txt">券</view> -->
             </view>
             <view class="bottom-row">
               <!-- <text class="price">工费: {{ item.price }}/克</text> -->
-              <text class="sales">工费{{ item.totalLaborCost }}</text>
+              <text class="sales">工费:¥{{ item.totalLaborCost }}</text>
               <text class="sales">
-                附加费{{ item.additionalAmount }}
+                附加费:¥{{ item.additionalAmount }}
               </text>
               <!-- <view class="txt">券</view> -->
             </view>
@@ -177,9 +177,16 @@ const getSbmerchantInfoFn = async () => {
   }
   let obj ={
     merchantId:query.value.merchantId,
-    userId:appStore.userInfo.userId
+    userId:appStore?.userInfo?.userId
+  }
+  if(appStore?.userInfo?.userId){
+	  await footprintScan(obj)
+	  appStore.USERINFO();
+  }
+  // 当浏览的店铺主页不是上次浏览店铺时,才改变状态
+  if(query.value.merchantId != appStore?.userInfo?.lastVisitedMerchantId){
+	  appStore.setIndexRefersh(true)
   }
-  await footprintScan(obj)
   getSbmerchantInfo(data).then((res) => {
     console.log(res);
     merchantInfo.value = res.data;
@@ -262,11 +269,13 @@ const goDetail = async (item) => {
   //padding: 30rpx;
   //box-sizing: border-box;
 }
+.merchant-info{
+	padding: 16rpx 16rpx 0;
+}
 .store-card{
   background: #ffffff;
   border-radius: 16rpx;
   padding: 20rpx;
-  margin-bottom: 10rpx;
 
   .info-top{
     display: flex;
@@ -320,10 +329,10 @@ const goDetail = async (item) => {
   float: right;
 }
 .index-product-wrapper {
-  //padding: 0 30rpx;
+  padding: 0 16rpx 16rpx;
   margin-bottom: 110rpx;
   min-height: 700rpx;
-  margin-top: 30rpx;
+  margin-top: 16rpx;
   //background: #fff;
   position: relative;
 
@@ -338,11 +347,11 @@ const goDetail = async (item) => {
 
     .item {
       width: 48.99%;
-      height: 490rpx;
+      // height: 490rpx;
       background-color: #ffffff;
-      box-shadow: 0rpx 3rpx 13rpx 0rpx rgba(0, 0, 0, 0.13);
-      border-radius: 20rpx;
-      margin-bottom: 20rpx;
+      // box-shadow: 0rpx 3rpx 13rpx 0rpx rgba(0, 0, 0, 0.13);
+      border-radius: 16rpx;
+      margin-bottom: 16rpx;
 
       overflow: hidden;
       display: flex;
@@ -359,10 +368,10 @@ const goDetail = async (item) => {
       }
 
       .text-info {
-        padding: 10rpx 20rpx 15rpx;
+        padding: 16rpx 8rpx;
 
         .title {
-          color: #222222;
+          color: #333;
           display: flex;
           align-items: center;
           justify-items: space-between;

+ 4 - 3
pages/merchantCenters/productCenter.vue

@@ -26,7 +26,7 @@
     <view class="product-list">
       <view class="product-card" v-for="(item, index) in goodsList" :key="index">
         <view class="product-header">
-          <image class="product-image" :src="item.image" mode="aspectFit" />
+          <image class="product-image" :src="item.image" mode="aspectFill" />
           <view class="product-info">
             <view class="nameweight">
               <text class="product-name">{{ item.storeName }}</text>
@@ -126,9 +126,10 @@ const getGroomList = async () => {
   if (!goodScroll.value) return;
   try {
     loading.value = true;
-    params.value.merchantId = merchantInfo.value.id;
+    // params.value.merchantId = merchantInfo.value.id;
     params.value.keyword = searchVal.value;
-    const { data } = await productsList(params.value);
+	const id = merchantInfo.value.id;
+    const { data } = await productsList({...params.value,productCenter:true});
     goodsList.value = [...goodsList.value, ...data.list] || [];
     goodScroll.value = data.list.length >= params.value.limit;
     params.value.page++;

+ 4 - 3
pages/merchantCenters/productManagement.vue

@@ -51,7 +51,7 @@
     <!-- 商品列表 -->
     <view class="product-list">
       <up-checkbox-group shape="circle" @change="checkboxChange" class="centent" activeColor="#F8C008">
-        <view class="product-card" v-for="(item, index) in goodsList" :key="index">
+        <view class="product-card" v-for="(item, index) in goodsList" :key="item.id">
           <view class="product-header">
             <!-- 多选框 -->
             <up-checkbox
@@ -62,7 +62,7 @@
                 activeColor="#F8C008"
             />
 
-            <image class="product-image" :src="item.image" mode="aspectFit" />
+            <image class="product-image" :src="item.image" mode="aspectFill" />
             <view class="product-info">
               <view class="nameweight">
                 <text class="product-name">{{ item.storeName }}</text>
@@ -213,7 +213,7 @@ const setAllSelectValue = (status) => {
   goodsList.value.forEach(item => {
     if (status) {
       item.checked = true;
-      selectValues.push(item.id);
+      selectValues.push(String(item.id));
       isAllSelect.value = true;
     } else {
       item.checked = false;
@@ -275,6 +275,7 @@ const batchPutOnShell = async () => {
           if (code === 200) {
             uni.showToast({ title: '批量上架成功', icon: 'success' });
             // 从列表中移除上架的商品
+			console.log(selectValue.value)
             goodsList.value = goodsList.value.filter(item => !selectValue.value.includes(item.id.toString()));
             resetSelection();
             footerswitch.value = true; // 退出管理模式

+ 4 - 4
pages/merchantCenters/releaseProduct.vue

@@ -132,7 +132,7 @@
                 <text class="upload-tip">点击上传</text>
               </view>
             </up-upload>
-            <text class="format-tip">支持上传PNG、JPG格式图片,每张不超过5MB,最多可上传5张。</text>
+            <text class="format-tip">支持上传PNG、JPG格式图片,每张不超过5MB,最多可上传10张。</text>
           </view>
         </view>
 
@@ -300,7 +300,7 @@
                 <text class="upload-tip">点击上传</text>
               </view>
             </up-upload>
-            <text class="format-tip">支持上传PNG、JPG格式图片,每张不超过5MB,最多可上传5张。</text>
+            <text class="format-tip">支持上传PNG、JPG格式图片,每张不超过5MB,最多可上传1张。</text>
           </view>
         </view>
         <up-form-item
@@ -919,7 +919,7 @@ const submitForm = async () => {
       ...formData.value
     };
     let urlString = '';
-    if(isProductCenter){
+    if(isProductCenter.value){
       submitData.image =previewImages.value[0].url;
       urlString = JSON.stringify(productImages.value.map(item => item.url));
     }else{
@@ -945,7 +945,7 @@ const submitForm = async () => {
         additionalAmount :formData.value.additionalFee,
         attrValue:"{\"规格\":\"默认\"}",
         barCode : formData.value.barCode,
-        image : isProductCenter ? productImagesGg.value[0].url : productImagesGg.value[0].info.url,
+        image : productImagesGg.value[0]?.info?.url || productImagesGg.value[0].url,
         price : formData.value.laborCost,
         stock : formData.value.stock,
         weight :formData.value.weight

+ 191 - 117
pages/order_addcart/order_addcart.vue

@@ -1,5 +1,5 @@
 <template>
-  <view>
+<!--  <view style="min-height: 100%;">-->
     <view class="shoppingCart copy-data">
       <view class="borRadius14">
           <view
@@ -338,20 +338,22 @@
       id="product-window"
     >
     </productWindow>
-    <!-- <view class="uni-p-b-96"></view> -->
+
+      <!-- <view class="uni-p-b-96"></view> -->
     <!-- <view class="uni-p-b-98"></view> -->
     <!-- #ifdef MP -->
     <!-- <authorize :isAuto="isAuto" :isShowAuth="isShowAuth" @authColse="authColse"></authorize> -->
     <!-- #endif -->
-    
+
     <!-- 自定义 tabBar -->
     <customTabBar :current="2" :showBackTop="false" />
-  </view>
+
+<!--  </view>-->
 </template>
 
 <script setup>
 import { ref, reactive, computed,watch } from "vue";
-import { onLoad, onShow, onReachBottom } from "@dcloudio/uni-app";
+import { onLoad, onShow, onReachBottom,onPullDownRefresh } from "@dcloudio/uni-app";
 import { useAppStore } from "@/stores/app.js";
 import {
   getCartList,
@@ -417,6 +419,7 @@ const isLogin = computed(()=>appStore.isLogin);
 // 添加全选的值控制
 const allCheckboxValue = ref([]);
 
+
 // 监听isAllSelect的变化,同步到allCheckboxValue
 watch(isAllSelect, (newVal) => {
   if (newVal) {
@@ -430,40 +433,91 @@ onLoad((options) => {
   // if (!isLogin.value) {
   //   toLogin();
   // }
+  canShow.value = false;
+  if (isLogin.value) {
+
+    resetAllState();
+
+    Promise.allSettled([
+      getCartListFn(),
+      getInvalidList(),
+      getHostProduct()
+    ]).finally(() => {
+      // 添加一个短暂延迟,确保 DOM 更新完成
+      setTimeout(() => {
+        canShow.value = true;
+        uni.hideLoading();
+      }, 50);
+    });
+  }
 });
 
 onShow(() => {
   // 隐藏原生 tabBar
   uni.hideTabBar();
-  
-  canShow.value = false;
-  if (isLogin.value) {
-    hotPage.value = 1;
-    hostProduct.value = [];
-    hotScroll.value = false;
-    loadend.value = false;
-    page.value = 1;
-    cartList.valid = [];
-    getCartListFn();
-    loadendInvalid.value = false;
-    pageInvalid.value = 1;
-    cartList.invalid = [];
-    getInvalidList();
-    footerswitch.value = true;
-    hotScroll.value = false;
-    hotPage.value = 1;
-    hotLimit.value = 10;
-    cartList.valid = [];
-    cartList.invalid = [];
-    // 不要重置选中状态
-    // isAllSelect.value = false;
-    // selectValue.value = [];
-    // selectCountPrice.value = 0.0;
-    cartCount.value = 0;
-    isShowAuth.value = false;
+  if(appStore.cartRefreshFlag){
+	  refresh();
+	  appStore.SET_CART_REFRESH(false)
   }
 });
+onPullDownRefresh(async () => {
+  refresh()
+})
+
+const refresh = ()=>{
+	canShow.value = false;
+	if (isLogin.value) {
+	  // 重置所有状态
+	  resetAllState();
+	  Promise.allSettled([
+	    getCartListFn(),
+	    getInvalidList(),
+	    getHostProduct()
+	  ]).finally(() => {
+	    // 添加一个短暂延迟,确保 DOM 更新完成
+	    setTimeout(() => {
+	      canShow.value = true;
+		  try {
+		  	uni.stopPullDownRefresh();
+		  } catch (error) {
+		  	//TODO handle the exception
+		  }
+	      uni.hideLoading();
+	    }, 50);
+	  });
+	}
+}
+
+function resetAllState() {
+  footerswitch.value = true;
+  goodsHidden.value = false;
+  hotScroll.value = false;
+  hotPage.value = 1;
+  page.value = 1;
+  pageInvalid.value = 1;
+
+  // 不直接清空数组,而是先保留引用
+  // 避免立即触发响应式更新
+  isAllSelect.value = false;
+  selectValue.value = [];
+  selectCountPrice.value = 0.0;
+  shopCheckbox.value = [];
+  loading.value = false;
+  loadend.value = false;
+  loadendInvalid.value = false;
+  loadingInvalid.value = false;
+  loadTitleInvalid.value = "加载更多";
+
+  // 先重置购物车数据
+  // 使用 Object.assign 保持响应式
+  Object.assign(cartList, {
+    valid: [],
+    invalid: [],
+  });
 
+  // 清空推荐商品
+  hostProduct.value = [];
+}
 onReachBottom(() => {
   if (loadend.value) {
     getInvalidList();
@@ -599,10 +653,10 @@ function reElection(item) {
 
 function getGoodsDetails(item) {
   console.log("item", item);
-  uni.showLoading({
-    title: "加载中",
-    mask: true,
-  });
+  // uni.showLoading({
+  //   title: "加载中",
+  //   mask: true,
+  // });
   cartId.value = item.id;
   product_id.value = item.productId;
   getProductDetail(item.productId)
@@ -1073,101 +1127,115 @@ function getCartData(data) {
 }
 
 async function getCartListFn() {
-  uni.showLoading({
-    title: "加载中",
-    mask: true,
-  });
-  let data = {
-    page: page.value,
-    limit: limit.value,
-    isValid: true,
-  };
-  getCartCounts(true, "sum").then(async (c) => {
-    // 获取购物车商品数量
+  if (loading.value) return;
+  loading.value = true;
+  try {
+    let data = {
+      page: page.value,
+      limit: limit.value,
+      isValid: true,
+    };
+
+    const c = await getCartCounts(true, "sum");
     cartCount.value = c.data.count;
     // 当没有商品时,获取推荐商品
-    if (c.data.count === 0) getHostProduct();
+    if (c.data.count === 0) {
+      await getHostProduct();
+    }
+
+    // 收集所有有效的商品
+    const allValidItems = [];
+
     for (let i = 0; i < Math.ceil(cartCount.value / limit.value); i++) {
       let cartListData = await getCartData(data);
       let valid = cartListData.list;
-      let validList = [...cartList.valid, ...valid];
-      let selectValueArr = [];
 
-      if (validList.length > 0) {
-        for (let index in validList) {
+      // 处理商品数据
+      if (valid.length > 0) {
+        for (let index in valid) {
           // 购物车加减状态
-          if (validList[index].cartNum == 1) {
-            validList[index].numSub = true;
+          if (valid[index].cartNum == 1) {
+            valid[index].numSub = true;
           } else {
-            validList[index].numSub = false;
+            valid[index].numSub = false;
           }
-          // 库存
-          let stock = validList[index].stock ? validList[index].stock : 0;
-
-          // 当购物车数量大于库存时,设置购物车数量为库存
-          if (validList[index].cartNum == stock) {
-            validList[index].numAdd = true;
-          } else if (validList[index].cartNum == validList[index].stock) {
-            validList[index].numAdd = true;
+
+          let stock = valid[index].stock ? valid[index].stock : 0;
+
+          if (valid[index].cartNum == stock) {
+            valid[index].numAdd = true;
+          } else if (valid[index].cartNum == valid[index].stock) {
+            valid[index].numAdd = true;
           } else {
-            validList[index].numAdd = false;
+            valid[index].numAdd = false;
           }
 
-          // attrStatus 判断商品是否有效
-          if (validList[index].attrStatus) {
-            // 关键修改:根据 selectValue 中的ID来设置选中状态
-            if (selectValue.value.includes(validList[index].id)) {
-              validList[index].checked = true;
-              selectValueArr.push(validList[index].id);
-            } else {
-              validList[index].checked = false;
-            }
+          if (valid[index].attrStatus) {
+            valid[index].checked = true;
           } else {
-            validList[index].checked = false;
+            valid[index].checked = false;
           }
         }
+        allValidItems.push(...valid);
       }
-      cartList.valid = validList;
-      data.page += 1;
-      // 不要重置 selectValue,保持原来的选中状态
-      // selectValue.value = selectValueArr;
 
-      let newArr = validList.filter((item) => item.attrStatus);
-      // 全选状态
-      isAllSelect.value = newArr.length > 0 && selectValue.value.length === newArr.length;
-      switchSelect();
+      data.page += 1;
     }
+
+    // 一次性更新数组,避免多次响应式更新
+    cartList.valid = allValidItems;
+
+    // 更新选中状态
+    const selectValueArr = allValidItems
+        .filter(item => item.attrStatus && item.checked)
+        .map(item => item.id);
+
+    selectValue.value = selectValueArr;
+
+    let newArr = allValidItems.filter((item) => item.attrStatus);
+    isAllSelect.value = newArr.length == selectValueArr.length && newArr.length;
+    switchSelect();
+
+  } catch (error) {
+    Toast({
+      title: error.message || '加载失败',
+    });
+  } finally {
     loading.value = false;
-    canShow.value = true;
-    uni.hideLoading();
-  });
+  }
 }
 
-function getInvalidList() {
+async function getInvalidList() {
   if (loadendInvalid.value) return false;
   if (loadingInvalid.value) return false;
-  let data = {
-    page: pageInvalid.value,
-    limit: limitInvalid.value,
-    isValid: false,
-  };
-  getCartList(data)
-    .then((res) => {
-      let invalid = res.data.list,
-        loadendInvalidFlag = invalid.length < limitInvalid.value;
-
-      cartList.invalid = [...invalid, ...cartList.invalid];
-      loadendInvalid.value = loadendInvalidFlag;
-      loadTitleInvalid.value = loadendInvalidFlag
-        ? "我也是有底线的"
-        : "加载更多";
-      pageInvalid.value = pageInvalid.value + 1;
-      loadingInvalid.value = false;
-    })
-    .catch((res) => {
-      loadingInvalid.value = false;
-      loadTitleInvalid.value = "加载更多";
-    });
+
+  loadingInvalid.value = true;
+
+  try {
+    let data = {
+      page: pageInvalid.value,
+      limit: limitInvalid.value,
+      isValid: false,
+    };
+
+    const res = await getCartList(data);
+    let invalid = res.data.list;
+    let loadendInvalidFlag = invalid.length < limitInvalid.value;
+
+    // 一次性更新数组
+    cartList.invalid = [...cartList.invalid, ...invalid];
+
+    loadendInvalid.value = loadendInvalidFlag;
+    loadTitleInvalid.value = loadendInvalidFlag ?
+        "我也是有底线的" :
+        "加载更多";
+    pageInvalid.value = pageInvalid.value + 1;
+
+  } catch (res) {
+    console.error('获取失效商品失败:', res);
+  } finally {
+    loadingInvalid.value = false;
+  }
 }
 
 function getHostProduct() {
@@ -1246,6 +1314,7 @@ const toMerchant = (obj) => {
 
 .shoppingCart {
   // .labelNav
+  padding-bottom: 300rpx;
   .labelNav {
     position: sticky;
     height: 178rpx;
@@ -1328,9 +1397,9 @@ const toMerchant = (obj) => {
         align-items: center;
 
         .pictrue {
-          width: 160rpx;
-          height: 160rpx;
-          margin-right: 15rpx;
+          width: 176rpx;
+          height: 176rpx;
+          margin-right: 16rpx;
 
           image {
             width: 100%;
@@ -1343,9 +1412,10 @@ const toMerchant = (obj) => {
         .text {
           width: 402rpx;
           font-size: 28rpx;
-          color: #282828;
+		  font-weight: bold;
+          color: #333;
           .storeName{
-            width: 40%;
+            width: 50%;
           }
           .reColor {
             color: #999;
@@ -1366,6 +1436,7 @@ const toMerchant = (obj) => {
             display: flex;
             justify-content: space-between;
             .attribute-suk {
+				font-weight: normal;
             }
             .invalid-count {
               text-align: right;
@@ -1478,8 +1549,8 @@ const toMerchant = (obj) => {
         .picTxt {
           width: 576rpx;
           .pictrue {
-            width: 160rpx;
-            height: 160rpx;
+            width: 176rpx;
+            height: 176rpx;
             image {
               width: 100%;
               height: 100%;
@@ -1518,7 +1589,7 @@ const toMerchant = (obj) => {
   padding: 0 24rpx;
   box-sizing: border-box;
   border-top: 1rpx solid #eee;
-  bottom: 0;
+  bottom: 160rpx;
 
 
   .checkAll {
@@ -1535,6 +1606,7 @@ const toMerchant = (obj) => {
   }
   .placeOrder {
     color: #333;
+	font-weight: bold;
     font-size: 32rpx;
     width: 192rpx;
     height: 88rpx;
@@ -1591,11 +1663,13 @@ const toMerchant = (obj) => {
         width: 40rpx;
         height: 40rpx;
         border-radius: 50%;
-        margin-right: 20rpx;
+        margin-right: 8rpx;
       }
 
       .merchant-name {
-        font-size: 24rpx;
+        font-size: 26rpx;
+		line-height: 40rpx;
+		margin-right: 16rpx;
         color: #333;
       }
     }

+ 98 - 32
pages/user/index.vue

@@ -12,7 +12,7 @@
       </template>
     </up-navbar>
     <!-- 顶部用户信息 -->
-    <view class="user-header">
+    <view class="user-header jianbianBG">
       <view class="user-info">
         <view class="user-main">
           <view>
@@ -24,7 +24,7 @@
           <view class="user-detail">
             <view class="name-vip" v-if="appStore.isLogin">
               <text class="name">{{ appStore.$userInfo?.nickname }}</text>
-              <image class="vip-tag" v-if="appStore.$userInfo?.svip" mode="widthFix" :src="HTTP_REQUEST_URL_IMG+'sviplogo.png'"></image>
+              <image class="vip-tag" v-if="appStore.$userInfo?.svip && !(appStore?.$wxConfig?.auditModeEnabled)" mode="widthFix" :src="HTTP_REQUEST_URL_IMG+'sviplogo.png'"></image>
             </view>
             <view
               class="name-vip"
@@ -37,8 +37,19 @@
             <text class="vip-expire" v-if="appStore.$userInfo?.svip"
               >到期时间:{{ appStore.$userInfo?.svipExpireTime }}</text
             >
+            <view class="intro">
+              <view class="item" @click="handleFaceDetect">
+                {{ appStore.$userInfo?.realNameVerified ? "已实名" : "未实名" }}
+              </view>
+              <view class="item" v-if="userInfoAddres !== ''">IP:
+                {{ userInfoAddres }}
+              </view>
+
+              <view class="item" v-if="appStore.$userInfo?.sex && appStore.$userInfo?.sex !== 0 ">{{ sexMap[appStore.$userInfo?.sex] }}·{{ appStore.$userInfo?.age }}岁</view>
+            </view>
           </view>
         </view>
+
         <view class="btn-content" @click="handleEdit()">
           <image
             class="setting"
@@ -49,8 +60,9 @@
         </view>
       </view>
 
+
       <!-- 会员开通提示 v-if="!userInfo.isVip"-->
-      <view class="vip-promote" v-if="useList&&useList.length>0&&showIcons">
+      <view class="vip-promote" v-if="!(appStore?.$wxConfig?.auditModeEnabled)">
         <image class="vipBG" :src="HTTP_REQUEST_URL_IMG+'vipBG.png'" mode="scaleToFill"></image>
         <view class="vip-text">
           <view class="title">
@@ -74,7 +86,7 @@
         <view
           class="transaction-detail"
           @click="viewTransactionDetail"
-          v-if="useList && useList.length > 0 && showIcons"
+          v-if="!(appStore?.$wxConfig?.auditModeEnabled)"
         >
           <text style="margin-right: 10rpx">交易明细</text>
           <uni-icons type="right" size="16" color="#666666"></uni-icons>
@@ -144,7 +156,7 @@
         <template v-for="(store,storeIndex) in recentStores" :key="store.id">
           <view class="store-item" v-if="storeIndex == 0" @click="viewStore(store)">
               <view class="store-logo">
-                <image class="img" :src="store.merchantLogo"></image>
+                <image class="img" :src="store.merchantLogo" mode="aspectFill"></image>
               </view>
               <view class="store-info">
                 <text class="store-name">{{ store.merchantName }}</text>
@@ -178,7 +190,7 @@
           @click="viewOrders(order.id)"
         >
           <view class="status-icon">
-            <image class="img" :src="order.src" mode="widthFix"></image>
+            <image class="img" :src="order.src"></image>
           </view>
           <text class="status-name">{{ order.name }}</text>
         </view>
@@ -372,6 +384,18 @@ const params = ref({
   page: 1,
   limit: 10,
 });
+const sexMap = {
+  0: "未知",
+  1: "男",
+  2: "女",
+  3: "保密",
+};
+
+const userInfoAddres = computed(() => {
+  let address = appStore.userInfo?.addres || "";
+  const list = address.split("-");
+  return list[0] || "";
+});
 
 // 页面加载
 onShow(async () => {
@@ -414,12 +438,14 @@ onPageScroll((e) => {
 const wxConfig = ref({});
 const tradeList = ref([]);
 const useList = ref([]);
+const isOwner = ref(true);
 watch(
   () => appStore.wxConfig,
   (newVal) => {
     const configDate = newVal || appStore.$wxConfig;
     wxConfig.value = configDate;
     const list = JSON.parse(configDate.essentialFunctions);
+    console.log('list',list)
     if (list[0].status == false) {
       showIcons.value = false;
     } else {
@@ -468,21 +494,24 @@ const openVip = () => {
 
 // 查看会员权益
 const goVIP = () => {
-  uni.navigateTo({ url: "/pages/users/VIP/VIP" });
+  // uni.navigateTo({ url: "/pages/users/VIP/VIP" });
+  goDetail("/pages/users/VIP/VIP")
 };
 
 // 查看交易明细
 const viewTransactionDetail = () => {
-  if (!isLogin) {
+  console.log(isLogin)
+  if (!appStore.isLogin) {
     toLogin();
   } else {
-    uni.navigateTo({ url: "/pages/users/vault/index" });
+    // uni.navigateTo({ url: "/pages/users/vault/index" });
+    goDetail("/pages/users/vault/index1")
   }
 };
 
 // 充值
 const recharge = () => {
-  if (!isLogin) {
+  if (!appStore.isLogin) {
     toLogin();
   } else {
     uni.navigateTo({
@@ -493,7 +522,7 @@ const recharge = () => {
 
 // 提现
 const withdraw = () => {
-  if (!isLogin) {
+  if (!appStore.isLogin) {
     toLogin();
   } else {
     uni.navigateTo({
@@ -644,19 +673,29 @@ const getHistoryList = async () => {
   const { data } = await footprintList(params.value);
   recentStores.value = data.records;
 };
+//人脸识别
+function handleFaceDetect() {
+  // #ifndef APP-PLUS
+  if (appStore.userInfo.realNameVerified || !isOwner.value) return;
+  uni.navigateTo({
+    url: "/pages/users/face_detect/index"
+  });
+  // #endif
+
+}
 </script>
 
 <style scoped lang="scss">
 .container {
   background-color: #f5f5f5;
   min-height: 100vh;
-  padding-bottom: 30rpx;
+  padding-bottom: 180rpx;
 }
 
 /* 顶部用户信息 */
 .user-header {
   height: 600rpx;
-  background-image: linear-gradient(200deg, #fcd965 0%, #ffffff 90%) !important;
+  //background-image: linear-gradient(200deg, #fcd965 0%, #ffffff 90%) !important;
   background-size: 100% 100%;
   padding: 150rpx 20rpx 20rpx;
   color: #fff;
@@ -668,17 +707,21 @@ const getHistoryList = async () => {
   display: flex;
   justify-content: space-between;
   align-items: center;
-  margin-bottom: 30rpx;
+  margin-bottom: 20rpx;
+}
+.user-detail{
+  display: flex;
+  flex-direction: column;
+  justify-content: center;
 }
-
 .user-main {
   display: flex;
   align-items: center;
 }
 
 .avatar {
-  width: 120rpx;
-  height: 120rpx;
+  width: 140rpx;
+  height: 140rpx;
   border-radius: 50%;
   background-color: #fff;
   margin-right: 30rpx;
@@ -687,7 +730,7 @@ const getHistoryList = async () => {
 .name-vip {
   display: flex;
   align-items: center;
-  margin-bottom: 16rpx;
+  margin-bottom: 14rpx;
 }
 
 .name {
@@ -700,10 +743,10 @@ const getHistoryList = async () => {
   margin-left: 16rpx;
 }
 
-.vip-expire,
-.login-tip {
+.vip-expire{
   font-size: 28rpx;
   color: #666;
+  margin-bottom: 14rpx;
 }
 
 .btn-content {
@@ -762,11 +805,13 @@ const getHistoryList = async () => {
     .open-vip {
       width: 144rpx;
       height: 60rpx;
-      line-height: 60rpx;
       font-size: 24rpx;
       color: #5d3d03;
       background: linear-gradient(270deg, #fee2a3 0%, #fdebcc 100%);
       border-radius: 16rpx 16rpx 16rpx 16rpx;
+      display: flex;
+      justify-content: center;
+      align-items: center;
       .bofang {
         width: 24rpx;
         height: 24rpx;
@@ -784,9 +829,9 @@ const getHistoryList = async () => {
 /* 钱包余额 */
 .wallet-section {
   background: #fff;
-  margin: -190rpx 20rpx 20rpx;
+  margin: -176rpx 20rpx 20rpx;
   border-radius: 24rpx;
-  padding: 30rpx;
+  padding: 32rpx;
 }
 
 .wallet-header {
@@ -862,6 +907,7 @@ const getHistoryList = async () => {
 
 .wallet-btn {
   flex: 1;
+  font-weight: bold;
   text-align: center;
   height: 88rpx;
   line-height: 88rpx;
@@ -916,16 +962,16 @@ const getHistoryList = async () => {
 .order-section,
 .common-functions {
   background: #fff;
-  margin: 20rpx;
+  margin: 16rpx;
   border-radius: 16rpx;
-  padding: 30rpx;
+  padding: 20rpx;
 }
 
 .section-header {
   display: flex;
   justify-content: space-between;
   align-items: center;
-  margin-bottom: 30rpx;
+  margin-bottom: 20rpx;
 }
 
 .section-title {
@@ -942,8 +988,8 @@ const getHistoryList = async () => {
   display: flex;
   align-items: center;
   justify-content: flex-start;
-  padding: 20rpx;
-  border-bottom: 2rpx solid #f0f0f0;
+  padding: 16rpx;
+  // border-bottom: 2rpx solid #f0f0f0;
   background-color: #f9f7f0;
   border-radius: 16rpx;
 }
@@ -953,18 +999,20 @@ const getHistoryList = async () => {
 }
 
 .store-logo {
+	width: 100rpx;
+	height: 100rpx;
+    margin-right: 16rpx;
   .img {
     width: 100rpx;
     height: 100rpx;
-    border-radius: 16rpx;
-    margin-right: 30rpx;
+    border-radius: 8rpx;
   }
 }
-
 .store-name {
   font-size: 32rpx;
+  font-weight: bold;
   color: #333;
-  margin-bottom: 20rpx;
+  margin-bottom: 10rpx;
   display: block;
 }
 
@@ -1029,4 +1077,22 @@ const getHistoryList = async () => {
     }
   }
 }
+.intro {
+  display: flex;
+  align-items: center;
+
+  .item {
+    color: #333;
+    font-size: 24rpx;
+    padding: 0 16rpx;
+    line-height: 40rpx;
+    margin-right: 16rpx;
+    background: #FEF8E6;
+    border-radius: 8rpx;
+
+    &:last-child {
+      margin-right: 0;
+    }
+  }
+}
 </style>

+ 9 - 5
pages/users/browsing_history/index.vue

@@ -7,7 +7,7 @@
           class="record-item"
       >
         <view>
-          <image class="icon-container" :src="record.merchantLogo" mode="aspectFit"></image>
+          <image class="icon-container" :src="record.merchantLogo"></image>
         </view>
         <view class="info-container">
           <view class="shop-name">{{ record.merchantName }}</view>
@@ -22,8 +22,9 @@
         ></text>
       </view>
       <view class="no-data" v-if="isNoDataState">
-        <image
-            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/zhanwu_20250827104005_1720_6.png"
+        <image class="img"
+            :src="HTTP_REQUEST_URL_IMG+'noData.png'"
+               mode="widthFix"
         />
       </view>
       <view class="mores-txt flex" v-if="!goodScroll && !isNoDataState">
@@ -37,7 +38,7 @@
 import {computed, ref} from 'vue';
 import { onLoad, onShow, onReachBottom } from "@dcloudio/uni-app";
 import { footprintList } from "@/api/merchant.js";
-
+import { HTTP_REQUEST_URL_IMG } from "@/config/app";
 const records = ref([]);
 const loading = ref(false);
 const goodScroll = ref(true);
@@ -147,8 +148,11 @@ const toMerchant = (obj) => {
 .no-data {
   margin: 150rpx auto 0;
   text-align: center;
+  width: 100%;
+  height: 100%;
+  min-height: 300rpx;
 
-  img {
+  .img {
     width: 65%;
     height: auto;
   }

+ 631 - 0
pages/users/face_detect/index.vue

@@ -0,0 +1,631 @@
+<template>
+	<view class="container">
+		<!-- <up-notify type="success" ref="uNotifyRef" duration="0" :show="true" message="Hi uview-plus"
+			:safeAreaInsetTop="true">审核中</up-notify> -->
+		
+		<view class="upload-section">
+			<!-- 状态展示 -->
+			<view v-if="verifyInfo" class="verify-status">
+				<view>认证状态:{{ statusText }}</view>
+			</view>
+			<!-- 身份证正面上传 -->
+			<view class="upload-box">
+				<view class="upload-title">上传身份证</view>
+				<view class="upload-box-list">
+					<up-upload width="335rpx" height="208rpx" :fileList="frontImageList" @afterRead="afterReadFront"
+						@delete="deletePicFront" :deletable="deletable" :previewImage="true" imageMode="aspectFill" name="front"
+						:maxCount="1">
+						<template #trigger>
+							<view class="upload-block">
+								<image mode="" v-if="frontImageList.length === 0" src="/static/img/IDFront.png" class="IDFront" />
+
+							</view>
+						</template>
+					</up-upload>
+					<up-upload width="335rpx" height="208rpx" :fileList="backImageList" @afterRead="afterReadBack"
+						@delete="deletePicBack" :previewImage="true" :deletable="deletable" imageMode="aspectFill" name="back"
+						:maxCount="1">
+						<template #trigger>
+							<view class="upload-block">
+								<image mode="aspectFill" v-if="backImageList.length === 0" src="/static/img/IDReverse.png"
+									class="IDBack" />
+							</view>
+						</template>
+					</up-upload>
+				</view>
+			</view>
+			<!-- 身份信息输入 -->
+			<view class="info-section">
+
+				<view class="info-title">身份信息</view>
+				<view class="info-form">
+					<view class="form-item">
+						<up-input v-model="realName" placeholder="请输入真实姓名" border="surround" clearable :customStyle="inputStyle"
+							:disabled="isReadonly" inputAlign="right">
+							<template #prefix>
+								<view class="">姓名</view>
+							</template>
+						</up-input>
+					</view>
+					<view class="form-item">
+						<up-input v-model="idCardNumber" placeholder="请输入身份证号码" border="surround" clearable
+							:customStyle="inputStyle" type="idcard" @change="onIdCardChange" maxlength="18" :disabled="isReadonly"
+							inputAlign="right">
+							<template #prefix>
+								<view class="">身份证号</view>
+							</template>
+						</up-input>
+					</view>
+				</view>
+			</view>
+			<view class="info-tips">
+				<image src="/static/img/tips@2x.png" mode=""></image>
+				<view class="">
+					<view class="">上传说明:</view>
+					<view class="">1.请确保身份证信息清晰可见</view>
+					<view class="">2.请上传真实的身份证照片</view>
+					<view class="">3.请确保光线充足,避免反光</view>
+					<view class="">4.请确保姓名和身份证号与身份证照片一致</view>
+				</view>
+			</view>
+		</view>
+		<view class="kong"></view>
+		<view class="footer">
+			<up-button class="btn" @click="submitDetect" :disabled="!canSubmit || isProcessing || isReadonly">
+				{{
+          isProcessing ? "认证中..." : isRejected ? "重新提交认证" : "提交认证"
+        }}
+			</up-button>
+		</view>
+	</view>
+</template>
+
+<script setup>
+	import {
+		ref,
+		computed
+	} from "vue";
+	import {
+		onLoad
+	} from "@dcloudio/uni-app";
+	import {
+		init,
+		query
+	} from "@/api/faceVerify.js";
+	import {
+		useToast
+	} from "@/hooks/useToast";
+	import {
+		useImageUpload
+	} from "@/hooks/useImageUpload";
+	import {
+		faceVerify,
+		getFaceVerify
+	} from "@/api/user";
+	import {
+		useAppStore
+	} from "@/stores/app";
+
+	const {
+		Toast
+	} = useToast();
+	const appStore = useAppStore();
+	const idCardPicUrl = ref("");
+	const isProcessing = ref(false);
+	const realName = ref("");
+	const idCardNumber = ref("");
+	const emit = defineEmits(["fetchUserInfo"]);
+	const verifyInfo = ref(null);
+	const deletable = ref(true);
+
+	// #ifdef APP
+	const aliyunVerify = uni.requireNativePlugin("AP-FaceDetectModule");
+	// #endif
+
+
+
+	const certifyId = ref("");
+	const metaInfo = ref("");
+
+	// 正面上传
+	const {
+		imageList: frontImageList,
+		afterRead: afterReadFront,
+		deletePic: deletePicFront,
+	} = useImageUpload({
+		pid: 7,
+		model: "user",
+	});
+	console.log("frontImageList", frontImageList.value);
+	// 反面上传
+	const {
+		imageList: backImageList,
+		afterRead: afterReadBack,
+		deletePic: deletePicBack,
+	} = useImageUpload({
+		pid: 5,
+		model: "user",
+	});
+
+	// 输入框样式
+	const inputStyle = {
+		backgroundColor: "#F9F7F0",
+		borderRadius: "16rpx",
+		padding: "28rpx 16rpx",
+		fontSize: "28rpx",
+		border: 'none'
+	};
+
+	const isReadonly = computed(() => {
+		return (
+			verifyInfo.value &&
+			(verifyInfo.value.status === 0 || verifyInfo.value.status === 1)
+		);
+	});
+	const showUploadImg = computed(() => {
+		// 如果是被拒绝状态,不显示已上传的图片,允许重新上传
+		if (isRejected.value) {
+			return false;
+		}
+		return verifyInfo.value || frontImageList.value[0]?.info?.url;
+	});
+	const isRejected = computed(() => {
+		return verifyInfo.value && verifyInfo.value.status === 2;
+	});
+	const statusText = computed(() => {
+		if (!verifyInfo.value) return "";
+		switch (verifyInfo.value.status) {
+			case 0:
+				return "审核中";
+			case 1:
+				return "已通过";
+			case 2:
+				return verifyInfo.value?.approveMsg || "认证被拒绝,请重新提交";
+			default:
+				return "";
+		}
+	});
+
+	// 计算是否可以提交(基础校验)
+	const canSubmit = computed(() => {
+		return (
+			frontImageList.value.length > 0 &&
+			backImageList.value.length > 0 &&
+			realName.value.trim() &&
+			idCardNumber.value.trim()
+		);
+	});
+
+	onLoad(() => {
+		fetchFaceVerify();
+	});
+
+	// 获取实名状态
+	async function fetchFaceVerify() {
+		try {
+			const {
+				data
+			} = await getFaceVerify({
+				uid: appStore.uid
+			});
+			if (data?.list.length > 0) {
+				verifyInfo.value = data.list[0];
+				realName.value = verifyInfo.value.realName || "";
+				idCardNumber.value = verifyInfo.value.cardId || "";
+				frontImageList.value[0] = {
+					url: verifyInfo.value.idCardFront,
+				};
+				backImageList.value[0] = {
+					url: verifyInfo.value.idCardBack,
+				};
+				if (verifyInfo.value.status === 0 || verifyInfo.value.status === 1) {
+					deletable.value = false;
+				}
+				// 如果是被拒绝状态,清空上传列表,允许重新上传
+				// if (verifyInfo.value.status === 2) {
+				//   frontImageList.value = [];
+				//   backImageList.value = [];
+				// }
+			} else {
+				verifyInfo.value = null;
+				realName.value = "";
+				idCardNumber.value = "";
+				frontImageList.value = [];
+				backImageList.value = [];
+			}
+		} catch (error) {
+			console.error("getFaceVerify", error);
+		}
+	}
+
+	function submitDetect() {
+		if (isReadonly.value) {
+			Toast({
+				title: "当前状态不可提交"
+			});
+			return;
+		}
+		if (!frontImageList.value.length || !backImageList.value.length) {
+			Toast({
+				title: "请先上传身份证正反面照片"
+			});
+			return;
+		} else if (!realName.value.trim()) {
+			Toast({
+				title: "请输入真实姓名"
+			});
+			return;
+		} else if (!idCardNumber.value.trim()) {
+			Toast({
+				title: "请输入身份证号码"
+			});
+			return;
+		} else if (!validateIdCard(idCardNumber.value.trim())) {
+			Toast({
+				title: "请输入正确的身份证号码"
+			});
+			return;
+		}
+		// 检查图片上传状态
+		const frontImage = frontImageList.value[0];
+		const backImage = backImageList.value[0];
+		console.log(frontImage, backImage);
+		if (!frontImage || !backImage) {
+			Toast({
+				title: "请先上传身份证正反面照片"
+			});
+			return;
+		}
+		if (frontImage?.status === "failed" || backImage?.status === "failed") {
+			Toast({
+				title: "有图片上传失败,请重新上传"
+			});
+			return;
+		}
+		if (frontImage?.status === "uploading" || backImage?.status === "uploading") {
+			Toast({
+				title: "图片正在上传中,请稍候"
+			});
+			return;
+		}
+		try {
+			isProcessing.value = true;
+			uni.showLoading({
+				title: "开始认证"
+			});
+			console.log("frontImage?.info", frontImage?.info);
+			const frontImageUrl = frontImage.info?.url || frontImage.url;
+			const backImageUrl = backImage.info?.url || backImage.url;
+			if (!frontImageUrl || !backImageUrl) {
+				Toast({
+					title: "图片上传失败,请重新上传"
+				});
+				uni.hideLoading();
+				isProcessing.value = false;
+				return;
+			}
+			const params = {
+				uid: appStore.uid,
+				idCardFront: frontImageUrl,
+				idCardBack: backImageUrl,
+				realName: realName.value.trim(),
+				cardId: idCardNumber.value.trim(),
+			};
+			faceVerify(params)
+				.then((res) => {
+					uni.hideLoading();
+					Toast({
+						title: "认证已提交,正在审核..."
+					});
+					emit("fetchUserInfo");
+					// 认证成功后清空所有数据
+					frontImageList.value = [];
+					backImageList.value = [];
+					realName.value = "";
+					idCardNumber.value = "";
+					isProcessing.value = false;
+					fetchFaceVerify(); // 重新拉取状态
+				})
+				.catch((err) => {
+					console.log("submitDetect-err", err);
+					uni.hideLoading();
+					isProcessing.value = false;
+					Toast({
+						title: err?.msg || "认证失败,请重试"
+					});
+				});
+		} catch (err) {
+			console.log("submitDetect-err", err);
+			uni.hideLoading();
+			isProcessing.value = false;
+			Toast({
+				title: "认证失败,请重试"
+			});
+		}
+	}
+
+	// 身份证号码验证
+	function validateIdCard(idCard) {
+		const reg = /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/;
+		return reg.test(idCard);
+	}
+	// 身份证号码输入处理
+	function onIdCardChange(value) {
+		if (value) {
+			idCardNumber.value = value.toUpperCase();
+		}
+	}
+	// 重试上传
+	function retryUpload(type) {
+		if (type === "front") {
+			frontImageList.value = [];
+		} else if (type === "back") {
+			backImageList.value = [];
+		}
+	}
+
+	// 重新上传(清空后重新选择)
+	function reUpload(type) {
+		if (type === "front") {
+			frontImageList.value = [];
+		} else if (type === "back") {
+			backImageList.value = [];
+		}
+	}
+
+	//调用getMetaInfo获取MetaInfo数据
+	function startVerify() {
+		try {
+			console.log("aliyunVerify", aliyunVerify);
+			metaInfo.value = aliyunVerify.getMetaInfo();
+			let p = uni.getSystemInfoSync().platform;
+			if (p === "ios") {
+				metaInfo.value = JSON.stringify(metaInfo);
+			}
+			console.log("metaInfo", metaInfo.value);
+			initFn();
+		} catch (error) {
+			console.log("startVerify-error", error);
+		}
+	}
+
+	function initFn() {
+		console.log("initFn-start");
+		try {
+			uni.showLoading({
+				title: "开始认证"
+			});
+			init({
+					idCardPicUrl: idCardPicUrl.value,
+					metaInfo: metaInfo.value,
+				})
+				.then((res) => {
+					console.log("initFn-----", res);
+					certifyId.value = res.data.certifyId || "";
+					uni.hideLoading();
+					aliyunVerify.verify({
+							certifyId: certifyId.value,
+							extParams: {},
+						},
+						function(response) {
+							console.log("aliyunVerify", response, response?.code);
+							if (response?.code == 1000) {
+								queryFn();
+							}
+						}
+					);
+				})
+				.catch((err) => {
+					console.log("initFn-err", err);
+					certifyId.value = "";
+				});
+		} catch (err) {
+			console.log("initFn-err", err);
+		}
+	}
+
+	function queryFn() {
+		console.log("initFn-start");
+		query({
+				certifyId: certifyId.value,
+			})
+			.then((res) => {
+				const passed = res.data && res.data.passed;
+				if (passed == "T") {
+					Toast({
+						title: "认证成功"
+					});
+					emit("fetchUserInfo");
+				} else {
+					Toast({
+						title: "认证失败,请确认身份证和人脸信息是否一致?"
+					});
+				}
+				console.log("queryFn", res);
+			})
+			.catch((err) => {
+				console.log("queryFn-err", err);
+			});
+	}
+
+	defineExpose({
+		startVerify,
+	});
+</script>
+
+<style lang="scss" scoped>
+	page {
+		background-color: #F9F7F0;
+	}
+
+	.upload-section {
+		padding: 16rpx;
+	}
+
+	.upload-box {
+		padding: 16rpx;
+		border-radius: 16rpx;
+		background: #FFFFFF;
+
+		&:last-child {
+			margin-bottom: 0;
+		}
+
+		::v-deep .u-upload__wrap {
+			// width: 100%;
+
+			.u-upload__wrap__preview {
+				// width: 100%;
+				margin: 0;
+
+				.u-upload__wrap__preview__image {
+					// width: 100% !important;
+				}
+			}
+
+			view:last-child {
+				flex: 1;
+			}
+		}
+	}
+
+	.upload-title {
+		font-size: 32rpx;
+		font-weight: 600;
+		color: #333;
+		margin-bottom: 16rpx;
+	}
+
+	.upload-box-list {
+		display: flex;
+	}
+
+	.upload-block {
+		width: 335rpx;
+
+	}
+
+	.IDFront,
+	.IDBack {
+		width: 100%;
+		height: 206rpx;
+		object-fit: cover;
+		border-radius: 8rpx;
+	}
+
+
+	.status-text {
+		font-size: 22rpx;
+		font-weight: 500;
+
+		&.uploading {
+			color: #fa8013;
+		}
+
+		&.failed {
+			color: #ff4444;
+		}
+
+		&.success {
+			color: #52c41a;
+		}
+	}
+
+	.retry-btn {
+		color: #fa8013;
+		text-decoration: underline;
+		margin-left: 10rpx;
+		font-size: 20rpx;
+	}
+
+	.upload-show {
+		padding: 15rpx;
+		background-color: #f8f9fa;
+		border-radius: 12rpx;
+	}
+
+	.info-section {
+		margin: 16rpx 0;
+		background-color: #fff;
+		border-radius: 16rpx;
+		padding: 16rpx;
+	}
+
+	.info-tips {
+		padding: 10rpx 16rpx;
+		display: flex;
+		background: #FEF2CE;
+		border-radius: 16rpx;
+		border: 1rpx solid #F8C008;
+
+		image {
+			top: 4rpx;
+			width: 32rpx;
+			height: 32rpx;
+			margin-right: 8rpx;
+		}
+
+		view {
+			flex: 1;
+			color: #333333;
+			font-size: 24rpx;
+			line-height: 40rpx;
+		}
+	}
+
+	.info-title {
+		font-size: 32rpx;
+		font-weight: 600;
+		color: #333;
+		margin-bottom: 16rpx;
+	}
+
+	.info-form {
+		.form-item {
+			margin-bottom: 16rpx;
+
+			&:last-child {
+				margin-bottom: 0;
+			}
+		}
+	}
+
+	.verify-status {
+		background-color: #fff;
+		border-radius: 16rpx;
+		padding: 16rpx;
+		font-size: 28rpx;
+		font-weight: 600;
+		color: #F8C008;
+		margin-bottom: 16rpx;
+	}
+
+	
+.kong {
+		height: calc(132rpx + constant(safe-area-inset-bottom));
+		height: calc(132rpx + env(safe-area-inset-bottom));
+	}
+	.footer {
+		width: 100%;
+		background: #FFFFFF;
+		box-shadow: inset 0rpx 1rpx 0rpx 0rpx #F1F3F8;
+		padding: 22rpx 32rpx calc(22rpx + constant(safe-area-inset-bottom));
+		padding: 22rpx 32rpx calc(22rpx + env(safe-area-inset-bottom));position: fixed;
+		bottom: 0;
+
+		.btn {
+			font-size: 32rpx;
+			color: #333333;
+			font-weight: bold;
+			background-color: #F8C008;
+			border-radius: 16rpx;
+			text-align: center;
+			line-height: 88rpx;
+
+			&:disabled {
+				background-image: linear-gradient(to right, #ccc 0%, #ccc 100%);
+				color: #999;
+			}
+		}
+	}
+</style>

+ 233 - 65
pages/users/login/index.vue

@@ -1,17 +1,27 @@
 <template>
-	<div class="login-wrapper">
+	<div class="login-wrapper bglogin">
 		<up-navbar title="登录" placeholder>
 			<template #left>
-				<view class=""></view>
+				<!--        <view-->
+				<!--            v-if="appStore?.$wxConfig?.auditModeEnabled"-->
+				<!--            @click="backHome"-->
+				<!--        >-->
+				<!--          <image src="@/static/images/tabbar/1-001.png" style="height: 40rpx;width: 40rpx;"></image>-->
+				<!--        </view>-->
+				<view class="back_extend" v-if="appStore?.$wxConfig?.auditModeEnabled" @click="backHome">
+					{{ "<" }} 回到首页
+				</view>
 			</template>
 		</up-navbar>
 		<div class="shading">
 			<view class="">Hello!</view>
 			<view class="">欢迎来到水贝搬运工</view>
+			<image src="@/static/images/login_ip.png" class="ip-pic"></image>
 		</div>
 		<div class="whiteBg" v-if="formItem === 1">
-			<view class="whiteBg-tab" :class="{'whiteBg-tabs':current == 1}">
-				<view @click="current = item.type" :class="{active:current != index,noActive:current == index}" class="whiteBg-tab-li" v-for="(item,index) in navList" :key="index">
+			<view class="whiteBg-tab whiteBg-tabimg" :class="{'whiteBg-tabs whiteBg-tabsimg':current == 1}">
+				<view @click="current = item.type" :class="{active:current != index,noActive:current == index}"
+					class="whiteBg-tab-li" v-for="(item,index) in navList" :key="index">
 					<view class="">{{ item.name }}</view>
 				</view>
 			</view>
@@ -32,13 +42,13 @@
 						</button>
 					</div>
 					<div class="item">
-						<input type="text" class="texts" placeholder="输入邀请码(非必填)" v-model="inviteCode" />
+						<input type="text" class="texts" placeholder="输入邀请码" v-model="inviteCode" />
 					</div>
 				</template>
-				
+
 			</div>
 			<div class="privacy-box" @click="aloneChecked = !aloneChecked">
-				
+
 				<image v-if="aloneChecked" src="/static/images/select-active@2x.png" mode=""></image>
 				<image v-else src="/static/images/select@2x.png" mode=""></image>
 				<view class="">我已阅读并同意</view>
@@ -46,10 +56,26 @@
 				<view class="privacy-text" @click.stop="openPrivacy">《隐私政策》</view>
 			</div>
 			<view class="footer">
-				<div class="logon" @click="loginMobile" v-if="current !== 0">登录</div>
-				<div class="logon" @click="submit" v-if="current === 0">登录</div>
+				<button class="logon" @click="loginMobile" v-if="current !== 0">登录</button>
+				<!-- <button class="logonWX"  open-type="getPhoneNumber" @getphonenumber="getPhoneNumberFn" v-if="current !== 0">微信登录</button> -->
+				<button class="logon" @click="submit" v-if="current === 0">登录</button>
 			</view>
-		
+			<view class="wx-login" open-type="getPhoneNumber" @getphonenumber="getPhoneNumberFn" v-if="current !== 0">
+				<view class="wx-login-tip">
+					<view class="login-line">
+					</view>
+					<text class="wx-tip">第三方登录</text>
+					<view class="login-line">
+					</view>
+				</view>
+				<view class="wx-login-btn">
+					<button class="logonWX" open-type="getPhoneNumber" @getphonenumber="getPhoneNumberFn"
+						v-if="current !== 0">
+						<image class="wx-icon" src="@/static/images/wxLogin.png" mode="widthFix"></image>
+					</button>
+				</view>
+			</view>
+
 		</div>
 	</div>
 </template>
@@ -85,6 +111,9 @@
 		useSendCode
 	} from "@/hooks/useSendCode";
 	import Cache from "@/utils/cache";
+	import {
+		getPhoneNumber
+	} from "@/utils/util.js";
 	import {
 		useToast
 	} from "@/hooks/useToast.js";
@@ -94,7 +123,9 @@
 	// import {
 	// 	getGroupchatList
 	// } from "@/api/customerService";
-  import { footprintScan } from "@/api/merchant.js";
+	import {
+		footprintScan
+	} from "@/api/merchant.js";
 	import {
 		EXPIRES_TIME
 	} from "@/config/cache";
@@ -111,7 +142,13 @@
 	const BACK_URL = "login_back_url";
 
 	// Reactive state
-	const navList = ref([{name:"快速登录",type:1}, {name:"账号登录",type:0}]);
+	const navList = ref([{
+		name: "快速登录",
+		type: 1
+	}, {
+		name: "账号登录",
+		type: 0
+	}]);
 	const current = ref(1);
 	const account = ref("");
 	const inviteCode = ref(""); // 邀请码
@@ -123,17 +160,17 @@
 	const keyCode = ref("");
 	const codeUrl = ref("");
 	const codeVal = ref("");
-	
+
 	const platform = ref("");
-	
-	
-	
-	
+
+
+
+
 	const appleShow = ref(false);
 	const aloneChecked = ref(false);
 
-  const merchantId = ref('');
-  const userInfo = ref({});
+	const merchantId = ref('');
+	const userInfo = ref({});
 
 	// Watch formItem to update type
 	watch(formItem, (newVal) => {
@@ -145,12 +182,26 @@
 		text,
 		sendCode
 	} = useSendCode();
-	
+
 
 	function openPrivacy() {
-		void plus.runtime.openWeb("https://www.shuibeibyg.com/shenhe.html");
+		// void plus.runtime.openWeb("https://www.shuibeibyg.com/shenhe.html");
+		goDetail("https://www.shuibeibyg.com/shenhe.html")
 	}
-
+	const goDetail = (url) => {
+		const webviewPageUrl = `/pages/webview/privacy?path=${url}`;
+		uni.navigateTo({
+			url: webviewPageUrl,
+			fail: (err) => {
+				console.error("跳转到webview页面失败:", err);
+				uni.showToast({
+					title: "跳转失败,请重试",
+					icon: "none",
+					duration: 1500,
+				});
+			},
+		});
+	};
 
 	// Get logo image
 	const getLogoImage = async () => {
@@ -313,6 +364,8 @@
 
 	// 账号密码登录
 	const submit = async () => {
+		
+		appStore.setIndexRefersh(true)
 		if (!account.value) return Toast({
 			title: "请填写账号",
 			icon: "none"
@@ -389,7 +442,7 @@
 			appStore.SETUID(data.uid);
 			const res = await getUserInfo();
 			appStore.UPDATE_USERINFO(res.data);
-      userInfo.value = res.data;
+			userInfo.value = res.data;
 
 			// connect({
 			// 	id: appStore.uid?.toString(),
@@ -403,18 +456,21 @@
 			// 订阅已加入的群组
 			// await getGroupchatListFn(data.uid);
 
-      if(merchantId.value != ''){
-        let obj ={
-          merchantId:merchantId.value,
-          userId:res.data.userId
-        }
-        await footprintScanFn(obj)
-      }else{
-        console.log('============')
-        appStore.UPDATE_MERCHANT_ID('')
-        Toast({ title: "登录成功" });
-        backHome();
-      }
+			if (merchantId.value != '') {
+				let obj = {
+					merchantId: merchantId.value,
+					userId: res.data.userId
+				}
+				
+				await footprintScanFn(obj)
+			} else {
+				console.log('============')
+				appStore.UPDATE_MERCHANT_ID('')
+				Toast({
+					title: "登录成功"
+				});
+				backHome();
+			}
 		} catch (err) {
 			console.error(err);
 			uni.showToast({
@@ -423,24 +479,49 @@
 			});
 		}
 	};
-  const backHome = () => {
-    if(userInfo.value.merchant && userInfo.value.merchant.id){
-      uni.navigateTo({
-        url:"/pages/merchantCenter/index"
-      })
-    }else{
-      uni.switchTab({
-        url: "/pages/index/index",
-      });
-    }
-  };
-  const footprintScanFn =async (data) => {
-    const res = await footprintScan(data);
-    Toast({ title: "登录成功" });
-    backHome();
-  }
+	const backHome = () => {
+		if (userInfo.value.merchant && userInfo.value.merchant.id) {
+			uni.navigateTo({
+				url: "/pages/merchantCenter/index"
+			})
+		} else {
+			uni.switchTab({
+				url: "/pages/index/index",
+			});
+		}
+	};
+	const footprintScanFn = async (data) => {
+		const res = await footprintScan(data);
+		appStore.USERINFO();
+		Toast({
+			title: "登录成功"
+		});
+		backHome();
+	}
+	const getPhoneNumberFn = async (e) => {
+		// Toast({ title: "登录中..." });
+		appStore.setIndexRefersh(true)
+		if (!aloneChecked.value) {
+			return Toast({
+				title: "请阅读并同意用户协议和隐私政策",
+				icon: "none"
+			});
+		}
+		const res = await getPhoneNumber(e);
+		console.log('res', res);
+		if (res) {
+			appStore.LOGIN({
+				token: res.data.token
+			});
+			// 保存过期时间(999天后过期)
+			const expiresTime = Math.round(new Date() / 1000) + 999 * 24 * 60 * 60;
+			Cache.set(EXPIRES_TIME, expiresTime, 0);
+			await getUserInfoFn(res.data);
+		}
+	}
 	onLoad(() => {
-    merchantId.value = appStore.merchantId || '';
+		console.log(appStore.$wxConfig)
+		merchantId.value = appStore.merchantId || '';
 		getLogoImage();
 	});
 
@@ -461,19 +542,21 @@
 		background: transparent;
 		background-color: transparent !important;
 	}
-	
+
 	::v-deep .u-navbar__content {
 		background: transparent;
 		background-color: transparent !important;
 	}
+
 	.login-wrapper {
-		background: url('https://sb-admin.oss-cn-shenzhen.aliyuncs.com/shuibei-mini/new-mini/login@2x.png');
+		//background: url('https://sb-admin.oss-cn-shenzhen.aliyuncs.com/shuibei-mini/new-mini/login@2x.png');
 		background-repeat: no-repeat;
 		background-size: 100% 624rpx;
 		background-color: #FFFFFF;
 	}
+
 	.appLogin {
-		
+
 
 		.hds {
 			display: flex;
@@ -557,43 +640,61 @@
 
 	.login-wrapper {
 
+		height: 100vh;
 
 		.shading {
 			padding: 72rpx 78rpx;
 			display: flex;
 			justify-content: center;
 			flex-direction: column;
+			position: relative;
+			z-index: 1;
+
 			view {
 				color: #333333;
 				font-size: 36rpx;
 				font-weight: bold;
+
 				&:first-child {
 					font-size: 48rpx;
 					margin-bottom: 16rpx;
 				}
 			}
+
+			.ip-pic {
+				width: 261rpx;
+				height: 480rpx;
+				position: absolute;
+				right: 14rpx;
+				bottom: calc(-76rpx - 88rpx);
+			}
 		}
 
 		.whiteBg {
-			margin-top: 100rpx;
+			// margin-top: 100rpx;
 			background: #FFFFFF;
 			border-radius: 48rpx 48rpx 0rpx 0rpx;
+			position: relative;
+			z-index: 5;
+
 			.whiteBg-tab {
 				color: #666666;
 				display: flex;
 				align-items: center;
 				height: 88rpx;
 				text-align: center;
-				background: url('https://sb-admin.oss-cn-shenzhen.aliyuncs.com/shuibei-mini/new-mini/logintab1.png');
+				//background: url('https://sb-admin.oss-cn-shenzhen.aliyuncs.com/shuibei-mini/new-mini/logintab1.png');
 				background-repeat: no-repeat;
 				background-size: cover;
+
 				.active {
 					width: 407rpx;
-					
+
 					view {
 						color: #F8C008;
 						font-weight: bold;
 						position: relative;
+
 						&::after {
 							left: 50%;
 							bottom: -12rpx;
@@ -607,15 +708,18 @@
 						}
 					}
 				}
+
 				.noActive {
 					flex: 1;
 				}
 			}
+
 			.whiteBg-tabs {
-				background: url('https://sb-admin.oss-cn-shenzhen.aliyuncs.com/shuibei-mini/new-mini/logintab.png');
+				//background: url('https://sb-admin.oss-cn-shenzhen.aliyuncs.com/shuibei-mini/new-mini/logintab.png');
 				background-repeat: no-repeat;
 				background-size: cover;
 			}
+
 			.list {
 				padding: 0 80rpx;
 				margin-top: 120rpx;
@@ -629,11 +733,12 @@
 					background: #F9F7F0;
 					border-radius: 16rpx;
 					margin-bottom: 32rpx;
+
 					.texts {
 						flex: 1;
 						font-size: 28rpx;
 					}
-					
+
 					.code {
 						padding: 0;
 						margin: 0;
@@ -648,6 +753,7 @@
 						font-size: 28rpx;
 						font-weight: bold;
 						border: none;
+
 						&::after {
 							width: 0;
 							border: none;
@@ -668,7 +774,21 @@
 				font-weight: bold;
 			}
 
-			
+			.logonWX {
+				display: flex;
+				align-items: center;
+				justify-content: center;
+				// height: 88rpx;
+				background-color: #fff;
+				border: none !important;
+				border-radius: 16rpx;
+				color: #ffffff;
+				font-size: 32rpx;
+			}
+
+			.logonWX[disabled] {
+				background-color: #BEEDC7;
+			}
 		}
 
 		.privacy-box {
@@ -676,7 +796,7 @@
 			padding: 0 80rpx;
 			display: flex;
 			align-items: center;
-			
+
 			image {
 				width: 28rpx;
 				height: 28rpx;
@@ -685,12 +805,60 @@
 
 			.privacy-text {
 				color: #F8C008;
-				
+
 				vertical-align: top;
 			}
 		}
 	}
+
 	.footer {
-		padding: 48rpx 80rpx;
+		padding: 48rpx 80rpx 72rpx;
+	}
+
+	.back_extend {
+		//position: fixed;
+		//top: 50px;
+		//left: 10px;
+		//font-size: 26rpx;
+		//color: #999;
+	}
+
+	.wx-login-tip {
+		display: flex;
+		align-items: center;
+		width: 590rpx;
+		margin: 0 auto;
+		justify-content: space-between;
+
+		.login-line {
+			width: 193rpx;
+			height: 1rpx;
+			background-color: #F1F3F8;
+		}
+
+		.wx-tip {
+			font-size: 28rpx;
+			line-height: 44rpx;
+			color: #999;
+			flex: 1;
+			width: 100rpx;
+			text-align: center;
+			display: block;
+		}
+	}
+
+	.wx-login-btn {
+		width: 590rpx;
+		margin: 0 auto;
+		display: flex;
+		align-items: center;
+		justify-content: center;
+		margin-top: 32rpx;
+		padding-bottom: 30rpx;
+
+		.wx-icon {
+			width: 92rpx;
+			height: 92rpx;
+		}
 	}
-</style>
+</style>

+ 4 - 4
pages/users/my_merchant/index.vue

@@ -4,7 +4,7 @@
     <view class="store-card">
       <view class="info-top">
         <view class="left">
-          <image class="storeImg" :src="merchantInfo.merchantLogo" mode="aspectFit"></image>
+          <image class="storeImg" :src="merchantInfo.merchantLogo"></image>
         </view>
         <view class="center">
           <view class="name">{{merchantInfo.merchantName}}</view>
@@ -29,7 +29,7 @@
       <!-- 二维码区域 -->
       <view class="qrcode-container">
         <image class="qrcode-img" :src="merchantInfo.merchantCodeUrl" mode="aspectFit"></image>
-        <view class="qrcode-tip">扫码添加微信好友</view>
+        <view class="qrcode-tip">扫码进入商家店铺</view>
       </view>
 
       <!-- 客服按钮 -->
@@ -136,7 +136,7 @@ const makePhoneCall = () => {
 
 <style scoped lang="scss">
 .container {
-  padding: 30rpx;
+  padding: 20rpx;
   background-color: #f5f5f5;
   min-height: 100vh;
   box-sizing: border-box;
@@ -234,7 +234,7 @@ const makePhoneCall = () => {
 }
 /* 联系商家部分 */
 .contact-section {
-  margin-top: 30rpx;
+  margin-top: 20rpx;
   padding: 40rpx;
   background-color: #fff;
   border-radius: 24rpx;

+ 1 - 0
pages/users/order_confirm/index.vue

@@ -1422,6 +1422,7 @@ const SubOrder = async (e) => {
     left: 0;
 
     .settlement {
+		font-weight: bold;
       font-size: 30rpx;
       color: #fff;
       width: 240rpx;

+ 372 - 351
pages/users/personal_info/personal_info.vue

@@ -1,371 +1,392 @@
 <template>
-  <view class="personal-info">
-    <!-- 上传 -->
-    <view class="upload-box">
-      <up-upload
-        @afterRead="
-          async (e) => {
-            await afterRead(e);
-            getImage();
-          }
-        "
-        name="1"
-        :maxCount="1"
-        :previewImage="false"
-        :deletable="false"
-        :multiple="false"
-      >
-        <!-- <template #default> -->
-        <view class="upload-block">
-          <up-avatar
-            size="160rpx"
-            shape="circle"
-            :src="userInfo.avatar"
-            mode="aspectFill"
-          ></up-avatar>
-        </view>
-        <!-- </template> -->
-      </up-upload>
-    </view>
-		<view class="flex-center-between personal-info-item">
-			<text class="label_width">昵称</text>
-			<up-input
-          class="title-input"
-          placeholder="请输入"
-          type="text"
-          confirmType="完成"
-          maxlength="50"
-          :adjustPosition="false"
-          border="none"
-          :showWordLimit="true"
-          v-model="userInfo.nickname"
-					inputAlign="right"
-          @blur="changeName"
-        ></up-input>
-		</view>
-		<view class="flex-center-between personal-info-item">
-			<text class="label_width">手机号</text>
-			<text class="gray">{{telEncrypt(userInfo.phone)}}</text>
-		</view>
-		<view class="flex-center-between personal-info-item" @click="pickerSexShow = true">
-			<text class="label_width">性别</text>
-			<view class="flex-center-between">
-				<text>{{sexText}}</text>
-				<uni-icons type="right" size="21"  color="#888"></uni-icons>
+	<view class="personal-info">
+		<view class="personal-info-box">
+			<!-- 上传 -->
+			<view class="upload">
+				<view class="upload-box">
+					<up-upload @afterRead="
+				      async (e) => {
+				        await afterRead(e);
+				        getImage();
+				      }
+				    " name="1" :maxCount="1" :previewImage="false" :deletable="false" :multiple="false">
+						<view class="upload-block">
+							<up-avatar size="144rpx" shape="circle" :src="userInfo.avatar" mode="aspectFill"></up-avatar>
+							<view class="upload-block-edit flex-center">
+								<image src="@/static/images/edit@2x.png" mode=""></image>
+							</view>
+						</view>
+					</up-upload>
+				</view>
+			</view>
+			<view class="personal-list">
+				<view class="flex-center-between border-bottom personal-info-item">
+					<text class="label_width">昵称</text>
+					<up-input class="title-input" placeholder="请输入" type="text" confirmType="完成" maxlength="10"
+						:adjustPosition="false" border="none" :showWordLimit="true" v-model="userInfo.nickname" inputAlign="right"></up-input>
+				</view>
+				<view class="flex-center-between border-bottom personal-info-item">
+					<text class="label_width">手机号</text>
+					<text class="gray">{{telEncrypt(userInfo.phone)}}</text>
+				</view>
+			</view>
+			<view class="personal-list">
+				<view class="flex-center-between border-bottom personal-info-item" @click="pickerSexShow = true">
+					<text class="label_width">性别</text>
+					<view class="flex-center-between">
+						<text>{{sexText}}</text>
+						<image style="width: 32rpx;height: 32rpx;" src="/static/images/shop/go@2x.png" mode=""></image>
+					</view>
+				</view>
+				<view class="flex-center-between border-bottom personal-info-item">
+					<text class="label_width">地址</text>
+					<picker mode="multiSelector" @change="bindRegionChange" @columnchange="bindMultiPickerColumnChange"
+						:value="valueRegion" :range="multiArray">
+						<view class='flex-center-between'>
+							<view class="picker line1">{{ region[0] }},{{ region[1] }},{{ region[2] }}</view>
+							<image style="width: 32rpx;height: 32rpx;" src="/static/images/shop/go@2x.png" mode=""></image>
+						</view>
+					</picker>
+					
+				</view>
+				<view class="flex-center-between border-bottom personal-info-item">
+					<text class="label_width">年龄</text>
+					<up-input class="title-input" placeholder="请输入年龄" fontSize="28rpx" type="text" confirmType="完成" maxlength="3"
+						:adjustPosition="false" border="none" :showWordLimit="true" v-model="userInfo.age" inputAlign="right"></up-input>
+				</view>
+			</view>
+			<view class="personal-list">
+				<view class="flex-center-between border-bottom personal-info-item">
+					<text class="label_width">个人简介</text>
+					<up-input class="title-input" placeholder="请输入个人简介" fontSize="28rpx" type="text" confirmType="完成" maxlength="50"
+						:adjustPosition="false" border="none" :showWordLimit="true" v-model="userInfo.mark" inputAlign="right"></up-input>
+				</view>
+				<!-- <view class="flex-center-between border-bottom personal-info-item" @tap.stop="setPayword">
+					<text class="label_width">支付密码</text>
+					<text>* * * * * *</text>
+				</view> -->
 			</view>
+			
+			
 		</view>
-		<view class="flex-center-between personal-info-item">
-			<text class="label_width">地址</text>
-      <picker mode="multiSelector" @change="bindRegionChange" @columnchange="bindMultiPickerColumnChange"
-        :value="valueRegion" :range="multiArray">
-        <view class='flex-center-between'>
-          <view class="picker line1">{{ region[0] }},{{ region[1] }},{{ region[2] }}</view>
-					<uni-icons type="right" size="21"  color="#888"></uni-icons>
-        </view>
-      </picker>
-      <!-- <up-input
-          class="title-input"
-          placeholder="请输入"
-          type="text"
-          confirmType="完成"
-          maxlength="50"
-          :adjustPosition="false"
-          border="none"
-          :showWordLimit="true"
-          v-model="userInfo.addres"
-					inputAlign="right"
-          @blur="change"
-        ></up-input> -->
-    </view>
-    <view class="flex-center-between personal-info-item">
-      <text class="label_width">年龄</text>
-      <up-input
-        class="title-input"
-        placeholder="请输入"
-        type="text"
-        confirmType="完成"
-        maxlength="50"
-        :adjustPosition="false"
-        border="none"
-        :showWordLimit="true"
-        v-model="userInfo.age"
-        inputAlign="right"
-      ></up-input>
-    </view>
-    <view class="flex-center-between personal-info-item">
-      <text class="label_width">个人简介</text>
-      <up-input
-        class="title-input"
-        placeholder="请输入"
-        type="text"
-        confirmType="完成"
-        maxlength="50"
-        :adjustPosition="false"
-        border="none"
-        :showWordLimit="true"
-        v-model="userInfo.mark"
-        inputAlign="right"
-      ></up-input>
-    </view>
-<!--    <view-->
-<!--      class="flex-center-between border-bottom personal-info-item"-->
-<!--      @tap.stop="setPayword"-->
-<!--    >-->
-<!--      <text class="label_width">支付密码</text>-->
-<!--      &lt;!&ndash; <up-input-->
-<!--        class="title-input"-->
-<!--        placeholder="请输入"-->
-<!--        type="text"-->
-<!--        confirmType="完成"-->
-<!--        maxlength="6"-->
-<!--        :adjustPosition="false"-->
-<!--        border="none"-->
-<!--        :showWordLimit="true"-->
-<!--        v-model="userInfo.payPassword"-->
-<!--        inputAlign="right"-->
-<!--        :password="true"-->
-<!--        :disabled="true"-->
-<!--        :passwordVisibilityToggle="false"-->
-<!--        disabledColor=""-->
-<!--      ></up-input> &ndash;&gt;-->
-<!--      <text>* * * * * *</text>-->
-<!--    </view>-->
-    <up-picker
-      @confirm="changeSex"
-      @cancel="pickerSexShow = false"
-      :show="pickerSexShow"
-      :columns="[
+		<view class="footer">
+			<view @click="submitFn" class="submit-btn">提交</view>
+		</view>
+
+		<up-picker @confirm="changeSex" @cancel="pickerSexShow = false" :show="pickerSexShow" :columns="[
         [
           { label: '男', id: 1 },
           { label: '女', id: 2 },
           { label: '保密', id: 3 },
         ],
-      ]"
-      keyName="label"
-      valueName="id"
-    ></up-picker>
-    <button
-      @click="submitFn"
-      class="submit-btn"
-    >提交</button>
-    <!-- 页面内 容结束 -->
-    <PayPop ref="paypopRef" :pwdlength="6" @pwd_e="handlerPwd"></PayPop>
-  </view>
+      ]" keyName="label" valueName="id"></up-picker>
+		
+		<!-- 页面内 容结束 -->
+	</view>
 </template>
 
 <script setup>
-import { ref, computed, nextTick } from "vue";
-import PayPop from "../../../components/pay-pop/pay-pop.vue";
-import { useImageUpload } from "@/hooks/useImageUpload";
-import { useAppStore } from "@/stores/app";
-import { onLoad } from "@dcloudio/uni-app";
-import { useToast } from "@/hooks/useToast";
-import { getUserInfo, userEdit, registerpayPasswordAPI } from "@/api/user";
-import { getCity } from "@/api/api.js";
-import Cache from "@/utils/cache";
-import { telEncrypt } from "@/utils/util.js";
-const paypopRef = ref(null);
-const { Toast } = useToast();
-const { imageList, afterRead, deletePic, uploadLoading } = useImageUpload({
-  pid: 5,
-  model: "book",
-});
-const appStore = useAppStore();
-const userInfo = ref({
-  avatar: "",
-  nickname: "",
-  addres: "",
-  mark: "",
-  sex: "",
-  age: "",
-});
-const pickerSexShow = ref(false);
-const sexText = computed(() => {
-  return userInfo.value.sex == 1
-    ? "男"
-    : userInfo.value.sex == 2
-    ? "女"
-    : userInfo.value.sex == 3
-    ? "保密"
-    : "未知";
-});
+	import {
+		ref,
+		computed,
+		nextTick
+	} from "vue";
+	import {
+		useImageUpload
+	} from "@/hooks/useImageUpload";
+	import {
+		useAppStore
+	} from "@/stores/app";
+	import {
+		onLoad
+	} from "@dcloudio/uni-app";
+	import {
+		useToast
+	} from "@/hooks/useToast";
+	import {
+		getUserInfo,
+		userEdit,
+		registerpayPasswordAPI
+	} from "@/api/user";
+	import {
+		getCity
+	} from "@/api/api.js";
+	import Cache from "@/utils/cache";
+	import {
+		telEncrypt
+	} from "@/utils/util.js";
+	const paypopRef = ref(null);
+	const {
+		Toast
+	} = useToast();
+	const {
+		imageList,
+		afterRead,
+		deletePic,
+		uploadLoading
+	} = useImageUpload({
+		pid: 5,
+		model: "book",
+	});
+	const appStore = useAppStore();
+	const userInfo = ref({
+		avatar: "",
+		nickname: "",
+		addres: "",
+		mark: "",
+		sex: "",
+		age: "",
+	});
+	const pickerSexShow = ref(false);
+	const sexText = computed(() => {
+		return userInfo.value.sex == 1 ?
+			"男" :
+			userInfo.value.sex == 2 ?
+			"女" :
+			userInfo.value.sex == 3 ?
+			"保密" :
+			"未知";
+	});
 
-//省市区选择
-const district = ref([]);
-const multiArray = ref([[], [], []]);
-const multiIndex = ref([0, 0, 0]);
-const region = ref(["省", "市", "区"]);
-const valueRegion = ref([0, 0, 0]);
+	//省市区选择
+	const district = ref([]);
+	const multiArray = ref([
+		[],
+		[],
+		[]
+	]);
+	const multiIndex = ref([0, 0, 0]);
+	const region = ref(["省", "市", "区"]);
+	const valueRegion = ref([0, 0, 0]);
 
-onLoad(() => {
-  console.log("personal_info 页面 onLoad");
-  fetchUserInfo();
-  getCityList();
-});
+	onLoad(() => {
+		fetchUserInfo();
+		getCityList();
+	});
 
-const changeSex = (e) => {
-  console.log("changeSex", e.value[0]);
-  userInfo.value.sex = e.value[0].id;
-  pickerSexShow.value = false;
-  // change();
-};
-// 设置支付密码
-const setPayword = () => {
-  console.log(111111);
+	const changeSex = (e) => {
+		userInfo.value.sex = e.value[0].id;
+		pickerSexShow.value = false;
+	};
+	// 设置支付密码
+	const setPayword = () => {
+		nextTick(() => {
+			paypopRef.value.Open();
+		});
+	};
+	const handlerPwd = async (e) => {
+		const res = await registerpayPasswordAPI({
+			account: appStore.userInfo.phone,
+			payPassword: e,
+		});
+		uni.showToast({
+			title: "修改成功",
+			duration: 2000,
+		});
+	};
+	// 获取用户头像
+	async function getImage() {
+		if (imageList.value.length > 0) {
+			if (imageList.value[0].status == "success") {
+				userInfo.value.avatar = imageList.value[0].info.url;
+			} else {
+				Toast({
+					title: "上传失败"
+				});
+			}
+		}
+		imageList.value = [];
+	}
 
-  console.log(paypopRef.value);
-  nextTick(() => {
-    paypopRef.value.Open();
-  });
-};
-const handlerPwd = async (e) => {
-  const res = await registerpayPasswordAPI({
-    account: appStore.userInfo.phone,
-    payPassword: e,
-  });
-  uni.showToast({
-    title: "修改成功",
-    duration: 2000,
-  });
-  change();
-};
-// 获取用户头像
-async function getImage() {
-  console.log("getImage", imageList.value[0]);
-  if (imageList.value.length > 0) {
-    if (imageList.value[0].status == "success") {
-      userInfo.value.avatar = imageList.value[0].info.url;
-      // change();
-    } else {
-      Toast({ title: "上传失败" });
-    }
-  }
-  imageList.value = [];
-}
-function submitFn() {
-  change();
-}
-function changeName(e) {
-  // console.log(e)
-  // console.log(userInfo.value)
-}
-const change = async () => {
-  await userEdit(userInfo.value);
-  Toast({ title: "修改成功", endtime: 1500 });
-  appStore.USERINFO();
-  setTimeout(() => {
-    uni.navigateBack();
-  }, 1600);
-  // const { data } = await getUserInfo(appStore.uid);
-  // appStore.UPDATE_userPanelInfo(data);
-};
-// 获取用户信息
-async function fetchUserInfo() {
-  try {
-    const { data } = await getUserInfo(appStore.uid);
-    userInfo.value = data;
-    userInfo.value.addres = userInfo.value.addres || "";
-    const list = userInfo.value.addres.split("-");
-    if (list.length > 0) {
-      region.value = [list[0], list[1], list[2]];
-    }
-  } catch (error) {
-    console.error("otherUserinfo", error);
-    Toast({ title: "获取用户信息失败" });
-  }
-}
+	function submitFn() {
+		change();
+	}
 
-function bindRegionChange(e) {
-  const mi = multiIndex.value;
-  const province = district.value[mi[0]] || { child: [] };
-  const ma = multiArray.value;
-  const value = e.detail.value;
-  region.value = [ma[0][value[0]], ma[1][value[1]], ma[2][value[2]]];
-  userInfo.value.addres = region.value.join("-");
-  valueRegion.value = [0, 0, 0];
-  //   change();
-  initialize();
-}
+	const change = async () => {
+		await userEdit(userInfo.value);
+		Toast({
+			title: "修改成功",
+			endtime: 1500
+		});
+		appStore.USERINFO();
+		setTimeout(() => {
+			uni.navigateBack();
+		}, 1600);
+	};
+	// 获取用户信息
+	async function fetchUserInfo() {
+		try {
+			const {
+				data
+			} = await getUserInfo(appStore.uid);
+			userInfo.value = data;
+			userInfo.value.addres = userInfo.value.addres || "";
+			const list = userInfo.value.addres.split("-");
+			if (list.length > 0) {
+				region.value = [list[0], list[1], list[2]];
+			}
+		} catch (error) {
+			console.error("otherUserinfo", error);
+			Toast({
+				title: "获取用户信息失败"
+			});
+		}
+	}
 
-function getCityList() {
-  getCity().then((res) => {
-    district.value = res.data;
-    let oneDay = 24 * 3600 * 1000;
-    Cache.setItem({ name: "cityList", value: res.data, expires: oneDay * 7 }); //设置七天过期时间
-    initialize();
-  });
-}
-function initialize() {
-  if (district.value.length) {
-    let province = [],
-      city = [],
-      area = [];
-    let cityChildren = district.value[0].child || [];
-    let areaChildren = cityChildren.length ? cityChildren[0].child || [] : [];
-    district.value.forEach((item) => province.push(item.name));
-    cityChildren.forEach((item) => city.push(item.name));
-    areaChildren.forEach((item) => area.push(item.name));
-    multiArray.value = [province, city, area];
-  }
-}
-function bindMultiPickerColumnChange(e) {
-  const column = e.detail.column;
-  const value = e.detail.value;
-  const ma = multiArray.value;
-  const mi = multiIndex.value;
-  mi[column] = value;
-  switch (column) {
-    case 0:
-      const currentCity = district.value[value] || { child: [] };
-      const areaList = currentCity.child[0] || { child: [] };
-      ma[1] = currentCity.child.map((item) => item.name);
-      ma[2] = areaList.child.map((item) => item.name);
-      break;
-    case 1:
-      const cityList = district.value[mi[0]].child[mi[1]].child || [];
-      ma[2] = cityList.map((item) => item.name);
-      break;
-    case 2:
-      break;
-  }
-  multiArray.value = [...ma];
-  multiIndex.value = [...mi];
-}
-</script>
+	function bindRegionChange(e) {
+		const mi = multiIndex.value;
+		const province = district.value[mi[0]] || {
+			child: []
+		};
+		const ma = multiArray.value;
+		const value = e.detail.value;
+		region.value = [ma[0][value[0]], ma[1][value[1]], ma[2][value[2]]];
+		userInfo.value.addres = region.value.join("-");
+		valueRegion.value = [0, 0, 0];
+		//   change();
+		initialize();
+	}
+
+	function getCityList() {
+		getCity().then((res) => {
+			district.value = res.data;
+			let oneDay = 24 * 3600 * 1000;
+			Cache.setItem({
+				name: "cityList",
+				value: res.data,
+				expires: oneDay * 7
+			}); //设置七天过期时间
+			initialize();
+		});
+	}
 
-<style lang="scss">
-.personal-info {
-  padding: 0 30rpx;
+	function initialize() {
+		if (district.value.length) {
+			let province = [],
+				city = [],
+				area = [];
+			let cityChildren = district.value[0].child || [];
+			let areaChildren = cityChildren.length ? cityChildren[0].child || [] : [];
+			district.value.forEach((item) => province.push(item.name));
+			cityChildren.forEach((item) => city.push(item.name));
+			areaChildren.forEach((item) => area.push(item.name));
+			multiArray.value = [province, city, area];
+		}
+	}
 
-  .upload-block {
-    display: flex;
-    justify-content: center;
-    width: 90vw;
-    box-sizing: border-box;
-    padding: 80rpx 0;
-  }
-  .personal-info-item {
-    height: 100rpx;
-    line-height: 100rpx;
-    padding: 0 30rpx;
-    box-sizing: border-box;
-    border-radius: 16rpx;
-    background-color: #FFF;
-    margin-bottom: 30rpx;
-    .label_width {
-      width: 200rpx;
-      display: inline-block;
-    }
-  }
-  .submit-btn {
-    font-size: 32rpx;
-    color: #333;
-    height: 88rpx;
-    line-height: 88rpx;
-    border-radius: 16rpx;
-    background-color: #F8C008;
-    border: none;
-    margin-top: 20px;
-  }
-}
+	function bindMultiPickerColumnChange(e) {
+		const column = e.detail.column;
+		const value = e.detail.value;
+		const ma = multiArray.value;
+		const mi = multiIndex.value;
+		mi[column] = value;
+		switch (column) {
+			case 0:
+				const currentCity = district.value[value] || {
+					child: []
+				};
+				const areaList = currentCity.child[0] || {
+					child: []
+				};
+				ma[1] = currentCity.child.map((item) => item.name);
+				ma[2] = areaList.child.map((item) => item.name);
+				break;
+			case 1:
+				const cityList = district.value[mi[0]].child[mi[1]].child || [];
+				ma[2] = cityList.map((item) => item.name);
+				break;
+			case 2:
+				break;
+		}
+		multiArray.value = [...ma];
+		multiIndex.value = [...mi];
+	}
+</script>
+<style>
+	page {
+		background: #F9F7F0;
+	}
 </style>
+<style lang="scss" scoped>
+	page{
+		height: 100%;
+	}
+
+	.personal-info {
+		.personal-info-box {
+			padding: 0 16rpx;
+
+			.upload {
+				padding: 16rpx 0;
+				display: flex;
+				align-items: center;
+				justify-content: center;
+			}
+
+			.upload-box {
+				width: 145rpx;
+				height: 145rpx;
+				border-radius: 50%;
+				border: 1rpx solid #CCCCCC;
+			}
+		}
+
+		.upload-block {
+			display: flex;
+			align-items: center;
+			justify-content: center;
+			position: relative;
+
+			.upload-block-edit {
+				bottom: 0;
+				right: 12rpx;
+				position: absolute;
+				width: 40rpx;
+				height: 40rpx;
+				background: #F8C008;
+				border-radius: 20rpx;
+				image {
+					width: 24rpx;
+					height: 24rpx;
+				}
+			}
+		}
+		.personal-list {
+			margin-bottom: 16rpx;
+			padding: 0 16rpx;
+			background: #FFFFFF;
+			border-radius: 16rpx;
+			&:last-child {
+				margin-bottom: 0;
+			}
+		}
+
+		.personal-info-item {
+			min-height: 100rpx;
+			border-bottom: 1rpx solid #F1F3F8; 
+			&:last-child {
+				border-bottom: none;
+			}
+
+			.label_width {
+				width: 200rpx;
+				display: inline-block;
+			}
+		}
+	}
+	.footer {
+		width: 100%;
+		bottom: 0;
+		position: fixed;
+		padding: 22rpx 32rpx 56rpx;
+		background: #FFFFFF;
+		.submit-btn {
+			font-weight: bold;
+			font-size: 32rpx;
+			text-align: center;
+			line-height: 88rpx;
+			background: #F8C008;
+			border-radius: 16rpx;
+		}
+	}
+</style>

+ 0 - 0
pages/users/personal_info/personal_info_bf.vue


+ 0 - 2
pages/users/share/index.vue

@@ -289,8 +289,6 @@ const saveToAlbum = async () => {
 onLoad((options) => {
   if (options.merchantInfo) {
     merchantInfo.value = JSON.parse(decodeURIComponent(options.merchantInfo))
-    merchantInfo.value.merchantName="一号商家一号商家一号商家一号商家一号商家一号商家一号商家一号商家一号商家一号商家一号商家一号商家"
-    merchantInfo.value.merchantDescribe="一号商家一号商家一号商家一号商家一号商家一号商家一号商家一号商家一号商家一号商家一号商家一号商家"
     // 修正语法错误
     merchantInfo.value.merchantNameNew = truncateText(merchantInfo.value.merchantName, 10) || ''
     merchantInfo.value.merchantDescribeNew = truncateText(merchantInfo.value.merchantDescribe, 10) || ''

+ 2 - 0
pages/users/user_address/index.vue

@@ -473,6 +473,7 @@ function ChangeIsDefault() {
 
 .addAddress .keepBnt {
   width: 690rpx;
+  font-weight: bold;
   height: 86rpx;
   border-radius: 50rpx;
   text-align: center;
@@ -484,6 +485,7 @@ function ChangeIsDefault() {
 
 .addAddress .wechatAddress {
   width: 690rpx;
+  font-weight: bold;
   height: 86rpx;
   border-radius: 50rpx;
   text-align: center;

+ 1 - 0
pages/users/user_address_list/index.vue

@@ -514,6 +514,7 @@ onReachBottom(() => {
 
 .footer .addressBnt {
   width: 330rpx;
+  font-weight: bold;
   height: 76rpx;
   border-radius: 50rpx;
   text-align: center;

Fichier diff supprimé car celui-ci est trop grand
+ 547 - 488
pages/users/user_goods_collection/index.vue


+ 1 - 1
pages/webview/index.vue

@@ -66,7 +66,7 @@ onLoad((query) => {
     };
 
     const queryString = buildQueryString(params);
-
+    console.log(H5_BASE_URL)
     h5Url.value = `${H5_BASE_URL}/#${normalizedPath}${
       queryString ? `?${queryString}` : ""
     }`;

+ 122 - 0
pages/webview/privacy.vue

@@ -0,0 +1,122 @@
+<template>
+  <view class="webview-wrapper">
+    <!-- 加载状态提示 -->
+    <view class="loading-mask" v-if="isLoading">
+      <uni-loading-icon type="circle" size="24" color="#333"></uni-loading-icon>
+      <text class="loading-txt">加载中...</text>
+    </view>
+
+    <web-view
+      :src="h5Url"
+      id="any-id"
+      @load="onWebViewLoad"
+      @error="onWebViewError"
+      @message="onWebViewMessage"
+    ></web-view>
+  </view>
+</template>
+
+<script setup>
+import { ref, onUnmounted } from "vue";
+import { onLoad } from "@dcloudio/uni-app";
+import { H5_BASE_URL, TOKENNAME, WHITELIST } from "@/config/app";
+import { useAppStore } from "@/stores/app";
+import { toLogin, checkLogin } from "@/libs/login";
+
+const h5Url = ref("");
+const appStore = useAppStore();
+const isLoading = ref(true);
+const errorMsg = ref("");
+
+onUnmounted(() => {
+  isLoading.value = false;
+});
+
+onLoad((query) => {
+  console.log('query',query)
+  try {
+    h5Url.value = query.path;
+  } catch (err) {
+    console.error("WebView 初始化失败:", err);
+    uni.showToast({ title: "页面加载异常", icon: "none", duration: 1500 });
+    setTimeout(() => uni.navigateBack(), 1500);
+  }
+});
+
+// 标准化H5路径
+
+
+/**
+ * web-view 加载成功
+ */
+const onWebViewLoad = () => {
+  isLoading.value = false; // 隐藏加载中
+};
+
+/**
+ * web-view 加载失败
+ * @param {object} err - 错误信息
+ */
+const onWebViewError = (err) => {
+  isLoading.value = false;
+  errorMsg.value = `页面加载失败:${err.detail.errMsg}`;
+  uni.showToast({ title: errorMsg.value, icon: "none", duration: 2000 });
+  console.error("WebView 加载错误:", err);
+  setTimeout(() => uni.navigateBack(), 1500);
+};
+
+/**
+ * 接收 H5 发送的消息
+ * @param {object} e - 消息事件
+ */
+const onWebViewMessage = (e) => {
+  const h5Msg = e.detail.data[0]; // H5 发送的消息格式为 { data: [消息体] }
+  console.log("接收 H5 消息:", h5Msg);
+
+  // 示例:H5 触发「返回小程序」
+  if (h5Msg.type === "navigateBack") {
+    uni.navigateBack({ delta: h5Msg.delta || 1 });
+  }
+
+  if (h5Msg.type === "refreshToken") {
+    appStore.refreshToken().then((newToken) => {
+      const webview = uni.createSelectorQuery().select("#any-id");
+      webview
+        .context((res) => {
+          res.context.postMessage({
+            data: { type: "newToken", token: newToken },
+          });
+        })
+        .exec();
+    });
+  }
+};
+</script>
+
+<style scoped>
+.webview-wrapper {
+  width: 100vw;
+  height: 100vh;
+  position: relative;
+}
+
+.loading-mask {
+  position: absolute;
+  top: 0;
+  left: 0;
+  width: 100%;
+  height: 100%;
+  background: rgba(255, 255, 255, 0.8);
+  display: flex;
+  flex-direction: column;
+  justify-content: center;
+  align-items: center;
+  z-index: 999;
+}
+
+.loading-txt {
+  margin-top: 16rpx;
+  font-size: 28rpx;
+  color: #666;
+}
+</style>

+ 22 - 0
static/css/base.css

@@ -470,4 +470,26 @@ checkbox .uni-checkbox-input.uni-checkbox-input-checked::before {
 }
 .font333{
 	color:#333 !important;
+}
+.jianbianBG{
+	background-image: url("https://sb-admin.oss-cn-shenzhen.aliyuncs.com/shuibei-mini/new-mini/jianbianBG.png");
+}
+.bglogin{
+	/* background: url('https://sb-admin.oss-cn-shenzhen.aliyuncs.com/shuibei-mini/new-mini/login@2x.png'); */
+	background-color: #fff;
+	background-image: url("https://sb-admin.oss-cn-shenzhen.aliyuncs.com/shuibei-mini/new-mini/jianbianBG.png");
+}
+.whiteBg-tabimg{
+	background: url('https://sb-admin.oss-cn-shenzhen.aliyuncs.com/shuibei-mini/new-mini/logintab1.png');
+}
+.whiteBg-tabsimg{
+	background: url('https://sb-admin.oss-cn-shenzhen.aliyuncs.com/shuibei-mini/new-mini/logintab.png');
+}
+
+.product-con .uni-swiper-dots-horizontal{
+  bottom: 42rpx;
+}
+
+.product-con .u-swiper__indicator{
+	bottom: 42rpx !important;
 }

BIN
static/images/edit@2x.png


BIN
static/images/login_ip.png


BIN
static/images/notice@2x.png


BIN
static/images/shou@2x.png


BIN
static/images/time@2x.png


BIN
static/images/wxLogin.png


BIN
static/img/IDFront.png


BIN
static/img/IDReverse.png


BIN
static/img/tips@2x.png


+ 7 - 1
stores/app.js

@@ -44,6 +44,9 @@ export const useAppStore = defineStore("app", {
         shopId: "001",
       },
       merchantId: null,
+	  // 首页展示刷新标识,当浏览了新店铺主页/扫店铺码时,改为true,首页onshow时判断true刷新列表并改为false
+	  indexRefreshFlag: false,
+	  cartRefreshFlag: false,
     };
   },
   getters: {
@@ -64,8 +67,11 @@ export const useAppStore = defineStore("app", {
     SET_REFRESH(val) {
       this.refreshArticles = val;
     },
+    SET_CART_REFRESH(val) {
+      this.cartRefreshFlag = val;
+    },
     setIndexRefersh(val) {
-      this.indexRefreshArticles = val;
+      this.indexRefreshFlag = val;
     },
     SET_NAVBAR_HEIGHT(val) {
       this.navbarHeight = val;

+ 40 - 0
utils/util.js

@@ -7,6 +7,7 @@ import { footprintScan } from "@/api/merchant.js";
 import { pathToBase64 } from "@/plugin/image-tools/index.js";
 import { useToast } from "@/hooks/useToast";
 import pageJson from "@/pages.json";
+import { wxLogin } from "@/api/user.js";
 const appStore = useAppStore(); // 调用函数获取实例
 export default {
   /**
@@ -909,7 +910,9 @@ export async function getSceneInfo(e, index) {
         merchantId: params.merchantId,
         userId: appStore.userInfo.userId,
       };
+	  appStore.setIndexRefersh(true)
       await footprintScan(obj);
+      await appStore.USERINFO();
     }
     console.log("获取邀请码-params", params);
     return params;
@@ -1282,3 +1285,40 @@ export const Calc = {
     return result;
   },
 };
+export async function getPhoneNumber(e, inviteCode) {
+  const { Toast } = useToast();
+  console.log('getPhoneNumber123', e);
+
+  // 用户拒绝授权
+  if (e.detail.errMsg !== 'getPhoneNumber:ok') {
+    Toast({ title: '请授权手机号以完成登录' });
+    return null;
+  }
+
+  // 授权成功
+  if (e.detail.code) {
+    try {
+      // 2. 将授权码发送到后端换取手机号
+      const res = await wxLogin({ code: e.detail.code });
+      console.log('wxLogin接口res=', res);
+
+      // 3. 处理后端响应
+      if (res.code === 200) {
+        return res; // 返回数据
+      } else {
+        Toast({ title: res.message || '获取失败' });
+        return null;
+      }
+    } catch (error) {
+      Toast({ title: "获取手机号失败:" + error });
+      console.error('获取手机号失败:', error);
+      return null;
+    } finally {
+
+    }
+  } else {
+    // 授权失败
+    Toast({ title: e.detail?.errorMessage || "请允许授权以获取手机号" });
+    return null;
+  }
+};