d6b56d99ce
- 新增忘记密码页面,支持邮箱找回和手机找回两种方式,包含验证码倒计时 - 添加密码强度和一致性校验,确保新密码安全性 - 开启对应路由 /forget,恢复已注释的忘记密码入口 - 新增发送短信验证码和邮箱验证码接口,适配未登录场景 - 新增重置密码接口,支持手机短信码及邮箱验证码方式 - 请求拦截器支持 X-Tenant-Skip 头,跳过租户信息注入,避免跨租户串扰 - 国际化新增忘记密码相关英文和中文文案 - 页面样式与登录页视觉风格一致,跨屏幕响应式布局优化
114 lines
3.1 KiB
TypeScript
114 lines
3.1 KiB
TypeScript
/**
|
||
* axios 实例
|
||
*/
|
||
import axios from 'axios';
|
||
import type { AxiosResponse } from 'axios';
|
||
import { unref } from 'vue';
|
||
import router from '@/router';
|
||
import { Modal } from 'ant-design-vue';
|
||
import {API_BASE_URL, TOKEN_HEADER_NAME, LAYOUT_PATH, TENANT_ID} from '@/config/setting';
|
||
import { getToken, setToken } from './token-util';
|
||
import { logout } from './page-tab-util';
|
||
import type { ApiResult } from '@/api';
|
||
import { getHostname, getTenantId } from '@/utils/domain';
|
||
import { getMerchantId } from '@/utils/merchant';
|
||
|
||
// 获取API基础地址的函数
|
||
const getBaseUrl = (): string => {
|
||
// 尝试从配置store获取后台配置的API地址
|
||
try {
|
||
// 如果store中没有,则尝试从localStorage获取
|
||
const ApiUrl = localStorage.getItem('ApiUrl');
|
||
if (ApiUrl) {
|
||
return ApiUrl;
|
||
}
|
||
} catch (error) {
|
||
console.warn('获取后台配置API地址失败:', error);
|
||
}
|
||
|
||
// 如果后台没有配置API地址,则使用本地配置
|
||
console.log('使用本地配置的API地址:', API_BASE_URL);
|
||
return API_BASE_URL;
|
||
};
|
||
|
||
const service = axios.create({
|
||
baseURL: getBaseUrl()
|
||
});
|
||
|
||
/**
|
||
* 添加请求拦截器
|
||
*/
|
||
service.interceptors.request.use(
|
||
(config) => {
|
||
const token = getToken();
|
||
// 添加 token 到 header(Axios 1.x 直接设置 headers)
|
||
if (token && config.headers) {
|
||
config.headers[TOKEN_HEADER_NAME] = token;
|
||
}
|
||
// 获取租户ID
|
||
if (config.headers) {
|
||
// 登录前场景(找回密码等)由调用方显式设置 X-Tenant-Skip,
|
||
// 此时不做任何租户/企业/商户/域名头注入,避免串租户
|
||
if (config.headers['X-Tenant-Skip']) {
|
||
return config;
|
||
}
|
||
// 附加企业ID
|
||
const companyId = localStorage.getItem('CompanyId');
|
||
if (companyId) {
|
||
config.headers['CompanyId'] = companyId;
|
||
}
|
||
// 附加商户ID
|
||
if (getMerchantId()) {
|
||
config.headers['MerchantId'] = getMerchantId();
|
||
}
|
||
// 通过网站域名获取租户ID
|
||
if (getHostname()) {
|
||
config.headers['Domain'] = getHostname();
|
||
}
|
||
// 解析二级域名获取租户ID(确保始终设置TenantId)
|
||
config.headers['TenantId'] = getTenantId() || TENANT_ID;
|
||
}
|
||
return config;
|
||
},
|
||
(error) => {
|
||
return Promise.reject(error);
|
||
}
|
||
);
|
||
|
||
/**
|
||
* 添加响应拦截器
|
||
*/
|
||
service.interceptors.response.use(
|
||
(res: AxiosResponse<ApiResult<unknown>>) => {
|
||
// 登录过期处理
|
||
if (res.data?.code === 401) {
|
||
const currentPath = unref(router.currentRoute).path;
|
||
if (currentPath == LAYOUT_PATH) {
|
||
logout(true);
|
||
} else {
|
||
Modal.destroyAll();
|
||
Modal.info({
|
||
title: '系统提示',
|
||
content: '登录状态已过期, 请退出重新登录!',
|
||
okText: '重新登录',
|
||
onOk: () => {
|
||
logout(false, currentPath);
|
||
}
|
||
});
|
||
}
|
||
return Promise.reject(new Error(res.data.message));
|
||
}
|
||
// token 自动续期
|
||
const token = res.headers[TOKEN_HEADER_NAME.toLowerCase()];
|
||
if (token) {
|
||
setToken(token);
|
||
}
|
||
return res;
|
||
},
|
||
(error) => {
|
||
return Promise.reject(error);
|
||
}
|
||
);
|
||
|
||
export default service;
|