新增资产服务订阅功能,在应用中集成模块未开通弹窗组件,当检测到402状态码时自动弹出订阅对话框引导用户开通服务,同时新增资产订阅相关API接口包括获取资产SKU信息和订阅服务接口,在请求拦截器中添加402状态码处理逻辑并过滤SKU查询接口避免循环触发

This commit is contained in:
WUSIJIAN
2026-01-20 17:54:29 +08:00
parent c743feee6e
commit aec7f3a017
5 changed files with 420 additions and 3 deletions

View File

@@ -0,0 +1,83 @@
import { ref } from 'vue';
// 路由路径与 assetId 的映射关系
const ROUTE_ASSET_MAP: Record<string, { assetId: string; serviceName: string }> = {
// CID广告业务(聚合广告)
'/cidService': { assetId: '696f423705e496ba4ccbe665', serviceName: '聚合广告' },
// AI客服业务
'/customerService': { assetId: '696f421205e496ba4ccbe662', serviceName: 'AI客服' },
// 聚合电商业务(资产管理)
'/assets': { assetId: '696b4acd1be1c8b76c4b4c15', serviceName: '资产管理' },
// 订单
// '/order': { assetId: '696b4acd1be1c8b76c4b4c15', serviceName: '资产管理' },
// AI数字人
// '/digitalHuman': { assetId: '696f421205e496ba4ccbe662', serviceName: 'AI客服' },
};
// 当前弹窗状态(响应式,供组件使用)
export const assetSubscribeState = ref({
visible: false,
assetId: '',
serviceName: '',
});
/**
* 根据路由路径获取对应的 assetId 和服务名称
*/
export function getAssetInfoByRoute(routePath: string): { assetId: string; serviceName: string } | null {
// 精确匹配
if (ROUTE_ASSET_MAP[routePath]) {
return ROUTE_ASSET_MAP[routePath];
}
// 前缀匹配
for (const [prefix, info] of Object.entries(ROUTE_ASSET_MAP)) {
if (routePath.startsWith(prefix)) {
return info;
}
}
return null;
}
/**
* 显示服务开通弹窗
*/
export function showAssetSubscribeDialog(assetId: string, serviceName: string) {
console.log('[showAssetSubscribeDialog] 显示弹窗:', { assetId, serviceName });
console.log('[showAssetSubscribeDialog] 修改前状态:', JSON.stringify(assetSubscribeState.value));
assetSubscribeState.value.visible = true;
assetSubscribeState.value.assetId = assetId;
assetSubscribeState.value.serviceName = serviceName;
console.log('[showAssetSubscribeDialog] 修改后状态:', JSON.stringify(assetSubscribeState.value));
}
/**
* 关闭服务开通弹窗
*/
export function closeAssetSubscribeDialog() {
assetSubscribeState.value.visible = false;
}
/**
* 处理 403 错误码(模块未开通)
*/
export function handleModuleNotEnabled(routePath: string): boolean {
console.log('[模块未开通] 当前路由路径:', routePath);
const assetInfo = getAssetInfoByRoute(routePath);
console.log('[模块未开通] 匹配到的资产信息:', assetInfo);
if (assetInfo) {
showAssetSubscribeDialog(assetInfo.assetId, assetInfo.serviceName);
return true;
}
// 如果没有匹配到路由,尝试使用默认的资产管理
console.warn('[模块未开通] 未匹配到路由,使用默认资产管理');
showAssetSubscribeDialog('696b4acd1be1c8b76c4b4c15', '资产管理');
return true;
}

View File

@@ -3,6 +3,7 @@ import { ElMessage, ElMessageBox } from 'element-plus';
import { Session } from '/@/utils/storage';
import qs from 'qs';
import { getChangedFields } from '/@/utils/diffUtils';
import { handleModuleNotEnabled } from '/@/utils/assetSubscribe';
// 标记是否正在处理 token 过期,避免重复弹窗
let isHandlingTokenExpired = false;
@@ -156,8 +157,20 @@ const responseInterceptor = (response: AxiosResponse) => {
return Promise.reject(new Error('登录状态已过期'));
}
// 业务逻辑错误处理
if (code !== undefined && code !== 0 && code !== 200) {
// 处理模块未开通错误 (403)
// 跳过资产SKU查询接口避免弹窗内部请求触发循环
const requestUrl = response.config.url || '';
if (code === 402 && !requestUrl.includes('/assets/asset/sku/')) {
// 获取当前路由路径
const currentPath = window.location.hash.replace('#', '') || window.location.pathname;
console.log('[request.ts] 检测到403错误当前路径:', currentPath);
handleModuleNotEnabled(currentPath);
// 直接返回,不再显示错误消息
return Promise.reject(new Error('模块未开通'));
}
// 业务逻辑错误处理排除403因为上面已处理
if (code !== undefined && code !== 0 && code !== 200 && code !== 403) {
const errorMsg = message || `请求失败(${code})`;
showErrorMessage(errorMsg);
return Promise.reject(new Error(errorMsg));
@@ -189,10 +202,21 @@ const responseErrorHandler = (error: any) => {
const responseMessage = error.response.data?.message;
// 处理 HTTP 错误状态
const requestUrl = error.response.config?.url || '';
switch (httpStatus) {
case 401:
handleTokenExpired();
break;
case 402:
// 模块未开通处理跳过SKU相关接口避免循环
if (!requestUrl.includes('/assets/asset/sku/') && !requestUrl.includes('getAssetAndSku')) {
const currentPath = window.location.hash.replace('#', '') || window.location.pathname;
console.log('[responseErrorHandler] 检测到HTTP 402错误当前路径:', currentPath);
handleModuleNotEnabled(currentPath);
return Promise.reject(new Error('模块未开通'));
}
showErrorMessage(responseMessage || '服务未开通');
break;
case 403:
showErrorMessage(responseMessage || '没有权限访问该资源');
break;