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:
@@ -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() {}
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user