<script setup>
|
import {ref, computed, watch} from "vue";
|
import {Connection} from "@element-plus/icons-vue";
|
import { ElMessage, ElMessageBox } from 'element-plus'; // 添加这行
|
import {useRoute, useRouter} from "vue-router";
|
import useOrderInfoStore from "@/stores/sd/order/orderInfo";
|
import requestOptimize from "@/utils/requestOptimize";
|
import request from "@/utils/request";
|
|
const router = useRouter()
|
const orderInfo = useOrderInfoStore()
|
const props = defineProps({
|
quantity : null,
|
area:null,
|
optimizeData:null
|
});
|
//计时器
|
let seconds = ref(0);
|
let isRunning = ref(false);
|
let intervalId;
|
|
//优化进度条
|
let progress = ref(0);
|
|
let quantity = ref(0);
|
let area = ref(0);
|
let optimizeData = ref();
|
|
let originalFilm = ref([]);
|
let totalUtilizationRate = ref('');
|
let tailPieceRate = ref('');
|
|
const mockData=ref();
|
|
//优化次数;时长;效率
|
let progressValue1 = ref(10);
|
let progressValue2 = ref(1000);
|
let progressValue3 = ref(50);
|
|
|
const formattedTime = computed(() => {
|
const minutes = Math.floor(seconds.value / 60);
|
const remainingSeconds = seconds.value % 60;
|
return `${minutes.toString().padStart(2, '0')}:${remainingSeconds.toString().padStart(2, '0')}`;
|
});
|
const startTimer = () => {
|
if(progress.value>0){
|
seconds.value = 0;
|
progress.value = 0;
|
originalFilm.value=[]
|
totalUtilizationRate.value=''
|
tailPieceRate.value=''
|
isRunning.value = false;
|
}
|
|
if(props.optimizeData!=null){
|
document.getElementById("start").disabled=true
|
document.getElementById("complete").style.display="none"
|
console.log(props.optimizeData)
|
if (!isRunning.value) {
|
isRunning.value = true;
|
intervalId = setInterval(() => {
|
seconds.value++;
|
// 最大只到99%
|
if (progress.value < 99) {
|
progress.value += 1;
|
}
|
}, 1000);
|
}
|
|
// 发送请求到真实接口
|
requestOptimize.post('/api/optimize', props.optimizeData, {timeout: 300000})
|
.then((response) => {
|
// 处理响应数据
|
if (response.code === 200 && response.data) {
|
// 解析接口返回的数据
|
const result = response.data;
|
|
// 更新 store 数据
|
if (result.layouts && result.layouts.length > 0) {
|
orderInfo.optimizeData.optimalResults = {
|
projectNo: result.projectNo,
|
glassThickness: result.glassThickness,
|
glassType: result.glassType,
|
totalQuantity: result.totalQuantity,
|
glassTotalQuantity: result.glassTotalQuantity,
|
glassTotalArea: result.glassTotalArea,
|
avgCutRate: result.avgCutRate,
|
lastCutRate: result.lastCutRate,
|
validCutRate: result.validCutRate,
|
layouts: result.layouts
|
};
|
}
|
// 在这里就设置 originalFilm 数据
|
const newOriginalFilm = [];
|
result.layouts.forEach(items => {
|
const existingItem = newOriginalFilm.find(
|
item => item.width === items.width && item.height === items.height
|
);
|
|
if (existingItem) {
|
existingItem.count += 1;
|
} else {
|
newOriginalFilm.push({
|
width: items.width,
|
height: items.height,
|
upTrim: items.upTrim,
|
downTrim: items.downTrim,
|
leftTrim: items.leftTrim,
|
rightTrim: items.rightTrim,
|
stockCode: items.stockCode,
|
glassArea: items.glassArea,
|
glassQuantity: items.glassQuantity,
|
usageRate: items.usageRate,
|
count: 1
|
});
|
}
|
});
|
originalFilm.value = newOriginalFilm;
|
orderInfo.optimizeData.originalFilm = newOriginalFilm; // 这一行很重要
|
console.log('优化完成后设置 originalFilm:', newOriginalFilm);
|
// 更新利用率
|
totalUtilizationRate.value = result.avgCutRate;
|
tailPieceRate.value = result.lastCutRate;
|
|
// 显示成功提示
|
ElMessage.success('优化完成');
|
} else {
|
// 显示失败提示
|
ElMessage.error(response.msg || '优化失败');
|
}
|
})
|
.catch((error) => {
|
// 捕获网络错误
|
console.error('优化请求失败:', error);
|
ElMessage.error('网络异常,请检查接口');
|
})
|
.finally(() => {
|
// 在请求完成时将进度条设为100%
|
progress.value = 100;
|
// 启用按钮
|
document.getElementById("start").disabled = false;
|
// 显示完成按钮
|
document.getElementById("complete").style.display = "block";
|
// 停止定时器
|
pauseTimer();
|
});
|
|
}
|
|
};
|
|
const pauseTimer = () => {
|
if (isRunning.value) {
|
clearInterval(intervalId);
|
isRunning.value = false;
|
}
|
};
|
|
|
const saveOptimizeData = async () => {
|
// 检查是否有优化数据
|
if(orderInfo.optimizeData !== null){
|
try {
|
// 确保 originalFilm 数据已设置
|
if (!orderInfo.optimizeData.originalFilm) {
|
orderInfo.optimizeData.originalFilm = originalFilm.value;
|
console.log('保存前设置 originalFilm:', originalFilm.value);
|
}
|
// 发送请求保存优化数据
|
const res = await request.post(`/glassOptimize/saveOptimizeData/${props.optimizeData.projectNo}`, orderInfo.optimizeData);
|
|
if (Number(res.code) === 200) {
|
ElMessage.success("保存成功");
|
return true; // 保存成功
|
} else {
|
ElMessage.warning(res.msg || "保存失败");
|
return false; // 保存失败
|
}
|
} catch (error) {
|
ElMessage.error("保存过程中发生错误");
|
console.error("保存数据出错:", error);
|
return false; // 保存出错
|
}
|
} else {
|
ElMessage.warning("无优化数据可保存");
|
return false;
|
}
|
}
|
|
const resetTimer = async () => {
|
// 先保存数据,保存成功后再跳转
|
const isSaved = await saveOptimizeData();
|
|
if (isSaved) {
|
// 保存成功后跳转到优化界面
|
router.push({path: '/main/glassOptimize/Optimization'});
|
} else {
|
// 保存失败,给用户选择是否仍要离开
|
ElMessageBox.confirm(
|
'数据保存失败,是否仍要离开当前页面?',
|
'提示',
|
{
|
confirmButtonText: '确定离开',
|
cancelButtonText: '取消',
|
type: 'warning'
|
}
|
).then(() => {
|
// 用户确认离开
|
router.push({path: '/main/glassOptimize/Optimization'});
|
}).catch(() => {
|
// 用户取消,留在当前页面
|
ElMessage.info('操作已取消');
|
});
|
}
|
};
|
|
// watch(
|
// () => progress.value,
|
// (newValue) => {
|
// if (newValue === 100 && orderInfo.optimizeData && orderInfo.optimizeData.optimalResults) {
|
// // 根据接口返回的 layouts 数据构建版图统计
|
// const layouts = orderInfo.optimizeData.optimalResults.layouts;
|
// const newOriginalFilm = [];
|
//
|
// layouts.forEach(items => {
|
// const existingItem = newOriginalFilm.find(
|
// item => item.width === items.width && item.height === items.height
|
// );
|
//
|
// if (existingItem) {
|
// existingItem.count += 1;
|
// } else {
|
// newOriginalFilm.push({
|
// width: items.width,
|
// height: items.height,
|
// upTrim: items.upTrim,
|
// downTrim: items.downTrim,
|
// leftTrim: items.leftTrim,
|
// rightTrim: items.rightTrim,
|
// stockCode: items.stockCode,
|
// count: 1
|
// });
|
// }
|
// });
|
// // 更新 originalFilm
|
// originalFilm.value = newOriginalFilm;
|
// console.log('设置 originalFilm 数据:', newOriginalFilm);
|
// }
|
// }
|
// );
|
|
// 简化 watch 函数
|
watch(
|
() => progress.value,
|
(newValue) => {
|
// 进度更新时不需要额外处理,因为已经在 startTimer 中处理了 originalFilm
|
console.log('优化进度更新:', newValue);
|
}
|
);
|
|
|
</script>
|
|
<template>
|
<div class="header">
|
<el-header>
|
<div class="header-content">
|
<span style="margin-left: -20px;">需切成品</span><br>
|
<div>
|
<span>总面积(m2):</span>
|
<vxe-input class="input" v-model="props.area" disabled ></vxe-input>
|
<span>总数量(片):</span>
|
<vxe-input class="input" v-model="props.quantity" disabled ></vxe-input>
|
<span>优化时长(秒):</span>
|
<span class="time-display">{{ formattedTime }}</span>
|
<el-button id="start" type="primary" style="margin-left: 20px" @click="startTimer">开始优化</el-button>
|
<!-- <el-button class="buttons" type="primary" @click="pauseTimer">暂停</el-button>-->
|
<el-button id="complete" class="buttons" type="primary" style="display: none" @click="resetTimer">完成</el-button>
|
</div>
|
<br>
|
<!-- <div style="display: flex;margin-top: -10px">
|
<span>方案池 优化次数:</span>
|
<el-slider v-model="progressValue1" :min="2" :max="20" size="small" style="max-width: 200px;"></el-slider>
|
<span>单次优化时长:</span>
|
<el-slider v-model="progressValue2" :min="50" :max="2000" size="small" style="max-width: 200px;"></el-slider>
|
<span>钢化效率优先:</span>
|
<el-slider v-model="progressValue3" :show-tooltip="false" size="small" style="max-width: 200px;"></el-slider>
|
<span>切裁率优先</span>
|
</div>-->
|
</div>
|
</el-header>
|
</div>
|
|
<div id="box">
|
<span style="font-size: 20px">优化进度</span>
|
<div class="progress-bar">
|
<el-progress :percentage="progress"
|
:text-inside="true"
|
:stroke-width="20"
|
status="success"
|
:striped="true"
|
:striped-flow="progress < 100"
|
:duration="progress < 100 ? 45 : 0"
|
/>
|
</div>
|
<div style="height: 250px; margin-top: 20px; border: 2px solid #e6e6e6; padding: 10px; border-radius: 5px;">
|
<span style="font-weight: bold">当前结果</span><br/>
|
<div v-for="(item, index) in originalFilm">
|
<div>{{index+1}}:{{item.width}}x{{item.height}}={{item.count}}</div>
|
</div>
|
<div style="margin-top: 2%">
|
<span>产生时间:{{ formattedTime }}</span>
|
<span style="margin-left: 20px">总利用率:{{totalUtilizationRate}}%</span>
|
<span style="margin-left: 20px">尾片:{{tailPieceRate}}%</span>
|
</div>
|
</div>
|
</div>
|
</template>
|
|
<style scoped>
|
|
.header {
|
height: 120px;
|
background-color: #d5eaff;
|
margin-top: -30px;
|
padding: 10px;
|
border-radius: 5px;
|
}
|
|
div header span {
|
margin-left: 10px;
|
font-weight: bold;
|
}
|
|
.input {
|
border: none !important;
|
height: 25px;
|
width: 80px;
|
}
|
|
.time-display {
|
font-size: 18px;
|
color: #409eff;
|
}
|
|
.buttons {
|
float: right;
|
}
|
|
#box {
|
padding: 10px;
|
margin-top: 10px;
|
width: 100%;
|
height: 80%;
|
}
|
|
|
</style>
|