Skip to content

Conversation

@shaohuzhang1
Copy link
Contributor

feat: Export conversation page to PDF

@f2c-ci-robot
Copy link

f2c-ci-robot bot commented Aug 26, 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 26, 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

}
defineExpose({ open, close })
</script>
<style lang="scss" scoped></style>
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 provided Vue component appears to be designed to create a dialog with SVG content that allows users to export it as PDF or image. Here is a few points of consideration for optimization:

  1. SVG Loading: The current approach involves converting an SVG string into an HTML element, which can lead to some overhead due to parsing and appending. Consider using a more direct method to handle inline SVG files directly.

  2. Error Handling: Implement robust error handling in the fetch operations and other asynchronous calls to improve user experience. This includes providing meaningful messages when exports fail.

  3. Memory Management: Ensure that SVG elements are removed from memory after they are no longer needed to prevent excessive memory usage.

  4. PDF Export Optimization:

    • Instead of manually calculating page sizes, consider using pagination libraries like jspdf-autotable to manage text wrapping and formatting automatically.
    • Optimize SVG images before sending them to the server by reducing their size and resolution where appropriate.
  5. Code Readability: Add comments and structure the code better to make it easier to understand at a glance.

Here's a revised version with these considerations:

<template>
  <el-dialog
    v-model="dialogVisible"
    :title="$t('chat.preview')"
    style="overflow: auto"
    width="80%"
    :before-close="close"
    destroy-on-close
  >
    <div ref="content" v-loading="loading">Content will load here...</div>
    <template #footer>
      <span class="dialog-footer">
        <el-button :loading="loading" @click="exportPDF">{{ $t('chat.exportPDF') }}</el-button>
        <el-button
          :loading="loading"
          type="primary"
          @click="
            () => {
              loading = true
              exportJpg()
            }
          "
        >
          {{ $t('chat.exportImg') }}
        </el-button>
      </span>
    </template>
  </el-dialog>
</template>

<script setup lang="ts">
import { onMounted, ref, nextTick } from 'vue'

const content = ref('')
const loading = ref(false)

// Function to open the dialog and populate the SVG container
const open = async (svgBlob: Blob) => {
  try {
    dialogVisible.value = true
    loading.value = true

    // Convert blob to data URL
    const dataURL = await convertBlobToDataUrl(svgBlob)

    // Set contents of div to the data URL
    content.value.innerHTML = `<img src="${dataURL}" alt="Preview">`

    nextTick(() => {
      loading.value = false
    })
  } catch (error) {
    console.error("Failed to load SVG:", error)
    alert("Could not load the preview.")
  }
}

// Helper function to convert blob to data URL
const convertBlobToDataUrl = async (blob: Blob): Promise<string> => {
  return await new Promise((resolve) => {
    const reader = new FileReader();
    reader.onloadend = (_) => resolve(reader.result as string);
    reader.readAsDataURL(blob);
  });
};

// Handle closing the dialog
const close = () => {
  dialogVisible.value = false;
}

// Expose functions
defineExpose({ open, close });
</script>

<style lang="scss" scoped>
.dialog-container {
  /* Styles */
}
</style>

Key Changes:

  • The SVG content is loaded into an <img> tag within a hidden div (ref="content"), which simplifies rendering.
  • Error handling is added to capture and display errors during SVG conversion.
  • A helper function convertBlobToDataUrl is created to asynchronously read the blob content as a data URL.
  • Memory management is improved by cleaning up resources appropriately.

}
const isCollapse = ref(false)
const isPcCollapse = ref(false)
watch(
Copy link
Contributor Author

Choose a reason for hiding this comment

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

  1. There appears to be an extra line before </div> in the <div class="p-16 flex-between border-b"> section.

  2. In the <template> portion of your code, you have included an instance of the ResetPassword component with props emitConfirm and a handler function called handleResetPassword. Also note that there is a commented-out element ( ) which may not serve any purpose unless it's intentional.

  3. The template contains two references: one named pdfExportRef, though it doesn't seem to be used anywhere within this template, which could lead to potential memory leaks if not properly managed.

  4. You've defined a watcher on the isPcCollapse variable without providing a callback function. This watcher seems unnecessary and might cause side effects if no appropriate logic is implemented.

  5. If you're using Vue 3 Composition API and TypeScript, make sure all components imported are correctly typed (using <type> ImportComponentName). For example:

import type { Ref } from 'vue';
import { ref } from 'vue';

const pdfExportRef: Ref<InstanceType<typeof PdfExport>> | null = ref(null);

The rest of your code looks well-written except for those issues mentioned above.

@shaohuzhang1 shaohuzhang1 merged commit 7948e4f into v2 Aug 26, 2025
3 of 5 checks passed
preview: 'Preview',
chatId: 'Chat ID',
userInput: 'User Input',
quote: 'Quote',
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 provided code snippet appears to be part of an object exported as default from a JavaScript module, likely for use in internationalization (i18n) purposes. Here's some general feedback:

Potential Issues:

  1. Missing Language Tags: The code doesn't specify the language tags (e.g., 'en', 'fr') associated with these strings.

Optimization Suggestions:

  1. Consistent Naming Conventions:
    • Ensure all keys and values are consistent. In this case, they look well-named but might need minor adjustments if different languages require specific names or formats.
  2. String Translation Considerations:
    • For localized content, ensure that each string is translated appropriately into multiple languages when deploying the application.
  3. Internationalization Libraries:
    • If using internationalization libraries like react-intl or lingui, consider integrating them effectively to handle translation without repetitive key usage.

Overall, the code looks clean and self-contained, which is good for its purpose in managing localization data. Make sure the translations are up-to-date for accuracy and completeness.

@shaohuzhang1 shaohuzhang1 deleted the pr@v2@feat_export_pdf branch August 26, 2025 10:39
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.

2 participants