feat(share): 启用全站系统分享 + 完善分享文案配置
- 各 Page 补齐 onShareAppMessage/onShareTimeline,修复右上角转发/朋友圈按钮灰色 - ui-btn 透传 open-type,完成弹窗接入分享按钮 - config.share 集中维护文案,动态标题用 titleTemplate 占位符 - leaderboard 的 myEntry.rank 缺失时回退静态标题,避免出现"排第 undefined" - 完成弹窗分享按钮高度对齐 88rpx,与同排按钮等高 Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -6,7 +6,13 @@ Component({
|
||||
block: { type: Boolean, value: false },
|
||||
disabled: { type: Boolean, value: false },
|
||||
iconSrc: { type: String, value: '' },
|
||||
customStyle: { type: String, value: '' }
|
||||
customStyle: { type: String, value: '' },
|
||||
// 透传微信原生 button 的 open-type:
|
||||
// share — 触发 Page.onShareAppMessage(分享给朋友)
|
||||
// contact / feedback / shareToPhone … 等
|
||||
// 设置后会在底层 button 上挂 open-type="{{openType}}",配合 Page 的
|
||||
// onShareAppMessage 即可让自定义按钮真正调起原生分享面板。
|
||||
openType: { type: String, value: '' }
|
||||
},
|
||||
methods: {
|
||||
onTap() {
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
style="{{customStyle}}"
|
||||
bindtap="onTap"
|
||||
disabled="{{disabled}}"
|
||||
open-type="{{openType}}"
|
||||
hover-class="none"
|
||||
>
|
||||
<image
|
||||
|
||||
@@ -52,5 +52,55 @@ module.exports = {
|
||||
],
|
||||
|
||||
/** 姿势要领每条显示的秒数 */
|
||||
tipInterval: 10
|
||||
tipInterval: 10,
|
||||
|
||||
/**
|
||||
* 小程序分享配置。微信分享能力依赖每个 Page 实现 onShareAppMessage /
|
||||
* onShareTimeline,这里集中维护所有场景的分享文案,改这里即可。
|
||||
*
|
||||
* 各 Page 根据自身场景从 share 字典里取对应的文案:
|
||||
* - share.default 默认(打开小程序时的转发)
|
||||
* - share.timer 训练完成时(最常见的分享节点)
|
||||
* - share.records 训练记录页(晒成绩)
|
||||
* - share.leaderboard 排行榜页(榜单拉人)
|
||||
* - share.settings 设置页(基本不会分享)
|
||||
*
|
||||
* 每个场景的 title 是静态兜底文案;带动态数据的场景额外提供
|
||||
* titleTemplate,用 {占位符} 标记运行时替换的位置,页面 replace 后使用:
|
||||
* - timer.titleTemplate {elapsed} 实际撑的秒数
|
||||
* - timer.timelineTitleTemplate {elapsed} 朋友圈晒成绩
|
||||
* - records.titleTemplate {minutes} 累计训练分钟数
|
||||
* - leaderboard.titleTemplate {period}/{rank} 榜单周期与名次
|
||||
* 数据缺失时页面回退到静态 title,避免分享卡片出现裸占位符。
|
||||
*
|
||||
* timelineTitle 用于非 timer 页的 onShareTimeline(分享到朋友圈)。
|
||||
* shareImageUrl 为空时微信自动用页面截图,无需提前准备图片。
|
||||
*/
|
||||
share: {
|
||||
default: {
|
||||
title: '平板支撑训练 — 每天一分钟,撑出好体态',
|
||||
path: '/pages/index/index'
|
||||
},
|
||||
timer: {
|
||||
title: '我刚完成一次平板支撑训练,一起来打卡!',
|
||||
titleTemplate: '我刚撑了 {elapsed} 秒!一起来平板支撑打卡',
|
||||
timelineTitleTemplate: '今天平板支撑 {elapsed} 秒,你能超过我吗?',
|
||||
path: '/pages/index/index'
|
||||
},
|
||||
records: {
|
||||
title: '看看我的平板支撑训练记录',
|
||||
titleTemplate: '累计平板支撑 {minutes} 分钟,你也来试试',
|
||||
path: '/pages/records/records'
|
||||
},
|
||||
leaderboard: {
|
||||
title: '平板支撑训练排行榜,看看你能撑多久?',
|
||||
titleTemplate: '我在平板支撑{period}榜排第 {rank},你能超过我吗?',
|
||||
path: '/pages/leaderboard/leaderboard'
|
||||
},
|
||||
settings: {
|
||||
title: '平板支撑训练小程序',
|
||||
path: '/pages/settings/settings'
|
||||
},
|
||||
timelineTitle: '平板支撑训练 — 一起打卡'
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ const planMod = require('../../utils/plan')
|
||||
const util = require('../../utils/util')
|
||||
const themeMod = require('../../utils/theme')
|
||||
const iconsMod = require('../../utils/icons')
|
||||
const config = require('../../config')
|
||||
|
||||
const MAX_CUSTOM_DURATION = 3600 // 1 hour max
|
||||
|
||||
@@ -190,5 +191,29 @@ Page({
|
||||
}
|
||||
this.setData({ showPicker: false })
|
||||
wx.navigateTo({ url: `/pages/timer/timer?free=${dur}` })
|
||||
},
|
||||
|
||||
/**
|
||||
* 分享给朋友。微信在用户点击右上角"···"菜单里的"转发给朋友"、
|
||||
* 或者页面内任何 `<button open-type="share">` / `<button open-type="share">`
|
||||
* 时,都会调用这个钩子,返回值即分享卡片的内容。
|
||||
* 没声明这个方法时分享按钮就是灰色的,见上轮分析。
|
||||
*/
|
||||
onShareAppMessage() {
|
||||
const s = config.share.default
|
||||
return {
|
||||
title: s.title,
|
||||
path: s.path
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 分享到朋友圈。基础库 2.11.3+ 可用。同样不实现就让"分享到朋友圈"按钮
|
||||
* 灰掉。各页统一用 config.share.timelineTitle 作为朋友圈文案。
|
||||
*/
|
||||
onShareTimeline() {
|
||||
return {
|
||||
title: config.share.timelineTitle
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -120,5 +120,32 @@ Page({
|
||||
} else {
|
||||
this.setData({ loading: false, empty: true })
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 分享给朋友 — 排行榜页。把用户当前名次写进标题,有"攀比"属性,
|
||||
* 分享欲望会强一些。
|
||||
*/
|
||||
onShareAppMessage() {
|
||||
const me = this.data.myEntry
|
||||
const s = config.share.leaderboard
|
||||
// myEntry.rank 依赖云函数返回,缺失时回退静态 title,避免出现"排第 undefined"
|
||||
if (me && me.rank) {
|
||||
const periodLabel = { day: '日', month: '月', year: '年' }[this.data.activePeriod] || ''
|
||||
return {
|
||||
title: s.titleTemplate.replace('{period}', periodLabel).replace('{rank}', me.rank),
|
||||
path: s.path
|
||||
}
|
||||
}
|
||||
return { title: s.title, path: s.path }
|
||||
},
|
||||
|
||||
/**
|
||||
* 分享到朋友圈。
|
||||
*/
|
||||
onShareTimeline() {
|
||||
return {
|
||||
title: config.share.timelineTitle
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -2,6 +2,7 @@ const storage = require('../../utils/storage')
|
||||
const util = require('../../utils/util')
|
||||
const themeMod = require('../../utils/theme')
|
||||
const iconsMod = require('../../utils/icons')
|
||||
const config = require('../../config')
|
||||
|
||||
Page({
|
||||
data: {
|
||||
@@ -163,5 +164,28 @@ Page({
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* 分享给朋友 — 训练记录页。把累计训练时长带进标题,
|
||||
* 让分享卡片有点击欲(看到对方"已经练了 X 小时"会想点开)。
|
||||
*/
|
||||
onShareAppMessage() {
|
||||
const stats = storage.getTotalStats()
|
||||
const minutes = Math.round((stats.totalDuration || 0) / 60)
|
||||
const s = config.share.records
|
||||
return {
|
||||
title: s.titleTemplate.replace('{minutes}', minutes),
|
||||
path: s.path
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 分享到朋友圈。
|
||||
*/
|
||||
onShareTimeline() {
|
||||
return {
|
||||
title: config.share.timelineTitle
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -542,5 +542,26 @@ Page({
|
||||
wx.showToast({ title: '已恢复默认', icon: 'success', duration: 1200 })
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* 分享给朋友 — 设置页(很少有人会从这里分享,但微信要求每个 Page 都
|
||||
* 实现钩子,否则对应页面的右上角菜单的转发按钮就是灰色的)。
|
||||
*/
|
||||
onShareAppMessage() {
|
||||
const s = config.share.settings
|
||||
return {
|
||||
title: s.title,
|
||||
path: s.path
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 分享到朋友圈。
|
||||
*/
|
||||
onShareTimeline() {
|
||||
return {
|
||||
title: config.share.timelineTitle
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
+24
-1
@@ -470,5 +470,28 @@ Page({
|
||||
// No-op handler for catchtouchmove. Swallows move events that would
|
||||
// otherwise bubble to underlying timer page controls (causing missed
|
||||
// taps on the completion modal).
|
||||
onNoop() { /* swallow */ }
|
||||
onNoop() { /* swallow */ },
|
||||
|
||||
/**
|
||||
* 分享给朋友。训练完成弹窗里的分享按钮会走到这里,标题里拼上用户
|
||||
* 刚才撑了多久,转化率更高;右上角"···"菜单也共用同一份文案。
|
||||
*/
|
||||
onShareAppMessage() {
|
||||
const elapsed = this.data.completionElapsed || this.data.duration
|
||||
const s = config.share.timer
|
||||
return {
|
||||
title: s.titleTemplate.replace('{elapsed}', elapsed),
|
||||
path: s.path
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 分享到朋友圈,同样带上刚完成的时长晒成绩。
|
||||
*/
|
||||
onShareTimeline() {
|
||||
const elapsed = this.data.completionElapsed || this.data.duration
|
||||
return {
|
||||
title: config.share.timer.timelineTitleTemplate.replace('{elapsed}', elapsed)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -164,6 +164,16 @@
|
||||
<view class="completion-btn" bindtap="onViewRecords">
|
||||
<text>查看记录</text>
|
||||
</view>
|
||||
<!-- openType="share" 会触发 Page.onShareAppMessage(已实现),
|
||||
没有这个属性 + onShareAppMessage 时分享按钮就是灰色的。
|
||||
ui-btn 透传 openType 到内部原生 button。 -->
|
||||
<ui-btn
|
||||
variant="ghost"
|
||||
size="md"
|
||||
customStyle="flex:1; height:88rpx;"
|
||||
text="分享"
|
||||
openType="share"
|
||||
></ui-btn>
|
||||
</view>
|
||||
<view class="completion-btn completion-btn--text" bindtap="onCloseCompletion">
|
||||
<text>回到首页</text>
|
||||
|
||||
Reference in New Issue
Block a user