fix(web): 编辑社媒账号页对齐全站布局——页头槽接管标识与操作,主体两张 Card 承载

This commit is contained in:
2026-09-30 14:49:02 +08:00
parent 17abec449f
commit 78b7f51596
+52 -38
View File
@@ -1,7 +1,10 @@
// 编辑社媒账号:账号资料维护 + 登录二维码/身份核验。
// 布局对齐全站模式:实体标识经 usePageInfo 进页头 content 左侧,返回/登录操作按钮经 usePageActions 进页头右侧;
// 主体两张 Card 纵向堆叠(登录状态 / 账号资料),不再自绘标题行、不再裸铺背景。
import { useCallback, useEffect, useState } from 'react';
import { history, useParams } from '@umijs/max';
import { Alert, App, Button, Card, Descriptions, Flex, Form, Input, InputNumber, Select, Space, Typography } from 'antd';
import { Alert, App, Button, Card, Descriptions, Divider, Flex, Form, Input, Select, Space, Typography } from 'antd';
import { usePageActions, usePageInfo } from '@/components/PageActions';
import { creatorAction, creatorGet, creatorUpdate, getList } from '@/services/api';
import { conflictMessage, dateTime } from '@/utils/helpers';
@@ -30,6 +33,35 @@ export default function Page() {
const selected = profiles.find((item) => item.id === selectedID);
// 页头 content 行左侧:实体标识(账号名 + 平台/账号 ID),与详情页同形态。
usePageInfo(
selected ? (
<Flex align="center" gap={8} wrap="wrap">
<Typography.Title level={5} style={{ marginBottom: 0 }} ellipsis>
{selected.name || selected.platform_account_key}
</Typography.Title>
<Typography.Text type="secondary">
{platformLabelMap[selected.platform] || selected.platform} · {selected.platform_account_key}
</Typography.Text>
</Flex>
) : null,
[selected?.id, selected?.name, selected?.platform],
);
// 页头 content 行右侧:返回 + 登录操作,不在卡片内重复渲染。
usePageActions(
<Space>
<Button onClick={() => history.push('/accounts')}>返回社媒账号</Button>
<Button disabled={busy || !selected || selected.platform !== 'douyin'} onClick={requestLoginQR}>
显示登录二维码
</Button>
<Button disabled={busy || !selected || selected.platform !== 'douyin'} onClick={verifyLogin}>
核验浏览器身份
</Button>
</Space>,
[selected?.id, selected?.platform],
);
const load = useCallback(async () => {
setPending(true);
setError(null);
@@ -121,39 +153,19 @@ export default function Page() {
if (!selected) return <Alert type="warning" showIcon title="账号不存在。" />;
return (
<div>
<div style={{ marginBottom: 16, display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
<div>
<Typography.Title level={4} style={{ marginBottom: 0 }}>
{selected.name || selected.platform_account_key}
</Typography.Title>
<Typography.Text type="secondary">
{platformLabelMap[selected.platform] || selected.platform} · {selected.platform_account_key}
</Typography.Text>
</div>
<Button onClick={() => history.push('/accounts')}>返回社媒账号</Button>
</div>
<Flex vertical gap={16}>
<Flex>
<Descriptions column={1} size="small" style={{ flex: 1, minWidth: 260 }}>
<Descriptions.Item label="登录核验">
{selected.login_status === 'logged_in' ? '已登录' : '需人工确认'}
{selected.login_checked_at ? ` · ${dateTime(selected.login_checked_at)}` : ' · 尚未核验'}
{selected.login_reason ? ` · ${selected.login_reason}` : ''}
</Descriptions.Item>
<Descriptions.Item label="密码凭据">{selected.password_configured ? '已配置' : '未配置'}</Descriptions.Item>
</Descriptions>
<Space wrap>
<Button disabled={busy || selected.platform !== 'douyin'} onClick={requestLoginQR}>
显示登录二维码
</Button>
<Button disabled={busy || selected.platform !== 'douyin'} onClick={verifyLogin}>
核验浏览器身份
</Button>
</Space>
</Flex>
<Flex vertical gap={16}>
<Card title="登录状态">
<Descriptions column={1} size="small">
<Descriptions.Item label="登录核验">
{selected.login_status === 'logged_in' ? '已登录' : '需人工确认'}
{selected.login_checked_at ? ` · ${dateTime(selected.login_checked_at)}` : ' · 尚未核验'}
{selected.login_reason ? ` · ${selected.login_reason}` : ''}
</Descriptions.Item>
<Descriptions.Item label="密码凭据">{selected.password_configured ? '已配置' : '未配置'}</Descriptions.Item>
</Descriptions>
{loginQR ? (
<Card size="small" title="人工登录" extra={<Button size="small" onClick={requestLoginQR} disabled={busy}>刷新登录画面</Button>}>
<>
<Divider />
<Typography.Text type="secondary">
{loginQR.qr_detected ? '请使用抖音 App 扫描下方二维码。' : '当前画面未检测到二维码,请按画面提示人工完成验证。'}
</Typography.Text>
@@ -165,8 +177,10 @@ export default function Page() {
<Typography.Text type="secondary" style={{ display: 'block', marginTop: 8, fontSize: 12 }}>
当前画面有效至 {dateTime(loginQR.expires_at)};完成扫码后请点击“核验浏览器身份”。
</Typography.Text>
</Card>
</>
) : null}
</Card>
<Card title="账号资料">
<Form form={form} layout="vertical" onFinish={save} initialValues={profileForm(selected)}>
<Space size={16} wrap style={{ display: 'flex' }}>
<Form.Item name="login_username" label="登录用户名" extra="密码只会进入凭据存储,不会回传到页面。">
@@ -206,14 +220,14 @@ export default function Page() {
<Form.Item name="note" label="账号备注">
<Input.TextArea />
</Form.Item>
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
<Flex justify="space-between" align="center" gap={16} wrap="wrap">
<Typography.Text type="secondary">最近更新:{selected.updated_at ? dateTime(selected.updated_at) : '—'}</Typography.Text>
<Button type="primary" htmlType="submit" loading={busy}>
{busy ? '保存中…' : '保存账号资料'}
</Button>
</div>
</Flex>
</Form>
</Flex>
</div>
</Card>
</Flex>
);
}