forked from b2894lxlx/tuanwei-admin
refactor(ai): 稿件与大纲页文案去掉接口术语与多余提示
面向学生的页面不再暴露实现细节: - 删除两页底部「提交说明」整块(含 `docType`/`inputs`、接口路径、 WebSocket 流式说明及对应样式) - 稿件页删除 `user_content`、`files` 字段说明;大纲页不再把 conversationId/messageId 拼成「接口摘要」展示,随之删除 buildSummary、resultSummary 及摘要渲染 - 加载态由三段式压成一行,空态与附件说明各留一句人话
This commit is contained in:
@@ -4,11 +4,7 @@
|
|||||||
<div>
|
<div>
|
||||||
<div class="hero-kicker">AI EVENT PLANNING OUTLINE</div>
|
<div class="hero-kicker">AI EVENT PLANNING OUTLINE</div>
|
||||||
<h1>活动策划大纲生成</h1>
|
<h1>活动策划大纲生成</h1>
|
||||||
<p>
|
<p>填写活动主题、受众、时间和预算,AI 给出一份结构完整的策划大纲,可直接改、复制或导出。</p>
|
||||||
输入活动主题、受众、时间和资金等信息,系统将调用
|
|
||||||
`/ai/activityOutlineGen`
|
|
||||||
生成结构化活动策划大纲,适合方案初稿、汇报材料和执行拆解场景。
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -91,13 +87,6 @@
|
|||||||
</a-button>
|
</a-button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="hint-block">
|
|
||||||
<div class="hint-title">提交说明</div>
|
|
||||||
<div class="hint-text">
|
|
||||||
必填字段会直接作为 `inputs` 透传给
|
|
||||||
AI,后端固定触发“活动策划大纲生成”指令,并返回整理后的正文结果。
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</a-card>
|
</a-card>
|
||||||
</a-col>
|
</a-col>
|
||||||
|
|
||||||
@@ -140,31 +129,19 @@
|
|||||||
|
|
||||||
<a-empty
|
<a-empty
|
||||||
v-if="!loading && !hasOutlineContent"
|
v-if="!loading && !hasOutlineContent"
|
||||||
description="填写左侧信息后开始生成活动策划大纲"
|
description="填写活动信息后开始生成"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div v-else class="result-shell">
|
<div v-else class="result-shell">
|
||||||
<div v-if="loading" class="loading-panel">
|
<div v-if="loading" class="loading-panel">
|
||||||
<div class="loading-kicker">OUTLINE GENERATING</div>
|
<div class="loading-title">正在生成活动策划大纲…</div>
|
||||||
<div class="loading-title">AI 正在整理活动策划结构</div>
|
|
||||||
<div class="loading-desc">
|
|
||||||
正在综合活动主题、受众、时间与经费信息,生成可直接二次编辑的策划大纲。
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-if="showThinkingIndicator" class="outline-thinking">
|
<div v-if="showThinkingIndicator" class="outline-thinking">
|
||||||
<span class="thinking-dot" aria-hidden="true"></span>
|
<span class="thinking-dot" aria-hidden="true"></span>
|
||||||
<span>AI 正在生成正文内容,请稍候...</span>
|
<span>正在生成正文…</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<a-alert
|
|
||||||
v-if="resultSummary"
|
|
||||||
class="result-alert"
|
|
||||||
type="info"
|
|
||||||
show-icon
|
|
||||||
:message="resultSummary"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<ByteMdEditor
|
<ByteMdEditor
|
||||||
v-if="hasOutlineContent"
|
v-if="hasOutlineContent"
|
||||||
v-model:value="editableOutlineMarkdown"
|
v-model:value="editableOutlineMarkdown"
|
||||||
@@ -236,7 +213,6 @@
|
|||||||
const result = ref<ActivityOutlineGenResponse | null>(null);
|
const result = ref<ActivityOutlineGenResponse | null>(null);
|
||||||
const outlineMarkdown = ref('');
|
const outlineMarkdown = ref('');
|
||||||
const editableOutlineMarkdown = ref('');
|
const editableOutlineMarkdown = ref('');
|
||||||
const resultSummary = ref('');
|
|
||||||
const activeConversationId = ref<string>();
|
const activeConversationId = ref<string>();
|
||||||
const activeMessageId = ref<string>();
|
const activeMessageId = ref<string>();
|
||||||
const webSocketRef = ref<WebSocket | null>(null);
|
const webSocketRef = ref<WebSocket | null>(null);
|
||||||
@@ -412,17 +388,6 @@
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const buildSummary = () => {
|
|
||||||
const parts = [] as string[];
|
|
||||||
if (activeConversationId.value) {
|
|
||||||
parts.push(`conversationId: ${activeConversationId.value}`);
|
|
||||||
}
|
|
||||||
if (activeMessageId.value) {
|
|
||||||
parts.push(`messageId: ${activeMessageId.value}`);
|
|
||||||
}
|
|
||||||
return parts.join(' | ');
|
|
||||||
};
|
|
||||||
|
|
||||||
const clearStreamResolver = () => {
|
const clearStreamResolver = () => {
|
||||||
streamResolverRef.value = null;
|
streamResolverRef.value = null;
|
||||||
};
|
};
|
||||||
@@ -485,7 +450,6 @@
|
|||||||
outlineMarkdown.value += chunk;
|
outlineMarkdown.value += chunk;
|
||||||
}
|
}
|
||||||
syncEditableOutline();
|
syncEditableOutline();
|
||||||
resultSummary.value = buildSummary() || '正在通过 WebSocket 接收流式内容';
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const finishStream = (conversationId?: string, messageId?: string) => {
|
const finishStream = (conversationId?: string, messageId?: string) => {
|
||||||
@@ -495,7 +459,6 @@
|
|||||||
if (messageId && messageId !== '0') {
|
if (messageId && messageId !== '0') {
|
||||||
activeMessageId.value = messageId;
|
activeMessageId.value = messageId;
|
||||||
}
|
}
|
||||||
resultSummary.value = buildSummary() || '已通过 WebSocket 接收生成结果';
|
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
resolveStream();
|
resolveStream();
|
||||||
disconnectWebSocket();
|
disconnectWebSocket();
|
||||||
@@ -512,7 +475,6 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (data?.loading === 'true' || data?.loading === true) {
|
if (data?.loading === 'true' || data?.loading === true) {
|
||||||
resultSummary.value = 'AI 正在组织活动策划大纲结构...';
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const chunk = pickRawString(data?.notice, data?.answer);
|
const chunk = pickRawString(data?.notice, data?.answer);
|
||||||
@@ -608,7 +570,6 @@
|
|||||||
result.value = null;
|
result.value = null;
|
||||||
outlineMarkdown.value = '';
|
outlineMarkdown.value = '';
|
||||||
editableOutlineMarkdown.value = '';
|
editableOutlineMarkdown.value = '';
|
||||||
resultSummary.value = '';
|
|
||||||
activeConversationId.value = undefined;
|
activeConversationId.value = undefined;
|
||||||
activeMessageId.value = undefined;
|
activeMessageId.value = undefined;
|
||||||
};
|
};
|
||||||
@@ -631,13 +592,11 @@
|
|||||||
}
|
}
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
clearResult();
|
clearResult();
|
||||||
resultSummary.value = '正在提交生成任务...';
|
|
||||||
try {
|
try {
|
||||||
// 一律走 HTTP 流式(/stream),不再先连 WebSocket:
|
// 一律走 HTTP 流式(/stream),不再先连 WebSocket:
|
||||||
// 触发生成的那个 POST 在整段生成期间是零字节的,会被链路上的 60s 空闲
|
// 触发生成的那个 POST 在整段生成期间是零字节的,会被链路上的 60s 空闲
|
||||||
// 超时掐成 504 Gateway Time-out。/stream 每 15s 有后端心跳续命。
|
// 超时掐成 504 Gateway Time-out。/stream 每 15s 有后端心跳续命。
|
||||||
const payload = buildPayload();
|
const payload = buildPayload();
|
||||||
resultSummary.value = '已提交生成任务,等待流式返回...';
|
|
||||||
const waitStream = createStreamWaiter();
|
const waitStream = createStreamWaiter();
|
||||||
await streamActivityOutlineGen(
|
await streamActivityOutlineGen(
|
||||||
payload as unknown as Record<string, unknown>,
|
payload as unknown as Record<string, unknown>,
|
||||||
@@ -895,27 +854,6 @@
|
|||||||
margin-top: 8px;
|
margin-top: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hint-block {
|
|
||||||
margin-top: 18px;
|
|
||||||
padding: 16px 18px;
|
|
||||||
border-radius: 16px;
|
|
||||||
background: #f6f9fe;
|
|
||||||
border: 1px solid #d9e6fb;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hint-title {
|
|
||||||
margin-bottom: 8px;
|
|
||||||
font-size: 13px;
|
|
||||||
font-weight: 600;
|
|
||||||
color: #274f84;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hint-text {
|
|
||||||
color: #5f6f84;
|
|
||||||
line-height: 1.8;
|
|
||||||
font-size: 13px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.result-card :deep(.ant-card-head) {
|
.result-card :deep(.ant-card-head) {
|
||||||
border-bottom: 1px solid #edf2f8;
|
border-bottom: 1px solid #edf2f8;
|
||||||
}
|
}
|
||||||
@@ -944,29 +882,12 @@
|
|||||||
border: 1px solid #d9e8fb;
|
border: 1px solid #d9e8fb;
|
||||||
}
|
}
|
||||||
|
|
||||||
.loading-kicker {
|
|
||||||
margin-bottom: 10px;
|
|
||||||
font-size: 12px;
|
|
||||||
letter-spacing: 0.18em;
|
|
||||||
color: #4875b0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.loading-title {
|
.loading-title {
|
||||||
font-size: 22px;
|
font-size: 18px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
color: #183b68;
|
color: #183b68;
|
||||||
}
|
}
|
||||||
|
|
||||||
.loading-desc {
|
|
||||||
margin-top: 10px;
|
|
||||||
line-height: 1.8;
|
|
||||||
color: #607086;
|
|
||||||
}
|
|
||||||
|
|
||||||
.result-alert {
|
|
||||||
border-radius: 14px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.outline-thinking {
|
.outline-thinking {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|||||||
@@ -4,10 +4,7 @@
|
|||||||
<div>
|
<div>
|
||||||
<div class="hero-kicker">AI CONTENT STUDIO</div>
|
<div class="hero-kicker">AI CONTENT STUDIO</div>
|
||||||
<h1>AI内容创作与宣传助手</h1>
|
<h1>AI内容创作与宣传助手</h1>
|
||||||
<p>
|
<p>写新闻稿、推文、发言稿,或直接说明你的需求,AI 先给出一份初稿,可以接着改。</p>
|
||||||
面向团委宣传、活动报道、新闻稿和推文草稿的快速生成场景。输入创作条件后,通过
|
|
||||||
`/ai/manuscriptGen` 发起生成任务,并通过 WebSocket 实时接收返回内容,支持继续编辑与复制。
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="hero-actions">
|
<div class="hero-actions">
|
||||||
<a-button type="primary" ghost @click="goChatPage">进入问答助手</a-button>
|
<a-button type="primary" ghost @click="goChatPage">进入问答助手</a-button>
|
||||||
@@ -41,9 +38,6 @@
|
|||||||
:auto-size="{ minRows: 6, maxRows: 12 }"
|
:auto-size="{ minRows: 6, maxRows: 12 }"
|
||||||
placeholder="例如:帮我写一段迎新晚会的主持人开场词,口语化一点,时长两分钟左右"
|
placeholder="例如:帮我写一段迎新晚会的主持人开场词,口语化一点,时长两分钟左右"
|
||||||
/>
|
/>
|
||||||
<div class="upload-tip">
|
|
||||||
不套模板时,这段内容会作为 `user_content` 交给「AI 创意助手」;选上面的文稿模板后可填写活动信息等可选参数。
|
|
||||||
</div>
|
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<template v-if="templateMode">
|
<template v-if="templateMode">
|
||||||
<a-form-item label="稿件标题">
|
<a-form-item label="稿件标题">
|
||||||
@@ -111,9 +105,6 @@
|
|||||||
上传附件
|
上传附件
|
||||||
</a-button>
|
</a-button>
|
||||||
</a-upload>
|
</a-upload>
|
||||||
<div class="upload-tip">
|
|
||||||
支持图片、文档等附件,上传后按 `files` 字段一并提交给接口。
|
|
||||||
</div>
|
|
||||||
<div v-if="uploadedFiles.length" class="file-list">
|
<div v-if="uploadedFiles.length" class="file-list">
|
||||||
<div
|
<div
|
||||||
v-for="(item, index) in uploadedFiles"
|
v-for="(item, index) in uploadedFiles"
|
||||||
@@ -145,15 +136,6 @@
|
|||||||
生成内容
|
生成内容
|
||||||
</a-button>
|
</a-button>
|
||||||
</div>
|
</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-card>
|
||||||
</a-col>
|
</a-col>
|
||||||
|
|
||||||
@@ -176,7 +158,7 @@
|
|||||||
</a-space>
|
</a-space>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<a-empty v-if="!markdownContent && !loading" description="填写左侧创作条件后开始生成" />
|
<a-empty v-if="!markdownContent && !loading" description="填写创作条件后开始生成" />
|
||||||
|
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<a-form layout="vertical">
|
<a-form layout="vertical">
|
||||||
@@ -201,11 +183,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-form>
|
</a-form>
|
||||||
|
|
||||||
<!-- <div v-if="responseSummary" class="response-meta">-->
|
|
||||||
<!-- <div class="meta-label">接口摘要</div>-->
|
|
||||||
<!-- <div class="meta-value">{{ responseSummary }}</div>-->
|
|
||||||
<!-- </div>-->
|
|
||||||
</template>
|
</template>
|
||||||
</a-card>
|
</a-card>
|
||||||
</a-col>
|
</a-col>
|
||||||
@@ -257,7 +234,6 @@
|
|||||||
interface ParsedResult {
|
interface ParsedResult {
|
||||||
title: string;
|
title: string;
|
||||||
content: string;
|
content: string;
|
||||||
summary: string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type DemoType = 'news' | 'wechat' | 'speech' | 'free';
|
type DemoType = 'news' | 'wechat' | 'speech' | 'free';
|
||||||
@@ -278,7 +254,6 @@
|
|||||||
const wsConnected = ref(false);
|
const wsConnected = ref(false);
|
||||||
const generatedTitle = ref('');
|
const generatedTitle = ref('');
|
||||||
const generatedContent = ref('');
|
const generatedContent = ref('');
|
||||||
const responseSummary = ref('');
|
|
||||||
const uploadedFiles = ref<Partial<FileRecord>[]>([]);
|
const uploadedFiles = ref<Partial<FileRecord>[]>([]);
|
||||||
const activeConversationId = ref<string>();
|
const activeConversationId = ref<string>();
|
||||||
const webSocketRef = ref<WebSocket | null>(null);
|
const webSocketRef = ref<WebSocket | null>(null);
|
||||||
@@ -458,8 +433,7 @@
|
|||||||
if (typeof payload === 'string') {
|
if (typeof payload === 'string') {
|
||||||
return {
|
return {
|
||||||
title: form.theme.trim(),
|
title: form.theme.trim(),
|
||||||
content: payload,
|
content: payload
|
||||||
summary: '接口直接返回文本内容'
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -468,8 +442,7 @@
|
|||||||
if (isFailedPayload(payload)) {
|
if (isFailedPayload(payload)) {
|
||||||
return {
|
return {
|
||||||
title: form.theme.trim(),
|
title: form.theme.trim(),
|
||||||
content: FAILED_TEXT,
|
content: FAILED_TEXT
|
||||||
summary: '上游工作流执行失败'
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -497,10 +470,6 @@
|
|||||||
payload.choices?.[0]?.message?.content
|
payload.choices?.[0]?.message?.content
|
||||||
);
|
);
|
||||||
|
|
||||||
const summary = Object.keys(payload).length
|
|
||||||
? `已解析返回字段:${Object.keys(payload).join('、')}`
|
|
||||||
: '返回对象为空';
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
title: title || form.theme.trim(),
|
title: title || form.theme.trim(),
|
||||||
// 不再 stringifyUnknown(payload):整包会带出 taskId / workflowRunId 等
|
// 不再 stringifyUnknown(payload):整包会带出 taskId / workflowRunId 等
|
||||||
@@ -509,8 +478,7 @@
|
|||||||
payload,
|
payload,
|
||||||
scope: 'gxmu/manuscriptGen.parseResult',
|
scope: 'gxmu/manuscriptGen.parseResult',
|
||||||
candidates: []
|
candidates: []
|
||||||
}),
|
})
|
||||||
summary
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -532,14 +500,10 @@
|
|||||||
return payload;
|
return payload;
|
||||||
};
|
};
|
||||||
|
|
||||||
const applyParsedResult = (
|
const applyParsedResult = (payload: ManuscriptGenResult) => {
|
||||||
payload: ManuscriptGenResult,
|
|
||||||
defaultSummary = '已通过 WebSocket 接收生成结果'
|
|
||||||
) => {
|
|
||||||
const parsed = parseResult(payload);
|
const parsed = parseResult(payload);
|
||||||
generatedTitle.value = parsed.title || generatedTitle.value || form.theme.trim();
|
generatedTitle.value = parsed.title || generatedTitle.value || form.theme.trim();
|
||||||
generatedContent.value = parsed.content;
|
generatedContent.value = parsed.content;
|
||||||
responseSummary.value = parsed.summary || defaultSummary;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const shouldTreatAsDirectResult = (payload: unknown) => {
|
const shouldTreatAsDirectResult = (payload: unknown) => {
|
||||||
@@ -620,7 +584,6 @@
|
|||||||
} else {
|
} else {
|
||||||
generatedContent.value += chunk;
|
generatedContent.value += chunk;
|
||||||
}
|
}
|
||||||
responseSummary.value = '正在通过 WebSocket 接收流式内容';
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const finishStream = (conversationId?: string) => {
|
const finishStream = (conversationId?: string) => {
|
||||||
@@ -628,7 +591,7 @@
|
|||||||
activeConversationId.value = conversationId;
|
activeConversationId.value = conversationId;
|
||||||
}
|
}
|
||||||
const payload = parseSerializedResult(generatedContent.value);
|
const payload = parseSerializedResult(generatedContent.value);
|
||||||
applyParsedResult(payload, '已通过 WebSocket 接收生成结果');
|
applyParsedResult(payload);
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
resolveStream();
|
resolveStream();
|
||||||
disconnectWebSocket();
|
disconnectWebSocket();
|
||||||
@@ -741,7 +704,6 @@
|
|||||||
const clearGenerated = () => {
|
const clearGenerated = () => {
|
||||||
generatedTitle.value = '';
|
generatedTitle.value = '';
|
||||||
generatedContent.value = '';
|
generatedContent.value = '';
|
||||||
responseSummary.value = '';
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const resetForm = () => {
|
const resetForm = () => {
|
||||||
@@ -850,7 +812,6 @@
|
|||||||
loading.value = true;
|
loading.value = true;
|
||||||
clearGenerated();
|
clearGenerated();
|
||||||
generatedTitle.value = form.theme.trim();
|
generatedTitle.value = form.theme.trim();
|
||||||
responseSummary.value = '正在提交生成任务...';
|
|
||||||
try {
|
try {
|
||||||
// 一律走 HTTP 流式(/stream),不再先连 WebSocket:
|
// 一律走 HTTP 流式(/stream),不再先连 WebSocket:
|
||||||
// 触发生成的那个 POST 在整段生成期间是零字节的,会被链路上的 60s 空闲
|
// 触发生成的那个 POST 在整段生成期间是零字节的,会被链路上的 60s 空闲
|
||||||
@@ -858,9 +819,6 @@
|
|||||||
// /stream 每 15s 有后端心跳续命,正文逐段喂给原来的帧处理,
|
// /stream 每 15s 有后端心跳续命,正文逐段喂给原来的帧处理,
|
||||||
// 结构化结果从末帧 {type:'final'} 取。
|
// 结构化结果从末帧 {type:'final'} 取。
|
||||||
const payload = buildPayload();
|
const payload = buildPayload();
|
||||||
responseSummary.value = templateMode.value
|
|
||||||
? '已提交生成任务,等待流式返回...'
|
|
||||||
: '自由创作已提交给 AI 创意助手,生成完成后一次性返回...';
|
|
||||||
const waitStream = createStreamWaiter();
|
const waitStream = createStreamWaiter();
|
||||||
const result = await runManuscriptGenStream(
|
const result = await runManuscriptGenStream(
|
||||||
payload as unknown as Record<string, unknown>,
|
payload as unknown as Record<string, unknown>,
|
||||||
@@ -871,8 +829,7 @@
|
|||||||
applyParsedResult(
|
applyParsedResult(
|
||||||
typeof result === 'string'
|
typeof result === 'string'
|
||||||
? parseSerializedResult(result)
|
? parseSerializedResult(result)
|
||||||
: (result as ManuscriptGenResult),
|
: (result as ManuscriptGenResult)
|
||||||
'接口直接返回生成结果'
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
// 兜底:流结束但没收到 __END__ 时也别把页面卡在加载中
|
// 兜底:流结束但没收到 __END__ 时也别把页面卡在加载中
|
||||||
@@ -1107,13 +1064,6 @@
|
|||||||
gap: 12px;
|
gap: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.upload-tip {
|
|
||||||
margin-top: 10px;
|
|
||||||
color: #5f7f9f;
|
|
||||||
font-size: 12px;
|
|
||||||
line-height: 1.7;
|
|
||||||
}
|
|
||||||
|
|
||||||
.file-list {
|
.file-list {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
@@ -1173,26 +1123,6 @@
|
|||||||
color: #1590ff;
|
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 {
|
.result-card {
|
||||||
min-height: 100%;
|
min-height: 100%;
|
||||||
}
|
}
|
||||||
@@ -1203,12 +1133,6 @@
|
|||||||
gap: 10px;
|
gap: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.response-meta {
|
|
||||||
padding: 12px 14px;
|
|
||||||
border-radius: 14px;
|
|
||||||
background: #f5fbff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.markdown-shell {
|
.markdown-shell {
|
||||||
min-height: 360px;
|
min-height: 360px;
|
||||||
border: 1px solid #c7e8ff;
|
border: 1px solid #c7e8ff;
|
||||||
@@ -1244,18 +1168,6 @@
|
|||||||
color: #1f2d3d;
|
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 {
|
.full-width {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user