refactor(components): 重构ElCard、FlipGrid、YifanSelector和PaymentPopup组件样式 refactor(pages): 优化地址管理、商品详情、订单列表、积分记录和活动页面UI style: 更新uni.scss全局样式变量和设计系统 docs: 添加说明文档记录UI优化进度
164 lines
3.6 KiB
Vue
164 lines
3.6 KiB
Vue
<template>
|
||
<view class="page">
|
||
<view class="bg-decoration"></view>
|
||
<view class="loading" v-if="loading">加载中...</view>
|
||
<view v-else-if="detail.id" class="detail-wrap">
|
||
<image v-if="detail.main_image" class="main-image" :src="detail.main_image" mode="widthFix" />
|
||
<view class="info-card">
|
||
<view class="title">{{ detail.title || detail.name || '-' }}</view>
|
||
<view class="price-row">
|
||
<text class="price">¥{{ formatPrice(detail.price_sale || detail.price) }}</text>
|
||
<text class="points" v-if="detail.points_required">{{ detail.points_required }}积分</text>
|
||
</view>
|
||
<view class="stock" v-if="detail.stock !== null && detail.stock !== undefined">库存:{{ detail.stock }}</view>
|
||
<view class="desc" v-if="detail.description">{{ detail.description }}</view>
|
||
</view>
|
||
</view>
|
||
<view v-else class="empty">商品不存在</view>
|
||
</view>
|
||
</template>
|
||
|
||
<script setup>
|
||
import { ref } from 'vue'
|
||
import { onLoad } from '@dcloudio/uni-app'
|
||
import { getProductDetail } from '../../api/appUser'
|
||
|
||
const detail = ref({})
|
||
const loading = ref(false)
|
||
|
||
function formatPrice(p) {
|
||
if (p === undefined || p === null) return '0.00'
|
||
return (Number(p) / 100).toFixed(2)
|
||
}
|
||
|
||
async function fetchDetail(id) {
|
||
loading.value = true
|
||
try {
|
||
const res = await getProductDetail(id)
|
||
detail.value = res || {}
|
||
} catch (e) {
|
||
detail.value = {}
|
||
} finally {
|
||
loading.value = false
|
||
}
|
||
}
|
||
|
||
onLoad((opts) => {
|
||
const id = opts && opts.id
|
||
if (id) fetchDetail(id)
|
||
})
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
/* ============================================
|
||
奇盒潮玩 - 商品详情页
|
||
============================================ */
|
||
|
||
.page {
|
||
min-height: 100vh;
|
||
background: $bg-page;
|
||
padding-bottom: env(safe-area-inset-bottom);
|
||
}
|
||
|
||
.loading, .empty {
|
||
text-align: center;
|
||
padding: 120rpx 40rpx;
|
||
color: $text-secondary;
|
||
font-size: $font-md;
|
||
}
|
||
|
||
.detail-wrap {
|
||
padding-bottom: 40rpx;
|
||
animation: fadeInUp 0.4s ease-out;
|
||
}
|
||
|
||
.main-image {
|
||
width: 100%;
|
||
height: 750rpx; /* Square aspect ratio */
|
||
display: block;
|
||
background: $bg-secondary;
|
||
box-shadow: $shadow-sm;
|
||
}
|
||
|
||
.info-card {
|
||
margin: $spacing-lg;
|
||
margin-top: -60rpx;
|
||
background: rgba(255, 255, 255, 0.95);
|
||
backdrop-filter: blur(20rpx);
|
||
border-radius: $radius-xl;
|
||
padding: $spacing-xl;
|
||
box-shadow: $shadow-lg;
|
||
position: relative;
|
||
z-index: 2;
|
||
}
|
||
|
||
.title {
|
||
font-size: $font-xl;
|
||
font-weight: 800;
|
||
color: $text-main;
|
||
margin-bottom: $spacing-md;
|
||
line-height: 1.4;
|
||
}
|
||
|
||
.price-row {
|
||
display: flex;
|
||
align-items: baseline;
|
||
gap: $spacing-sm;
|
||
margin-bottom: $spacing-lg;
|
||
}
|
||
|
||
.price {
|
||
font-size: $font-xxl;
|
||
font-weight: 900;
|
||
color: $brand-primary;
|
||
font-family: 'DIN Alternate', sans-serif;
|
||
|
||
&::before {
|
||
content: '¥';
|
||
font-size: $font-md;
|
||
margin-right: 4rpx;
|
||
}
|
||
}
|
||
|
||
.points {
|
||
font-size: $font-sm;
|
||
color: $brand-primary;
|
||
padding: 6rpx $spacing-md;
|
||
background: rgba($brand-primary, 0.1);
|
||
border-radius: 100rpx;
|
||
font-weight: 600;
|
||
}
|
||
|
||
.stock {
|
||
font-size: $font-sm;
|
||
color: $text-secondary;
|
||
margin-bottom: $spacing-lg;
|
||
background: $bg-secondary;
|
||
display: inline-block;
|
||
padding: 6rpx $spacing-md;
|
||
border-radius: $radius-sm;
|
||
}
|
||
|
||
.desc {
|
||
font-size: $font-lg;
|
||
color: $text-main;
|
||
line-height: 1.8;
|
||
padding-top: $spacing-lg;
|
||
border-top: 1rpx dashed $border-color-light;
|
||
|
||
&::before {
|
||
content: '商品详情';
|
||
display: block;
|
||
font-size: $font-md;
|
||
color: $text-secondary;
|
||
margin-bottom: $spacing-sm;
|
||
font-weight: 700;
|
||
}
|
||
}
|
||
|
||
@keyframes fadeInUp {
|
||
from { opacity: 0; transform: translateY(40rpx); }
|
||
to { opacity: 1; transform: translateY(0); }
|
||
}
|
||
</style>
|