Bladeren bron

refactor(beautify): F 批 TagChip 事件名 tap -> select

- 避免与小程序原生 tap 冒泡重复触发(选中态赋值虽幂等,但事件语义应区隔)
- TagChip 统一 \('select'),4 个消费页改 @select
liaoxg 6 dagen geleden
bovenliggende
commit
e1131fe142

+ 3 - 3
cfc-frontend/components/TagChip.vue

@@ -2,7 +2,7 @@
   <view
     class="tag-chip"
     :class="['tag-chip--' + variant, { 'is-active': active }]"
-    @tap="onTap"
+    @select="onTap"
   >
     <text class="tag-chip__label">{{ label }}</text>
   </view>
@@ -20,7 +20,7 @@
  *   active   — 是否选中
  *   variant  — 'brand'(成长记录页,品牌橙选中态)| 'body'(身维度首页,身体维度色选中态)
  * Events:
- *   tap      — 点击
+ *   select   — 点击(用 select 而非 tap,避免与小程序原生 tap 冒泡重复触发)
  */
 export default {
   name: 'TagChip',
@@ -31,7 +31,7 @@ export default {
   },
   methods: {
     onTap() {
-      this.$emit('tap')
+      this.$emit('select')
     }
   }
 }

+ 13 - 13
cfc-frontend/pages/growth/diet-checkin.vue

@@ -2,7 +2,7 @@
   <view class="page">
     <!-- 顶部导航栏 -->
     <view class="nav-bar">
-      <view class="nav-left" @tap="goBack">
+      <view class="nav-left" @select="goBack">
         <text class="nav-icon">‹</text>
         <text class="nav-title">{{ todayText }}</text>
       </view>
@@ -25,7 +25,7 @@
           <view class="tag-row">
             <TagChip v-for="m in mealTypes" :key="m.value" :label="m.label"
               :active="form.mealType === m.value"
-              @tap="form.mealType = m.value" />
+              @select="form.mealType = m.value" />
           </view>
         </view>
       </view>
@@ -56,13 +56,13 @@
         </view>
         <view class="card-body">
           <view class="media-toolbar">
-            <view class="tool-btn" @tap="choosePhoto">
+            <view class="tool-btn" @select="choosePhoto">
               <text class="tool-icon">📷</text>
               <text class="tool-label">照片</text>
               <text class="tool-count" v-if="form.photos.length > 0">{{ form.photos.length }}/9</text>
             </view>
             <view class="tool-divider"></view>
-            <view class="tool-btn" @tap="toggleRecord">
+            <view class="tool-btn" @select="toggleRecord">
               <text class="tool-icon">🎙</text>
               <text class="tool-label">{{ isRecording ? '录音中…' : (form.voicePath ? '已录制' : '录音') }}</text>
               <text class="tool-count" v-if="isRecording">{{ recordSeconds }}s</text>
@@ -70,7 +70,7 @@
           </view>
           <!-- 照片缩略图 -->
           <view class="photo-strip" v-if="form.photos.length > 0">
-            <view class="photo-item" v-for="(img, idx) in form.photos" :key="getItemKey(img, idx)" @tap="removePhoto(idx)">
+            <view class="photo-item" v-for="(img, idx) in form.photos" :key="getItemKey(img, idx)" @select="removePhoto(idx)">
               <image :src="img" mode="aspectFill" class="photo-img" lazy-load />
               <view class="photo-delete-overlay">
                 <text class="delete-icon">×</text>
@@ -84,8 +84,8 @@
               <view class="wave-bar" v-for="n in 7" :key="n" :style="{animationDelay: (n * 0.1) + 's'}"></view>
             </view>
             <view class="voice-controls">
-              <view class="mini-btn cancel-mini" @tap="cancelRecord"><text>取消</text></view>
-              <view class="mini-btn done-mini" @tap="finishRecord"><text>完成</text></view>
+              <view class="mini-btn cancel-mini" @select="cancelRecord"><text>取消</text></view>
+              <view class="mini-btn done-mini" @select="finishRecord"><text>完成</text></view>
             </view>
           </view>
           <view class="voice-strip" v-else-if="form.voicePath">
@@ -93,14 +93,14 @@
               <text class="play-icon">▶</text>
               <text class="voice-duration">{{ recordDurationText }}</text>
             </view>
-            <view class="delete-voice" @tap="deleteVoice"><text>×</text></view>
+            <view class="delete-voice" @select="deleteVoice"><text>×</text></view>
           </view>
         </view>
       </view>
 
       <!-- 提交按钮 -->
       <view class="submit-wrap">
-        <view class="submit-btn" :class="{ 'submitting': submitting }" @tap="doCheckin">
+        <view class="submit-btn" :class="{ 'submitting': submitting }" @select="doCheckin">
           <text>{{ submitting ? '提交中...' : '✓ 完成打卡' }}</text>
         </view>
       </view>
@@ -131,7 +131,7 @@
     </scroll-view>
 
     <!-- 图片识别结果确认弹窗 -->
-    <view class="recognize-overlay" v-if="showRecognizeModal" @tap="cancelRecognize">
+    <view class="recognize-overlay" v-if="showRecognizeModal" @select="cancelRecognize">
       <view class="recognize-modal" @tap.stop>
         <view class="recognize-header">
           <text class="recognize-title">🍽️ 识别结果</text>
@@ -141,15 +141,15 @@
           <view class="food-chip" v-for="(f, idx) in recognizedFoods" :key="getFoodsKey(f, idx)">
             <text class="food-chip-name">{{ f.name }}</text>
             <text class="food-chip-cat" v-if="f.category && f.category !== 'unknown'">{{ f.category }}</text>
-            <text class="food-chip-del" @tap="removeRecognizedFood(idx)">×</text>
+            <text class="food-chip-del" @select="removeRecognizedFood(idx)">×</text>
           </view>
           <view class="recognize-hint">
             <text>可手动删除不需要的食材,确认后自动填入食物清单</text>
           </view>
         </view>
         <view class="recognize-footer">
-          <view class="btn-cancel" @tap="cancelRecognize"><text>取消</text></view>
-          <view class="btn-confirm" @tap="confirmRecognize"><text>✓ 确认填入</text></view>
+          <view class="btn-cancel" @select="cancelRecognize"><text>取消</text></view>
+          <view class="btn-confirm" @select="confirmRecognize"><text>✓ 确认填入</text></view>
         </view>
       </view>
     </view>

+ 11 - 11
cfc-frontend/pages/growth/exercise-checkin.vue

@@ -2,7 +2,7 @@
   <view class="page">
     <!-- 顶部导航栏 -->
     <view class="nav-bar">
-      <view class="nav-left" @tap="goBack">
+      <view class="nav-left" @select="goBack">
         <text class="nav-icon">‹</text>
         <text class="nav-title">{{ todayText }}</text>
       </view>
@@ -19,7 +19,7 @@
           <view class="tag-row">
             <TagChip v-for="t in exerciseTypes" :key="t.value" :label="t.label"
               :active="form.exerciseType === t.value"
-              @tap="form.exerciseType = t.value" />
+              @select="form.exerciseType = t.value" />
           </view>
         </view>
       </view>
@@ -40,7 +40,7 @@
             <view class="tag-row">
               <TagChip v-for="s in intensityOptions" :key="s.value" :label="s.label"
                 :active="form.intensity === s.value"
-                @tap="form.intensity = s.value" />
+                @select="form.intensity = s.value" />
             </view>
           </view>
           <view class="form-group">
@@ -51,7 +51,7 @@
             <text class="form-label">微信步数(选填)</text>
             <view class="step-sync-row">
               <input class="form-input step-input" type="number" v-model="form.stepCount" placeholder="手动填写步数" />
-              <view class="sync-btn" :class="{'syncing': syncingSteps}" @tap="syncWechatSteps">
+              <view class="sync-btn" :class="{'syncing': syncingSteps}" @select="syncWechatSteps">
                 <text>{{ syncingSteps ? '同步中…' : '同步微信步数' }}</text>
               </view>
             </view>
@@ -72,13 +72,13 @@
         </view>
         <view class="card-body">
           <view class="media-toolbar">
-            <view class="tool-btn" @tap="choosePhoto">
+            <view class="tool-btn" @select="choosePhoto">
               <text class="tool-icon">📷</text>
               <text class="tool-label">照片</text>
               <text class="tool-count" v-if="form.photos.length > 0">{{ form.photos.length }}/9</text>
             </view>
             <view class="tool-divider"></view>
-            <view class="tool-btn" @tap="toggleRecord">
+            <view class="tool-btn" @select="toggleRecord">
               <text class="tool-icon">🎙</text>
               <text class="tool-label">{{ isRecording ? '录音中…' : (form.voicePath ? '已录制' : '录音') }}</text>
               <text class="tool-count" v-if="isRecording">{{ recordSeconds }}s</text>
@@ -86,7 +86,7 @@
           </view>
           <!-- 照片缩略图 -->
           <view class="photo-strip" v-if="form.photos.length > 0">
-            <view class="photo-item" v-for="(img, idx) in form.photos" :key="getItemKey(img, idx)" @tap="removePhoto(idx)">
+            <view class="photo-item" v-for="(img, idx) in form.photos" :key="getItemKey(img, idx)" @select="removePhoto(idx)">
               <image :src="img" mode="aspectFill" class="photo-img" lazy-load />
               <view class="photo-delete-overlay">
                 <text class="delete-icon">×</text>
@@ -100,8 +100,8 @@
               <view class="wave-bar" v-for="n in 7" :key="n" :style="{animationDelay: (n * 0.1) + 's'}"></view>
             </view>
             <view class="voice-controls">
-              <view class="mini-btn cancel-mini" @tap="cancelRecord"><text>取消</text></view>
-              <view class="mini-btn done-mini" @tap="finishRecord"><text>完成</text></view>
+              <view class="mini-btn cancel-mini" @select="cancelRecord"><text>取消</text></view>
+              <view class="mini-btn done-mini" @select="finishRecord"><text>完成</text></view>
             </view>
           </view>
           <view class="voice-strip" v-else-if="form.voicePath">
@@ -109,14 +109,14 @@
               <text class="play-icon">▶</text>
               <text class="voice-duration">{{ recordDurationText }}</text>
             </view>
-            <view class="delete-voice" @tap="deleteVoice"><text>×</text></view>
+            <view class="delete-voice" @select="deleteVoice"><text>×</text></view>
           </view>
         </view>
       </view>
 
       <!-- 提交按钮 -->
       <view class="submit-wrap">
-        <view class="submit-btn" :class="{ 'submitting': submitting }" @tap="doCheckin">
+        <view class="submit-btn" :class="{ 'submitting': submitting }" @select="doCheckin">
           <text>{{ submitting ? '提交中...' : '✓ 完成打卡' }}</text>
         </view>
       </view>

+ 2 - 2
cfc-frontend/pages/health/diet-index.vue

@@ -81,7 +81,7 @@
             <view class="tag-row">
               <TagChip v-for="m in mealTypes" :key="m.value" :label="m.label" variant="body"
                 :active="form.mealType === m.value"
-                @tap="form.mealType = m.value" />
+                @select="form.mealType = m.value" />
             </view>
           </view>
           <view class="form-group">
@@ -96,7 +96,7 @@
             <text class="form-label">备注(选填)</text>
             <input class="form-input" v-model="form.remark" placeholder="记录饮食感受..." />
           </view>
-          <view class="submit-btn" @tap="doCheckin">
+          <view class="submit-btn" @select="doCheckin">
             <text>{{ submitting ? '提交中...' : '提交打卡' }}</text>
           </view>
         </view>

+ 3 - 3
cfc-frontend/pages/health/exercise-index.vue

@@ -73,7 +73,7 @@
             <view class="tag-row">
               <TagChip v-for="t in exerciseTypes" :key="t.value" :label="t.label" variant="body"
                 :active="form.exerciseType === t.value"
-                @tap="form.exerciseType = t.value" />
+                @select="form.exerciseType = t.value" />
             </view>
           </view>
           <view class="form-group">
@@ -85,7 +85,7 @@
             <view class="tag-row">
               <TagChip v-for="s in intensityOptions" :key="s.value" :label="s.label" variant="body"
                 :active="form.intensity === s.value"
-                @tap="form.intensity = s.value" />
+                @select="form.intensity = s.value" />
             </view>
           </view>
           <view class="form-group">
@@ -96,7 +96,7 @@
             <text class="form-label">备注(选填)</text>
             <input class="form-input" v-model="form.remark" placeholder="记录运动感受..." />
           </view>
-          <view class="submit-btn" @tap="doCheckin">
+          <view class="submit-btn" @select="doCheckin">
             <text>{{ submitting ? '提交中...' : '提交打卡' }}</text>
           </view>
         </view>