From a21e4a7e2aff8b0370e4ca845532f89ac20b591f Mon Sep 17 00:00:00 2001 From: yml2213 Date: Sun, 4 Oct 2026 17:12:13 +0800 Subject: [PATCH] =?UTF-8?q?feat(ui):=20=E8=B4=A6=E5=8F=B7=E5=88=97?= =?UTF-8?q?=E8=A1=A8=E6=81=A2=E5=A4=8D=E3=80=8C=E6=A0=87=E7=AD=BE=E3=80=8D?= =?UTF-8?q?=E5=88=97=EF=BC=88=E5=90=AB=E5=B0=B1=E5=9C=B0=E7=BC=96=E8=BE=91?= =?UTF-8?q?=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 按反馈把标签列加回来。这列不只是展示 —— **有 `account:tag` 权限时就是一个 内联编辑框**:选已有标签或直接输入新标签即保存,无权限时退化为只读 Tag。 因此一并恢复它所依赖的东西: - `handleSetTag`(单条改标签) - `tagColorMap` + `TAG_COLORS`(只读态的标签配色) - `useMemo` 导入 所以现在改标签有三个入口,各管一段场景: | 入口 | 场景 | | --- | --- | | 列表「标签」列 | 单条快速改 | | 列表「批量打标签」 | 一批一起改 | | 详情页状态卡 | 在账号全貌下改(S6) | 列表列最终为:**账号 / 状态 / 绑定 / 积分·鱼翅 / 标签 /(凭据三列,开关控制)/ 操作** 验证:pytest 500 passed / 6 skipped;ruff 全绿;前端 build 通过、lint 0 errors。 --- web/frontend/src/pages/AccountsPage.tsx | 52 +++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/web/frontend/src/pages/AccountsPage.tsx b/web/frontend/src/pages/AccountsPage.tsx index 0a492e8..d710720 100644 --- a/web/frontend/src/pages/AccountsPage.tsx +++ b/web/frontend/src/pages/AccountsPage.tsx @@ -12,6 +12,10 @@ import { usePermissions } from '../hooks/usePermissions'; import { formatTime } from '../utils/time'; import { getErrorMessage } from '../utils/error'; +const TAG_COLORS = [ + 'blue', 'green', 'cyan', 'geekblue', 'purple', 'orange', 'magenta', 'volcano', +]; + const { TextArea } = Input; const { Text } = Typography; @@ -194,6 +198,14 @@ export default function AccountsPage() { } }; + const tagColorMap = useMemo(() => { + const map: Record = {}; + tags.forEach((tg, i) => { + map[tg] = TAG_COLORS[i % TAG_COLORS.length]; + }); + return map; + }, [tags]); + const handleBatchTag = async () => { if (selectedCount === 0) { message.warning('请先选择账号'); @@ -213,6 +225,17 @@ export default function AccountsPage() { } }; + const handleSetTag = async (accountId: number, tag: string) => { + try { + await accountApi.setTag(accountId, tag); + message.success('标签已更新'); + loadAccounts(); + loadTags(); + } catch (e: unknown) { + message.error(getErrorMessage(e)); + } + }; + const handleDelete = async (id: number) => { try { await accountApi.delete(id); @@ -351,6 +374,35 @@ export default function AccountsPage() { ), }, + { + title: '标签', + dataIndex: 'tag', + width: 170, + render: (tag: string, record: AccountItem) => { + // 有权限时直接就地改(Select 输入新标签即保存);无权限则只读展示。 + if (canTag) { + return ( +