更新开发文档,强调接口路径必须按使用方区分,禁止通用路径混用。新增小程序分享功能,统一使用推荐码,确保用户体验一致性。
This commit is contained in:
54
miniprogram/RESTORE-ANALYSIS.md
Normal file
54
miniprogram/RESTORE-ANALYSIS.md
Normal file
@@ -0,0 +1,54 @@
|
||||
# miniprogram 功能还原分析报告
|
||||
|
||||
## 一、对比结论
|
||||
|
||||
| 项目 | miniprogram(甲方) | miniprogram2(你写的) |
|
||||
|------|-------------------|------------------------|
|
||||
| 页面分享 | 仅 read、referral 有 | 几乎所有页面都有 |
|
||||
| scene 解析 | 无 | 有 utils/scene.js |
|
||||
| 推荐码获取 | 分散(userInfo?.referralCode 等) | 统一 app.getMyReferralCode() |
|
||||
| 书籍 API | /api/book/all-chapters | /api/miniprogram/book/all-chapters |
|
||||
| 特有页面 | vip、member-detail | scan、profile-edit |
|
||||
|
||||
## 二、已完成的还原项
|
||||
|
||||
### 1. 基础能力(app.js + utils/scene.js)
|
||||
|
||||
- **新增** `utils/scene.js`:扫码 scene 参数编解码,支持 `mid`、`id`、`ref`
|
||||
- **app.js**:
|
||||
- 引入 `parseScene`,`handleReferralCode` 支持 `options.scene` 解析
|
||||
- 新增 `getMyReferralCode()`:统一获取邀请码
|
||||
- 新增 `getSectionMid(sectionId)`:根据 id 查 mid
|
||||
- `loadBookData` 改为 `/api/miniprogram/book/all-chapters`
|
||||
|
||||
### 2. 页面分享(onShareAppMessage)
|
||||
|
||||
已为以下页面补充分享,路径统一带 `ref` 参数:
|
||||
|
||||
- index、chapters、match、my
|
||||
- read、referral(原有,已统一用 getMyReferralCode)
|
||||
- search、settings、purchases、privacy
|
||||
- withdraw-records、addresses、addresses/edit
|
||||
- agreement、about、vip、member-detail
|
||||
|
||||
### 3. read.js 分享逻辑
|
||||
|
||||
- 使用 `app.getMyReferralCode()` 替代 `userInfo?.referralCode || wx.getStorageSync('referralCode')`
|
||||
- 保持 `onShareAppMessage`、`onShareTimeline` 行为不变
|
||||
|
||||
### 4. API 路径修正
|
||||
|
||||
- `app.loadBookData`:`/api/book/all-chapters` → `/api/miniprogram/book/all-chapters`
|
||||
- `index.loadBookData`、`loadFeaturedFromServer`、`loadLatestChapters`:同上
|
||||
- `chapters.loadDailyChapters`:同上
|
||||
|
||||
## 三、未改动项(保留甲方逻辑)
|
||||
|
||||
- **vip 相关接口**:`/api/vip/members`、`/api/vip/status`、`/api/vip/profile` 仍为原路径,未改为 `/api/miniprogram/*`(若 soul-api 无对应 miniprogram 接口,需后端补充)
|
||||
- **页面结构**:保留 vip、member-detail,未引入 scan、profile-edit
|
||||
|
||||
## 四、后续建议
|
||||
|
||||
1. **soul-api 路由**:确认 `/api/miniprogram/book/all-chapters` 已注册;若 vip 需在小程序使用,建议在 miniprogram 组下增加等价接口。
|
||||
2. **referral.js**:检查是否已使用 `app.getMyReferralCode()`,若仍用旧方式可统一替换。
|
||||
3. **read.js 的 mid 支持**:miniprogram2 的 read 支持 `mid` 参数(便于扫码直达),若需要可在 miniprogram 的 read 中补充 `sectionMid` 与 `getShareConfig` 的 mid 逻辑。
|
||||
@@ -3,6 +3,8 @@
|
||||
* 开发: 卡若
|
||||
*/
|
||||
|
||||
const { parseScene } = require('./utils/scene.js')
|
||||
|
||||
App({
|
||||
globalData: {
|
||||
// API基础地址 - 连接真实后端
|
||||
@@ -77,11 +79,17 @@ App({
|
||||
this.handleReferralCode(options)
|
||||
},
|
||||
|
||||
// 处理推荐码绑定
|
||||
// 处理推荐码绑定:官方以 options.scene 接收扫码参数(可同时带 mid/id + ref),与 utils/scene 解析闭环
|
||||
handleReferralCode(options) {
|
||||
const query = options?.query || {}
|
||||
const refCode = query.ref || query.referralCode
|
||||
|
||||
let refCode = query.ref || query.referralCode
|
||||
const sceneStr = (options && (typeof options.scene === 'string' ? options.scene : '')) || ''
|
||||
if (sceneStr) {
|
||||
const parsed = parseScene(sceneStr)
|
||||
if (parsed.mid) this.globalData.initialSectionMid = parsed.mid
|
||||
if (parsed.id) this.globalData.initialSectionId = parsed.id
|
||||
if (parsed.ref) refCode = parsed.ref
|
||||
}
|
||||
if (refCode) {
|
||||
console.log('[App] 检测到推荐码:', refCode)
|
||||
|
||||
@@ -156,6 +164,22 @@ App({
|
||||
}
|
||||
},
|
||||
|
||||
// 根据业务 id 从 bookData 查 mid(用于跳转)
|
||||
getSectionMid(sectionId) {
|
||||
const list = this.globalData.bookData || []
|
||||
const ch = list.find(c => c.id === sectionId)
|
||||
return ch?.mid || 0
|
||||
},
|
||||
|
||||
// 获取当前用户的邀请码(用于分享带 ref,未登录返回空字符串)
|
||||
getMyReferralCode() {
|
||||
const user = this.globalData.userInfo
|
||||
if (!user) return ''
|
||||
if (user.referralCode) return user.referralCode
|
||||
if (user.id) return 'SOUL' + String(user.id).toUpperCase().slice(-6)
|
||||
return ''
|
||||
},
|
||||
|
||||
// 获取系统信息
|
||||
getSystemInfo() {
|
||||
try {
|
||||
@@ -200,7 +224,7 @@ App({
|
||||
}
|
||||
|
||||
// 从服务器获取最新数据
|
||||
const res = await this.request('/api/book/all-chapters')
|
||||
const res = await this.request('/api/miniprogram/book/all-chapters')
|
||||
if (res && (res.data || res.chapters)) {
|
||||
const chapters = res.data || res.chapters || []
|
||||
this.globalData.bookData = chapters
|
||||
|
||||
@@ -77,5 +77,13 @@ Page({
|
||||
// 返回
|
||||
goBack() {
|
||||
wx.navigateBack()
|
||||
},
|
||||
|
||||
onShareAppMessage() {
|
||||
const ref = app.getMyReferralCode()
|
||||
return {
|
||||
title: 'Soul创业派对 - 关于',
|
||||
path: ref ? `/pages/about/about?ref=${ref}` : '/pages/about/about'
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -119,5 +119,13 @@ Page({
|
||||
// 返回
|
||||
goBack() {
|
||||
wx.navigateBack()
|
||||
},
|
||||
|
||||
onShareAppMessage() {
|
||||
const ref = app.getMyReferralCode()
|
||||
return {
|
||||
title: 'Soul创业派对 - 地址管理',
|
||||
path: ref ? `/pages/addresses/addresses?ref=${ref}` : '/pages/addresses/addresses'
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -197,5 +197,13 @@ Page({
|
||||
// 返回
|
||||
goBack() {
|
||||
wx.navigateBack()
|
||||
},
|
||||
|
||||
onShareAppMessage() {
|
||||
const ref = app.getMyReferralCode()
|
||||
return {
|
||||
title: 'Soul创业派对 - 编辑地址',
|
||||
path: ref ? `/pages/addresses/edit?ref=${ref}` : '/pages/addresses/edit'
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -17,5 +17,13 @@ Page({
|
||||
|
||||
goBack() {
|
||||
wx.navigateBack()
|
||||
},
|
||||
|
||||
onShareAppMessage() {
|
||||
const ref = app.getMyReferralCode()
|
||||
return {
|
||||
title: 'Soul创业派对 - 用户协议',
|
||||
path: ref ? `/pages/agreement/agreement?ref=${ref}` : '/pages/agreement/agreement'
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -217,7 +217,7 @@ Page({
|
||||
|
||||
async loadTotalFromServer() {
|
||||
try {
|
||||
const res = await app.request({ url: '/api/book/all-chapters', silent: true })
|
||||
const res = await app.request({ url: '/api/miniprogram/book/all-chapters', silent: true })
|
||||
if (res && res.total) {
|
||||
this.setData({ totalSections: res.total })
|
||||
}
|
||||
@@ -270,7 +270,7 @@ Page({
|
||||
|
||||
async loadDailyChapters() {
|
||||
try {
|
||||
const res = await app.request({ url: '/api/book/all-chapters', silent: true })
|
||||
const res = await app.request({ url: '/api/miniprogram/book/all-chapters', silent: true })
|
||||
const chapters = (res && res.data) || (res && res.chapters) || []
|
||||
const daily = chapters
|
||||
.filter(c => (c.sectionOrder || c.sort_order || 0) > 62)
|
||||
@@ -294,5 +294,13 @@ Page({
|
||||
// 跳转到搜索页
|
||||
goToSearch() {
|
||||
wx.navigateTo({ url: '/pages/search/search' })
|
||||
},
|
||||
|
||||
onShareAppMessage() {
|
||||
const ref = app.getMyReferralCode()
|
||||
return {
|
||||
title: 'Soul创业派对 - 目录',
|
||||
path: ref ? `/pages/chapters/chapters?ref=${ref}` : '/pages/chapters/chapters'
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -149,7 +149,7 @@ Page({
|
||||
// 从服务端获取精选推荐(加权算法:阅读量50% + 时效30% + 付款率20%)和最新更新
|
||||
async loadFeaturedFromServer() {
|
||||
try {
|
||||
const res = await app.request({ url: '/api/book/all-chapters', silent: true })
|
||||
const res = await app.request({ url: '/api/miniprogram/book/all-chapters', silent: true })
|
||||
const chapters = (res && res.data) ? res.data : (res && res.chapters) ? res.chapters : []
|
||||
let featured = (res && res.featuredSections) ? res.featuredSections : []
|
||||
// 服务端未返回精选时,从前端按更新时间取前3条有效章节作为回退
|
||||
@@ -199,7 +199,7 @@ Page({
|
||||
|
||||
async loadBookData() {
|
||||
try {
|
||||
const res = await app.request({ url: '/api/book/all-chapters', silent: true })
|
||||
const res = await app.request({ url: '/api/miniprogram/book/all-chapters', silent: true })
|
||||
if (res && (res.data || res.chapters)) {
|
||||
const chapters = res.data || res.chapters || []
|
||||
this.setData({
|
||||
@@ -254,7 +254,7 @@ Page({
|
||||
|
||||
async loadLatestChapters() {
|
||||
try {
|
||||
const res = await app.request({ url: '/api/book/all-chapters', silent: true })
|
||||
const res = await app.request({ url: '/api/miniprogram/book/all-chapters', silent: true })
|
||||
const chapters = (res && res.data) || (res && res.chapters) || []
|
||||
const latest = chapters
|
||||
.filter(c => (c.sectionOrder || c.sort_order || 0) > 62)
|
||||
@@ -288,5 +288,13 @@ Page({
|
||||
await this.initData()
|
||||
this.updateUserStatus()
|
||||
wx.stopPullDownRefresh()
|
||||
},
|
||||
|
||||
onShareAppMessage() {
|
||||
const ref = app.getMyReferralCode()
|
||||
return {
|
||||
title: 'Soul创业派对 - 真实商业故事',
|
||||
path: ref ? `/pages/index/index?ref=${ref}` : '/pages/index/index'
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -659,5 +659,13 @@ Page({
|
||||
},
|
||||
|
||||
// 阻止事件冒泡
|
||||
preventBubble() {}
|
||||
preventBubble() {},
|
||||
|
||||
onShareAppMessage() {
|
||||
const ref = app.getMyReferralCode()
|
||||
return {
|
||||
title: 'Soul创业派对 - 找伙伴',
|
||||
path: ref ? `/pages/match/match?ref=${ref}` : '/pages/match/match'
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -87,5 +87,14 @@ Page({
|
||||
|
||||
goToMatch() { wx.switchTab({ url: '/pages/match/match' }) },
|
||||
goToVip() { wx.navigateTo({ url: '/pages/vip/vip' }) },
|
||||
goBack() { wx.navigateBack() }
|
||||
goBack() { wx.navigateBack() },
|
||||
|
||||
onShareAppMessage() {
|
||||
const ref = app.getMyReferralCode()
|
||||
const id = this.data.member?.id
|
||||
return {
|
||||
title: 'Soul创业派对 - 创业者详情',
|
||||
path: id && ref ? `/pages/member-detail/member-detail?id=${id}&ref=${ref}` : id ? `/pages/member-detail/member-detail?id=${id}` : ref ? `/pages/member-detail/member-detail?ref=${ref}` : '/pages/member-detail/member-detail'
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -711,5 +711,13 @@ Page({
|
||||
},
|
||||
|
||||
// 阻止冒泡
|
||||
stopPropagation() {}
|
||||
stopPropagation() {},
|
||||
|
||||
onShareAppMessage() {
|
||||
const ref = app.getMyReferralCode()
|
||||
return {
|
||||
title: 'Soul创业派对 - 我的',
|
||||
path: ref ? `/pages/my/my?ref=${ref}` : '/pages/my/my'
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -17,5 +17,13 @@ Page({
|
||||
|
||||
goBack() {
|
||||
wx.navigateBack()
|
||||
},
|
||||
|
||||
onShareAppMessage() {
|
||||
const ref = app.getMyReferralCode()
|
||||
return {
|
||||
title: 'Soul创业派对 - 隐私政策',
|
||||
path: ref ? `/pages/privacy/privacy?ref=${ref}` : '/pages/privacy/privacy'
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -63,5 +63,13 @@ Page({
|
||||
wx.navigateTo({ url: `/pages/read/read?id=${id}` })
|
||||
},
|
||||
|
||||
goBack() { wx.navigateBack() }
|
||||
goBack() { wx.navigateBack() },
|
||||
|
||||
onShareAppMessage() {
|
||||
const ref = app.getMyReferralCode()
|
||||
return {
|
||||
title: 'Soul创业派对 - 购买记录',
|
||||
path: ref ? `/pages/purchases/purchases?ref=${ref}` : '/pages/purchases/purchases'
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -454,11 +454,10 @@ Page({
|
||||
})
|
||||
},
|
||||
|
||||
// 分享到微信 - 自动带分享人ID
|
||||
// 分享到微信 - 自动带分享人ID(统一使用 app.getMyReferralCode)
|
||||
onShareAppMessage() {
|
||||
const { section, sectionId } = this.data
|
||||
const userInfo = app.globalData.userInfo
|
||||
const referralCode = userInfo?.referralCode || wx.getStorageSync('referralCode') || ''
|
||||
const ref = app.getMyReferralCode()
|
||||
|
||||
// 分享标题优化
|
||||
const shareTitle = section?.title
|
||||
@@ -467,7 +466,7 @@ Page({
|
||||
|
||||
return {
|
||||
title: shareTitle,
|
||||
path: `/pages/read/read?id=${sectionId}${referralCode ? '&ref=' + referralCode : ''}`,
|
||||
path: `/pages/read/read?id=${sectionId}${ref ? '&ref=' + ref : ''}`,
|
||||
imageUrl: '/assets/share-cover.png' // 可配置分享封面图
|
||||
}
|
||||
},
|
||||
@@ -475,12 +474,11 @@ Page({
|
||||
// 分享到朋友圈
|
||||
onShareTimeline() {
|
||||
const { section, sectionId } = this.data
|
||||
const userInfo = app.globalData.userInfo
|
||||
const referralCode = userInfo?.referralCode || ''
|
||||
const ref = app.getMyReferralCode()
|
||||
|
||||
return {
|
||||
title: `${section?.title || 'Soul创业派对'} - 来自派对房的真实故事`,
|
||||
query: `id=${sectionId}${referralCode ? '&ref=' + referralCode : ''}`
|
||||
query: `id=${sectionId}${ref ? '&ref=' + ref : ''}`
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@@ -877,12 +877,13 @@ Page({
|
||||
})
|
||||
},
|
||||
|
||||
// 分享 - 带推荐码
|
||||
// 分享 - 带推荐码(优先用页面数据,空时用 app.getMyReferralCode)
|
||||
onShareAppMessage() {
|
||||
console.log('[Referral] 分享给好友,推荐码:', this.data.referralCode)
|
||||
const ref = this.data.referralCode || app.getMyReferralCode()
|
||||
console.log('[Referral] 分享给好友,推荐码:', ref)
|
||||
return {
|
||||
title: 'Soul创业派对 - 来自派对房的真实商业故事',
|
||||
path: `/pages/index/index?ref=${this.data.referralCode}`
|
||||
path: ref ? `/pages/index/index?ref=${ref}` : '/pages/index/index'
|
||||
// 不设置 imageUrl,使用小程序默认截图
|
||||
// 如需自定义图片,请将图片放在 /assets/ 目录并配置路径
|
||||
}
|
||||
@@ -890,10 +891,11 @@ Page({
|
||||
|
||||
// 分享到朋友圈
|
||||
onShareTimeline() {
|
||||
console.log('[Referral] 分享到朋友圈,推荐码:', this.data.referralCode)
|
||||
const ref = this.data.referralCode || app.getMyReferralCode()
|
||||
console.log('[Referral] 分享到朋友圈,推荐码:', ref)
|
||||
return {
|
||||
title: `Soul创业派对 - 62个真实商业案例`,
|
||||
query: `ref=${this.data.referralCode}`
|
||||
query: ref ? `ref=${ref}` : ''
|
||||
// 不设置 imageUrl,使用小程序默认截图
|
||||
}
|
||||
},
|
||||
|
||||
@@ -105,5 +105,13 @@ Page({
|
||||
// 返回上一页
|
||||
goBack() {
|
||||
wx.navigateBack()
|
||||
},
|
||||
|
||||
onShareAppMessage() {
|
||||
const ref = app.getMyReferralCode()
|
||||
return {
|
||||
title: 'Soul创业派对 - 搜索',
|
||||
path: ref ? `/pages/search/search?ref=${ref}` : '/pages/search/search'
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -493,5 +493,13 @@ Page({
|
||||
// 跳转到地址管理页
|
||||
goToAddresses() {
|
||||
wx.navigateTo({ url: '/pages/addresses/addresses' })
|
||||
},
|
||||
|
||||
onShareAppMessage() {
|
||||
const ref = app.getMyReferralCode()
|
||||
return {
|
||||
title: 'Soul创业派对 - 设置',
|
||||
path: ref ? `/pages/settings/settings?ref=${ref}` : '/pages/settings/settings'
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -128,5 +128,13 @@ Page({
|
||||
} catch (e) { wx.showToast({ title: '保存失败', icon: 'none' }) }
|
||||
},
|
||||
|
||||
goBack() { wx.navigateBack() }
|
||||
goBack() { wx.navigateBack() },
|
||||
|
||||
onShareAppMessage() {
|
||||
const ref = app.getMyReferralCode()
|
||||
return {
|
||||
title: 'Soul创业派对 - VIP会员',
|
||||
path: ref ? `/pages/vip/vip?ref=${ref}` : '/pages/vip/vip'
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -119,5 +119,13 @@ Page({
|
||||
wx.hideLoading()
|
||||
wx.showToast({ title: '网络异常,请重试', icon: 'none' })
|
||||
}
|
||||
},
|
||||
|
||||
onShareAppMessage() {
|
||||
const ref = app.getMyReferralCode()
|
||||
return {
|
||||
title: 'Soul创业派对 - 提现记录',
|
||||
path: ref ? `/pages/withdraw-records/withdraw-records?ref=${ref}` : '/pages/withdraw-records/withdraw-records'
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
45
miniprogram/utils/scene.js
Normal file
45
miniprogram/utils/scene.js
Normal file
@@ -0,0 +1,45 @@
|
||||
/**
|
||||
* Soul创业派对 - 小程序码 scene 参数统一编解码(海报生成 ↔ 扫码解析闭环)
|
||||
* 官方以 options.scene 接收扫码参数;后端生成码时会把 & 转为 _,故解析时同时支持 & 和 _
|
||||
* scene 同时可带两个参数:章节标识(mid/id) + 推荐人(ref)
|
||||
*/
|
||||
|
||||
const SEP = '_' // 生成时统一用 _,与微信实际存储一致,且不占 32 字符限制
|
||||
|
||||
/**
|
||||
* 编码:生成海报/分享时组 scene 字符串(同时带 mid或id + ref)
|
||||
* @param {{ mid?: number, id?: string, ref?: string }} opts
|
||||
* @returns {string} 如 "mid=1_ref=ogpTW5fmXR" 或 "id=1.1_ref=xxx"
|
||||
*/
|
||||
function buildScene(opts) {
|
||||
const parts = []
|
||||
if (opts.mid != null && opts.mid !== '') parts.push(`mid=${opts.mid}`)
|
||||
if (opts.id) parts.push(`id=${opts.id}`)
|
||||
if (opts.ref) parts.push(`ref=${opts.ref}`)
|
||||
return parts.join(SEP)
|
||||
}
|
||||
|
||||
/**
|
||||
* 解码:从 options.scene 解析出 mid、id、ref(支持 & 或 _ 分隔)
|
||||
* @param {string} sceneStr 原始 scene(可能未 decodeURIComponent)
|
||||
* @returns {{ mid: number, id: string, ref: string }}
|
||||
*/
|
||||
function parseScene(sceneStr) {
|
||||
const res = { mid: 0, id: '', ref: '' }
|
||||
if (!sceneStr || typeof sceneStr !== 'string') return res
|
||||
const decoded = decodeURIComponent(String(sceneStr)).trim()
|
||||
const parts = decoded.split(/[&_]/)
|
||||
for (const part of parts) {
|
||||
const eq = part.indexOf('=')
|
||||
if (eq > 0) {
|
||||
const k = part.slice(0, eq)
|
||||
const v = part.slice(eq + 1)
|
||||
if (k === 'mid') res.mid = parseInt(v, 10) || 0
|
||||
if (k === 'id' && v) res.id = v
|
||||
if (k === 'ref' && v) res.ref = v
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
module.exports = { buildScene, parseScene }
|
||||
Reference in New Issue
Block a user