From 625a9fbbcbc93a0df02bc5e098f0b1d6cac4dc88 Mon Sep 17 00:00:00 2001 From: HHY Date: Mon, 21 Sep 2026 05:31:23 -0700 Subject: [PATCH] =?UTF-8?q?fix:=20v2.3=20=E7=BB=84=E5=90=88=E6=8E=92?= =?UTF-8?q?=E5=88=97=203D=20=E9=87=8D=E5=8F=A0=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - CombineCanvas 新增 autoArrange: 单元按 X 序紧贴排布+底边对齐 - 拖动松手重叠检测: 与其他单元相交时自动重新排列 (消除 3D 玻璃面穿插与 z-fighting) - 工具栏新增自动排列按钮 - 移除 CombineCanvas 孤儿 @drop(归父容器统一处理) --- 3D窗型.png | Bin 4672 -> 6926 bytes CHANGELOG | 1 + frontend/src/components/CombineCanvas.vue | 44 +++++++++++++++++++++- frontend/src/views/CombineView.vue | 3 ++ 4 files changed, 46 insertions(+), 2 deletions(-) diff --git a/3D窗型.png b/3D窗型.png index 83b843ba02bc35b913c60512f9e740f025af146c..b5abc7a80385f42c5d70c73e68e9b1cd35716009 100644 GIT binary patch literal 6926 zcmZu$c|4Ts+n<>RgD{p*#B)?bMN&c~o%On+doA~MedmO=rKy<65)l%KB(`&h z@g5S1LMM^PC`}OlGvsCRnM9(Kb{cQBjUa#TY(MMizkR8iB?GB_8sQ=20cjWo-fZ)fZ6*Jd1B->~pP^IAD~ z!E+^H4$Yl*E_T;KeP7+PX?3~t>R$e9*U0SgZ@B~eCb|ZT-t~p|&%MeSNVy$eIe9r; zOweG#fBy2L1TX#JMy1gal!baxzFl68-r}+sVV@-ScPcgUyR+9*Z26os`jbwjrBf*Q zW~LXJ?BTUe4wrK#x0WIZdgO-aI}jsNsOzNZ$U46(U!)KeDP&DkZ?Z^|ix$pHGC-2C zMpb%#?a6N-`Im(KR$TIt6difwd%0E$yD*wUod6ZK2)PLp3N41O#ktqaSg0>~T$tW} zl0|AxwsaJND{1uSJ5bj1yH1zP@GEI_c@Y}jNcb#aTU85%!fCO!TuvNIJ7S8m`Ykmd z9LLn99ax5-2i~p{wa~~gz`nnW(&#g?X_6QUWQq+OWV3Cf24)E$(X@h0zPYP2R~EPD z+zA%x{La7jXxf0bu)1~)f}Zw^u*9vQnXf=l^V*Bk%RyTV;UX{~V7$f`Ho})I=p^GG zEP|_#1X-gjz5bp>#Mjz5RFLd((nT*0*O2aGhq8Q<_iEvnSjSi8k#C;%|0qCgZn_0P z+{!E=j@6~gR)~;2dN?8kYCqu8A4h#nG4;+lXZ$fuF&40RY=WQEQ~;6%cc(B(3^xrL zjjn;LCY)ggZZsRb`*VKH4%X}nJ}?MV@+lPK{4}p+U!C++Y(SxebutK+2Pe0p95@U9-#7R3R%YlgD!-tW}eMI_)w@cP9!J7)-deqlbJ zoIbGE$Lx(hVWbKedDE-i7tdo7(xjoyOSVJ>5!rqO$))QX$1;u@x zuOIyj0tq5wCup~`vp|k85)Z5+1MBcL5}P3aMs8>%yuJz)cRpC4Lfo$oXFiDeD2AKi zW0G-_)O_;R{Mx*3tB5tTj5tzr%brGvY&mMc=2)GM=$;1Vwaxib0UMs=TKXXw8hGx@hSki+`@z!vC$6C^_@BW7Dos(Aj)qd>FTy`>wK$}r;UG6W@vNS9WLs5df@Q&tPLsRanIaHXBFpd4@7f{p zLj0}-=hDDWR0dSYKcf{_SQl3Pob0e0pOf}?b)q0E;XH#;aY!GLt| zw~L`tK28}QOC>ZmuQo*-;Oe$lPP%LXk>Z(Lbf1m1nlV(2Tjw8d%~;9iwdqKAMf>lEa{$jT_4=VC6UqK-5Yr`>9O>*M zm_7LpDQEzML%`Dft_uPehBfBCA1jsExi>?P{Q!dI!AH+Ls;p}Fa82)_M)M3~2mnsb z$G0!2t19X{6HcZE4pJ@E5cC@Tl_%9q%CV(0A;jC>%;OP+)-w>-T4?pBh+5hXfXR5I zUh4TiczVj%m#mnsY?IFDE8#9Vs%S<#TwgTvwrjxl{vLoXcI;;TyLN4M37}jeY=I(f zWPbfXRHXM8>K;Jz-sW6~PY#r9QBJ8uww&EL659hV@^C)5jOryFH0iFR=`D@F5s6BI z?0RZU4?EoU@&5J|XvRTM{^0I0Nr-{U#~(%oos`(-)FQ?j1Mm&n6YKye)|75<` zWA6vw?Pn=6npUtGZBkr)j$~h1P>%<1N~mj5eB~vp>ms`EEE86@#cqmvxeVYChs+Vu zD?_Xk(1qe>4d)yqzJF7#mbQxWTkHD!m%9C_pTx?OTbuR{#|>rs?dL|C0oGd}F<(D* zpxDqZhSXmVjA`$kEuTz~XY}%hlk-Z&%D?26mM%T&zH(pX#LN_nN`l2KH^Z-4qONx?mQ{2!l}-hu6W`?`J$ ztP(mi`QfMUFFuq;Vz*C+FI9t(VmgDU^F2=AN-JhFB`a&SZnFHGBF91qq5vI-Xd721 zlkmu7hQZEN>s2MyY`V=}2a-L*-sRBLU8}fCr*!SvpahjBqk7JSrDoX~PXy~%5dSJx z5QS&Jxoymor1Kt5zEVh2X4UZfO5^*DPkiC!dk7t0Aoszws$PMk<+W|rY!bVcrXFEW z_IO&Asd}!EwOQJ!=yk8K`W}?!cq^ww`0q7q`<5n--Ejz!%Z;I^E>fG@M83(BZAXYV z#TA~yu9nl(A2P*{()ylcU#-ffmK6no@>mP^+=w|-BDY<1$Uh)Hw{XMJAz>_Bz%dCX zWen@ws-eDDN+qS&cX4T{-mi}5K2o%IaH#pwniTZ&$4k>RE{QEn5w}BfZJ#RnpC_?b zQZEe`Zz=onYFE#f^vFowi>Z*FFSiSG^ViqLS^kD*m_fGGKZYvxg3@-hJSe+JD(v#* znnJPg-xz+OBX?Iw`fLSl$xgx)7n%1Ty7Yscvf7HOza=F#l~%m16g~X;`IsVtX1KyJ zU0v-P*(WHgFMp!lC{pNsnBADfW16dWt5g2Bk!)b(hWc)J@F_CTaZ?E6TKP~~(Ehh> zqt`5&K2YnSjMQ`UmP+aEVXmADZCrLXKDT}EV#US*!^ayO^B_FcodMs1+$rHBj?9^l z<9|7{@rP@Fyy*&*ykq(4_kVsrLr1J{S9Nj4?E*S8g z&%W~O3hoCZBS*Rhl3%(H{z!g0_NDdhvAUHN&~>xTAcf7A_@`2z39NBB>JY(=?2=ZB znuOGko;;o(Si1VVx@MeBV40+)OU07m*{)sgQ+0+5+jSWoH{{csLMYVx&`90)`@K^k zroUVw-f*TtIW1y#TF8(tyRmor>yn>8Ez0I@2$?FgMCI1R7d=o%nghs!>CArlxCEB(D2CBp3l6{gmnJ9 zz*y~tb*2UrqtXe5JGTa&-;x+&wa~pTu3+UEIex6R!h>zllH6?6*(k&7=g!6OCjPXN zaMSteSR3_;cllvLLgj>nZW4EH(&pG?#bo8{<2`z@UgI2h|2@x7#Xi>zR$s@dEm5BP z=rCh%dbYS|m4UfVN+D!X=#2W@a>_Q&ci-1rW)AUw$W_XFMDU)q&5(Q3r^&rdydQmh z75%9Ga{1+65AFLFX}yp65;&*BkxXy9$86gOFT}>sm(Hr94MDbvSH%5f6sK?Wlz69$ zYU!JY-_AcHmDq#CAJ;SZk!Ka}Hr48;aGIBLnp->ix6P-G1HoMB{?pJhq}V&|Xs3+o ze&?nB-X2=&$}O4ejMt0deopWI6w2EZk)y2G+duuJ^l=66!%25UeCrLr&b+kwj#*OR zk)oFI>`d&ecf?R(+Y*IA1qJsvdO7xG6U8CV&ISeqSU!;JQ#iA;&tR-!y*p3iq=2!< zIuc2w2;%}YV@G!-jjw-K)+#Ss+?rRz6?>g@cGNNId$qiT@E_acHhGBo!!zpdo7K9L zZOCi!26yvogL8rkVc;EGip~HQrmEHF4O?A|KrK@;@@8=)7;q+O#*pXu+ zfoJvCiAY#<`M>Y@$k&Vs2=I?v@VT)&q`SPPuWaf`<@en?PWDMGXwFvpT%vV=v;Xtf z!I7~D{WLk#s2CoPH&|CO&g=G;X2czjXed&;S+V;RH0EY^hW4*vN2sdIz5RRNp9g{t zFI1?>lT%a@bDPSl92QD6HHzx|NA{h4TeY)cH%DusR!!aBa$Wr}o>tD_NTg}`nLhD8 zB?;$*^t!>%zaQrGjYcfIz~>bv7%9firWi^n^ST2UK2tTAy0@D}m%5p|6`_)=@35*; zDO$#y*ppFXo_P|Z?J}c*wwyql7M{_0EwyI`5((*6Y7>72>=%Vj_bORu*Kd?jiR2!u zTHR53e$c=hUQ&szTeeKAPWnV#-GDvmG`gB=#tG7H{R?8igJ3O<5WK&~lw66?#fNW~!~}O}oQsSmt4xYJ8{!A;fcbGb>Tm&jvtWodgcnHbVa6aK7zcuJ7Db*Q z2pyJTEcDiVrH@39<>La?`ue`D#9DgQEOaun@m_>Ft&l&hg&pz2*nnujmV$aG^~6U4 ze>*cgp@Mq`eW6`Matq3?j_RmihY1RH{P&oM36r7E{I@ZYSfl=DOe~`7g?oLGNj8PIVI#VQ*iqRVGswiKyEZd+%jfABTP@uskTT_{gWdHMeJGmKi9m zx4#_O^RYF{eSdWHhyp#U>ws(wyxdZ@zwFJSj`4nlqlInV|E`tXQhI_;Z6-@#HqmYtA2XN;D=c z5kL0r2M&RwR9b`jTAH+Bl&1`%cQC6hygJJvpuoVRGex%>c)m@*%oVf~o1 zoWx!w;4DnHtN*A?q=qBRd&MP>x8s6e=~p7|k+ja&VSx&g-S%*9wr!ayzPd;BNLdA` z85?YH*?yoCn`?6%rLivvdA>ZE+$)bH;ORhOr-DmUEy|2ASzv>>Ww09?n+e%8_$p6x zl!Pyg4(fIUSw|IBY*vB&zdGc3ZgL$A2}0V;sc@UJGTe!dg>?>O8~v8O$w?@540$sLUbH%$Ink5Sh3O ze0=$dy9U8*K??`=t-NuKK<*b+c^hUctU5e`Y5UQ^j=rqR1a4Fo1+iriOc6G%*GizFYUlj3Xt6~bB1*Oom(jG>2tTC3-D}Lzlz#RGMzAD409yP8d*&Ekm?0i zdND$<3W%*B<#0!Z5RfX^C6Ayfd*qiQAU)4uZKESm#HdPQrvS1kFJP8Ofzbwf`44bf z+#1IPAO`fZIoR>Q{n9+U1p^Po*mf;GH-IFdl~R1oe4gFvj|WMNpdloI>w13QMK%>@ zv}yGBpu&V=)Cxi&FNh+qs^EF<3(Z&!=Q?b1Uy4J3ECVb5^1AJMAE%yCCQRWASLn~< zZUcqH#^$!cZi0GlS_(CLb9t^50WEN+TAo?|FHYtI&PL>b6q4DI^mbli|7w9LOb*5K_vp^^MLa1eE($J2ihyF%~(G5 zH3WP5-&I&!8WDf>ZT^P@>tYa%IOcyA7gb!b_Vo;fqklAq2)|_TZL&_+V=Q%%LbPjK zAhB%5o8X=i?5B<6F1s-e0I<0zis1qhiO;`O63`33Y6)U3>;e*FM*UsKYK0&0AJR?} LOXHkv%s>7Ip3z_J literal 4672 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 diff --git a/CHANGELOG b/CHANGELOG index fd04bcd..cb49c66 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,6 @@ # CHANGELOG +- [2026-09-21 12:35] FIX: v2.3 组合排列 3D 重叠修复——①CombineCanvas 新增 autoArrange: 全部单元按 X 序紧贴排布+底边对齐; ②拖动松手重叠检测: 移动单元与其他单元相交时自动重新排列(消除 3D 玻璃面穿插/z-fighting); ③CombineView 工具栏新增自动排列按钮; ④组合画布移除孤儿 @drop(归父容器) (Files: frontend/src/components/CombineCanvas.vue, frontend/src/views/CombineView.vue) - [2026-09-21 12:40] FIX: v2.2 前端完整性治理——引入 vue-tsc 全量类型检查并清零全部错误: ①组合画布 3D 扇面板解构键名错误(rect/s→rect/sash)致扇面板全挂(3D 混乱根因之一); ②WindoorCanvas isDoor 标注 cx 作用域泄漏; ③WindoorThreed rebuild 函数缺失(墙体开关点击报错)+wallBoxes 元组类型; ④量尺页 openCreate 未定义(点击报错); ⑤状态筛选 ref 类型纳入空串(el-select clearable 语义); ⑥CombineCanvas 移除孤儿 @drop(归父容器)+容器补 dragover.prevent(修复拖放入库); ⑦AIRenderCanvas style 属性名保留处理+表单联合类型; ⑧零散隐式 any 参数; 新增检查脚本 scripts/check-frontend.cjs(未定义引用+API 路径一致性比对) (Files: frontend/src/**, frontend/scripts/check-frontend.cjs) - [2026-09-21 12:25] FIX: v2.2 修复 3D 截图为纯色空白——墙体尺寸单位错误(bw=1/S*0.72 误用模型单位≈2304, 而放置坐标是世界单位±0.5), 相机被包在数千单位宽的巨墙内只见背景色; 改为世界单位(侧墙 0.55, 上下墙覆盖窗洞±2.2), 墙体不投影(避免自身遮挡), Node 验证四墙尺寸全部 ≤2.2 世界单位 (Files: frontend/src/components/WindoorThreed.vue) - [2026-09-21 12:10] FIX: 3D"解析失败"根因修复+错误可见性——①根因: watch immediate 首跑时 camera 未创建而 build() 触碰 camera 抛 TypeError; 移除 build 内相机定位(每帧 loop 已定位); ②shadowMap.type 赋值整行移除(three r186 已移除 PCFSoft 常量, 默认即 PCFShadowMap, 杜绝弃用警告); ③解析失败时显示真实错误信息(info+console.error), 便于后续定位; 重建 dist 后 PCFSoft 赋值触发路径已清零 (Files: frontend/src/components/WindoorThreed.vue) diff --git a/frontend/src/components/CombineCanvas.vue b/frontend/src/components/CombineCanvas.vue index d7070cc..af21c70 100644 --- a/frontend/src/components/CombineCanvas.vue +++ b/frontend/src/components/CombineCanvas.vue @@ -305,9 +305,15 @@ function onMove(e: MouseEvent) { function onUp() { if (dragUnit) { - if (dragUnit.moved) emit('change') + const uid = dragUnit.uid + const moved = dragUnit.moved guides = { v: [], h: [] } dragUnit = null + if (moved && uid !== null && unitOverlaps(uid)) { + // 拖动后与其他单元重叠 → 自动重新排列消除重叠 + autoArrange() + return + } render() return } @@ -362,6 +368,40 @@ function nudgeSelected(dx: number, dy: number) { emit('change') } +function rectsIntersect(a: BBox, b: BBox): boolean { + return a.x0 < b.x1 - 1 && b.x0 < a.x1 - 1 && a.y0 < b.y1 - 1 && b.y0 < a.y1 - 1 +} + +/** 单元是否与其它单元重叠 */ +function unitOverlaps(uid: number): boolean { + const bb = unitBBox(uid) + if (!bb) return false + return uids().filter(u => u !== uid).some(u => { + const o = unitBBox(u) + return o ? rectsIntersect(bb, o) : false + }) +} + +/** 自动排列: 全部单元按 X 序紧贴排布、底边对齐(消除重叠) */ +function autoArrange() { + const ids = uids().filter(u => unitBBox(u)).sort((a, b) => + (unitBBox(a)!.x0) - (unitBBox(b)!.x0)) + if (!ids.length) return + let bottom = Infinity + for (const id of ids) { + const bb = unitBBox(id)! + bottom = Math.min(bottom, bb.y0) + } + let x = ids.length ? unitBBox(ids[0])!.x0 : 0 + for (const id of ids) { + const bb = unitBBox(id)! + translateUid(id, x - bb.x0, bottom - bb.y0) + x += bb.x1 - bb.x0 + } + refresh() + emit('change') +} + function exportDrawing(): string | null { if (!props.shapes.length) return null return JSON.stringify({ @@ -369,7 +409,7 @@ function exportDrawing(): string | null { epi: [], sbf: [], wlc: '', wall: [], scale: 0, note: [], }) } -defineExpose({ refresh, modelAt, exportDrawing, rotateUnit, mirrorUnit, resizeSelected, nudgeSelected }) +defineExpose({ refresh, modelAt, exportDrawing, rotateUnit, mirrorUnit, resizeSelected, nudgeSelected, autoArrange }) onMounted(() => { watch(() => props.shapes, () => { selectedUid.value = null; rebuild() }, { immediate: true }) diff --git a/frontend/src/views/CombineView.vue b/frontend/src/views/CombineView.vue index 13e41e3..8a92b10 100644 --- a/frontend/src/views/CombineView.vue +++ b/frontend/src/views/CombineView.vue @@ -41,6 +41,9 @@ + + 自动排列 + 底边对齐 删除单元