如何在 React.js [关闭] 中创建一个按钮来生成页面中所有内容的 pdf 文件

How to create a button that generates a pdf file of everything in the page in React.js [closed]

提问人:NotprQn 提问时间:11/17/2023 更新时间:11/17/2023 访问量:15

问:


想改进这个问题吗?通过编辑这篇文章添加详细信息并澄清问题。

3天前关闭。

import React, { useState, useRef } from 'react';
import Modal from 'react-modal';
import './App.css';

function App() {
  const [scenarios, setScenarios] = useState([]);
  const [images, setImages] = useState([]);
  const [editing, setEditing] = useState(null);
  const [modalIsOpen, setModalIsOpen] = useState(false);

  const [title, setTitle] = useState('Titulo: ');
  const [given, setGiven] = useState('Dado que ');
  const [when, setWhen] = useState('Quando ');
  const [and, setAnd] = useState('E ');
  const [then, setThen] = useState('Então ');

  const inputRef = useRef([]);

  const openModal = () => {
    setTitle(`CT${scenarios.length + 1}: `);
    setModalIsOpen(true);
  };

  const closeModal = () => {
    setModalIsOpen(false);
  };

  const handleImageUpload = (e) => {
    const files = Array.from(e.target.files);
    const newImages = files.map(file => URL.createObjectURL(file));
    setImages(oldImages => [...oldImages, ...newImages]);
  };

  const handleAddScenario = () => {
    if (given.trim() === '' || when.trim() === '' || and.trim() === '' || then.trim() === '') {
      alert('Please fill in all the textareas.');
      return;
    }
  
    const scenario = {
      title,
      given,
      when,
      and,
      then,
      images,
    };
  
    if (editing !== null) {
      const newScenarios = [...scenarios];
      newScenarios[editing] = scenario;
      setScenarios(newScenarios);
      setEditing(null);
    } else {
      setScenarios(oldScenarios => [...oldScenarios, scenario]);
      setTitle(`CT ${scenarios.length + 2}: `);
    }
    setGiven('Dado que ');
    setWhen('Quando ');
    setAnd('E ');
    setThen('Então ');
    setImages([]);
    setModalIsOpen(false);
  };

  const handleTextChange = (e, index, field) => {
    const text = e.target.value;
    const newScenarios = [...scenarios];
  
    if (index >= 0 && index < newScenarios.length) {
      newScenarios[index][field] = text;
      setScenarios(newScenarios);
    } else {
      console.error(`Invalid index: ${index}`);
    }
  };

  const handleRemoveImage = (scenarioIndex, imageIndex) => {
    const newScenarios = [...scenarios];
    newScenarios[scenarioIndex].images.splice(imageIndex, 1);
    setScenarios(newScenarios);
  };

  const handleImageChange = (e, scenarioIndex, imageIndex) => {
    const file = e.target.files[0];
    const reader = new FileReader();
    reader.onloadend = () => {
      const newScenarios = [...scenarios];
      newScenarios[scenarioIndex].images[imageIndex] = reader.result;
      setScenarios(newScenarios);
    };
    reader.readAsDataURL(file);
  };

  const handleRemoveScenario = (index) => {
    const newScenarios = [...scenarios];
    newScenarios.splice(index, 1);
    setScenarios(newScenarios);
  };

 
  return (
    
    <div className="App">
      
      <Modal
        isOpen={modalIsOpen}
        onRequestClose={closeModal}
        contentLabel="Create Scenario"
      >
        <textarea 
          value={title} 
          onChange={e => setTitle(e.target.value)} 
        />
        <textarea 
          value={given} 
          onChange={e => setGiven(e.target.value)} 
        />
        <textarea 
          value={when} 
          onChange={e => setWhen(e.target.value)} 
        />
        <textarea 
          value={and} 
          onChange={e => setAnd(e.target.value)} 
        />
        <textarea 
          value={then} 
          onChange={e => setThen(e.target.value)} 
        />
        <label htmlFor="fileUpload" className="fileUpload"> Importar Imagens
          <input id="fileUpload" type="file" onChange={handleImageUpload} multiple />
        </label>
        <button onClick={handleAddScenario}><i class="fas fa-plus"></i>Add Scenario</button>
        <button onClick={closeModal}><i class="fas fa-times"></i>Close</button>
      </Modal>
      
      {scenarios.map((scenario, index) => (
      <div key={index}>
        <div className = "hover-container">
          <div className="hover-button">
            <button onClick={() => handleRemoveScenario(index)}>Remove Scenario {index+1}</button>
          </div>
              
          <textarea 
            value={scenario.title} 
            onChange={e => handleTextChange(e, index, 'title')} 
            style={{
              width: '100%',
              minHeight: '5px',
              border: '1px solid #ccc',
              borderRadius: '4px',
              padding: '10px'
            }}
          />
          <textarea 
            value={scenario.given} 
            onChange={e => handleTextChange(e, index, 'given')} 
            style={{
              width: '100%',
              minHeight: '5px',
              border: '1px solid #ccc',
              borderRadius: '4px',
              padding: '10px'
            }}
          />
          <textarea 
            value={scenario.when} 
            onChange={e => handleTextChange(e, index, 'when')} 
            style={{
              width: '100%',
              minHeight: '5px',
              border: '1px solid #ccc',
              borderRadius: '4px',
              padding: '10px'
            }}
          />
          <textarea 
            value={scenario.and} 
            onChange={e => handleTextChange(e, index, 'and')} 
            style={{
              width: '100%',
              minHeight: '5px',
              border: '1px solid #ccc',
              borderRadius: '4px',
              padding: '10px'
            }}
          />
          <textarea 
            value={scenario.then} 
            onChange={e => handleTextChange(e, index, 'then')} 
            style={{
              width: '100%',
              minHeight: '5px',
              border: '1px solid #ccc',
              borderRadius: '4px',
              padding: '10px'
            }}
          />
        </div> 
        {scenario.images.map((image, imageIndex) => (
          <div key={imageIndex} className="image-container">
          <img src={image} alt="" />
          <div className="image-buttons">
            <button onClick={() => handleRemoveImage(index, imageIndex)}>
              <i className="fa fa-trash"></i>
            </button>
            <input type="file" style={{display: 'none'}} ref={input => inputRef.current[imageIndex] = input} onChange={e => handleImageChange(e, index, imageIndex)} />
            <button onClick={() => inputRef.current[imageIndex].click()}>
              <i className="fa fa-pencil-alt"></i>
            </button>
          </div>
        </div>
        ))}
      </div>
    ))}
    <button onClick={openModal}>Create Scenario</button>
    </div>
  );
}

export default App;

此代码创建场景,您需要填写所有必要的信息并添加图像(如果您也需要),然后将此信息作为 div 添加到页面中,您可以创建多个,删除图像,更改不需要的图像等。

根据此代码,我想创建一个按钮,将整个页面转换为动态 pdf,并显示所有场景和图像,删除按钮并在打印时将文本区域转换为普通文本。

您可以使用任何实现该结果的 mehtod,我尝试过 jspdfhtml2canvas 甚至文件保护程序,但它们效果不佳。

我觉得我尝试了一切,但没有任何效果。他们要么没有在pdf中显示任何内容,要么添加了多个不需要的页面,pdf中元素的位置错误,还有很多其他问题。

我怎么能做这样的东西?

Javascript HTML 反应JS PDF

评论

0赞 tao 11/17/2023
出于几个原因,您的问题在 Stack Overflow偏离了主题。从描述来看,您的问题似乎与CSS相关,但您尚未添加CSS。理想情况下,如果您需要类似节点的环境,您应该使用 Stack 代码段或 codesandbox.io(或类似)提供可运行的最小可重现示例。其次,即使你确实添加了所有必要的细节供某人重现,以及让你最接近目标的方法进入问题,这也是一项需要经验丰富的开发人员才能完成的任务。SO 问题的回答时间不应超过 15 分钟。这是推荐的尺寸。

答: 暂无答案