refactor(web): 前端错误处理统一化 — 9 个文件 13 处替换 handleApiError
Some checks failed
CI / rust-check (push) Has been cancelled
CI / rust-test (push) Has been cancelled
CI / frontend-build (push) Has been cancelled
CI / security-audit (push) Has been cancelled

统一使用 api/client.ts 的 handleApiError() 替代内联错误提取:
- Login/Users/Roles/Organizations/Settings 操作失败提示
- ArticleEditor/ArticleTagManage/ArticleCategoryManage 表单错误
- FamilyMembersTab 家庭成员操作

零 response?.data?.message 内联模式残留
This commit is contained in:
iven
2026-05-03 19:59:12 +08:00
parent 443bfbae61
commit 0d3e45300f
9 changed files with 23 additions and 47 deletions

View File

@@ -3,6 +3,7 @@ import { useNavigate } from 'react-router-dom';
import { Form, Input, Button, message, Divider } from 'antd';
import { UserOutlined, LockOutlined, SafetyCertificateOutlined } from '@ant-design/icons';
import { useAuthStore } from '../stores/auth';
import { handleApiError } from '../api/client';
import ThemeSwitcher from '../components/ThemeSwitcher';
import { getPublicBrand, type BrandConfig } from '../api/themes';
@@ -23,10 +24,7 @@ export default function Login() {
messageApi.success('登录成功');
navigate('/');
} catch (err: unknown) {
const errorMsg =
(err as { response?: { data?: { message?: string } } })?.response?.data?.message ||
'登录失败,请检查用户名和密码';
messageApi.error(errorMsg);
handleApiError(err, '登录失败,请检查用户名和密码');
}
};

View File

@@ -21,6 +21,7 @@ import {
} from '@ant-design/icons';
import type { DataNode } from 'antd/es/tree';
import { useThemeMode } from '../hooks/useThemeMode';
import { handleApiError } from '../api/client';
import {
listOrgTree,
createOrg,
@@ -158,9 +159,7 @@ export default function Organizations() {
orgForm.resetFields();
fetchOrgTree();
} catch (err: unknown) {
const errorMsg =
(err as { response?: { data?: { message?: string } } })?.response?.data?.message || '操作失败';
message.error(errorMsg);
handleApiError(err, '操作失败');
}
};
@@ -173,9 +172,7 @@ export default function Organizations() {
setPositions([]);
fetchOrgTree();
} catch (err: unknown) {
const errorMsg =
(err as { response?: { data?: { message?: string } } })?.response?.data?.message || '删除失败';
message.error(errorMsg);
handleApiError(err, '删除失败');
}
};
@@ -198,9 +195,7 @@ export default function Organizations() {
deptForm.resetFields();
fetchDeptTree();
} catch (err: unknown) {
const errorMsg =
(err as { response?: { data?: { message?: string } } })?.response?.data?.message || '操作失败';
message.error(errorMsg);
handleApiError(err, '操作失败');
}
};
@@ -212,9 +207,7 @@ export default function Organizations() {
setPositions([]);
fetchDeptTree();
} catch (err: unknown) {
const errorMsg =
(err as { response?: { data?: { message?: string } } })?.response?.data?.message || '删除失败';
message.error(errorMsg);
handleApiError(err, '删除失败');
}
};
@@ -238,9 +231,7 @@ export default function Organizations() {
positionForm.resetFields();
fetchPositions();
} catch (err: unknown) {
const errorMsg =
(err as { response?: { data?: { message?: string } } })?.response?.data?.message || '操作失败';
message.error(errorMsg);
handleApiError(err, '操作失败');
}
};

View File

@@ -23,6 +23,7 @@ import {
type RoleInfo,
type PermissionInfo,
} from '../api/roles';
import { handleApiError } from '../api/client';
import { useThemeMode } from '../hooks/useThemeMode';
export default function Roles() {
@@ -79,9 +80,7 @@ export default function Roles() {
form.resetFields();
fetchRoles();
} catch (err: unknown) {
const errorMsg =
(err as { response?: { data?: { message?: string } } })?.response?.data?.message || '操作失败';
message.error(errorMsg);
handleApiError(err, '操作失败');
}
};

View File

@@ -32,6 +32,7 @@ import {
} from '../api/users';
import { listRoles, type RoleInfo } from '../api/roles';
import type { UserInfo } from '../api/auth';
import { handleApiError } from '../api/client';
import { useThemeMode } from '../hooks/useThemeMode';
const STATUS_COLOR_MAP: Record<string, string> = {
@@ -135,9 +136,7 @@ export default function Users() {
form.resetFields();
fetchUsers();
} catch (err: unknown) {
const errorMsg =
(err as { response?: { data?: { message?: string } } })?.response?.data?.message || '操作失败';
message.error(errorMsg);
handleApiError(err, '操作失败');
}
};

View File

@@ -22,6 +22,7 @@ import {
type CreateCategoryReq,
type UpdateCategoryReq,
} from '../../api/health/articles';
import { handleApiError } from '../../api/client';
import { useThemeMode } from '../../hooks/useThemeMode';
import { AuthButton } from '../../components/AuthButton';
@@ -106,10 +107,7 @@ export default function ArticleCategoryManage() {
closeModal();
fetchCategories();
} catch (err: unknown) {
const errorMsg =
(err as { response?: { data?: { message?: string } } })?.response?.data?.message ||
'操作失败';
message.error(errorMsg);
handleApiError(err, '操作失败');
}
};

View File

@@ -13,7 +13,7 @@ import {
} from '../../api/health/articles';
import { useThemeMode } from '../../hooks/useThemeMode';
import { AuthButton } from '../../components/AuthButton';
import client from '../../api/client';
import client, { handleApiError } from '../../api/client';
import '@wangeditor/editor/dist/css/style.css';
export default function ArticleEditor() {
@@ -175,10 +175,7 @@ export default function ArticleEditor() {
navigate('/health/articles');
}
} catch (err: unknown) {
const errorMsg =
(err as { response?: { data?: { message?: string } } })?.response?.data?.message ||
'保存失败';
message.error(errorMsg);
handleApiError(err, '保存失败');
} finally {
setSaving(false);
}
@@ -236,10 +233,7 @@ export default function ArticleEditor() {
message.success('已提交审核');
navigate('/health/articles');
} catch (err: unknown) {
const errorMsg =
(err as { response?: { data?: { message?: string } } })?.response?.data?.message ||
'提交审核失败';
message.error(errorMsg);
handleApiError(err, '提交审核失败');
} finally {
setSaving(false);
}

View File

@@ -15,6 +15,7 @@ import {
type ArticleTagItem,
type CreateTagReq,
} from '../../api/health/articles';
import { handleApiError } from '../../api/client';
import { useThemeMode } from '../../hooks/useThemeMode';
import { AuthButton } from '../../components/AuthButton';
@@ -77,10 +78,7 @@ export default function ArticleTagManage() {
closeModal();
fetchTags();
} catch (err: unknown) {
const errorMsg =
(err as { response?: { data?: { message?: string } } })?.response?.data?.message ||
(editing ? '更新失败' : '创建失败');
message.error(errorMsg);
handleApiError(err, editing ? '更新失败' : '创建失败');
}
};

View File

@@ -2,6 +2,7 @@ import { useCallback, useEffect, useState } from 'react';
import { Table, Button, Form, Input, Select, Drawer, message, Popconfirm, Space } from 'antd';
import { PlusOutlined } from '@ant-design/icons';
import { patientApi, type FamilyMember, type CreateFamilyMemberReq } from '../../../api/health/patients';
import { handleApiError } from '../../../api/client';
import { AuthButton } from '../../../components/AuthButton';
import { useDictionary } from '../../../hooks/useDictionary';
@@ -52,8 +53,7 @@ export function FamilyMembersTab({ patientId }: Props) {
form.resetFields();
fetchMembers();
} catch (err: unknown) {
const msg = (err as { response?: { data?: { message?: string } } })?.response?.data?.message || '操作失败';
message.error(msg);
handleApiError(err, '操作失败');
}
};

View File

@@ -16,6 +16,7 @@ import {
updateSetting,
deleteSetting,
} from '../../api/settings';
import { handleApiError } from '../../api/client';
import { useThemeMode } from '../../hooks/useThemeMode';
interface SettingEntry {
@@ -93,9 +94,7 @@ export default function SystemSettings() {
message.success('设置已保存');
closeModal();
} catch (err: unknown) {
const errorMsg =
(err as { response?: { data?: { message?: string } } })?.response?.data?.message || '保存失败';
message.error(errorMsg);
handleApiError(err, '保存失败');
}
};