Эх сурвалжийг харах

fix(health): 修复小程序健康报告列表点详情崩溃(MP 内联事件传对象导致 undefined)

根因:report-list.vue 在 v-for 内将整个 item 对象作为内联事件参数传给 onTouchStart/onRowClick 等处理方法,
微信小程序运行时该参数解析为 undefined,触发 Cannot read properties of undefined (reading 'id'),
报告列表无法进入详情。H5 正常,仅 MP 端复现。

修复:模板内联事件改传基本类型 id / reportType / subjectId,同步调整 7 个处理方法签名
(onRowClick / onTouchStart / adjustBinding / confirmDelete / doDelete / approveTransfer /
denyTransfer / selectMemberAdjust)。模板 :class/:style/:key 的 item.x 绑定不受影响,保持原样。

验证:
- scripts/verify-vue-compile.js report-list.vue → PASS(模板/样式/脚本)
- scripts/audit-mp-antipatterns.js --error-only → ERROR 0(含全站回归扫描)
- npm run build:mp-weixin → DONE exit 0;编译后 wxml 确认各 handler 改为从列表数据提取基本字段
  (onRowClick: item.m10,'id' + item.m11,'reportType' 等),不再传递整个对象
Agnes Agent 2 долоо хоног өмнө
parent
commit
cd256838cc

+ 30 - 30
cfc-frontend/pages/health/report-list.vue

@@ -23,8 +23,8 @@
           <text class="transfer-meta">申请时间:{{ formatDateTime(item.createdAt) }}</text>
           <text class="transfer-meta">申请时间:{{ formatDateTime(item.createdAt) }}</text>
         </view>
         </view>
         <view class="transfer-actions">
         <view class="transfer-actions">
-          <view class="transfer-btn transfer-deny" @click.stop="denyTransfer(item)">拒绝</view>
-          <view class="transfer-btn transfer-approve" @click.stop="approveTransfer(item)">同意</view>
+          <view class="transfer-btn transfer-deny" @click.stop="denyTransfer(item.id)">拒绝</view>
+          <view class="transfer-btn transfer-approve" @click.stop="approveTransfer(item.id)">同意</view>
         </view>
         </view>
       </view>
       </view>
       <!-- 本家庭发起的申请 -->
       <!-- 本家庭发起的申请 -->
@@ -61,17 +61,17 @@
       <view class="swipe-row" v-for="item in reports" :key="getReportKey(item)">
       <view class="swipe-row" v-for="item in reports" :key="getReportKey(item)">
         <!-- 右侧操作按钮(左滑后露出:删除 + 调整归属);DAN 报告不可左右滑动删除 -->
         <!-- 右侧操作按钮(左滑后露出:删除 + 调整归属);DAN 报告不可左右滑动删除 -->
         <view class="swipe-actions" v-if="item.reportType !== 'dan'">
         <view class="swipe-actions" v-if="item.reportType !== 'dan'">
-          <view class="swipe-delete" @click.stop="confirmDelete(item)">删除</view>
-          <view class="swipe-adjust" @click.stop="adjustBinding(item)">调整归属</view>
+          <view class="swipe-delete" @click.stop="confirmDelete(item.id)">删除</view>
+          <view class="swipe-adjust" @click.stop="adjustBinding(item.id, item.subjectId)">调整归属</view>
         </view>
         </view>
         <!-- 卡片内容(可左滑) -->
         <!-- 卡片内容(可左滑) -->
         <view class="swipe-content"
         <view class="swipe-content"
               :class="{ 'swipe-moving': curId === item.id }"
               :class="{ 'swipe-moving': curId === item.id }"
               :style="'transform: translateX(' + (curId === item.id ? moveOffset : (openMap[item.id] ? -160 : 0)) + 'px)'"
               :style="'transform: translateX(' + (curId === item.id ? moveOffset : (openMap[item.id] ? -160 : 0)) + 'px)'"
-              @touchstart="onTouchStart($event, item)"
+              @touchstart="onTouchStart($event, item.id, item.reportType)"
               @touchmove="onTouchMove"
               @touchmove="onTouchMove"
               @touchend="onTouchEnd"
               @touchend="onTouchEnd"
-              @click="onRowClick(item)">
+              @click="onRowClick(item.id, item.reportType)">
           <view class="report-card">
           <view class="report-card">
             <view class="report-card-left">
             <view class="report-card-left">
               <view class="report-type-badge" :class="'badge-' + (item.reportType === 'gut_flora' ? 'gut' : item.reportType === 'tongue' ? 'tongue' : item.reportType === 'dan' ? 'dan' : 'exam')">
               <view class="report-type-badge" :class="'badge-' + (item.reportType === 'gut_flora' ? 'gut' : item.reportType === 'tongue' ? 'tongue' : item.reportType === 'dan' ? 'dan' : 'exam')">
@@ -122,7 +122,7 @@
                 v-for="member in adjustMembers"
                 v-for="member in adjustMembers"
                 :key="member.id"
                 :key="member.id"
                 :class="{ 'chip-active': selectedAdjustMemberId === member._filterId }"
                 :class="{ 'chip-active': selectedAdjustMemberId === member._filterId }"
-                @click="selectMemberAdjust(member)"
+                @click="selectMemberAdjust(member.id)"
               >
               >
                 <text class="chip-text">{{ member.nickname || '成员' }}</text>
                 <text class="chip-text">{{ member.nickname || '成员' }}</text>
               </view>
               </view>
@@ -136,7 +136,7 @@
             class="member-item"
             class="member-item"
             v-for="(member, mIdx) in adjustMembers"
             v-for="(member, mIdx) in adjustMembers"
             :key="mIdx"
             :key="mIdx"
-            @click="selectMemberAdjust(member)"
+            @click="selectMemberAdjust(member.id)"
           >
           >
             <text class="member-avatar">{{ (member.nickname || '?').substring(0, 1) }}</text>
             <text class="member-avatar">{{ (member.nickname || '?').substring(0, 1) }}</text>
             <text class="member-name">{{ member.nickname || '未知' }}</text>
             <text class="member-name">{{ member.nickname || '未知' }}</text>
@@ -232,13 +232,13 @@ export default {
     getReportKey(item) {
     getReportKey(item) {
       return item.reportType + '-' + item.id
       return item.reportType + '-' + item.id
     },
     },
-    adjustBinding(item) {
+    adjustBinding(id, subjectId) {
       var self = this
       var self = this
       // 显示成员选择面板
       // 显示成员选择面板
       self.showAdjustPanel = true
       self.showAdjustPanel = true
-      self.adjustReportId = item.id
+      self.adjustReportId = id
       // 记录当前归属成员ID(用于判断是否显示"取消归属"选项)
       // 记录当前归属成员ID(用于判断是否显示"取消归属"选项)
-      self.adjustCurrentMemberId = item.subjectId
+      self.adjustCurrentMemberId = subjectId
       // 使用已加载的成员列表
       // 使用已加载的成员列表
       self.adjustMembers = self.members
       self.adjustMembers = self.members
       self.selectedAdjustMemberId = null
       self.selectedAdjustMemberId = null
@@ -344,11 +344,11 @@ export default {
       this.selectedMemberId = filterId
       this.selectedMemberId = filterId
       this.loadData()
       this.loadData()
     },
     },
-    selectMemberAdjust(member) {
+    selectMemberAdjust(memberId) {
       var self = this
       var self = this
       self.showAdjustPanel = false
       self.showAdjustPanel = false
       // 调用后端接口修改归属
       // 调用后端接口修改归属
-      reassignReport(self.adjustReportId, member.id).then(function(res) {
+      reassignReport(self.adjustReportId, memberId).then(function(res) {
         if (res.code === 200) {
         if (res.code === 200) {
           uni.showToast({ title: '归属修改成功', icon: 'success' })
           uni.showToast({ title: '归属修改成功', icon: 'success' })
           self.loadData()
           self.loadData()
@@ -390,7 +390,7 @@ export default {
       if (status === 'denied') return '对方已拒绝'
       if (status === 'denied') return '对方已拒绝'
       return '等待对方同意'
       return '等待对方同意'
     },
     },
-    approveTransfer(item) {
+    approveTransfer(id) {
       var self = this
       var self = this
       uni.showModal({
       uni.showModal({
         title: '同意转移',
         title: '同意转移',
@@ -398,7 +398,7 @@ export default {
         confirmColor: BrandColors.elementDanger,
         confirmColor: BrandColors.elementDanger,
         success: function(res) {
         success: function(res) {
           if (!res.confirm) return
           if (!res.confirm) return
-          approveReportTransfer(item.id).then(function(r) {
+          approveReportTransfer(id).then(function(r) {
             if (r && r.code === 200) {
             if (r && r.code === 200) {
               uni.showToast({ title: '已同意,报告已转入对方家庭', icon: 'none' })
               uni.showToast({ title: '已同意,报告已转入对方家庭', icon: 'none' })
               self.loadTransferRequests()
               self.loadTransferRequests()
@@ -412,14 +412,14 @@ export default {
         }
         }
       })
       })
     },
     },
-    denyTransfer(item) {
+    denyTransfer(id) {
       var self = this
       var self = this
       uni.showModal({
       uni.showModal({
         title: '拒绝转移',
         title: '拒绝转移',
         content: '拒绝后该报告继续留在您的家庭。',
         content: '拒绝后该报告继续留在您的家庭。',
         success: function(res) {
         success: function(res) {
           if (!res.confirm) return
           if (!res.confirm) return
-          denyReportTransfer(item.id, '').then(function(r) {
+          denyReportTransfer(id, '').then(function(r) {
             if (r && r.code === 200) {
             if (r && r.code === 200) {
               uni.showToast({ title: '已拒绝', icon: 'none' })
               uni.showToast({ title: '已拒绝', icon: 'none' })
               self.loadTransferRequests()
               self.loadTransferRequests()
@@ -458,36 +458,36 @@ export default {
  		}
  		}
  		uni.navigateTo({ url: url })
  		uni.navigateTo({ url: url })
  	},
  	},
-    onRowClick(item) {
+    onRowClick(id, reportType) {
       // 刚滑动过,忽略本次点击
       // 刚滑动过,忽略本次点击
       if (this.touchDidMove) {
       if (this.touchDidMove) {
         this.touchDidMove = false
         this.touchDidMove = false
         return
         return
       }
       }
       // 行处于打开态,点击先收起
       // 行处于打开态,点击先收起
-      if (this.openMap[item.id]) {
-        this.$set(this.openMap, item.id, false)
+      if (this.openMap[id]) {
+        this.$set(this.openMap, id, false)
         return
         return
       }
       }
-      this.goToDetail(item.id, item.reportType)
+      this.goToDetail(id, reportType)
     },
     },
-    onTouchStart(e, item) {
+    onTouchStart(e, id, reportType) {
       // DAN 报告无删除/调整归属能力,禁止左滑
       // DAN 报告无删除/调整归属能力,禁止左滑
-      if (item && item.reportType === 'dan') {
+      if (id != null && reportType === 'dan') {
         this.curId = null
         this.curId = null
         return
         return
       }
       }
 
 
       // 先收起其它已打开行
       // 先收起其它已打开行
-      if (this.curId !== null && this.curId !== item.id && this.openMap[this.curId]) {
+      if (this.curId !== null && this.curId !== id && this.openMap[this.curId]) {
         this.$set(this.openMap, this.curId, false)
         this.$set(this.openMap, this.curId, false)
       }
       }
       var touch = e.touches[0]
       var touch = e.touches[0]
-      this.curId = item.id
+      this.curId = id
       this.startX = touch.clientX
       this.startX = touch.clientX
       this.startY = touch.clientY
       this.startY = touch.clientY
       this.touchDidMove = false
       this.touchDidMove = false
-      this.baseOffset = this.openMap[item.id] ? -160 : 0
+      this.baseOffset = this.openMap[id] ? -160 : 0
       this.moveOffset = this.baseOffset
       this.moveOffset = this.baseOffset
     },
     },
     onTouchMove(e) {
     onTouchMove(e) {
@@ -515,7 +515,7 @@ export default {
     goToUpload() {
     goToUpload() {
       uni.navigateTo({ url: '/pages/health/report-upload' })
       uni.navigateTo({ url: '/pages/health/report-upload' })
     },
     },
-    confirmDelete(item) {
+    confirmDelete(id) {
       var self = this
       var self = this
       uni.showModal({
       uni.showModal({
         title: '删除报告',
         title: '删除报告',
@@ -523,13 +523,13 @@ export default {
         confirmColor: BrandColors.elementDanger,
         confirmColor: BrandColors.elementDanger,
         success: function(res) {
         success: function(res) {
           if (!res.confirm) return
           if (!res.confirm) return
-          self.doDelete(item)
+          self.doDelete(id)
         }
         }
       })
       })
     },
     },
-    doDelete(item) {
+    doDelete(id) {
       var self = this
       var self = this
-      deleteReport(item.id).then(function(res) {
+      deleteReport(id).then(function(res) {
         if (res.code === 200) {
         if (res.code === 200) {
           uni.showToast({ title: '已删除', icon: 'success' })
           uni.showToast({ title: '已删除', icon: 'success' })
           self.loadData()
           self.loadData()