Files
wx_pbzc/pages/index/index.wxss
T
lc 346d46cb27 feat(index): 新版本更新通知(What's New)弹窗
- 复用 ui-modal(position:center) + ui-btn,不新建组件,风格统一且自动跟随暗黑
- config.js 新增 releaseNotes 数组(每条一行短句),复用已有 version 字段
- 首页 _checkUpdateNote() 在 onShow 检测 storage 版本 vs config.version,
  不一致则居中弹通知并写回 storage 防重复;onCloseUpdateNote 关闭
- 绿色渐变徽章 + sparkleWhite 图标 + 版本标题 + 要点列表 + 知道了按钮
- 纯通知不重启应用;发版时改 version 同步更新 releaseNotes 即可
2026-08-14 10:40:03 +08:00

518 lines
11 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 思路)。 */
/* index-page:仅本页面把 .container 升级为 flex 列,
时钟区 flex:1 居中,操作按钮 margin-top:auto 贴底(不动全局 container)。 */
.index-page {
display: flex;
flex-direction: column;
}
.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-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); }
}
/* ===== 今日目标时长(无圆环, 大字流光) =====
在 index-page 这条 flex 列里 .timer-wrap 充当"中间时钟区":flex:1 占满
hero+quest 与底部按钮之间的剩余高度,内部再垂直居中把"00:30 / 今日目标
时长 / 预计消耗 千卡"这组文字真正落到屏幕中部(原来只是默认排在卡片下方) */
.timer-wrap {
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
text-align: center;
min-height: 0;
}
.time-display {
display: block;
font-family: 'Saira Condensed', 'Arial Narrow', sans-serif;
font-size: 200rpx;
font-weight: 900;
line-height: 1.1;
letter-spacing: 6rpx;
font-variant-numeric: tabular-nums;
color: var(--primary);
text-shadow: 0 8rpx 6rpx rgba(var(--primary-rgb), 0.35);
}
.time-label {
display: block;
font-size: 26rpx;
color: var(--text-secondary);
margin-top: 8rpx;
}
.benefit {
margin-top: 18rpx;
font-size: 28rpx;
color: var(--text-secondary);
}
.benefit-hl {
color: var(--primary);
font-weight: 700;
font-size: 30rpx;
}
/* ===== action buttons ===== */
/* 在 index-page flex 列里,3 个按钮(rechallenge + free + circuit)靠
margin-top:auto 推到列底、紧贴底部 toolbar 上方,与上方居中的时钟
区之间自然留白;gap 保持按钮自身间距不变 */
.action-buttons {
display: flex;
flex-direction: column;
gap: 24rpx;
margin: 8rpx 0 8rpx;
margin-top: auto;
}
/* 自由训练 / 循环训练 并排一行 */
.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); }
}
/* ===== 新版本更新通知(What's New) ===== */
/* slot 内容由页面 wxss 控制;ui-modal--center 的 body 已居中且用 --card-bg,
这里只管内部排版。徽章用负 margin 上探出卡片顶,制造浮动感。 */
.update-note {
display: flex;
flex-direction: column;
align-items: center;
width: 100%;
}
.update-note__badge {
width: 96rpx;
height: 96rpx;
border-radius: 50%;
margin: -76rpx auto 18rpx;
background: linear-gradient(135deg, #4CAF50, #81C784);
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 8rpx 20rpx rgba(76, 175, 80, 0.35);
}
.update-note__icon {
width: 52rpx;
height: 52rpx;
}
.update-note__title {
font-size: 36rpx;
font-weight: 700;
color: var(--text);
line-height: 1.4;
}
.update-note__date {
font-size: 24rpx;
color: var(--text-secondary);
margin-top: 6rpx;
}
.update-note__list {
width: 100%;
margin: 26rpx 0 4rpx;
text-align: left;
box-sizing: border-box;
}
.update-note__item {
display: flex;
align-items: flex-start;
margin-bottom: 16rpx;
}
.update-note__dot {
color: var(--primary);
font-weight: 700;
margin-right: 12rpx;
line-height: 1.5;
flex-shrink: 0;
}
.update-note__text {
flex: 1;
font-size: 27rpx;
color: var(--text);
line-height: 1.5;
text-align: left;
}