feat(ui): 账号列表恢复「标签」列(含就地编辑)
按反馈把标签列加回来。这列不只是展示 —— **有 `account:tag` 权限时就是一个 内联编辑框**:选已有标签或直接输入新标签即保存,无权限时退化为只读 Tag。 因此一并恢复它所依赖的东西: - `handleSetTag`(单条改标签) - `tagColorMap` + `TAG_COLORS`(只读态的标签配色) - `useMemo` 导入 所以现在改标签有三个入口,各管一段场景: | 入口 | 场景 | | --- | --- | | 列表「标签」列 | 单条快速改 | | 列表「批量打标签」 | 一批一起改 | | 详情页状态卡 | 在账号全貌下改(S6) | 列表列最终为:**账号 / 状态 / 绑定 / 积分·鱼翅 / 标签 /(凭据三列,开关控制)/ 操作** 验证:pytest 500 passed / 6 skipped;ruff 全绿;前端 build 通过、lint 0 errors。
This commit is contained in:
@@ -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<string, string> = {};
|
||||
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() {
|
||||
</Space>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: '标签',
|
||||
dataIndex: 'tag',
|
||||
width: 170,
|
||||
render: (tag: string, record: AccountItem) => {
|
||||
// 有权限时直接就地改(Select 输入新标签即保存);无权限则只读展示。
|
||||
if (canTag) {
|
||||
return (
|
||||
<Select
|
||||
mode="tags"
|
||||
maxCount={1}
|
||||
allowClear
|
||||
showSearch
|
||||
optionFilterProp="label"
|
||||
size="small"
|
||||
placeholder="选择或输入标签"
|
||||
style={{ width: 150 }}
|
||||
value={tag ? [tag] : []}
|
||||
onChange={(values) => {
|
||||
const value = values.at(-1)?.trim() || '';
|
||||
if (value !== tag) handleSetTag(record.id, value);
|
||||
}}
|
||||
options={tags.map((value) => ({ value, label: value }))}
|
||||
/>
|
||||
);
|
||||
}
|
||||
return tag ? <Tag color={tagColorMap[tag]}>{tag}</Tag> : <Text type="secondary">-</Text>;
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
if (canViewFull && sensitiveVisible) {
|
||||
|
||||
Reference in New Issue
Block a user