新增提示Toast组件

This commit is contained in:
2025-04-21 09:22:13 +08:00
parent 01d93522b8
commit 5c2c367856
36 changed files with 2609 additions and 478 deletions
+139 -83
View File
@@ -7,29 +7,51 @@ import dayjs from 'dayjs';
* @returns 提取后的数据或 null
*/
function extractApiData<T>(responseData: unknown): T | null {
if (!responseData) return null;
// 格式1: { code: number, msg: string, data: T }
if (typeof responseData === 'object' && responseData !== null &&
'code' in responseData &&
'data' in responseData &&
(responseData as { data: unknown }).data) {
return (responseData as { data: T }).data;
if (!responseData) {
console.warn('API响应数据为空');
return null;
}
// 格式2: 直接是数据对象
return responseData as T;
}
try {
// 检查是否有错误信息
if (typeof responseData === 'object' && responseData !== null) {
// 错误检查: 检查错误码,一般成功的错误码是0或200
if ('code' in responseData) {
const code = (responseData as { code: number }).code;
// 如果有错误码且不是成功状态
if (code !== 0 && code !== 200) {
const errorMsg = 'msg' in responseData
? (responseData as { msg: string }).msg
: '未知错误';
console.error(`API响应错误: [${code}] ${errorMsg}`);
return null;
}
}
/**
* 评估结果类型定义
*/
interface EvaluationResult {
result: boolean;
rule_id?: string;
rule_name?: string;
description?: string;
[key: string]: unknown;
// 错误检查: 检查是否包含错误消息但没有数据
if ('error' in responseData && (responseData as { error: unknown }).error) {
const error = (responseData as { error: unknown }).error;
console.error(`API响应包含错误: ${typeof error === 'string' ? error : JSON.stringify(error)}`);
return null;
}
// 格式1: { code: number, msg: string, data: T }
if ('data' in responseData) {
const data = (responseData as { data: unknown }).data;
if (!data) {
console.warn('API响应中的data字段为空');
return null;
}
return data as T;
}
}
// 格式2: 直接是数据对象
return responseData as T;
} catch (error) {
console.error('处理API响应数据时出错:', error);
return null;
}
}
/**
@@ -67,43 +89,81 @@ export async function getHomeData(): Promise<HomeStatistics> {
const startOfLastMonth = dayjs().subtract(1, 'month').startOf('month').format('YYYY-MM-DD HH:mm:ss');
const endOfLastMonth = dayjs().subtract(1, 'month').endOf('month').format('YYYY-MM-DD HH:mm:ss');
// 通用API响应处理函数
const handleApiResponse = async <T>(
apiCall: Promise<{
data?: unknown;
headers?: Record<string, string>;
error?: string;
status?: number
}>,
errorMessage: string,
defaultValue: T
): Promise<T> => {
try {
const response = await apiCall;
if (response.error) {
console.error(`${errorMessage}: ${response.error}`);
return defaultValue;
}
const data = extractApiData<T>(response.data);
if (!data) {
console.warn(`${errorMessage}: 无法提取有效数据`);
return defaultValue;
}
return data;
} catch (error) {
console.error(`${errorMessage}: ${error instanceof Error ? error.message : '未知错误'}`);
return defaultValue;
}
};
// 1. 今日待审核文件 - 获取今天的待审核文件数量 (audit_status = 0 或 2)
const todayPendingParams: PostgrestParams = {
select: 'count',
filter: {
or: `(audit_status.eq.0,audit_status.eq.2)`,
or: `(audit_status.eq.0,audit_status.eq.2,audit_status.is.null)`,
created_at: `gte.${startOfToday}`
}
};
const todayPendingResponse = await postgrestGet('documents', todayPendingParams);
const todayPendingCount = extractApiData<{count: number}[]>(todayPendingResponse.data);
const todayPendingFiles = todayPendingCount?.[0]?.count || 0;
const todayPendingCount = await handleApiResponse<{count: number}[]>(
postgrestGet('documents', todayPendingParams),
'获取今日待审核文件数量失败',
[]
);
const todayPendingFiles = todayPendingCount[0]?.count || 0;
// 2. 本月已审核文件 - 获取本月已审核文件数量 (audit_status != 0 且 != 2)
const thisMonthReviewedParams: PostgrestParams = {
select: 'count',
filter: {
and: `(audit_status.neq.0,audit_status.neq.2)`,
created_at: `gte.${startOfThisMonth}`,
created_at_lte: `lte.${endOfThisMonth}`
created_at: `gte.${startOfThisMonth}`
}
};
const thisMonthReviewedResponse = await postgrestGet('documents', thisMonthReviewedParams);
const thisMonthReviewedCount = extractApiData<{count: number}[]>(thisMonthReviewedResponse.data);
const monthlyReviewedFiles = thisMonthReviewedCount?.[0]?.count || 0;
const thisMonthReviewedCount = await handleApiResponse<{count: number}[]>(
postgrestGet('documents', thisMonthReviewedParams),
'获取本月已审核文件数量失败',
[]
);
// 本月已审核文件数量
const monthlyReviewedFiles = thisMonthReviewedCount[0]?.count || 0;
// 上月已审核文件
const lastMonthReviewedParams: PostgrestParams = {
select: 'count',
filter: {
and: `(audit_status.neq.0,audit_status.neq.2)`,
created_at: `gte.${startOfLastMonth}`,
created_at_lte: `lte.${endOfLastMonth}`
or: `(audit_status.eq.1,audit_status.eq.-1)`,
and: `(created_at.gte.${startOfLastMonth},created_at.lte.${endOfLastMonth})`
}
};
const lastMonthReviewedResponse = await postgrestGet('documents', lastMonthReviewedParams);
const lastMonthReviewedCount = extractApiData<{count: number}[]>(lastMonthReviewedResponse.data);
const lastMonthReviewed = lastMonthReviewedCount?.[0]?.count || 0;
const lastMonthReviewedCount = await handleApiResponse<{count: number}[]>(
postgrestGet('documents', lastMonthReviewedParams),
'获取上月已审核文件数量失败',
[]
);
// 上月已审核文件数量
const lastMonthReviewed = lastMonthReviewedCount[0]?.count || 0;
// 计算同比增长
let reviewGrowthValue = 0;
@@ -115,37 +175,46 @@ export async function getHomeData(): Promise<HomeStatistics> {
reviewGrowthIsUp = growthRate >= 0;
}
// 3. 审核通过率 - 本月审核通过率 (已审核文件 / 总待审核文件 + 已审核文件)
// 3. 审核通过率 - 本月审核通过率
const thisMonthTotalParams: PostgrestParams = {
select: 'count',
filter: {
created_at: `gte.${startOfThisMonth}`,
created_at_lte: `lte.${endOfThisMonth}`
audit_status: `eq.1`,
created_at: `gte.${startOfThisMonth}`
}
};
const thisMonthTotalResponse = await postgrestGet('documents', thisMonthTotalParams);
const thisMonthTotalCount = extractApiData<{count: number}[]>(thisMonthTotalResponse.data);
const thisMonthTotal = thisMonthTotalCount?.[0]?.count || 0;
const thisMonthTotalCount = await handleApiResponse<{count: number}[]>(
postgrestGet('documents', thisMonthTotalParams),
'获取本月审核通过数量失败',
[]
);
// 本月审核通过数量
const thisMonthPassTotal = thisMonthTotalCount[0]?.count || 0;
// 本月审核通过率
const monthlyPassRate = thisMonthTotal > 0
? parseFloat(((monthlyReviewedFiles / thisMonthTotal) * 100).toFixed(1))
const monthlyPassRate = (thisMonthPassTotal > 0 && monthlyReviewedFiles > 0)
? parseFloat(((thisMonthPassTotal / monthlyReviewedFiles) * 100).toFixed(1))
: 0;
// 上月审核通过率
const lastMonthTotalParams: PostgrestParams = {
select: 'count',
filter: {
created_at: `gte.${startOfLastMonth}`,
created_at_lte: `lte.${endOfLastMonth}`
audit_status: `eq.1`,
and: `(created_at.gte.${startOfLastMonth},created_at.lte.${endOfLastMonth})`
}
};
const lastMonthTotalResponse = await postgrestGet('documents', lastMonthTotalParams);
const lastMonthTotalCount = extractApiData<{count: number}[]>(lastMonthTotalResponse.data);
const lastMonthTotal = lastMonthTotalCount?.[0]?.count || 0;
const lastMonthTotalCount = await handleApiResponse<{count: number}[]>(
postgrestGet('documents', lastMonthTotalParams),
'获取上月审核通过数量失败',
[]
);
// 上月审核通过数量
const lastMonthTotal = lastMonthTotalCount[0]?.count || 0;
// 上月审核通过率
const lastMonthPassRate = (lastMonthTotal > 0 && lastMonthReviewed > 0)
? (lastMonthReviewed / lastMonthTotal) * 100
? parseFloat(((lastMonthTotal / lastMonthReviewed) * 100).toFixed(1))
: 0;
// 计算通过率同比增长
@@ -160,48 +229,35 @@ export async function getHomeData(): Promise<HomeStatistics> {
// 4. 检查出的问题总数(从评估结果表中统计)
const thisMonthIssuesParams: PostgrestParams = {
select: 'evaluated_results',
select: 'count',
filter: {
created_at: `gte.${startOfThisMonth}`,
created_at_lte: `lte.${endOfThisMonth}`
and: `(created_at.gte.${startOfThisMonth},created_at.lte.${endOfThisMonth})`,
'evaluated_results->result': 'eq.false' // 使用->操作符访问JSONB字段
}
};
const thisMonthIssuesResponse = await postgrestGet('evaluation_results', thisMonthIssuesParams);
const thisMonthIssuesData = extractApiData<{ evaluated_results: EvaluationResult[] }[]>(thisMonthIssuesResponse.data);
// 累计本月问题数量
let thisMonthIssuesCount = 0;
if (thisMonthIssuesData && thisMonthIssuesData.length > 0) {
thisMonthIssuesData.forEach(row => {
if (row.evaluated_results && Array.isArray(row.evaluated_results)) {
thisMonthIssuesCount += row.evaluated_results.filter((result: EvaluationResult) =>
result && result.result === false
).length;
}
});
}
const thisMonthIssuesResponse = await handleApiResponse<{count: number}[]>(
postgrestGet('evaluation_results', thisMonthIssuesParams),
'获取本月问题数据失败',
[]
);
// 本月问题数量
const thisMonthIssuesCount = thisMonthIssuesResponse[0]?.count || 0;
// 上月问题数量
const lastMonthIssuesParams: PostgrestParams = {
select: 'evaluated_results',
select: 'count',
filter: {
created_at: `gte.${startOfLastMonth}`,
created_at_lte: `lte.${endOfLastMonth}`
and: `(created_at.gte.${startOfLastMonth},created_at.lte.${endOfLastMonth})`,
'evaluated_results->result': 'eq.false' // 使用->操作符访问JSONB字段
}
};
const lastMonthIssuesResponse = await postgrestGet('evaluation_results', lastMonthIssuesParams);
const lastMonthIssuesData = extractApiData<{ evaluated_results: EvaluationResult[] }[]>(lastMonthIssuesResponse.data);
let lastMonthIssuesCount = 0;
if (lastMonthIssuesData && lastMonthIssuesData.length > 0) {
lastMonthIssuesData.forEach(row => {
if (row.evaluated_results && Array.isArray(row.evaluated_results)) {
lastMonthIssuesCount += row.evaluated_results.filter((result: EvaluationResult) =>
result && result.result === false
).length;
}
});
}
const lastMonthIssuesResponse = await handleApiResponse<{count: number}[]>(
postgrestGet('evaluation_results', lastMonthIssuesParams),
'获取上月问题数据失败',
[]
);
// 上月问题数量
const lastMonthIssuesCount = lastMonthIssuesResponse[0]?.count || 0;
// 计算问题数量同比增长
let issuesGrowthValue = 0;
@@ -233,7 +289,7 @@ export async function getHomeData(): Promise<HomeStatistics> {
}
};
} catch (error) {
console.error('获取首页数据失败:', error);
console.error('获取首页数据失败:', error instanceof Error ? error.message : String(error));
// 返回默认值以防止页面崩溃
return {
todayPendingFiles: 0,