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