- 布局:PageContainer extra 渲染标题+副标题(内容区右上角),卡内重复标题/副标题移除 - 详情页(账号/编辑/草稿/Attempt/环境/出口)外层 Card 拆除,区块卡平铺在灰底上 - 任务中心、竞品分析改为筛选卡+表格卡双卡片;工作台外层 Card 拆除,操作记录表包 Card - 浏览器实测 13 个页面:0 嵌套卡片、表格均在 Card 内、标题无重复;生产构建通过
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
import { history, Outlet, useLocation } from '@umijs/max';
|
||||
import { PageContainer, ProLayout } from '@ant-design/pro-components';
|
||||
import { Dropdown } from 'antd';
|
||||
import { Dropdown, Typography } from 'antd';
|
||||
import { LogoutOutlined } from '@ant-design/icons';
|
||||
import { menu } from '@/utils/metadata';
|
||||
import { menu, pageMetadata } from '@/utils/metadata';
|
||||
|
||||
// 菜单结构对齐 web.archived/src/app/Layout.jsx(运营 / 资源 两组);侧栏仅保留模块链接菜单,标题由 TopNav 呈现。
|
||||
// Umi 4(react-router 6)全局布局:location 用 useLocation(),子路由用 <Outlet/> 渲染
|
||||
@@ -48,7 +48,18 @@ export default function Layout() {
|
||||
),
|
||||
}}
|
||||
>
|
||||
<PageContainer title={false} subTitle={false} ghost>
|
||||
{/* 页面标题在卡片外面(内容区右上角);卡片内不再重复渲染标题。 */}
|
||||
<PageContainer
|
||||
ghost
|
||||
title={false}
|
||||
subTitle={false}
|
||||
extra={
|
||||
<div style={{ textAlign: 'right' }}>
|
||||
<Typography.Title level={4} style={{ marginBottom: 2 }}>{pageMetadata(location.pathname).title}</Typography.Title>
|
||||
<Typography.Text type="secondary" style={{ fontSize: 12 }}>{pageMetadata(location.pathname).subtitle}</Typography.Text>
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<Outlet />
|
||||
</PageContainer>
|
||||
</ProLayout>
|
||||
|
||||
@@ -477,7 +477,7 @@ export default function Page() {
|
||||
);
|
||||
|
||||
return (
|
||||
<Card variant="outlined">
|
||||
<div>
|
||||
{contextHolder}
|
||||
<div style={{ marginBottom: 16, display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
|
||||
<div>
|
||||
@@ -497,6 +497,6 @@ export default function Page() {
|
||||
{ key: 'strategy', label: '自动响应策略', children: strategyTab },
|
||||
]}
|
||||
/>
|
||||
</Card>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -223,7 +223,7 @@ export default function Page() {
|
||||
];
|
||||
|
||||
return (
|
||||
<Card variant="outlined">
|
||||
<div>
|
||||
{contextHolder}
|
||||
<div style={{ marginBottom: 16, display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', gap: 12 }}>
|
||||
<div style={{ minWidth: 0 }}>
|
||||
@@ -255,6 +255,6 @@ export default function Page() {
|
||||
>
|
||||
<p>{`暂停账号 ${account.name}?待领取任务将进入 hold,恢复账号不会自动恢复既有 hold。`}</p>
|
||||
</Modal>
|
||||
</Card>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ export default function Page() {
|
||||
}
|
||||
|
||||
return (
|
||||
<Card title="创建社媒账号">
|
||||
<Card variant="outlined">
|
||||
{error ? (
|
||||
<Alert type="error" showIcon style={{ marginBottom: 16 }} message={conflictMessage(error, '该平台的账号 ID 已存在;表单内容已保留。')} />
|
||||
) : null}
|
||||
|
||||
@@ -35,11 +35,8 @@ export default function Page() {
|
||||
if (!attempt) return null;
|
||||
|
||||
return (
|
||||
<Card variant="outlined">
|
||||
<div>
|
||||
<div style={{ marginBottom: 16 }}>
|
||||
<Typography.Title level={4} style={{ marginBottom: 0 }}>
|
||||
Attempt 详情
|
||||
</Typography.Title>
|
||||
<Typography.Text type="secondary" copyable>
|
||||
{attempt.id}
|
||||
</Typography.Text>
|
||||
@@ -66,6 +63,6 @@ export default function Page() {
|
||||
</Space>
|
||||
</Space>
|
||||
</Card>
|
||||
</Card>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ export default function Page() {
|
||||
if (error || !runtime) return <Alert type="error" showIcon message={error?.message || '运行环境不存在'} />;
|
||||
|
||||
return (
|
||||
<Card variant="outlined">
|
||||
<div>
|
||||
<div style={{ marginBottom: 16, display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
|
||||
<Typography.Title level={4} style={{ marginBottom: 0 }}>
|
||||
{`${runtime.name}(${runtime.alias})`}
|
||||
@@ -106,6 +106,6 @@ export default function Page() {
|
||||
</Space>
|
||||
</Space>
|
||||
</Card>
|
||||
</Card>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -102,13 +102,12 @@ export default function Page() {
|
||||
}
|
||||
|
||||
return (
|
||||
<Card variant="outlined">
|
||||
<div>
|
||||
{contextHolder}
|
||||
<div style={{ marginBottom: 16, display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
|
||||
<Typography.Text type="secondary">为已授权且暂停的账号绑定网关、指纹与网络出口</Typography.Text>
|
||||
<div style={{ marginBottom: 16, display: 'flex', justifyContent: 'flex-end' }}>
|
||||
<Button onClick={() => history.push('/browsers')}>返回运行环境</Button>
|
||||
</div>
|
||||
<Card>
|
||||
<Card variant="outlined">
|
||||
<Form form={form} layout="vertical" onFinish={submit}>
|
||||
<Space size={16} wrap style={{ display: 'flex' }}>
|
||||
<Form.Item name="name" label="环境名称" required rules={[{ required: true, message: '请输入环境名称' }]} extra="展示名称,支持中文,如:店铺一号">
|
||||
@@ -201,6 +200,6 @@ export default function Page() {
|
||||
</Space>
|
||||
</Form>
|
||||
</Card>
|
||||
</Card>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -262,14 +262,11 @@ export default function Page() {
|
||||
!['not_started', 'running', 'failed'].includes(material.transcription_status);
|
||||
|
||||
return (
|
||||
<Card variant="outlined">
|
||||
<div>
|
||||
{contextHolder}
|
||||
<Card title="作品与指标" extra={<Typography.Text type="secondary" style={{ fontSize: 12 }}>共 {workPageInfo.total} 条</Typography.Text>}>
|
||||
<Typography.Paragraph type="secondary" style={{ marginTop: 0 }}>时间窗口、指标阈值和“不可用”字段由后端原样保留。</Typography.Paragraph>
|
||||
<div style={{ marginBottom: 16, background: '#fafafa', padding: 16, borderRadius: 8 }}>
|
||||
<Typography.Text strong>筛选作品</Typography.Text>
|
||||
<Typography.Text type="secondary" style={{ marginLeft: 8, fontSize: 12 }}>调整条件后自动刷新</Typography.Text>
|
||||
<Space size={12} wrap style={{ marginTop: 12, display: 'flex' }}>
|
||||
<Space direction="vertical" size={16} style={{ width: '100%' }}>
|
||||
<Card title="筛选作品" extra={<Typography.Text type="secondary" style={{ fontSize: 12 }}>调整条件后自动刷新</Typography.Text>}>
|
||||
<Space size={12} wrap style={{ display: 'flex' }}>
|
||||
<Select
|
||||
style={{ width: 140 }}
|
||||
placeholder="全部平台"
|
||||
@@ -292,30 +289,30 @@ export default function Page() {
|
||||
<Input type="date" style={{ width: 160 }} value={filters.publishedAfter} onChange={(e) => setFilters((f) => ({ ...f, publishedAfter: e.target.value }))} />
|
||||
<Input type="date" style={{ width: 160 }} value={filters.publishedBefore} onChange={(e) => setFilters((f) => ({ ...f, publishedBefore: e.target.value }))} />
|
||||
</Space>
|
||||
</div>
|
||||
</Card>
|
||||
<Card title="作品与指标">
|
||||
{error ? (
|
||||
<Alert type="error" showIcon style={{ marginBottom: 16 }} message={error.message} action={<Button size="small" onClick={load}>重试</Button>} />
|
||||
) : null}
|
||||
<Table rowKey="id" columns={columns} dataSource={works} loading={pending} pagination={false} locale={{ emptyText: '暂无符合条件的作品。' }} />
|
||||
<div style={{ marginTop: 12, display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
|
||||
<Typography.Text type="secondary" style={{ fontSize: 12 }}>
|
||||
当前页 {works.length} 条 · 共 {workPageInfo.total} 条
|
||||
</Typography.Text>
|
||||
<Space>
|
||||
<Button size="small" onClick={() => setWorkPage((page) => Math.max(1, page - 1))} disabled={workPage === 1 || pending}>
|
||||
上一页
|
||||
</Button>
|
||||
<Button size="small" onClick={() => setWorkPage((page) => page + 1)} disabled={!workPageInfo.hasNext || pending}>
|
||||
下一页
|
||||
</Button>
|
||||
</Space>
|
||||
</div>
|
||||
{workDetail ? (
|
||||
{workPageInfo.total > works.length ? (
|
||||
<div style={{ marginTop: 12, display: 'flex', justifyContent: 'flex-end' }}>
|
||||
<Space>
|
||||
<Button size="small" onClick={() => setWorkPage((page) => Math.max(1, page - 1))} disabled={workPage === 1 || pending}>
|
||||
上一页
|
||||
</Button>
|
||||
<Button size="small" onClick={() => setWorkPage((page) => page + 1)} disabled={!workPageInfo.hasNext || pending}>
|
||||
下一页
|
||||
</Button>
|
||||
</Space>
|
||||
</div>
|
||||
) : null}
|
||||
</Card>
|
||||
{workDetail ? (
|
||||
<Card
|
||||
size="small"
|
||||
title={<span>作品详情 <Typography.Text type="secondary" style={{ fontSize: 12, fontWeight: 'normal' }}>{workDetail.work_key || workDetail.id}</Typography.Text></span>}
|
||||
extra={<Button size="small" onClick={() => setWorkDetail(null)}>关闭</Button>}
|
||||
style={{ marginTop: 16 }}
|
||||
>
|
||||
<Space direction="vertical" style={{ width: '100%' }} size={16}>
|
||||
{workDetail.cover_url ? <img src={workDetail.cover_url} alt="作品封面" style={{ maxHeight: 256, borderRadius: 4, border: '1px solid #f0f0f0' }} /> : null}
|
||||
@@ -346,7 +343,7 @@ export default function Page() {
|
||||
</Card>
|
||||
) : null}
|
||||
{material ? (
|
||||
<Card size="small" title="素材处理" style={{ marginTop: 16 }}>
|
||||
<Card size="small" title="素材处理">
|
||||
<Typography.Paragraph type="secondary" style={{ marginTop: 0 }}>每一步都保留真实状态;失败不会被显示为成功。</Typography.Paragraph>
|
||||
<Button type="primary" onClick={processMaterial} loading={materialPending || material.download_status === 'running'} style={{ marginBottom: 16 }}>
|
||||
开始处理素材
|
||||
@@ -397,7 +394,7 @@ export default function Page() {
|
||||
</Space>
|
||||
</Card>
|
||||
) : null}
|
||||
</Card>
|
||||
</Space>
|
||||
<Modal
|
||||
open={Boolean(pendingSwitchWork)}
|
||||
title="放弃未保存的素材文稿"
|
||||
@@ -408,6 +405,6 @@ export default function Page() {
|
||||
>
|
||||
当前素材文稿尚未保存,确定放弃并切换吗?
|
||||
</Modal>
|
||||
</Card>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -74,10 +74,10 @@ export default function Page() {
|
||||
if (error) return <Alert type="error" showIcon message={error.message} action={<Button size="small" onClick={load}>重试</Button>} />;
|
||||
|
||||
return (
|
||||
<Card variant="outlined">
|
||||
<div>
|
||||
{contextHolder}
|
||||
<Typography.Paragraph type="secondary">按配置类别管理 UTC 采集窗口、指标采集和已批准的服务。</Typography.Paragraph>
|
||||
<Card>
|
||||
<Typography.Paragraph type="secondary" style={{ marginBottom: 16 }}>按配置类别管理 UTC 采集窗口、指标采集和已批准的服务。</Typography.Paragraph>
|
||||
<Card variant="outlined">
|
||||
<Form form={form} layout="vertical" onFinish={save} initialValues={{}}>
|
||||
<Tabs
|
||||
items={[
|
||||
@@ -158,6 +158,6 @@ export default function Page() {
|
||||
</div>
|
||||
</Form>
|
||||
</Card>
|
||||
</Card>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -990,18 +990,20 @@ export default function Page() {
|
||||
];
|
||||
|
||||
const operationsTab = (
|
||||
<Table
|
||||
rowKey="id"
|
||||
loading={pending}
|
||||
pagination={false}
|
||||
dataSource={error ? [] : visibleData}
|
||||
columns={operationsColumns}
|
||||
locale={{ emptyText: '暂无操作记录。' }}
|
||||
/>
|
||||
<Card variant="outlined">
|
||||
<Table
|
||||
rowKey="id"
|
||||
loading={pending}
|
||||
pagination={false}
|
||||
dataSource={error ? [] : visibleData}
|
||||
columns={operationsColumns}
|
||||
locale={{ emptyText: '暂无操作记录。' }}
|
||||
/>
|
||||
</Card>
|
||||
);
|
||||
|
||||
return (
|
||||
<Card variant="outlined">
|
||||
<div>
|
||||
{contextHolder}
|
||||
<Tabs
|
||||
activeKey={tab}
|
||||
@@ -1062,6 +1064,6 @@ export default function Page() {
|
||||
>
|
||||
当前私信文案尚未发送,放弃后再切换吗?
|
||||
</Modal>
|
||||
</Card>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -110,15 +110,12 @@ export default function Page() {
|
||||
}
|
||||
|
||||
return (
|
||||
<Card variant="outlined">
|
||||
<div>
|
||||
{contextHolder}
|
||||
<div style={{ marginBottom: 16, display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
|
||||
<div style={{ minWidth: 0 }}>
|
||||
<Typography.Title level={4} style={{ marginBottom: 0 }}>草稿核对</Typography.Title>
|
||||
<Typography.Text type="secondary" ellipsis>
|
||||
{draft.account.platform_account_key} · 草稿版本 {draft.version}
|
||||
</Typography.Text>
|
||||
</div>
|
||||
<Typography.Text type="secondary" ellipsis>
|
||||
{draft.account.platform_account_key} · 草稿版本 {draft.version}
|
||||
</Typography.Text>
|
||||
<Button onClick={() => history.push(`/accounts/${draft.account_id}`)}>返回账号详情</Button>
|
||||
</div>
|
||||
{browsersError ? (
|
||||
@@ -222,6 +219,6 @@ export default function Page() {
|
||||
{binding?.network_exit_id || '当前机器直连'} 的只读确认快照。版本变化后必须重新确认。
|
||||
</p>
|
||||
</Modal>
|
||||
</Card>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -42,10 +42,9 @@ export default function Page() {
|
||||
|
||||
const known = Object.hasOwn(healthText, exit.health_status ?? '');
|
||||
return (
|
||||
<Card variant="outlined">
|
||||
<div>
|
||||
<div style={{ marginBottom: 16, display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
|
||||
<div style={{ minWidth: 0 }}>
|
||||
<Typography.Title level={4} style={{ marginBottom: 0 }}>网络出口详情</Typography.Title>
|
||||
<Typography.Text type="secondary" ellipsis>
|
||||
{`${exit.protocol}://${exit.host}:${exit.port}`}
|
||||
</Typography.Text>
|
||||
@@ -71,6 +70,6 @@ export default function Page() {
|
||||
</Descriptions>
|
||||
</Space>
|
||||
</Card>
|
||||
</Card>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -110,9 +110,9 @@ export default function Page() {
|
||||
];
|
||||
|
||||
return (
|
||||
<Card variant="outlined">
|
||||
<Typography.Paragraph type="secondary">逐条处理暂停、版本变化与未知执行结果;不会自动重试或更换出口</Typography.Paragraph>
|
||||
<Space wrap style={{ marginBottom: 16 }}>
|
||||
<div>
|
||||
<Card variant="outlined" style={{ marginBottom: 16 }}>
|
||||
<Space wrap>
|
||||
<Input
|
||||
style={{ width: 280 }}
|
||||
placeholder="账号 ID"
|
||||
@@ -128,8 +128,10 @@ export default function Page() {
|
||||
onChange={setStateFilter}
|
||||
options={Object.entries(stateText).map(([value, label]) => ({ value, label }))}
|
||||
/>
|
||||
</Space>
|
||||
{error ? <Alert type="error" showIcon style={{ marginBottom: 16 }} message={error.message} action={<Button size="small" onClick={load}>重试</Button>} /> : null}
|
||||
</Space>
|
||||
</Card>
|
||||
<Card variant="outlined">
|
||||
{error ? <Alert type="error" showIcon style={{ marginBottom: 16 }} message={error.message} action={<Button size="small" onClick={load}>重试</Button>} /> : null}
|
||||
<Table
|
||||
rowKey="id"
|
||||
columns={columns}
|
||||
@@ -137,7 +139,8 @@ export default function Page() {
|
||||
loading={pending}
|
||||
pagination={false}
|
||||
locale={{ emptyText: accountFilter || stateFilter ? '没有符合筛选条件的任务' : '尚无任务' }}
|
||||
/>
|
||||
</Card>
|
||||
/>
|
||||
</Card>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user