| src/api/qualityManagement/productInspectionRecord.js | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/views/productionManagement/productionOrder/Detail/index.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/views/productionManagement/workOrder/index.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/views/qualityManagement/productInspectionRecord/components/formDia.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/views/qualityManagement/productInspectionRecord/index.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
src/api/qualityManagement/productInspectionRecord.js
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,54 @@ import request from '@/utils/request' // å·¡æ£è®°å½ å页æ¥è¯¢ export function productInspectionRecordListPage(query) { return request({ url: '/productInspectionRecord/listPage', method: 'get', params: query, }) } // å·¡æ£è®°å½ æ°å¢ export function addProductInspectionRecord(data) { return request({ url: '/productInspectionRecord/addProductInspectionRecord', method: 'post', data: data, }) } // å·¡æ£è®°å½ ä¿®æ¹ export function updProductInspectionRecord(data) { return request({ url: '/productInspectionRecord/updProductInspectionRecord', method: 'put', data: data, }) } // å·¡æ£è®°å½ å é¤ export function delProductInspectionRecord(ids) { return request({ url: `/productInspectionRecord/${ids}`, method: 'delete', }) } // å·¡æ£è®°å½ éç¥ export function notifyProductInspectionRecord(ids) { return request({ url: '/productInspectionRecord/notify', method: 'post', data: ids, }) } // æ ¹æ®å·¥åºåæ£éªç±»åè·åæ£æµé¡¹ç® export function getParameterItemByProcessOrCategory(params) { return request({ url: '/qualityTestStandard/getParameterItemByProcessOrCategory', method: 'get', params: params, }) } src/views/productionManagement/productionOrder/Detail/index.vue
@@ -120,12 +120,12 @@ <div v-else class="right-content"> <el-table :data="reports" border height="420" v-loading="reportLoading"> <el-table-column label="åºå·" type="index" width="60" align="center" /> <el-table-column label="æ¥å·¥åå·" prop="reportNo" min-width="140" show-overflow-tooltip /> <el-table-column label="æ¥å·¥äººå" prop="reportUser" min-width="120" show-overflow-tooltip /> <el-table-column label="æ¥å·¥æ¶é´" prop="reportTime" min-width="160" show-overflow-tooltip /> <el-table-column label="äº§åºæ°é" prop="outputQty" min-width="110" /> <el-table-column label="æ¥å·¥åå·" prop="productNo" min-width="140" show-overflow-tooltip /> <el-table-column label="æ¥å·¥äººå" prop="nickName" min-width="120" show-overflow-tooltip /> <el-table-column label="æ¥å·¥æ¶é´" prop="createTime" min-width="160" show-overflow-tooltip /> <el-table-column label="äº§åºæ°é" prop="quantity" min-width="110" /> <el-table-column label="åæ ¼æ°é" prop="qualifiedQty" min-width="110" /> <el-table-column label="ä¸è¯æ°é" prop="badQty" min-width="110" /> <el-table-column label="ä¸è¯æ°é" prop="scrapQty" min-width="110" /> <el-table-column label="ä¸åæ ¼å¤ç" prop="dealResult" min-width="160" show-overflow-tooltip /> <el-table-column label="æä½" width="150" fixed="right"> <template #default="{ row }"> @@ -140,21 +140,45 @@ </div> </div> </el-card> <el-dialog v-model="reportRecordDialogVisible" title="æ¥å·¥ç产记å½" width="680px" destroy-on-close > <div class="report-record-placeholder"> <div>æ¥å·¥åå·ï¼{{ currentReportRow?.reportNo || "-" }}</div> <div>å·¥åºï¼{{ selectedProcess?.processName || "-" }}</div> <div class="placeholder-tip">å¼¹æ¡å å®¹å¾ å®ï¼åç»è¡¥å 详ç»ç产记å½ï¼ã</div> </div> <template #footer> <el-button @click="reportRecordDialogVisible = false">å ³é</el-button> </template> </el-dialog> <!-- <el-dialog--> <!-- v-model="reportRecordDialogVisible"--> <!-- title="æ¥å·¥ç产记å½"--> <!-- width="680px"--> <!-- destroy-on-close--> <!-- >--> <!-- <div class="report-record-placeholder">--> <!-- <div>æ¥å·¥åå·ï¼{{ currentReportRow?.reportNo || "-" }}</div>--> <!-- <div>å·¥åºï¼{{ selectedProcess?.processName || "-" }}</div>--> <!-- <div class="placeholder-tip">å¼¹æ¡å å®¹å¾ å®ï¼åç»è¡¥å 详ç»ç产记å½ï¼ã</div>--> <!-- </div>--> <!-- <template #footer>--> <!-- <el-button @click="reportRecordDialogVisible = false">å ³é</el-button>--> <!-- </template>--> <!-- </el-dialog>--> <CopperPrintingForm v-if="copperPrintingFormVisible" v-model:isShow="copperPrintingFormVisible" :isEdit="false" :row="currentReportRow" @refreshData="fetchReportsForProcess(selectedProcess.value)"/> <VoltageSortingForm v-if="voltageSortingFormVisible" v-model:isShow="voltageSortingFormVisible" :isEdit="false" :row="currentReportRow" @refreshData="fetchReportsForProcess(selectedProcess.value)"/> <GranulationForm v-if="granulationFormVisible" v-model:isShow="granulationFormVisible" :isEdit="false" :row="currentReportRow" @refreshData="fetchReportsForProcess(selectedProcess.value)"/> <Detail v-if="reportRecordDialogVisible" v-model:isShow="reportRecordDialogVisible" @refreshData="fetchReportsForProcess(selectedProcess.value)" :row="currentReportRow"/> </div> </template> @@ -163,7 +187,10 @@ import { useRoute } from "vue-router"; import { getByProductOrderId } from "@/api/productionManagement/workOrder.js"; import { getByProductWorkOrderId } from "@/api/productionManagement/productionProductMain.js"; const VoltageSortingForm = defineAsyncComponent(() => import("@/views/productionManagement/workOrder/components/VoltageSortingForm.vue")); const CopperPrintingForm = defineAsyncComponent(() => import("@/views/productionManagement/workOrder/components/CopperPrintingForm.vue")); const GranulationForm = defineAsyncComponent(() => import("@/views/productionManagement/workOrder/components/GranulationForm.vue")); const Detail = defineAsyncComponent(() => import("@/views/productionManagement/productionReporting/components/Detail.vue")); const route = useRoute(); const header = computed(() => ({ @@ -176,6 +203,10 @@ // å·¥åºæ°æ®ï¼æ¥å£æ¿æ¢ï¼ const processes = ref([]); const copperPrintingFormVisible = ref(false); const voltageSortingFormVisible = ref(false); const granulationFormVisible = ref(false); const normalizeStatus = (statusText, completionStatus, inputQty, outputQty) => { const s = statusText === null || statusText === undefined ? "" : String(statusText).trim(); @@ -271,19 +302,11 @@ const reportLoading = ref(false); const normalizeReport = (item) => { // æ¥å·¥è®°å½ï¼productNo/userName/createTime/quantity/qualifiedQty/scrapQty const outputQty = Number(item?.quantity ?? item?.outputQty ?? 0); const qualifiedQty = Number(item?.qualifiedQty ?? item?.completeQty ?? item?.goodQty ?? 0); const badQty = Number(item?.scrapQty ?? item?.badQty ?? 0); return { reportNo: item?.productNo ?? item?.reportNo ?? item?.productionReportNo ?? item?.id ?? "", reportUser: item?.userName ?? item?.reportUser ?? item?.createdByName ?? item?.reportUserName ?? "", reportTime: item?.createTime ?? item?.reportTime ?? item?.createdAt ?? item?.reportDate ?? "", outputQty: Number.isFinite(outputQty) ? outputQty : 0, qualifiedQty: Math.max(0, Number.isFinite(qualifiedQty) ? qualifiedQty : 0), badQty: Number.isFinite(badQty) ? Math.max(0, badQty) : 0, dealResult: item?.dealResult ?? item?.dealResultText ?? item?.description ?? "", ...item, quantity: Math.max(0, Number.isFinite(item.quantity) ? item.quantity : 0), scrapQty: Math.max(0, Number.isFinite(item.scrapQty) ? item.scrapQty : 0), qualifiedQty: Math.max(0, Number.isFinite(item.qualifiedQty) ? item.qualifiedQty : 0), }; }; @@ -323,9 +346,17 @@ ); const viewReportRecord = (row) => { if (!row?.reportNo) return; if (!row?.productNo) return; currentReportRow.value = row; reportRecordDialogVisible.value = true; if (row.process ==='å°é' || row.process ==='å°é¶') { copperPrintingFormVisible.value = true; } else if (row.process === 'çµååé') { voltageSortingFormVisible.value = true; } else if (row.process === 'é ç²') { granulationFormVisible.value = true; } else { reportRecordDialogVisible.value = true; } }; const reportRecordDialogVisible = ref(false); src/views/productionManagement/workOrder/index.vue
@@ -709,7 +709,7 @@ const handleReport = async () => { const data = await productionRecordFormRef.value.submitData() reportForm.otherData.rows = JSON.stringify(data || {}); reportForm.otherData.rows = data || []; reportFormRef.value?.validate((valid) => { if (!valid) { return false; @@ -761,7 +761,8 @@ const submitData = { ...reportForm, quantity: quantity, scrapQty: scrapQty scrapQty: scrapQty, otherData: JSON.stringify(reportForm.otherData) }; // console.log(submitData); src/views/qualityManagement/productInspectionRecord/components/formDia.vue
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,301 @@ <template> <el-dialog v-model="dialogFormVisible" :title="operationType === 'add' ? 'æ°å¢å·¡æ£è®°å½' : 'ç¼è¾å·¡æ£è®°å½'" width="700px" @close="closeDia" > <el-form :model="form" label-width="140px" label-position="top" :rules="rules" ref="formRef"> <el-row :gutter="20"> <el-col :span="12"> <el-form-item label="å·¥åºï¼" prop="processId"> <el-select v-model="form.processId" placeholder="è¯·éæ©å·¥åº" clearable @change="handleProcessChange" style="width: 100%"> <el-option v-for="item in processList" :key="item.id" :label="item.processName || item.name" :value="item.id" /> </el-select> </el-form-item> </el-col> <el-col :span="12"> <el-form-item label="å·¡æ£æ¶é´ï¼" prop="inspectionTime"> <el-date-picker v-model="form.inspectionTime" value-format="YYYY-MM-DD HH:mm:ss" format="YYYY-MM-DD HH:mm:ss" type="datetime" placeholder="è¯·éæ©å·¡æ£æ¶é´" style="width: 100%" /> </el-form-item> </el-col> </el-row> <el-row :gutter="20"> <el-col :span="12"> <el-form-item label="å·¡æ£åï¼" prop="inspector"> <el-input v-model="form.inspector" placeholder="请è¾å ¥å·¡æ£å" /> </el-form-item> </el-col> <el-col :span="12"> <el-form-item label="æ£æµé¡¹ï¼" prop="inspectionItem"> <el-select v-model="form.inspectionItem" placeholder="è¯·éæ©æ£æµé¡¹" clearable @change="handleInspectionItemChange" style="width: 100%"> <el-option v-for="item in inspectionItemList" :key="item.parameterItem" :label="item.parameterItem" :value="item.parameterItem" /> </el-select> </el-form-item> </el-col> </el-row> <el-row :gutter="20"> <el-col :span="12"> <el-form-item label="æ åè¦æ±ï¼" prop="standardRequirement"> <el-input v-model="form.standardRequirement" placeholder="æ åè¦æ±" readonly /> </el-form-item> </el-col> <el-col :span="12"> <el-form-item label="宿µå¼ï¼" prop="actualValue"> <el-input v-model="form.actualValue" placeholder="请è¾å ¥å®æµå¼" /> </el-form-item> </el-col> </el-row> <el-row :gutter="20"> <el-col :span="12"> <el-form-item label="å¤å®ï¼" prop="judgement"> <el-select v-model="form.judgement" placeholder="è¯·éæ©" clearable style="width: 100%"> <el-option label="åæ ¼" value="yes" /> <el-option label="ä¸åæ ¼" value="no" /> </el-select> </el-form-item> </el-col> <el-col :span="12"> <el-form-item label="ä¸åæ ¼è®¢åï¼" prop="unqualifiedOrder"> <el-input v-model="form.unqualifiedOrder" placeholder="请è¾å ¥ä¸åæ ¼è®¢å" /> </el-form-item> </el-col> </el-row> <el-row :gutter="20"> <el-col :span="24"> <el-form-item label="夿³¨ï¼" prop="remark"> <el-input v-model="form.remark" type="textarea" :rows="3" placeholder="请è¾å ¥å¤æ³¨" /> </el-form-item> </el-col> </el-row> </el-form> <template #footer> <div class="dialog-footer"> <el-button type="primary" @click="submitForm">确认</el-button> <el-button @click="closeDia">åæ¶</el-button> </div> </template> </el-dialog> </template> <script setup> import { ref, reactive } from "vue"; import { ElMessage } from "element-plus"; import { addProductInspectionRecord, updProductInspectionRecord, getParameterItemByProcessOrCategory } from "@/api/qualityManagement/productInspectionRecord.js"; import { processList as getProcessList } from "@/api/productionManagement/productionProcess.js"; import useUserStore from "@/store/modules/user"; const userStore = useUserStore(); const dialogFormVisible = ref(false); const operationType = ref("add"); const formRef = ref(null); const form = reactive({ id: undefined, processId: undefined, process: "", checkDate: undefined, inspector: "", inspectionTime: undefined, inspectionItem: "", standardRequirement: "", actualValue: "", judgement: "", unqualifiedOrder: "", remark: "", createUser: "", createTime: undefined, }); const processList = ref([]); const inspectionItemList = ref([]); /** å·¥åº id ä¸å端å¯è½ä¸º number/stringï¼ç»ä¸æ¯è¾ */ const sameProcessId = (a, b) => a != null && b != null && String(a) === String(b); /** ä»å·¥åºå表åä¸ row å¹é ç idï¼ä¿è¯ä¸ el-option ç value ç±»åä¸è´ï¼é¿å åæ¾æçº¯æ°åï¼ */ const resolveProcessIdFromRow = (row) => { let pid = row.processId ?? row.process_id; if (pid != null && pid !== "") { const hit = processList.value.find((item) => sameProcessId(item.id, pid)); return hit ? hit.id : pid; } // é¨åæ¥å£æå·¥åº id åå¨ process åæ®µé const p = row.process; if (p != null && p !== "" && /^\d+$/.test(String(p).trim())) { const hit = processList.value.find((item) => sameProcessId(item.id, p)); return hit ? hit.id : p; } return undefined; }; const getProcessLabel = (item) => item?.processName || item?.name || ""; const rules = { processId: [{ required: true, message: "è¯·éæ©å·¥åº", trigger: "change" }], checkDate: [{ required: true, message: "è¯·éæ©å·¡æ£æ¥æ", trigger: "change" }], }; const loadProcessList = async () => { try { const res = await getProcessList({ current: 1, size: 1000 }); processList.value = res.data || []; } catch (error) { console.error("å 载工åºå表失败", error); } }; /** * @param processId å·¥åº id * @param options.preserveInspection 为 true æ¶ä¿çå·²ææ£æµé¡¹/æ åï¼ç¼è¾åæ¾ï¼ */ const handleProcessChange = async (processId, options = {}) => { const { preserveInspection = false } = options; if (!preserveInspection) { form.process = ""; form.inspectionItem = ""; form.standardRequirement = ""; } inspectionItemList.value = []; if (!processId) { return; } const process = processList.value.find((item) => sameProcessId(item.id, processId)); if (process) { form.process = getProcessLabel(process); } try { const { data } = await getParameterItemByProcessOrCategory({ id: processId, inspectType: 3, }); if (data && data.length > 0) { inspectionItemList.value = data; if (preserveInspection && form.inspectionItem) { const cur = data.find((i) => i.parameterItem === form.inspectionItem); form.standardRequirement = cur?.standardValue ?? form.standardRequirement ?? ""; } else { const firstItem = data[0]; form.inspectionItem = firstItem.parameterItem; form.standardRequirement = firstItem.standardValue || ""; } } } catch (error) { console.error("å è½½æ£æµé¡¹ç®å¤±è´¥", error); } }; const handleInspectionItemChange = (val) => { if (!val) { form.standardRequirement = ""; return; } const item = inspectionItemList.value.find(i => i.parameterItem === val); if (item) { form.standardRequirement = item.standardValue || ""; } }; const open = async (type, row) => { operationType.value = type; await loadProcessList(); if (type === "edit" && row) { Object.assign(form, row); const resolvedId = resolveProcessIdFromRow(row); if (resolvedId != null && resolvedId !== "") { form.processId = resolvedId; const processItem = processList.value.find((item) => sameProcessId(item.id, resolvedId)); if (processItem) { form.process = getProcessLabel(processItem); } else if (row.process && !/^\d+$/.test(String(row.process).trim())) { form.process = row.process; } } if (form.processId != null && form.processId !== "") { await handleProcessChange(form.processId, { preserveInspection: true }); } } else { resetForm(); } dialogFormVisible.value = true; }; const formatDateTime = () => { const now = new Date(); const year = now.getFullYear(); const month = String(now.getMonth() + 1).padStart(2, '0'); const day = String(now.getDate()).padStart(2, '0'); const hours = String(now.getHours()).padStart(2, '0'); const minutes = String(now.getMinutes()).padStart(2, '0'); const seconds = String(now.getSeconds()).padStart(2, '0'); return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`; }; const resetForm = () => { form.id = undefined; form.processId = undefined; form.process = ""; form.checkDate = undefined; form.inspector = ""; form.inspectionTime = formatDateTime(); form.inspectionItem = ""; form.standardRequirement = ""; form.actualValue = ""; form.judgement = ""; form.unqualifiedOrder = ""; form.remark = ""; form.createUser = ""; form.createTime = undefined; inspectionItemList.value = []; }; const closeDia = () => { dialogFormVisible.value = false; resetForm(); }; const submitForm = async () => { const valid = await formRef.value.validate().catch(() => false); if (!valid) return; const p = processList.value.find((item) => sameProcessId(item.id, form.processId)); form.process = getProcessLabel(p); try { if (operationType.value === "add") { await addProductInspectionRecord(form); ElMessage.success("æ°å¢æå"); } else { await updProductInspectionRecord(form); ElMessage.success("ä¿®æ¹æå"); } closeDia(); emit("close"); } catch (error) { console.error(error); } }; const emit = defineEmits(["close"]); defineExpose({ open, }); </script> <style scoped> </style> src/views/qualityManagement/productInspectionRecord/index.vue
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,258 @@ <template> <div class="app-container"> <div class="search_form"> <div> <span class="search_title">å·¥åºï¼</span> <el-input v-model="searchForm.process" style="width: 240px" placeholder="请è¾å ¥å·¥åºæç´¢" @change="handleQuery" clearable /> <span style="margin-left: 10px" class="search_title">å·¡æ£æ¥æï¼</span> <el-date-picker v-model="searchForm.checkDate" value-format="YYYY-MM-DD HH:mm:ss" format="YYYY-MM-DD HH:mm:ss" type="datetimerange" placeholder="è¯·éæ©" clearable @change="changeDaterange" /> <el-button type="primary" @click="handleQuery" style="margin-left: 10px" >æç´¢</el-button > </div> <div> <el-button type="primary" @click="openForm('add')">æ°å¢</el-button> <el-button type="danger" plain @click="handleDelete">å é¤</el-button> <el-button type="success" plain @click="handleNotify">éç¥</el-button> </div> </div> <div class="table_list"> <PIMTable rowKey="id" :column="tableColumn" :tableData="tableData" :page="page" :isSelection="true" @selection-change="handleSelectionChange" :tableLoading="tableLoading" @pagination="pagination" :total="page.total" ></PIMTable> </div> <FormDia ref="formDia" @close="handleQuery"></FormDia> </div> </template> <script setup> import { onMounted, ref, reactive, toRefs } from "vue"; import FormDia from "./components/formDia.vue"; import {ElMessage, ElMessageBox} from "element-plus"; import { productInspectionRecordListPage, delProductInspectionRecord, notifyProductInspectionRecord } from "@/api/qualityManagement/productInspectionRecord.js"; const data = reactive({ searchForm: { keyword: "", checkDate: undefined, checkDateStart: undefined, checkDateEnd: undefined, }, }); const { searchForm } = toRefs(data); const tableData = ref([]); const tableLoading = ref(false); const page = reactive({ current: 1, size: 10, total: 0, }); const ids = ref([]); const tableColumn = ref([ { label: "å·¥åº", prop: "process", }, { label: "æ£æµé¡¹", prop: "inspectionItem", }, { label: "æ åè¦æ±", prop: "standardRequirement", }, { label: "宿µå¼", prop: "actualValue", }, { label: "å¤å®", prop: "judgement", dataType: "tag", formatData: (params) => { if (params === 'yes') { return "åæ ¼"; } else if (params === 'no') { return "ä¸åæ ¼"; } return params; }, formatType: (params) => { if (params === 'yes') { return "success"; } else if (params === 'no') { return "danger"; } return null; }, }, { label: "ä¸åæ ¼è®¢å", prop: "unqualifiedOrder", }, { label: "å·¡æ£æ¥æ", prop: "inspectionTime", width: 160 }, { label: "å·¡æ£å", prop: "inspector", }, { label: "å建人", prop: "createUser", }, { label: "å建æ¶é´", prop: "createTime", width: 160 }, { dataType: "action", label: "æä½", align: "center", fixed: "right", width: 150, operation: [ { name: "ç¼è¾", type: "text", clickFun: (row) => { openForm("edit", row); }, }, { name: "å é¤", type: "text", clickFun: (row) => { handleDelete(row); }, }, ], }, ]); const formDia = ref(null); const openForm = (type, row) => { formDia.value.open(type, row); }; const changeDaterange = (val) => { if (val) { searchForm.value.startTime = val[0]; searchForm.value.endTime = val[1]; } else { searchForm.value.startTime = undefined; searchForm.value.endTime = undefined; } handleQuery(); }; const handleQuery = () => { page.current = 1; getList(); }; const pagination = (obj) => { page.current = obj.page; page.size = obj.limit; getList(); }; const getList = async () => { tableLoading.value = true; try { const res = await productInspectionRecordListPage({ ...searchForm.value, current: page.current, size: page.size, }); tableData.value = res.data.records || []; page.total = res.data.total || 0; } finally { tableLoading.value = false; } }; const handleSelectionChange = (selection) => { ids.value = selection.map((item) => item.id); }; const handleDelete = (row) => { const _ids = row ? [row.id] : ids.value; if (_ids.length === 0) { ElMessage.warning("è¯·éæ©è¦å é¤çæ°æ®"); return; } ElMessageBox.confirm("æ¯å¦ç¡®è®¤å é¤éä¸çæ°æ®ï¼", "è¦å", { confirmButtonText: "ç¡®å®", cancelButtonText: "åæ¶", type: "warning", }).then(async () => { await delProductInspectionRecord(_ids); ElMessage.success("å 餿å"); getList(); }); }; const handleNotify = () => { if (ids.value.length === 0) { ElMessage.warning("è¯·éæ©è¦éç¥çæ°æ®"); return; } ElMessageBox.confirm("æ¯å¦ç¡®è®¤åééç¥ï¼", "è¦å", { confirmButtonText: "ç¡®å®", cancelButtonText: "åæ¶", type: "warning", }).then(async () => { await notifyProductInspectionRecord(ids.value); ElMessage.success("åééç¥æå"); }) }; onMounted(() => { getList(); }); </script> <style scoped lang="scss"> .search_form { display: flex; justify-content: space-between; align-items: center; margin-bottom: 16px; } .search_title { font-size: 14px; color: #606266; } </style>