feat(miniprogram): 登录/资料改走平台 /auth(统一账号 + 平台 JWT)
阶段2: - sendCode/phoneLogin/wxLogin/getMe/updateProfile 端点 /api/auth/*→/auth/*, pine_token 存平台 JWT;按平台 profile 契约映射 pine_user (username/name/avatar/phone/phoneBound/status/topics/source)。 - sendCode 兼容平台 stub_code→debugCode。 - bindPhone/wxPhoneBind 保留 /api/auth(阶段3 已使其读写平台 users + 验平台 JWT)。 - 手机绑定、业务(报名/签到/测评)使用平台 JWT 鉴权。 Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -1,23 +1,38 @@
|
||||
import Taro from '@tarojs/taro';
|
||||
import { request } from './api';
|
||||
|
||||
/* 用户端认证:手机号 + 短信验证码(与 web 端一致,见 小程序同步约束.md) */
|
||||
/* 用户端认证(统一账号):登录/资料走平台 /auth(单一 users + 平台 JWT);
|
||||
手机绑定走培训 /api/auth(阶段3 后同样读写平台 users + 验平台 JWT)。
|
||||
与 web 端一致,见 小程序同步约束.md */
|
||||
|
||||
/** pine_user 契约字段(各页面读取):username/name/avatar/phone/phoneBound/status/topics/source */
|
||||
function pickUser(d) {
|
||||
return {
|
||||
username: d.username,
|
||||
name: d.name || d.nickname || d.username || '微信用户',
|
||||
avatar: d.avatar || '',
|
||||
phone: d.phone || '',
|
||||
phoneBound: !!d.phoneBound,
|
||||
status: d.status || '',
|
||||
topics: Array.isArray(d.topics) ? d.topics : [],
|
||||
source: d.source || ''
|
||||
};
|
||||
}
|
||||
|
||||
function saveUser(d) {
|
||||
Taro.setStorageSync('pine_user', pickUser(d));
|
||||
}
|
||||
|
||||
export async function sendCode(phone) {
|
||||
return request('POST', '/api/auth/send-code', { phone });
|
||||
const data = await request('POST', '/auth/send-code', { phone });
|
||||
return { ...data, debugCode: data.stub_code ?? data.debugCode };
|
||||
}
|
||||
|
||||
export async function phoneLogin(phone, code) {
|
||||
const data = await request('POST', '/api/auth/phone-login', { phone, code });
|
||||
const data = await request('POST', '/auth/phone-login', { phone, code });
|
||||
if (data.token) {
|
||||
Taro.setStorageSync('pine_token', data.token);
|
||||
// 手机号登录账号即以手机号为账号,天然已绑定手机号(phoneBound=true),保持一致避免再次提示绑定
|
||||
Taro.setStorageSync('pine_user', {
|
||||
username: data.username,
|
||||
name: data.name || data.username,
|
||||
avatar: '',
|
||||
phone: data.username,
|
||||
phoneBound: true
|
||||
});
|
||||
saveUser(data);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
@@ -35,23 +50,42 @@ export function logout() {
|
||||
Taro.removeStorageSync('pine_user');
|
||||
}
|
||||
|
||||
/* ---------------- 微信登录 / 手机绑定 / 我的资料 ---------------- */
|
||||
/** 微信一键登录:wx.login 拿 code(演示后端用 code 哈希做伪 openid),可携带昵称/头像 */
|
||||
/* ---------------- 微信登录 / 我的资料(平台 /auth) ---------------- */
|
||||
/** 微信一键登录:wx.login 拿 code → 平台 /auth/wx-login(需后端配 PINEAGENTS_WECHAT_LOGIN=true) */
|
||||
export async function wxLogin({ code, nickName, avatarUrl }) {
|
||||
const data = await request('POST', '/api/auth/wx-login', { code, nickName, avatarUrl });
|
||||
const data = await request('POST', '/auth/wx-login', { code, nickName, avatarUrl });
|
||||
if (data.token) {
|
||||
Taro.setStorageSync('pine_token', data.token);
|
||||
Taro.setStorageSync('pine_user', {
|
||||
username: data.username,
|
||||
name: data.name || '微信用户',
|
||||
avatar: data.avatar || '',
|
||||
phone: '',
|
||||
phoneBound: !!data.phoneBound
|
||||
});
|
||||
saveUser(data);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
/** 拉取当前账号资料(刷新昵称/头像/手机绑定状态)——平台 /auth/me 返回扁平 profile */
|
||||
export async function getMe() {
|
||||
const data = await request('GET', '/auth/me', {}, true);
|
||||
if (data && data.username) {
|
||||
const u = getUser() || {};
|
||||
const picked = pickUser(data);
|
||||
Taro.setStorageSync('pine_user', { ...u, ...picked });
|
||||
return { ok: true, user: picked };
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
/** 更新当前用户资料(昵称/头像 + 报名资料 status/topics/source)——平台 /auth/update-profile */
|
||||
export async function updateProfile(body) {
|
||||
const data = await request('POST', '/auth/update-profile', body, true);
|
||||
if (data && data.username) {
|
||||
const u = getUser() || {};
|
||||
const picked = pickUser(data);
|
||||
Taro.setStorageSync('pine_user', { ...u, ...picked });
|
||||
return { ok: true, user: picked };
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
/* ---------------- 手机绑定(培训 /api/auth,阶段3 读写平台 users + 验平台 JWT) ---------------- */
|
||||
/** 绑定手机:验证码校验后把手机号挂到当前账号 */
|
||||
export async function bindPhone(phone, code) {
|
||||
const data = await request('POST', '/api/auth/bind-phone', { phone, code }, true);
|
||||
@@ -62,16 +96,6 @@ export async function bindPhone(phone, code) {
|
||||
return data;
|
||||
}
|
||||
|
||||
/** 拉取当前账号资料(刷新昵称/头像/手机绑定状态) */
|
||||
export async function getMe() {
|
||||
const data = await request('GET', '/api/auth/me', {}, true);
|
||||
if (data.ok && data.user) {
|
||||
const u = getUser() || {};
|
||||
Taro.setStorageSync('pine_user', { ...u, ...data.user });
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
/** 微信官方手机号一键绑定(getPhoneNumber 回调 code) */
|
||||
export async function wxPhoneBind(code) {
|
||||
const data = await request('POST', '/api/auth/wx-phone', { code }, true);
|
||||
@@ -81,14 +105,3 @@ export async function wxPhoneBind(code) {
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
/** 更新当前用户资料(昵称/头像 + 报名资料 status/topics/source) */
|
||||
export async function updateProfile(data) {
|
||||
const r = await request('POST', '/api/auth/update-profile', data, true);
|
||||
if (r.ok && r.user) {
|
||||
const u = getUser() || {};
|
||||
// 用后端返回的完整 user(含 nickname/avatar/phone/phoneBound/status/topics/source)覆盖内存资料
|
||||
Taro.setStorageSync('pine_user', { ...u, ...r.user });
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user