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

fix: FamilyRelationGraph 齿轮/+号/高度自适应被误回退,重新实现

修复 merge 冲突提交 fc27e606 意外回退了 b00b345a 的功能:右上角齿轮跳转成员管理、触摸自身节点显示+号进入添加成员页、高度按成员数自适应
openhands 3 месяцев назад
Родитель
Сommit
4e0d886be8
1 измененных файлов с 116 добавлено и 15 удалено
  1. 116 15
      cfc-frontend/components/FamilyRelationGraph.vue

+ 116 - 15
cfc-frontend/components/FamilyRelationGraph.vue

@@ -1,6 +1,10 @@
 <template>
   <!-- 全 Canvas 关系图谱 - Force-directed 物理布局 -->
-  <view class="family-graph-wrapper" v-if="members && members.length >= 1">
+  <view class="family-graph-wrapper" v-if="members && members.length >= 1" :style="{ minHeight: canvasHeight + 'px' }">
+    <!-- 右上角小齿轮 → 成员管理 -->
+    <view class="gear-icon" @click="onManageTap" @tap.stop="onManageTap">
+      <text class="gear-text">⚙</text>
+    </view>
     <canvas
       class="family-graph-canvas"
       canvas-id="forceGraphCanvas"
@@ -10,6 +14,10 @@
       @touchstart="onTouchStart"
       @touchmove="onTouchMove"
       @touchend="onTouchEnd" />
+    <!-- + 添加成员提示(触摸自身节点时显示) -->
+    <view class="add-hint" :class="{ 'add-hint-visible': touchingSelf }" :style="addHintPosition">
+      <text class="add-hint-text">+</text>
+    </view>
   </view>
   <!-- 空状态 -->
   <view class="family-graph-empty" v-else-if="members && members.length === 0">
@@ -71,9 +79,6 @@ export default {
       canvasHeight: 280,
       dpr: 1,
 
-      // 物理模拟节点
-      simNodes: [],
-
       // 物理参数
       physics: {
         repulsion: 800,      // 节点间斥力强度
@@ -89,6 +94,13 @@ export default {
       dragging: null,         // { nodeIndex, offsetX, offsetY }
       dragStartPos: null,    // 用于判断是否真的拖拽了
 
+      // 触摸/悬停状态(显示 + 号)
+      touchingSelf: false,
+      hoveringSelf: false,
+
+      // 是否 PC 环境(h5 编译)
+      isPC: false,
+
       // 动画
       animFrameId: null,
       isSimulating: false,
@@ -108,6 +120,16 @@ export default {
       return this.themeColors[this.dimensionCode] || '#8D6E63'
     },
 
+    // + 提示位置(跟随中心节点偏移)
+    addHintPosition: function() {
+      var selfNode = this.nodeData.find(function(n) { return n.isSelf })
+      if (!selfNode) return {}
+      return {
+        left: (selfNode.x + selfNode.radius * 0.7) + 'px',
+        top: (selfNode.y - selfNode.radius * 0.5) + 'px'
+      }
+    },
+
     // 将 members 转换为 simNodes
     nodeData: function() {
       var self = this
@@ -546,6 +568,7 @@ export default {
       var touch = e.touches ? e.touches[0] : e.detail
       if (!touch) return
 
+      var self = this
       var rect = {}
       var query = uni.createSelectorQuery().in(this)
       query.select('#forceGraphCanvas').boundingClientRect()
@@ -556,16 +579,21 @@ export default {
           var y = touch.clientY - rect.top
           var node = self.getTouchNode(x, y)
           if (node) {
-            self.dragging = {
-              node: node,
-              offsetX: x - node.x,
-              offsetY: y - node.y
+            if (node.isSelf) {
+              // 自身节点 → 显示 + 号
+              self.touchingSelf = true
+            } else {
+              // 其他节点 → 拖拽
+              self.dragging = {
+                node: node,
+                offsetX: x - node.x,
+                offsetY: y - node.y
+              }
+              self.dragStartPos = { x: x, y: y }
+              node.fx = node.x
+              node.fy = node.y
+              node.fixed = true
             }
-            self.dragStartPos = { x: x, y: y }
-            // 固定节点
-            node.fx = node.x
-            node.fy = node.y
-            node.fixed = true
           }
         }
       }.bind(this))
@@ -597,6 +625,18 @@ export default {
     },
 
     onTouchEnd: function(e) {
+      // 如果正在触摸自身节点 → 跳转添加成员
+      if (this.touchingSelf) {
+        this.touchingSelf = false
+        if (this.interactive) {
+          this.$emit('addMemberTap')
+          this.goAddMember()
+        }
+        this.dragging = null
+        this.dragStartPos = null
+        return
+      }
+
       if (!this.dragging) return
 
       var wasDragged = this.dragStartPos && (
@@ -622,6 +662,20 @@ export default {
       this.dragStartPos = null
     },
 
+    // 跳转到添加成员页面
+    goAddMember: function() {
+      uni.navigateTo({
+        url: '/pages/family/add-member'
+      })
+    },
+
+    // 点击右上角小齿轮 → 跳转成员管理页
+    onManageTap: function() {
+      uni.navigateTo({
+        url: '/pages/profile/family-members'
+      })
+    },
+
     // ===== 工具方法 =====
 
     getEnergy: function(memberId) {
@@ -644,11 +698,12 @@ export default {
 
     updateCanvasSize: function() {
       var self = this
+      var cnt = this.members ? this.members.length : 0
+      self.canvasHeight = Math.max(200, cnt * 90)
       var query = uni.createSelectorQuery().in(this)
       query.select('.family-graph-wrapper').boundingClientRect(function(rect) {
         if (rect) {
           self.canvasWidth = rect.width || 340
-          self.canvasHeight = rect.height || 280
         }
       }).exec()
     }
@@ -660,7 +715,8 @@ export default {
 .family-graph-wrapper {
   position: relative;
   width: 100%;
-  height: 280px;
+  min-height: 200px;
+  height: auto;
   margin: 10rpx 0;
   background: #FFFFFF;
   border-radius: 24rpx;
@@ -672,6 +728,51 @@ export default {
   left: 0;
   z-index: 1;
 }
+/* 右上角小齿轮 */
+.gear-icon {
+  position: absolute;
+  top: 12rpx;
+  right: 12rpx;
+  z-index: 10;
+  width: 56rpx;
+  height: 56rpx;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  background: rgba(255, 255, 255, 0.9);
+  border-radius: 50%;
+  box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
+}
+.gear-text {
+  font-size: 32rpx;
+  color: #94A3B8;
+}
+/* + 添加成员提示 */
+.add-hint {
+  position: absolute;
+  z-index: 5;
+  width: 40rpx;
+  height: 40rpx;
+  border-radius: 50%;
+  background: #10B981;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  opacity: 0;
+  transform: scale(0.5);
+  transition: opacity 0.15s, transform 0.15s;
+  pointer-events: none;
+}
+.add-hint.add-hint-visible {
+  opacity: 1;
+  transform: scale(1);
+}
+.add-hint-text {
+  font-size: 28rpx;
+  color: #FFFFFF;
+  font-weight: bold;
+  line-height: 1;
+}
 .family-graph-empty {
   display: flex;
   align-items: center;