批次以及批次的生产安排

This commit is contained in:
砂糖
2025-08-15 10:12:50 +08:00
parent 916d64c1ca
commit 7f0b243c7f
4 changed files with 285 additions and 22 deletions

View File

@@ -0,0 +1,200 @@
<template>
<div class="merge-source-selector">
<!-- 已选任务列表 -->
<div v-if="selectedTasks.length > 0" class="selected-tasks">
<div v-for="task in selectedTasks" :key="task.taskId" class="selected-task-item">
<div class="task-info">
<ProductInfo :productId="task.productId" />
<CraftInfo :craftId="task.processId" />
<span class="task-quantity">数量: {{ task.taskQuantity }}</span>
</div>
<el-button
type="text"
icon="el-icon-delete"
size="mini"
class="delete-btn"
@click="removeTask(task.taskId)"
></el-button>
</div>
</div>
<!-- 未选择任务时的提示 -->
<div v-else class="no-selected-tip">
暂无选择的任务请从下方选择
</div>
<!-- 任务选择器 -->
<div class="task-selector">
<el-select
v-model="currentSelectTaskId"
placeholder="选择未合并的任务"
clearable
style="width: 100%;"
@change="addSelectedTask"
>
<el-option
v-for="task in availableTasks"
:key="task.taskId"
:label="`[产品: ${task.productName || task.productId}] [工艺: ${task.processName || task.processId}] 数量: ${task.taskQuantity}`"
:value="task.taskId"
></el-option>
</el-select>
</div>
</div>
</template>
<script>
import CraftInfo from '@/components/KLPService/Renderer/CraftInfo.vue';
import ProductInfo from '@/components/KLPService/Renderer/ProductInfo.vue';
export default {
name: 'MergeSourceSelector',
components: {
CraftInfo,
ProductInfo
},
props: {
// 所有未合并的任务列表
unmergedTasks: {
type: Array,
required: true,
default: () => []
},
// 所有任务列表(用于回显)
allTasks: {
type: Array,
required: true,
default: () => []
},
// 绑定的合并来源ID字符串逗号分隔
value: {
type: String,
default: ''
}
},
computed: {
// 可选择的任务(未合并且不在当前已选中列表中)
availableTasks() {
return this.unmergedTasks.filter(task =>
!this.selectedTasks.some(t => t.taskId === task.taskId)
);
}
},
data() {
return {
selectedTasks: [], // 当前选中的任务列表
currentSelectTaskId: null // 当前选择的任务ID
};
},
watch: {
// 监听外部传入的value变化同步到选中任务列表
value: {
handler(val) {
if (val) {
this.syncSelectedTasks(val.split(','));
} else {
this.selectedTasks = [];
}
},
immediate: true
},
// 监听选中任务变化,同步到外部
selectedTasks: {
handler() {
const mergeSource = this.selectedTasks.map(t => t.taskId).join(',');
this.$emit('input', mergeSource);
this.$emit('change', mergeSource, this.selectedTasks);
},
deep: true
}
},
methods: {
/** 同步选中的任务列表 */
syncSelectedTasks(taskIds) {
this.selectedTasks = taskIds
.map(taskId => this.allTasks.find(t => t.taskId === taskId))
.filter(Boolean); // 过滤无效任务
},
/** 添加选中的任务 */
addSelectedTask(taskId) {
if (!taskId) return;
// 查找任务信息
const task = this.unmergedTasks.find(t => t.taskId === taskId);
if (task && !this.selectedTasks.some(t => t.taskId === taskId)) {
this.selectedTasks.push(task);
this.currentSelectTaskId = null; // 清空选择器
}
},
/** 移除任务 */
removeTask(taskId) {
this.selectedTasks = this.selectedTasks.filter(t => t.taskId !== taskId);
},
/** 清空选中的任务 */
clear() {
this.selectedTasks = [];
}
}
};
</script>
<style scoped>
.merge-source-selector {
width: 100%;
}
.selected-tasks {
margin-bottom: 15px;
max-height: 200px;
overflow-y: auto;
border: 1px solid #e4e7ed;
border-radius: 4px;
padding: 10px;
}
.selected-task-item {
display: flex;
align-items: center;
justify-content: space-between;
padding: 8px 5px;
border-bottom: 1px dashed #e4e7ed;
}
.selected-task-item:last-child {
border-bottom: none;
}
.task-info {
display: flex;
align-items: center;
gap: 10px;
flex: 1;
flex-wrap: wrap;
}
.task-quantity {
color: #606266;
font-size: 12px;
}
.delete-btn {
color: #f56c6c;
padding: 0 5px;
}
.no-selected-tip {
text-align: center;
color: #909399;
padding: 10px;
margin-bottom: 15px;
border: 1px dashed #e4e7ed;
border-radius: 4px;
}
.task-selector {
margin-top: 10px;
}
</style>