feat: v0.5 画布尺寸编辑+自动报价+扇样式保真修复
- 参数化尺寸编辑: W/H输入框 + 拖拽外框右缘/下缘/右下角手柄 - 全部几何按比例自动缩放(型材料宽不变, 最小300mm) - 拖拽过程静默更新, 松手提交或回滚撤销点 - 自动报价: 画布变化600ms防抖调用offer-price, 实时显示总价 - 修复样板显示为默认矩形的问题: 扇样式推断引擎三级解析 (有效bd → polyId区域映射双扇对半 → 帧bbox按扇数竖向均分) - 还原真实分格与开向(od角度/inward空心/门标注) - 无图纸订单显示引导提示
This commit is contained in:
@@ -24,18 +24,19 @@
|
||||
<div v-if="current" class="preview">
|
||||
<div class="canvas-box">
|
||||
<WindoorCanvas ref="editRef" :drawing-data="current.drawing_data"
|
||||
:editable="editing" @change="dirty = true" />
|
||||
:editable="editing" @change="onCanvasChange" />
|
||||
</div>
|
||||
<div class="meta">
|
||||
<template v-if="!editing">
|
||||
<span>尺寸限制: {{ current.low_width }}-{{ current.high_width }} × {{ current.low_height }}-{{ current.high_height }} mm</span>
|
||||
<span>引用次数: {{ current.times }}</span>
|
||||
<el-button type="success" size="small" @click="quoteRef.open({ template_id: current.id })">算料报价</el-button>
|
||||
<el-button size="small" @click="editing = true">编辑分格</el-button>
|
||||
<el-button size="small" @click="editing = true">编辑分格/尺寸</el-button>
|
||||
<el-button type="primary" size="small" @click="useInOrder">用此样板下单</el-button>
|
||||
</template>
|
||||
<template v-else>
|
||||
<span class="tip">左侧工具:+竖梃/+横梃 → 点击玻璃区域完成分割,支持撤销</span>
|
||||
<span class="tip">改 W/H 或拖右下角手柄缩放;+竖梃/+横梃点击分割</span>
|
||||
<span class="live-price" v-if="liveTotal !== null">当前报价 ¥{{ liveTotal }}</span>
|
||||
<el-button size="small" @click="cancelEdit">取消</el-button>
|
||||
<el-button type="primary" size="small" :disabled="!dirty" @click="saveAsTemplate">另存为我的样板</el-button>
|
||||
</template>
|
||||
@@ -69,6 +70,22 @@ const current = ref<any>(null)
|
||||
const editing = ref(false)
|
||||
const dirty = ref(false)
|
||||
const editRef = ref()
|
||||
const liveTotal = ref<number | null>(null)
|
||||
let quoteTimer: number | undefined
|
||||
|
||||
// 画布变化(改尺寸/加分格)→ 防抖自动重算报价
|
||||
function onCanvasChange() {
|
||||
dirty.value = true
|
||||
clearTimeout(quoteTimer)
|
||||
quoteTimer = window.setTimeout(async () => {
|
||||
const drawing = editRef.value?.exportDrawing()
|
||||
if (!drawing) return
|
||||
try {
|
||||
const r = await api<any>('post', '/api/offer-price', { drawing_data: drawing })
|
||||
liveTotal.value = r.total
|
||||
} catch { /* 报价失败不打断编辑 */ }
|
||||
}, 600)
|
||||
}
|
||||
|
||||
async function load() {
|
||||
loading.value = true
|
||||
@@ -85,6 +102,7 @@ async function preview(t: any) {
|
||||
current.value = await api<any>('get', `/api/windoor/templates/${t.id}`)
|
||||
editing.value = false
|
||||
dirty.value = false
|
||||
liveTotal.value = null
|
||||
previewVisible.value = true
|
||||
}
|
||||
|
||||
@@ -130,5 +148,7 @@ onMounted(async () => {
|
||||
.pic { width: 100%; height: 110px; }
|
||||
.cap { font-size: 12px; color: #606266; margin-top: 6px; text-align: center; }
|
||||
.preview .canvas-box { height: 60vh; border: 1px solid #e4e7ed; border-radius: 6px; overflow: hidden; }
|
||||
.preview .meta { display: flex; gap: 20px; margin-top: 10px; color: #606266; font-size: 13px; align-items: center; }
|
||||
.preview .meta { display: flex; gap: 20px; margin-top: 10px; color: #606266; font-size: 13px; align-items: center; flex-wrap: wrap; }
|
||||
.tip { color: #909399; }
|
||||
.live-price { color: #e6483d; font-size: 16px; font-weight: 700; }
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user