Browse Source

Merge branch 'home' into dev

陈雪 1 month ago
parent
commit
e75685ae22

+ 2 - 2
src/components/product-list/data.json

@@ -5,7 +5,7 @@
     "price": 299.9,
     "cover": "https://t.xiaoyaotravel.com/image/TourImComplait/messageContent/890ed9e754c54ceaa886a3946d55adbe.png",
     "category": "Electronics",
-    "rate": 4.5,
+    "rate": 4.0,
     "sold": 1200
   },
   {
@@ -14,7 +14,7 @@
     "price": 159.0,
     "cover": "https://t.xiaoyaotravel.com/image/TourImComplait/messageContent/890ed9e754c54ceaa886a3946d55adbe.png",
     "category": "Daily Essentials",
-    "rate": 4.2,
+    "rate": 4.21,
     "sold": 850
   },
   {

+ 18 - 3
src/components/product-list/product-item.vue

@@ -5,13 +5,16 @@
     <view class="product-name">{{ product.name }}</view>
     <view class="sell-rate">
       <view class="rate">
-        {{ product.rate }}
+        <view v-format.rate>{{ product.rate }}</view>
         <image src="@/static/images/rate.svg" class="w-28rpx ml-8rpx" mode="widthFix"></image>
       </view>
       <view class="sold">{{ product.sold }} Sold</view>
     </view>
     <view class="price-cart">
-      <view class="price">USD {{ product.price }}</view>
+      <view class="flex">
+        USD
+        <view class="ml-8rpx" v-format.price>{{ product.price }}</view>
+      </view>
       <view class="cart">
         <image src="@/static/images/cart.svg" class="w-32rpx" mode="widthFix"></image>
       </view>
@@ -20,7 +23,7 @@
 </template>
 
 <script lang="ts" setup>
-  import { ProductSimpleType } from '@/types/product-type'
+  import { ProductSimpleType } from '@/model/product-type'
 
   defineOptions({
     name: 'ProductItem',
@@ -34,6 +37,11 @@
     width: 328rpx;
     margin-bottom: 26rpx;
 
+    &:nth-last-child(1),
+    &:nth-last-child(2) {
+      margin-bottom: 0;
+    }
+
     .is-collect {
       position: absolute;
       display: flex;
@@ -45,13 +53,16 @@
     }
 
     .product-name {
+      height: 30rpx;
       margin-top: 16rpx;
+      overflow: hidden;
       font-family: 'PingFang SC';
       font-size: 28rpx;
       font-style: normal;
       font-weight: 600;
       line-height: 30rpx;
       color: $shop-text-3;
+      white-space: nowrap;
     }
 
     .sell-rate {
@@ -88,6 +99,10 @@
       line-height: 48rpx; /* 157.143% */
       color: $shop-primary;
 
+      .price {
+        display: flex;
+      }
+
       .cart {
         display: flex;
         align-items: center;

+ 29 - 2
src/components/product-list/product-list.vue

@@ -1,17 +1,32 @@
 <template>
-  <view class="product-list-container">
+  <view v-if="showSkeleton" class="product-list-container">
+    <view v-for="k in skeletonCount" :key="k" class="skeleton-item">
+      <wd-skeleton
+        :row-col="[
+          { width: '328rpx', height: '328rpx' },
+          1,
+          { width: '222rpx' },
+          [{ width: '142rpx' }, { width: '48rpx', height: '48rpx', type: 'circle' }],
+        ]"
+      />
+    </view>
+  </view>
+  <view v-else class="product-list-container">
     <ProductItem v-for="item in productList" :key="item.id" :product="item"></ProductItem>
   </view>
 </template>
 
 <script lang="ts" setup>
-  import { ProductSimpleType } from '@/types/product-type'
+  import { ProductSimpleType } from '@/model/product-type'
   import data from './data.json'
   import ProductItem from './product-item.vue'
 
   defineOptions({
     name: 'ProductList',
   })
+  withDefaults(defineProps<{ skeletonCount?: number; showSkeleton?: boolean }>(), {
+    skeletonCount: 2,
+  })
 
   const productList = ref<ProductSimpleType[]>(data)
 </script>
@@ -23,5 +38,17 @@
     flex-wrap: wrap;
     justify-content: space-between;
     padding-right: 32rpx;
+
+    .skeleton-item {
+      --wot-skeleton-row-margin-bottom: 16rpx;
+      display: flex;
+      justify-content: space-between;
+      width: 328rpx;
+      height: 488rpx;
+
+      &:nth-child(2n) {
+        margin-left: 30rpx;
+      }
+    }
   }
 </style>

+ 11 - 0
src/components/sku/sku.vue

@@ -0,0 +1,11 @@
+<template>
+  <view class="">商品SKU选择</view>
+</template>
+
+<script lang="ts" setup>
+  //
+</script>
+
+<style lang="scss" scoped>
+  //
+</style>

+ 28 - 0
src/directives/format.ts

@@ -0,0 +1,28 @@
+import { Directive } from 'vue'
+
+type FormatType = number | string
+
+export type FormatDirective = Directive<HTMLElement, FormatType>
+
+/**
+ * Format directive 格式化指令
+ * modifiers参数:
+ *  - date: 日期格式化
+ *  - price: 格式化价格
+ *  - rate: 评分格式化
+ * value: number 格式化小数点 string: 格式化日期
+ */
+export const vFormat: Directive<HTMLElement, FormatType> = {
+  mounted(el, { value, modifiers }) {
+    const { textContent } = el
+    if (modifiers.date) {
+      el.textContent = new Date(textContent).toLocaleDateString()
+    }
+    if (modifiers.price || modifiers.rate) {
+      if (!Number.isNaN(textContent)) {
+        const decimal = typeof value === 'number' ? value : modifiers.price ? 2 : 1
+        el.textContent = Number(textContent).toFixed(decimal)
+      }
+    }
+  },
+}

+ 6 - 0
src/directives/index.ts

@@ -0,0 +1,6 @@
+import { App } from 'vue'
+import { vFormat } from './format'
+
+export default function Directives(app: App) {
+  app.directive('format', vFormat)
+}

+ 2 - 0
src/main.ts

@@ -6,6 +6,7 @@ import App from './App.vue'
 import { prototypeInterceptor, requestInterceptor } from './interceptors'
 import i18n from './locale/index'
 import store from './store'
+import Directives from './directives'
 
 export function createApp() {
   const app = createSSRApp(App)
@@ -14,6 +15,7 @@ export function createApp() {
   app.use(requestInterceptor)
   app.use(prototypeInterceptor)
   app.use(VueQueryPlugin)
+  app.use(Directives)
 
   return {
     app,

+ 0 - 0
src/types/product-type.ts → src/model/product-type.ts


+ 0 - 0
src/types/user.ts → src/model/user.ts


+ 1 - 0
src/pages.json

@@ -78,6 +78,7 @@
       "type": "page",
       "layout": "tabbar",
       "style": {
+        "navigationStyle": "custom",
         "navigationBarTitleText": "%tabbar.cart%"
       }
     },

+ 10 - 1
src/pages/cart/cart.vue

@@ -2,10 +2,19 @@
 {
   layout: 'tabbar',
   style: {
+    navigationStyle: 'custom',
     navigationBarTitleText: '%tabbar.cart%',
   },
 }
 </route>
+<script setup lang="ts">
+  const { safeAreaInsets } = uni.getSystemInfoSync()
+</script>
 <template>
-  <view>购物车</view>
+  <view
+    class="pb-tab bg-white overflow-hidden box-border"
+    :style="{ marginTop: safeAreaInsets?.top + 'px' }"
+  >
+    购物车
+  </view>
 </template>

+ 7 - 5
src/pages/index/index.vue

@@ -42,7 +42,7 @@
     <view class="hot-category">
       <view class="home-title">
         <view class="home-title-text">{{ t('home.hotCategory') }}</view>
-        <view class="home-see-all">
+        <view @click="gotoCategory" class="home-see-all">
           <view class="see-all-text">{{ t('home.seeAll') }}</view>
           <image class="w-9rpx" src="@/static/images/right.svg" mode="widthFix"></image>
         </view>
@@ -57,10 +57,7 @@
     <view class="hot-selling">
       <view class="selling-title">
         <view class="selling-title-text">{{ t('home.hotSelling') }}</view>
-        <view class="selling-see-all">
-          <view class="selling-see-all-text">{{ t('home.seeAll') }}</view>
-          <image class="w-9rpx" src="@/static/images/right.svg" mode="widthFix"></image>
-        </view>
+        <view class="block"></view>
       </view>
       <HotTags v-model:current-tag="currentTag"></HotTags>
       <ProductList></ProductList>
@@ -85,6 +82,11 @@
   const current = ref(0)
   const currentTag = ref(0)
 
+  const gotoCategory = () => {
+    uni.switchTab({
+      url: '/pages/category/category',
+    })
+  }
   const swiperList = ref([
     'https://t.xiaoyaotravel.com/image/TourImComplait/messageContent/696b679508664bb4bceb6cc6b06d0cdc.png',
     'https://registry.npmmirror.com/wot-design-uni-assets/*/files/redpanda.jpg',

+ 1 - 1
src/store/user.ts

@@ -1,4 +1,4 @@
-import { UserInfo } from '@/types/user'
+import { UserInfo } from '@/model/user'
 import { http } from '@/utils/http'
 import { defineStore } from 'pinia'
 

+ 12 - 0
src/types/directives.d.ts

@@ -0,0 +1,12 @@
+/* eslint-disable */
+/// <reference types="vite/client" />
+import { FormatDirective } from '@/directives/format'
+
+// 关键:必须导入 'vue' 以合并类型
+import 'vue'
+
+declare module 'vue' {
+  interface ComponentCustomProperties {
+    vFormat: FormatDirective
+  }
+}

+ 1 - 0
src/typings.d.ts

@@ -1,4 +1,5 @@
 // 全局要用的类型放到这里
+import { ObjectDirective } from 'vue'
 
 declare global {
   type IResData<T> = {

+ 0 - 6
src/typings.ts

@@ -1,6 +0,0 @@
-// 枚举定义
-
-export enum TestEnum {
-  A = '1',
-  B = '2',
-}

+ 1 - 1
uno.config.ts

@@ -77,7 +77,7 @@ export default defineConfig({
     ['pt-safe', { 'padding-top': 'env(safe-area-inset-top)' }],
     ['pb-safe', { 'padding-bottom': 'env(safe-area-inset-bottom)' }],
     ['border', { border: '1rpx solid red' }],
-    ['pb-tab', { 'padding-bottom': '100rpx' }],
+    ['pb-tab', { 'padding-bottom': '144rpx' }],
   ],
 })