Files
wechat-clock-mini/utils/auth.js
王宏豪 ba2d9245ef feat(api): 重构图片地址管理与上传机制
- 替换开发环境API基础URL为本地服务地址
- 实现签名URL本地缓存机制,解决微信按URL缓存图片导致重复下载问题
- 添加缓存清理功能,包括过期清理和按需删除特定缓存项
- 集成阿里云OSS上传功能,支持直传减少服务器带宽占用
- 优化头像地址处理逻辑,统一使用签名缓存避免地址频繁变化
- 移除过时的OSS上传示例文件oss-upload.js
- 更新课程页面实现跳转第三方小程序功能
- 调整打卡记录图片地址获取方式,统一使用新的签名缓存逻辑
- 优化图片上传流程,增加压缩处理和批量上传支持
- 完善认证模块中的缓存清理逻辑,切换账号时清除相关图片缓存
- 添加后端环境变量配置模板和代理文档说明
2026-09-23 17:46:40 +08:00

111 lines
3.2 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
const api = require('./api');
let loginPromise = null;
function getToken() {
return wx.getStorageSync('token') || '';
}
function setToken(token) {
wx.setStorageSync('token', token);
}
function clearToken() {
wx.removeStorageSync('token');
// 顺带清掉签名 URL 缓存:换账号后不该复用上一个人的图片地址
api.clearSignedCache();
}
function wxLogin(retries) {
const remain = typeof retries === 'number' ? retries : 3;
return new Promise((resolve, reject) => {
wx.login({
success(res) {
if (res && res.code) {
resolve(res.code);
} else {
reject(new Error((res && res.errMsg) || '登录失败'));
}
},
fail: reject
});
}).catch((err) => {
// 冷启动时微信登录服务可能尚未就绪,指数退避重试
if (remain > 0) {
const delay = 400 + (4 - remain) * 200; // 首次 600ms,依次 800ms、1000ms
return new Promise((resolve) => setTimeout(resolve, delay))
.then(() => wxLogin(remain - 1));
}
throw err;
});
}
// 整个微信登录流程失败时重新取 code 再试一次,覆盖冷启动首个网络请求偶发失败
function wechatLogin(retries) {
const remain = typeof retries === 'number' ? retries : 1;
return wxLogin()
.then((code) => api.request({
url: '/api/v1/auth/wechat-login',
method: 'POST',
data: { code },
auth: false
}))
.catch((err) => {
if (remain > 0) {
return new Promise((resolve) => setTimeout(resolve, 500)).then(() => wechatLogin(remain - 1));
}
throw err;
});
}
// 单例登录:App.onLaunch 与首屏页面 onShow 可能几乎同时调用,
// 共享同一个进行中的登录 Promise,避免重复 wx.login / wechat-login 造成竞态。
// 关键:登录失败时必须清空单例,让下一次调用能重新发起,
// 否则冷启动 wx.login 偶发失败后,后续页面永远拿不到 token。
function ensureLogin(refresh) {
const existing = getToken();
if (existing && !refresh) {
return Promise.resolve(existing);
}
if (loginPromise) {
return loginPromise;
}
const p = wechatLogin()
.then((res) => {
if (res && res.success) {
setToken(res.token);
return res.token;
}
// need_phone:未绑定手机号时 resolve(null),由页面引导去「我的」绑定
return null;
})
.finally(() => {
// 无论成功失败,完成后都清掉单例,让下一次调用可以重新发起
if (loginPromise === p) {
loginPromise = null;
}
});
loginPromise = p;
return p;
}
function loginWithPhone(phoneCode) {
return wxLogin()
.then((code) => api.request({
url: '/api/v1/auth/bind-phone',
method: 'POST',
data: { code, phone_code: phoneCode },
auth: false
}))
.then((res) => {
if (res && res.success) {
setToken(res.token);
return res;
}
const error = new Error((res && res.error) || '手机号登录失败');
error.error = (res && res.error) || '手机号登录失败';
throw error;
});
}
module.exports = { getToken, setToken, clearToken, wxLogin, ensureLogin, loginWithPhone };