mirror of
https://github.com/open-webui/open-webui.git
synced 2025-12-26 03:05:20 +00:00
fix: fix PDF export logic issue in ChatMenu
This commit is contained in:
parent
8a01727397
commit
e48246ad43
2 changed files with 23 additions and 39 deletions
|
|
@ -85,20 +85,19 @@
|
||||||
const downloadPdf = async () => {
|
const downloadPdf = async () => {
|
||||||
chat = await getChatById(localStorage.token, chatId);
|
chat = await getChatById(localStorage.token, chatId);
|
||||||
if (chat) {
|
if (chat) {
|
||||||
return;
|
await downloadChatPdf({
|
||||||
|
title: chat.chat.title,
|
||||||
|
stylizedPdfExport: $settings?.stylizedPdfExport ?? true,
|
||||||
|
chatText: await getChatAsText(chat),
|
||||||
|
async onBeforeRender() {
|
||||||
|
showFullMessages = true;
|
||||||
|
await tick();
|
||||||
|
},
|
||||||
|
onAfterRender() {
|
||||||
|
showFullMessages = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
await downloadChatPdf({
|
|
||||||
title: chat.chat.title,
|
|
||||||
stylizedPdfExport: $settings?.stylizedPdfExport ?? true,
|
|
||||||
chatText: await getChatAsText(chat),
|
|
||||||
async onBeforeRender() {
|
|
||||||
showFullMessages = true;
|
|
||||||
await tick();
|
|
||||||
},
|
|
||||||
onAfterRender() {
|
|
||||||
showFullMessages = false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const downloadJSONExport = async () => {
|
const downloadJSONExport = async () => {
|
||||||
|
|
|
||||||
|
|
@ -77,7 +77,7 @@ const isDarkMode = (): boolean => {
|
||||||
* @returns New jsPDF instance configured for A4 portrait orientation
|
* @returns New jsPDF instance configured for A4 portrait orientation
|
||||||
*/
|
*/
|
||||||
const createPdfDocument = async () => {
|
const createPdfDocument = async () => {
|
||||||
const { jsPDF } = await import('jspdf');
|
const { jsPDF } = await import('jspdf');
|
||||||
return new jsPDF('p', 'mm', 'a4');
|
return new jsPDF('p', 'mm', 'a4');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -87,11 +87,7 @@ const createPdfDocument = async () => {
|
||||||
* @param pageWidthMM - Page width in millimeters
|
* @param pageWidthMM - Page width in millimeters
|
||||||
* @param pageHeightMM - Page height in millimeters
|
* @param pageHeightMM - Page height in millimeters
|
||||||
*/
|
*/
|
||||||
const applyDarkModeBackground = (
|
const applyDarkModeBackground = (pdf: JSPDF, pageWidthMM: number, pageHeightMM: number): void => {
|
||||||
pdf: JSPDF,
|
|
||||||
pageWidthMM: number,
|
|
||||||
pageHeightMM: number
|
|
||||||
): void => {
|
|
||||||
if (isDarkMode()) {
|
if (isDarkMode()) {
|
||||||
pdf.setFillColor(0, 0, 0);
|
pdf.setFillColor(0, 0, 0);
|
||||||
pdf.rect(0, 0, pageWidthMM, pageHeightMM, 'F'); // black bg
|
pdf.rect(0, 0, pageWidthMM, pageHeightMM, 'F'); // black bg
|
||||||
|
|
@ -124,7 +120,7 @@ const renderElementToCanvas = async (
|
||||||
virtualWidth: number,
|
virtualWidth: number,
|
||||||
options?: RenderCanvasOptions
|
options?: RenderCanvasOptions
|
||||||
): Promise<HTMLCanvasElement> => {
|
): Promise<HTMLCanvasElement> => {
|
||||||
const { default: html2canvas } = await import('html2canvas-pro');
|
const { default: html2canvas } = await import('html2canvas-pro');
|
||||||
|
|
||||||
const isDark = isDarkMode();
|
const isDark = isDarkMode();
|
||||||
const canvasOptions: Record<string, unknown> = {
|
const canvasOptions: Record<string, unknown> = {
|
||||||
|
|
@ -187,17 +183,7 @@ const canvasToPdfWithSlicing = (
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw the slice of original canvas onto pageCanvas
|
// Draw the slice of original canvas onto pageCanvas
|
||||||
ctx.drawImage(
|
ctx.drawImage(canvas, 0, offsetY, canvas.width, sliceHeight, 0, 0, canvas.width, sliceHeight);
|
||||||
canvas,
|
|
||||||
0,
|
|
||||||
offsetY,
|
|
||||||
canvas.width,
|
|
||||||
sliceHeight,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
canvas.width,
|
|
||||||
sliceHeight
|
|
||||||
);
|
|
||||||
|
|
||||||
const imgData = pageCanvas.toDataURL('image/jpeg', JPEG_QUALITY);
|
const imgData = pageCanvas.toDataURL('image/jpeg', JPEG_QUALITY);
|
||||||
|
|
||||||
|
|
@ -293,10 +279,7 @@ const cloneElementForRendering = (element: HTMLElement, virtualWidth: number): H
|
||||||
* @param text - Plain text content to export
|
* @param text - Plain text content to export
|
||||||
* @param filename - Filename for the PDF file
|
* @param filename - Filename for the PDF file
|
||||||
*/
|
*/
|
||||||
const exportPlainTextToPdf = async (
|
const exportPlainTextToPdf = async (text: string, filename: string): Promise<void> => {
|
||||||
text: string,
|
|
||||||
filename: string
|
|
||||||
): Promise<void> => {
|
|
||||||
const doc = await createPdfDocument();
|
const doc = await createPdfDocument();
|
||||||
|
|
||||||
// Margins
|
// Margins
|
||||||
|
|
@ -357,7 +340,9 @@ export const downloadNotePdf = async (note: NoteData): Promise<void> => {
|
||||||
const node = createNoteNode(note, DEFAULT_VIRTUAL_WIDTH);
|
const node = createNoteNode(note, DEFAULT_VIRTUAL_WIDTH);
|
||||||
const htmlContent = note.data?.content?.html;
|
const htmlContent = note.data?.content?.html;
|
||||||
const shouldRemoveNode = !(
|
const shouldRemoveNode = !(
|
||||||
htmlContent && typeof htmlContent === 'object' && htmlContent instanceof HTMLElement
|
htmlContent &&
|
||||||
|
typeof htmlContent === 'object' &&
|
||||||
|
htmlContent instanceof HTMLElement
|
||||||
);
|
);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
@ -383,12 +368,12 @@ export const downloadNotePdf = async (note: NoteData): Promise<void> => {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Download PDF from chat (supports stylized and plain text modes)
|
* Download PDF from chat (supports stylized and plain text modes)
|
||||||
*
|
*
|
||||||
* Stylized mode: Renders the chat messages container as an image using html2canvas,
|
* Stylized mode: Renders the chat messages container as an image using html2canvas,
|
||||||
* then converts it to PDF with proper pagination.
|
* then converts it to PDF with proper pagination.
|
||||||
*
|
*
|
||||||
* Plain text mode: Exports chat content as plain text with basic formatting.
|
* Plain text mode: Exports chat content as plain text with basic formatting.
|
||||||
*
|
*
|
||||||
* @param options - Configuration object
|
* @param options - Configuration object
|
||||||
* @param options.containerElementId - ID of the container element to render (for stylized mode). Defaults to 'full-messages-container'
|
* @param options.containerElementId - ID of the container element to render (for stylized mode). Defaults to 'full-messages-container'
|
||||||
* @param options.chatText - Plain text content (required for plain text mode)
|
* @param options.chatText - Plain text content (required for plain text mode)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue