| | |
| | | v-model:visible="isShowNewModal" |
| | | type="qualified" |
| | | @completed="handleQuery" /> |
| | | |
| | | <!-- æ¥çæå
¥å¼¹æ¡ --> |
| | | <el-dialog v-model="inputDialogVisible" |
| | | title="æå
¥" |
| | | width="1000px"> |
| | | <PIMTable |
| | | rowKey="id" |
| | | :column="inputTableColumn" |
| | | :tableData="inputTableData" |
| | | :page="inputPage" |
| | | :tableLoading="inputTableLoading" |
| | | @pagination="handleInputPagination" |
| | | /> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button type="primary" @click="inputDialogVisible = false">å
³é</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | |
| | | <!-- é¢æå¼¹æ¡ --> |
| | | <el-dialog v-model="pickingDialogVisible" |
| | | title="å·¥å颿" |
| | | width="1200px" |
| | | :close-on-click-modal="false"> |
| | | |
| | | <el-table |
| | | :data="pickingTableData" |
| | | border |
| | | size="small" |
| | | @selection-change="handlePickingSelectionChange" |
| | | :header-cell-style="{ background: '#f5f7fa' }" |
| | | show-summary |
| | | :summary-method="summarizePickingTable" |
| | | > |
| | | <el-table-column type="selection" width="50" align="center" /> |
| | | <el-table-column label="产ååç§°" prop="productName" min-width="120" /> |
| | | <el-table-column label="å¾çº¸ç¼å·" prop="model" min-width="100" /> |
| | | <el-table-column label="åä½ç¨é" prop="unitQuantity" min-width="100" align="center" /> |
| | | <el-table-column label="åä½" prop="unit" min-width="100" align="center" /> |
| | | <el-table-column label="éæ±æ°é" prop="demandedQuantity" min-width="100" align="center" /> |
| | | <el-table-column label="已颿æ°é" prop="completedQuantity" min-width="100" align="center" /> |
| | | <el-table-column label="æªé¢ææ°é" prop="unpickedQuantity" min-width="100" align="center" /> |
| | | <el-table-column label="颿æ°é" min-width="180" align="center" prop="quantity"> |
| | | <template #default="{ row }"> |
| | | <el-input-number |
| | | v-model="row.quantity" |
| | | :min="0" |
| | | :max="row.unpickedQuantity" |
| | | :precision="0" |
| | | size="small" |
| | | style="width: 160px" |
| | | @change="(val) => handlePickingQuantityChange(val, row)" |
| | | /> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | <div class="picking-footer-info"> |
| | | <span>å·²é {{ pickingSelectedRows.length }} æ¡</span> |
| | | <span>{{ pickingTableData.length }} æ¡è®°å½</span> |
| | | </div> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button type="success" @click="handlePickingNext">确认</el-button> |
| | | <el-button @click="pickingDialogVisible = false">åæ¶</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { onMounted, ref } from "vue"; |
| | | import { onMounted, ref, computed } from "vue"; |
| | | import { ElMessageBox } from "element-plus"; |
| | | import { Setting } from '@element-plus/icons-vue'; |
| | | import dayjs from "dayjs"; |
| | | import { useRouter } from "vue-router"; |
| | | import { |
| | |
| | | listProcessBom, delProductOrder, startOrPause, |
| | | } from "@/api/productionManagement/productionOrder.js"; |
| | | import { listMain as getOrderProcessRouteMain } from "@/api/productionManagement/productProcessRoute.js"; |
| | | import { productionProductInputListPage } from "@/api/productionManagement/productionProductInput.js"; |
| | | import { listPage as listProductStructureRecord, pick as pickMaterial } from "@/api/productionManagement/productStructureRecord.js"; |
| | | |
| | | import {fileDel} from "@/api/financialManagement/revenueManagement.js"; |
| | | import PIMTable from "@/components/PIMTable/PIMTable.vue"; |
| | | const NewProductOrder = defineAsyncComponent(() => import("@/views/productionManagement/productionOrder/New.vue")); |
| | |
| | | label: "æä½", |
| | | align: "center", |
| | | fixed: "right", |
| | | width: 240, |
| | | width: 360, |
| | | operation: [ |
| | | { |
| | | name: "å¼å§", |
| | | type: "text", |
| | | type: "success", |
| | | showHide: row => row.status === 'å¾
ç产', |
| | | clickFun: row => { |
| | | handleStartOrPause(row); |
| | |
| | | }, |
| | | { |
| | | name: "æå", |
| | | type: "text", |
| | | type: "danger", |
| | | showHide: row => row.status === 'ç产ä¸', |
| | | clickFun: row => { |
| | | handleStartOrPause(row); |
| | | }, |
| | | }, |
| | | { |
| | | name: "颿", |
| | | type: "success", |
| | | clickFun: row => { |
| | | showPickingDialog(row); |
| | | }, |
| | | }, |
| | | { |
| | |
| | | showProductStructure(row); |
| | | }, |
| | | }, |
| | | { |
| | | name: "æ¥çæå
¥", |
| | | type: "text", |
| | | clickFun: row => { |
| | | showInputDialog(row); |
| | | }, |
| | | }, |
| | | ], |
| | | }, |
| | | ]); |
| | |
| | | total: 0, |
| | | }); |
| | | const selectedRows = ref([]); |
| | | |
| | | // æ¥çæå
¥ç¸å
³ |
| | | const inputDialogVisible = ref(false); |
| | | const inputTableData = ref([]); |
| | | const inputTableLoading = ref(false); |
| | | const inputCurrentRow = ref(null); |
| | | const inputPage = reactive({ |
| | | current: 1, |
| | | size: 100, |
| | | total: 0, |
| | | }); |
| | | const inputTableColumn = ref([ |
| | | { |
| | | label: 'æå
¥äº§ååç§°', |
| | | prop: 'productName', |
| | | }, |
| | | { |
| | | label: 'å¾çº¸ç¼å·', |
| | | prop: 'model' |
| | | }, |
| | | { |
| | | label: 'æå
¥æ°é', |
| | | prop: 'quantity', |
| | | }, |
| | | { |
| | | label: 'åä½', |
| | | prop: 'unit', |
| | | }, |
| | | ]); |
| | | |
| | | // 颿ç¸å
³ |
| | | const pickingDialogVisible = ref(false); |
| | | const pickingTableData = ref([]); |
| | | const pickingSelectedRows = ref([]); |
| | | const pickingForm = reactive({ |
| | | orderId: null, |
| | | }); |
| | | |
| | | const data = reactive({ |
| | | searchForm: { |
| | |
| | | |
| | | const handleConfirmRoute = () => {}; |
| | | |
| | | // æ¾ç¤ºæ¥çæå
¥å¼¹æ¡ |
| | | const showInputDialog = (row) => { |
| | | inputCurrentRow.value = row; |
| | | inputDialogVisible.value = true; |
| | | inputPage.current = 1; |
| | | inputPage.total = 0; |
| | | fetchInputData(); |
| | | }; |
| | | |
| | | // æ¥çæå
¥å页 |
| | | const handleInputPagination = (obj) => { |
| | | inputPage.current = obj.page; |
| | | inputPage.size = obj.limit; |
| | | fetchInputData(); |
| | | }; |
| | | |
| | | // è·åæå
¥æ°æ® |
| | | const fetchInputData = () => { |
| | | inputTableLoading.value = true; |
| | | const params = { productOrderId: inputCurrentRow.value.id, ...inputPage }; |
| | | productionProductInputListPage(params) |
| | | .then(res => { |
| | | inputTableLoading.value = false; |
| | | inputTableData.value = res.data.records; |
| | | inputPage.total = res.data.total; |
| | | }) |
| | | .catch(err => { |
| | | inputTableLoading.value = false; |
| | | console.error("è·åæå
¥æ°æ®å¤±è´¥ï¼", err); |
| | | }); |
| | | }; |
| | | |
| | | // æ¾ç¤ºé¢æå¼¹æ¡ |
| | | const showPickingDialog = async (row) => { |
| | | pickingForm.orderId = row.id; |
| | | pickingDialogVisible.value = true; |
| | | pickingTableData.value = []; |
| | | |
| | | // è·åç©ææ¸
åæ°æ® |
| | | try { |
| | | const res = await listProductStructureRecord({ productOrderId: row.id }); |
| | | const materials = res.data?.records || []; |
| | | pickingTableData.value = materials.map(item => ({ |
| | | ...item, |
| | | quantity: 0, |
| | | unpickedQuantity: (item.demandedQuantity || 0) - (item.pickedQuantity || 0), |
| | | })); |
| | | } catch (e) { |
| | | console.error("è·åç©ææ¸
å失败ï¼", e); |
| | | proxy.$modal.msgError("è·åç©ææ¸
å失败"); |
| | | } |
| | | }; |
| | | |
| | | // é¢æè¡¨æ ¼éæ©åå |
| | | const handlePickingSelectionChange = (selection) => { |
| | | pickingSelectedRows.value = selection; |
| | | }; |
| | | |
| | | // 颿æ°éååå¤ç |
| | | const handlePickingQuantityChange = (val, row) => { |
| | | if (val > row.unpickedQuantity) { |
| | | proxy.$modal.msgWarning("颿æ°éä¸è½è¶
è¿æªé¢ææ°é"); |
| | | row.quantity = row.unpickedQuantity; |
| | | } |
| | | }; |
| | | |
| | | // ç¡®è®¤é¢æ |
| | | const handlePickingNext = async () => { |
| | | if (pickingSelectedRows.value.length === 0) { |
| | | proxy.$modal.msgWarning("è¯·éæ©è¦é¢æçç©æ"); |
| | | return; |
| | | } |
| | | // æ ¡éªé¢ææ°é |
| | | for (const row of pickingSelectedRows.value) { |
| | | if (row.quantity > row.unpickedQuantity) { |
| | | proxy.$modal.msgWarning(`${row.productName} ç颿æ°éä¸è½è¶
è¿æªé¢ææ°é`); |
| | | return; |
| | | } |
| | | if (row.quantity <= 0) { |
| | | proxy.$modal.msgWarning(`${row.productName} ç颿æ°éå¿
须大äº0`); |
| | | return; |
| | | } |
| | | } |
| | | |
| | | // æäº¤é¢ææ°æ® |
| | | try { |
| | | const pickData = pickingSelectedRows.value.map(row => ({ |
| | | productOrderId: row.productOrderId, |
| | | productStructureRecordId: row.id, |
| | | productModelId: row.productModelId, |
| | | quantity: row.quantity, |
| | | })); |
| | | await pickMaterial(pickData); |
| | | proxy.$modal.msgSuccess("颿æå"); |
| | | pickingDialogVisible.value = false; |
| | | } catch (e) { |
| | | console.error("é¢æå¤±è´¥ï¼", e); |
| | | proxy.$modal.msgError("é¢æå¤±è´¥"); |
| | | } |
| | | }; |
| | | |
| | | // é¢æè¡¨æ ¼åè®¡æ¹æ³ |
| | | const summarizePickingTable = (param) => { |
| | | return proxy.summarizeTable(param, [ |
| | | "quantity", |
| | | "unpickedQuantity", |
| | | "inventoryQuantity", |
| | | "demandedQuantity", |
| | | ]); |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | getList(); |
| | | }); |
| | |
| | | :deep(.purple){ |
| | | background-color: #F4DEFA; |
| | | } |
| | | |
| | | .picking-footer-info { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | padding: 10px; |
| | | font-size: 14px; |
| | | color: #606266; |
| | | } |
| | | |
| | | </style> |