From 4563c570aca89380edd86faf9bacb71363c9e2e7 Mon Sep 17 00:00:00 2001 From: web Date: Wed, 3 Sep 2025 09:59:54 -0700 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20feat:=20Add=20queryNodeTag=20functi?= =?UTF-8?q?on=20and=20integrate=20tag=20retrieval=20in=20NodeForm=20and=20?= =?UTF-8?q?SubscribeForm=20components?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/admin/app/dashboard/nodes/node-form.tsx | 12 ++++- .../app/dashboard/product/subscribe-form.tsx | 48 ++++++++++++++----- apps/admin/services/admin/server.ts | 8 ++++ apps/admin/services/admin/typings.d.ts | 4 ++ 4 files changed, 60 insertions(+), 12 deletions(-) diff --git a/apps/admin/app/dashboard/nodes/node-form.tsx b/apps/admin/app/dashboard/nodes/node-form.tsx index 527890a..07805c3 100644 --- a/apps/admin/app/dashboard/nodes/node-form.tsx +++ b/apps/admin/app/dashboard/nodes/node-form.tsx @@ -1,6 +1,6 @@ 'use client'; -import { filterServerList } from '@/services/admin/server'; +import { filterServerList, queryNodeTag } from '@/services/admin/server'; import { zodResolver } from '@hookform/resolvers/zod'; import { useQuery } from '@tanstack/react-query'; import { Button } from '@workspace/ui/components/button'; @@ -98,6 +98,15 @@ export default function NodeForm(props: { }); const servers: ServerRow[] = data as ServerRow[]; + const { data: tagsData } = useQuery({ + queryKey: ['queryNodeTag'], + queryFn: async () => { + const { data } = await queryNodeTag(); + return data?.data?.tags || []; + }, + }); + const existingTags: string[] = tagsData as string[]; + const currentServer = useMemo(() => servers?.find((s) => s.id === serverId), [servers, serverId]); const availableProtocols = useMemo(() => { @@ -298,6 +307,7 @@ export default function NodeForm(props: { placeholder={t('tags_placeholder')} value={field.value || []} onChange={(v) => form.setValue(field.name, v)} + options={existingTags} /> {t('tags_description')} diff --git a/apps/admin/app/dashboard/product/subscribe-form.tsx b/apps/admin/app/dashboard/product/subscribe-form.tsx index f7c2f12..c51d1d3 100644 --- a/apps/admin/app/dashboard/product/subscribe-form.tsx +++ b/apps/admin/app/dashboard/product/subscribe-form.tsx @@ -1,6 +1,6 @@ 'use client'; -import { filterNodeList } from '@/services/admin/server'; +import { filterNodeList, queryNodeTag } from '@/services/admin/server'; import { getSubscribeGroupList } from '@/services/admin/subscribe'; import { zodResolver } from '@hookform/resolvers/zod'; import { useQuery } from '@tanstack/react-query'; @@ -245,7 +245,16 @@ export default function SubscribeForm>({ return (data.data?.list || []) as API.Node[]; }, }); - const tagGroups = Array.from( + + const { data: allTagsData } = useQuery({ + queryKey: ['queryNodeTag'], + queryFn: async () => { + const { data } = await queryNodeTag(); + return data?.data?.tags || []; + }, + }); + + const nodeExtractedTags = Array.from( new Set( ((nodes as API.Node[]) || []) .flatMap((n) => (Array.isArray(n.tags) ? n.tags : [])) @@ -253,6 +262,12 @@ export default function SubscribeForm>({ ), ) as string[]; + const allAvailableTags = (allTagsData as string[]) || []; + + const tagGroups = Array.from(new Set([...allAvailableTags, ...nodeExtractedTags])).filter( + Boolean, + ); + const unit_time = form.watch('unit_time'); return ( @@ -271,7 +286,7 @@ export default function SubscribeForm>({ {title} - +
@@ -801,8 +816,12 @@ export default function SubscribeForm>({ {tagGroups.map((tag) => { const value = field.value || []; - // Use a synthetic ID for tag grouping selection by name const tagId = tag; + const nodesWithTag = + (nodes as API.Node[])?.filter((n) => + (n.tags || []).includes(tag), + ) || []; + return ( @@ -818,7 +837,12 @@ export default function SubscribeForm>({ ); }} /> - + @@ -830,11 +854,13 @@ export default function SubscribeForm>({ key={node.id} className='flex items-center justify-between gap-3' > - {node.name} - + {node.name} + {node.address}:{node.port} - {node.protocol} + + {node.protocol} + ))} @@ -876,11 +902,11 @@ export default function SubscribeForm>({ }} /> ); diff --git a/apps/admin/services/admin/server.ts b/apps/admin/services/admin/server.ts index fdb1522..85af29b 100644 --- a/apps/admin/services/admin/server.ts +++ b/apps/admin/services/admin/server.ts @@ -141,6 +141,14 @@ export async function toggleNodeStatus( }); } +/** Query all node tags GET /v1/admin/server/node/tags */ +export async function queryNodeTag(options?: { [key: string]: any }) { + return request('/v1/admin/server/node/tags', { + method: 'GET', + ...(options || {}), + }); +} + /** Update Node POST /v1/admin/server/node/update */ export async function updateNode(body: API.UpdateNodeRequest, options?: { [key: string]: any }) { return request('/v1/admin/server/node/update', { diff --git a/apps/admin/services/admin/typings.d.ts b/apps/admin/services/admin/typings.d.ts index a9c0c57..2211ea5 100644 --- a/apps/admin/services/admin/typings.d.ts +++ b/apps/admin/services/admin/typings.d.ts @@ -1551,6 +1551,10 @@ declare namespace API { list: Document[]; }; + type QueryNodeTagResponse = { + tags: string[]; + }; + type QueryOrderDetailRequest = { order_no: string; };