| | |
| | | <div style="display: flex; height: 90vh;">
|
| | | <!-- Sidebar -->
|
| | | <div class="sidebar" style="width: 200px; background: #f4f4f4; padding: 10px; height: 93%; overflow-y: auto; max-height: 90vh; border-radius: 8px;">
|
| | | <div
|
| | | v-for="(layout, layoutIndex) in layouts"
|
| | | :key="layoutIndex"
|
| | | class="sidebar-item"
|
| | | @click="selectLayout(layoutIndex)"
|
| | | :class="{ 'selected': selectedLayoutIndex === layoutIndex }" style="margin-bottom: 5px;"
|
| | | >
|
| | | {{ layout.realWidth }} × {{ layout.realHeight }} × {{ layout.quantity }}
|
| | | <div class="folder">
|
| | | <div
|
| | | class="folder-header" style="padding: 8px; background: #e0e0e0; margin-bottom: 5px; border-radius: 4px; user-select: none; display: flex; justify-content: space-between; align-items: center;"
|
| | | >
|
| | | <span @click="toggleFolder('pending')" style="flex: 1; cursor: pointer;">待切割原片</span>
|
| | | <button
|
| | | @click="toggleFolder('pending')" style="background: none; border: none; cursor: pointer; font-size: 14px; padding: 2px 5px; border-radius: 3px;"
|
| | | :title="openFolders.pending ? '收起' : '展开'"
|
| | | >
|
| | | <el-icon v-if="openFolders.pending"><ArrowUp /></el-icon>
|
| | | <el-icon v-else><ArrowDown /></el-icon>
|
| | | </button>
|
| | | </div>
|
| | | <div v-show="openFolders.pending" class="folder-content" style="padding-left: 15px;">
|
| | | <div
|
| | | v-for="(layout, layoutIndex) in layouts"
|
| | | :key="layoutIndex"
|
| | | class="sidebar-item"
|
| | | @click="selectLayout(layoutIndex)"
|
| | | :class="{ 'selected': selectedLayoutIndex === layoutIndex }" style="margin-bottom: 5px;"
|
| | | >
|
| | | {{ layout.realWidth }} × {{ layout.realHeight }} × {{ layout.quantity }}
|
| | | </div>
|
| | | </div>
|
| | | </div>
|
| | |
|
| | | <!-- 待补片队列文件夹 -->
|
| | | <div class="folder">
|
| | | <div
|
| | | class="folder-header" style="padding: 8px; background: #e0e0e0; margin-bottom: 5px; border-radius: 4px; user-select: none; display: flex; justify-content: space-between; align-items: center;"
|
| | | >
|
| | | <span @click="toggleFolder('patchQueue')" style="flex: 1; cursor: pointer;">待补片队列</span>
|
| | | <button
|
| | | @click="toggleFolder('patchQueue')" style="background: none; border: none; cursor: pointer; font-size: 14px; padding: 2px 5px; border-radius: 3px;"
|
| | | :title="openFolders.patchQueue ? '收起' : '展开'"
|
| | | >
|
| | | <el-icon v-if="openFolders.patchQueue"><ArrowUp /></el-icon>
|
| | | <el-icon v-else><ArrowDown /></el-icon>
|
| | | </button>
|
| | | </div>
|
| | | <div v-show="openFolders.patchQueue" class="folder-content" style="padding-left: 15px;">
|
| | | <div style="padding: 10px; color: #666; font-style: italic;">
|
| | | 暂无补片任务
|
| | | </div>
|
| | | </div>
|
| | | </div>
|
| | |
|
| | | <!-- 添加自定义尺寸文件夹 -->
|
| | | <div class="folder">
|
| | | <div
|
| | | class="folder-header" style="padding: 8px; background: #e0e0e0; margin-bottom: 5px; border-radius: 4px; user-select: none; display: flex; justify-content: space-between; align-items: center;"
|
| | | >
|
| | | <span @click="toggleFolder('customSize')" style="flex: 1; cursor: pointer;">添加自定义尺寸</span>
|
| | | <button
|
| | | @click="toggleFolder('customSize')" style="background: none; border: none; cursor: pointer; font-size: 14px; padding: 2px 5px; border-radius: 3px;"
|
| | | :title="openFolders.customSize ? '收起' : '展开'"
|
| | | >
|
| | | <el-icon v-if="openFolders.customSize"><ArrowUp /></el-icon>
|
| | | <el-icon v-else><ArrowDown /></el-icon>
|
| | | </button>
|
| | | </div>
|
| | | <div v-show="openFolders.customSize" class="folder-content" style="padding-left: 15px;">
|
| | | <div style="padding: 10px;">
|
| | | <button
|
| | | @click="showAddCustomSizeDialog" style="width: 100%; padding: 8px; background: #409eff; color: white; border: none; border-radius: 4px; cursor: pointer;"
|
| | | >
|
| | | + 添加自定义尺寸
|
| | | </button>
|
| | | </div>
|
| | | </div>
|
| | | </div>
|
| | |
|
| | |
|
| | | </div>
|
| | |
|
| | | <!-- Main Layout Panel -->
|
| | |
| | | class="layout-glassDetail"
|
| | | :style="rectStyle(glassDetail, layoutIndex)"
|
| | | @contextmenu.prevent="handleRectRightClick(layoutIndex, rectIndex)"
|
| | | @mousedown="handleRectDragStart(layoutIndex, rectIndex)"
|
| | | @mousemove="handleRectDragging"
|
| | | @mouseup="handleRectDragEnd"
|
| | | @mouseleave="handleRectDragEnd"
|
| | | @click="handleRectClick(layoutIndex, rectIndex)"
|
| | | >
|
| | | <div class="glassDetail-content">
|
| | |
| | | </div>
|
| | | </div>
|
| | |
|
| | | <!-- 提交按钮 -->
|
| | | <button @click="submitLayouts" style="position: fixed; top: 90px; right: 20px; padding: 10px; background: #4CAF50; color: white; border: none; border-radius: 5px; cursor: pointer;">
|
| | | <button @click="submitLayouts" style="position: fixed; top: 90px; right: 20px; padding: 10px; background: #409eff; color: white; border: none; border-radius: 5px; cursor: pointer;">
|
| | | 保存调整
|
| | | </button>
|
| | | </div>
|
| | |
| | |
|
| | | <script setup>
|
| | | import { ref, reactive, onMounted, onUnmounted } from 'vue';
|
| | | import { useRouter } from 'vue-router'; // 添加这行
|
| | | import { useRouter } from 'vue-router';
|
| | | import { ArrowUp, ArrowDown } from '@element-plus/icons-vue'
|
| | | import request from "@/utils/request";
|
| | | const router = useRouter(); // 添加这行
|
| | | const router = useRouter();
|
| | | import { useI18n } from "vue-i18n";
|
| | | import { ElMessage, ElMessageBox } from "element-plus";
|
| | | import useUserInfoStore from "@/stores/userInfo";
|
| | |
| | | const rectClass = ref('layout-glassDetail');
|
| | | const selectedLayoutIndex = ref(0);
|
| | | const currentRect = ref(null);
|
| | | const dragging = ref(false);
|
| | | const dragStartPos = ref({ x: 0, y: 0 });
|
| | | const dragRect = ref(null);
|
| | | // const dragging = ref(false);
|
| | | // const dragStartPos = ref({ x: 0, y: 0 });
|
| | | // const dragRect = ref(null);
|
| | | const showJiaHao = ref(false);
|
| | | const showProcessId = ref(false);
|
| | | const themeColor = ref(null);
|
| | |
| | | const submitLayouts = async () => {
|
| | | layouts.value.forEach(layout => {
|
| | | layout.glassDetails.forEach(glassDetail => {
|
| | | glassDetail.x = Math.round(glassDetail.x);
|
| | | glassDetail.y = Math.round(glassDetail.y);
|
| | | glassDetail.width = Math.round(glassDetail.width);
|
| | | glassDetail.height = Math.round(glassDetail.height);
|
| | | glassDetail.x = parseFloat(glassDetail.x.toFixed(2));
|
| | | glassDetail.y = parseFloat(glassDetail.y.toFixed(2));
|
| | | glassDetail.width = parseFloat(glassDetail.width.toFixed(2));
|
| | | glassDetail.height = parseFloat(glassDetail.height.toFixed(2));
|
| | | });
|
| | | });
|
| | | const savedProjectNo = localStorage.getItem('projectNo');
|
| | |
| | | ElMessage.warning(res.msg);
|
| | | }
|
| | | });
|
| | | };
|
| | |
|
| | | const openFolders = ref({
|
| | | pending: true, // 默认展开"待切割原片"文件夹
|
| | | patchQueue: false, // 默认收起"待补片队列"文件夹
|
| | | customSize: false // 默认收起"添加自定义尺寸"文件夹
|
| | | });
|
| | |
|
| | | // 切换文件夹展开/收起状态
|
| | | const toggleFolder = (folderName) => {
|
| | | openFolders.value[folderName] = !openFolders.value[folderName];
|
| | | };
|
| | |
|
| | |
|
| | |
|
| | | const showAddCustomSizeDialog = () => {
|
| | | // 检查是否选择了版图
|
| | | if (selectedLayoutIndex.value === null || layouts.value.length === 0) {
|
| | | ElMessage.warning('请先选择一个版图');
|
| | | return;
|
| | | }
|
| | |
|
| | | // 使用现有的添加成品逻辑,传入当前选中的版图索引
|
| | | showAddDialog(selectedLayoutIndex.value);
|
| | | };
|
| | |
|
| | | //查询设置的基础信息架号,矩形颜色,订单序号等
|
| | |
| | | return bestFit;
|
| | | };
|
| | |
|
| | | const isSelected = (layoutIndex, rectIndex) => {
|
| | | return focusIndex.value &&
|
| | | focusIndex.value.layoutIndex === layoutIndex &&
|
| | | focusIndex.value.rectIndex === rectIndex;
|
| | | };
|
| | |
|
| | | //版图内容样式加载
|
| | | const layoutContainerStyle = (layoutIndex) => {
|
| | | const layout = layouts.value[layoutIndex];
|
| | |
| | | //版图内容小片样式加载
|
| | | const rectStyle = (glassDetail, layoutIndex) => {
|
| | | const layout = layouts.value[layoutIndex];
|
| | | const scale = Math.min(0.25
|
| | | );
|
| | | return {
|
| | | const scale = Math.min(0.25);
|
| | | const isSelectedRect = isSelected(layoutIndex, layout.glassDetails.indexOf(glassDetail));
|
| | |
|
| | | let style = {
|
| | | position: 'absolute',
|
| | | left: `${glassDetail.x * scale}px`,
|
| | | top: `${glassDetail.y * scale}px`,
|
| | |
| | | draggable: !glassDetail.isRemain,
|
| | | zIndex: glassDetail.isRemain ? 1 : 2
|
| | | };
|
| | |
|
| | | // 如果被选中,则添加内侧红框
|
| | | if (isSelectedRect) {
|
| | | style.boxShadow = 'inset 0 0 0 2px red';
|
| | | }
|
| | |
|
| | | return style;
|
| | | };
|
| | |
|
| | | const rectStyle1 = (glassDetail, layoutIndex) => {
|
| | | const layout = layouts.value[layoutIndex];
|
| | | const scale = Math.min(0.25
|
| | | );
|
| | | return {
|
| | | const scale = Math.min(0.25);
|
| | | const isSelectedRect = isSelected(layoutIndex, layout.glassDetails.indexOf(glassDetail));
|
| | |
|
| | | let style = {
|
| | | position: 'absolute',
|
| | | left: `${glassDetail.x * scale}px`,
|
| | | top: `${glassDetail.y * scale}px`,
|
| | |
| | | draggable: !glassDetail.isRemain,
|
| | | zIndex: glassDetail.isRemain ? 1 : 2
|
| | | };
|
| | |
|
| | | // 如果被选中,则添加内侧红框
|
| | | if (isSelectedRect) {
|
| | | style.boxShadow = 'inset 0 0 0 2px red';
|
| | | }
|
| | |
|
| | | return style;
|
| | | };
|
| | |
|
| | | //点击小片
|
| | | const handleRectClick = (layoutIndex, rectIndex) => {
|
| | | // if (dragging.value) {
|
| | | // return;
|
| | | // }
|
| | |
|
| | | focusIndex.value = { layoutIndex, rectIndex };
|
| | | emit('rectClicked', layoutIndex, rectIndex);
|
| | | };
|
| | |
| | | const handleRectRightClick = (layoutIndex, rectIndex) => {
|
| | | const glassDetail = layouts.value[layoutIndex].glassDetails[rectIndex];
|
| | | if (glassDetail.isRemain) return;
|
| | | document.querySelectorAll('.context-menu').forEach(el => el.remove());
|
| | |
|
| | | const contextMenu = document.createElement('div');
|
| | | contextMenu.className = 'context-menu';
|
| | | contextMenu.style.position = 'absolute';
|
| | | contextMenu.style.left = `${event.clientX}px`;
|
| | | contextMenu.style.bottom = `${event.clientY}px`;
|
| | | contextMenu.style.top = `${event.clientY}px`;
|
| | | contextMenu.style.backgroundColor = '#fff';
|
| | | contextMenu.style.border = '1px solid #ccc';
|
| | | contextMenu.style.padding = '5px';
|
| | |
| | | const handleGrayRectRightClick = (layoutIndex, rectIndex,glassDetails) => {
|
| | | //const glassDetail = glassDetails[rectIndex];
|
| | | if (!glassDetails.isRemain) return;
|
| | | document.querySelectorAll('.context-menu').forEach(el => el.remove());
|
| | |
|
| | | const contextMenu = document.createElement('div');
|
| | | contextMenu.className = 'context-menu';
|
| | | contextMenu.style.position = 'absolute';
|
| | | contextMenu.style.left = `${event.clientX}px`;
|
| | | contextMenu.style.bottom = `${event.clientY}px`;
|
| | | contextMenu.style.top = `${event.clientY}px`;
|
| | | contextMenu.style.backgroundColor = '#fff';
|
| | | contextMenu.style.border = '1px solid #ccc';
|
| | | contextMenu.style.padding = '5px';
|
| | |
| | | };
|
| | |
|
| | | //小片鼠标按下事件
|
| | | const handleRectDragStart = (layoutIndex, rectIndex) => {
|
| | | const layout = layouts.value[layoutIndex];
|
| | | const glassDetail = layout.glassDetails[rectIndex];
|
| | | if (glassDetail.isRemain) return;
|
| | | // const handleRectDragStart = (layoutIndex, rectIndex) => {
|
| | | // const layout = layouts.value[layoutIndex];
|
| | | // const glassDetail = layout.glassDetails[rectIndex];
|
| | | // if (glassDetail.isRemain) return;
|
| | | //
|
| | | // dragRect.value = { layoutIndex, rectIndex };
|
| | | // dragStartPos.value = {
|
| | | // x: event.clientX,
|
| | | // y: event.clientY
|
| | | // };
|
| | | // };
|
| | |
|
| | | dragging.value = true;
|
| | | dragRect.value = { layoutIndex, rectIndex };
|
| | | dragStartPos.value = {
|
| | | x: event.clientX,
|
| | | y: event.clientY
|
| | | };
|
| | | };
|
| | | // //小片鼠标移动事件
|
| | | // const handleRectDragging = (event) => {
|
| | | // if (!dragRect.value) return;
|
| | | //
|
| | | // // 如果还没确认是拖拽,则先判断是否达到拖拽阈值(例如5像素)
|
| | | // if (!dragging.value) {
|
| | | // const deltaX = event.clientX - dragStartPos.value.x;
|
| | | // const deltaY = event.clientY - dragStartPos.value.y;
|
| | | // const distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
|
| | | //
|
| | | // // 如果移动距离小于阈值,则认为是点击而非拖拽
|
| | | // if (distance < 5) {
|
| | | // return;
|
| | | // }
|
| | | //
|
| | | // // 达到阈值,确认是拖拽操作
|
| | | // dragging.value = true;
|
| | | // }
|
| | | //
|
| | | // const layoutIndex = dragRect.value.layoutIndex;
|
| | | // const rectIndex = dragRect.value.rectIndex;
|
| | | // const layout = layouts.value[layoutIndex];
|
| | | // const glassDetail = layout.glassDetails[rectIndex];
|
| | | //
|
| | | // // 保存原始坐标用于计算偏移量
|
| | | // const originalX = glassDetail.x;
|
| | | // const originalY = glassDetail.y;
|
| | | //
|
| | | // const scale = Math.min(
|
| | | // (props.gw - 100) / layout.width,
|
| | | // (props.gh - 100) / layout.height
|
| | | // );
|
| | | //
|
| | | // const deltaX = event.clientX - dragStartPos.value.x;
|
| | | // const deltaY = event.clientY - dragStartPos.value.y;
|
| | | //
|
| | | // const newRect = { ...glassDetail };
|
| | | // newRect.x += deltaX / scale;
|
| | | // newRect.y += deltaY / scale;
|
| | | //
|
| | | // const otherRects = layout.glassDetails.filter(r => !r.isRemain && r !== glassDetail);
|
| | | // let isValidMove = true;
|
| | | //
|
| | | // otherRects.forEach(otherRect => {
|
| | | // if (checkOverlap(newRect, otherRect)) {
|
| | | // isValidMove = false;
|
| | | // }
|
| | | // });
|
| | | //
|
| | | // if (newRect.x < 0 || newRect.y < 0 ||
|
| | | // newRect.x + newRect.width > layout.width ||
|
| | | // newRect.y + newRect.height > layout.height) {
|
| | | // isValidMove = false;
|
| | | // }
|
| | | //
|
| | | // if (isValidMove) {
|
| | | // glassDetail.x = newRect.x;
|
| | | // glassDetail.y = newRect.y;
|
| | | //
|
| | | // // 更新glassPoint坐标
|
| | | // if (glassDetail.glassPoint && Array.isArray(glassDetail.glassPoint)) {
|
| | | // const offsetX = glassDetail.x - originalX;
|
| | | // const offsetY = glassDetail.y - originalY;
|
| | | //
|
| | | // glassDetail.glassPoint.forEach(point => {
|
| | | // point.X += offsetX;
|
| | | // point.Y += offsetY;
|
| | | // // 添加精度控制
|
| | | // point.X = parseFloat(point.X.toFixed(2));
|
| | | // point.Y = parseFloat(point.Y.toFixed(2));
|
| | | // });
|
| | | // }
|
| | | //
|
| | | // dragStartPos.value = {
|
| | | // x: event.clientX,
|
| | | // y: event.clientY
|
| | | // };
|
| | | // adjustGrayRectangles(layoutIndex);
|
| | | // }
|
| | | // };
|
| | |
|
| | | //小片鼠标移动事件
|
| | | const handleRectDragging = (event) => {
|
| | | if (!dragging.value || !dragRect.value) return;
|
| | |
|
| | | const layoutIndex = dragRect.value.layoutIndex;
|
| | | const rectIndex = dragRect.value.rectIndex;
|
| | | const layout = layouts.value[layoutIndex];
|
| | | const glassDetail = layout.glassDetails[rectIndex];
|
| | | const scale = Math.min(
|
| | | (props.gw - 100) / layout.width,
|
| | | (props.gh - 100) / layout.height
|
| | | );
|
| | |
|
| | | const deltaX = event.clientX - dragStartPos.value.x;
|
| | | const deltaY = event.clientY - dragStartPos.value.y;
|
| | |
|
| | | const newRect = { ...glassDetail };
|
| | | newRect.x += deltaX / scale;
|
| | | newRect.y += deltaY / scale;
|
| | |
|
| | | const otherRects = layout.glassDetails.filter(r => !r.isRemain && r !== glassDetail);
|
| | | let isValidMove = true;
|
| | |
|
| | | otherRects.forEach(otherRect => {
|
| | | if (checkOverlap(newRect, otherRect)) {
|
| | | isValidMove = false;
|
| | | }
|
| | | });
|
| | |
|
| | | if (newRect.x < 0 || newRect.y < 0 ||
|
| | | newRect.x + newRect.width > layout.width ||
|
| | | newRect.y + newRect.height > layout.height) {
|
| | | isValidMove = false;
|
| | | }
|
| | |
|
| | | if (isValidMove) {
|
| | | glassDetail.x = newRect.x;
|
| | | glassDetail.y = newRect.y;
|
| | | dragStartPos.value = {
|
| | | x: event.clientX,
|
| | | y: event.clientY
|
| | | };
|
| | | adjustGrayRectangles(layoutIndex);
|
| | | }
|
| | | };
|
| | |
|
| | | //小片鼠标松开事件
|
| | | const handleRectDragEnd = () => {
|
| | | if (dragRect.value) {
|
| | | const layoutIndex = dragRect.value.layoutIndex;
|
| | | const rectIndex = dragRect.value.rectIndex;
|
| | | const glassDetail = layouts.value[layoutIndex].glassDetails[rectIndex];
|
| | | const layout = layouts.value[layoutIndex];
|
| | | const scale = Math.min(
|
| | | (props.gw - 100) / layout.width,
|
| | | (props.gh - 100) / layout.height
|
| | | );
|
| | |
|
| | | glassDetail.x = Math.round(glassDetail.x);
|
| | | glassDetail.y = Math.round(glassDetail.y);
|
| | | adjustAlignmentPosition(layoutIndex, rectIndex);
|
| | | }
|
| | |
|
| | | dragging.value = false;
|
| | | dragRect.value = null;
|
| | | };
|
| | | // //小片鼠标松开事件
|
| | | // const handleRectDragEnd = () => {
|
| | | // dragging.value = false;
|
| | | // dragRect.value = null;
|
| | | // dragStartPos.value = { x: 0, y: 0 };
|
| | | // if (dragRect.value) {
|
| | | // const layoutIndex = dragRect.value.layoutIndex;
|
| | | // const rectIndex = dragRect.value.rectIndex;
|
| | | // const glassDetail = layouts.value[layoutIndex].glassDetails[rectIndex];
|
| | | // const layout = layouts.value[layoutIndex];
|
| | | // const scale = Math.min(
|
| | | // (props.gw - 100) / layout.width,
|
| | | // (props.gh - 100) / layout.height
|
| | | // );
|
| | | //
|
| | | // glassDetail.x = parseFloat(glassDetail.x.toFixed(2));
|
| | | // glassDetail.y = parseFloat(glassDetail.y.toFixed(2));
|
| | | // adjustAlignmentPosition(layoutIndex, rectIndex);
|
| | | // }
|
| | | //
|
| | | // dragging.value = false;
|
| | | // dragRect.value = null;
|
| | | // };
|
| | |
|
| | | const adjustAlignmentPosition = (layoutIndex, rectIndex) => {
|
| | | const layout = layouts.value[layoutIndex];
|
| | |
| | | else {
|
| | | // 无法合并,保存当前矩形,开始新的合并
|
| | | merged.push({
|
| | | x: Math.round(current.x),
|
| | | y: Math.round(current.y),
|
| | | width: Math.round(current.width),
|
| | | height: Math.round(current.height),
|
| | | x: current.x,
|
| | | y: current.y,
|
| | | width: current.width,
|
| | | height: current.height,
|
| | | isRemain: true
|
| | | });
|
| | | current = { ...next };
|
| | |
| | |
|
| | | // 添加最后一个矩形
|
| | | merged.push({
|
| | | x: Math.round(current.x),
|
| | | y: Math.round(current.y),
|
| | | width: Math.round(current.width),
|
| | | height: Math.round(current.height),
|
| | | x: current.x,
|
| | | y: current.y,
|
| | | width: current.width,
|
| | | height: current.height,
|
| | | isRemain: true
|
| | | });
|
| | |
|
| | |
| | | // 添加新的余料矩形
|
| | | uniqueArr.forEach((area) => {
|
| | | newGlassDetails.push({
|
| | | x: Math.round(area.x),
|
| | | y: Math.round(area.y),
|
| | | width: Math.round(area.width),
|
| | | height: Math.round(area.height),
|
| | | x: area.x,
|
| | | y: area.y,
|
| | | width: area.width,
|
| | | height: area.height,
|
| | | isRemain: true
|
| | | });
|
| | | });
|
| | |
| | | }
|
| | |
|
| | | if (isValidRotation) {
|
| | | // 更新glassPoint坐标(如果存在)
|
| | | if (glassDetail.glassPoint && Array.isArray(glassDetail.glassPoint)) {
|
| | | // 保存原始点坐标
|
| | | const originalPoints = JSON.parse(JSON.stringify(glassDetail.glassPoint));
|
| | |
|
| | | // 旋转点坐标(以矩形左上角为原点的旋转)
|
| | | glassDetail.glassPoint.forEach((point, index) => {
|
| | | // 计算相对于矩形左上角的坐标
|
| | | const relX = originalPoints[index].X - originalState.x;
|
| | | const relY = originalPoints[index].Y - originalState.y;
|
| | |
|
| | | // 旋转90度后的坐标(顺时针)
|
| | | point.X = originalState.x + relY;
|
| | | point.Y = originalState.y + (originalState.width - relX);
|
| | | // 添加精度控制
|
| | | point.X = parseFloat(point.X.toFixed(2));
|
| | | point.Y = parseFloat(point.Y.toFixed(2));
|
| | | });
|
| | | }
|
| | | adjustGrayRectangles(layoutIndex);
|
| | | } else {
|
| | | glassDetail.width = originalState.width;
|
| | |
| | | return;
|
| | | }
|
| | |
|
| | |
|
| | | // 保存原始坐标
|
| | | const originalX = glassDetail.x;
|
| | | const originalY = glassDetail.y;
|
| | |
|
| | | switch (direction) {
|
| | | case 'up':
|
| | | glassDetail.y += maxStep;
|
| | |
| | | }
|
| | |
|
| | | if (isValidMove) {
|
| | | // 更新glassPoint坐标
|
| | | if (glassDetail.glassPoint && Array.isArray(glassDetail.glassPoint)) {
|
| | | const offsetX = glassDetail.x - originalX;
|
| | | const offsetY = glassDetail.y - originalY;
|
| | |
|
| | | glassDetail.glassPoint.forEach(point => {
|
| | | point.X += offsetX;
|
| | | point.Y += offsetY;
|
| | | // 添加精度控制
|
| | | point.X = parseFloat(point.X.toFixed(2));
|
| | | point.Y = parseFloat(point.Y.toFixed(2));
|
| | | });
|
| | | }
|
| | | adjustGrayRectangles(layoutIndex);
|
| | | } else {
|
| | | glassDetail.x = originalState.x;
|
| | |
| | | // 更新矩形位置
|
| | | glassDetail.x = newX;
|
| | | glassDetail.y = newY;
|
| | |
|
| | | // 更新glassPoint坐标
|
| | | if (glassDetail.glassPoint && Array.isArray(glassDetail.glassPoint)) {
|
| | | glassDetail.glassPoint.forEach(point => {
|
| | | point.X = width - point.X;
|
| | | point.X = parseFloat(point.X.toFixed(2));
|
| | | point.Y = parseFloat(point.Y.toFixed(2));
|
| | | });
|
| | | }
|
| | | });
|
| | |
|
| | | // 更新布局
|
| | |
| | |
|
| | | // 更新矩形位置
|
| | | glassDetail.y = newY;
|
| | |
|
| | | // 更新glassPoint坐标
|
| | | if (glassDetail.glassPoint && Array.isArray(glassDetail.glassPoint)) {
|
| | | glassDetail.glassPoint.forEach(point => {
|
| | | point.Y = height - point.Y;
|
| | | // 添加精度控制
|
| | | point.X = parseFloat(point.X.toFixed(2));
|
| | | point.Y = parseFloat(point.Y.toFixed(2));
|
| | | });
|
| | | }
|
| | | });
|
| | |
|
| | | // 更新布局
|
| | |
| | | .context-menu div:hover {
|
| | | background-color: #f0f0f0;
|
| | | }
|
| | |
|
| | | .folder-header {
|
| | | font-weight: bold;
|
| | | }
|
| | |
|
| | | .folder-header:hover {
|
| | | background-color: #d0d0d0 !important;
|
| | | }
|
| | |
|
| | | .folder-content {
|
| | | border-left: 2px solid #ccc;
|
| | | margin-left: 5px;
|
| | | }
|
| | | </style>
|