页面提交
This commit is contained in:
@@ -1,13 +1,184 @@
|
||||
<script lang="ts" setup>
|
||||
import { getBannerList } from '@/api/banner'
|
||||
import { getCategoryList } from '@/api/category'
|
||||
import { getRecommendGoods } from '@/api/goods'
|
||||
import type { Banner, Category, Goods } from '@/typings/mall'
|
||||
import SearchBar from '@/components/common/SearchBar.vue'
|
||||
import BannerComponent from '@/components/common/Banner.vue'
|
||||
import CategoryGrid from '@/components/common/CategoryGrid.vue'
|
||||
import GoodsCard from '@/components/goods/GoodsCard.vue'
|
||||
import { useCartStore } from '@/store/cart'
|
||||
|
||||
definePage({
|
||||
style: {
|
||||
navigationBarTitleText: '首页',
|
||||
},
|
||||
})
|
||||
|
||||
const cartStore = useCartStore()
|
||||
|
||||
// 数据
|
||||
const bannerList = ref<Banner[]>([])
|
||||
const categoryList = ref<Category[]>([])
|
||||
const goodsList = ref<Goods[]>([])
|
||||
const searchKeyword = ref('')
|
||||
|
||||
// 加载状态
|
||||
const loading = ref(false)
|
||||
|
||||
onMounted(() => {
|
||||
loadData()
|
||||
})
|
||||
|
||||
// 加载数据
|
||||
async function loadData() {
|
||||
loading.value = true
|
||||
try {
|
||||
// 并行加载数据
|
||||
const [bannerRes, categoryRes, goodsRes] = await Promise.all([
|
||||
getBannerList(),
|
||||
getCategoryList(),
|
||||
getRecommendGoods(10),
|
||||
])
|
||||
|
||||
bannerList.value = (bannerRes as any).data || []
|
||||
categoryList.value = (categoryRes as any).data || []
|
||||
goodsList.value = (goodsRes as any).data || []
|
||||
}
|
||||
catch (error) {
|
||||
console.error('加载数据失败', error)
|
||||
uni.showToast({
|
||||
title: '加载失败',
|
||||
icon: 'none',
|
||||
})
|
||||
}
|
||||
finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 搜索
|
||||
function handleSearch(keyword: string) {
|
||||
if (!keyword.trim()) {
|
||||
uni.showToast({
|
||||
title: '请输入搜索关键词',
|
||||
icon: 'none',
|
||||
})
|
||||
return
|
||||
}
|
||||
uni.navigateTo({
|
||||
url: `/pages/goods/list?keyword=${encodeURIComponent(keyword)}`,
|
||||
})
|
||||
}
|
||||
|
||||
// 下拉刷新
|
||||
function onPullDownRefresh() {
|
||||
loadData().finally(() => {
|
||||
uni.stopPullDownRefresh()
|
||||
})
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
onPullDownRefresh,
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<view class="mt-10 text-center text-green-500">
|
||||
首页
|
||||
<view class="index-page">
|
||||
<!-- 搜索框 -->
|
||||
<SearchBar
|
||||
v-model="searchKeyword"
|
||||
:show-cancel="false"
|
||||
@search="handleSearch"
|
||||
/>
|
||||
|
||||
<!-- 轮播图 -->
|
||||
<BannerComponent v-if="bannerList.length" :list="bannerList" />
|
||||
|
||||
<!-- 分类 -->
|
||||
<view class="section">
|
||||
<view class="section-title">商品分类</view>
|
||||
<CategoryGrid :list="categoryList" :columns="4" />
|
||||
</view>
|
||||
|
||||
<!-- 推荐商品 -->
|
||||
<view class="section">
|
||||
<view class="section-title">
|
||||
<text>为你推荐</text>
|
||||
<text class="more" @click="() => uni.switchTab({ url: '/pages/sort/index' })">
|
||||
更多
|
||||
<text class="i-carbon-chevron-right"></text>
|
||||
</text>
|
||||
</view>
|
||||
<view class="goods-list">
|
||||
<GoodsCard
|
||||
v-for="item in goodsList"
|
||||
:key="item.id"
|
||||
:goods="item"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 购物车角标 -->
|
||||
<view v-if="cartStore.totalCount > 0" class="cart-badge">
|
||||
{{ cartStore.totalCount > 99 ? '99+' : cartStore.totalCount }}
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.index-page {
|
||||
min-height: 100vh;
|
||||
background: #f5f5f5;
|
||||
padding-bottom: 120rpx;
|
||||
}
|
||||
|
||||
.section {
|
||||
margin-top: 24rpx;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 24rpx;
|
||||
font-size: 32rpx;
|
||||
font-weight: 600;
|
||||
color: #333;
|
||||
|
||||
.more {
|
||||
font-size: 24rpx;
|
||||
font-weight: 400;
|
||||
color: #999;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.goods-list {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: 16rpx;
|
||||
padding: 0 16rpx 16rpx;
|
||||
}
|
||||
|
||||
.cart-badge {
|
||||
position: fixed;
|
||||
bottom: 120rpx;
|
||||
right: 40rpx;
|
||||
width: 80rpx;
|
||||
height: 80rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: linear-gradient(135deg, #ff6b6b 0%, #ff4d4f 100%);
|
||||
color: #fff;
|
||||
font-size: 24rpx;
|
||||
font-weight: 600;
|
||||
border-radius: 50%;
|
||||
box-shadow: 0 4rpx 12rpx rgba(255, 77, 79, 0.4);
|
||||
z-index: 100;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user