AI CONTENT STUDIO
AI内容创作与宣传助手
-
- 面向团委宣传、活动报道、新闻稿和推文草稿的快速生成场景。输入创作条件后,通过
- `/ai/manuscriptGen` 发起生成任务,并通过 WebSocket 实时接收返回内容,支持继续编辑与复制。
-
+
写新闻稿、推文、发言稿,或直接说明你的需求,AI 先给出一份初稿,可以接着改。
进入问答助手
@@ -41,9 +38,6 @@
:auto-size="{ minRows: 6, maxRows: 12 }"
placeholder="例如:帮我写一段迎新晚会的主持人开场词,口语化一点,时长两分钟左右"
/>
-
- 不套模板时,这段内容会作为 `user_content` 交给「AI 创意助手」;选上面的文稿模板后可填写活动信息等可选参数。
-
@@ -111,9 +105,6 @@
上传附件
-
- 支持图片、文档等附件,上传后按 `files` 字段一并提交给接口。
-
-
-
-
提交说明
-
- 未选模板(自由创作)时只提交一段内容,后端转「AI 创意助手」;选了模板才提交
- `docType` 等结构化条件。两种都会先 `POST /ai/manuscriptGen`,再按 `/ai` 页面的方式
- 通过 WebSocket 流式接收生成结果;如果后端仍然直接返回正文,页面也会自动兼容解析。
-
-
@@ -176,7 +158,7 @@
-
+
@@ -201,11 +183,6 @@
-
-
-
-
-
@@ -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
[]>([]);
const activeConversationId = ref();
const webSocketRef = ref(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,
@@ -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%;
}