37 Commits 85bbd8d6ae ... 36f7b12df3

Autor SHA1 Mensaje Fecha
  ext.zhangbin71 36f7b12df3 fix: 登录页样式调整,首页展示商铺/展示商品刷新逻辑修改,其他页面细节样式调整; hace 1 mes
  ext.zhangbin71 f658c333e1 Merge branch 'dev_v3_lqw' into dev_v3 hace 1 mes
  ext.zhangbin71 b6b5166e75 fix: 店铺主页点击我的商城,查看自己商城功能add;产品中心接口加字段; hace 1 mes
  ext.zhangbin71 d4aace8eb6 fix: 部分页面样式修复 hace 1 mes
  ext.liuqiwen3 6d7b41d4db Merge branch 'dev_v3_lqw' into dev_v3 hace 1 mes
  ext.zhangbin71 7a984e295e fix: 1、修复手动发布商品图片路径不正确问题;2、修复首页商品重复渲染问题;3、修复商品管理批量管理上下架后列表未及时更新问题; hace 1 mes
  ext.liuqiwen3 260f41b2a9 Merge branch 'dev_v3_lqw' into dev_v3 hace 1 mes
  ext.zhangbin71 1a26c62f71 fix: 首页轮播图imgMode改为scaleFill;商品详情页店铺头像展示mode修复;商家详情页店铺头像展示mode修复。 hace 1 mes
  HHE-5476 9bd0545c20 Merge branch 'dev_v3' of http://git.dgtis.com/armg/wxapp_shuibei into dev_v3 hace 1 mes
  HHE-5476 dbfa69ec5e 去除登录邀请码必填,大盘改名实时金价 hace 1 mes
  ext.liuqiwen3 f1cab01a2f Merge branch 'dev_v3_lqw' into dev_v3 hace 1 mes
  ext.liuqiwen3 fe048f6b8a 首页增加下拉刷新 hace 1 mes
  ext.liuqiwen3 c12d8833a0 Merge branch 'dev_v3_lqw' into dev_v3 hace 1 mes
  ext.liuqiwen3 dec934d0fa 修改跳转页面 hace 1 mes
  ext.liuqiwen3 88304c8b0c Merge branch 'dev_v3_lqw' into dev_v3 hace 1 mes
  ext.liuqiwen3 f91b0bad59 优化样式 hace 1 mes
  ext.liuqiwen3 852fcc845c Merge branch 'dev_v3_lqw' into dev_v3 hace 1 mes
  ext.liuqiwen3 8f4197e087 登录增加微信授权登录,首页默认展示最后访问商家 hace 1 mes
  ext.liuqiwen3 e4d5fca21e Merge branch 'dev_v3_lqw' into dev_v3 hace 1 mes
  ext.liuqiwen3 3bd1aa833b 修改购物车下拉刷新问题 hace 1 mes
  ext.liuqiwen3 a48dec983b 修改小程序bug问题 hace 1 mes
  ext.liuqiwen3 79ef8b5e78 Merge branch 'dev_v3_lqw' into dev_v3 hace 1 mes
  ext.liuqiwen3 ff4ad5b0d3 修改小程序bug问题 hace 1 mes
  HHE-5476 0b41f1dbfd 首页筛选掉贝币商城分类 hace 1 mes
  HHE-5476 6ff8f31f97 分类筛掉折扣券分类 hace 1 mes
  HHE-5476 7d883bd61e Merge branch 'dev_v3' of http://git.dgtis.com/armg/wxapp_shuibei into dev_v3 hace 1 mes
  HHE-5476 9e638d8996 少了图片 hace 1 mes
  ext.liuqiwen3 7cb969f7be 修改商品数据为0时不可下单 hace 1 mes
  ext.liuqiwen3 4221fc0718 修改价格乱码 hace 1 mes
  ext.liuqiwen3 ce443c95a6 修改首页金价显示,及大盘样式更新 hace 1 mes
  ext.liuqiwen3 ad66161136 修改隐私协议没反应问题 hace 1 mes
  ext.zhangbin71 af5c6e4885 Merge branch 'dev_v3_lqw' of http://git.dgtis.com/armg/wxapp_shuibei into dev_v3_lqw hace 1 mes
  ext.zhangbin71 806bf9b789 bugfix hace 1 mes
  ext.liuqiwen3 3a229ad22d 修改问题 hace 1 mes
  ext.zhangbin71 648ecbfa3e fix: 修复商品库存都为0时,商品详情价格显示错误问题 hace 1 mes
  ext.liuqiwen3 acb53e4f6d 修改问题 hace 1 mes
  ext.zhangbin71 5459ddce34 fix:购物车接口报错loading弹窗未正确关闭问题修复 hace 1 mes
Se han modificado 39 ficheros con 4545 adiciones y 2930 borrados
  1. 17 0
      api/faceVerify.js
  2. 21 0
      api/user.js
  3. 18 11
      components/productWindow/index.vue
  4. 4 3
      config/app.js
  5. 1 1
      hooks/useSendCode.js
  6. 29 4
      pages.json
  7. 97 54
      pages/goods/goods_details/index.vue
  8. 201 11
      pages/goods/goods_search/index.vue
  9. 2 1
      pages/goods_cate/goods_cate.vue
  10. 1589 1443
      pages/index/index.vue
  11. 453 500
      pages/mall/dapan.vue
  12. 780 672
      pages/merchantCenter/index.vue
  13. 6 1
      pages/merchantCenters/merchant.vue
  14. 4 3
      pages/merchantCenters/productCenter.vue
  15. 4 3
      pages/merchantCenters/productManagement.vue
  16. 4 4
      pages/merchantCenters/releaseProduct.vue
  17. 176 115
      pages/order_addcart/order_addcart.vue
  18. 93 30
      pages/user/index.vue
  19. 9 5
      pages/users/browsing_history/index.vue
  20. 631 0
      pages/users/face_detect/index.vue
  21. 225 60
      pages/users/login/index.vue
  22. 4 4
      pages/users/my_merchant/index.vue
  23. 1 0
      pages/users/order_confirm/index.vue
  24. 0 2
      pages/users/share/index.vue
  25. 2 0
      pages/users/user_address/index.vue
  26. 1 0
      pages/users/user_address_list/index.vue
  27. 1 1
      pages/webview/index.vue
  28. 122 0
      pages/webview/privacy.vue
  29. 7 1
      static/css/base.css
  30. BIN
      static/images/login_ip.png
  31. BIN
      static/images/notice@2x.png
  32. BIN
      static/images/shou@2x.png
  33. BIN
      static/images/time@2x.png
  34. BIN
      static/images/wxLogin.png
  35. BIN
      static/img/IDFront.png
  36. BIN
      static/img/IDReverse.png
  37. BIN
      static/img/tips@2x.png
  38. 3 1
      stores/app.js
  39. 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;

+ 4 - 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;

+ 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
 

+ 29 - 4
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": [
@@ -228,6 +238,21 @@
             "enablePullDownRefresh": false
           }
         },
+        {
+          "path": "face_detect/index",
+          "style": {
+            "navigationBarTitleText": "实名认证",
+            "navigationBarBackgroundColor": "#FFFFFF",
+            "navigationBarTextStyle": "black",
+            "app-plus": {
+              // #ifdef APP-PLUS
+              "titleNView": {
+                "type": "default"
+              }
+              // #endif
+            }
+          }
+        },
         {
           "path": "goods_return/index",
           "style": {
@@ -321,7 +346,7 @@
         {
           "path": "goods_search/index",
           "style": {
-            "navigationBarBackgroundColor": "#FFE079",
+            "navigationBarBackgroundColor": "#ffffff",
             "navigationBarTitleText": "搜索商品",
             "navigationBarTextStyle": "black"
           }

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 97 - 54
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>

+ 2 - 1
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)
     })

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 1589 - 1443
pages/index/index.vue


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 453 - 500
pages/mall/dapan.vue


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 780 - 672
pages/merchantCenter/index.vue


+ 6 - 1
pages/merchantCenters/merchant.vue

@@ -7,7 +7,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" mode="aspectFill"></image>
           </view>
           <view class="center">
             <view class="name">{{merchantInfo.merchantName}}</view>
@@ -180,6 +180,11 @@ const getSbmerchantInfoFn = async () => {
     userId:appStore.userInfo.userId
   }
   await footprintScan(obj)
+  appStore.USERINFO();
+  // 当浏览的店铺主页不是上次浏览店铺时,才改变状态
+  if(query.value.merchantId != appStore.userInfo.lastVisitedMerchantId){
+	  appStore.setIndexRefersh(true)
+  }
   getSbmerchantInfo(data).then((res) => {
     console.log(res);
     merchantInfo.value = res.data;

+ 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

+ 176 - 115
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,80 @@ 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();
-  
+});
+onPullDownRefresh(async () => {
   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;
+    // 重置所有状态
+    resetAllState();
+    Promise.allSettled([
+      getCartListFn(),
+      getInvalidList(),
+      getHostProduct()
+    ]).finally(() => {
+      // 添加一个短暂延迟,确保 DOM 更新完成
+      setTimeout(() => {
+        canShow.value = true;
+        uni.stopPullDownRefresh();
+        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 +642,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 +1116,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() {
@@ -1329,9 +1386,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%;
@@ -1344,9 +1401,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;
@@ -1479,8 +1537,8 @@ const toMerchant = (obj) => {
         .picTxt {
           width: 576rpx;
           .pictrue {
-            width: 160rpx;
-            height: 160rpx;
+            width: 176rpx;
+            height: 176rpx;
             image {
               width: 100%;
               height: 100%;
@@ -1536,6 +1594,7 @@ const toMerchant = (obj) => {
   }
   .placeOrder {
     color: #333;
+	font-weight: bold;
     font-size: 32rpx;
     width: 192rpx;
     height: 88rpx;
@@ -1592,11 +1651,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;
       }
     }

+ 93 - 30
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 && useList&&useList.length>0&&showIcons" 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,6 +438,7 @@ onPageScroll((e) => {
 const wxConfig = ref({});
 const tradeList = ref([]);
 const useList = ref([]);
+const isOwner = ref(true);
 watch(
   () => appStore.wxConfig,
   (newVal) => {
@@ -470,12 +495,13 @@ const openVip = () => {
 // 查看会员权益
 const goVIP = () => {
   // uni.navigateTo({ url: "/pages/users/VIP/VIP" });
-  goDetail("/pages/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" });
@@ -485,7 +511,7 @@ const viewTransactionDetail = () => {
 
 // 充值
 const recharge = () => {
-  if (!isLogin) {
+  if (!appStore.isLogin) {
     toLogin();
   } else {
     uni.navigateTo({
@@ -496,7 +522,7 @@ const recharge = () => {
 
 // 提现
 const withdraw = () => {
-  if (!isLogin) {
+  if (!appStore.isLogin) {
     toLogin();
   } else {
     uni.navigateTo({
@@ -647,6 +673,16 @@ 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">
@@ -659,7 +695,7 @@ const getHistoryList = async () => {
 /* 顶部用户信息 */
 .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;
@@ -671,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;
@@ -690,7 +730,7 @@ const getHistoryList = async () => {
 .name-vip {
   display: flex;
   align-items: center;
-  margin-bottom: 16rpx;
+  margin-bottom: 14rpx;
 }
 
 .name {
@@ -703,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 {
@@ -765,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;
@@ -787,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 {
@@ -865,6 +907,7 @@ const getHistoryList = async () => {
 
 .wallet-btn {
   flex: 1;
+  font-weight: bold;
   text-align: center;
   height: 88rpx;
   line-height: 88rpx;
@@ -919,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 {
@@ -945,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;
 }
@@ -956,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;
 }
 
@@ -1032,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>

+ 225 - 60
pages/users/login/index.vue

@@ -2,16 +2,26 @@
 	<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 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 @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 () => {
@@ -389,7 +440,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 +454,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
+				}
+				appStore.setIndexRefersh(true)
+				await footprintScanFn(obj)
+			} else {
+				console.log('============')
+				appStore.UPDATE_MERCHANT_ID('')
+				Toast({
+					title: "登录成功"
+				});
+				backHome();
+			}
 		} catch (err) {
 			console.error(err);
 			uni.showToast({
@@ -423,24 +477,48 @@
 			});
 		}
 	};
-  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: "登录中..." });
+		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 +539,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-repeat: no-repeat;
 		background-size: 100% 624rpx;
 		background-color: #FFFFFF;
 	}
+
 	.appLogin {
-		
+
 
 		.hds {
 			display: flex;
@@ -557,27 +637,43 @@
 
 	.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;
@@ -587,13 +683,15 @@
 				//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 +705,18 @@
 						}
 					}
 				}
+
 				.noActive {
 					flex: 1;
 				}
 			}
+
 			.whiteBg-tabs {
 				//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 +730,12 @@
 					background: #F9F7F0;
 					border-radius: 16rpx;
 					margin-bottom: 32rpx;
+
 					.texts {
 						flex: 1;
 						font-size: 28rpx;
 					}
-					
+
 					.code {
 						padding: 0;
 						margin: 0;
@@ -648,6 +750,7 @@
 						font-size: 28rpx;
 						font-weight: bold;
 						border: none;
+
 						&::after {
 							width: 0;
 							border: none;
@@ -668,7 +771,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 +793,7 @@
 			padding: 0 80rpx;
 			display: flex;
 			align-items: center;
-			
+
 			image {
 				width: 28rpx;
 				height: 28rpx;
@@ -685,12 +802,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;

+ 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;

+ 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>

+ 7 - 1
static/css/base.css

@@ -475,11 +475,17 @@ checkbox .uni-checkbox-input.uni-checkbox-input-checked::before {
 	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: 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;
 }

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


+ 3 - 1
stores/app.js

@@ -44,6 +44,8 @@ export const useAppStore = defineStore("app", {
         shopId: "001",
       },
       merchantId: null,
+	  // 首页展示刷新标识,当浏览了新店铺主页/扫店铺码时,改为true,首页onshow时判断true刷新列表并改为false
+	  indexRefreshFlag: false,
     };
   },
   getters: {
@@ -65,7 +67,7 @@ export const useAppStore = defineStore("app", {
       this.refreshArticles = 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;
+  }
+};