进度条及tab框修改
This commit is contained in:
		
							parent
							
								
									5d2ab9b9e4
								
							
						
					
					
						commit
						4f1dccacc8
					
				| 
						 | 
				
			
			@ -54,7 +54,7 @@
 | 
			
		|||
        <div class="timeline-container">
 | 
			
		||||
          <!-- 时间开始标签 -->
 | 
			
		||||
          <span class="time-label">2023.10.07 00:00:00</span>
 | 
			
		||||
          <div class="timeline-track">
 | 
			
		||||
          <div class="timeline-track" :style="trackStyle">
 | 
			
		||||
            <div
 | 
			
		||||
              v-for="point in store.timePoints"
 | 
			
		||||
              :key="point.id"
 | 
			
		||||
| 
						 | 
				
			
			@ -100,7 +100,7 @@
 | 
			
		|||
import { ref, defineExpose } from 'vue';
 | 
			
		||||
import { useKeyNodeStore1 } from '@/store/keyNodeStore1';
 | 
			
		||||
import DynamicGraph from "./graph/dynamicGraph.vue";
 | 
			
		||||
import { watch } from 'vue'
 | 
			
		||||
import { watch, computed } from 'vue'
 | 
			
		||||
 | 
			
		||||
const store = useKeyNodeStore1();
 | 
			
		||||
const leaderGraphRef = ref(null);
 | 
			
		||||
| 
						 | 
				
			
			@ -171,6 +171,15 @@ watch(
 | 
			
		|||
  { immediate: true, deep: true }
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
// 计算时间轴轨道样式
 | 
			
		||||
const trackStyle = computed(() => {
 | 
			
		||||
  if (!store.activeTimePoint) return {};
 | 
			
		||||
  const activePosition = pointPositions.value[store.activeTimePoint] || 0;
 | 
			
		||||
  return {
 | 
			
		||||
    background: `linear-gradient(90deg, #3B7699 0%, #00F3FF ${activePosition}%, #3B7699 ${activePosition}%, #3B7699 100%)`
 | 
			
		||||
  };
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
defineExpose({ highlightNode });
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -227,7 +236,8 @@ defineExpose({ highlightNode });
 | 
			
		|||
.timeline-track {
 | 
			
		||||
  flex-grow: 1;
 | 
			
		||||
  height: 4px;
 | 
			
		||||
  background: linear-gradient(90deg, #1b62a9, #3aa1f8, #1b62a9);
 | 
			
		||||
  /* background: linear-gradient(90deg, #1b62a9, #3aa1f8, #1b62a9); */
 | 
			
		||||
  /* background-color:  #3B7699; */
 | 
			
		||||
  margin: 0 15px;
 | 
			
		||||
  position: relative;
 | 
			
		||||
  display: flex;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,34 +3,45 @@
 | 
			
		|||
    <img
 | 
			
		||||
      src="../../../assets/images/leaderTitle.png"
 | 
			
		||||
      alt=""
 | 
			
		||||
      class="headerImage"
 | 
			
		||||
      style="margin-top: -22px; margin-left: -15px"
 | 
			
		||||
    />
 | 
			
		||||
    <div class="tabs">
 | 
			
		||||
      <button
 | 
			
		||||
        v-for="tab in tabs"
 | 
			
		||||
        :key="tab"
 | 
			
		||||
        :class="{ active: activeTab === tab }"
 | 
			
		||||
        @click="activeTab = tab"
 | 
			
		||||
      >
 | 
			
		||||
        {{ tab }}
 | 
			
		||||
      </button>
 | 
			
		||||
      <div class="tabs-switch">
 | 
			
		||||
        <div
 | 
			
		||||
          class="switch-item"
 | 
			
		||||
          v-for="tab in tabs"
 | 
			
		||||
          :key="tab"
 | 
			
		||||
          @click="activeTab = tab"
 | 
			
		||||
          :class="{ 'tabsSwich-active': activeTab === tab }"
 | 
			
		||||
        >
 | 
			
		||||
          {{ tab }}
 | 
			
		||||
        </div>
 | 
			
		||||
      </div>
 | 
			
		||||
    </div>
 | 
			
		||||
    <div class="leader-list" ref="leaderListRef">
 | 
			
		||||
      <div
 | 
			
		||||
        v-for="leader in filteredVisibleLeaders"
 | 
			
		||||
        v-for="(leader, index) in filteredVisibleLeaders"
 | 
			
		||||
        :key="leader.id"
 | 
			
		||||
        class="leader-item"
 | 
			
		||||
        @click="emit('selectLeader', leader)"
 | 
			
		||||
      >
 | 
			
		||||
        <div class="order">{{ index + 1 }}</div>
 | 
			
		||||
        <img :src="leader.avatar" :alt="leader.name" class="avatar" />
 | 
			
		||||
        <div class="info">
 | 
			
		||||
          <div class="name">
 | 
			
		||||
        <div class="user-info">
 | 
			
		||||
          <div class="username">
 | 
			
		||||
            <span class="en-name">{{ leader.name }}</span>
 | 
			
		||||
            <span v-if="leader.chineseName" class="cn-name">{{ leader.chineseName }}</span>
 | 
			
		||||
            <span v-if="leader.chineseName" class="cn-name">({{ leader.chineseName }})</span>
 | 
			
		||||
          </div>
 | 
			
		||||
          <div class="stats">
 | 
			
		||||
            <span>粉丝数量: {{ leader.followers }}</span>
 | 
			
		||||
            <span>发帖总数: {{ leader.posts }}</span>
 | 
			
		||||
          <div class="userState">
 | 
			
		||||
            <div class="userState-fancy">
 | 
			
		||||
              粉丝数:
 | 
			
		||||
              <p>{{ leader.followers }}</p>
 | 
			
		||||
            </div>
 | 
			
		||||
            <div class="userState-monitor-count">
 | 
			
		||||
              发帖数:
 | 
			
		||||
              <p>{{ leader.posts }}</p>
 | 
			
		||||
            </div>
 | 
			
		||||
          </div>
 | 
			
		||||
        </div>
 | 
			
		||||
      </div>
 | 
			
		||||
| 
						 | 
				
			
			@ -67,7 +78,7 @@ watch(filteredVisibleLeaders, async () => {
 | 
			
		|||
}, { deep: true });
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<style scoped>
 | 
			
		||||
<style scoped lang="less">
 | 
			
		||||
.left-panel {
 | 
			
		||||
  width: 350px;
 | 
			
		||||
  flex-shrink: 0;
 | 
			
		||||
| 
						 | 
				
			
			@ -76,89 +87,117 @@ watch(filteredVisibleLeaders, async () => {
 | 
			
		|||
  display: flex;
 | 
			
		||||
  flex-direction: column;
 | 
			
		||||
  padding: 15px;
 | 
			
		||||
  height: 100%;
 | 
			
		||||
}
 | 
			
		||||
.tabs {
 | 
			
		||||
  display: flex;
 | 
			
		||||
  margin-bottom: 15px;
 | 
			
		||||
  border-bottom: 2px solid #1a5a9c;
 | 
			
		||||
  padding: 10px 20px;
 | 
			
		||||
}
 | 
			
		||||
.tabs button {
 | 
			
		||||
  background: none;
 | 
			
		||||
  border: none;
 | 
			
		||||
  color: #a9c2e0;
 | 
			
		||||
  padding: 8px 16px;
 | 
			
		||||
.tabs-switch {
 | 
			
		||||
  margin: 0 auto;
 | 
			
		||||
  display: flex;
 | 
			
		||||
  justify-content: space-between;
 | 
			
		||||
}
 | 
			
		||||
.switch-item {
 | 
			
		||||
  flex: 1;
 | 
			
		||||
  padding: 4px 0px;
 | 
			
		||||
  display: flex;
 | 
			
		||||
  justify-content: center;
 | 
			
		||||
  align-items: center;
 | 
			
		||||
  border: 1px solid #20406e;
 | 
			
		||||
  font-size: 14px;
 | 
			
		||||
  cursor: pointer;
 | 
			
		||||
  transition: all 0.3s ease;
 | 
			
		||||
  position: relative;
 | 
			
		||||
  color: #cccccc9d;
 | 
			
		||||
}
 | 
			
		||||
.tabs button.active {
 | 
			
		||||
  color: #fff;
 | 
			
		||||
  font-weight: bold;
 | 
			
		||||
.switch-item:first-child {
 | 
			
		||||
  border-radius: 5px 0 0 5px;
 | 
			
		||||
}
 | 
			
		||||
.tabs button.active::after {
 | 
			
		||||
  content: "";
 | 
			
		||||
  position: absolute;
 | 
			
		||||
  bottom: -2px;
 | 
			
		||||
  left: 0;
 | 
			
		||||
.switch-item:last-child {
 | 
			
		||||
  border-radius: 0px 5px 5px 0px;
 | 
			
		||||
}
 | 
			
		||||
.tabsSwich-active {
 | 
			
		||||
  width: 100%;
 | 
			
		||||
  height: 2px;
 | 
			
		||||
  background-color: #3aa1f8;
 | 
			
		||||
  height: 100%;
 | 
			
		||||
  color: #fff;
 | 
			
		||||
  opacity: 1;
 | 
			
		||||
  background-color: #236291;
 | 
			
		||||
  border: 1px solid #3fa9f5;
 | 
			
		||||
}
 | 
			
		||||
.leader-list {
 | 
			
		||||
  width: 100%;
 | 
			
		||||
  height: 410px;
 | 
			
		||||
  flex-grow: 1;
 | 
			
		||||
  height: 430px;
 | 
			
		||||
  margin-top: 10px;
 | 
			
		||||
  padding-right: 5px;
 | 
			
		||||
  overflow: auto;
 | 
			
		||||
  scrollbar-width: none;
 | 
			
		||||
  color: #fff;
 | 
			
		||||
}
 | 
			
		||||
.leader-list::-webkit-scrollbar {
 | 
			
		||||
  width: 4px;
 | 
			
		||||
}
 | 
			
		||||
.leader-list::-webkit-scrollbar-track {
 | 
			
		||||
  background: transparent;
 | 
			
		||||
  width: 3px;
 | 
			
		||||
  height: 5px;
 | 
			
		||||
}
 | 
			
		||||
.leader-list::-webkit-scrollbar-thumb {
 | 
			
		||||
  background: #3aa1f8;
 | 
			
		||||
  border-radius: 2px;
 | 
			
		||||
  background: rgba(147, 210, 255, 0.3);
 | 
			
		||||
  border-radius: 4px;
 | 
			
		||||
}
 | 
			
		||||
.leader-list::-webkit-scrollbar-thumb:hover {
 | 
			
		||||
  background: rgba(147, 210, 255, 0.5);
 | 
			
		||||
}
 | 
			
		||||
.leader-item {
 | 
			
		||||
  width: 100%;
 | 
			
		||||
  height: 80px;
 | 
			
		||||
  padding: 10px 0px;
 | 
			
		||||
  display: flex;
 | 
			
		||||
  justify-content: space-between;
 | 
			
		||||
  align-items: center;
 | 
			
		||||
  padding: 10px 5px;
 | 
			
		||||
  border-bottom: 1px solid rgba(58, 161, 248, 0.2);
 | 
			
		||||
  cursor: pointer;
 | 
			
		||||
  border-bottom: 0.5px solid rgba(0, 113, 188, 0.5);
 | 
			
		||||
}
 | 
			
		||||
.order {
 | 
			
		||||
  color: #fff;
 | 
			
		||||
  font-size: 16px;
 | 
			
		||||
  font-style: normal;
 | 
			
		||||
  font-weight: 400;
 | 
			
		||||
  margin-right: 15px;
 | 
			
		||||
}
 | 
			
		||||
.avatar {
 | 
			
		||||
  width: 50px;
 | 
			
		||||
  height: 50px;
 | 
			
		||||
  border-radius: 50%;
 | 
			
		||||
  margin-right: 15px;
 | 
			
		||||
  width: 48px;
 | 
			
		||||
  height: 48px;
 | 
			
		||||
  border-radius: 5px;
 | 
			
		||||
  flex-shrink: 0;
 | 
			
		||||
}
 | 
			
		||||
.info {
 | 
			
		||||
.user-info {
 | 
			
		||||
  flex: 1;
 | 
			
		||||
  padding-left: 15px;
 | 
			
		||||
  display: flex;
 | 
			
		||||
  flex-direction: column;
 | 
			
		||||
  gap: 5px;
 | 
			
		||||
  justify-content: space-between;
 | 
			
		||||
}
 | 
			
		||||
.name {
 | 
			
		||||
  display: flex;
 | 
			
		||||
  align-items: baseline;
 | 
			
		||||
  gap: 8px;
 | 
			
		||||
}
 | 
			
		||||
.en-name {
 | 
			
		||||
.username {
 | 
			
		||||
  color: #fff;
 | 
			
		||||
  font-size: 16px;
 | 
			
		||||
  font-weight: bold;
 | 
			
		||||
  font-family: "微软雅黑";
 | 
			
		||||
}
 | 
			
		||||
.cn-name {
 | 
			
		||||
  font-size: 14px;
 | 
			
		||||
  color: #a9c2e0;
 | 
			
		||||
  margin-left: 5px;
 | 
			
		||||
}
 | 
			
		||||
.stats {
 | 
			
		||||
  font-size: 12px;
 | 
			
		||||
  color: #a9c2e0;
 | 
			
		||||
.userState {
 | 
			
		||||
  display: flex;
 | 
			
		||||
  gap: 20px;
 | 
			
		||||
  justify-content: space-between;
 | 
			
		||||
  margin-top: 8px;
 | 
			
		||||
  font-size: 13px;
 | 
			
		||||
  color: #cccccc9d;
 | 
			
		||||
  div {
 | 
			
		||||
    display: flex;
 | 
			
		||||
    p {
 | 
			
		||||
      color: #fff;
 | 
			
		||||
      margin-left: 5px;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.userState-monitor-count {
 | 
			
		||||
  width: 100px; /* 固定宽度确保对齐 */
 | 
			
		||||
  justify-content: flex-start; /* 内容靠左对齐 */
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
| 
						 | 
				
			
			@ -53,11 +53,12 @@
 | 
			
		|||
        </div>
 | 
			
		||||
        <div class="timeline-container">
 | 
			
		||||
          <span class="time-label">2023.10.07 00:00:00</span>
 | 
			
		||||
          <div class="timeline-track">
 | 
			
		||||
          <div class="timeline-track" :style="trackStyle">
 | 
			
		||||
            <div
 | 
			
		||||
              v-for="point in store.timePoints"
 | 
			
		||||
              :key="point.id"
 | 
			
		||||
              class="timeline-point-wrapper"
 | 
			
		||||
              :style="{ left: `${pointPositions[point.id]}%` }"
 | 
			
		||||
              @click="store.setActiveTimePoint(point.id)"
 | 
			
		||||
            >
 | 
			
		||||
              <el-tooltip
 | 
			
		||||
| 
						 | 
				
			
			@ -92,7 +93,7 @@
 | 
			
		|||
</template>
 | 
			
		||||
 | 
			
		||||
<script setup>
 | 
			
		||||
import { ref, defineExpose } from 'vue';
 | 
			
		||||
import { ref, defineExpose, watch, computed } from 'vue';
 | 
			
		||||
import { useKeyNodeStore2 } from '@/store/keyNodeStore2';
 | 
			
		||||
import DynamicGraph from "./graph/dynamicGraph.vue";
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -108,6 +109,72 @@ const highlightNode = (leaderId) => {
 | 
			
		|||
    leaderGraphRef.value.highlightNode(leaderId);
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// 计算时间点在时间轴上的位置百分比
 | 
			
		||||
const calculatePositions = (timestamp) => {
 | 
			
		||||
// 时间范围: 2023-10-07T00:00:00 到 2023-10-15T00:00:00
 | 
			
		||||
  const startTime = new Date('2023-10-07T00:00:00').getTime()
 | 
			
		||||
  const endTime = new Date('2023-10-15T00:00:00').getTime()
 | 
			
		||||
  const timeRange = endTime - startTime;
 | 
			
		||||
  // 复制并排序时间点数据
 | 
			
		||||
  const sortedPoints = [...store.timePoints].sort((a, b) => {
 | 
			
		||||
    return new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime();
 | 
			
		||||
  });
 | 
			
		||||
  // 计算每个点的原始位置
 | 
			
		||||
  const pointPositions = {};
 | 
			
		||||
  sortedPoints.forEach(point => {
 | 
			
		||||
    const pointTime = new Date(point.timestamp).getTime();
 | 
			
		||||
    const position = ((pointTime - startTime) / timeRange) * 100;
 | 
			
		||||
    pointPositions[point.id] = Math.max(0, Math.min(100, position));
 | 
			
		||||
  });
 | 
			
		||||
  // 处理重叠 (假设每个点宽度约为20px,时间轴总宽度为可用宽度)
 | 
			
		||||
  const pointWidthPercentage = 5; // 估算的点宽度百分比
 | 
			
		||||
  const minSpacing = pointWidthPercentage; // 最小间距百分比
 | 
			
		||||
 | 
			
		||||
  // 调整重叠的点
 | 
			
		||||
  for (let i = 1; i < sortedPoints.length; i++) {
 | 
			
		||||
    const prevPoint = sortedPoints[i - 1];
 | 
			
		||||
    const currPoint = sortedPoints[i];
 | 
			
		||||
 | 
			
		||||
    const prevPosition = pointPositions[prevPoint.id];
 | 
			
		||||
    const currPosition = pointPositions[currPoint.id];
 | 
			
		||||
 | 
			
		||||
    // 检查是否重叠
 | 
			
		||||
    if (currPosition - prevPosition < minSpacing) {
 | 
			
		||||
      // 调整当前点位置
 | 
			
		||||
      pointPositions[currPoint.id] = prevPosition + minSpacing;
 | 
			
		||||
 | 
			
		||||
      // 确保不超出范围
 | 
			
		||||
      if (pointPositions[currPoint.id] > 100) {
 | 
			
		||||
        pointPositions[currPoint.id] = 100;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return pointPositions;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 响应式引用存储位置信息
 | 
			
		||||
const pointPositions = ref({});
 | 
			
		||||
 | 
			
		||||
// 监听时间点变化,重新计算位置
 | 
			
		||||
watch(
 | 
			
		||||
  () => store.timePoints,
 | 
			
		||||
  () => {
 | 
			
		||||
    pointPositions.value = calculatePositions();
 | 
			
		||||
  },
 | 
			
		||||
  { immediate: true, deep: true }
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
// 计算时间轴轨道样式
 | 
			
		||||
const trackStyle = computed(() => {
 | 
			
		||||
  if (!store.activeTimePoint) return {};
 | 
			
		||||
  const activePosition = pointPositions.value[store.activeTimePoint] || 0;
 | 
			
		||||
  return {
 | 
			
		||||
    background: `linear-gradient(90deg, #3B7699 0%, #00F3FF ${activePosition}%, #3B7699 ${activePosition}%, #3B7699 100%)`
 | 
			
		||||
  };
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
defineExpose({ highlightNode });
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -164,11 +231,11 @@ defineExpose({ highlightNode });
 | 
			
		|||
.timeline-track {
 | 
			
		||||
  flex-grow: 1;
 | 
			
		||||
  height: 4px;
 | 
			
		||||
  background: linear-gradient(90deg, #1b62a9, #3aa1f8, #1b62a9);
 | 
			
		||||
  /* background: linear-gradient(90deg, #1b62a9, #3aa1f8, #1b62a9); */
 | 
			
		||||
  margin: 0 15px;
 | 
			
		||||
  position: relative;
 | 
			
		||||
  display: flex;
 | 
			
		||||
  justify-content: space-between;
 | 
			
		||||
  /* justify-content: space-between; */
 | 
			
		||||
  align-items: center;
 | 
			
		||||
}
 | 
			
		||||
.timeline-point-wrapper {
 | 
			
		||||
| 
						 | 
				
			
			@ -177,22 +244,37 @@ defineExpose({ highlightNode });
 | 
			
		|||
  justify-content: center;
 | 
			
		||||
  height: 20px;
 | 
			
		||||
  cursor: pointer;
 | 
			
		||||
  position: absolute;
 | 
			
		||||
  transform: translateX(-50%);
 | 
			
		||||
}
 | 
			
		||||
.timeline-point {
 | 
			
		||||
  width: 10px;
 | 
			
		||||
  height: 10px;
 | 
			
		||||
  background-color: #8dc5ff;
 | 
			
		||||
  width: 18px;
 | 
			
		||||
  height: 18px;
 | 
			
		||||
  background-color: transparent;
 | 
			
		||||
  border-radius: 50%;
 | 
			
		||||
  border: 1px solid #cce7ff;
 | 
			
		||||
  border: 1.6px solid #FFE5A4;
 | 
			
		||||
  transition: transform 0.3s ease;
 | 
			
		||||
  position: relative;
 | 
			
		||||
  display: flex;
 | 
			
		||||
  align-items: center;
 | 
			
		||||
  justify-content: center;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.timeline-point::after {
 | 
			
		||||
  content: '';
 | 
			
		||||
  width: 10px;
 | 
			
		||||
  height: 10px;
 | 
			
		||||
  background-color: #F9BD25;
 | 
			
		||||
  border-radius: 50%;
 | 
			
		||||
  position: absolute;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.timeline-point-wrapper:hover .timeline-point {
 | 
			
		||||
  transform: scale(1.5);
 | 
			
		||||
}
 | 
			
		||||
.timeline-point.active {
 | 
			
		||||
  background-color: #ffc94d;
 | 
			
		||||
  border-color: #fff;
 | 
			
		||||
  background-color: transparent;
 | 
			
		||||
  border-color: #FFE5A4;
 | 
			
		||||
  transform: scale(1.3);
 | 
			
		||||
}
 | 
			
		||||
.active-pin {
 | 
			
		||||
| 
						 | 
				
			
			@ -200,8 +282,7 @@ defineExpose({ highlightNode });
 | 
			
		|||
  height: 34px;
 | 
			
		||||
  background-image: url("@/assets/images/point.png");
 | 
			
		||||
  background-size: cover;
 | 
			
		||||
  bottom: 5px;
 | 
			
		||||
  left: -11px;
 | 
			
		||||
  bottom:6px;
 | 
			
		||||
  position: absolute;
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
| 
						 | 
				
			
			@ -1,36 +1,47 @@
 | 
			
		|||
<template>
 | 
			
		||||
  <div class="left-panel">
 | 
			
		||||
    <img
 | 
			
		||||
      src="@/assets/images/chuanbo-show-title.png"
 | 
			
		||||
      src="../../../assets/images/leaderTitle.png"
 | 
			
		||||
      alt=""
 | 
			
		||||
      class="headerImage"
 | 
			
		||||
      style="margin-top: -22px; margin-left: -15px"
 | 
			
		||||
    />
 | 
			
		||||
    <div class="tabs">
 | 
			
		||||
      <button
 | 
			
		||||
        v-for="tab in tabs"
 | 
			
		||||
        :key="tab"
 | 
			
		||||
        :class="{ active: activeTab === tab }"
 | 
			
		||||
        @click="activeTab = tab"
 | 
			
		||||
      >
 | 
			
		||||
        {{ tab }}
 | 
			
		||||
      </button>
 | 
			
		||||
      <div class="tabs-switch">
 | 
			
		||||
        <div
 | 
			
		||||
          class="switch-item"
 | 
			
		||||
          v-for="tab in tabs"
 | 
			
		||||
          :key="tab"
 | 
			
		||||
          @click="activeTab = tab"
 | 
			
		||||
          :class="{ 'tabsSwich-active': activeTab === tab }"
 | 
			
		||||
        >
 | 
			
		||||
          {{ tab }}
 | 
			
		||||
        </div>
 | 
			
		||||
      </div>
 | 
			
		||||
    </div>
 | 
			
		||||
    <div class="leader-list" ref="leaderListRef">
 | 
			
		||||
      <div
 | 
			
		||||
        v-for="leader in filteredVisibleLeaders"
 | 
			
		||||
        v-for="(leader, index) in filteredVisibleLeaders"
 | 
			
		||||
        :key="leader.id"
 | 
			
		||||
        class="leader-item"
 | 
			
		||||
        @click="emit('selectLeader', leader)"
 | 
			
		||||
      >
 | 
			
		||||
        <div class="order">{{ index + 1 }}</div>
 | 
			
		||||
        <img :src="leader.avatar" :alt="leader.name" class="avatar" />
 | 
			
		||||
        <div class="info">
 | 
			
		||||
          <div class="name">
 | 
			
		||||
        <div class="user-info">
 | 
			
		||||
          <div class="username">
 | 
			
		||||
            <span class="en-name">{{ leader.name }}</span>
 | 
			
		||||
            <span v-if="leader.chineseName" class="cn-name">{{ leader.chineseName }}</span>
 | 
			
		||||
            <span v-if="leader.chineseName" class="cn-name">({{ leader.chineseName }})</span>
 | 
			
		||||
          </div>
 | 
			
		||||
          <div class="stats">
 | 
			
		||||
            <span>粉丝数量: {{ leader.followers }}</span>
 | 
			
		||||
            <span>发帖总数: {{ leader.posts }}</span>
 | 
			
		||||
          <div class="userState">
 | 
			
		||||
            <div class="userState-fancy">
 | 
			
		||||
              粉丝数:
 | 
			
		||||
              <p>{{ leader.followers }}</p>
 | 
			
		||||
            </div>
 | 
			
		||||
            <div class="userState-monitor-count">
 | 
			
		||||
              发帖数:
 | 
			
		||||
              <p>{{ leader.posts }}</p>
 | 
			
		||||
            </div>
 | 
			
		||||
          </div>
 | 
			
		||||
        </div>
 | 
			
		||||
      </div>
 | 
			
		||||
| 
						 | 
				
			
			@ -67,7 +78,7 @@ watch(filteredVisibleLeaders, async () => {
 | 
			
		|||
}, { deep: true });
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<style scoped>
 | 
			
		||||
<style scoped lang="less">
 | 
			
		||||
.left-panel {
 | 
			
		||||
  width: 350px;
 | 
			
		||||
  flex-shrink: 0;
 | 
			
		||||
| 
						 | 
				
			
			@ -76,89 +87,117 @@ watch(filteredVisibleLeaders, async () => {
 | 
			
		|||
  display: flex;
 | 
			
		||||
  flex-direction: column;
 | 
			
		||||
  padding: 15px;
 | 
			
		||||
  height: 100%;
 | 
			
		||||
}
 | 
			
		||||
.tabs {
 | 
			
		||||
  display: flex;
 | 
			
		||||
  margin-bottom: 15px;
 | 
			
		||||
  border-bottom: 2px solid #1a5a9c;
 | 
			
		||||
  padding: 10px 20px;
 | 
			
		||||
}
 | 
			
		||||
.tabs button {
 | 
			
		||||
  background: none;
 | 
			
		||||
  border: none;
 | 
			
		||||
  color: #a9c2e0;
 | 
			
		||||
  padding: 8px 16px;
 | 
			
		||||
.tabs-switch {
 | 
			
		||||
  margin: 0 auto;
 | 
			
		||||
  display: flex;
 | 
			
		||||
  justify-content: space-between;
 | 
			
		||||
}
 | 
			
		||||
.switch-item {
 | 
			
		||||
  flex: 1;
 | 
			
		||||
  padding: 4px 0px;
 | 
			
		||||
  display: flex;
 | 
			
		||||
  justify-content: center;
 | 
			
		||||
  align-items: center;
 | 
			
		||||
  border: 1px solid #20406e;
 | 
			
		||||
  font-size: 14px;
 | 
			
		||||
  cursor: pointer;
 | 
			
		||||
  transition: all 0.3s ease;
 | 
			
		||||
  position: relative;
 | 
			
		||||
  color: #cccccc9d;
 | 
			
		||||
}
 | 
			
		||||
.tabs button.active {
 | 
			
		||||
  color: #fff;
 | 
			
		||||
  font-weight: bold;
 | 
			
		||||
.switch-item:first-child {
 | 
			
		||||
  border-radius: 5px 0 0 5px;
 | 
			
		||||
}
 | 
			
		||||
.tabs button.active::after {
 | 
			
		||||
  content: "";
 | 
			
		||||
  position: absolute;
 | 
			
		||||
  bottom: -2px;
 | 
			
		||||
  left: 0;
 | 
			
		||||
.switch-item:last-child {
 | 
			
		||||
  border-radius: 0px 5px 5px 0px;
 | 
			
		||||
}
 | 
			
		||||
.tabsSwich-active {
 | 
			
		||||
  width: 100%;
 | 
			
		||||
  height: 2px;
 | 
			
		||||
  background-color: #3aa1f8;
 | 
			
		||||
  height: 100%;
 | 
			
		||||
  color: #fff;
 | 
			
		||||
  opacity: 1;
 | 
			
		||||
  background-color: #236291;
 | 
			
		||||
  border: 1px solid #3fa9f5;
 | 
			
		||||
}
 | 
			
		||||
.leader-list {
 | 
			
		||||
  width: 100%;
 | 
			
		||||
  height: 410px;
 | 
			
		||||
  flex-grow: 1;
 | 
			
		||||
  height: 430px;
 | 
			
		||||
  margin-top: 10px;
 | 
			
		||||
  padding-right: 5px;
 | 
			
		||||
  overflow: auto;
 | 
			
		||||
  scrollbar-width: none;
 | 
			
		||||
  color: #fff;
 | 
			
		||||
}
 | 
			
		||||
.leader-list::-webkit-scrollbar {
 | 
			
		||||
  width: 4px;
 | 
			
		||||
}
 | 
			
		||||
.leader-list::-webkit-scrollbar-track {
 | 
			
		||||
  background: transparent;
 | 
			
		||||
  width: 3px;
 | 
			
		||||
  height: 5px;
 | 
			
		||||
}
 | 
			
		||||
.leader-list::-webkit-scrollbar-thumb {
 | 
			
		||||
  background: #3aa1f8;
 | 
			
		||||
  border-radius: 2px;
 | 
			
		||||
  background: rgba(147, 210, 255, 0.3);
 | 
			
		||||
  border-radius: 4px;
 | 
			
		||||
}
 | 
			
		||||
.leader-list::-webkit-scrollbar-thumb:hover {
 | 
			
		||||
  background: rgba(147, 210, 255, 0.5);
 | 
			
		||||
}
 | 
			
		||||
.leader-item {
 | 
			
		||||
  width: 100%;
 | 
			
		||||
  height: 80px;
 | 
			
		||||
  padding: 10px 0px;
 | 
			
		||||
  display: flex;
 | 
			
		||||
  justify-content: space-between;
 | 
			
		||||
  align-items: center;
 | 
			
		||||
  padding: 10px 5px;
 | 
			
		||||
  border-bottom: 1px solid rgba(58, 161, 248, 0.2);
 | 
			
		||||
  cursor: pointer;
 | 
			
		||||
  border-bottom: 0.5px solid rgba(0, 113, 188, 0.5);
 | 
			
		||||
}
 | 
			
		||||
.order {
 | 
			
		||||
  color: #fff;
 | 
			
		||||
  font-size: 16px;
 | 
			
		||||
  font-style: normal;
 | 
			
		||||
  font-weight: 400;
 | 
			
		||||
  margin-right: 15px;
 | 
			
		||||
}
 | 
			
		||||
.avatar {
 | 
			
		||||
  width: 50px;
 | 
			
		||||
  height: 50px;
 | 
			
		||||
  border-radius: 50%;
 | 
			
		||||
  margin-right: 15px;
 | 
			
		||||
  width: 48px;
 | 
			
		||||
  height: 48px;
 | 
			
		||||
  border-radius: 5px;
 | 
			
		||||
  flex-shrink: 0;
 | 
			
		||||
}
 | 
			
		||||
.info {
 | 
			
		||||
.user-info {
 | 
			
		||||
  flex: 1;
 | 
			
		||||
  padding-left: 15px;
 | 
			
		||||
  display: flex;
 | 
			
		||||
  flex-direction: column;
 | 
			
		||||
  gap: 5px;
 | 
			
		||||
  justify-content: space-between;
 | 
			
		||||
}
 | 
			
		||||
.name {
 | 
			
		||||
  display: flex;
 | 
			
		||||
  align-items: baseline;
 | 
			
		||||
  gap: 8px;
 | 
			
		||||
}
 | 
			
		||||
.en-name {
 | 
			
		||||
.username {
 | 
			
		||||
  color: #fff;
 | 
			
		||||
  font-size: 16px;
 | 
			
		||||
  font-weight: bold;
 | 
			
		||||
  font-family: "微软雅黑";
 | 
			
		||||
}
 | 
			
		||||
.cn-name {
 | 
			
		||||
  font-size: 14px;
 | 
			
		||||
  color: #a9c2e0;
 | 
			
		||||
  margin-left: 5px;
 | 
			
		||||
}
 | 
			
		||||
.stats {
 | 
			
		||||
  font-size: 12px;
 | 
			
		||||
  color: #a9c2e0;
 | 
			
		||||
.userState {
 | 
			
		||||
  display: flex;
 | 
			
		||||
  gap: 20px;
 | 
			
		||||
  justify-content: space-between;
 | 
			
		||||
  margin-top: 8px;
 | 
			
		||||
  font-size: 13px;
 | 
			
		||||
  color: #cccccc9d;
 | 
			
		||||
  div {
 | 
			
		||||
    display: flex;
 | 
			
		||||
    p {
 | 
			
		||||
      color: #fff;
 | 
			
		||||
      margin-left: 5px;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.userState-monitor-count {
 | 
			
		||||
  width: 100px; /* 固定宽度确保对齐 */
 | 
			
		||||
  justify-content: flex-start; /* 内容靠左对齐 */
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user