Sfoglia il codice sorgente

处理填写完成无法提交的问题

wzz 1 settimana fa
parent
commit
0ab1d56b55

+ 5 - 1
src/pages/sickForm/historyDetail.vue

@@ -234,7 +234,11 @@ export default {
 		}
 		that.submitContent = (item.id + ':' + valArr + ';');
 		if(e.detail.isInput && !item.type){
-		   item.answer = that.submitContent;
+		   // 修复:这里原来把整条 submitContent(带题目自己的 id,格式是"题目id:选项id#文本#;")
+		   // 直接写回 item.answer,但 item.answer 是 checkbox 组件自己 v-model 绑定的值,它只认得
+		   // "选项id#文本#"这种不带题目 id 的格式——写成带题目 id 的格式后,组件反过来解析就会完全找不到
+		   // 匹配的选项,导致刚输入的这个单选连同填空框一起立刻变成"未选中"。这里改成只用选项级别的值。
+		   item.answer = Array.isArray(valArr) ? (valArr.length ? valArr[0] : '') : valArr;
 		}
 		let obj = {
 			qId:item.id,

+ 34 - 12
src/uni_modules/uni-data-checkbox/components/uni-data-checkbox/uni-data-checkbox.vue

@@ -21,7 +21,7 @@
 					</view>
 					<view class="checklist-content" :class="{'list-content':mode === 'list' && icon ==='left'}">
 						<text class="checklist-text" :style="item.styleIconText">{{item[map.text].includes('##') ? item[map.text].slice(0,-2) : item[map.text]}}</text>
-						<input v-show="(item[map.text].includes('##')) && item.selected" type="text" placeholder="请输入" class="multiple-Input" v-model="item.inputValue" @change="inputChange('',$event)">
+						<input v-show="(item[map.text].includes('##')) && item.selected" type="text" placeholder="请输入" class="multiple-Input" v-model="item.inputValue" @input="inputChange('',$event)" @change="inputChange('',$event)">
 						<view v-if="mode === 'list' && icon === 'right'" class="checkobx__list" :style="item.styleBackgroud"></view>
 					</view>
 				</label>
@@ -38,7 +38,7 @@
 					</view>
 					<view class="checklist-content" :class="{'list-content':mode === 'list' && icon ==='left'}">
 						<text class="checklist-text" :style="item.styleIconText">{{item[map.text].includes('##') ? item[map.text].slice(0,-2) : item[map.text]}}</text>
-						<input v-show="(item[map.text].includes('##'))  && item.selected" type="text" placeholder="请输入" class="multiple-Input" v-model="item.inputValue" @change="inputChange('',$event)">
+						<input v-show="(item[map.text].includes('##'))  && item.selected" type="text" placeholder="请输入" class="multiple-Input" v-model="item.inputValue" @input="inputChange('',$event)" @change="inputChange('',$event)">
 						<view v-if="mode === 'list' && icon === 'right'" :style="item.styleRightIcon" class="checkobx__list"></view>
 					</view>
 				</label>
@@ -162,6 +162,10 @@
 			},
 			value(newVal) {
 				let that = this;
+				// 打字时(inputChange)自己往外 emit 这个值,只是为了让父组件的 item.answer 跟着同步,
+				// 这里的 dataList 本来就已经是最新的了,不需要也不应该借着这次赋值再重建一遍
+				// (重建会整个替换 dataList,正在输入的框可能因此丢失焦点/光标,见 inputChange 里的说明)
+				if (that._skipModelRebuild) { that._skipModelRebuild = false; return }
 				that.dataList = that.getDataList(newVal)
 				// fix by mehaotian is_reset 在 uni-forms 中定义
 				// if(!this.is_reset){
@@ -170,6 +174,7 @@
 				// }
 			},
 			modelValue(newVal) {
+				if (this._skipModelRebuild) { this._skipModelRebuild = false; return }
 				this.dataList = this.getDataList(newVal);
 				// if(!this.is_reset){
 				// 	this.is_reset = false
@@ -193,7 +198,10 @@
 				},
 				isTop: 0,
 				nowRecordList:[],//记录当前选择
-				saveList:[]
+				saveList:[],
+				// inputChange 往外 emit modelValue 只是为了同步父组件的 item.answer,配合 value/modelValue
+				// watcher 用来跳过那一次没必要、还可能打断正在输入的重建
+				_skipModelRebuild: false
 			};
 		},
 		computed: {
@@ -314,6 +322,9 @@
 					this.dataList = this.getDataList(detail.value)
 				}
 			},
+			// 修复:填空框原来只绑定了 @change(失焦/回车才触发),如果用户打完字直接点提交、
+			// 输入框没有失焦,这次编辑就完全没被记录下来,提交内容里这一项还是打字之前的旧值(甚至是空的)。
+			// 现在同时绑定 @input,每敲一个字都会同步一次,不再依赖"有没有失焦"这个时机。
 			inputChange(type,e){
 				console.log('datalistInput,',e)
 				let detail = {
@@ -352,9 +363,16 @@
 					}
 				})
 				console.log('selectedValue92929',detail)
-				// this.$emit('input', detail.value);
-				// // // TOTO 兼容 vue3
-				// this.$emit('update:modelValue', detail.value);
+				// 修复:原来这两行是注释掉的,导致父组件 v-model 绑定的 item.answer 只有勾选/取消勾选时才会
+				// 同步,打字编辑永远不会同步——如果用户对同一题的操作顺序是"先勾选、再打字"(而不是"打完字
+				// 又去点别的勾选框"),item.answer 就会一直停留在打字之前的旧快照上,表单提交前的完整性校验
+				// (读的正是 item.answer)会一直误判成"没填",即使实际要提交的内容早就是对的。
+				// 这里把 emit 打开,让 item.answer 跟着每次打字同步;同时给 _skipModelRebuild 打标记,
+				// 配合 value/modelValue watcher 跳过因为这次 emit 引发的重建(dataList 现在已经是最新的,
+				// 不需要再重建一遍,重建反而可能打断正在输入的框)。
+				this._skipModelRebuild = true
+				this.$emit('input', detail.value);
+				this.$emit('update:modelValue', detail.value);
 				this.$emit('change', {
 					detail
 				})
@@ -364,8 +382,10 @@
 					// this.dataList = this.getDataList(detail.value, true)
 					// }
 				} else {
-					
-					this.dataList = this.getDataList(detail.value)
+					// 单选场景下 detail.value 是数组(上面统一按 push 方式构建的),但 getDataList 单选分支
+					// 是按"传入的是一个值"来解析的(取首字符当选项标识),直接把数组传进去每个 typeof 判断都对不上,
+					// 会导致 item.selected 全部算不出来、勾选状态和填空框跟着一起消失,这里取数组里唯一的一项传进去
+					this.dataList = this.getDataList(detail.value.length ? detail.value[0] : '')
 				}
 					// console.log('selectedValue6656565',this.dataList)
 			},
@@ -514,12 +534,14 @@
 						// console.log('otherObj77777',otherObj)
 						item.inputValue = otherObj.end
 						// console.log('otherObj77777',item)
-						// 多选下 item.selected 上面按 value 数组已经正确算过了,这里不再需要、也不能再用 item.value = otherObj.end
-						// 去覆盖 —— item.value 是这个 checkbox 原生 value 属性绑定的标识,多选场景下改成填写的文本内容,
-						// 会导致下一次勾选变化时对不上号,选中状态跟着丢
+						// 之前这里不管单选多选,只要匹配上就会把 item.value 整个改成填写的文本内容——item.value 是
+						// checkbox 原生 value 属性绑定的标识(比如"E"),选中状态靠它和 item_number 对比来判断。
+						// 改了之后下一次编辑/切换再用 item.value 去拼自描述串或者做选中判断就全错位了(单选场景之前
+						// 只排除了多选,单选这条尾巴一直留着,导致单选"其他"填空打完字失焦后连带选中状态一起丢)。
+						// item.selected 上面 sliceInput === item.item_number 那步已经算对了,这里不再需要,
+						// 文本内容已经通过 item.inputValue 记录,不需要也不能再动 item.value。
 						if(!this.multiple && otherObj.start === item.value){
 							item.selected = true;
-							item.value = otherObj.end;
 						}
 						// showOtherInputVal 反推不出来时,用重建前缓存的内容(按下标)兜底,避免多选下切换勾选把已填文本冲掉
 						if (this.multiple && !item.inputValue && prevInputMap[index]) {