refactor(ai): 稿件与大纲页文案去掉接口术语与多余提示
面向学生的页面不再暴露实现细节: - 删除两页底部「提交说明」整块(含 `docType`/`inputs`、接口路径、 WebSocket 流式说明及对应样式) - 稿件页删除 `user_content`、`files` 字段说明;大纲页不再把 conversationId/messageId 拼成「接口摘要」展示,随之删除 buildSummary、resultSummary 及摘要渲染 - 加载态由三段式压成一行,空态与附件说明各留一句人话
This commit is contained in:
@@ -4,10 +4,7 @@
|
||||
<div>
|
||||
<div class="hero-kicker">AI CONTENT STUDIO</div>
|
||||
<h1>AI内容创作与宣传助手</h1>
|
||||
<p>
|
||||
面向团委宣传、活动报道、新闻稿和推文草稿的快速生成场景。输入创作条件后,通过
|
||||
`/ai/manuscriptGen` 发起生成任务,并通过 WebSocket 实时接收返回内容,支持继续编辑与复制。
|
||||
</p>
|
||||
<p>写新闻稿、推文、发言稿,或直接说明你的需求,AI 先给出一份初稿,可以接着改。</p>
|
||||
</div>
|
||||
<div class="hero-actions">
|
||||
<a-button type="primary" ghost @click="goChatPage">进入问答助手</a-button>
|
||||
@@ -41,9 +38,6 @@
|
||||
:auto-size="{ minRows: 6, maxRows: 12 }"
|
||||
placeholder="例如:帮我写一段迎新晚会的主持人开场词,口语化一点,时长两分钟左右"
|
||||
/>
|
||||
<div class="upload-tip">
|
||||
不套模板时,这段内容会作为 `user_content` 交给「AI 创意助手」;选上面的文稿模板后可填写活动信息等可选参数。
|
||||
</div>
|
||||
</a-form-item>
|
||||
<template v-if="templateMode">
|
||||
<a-form-item label="稿件标题">
|
||||
@@ -111,9 +105,6 @@
|
||||
上传附件
|
||||
</a-button>
|
||||
</a-upload>
|
||||
<div class="upload-tip">
|
||||
支持图片、文档等附件,上传后按 `files` 字段一并提交给接口。
|
||||
</div>
|
||||
<div v-if="uploadedFiles.length" class="file-list">
|
||||
<div
|
||||
v-for="(item, index) in uploadedFiles"
|
||||
@@ -145,15 +136,6 @@
|
||||
生成内容
|
||||
</a-button>
|
||||
</div>
|
||||
|
||||
<div class="hint-block">
|
||||
<div class="hint-title">提交说明</div>
|
||||
<div class="hint-text">
|
||||
未选模板(自由创作)时只提交一段内容,后端转「AI 创意助手」;选了模板才提交
|
||||
`docType` 等结构化条件。两种都会先 `POST /ai/manuscriptGen`,再按 `/ai` 页面的方式
|
||||
通过 WebSocket 流式接收生成结果;如果后端仍然直接返回正文,页面也会自动兼容解析。
|
||||
</div>
|
||||
</div>
|
||||
</a-card>
|
||||
</a-col>
|
||||
|
||||
@@ -176,7 +158,7 @@
|
||||
</a-space>
|
||||
</template>
|
||||
|
||||
<a-empty v-if="!markdownContent && !loading" description="填写左侧创作条件后开始生成" />
|
||||
<a-empty v-if="!markdownContent && !loading" description="填写创作条件后开始生成" />
|
||||
|
||||
<template v-else>
|
||||
<a-form layout="vertical">
|
||||
@@ -201,11 +183,6 @@
|
||||
</div>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
|
||||
<!-- <div v-if="responseSummary" class="response-meta">-->
|
||||
<!-- <div class="meta-label">接口摘要</div>-->
|
||||
<!-- <div class="meta-value">{{ responseSummary }}</div>-->
|
||||
<!-- </div>-->
|
||||
</template>
|
||||
</a-card>
|
||||
</a-col>
|
||||
@@ -257,7 +234,6 @@
|
||||
interface ParsedResult {
|
||||
title: string;
|
||||
content: string;
|
||||
summary: string;
|
||||
}
|
||||
|
||||
type DemoType = 'news' | 'wechat' | 'speech' | 'free';
|
||||
@@ -278,7 +254,6 @@
|
||||
const wsConnected = ref(false);
|
||||
const generatedTitle = ref('');
|
||||
const generatedContent = ref('');
|
||||
const responseSummary = ref('');
|
||||
const uploadedFiles = ref<Partial<FileRecord>[]>([]);
|
||||
const activeConversationId = ref<string>();
|
||||
const webSocketRef = ref<WebSocket | null>(null);
|
||||
@@ -458,8 +433,7 @@
|
||||
if (typeof payload === 'string') {
|
||||
return {
|
||||
title: form.theme.trim(),
|
||||
content: payload,
|
||||
summary: '接口直接返回文本内容'
|
||||
content: payload
|
||||
};
|
||||
}
|
||||
|
||||
@@ -468,8 +442,7 @@
|
||||
if (isFailedPayload(payload)) {
|
||||
return {
|
||||
title: form.theme.trim(),
|
||||
content: FAILED_TEXT,
|
||||
summary: '上游工作流执行失败'
|
||||
content: FAILED_TEXT
|
||||
};
|
||||
}
|
||||
|
||||
@@ -497,10 +470,6 @@
|
||||
payload.choices?.[0]?.message?.content
|
||||
);
|
||||
|
||||
const summary = Object.keys(payload).length
|
||||
? `已解析返回字段:${Object.keys(payload).join('、')}`
|
||||
: '返回对象为空';
|
||||
|
||||
return {
|
||||
title: title || form.theme.trim(),
|
||||
// 不再 stringifyUnknown(payload):整包会带出 taskId / workflowRunId 等
|
||||
@@ -509,8 +478,7 @@
|
||||
payload,
|
||||
scope: 'gxmu/manuscriptGen.parseResult',
|
||||
candidates: []
|
||||
}),
|
||||
summary
|
||||
})
|
||||
};
|
||||
};
|
||||
|
||||
@@ -532,14 +500,10 @@
|
||||
return payload;
|
||||
};
|
||||
|
||||
const applyParsedResult = (
|
||||
payload: ManuscriptGenResult,
|
||||
defaultSummary = '已通过 WebSocket 接收生成结果'
|
||||
) => {
|
||||
const applyParsedResult = (payload: ManuscriptGenResult) => {
|
||||
const parsed = parseResult(payload);
|
||||
generatedTitle.value = parsed.title || generatedTitle.value || form.theme.trim();
|
||||
generatedContent.value = parsed.content;
|
||||
responseSummary.value = parsed.summary || defaultSummary;
|
||||
};
|
||||
|
||||
const shouldTreatAsDirectResult = (payload: unknown) => {
|
||||
@@ -620,7 +584,6 @@
|
||||
} else {
|
||||
generatedContent.value += chunk;
|
||||
}
|
||||
responseSummary.value = '正在通过 WebSocket 接收流式内容';
|
||||
};
|
||||
|
||||
const finishStream = (conversationId?: string) => {
|
||||
@@ -628,7 +591,7 @@
|
||||
activeConversationId.value = conversationId;
|
||||
}
|
||||
const payload = parseSerializedResult(generatedContent.value);
|
||||
applyParsedResult(payload, '已通过 WebSocket 接收生成结果');
|
||||
applyParsedResult(payload);
|
||||
loading.value = false;
|
||||
resolveStream();
|
||||
disconnectWebSocket();
|
||||
@@ -741,7 +704,6 @@
|
||||
const clearGenerated = () => {
|
||||
generatedTitle.value = '';
|
||||
generatedContent.value = '';
|
||||
responseSummary.value = '';
|
||||
};
|
||||
|
||||
const resetForm = () => {
|
||||
@@ -850,7 +812,6 @@
|
||||
loading.value = true;
|
||||
clearGenerated();
|
||||
generatedTitle.value = form.theme.trim();
|
||||
responseSummary.value = '正在提交生成任务...';
|
||||
try {
|
||||
// 一律走 HTTP 流式(/stream),不再先连 WebSocket:
|
||||
// 触发生成的那个 POST 在整段生成期间是零字节的,会被链路上的 60s 空闲
|
||||
@@ -858,9 +819,6 @@
|
||||
// /stream 每 15s 有后端心跳续命,正文逐段喂给原来的帧处理,
|
||||
// 结构化结果从末帧 {type:'final'} 取。
|
||||
const payload = buildPayload();
|
||||
responseSummary.value = templateMode.value
|
||||
? '已提交生成任务,等待流式返回...'
|
||||
: '自由创作已提交给 AI 创意助手,生成完成后一次性返回...';
|
||||
const waitStream = createStreamWaiter();
|
||||
const result = await runManuscriptGenStream(
|
||||
payload as unknown as Record<string, unknown>,
|
||||
@@ -871,8 +829,7 @@
|
||||
applyParsedResult(
|
||||
typeof result === 'string'
|
||||
? parseSerializedResult(result)
|
||||
: (result as ManuscriptGenResult),
|
||||
'接口直接返回生成结果'
|
||||
: (result as ManuscriptGenResult)
|
||||
);
|
||||
}
|
||||
// 兜底:流结束但没收到 __END__ 时也别把页面卡在加载中
|
||||
@@ -1107,13 +1064,6 @@
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.upload-tip {
|
||||
margin-top: 10px;
|
||||
color: #5f7f9f;
|
||||
font-size: 12px;
|
||||
line-height: 1.7;
|
||||
}
|
||||
|
||||
.file-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@@ -1173,26 +1123,6 @@
|
||||
color: #1590ff;
|
||||
}
|
||||
|
||||
.hint-block {
|
||||
margin-top: 18px;
|
||||
padding: 14px 16px;
|
||||
border-radius: 14px;
|
||||
background: #f5fbff;
|
||||
border: 1px solid #c7e8ff;
|
||||
}
|
||||
|
||||
.hint-title {
|
||||
margin-bottom: 6px;
|
||||
font-weight: 600;
|
||||
color: #1590ff;
|
||||
}
|
||||
|
||||
.hint-text {
|
||||
color: #5f7f9f;
|
||||
line-height: 1.7;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.result-card {
|
||||
min-height: 100%;
|
||||
}
|
||||
@@ -1203,12 +1133,6 @@
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.response-meta {
|
||||
padding: 12px 14px;
|
||||
border-radius: 14px;
|
||||
background: #f5fbff;
|
||||
}
|
||||
|
||||
.markdown-shell {
|
||||
min-height: 360px;
|
||||
border: 1px solid #c7e8ff;
|
||||
@@ -1244,18 +1168,6 @@
|
||||
color: #1f2d3d;
|
||||
}
|
||||
|
||||
.meta-label {
|
||||
margin-bottom: 4px;
|
||||
font-weight: 600;
|
||||
color: #1f2d3d;
|
||||
}
|
||||
|
||||
.meta-value {
|
||||
color: #5f7f9f;
|
||||
line-height: 1.7;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.full-width {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user