feat: 优化UI设计并重构样式系统

refactor(components): 重构ElCard、FlipGrid、YifanSelector和PaymentPopup组件样式
refactor(pages): 优化地址管理、商品详情、订单列表、积分记录和活动页面UI
style: 更新uni.scss全局样式变量和设计系统
docs: 添加说明文档记录UI优化进度
This commit is contained in:
邹方成 2025-12-17 14:32:55 +08:00
parent dd12d8e500
commit 6f7207da2d
23 changed files with 3968 additions and 3932 deletions

45
App.vue
View File

@ -17,6 +17,49 @@
}
</script>
<style>
<style lang="scss">
/*每个页面公共css */
@import '@/uni.scss';
page {
background-color: $bg-page;
color: $text-main;
font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', Helvetica, Segoe UI, Arial, Roboto, 'PingFang SC', 'miui', 'Hiragino Sans GB', 'Microsoft Yahei', sans-serif;
}
.container {
padding: $spacing-lg;
}
/* Global Keyframes */
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
@keyframes fadeInDown {
from { opacity: 0; transform: translateY(-30rpx); }
to { opacity: 1; transform: translateY(0); }
}
@keyframes fadeInUp {
from { opacity: 0; transform: translateY(30rpx); }
to { opacity: 1; transform: translateY(0); }
}
@keyframes slideUp {
from { opacity: 0; transform: translateY(100%); }
to { opacity: 1; transform: translateY(0); }
}
@keyframes zoomIn {
from { opacity: 0; transform: scale(0.9); }
to { opacity: 1; transform: scale(1); }
}
@keyframes pulse {
0% { transform: scale(1); }
50% { transform: scale(1.05); }
100% { transform: scale(1); }
}
@keyframes float {
0% { transform: translateY(0); }
50% { transform: translateY(-20rpx); }
100% { transform: translateY(0); }
}
</style>

View File

@ -147,3 +147,19 @@ export function getShipments(user_id, page = 1, page_size = 20) {
export function getUserInvites(user_id, page = 1, page_size = 20) {
return authRequest({ url: `/api/app/users/${user_id}/invites`, method: 'GET', data: { page, page_size } })
}
// ============================================
// 兼容性适配接口 (适配 pages/mine/index.vue)
// ============================================
export function getUserInfo() {
const user_info = uni.getStorageSync('user_info')
if (user_info) return Promise.resolve(user_info)
return authRequest({ url: '/api/app/users/info', method: 'GET' })
}
export const getUserTasks = getTasks
export function getInviteRecords(page = 1, page_size = 20) {
const user_id = uni.getStorageSync('user_id')
return getUserInvites(user_id, page, page_size)
}

View File

@ -20,11 +20,36 @@ const shadowClass = computed(() => {
})
</script>
<style scoped>
.ep-card { background: #fff; border-radius: 12rpx; overflow: hidden; border: 1rpx solid #eee }
.is-always-shadow { box-shadow: 0 6rpx 16rpx rgba(0,0,0,0.06) }
.is-hover-shadow { box-shadow: 0 6rpx 16rpx rgba(0,0,0,0.06) }
.is-no-shadow { box-shadow: none }
.ep-card__header { padding: 12rpx 16rpx; border-bottom: 1rpx solid #f0f0f0 }
.ep-card__body { padding: 12rpx 16rpx }
<style lang="scss" scoped>
.ep-card {
background: $bg-card;
border: 1rpx solid $border-color-light;
border-radius: $radius-lg;
overflow: hidden;
transition: all 0.3s ease;
}
.is-always-shadow {
box-shadow: $shadow-sm;
}
.is-hover-shadow {
/* 在移动端hover效果不如PC明显这里可以处理为点击态 */
box-shadow: $shadow-sm;
}
.is-no-shadow {
box-shadow: none;
}
.ep-card__header {
padding: $spacing-sm $spacing-md;
border-bottom: 1rpx solid $border-color-light;
font-weight: 600;
color: $text-main;
}
.ep-card__body {
padding: $spacing-md;
}
</style>

View File

@ -24,7 +24,7 @@
</template>
<script setup>
import { ref, defineExpose } from 'vue'
import { ref } from 'vue'
const props = defineProps({ rewards: { type: Array, default: () => [] }, controls: { type: Boolean, default: true } })
const emit = defineEmits(['draw'])
@ -64,7 +64,7 @@ function onPreview(cell) {
defineExpose({ revealResults, reset })
</script>
<style scoped>
<style lang="scss" scoped>
/* ============================================
奇盒潮玩 - 翻牌动画组件
采用暖橙色调的开箱效果
@ -73,34 +73,40 @@ defineExpose({ revealResults, reset })
.flip-root {
display: flex;
flex-direction: column;
gap: 20rpx;
padding: 20rpx;
gap: $spacing-md;
padding: $spacing-md;
}
.flip-actions {
display: flex;
gap: 16rpx;
gap: $spacing-sm;
}
.flip-btn {
flex: 1;
background: linear-gradient(135deg, #FF9F43, #FF6B35) !important;
background: $gradient-brand !important;
color: #FFFFFF !important;
border-radius: 16rpx;
border-radius: $radius-md;
font-weight: 600;
box-shadow: 0 6rpx 16rpx rgba(255, 107, 53, 0.35);
}
.flip-btn:active {
box-shadow: $shadow-md;
border: none;
font-size: $font-md;
transition: all 0.2s ease;
&:active {
transform: scale(0.97);
box-shadow: $shadow-sm;
}
}
.flip-grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 16rpx;
gap: $spacing-sm;
background: rgba(255, 255, 255, 0.5);
backdrop-filter: blur(10rpx);
border-radius: 24rpx;
padding: 16rpx;
backdrop-filter: blur(10px);
border-radius: $radius-lg;
padding: $spacing-sm;
box-shadow: inset 0 0 20rpx rgba(255, 255, 255, 0.5);
}
.flip-card {
@ -124,7 +130,7 @@ defineExpose({ revealResults, reset })
width: 100%;
height: 100%;
backface-visibility: hidden;
border-radius: 16rpx;
border-radius: $radius-md;
overflow: hidden;
}
@ -133,15 +139,15 @@ defineExpose({ revealResults, reset })
display: flex;
align-items: center;
justify-content: center;
border: 2rpx solid rgba(255, 159, 67, 0.2);
box-shadow: 0 4rpx 12rpx rgba(255, 159, 67, 0.15);
border: 2rpx solid rgba($brand-primary, 0.2);
box-shadow: $shadow-sm;
}
.front-placeholder {
width: 60%;
height: 60%;
border-radius: 16rpx;
background: linear-gradient(135deg, rgba(255, 159, 67, 0.3), rgba(255, 107, 53, 0.2));
border-radius: $radius-md;
background: linear-gradient(135deg, rgba($brand-primary, 0.3), rgba($brand-primary-light, 0.2));
animation: pulse 2s ease-in-out infinite;
}
@keyframes pulse {
@ -150,28 +156,28 @@ defineExpose({ revealResults, reset })
}
.flip-back {
background: #FFFFFF;
background: $bg-card;
transform: rotateY(180deg);
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 16rpx;
border: 2rpx solid rgba(255, 159, 67, 0.3);
box-shadow: 0 8rpx 24rpx rgba(255, 107, 53, 0.2);
padding: $spacing-sm;
border: 2rpx solid rgba($brand-primary, 0.3);
box-shadow: $shadow-md;
}
.flip-image {
width: 75%;
border-radius: 12rpx;
margin-bottom: 8rpx;
border-radius: $radius-sm;
margin-bottom: $spacing-xs;
background: linear-gradient(145deg, #FFF8F3, #FFF4E6);
}
.flip-title {
font-size: 24rpx;
font-size: $font-xs;
font-weight: 600;
color: #1F2937;
color: $text-main;
text-align: center;
max-width: 90%;
word-break: break-all;
@ -184,13 +190,17 @@ defineExpose({ revealResults, reset })
}
.flip-reset {
background: linear-gradient(135deg, #FFD166, #FF9F43) !important;
background: linear-gradient(135deg, $accent-gold, $brand-primary-light) !important;
color: #6b4b1f !important;
border-radius: 999rpx;
font-weight: 600;
box-shadow: 0 6rpx 16rpx rgba(255, 159, 67, 0.35);
}
.flip-reset:active {
box-shadow: $shadow-sm;
font-size: $font-sm;
padding: 0 40rpx;
transition: all 0.2s ease;
&:active {
transform: scale(0.96);
}
}
</style>

View File

@ -133,7 +133,7 @@ function handleConfirm() {
}
</script>
<style scoped>
<style lang="scss" scoped>
/* ============================================
奇盒潮玩 - 支付弹窗组件
采用暖橙色调的底部弹窗设计
@ -153,11 +153,11 @@ function handleConfirm() {
.payment-popup-content {
width: 100%;
background: #FFFFFF;
border-radius: 32rpx 32rpx 0 0;
padding: 32rpx;
padding-bottom: calc(32rpx + constant(safe-area-inset-bottom));
padding-bottom: calc(32rpx + env(safe-area-inset-bottom));
background: $bg-card;
border-radius: $radius-xl $radius-xl 0 0;
padding: $spacing-lg;
padding-bottom: calc($spacing-lg + constant(safe-area-inset-bottom));
padding-bottom: calc($spacing-lg + env(safe-area-inset-bottom));
animation: slideUp 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}
@keyframes slideUp {
@ -168,10 +168,10 @@ function handleConfirm() {
.risk-warning {
background: linear-gradient(135deg, #FFF8F3, #FFF4E6);
color: #B45309;
font-size: 24rpx;
padding: 20rpx 24rpx;
border-radius: 16rpx;
margin-bottom: 24rpx;
font-size: $font-xs;
padding: $spacing-sm $spacing-md;
border-radius: $radius-md;
margin-bottom: $spacing-md;
display: flex;
align-items: center;
justify-content: center;
@ -182,7 +182,7 @@ function handleConfirm() {
}
.agreement-link {
color: #FF9F43;
color: $brand-primary;
font-weight: 500;
}
@ -190,13 +190,13 @@ function handleConfirm() {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 32rpx;
margin-bottom: $spacing-lg;
position: relative;
}
.popup-title {
font-size: 36rpx;
font-size: $font-lg;
font-weight: 700;
color: #1F2937;
color: $text-main;
}
.close-icon {
position: absolute;
@ -204,96 +204,96 @@ function handleConfirm() {
top: 50%;
transform: translateY(-50%);
font-size: 48rpx;
color: #9CA3AF;
color: $text-placeholder;
line-height: 1;
padding: 10rpx;
transition: color 0.2s ease;
}
.close-icon:active {
color: #6B7280;
color: $text-secondary;
}
.popup-body {
padding: 16rpx 0 24rpx;
padding: $spacing-sm 0 $spacing-md;
}
.amount-section {
text-align: center;
margin-bottom: 40rpx;
padding: 24rpx;
margin-bottom: $spacing-xl;
padding: $spacing-md;
background: linear-gradient(145deg, #FFFFFF, #FFF8F3);
border-radius: 20rpx;
border-radius: $radius-lg;
border: 1rpx solid rgba(255, 159, 67, 0.1);
}
.amount-section .label {
font-size: 28rpx;
color: #6B7280;
margin-right: 10rpx;
font-size: $font-sm;
color: $text-secondary;
margin-right: $spacing-xs;
}
.amount-section .amount {
font-size: 56rpx;
font-weight: 800;
background: linear-gradient(135deg, #FF6B35, #FF9F43);
background: $gradient-brand;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
.form-item {
margin-bottom: 24rpx;
margin-bottom: $spacing-md;
}
.form-item .label {
display: block;
font-size: 28rpx;
color: #1F2937;
font-size: $font-sm;
color: $text-main;
font-weight: 600;
margin-bottom: 16rpx;
margin-bottom: $spacing-xs;
}
.picker-display {
border: 2rpx solid #E5E7EB;
border-radius: 16rpx;
padding: 24rpx;
border: 2rpx solid $border-color-light;
border-radius: $radius-md;
padding: $spacing-md;
display: flex;
justify-content: space-between;
align-items: center;
font-size: 28rpx;
background: #F9FAFB;
font-size: $font-sm;
background: $bg-page;
transition: all 0.2s ease;
}
.picker-display:active {
border-color: #FF9F43;
border-color: $brand-primary;
background: #FFF8F3;
}
.selected-text {
color: #1F2937;
color: $text-main;
font-weight: 500;
}
.placeholder {
color: #9CA3AF;
color: $text-placeholder;
}
.arrow {
color: #9CA3AF;
color: $text-placeholder;
width: 16rpx;
height: 16rpx;
border-right: 3rpx solid #9CA3AF;
border-bottom: 3rpx solid #9CA3AF;
border-right: 3rpx solid $text-placeholder;
border-bottom: 3rpx solid $text-placeholder;
transform: rotate(-45deg);
margin-right: 8rpx;
margin-right: $spacing-xs;
}
.popup-footer {
display: flex;
gap: 20rpx;
margin-top: 16rpx;
gap: $spacing-md;
margin-top: $spacing-sm;
}
.btn-cancel, .btn-confirm {
flex: 1;
border: none;
border-radius: 24rpx;
font-size: 32rpx;
padding: 24rpx 0;
border-radius: $radius-lg;
font-size: $font-md;
padding: $spacing-md 0;
line-height: 1.5;
font-weight: 600;
transition: all 0.2s ease;
@ -302,19 +302,19 @@ function handleConfirm() {
border: none;
}
.btn-cancel {
color: #6B7280;
color: $text-secondary;
background: #F3F4F6;
}
.btn-cancel:active {
background: #E5E7EB;
background: $border-color-light;
}
.btn-confirm {
color: #FFFFFF;
background: linear-gradient(135deg, #FF9F43, #FF6B35);
box-shadow: 0 8rpx 24rpx rgba(255, 107, 53, 0.35);
background: $gradient-brand;
box-shadow: $shadow-lg;
}
.btn-confirm:active {
transform: scale(0.97);
box-shadow: 0 4rpx 12rpx rgba(255, 107, 53, 0.25);
box-shadow: $shadow-md;
}
</style>

View File

@ -290,62 +290,94 @@ async function onPaymentConfirm(paymentData) {
}
</script>
<style scoped>
<style lang="scss" scoped>
/* ============================================
奇盒潮玩 - 选号组件 (适配高级卡片布局)
============================================ */
/* 容器 - 去除背景,融入父级卡片 */
.choice-grid-container {
padding: 10rpx 0;
padding: $spacing-xs 0;
background: transparent;
}
/* 加载和空状态 */
.loading-state, .empty-state {
text-align: center;
padding: 60rpx 0;
color: #9CA3AF;
font-size: 26rpx;
padding: 80rpx 0;
color: $text-placeholder;
font-size: $font-sm;
display: flex;
flex-direction: column;
align-items: center;
gap: 20rpx;
&::before {
content: '📦';
font-size: 60rpx;
opacity: 0.5;
animation: float 3s ease-in-out infinite;
}
}
/* 网格包装 */
.grid-wrapper {
padding-bottom: 160rpx; /* 留出底部操作栏空间 */
padding-bottom: 200rpx; /* 留出底部操作栏空间 */
padding: 0 20rpx 200rpx;
}
/* 号码网格 - 8列布局 */
/* 号码网格 - 调整为更合理的列数,适配不同屏幕 */
.choices-grid {
display: grid;
grid-template-columns: repeat(8, 1fr);
gap: 10rpx;
padding: 0;
grid-template-columns: repeat(6, 1fr); /* 默认6列更大尺寸 */
gap: 16rpx;
padding: 10rpx 0;
animation: scaleIn 0.4s ease-out backwards;
}
/* 单个号码格子 */
.choice-item {
aspect-ratio: 1;
background: #F9FAFB;
border: 1rpx solid #E5E7EB;
border-radius: 12rpx;
background: $bg-card;
border: 1rpx solid $border-color-light;
border-radius: $radius-md;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
position: relative;
overflow: hidden;
transition: all 0.2s;
transition: all 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
box-shadow: $shadow-sm;
/* 票据孔装饰 */
&::before, &::after {
content: '';
position: absolute;
width: 8rpx;
height: 8rpx;
background: $bg-page; /* 与背景色一致 */
border-radius: 50%;
top: 50%;
transform: translateY(-50%);
opacity: 0.5;
}
&::before { left: -4rpx; }
&::after { right: -4rpx; }
}
.choice-item:active {
transform: scale(0.9);
transform: scale(0.92);
}
/* 号码文字 */
.choice-number {
font-size: 24rpx;
font-weight: 700;
color: #4B5563;
font-size: 28rpx;
font-weight: 800;
color: $text-sub;
z-index: 1;
font-family: 'DIN Alternate', sans-serif;
transition: color 0.2s;
}
/* 状态文字 - 简化为小点或隐藏 */
@ -357,65 +389,91 @@ async function onPaymentConfirm(paymentData) {
/* 可选状态 */
.is-available {
background: #F9FAFB;
background: #FFFFFF;
&:hover {
border-color: $brand-primary;
}
}
/* 已售状态 */
.is-sold {
background: #F3F4F6;
border-color: #F3F4F6;
color: $text-disabled;
border-color: $border-color-light;
background: $bg-secondary;
opacity: 0.8;
}
.is-sold::after {
content: '';
pointer-events: none;
&::before {
content: 'SOLD';
position: absolute;
width: 100%;
height: 100%;
background: rgba(0,0,0,0.05);
top: 50%;
left: 50%;
transform: translate(-50%, -50%) rotate(-30deg);
font-size: 20rpx;
font-weight: 900;
color: $text-disabled;
opacity: 0.2;
letter-spacing: 2rpx;
border: 2rpx solid $text-disabled;
padding: 2rpx 6rpx;
border-radius: 4rpx;
z-index: 0;
}
}
.is-sold .choice-number {
color: #D1D5DB;
text-decoration: line-through;
color: $text-disabled;
opacity: 0.3;
}
/* 选中状态 - 橙色高亮 */
.is-selected {
background: linear-gradient(135deg, #FF9F43, #FF6B35);
background: $gradient-brand;
border-color: transparent;
box-shadow: 0 4rpx 12rpx rgba(255, 107, 53, 0.4);
box-shadow: 0 8rpx 20rpx rgba($brand-primary, 0.3);
transform: scale(1.08);
z-index: 2;
&::before, &::after {
display: none; /* 选中状态隐藏票据孔 */
}
}
.is-selected .choice-number {
color: #FFFFFF;
text-shadow: 0 2rpx 4rpx rgba(0,0,0,0.1);
}
/* ============= 底部操作栏 ============= */
.action-bar {
position: fixed;
bottom: 30rpx;
bottom: calc(40rpx + env(safe-area-inset-bottom));
left: 30rpx;
right: 30rpx;
background: rgba(255, 255, 255, 0.95);
background: rgba($bg-card, 0.9);
backdrop-filter: blur(20rpx);
padding: 20rpx 30rpx;
box-shadow: 0 8rpx 32rpx rgba(0, 0, 0, 0.12);
box-shadow: $shadow-lg;
border-radius: 999rpx;
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
z-index: 100;
border: 1rpx solid rgba(255, 255, 255, 0.5);
border: 1rpx solid rgba($bg-card, 0.5);
animation: slideUp 0.4s ease-out backwards;
}
/* 选择信息行 */
.selection-info {
font-size: 26rpx;
color: #4B5563;
color: $text-main;
display: flex;
align-items: center;
font-weight: 600;
}
.highlight {
color: #FF6B35;
color: $brand-primary;
font-weight: 800;
font-size: 36rpx;
margin: 0 8rpx;
@ -424,30 +482,63 @@ async function onPaymentConfirm(paymentData) {
/* 按钮组 */
.action-buttons {
display: flex;
gap: 16rpx;
gap: 20rpx;
}
/* 通用按钮样式 */
.btn-common {
height: 72rpx;
line-height: 72rpx;
padding: 0 40rpx;
height: 80rpx;
line-height: 80rpx;
padding: 0 48rpx;
border-radius: 999rpx;
font-size: 28rpx;
font-weight: 600;
font-weight: 700;
margin: 0;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.2s;
&:active {
transform: scale(0.96);
}
}
/* 购买按钮 */
.btn-buy {
background: linear-gradient(135deg, #FF9F43, #FF6B35) !important;
background: $gradient-brand !important;
color: #FFFFFF !important;
box-shadow: 0 6rpx 16rpx rgba(255, 107, 53, 0.3);
box-shadow: 0 8rpx 20rpx rgba($brand-primary, 0.3);
/* 脉冲动画 */
animation: pulse 2s infinite;
}
/* 随机按钮 */
.btn-random {
background: #F3F4F6 !important;
color: #4B5563 !important;
background: $bg-secondary !important;
color: $text-main !important;
box-shadow: none;
border: 1rpx solid transparent;
&:active {
background: #E5E7EB !important;
}
}
@keyframes slideUp {
from { transform: translateY(100%); opacity: 0; }
to { transform: translateY(0); opacity: 1; }
}
@keyframes pulse {
0% { box-shadow: 0 0 0 0 rgba($brand-primary, 0.4); }
70% { box-shadow: 0 0 0 20rpx rgba($brand-primary, 0); }
100% { box-shadow: 0 0 0 0 rgba($brand-primary, 0); }
}
@keyframes float {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-10rpx); }
}
</style>

View File

@ -23,51 +23,60 @@
</view>
<view v-show="tabActive === 'pool'">
<view class="rewards" v-if="currentIssueId && rewardsMap[currentIssueId] && rewardsMap[currentIssueId].length">
<el-card v-for="rw in rewardsMap[currentIssueId]" :key="rw.id" class="el-reward-card" shadow="hover">
<template #header>
<view class="el-card-header">
<text class="el-card-title">{{ rw.title }}</text>
<view class="rewards-grid" v-if="currentIssueId && rewardsMap[currentIssueId] && rewardsMap[currentIssueId].length">
<view v-for="(rw, idx) in rewardsMap[currentIssueId]" :key="rw.id"
class="reward-card animate-stagger"
:style="{ '--delay': idx * 0.05 + 's' }">
<view class="card-header">
<text class="card-title">{{ rw.title }}</text>
<text v-if="rw.boss" class="badge-boss">BOSS</text>
</view>
</template>
<view class="card-image-wrap">
<image v-if="rw.image" class="card-image" :src="rw.image" mode="widthFix" />
<text class="prob-corner tl">概率 {{ rw.percent }}%</text>
<view class="image-wrapper">
<image v-if="rw.image" class="reward-image" :src="rw.image" mode="aspectFill" />
<text class="prob-tag absolute-tag">概率 {{ rw.percent }}%</text>
</view>
</el-card>
</view>
<view class="rewards-empty" v-else>暂无奖励配置</view>
</view>
<view class="empty-state" v-else>
<text class="empty-icon">📭</text>
<text class="empty-text">暂无奖励配置</text>
</view>
</view>
<view v-show="tabActive === 'records'">
<view class="records" v-if="winRecords.length">
<el-card v-for="it in winRecords" :key="it.id" class="el-reward-card" shadow="hover">
<template #header>
<view class="el-card-header">
<text class="el-card-title">{{ it.title }}</text>
<text v-if="it.count !== undefined" class="badge-count">x{{ it.count }}</text>
<view class="records-list" v-if="winRecords.length">
<view v-for="(it, idx) in winRecords" :key="it.id"
class="record-item animate-stagger"
:style="{ '--delay': idx * 0.05 + 's' }">
<image class="record-img" :src="it.image" mode="aspectFill" />
<view class="record-info">
<view class="record-title">{{ it.title }}</view>
<view class="record-meta">
<text class="record-count">x{{ it.count }}</text>
<text v-if="it.percent !== undefined">占比 {{ it.percent }}%</text>
</view>
</template>
<view class="card-image-wrap">
<image v-if="it.image" class="card-image" :src="it.image" mode="widthFix" />
<text v-if="it.percent !== undefined" class="prob-corner tl">占比 {{ it.percent }}%</text>
</view>
</el-card>
</view>
<view class="rewards-empty" v-else>暂无中奖记录</view>
</view>
<view class="empty-state" v-else>
<text class="empty-icon">📝</text>
<text class="empty-text">暂无中奖记录</text>
</view>
</view>
</view>
<view v-else class="issues-empty">暂无期数</view>
</view>
</scroll-view>
<view class="float-actions">
<button class="float-btn primary" @click="onParticipate">立即参与</button>
<view class="float-bar">
<button class="action-btn primary" @click="onParticipate">
立即参与
<view class="btn-shine"></view>
</button>
</view>
</template>
<script setup>
import { ref, computed, getCurrentInstance } from 'vue'
import { ref, computed } from 'vue'
import ElCard from '../../../components/ElCard.vue'
import { onLoad } from '@dcloudio/uni-app'
import { getActivityDetail, getActivityIssues, getActivityIssueRewards, drawActivityIssue, getActivityWinRecords } from '../../../api/appUser'
@ -241,21 +250,6 @@ function onIssueChange(e) {
currentIssueId.value = (cur && cur.id) || ''
}
async function ensureElCard() {
const inst = getCurrentInstance()
const app = inst && inst.appContext && inst.appContext.app
let comp = null
if (typeof window !== 'undefined' && window.ElementPlus && window.ElementPlus.ElCard) {
comp = window.ElementPlus.ElCard
} else {
comp = ElCard
}
if (app && !app.component('el-card')) app.component('el-card', comp)
}
function onPreviewBanner() {
const url = detail.value.banner || ''
if (url) uni.previewImage({ urls: [url], current: url })
@ -292,39 +286,369 @@ onLoad((opts) => {
})
</script>
<style scoped>
/* 奇盒潮玩 - 对对碰活动页面 */
.page { height: 100vh; padding-bottom: 140rpx; background: linear-gradient(180deg, #FFF8F3 0%, #FFFFFF 100%); }
.banner { padding: 24rpx }
.banner-img { width: 100%; border-radius: 20rpx; box-shadow: 0 12rpx 32rpx rgba(0, 0, 0, 0.1); }
.header { padding: 0 24rpx }
.title { font-size: 40rpx; font-weight: 800; background: linear-gradient(135deg, #FF6B35, #FF9F43); -webkit-background-clip: text; -webkit-text-fill-color: transparent; text-align: center; }
.meta { margin-top: 12rpx; font-size: 28rpx; color: #6B7280; text-align: center; }
.actions { display: flex; padding: 24rpx; gap: 16rpx }
.btn { flex: 1 }
.primary { background: linear-gradient(135deg, #FF9F43, #FF6B35) !important; color: #fff !important; box-shadow: 0 6rpx 20rpx rgba(255, 107, 53, 0.35); }
.float-actions { position: fixed; left: 0; right: 0; bottom: 0; padding: 20rpx 24rpx; padding-bottom: calc(20rpx + env(safe-area-inset-bottom)); background: rgba(255, 255, 255, 0.95); backdrop-filter: blur(20rpx); box-shadow: 0 -8rpx 24rpx rgba(0, 0, 0, 0.08); z-index: 9999 }
.float-btn { width: 100%; border-radius: 999rpx; background: linear-gradient(135deg, #FF9F43, #FF6B35) !important; color: #fff !important; font-weight: 600; box-shadow: 0 8rpx 24rpx rgba(255, 107, 53, 0.35); }
.issues { background: #FFFFFF; border-radius: 20rpx; margin: 0 24rpx 24rpx; padding: 20rpx; box-shadow: 0 8rpx 24rpx rgba(0, 0, 0, 0.06); }
.issues-title { font-size: 32rpx; font-weight: 700; color: #1F2937; margin-bottom: 16rpx; padding-left: 16rpx; position: relative; }
.issues-title::before { content: ''; position: absolute; left: 0; top: 50%; transform: translateY(-50%); width: 6rpx; height: 28rpx; background: linear-gradient(180deg, #FF9F43, #FF6B35); border-radius: 999rpx; }
.issue-picker { height: 200rpx; background: linear-gradient(145deg, #FFF8F3, #FFF4E6); border-radius: 16rpx; margin-bottom: 64rpx }
.picker-item { height: 40rpx; line-height: 40rpx; text-align: center; font-size: 28rpx; color: #1F2937; }
.tabs { display: flex; padding: 0 12rpx; margin-bottom: 20rpx; gap: 12rpx; }
.tab { flex: 1; text-align: center; font-size: 28rpx; padding: 18rpx 0; border: 2rpx solid rgba(255, 159, 67, 0.3); color: #B45309; background: linear-gradient(145deg, #FFFFFF, #FFF8F3); border-radius: 16rpx; font-weight: 500; transition: all 0.2s ease; }
.tab.active { background: linear-gradient(135deg, #FF9F43, #FF6B35); border-color: #FF6B35; color: #fff; font-weight: 600; box-shadow: 0 6rpx 16rpx rgba(255, 107, 53, 0.3); }
.rewards { width: 100%; margin-top: 24rpx }
.reward-card { background: #FFFFFF; border-radius: 16rpx; overflow: hidden; box-shadow: 0 8rpx 24rpx rgba(0, 0, 0, 0.06); margin-bottom: 16rpx }
.el-reward-card { margin-bottom: 16rpx }
.el-card-header { display: flex; align-items: center; justify-content: space-between }
.el-card-title { font-size: 28rpx; color: #1F2937; flex: 1; margin-right: 8rpx; word-break: break-all; font-weight: 600; }
.card-image-wrap { position: relative; padding-bottom: 48rpx }
.card-image { width: 100%; height: auto; display: block; background: linear-gradient(145deg, #FFF8F3, #FFF4E6); position: relative; z-index: 1 }
.prob-corner { position: absolute; background: linear-gradient(135deg, #FF6B35, #FF9F43); color: #fff; font-size: 22rpx; font-weight: 600; padding: 8rpx 16rpx; border-radius: 999rpx; z-index: 2; box-shadow: 0 4rpx 12rpx rgba(255, 107, 53, 0.35); }
.prob-corner.tl { top: 12rpx; left: 12rpx }
.card-body { display: flex; align-items: center; justify-content: space-between; padding: 16rpx }
.card-title { font-size: 28rpx; color: #1F2937; flex: 1; margin-right: 8rpx; word-break: break-all; font-weight: 600; }
.badge-boss { background: linear-gradient(135deg, #FF9F43, #FFD166); color: #6b4b1f; font-size: 22rpx; font-weight: 600; padding: 6rpx 14rpx; border-radius: 999rpx }
.badge-count { background: linear-gradient(135deg, #FFD166, #FFE8A3); color: #6b4b1f; font-size: 22rpx; font-weight: 600; padding: 6rpx 14rpx; border-radius: 999rpx }
.rewards-empty, .issues-empty { font-size: 26rpx; color: #9CA3AF; text-align: center; padding: 40rpx }
<style lang="scss" scoped>
/* ============================================
对对碰活动页面 - 高级设计重构 (SCSS Integration)
============================================ */
.page-container {
min-height: 100vh;
background: $bg-page;
position: relative;
overflow: hidden;
display: flex;
flex-direction: column;
}
/* 背景装饰 */
.bg-decoration {
position: absolute;
top: 0; left: 0; width: 100%; height: 100%;
z-index: 0;
pointer-events: none;
overflow: hidden;
}
.orb {
position: absolute;
border-radius: 50%;
filter: blur(80rpx);
opacity: 0.6;
}
.orb-1 {
width: 500rpx; height: 500rpx;
background: radial-gradient(circle, rgba($brand-primary, 0.2) 0%, transparent 70%);
top: -100rpx; left: -100rpx;
}
.orb-2 {
width: 600rpx; height: 600rpx;
background: radial-gradient(circle, rgba($accent-gold, 0.15) 0%, transparent 70%);
bottom: -100rpx; right: -100rpx;
}
.page-content {
flex: 1;
position: relative;
z-index: 1;
padding-bottom: calc(160rpx + env(safe-area-inset-bottom));
}
/* Banner */
.banner-wrapper {
margin: $spacing-md $spacing-lg;
border-radius: $radius-lg;
overflow: hidden;
box-shadow: $shadow-lg;
position: relative;
animation: fadeInDown 0.6s ease-out;
}
.banner-img {
width: 100%;
display: block;
}
.banner-shadow {
position: absolute;
bottom: 0; left: 0; width: 100%; height: 40%;
background: linear-gradient(to top, rgba(0,0,0,0.3), transparent);
}
/* Header */
.header-section {
padding: 0 $spacing-lg;
margin-bottom: $spacing-lg;
text-align: center;
animation: fadeIn 0.8s ease-out;
}
.title-row {
margin-bottom: $spacing-sm;
}
.title-text {
font-size: $font-xxl;
font-weight: 900;
background: $gradient-brand;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
display: inline-block;
}
.price-tag {
display: inline-flex;
align-items: baseline;
background: rgba($bg-card, 0.6);
padding: $spacing-xs $spacing-lg;
border-radius: $radius-round;
backdrop-filter: blur(20rpx);
box-shadow: $shadow-sm;
}
.price-label { font-size: $font-sm; color: $text-sub; margin-right: $spacing-xs; }
.price-symbol { font-size: $font-sm; color: $brand-primary; font-weight: 700; }
.price-value { font-size: $font-xl; color: $brand-primary; font-weight: 900; font-family: 'DIN Alternate', sans-serif; }
/* Glass Card */
.glass-card {
margin: 0 $spacing-lg $spacing-lg;
background: rgba($bg-card, 0.8);
backdrop-filter: blur(40rpx);
border-radius: $radius-xl;
padding: $spacing-lg;
box-shadow: $shadow-card;
border: 1rpx solid rgba(255, 255, 255, 0.6);
animation: fadeInUp 0.6s ease-out 0.2s backwards;
}
.section-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: $spacing-md;
padding: 0 4rpx;
}
.section-title {
font-size: $font-lg;
font-weight: 800;
color: $text-main;
position: relative;
padding-left: 20rpx;
&::before {
content: '';
position: absolute;
left: 0; top: 50%; transform: translateY(-50%);
width: 8rpx; height: 32rpx;
background: $gradient-brand;
border-radius: 4rpx;
}
}
.issue-indicator {
font-size: $font-sm;
color: $brand-primary;
background: rgba($brand-primary, 0.1);
padding: 4rpx $spacing-md;
border-radius: $radius-round;
font-weight: 600;
}
/* Custom Picker */
.custom-picker {
height: 280rpx;
background: rgba($bg-secondary, 0.5);
border-radius: $radius-lg;
margin-bottom: $spacing-lg;
overflow: hidden;
}
.picker-item {
height: 80rpx;
display: flex;
align-items: center;
justify-content: center;
gap: $spacing-md;
}
.picker-text { font-size: $font-lg; color: $text-main; font-weight: 600; }
.picker-status {
font-size: $font-xs; color: $text-sub; background: rgba(0,0,0,0.05); padding: 2rpx $spacing-sm; border-radius: $radius-sm;
&.status-active { background: #D1FAE5; color: #059669; }
}
/* Modern Tabs */
.modern-tabs {
display: flex;
background: $bg-secondary;
padding: 8rpx;
border-radius: $radius-lg;
margin-bottom: $spacing-lg;
}
.tab-item {
flex: 1;
text-align: center;
padding: $spacing-md 0;
font-size: $font-md;
color: $text-sub;
border-radius: $radius-md;
font-weight: 600;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
position: relative;
&.active {
background: #FFFFFF;
color: $brand-primary;
box-shadow: $shadow-sm;
}
}
.active-dot {
width: 8rpx; height: 8rpx;
background: $brand-primary;
border-radius: 50%;
position: absolute;
bottom: 8rpx; left: 50%; transform: translateX(-50%);
}
/* Rewards Grid */
.rewards-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: $spacing-lg;
}
.reward-card {
background: #FFFFFF;
border-radius: $radius-lg;
padding: $spacing-lg;
box-shadow: $shadow-sm;
border: 1rpx solid rgba(0,0,0,0.03);
display: flex;
flex-direction: column;
}
.card-header {
display: flex;
justify-content: space-between;
align-items: flex-start;
margin-bottom: $spacing-md;
height: 44rpx;
}
.card-title {
font-size: $font-md;
color: $text-main;
font-weight: 600;
flex: 1;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
margin-right: 8rpx;
}
.badge-boss {
font-size: $font-xs;
background: $gradient-gold;
color: #78350F;
padding: 2rpx $spacing-sm;
border-radius: $radius-sm;
font-weight: 800;
flex-shrink: 0;
}
.card-body {
flex: 1;
display: flex;
flex-direction: column;
}
.image-wrapper {
width: 100%;
padding-bottom: 100%;
position: relative;
background: $bg-secondary;
border-radius: $radius-md;
overflow: hidden;
margin-bottom: $spacing-sm;
}
.reward-image {
position: absolute;
top: 0; left: 0; width: 100%; height: 100%;
}
.prob-tag {
position: absolute;
top: 8rpx; left: 8rpx;
font-size: $font-xs;
color: #fff;
background: rgba(0,0,0,0.6);
backdrop-filter: blur(4rpx);
padding: 4rpx $spacing-sm;
border-radius: $radius-sm;
z-index: 2;
}
/* Records List */
.records-list {
display: flex;
flex-direction: column;
gap: $spacing-lg;
}
.record-item {
display: flex;
background: #FFFFFF;
padding: $spacing-lg;
border-radius: $radius-lg;
box-shadow: $shadow-sm;
align-items: center;
}
.record-img {
width: 100rpx; height: 100rpx;
border-radius: $radius-md;
background: $bg-secondary;
margin-right: $spacing-lg;
}
.record-info {
flex: 1;
}
.record-title {
font-size: $font-md;
font-weight: 600;
color: $text-main;
margin-bottom: $spacing-xs;
}
.record-meta {
display: flex;
gap: $spacing-md;
font-size: $font-sm;
color: $text-sub;
}
.record-count {
background: rgba($brand-primary, 0.1);
color: $brand-primary;
padding: 2rpx $spacing-sm;
border-radius: $radius-sm;
}
/* Empty State */
.empty-state {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 80rpx 0;
color: $text-placeholder;
}
.empty-icon { font-size: 80rpx; margin-bottom: $spacing-lg; opacity: 0.5; }
.empty-text { font-size: $font-md; }
/* Float Bar */
.float-bar {
position: fixed;
left: 0; right: 0; bottom: 0;
padding: $spacing-lg $spacing-xl;
padding-bottom: calc($spacing-lg + env(safe-area-inset-bottom));
background: rgba(255, 255, 255, 0.9);
backdrop-filter: blur(20px);
box-shadow: 0 -8rpx 30rpx rgba(0, 0, 0, 0.05);
z-index: 100;
animation: slideUp 0.4s ease-out backwards;
}
.action-btn {
height: 96rpx;
border-radius: $radius-round;
display: flex;
align-items: center;
justify-content: center;
font-size: $font-xl;
font-weight: 800;
position: relative;
overflow: hidden;
transition: all 0.2s;
&.primary {
background: $gradient-brand;
color: #fff;
box-shadow: $shadow-warm;
}
&:active { transform: scale(0.98); }
}
.btn-shine {
position: absolute;
top: 0; left: -100%; width: 50%; height: 100%;
background: linear-gradient(90deg, transparent, rgba(255,255,255,0.3), transparent);
transform: skewX(-20deg);
animation: shine 3s infinite;
}
/* Animation Utilities */
.animate-stagger {
animation: fadeInUp 0.5s ease-out backwards;
animation-delay: var(--delay, 0s);
}
</style>

View File

@ -139,36 +139,44 @@ onShareTimeline(() => {
})
</script>
<style scoped>
<style lang="scss" scoped>
.page {
min-height: 100vh;
background: #F8F8F8;
background: $bg-page;
display: flex;
flex-direction: column;
}
.content {
flex: 1;
padding: 24rpx;
padding: $spacing-lg;
}
.activity-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 20rpx;
gap: $spacing-md;
}
.activity-item {
background: #fff;
border-radius: 20rpx;
border-radius: $radius-lg;
overflow: hidden;
box-shadow: 0 8rpx 20rpx rgba(0,0,0,0.06);
box-shadow: $shadow-sm;
display: flex;
flex-direction: column;
transition: all 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94);
position: relative;
&:active {
transform: scale(0.98);
box-shadow: $shadow-xs;
}
}
.thumb-box {
position: relative;
width: 100%;
padding-top: 100%; /* 1:1 Aspect Ratio */
height: 0;
background: #f0f0f0;
background: $bg-secondary;
}
.thumb {
position: absolute;
@ -176,19 +184,27 @@ onShareTimeline(() => {
left: 0;
width: 100%;
height: 100%;
object-fit: cover;
background: linear-gradient(90deg, $bg-secondary 25%, #e8e8e8 50%, $bg-secondary 75%);
background-size: 200% 100%;
animation: shimmer 1.5s infinite;
}
.tag-hot {
position: absolute;
top: 12rpx; left: 12rpx;
background: #333;
color: #FFD700;
top: 16rpx; left: 16rpx;
background: rgba(255, 69, 58, 0.9);
color: #fff;
font-size: 20rpx;
padding: 4rpx 12rpx;
padding: 6rpx 14rpx;
border-radius: 8rpx;
font-weight: 800;
letter-spacing: 1rpx;
box-shadow: 0 4rpx 12rpx rgba(255, 69, 58, 0.3);
backdrop-filter: blur(4rpx);
}
.info {
padding: 20rpx 16rpx;
padding: 20rpx 20rpx;
display: flex;
flex-direction: column;
flex: 1;
@ -197,32 +213,42 @@ onShareTimeline(() => {
.name {
font-size: 28rpx;
font-weight: 700;
color: #1A1A1A;
margin-bottom: 20rpx;
color: $text-main;
margin-bottom: 16rpx;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
height: 76rpx;
line-height: 1.35;
line-height: 1.4;
height: 80rpx;
}
.bottom-row {
display: flex;
justify-content: space-between;
align-items: center;
align-items: flex-end;
}
.price-text {
font-size: 24rpx;
color: #FF4D4F;
font-weight: 700;
font-size: 22rpx;
color: $text-secondary;
max-width: 70%;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.btn-go {
background: #1A1A1A;
color: #FFD700;
font-size: 24rpx;
background: $brand-primary;
color: #fff;
font-size: 20rpx;
font-weight: 900;
padding: 8rpx 24rpx;
border-radius: 999rpx;
padding: 6rpx 20rpx;
border-radius: 100rpx;
box-shadow: 0 4rpx 10rpx rgba($brand-primary, 0.3);
transition: all 0.2s ease;
&:active {
transform: scale(0.9);
background: darken($brand-primary, 5%);
}
}
.loading-wrap {
@ -230,7 +256,8 @@ onShareTimeline(() => {
}
.spinner {
width: 48rpx; height: 48rpx;
border: 4rpx solid #ddd; border-top-color: #FF9F43;
border: 4rpx solid $border-color-light;
border-top-color: $brand-primary;
border-radius: 50%;
animation: spin 0.8s linear infinite;
}
@ -241,90 +268,35 @@ onShareTimeline(() => {
flex-direction: column;
align-items: center;
padding-top: 200rpx;
animation: fadeInUp 0.5s ease-out;
}
.empty-img {
width: 240rpx;
margin-bottom: 24rpx;
opacity: 0.4;
opacity: 0.5;
}
.empty-text {
color: #999;
color: $text-secondary;
font-size: 28rpx;
}
/* ============================================
活动列表 UX/UI 增强
动画增强
============================================ */
/* 入场动画 */
@keyframes fadeInUp {
from { opacity: 0; transform: translateY(30rpx); }
to { opacity: 1; transform: translateY(0); }
}
@keyframes shimmer {
0% { background-position: -200% 0; }
100% { background-position: 200% 0; }
}
@keyframes pulse {
0%, 100% { transform: scale(1); }
50% { transform: scale(1.05); }
}
@keyframes float {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-6rpx); }
}
/* 卡片交错入场 */
.activity-item:nth-child(1) { animation: fadeInUp 0.4s ease-out 0.1s both; }
.activity-item:nth-child(2) { animation: fadeInUp 0.4s ease-out 0.15s both; }
.activity-item:nth-child(3) { animation: fadeInUp 0.4s ease-out 0.2s both; }
.activity-item:nth-child(4) { animation: fadeInUp 0.4s ease-out 0.25s both; }
.activity-item:nth-child(n+5) { animation: fadeInUp 0.4s ease-out 0.3s both; }
/* 图片加载动画 */
.thumb {
background: linear-gradient(90deg, #f0f0f0 25%, #e8e8e8 50%, #f0f0f0 75%);
background-size: 200% 100%;
animation: shimmer 1.5s infinite;
@for $i from 1 through 10 {
.activity-item:nth-child(#{$i}) {
animation: fadeInUp 0.4s ease-out #{$i * 0.05}s both;
}
}
/* 热门标签浮动 */
.tag-hot {
animation: float 3s ease-in-out infinite;
background: linear-gradient(135deg, rgba(255,77,79,0.9), rgba(255,107,53,0.9));
color: #fff;
}
/* 卡片点击效果 */
.activity-item {
transition: all 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94);
}
.activity-item:active {
transform: scale(0.96) translateY(4rpx);
box-shadow: 0 4rpx 12rpx rgba(0,0,0,0.08);
}
/* GO 按钮脉冲 */
.btn-go {
animation: pulse 2s infinite;
transition: all 0.2s ease;
}
.btn-go:active {
animation: none;
transform: scale(0.9);
}
/* 增强加载器 */
.spinner {
border-width: 6rpx;
border-top-color: #FF6B35;
}
/* 空状态入场 */
.empty {
animation: fadeInUp 0.5s ease-out;
@keyframes fadeInUp {
from { opacity: 0; transform: translateY(20rpx); }
to { opacity: 1; transform: translateY(0); }
}
</style>

View File

@ -241,25 +241,71 @@ onLoad((opts) => {
})
</script>
<style scoped>
<style lang="scss" scoped>
/* ============================================
爬塔页面 - 沉浸式暗黑风格 (SCSS Integration)
============================================ */
$local-gold: #FFD700; //
.page-wrapper {
min-height: 100vh;
position: relative;
background: #2D1B4E; /* Dark Purple Theme */
color: #fff;
background: $bg-dark;
color: $text-dark-main;
display: flex;
flex-direction: column;
overflow: hidden;
}
/* 背景装饰 - 暗黑版 */
.bg-decoration {
position: absolute;
top: 0; left: 0; width: 100%; height: 100%;
pointer-events: none;
z-index: 0;
&::before {
content: '';
position: absolute;
top: -10%; left: -20%;
width: 600rpx; height: 600rpx;
background: radial-gradient(circle, rgba($brand-primary, 0.1) 0%, transparent 70%);
filter: blur(80rpx);
border-radius: 50%;
opacity: 0.6;
animation: float 10s ease-in-out infinite;
}
&::after {
content: '';
position: absolute;
bottom: 10%; right: -10%;
width: 500rpx; height: 500rpx;
background: radial-gradient(circle, rgba($local-gold, 0.08) 0%, transparent 70%);
filter: blur(60rpx);
border-radius: 50%;
opacity: 0.5;
animation: float 12s ease-in-out infinite reverse;
}
}
@keyframes float {
0%, 100% { transform: translate(0, 0); }
50% { transform: translate(20rpx, 30rpx); }
}
.bg-fixed {
position: absolute;
top: 0; left: 0; width: 100%; height: 100%;
opacity: 0.3;
z-index: 0;
filter: blur(8rpx);
}
.bg-mask {
position: absolute;
top: 0; left: 0; width: 100%; height: 100%;
background: linear-gradient(180deg, rgba(45,27,78,0.8), #2D1B4E);
background: linear-gradient(180deg, rgba($bg-dark, 0.85), $bg-dark 95%);
z-index: 1;
}
@ -269,23 +315,55 @@ onLoad((opts) => {
flex: 1;
display: flex;
flex-direction: column;
padding: 30rpx;
padding: $spacing-lg;
padding-top: calc(env(safe-area-inset-top) + 20rpx);
}
.header-section {
display: flex;
justify-content: space-between;
align-items: flex-start;
margin-bottom: 60rpx;
margin-bottom: $spacing-xl;
animation: fadeInDown 0.6s ease-out;
}
.title-box {
display: flex;
flex-direction: column;
}
.main-title {
font-size: 60rpx;
font-weight: 900;
font-style: italic;
display: block;
text-shadow: 0 4rpx 16rpx rgba(0,0,0,0.6);
background: linear-gradient(180deg, #fff, #b3b3b3);
-webkit-background-clip: text;
color: transparent;
letter-spacing: 2rpx;
}
.sub-title {
font-size: 26rpx;
opacity: 0.8;
margin-top: $spacing-xs;
display: block;
letter-spacing: 4rpx;
color: $brand-primary;
text-transform: uppercase;
}
.main-title { font-size: 48rpx; font-weight: 900; font-style: italic; display: block; }
.sub-title { font-size: 24rpx; opacity: 0.8; margin-top: 8rpx; display: block; }
.rule-btn {
background: rgba(255,255,255,0.1);
border: 1px solid rgba(255,255,255,0.2);
padding: 8rpx 24rpx;
border-radius: 999rpx;
border: 1px solid $border-dark;
padding: 12rpx 32rpx;
border-radius: 100rpx;
font-size: 24rpx;
backdrop-filter: blur(10rpx);
transition: all 0.2s;
color: rgba(255,255,255,0.9);
&:active {
background: rgba(255,255,255,0.25);
transform: scale(0.96);
}
}
.tower-container {
@ -294,81 +372,202 @@ onLoad((opts) => {
flex-direction: column;
justify-content: center;
align-items: center;
padding-bottom: 40rpx;
}
.tower-level {
width: 100%;
background: linear-gradient(135deg, #6D28D9, #4C1D95);
padding: 40rpx;
border-radius: 24rpx;
box-shadow: 0 8rpx 32rpx rgba(0,0,0,0.3);
background: $bg-dark-card;
backdrop-filter: blur(20rpx);
padding: 48rpx;
border-radius: $radius-xl;
box-shadow: 0 16rpx 40rpx rgba(0,0,0,0.3);
margin-bottom: 40rpx;
border: 2rpx solid rgba(255,255,255,0.1);
border: 1px solid $border-dark;
display: flex;
justify-content: space-between;
align-items: center;
position: relative;
overflow: hidden;
animation: zoomIn 0.5s ease-out backwards;
&::before {
content: '';
position: absolute;
top: 0; left: 0; right: 0; height: 1px;
background: linear-gradient(90deg, transparent, rgba(255,255,255,0.3), transparent);
}
&.current {
background: rgba($local-gold, 0.15);
border-color: rgba($local-gold, 0.5);
box-shadow: 0 0 40rpx rgba($local-gold, 0.15), inset 0 0 20rpx rgba($local-gold, 0.05);
}
}
.level-info { display: flex; flex-direction: column; z-index: 1; }
.level-num {
font-size: 24rpx;
color: $text-dark-sub;
margin-bottom: 8rpx;
text-transform: uppercase;
letter-spacing: 2rpx;
}
.level-name {
font-size: 48rpx;
font-weight: 700;
color: $text-dark-main;
text-shadow: 0 4rpx 8rpx rgba(0,0,0,0.3);
}
.level-status {
font-size: 24rpx;
background: linear-gradient(135deg, $local-gold, $brand-secondary);
color: #3e2723;
padding: 8rpx 20rpx;
border-radius: 12rpx;
font-weight: 800;
box-shadow: 0 4rpx 16rpx rgba($brand-secondary, 0.3);
z-index: 1;
}
.level-info { display: flex; flex-direction: column; }
.level-num { font-size: 24rpx; opacity: 0.8; margin-bottom: 8rpx; }
.level-name { font-size: 40rpx; font-weight: 700; }
.level-status { font-size: 24rpx; background: rgba(0,0,0,0.2); padding: 4rpx 12rpx; border-radius: 8rpx; }
.rewards-preview {
width: 100%;
margin-top: 40rpx;
}
.rewards-scroll {
white-space: nowrap;
width: 100%;
}
.reward-item {
display: inline-block;
display: inline-flex;
flex-direction: column;
align-items: center;
width: 160rpx;
margin-right: 20rpx;
text-align: center;
margin-right: 24rpx;
animation: fadeInUp 0.5s ease-out backwards;
@for $i from 1 through 5 {
&:nth-child(#{$i}) {
animation-delay: #{$i * 0.1}s;
}
}
}
.reward-img {
width: 120rpx; height: 120rpx;
border-radius: 16rpx;
background: rgba(255,255,255,0.1);
margin-bottom: 12rpx;
border-radius: 24rpx;
background: rgba(255,255,255,0.05);
margin-bottom: 16rpx;
border: 1px solid $border-dark;
box-shadow: 0 4rpx 12rpx rgba(0,0,0,0.2);
}
.reward-name {
font-size: 22rpx;
color: $text-dark-sub;
width: 100%;
text-align: center;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.reward-prob {
font-size: 20rpx;
color: $local-gold;
font-weight: 600;
margin-top: 4rpx;
}
.reward-name { font-size: 22rpx; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.reward-prob { font-size: 20rpx; color: #FFD700; }
.action-area {
background: rgba(0,0,0,0.4);
backdrop-filter: blur(20rpx);
padding: 30rpx;
border-radius: 32rpx;
background: $bg-dark-card;
backdrop-filter: blur(40rpx);
padding: 24rpx 32rpx;
border-radius: 100rpx;
display: flex;
align-items: center;
justify-content: space-between;
border: 1px solid $border-dark;
box-shadow: 0 20rpx 60rpx rgba(0,0,0,0.5);
margin-bottom: calc(env(safe-area-inset-bottom) + 20rpx);
animation: slideUp 0.6s ease-out backwards;
animation-delay: 0.3s;
}
.price-display {
display: flex;
align-items: baseline;
color: $local-gold;
font-weight: 700;
margin-left: 20rpx;
text-shadow: 0 0 20rpx rgba(255, 215, 0, 0.2);
}
.price-display { color: #FFD700; font-weight: 700; }
.currency { font-size: 28rpx; }
.amount { font-size: 48rpx; margin: 0 4rpx; }
.unit { font-size: 24rpx; opacity: 0.8; }
.amount { font-size: 48rpx; margin: 0 4rpx; font-family: 'DIN Alternate', sans-serif; }
.unit { font-size: 24rpx; opacity: 0.8; font-weight: normal; }
.challenge-btn {
background: linear-gradient(135deg, #FFD700, #F59E0B);
color: #333;
background: $gradient-brand;
color: #fff;
font-weight: 900;
border-radius: 999rpx;
border-radius: 100rpx;
padding: 0 60rpx;
height: 88rpx;
line-height: 88rpx;
font-size: 32rpx;
box-shadow: 0 8rpx 24rpx rgba(245, 158, 11, 0.4);
box-shadow: 0 8rpx 24rpx rgba(255, 107, 0, 0.3);
border: none;
position: relative;
overflow: hidden;
transition: all 0.2s;
&::after {
content: '';
position: absolute;
top: 0; left: -100%; width: 100%; height: 100%;
background: linear-gradient(90deg, transparent, rgba(255,255,255,0.3), transparent);
animation: shimmer 3s infinite;
}
&:active {
transform: scale(0.96);
box-shadow: 0 4rpx 12rpx rgba(255, 107, 0, 0.2);
}
}
.flip-overlay {
position: fixed; top: 0; left: 0; right: 0; bottom: 0; z-index: 999;
}
.flip-mask {
position: absolute; top: 0; bottom: 0; width: 100%; background: rgba(0,0,0,0.8);
position: absolute; top: 0; bottom: 0; width: 100%; background: rgba(0,0,0,0.85);
backdrop-filter: blur(10rpx);
animation: fadeIn 0.3s ease-out;
}
.flip-content {
position: relative; z-index: 2; height: 100%; display: flex; flex-direction: column; padding: 40rpx;
position: relative;
z-index: 2;
height: 100%;
display: flex;
flex-direction: column;
padding: 40rpx;
justify-content: center;
animation: zoomIn 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275);
}
.close-btn {
margin-top: auto;
background: #fff; color: #333; border-radius: 999rpx; font-weight: 700;
margin-top: 60rpx;
background: #fff;
color: #333;
border-radius: 100rpx;
font-weight: 700;
width: 50%;
height: 80rpx;
line-height: 80rpx;
align-self: center;
box-shadow: 0 10rpx 30rpx rgba(255,255,255,0.15);
transition: all 0.2s;
&:active {
transform: scale(0.95);
}
}
@keyframes shimmer {
0% { left: -100%; }
50%, 100% { left: 200%; }
}
</style>

View File

@ -1,4 +1,5 @@
<template>
<view class="bg-decoration"></view>
<scroll-view class="page" scroll-y>
<!-- 顶部 Banner -->
<view class="banner" v-if="detail.banner">
@ -75,8 +76,7 @@
</template>
<script setup>
import { ref, computed, getCurrentInstance } from 'vue'
import ElCard from '../../../components/ElCard.vue'
import { ref, computed } from 'vue'
import FlipGrid from '../../../components/FlipGrid.vue'
import { onLoad } from '@dcloudio/uni-app'
import PaymentPopup from '../../../components/PaymentPopup.vue'
@ -255,19 +255,6 @@ function nextIssue() {
currentIssueId.value = (cur && cur.id) || ''
}
async function ensureElCard() {
const inst = getCurrentInstance()
const app = inst && inst.appContext && inst.appContext.app
let comp = null
if (typeof window !== 'undefined' && window.ElementPlus && window.ElementPlus.ElCard) {
comp = window.ElementPlus.ElCard
} else {
comp = ElCard
}
if (app && !app.component('el-card')) app.component('el-card', comp)
}
function onPreviewBanner() {
const url = detail.value.banner || ''
if (url) uni.previewImage({ urls: [url], current: url })
@ -418,55 +405,358 @@ onLoad((opts) => {
fetchDetail(id)
fetchIssues(id)
}
ensureElCard()
})
function closeFlip() { showFlip.value = false }
</script>
<style scoped>
<style lang="scss" scoped>
/* 奇盒潮玩 - 无限赏活动页面 */
.page { height: 100vh; padding-bottom: 200rpx; background: linear-gradient(180deg, #FFF8F3 0%, #FFFFFF 100%); }
.banner { padding: 24rpx 24rpx 0; }
.banner-img { width: 100%; border-radius: 20rpx; box-shadow: 0 12rpx 32rpx rgba(0, 0, 0, 0.1); }
.page {
min-height: 100vh;
padding-bottom: calc(200rpx + env(safe-area-inset-bottom));
background: transparent;
position: relative;
z-index: 1;
}
.bg-decoration {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100vh;
background-color: $bg-page;
z-index: 0;
overflow: hidden;
pointer-events: none;
&::before, &::after {
content: '';
position: absolute;
border-radius: 50%;
filter: blur(80px);
opacity: 0.5;
}
&::before {
width: 600rpx;
height: 600rpx;
background: radial-gradient(circle, rgba($brand-primary, 0.12), transparent 70%);
top: -200rpx;
left: -200rpx;
animation: float 10s ease-in-out infinite;
}
&::after {
width: 500rpx;
height: 500rpx;
background: radial-gradient(circle, rgba($accent-gold, 0.15), transparent 70%);
bottom: 10%;
right: -100rpx;
animation: float 12s ease-in-out infinite reverse;
}
}
@keyframes float {
0%, 100% { transform: translate(0, 0); }
50% { transform: translate(30rpx, 50rpx); }
}
.banner {
padding: $spacing-lg $spacing-lg 0;
animation: fadeInDown 0.6s $ease-out;
}
.banner-img {
width: 100%;
border-radius: $radius-lg;
box-shadow: $shadow-lg;
}
/* 商品信息卡片 */
.product-card { margin: 20rpx 24rpx; background: #FFFFFF; border-radius: 20rpx; padding: 20rpx; box-shadow: 0 8rpx 24rpx rgba(0, 0, 0, 0.06); }
.product-info { display: flex; align-items: flex-start; gap: 16rpx; }
.product-thumb { width: 120rpx; height: 120rpx; border-radius: 16rpx; flex-shrink: 0; background: linear-gradient(145deg, #FFF8F3, #FFF4E6); }
.product-detail { flex: 1; min-width: 0; }
.product-name { font-size: 30rpx; font-weight: 700; color: #1F2937; margin-bottom: 8rpx; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.product-price { font-size: 34rpx; font-weight: 800; color: #FF6B35; }
.product-actions { display: flex; flex-direction: column; gap: 12rpx; }
.action-btn { background: linear-gradient(145deg, #FFFFFF, #FFF8F3); border: 2rpx solid rgba(255, 159, 67, 0.3); border-radius: 12rpx; padding: 10rpx 14rpx; font-size: 22rpx; color: #B45309; text-align: center; }
.action-btn:active { background: #FFF4E6; }
.product-card {
margin: $spacing-lg;
background: $bg-glass;
backdrop-filter: blur(20rpx);
border-radius: $radius-lg;
padding: $spacing-lg;
box-shadow: $shadow-card;
animation: fadeInUp 0.6s $ease-out 0.1s backwards;
border: 1rpx solid rgba(255, 255, 255, 0.6);
}
.product-info {
display: flex;
align-items: flex-start;
gap: $spacing-lg;
}
.product-thumb {
width: 140rpx;
height: 140rpx;
border-radius: $radius-md;
flex-shrink: 0;
background: $bg-page;
box-shadow: $shadow-inner;
}
.product-detail {
flex: 1;
min-width: 0;
}
.product-name {
font-size: $font-lg;
font-weight: 700;
color: $text-main;
margin-bottom: $spacing-sm;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
line-height: 1.4;
}
.product-price {
font-size: $font-xl;
font-weight: 800;
color: $brand-primary;
font-family: 'DIN Alternate', sans-serif;
}
.product-actions {
display: flex;
flex-direction: column;
gap: $spacing-sm;
}
.action-btn {
background: rgba($brand-primary, 0.05);
border: 1rpx solid rgba($brand-primary, 0.2);
border-radius: $radius-sm;
padding: $spacing-sm $spacing-lg;
font-size: $font-sm;
color: $brand-primary-dark;
text-align: center;
font-weight: 600;
transition: all $transition-fast;
}
.action-btn:active {
background: rgba($brand-primary, 0.1);
transform: scale(0.95);
}
/* 期号切换条 */
.issue-bar { display: flex; align-items: center; justify-content: center; gap: 20rpx; margin: 0 24rpx 20rpx; padding: 16rpx 20rpx; background: #FFFFFF; border-radius: 999rpx; box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.06); }
.nav-btn { width: 64rpx; height: 64rpx; border-radius: 50%; background: linear-gradient(135deg, #FF9F43, #FF6B35); color: #FFFFFF; display: flex; align-items: center; justify-content: center; font-size: 28rpx; padding: 0; margin: 0; line-height: 1; box-shadow: 0 4rpx 12rpx rgba(255, 107, 53, 0.3); }
.nav-btn:active { transform: scale(0.92); }
.issue-info { display: flex; flex-direction: column; align-items: center; gap: 4rpx; }
.issue-label { font-size: 28rpx; font-weight: 700; color: #1F2937; }
.issue-bar {
display: flex;
align-items: center;
justify-content: center;
gap: $spacing-lg;
margin: 0 $spacing-lg $spacing-lg;
padding: $spacing-md $spacing-lg;
background: $bg-glass;
backdrop-filter: blur(20rpx);
border-radius: $radius-round;
box-shadow: $shadow-sm;
animation: fadeInUp 0.6s $ease-out 0.2s backwards;
border: 1rpx solid rgba(255, 255, 255, 0.6);
}
.nav-btn {
width: 64rpx;
height: 64rpx;
border-radius: 50%;
background: $bg-page;
color: $text-sub;
display: flex;
align-items: center;
justify-content: center;
font-size: $font-sm;
padding: 0;
margin: 0;
line-height: 1;
transition: all $transition-fast;
border: none;
&:active {
background: darken($bg-page, 5%);
transform: scale(0.9);
}
}
.issue-info {
display: flex;
flex-direction: column;
align-items: center;
gap: 4rpx;
min-width: 200rpx;
}
.issue-label {
font-size: $font-lg;
font-weight: 700;
color: $text-main;
}
/* 玩法福利标签 */
.gameplay-tags { display: flex; gap: 12rpx; padding: 0 24rpx; margin-bottom: 20rpx; flex-wrap: wrap; }
.tag { padding: 10rpx 20rpx; border-radius: 999rpx; font-size: 22rpx; font-weight: 600; }
.tag-pool { background: linear-gradient(135deg, #10B981, #34D399); color: #FFFFFF; box-shadow: 0 4rpx 12rpx rgba(16, 185, 129, 0.3); }
.tag-drop { background: linear-gradient(135deg, #FF9F43, #FF6B35); color: #FFFFFF; box-shadow: 0 4rpx 12rpx rgba(255, 107, 53, 0.3); }
.tag-free { background: linear-gradient(135deg, #FFD166, #FF9F43); color: #6b4b1f; box-shadow: 0 4rpx 12rpx rgba(255, 159, 67, 0.3); }
.gameplay-tags {
display: flex;
gap: $spacing-md;
padding: 0 $spacing-lg;
margin-bottom: $spacing-lg;
flex-wrap: wrap;
animation: fadeInUp 0.6s $ease-out 0.3s backwards;
}
.tag {
padding: $spacing-sm $spacing-lg;
border-radius: $radius-round;
font-size: $font-sm;
font-weight: 600;
display: flex;
align-items: center;
box-shadow: $shadow-sm;
backdrop-filter: blur(4px);
}
.tag-pool {
background: $color-success;
color: #FFFFFF;
box-shadow: 0 4rpx 12rpx rgba($color-success, 0.3);
border: 1rpx solid rgba(255, 255, 255, 0.2);
}
.tag-drop {
background: $gradient-brand;
color: #FFFFFF;
box-shadow: 0 4rpx 12rpx rgba($brand-primary, 0.3);
border: 1rpx solid rgba(255, 255, 255, 0.2);
}
.tag-free {
background: $gradient-gold;
color: #FFFFFF;
box-shadow: 0 4rpx 12rpx rgba($accent-gold, 0.3);
text-shadow: 0 1rpx 2rpx rgba(0,0,0,0.1);
border: 1rpx solid rgba(255, 255, 255, 0.2);
}
/* 底部多档位抽赏按钮 */
.bottom-actions { position: fixed; left: 0; right: 0; bottom: 0; display: flex; gap: 12rpx; padding: 16rpx 24rpx; padding-bottom: calc(16rpx + env(safe-area-inset-bottom)); background: linear-gradient(180deg, rgba(255,255,255,0.95) 0%, #FFFFFF 100%); backdrop-filter: blur(20rpx); box-shadow: 0 -8rpx 24rpx rgba(0, 0, 0, 0.08); z-index: 999; }
.tier-btn { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; padding: 12rpx 8rpx; background: linear-gradient(135deg, #FFD166, #FF9F43); border-radius: 16rpx; box-shadow: 0 4rpx 12rpx rgba(255, 159, 67, 0.3); }
.tier-btn:active { transform: scale(0.95); }
.tier-price { font-size: 24rpx; font-weight: 700; color: #6b4b1f; }
.tier-label { font-size: 22rpx; color: #8a5a2b; margin-top: 4rpx; }
.tier-hot { background: linear-gradient(135deg, #FF9F43, #FF6B35); }
.tier-hot .tier-price, .tier-hot .tier-label { color: #FFFFFF; }
.bottom-actions {
position: fixed;
left: 0;
right: 0;
bottom: 0;
display: flex;
gap: $spacing-md;
padding: $spacing-lg $spacing-lg;
padding-bottom: calc($spacing-lg + env(safe-area-inset-bottom));
background: rgba(255, 255, 255, 0.9);
backdrop-filter: blur(20rpx);
box-shadow: 0 -8rpx 24rpx rgba(0, 0, 0, 0.08);
z-index: 999;
animation: slideUp $transition-slow $ease-out backwards;
border-top: 1rpx solid rgba(0,0,0,0.05);
}
.tier-btn {
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: $spacing-md $spacing-xs;
background: $bg-card;
border: 1rpx solid $border-color-light;
border-radius: $radius-lg;
box-shadow: $shadow-sm;
transition: all $transition-fast;
&:active {
transform: scale(0.95);
background: $bg-page;
}
}
.tier-price {
font-size: $font-lg;
font-weight: 800;
color: $text-main;
font-family: 'DIN Alternate', sans-serif;
}
.tier-label {
font-size: $font-xs;
color: $text-sub;
margin-top: 4rpx;
font-weight: 500;
}
.tier-hot {
background: $gradient-brand;
border: none;
box-shadow: $shadow-warm;
position: relative;
overflow: hidden;
.tier-price, .tier-label {
color: #fff;
}
&::after {
content: 'HOT';
position: absolute;
top: 0;
right: 0;
background: linear-gradient(135deg, $accent-red, #D32F2F);
color: #fff;
font-size: 18rpx;
font-weight: 800;
padding: 4rpx 10rpx;
border-bottom-left-radius: $radius-md;
box-shadow: -2rpx 2rpx 4rpx rgba(0,0,0,0.1);
}
&:active {
opacity: 0.9;
transform: scale(0.96);
}
}
.tier-hot .tier-price, .tier-hot .tier-label {
color: #FFFFFF;
}
/* 翻牌弹窗 */
.flip-overlay { position: fixed; left: 0; right: 0; top: 0; bottom: 0; z-index: 10000 }
.flip-mask { position: absolute; left: 0; right: 0; top: 0; bottom: 0; background: rgba(0,0,0,0.6); z-index: 1 }
.flip-content { position: relative; display: flex; flex-direction: column; height: 100%; padding: 24rpx; z-index: 2 }
.overlay-close { background: linear-gradient(135deg, #FFD166, #FF9F43) !important; color: #6b4b1f !important; border-radius: 999rpx; align-self: flex-end; font-weight: 600; box-shadow: 0 6rpx 16rpx rgba(255, 159, 67, 0.35); }
.flip-overlay {
position: fixed;
left: 0;
right: 0;
top: 0;
bottom: 0;
z-index: 10000;
animation: fadeIn 0.3s ease-out;
}
.flip-mask {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
background: rgba(0,0,0,0.8);
backdrop-filter: blur(10px);
z-index: 1;
}
.flip-content {
position: relative;
display: flex;
flex-direction: column;
height: 100%;
padding: 24rpx;
z-index: 2;
justify-content: center;
align-items: center;
animation: zoomIn 0.3s $ease-bounce;
}
.overlay-close {
margin-top: 60rpx;
width: 240rpx;
height: 88rpx;
line-height: 88rpx;
background: rgba(255,255,255,0.15) !important;
border: 1rpx solid rgba(255,255,255,0.3);
color: #FFFFFF !important;
border-radius: $radius-round;
font-weight: 600;
font-size: 30rpx;
backdrop-filter: blur(10px);
transition: all $transition-fast;
&:active {
background: rgba(255,255,255,0.25) !important;
transform: scale(0.95);
}
}
</style>

View File

@ -1,5 +1,11 @@
<template>
<view class="page-wrapper">
<!-- 背景装饰 -->
<view class="bg-decoration">
<view class="orb orb-1"></view>
<view class="orb orb-2"></view>
</view>
<!-- 顶部背景图模糊处理 -->
<view class="page-bg">
<image class="bg-image" :src="detail.banner" mode="aspectFill" />
@ -13,7 +19,7 @@
<scroll-view class="main-scroll" scroll-y>
<!-- 头部信息卡片 -->
<view class="header-card">
<view class="header-card animate-enter">
<image class="header-cover" :src="detail.banner" mode="aspectFill" />
<view class="header-info">
<view class="header-title">{{ detail.name || detail.title || '一番赏活动' }}</view>
@ -40,7 +46,7 @@
</view>
<!-- 赏品概览 -->
<view class="section-container" v-if="currentIssueRewards.length > 0">
<view class="section-container animate-enter stagger-1" v-if="currentIssueRewards.length > 0">
<view class="section-header">
<text class="section-title">赏品一览</text>
<text class="section-more">查看全部 ></text>
@ -55,7 +61,7 @@
</view>
<!-- 选号区域 -->
<view class="section-container selector-container">
<view class="section-container selector-container animate-enter stagger-2">
<!-- 期号切换 -->
<view class="issue-header">
<view class="issue-switch-btn" @click="prevIssue">
@ -99,8 +105,7 @@
</template>
<script setup>
import { ref, computed, getCurrentInstance } from 'vue'
import ElCard from '../../../components/ElCard.vue'
import { ref, computed } from 'vue'
import { onLoad } from '@dcloudio/uni-app'
import FlipGrid from '../../../components/FlipGrid.vue'
import YifanSelector from '@/components/YifanSelector.vue'
@ -313,17 +318,7 @@ function nextIssue() {
currentIssueId.value = (cur && cur.id) || ''
}
async function ensureElCard() {
const inst = getCurrentInstance()
const app = inst && inst.appContext && inst.appContext.app
let comp = null
if (typeof window !== 'undefined' && window.ElementPlus && window.ElementPlus.ElCard) {
comp = window.ElementPlus.ElCard
} else {
comp = ElCard
}
if (app && !app.component('el-card')) app.component('el-card', comp)
}
function onPreviewBanner() {
const url = detail.value.banner || ''
@ -373,38 +368,79 @@ onLoad((opts) => {
fetchIssues(id)
fetchWinRecords(id)
}
ensureElCard()
})
function closeFlip() { showFlip.value = false }
</script>
<style scoped>
<style lang="scss" scoped>
/* ============================================
一番赏页面 - 高级设计重构
一番赏页面 - 高级设计重构 (SCSS Integration)
============================================ */
.page-wrapper {
min-height: 100vh;
background: #F2F3F7;
background: $bg-page;
position: relative;
overflow: hidden;
}
/* 背景装饰 */
.bg-decoration {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 0;
pointer-events: none;
overflow: hidden;
}
.orb {
position: absolute;
border-radius: 50%;
filter: blur(80px);
opacity: 0.6;
}
.orb-1 {
width: 600rpx;
height: 600rpx;
background: radial-gradient(circle, rgba($brand-primary, 0.2), transparent 70%);
top: -200rpx;
left: -200rpx;
animation: float 10s ease-in-out infinite;
}
.orb-2 {
width: 500rpx;
height: 500rpx;
background: radial-gradient(circle, rgba($accent-gold, 0.2), transparent 70%);
bottom: 20%;
right: -100rpx;
animation: float 12s ease-in-out infinite reverse;
}
@keyframes float {
0%, 100% { transform: translate(0, 0); }
50% { transform: translate(30rpx, 50rpx); }
}
/* 顶部背景 */
.page-bg {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 600rpx;
height: 700rpx; /* 加高背景区域 */
z-index: 1;
}
.bg-image {
width: 100%;
height: 100%;
filter: blur(40rpx);
opacity: 0.8;
filter: blur(30rpx) brightness(0.9); /* 降低亮度提升文字对比度 */
transform: scale(1.1); /* 防止模糊边缘 */
}
.bg-mask {
position: absolute;
@ -412,7 +448,7 @@ function closeFlip() { showFlip.value = false }
left: 0;
width: 100%;
height: 100%;
background: linear-gradient(180deg, rgba(242,243,247,0.3) 0%, #F2F3F7 100%);
background: linear-gradient(180deg, rgba($bg-page, 0.2) 0%, $bg-page 90%, $bg-page 100%);
}
.main-scroll {
@ -423,83 +459,116 @@ function closeFlip() { showFlip.value = false }
/* 头部卡片 */
.header-card {
margin: 30rpx 24rpx;
background: rgba(255, 255, 255, 0.9);
backdrop-filter: blur(20rpx);
border-radius: 32rpx;
padding: 24rpx;
margin: $spacing-xl $spacing-lg;
background: rgba($bg-card, 0.85);
backdrop-filter: blur(24rpx);
border-radius: $radius-xl;
padding: $spacing-lg;
display: flex;
align-items: center;
box-shadow: 0 16rpx 40rpx rgba(0, 0, 0, 0.08);
box-shadow: $shadow-card;
border: 1rpx solid rgba(255, 255, 255, 0.6);
position: relative;
overflow: hidden;
/* 光泽效果 */
&::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 2rpx;
background: linear-gradient(90deg, transparent, rgba(255,255,255,0.8), transparent);
}
}
.header-cover {
width: 160rpx;
height: 160rpx;
border-radius: 20rpx;
margin-right: 24rpx;
background: #EEE;
box-shadow: 0 8rpx 16rpx rgba(0,0,0,0.1);
width: 180rpx;
height: 180rpx;
border-radius: $radius-md;
margin-right: $spacing-lg;
background: $bg-secondary;
box-shadow: $shadow-md;
flex-shrink: 0;
}
.header-info {
flex: 1;
display: flex;
flex-direction: column;
justify-content: center;
height: 180rpx;
}
.header-title {
font-size: 34rpx;
font-weight: 700;
color: #1A1A1A;
margin-bottom: 12rpx;
font-size: $font-xl;
font-weight: 800;
color: $text-main;
margin-bottom: $spacing-xs;
line-height: 1.3;
@include text-ellipsis(2);
}
.header-price-row {
display: flex;
align-items: baseline;
color: #FF6B35;
margin-bottom: 12rpx;
color: $brand-primary;
margin-bottom: $spacing-sm;
text-shadow: 0 2rpx 4rpx rgba($brand-primary, 0.1);
}
.price-symbol { font-size: 24rpx; font-weight: 600; }
.price-num { font-size: 40rpx; font-weight: 800; margin: 0 4rpx; }
.price-unit { font-size: 24rpx; color: #999; }
.price-symbol { font-size: $font-md; font-weight: 700; }
.price-num { font-size: $font-xxl; font-weight: 900; margin: 0 4rpx; font-family: 'DIN Alternate', sans-serif; }
.price-unit { font-size: $font-sm; color: $text-sub; margin-left: 4rpx; }
.header-tags {
display: flex;
gap: 12rpx;
gap: $spacing-xs;
flex-wrap: wrap;
}
.tag-item {
font-size: 20rpx;
color: #B45309;
background: #FFF4E6;
padding: 4rpx 12rpx;
border-radius: 6rpx;
font-size: $font-xs;
color: $brand-primary-dark;
background: rgba($brand-primary, 0.08);
padding: 4rpx $spacing-sm;
border-radius: $radius-sm;
font-weight: 600;
border: 1rpx solid rgba($brand-primary, 0.1);
}
.header-actions {
display: flex;
flex-direction: column;
gap: 20rpx;
gap: $spacing-lg;
margin-left: 20rpx;
padding-left: 20rpx;
border-left: 1rpx solid #EEE;
padding-left: $spacing-lg;
border-left: 1rpx solid rgba(0,0,0,0.06);
justify-content: center;
height: 140rpx;
}
.action-btn {
display: flex;
flex-direction: column;
align-items: center;
font-size: 20rpx;
color: #666;
font-size: $font-xs;
color: $text-sub;
transition: all 0.2s;
&:active {
transform: scale(0.9);
color: $text-main;
}
}
.action-btn .icon {
font-size: 32rpx;
margin-bottom: 4rpx;
font-size: $font-xl;
margin-bottom: 6rpx;
filter: grayscale(0.2);
}
/* 通用板块容器 */
.section-container {
margin: 24rpx;
background: #FFFFFF;
border-radius: 32rpx;
padding: 24rpx;
box-shadow: 0 8rpx 24rpx rgba(0, 0, 0, 0.04);
margin: 0 $spacing-lg $spacing-lg;
background: rgba(255, 255, 255, 0.9); /* 略微透明 */
border-radius: $radius-xl;
padding: $spacing-lg;
box-shadow: $shadow-sm;
backdrop-filter: blur(10rpx);
}
/* 板块标题 */
@ -507,66 +576,111 @@ function closeFlip() { showFlip.value = false }
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20rpx;
padding: 0 8rpx;
margin-bottom: 24rpx;
padding: 0 4rpx;
}
.section-title {
font-size: 30rpx;
font-weight: 700;
color: #1A1A1A;
font-size: $font-lg;
font-weight: 800;
color: $text-main;
position: relative;
padding-left: $spacing-lg;
&::before {
content: '';
position: absolute;
left: 0;
top: 50%;
transform: translateY(-50%);
width: 8rpx;
height: 28rpx;
background: $gradient-brand;
border-radius: 4rpx;
}
}
.section-more {
font-size: 24rpx;
color: #999;
font-size: $font-sm;
color: $text-tertiary;
display: flex;
align-items: center;
&::after {
content: '>';
font-family: monospace;
margin-left: 6rpx;
font-weight: 700;
}
}
/* 奖品概览 */
.preview-scroll {
white-space: nowrap;
margin: 0 -$spacing-lg; /* 负边距抵消padding */
padding: 0 $spacing-lg;
width: calc(100% + 40rpx);
}
.preview-item {
display: inline-block;
width: 180rpx;
margin-right: 20rpx;
width: 200rpx;
margin-right: $spacing-lg;
vertical-align: top;
position: relative;
transition: transform 0.2s;
&:active {
transform: scale(0.96);
}
&:last-child {
margin-right: 40rpx;
}
}
.preview-img {
width: 180rpx;
height: 180rpx;
border-radius: 20rpx;
background: #F8F8F8;
margin-bottom: 12rpx;
box-shadow: inset 0 0 0 1rpx rgba(0,0,0,0.03);
width: 200rpx;
height: 200rpx;
border-radius: $radius-lg;
background: $bg-secondary;
margin-bottom: $spacing-md;
box-shadow: $shadow-sm;
border: 1rpx solid rgba(0,0,0,0.03);
}
.preview-name {
font-size: 24rpx;
color: #333;
font-size: $font-sm;
color: $text-secondary;
width: 100%;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
text-align: center;
font-weight: 500;
}
.prize-tag {
position: absolute;
top: 8rpx;
left: 8rpx;
top: 10rpx;
left: 10rpx;
background: rgba(0,0,0,0.6);
color: #fff;
font-size: 18rpx;
padding: 2rpx 8rpx;
border-radius: 6rpx;
font-size: $font-xs;
padding: 4rpx $spacing-sm;
border-radius: $radius-sm;
z-index: 10;
font-weight: 700;
backdrop-filter: blur(4rpx);
transform: scale(0.9);
transform-origin: top left;
}
.prize-tag.tag-boss {
background: linear-gradient(135deg, #FF9F43, #FF6B35);
background: $gradient-brand;
box-shadow: 0 4rpx 12rpx rgba($brand-primary, 0.4);
}
/* 选号区容器 */
.selector-container {
min-height: 600rpx;
min-height: 800rpx;
display: flex;
flex-direction: column;
background: rgba($bg-card, 0.95);
backdrop-filter: blur(20rpx);
}
/* 期号头部 */
@ -574,46 +688,53 @@ function closeFlip() { showFlip.value = false }
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 24rpx;
background: #F9FAFB;
border-radius: 20rpx;
padding: 12rpx;
margin-bottom: 30rpx;
background: $bg-grey;
border-radius: $radius-round; /* 胶囊形 */
padding: 10rpx;
border: 1rpx solid $border-color-light;
}
.issue-switch-btn {
width: 64rpx;
height: 64rpx;
width: 72rpx;
height: 72rpx;
display: flex;
align-items: center;
justify-content: center;
background: #FFFFFF;
border-radius: 16rpx;
box-shadow: 0 2rpx 8rpx rgba(0,0,0,0.05);
background: $bg-card;
border-radius: 50%;
box-shadow: $shadow-sm;
transition: all 0.2s;
color: $text-secondary;
&:active {
transform: scale(0.9);
background: $bg-secondary;
color: $brand-primary;
}
.issue-switch-btn:active {
transform: scale(0.95);
background: #F0F0F0;
}
.arrow {
font-size: 24rpx;
color: #999;
font-size: $font-sm;
font-weight: 800;
}
.issue-info-center {
display: flex;
flex-direction: column;
align-items: center;
flex: 1;
}
.issue-current-text {
font-size: 30rpx;
font-size: $font-lg;
font-weight: 700;
color: #333;
color: $text-main;
}
.issue-status-badge {
font-size: 20rpx;
color: #10B981;
background: #D1FAE5;
padding: 2rpx 12rpx;
border-radius: 999rpx;
font-size: $font-xs;
color: $uni-color-success;
background: rgba($uni-color-success, 0.1);
padding: 2rpx $spacing-md;
border-radius: $radius-round;
margin-top: 4rpx;
font-weight: 600;
}
.selector-body {
@ -622,9 +743,61 @@ function closeFlip() { showFlip.value = false }
/* 翻牌弹窗 */
.flip-overlay { position: fixed; left: 0; right: 0; top: 0; bottom: 0; z-index: 10000; }
.flip-mask { position: absolute; left: 0; right: 0; top: 0; bottom: 0; background: rgba(0,0,0,0.6); z-index: 1; }
.flip-content { position: relative; display: flex; flex-direction: column; height: 100%; padding: 24rpx; z-index: 2; }
.overlay-close { background: linear-gradient(135deg, #FFD93D, #FFB800) !important; color: #6b4b1f !important; border-radius: 999rpx; align-self: flex-end; font-weight: 600; box-shadow: 0 6rpx 16rpx rgba(255, 184, 0, 0.35); }
.flip-mask {
position: absolute; left: 0; right: 0; top: 0; bottom: 0;
background: rgba(0,0,0,0.75);
backdrop-filter: blur(10rpx);
z-index: 1;
animation: fadeIn 0.3s ease-out;
}
.flip-content {
position: relative; display: flex; flex-direction: column; height: 100%; padding: 40rpx; z-index: 2;
animation: scaleIn 0.3s ease-out;
}
.overlay-close {
background: rgba(255,255,255,0.2) !important;
color: #FFFFFF !important;
border-radius: 999rpx;
align-self: center;
margin-top: 40rpx;
font-weight: 600;
border: 1rpx solid rgba(255,255,255,0.3);
padding: 10rpx 60rpx;
font-size: 30rpx;
backdrop-filter: blur(10rpx);
&:active {
background: rgba(255,255,255,0.3) !important;
}
}
/* 动画定义 */
.animate-enter {
animation: fadeInUp 0.6s cubic-bezier(0.2, 0.8, 0.2, 1) backwards;
}
.stagger-1 { animation-delay: 0.1s; }
.stagger-2 { animation-delay: 0.2s; }
.stagger-3 { animation-delay: 0.3s; }
@keyframes fadeInUp {
from {
opacity: 0;
transform: translateY(40rpx);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
@keyframes scaleIn {
from { opacity: 0; transform: scale(0.9); }
to { opacity: 1; transform: scale(1); }
}
</style>

View File

@ -148,16 +148,16 @@ onLoad((opts) => {
})
</script>
<style scoped>
<style lang="scss" scoped>
/* ============================================
奇盒潮玩 - 地址编辑页面
采用暖橙色调的表单设计
============================================ */
.wrap {
padding: 24rpx;
padding: $spacing-lg;
min-height: 100vh;
background: linear-gradient(180deg, #FFF8F3 0%, #FFFFFF 100%);
background: $bg-page;
}
/* 表单项 */
@ -165,59 +165,70 @@ onLoad((opts) => {
display: flex;
align-items: center;
background: #FFFFFF;
border-radius: 16rpx;
padding: 20rpx 24rpx;
margin-bottom: 16rpx;
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.04);
border-radius: $radius-lg;
padding: $spacing-lg $spacing-xl;
margin-bottom: $spacing-md;
box-shadow: $shadow-sm;
transition: all 0.2s;
&:focus-within {
box-shadow: $shadow-md;
transform: translateY(-2rpx);
}
}
.label {
width: 160rpx;
font-size: 28rpx;
font-weight: 500;
color: #6B7280;
font-size: $font-md;
font-weight: 600;
color: $text-main;
flex-shrink: 0;
}
.input {
flex: 1;
font-size: 28rpx;
color: #1F2937;
font-size: $font-md;
color: $text-main;
background: transparent;
height: 48rpx;
}
/* 提交按钮 */
.submit {
width: 100%;
height: 88rpx;
line-height: 88rpx;
margin-top: 32rpx;
background: linear-gradient(135deg, #FF9F43, #FF6B35) !important;
height: 96rpx;
line-height: 96rpx;
margin-top: 60rpx;
background: $gradient-brand !important;
color: #FFFFFF !important;
border-radius: 44rpx;
font-size: 32rpx;
font-weight: 600;
border-radius: $radius-round;
font-size: $font-lg;
font-weight: 800;
border: none;
box-shadow: 0 8rpx 24rpx rgba(255, 107, 53, 0.35);
box-shadow: $shadow-warm;
transition: all 0.2s ease;
&:active {
transform: scale(0.96);
box-shadow: none;
}
.submit:active {
transform: scale(0.97);
box-shadow: 0 4rpx 12rpx rgba(255, 107, 53, 0.25);
}
.submit[disabled] {
&[disabled] {
opacity: 0.6;
box-shadow: none;
background: $text-disabled !important;
}
}
/* 错误提示 */
.error {
color: #EF4444;
font-size: 26rpx;
margin-top: 16rpx;
padding: 16rpx;
background: rgba(239, 68, 68, 0.1);
border-radius: 12rpx;
color: $color-error;
font-size: $font-sm;
margin-top: $spacing-lg;
padding: $spacing-md;
background: rgba($color-error, 0.1);
border-radius: $radius-md;
text-align: center;
font-weight: 500;
}
</style>

View File

@ -113,33 +113,33 @@ onLoad(() => {
})
</script>
<style scoped>
<style lang="scss" scoped>
/* ============================================
奇盒潮玩 - 地址管理页面
采用暖橙色调的卡片列表设计
============================================ */
.wrap {
padding: 24rpx;
padding: $spacing-md;
min-height: 100vh;
background: linear-gradient(180deg, #FFF8F3 0%, #FFFFFF 100%);
background-color: $bg-page;
}
.header {
display: flex;
justify-content: flex-end;
margin-bottom: 20rpx;
margin-bottom: $spacing-lg;
}
.add {
font-size: 28rpx;
background: linear-gradient(135deg, #FF9F43, #FF6B35) !important;
font-size: $font-md;
background: $gradient-brand !important;
color: #FFFFFF !important;
border-radius: 999rpx;
padding: 0 32rpx;
border-radius: $radius-round;
padding: 0 $spacing-xl;
height: 72rpx;
line-height: 72rpx;
font-weight: 600;
box-shadow: 0 6rpx 16rpx rgba(255, 107, 53, 0.35);
box-shadow: $shadow-warm;
}
.add:active {
transform: scale(0.96);
@ -148,49 +148,56 @@ onLoad(() => {
/* 地址卡片 */
.addr {
background: #FFFFFF;
border-radius: 20rpx;
padding: 24rpx;
margin-bottom: 16rpx;
box-shadow: 0 8rpx 24rpx rgba(0, 0, 0, 0.06);
border-radius: $radius-md;
padding: $spacing-lg;
margin-bottom: $spacing-md;
box-shadow: $shadow-sm;
animation: fadeInUp 0.4s ease-out backwards;
}
@for $i from 1 through 10 {
.addr:nth-child(#{$i}) {
animation-delay: #{$i * 0.05}s;
}
}
.addr-main {
margin-bottom: 16rpx;
margin-bottom: $spacing-md;
}
.addr-row {
display: flex;
align-items: center;
margin-bottom: 12rpx;
margin-bottom: $spacing-sm;
}
.addr-row:last-child {
margin-bottom: 0;
}
.name {
font-size: 30rpx;
font-size: $font-lg;
font-weight: 600;
color: #1F2937;
color: $text-main;
}
.phone {
font-size: 28rpx;
color: #6B7280;
font-size: $font-md;
color: $text-sub;
}
.default {
font-size: 22rpx;
font-size: $font-xs;
color: #FFFFFF;
background: linear-gradient(135deg, #FF9F43, #FF6B35);
padding: 4rpx 12rpx;
border-radius: 999rpx;
background: $gradient-brand;
padding: 4rpx $spacing-sm;
border-radius: $radius-round;
font-weight: 500;
}
.region {
font-size: 26rpx;
color: #6B7280;
font-size: $font-sm;
color: $text-sub;
}
.detail {
font-size: 26rpx;
color: #1F2937;
font-size: $font-md;
color: $text-main;
line-height: 1.5;
}
@ -198,47 +205,66 @@ onLoad(() => {
.addr-actions {
display: flex;
justify-content: flex-end;
gap: 12rpx;
margin-top: 16rpx;
padding-top: 16rpx;
border-top: 1rpx solid #F3F4F6;
gap: $spacing-md;
margin-top: $spacing-lg;
padding-top: $spacing-lg;
border-top: 1rpx solid $border-color-light;
}
.addr-actions button {
font-size: 26rpx;
height: 56rpx;
line-height: 56rpx;
padding: 0 24rpx;
border-radius: 28rpx;
font-size: $font-sm;
height: 52rpx;
line-height: 52rpx;
padding: 0 $spacing-lg;
border-radius: $radius-round;
margin: 0;
font-weight: 600;
border: none;
background: $bg-secondary;
color: $text-main;
&::after { border: none; }
&:active {
transform: scale(0.96);
background: darken($bg-secondary, 5%);
}
}
.addr-actions button[type="warn"] {
background: #FEE2E2 !important;
color: #EF4444 !important;
background: rgba($color-error, 0.1) !important;
color: $color-error !important;
}
.addr-actions button:not([type]) {
background: #F3F4F6 !important;
color: #6B7280 !important;
}
.addr-actions button:not([type]):active {
background: #E5E7EB !important;
background: $bg-secondary !important;
color: $text-main !important;
}
/* 空状态 */
.empty {
text-align: center;
color: #9CA3AF;
color: $text-sub;
margin-top: 120rpx;
font-size: 28rpx;
font-size: $font-md;
}
/* 错误提示 */
.error {
color: #EF4444;
font-size: 26rpx;
margin-bottom: 16rpx;
padding: 16rpx;
background: rgba(239, 68, 68, 0.1);
border-radius: 12rpx;
color: $color-error;
font-size: $font-sm;
margin-bottom: $spacing-md;
padding: $spacing-md;
background: rgba($color-error, 0.1);
border-radius: $radius-md;
text-align: center;
}
@keyframes fadeInUp {
from {
opacity: 0;
transform: translateY(20rpx);
}
to {
opacity: 1;
transform: translateY(0);
}
}
</style>

View File

@ -680,242 +680,251 @@ async function onShip() {
}
</script>
<style scoped>
<style lang="scss" scoped>
/* ============================================
奇盒潮玩 - 货柜页面
采用暖橙色调物品卡片式布局
采用现代卡片式布局统一设计语言
============================================ */
.item-status {
font-size: 24rpx;
color: #FF9F43;
margin-top: 4rpx;
font-weight: 500;
}
.item-meta {
font-size: 22rpx;
color: #9CA3AF;
margin-top: 4rpx;
}
.wrap {
padding: 24rpx;
padding: 0;
min-height: 100vh;
background: linear-gradient(180deg, #FFF8F3 0%, #FFFFFF 100%);
background: $bg-page;
padding-bottom: calc(180rpx + env(safe-area-inset-bottom));
display: flex;
flex-direction: column;
}
/* Tab 切换 */
/* 顶部 Tab */
.tabs {
position: fixed;
top: 0;
left: 0;
right: 0;
height: 88rpx;
background: rgba($bg-card, 0.9);
backdrop-filter: blur(20rpx);
display: flex;
background: #FFFFFF;
border-radius: 20rpx;
padding: 8rpx;
margin-bottom: 24rpx;
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.06);
align-items: center;
justify-content: center;
z-index: 100;
box-shadow: $shadow-sm;
padding: 0;
margin: 0;
border-radius: 0;
}
.tab-item {
position: relative;
flex: 1;
text-align: center;
font-size: 28rpx;
color: #6B7280;
padding: 20rpx 0;
border-radius: 16rpx;
transition: all 0.25s ease;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
gap: 8rpx;
}
.tab-item.active {
background: linear-gradient(135deg, #FF9F43, #FF6B35);
color: #FFFFFF;
font-weight: 600;
box-shadow: 0 6rpx 20rpx rgba(255, 107, 53, 0.35);
}
.tab-text {
justify-content: center;
font-size: 28rpx;
color: $text-sub;
transition: all 0.3s;
padding: 0;
border-radius: 0;
&.active {
color: $brand-primary;
font-weight: 700;
font-size: 30rpx;
background: transparent;
box-shadow: none;
&::after {
content: '';
position: absolute;
bottom: 0;
left: 50%;
transform: translateX(-50%);
width: 40rpx;
height: 4rpx;
background: $brand-primary;
border-radius: 4rpx;
}
}
}
.tab-count {
font-size: 24rpx;
opacity: 0.85;
margin-left: 8rpx;
font-size: 20rpx;
background: rgba($brand-primary, 0.1);
padding: 2rpx 10rpx;
border-radius: 20rpx;
color: $brand-primary;
opacity: 1;
}
/* 操作栏 */
/* 状态提示 */
.status-text {
padding-top: 200rpx;
text-align: center;
color: $text-tertiary;
font-size: 28rpx;
margin-top: 0;
}
.loading-more, .no-more {
text-align: center;
padding: 30rpx;
color: $text-tertiary;
font-size: 24rpx;
}
/* Tab 0: 待处理列表 */
.action-bar {
margin-top: 108rpx; /* 88rpx tabs + 20rpx spacing */
padding: 0 $spacing-lg;
margin-bottom: 20rpx;
display: flex;
align-items: center;
margin-bottom: 20rpx;
padding: 0 8rpx;
}
.select-all {
display: flex;
align-items: center;
font-size: 28rpx;
color: #1F2937;
font-weight: 500;
color: $text-main;
}
.select-all .checkbox {
margin-right: 12rpx;
}
.header {
font-size: 32rpx;
font-weight: 700;
color: #1F2937;
margin-bottom: 24rpx;
}
.status-text {
text-align: center;
color: #9CA3AF;
margin-top: 120rpx;
font-size: 28rpx;
}
/* 物品列表 */
.inventory-grid {
padding: 0 $spacing-lg;
margin-top: 108rpx; /* default margin if no action bar */
display: flex;
flex-direction: column;
gap: 16rpx;
gap: 20rpx;
}
/* Adjust margin if action bar exists */
.action-bar + .inventory-grid {
margin-top: 0;
}
.inventory-item {
background: #FFFFFF;
border-radius: 20rpx;
background: $bg-card;
border-radius: $radius-lg;
padding: 24rpx;
margin-bottom: 0; /* handled by gap */
display: flex;
flex-direction: row;
align-items: center;
box-shadow: 0 8rpx 24rpx rgba(0, 0, 0, 0.06);
box-shadow: $shadow-sm;
border: 1rpx solid rgba(0,0,0,0.02);
transition: all 0.2s ease;
animation: fadeInUp 0.4s ease-out backwards;
@for $i from 1 through 10 {
&:nth-child(#{$i}) {
animation-delay: #{$i * 0.05}s;
}
.inventory-item:active {
}
&:active {
transform: scale(0.98);
}
}
.checkbox-area {
padding: 20rpx 20rpx 20rpx 0;
}
.checkbox {
width: 40rpx;
height: 40rpx;
border: 2rpx solid $text-tertiary;
border-radius: 50%;
transition: all 0.2s;
&.checked {
background: $brand-primary;
border-color: $brand-primary;
position: relative;
box-shadow: 0 0 10rpx rgba($brand-primary, 0.3);
&::after {
content: '';
position: absolute;
top: 50%;
left: 50%;
width: 18rpx;
height: 10rpx;
border-left: 3rpx solid #fff;
border-bottom: 3rpx solid #fff;
transform: translate(-50%, -65%) rotate(-45deg);
}
}
}
.item-image {
width: 140rpx;
height: 140rpx;
margin-right: 24rpx;
border-radius: 16rpx;
background: linear-gradient(145deg, #FFF8F3, #FFF4E6);
border-radius: $radius-md;
background: $bg-page;
flex-shrink: 0;
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.06);
margin-right: 0; /* reset old margin */
}
.item-info {
flex: 1;
text-align: left;
margin-left: 24rpx;
display: flex;
flex-direction: column;
justify-content: center;
justify-content: space-between;
height: 140rpx;
text-align: left; /* reset old text-align */
}
.item-name {
font-size: 28rpx;
color: #1F2937;
font-weight: 600;
display: block;
margin-bottom: 8rpx;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
color: $text-main;
@include text-ellipsis(2);
margin-bottom: 0; /* reset old margin */
}
.item-count {
font-size: 24rpx;
color: #9CA3AF;
margin-bottom: 4rpx;
}
.item-price {
font-size: 26rpx;
color: #FF6B35;
font-size: 24rpx;
color: $brand-primary;
margin-top: 8rpx;
font-weight: 600;
}
/* 复选框 */
.checkbox-area {
padding: 10rpx 20rpx 10rpx 0;
display: flex;
align-items: center;
}
.checkbox {
width: 44rpx;
height: 44rpx;
border: 3rpx solid #E5E7EB;
border-radius: 50%;
position: relative;
transition: all 0.2s ease;
}
.checkbox.checked {
background: linear-gradient(135deg, #FF9F43, #FF6B35);
border-color: #FF9F43;
box-shadow: 0 4rpx 12rpx rgba(255, 107, 53, 0.35);
}
.checkbox.checked::after {
content: '';
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -60%) rotate(45deg);
width: 12rpx;
height: 22rpx;
border-right: 4rpx solid #fff;
border-bottom: 4rpx solid #fff;
}
/* 数量步进器 */
.item-actions {
margin-top: 12rpx;
margin-top: auto;
display: flex;
justify-content: flex-end;
align-items: center;
}
.item-count {
font-size: 28rpx;
color: $text-main;
font-weight: 600;
}
.stepper {
display: flex;
align-items: center;
background: #F9FAFB;
border: 2rpx solid #E5E7EB;
border-radius: 12rpx;
height: 52rpx;
overflow: hidden;
background: $bg-page;
border-radius: $radius-sm;
padding: 4rpx;
height: auto; /* reset old height */
border: none; /* reset old border */
}
.step-btn {
width: 52rpx;
height: 100%;
width: 56rpx;
height: 56rpx;
display: flex;
align-items: center;
justify-content: center;
background: transparent;
font-size: 32rpx;
color: #6B7280;
transition: all 0.15s ease;
}
.step-btn:active {
background: #FFF4E6;
color: #FF6B35;
}
color: $text-main;
background: transparent;
.step-btn.minus { border-right: 2rpx solid #E5E7EB; }
.step-btn.plus { border-left: 2rpx solid #E5E7EB; }
&.minus { color: $text-sub; border: none; }
&.plus { color: $brand-primary; border: none; }
&:active { opacity: 0.6; background: transparent !important; transform: scale(0.9); }
}
.step-num {
width: 64rpx;
min-width: 60rpx;
text-align: center;
font-size: 28rpx;
font-weight: 600;
color: #1F2937;
color: $text-main;
}
/* 底部操作栏 */
@ -924,411 +933,227 @@ async function onShip() {
bottom: 0;
left: 0;
right: 0;
height: 110rpx;
background: #FFFFFF;
background: rgba($bg-card, 0.95);
backdrop-filter: blur(20rpx);
padding: 20rpx 30rpx calc(20rpx + env(safe-area-inset-bottom));
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 24rpx;
box-shadow: 0 -4rpx 20rpx rgba(0, 0, 0, 0.08);
z-index: 100;
padding-bottom: constant(safe-area-inset-bottom);
padding-bottom: env(safe-area-inset-bottom);
box-shadow: 0 -4rpx 20rpx rgba(0,0,0,0.05);
z-index: 99;
height: auto; /* reset old height */
animation: slideUp 0.3s ease-out;
}
.selected-info {
font-size: 28rpx;
color: #1F2937;
color: $text-main;
font-weight: 600;
}
.btn-group {
display: flex;
gap: 16rpx;
gap: 20rpx;
}
.action-btn {
margin: 0;
height: 72rpx;
line-height: 72rpx;
padding: 0 40rpx;
border-radius: $radius-round;
font-size: 28rpx;
font-weight: 600;
border-radius: 36rpx;
padding: 0 36rpx;
border: none;
transition: all 0.2s ease;
}
.action-btn:active {
transform: scale(0.95);
}
display: flex;
align-items: center;
justify-content: center;
transition: all 0.2s;
margin: 0;
line-height: 1; /* reset line-height */
&:active { transform: scale(0.96); }
}
.btn-ship {
background: linear-gradient(135deg, #FFD166, #FF9F43);
color: #6b4b1f;
box-shadow: 0 6rpx 16rpx rgba(255, 159, 67, 0.35);
background: rgba($brand-primary, 0.1);
color: $brand-primary;
box-shadow: none; /* reset shadow */
}
.btn-redeem {
background: linear-gradient(135deg, #FF9F43, #FF6B35);
color: #FFFFFF;
box-shadow: 0 6rpx 16rpx rgba(255, 107, 53, 0.35);
background: $gradient-brand;
color: #fff;
box-shadow: $shadow-warm;
animation: none; /* reset animation */
}
.loading-more, .no-more {
text-align: center;
color: #9CA3AF;
padding: 24rpx 0;
font-size: 26rpx;
}
.bottom-spacer {
height: 130rpx;
height: calc(130rpx + constant(safe-area-inset-bottom));
height: calc(130rpx + env(safe-area-inset-bottom));
}
/* ============================================
发货单卡片样式
============================================ */
/* Tab 1: 已申请发货 */
.shipment-list {
padding: 0 $spacing-lg;
margin-top: 108rpx;
display: flex;
flex-direction: column;
gap: 24rpx;
}
.shipment-card {
background: #FFFFFF;
border-radius: 24rpx;
padding: 28rpx;
box-shadow: 0 8rpx 32rpx rgba(0, 0, 0, 0.08);
background: $bg-card;
border-radius: $radius-lg;
padding: 30rpx;
margin-bottom: 0; /* handled by gap */
box-shadow: $shadow-sm;
border: 1rpx solid rgba(0,0,0,0.02);
animation: fadeInUp 0.4s ease-out backwards;
}
/* 发货单头部 */
.shipment-header {
display: flex;
justify-content: space-between;
align-items: flex-start;
align-items: center;
margin-bottom: 24rpx;
padding-bottom: 20rpx;
border-bottom: 1rpx solid #F3F4F6;
border-bottom: 1rpx solid rgba(0,0,0,0.05);
}
.shipment-batch {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 12rpx;
}
.batch-label {
font-size: 28rpx;
font-weight: 700;
color: #1F2937;
color: $text-main;
}
.batch-no {
font-size: 22rpx;
color: #9CA3AF;
font-size: 24rpx;
color: $text-sub;
font-family: monospace;
}
.count-badge {
background: linear-gradient(135deg, #FFF4E6, #FFEDD5);
color: #FF6B35;
font-size: 22rpx;
font-weight: 600;
padding: 6rpx 16rpx;
border-radius: 20rpx;
font-size: 20rpx;
color: $brand-primary;
background: rgba($brand-primary, 0.1);
padding: 2rpx 10rpx;
border-radius: 8rpx;
}
/* 发货状态标签 */
.shipment-status {
font-size: 24rpx;
font-weight: 600;
padding: 8rpx 20rpx;
border-radius: 16rpx;
flex-shrink: 0;
padding: 4rpx 16rpx;
border-radius: 20rpx;
&.status-pending { background: #FFF7E6; color: #FA8C16; }
&.status-shipped { background: #E6F7FF; color: #1890FF; }
&.status-delivered { background: #F6FFED; color: #52C41A; }
&.status-cancelled { background: #F5F5F5; color: #999; }
}
.status-pending {
background: #FEF3C7;
color: #D97706;
}
.status-shipped {
background: #DBEAFE;
color: #2563EB;
}
.status-delivered {
background: #D1FAE5;
color: #059669;
}
.status-cancelled {
background: #FEE2E2;
color: #DC2626;
}
/* 商品缩略图 */
.product-thumbnails {
margin-bottom: 20rpx;
margin-bottom: 24rpx;
}
.thumb-scroll {
display: flex;
align-items: center;
gap: 16rpx;
margin-bottom: 16rpx;
overflow-x: auto;
}
.thumb-img {
width: 120rpx;
height: 120rpx;
border-radius: 16rpx;
background: linear-gradient(145deg, #FFF8F3, #FFF4E6);
width: 100rpx;
height: 100rpx;
border-radius: $radius-sm;
background: $bg-page;
flex-shrink: 0;
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.06);
border: 1rpx solid rgba(0,0,0,0.05);
}
.thumb-more {
width: 120rpx;
height: 120rpx;
border-radius: 16rpx;
background: linear-gradient(135deg, #F9FAFB, #F3F4F6);
width: 100rpx;
height: 100rpx;
border-radius: $radius-sm;
background: $bg-page;
display: flex;
align-items: center;
justify-content: center;
font-size: 28rpx;
color: $text-sub;
font-size: 24rpx;
font-weight: 600;
color: #6B7280;
flex-shrink: 0;
}
/* 商品名称列表 */
.product-names {
display: flex;
flex-wrap: wrap;
gap: 8rpx 16rpx;
font-size: 24rpx;
color: $text-sub;
line-height: 1.4;
display: block; /* reset flex */
}
.product-name-item {
font-size: 24rpx;
color: #6B7280;
background: #F9FAFB;
padding: 6rpx 14rpx;
border-radius: 8rpx;
max-width: 200rpx;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
margin-right: 12rpx;
background: transparent; /* reset bg */
padding: 0;
&:not(:last-child)::after {
content: '、';
}
}
.product-name-more {
font-size: 24rpx;
color: #FF6B35;
font-weight: 500;
}
/* 物流信息 */
.shipment-express {
background: $bg-page;
border-radius: $radius-md;
padding: 16rpx;
display: flex;
align-items: center;
background: linear-gradient(135deg, #F0F9FF, #E0F2FE);
border-radius: 16rpx;
padding: 20rpx;
margin-bottom: 16rpx;
margin-bottom: 20rpx;
}
.express-icon {
width: 48rpx;
height: 48rpx;
width: 60rpx;
height: 60rpx;
background: #fff;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: 32rpx;
margin-right: 16rpx;
}
.express-info {
flex: 1;
display: flex;
flex-direction: column;
gap: 4rpx;
}
.express-company {
font-size: 26rpx;
font-weight: 600;
color: #1F2937;
color: $text-main;
}
.express-no {
font-size: 24rpx;
color: #6B7280;
font-family: monospace;
color: $text-sub;
margin-top: 4rpx;
}
.express-copy {
font-size: 24rpx;
color: #2563EB;
font-weight: 500;
padding: 12rpx 20rpx;
background: #FFFFFF;
border-radius: 12rpx;
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.05);
font-size: 22rpx;
color: $brand-primary;
padding: 6rpx 16rpx;
border: 1rpx solid $brand-primary;
border-radius: 20rpx;
background: transparent; /* reset bg */
box-shadow: none; /* reset shadow */
&:active { background: rgba($brand-primary, 0.05); }
}
/* 时间信息 */
.shipment-time {
display: flex;
flex-direction: column;
gap: 6rpx;
gap: 8rpx;
border-top: 1rpx dashed rgba(0,0,0,0.05);
padding-top: 20rpx;
}
.time-item {
font-size: 22rpx;
color: #9CA3AF;
color: $text-tertiary;
}
/* ============================================
盒柜 UX/UI 增强
============================================ */
/* 入场动画 */
@keyframes fadeInUp {
from { opacity: 0; transform: translateY(30rpx); }
from { opacity: 0; transform: translateY(20rpx); }
to { opacity: 1; transform: translateY(0); }
}
@keyframes scaleIn {
from { opacity: 0; transform: scale(0.95); }
to { opacity: 1; transform: scale(1); }
}
@keyframes slideUp {
from { opacity: 0; transform: translateY(100%); }
to { opacity: 1; transform: translateY(0); }
from { transform: translateY(100%); }
to { transform: translateY(0); }
}
@keyframes bounceIn {
0% { transform: scale(0); }
50% { transform: scale(1.2); }
100% { transform: scale(1); }
}
@keyframes pulse {
0%, 100% { transform: scale(1); }
50% { transform: scale(1.05); }
}
/* Tab 切换动画 */
.tabs {
animation: fadeInUp 0.3s ease-out;
}
.tab-item {
transition: all 0.25s ease;
}
.tab-item:active {
transform: scale(0.96);
}
/* 库存卡片交错入场 */
.inventory-item:nth-child(1) { animation: fadeInUp 0.4s ease-out 0.1s both; }
.inventory-item:nth-child(2) { animation: fadeInUp 0.4s ease-out 0.15s both; }
.inventory-item:nth-child(3) { animation: fadeInUp 0.4s ease-out 0.2s both; }
.inventory-item:nth-child(4) { animation: fadeInUp 0.4s ease-out 0.25s both; }
.inventory-item:nth-child(n+5) { animation: fadeInUp 0.4s ease-out 0.3s both; }
/* 发货单卡片交错入场 */
.shipment-card:nth-child(1) { animation: fadeInUp 0.4s ease-out 0.1s both; }
.shipment-card:nth-child(2) { animation: fadeInUp 0.4s ease-out 0.15s both; }
.shipment-card:nth-child(3) { animation: fadeInUp 0.4s ease-out 0.2s both; }
.shipment-card:nth-child(n+4) { animation: fadeInUp 0.4s ease-out 0.25s both; }
/* 卡片点击效果 */
.inventory-item {
transition: all 0.25s cubic-bezier(0.25, 0.46, 0.45, 0.94);
}
.inventory-item:active {
transform: scale(0.98);
box-shadow: 0 4rpx 16rpx rgba(0,0,0,0.08);
}
/* 选中时的高亮效果 */
.inventory-item:has(.checkbox.checked) {
box-shadow: 0 8rpx 32rpx rgba(255, 107, 53, 0.15);
border: 2rpx solid rgba(255, 159, 67, 0.3);
}
/* 复选框动画 */
.checkbox {
transition: all 0.2s ease;
}
.checkbox.checked {
animation: bounceIn 0.3s ease-out;
}
/* 底部操作栏增强 */
.bottom-bar {
animation: slideUp 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94);
backdrop-filter: blur(20rpx);
-webkit-backdrop-filter: blur(20rpx);
background: rgba(255, 255, 255, 0.95);
}
/* 操作按钮动画 */
.action-btn {
transition: all 0.2s ease;
}
.action-btn:active {
transform: scale(0.95);
}
.btn-redeem {
animation: pulse 2s infinite;
}
.btn-redeem:active {
animation: none;
}
/* 步进器按钮效果 */
.step-btn {
transition: all 0.15s ease;
}
.step-btn:active {
background: #FF9F43 !important;
color: #fff !important;
transform: scale(0.9);
}
/* 全选栏入场 */
.action-bar {
animation: fadeInUp 0.3s ease-out;
}
/* 发货单卡片点击效果 */
.shipment-card {
transition: all 0.25s ease;
}
.shipment-card:active {
transform: scale(0.98);
box-shadow: 0 4rpx 20rpx rgba(0,0,0,0.1);
}
/* 复制按钮效果 */
.express-copy {
transition: all 0.2s ease;
}
.express-copy:active {
background: #2563EB;
color: #fff;
transform: scale(0.95);
}
/* 缩略图图片悬浮效果 */
.thumb-img {
transition: all 0.2s ease;
}
.thumb-img:active {
transform: scale(1.05);
.bottom-spacer {
height: 120rpx;
}
</style>

View File

@ -1,5 +1,8 @@
<template>
<view class="page">
<!-- 背景装饰 -->
<view class="bg-decoration"></view>
<!-- 顶部导航栏 (搜索) -->
<view class="nav-header">
<view class="brand-logo">
@ -336,14 +339,14 @@ export default {
}
</script>
<style>
<style lang="scss">
/* ============================================
奇盒潮玩 - 首页样式 (V6.0 新版)
奇盒潮玩 - 首页样式 (V6.0 Pro Refined)
============================================ */
.page {
padding: 0;
background: #FFFFFF;
background-color: $bg-page;
min-height: 100vh;
display: flex;
flex-direction: column;
@ -353,166 +356,232 @@ export default {
.nav-header {
display: flex;
align-items: center;
padding: 20rpx 24rpx;
background: #FFF8F3;
padding-top: calc(20rpx + env(safe-area-inset-top));
gap: 24rpx;
padding: $spacing-md $spacing-lg;
background: transparent; /* 透明背景,依靠内容区的渐变 */
padding-top: calc($spacing-md + env(safe-area-inset-top));
gap: $spacing-lg;
z-index: 10;
}
.brand-logo {
display: flex;
align-items: center;
}
.brand-text {
font-size: 36rpx;
font-size: 40rpx;
font-weight: 900;
color: #1A1A1A;
color: $text-main;
font-style: italic;
letter-spacing: -1rpx;
text-shadow: 0 2rpx 4rpx rgba(255, 255, 255, 0.5);
}
.brand-star {
font-size: 24rpx;
margin-left: 4rpx;
margin-top: -12rpx;
margin-top: -16rpx;
animation: pulse 2s infinite;
}
.search-bar {
flex: 1;
height: 64rpx;
background: white;
border-radius: 999rpx;
height: 72rpx;
background: rgba(255, 255, 255, 0.8);
backdrop-filter: blur(10px);
border-radius: $radius-round;
display: flex;
align-items: center;
padding: 0 24rpx;
border: 1rpx solid #F0F0F0;
padding: 0 $spacing-lg;
border: 1rpx solid rgba(255, 255, 255, 0.6);
box-shadow: $shadow-sm;
transition: all 0.3s ease;
}
.search-icon { margin-right: 12rpx; font-size: 28rpx; }
.search-placeholder { color: #999; font-size: 28rpx; }
.search-bar:active {
background: #fff;
transform: scale(0.98);
}
.search-icon { margin-right: 12rpx; font-size: 32rpx; }
.search-placeholder { color: $text-tertiary; font-size: 28rpx; font-weight: 500; }
/* ========== 滚动主内容区 ========== */
.main-content {
flex: 1;
background: linear-gradient(180deg, #FFF8F3 0%, #FFFFFF 600rpx);
padding-top: 20rpx;
/* background: linear-gradient(180deg, $bg-secondary 0%, $bg-page 400rpx); */ /* 移除原有背景,使用全局背景装饰 */
position: relative;
z-index: 1; /* 确保内容在背景装饰之上 */
padding-top: $spacing-sm;
}
/* Logo Banner */
.banner-box {
margin: 0 24rpx 24rpx;
border-radius: 24rpx;
margin: 0 $spacing-lg $spacing-lg;
border-radius: $radius-lg;
overflow: hidden;
box-shadow: 0 8rpx 24rpx rgba(0,0,0,0.06);
box-shadow: $shadow-float;
transform: translateZ(0); /* 开启硬件加速 */
animation: fadeInUp 0.6s ease-out;
}
.banner-swiper, .banner-image, .banner-fallback {
width: 100%;
height: 320rpx;
height: 340rpx; /* 略微增高 */
}
.banner-fallback {
background: #FFFBE8;
background: linear-gradient(135deg, $bg-secondary, #FFF0D6);
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
border: 2rpx dashed #FFE58F;
border: 4rpx dashed $brand-primary-light;
}
.banner-fallback-text {
font-size: 48rpx;
font-weight: 900;
color: $brand-primary;
font-style: italic;
margin-bottom: 12rpx;
text-shadow: 0 2rpx 0 rgba(255,255,255,1);
}
.banner-tag {
background: #1A1A1A;
color: $accent-gold;
padding: 6rpx 20rpx;
border-radius: $radius-round;
font-size: 24rpx;
font-weight: 700;
}
.banner-fallback-text { font-size: 48rpx; font-weight: 900; color: #1A1A1A; font-style: italic; margin-bottom: 12rpx; }
.banner-tag { background: #CCFF00; padding: 4rpx 16rpx; border-radius: 999rpx; font-size: 24rpx; font-weight: 700; color: #1A1A1A; }
/* 通知栏 */
.notice-bar {
margin: 0 24rpx 32rpx;
background: #F9F9F9;
border-radius: 12rpx;
padding: 16rpx 20rpx;
margin: 0 $spacing-lg $spacing-xl;
background: #FFFFFF;
border-radius: $radius-round;
padding: 16rpx 24rpx;
display: flex;
align-items: center;
gap: 16rpx;
box-shadow: $shadow-sm;
animation: fadeInUp 0.6s ease-out 0.1s backwards;
}
.notice-tag {
background: #333;
color: #fff;
font-size: 22rpx;
padding: 2rpx 8rpx;
border-radius: 6rpx;
font-weight: 700;
}
.notice-swiper { flex: 1; height: 36rpx; }
.notice-item { font-size: 24rpx; color: #333; line-height: 36rpx; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.notice-more { font-size: 24rpx; color: #999; }
.notice-tag {
background: $gradient-brand;
color: #fff;
font-size: 20rpx;
padding: 4rpx 12rpx;
border-radius: 8rpx;
font-weight: 700;
box-shadow: 0 2rpx 6rpx rgba($brand-primary, 0.3);
}
.notice-swiper { flex: 1; height: 36rpx; }
.notice-item {
font-size: 26rpx;
color: $text-main;
line-height: 36rpx;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
font-weight: 500;
}
.notice-more { font-size: 24rpx; color: $text-sub; display: flex; align-items: center; }
.notice-more::after { content: ''; margin-left: 4rpx; font-size: 32rpx; line-height: 24rpx; }
/* 玩法专区 - 方案B2+3 杂志风布局 */
.gameplay-section {
padding: 0 24rpx;
margin-bottom: 24rpx;
padding: 0 $spacing-lg;
margin-bottom: $spacing-xl;
animation: fadeInUp 0.6s ease-out 0.2s backwards;
}
.section-header {
margin-bottom: 16rpx;
margin-bottom: 20rpx;
display: flex;
align-items: center;
justify-content: space-between;
}
.section-title {
font-size: 34rpx;
font-size: 36rpx;
font-weight: 900;
color: #1A1A1A;
color: $text-main;
position: relative;
z-index: 1;
padding-bottom: 4rpx;
padding-left: 12rpx;
font-style: italic;
letter-spacing: 2rpx;
}
/* 黄色高光底线效果 */
.section-title::after {
/* 标题装饰竖线 */
.section-title::before {
content: '';
position: absolute;
left: 0;
bottom: 0;
width: 100%;
height: 16rpx;
background: #FFD700;
z-index: -1;
border-radius: 4rpx;
transform: skewX(-10deg);
top: 50%;
transform: translateY(-50%) skewX(-10deg);
width: 8rpx;
height: 32rpx;
background: $brand-primary;
border-radius: 2rpx;
}
.gameplay-grid-v2 {
display: flex;
flex-direction: column;
gap: 16rpx;
gap: 20rpx;
}
/* 上排 */
.grid-row-top {
display: flex;
gap: 16rpx;
height: 180rpx; /* 大卡片高度 */
gap: 20rpx;
height: 220rpx; /* 增加高度,展示更多细节 */
}
.game-card-large {
flex: 1;
border-radius: 20rpx;
border-radius: $radius-lg;
position: relative;
overflow: hidden;
padding: 24rpx;
box-shadow: 0 4rpx 16rpx rgba(0,0,0,0.05);
padding: 28rpx;
box-shadow: $shadow-card;
transition: transform 0.2s;
}
.game-card-large:active {
transform: scale(0.98);
}
/* 下排 */
.grid-row-bottom {
display: flex;
gap: 16rpx;
height: 140rpx; /* 小卡片高度 */
gap: 20rpx;
height: 160rpx;
}
.game-card-small {
flex: 1;
border-radius: 16rpx;
border-radius: $radius-md;
position: relative;
overflow: hidden;
padding: 16rpx;
padding: 20rpx;
display: flex;
flex-direction: column;
justify-content: center;
box-shadow: 0 4rpx 12rpx rgba(0,0,0,0.03);
background: white; /* 默认底色 */
box-shadow: $shadow-sm;
background: white;
transition: all 0.2s;
}
.game-card-small:active {
transform: scale(0.96);
box-shadow: none;
}
/* 内容样式 - 大卡片 */
@ -525,100 +594,116 @@ export default {
justify-content: center;
align-items: flex-start;
}
.card-title-large {
font-size: 36rpx;
font-size: 40rpx;
font-weight: 900;
color: #FFF;
font-style: italic;
margin-bottom: 12rpx;
text-shadow: 2rpx 2rpx 0 rgba(0,0,0,0.1);
margin-bottom: 16rpx;
text-shadow: 0 4rpx 8rpx rgba(0,0,0,0.1);
}
.card-tag-large {
font-size: 20rpx;
background: #FFF;
color: #333;
padding: 4rpx 12rpx;
border-radius: 8rpx;
font-weight: 700;
box-shadow: 2rpx 2rpx 0 rgba(0,0,0,0.1);
transform: skewX(-10deg);
font-size: 22rpx;
background: rgba(255, 255, 255, 0.9);
color: $text-main;
padding: 6rpx 16rpx;
border-radius: $radius-round;
font-weight: 800;
box-shadow: 0 4rpx 12rpx rgba(0,0,0,0.1);
backdrop-filter: blur(4px);
}
.card-tag-large.yellow { color: #875700; }
.card-tag-large.yellow { color: #D97706; }
.card-mascot-large {
position: absolute;
right: -10rpx;
bottom: -20rpx;
width: 160rpx;
height: 160rpx;
transform: rotate(5deg);
right: -20rpx;
bottom: -30rpx;
width: 180rpx;
height: 180rpx;
transform: rotate(10deg);
filter: drop-shadow(0 8rpx 16rpx rgba(0,0,0,0.2));
}
/* 内容样式 - 小卡片 */
.card-title-small {
font-size: 28rpx;
font-size: 30rpx;
font-weight: 800;
color: #333;
margin-bottom: 4rpx;
color: $text-main;
margin-bottom: 6rpx;
z-index: 2;
}
.card-subtitle-small {
font-size: 20rpx;
color: #888;
z-index: 2;
}
.card-icon-small {
position: absolute;
right: 0;
bottom: 0;
width: 90rpx;
height: 90rpx;
opacity: 0.8;
}
/* 背景配色 - 仿参考图Pop风格 */
.card-subtitle-small {
font-size: 22rpx;
color: $text-sub;
z-index: 2;
}
.card-icon-small {
position: absolute;
right: -10rpx;
bottom: -10rpx;
width: 100rpx;
height: 100rpx;
opacity: 0.9;
transform: rotate(-10deg);
}
/* 背景配色 - 优化后的渐变 */
.card-yifan {
background: linear-gradient(135deg, #FF9C6E 0%, #FF7875 100%); /* 粉红/橘色 */
background: linear-gradient(135deg, $brand-primary 0%, $brand-secondary 100%); /* 品牌橙渐变 */
}
.card-wuxian {
background: linear-gradient(135deg, #FFD666 0%, #FFA940 100%); /* 黄色/橙色 */
background: $gradient-gold; /* 质感金渐变 */
}
.card-match {
background: linear-gradient(135deg, #FFADD2 0%, #FF85C0 100%); /* 粉色 */
background: linear-gradient(135deg, #FF9A9E 0%, #FECFEF 100%); /* 柔和粉 */
}
.card-match .card-title-small { color: $accent-pink; }
.card-tower {
background: linear-gradient(135deg, #B37FEB 0%, #9254DE 100%); /* 紫色 */
background: linear-gradient(135deg, #E0C3FC 0%, #8EC5FC 100%); /* 梦幻紫蓝 */
}
.card-tower .card-title-small { color: $accent-purple; }
.card-more {
background: linear-gradient(135deg, #E0E0E0 0%, #F5F5F5 100%); /* 灰色 */
background: linear-gradient(135deg, $bg-secondary 0%, #E5E7EB 100%); /* 金属灰 */
}
/* 对对碰文字颜色适配 */
.card-match .card-title-small { color: #FFF; }
.card-match .card-subtitle-small { color: rgba(255,255,255,0.8); }
.card-tower .card-title-small { color: #FFF; }
.card-tower .card-subtitle-small { color: rgba(255,255,255,0.8); }
.card-more .card-title-small { color: $text-sub; }
/* 推荐活动列表 */
.activity-section {
padding: 0 24rpx;
padding: 0 $spacing-lg;
animation: fadeInUp 0.6s ease-out 0.3s backwards;
}
.activity-grid-list {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 20rpx;
gap: 24rpx;
}
.activity-item {
background: white;
border-radius: 20rpx;
background: #FFFFFF;
border-radius: $radius-lg;
overflow: hidden;
box-shadow: 0 8rpx 20rpx rgba(0,0,0,0.06);
box-shadow: $shadow-card;
display: flex;
flex-direction: column;
transition: transform 0.2s;
}
.activity-item:active {
transform: scale(0.98);
}
.activity-thumb-box {
position: relative;
width: 100%;
padding-bottom: 100%; /* 1:1 正方形图片 */
padding-bottom: 100%; /* 1:1 正方形 */
}
.activity-thumb {
position: absolute;
@ -627,41 +712,34 @@ export default {
height: 100%;
background: #EEE;
}
.banner-fallback.mini {
position: absolute;
top: 0; left: 0;
width: 100%;
height: 100%;
background: #F5F5F5;
display: flex;
align-items: center;
justify-content: center;
}
.activity-tag-hot {
position: absolute;
top: 12rpx;
left: 12rpx;
background: rgba(0,0,0,0.6);
color: #FFD700;
top: 16rpx;
left: 16rpx;
background: $gradient-brand;
color: #fff;
font-size: 20rpx;
padding: 4rpx 12rpx;
padding: 6rpx 14rpx;
border-radius: 8rpx;
font-weight: 700;
backdrop-filter: blur(4rpx);
font-weight: 800;
box-shadow: 0 4rpx 10rpx rgba($brand-primary, 0.3);
animation: pulse 2s infinite;
}
.activity-info {
padding: 20rpx;
padding: 24rpx;
flex: 1;
display: flex;
flex-direction: column;
justify-content: space-between;
}
.activity-name {
font-size: 28rpx;
font-weight: 700;
color: #1A1A1A;
margin-bottom: 16rpx;
color: $text-main;
margin-bottom: 20rpx;
line-height: 1.4;
overflow: hidden;
text-overflow: ellipsis;
@ -669,43 +747,43 @@ export default {
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}
.activity-row {
display: flex;
justify-content: space-between;
align-items: center;
}
.activity-desc {
font-size: 24rpx;
color: #FF4D4F; /* 价格/品类突出颜色 */
font-weight: 600;
max-width: 70%;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
font-size: 26rpx;
color: $accent-red; /* 价格/热度颜色 */
font-weight: 800;
}
.activity-btn-go {
background: #1A1A1A;
background: $text-main;
color: #FFD700;
font-size: 20rpx;
font-weight: 900;
padding: 6rpx 20rpx;
border-radius: 30rpx;
box-shadow: 0 4rpx 10rpx rgba(0,0,0,0.15);
padding: 8rpx 24rpx;
border-radius: $radius-round;
box-shadow: 0 4rpx 12rpx rgba(0,0,0,0.2);
}
/* 空状态 */
.activity-empty {
text-align: center;
padding: 60rpx 0;
color: #9CA3AF;
padding: 80rpx 0;
color: $text-tertiary;
font-size: 28rpx;
}
/* ============================================
UX/UI 增强 - 动画与交互
============================================ */
@keyframes pulse {
0% { transform: scale(1); opacity: 1; }
50% { transform: scale(1.05); opacity: 0.9; }
100% { transform: scale(1); opacity: 1; }
}
/* 入场动画 */
@keyframes fadeInUp {
from {
opacity: 0;
@ -733,11 +811,6 @@ export default {
100% { background-position: 200% 0; }
}
@keyframes pulse {
0%, 100% { transform: scale(1); }
50% { transform: scale(1.05); }
}
@keyframes float {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-8rpx); }

View File

@ -5,6 +5,7 @@
<view class="orb orb-2"></view>
<view class="content-wrap">
<view class="glass-card">
<!-- 品牌Logo -->
<view class="brand-section">
<view class="logo-box">
@ -81,6 +82,7 @@
登录即代表同意 <text class="link" @tap="toUserAgreement">用户协议</text> & <text class="link" @tap="toPurchaseAgreement">隐私政策</text>
</view>
</view>
</view>
<view v-if="error" class="error-toast">{{ error }}</view>
</view>
@ -141,7 +143,6 @@ function onGetPhoneNumber(e) {
}
const phoneCode = e.detail.code
console.log('login_flow start getPhoneNumber, codeExists:', !!phoneCode)
if (!phoneCode) {
uni.showToast({ title: '未授权手机号', icon: 'none' })
return
@ -211,12 +212,12 @@ function onGetPhoneNumber(e) {
}
</script>
<style scoped>
<style lang="scss" scoped>
/* Page Container */
.container {
min-height: 100vh;
position: relative;
background: #F8F5F2; /* Cream base */
background: $bg-secondary; /* Use secondary for better depth with orbs */
overflow: hidden;
display: flex;
flex-direction: column;
@ -224,33 +225,56 @@ function onGetPhoneNumber(e) {
}
/* Orbs Background */
.bg-decoration {
position: absolute;
top: 0; left: 0; width: 100%; height: 100%;
pointer-events: none;
z-index: 0;
}
.orb {
position: absolute;
border-radius: 50%;
filter: blur(60rpx);
z-index: 0;
filter: blur(80rpx); /* Increased blur for smoother look */
opacity: 0.6;
}
.orb-1 {
width: 400rpx;
height: 400rpx;
background: rgba(255, 107, 0, 0.15);
top: -100rpx;
left: -100rpx;
}
.orb-2 {
width: 500rpx;
height: 500rpx;
background: rgba(255, 215, 0, 0.1);
background: radial-gradient(circle, rgba($brand-primary, 0.4), transparent 70%);
top: -100rpx;
left: -100rpx;
animation: float 8s ease-in-out infinite;
}
.orb-2 {
width: 600rpx;
height: 600rpx;
background: radial-gradient(circle, rgba($accent-gold, 0.3), transparent 70%);
bottom: -150rpx;
right: -150rpx;
animation: float 10s ease-in-out infinite reverse;
}
@keyframes float {
0%, 100% { transform: translate(0, 0); }
50% { transform: translate(30rpx, 40rpx); }
}
.content-wrap {
position: relative;
z-index: 1;
padding: 0 60rpx;
padding: 0 40rpx;
width: 100%;
box-sizing: border-box;
animation: fadeInUp 0.6s ease-out;
}
.glass-card {
background: $bg-glass;
backdrop-filter: blur(30rpx);
border-radius: 40rpx;
padding: 60rpx 40rpx;
box-shadow: 0 20rpx 60rpx rgba(0, 0, 0, 0.08);
border: 1rpx solid rgba(255, 255, 255, 0.8);
}
/* Brand Section */
@ -258,80 +282,112 @@ function onGetPhoneNumber(e) {
display: flex;
flex-direction: column;
align-items: center;
margin-bottom: 80rpx;
margin-bottom: 60rpx;
}
.logo-box {
width: 180rpx;
height: 180rpx;
background: #FFFFFF;
width: 160rpx;
height: 160rpx;
background: $bg-card;
border-radius: 40rpx;
padding: 20rpx;
box-shadow: 0 20rpx 60rpx rgba(255, 107, 0, 0.15);
box-shadow: 0 12rpx 30rpx rgba($brand-primary, 0.2);
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 32rpx;
animation: float 6s ease-in-out infinite;
}
@keyframes float {
0% { transform: translateY(0); }
50% { transform: translateY(-20rpx); }
100% { transform: translateY(0); }
margin-bottom: $spacing-xl;
animation: pulse 3s infinite;
}
.logo { width: 100%; height: 100%; }
.app-name { font-size: 48rpx; font-weight: 900; color: #1A1A1A; margin-bottom: 8rpx; letter-spacing: 2rpx; }
.welcome-text { font-size: 28rpx; color: #888; letter-spacing: 4rpx; }
.app-name {
font-size: 44rpx;
font-weight: 900;
color: $text-main;
margin-bottom: 12rpx;
letter-spacing: 2rpx;
text-shadow: 0 2rpx 4rpx rgba(0,0,0,0.05);
}
.welcome-text {
font-size: 26rpx;
color: $text-sub;
letter-spacing: 4rpx;
text-transform: uppercase;
opacity: 0.8;
}
/* Form Styles */
.input-group {
background: #FFFFFF;
border-radius: 999rpx;
background: $bg-card;
border-radius: $radius-round;
height: 100rpx;
display: flex;
align-items: center;
padding: 0 32rpx;
margin-bottom: 32rpx;
margin-bottom: $spacing-xl;
border: 2rpx solid transparent;
transition: all 0.3s;
box-shadow: 0 4rpx 12rpx rgba(0,0,0,0.03);
}
.input-group:focus-within {
border-color: #FF6B00;
box-shadow: 0 0 0 6rpx rgba(255, 107, 0, 0.1);
box-shadow: $shadow-sm;
&.glass-input {
background: rgba(255, 255, 255, 0.5);
border: 1px solid rgba(255, 255, 255, 0.5);
&:focus-within {
background: $bg-card;
border-color: $brand-primary;
box-shadow: 0 0 0 4rpx rgba($brand-primary, 0.15);
transform: translateY(-2rpx);
}
.input-icon { width: 40rpx; height: 40rpx; margin-right: 20rpx; opacity: 0.6; }
}
}
.input-icon { width: 40rpx; height: 40rpx; margin-right: 20rpx; opacity: 1; }
.input-icon image { width: 100%; height: 100%; }
.input-field { flex: 1; height: 100%; font-size: 30rpx; color: #333; }
.input-placeholder { color: #BBB; }
.input-field { flex: 1; height: 100%; font-size: 30rpx; color: $text-main; font-weight: 500; }
.input-placeholder { color: $text-tertiary; font-weight: 400; }
.options-row { display: flex; justify-content: space-between; margin-bottom: 60rpx; }
.options-row { display: flex; justify-content: space-between; margin-bottom: 60rpx; padding: 0 10rpx; }
.remember-box { display: flex; align-items: center; }
.checkbox { width: 36rpx; height: 36rpx; border: 3rpx solid #DDD; border-radius: 8rpx; margin-right: 12rpx; display: flex; align-items: center; justify-content: center; transition: all 0.2s; }
.checkbox.checked { background: #FF6B00; border-color: #FF6B00; }
.check-mark { color: #FFF; font-size: 24rpx; font-weight: bold; }
.remember-text { font-size: 26rpx; color: #666; }
/* Buttons */
.btn {
height: 100rpx;
border-radius: 999rpx;
.checkbox {
width: 36rpx; height: 36rpx;
border: 3rpx solid $border-color;
border-radius: 10rpx;
margin-right: 12rpx;
display: flex;
align-items: center;
justify-content: center;
font-size: 32rpx;
transition: all 0.2s;
background: rgba(255,255,255,0.5);
&.checked {
background: $brand-primary;
border-color: $brand-primary;
box-shadow: 0 4rpx 10rpx rgba($brand-primary, 0.3);
}
}
.check-mark { color: $text-inverse; font-size: $font-sm; font-weight: bold; }
.remember-text { font-size: 26rpx; color: $text-sub; }
/* Buttons */
.btn {
height: 96rpx;
border-radius: $radius-round;
display: flex;
align-items: center;
justify-content: center;
font-size: $font-lg;
font-weight: 800;
position: relative;
overflow: hidden;
transition: all 0.2s;
&:active { transform: scale(0.96); }
}
.btn:active { transform: scale(0.96); }
.login-btn {
background: linear-gradient(90deg, #FF6B00 0%, #FFA500 100%);
color: #FFF;
box-shadow: 0 10rpx 30rpx rgba(255, 107, 0, 0.3);
margin-bottom: 32rpx;
background: $gradient-brand;
color: $text-inverse;
box-shadow: 0 10rpx 30rpx rgba($brand-primary, 0.3);
margin-bottom: $spacing-xl;
border: none;
}
.btn-shine {
position: absolute;
@ -348,39 +404,52 @@ function onGetPhoneNumber(e) {
}
.weixin-btn {
background: #07C160;
color: #FFF;
background: #07C160; /* WeChat Brand Color */
color: $text-inverse;
box-shadow: 0 10rpx 30rpx rgba(7, 193, 96, 0.3);
border: none;
}
.wx-icon { width: 48rpx; height: 48rpx; margin-right: 16rpx; }
.wx-icon { width: 48rpx; height: 48rpx; margin-right: 16rpx; filter: brightness(100); } /* Make logo white if it's the logo, but ideally it should be WeChat icon */
/* Register Link */
.register-link { text-align: center; margin-top: 32rpx; }
.register-text { font-size: 28rpx; color: #888; }
.highlight { color: #FF6B00; font-weight: 700; margin-left: 8rpx; }
.register-link { text-align: center; margin-top: $spacing-xl; }
.register-text { font-size: $font-md; color: $text-sub; }
.highlight { color: $brand-primary; font-weight: 700; margin-left: 8rpx; }
/* Agreements */
.agreements {
margin-top: 80rpx;
margin-top: 60rpx;
display: flex;
justify-content: center;
align-items: center;
align-items: flex-start;
padding: 0 20rpx;
}
.checkbox.round { border-radius: 50%; width: 32rpx; height: 32rpx; }
.checkbox-area { padding: 10rpx; }
.agreement-text { font-size: 24rpx; color: #999; margin-left: 8rpx; }
.link { color: #FF6B00; text-decoration: underline; margin: 0 4rpx; }
.checkbox.round { border-radius: 50%; width: 32rpx; height: 32rpx; margin-top: 4rpx; }
.checkbox-area { padding-right: 12rpx; }
.agreement-text {
font-size: $font-sm;
color: $text-tertiary;
line-height: 1.5;
text-align: left;
}
.link { color: $brand-primary; text-decoration: none; font-weight: 600; margin: 0 4rpx; }
.error-toast {
position: fixed;
top: 100rpx;
left: 50%;
transform: translateX(-50%);
background: rgba(255, 60, 60, 0.9);
color: #fff;
background: rgba($uni-color-error, 0.9);
color: $text-inverse;
padding: 16rpx 32rpx;
border-radius: 12rpx;
font-size: 26rpx;
z-index: 999;
box-shadow: 0 8rpx 20rpx rgba(0,0,0,0.2);
animation: slideDown 0.3s ease-out;
}
@keyframes slideDown {
from { transform: translate(-50%, -100%); opacity: 0; }
to { transform: translate(-50%, 0); opacity: 1; }
}
</style>

File diff suppressed because it is too large Load Diff

View File

@ -1,11 +1,15 @@
<template>
<view class="wrap">
<view class="bg-decoration"></view>
<view class="tabs">
<view class="tab" :class="{ active: currentTab === 'pending' }" @click="switchTab('pending')">待付款</view>
<view class="tab" :class="{ active: currentTab === 'completed' }" @click="switchTab('completed')">已完成</view>
</view>
<view v-if="error" class="error">{{ error }}</view>
<view v-if="orders.length === 0 && !loading" class="empty">暂无订单</view>
<view v-if="orders.length === 0 && !loading" class="empty">
<view class="empty-icon">📦</view>
<view class="empty-text">暂无订单</view>
</view>
<view v-for="item in orders" :key="item.id || item.order_no" class="order">
<view class="order-main">
<view class="order-title">{{ item.title || item.subject || '订单' }}</view>
@ -13,7 +17,7 @@
</view>
<view class="order-right">
<view class="order-amount">{{ formatAmount(item.total_amount || item.amount || item.price) }}</view>
<view class="order-status">{{ statusText(item) }}</view>
<view class="order-status" :class="getStatusClass(item)">{{ statusText(item) }}</view>
</view>
</view>
<view v-if="loadingMore" class="loading">加载中...</view>
@ -65,6 +69,13 @@ function statusText(item) {
return s || ''
}
function getStatusClass(item) {
const text = statusText(item)
if (text === '待付款') return 'status-pending'
if (text === '已完成') return 'status-completed'
return ''
}
function switchTab(tab) {
if (currentTab.value === tab) return
currentTab.value = tab
@ -163,42 +174,56 @@ onReachBottom(() => {
})
</script>
<style scoped>
<style lang="scss" scoped>
/* ============================================
奇盒潮玩 - 订单页面
采用暖橙色调的订单列表设计
============================================ */
.wrap {
padding: 24rpx;
padding: $spacing-md;
min-height: 100vh;
background: linear-gradient(180deg, #FFF8F3 0%, #FFFFFF 100%);
background-color: $bg-page;
position: relative;
overflow-x: hidden;
&::before {
content: '';
position: fixed;
top: 0; left: 0; width: 100%; height: 100vh;
background: radial-gradient(circle at 10% 10%, rgba($brand-primary, 0.05), transparent 40%),
radial-gradient(circle at 90% 90%, rgba($accent-gold, 0.05), transparent 40%);
pointer-events: none;
z-index: 0;
}
}
/* Tab 切换 */
.tabs {
display: flex;
background: #FFFFFF;
border-radius: 20rpx;
background: $bg-glass;
backdrop-filter: blur(10rpx);
border: 1px solid rgba(255, 255, 255, 0.5);
border-radius: $radius-lg;
padding: 8rpx;
margin-bottom: 24rpx;
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.06);
margin-bottom: $spacing-lg;
box-shadow: $shadow-sm;
}
.tab {
flex: 1;
text-align: center;
padding: 20rpx 0;
font-size: 28rpx;
color: #6B7280;
border-radius: 16rpx;
font-size: $font-md;
color: $text-sub;
border-radius: $radius-md;
transition: all 0.25s ease;
font-weight: 500;
}
.tab.active {
background: linear-gradient(135deg, #FF9F43, #FF6B35);
color: #FFFFFF;
background: $gradient-brand;
color: $text-inverse;
font-weight: 600;
box-shadow: 0 6rpx 20rpx rgba(255, 107, 53, 0.35);
box-shadow: $shadow-glow;
}
/* 订单卡片 */
@ -206,15 +231,25 @@ onReachBottom(() => {
display: flex;
justify-content: space-between;
align-items: center;
background: #FFFFFF;
border-radius: 20rpx;
padding: 24rpx;
margin-bottom: 16rpx;
box-shadow: 0 8rpx 24rpx rgba(0, 0, 0, 0.06);
background: $bg-card;
border-radius: $radius-md;
padding: $spacing-lg;
margin-bottom: $spacing-lg;
box-shadow: $shadow-sm;
border: 1rpx solid rgba(0,0,0,0.02);
transition: all 0.2s ease;
animation: fadeInUp 0.4s ease-out backwards;
}
@for $i from 1 through 10 {
.order:nth-child(#{$i}) {
animation-delay: #{$i * 0.05}s;
}
}
.order:active {
transform: scale(0.98);
box-shadow: none;
}
.order-main {
@ -224,67 +259,90 @@ onReachBottom(() => {
min-width: 0;
}
.order-title {
font-size: 28rpx;
font-weight: 600;
color: #1F2937;
font-size: $font-md;
font-weight: 700;
color: $text-main;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
margin-bottom: $spacing-xs;
}
.order-sub {
font-size: 24rpx;
color: #9CA3AF;
margin-top: 8rpx;
font-size: $font-sm;
color: $text-sub;
}
.order-right {
display: flex;
flex-direction: column;
align-items: flex-end;
margin-left: 16rpx;
margin-left: $spacing-lg;
flex-shrink: 0;
}
.order-amount {
font-size: 30rpx;
font-weight: 700;
background: linear-gradient(135deg, #FF6B35, #FF9F43);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
font-size: $font-lg;
font-weight: 800;
color: $brand-primary;
font-family: 'DIN Alternate', sans-serif;
}
.order-status {
font-size: 24rpx;
color: #6B7280;
margin-top: 8rpx;
padding: 4rpx 12rpx;
background: #F3F4F6;
border-radius: 999rpx;
font-size: $font-xs;
color: $text-sub;
margin-top: 10rpx;
padding: 4rpx $spacing-md;
background: $bg-page;
border-radius: $radius-round;
font-weight: 600;
&.status-pending {
background: rgba($brand-primary, 0.1);
color: $brand-primary;
}
&.status-completed {
background: rgba($uni-color-success, 0.1);
color: $uni-color-success;
}
}
/* 空状态 */
.empty {
text-align: center;
color: #9CA3AF;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
margin-top: 120rpx;
font-size: 28rpx;
animation: fadeInUp 0.5s ease-out;
.empty-icon {
font-size: 80rpx;
margin-bottom: $spacing-lg;
opacity: 0.6;
animation: float 4s ease-in-out infinite;
}
.empty-text {
color: $text-sub;
font-size: $font-md;
}
}
/* 错误提示 */
.error {
color: #EF4444;
font-size: 26rpx;
margin-bottom: 16rpx;
padding: 16rpx;
background: rgba(239, 68, 68, 0.1);
border-radius: 12rpx;
color: $uni-color-error;
font-size: $font-sm;
margin-bottom: $spacing-md;
padding: $spacing-md;
background: rgba($uni-color-error, 0.1);
border-radius: $radius-lg;
text-align: center;
}
/* 加载状态 */
.loading, .end {
text-align: center;
color: #9CA3AF;
padding: 24rpx 0;
font-size: 26rpx;
color: $text-sub;
padding: $spacing-lg 0;
font-size: $font-sm;
}
</style>

View File

@ -1,18 +1,55 @@
<template>
<view class="wrap">
<view v-if="error" class="error">{{ error }}</view>
<view v-if="records.length === 0 && !loading" class="empty">暂无积分记录</view>
<view v-for="item in records" :key="item.id || item.time || item.created_at" class="record">
<view class="record-main">
<view class="record-title">{{ item.title || item.reason || '变更' }}</view>
<view class="record-time">{{ formatTime(item.time || item.created_at) }}</view>
<!-- 顶部装饰背景 -->
<view class="page-bg-decoration"></view>
<view class="header-area">
<view class="page-title">积分明细</view>
<view class="page-subtitle">Points Record</view>
</view>
<view class="content-area">
<view v-if="error" class="error-card">
<text class="error-icon"></text>
<text>{{ error }}</text>
</view>
<view v-if="records.length === 0 && !loading" class="empty-state">
<image class="empty-img" src="/static/empty-points.png" mode="widthFix" />
<text class="empty-text">暂无积分记录</text>
</view>
<view class="records-list" v-else>
<view
v-for="(item, index) in records"
:key="item.id || item.time || item.created_at"
class="record-item"
:style="{ animationDelay: `${index * 0.05}s` }"
>
<view class="record-icon" :class="{ 'is-add': (item.change || item.amount || 0) > 0 }">
{{ (item.change || item.amount || 0) > 0 ? '↓' : '↑' }}
</view>
<view class="record-content">
<view class="record-main">
<view class="record-title">{{ item.title || item.reason || '积分变更' }}</view>
<view class="record-amount" :class="{ inc: (item.change || item.amount || 0) > 0, dec: (item.change || item.amount || 0) < 0 }">
{{ (item.change ?? item.amount ?? 0) > 0 ? '+' : '' }}{{ item.change ?? item.amount ?? 0 }}
</view>
</view>
<view v-if="loadingMore" class="loading">加载中...</view>
<view v-else-if="!hasMore && records.length > 0" class="end">没有更多了</view>
<view class="record-footer">
<view class="record-time">{{ formatTime(item.time || item.created_at) }}</view>
<view class="record-status">交易成功</view>
</view>
</view>
</view>
</view>
<view v-if="loadingMore" class="loading-more">
<view class="spinner"></view>
<text>加载中...</text>
</view>
<view v-else-if="!hasMore && records.length > 0" class="no-more">- 到底啦 -</view>
</view>
</view>
</template>
@ -101,17 +138,202 @@ onReachBottom(() => {
})
</script>
<style scoped>
.wrap { padding: 24rpx }
.record { display: flex; justify-content: space-between; align-items: center; background: #fff; border-radius: 12rpx; padding: 20rpx; margin-bottom: 16rpx; box-shadow: 0 2rpx 8rpx rgba(0,0,0,0.04) }
.record-main { display: flex; flex-direction: column }
.record-title { font-size: 28rpx; color: #333 }
.record-time { font-size: 24rpx; color: #999; margin-top: 6rpx }
.record-amount { font-size: 32rpx }
.record-amount.inc { color: #18a058 }
.record-amount.dec { color: #d03050 }
.empty { text-align: center; color: #999; margin-top: 40rpx }
.error { color: #e43; margin-bottom: 12rpx }
.loading { text-align: center; color: #666; margin: 20rpx 0 }
.end { text-align: center; color: #999; margin: 20rpx 0 }
<style lang="scss" scoped>
.wrap {
min-height: 100vh;
background-color: $bg-page;
position: relative;
overflow-x: hidden;
}
.page-bg-decoration {
position: absolute;
top: -200rpx;
right: -200rpx;
width: 600rpx;
height: 600rpx;
background: radial-gradient(circle, rgba($brand-primary, 0.15), transparent 70%);
border-radius: 50%;
pointer-events: none;
z-index: 0;
}
.header-area {
padding: $spacing-xl $spacing-lg;
position: relative;
z-index: 1;
}
.page-title {
font-size: 48rpx;
font-weight: 900;
color: $text-main;
margin-bottom: 8rpx;
letter-spacing: 1rpx;
}
.page-subtitle {
font-size: 24rpx;
color: $text-tertiary;
text-transform: uppercase;
letter-spacing: 2rpx;
font-weight: 600;
}
.content-area {
padding: 0 $spacing-lg $spacing-xl;
position: relative;
z-index: 1;
}
.records-list {
display: flex;
flex-direction: column;
gap: 20rpx;
}
.record-item {
display: flex;
align-items: center;
background: rgba($bg-card, 0.8);
border-radius: $radius-lg;
padding: 30rpx;
box-shadow: $shadow-sm;
backdrop-filter: blur(10px);
border: 1rpx solid rgba(255,255,255,0.5);
animation: fadeInUp 0.5s ease-out backwards;
transition: all 0.2s;
&:active {
transform: scale(0.98);
background: rgba($bg-card, 0.95);
}
}
.record-icon {
width: 80rpx;
height: 80rpx;
border-radius: 50%;
background: $bg-secondary;
display: flex;
align-items: center;
justify-content: center;
font-size: 32rpx;
color: $text-secondary;
margin-right: 24rpx;
flex-shrink: 0;
font-weight: 800;
&.is-add {
background: rgba($uni-color-success, 0.1);
color: $uni-color-success;
}
}
.record-content {
flex: 1;
}
.record-main {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 8rpx;
}
.record-title {
font-size: 30rpx;
font-weight: 700;
color: $text-main;
}
.record-amount {
font-size: 36rpx;
font-weight: 900;
font-family: 'DIN Alternate', sans-serif;
&.inc { color: $uni-color-success; }
&.dec { color: $text-main; }
}
.record-footer {
display: flex;
justify-content: space-between;
align-items: center;
}
.record-time {
font-size: 24rpx;
color: $text-tertiary;
}
.record-status {
font-size: 20rpx;
color: $text-tertiary;
background: $bg-secondary;
padding: 2rpx 10rpx;
border-radius: 6rpx;
}
.empty-state {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 100rpx 0;
.empty-img {
width: 240rpx;
margin-bottom: 30rpx;
opacity: 0.6;
filter: grayscale(100%);
}
.empty-text {
color: $text-tertiary;
font-size: 28rpx;
}
}
.error-card {
background: rgba($uni-color-error, 0.05);
border: 1rpx solid rgba($uni-color-error, 0.1);
color: $uni-color-error;
padding: 20rpx;
border-radius: $radius-md;
margin-bottom: 30rpx;
display: flex;
align-items: center;
font-size: 26rpx;
.error-icon {
margin-right: 12rpx;
}
}
.loading-more {
display: flex;
align-items: center;
justify-content: center;
padding: 30rpx 0;
color: $text-tertiary;
font-size: 24rpx;
gap: 12rpx;
}
.spinner {
width: 28rpx;
height: 28rpx;
border: 3rpx solid $bg-secondary;
border-top-color: $text-tertiary;
border-radius: 50%;
animation: spin 0.8s linear infinite;
}
.no-more {
text-align: center;
padding: 40rpx 0;
color: $text-tertiary;
font-size: 24rpx;
opacity: 0.6;
}
@keyframes spin { to { transform: rotate(360deg); } }
</style>

View File

@ -1,5 +1,6 @@
<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" />
@ -48,80 +49,115 @@ onLoad((opts) => {
})
</script>
<style scoped>
<style lang="scss" scoped>
/* ============================================
奇盒潮玩 - 商品详情页
============================================ */
.page {
min-height: 100vh;
background: linear-gradient(180deg, #FFF8F3 0%, #FFFFFF 100%);
background: $bg-page;
padding-bottom: env(safe-area-inset-bottom);
}
.loading, .empty {
text-align: center;
padding: 120rpx 40rpx;
color: #9CA3AF;
font-size: 28rpx;
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: 24rpx;
background: #FFFFFF;
border-radius: 20rpx;
padding: 28rpx;
box-shadow: 0 8rpx 24rpx rgba(0, 0, 0, 0.06);
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: 34rpx;
font-weight: 700;
color: #1F2937;
margin-bottom: 16rpx;
font-size: $font-xl;
font-weight: 800;
color: $text-main;
margin-bottom: $spacing-md;
line-height: 1.4;
}
.price-row {
display: flex;
align-items: center;
gap: 16rpx;
margin-bottom: 12rpx;
align-items: baseline;
gap: $spacing-sm;
margin-bottom: $spacing-lg;
}
.price {
font-size: 40rpx;
font-weight: 800;
background: linear-gradient(135deg, #FF6B35, #FF9F43);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
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: 26rpx;
color: #FF9F43;
padding: 4rpx 12rpx;
background: rgba(255, 159, 67, 0.15);
border-radius: 999rpx;
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: 26rpx;
color: #6B7280;
margin-bottom: 16rpx;
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: 28rpx;
color: #4B5563;
line-height: 1.7;
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>

View File

@ -1,8 +1,9 @@
<template>
<view class="page">
<view class="bg-decoration"></view>
<!-- 顶部固定区域 -->
<view class="header-section">
<view class="search-box" style="margin-top: 20rpx;">
<view class="search-box">
<view class="search-input-wrap">
<text class="search-icon">🔍</text>
<input class="search-input" v-model="keyword" placeholder="搜索心仪的商品" placeholder-class="placeholder-style" confirm-type="search" @confirm="onSearchConfirm" />
@ -228,11 +229,49 @@ onShareTimeline(() => {
</script>
<style scoped>
<style lang="scss" scoped>
.page {
min-height: 100vh;
background-color: #F5F6F8;
background-color: $bg-page;
padding-bottom: 40rpx;
position: relative;
overflow-x: hidden;
}
.bg-decoration {
position: fixed;
top: 0; left: 0; width: 100%; height: 100vh;
pointer-events: none;
z-index: 0;
&::before {
content: '';
position: absolute;
top: -100rpx; left: -100rpx;
width: 600rpx; height: 600rpx;
background: radial-gradient(circle, rgba($brand-primary, 0.1) 0%, transparent 70%);
filter: blur(60rpx);
border-radius: 50%;
opacity: 0.6;
animation: float 10s ease-in-out infinite;
}
&::after {
content: '';
position: absolute;
bottom: 10%; right: -100rpx;
width: 500rpx; height: 500rpx;
background: radial-gradient(circle, rgba($brand-secondary, 0.1) 0%, transparent 70%);
filter: blur(50rpx);
border-radius: 50%;
opacity: 0.5;
animation: float 15s ease-in-out infinite reverse;
}
}
@keyframes float {
0%, 100% { transform: translate(0, 0); }
50% { transform: translate(30rpx, 50rpx); }
}
/* 顶部 Header */
@ -242,9 +281,11 @@ onShareTimeline(() => {
left: 0;
right: 0;
z-index: 100;
background: #FFFFFF;
background: $bg-glass;
backdrop-filter: blur(20rpx);
padding: 0 24rpx 24rpx;
box-shadow: 0 4rpx 20rpx rgba(0,0,0,0.04);
box-shadow: $shadow-sm;
border-bottom: 1rpx solid $border-color-light;
}
.header-placeholder {
height: 160rpx; /* 根据 header 高度调整 */
@ -253,25 +294,28 @@ onShareTimeline(() => {
.page-title {
font-size: 36rpx;
font-weight: 800;
color: #111;
color: $text-main;
padding: 20rpx 0;
}
/* 搜索框 */
.search-box {
margin-bottom: 20rpx;
margin-top: 20rpx;
}
.search-input-wrap {
display: flex;
align-items: center;
background: #F5F7FA;
border-radius: 16rpx;
background: rgba(255, 255, 255, 0.6);
border: 1px solid rgba(255, 255, 255, 0.8);
border-radius: $radius-round;
padding: 18rpx 24rpx;
transition: all 0.3s;
}
.search-input-wrap:focus-within {
background: #FFF;
box-shadow: 0 0 0 2rpx #FF9F43;
background: $bg-card;
border-color: $brand-primary;
box-shadow: 0 0 0 4rpx rgba($brand-primary, 0.1);
}
.search-icon {
font-size: 28rpx;
@ -281,10 +325,10 @@ onShareTimeline(() => {
.search-input {
flex: 1;
font-size: 28rpx;
color: #333;
color: $text-main;
}
.placeholder-style {
color: #999;
color: $text-tertiary;
}
/* 筛选行 */
@ -298,39 +342,40 @@ onShareTimeline(() => {
flex: 1;
display: flex;
align-items: center;
background: #F5F7FA;
border-radius: 12rpx;
background: $bg-secondary;
border-radius: $radius-md;
padding: 10rpx 20rpx;
}
.price-label {
font-size: 24rpx;
color: #666;
color: $text-sub;
margin-right: 16rpx;
}
.price-input {
flex: 1;
font-size: 26rpx;
text-align: center;
color: #333;
color: $text-main;
}
.price-ph {
color: #BBB;
color: $text-tertiary;
font-size: 24rpx;
}
.price-sep {
color: #CCC;
color: $text-tertiary;
margin: 0 10rpx;
}
.filter-btn {
background: linear-gradient(135deg, #FF9F43, #FF6B35);
color: white;
background: $gradient-brand;
color: $text-inverse;
font-size: 26rpx;
font-weight: 600;
border-radius: 12rpx;
border-radius: $radius-md;
padding: 0 32rpx;
height: 64rpx;
line-height: 64rpx;
border: none;
box-shadow: $shadow-sm;
}
.btn-hover {
opacity: 0.9;
@ -348,19 +393,34 @@ onShareTimeline(() => {
}
/* 商品卡片 */
.product-item {
animation: fadeInUp 0.5s ease-out backwards;
}
@for $i from 1 through 10 {
.product-item:nth-child(#{$i}) {
animation-delay: #{$i * 0.05}s;
}
}
.product-card {
background: #FFFFFF;
border-radius: 20rpx;
background: $bg-card;
border-radius: $radius-lg;
overflow: hidden;
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.04);
box-shadow: $shadow-card;
display: flex;
flex-direction: column;
transition: all 0.3s ease;
}
.product-item:active .product-card {
transform: scale(0.98);
box-shadow: $shadow-sm;
}
.thumb-wrap {
position: relative;
width: 100%;
padding-top: 100%; /* 1:1 Aspect Ratio */
background: #F9F9F9;
background: $bg-secondary;
}
.product-thumb {
position: absolute;
@ -374,11 +434,14 @@ onShareTimeline(() => {
position: absolute;
bottom: 0;
right: 0;
background: rgba(0,0,0,0.6);
background: rgba($accent-red, 0.9);
color: #fff;
font-size: 20rpx;
padding: 4rpx 12rpx;
border-top-left-radius: 12rpx;
backdrop-filter: blur(4px);
font-weight: 700;
box-shadow: 0 -2rpx 8rpx rgba(0,0,0,0.1);
}
.product-info {
@ -391,7 +454,7 @@ onShareTimeline(() => {
.product-title {
font-size: 28rpx;
color: #333;
color: $text-main;
line-height: 1.4;
height: 2.8em; /* 2 lines */
overflow: hidden;
@ -399,6 +462,7 @@ onShareTimeline(() => {
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
margin-bottom: 16rpx;
font-weight: 600;
}
.product-bottom {
@ -409,7 +473,7 @@ onShareTimeline(() => {
gap: 8rpx;
}
.price-row {
color: #FF5500;
color: $accent-red;
font-weight: 700;
display: flex;
align-items: baseline;
@ -421,9 +485,9 @@ onShareTimeline(() => {
font-size: 34rpx;
}
.points-badge {
background: #FFF0E6;
color: #FF6B35;
border: 1px solid rgba(255, 107, 53, 0.2);
background: rgba($brand-primary, 0.1);
color: $brand-primary;
border: 1px solid rgba($brand-primary, 0.2);
border-radius: 8rpx;
padding: 2rpx 10rpx;
display: flex;
@ -447,8 +511,8 @@ onShareTimeline(() => {
.spinner {
width: 50rpx;
height: 50rpx;
border: 4rpx solid #ddd;
border-top-color: #FF9F43;
border: 4rpx solid rgba($brand-primary, 0.2);
border-top-color: $brand-primary;
border-radius: 50%;
animation: spin 0.8s linear infinite;
}
@ -466,12 +530,23 @@ onShareTimeline(() => {
opacity: 0.6;
}
.empty-text {
color: #999;
color: $text-tertiary;
font-size: 28rpx;
}
.check-text {
font-size: 26rpx;
color: #888;
color: $text-sub;
}
@keyframes fadeInUp {
from {
opacity: 0;
transform: translateY(30rpx);
}
to {
opacity: 1;
transform: translateY(0);
}
}
</style>

164
uni.scss
View File

@ -6,98 +6,96 @@
*/
/* ============================================
🎨 品牌色彩系统 - 潮玩暖色调
🎨 品牌色彩系统 - 潮玩盲盒 Pro (2025 Refined)
============================================ */
/* 主色 - 暖橙渐变 */
$primary-orange: #FF9F43; // 活力橙
$primary-deep: #FF6B35; // 深橙红
$primary-light: #FFB366; // 浅橙
/* 主色调 - 更加活力与现代 */
$brand-primary: #FF6B00; // 核心品牌橙 (更纯粹)
$brand-secondary: #FF9500; // 次级品牌色 (用于渐变/辅助)
$brand-primary-light: #FF9500; // 亮橙
$brand-primary-dark: #E65100; // 深橙
/* 辅助色 */
$accent-gold: #FFD166; // 金币黄
$accent-pink: #FF8FAB; // 少女粉
$accent-coral: #FF7B7B; // 珊瑚红
$accent-purple: #A78BFA; // 梦幻紫
/* 辅助色 - 丰富视觉层次 */
$accent-gold: #FFC107; // 质感金
$accent-red: #FF3B30; // 促销红
$accent-blue: #007AFF; // 科技蓝
$accent-purple: #AF52DE; // 梦幻紫
$accent-pink: #FF2D55; // 活力粉
$accent-cyan: #5AC8FA; // 清新蓝
$color-success: #34C759; // 成功色
$color-warning: #FF9F0A; // 警告色
$color-error: #FF3B30; // 错误色
/* 功能色 */
$success-color: #10B981; // 成功绿
$warning-color: #FBBF24; // 警告黄
$error-color: #EF4444; // 错误红
$info-color: #3B82F6; // 信息蓝
/* 中性色 - 提升阅读体验 */
$text-main: #1D1D1F; // 主要文字 (接近纯黑但柔和)
$text-sub: #86868B; // 次要文字
$text-secondary: $text-sub; // Alias for compatibility
$text-tertiary: #C7C7CC; // 辅助/占位
$text-placeholder: $text-tertiary; // Alias for compatibility
$text-disabled: #D1D1D6; // 禁用状态文字
$text-inverse: #FFFFFF; // 反白文字
/* 中性色 */
$text-primary: #1F2937; // 主要文字
$text-secondary: #6B7280; // 次要文字
$text-tertiary: #9CA3AF; // 辅助文字
$text-inverse: #FFFFFF; // 反色文字
/* 背景色 - 营造氛围 */
$bg-page: #F5F5F7; // 页面底色 (高级灰)
$bg-card: #FFFFFF; // 卡片背景
$bg-glass: rgba(255, 255, 255, 0.8); // 毛玻璃背景
$bg-secondary: #F8F8F8; // 次级背景
$bg-grey: #FAFAFA; // 浅灰背景
/* 背景色 */
$bg-page: #FFF8F3; // 页面暖白底
$bg-card: #FFFFFF; // 卡片白
$bg-warm: #FFF4E6; // 暖色面板
$bg-grey: #F9FAFB; // 冷灰面板
/* 边框色 */
$border-light: #F3F4F6;
$border-normal: #E5E7EB;
$border-warm: rgba(255, 159, 67, 0.2);
/* 渐变色 - 视觉冲击力 */
// 使用 CSS 变量在 style 中定义此处保留 SCSS 变量供编译使用
$gradient-brand: linear-gradient(135deg, #FF9500 0%, #FF5E00 100%);
$gradient-gold: linear-gradient(135deg, #FFD60A 0%, #FF9F0A 100%);
$gradient-red: linear-gradient(135deg, #FF3B30 0%, #D32F2F 100%);
$gradient-purple: linear-gradient(135deg, #BF5AF2 0%, #5E5CE6 100%);
/* ============================================
渐变预设
🌑 暗黑/特殊主题变量 (Dark Mode Support)
============================================ */
$bg-dark: #1A1A2E; // 深邃蓝黑
$bg-dark-card: rgba(30, 30, 50, 0.7); // 暗色玻璃卡片
$text-dark-main: #FFFFFF; // 暗色模式主字
$text-dark-sub: rgba(255, 255, 255, 0.7); // 暗色模式副字
$border-dark: rgba(255, 255, 255, 0.1); // 暗色边框
/* 注意Sass变量不能存储CSS渐变值用于直接引用
以下为文档记录使用时直接写CSS */
// 主渐变linear-gradient(135deg, #FF9F43, #FF6B35)
// 金色渐变linear-gradient(135deg, #FFD166, #FF9F43)
// 粉色渐变linear-gradient(135deg, #FF8FAB, #FF6B81)
// 卡片高光linear-gradient(145deg, #FFFFFF, #FFF8F3)
/* ============================================
📐 间距与圆角
📐 布局与间距
============================================ */
$font-xxs: 18rpx;
$font-xs: 22rpx;
$font-sm: 24rpx;
$font-md: 28rpx;
$font-lg: 32rpx;
$font-xl: 36rpx;
$font-xxl: 48rpx;
/* 间距 */
$spacing-xs: 8rpx;
$spacing-sm: 12rpx;
$spacing-md: 16rpx;
$spacing-lg: 24rpx;
$spacing-xl: 32rpx;
$spacing-2xl: 48rpx;
$spacing-xxl: 48rpx;
/* 圆角 */
$radius-sm: 8rpx;
$radius-md: 12rpx;
$radius-lg: 16rpx;
$radius-xl: 24rpx;
$radius-full: 999rpx;
$radius-md: 16rpx;
$radius-lg: 24rpx;
$radius-xl: 32rpx;
$radius-round: 999rpx;
$border-color-light: #F0F0F0;
$border-color: $border-color-light;
/* ============================================
🔤 字体系统
阴影与质感
============================================ */
$font-size-xs: 22rpx;
$font-size-sm: 24rpx;
$font-size-base: 28rpx;
$font-size-md: 30rpx;
$font-size-lg: 32rpx;
$font-size-xl: 36rpx;
$font-size-2xl: 44rpx;
$font-size-3xl: 56rpx;
$font-weight-normal: 400;
$font-weight-medium: 500;
$font-weight-semibold: 600;
$font-weight-bold: 700;
/* ============================================
🌟 阴影效果
============================================ */
$shadow-xs: 0 1rpx 4rpx rgba(0, 0, 0, 0.02);
$shadow-sm: 0 2rpx 8rpx rgba(0, 0, 0, 0.04);
$shadow-md: 0 8rpx 24rpx rgba(0, 0, 0, 0.08);
$shadow-md: 0 6rpx 16rpx rgba(0, 0, 0, 0.08);
$shadow-card: 0 8rpx 24rpx rgba(0, 0, 0, 0.06);
$shadow-float: 0 16rpx 48rpx rgba(255, 107, 0, 0.15); // 悬浮投影
$shadow-inner: inset 0 2rpx 6rpx rgba(0, 0, 0, 0.04);
$shadow-lg: 0 16rpx 48rpx rgba(0, 0, 0, 0.12);
$shadow-warm: 0 8rpx 24rpx rgba(255, 107, 53, 0.15);
$shadow-glow: 0 4rpx 16rpx rgba(255, 159, 67, 0.4);
@ -117,13 +115,13 @@ $ease-bounce: cubic-bezier(0.68, -0.55, 0.265, 1.55);
============================================ */
/* 行为相关颜色 - 使用新配色 */
$uni-color-primary: $primary-orange;
$uni-color-success: $success-color;
$uni-color-warning: $warning-color;
$uni-color-error: $error-color;
$uni-color-primary: $brand-primary;
$uni-color-success: #10B981;
$uni-color-warning: $accent-gold;
$uni-color-error: $accent-red;
/* 文字基本颜色 */
$uni-text-color: $text-primary;
$uni-text-color: $text-main;
$uni-text-color-inverse: $text-inverse;
$uni-text-color-grey: $text-tertiary;
$uni-text-color-placeholder: $text-tertiary;
@ -131,12 +129,12 @@ $uni-text-color-disable: #D1D5DB;
/* 背景颜色 */
$uni-bg-color: $bg-card;
$uni-bg-color-grey: $bg-grey;
$uni-bg-color-grey: $bg-page;
$uni-bg-color-hover: #FFF0E6;
$uni-bg-color-mask: rgba(0, 0, 0, 0.5);
/* 边框颜色 */
$uni-border-color: $border-normal;
$uni-border-color: #E5E7EB;
/* 尺寸变量 */
$uni-font-size-sm: 12px;
@ -167,9 +165,21 @@ $uni-spacing-col-lg: 14px;
$uni-opacity-disabled: 0.4;
/* 文章场景相关 */
$uni-color-title: $text-primary;
$uni-color-title: $text-main;
$uni-font-size-title: 20px;
$uni-color-subtitle: $text-secondary;
$uni-color-subtitle: $text-sub;
$uni-font-size-subtitle: 16px;
$uni-color-paragraph: $text-secondary;
$uni-color-paragraph: $text-sub;
$uni-font-size-paragraph: 15px;
/* ============================================
🛠 工具 Mixins
============================================ */
@mixin text-ellipsis($lines: 1) {
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: $lines;
-webkit-box-orient: vertical;
}

34
说明文档.md Normal file
View File

@ -0,0 +1,34 @@
# 说明文档
## 一、项目规划
### 1.1 项目概述
本项目为 Uni-App 开发的 bindbox-mini 小程序。当前阶段任务为优化现有 UI 设计,重点调整色彩、按钮样式及视觉层级,保持整体布局不变。
### 1.2 实施方案
1. **全局样式分析**:检查 `uni.scss` 及各页面样式,提取现有色彩和组件样式。
2. **视觉优化设计**
* 定义新的色彩系统(主色、辅助色、中性色)。
* 优化按钮样式(圆角、阴影、交互态)。
* 提升卡片及列表的视觉质感。
3. **代码实现**
* 更新 `uni.scss` 变量。
* 重构主要组件/页面的样式代码。
4. **验证与测试**:确保各页面视觉一致且无布局崩坏。
### 1.3 进度记录
* [x] 2025-12-17: 初始化说明文档,启动 UI 优化任务。
* [x] 2025-12-17: 完成全局 SCSS 变量定义 (`uni.scss`),建立色彩与设计系统。
* [x] 2025-12-17: 优化 `pages/index/index.vue` (首页),集成新设计系统与微交互动画。
* [x] 2025-12-17: 优化 `pages/activity/pata/index.vue` (帕塔页面),增强动画与视觉质感。
* [x] 2025-12-17: 优化 `pages/activity/wuxianshang/index.vue` (无限赏),统一视觉风格。
* [x] 2025-12-17: 优化 `pages/mine/index.vue` (个人中心),实现磨砂玻璃效果与动态交互。
* [x] 2025-12-17: 优化 `pages/orders/index.vue` (订单列表),增强状态标识与列表质感。
* [x] 2025-12-17: 修复 `pages/address` 模块编译错误,并完成地址管理页面的样式标准化优化。
* [x] 2025-12-17: 修复 `components/ElCard.vue``components/YifanSelector.vue` 中的未定义变量错误,统一组件样式。
* [x] 2025-12-17: 优化 `pages/activity/wuxianshang/index.vue` (无限赏),替换硬编码样式为全局变量。
* [x] 2025-12-17: 修复 `pages/activity/yifanshang/index.vue` 编译错误,在 `uni.scss` 中补充 `text-ellipsis` mixin 定义。
* [x] 2025-12-17: 修复 `pages/login/index.vue` 等多处 `$border-color` 未定义错误,在 `uni.scss` 中增加变量别名。
* [x] 2025-12-17: 修复 `pages/mine/index.vue` 编译错误,在 `api/appUser.js` 中补充 `getUserInfo`, `getUserTasks`, `getInviteRecords` 导出。
* [ ] 2025-12-17: 进行中 - 优化 `pages/activity/yifanshang/index.vue` 及相关组件。
* [ ] 2025-12-17: 待开始 - 优化 `pages/login/index.vue` 视觉细节。