feat(ai-writing): 支持用户粘贴已有大纲并按结构生成
表单可提交 userOutline,后端解析/归一用户大纲并关联素材;补充大纲测试用例与右侧编辑器滑词/段落菜单文档。
This commit is contained in:
1 parent
3b5525a0a5
commit
ab876fc7d8
10 files changed
+944
-3
No files matched your search
@@ -50,6 +50,8 @@ export function AIWritingForm({
|
||||
hideAdvancedFields = false,
|
||||
}: AIWritingFormProps) {
|
||||
const [intent, setIntent] = useState('');
|
||||
const [showOutline, setShowOutline] = useState(false);
|
||||
const [outlineText, setOutlineText] = useState('');
|
||||
const [articleType, setArticleType] = useState('analysis');
|
||||
const [audience, setAudience] = useState('普通读者');
|
||||
const [wordCountInput, setWordCountInput] = useState('800');
|
||||
@@ -115,6 +117,7 @@ export function AIWritingForm({
|
||||
const wordCount = Math.max(100, parseInt(wordCountInput, 10) || 800);
|
||||
onSubmit({
|
||||
userIntent: intent.trim(),
|
||||
userOutline: outlineText.trim() || undefined,
|
||||
articleType,
|
||||
targetAudience: hideAdvancedFields
|
||||
? DEFAULT_AUDIENCE
|
||||
@@ -155,6 +158,43 @@ export function AIWritingForm({
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="mt-4 space-y-2">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setShowOutline((v) => !v)}
|
||||
disabled={disabled}
|
||||
className="flex w-full items-center justify-between text-left"
|
||||
>
|
||||
<span className={FIELD_LABEL_CLASS}>
|
||||
已有大纲
|
||||
<span className="ml-1 text-sm font-normal text-muted-foreground dark:text-white/70">
|
||||
(可选)
|
||||
</span>
|
||||
</span>
|
||||
<span className="text-sm text-muted-foreground dark:text-white/70">
|
||||
{showOutline ? '收起 ▴' : '我已有大纲,直接粘贴 ▾'}
|
||||
</span>
|
||||
</button>
|
||||
{showOutline && (
|
||||
<>
|
||||
<Textarea
|
||||
placeholder={
|
||||
'粘贴你已有的大纲,将完全按你的大纲生成(支持一/二/三级目录)。例如:\n' +
|
||||
'一、引言\n(一)背景\n(二)意义\n二、现状分析\n…'
|
||||
}
|
||||
value={outlineText}
|
||||
onChange={(e) => setOutlineText(e.target.value)}
|
||||
disabled={disabled}
|
||||
rows={6}
|
||||
className="resize-none rounded-2xl border-[#e8dedd] bg-white px-4 py-3 text-sm leading-6 shadow-sm"
|
||||
/>
|
||||
<p className="text-xs leading-relaxed text-muted-foreground/80">
|
||||
填写后将跳过自动大纲规划,按你粘贴的大纲逐章生成;留空则由 AI 自动规划大纲。
|
||||
</p>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="mt-4 grid grid-cols-2 gap-4">
|
||||
<div className="min-w-0 space-y-2">
|
||||
<label className={FIELD_LABEL_CLASS}>文章类型</label>
|
||||
|
||||
@@ -259,6 +259,8 @@ export function AIWritingProvider({ children }: { children: ReactNode }) {
|
||||
await stream.submit(
|
||||
{
|
||||
user_intent: request.userIntent,
|
||||
// 用户自带大纲原文(留空则后端走自动规划)
|
||||
user_outline_raw: request.userOutline?.trim() || '',
|
||||
article_type: request.articleType,
|
||||
target_audience: request.targetAudience,
|
||||
word_count_target: request.wordCountTarget,
|
||||
|
||||
@@ -623,6 +623,7 @@ export function interruptToEvent(value: unknown, sessionId: string): ProgressEve
|
||||
|
||||
export type AIWritingValues = {
|
||||
user_intent?: string;
|
||||
user_outline_raw?: string;
|
||||
article_type?: string;
|
||||
status?: string;
|
||||
material_package?: unknown;
|
||||
|
||||
@@ -220,6 +220,8 @@ export interface UserInterventionPayload {
|
||||
|
||||
export interface AIWritingRequest {
|
||||
userIntent: string;
|
||||
/** 用户粘贴的「已有大纲」原文(可选)。非空时后端按此大纲生成,不再自动规划 */
|
||||
userOutline?: string;
|
||||
articleType: string;
|
||||
targetAudience: string;
|
||||
wordCountTarget: number;
|
||||
|
||||
Reference in new issue
Block a user