<template>
|
<div>
|
<el-dialog
|
v-model="isShow"
|
title="新增生产订单"
|
width="1500"
|
:close-on-click-modal="false"
|
@close="closeModal"
|
class="production-order-dialog"
|
>
|
<!-- 基本信息 -->
|
<div class="section-card">
|
<div class="section-header">
|
<span class="section-icon">📋</span>
|
<span class="section-title-text">基本信息</span>
|
</div>
|
<el-form label-width="100px" :model="formState" label-position="right" ref="formRef" class="compact-form">
|
<el-row :gutter="20">
|
<el-col :span="12">
|
<el-form-item
|
label="产品名称"
|
prop="productModelId"
|
:rules="[{ required: true, message: '请选择产品', trigger: 'change' }]"
|
>
|
<el-button type="primary" @click="showProductSelectDialog = true" class="select-btn">
|
{{ formState.productName ? formState.productName : '选择产品' }}
|
</el-button>
|
</el-form-item>
|
</el-col>
|
<el-col :span="12">
|
<el-form-item label="图纸编号" prop="productModelName">
|
<el-input v-model="formState.productModelName" disabled />
|
</el-form-item>
|
</el-col>
|
</el-row>
|
<el-row :gutter="20">
|
<el-col :span="12">
|
<el-form-item label="单位" prop="unit">
|
<el-input v-model="formState.unit" disabled />
|
</el-form-item>
|
</el-col>
|
<el-col :span="12">
|
<el-form-item label="销售合同号" prop="salesContractNo">
|
<el-input v-model="formState.salesContractNo" placeholder="请输入销售合同号" />
|
</el-form-item>
|
</el-col>
|
</el-row>
|
<el-row :gutter="20">
|
<el-col :span="12">
|
<el-form-item label="客户名称" prop="customerName">
|
<el-input v-model="formState.customerName" placeholder="请输入客户名称" />
|
</el-form-item>
|
</el-col>
|
<el-col :span="12">
|
<el-form-item label="需求数量" prop="quantity">
|
<el-input-number v-model="formState.quantity" :step="1" :min="1" style="width: 100%" />
|
</el-form-item>
|
</el-col>
|
</el-row>
|
<el-row :gutter="20">
|
<el-col :span="12">
|
<el-form-item label="交付日期" prop="deliveryDate">
|
<el-date-picker
|
v-model="formState.deliveryDate"
|
type="date"
|
placeholder="选择交付日期"
|
style="width: 100%"
|
format="YYYY-MM-DD"
|
value-format="YYYY-MM-DD"
|
/>
|
</el-form-item>
|
</el-col>
|
<el-col :span="12">
|
<el-form-item label="图纸上传">
|
<el-upload
|
action="#"
|
:auto-upload="false"
|
:on-change="handleFileChange"
|
:file-list="fileList"
|
:limit="5"
|
class="upload-inline"
|
>
|
<el-button type="primary" plain size="small">
|
<el-icon><Upload /></el-icon> 选择文件
|
</el-button>
|
<template #tip>
|
<div class="el-upload__tip">支持jpg/png/pdf,单个不超过10MB</div>
|
</template>
|
</el-upload>
|
</el-form-item>
|
</el-col>
|
</el-row>
|
</el-form>
|
</div>
|
|
<!-- 产品选择弹窗 -->
|
<ProductSelectDialog
|
v-model="showProductSelectDialog"
|
@confirm="handleProductSelect"
|
single
|
/>
|
|
<!-- 生产任务 -->
|
<div class="section-card">
|
<div class="section-header">
|
<span class="section-icon">🔧</span>
|
<span class="section-title-text">生产任务</span>
|
<el-button type="primary" size="small" @click="addProductionTask" class="add-btn">
|
<el-icon><Plus /></el-icon> 添加任务
|
</el-button>
|
</div>
|
<div class="table-container">
|
<el-table :data="productionTaskList" border size="small" class="compact-table">
|
<el-table-column type="index" label="序号" width="60" />
|
<el-table-column label="工序名称" min-width="150">
|
<template #default="{ row }">
|
<el-input v-model="row.processName" placeholder="请输入工序名称" />
|
</template>
|
</el-table-column>
|
<el-table-column label="计划数" min-width="120">
|
<template #default="{ row }">
|
<el-input-number v-model="row.planQuantity" :min="0" style="width: 100%" />
|
</template>
|
</el-table-column>
|
<el-table-column label="报工权限" min-width="150">
|
<template #default="{ row }">
|
<el-input v-model="row.reportPermission" placeholder="请输入报工权限" />
|
</template>
|
</el-table-column>
|
<el-table-column label="计划开始时间" min-width="180">
|
<template #default="{ row }">
|
<el-date-picker
|
v-model="row.planStartTime"
|
type="datetime"
|
placeholder="选择开始时间"
|
style="width: 100%"
|
format="YYYY-MM-DD HH:mm"
|
value-format="YYYY-MM-DD HH:mm:ss"
|
/>
|
</template>
|
</el-table-column>
|
<el-table-column label="计划结束时间" min-width="180">
|
<template #default="{ row }">
|
<el-date-picker
|
v-model="row.planEndTime"
|
type="datetime"
|
placeholder="选择结束时间"
|
style="width: 100%"
|
format="YYYY-MM-DD HH:mm"
|
value-format="YYYY-MM-DD HH:mm:ss"
|
/>
|
</template>
|
</el-table-column>
|
<el-table-column label="操作" width="80" fixed="right" align="center">
|
<template #default="{ $index }">
|
<el-button type="danger" link size="small" @click="removeProductionTask($index)">
|
<el-icon><Delete /></el-icon>
|
</el-button>
|
</template>
|
</el-table-column>
|
</el-table>
|
<div v-if="productionTaskList.length === 0" class="empty-tip">
|
<el-empty description="暂无生产任务,点击上方按钮添加" :image-size="60" />
|
</div>
|
</div>
|
</div>
|
|
<!-- 用料清单 -->
|
<div class="section-card">
|
<div class="section-header">
|
<span class="section-icon">📦</span>
|
<span class="section-title-text">用料清单</span>
|
<el-button type="primary" size="small" @click="addMaterialItem" class="add-btn">
|
<el-icon><Plus /></el-icon> 添加用料
|
</el-button>
|
</div>
|
<div class="table-container">
|
<el-table :data="materialList" border size="small" class="compact-table">
|
<el-table-column type="index" label="序号" width="50" align="center" />
|
<el-table-column label="图纸编号" min-width="140">
|
<template #default="{ row }">
|
<el-input v-model="row.drawingNumber" placeholder="请输入图纸编号" size="small" />
|
</template>
|
</el-table-column>
|
<el-table-column label="产品名称" min-width="140">
|
<template #default="{ row }">
|
<el-input v-model="row.productName" placeholder="请输入产品名称" size="small" />
|
</template>
|
</el-table-column>
|
<el-table-column label="单位用量" min-width="100">
|
<template #default="{ row }">
|
<el-input-number v-model="row.unitQuantity" :min="0" :precision="2" size="small" style="width: 100%" />
|
</template>
|
</el-table-column>
|
<el-table-column label="库存数量" min-width="100">
|
<template #default="{ row }">
|
<el-input-number v-model="row.inventoryQuantity" :min="0" size="small" style="width: 100%" />
|
</template>
|
</el-table-column>
|
<el-table-column label="操作" width="80" fixed="right" align="center">
|
<template #default="{ $index }">
|
<el-button type="danger" link size="small" @click="removeMaterialItem($index)">
|
<el-icon><Delete /></el-icon>
|
</el-button>
|
</template>
|
</el-table-column>
|
</el-table>
|
<div v-if="materialList.length === 0" class="empty-tip">
|
<el-empty description="暂无用料清单,点击上方按钮添加" :image-size="60" />
|
</div>
|
</div>
|
</div>
|
|
<template #footer>
|
<div class="dialog-footer">
|
<el-button type="primary" @click="handleSubmit">确认</el-button>
|
<el-button @click="closeModal">取消</el-button>
|
</div>
|
</template>
|
</el-dialog>
|
</div>
|
</template>
|
|
<script setup>
|
import {ref, computed, getCurrentInstance} from "vue";
|
import { Plus, Delete, Upload } from '@element-plus/icons-vue';
|
import ProductSelectDialog from "@/views/basicData/product/ProductSelectDialog.vue";
|
import {addProductOrder, listProcessRoute} from "@/api/productionManagement/productionOrder.js";
|
|
const props = defineProps({
|
visible: {
|
type: Boolean,
|
required: true,
|
},
|
|
type: {
|
type: String,
|
required: true,
|
default: 'qualified',
|
},
|
});
|
|
const emit = defineEmits(['update:visible', 'completed']);
|
|
// 响应式数据(替代选项式的 data)
|
const formState = ref({
|
productId: undefined,
|
productModelId: undefined,
|
routeId: undefined,
|
productName: "",
|
productModelName: "",
|
unit: "",
|
drawingNumber: "",
|
quantity: 0,
|
salesContractNo: "",
|
customerName: "",
|
deliveryDate: "",
|
});
|
|
// 生产任务列表
|
const productionTaskList = ref([]);
|
|
// 用料清单列表
|
const materialList = ref([]);
|
|
// 文件列表
|
const fileList = ref([]);
|
|
const isShow = computed({
|
get() {
|
return props.visible;
|
},
|
set(val) {
|
emit('update:visible', val);
|
},
|
});
|
|
const showProductSelectDialog = ref(false);
|
|
let { proxy } = getCurrentInstance()
|
|
const closeModal = () => {
|
// 重置表单数据
|
formState.value = {
|
productId: undefined,
|
productModelId: undefined,
|
routeId: undefined,
|
productName: "",
|
drawingNumber: "",
|
productModelName: "",
|
unit: "",
|
quantity: 0,
|
salesContractNo: "",
|
customerName: "",
|
deliveryDate: "",
|
};
|
// 重置生产任务和用料清单
|
productionTaskList.value = [];
|
materialList.value = [];
|
fileList.value = [];
|
isShow.value = false;
|
};
|
|
// 产品选择处理
|
const handleProductSelect = async (products) => {
|
if (products && products.length > 0) {
|
const product = products[0];
|
formState.value.productId = product.productId;
|
formState.value.productName = product.productName;
|
formState.value.drawingNumber = product.drawingNumber;
|
formState.value.productModelName = product.model;
|
formState.value.productModelId = product.id;
|
formState.value.unit = product.unit;
|
showProductSelectDialog.value = false;
|
fetchRouteOptions( product.id);
|
// 触发表单验证更新
|
proxy.$refs["formRef"]?.validateField('productModelId');
|
}
|
};
|
|
const routeOptions = ref([]);
|
const bindRouteLoading = ref(false);
|
const fetchRouteOptions = (productModelId) => {
|
formState.value.routeId = undefined;
|
routeOptions.value = []
|
bindRouteLoading.value = true;
|
listProcessRoute({ productModelId: productModelId }).then(res => {
|
routeOptions.value = res.data || [];
|
}).finally(() => {
|
bindRouteLoading.value = false;
|
})
|
}
|
|
// 添加生产任务
|
const addProductionTask = () => {
|
productionTaskList.value.push({
|
processName: "",
|
planQuantity: 0,
|
reportPermission: "",
|
planStartTime: "",
|
planEndTime: "",
|
});
|
};
|
|
// 删除生产任务
|
const removeProductionTask = (index) => {
|
productionTaskList.value.splice(index, 1);
|
};
|
|
// 添加用料
|
const addMaterialItem = () => {
|
materialList.value.push({
|
drawingNumber: "",
|
productName: "",
|
unitQuantity: 0,
|
inventoryQuantity: 0,
|
});
|
};
|
|
// 删除用料
|
const removeMaterialItem = (index) => {
|
materialList.value.splice(index, 1);
|
};
|
|
// 文件上传变更
|
const handleFileChange = (file, files) => {
|
fileList.value = files;
|
};
|
|
const handleSubmit = () => {
|
proxy.$refs["formRef"].validate(valid => {
|
if (valid) {
|
// 验证是否选择了产品和规格
|
if (!formState.value.productModelId) {
|
proxy.$modal.msgError("请选择产品");
|
return;
|
}
|
if (!formState.value.productModelId) {
|
proxy.$modal.msgError("请选择规格");
|
return;
|
}
|
|
// 组装提交数据
|
const submitData = {
|
...formState.value,
|
productionTasks: productionTaskList.value,
|
materials: materialList.value,
|
files: fileList.value,
|
};
|
|
addProductOrder(submitData).then(res => {
|
// 关闭模态框
|
isShow.value = false;
|
// 告知父组件已完成
|
emit('completed');
|
proxy.$modal.msgSuccess("提交成功");
|
})
|
}
|
})
|
};
|
|
|
defineExpose({
|
closeModal,
|
handleSubmit,
|
isShow,
|
});
|
</script>
|
|
<style scoped>
|
.production-order-dialog :deep(.el-dialog__body) {
|
padding: 15px 20px;
|
max-height: 70vh;
|
overflow-y: auto;
|
}
|
|
.section-card {
|
background: #f8f9fa;
|
border-radius: 8px;
|
padding: 15px;
|
margin-bottom: 15px;
|
}
|
|
.section-header {
|
display: flex;
|
align-items: center;
|
margin-bottom: 15px;
|
padding-bottom: 10px;
|
border-bottom: 1px solid #e4e7ed;
|
}
|
|
.section-icon {
|
font-size: 18px;
|
margin-right: 8px;
|
}
|
|
.section-title-text {
|
font-size: 15px;
|
font-weight: 600;
|
color: #303133;
|
flex: 1;
|
}
|
|
.add-btn {
|
margin-left: auto;
|
}
|
|
.compact-form :deep(.el-form-item) {
|
margin-bottom: 12px;
|
}
|
|
.compact-form :deep(.el-form-item__label) {
|
font-size: 13px;
|
color: #606266;
|
}
|
|
.select-btn {
|
width: 100%;
|
justify-content: flex-start;
|
}
|
|
.table-container {
|
background: #fff;
|
border-radius: 4px;
|
padding: 10px;
|
}
|
|
.compact-table :deep(.el-table__cell) {
|
padding: 4px 0;
|
}
|
|
.compact-table :deep(.el-input__wrapper),
|
.compact-table :deep(.el-input-number) {
|
width: 100%;
|
}
|
|
.empty-tip {
|
padding: 20px 0;
|
}
|
|
.upload-inline :deep(.el-upload) {
|
display: inline-flex;
|
}
|
|
.upload-inline :deep(.el-upload__tip) {
|
margin-top: 4px;
|
font-size: 12px;
|
}
|
|
.dialog-footer {
|
display: flex;
|
justify-content: center;
|
gap: 10px;
|
}
|
</style>
|