Browse Source

add 订单添加图片

tea 3 months ago
parent
commit
baf7d0399d

+ 11 - 12
kxmall-admin-ui/src/components/AttachmentUpload/index.vue

@@ -17,7 +17,6 @@
         {{ buttonText }}
       </el-button>
     </el-upload>
-    
     <div v-if="fileList.length > 0" class="file-list">
       <div v-for="(file, index) in fileList" :key="index" class="file-item">
         <div class="file-preview">
@@ -123,15 +122,15 @@ export default {
         this.$message.error('上传文件大小不能超过 10MB!');
         return false;
       }
-      
+
       this.uploading = true;
       return true;
     },
-    
+
     // 上传成功
     handleUploadSuccess(response, file) {
       this.uploading = false;
-      
+
       if (response.code === 200) {
         const fileInfo = {
           name: file.name,
@@ -139,24 +138,24 @@ export default {
           size: file.size,
           type: file.type
         };
-        
+
         this.fileList.push(fileInfo);
         this.$emit('input', this.fileList);
         this.$emit('success', fileInfo);
-        
+
         this.$message.success('上传成功');
       } else {
         this.$message.error(response.msg || '上传失败');
       }
     },
-    
+
     // 上传失败
     handleUploadError(err, file) {
       this.uploading = false;
       this.$message.error('上传失败');
       this.$emit('error', err, file);
     },
-    
+
     // 预览文件
     previewFile(file) {
       if (this.isImageFile(file.url)) {
@@ -171,7 +170,7 @@ export default {
         window.open(file.url, '_blank');
       }
     },
-    
+
     // 下载文件
     downloadFile(file) {
       const link = document.createElement('a');
@@ -181,21 +180,21 @@ export default {
       link.click();
       document.body.removeChild(link);
     },
-    
+
     // 删除文件
     removeFile(index) {
       this.fileList.splice(index, 1);
       this.$emit('input', this.fileList);
       this.$emit('remove', index);
     },
-    
+
     // 判断是否为图片文件
     isImageFile(url) {
       if (!url) return false;
       const imageExtensions = ['.jpg', '.jpeg', '.png', '.gif', '.bmp', '.webp'];
       return imageExtensions.some(ext => url.toLowerCase().includes(ext));
     },
-    
+
     // 格式化文件大小
     formatFileSize(bytes) {
       if (bytes === 0) return '0 B';

+ 71 - 50
kxmall-admin-ui/src/views/order/storeOrder/index.vue

@@ -1,16 +1,16 @@
 <template>
   <div class="app-container">
     <el-tabs v-model="queryParams.orderStatus" @tab-click="onOrderStatusChange">
-      <el-tab-pane v-for="item in status" :key="item.name" :label="item.label" :name="item.name" />
+      <el-tab-pane v-for="item in status" :key="item.name" :label="item.label" :name="item.name"/>
     </el-tabs>
     <el-form ref="queryForm" :model="queryParams" size="small" :inline="true" label-width="68px">
       <el-form-item prop="storageId">
         <el-select v-model="queryParams.storageId" placeholder="请选择前置仓" clearable>
-          <el-option v-for="item in storages" :key="item.id" :label="item.name" :value="item.id" />
+          <el-option v-for="item in storages" :key="item.id" :label="item.name" :value="item.id"/>
         </el-select>
       </el-form-item>
       <el-form-item prop="orderId">
-        <el-input v-model="queryParams.orderId" clearable placeholder="输入订单号" @keyup.enter.native="toQuery" />
+        <el-input v-model="queryParams.orderId" clearable placeholder="输入订单号" @keyup.enter.native="toQuery"/>
       </el-form-item>
       <el-form-item prop="createTime">
         <el-date-picker
@@ -102,7 +102,10 @@
         label="订单类型"
       >
         <template slot-scope="{row}">
-          <el-tag :type="row.shippingType==1 ? 'error' : 'success'">{{ row.shippingType==1?'配送':'自提' }}</el-tag>
+          <el-tag :type="row.shippingType==1 ? 'error' : 'success'">{{
+              row.shippingType == 1 ? '配送' : '自提'
+            }}
+          </el-tag>
         </template>
       </el-table-column>
       <el-table-column
@@ -117,7 +120,7 @@
         label="配送费"
       >
         <template slot-scope="scope">
-          <span>{{ scope.row.freightPrice == 0?'免配送':scope.row.freightPrice }}</span>
+          <span>{{ scope.row.freightPrice == 0 ? '免配送' : scope.row.freightPrice }}</span>
         </template>
       </el-table-column>
       <el-table-column
@@ -134,7 +137,7 @@
         label="实付金额"
       >
         <template slot-scope="scope">
-          <span>{{ scope.row.payIntegral?'积分'+scope.row.payIntegral:'¥'+scope.row.payPrice }}</span>
+          <span>{{ scope.row.payIntegral ? '积分' + scope.row.payIntegral : '¥' + scope.row.payPrice }}</span>
         </template>
       </el-table-column>
       <el-table-column
@@ -205,34 +208,36 @@
             type="primary"
             size="mini"
             @click="viewDetail(row.id)"
-          >详情</el-button>
+          >详情
+          </el-button>
           <el-button
             v-if="row.status===14"
             type="primary"
             size="mini"
             @click="handleOperation(row.id,'startStocking')"
-          >开始配货</el-button>
+          >开始配货
+          </el-button>
           <el-button
             v-if="row.status===16"
             type="primary"
             size="mini"
             @click="handleOperation(row.id,'completeAllocation')"
-          >完成配货</el-button>
-
+          >完成配货
+          </el-button>
           <el-button
             v-if="row.status===30"
             type="primary"
             size="mini"
             @click="handleOperation(row.id,'completeDelivery')"
-          >完成配送</el-button>
+          >完成配送
+          </el-button>
           <el-button
             v-if="(row.status===20||row.status===32||row.status===30) && row.shippingType===2"
             type="success"
             size="mini"
             @click="showVerifyDialog(row.id)"
-          >完成取货</el-button>
-
-
+          >完成取货
+          </el-button>
           <!-- 合并后的配送下拉按钮 -->
           <el-dropdown
             v-if="(row.status===20||row.status===32||row.status===30) && row.shippingType===1"
@@ -247,20 +252,17 @@
               <el-dropdown-item command="merchant">商家自配</el-dropdown-item>
             </el-dropdown-menu>
           </el-dropdown>
-
-
           <el-button
             v-if="[16,20,30,32,34].includes(row.status)"
             type="danger"
             size="mini"
             style="margin-left: 10px;"
             @click="handleCancelOrder(row)"
-          >取消订单</el-button>
-
+          >取消订单
+          </el-button>
         </template>
       </el-table-column>
     </el-table>
-
     <pagination
       v-show="total > 0"
       :total="total"
@@ -268,7 +270,6 @@
       :limit.sync="queryParams.pageSize"
       @pagination="getList"
     />
-
     <!-- 添加或修改订单对话框 -->
     <el-dialog title="订单详情" :visible.sync="open" width="1050px" append-to-body class="order-detail-dialog">
       <div class="detail-container">
@@ -292,7 +293,7 @@
               <div class="detail-item">
                 <span class="item-label">订单类型:</span>
                 <el-tag :type="form.shippingType==1 ? 'primary' : 'success'">
-                  {{ form.shippingType==1?'配送':'自提' }}
+                  {{ form.shippingType == 1 ? '配送' : '自提' }}
                 </el-tag>
               </div>
             </el-col>
@@ -407,7 +408,7 @@
               <div class="detail-item">
                 <span class="item-label">支付金额:</span>
                 <span class="item-value highlight">
-              {{ form.payIntegral?'积分'+form.payIntegral:'¥'+form.payPrice }}
+              {{ form.payIntegral ? '积分' + form.payIntegral : '¥' + form.payPrice }}
             </span>
               </div>
             </el-col>
@@ -527,7 +528,7 @@
           <div class="summary-row total-row">
             <span class="summary-label">实付金额:</span>
             <span class="summary-value highlight">
-          {{ form.payIntegral?'积分'+form.payIntegral:'¥'+form.payPrice }}
+          {{ form.payIntegral ? '积分' + form.payIntegral : '¥' + form.payPrice }}
         </span>
           </div>
         </div>
@@ -589,10 +590,21 @@
 
 <script>
 import Clipboard from 'clipboard';
-import { multiply } from '@/utils/math'
-import { listStoreOrder /** delStoreOrder, addStoreOrder, updateStoreOrder*/, getStoreOrder, startStocking, completeAllocation, merchantDistribution, completeDelivery, distributeOrder, completePickup,thirdPartyDistribution,cancelOrder } from '@/api/order/storeOrder'
-import { listAllStorage } from '@/api/storage/storage'
-import { getRiderByStorageId } from '@/api/rider/rider'
+import {multiply} from '@/utils/math'
+import {
+  listStoreOrder /** delStoreOrder, addStoreOrder, updateStoreOrder*/,
+  getStoreOrder,
+  startStocking,
+  completeAllocation,
+  merchantDistribution,
+  completeDelivery,
+  distributeOrder,
+  completePickup,
+  thirdPartyDistribution,
+  cancelOrder
+} from '@/api/order/storeOrder'
+import {listAllStorage} from '@/api/storage/storage'
+import {getRiderByStorageId} from '@/api/rider/rider'
 
 export default {
   name: 'StoreOrder',
@@ -639,17 +651,17 @@ export default {
       form: {},
       // 表单校验
       status: [
-        { label: '待配货', name: '14' },
-        { label: '配货中', name: '16' },
-        { label: '待配送', name: '20' },
-        { label: '配送中', name: '30' },
-        { label: '已完成', name: '40,50' },
-        { label: '配送异常', name: '32' },
-        { label: '超时订单', name: '34' },
-        { label: '待支付', name: '10' },
-        { label: '已退款', name: '70' },
-        { label: '已取消', name: '80' },
-        { label: '全部订单', name: 'all' }
+        {label: '待配货', name: '14'},
+        {label: '配货中', name: '16'},
+        {label: '待配送', name: '20'},
+        {label: '配送中', name: '30'},
+        {label: '已完成', name: '40,50'},
+        {label: '配送异常', name: '32'},
+        {label: '超时订单', name: '34'},
+        {label: '待支付', name: '10'},
+        {label: '已退款', name: '70'},
+        {label: '已取消', name: '80'},
+        {label: '全部订单', name: 'all'}
       ],
       storages: []
     }
@@ -667,7 +679,7 @@ export default {
   methods: {
     multiply,
     listAllStorage() {
-      listAllStorage().then(({ data }) => {
+      listAllStorage().then(({data}) => {
         this.storages = data
         this.storages.forEach(storage => {
           this.storageMap[storage.id] = storage.name
@@ -744,7 +756,7 @@ export default {
     },
     // 添加这个新方法
     handleDeliveryCommand(row, command) {
-      switch(command) {
+      switch (command) {
         case 'system':
           this.allot(row.storeId, row.orderId, row.postId);
           break;
@@ -757,7 +769,6 @@ export default {
       }
     },
     async confirmCompletePickup() {
-
       if (!this.verifyCode) {
         this.$message.warning('请输入核销码');
         return;
@@ -800,8 +811,8 @@ export default {
     getList() {
       this.loading = true
       this.storeOrderList = []
-      const params = { ...this.queryParams }
-      if(params.createTime){
+      const params = {...this.queryParams}
+      if (params.createTime) {
         params.startTime = params.createTime[0]
         params.endTime = params.createTime[1]
       }
@@ -832,7 +843,7 @@ export default {
       this.handleQuery()
     },
     viewDetail(id) {
-      getStoreOrder(id).then(({ data }) => {
+      getStoreOrder(id).then(({data}) => {
         this.form = data
         this.open = true
       })
@@ -904,17 +915,25 @@ export default {
       return status[s]
     },
     getOrderType(s) {
-      if(s.combinationId){
+      if (s.combinationId) {
         return '团购'
       }
-      if(s.seckillId){
+      if (s.seckillId) {
         return '秒杀'
       }
       return '普通'
     },
     handleOperation(id, operation) {
-      const operations = { startStocking, completeAllocation, merchantDistribution, completeDelivery, completePickup,thirdPartyDistribution, cancelOrder  }
-      operations[operation]({ id }).then(() => {
+      const operations = {
+        startStocking,
+        completeAllocation,
+        merchantDistribution,
+        completeDelivery,
+        completePickup,
+        thirdPartyDistribution,
+        cancelOrder
+      }
+      operations[operation]({id}).then(() => {
         this.$message({
           message: '操作成功',
           type: 'success'
@@ -923,9 +942,9 @@ export default {
       })
     },
     check(val) {
-      const loadingInstance = this.$loading({ text: '正在分配中...' })
+      const loadingInstance = this.$loading({text: '正在分配中...'})
       distributeOrder({
-        orderId: this.orderId,
+        orderNo: this.orderId,
         riderId: val
       }).then(res => {
         this.allotShow = false
@@ -1028,10 +1047,12 @@ export default {
     padding: 20px;
   }
 }
+
 .rider-info {
   .status-tag {
     margin-left: 5px;
   }
+
   .abnormal-reason {
     color: #f56c6c;
     font-weight: bold;

+ 40 - 2
kxmall-admin-ui/src/views/product/storeProduct/index.vue

@@ -133,7 +133,23 @@
           </el-col>
           <el-col :span="8">
             <el-form-item label="商品关键字" prop="keyword">
-              <el-input v-model="form.keyword" placeholder="请输入商品关键字,多个关键字用逗号隔开" />
+              <el-select
+                v-model="form.keywordArray"
+                multiple
+                filterable
+                allow-create
+                default-first-option
+                placeholder="请选择或输入商品关键字"
+                style="width: 100%"
+                @change="handleKeywordChange"
+              >
+                <el-option
+                  v-for="item in keywordOptions"
+                  :key="item.dictValue"
+                  :label="item.dictLabel"
+                  :value="item.dictValue"
+                />
+              </el-select>
             </el-form-item>
           </el-col>
         </el-row>
@@ -580,6 +596,8 @@ export default {
       },
       // 表单参数
       form: {},
+      // 关键字选项数据
+      keywordOptions: [],
       // 表单校验
       rules: {
         storeName: [
@@ -589,7 +607,7 @@ export default {
           { required: true, message: '请选择商品分类', trigger: 'change' }
         ],
         keyword: [
-          { required: true, message: '请输入商品关键字', trigger: 'blur' }
+          { required: true, message: '请选择商品关键字', trigger: 'change' }
         ],
         unitName: [
           { required: true, message: '请输入单位', trigger: 'blur' }
@@ -649,8 +667,20 @@ export default {
   created() {
     this.listStoreCategoryTree()
     this.getList()
+    this.loadKeywordOptions()
   },
   methods: {
+    /** 加载关键字选项数据 */
+    loadKeywordOptions() {
+      this.getDicts("sys_store_keyword").then(response => {
+        this.keywordOptions = response.data
+      })
+    },
+    /** 处理关键字变化 */
+    handleKeywordChange(value) {
+      // 将选中的关键字数组转换为逗号分隔的字符串
+      this.form.keyword = value.join(',')
+    },
     /** 导入按钮操作 */
     handleImport() {
       this.upload.title = "商品导入";
@@ -717,6 +747,8 @@ export default {
         cateId: undefined,
         unitName: undefined,
         storeInfo: undefined,
+        keyword: undefined,
+        keywordArray: [],
         sliderImage: [],
         specType: 0,
         isIntegral: 0,
@@ -791,6 +823,12 @@ export default {
         this.loading = false
         this.form = productInfo
         this.form.header = []
+        // 将关键字字符串转换为数组
+        if (this.form.keyword) {
+          this.form.keywordArray = this.form.keyword.split(',').filter(item => item.trim())
+        } else {
+          this.form.keywordArray = []
+        }
         this.ruleList = ruleList
         this.attr = [productInfo.attr]
         if (productInfo.specType === 1) {

+ 104 - 2
kxmall-admin-ui/src/views/rider/rider/index.vue

@@ -52,6 +52,13 @@
       <el-table-column label="配送员编号" align="center" prop="id" v-if="true"/>
       <el-table-column label="配送员名字" align="center" prop="name" />
       <el-table-column label="联系电话" align="center" prop="phone" />
+      <el-table-column label="等级" align="center" prop="level">
+        <template slot-scope="scope">
+          {{ getLevelText(scope.row.level) }}
+        </template>
+      </el-table-column>
+      <el-table-column label="服务半径(km)" align="center" prop="deliveryRadius" />
+      <el-table-column label="擅长类型" align="center" prop="workTypeKeywords" show-overflow-tooltip />
 
       <el-table-column
           prop="storageId"
@@ -133,6 +140,49 @@
           <el-input v-model="form.phone" placeholder="请输入联系电话" />
         </el-form-item>
 
+        <el-form-item label="身份证号" prop="idCardNumber">
+          <el-input v-model="form.idCardNumber" placeholder="请输入身份证号" maxlength="18" />
+        </el-form-item>
+
+        <el-form-item label="等级" prop="level">
+          <el-select v-model="form.level" placeholder="请选择骑手等级" clearable>
+            <el-option label="初级骑手" :value="1" />
+            <el-option label="中级骑手" :value="2" />
+            <el-option label="高级骑手" :value="3" />
+            <el-option label="资深骑手" :value="4" />
+            <el-option label="专家骑手" :value="5" />
+          </el-select>
+        </el-form-item>
+
+        <el-form-item label="服务半径(km)" prop="deliveryRadius">
+          <el-input-number
+            v-model="form.deliveryRadius"
+            :min="1"
+            :max="50"
+            :precision="0"
+            placeholder="请输入服务半径"
+            style="width: 30%"
+          />
+        </el-form-item>
+
+        <el-form-item label="擅长类型" prop="workTypeKeywords">
+          <el-select
+            v-model="form.workTypeKeywordsArray"
+            multiple
+            filterable
+            placeholder="请选择擅长的服务类型"
+            style="width: 100%"
+            @change="handleWorkTypeKeywordsChange"
+          >
+            <el-option
+              v-for="item in specialtyOptions"
+              :key="item.dictValue"
+              :label="item.dictLabel"
+              :value="item.dictValue"
+            />
+          </el-select>
+        </el-form-item>
+
         <el-form-item prop="phone" label="新密码">
           <el-input v-model="form.newPassword" autocomplete="off" clearable></el-input>
         </el-form-item>
@@ -361,6 +411,8 @@ export default {
       qrcode: '',
       // 仓库map
       storageMap: {},
+      // 擅长类型选项数据
+      specialtyOptions: [],
       // 表单参数
       form: {},
       // 表单校验
@@ -371,6 +423,20 @@ export default {
         storageId: [
           { required: true, message: "所属仓库不能为空", trigger: "blur" }
         ],
+        idCardNumber: [
+          { required: true, message: "身份证号不能为空", trigger: "blur" },
+          { pattern: /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/, message: "身份证号格式不正确", trigger: "blur" }
+        ],
+        level: [
+          { required: true, message: "请选择骑手等级", trigger: "change" }
+        ],
+        deliveryRadius: [
+          { required: true, message: "服务半径不能为空", trigger: "blur" },
+          { type: 'number', min: 1, max: 50, message: "服务半径必须在1-50km之间", trigger: "blur" }
+        ],
+        workTypeKeywords: [
+          { required: true, message: "请选择擅长类型", trigger: "change" }
+        ],
       },
       // 上传相关配置
       uploadUrl: process.env.VUE_APP_BASE_API + '/system/oss/upload',
@@ -381,9 +447,32 @@ export default {
   },
   created() {
     this.listAllStorage()
-    this.getList();
+    this.getList()
+    this.loadSpecialtyOptions()
   },
   methods: {
+    /** 加载擅长类型选项数据 */
+    loadSpecialtyOptions() {
+      this.getDicts("sys_store_keyword").then(response => {
+        this.specialtyOptions = response.data
+      })
+    },
+    /** 处理擅长类型变化 */
+    handleWorkTypeKeywordsChange(value) {debugger
+      // 将选中的擅长类型数组转换为逗号分隔的字符串
+      this.form.workTypeKeywords = value.join(',')
+    },
+    /** 获取等级文本 */
+    getLevelText(level) {
+      const levelMap = {
+        1: '初级骑手',
+        2: '中级骑手',
+        3: '高级骑手',
+        4: '资深骑手',
+        5: '专家骑手'
+      }
+      return levelMap[level] || '未设置'
+    },
     onChanged() {
     },
     listAllStorage() {
@@ -432,7 +521,13 @@ export default {
         newPassword: undefined,
         weekNumberIds: ['周一', '周二', '周三', '周四', '周五', '周六', '周日'],
         updateBy: undefined,
-        attachments: []
+        attachments: [],
+        // 新增字段
+        idCardNumber: undefined,
+        level: undefined,
+        deliveryRadius: undefined,
+        workTypeKeywords: undefined,
+        workTypeKeywordsArray: []
       };
       this.resetForm("form");
       // 重置行上传无需额外状态
@@ -473,6 +568,13 @@ export default {
         this.form = response.data;
         this.form.weekNumberIds = (this.form.weekNumberIds || []).map(item => num2TextMap[item])
 
+        // 处理擅长类型:将字符串转换为数组
+        if (this.form.workTypeKeywords) {
+          this.form.workTypeKeywordsArray = this.form.workTypeKeywords.split(',').filter(item => item.trim())
+        } else {
+          this.form.workTypeKeywordsArray = []
+        }
+
         // 加载附件数据
         if (this.form.attachments) {
           this.form.attachments = this.form.attachments.map(att => ({

+ 10 - 6
kxmall-app-ui/main.js

@@ -161,7 +161,7 @@ const request = (method, endpoint, data = {}, failCallback) => {
 }
 
 
-const uploadImg = (num = 9, successCallback) => {
+const uploadImg = (num = 9, successCallback, failCallback= undefined) => {
   userInfo = uni.getStorageSync('userInfo');
   var accessToken = userInfo ? userInfo.accessToken : '';
   let baseUrl = config.def().baseUrl
@@ -191,11 +191,15 @@ const uploadImg = (num = 9, successCallback) => {
               }
             },
             fail: err => {
-              uni.showToast({
-                title: '上传图片失败',
-                icon: 'none',
-                duration: 2000,
-              })
+              if (failCallback) {
+                failCallback(err)
+              } else {
+                uni.showToast({
+                  title: '上传图片失败',
+                  icon: 'none',
+                  duration: 2000,
+                })
+              }
             },
             complete: res => {
               uni.hideLoading()

+ 1 - 1
kxmall-app-ui/manifest.json

@@ -132,7 +132,7 @@
     "mp-weixin" : {
         /* 小程序特有相关 */
         "usingComponents" : true,
-        "appid" : "wxfaacb8d3e761189c",
+        "appid" : "wxb9c68e78feee66b7",
         "setting" : {
             "urlCheck" : false,
             "es6" : true,

File diff suppressed because it is too large
+ 13 - 8
kxmall-app-ui/pages/order/create.vue


+ 1 - 1
kxmall-app-ui/pages/order/detail.vue

@@ -13,7 +13,7 @@
     <view class="state">
       <view class="state-text" v-if="orderDetail.status !== 10"
         :style="state == 5 || state == 8?'color:#1B1C33;font-size:20px':''">
-        {{orderDetail.orderType == 1?'(自提)':''}}{{stateText}}
+        {{ orderDetail.orderType === 1 ? '(自提)' : '' }}{{ stateText }}
       </view>
       <view class="state-text" v-if="state === 0">
         {{'等待支付 剩余'+ num(minutes)}}:{{num(seconds)}}

+ 680 - 627
kxmall-app-ui/pages/user/user.vue

@@ -1,686 +1,739 @@
 <template>
-    <view >
-		<view v-if="storage">
-			<view class="bg-user-gradual-green" style=" background-image: url(https://kxmalls.oss-cn-hangzhou.aliyuncs.com/bg/bg.png);">
-				<view :style="'height:'+statusBarHeight+'px;'" style="width: 750rpx;display: flex; position: relative;"></view>
-				<view class="flex align-center justify-center"
-				style="height: 88rpx;font-size: 36rpx;"
-				 >
-					个人中心
-				</view>
-				<view class="padding-top-lg flex justify-between align-end padding-lr" style="padding-top: 30rpx;">
+  <view>
+    <view v-if="storage">
+      <view class="bg-user-gradual-green"
+            style=" background-image: url(https://kxmalls.oss-cn-hangzhou.aliyuncs.com/bg/bg.png);">
+        <view :style="'height:'+statusBarHeight+'px;'" style="width: 750rpx;display: flex; position: relative;"></view>
+        <view class="flex align-center justify-center"
+              style="height: 88rpx;font-size: 36rpx;"
+        >
+          个人中心
+        </view>
+        <view class="padding-top-lg flex justify-between align-end padding-lr" style="padding-top: 30rpx;">
           <view class="">
             <view @click="toLogin" style="margin-top: 16rpx;font-size: 40rpx;height: 56rpx;">
-              HI,{{ hasLogin? (userInfo.nickname || '未设置昵称') : '请注册/登录' }}
+              HI,{{ hasLogin ? (userInfo.nickname || '未设置昵称') : '请注册/登录' }}
               <!-- 添加VIP标识 -->
               <view v-if="hasLogin && userInfo.level > 0"
                     style="display: inline-flex; align-items: center; margin-left: 10rpx;">
                 <text v-if="hasLogin && userInfo.level > 0"
                       :style="{color: getVipColor(userInfo.level)}"
                       style="font-size: 24rpx;margin-left: 10rpx;">
-                  {{ getVipName(userInfo.level)}}
+                  {{ getVipName(userInfo.level) }}
                 </text>
               </view>
             </view>
           </view>
-					<view @click="navTo('/pages/user/profile')" style="position: relative;padding-right: 8rpx;">
-						<image :src="hasLogin && userInfo.avatar ? userInfo.avatar :'../../static/user/touxiang-@2x.png'"
-						class="round" mode="aspectFill"
-						style="width: 144rpx;height: 144rpx;"></image>
-						<view v-if="hasLogin" class="flex align-center justify-center" style="position: absolute;bottom: 0rpx;left: 29rpx; background-color: #8AD62A;border-radius: 200rpx;width: 86rpx;height: 38rpx;color: #FFFFFF;font-size: 22rpx;"
-						>编辑</view>
-					</view>
-				</view>
-			</view>
+          <view @click="navTo('/pages/user/profile')" style="position: relative;padding-right: 8rpx;">
+            <image :src="hasLogin && userInfo.avatar ? userInfo.avatar :'../../static/user/touxiang-@2x.png'"
+                   class="round" mode="aspectFill"
+                   style="width: 144rpx;height: 144rpx;"></image>
+            <view v-if="hasLogin" class="flex align-center justify-center"
+                  style="position: absolute;bottom: 0rpx;left: 29rpx; background-color: #8AD62A;border-radius: 200rpx;width: 86rpx;height: 38rpx;color: #FFFFFF;font-size: 22rpx;"
+            >编辑
+            </view>
+          </view>
+        </view>
+      </view>
       <view class="margin-lr bg-white shadow"
             style="border-radius: 16rpx 16rpx 16rpx 16rpx;width: 690rpx;height: 140rpx;margin-top: -146rpx;margin-bottom: 20rpx">
         <view class="flex justify-around align-center padding-top-sm">
           <view class="flex align-center justify-center flex-direction" style="width: 108rpx;">
-            {{ nowMoney || 0 }}
-            <view @click="navTo('/pages/user/money')" style="padding-top: 20rpx;font-size: 24rpx;color: #272B54;">余额</view>
+            {{ hasLogin ? (nowMoney || 0) : '-' }}
+            <view @click="navTo('/pages/user/money')" style="padding-top: 20rpx;font-size: 24rpx;color: #272B54;">余额
+            </view>
           </view>
-          <view @click="navTo('/pages/user/coupons?type=user')" class="flex align-center justify-center flex-direction" style="width: 108rpx;">
-            {{ couponListSize || 0 }}
+          <view @click="navTo('/pages/user/coupons?type=user')" class="flex align-center justify-center flex-direction"
+                style="width: 108rpx;">
+            {{ hasLogin ? (couponListSize || 0) : '-' }}
             <view style="padding-top: 20rpx;font-size: 24rpx;color: #272B54;">优惠券</view>
           </view>
-          <view @click="navTo('/pages/user/integral')" class="flex align-center justify-center flex-direction" style="width: 108rpx;">
-            {{ integral || 0 }}
+          <view @click="navTo('/pages/user/integral')" class="flex align-center justify-center flex-direction"
+                style="width: 108rpx;">
+            {{ hasLogin ? (integral || 0) : '-' }}
             <view style="padding-top: 20rpx;font-size: 24rpx;color: #272B54;">积分</view>
           </view>
         </view>
       </view>
-			<view class="margin-lr bg-white shadow"
-			style="border-radius: 16rpx 16rpx 16rpx 16rpx;width: 690rpx;height: 140rpx;">
-				<view class="flex justify-around align-center padding-top-sm">
-					<view @click="navTo('/pages/order/list?state=0')" class="flex align-center justify-center flex-direction" style="width: 108rpx;">
-						<image src="../../static/user/all_order.png" mode="aspectFit" style="width: 46rpx;height: 50rpx;"></image>
-						<view style="padding-top: 20rpx;font-size: 24rpx;color: #272B54;">全部订单</view>
-					</view>
-					<view @click="navTo('/pages/order/list?state=1')" class="flex align-center justify-center flex-direction" style="width: 108rpx;">
-						<image src="../../static/user/waitpay.png" mode="aspectFit" style="width: 46rpx;height: 50rpx;"></image>
-						<view style="padding-top: 20rpx;font-size: 24rpx;color: #272B54;">待付款</view>
-					</view>
-					<view @click="navTo('/pages/order/list?state=2')" class="flex align-center justify-center flex-direction" style="width: 108rpx;">
-						<image src="../../static/user/daishouhuo@3x.png" mode="aspectFit" style="width: 46rpx;height: 50rpx;"></image>
-						<view style="padding-top: 20rpx;font-size: 24rpx;color: #272B54;">待收货</view>
-					</view>
-					<view @click="navTo('/pages/order/list?state=3')" class="flex align-center justify-center flex-direction" style="width: 108rpx;">
-						<image src="../../static/user/shouhou@3x.png" mode="aspectFit" style="width: 46rpx;height: 50rpx;"></image>
-						<view style="padding-top: 20rpx;font-size: 24rpx;color: #272B54;">待评价</view>
-					</view>
-          <view @click="navTo('/pages/refund/index?state=0')" class="flex align-center justify-center flex-direction" style="width: 108rpx;">
-						<image src="../../static/user/shouhou@3x.png" mode="aspectFit" style="width: 46rpx;height: 50rpx;"></image>
-						<view style="padding-top: 20rpx;font-size: 24rpx;color: #272B54;">售后</view>
-					</view>
-				</view>
-			</view>
-			<view class="padding-lr padding-tb-sm">
-				<image src="https://nontax.oss-cn-beijing.aliyuncs.com/kxmall/G2usUI.png" mode="aspectFit"
-				style="width: 690rpx;height: 184rpx;"></image>
-			</view>
-
-			<view class="margin-lr margin-bottom-sm shadow bg-white" style="border-radius: 10rpx;">
-				<view @click="navTo('/pages/address/list')" class="flex align-center padding">
-					<image src="../../static/user/location@3x.png" mode="aspectFit"
-					style="width: 32rpx;height: 36rpx;"></image>
-					<view class="padding-left-sm lem-text-black" style="font-size: 28rpx;">地址管理</view>
-				</view>
-				<view @click="navTo('/pages/user/userVip')" class="flex align-center padding">
-					<image src="../../static/user/vip.png" mode="aspectFit"
-					style="width: 32rpx;height: 36rpx;"></image>
-					<view class="padding-left-sm lem-text-black" style="font-size: 28rpx;">会员中心</view>
-				</view>
+      <view class="margin-lr bg-white shadow"
+            style="border-radius: 16rpx 16rpx 16rpx 16rpx;width: 690rpx;height: 140rpx;">
+        <view class="flex justify-around align-center padding-top-sm">
+          <view @click="navTo('/pages/order/list?state=0')" class="flex align-center justify-center flex-direction"
+                style="width: 108rpx;">
+            <image src="../../static/user/all_order.png" mode="aspectFit" style="width: 46rpx;height: 50rpx;"></image>
+            <view style="padding-top: 20rpx;font-size: 24rpx;color: #272B54;">全部订单</view>
+          </view>
+          <view @click="navTo('/pages/order/list?state=1')" class="flex align-center justify-center flex-direction"
+                style="width: 108rpx;">
+            <image src="../../static/user/waitpay.png" mode="aspectFit" style="width: 46rpx;height: 50rpx;"></image>
+            <view style="padding-top: 20rpx;font-size: 24rpx;color: #272B54;">待付款</view>
+          </view>
+          <view @click="navTo('/pages/order/list?state=2')" class="flex align-center justify-center flex-direction"
+                style="width: 108rpx;">
+            <image src="../../static/user/daishouhuo@3x.png" mode="aspectFit"
+                   style="width: 46rpx;height: 50rpx;"></image>
+            <view style="padding-top: 20rpx;font-size: 24rpx;color: #272B54;">待收货</view>
+          </view>
+          <view @click="navTo('/pages/order/list?state=3')" class="flex align-center justify-center flex-direction"
+                style="width: 108rpx;">
+            <image src="../../static/user/shouhou@3x.png" mode="aspectFit" style="width: 46rpx;height: 50rpx;"></image>
+            <view style="padding-top: 20rpx;font-size: 24rpx;color: #272B54;">待评价</view>
+          </view>
+          <view @click="navTo('/pages/refund/index?state=0')" class="flex align-center justify-center flex-direction"
+                style="width: 108rpx;">
+            <image src="../../static/user/shouhou@3x.png" mode="aspectFit" style="width: 46rpx;height: 50rpx;"></image>
+            <view style="padding-top: 20rpx;font-size: 24rpx;color: #272B54;">售后</view>
+          </view>
+        </view>
+      </view>
+      <view class="padding-lr padding-tb-sm">
+        <image src="https://nontax.oss-cn-beijing.aliyuncs.com/kxmall/G2usUI.png" mode="aspectFit"
+               style="width: 690rpx;height: 184rpx;"></image>
+      </view>
+      
+      <view class="margin-lr margin-bottom-sm shadow bg-white" style="border-radius: 10rpx;">
+        <view @click="navTo('/pages/address/list')" class="flex align-center padding">
+          <image src="../../static/user/location@3x.png" mode="aspectFit"
+                 style="width: 32rpx;height: 36rpx;"></image>
+          <view class="padding-left-sm lem-text-black" style="font-size: 28rpx;">地址管理</view>
+        </view>
+        <view @click="navTo('/pages/user/userVip')" class="flex align-center padding">
+          <image src="../../static/user/vip.png" mode="aspectFit"
+                 style="width: 32rpx;height: 36rpx;"></image>
+          <view class="padding-left-sm lem-text-black" style="font-size: 28rpx;">会员中心</view>
+        </view>
         <view @click="navTo('/pages/user/coupons?type=user')" class="flex align-center padding">
           <image src="../../static/user/notice@3x.png" mode="aspectFit"
                  style="width: 32rpx;height: 36rpx;"></image>
           <view class="padding-left-sm lem-text-black" style="font-size: 28rpx;">我的优惠券</view>
         </view>
-				<button open-type="contact" class="flex align-center padding contact-btn" >
-					<image src="../../static/user/secretary@3x.png" mode="aspectFit"
-					style="width: 32rpx;height: 36rpx;"></image>
-					<view class="padding-left-sm lem-text-black" style="font-size: 28rpx;">在线客服</view>
-				</button>
-			</view>
-			<view class="margin-lr margin-bottom-sm shadow bg-white" style="border-radius: 10rpx;">
-				<view @click="navTo('/pages/product/favorite')" class="flex align-center padding">
-					<image src="../../static/user/collect@3x.png" mode="aspectFit"
-					style="width: 32rpx;height: 36rpx;"></image>
-					<view class="padding-left-sm lem-text-black" style="font-size: 28rpx;">我的收藏</view>
-				</view>
-				<view @click="navTo('/pages/product/footprint')" class="flex align-center padding">
-					<image src="../../static/user/zuji.png" mode="aspectFit"
-					style="width: 32rpx;height: 36rpx;"></image>
-					<view class="padding-left-sm lem-text-black" style="font-size: 28rpx;">我的足迹</view>
-				</view>
+        <button open-type="contact" class="flex align-center padding contact-btn">
+          <image src="../../static/user/secretary@3x.png" mode="aspectFit"
+                 style="width: 32rpx;height: 36rpx;"></image>
+          <view class="padding-left-sm lem-text-black" style="font-size: 28rpx;">在线客服</view>
+        </button>
+      </view>
+      <view class="margin-lr margin-bottom-sm shadow bg-white" style="border-radius: 10rpx;">
+        <view @click="navTo('/pages/product/favorite')" class="flex align-center padding">
+          <image src="../../static/user/collect@3x.png" mode="aspectFit"
+                 style="width: 32rpx;height: 36rpx;"></image>
+          <view class="padding-left-sm lem-text-black" style="font-size: 28rpx;">我的收藏</view>
+        </view>
+        <view @click="navTo('/pages/product/footprint')" class="flex align-center padding">
+          <image src="../../static/user/zuji.png" mode="aspectFit"
+                 style="width: 32rpx;height: 36rpx;"></image>
+          <view class="padding-left-sm lem-text-black" style="font-size: 28rpx;">我的足迹</view>
+        </view>
         <view @click="navTo('/pages/user/promotion')" class="flex align-center padding">
-					<image src="../../static/user/promoter.png" mode="aspectFit"
-					style="width: 32rpx;height: 36rpx;"></image>
-					<view class="padding-left-sm lem-text-black" style="font-size: 28rpx;">我的推广</view>
-				</view>
-				<view @click="navTo('/pages/user/about')" class="flex align-center padding">
-					<image src="../../static/user/tip_round@3x.png" mode="aspectFit"
-					style="width: 32rpx;height: 36rpx;"></image>
-					<view class="padding-left-sm lem-text-black" style="font-size: 28rpx;">关于</view>
-				</view>
-				<view @click="navTo('/pages/set/set')" class="flex align-center padding">
-					<image src="../../static/user/setting@3x.png" mode="aspectFit"
-					style="width: 32rpx;height: 36rpx;"></image>
-					<view class="padding-left-sm lem-text-black" style="font-size: 28rpx;">设置</view>
-				</view>
-				<view @click="navTo('/pages/notice/notice')" class="flex align-center padding">
-					<image src="../../static/user/notice@3x.png" mode="aspectFit"
-					style="width: 32rpx;height: 36rpx;"></image>
-					<view class="padding-left-sm lem-text-black" style="font-size: 28rpx;">通知</view>
-				</view>
-			</view>
-		</view>
-		<view v-else style="padding-top: 180rpx;padding-bottom: 180rpx;">
-			<missing :buttonName="'换个地址试试吧~'" :handlerName="'buttonClick'"
-			@buttonClick="chooseLocation"
-			:imgUrl="'http://qiniuoss.nauzone.cn/%E7%BB%84%204%20%E6%8B%B7%E8%B4%9D@3x.png'" :desc="'当前地区不在配送范围哦'"></missing>
-		</view>
-
-      <!-- 猜您喜欢 -->
-      <view style="padding: 20rpx 12rpx 20rpx 30rpx;background-color: #f1f1f1;">
-        <view class="flex justify-between align-center" style="padding: 20rpx 0;">
-          <view style="font-size: 32rpx;font-weight: bold;color: #333;">猜您喜欢</view>
-          <view @click="refreshRecommend" style="font-size: 24rpx;color: #999;margin-right: 10px;">换一批</view>
+          <image src="../../static/user/promoter.png" mode="aspectFit"
+                 style="width: 32rpx;height: 36rpx;"></image>
+          <view class="padding-left-sm lem-text-black" style="font-size: 28rpx;">我的推广</view>
         </view>
-
-        <view v-if="recommendList.length > 0 && storage" class="flex flex-wrap">
-          <view v-for="(item,index) in recommendList" :key="index"
-                class="margin-bottom-sm bg-white flex align-center justify-center flex-direction"
-                style="width: 335rpx;height: 520rpx;padding: 10rpx;margin-right: 18rpx;border-radius: 8rpx;"
-                @click="navToDetailPage(item.id)">
-            <image style="width: 280rpx;height: 280rpx;margin: 10rpx;" :src="JSON.parse(item.image)[0].url"
-                   mode="aspectFit"></image>
-            <view style="padding-top: 28rpx;">
-              <view class="text-cut"
-                    style="width: 294rpx;height: 40rpx;font-size: 28rpx;font-weight: Medium; color: #2D4454;">{{item.storeName}}
-              </view>
-              <view class="text-cut margin-tb-xs" style="width: 294rpx;height: 40rpx;font-size: 28rpx;color: #999999;">
-                {{item.storeInfo}}
-              </view>
-              <view style="padding-top: 6rpx;" class="flex align-center justify-between">
-                <view style="width: 114rpx;height: 42rpx;line-height: 42rpx;font-size: 24rpx;color:#F62929;">
-                  ¥{{item.kxStockVo.price}}</view>
-                <view style="color: #B0B0B0;font-size: 24rpx;">{{item.unitName}}/份</view>
-                <image @click.stop="addCart(item)" style="width: 48rpx;height: 48rpx;"
-                       src="../../static/index/cart.png" mode="aspectFit" class="round"></image>
+        <view @click="navTo('/pages/user/about')" class="flex align-center padding">
+          <image src="../../static/user/tip_round@3x.png" mode="aspectFit"
+                 style="width: 32rpx;height: 36rpx;"></image>
+          <view class="padding-left-sm lem-text-black" style="font-size: 28rpx;">关于</view>
+        </view>
+        <view @click="navTo('/pages/set/set')" class="flex align-center padding">
+          <image src="../../static/user/setting@3x.png" mode="aspectFit"
+                 style="width: 32rpx;height: 36rpx;"></image>
+          <view class="padding-left-sm lem-text-black" style="font-size: 28rpx;">设置</view>
+        </view>
+        <view @click="navTo('/pages/notice/notice')" class="flex align-center padding">
+          <image src="../../static/user/notice@3x.png" mode="aspectFit"
+                 style="width: 32rpx;height: 36rpx;"></image>
+          <view class="padding-left-sm lem-text-black" style="font-size: 28rpx;">通知</view>
+        </view>
+      </view>
+    </view>
+    <view v-else style="padding-top: 180rpx;padding-bottom: 180rpx;">
+      <missing :buttonName="'换个地址试试吧~'" :handlerName="'buttonClick'"
+               @buttonClick="chooseLocation"
+               :imgUrl="'http://qiniuoss.nauzone.cn/%E7%BB%84%204%20%E6%8B%B7%E8%B4%9D@3x.png'"
+               :desc="'当前地区不在配送范围哦'"></missing>
+    </view>
+    
+    <!-- 猜您喜欢 -->
+    <view style="padding: 20rpx 12rpx 20rpx 30rpx;background-color: #f1f1f1;">
+      <view class="flex justify-between align-center" style="padding: 20rpx 0;">
+        <view style="font-size: 32rpx;font-weight: bold;color: #333;">猜您喜欢</view>
+        <view @click="refreshRecommend" style="font-size: 24rpx;color: #999;margin-right: 10px;">换一批</view>
+      </view>
+      
+      <view v-if="recommendList.length > 0 && storage" class="flex flex-wrap">
+        <view v-for="(item,index) in recommendList" :key="index"
+              class="margin-bottom-sm bg-white flex align-center justify-center flex-direction"
+              style="width: 335rpx;height: 520rpx;padding: 10rpx;margin-right: 18rpx;border-radius: 8rpx;"
+              @click="navToDetailPage(item.id)">
+          <image style="width: 280rpx;height: 280rpx;margin: 10rpx;" :src="JSON.parse(item.image)[0].url"
+                 mode="aspectFit"></image>
+          <view style="padding-top: 28rpx;">
+            <view class="text-cut"
+                  style="width: 294rpx;height: 40rpx;font-size: 28rpx;font-weight: Medium; color: #2D4454;">
+              {{ item.storeName }}
+            </view>
+            <view class="text-cut margin-tb-xs" style="width: 294rpx;height: 40rpx;font-size: 28rpx;color: #999999;">
+              {{ item.storeInfo }}
+            </view>
+            <view style="padding-top: 6rpx;" class="flex align-center justify-between">
+              <view style="width: 114rpx;height: 42rpx;line-height: 42rpx;font-size: 24rpx;color:#F62929;">
+                ¥{{ item.kxStockVo.price }}
               </view>
+              <view style="color: #B0B0B0;font-size: 24rpx;">{{ item.unitName }}/份</view>
+              <image @click.stop="addCart(item)" style="width: 48rpx;height: 48rpx;"
+                     src="../../static/index/cart.png" mode="aspectFit" class="round"></image>
             </view>
           </view>
         </view>
-
-        <view v-else class="flex align-center justify-center" style="height: 200rpx;color: #999;">
-          暂无推荐商品
-        </view>
       </view>
-
+      
+      <view v-else class="flex align-center justify-center" style="height: 200rpx;color: #999;">
+        暂无推荐商品
+      </view>
     </view>
+  
+  </view>
 </template>
 <script>
-	import listCell from '@/components/mix-list-cell';
-	import missing from "@/components/missing.vue"
-    import {
-        mapState
-    } from 'vuex';
-	let startY = 0, moveY = 0, pageAtTop = true;
-    export default {
-		components: {
-			listCell,missing
-		},
-		data(){
-			return {
-        recommendList: [], // 推荐商品列表
-        currentPage: 1,    // 当前页码
-        pageSize: 4,       // 每页显示数量
-        nowMoney: 0,
-        integral: 0,
-        couponListSize: 0,
-				coverTransform: 'translateY(0px)',
-				coverTransition: '0s',
-				moving: false,
-				footprintList: [],
-				isVip: false,
-				statusBarHeight:88,
-				storage:true,
-				banner:{
-					imgUrl:''
-				}
-			}
-		},
-		onShow() {
-			this.isVip = this.$api.isVip()
-			//this.loadFootprint()
-			this.$store.state.storageId ? this.storage = true : this.storage = false
-			//如果用户已登录,获取购物车数量
-			if(this.$store.state.userInfo.accessToken){
-				this.$api.request('get','cart/app/countCart',{
-					storageId:this.$store.state.storageId
-				}).then(res=>{
-					if(res.data > 0){
-						uni.setTabBarBadge({
-							index:2,
-							text:res.data+''
-						})
-					}
-					this.$store.commit('addCart',res.data)
-          this.$api.request('get', 'coupon/app/getUserCoupons').then(res => {
-            this.couponListSize = res.data.length
-          })
-          this.$api.request('get', 'user/app/getUser').then(res => {
-            this.nowMoney = res.data.nowMoney
-            this.integral = res.data.integral
-          })
-				}).catch(err=>{
-					// this.$api.msg('请求失败,请稍后再试')
-				})
-			}
-      // 获取推荐商品
-      if(this.$store.state.storageId) {
-        this.getRecommendList()
-      }
-		},
-		onLoad(){
-			try {
-			    const res = uni.getSystemInfoSync();
-			    console.log(res.statusBarHeight);
-			    this.statusBarHeight = res.statusBarHeight
-			} catch (e) {
-			    // error
-			}
-			this.$api.request('get','carousel/app/getCarouselActive',{
-				adType:8
-			}).then(res=>{
-				this.banner = res.data[0]
-			})
-		},
-		// #ifndef MP
-		onNavigationBarButtonTap(e) {
-			const index = e.index;
-			if (index === 0) {
-				this.navTo('/pages/set/set');
-			}else if(index === 1){
-				// #ifdef APP-PLUS
-				const pages = getCurrentPages();
-				const page = pages[pages.length - 1];
-				const currentWebview = page.$getAppWebview();
-				currentWebview.hideTitleNViewButtonRedDot({
-					index
-				});
-				// #endif
-				uni.navigateTo({
-					url: '/pages/notice/notice'
-				})
-			}
-		},
-		// #endif
-        computed: {
-			...mapState(['hasLogin','userInfo'])
-		},
-        methods: {
-			// async loadFootprint() {
-			// 	const that = this
-			// 	that.$api.request('get', 'getAllFootprint').then(res => {
-			// 		that.footprintList = res.data
-			// 	})
-			// },
-      // 获取VIP等级名称
-      getVipName(level) {
-        const levels = {
-          0: '非会员',
-          1: '普通会员',
-          2: '青铜会员',
-          3: '白银会员',
-          4: '黄金会员',
-          5: '铂金会员',
-          6: '钻石会员'
-        };
-        return levels[level] || '未知等级';
-      },
+import listCell from '@/components/mix-list-cell';
+import missing from "@/components/missing.vue"
+import {
+  mapState
+} from 'vuex';
 
-      // 获取VIP等级对应颜色
-      getVipColor(level) {
-        const colors = {
-          0: '#999',
-          1: '#2a2fd6',  // 普通会员绿色
-          2: '#CD7F32',  // 青铜色
-          3: '#C0C0C0',  // 银色
-          4: '#FFD700',  // 金色
-          5: '#E5E4E2',  // 铂金色
-          6: '#B9F2FF'   // 钻石蓝
-        };
-        return colors[level] || '#2a2fd6';
-      },
-      //详情页
-      navToDetailPage(id) {
-        uni.navigateTo({
-          url: `/pages/product/detail?id=${id}`
-        })
-      },
-      addCart(item) {
-        const that = this
-        that.$api.request('get', 'cart/app/addCartItem', {
-          productId: item.id,
-          num: 1
-        }).then(res => {
-          that.$api.msg('添加购物车成功')
-          var cartNum = this.$store.state.cartNum + 1
-          that.$store.commit('addCart', cartNum)
+let startY = 0, moveY = 0, pageAtTop = true;
+export default {
+  components: {
+    listCell, missing
+  },
+  data() {
+    return {
+      recommendList: [], // 推荐商品列表
+      currentPage: 1,    // 当前页码
+      pageSize: 4,       // 每页显示数量
+      nowMoney: 0,
+      integral: 0,
+      couponListSize: 0,
+      coverTransform: 'translateY(0px)',
+      coverTransition: '0s',
+      moving: false,
+      footprintList: [],
+      isVip: false,
+      statusBarHeight: 88,
+      storage: true,
+      banner: {
+        imgUrl: ''
+      }
+    }
+  },
+  onShow() {
+    this.isVip = this.$api.isVip()
+    //this.loadFootprint()
+    this.$store.state.storageId ? this.storage = true : this.storage = false
+    //如果用户已登录,获取购物车数量
+    if (this.$store.state.userInfo.accessToken) {
+      this.$api.request('get', 'cart/app/countCart', {
+        storageId: this.$store.state.storageId
+      }).then(res => {
+        if (res.data > 0) {
           uni.setTabBarBadge({
             index: 2,
-            text: cartNum + ''
+            text: res.data + ''
           })
+        }
+        this.$store.commit('addCart', res.data)
+        this.$api.request('get', 'coupon/app/getUserCoupons').then(res => {
+          this.couponListSize = res.data.length
         })
-      },
-      // 刷新推荐
-      refreshRecommend() {
-        this.currentPage++
-        this.getRecommendList()
-      },
-      // 获取推荐商品
-      getRecommendList() {
-        this.$api.request('get', 'product/app/recommend', {
-          page: this.currentPage,
-          size: this.pageSize,
-          storageId: this.$store.state.storageId
-        }).then(res => {
-          this.recommendList = res.rows || []
-        }).catch(err => {
-          console.log('获取推荐商品失败', err)
+        this.$api.request('get', 'user/app/getUser').then(res => {
+          this.nowMoney = res.data.nowMoney
+          this.integral = res.data.integral
         })
-      },
-			deleteFootprint(item) {
-				const that = this
-				uni.showModal({
-					title: '删除?',
-					content: '您确定要删除此足迹吗?',
-					success : (e) => {
-						if (e.confirm) {
-							that.$api.request('get', '/deleteFootprint', {
-								footprintId: item.id
-							}).then(res => {
-								that.loadFootprint()
-							})
-						}
-					}
-				})
-			},
+      }).catch(err => {
+        // this.$api.msg('请求失败,请稍后再试')
+      })
+    } else {
+      // 用户未登录时,清空数据
+      this.nowMoney = 0
+      this.integral = 0
+      this.couponListSize = 0
+    }
+    // 获取推荐商品
+    if (this.$store.state.storageId) {
+      this.getRecommendList()
+    }
+  },
+  onLoad() {
+    try {
+      const res = uni.getSystemInfoSync();
+      console.log(res.statusBarHeight);
+      this.statusBarHeight = res.statusBarHeight
+    } catch (e) {
+      // error
+    }
+    this.$api.request('get', 'carousel/app/getCarouselActive', {
+      adType: 8
+    }).then(res => {
+      this.banner = res.data[0]
+    })
+  },
+  // #ifndef MP
+  onNavigationBarButtonTap(e) {
+    const index = e.index;
+    if (index === 0) {
+      this.navTo('/pages/set/set');
+    } else if (index === 1) {
+      // #ifdef APP-PLUS
+      const pages = getCurrentPages();
+      const page = pages[pages.length - 1];
+      const currentWebview = page.$getAppWebview();
+      currentWebview.hideTitleNViewButtonRedDot({
+        index
+      });
+      // #endif
+      uni.navigateTo({
+        url: '/pages/notice/notice'
+      })
+    }
+  },
+  // #endif
+  computed: {
+    ...mapState(['hasLogin', 'userInfo'])
+  },
+  methods: {
+    // async loadFootprint() {
+    // 	const that = this
+    // 	that.$api.request('get', 'getAllFootprint').then(res => {
+    // 		that.footprintList = res.data
+    // 	})
+    // },
+    // 获取VIP等级名称
+    getVipName(level) {
+      const levels = {
+        0: '非会员',
+        1: '普通会员',
+        2: '青铜会员',
+        3: '白银会员',
+        4: '黄金会员',
+        5: '铂金会员',
+        6: '钻石会员'
+      };
+      return levels[level] || '未知等级';
+    },
+    
+    // 获取VIP等级对应颜色
+    getVipColor(level) {
+      const colors = {
+        0: '#999',
+        1: '#2a2fd6',  // 普通会员绿色
+        2: '#CD7F32',  // 青铜色
+        3: '#C0C0C0',  // 银色
+        4: '#FFD700',  // 金色
+        5: '#E5E4E2',  // 铂金色
+        6: '#B9F2FF'   // 钻石蓝
+      };
+      return colors[level] || '#2a2fd6';
+    },
+    //详情页
+    navToDetailPage(id) {
+      uni.navigateTo({
+        url: `/pages/product/detail?id=${id}`
+      })
+    },
+    addCart(item) {
+      const that = this
+      that.$api.request('get', 'cart/app/addCartItem', {
+        productId: item.id,
+        num: 1
+      }).then(res => {
+        that.$api.msg('添加购物车成功')
+        var cartNum = this.$store.state.cartNum + 1
+        that.$store.commit('addCart', cartNum)
+        uni.setTabBarBadge({
+          index: 2,
+          text: cartNum + ''
+        })
+      })
+    },
+    // 刷新推荐
+    refreshRecommend() {
+      this.currentPage++
+      this.getRecommendList()
+    },
+    // 获取推荐商品
+    getRecommendList() {
+      this.$api.request('get', 'product/app/recommend', {
+        page: this.currentPage,
+        size: this.pageSize,
+        storageId: this.$store.state.storageId
+      }).then(res => {
+        this.recommendList = res.rows || []
+      }).catch(err => {
+        console.log('获取推荐商品失败', err)
+      })
+    },
+    deleteFootprint(item) {
+      const that = this
+      uni.showModal({
+        title: '删除?',
+        content: '您确定要删除此足迹吗?',
+        success: (e) => {
+          if (e.confirm) {
+            that.$api.request('get', '/deleteFootprint', {
+              footprintId: item.id
+            }).then(res => {
+              that.loadFootprint()
+            })
+          }
+        }
+      })
+    },
+    
+    toLogin() {
+      if (!this.hasLogin) {
+        uni.navigateTo({
+          url: '/pages/public/login'
+        })
+      }
+    },
+    
+    logout() {
+      const that = this
+      uni.showModal({
+        title: '询问',
+        content: '您确定要退出吗?',
+        cancelText: '取消',
+        confirmText: '确定',
+        success: (e) => {
+          if (e.confirm) {
+            // 清空用户数据
+            that.nowMoney = 0
+            that.integral = 0
+            that.couponListSize = 0
+            // 退出登录
+            that.$store.commit('logout')
+            that.$api.logout()
+            // 清除本地存储
+            uni.removeStorageSync("addresses")
+            uni.removeStorageSync("userInfo")
+          }
+        }
+      })
+    },
+    
+    /**
+     * 统一跳转接口,拦截未登录路由
+     * navigator标签现在默认没有转场动画,所以用view
+     */
+    navTo(url) {
+      if (!this.hasLogin) {
+        url = '/pages/public/login';
+      }
+      uni.navigateTo({
+        url
+      })
+    },
+    
+    /**
+     *  会员卡下拉和回弹
+     *  1.关闭bounce避免ios端下拉冲突
+     *  2.由于touchmove事件的缺陷(以前做小程序就遇到,比如20跳到40,h5反而好很多),下拉的时候会有掉帧的感觉
+     *    transition设置0.1秒延迟,让css来过渡这段空窗期
+     *  3.回弹效果可修改曲线值来调整效果,推荐一个好用的bezier生成工具 http://cubic-bezier.com/
+     */
+    coverTouchstart(e) {
+      if (pageAtTop === false) {
+        return;
+      }
+      this.coverTransition = 'transform .1s linear';
+      startY = e.touches[0].clientY;
+    },
+    coverTouchmove(e) {
+      moveY = e.touches[0].clientY;
+      let moveDistance = moveY - startY;
+      if (moveDistance < 0) {
+        this.moving = false;
+        return;
+      }
+      this.moving = true;
+      if (moveDistance >= 80 && moveDistance < 100) {
+        moveDistance = 80;
+      }
+      
+      if (moveDistance > 0 && moveDistance <= 80) {
+        this.coverTransform = `translateY(${moveDistance}px)`;
+      }
+    },
+    coverTouchend() {
+      if (this.moving === false) {
+        return;
+      }
+      this.moving = false;
+      this.coverTransition = 'transform 0.3s cubic-bezier(.21,1.93,.53,.64)';
+      this.coverTransform = 'translateY(0px)';
+    },
+    //配送外区域选择区域
+    chooseLocation() {
+      uni.chooseLocation({
+        success: (res1) => {
+          console.log(res1)
+          this.district = res1.name
+          uni.showLoading({
+            title: "加载中..."
+          })
+          this.$api.request('get', 'storage/position/getRecentlyStorage', {
+            lng: res1.longitude,
+            lat: res1.latitude
+          }, failres => {
+            uni.hideLoading()
+            this.logining = false
+            this.$api.msg(failres.msg)
+            this.storage ? this.storage = false : this.storage = true
+          }).then(res => {
+            uni.hideLoading()
+            console.log(res)
+            this.$store.commit('setStorage', res.data.id)
+            this.newTop = []
+            this.cheapRecommend = []
+            this.salesTop = []
+            this.loadData(res.data.id)
+            if (!res.data.id) {
+              this.storage = false
+            } else {
+              this.storage ? this.storage = false : this.storage = true
+              // this.loadRecommand('refresh')
+            }
+          })
+        }
+      });
+    }
+  }
+}
+</script>
+<style lang='scss'>
+page {
+  background-color: #f1f1f1;;
+}
 
-			toLogin() {
-				if (!this.hasLogin) {
-					uni.navigateTo({
-						url: '/pages/public/login'
-					})
-				}
-			},
+.contact-btn {
+  border: none;
+  background-color: #FFFFFF;
+}
 
-			logout() {
-				const that = this
-				uni.showModal({
-					title: '询问',
-					content: '您确定要退出吗?',
-					cancelText: '取消',
-					confirmText: '确定',
-					success: (e) => {
-						if (e.confirm) {
-							that.$store.commit('logout')
-							that.$api.logout()
-						}
-					}
-				})
-			},
+.contact-btn::after {
+  border: none;
+}
 
-			/**
-			 * 统一跳转接口,拦截未登录路由
-			 * navigator标签现在默认没有转场动画,所以用view
-			 */
-			navTo(url){
-				if(!this.hasLogin){
-					url = '/pages/public/login';
-				}
-				uni.navigateTo({
-					url
-				})
-			},
+.bg-user-gradual-green {
+  background-repeat: no-repeat;
+  background-size: 100%;
+  color: #fff;
+  height: 260*2rpx;
+  width: 750rpx;
+}
 
-			/**
-			 *  会员卡下拉和回弹
-			 *  1.关闭bounce避免ios端下拉冲突
-			 *  2.由于touchmove事件的缺陷(以前做小程序就遇到,比如20跳到40,h5反而好很多),下拉的时候会有掉帧的感觉
-			 *    transition设置0.1秒延迟,让css来过渡这段空窗期
-			 *  3.回弹效果可修改曲线值来调整效果,推荐一个好用的bezier生成工具 http://cubic-bezier.com/
-			 */
-			coverTouchstart(e){
-				if(pageAtTop === false){
-					return;
-				}
-				this.coverTransition = 'transform .1s linear';
-				startY = e.touches[0].clientY;
-			},
-			coverTouchmove(e){
-				moveY = e.touches[0].clientY;
-				let moveDistance = moveY - startY;
-				if(moveDistance < 0){
-					this.moving = false;
-					return;
-				}
-				this.moving = true;
-				if(moveDistance >= 80 && moveDistance < 100){
-					moveDistance = 80;
-				}
+.shadow {
+  box-shadow: 0 1rpx 6rpx rgba(0, 0, 0, 0.1);
+}
 
-				if(moveDistance > 0 && moveDistance <= 80){
-					this.coverTransform = `translateY(${moveDistance}px)`;
-				}
-			},
-			coverTouchend(){
-				if(this.moving === false){
-					return;
-				}
-				this.moving = false;
-				this.coverTransition = 'transform 0.3s cubic-bezier(.21,1.93,.53,.64)';
-				this.coverTransform = 'translateY(0px)';
-			},
-			//配送外区域选择区域
-			chooseLocation(){
-				uni.chooseLocation({
-				    success: (res1)=> {
-						console.log(res1)
-						this.district = res1.name
-						uni.showLoading({
-							title:"加载中..."
-						})
-						this.$api.request('get','storage/position/getRecentlyStorage',{
-							lng:res1.longitude,
-							lat:res1.latitude
-						},failres => {
-							uni.hideLoading()
-								this.logining = false
-								this.$api.msg(failres.msg)
-								this.storage ? this.storage = false : this.storage = true
-						}).then(res=>{
-							uni.hideLoading()
-							console.log(res)
-							this.$store.commit('setStorage',res.data.id)
-							this.newTop = []
-							this.cheapRecommend = []
-							this.salesTop = []
-							this.loadData(res.data.id)
-							if(!res.data.id){
-								this.storage = false
-							}else{
-								this.storage ? this.storage = false : this.storage = true
-								// this.loadRecommand('refresh')
-							}
-						})
-				    }
-				});
-			}
-        }
-    }
-</script>
-<style lang='scss'>
-	page{
-		background-color: #f1f1f1;;
-	}
+%flex-center {
+  display: flex;
+  flex-direction: column;
+  justify-content: center;
+  align-items: center;
+}
+
+%section {
+  display: flex;
+  justify-content: space-around;
+  align-content: center;
+  background: #fff;
+  border-radius: 10upx;
+}
 
-	.contact-btn{
-		border: none;
-		background-color: #FFFFFF;
-	}
+.user-section {
+  height: 520upx;
+  padding: 100upx 30upx 0;
+  position: relative;
+  
+  .bg {
+    position: absolute;
+    left: 0;
+    top: 0;
+    width: 100%;
+    height: 100%;
+    filter: blur(1px);
+    opacity: .7;
+  }
+}
 
-	.contact-btn::after{
-		border: none;
-	}
+.user-info-box {
+  height: 180upx;
+  display: flex;
+  align-items: center;
+  position: relative;
+  z-index: 1;
+  
+  .portrait {
+    width: 130upx;
+    height: 130upx;
+    border: 5upx solid #fff;
+    border-radius: 50%;
+  }
+  
+  .username {
+    font-size: $font-lg + 6upx;
+    color: $font-color-dark;
+    margin-left: 20upx;
+  }
+}
 
-	.bg-user-gradual-green {
-	  background-repeat: no-repeat;
-	  background-size: 100%;
-	  color: #fff;
-	  height: 260*2rpx;
-	  width: 750rpx;
-	}
+.vip-card-box {
+  display: flex;
+  flex-direction: column;
+  color: #f7d680;
+  height: 240upx;
+  background: linear-gradient(left, rgba(0, 0, 0, .7), rgba(0, 0, 0, .8));
+  border-radius: 16upx 16upx 0 0;
+  overflow: hidden;
+  position: relative;
+  padding: 20upx 24upx;
+  
+  .card-bg {
+    position: absolute;
+    top: 20upx;
+    right: 0;
+    width: 380upx;
+    height: 260upx;
+  }
+  
+  .b-btn {
+    position: absolute;
+    right: 20upx;
+    top: 16upx;
+    width: 132upx;
+    height: 40upx;
+    text-align: center;
+    line-height: 40upx;
+    font-size: 22upx;
+    color: #36343c;
+    border-radius: 20px;
+    background: linear-gradient(left, #f9e6af, #ffd465);
+    z-index: 1;
+  }
+  
+  .tit {
+    font-size: $font-base+2upx;
+    color: #f7d680;
+    margin-bottom: 28upx;
+    
+    .yticon {
+      color: #f6e5a3;
+      margin-right: 16upx;
+    }
+  }
+  
+  .e-b {
+    font-size: $font-sm;
+    color: #d8cba9;
+    margin-top: 10upx;
+  }
+}
 
-	.shadow {
-	  box-shadow: 0 1rpx 6rpx rgba(0, 0, 0, 0.1);
-	}
+.cover-container {
+  background: $page-color-base;
+  margin-top: -150upx;
+  padding: 0 30upx;
+  position: relative;
+  background: #f5f5f5;
+  padding-bottom: 20upx;
+  
+  .arc {
+    position: absolute;
+    left: 0;
+    top: -34upx;
+    width: 100%;
+    height: 36upx;
+  }
+}
 
-	%flex-center {
-	 display:flex;
-	 flex-direction: column;
-	 justify-content: center;
-	 align-items: center;
-	}
-	%section {
-	  display:flex;
-	  justify-content: space-around;
-	  align-content: center;
-	  background: #fff;
-	  border-radius: 10upx;
-	}
+.tj-sction {
+  @extend %section;
+  
+  .tj-item {
+    @extend %flex-center;
+    flex-direction: column;
+    height: 140upx;
+    font-size: $font-sm;
+    color: #75787d;
+  }
+  
+  .num {
+    font-size: $font-lg;
+    color: $font-color-dark;
+    margin-bottom: 8upx;
+  }
+}
 
-	.user-section{
-		height: 520upx;
-		padding: 100upx 30upx 0;
-		position:relative;
-		.bg{
-			position:absolute;
-			left: 0;
-			top: 0;
-			width: 100%;
-			height: 100%;
-			filter: blur(1px);
-			opacity: .7;
-		}
-	}
-	.user-info-box{
-		height: 180upx;
-		display:flex;
-		align-items:center;
-		position:relative;
-		z-index: 1;
-		.portrait{
-			width: 130upx;
-			height: 130upx;
-			border:5upx solid #fff;
-			border-radius: 50%;
-		}
-		.username{
-			font-size: $font-lg + 6upx;
-			color: $font-color-dark;
-			margin-left: 20upx;
-		}
-	}
+.order-section {
+  @extend %section;
+  padding: 28upx 0;
+  margin-top: 20upx;
+  
+  .order-item {
+    @extend %flex-center;
+    width: 120upx;
+    height: 120upx;
+    border-radius: 10upx;
+    font-size: $font-sm;
+    color: $base-color;
+  }
+  
+  .yticon {
+    font-size: 48upx;
+    margin-bottom: 18upx;
+    color: $base-color;
+  }
+  
+  .icon-shouhoutuikuan {
+    font-size: 44upx;
+  }
+}
 
-	.vip-card-box{
-		display:flex;
-		flex-direction: column;
-		color: #f7d680;
-		height: 240upx;
-		background: linear-gradient(left, rgba(0,0,0,.7), rgba(0,0,0,.8));
-		border-radius: 16upx 16upx 0 0;
-		overflow: hidden;
-		position: relative;
-		padding: 20upx 24upx;
-		.card-bg{
-			position:absolute;
-			top: 20upx;
-			right: 0;
-			width: 380upx;
-			height: 260upx;
-		}
-		.b-btn{
-			position: absolute;
-			right: 20upx;
-			top: 16upx;
-			width: 132upx;
-			height: 40upx;
-			text-align: center;
-			line-height: 40upx;
-			font-size: 22upx;
-			color: #36343c;
-			border-radius: 20px;
-			background: linear-gradient(left, #f9e6af, #ffd465);
-			z-index: 1;
-		}
-		.tit{
-			font-size: $font-base+2upx;
-			color: #f7d680;
-			margin-bottom: 28upx;
-			.yticon{
-				color: #f6e5a3;
-				margin-right: 16upx;
-			}
-		}
-		.e-b{
-			font-size: $font-sm;
-			color: #d8cba9;
-			margin-top: 10upx;
-		}
-	}
-	.cover-container{
-		background: $page-color-base;
-		margin-top: -150upx;
-		padding: 0 30upx;
-		position:relative;
-		background: #f5f5f5;
-		padding-bottom: 20upx;
-		.arc{
-			position:absolute;
-			left: 0;
-			top: -34upx;
-			width: 100%;
-			height: 36upx;
-		}
-	}
-	.tj-sction{
-		@extend %section;
-		.tj-item{
-			@extend %flex-center;
-			flex-direction: column;
-			height: 140upx;
-			font-size: $font-sm;
-			color: #75787d;
-		}
-		.num{
-			font-size: $font-lg;
-			color: $font-color-dark;
-			margin-bottom: 8upx;
-		}
-	}
-	.order-section{
-		@extend %section;
-		padding: 28upx 0;
-		margin-top: 20upx;
-		.order-item{
-			@extend %flex-center;
-			width: 120upx;
-			height: 120upx;
-			border-radius: 10upx;
-			font-size: $font-sm;
-			color: $base-color;
-		}
-		.yticon{
-			font-size: 48upx;
-			margin-bottom: 18upx;
-			color: $base-color;
-		}
-		.icon-shouhoutuikuan{
-			font-size:44upx;
-		}
-	}
-	.history-section{
-		padding: 30upx 0 0;
-		margin-top: 20upx;
-		background: #fff;
-		border-radius:10upx;
-		.sec-header{
-			display:flex;
-			align-items: center;
-			font-size: $font-base;
-			color: $font-color-dark;
-			line-height: 40upx;
-			margin-left: 30upx;
-			.yticon{
-				font-size: 44upx;
-				color: #5eba8f;
-				margin-right: 16upx;
-				line-height: 40upx;
-			}
-		}
-		.h-list{
-			white-space: nowrap;
-			padding: 30upx 30upx 0;
-			image{
-				display:inline-block;
-				width: 160upx;
-				height: 160upx;
-				margin-right: 20upx;
-				border-radius: 10upx;
-			}
-		}
-	}
+.history-section {
+  padding: 30upx 0 0;
+  margin-top: 20upx;
+  background: #fff;
+  border-radius: 10upx;
+  
+  .sec-header {
+    display: flex;
+    align-items: center;
+    font-size: $font-base;
+    color: $font-color-dark;
+    line-height: 40upx;
+    margin-left: 30upx;
+    
+    .yticon {
+      font-size: 44upx;
+      color: #5eba8f;
+      margin-right: 16upx;
+      line-height: 40upx;
+    }
+  }
+  
+  .h-list {
+    white-space: nowrap;
+    padding: 30upx 30upx 0;
+    
+    image {
+      display: inline-block;
+      width: 160upx;
+      height: 160upx;
+      margin-right: 20upx;
+      border-radius: 10upx;
+    }
+  }
+}
 
 </style>

+ 12 - 1
kxmall-rider-ui/components/uni-load-more/uni-load-more.vue

@@ -28,7 +28,18 @@
 </template>
 
 <script>
-	const platform = uni.getSystemInfoSync().platform
+	// 兼容新版本微信小程序API
+	let platform = 'ios' // 默认值
+	try {
+		// 优先使用新API
+		if (uni.getDeviceInfo) {
+			platform = uni.getDeviceInfo().platform
+		} else if (uni.getSystemInfoSync) {
+			platform = uni.getSystemInfoSync().platform
+		}
+	} catch (e) {
+		console.warn('获取平台信息失败,使用默认值')
+	}
 
 	/**
 	 * LoadMore 加载更多

+ 83 - 0
kxmall-rider-ui/fix-compatibility.md

@@ -0,0 +1,83 @@
+# 兼容性问题修复说明
+
+## 问题描述
+项目在运行时出现以下兼容性问题:
+
+1. **wx.getSystemInfoSync 废弃警告** - 微信小程序新版本API弃用警告
+2. **uni-data-select mixinDatacom 未定义错误** - uniCloud组件缺少依赖
+
+## 修复方案
+
+### 1. 修复 uni-load-more 组件
+**文件位置**: `components/uni-load-more/uni-load-more.vue`
+
+**问题**: 使用了废弃的 `wx.getSystemInfoSync()` API
+
+**修复**: 
+```javascript
+// 修复前
+const platform = uni.getSystemInfoSync().platform
+
+// 修复后 - 兼容新版本微信小程序API
+let platform = 'ios' // 默认值
+try {
+    // 优先使用新API
+    if (uni.getDeviceInfo) {
+        platform = uni.getDeviceInfo().platform
+    } else if (uni.getSystemInfoSync) {
+        platform = uni.getSystemInfoSync().platform
+    }
+} catch (e) {
+    console.warn('获取平台信息失败,使用默认值')
+}
+```
+
+### 2. 修复 uni-data-select 组件
+**文件位置**: `uni_modules/uni-data-select/components/uni-data-select/uni-data-select.vue`
+
+**问题**: `uniCloud.mixinDatacom` 可能未定义
+
+**修复**:
+```javascript
+// 修复前
+mixins: [uniCloud.mixinDatacom || {}],
+
+// 修复后
+mixins: [uniCloud && uniCloud.mixinDatacom ? uniCloud.mixinDatacom : {}],
+```
+
+**数据安全检查**:
+```javascript
+// 模板中增加安全检查
+v-if="(mixinDatacomResData || localdata).length === 0"
+v-for="(item,index) in (mixinDatacomResData || localdata)"
+
+// created 钩子中增加初始化
+created() {
+    // 确保 mixinDatacomResData 初始化
+    if (!this.mixinDatacomResData) {
+        this.mixinDatacomResData = [];
+    }
+    // ... 其他逻辑
+}
+```
+
+## 修复效果
+
+✅ **解决微信小程序API废弃警告**
+✅ **修复 uniCloud 组件依赖问题**
+✅ **提高组件稳定性和兼容性**
+✅ **不影响现有功能**
+
+## 注意事项
+
+1. 这些修复主要针对组件库的兼容性问题
+2. 评价列表功能不受这些组件问题影响
+3. 建议定期更新 uni-app 和相关组件库到最新版本
+4. 如果项目使用了 uniCloud,建议正确配置 uniCloud 服务
+
+## 测试建议
+
+- 在微信小程序开发者工具中测试修复效果
+- 检查控制台是否还有相关错误信息
+- 验证组件功能是否正常工作

+ 1 - 1
kxmall-rider-ui/manifest.json

@@ -84,7 +84,7 @@
     "quickapp" : {},
     /* 小程序特有相关 */
     "mp-weixin" : {
-        "appid" : "wx8785fa77512b4f0a",
+        "appid" : "wxb9c68e78feee66b7",
         "setting" : {
             "urlCheck" : false
         },

+ 8 - 0
kxmall-rider-ui/pages.json

@@ -96,6 +96,14 @@
         "navigationBarTitleText": "我的",
         "navigationStyle": "custom"
       }
+    },
+    {
+      "path": "pages/review/review-list",
+      "style": {
+        "navigationBarTitleText": "评价列表",
+        "navigationBarBackgroundColor": "#FFFFFF",
+        "enablePullDownRefresh": true
+      }
     }
   ],
   "globalStyle": {

+ 511 - 0
kxmall-rider-ui/pages/review/review-list.vue

@@ -0,0 +1,511 @@
+<template>
+	<view class="container">
+		<!-- 头部统计卡片 -->
+		<view class="stats-card">
+			<view class="stats-item">
+				<text class="stats-value">{{totalReviews}}</text>
+				<text class="stats-label">总评价数</text>
+			</view>
+			<view class="stats-divider"></view>
+			<view class="stats-item">
+				<text class="stats-value">{{averageRating}}</text>
+				<text class="stats-label">平均评分</text>
+			</view>
+		</view>
+
+		<!-- 筛选栏 -->
+		<view class="filter-bar">
+			<view class="filter-item" 
+				  :class="{'active': currentFilter === 'all'}" 
+				  @click="changeFilter('all')">
+				全部
+			</view>
+			<view class="filter-item" 
+				  :class="{'active': currentFilter === 'good'}" 
+				  @click="changeFilter('good')">
+				好评
+			</view>
+			<view class="filter-item" 
+				  :class="{'active': currentFilter === 'medium'}" 
+				  @click="changeFilter('medium')">
+				中评
+			</view>
+			<view class="filter-item" 
+				  :class="{'active': currentFilter === 'bad'}" 
+				  @click="changeFilter('bad')">
+				差评
+			</view>
+		</view>
+
+		<!-- 评价列表 -->
+		<view class="review-list">
+			<view class="review-item" v-for="item in reviewList" :key="item.id">
+				<!-- 订单信息 -->
+				<view class="order-info">
+					<text class="order-number">订单号:{{item.orderId}}</text>
+					<text class="order-time">{{formatTime(item.createTime)}}</text>
+				</view>
+
+				<!-- 评价内容 -->
+				<view class="review-content">
+					<!-- 评分星级 -->
+					<view class="rating-section">
+						<view class="stars">
+							<view class="star" 
+								  v-for="i in 5" 
+								  :key="i"
+								  :class="{'filled': i <= item.score}">
+								★
+							</view>
+						</view>
+						<text class="rating-text">{{getRatingText(item.score)}}</text>
+					</view>
+
+					<!-- 评价文字 -->
+					<view class="review-text" v-if="item.content">
+						{{item.content}}
+					</view>
+
+					<!-- 评价图片 -->
+					<view class="review-images" v-if="item.images && item.images.length > 0">
+						<image class="review-image" 
+							   v-for="(img, index) in item.images" 
+							   :key="index"
+							   :src="img" 
+							   mode="aspectFill"
+							   @click="previewImage(img, item.images)">
+						</image>
+					</view>
+
+					<!-- 用户信息 -->
+					<view class="reviewer-info">
+						<image class="avatar" :src="item.userAvatar || '/static/login/logo.png'" mode="aspectFill"></image>
+						<view class="user-details">
+							<text class="username">{{hideUserName(item.userNickName)}}</text>
+							<text class="review-time">{{formatTime(item.createTime)}}</text>
+						</view>
+					</view>
+				</view>
+
+				<!-- 商家回复 -->
+				<view class="merchant-reply" v-if="item.reply">
+					<view class="reply-header">
+						<text class="reply-label">商家回复:</text>
+					</view>
+					<view class="reply-content">
+						{{item.reply}}
+					</view>
+					<view class="reply-time">
+						{{formatTime(item.replyTime)}}
+					</view>
+				</view>
+			</view>
+
+			<!-- 加载更多 -->
+			<view class="load-more" @click="loadMore" v-if="hasMore && !loading">
+				<text>加载更多</text>
+			</view>
+
+			<!-- 加载中 -->
+			<view class="loading" v-if="loading">
+				<text>加载中...</text>
+			</view>
+
+			<!-- 空状态 -->
+			<view class="empty-state" v-if="!loading && reviewList.length === 0">
+				<image class="empty-icon" src="/static/icons/empty-review.png" mode="aspectFit"></image>
+				<text class="empty-text">暂无评价数据</text>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	import {
+		mapState
+	} from 'vuex';
+
+	export default {
+		computed: {
+			...mapState(['token', 'userInfo'])
+		},
+		data() {
+			return {
+				reviewList: [],
+				currentFilter: 'all',
+				page: 1,
+				pageSize: 10,
+				total: 0,
+				totalReviews: 0,
+				averageRating: 0,
+				loading: false,
+				hasMore: true
+			};
+		},
+		onLoad() {
+			this.initData();
+		},
+		onPullDownRefresh() {
+			this.refreshData();
+		},
+		onReachBottom() {
+			this.loadMore();
+		},
+		methods: {
+			initData() {
+				this.getReviewStats();
+				this.getReviewList(true);
+			},
+
+			refreshData() {
+				this.page = 1;
+				this.hasMore = true;
+				this.getReviewStats();
+				this.getReviewList(true);
+				uni.stopPullDownRefresh();
+			},
+
+			changeFilter(filter) {
+				this.currentFilter = filter;
+				this.page = 1;
+				this.hasMore = true;
+				this.getReviewList(true);
+			},
+
+			getReviewStats() {
+				this.request("get", "rider/review/stats", this.token).then(res => {
+					if (res.code === 200) {
+						this.totalReviews = res.data.totalReviews || 0;
+						this.averageRating = (res.data.averageRating || 0).toFixed(1);
+					}
+				});
+			},
+
+			getReviewList(refresh = false) {
+				if (this.loading) return;
+				this.loading = true;
+
+				if (refresh) {
+					this.page = 1;
+				}
+
+				const params = {
+					pageNum: this.page,
+					pageSize: this.pageSize
+				};
+
+				// 添加筛选条件
+				if (this.currentFilter !== 'all') {
+					if (this.currentFilter === 'good') {
+						params.minRating = 4;
+					} else if (this.currentFilter === 'medium') {
+						params.minRating = 3;
+						params.maxRating = 3;
+					} else if (this.currentFilter === 'bad') {
+						params.maxRating = 2;
+					}
+				}
+
+				this.request("get", "rider/review/list", this.token, params).then(res => {
+					if (res.code === 200) {
+						const newData = res.rows || [];
+						this.reviewList = refresh ? newData : [...this.reviewList, ...newData];
+						this.total = res.total || 0;
+						this.hasMore = this.reviewList.length < this.total;
+					}
+				}).finally(() => {
+					this.loading = false;
+				});
+			},
+
+			loadMore() {
+				if (this.hasMore && !this.loading) {
+					this.page++;
+					this.getReviewList();
+				}
+			},
+
+			getRatingText(rating) {
+				if (rating >= 4) return '好评';
+				if (rating >= 3) return '中评';
+				return '差评';
+			},
+
+			hideUserName(name) {
+				if (!name) return '匿名用户';
+				if (name.length <= 2) return name;
+				return name.charAt(0) + '*'.repeat(name.length - 2) + name.charAt(name.length - 1);
+			},
+
+			formatTime(time) {
+				if (!time) return '';
+				const date = new Date(time);
+				const now = new Date();
+				const diff = now.getTime() - date.getTime();
+				const diffDays = Math.floor(diff / (1000 * 60 * 60 * 24));
+				
+				if (diffDays === 0) {
+					const diffHours = Math.floor(diff / (1000 * 60 * 60));
+					if (diffHours === 0) {
+						const diffMinutes = Math.floor(diff / (1000 * 60));
+						return diffMinutes + '分钟前';
+					}
+					return diffHours + '小时前';
+				} else if (diffDays === 1) {
+					return '昨天';
+				} else if (diffDays < 7) {
+					return diffDays + '天前';
+				} else {
+					return date.getFullYear() + '-' + 
+						   String(date.getMonth() + 1).padStart(2, '0') + '-' + 
+						   String(date.getDate()).padStart(2, '0');
+				}
+			},
+
+			previewImage(current, urls) {
+				uni.previewImage({
+					current: current,
+					urls: urls
+				});
+			}
+		}
+	};
+</script>
+
+<style lang="scss" scoped>
+	.container {
+		background-color: #f7f7f7;
+		min-height: 100vh;
+		padding-bottom: 40rpx;
+	}
+
+	/* 统计卡片 */
+	.stats-card {
+		display: flex;
+		background-color: #fff;
+		margin: 20rpx;
+		border-radius: 16rpx;
+		padding: 30rpx;
+		box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.05);
+
+		.stats-item {
+			flex: 1;
+			text-align: center;
+
+			.stats-value {
+				display: block;
+				font-size: 48rpx;
+				font-weight: bold;
+				color: #ff6b35;
+				margin-bottom: 10rpx;
+			}
+
+			.stats-label {
+				font-size: 26rpx;
+				color: #666;
+			}
+		}
+
+		.stats-divider {
+			width: 1rpx;
+			background-color: #f0f0f0;
+			margin: 0 30rpx;
+		}
+	}
+
+	/* 筛选栏 */
+	.filter-bar {
+		display: flex;
+		background-color: #fff;
+		margin: 0 20rpx 20rpx;
+		border-radius: 16rpx;
+		padding: 10rpx;
+		box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.05);
+
+		.filter-item {
+			flex: 1;
+			text-align: center;
+			padding: 20rpx 0;
+			font-size: 28rpx;
+			color: #666;
+			border-radius: 12rpx;
+			transition: all 0.3s;
+
+			&.active {
+				background-color: #437CE8;
+				color: #fff;
+			}
+		}
+	}
+
+	/* 评价列表 */
+	.review-list {
+		margin: 0 20rpx;
+
+		.review-item {
+			background-color: #fff;
+			border-radius: 16rpx;
+			margin-bottom: 20rpx;
+			overflow: hidden;
+			box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.05);
+
+			.order-info {
+				display: flex;
+				justify-content: space-between;
+				align-items: center;
+				padding: 20rpx 30rpx;
+				background-color: #f8f9fa;
+				border-bottom: 1rpx solid #f0f0f0;
+
+				.order-number {
+					font-size: 26rpx;
+					color: #333;
+					font-weight: 500;
+				}
+
+				.order-time {
+					font-size: 24rpx;
+					color: #999;
+				}
+			}
+
+			.review-content {
+				padding: 30rpx;
+
+				.rating-section {
+					display: flex;
+					align-items: center;
+					margin-bottom: 20rpx;
+
+					.stars {
+						display: flex;
+						margin-right: 15rpx;
+
+						.star {
+							font-size: 32rpx;
+							color: #ddd;
+							margin-right: 5rpx;
+
+							&.filled {
+								color: #ffa500;
+							}
+						}
+					}
+
+					.rating-text {
+						font-size: 26rpx;
+						color: #666;
+					}
+				}
+
+				.review-text {
+					font-size: 28rpx;
+					color: #333;
+					line-height: 1.6;
+					margin-bottom: 20rpx;
+				}
+
+				.review-images {
+					display: flex;
+					flex-wrap: wrap;
+					margin-bottom: 20rpx;
+
+					.review-image {
+						width: 160rpx;
+						height: 160rpx;
+						border-radius: 12rpx;
+						margin-right: 15rpx;
+						margin-bottom: 15rpx;
+					}
+				}
+
+				.reviewer-info {
+					display: flex;
+					align-items: center;
+
+					.avatar {
+						width: 60rpx;
+						height: 60rpx;
+						border-radius: 50%;
+						margin-right: 20rpx;
+					}
+
+					.user-details {
+						flex: 1;
+
+						.username {
+							display: block;
+							font-size: 26rpx;
+							color: #333;
+							margin-bottom: 5rpx;
+						}
+
+						.review-time {
+							font-size: 24rpx;
+							color: #999;
+						}
+					}
+				}
+			}
+
+			.merchant-reply {
+				background-color: #f8f9fa;
+				padding: 20rpx 30rpx;
+				border-top: 1rpx solid #f0f0f0;
+
+				.reply-header {
+					margin-bottom: 10rpx;
+
+					.reply-label {
+						font-size: 26rpx;
+						color: #437CE8;
+						font-weight: 500;
+					}
+				}
+
+				.reply-content {
+					font-size: 26rpx;
+					color: #333;
+					line-height: 1.6;
+					margin-bottom: 10rpx;
+				}
+
+				.reply-time {
+					font-size: 22rpx;
+					color: #999;
+					text-align: right;
+				}
+			}
+		}
+
+		.load-more {
+			text-align: center;
+			padding: 30rpx 0;
+			color: #437CE8;
+			font-size: 28rpx;
+		}
+
+		.loading {
+			text-align: center;
+			padding: 30rpx 0;
+			color: #999;
+			font-size: 28rpx;
+		}
+
+		.empty-state {
+			text-align: center;
+			padding: 100rpx 0;
+
+			.empty-icon {
+				width: 200rpx;
+				height: 200rpx;
+				margin-bottom: 30rpx;
+			}
+
+			.empty-text {
+				font-size: 28rpx;
+				color: #999;
+			}
+		}
+	}
+</style>

+ 11 - 4
kxmall-rider-ui/pages/user/user.vue

@@ -49,6 +49,10 @@
 				<image class="icon" src="@/static/icons/profile.png" mode="aspectFit"></image>
 				<text class="text">资料填写</text>
 			</view>
+			<view class="action-item" @click="navTo('review')">
+				<image class="icon" src="@/static/icons/review.png" mode="aspectFit"></image>
+				<text class="text">评价列表</text>
+			</view>
 		</view>
 
 		<!-- 交易记录列表 -->
@@ -142,7 +146,8 @@
 					income: '../income/income',
 					withdraw: '../wallet/withdraw',
 					transaction: '../wallet/transaction-list',
-					profile: '../profile/edit' // 新增
+					profile: '../profile/edit',
+					review: '../review/review-list'
 				};
 				uni.navigateTo({
 					url: pages[url] || url
@@ -352,11 +357,12 @@
 
 	/* 快捷功能区 */
 	.quick-actions {
-		display: flex;
-		justify-content: space-around;
+		display: grid;
+		grid-template-columns: 1fr 1fr;
+		gap: 30rpx;
 		background-color: #fff;
 		border-radius: 16rpx;
-		padding: 30rpx 0;
+		padding: 30rpx;
 		margin-bottom: 20rpx;
 		box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.05);
 
@@ -364,6 +370,7 @@
 			display: flex;
 			flex-direction: column;
 			align-items: center;
+			padding: 20rpx 0;
 
 			.icon {
 				width: 60rpx;

BIN
kxmall-rider-ui/static/icons/empty-review.png


BIN
kxmall-rider-ui/static/icons/review.png


+ 11 - 6
kxmall-rider-ui/uni_modules/uni-data-select/components/uni-data-select/uni-data-select.vue

@@ -17,11 +17,11 @@
 				<view class="uni-select__selector" v-if="showSelector">
 					<view class="uni-popper__arrow"></view>
 					<scroll-view scroll-y="true" class="uni-select__selector-scroll">
-						<view class="uni-select__selector-empty" v-if="mixinDatacomResData.length === 0">
-							<text>{{emptyTips}}</text>
-						</view>
-						<view v-else class="uni-select__selector-item" v-for="(item,index) in mixinDatacomResData" :key="index"
-							@click="change(item)">
+											<view class="uni-select__selector-empty" v-if="(mixinDatacomResData || localdata).length === 0">
+						<text>{{emptyTips}}</text>
+					</view>
+					<view v-else class="uni-select__selector-item" v-for="(item,index) in (mixinDatacomResData || localdata)" :key="index"
+						@click="change(item)">
 							<text :class="{'uni-select__selector__disabled': item.disable}">{{formatItemName(item)}}</text>
 						</view>
 					</scroll-view>
@@ -48,7 +48,7 @@
 
 	export default {
 		name: "uni-data-select",
-		mixins: [uniCloud.mixinDatacom || {}],
+		mixins: [uniCloud && uniCloud.mixinDatacom ? uniCloud.mixinDatacom : {}],
 		props: {
 			localdata: {
 				type: Array,
@@ -105,6 +105,11 @@
 			};
 		},
 		created() {
+			// 确保 mixinDatacomResData 初始化
+			if (!this.mixinDatacomResData) {
+				this.mixinDatacomResData = [];
+			}
+			
 			this.debounceGet = this.debounce(() => {
 				this.query();
 			}, 300);

Some files were not shown because too many files changed in this diff