- miniprogram/config.js: BASE_URL 指向 http://192.227.237.8:3001 - 动作标题中文化(nameZh),搜索匹配 name/nameZh/nameEn - 新增计划/收藏/我的 等页面与组件 - 后端 Docker 化(Dockerfile/.dockerignore)与翻译脚本 - .gitignore 补充 .DS_Store
116 lines
3.3 KiB
JavaScript
116 lines
3.3 KiB
JavaScript
// 登录与用户态管理:封装 wx.login + 后端 /api/auth/login。
|
||
// 后端在首次登录时自动创建用户;开发模式(未配置 WX_APPID)接受任意 code
|
||
// 并返回稳定的虚拟 openid。
|
||
const { request, setUnauthorizedHandler } = require('./request');
|
||
|
||
const TOKEN_KEY = 'access_token';
|
||
const OPENID_KEY = 'openid';
|
||
const PROFILE_KEY = 'user_profile';
|
||
|
||
// 模块加载时注册 401 自动重新登录:成功后返回新的 token,失败返回 null。
|
||
setUnauthorizedHandler(async () => {
|
||
try {
|
||
await login();
|
||
return wx.getStorageSync(TOKEN_KEY);
|
||
} catch (e) {
|
||
return null;
|
||
}
|
||
});
|
||
|
||
function login() {
|
||
return new Promise((resolve, reject) => {
|
||
wx.login({
|
||
success(res) {
|
||
const code = res.code || 'tourist';
|
||
request({ url: '/api/auth/login', method: 'POST', data: { code } })
|
||
.then((r) => {
|
||
const token = r.token;
|
||
const user = r.user || {};
|
||
wx.setStorageSync(TOKEN_KEY, token);
|
||
if (user.openid) wx.setStorageSync(OPENID_KEY, user.openid);
|
||
const profile = { nickname: user.nickname || '', avatar: user.avatar || '' };
|
||
wx.setStorageSync(PROFILE_KEY, profile);
|
||
resolve(profile);
|
||
})
|
||
.catch((err) => {
|
||
wx.showToast({ title: '登录失败,请重试', icon: 'none' });
|
||
reject(err);
|
||
});
|
||
},
|
||
fail() {
|
||
// 拿不到 code 时降级为游客 code
|
||
request({ url: '/api/auth/login', method: 'POST', data: { code: 'tourist' } })
|
||
.then((r) => {
|
||
const token = r.token;
|
||
const user = r.user || {};
|
||
wx.setStorageSync(TOKEN_KEY, token);
|
||
if (user.openid) wx.setStorageSync(OPENID_KEY, user.openid);
|
||
const profile = { nickname: user.nickname || '', avatar: user.avatar || '' };
|
||
wx.setStorageSync(PROFILE_KEY, profile);
|
||
resolve(profile);
|
||
})
|
||
.catch((err) => {
|
||
wx.showToast({ title: '登录失败,请重试', icon: 'none' });
|
||
reject(err);
|
||
});
|
||
}
|
||
});
|
||
});
|
||
}
|
||
|
||
// 确保已登录:有 token 直接返回,否则执行登录。
|
||
async function ensureLogin() {
|
||
const token = getToken();
|
||
if (token) return token;
|
||
await login();
|
||
return getToken();
|
||
}
|
||
|
||
function getToken() {
|
||
return wx.getStorageSync(TOKEN_KEY) || '';
|
||
}
|
||
|
||
function getProfile() {
|
||
return wx.getStorageSync(PROFILE_KEY) || { nickname: '', avatar: '' };
|
||
}
|
||
|
||
function isLogin() {
|
||
return !!getToken();
|
||
}
|
||
|
||
function logout() {
|
||
wx.removeStorageSync(TOKEN_KEY);
|
||
wx.removeStorageSync(OPENID_KEY);
|
||
wx.removeStorageSync(PROFILE_KEY);
|
||
}
|
||
|
||
function setProfile(p) {
|
||
const profile = Object.assign({}, getProfile(), p || {});
|
||
wx.setStorageSync(PROFILE_KEY, profile);
|
||
return profile;
|
||
}
|
||
|
||
// 更新昵称 / 头像,写回后端并刷新本地状态。
|
||
function updateProfile(dto) {
|
||
return request({ url: '/api/users/me', method: 'PATCH', data: dto })
|
||
.then((user) => {
|
||
const profile = {
|
||
nickname: (user && user.nickname) || getProfile().nickname,
|
||
avatar: (user && user.avatar) || getProfile().avatar
|
||
};
|
||
wx.setStorageSync(PROFILE_KEY, profile);
|
||
return profile;
|
||
});
|
||
}
|
||
|
||
module.exports = {
|
||
login,
|
||
ensureLogin,
|
||
getToken,
|
||
getProfile,
|
||
isLogin,
|
||
logout,
|
||
setProfile,
|
||
updateProfile
|
||
};
|