Files
consumer-front/pages/index/index.vue
T
2026-04-29 16:51:52 +08:00

178 lines
7.7 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<view class="app-container">
<!-- ========== 首页内容 ========== -->
<view v-if="currentTab === 'home'" class="page-content home-page">
<scroll-view
class="product-area"
scroll-y
>
<view class="section-title">热销商品</view>
<view class="product-grid" id="productGrid">
<view
v-for="(item, index) in productList"
:key="index"
class="product-card"
>
<image class="product-img" :src="item.image" mode="aspectFill" />
<view class="product-name">{{ item.name }}</view>
<view class="product-price">{{ item.price }}</view>
</view>
</view>
<!-- 底部占位防止被tab-bar遮挡 -->
<view class="bottom-spacer"></view>
</scroll-view>
<!-- 底部导航栏 -->
<view class="tab-bar">
<view class="tab-item" :class="{ active: currentTab === 'home' }" @click="switchTab('home')">
<text class="tab-text">首页</text>
</view>
<view class="door-btn-wrapper" @click="handleOpenDoor">
<view class="door-btn">开门</view>
</view>
<view class="tab-item" :class="{ active: currentTab === 'mine' }" @click="switchTab('mine')">
<text class="tab-text">我的</text>
</view>
</view>
</view>
<!-- ========== 我的内容 ========== -->
<view v-if="currentTab === 'mine'" class="page-content mine-page">
<!-- 蓝色个人信息区域 -->
<view class="user-header">
<view class="user-info">
<view class="avatar-wrapper">
<image class="avatar" :src="userInfo.avatar || '/static/default-avatar.png'" mode="aspectFill" />
</view>
<view class="user-detail">
<text class="nickname">{{ userInfo.nickname || '未登录' }}</text>
<text class="phone">{{ maskedPhone }}</text>
</view>
</view>
</view>
<!-- 菜单列表顶部 -->
<view class="content-area">
<view class="menu-list">
<view class="menu-item" v-for="(item, index) in menuList" :key="index" @click="handleMenuClick(item)">
<text class="menu-text">{{ item.title }}</text>
<text class="menu-arrow">></text>
</view>
</view>
</view>
<!-- 底部左右箭头导航条 -->
<page-nav-bar
:hasPrev="true"
:hasNext="false"
@prev="handleNavPrev"
@next="handleNavNext"
/>
</view>
</view>
</template>
<script>
import PageNavBar from '@/components/page-nav-bar/page-nav-bar.vue';
export default {
components: { PageNavBar },
data() {
return {
currentTab: 'home',
contentHeight: 0,
areaHeight: 0,
productList: [
{ name: '君乐宝450ml悦鲜活', price: '0.01', image: '/static/c1.png' },
{ name: '白红(0.0.0.0-9.9.9', price: '0.06', image: '/static/c2.png' },
{ name: '白桔(0.0.0.0-5.5.5', price: '0.05', image: '/static/c3.png' },
{ name: '可口可乐330ml', price: '3.00', image: '/static/c4.png' },
{ name: '农夫山泉550ml', price: '2.00', image: '/static/c5.png' },
{ name: '君乐宝450ml悦鲜活', price: '0.01', image: '/static/c1.png' },
{ name: '白红(0.0.0.0-9.9.9', price: '0.06', image: '/static/c2.png' },
{ name: '白桔(0.0.0.0-5.5.5', price: '0.05', image: '/static/c3.png' },
{ name: '可口可乐330ml', price: '3.00', image: '/static/c4.png' },
{ name: '农夫山泉550ml', price: '2.00', image: '/static/c5.png' },
{ name: '乐事薯片原味75g', price: '7.50', image: '/static/c6.png' }
],
userInfo: { nickname: '张三', phone: '13812345678' },
menuList: [
{ title: '我的订单', page: '/pages/order/order' },
{ title: '收货地址', page: '/pages/address/address' },
{ title: '常见问题', page: '/pages/faq/faq' }
]
};
},
computed: {
maskedPhone() {
const p = this.userInfo.phone;
return p ? p.substring(0,3) + '****' + p.substring(7) : '';
}
},
mounted() {},
methods: {
switchTab(tab) { this.currentTab = tab; },
handleOpenDoor() {
uni.showModal({ title: '开门', content: '确认打开柜门?', success: r => r.confirm && uni.showToast({title:'柜门已打开', icon:'success'}) });
},
handleMenuClick(item) {
if (item.page) {
uni.showToast({title:'功能开发中', icon:'none'});
}
},
handleNavPrev() {
this.currentTab = 'home';
},
handleNavNext() {
uni.showToast({ title: '暂无下一页', icon: 'none' });
}
}
};
</script>
<style scoped>
page { height: 100%; background-color: #fff; }
.app-container { display: flex; flex-direction: column; height: 100vh; background-color: #fff; }
.page-content { flex: 1; overflow: hidden; display: flex; flex-direction: column; position: relative; }
/* ====== 首页样式 ====== */
.home-page { display: flex; flex-direction: column; height: 100%; }
.product-area { flex: 1; overflow-y: auto; height: 0; }
.section-title { font-size: 36rpx; font-weight: bold; color: #333; padding: 24rpx 28rpx 16rpx; }
.product-grid { display: flex; flex-wrap: wrap; padding: 12rpx; gap: 12rpx; }
.product-card { width: calc((100% - 24rpx) / 3); text-align: center; }
.product-img { width: 100%; height: 220rpx; border-radius: 8rpx; background-color: #f0f0f0; }
.product-name { font-size: 24rpx; color: #333; padding: 10rpx 8rpx 6rpx; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.product-price { font-size: 30rpx; font-weight: bold; color: #e4393c; padding: 0 8rpx 16rpx; }
/* 底部占位:给tab-bar和开门按钮留出空间 */
.bottom-spacer { height: 160rpx; }
/* 底部导航栏 */
.tab-bar { position: absolute; bottom: 0; left: 0; right: 0; height: 120rpx; background: #fff; display: flex; align-items: center; justify-content: space-around; box-shadow: 0 -2rpx 16rpx rgba(0,0,0,0.08); z-index: 999; padding-bottom: constant(safe-area-inset-bottom); padding-bottom: env(safe-area-inset-bottom); }
.tab-item { flex: 1; display: flex; align-items: center; justify-content: center; height: 100%; }
.tab-text { font-size: 28rpx; color: #999; font-weight: normal; }
.tab-item.active .tab-text { color: #2979ff; }
.door-btn-wrapper { position: relative; display: flex; align-items: center; justify-content: center; margin-top: -80rpx; }
.door-btn { width: 160rpx; height: 160rpx; border-radius: 50%; background: linear-gradient(135deg, #2979ff, #1e60e0); color: #fff; font-size: 38rpx; font-weight: bold; display: flex; align-items: center; justify-content: center; box-shadow: 0 10rpx 36rpx rgba(41,121,255,0.55); }
/* ====== 我的页面样式 ====== */
.mine-page { background-color: #f5f5f5; position: relative; overflow-y: auto; }
.user-header { background: linear-gradient(135deg, #2979ff, #1e60e0); padding: 60rpx 40rpx; }
.user-info { display: flex; align-items: center; }
.avatar { width: 120rpx; height: 120rpx; border-radius: 50%; border: 4rpx solid rgba(255,255,255,0.8); background-color: #e0e0e0; }
.avatar-wrapper { margin-right: 30rpx; }
.user-detail { display: flex; flex-direction: column; flex: 1; }
.nickname { font-size: 36rpx; font-weight: bold; color: #fff; margin-bottom: 12rpx; }
.phone { font-size: 28rpx; color: rgba(255,255,255,0.9); }
.content-area { padding: 20rpx; padding-bottom: 140rpx; }
.menu-list { background-color: #fff; border-radius: 16rpx; overflow: hidden; }
.menu-item { display: flex; justify-content: space-between; padding: 32rpx 28rpx; border-bottom: 1rpx solid #f0f0f0; }
.menu-item:last-child { border-bottom: none; }
.menu-text { font-size: 30rpx; color: #333; }
.menu-arrow { font-size: 28rpx; color: #ccc; }
</style>