Jelajahi Sumber

1.继续完善商城的国际化,2.修复英文版的时候,我的页面英文挤在一块的问题

npzzwq99 2 minggu lalu
induk
melakukan
4fe0a52130

+ 46 - 5
locale/en.json

@@ -1270,9 +1270,50 @@
   "mine.myCoupon": "MyCoupons",
   "mine.followShop": "Followed Shops",
   "mine.footprint": "Footprint",
-  "order.pendingPayment": "PendingPayment",
-  "order.pendingShipment": "PendingShipment",
-  "order.pendingReceipt": "PendingReceipt",
-  "order.pendingReview": "PendingReview",
-  "order.refundAfterSales": "RefundAfterSales"
+  "order.pendingPayment": "ToPay",
+  "order.pendingShipment": "ToShip",
+  "order.pendingReceipt": "ToReceive",
+  "order.pendingReview": "ToReview",
+  "order.refundAfterSales": "Refund",
+  "address.empty": "No shipping address yet",
+  "address.addNew": "+ Add New Address",
+  "address.confirmDelete": "Are you sure you want to delete this address?",
+  "address.confirmChange": "Are you sure you want to change to this address? (Each order can only be changed once)",
+  "common.pleaseLogin": "Please login first",
+  "common.tip": "Tip",
+  "common.updating": "Updating...",
+  "common.updateSuccess": "Update successful",
+  "common.updateFailed": "Update failed",
+  "addressManage.contact": "Contact",
+  "addressManage.namePlaceholder": "Recipient Name",
+  "addressManage.mobile": "Mobile Number",
+  "addressManage.mobilePlaceholder": "Recipient Mobile Number",
+  "addressManage.region": "Region",
+  "addressManage.regionPlaceholder": "Select Province/City/District",
+  "addressManage.detailAddress": "Detail Address",
+  "addressManage.detailAddressPlaceholder": "Street, building number, etc.",
+  "addressManage.setDefault": "Set as Default",
+  "addressManage.editTitle": "Edit Address",
+  "addressManage.addTitle": "Add Address",
+  "addressManage.nameRequired": "Please enter recipient name",
+  "addressManage.mobileRequired": "Please enter mobile number",
+  "addressManage.regionRequired": "Please select region",
+  "addressManage.addressRequired": "Please enter detail address",
+  "addressManage.saveSuccess": "Address {0} successfully",
+  "addressManage.operationFailed": "Operation failed",
+  "coupon.universal": "Universal",
+  "coupon.start": "Starts {0}",
+  "coupon.end": "Ends {0}",
+  "coupon.permanent": "Permanent",
+  "coupon.validDays": "Valid for {0} days after receiving",
+  "coupon.receiveFailed": "Failed to receive",
+  "coupon.noDetails": "No coupon details",
+  "coupon.validPeriod": "Valid Period",
+  "coupon.noCoupons": "No coupons",
+  "coupon.remaining": "{0} remaining",
+  "coupon.limitClaim": "Limit {0} per person",
+  "coupon.useNow": "Use Now",
+  "coupon.reductionCoupon": "Reduction",
+  "coupon.discountCoupon": "Discount",
+  "coupon.shippingCoupon": "Shipping"
 }

+ 46 - 1
locale/zh-Hans.json

@@ -1247,5 +1247,50 @@
   "order.pendingShipment": "待发货",
   "order.pendingReceipt": "待收货",
   "order.pendingReview": "待评价",
-  "order.refundAfterSales": "退款/售后"
+  "order.refundAfterSales": "退款/售后",
+  "address.empty": "暂无收货地址",
+  "address.addNew": "+ 新增收货地址",
+  "address.confirmDelete": "确定删除该地址吗?",
+  "address.confirmChange": "确定修改为该地址吗?(每个订单仅可修改一次)",
+  "common.pleaseLogin": "请先登录",
+  "common.tip": "提示",
+  "common.updating": "修改中...",
+  "common.updateSuccess": "修改成功",
+  "common.updateFailed": "修改失败",
+  "addressManage.contact": "联系人",
+  "addressManage.namePlaceholder": "收货人姓名",
+  "addressManage.mobile": "手机号码",
+  "addressManage.mobilePlaceholder": "收货人手机号码",
+  "addressManage.region": "所在地区",
+  "addressManage.regionPlaceholder": "请选择省/市/区",
+  "addressManage.detailAddress": "详细地址",
+  "addressManage.detailAddressPlaceholder": "街道、门牌号等详细地址",
+  "addressManage.setDefault": "设为默认",
+  "addressManage.editTitle": "编辑地址",
+  "addressManage.addTitle": "新增地址",
+  "addressManage.nameRequired": "请填写收货人姓名",
+  "addressManage.mobileRequired": "请填写手机号码",
+  "addressManage.regionRequired": "请选择所在地区",
+  "addressManage.addressRequired": "请填写详细地址",
+  "addressManage.saveSuccess": "地址{0}成功",
+  "addressManage.operationFailed": "操作失败",
+  "coupon.universal": "全场通用",
+  "coupon.start": "{0} 开始",
+  "coupon.end": "{0} 结束",
+  "coupon.permanent": "永久有效",
+  "coupon.validDays": "领取后{0}天内有效",
+  "coupon.receiveFailed": "领取失败",
+  "coupon.noDetails": "暂无优惠券详情",
+  "coupon.validPeriod": "有效期",
+  "coupon.noCoupons": "暂无优惠券",
+  "coupon.remaining": "剩余 {0} 张",
+  "coupon.limitClaim": "限领 {0} 张",
+  "coupon.useNow": "去使用",
+  "coupon.reductionCoupon": "满减券",
+  "coupon.discountCoupon": "折扣券",
+  "coupon.shippingCoupon": "包邮券",
+  "coupon.validUntil": "有效期至 {0}",
+  "coupon.unused": "未使用",
+  "coupon.used": "已使用",
+  "coupon.expired": "已过期"
 }

+ 42 - 1
locale/zh-Hant.json

@@ -1300,5 +1300,46 @@
   "order.pendingShipment": "待發貨",
   "order.pendingReceipt": "待收貨",
   "order.pendingReview": "待評價",
-  "order.refundAfterSales": "退款/售後"
+  "order.refundAfterSales": "退款/售後",
+  "address.empty": "暫無收貨地址",
+  "address.addNew": "+ 新增收貨地址",
+  "address.confirmDelete": "確定刪除該地址嗎?",
+  "address.confirmChange": "確定修改為該地址嗎?(每個訂單僅可修改一次)",
+  "common.pleaseLogin": "請先登錄",
+  "common.tip": "提示",
+  "common.updating": "修改中...",
+  "common.updateSuccess": "修改成功",
+  "common.updateFailed": "修改失敗",
+  "addressManage.contact": "聯絡人",
+  "addressManage.namePlaceholder": "收貨人姓名",
+  "addressManage.mobile": "手機號碼",
+  "addressManage.mobilePlaceholder": "收貨人手機號碼",
+  "addressManage.region": "所在地區",
+  "addressManage.regionPlaceholder": "請選擇省/市/區",
+  "addressManage.detailAddress": "詳細地址",
+  "addressManage.detailAddressPlaceholder": "街道、樓牌號等詳細地址",
+  "addressManage.setDefault": "設為默認",
+  "addressManage.editTitle": "編輯地址",
+  "addressManage.addTitle": "新增地址",
+  "addressManage.nameRequired": "請填寫收貨人姓名",
+  "addressManage.mobileRequired": "請填寫手機號碼",
+  "addressManage.regionRequired": "請選擇所在地區",
+  "addressManage.addressRequired": "請填寫詳細地址",
+  "addressManage.saveSuccess": "地址{0}成功",
+  "addressManage.operationFailed": "操作失敗",
+  "coupon.universal": "全場通用",
+  "coupon.start": "{0} 開始",
+  "coupon.end": "{0} 結束",
+  "coupon.permanent": "永久有效",
+  "coupon.validDays": "領取後{0}天內有效",
+  "coupon.receiveFailed": "領取失敗",
+  "coupon.noDetails": "暫無優惠券詳情",
+  "coupon.validPeriod": "有效期",
+  "coupon.noCoupons": "暫無優惠券",
+  "coupon.remaining": "剩餘 {0} 張",
+  "coupon.limitClaim": "限領 {0} 張",
+  "coupon.useNow": "去使用",
+  "coupon.reductionCoupon": "滿減券",
+  "coupon.discountCoupon": "折扣券",
+  "coupon.shippingCoupon": "包郵券"
 }

+ 450 - 0
pages/travel/hotel/hotel-list.vue

@@ -0,0 +1,450 @@
+<template>
+  <view class="hotel-list-page">
+    <!-- ========== 1. 顶部状态栏占位 ========== -->
+    <!-- 自定义导航栏,需要预留状态栏位置(适配刘海屏) -->
+    <view class="status-bar"></view>
+
+    <!-- ========== 2. 导航栏 ========== -->
+    <view class="nav-bar">
+      <!-- 返回按钮 -->
+      <view class="nav-btn" @click="goBack">
+        <text class="nav-icon">‹</text>
+      </view>
+      <!-- 中间标题 -->
+      <text class="nav-title"></text>
+      <!-- 右侧订单按钮 -->
+      <view class="nav-btn" @click="toOrder">
+        <text class="order-icon">📋</text>
+        <text class="order-text">订单</text>
+      </view>
+    </view>
+
+    <!-- ========== 3. 搜索框 ========== -->
+    <view class="search-container">
+      <view class="search-box">
+        <!-- 搜索图标 -->
+        <text class="search-icon"></text>
+        <!-- 搜索输入框 -->
+        <input class="search-input" type="text" placeholder="搜索.." placeholder-class="placeholder" />
+        <!-- 右侧筛选按钮 -->
+        <view class="filter-btn">
+          <text class="filter-icon">⚙</text>
+        </view>
+      </view>
+    </view>
+
+    <!-- ========== 4. 分类筛选标签 ========== -->
+    <view class="filter-tabs">
+      <!-- 所有 - 默认激活(蓝色背景) -->
+      <view class="filter-tab active" @click="switchFilter('所有')">
+        <text>所有</text>
+      </view>
+      <!-- 别墅 -->
+      <view class="filter-tab" @click="switchFilter('别墅')">
+        <text class="tab-icon">🏠</text>
+        <text>别墅</text>
+      </view>
+      <!-- 酒店 -->
+      <view class="filter-tab" @click="switchFilter('酒店')">
+        <text class="tab-icon">🏨</text>
+        <text>酒店</text>
+      </view>
+      <!-- 民宿 -->
+      <view class="filter-tab" @click="switchFilter('民宿')">
+        <text class="tab-icon">🏢</text>
+        <text>民宿</text>
+      </view>
+    </view>
+
+    <!-- ========== 5. 酒店列表 ========== -->
+    <scroll-view class="hotel-scroll" scroll-y>
+      <view class="hotel-list">
+        <!-- 酒店卡片,使用v-for循环渲染 -->
+        <view class="hotel-card" v-for="(hotel, index) in hotelList" :key="hotel.id" @click="goToHotelDetail(hotel)">
+          <!-- 酒店图片区域(全宽) -->
+          <view class="hotel-image-wrapper">
+            <!-- 图片占位(后端接口就绪后替换为真实图片) -->
+            <image class="hotel-image" :src="hotel.img" mode="aspectFill"></image>
+            
+            <!-- 评分徽章(左上角) -->
+            <view class="rating-badge">
+              <text class="rating-star">⭐</text>
+              <text class="rating-score">{{ hotel.rating }}</text>
+            </view>
+            
+            <!-- 收藏按钮(右上角) -->
+            <view class="collect-btn" @click.stop="toggleCollect(hotel)">
+              <text class="heart-icon">{{ hotel.collect ? '❤️' : '🤍' }}</text>
+            </view>
+          </view>
+
+          <!-- 酒店信息区域(图片下方) -->
+          <view class="hotel-info">
+            <!-- 第一行:酒店名称 + 价格 -->
+            <view class="info-row">
+              <text class="hotel-name">{{ hotel.name }}</text>
+              <view class="price-group">
+                <text class="price-symbol">¥</text>
+                <text class="price-number">{{ hotel.price }}</text>
+              </view>
+            </view>
+
+            <!-- 第二行:位置 -->
+            <text class="hotel-location">{{ hotel.location }}</text>
+
+            <!-- 第三行:每晚标识(右对齐) -->
+            <text class="price-per-night">每晚</text>
+
+            <!-- 第四行:房间设施信息 -->
+            <view class="hotel-amenities">
+              <text class="amenity-icon">🛏</text>
+              <text class="amenity-item">{{ hotel.beds }}</text>
+              <text class="amenity-divider">·</text>
+              <text class="amenity-icon">🛁</text>
+              <text class="amenity-item">{{ hotel.bathrooms }}</text>
+            </view>
+          </view>
+        </view>
+      </view>
+    </scroll-view>
+  </view>
+</template>
+
+<script>
+export default {
+  name: 'HotelList',
+  data() {
+    return {
+      // 当前选中的分类标签(默认"所有")
+      currentFilter: '所有',
+      // 酒店列表数据(实际项目中从接口获取)
+      hotelList: [
+        {
+          id: 1,
+          name: '蓝宝石海湾酒店',
+          location: '佛罗里达州基韦斯特',
+          rating: 4.9,
+          price: 290,
+          beds: '3张床',
+          bathrooms: '3浴室',
+          img: '', // 后端接口就绪后替换为真实图片URL
+          collect: true // 是否已收藏
+        },
+        {
+          id: 2,
+          name: '微风山酒店',
+          location: '加州棕榈泉',
+          rating: 4.9,
+          price: 180,
+          beds: '两张床',
+          bathrooms: '3浴室',
+          img: '',
+          collect: false
+        }
+      ]
+    }
+  },
+  methods: {
+    // 切换分类筛选
+    switchFilter(filter) {
+      this.currentFilter = filter
+      console.log('切换到分类:', filter)
+    },
+    // 点击酒店卡片,跳转到详情页
+    goToHotelDetail(hotel) {
+      console.log('跳转酒店详情:', hotel.name)
+    },
+    // 切换收藏状态
+    toggleCollect(hotel) {
+      hotel.collect = !hotel.collect
+    },
+    // 返回上一页
+    goBack() {
+      uni.navigateBack()
+    },
+    // 跳转订单页面
+    toOrder() {
+      uni.navigateTo({ url: '/pages/order/order' })
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+// 全局样式
+page {
+  background-color: #f5f7fa; // 页面背景色(浅灰蓝)
+  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
+}
+
+// 页面容器
+.hotel-list-page {
+  min-height: 100vh;
+}
+
+/* ========== 1. 状态栏 ========== */
+.status-bar {
+  height: 88rpx; // 状态栏高度(适配刘海屏)
+  background-color: #f5f7fa;
+}
+
+/* ========== 2. 导航栏 ========== */
+.nav-bar {
+  display: flex;
+  justify-content: space-between; // 左右两端对齐
+  align-items: center; // 垂直居中
+  padding: 20rpx 32rpx;
+  background-color: #f5f7fa;
+
+  // 导航按钮(返回/订单)
+  .nav-btn {
+    width: 72rpx;
+    height: 72rpx;
+    background: #fff;
+    border-radius: 16rpx; // 白色圆角按钮
+    display: flex;
+    align-items: center;
+    justify-content: center;
+
+    .nav-icon {
+      font-size: 40rpx;
+      color: #333;
+    }
+
+    .order-icon {
+      font-size: 28rpx;
+    }
+
+    .order-text {
+      font-size: 20rpx;
+      color: #333;
+    }
+  }
+}
+
+/* ========== 3. 搜索框 ========== */
+.search-container {
+  padding: 16rpx 32rpx 24rpx;
+
+  .search-box {
+    display: flex;
+    align-items: center;
+    padding: 20rpx 24rpx;
+    background-color: #fff; // 白色背景
+    border-radius: 40rpx; // 胶囊形状
+    box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.06); // 轻微阴影
+
+    // 搜索图标
+    .search-icon {
+      font-size: 32rpx;
+      color: #999;
+      margin-right: 12rpx;
+    }
+
+    // 输入框
+    .search-input {
+      flex: 1;
+      font-size: 28rpx;
+      color: #333;
+    }
+
+    // 占位文本样式
+    .placeholder {
+      color: #bbb;
+    }
+
+    // 右侧筛选按钮
+    .filter-btn {
+      width: 48rpx;
+      height: 48rpx;
+      display: flex;
+      align-items: center;
+      justify-content: center;
+      border-left: 1rpx solid #eee; // 左侧分割线
+      margin-left: 12rpx;
+      padding-left: 12rpx;
+
+      .filter-icon {
+        font-size: 32rpx;
+        color: #666;
+      }
+    }
+  }
+}
+
+/* ========== 4. 分类筛选标签 ========== */
+.filter-tabs {
+  display: flex;
+  padding: 0 32rpx 24rpx;
+  gap: 16rpx; // 标签间距
+
+  .filter-tab {
+    padding: 16rpx 32rpx;
+    border-radius: 12rpx;
+    background-color: #fff; // 默认白色背景
+    font-size: 28rpx;
+    color: #666;
+    display: flex;
+    align-items: center;
+    gap: 8rpx;
+
+    .tab-icon {
+      font-size: 28rpx;
+    }
+
+    // 激活状态(蓝色背景)
+    &.active {
+      background-color: #0066ff; // 蓝色背景
+      color: #fff; // 白色文字
+      font-weight: 600;
+    }
+  }
+}
+
+/* ========== 5. 酒店列表滚动区域 ========== */
+.hotel-scroll {
+  padding: 0 32rpx;
+  max-height: calc(100vh - 300rpx); // 动态计算最大高度
+}
+
+.hotel-list {
+  display: flex;
+  flex-direction: column;
+  gap: 32rpx; // 卡片间距
+  padding-bottom: 40rpx;
+}
+
+/* 酒店卡片 */
+.hotel-card {
+  background-color: #fff;
+  border-radius: 20rpx; // 大圆角
+  overflow: hidden;
+  box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.08);
+
+  // 图片区域(全宽)
+  .hotel-image-wrapper {
+    width: 100%;
+    height: 400rpx; // 图片高度
+    position: relative; // 相对定位,用于徽章定位
+
+    .hotel-image {
+      width: 100%;
+      height: 100%;
+      background-color: #e8e8e8; // 占位背景色
+    }
+
+    // 评分徽章(左上角)
+    .rating-badge {
+      position: absolute;
+      top: 20rpx;
+      left: 20rpx;
+      background-color: rgba(0, 0, 0, 0.6); // 半透明黑色
+      padding: 8rpx 16rpx;
+      border-radius: 20rpx;
+      display: flex;
+      align-items: center;
+      gap: 6rpx;
+
+      .rating-star {
+        font-size: 24rpx;
+      }
+
+      .rating-score {
+        font-size: 26rpx;
+        color: #fff;
+        font-weight: 600;
+      }
+    }
+
+    // 收藏按钮(右上角)
+    .collect-btn {
+      position: absolute;
+      top: 20rpx;
+      right: 20rpx;
+      width: 64rpx;
+      height: 64rpx;
+      background-color: rgba(255, 255, 255, 0.8);
+      border-radius: 50%;
+      display: flex;
+      align-items: center;
+      justify-content: center;
+
+      .heart-icon {
+        font-size: 32rpx;
+      }
+    }
+  }
+
+  // 信息区域(图片下方)
+  .hotel-info {
+    padding: 24rpx;
+
+    // 第一行:名称 + 价格
+    .info-row {
+      display: flex;
+      justify-content: space-between;
+      align-items: flex-start;
+      margin-bottom: 12rpx;
+
+      .hotel-name {
+        font-size: 34rpx;
+        font-weight: bold;
+        color: #222;
+        flex: 1;
+      }
+
+      // 价格组
+      .price-group {
+        display: flex;
+        align-items: baseline;
+        flex-shrink: 0;
+
+        .price-symbol {
+          font-size: 28rpx;
+          color: #0066ff; // 蓝色
+          font-weight: 600;
+        }
+
+        .price-number {
+          font-size: 40rpx;
+          color: #0066ff; // 蓝色
+          font-weight: bold;
+        }
+      }
+    }
+
+    // 位置信息
+    .hotel-location {
+      font-size: 26rpx;
+      color: #999;
+      margin-bottom: 16rpx;
+    }
+
+    // 每晚标识(右对齐)
+    .price-per-night {
+      font-size: 24rpx;
+      color: #999;
+      text-align: right;
+      margin-bottom: 16rpx;
+    }
+
+    // 房间设施信息
+    .hotel-amenities {
+      display: flex;
+      align-items: center;
+      font-size: 26rpx;
+      color: #666;
+
+      .amenity-icon {
+        font-size: 28rpx;
+        margin-right: 6rpx;
+      }
+
+      .amenity-divider {
+        margin: 0 12rpx;
+        color: #ccc;
+      }
+    }
+  }
+}
+</style>

+ 457 - 0
pages/travel/hotel/hotel-search.vue

@@ -0,0 +1,457 @@
+<template>
+  <view class="hotel-search">
+    <!-- ========== 1. 顶部状态栏占位 ========== -->
+    <!-- 因为使用了自定义导航栏,需要预留状态栏位置(适配刘海屏等) -->
+    <view class="status-bar"></view>
+
+    <!-- ========== 2. 导航栏 ========== -->
+    <view class="nav-bar">
+      <!-- 返回按钮 -->
+      <view class="nav-btn" @click="goBack">
+        <text class="wlIcon wlIcon-fanhui1"></text>
+      </view>
+      <!-- 中间标题 -->
+      <text class="nav-title">搜索</text>
+      <!-- 右侧订单按钮 -->
+      <view class="nav-btn" @click="toOrder">
+        <!-- <text class="order-icon">📋</text> -->
+        <text class="order-text">订单</text>
+      </view>
+    </view>
+
+    <!-- ========== 3. 搜索框 ========== -->
+    <view class="search-container">
+      <view class="search-box">
+        <!-- 搜索图标 -->
+        <text class="search-icon">🔍</text>
+        <!-- 输入框,placeholder-class 自定义占位文本样式 -->
+        <input class="search-input" type="text" placeholder="搜索.." placeholder-class="placeholder" />
+        <!-- 右侧筛选按钮 -->
+        <view class="filter-btn">
+          <text class="filter-icon">⚙</text>
+        </view>
+      </view>
+    </view>
+
+    <!-- ========== 4. 最近搜索区域 ========== -->
+    <view class="section">
+      <!-- 区域头部:标题 + 右侧操作按钮 -->
+      <view class="section-header">
+        <text class="section-title">最近的搜索</text>
+        <text class="section-action" @click="clearAllSearches">全部清除</text>
+      </view>
+
+      <!-- 搜索历史标签列表 -->
+      <view class="search-tags">
+        <!-- 单个搜索标签,使用v-for循环渲染 -->
+        <view class="tag" v-for="(item, index) in recentSearches" :key="item.id" @click="onTagClick(item)">
+          <!-- 时钟图标 -->
+          <text class="tag-icon"></text>
+          <!-- 标签内容:酒店名称 + 地址 -->
+          <view class="tag-content">
+            <text class="tag-text">{{ item.name }}</text>
+            <text class="tag-location">{{ item.location }}</text>
+          </view>
+        </view>
+      </view>
+    </view>
+
+    <!-- ========== 5. 最近查看区域 ========== -->
+    <view class="section">
+      <!-- 区域头部 -->
+      <view class="section-header">
+        <text class="section-title">最近查看</text>
+        <text class="section-action" @click="viewAllHotels">查看全部</text>
+      </view>
+
+      <!-- 酒店列表 -->
+      <scroll-view class="hotel-scroll" scroll-y>
+        <view class="hotel-list">
+          <!-- 酒店卡片,使用v-for循环渲染 -->
+          <view class="hotel-item" v-for="(hotel, index) in recentHotels" :key="hotel.id"
+            @click="goToHotelDetail(hotel)">
+            <!-- 左侧:酒店图片 -->
+            <image class="hotel-image" :src="hotel.img" mode="aspectFill"></image>
+            <!-- 右侧:酒店信息 -->
+            <view class="hotel-info">
+              <!-- 第一行:酒店名称 + 评分 -->
+              <view class="hotel-top">
+                <text class="hotel-name">{{ hotel.name }}</text>
+                <view class="rating">
+                  <text class="rating-star">⭐</text>
+                  <text class="rating-score">{{ hotel.rating }}</text>
+                </view>
+              </view>
+              <!-- 第二行:位置 -->
+              <view class="hotel-location">
+                <text class="loc-icon"></text>
+                <text class="loc-text">{{ hotel.location }}</text>
+              </view>
+              <!-- 第三行:价格 -->
+              <text class="hotel-price">{{ hotel.price }}元/晚</text>
+            </view>
+          </view>
+        </view>
+      </scroll-view>
+    </view>
+  </view>
+</template>
+
+<script>
+export default {
+  name: 'HotelSearch',
+  data() {
+    return {
+      // 最近搜索列表
+      recentSearches: [
+        {
+          id: 1,
+          name: '金沙度假村',
+          location: '佛罗里达州克利尔沃特'
+        },
+        {
+          id: 2,
+          name: '水晶峰旅馆',
+          location: '科罗拉多州阿斯彭'
+        },
+        {
+          id: 3,
+          name: '珊瑚湾度假村',
+          location: '佛罗里达州迈阿密海滩'
+        }
+      ],
+      // 最近查看的酒店列表
+      recentHotels: [
+        {
+          id: 1,
+          name: '神秘的棕榈',
+          location: '加州棕榈泉',
+          rating: 4.0,
+          price: 230,
+          img: '' // 后端接口就绪后替换为真实图片URL
+        },
+        {
+          id: 2,
+          name: '蓝宝石海湾酒店',
+          location: '佛罗里达州基韦斯特',
+          rating: 3.8,
+          price: 290,
+          img: ''
+        },
+        {
+          id: 3,
+          name: '极乐套房',
+          location: '加利福尼亚州圣地亚哥',
+          rating: 3.8,
+          price: 320,
+          img: ''
+        }
+      ]
+    }
+  },
+  methods: {
+    // 返回上一页
+    goBack() {
+      uni.navigateBack()
+    },
+    // 跳转订单页面
+    toOrder() {
+      uni.navigateTo({ url: '/pages/order/order' })
+    },
+    // 清除所有搜索历史
+    clearAllSearches() {
+      uni.showToast({
+        title: '已清除所有搜索记录',
+        icon: 'success'
+      })
+    },
+    // 查看全部酒店
+    viewAllHotels() {
+      uni.navigateTo({ url: '/pages/travel/hotel/hotel-list' })
+    },
+    // 点击搜索标签
+    onTagClick(item) {
+      console.log('点击搜索:', item.name)
+    },
+    // 点击酒店卡片,跳转详情
+    goToHotelDetail(hotel) {
+      console.log('跳转酒店详情:', hotel.name)
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+// 全局样式
+page {
+  background-color: #f5f7fa; // 页面背景色(浅灰蓝)
+  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
+}
+
+// 页面容器
+.hotel-search {
+  min-height: 100vh;
+  padding-bottom: 40rpx;
+}
+
+/* ========== 1. 状态栏 ========== */
+.status-bar {
+  height: 88rpx; // 状态栏高度(适配刘海屏)
+  background-color: #f5f7fa;
+}
+
+/* ========== 2. 导航栏 ========== */
+.nav-bar {
+  display: flex;
+  justify-content: space-between; // 左右两端对齐
+  align-items: center; // 垂直居中
+  padding: 20rpx 32rpx;
+  background-color: #f5f7fa;
+
+  // 导航按钮(返回/订单)
+  .nav-btn {
+    width: 72rpx;
+    height: 72rpx;
+    background: #fff;
+    border-radius: 16rpx; // 白色圆角按钮
+    display: flex;
+    align-items: center;
+    justify-content: center;
+
+    .nav-icon {
+      font-size: 40rpx;
+      color: #333;
+    }
+
+    .order-icon {
+      font-size: 28rpx;
+    }
+
+    .order-text {
+      font-size: 20rpx;
+      color: #333;
+    }
+  }
+
+  // 导航标题
+  .nav-title {
+    font-size: 40rpx;
+    font-weight: bold;
+    color: #222;
+  }
+}
+
+/* ========== 3. 搜索框 ========== */
+.search-container {
+  padding: 16rpx 32rpx 24rpx;
+
+  .search-box {
+    display: flex;
+    align-items: center;
+    padding: 20rpx 24rpx;
+    background-color: #fff; // 白色背景
+    border-radius: 40rpx; // 胶囊形状
+    box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.06); // 轻微阴影
+
+    // 搜索图标
+    .search-icon {
+      font-size: 32rpx;
+      color: #999;
+      margin-right: 12rpx;
+    }
+
+    // 输入框
+    .search-input {
+      flex: 1;
+      font-size: 28rpx;
+      color: #333;
+    }
+
+    // 占位文本样式
+    .placeholder {
+      color: #bbb;
+    }
+
+    // 右侧筛选按钮
+    .filter-btn {
+      width: 48rpx;
+      height: 48rpx;
+      display: flex;
+      align-items: center;
+      justify-content: center;
+      border-left: 1rpx solid #eee; // 左侧分割线
+      margin-left: 12rpx;
+      padding-left: 12rpx;
+
+      .filter-icon {
+        font-size: 32rpx;
+        color: #666;
+      }
+    }
+  }
+}
+
+/* ========== 4. 区块(最近搜索/最近查看) ========== */
+.section {
+  padding: 0 32rpx;
+  margin-bottom: 32rpx;
+
+  // 区块头部
+  .section-header {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    padding: 24rpx 0;
+
+    .section-title {
+      font-size: 34rpx;
+      font-weight: bold;
+      color: #222;
+    }
+
+    // 操作按钮(全部清除/查看全部)
+    .section-action {
+      font-size: 28rpx;
+      color: #ff4757; // 红色
+    }
+  }
+}
+
+/* ========== 5. 最近搜索标签 ========== */
+.search-tags {
+  display: flex;
+  flex-direction: column;
+
+  .tag {
+    display: flex;
+    align-items: center;
+    padding: 24rpx 0;
+    border-bottom: 1rpx solid #eee; // 底部分割线
+
+    &:last-child {
+      border-bottom: none; // 最后一个去掉分割线
+    }
+
+    // 时钟图标
+    .tag-icon {
+      font-size: 36rpx;
+      color: #999;
+      margin-right: 20rpx;
+    }
+
+    // 标签内容
+    .tag-content {
+      flex: 1;
+      display: flex;
+      flex-direction: column;
+
+      .tag-text {
+        font-size: 30rpx;
+        font-weight: 600;
+        color: #222;
+        margin-bottom: 8rpx;
+      }
+
+      .tag-location {
+        font-size: 26rpx;
+        color: #999;
+      }
+    }
+  }
+}
+
+/* ========== 6. 酒店列表 ========== */
+.hotel-scroll {
+  max-height: 800rpx; // 设置最大高度,超出部分可滚动
+  overflow-y: auto;
+}
+
+.hotel-list {
+  display: flex;
+  flex-direction: column;
+
+  .hotel-item {
+    display: flex;
+    padding: 24rpx 0;
+    border-bottom: 1rpx solid #eee;
+
+    &:last-child {
+      border-bottom: none;
+    }
+
+    // 酒店图片
+    .hotel-image {
+      width: 200rpx;
+      height: 160rpx;
+      border-radius: 16rpx;
+      flex-shrink: 0; // 防止被压缩
+      background-color: #e8e8e8; // 占位背景色
+    }
+
+    // 酒店信息
+    .hotel-info {
+      flex: 1;
+      margin-left: 20rpx;
+      display: flex;
+      flex-direction: column;
+      justify-content: space-between;
+
+      // 第一行:名称 + 评分
+      .hotel-top {
+        display: flex;
+        justify-content: space-between;
+        align-items: center;
+
+        .hotel-name {
+          font-size: 32rpx;
+          font-weight: bold;
+          color: #222;
+          flex: 1;
+        }
+
+        // 评分
+        .rating {
+          display: flex;
+          align-items: center;
+          flex-shrink: 0;
+
+          .rating-star {
+            font-size: 28rpx;
+            margin-right: 6rpx;
+          }
+
+          .rating-score {
+            font-size: 30rpx;
+            color: #222;
+            font-weight: 500;
+          }
+        }
+      }
+
+      // 第二行:位置
+      .hotel-location {
+        display: flex;
+        align-items: center;
+        margin: 8rpx 0;
+
+        .loc-icon {
+          font-size: 24rpx;
+          margin-right: 6rpx;
+        }
+
+        .loc-text {
+          font-size: 26rpx;
+          color: #999;
+        }
+      }
+
+      // 第三行:价格
+      .hotel-price {
+        font-size: 34rpx;
+        color: #0066ff; // 蓝色价格
+        font-weight: bold;
+      }
+    }
+  }
+}
+</style>

+ 646 - 796
pages/travel/hotel/index.vue

@@ -1,976 +1,826 @@
 <template>
-	<view class="hotel-page">
-		<!-- 顶部导航栏 -->
-		<view class="hotel-nav" :style="{ paddingTop: statusBarHeight + 'px' }">
-			<view class="nav-row">
-				<view class="nav-back" @tap="goBack">
-					<text class="nav-back-icon">‹</text>
+	<view class="page-wrap">
+		<!-- ===== 顶部渐变导航栏 ===== -->
+		<view class="header-gradient">
+			<view class="nav-bar flex-between">
+				<!-- 返回按钮 -->
+				<view class="nav-btn" @click="goBack">
+					<text class="wlIcon wlIcon-fanhui1"></text>
 				</view>
+				<!-- 页面标题 -->
 				<text class="nav-title">酒店</text>
-				<view class="nav-order" @tap="goOrder">
-					<text class="nav-order-icon"></text>
-					<text class="nav-order-text">订单</text>
+				<!-- 订单按钮 -->
+				<view class="nav-btn" @click="toOrder">
+					<text class="btn-text">订单</text>
 				</view>
 			</view>
 		</view>
-
-		<!-- 类型标签 -->
-		<view class="type-tabs">
-			<view 
-				v-for="(tab, index) in typeTabs" 
-				:key="index"
-				class="type-tab"
-				:class="{ 'type-tab--active': activeTypeTab === index }"
-				@tap="selectTypeTab(index)"
-			>
-				<text class="type-tab__text">{{ tab }}</text>
+		<!-- Tab栏(国内/国际/钟点房/民宿/短租) -->
+		<view class="tab-wrap">
+			<view v-for="(item, index) in tabList" :key="index" class="tab-item" :class="{ active: currentTab === index }"
+				@click="switchTab(index)">
+				{{ item.label }}
 			</view>
 		</view>
-
-		<!-- 滚动内容区域 -->
-		<scroll-view scroll-y class="content-scroll" :style="{ height: scrollHeight + 'px' }">
-			<!-- 搜索区域 -->
-			<view class="search-section">
-				<!-- 城市和搜索框 -->
-				<view class="search-header">
-					<view class="city-selector" @tap="openCityPicker">
-						<text class="city-selector__text">{{ cityName || '选择城市' }}</text>
-						<text class="city-selector__arrow">▾</text>
-					</view>
-					<view class="search-input" @tap="goSearch">
-						<text class="search-input__icon">🔍</text>
-						<text class="search-input__placeholder">位置/品牌/酒店</text>
-					</view>
-					<view class="location-btn" @tap="openLocation">
-						<text class="location-btn__icon">📍</text>
-					</view>
+		<!-- ===== 筛选白色卡片区域 ===== -->
+		<view class="filter-card">
+			<!-- 城市选择 + 搜索框 + 定位按钮 -->
+			<view class="city-search-row flex-between">
+				<!-- 城市选择器 -->
+				<view class="city-select" @click="selectCity">
+					<text class="city-text">{{ cityName }}</text>
+					<text class="wlIcon wlIcon-fanhui4"></text>
 				</view>
-
-				<!-- 定位提示条 -->
-				<view class="location-tip" @tap="openLocation">
-					<text class="location-tip__icon">📍</text>
-					<text class="location-tip__text">开启定位权限,发现附近优质酒店</text>
-					<text class="location-tip__action">去开启 ›</text>
+				<!-- 搜索输入框 -->
+				<view class="search-input-box" @click="openSearch">
+					<text class="search-icon">🔍</text>
+					<text class="search-placeholder">位置/品牌/酒店</text>
 				</view>
-
-				<!-- 日期选择 -->
-				<view class="date-section">
-					<view class="date-item" @tap="openDatePicker">
-						<text class="date-item__month">{{ checkInMonth }}月</text>
-						<text class="date-item__day">{{ checkInDay }}</text>
-						<text class="date-item__label">{{ checkInLabel }}</text>
-					</view>
-					<view class="date-nights">
-						<text class="date-nights__text">{{ nights }}晚</text>
-					</view>
-					<view class="date-item date-item--right" @tap="openDatePicker">
-						<text class="date-item__month">{{ checkOutMonth }}月</text>
-						<text class="date-item__day">{{ checkOutDay }}</text>
-						<text class="date-item__label">{{ checkOutLabel }}</text>
-					</view>
+				<!-- 定位按钮 -->
+				<view class="loc-btn" @click="openLocation">
+					<text class="loc-icon">⚙</text>
 				</view>
+			</view>
+			<view class="divider"></view>
+			<!-- 定位提示条 -->
+			<view class="location-tip flex-between" @click="goOpenSetting">
+				<view class="tip-left flex-row">
+					<text class="tip-icon">📍</text>
+					<text class="tip-text">开启定位权限,发现附近优质酒店</text>
+				</view>
+				<text class="tip-link">去开启 ›</text>
+			</view>
 
-				<!-- 房间人数和筛选 -->
-				<view class="room-section">
-					<view class="room-selector" @tap="openPassengerPicker">
-						<text class="room-selector__text">{{ roomText }}</text>
-						<text class="room-selector__arrow">▾</text>
-					</view>
-					<view class="filter-btn" @tap="openFilter">
-						<text class="filter-btn__text">价格/星级</text>
+			<!-- 日期选择区域(入住日期 - 晚数 - 离店日期) -->
+			<view class="date-row flex-between">
+				<!-- 入住日期 -->
+				<view class="date-block" @click="pickCheckIn">
+					<text class="date-month">{{ checkInMonth }}月</text>
+					<text class="date-num">{{ checkInDay }}</text>
+					<text class="date-desc">{{ checkInLabel }}</text>
+				</view>
+				<!-- 入住晚数 -->
+				<view class="night-tag">{{ nightCount }}晚</view>
+				<!-- 离店日期 -->
+				<view class="date-block" @click="pickCheckOut">
+					<text class="date-month">{{ checkOutMonth }}月</text>
+					<text class="date-num">{{ checkOutDay }}</text>
+					<text class="date-desc">{{ checkOutLabel }}</text>
+				</view>
+			</view>
+			<view class="divider"></view>
+
+			<!-- 房间人数选择 + 价格星级筛选 -->
+			<view class="guest-row flex-between">
+				<!-- 房间人数选择器 -->
+				<view class="guest-select flex-row" @click="selectGuest">
+					<text>{{ roomDesc }}</text>
+					<text class="wlIcon wlIcon-fanhui4 "></text>
+				</view>
+				<!-- 价格/星级筛选 -->
+				<text class="filter-text">价格/星级</text>
+			</view>
+			<view class="divider"></view>
+
+			<!-- 快捷标签横向滚动(亲子出游/环球影城等) -->
+			<scroll-view scroll-x class="tag-scroll" :show-scrollbar="false">
+				<view class="tag-list flex-row">
+					<view v-for="(tag, idx) in hotTagList" :key="idx" class="tag-item" :class="{ active: activeTagIdx === idx }"
+						@click="onTagClick(idx)">
+						{{ tag }}
 					</view>
 				</view>
+			</scroll-view>
 
-				<!-- 快捷标签 -->
-				<scroll-view scroll-x class="quick-tags" :show-scrollbar="false">
-					<view 
-						v-for="(tag, index) in quickTags" 
-						:key="index"
-						class="quick-tag"
-						:class="{ 'quick-tag--active': activeTag === index }"
-						@tap="selectTag(index)"
-					>
-						<text class="quick-tag__text">{{ tag }}</text>
-					</view>
-				</scroll-view>
+			<!-- 搜索酒店按钮 -->
+			<button class="search-btn" @click="searchHotel">搜索酒店</button>
+		</view>
 
-				<!-- 搜索按钮 -->
-				<view class="search-btn" @tap="onSearch">
-					<text class="search-btn__text">搜索酒店</text>
-				</view>
+		<!-- ===== 最受欢迎酒店横向滚动列表 ===== -->
+		<view class="hot-section">
+			<view class="section-head flex-between">
+				<text class="section-title">最受欢迎</text>
+				<text class="more-link" @click="lookMoreHot">查看全部 ›</text>
 			</view>
-
-			<!-- 最受欢迎 -->
-			<view class="section">
-				<view class="section-header">
-					<text class="section-title">最受欢迎</text>
-					<text class="section-more" @tap="goMore">查看全部 ›</text>
-				</view>
-				<scroll-view scroll-x class="hot-scroll" :show-scrollbar="false">
-					<view class="hot-list">
-						<view 
-							v-for="(hotel, index) in hotHotels" 
-							:key="hotel.id"
-							class="hot-item"
-							@tap="goHotelDetail(hotel)"
-						>
-							<image class="hot-item__image" :src="hotel.image" mode="aspectFill" />
-							<view class="hot-item__favorite">
-								<text class="hot-item__favorite-icon">❤️</text>
-							</view>
-							<view class="hot-item__info">
-								<text class="hot-item__name">{{ hotel.name }}</text>
-								<text class="hot-item__address">{{ hotel.address }}</text>
-								<view class="hot-item__bottom">
-									<view class="hot-item__price">
-										<text class="hot-item__price-symbol">¥</text>
-										<text class="hot-item__price-value">{{ hotel.price }}</text>
-										<text class="hot-item__price-unit">/晚</text>
-									</view>
-									<view class="hot-item__score">
-										<text class="hot-item__score-icon">⭐</text>
-										<text class="hot-item__score-value">{{ hotel.score }}</text>
-									</view>
+			<scroll-view scroll-x class="hot-card-scroll" :show-scrollbar="false">
+				<view class="hot-card-list flex-row">
+					<view v-for="(hotel, idx) in hotHotelList" :key="idx" class="hot-card" @click="goHotelDetail(hotel)">
+						<!-- 收藏按钮(右上角心形) -->
+						<view class="collect-btn" @click.stop="toggleCollect(hotel)">
+							<text class="heart">{{ hotel.collect ? '❤️' : '' }}</text>
+						</view>
+						<!-- 酒店封面图片(暂时留空,后端接口就绪后替换) -->
+						<image class="card-img" :src="hotel.img" mode="aspectFill"></image>
+						<!-- 酒店信息 -->
+						<view class="card-info">
+							<text class="card-name">{{ hotel.name }}</text>
+							<text class="card-address">{{ hotel.address }}</text>
+							<view class="card-bottom flex-between">
+								<text class="card-price">{{ hotel.price }}</text>
+								<view class="score-box flex-row">
+									<text class="score-star">⭐</text>
+									<text class="score">{{ hotel.score }}</text>
 								</view>
 							</view>
 						</view>
 					</view>
-				</scroll-view>
-			</view>
-
-			<!-- 推荐给你 -->
-			<view class="section">
-				<view class="section-header">
-					<text class="section-title">推荐给你</text>
-					<text class="section-more" @tap="goMore">查看全部 ›</text>
 				</view>
-				
-				<!-- 分类标签 -->
-				<view class="category-tabs">
-					<view 
-						v-for="(cat, index) in categoryTabs" 
-						:key="index"
-						class="category-tab"
-						:class="{ 'category-tab--active': activeCategory === index }"
-						@tap="selectCategory(index)"
-					>
-						<text class="category-tab__icon">{{ cat.icon }}</text>
-						<text class="category-tab__text">{{ cat.name }}</text>
+			</scroll-view>
+		</view>
+
+		<!-- ===== 推荐给你列表 ===== -->
+		<view class="recommend-section">
+			<view class="section-head flex-between">
+				<text class="section-title">推荐给你</text>
+				<text class="more-link" @click="lookMoreRec">查看全部 ›</text>
+			</view>
+			<!-- 分类标签(所有/别墅/酒店/民宿) -->
+			<scroll-view scroll-x class="cate-scroll" :show-scrollbar="false">
+				<view class="cate-list flex-row">
+					<view v-for="(cate, idx) in cateList" :key="idx" class="cate-item" :class="{ active: activeCateIdx === idx }"
+						@click="onCateClick(idx)">
+						{{ cate.label }}
 					</view>
 				</view>
-
-				<!-- 推荐列表 -->
-				<view class="recommend-list">
-					<view 
-						v-for="hotel in recommendHotels" 
-						:key="hotel.id"
-						class="recommend-item"
-						@tap="goHotelDetail(hotel)"
-					>
-						<image class="recommend-item__image" :src="hotel.image" mode="aspectFill" />
-						<view class="recommend-item__content">
-							<view class="recommend-item__header">
-								<text class="recommend-item__name">{{ hotel.name }}</text>
-								<view class="recommend-item__score">
-									<text class="recommend-item__score-icon">⭐</text>
-									<text class="recommend-item__score-value">{{ hotel.score }}</text>
-								</view>
-							</view>
-							<text class="recommend-item__address">📍 {{ hotel.address }}</text>
-							<view class="recommend-item__price">
-								<text class="recommend-item__price-value">{{ hotel.price }}元/晚</text>
+			</scroll-view>
+			<!-- 酒店列表 -->
+			<view class="rec-list">
+				<view v-for="(item, idx) in recHotelList" :key="idx" class="rec-item flex-row" @click="goHotelDetail(item)">
+					<!-- 酒店封面图片(暂时留空,后端接口就绪后替换) -->
+					<image class="rec-img" :src="item.img" mode="aspectFill"></image>
+					<view class="rec-info flex-col ">
+						<view class="rec-top flex-between">
+							<text class="rec-name">{{ item.name }}</text>
+							<view class="score-box flex-row">
+								<text class="score-star">⭐</text>
+								<text class="score">{{ item.score }}</text>
 							</view>
 						</view>
+						<view class="rec-address flex-row">
+							<text class="addr-icon">📍</text>
+							<text class="addr-text">{{ item.address }}</text>
+						</view>
+						<text class="rec-price">{{ item.price }}</text>
 					</view>
 				</view>
-				
-				<uni-load-more :status="loadStatus" />
 			</view>
-		</scroll-view>
-
-		<!-- 城市选择器 -->
-		<city-picker 
-			v-model="selectedCity" 
-			@change="onCityChange"
-		/>
-
-		<!-- 日期选择器 -->
-		<date-range-picker 
-			:check-in="checkInDate"
-			:check-out="checkOutDate"
-			@confirm="onDateConfirm"
-		/>
-
-		<!-- 人数选择器 -->
-		<passenger-picker 
-			@confirm="onPassengerConfirm"
-		/>
+		</view>
 	</view>
 </template>
 
 <script>
-import CityPicker from '@/components/travel/city-picker/city-picker.vue'
-import DateRangePicker from '@/components/travel/date-range-picker/date-range-picker.vue'
-import PassengerPicker from '@/components/travel/passenger-picker/passenger-picker.vue'
-import { pullHotelList, pullHotelRecommend } from '@/features/travel/travel-gateway.js'
-
 export default {
-	components: {
-		CityPicker,
-		DateRangePicker,
-		PassengerPicker
-	},
 	data() {
 		return {
-			statusBarHeight: 0,
-			scrollHeight: 0,
-			typeTabs: ['国内', '国际', '钟点房', '民宿', '短租'],
-			activeTypeTab: 0,
+			// 城市名称
 			cityName: '北京',
-			selectedCity: '',
-			checkInDate: '',
-			checkOutDate: '',
+			// Tab栏数据
+			tabList: [
+				{ label: '国内' },
+				{ label: '国际' },
+				{ label: '钟点房' },
+				{ label: '民宿' },
+				{ label: '短租' }
+			],
+			currentTab: 0,
+			// 日期数据
 			checkInMonth: 7,
 			checkInDay: 20,
 			checkInLabel: '今天',
 			checkOutMonth: 7,
 			checkOutDay: 21,
 			checkOutLabel: '明天',
-			nights: 1,
-			roomText: '1 间房 2 成人 1 儿童',
-			passengerInfo: {
-				room: 1,
-				adult: 2,
-				child: 1,
-				infant: 0
-			},
-			quickTags: ['亲子出游', '环球影城', '天安门广场', '鸟巢', '故宫', '迪士尼'],
-			activeTag: 0,
-			categoryTabs: [
-				{ name: '所有', icon: '' },
-				{ name: '别墅', icon: '🏡' },
-				{ name: '酒店', icon: '🏨' },
-				{ name: '民宿', icon: '🏠' }
+			nightCount: 1,
+			// 房间人数
+			roomCount: 1,
+			adultCount: 2,
+			childCount: 1,
+			// 快捷标签
+			hotTagList: ['亲子出游', '环球影城', '天安门广场', '鸟巢', '故宫'],
+			activeTagIdx: 0,
+			// 分类标签
+			cateList: [
+				{ label: '所有' },
+				{ label: ' 别墅' },
+				{ label: '🏨 酒店' },
+				{ label: '🏢 民宿' }
 			],
-			activeCategory: 0,
-			hotHotels: [],
-			recommendHotels: [],
-			loadStatus: 'more',
-			pageIndex: 1,
-			pageSize: 10
+			activeCateIdx: 0,
+			// 横向卡片【最受欢迎】酒店数据
+			hotHotelList: [
+				{
+					name: '地平线撤退',
+					address: '加利福尼亚州洛杉矶',
+					price: '480元/晚',
+					score: '4.5',
+					collect: true,
+					img: ''
+				},
+				{
+					name: '阿斯特拉大酒店',
+					address: '纽约州纽约市',
+					price: '每晚300元',
+					score: '4.5',
+					collect: false,
+					img: ''
+				}
+			],
+			// 竖向【推荐给你】酒店列表
+			recHotelList: [
+				{
+					name: '宁静沙滩',
+					address: '檀香山,你好',
+					price: '270元/晚',
+					score: '4.0',
+					img: ''
+				},
+				{
+					name: '极乐套房',
+					address: '加利福尼亚州圣地亚哥',
+					price: '320元/晚',
+					score: '3.8',
+					img: ''
+				}
+			]
 		}
 	},
-	created() {
-		this.initPage()
-	},
-	onShow() {
-		this.loadData()
-		this.loadHotHotels()
+	computed: {
+		// 房间人数描述
+		roomDesc() {
+			const parts = [`${this.roomCount}间房`, `${this.adultCount}成人`]
+			if (this.childCount > 0) parts.push(`${this.childCount}儿童`)
+			return parts.join(' ')
+		}
 	},
 	methods: {
-		initPage() {
-			const sys = uni.getSystemInfoSync()
-			this.statusBarHeight = sys.statusBarHeight || 0
-			this.scrollHeight = sys.windowHeight - uni.upx2px(600)
-			this.setDefaultDates()
+		// 切换tab
+		switchTab(index) {
+			this.currentTab = index
 		},
-		setDefaultDates() {
-			const today = new Date()
-			const tomorrow = new Date()
-			tomorrow.setDate(today.getDate() + 1)
-			this.checkInDate = this.formatDate(today)
-			this.checkOutDate = this.formatDate(tomorrow)
-			this.checkInMonth = today.getMonth() + 1
-			this.checkInDay = today.getDate()
-			this.checkOutMonth = tomorrow.getMonth() + 1
-			this.checkOutDay = tomorrow.getDate()
+		// 返回上一页
+		goBack() {
+			uni.navigateBack()
 		},
-		formatDate(date) {
-			const year = date.getFullYear()
-			const month = String(date.getMonth() + 1).padStart(2, '0')
-			const day = String(date.getDate()).padStart(2, '0')
-			return `${year}-${month}-${day}`
+		// 订单页面
+		toOrder() {
+			uni.navigateTo({ url: '/pages/order/order' })
 		},
-		selectTypeTab(index) {
-			this.activeTypeTab = index
+		// 搜索酒店
+		searchHotel() {
+			uni.showToast({ title: '搜索酒店' })
 		},
-		openCityPicker() {
-			uni.showToast({
-				title: '打开城市选择器',
-				icon: 'none'
-			})
+		// 选择城市
+		selectCity() {
+			uni.navigateTo({ url: '/pages/travel/city-picker' })
 		},
-		onCityChange(city) {
-			this.cityName = city.name || city
-			this.selectedCity = city
-		},
-		goSearch() {
-			uni.navigateTo({
-				url: '/pages/travel/hotel/search'
-			})
+		// 打开搜索
+		openSearch() {
+			uni.navigateTo({ url: '/pages/travel/hotel/hotel-search' })
 		},
+		// 打开定位
 		openLocation() {
-			uni.showToast({
-				title: '打开定位',
-				icon: 'none'
-			})
-		},
-		openDatePicker() {
-			uni.showToast({
-				title: '打开日期选择器',
-				icon: 'none'
-			})
-		},
-		onDateConfirm({ checkIn, checkOut, nights }) {
-			this.checkInDate = checkIn
-			this.checkOutDate = checkOut
-			this.nights = nights
-			const checkInDate = new Date(checkIn)
-			const checkOutDate = new Date(checkOut)
-			this.checkInMonth = checkInDate.getMonth() + 1
-			this.checkInDay = checkInDate.getDate()
-			this.checkOutMonth = checkOutDate.getMonth() + 1
-			this.checkOutDay = checkOutDate.getDate()
-		},
-		openPassengerPicker() {
-			uni.showToast({
-				title: '打开人数选择器',
-				icon: 'none'
-			})
-		},
-		onPassengerConfirm(data) {
-			this.passengerInfo = data
-			this.roomText = `${data.room}间房 ${data.adult}成人 ${data.child}儿童`
-		},
-		openFilter() {
-			uni.navigateTo({
-				url: '/pages/travel/hotel/filter'
+			uni.getLocation({
+				type: 'gcj02',
+				success: (res) => {
+					console.log('定位成功', res)
+				},
+				fail: () => {
+					uni.showToast({ title: '定位失败', icon: 'none' })
+				}
 			})
 		},
-		selectTag(index) {
-			this.activeTag = index
+		// 去开启定位权限
+		goOpenSetting() {
+			uni.openSetting()
 		},
-		onSearch() {
-			uni.navigateTo({
-				url: '/pages/travel/hotel/list'
-			})
+		// 选择入住日期
+		pickCheckIn() {
+			uni.showToast({ title: '选择入住日期' })
 		},
-		selectCategory(index) {
-			this.activeCategory = index
-			this.pageIndex = 1
-			this.recommendHotels = []
-			this.loadData()
+		// 选择离店日期
+		pickCheckOut() {
+			uni.showToast({ title: '选择离店日期' })
 		},
-		async loadData() {
-			if (this.loadStatus === 'noMore') return
-			this.loadStatus = 'loading'
-			try {
-				const result = await pullHotelList({
-					cityName: this.cityName,
-					checkInDate: this.checkInDate,
-					checkOutDate: this.checkOutDate,
-					pageIndex: this.pageIndex,
-					pageSize: this.pageSize
-				})
-				if (result && result.hotelList) {
-					if (this.pageIndex === 1) {
-						this.recommendHotels = result.hotelList
-					} else {
-						this.recommendHotels = [...this.recommendHotels, ...result.hotelList]
-					}
-					this.loadStatus = result.hotelList.length < this.pageSize ? 'noMore' : 'more'
-				} else {
-					this.loadStatus = 'noMore'
-				}
-			} catch (error) {
-				console.error('加载酒店列表失败:', error)
-				this.loadStatus = 'more'
-			}
+		// 选择入住人数
+		selectGuest() {
+			uni.navigateTo({ url: '/pages/travel/hotel/room-picker' })
 		},
-		async loadHotHotels() {
-			try {
-				const result = await pullHotelRecommend({
-					pageSize: 10
-				})
-				if (result && result.hotelList) {
-					this.hotHotels = result.hotelList
-				}
-			} catch (error) {
-				console.error('加载热门酒店失败:', error)
-			}
+		// 热门标签点击
+		onTagClick(idx) {
+			this.activeTagIdx = idx
 		},
-		goHotelDetail(hotel) {
-			uni.navigateTo({
-				url: `/pages/travel/hotel/detail?id=${hotel.id}`
-			})
+		// 分类标签点击
+		onCateClick(idx) {
+			this.activeCateIdx = idx
 		},
-		goOrder() {
-			uni.navigateTo({
-				url: '/pages/travel/hotel/order-list'
-			})
+		// 切换收藏
+		toggleCollect(hotel) {
+			hotel.collect = !hotel.collect
 		},
-		goBack() {
-			uni.navigateBack()
+		// 查看更多
+		lookMoreHot() { },
+		lookMoreRec() { 
+			uni.navigateTo({ url: '/pages/travel/hotel/hotel-list' })
 		},
-		goMore() {
-			uni.navigateTo({
-				url: '/pages/travel/hotel/list'
-			})
-		}
-	},
-	onReachBottom() {
-		if (this.loadStatus === 'more') {
-			this.pageIndex++
-			this.loadData()
+		// 跳转酒店详情
+		goHotelDetail(item) {
+			console.log('跳转酒店详情:', item.name)
 		}
 	}
 }
 </script>
 
 <style lang="scss" scoped>
-.hotel-page {
-	background-color: #f5f7fa;
-	min-height: 100vh;
-}
-
-.hotel-nav {
-	background: linear-gradient(135deg, #74b9ff 0%, #a29bfe 100%);
-	padding-bottom: 20rpx;
+page {
+	background-color: #f7f9fc;
+	margin: 0;
+	padding: 0;
 }
 
-.nav-row {
+.flex-row {
 	display: flex;
-	justify-content: space-between;
+	flex-direction: row;
 	align-items: center;
-	padding: 20rpx 30rpx;
 }
 
-.nav-back {
-	width: 60rpx;
-	height: 60rpx;
-	background-color: rgba(255, 255, 255, 0.9);
-	border-radius: 16rpx;
+.flex-between {
 	display: flex;
-	justify-content: center;
+	flex-direction: row;
+	justify-content: space-between;
 	align-items: center;
 }
 
-.nav-back-icon {
-	font-size: 40rpx;
-	color: #333;
-}
-
-.nav-title {
-	font-size: 36rpx;
-	font-weight: 700;
-	color: #fff;
-}
-
-.nav-order {
+.flex-col {
 	display: flex;
 	flex-direction: column;
-	align-items: center;
-	padding: 10rpx 20rpx;
-	background-color: rgba(255, 255, 255, 0.9);
-	border-radius: 16rpx;
 }
 
-.nav-order-icon {
-	font-size: 32rpx;
+.page-wrap {
+	min-height: 100vh;
 }
 
-.nav-order-text {
-	font-size: 20rpx;
-	color: #333;
+/* ========== 顶部渐变导航栏 ========== */
+.header-gradient {
+	background: linear-gradient(90deg, #60d8f7, #3898f2);
+	padding: 16rpx 32rpx;
+	height: 200rpx;
 }
 
-.type-tabs {
-	display: flex;
-	background-color: #fff;
-	padding: 20rpx 30rpx;
-	border-radius: 0 0 24rpx 24rpx;
-}
+.nav-bar {
+	margin-bottom: 16rpx;
 
-.type-tab {
-	flex: 1;
-	text-align: center;
-	padding: 16rpx 0;
-}
+	.nav-btn {
+		width: 88rpx;
+		height: 88rpx;
+		background: #fff;
+		border-radius: 20rpx;
+		display: flex;
+		flex-direction: column;
+		justify-content: center;
+		align-items: center;
 
-.type-tab--active {
-	position: relative;
-}
-
-.type-tab--active::after {
-	content: '';
-	position: absolute;
-	bottom: 0;
-	left: 50%;
-	transform: translateX(-50%);
-	width: 40rpx;
-	height: 6rpx;
-	background-color: #4a8cff;
-	border-radius: 3rpx;
-}
+		.nav-icon {
+			font-size: 32rpx;
+			color: #333;
+		}
 
-.type-tab__text {
-	font-size: 28rpx;
-	color: #666;
-}
+		.btn-text {
+			font-size: 20rpx;
+			color: #333;
+		}
+	}
 
-.type-tab--active .type-tab__text {
-	color: #4a8cff;
-	font-weight: 600;
+	.nav-title {
+		font-size: 52rpx;
+		font-weight: bold;
+		color: #222;
+	}
 }
 
-.content-scroll {
-	background-color: #f5f7fa;
-}
+/* ========== 筛选白色卡片 ========== */
+.filter-card {
+	margin: 0;
+	padding: 16rpx 24rpx;
 
-.search-section {
-	background-color: #fff;
-	padding: 30rpx;
-	margin: 20rpx;
-	border-radius: 24rpx;
 }
 
-.search-header {
+/* Tab栏(渐变背景 + 选中白色圆角) */
+.tab-wrap {
 	display: flex;
-	align-items: center;
-	margin-bottom: 20rpx;
-}
+	background: linear-gradient(180deg, #daeef9, #f9fbfe);
+	border-radius: 36rpx 36rpx 0 0;
+	margin-top: -50rpx;
+	overflow: visible;
+
+	.tab-item {
+		flex: 1;
+		text-align: center;
+		padding: 10rpx;
+		font-size: 34rpx;
+		color: #667799;
+
+		// 第一个tab左上圆角
+		&:first-child {
+			border-radius: 36rpx 0 0 0;
+		}
 
-.city-selector {
-	display: flex;
-	align-items: center;
-	margin-right: 20rpx;
-}
+		// 最后一个tab右上圆角
+		&:last-child {
+			border-radius: 0 36rpx 0 0;
+		}
 
-.city-selector__text {
-	font-size: 32rpx;
-	font-weight: 600;
-	color: #333;
+		&.active {
+			background-color: #ffffff;
+			color: #0066ff;
+			font-weight: bold;
+			border-radius: 24rpx 20rpx 0 0; // 选中状态圆角40rpx,比容器大4rpx
+			margin-top: -12rpx;
+			padding-top: 20rpx;
+		}
+	}
 }
 
-.city-selector__arrow {
-	font-size: 20rpx;
-	color: #999;
-	margin-left: 8rpx;
-}
+/* 城市选择 + 搜索框 + 定位 */
+.city-search-row {
+	margin-bottom: 32rpx;
 
-.search-input {
-	flex: 1;
-	display: flex;
-	align-items: center;
-	background-color: #f5f5f5;
-	border-radius: 30rpx;
-	padding: 16rpx 24rpx;
-}
+	.city-select {
+		.city-text {
+			font-size: 40rpx;
+			font-weight: 500;
+			color: #222;
+		}
 
-.search-input__icon {
-	font-size: 28rpx;
-	margin-right: 12rpx;
-}
+		.arrow {
+			font-size: 24rpx;
+			color: #666;
+			margin-left: 8rpx;
+		}
+	}
 
-.search-input__placeholder {
-	font-size: 26rpx;
-	color: #999;
-}
+	.search-input-box {
+		flex: 1;
+		margin: 0 24rpx;
+		background-color: #f2f3f6;
+		border-radius: 16rpx;
+		padding: 20rpx 24rpx;
+		display: flex;
+		align-items: center;
+
+		.search-icon {
+			font-size: 28rpx;
+			color: #ccc;
+			margin-right: 8rpx;
+		}
 
-.location-btn {
-	margin-left: 20rpx;
-	padding: 12rpx;
-}
+		.search-placeholder {
+			flex: 1;
+			font-size: 30rpx;
+			color: #bbb;
+		}
+	}
 
-.location-btn__icon {
-	font-size: 36rpx;
+	.loc-btn {
+		.loc-icon {
+			font-size: 36rpx;
+			color: #0066ff;
+		}
+	}
 }
 
+/* 定位提示条 */
 .location-tip {
-	display: flex;
-	align-items: center;
-	background-color: #f0f7ff;
-	padding: 16rpx 20rpx;
-	border-radius: 12rpx;
-	margin-bottom: 24rpx;
-}
-
-.location-tip__icon {
-	font-size: 28rpx;
-	margin-right: 12rpx;
-}
-
-.location-tip__text {
-	flex: 1;
-	font-size: 24rpx;
-	color: #4a8cff;
-}
-
-.location-tip__action {
-	font-size: 24rpx;
-	color: #4a8cff;
-}
-
-.date-section {
-	display: flex;
-	align-items: center;
-	margin-bottom: 20rpx;
-}
+	background-color: #e8f4ff;
+	border-radius: 16rpx;
+	padding: 12rpx;
+	margin-bottom: 36rpx;
 
-.date-item {
-	flex: 1;
-	text-align: center;
-	padding: 20rpx 0;
-}
+	.tip-left {
+		.tip-icon {
+			font-size: 28rpx;
+			color: #0066ff;
+			margin-right: 8rpx;
+		}
 
-.date-item--right {
-	border-left: 1rpx solid #eee;
-}
+		.tip-text {
+			font-size: 28rpx;
+			color: #0052aa;
+		}
+	}
 
-.date-item__month {
-	display: block;
-	font-size: 24rpx;
-	color: #999;
-	margin-bottom: 8rpx;
+	.tip-link {
+		font-size: 28rpx;
+		color: #0066ff;
+	}
 }
 
-.date-item__day {
-	display: block;
-	font-size: 40rpx;
-	font-weight: 700;
-	color: #333;
-	margin-bottom: 8rpx;
-}
+/* 日期选择区域 */
+.date-row {
+	margin-bottom: 24rpx;
 
-.date-item__label {
-	display: block;
-	font-size: 22rpx;
-	color: #999;
-}
+	.date-block {
+		display: flex;
+		align-items: baseline;
 
-.date-nights {
-	padding: 0 20rpx;
-}
+		.date-month {
+			font-size: 28rpx;
+			color: #666;
+			margin-right: 4rpx;
+		}
 
-.date-nights__text {
-	font-size: 24rpx;
-	color: #666;
-	background-color: #f5f5f5;
-	padding: 8rpx 20rpx;
-	border-radius: 20rpx;
-}
+		.date-num {
+			font-size: 48rpx;
+			font-weight: bold;
+			color: #222;
+		}
 
-.room-section {
-	display: flex;
-	justify-content: space-between;
-	align-items: center;
-	margin-bottom: 20rpx;
-	padding-bottom: 20rpx;
-	border-bottom: 1rpx solid #f5f5f5;
-}
+		.date-desc {
+			font-size: 30rpx;
+			color: #999;
+			margin-left: 8rpx;
+		}
+	}
 
-.room-selector {
-	display: flex;
-	align-items: center;
+	.night-tag {
+		background-color: #f2f3f6;
+		padding: 8rpx 24rpx;
+		border-radius: 99rpx;
+		font-size: 26rpx;
+		color: #666;
+	}
 }
 
-.room-selector__text {
-	font-size: 26rpx;
-	color: #333;
-}
+/* 房间人数 + 价格筛选 */
+.guest-row {
+	margin-bottom: 24rpx;
 
-.room-selector__arrow {
-	font-size: 20rpx;
-	color: #999;
-	margin-left: 8rpx;
-}
+	.guest-select {
+		font-size: 34rpx;
+		color: #222;
 
-.filter-btn {
-	padding: 12rpx 24rpx;
-	background-color: #f5f5f5;
-	border-radius: 20rpx;
-}
+		.arrow {
+			font-size: 24rpx;
+			color: #999;
+			margin-left: 8rpx;
+		}
+	}
 
-.filter-btn__text {
-	font-size: 24rpx;
-	color: #666;
+	.filter-text {
+		font-size: 34rpx;
+		color: #888;
+	}
 }
 
-.quick-tags {
-	white-space: nowrap;
-	margin-bottom: 24rpx;
+/* 分割线 */
+.divider {
+	width: 100%;
+	height: 1rpx;
+	background-color: #eeeeee;
+	margin-bottom: 32rpx;
 }
 
-.quick-tag {
-	display: inline-block;
-	padding: 12rpx 24rpx;
-	background-color: #f5f5f5;
-	border-radius: 30rpx;
-	margin-right: 16rpx;
+/* 快捷标签横向滚动 */
+.tag-scroll {
+	margin-bottom: 44rpx;
 }
 
-.quick-tag--active {
-	background-color: #fff0f0;
-}
+.tag-list {
+	gap: 24rpx;
 
-.quick-tag__text {
-	font-size: 24rpx;
-	color: #666;
-}
+	.tag-item {
+		padding: 14rpx 36rpx;
+		background-color: #f2f3f6;
+		border-radius: 24rpx;
+		font-size: 30rpx;
+		white-space: nowrap;
+		color: #666;
 
-.quick-tag--active .quick-tag__text {
-	color: #ff6b6b;
+		&.active {
+			background-color: #ffe9ec;
+			color: #ff6b7b;
+		}
+	}
 }
 
+/* 搜索酒店按钮 */
 .search-btn {
-	background: linear-gradient(135deg, #4a8cff 0%, #667eea 100%);
-	border-radius: 40rpx;
-	padding: 24rpx 0;
-	text-align: center;
-}
-
-.search-btn__text {
-	font-size: 30rpx;
+	width: 100%;
+	background-color: #0066ff;
 	color: #fff;
-	font-weight: 600;
-}
-
-.section {
-	padding: 30rpx;
-}
-
-.section-header {
-	display: flex;
-	justify-content: space-between;
-	align-items: center;
-	margin-bottom: 24rpx;
-}
-
-.section-title {
-	font-size: 32rpx;
-	font-weight: 600;
-	color: #333;
+	font-size: 40rpx;
+	font-weight: bold;
+	border-radius: 50rpx;
+	// padding: 36rpx 0;
+	border: none;
+	box-shadow: 0 6rpx 16rpx rgba(0, 102, 255, 0.22);
 }
 
-.section-more {
-	font-size: 24rpx;
-	color: #999;
+/* ========== 最受欢迎模块 ========== */
+.hot-section {
+	background-color: #fff;
+	padding: 0 32rpx 36rpx;
 }
 
-.hot-scroll {
-	white-space: nowrap;
-}
+.section-head {
+	padding: 36rpx 0 24rpx;
 
-.hot-list {
-	display: inline-flex;
-	gap: 20rpx;
-}
+	.section-title {
+		font-size: 40rpx;
+		font-weight: bold;
+		color: #222;
+	}
 
-.hot-item {
-	width: 320rpx;
-	position: relative;
-	border-radius: 16rpx;
-	overflow: hidden;
+	.more-link {
+		font-size: 30rpx;
+		color: #0066ff;
+	}
 }
 
-.hot-item__image {
+.hot-card-scroll {
 	width: 100%;
-	height: 240rpx;
-}
-
-.hot-item__favorite {
-	position: absolute;
-	top: 12rpx;
-	right: 12rpx;
-	width: 48rpx;
-	height: 48rpx;
-	background-color: rgba(255, 255, 255, 0.9);
-	border-radius: 50%;
-	display: flex;
-	justify-content: center;
-	align-items: center;
-}
-
-.hot-item__favorite-icon {
-	font-size: 24rpx;
-}
-
-.hot-item__info {
-	position: absolute;
-	bottom: 0;
-	left: 0;
-	right: 0;
-	padding: 20rpx;
-	background: linear-gradient(to top, rgba(0, 0, 0, 0.7), transparent);
 }
 
-.hot-item__name {
-	display: block;
-	font-size: 28rpx;
-	color: #fff;
-	font-weight: 600;
-	margin-bottom: 8rpx;
+.hot-card-list {
+	gap: 28rpx;
 }
 
-.hot-item__address {
-	display: block;
-	font-size: 22rpx;
-	color: rgba(255, 255, 255, 0.8);
-	margin-bottom: 12rpx;
+.hot-card {
+	width: 540rpx;
+	border-radius: 28rpx;
 	overflow: hidden;
-	text-overflow: ellipsis;
-	white-space: nowrap;
-}
-
-.hot-item__bottom {
-	display: flex;
-	justify-content: space-between;
-	align-items: center;
-}
-
-.hot-item__price {
-	display: flex;
-	align-items: baseline;
-}
-
-.hot-item__price-symbol {
-	font-size: 22rpx;
-	color: #fff;
-	font-weight: 600;
-}
-
-.hot-item__price-value {
-	font-size: 32rpx;
-	color: #fff;
-	font-weight: 700;
-	margin: 0 4rpx;
-}
+	position: relative;
+	flex-shrink: 0;
+
+	.collect-btn {
+		position: absolute;
+		top: 20rpx;
+		right: 20rpx;
+		width: 64rpx;
+		height: 64rpx;
+		background-color: rgba(255, 255, 255, 0.7);
+		border-radius: 50%;
+		display: flex;
+		align-items: center;
+		justify-content: center;
+		z-index: 2;
+
+		.heart {
+			font-size: 32rpx;
+		}
+	}
 
-.hot-item__price-unit {
-	font-size: 20rpx;
-	color: rgba(255, 255, 255, 0.8);
-}
+	.card-img {
+		width: 100%;
+		height: 340rpx;
+		background-color: #f0f0f0;
+	}
 
-.hot-item__score {
-	display: flex;
-	align-items: center;
-}
+	.card-info {
+		position: absolute;
+		left: 0;
+		bottom: 0;
+		width: 100%;
+		padding: 28rpx;
+		background: linear-gradient(to top, rgba(0, 0, 0, 0.65), transparent);
+		color: #fff;
+
+		.card-name {
+			font-size: 36rpx;
+			font-weight: bold;
+			display: block;
+		}
 
-.hot-item__score-icon {
-	font-size: 20rpx;
-}
+		.card-address {
+			font-size: 28rpx;
+			opacity: 0.9;
+			display: block;
+			margin: 8rpx 0 16rpx;
+		}
 
-.hot-item__score-value {
-	font-size: 22rpx;
-	color: #fff;
-	margin-left: 4rpx;
-}
+		.card-price {
+			font-size: 30rpx;
+			font-weight: bold;
+		}
 
-.category-tabs {
-	display: flex;
-	gap: 16rpx;
-	margin-bottom: 24rpx;
+		.score-box {
+			.score {
+				font-size: 28rpx;
+				margin-left: 6rpx;
+			}
+		}
+	}
 }
 
-.category-tab {
-	flex: 1;
-	display: flex;
-	flex-direction: column;
-	align-items: center;
-	padding: 20rpx 0;
+/* ========== 推荐模块 ========== */
+.recommend-section {
 	background-color: #fff;
-	border-radius: 16rpx;
+	margin-top: 20rpx;
+	padding: 0 32rpx 100rpx;
 }
 
-.category-tab--active {
-	background-color: #4a8cff;
+.cate-scroll {
+	margin-bottom: 32rpx;
 }
 
-.category-tab__icon {
-	font-size: 32rpx;
-	margin-bottom: 8rpx;
-}
+.cate-list {
+	gap: 24rpx;
 
-.category-tab__text {
-	font-size: 24rpx;
-	color: #666;
-}
+	.cate-item {
+		padding: 20rpx 44rpx;
+		border-radius: 18rpx;
+		background-color: #f2f3f6;
+		font-size: 30rpx;
+		white-space: nowrap;
+		color: #666;
 
-.category-tab--active .category-tab__text {
-	color: #fff;
+		&.active {
+			background-color: #0066ff;
+			color: #fff;
+		}
+	}
 }
 
-.recommend-list {
-	margin-top: 16rpx;
-}
+.rec-list {
+	.rec-item {
+		padding: 32rpx 0;
+		border-bottom: 1rpx solid #eee;
 
-.recommend-item {
-	display: flex;
-	background-color: #fff;
-	border-radius: 16rpx;
-	overflow: hidden;
-	margin-bottom: 20rpx;
-}
-
-.recommend-item__image {
-	width: 240rpx;
-	height: 200rpx;
-}
+		&:last-child {
+			border-bottom: none;
+		}
 
-.recommend-item__content {
-	flex: 1;
-	padding: 20rpx;
-	display: flex;
-	flex-direction: column;
-	justify-content: space-between;
-}
+		.rec-img {
+			width: 240rpx;
+			height: 200rpx;
+			border-radius: 16rpx;
+			flex-shrink: 0;
+			background-color: #f0f0f0;
+		}
 
-.recommend-item__header {
-	display: flex;
-	justify-content: space-between;
-	align-items: flex-start;
-}
+		.rec-info {
+			display: flex;
+			flex-direction: column;
+			justify-content: space-between;
+			flex: 1;
+			margin-left: 24rpx;
+			height: 200rpx;
+
+			.rec-top {
+				display: flex;
+				justify-content: space-between;
+				margin-bottom: 12rpx;
+
+				.rec-name {
+					font-size: 34rpx;
+					font-weight: bold;
+					color: #222;
+					flex: 1;
+				}
 
-.recommend-item__name {
-	flex: 1;
-	font-size: 30rpx;
-	font-weight: 600;
-	color: #333;
-	margin-right: 16rpx;
-}
+				.score-box {
+					flex-shrink: 0;
+					display: flex;
+					align-items: center;
 
-.recommend-item__score {
-	display: flex;
-	align-items: center;
-}
+					.score-star {
+						font-size: 28rpx;
+						margin-right: 6rpx;
+					}
 
-.recommend-item__score-icon {
-	font-size: 24rpx;
-}
+					.score {
+						font-size: 30rpx;
+						color: #222;
+						font-weight: 500;
+					}
+				}
+			}
 
-.recommend-item__score-value {
-	font-size: 26rpx;
-	color: #ffa940;
-	font-weight: 600;
-	margin-left: 4rpx;
-}
+			.rec-address {
+				display: flex;
+				align-items: center; // 垂直居中对齐
+				justify-items: start;
+				margin-bottom: 16rpx;
 
-.recommend-item__address {
-	font-size: 24rpx;
-	color: #999;
-	margin: 12rpx 0;
-	overflow: hidden;
-	text-overflow: ellipsis;
-	white-space: nowrap;
-}
+				.addr-icon {
+					font-size: 22rpx;
+					margin-right: 6rpx;
+				}
 
-.recommend-item__price {
-	align-self: flex-start;
-}
+				.addr-text {
+					font-size: 26rpx;
+					color: #999;
+				}
+			}
 
-.recommend-item__price-value {
-	font-size: 32rpx;
-	color: #4a8cff;
-	font-weight: 700;
+			.rec-price {
+				display: flex;
+				align-items: center;
+				justify-content: flex-start;
+				font-size: 34rpx;
+				color: #0066ff;
+				font-weight: bold;
+			}
+		}
+	}
 }
 </style>

+ 12 - 12
pages/user/address/address.vue

@@ -1,6 +1,6 @@
 <template>
   <view class="address-page">
-    <empty v-if="addressList.length === 0 && !loading" text="暫無收貨地址" />
+    <empty v-if="addressList.length === 0 && !loading" :text="$t('address.empty')" />
     <view class="margin-top-bj">
       <view class="cu-list menu-avatar">
         <view class="cu-item" :class="modalName == 'move-box-' + index ? 'move-cur' : ''"
@@ -21,8 +21,8 @@
             <text class="wlIcon wlIcon-xiugaioryijian text-xl"></text>
           </view>
           <view class="move">
-            <view class="bg-grey" @tap.stop="addAddress('edit', item)">編輯</view>
-            <view class="bg-red" @tap.stop="delAddress(item.id, index)">刪除</view>
+            <view class="bg-grey" @tap.stop="addAddress('edit', item)">{{ $t('mine.edit') }}</view>
+            <view class="bg-red" @tap.stop="delAddress(item.id, index)">{{ $t('mine.delete') }}</view>
           </view>
         </view>
       </view>
@@ -30,7 +30,7 @@
 
     <view class="safeAreaBottom"></view>
     <view class="wanlian cu-bar tabbar foot flex flex-direction">
-      <button @tap="addAddress('add')" class="cu-btn wanl-bg-orange lg">+ 新增收貨地址</button>
+      <button @tap="addAddress('add')" class="cu-btn wanl-bg-orange lg">{{ $t('address.addNew') }}</button>
     </view>
   </view>
 </template>
@@ -53,7 +53,7 @@ export default {
     this.source = option.source || 0
     this.orderId = option.order_id || 0
     if (!this.$store.state.user.isLogin) {
-      uni.showToast({ title: '請先登錄', icon: 'none' })
+      uni.showToast({ title: this.$t('common.pleaseLogin'), icon: 'none' })
       setTimeout(() => {
         uni.navigateTo({ url: '/pages/passport/signin' })
       }, 500)
@@ -85,8 +85,8 @@ export default {
     },
     async delAddress(id, key) {
       uni.showModal({
-        title: '提示',
-        content: '確定刪除該地址嗎?',
+        title: this.$t('common.tip'),
+        content: this.$t('address.confirmDelete'),
         success: async (res) => {
           if (res.confirm) {
             this.addressList.splice(key, 1)
@@ -109,22 +109,22 @@ export default {
         uni.navigateBack({ delta: 1 })
       } else if (this.source == 2) {
         uni.showModal({
-          title: '提示',
-          content: '確定修改為該地址嗎?(每個訂單僅可修改一次)',
+          title: this.$t('common.tip'),
+          content: this.$t('address.confirmChange'),
           success: async (res) => {
             if (res.confirm) {
-              uni.showLoading({ title: '修改中...', mask: true })
+              uni.showLoading({ title: this.$t('common.updating'), mask: true })
               try {
                 await postOrderEditAddress({ id: this.orderId, address_id: item.id })
                 uni.hideLoading()
-                uni.showToast({ title: '修改成功', icon: 'success' })
+                uni.showToast({ title: this.$t('common.updateSuccess'), icon: 'success' })
                 uni.$emit('orderAddressUpdated')
                 setTimeout(() => {
                   uni.navigateBack({ delta: 1 })
                 }, 500)
               } catch (e) {
                 uni.hideLoading()
-                const msg = (e && e.msg) || (e && e.message) || '修改失敗'
+                const msg = (e && e.msg) || (e && e.message) || this.$t('common.updateFailed')
                 uni.showToast({ title: msg, icon: 'none', duration: 500 })
               }
             }

+ 20 - 20
pages/user/address/addressManage.vue

@@ -2,32 +2,32 @@
   <view class="address-manage">
     <view class="form-wrap">
       <view class="cu-form-group">
-        <view class="title">聯繫人</view>
-        <input type="text" placeholder="收貨人姓名" v-model="addressData.name" />
+        <view class="title">{{ $t('addressManage.contact') }}</view>
+        <input type="text" :placeholder="$t('addressManage.namePlaceholder')" v-model="addressData.name" />
       </view>
       <view class="cu-form-group">
-        <view class="title">手機號碼</view>
-        <input type="number" placeholder="收貨人手機號碼" v-model="addressData.mobile" maxlength="11" />
+        <view class="title">{{ $t('addressManage.mobile') }}</view>
+        <input type="number" :placeholder="$t('addressManage.mobilePlaceholder')" v-model="addressData.mobile" maxlength="11" />
       </view>
       <view class="cu-form-group" @tap="openAddressPicker">
-        <view class="title">所在地區</view>
+        <view class="title">{{ $t('addressManage.region') }}</view>
         <view class="picker-text" :class="{ placeholder: !addressData.formatted_address }">
-          {{ addressData.formatted_address || '請選擇省/市/區' }}
+          {{ addressData.formatted_address || $t('addressManage.regionPlaceholder') }}
         </view>
       </view>
       <view class="cu-form-group align-start">
-        <view class="title">詳細地址</view>
-        <textarea maxlength="-1" v-model="addressData.address" placeholder="街道、樓牌號等詳細地址" />
+        <view class="title">{{ $t('addressManage.detailAddress') }}</view>
+        <textarea maxlength="-1" v-model="addressData.address" :placeholder="$t('addressManage.detailAddressPlaceholder')" />
       </view>
       <view class="cu-form-group margin-top">
-        <view class="title">設為默認</view>
+        <view class="title">{{ $t('addressManage.setDefault') }}</view>
         <switch @change="switchChange" :class="addressData.default == 1 ? 'checked' : ''"
           :checked="addressData.default == 1" />
       </view>
     </view>
 
     <view class="padding-bj flex flex-direction margin-top">
-      <button @tap="confirm" class="cu-btn wanl-bg-orange lg">完成</button>
+      <button @tap="confirm" class="cu-btn wanl-bg-orange lg">{{ $t('orderConfirm.complete') }}</button>
     </view>
     <address-picker ref="addressPicker" @selectAddress="successSelectAddress"></address-picker>
   </view>
@@ -58,7 +58,7 @@ export default {
   },
   onLoad(option) {
     if (!this.$store.state.user.isLogin) {
-      uni.showToast({ title: '請先登錄', icon: 'none' })
+      uni.showToast({ title: this.$t('common.pleaseLogin'), icon: 'none' })
       setTimeout(() => {
         uni.navigateTo({ url: '/pages/passport/signin' })
       }, 500)
@@ -66,8 +66,8 @@ export default {
     }
     if (option.type === 'newadd') {
       this.addressData.default = 1
-      this.manageType = 'add'  // ← 新增這行
-    } else if (option.type === 'edit') {  // ← 把 if 改成 else if
+      this.manageType = 'add'  
+    } else if (option.type === 'edit') {  
       this.manageType = 'edit'
       if (option.data) {
         this.addressData = JSON.parse(option.data)
@@ -75,7 +75,7 @@ export default {
     } else {
       this.manageType = option.type || 'add'
     }
-    uni.setNavigationBarTitle({ title: this.manageType === 'edit' ? '編輯地址' : '新增地址' })
+    uni.setNavigationBarTitle({ title: this.manageType === 'edit' ? this.$t('addressManage.editTitle') : this.$t('addressManage.addTitle') })
   },
   methods: {
     openAddressPicker() {
@@ -98,19 +98,19 @@ export default {
     async confirm() {
       let data = this.addressData
       if (!data.name) {
-        uni.showToast({ title: '請填寫收貨人姓名', icon: 'none' })
+        uni.showToast({ title: this.$t('addressManage.nameRequired'), icon: 'none' })
         return
       }
       if (!data.mobile) {
-        uni.showToast({ title: '請填寫手機號碼', icon: 'none' })
+        uni.showToast({ title: this.$t('addressManage.mobileRequired'), icon: 'none' })
         return
       }
       if (!data.formatted_address) {
-        uni.showToast({ title: '請選擇所在地區', icon: 'none' })
+        uni.showToast({ title: this.$t('addressManage.regionRequired'), icon: 'none' })
         return
       }
       if (!data.address) {
-        uni.showToast({ title: '請填寫詳細地址', icon: 'none' })
+        uni.showToast({ title: this.$t('addressManage.addressRequired'), icon: 'none' })
         return
       }
       try {
@@ -119,7 +119,7 @@ export default {
         }
         const resData = await postAddressSave({ data, type: this.manageType })
         uni.showToast({
-          title: '地址' + (this.manageType === 'edit' ? '更新' : '添加') + '成功',
+          title: this.$t('addressManage.saveSuccess', [this.manageType === 'edit' ? '更新' : '添加']),
           icon: 'none'
         })
         setTimeout(() => {
@@ -136,7 +136,7 @@ export default {
           }, 100)
         }, 500)
       } catch (e) {
-        const message = e && e.message ? e.message : '操作失敗'
+        const message = e && e.message ? e.message : this.$t('addressManage.operationFailed')
         uni.showToast({ title: message, icon: 'none' })
       }
     },

+ 13 - 13
pages/user/coupon/apply.vue

@@ -15,24 +15,24 @@
 							<text class="price">{{ Number(coupon.price) }}</text>
 						</view>
 						<view class="cu-tag wanl-gray-dark radius text-sm">
-							滿{{ Number(coupon.limit) }}減{{ Number(coupon.price) }}
+							{{ $t('mall.fullReduction', [Number(coupon.limit), Number(coupon.price)]) }}
 						</view>
 					</block>
 					<block v-if="coupon.type == 'discount' || (coupon.type == 'vip' && coupon.usertype == 'discount')">
 						<view class="colour">
 							<text class="price">{{ Number(coupon.discount) }}</text>
-							<text class="discount"></text>
+							<text class="discount">{{ $t('mall.discountSuffix') }}</text>
 						</view>
 						<view class="cu-tag wanl-gray-dark radius text-sm">
-							滿{{ Number(coupon.limit) }}打{{ Number(coupon.discount) }}折
+							{{ $t('mall.fullDiscount', [Number(coupon.limit), Number(coupon.discount)]) }}
 						</view>
 					</block>
 					<block v-if="coupon.type == 'shipping'">
 						<view class="colour">
-							<text class="price">包郵</text>
+							<text class="price">{{ $t('mall.freeShipping') }}</text>
 						</view>
 						<view class="cu-tag wanl-gray-dark radius text-sm">
-							滿{{ Number(coupon.limit) }}包郵
+							{{ $t('mall.freeShippingFull', [Number(coupon.limit)]) }}
 						</view>
 					</block>
 				</view>
@@ -44,23 +44,23 @@
 					</view>
 					<view class="content text-min">
 						<view class="wanl-gray">
-							<view><text class="wlIcon-dot"></text>全場通用</view>
+							<view><text class="wlIcon-dot"></text>{{ $t('coupon.universal') }}</view>
 							<block v-if="coupon.pretype == 'fixed'">
-								<view><text class="wlIcon-dot"></text>{{ coupon.startdate }} 開始</view>
-								<view><text class="wlIcon-dot"></text>{{ coupon.enddate }} 結束</view>
+								<view><text class="wlIcon-dot"></text>{{ $t('coupon.start', [coupon.startdate]) }}</view>
+								<view><text class="wlIcon-dot"></text>{{ $t('coupon.end', [coupon.enddate]) }}</view>
 							</block>
 							<block v-if="coupon.pretype == 'appoint'">
 								<view v-if="coupon.validity == 0">
-									<text class="wlIcon-dot"></text>永久有效
+									<text class="wlIcon-dot"></text>{{ $t('coupon.permanent') }}
 								</view>
 								<view v-else>
-									<text class="wlIcon-dot"></text>領取後{{ coupon.validity }}天內有效
+									<text class="wlIcon-dot"></text>{{ $t('coupon.validDays', [coupon.validity]) }}
 								</view>
 							</block>
 						</view>
 						<!-- 未领取显示领取按钮 -->
 						<view class="cu-btn sm round" @tap.stop="onReceive(coupon.id)" v-if="!coupon_state">
-							立即領取
+							{{ $t('mall.getNow') }}
 						</view>
 					</view>
 				</view>
@@ -135,12 +135,12 @@ export default {
 			try {
 				const res = await postCouponReceive({ id: coupon_id })
 				this.coupon_state = true
-				uni.showToast({ title: typeof res === 'string' ? res : '領取成功', icon: 'none' })
+				uni.showToast({ title: typeof res === 'string' ? res : this.$t('mall.receiveSuccess'), icon: 'none' })
 				this.$store.commit('statistics/dynamic', {
 					coupon: this.$store.state.statistics.dynamic.coupon + 1
 				})
 			} catch (e) {
-				uni.showToast({ title: '領取失敗', icon: 'none' })
+				uni.showToast({ title: this.$t('coupon.receiveFailed'), icon: 'none' })
 			}
 		}
 	}

+ 5 - 5
pages/user/coupon/details.vue

@@ -2,21 +2,21 @@
 	<view class="wanl-coupon">
 		<view class="edgeInsetTop"></view>
 		<view class="details padding-bj">
-			<view class="text-center wanl-gray" v-if="!couponData.id">暫無優惠券詳情</view>
+			<view class="text-center wanl-gray" v-if="!couponData.id">{{ $t('coupon.noDetails') }}</view>
 			<view v-else>
 				<view class="text-lg text-bold margin-bottom-bj">{{ couponData.name }}</view>
 				<view class="wanl-gray text-sm margin-bottom-bj">
 					<text class="cu-tag sm radius margin-right-xs">{{ couponData.type_text }}</text>
-					{{ couponData.type == 'reduction' ? '滿' + Number(couponData.limit) + '減' + Number(couponData.price) : couponData.type == 'discount' ? '滿' + Number(couponData.limit) + '打' + Number(couponData.discount) + '折' : '滿' + Number(couponData.limit) + '包郵' }}
+					{{ couponData.type == 'reduction' ? $t('mall.fullReduction', [Number(couponData.limit), Number(couponData.price)]) : couponData.type == 'discount' ? $t('mall.fullDiscount', [Number(couponData.limit), Number(couponData.discount)]) : $t('mall.freeShippingFull', [Number(couponData.limit)]) }}
 				</view>
 				<view class="wanl-gray text-sm" v-if="couponData.pretype == 'fixed'">
-					有效期:{{ couponData.startdate }} ~ {{ couponData.enddate }}
+					{{ $t('coupon.validPeriod') }}:{{ couponData.startdate }} ~ {{ couponData.enddate }}
 				</view>
 				<view class="wanl-gray text-sm" v-else-if="couponData.pretype == 'appoint' && couponData.validity != 0">
-					領取後{{ couponData.validity }}天內有效
+					{{ $t('coupon.validDays', [couponData.validity]) }}
 				</view>
 				<view class="wanl-gray text-sm" v-else>
-					永久有效
+					{{ $t('coupon.permanent') }}
 				</view>
 			</view>
 		</view>

+ 96 - 95
pages/user/coupon/list.vue

@@ -1,104 +1,105 @@
 <!-- 优惠券列表 -->
 <template>
-		<view class="wanl-order-list">
-			<!-- 顶部Tab:满减/折扣/包邮 -->
-			<view class="navbar">
-				<view class="nav-item text-df" v-for="(item, index) in navList" :key="index"
-					:class="{ current: tabCurrentIndex === index }" @tap="tabClick(index)">
-					{{ item.text }}
-				</view>
+	<view class="wanl-order-list">
+		<!-- 顶部Tab:满减/折扣/包邮 -->
+		<view class="navbar">
+			<view class="nav-item text-df" v-for="(item, index) in navList" :key="index"
+				:class="{ current: tabCurrentIndex === index }" @tap="tabClick(index)">
+				{{ item.text }}
 			</view>
-			<!-- 滑动切换 -->
-			<swiper :current="tabCurrentIndex" style="height: calc(100% - 60rpx)" duration="300" @change="changeTab">
-				<swiper-item class="tab-content" v-for="(tag, key) in navList" :key="key">
-					<scroll-view class="list-scroll-content" scroll-y @scrolltolower="loadData">
-						<!-- 空白页 -->
-						<wanl-empty text="暫無優惠券" src="ticket_default3x" v-if="tag.loaded === true && tag.cardList.length === 0" />
-						<!-- 优惠券列表 -->
-						<view class="wanl-coupon">
-							<view v-for="(coupon, seat) in tag.cardList" :key="seat" :class="coupon.type"
-								class="item margin-bj radius-bock" @tap="onDetails(coupon)">
-								<image :src="couponBg" class="coupon-bg"></image>
-								<image :src="couponReceived" class="coupon-sign" v-if="coupon.state"></image>
-								<!-- 左侧:金额/折扣 -->
-								<view class="item-left">
-									<block v-if="coupon.type == 'reduction' || (coupon.type == 'vip' && coupon.usertype == 'reduction')">
-										<view class="colour">
-											<text class="text-price"></text>
-											<text class="price">{{ Number(coupon.price) }}</text>
-										</view>
-										<view class="cu-tag wanl-gray-dark radius text-sm">
-											滿{{ Number(coupon.limit) }}減{{ Number(coupon.price) }}
-										</view>
-									</block>
-									<block v-if="coupon.type == 'discount' || (coupon.type == 'vip' && coupon.usertype == 'discount')">
-										<view class="colour">
-											<text class="price">{{ Number(coupon.discount) }}</text>
-											<text class="discount">折</text>
-										</view>
-										<view class="cu-tag wanl-gray-dark radius text-sm">
-											滿{{ Number(coupon.limit) }}打{{ Number(coupon.discount) }}折
-										</view>
-									</block>
-									<block v-if="coupon.type == 'shipping'">
-										<view class="colour">
-											<text class="price">包郵</text>
-										</view>
-										<view class="cu-tag wanl-gray-dark radius text-sm">
-											滿{{ Number(coupon.limit) }}包郵
-										</view>
-									</block>
-								</view>
-								<!-- 右侧:店铺+名称+有效期+操作 -->
-								<view class="item-right padding-bj">
-									<view class="shop" @tap="onShop(coupon.shop_id)">
-										<view class="name">
-											<text class="wlIcon-dianpu margin-right-xs"></text> {{ coupon.shop.shopname }}
-										</view>
-										<view><text class="wlIcon-fanhui2"></text></view>
+		</view>
+		<!-- 滑动切换 -->
+		<swiper :current="tabCurrentIndex" style="height: calc(100% - 60rpx)" duration="300" @change="changeTab">
+			<swiper-item class="tab-content" v-for="(tag, key) in navList" :key="key">
+				<scroll-view class="list-scroll-content" scroll-y @scrolltolower="loadData">
+					<!-- 空白页 -->
+					<wanl-empty :text="$t('coupon.noCoupons')" src="ticket_default3x"
+						v-if="tag.loaded === true && tag.cardList.length === 0" />
+					<!-- 优惠券列表 -->
+					<view class="wanl-coupon">
+						<view v-for="(coupon, seat) in tag.cardList" :key="seat" :class="coupon.type"
+							class="item margin-bj radius-bock" @tap="onDetails(coupon)">
+							<image :src="couponBg" class="coupon-bg"></image>
+							<image :src="couponReceived" class="coupon-sign" v-if="coupon.state"></image>
+							<!-- 左侧:金额/折扣 -->
+							<view class="item-left">
+								<block v-if="coupon.type == 'reduction' || (coupon.type == 'vip' && coupon.usertype == 'reduction')">
+									<view class="colour">
+										<text class="text-price"></text>
+										<text class="price">{{ Number(coupon.price) }}</text>
 									</view>
-									<view class="title">
-										<view class="cu-tag sm radius margin-right-xs tagstyle">{{ coupon.type_text }}</view>
-										<text class="text-cut wanl-gray text-min">{{ coupon.name }}</text>
+									<view class="cu-tag wanl-gray-dark radius text-sm">
+										{{ $t('mall.fullReduction', [Number(coupon.limit), Number(coupon.price)]) }}
 									</view>
-									<view class="content text-min">
-										<view class="wanl-gray">
-											<view v-if="coupon.grant != '-1'">
-												<text class="wlIcon-dot"></text>剩餘 {{ coupon.surplus }} 張
-											</view>
-											<view v-if="coupon.drawlimit != 0">
-												<text class="wlIcon-dot"></text>限領 {{ coupon.drawlimit }} 張
-											</view>
-											<block v-if="coupon.pretype == 'fixed'">
-												<view><text class="wlIcon-dot"></text>{{ coupon.startdate }} 開始</view>
-												<view><text class="wlIcon-dot"></text>{{ coupon.enddate }} 結束</view>
-											</block>
-											<block v-if="coupon.pretype == 'appoint'">
-												<view v-if="coupon.validity == 0">
-													<text class="wlIcon-dot"></text>永久有效
-												</view>
-												<view v-else>
-													<text class="wlIcon-dot"></text>領取後{{ coupon.validity }}天內有效
-												</view>
-											</block>
-										</view>
-										<!-- 已领取:去使用 / 未领取:立即领取 -->
-										<view class="cu-btn sm round line-colour" @tap.stop="onApply(coupon.id)" v-if="coupon.state">
-											去使用
+								</block>
+								<block v-if="coupon.type == 'discount' || (coupon.type == 'vip' && coupon.usertype == 'discount')">
+									<view class="colour">
+										<text class="price">{{ Number(coupon.discount) }}</text>
+										<text class="discount">{{ $t('mall.discountSuffix') }}</text>
+									</view>
+									<view class="cu-tag wanl-gray-dark radius text-sm">
+										{{ $t('mall.fullDiscount', [Number(coupon.limit), Number(coupon.discount)]) }}
+									</view>
+								</block>
+								<block v-if="coupon.type == 'shipping'">
+									<view class="colour">
+										<text class="price">{{ $t('mall.freeShipping') }}</text>
+									</view>
+									<view class="cu-tag wanl-gray-dark radius text-sm">
+										{{ $t('mall.freeShippingFull', [Number(coupon.limit)]) }}
+									</view>
+								</block>
+							</view>
+							<!-- 右侧:店铺+名称+有效期+操作 -->
+							<view class="item-right padding-bj">
+								<view class="shop" @tap="onShop(coupon.shop_id)">
+									<view class="name">
+										<text class="wlIcon-dianpu margin-right-xs"></text> {{ coupon.shop.shopname }}
+									</view>
+									<view><text class="wlIcon-fanhui2"></text></view>
+								</view>
+								<view class="title">
+									<view class="cu-tag sm radius margin-right-xs tagstyle">{{ coupon.type_text }}</view>
+									<text class="text-cut wanl-gray text-min">{{ coupon.name }}</text>
+								</view>
+								<view class="content text-min">
+									<view class="wanl-gray">
+										<view v-if="coupon.grant != '-1'">
+											<text class="wlIcon-dot"></text>{{ $t('coupon.remaining', [coupon.surplus]) }}
 										</view>
-										<view class="cu-btn sm round" @tap.stop="onReceive(key, seat)" v-else>
-											立即領取
+										<view v-if="coupon.drawlimit != 0">
+											<text class="wlIcon-dot"></text>{{ $t('coupon.limitClaim', [coupon.drawlimit]) }}
 										</view>
+										<block v-if="coupon.pretype == 'fixed'">
+											<view><text class="wlIcon-dot"></text>{{ $t('coupon.start', [coupon.startdate]) }}</view>
+											<view><text class="wlIcon-dot"></text>{{ $t('coupon.end', [coupon.enddate]) }}</view>
+										</block>
+										<block v-if="coupon.pretype == 'appoint'">
+											<view v-if="coupon.validity == 0">
+												<text class="wlIcon-dot"></text>{{ $t('coupon.permanent') }}
+											</view>
+											<view v-else>
+												<text class="wlIcon-dot"></text>{{ $t('coupon.validDays', [coupon.validity]) }}
+											</view>
+										</block>
+									</view>
+									<!-- 已领取:去使用 / 未领取:立即领取 -->
+									<view class="cu-btn sm round line-colour" @tap.stop="onApply(coupon.id)" v-if="coupon.state">
+										{{ $t('coupon.useNow') }}
+									</view>
+									<view class="cu-btn sm round" @tap.stop="onReceive(key, seat)" v-else>
+										{{ $t('mall.getNow') }}
 									</view>
 								</view>
 							</view>
 						</view>
-						<uni-load-more :status="tag.loadingType" />
-						<view class="edgeInsetBottom"></view>
-					</scroll-view>
-				</swiper-item>
-			</swiper>
-		</view>
+					</view>
+					<uni-load-more :status="tag.loadingType" />
+					<view class="edgeInsetBottom"></view>
+				</scroll-view>
+			</swiper-item>
+		</swiper>
+	</view>
 </template>
 
 <script>
@@ -109,9 +110,9 @@ export default {
 		return {
 			tabCurrentIndex: 0,
 			navList: [
-				{ type: 'reduction', text: '滿減券', loadingType: 'more', current_page: 1, cardList: [] },
-				{ type: 'discount', text: '折扣券', loadingType: 'more', current_page: 1, cardList: [] },
-				{ type: 'shipping', text: '包郵券', loadingType: 'more', current_page: 1, cardList: [] }
+				{ type: 'reduction', text: this.$t('coupon.reductionCoupon'), loadingType: 'more', current_page: 1, cardList: [] },
+				{ type: 'discount', text: this.$t('coupon.discountCoupon'), loadingType: 'more', current_page: 1, cardList: [] },
+				{ type: 'shipping', text: this.$t('coupon.shippingCoupon'), loadingType: 'more', current_page: 1, cardList: [] }
 			],
 			couponBg: '/static/coupon/bg_coupon_3x.png',
 			couponReceived: '/static/coupon/img_couponcentre_received_3x.png'
@@ -168,12 +169,12 @@ export default {
 				const res = await postCouponReceive({ id: coupon.id })
 				coupon.id = res.id
 				coupon.state = true
-				uni.showToast({ title: res.msg || '領取成功', icon: 'none' })
+				uni.showToast({ title: res.msg || this.$t('mall.receiveSuccess'), icon: 'none' })
 				this.$store.commit('statistics/dynamic', {
 					coupon: this.$store.state.statistics.dynamic.coupon + 1
 				})
 			} catch (e) {
-				uni.showToast({ title: '領取失敗', icon: 'none' })
+				uni.showToast({ title: this.$t('coupon.receiveFailed'), icon: 'none' })
 			}
 		},
 		/** 去使用优惠券 */