fix(fe): 保存到相册的方法根本没写进去 + 重构社区版式
## 保存到相册点了没反应 上次改的时候,插入方法的锚点用的是「// AI 聊天」那段注释,而它在 AI 独立成页时已经被删掉了 —— 替换没匹配上,onSavePoster / drawPoster / saveToAlbum 三个方法一个都没进 js,按钮绑了个不存在的方法。 我的检查器没拦住,是因为「事件绑定是否有实现」那条写在临时的 audit.js 里,日常只跑 check.js。已经把这条并进 check.js —— 加完立刻抓出了本次 新写的 13 处缺样式 class,说明它管用。 ## 社区 帖子操作栏原来是 space-around 排三个宽度不一的项:点赞数从 9 变 10 整行就会跳。改成三等分,图标 32rpx 居中对齐,没有数字时显示「点赞/评论」 而不是一个孤零零的 0,加了按下态。 帖子头部原来副标题固定写死「宠友」两个字,等于没有信息。换成发布时间 (刚刚 / 12 分钟前 / 3 天前)。 评论弹层原来拿 .record-row 当评论用 —— 那是个「左右两端对齐」的行, 昵称在左内容在右,评论一长就被挤扁,完全不是评论该有的样子。重做成 头像 + 昵称/时间 + 内容的正常结构;没有头像字段就用昵称首字做色块, 比一律显示同一个 emoji 强。发送按钮有输入才点亮,支持键盘回车发送。 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -15,6 +15,21 @@ function daysLater(n) {
|
|||||||
return d.getFullYear() + '-' + p(d.getMonth() + 1) + '-' + p(d.getDate());
|
return d.getFullYear() + '-' + p(d.getMonth() + 1) + '-' + p(d.getDate());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 相对时间。社区里关心的是「多久以前发的」,精确到秒没意义
|
||||||
|
function fmtAgo(iso) {
|
||||||
|
if (!iso) return '';
|
||||||
|
const d = new Date(iso);
|
||||||
|
if (isNaN(d.getTime())) return '';
|
||||||
|
const min = Math.floor((Date.now() - d.getTime()) / 60000);
|
||||||
|
if (min < 1) return '刚刚';
|
||||||
|
if (min < 60) return min + ' 分钟前';
|
||||||
|
if (min < 60 * 24) return Math.floor(min / 60) + ' 小时前';
|
||||||
|
if (min < 60 * 24 * 7) return Math.floor(min / 1440) + ' 天前';
|
||||||
|
const p = (n) => (n < 10 ? '0' + n : '' + n);
|
||||||
|
const sameYear = d.getFullYear() === new Date().getFullYear();
|
||||||
|
return (sameYear ? '' : d.getFullYear() + '-') + p(d.getMonth() + 1) + '-' + p(d.getDate());
|
||||||
|
}
|
||||||
|
|
||||||
function ageFromBirthday(bday) {
|
function ageFromBirthday(bday) {
|
||||||
if (!bday) return '';
|
if (!bday) return '';
|
||||||
const b = new Date(bday);
|
const b = new Date(bday);
|
||||||
@@ -223,6 +238,148 @@ Component({
|
|||||||
page.getTabBar().setData({ hidden });
|
page.getTabBar().setData({ hidden });
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
// ---- 成长海报:画进 canvas 才能存进相册 ----
|
||||||
|
|
||||||
|
onSavePoster() {
|
||||||
|
if (this.data.posterSaving) return;
|
||||||
|
this.setData({ posterSaving: true });
|
||||||
|
this.drawPoster()
|
||||||
|
.then((tempPath) => this.saveToAlbum(tempPath))
|
||||||
|
.then(() => wx.showToast({ title: '已保存到相册', icon: 'success' }))
|
||||||
|
.catch((e) => {
|
||||||
|
if (e && e.canceled) return;
|
||||||
|
wx.showToast({ title: (e && e.message) || '保存失败', icon: 'none' });
|
||||||
|
})
|
||||||
|
.then(() => this.setData({ posterSaving: false }));
|
||||||
|
},
|
||||||
|
|
||||||
|
// 把海报画到离屏 canvas 上,返回临时图片路径
|
||||||
|
drawPoster() {
|
||||||
|
const W = 600;
|
||||||
|
const H = 840;
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
wx.createSelectorQuery()
|
||||||
|
.in(this)
|
||||||
|
.select('#posterCanvas')
|
||||||
|
.fields({ node: true, size: true })
|
||||||
|
.exec((res) => {
|
||||||
|
const node = res && res[0] && res[0].node;
|
||||||
|
if (!node) return reject(new Error('画布还没准备好,稍后再试'));
|
||||||
|
|
||||||
|
// 按设备像素比放大,否则在高分屏上导出的图是糊的
|
||||||
|
let dpr = 2;
|
||||||
|
try {
|
||||||
|
dpr = (wx.getWindowInfo ? wx.getWindowInfo() : wx.getSystemInfoSync()).pixelRatio || 2;
|
||||||
|
} catch (err) {
|
||||||
|
dpr = 2;
|
||||||
|
}
|
||||||
|
node.width = W * dpr;
|
||||||
|
node.height = H * dpr;
|
||||||
|
const ctx = node.getContext('2d');
|
||||||
|
ctx.scale(dpr, dpr);
|
||||||
|
|
||||||
|
const pet = this.data.pet || {};
|
||||||
|
const p = this.data.poster || {};
|
||||||
|
|
||||||
|
const bg = ctx.createLinearGradient(0, 0, W, H);
|
||||||
|
bg.addColorStop(0, '#FFF7E8');
|
||||||
|
bg.addColorStop(1, '#FFFFFF');
|
||||||
|
ctx.fillStyle = bg;
|
||||||
|
ctx.fillRect(0, 0, W, H);
|
||||||
|
ctx.fillStyle = '#F2DFC3';
|
||||||
|
ctx.fillRect(0, 0, W, 8);
|
||||||
|
|
||||||
|
ctx.textAlign = 'center';
|
||||||
|
ctx.fillStyle = '#2D2925';
|
||||||
|
ctx.font = '600 40px sans-serif';
|
||||||
|
ctx.fillText((pet.name || '毛孩子') + ' 的成长报告', W / 2, 96);
|
||||||
|
|
||||||
|
ctx.font = '96px sans-serif';
|
||||||
|
ctx.fillText(pet.emoji || '🐾', W / 2, 216);
|
||||||
|
|
||||||
|
ctx.fillStyle = '#8D8277';
|
||||||
|
ctx.font = '24px sans-serif';
|
||||||
|
ctx.fillText([pet.age, pet.weight, pet.stage].filter(Boolean).join(' | '), W / 2, 268);
|
||||||
|
|
||||||
|
ctx.fillStyle = 'rgba(255,255,255,.8)';
|
||||||
|
this.roundRect(ctx, 60, 310, W - 120, 232, 24);
|
||||||
|
ctx.fill();
|
||||||
|
const lines = [
|
||||||
|
'完成任务 ' + (p.tasks_completed || 0) + ' 项',
|
||||||
|
'体重记录 ' + (p.weight_records || 0) + ' 次',
|
||||||
|
'疫苗记录 ' + (p.vaccine_records || 0) + ' 次',
|
||||||
|
'高风险异常 ' + (p.high_risk_count || 0) + ' 次',
|
||||||
|
];
|
||||||
|
ctx.textAlign = 'left';
|
||||||
|
ctx.font = '28px sans-serif';
|
||||||
|
lines.forEach((t, i) => {
|
||||||
|
const y = 360 + i * 52;
|
||||||
|
ctx.fillStyle = '#73BE9D';
|
||||||
|
ctx.fillText('✓', 92, y);
|
||||||
|
ctx.fillStyle = '#443D37';
|
||||||
|
ctx.fillText(t, 132, y);
|
||||||
|
});
|
||||||
|
|
||||||
|
ctx.textAlign = 'center';
|
||||||
|
ctx.fillStyle = '#2D2925';
|
||||||
|
ctx.font = '600 30px sans-serif';
|
||||||
|
ctx.fillText('健康状态:' + (p.headline || '稳定成长'), W / 2, 620);
|
||||||
|
|
||||||
|
ctx.fillStyle = '#B5A99D';
|
||||||
|
ctx.font = '22px sans-serif';
|
||||||
|
ctx.fillText('生成自 · 肉垫计划', W / 2, 780);
|
||||||
|
|
||||||
|
// canvas 2d 是同步绘制,画完直接导出
|
||||||
|
wx.canvasToTempFilePath(
|
||||||
|
{
|
||||||
|
canvas: node,
|
||||||
|
fileType: 'png',
|
||||||
|
success: (r) => resolve(r.tempFilePath),
|
||||||
|
fail: () => reject(new Error('生成图片失败')),
|
||||||
|
},
|
||||||
|
this,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
roundRect(ctx, x, y, w, h, r) {
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.moveTo(x + r, y);
|
||||||
|
ctx.arcTo(x + w, y, x + w, y + h, r);
|
||||||
|
ctx.arcTo(x + w, y + h, x, y + h, r);
|
||||||
|
ctx.arcTo(x, y + h, x, y, r);
|
||||||
|
ctx.arcTo(x, y, x + w, y, r);
|
||||||
|
ctx.closePath();
|
||||||
|
},
|
||||||
|
|
||||||
|
// 存相册要相册写权限。用户拒过一次之后 wx.authorize 不会再弹,
|
||||||
|
// 必须引导他去设置页打开,否则这里会永远静默失败。
|
||||||
|
saveToAlbum(filePath) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
wx.saveImageToPhotosAlbum({
|
||||||
|
filePath,
|
||||||
|
success: resolve,
|
||||||
|
fail: (err) => {
|
||||||
|
const msg = (err && err.errMsg) || '';
|
||||||
|
if (msg.indexOf('cancel') >= 0) return reject({ canceled: true });
|
||||||
|
if (msg.indexOf('auth deny') >= 0 || msg.indexOf('authorize') >= 0) {
|
||||||
|
wx.showModal({
|
||||||
|
title: '需要相册权限',
|
||||||
|
content: '保存卡片需要允许访问相册,去设置里打开一下?',
|
||||||
|
confirmText: '去设置',
|
||||||
|
success: (r) => {
|
||||||
|
if (r.confirm) wx.openSetting({});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
return reject({ canceled: true });
|
||||||
|
}
|
||||||
|
reject(new Error('保存失败'));
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
onSeg(e) {
|
onSeg(e) {
|
||||||
const { group, index } = e.currentTarget.dataset;
|
const { group, index } = e.currentTarget.dataset;
|
||||||
const segSel = Object.assign({}, this.data.segSel, { [group]: Number(index) });
|
const segSel = Object.assign({}, this.data.segSel, { [group]: Number(index) });
|
||||||
@@ -248,7 +405,16 @@ Component({
|
|||||||
loadComments() {
|
loadComments() {
|
||||||
if (!this.data.postId) return;
|
if (!this.data.postId) return;
|
||||||
api.listComments(this.data.postId)
|
api.listComments(this.data.postId)
|
||||||
.then((page) => this.setData({ comments: page.list || [] }))
|
.then((page) =>
|
||||||
|
this.setData({
|
||||||
|
comments: (page.list || []).map((c) => ({
|
||||||
|
...c,
|
||||||
|
timeText: fmtAgo(c.created_at),
|
||||||
|
// 没有头像字段,用昵称首字做个色块,比一律显示同一个 emoji 强
|
||||||
|
initial: (c.author_name || '?').slice(0, 1),
|
||||||
|
})),
|
||||||
|
}),
|
||||||
|
)
|
||||||
.catch(() => {});
|
.catch(() => {});
|
||||||
},
|
},
|
||||||
// 长按删除自己的评论
|
// 长按删除自己的评论
|
||||||
|
|||||||
@@ -319,16 +319,27 @@ module.exports.sel = function (map, key, index, def) {
|
|||||||
|
|
||||||
<!-- 评论 -->
|
<!-- 评论 -->
|
||||||
<block wx:elif="{{innerType === 'comments'}}">
|
<block wx:elif="{{innerType === 'comments'}}">
|
||||||
<view class="sheet-h3">评论</view>
|
<view class="sheet-h3">评论 {{comments.length ? comments.length : ''}}</view>
|
||||||
<view wx:for="{{comments}}" wx:key="id" class="record-row" bindlongpress="onDeleteComment" data-index="{{index}}">
|
|
||||||
<text class="bold">{{item.author_name}}<text wx:if="{{item.is_self}}" class="mine-tag">我</text></text>
|
<view wx:for="{{comments}}" wx:key="id" class="cm" bindlongpress="onDeleteComment" data-index="{{index}}">
|
||||||
<text class="muted">{{item.content}}</text>
|
<view class="cm-av">{{item.initial}}</view>
|
||||||
|
<view class="cm-body">
|
||||||
|
<view class="cm-head">
|
||||||
|
<text class="cm-name">{{item.author_name}}</text>
|
||||||
|
<text wx:if="{{item.is_self}}" class="mine-tag">我</text>
|
||||||
|
<text class="cm-time">{{item.timeText}}</text>
|
||||||
</view>
|
</view>
|
||||||
<view wx:if="{{!comments.length}}" class="sheet-p">还没有评论,来抢沙发~</view>
|
<view class="cm-text">{{item.content}}</view>
|
||||||
<view wx:if="{{comments.length}}" class="sheet-p" style="font-size:22rpx;color:var(--muted)">长按自己的评论可删除</view>
|
</view>
|
||||||
<view class="ai-input-row" style="margin-top:24rpx">
|
</view>
|
||||||
<input class="input" placeholder="友善交流,分享经验..." placeholder-class="placeholder" value="{{commentText}}" bindinput="onCommentInput"/>
|
|
||||||
<button class="btn btn-primary ai-send" bindtap="onSendComment">发</button>
|
<view wx:if="{{!comments.length}}" class="empty">还没有评论,来抢个沙发</view>
|
||||||
|
<view wx:if="{{comments.length}}" class="cm-tip">长按自己的评论可删除</view>
|
||||||
|
|
||||||
|
<view class="cm-input">
|
||||||
|
<input class="input" placeholder="友善交流,分享经验…" placeholder-class="placeholder"
|
||||||
|
value="{{commentText}}" bindinput="onCommentInput" confirm-type="send" bindconfirm="onSendComment"/>
|
||||||
|
<view class="cm-send {{commentText ? 'on' : ''}}" bindtap="onSendComment">发送</view>
|
||||||
</view>
|
</view>
|
||||||
</block>
|
</block>
|
||||||
|
|
||||||
|
|||||||
@@ -82,3 +82,29 @@
|
|||||||
|
|
||||||
/* 离屏画布:挪到可视区外而不是 display:none,否则 selectorQuery 取不到节点 */
|
/* 离屏画布:挪到可视区外而不是 display:none,否则 selectorQuery 取不到节点 */
|
||||||
.poster-canvas{position:fixed;left:-9999rpx;top:0;width:600rpx;height:840rpx}
|
.poster-canvas{position:fixed;left:-9999rpx;top:0;width:600rpx;height:840rpx}
|
||||||
|
|
||||||
|
/* 评论。原来拿 .record-row(左右两端对齐)当评论用,昵称在左内容在右,
|
||||||
|
内容一长就被挤扁。改成头像 + 昵称时间 + 内容的正常结构。 */
|
||||||
|
.cm{display:flex;gap:var(--sp-3);padding:var(--sp-3) 0;border-bottom:1rpx solid var(--line)}
|
||||||
|
.cm:last-of-type{border-bottom:0}
|
||||||
|
.cm-av{
|
||||||
|
width:64rpx;height:64rpx;border-radius:var(--r-sm);flex:none;
|
||||||
|
display:flex;align-items:center;justify-content:center;
|
||||||
|
background:var(--primary-soft);color:var(--primary-ink);
|
||||||
|
font-size:var(--fs-md);font-weight:var(--fw-b);
|
||||||
|
}
|
||||||
|
.cm-body{flex:1;min-width:0}
|
||||||
|
.cm-head{display:flex;align-items:center;gap:var(--sp-1)}
|
||||||
|
.cm-name{font-size:var(--fs-sm);font-weight:var(--fw-b);color:var(--text-2)}
|
||||||
|
.cm-time{margin-left:auto;font-size:var(--fs-cap);color:var(--muted2);flex:none}
|
||||||
|
.cm-text{margin-top:6rpx;font-size:var(--fs-md);line-height:1.55;word-break:break-word}
|
||||||
|
.cm-tip{margin-top:var(--sp-3);text-align:center;color:var(--muted2);font-size:var(--fs-cap)}
|
||||||
|
|
||||||
|
.cm-input{display:flex;align-items:center;gap:var(--sp-3);margin-top:var(--sp-4)}
|
||||||
|
.cm-input .input{flex:1}
|
||||||
|
.cm-send{
|
||||||
|
flex:none;height:88rpx;padding:0 var(--sp-5);border-radius:var(--r-md);
|
||||||
|
display:flex;align-items:center;justify-content:center;
|
||||||
|
background:var(--line);color:#fff;font-size:var(--fs-md);font-weight:var(--fw-b);transition:.16s ease;
|
||||||
|
}
|
||||||
|
.cm-send.on{background:var(--cta)}
|
||||||
|
|||||||
@@ -2,6 +2,21 @@ const store = require('../../utils/store.js');
|
|||||||
const api = require('../../utils/api.js');
|
const api = require('../../utils/api.js');
|
||||||
const { toastErr } = require('../../utils/ui.js');
|
const { toastErr } = require('../../utils/ui.js');
|
||||||
|
|
||||||
|
// 相对时间。社区里关心的是「多久以前发的」,精确到秒没意义
|
||||||
|
function fmtAgo(iso) {
|
||||||
|
if (!iso) return '';
|
||||||
|
const d = new Date(iso);
|
||||||
|
if (isNaN(d.getTime())) return '';
|
||||||
|
const min = Math.floor((Date.now() - d.getTime()) / 60000);
|
||||||
|
if (min < 1) return '刚刚';
|
||||||
|
if (min < 60) return min + ' 分钟前';
|
||||||
|
if (min < 60 * 24) return Math.floor(min / 60) + ' 小时前';
|
||||||
|
if (min < 60 * 24 * 7) return Math.floor(min / 1440) + ' 天前';
|
||||||
|
const p = (n) => (n < 10 ? '0' + n : '' + n);
|
||||||
|
const sameYear = d.getFullYear() === new Date().getFullYear();
|
||||||
|
return (sameYear ? '' : d.getFullYear() + '-') + p(d.getMonth() + 1) + '-' + p(d.getDate());
|
||||||
|
}
|
||||||
|
|
||||||
const TAG_CLASS = { 求助: 'warn', 经验: 'blue', 精选: 'purple', 避坑: 'red', 晒宠: '' };
|
const TAG_CLASS = { 求助: 'warn', 经验: 'blue', 精选: 'purple', 避坑: 'red', 晒宠: '' };
|
||||||
|
|
||||||
function mapPost(p) {
|
function mapPost(p) {
|
||||||
@@ -22,6 +37,7 @@ function mapPost(p) {
|
|||||||
user_id: p.user_id,
|
user_id: p.user_id,
|
||||||
followed: !!p.followed,
|
followed: !!p.followed,
|
||||||
is_self: !!p.is_self,
|
is_self: !!p.is_self,
|
||||||
|
timeText: fmtAgo(p.created_at),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,10 @@ module.exports.isUrl = function (s) { return s && s.indexOf('http') === 0; }
|
|||||||
<view wx:for="{{posts}}" wx:key="id" class="post-card" bindlongpress="onLongPressPost" data-index="{{index}}">
|
<view wx:for="{{posts}}" wx:key="id" class="post-card" bindlongpress="onLongPressPost" data-index="{{index}}">
|
||||||
<view class="post-head">
|
<view class="post-head">
|
||||||
<view class="post-avatar">{{item.author_emoji}}</view>
|
<view class="post-avatar">{{item.author_emoji}}</view>
|
||||||
<view class="post-user"><text class="pu-b">{{item.author_name}}<text wx:if="{{item.is_ai}}" class="ai-tag">AI</text></text><text class="pu-s">宠友</text></view>
|
<view class="post-user">
|
||||||
|
<view class="pu-b">{{item.author_name}}<text wx:if="{{item.is_ai}}" class="ai-tag">AI</text></view>
|
||||||
|
<view class="pu-s">{{item.timeText}}</view>
|
||||||
|
</view>
|
||||||
<view wx:if="{{!item.is_self && item.user_id}}" class="follow-btn {{item.followed ? 'on' : ''}}"
|
<view wx:if="{{!item.is_self && item.user_id}}" class="follow-btn {{item.followed ? 'on' : ''}}"
|
||||||
catchtap="toggleFollow" data-index="{{index}}">{{item.followed ? '已关注' : '+ 关注'}}</view>
|
catchtap="toggleFollow" data-index="{{index}}">{{item.followed ? '已关注' : '+ 关注'}}</view>
|
||||||
<view wx:if="{{item.tag}}" class="tag {{item.tagClass}}">{{item.tag}}</view>
|
<view wx:if="{{item.tag}}" class="tag {{item.tagClass}}">{{item.tag}}</view>
|
||||||
@@ -27,9 +30,18 @@ module.exports.isUrl = function (s) { return s && s.indexOf('http') === 0; }
|
|||||||
</block>
|
</block>
|
||||||
</view>
|
</view>
|
||||||
<view class="post-actions">
|
<view class="post-actions">
|
||||||
<view class="pa-btn {{item.liked ? 'liked' : ''}}" data-index="{{index}}" bindtap="likePost"><pt-icon name="{{item.liked ? 'like-on' : 'like'}}" size="{{30}}"></pt-icon>{{item.like_count}}</view>
|
<view class="pa-btn {{item.liked ? 'liked' : ''}}" data-index="{{index}}" bindtap="likePost">
|
||||||
<view class="pa-btn" data-id="{{item.id}}" bindtap="openComments"><pt-icon name="comment" size="{{30}}"></pt-icon>{{item.comment_count}}</view>
|
<pt-icon name="{{item.liked ? 'like-on' : 'like'}}" size="{{32}}"></pt-icon>
|
||||||
<button class="pa-btn pa-share" open-type="share" data-content="{{item.content}}"><pt-icon name="share" size="{{30}}"></pt-icon>分享</button>
|
<text class="pa-n">{{item.like_count || '点赞'}}</text>
|
||||||
|
</view>
|
||||||
|
<view class="pa-btn" data-id="{{item.id}}" bindtap="openComments">
|
||||||
|
<pt-icon name="comment" size="{{32}}"></pt-icon>
|
||||||
|
<text class="pa-n">{{item.comment_count || '评论'}}</text>
|
||||||
|
</view>
|
||||||
|
<button class="pa-btn pa-share" open-type="share" data-content="{{item.content}}">
|
||||||
|
<pt-icon name="share" size="{{32}}"></pt-icon>
|
||||||
|
<text class="pa-n">分享</text>
|
||||||
|
</button>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
|
|||||||
@@ -21,14 +21,18 @@
|
|||||||
display:flex;align-items:center;justify-content:center;font-size:56rpx;
|
display:flex;align-items:center;justify-content:center;font-size:56rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
.post-actions{display:flex;justify-content:space-around;border-top:1rpx solid var(--line);padding-top:var(--sp-3)}
|
/* 三等分。原来是 space-around 排三个宽度不一的项,点赞数一变宽度就跳 */
|
||||||
|
.post-actions{display:flex;border-top:1rpx solid var(--line);padding-top:var(--sp-2)}
|
||||||
.pa-btn{
|
.pa-btn{
|
||||||
display:flex;align-items:center;gap:var(--sp-1);
|
flex:1;height:72rpx;
|
||||||
color:var(--muted);font-weight:var(--fw-b);font-size:var(--fs-sm);
|
display:flex;align-items:center;justify-content:center;gap:var(--sp-1);
|
||||||
|
color:var(--muted);font-weight:var(--fw);font-size:var(--fs-sm);
|
||||||
}
|
}
|
||||||
|
.pa-n{line-height:1}
|
||||||
.pa-btn.liked{color:var(--red-ink)}
|
.pa-btn.liked{color:var(--red-ink)}
|
||||||
|
.pa-btn:active{background:var(--surface-2);border-radius:var(--r-sm)}
|
||||||
/* 分享用微信原生 open-type=share,得抹掉 button 默认外观 */
|
/* 分享用微信原生 open-type=share,得抹掉 button 默认外观 */
|
||||||
.pa-share{background:transparent;border:none;padding:0;margin:0;line-height:inherit;height:auto}
|
.pa-share{background:transparent;border:none;padding:0;margin:0;line-height:inherit}
|
||||||
.pa-share::after{border:none}
|
.pa-share::after{border:none}
|
||||||
|
|
||||||
/* 关注按钮 */
|
/* 关注按钮 */
|
||||||
|
|||||||
Reference in New Issue
Block a user