10 小时以前 1c829f9177eab675b22be4d20ef2761ed1bbb423
src/views/reportAnalysis/productionAnalysis/components/CarouselCards.vue
@@ -1,14 +1,15 @@
<template>
  <div class="carousel-cards">
    <button
    <button
      v-if="canScrollLeft"
      class="nav-button nav-button-left"
      aria-label="向左滚动"
      @click="scrollLeftFn"
    >
      <img src="@/assets/BI/jiantou.png" alt="左箭头" />
      <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M15 18l-6-6 6-6"/></svg>
    </button>
    <div
      class="cards-container"
    <div
      class="cards-container"
      :style="{ '--visible-count': visibleCount }"
      ref="cardsContainerRef"
    >
@@ -17,7 +18,6 @@
        :key="index"
        class="card-item"
      >
        <div v-if="item.icon" class="card-icon" :style="{ backgroundImage: `url(${item.icon})` }"></div>
        <div class="card-title">
          <div class="card-label">{{ item.label }}</div>
          <div class="card-value">
@@ -30,12 +30,13 @@
        </div>
      </div>
    </div>
    <button
    <button
      v-if="canScrollRight"
      class="nav-button nav-button-right"
      aria-label="向右滚动"
      @click="scrollRightFn"
    >
      <img src="@/assets/BI/jiantou.png" alt="右箭头" />
      <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M9 18l6-6-6-6"/></svg>
    </button>
  </div>
</template>
@@ -48,9 +49,9 @@
    type: Array,
    default: () => [],
    validator: (value) => {
      return value.every(item =>
        item && typeof item.label !== 'undefined' &&
        typeof item.value !== 'undefined' &&
      return value.every(item =>
        item && typeof item.label !== 'undefined' &&
        typeof item.value !== 'undefined' &&
        typeof item.unit !== 'undefined'
      )
    }
@@ -79,7 +80,7 @@
const updateScrollState = () => {
  const container = cardsContainerRef.value
  if (!container) return
  currentScrollLeft.value = container.scrollLeft
  maxScrollLeft.value = container.scrollWidth - container.clientWidth
}
@@ -88,19 +89,19 @@
const scrollLeftFn = () => {
  const container = cardsContainerRef.value
  if (!container) return
  const scrollItems = Array.from(container.querySelectorAll('.card-item'))
  if (scrollItems.length === 0) return
  const itemWidth = scrollItems[0]?.offsetWidth || 0
  const gap = 12
  const scrollDistance = itemWidth + gap
  container.scrollBy({
    left: -scrollDistance,
    behavior: 'smooth'
  })
  // 延迟更新状态,等待滚动动画完成
  setTimeout(() => {
    updateScrollState()
@@ -111,19 +112,19 @@
const scrollRightFn = () => {
  const container = cardsContainerRef.value
  if (!container) return
  const scrollItems = Array.from(container.querySelectorAll('.card-item'))
  if (scrollItems.length === 0) return
  const itemWidth = scrollItems[0]?.offsetWidth || 0
  const gap = 12
  const scrollDistance = itemWidth + gap
  container.scrollBy({
    left: scrollDistance,
    behavior: 'smooth'
  })
  // 延迟更新状态,等待滚动动画完成
  setTimeout(() => {
    updateScrollState()
@@ -188,40 +189,30 @@
  transform: translateY(-50%);
  width: 32px;
  height: 32px;
  background: rgba(26, 88, 176, 0.6);
  border: 1px solid rgba(26, 88, 176, 0.8);
  background: var(--bi-surface-2);
  border: 1px solid var(--bi-border);
  border-radius: 50%;
  color: var(--bi-text-secondary);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  z-index: 10;
  transition: all 0.3s ease;
  transition: color 0.2s ease, border-color 0.2s ease;
  padding: 0;
}
.nav-button:hover {
  background: rgba(26, 88, 176, 0.8);
  transform: translateY(-50%) scale(1.1);
  color: var(--bi-accent);
  border-color: var(--bi-accent);
}
.nav-button-left {
  left: -16px;
}
.nav-button-left img {
  width: 16px;
  height: 16px;
  transform: rotate(180deg);
}
.nav-button-right {
  right: -16px;
}
.nav-button-right img {
  width: 16px;
  height: 16px;
}
.card-item {
@@ -229,24 +220,15 @@
  min-width: calc((100% - (var(--visible-count) - 1) * 12px) / var(--visible-count));
  display: flex;
  align-items: center;
  background: linear-gradient(269deg, rgba(27,57,126,0.13) 0%, rgba(33,137,206,0.33) 98.13%, #24AFF4 100%);
  border-radius: 8px 8px 8px 8px;
  background: var(--bi-surface-2);
  border: 1px solid var(--bi-border);
  border-radius: 8px;
  padding: 12px 16px;
  transition: all 0.3s ease;
  transition: border-color 0.2s ease;
}
.card-item:hover {
  transform: translateY(-2px);
}
.card-icon {
  width: 80px;
  height: 60px;
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  flex-shrink: 0;
  margin-right: 12px;
  border-color: rgba(91, 140, 255, 0.45);
}
.card-title {
@@ -254,12 +236,13 @@
  align-items: flex-start;
  flex-direction: column;
  flex: 1;
  min-width: 0;
}
.card-label {
  font-weight: 400;
  font-size: 14px;
  color: #FFFFFF;
  color: var(--bi-text-secondary);
  margin-bottom: 4px;
  white-space: nowrap;
  overflow: hidden;
@@ -280,7 +263,7 @@
  gap: 6px;
  font-weight: 400;
  font-size: 12px;
  color: rgba(255, 255, 255, 0.85);
  color: var(--bi-text-secondary);
}
.rate-label {
@@ -292,15 +275,17 @@
}
.value-number {
  font-weight: 400;
  font-size: 14px;
  color: #FFFFFF;
  line-height: 1;
  font-weight: 600;
  font-size: 22px;
  color: var(--bi-text);
  line-height: 1.1;
  font-variant-numeric: tabular-nums;
  font-feature-settings: 'tnum';
}
.value-unit {
  font-size: 14px;
  color: #FFFFFF;
  font-size: 12px;
  color: var(--bi-text-secondary);
  font-weight: 400;
}
</style>