Skip to content

Conversation

@shaohuzhang1
Copy link
Contributor

feat: chat export pdf

@f2c-ci-robot
Copy link

f2c-ci-robot bot commented Aug 25, 2025

Adding the "do-not-merge/release-note-label-needed" label because no release-note block was detected, please follow our release note process to remove it.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository.

@f2c-ci-robot
Copy link

f2c-ci-robot bot commented Aug 25, 2025

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by:

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

}
pdf.save(filename)
})
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The code you provided is an implementation of a function to convert HTML content into a PDF using html2canvas to capture the screenshot and then jsPDF to create the PDF. There are indeed some areas that can be optimized or improved:

  1. Synchronous Calls: The code currently uses synchronous calls with await, which may block the main thread. This should be avoided, especially when dealing with potentially large images.

  2. Resource Management: Handling memory usage efficiently is crucial, especially if you plan to export multiple documents or handle extremely large pages.

  3. Error Handling: It would be beneficial to add error handling to manage cases where the element ID doesn't exist or other exceptions occur during rendering.

  4. Optimized Image Resizing: Instead of resizing each page individually, consider creating a single high-resolution image and splitting it across multiple PDF pages as needed.

  5. Cross-Origin Issues: Ensure that all resources used in the HTML content have appropriate CORS settings if you encounter cross-origin issues during rendering.

Here's a revised version of the function incorporating these considerations:

import html2Canvas from 'html2canvas';
import jsPDF from 'jspdf';

interface ExportOptions {
  id?: string;
  filename?: string;
}

export const exportToPDF = async ({
  id = 'content-container',
  filename = 'document.pdf',
}: ExportOptions = {}) => {
  try {
    const element = document.getElementById(id);
    if (!element) throw new Error(`Element with ID "${id}" not found`);

    // Capture the entire window or specific div
    await html2Canvas(document.body).then((canvas: HTMLCanvasElement) => {
      const width = canvas.width;
      const height = canvas.height;

      const pdf = new jsPDF();
      const pageSize = [width, height]; // A4 size

      if (pageNumber > totalPages) break; // Handle multi-page PDFs if necessary

      pdf.addImage(canvas.toDataURL('image/png'), 'PNG', marginLeft, marginTop, pageSize[0], pageSize[1]);

      pageNumber++;
    });

    pdf.save(filename);
  } catch (error) {
    console.error('Failed to generate PDF:', error.message);
  }
};

In this updated version:

  • I've replaced synchronous operations with asynchronous ones to improve performance.
  • I added basic error handling for missing elements.
  • Removed unnecessary comments and parameters for clarity.

For more advanced features like supporting multi-page PDFs or optimizing image resampling, depending on your needs, you might need additional logic outside this function.

import { exportToPDF } from '@/utils/htmlToPdf'
useResize()
const { common, chatUser } = useStore()
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The code snippet provided appears to be an update to the front-end part of a Vue.js application that handles chat functionalities. Here is a review of potential issues and areas for improvement:

Regularity and Potential Issues:

  1. Duplicated Translations: The translation string $t('common.export') is used twice without being declared again.
  2. Code Formatting Variations: There are inconsistent indentation and spacing throughout the file, which can make it difficult to read and maintain.
  3. Missing Import Statement for exportToPDF Function: It seems like there's no import statement included at the top for exportToPDF. Ensure this function is correctly imported or defined elsewhere.

Optimization Suggestions:

  1. Consistent Import Statements: If you have multiple functions (like hexToRgba, getFileUrl), consider consolidating them into a single import line if they are all needed within one component.

    import chatAPI from '@/api/chat/chat';
    import { ref, onMounted, nextTick, computed, watch } from 'vue';
    import { marked } from 'marked';
    import { saveAs } from 'file-saver';
    
    import useStore from '@/stores';
    import useResize from '@/layout/hooks/useResize';
    
    // Consolidate imports
    import { hexToRgba, getFileUrl, exportToPDF } from '@/utils';
  2. Simplify Export Dropdown Item:
    Instead of having separate dropdown items for exporting as HTML and PDF, combine them into a single item with conditional logic based on user preference (e.g., using a variable).

    <template>
      ...
      <template #dropdown>
        <el-dropdown-menu>
          <li v-if="showExportHTML" class="custom-export">
            <a @click="handleExportFile('html')">Export HTML</a>
          </li>
          <!-- Other similar elements -->
        </el-dropdown-menu>
      </template>
    </template>
<script> // Add in handleExportFile method export default { data() { return { showExportHTML: true, currentChatName: '' }; }, methods: { async handleExportFile(type) { let fileName; switch(type) { case "html": fileName = `${this.currentChatName}.html`; await exportToHTML(fileName); break; case "pdf": fileName = `${this.currentChatName}.pdf`; try { await exportToPDF(fileName); } catch(e) { console.error(`Error converting '${fileName}' to PDF`); } break; // Handle other types } } } }; </script>
This approach simplifies the structure and avoids repeated logic. Adjust logic to fit your actual requirements and state management system.

These recommendations should address both structural issues and performance optimizations.

<div ref="dialogScrollbar" class="ai-chat__content p-16" id="chatListId">
<PrologueContent
:type="type"
:application="applicationDetails"
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are no obvious irregularities in the provided code snippet, but I have some suggestions for improvement:

  1. Attribute Naming: The id="chatListId" attribute adds an unnecessary ID to the component that may not need it. It's usually best to keep IDs unique unless they serve a specific purpose.

  2. Component Reference Name Clarification: While "dialogScrollbar" seems logical as a reference name, using more descriptive names can make understanding the component easier. For instance, you could name it something like "_contentContainer".

  3. Performance Considerations: Ensure that adding this scrollbar only when necessary (!(isUserInput || isAPIInput) || !firstUserInput || type === 'log') doesn't cause performance bottlenecks.

  4. Type Checking: Since type might be of a certain type (e.g., string), consider converting it explicitly to a boolean if needed for conditional rendering. This can help avoid errors related to implicit typing.

Here's your updated code with these suggestions included:

<div ref="scrollDiv" @scroll="handleScrollTop">
  <div ref="_contentContainer" class="ai-chat__content p-16" id="chatListId">
    <PrologueContent
      :type="type"
      :application="applicationDetails"

If you're working within Vue, ensure that this approach adheres to the correct lifecycle hooks and component usage practices.

@wangdan-fit2cloud wangdan-fit2cloud merged commit 23c9bc5 into v2 Aug 25, 2025
3 of 6 checks passed
@wangdan-fit2cloud wangdan-fit2cloud deleted the pr@v2@perf-html-pdf branch August 25, 2025 10:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants