|
|
|
|
@ -11,12 +11,14 @@ |
|
|
|
|
filterable |
|
|
|
|
placeholder="请选择" |
|
|
|
|
size="small" |
|
|
|
|
value-key="id" |
|
|
|
|
@change="teamChange" |
|
|
|
|
> |
|
|
|
|
<el-option |
|
|
|
|
v-for="(item, index) in selectTeamOptions" |
|
|
|
|
:label="item" |
|
|
|
|
:label="item.tsName" |
|
|
|
|
:value="item" |
|
|
|
|
:key="index" |
|
|
|
|
:key="item" |
|
|
|
|
></el-option> |
|
|
|
|
</el-select> |
|
|
|
|
</el-form-item> |
|
|
|
|
@ -29,10 +31,12 @@ |
|
|
|
|
filterable |
|
|
|
|
placeholder="请选择" |
|
|
|
|
size="small" |
|
|
|
|
value-key="id" |
|
|
|
|
@change="equipChange" |
|
|
|
|
> |
|
|
|
|
<el-option |
|
|
|
|
v-for="(item, index) in selectEquipOptions" |
|
|
|
|
:label="item" |
|
|
|
|
:label="item.deviceName" |
|
|
|
|
:value="item" |
|
|
|
|
:key="index" |
|
|
|
|
></el-option> |
|
|
|
|
@ -41,19 +45,21 @@ |
|
|
|
|
</el-col> |
|
|
|
|
<el-col :span="5"> |
|
|
|
|
<el-form-item label="工序:"> |
|
|
|
|
<!-- <el-input v-model="formLabelAlign.processName" placeholder="请输入"></el-input> --> |
|
|
|
|
<el-select |
|
|
|
|
v-model="formLabelAlign.processName" |
|
|
|
|
v-model="formLabelAlign.processId" |
|
|
|
|
clearable |
|
|
|
|
filterable |
|
|
|
|
placeholder="请选择" |
|
|
|
|
size="small" |
|
|
|
|
@change="processChange" |
|
|
|
|
value-key="id" |
|
|
|
|
> |
|
|
|
|
<el-option |
|
|
|
|
v-for="(item, index) in selectProcessOptions" |
|
|
|
|
:label="item.name" |
|
|
|
|
:value="item.name" |
|
|
|
|
:value="item" |
|
|
|
|
:key="index" |
|
|
|
|
|
|
|
|
|
></el-option> |
|
|
|
|
</el-select> |
|
|
|
|
</el-form-item> |
|
|
|
|
@ -84,6 +90,9 @@ |
|
|
|
|
<!-- 头部标题和图例 --> |
|
|
|
|
<div class="gantt-header"> |
|
|
|
|
<div class="status-legend"> |
|
|
|
|
<div class="legend-item"> |
|
|
|
|
<el-button type="primary" size="small" @click="exportXls">导出</el-button> |
|
|
|
|
</div> |
|
|
|
|
<div class="legend-item"> |
|
|
|
|
<span class="legend-color completed"></span> |
|
|
|
|
<span>已完成</span> |
|
|
|
|
@ -104,11 +113,12 @@ |
|
|
|
|
<!-- 左侧信息列表 - 展示车间订单号等信息 --> |
|
|
|
|
<div class="info-list"> |
|
|
|
|
<div class="info-item-title"> |
|
|
|
|
<div class="info-title-cell info-title-no">车间订单号</div> |
|
|
|
|
<div class="info-title-cell">订单信息</div> |
|
|
|
|
<!-- <div class="info-title-cell info-title-no">车间订单号</div> |
|
|
|
|
<div class="info-title-cell info-title-no">零件号</div> |
|
|
|
|
<div class="info-title-cell">批次号</div> |
|
|
|
|
<div class="info-title-cell info-title-num">数量</div> |
|
|
|
|
<div class="info-title-cell info-title-num">质量等级</div> |
|
|
|
|
<div class="info-title-cell info-title-num">质量等级</div> --> |
|
|
|
|
</div> |
|
|
|
|
<div class="info-container"> |
|
|
|
|
<div |
|
|
|
|
@ -121,11 +131,28 @@ |
|
|
|
|
}" |
|
|
|
|
> |
|
|
|
|
<div class="info-item"> |
|
|
|
|
<div class="info-cell info-title-no">{{ order.woCode }}</div> |
|
|
|
|
<el-row> |
|
|
|
|
<el-col :span="12"> |
|
|
|
|
<div class="info-item-txt">订单号:{{ order.woCode }}</div> |
|
|
|
|
</el-col> |
|
|
|
|
<el-col :span="12"> |
|
|
|
|
<div class="info-item-txt">零件号:{{ order.partCode }}</div> |
|
|
|
|
</el-col> |
|
|
|
|
<el-col :span="8"> |
|
|
|
|
<div class="info-item-txt">批次号:{{ order.batchNo }}</div> |
|
|
|
|
</el-col> |
|
|
|
|
<el-col :span="8"> |
|
|
|
|
<div class="info-item-txt">数量:{{ order.makeQty }}</div> |
|
|
|
|
</el-col> |
|
|
|
|
<el-col :span="8"> |
|
|
|
|
<div class="info-item-txt">质量等级:{{ order.productIdent }}</div> |
|
|
|
|
</el-col> |
|
|
|
|
</el-row> |
|
|
|
|
<!-- <div class="info-cell info-title-no">{{ order.woCode }}</div> |
|
|
|
|
<div class="info-cell info-title-no">{{ order.partCode }}</div> |
|
|
|
|
<div class="info-cell">{{ order.batchNo }}</div> |
|
|
|
|
<div class="info-cell info-title-num">{{ order.makeQty }}</div> |
|
|
|
|
<div class="info-cell info-title-num">{{ order.productIdent }}</div> |
|
|
|
|
<div class="info-cell info-title-num">{{ order.productIdent }}</div> --> |
|
|
|
|
</div> |
|
|
|
|
</div> |
|
|
|
|
</div> |
|
|
|
|
@ -331,7 +358,9 @@ |
|
|
|
|
|
|
|
|
|
<script> |
|
|
|
|
import { getData, selectEquip, selectTeam } from '@/api/productionSchedulingPlan/scheduling'; |
|
|
|
|
import { getProcessSet } from '@/api/productionSchedulingPlan/basic'; |
|
|
|
|
import { getProcessSet, exportBlob,getEquipment,getTeamSet } from '@/api/productionSchedulingPlan/basic'; |
|
|
|
|
import { downloadXls } from '@/utils/util'; |
|
|
|
|
// import { exportBlob } from '@/api/common'; |
|
|
|
|
export default { |
|
|
|
|
name: 'GanttChart', |
|
|
|
|
data() { |
|
|
|
|
@ -339,8 +368,11 @@ export default { |
|
|
|
|
formLabelAlign: { |
|
|
|
|
startTime: null, //时间 |
|
|
|
|
teamName: '', //班组 |
|
|
|
|
teamId: '', //班组 |
|
|
|
|
equipName: '', //设备 |
|
|
|
|
equipId: '', //设备 |
|
|
|
|
processName: '', //工序 |
|
|
|
|
processId: '', //工序 |
|
|
|
|
woCode: '', //车间订单号 |
|
|
|
|
}, |
|
|
|
|
zoomLevel: 12, // 缩放级别 (1-4) |
|
|
|
|
@ -355,7 +387,7 @@ export default { |
|
|
|
|
|
|
|
|
|
// 分页参数 |
|
|
|
|
currentPage: 1, |
|
|
|
|
pageSize: 10, |
|
|
|
|
pageSize: 6, |
|
|
|
|
|
|
|
|
|
// 提示框相关 |
|
|
|
|
tooltipVisible: false, |
|
|
|
|
@ -364,8 +396,8 @@ export default { |
|
|
|
|
tooltipY: 0, |
|
|
|
|
|
|
|
|
|
// 样式相关 |
|
|
|
|
baseRowHeight: 36, |
|
|
|
|
baseRowChartHeight: 37, |
|
|
|
|
baseRowHeight: 70, |
|
|
|
|
baseRowChartHeight: 71, |
|
|
|
|
rowHeights: {}, |
|
|
|
|
selectTeamOptions: [], |
|
|
|
|
selectEquipOptions: [], |
|
|
|
|
@ -423,11 +455,49 @@ export default { |
|
|
|
|
this.getData(); |
|
|
|
|
this.calcCurrentTimePosition(); |
|
|
|
|
// 定时更新当前时间线位置 |
|
|
|
|
// setInterval(() => { |
|
|
|
|
// this.calcCurrentTimePosition(); |
|
|
|
|
// }, 60000); // 每分钟更新一次 |
|
|
|
|
setInterval(() => { |
|
|
|
|
this.calcCurrentTimePosition(); |
|
|
|
|
}, 600000); // 每分钟更新一次 |
|
|
|
|
}, |
|
|
|
|
methods: { |
|
|
|
|
processChange(val){ |
|
|
|
|
this.formLabelAlign.processName = val.name |
|
|
|
|
}, |
|
|
|
|
equipChange(val){ |
|
|
|
|
this.formLabelAlign.equipName = val.deviceName |
|
|
|
|
}, |
|
|
|
|
teamChange(val){ |
|
|
|
|
this.formLabelAlign.teamName = val.tsName |
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
// 导出 |
|
|
|
|
exportXls() { |
|
|
|
|
exportBlob(`/blade-scheduling/workOrder/exportBoard`, this.formLabelAlign).then(res => { |
|
|
|
|
// |
|
|
|
|
console.log(this.$route.path == '/productionSchedulingPlan/schedulingDashboard/index'); |
|
|
|
|
if (this.$route.path == '/productionSchedulingPlan/schedulingDashboard/index') { |
|
|
|
|
downloadXls(res.data, `排产看板数据.xlsx`); |
|
|
|
|
} else { |
|
|
|
|
const blob = res.data; |
|
|
|
|
const reader = new FileReader(); |
|
|
|
|
reader.onload = function (e) { |
|
|
|
|
const base64 = e.target.result; // 格式:data:application/octet-stream;base64,... |
|
|
|
|
const fileName = '排产看板数据.xlsx'; // 可从接口响应头获取(如 Content-Disposition) |
|
|
|
|
|
|
|
|
|
// 4. 通过 postMessage 通知父页面 |
|
|
|
|
window.parent.postMessage( |
|
|
|
|
{ |
|
|
|
|
type: 'DOWNLOAD_FILE', |
|
|
|
|
base64: base64, |
|
|
|
|
fileName: fileName, |
|
|
|
|
}, |
|
|
|
|
'*' // 生产环境建议指定父页面域名(如 "https://parent-domain.com"),避免安全风险 |
|
|
|
|
); |
|
|
|
|
}; |
|
|
|
|
reader.readAsDataURL(blob); |
|
|
|
|
} |
|
|
|
|
}); |
|
|
|
|
}, |
|
|
|
|
// 计算当前时间在时间轴上的位置百分比 |
|
|
|
|
calcCurrentTimePosition() { |
|
|
|
|
const now = new Date(); |
|
|
|
|
@ -473,12 +543,12 @@ export default { |
|
|
|
|
}); |
|
|
|
|
}, |
|
|
|
|
getSelectEquip() { |
|
|
|
|
selectEquip().then(res => { |
|
|
|
|
getEquipment().then(res => { |
|
|
|
|
this.selectEquipOptions = res.data.data; |
|
|
|
|
}); |
|
|
|
|
}, |
|
|
|
|
getSelectTeam() { |
|
|
|
|
selectTeam().then(res => { |
|
|
|
|
getTeamSet().then(res => { |
|
|
|
|
this.selectTeamOptions = res.data.data; |
|
|
|
|
}); |
|
|
|
|
}, |
|
|
|
|
@ -544,8 +614,11 @@ export default { |
|
|
|
|
this.formLabelAlign = { |
|
|
|
|
startTime: new Date().toISOString().substr(0, 10), |
|
|
|
|
teamName: '', |
|
|
|
|
teamId:'', |
|
|
|
|
equipName: '', |
|
|
|
|
equipId:'', |
|
|
|
|
processName: '', |
|
|
|
|
processId:'', |
|
|
|
|
woCode: '', |
|
|
|
|
}; |
|
|
|
|
this.getData(); |
|
|
|
|
@ -675,10 +748,10 @@ export default { |
|
|
|
|
getLayerTaskHeight(totalLayers, device) { |
|
|
|
|
const rowHeight = this.getRowChartHeight(device); |
|
|
|
|
if (totalLayers <= 1) { |
|
|
|
|
return rowHeight - 18; |
|
|
|
|
return rowHeight - 40; |
|
|
|
|
} else { |
|
|
|
|
const totalSpacing = totalLayers * 18; |
|
|
|
|
const availableHeight = rowHeight - totalSpacing; |
|
|
|
|
const availableHeight = rowHeight - 40 - totalSpacing; |
|
|
|
|
return availableHeight / totalLayers; |
|
|
|
|
} |
|
|
|
|
}, |
|
|
|
|
@ -737,7 +810,7 @@ export default { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
.gantt-header { |
|
|
|
|
height: 15px; |
|
|
|
|
height: 35px; |
|
|
|
|
margin-bottom: 10px; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@ -780,7 +853,7 @@ export default { |
|
|
|
|
|
|
|
|
|
/* 左侧信息列表样式 */ |
|
|
|
|
.info-list { |
|
|
|
|
width: 480px; |
|
|
|
|
width: 450px; |
|
|
|
|
background-color: #f8f9fa; |
|
|
|
|
/* border-right: 1px solid #eee; */ |
|
|
|
|
flex-shrink: 0; |
|
|
|
|
@ -795,13 +868,21 @@ export default { |
|
|
|
|
background: #284c89; |
|
|
|
|
color: #fff; |
|
|
|
|
font-weight: bold; |
|
|
|
|
height: 25px; |
|
|
|
|
height: 30px; |
|
|
|
|
} |
|
|
|
|
.info-item-txt { |
|
|
|
|
line-height: 25px; |
|
|
|
|
overflow: hidden; |
|
|
|
|
text-overflow: ellipsis; |
|
|
|
|
white-space: nowrap; |
|
|
|
|
font-size: 12px; |
|
|
|
|
text-align: center; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
.info-title-cell { |
|
|
|
|
flex: 1; |
|
|
|
|
text-align: center; |
|
|
|
|
line-height: 25px; |
|
|
|
|
line-height: 30px; |
|
|
|
|
border-right: 1px solid #eee; |
|
|
|
|
font-size: 12px; |
|
|
|
|
} |
|
|
|
|
@ -817,6 +898,7 @@ export default { |
|
|
|
|
.info-item { |
|
|
|
|
display: flex; |
|
|
|
|
height: 100%; |
|
|
|
|
padding: 5px; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
.info-cell { |
|
|
|
|
@ -842,7 +924,7 @@ export default { |
|
|
|
|
|
|
|
|
|
/* 图表X轴区域样式 */ |
|
|
|
|
.chart-axis { |
|
|
|
|
height: 25px; |
|
|
|
|
height: 30px; |
|
|
|
|
position: relative; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@ -851,7 +933,7 @@ export default { |
|
|
|
|
top: 0; |
|
|
|
|
left: 0; |
|
|
|
|
width: 100%; |
|
|
|
|
height: 25px; |
|
|
|
|
height: 30px; |
|
|
|
|
display: flex; |
|
|
|
|
background-color: #284c89; |
|
|
|
|
} |
|
|
|
|
@ -864,7 +946,7 @@ export default { |
|
|
|
|
color: #fff; |
|
|
|
|
font-weight: 500; |
|
|
|
|
white-space: nowrap; |
|
|
|
|
line-height: 25px; |
|
|
|
|
line-height: 30px; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
.minor-labels { |
|
|
|
|
@ -882,7 +964,7 @@ export default { |
|
|
|
|
font-size: 12px; |
|
|
|
|
color: #fff; |
|
|
|
|
white-space: nowrap; |
|
|
|
|
line-height: 25px; |
|
|
|
|
line-height: 30px; |
|
|
|
|
padding: 0 2px; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@ -1100,16 +1182,21 @@ export default { |
|
|
|
|
|
|
|
|
|
/* 分页样式 */ |
|
|
|
|
.pagination-container { |
|
|
|
|
position: fixed; /* 固定定位 */ |
|
|
|
|
right: 20px; /* 距离右侧20px */ |
|
|
|
|
bottom: 20px; /* 距离底部20px */ |
|
|
|
|
/* position: fixed; */ |
|
|
|
|
/* right: 20px; |
|
|
|
|
bottom: 20px; */ |
|
|
|
|
height: 35px; |
|
|
|
|
margin-top: 15px; |
|
|
|
|
background-color: #fff; /* 增加背景色避免与内容重叠时看不清 */ |
|
|
|
|
padding: 10px; /* 增加内边距 */ |
|
|
|
|
z-index: 10; |
|
|
|
|
float: right; |
|
|
|
|
width: calc(100% - 20px); |
|
|
|
|
/* width:100%; */ |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
:deep(.el-pagination) { |
|
|
|
|
float: right; |
|
|
|
|
} |
|
|
|
|
:deep(.el-button--primary) { |
|
|
|
|
background-color: #284c89 !important; |
|
|
|
|
color: #fff; |
|
|
|
|
|