header.tsx 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. import { ArrowLeftOutlined } from "@ant-design/icons"
  2. import { Button } from "antd"
  3. import { useNavigate, fillRoutePath, RoutePath, usePathData } from "router"
  4. import { saveAs } from 'utils'
  5. import style from './style.module.scss'
  6. import {
  7. BoardTypeDesc,
  8. BoardType,
  9. saveBoard,
  10. TitleShapeData
  11. } from 'api'
  12. import { useEffect, useState } from "react"
  13. import { Board, title } from "./board"
  14. import type { SaveBoardProps } from 'api'
  15. type HeaderProps = {
  16. board: Board
  17. type: BoardType
  18. }
  19. const Header = ({ board, type }: HeaderProps) => {
  20. const [backDisabled, setBackDisabled] = useState(true)
  21. const [forwardDisabled, setForwradDisabled] = useState(true)
  22. const path = usePathData()
  23. const caseId = path!.caseId
  24. const pathId = Number(path!.id)
  25. const pathType = path!.type as BoardType
  26. const navigate = useNavigate()
  27. const exportPng = async () => {
  28. const blob = await board.export()
  29. saveAs(blob, '现场图.png')
  30. }
  31. const save = async () => {
  32. const store = board.getStore()
  33. const titleShape = store.shapes.find(shape => shape.type === title) as TitleShapeData
  34. const blob = await board.export()
  35. const isNew = pathId === -1
  36. const body: SaveBoardProps = {
  37. caseId,
  38. imgType: pathType,
  39. file: new File([blob], `${pathType}_${pathId}.png`),
  40. filesTitle: titleShape?.text || `${caseId}_${BoardTypeDesc[pathType]}`,
  41. content: board.getStore()
  42. }
  43. if (!isNew) {
  44. body.filesId = pathId
  45. }
  46. const data = await saveBoard(body)
  47. if (isNew) {
  48. navigate(
  49. fillRoutePath(RoutePath.drawFile, { ...path as any, id: data.filesId.toString() }),
  50. { replace: true }
  51. )
  52. }
  53. }
  54. useEffect(() => {
  55. board.bus.on('backDisabled', setBackDisabled)
  56. board.bus.on('forwardDisabled', setForwradDisabled)
  57. return () => {
  58. board.bus.off('backDisabled', setBackDisabled)
  59. board.bus.off('forwardDisabled', setForwradDisabled)
  60. }
  61. }, [board])
  62. useEffect(() => {
  63. const keydownHandler = (ev: KeyboardEvent) => {
  64. if (ev.keyCode === 32) {
  65. board.viewInit()
  66. }
  67. }
  68. window.addEventListener('keydown', keydownHandler)
  69. return () => {
  70. window.removeEventListener('keydown', keydownHandler)
  71. }
  72. }, [board])
  73. return (
  74. <>
  75. <div className={style['df-header-left']}>
  76. <span className={`${style['df-header-back']} icon`} onClick={() => navigate(-1)}>
  77. <ArrowLeftOutlined />
  78. 返回
  79. </span>
  80. </div>
  81. <h1 className={style['df-header-center']}>
  82. 创建{ BoardTypeDesc[type] }
  83. </h1>
  84. <div className={style['df-header-right']}>
  85. <div className={style['df-header-action']}>
  86. <i className={`iconfont icon-repeal ${backDisabled ? 'disabled': 'icon'} `}
  87. onClick={() => board.back()}
  88. />
  89. <i className={`iconfont icon-recover ${forwardDisabled ? 'disabled': 'icon'} `}
  90. onClick={() => board.forward()}
  91. />
  92. <i className="iconfont icon-keyboard" />
  93. </div>
  94. <Button type="primary" size="middle" onClick={save}>保存</Button>
  95. <Button type="default" size="middle" onClick={exportPng}>导出</Button>
  96. </div>
  97. </>
  98. )
  99. }
  100. export default Header