Files
wx_pbzc/pages/index/index.wxss
T
lc 6f89494c0b feat(index): 首页改版 hero + 进度点地图 + 计时环 dial + CTA 脉冲
- 全宽橙渐变 hero:头像+昵称+按小时问候+「时长」敢不敢来挑战+连胜(昵称同行)
- 进度点地图 quest-card 上浮叠 hero,圆点+连线 done/now/final 三态,与 CTA 等宽
- 计时环 dial 虚线刻度环+呼吸动画,整体放大(320rpx/数字96rpx)
- CTA「立即挑战+时长」带脉冲,保留自由/循环入口
- 千卡按 4 千卡/分钟估算(激励参考);删除「今天还没开始」整段与连胜前图标
- 循环训练秒数步进 ±10;取消每日语录模块
2026-08-11 14:32:25 +08:00

462 lines
9.1 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* ===== 全宽渐变头图 hero ===== */
/* 负 margin 抵消 container 的 24rpx 内边距,让头图左右贯穿并贴到导航栏底边;
底部留大内边距给下方 quest-card 负 margin 上浮叠住。文字统一白色,图标用
*White 变体(若有)。hero 用 opacity-only 动画,避免 transform 把 .container
变成 containing block 而破坏弹窗定位(同 app.wxss pageIn 思路)。 */
.hero {
margin: -24rpx -24rpx 0;
padding: 24rpx 24rpx 72rpx;
background: linear-gradient(160deg, var(--primary) 0%, var(--primary-light) 100%);
color: #fff;
position: relative;
overflow: hidden;
animation: heroFade 0.4s ease both;
}
.hero::after {
content: '';
position: absolute;
right: -60rpx;
top: -60rpx;
width: 240rpx;
height: 240rpx;
border-radius: 50%;
background: radial-gradient(circle, rgba(255, 255, 255, 0.18), transparent 70%);
pointer-events: none;
}
@keyframes heroFade {
from { opacity: 0; }
to { opacity: 1; }
}
/* 顶部行:圆形头像 + 时间问候 */
.hero-top {
display: flex;
align-items: center;
gap: 18rpx;
}
.hero-avatar {
width: 84rpx;
height: 84rpx;
flex-shrink: 0;
border-radius: 50%;
overflow: hidden;
background: #fff;
display: flex;
align-items: center;
justify-content: center;
border: 3rpx solid rgba(255, 255, 255, 0.6);
}
.hero-avatar-img {
width: 100%;
height: 100%;
border-radius: 50%;
display: block;
}
/* 有头像时去掉白底,只留浅描边,避免深色头像边缘露白缝 */
.hero-avatar.has-avatar {
background: transparent;
border-color: rgba(255, 255, 255, 0.85);
}
.hero-user {
display: flex;
flex-direction: row;
align-items: center;
gap: 14rpx;
min-width: 0;
}
.hero-greet {
font-size: 28rpx;
color: rgba(255, 255, 255, 0.92);
font-weight: 500;
}
/* 挑战主句:时长强调色 + 「敢不敢」白字 */
.hero-challenge {
margin-top: 28rpx;
display: flex;
align-items: baseline;
flex-wrap: wrap;
}
.hero-time {
font-size: 48rpx;
font-weight: 800;
color: #FFE3C2;
letter-spacing: 1rpx;
margin-right: 12rpx;
font-variant-numeric: tabular-nums;
}
.hero-cta-text {
font-size: 44rpx;
font-weight: 800;
color: #fff;
text-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.15);
line-height: 1.2;
}
.hero-social {
margin-top: 0;
font-size: 28rpx;
color: rgba(255, 255, 255, 0.9);
}
/* ===== 闯关进度地图(上浮卡片) ===== */
.quest-card {
margin-top: -56rpx;
margin-left: 0;
margin-right: 0;
position: relative;
z-index: 2;
}
.quest-head {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 24rpx;
}
.quest-title {
font-size: 32rpx;
font-weight: 700;
color: var(--text);
}
.quest-sub {
font-size: 24rpx;
font-weight: 400;
color: var(--text-secondary);
margin-left: 12rpx;
}
.quest-trophy {
font-size: 40rpx;
}
.quest-map {
display: flex;
align-items: center;
padding: 8rpx 4rpx;
}
.q-node {
width: 48rpx;
height: 48rpx;
border-radius: 50%;
flex-shrink: 0;
display: flex;
align-items: center;
justify-content: center;
font-size: 24rpx;
font-weight: 700;
background: var(--bg-soft);
color: var(--text-secondary);
}
.q-node.done {
background: var(--primary);
color: #fff;
}
.q-node.now {
background: linear-gradient(135deg, var(--primary), var(--primary-light));
color: #fff;
box-shadow: 0 0 0 6rpx rgba(var(--primary-rgb), 0.18);
animation: qPulse 1.6s ease-in-out infinite;
}
.q-node.final {
background: #FFF3E0;
font-size: 30rpx;
}
.q-link {
flex: 1;
height: 4rpx;
background: var(--bg-soft);
margin: 0 2rpx;
}
.q-link.done {
background: var(--primary);
}
.quest-tip {
display: block;
margin-top: 20rpx;
font-size: 24rpx;
font-weight: 600;
color: var(--primary);
}
@keyframes qPulse {
0% { box-shadow: 0 0 0 4rpx rgba(var(--primary-rgb), 0.28); }
70% { box-shadow: 0 0 0 12rpx rgba(var(--primary-rgb), 0); }
100% { box-shadow: 0 0 0 4rpx rgba(var(--primary-rgb), 0); }
}
/* ===== 计时环 dial ===== */
.timer-wrap {
text-align: center;
margin: 32rpx 0 8rpx;
}
.dial {
width: 320rpx;
height: 320rpx;
border-radius: 50%;
margin: 0 auto;
position: relative;
background: radial-gradient(circle at 35% 30%, #ffffff, #f4f6f2 70%);
box-shadow: inset 0 4rpx 14rpx rgba(var(--primary-rgb), 0.12), 0 10rpx 24rpx rgba(var(--primary-rgb), 0.12);
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
animation: ringBreathe 3s ease-in-out infinite;
}
/* 虚线刻度环 */
.dial::before {
content: '';
position: absolute;
inset: 14rpx;
border-radius: 50%;
border: 2rpx dashed rgba(var(--primary-rgb), 0.28);
}
.dial-time {
font-size: 84rpx;
font-weight: 800;
color: var(--primary);
font-variant-numeric: tabular-nums;
letter-spacing: -1rpx;
line-height: 1;
max-width: 280rpx;
text-align: center;
white-space: nowrap;
overflow: hidden;
}
.dial-label {
font-size: 24rpx;
color: var(--text-secondary);
margin-top: 8rpx;
}
.benefit {
margin-top: 20rpx;
font-size: 28rpx;
color: var(--text-secondary);
}
.benefit-hl {
color: var(--primary);
font-weight: 700;
font-size: 30rpx;
}
@keyframes ringBreathe {
0%, 100% { transform: scale(1); }
50% { transform: scale(1.02); }
}
/* ===== action buttons ===== */
.action-buttons {
display: flex;
flex-direction: column;
gap: 24rpx;
margin: 8rpx 0 8rpx;
}
/* 自由训练 / 循环训练 并排一行 */
.action-row {
display: flex;
gap: 16rpx;
}
.action-row .action-cell {
flex: 1;
min-width: 0; /* 防止图标+文字在窄屏撑破 flex 项 */
}
/* 主按钮脉冲发光(加在 ui-btn 宿主上,__usePrivacyCheck__ 不影响) */
@keyframes ctaPulse {
0%, 100% { box-shadow: 0 8rpx 20rpx rgba(var(--primary-rgb), 0.35); }
50% { box-shadow: 0 8rpx 30rpx rgba(var(--primary-rgb), 0.6); }
}
/* ===== picker ===== */
.picker-title {
font-size: 34rpx;
font-weight: 600;
color: var(--text);
display: block;
text-align: center;
margin-bottom: 32rpx;
}
.preset-grid {
display: flex;
flex-wrap: wrap;
gap: 16rpx;
margin-bottom: 28rpx;
}
.preset-item {
flex: 0 0 calc(33.33% - 12rpx);
box-sizing: border-box;
background: var(--bg-soft);
border: 2rpx solid transparent;
border-radius: 16rpx;
padding: 20rpx 0;
text-align: center;
display: flex;
flex-direction: column;
transition: all 0.2s ease;
}
.preset-item:active {
transform: scale(0.94);
}
.preset-item.selected {
background: var(--primary-bg);
border: 2rpx solid var(--primary);
}
.preset-num {
font-size: 36rpx;
font-weight: 700;
color: var(--text);
line-height: 1.1;
}
.preset-item.selected .preset-num {
color: var(--primary);
}
.preset-unit {
font-size: 20rpx;
color: var(--text-secondary);
margin-top: 2rpx;
line-height: 1;
}
.custom-input-row {
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 28rpx;
}
.custom-label {
font-size: 28rpx;
color: var(--text-secondary);
line-height: 1;
}
.custom-input {
width: 160rpx;
height: 64rpx;
background: var(--bg-soft);
border-radius: 12rpx;
text-align: center;
font-size: 32rpx;
font-weight: 600;
color: var(--primary);
margin: 0 16rpx;
}
.picker-cancel {
display: block;
text-align: center;
font-size: 28rpx;
color: var(--text-secondary);
padding: 12rpx 0;
margin-top: 8rpx;
}
/* ===== circuit (循环训练) config panel ===== */
.picker-sub {
display: block;
text-align: center;
font-size: 24rpx;
color: var(--text-secondary);
margin: -18rpx 0 24rpx;
}
.circuit-row {
display: flex;
align-items: center;
justify-content: space-between;
padding: 20rpx 8rpx;
border-bottom: 1rpx solid var(--border);
}
.circuit-row-label {
font-size: 30rpx;
color: var(--text);
font-weight: 500;
}
.stepper {
display: flex;
align-items: center;
gap: 20rpx;
}
.stepper-btn {
width: 64rpx;
height: 64rpx;
border-radius: 50%;
background: var(--bg-soft);
color: var(--primary);
font-size: 40rpx;
font-weight: 700;
display: flex;
align-items: center;
justify-content: center;
line-height: 1;
transition: transform 0.12s ease, opacity 0.12s ease;
}
.stepper-btn:active {
transform: scale(0.9);
opacity: 0.8;
}
.stepper-val {
min-width: 124rpx;
text-align: center;
font-size: 32rpx;
font-weight: 700;
color: var(--text);
font-variant-numeric: tabular-nums;
}
/* ===== 训练完成高亮 (3 秒后淡出) ===== */
/* 这个 class 落在 <ui-card> 宿主节点上(ui-card.wxss 已把宿主设为 display:block
否则 border/box-shadow 只会碎成两根竖条、transform 完全不生效)。
描边用 box-shadow 的 spread 而非 borderborder 会撑大宿主 8rpx,高亮出现/消失
时整页布局跳动;box-shadow 不占布局空间。宿主自身无圆角,必须补上与内部卡片
一致的 24rpx,否则描边会是直角框套在圆角卡片外面。 */
.just-completed {
animation: justCompletedPulse 1s ease-in-out 2;
border-radius: 24rpx;
box-shadow: 0 0 0 4rpx var(--primary), 0 4rpx 24rpx rgba(var(--primary-rgb), 0.3);
}
@keyframes justCompletedPulse {
0%, 100% { transform: scale(1); }
50% { transform: scale(1.02); }
}