feat(此刻): 陪伴版文案 + 7 个头像 + 同周悄悄话(预设句/自由输入、抱抱) (v26100157)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
43
index.html
43
index.html
@@ -7,7 +7,7 @@
|
||||
<meta name="mobile-web-app-capable" content="yes">
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<title>兜爸心选 · 孕育陪伴</title>
|
||||
<!-- V:26100156 缓存版本标记:改 css/js 时同步 bump 该值(与 js/app.js 的 VER 同源),静态资源按 mtime 走 ETag 自动刷新 -->
|
||||
<!-- V:26100157 缓存版本标记:改 css/js 时同步 bump 该值(与 js/app.js 的 VER 同源),静态资源按 mtime 走 ETag 自动刷新 -->
|
||||
<link rel="stylesheet" href="mama-box.css">
|
||||
<script src="https://res.wx.qq.com/open/js/jweixin-1.6.0.js"></script>
|
||||
<!-- 共享助手:授权/跳商城/位置上报(分享卡片同步,见 docs/h5-auth-standard.md 第四节) -->
|
||||
@@ -292,13 +292,29 @@
|
||||
同日三改(用户:「此刻有一点点不够清爽,文字太多了,密密麻麻的」):从 5 行减到 3 行 ——
|
||||
① 标题行不变;② 「她们在做」两条进度条合成**一句**,只挑你今天还没做的那项(都做了就一句夸奖),去掉进度条;
|
||||
③ 「今天别忘了」整行删(产检、盲盒在上面工具宫格和盲盒横幅里都有);④ 滚动动态去掉白底卡片,压成一行小字。 -->
|
||||
<div class="pulse hide" id="pulse" role="region" aria-label="此刻,孕妈们在做什么">
|
||||
<!-- 2026-10-02 陪伴版(用户:「改成陪伴的语气……头像展示 6 到 8 个……升级成同周妈妈的悄悄话……
|
||||
不做复杂社区,只做一点陪伴」):
|
||||
① 头像从标题行挪到第二行,一排 7 个,后面跟「今天 N 位同周妈妈陪宝宝数了胎动」——说人数不说百分比,不和你比;
|
||||
② 「你今天还没数 ›」改成邀请:「小米粒在等你,陪它数一数 ›」,做过了就是「你今天也陪它数过啦 ✓」;
|
||||
③ 同周悄悄话 #whWall:横滑的小纸条,只能「抱抱」不能评论,没有昵称头像。数据 GET /whisper(app.js whisperWall())。
|
||||
拉到悄悄话时滚动动态 #plFeed 让位(一块地方只讲一件事),拉不到就还是滚动动态。 -->
|
||||
<div class="pulse hide" id="pulse" role="region" aria-label="此刻,同周妈妈们">
|
||||
<div class="pl-head">
|
||||
<span class="pl-live"><i></i>此刻</span>
|
||||
<span class="pp-avs" id="ppAvs" aria-hidden="true"></span>
|
||||
<span class="pl-title" id="plTitle"></span>
|
||||
</div>
|
||||
<div class="pp-crowd">
|
||||
<span class="pp-avs" id="ppAvs" aria-hidden="true"></span>
|
||||
<span class="pp-crowd-t" id="ppCrowd"></span>
|
||||
</div>
|
||||
<div class="pp-doing hide" id="ppDoing"></div>
|
||||
<div class="wh-wall hide" id="whWall">
|
||||
<div class="wh-head">
|
||||
<span class="wh-t">同周悄悄话<em>匿名 · 只有同孕期妈妈能看到</em></span>
|
||||
<button class="wh-say" type="button" id="whSay">说一句</button>
|
||||
</div>
|
||||
<div class="wh-strip" id="whStrip"></div>
|
||||
</div>
|
||||
<div class="pl-feed hide" id="plFeed"><div class="pl-track" id="plTrack"></div></div>
|
||||
</div>
|
||||
</section>
|
||||
@@ -1727,6 +1743,27 @@
|
||||
<div class="modal-foot"><button class="dl-btn main" id="bxAddrSave">提交</button></div>
|
||||
</section>
|
||||
|
||||
<!-- 此刻 · 说一句悄悄话(2026-10-02)。预设句点一下就填进输入框;自由输入由服务端过微信内容安全审核 -->
|
||||
<section class="modal wh-modal" id="modalWhisper" data-autofocus="off" role="dialog" aria-modal="true" aria-labelledby="whMTitle">
|
||||
<div class="modal-head">
|
||||
<h3 id="whMTitle">说一句悄悄话</h3>
|
||||
<button class="modal-x" data-modal="close" aria-label="关闭">
|
||||
<svg viewBox="0 0 24 24" width="15" height="15" aria-hidden="true"><path d="M6 6l12 12M18 6L6 18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round"/></svg>
|
||||
</button>
|
||||
</div>
|
||||
<p class="wh-m-lead" id="whMLead">不显示昵称和头像,只有同孕期的妈妈能看到。她们会给你一个抱抱。</p>
|
||||
<div class="wh-ta-box">
|
||||
<textarea class="wh-ta" id="whTa" maxlength="40" rows="2" placeholder="今天想对谁说点什么?"></textarea>
|
||||
<span class="wh-cnt" id="whCnt">0/40</span>
|
||||
</div>
|
||||
<div class="wh-m-sub">不知道说什么?点一句</div>
|
||||
<div class="wh-presets" id="whPresets"></div>
|
||||
<div class="modal-foot">
|
||||
<button class="dl-btn main" id="whSend" type="button">悄悄发出</button>
|
||||
<p class="wh-left" id="whLeft"></p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- 盲盒 · 分段集齐达成的庆祝弹层(内容由 app.js showPrize() 填) -->
|
||||
<section class="modal bx-prize" id="modalBxPrize" role="dialog" aria-modal="true" aria-labelledby="bxPrizeT">
|
||||
<div class="bx-prize-ico" aria-hidden="true">🏆</div>
|
||||
|
||||
173
js/app.js
173
js/app.js
@@ -3,7 +3,7 @@
|
||||
(function () {
|
||||
'use strict';
|
||||
/* 页面版本号(YYMMDD+序号):显示在「关于兜爸心选」页底部;bump 时同步 head 注释与 ?v= */
|
||||
var VER = '26100156';
|
||||
var VER = '26100157';
|
||||
const $ = (s, c) => (c || document).querySelector(s);
|
||||
const $$ = (s, c) => Array.from((c || document).querySelectorAll(s));
|
||||
|
||||
@@ -3296,6 +3296,146 @@
|
||||
if (k < 1) requestAnimationFrame(step);
|
||||
})(t0);
|
||||
}
|
||||
/* ================= 此刻 · 同周悄悄话(2026-10-02) =================
|
||||
用户原话:「升级成同周妈妈的悄悄话,就是匿名一句心愿墙……不做复杂社区,就是只做一点陪伴」;发言 = 预设句 + 自由输入。
|
||||
GET /api/mp/public/mama-box/whisper?openid=&week= → { show, week, canPost, left, maxLen, presets[], list[] }
|
||||
POST /api/mp/public/mama-box/whisper?openid= {text} → 新的一条(自由输入由服务端过微信内容安全审核,不通就 code≠200)
|
||||
POST /api/mp/public/mama-box/whisper/hug?openid=&id=
|
||||
· 只能「抱抱」,没有评论、昵称、头像 —— 刻意不做成社区。自己说的那句排第一,显示「收到 N 个抱抱」。
|
||||
· 拉不到(show=false / 失败 / 访客没孕周)→ 整块隐藏,此刻卡退回滚动动态。不在前端造任何内容。
|
||||
· 由 pulseCard 的 load() 带着孕周触发(孕周回来 / 变了才重拉),另每 5 分钟静默刷新一次。 */
|
||||
let whLoad = null;
|
||||
(function whisperWall() {
|
||||
const wall = $('#whWall');
|
||||
if (!wall) return;
|
||||
const API = '/api/mp/public/mama-box/whisper';
|
||||
const esc = s => String(s == null ? '' : s).replace(/[&<>"]/g, c => ({ '&': '&', '<': '<', '>': '>', '"': '"' })[c]);
|
||||
const HEART = '<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M12 20.5s-7.5-4.6-7.5-10.2A4.3 4.3 0 0112 7.6a4.3 4.3 0 017.5 2.7c0 5.6-7.5 10.2-7.5 10.2z"/></svg>';
|
||||
let data = null, wk = null, sig = '', busy = false;
|
||||
const oid = () => hashParam('openid');
|
||||
|
||||
function card(it, i) {
|
||||
const tint = 't' + (i % 4);
|
||||
const meta = '孕 ' + it.week + ' 周 · ' + esc(it.ago);
|
||||
const foot = it.mine
|
||||
? '<span class="wh-got">' + HEART + (it.hugs ? '收到 <b>' + it.hugs + '</b> 个抱抱' : '抱抱正在路上') + '</span>'
|
||||
: '<button class="wh-hug' + (it.hugged ? ' on' : '') + '" type="button" data-hug="' + esc(it.id) + '" aria-label="给她一个抱抱">' +
|
||||
HEART + '<span>抱抱</span><b>' + (it.hugs || '') + '</b></button>';
|
||||
return '<div class="wh-card ' + tint + (it.mine ? ' mine' : '') + '">' +
|
||||
(it.mine ? '<span class="wh-mine">我说的</span>' : '') +
|
||||
'<p class="wh-txt">' + esc(it.text) + '</p>' +
|
||||
'<div class="wh-meta"><span>' + meta + '</span>' + foot + '</div></div>';
|
||||
}
|
||||
function render(keepScroll) {
|
||||
const st = $('#whStrip');
|
||||
const x = st.scrollLeft;
|
||||
const list = (data && data.list) || [];
|
||||
st.innerHTML = list.map(card).join('');
|
||||
if (keepScroll) st.scrollLeft = x; else st.scrollLeft = 0;
|
||||
}
|
||||
function show(on) {
|
||||
wall.classList.toggle('hide', !on);
|
||||
const sec = $('#pulse');
|
||||
if (sec) sec.classList.toggle('has-wh', on);
|
||||
}
|
||||
function load(w, silent) {
|
||||
wk = w;
|
||||
if (!w) { data = null; show(false); return; }
|
||||
const o = oid();
|
||||
fetch(API + '?openid=' + encodeURIComponent(o || '') + '&week=' + w)
|
||||
.then(r => (r.ok ? r.json() : null))
|
||||
.then(j => {
|
||||
const r = j && j.code === 200 && j.result;
|
||||
if (!r || !r.show || !(r.list || []).length) { data = null; show(false); return; }
|
||||
data = r;
|
||||
const ns = r.list.map(x => x.id + ':' + x.hugs + (x.hugged ? 'h' : '')).join('|');
|
||||
if (ns !== sig) { sig = ns; render(silent); }
|
||||
show(true);
|
||||
})
|
||||
.catch(() => { if (!silent) show(false); });
|
||||
}
|
||||
whLoad = w => load(w, false);
|
||||
setInterval(() => { if (wk && !document.hidden && !busy) load(wk, true); }, 300000);
|
||||
|
||||
/* 抱抱:先变(心跳一下、数字 +1),失败再退回 */
|
||||
$('#whStrip').addEventListener('click', e => {
|
||||
const b = e.target.closest('[data-hug]');
|
||||
if (!b) return;
|
||||
const o = oid();
|
||||
if (!o) { toast('登录后就能给她抱抱啦'); return; }
|
||||
if (b.classList.contains('on')) { toast('你已经抱过她啦'); return; }
|
||||
const it = ((data && data.list) || []).find(x => x.id === b.dataset.hug);
|
||||
haptic();
|
||||
b.classList.add('on', 'pop');
|
||||
setTimeout(() => b.classList.remove('pop'), 600);
|
||||
const nb = $('b', b);
|
||||
const n0 = it ? it.hugs : 0;
|
||||
if (it) { it.hugs = n0 + 1; it.hugged = true; }
|
||||
nb.textContent = n0 + 1;
|
||||
fetch(API + '/hug?openid=' + encodeURIComponent(o) + '&id=' + encodeURIComponent(b.dataset.hug), { method: 'POST' })
|
||||
.then(r => r.json())
|
||||
.then(j => { if (!j || j.code !== 200) throw j; })
|
||||
.catch(j => {
|
||||
b.classList.remove('on');
|
||||
if (it) { it.hugs = n0; it.hugged = false; }
|
||||
nb.textContent = n0 || '';
|
||||
toast((j && j.message) || '网络不太好,再抱一次试试');
|
||||
});
|
||||
});
|
||||
|
||||
/* 说一句 */
|
||||
const ta = $('#whTa');
|
||||
const cnt = () => { $('#whCnt').textContent = ta.value.length + '/' + ((data && data.maxLen) || 40); };
|
||||
ta.addEventListener('input', () => {
|
||||
cnt();
|
||||
$$('.wh-pre', $('#whPresets')).forEach(c => c.classList.toggle('on', c.textContent === ta.value));
|
||||
});
|
||||
$('#whSay').addEventListener('click', () => {
|
||||
if (!data) return;
|
||||
if (!oid() || !data.canPost) { toast('填好预产期,就能和同周妈妈说悄悄话啦'); return; }
|
||||
if (!data.left) { toast('今天已经说了 3 句啦,明天再来'); return; }
|
||||
ta.value = '';
|
||||
ta.maxLength = data.maxLen || 40;
|
||||
cnt();
|
||||
$('#whPresets').innerHTML = (data.presets || []).map(t => '<button class="wh-pre" type="button">' + esc(t) + '</button>').join('');
|
||||
$('#whLeft').textContent = '今天还能说 ' + data.left + ' 句';
|
||||
openModal('modalWhisper');
|
||||
});
|
||||
$('#whPresets').addEventListener('click', e => {
|
||||
const c = e.target.closest('.wh-pre');
|
||||
if (!c) return;
|
||||
haptic();
|
||||
ta.value = c.textContent;
|
||||
ta.dispatchEvent(new Event('input'));
|
||||
});
|
||||
$('#whSend').addEventListener('click', () => {
|
||||
const t = ta.value.trim();
|
||||
if (t.length < 2) { toast('写一两个字,或者点一句吧'); return; }
|
||||
if (busy) return;
|
||||
busy = true;
|
||||
const btn = $('#whSend');
|
||||
btn.disabled = true;
|
||||
btn.textContent = '正在发出…';
|
||||
fetch(API + '?openid=' + encodeURIComponent(oid()), {
|
||||
method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ text: t })
|
||||
})
|
||||
.then(r => r.json())
|
||||
.then(j => {
|
||||
if (!j || j.code !== 200 || !j.result) { toast((j && j.message) || '没发出去,再试一次'); return; }
|
||||
const it = j.result;
|
||||
data.left = it.left;
|
||||
delete it.left;
|
||||
data.list = [it].concat(data.list || []);
|
||||
sig = '';
|
||||
render(false);
|
||||
closeModal();
|
||||
toast('发出去啦,同周妈妈会给你抱抱的');
|
||||
})
|
||||
.catch(() => toast('网络不太好,再试一次'))
|
||||
.then(() => { busy = false; btn.disabled = false; btn.textContent = '悄悄发出'; });
|
||||
});
|
||||
})();
|
||||
|
||||
(function pulseCard() {
|
||||
const sec = $('#pulse');
|
||||
if (!sec) return;
|
||||
@@ -3311,7 +3451,14 @@
|
||||
};
|
||||
/* 用户自己今天做没做(足迹 used[].appId 是上游 URL slug)。足迹没回来 / 读不到 → null,不显示「你」那半句 */
|
||||
const SELF_APP = { kick: 'taidong', weight: 'yunqi-tizhong' };
|
||||
const SELF_TXT = { kick: ['你今天还没数', '你也数过了'], weight: ['你今天还没记', '你也记过了'] };
|
||||
/* 2026-10-02 陪伴版:不说「你今天还没数」(像点名),改成宝宝在等你的邀请;做过了就一句肯定。
|
||||
同周人数那句也不再给百分比(「她们有 18%」是在和你比),只说多少位妈妈今天也在做。 */
|
||||
const nmB = () => state.babyName || '宝宝';
|
||||
const SELF_TXT = {
|
||||
kick: [() => nmB() + '在等你,陪它数一数', () => '你今天也陪' + nmB() + '数过啦'],
|
||||
weight: [() => '也记一下今天的自己', () => '你今天也记过啦']
|
||||
};
|
||||
const CROWD_TXT = { kick: '位妈妈陪宝宝数了胎动', weight: '位妈妈记下了体重' };
|
||||
function selfDone(k) {
|
||||
if (_fpMode !== 'rows' && _fpMode !== 'guide') return null;
|
||||
return ((_fpData && _fpData.used) || []).some(u => u.appId === SELF_APP[k]);
|
||||
@@ -3343,7 +3490,8 @@
|
||||
const avs = $('#ppAvs');
|
||||
if (avs.dataset.seed === String(seed)) return;
|
||||
avs.dataset.seed = seed;
|
||||
avs.innerHTML = [3, 11, 7].map(x => '<i>' + momAva(x + seed) + '</i>').join('');
|
||||
/* 2026-10-02 用户:「头像现在展示 3 个,给我展示 6 到 8 个」→ 7 个 */
|
||||
avs.innerHTML = [3, 11, 7, 19, 2, 14, 23].map(x => '<i>' + momAva(x + seed) + '</i>').join('');
|
||||
}
|
||||
function paintPeer(p) {
|
||||
paintAvs(p.week);
|
||||
@@ -3351,14 +3499,16 @@
|
||||
/* 只说一句:优先挑你今天还没做的那项;都做了(或读不到你的足迹)就取第一项 */
|
||||
const ds = (p.doing || []).filter(d => SELF_TXT[d.key]);
|
||||
const pick = ds.find(d => selfDone(d.key) === false) || ds[0];
|
||||
if (pick) {
|
||||
const me = selfDone(pick.key);
|
||||
const meH = me == null ? '' : me
|
||||
? '<span class="pp-me ok">' + SELF_TXT[pick.key][1] + ' ✓</span>'
|
||||
: '<button class="pp-me todo" type="button" data-go="' + pick.key + '">' + SELF_TXT[pick.key][0] + ' ›</button>';
|
||||
$('#ppDoing').innerHTML = '<div class="pp-do"><span class="pp-dt">她们有 <b>' + (+pick.pct || 0) + '%</b> ' + esc(pick.label) + '</span>' + meH + '</div>';
|
||||
const n = pick ? Math.round((+p.count || 0) * (+pick.pct || 0) / 100) : 0;
|
||||
$('#ppCrowd').innerHTML = pick && n >= 3 ? '今天 <b>' + fmtN(n) + '</b> ' + CROWD_TXT[pick.key] : '她们和你一样,在等宝宝来';
|
||||
const me = pick ? selfDone(pick.key) : null;
|
||||
if (me != null) {
|
||||
$('#ppDoing').innerHTML = me
|
||||
? '<span class="pp-me ok"><svg viewBox="0 0 16 16" aria-hidden="true"><path d="M3.5 8.4l3 3 6-6.4" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>' + esc(SELF_TXT[pick.key][1]()) + '</span>'
|
||||
: '<button class="pp-me todo" type="button" data-go="' + pick.key + '">' + esc(SELF_TXT[pick.key][0]()) +
|
||||
'<i aria-hidden="true"><svg viewBox="0 0 16 16"><path d="M6 3.5L10.5 8 6 12.5" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg></i></button>';
|
||||
}
|
||||
$('#ppDoing').classList.toggle('hide', !pick);
|
||||
$('#ppDoing').classList.toggle('hide', me == null);
|
||||
}
|
||||
function paint() {
|
||||
const r = last;
|
||||
@@ -3371,6 +3521,8 @@
|
||||
/* 全站版(访客 / real 模式):只留一行总人数 + 滚动动态 */
|
||||
paintAvs(0);
|
||||
$('#ppDoing').classList.add('hide');
|
||||
const td = (r.today || [])[0];
|
||||
$('#ppCrowd').innerHTML = td ? '今天 <b>' + fmtN(td.value) + '</b> ' + esc(td.label) : '她们和你一样,在等宝宝来';
|
||||
const t = r.total;
|
||||
/* 前缀「已有」省掉:一行放得下「10,037 位妈妈在这里迎接宝宝」,带上就会折出一个孤零零的「宝宝」 */
|
||||
$('#plTitle').innerHTML = t ? '<b data-n="' + t.value + '">0</b> ' + esc(t.suffix) : '孕妈们在做什么';
|
||||
@@ -3407,6 +3559,7 @@
|
||||
function load() {
|
||||
const w = myWeek();
|
||||
loadedWk = w;
|
||||
if (whLoad) whLoad(w);
|
||||
return fetch('/api/mp/public/mama-box/pulse' + (w ? '?week=' + w : ''))
|
||||
.then(r => (r.ok ? r.json() : null))
|
||||
.then(j => { if (j && j.code === 200 && j.result) { last = j.result; paint(); } })
|
||||
|
||||
73
mama-box.css
73
mama-box.css
@@ -3443,3 +3443,76 @@ a.skip:focus{left:16px;top:16px}
|
||||
.lc-arrow{flex-basis:26px;width:26px;height:26px}
|
||||
.lc-arrow svg{width:14px;height:14px}
|
||||
.lc-env-v{left:9px;top:-10px;width:48px;height:36px;filter:drop-shadow(0 6px 8px rgba(150,30,60,.28))}
|
||||
|
||||
/* ================= 此刻 · 陪伴版 + 同周悄悄话(2026-10-02) =================
|
||||
头像一排 7 个单独成行;「还没数」改成邀请式文字链;悄悄话是一条横滑的小纸条带,四种淡色轮换。 */
|
||||
.pulse .pl-title{white-space:normal}
|
||||
.pp-crowd{display:flex;align-items:center;gap:9px;margin-top:9px;min-width:0}
|
||||
.pp-crowd .pp-avs i{width:24px;height:24px;margin-left:-8px;border:2px solid #fff;box-shadow:0 1px 3px rgba(120,70,50,.12)}
|
||||
.pp-crowd .pp-avs i:first-child{margin-left:0}
|
||||
.pp-crowd-t{flex:1;min-width:0;font-size:12.5px;color:var(--muted);line-height:1.35}
|
||||
.pp-crowd-t b{font-size:14px;font-weight:800;color:var(--ink-2);font-variant-numeric:tabular-nums}
|
||||
.pp-doing{margin-top:8px}
|
||||
.pp-me{display:inline-flex;align-items:center;gap:5px;padding:0;background:none;border-radius:0;font-size:13px;font-weight:700}
|
||||
.pp-me.todo{color:#E5533A;background:none}
|
||||
.pp-me.todo i{display:grid;place-items:center;width:17px;height:17px;border-radius:50%;background:#FFE5DC}
|
||||
.pp-me.todo i svg{width:11px;height:11px}
|
||||
.pp-me.todo:active{opacity:.7;transform:none}
|
||||
.pp-me.ok{color:#4E8A43;background:none;font-weight:600}
|
||||
.pp-me.ok svg{width:15px;height:15px}
|
||||
|
||||
.pulse.has-wh .pl-feed{display:none}
|
||||
.wh-wall.hide{display:none}
|
||||
.wh-wall{margin-top:13px}
|
||||
.wh-head{display:flex;align-items:center;justify-content:space-between;gap:10px}
|
||||
.wh-t{font-size:14px;font-weight:800;color:var(--ink);display:flex;align-items:baseline;gap:7px;min-width:0}
|
||||
.wh-t em{font-style:normal;font-size:11px;font-weight:500;color:var(--muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
|
||||
.wh-say{flex:0 0 auto;display:inline-flex;align-items:center;gap:4px;font:inherit;font-size:12.5px;font-weight:700;color:#E5533A;
|
||||
background:none;border:0;padding:4px 0}
|
||||
.wh-say::before{content:"";width:14px;height:14px;background:currentColor;
|
||||
-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M3 12.5l.6-2.6 7-7a1.4 1.4 0 012 2l-7 7z' fill='none' stroke='black' stroke-width='1.6' stroke-linejoin='round'/%3E%3C/svg%3E") center/contain no-repeat;
|
||||
mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M3 12.5l.6-2.6 7-7a1.4 1.4 0 012 2l-7 7z' fill='none' stroke='black' stroke-width='1.6' stroke-linejoin='round'/%3E%3C/svg%3E") center/contain no-repeat}
|
||||
.wh-say:active{opacity:.6}
|
||||
.wh-strip{display:flex;gap:10px;margin:9px -2px 0;padding:4px 2px 6px;overflow-x:auto;scroll-snap-type:x mandatory;
|
||||
-webkit-overflow-scrolling:touch;scrollbar-width:none}
|
||||
.wh-strip::-webkit-scrollbar{display:none}
|
||||
.wh-card{position:relative;flex:0 0 172px;scroll-snap-align:start;display:flex;flex-direction:column;justify-content:space-between;
|
||||
min-height:104px;padding:12px 12px 10px;border-radius:16px 16px 16px 5px;background:#FFF4EE}
|
||||
.wh-card.t0{background:#FFF1EC}
|
||||
.wh-card.t1{background:#F3F0FF}
|
||||
.wh-card.t2{background:#FFF7E6}
|
||||
.wh-card.t3{background:#EEF8F2}
|
||||
.wh-card.mine{background:#fff;box-shadow:inset 0 0 0 1.5px #FFC9B8}
|
||||
.wh-mine{position:absolute;top:-6px;right:10px;font-size:10px;font-weight:700;color:#fff;background:#F4593C;padding:2px 7px;border-radius:6px}
|
||||
.wh-txt{font-size:14px;line-height:1.5;color:var(--ink);font-weight:600;display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden}
|
||||
.wh-txt::before{content:"“";color:#E8A08C;font-weight:800;margin-right:1px}
|
||||
.wh-txt::after{content:"”";color:#E8A08C;font-weight:800;margin-left:1px}
|
||||
.wh-meta{display:flex;align-items:center;justify-content:space-between;gap:6px;margin-top:9px;font-size:10.5px;color:var(--muted);white-space:nowrap}
|
||||
.wh-hug{display:inline-flex;align-items:center;gap:3px;font:inherit;font-size:11px;font-weight:700;color:#C7837A;
|
||||
background:rgba(255,255,255,.8);border:0;border-radius:999px;padding:3px 8px 3px 6px;transition:color .2s,background .2s}
|
||||
.wh-hug svg,.wh-got svg{width:13px;height:13px;fill:none;stroke:currentColor;stroke-width:2.2}
|
||||
.wh-hug b{font-weight:800;font-variant-numeric:tabular-nums}
|
||||
.wh-hug b:empty{display:none}
|
||||
.wh-hug.on{color:#fff;background:#F4593C}
|
||||
.wh-hug.on svg{fill:currentColor}
|
||||
.wh-hug.pop svg{animation:whPop .6s var(--ease)}
|
||||
@keyframes whPop{0%{transform:scale(1)}30%{transform:scale(1.5)}60%{transform:scale(.9)}100%{transform:scale(1)}}
|
||||
.wh-got{display:inline-flex;align-items:center;gap:3px;color:#E5533A;font-weight:600}
|
||||
.wh-got svg{fill:#F4593C;stroke:#F4593C}
|
||||
.wh-got b{font-weight:800}
|
||||
|
||||
.wh-m-lead{margin-top:8px;font-size:13px;color:var(--muted);line-height:1.55}
|
||||
.wh-ta-box{position:relative;margin-top:14px}
|
||||
.wh-ta{display:block;width:100%;box-sizing:border-box;resize:none;font:inherit;font-size:15px;line-height:1.55;color:var(--ink);
|
||||
padding:13px 15px 24px;border:1.5px solid #EADFD8;border-radius:16px;background:#fff}
|
||||
.wh-ta:focus{outline:none;border-color:var(--brand);box-shadow:0 0 0 3px rgba(244,89,60,.12)}
|
||||
.wh-cnt{position:absolute;right:12px;bottom:8px;font-size:11px;color:#C9B7AC;font-variant-numeric:tabular-nums}
|
||||
.wh-m-sub{margin-top:14px;font-size:12px;font-weight:700;color:var(--ink-2)}
|
||||
.wh-presets{display:flex;flex-wrap:wrap;gap:8px;margin-top:9px}
|
||||
.wh-pre{font:inherit;font-size:12.5px;color:var(--ink-2);background:#fff;border:1px solid #EFE4DD;border-radius:12px;padding:7px 11px;text-align:left}
|
||||
.wh-pre.on{color:#E5533A;border-color:#FFB7A3;background:#FFF3EE}
|
||||
.wh-pre:active{transform:scale(.97)}
|
||||
.wh-modal .modal-foot{margin-top:18px}
|
||||
.wh-left{margin-top:8px;text-align:center;font-size:11.5px;color:var(--muted)}
|
||||
@media (prefers-reduced-motion: reduce){.wh-hug.pop svg{animation:none}}
|
||||
.wh-modal .modal-foot{flex-direction:column;align-items:stretch;gap:0}
|
||||
|
||||
Reference in New Issue
Block a user