feat(api, agents): add agent node profile retrieval and update functionality

Implemented new API functions to fetch and update agent node profiles, enhancing the management capabilities for agent data. This addition improves the overall functionality of the admin agents console, allowing for better user interaction with agent profiles. Updated related types for improved type safety and clarity in the codebase.
This commit is contained in:
2026-06-04 09:17:55 +08:00
parent 59b0684ea1
commit cbc499e5b2
79 changed files with 3468 additions and 1406 deletions

View File

@@ -12,6 +12,7 @@ import {
BreadcrumbSeparator,
} from "@/components/ui/breadcrumb";
import { adminNavLabel } from "@/lib/admin-nav-label";
import { resolveAdminPageTitle } from "@/lib/admin-page-title";
import { ADMIN_BASE } from "@/modules/_config/admin-nav";
import { useAdminProfile } from "@/stores/admin-session";
import React from "react";
@@ -39,6 +40,13 @@ const TOP_ROUTE_LABELS: Record<string, string> = {
agents: "agents.title",
};
const AGENT_ROUTE_LABELS: Record<string, string> = {
list: "agents.directoryTitle",
provision: "agents.subnav.provision",
sites: "agents.sitesTitle",
"settlement-bills": "agents.subnav.settlementBills",
};
const CONFIG_ROUTE_LABELS: Record<string, string> = {
"integration-sites": "integrationSites.title",
plays: "nav.items.plays",
@@ -119,10 +127,15 @@ export function AdminBreadcrumb() {
navItem != null &&
(pathname === navItem.href || pathname.startsWith(`${navItem.href}/`));
if (segments.length > 2 && !navCoversPath) {
if (segments.length > 2 && (!navCoversPath || businessSegment === "agents")) {
const subSegment = segments[2];
let subLabel = "";
if (businessSegment === "rules" && subSegment) {
if (businessSegment === "agents" && subSegment) {
const key = AGENT_ROUTE_LABELS[subSegment];
subLabel = key
? t(key, { ns: "agents", defaultValue: titleCase(subSegment) })
: titleCase(subSegment);
} else if (businessSegment === "rules" && subSegment) {
const key = RULES_ROUTE_LABELS[subSegment];
subLabel = key
? t(key, { ns: "config", defaultValue: titleCase(subSegment) })
@@ -143,12 +156,20 @@ export function AdminBreadcrumb() {
? t(key, { ns: "config", defaultValue: titleCase(subSegment) })
: titleCase(subSegment);
} else {
subLabel = subSegment
? t(`subnav.${subSegment}`, {
ns: "draws",
defaultValue: DRAW_ROUTE_LABELS[subSegment] ?? titleCase(subSegment),
})
: "";
const pageTitle = resolveAdminPageTitle(pathname);
if (pageTitle) {
subLabel = t(pageTitle.key, {
ns: pageTitle.ns,
...(pageTitle.params ?? {}),
});
} else if (subSegment) {
subLabel = t(`subnav.${subSegment}`, {
ns: "draws",
defaultValue: DRAW_ROUTE_LABELS[subSegment] ?? titleCase(subSegment),
});
} else {
subLabel = "";
}
}
if (subLabel) {
breadcrumbs.push({

View File

@@ -5,14 +5,18 @@ import { cn } from "@/lib/utils";
type ModuleScaffoldProps = {
children?: ReactNode;
className?: string;
/** 已处于带外边距的 layout如代理线路子导航内时为 true */
embedded?: boolean;
};
/** 内容区容器;模块标题由侧栏导航体现,此处不再重复大标题与说明。 */
export function ModuleScaffold({ children, className }: ModuleScaffoldProps) {
export function ModuleScaffold({ children, className, embedded = false }: ModuleScaffoldProps) {
return (
<div
className={cn(
"mx-auto flex w-full max-w-[1680px] min-w-0 flex-col gap-6 px-4 py-5 sm:px-6 lg:px-8 lg:py-6",
embedded
? "flex w-full min-w-0 flex-col gap-6"
: "mx-auto flex w-full max-w-[1680px] min-w-0 flex-col gap-6 px-4 py-5 sm:px-6 lg:px-8 lg:py-6",
className,
)}
>