Procházet zdrojové kódy

feat:积分商城 - 首页界面构建提交

xyh před 5 měsíci
rodič
revize
c7e132904a

+ 62 - 162
src/points/components/product-list/product-list.vue

@@ -2,51 +2,55 @@
   <view class="product-list-container">
     <!-- 商品列表头部 -->
     <view class="product-header">
-      <view class="product-title">
-        <text class="title-text">精选好物兑换</text>
-      </view>
-      <view class="search-bar">
-        <u-search placeholder="日照香炉生紫烟" v-model="keyword"></u-search>
-      </view>
+      <view class="title-text"><text>精选好物</text>兑换</view>
+      <u-search placeholder="日照香炉生紫烟" v-model="keyword" :showAction="false"></u-search>
     </view>
     
     <!-- 分类标签 -->
-    <view class="category-tabs">
-      <view 
-        v-for="(category, index) in categories" 
-        :key="index"
-        :class="['category-tab', { active: activeCategory === category.key }]"
-        @click="switchCategory(category.key)"
-      >
-        <text :class="['category-text', { active: activeCategory === category.key }]">{{ category.name }}</text>
-      </view>
-    </view>
+    <u-tabs 
+      :list="categories" 
+      :current="activeCategoryIndex"
+      @change="handleCategoryChange"
+      lineWidth="30"
+      lineColor="#20CAC2"
+      :activeStyle="{
+            color: '#303133',
+            fontWeight: 'bold',
+            transform: 'scale(1.05)'
+        }"
+      :inactiveStyle="{
+            color: '#606266',
+            transform: 'scale(1)'
+        }"
+      itemStyle="padding:0 45rpx; height: 72rpx;font-size:28rpx"
+      class="category-tabs"
+    ></u-tabs>
     
     <!-- 排序选项 -->
     <view class="sort-options">
       <view 
         v-for="(sort, index) in sortOptions" 
         :key="index"
-        :class="['sort-option', { active: activeSort === sort.key }]"
+        class="sort-option"
         @click="switchSort(sort.key)"
       >
         <text :class="['sort-text', { active: activeSort === sort.key }]">{{ sort.name }}</text>
-        <text v-if="sort.key === 'price' || sort.key === 'sales'" :class="['sort-icon', { active: activeSort === sort.key }]">
-          {{ sortDirection === 'asc' ? '↑' : '↓' }}
-        </text>
+        <view v-if="['price','sales'].includes(sort.key)">
+          <ImageItem src="/static/points/arrow-up.png" v-if="sortDirection === 'asc'"></ImageItem>
+          <ImageItem src="/static/points/arrow-down.png" v-else-if="sortDirection === 'desc'"></ImageItem>
+          <ImageItem src="/static/points/details.png" v-else></ImageItem>
+        </view>
       </view>
     </view>
     
     <!-- 商品列表 -->
-
       <view class="product-grid">
         <view 
           v-for="(product, index) in products" 
           :key="index"
-          class="product-item"
-        >
+          class="product-item">
           <view class="product-image">
-            <image :src="product.image" mode="aspectFill"></image>
+            <ImageItem :src="product.image" mode="aspectFill"/>
           </view>
           <view class="product-info">
             <u--text class="product-name" :lines="1" :text="product.name"></u--text>
@@ -67,9 +71,14 @@
 </template>
 
 <script>
+import ImageItem from "@/components/swiper/components/image.vue";
+
 export default {
+  components: {ImageItem},
   data() {
     return {
+      // 搜索关键词
+      keyword: '',
       // 分类数据
       categories: [
         { key: 'all', name: '全部' },
@@ -87,7 +96,7 @@ export default {
       // 当前选中的分类和排序
       activeCategory: 'all',
       activeSort: '综合',
-      sortDirection: 'asc',
+      sortDirection: '',
       // 商品数据
       products: [
         {
@@ -190,96 +199,25 @@ export default {
       // 分页数据
       page: 1,
       pageSize: 10,
-      hasMore: true,
-      // 下拉刷新和上拉加载配置
-      downOption: {
-        use: true,
-        auto: false,
-        callback: this.onDown
-      },
-      upOption: {
-        use: true,
-        auto: true,
-        page: {
-          num: 1,
-          size: 10
-        },
-        noMoreSize: 5,
-        empty: {
-          tip: '暂无商品'
-        },
-        callback: this.onUp
-      }
+    }
+  },
+  computed: {
+    activeCategoryIndex() {
+      return this.categories.findIndex(item => item.key === this.activeCategory)
     }
   },
   methods: {
-    // 切换分类
-    switchCategory(category) {
-      this.activeCategory = category
-      this.page = 1
-      this.products = []
-      this.onUp()
+    // 处理分类切换
+    handleCategoryChange(index) {
+
     },
     // 切换排序
     switchSort(sort) {
-      if (this.activeSort === sort && (sort === 'price' || sort === 'sales')) {
-        this.sortDirection = this.sortDirection === 'asc' ? 'desc' : 'asc'
-      } else {
-        this.activeSort = sort
-        this.sortDirection = 'asc'
-      }
-      this.page = 1
-      this.products = []
-      this.onUp()
-    },
-    // 下拉刷新
-    onDown() {
-      this.page = 1
-      this.products = []
-      this.onUp()
-    },
-    // 上拉加载
-    onUp(mescroll) {
-      // 模拟请求数据
-      setTimeout(() => {
-        // 模拟加载更多数据
-        const newProducts = [
-          {
-            id: this.products.length + 1,
-            name: '广誉源会员定制玻璃杯',
-            price: '10元+1000积分',
-            value: '100',
-            sales: 10,
-            image: `https://via.placeholder.com/300x300?text=Product+${this.products.length + 1}`
-          },
-          {
-            id: this.products.length + 2,
-            name: '广誉源会员定制玻璃杯',
-            price: '10元+1000积分',
-            value: '100',
-            sales: 10,
-            image: `https://via.placeholder.com/300x300?text=Product+${this.products.length + 2}`
-          }
-        ]
-        
-        this.products = [...this.products, ...newProducts]
-        this.page++
-        
-        // 模拟没有更多数据
-        if (this.page > 3) {
-          this.hasMore = false
-        }
-        
-        // 结束加载
-        if (mescroll) {
-          mescroll.endSuccess(newProducts.length, this.hasMore)
-        }
-      }, 1000)
+
     },
     // 处理兑换
     handleExchange(product) {
       console.log('兑换商品:', product)
-      // 这里可以调用兑换API
     }
   }
 }
@@ -295,92 +233,54 @@ export default {
     display: flex;
     justify-content: space-between;
     align-items: center;
-    padding: 20rpx 32rpx;
+    padding: 24rpx 32rpx 0 32rpx;
     background-color: #fff;
-    
-    .product-title {
-      .title-text {
-        font-size: 32rpx;
-        font-weight: 600;
-        color: #333;
+    .title-text {
+      font-size: 32rpx;
+      font-weight: 600;
+      color: #333;
+      margin-right: 22rpx;
+      text{
+        color: #20CAC2;
       }
     }
     
-    .search-bar {
-      display: flex;
-      align-items: center;
-      background-color: #F5F5F5;
-      padding: 8rpx 16rpx;
-      border-radius: 20rpx;
-      
-      .search-icon {
-        margin-right: 8rpx;
-        font-size: 24rpx;
-        color: #999;
-      }
-      
-      .search-text {
-        font-size: 24rpx;
-        color: #999;
-      }
+    .search-icon {
+      margin-right: 8rpx;
     }
   }
   
   .category-tabs {
-    display: flex;
-    padding: 20rpx 32rpx;
     background-color: #fff;
-    overflow-x: auto;
-    
-    .category-tab {
-      padding: 8rpx 20rpx;
-      margin-right: 20rpx;
-      border-radius: 20rpx;
-      background-color: #F5F5F5;
-      
-      &.active {
-        background-color: #FF6B6B;
-      }
-      
-      .category-text {
-        font-size: 24rpx;
-        color: #666;
-        
-        &.active {
-          color: #fff;
-        }
-      }
-    }
+    border-bottom: 1rpx solid #f0f0f0;
   }
   
   .sort-options {
     display: flex;
+    justify-content: space-around;
     padding: 16rpx 32rpx;
     background-color: #fff;
-    margin-bottom: 12rpx;
+    border-bottom: 1rpx solid #F5F5F5;
     
     .sort-option {
       display: flex;
       align-items: center;
-      margin-right: 40rpx;
+      justify-content: center;
+      flex: 1;
       
       .sort-text {
         font-size: 24rpx;
         color: #666;
         
         &.active {
-          color: #FF6B6B;
+          color: #03C8BE;
         }
       }
       
-      .sort-icon {
+      image {
         margin-left: 4rpx;
-        font-size: 20rpx;
-        color: #999;
-        
-        &.active {
-          color: #FF6B6B;
-        }
+        width: 20rpx;
+        height: 20rpx;
       }
     }
   }

+ 5 - 5
src/points/components/sign-in/sign-in.vue

@@ -11,8 +11,8 @@
         @click="handleSign(day, index)"
       >
         <view class="sign-day-circle" :class="getSignCircleClass(day)">
-          <image src="@/static/points/Signed.png" v-if="day.status === '1'"></image>
-          <image src="@/static/points/notSigned.png" v-else></image>
+          <ImageItem src="/static/points/Signed.png" v-if="day.status === '1'"/>
+          <ImageItem src="/static/points/notSigned.png" v-else/>
           <text class="sign-day-number" v-if="day.status === ''">+{{ day.point }}</text>
         </view>
         <text :class="day.status === '1' ? 'sign-day-text' : 'day-text'">{{ getSignText(day) }}</text>
@@ -22,10 +22,10 @@
 </template>
 
 <script>
-import Image from "@/components/swiper/components/image.vue";
+import ImageItem from "@/components/swiper/components/image.vue";
 
 export default {
-  components: {Image},
+  components: {ImageItem},
   props: {
     signData: {
       type: Array,
@@ -105,7 +105,7 @@ export default {
         align-items: center;
         margin-bottom: 16rpx;
         position: relative;
-        image{
+      .image{
           width: 60rpx;
           height: 74rpx;
         }

+ 9 - 6
src/points/components/task-list/task-list.vue

@@ -12,17 +12,17 @@
       >
         <view class="task-item-left">
           <view class="task-icon" :class="task.iconClass">
-            <image src="@/static/points/task_order.png"></image>
-<!--            <image src="@/static/points/task_shop.png"></image>-->
-<!--            <image src="@/static/points/task_trend.png"></image>-->
-<!--            <image src="@/static/points/task_wx.png"></image>-->
-<!--            <image src="@/static/points/task_account.png"></image>-->
+            <ImageItem src="/static/points/task_order.png"/>
+<!--            <ImageItem src="/static/points/task_shop.png"/>-->
+<!--            <ImageItem src="/static/points/task_trend.png"/>-->
+<!--            <ImageItem src="/static/points/task_wx.png"/>-->
+<!--            <ImageItem src="/static/points/task_account.png"/>-->
           </view>
 
           <view class="task-info">
             <view class="task-name">{{ task.name }}</view>
             <view class="task-reward">
-              <image src="@/static/points/point.png"></image>
+              <ImageItem src="/static/points/point.png"/>
               <text>+{{ task.reward }}</text>
             </view>
           </view>
@@ -41,7 +41,10 @@
 </template>
 
 <script>
+import ImageItem from "@/components/swiper/components/image.vue";
+
 export default {
+  components: {ImageItem},
   data() {
     return {
       tasks: [

binární
src/static/points/arrow-down.png


binární
src/static/points/arrow-up.png


binární
src/static/points/details.png