From 1bcee828a3340d5f5642b3dbcf4cd9733072b7aa Mon Sep 17 00:00:00 2001
From: 啊鑫 <t2856754968@163.com>
Date: 星期一, 21 七月 2025 14:24:35 +0800
Subject: [PATCH] LLJ检验结果录入优化:添加自动保存和回车保存功能

---
 pages/QC/LLJ/detail.vue |  396 ++++++++++++++++++++++++++++++++++++++++++++++++++------
 1 files changed, 351 insertions(+), 45 deletions(-)

diff --git a/pages/QC/LLJ/detail.vue b/pages/QC/LLJ/detail.vue
index af7cc9e..41783ec 100644
--- a/pages/QC/LLJ/detail.vue
+++ b/pages/QC/LLJ/detail.vue
@@ -7,12 +7,14 @@
 		</view>
 
 		<!-- 鏍囩鏍� -->
-		<view class="tabs">
-			<view v-for="(tab, index) in tabs" :key="index" class="tab" :class="{active: currentTab === index}"
-				@tap="switchTab(index,tab.id)">
-				{{ tab.fcheckItem }}
+		<scroll-view class="tabs" scroll-x="true" :show-scrollbar="false">
+			<view class="tabs-container">
+				<view v-for="(tab, index) in tabs" :key="index" class="tab" :class="{active: currentTab === index}"
+					@tap="switchTab(index,tab.id)">
+					{{ tab.fcheckItem }}
+				</view>
 			</view>
-		</view>
+		</scroll-view>
 		<view class="tab-content">
 			<!-- 鍩烘湰淇℃伅 -->
 			<view class="section">
@@ -97,9 +99,13 @@
 						<view class="info-value">{{formData.result}}</view>
 					</view>
 
-					<view v-if="formData.remarks!=null" class="result-ng">
+					<view v-if="formData.funit!=null" class="result-ng">
 						<view class="info-label">涓嶈壇鎻忚堪</view>
-						<view class="info-value danger">{{formData.remarks}}</view>
+						<view class="info-value danger">{{formData.funit}}</view>
+					</view>
+					<view class="result-ng">
+					    <view class="info-label">澶囨敞</view>
+					    <view class="info-value danger">{{formData.meom}}</view>
 					</view>
 				</view>
 			</view>
@@ -108,6 +114,17 @@
 			<view class="section">
 				<view class="section-header">妫�楠岀粨鏋滃綍鍏�</view>
 				<view class="section-body">
+					<view class="input-group" v-if="tableData.length >= formData.checkQyt && formData.fstand == null">
+						<view class="input-wrapper">
+							<input v-model="batchInput" type="text" class="result-input"
+								placeholder="鏍煎紡锛歄K-3 鎴� NG-3锛堣鍕夸慨鏀圭粨鏋滀负鏁板瓧鐨勫�硷級" placeholder-class="placeholder"
+								@input="validateBatchInput" @blur="validateBatchInput" />
+							<button :disabled="!isBatchInputValid" :class="{ 'btn-disabled': !isBatchInputValid }"
+								style="margin: 0px;background-color: #3498db;color:#ffffff ;" class="btn primary-btn"
+								@tap="batchUpdateResults">鎵归噺淇敼</button>
+						</view>
+						<view v-if="batchInputError" class="error-message">{{ batchInputError }}</view>
+					</view>
 					<view class="input-group input1">
 						<view class="input-wrapper">
 
@@ -119,18 +136,35 @@
 								<uni-icons type="compose" size="16" color="#fff"></uni-icons>
 								涓嶈壇鎻忚堪
 							</button>
-							<input v-if="(tableData.length < formData.checkQyt)" @input="search($event)"
-								v-model="inputTxt" type="text" class="result-input" placeholder="璇疯緭鍏ユ楠岀粨鏋�..."
+							<button v-if="this.current" class="btn upload-btn" @tap="upMeom">
+								<uni-icons type="compose" size="16" color="#fff"></uni-icons>
+								澶囨敞
+							</button>
+							<input v-if="(tableData.length < formData.checkQyt) && formData.fupAllow && formData.fdownAllow"
+								@input="onNumberInput"
+								@confirm="onEnterSave"
+								v-model="formData.fcheckResu"
+								type="text"
+								class="result-input"
+								placeholder="璇疯緭鍏ユ楠岀粨鏋�..."
+								placeholder-class="placeholder" />
+							<input v-else
+								@input="search($event)"
+								@confirm="onEnterSave"
+								v-model="inputTxt"
+								type="text"
+								class="result-input"
+								placeholder="璇疯緭鍏ユ楠岀粨鏋�..."
 								placeholder-class="placeholder" />
 							<button v-if="(tableData.length < formData.checkQyt)"
 								style="margin: 0px;background-color: #3498db;color:#ffffff ;" class="btn primary-btn"
 								@tap="saveResult">淇濆瓨缁撴灉</button>
 						</view>
 					</view>
-					
+
 					<view class="input-group input2">
 						<view class="input-wrapper">
-					
+
 							<button class="btn upload-btn" @tap="chooseImage">
 								<uni-icons type="upload" size="16" color="#fff"></uni-icons>
 								涓婁紶/鏌ョ湅鍥剧墖
@@ -139,10 +173,17 @@
 								<uni-icons type="compose" size="16" color="#fff"></uni-icons>
 								涓嶈壇鎻忚堪
 							</button>
+							<button v-if="this.current" class="btn upload-btn" @tap="upMeom">
+							            <uni-icons type="compose" size="16" color="#fff"></uni-icons>
+							            澶囨敞
+							        </button>
+							
 						</view>
+						 
 						<view class="input-wrapper" style="margin-top: 15px;">
-						
+
 							<input v-if="(tableData.length < formData.checkQyt)" @input="search($event)"
+								@confirm="onEnterSave"
 								v-model="inputTxt" type="text" class="result-input" placeholder="璇疯緭鍏ユ楠岀粨鏋�..."
 								placeholder-class="placeholder" />
 							<button v-if="(tableData.length < formData.checkQyt)"
@@ -157,7 +198,8 @@
 			<view v-if="tableData.length>0" class="table-container">
 				<view class="table-header">
 					<view class="th">缂栧彿</view>
-					<view class="th">妫�楠岀粨鏋�<i style="color: rgb(0 212 68);" v-if="!(tableData.length < formData.checkQyt)">锛堣緭鍏ュ凡瀹屾垚锛�</i></view>
+					<view class="th">妫�楠岀粨鏋�<i style="color: rgb(0 212 68);"
+							v-if="!(tableData.length < formData.checkQyt)">锛堣緭鍏ュ凡瀹屾垚锛�</i></view>
 					<view class="th" v-if="current">鎿嶄綔</view>
 				</view>
 
@@ -168,7 +210,7 @@
 							{{ item.fcheckResu }}
 						</view>
 					</view>
-					<view class="td" v-if="current" >
+					<view class="td" v-if="current">
 						<button v-if="!isNumber" class="btn danger-btn" @tap="toggleResult(item)">
 							{{ editResult(item.fcheckResu) }}
 						</button>
@@ -191,7 +233,20 @@
 					</form>
 				</view>
 			</view>
-			<view v-if="showPopup" class="overlay">
+			<view v-if="meomPopup" class="overlay">
+			    <view class="popup">
+			        <h3>淇敼澶囨敞</h3>
+			        <form>
+			            <view class="form-group">
+			                <label class="form-label">澶囨敞:</label>
+			                <input class="form-input" type="text" v-model="meom" />
+			            </view>
+			            <button class="updateBut" type="warn" @click="editMeom">淇敼</button>
+			            <button @click="meomPopup = !meomPopup">鍙栨秷</button>
+			        </form>
+			    </view>
+			</view>
+			<view v-if="showMeom" class="overlay">
 				<view class="popup">
 					<h3>淇敼妫�楠岀粨鏋�</h3>
 					<form :modelValue="editData">
@@ -200,7 +255,7 @@
 							<input class="form-input" type="text" v-model="editData.fcheckResu" />
 						</view>
 						<button type="warn" @click="eidt">淇敼</button>
-						<button @click="showPopup = !showPopup">鍙栨秷</button>
+						<button @click="showMeom = !showMeom">鍙栨秷</button>
 					</form>
 				</view>
 			</view>
@@ -228,20 +283,184 @@
 				showPopup: false,
 				editData: {},
 				inputTxt: '',
-				formID:'',
-				releaseNo:'',
-				current:false
+				formID: '',
+				releaseNo: '',
+				current: false,
+				batchInput: '',
+				batchInputError: '',
+				isBatchInputValid: false,
+				funit:'',
+				meomPopup: false,
+				showMeom:false,
+				meom: '',
+				autoSaveTimer: null, // 鑷姩淇濆瓨瀹氭椂鍣�
 			}
 		},
 		methods: {
-			switchTab(index,mainIds) {
+			// 闃叉姈鑷姩淇濆瓨鏂规硶
+			autoSaveResult() {
+				// 娓呴櫎涔嬪墠鐨勫畾鏃跺櫒
+				if (this.autoSaveTimer) {
+					clearTimeout(this.autoSaveTimer);
+				}
+				
+				// 璁剧疆鏂扮殑瀹氭椂鍣紝1绉掑悗鑷姩淇濆瓨
+				this.autoSaveTimer = setTimeout(() => {
+					// 妫�鏌ユ槸鍚﹀凡缁忚揪鍒版楠屾暟閲忎笂闄�
+					if (this.tableData.length >= this.formData.checkQyt) {
+						return;
+					}
+					
+					// 楠岃瘉杈撳叆骞朵繚瀛�
+					if (this.validateAndSave()) {
+						this.saveResult();
+					}
+				}, 2000);
+			},
+			
+			// 楠岃瘉杈撳叆鏄惁鏈夋晥
+			validateAndSave() {
+				// 鏈変笂涓嬮檺鐨勬儏鍐�
+				if (this.formData.fupAllow && this.formData.fdownAllow) {
+					const value = this.formData.fcheckResu;
+					if (!value || value.trim() === '') {
+						return false;
+					}
+					
+					// 楠岃瘉鏄惁涓烘湁鏁堟暟瀛�
+					if (isNaN(parseFloat(value)) || !/^-?\d+(\.\d+)?$/.test(value)) {
+						return false;
+					}
+					
+					return true;
+				} else {
+					// 鏃犱笂涓嬮檺鐨勬儏鍐碉紝妫�楠岀粨鏋滃瓨鍌ㄥ湪 formData.fcheckResu 涓�
+					const value = this.formData.fcheckResu;
+					if (!value || value.trim() === '') {
+						return false;
+					}
+					
+					return true;
+				}
+			},
+			
+			// 澶勭悊鍥炶溅閿繚瀛樹簨浠�
+			onEnterSave() {
+				// 妫�鏌ユ槸鍚﹀凡缁忚揪鍒版楠屾暟閲忎笂闄�
+				if (this.tableData.length >= this.formData.checkQyt) {
+					this.$showMessage("宸茶揪鍒版楠屾暟閲忎笂闄�");
+					return;
+				}
+				
+				// 娓呴櫎鑷姩淇濆瓨瀹氭椂鍣�
+				if (this.autoSaveTimer) {
+					clearTimeout(this.autoSaveTimer);
+					this.autoSaveTimer = null;
+				}
+				
+				// 鐩存帴淇濆瓨缁撴灉
+				this.saveResult();
+			},
+			
+			switchTab(index, mainIds) {
 				this.currentTab = index
 				this.mainId = mainIds;
 				this.refreshResult();
+
+			},
+			validateBatchInput() {
+				const input = this.batchInput.trim();
+				if (!input) {
+					this.batchInputError = '';
+					this.isBatchInputValid = false;
+					return;
+				}
+
+				// 楠岃瘉鏍煎紡锛歄K-鏁板瓧 鎴� NG-鏁板瓧
+				const match = input.match(/^(OK|NG)-(\d+)$/);
+				if (!match) {
+					this.batchInputError = '鏍煎紡閿欒锛岃杈撳叆锛歄K-鏁板瓧 鎴� NG-鏁板瓧';
+					this.isBatchInputValid = false;
+					return;
+				}
+
+				const count = parseInt(match[2]);
+				if (count <= 0 || count > this.tableData.length) {
+					this.batchInputError = `鏁伴噺蹇呴』鍦� 1-${this.tableData.length} 涔嬮棿`;
+					this.isBatchInputValid = false;
+					return;
+				}
+
+
+				this.batchInputError = '';
+				this.isBatchInputValid = true;
+			},
+
+			// 鎵归噺鏇存柊妫�楠岀粨鏋�
+			batchUpdateResults() {
+				if (!this.isBatchInputValid) return;
+
+				const [status, countStr] = this.batchInput.split('-');
+				const count = parseInt(countStr);
+
+				if (this.tableData.length > 0) {
+					const firstItem = this.tableData[0];
+					const isNumber = /^-?\d+(\.\d+)?$/.test(firstItem.fcheckResu);
+					if (isNumber) {
+						this.$showMessage("涓嶈兘鎵归噺淇敼鏁板瓧绫诲瀷鐨勭粨鏋�");
+						return;
+					}
+				}
+				let updatedCount = 0;
+				const requests = [];
+				for (let i = 0; i < count; i++) {
+					const item = this.tableData[i];
+					const fstand = status === 'OK' ? '鈭�' : '脳';
+					const fcheckResu = status;
+
+					requests.push(this.$post({
+						url: "/LLJ/UpdateQSItemDetail",
+						data: {
+							id: item.id,
+							mainId: this.formData.id,
+							releaseNo: this.formData.releaseNo,
+							fstand: fstand,
+							fcheckResu: fcheckResu,
+							updateBy: this.$loginInfo.account,
+						}
+					}));
+				}
+
+				Promise.all(requests)
+					.then(() => {
+						this.$showMessage(`鎴愬姛灏嗗墠${count}涓粨鏋滀慨鏀逛负${status}`);
+						this.batchInput = '';
+						this.batchInputError = '';
+						this.isBatchInputValid = false;
+						this.refreshResult(); // 鍒锋柊缁撴灉
+					})
+					.catch(error => {
+						this.$showMessage(`鎵归噺淇敼澶辫触: ${error.message}`);
+					});
 			},
 			//妫�娴嬭緭鍏ユ鐨勮緭鍏ワ紝骞剁粰鍙橀噺璧嬪��
 			search(event) {
 				this.formData.fcheckResu = event.detail.value;
+				this.inputTxt = event.detail.value;
+				
+				// 瑙﹀彂鑷姩淇濆瓨
+				this.autoSaveResult();
+			},
+			onNumberInput(e) {
+				// 鍙厑璁歌緭鍏ユ暟瀛楀拰灏忔暟鐐�
+				let val = e.detail.value.replace(/[^\d.]/g, '');
+				// 鍙厑璁镐竴涓皬鏁扮偣
+				val = val.replace(/\.{2,}/g, '.');
+				val = val.replace('.', '$#$').replace(/\./g, '').replace('$#$', '.');
+				this.formData.fcheckResu = val;
+				
+				// 瑙﹀彂鑷姩淇濆瓨
+				this.autoSaveResult();
 			},
 			toggleResult(item) {
 				let fstand = "鈭�";
@@ -292,7 +511,11 @@
 						this.$showMessage("璇疯緭鍏ユ纭殑妫�楠屽��");
 						return;
 					}
-
+					
+					if (!/^-?\d+(\.\d+)?$/.test(this.formData.fcheckResu)) {
+					            this.$showMessage("璇疯緭鍏ユ纭殑鏁板�硷紒");
+					            return;
+					}
 					if (parseFloat(this.formData.fcheckResu) >= parseFloat(this.formData.fdownAllow) && parseFloat(this
 							.formData
 							.fcheckResu) <= parseFloat(this.formData.fupAllow)) {
@@ -359,9 +582,10 @@
 					//fupAllow  fdownAllow  standardValue
 					if (this.formData.fupAllow && this.formData.fdownAllow && this.formData.fstand) {
 						this.isNumber = true;
-					}else{
+					} else {
 						this.isNumber = false;
 					}
+					
 				})
 			},
 			editResult(fcheckResu) {
@@ -373,11 +597,50 @@
 			},
 			toDetail(item) {
 				this.showPopup = !this.showPopup;
+				this.showMeom = !this.showMeom;
 				this.editData = item;
+				
+			},
+			upMeom() {
+			    this.meomPopup = true;
+			    
+			},
+			editMeom() {
+			    // 淇濆瓨澶囨敞淇℃伅
+			    if (this.meom) {
+			        this.$post({
+			            url: "/LLJ/saveRemarksPid",
+			            data: {
+			                pid: this.formData.id,
+			                meom: this.meom,
+							
+			            }
+			        }).then(res => {
+			            if (res.data.tbBillList > 0) {
+			                this.formData.meom = this.meom;
+			                this.meomPopup = !this.meomPopup;
+			                this.$showMessage("淇濆瓨鎴愬姛");
+			            }
+			        })
+			    } else {
+			        this.$post({
+			            url: "/LLJ/saveRemarksPid",
+			            data: {
+			                pid: this.formData.id,
+			                meom: ''
+			            }
+			        }).then(res => {
+			            if (res.data.tbBillList > 0) {
+			                this.formData.meom = this.meom;
+			                this.meomPopup = !this.meomPopup;
+			                this.$showMessage("淇濆瓨鎴愬姛");
+			            }
+			        })
+			    }
 			},
 			editRemarks() {
 				if (this.remarks) {
-					//saveRemarksGid
+					
 					this.$post({
 						url: "/LLJ/saveRemarksPid",
 						data: {
@@ -475,15 +738,16 @@
 			let params = options;
 			this.mainId = params["mainId"];
 			this.refreshResult();
-			this.formID= params["formID"];
-			this.releaseNo= params["releaseNo"];
-            this.currentTab=parseInt(params["index"]);
-			this.current=params["current"] === 'true' ? true : false;
+			this.formID = params["formID"];
+			this.releaseNo = params["releaseNo"];
+			this.currentTab = parseInt(params["index"]);
+			this.current = params["current"] === 'true' ? true : false;
 			this.$post({
 				url: "/LLJ/getJYItem",
 				data: {
 					id: this.formID,
-					releaseNo: this.releaseNo
+					releaseNo: this.releaseNo,
+					
 				}
 			}).then(res1 => {
 				let tableData = res1.data.tbBillList
@@ -497,7 +761,7 @@
 						return 0;
 					}
 				});
-				 this.tabs = tableData;
+				this.tabs = tableData;
 				// if (this.tableData.length === 0) {
 				// 	this.isShowTable = true;
 				// }
@@ -505,7 +769,20 @@
 					this.set(item, 'current', this.current);
 				});
 				console.log(this.tableData);
+
+
 			})
+			this.$nextTick(() => {
+				this.validateBatchInput();
+			});
+		},
+		
+		// 椤甸潰鍗歌浇鏃舵竻闄ゅ畾鏃跺櫒
+		onUnload() {
+			if (this.autoSaveTimer) {
+				clearTimeout(this.autoSaveTimer);
+				this.autoSaveTimer = null;
+			}
 		}
 	}
 </script>
@@ -540,17 +817,25 @@
 	}
 
 	.tabs {
-		display: flex;
 		background-color: $bg-color;
 		border-bottom: 1px solid $border-color;
+		width: 100%;
+		white-space: nowrap;
+
+		.tabs-container {
+			display: flex;
+			min-width: 100%;
+		}
 
 		.tab {
-			flex: 1;
+			flex: none;
+			min-width: 120px;
 			text-align: center;
-			padding: 12px 0;
+			padding: 12px 16px;
 			border-right: 1px solid $border-color;
 			color: #666;
 			transition: all 0.3s;
+			white-space: nowrap;
 
 			&:last-child {
 				border-right: none;
@@ -745,20 +1030,41 @@
 		background-color: #3498db;
 		color: white;
 	}
- .input1{
- 		   display: block;
- }
- .input2{
- 		   display: none;
- }
+
+	.input1 {
+		display: block;
+	}
+
+	.input2 {
+		display: none;
+	}
+
 	/* 鍝嶅簲寮忚璁� */
 	@media (max-width: 500px) {
-	   .input1{
-		   display: none;
-	   }
-	   .input2{
-		   display: block;
-	   }
+		.input1 {
+			display: none;
+		}
+
+		.input2 {
+			display: block;
+		}
 	}
-	
+
+	.error-message {
+		color: $danger-color;
+		font-size: 12px;
+		margin-top: 4px;
+	}
+
+	.input-group:first-child {
+		.result-input {
+			border-color: $primary-color;
+			box-shadow: 0 0 0 2px rgba($primary-color, 0.2);
+		}
+	}
+
+	.btn-disabled {
+		opacity: 0.6;
+		cursor: not-allowed;
+	}
 </style>
\ No newline at end of file

--
Gitblit v1.9.3