Files
soul/miniprogram/pages/my/my.js
卡若 934f7c7988 精简「我的」页面菜单 + 数据库去重 + 内容上传接口
- 移除扫一扫/提现记录/设置独立菜单项,设置功能整合到页面内
- 新增绑定微信号、清缓存、退出登录的内联设置区
- 添加 content_upload.py:Skill 可直接调用上传内容到数据库
- 数据库已去重(196→69条)并添加唯一索引防止再次重复

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-21 14:04:55 +08:00

395 lines
10 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* Soul创业派对 - 我的页面
* 开发: 卡若
* 技术支持: 存客宝
*/
const app = getApp()
Page({
data: {
// 系统信息
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: '' },
{ id: 'about', title: '关于作者', icon: '👤', iconBg: 'brand' }
],
// 登录弹窗
showLoginModal: false,
isLoggingIn: false
},
onLoad() {
this.setData({
statusBarHeight: app.globalData.statusBarHeight,
navBarHeight: app.globalData.navBarHeight
})
this.initUserStatus()
},
onShow() {
// 设置TabBar选中状态
if (typeof this.getTabBar === 'function' && this.getTabBar()) {
this.getTabBar().setData({ selected: 3 })
}
this.initUserStatus()
},
// 初始化用户状态
initUserStatus() {
const { isLoggedIn, userInfo, hasFullBook, purchasedSections } = app.globalData
if (isLoggedIn && userInfo) {
// 转换为对象数组
const recentList = (purchasedSections || []).slice(-5).map(id => ({
id: id,
title: `章节 ${id}`
}))
// 截短用户ID显示
const userId = userInfo.id || ''
const userIdShort = userId.length > 20 ? userId.slice(0, 10) + '...' + userId.slice(-6) : userId
// 获取微信号(优先显示)
const userWechat = wx.getStorageSync('user_wechat') || userInfo.wechat || ''
this.setData({
isLoggedIn: true,
userInfo,
userIdShort,
userWechat,
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
})
} else {
this.setData({
isLoggedIn: false,
userInfo: null,
userIdShort: '',
purchasedCount: 0,
referralCount: 0,
earnings: 0,
pendingEarnings: 0,
recentChapters: []
})
}
},
// 微信原生获取头像button open-type="chooseAvatar" 回调)
async onChooseAvatar(e) {
const avatarUrl = e.detail.avatarUrl
if (!avatarUrl) return
wx.showLoading({ title: '更新中...', mask: true })
try {
const userInfo = this.data.userInfo
userInfo.avatar = avatarUrl
this.setData({ userInfo })
app.globalData.userInfo = userInfo
wx.setStorageSync('userInfo', userInfo)
// 同步到服务器
await app.request('/api/user/update', {
method: 'POST',
data: { userId: userInfo.id, avatar: avatarUrl }
})
wx.hideLoading()
wx.showToast({ title: '头像已获取', icon: 'success' })
} catch (e) {
wx.hideLoading()
console.log('同步头像失败', e)
wx.showToast({ title: '头像已更新', icon: 'success' })
}
},
// 微信原生获取昵称input type="nickname" 回调)
async onNicknameInput(e) {
const nickname = e.detail.value
if (!nickname || nickname === this.data.userInfo?.nickname) return
try {
const userInfo = this.data.userInfo
userInfo.nickname = nickname
this.setData({ userInfo })
app.globalData.userInfo = userInfo
wx.setStorageSync('userInfo', userInfo)
// 同步到服务器
await app.request('/api/user/update', {
method: 'POST',
data: { userId: userInfo.id, nickname }
})
wx.showToast({ title: '昵称已获取', icon: 'success' })
} catch (e) {
console.log('同步昵称失败', e)
}
},
// 点击昵称修改(备用)
editNickname() {
wx.showModal({
title: '修改昵称',
editable: true,
placeholderText: '请输入昵称',
success: async (res) => {
if (res.confirm && res.content) {
const newNickname = res.content.trim()
if (newNickname.length < 1 || newNickname.length > 20) {
wx.showToast({ title: '昵称1-20个字符', icon: 'none' })
return
}
// 更新本地
const userInfo = this.data.userInfo
userInfo.nickname = newNickname
this.setData({ userInfo })
app.globalData.userInfo = userInfo
wx.setStorageSync('userInfo', userInfo)
// 同步到服务器
try {
await app.request('/api/user/update', {
method: 'POST',
data: { userId: userInfo.id, nickname: newNickname }
})
} catch (e) {
console.log('同步昵称到服务器失败', e)
}
wx.showToast({ title: '昵称已更新', icon: 'success' })
}
}
})
},
// 复制用户ID
copyUserId() {
const userId = this.data.userInfo?.id || ''
if (!userId) {
wx.showToast({ title: '暂无ID', icon: 'none' })
return
}
wx.setClipboardData({
data: userId,
success: () => {
wx.showToast({ title: 'ID已复制', icon: 'success' })
}
})
},
// 切换Tab
switchTab(e) {
const tab = e.currentTarget.dataset.tab
this.setData({ activeTab: tab })
},
// 显示登录弹窗
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'
}
if (routes[id]) {
wx.navigateTo({ url: routes[id] })
}
},
// 绑定微信号
bindWechat() {
wx.showModal({
title: '绑定微信号',
editable: true,
placeholderText: '请输入微信号',
success: async (res) => {
if (res.confirm && res.content) {
const wechat = res.content.trim()
if (!wechat) return
try {
wx.setStorageSync('user_wechat', wechat)
const userInfo = this.data.userInfo
userInfo.wechat = wechat
this.setData({ userInfo, userWechat: wechat })
app.globalData.userInfo = userInfo
wx.setStorageSync('userInfo', userInfo)
await app.request('/api/user/update', {
method: 'POST',
data: { userId: userInfo.id, wechat }
})
wx.showToast({ title: '绑定成功', icon: 'success' })
} catch (e) {
console.log('绑定微信号失败', e)
wx.showToast({ title: '已保存到本地', icon: 'success' })
}
}
}
})
},
// 清除缓存
clearCache() {
wx.showModal({
title: '清除缓存',
content: '确定要清除本地缓存吗?不会影响账号数据',
success: (res) => {
if (res.confirm) {
const userInfo = wx.getStorageSync('userInfo')
const token = wx.getStorageSync('token')
wx.clearStorageSync()
if (userInfo) wx.setStorageSync('userInfo', userInfo)
if (token) wx.setStorageSync('token', token)
wx.showToast({ title: '缓存已清除', icon: 'success' })
}
}
})
},
// 跳转到阅读页
goToRead(e) {
const id = e.currentTarget.dataset.id
wx.navigateTo({ url: `/pages/read/read?id=${id}` })
},
// 跳转到目录
goToChapters() {
wx.switchTab({ url: '/pages/chapters/chapters' })
},
// 跳转到关于页
goToAbout() {
wx.navigateTo({ url: '/pages/about/about' })
},
// 跳转到匹配
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: '确定要退出登录吗?',
success: (res) => {
if (res.confirm) {
app.logout()
this.initUserStatus()
wx.showToast({ title: '已退出登录', icon: 'success' })
}
}
})
},
// 阻止冒泡
stopPropagation() {}
})