From 25880e91a7871f9f84f1ecb2c11f0ee47d743896 Mon Sep 17 00:00:00 2001 From: yml2213 Date: Thu, 6 Aug 2026 13:20:12 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=97=E9=B1=BC=E5=AE=A2=E6=9C=8D=E5=AF=BC?= =?UTF-8?q?=E5=85=A5=E8=B4=A6=E5=8F=B7=20=E6=94=AF=E6=8C=81tag?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + web/backend/routers/douyu.py | 6 ++++- web/frontend/src/api/douyu.ts | 4 +-- web/frontend/src/pages/DouyuTasksPage.tsx | 33 +++++++++++++++++------ 4 files changed, 33 insertions(+), 11 deletions(-) diff --git a/.gitignore b/.gitignore index e3112da..57e67c2 100644 --- a/.gitignore +++ b/.gitignore @@ -25,3 +25,4 @@ web/frontend/node_modules/ web/frontend/dist/ data/web.db .DS_Store +.reasonix/ diff --git a/web/backend/routers/douyu.py b/web/backend/routers/douyu.py index 8030b06..06fe15b 100644 --- a/web/backend/routers/douyu.py +++ b/web/backend/routers/douyu.py @@ -239,6 +239,7 @@ def task_types(current: User = Depends(require_permission("douyu:task"))): @router.get("/accounts") def list_task_accounts( search: str = Query(""), + tag: str = Query(""), ids: str = Query(""), page: int | None = Query(None, ge=1), page_size: int = Query(50, ge=1, le=200), @@ -247,12 +248,15 @@ def list_task_accounts( ): """查看可执行斗鱼任务的账号(必须有成功 Cookie)。 - ids 为逗号分隔的账号 ID,用于工作台按已导入账号过滤;为空时返回全部。 + tag 按账号标签精确筛选;ids 为逗号分隔的账号 ID,用于工作台按已导入账号过滤;为空时返回全部。 """ query = _visible_task_accounts_query(db, current) id_list = [int(x) for x in ids.split(",") if x.strip().isdigit()] if id_list: query = query.filter(Account.id.in_(id_list)) + tag_text = (tag or "").strip() + if tag_text: + query = query.filter(Account.tag == tag_text) search_text = (search or "").strip() if search_text: pattern = f"%{search_text}%" diff --git a/web/frontend/src/api/douyu.ts b/web/frontend/src/api/douyu.ts index ff5ef47..da1658b 100644 --- a/web/frontend/src/api/douyu.ts +++ b/web/frontend/src/api/douyu.ts @@ -13,9 +13,9 @@ import type { export const douyuApi = { taskTypes: () => api.get, Record>('/douyu/task-types'), - listAccounts: (params?: { search?: string; ids?: string }) => + listAccounts: (params?: { search?: string; tag?: string; ids?: string }) => api.get('/douyu/accounts', { params }), - listAccountsPaged: (params: PageParams & { ids?: string }) => + listAccountsPaged: (params: PageParams & { tag?: string; ids?: string }) => api.get, PaginatedResponse>('/douyu/accounts', { params }), getConfig: () => api.get('/douyu/config'), updateConfig: (data: Partial) => api.put('/douyu/config', data), diff --git a/web/frontend/src/pages/DouyuTasksPage.tsx b/web/frontend/src/pages/DouyuTasksPage.tsx index 0fb2e48..0e2a8ab 100644 --- a/web/frontend/src/pages/DouyuTasksPage.tsx +++ b/web/frontend/src/pages/DouyuTasksPage.tsx @@ -9,6 +9,7 @@ import { SearchOutlined, SettingOutlined, ShoppingOutlined, StopOutlined, } from '@ant-design/icons'; import { + accountApi, douyuApi, type DouyuConfig, type DouyuGoodsItem, @@ -307,6 +308,8 @@ export default function DouyuTasksPage({ handbook }: { handbook: HandbookKind }) const [importOpen, setImportOpen] = useState(false); const [importPool, setImportPool] = useState([]); const [importSearch, setImportSearch] = useState(''); + const [importTag, setImportTag] = useState(''); + const [importTags, setImportTags] = useState([]); const [importSelectedIds, setImportSelectedIds] = useState([]); const [importLoading, setImportLoading] = useState(false); @@ -838,14 +841,18 @@ export default function DouyuTasksPage({ handbook }: { handbook: HandbookKind }) const loadImportPool = useCallback(async () => { setImportLoading(true); try { - // 候选池 = 账号库全量,过滤已导入工作台的账号 - const result = await douyuApi.listAccounts({ search: importSearch }); + // 候选池 = 账号库按搜索/标签过滤,剔除已导入工作台的账号 + const result = await douyuApi.listAccounts({ search: importSearch, tag: importTag || undefined }); setImportPool(result.filter((a) => !workbenchIds.includes(a.id))); } finally { setImportLoading(false); } - }, [importSearch, workbenchIds]); + }, [importSearch, importTag, workbenchIds]); useEffect(() => { if (importOpen) void loadImportPool(); }, [importOpen, loadImportPool]); + useEffect(() => { + if (!importOpen) return; + accountApi.listTags().then(setImportTags).catch(() => {}); + }, [importOpen]); const importAccounts = (ids: number[]) => { const toImport = importPool.filter((a) => ids.includes(a.id)); @@ -1746,11 +1753,20 @@ export default function DouyuTasksPage({ handbook }: { handbook: HandbookKind }) width={700} > - } - value={importSearch} onChange={(e) => setImportSearch(e.target.value)} - style={{ width: 250 }} - /> + + } + value={importSearch} onChange={(e) => setImportSearch(e.target.value)} + style={{ width: 220 }} + /> +