diff --git a/pages_tool/card/detail.vue b/pages_tool/card/detail.vue index 0775e5d..bcf8887 100644 --- a/pages_tool/card/detail.vue +++ b/pages_tool/card/detail.vue @@ -531,11 +531,28 @@ export default { const txt = d.receiver_created === 0 ? '已交换(人脉已存在)' : '已交换,人脉已互加'; uni.showToast({ title: txt, icon: 'none' }); this.loadExchange(); - // 契约 §4(2026-10-15): 同意后用响应里的 wap_url 跳对方公开名片页, - // 仅追加 &back_url=(encodeURIComponent 我方名片页完整地址); wap_url 为空不跳转 - if (d.wap_url) { - this.jumpToOtherPublic(d.wap_url); - } + // 需求: 点「同意」后对方名片必须出现在我的人脉中。 + // 后端虽声明 agree 双向建人脉, 实测出现「同意成功、人脉里却没有对方」, + // 故不再用 receiver_created 判断, 一律在同意后校验/补建(幂等, 不会重复): + // 取对方名片详情 → 按手机号查我的人脉 → 没有才以 source=exchange 新建。 + // 兜底完成后再跳转: H5 跳转会中断进行中的请求, 先跳会导致兜底漏执行。 + this.ensureExchangeContact(item.from_card_id, ensureRes => { + // 命中同手机号人脉但姓名不同(多为对方改过名片名): 提示实际名称, + // 避免「交换后对方没出现」的误判(该联系人其实已在人脉里, 只是显示旧名) + if (ensureRes && ensureRes.existed && ensureRes.existed.name + && item.name && ensureRes.existed.name !== item.name) { + uni.showToast({ + title: '人脉中已有同手机号联系人「' + ensureRes.existed.name + '」', + icon: 'none', + duration: 2500 + }); + } + // 契约 §4(2026-10-15): 同意后用响应里的 wap_url 跳对方公开名片页, + // 仅追加 &back_url=(encodeURIComponent 我方名片页完整地址); wap_url 为空不跳转 + if (d.wap_url) { + this.jumpToOtherPublic(d.wap_url); + } + }); } else if (res.message) { // 请求已被处理/不存在/对方名片失效: 直接提示后端文案, 不二次弹「没有待处理请求」 uni.showToast({ title: res.message, icon: 'none' }); @@ -544,6 +561,27 @@ export default { fail: () => {} }); }, + /** + * 同意交换后校验并兜底建人脉: 保证对方名片出现在我的人脉中。 + * 走 card-api 的 ensureExchangeContact(取对方名片详情 → 按手机号去重 → 没有才 source=exchange 新建), 幂等。 + * 无论成败都执行 done(res) —— 兜底失败不阻塞同意后的跳转(交换本身已成功), 人脉页仍可手动补录。 + */ + ensureExchangeContact(fromCardId, done) { + if (!fromCardId) { typeof done === 'function' && done(null); return; } + this.$cardApi.ensureExchangeContact({ + fromCardId: fromCardId, + success: res => { + if (res && res.created) { + console.log('[card/detail] 兜底新建人脉成功:', fromCardId); + } + typeof done === 'function' && done(res); + }, + fail: err => { + console.warn('[card/detail] 兜底建人脉失败(不影响交换结果):', err); + typeof done === 'function' && done(null); + } + }); + }, closeShare() { this.showShare = false; }, diff --git a/pages_tool/card/exchange.vue b/pages_tool/card/exchange.vue index ee02ba3..ef98345 100644 --- a/pages_tool/card/exchange.vue +++ b/pages_tool/card/exchange.vue @@ -156,13 +156,29 @@ export default { const d = res.data || {}; const txt = d.receiver_created === 0 ? '已交换(人脉已存在)' : '已交换,人脉已互加'; uni.showToast({ title: txt, icon: 'none' }); - // 契约 §4(2026-10-15): 同意后用响应里的 wap_url 跳对方公开名片页, - // 仅追加 &back_url=; wap_url 为空则退回刷新列表(对方刚删卡等) - if (d.wap_url) { - this.jumpToOtherPublic(d.wap_url); - } else { - this.loadList(); - } + // 需求: 点「同意」后对方名片必须出现在我的人脉中。 + // 后端虽声明 agree 双向建人脉, 实测出现「同意成功、人脉里却没有对方」, + // 故不再用 receiver_created 判断, 一律在同意后校验/补建(幂等, 不会重复); + // 实现见 card/detail 页同名方法(取对方名片详情 → 按手机号查我的人脉 → 没有才新建)。 + this.ensureExchangeContact(item.from_card_id, ensureRes => { + // 命中同手机号人脉但姓名不同(多为对方改过名片名): 提示实际名称, + // 避免「交换后对方没出现」的误判(该联系人其实已在人脉里, 只是显示旧名) + if (ensureRes && ensureRes.existed && ensureRes.existed.name + && item.name && ensureRes.existed.name !== item.name) { + uni.showToast({ + title: '人脉中已有同手机号联系人「' + ensureRes.existed.name + '」', + icon: 'none', + duration: 2500 + }); + } + // 契约 §4(2026-10-15): 同意后用响应里的 wap_url 跳对方公开名片页, + // 仅追加 &back_url=; wap_url 为空则退回刷新列表(对方刚删卡等) + if (d.wap_url) { + this.jumpToOtherPublic(d.wap_url); + } else { + this.loadList(); + } + }); } else if (res.message) { uni.showToast({ title: res.message, icon: 'none' }); } @@ -170,6 +186,27 @@ export default { fail: () => {} }); }, + /** + * 同意交换后校验并兜底建人脉: 保证对方名片出现在我的人脉中。 + * 走 card-api 的 ensureExchangeContact(取对方名片详情 → 按手机号去重 → 没有才 source=exchange 新建), 幂等。 + * 无论成败都执行 done(res) —— 兜底失败不阻塞同意后的跳转(交换本身已成功), 人脉页仍可手动补录。 + */ + ensureExchangeContact(fromCardId, done) { + if (!fromCardId) { typeof done === 'function' && done(null); return; } + this.$cardApi.ensureExchangeContact({ + fromCardId: fromCardId, + success: res => { + if (res && res.created) { + console.log('[card/exchange] 兜底新建人脉成功:', fromCardId); + } + typeof done === 'function' && done(res); + }, + fail: err => { + console.warn('[card/exchange] 兜底建人脉失败(不影响交换结果):', err); + typeof done === 'function' && done(null); + } + }); + }, onIgnore(item) { this.$cardApi.exchangeIgnore({ data: { id: item.id },