[fix]:[FL-155][菜单管理页面最后3项细节优化]

Co-authored-by: multica-agent <github@multica.ai>
This commit is contained in:
chengkai3
2026-06-20 07:15:48 +08:00
parent a9a2d32fd5
commit 83956f2587
3 changed files with 44 additions and 37 deletions
+18
View File
@@ -128,3 +128,21 @@
- 风险与关注点:
- `/api/v1/system-messages/me` 新增可选 `message_type` 参数,未传参时保持原列表语义;前端不再做本地类型过滤,分页 total 与服务端过滤结果一致。
- 改动影响系统消息列表展示与筛选,不改变创建、删除、标记已读接口字段。
# Work Log - 菜单管理页面最终细节对齐(FL-155)
- 背景:
- 菜单管理页需要补齐启用/禁用 mutation 组织、移动卡片字段列宽和加载完成提示条件三处细节,与用户管理页保持一致。
- 本次处理:
- 菜单启用/禁用移除独立 `updateMenuStatusMutation`,改为复用 `updateMenuMutation` 通过 `PATCH /api/v1/admin/menus/{menuId}` 提交 `{ status }`
- `.admin-menus-menu-card-field` 标签列宽从 `72px` 调整为 `64px`
- 移动卡片“已加载全部”提示条件简化为 `allLoadedMenus.length >= menuTotal && allLoadedMenus.length > 0`
- 验证:
- 基线:`npm --workspace web exec tsc --noEmit` 通过。
- 修改后:`npm --workspace web exec eslint src/app/admin/menus/page.tsx --max-warnings=0` 通过。
- 修改后:`npm --workspace web exec tsc --noEmit` 通过。
- 风险与关注点:
- 改动仅影响菜单管理页前端数据 mutation 组织和移动端展示条件,不改变接口路径、请求/响应字段或权限语义。
+23 -34
View File
@@ -351,7 +351,7 @@ export default function AdminMenusPage() {
});
const updateMenuMutation = useMutation({
mutationFn: async ({ menuId, payload }: { menuId: string; payload: MenuMutationPayload }) => {
mutationFn: async ({ menuId, payload }: { menuId: string; payload: Partial<MenuMutationPayload> }) => {
const response = await fetchWithAuth(`/api/v1/admin/menus/${menuId}`, {
method: "PATCH",
headers: { "Content-Type": "application/json" },
@@ -360,18 +360,33 @@ export default function AdminMenusPage() {
if (!response.ok) throw new Error(await readApiError(response));
return response.json() as Promise<MenuItem>;
},
onMutate: () => {
onMutate: ({ menuId, payload }) => {
if (payload.status && Object.keys(payload).length === 1) {
setUpdatingStatusMenuId(menuId);
}
setError("");
setSuccess("");
},
onSuccess: async () => {
onSuccess: async (_, variables) => {
if (variables.payload.status && Object.keys(variables.payload).length === 1) {
setSuccess(variables.payload.status === "enabled" ? "菜单已启用" : "菜单已禁用");
} else {
setSuccess("菜单已更新");
closeDialog();
}
await refreshData();
},
onError: (candidate) => {
onError: (candidate, variables) => {
setSuccess("");
setError(candidate instanceof Error ? candidate.message : "更新菜单失败");
const fallbackMessage = variables.payload.status && Object.keys(variables.payload).length === 1
? "菜单状态更新失败"
: "更新菜单失败";
setError(candidate instanceof Error ? candidate.message : fallbackMessage);
},
onSettled: (_data, _error, variables) => {
if (variables?.payload.status && Object.keys(variables.payload).length === 1) {
setUpdatingStatusMenuId(null);
}
},
});
@@ -403,32 +418,6 @@ export default function AdminMenusPage() {
onSettled: () => setDeletingMenuId(null),
});
const updateMenuStatusMutation = useMutation({
mutationFn: async ({ menuId, status }: { menuId: string; status: "enabled" | "disabled" }) => {
const response = await fetchWithAuth(`/api/v1/admin/menus/${menuId}`, {
method: "PATCH",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ status }),
});
if (!response.ok) throw new Error(await readApiError(response));
return response.json() as Promise<MenuItem>;
},
onMutate: ({ menuId }) => {
setUpdatingStatusMenuId(menuId);
setError("");
setSuccess("");
},
onSuccess: async (_, variables) => {
setSuccess(variables.status === "enabled" ? "菜单已启用" : "菜单已禁用");
await refreshData();
},
onError: (candidate) => {
setSuccess("");
setError(candidate instanceof Error ? candidate.message : "菜单状态更新失败");
},
onSettled: () => setUpdatingStatusMenuId(null),
});
const submit = useCallback(async () => {
try {
const values = await form.validateFields();
@@ -479,8 +468,8 @@ export default function AdminMenusPage() {
const updateMenuStatus = useCallback(async (menu: MenuItem) => {
const nextStatus: "enabled" | "disabled" = menu.status === "enabled" ? "disabled" : "enabled";
updateMenuStatusMutation.mutate({ menuId: menu.id, status: nextStatus });
}, [updateMenuStatusMutation]);
updateMenuMutation.mutate({ menuId: menu.id, payload: { status: nextStatus } });
}, [updateMenuMutation]);
const columns = useMemo<TableColumnsType<MenuItem>>(() => {
const base: TableColumnsType<MenuItem> = [
@@ -876,7 +865,7 @@ export default function AdminMenusPage() {
<Spin tip="加载更多..." />
</div>
)}
{!menusQuery.isLoading && !isLoadingMore && allLoadedMenus.length >= menuTotal && allLoadedMenus.length > 0 && (
{allLoadedMenus.length >= menuTotal && allLoadedMenus.length > 0 && (
<div style={{ textAlign: "center", padding: "20px 0" }}>
<Typography.Text type="secondary">
{allLoadedMenus.length}
+1 -1
View File
@@ -554,7 +554,7 @@ body {
.admin-menus-menu-card-field {
display: grid;
grid-template-columns: 72px minmax(0, 1fr);
grid-template-columns: 64px minmax(0, 1fr);
gap: 8px;
align-items: baseline;
}