Files
creator-hub/web/src/pages/creator/settings/index.tsx
T
rogee caf4b0fdcb
douyin-release-gate / verify (push) Failing after 3m49s
feat(web): 页面标题移至右上角、拆卡片嵌套、筛选与表格双卡片
- 布局:PageContainer extra 渲染标题+副标题(内容区右上角),卡内重复标题/副标题移除
- 详情页(账号/编辑/草稿/Attempt/环境/出口)外层 Card 拆除,区块卡平铺在灰底上
- 任务中心、竞品分析改为筛选卡+表格卡双卡片;工作台外层 Card 拆除,操作记录表包 Card
- 浏览器实测 13 个页面:0 嵌套卡片、表格均在 Card 内、标题无重复;生产构建通过
2026-09-23 08:42:31 +08:00

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>
);
}