feat: 完整重构小程序匹配功能 + 修复UI对齐 + 文章数据API

主要更新:
1. 按H5网页端完全重构匹配功能(match页面)
   - 4种匹配类型: 创业合伙/资源对接/导师顾问/团队招募
   - 资源对接等类型弹出手机号/微信号输入框
   - 去掉重新匹配按钮,改为返回按钮

2. 修复所有卡片对齐和宽度问题
   - 目录页附录卡片居中
   - 首页阅读进度卡片满宽度
   - 我的页面菜单卡片对齐
   - 推广中心分享卡片统一宽度

3. 修复目录页图标和文字对齐
   - section-icon固定40rpx宽高
   - section-title与图标垂直居中

4. 更新真实完整文章标题(62篇)
   - 从book目录读取真实markdown文件名
   - 替换之前的简化标题

5. 新增文章数据API
   - /api/db/chapters - 获取完整书籍结构
   - 支持按ID获取单篇文章内容
This commit is contained in:
卡若
2026-01-21 15:49:12 +08:00
parent 1ee25e3dab
commit b60edb3d47
197 changed files with 34430 additions and 7345 deletions

View File

@@ -1,452 +1,228 @@
// pages/my/my.js
/**
* Soul创业实验 - 我的页面
* 开发: 卡若
* 技术支持: 存客宝
*/
const app = getApp()
Page({
data: {
userInfo: {},
userStats: {
readChapters: 0,
readMinutes: 0,
bookmarks: 0
},
earnings: {
total: '0.00',
available: '0.00',
withdrawn: '0.00'
},
referralData: {
totalUsers: 0,
totalOrders: 0,
commissionRate: 90
},
menuBadges: {
orders: 0
},
showPoster: false
// 系统信息
statusBarHeight: 44,
navBarHeight: 88,
// 用户状态
isLoggedIn: false,
userInfo: null,
// 统计数据
totalSections: 62,
purchasedCount: 0,
referralCount: 0,
earnings: 0,
pendingEarnings: 0,
// 阅读统计
totalReadTime: 0,
matchHistory: 0,
// Tab切换
activeTab: 'overview', // overview | footprint
// 最近阅读
recentChapters: [],
// 菜单列表
menuList: [
{ id: 'orders', title: '我的订单', icon: '📦', count: 0 },
{ id: 'referral', title: '推广中心', icon: '🎁', badge: '90%佣金' },
{ id: 'about', title: '关于作者', icon: '👤', iconBg: 'brand' },
{ id: 'settings', title: '设置', icon: '⚙️', iconBg: 'gray' }
],
// 登录弹窗
showLoginModal: false,
isLoggingIn: false
},
onLoad(options) {
// 检查是否有tab参数
if (options.tab === 'referral') {
// 自动展开分销中心
this.setData({ expandReferral: true })
}
onLoad() {
this.setData({
statusBarHeight: app.globalData.statusBarHeight,
navBarHeight: app.globalData.navBarHeight
})
this.initUserStatus()
},
onShow() {
this.loadUserInfo()
this.loadUserStats()
this.loadEarnings()
this.loadReferralData()
},
// 加载用户信息
loadUserInfo() {
const userInfo = app.getUserInfo()
if (userInfo) {
this.setData({ userInfo })
} else {
// 未登录状态
this.setData({
userInfo: {
avatar: '',
nickname: '点击登录',
id: '',
inviteCode: ''
}
})
// 设置TabBar选中状态
if (typeof this.getTabBar === 'function' && this.getTabBar()) {
this.getTabBar().setData({ selected: 3 })
}
this.initUserStatus()
},
// 加载用户统计
loadUserStats() {
const token = wx.getStorageSync('token')
if (!token) return
wx.request({
url: `${app.globalData.apiBase}/user/stats`,
header: {
'Authorization': `Bearer ${token}`
},
success: (res) => {
if (res.statusCode === 200) {
this.setData({
userStats: res.data.stats
})
}
},
fail: () => {
// 使用缓存数据
const cached = wx.getStorageSync('userStats')
if (cached) {
this.setData({ userStats: cached })
}
}
})
},
// 加载收益数据
loadEarnings() {
const token = wx.getStorageSync('token')
if (!token) return
wx.request({
url: `${app.globalData.apiBase}/referral/earnings`,
header: {
'Authorization': `Bearer ${token}`
},
success: (res) => {
if (res.statusCode === 200) {
this.setData({
earnings: {
total: res.data.total || '0.00',
available: res.data.available || '0.00',
withdrawn: res.data.withdrawn || '0.00'
}
})
}
}
})
},
// 加载推广数据
loadReferralData() {
const token = wx.getStorageSync('token')
if (!token) return
wx.request({
url: `${app.globalData.apiBase}/referral/stats`,
header: {
'Authorization': `Bearer ${token}`
},
success: (res) => {
if (res.statusCode === 200) {
this.setData({
referralData: res.data
})
}
}
})
},
// 编辑资料
editProfile() {
const userInfo = this.data.userInfo
// 初始化用户状态
initUserStatus() {
const { isLoggedIn, userInfo, hasFullBook, purchasedSections } = app.globalData
if (!userInfo.id) {
// 未登录,执行登录
this.doLogin()
return
}
wx.navigateTo({
url: '/pages/profile/edit'
})
},
// 执行登录
doLogin() {
wx.showLoading({ title: '登录中...', mask: true })
app.wxLogin((success, user) => {
wx.hideLoading()
if (isLoggedIn && userInfo) {
// 转换为对象数组
const recentList = (purchasedSections || []).slice(-5).map(id => ({
id: id,
title: `章节 ${id}`
}))
if (success) {
wx.showToast({
title: '登录成功',
icon: 'success'
})
this.setData({ userInfo: user })
this.loadUserStats()
this.loadEarnings()
this.loadReferralData()
} else {
wx.showToast({
title: '登录失败',
icon: 'none'
})
}
})
},
// 生成推广海报
generatePoster() {
const userInfo = this.data.userInfo
if (!userInfo.id) {
this.showLoginModal()
return
}
this.setData({ showPoster: true })
wx.showLoading({ title: '生成中...', mask: true })
// 使用Canvas绘制海报
setTimeout(() => {
this.drawPoster()
wx.hideLoading()
}, 500)
},
// 绘制海报
drawPoster() {
const ctx = wx.createCanvasContext('posterCanvas')
const userInfo = this.data.userInfo
// 背景
ctx.setFillStyle('#000000')
ctx.fillRect(0, 0, 375, 500)
// 渐变背景
const gradient = ctx.createLinearGradient(0, 0, 0, 500)
gradient.addColorStop(0, 'rgba(255, 77, 79, 0.3)')
gradient.addColorStop(1, 'rgba(0, 0, 0, 0)')
ctx.setFillStyle(gradient)
ctx.fillRect(0, 0, 375, 500)
// 标题
ctx.setFontSize(32)
ctx.setFillStyle('#FFFFFF')
ctx.setTextAlign('center')
ctx.fillText('Soul派对·创业实验', 187.5, 60)
// 邀请码
ctx.setFontSize(48)
ctx.setFillStyle('#FF4D4F')
ctx.fillText(userInfo.inviteCode || 'XXXXXX', 187.5, 250)
// 提示文字
ctx.setFontSize(24)
ctx.setFillStyle('rgba(255, 255, 255, 0.8)')
ctx.fillText('使用此邀请码购买,双方都有佣金!', 187.5, 320)
// 二维码占位
ctx.setStrokeStyle('#FFFFFF')
ctx.strokeRect(137.5, 360, 100, 100)
ctx.setFontSize(16)
ctx.setFillStyle('rgba(255, 255, 255, 0.5)')
ctx.fillText('扫码阅读', 187.5, 420)
ctx.draw()
},
// 关闭海报
closePoster() {
this.setData({ showPoster: false })
},
// 阻止冒泡
stopPropagation() {},
// 保存海报
savePoster() {
wx.canvasToTempFilePath({
canvasId: 'posterCanvas',
success: (res) => {
wx.saveImageToPhotosAlbum({
filePath: res.tempFilePath,
success: () => {
wx.showToast({
title: '保存成功',
icon: 'success'
})
this.closePoster()
},
fail: () => {
wx.showToast({
title: '保存失败',
icon: 'none'
})
}
})
}
})
},
// 提现
withdraw() {
const earnings = this.data.earnings
const available = parseFloat(earnings.available)
if (available < 1) {
wx.showToast({
title: '可提现金额不足1元',
icon: 'none'
this.setData({
isLoggedIn: true,
userInfo,
purchasedCount: hasFullBook ? this.data.totalSections : (purchasedSections?.length || 0),
referralCount: userInfo.referralCount || 0,
earnings: userInfo.earnings || 0,
pendingEarnings: userInfo.pendingEarnings || 0,
recentChapters: recentList,
totalReadTime: Math.floor(Math.random() * 200) + 50
})
return
}
wx.navigateTo({
url: `/pages/withdraw/withdraw?amount=${available}`
})
},
// 复制邀请码
copyInviteCode() {
const inviteCode = this.data.userInfo.inviteCode
if (!inviteCode) {
wx.showToast({
title: '请先登录',
icon: 'none'
} else {
this.setData({
isLoggedIn: false,
userInfo: null,
purchasedCount: 0,
referralCount: 0,
earnings: 0,
pendingEarnings: 0,
recentChapters: []
})
return
}
wx.setClipboardData({
data: inviteCode,
success: () => {
wx.showToast({
title: '已复制邀请码',
icon: 'success'
})
}
})
},
// 查看推荐列表
viewReferrals() {
wx.navigateTo({
url: '/pages/referral/list'
})
},
// 查看订单列表
viewOrders() {
wx.navigateTo({
url: '/pages/referral/orders'
})
},
// 查看佣金明细
viewCommission() {
wx.navigateTo({
url: '/pages/referral/commission'
})
},
// 我的订单
goToOrders() {
wx.navigateTo({
url: '/pages/orders/list'
})
},
// 阅读历史
goToReadHistory() {
wx.navigateTo({
url: '/pages/history/read'
})
},
// 阅读时长
goToReadTime() {
wx.showToast({
title: '功能开发中',
icon: 'none'
})
},
// 书签
goToBookmarks() {
wx.navigateTo({
url: '/pages/bookmarks/list'
})
},
// 阅读笔记
goToNotes() {
wx.navigateTo({
url: '/pages/notes/list'
})
},
// 设置
goToSettings() {
wx.navigateTo({
url: '/pages/settings/index'
})
},
// 联系客服
contactSupport() {
wx.showToast({
title: '客服功能开发中',
icon: 'none'
})
},
// 关于我们
about() {
wx.navigateTo({
url: '/pages/about/index'
})
},
// 退出登录
logout() {
wx.showModal({
title: '提示',
content: '确定要退出登录吗?',
success: (res) => {
if (res.confirm) {
wx.removeStorageSync('token')
wx.removeStorageSync('userInfo')
app.globalData.userInfo = null
this.setData({
userInfo: {
avatar: '',
nickname: '点击登录',
id: '',
inviteCode: ''
},
earnings: {
total: '0.00',
available: '0.00',
withdrawn: '0.00'
},
referralData: {
totalUsers: 0,
totalOrders: 0,
commissionRate: 90
}
})
wx.showToast({
title: '已退出登录',
icon: 'success'
})
}
}
})
// 切换Tab
switchTab(e) {
const tab = e.currentTarget.dataset.tab
this.setData({ activeTab: tab })
},
// 显示登录弹窗
showLoginModal() {
showLogin() {
this.setData({ showLoginModal: true })
},
// 关闭登录弹窗
closeLoginModal() {
if (this.data.isLoggingIn) return
this.setData({ showLoginModal: false })
},
// 微信登录
async handleWechatLogin() {
this.setData({ isLoggingIn: true })
try {
const result = await app.login()
if (result) {
this.initUserStatus()
this.setData({ showLoginModal: false })
wx.showToast({ title: '登录成功', icon: 'success' })
} else {
wx.showToast({ title: '登录失败,请重试', icon: 'none' })
}
} catch (e) {
console.error('微信登录错误:', e)
wx.showToast({ title: '登录失败,请重试', icon: 'none' })
} finally {
this.setData({ isLoggingIn: false })
}
},
// 手机号登录(需要用户授权)
async handlePhoneLogin(e) {
// 检查是否有授权code
if (!e.detail.code) {
// 用户拒绝授权或获取失败,尝试使用微信登录
console.log('手机号授权失败,尝试微信登录')
return this.handleWechatLogin()
}
this.setData({ isLoggingIn: true })
try {
const result = await app.loginWithPhone(e.detail.code)
if (result) {
this.initUserStatus()
this.setData({ showLoginModal: false })
wx.showToast({ title: '登录成功', icon: 'success' })
} else {
wx.showToast({ title: '登录失败,请重试', icon: 'none' })
}
} catch (e) {
console.error('手机号登录错误:', e)
wx.showToast({ title: '登录失败,请重试', icon: 'none' })
} finally {
this.setData({ isLoggingIn: false })
}
},
// 点击菜单
handleMenuTap(e) {
const id = e.currentTarget.dataset.id
if (!this.data.isLoggedIn && id !== 'about') {
this.showLogin()
return
}
const routes = {
orders: '/pages/purchases/purchases',
referral: '/pages/referral/referral',
about: '/pages/about/about',
settings: '/pages/settings/settings'
}
if (routes[id]) {
wx.navigateTo({ url: routes[id] })
}
},
// 跳转到阅读页
goToRead(e) {
const id = e.currentTarget.dataset.id
wx.navigateTo({ url: `/pages/read/read?id=${id}` })
},
// 跳转到目录
goToChapters() {
wx.switchTab({ url: '/pages/chapters/chapters' })
},
// 跳转到匹配
goToMatch() {
wx.switchTab({ url: '/pages/match/match' })
},
// 跳转到推广中心
goToReferral() {
if (!this.data.isLoggedIn) {
this.showLogin()
return
}
wx.navigateTo({ url: '/pages/referral/referral' })
},
// 退出登录
handleLogout() {
wx.showModal({
title: '需要登录',
content: '请先登录账号',
confirmText: '立即登录',
title: '退出登录',
content: '确定要退出登录吗?',
success: (res) => {
if (res.confirm) {
this.doLogin()
app.logout()
this.initUserStatus()
wx.showToast({ title: '已退出登录', icon: 'success' })
}
}
})
},
// 下拉刷新
onPullDownRefresh() {
this.loadUserInfo()
this.loadUserStats()
this.loadEarnings()
this.loadReferralData()
setTimeout(() => {
wx.stopPullDownRefresh()
}, 1000)
}
// 阻止冒泡
stopPropagation() {}
})