mirror of
https://gitee.com/wanwujie/deer-flow
synced 2026-04-13 10:24:44 +08:00
feat: 改进设置页面UI和国际化支持 / Improve settings pages UI and i18n support
- 添加 rehype-raw 依赖以支持在 markdown 中渲染 HTML Add rehype-raw dependency to support HTML rendering in markdown - 重构 memory-settings-page,提取 formatMemorySection 函数减少重复代码 Refactor memory-settings-page by extracting formatMemorySection function to reduce code duplication - 改进空状态显示,使用 HTML span 标签替代 markdown 斜体,提供更好的样式控制 Improve empty state display by using HTML span tags instead of markdown italics for better style control - 为 skill-settings-page 添加完整的国际化支持,替换硬编码的英文文本 Add complete i18n support for skill-settings-page, replacing hardcoded English text - 更新国际化文件,添加技能设置页面的空状态文本(中英文) Update i18n files with empty state text for skill settings page (both Chinese and English) - 在 streamdown 插件配置中添加 rehypeRaw 以支持 HTML 渲染 Add rehypeRaw to streamdown plugins configuration to support HTML rendering Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -31,6 +31,26 @@ function confidenceToLevelKey(confidence: unknown): {
|
||||
return { key: "normal", value };
|
||||
}
|
||||
|
||||
function formatMemorySection(
|
||||
title: string,
|
||||
summary: string,
|
||||
updatedAt: string | undefined,
|
||||
t: ReturnType<typeof useI18n>["t"],
|
||||
): string {
|
||||
const content =
|
||||
summary.trim() ||
|
||||
`<span class="text-muted-foreground">${t.settings.memory.markdown.empty}</span>`;
|
||||
return [
|
||||
`### ${title}`,
|
||||
content,
|
||||
"",
|
||||
updatedAt &&
|
||||
`> ${t.settings.memory.markdown.updatedAt}: \`${formatTimeAgo(updatedAt)}\``,
|
||||
]
|
||||
.filter(Boolean)
|
||||
.join("\n");
|
||||
}
|
||||
|
||||
function memoryToMarkdown(
|
||||
memory: UserMemory,
|
||||
t: ReturnType<typeof useI18n>["t"],
|
||||
@@ -44,65 +64,61 @@ function memoryToMarkdown(
|
||||
|
||||
parts.push(`\n## ${t.settings.memory.markdown.userContext}`);
|
||||
parts.push(
|
||||
[
|
||||
`### ${t.settings.memory.markdown.work}`,
|
||||
memory.user.workContext.summary || "-",
|
||||
"",
|
||||
memory.user.workContext.updatedAt &&
|
||||
`> ${t.settings.memory.markdown.updatedAt}: \`${formatTimeAgo(memory.user.workContext.updatedAt)}\``,
|
||||
].join("\n"),
|
||||
formatMemorySection(
|
||||
t.settings.memory.markdown.work,
|
||||
memory.user.workContext.summary,
|
||||
memory.user.workContext.updatedAt,
|
||||
t,
|
||||
),
|
||||
);
|
||||
parts.push(
|
||||
[
|
||||
`### ${t.settings.memory.markdown.personal}`,
|
||||
memory.user.personalContext.summary || "-",
|
||||
"",
|
||||
memory.user.personalContext.updatedAt &&
|
||||
`> ${t.settings.memory.markdown.updatedAt}: \`${formatTimeAgo(memory.user.personalContext.updatedAt)}\``,
|
||||
].join("\n"),
|
||||
formatMemorySection(
|
||||
t.settings.memory.markdown.personal,
|
||||
memory.user.personalContext.summary,
|
||||
memory.user.personalContext.updatedAt,
|
||||
t,
|
||||
),
|
||||
);
|
||||
parts.push(
|
||||
[
|
||||
`### ${t.settings.memory.markdown.topOfMind}`,
|
||||
memory.user.topOfMind.summary || "-",
|
||||
"",
|
||||
memory.user.topOfMind.updatedAt &&
|
||||
`> ${t.settings.memory.markdown.updatedAt}: \`${formatTimeAgo(memory.user.topOfMind.updatedAt)}\``,
|
||||
].join("\n"),
|
||||
formatMemorySection(
|
||||
t.settings.memory.markdown.topOfMind,
|
||||
memory.user.topOfMind.summary,
|
||||
memory.user.topOfMind.updatedAt,
|
||||
t,
|
||||
),
|
||||
);
|
||||
|
||||
parts.push(`\n## ${t.settings.memory.markdown.historyBackground}`);
|
||||
parts.push(
|
||||
[
|
||||
`### ${t.settings.memory.markdown.recentMonths}`,
|
||||
memory.history.recentMonths.summary || "-",
|
||||
"",
|
||||
memory.history.recentMonths.updatedAt &&
|
||||
`> ${t.settings.memory.markdown.updatedAt}: \`${formatTimeAgo(memory.history.recentMonths.updatedAt)}\``,
|
||||
].join("\n"),
|
||||
formatMemorySection(
|
||||
t.settings.memory.markdown.recentMonths,
|
||||
memory.history.recentMonths.summary,
|
||||
memory.history.recentMonths.updatedAt,
|
||||
t,
|
||||
),
|
||||
);
|
||||
parts.push(
|
||||
[
|
||||
`### ${t.settings.memory.markdown.earlierContext}`,
|
||||
memory.history.earlierContext.summary || "-",
|
||||
"",
|
||||
memory.history.earlierContext.updatedAt &&
|
||||
`> ${t.settings.memory.markdown.updatedAt}: \`${formatTimeAgo(memory.history.earlierContext.updatedAt)}\``,
|
||||
].join("\n"),
|
||||
formatMemorySection(
|
||||
t.settings.memory.markdown.earlierContext,
|
||||
memory.history.earlierContext.summary,
|
||||
memory.history.earlierContext.updatedAt,
|
||||
t,
|
||||
),
|
||||
);
|
||||
parts.push(
|
||||
[
|
||||
`### ${t.settings.memory.markdown.longTermBackground}`,
|
||||
memory.history.longTermBackground.summary || "-",
|
||||
"",
|
||||
memory.history.longTermBackground.updatedAt &&
|
||||
`> ${t.settings.memory.markdown.updatedAt}: \`${formatTimeAgo(memory.history.longTermBackground.updatedAt)}\``,
|
||||
].join("\n"),
|
||||
formatMemorySection(
|
||||
t.settings.memory.markdown.longTermBackground,
|
||||
memory.history.longTermBackground.summary,
|
||||
memory.history.longTermBackground.updatedAt,
|
||||
t,
|
||||
),
|
||||
);
|
||||
|
||||
parts.push(`\n## ${t.settings.memory.markdown.facts}`);
|
||||
if (memory.facts.length === 0) {
|
||||
parts.push(`_${t.settings.memory.markdown.empty}_`);
|
||||
parts.push(
|
||||
`<span class="text-muted-foreground">${t.settings.memory.markdown.empty}</span>`,
|
||||
);
|
||||
} else {
|
||||
parts.push(
|
||||
[
|
||||
|
||||
@@ -115,20 +115,20 @@ function SkillSettingsList({
|
||||
}
|
||||
|
||||
function EmptySkill({ onCreateSkill }: { onCreateSkill: () => void }) {
|
||||
const { t } = useI18n();
|
||||
return (
|
||||
<Empty>
|
||||
<EmptyHeader>
|
||||
<EmptyMedia variant="icon">
|
||||
<SparklesIcon />
|
||||
</EmptyMedia>
|
||||
<EmptyTitle>No agent skill yet</EmptyTitle>
|
||||
<EmptyTitle>{t.settings.skills.emptyTitle}</EmptyTitle>
|
||||
<EmptyDescription>
|
||||
Put your agent skill folders under the `/skills/custom` folder under
|
||||
the root folder of DeerFlow.
|
||||
{t.settings.skills.emptyDescription}
|
||||
</EmptyDescription>
|
||||
</EmptyHeader>
|
||||
<EmptyContent>
|
||||
<Button onClick={onCreateSkill}>Create Your First Skill</Button>
|
||||
<Button onClick={onCreateSkill}>{t.settings.skills.emptyButton}</Button>
|
||||
</EmptyContent>
|
||||
</Empty>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user