490 lines
17 KiB
Vue
490 lines
17 KiB
Vue
<template>
|
||
<div class="app-container">
|
||
<el-row style="margin-bottom: 20px; padding: 0 10px;">
|
||
<!-- 任务列表容器 -->
|
||
<div class="task-list-container">
|
||
<!-- 单个任务项 -->
|
||
<div v-for="(item, index) in taskList"
|
||
:key="index"
|
||
class="task-item"
|
||
:style="{marginBottom: index === taskList.length - 1 ? '0' : '20px'}">
|
||
|
||
<!-- 产品信息区域 -->
|
||
<div class="product-info-wrapper">
|
||
<ProductInfo :productId="item && item[0] && item[0].productId" />
|
||
</div>
|
||
|
||
<!-- 工艺流程区域 -->
|
||
<div class="process-flow-container">
|
||
<div v-for="(process, pIndex) in item"
|
||
:key="process.processId"
|
||
class="process-item"
|
||
:style="{
|
||
marginRight: pIndex !== item.length - 1 ? '15px' : '0',
|
||
// 最后一个工艺项不加右侧间距
|
||
}">
|
||
<CraftInfo :craftId="process.processId" />
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</el-row>
|
||
|
||
<el-row :gutter="10" class="mb8">
|
||
<el-col :span="1.5">
|
||
<el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleInitBatch">生成生产任务</el-button>
|
||
</el-col>
|
||
<el-col :span="1.5">
|
||
<el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd">新增</el-button>
|
||
</el-col>
|
||
<el-col :span="1.5">
|
||
<el-button type="success" plain icon="el-icon-edit" size="mini" :disabled="single"
|
||
@click="handleUpdate">修改</el-button>
|
||
</el-col>
|
||
<el-col :span="1.5">
|
||
<el-button type="danger" plain icon="el-icon-delete" size="mini" :disabled="multiple"
|
||
@click="handleDelete">删除</el-button>
|
||
</el-col>
|
||
<el-col :span="1.5">
|
||
<el-button type="warning" plain icon="el-icon-download" size="mini" @click="handleExport">导出</el-button>
|
||
</el-col>
|
||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
||
</el-row>
|
||
|
||
<el-table v-loading="loading" :data="batchList" @selection-change="handleSelectionChange">
|
||
<el-table-column type="selection" width="55" align="center" />
|
||
<el-table-column label="生产任务ID" align="center" prop="batchId" v-if="true" />
|
||
<el-table-column label="生产任务编号" align="center" prop="batchNo" />
|
||
<el-table-column label="关联工艺ID" align="center" prop="processId">
|
||
<template slot-scope="scope">
|
||
<CraftInfo :craftId="scope.row.processId" />
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column label="生产任务总数量" align="center" prop="totalQuantity" />
|
||
<el-table-column label="合并来源" align="center" prop="mergeSource">
|
||
<template slot-scope="scope">
|
||
<div v-for="item in scope.row.mergeSource.split(',')" style="display: flex; align-items: center; justify-content: center; gap: 10px;" :key="item">
|
||
<ProductInfo :productId="getTaskInfo(item).productId" />
|
||
<CraftInfo :craftId="getTaskInfo(item).processId" />
|
||
</div>
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column label="预计开始时间" align="center" prop="estimatedStartTime" width="180">
|
||
<template slot-scope="scope">
|
||
<span>{{ parseTime(scope.row.estimatedStartTime, '{y}-{m}-{d}') }}</span>
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column label="预计结束时间" align="center" prop="estimatedEndTime" width="180">
|
||
<template slot-scope="scope">
|
||
<span>{{ parseTime(scope.row.estimatedEndTime, '{y}-{m}-{d}') }}</span>
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column label="状态" align="center" prop="batchStatus">
|
||
<template slot-scope="scope">
|
||
<dict-tag :options="dict.type.batch_status" :value="scope.row.batchStatus" />
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column label="备注" align="center" prop="remark" />
|
||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||
<template slot-scope="scope">
|
||
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)">修改</el-button>
|
||
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)">删除</el-button>
|
||
</template>
|
||
</el-table-column>
|
||
</el-table>
|
||
|
||
<!-- 添加或修改批次(合并相同工艺的任务)对话框 -->
|
||
<el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
|
||
<el-form ref="form" :model="form" :rules="rules" label-width="120px">
|
||
<el-form-item label="生产任务编号" prop="batchNo">
|
||
<el-input v-model="form.batchNo" placeholder="请输入生产任务编号" />
|
||
</el-form-item>
|
||
<!-- <el-form-item label="关联工艺ID" prop="processId">
|
||
<el-input v-model="form.processId" placeholder="请输入关联工艺ID" />
|
||
</el-form-item> -->
|
||
<!-- <el-form-item label="批次总数量" prop="totalQuantity">
|
||
<el-input v-model="form.totalQuantity" placeholder="请输入批次总数量" />
|
||
</el-form-item> -->
|
||
<el-form-item label="合并来源" prop="mergeSource">
|
||
<merge-source-selector
|
||
v-model="form.mergeSource"
|
||
:unmerged-tasks="unmergedTaskList"
|
||
:all-tasks="allTasks"
|
||
@change="handleMergeSourceChange"
|
||
/>
|
||
<!-- <el-input v-model="form.mergeSource" type="textarea" placeholder="请输入内容" /> -->
|
||
</el-form-item>
|
||
<el-form-item label="预计开始时间" prop="estimatedStartTime">
|
||
<el-date-picker clearable v-model="form.estimatedStartTime" type="datetime" value-format="yyyy-MM-dd HH:mm:ss"
|
||
placeholder="请选择预计开始时间">
|
||
</el-date-picker>
|
||
</el-form-item>
|
||
<el-form-item label="预计结束时间" prop="estimatedEndTime">
|
||
<el-date-picker clearable v-model="form.estimatedEndTime" type="datetime" value-format="yyyy-MM-dd HH:mm:ss"
|
||
placeholder="请选择预计结束时间">
|
||
</el-date-picker>
|
||
</el-form-item>
|
||
<el-form-item label="备注" prop="remark">
|
||
<el-input v-model="form.remark" placeholder="请输入备注" />
|
||
</el-form-item>
|
||
</el-form>
|
||
<div slot="footer" class="dialog-footer">
|
||
<el-button :loading="buttonLoading" type="primary" @click="submitForm">确 定</el-button>
|
||
<el-button @click="cancel">取 消</el-button>
|
||
</div>
|
||
</el-dialog>
|
||
|
||
<el-drawer title="生成生产任务" direction="btt" size="90vh" :visible.sync="batchGenerateDialogVisible" append-to-body>
|
||
<el-table :data="generateBatchList" style="width: 100%;" border>
|
||
<el-table-column label="生产任务编号" align="center" prop="batchNo">
|
||
<template slot-scope="scope">
|
||
<el-input v-model="scope.row.batchNo" />
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column label="合并来源" align="center" prop="mergeSource">
|
||
<template slot-scope="scope">
|
||
<div v-for="item in scope.row.mergeSource.split(',')"
|
||
style="display: flex; align-items: center; justify-content: center; gap: 10px;" :key="item">
|
||
<!-- 返回的是taskId, 需要查找到对应的processId和productId -->
|
||
<ProductInfo :productId="getTaskInfo(item).productId" />
|
||
<CraftInfo :craftId="getTaskInfo(item).processId" />
|
||
</div>
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column label="生产任务总数量" align="center" prop="totalQuantity" />
|
||
<el-table-column label="预计开始时间" align="center" prop="estimatedStartTime">
|
||
<template slot-scope="scope">
|
||
<el-date-picker v-model="scope.row.estimatedStartTime" type="datetime" value-format="yyyy-MM-dd HH:mm:ss"
|
||
placeholder="请选择预计开始时间" />
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column label="预计结束时间" align="center" prop="estimatedEndTime">
|
||
<template slot-scope="scope">
|
||
<el-date-picker v-model="scope.row.estimatedEndTime" type="datetime" value-format="yyyy-MM-dd HH:mm:ss"
|
||
placeholder="请选择预计结束时间" />
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||
<template slot-scope="scope">
|
||
<el-button type="primary" size="mini" @click="handleAddBatch(scope.row)">创建生产任务</el-button>
|
||
</template>
|
||
</el-table-column>
|
||
</el-table>
|
||
</el-drawer>
|
||
</div>
|
||
</template>
|
||
|
||
<script>
|
||
import { listBatch, getBatch, delBatch, addBatch, updateBatch, generateBatch } from "@/api/wms/batch";
|
||
import { listProcessTask } from "@/api/wms/processTask";
|
||
|
||
|
||
import CraftInfo from '@/components/KLPService/Renderer/CraftInfo.vue';
|
||
import ProductInfo from '@/components/KLPService/Renderer/ProductInfo.vue';
|
||
import MergeSourceSelector from "../components/MergeSourceSelector.vue";
|
||
|
||
export default {
|
||
name: "Batch",
|
||
components: {
|
||
CraftInfo,
|
||
ProductInfo,
|
||
MergeSourceSelector
|
||
},
|
||
dicts: ['batch_status'],
|
||
props: {
|
||
planId: {
|
||
type: [String, Number, undefined],
|
||
required: true
|
||
}
|
||
},
|
||
computed: {
|
||
// 所有还没有被合并的任务
|
||
unmergedTaskList() {
|
||
// 也就是不在batchList.mergeSource中的
|
||
return this.allTasks.filter(item => !this.batchList.some(batch => batch.mergeSource.split(',').includes(item.taskId)));
|
||
},
|
||
allTasks() {
|
||
return this.taskList.flat(1);
|
||
},
|
||
},
|
||
data() {
|
||
return {
|
||
// 按钮loading
|
||
buttonLoading: false,
|
||
// 遮罩层
|
||
loading: true,
|
||
// 选中数组
|
||
ids: [],
|
||
// 非单个禁用
|
||
single: true,
|
||
// 非多个禁用
|
||
multiple: true,
|
||
// 显示搜索条件
|
||
showSearch: true,
|
||
// 总条数
|
||
total: 0,
|
||
// 批次(合并相同工艺的任务)表格数据
|
||
batchList: [],
|
||
// 弹出层标题
|
||
title: "",
|
||
// 是否显示弹出层
|
||
open: false,
|
||
// 查询参数
|
||
queryParams: {
|
||
pageNum: 1,
|
||
pageSize: 999,
|
||
planId: this.planId,
|
||
batchNo: undefined,
|
||
processId: undefined,
|
||
totalQuantity: undefined,
|
||
mergeSource: undefined,
|
||
estimatedStartTime: undefined,
|
||
estimatedEndTime: undefined,
|
||
batchStatus: undefined,
|
||
},
|
||
// 表单参数
|
||
form: {},
|
||
// 表单校验
|
||
rules: {
|
||
},
|
||
// 所有的工序任务
|
||
taskList: [],
|
||
// 批次生成对话框是否显示
|
||
batchGenerateDialogVisible: false,
|
||
generateBatchList: []
|
||
};
|
||
},
|
||
created() {
|
||
this.getList();
|
||
this.getProcessList();
|
||
},
|
||
methods: {
|
||
async getProcessList() {
|
||
const { rows } = await listProcessTask({ planId: this.planId });
|
||
// 整理成二维数组,按照productId
|
||
const productIdToProcessTaskList = {};
|
||
rows.forEach(item => {
|
||
if (!productIdToProcessTaskList[item.productId]) {
|
||
productIdToProcessTaskList[item.productId] = [];
|
||
}
|
||
productIdToProcessTaskList[item.productId].push(item);
|
||
});
|
||
this.taskList = Object.values(productIdToProcessTaskList);
|
||
},
|
||
getTaskInfo(taskId) {
|
||
const task = this.allTasks.find(item => item.taskId == taskId);
|
||
// console.log(task, taskId);
|
||
if (!task) {
|
||
return {
|
||
productId: '',
|
||
processId: ''
|
||
};
|
||
}
|
||
return task;
|
||
},
|
||
/** 查询批次(合并相同工艺的任务)列表 */
|
||
getList() {
|
||
this.loading = true;
|
||
listBatch(this.queryParams).then(response => {
|
||
this.batchList = response.rows;
|
||
this.total = response.total;
|
||
this.loading = false;
|
||
});
|
||
},
|
||
// 取消按钮
|
||
cancel() {
|
||
this.open = false;
|
||
this.reset();
|
||
},
|
||
// 表单重置
|
||
reset() {
|
||
this.form = {
|
||
batchId: undefined,
|
||
batchNo: undefined,
|
||
processId: undefined,
|
||
totalQuantity: undefined,
|
||
mergeSource: undefined,
|
||
estimatedStartTime: undefined,
|
||
estimatedEndTime: undefined,
|
||
batchStatus: undefined,
|
||
delFlag: undefined,
|
||
remark: undefined,
|
||
createTime: undefined,
|
||
createBy: undefined,
|
||
updateTime: undefined,
|
||
updateBy: undefined
|
||
};
|
||
this.resetForm("form");
|
||
},
|
||
/** 搜索按钮操作 */
|
||
handleQuery() {
|
||
this.queryParams.pageNum = 1;
|
||
this.getList();
|
||
},
|
||
// 处理合并来源变化的回调
|
||
handleMergeSourceChange(mergeSource, selectedTasks) {
|
||
console.log('合并来源变化:', mergeSource);
|
||
console.log('选中的任务:', selectedTasks);
|
||
// 可以在这里做一些额外处理,比如计算总数量等
|
||
},
|
||
async handleInitBatch() {
|
||
generateBatch(this.taskList).then(res => {
|
||
console.log(res)
|
||
this.batchGenerateDialogVisible = true;
|
||
this.generateBatchList = res.data.map(item => {
|
||
let totalQuantity = 0;
|
||
for (const taskId of item.taskIds) {
|
||
const task = this.allTasks.find(item => item.taskId == taskId);
|
||
totalQuantity += task.taskQuantity;
|
||
}
|
||
return {
|
||
...item,
|
||
planId: this.planId,
|
||
processId: item.processId,
|
||
mergeSource: item.taskIds.join(','),
|
||
batchNo: item.groupId,
|
||
totalQuantity
|
||
}
|
||
});
|
||
})
|
||
},
|
||
/** 重置按钮操作 */
|
||
resetQuery() {
|
||
this.resetForm("queryForm");
|
||
this.handleQuery();
|
||
},
|
||
// 多选框选中数据
|
||
handleSelectionChange(selection) {
|
||
this.ids = selection.map(item => item.batchId)
|
||
this.single = selection.length !== 1
|
||
this.multiple = !selection.length
|
||
},
|
||
/** 新增按钮操作 */
|
||
handleAdd() {
|
||
this.reset();
|
||
this.open = true;
|
||
this.title = "添加生产任务(合并相同工艺的任务)";
|
||
},
|
||
/** 修改按钮操作 */
|
||
handleUpdate(row) {
|
||
this.loading = true;
|
||
this.reset();
|
||
const batchId = row.batchId || this.ids
|
||
getBatch(batchId).then(response => {
|
||
this.loading = false;
|
||
this.form = response.data;
|
||
this.open = true;
|
||
this.title = "修改生产任务(合并相同工艺的任务)";
|
||
});
|
||
},
|
||
/** 提交按钮 */
|
||
submitForm() {
|
||
this.$refs["form"].validate(valid => {
|
||
if (valid) {
|
||
this.buttonLoading = true;
|
||
if (this.form.batchId != null) {
|
||
updateBatch(this.form).then(response => {
|
||
this.$modal.msgSuccess("修改成功");
|
||
this.open = false;
|
||
this.getList();
|
||
}).finally(() => {
|
||
this.buttonLoading = false;
|
||
});
|
||
} else {
|
||
addBatch(this.form).then(response => {
|
||
this.$modal.msgSuccess("新增成功");
|
||
this.open = false;
|
||
this.getList();
|
||
}).finally(() => {
|
||
this.buttonLoading = false;
|
||
});
|
||
}
|
||
}
|
||
});
|
||
},
|
||
handleAddBatch(row) {
|
||
addBatch(row).then(response => {
|
||
this.$modal.msgSuccess("新增成功");
|
||
this.getList();
|
||
}).finally(() => {
|
||
this.buttonLoading = false;
|
||
});
|
||
},
|
||
/** 删除按钮操作 */
|
||
handleDelete(row) {
|
||
const batchIds = row.batchId || this.ids;
|
||
this.$modal.confirm('是否确认删除生产任务(合并相同工艺的任务)编号为"' + batchIds + '"的数据项?').then(() => {
|
||
this.loading = true;
|
||
return delBatch(batchIds);
|
||
}).then(() => {
|
||
this.loading = false;
|
||
this.getList();
|
||
this.$modal.msgSuccess("删除成功");
|
||
}).catch(() => {
|
||
}).finally(() => {
|
||
this.loading = false;
|
||
});
|
||
},
|
||
/** 导出按钮操作 */
|
||
handleExport() {
|
||
this.download('klp/batch/export', {
|
||
...this.queryParams
|
||
}, `batch_${new Date().getTime()}.xlsx`)
|
||
}
|
||
}
|
||
};
|
||
</script>
|
||
|
||
<style scoped>
|
||
/* 任务列表容器 */
|
||
.task-list-container {
|
||
width: 100%;
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
/* 单个任务项样式 */
|
||
.task-item {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
align-items: center;
|
||
}
|
||
|
||
/* 鼠标悬停效果 */
|
||
.task-item:hover {
|
||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
|
||
background-color: #fff;
|
||
}
|
||
|
||
/* 产品信息容器 */
|
||
.product-info-wrapper {
|
||
min-width: 180px; /* 固定产品信息宽度,保证对齐 */
|
||
padding: 8px 0;
|
||
border-right: 1px dashed #e5e7eb; /* 分隔线 */
|
||
margin-right: 15px;
|
||
}
|
||
|
||
/* 工艺流程容器 */
|
||
.process-flow-container {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: 12px; /* 工艺项之间的间距 */
|
||
padding: 8px 0;
|
||
flex: 1; /* 占满剩余空间 */
|
||
}
|
||
|
||
/* 单个工艺项样式 */
|
||
.process-item {
|
||
flex: 0 0 auto; /* 不自动拉伸 */
|
||
padding: 8px 12px;
|
||
border-radius: 4px;
|
||
background-color: #fff;
|
||
border: 1px solid #eee;
|
||
transition: border-color 0.2s ease;
|
||
}
|
||
|
||
.process-item:hover {
|
||
border-color: #409eff; /* 高亮边框 */
|
||
}
|
||
|
||
</style>
|