PreviewModal.tsx 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152
  1. 'use client'
  2. import { useAtomValue } from "jotai"
  3. import { exportFlowToDocx } from "../export"
  4. import { instantDataAtom, stepsNodesAtom } from "../store"
  5. import { twMerge } from "tailwind-merge"
  6. import { renderAsync } from 'docx-preview'
  7. import { useEffect, useRef, useState } from "react"
  8. import saveAs from "file-saver"
  9. export default function PreviewModal({ open, onClose }: { open: boolean, onClose: () => void }) {
  10. const instantData = useAtomValue(instantDataAtom)
  11. const stepsNodes = useAtomValue(stepsNodesAtom)
  12. const [blob, setBlob] = useState(null)
  13. const previewRef = useRef()
  14. useEffect(() => {
  15. if (open) {
  16. (async () => {
  17. const stepsInstantData = stepsNodes.map(node => instantData[node.id])
  18. const blob = await exportFlowToDocx(stepsInstantData)
  19. setBlob(blob)
  20. await renderAsync(blob, previewRef.current)
  21. })()
  22. } else {
  23. setBlob(null)
  24. }
  25. }, [open])
  26. const onExport = async () => {
  27. blob && saveAs(blob, "课程设计.docx", { type: "application/vnd.openxmlformats-officedocument.wordprocessingml.document" })
  28. }
  29. return (
  30. <dialog className={twMerge("modal", open ? "modal-open" : "")}>
  31. <div className="modal-box w-11/12 max-w-5xl pb-5">
  32. <div ref={previewRef}></div>
  33. </div>
  34. <div className="modal-action mb-6">
  35. <form method="dialog" className="flex gap-4">
  36. <button className="btn btn-wide" onClick={onClose}>关闭</button>
  37. <button className="btn btn-wide btn-primary" disabled={!blob} onClick={onExport}>
  38. {blob
  39. ? '导出'
  40. : <span className="loading loading-spinner"></span>}
  41. </button>
  42. </form>
  43. </div>
  44. </dialog>
  45. )
  46. }