hookehuyr

feat(输入框): 添加自动聚焦功能并优化样式

在创建家庭和加入家庭页面中,为输入框添加自动聚焦功能,当输入有效字符时自动跳转到下一个输入框
优化输入框的边框样式,移除不必要的内联样式
将加入家庭成功后的跳转改为 reLaunch 以清除页面栈
...@@ -74,6 +74,7 @@ ...@@ -74,6 +74,7 @@
74 <view v-for="(char, index) in familyMotto" :key="index" class="flex-1"> 74 <view v-for="(char, index) in familyMotto" :key="index" class="flex-1">
75 <view class="w-full aspect-square flex items-center justify-center bg-gray-100 rounded-lg"> 75 <view class="w-full aspect-square flex items-center justify-center bg-gray-100 rounded-lg">
76 <input 76 <input
77 + :ref="(el) => (inputRefs[index] = el)"
77 type="text" 78 type="text"
78 v-model="familyMotto[index]" 79 v-model="familyMotto[index]"
79 :placeholder="familyMottoPlaceholder[index]" 80 :placeholder="familyMottoPlaceholder[index]"
...@@ -159,7 +160,7 @@ ...@@ -159,7 +160,7 @@
159 </template> 160 </template>
160 161
161 <script setup> 162 <script setup>
162 -import { ref } from 'vue'; 163 +import { ref, nextTick } from 'vue';
163 import Taro from '@tarojs/taro'; 164 import Taro from '@tarojs/taro';
164 import { Edit, Tips, Photograph } from '@nutui/icons-vue-taro'; 165 import { Edit, Tips, Photograph } from '@nutui/icons-vue-taro';
165 // import AppHeader from '../../components/AppHeader.vue'; 166 // import AppHeader from '../../components/AppHeader.vue';
...@@ -173,6 +174,7 @@ const familyMottoPlaceholder = ref(['孝', '敬', '和', '睦']); ...@@ -173,6 +174,7 @@ const familyMottoPlaceholder = ref(['孝', '敬', '和', '睦']);
173 const familySizes = ['2人', '3-5人', '6人+']; 174 const familySizes = ['2人', '3-5人', '6人+'];
174 const familyAvatar = ref(''); 175 const familyAvatar = ref('');
175 const focusedIndex = ref(-1); 176 const focusedIndex = ref(-1);
177 +const inputRefs = ref([]);
176 178
177 // 图片预览相关 179 // 图片预览相关
178 const previewVisible = ref(false); 180 const previewVisible = ref(false);
...@@ -192,6 +194,17 @@ const handleInputChange = (index, value) => { ...@@ -192,6 +194,17 @@ const handleInputChange = (index, value) => {
192 // 只保留第一个有效字符(汉字、数字、大小写字母) 194 // 只保留第一个有效字符(汉字、数字、大小写字母)
193 const validChar = value.match(/[\u4e00-\u9fa5a-zA-Z0-9]/)?.[0] || ''; 195 const validChar = value.match(/[\u4e00-\u9fa5a-zA-Z0-9]/)?.[0] || '';
194 familyMotto.value[index] = validChar; 196 familyMotto.value[index] = validChar;
197 +
198 + // 如果输入了有效字符且不是最后一个输入框,自动聚焦下一个
199 + if (validChar && index < 3) {
200 + focusedIndex.value = index + 1;
201 + // 使用 nextTick 确保 DOM 更新后再聚焦
202 + nextTick(() => {
203 + if (inputRefs.value[index + 1]) {
204 + inputRefs.value[index + 1].focus();
205 + }
206 + });
207 + }
195 }; 208 };
196 209
197 /** 210 /**
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
15 <view 15 <view
16 v-for="(char, index) in mottoChars" 16 v-for="(char, index) in mottoChars"
17 :key="index" 17 :key="index"
18 - class="w-16 h-16 border border-gray-300 rounded-md flex items-center justify-center" 18 + class="w-16 h-16 border border-gray-500 rounded-md flex items-center justify-center"
19 :style="{ 19 :style="{
20 borderColor: focusedIndex === index ? '#3b82f6' : '#d1d5db' 20 borderColor: focusedIndex === index ? '#3b82f6' : '#d1d5db'
21 }" 21 }"
...@@ -29,7 +29,6 @@ ...@@ -29,7 +29,6 @@
29 @focus="focusedIndex = index" 29 @focus="focusedIndex = index"
30 @blur="handleBlur(index)" 30 @blur="handleBlur(index)"
31 class="w-full h-full text-center text-xl bg-transparent outline-none" 31 class="w-full h-full text-center text-xl bg-transparent outline-none"
32 - style="border: none;"
33 /> 32 />
34 </view> 33 </view>
35 </view> 34 </view>
...@@ -89,7 +88,7 @@ ...@@ -89,7 +88,7 @@
89 </template> 88 </template>
90 89
91 <script setup> 90 <script setup>
92 -import { ref, computed } from 'vue'; 91 +import { ref, computed, nextTick } from 'vue';
93 import Taro from '@tarojs/taro'; 92 import Taro from '@tarojs/taro';
94 import { My } from '@nutui/icons-vue-taro'; 93 import { My } from '@nutui/icons-vue-taro';
95 import AppHeader from '../../components/AppHeader.vue'; 94 import AppHeader from '../../components/AppHeader.vue';
...@@ -108,8 +107,13 @@ const handleInputChange = (index, value) => { ...@@ -108,8 +107,13 @@ const handleInputChange = (index, value) => {
108 107
109 // 如果输入了有效字符且不是最后一个输入框,自动聚焦下一个 108 // 如果输入了有效字符且不是最后一个输入框,自动聚焦下一个
110 if (firstChar && index < 3) { 109 if (firstChar && index < 3) {
111 - // Taro中无法直接操作DOM进行focus,这里仅保留逻辑 110 + focusedIndex.value = index + 1;
112 - // 在小程序中,可以通过设置 `focus` 属性来控制 111 + // 使用 nextTick 确保 DOM 更新后再聚焦
112 + nextTick(() => {
113 + if (inputRefs.value[index + 1]) {
114 + inputRefs.value[index + 1].focus();
115 + }
116 + });
113 } 117 }
114 } else { 118 } else {
115 mottoChars.value[index] = ''; 119 mottoChars.value[index] = '';
...@@ -157,7 +161,7 @@ const isComplete = computed(() => { ...@@ -157,7 +161,7 @@ const isComplete = computed(() => {
157 161
158 const handleJoinFamily = () => { 162 const handleJoinFamily = () => {
159 if (isComplete.value) { 163 if (isComplete.value) {
160 - Taro.navigateTo({ 164 + Taro.reLaunch({
161 url: '/pages/Dashboard/index' 165 url: '/pages/Dashboard/index'
162 }); 166 });
163 } 167 }
......