feat: 态势感知看板全量 mock 适配(page1+page2+page3 共 48 接口)

- 新增 src/mock/{page1,page2,page3,registry}.ts,按 URL 路由 13+10+25 个接口
- request.ts 在 proxyService 顶部加 mock 短路,命中直接返回本地假数据
- .env.development 新增 VITE_USE_MOCK='true',生产环境不设即默认关闭
- 业务代码(API、视图)零改动
This commit is contained in:
2026-06-29 20:27:15 +08:00
parent c1e9a4be83
commit aaa3994305
6 changed files with 1061 additions and 1 deletions

92
src/mock/registry.ts Normal file
View File

@@ -0,0 +1,92 @@
/**
* Mock 路由注册表
*
* 根据请求 URL 匹配对应的 mock handler匹配命中时短路掉 axios 直接返回假数据。
* 当前覆盖 /api/v1/page1/* 13 个 + /api/v1/page2/* 10 个接口。
*/
import type { AxiosRequestConfig, AxiosResponse } from 'axios';
import * as page1 from './page1';
import * as page2 from './page2';
import * as page3 from './page3';
type MockHandler = (params?: any, data?: any) => Promise<AxiosResponse>;
/** 精确匹配优先,模糊匹配兜底(处理带 query 的 URL */
const registry: Record<string, MockHandler> = {
'/api/v1/page1/overviewData': page1.overviewData,
'/api/v1/page1/map/alerts': page1.mapAlerts,
'/api/v1/page1/map/mapData': page1.mapData,
'/api/v1/page1/map/vulnStats': page1.vulnStats,
'/api/v1/page1/map/regionStats': page1.regionStats,
'/api/v1/page1/industryDistribution': page1.industryDistribution,
'/api/v1/page1/highRiskComponent': page1.highRiskComponent,
'/api/v1/page1/feedList': page1.feedList,
'/api/v1/page1/cveData/global': page1.cveDataGlobal,
'/api/v1/page1/cveData/regional': page1.cveDataRegional,
'/api/v1/page1/languageTrend': page1.languageTrend,
'/api/v1/page1/vulnerabilitySeverity': page1.vulnerabilitySeverity,
'/api/v1/page1/scatterData': page1.scatterData,
// page2 - 开源生态与贡献价值全景
'/api/v1/page2/overviewData': page2.overviewData,
'/api/v1/page2/rawEnterpriseData': page2.rawEnterpriseData,
'/api/v1/page2/infrastructure': page2.infrastructure,
'/api/v1/page2/universityClubs': page2.universityClubs,
'/api/v1/page2/communityHealth': page2.communityHealth,
'/api/v1/page2/languageTech': page2.languageTech,
'/api/v1/page2/excellentDeveloper': page2.excellentDeveloper,
'/api/v1/page2/vitalityData': page2.vitalityData,
'/api/v1/page2/projectHeatmap': page2.projectHeatmap,
'/api/v1/page2/talentMapData': page2.talentMapData,
// page3 - 武汉市开源生态建设
'/api/v1/page3/hmStatsBar': page3.hmStatsBar,
'/api/v1/page3/statsBar': page3.statsBar,
'/api/v1/page3/hmCityData': page3.hmCityData,
'/api/v1/page3/hmProjects': page3.hmProjects,
'/api/v1/page3/whProjects': page3.whProjects,
'/api/v1/page3/hmDevelopers': page3.hmDevelopers,
'/api/v1/page3/hmDevCityData': page3.hmDevCityData,
'/api/v1/page3/whHmDevelopers': page3.whHmDevelopers,
'/api/v1/page3/hmEnterpriseCityData': page3.hmEnterpriseCityData,
'/api/v1/page3/hmEnterprises': page3.hmEnterprises,
'/api/v1/page3/whEnterprises': page3.whEnterprises,
'/api/v1/page3/uniCityData': page3.uniCityData,
'/api/v1/page3/uniContributors': page3.uniContributors,
'/api/v1/page3/wuhanGithubProjects': page3.wuhanGithubProjects,
'/api/v1/page3/cityProject': page3.cityProject,
'/api/v1/page3/talent': page3.talent,
'/api/v1/page3/communityRankChart': page3.communityRankChart,
'/api/v1/page3/chinaExcellentProjects': page3.chinaExcellentProjects,
'/api/v1/page3/excellentProjects': page3.excellentProjects,
'/api/v1/page3/developerNames': page3.developerNames,
'/api/v1/page3/wuhanCommunities': page3.wuhanCommunities,
'/api/v1/page3/club': page3.club,
'/api/v1/page3/policy': page3.policy,
'/api/v1/page3/campus': page3.campus,
'/api/v1/page3/mirrors': page3.mirrors
};
/**
* 根据请求 URL 查找 mock handler
* @returns mock 响应或 null未命中
*/
export async function getMockResponse(
url: string,
config: AxiosRequestConfig
): Promise<AxiosResponse | null> {
// 去掉 query string 和前缀 slash
const cleanUrl = url.split('?')[0].replace(/^\/+/, '');
const fullPath = '/' + cleanUrl;
// 精确匹配
const exact = registry[fullPath];
if (exact) return exact(config?.params, config?.data);
// 模糊匹配registry key 是请求 URL 的前缀)
for (const pattern in registry) {
if (fullPath === pattern || fullPath.startsWith(pattern + '/')) {
return registry[pattern](config?.params, config?.data);
}
}
return null;
}