修改功能,现已测试注册登录忘记密码

This commit is contained in:
rain
2026-06-12 11:42:49 +08:00
parent 0bf2f573ed
commit cfc64c69e5
26 changed files with 2238 additions and 898 deletions
+156 -8
View File
@@ -13,6 +13,7 @@ const ApiClient = {
authVerifyConfig: '/api/web/auth/verify-config',
authSlideCaptcha: '/api/web/auth/slide-captcha',
authSlideCaptchaVerify: '/api/web/auth/slide-captcha/verify',
authHeartbeat: '/api/web/auth/heartbeat',
authForgotPasswordSmsCode: '/api/web/auth/forgot-password/sms-code',
authForgotPasswordReset: '/api/web/auth/forgot-password/reset',
authSocialLogin: '/api/web/auth/social-login',
@@ -20,7 +21,23 @@ const ApiClient = {
authSocialBind: '/api/web/auth/social-bind',
authSocialBindPhone: '/api/web/auth/social-bind-phone',
authSocialBindPhoneSmsCode: '/api/web/auth/social-bind-phone/sms-code',
appDownloadInfo: '/api/web/app/getDownloadInfo',
agreement: (type) => `/api/web/agreement/${encodeURIComponent(type || '')}`,
noticeList: '/api/web/notice/list',
noticeDetail: (id) => `/api/web/notice/${encodeURIComponent(id || '')}`,
friendLinks: '/api/web/link/friend',
otherRecommendLinks: '/api/web/link/other',
latestLotteryResult: '/api/web/lottery/result/latest',
lotteryResultList: '/api/web/lottery/result/list',
webConfigList: '/api/web/config/list',
webConfig: '/api/web/config',
configList: '/api/web/config/list',
configSite: '/api/web/config/site',
bannerList: '/api/web/banner/list',
adList: '/api/web/ad/list',
freeArticleRecommend: '/api/web/free-article/recommend',
freeArticleList: '/api/web/free-article/list',
freeArticleLatest: '/api/web/free-article/latest',
referralShareInfo: '/api/web/referral/share-info',
referralSummary: '/api/web/referral/summary',
referralInviteList: '/api/web/referral/invite-list',
@@ -38,8 +55,11 @@ const ApiClient = {
menuChildren: (id) => `/api/web/menu/${encodeURIComponent(id)}/children`,
payArticleExpertProfile: '/api/web/pay-article/expert-profile',
payArticleExpertList: '/api/web/pay-article/expert-list',
payArticleExpertRank: '/api/web/pay-article/expert-rank',
payArticlePublishOptions: (menuId) => `/api/web/pay-article/publish/options?menuId=${encodeURIComponent(menuId || '')}`,
payArticlePublish: '/api/web/pay-article/publish',
payArticleLatest: '/api/web/pay-article/latest',
payArticleRelated: (id) => `/api/web/pay-article/${encodeURIComponent(id || '')}/related`,
payArticleCollect: (id) => `/api/web/pay-article/article-collect/${encodeURIComponent(id)}`,
expertCollect: (expertId, accountType = 1) =>
`/api/web/pay-article/expert-collect?${new URLSearchParams({
@@ -50,6 +70,7 @@ const ApiClient = {
walletFlowList: '/api/web/wallet/flow/list',
walletRechargeConfigList: '/api/web/wallet/recharge/config/list',
walletRechargeOrder: '/api/web/wallet/recharge/order',
walletRechargeOrderStatus: (outTradeNo) => `/api/web/wallet/recharge/order/status/${encodeURIComponent(outTradeNo || '')}`,
walletRechargeNotify: '/api/web/wallet/recharge/notify',
walletTransferToAccount: '/api/web/wallet/transfer-to-account',
walletWithdraw: '/api/web/wallet/withdraw',
@@ -62,10 +83,16 @@ const ApiClient = {
walletReceiveAccountDelete: (id) => `/api/web/wallet/receive-account/${encodeURIComponent(id)}`,
walletReceiveAccountUploadQrcode: '/api/web/wallet/receive-account/upload-qrcode',
mineSummary: '/api/web/mine/summary',
mineFreeCollectList: '/api/web/mine/free-collect/list',
minePayCollectList: '/api/web/mine/pay-collect/list',
mineExpertCollectList: '/api/web/mine/expert-collect/list',
mineSignInList: '/api/web/mine/sign-in/list',
mineSignInStatus: '/api/web/mine/sign-in/status',
mineSignIn: '/api/web/mine/sign-in',
walletPurchasePayArticle: '/api/web/wallet/purchase/pay-article',
freeArticlePublish: '/api/web/free-article/publish',
mineFreeArticleList: '/api/web/mine/free-article/list',
mineFreeArticleDetail: (id) => `/api/web/mine/free-article/${encodeURIComponent(id || '')}`,
minePayArticleList: '/api/web/mine/pay-article/list',
minePayArticleDetail: (id) => `/api/web/mine/pay-article/${encodeURIComponent(id)}`,
minePurchasedPayArticleList: '/api/web/mine/purchased-pay-article/list',
@@ -81,6 +108,8 @@ const ApiClient = {
fc3dSchemeList: '/api/web/fc3d/scheme/list',
fc3dSchemeDetail: (id) => `/api/web/fc3d/scheme/${encodeURIComponent(id)}`,
walletPurchaseFc3dScheme: '/api/web/wallet/purchase/fc3d-scheme',
lotteryTrendTools: '/api/web/lottery/trend/tools',
lotteryTrend: '/api/web/lottery/trend',
},
get baseUrl() {
@@ -146,7 +175,9 @@ const ApiClient = {
}
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
return this.normalizeResponse(await this.parseResponse(response), normalized);
const result = this.normalizeResponse(await this.parseResponse(response), normalized);
if (this.isAuthExpiredResponse(result)) this.handleAuthExpired();
return result;
})
.catch((error) => {
clearTimeout(timeoutId);
@@ -225,6 +256,19 @@ const ApiClient = {
return !!res && (res.code === 0 || res.code === 200 || res.success === true);
},
isAuthExpiredResponse(result) {
if (!result || typeof result !== 'object') return false;
const code = Number(result.code);
const message = String(result.msg || result.message || result.error || '').toLowerCase();
return (
code === 401 ||
code === 403 ||
code === 40101 ||
code === 40102 ||
message.indexOf('token') >= 0 && (message.indexOf('expired') >= 0 || message.indexOf('invalid') >= 0)
);
},
getToken() {
const raw = localStorage.getItem('token');
if (!raw) return '';
@@ -240,19 +284,76 @@ const ApiClient = {
return this.getToken();
},
clearToken() {
localStorage.removeItem('token');
localStorage.removeItem('userInfo');
localStorage.removeItem('user');
},
getLocalUserInfo() {
const raw = localStorage.getItem('userInfo') || localStorage.getItem('user') || '';
if (!raw) return {};
try {
return JSON.parse(raw) || {};
} catch (e) {
return {};
}
},
isJwtExpired(token) {
const parts = String(token || '').split('.');
if (parts.length < 2) return false;
try {
let payloadText = parts[1].replace(/-/g, '+').replace(/_/g, '/');
while (payloadText.length % 4) payloadText += '=';
const payload = JSON.parse(decodeURIComponent(escape(window.atob(payloadText))));
return payload.exp ? payload.exp * 1000 <= Date.now() : false;
} catch (e) {
return false;
}
},
isTokenExpired() {
const token = this.token();
if (!token) return true;
if (this.isJwtExpired(token)) return true;
const userInfo = this.getLocalUserInfo();
const expireTime = Number(userInfo.expireTime || userInfo.expire_time || userInfo.expiresAt || userInfo.expires_at || 0);
return expireTime ? expireTime <= Date.now() : false;
},
handleAuthExpired() {
if (typeof window === 'undefined') return;
this.clearToken();
const path = window.location.pathname || '';
if (/\/(login|reg|repwd)\.html$/i.test(path)) return;
const returnUrl = window.location.pathname + window.location.search;
const loginPath = '/login.html?redirect=' + encodeURIComponent(returnUrl);
window.location.href =
typeof CommonUtil !== 'undefined' && CommonUtil.siteHref
? CommonUtil.siteHref(loginPath)
: ((window.CURRENT_ENV === 'development' ? '/html/login.html?redirect=' : '/login.html?redirect=') + encodeURIComponent(returnUrl));
},
buildUrl(url, params) {
if (!params || params instanceof FormData) return url;
const clean = {};
Object.keys(params).forEach((key) => {
if (params[key] !== undefined && params[key] !== null && params[key] !== '') {
clean[key] = params[key];
}
});
const clean = this.cleanParams(params);
const query = new URLSearchParams(clean).toString();
if (!query) return url;
return url + (url.indexOf('?') >= 0 ? '&' : '?') + query;
},
cleanParams(params, omittedKeys = []) {
const clean = {};
const omitted = new Set(omittedKeys || []);
Object.keys(params || {}).forEach((key) => {
const value = params[key];
if (omitted.has(key)) return;
if (value !== undefined && value !== null && value !== '') clean[key] = value;
});
return clean;
},
async parseResponse(response) {
const contentType = response.headers.get('content-type') || '';
if (contentType.indexOf('application/json') >= 0) return response.json();
@@ -380,6 +481,21 @@ const ApiClient = {
if (Array.isArray(value.records)) return value.records;
if (Array.isArray(value.rows)) return value.rows;
if (Array.isArray(value.list)) return value.list;
if (Array.isArray(value.data)) return value.data;
return [];
},
unwrap(result, fallback) {
return this.pickData(result, fallback);
},
listFrom(source, keys = ['records', 'rows', 'list', 'data']) {
if (Array.isArray(source)) return source;
if (!source || typeof source !== 'object') return [];
for (const key of keys || []) {
const nested = this.asArray(source[key]);
if (nested.length) return nested;
}
return [];
},
@@ -416,7 +532,7 @@ const ApiClient = {
};
}
if (url === '/api/web/lotteryResult/getList') {
return { compose: () => this.requestWithMenu('/api/web/lottery/result/list', data) };
return { compose: () => this.requestLegacyLotteryResultCompat(data) };
}
if (url === '/api/web/freeArticle/getPageList') {
return { compose: () => this.requestWithMenu('/api/web/free-article/list', data) };
@@ -646,6 +762,26 @@ const ApiClient = {
return this.get(url, params);
},
async requestLegacyLotteryResultCompat(data = {}) {
const params = this.normalizePageParams(data || {});
const code = params.code || params.suoxie || params.lotteryCode || '';
const pageSize = params.pageSize || params.limit || params.count || 100;
if (code && this.API.lotteryTrend) {
try {
const trendRes = await this.get(this.API.lotteryTrend, {
code,
pageSize,
});
if (this.isSuccess(trendRes) && this.asArray(this.pickData(trendRes, [])).length) {
return trendRes;
}
} catch (e) {
// Fall back to the older result-list endpoint below.
}
}
return this.requestWithMenu('/api/web/lottery/result/list', data);
},
async loadLegacyExpertDetailCompat(data = {}) {
const cacheKey = JSON.stringify(this.normalizePageParams(data));
if (!this._legacyExpertDetailPromises) this._legacyExpertDetailPromises = {};
@@ -847,18 +983,30 @@ const ApiClient = {
},
get(url, params, options = {}) {
if (typeof options === 'function') {
return this.request({ url, method: 'GET', data: params || null }).then(options);
}
return this.request({ url, method: 'GET', data: params || null, ...options });
},
post(url, data, options = {}) {
if (typeof options === 'function') {
return this.request({ url, method: 'POST', data: data || null }).then(options);
}
return this.request({ url, method: 'POST', data: data || null, ...options });
},
put(url, data, options = {}) {
if (typeof options === 'function') {
return this.request({ url, method: 'PUT', data: data || null }).then(options);
}
return this.request({ url, method: 'PUT', data: data || null, ...options });
},
delete(url, data, options = {}) {
if (typeof options === 'function') {
return this.request({ url, method: 'DELETE', data: data || null }).then(options);
}
return this.request({ url, method: 'DELETE', data: data || null, ...options });
},
};