From abb1fe7c5e97e8dceca34456f53ee05ee32e9915 Mon Sep 17 00:00:00 2001 From: jeremygan2021 Date: Thu, 12 Feb 2026 17:32:22 +0800 Subject: [PATCH] forum --- .../shop/__pycache__/views.cpython-312.pyc | Bin 65593 -> 67223 bytes backend/shop/views.py | 101 ++++++++++++------ miniprogram/src/pages/user/index.tsx | 85 ++++++++++++++- 3 files changed, 152 insertions(+), 34 deletions(-) diff --git a/backend/shop/__pycache__/views.cpython-312.pyc b/backend/shop/__pycache__/views.cpython-312.pyc index 477e8b80d7934bb9ffe46fc7a1ef1b02863747e5..c2c010c766f4d885b3dddcde180994ab14ffe2c7 100644 GIT binary patch delta 11968 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 delta 11071 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 将手机号用户(Web)合并到小程序用户 + # 注意: 如果 phone_user 也是真实的 MP 用户(有 openid 且不是 web_), 则可能冲突,这里默认保留当前登录的 mp_user + + # 1. 迁移订单 + Order.objects.filter(wechat_user=phone_user).update(wechat_user=mp_user) + # 2. 迁移社区数据 (延迟导入避免循环引用) + from community.models import ActivitySignup, Topic, Reply + ActivitySignup.objects.filter(user=phone_user).update(user=mp_user) + Topic.objects.filter(author=phone_user).update(author=mp_user) + Reply.objects.filter(author=phone_user).update(author=mp_user) + # 3. 迁移分销员 + if hasattr(phone_user, 'distributor') and not hasattr(mp_user, 'distributor'): + dist = phone_user.distributor + dist.user = mp_user + dist.save() + + # 删除旧用户 + phone_user.delete() + user = mp_user + + # 更新手机号 + if not user.phone_number: + user.phone_number = phone_number + else: + # 同一个用户 + user = mp_user + + elif phone_user: + # 【绑定场景】: 只有手机号用户存在 (通常是 Web 用户) -> 升级为小程序用户 + user = phone_user + # 只有当它是 Web 虚拟用户时,才覆盖 OpenID + # 或者如果它就是目标用户,直接更新 + if user.openid.startswith('web_') or not user.openid: + user.openid = openid + elif user.openid != openid: + # 冲突: 手机号已被另一个真实 OpenID 绑定,但当前登录的是新的 OpenID + # 策略: 创建新用户,不合并 (避免安全风险) + user = WeChatUser.objects.create(openid=openid) + + elif mp_user: + # 【更新场景】: 只有小程序用户存在 -> 更新手机号 + user = mp_user + if phone_number: + user.phone_number = phone_number + + else: + # 【新建场景】: 都不存在 -> 创建新用户 + user = WeChatUser.objects.create(openid=openid) + if phone_number: + user.phone_number = phone_number + + # 统一更新会话信息 user.session_key = session_key user.unionid = unionid user.save() - created = False + created = False # 简化处理 + + except Exception as e: + import traceback + traceback.print_exc() + return Response({'error': f'Login failed: {str(e)}'}, status=500) # 生成 Token signer = TimestampSigner() diff --git a/miniprogram/src/pages/user/index.tsx b/miniprogram/src/pages/user/index.tsx index 76c3ebe..ee9d18c 100644 --- a/miniprogram/src/pages/user/index.tsx +++ b/miniprogram/src/pages/user/index.tsx @@ -20,8 +20,70 @@ export default function UserIndex() { try { await Taro.chooseAddress() } catch(e) {} } - const login = () => { - Taro.reLaunch({ url: '/pages/index/index' }) + const login = async () => { + try { + // 1. 获取微信登录 Code + const { code } = await Taro.login() + if (!code) throw new Error('登录失败:无法获取 Code') + + // 2. 调用后端登录 (仅 Code) + const res = await Taro.request({ + url: 'https://market.quant-speed.com/api/wechat/login/', + method: 'POST', + data: { code } + }) + + console.log('code:', code) + + if (res.statusCode === 200 && res.data.token) { + Taro.setStorageSync('token', res.data.token) + Taro.setStorageSync('userInfo', res.data) + setUserInfo(res.data) + Taro.showToast({ title: '登录成功', icon: 'success' }) + } else { + throw new Error(res.data.error || '登录请求失败') + } + } catch (e) { + Taro.showToast({ title: e.message || '登录失败', icon: 'none' }) + } + } + + const getPhoneNumber = async (e) => { + const { code: phoneCode, errMsg } = e.detail + if (errMsg !== "getPhoneNumber:ok") { + Taro.showToast({ title: '获取手机号失败', icon: 'none' }) + return + } + + try { + Taro.showLoading({ title: '登录中...' }) + // 1. 获取登录 Code + const { code: loginCode } = await Taro.login() + + // 2. 调用后端登录 (Code + PhoneCode) + const res = await Taro.request({ + url: 'https://market.quant-speed.com/api/wechat/login/', + method: 'POST', + data: { + code: loginCode, + phone_code: phoneCode + } + }) + + Taro.hideLoading() + + if (res.statusCode === 200 && res.data.token) { + Taro.setStorageSync('token', res.data.token) + Taro.setStorageSync('userInfo', res.data) + setUserInfo(res.data) + Taro.showToast({ title: '授权登录成功', icon: 'success' }) + } else { + throw new Error(res.data.error || '登录失败') + } + } catch(err) { + Taro.hideLoading() + Taro.showToast({ title: err.message || '系统异常', icon: 'none' }) + } } const serviceGroups = [ @@ -65,9 +127,24 @@ export default function UserIndex() { {userInfo?.nickname || '未登录用户'} - ID: {userInfo ? '888888' : '----'} + ID: {userInfo ? (userInfo.phone_number || userInfo.id || '----') : '----'} {!userInfo && ( - + + + + )}