瀏覽代碼

feat: 痕迹物证对接,自动生成序号表格制作

bill 5 天之前
父節點
當前提交
7a1c216f5c

File diff suppressed because it is too large
+ 11 - 0
public/icons/cartridge.svg


+ 6 - 0
public/icons/case_other.svg

@@ -0,0 +1,6 @@
+<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M4.5 3.5V10.5H15.687C15.9347 10.5 16.1735 10.5919 16.3573 10.7579L20.2145 14.2421C20.3983 14.4081 20.6371 14.5 20.8848 14.5H23.5V3.5C23.5 2.39543 22.6046 1.5 21.5 1.5H6.5C5.39543 1.5 4.5 2.39543 4.5 3.5Z" stroke="black" stroke-linecap="round" stroke-linejoin="round"/>
+<path d="M4.5 4.5H23.5" stroke="black" stroke-linecap="round" stroke-linejoin="round"/>
+<path d="M23.5 6.5H25.5C26.6046 6.5 27.5 7.39543 27.5 8.5V14.5" stroke="black" stroke-linecap="round" stroke-linejoin="round"/>
+<path d="M13.0858 14.5H4.5C3.39543 14.5 2.5 15.3954 2.5 16.5V28.5C2.5 29.6046 3.39543 30.5 4.5 30.5H27.5C28.6046 30.5 29.5 29.6046 29.5 28.5V21.5C29.5 20.3954 28.6046 19.5 27.5 19.5H18.9142C18.649 19.5 18.3946 19.3946 18.2071 19.2071L13.7929 14.7929C13.6054 14.6054 13.351 14.5 13.0858 14.5Z" stroke="black" stroke-linecap="round" stroke-linejoin="round"/>
+</svg>

+ 6 - 0
public/icons/check.svg

@@ -0,0 +1,6 @@
+<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M24 13C24 19.0751 19.0751 24 13 24C6.92487 24 2 19.0751 2 13C2 6.92487 6.92487 2 13 2C19.0751 2 24 6.92487 24 13Z" stroke="black"/>
+<path d="M20.8025 20.8026L24.5978 24.5979" stroke="black" stroke-linecap="round"/>
+<path d="M24.6508 26.7134C24.0799 26.1425 24.0799 25.2169 24.6508 24.646C25.2217 24.0751 26.1473 24.0751 26.7182 24.646L30.1977 28.1255C30.7686 28.6964 30.7686 29.622 30.1977 30.1929C29.6268 30.7638 28.7012 30.7638 28.1303 30.1929L24.6508 26.7134Z" stroke="black"/>
+<path d="M6.33594 11.3333H9.0026L10.4317 6L14.183 20L18.8018 12H21.0026" stroke="black" stroke-linecap="round" stroke-linejoin="round"/>
+</svg>

+ 11 - 0
public/icons/corpse.svg

@@ -0,0 +1,11 @@
+<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M5.5 17.1179C5.5 16.7777 5.67298 16.4608 5.95916 16.2768L8.95916 14.3478C9.28861 14.1359 9.7114 14.1359 10.0408 14.3478L13.0408 16.2768C13.327 16.4608 13.5 16.7777 13.5 17.1179V25.5C13.5 26.0523 13.0523 26.5 12.5 26.5H6.5C5.94772 26.5 5.5 26.0523 5.5 25.5V17.1179Z" stroke="black"/>
+<path d="M9.5 18.5V23" stroke="black" stroke-linecap="round" stroke-linejoin="round"/>
+<path d="M25.5 13.4991C25.5 19.4982 22 31.6241 17.5 30.4991C13 29.3741 15.5519 25.4032 15.9988 20.4991C16.5 14.9991 11.9998 14 12.4998 9.5C12.9998 5 18.4998 5.5 18.4998 5.5C20.6665 5.66667 25.5 7.48578 25.5 13.4991Z" stroke="black" stroke-linecap="round" stroke-linejoin="round"/>
+<path d="M18.5 5.50098C18.5 5.50098 11.5 4.50184 9.5 14.001" stroke="black" stroke-linejoin="round"/>
+<path d="M13.5016 6.99678C11.0032 5.99698 11.4987 2.50989 12.4983 2.00372C13.4979 1.49755 15.5012 3.00231 15.5012 6.00232" stroke="black"/>
+<path d="M15.5029 5.50001C15.6877 4.08365 16.0031 2.49193 17.5009 2.49606C18.9987 2.50018 19.1866 4.08364 19.0019 5.5" stroke="black"/>
+<path d="M19 5.5C19.1667 4.66667 19.8 3.1 21 3.5C22.2 3.9 22.1667 5.66553 22 6.4983" stroke="black" stroke-linecap="round" stroke-linejoin="round"/>
+<path d="M24 8.00288C24.5 7.00264 25 5.50181 24 4.99786C22.8704 4.4286 22.1667 5.66744 22 6.50021" stroke="black" stroke-linecap="round" stroke-linejoin="round"/>
+<path d="M24 7.99722C24.3333 7.49722 25.2 6.7016 26 7.5016C26.8 8.3016 26.5 9.49717 25.5 10.9972" stroke="black" stroke-linecap="round" stroke-linejoin="round"/>
+</svg>

+ 5 - 0
public/icons/cube.svg

@@ -0,0 +1,5 @@
+<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M15.0287 1.5396C15.6328 1.20402 16.3672 1.20402 16.9713 1.5396L28.4713 7.92849C29.1062 8.28123 29.5 8.95047 29.5 9.67681V22.3232C29.5 23.0495 29.1062 23.7188 28.4713 24.0715L16.9713 30.4604C16.3672 30.796 15.6328 30.796 15.0287 30.4604L3.52871 24.0715C2.89378 23.7188 2.5 23.0495 2.5 22.3232V9.67681C2.5 8.95047 2.89378 8.28123 3.52871 7.92849L15.0287 1.5396Z" stroke="black"/>
+<path d="M16 15V31" stroke="black"/>
+<path d="M2.5 8.5L16 15L29.5 8.5" stroke="black"/>
+</svg>

+ 8 - 0
public/icons/electronic.svg

@@ -0,0 +1,8 @@
+<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M2.49658 20.5H29.4966V29.5C29.4966 30.0523 29.0489 30.5 28.4966 30.5H3.49658C2.9443 30.5 2.49658 30.0523 2.49658 29.5V20.5Z" stroke="black" stroke-linejoin="round"/>
+<path d="M2.5 20.5H29.5L25.6672 2.29653C25.5697 1.8338 25.1615 1.50257 24.6886 1.50257H7.31137C6.83849 1.50257 6.43026 1.8338 6.33283 2.29653L2.5 20.5Z" stroke="black" stroke-linejoin="round"/>
+<path d="M16.5 26.5H25.5" stroke="black" stroke-linecap="round" stroke-linejoin="round"/>
+<path d="M17 11C17 11.5523 16.5523 12 16 12C15.4477 12 15 11.5523 15 11C15 10.4477 15.4477 10 16 10C16.5523 10 17 10.4477 17 11Z" stroke="black"/>
+<path d="M21.5 11C21.5 14.0376 19.0376 16.5 16 16.5C12.9624 16.5 10.5 14.0376 10.5 11C10.5 7.96243 12.9624 5.5 16 5.5C19.0376 5.5 21.5 7.96243 21.5 11Z" stroke="black"/>
+<path d="M18.5 13.5L22.5 17.5" stroke="black" stroke-linecap="round" stroke-linejoin="round"/>
+</svg>

+ 11 - 0
public/icons/folder_close.svg

@@ -0,0 +1,11 @@
+<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
+<g clip-path="url(#clip0_21286_180205)">
+<path d="M13.5 2.5C14.6046 2.5 15.5 3.39543 15.5 4.5V6.5H29.5C30.6046 6.5 31.5 7.39543 31.5 8.5V27.5C31.5 28.6046 30.6046 29.5 29.5 29.5H2.5C1.39543 29.5 0.5 28.6046 0.5 27.5V4.5C0.5 3.39543 1.39543 2.5 2.5 2.5H13.5Z" stroke="black"/>
+<path d="M0.498535 12.5H31.4985" stroke="black" stroke-linecap="round" stroke-linejoin="round"/>
+</g>
+<defs>
+<clipPath id="clip0_21286_180205">
+<rect width="32" height="32" fill="white"/>
+</clipPath>
+</defs>
+</svg>

File diff suppressed because it is too large
+ 3 - 0
public/icons/footprint.svg


+ 5 - 0
public/icons/handprint.svg

@@ -0,0 +1,5 @@
+<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M17.0001 17V5C17.0001 3.89543 16.1047 3 15.0001 3C13.8955 3 13.0001 3.89543 13.0001 5V20L8.63187 14.5397C7.73976 13.4246 6.10114 13.2705 5.01686 14.1999C4.12797 14.9618 3.87774 16.2284 4.44218 17.2541C6.67493 21.3114 12.3377 31 15.5001 31H22.5001C23.1646 31 23.8536 30.6811 24.5236 30.1847C28.3636 27.3394 29.0001 21.9982 29.0001 17.2189V9C29.0001 7.89543 28.1047 7 27.0001 7C25.8955 7 25.0001 7.89543 25.0001 9V17" stroke="black" stroke-linecap="round" stroke-linejoin="round"/>
+<path d="M17 17V3C17 1.89543 17.8954 1 19 1C20.1046 1 21 1.89543 21 3V17" stroke="black" stroke-linecap="round"/>
+<path d="M21.0037 16L21.0005 5.00059C21.0002 3.89579 21.8957 3 23.0005 3C24.1048 3 25.0002 3.89507 25.0005 4.99941L25.0037 16" stroke="black" stroke-linecap="round"/>
+</svg>

+ 7 - 0
public/icons/physics_and_chemistry.svg

@@ -0,0 +1,7 @@
+<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M21.4973 14.5L28.8204 27.5195C29.5703 28.8527 28.6069 30.5 27.0773 30.5H4.91697C3.38732 30.5 2.42389 28.8527 3.17382 27.5195L10.4973 14.5H21.4973Z" stroke="black" stroke-linecap="round" stroke-linejoin="round"/>
+<path d="M6.50342 1.5H25.5034" stroke="black" stroke-linecap="round" stroke-linejoin="round"/>
+<path d="M18.5 20.5L21.5 25.5" stroke="black" stroke-linecap="round" stroke-linejoin="round"/>
+<path d="M10.5 1.50078V14.6336" stroke="black" stroke-linecap="round" stroke-linejoin="round"/>
+<path d="M21.5 1.5V14.5" stroke="black" stroke-linecap="round" stroke-linejoin="round"/>
+</svg>

File diff suppressed because it is too large
+ 17 - 0
public/icons/poison.svg


+ 6 - 0
public/icons/video.svg

@@ -0,0 +1,6 @@
+<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M6.5 15.5C6.5 14.9477 6.94772 14.5 7.5 14.5H16.5C17.0523 14.5 17.5 14.9477 17.5 15.5V24.5C17.5 25.0523 17.0523 25.5 16.5 25.5H7.5C6.94771 25.5 6.5 25.0523 6.5 24.5V15.5Z" stroke="black"/>
+<path d="M20.5 19.177C20.5 18.7681 20.749 18.4004 21.1286 18.2486L24.1286 17.0486C24.7855 16.7858 25.5 17.2696 25.5 17.977V22.382C25.5 23.1253 24.7177 23.6088 24.0528 23.2764L21.0528 21.7764C20.714 21.607 20.5 21.2607 20.5 20.882V19.177Z" stroke="black"/>
+<path d="M2.5 2.5C2.5 1.94772 2.94772 1.5 3.5 1.5H19.0858C19.351 1.5 19.6054 1.60536 19.7929 1.79289L29.2071 11.2071C29.3946 11.3946 29.5 11.649 29.5 11.9142V29.5C29.5 30.0523 29.0523 30.5 28.5 30.5H3.5C2.94771 30.5 2.5 30.0523 2.5 29.5V2.5Z" stroke="black"/>
+<path d="M19.5 1.5V10.5C19.5 11.0523 19.9477 11.5 20.5 11.5H29.5" stroke="black"/>
+</svg>

+ 16 - 0
public/icons/virus.svg

@@ -0,0 +1,16 @@
+<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M24.887 16C24.887 20.9082 20.9081 24.8871 15.9999 24.8871C11.0917 24.8871 7.11279 20.9082 7.11279 16C7.11279 11.0918 11.0917 7.1129 15.9999 7.1129C20.9081 7.1129 24.887 11.0918 24.887 16Z" stroke="black"/>
+<path d="M16 7.1129V4.30645M17.4471 2.90323C17.4471 3.67821 16.8188 4.30645 16.0439 4.30645C15.2689 4.30645 14.6406 3.67821 14.6406 2.90323C14.6406 2.12825 15.2689 1.5 16.0439 1.5C16.8188 1.5 17.4471 2.12825 17.4471 2.90323Z" stroke="black" stroke-linecap="round"/>
+<path d="M20.4443 8.30497L21.8476 5.87451M23.8024 5.38282C23.4149 6.05397 22.5567 6.28393 21.8855 5.89644C21.2144 5.50895 20.9844 4.65075 21.3719 3.9796C21.7594 3.30844 22.6176 3.07849 23.2888 3.46598C23.9599 3.85347 24.1899 4.71167 23.8024 5.38282Z" stroke="black" stroke-linecap="round"/>
+<path d="M23.6948 11.557L26.1253 10.1538M28.0641 10.7054C27.3929 11.0929 26.5347 10.8629 26.1472 10.1918C25.7597 9.52064 25.9897 8.66244 26.6608 8.27495C27.332 7.88746 28.1902 8.11741 28.5777 8.78856C28.9652 9.45972 28.7352 10.3179 28.0641 10.7054Z" stroke="black" stroke-linecap="round"/>
+<path d="M24.8872 16L27.6937 16M29.0969 17.4471C28.3219 17.4471 27.6937 16.8188 27.6937 16.0439C27.6937 15.2689 28.3219 14.6406 29.0969 14.6406C29.8719 14.6406 30.5001 15.2689 30.5001 16.0439C30.5001 16.8188 29.8719 17.4471 29.0969 17.4471Z" stroke="black" stroke-linecap="round"/>
+<path d="M23.6948 20.4441L26.1253 21.8474M26.617 23.8022C25.9458 23.4147 25.7159 22.5565 26.1034 21.8853C26.4908 21.2142 27.349 20.9842 28.0202 21.3717C28.6914 21.7592 28.9213 22.6174 28.5338 23.2886C28.1463 23.9597 27.2881 24.1897 26.617 23.8022Z" stroke="black" stroke-linecap="round"/>
+<path d="M20.4429 23.695L21.8461 26.1255M21.2945 28.0643C20.907 27.3931 21.137 26.5349 21.8081 26.1474C22.4793 25.7599 23.3375 25.9899 23.725 26.661C24.1125 27.3322 23.8825 28.1904 23.2113 28.5779C22.5402 28.9654 21.682 28.7354 21.2945 28.0643Z" stroke="black" stroke-linecap="round"/>
+<path d="M15.9998 24.8871L15.9998 27.6936M14.5527 29.0968C14.5527 28.3218 15.181 27.6936 15.956 27.6936C16.7309 27.6936 17.3592 28.3218 17.3592 29.0968C17.3592 29.8718 16.7309 30.5 15.956 30.5C15.181 30.5 14.5527 29.8718 14.5527 29.0968Z" stroke="black" stroke-linecap="round"/>
+<path d="M11.556 23.695L10.1528 26.1255M8.198 26.6172C8.58549 25.946 9.44369 25.7161 10.1148 26.1036C10.786 26.4911 11.0159 27.3493 10.6285 28.0204C10.241 28.6916 9.38277 28.9215 8.71161 28.534C8.04046 28.1465 7.81051 27.2883 8.198 26.6172Z" stroke="black" stroke-linecap="round"/>
+<path d="M8.30496 20.443L5.8745 21.8462M3.93573 21.2946C4.60689 20.9071 5.46509 21.1371 5.85258 21.8082C6.24007 22.4794 6.01011 23.3376 5.33896 23.725C4.66781 24.1125 3.80961 23.8826 3.42212 23.2114C3.03463 22.5403 3.26458 21.6821 3.93573 21.2946Z" stroke="black" stroke-linecap="round"/>
+<path d="M7.11291 16L4.30645 16M2.90323 14.5529C3.67821 14.5529 4.30645 15.1812 4.30645 15.9562C4.30645 16.7311 3.67821 17.3594 2.90323 17.3594C2.12825 17.3594 1.5 16.7311 1.5 15.9562C1.5 15.1812 2.12825 14.5529 2.90323 14.5529Z" stroke="black" stroke-linecap="round"/>
+<path d="M8.30506 11.5559L5.8746 10.1526M5.38291 8.19781C6.05406 8.5853 6.28401 9.4435 5.89652 10.1147C5.50903 10.7858 4.65083 11.0158 3.97968 10.6283C3.30853 10.2408 3.07857 9.38258 3.46606 8.71143C3.85355 8.04028 4.71175 7.81032 5.38291 8.19781Z" stroke="black" stroke-linecap="round"/>
+<path d="M11.5572 8.30497L10.154 5.87451M10.7056 3.93574C11.0931 4.60689 10.8631 5.46509 10.192 5.85258C9.52084 6.24007 8.66264 6.01012 8.27515 5.33897C7.88765 4.66782 8.11761 3.80962 8.78876 3.42213C9.45991 3.03464 10.3181 3.26459 10.7056 3.93574Z" stroke="black" stroke-linecap="round"/>
+<path d="M15.5 18C16.1667 17.8333 17.209 17.1642 17.5 16C18 14 17 12.5 15 12.5C13 12.5 11 14 11 16C11 18 12 21 15.5 21C19 21 21 19 21 15" stroke="black" stroke-linecap="round"/>
+</svg>

+ 10 - 0
public/icons/wrenchAndScrewdriver.svg

@@ -0,0 +1,10 @@
+<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M16.4312 19.3588L22.3143 25.2419L23.3749 27.7168L27.6176 30.5452L29.8379 28.3249L27.0095 24.0822L24.5346 23.0216L18.3616 16.8485" stroke="black"/>
+<path d="M17.0549 12.1054L8.93027 3.98074C7.75647 2.80694 5.86143 2.80694 4.68763 3.98074L3.27341 5.39495C2.09962 6.56875 2.09962 8.46379 3.27341 9.63759L10.6556 17.0198" stroke="black"/>
+<path d="M11.7574 11.0502L6.80762 6.1005" stroke="black" stroke-linecap="round"/>
+<path d="M10.3433 12.4645L5.39355 7.51472" stroke="black" stroke-linecap="round"/>
+<path d="M3.27197 28.7279C5.22359 30.6795 8.18637 30.8846 9.89049 29.1805C10.6188 28.4522 12.429 24.959 14.7342 21.6781C17.8101 17.3011 20.8577 13.7868 20.8577 13.7868" stroke="black"/>
+<path d="M18.2076 11.1367C18.2076 11.1367 14.6933 14.1843 10.3163 17.2602C7.03534 19.5654 3.5493 21.3685 2.81391 22.1039C1.10978 23.808 1.31484 26.7708 3.26646 28.7224" stroke="black"/>
+<path d="M5.49405 24.8945C5.04886 25.3397 5.04886 26.0615 5.49405 26.5067C5.93925 26.9519 6.66106 26.9519 7.10626 26.5067C7.55145 26.0615 7.55146 25.3397 7.10626 24.8945C6.66106 24.4493 5.93925 24.4493 5.49405 24.8945Z" stroke="black"/>
+<path d="M27.8076 12.6777C25.467 15.0182 21.6628 15.0182 19.3223 12.6777C16.9818 10.3372 16.9818 6.53295 19.3223 4.19242C20.8921 2.62265 23.1195 2.10646 25.1206 2.63679L22.8578 4.89953C22.4689 5.28844 22.4689 5.92483 22.8578 6.31374L25.6862 9.14217C26.0752 9.53108 26.7116 9.53108 27.1005 9.14217L29.3632 6.87943C29.8935 8.88054 29.3844 11.1009 27.8076 12.6777Z" stroke="black"/>
+</svg>

+ 1 - 0
src/core/components/circle/index.ts

@@ -77,6 +77,7 @@ export type CircleData = Partial<typeof defaultStyle> &
     radiusX: number;
     radiusY: number;
     content?: string;
+    desc?: string
     padding?: number;
   };
 

+ 47 - 21
src/core/components/serial/index.ts

@@ -4,6 +4,8 @@ import { CircleData, defaultStyle as circleDefaultStyle } from "../circle";
 import { InteractiveFix, InteractiveTo, MatResponseProps } from "../index.ts";
 import { DrawStore } from "@/core/store/index.ts";
 import { Pos } from "@/utils/math.ts";
+import { TableData } from "../table/index.ts";
+import { copy } from "@/utils/shared.ts";
 
 export {
   getMouseStyle,
@@ -25,7 +27,7 @@ export const defaultTableStyle = {
   nameColWidth: 100,
   valueColWidth: 180,
   repColCount: 1,
-  tableStrokeWidth: 1
+  tableStrokeWidth: 1,
 };
 export const shapeName = "序号";
 export const addMode = "dot";
@@ -49,20 +51,22 @@ export const getSerialFontSizeByFontW = (data: SerialData, w: number) => {
   return (w - pad * 2) / len;
 };
 
-export const getCurrentNdx = (store: DrawStore) => {
-  const cs = store
-    .getTypeItems("serial")
-    .map((item) => Number(item.content || 0));
-  let max = Math.max(...cs, 0) + 1
-  let i = 1
+export const getCurrentNdxRaw = (serials: SerialData[]) => {
+  const cs = serials.map((item) => Number(item.content || 0));
+  let max = Math.max(...cs, 0) + 1;
+  let i = 1;
   for (; i < max; i++) {
     if (!cs.includes(i)) {
       break;
     }
-  } 
+  }
   return i.toString();
 };
 
+export const getCurrentNdx = (store: DrawStore) => {
+  return getCurrentNdxRaw(store.getTypeItems("serial"));
+};
+
 export const interactiveToData: InteractiveTo<"serial"> = ({
   info,
   preset = {},
@@ -78,7 +82,6 @@ export const interactiveToData: InteractiveTo<"serial"> = ({
       content: getCurrentNdx(store),
       ...preset,
     } as unknown as SerialData;
-
     return interactiveFixData({ ...args, info, store, data: item });
   }
 };
@@ -94,21 +97,18 @@ export const interactiveFixData: InteractiveFix<"serial"> = ({
   return data;
 };
 
-export const joinKey = "serial-table";
-export const delItem = (store: DrawStore, item: SerialData) => {
-  const table = store
-    .getTypeItems("table")
-    .find((item) => item.key === joinKey)!;
-  const data = store.getTypeItems("serial");
+export const delItemRaw = (
+  table: TableData,
+  data: SerialData[],
+  item: SerialData
+) => {
   const ndx = data.indexOf(item);
-
   const getPosition = (itemNdx: number) => {
     const colCount = table.content[0].length / 2;
     const rowNdx = 1 + Math.floor(itemNdx / colCount);
     const colNdx = itemNdx % colCount;
     return [rowNdx, colNdx * colCount, colCount] as const;
   };
-
   if (table && ~ndx) {
     let i = ndx + 1;
     let s = getPosition(i - 1);
@@ -118,7 +118,8 @@ export const delItem = (store: DrawStore, item: SerialData) => {
       r = s;
       s = getPosition(i);
       for (let j = 0; j < s[2]; j++) {
-        table.content[r[0]][r[1] + j] = table.content[s[0]][s[1] + j];
+        Object.assign(table.content[r[0]][r[1] + j], table.content[s[0]][s[1] + j])
+        // table.content[r[0]][r[1] + j] = copy(table.content[s[0]][s[1] + j]);
         // if (j === 0) {
         //   table.content[r[0]][r[1] + j].content = oldItem.content!;
         // } else {
@@ -139,7 +140,19 @@ export const delItem = (store: DrawStore, item: SerialData) => {
       // store.setItem("serial", { id: data[i].id, value: { ...data[i] } });
       // oldItem = cur;
     }
-    table.content[s[0]][s[1]].content = "";
+
+    console.log(copy(table))
+    for (let j = 0; j < s[2]; j++) {
+      console.log({...table.content[s[0]][s[1] + j]})
+      table.content[s[0]][s[1] + j].content = "";
+      // if (j === 0) {
+      //   table.content[r[0]][r[1] + j].content = oldItem.content!;
+      // } else {
+      //   table.content[r[0]][r[1] + j].content =
+      //     table.content[s[0]][s[1] + j].content!;
+      // }
+    }
+    console.log(copy(table))
     const cols = table.content.flatMap((row) => {
       const cols = [];
       for (let i = 0; i < row.length; i += 2) {
@@ -147,13 +160,26 @@ export const delItem = (store: DrawStore, item: SerialData) => {
       }
       return cols;
     });
+
     const delRowCount = Math.floor(
       cols.filter((item) => item.content === "").length / 2
     );
+    console.log('delRowCount', delRowCount, cols.filter((item) => item.content === "").length)
     for (let i = 0; i < delRowCount; i++) {
       table.height -= table.content.pop()![0].height;
     }
+  }
+};
+
+export const joinKey = "serial-table";
+export const delItem = (store: DrawStore, item: SerialData) => {
+  const table = store
+    .getTypeItems("table")
+    .find((item) => item.key === joinKey)!;
+  const data = store.getTypeItems("serial");
 
+  delItemRaw(table, data, item);
+  if (table) {
     if (data.length === 1) {
       store.delItem("table", table.id);
     } else {
@@ -187,7 +213,7 @@ export const matResponse = (
 export const getPredefine = (key: keyof CircleData) => {
   if (key === "fill") {
     return { canun: true };
-  } else if (key === 'strokeWidth') {
-    return { proportion: true }
+  } else if (key === "strokeWidth") {
+    return { proportion: true };
   }
 };

+ 2 - 3
src/core/components/serial/serial-group.vue

@@ -139,11 +139,12 @@ const syncTable = (table: TableData) => {
     let colNdx = (i % colCount) * 2;
     if (colNdx) {
       table.content[rowNdx][colNdx].content = item.content!;
+      table.content[rowNdx][colNdx + 1].content = item.desc || "";
     } else {
       table.height += tempRow[0].height;
       let cols = [
         { ...tempRow[0], content: item.content! },
-        { ...tempRow[1], content: "", readonly: false },
+        { ...tempRow[1], content: item.desc || "", readonly: false },
       ];
       for (let i = 1; i < colCount; i++) {
         cols.push(
@@ -153,7 +154,6 @@ const syncTable = (table: TableData) => {
       }
       table.content.push(cols);
     }
-    
 
     isUpdate = true;
   }
@@ -171,7 +171,6 @@ const updateJoinTable = () => {
   if (!table) {
     history.preventTrack(() => {
       store.addItem("table", (table = addTable()));
-      console.log(table);
     });
   }
   if (syncTable(table!)) {

+ 1 - 2
src/example/components/slide/slide.vue

@@ -80,8 +80,7 @@ const enterItem = (item: MenuItem) => {
       });
     },
   };
-  const cleanup = hoverMenu.push(svar);
-  return cleanup;
+  return hoverMenu.push(svar);
 };
 const hover = hoverManage(enterItem);
 // enterItem(props.menus[2]);

+ 33 - 7
src/example/constant.ts

@@ -6,6 +6,7 @@ export type IconItem = {
   name: string;
   color?: string;
   parse?: {
+    key?: string;
     fill?: string;
     stroke?: string;
     type?: LineIconData["type"];
@@ -47,7 +48,7 @@ export const iconGroups: IconGroup[] = [
             parse: { type: "align-bottom" },
           },
           {
-             wall: true,
+            wall: true,
             icon: "yimen",
             name: "移门",
             parse: { type: "full" },
@@ -158,9 +159,36 @@ export const iconGroups: IconGroup[] = [
             color: "#DD2C2C",
             parse: { fill: "#DD2C2C", stroke: undefined },
           },
-          { icon: "shitiz_o", name: "尸体正面" },
-          { icon: "shitib_o", name: "尸体背面" },
-          { icon: "shitifuhao_o", name: "尸体" },
+          { parse: { key: "trace" }, icon: "shitiz_o", name: "尸体正面" },
+          { parse: { key: "trace" }, icon: "shitib_o", name: "尸体背面" },
+          { parse: { key: "trace" }, icon: "shitifuhao_o", name: "尸体" },
+
+          { parse: { key: "trace" }, icon: "handprint", name: "手印痕迹" },
+          { parse: { key: "trace" }, icon: "footprint", name: "足迹痕迹" },
+          {
+            parse: { key: "trace" },
+            icon: "wrenchAndScrewdriver",
+            name: "工具痕迹",
+          },
+          { parse: { key: "trace" }, icon: "video", name: "视听物证" },
+          { parse: { key: "trace" }, icon: "virus", name: "生物物证" },
+          { parse: { key: "trace" }, icon: "cartridge", name: "枪弹痕迹" },
+          { parse: { key: "trace" }, icon: "poison", name: "毒化物证" },
+          {
+            parse: { key: "trace" },
+            icon: "physics_and_chemistry",
+            name: "理化物证",
+          },
+          { parse: { key: "trace" }, icon: "folder_close", name: "文捡物证" },
+          { parse: { key: "trace" }, icon: "check", name: "特殊物证" },
+          {
+            parse: { key: "trace" },
+            icon: "case_other",
+            name: "其他物证",
+          },
+          { parse: { key: "trace" }, icon: "electronic", name: "电子物证" },
+          { parse: { key: "trace" }, icon: "cube", name: "提取物品" },
+          { parse: { key: "trace" }, icon: "corpse", name: "尸体" },
         ],
       },
     ],
@@ -206,6 +234,4 @@ export const styleIconMap = {
   "style-17": "chelunhenji_o",
 };
 
-export const traceIconMap = {
-  
-}
+export const traceIconMap = {};

+ 7 - 1
src/example/dialog/vr/vr.vue

@@ -28,7 +28,7 @@
 
 <script lang="ts" setup>
 import { ElSelect, ElOption, ElMessage } from "element-plus";
-import { computed, ref } from "vue";
+import { computed, ref, watch } from "vue";
 import { asyncTimeout } from "@/utils/shared";
 import { Scene, SceneTypeNames } from "../../platform/platform-resource";
 
@@ -59,6 +59,12 @@ const refresh = async () => {
   loading.value = false;
 };
 
+watch(scenes, (scenes) => {
+  if (scenes.length === 1) {
+    emit("update:value", scenes[0]);
+  }
+});
+
 const keyword = ref<string>("");
 const getSceneList = computed(() => window.platform.getSceneList(keyword.value));
 let oldKeyword: string;

+ 28 - 23
src/example/fuse/store.ts

@@ -2,16 +2,18 @@ import { Ref, ref } from "vue";
 import { StoreData } from "@/core/store/store";
 import { PaperKey } from "../components/slide/actions";
 import { overviewId, tabulationId } from "../env";
+import { DrawItem } from "@/core/components";
+import { IRect } from "konva/lib/types";
+import { ShapeType } from "@/index";
 
-
-export const tableCoverKey = '__tableCoverKey'
-export const tableCoverScaleKey = '__tableCoverScaleKey'
-export const tableTableKey = '__tableTableKey'
-export const tableTitleKey = '__tableTitleKey'
-export const tableCompassKey = '__tableCompassKey'
-export const mapImageKey = '__mapKey'
-export const tableCoverWidth = 370
-export const tableCoverHeight = 306
+export const tableCoverKey = "__tableCoverKey";
+export const tableCoverScaleKey = "__tableCoverScaleKey";
+export const tableTableKey = "__tableTableKey";
+export const tableTitleKey = "__tableTitleKey";
+export const tableCompassKey = "__tableCompassKey";
+export const mapImageKey = "__mapKey";
+export const tableCoverWidth = 370;
+export const tableCoverHeight = 306;
 
 export type TabCover = {
   url: string;
@@ -21,31 +23,34 @@ export type TabCover = {
     scale: number;
     unit: string;
   };
+  syncItems?: (DrawItem<ShapeType> & { rect: IRect; desc: string })[];
 };
 
 export const overviewData = ref() as Ref<{
-  title?: string
-  cover?: string
+  title?: string;
+  cover?: string;
   store: StoreData;
   viewport: number[] | null;
-}>
+}>;
 export const refreshOverviewData = () => {
   return window.platform.getOverviewData(overviewId.value).then((data: any) => {
-    overviewData.value = data
-  })
-}
+    overviewData.value = data;
+  });
+};
 
 export const tabulationData = ref() as Ref<{
   store: StoreData;
   cover: TabCover | null;
-  title?: string
+  title?: string;
   paperKey: PaperKey;
-  isAutoGen: boolean
+  isAutoGen: boolean;
   viewport: number[] | null;
-  mapUrl: string | null,
-  high?: number,
-  width?: number,
-}>
+  mapUrl: string | null;
+  high?: number;
+  width?: number;
+}>;
 export const refreshTabulationData = () => {
-  return window.platform.getTabulationData(tabulationId.value).then((data: any) => tabulationData.value = data)
-}
+  return window.platform
+    .getTabulationData(tabulationId.value)
+    .then((data: any) => (tabulationData.value = data));
+};

+ 44 - 20
src/example/fuse/views/overview/header.vue

@@ -29,6 +29,7 @@ import {
   tableCoverWidth,
   tableCoverHeight,
   overviewData,
+  TabCover,
 } from "../../store.ts";
 import { nextTick, onUnmounted } from "vue";
 import { DataGroupId } from "@/constant/index.ts";
@@ -79,7 +80,7 @@ const actions = [
           if (format !== "dxf") {
             const blob = await draw.enterTemp(async () => {
               const back = draw.config.back;
-              const [_, recover] = await setViewToTableCover();
+              const [_, _a, recover] = await setViewToTableCover();
               if (format === "jpg") draw.config.back = back;
               await nextTick();
               const blob = await getImage(draw, `image/${format}`);
@@ -112,10 +113,11 @@ const setViewToTableCover = async () => {
   const oldShowOffset = draw.config.labelLineConfig.showOffset;
   draw.initViewport(0);
   await nextTick();
-  const getRect = () => draw.stage!.findOne<Group>(`#${DataGroupId}`)!.getClientRect();
+  const getRect = (id: string) => draw.stage!.findOne<Group>(`#${id}`)?.getClientRect();
 
   const pop = draw.mode.push(Mode.readonly);
-  const rect = getRect();
+  const rect = getRect(DataGroupId)!;
+
   let width = rect.width;
   let height = rect.height;
   const rectScale = width / height;
@@ -148,11 +150,29 @@ const setViewToTableCover = async () => {
   draw.initViewport(padding);
   await nextTick();
 
+  const syncItems: TabCover["syncItems"] = [];
+  const positionRect = getRect("formal")!;
+  draw.store.items.forEach((item) => {
+    if (item.key === "trace") {
+      const itemRect = getRect(item.id);
+      if (itemRect) {
+        itemRect.x = itemRect.x - positionRect.x;
+        itemRect.y = itemRect.y - positionRect.y;
+        syncItems.push({
+          ...item,
+          rect: itemRect,
+          desc: (item as any).name || "",
+        } as any);
+      }
+    }
+  });
+
   return [
     {
       width,
       height,
     },
+    syncItems,
     () => {
       pop();
       draw.config.size = oldSize;
@@ -231,24 +251,26 @@ const setViewToKanKanCover = async () => {
 
 const saveHandler = repeatedlyOnly(async () => {
   const storeData = draw.getData();
-  const [tabBlob, listBlob, kkBlob, scale, rect] = await draw.enterTemp(async () => {
-    const back = draw.config.back;
-    const [rect, recover] = await setViewToTableCover();
-    await nextTick();
-    const mat = draw.viewer.transform.invert();
-    const scale =
-      lineLen(mat.point({ x: 1, y: 0 }), mat.point({ x: 0, y: 0 })) *
-      draw.store.config.proportion.scale;
-    const tabBlob = await getImage(draw, "image/png");
-    draw.config.back = back;
-    await nextTick();
-    const listBlob = await getImage(draw, "image/jpg");
-    recover();
-    await nextTick();
+  const [tabBlob, listBlob, kkBlob, scale, rect, syncItems] = await draw.enterTemp(
+    async () => {
+      const back = draw.config.back;
+      const [rect, syncItems, recover] = await setViewToTableCover();
+      await nextTick();
+      const mat = draw.viewer.transform.invert();
+      const scale =
+        lineLen(mat.point({ x: 1, y: 0 }), mat.point({ x: 0, y: 0 })) *
+        draw.store.config.proportion.scale;
+      const tabBlob = await getImage(draw, "image/png");
+      draw.config.back = back;
+      await nextTick();
+      const listBlob = await getImage(draw, "image/jpg");
+      recover();
+      await nextTick();
 
-    const kkBlob = await setViewToKanKanCover();
-    return [tabBlob, listBlob, kkBlob, scale, rect] as const;
-  });
+      const kkBlob = await setViewToKanKanCover();
+      return [tabBlob, listBlob, kkBlob, scale, rect, syncItems] as const;
+    }
+  );
 
   let tabUrl = null;
   let listUrl = null;
@@ -271,8 +293,10 @@ const saveHandler = repeatedlyOnly(async () => {
     width: rect.width,
     height: rect.height,
     proportion: { ...draw.store.config.proportion, scale },
+    syncItems,
   };
 
+  console.log(tabulationData.value.store);
   const tabStore = await repTabulationStore(
     tabulationData.value.paperKey,
     storeData.config.compass.rotation,

+ 98 - 3
src/example/fuse/views/tabulation/gen-tab.ts

@@ -24,6 +24,14 @@ import { getEmptyStoreData, StoreData } from "@/core/store/store";
 import { defaultLayer } from "@/constant";
 import { getIconStyle, IconData } from "@/core/components/icon";
 import { MathUtils } from "three";
+import {
+  delItemRaw,
+  getCurrentNdxRaw,
+  getSerialFontW,
+  joinKey,
+  SerialData,
+  defaultStyle as serialDefaultStyle,
+} from "@/core/components/serial";
 
 export const getRealPixel = (real: number, paperKey: PaperKey) => {
   const realPixelScale = paperConfigs[paperKey].scale;
@@ -85,7 +93,7 @@ export const genTabulationData = async (
     const valueColl = { ...nameColl, width: w2 };
     const tableTemp: Record<string, string> =
       window.platform.getTableTemp().table;
-    const rows = Object.entries(tableTemp)
+    const rows = Object.entries(tableTemp);
     const data = {
       ...getBaseItem(),
       content: rows.map(([name, value]) => [
@@ -164,7 +172,7 @@ export const genTabulationData = async (
 
   const getCoverScale = (cover: ImageData) => {
     const scale = (cover.widthRaw! / cover.width) * cover.proportion!.scale;
-    console.log(cover);
+
     const text = {
       ...getBaseItem(),
       content: `1:${scale}`,
@@ -238,14 +246,63 @@ export const genTabulationData = async (
     return data;
   };
 
+  const getSerials = (refImage: ImageData, items: TabCover["syncItems"]) => {
+    if (!items) return;
+
+    const scale = refImage.width / refImage.widthRaw!;
+    const offset = {
+      x: refImage.widthRaw! / 2,
+      y: refImage.heightRaw! / 2,
+    };
+
+    const mat = new Transform()
+      .multiply(new Transform(refImage.mat))
+      .scale(scale, scale)
+      .translate(-offset.x, -offset.y);
+
+    const serials: SerialData[] = [];
+    let i = 0;
+    for (const shape of items) {
+      const start = {
+        x: shape.rect.x,
+        y: shape.rect.y,
+        // x: refImage.widthRaw,
+        // y: refImage.heightRaw
+      };
+      const point = mat.point(start);
+      const s = {
+        ...serialDefaultStyle,
+        ...getBaseItem(),
+        padding: 3,
+        key: "join-" + shape.id,
+        content: (++i).toString(),
+        strokeWidth: getRealPixel(0.5, paperKey),
+        mat: [1, 0, 0, 1, point.x, point.y],
+        radiusX: 1,
+        desc: shape.desc || "",
+        radiusY: 1,
+      };
+      const radius = (getSerialFontW(s) * Math.sqrt(2)) / 2;
+      s.radiusX = s.radiusY = radius;
+      serials.push(s);
+    }
+    return serials;
+  };
+
   const data: DrawData = {
     table: [getTable()],
     text: [getTitle()],
+    serial: [],
   };
   const image = await getCover();
   if (image) {
     data.image = [image];
     data.text!.push(getCoverScale(image));
+
+    const serials = getSerials(image, cover?.syncItems);
+    if (serials) {
+      data.serial = serials;
+    }
   }
   if (compass !== undefined) {
     data.icon = [await getCompass()];
@@ -262,7 +319,7 @@ export const repTabulationStore = async (
 ) => {
   const repData = await genTabulationData(paperKey, compass, cover);
   const layer = store?.layers && store?.layers[defaultLayer];
-
+  console.error("rep", layer);
   if (!layer) {
     return {
       ...(store || {}),
@@ -305,6 +362,7 @@ export const repTabulationStore = async (
     }
     layer.text = texts;
   }
+
   if (repData.icon) {
     const iconData = repData.icon[0];
     const icons = layer.icon || [];
@@ -316,6 +374,43 @@ export const repTabulationStore = async (
     }
     layer.icon = icons;
   }
+
+  if (repData.serial) {
+    if (layer.serial) {
+      const oldSerials = [...layer.serial];
+      const notAutoSerials = oldSerials.filter(
+        (item) => !item.key?.startsWith("join-")
+      );
+      const newSerials = [...repData.serial, ...notAutoSerials];
+
+      layer.serial = newSerials;
+      const tableNdx = layer.table
+        ? layer.table.findIndex((table) => table.key === joinKey)
+        : -1;
+      if (~tableNdx) {
+        const table = layer.table![tableNdx];
+        layer.table!.splice(tableNdx, 1);
+
+        for (const serial of notAutoSerials) {
+          for (let r = 0; r < table.content.length; r++) {
+            for (let c = 0; c < table.content[r].length; c += 2) {
+              if (table.content[r][c].content === serial.content) {
+                serial.desc = table.content[r][c + 1].content;
+              }
+            }
+          }
+        }
+      }
+
+      const updateSerials = [...repData.serial];
+      for (const serial of notAutoSerials) {
+        serial.content = getCurrentNdxRaw(updateSerials);
+        updateSerials.push(serial);
+      }
+    } else {
+      layer.serial = repData.serial;
+    }
+  }
   // if (import.meta.env.DEV) {
   //   layer.table = repData.table
   //   layer.text = repData.text

+ 2 - 0
src/example/platform/platform-draw.ts

@@ -126,6 +126,7 @@ const getTaggingShapes = async (taggings: SceneResource["taggings"]) => {
       texts.push({
         ...getBaseItem(),
         ...textDefaultStyle,
+        key: item.key,
         content: item.url,
         zIndex: 1,
         mat: mat.m,
@@ -137,6 +138,7 @@ const getTaggingShapes = async (taggings: SceneResource["taggings"]) => {
       ...getBaseItem(),
       ...(item.size || { width: 100, height: 100 }),
       name: item.name,
+      key: item.key,
       createTime: now + ndx,
       url: item.url,
       mat: mat.m,

+ 2 - 0
src/example/platform/platform-resource.ts

@@ -35,6 +35,7 @@ export type TaggingInfo = {
   url: string;
   position?: Pos & { z?: number };
   mat?: number[];
+  key?: string,
   rotate?: number;
   size?: Size;
   name?: string;
@@ -45,6 +46,7 @@ export type TaggingInfo = {
 export type WallTaggingInfo = {
   url: string,
   pointIds: string[]
+  key?: string,
   name?: string
   height?: number,
 } & Pick<LineIconData, 'startLen' | 'endLen' | 'type' | 'openSide'>

+ 2 - 3
src/example/platform/resource-swkk.ts

@@ -20,7 +20,6 @@ import {
   Vector3,
 } from "three";
 import { extractConnectedSegments } from "@/utils/polygon";
-import { getImage } from "@/utils/resource";
 
 const fetchResource = genCache(
   (scene: Scene) => scene.m,
@@ -128,7 +127,6 @@ export const getCoverLine = async (
         y_max: bound.y_max * scale,
       };
     }
-    console.log(bound);
 
     const item = {
       name: floor.name,
@@ -269,7 +267,7 @@ export const getTraceTaggingInfos = async (
       getAttr
         .then((attr) => ({
           url: attr.url,
-          name,
+          name: trace.title || name,
           position: {
             x: trace.position.x * scale,
             y: trace.position.z * scale,
@@ -278,6 +276,7 @@ export const getTraceTaggingInfos = async (
                 ? Math.ceil(trace.position.y * scale * 10) / 10
                 : Math.floor(trace.position.y * scale * 10) / 10,
           },
+          key: 'trace',
           rotate: attr.angle,
           size: {
             width: attr.size.width * scale,

File diff suppressed because it is too large
+ 1086 - 0
test.json