bill 2 năm trước cách đây
mục cha
commit
43609c4ab1

+ 1 - 1
src/api/board.ts

@@ -51,7 +51,7 @@ export interface BgImageShapeData extends ShapeData {
   type: typeof bgImage
 }
 export interface CompassShapeData extends ShapeData {
-  url: string
+  rotate: number
   type: typeof compass
 }
 

+ 4 - 3
src/hook/refersh.ts

@@ -1,9 +1,10 @@
-import { useState } from 'react'
+import { useCallback, useState } from 'react'
 
 export const useRefersh = () => {
   const [refershCount, setRefershCount] = useState(0)
 
-  return () => {
+  return useCallback(() => {
     setRefershCount(refershCount + 1)
-  }
+  // eslint-disable-next-line react-hooks/exhaustive-deps
+  }, [])
 }

+ 6 - 5
src/views/draw-file/board/index.d.ts

@@ -22,8 +22,9 @@ import {
 } from './shape'
 
 type Metas = typeof fMetas
-export type ShapeType = brokenLine | text | table | rect | circular | arrow | icon | cigarette |
-  fireoint | footPrint | shoePrint | fingerPrint | corpse | theBlood | compass | title | bgImage
+export type ShapeType = typeof brokenLine | typeof text | typeof table | typeof rect | typeof circular | typeof arrow 
+  | typeof icon | typeof cigarette | typeof fireoint | typeof footPrint | typeof shoePrint | typeof fingerPrint 
+  | typeof corpse | typeof theBlood | typeof compass | typeof title | typeof bgImage
 
 export type MetaShapeType = keyof Metas
 
@@ -54,7 +55,7 @@ export type Board = {
     forwardDisabled: boolean
   }>
   unSelectShape(): void,
-  readyAddShape(type: ShapeType, onFinish?: () => void): () => void
+  readyAddShape(type: MetaShapeType, onFinish?: () => void): () => void
   back(): void
   forward(): void
 
@@ -70,8 +71,8 @@ function create (store: BoardData, canvas: HTMLCanvasElement): Board
 
 export { BoardShapeData }
 export const metas: Metas
-export const images: ShapeType[]
-export const labels: ShapeType[]
+export const images: MetaShapeType[]
+export const labels: MetaShapeType[]
 export {
   brokenLine,
   text,

+ 17 - 5
src/views/draw-file/board/index.js

@@ -1,7 +1,8 @@
 import mitt from 'mitt'
 import {
   text,
-  table
+  table,
+  compass
 } from './shape'
 import Layer from './editCAD/Layer'
 import { history } from './editCAD/History/History.js'
@@ -56,17 +57,28 @@ export const create = (store, canvas) => {
         }
         break;
       }
+      case compass: {
+        data = data || 0
+        shape.data.rotate = 0
+        shape.setRotate = (newData) => {
+          console.log(newData)
+          shape.data.rotate = newData
+          update(newData)
+        }
+      }
     }
+    console.log(shape)
     refs.bus.emit('selectShape', shape)
   })
   layer.uiControl.bus.on('hideAttribute', () => refs.bus.emit('selectShape', null))
   history.bus.on('undoAvailable', availabe => refs.bus.emit('backDisabled', !availabe))
   history.bus.on('redoAvailable', availabe => refs.bus.emit('forwardDisabled', !availabe))
 
-  // setTimeout(() => {
-  //   history.bus.emit('undoAvailable', true)
-  //   history.bus.emit('redoAvailable', true)
-  // }, 100)
+  setTimeout(() => {
+    // layer.uiControl.bus.emit('showAttribute', { type: compass, data: 0 })
+    // history.bus.emit('undoAvailable', true)
+    // history.bus.emit('redoAvailable', true)
+  }, 100)
 
   const board = {
     bus: refs.bus,

+ 3 - 2
src/views/draw-file/board/shape.js

@@ -75,5 +75,6 @@ export const metas = {
   [fingerPrint]: { desc: '指纹', icon: fingerPrintSVG },
   [corpse]: { desc: '尸体', icon: corpseSVG },
   [theBlood]: { desc: '血迹', icon: theBloodSVG },
-  [compass]: { desc: '指南针', icon: compassSVG  }
-}
+}
+
+metas[compass] = { desc: '指南针', icon: compassSVG  }

+ 20 - 10
src/views/draw-file/eshape.tsx

@@ -1,11 +1,11 @@
 import { useEffect, useMemo, useState } from "react"
 import { Button, Form, Modal, Input } from 'antd'
-import { CloseOutlined, PlusOutlined } from '@ant-design/icons'
+import { CloseOutlined, PlusOutlined, RotateRightOutlined } from '@ant-design/icons'
 import style from './style.module.scss'
 import ReactEditeTable, { InputEditor } from 'react-edit-table'
 
 import type { Board, BoardShape, ShapeType, ExtractShape } from "./board"
-import type { RefObject, ComponentType } from 'react'
+import type { ComponentType } from 'react'
 
 
 // import { Select } from 'antd'
@@ -158,23 +158,33 @@ const ContentInput = ({ shape }: { shape: ExtractShape<'content'> }) => {
   )
 }
 
+const RotateInput = ({ shape }: { shape: ExtractShape<'rotate'> }) => (
+  <Button 
+    onClick={() => shape.setRotate((shape.data.rotate + 90) % 360)} 
+    type="primary" 
+    style={{marginRight: '10px'}}
+  >
+    <RotateRightOutlined /> 旋转
+  </Button>
+)
+
 const shapeCompontes: { [key in ShapeType]?: ComponentType<{ shape: any }> } = {
-  Tag: (props) => <><TextInput {...props} /> </>,
-  Table: (props) => <><ContentInput {...props} /> </>,
+  Tag: TextInput,
+  Table: ContentInput,
+  Compass: RotateInput
 }
 
 export type EShapeProps = {
-  board: RefObject<Board>
+  board: Board
 }
 export const EShape = ({ board }: EShapeProps) => {
   const [shape, setShape] = useState<BoardShape | null>(null)
   
   const Edit = shape && shapeCompontes[shape.data.type]
   useEffect(() => {
-    if (board.current) {
-      const boardRef = board.current
-      boardRef.bus.on('selectShape', setShape)
-      return () => boardRef.bus.off('selectShape', setShape)
+    board.bus.on('selectShape', setShape)
+    return () => {
+      board.bus.off('selectShape', setShape)
     }
   }, [board])
 
@@ -185,7 +195,7 @@ export const EShape = ({ board }: EShapeProps) => {
         <Button type="primary" onClick={() => shape.delete()}>删除</Button>
       </Form.Item>
       <div className={`ant-form-item ${style['def-close-shape-edit']}`} onClick={() => setShape(null)}>
-        <CloseOutlined className={`${style['icon']}`} onClick={() => board.current?.unSelectShape()}  />
+        <CloseOutlined className={`${style['icon']}`} onClick={() => board.unSelectShape()}  />
       </div>
     </div>
   ) : <></>

+ 31 - 38
src/views/draw-file/header.tsx

@@ -10,12 +10,12 @@ import {
   TitleShapeData
 } from 'api'
 
-import { RefObject, useEffect, useState } from "react"
+import { useEffect, useState } from "react"
 import { Board, title } from "./board"
 import type { SaveBoardProps } from 'api'
 
 type HeaderProps = {
-  board: RefObject<Board>
+  board: Board
   type: BoardType
 }
 const Header = ({ board, type }: HeaderProps) => {
@@ -27,50 +27,43 @@ const Header = ({ board, type }: HeaderProps) => {
   const pathType = path!.type as BoardType
   const navigate = useNavigate()
   const exportPng = async () => {
-    if (board.current) {
-      const blob = await board.current.export()
-      saveAs(blob, '现场图.png')
-    }
+    const blob = await board.export()
+    saveAs(blob, '现场图.png')
   }
 
   
   const save = async () => {
-    if (board.current) {
-      const store = board.current.getStore()
-      const titleShape = store.shapes.find(shape => shape.type === title) as TitleShapeData
-      const blob = await board.current.export()
-      const isNew = pathId === -1
-      const body: SaveBoardProps = {
-        caseId, 
-        imgType: pathType,
-        file: new File([blob], `${pathType}_${pathId}.png`),
-        filesTitle: titleShape?.text || `${caseId}_${BoardTypeDesc[pathType]}`, 
-        content: board.current.getStore()
-      }
-      if (!isNew) {
-        body.filesId = pathId
-      }
-      const data = await saveBoard(body)
+    const store = board.getStore()
+    const titleShape = store.shapes.find(shape => shape.type === title) as TitleShapeData
+    const blob = await board.export()
+    const isNew = pathId === -1
+    const body: SaveBoardProps = {
+      caseId, 
+      imgType: pathType,
+      file: new File([blob], `${pathType}_${pathId}.png`),
+      filesTitle: titleShape?.text || `${caseId}_${BoardTypeDesc[pathType]}`, 
+      content: board.getStore()
+    }
+    if (!isNew) {
+      body.filesId = pathId
+    }
+    const data = await saveBoard(body)
 
-      if (isNew) {
-        navigate(
-          fillRoutePath(RoutePath.drawFile, { ...path as any, id: data.filesId.toString() }),
-          { replace: true }
-        )
-      }
+    if (isNew) {
+      navigate(
+        fillRoutePath(RoutePath.drawFile, { ...path as any, id: data.filesId.toString() }),
+        { replace: true }
+      )
     }
   }
 
   useEffect(() => {
-    const boardRef = board.current
-    if (boardRef) {
-      boardRef.bus.on('backDisabled', setBackDisabled)
-      boardRef.bus.on('forwardDisabled', setForwradDisabled)
+    board.bus.on('backDisabled', setBackDisabled)
+    board.bus.on('forwardDisabled', setForwradDisabled)
 
-      return () => {
-        boardRef.bus.off('backDisabled', setBackDisabled)
-        boardRef.bus.off('forwardDisabled', setForwradDisabled)
-      }
+    return () => {
+      board.bus.off('backDisabled', setBackDisabled)
+      board.bus.off('forwardDisabled', setForwradDisabled)
     }
   }, [board])
 
@@ -89,11 +82,11 @@ const Header = ({ board, type }: HeaderProps) => {
         <div className={style['df-header-action']}>
           <ArrowLeftOutlined 
             className={backDisabled ? 'disabled':  'icon'} 
-            onClick={() => board.current?.back()} 
+            onClick={() => board.back()} 
           />
           <ArrowRightOutlined 
             className={forwardDisabled ? 'disabled': 'icon'} 
-            onClick={() => board.current?.forward()} 
+            onClick={() => board.forward()} 
           />
         </div>
         <Button type="primary" size="middle" onClick={save}>保存</Button>

+ 14 - 6
src/views/draw-file/index.tsx

@@ -8,6 +8,7 @@ import DfHeader from './header'
 import EShape from './eshape'
 import { useDispatch } from 'store'
 import { getBoardById, BoardType, BoardData } from 'api'
+import { useRefersh } from 'hook'
 
 import type { Board } from './board'
 
@@ -36,17 +37,24 @@ const DfBoard = memo(forwardRef(({ data: boardData }: { data: BoardData }, ref)
 }))
 
 export const DrawFile = () => {
+  const refersh = useRefersh()
   const path = usePathData()
   const dispatch = useDispatch()
   const pathId = Number(path!.id)
   const caseId = Number(path!.caseId)
   const pathType = path!.type as BoardType
   const [boardData, setBoardData] = useState<BoardData>()
-  const board = useRef<Board>(null)
+  const board = useRef<Board>()
+
+  const updateBoard = useCallback((data: Board) => {
+    if (data !== board.current) {
+      board.current = data
+      refersh()
+    }
+  }, [refersh])
 
   useEffect(() => {
     if (!boardData || pathId !== boardData.id) {
-      console.log(pathId, boardData?.id)
       if (pathId !== -1) {
         getBoardById({ id: pathId }).then((data) => setBoardData({ ...data.content, id: data.filesId! }))
       } else {
@@ -65,15 +73,15 @@ export const DrawFile = () => {
   return (
     <Layout className={style['df-layout']}>
       <Header className={style['df-header']}>
-        <DfHeader board={ board } type={ pathType } />
+        { board.current && <DfHeader board={ board.current } type={ pathType } /> }
       </Header>
       <Layout>
         <Sider className={style['df-sider']}>
-          <DfSlider board={ board } type={ pathType } caseId={ caseId } />
+        { board.current && <DfSlider board={ board.current } type={ pathType } caseId={ caseId } /> }
         </Sider>
         <Content className={style['def-content']}>
-          { <EShape board={ board } /> }
-          { pathId === boardData?.id && <DfBoard data={boardData} ref={board} /> }
+          { board.current && <EShape board={ board.current } /> }
+          { pathId === boardData?.id && <DfBoard data={boardData} ref={updateBoard} /> }
         </Content>
       </Layout>
     </Layout>

+ 2 - 2
src/views/draw-file/shapes/index.tsx

@@ -15,10 +15,10 @@ import { ReactComponent as fingerPrintSVG} from 'assets/svg/fingerPrint.svg'
 import { ReactComponent as corpseSVG} from 'assets/svg/corpse.svg'
 import { ReactComponent as theBloodSVG} from 'assets/svg/theBlood.svg'
 
-import type { ShapeType } from '../board'
+import type { MetaShapeType } from '../board'
 import type { ComponentType } from 'react'
 
-export const shapes: { [key in ShapeType]: ComponentType } = {
+export const shapes: { [key in MetaShapeType]: ComponentType } = {
   Wall: brokenLineSVG,
   Tag: textSVG,
   Table: tableSVG,

+ 4 - 6
src/views/draw-file/slider.tsx

@@ -7,11 +7,10 @@ import shapes from './shapes'
 import style from './style.module.scss'
 
 import type { MetaShapeType, Board } from './board'
-import type { RefObject } from 'react'
 import type { Tagging } from 'api'
 
 type SliderProps = {
-  board: RefObject<Board>
+  board: Board
   type: BoardType
   caseId: number
 }
@@ -34,7 +33,7 @@ export const DfSlider = ({ board, type, caseId }: SliderProps) => {
   const setBoardImage = async (blob: Blob | null, taggings: Tagging[]) => {
     if (blob) {
       const url = URL.createObjectURL(blob)
-      board.current?.setImage(url)
+      board.setImage(url)
     }
   }
   const SelectImage = type  === BoardType.map ? SelectMap : SelectFuse
@@ -45,10 +44,9 @@ export const DfSlider = ({ board, type, caseId }: SliderProps) => {
   />
 
   useEffect(() => {
-    const boardRef = board.current
-    if (currentShape && boardRef) {
+    if (currentShape) {
       console.log('read add', currentShape)
-      const cleaup = boardRef.readyAddShape(
+      const cleaup = board.readyAddShape(
         currentShape,
         () => setCurrentShape(void 0)
       )