fix: QA 第二轮修复 — PatientDetail 重构/测试覆盖/id_number 列宽/小程序 URL 规范化
- refactor(web): PatientDetail.tsx 拆分为 4 个子组件(737→334行) - refactor(web): 提取 usePaginatedData hook 消除重复分页状态 - feat(db): patient.id_number varchar(20)→varchar(255) 容纳加密值 - test(health): 添加预约模块集成测试(创建/列表/租户隔离) - test(plugin): 添加 6 个 SQL 注入 sanitize 测试 - fix(miniprogram): 7 个 service 文件 URL 构建规范化(params 对象) - fix(miniprogram): 跨平台字段名对齐(birth_date/start_time/end_time)
This commit is contained in:
@@ -2,6 +2,7 @@ import Taro from '@tarojs/taro';
|
||||
import { secureGet, secureSet, secureRemove } from '@/utils/secure-storage';
|
||||
|
||||
const BASE_URL = process.env.TARO_APP_API_URL || 'http://localhost:3000/api/v1';
|
||||
const IS_DEV = process.env.NODE_ENV !== 'production';
|
||||
|
||||
interface ApiResponse<T> {
|
||||
success: boolean;
|
||||
@@ -44,12 +45,23 @@ async function tryRefreshToken(): Promise<boolean> {
|
||||
|
||||
export async function request<T>(method: string, path: string, data?: unknown): Promise<T> {
|
||||
const headers = await getHeaders();
|
||||
const res = await Taro.request({ url: `${BASE_URL}${path}`, method, data, header: headers });
|
||||
const url = `${BASE_URL}${path}`;
|
||||
if (IS_DEV) {
|
||||
console.log(`[API] ${method} ${path}`, data ?? '');
|
||||
}
|
||||
const res = await Taro.request({ url, method: method as any, data, header: headers, timeout: 30000 });
|
||||
if (IS_DEV) {
|
||||
console.log(`[API] ${method} ${path} → ${res.statusCode}`);
|
||||
}
|
||||
|
||||
if (res.statusCode === 401) {
|
||||
const refreshed = await tryRefreshToken();
|
||||
if (refreshed) return request<T>(method, path, data);
|
||||
Taro.redirectTo({ url: '/pages/login/index' });
|
||||
const pages = Taro.getCurrentPages();
|
||||
const currentPath = pages[pages.length - 1]?.path || '';
|
||||
if (!currentPath.includes('pages/login')) {
|
||||
Taro.redirectTo({ url: '/pages/login/index' });
|
||||
}
|
||||
throw new Error('登录已过期');
|
||||
}
|
||||
|
||||
@@ -58,8 +70,20 @@ export async function request<T>(method: string, path: string, data?: unknown):
|
||||
return body.data as T;
|
||||
}
|
||||
|
||||
function buildQuery(params?: Record<string, string | number | undefined>): string {
|
||||
if (!params) return '';
|
||||
const entries = Object.entries(params).filter(([, v]) => v !== undefined && v !== '');
|
||||
return entries.length > 0
|
||||
? '?' +
|
||||
entries
|
||||
.map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(String(v))}`)
|
||||
.join('&')
|
||||
: '';
|
||||
}
|
||||
|
||||
export const api = {
|
||||
get: <T>(path: string) => request<T>('GET', path),
|
||||
get: <T>(path: string, params?: Record<string, string | number | undefined>) =>
|
||||
request<T>('GET', `${path}${buildQuery(params)}`),
|
||||
post: <T>(path: string, data?: unknown) => request<T>('POST', path, data),
|
||||
put: <T>(path: string, data?: unknown) => request<T>('PUT', path, data),
|
||||
delete: <T>(path: string) => request<T>('DELETE', path),
|
||||
|
||||
Reference in New Issue
Block a user