修复API + 优化用户体验

## 新增API
1. /api/user/update - 用户信息更新
2. /api/withdraw - 提现功能

## 我的页面
1. 头像使用微信原生chooseAvatar
2. 昵称使用input type="nickname"一键获取
3. ID点击复制

## 设置页面
1. 新增收货地址一键获取
2. 自动提现默认开启

## 找伙伴
1. "创业合伙"改为"找伙伴"
2. 所有匹配类型都从数据库匹配
This commit is contained in:
卡若
2026-01-29 12:44:29 +08:00
parent 3f54e1af47
commit 051f064707
8 changed files with 247 additions and 272 deletions

View File

@@ -8,10 +8,10 @@ const app = getApp()
// 默认匹配类型配置
let MATCH_TYPES = [
{ id: 'partner', label: '创业合伙', matchLabel: '创业伙伴', icon: '⭐', matchFromDB: true, showJoinAfterMatch: false },
{ id: 'investor', label: '资源对接', matchLabel: '资源对接', icon: '👥', matchFromDB: false, showJoinAfterMatch: true },
{ id: 'mentor', label: '导师顾问', matchLabel: '立即咨询', icon: '❤️', matchFromDB: false, showJoinAfterMatch: true },
{ id: 'team', label: '团队招募', matchLabel: '团队招募', icon: '🎮', matchFromDB: false, showJoinAfterMatch: true }
{ id: 'partner', label: '找伙伴', matchLabel: '伙伴', icon: '⭐', matchFromDB: true, showJoinAfterMatch: false },
{ id: 'investor', label: '资源对接', matchLabel: '资源对接', icon: '👥', matchFromDB: true, showJoinAfterMatch: true },
{ id: 'mentor', label: '导师顾问', matchLabel: '立即咨询', icon: '❤️', matchFromDB: true, showJoinAfterMatch: true },
{ id: 'team', label: '团队招募', matchLabel: '团队招募', icon: '🎮', matchFromDB: true, showJoinAfterMatch: true }
]
let FREE_MATCH_LIMIT = 3 // 每日免费匹配次数
@@ -23,7 +23,7 @@ Page({
// 匹配类型
matchTypes: MATCH_TYPES,
selectedType: 'partner',
currentTypeLabel: '创业合伙',
currentTypeLabel: '找伙伴',
// 用户状态
isLoggedIn: false,

View File

@@ -102,46 +102,60 @@ Page({
}
},
// 点击头像 - 从相册选择
chooseAvatar() {
wx.chooseMedia({
count: 1,
mediaType: ['image'],
sourceType: ['album', 'camera'],
success: async (res) => {
const tempFilePath = res.tempFiles[0].tempFilePath
wx.showLoading({ title: '更新中...', mask: true })
try {
// 更新本地显示
const userInfo = this.data.userInfo
userInfo.avatar = tempFilePath
this.setData({ userInfo })
app.globalData.userInfo = userInfo
wx.setStorageSync('userInfo', userInfo)
// 同步到服务器
try {
await app.request('/api/user/update', {
method: 'POST',
data: { userId: userInfo.id, avatar: tempFilePath }
})
} catch (e) {
console.log('同步头像失败', e)
}
wx.hideLoading()
wx.showToast({ title: '头像已更新', icon: 'success' })
} catch (e) {
wx.hideLoading()
wx.showToast({ title: '更新失败', icon: 'none' })
}
}
})
// 微信原生获取头像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: '修改昵称',

View File

@@ -27,22 +27,28 @@
<!-- 用户卡片 - 已登录状态 -->
<view class="user-card card-gradient" wx:else>
<view class="user-header-row">
<!-- 头像 - 点击获取微信头像 -->
<view class="avatar-wrapper" bindtap="chooseAvatar">
<!-- 头像 - 使用微信原生选择头像 -->
<button class="avatar-wrapper-btn" open-type="chooseAvatar" bindchooseavatar="onChooseAvatar">
<view class="avatar">
<image class="avatar-img" wx:if="{{userInfo.avatar}}" src="{{userInfo.avatar}}" mode="aspectFill"/>
<text class="avatar-text" wx:else>{{userInfo.nickname[0] || '微'}}</text>
</view>
<view class="avatar-edit-hint">
<text class="edit-icon"></text>
<text class="edit-icon">获取</text>
</view>
</view>
</button>
<!-- 用户信息 -->
<view class="user-info-block">
<view class="user-name-row" bindtap="editNickname">
<text class="user-name">{{userInfo.nickname || '微信用户'}}</text>
<text class="edit-name-icon">✎</text>
<view class="user-name-row">
<input
class="nickname-input"
type="nickname"
placeholder="点击获取昵称"
value="{{userInfo.nickname}}"
bindblur="onNicknameInput"
/>
<text class="edit-name-icon">获取</text>
</view>
<view class="user-id-row" bindtap="copyUserId">
<text class="user-id">ID: {{userIdShort}}</text>

View File

@@ -77,6 +77,31 @@
height: 120rpx;
}
/* 头像按钮样式 */
.avatar-wrapper-btn {
position: relative;
flex-shrink: 0;
width: 120rpx;
height: 120rpx;
padding: 0;
margin: 0;
background: transparent;
border: none;
line-height: normal;
}
.avatar-wrapper-btn::after { border: none; }
/* 昵称输入框 */
.nickname-input {
flex: 1;
font-size: 32rpx;
font-weight: 600;
color: #fff;
background: transparent;
padding: 8rpx 0;
min-width: 0;
}
.avatar {
width: 120rpx;
height: 120rpx;

View File

@@ -15,9 +15,10 @@ Page({
phoneNumber: '',
wechatId: '',
alipayAccount: '',
address: '',
// 自动提现
autoWithdrawEnabled: false,
// 自动提现(默认开启)
autoWithdrawEnabled: true,
// 绑定弹窗
showBindModal: false,
@@ -46,7 +47,9 @@ Page({
const phoneNumber = wx.getStorageSync('user_phone') || userInfo.phone || ''
const wechatId = wx.getStorageSync('user_wechat') || userInfo.wechat || ''
const alipayAccount = wx.getStorageSync('user_alipay') || userInfo.alipay || ''
const autoWithdrawEnabled = wx.getStorageSync('auto_withdraw_enabled') || false
const address = wx.getStorageSync('user_address') || userInfo.address || ''
// 默认开启自动提现
const autoWithdrawEnabled = wx.getStorageSync('auto_withdraw_enabled') !== false
this.setData({
isLoggedIn: true,
@@ -54,11 +57,48 @@ Page({
phoneNumber,
wechatId,
alipayAccount,
address,
autoWithdrawEnabled
})
}
},
// 一键获取收货地址
async getAddress() {
try {
const res = await wx.chooseAddress()
if (res) {
const fullAddress = `${res.provinceName}${res.cityName}${res.countyName}${res.detailInfo}`
wx.setStorageSync('user_address', fullAddress)
this.setData({ address: fullAddress })
// 更新用户信息
if (app.globalData.userInfo) {
app.globalData.userInfo.address = fullAddress
wx.setStorageSync('userInfo', app.globalData.userInfo)
}
// 同步到服务器
this.syncProfileToServer()
wx.showToast({ title: '地址已获取', icon: 'success' })
}
} catch (e) {
console.log('[Settings] 获取地址失败:', e)
if (e.errMsg?.includes('auth deny')) {
wx.showModal({
title: '需要授权',
content: '请允许获取收货地址',
confirmText: '去设置',
success: (res) => {
if (res.confirm) wx.openSetting()
}
})
}
}
},
// 切换自动提现
async toggleAutoWithdraw(e) {
const enabled = e.detail.value

View File

@@ -67,6 +67,21 @@
<text class="bind-btn" wx:else>去绑定</text>
</view>
</view>
<!-- 收货地址 - 微信一键获取 -->
<view class="bind-item" bindtap="getAddress">
<view class="bind-left">
<view class="bind-icon address-icon">📍</view>
<view class="bind-info">
<text class="bind-label">收货地址</text>
<text class="bind-value address-text">{{address || '未绑定'}}</text>
</view>
</view>
<view class="bind-right">
<text class="bind-check" wx:if="{{address}}">✓</text>
<text class="bind-btn" wx:else>一键获取</text>
</view>
</view>
</view>
</view>