| | |
| | | <span class="info-value">{{ routeInfo.bomNo || '-' }}</span> |
| | | </div> |
| | | </div> |
| | | <div class="info-item" |
| | | v-if="routeInfo.quantity && routeInfo.quantity !== 0"> |
| | | <div class="info-label-wrapper"> |
| | | <span class="info-label">需求数量</span> |
| | | </div> |
| | | <div class="info-value-wrapper"> |
| | | <span class="info-value">{{ routeInfo.quantity || '-' }}</span> |
| | | </div> |
| | | </div> |
| | | <div class="info-item full-width" |
| | | v-if="routeInfo.description"> |
| | | <div class="info-label-wrapper"> |
| | |
| | | style="margin-right: 10px;"> |
| | | 卡片视图 |
| | | </el-button> |
| | | <el-button type="primary" |
| | | <el-button v-if="editable" |
| | | type="primary" |
| | | @click="handleAdd">新增</el-button> |
| | | </div> |
| | | </div> |
| | |
| | | prop="technologyOperationId" |
| | | width="200"> |
| | | <template #default="scope"> |
| | | {{ getProcessName(scope.row.technologyOperationId) || '-' }} |
| | | {{ scope.row.technologyOperationName || scope.row.operationName || '-' }} |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="参数列表" |
| | |
| | | link |
| | | size="small" |
| | | @click="handleEdit(scope.row)" |
| | | :disabled="scope.row.isComplete">编辑</el-button> |
| | | :disabled="scope.row.isComplete || !editable">编辑</el-button> |
| | | <el-button type="danger" |
| | | link |
| | | size="small" |
| | | @click="handleDelete(scope.row)" |
| | | :disabled="scope.row.isComplete">删除</el-button> |
| | | :disabled="scope.row.isComplete || !editable">删除</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | |
| | | style="margin-right: 10px;"> |
| | | 表格视图 |
| | | </el-button> |
| | | <el-button type="primary" |
| | | <el-button v-if="editable" |
| | | type="primary" |
| | | @click="handleAdd">新增</el-button> |
| | | </div> |
| | | </div> |
| | |
| | | <!-- 序号圆圈 --> |
| | | <div class="card-header"> |
| | | <div class="card-number">{{ index + 1 }}</div> |
| | | <div class="card-process-name">{{ getProcessName(item.technologyOperationId) || '-' }}</div> |
| | | <div class="card-process-name">{{ item.technologyOperationName || item.operationName || '-' }}</div> |
| | | </div> |
| | | <!-- 产品信息 --> |
| | | <div class="card-content"> |
| | |
| | | link |
| | | size="small" |
| | | @click="handleEdit(item)" |
| | | :disabled="item.isComplete">编辑</el-button> |
| | | :disabled="item.isComplete || !editable">编辑</el-button> |
| | | <el-button type="info" |
| | | link |
| | | size="small" |
| | |
| | | link |
| | | size="small" |
| | | @click="handleDelete(item)" |
| | | :disabled="item.isComplete">删除</el-button> |
| | | :disabled="item.isComplete || !editable">删除</el-button> |
| | | </div> |
| | | </div> |
| | | </div> |
| | |
| | | style="margin-top: 20px;"> |
| | | <div class="section-title">BOM 结构</div> |
| | | <div class="section-actions" |
| | | v-if="pageType === 'order'"> |
| | | v-if="pageType === 'order' && editable"> |
| | | <el-button v-if="!bomDataValue.isEdit" |
| | | type="primary" |
| | | @click="bomDataValue.isEdit = true"> |
| | |
| | | style="width: 100%"> |
| | | <el-table-column type="expand"> |
| | | <template #default> |
| | | <el-form ref="form" |
| | | <el-form ref="bomFormRef" |
| | | :model="bomDataValue"> |
| | | <el-table :data="bomDataValue.dataList" |
| | | row-key="tempId" |
| | |
| | | :step="1" |
| | | controls-position="right" |
| | | style="width: 100%" |
| | | @change="handleUnitQuantityChange(row)" |
| | | :disabled="!bomDataValue.isEdit || bomDataValue.dataList.some(item => (item).tempId === row.tempId)" /> |
| | | </el-form-item> |
| | | </template> |
| | |
| | | prop="model" /> |
| | | </el-table> |
| | | <ProductSelectDialog v-if="bomDataValue.showProductDialog" |
| | | v-model:model-value="bomDataValue.showProductDialog" |
| | | v-model="bomDataValue.showProductDialog" |
| | | :single="true" |
| | | @confirm="handleBomProduct" /> |
| | | <!-- 新增/编辑弹窗 --> |
| | |
| | | :rules="rules" |
| | | label-width="120px"> |
| | | <el-form-item label="工序" |
| | | v-if="operationType === 'add' || pageType === 'route'" |
| | | prop="technologyOperationId"> |
| | | <el-select v-model="form.technologyOperationId" |
| | | placeholder="请选择工序" |
| | |
| | | :value="process.id" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="工序" |
| | | v-else> |
| | | <span>{{ getProcessName(form.technologyOperationId) }}</span> |
| | | </el-form-item> |
| | | <el-form-item label="产品名称" |
| | | v-if="operationType === 'add' || pageType === 'route'" |
| | | prop="productModelId"> |
| | | <el-button type="primary" |
| | | @click="showProductSelectDialog = true"> |
| | | {{ form.productName && form.model |
| | | ? `${form.productName} - ${form.model}` |
| | | {{ form.productName |
| | | ? (form.model ? `${form.productName} - ${form.model}` : form.productName) |
| | | : '选择产品' }} |
| | | </el-button> |
| | | </el-form-item> |
| | | <el-form-item label="产品名称" |
| | | v-else> |
| | | <span>{{ form.productName }}{{ form.model ? ' - ' + form.model : '' }}</span> |
| | | </el-form-item> |
| | | <el-form-item label="单位" |
| | | v-if="operationType === 'add' || pageType === 'route'" |
| | | prop="unit"> |
| | | <el-input v-model="form.unit" |
| | | :placeholder="form.productModelId ? '根据选择的产品自动带出' : '请先选择产品'" |
| | | clearable |
| | | :disabled="true" /> |
| | | </el-form-item> |
| | | <el-form-item label="单位" |
| | | v-else> |
| | | <span>{{ form.unit }}</span> |
| | | </el-form-item> |
| | | <el-form-item label="是否质检" |
| | | prop="isQuality"> |
| | | <el-switch v-model="form.isQuality" |
| | | :active-value="true" |
| | | inactive-value="false" /> |
| | | :inactive-value="false" /> |
| | | </el-form-item> |
| | | <el-form-item label="是否生产" |
| | | prop="isProduction"> |
| | | <el-switch v-model="form.isProduction" |
| | | :active-value="true" |
| | | inactive-value="false" /> |
| | | :inactive-value="false" /> |
| | | </el-form-item> |
| | | </el-form> |
| | | <template #footer> |
| | |
| | | @confirm="handleProductSelect" |
| | | single /> |
| | | <!-- 参数列表对话框 --> |
| | | <!-- :editable="!routeInfo.status" --> |
| | | <ProcessParamListDialog v-model="showParamListDialog" |
| | | :title="`${currentProcess ? (currentProcess.processName || getProcessName(currentProcess.technologyOperationId)) : ''} - 参数列表`" |
| | | :title="`${currentProcess ? (currentProcess.processName || currentProcess.technologyOperationName || currentProcess.operationName) : ''} - 参数列表`" |
| | | :route-id="routeId" |
| | | :order-id="orderId" |
| | | :process="currentProcess" |
| | | :page-type="pageType" |
| | | :param-list="paramList" |
| | | :editable="editable" |
| | | @getsyncProcessParamItem="getsyncProcessParamItem" |
| | | @refresh="refreshParamList" /> |
| | | </div> |
| | |
| | | batchDeleteProcessRouteItem, |
| | | getProcessParamList, |
| | | } from "@/api/productionManagement/processRouteItem.js"; |
| | | import { syncProcessParamItem } from "@/api/productionManagement/processRouteItem.js"; |
| | | import { |
| | | syncProcessParamItem, |
| | | syncProcessParamItemOrder, |
| | | } from "@/api/productionManagement/processRouteItem.js"; |
| | | import { |
| | | findProductProcessRouteItemList, |
| | | deleteRouteItem, |
| | |
| | | import { listProcessBom } from "@/api/productionManagement/productionOrder.js"; |
| | | import { |
| | | queryList, |
| | | addBomDetail, |
| | | queryList2, |
| | | add2, |
| | | } from "@/api/productionManagement/productStructure.js"; |
| | | |
| | | import { useRoute } from "vue-router"; |
| | | import { ElMessageBox, ElMessage } from "element-plus"; |
| | | import Sortable from "sortablejs"; |
| | |
| | | const routeId = computed(() => route.query.id); |
| | | const orderId = computed(() => route.query.orderId); |
| | | const pageType = computed(() => route.query.type); |
| | | const editable = computed(() => route.query.editable !== "false"); |
| | | |
| | | const tableLoading = ref(false); |
| | | const tableData = ref([]); |
| | | const dialogVisible = ref(false); |
| | | const operationType = ref("add"); // add | edit |
| | | const formRef = ref(null); |
| | | const bomFormRef = ref(null); |
| | | const submitLoading = ref(false); |
| | | const cardsContainer = ref(null); |
| | | const tableRef = ref(null); |
| | |
| | | model: "", |
| | | bomNo: "", |
| | | description: "", |
| | | quantity: 0, |
| | | }); |
| | | |
| | | const processOptions = ref([]); |
| | |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | syncProcessParamItem({ |
| | | replaceExisting: true, |
| | | technologyRoutingOperationId: currentProcess.value.id, |
| | | }).then(res => { |
| | | if (res.code === 200) { |
| | | ElMessage.success("同步成功"); |
| | | refreshParamList(); |
| | | } else { |
| | | ElMessage.error(res.msg || "同步失败"); |
| | | } |
| | | }); |
| | | if (pageType.value === "order") { |
| | | syncProcessParamItemOrder({ |
| | | replaceExisting: true, |
| | | technologyRoutingOperationId: currentProcess.value.id, |
| | | }).then(res => { |
| | | if (res.code === 200) { |
| | | ElMessage.success("同步成功"); |
| | | refreshParamList(); |
| | | } else { |
| | | ElMessage.error(res.msg || "同步失败"); |
| | | } |
| | | }); |
| | | } else { |
| | | syncProcessParamItem({ |
| | | replaceExisting: true, |
| | | technologyRoutingOperationId: currentProcess.value.id, |
| | | }).then(res => { |
| | | if (res.code === 200) { |
| | | ElMessage.success("同步成功"); |
| | | refreshParamList(); |
| | | } else { |
| | | ElMessage.error(res.msg || "同步失败"); |
| | | } |
| | | }); |
| | | } |
| | | }) |
| | | .catch(() => {}); |
| | | }; |
| | |
| | | bomNo: route.query.bomNo || "", |
| | | bomId: route.query.bomId || "", |
| | | description: route.query.description || "", |
| | | quantity: route.query.quantity || 0, |
| | | status: !(route.query.status == 1 || route.query.status === "false"), |
| | | }; |
| | | bomTableData.value[0].productName = routeInfo.value.productName; |
| | |
| | | |
| | | // 产品选择 |
| | | const handleProductSelect = products => { |
| | | console.log(products, "===products==="); |
| | | if (products && products.length > 0) { |
| | | const product = products[0]; |
| | | form.value.productModelId = product.id; |
| | | form.value.productName = product.productName; |
| | | form.value.model = product.model; |
| | | form.value.unit = product.unit || ""; |
| | | console.log(product, "product"); |
| | | form.value = { |
| | | ...form.value, |
| | | productModelId: product.id, |
| | | productName: product.productName, |
| | | model: product.model, |
| | | unit: product.unit || "", |
| | | }; |
| | | showProductSelectDialog.value = false; |
| | | // 触发表单验证 |
| | | formRef.value?.validateField("productModelId"); |
| | | // formRef.value?.validateField("productModelId"); |
| | | } |
| | | }; |
| | | |
| | |
| | | |
| | | const addPromise = isOrderPage |
| | | ? addRouteItem({ |
| | | productOrderId: orderId.value, |
| | | productRouteId: routeId.value, |
| | | productionOrderId: Number(orderId.value), |
| | | orderRoutingId: Number(routeId.value), |
| | | technologyOperationId: form.value.technologyOperationId, |
| | | technologyRoutingId: Number(routeId.value), |
| | | operationName: getProcessName(form.value.technologyOperationId), |
| | | productModelId: form.value.productModelId, |
| | | isQuality: form.value.isQuality, |
| | | isProduction: form.value.isProduction, |
| | |
| | | ? addOrUpdateProductProcessRouteItem({ |
| | | id: form.value.id, |
| | | technologyOperationId: form.value.technologyOperationId, |
| | | operationName: getProcessName(form.value.technologyOperationId), |
| | | productModelId: form.value.productModelId, |
| | | isQuality: form.value.isQuality, |
| | | isProduction: form.value.isProduction, |
| | |
| | | productName: "", |
| | | model: "", |
| | | unit: "", |
| | | isQuality: false, |
| | | isProduction: false, |
| | | }; |
| | | formRef.value?.resetFields(); |
| | | }; |
| | |
| | | // 查看参数列表 |
| | | const handleViewParams = row => { |
| | | currentProcess.value = row; |
| | | const query = { |
| | | const param = { |
| | | productionOrderRoutingOperationId: row.id, |
| | | productionOrderId: orderId.value, |
| | | }; |
| | | const param1 = { |
| | | technologyRoutingOperationId: row.id, |
| | | orderId: orderId.value, |
| | | productionOrderId: orderId.value, |
| | | }; |
| | | |
| | | const apiPromise = |
| | | pageType.value === "order" |
| | | ? findProcessParamListOrder(query) |
| | | : getProcessParamList(query); |
| | | ? findProcessParamListOrder(param) |
| | | : getProcessParamList(param1); |
| | | |
| | | apiPromise |
| | | .then(res => { |
| | |
| | | // 初始化拖拽排序 |
| | | const initSortable = () => { |
| | | destroySortable(); |
| | | if (!editable.value) return; |
| | | |
| | | if (viewMode.value === "table") { |
| | | // 表格视图的拖拽排序 |
| | |
| | | }); |
| | | |
| | | const syncProcessOperationFields = item => { |
| | | const processId = item.processId ?? item.operationId ?? ""; |
| | | const processId = |
| | | item.processId ?? item.operationId ?? item.technologyOperationId ?? ""; |
| | | if (!processId) { |
| | | item.processId = ""; |
| | | return; |
| | |
| | | option?.name || item.processName || item.operationName || ""; |
| | | |
| | | item.processId = processId; |
| | | item.operationId = processId; |
| | | if (pageType.value === "order") { |
| | | item.technologyOperationId = processId; |
| | | } else { |
| | | item.operationId = processId; |
| | | } |
| | | item.processName = processName; |
| | | item.operationName = processName; |
| | | }; |
| | |
| | | |
| | | const fetchBomData = async () => { |
| | | try { |
| | | const { data } = await queryList(routeInfo.value.bomId); |
| | | const isOrderPage = pageType.value === "order"; |
| | | const { data } = await (isOrderPage ? queryList2 : queryList)( |
| | | routeInfo.value.bomId |
| | | ); |
| | | bomDataValue.value.dataList = data || []; |
| | | normalizeTreeData(bomDataValue.value.dataList); |
| | | } catch (err) { |
| | |
| | | }); |
| | | }; |
| | | |
| | | const handleUnitQuantityChange = row => { |
| | | if (routeInfo.value.quantity && routeInfo.value.quantity !== 0) { |
| | | row.demandedQuantity = (row.unitQuantity || 0) * routeInfo.value.quantity; |
| | | } |
| | | }; |
| | | |
| | | const addchildItem = (item, tempId) => { |
| | | if (item.tempId === tempId) { |
| | | if (!item.children) { |
| | |
| | | productModelId: undefined, |
| | | processId: "", |
| | | processName: "", |
| | | operationId: "", |
| | | [pageType.value === "order" ? "technologyOperationId" : "operationId"]: |
| | | "", |
| | | operationName: "", |
| | | unitQuantity: 1, |
| | | demandedQuantity: 0, |
| | | demandedQuantity: |
| | | routeInfo.value.quantity && routeInfo.value.quantity !== 0 |
| | | ? 1 * routeInfo.value.quantity |
| | | : 0, |
| | | children: [], |
| | | unit: "", |
| | | tempId: new Date().getTime(), |
| | |
| | | productModelId: undefined, |
| | | processId: "", |
| | | processName: "", |
| | | operationId: "", |
| | | [pageType.value === "order" ? "technologyOperationId" : "operationId"]: |
| | | "", |
| | | operationName: "", |
| | | unitQuantity: 1, |
| | | demandedQuantity: 0, |
| | | demandedQuantity: |
| | | routeInfo.value.quantity && routeInfo.value.quantity !== 0 |
| | | ? 1 * routeInfo.value.quantity |
| | | : 0, |
| | | unit: "", |
| | | children: [], |
| | | tempId: new Date().getTime(), |
| | |
| | | |
| | | const handleSaveBom = () => { |
| | | bomDataValue.value.loading = true; |
| | | console.log(bomDataValue.value.dataList, "bomDataValue.value.dataList"); |
| | | |
| | | normalizeTreeData(bomDataValue.value.dataList); |
| | | |
| | | const valid = validateAllBom(); |
| | | if (valid) { |
| | | addBomDetail({ |
| | | bomId: routeInfo.value.bomId, |
| | | add2({ |
| | | // bomId: Number(routeInfo.value.bomId), |
| | | productionOrderBomId: Number(routeInfo.value.bomId) || null, |
| | | children: buildSubmitTree(bomDataValue.value.dataList || []), |
| | | }) |
| | | .then(() => { |