From ecee1bb2bb895f8bb7ac885ba47c452cbd072215 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B9=98=E9=A3=8E?= Date: Wed, 11 Feb 2026 15:50:53 +0800 Subject: [PATCH] =?UTF-8?q?=E9=87=8D=E6=9E=84=E5=8C=B9=E9=85=8D=E9=A1=B5?= =?UTF-8?q?=E9=9D=A2=EF=BC=8C=E9=80=9A=E8=BF=87=E6=96=B0=E5=A2=9E=E7=99=BB?= =?UTF-8?q?=E5=BD=95=E5=92=8C=E6=89=8B=E6=9C=BA=E5=8F=B7=E7=BB=91=E5=AE=9A?= =?UTF-8?q?=E6=A8=A1=E6=80=81=E7=AA=97=E5=8F=A3=E6=9D=A5=E6=8F=90=E5=8D=87?= =?UTF-8?q?=E7=94=A8=E6=88=B7=E4=BD=93=E9=AA=8C=E3=80=82=E5=9C=A8=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E5=A5=BD=E5=8F=8B=E5=89=8D=EF=BC=8C=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E4=BA=86=E9=80=9A=E8=BF=87=E5=BE=AE=E4=BF=A1=E5=92=8C=E6=89=8B?= =?UTF-8?q?=E6=9C=BA=E5=8F=B7=E7=BB=91=E5=AE=9A=E7=99=BB=E5=BD=95=E7=9A=84?= =?UTF-8?q?=E5=8A=9F=E8=83=BD=E3=80=82=E6=9B=B4=E6=96=B0=E4=BA=86API?= =?UTF-8?q?=E9=85=8D=E7=BD=AE=EF=BC=8C=E5=B9=B6=E8=B0=83=E6=95=B4=E4=BA=86?= =?UTF-8?q?=E7=94=A8=E6=88=B7=E8=81=94=E7=B3=BB=E4=BF=A1=E6=81=AF=E7=9A=84?= =?UTF-8?q?=E6=9C=AC=E5=9C=B0=E5=AD=98=E5=82=A8=E5=A4=84=E7=90=86=E6=96=B9?= =?UTF-8?q?=E5=BC=8F=E3=80=82=E6=94=B9=E8=BF=9B=E4=BA=86=E6=A8=A1=E6=80=81?= =?UTF-8?q?=E7=AA=97=E5=8F=A3=E7=9A=84=E7=94=A8=E6=88=B7=E7=95=8C=E9=9D=A2?= =?UTF-8?q?=E5=85=83=E7=B4=A0=EF=BC=8C=E5=B9=B6=E7=A1=AE=E4=BF=9D=E7=94=A8?= =?UTF-8?q?=E6=88=B7=E4=BA=A4=E4=BA=92=E7=9A=84=E6=95=B0=E6=8D=AE=E6=B5=81?= =?UTF-8?q?=E6=AD=A3=E7=A1=AE=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- miniprogram/app.js | 4 +- miniprogram/pages/match/match.js | 252 +++++++++++++++++++++--- miniprogram/pages/match/match.wxml | 69 +++++++ miniprogram/pages/match/match.wxss | 168 +++++++++++++++- miniprogram/pages/my/my.wxml | 42 +--- miniprogram/project.private.config.json | 13 +- soul-api/internal/handler/ckb.go | 63 ++++-- soul-api/internal/handler/match.go | 8 +- soul-api/wechat/info.log | 10 + tmp/build-errors.log | 1 + 10 files changed, 532 insertions(+), 98 deletions(-) create mode 100644 tmp/build-errors.log diff --git a/miniprogram/app.js b/miniprogram/app.js index cc86b263..2bd161cf 100644 --- a/miniprogram/app.js +++ b/miniprogram/app.js @@ -7,9 +7,9 @@ App({ globalData: { // API基础地址 - 连接真实后端 // baseUrl: 'https://soulapi.quwanzhi.com', - baseUrl: 'https://souldev.quwanzhi.com', + // baseUrl: 'https://souldev.quwanzhi.com', // baseUrl: 'http://localhost:3006', - // baseUrl: 'http://localhost:8080', + baseUrl: 'http://localhost:8080', // 小程序配置 - 真实AppID appId: 'wxb8bbb2b10dec74aa', diff --git a/miniprogram/pages/match/match.js b/miniprogram/pages/match/match.js index fe9d7b4d..6054c1b8 100644 --- a/miniprogram/pages/match/match.js +++ b/miniprogram/pages/match/match.js @@ -66,6 +66,17 @@ Page({ // 解锁弹窗 showUnlockModal: false, + // 手机号绑定弹窗(一键加好友前校验) + showBindPhoneModal: false, + pendingAddWechatAfterBind: false, + bindPhoneInput: '', + showMatchPhoneManualInput: false, + + // 登录弹窗(未登录时点击匹配弹出) + showLoginModal: false, + isLoggingIn: false, + agreeProtocol: false, + // 匹配价格(可配置) matchPrice: 1, extraMatches: 0 @@ -90,6 +101,7 @@ Page({ tabBar.setData({ selected: 2 }) } } + this.loadStoredContact() this.initUserStatus() }, @@ -123,10 +135,11 @@ Page({ } }, - // 加载本地存储的联系方式 + // 加载本地存储的联系方式(含用户资料的手机号、微信号) loadStoredContact() { - const phone = wx.getStorageSync('user_phone') || '' - const wechat = wx.getStorageSync('user_wechat') || '' + const ui = app.globalData.userInfo || {} + const phone = wx.getStorageSync('user_phone') || ui.phone || '' + const wechat = wx.getStorageSync('user_wechat') || ui.wechat || ui.wechatId || '' this.setData({ phoneNumber: phone, wechatId: wechat, @@ -192,25 +205,16 @@ Page({ // 点击匹配按钮 handleMatchClick() { + // 检测是否登录,未登录则弹出登录弹窗 + if (!this.data.isLoggedIn) { + this.setData({ showLoginModal: true, agreeProtocol: false }) + return + } + const currentType = MATCH_TYPES.find(t => t.id === this.data.selectedType) - // 资源对接类型需要登录+购买章节才能使用 + // 资源对接类型需要购买章节才能使用 if (currentType && currentType.id === 'investor') { - // 检查是否登录 - if (!this.data.isLoggedIn) { - wx.showModal({ - title: '需要登录', - content: '请先登录后再使用资源对接功能', - confirmText: '去登录', - success: (res) => { - if (res.confirm) { - wx.switchTab({ url: '/pages/my/my' }) - } - } - }) - return - } - // 检查是否购买过章节 const hasPurchased = app.globalData.purchasedSections?.length > 0 || app.globalData.hasFullBook if (!hasPurchased) { @@ -235,7 +239,8 @@ Page({ const hasWechat = !!this.data.wechatId if (!hasPhone && !hasWechat) { - // 没有绑定联系方式,先显示绑定提示 + // 没有绑定联系方式,先显示绑定提示(仍尝试加载已有资料填充) + this.loadStoredContact() this.setData({ showJoinModal: true, joinType: currentType.id, @@ -279,6 +284,8 @@ Page({ const delay = Math.random() * 2000 + 1000 setTimeout(() => { clearInterval(timer) + // 打开弹窗前调取用户资料填充手机号、微信号 + this.loadStoredContact() this.setData({ isMatching: false, showJoinModal: true, @@ -435,26 +442,78 @@ Page({ this.setData({ currentMatch: null }) }, - // 添加微信好友 + // 添加微信好友(先校验手机号绑定) handleAddWechat() { if (!this.data.currentMatch) return + // 未登录需先登录 + if (!app.globalData.isLoggedIn) { + wx.showModal({ + title: '需要登录', + content: '请先登录后再添加好友', + confirmText: '去登录', + success: (res) => { + if (res.confirm) wx.switchTab({ url: '/pages/my/my' }) + } + }) + return + } + + // 判断是否已绑定手机号(本地缓存或用户资料) + const hasPhone = !!( + wx.getStorageSync('user_phone') || + app.globalData.userInfo?.phone + ) + + if (!hasPhone) { + this.setData({ + showBindPhoneModal: true, + pendingAddWechatAfterBind: true + }) + return + } + + this.doCopyWechat() + }, + + // 执行复制联系方式(优先微信号,无则复制手机号) + doCopyWechat() { + if (!this.data.currentMatch) return + const wechat = (this.data.currentMatch.wechat || this.data.currentMatch.wechatId || '').trim() + const phone = (this.data.currentMatch.phone || '').trim() + const toCopy = wechat || phone + if (!toCopy) { + wx.showModal({ + title: '暂无可复制', + content: '该用户未提供微信号或手机号,请通过其他方式联系', + showCancel: false, + confirmText: '知道了' + }) + return + } + const label = wechat ? '微信号' : '手机号' wx.setClipboardData({ - data: this.data.currentMatch.wechat, + data: toCopy, success: () => { wx.showModal({ - title: '微信号已复制', - content: `微信号:${this.data.currentMatch.wechat}\n\n请打开微信添加好友,备注"创业合作"即可`, + title: wechat ? '微信号已复制' : '手机号已复制', + content: wechat + ? `${label}:${toCopy}\n\n请打开微信添加好友,备注"创业合作"即可` + : `${label}:${toCopy}\n\n可通过微信搜索该手机号添加好友`, showCancel: false, confirmText: '知道了' }) + }, + fail: () => { + wx.showToast({ title: '复制失败,请重试', icon: 'none' }) } }) }, - // 切换联系方式类型 + // 切换联系方式类型(同步刷新用户资料填充) switchContactType(e) { const type = e.currentTarget.dataset.type + this.loadStoredContact() this.setData({ contactType: type, joinError: '' }) }, @@ -565,6 +624,149 @@ Page({ this.setData({ showJoinModal: false, joinError: '' }) }, + // 关闭手机绑定弹窗 + closeBindPhoneModal() { + this.setData({ + showBindPhoneModal: false, + pendingAddWechatAfterBind: false, + bindPhoneInput: '', + showMatchPhoneManualInput: false + }) + }, + + // 关闭登录弹窗 + closeLoginModal() { + if (this.data.isLoggingIn) return + this.setData({ showLoginModal: false }) + }, + + // 切换协议勾选 + toggleAgree() { + this.setData({ agreeProtocol: !this.data.agreeProtocol }) + }, + + // 打开用户协议 + openUserProtocol() { + wx.navigateTo({ url: '/pages/agreement/agreement' }) + }, + + // 打开隐私政策 + openPrivacy() { + wx.navigateTo({ url: '/pages/privacy/privacy' }) + }, + + // 微信登录(匹配页) + async handleMatchWechatLogin() { + if (!this.data.agreeProtocol) { + wx.showToast({ title: '请先阅读并同意用户协议和隐私政策', icon: 'none' }) + return + } + this.setData({ isLoggingIn: true }) + try { + const result = await app.login() + if (result) { + this.initUserStatus() + this.setData({ showLoginModal: false, agreeProtocol: false }) + wx.showToast({ title: '登录成功', icon: 'success' }) + } else { + wx.showToast({ title: '登录失败,请重试', icon: 'none' }) + } + } catch (e) { + console.error('[Match] 微信登录错误:', e) + wx.showToast({ title: '登录失败,请重试', icon: 'none' }) + } finally { + this.setData({ isLoggingIn: false }) + } + }, + + // 一键获取手机号(匹配页加好友前绑定) + async onMatchGetPhoneNumber(e) { + if (e.detail.errMsg !== 'getPhoneNumber:ok') { + wx.showToast({ title: '授权失败', icon: 'none' }) + return + } + const code = e.detail.code + if (!code) { + this.setData({ showMatchPhoneManualInput: true }) + return + } + try { + wx.showLoading({ title: '获取中...', mask: true }) + const userId = app.globalData.userInfo?.id + const res = await app.request('/api/miniprogram/phone', { + method: 'POST', + data: { code, userId } + }) + wx.hideLoading() + if (res.success && res.phoneNumber) { + await this.saveMatchPhoneAndContinue(res.phoneNumber) + } else { + this.setData({ showMatchPhoneManualInput: true }) + } + } catch (err) { + wx.hideLoading() + this.setData({ showMatchPhoneManualInput: true }) + } + }, + + // 切换为手动输入 + onMatchShowManualInput() { + this.setData({ showMatchPhoneManualInput: true }) + }, + + // 手动输入手机号 + onMatchPhoneInput(e) { + this.setData({ + bindPhoneInput: e.detail.value.replace(/\D/g, '').slice(0, 11) + }) + }, + + // 确认手动绑定手机号 + async confirmMatchPhoneBind() { + const { bindPhoneInput } = this.data + if (!bindPhoneInput || bindPhoneInput.length !== 11) { + wx.showToast({ title: '请输入正确的11位手机号', icon: 'none' }) + return + } + if (!/^1[3-9]\d{9}$/.test(bindPhoneInput)) { + wx.showToast({ title: '请输入正确的手机号', icon: 'none' }) + return + } + await this.saveMatchPhoneAndContinue(bindPhoneInput) + }, + + // 保存手机号到本地+服务器,并继续加好友 + async saveMatchPhoneAndContinue(phone) { + wx.setStorageSync('user_phone', phone) + if (app.globalData.userInfo) { + app.globalData.userInfo.phone = phone + wx.setStorageSync('userInfo', app.globalData.userInfo) + } + this.setData({ + phoneNumber: phone, + userPhone: phone, + bindPhoneInput: '' + }) + this.loadStoredContact() + try { + const userId = app.globalData.userInfo?.id + if (userId) { + await app.request('/api/miniprogram/user/profile', { + method: 'POST', + data: { userId, phone } + }) + } + } catch (e) { + console.log('[Match] 同步手机号到服务器失败:', e) + } + const pending = this.data.pendingAddWechatAfterBind + this.closeBindPhoneModal() + if (pending) { + wx.showToast({ title: '绑定成功', icon: 'success' }) + setTimeout(() => this.doCopyWechat(), 500) + } + }, + // 显示解锁弹窗 showUnlockModal() { this.setData({ showUnlockModal: true }) diff --git a/miniprogram/pages/match/match.wxml b/miniprogram/pages/match/match.wxml index 3585aee0..df47b547 100644 --- a/miniprogram/pages/match/match.wxml +++ b/miniprogram/pages/match/match.wxml @@ -265,6 +265,75 @@ + + + + + + + + + + + 📱 + + 需要先绑定手机号 + 为保障联系方式真实有效,加好友前请先绑定手机号 + + + + + + + 手动输入手机号 + + + + + + + +86 + + + + 确认绑定 + + + + diff --git a/miniprogram/pages/match/match.wxss b/miniprogram/pages/match/match.wxss index 378e1c99..3719ae27 100644 --- a/miniprogram/pages/match/match.wxss +++ b/miniprogram/pages/match/match.wxss @@ -584,6 +584,133 @@ overflow: hidden; } +/* ===== 登录弹窗 ===== */ +.login-modal-content { + padding: 48rpx; + position: relative; +} + +.login-modal-content .modal-close { + position: absolute; + top: 24rpx; + right: 24rpx; + width: 64rpx; + height: 64rpx; + border-radius: 50%; + background: rgba(255, 255, 255, 0.1); + display: flex; + align-items: center; + justify-content: center; + font-size: 28rpx; + color: rgba(255, 255, 255, 0.6); +} + +.login-icon { + font-size: 96rpx; + text-align: center; + display: block; + margin-bottom: 24rpx; +} + +.login-title { + font-size: 36rpx; + font-weight: 700; + color: #ffffff; + text-align: center; + display: block; + margin-bottom: 16rpx; +} + +.login-desc { + font-size: 26rpx; + color: rgba(255, 255, 255, 0.6); + text-align: center; + display: block; + margin-bottom: 48rpx; +} + +.btn-wechat { + width: 100%; + display: flex; + align-items: center; + justify-content: center; + gap: 16rpx; + padding: 28rpx; + background: #07C160; + color: #ffffff; + font-size: 28rpx; + font-weight: 500; + border-radius: 24rpx; + margin-bottom: 24rpx; + border: none; +} + +.btn-wechat::after { + border: none; +} + +.btn-wechat-icon { + width: 40rpx; + height: 40rpx; + background: rgba(255, 255, 255, 0.2); + border-radius: 8rpx; + display: flex; + align-items: center; + justify-content: center; + font-size: 24rpx; +} + +.login-modal-cancel { + margin-top: 24rpx; + padding: 24rpx; + font-size: 28rpx; + color: rgba(255, 255, 255, 0.5); + text-align: center; +} + +.login-agree-row { + display: flex; + flex-wrap: wrap; + align-items: center; + justify-content: center; + margin-top: 32rpx; + font-size: 22rpx; + color: rgba(255, 255, 255, 0.5); +} + +.agree-checkbox { + width: 32rpx; + height: 32rpx; + border: 2rpx solid rgba(255, 255, 255, 0.5); + border-radius: 6rpx; + margin-right: 12rpx; + display: flex; + align-items: center; + justify-content: center; + font-size: 22rpx; + color: #fff; + flex-shrink: 0; +} + +.agree-checked { + background: #00CED1; + border-color: #00CED1; +} + +.agree-text { + color: rgba(255, 255, 255, 0.6); +} + +.agree-link { + color: #00CED1; + text-decoration: underline; + padding: 0 4rpx; +} + +.btn-wechat-disabled { + opacity: 0.6; +} + /* ===== 加入弹窗 ===== */ .join-modal { padding: 40rpx; @@ -705,7 +832,7 @@ .join-header { position: relative; - padding: 48rpx 40rpx 32rpx; + padding: 48rpx 48rpx 32rpx; background: linear-gradient(135deg, rgba(0, 206, 209, 0.15) 0%, rgba(123, 97, 255, 0.1) 100%); text-align: center; } @@ -754,10 +881,39 @@ color: rgba(255, 255, 255, 0.6); } +/* 手机号绑定弹窗 */ +.bind-phone-actions { + padding: 32rpx 40rpx 48rpx; + display: flex; + flex-direction: column; + align-items: center; + gap: 24rpx; +} + +.get-phone-btn-modal { + width: 100%; + padding: 28rpx 48rpx; + background: linear-gradient(135deg, #00CED1 0%, #20B2AA 100%); + color: #fff; + font-size: 32rpx; + font-weight: 600; + border-radius: 20rpx; + border: none; +} + +.get-phone-btn-modal::after { + border: none; +} + +.manual-bind-link { + font-size: 28rpx; + color: rgba(0, 206, 209, 0.9); +} + .contact-switch { display: flex; gap: 16rpx; - padding: 24rpx 40rpx; + padding: 24rpx 48rpx; } .switch-item { @@ -785,7 +941,7 @@ } .input-area { - padding: 0 40rpx 24rpx; + padding: 0 48rpx 24rpx; } .input-wrapper { @@ -824,7 +980,7 @@ } .submit-btn-new { - margin: 8rpx 40rpx 24rpx; + margin: 8rpx 48rpx 24rpx; padding: 28rpx; background: linear-gradient(135deg, #00CED1 0%, #20B2AA 100%); color: #ffffff; @@ -843,7 +999,7 @@ text-align: center; font-size: 22rpx; color: rgba(255, 255, 255, 0.3); - padding-bottom: 32rpx; + padding: 0 48rpx 32rpx; } /* ===== 新版加入成功 ===== */ @@ -1181,7 +1337,7 @@ display: flex; flex-direction: column; gap: 20rpx; - margin-bottom: 24rpx; + margin: 0 48rpx 24rpx; } .resource-form .form-item { display: flex; diff --git a/miniprogram/pages/my/my.wxml b/miniprogram/pages/my/my.wxml index 2a5e74d2..0fd009b3 100644 --- a/miniprogram/pages/my/my.wxml +++ b/miniprogram/pages/my/my.wxml @@ -90,46 +90,8 @@ - - - - - - - - - - - 💰 - 我的收益 - - - - - - - - - - 累计收益 - {{earningsLoading ? '-' : '¥' + earnings}} - - - 可提现 - {{earningsLoading ? '-' : '¥' + pendingEarnings}} - - - - - - 🎁 - 推广中心 / 提现 - - - - - - + + 待确认收款 审核已通过,点击下方按钮完成收款 diff --git a/miniprogram/project.private.config.json b/miniprogram/project.private.config.json index e2f657fd..10365da5 100644 --- a/miniprogram/project.private.config.json +++ b/miniprogram/project.private.config.json @@ -3,7 +3,7 @@ "projectname": "miniprogram", "setting": { "compileHotReLoad": true, - "urlCheck": true, + "urlCheck": false, "coverView": true, "lazyloadPlaceholderEnable": false, "skylineRenderEnable": false, @@ -23,12 +23,19 @@ "condition": { "miniprogram": { "list": [ + { + "name": "找伙伴", + "pathName": "pages/match/match", + "query": "", + "scene": null, + "launchMode": "default" + }, { "name": "pages/read/read", "pathName": "pages/read/read", "query": "id=1.1", - "scene": null, - "launchMode": "default" + "launchMode": "default", + "scene": null }, { "name": "pages/match/match", diff --git a/soul-api/internal/handler/ckb.go b/soul-api/internal/handler/ckb.go index 72b2f261..ce37f3ab 100644 --- a/soul-api/internal/handler/ckb.go +++ b/soul-api/internal/handler/ckb.go @@ -5,6 +5,7 @@ import ( "crypto/md5" "encoding/hex" "encoding/json" + "fmt" "io" "net/http" "sort" @@ -20,6 +21,7 @@ const ckbAPIURL = "https://ckbapi.quwanzhi.com/v1/api/scenarios" var ckbSourceMap = map[string]string{"team": "团队招募", "investor": "资源对接", "mentor": "导师顾问", "partner": "创业合伙"} var ckbTagsMap = map[string]string{"team": "切片团队,团队招募", "investor": "资源对接,资源群", "mentor": "导师顾问,咨询服务", "partner": "创业合伙,创业伙伴"} +// ckbSign 与 next-project app/api/ckb/join 一致:排除 sign/apiKey/portrait,空值跳过,按键升序拼接值,MD5(拼接串) 再 MD5(结果+apiKey) func ckbSign(params map[string]interface{}, apiKey string) string { keys := make([]string, 0, len(params)) for k := range params { @@ -35,13 +37,16 @@ func ckbSign(params map[string]interface{}, apiKey string) string { sort.Strings(keys) var concat string for _, k := range keys { - switch v := params[k].(type) { + v := params[k] + switch val := v.(type) { case string: - concat += v + concat += val case float64: - concat += strconv.FormatFloat(v, 'f', -1, 64) + concat += strconv.FormatFloat(val, 'f', -1, 64) case int: - concat += strconv.Itoa(v) + concat += strconv.Itoa(val) + case int64: + concat += strconv.FormatInt(val, 10) default: concat += "" } @@ -55,12 +60,14 @@ func ckbSign(params map[string]interface{}, apiKey string) string { // CKBJoin POST /api/ckb/join func CKBJoin(c *gin.Context) { var body struct { - Type string `json:"type" binding:"required"` - Phone string `json:"phone"` - Wechat string `json:"wechat"` - Name string `json:"name"` - UserID string `json:"userId"` - Remark string `json:"remark"` + Type string `json:"type" binding:"required"` + Phone string `json:"phone"` + Wechat string `json:"wechat"` + Name string `json:"name"` + UserID string `json:"userId"` + Remark string `json:"remark"` + CanHelp string `json:"canHelp"` // 资源对接:我能帮到你什么 + NeedHelp string `json:"needHelp"` // 资源对接:我需要什么帮助 } if err := c.ShouldBindJSON(&body); err != nil { c.JSON(http.StatusBadRequest, gin.H{"success": false, "message": "请提供手机号或微信号"}) @@ -83,7 +90,11 @@ func CKBJoin(c *gin.Context) { "remark": body.Remark, } if body.Remark == "" { - params["remark"] = "用户通过创业实验APP申请" + ckbSourceMap[body.Type] + remark := "用户通过创业实验APP申请" + ckbSourceMap[body.Type] + if body.Type == "investor" && (body.CanHelp != "" || body.NeedHelp != "") { + remark = fmt.Sprintf("能帮:%s 需要:%s", body.CanHelp, body.NeedHelp) + } + params["remark"] = remark } if body.Phone != "" { params["phone"] = body.Phone @@ -96,14 +107,23 @@ func CKBJoin(c *gin.Context) { } params["apiKey"] = ckbAPIKey params["sign"] = ckbSign(params, ckbAPIKey) + sourceData := map[string]interface{}{ + "joinType": body.Type, "joinLabel": ckbSourceMap[body.Type], "userId": body.UserID, + "device": "webapp", "timestamp": time.Now().Format(time.RFC3339), + } + if body.Type == "investor" { + if body.CanHelp != "" { + sourceData["canHelp"] = body.CanHelp + } + if body.NeedHelp != "" { + sourceData["needHelp"] = body.NeedHelp + } + } params["portrait"] = map[string]interface{}{ "type": 4, "source": 0, - "sourceData": map[string]interface{}{ - "joinType": body.Type, "joinLabel": ckbSourceMap[body.Type], "userId": body.UserID, - "device": "webapp", "timestamp": time.Now().Format(time.RFC3339), - }, - "remark": ckbSourceMap[body.Type] + "申请", - "uniqueId": "soul_" + body.Phone + body.Wechat + strconv.FormatInt(ts, 10), + "sourceData": sourceData, + "remark": ckbSourceMap[body.Type] + "申请", + "uniqueId": "soul_" + body.Phone + body.Wechat + strconv.FormatInt(ts, 10), } raw, _ := json.Marshal(params) resp, err := http.Post(ckbAPIURL, "application/json", bytes.NewReader(raw)) @@ -127,7 +147,14 @@ func CKBJoin(c *gin.Context) { c.JSON(http.StatusOK, gin.H{"success": true, "message": msg, "data": result.Data}) return } - c.JSON(http.StatusOK, gin.H{"success": false, "message": result.Message}) + errMsg := result.Message + if errMsg == "" { + errMsg = "加入失败,请稍后重试" + } + // 打印 CKB 原始响应便于排查 + fmt.Printf("[CKBJoin] 失败 type=%s wechat=%s code=%d message=%s raw=%s\n", + body.Type, body.Wechat, result.Code, result.Message, string(b)) + c.JSON(http.StatusOK, gin.H{"success": false, "message": errMsg}) } // CKBMatch POST /api/ckb/match diff --git a/soul-api/internal/handler/match.go b/soul-api/internal/handler/match.go index 0b2d77fd..595d6428 100644 --- a/soul-api/internal/handler/match.go +++ b/soul-api/internal/handler/match.go @@ -88,8 +88,11 @@ func MatchUsers(c *gin.Context) { c.JSON(http.StatusBadRequest, gin.H{"success": false, "message": "缺少用户ID"}) return } + // 只匹配已绑定微信或手机号的用户 var users []model.User - if err := database.DB().Where("id != ?", body.UserID).Order("created_at DESC").Limit(20).Find(&users).Error; err != nil || len(users) == 0 { + q := database.DB().Where("id != ?", body.UserID). + Where("((wechat_id IS NOT NULL AND wechat_id != '') OR (phone IS NOT NULL AND phone != ''))") + if err := q.Order("created_at DESC").Limit(20).Find(&users).Error; err != nil || len(users) == 0 { c.JSON(http.StatusOK, gin.H{"success": false, "message": "暂无匹配用户", "data": nil}) return } @@ -114,9 +117,6 @@ func MatchUsers(c *gin.Context) { phone := "" if r.Phone != nil { phone = *r.Phone - if len(phone) == 11 { - phone = phone[:3] + "****" + phone[7:] - } } intro := "来自Soul创业派对的伙伴" matchLabels := map[string]string{"partner": "找伙伴", "investor": "资源对接", "mentor": "导师顾问", "team": "团队招募"} diff --git a/soul-api/wechat/info.log b/soul-api/wechat/info.log index 3ef83fe7..9214fa49 100644 --- a/soul-api/wechat/info.log +++ b/soul-api/wechat/info.log @@ -76,3 +76,13 @@ {"level":"debug","timestamp":"2026-02-10T12:08:49+08:00","caller":"kernel/baseClient.go:459","content":"------------------response content:HTTP/1.1 403 Forbidden\r\nContent-Length: 171\r\nCache-Control: no-cache, must-revalidate\r\nConnection: keep-alive\r\nContent-Language: zh-CN\r\nContent-Type: application/json; charset=utf-8\r\nDate: Tue, 10 Feb 2026 04:08:49 GMT\r\nKeep-Alive: timeout=8\r\nRequest-Id: 08D1DEAACC06102B18FFD6BCA80120AA1928EBB404-268561072\r\nServer: nginx\r\nWechatpay-Nonce: 6c965e3c5aca952b9666dbccc6881923\r\nWechatpay-Serial: 5F2543BF58239A4EB68FA4433DF1438A88B34B16\r\nWechatpay-Signature: KKjTWimPKOSVdM/MzuPt3oAxtq3Cy2lr3ZqFXByMmgs3lovRianNEmtwmOi5EGtyo4TbdbUVpzObLUepZGfTIG7Cz8U1cnGLmqxfZxgSyRIatf5OVGYIh5RIwYrkqFdJaN/zcdjYOc73N8FWYn5+bgY51D6aD27AWbPwA7nYNJB4rKmH2QRR9ZuI1kuwDob2ezKWgzV8pkU3DxRSPP/G+BM/HINzurl04/bjAfAtst9JynlPfO61EmEEUCILSpBbKn9dSzEIq2YSz5SxIExv24fhUJ0pjcjvVZo+O0Ddx9vrkNDNSPXao83zqiZTrQkix2vDAEIc6r5SsLCyaGwaTA==\r\nWechatpay-Signature-Type: WECHATPAY2-SHA256-RSA2048\r\nWechatpay-Timestamp: 1770696529\r\nX-Content-Type-Options: nosniff\r\n\r\n{\"code\":\"NO_AUTH\",\"message\":\"当前商户号接入升级版本功能,暂不支持使用升级前功能,请在产品中心-商家转账-前往功能查看接口文档\"}"} {"level":"debug","timestamp":"2026-02-10T14:30:44+08:00","caller":"kernel/baseClient.go:457","content":"POST https://api.mch.weixin.qq.com/v3/fund-app/mch-transfer/transfer-bills request header: { Content-Type:application/jsonAuthorization:WECHATPAY2-SHA256-RSA2048 mchid=\"1318592501\",nonce_str=\"tAslXtBASHF46eu8viT6eWrevb5s3amJ\",timestamp=\"1770705044\",serial_no=\"4A1DB62CD5C9BE0B6FC51C30621D6F99686E75C5\",signature=\"45mBO41rIGYDKEtV0wVTh5IjM9OsZNFFDcPpHCEXZin9ukqYHo8GXRlLR50gTYaETzoOry+kdI6Xe1aNpGoLLbeGFOw5Znj167BGrGPnfwyX87lAEvXbafrq7fpab+tVDHXJfLw/dnQ8q+Wy5/gszJx/YllSgyMgoIg+7gc3TDy8e6Ft/QtbbB8CLP4LVUvonG30OdVbspIDd6YpCsJSDQ58dM8Xb7sFEHaUv4bBVwu4U3sZ41muEXFH2JUgsVCT3AR+PgwXyTPeb+cNJyQ0RVAJ04/0fdPV3LszfKvjNJx5rtl05MQd5uS+Dh8JlFDXfHicnC4jG3EtAz1rT7crjw==\"Accept:*/*} request body:"} {"level":"debug","timestamp":"2026-02-10T14:30:44+08:00","caller":"kernel/baseClient.go:459","content":"------------------response content:HTTP/1.1 400 Bad Request\r\nContent-Length: 98\r\nCache-Control: no-cache, must-revalidate\r\nConnection: keep-alive\r\nContent-Language: zh-CN\r\nContent-Type: application/json; charset=utf-8\r\nDate: Tue, 10 Feb 2026 06:30:44 GMT\r\nKeep-Alive: timeout=8\r\nRequest-Id: 0894A1ABCC0610DF0318ECE7F8AF0120EE482884D103-268491067\r\nServer: nginx\r\nWechatpay-Nonce: 1edf81984af96eff23f05a173edee1a9\r\nWechatpay-Serial: 5F2543BF58239A4EB68FA4433DF1438A88B34B16\r\nWechatpay-Signature: sSpmhuIF5wtIHyiwwk7/4mjif3D6FadetjRTkamWXzuiTPp2Vmfo0je2ZKIC038nEqQpfC59ZuC2D6/xROJeAgbpuveTsNw+gRuw7ixMomRnu2ur5paxrelIxjxrStp66wjlbHRQgmsJyCag42ObZqrvJWA7SqPbyaYl3fmLGCv5I4uTiVLwTNmv2dg+9iMw6mk00A5sN99FXKDXIPrrTvKpyi7lbqoleDNzVBdG+DMhPh8Etjlr/QpHydjrTZ28plul6YtITAp8zYmEOMg/s0Iiz9Mp9ZCNDA2PPG1D/jZ2wpxqr1XMCnE6yZE3oKQqoXZZQr336LYjMxeQEh1lRA==\r\nWechatpay-Signature-Type: WECHATPAY2-SHA256-RSA2048\r\nWechatpay-Timestamp: 1770705044\r\nX-Content-Type-Options: nosniff\r\n\r\n{\"code\":\"INVALID_REQUEST\",\"message\":\"此IP地址不允许调用接口,请按开发指引设置\"}"} +{"level":"debug","timestamp":"2026-02-11T15:24:51+08:00","caller":"kernel/accessToken.go:381","content":"GET https://api.weixin.qq.com/cgi-bin/token?appid=wxb8bbb2b10dec74aa&grant_type=client_credential&neededText=&secret=3c1fb1f63e6e052222bbcead9d07fe0c request header: { Accept:*/*} "} +{"level":"debug","timestamp":"2026-02-11T15:24:51+08:00","caller":"kernel/accessToken.go:383","content":"------------------response content:HTTP/1.1 200 OK\r\nContent-Length: 174\r\nConnection: keep-alive\r\nContent-Type: application/json; encoding=utf-8\r\nDate: Wed, 11 Feb 2026 07:24:52 GMT\r\n\r\n{\"access_token\":\"101_rGBEywFQ8RzMuEbFWgtU8oYu6Dh5XR2GmwL5EUfPc1oCatASfWinC9ei7mYVYWAOXpKY0KLnwHNB3XAOlqu1eMxy99iEUFzxW0V8dT84peEIOYxzZjKqWpxPamEBZZaABAJHH\",\"expires_in\":7200}"} +{"level":"debug","timestamp":"2026-02-11T15:33:31+08:00","caller":"kernel/baseClient.go:457","content":"GET https://api.weixin.qq.com/sns/jscode2session?access_token=101_rGBEywFQ8RzMuEbFWgtU8oYu6Dh5XR2GmwL5EUfPc1oCatASfWinC9ei7mYVYWAOXpKY0KLnwHNB3XAOlqu1eMxy99iEUFzxW0V8dT84peEIOYxzZjKqWpxPamEBZZaABAJHH&appid=wxb8bbb2b10dec74aa&grant_type=authorization_code&js_code=0c3dPKll2GXA9h4XdBol2lv2Hv2dPKlL&secret=3c1fb1f63e6e052222bbcead9d07fe0c request header: { Accept:*/*} "} +{"level":"debug","timestamp":"2026-02-11T15:33:31+08:00","caller":"kernel/baseClient.go:459","content":"------------------response content:HTTP/1.1 200 OK\r\nContent-Length: 82\r\nConnection: keep-alive\r\nContent-Type: text/plain\r\nDate: Wed, 11 Feb 2026 07:33:32 GMT\r\n\r\n{\"session_key\":\"/BZGO5L50veBj7S7Jmt5KQ==\",\"openid\":\"ogpTW5fmXRGNpoUbXB3UEqnVe5Tg\"}"} +{"level":"debug","timestamp":"2026-02-11T15:34:32+08:00","caller":"kernel/baseClient.go:457","content":"GET https://api.weixin.qq.com/sns/jscode2session?access_token=101_rGBEywFQ8RzMuEbFWgtU8oYu6Dh5XR2GmwL5EUfPc1oCatASfWinC9ei7mYVYWAOXpKY0KLnwHNB3XAOlqu1eMxy99iEUFzxW0V8dT84peEIOYxzZjKqWpxPamEBZZaABAJHH&appid=wxb8bbb2b10dec74aa&grant_type=authorization_code&js_code=0d3AGZGa1YadaL04jeJa1qd37z2AGZGO&secret=3c1fb1f63e6e052222bbcead9d07fe0c request header: { Accept:*/*} "} +{"level":"debug","timestamp":"2026-02-11T15:34:32+08:00","caller":"kernel/baseClient.go:459","content":"------------------response content:HTTP/1.1 200 OK\r\nContent-Length: 82\r\nConnection: keep-alive\r\nContent-Type: text/plain\r\nDate: Wed, 11 Feb 2026 07:34:32 GMT\r\n\r\n{\"session_key\":\"79hxrJbW2eK1gDiqMBhZMg==\",\"openid\":\"ogpTW5fmXRGNpoUbXB3UEqnVe5Tg\"}"} +{"level":"debug","timestamp":"2026-02-11T15:36:10+08:00","caller":"kernel/accessToken.go:381","content":"GET https://api.weixin.qq.com/cgi-bin/token?appid=wxb8bbb2b10dec74aa&grant_type=client_credential&neededText=&secret=3c1fb1f63e6e052222bbcead9d07fe0c request header: { Accept:*/*} "} +{"level":"debug","timestamp":"2026-02-11T15:36:10+08:00","caller":"kernel/accessToken.go:383","content":"------------------response content:HTTP/1.1 200 OK\r\nContent-Length: 174\r\nConnection: keep-alive\r\nContent-Type: application/json; encoding=utf-8\r\nDate: Wed, 11 Feb 2026 07:36:11 GMT\r\n\r\n{\"access_token\":\"101_MiWs49YphSqT8fdzbbvWznN0pNKQ99O94IqbcNCL6FoMWAZG6t0v-D4xg37xDjsyGgttZm2qfQd1pg6C4za3yiJrKv8g7s8M1n_-biSvQq-zNg6WqUzq1zTv_HQVRQaACALHG\",\"expires_in\":7200}"} +{"level":"debug","timestamp":"2026-02-11T15:36:11+08:00","caller":"kernel/baseClient.go:457","content":"GET https://api.weixin.qq.com/sns/jscode2session?access_token=101_MiWs49YphSqT8fdzbbvWznN0pNKQ99O94IqbcNCL6FoMWAZG6t0v-D4xg37xDjsyGgttZm2qfQd1pg6C4za3yiJrKv8g7s8M1n_-biSvQq-zNg6WqUzq1zTv_HQVRQaACALHG&appid=wxb8bbb2b10dec74aa&grant_type=authorization_code&js_code=0a1alR000sNRQV1MJl400aJVgF3alR0q&secret=3c1fb1f63e6e052222bbcead9d07fe0c request header: { Accept:*/*} "} +{"level":"debug","timestamp":"2026-02-11T15:36:11+08:00","caller":"kernel/baseClient.go:459","content":"------------------response content:HTTP/1.1 200 OK\r\nContent-Length: 82\r\nConnection: keep-alive\r\nContent-Type: text/plain\r\nDate: Wed, 11 Feb 2026 07:36:11 GMT\r\n\r\n{\"session_key\":\"XL+GLsPRGyvEHUMFyzfbZg==\",\"openid\":\"ogpTW5a9exdEmEwqZsYywvgSpSQg\"}"} diff --git a/tmp/build-errors.log b/tmp/build-errors.log new file mode 100644 index 00000000..0efc0f31 --- /dev/null +++ b/tmp/build-errors.log @@ -0,0 +1 @@ +exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1 \ No newline at end of file