Procházet zdrojové kódy

fix: 修复移动端相机拍摄第二张图片无法上传

- 相机 input 使用 :key 绑定 cameraKey,每次拍摄后自增强制重建 DOM
- 分离 onCameraChange / onAlbumChange 处理逻辑
- 抽离 uploadFiles 公共方法

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
tanlie před 2 týdny
rodič
revize
391c93eb80
2 změnil soubory, kde provedl 23 přidání a 15 odebrání
  1. 23 15
      wishing-tree-h5/src/components/ImageUploader.vue
  2. binární
      wishing-tree-h5/wish.zip

+ 23 - 15
wishing-tree-h5/src/components/ImageUploader.vue

@@ -1,20 +1,21 @@
 <template>
   <div class="image-uploader">
-    <!-- 持久化隐藏 input,避免移动端动态创建 input 重复点击失效 -->
+    <!-- 持久化隐藏 input,用 key 强制重建,解决移动端相机二次拍摄失效 -->
     <input
+      :key="'camera-' + cameraKey"
       ref="cameraInput"
       type="file"
       accept="image/*"
       capture="environment"
       style="display: none"
-      @change="onFileChange"
+      @change="onCameraChange"
     />
     <input
       ref="albumInput"
       type="file"
       accept="image/*"
       style="display: none"
-      @change="onFileChange"
+      @change="onAlbumChange"
     />
 
     <div class="upload-grid">
@@ -66,8 +67,7 @@ const showAction = ref(false)
 const uploading = ref(false)
 const cameraInput = ref<HTMLInputElement | null>(null)
 const albumInput = ref<HTMLInputElement | null>(null)
-// 记录本次选择的模式,在 onFileChange 中区分
-let currentMode: 'camera' | 'album' = 'album'
+const cameraKey = ref(0)
 
 const actions = [
   { name: 'camera', description: '拍摄照片' },
@@ -86,12 +86,9 @@ function onSelect(action: { name: string }) {
   showAction.value = false
   if (uploading.value) return
 
-  currentMode = action.name as 'camera' | 'album'
-
   if (action.name === 'camera') {
     cameraInput.value?.click()
   } else {
-    // 设置多选
     const input = albumInput.value
     if (input) {
       input.multiple = props.max - props.modelValue.length > 1
@@ -100,21 +97,34 @@ function onSelect(action: { name: string }) {
   }
 }
 
-async function onFileChange(e: Event) {
+async function onCameraChange(e: Event) {
   const input = e.target as HTMLInputElement
   const files = input.files
   if (!files?.length) {
-    // 用户取消,重置 input 以便下次复用
     input.value = ''
     return
   }
+  await uploadFiles(Array.from(files))
+  // 移动端相机 input 需要重建 DOM 才能再次触发
+  cameraKey.value++
+}
 
+async function onAlbumChange(e: Event) {
+  const input = e.target as HTMLInputElement
+  const files = input.files
+  if (!files?.length) {
+    input.value = ''
+    return
+  }
+  await uploadFiles(Array.from(files))
+  input.value = ''
+}
+
+async function uploadFiles(files: File[]) {
   uploading.value = true
   try {
     showToast('上传中...')
-    const compressed = await Promise.all(
-      Array.from(files).map((f) => compressImage(f))
-    )
+    const compressed = await Promise.all(files.map(compressImage))
     const urls = await Promise.all(compressed.map(uploadImage))
     emit('update:modelValue', [...props.modelValue, ...urls])
   } catch (err: any) {
@@ -123,8 +133,6 @@ async function onFileChange(e: Event) {
     }
   } finally {
     uploading.value = false
-    // 重置 input,否则重复选同一文件不会触发 change
-    input.value = ''
   }
 }
 </script>

binární
wishing-tree-h5/wish.zip