From 3a63dff0d98c148c6b915cd762a50ed87aa6c3a5 Mon Sep 17 00:00:00 2001
From: liding <756868258@qq.com>
Date: 星期四, 26 三月 2026 11:20:55 +0800
Subject: [PATCH] feat:1.生产订单增加清场记录弹框
---
src/views/productionManagement/productionOrder/ClearanceRecordDialog.vue | 400 ++++++++++++++++++++++++++++++++++++++++++++++++++
src/views/productionManagement/productionOrder/index.vue | 47 +++++
src/api/productionManagement/productionOrder.js | 9 +
3 files changed, 456 insertions(+), 0 deletions(-)
diff --git a/src/api/productionManagement/productionOrder.js b/src/api/productionManagement/productionOrder.js
index 9441544..72cdb10 100644
--- a/src/api/productionManagement/productionOrder.js
+++ b/src/api/productionManagement/productionOrder.js
@@ -136,4 +136,13 @@
url: `/productOrder/${id}`,
method: "patch",
});
+}
+
+// 淇濆瓨娓呭満璁板綍
+export function saveCleanRecord(id, data) {
+ return request({
+ url: `/productOrder/cleanRecord/${id}`,
+ method: "patch",
+ data: data,
+ });
}
\ No newline at end of file
diff --git a/src/views/productionManagement/productionOrder/ClearanceRecordDialog.vue b/src/views/productionManagement/productionOrder/ClearanceRecordDialog.vue
new file mode 100644
index 0000000..0b8d3af
--- /dev/null
+++ b/src/views/productionManagement/productionOrder/ClearanceRecordDialog.vue
@@ -0,0 +1,400 @@
+<template>
+ <el-dialog
+ v-model="visible"
+ title="娓呭満璁板綍"
+ width="900px"
+ :close-on-click-modal="false"
+ destroy-on-close
+ >
+ <div class="clearance-record-form">
+ <!-- 鍩烘湰淇℃伅鍖哄煙 -->
+ <div class="basic-info">
+ <table class="info-table">
+ <tr>
+ <td class="label">浜у搧鍚嶇О</td>
+ <td class="value" colspan="3">{{ formData.productName }}</td>
+ <td class="label">鐢熶骇鏃ユ湡</td>
+ <td class="value">{{ formData.productionDate }}</td>
+ </tr>
+ <tr>
+ <td class="label">瑙勬牸</td>
+ <td class="value">{{ formData.spec }}</td>
+ <td class="label">鎵瑰彿</td>
+ <td class="value">{{ formData.batchNo }}</td>
+ <td class="label">鐢熶骇杞﹂棿</td>
+ <td class="value">{{ formData.workshop }}</td>
+ </tr>
+ </table>
+ </div>
+
+ <!-- 娓呭満妫�鏌ラ」鐩〃鏍� -->
+ <div class="check-items-section">
+ <table class="check-table">
+ <thead>
+ <tr>
+ <th class="item-no">搴忓彿</th>
+ <th class="content">娓呭満鍐呭鍙婅姹�</th>
+ <th class="result" colspan="2">妫�鏌ョ粨鏋�</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr v-for="(item, index) in formData.checkItems" :key="index">
+ <td class="item-no">{{ item.itemNo }}</td>
+ <td class="content">{{ item.content }}</td>
+ <td class="result-option">
+ <el-radio-group v-model="item.result">
+ <el-radio label="绗﹀悎瑙勫畾">绗﹀悎瑙勫畾</el-radio>
+ </el-radio-group>
+ </td>
+ <td class="result-option">
+ <el-radio-group v-model="item.result">
+ <el-radio label="涓嶇鍚堣瀹�">涓嶇鍚堣瀹�</el-radio>
+ </el-radio-group>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+
+ <!-- 绛惧悕鍖哄煙 -->
+ <div class="signature-section">
+ <table class="signature-table">
+ <tr>
+ <td class="label">娓呭満浜�</td>
+ <td class="value">
+ <el-input v-model="formData.cleaner" placeholder="璇疯緭鍏ユ竻鍦轰汉" clearable />
+ </td>
+ <td class="label">鏃ユ湡</td>
+ <td class="value">
+ <el-date-picker
+ v-model="formData.cleanDate"
+ type="datetime"
+ placeholder="閫夋嫨鏃ユ湡鏃堕棿"
+ format="YYYY-MM-DD HH:mm:ss"
+ value-format="YYYY-MM-DD HH:mm:ss"
+ style="width: 100%"
+ />
+ </td>
+ <td class="label">妫�鏌ヤ汉</td>
+ <td class="value">
+ <el-input v-model="formData.inspector" placeholder="璇疯緭鍏ユ鏌ヤ汉" clearable />
+ </td>
+ <td class="label">鏃ユ湡</td>
+ <td class="value">
+ <el-date-picker
+ v-model="formData.inspectDate"
+ type="datetime"
+ placeholder="閫夋嫨鏃ユ湡鏃堕棿"
+ format="YYYY-MM-DD HH:mm:ss"
+ value-format="YYYY-MM-DD HH:mm:ss"
+ style="width: 100%"
+ />
+ </td>
+ </tr>
+ </table>
+ </div>
+ </div>
+
+ <template #footer>
+ <span class="dialog-footer">
+ <el-button @click="handleCancel">鍙� 娑�</el-button>
+ <el-button type="primary" :loading="saving" @click="handleSave">淇� 瀛�</el-button>
+ </span>
+ </template>
+ </el-dialog>
+</template>
+
+<script setup>
+import { ref, reactive, watch, computed } from 'vue';
+import dayjs from 'dayjs';
+
+const props = defineProps({
+ modelValue: {
+ type: Boolean,
+ default: false
+ },
+ orderData: {
+ type: Object,
+ default: () => ({})
+ }
+});
+
+const emit = defineEmits(['update:modelValue', 'save']);
+
+const visible = computed({
+ get: () => props.modelValue,
+ set: (val) => emit('update:modelValue', val)
+});
+
+const saving = ref(false);
+
+// 榛樿妫�鏌ラ」鐩�
+const defaultCheckItems = [
+ { itemNo: 1, content: '杞﹂棿鍐呮棤鍓嶆壒閬楃暀鐗┿�佸簾寮冪墿銆�', result: '绗﹀悎瑙勫畾', remark: '' },
+ { itemNo: 2, content: '杞﹂棿鍐呮棤鏃犲叧鎸囦护銆佽绋嬨�佽褰曠瓑銆�', result: '绗﹀悎瑙勫畾', remark: '' },
+ { itemNo: 3, content: '妗岄潰銆佸伐浣滃彴搴旀竻娲侊紝鏃犲皹銆佹棤鍨€��', result: '绗﹀悎瑙勫畾', remark: '' },
+ { itemNo: 4, content: '鍦伴潰娓呮磥锛屾棤绉皹銆佹潅鐗┿��', result: '绗﹀悎瑙勫畾', remark: '' },
+ { itemNo: 5, content: '璁惧鍙婇儴浠跺唴銆佸搴旀竻娲侊紝鏃犲紓鐗┿��', result: '绗﹀悎瑙勫畾', remark: '' },
+ { itemNo: 6, content: '瀹瑰櫒鍏峰簲娓呮磥鏃犲紓鐗╋紝骞剁疆鎸囧畾浣嶇疆', result: '绗﹀悎瑙勫畾', remark: '' },
+ { itemNo: 7, content: '鍗敓娲佸叿娓呮磥锛屽苟缃寚瀹氫綅缃�', result: '绗﹀悎瑙勫畾', remark: '' },
+ { itemNo: 8, content: '鍏跺畠', result: '绗﹀悎瑙勫畾', remark: '' }
+];
+
+const formData = reactive({
+ orderId: '',
+ productName: '',
+ productionDate: '',
+ spec: '',
+ batchNo: '',
+ workshop: '',
+ checkItems: JSON.parse(JSON.stringify(defaultCheckItems)),
+ cleaner: '',
+ cleanDate: '',
+ inspector: '',
+ inspectDate: ''
+});
+
+// 鐩戝惉寮规鎵撳紑锛屽垵濮嬪寲鏁版嵁
+watch(() => props.modelValue, (val) => {
+ if (val && props.orderData) {
+ initFormData();
+ }
+});
+
+const initFormData = () => {
+ const order = props.orderData;
+
+ const cleanRecord = order.cleanRecord || order.clearanceRecord;
+ if (cleanRecord) {
+ try {
+ const record = typeof cleanRecord === 'string'
+ ? JSON.parse(cleanRecord)
+ : cleanRecord;
+
+ // 鍔犺浇鍩烘湰瀛楁
+ formData.orderId = record.orderId || order.npsNo || '';
+ formData.productName = record.productName || order.productCategory || '';
+ formData.productionDate = record.productionDate || (order.startTime ? dayjs(order.startTime).format('YYYY-MM-DD') : dayjs().format('YYYY-MM-DD'));
+ formData.spec = record.spec || order.specificationModel || '';
+ formData.batchNo = record.batchNo || order.batchNo || order.uidNo || '';
+ formData.workshop = record.workshop || order.workshop || order.manufacturingTeam || '';
+
+ // 鍔犺浇妫�鏌ラ」鐩紝淇濇寔榛樿缁撴瀯浣嗘洿鏂扮粨鏋�
+ if (record.checkItems && Array.isArray(record.checkItems)) {
+ formData.checkItems = defaultCheckItems.map((defaultItem, index) => {
+ const savedItem = record.checkItems.find(item => item.itemNo === defaultItem.itemNo);
+ return {
+ ...defaultItem,
+ result: savedItem?.result || '绗﹀悎瑙勫畾',
+ remark: savedItem?.remark || ''
+ };
+ });
+ } else {
+ formData.checkItems = JSON.parse(JSON.stringify(defaultCheckItems));
+ }
+
+ // 鍔犺浇绛惧悕淇℃伅
+ formData.cleaner = record.cleaner || '';
+ formData.cleanDate = record.cleanDate || dayjs().format('YYYY-MM-DD HH:mm:ss');
+ formData.inspector = record.inspector || '';
+ formData.inspectDate = record.inspectDate || dayjs().format('YYYY-MM-DD HH:mm:ss');
+ } catch (e) {
+ console.error('瑙f瀽娓呭満璁板綍鏁版嵁澶辫触:', e);
+ resetFormData(order);
+ }
+ } else {
+ resetFormData(order);
+ }
+};
+
+const resetFormData = (order) => {
+ // 閲嶇疆妫�鏌ラ」鐩�
+ formData.checkItems = JSON.parse(JSON.stringify(defaultCheckItems));
+
+ // 鑷姩甯﹀叆璁㈠崟鏁版嵁
+ formData.orderId = order.npsNo || '';
+ formData.productName = order.productCategory || '';
+ formData.productionDate = order.startTime ? dayjs(order.startTime).format('YYYY-MM-DD') : dayjs().format('YYYY-MM-DD');
+ formData.spec = order.specificationModel || '';
+ formData.batchNo = order.batchNo || order.uidNo || '';
+ formData.workshop = order.workshop || order.manufacturingTeam || '';
+
+ // 娓呭満浜哄拰妫�鏌ヤ汉榛樿涓虹┖锛屾棩鏈熼粯璁や负褰撳墠鏃堕棿
+ formData.cleaner = '';
+ formData.cleanDate = dayjs().format('YYYY-MM-DD HH:mm:ss');
+ formData.inspector = '';
+ formData.inspectDate = dayjs().format('YYYY-MM-DD HH:mm:ss');
+};
+
+const handleCancel = () => {
+ visible.value = false;
+};
+
+const handleSave = () => {
+ // 楠岃瘉蹇呭~椤�
+ if (!formData.cleaner) {
+ ElMessage.warning('璇疯緭鍏ユ竻鍦轰汉');
+ return;
+ }
+ if (!formData.cleanDate) {
+ ElMessage.warning('璇烽�夋嫨娓呭満鏃ユ湡');
+ return;
+ }
+ if (!formData.inspector) {
+ ElMessage.warning('璇疯緭鍏ユ鏌ヤ汉');
+ return;
+ }
+ if (!formData.inspectDate) {
+ ElMessage.warning('璇烽�夋嫨妫�鏌ユ棩鏈�');
+ return;
+ }
+
+ // 鏋勯�犱繚瀛樼殑JSON鏁版嵁
+ const saveData = {
+ orderId: formData.orderId,
+ productName: formData.productName,
+ productionDate: formData.productionDate,
+ spec: formData.spec,
+ batchNo: formData.batchNo,
+ workshop: formData.workshop,
+ checkItems: formData.checkItems.map(item => ({
+ itemNo: item.itemNo,
+ content: item.content,
+ result: item.result,
+ remark: item.remark || undefined
+ })),
+ cleaner: formData.cleaner,
+ cleanDate: formData.cleanDate,
+ inspector: formData.inspector,
+ inspectDate: formData.inspectDate
+ };
+
+ // 绉婚櫎undefined瀛楁
+ saveData.checkItems = saveData.checkItems.map(item => {
+ if (!item.remark) delete item.remark;
+ return item;
+ });
+
+ saving.value = true;
+ emit('save', saveData, () => {
+ saving.value = false;
+ visible.value = false;
+ });
+};
+</script>
+
+<style scoped lang="scss">
+.clearance-record-form {
+ .basic-info {
+ margin-bottom: 20px;
+ }
+
+ .info-table {
+ width: 100%;
+ border-collapse: collapse;
+ border: 1px solid #dcdfe6;
+
+ td {
+ border: 1px solid #dcdfe6;
+ padding: 10px;
+ font-size: 14px;
+ }
+
+ .label {
+ background-color: #f5f7fa;
+ width: 100px;
+ text-align: center;
+ font-weight: 500;
+ }
+
+ .value {
+ background-color: #fff;
+ min-width: 150px;
+ }
+ }
+
+ .check-items-section {
+ margin-bottom: 10px;
+
+ .check-table {
+ width: 100%;
+ border-collapse: collapse;
+ border: 1px solid #dcdfe6;
+
+ th, td {
+ border: 1px solid #dcdfe6;
+ padding: 12px 10px;
+ font-size: 14px;
+ }
+
+ th {
+ background-color: #f5f7fa;
+ font-weight: 500;
+ text-align: center;
+ }
+
+ .item-no {
+ width: 60px;
+ text-align: center;
+ }
+
+ .content {
+ text-align: left;
+ padding-left: 15px;
+ }
+
+ .result {
+ width: 200px;
+ text-align: center;
+ }
+
+ .result-option {
+ width: 150px;
+ text-align: center;
+
+ :deep(.el-radio-group) {
+ display: flex;
+ justify-content: center;
+ }
+ }
+ }
+ }
+
+ .remark-section {
+ margin-bottom: 20px;
+ padding: 0 10px;
+ }
+
+ .signature-section {
+ .signature-table {
+ width: 100%;
+ border-collapse: collapse;
+ border: 1px solid #dcdfe6;
+
+ td {
+ border: 1px solid #dcdfe6;
+ padding: 10px;
+ font-size: 14px;
+ }
+
+ .label {
+ background-color: #f5f7fa;
+ width: 80px;
+ text-align: center;
+ font-weight: 500;
+ }
+
+ .value {
+ background-color: #fff;
+ min-width: 150px;
+ }
+ }
+ }
+}
+
+.dialog-footer {
+ display: flex;
+ justify-content: flex-end;
+ gap: 10px;
+}
+</style>
diff --git a/src/views/productionManagement/productionOrder/index.vue b/src/views/productionManagement/productionOrder/index.vue
index 829f7ab..8c254da 100644
--- a/src/views/productionManagement/productionOrder/index.vue
+++ b/src/views/productionManagement/productionOrder/index.vue
@@ -95,6 +95,13 @@
<new-product-order v-if="isShowNewModal"
v-model:visible="isShowNewModal"
@completed="handleQuery"/>
+
+ <!-- 娓呭満璁板綍寮规 -->
+ <clearance-record-dialog
+ v-model="clearanceDialogVisible"
+ :order-data="currentOrderData"
+ @save="handleSaveClearanceRecord"
+ />
</div>
</template>
@@ -108,12 +115,14 @@
listProcessRoute,
bindingRoute,
delProductOrder, finishOrder,
+ saveCleanRecord,
} from "@/api/productionManagement/productionOrder.js";
import {listMain as getOrderProcessRouteMain} from "@/api/productionManagement/productProcessRoute.js";
import {fileDel} from "@/api/financialManagement/revenueManagement.js";
import PIMTable from "@/components/PIMTable/PIMTable.vue";
const NewProductOrder = defineAsyncComponent(() => import("@/views/productionManagement/productionOrder/New.vue"));
+const ClearanceRecordDialog = defineAsyncComponent(() => import("@/views/productionManagement/productionOrder/ClearanceRecordDialog.vue"));
const {proxy} = getCurrentInstance();
@@ -227,6 +236,14 @@
handleFinishOrder(row);
},
},
+ {
+ name: "娓呭満璁板綍",
+ type: "text",
+ showHide: row => !row.isEnd,
+ clickFun: row => {
+ handleClearanceRecord(row);
+ },
+ },
],
},
]);
@@ -289,6 +306,10 @@
const bindRouteLoading = ref(false);
const bindRouteSaving = ref(false);
const routeOptions = ref([]);
+
+// 娓呭満璁板綍寮规
+const clearanceDialogVisible = ref(false);
+const currentOrderData = ref({});
const bindForm = reactive({
orderId: null,
routeId: null,
@@ -478,6 +499,32 @@
proxy.$modal.msg("宸插彇娑�");
});
};
+
+// 鎵撳紑娓呭満璁板綍寮规
+const handleClearanceRecord = (row) => {
+ currentOrderData.value = row;
+ clearanceDialogVisible.value = true;
+};
+
+// 淇濆瓨娓呭満璁板綍
+const handleSaveClearanceRecord = async (saveData, callback) => {
+ const orderId = currentOrderData.value?.id;
+ if (!orderId) {
+ proxy.$modal.msgError("璁㈠崟ID涓嶅瓨鍦�");
+ return;
+ }
+
+ try {
+ await saveCleanRecord(orderId, saveData);
+ proxy.$modal.msgSuccess("娓呭満璁板綍淇濆瓨鎴愬姛");
+ currentOrderData.value.cleanRecord = saveData;
+ if (callback) callback();
+ getList();
+ } catch (error) {
+ console.error('淇濆瓨娓呭満璁板綍澶辫触:', error);
+ proxy.$modal.msgError("娓呭満璁板綍淇濆瓨澶辫触");
+ }
+};
onMounted(() => {
getList();
});
--
Gitblit v1.9.3