DG7/MRF7 移动信息架构与展示去重治理

这个提交包含在:
2026-05-12 21:03:36 +08:00
父节点 b6b7b77c41
当前提交 9da0ca9632
共修改 26 个文件,包含 1556 行新增和 258 行删除
+29 -35
查看文件
@@ -1,7 +1,7 @@
import { Link, useSearchParams } from "react-router-dom";
import { useNavigate, useSearchParams } from "react-router-dom";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { toast } from "sonner";
import { fetchNotifications, markAllNotificationsRead, markNotificationRead } from "../api/notifications";
import { fetchNotifications, markAllNotificationsRead, markNotificationRead, type NotificationItem } from "../api/notifications";
import { isApiError } from "../api/types";
import { mapApiErrorMessage } from "../api/errorMessages";
import { PageHeader } from "../components/common/PageHeader";
@@ -9,8 +9,7 @@ import { Pagination } from "../components/common/Pagination";
import { PageScaffold } from "../components/patterns/PageScaffold";
import { Button } from "../components/ui/button";
import { Tabs, TabsList, TabsTrigger } from "../components/ui/tabs";
import { resolveNotificationTargetLink } from "../lib/notificationLinks";
import { resolveMobileEquivalentPath } from "../lib/runtimeContext";
import { resolveMobileNotificationTargetLink } from "../lib/notificationLinks";
import { resolveErrorMessage } from "../lib/resolveErrorMessage";
const PAGE_SIZE = 20;
@@ -33,19 +32,13 @@ function resolveNotificationError(error: unknown) {
return "加载通知失败";
}
function resolveMobileNotificationTarget(item: Parameters<typeof resolveNotificationTargetLink>[0]) {
const targetLink = resolveNotificationTargetLink(item);
if (!targetLink) return null;
const [pathname, search = ""] = targetLink.split("?");
return resolveMobileEquivalentPath(pathname, search ? `?${search}` : "");
}
function formatTime(value: string) {
return value.slice(0, 19).replace("T", " ");
}
export function MobileNotificationsPage() {
const queryClient = useQueryClient();
const navigate = useNavigate();
const [searchParams, setSearchParams] = useSearchParams();
const unreadOnlyRaw = searchParams.get("unreadOnly") ?? "0";
@@ -82,6 +75,21 @@ export function MobileNotificationsPage() {
},
});
const openNotificationTarget = async (item: NotificationItem, targetLink: string | null) => {
if (!targetLink) {
toast.info("这条通知没有可直达的业务详情");
return;
}
try {
if (!item.readAt) {
await markReadMutation.mutateAsync(item.id);
}
navigate(targetLink);
} catch (error) {
toast.error(resolveErrorMessage(error));
}
};
const markAllReadMutation = useMutation({
mutationFn: () => markAllNotificationsRead(),
onSuccess: async () => {
@@ -174,9 +182,15 @@ export function MobileNotificationsPage() {
) : null}
{notificationItems.map((item) => {
const targetLink = resolveMobileNotificationTarget(item);
const targetLink = resolveMobileNotificationTargetLink(item);
return (
<article data-testid="mobile-notification-card" key={item.id} className="mobile-list-card">
<button
data-testid="mobile-notification-card"
key={item.id}
className="mobile-list-card w-full text-left"
type="button"
onClick={() => void openNotificationTarget(item, targetLink)}
>
<div className="flex items-start justify-between gap-3">
<div className="min-w-0">
<div className="text-sm font-semibold text-zinc-900">{item.title}</div>
@@ -188,28 +202,8 @@ export function MobileNotificationsPage() {
</div>
<div className="mt-3 text-xs text-zinc-500">{formatTime(item.createdAt)}</div>
<div className="mobile-two-action-grid mt-3">
{targetLink ? (
<Button asChild size="sm" variant="secondary" data-testid="mobile-notification-target-link">
<Link to={targetLink}>查看</Link>
</Button>
) : null}
{!item.readAt ? (
<Button
className={targetLink ? "" : "col-span-2"}
data-testid="mobile-notification-mark-read"
size="sm"
type="button"
variant="secondary"
disabled={markReadMutation.isPending}
onClick={() => markReadMutation.mutate(item.id)}
>
标为已读
</Button>
) : null}
</div>
</article>
<div className="mt-3 text-xs text-primary">{targetLink ? "查看详情" : "暂无直达详情"}</div>
</button>
);
})}