gcx/frontend/miniapp/src/pages/h5-activity/index.tsx

553 lines
13 KiB
TypeScript

import React from 'react';
import { t } from '@/i18n';
// Taro mini-program component
/**
* H5 Activity / Campaign Landing Page
*
* 活动落地页 - 通过微信/社交媒体分享的促销活动页面
* 包含:倒计时、优惠券卡片、活动规则、分享栏
*/
const H5ActivityPage: React.FC = () => {
return (
<view className="activity-page">
{/* Hero Banner */}
<view className="hero-banner">
<view className="hero-badge">
<text className="hero-badge-icon">🔥</text>
<text className="hero-badge-text">{t('activity_flash')}</text>
</view>
<text className="hero-title">{t('activity_title')}</text>
<text className="hero-subtitle">{t('activity_subtitle')}</text>
{/* Countdown Timer */}
<view className="countdown-section">
<text className="countdown-label">{t('activity_countdown')}</text>
<view className="countdown-timer">
<view className="countdown-block">
<text className="countdown-num">02</text>
</view>
<text className="countdown-sep">:</text>
<view className="countdown-block">
<text className="countdown-num">18</text>
</view>
<text className="countdown-sep">:</text>
<view className="countdown-block">
<text className="countdown-num">45</text>
</view>
<text className="countdown-sep">:</text>
<view className="countdown-block countdown-block-ms">
<text className="countdown-num-ms">32</text>
</view>
</view>
</view>
</view>
{/* Featured Coupon Cards */}
<view className="coupon-section">
<view className="section-header">
<text className="section-title">{t('activity_featured')}</text>
<text className="section-subtitle">{t('activity_limited')}</text>
</view>
{[
{
brand: 'Starbucks',
brandInitial: 'S',
name: '星巴克 ¥50 礼品卡',
originalPrice: '¥50.00',
discountPrice: '¥35.00',
discount: '7折',
tag: t('activity_tag_hot'),
},
{
brand: 'Amazon',
brandInitial: 'A',
name: 'Amazon ¥200 购物券',
originalPrice: '¥200.00',
discountPrice: '¥156.00',
discount: '7.8折',
tag: t('activity_tag_selling'),
},
{
brand: 'Nike',
brandInitial: 'N',
name: 'Nike ¥100 运动券',
originalPrice: '¥100.00',
discountPrice: '¥72.00',
discount: '7.2折',
tag: t('activity_tag_new'),
},
].map((coupon, i) => (
<view key={i} className="coupon-card">
{/* Discount Badge */}
<view className="coupon-badge">
<text className="coupon-badge-text">{coupon.tag}</text>
</view>
{/* Card Top: Brand + Image */}
<view className="coupon-card-top">
<view className="coupon-image-area">
<text className="coupon-image-icon">🎫</text>
</view>
<view className="coupon-discount-tag">
<text className="coupon-discount-text">{coupon.discount}</text>
</view>
</view>
{/* Card Body */}
<view className="coupon-card-body">
<view className="coupon-brand-row">
<view className="coupon-brand-avatar">
<text className="coupon-brand-initial">{coupon.brandInitial}</text>
</view>
<text className="coupon-brand-name">{coupon.brand}</text>
</view>
<text className="coupon-name">{coupon.name}</text>
<view className="coupon-price-row">
<text className="coupon-price-symbol">¥</text>
<text className="coupon-price-value">{coupon.discountPrice.replace('¥', '')}</text>
<text className="coupon-original-price">{coupon.originalPrice}</text>
</view>
</view>
{/* Buy Button */}
<view className="coupon-buy-btn">
<text className="coupon-buy-text">{t('activity_buy_now')}</text>
</view>
</view>
))}
</view>
{/* Activity Rules */}
<view className="rules-section">
<view className="rules-header">
<view className="rules-icon">
<text className="rules-icon-text">📋</text>
</view>
<text className="rules-title">{t('activity_rules')}</text>
</view>
<view className="rules-list">
{[
t('activity_rule_1'),
t('activity_rule_2'),
t('activity_rule_3'),
t('activity_rule_4'),
t('activity_rule_5'),
t('activity_rule_6'),
t('activity_rule_7'),
].map((rule, i) => (
<view key={i} className="rule-item">
<view className="rule-dot" />
<text className="rule-text">{rule}</text>
</view>
))}
</view>
</view>
{/* Share Bar */}
<view className="share-bar">
<view className="share-info">
<text className="share-count-icon">👥</text>
<text className="share-count-text"> 2,386 </text>
</view>
<view className="share-btn">
<text className="share-btn-icon">📤</text>
<text className="share-btn-text">{t('share_to_friends')}</text>
</view>
</view>
{/* Brand Footer */}
<view className="brand-footer">
<view className="footer-logo">
<view className="footer-logo-box">
<text className="footer-logo-text">G</text>
</view>
<text className="footer-logo-name">Genex</text>
</view>
<text className="footer-slogan">{t('app_platform_slogan')}</text>
<text className="footer-copyright">© 2026 Genex. All rights reserved.</text>
</view>
</view>
);
};
export default H5ActivityPage;
/*
CSS (H5活动页样式 - 对应 index.scss):
.activity-page {
min-height: 100vh;
background: #F8F9FC;
padding-bottom: 180rpx;
}
/* === Hero Banner === */
.hero-banner {
background: linear-gradient(135deg, #6C5CE7 0%, #9B8FFF 100%);
padding: 80rpx 40rpx 60rpx;
display: flex;
flex-direction: column;
align-items: center;
border-radius: 0 0 40rpx 40rpx;
position: relative;
overflow: hidden;
}
.hero-banner::after {
content: '';
position: absolute;
width: 400rpx; height: 400rpx;
background: rgba(255,255,255,0.06);
border-radius: 50%;
top: -100rpx; right: -80rpx;
}
.hero-badge {
display: flex;
align-items: center;
padding: 8rpx 24rpx;
background: rgba(255,255,255,0.2);
border-radius: 999rpx;
margin-bottom: 24rpx;
}
.hero-badge-icon { font-size: 24rpx; margin-right: 8rpx; }
.hero-badge-text { font-size: 24rpx; color: white; font-weight: 500; }
.hero-title {
font-size: 44rpx;
font-weight: 700;
color: white;
text-align: center;
letter-spacing: 2rpx;
}
.hero-subtitle {
font-size: 28rpx;
color: rgba(255,255,255,0.8);
margin-top: 12rpx;
text-align: center;
}
/* Countdown */
.countdown-section {
margin-top: 40rpx;
display: flex;
flex-direction: column;
align-items: center;
}
.countdown-label {
font-size: 24rpx;
color: rgba(255,255,255,0.7);
margin-bottom: 16rpx;
}
.countdown-timer {
display: flex;
align-items: center;
}
.countdown-block {
width: 72rpx; height: 72rpx;
background: rgba(0,0,0,0.25);
border-radius: 12rpx;
display: flex;
align-items: center;
justify-content: center;
}
.countdown-block-ms {
width: 60rpx; height: 60rpx;
background: rgba(0,0,0,0.15);
border-radius: 10rpx;
}
.countdown-num {
font-size: 36rpx;
font-weight: 700;
color: white;
font-family: 'DIN Alternate', 'Roboto Mono', monospace;
}
.countdown-num-ms {
font-size: 28rpx;
font-weight: 700;
color: rgba(255,255,255,0.8);
font-family: 'DIN Alternate', 'Roboto Mono', monospace;
}
.countdown-sep {
font-size: 28rpx;
font-weight: 700;
color: rgba(255,255,255,0.6);
margin: 0 8rpx;
}
/* === Coupon Section === */
.coupon-section {
padding: 32rpx;
}
.section-header {
margin-bottom: 24rpx;
}
.section-title {
font-size: 36rpx;
font-weight: 700;
color: #141723;
display: block;
}
.section-subtitle {
font-size: 24rpx;
color: #A0A8BE;
margin-top: 4rpx;
display: block;
}
.coupon-card {
background: white;
border-radius: 24rpx;
margin-bottom: 24rpx;
border: 1rpx solid #F1F3F8;
overflow: hidden;
position: relative;
box-shadow: 0 4rpx 24rpx rgba(0,0,0,0.04);
}
.coupon-badge {
position: absolute;
top: 0; left: 0;
background: linear-gradient(135deg, #FF6B6B, #FF8E8E);
padding: 6rpx 20rpx 6rpx 16rpx;
border-radius: 0 0 16rpx 0;
z-index: 2;
}
.coupon-badge-text {
font-size: 22rpx;
font-weight: 700;
color: white;
}
.coupon-card-top {
height: 200rpx;
background: linear-gradient(135deg, #F3F1FF 0%, #E8E4FF 100%);
display: flex;
align-items: center;
justify-content: center;
position: relative;
}
.coupon-image-area {
width: 160rpx; height: 160rpx;
display: flex;
align-items: center;
justify-content: center;
}
.coupon-image-icon { font-size: 80rpx; opacity: 0.5; }
.coupon-discount-tag {
position: absolute;
top: 16rpx; right: 16rpx;
background: linear-gradient(135deg, #6C5CE7, #9B8FFF);
padding: 8rpx 20rpx;
border-radius: 999rpx;
}
.coupon-discount-text {
font-size: 24rpx;
font-weight: 700;
color: white;
}
.coupon-card-body {
padding: 24rpx 28rpx;
}
.coupon-brand-row {
display: flex;
align-items: center;
margin-bottom: 12rpx;
}
.coupon-brand-avatar {
width: 40rpx; height: 40rpx;
background: #F1F3F8;
border-radius: 8rpx;
display: flex;
align-items: center;
justify-content: center;
margin-right: 12rpx;
}
.coupon-brand-initial {
font-size: 22rpx;
font-weight: 700;
color: #6C5CE7;
}
.coupon-brand-name {
font-size: 24rpx;
color: #5C6478;
}
.coupon-name {
font-size: 30rpx;
font-weight: 600;
color: #141723;
display: block;
margin-bottom: 16rpx;
}
.coupon-price-row {
display: flex;
align-items: flex-end;
}
.coupon-price-symbol {
font-size: 24rpx;
font-weight: 700;
color: #6C5CE7;
margin-bottom: 4rpx;
}
.coupon-price-value {
font-size: 40rpx;
font-weight: 700;
color: #6C5CE7;
line-height: 1;
margin-right: 12rpx;
}
.coupon-original-price {
font-size: 24rpx;
color: #A0A8BE;
text-decoration: line-through;
margin-bottom: 4rpx;
}
.coupon-buy-btn {
margin: 0 28rpx 28rpx;
height: 80rpx;
background: linear-gradient(135deg, #6C5CE7, #9B8FFF);
border-radius: 16rpx;
display: flex;
align-items: center;
justify-content: center;
}
.coupon-buy-text {
font-size: 28rpx;
font-weight: 600;
color: white;
letter-spacing: 2rpx;
}
/* === Rules Section === */
.rules-section {
margin: 0 32rpx;
background: white;
border-radius: 24rpx;
padding: 32rpx;
border: 1rpx solid #F1F3F8;
}
.rules-header {
display: flex;
align-items: center;
margin-bottom: 24rpx;
padding-bottom: 20rpx;
border-bottom: 1rpx solid #F1F3F8;
}
.rules-icon {
width: 48rpx; height: 48rpx;
background: #F3F1FF;
border-radius: 12rpx;
display: flex;
align-items: center;
justify-content: center;
margin-right: 16rpx;
}
.rules-icon-text { font-size: 28rpx; }
.rules-title {
font-size: 30rpx;
font-weight: 600;
color: #141723;
}
.rules-list { padding: 0; }
.rule-item {
display: flex;
align-items: flex-start;
margin-bottom: 20rpx;
}
.rule-dot {
width: 10rpx; height: 10rpx;
background: #6C5CE7;
border-radius: 50%;
margin-top: 14rpx;
margin-right: 16rpx;
flex-shrink: 0;
}
.rule-text {
font-size: 24rpx;
color: #5C6478;
line-height: 1.6;
}
/* === Share Bar === */
.share-bar {
position: fixed;
bottom: 0; left: 0; right: 0;
height: 120rpx;
background: white;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 32rpx;
border-top: 1rpx solid #F1F3F8;
box-shadow: 0 -4rpx 24rpx rgba(0,0,0,0.06);
z-index: 100;
}
.share-info {
display: flex;
align-items: center;
}
.share-count-icon { font-size: 32rpx; margin-right: 8rpx; }
.share-count-text {
font-size: 24rpx;
color: #5C6478;
}
.share-btn {
display: flex;
align-items: center;
padding: 16rpx 40rpx;
background: linear-gradient(135deg, #6C5CE7, #9B8FFF);
border-radius: 999rpx;
}
.share-btn-icon { font-size: 28rpx; margin-right: 8rpx; }
.share-btn-text {
font-size: 28rpx;
font-weight: 600;
color: white;
}
/* === Brand Footer === */
.brand-footer {
padding: 60rpx 32rpx 40rpx;
display: flex;
flex-direction: column;
align-items: center;
}
.footer-logo {
display: flex;
align-items: center;
margin-bottom: 12rpx;
}
.footer-logo-box {
width: 48rpx; height: 48rpx;
background: linear-gradient(135deg, #6C5CE7, #9B8FFF);
border-radius: 12rpx;
display: flex;
align-items: center;
justify-content: center;
margin-right: 12rpx;
}
.footer-logo-text {
font-size: 28rpx;
font-weight: 700;
color: white;
}
.footer-logo-name {
font-size: 30rpx;
font-weight: 600;
color: #141723;
}
.footer-slogan {
font-size: 22rpx;
color: #A0A8BE;
margin-bottom: 8rpx;
}
.footer-copyright {
font-size: 20rpx;
color: #C8CDDA;
}
*/