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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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

View File

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