feat: v1.6 组合画布编辑能力增强
- 选中单元可视化: 蓝色虚线框+四角手柄+实时尺寸标注 - 精确尺寸编辑: 工具栏 W/H 输入框(几何按比例缩放, 锚定左下角) - 方向键微调: 1mm/Shift+方向键 10mm - 右侧单元清单点击选中与画布联动, selSize 双向同步
This commit is contained in:
@@ -34,6 +34,13 @@
|
||||
<el-tooltip content="选中单元水平镜像" placement="top">
|
||||
<el-button size="small" :disabled="!selectedUid" @click="canvasRef?.mirrorUnit(selectedUid!)">⇋ 镜像</el-button>
|
||||
</el-tooltip>
|
||||
<template v-if="selectedUid">
|
||||
<span style="font-size:12px; color:#909399">尺寸</span>
|
||||
<el-input-number v-model="selSize.w" :min="300" :step="10" size="small" controls-position="right"
|
||||
style="width:96px" @change="onSelResize" />
|
||||
<el-input-number v-model="selSize.h" :min="300" :step="10" size="small" controls-position="right"
|
||||
style="width:96px" @change="onSelResize" />
|
||||
</template>
|
||||
<el-divider direction="vertical" />
|
||||
<el-button size="small" :disabled="!selectedUid" @click="alignBottom">底边对齐</el-button>
|
||||
<el-button size="small" :disabled="!selectedUid" type="danger" plain @click="deleteSelected">删除单元</el-button>
|
||||
@@ -42,7 +49,7 @@
|
||||
</div>
|
||||
</template>
|
||||
<div class="canvas-box" @drop="onDrop" style="position:relative">
|
||||
<CombineCanvas ref="canvasRef" :shapes="shapes" @select="onSelect" @change="refreshMeta" />
|
||||
<CombineCanvas ref="canvasRef" :shapes="shapes" @select="onSelect" @change="onCanvasChange" />
|
||||
</div>
|
||||
<div class="save-bar">
|
||||
<el-input v-model="saveName" placeholder="组合样板名称(如:三扇组合窗)" style="flex:1" />
|
||||
@@ -84,7 +91,7 @@
|
||||
* 数据模型:shapes = 多形状 drawing_data 的 sm[](每形状打 __uid 单元标记);
|
||||
* 组合结果与渲染/报价/AI 炫图/3D 全链路兼容,可另存为"我的样板"。
|
||||
*/
|
||||
import { computed, onMounted, onBeforeUnmount, ref } from 'vue'
|
||||
import { computed, onBeforeUnmount, onMounted, reactive, ref } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { api } from '../api'
|
||||
import { parseDrawing } from '../types/drawing'
|
||||
@@ -181,7 +188,21 @@ async function onDrop(e: DragEvent) {
|
||||
}
|
||||
|
||||
// ---------- 单元操作 ----------
|
||||
function onSelect(uid: number | null) { selectedUid.value = uid }
|
||||
function onSelect(uid: number | null) { selectedUid.value = uid; syncSelSize() }
|
||||
|
||||
const selSize = reactive({ w: 0, h: 0 })
|
||||
|
||||
function syncSelSize() {
|
||||
if (selectedUid.value === null) { selSize.w = selSize.h = 0; return }
|
||||
const bb = bbOf(shapes.value.filter(s => s.__uid === selectedUid.value))
|
||||
if (bb) { selSize.w = Math.round(bb.x1 - bb.x0); selSize.h = Math.round(bb.y1 - bb.y0) }
|
||||
}
|
||||
|
||||
function onCanvasChange() { refreshMeta(); syncSelSize() }
|
||||
|
||||
function onSelResize() {
|
||||
if (selSize.w >= 300 && selSize.h >= 300) canvasRef.value?.resizeSelected(selSize.w, selSize.h)
|
||||
}
|
||||
function selectUnit(uid: number) { selectedUid.value = uid; canvasRef.value?.refresh() }
|
||||
|
||||
function refreshMeta() {
|
||||
@@ -249,7 +270,13 @@ async function saveAsTemplate() {
|
||||
}
|
||||
|
||||
function onKeydown(e: KeyboardEvent) {
|
||||
if (e.key === 'Delete' && selectedUid.value !== null) deleteSelected()
|
||||
if (e.key === 'Delete' && selectedUid.value !== null) { deleteSelected(); return }
|
||||
// 方向键微调选中单元(1mm,Shift=10mm)
|
||||
if (selectedUid.value !== null && e.key.startsWith('Arrow')) {
|
||||
const step = e.shiftKey ? 10 : 1
|
||||
const d = { ArrowLeft: [-step, 0], ArrowRight: [step, 0], ArrowUp: [0, step], ArrowDown: [0, -step] }[e.key] as [number, number] | undefined
|
||||
if (d) { e.preventDefault(); canvasRef.value?.nudgeSelected(d[0], d[1]) }
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
|
||||
Reference in New Issue
Block a user