Skip to content

Commit 23c9bc5

Browse files
feat: chat export pdf (#3931)
Co-authored-by: wangdan-fit2cloud <[email protected]>
1 parent deb7333 commit 23c9bc5

File tree

7 files changed

+99
-4
lines changed

7 files changed

+99
-4
lines changed

ui/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@
3232
"element-plus": "^2.10.2",
3333
"file-saver": "^2.0.5",
3434
"highlight.js": "^11.11.1",
35+
"html2canvas": "^1.4.1",
36+
"jspdf": "^3.0.1",
3537
"katex": "^0.16.10",
3638
"marked": "^12.0.2",
3739
"md-editor-v3": "^5.8.2",

ui/src/assets/logo/logo.png

7.96 KB
Loading

ui/src/assets/logo/logo.svg

Lines changed: 35 additions & 1 deletion
Loading

ui/src/components/ai-chat/index.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
</div>
2727
<template v-if="!(isUserInput || isAPIInput) || !firsUserInput || type === 'log'">
2828
<el-scrollbar ref="scrollDiv" @scroll="handleScrollTop">
29-
<div ref="dialogScrollbar" class="ai-chat__content p-16">
29+
<div ref="dialogScrollbar" class="ai-chat__content p-16" id="chatListId">
3030
<PrologueContent
3131
:type="type"
3232
:application="applicationDetails"

ui/src/components/logo/LogoIcon.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
d="M166.8344,48.8968H65.6064A33.7544,33.7544,0,0,0,31.89,82.6131v57.07A33.7548,33.7548,0,0,0,65.6064,173.4h101.228a33.7549,33.7549,0,0,0,33.7168-33.7168v-57.07A33.7545,33.7545,0,0,0,166.8344,48.8968Zm2.831,90.4457a6.0733,6.0733,0,0,1-6.0732,6.0733H114.2168a43.5922,43.5922,0,0,0-21.3313,5.5757l-16.5647,9.2946v-14.87h-7.472a6.0733,6.0733,0,0,1-6.0733-6.0733v-60.5a6.0733,6.0733,0,0,1,6.0733-6.0733h94.7434a6.0733,6.0733,0,0,1,6.0732,6.0733Z"
3333
/>
3434
</svg>
35-
<img v-else src="@/assets/logo/logo.svg" :height="height" />
35+
<img v-else src="@/assets/logo/logo.png" :height="height" />
3636
</template>
3737
<script setup lang="ts">
3838
import { ref, computed, onMounted } from 'vue'

ui/src/utils/htmlToPdf.ts

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import html2Canvas from 'html2canvas'
2+
import jsPDF from 'jspdf'
3+
4+
export const exportToPDF = async (elementId: string, filename = 'document.pdf') => {
5+
const element = document.getElementById(elementId)
6+
if (!element) return
7+
await html2Canvas(element, {
8+
useCORS: true,
9+
allowTaint: true,
10+
logging: false,
11+
scale: 2,
12+
backgroundColor: '#fff',
13+
}).then((canvas: any) => {
14+
const pdf = new jsPDF('p', 'mm', 'a4')
15+
const pageWidth = 190 // 保留边距后的有效宽度
16+
const pageHeight = 277 // 保留边距后的有效高度 //A4大小,210mm x 297mm,四边各保留10mm的边距,显示区域190x277
17+
const imgHeight = (pageHeight * canvas.width) / pageWidth
18+
19+
let renderedHeight = 0
20+
while (renderedHeight < canvas.height) {
21+
const pageCanvas = document.createElement('canvas')
22+
pageCanvas.width = canvas.width
23+
pageCanvas.height = Math.min(imgHeight, canvas.height - renderedHeight)
24+
25+
pageCanvas
26+
.getContext('2d')!
27+
.putImageData(
28+
canvas
29+
.getContext('2d')!
30+
.getImageData(
31+
0,
32+
renderedHeight,
33+
canvas.width,
34+
Math.min(imgHeight, canvas.height - renderedHeight),
35+
),
36+
0,
37+
0,
38+
)
39+
40+
pdf.addImage(
41+
pageCanvas.toDataURL('image/jpeg', 1.0),
42+
'JPEG',
43+
10,
44+
10, // 左边距和上边距
45+
pageWidth,
46+
Math.min(pageHeight, (pageWidth * pageCanvas.height) / pageCanvas.width),
47+
)
48+
49+
renderedHeight += imgHeight
50+
if (renderedHeight < canvas.height) {
51+
pdf.addPage()
52+
}
53+
}
54+
pdf.save(filename)
55+
})
56+
}

ui/src/views/chat/pc/index.vue

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,9 @@
139139
<el-dropdown-item @click="exportHTML"
140140
>{{ $t('common.export') }} HTML</el-dropdown-item
141141
>
142+
<el-dropdown-item @click="exportToPDF('chatListId', currentChatName + '.pdf')"
143+
>{{ $t('common.export') }} PDF</el-dropdown-item
144+
>
142145
</el-dropdown-menu>
143146
</template>
144147
</el-dropdown>
@@ -222,7 +225,6 @@ import { ref, onMounted, nextTick, computed, watch } from 'vue'
222225
import { marked } from 'marked'
223226
import { saveAs } from 'file-saver'
224227
import chatAPI from '@/api/chat/chat'
225-
226228
import useStore from '@/stores'
227229
import useResize from '@/layout/hooks/useResize'
228230
import { hexToRgba } from '@/utils/theme'
@@ -236,6 +238,7 @@ import ParagraphDocumentContent from '@/components/ai-chat/component/knowledge-s
236238
import HistoryPanel from '@/views/chat/component/HistoryPanel.vue'
237239
import { cloneDeep } from 'lodash'
238240
import { getFileUrl } from '@/utils/common'
241+
import { exportToPDF } from '@/utils/htmlToPdf'
239242
useResize()
240243
241244
const { common, chatUser } = useStore()

0 commit comments

Comments
 (0)