Files
cut-abstractions/tests/dev1/index3.vue

1270 lines
38 KiB
Vue
Raw Normal View History

2025-07-22 18:22:31 +08:00
<script lang="ts" setup>
import { ref, onMounted, computed } from 'vue'
import { nextTick } from 'vue'
import BoardView from '@/components/borderView/BoardView.vue'
import {
Select, SelectOption, Pagination, TreeSelect, Form, FormItem,
Input, Button, Table, Modal, Textarea, Tooltip, Switch,
InputNumber, Checkbox
} from 'ant-design-vue'
import { Knife, SysConfig } from '@/imes/biz/SysConfig'
import { ParserMain } from '@/imes/processParser/parseMain'
import { PlusOutlined } from '@ant-design/icons-vue'
import { getListAllSimple, getOrderSource } from '@/api/production/productManagerList'
import { BoardShowType } from '@/imes/vo/enums/BoardShowType'
import { BlockBorderPoint } from '@/imes/vo/point/BlockBorderPoint'
import { BoardEditor } from '@/imes/biz/RenderNewBoard'
import { BasicTable, TableAction, useTable } from '@/components/Table'
import { optimizeColumns1 } from '../production/productManagerList/productManagerList.data'
import { DataHandleServe } from '@/imes/dataHandle/DataHandleServe'
import { convertData } from '@/imes/common/transform'
import { blockborderClass } from '@/imes/dataClass/blockborderClass'
import { Arc2d, Curve2d } from '@/imes/common/base/CAD'
import { ProcessorContext } from './dataHandle/base'
import { OptimizeLayoutProcessor } from './dataHandle/optimizeLayout/optimizeLayout'
import { ToolsHelper } from './dataHandle/tools/tool'
import {
BlockPlaceResult, BoardPlaceResult, BoardPosition, MaterialPlaceResult, PlaceBoard, PlaceStyle,
PlaceBlock, PlaceBlockDetail,
PlaceMaterial, RemainBlock,
PlacePositionClass,
CodeParams,
BlockHole,
BlockModel,
BlockModelPoint
} from './dataHandle/confClass'
import { BlockSizePlus } from './dataHandle/common/LayoutEngine/BlockSizePlus'
import { Point } from './dataHandle/common/Vector2'
import { PlacePositionHelper } from './dataHandle/common/PlacePostionHelper'
import { DisPoseModelInBoardBorder } from './dataHandle/common/LayoutEngine/DisposeModelInBoardBorder'
import { getMaterialSealEdge } from './dataHandle/common/BlockSealEdge'
import { ArrayExt } from './dataHandle/ArrayExt'
import { CutOrder } from './dataHandle/common/cutorder/CutOrder'
import { CutPointHelper } from './dataHandle/common/cutorder/CutPointHelper'
import { CodeParamsList, CodeParamsObj } from '@/imes/processParser/confClass'
import { BlockHelper } from './dataHandle/common/LayoutEngine/BlockHelper'
const selectedMachineID = ref() // 机台选中
const machineList = ref<any>([]) // 机台列表
// 1920321997498220544 1907276351086264320 1920401449485860864 1920739893772812288
const orderNo = ref('1920401449485860864')
const canvasWidth = ref(1200)
const canvasHeight = ref(650)
const paginationCurrent = ref<any>(1)
2025-07-23 10:12:11 +08:00
const paginationCurrentAll = ref<any>(1)
2025-07-22 18:22:31 +08:00
const boardEditor = ref<BoardEditor>()
const canvasMain = ref()
const canvas = ref()
const isOptimizeing = ref(false)
const _handleServe = ref<OptimizeLayoutProcessor | null>(null)
const selectVal = ref<any>()
const plateSelectOptions = ref<any>([])
const parserMain = ref<ParserMain>(new ParserMain())
2025-07-23 10:12:11 +08:00
const testData1 = ref('')
2025-07-22 18:22:31 +08:00
const dataBase = ref<any>(null)
// 添加显示标志位数组,用于记录当前需要绘制的内容
const displayFlags = ref({
isLockd: false, // 是否锁定
showBlocks: false, // 是否显示小板
showCutPoints: false, // 是否显示下刀点
showCutOrders: false, // 是否显示开料顺序
showCutNo: false, // 是否显示板号
showCutArrow: false, // 是否显示开料方向箭头
showManualPlace: false, // 是否显示手动排版
showHoles: false, // 是否显示孔洞
showModels: false, // 是否显示造型
});
// 初始化解析器
parserMain.value.setDeviceByKey('device1')
// 画布控制器
const canvasController = ref({
showType: BoardShowType.NORMAL,
showHelpCut: false,
isDragingBlock: false,
clickedBlock: new PlaceBlock(),
clickedScrapBlock: new RemainBlock(1, 1, 100, 100),
dragedDistance: Point,
beginDragPosition: Point,
mousePostion: Point,
dragingBlockPoint: BlockBorderPoint,
closestBlockPoint: BlockBorderPoint
})
const currentMaterial = computed(() => {
if (!dataBase.value?.materialList) return null;
const mIndex = dataBase.value.materialList.findIndex(e => e.goodsId === selectVal.value);
return mIndex >= 0 ? dataBase.value.materialList[mIndex] : null;
});
const currentBoard = computed(() => {
if (!currentMaterial.value?.boardList) return null;
const pIndex = paginationCurrent.value - 1;
return pIndex >= 0 && pIndex < currentMaterial.value.boardList.length
? currentMaterial.value.boardList[pIndex]
: null;
});
onMounted(() => {
getOptions();
})
const [registerTable, { setTableData, updateTableData, getDataSource }] = useTable({
title: '',
columns: optimizeColumns1,
useSearchForm: false,
rowKey: 'id',
pagination: false,
canResize: true,
maxHeight: 100,
showTableSetting: false,
actionColumn: {}
})
/**
* 获取弹出容器
*/
function getPopupContainer(node?: HTMLElement): HTMLElement {
return (node?.parentNode as HTMLElement) ?? document.body
}
/**
* 获取机台列表
*/
async function getOptions() {
const res = await getListAllSimple({ type: 1 });
if (res) {
machineList.value = res;
selectedMachineID.value = res[0].id;
_getPlaceOrderData();
}
}
/**
* 订单变化处理
*/
function orderNoChange() {
_getPlaceOrderData();
}
/**
* 机台变化处理
*/
function machineChange() {
// 机台变化逻辑
}
/**
* 获取排版订单数据
*/
async function _getPlaceOrderData() {
const params = {
// orderId: '1792854086534561792',
// machineId: '14193',
orderId: orderNo.value,
machineId: selectedMachineID.value,
};
const res = await getOrderSource(params);
if (!res) return;
let conf = JSON.parse(res.machineDTO.setting);
let tempData = { ...res, optimizeBoardModelDOS: [] };
let newGoodsList: any[] = [];
for (let material of tempData.goodsList) {
if (material.height == 0) material.height = 2440;
if (material.width == 0) material.width = 1220;
if (newGoodsList.findIndex(e => e.goodsId == material.goodsId) == -1) {
newGoodsList.push(material);
}
}
tempData.goodsList = newGoodsList;
let newTestData = convertData(tempData);
let goodsId = newTestData.materialList.map(e => e.goodsId)[0]
newTestData.blockList.forEach(block => {
block.goodsId = goodsId
});
dataBase.value = newTestData;
let sysConfig = new SysConfig(conf);
let _sysConfig = { ...sysConfig };
setTableData(newTestData.materialList);
selectVal.value = newTestData.materialList[0].goodsId;
plateSelectOptions.value = newTestData.materialList;
_sysConfig.boardBorder = _sysConfig.cutBoardBorder;
let eleCanvasMain = document.getElementsByClassName('contentMain')[0];
const { clientWidth, clientHeight } = eleCanvasMain;
canvasWidth.value = clientWidth - 10;
canvasHeight.value = clientHeight - 30;
await nextTick();
boardEditor.value = new BoardEditor(
canvas.value.canvasRef,
_sysConfig,
canvasController.value
);
boardEditor.value.boardWidth = sysConfig.boardWidth;
boardEditor.value.boardLength = sysConfig.boardLength;
boardEditor.value.drawBase();
boardEditor.value.setSysConfig(_sysConfig);
}
2025-07-23 10:12:11 +08:00
2025-07-22 18:22:31 +08:00
async function initHandleServe1() {
let newTestData = dataBase.value;
//#region 刀库
let toolsHelperClass = new ToolsHelper();
let contextKnife: ProcessorContext<Knife[], any, any> = {
input: newTestData.sysConfig.knifeList,
output: {},
params: newTestData.sysConfig
}
const toolsHelper = toolsHelperClass.exec(contextKnife)
//#endregion
//#region 优化排版
let input = {
materialList: newTestData.materialList,
blockList: newTestData.blockList,
blockDetailList: newTestData.blockDetailList,
toolsHelper: toolsHelper,
}
let params = newTestData.sysConfig
let context: ProcessorContext<any, Function, any> = {
input: input,
params: params,
output: optimizeLayoutProcessorCallBack
};
const optimizeLayoutProcessor = new OptimizeLayoutProcessor()
let res = optimizeLayoutProcessor.exec(context)
_handleServe.value = optimizeLayoutProcessor
//#endregion
}
/** 优化的处理器回调--这部分 不做到处理器 */
async function optimizeLayoutProcessorCallBack(context) {
console.log('optimizeLayoutProcessorCallBack', context);
const { data, info } = context;
if (['noBan', 'stop'].includes(info.type)) {
await _handleServe.value?.terminateWorker({ goodsId: context.data.pm.goodsId });
return;
}
// 优化算法拿到优化数据后 各部门根据情况 将数据加载到各自的数据结构中
let materialPlaceResult = await getMaterialPlaceResult(data);
if (materialPlaceResult) {
const { placeResult, pm } = materialPlaceResult;
const remain = placeResult.boards.filter(e => e.isRemainBoard == true);
for (const i in dataBase.value.materialList) {
let material = dataBase.value.materialList[i];
if (material.goodsId == pm.goodsId) {
// let hasResPm = _handleServe.value?.handlePlaceResult(placeResult, pm);
let _hasResPm = await handleTempPlaceResultToPlaceMaterial(placeResult, pm);
dataBase.value.materialList[i] = {
...material,
...pm,
..._hasResPm,
optimizingAvgUsageRateExcludeLastBoard: placeResult.avgUsageRateExcludeLastBoard.toFixed(3),
optimizingUsageRateLastBoard: placeResult.usageRateLastBoard.toFixed(3),
optimizingBoardCount: placeResult.boardCount,
optimizingRemainBoardCount: remain.length,
selectedBlockCount: pm.blockList.length,
};
}
}
setTableData(dataBase.value.materialList);
}
}
/** 数据处理 将优化数据转 为 MaterialPlaceResult */
function getMaterialPlaceResult(data) {
let {
bList, best, yl, pm, width, length
} = data
const config = dataBase.value.sysConfig
let blocks = bList
let retData = new MaterialPlaceResult()
let boardCount = 0
let remainCount = 0
let border = config.cutBoardBorder
let borderOff = (pm.diameter + pm.cutKnifeGap) / 2
// 所有大板上的小板面积
let size_all = 0
for (let i = 0; i < best.length; i++) {
let bd = best[i]
let isRemainBoard = false
boardCount = retData.boards.length + 1
if (i < yl.length) // 余料板
{
width = yl[i].w + border * 2 - borderOff * 2
length = yl[i].l + border * 2 - borderOff * 2
isRemainBoard = true
remainCount++
}
let boardResult = new BoardPlaceResult()
boardResult.boardId = boardCount
boardResult.width = width
boardResult.length = length
boardResult.isRemainBoard = isRemainBoard
let pid = 0
for (let b of bd) {
pid++
let block = blocks[b.bangid]
let placeStyle = PlaceStyle.FRONT
if (!block) {
return
}
let faceF = block.isTurnFaceToPlace || false
let isTurnFaceToPlace = config.placeOriginByBoardLocation && (
config.boardLocation == BoardPosition.RIGHT_BOTTOM || config.boardLocation == BoardPosition.LEFT_TOP)
if (isTurnFaceToPlace)
faceF = !faceF
if (faceF) // 翻面开料
{
if (block.texture == 0) {
placeStyle = PlaceStyle.BACK
}
else if (block.texture == 2) {
placeStyle = PlaceStyle.BACK_TURN_LEFT
}
else {
placeStyle = (b.pbg == block.placeFullLength ? PlaceStyle.BACK : PlaceStyle.BACK_TURN_LEFT)
}
}
else {
if (block.texture == 0) {
placeStyle = PlaceStyle.FRONT
}
else if (block.texture == 2) {
placeStyle = PlaceStyle.FRONT_TURN_RIGHT
}
else {
placeStyle = (b.pbg == block.placeFullLength ? PlaceStyle.FRONT : PlaceStyle.FRONT_TURN_RIGHT)
}
}
let br: any = null
br = new BlockPlaceResult(block.blockNo, boardCount, pid, b.x, b.y, b.pbk, b.pbg, placeStyle, block.area)
boardResult.blocks.push(br)
boardResult.area += block.area
}
retData.boards.push(boardResult)
size_all += boardResult.area
let val = (size_all - boardResult.area) / (retData.boards.length - 1)
retData.avgUsageRateAll = size_all / retData.boards.length
retData.avgUsageRateExcludeLastBoard = Number.isNaN(val) ? boardResult.area : val
retData.usageRateLastBoard = boardResult.area
retData.boardCount = retData.boards.length
}
retData.boardCount = retData.boards.length // 大板数
let remainBoardCount = retData.boards.filter(t => t.remainNo != '').length // 异形大板数
let remianCount = 0
if (Array.isArray(pm.remainBoardList)) {
pm.remainBoardList.forEach(e => {
if (e?.placeBoardJSON) {
let str = e?.placeBoardJSON
e.placeBoardList = JSON.parse(str)
remianCount += e.placeBoardList.length
}
})
}
retData.remainBoardCount = pm?.remainBoardList ? remianCount : yl.length + remainBoardCount
return { placeResult: retData, pm }
}
async function handleTempPlaceResultToPlaceMaterial(_placeResult: MaterialPlaceResult, _pm: PlaceMaterial) {
console.log('确认优化生效 affirmPlace')
let pm: PlaceMaterial = _pm
pm.tempBestPlaceResult = _placeResult
const config = dataBase.value.sysConfig
// 没发现优化结果
if (!pm.tempBestPlaceResult)
return
let placeResult = pm.tempBestPlaceResult
let orgBoardList = pm.boardList
let dic: any = [] // 存放当前 优化的小板
pm.boardList = []
let boardId1 = 1
// 第一次 false
if (pm.tempPlaceResultOnyUnlockedBoard) {
for (let pb of orgBoardList) {
if (pb.isLocked == false && pb.cutedType == 0) // 未锁定
{
pb.blockList.forEach(i => dic[i.blockNo] = i)
}
else // 锁定
{
if (pb.isAdnormal()) {
let sb = pm.remainBoardList.find(t => t.id == Number(pb.boardNo))
if (sb)
sb.isUsed = true
}
pb.boardId = boardId1
pm.boardList.push(pb)
boardId1++
}
}
}
else {
pm.blockList.forEach(i => dic[i.blockNo] = i)
}
// 0904 修复 需求改造后 导致 这里的dic 最终为空
if (Object.keys(dic).length == 0) {
pm.blockList.forEach(i => dic[i.blockNo] = i)
}
let locator = config.boardLocation
// 大板优化结果
let boardId = 0
for (let bpr of placeResult.boards) {
boardId++
// bpr.isRemainBoard false
let bW = bpr.isRemainBoard ? bpr.width : pm.width
let bL = bpr.isRemainBoard ? bpr.length : pm.length
let pb = new PlaceBoard(boardId, bW, bL, bpr.remainId, bpr.remainNo)
pb.isCreateRemainSpace = true
for (let bInfo of bpr.blocks) {
let block: PlaceBlock = dic[bInfo.blockId]
if (block) {
block.isPlaced = true
block.boardId = boardId
block.placeId = bInfo.placeId
block.placeX = bInfo.placeX
block.placeY = bInfo.placeY
// console.log('重置 开料面 开料信息 after', block.boardId, block.blockNo, block, block.placeStyle, bInfo.placeStyle)
/**
* 雕刻机(钻孔拉槽开料)优化排版开料排版面(开料正面)选择顺序排版面>>造型>>排钻>>设计正面
1. 排版面
小板设计排版面为正面或反面设置对应面为开料排版面
小板设计排版面为随意面则继续
2. 造型
小板只有单面造型设置对应面为开料排版面
小板双面无造型或双面有造型则继续
3. 排钻
小板有大孔(偏心轮锁孔)设置对应面为开料排版面
小板无大孔(偏心轮锁孔)则设置孔多的面为开料排版面
小板无孔则继续
4. 设计正面
默认设置设计正面为开料排版面
*/
block.placeStyle = bInfo.placeStyle
let posOff = BlockSizePlus.getOffDis(block)// this.getOffDis(block)
block.placeOffX = posOff.x
block.placeOffY = posOff.y
block.placeX = bInfo.placeX + posOff.x
block.placeY = bInfo.placeY + posOff.y
if (bInfo.placeStyle == PlaceStyle.FRONT || bInfo.placeStyle == PlaceStyle.FRONT_TURN_BACK
|| bInfo.placeStyle == PlaceStyle.BACK || bInfo.placeStyle == PlaceStyle.BACK_TURN_BACK) {
block.placeWidth = block.cutWidth
block.placeLength = block.cutLength
}
else {
block.placeWidth = block.cutLength
block.placeLength = block.cutWidth
}
block.isAutoPlaced = true
block.isOverlap = false
block.cutOrder = 0
pb.blockList.push(block)
pb.blockCount++
pb.blockArea += block.area
delete dic[bInfo.blockId] // 移除block;
} else {
}
}
if (bpr.isScrap) {
// 设置前余料板的使用状态,将不需要的释放.
console.log('设置前余料板的使用状态,将不需要的释放.')
let sb = pm.remainBoardList.find(t => t.id == bpr.remainId)
if (sb) {
sb.isUsed = true
if (sb.placeStyle % 2 != 0) {
pb.width = sb.length
pb.length = sb.width
}
let pl = sb.placePolyline
pb.points = sb?.placePolyline?.LineData.map((t) => { return { x: t.pt.x, y: t.pt.y, bul: t.bul } }) || []
// pb.StoreNo = sb.StoreHouse;
}
}
pb.usageRate = Math.round(10000 * pb.blockArea / pb.area) / 100
pm.boardList.push(pb)
console.log('大板靠板翻转', pb.boardId, locator)
// 大板靠板翻转
PlacePositionHelper.turnPlacePosition(pb, locator, config)
for (let block of pb.blockList) {
// 重置 开料面 开料信息
// console.log('重置 开料面 开料信息', block.boardId, block.blockNo, block, block.placeStyle)
if (block.placeStyle == null || block.placeStyle == undefined) {
console.log('handleTempPlaceResultToPlaceMaterial error block.placeStyle is null or undefined')
} else {
PlacePositionClass.resetPlaceStyle(block, block.placeStyle)
}
}
}
// 大板长边两侧 width 范围内 避免出现造型 DisPoseModelInBoardBorderWidth > 0 生效
DisPoseModelInBoardBorder(
pm,
config.boardBorderModelRange,
config.boardBorderModelModeToFace,
config.boardBorderModelByMachine,
config.modelNearBoardBorder,
)
// for (let pb of pm.boardList) {
// // 重设大板汇总 重设 大板开料 顺序,下刀点
// this.resetPlaceBoard(pm, pb)
// // 检查干涉
// if (pb.isLocked == false && pb.cutedType == 0)
// this.checkOverlapInBoard(pm, pb)
// }
let rBoardCount = placeResult.boardCount
let rUseSize_avg = placeResult.avgUsageRateAll
let rUseSize_noLast = placeResult.avgUsageRateExcludeLastBoard
let rUseSize_last = placeResult.usageRateLastBoard
pm.avgUsageRateAll = rUseSize_avg
pm.avgUsageRateExcludeLastBoard = rUseSize_noLast
pm.usageRateLastBoard = rUseSize_last
pm.boardCount = pm.boardList.length
pm.remainBoardCount = placeResult.remainBoardCount
pm.minBoardId = 1
pm.maxBoardId = pm.boardCount
pm.edgeSealLengthList = getMaterialSealEdge(pm)
pm.boardCountFlipFace = ArrayExt.count(pm.boardList, t => t.isTwoFaceProcessing())
pm.isOptimized = true
pm.tempBestPlaceResult = null
pm.tempPlaceResultError = ''
let mesg = ''
let c = 0
for (let v in dic) {
mesg += `${v} `
c++
}
mesg = `${c}片小板未能排入大板,有可能是尖角导致优化失败.${mesg}`
if (c > 0) {
console.log(pm)
// createMessage.error(mesg)
throw new Error(mesg)
}
return pm
}
/**
* 绘制下刀点
*/
function drawCutPoint() {
if (!boardEditor.value || !dataBase.value || !_handleServe.value) return;
let mIndex = dataBase.value.materialList.findIndex(e => e.goodsId == selectVal.value);
let pIndex = paginationCurrent.value - 1;
if (mIndex >= 0 && dataBase.value.materialList[mIndex].boardList?.length > 0) {
const pm = dataBase.value.materialList[mIndex];
const pb = pm.boardList[pIndex];
// 计算开料顺序和下刀点
// _handleServe.value.autoCalcCutOrder(pm, pb);
CutPointHelper.autoFindCutPoint(pm, pb)
// 设置显示标志位,只显示小板和下刀点
displayFlags.value.showBlocks = true;
displayFlags.value.showCutPoints = !displayFlags.value.showCutPoints; // 切换下刀点显示状态
// 重新绘制
// reDrawCanvas();
} else {
alert('请先进行优化!');
}
}
2025-07-23 10:12:11 +08:00
2025-07-22 18:22:31 +08:00
/**
* 绘制开料顺序
*/
function drawSortingPlace() {
if (!boardEditor.value || !dataBase.value || !_handleServe.value) return;
let mIndex = dataBase.value.materialList.findIndex(e => e.goodsId == selectVal.value);
let pIndex = paginationCurrent.value - 1;
if (mIndex >= 0 && dataBase.value.materialList[mIndex].boardList?.length > 0) {
const pm = dataBase.value.materialList[mIndex];
const pb = pm.boardList[pIndex];
const config = dataBase.value.sysConfig
// 计算所有板材的 开料顺序
let newList = CutOrder.autoSetCutOrder(dataBase.value.materialList, config)
// 计算当前板材的开料顺序
// CutOrder.autoCalcCutOrder(pm,pb,false,config)
// 设置显示标志位,只显示小板和开料顺序
displayFlags.value.showBlocks = true;
displayFlags.value.showCutOrders = !displayFlags.value.showCutOrders; // 切换开料顺序显示状态
// 重新绘制
// reDrawCanvas();
} else {
alert('请先进行优化!');
}
}
2025-07-23 10:12:11 +08:00
2025-07-22 18:22:31 +08:00
/**
* 处理画布事件
*/
function boardViewEvent(name, e) {
if (!boardEditor.value) return;
if (name === 'CanvasEvent_MouseDown') {
// 处理鼠标按下事件
boardEditor.value.CanvasEvent_MouseDown(e);
} else if (name === 'CanvasEvent_MouseMove') {
// 使用节流函数处理鼠标移动事件,减少事件触发频率
throttledMouseMove(e);
} else if (name === 'CanvasEvent_Mouseup') {
boardEditor.value.CanvasEvent_Mouseup(e);
} else if (name === 'CanvasEvent_dblclick') {
// 双击事件处理
} else if (name === 'CanvasEvent_Wheel') {
// 滚轮事件处理
} else if (name === 'keyDown') {
boardEditor.value.keyDown(e);
}
}
const throttledMouseMove = throttle((e) => {
if (boardEditor.value) {
boardEditor.value.CanvasEvent_MouseMove(e);
}
}, 16);
/**
* 节流函数
*/
function throttle(fn, delay) {
let lastCall = 0;
return function (...args) {
const now = Date.now();
if (now - lastCall >= delay) {
lastCall = now;
fn.apply(this, args);
}
};
}
/**
* 开始排版
*/
function startPlace() {
// initHandleServe();
initHandleServe1();
// 设置显示标志位,显示所有内容
displayFlags.value.showBlocks = true;
displayFlags.value.showCutPoints = true;
displayFlags.value.showCutOrders = true;
displayFlags.value.showCutArrow = true;
displayFlags.value.showCutNo = true;
displayFlags.value.showHoles = true;
displayFlags.value.showModels = true;
}
2025-07-23 10:12:11 +08:00
2025-07-22 18:22:31 +08:00
/**
* 清空画布
*/
function clearCanvas() {
// 重置显示标志位
displayFlags.value.showBlocks = false;
displayFlags.value.showCutPoints = false;
displayFlags.value.showCutOrders = false;
displayFlags.value.showCutArrow = false;
displayFlags.value.showCutNo = false;
displayFlags.value.showHoles = false;
displayFlags.value.showModels = false;
// 清空画布
boardEditor.value?.clearCanvas();
}
2025-07-23 10:12:11 +08:00
2025-07-22 18:22:31 +08:00
/**
* 获取解析器参数
*/
function getParserParams() {
handleTemplateData();
}
2025-07-23 10:12:11 +08:00
2025-07-22 18:22:31 +08:00
/**
* 处理模板数据
*/
async function handleTemplateData() {
// 获取模板和范例
let templateData = parserMain.value._device.getTemplateData();
console.log(templateData, dataBase.value);
if (!currentMaterial.value || !currentBoard.value) {
alert('请先进行优化!');
return;
}
// 准备代码参数列表
let data: CodeParamsList = {
processList: [],
};
// 获取速度参数
let freeSpeed = _handleServe.value?.freeSpeed || 10000;
let workSpeed = _handleServe.value?.workSpeed || 8000;
let modelSpeed = _handleServe.value?.modelSpeed || 8000;
let holeSpeed = _handleServe.value?.holeSpeed || 8000;
2025-07-23 10:12:11 +08:00
/** 根据哪个加工面加工 */
let doBackFace = true
2025-07-22 18:22:31 +08:00
for (const template of templateData) {
// 必须要有指令和代码
if (!template.value || !template.orderStr) continue;
if (template.isLoop) {
// 处理循环节点(加工刀路数据)
let material = currentMaterial.value;
let board = currentBoard.value;
// 根据开料顺序做个排序
board.blockList = board.blockList.sort((a, b) => a.cutOrder - b.cutOrder)
//#region 排钻
/**
* 先对该大板内所有小板上的孔进行分析
*/
2025-07-23 10:12:11 +08:00
let allHoles: BlockHole[] = await BlockHelper.GetHoles_BoardAllBlocksByDoFace(board,doBackFace)
2025-07-22 18:22:31 +08:00
// 对孔列表 根据 孔直径 排序
allHoles = allHoles.sort((a, b) => a.radius - b.radius)
for (const key in allHoles) {
let hole = allHoles[key]
let block: PlaceBlock = board.blockList.find(e => e.blockNo == hole.blockNo)
// 加工项 孔的
let temp: CodeParamsObj = {
processItemInfo: {
code: template.value,
order: template.orderStr,
block: {
blockNo: block.blockNo,
cutLength: block.cutLength,
cutWidth: block.cutWidth
},
knife: {
diameter: hole.radius * 2
},
}
};
let list: CodeParams[] = [];
let depth = hole.depth >= block.thickness ? block.thickness : hole.depth
// 刀移动到孔的安全点
let moveToHolePoint = pointToCodeParams(hole.pointX, hole.pointY, block.placeX, block.placeY)
moveToHolePoint.dir = 0
moveToHolePoint.z = 30
moveToHolePoint.f = freeSpeed
list.push(moveToHolePoint)
// 刀下到版面
let moveToblockToDoHole = pointToCodeParams(hole.pointX, hole.pointY, block.placeX, block.placeY)
moveToblockToDoHole.dir = 0
moveToblockToDoHole.z = -block.thickness
moveToblockToDoHole.f = freeSpeed
list.push(moveToblockToDoHole)
// 下刀
let knifeDown_DoHole = pointToCodeParams(hole.pointX, hole.pointY, block.placeX, block.placeY)
knifeDown_DoHole.z = -depth
knifeDown_DoHole.dir = 1
knifeDown_DoHole.f = holeSpeed
list.push(knifeDown_DoHole)
// 抬刀
let knifeEnd_DoHoleEnd = pointToCodeParams(hole.pointX, hole.pointY, block.placeX, block.placeY)
knifeEnd_DoHoleEnd.dir = 0
knifeEnd_DoHoleEnd.z = 30
knifeEnd_DoHoleEnd.f = freeSpeed
list.push(knifeEnd_DoHoleEnd)
temp.list = list
data.processList?.push(temp);
}
//#endregion
//#region 造型
// 所有造型
2025-07-23 10:12:11 +08:00
let allModels: BlockModel[] = await BlockHelper.GetModels_BoardAllBlocksByDoFace(board,doBackFace)
2025-07-22 18:22:31 +08:00
allModels = allModels.sort((a, b) => a.knifeRadius - b.knifeRadius)
for (const key in allModels) {
let model = allModels[key]
let block: PlaceBlock = board.blockList.find(e => e.blockNo == model.blockNo)
let { placeX, placeY } = block;
let temp: CodeParamsObj = {
processItemInfo: {
code: template.value,
order: template.orderStr,
block: {
blockNo: block.blockNo,
cutLength: block.cutLength,
cutWidth: block.cutWidth
},
knife: {
diameter: model.realKnifeRadius * 2
},
}
};
let list: CodeParams[] = [];
let realPointList:any[] = []
// model.realPointList.forEach((p,i)=>{
// if(p.curve !=0 || p.radius != 0){
// }
// })
for (let index = 0; index < model.realPointList.length; index++) {
const p = model.realPointList[index];
let last_p: BlockModelPoint;
if (index == 0) {
last_p = model.realPointList[model.realPointList.length - 1]
} else {
last_p = model.realPointList[index - 1]
}
// p.curve
// p.radius
let new_p = { ...p, radius: last_p.radius, curve: last_p.curve }
realPointList.push(new_p);
}
let depth = model.depth >= block.thickness ? block.thickness : model.depth
// 移动到起点
let codeLineStart = pointToCodeParams(realPointList[0].pointX, realPointList[0].pointY, placeX, placeY)
codeLineStart.dir = 0;
codeLineStart.z = 30;
codeLineStart.f = freeSpeed;
list.push(codeLineStart);
// 下刀至版面
let knifeToBlock_DoModel = pointToCodeParams(realPointList[0].pointX, realPointList[0].pointY, placeX, placeY)
knifeToBlock_DoModel.dir = 0;
knifeToBlock_DoModel.z = block.thickness;
knifeToBlock_DoModel.f = freeSpeed
list.push(knifeToBlock_DoModel)
// 扎入 下刀至起点
let knifeInnerBlock_DoBlock = pointToCodeParams(realPointList[0].pointX, realPointList[0].pointY, placeX, placeY)
knifeInnerBlock_DoBlock.dir = 1;
knifeInnerBlock_DoBlock.z = -depth
knifeInnerBlock_DoBlock.f = modelSpeed
list.push(knifeInnerBlock_DoBlock)
// 开始造型走刀
for (const modelPoint of realPointList) {
let codeLineMove = pointToCodeParams(modelPoint.pointX, modelPoint.pointY, placeX, placeY, modelPoint.curve)
codeLineMove.z = -depth
codeLineMove.f = modelSpeed
if (modelPoint.radius != 0) {
codeLineMove.r = modelPoint.radius
}
list.push(codeLineMove)
}
// 走刀结束 抬刀
let endPoint = realPointList[realPointList.length - 1]
let codeLineEnd = pointToCodeParams(endPoint.pointX, endPoint.pointY, placeX, placeY)
codeLineEnd.dir = 0
codeLineEnd.f = freeSpeed
codeLineEnd.z = 30
list.push(codeLineEnd)
temp.list = list
data.processList?.push(temp);
}
//#endregion
//#region 开料
// 轮廓的集合 开料用
let borderFinalList = board.blockList.map(e => e.blockDetail.borderContour.borderFinal);
for (const i in borderFinalList) {
let block = board.blockList[i];
let border = borderFinalList[i];
// 添加标记
let temp1: CodeParamsObj = {
processItemInfo: {
code: 'MARK',
order: 'Mark',
codeParams: block.blockNo + ' cut block'
}
};
data.processList?.push(temp1);
// 加工项 开料的
let temp: CodeParamsObj = {
processItemInfo: {
code: template.value,
order: template.orderStr,
block: {
cutLength: block.cutLength,
cutWidth: block.cutWidth
},
knife: {
diameter: material.diameter
}
}
};
// 加工刀路信息 代码生成参数列表
let list: CodeParams[] = [];
let { placeX, placeY } = block;
// 移动到起点
let codeLineStart = BoardToCodeParams(border[0], placeX, placeY);
codeLineStart.dir = 0;
codeLineStart.z = 30;
codeLineStart.f = freeSpeed;
list.push(codeLineStart);
// 下刀到板面
let codeLine1 = BoardToCodeParams(border[0], placeX, placeY);
codeLine1.dir = 0;
codeLine1.z = block.thickness;
codeLine1.f = freeSpeed;
list.push(codeLine1);
// 扎入
let codeLine2 = BoardToCodeParams(border[0], placeX, placeY);
codeLine2.dir = 1;
codeLine2.z = 0;
codeLine2.f = workSpeed;
// 走刀
for (const p of border) {
// if (block.blockNo == '25044454400') {
// debugger
// }
let codeLine = BoardToCodeParams(p, placeX, placeY);
codeLine.z = -block.thickness;
codeLine.f = workSpeed;
list.push(codeLine);
}
// 回到起点
let codeLine3 = BoardToCodeParams(border[0], placeX, placeY);
codeLine3.z = -block.thickness;
codeLine3.f = freeSpeed;
list.push(codeLine3);
// 抬刀
let codeLineEnd = BoardToCodeParams(border[0], placeX, placeY);
codeLineEnd.dir = 0;
codeLineEnd.z = 30;
codeLineEnd.f = freeSpeed;
list.push(codeLineEnd);
temp.list = list;
data.processList?.push(temp);
}
//#endregion
} else {
// 处理非循环节点(文件头尾)
let temp: CodeParamsObj = {
processItemInfo: {
code: template.value,
order: template.orderStr
}
};
if (template.params) {
temp.processItemInfo.codeParams = template.params;
}
data.processList?.push(temp);
}
}
console.log('处理完成', data);
// 生成代码
let str = await parserMain.value.getCode(data);
testData1.value = str;
console.log('最终结果', str);
}
/**
* 将板轮廓转换为代码参数
* border 轮廓线
* placeX 板件优化X坐标
* placeY 板件优化Y坐标
*/
function BoardToCodeParams(border: Curve2d | Arc2d, placeX = 0, placeY = 0): CodeParams {
let codeLine: CodeParams = {};
codeLine.x = border.EndPoint.m_X + placeX;
codeLine.y = border.EndPoint.m_Y + placeY;
codeLine.dir = 1;
if (border instanceof Arc2d || (Reflect.has(border, 'm_Radius') && border['m_Radius'] != 0)) {
codeLine.r = border.m_Radius;
if (border.Bul > 0) {
codeLine.dir = 3;
} else if (border.Bul < 0) {
codeLine.dir = 2;
}
}
return codeLine;
}
/**
* x , y 点坐标
* hole
* placeX 板件优化X坐标
* placeY 板件优化Y坐标
*/
function pointToCodeParams(x, y, placeX = 0, placeY = 0, bul?) {
let codeLine: CodeParams = {}
codeLine.x = x + placeX
codeLine.y = y + placeY
if (bul != undefined) {
if (bul > 0) {
codeLine.dir = 3
} else if (bul < 0) {
codeLine.dir = 2
}
}
return codeLine
}
/**
* 重新绘制画布
*/
function reDrawCanvas() {
if (!boardEditor.value || !dataBase.value) return;
let mIndex = dataBase.value.materialList.findIndex(e => e.goodsId == selectVal.value);
let pIndex = paginationCurrent.value - 1;
if (mIndex >= 0 && dataBase.value.materialList[mIndex].boardList?.length > 0) {
const pm = dataBase.value.materialList[mIndex];
const pb = pm.boardList[pIndex];
// 确保每个板件都有开料顺序和下刀点
if (_handleServe.value && pb.blockList.some(block => !block.cutOrder)) {
_handleServe.value.autoCalcCutOrder(pm, pb);
}
boardEditor.value.setMaterial(pm);
boardEditor.value.setBoard(pb);
// 清空画布并绘制基础内容
boardEditor.value.clearCanvas();
boardEditor.value.drawBase();
boardEditor.value.drawBoard(pb);
boardEditor.value.setDisplayFlags({
isLockd: displayFlags.value.isLockd,
showBlocks: displayFlags.value.showBlocks,
showCutPoints: displayFlags.value.showCutPoints,
showCutOrders: displayFlags.value.showCutOrders,
showCutArrow: displayFlags.value.showCutArrow,
showCutNo: displayFlags.value.showCutNo,
showHoles: displayFlags.value.showHoles,
showModels: displayFlags.value.showModels,
showManualPlace: displayFlags.value.showManualPlace
});
boardEditor.value.drawAllElements();
}
}
</script>
<template>
<div class="processDemo1">
<div class="tools">
<span class="toolItemLabel">生产单号</span>
<Input class="toolItem" v-model:value="orderNo" style="width: 170px;" @change="orderNoChange" />
<span class="toolItemLabel">机台选择</span>
<Select v-model:value="selectedMachineID" placeholder="请选择机台" :get-popup-container="getPopupContainer"
style="width: 170px;" @change="machineChange">
<SelectOption v-for="item in machineList" :key="item.id" :value="item.id">
{{ item.name }}
</SelectOption>
</Select>
<Button v-if="!isOptimizeing" @click="startPlace">开始优化</Button>
2025-07-23 10:12:11 +08:00
2025-07-22 18:22:31 +08:00
<Button @click="drawSortingPlace">开料顺序</Button>
<Button @click="drawCutPoint">下刀点</Button>
<Button @click="getParserParams"> 解析器</Button>
<BasicTable @register="registerTable" />
</div>
<div class="content">
<div class="contentLeft">
<div class="contentTools">
<Select v-model:value="selectVal" class="plateSelect" :style="{ width: '200px', marginLeft: '10px' }"
:options="plateSelectOptions" :field-names="{ label: 'goodsName', value: 'goodsId' }"
@change="reDrawCanvas" />
<Pagination v-model:current="paginationCurrent" @change="reDrawCanvas" :page-size="1" class="platePagination"
:total="paginationCurrentAll" />
</div>
<div class="contentBtns">
<Button class="contentBtn" @click="clearCanvas">清空</Button>
2025-07-23 10:12:11 +08:00
2025-07-22 18:22:31 +08:00
<Textarea class="testData" v-model:value="testData1"></Textarea>
</div>
</div>
<!-- 画布区域 -->
<div class="contentMain" ref="canvasMain">
<BoardView ref="canvas" class="BoardView" :width="canvasWidth" :height="canvasHeight" tabindex="0"
@keydown="boardViewEvent('keyDown', $event)" @dblclick="boardViewEvent('CanvasEvent_dblclick', $event)"
@mousedown="boardViewEvent('CanvasEvent_MouseDown', $event)"
@mouseup="boardViewEvent('CanvasEvent_Mouseup', $event)"
@mousemove="boardViewEvent('CanvasEvent_MouseMove', $event)"
@wheel="boardViewEvent('CanvasEvent_Wheel', $event)"
@contextmenu="boardViewEvent('CanvasEvent_RightClick', $event)" />
</div>
</div>
</div>
</template>
<style>
.processDemo1 {
height: 100%;
width: 100%;
display: flex;
flex-direction: column;
padding: 10px;
}
.tools {
display: flex;
flex-direction: row;
flex-wrap: wrap;
}
.toolItemLabel {
margin: auto 0;
}
.content {
display: flex;
flex-direction: row;
}
.contentLeft {
display: flex;
flex-direction: column;
flex: 1;
}
.contentTools {
display: flex;
flex-direction: row;
}
.BoardView {
border: 1px solid silver;
}
.contentBtns {
display: flex;
flex-direction: row;
flex-wrap: wrap;
}
.contentBtn {
margin: 6px 8px;
}
.testData {
overflow: auto;
min-height: 450px !important;
background-color: #FFFFFF !important;
color: #000000 !important;
}
</style>