douyin-release-gate / verify (push) Failing after 3m49s
- 布局:PageContainer extra 渲染标题+副标题(内容区右上角),卡内重复标题/副标题移除 - 详情页(账号/编辑/草稿/Attempt/环境/出口)外层 Card 拆除,区块卡平铺在灰底上 - 任务中心、竞品分析改为筛选卡+表格卡双卡片;工作台外层 Card 拆除,操作记录表包 Card - 浏览器实测 13 个页面:0 嵌套卡片、表格均在 Card 内、标题无重复;生产构建通过
164 lines
6.2 KiB
TypeScript
164 lines
6.2 KiB
TypeScript
// 采集设置:语义对齐 web.archived CreatorSettingsPage.jsx(提交 d97cade)。
|
|
// 四类配置用 antd Tabs 组织;仅用 antd 默认组件。
|
|
import { useCallback, useEffect, useState } from 'react';
|
|
import { Alert, Button, Card, Checkbox, Form, Input, InputNumber, Tabs, Typography, message } from 'antd';
|
|
import { creatorGet, creatorUpdate } from '@/services/api';
|
|
import { conflictMessage } from '@/utils/helpers';
|
|
|
|
const numericFields = new Set([
|
|
'lookback_days',
|
|
'new_work_interval_seconds',
|
|
'metric_initial_interval_seconds',
|
|
'metric_multiplier',
|
|
'metric_max_interval_seconds',
|
|
'metric_age_seconds',
|
|
]);
|
|
|
|
const editableFields = [
|
|
'lookback_days',
|
|
'new_work_interval_seconds',
|
|
'metric_initial_interval_seconds',
|
|
'metric_multiplier',
|
|
'metric_max_interval_seconds',
|
|
'metric_age_seconds',
|
|
'ai_provider',
|
|
'ai_model',
|
|
'ai_configured',
|
|
'transcription_provider',
|
|
'transcription_model',
|
|
'transcription_configured',
|
|
];
|
|
|
|
const editableSettings = (value: any) => Object.fromEntries(editableFields.map((field) => [field, value[field]]));
|
|
|
|
export default function Page() {
|
|
const [form] = Form.useForm();
|
|
const [pending, setPending] = useState(true);
|
|
const [error, setError] = useState<any>(null);
|
|
const [busy, setBusy] = useState(false);
|
|
const [messageApi, contextHolder] = message.useMessage();
|
|
|
|
const load = useCallback(async () => {
|
|
setPending(true);
|
|
setError(null);
|
|
try {
|
|
const result = await creatorGet('/creator/settings');
|
|
form.setFieldsValue(editableSettings(result));
|
|
} catch (loadError) {
|
|
setError(loadError);
|
|
} finally {
|
|
setPending(false);
|
|
}
|
|
}, [form]);
|
|
|
|
useEffect(() => {
|
|
load();
|
|
}, [load]);
|
|
|
|
async function save(values: any) {
|
|
setBusy(true);
|
|
try {
|
|
// 数值字段清空时归零,对齐归档版 Number('') 的提交语义;服务侧字段为必填数值。
|
|
const payload = Object.fromEntries(editableFields.map((field) => [field, numericFields.has(field) ? values[field] ?? 0 : values[field]]));
|
|
const result = await creatorUpdate('/creator/settings', payload);
|
|
form.setFieldsValue(editableSettings(result));
|
|
messageApi.success('采集与 AI 配置已保存。');
|
|
} catch (saveError) {
|
|
messageApi.error(conflictMessage(saveError, '设置保存失败'));
|
|
} finally {
|
|
setBusy(false);
|
|
}
|
|
}
|
|
|
|
if (pending) return <Card loading />;
|
|
if (error) return <Alert type="error" showIcon message={error.message} action={<Button size="small" onClick={load}>重试</Button>} />;
|
|
|
|
return (
|
|
<div>
|
|
{contextHolder}
|
|
<Typography.Paragraph type="secondary" style={{ marginBottom: 16 }}>按配置类别管理 UTC 采集窗口、指标采集和已批准的服务。</Typography.Paragraph>
|
|
<Card variant="outlined">
|
|
<Form form={form} layout="vertical" onFinish={save} initialValues={{}}>
|
|
<Tabs
|
|
items={[
|
|
{
|
|
key: 'collection',
|
|
label: '采集策略',
|
|
children: (
|
|
<div style={{ maxWidth: 640 }}>
|
|
<Form.Item name="lookback_days" label="竞品回溯天数" extra="首次回溯默认 30 天;不会猜测缺失发布时间。">
|
|
<InputNumber min={1} style={{ width: 200 }} />
|
|
</Form.Item>
|
|
<Form.Item name="new_work_interval_seconds" label="新作品/一级评论间隔(秒)">
|
|
<InputNumber min={1} style={{ width: 200 }} />
|
|
</Form.Item>
|
|
</div>
|
|
),
|
|
},
|
|
{
|
|
key: 'metrics',
|
|
label: '指标采集',
|
|
children: (
|
|
<div style={{ maxWidth: 640 }}>
|
|
<Form.Item name="metric_initial_interval_seconds" label="指标首次间隔(秒)">
|
|
<InputNumber min={1} style={{ width: 200 }} />
|
|
</Form.Item>
|
|
<Form.Item name="metric_multiplier" label="指标间隔倍数">
|
|
<InputNumber min={1.01} step={0.01} style={{ width: 200 }} />
|
|
</Form.Item>
|
|
<Form.Item name="metric_max_interval_seconds" label="指标最大间隔(秒)">
|
|
<InputNumber min={1} style={{ width: 200 }} />
|
|
</Form.Item>
|
|
<Form.Item name="metric_age_seconds" label="指标监测最长时长(秒)">
|
|
<InputNumber min={1} style={{ width: 200 }} />
|
|
</Form.Item>
|
|
</div>
|
|
),
|
|
},
|
|
{
|
|
key: 'ai',
|
|
label: 'AI 服务',
|
|
children: (
|
|
<div style={{ maxWidth: 640 }}>
|
|
<Form.Item name="ai_provider" label="AI Provider">
|
|
<Input />
|
|
</Form.Item>
|
|
<Form.Item name="ai_model" label="AI Model">
|
|
<Input />
|
|
</Form.Item>
|
|
<Form.Item name="ai_configured" valuePropName="checked">
|
|
<Checkbox>已完成 AI 配置审批</Checkbox>
|
|
</Form.Item>
|
|
</div>
|
|
),
|
|
},
|
|
{
|
|
key: 'transcription',
|
|
label: '转写服务',
|
|
children: (
|
|
<div style={{ maxWidth: 640 }}>
|
|
<Form.Item name="transcription_provider" label="转写 Provider">
|
|
<Input />
|
|
</Form.Item>
|
|
<Form.Item name="transcription_model" label="转写 Model">
|
|
<Input />
|
|
</Form.Item>
|
|
<Form.Item name="transcription_configured" valuePropName="checked">
|
|
<Checkbox>已完成转写配置审批</Checkbox>
|
|
</Form.Item>
|
|
</div>
|
|
),
|
|
},
|
|
]}
|
|
/>
|
|
<div style={{ display: 'flex', justifyContent: 'flex-end' }}>
|
|
<Button type="primary" htmlType="submit" loading={busy}>
|
|
{busy ? '保存中…' : '保存设置'}
|
|
</Button>
|
|
</div>
|
|
</Form>
|
|
</Card>
|
|
</div>
|
|
);
|
|
}
|