Repository: CherryHQ/cherry-studio (TypeScript)

Issue:
[讨论]: 将话题复制为markdown时的标题问题
### Issue 检查清单

- [x] 我理解 Issue 是用于反馈和解决问题的，而非吐槽评论区，将尽可能提供更多信息帮助问题解决。
- [x] 我确认自己需要的是提出问题并且讨论问题，而不是 Bug 反馈或需求建议。

### 平台

Windows

### 版本

1.5.3

### 您的问题

将话题复制为markdown时
🧑‍💻 User和🤖 Assistant应该是二级标题吧
现在是三级标题，和消息中的标题同级了

### 相关背景

_No response_

### 补充信息

```shell

```

### 优先级

低 (有空再看)


Discussion:

Patch:
diff --git a/src/renderer/src/utils/export.ts b/src/renderer/src/utils/export.ts
index 7f441ef1e33..bc7d9b20adf 100644
--- a/src/renderer/src/utils/export.ts
+++ b/src/renderer/src/utils/export.ts
@@ -169,7 +169,7 @@ const createBaseMarkdown = (
 ) => {
   const { forceDollarMathInMarkdown } = store.getState().settings
   const roleText = getRoleText(message.role, message.model?.name, message.model?.provider)
-  const titleSection = `### ${roleText}`
+  const titleSection = `## ${roleText}`
   let reasoningSection = ''
 
   if (includeReasoning) {


Test patch:
diff --git a/src/renderer/src/utils/__tests__/export.test.ts b/src/renderer/src/utils/__tests__/export.test.ts
index e3c5c4d16ea..da7cc668151 100644
--- a/src/renderer/src/utils/__tests__/export.test.ts
+++ b/src/renderer/src/utils/__tests__/export.test.ts
@@ -262,7 +262,7 @@ describe('export', () => {
         { type: MessageBlockType.MAIN_TEXT, content: '' }
       ])
       const markdown = messageToMarkdown(msgWithEmptyContent)
-      expect(markdown).toContain('### 🧑‍💻 User')
+      expect(markdown).toContain('## 🧑‍💻 User')
       // Should handle empty content gracefully
       expect(markdown).toBeDefined()
       expect(markdown.split('\n\n').filter((s) => s.trim()).length).toBeGreaterThanOrEqual(1)
@@ -272,11 +272,11 @@ describe('export', () => {
       const msg = mockedMessages.find((m) => m.id === 'u1')
       expect(msg).toBeDefined()
       const markdown = messageToMarkdown(msg!)
-      expect(markdown).toContain('### 🧑‍💻 User')
+      expect(markdown).toContain('## 🧑‍💻 User')
       expect(markdown).toContain('hello user')
 
       // The format is: [titleSection, '', contentSection, citation].join('\n')
-      // When citation is empty, we get: "### 🧑‍💻 User\n\nhello user\n"
+      // When citation is empty, we get: "## 🧑‍💻 User\n\nhello user\n"
       const sections = markdown.split('\n\n')
       expect(sections.length).toBeGreaterThanOrEqual(2) // title section and content section
     })
@@ -285,11 +285,11 @@ describe('export', () => {
       const msg = mockedMessages.find((m) => m.id === 'a1')
       expect(msg).toBeDefined()
       const markdown = messageToMarkdown(msg!)
-      expect(markdown).toContain('### 🤖 Assistant')
+      expect(markdown).toContain('## 🤖 Assistant')
       expect(markdown).toContain('hi assistant')
 
       // The format is: [titleSection, '', contentSection, citation].join('\n')
-      // When citation is empty, we get: "### 🤖 Assistant\n\nhi assistant\n"
+      // When citation is empty, we get: "## 🤖 Assistant\n\nhi assistant\n"
       const sections = markdown.split('\n\n')
       expect(sections.length).toBeGreaterThanOrEqual(2) // title section and content section
     })
@@ -298,7 +298,7 @@ describe('export', () => {
       const msg = createMessage({ role: 'user', id: 'u2' }, [])
       mockedMessages.push(msg)
       const markdown = messageToMarkdown(msg)
-      expect(markdown).toContain('### 🧑‍💻 User')
+      expect(markdown).toContain('## 🧑‍💻 User')
       // Check that it doesn't fail when no content exists
       expect(markdown).toBeDefined()
     })
@@ -309,7 +309,7 @@ describe('export', () => {
         { type: MessageBlockType.CITATION }
       ])
       const markdown = messageToMarkdown(msgWithCitation)
-      expect(markdown).toContain('### 🤖 Assistant')
+      expect(markdown).toContain('## 🤖 Assistant')
       expect(markdown).toContain('Main content')
       expect(markdown).toContain('[1] [https://example1.com](Example Citation 1)')
     })
@@ -341,7 +341,7 @@ describe('export', () => {
       const msg = mockedMessages.find((m) => m.id === 'a2')
       expect(msg).toBeDefined()
       const markdown = messageToMarkdownWithReasoning(msg!)
-      expect(markdown).toContain('### 🤖 Assistant')
+      expect(markdown).toContain('## 🤖 Assistant')
       expect(markdown).toContain('Main Answer')
       expect(markdown).toContain('<details')
       expect(markdown).toContain('<summary>common.reasoning_content</summary>')
@@ -366,7 +366,7 @@ describe('export', () => {
       const msg = mockedMessages.find((m) => m.id === 'a4')
       expect(msg).toBeDefined()
       const markdown = messageToMarkdownWithReasoning(msg!)
-      expect(markdown).toContain('### 🤖 Assistant')
+      expect(markdown).toContain('## 🤖 Assistant')
       expect(markdown).toContain('Simple Answer')
       expect(markdown).not.toContain('<details')
     })
@@ -375,7 +375,7 @@ describe('export', () => {
       const msg = mockedMessages.find((m) => m.id === 'a5')
       expect(msg).toBeDefined()
       const markdown = messageToMarkdownWithReasoning(msg!)
-      expect(markdown).toContain('### 🤖 Assistant')
+      expect(markdown).toContain('## 🤖 Assistant')
       expect(markdown).toContain('Answer with citation')
       expect(markdown).toContain('<details')
       expect(markdown).toContain('Some thinking')
@@ -1015,7 +1015,7 @@ describe('Citation formatting in Markdown export', () => {
     const markdown = messageToMarkdown(msgWithCitations)
 
     // Should contain the title and content
-    expect(markdown).toContain('### 🤖 Assistant')
+    expect(markdown).toContain('## 🤖 Assistant')
     expect(markdown).toContain('Content with citations')
 
     // Should include citation content (mocked by getCitationContent)