Просмотр исходного кода

fix(health): 健康报告列表删除按钮改为左滑出现,修复未注册组件导致按钮显示在行上方

liaoxg 2 недель назад
Родитель
Сommit
ccc032e5ea
1 измененных файлов с 128 добавлено и 50 удалено
  1. 128 50
      cfc-frontend/pages/health/report-list.vue

+ 128 - 50
cfc-frontend/pages/health/report-list.vue

@@ -27,25 +27,35 @@
 
 
     <!-- 报告列表 -->
     <!-- 报告列表 -->
     <view class="report-list" v-else-if="reports.length > 0">
     <view class="report-list" v-else-if="reports.length > 0">
-      <swipe-action v-for="item in reports" :key="item.id">
-        <view class="report-card" @click="goToDetail(item.id, item.reportType)">
-          <view class="report-card-left">
-            <view class="report-type-badge" :class="'badge-' + (item.reportType === 'gut_flora' ? 'gut' : item.reportType === 'tongue' ? 'tongue' : 'exam')">
-              <text>{{ item.reportType === 'gut_flora' ? '肠道检测' : item.reportType === 'tongue' ? '舌诊' : '体检报告' }}</text>
+      <view class="swipe-row" v-for="item in reports" :key="item.id">
+        <!-- 右侧删除按钮(滑动后露出) -->
+        <view class="swipe-actions">
+          <view class="swipe-delete" @click.stop="confirmDelete(item)">删除</view>
+        </view>
+        <!-- 卡片内容(可左滑) -->
+        <view class="swipe-content"
+              :class="{ 'swipe-moving': curId === item.id }"
+              :style="'transform: translateX(' + (curId === item.id ? moveOffset : (openMap[item.id] ? -80 : 0)) + 'px)'"
+              @touchstart="onTouchStart($event, item)"
+              @touchmove="onTouchMove"
+              @touchend="onTouchEnd"
+              @click="onRowClick(item)">
+          <view class="report-card">
+            <view class="report-card-left">
+              <view class="report-type-badge" :class="'badge-' + (item.reportType === 'gut_flora' ? 'gut' : item.reportType === 'tongue' ? 'tongue' : 'exam')">
+                <text>{{ item.reportType === 'gut_flora' ? '肠道检测' : item.reportType === 'tongue' ? '舌诊' : '体检报告' }}</text>
+              </view>
+              <text class="report-person" v-if="item.personName">{{ item.personName }}</text>
+              <text class="report-date">报告日期:{{ formatDate(item.reportDate) }}</text>
+              <text class="report-upload-date">上传日期:{{ formatDate(item.createdAt) }}</text>
+            </view>
+            <view class="report-card-right">
+              <text class="report-score">{{ item.overallScore || '--' }}<text class="score-unit">分</text></text>
+              <text class="report-arrow">›</text>
             </view>
             </view>
-            <text class="report-person" v-if="item.personName">{{ item.personName }}</text>
-            <text class="report-date">报告日期:{{ formatDate(item.reportDate) }}</text>
-            <text class="report-upload-date">上传日期:{{ formatDate(item.createdAt) }}</text>
-          </view>
-          <view class="report-card-right">
-            <text class="report-score">{{ item.overallScore || '--' }}<text class="score-unit">分</text></text>
-            <text class="report-arrow">›</text>
           </view>
           </view>
         </view>
         </view>
-        <template #right>
-          <button class="swipe-delete" @click.stop="confirmDelete(item)">删除</button>
-        </template>
-      </swipe-action>
+      </view>
     </view>
     </view>
 
 
     <!-- 空状态 -->
     <!-- 空状态 -->
@@ -72,7 +82,15 @@ export default {
       members: [],
       members: [],
       selectedMemberId: null,
       selectedMemberId: null,
       loading: false,
       loading: false,
-      memberId: null
+      memberId: null,
+      // 左滑删除
+      openMap: {},
+      curId: null,
+      moveOffset: 0,
+      startX: 0,
+      startY: 0,
+      touchDidMove: false,
+      baseOffset: 0
     }
     }
   },
   },
   onLoad(options) {
   onLoad(options) {
@@ -128,16 +146,64 @@ export default {
       })
       })
     },
     },
     goToDetail(reportId, reportType) {
     goToDetail(reportId, reportType) {
-		var url
-		if (reportType === 'gut_flora') {
-			url = '/pages/health/gut-flora-detail?reportId=' + reportId
-		} else if (reportType === 'dan') {
-			url = '/pages/dan-assessment/report-result?reportId=' + reportId
-		} else {
-			url = '/pages/health/report-detail?reportType=' + (reportType || 'gut_flora') + '&reportId=' + reportId
-		}
-		uni.navigateTo({ url: url })
-	},
+ 		var url
+ 		if (reportType === 'gut_flora') {
+ 			url = '/pages/health/gut-flora-detail?reportId=' + reportId
+ 		} else if (reportType === 'dan') {
+ 			url = '/pages/dan-assessment/report-result?reportId=' + reportId
+ 		} else {
+ 			url = '/pages/health/report-detail?reportType=' + (reportType || 'gut_flora') + '&reportId=' + reportId
+ 		}
+ 		uni.navigateTo({ url: url })
+ 	},
+    onRowClick(item) {
+      // 刚滑动过,忽略本次点击
+      if (this.touchDidMove) {
+        this.touchDidMove = false
+        return
+      }
+      // 行处于打开态,点击先收起
+      if (this.openMap[item.id]) {
+        this.$set(this.openMap, item.id, false)
+        return
+      }
+      this.goToDetail(item.id, item.reportType)
+    },
+    onTouchStart(e, item) {
+      // 先收起其它已打开行
+      if (this.curId !== null && this.curId !== item.id && this.openMap[this.curId]) {
+        this.$set(this.openMap, this.curId, false)
+      }
+      var touch = e.touches[0]
+      this.curId = item.id
+      this.startX = touch.clientX
+      this.startY = touch.clientY
+      this.touchDidMove = false
+      this.baseOffset = this.openMap[item.id] ? -80 : 0
+      this.moveOffset = this.baseOffset
+    },
+    onTouchMove(e) {
+      if (this.curId === null) return
+      var touch = e.touches[0]
+      var dx = touch.clientX - this.startX
+      var dy = touch.clientY - this.startY
+      // 横向滑动(水平分量大于垂直分量)
+      if (Math.abs(dx) > Math.abs(dy)) {
+        this.touchDidMove = Math.abs(dx) > 10
+        var offset = this.baseOffset + dx
+        if (offset < -80) offset = -80
+        if (offset > 0) offset = 0
+        this.moveOffset = offset
+      }
+    },
+    onTouchEnd() {
+      if (this.curId === null) return
+      // 位移超过阈值则打开,否则收起
+      var shouldOpen = this.moveOffset < -20
+      this.$set(this.openMap, this.curId, shouldOpen)
+      this.moveOffset = shouldOpen ? -80 : 0
+      this.curId = null
+    },
     goToUpload() {
     goToUpload() {
       uni.navigateTo({ url: '/pages/health/report-upload' })
       uni.navigateTo({ url: '/pages/health/report-upload' })
     },
     },
@@ -234,16 +300,47 @@ export default {
 .report-list {
 .report-list {
   margin: 20rpx 30rpx;
   margin: 20rpx 30rpx;
 }
 }
-.report-card {
-  background: #fff;
+.swipe-row {
+  position: relative;
+  overflow: hidden;
   border-radius: 16rpx;
   border-radius: 16rpx;
-  padding: 28rpx 24rpx;
   margin-bottom: 16rpx;
   margin-bottom: 16rpx;
+  box-shadow: 0 2rpx 8rpx rgba(0,0,0,0.04);
+}
+.swipe-actions {
+  position: absolute;
+  top: 0;
+  right: 0;
+  height: 100%;
+  display: flex;
+  flex-direction: row;
+}
+.swipe-delete {
+  width: 80px;
+  height: 100%;
+  background: #F56C6C;
+  color: #fff;
+  font-size: 28rpx;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+}
+.swipe-content {
+  position: relative;
+  z-index: 2;
+  background: #fff;
+  transition: transform 0.25s ease;
+}
+.swipe-moving {
+  transition: none;
+}
+.report-card {
+  border-radius: 0;
+  padding: 28rpx 24rpx;
   display: flex;
   display: flex;
   flex-direction: row;
   flex-direction: row;
   align-items: center;
   align-items: center;
   justify-content: space-between;
   justify-content: space-between;
-  box-shadow: 0 2rpx 8rpx rgba(0,0,0,0.04);
 }
 }
 .report-card:active {
 .report-card:active {
   opacity: 0.8;
   opacity: 0.8;
@@ -346,25 +443,6 @@ export default {
   opacity: 0.8;
   opacity: 0.8;
 }
 }
 
 
-/* ===== 滑动删除 ===== */
-.swipe-delete {
-  height: 100%;
-  width: 160rpx;
-  background: #F56C6C;
-  color: #fff;
-  font-size: 28rpx;
-  border: none;
-  border-radius: 0;
-}
-
-/* swipe-action 组件内部样式覆盖 */
-/deep/ .uni-swipe-action__content {
-  border-radius: 16rpx;
-}
-/deep/ .uni-swipe-action__button {
-  border-radius: 0 16rpx 16rpx 0;
-}
-
 /* ===== 底部 ===== */
 /* ===== 底部 ===== */
 .bottom-spacer {
 .bottom-spacer {
   height: 60rpx;
   height: 60rpx;