feat(weibo): 增加工作台独占与快捷操作

This commit is contained in:
yml2213
2026-11-08 16:39:32 +08:00
parent d566518478
commit c8b62e5267
10 changed files with 341 additions and 29 deletions
+9 -1
View File
@@ -19,6 +19,7 @@ import type {
export const weiboApi = {
listAccounts: (params: {
search?: string;
tag?: string;
bind_status?: string;
enabled?: boolean;
page: number;
@@ -30,10 +31,11 @@ export const weiboApi = {
),
getAccount: (accountId: number) =>
api.get<WeiboAccountItem, WeiboAccountItem>(`/weibo/accounts/${accountId}`),
importCookies: (text: string, tag = '') =>
importCookies: (text: string, tag = '', updateExisting = false) =>
api.post<WeiboImportResult, WeiboImportResult>('/weibo/accounts/import-cookies', {
text,
tag,
update_existing: updateExisting,
}),
updateAccount: (
accountId: number,
@@ -67,8 +69,13 @@ export const weiboApi = {
'/weibo/accounts/batch-tag',
{ ids, tag },
),
accountTags: () =>
api.get<{ tags: string[] }, { tags: string[] }>('/weibo/accounts/tags'),
workbenchTags: () =>
api.get<{ tags: string[] }, { tags: string[] }>('/weibo/workbench/tags'),
listWorkbenchAccounts: (params: {
search?: string;
tag?: string;
bind_status?: string;
enabled?: boolean;
page: number;
@@ -80,6 +87,7 @@ export const weiboApi = {
),
listWorkbenchPool: (params: {
search?: string;
tag?: string;
page: number;
page_size: number;
}) =>
+66 -11
View File
@@ -3,6 +3,7 @@ import {
Alert,
AutoComplete,
Button,
Checkbox,
Descriptions,
Drawer,
Empty,
@@ -137,6 +138,8 @@ export default function WeiboAccountsPage({
const [page, setPage] = useState(1);
const [pageSize, setPageSize] = useState(20);
const [search, setSearch] = useState('');
const [tagFilter, setTagFilter] = useState('');
const [knownTags, setKnownTags] = useState<string[]>([]);
const [bindFilter, setBindFilter] = useState('');
const [enabledFilter, setEnabledFilter] = useState('');
const [loading, setLoading] = useState(false);
@@ -161,7 +164,11 @@ export default function WeiboAccountsPage({
const [importOpen, setImportOpen] = useState(false);
const [importing, setImporting] = useState(false);
const [importErrors, setImportErrors] = useState<WeiboImportError[]>([]);
const [form] = Form.useForm<{ text: string; tag?: string }>();
const [form] = Form.useForm<{
text: string;
tag?: string;
update_existing?: boolean;
}>();
const [editForm] = Form.useForm<{ tag?: string; remark?: string }>();
const [editOpen, setEditOpen] = useState(false);
const [editAccount, setEditAccount] = useState<WeiboAccountItem | null>(null);
@@ -199,6 +206,7 @@ export default function WeiboAccountsPage({
try {
const params = {
search: search.trim() || undefined,
tag: tagFilter || undefined,
bind_status: bindFilter || undefined,
enabled:
enabledFilter === 'enabled'
@@ -222,17 +230,36 @@ export default function WeiboAccountsPage({
} finally {
setLoading(false);
}
}, [bindFilter, enabledFilter, isWorkbench, page, pageSize, search]);
}, [bindFilter, enabledFilter, isWorkbench, page, pageSize, search, tagFilter]);
const loadKnownTags = useCallback(async () => {
try {
const result = isWorkbench
? await weiboApi.workbenchTags()
: await weiboApi.accountTags();
setKnownTags(result.tags);
} catch {
// 标签字典失败不影响账号列表;筛选选项退化为空。
}
}, [isWorkbench]);
useEffect(() => {
void loadAccounts();
}, [loadAccounts]);
useEffect(() => {
void loadKnownTags();
}, [loadKnownTags]);
const handleImport = async () => {
const values = await form.validateFields();
setImporting(true);
try {
const result = await weiboApi.importCookies(values.text, values.tag || '');
const result = await weiboApi.importCookies(
values.text,
values.tag || '',
Boolean(values.update_existing),
);
setImportErrors(result.errors);
let workbenchError = '';
if (isWorkbench && result.accounts.length > 0) {
@@ -253,11 +280,15 @@ export default function WeiboAccountsPage({
message.success(result.message);
}
await loadAccounts();
await loadKnownTags();
}
if (result.errors.length === 0 && result.count > 0) {
setImportOpen(false);
form.resetFields();
} else if (result.count === 0) {
} else if (result.skipped > 0) {
message.warning(result.message);
await loadAccounts();
} else {
message.error(result.message);
}
} catch (error) {
@@ -351,6 +382,7 @@ export default function WeiboAccountsPage({
setBatchTagValue('');
setSelectedIds([]);
await loadAccounts();
await loadKnownTags();
message.success(`已为 ${result.updated} 个账号设置标签`);
} catch (error) {
message.error(getErrorMessage(error));
@@ -819,7 +851,14 @@ export default function WeiboAccountsPage({
width: isWorkbench ? 90 : 120,
align: 'center',
onHeaderCell: centerHeader,
render: (value: string) => value || <Text type="secondary">-</Text>,
render: (value: string) =>
value ? (
<Tag color="blue" style={{ marginInlineEnd: 0 }}>
{value}
</Tag>
) : (
<Text type="secondary">-</Text>
),
},
{
title: 'CK',
@@ -1176,11 +1215,8 @@ export default function WeiboAccountsPage({
workbenchSelectedGoods.price >
(mallResult?.weidou_balance ?? featureAccount?.weidou_balance ?? 0);
const tagOptions = useMemo(
() =>
[...new Set(items.map((item) => item.tag.trim()).filter(Boolean))].map(
(tag) => ({ value: tag }),
),
[items],
() => knownTags.map((tag) => ({ value: tag })),
[knownTags],
);
return (
@@ -1216,6 +1252,17 @@ export default function WeiboAccountsPage({
}}
style={{ width: 240 }}
/>
<Select
allowClear
value={tagFilter || undefined}
onChange={(value) => {
setTagFilter(value || '');
setPage(1);
}}
placeholder="全部标签"
style={{ width: 130 }}
options={knownTags.map((tag) => ({ value: tag, label: tag }))}
/>
<Select
value={bindFilter}
onChange={(value) => {
@@ -1257,6 +1304,8 @@ export default function WeiboAccountsPage({
disabled={!canImport}
onClick={() => {
setImportErrors([]);
form.resetFields();
form.setFieldsValue({ update_existing: false });
setImportOpen(true);
}}
>
@@ -1736,7 +1785,8 @@ export default function WeiboAccountsPage({
title: '标签',
dataIndex: 'tag',
width: 120,
render: (value: string) => value || '-',
render: (value: string) =>
value ? <Tag color="blue">{value}</Tag> : '-',
},
{
title: 'CK',
@@ -1787,6 +1837,11 @@ export default function WeiboAccountsPage({
<Form.Item name="tag" label="标签">
<Input placeholder="可选" maxLength={64} />
</Form.Item>
<Form.Item name="update_existing" valuePropName="checked">
<Checkbox>
重复账号时更新 CK(仍只有一条全局账号,不新建)
</Checkbox>
</Form.Item>
</Form>
{importErrors.length > 0 && (
<Alert