RechargeSuccessCard.vue 5.31 KB
<template>
  <Transition name="fade">
    <div v-if="visible" class="success-card-overlay" @click.self="handleClose">
      <div class="success-card">
        <button class="close-btn" @click="handleClose">
          <i class="fas fa-times"></i>
        </button>
        <div class="success-icon">
          <div class="checkmark-circle">
            <i class="fas fa-check"></i>
          </div>
        </div>
        <h2 class="success-title">
          {{ $t("settingsSidebar.rechargeSuccessCard.title") }}
        </h2>
        <p class="success-message" v-if="memberType !== 'temporary'">
          {{
            $t("settingsSidebar.rechargeSuccessCard.message", {
              memberType: memberTypeText,
            })
          }}
        </p>
        <div class="beans-info">
          <div class="beans-icon-wrapper">
            <img src="/douzi.svg" class="beans-icon" alt="医豆" />
          </div>
          <div class="beans-text">
            <span class="beans-label">{{
              $t("settingsSidebar.rechargeSuccessCard.beansObtained")
            }}</span>
            <span class="beans-value"
              >+{{ beansQuantity }}{{ $t("settingsSidebar.beansUnit") }}</span
            >
          </div>
        </div>
        <button class="confirm-btn" @click="handleConfirm">
          {{ $t("settingsSidebar.rechargeSuccessCard.confirmButton") }}
        </button>
      </div>
    </div>
  </Transition>
</template>

<script setup lang="ts">
import { computed, watch } from "vue";
import { useI18n } from "vue-i18n";

interface Props {
  visible: boolean;
  memberType: "gold" | "platinum" | "temporary";
  beansQuantity: number;
}

const props = defineProps<Props>();
const emit = defineEmits<{
  close: [];
}>();

const { t } = useI18n();

const memberTypeText = computed(() => {
  if (props.memberType === "gold") {
    return t("settingsSidebar.memberTypeGold");
  } else if (props.memberType === "platinum") {
    return t("settingsSidebar.memberTypePlatinum");
  } else if (props.memberType === "temporary") {
    return t("settingsSidebar.memberTypeTemporary");
  } else {
    return "";
  }
});

const handleClose = () => {
  emit("close");
};

const handleConfirm = () => {
  emit("close");
};

watch(
  () => props.visible,
  (newVal) => {
    if (newVal) {
      document.body.style.overflow = "hidden";
    } else {
      document.body.style.overflow = "";
    }
  },
);
</script>

<style scoped lang="scss">
.success-card-overlay {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: rgba(0, 0, 0, 0.5);
  display: flex;
  justify-content: center;
  align-items: center;
  z-index: 10000;
  backdrop-filter: blur(4px);
}

.success-card {
  background: white;
  border-radius: 20px;
  padding: 40px 32px;
  max-width: 480px;
  width: 90%;
  position: relative;
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
  animation: slideUp 0.3s ease-out;
}

@keyframes slideUp {
  from {
    transform: translateY(30px);
    opacity: 0;
  }
  to {
    transform: translateY(0);
    opacity: 1;
  }
}

.close-btn {
  position: absolute;
  top: 16px;
  right: 16px;
  background: none;
  border: none;
  font-size: 20px;
  color: #909399;
  cursor: pointer;
  width: 32px;
  height: 32px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  transition: all 0.2s ease;

  &:hover {
    background: #f5f5f5;
    color: #606266;
  }
}

.success-icon {
  display: flex;
  justify-content: center;
  margin-bottom: 24px;
}

.checkmark-circle {
  width: 80px;
  height: 80px;
  border-radius: 50%;
  background: linear-gradient(135deg, #67c23a 0%, #85ce61 100%);
  display: flex;
  align-items: center;
  justify-content: center;
  animation: scaleIn 0.3s ease-out;

  i {
    font-size: 40px;
    color: white;
  }
}

@keyframes scaleIn {
  from {
    transform: scale(0);
  }
  to {
    transform: scale(1);
  }
}

.success-title {
  font-size: 24px;
  font-weight: 700;
  color: #303133;
  text-align: center;
  margin: 0 0 16px 0;
}

.success-message {
  font-size: 16px;
  color: #606266;
  text-align: center;
  margin: 0 0 24px 0;
  line-height: 1.6;
}

.beans-info {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  background: linear-gradient(135deg, #fff4e6 0%, #ffe8cc 100%);
  border-radius: 12px;
  padding: 20px;
  margin-bottom: 24px;

  .beans-icon-wrapper {
    display: flex;
    align-items: center;
    justify-content: center;
  }

  .beans-icon {
    width: 40px;
    height: 40px;
    object-fit: contain;
  }

  .beans-text {
    display: flex;
    flex-direction: column;
    gap: 4px;

    .beans-label {
      font-size: 14px;
      color: #666;
      font-weight: 500;
    }

    .beans-value {
      font-size: 28px;
      font-weight: 700;
      color: #ff6b00;
    }
  }
}

.confirm-btn {
  width: 100%;
  padding: 14px 24px;
  background: linear-gradient(135deg, #1e6fff 0%, #409eff 100%);
  color: white;
  border: none;
  border-radius: 12px;
  font-size: 16px;
  font-weight: 600;
  cursor: pointer;
  transition: all 0.3s ease;
  box-shadow: 0 4px 12px rgba(30, 111, 255, 0.3);

  &:hover {
    transform: translateY(-2px);
    box-shadow: 0 6px 16px rgba(30, 111, 255, 0.4);
  }

  &:active {
    transform: translateY(0);
  }
}

.fade-enter-active,
.fade-leave-active {
  transition: opacity 0.3s ease;
}

.fade-enter-from,
.fade-leave-to {
  opacity: 0;
}
</style>