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

@@ -63,25 +63,41 @@ function riskSortLabel(
return option ? t(option.label) : value;
}
type RiskFilter = "all" | "sold_out" | "high_risk";
export type RiskPoolListFilter = "all" | "sold_out" | "high_risk";
type RiskPoolsConsoleProps = {
drawId: number;
/** @deprecated 优先使用 titleKey */
title?: string;
titleKey?: RiskPoolsPageTitleKey;
soldOutOnly: boolean;
defaultSort: "usage_desc" | "locked_desc" | "remaining_asc" | "number_asc";
/** @deprecated 使用 initialFilter */
soldOutOnly?: boolean;
initialFilter?: RiskPoolListFilter;
defaultSort?: "usage_desc" | "locked_desc" | "remaining_asc" | "number_asc";
allowSortChange?: boolean;
};
function resolveInitialFilter(
initialFilter: RiskPoolListFilter | undefined,
soldOutOnly: boolean | undefined,
): RiskPoolListFilter {
if (initialFilter) {
return initialFilter;
}
if (soldOutOnly) {
return "sold_out";
}
return "all";
}
export function RiskPoolsConsole({
drawId,
title,
titleKey,
soldOutOnly,
defaultSort,
allowSortChange = false,
initialFilter: initialFilterProp,
defaultSort = "number_asc",
allowSortChange = true,
}: RiskPoolsConsoleProps) {
const { t } = useTranslation(["risk", "common"]);
const tRef = useTranslationRef(["risk", "common"]);
@@ -91,11 +107,12 @@ export function RiskPoolsConsole({
PRD_RISK_MANAGE,
PRD_DRAW_RESULT_MANAGE,
]);
const initialFilter = resolveInitialFilter(initialFilterProp, soldOutOnly);
const pageTitle = titleKey ? t(titleKey) : (title ?? t("poolsTitle"));
const exportLabels = useExportLabels("riskPools");
useAdminCurrencyCatalog();
const [sort, setSort] = useState(defaultSort);
const [filter, setFilter] = useState<RiskFilter>(soldOutOnly ? "sold_out" : "all");
const [filter, setFilter] = useState<RiskPoolListFilter>(initialFilter);
const [number, setNumber] = useState("");
const [page, setPage] = useState(1);
const [perPage, setPerPage] = useState(10);
@@ -162,19 +179,22 @@ export function RiskPoolsConsole({
return (
<>
<Card className="admin-list-card">
<CardHeader className="admin-list-header space-y-3">
<CardHeader className="admin-list-header">
<CardTitle className="admin-list-title">{pageTitle}</CardTitle>
</CardHeader>
<CardContent className="admin-list-content">
<div className="admin-list-toolbar">
<div className="admin-list-field">
<Label htmlFor="risk-pool-number" className="sm:w-16 sm:shrink-0">
<Label htmlFor="risk-pool-number" className="sm:w-20 sm:shrink-0">
{t("searchNumber")}
</Label>
<Input
id="risk-pool-number"
inputMode="numeric"
value={number}
maxLength={4}
placeholder={t("searchNumberPlaceholder")}
className="h-8 w-full font-mono sm:w-52"
className="h-8 w-full font-mono sm:w-32"
onChange={(event) => {
setNumber(event.target.value.replace(/\D/g, "").slice(0, 4));
setPage(1);
@@ -182,31 +202,35 @@ export function RiskPoolsConsole({
/>
</div>
<div className="admin-list-field">
<Label className="sm:w-16 sm:shrink-0">{t("riskFilter")}</Label>
<div className="flex flex-wrap gap-2">
{[
["all", t("filterAll")],
["sold_out", t("filterSoldOut")],
["high_risk", t("filterHighRisk")],
].map(([value, label]) => (
<Button
key={value}
type="button"
size="sm"
variant={filter === value ? "default" : "outline"}
onClick={() => {
setFilter(value as RiskFilter);
setPage(1);
}}
>
{label}
</Button>
))}
</div>
<Label className="sm:w-20 sm:shrink-0">{t("riskFilter")}</Label>
<Select
modal={false}
value={filter}
onValueChange={(v) => {
if (!v) return;
setFilter(v as RiskPoolListFilter);
setPage(1);
}}
>
<SelectTrigger id="risk-pool-filter" size="sm" className="h-8 w-full sm:w-40">
<SelectValue>
{filter === "all"
? t("filterAll")
: filter === "sold_out"
? t("filterSoldOut")
: t("filterHighRisk")}
</SelectValue>
</SelectTrigger>
<SelectContent>
<SelectItem value="all">{t("filterAll")}</SelectItem>
<SelectItem value="sold_out">{t("filterSoldOut")}</SelectItem>
<SelectItem value="high_risk">{t("filterHighRisk")}</SelectItem>
</SelectContent>
</Select>
</div>
{allowSortChange ? (
<div className="admin-list-field">
<Label htmlFor="risk-pool-sort" className="sm:w-10 sm:shrink-0">
<Label htmlFor="risk-pool-sort" className="sm:w-20 sm:shrink-0">
{t("sort")}
</Label>
<Select
@@ -218,7 +242,7 @@ export function RiskPoolsConsole({
setPage(1);
}}
>
<SelectTrigger id="risk-pool-sort" size="sm" className="w-full sm:w-52">
<SelectTrigger id="risk-pool-sort" size="sm" className="h-8 w-full sm:w-44">
<SelectValue>{riskSortLabel(sort, t)}</SelectValue>
</SelectTrigger>
<SelectContent>
@@ -239,8 +263,7 @@ export function RiskPoolsConsole({
/>
</div>
</div>
</CardHeader>
<CardContent className="admin-list-content">
{error ? <p className="text-sm text-destructive">{error}</p> : null}
<>
<div className="admin-table-shell">
@@ -253,7 +276,7 @@ export function RiskPoolsConsole({
<TableHead className="text-center">{t("remainingAmount")}</TableHead>
<TableHead className="text-center">{t("usageRatio")}</TableHead>
<TableHead>{t("poolStatus")}</TableHead>
<TableHead className="sticky right-0 z-10 bg-card text-center shadow-[-1px_0_0_rgba(203,213,225,0.7)]">{t("table.actions", { ns: "common" })}</TableHead>
<TableHead className="sticky right-0 z-10 text-center">{t("table.actions", { ns: "common" })}</TableHead>
</TableRow>
</TableHeader>
<TableBody>
@@ -301,7 +324,7 @@ export function RiskPoolsConsole({
{row.is_sold_out ? t("soldOut") : highRisk ? t("warning") : t("normal")}
</span>
</TableCell>
<TableCell className="sticky right-0 z-10 bg-card text-center shadow-[-1px_0_0_rgba(203,213,225,0.7)]">
<TableCell className="sticky right-0 z-10 text-center">
<AdminRowActionsMenu
busy={acting}
actions={[
@@ -345,7 +368,7 @@ export function RiskPoolsConsole({
{data ? (
<AdminListPaginationFooter
selectId={`risk-pools-${drawId}-${soldOutOnly ? "so" : "all"}`}
selectId={`risk-pools-${drawId}-${filter}`}
total={data.meta.total}
page={data.meta.current_page}
lastPage={data.meta.last_page}