From a0894837bdb41beff4dfb49f939cba341a552633 Mon Sep 17 00:00:00 2001
From: wm <2747639460@qq.com>
Date: Wed, 22 Jul 2026 23:25:17 +0800
Subject: [PATCH] =?UTF-8?q?ux:=20=E5=8A=A8=E4=BD=9C=E6=94=B6=E8=97=8F?=
=?UTF-8?q?=E6=8C=89=E9=92=AE=E4=BB=8E=E9=A1=B6=E9=83=A8=E6=B5=AE=E7=AA=97?=
=?UTF-8?q?=E7=A7=BB=E5=88=B0=E5=BA=95=E9=83=A8=EF=BC=8C=E4=B8=8E=E5=8A=A0?=
=?UTF-8?q?=E5=85=A5=E8=AE=A1=E5=88=92=E5=B9=B6=E6=8E=92=20+=20=E5=9B=BE?=
=?UTF-8?q?=E6=A0=87=E7=BE=8E=E5=8C=96?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- detail 顶部 favbtn 浮窗(需避让胶囊、丑)移除,改为底部 addbar 内与 CTA 并排的方形按钮
- fc-icon 新增 filled 属性:收藏态实心心形(Lucide 描边图标默认 fill=none,filled=true 时 fill=stroke 变实心)
- 收藏按钮美化:圆角 24rpx 方形 + 发丝边框,未收藏描边(text-2)、已收藏实心(accent)+ accent-soft 底色 + accent-ring 边框 + 点按 scale 反馈
- detail.js 清理 favRight/favTop 胶囊避让逻辑(不再需要)
---
miniprogram/components/fc-icon/index.js | 15 ++++++++++-----
miniprogram/pages/detail/detail.js | 15 +--------------
miniprogram/pages/detail/detail.wxml | 11 ++++++-----
miniprogram/pages/detail/detail.wxss | 25 ++++++++++++++-----------
4 files changed, 31 insertions(+), 35 deletions(-)
diff --git a/miniprogram/components/fc-icon/index.js b/miniprogram/components/fc-icon/index.js
index 712542c..867e882 100644
--- a/miniprogram/components/fc-icon/index.js
+++ b/miniprogram/components/fc-icon/index.js
@@ -29,23 +29,28 @@ Component({
size: { type: Number, value: 20 },
// 颜色:可传具体 hex,或 var(--xxx)(自动解析为对应 token 色值)
color: { type: String, value: '' },
+ // 是否实心填充(如收藏后实心心形)。默认描边
+ filled: { type: Boolean, value: false },
},
data: { src: '' },
observers: {
- name(n) { this._build(n, this.data.color); },
- color(c) { this._build(this.data.name, c); },
+ name() { this._build(); },
+ color() { this._build(); },
+ filled() { this._build(); },
},
lifetimes: {
- attached() { this._build(this.data.name, this.data.color); },
+ attached() { this._build(); },
},
methods: {
- _build(name, color) {
+ _build() {
+ const { name, color, filled } = this.data;
const inner = iconSvg[name];
if (!inner) { this.setData({ src: '' }); return; }
const stroke = resolveColor(color);
+ const fill = filled ? stroke : 'none';
const body = inner.replace(/__C__/g, stroke);
const svg =
- '';
this.setData({ src: 'data:image/svg+xml,' + encodeURIComponent(svg) });
diff --git a/miniprogram/pages/detail/detail.js b/miniprogram/pages/detail/detail.js
index f5a8519..c0149af 100644
--- a/miniprogram/pages/detail/detail.js
+++ b/miniprogram/pages/detail/detail.js
@@ -7,8 +7,6 @@ const auth = require('../../utils/auth');
Page({
data: {
statusBarHeight: 20,
- favRight: 8,
- favTop: 20,
id: '',
planId: '',
exercise: null,
@@ -23,18 +21,7 @@ Page({
onLoad(query) {
const id = query.id || '';
const planId = query.planId || '';
- // 收藏按钮需避让微信右上角胶囊按钮(···◯):用胶囊实际位置算出安全右/上边距
- let favRight = 8;
- let favTop = (app.globalData.statusBarHeight || 20) + 6;
- try {
- const menu = wx.getMenuButtonBoundingClientRect();
- const win = (wx.getWindowInfo && wx.getWindowInfo()) || wx.getSystemInfoSync();
- if (menu && win) {
- favRight = Math.max(8, win.windowWidth - menu.left + 8);
- favTop = menu.top + Math.max(0, (menu.height - 36) / 2);
- }
- } catch (e) {}
- this.setData({ statusBarHeight: app.globalData.statusBarHeight || 20, favRight, favTop, id, planId });
+ this.setData({ statusBarHeight: app.globalData.statusBarHeight || 20, id, planId });
// 防御:id 缺失直接显示空态,避免请求 /api/exercises/ 导致错乱或 404
if (!id) {
this.setData({ loading: false });
diff --git a/miniprogram/pages/detail/detail.wxml b/miniprogram/pages/detail/detail.wxml
index 5028c74..582a386 100644
--- a/miniprogram/pages/detail/detail.wxml
+++ b/miniprogram/pages/detail/detail.wxml
@@ -1,10 +1,6 @@
-
-
-
-
- {{ planId ? '加入该计划' : '加入计划' }}
+
+
+
+
+ {{ planId ? '加入该计划' : '加入计划' }}
+
diff --git a/miniprogram/pages/detail/detail.wxss b/miniprogram/pages/detail/detail.wxss
index 3af5ca4..4d74850 100644
--- a/miniprogram/pages/detail/detail.wxss
+++ b/miniprogram/pages/detail/detail.wxss
@@ -45,24 +45,27 @@
border-top: 1rpx solid var(--line);
padding-bottom: calc(20rpx + env(safe-area-inset-bottom));
}
+.addbar__inner { display: flex; align-items: center; gap: 20rpx; }
.cta {
+ flex: 1;
display: flex; align-items: center; justify-content: center;
background: linear-gradient(135deg, var(--gold) 0%, var(--gold-2) 100%);
color: var(--accent-on); font-weight: 700; font-size: 32rpx;
- border-radius: 999rpx; padding: 26rpx;
+ border-radius: 999rpx; height: 92rpx; box-sizing: border-box; padding: 0 24rpx;
}
+.fav {
+ flex: 0 0 auto;
+ width: 92rpx; height: 92rpx; box-sizing: border-box;
+ border-radius: 24rpx;
+ background: var(--surface);
+ border: 1rpx solid var(--line);
+ display: flex; align-items: center; justify-content: center;
+ transition: background 200ms var(--ease), border-color 200ms var(--ease), transform 120ms var(--ease);
+}
+.fav--on { background: var(--accent-soft); border-color: var(--accent-ring); }
+.fav--hover { transform: scale(0.94); }
.empty-page { min-height: 100vh; background: var(--bg-grad); }
.topbar { height: 88rpx; display: flex; align-items: center; padding: 0 24rpx; }
.topbar__back { font-size: 56rpx; color: var(--gold); width: 60rpx; line-height: 1; }
.empty { color: var(--text-3); font-size: 28rpx; text-align: center; padding: 120rpx 0; }
-
-.favbtn {
- position: fixed; right: 28rpx; z-index: 60;
- width: 72rpx; height: 72rpx; border-radius: 999rpx;
- background: var(--float-bg);
- backdrop-filter: blur(8px);
- border: 1rpx solid var(--gold-line);
- display: flex; align-items: center; justify-content: center;
- font-size: 44rpx; color: var(--gold-2); line-height: 1;
-}