diff --git a/pets-fe/components/seg-tabs/index.js b/pets-fe/components/seg-tabs/index.js
new file mode 100644
index 0000000..207862d
--- /dev/null
+++ b/pets-fe/components/seg-tabs/index.js
@@ -0,0 +1,38 @@
+// 横向切换控件。此前有三套长得像但尺寸各不同的实现:
+// plan 的 .inline-tabs(灰槽 + 白块)、community 的 .feed-tab(白药丸 + 橙选中 + 阴影)、
+// record 的 .rf-chip(白药丸 + 橙选中 + 无阴影,高度还差 10rpx)
+// 这里合成一个:variant="solid" 对应灰槽白块,variant="pill" 对应横滑药丸。
+//
+// items 支持两种写法:
+// ['推荐','关注','经验'] —— current 传下标
+// [{key:'',label:'全部'},{key:'weight',label:'体重'}] —— current 传 key
+Component({
+ options: { addGlobalClass: true },
+ properties: {
+ items: { type: Array, value: [] },
+ current: { type: null, value: 0 },
+ variant: { type: String, value: 'pill' },
+ },
+ data: { list: [] },
+ observers: {
+ 'items,current': function (items, current) {
+ const byKey = typeof current === 'string';
+ const list = (items || []).map((it, i) => {
+ const obj = it && typeof it === 'object';
+ const key = obj ? it.key : i;
+ return {
+ key,
+ label: obj ? it.label : it,
+ active: byKey ? key === current : i === Number(current),
+ };
+ });
+ this.setData({ list });
+ },
+ },
+ methods: {
+ onTap(e) {
+ const { index, key } = e.currentTarget.dataset;
+ this.triggerEvent('change', { index: Number(index), key });
+ },
+ },
+});
diff --git a/pets-fe/components/seg-tabs/index.json b/pets-fe/components/seg-tabs/index.json
new file mode 100644
index 0000000..a89ef4d
--- /dev/null
+++ b/pets-fe/components/seg-tabs/index.json
@@ -0,0 +1,4 @@
+{
+ "component": true,
+ "usingComponents": {}
+}
diff --git a/pets-fe/components/seg-tabs/index.wxml b/pets-fe/components/seg-tabs/index.wxml
new file mode 100644
index 0000000..0b303f1
--- /dev/null
+++ b/pets-fe/components/seg-tabs/index.wxml
@@ -0,0 +1,9 @@
+
+ {{item.label}}
+
+
+
+ {{item.label}}
+
diff --git a/pets-fe/components/seg-tabs/index.wxss b/pets-fe/components/seg-tabs/index.wxss
new file mode 100644
index 0000000..102f21c
--- /dev/null
+++ b/pets-fe/components/seg-tabs/index.wxss
@@ -0,0 +1,21 @@
+.st{white-space:nowrap}
+
+/* 横滑药丸:数量不定、可滚动(社区分类、记录类型筛选) */
+.st-pill{padding:0 0 var(--sp-4)}
+.st-pill .st-item{
+ display:inline-block;height:var(--h-sm);line-height:var(--h-sm);padding:0 var(--sp-4);
+ margin-right:var(--sp-2);border-radius:var(--r-full);border:1rpx solid var(--line);
+ background:#fff;color:var(--muted);font-size:var(--fs-sm);font-weight:var(--fw-b);
+}
+.st-pill .st-item.on{color:var(--primary-dark);background:var(--primary-soft);border-color:var(--primary-line)}
+
+/* 灰槽白块:数量固定的互斥视图(计划页三段) */
+.st-solid{
+ display:flex;gap:var(--sp-1);padding:var(--sp-1);border-radius:var(--r-md);
+ background:#EFE8DE;margin-bottom:var(--sp-4);
+}
+.st-solid .st-item{
+ flex:1;height:var(--h-sm);line-height:var(--h-sm);text-align:center;border-radius:var(--r-sm);
+ color:var(--muted);font-size:var(--fs-md);font-weight:var(--fw-b);
+}
+.st-solid .st-item.on{background:#fff;color:var(--primary-dark)}
diff --git a/pets-fe/components/stat-ring/index.js b/pets-fe/components/stat-ring/index.js
new file mode 100644
index 0000000..b62c511
--- /dev/null
+++ b/pets-fe/components/stat-ring/index.js
@@ -0,0 +1,41 @@
+// 完成度环。用 SVG data-uri 画(和 record 页的体重折线图同一套路),不用 canvas:
+// canvas 在 scroll-view 里的层级、滚动跟随和截图行为全是坑。
+const TAU = 2 * Math.PI;
+const R = 42; // viewBox 100 下的半径,留出描边宽度
+
+function ringSvg(percent, stroke, track, fill) {
+ const c = TAU * R;
+ const p = Math.max(0, Math.min(100, Number(percent) || 0));
+ const off = c * (1 - p / 100);
+ const circle = (color, dash) =>
+ '';
+ return (
+ ''
+ );
+}
+
+Component({
+ options: { addGlobalClass: true },
+ properties: {
+ percent: { type: Number, value: 0 },
+ size: { type: Number, value: 180 }, // rpx
+ stroke: { type: Number, value: 8 }, // viewBox 单位,即直径的百分比
+ track: { type: String, value: '#FFE6BA' },
+ fill: { type: String, value: '#F5A947' },
+ },
+ data: { src: '', boxStyle: '' },
+ observers: {
+ 'percent,size,stroke,track,fill': function (percent, size, stroke, track, fill) {
+ const svg = ringSvg(percent, stroke, track, fill);
+ this.setData({
+ src: 'data:image/svg+xml,' + encodeURIComponent(svg),
+ boxStyle: 'width:' + size + 'rpx;height:' + size + 'rpx',
+ });
+ },
+ },
+});
diff --git a/pets-fe/components/stat-ring/index.json b/pets-fe/components/stat-ring/index.json
new file mode 100644
index 0000000..a89ef4d
--- /dev/null
+++ b/pets-fe/components/stat-ring/index.json
@@ -0,0 +1,4 @@
+{
+ "component": true,
+ "usingComponents": {}
+}
diff --git a/pets-fe/components/stat-ring/index.wxml b/pets-fe/components/stat-ring/index.wxml
new file mode 100644
index 0000000..3864936
--- /dev/null
+++ b/pets-fe/components/stat-ring/index.wxml
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/pets-fe/components/stat-ring/index.wxss b/pets-fe/components/stat-ring/index.wxss
new file mode 100644
index 0000000..b3d6b91
--- /dev/null
+++ b/pets-fe/components/stat-ring/index.wxss
@@ -0,0 +1,6 @@
+.ring{position:relative;flex:none}
+.ring-img{width:100%;height:100%;display:block}
+.ring-center{
+ position:absolute;left:0;top:0;right:0;bottom:0;
+ display:flex;flex-direction:column;align-items:center;justify-content:center;
+}
diff --git a/pets-fe/preview-v2.html b/pets-fe/preview-v2.html
index f74c8f8..ccffaad 100644
--- a/pets-fe/preview-v2.html
+++ b/pets-fe/preview-v2.html
@@ -526,3 +526,46 @@ view,text{box-sizing:border-box}
+
11 · 首页门面(方案 C)
+状态环 + 状态 chip 做门面,今日任务提到首屏,4 色分类块替掉 8 宫格 emoji,最后一块深色 CTA。
+
+
+
+
%22%3E%3Ccircle%20cx%3D%2250%22%20cy%3D%2250%22%20r%3D%2242%22%20fill%3D%22none%22%20stroke%3D%22%23F5A947%22%20stroke-width%3D%228%22%20stroke-linecap%3D%22round%22%20stroke-dasharray%3D%22263.9%22%20stroke-dashoffset%3D%2273.9%22%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E)
+
+
+
+
小橘今天状态不错
+
还有 3 件事没做完
+
+ 体重稳定
+ 驱虫将到期
+
+
+
+
+
+
+
+
+
问问 AI 养宠助手
+
+