GoActivate.vue 7.53 KB
<template>
  <div class="auth-bg">
    <div class="auth-container">
      <!-- 返回按钮 -->
      <div class="back-button" @click="goBack">
        <img src="/zuo.svg" alt="goBack" class="input-icon-svg" />
      </div>

      <!-- 头部Logo与标题 -->
      <div class="auth-header">
        <div class="logo-container">
          <img src="/newLogo.png" alt="Logo" class="logo-img" />
        </div>
        <h1 class="auth-title">{{ $t("goActivateV2.title") }}</h1>
        <p class="auth-subtitle">
          {{
            $t("goActivateV2.description_link") ||
            $t("goActivateV2.description")
          }}
        </p>
      </div>

      <!-- 激活表单(仅邮箱) -->
      <el-form
        :model="form"
        :rules="rules"
        ref="activateFormRef"
        class="activate-form"
        label-position="top"
        @submit.prevent="onSubmit"
      >
        <el-form-item prop="email" :label="$t('goActivateV2.emailLabel')">
          <el-input
            v-model="form.email"
            :placeholder="$t('goActivateV2.emailPlaceholder')"
            clearable
          >
            <template #prefix>
              <img src="/youxiang.svg" alt="email" class="input-icon-svg" />
            </template>
          </el-input>
        </el-form-item>

        <el-form-item>
          <el-button
            type="primary"
            class="submit-btn"
            @click="onSubmit"
            :loading="loading"
            round
            native-type="button"
          >
            {{
              $t("goActivateV2.sendActivationEmail") ||
              $t("goActivateV2.activateBtn")
            }}
          </el-button>
        </el-form-item>
      </el-form>

      <!-- 步骤说明(改为链接激活流程) -->
      <div class="steps-info">
        <h4>{{ $t("goActivateV2.stepsTitle") }}</h4>
        <ol>
          <li>
            {{ $t("goActivateV2.step1_link") || $t("goActivateV2.step1") }}
          </li>
          <li>
            {{ $t("goActivateV2.step2_link") || $t("goActivateV2.step2") }}
          </li>
          <li>
            {{ $t("goActivateV2.step3_link") || $t("goActivateV2.step3") }}
          </li>
        </ol>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, reactive, computed, onMounted } from "vue";
import { useRouter, useRoute } from "vue-router";
import { useI18n } from "vue-i18n";
import { ElMessage, type FormInstance, type FormRules } from "element-plus";
import { useAuthStore } from "@/stores/auth";

const router = useRouter();
const route = useRoute();
const { t } = useI18n();
const authStore = useAuthStore();

const activateFormRef = ref<FormInstance>();
const loading = ref(false);

const form = reactive({
  email: "",
});

// 从路由 query 参数中获取邮箱并回显
onMounted(() => {
  const emailFromQuery = route.query.email as string;
  if (emailFromQuery) {
    form.email = emailFromQuery;
  }
});

const rules = computed<FormRules>(() => ({
  email: [
    {
      required: true,
      message: "请输入邮箱地址",
      trigger: "blur",
    },
    {
      validator: (_rule: any, value: string, callback: any) => {
        const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
        if (value && !emailRegex.test(value)) {
          callback(new Error("邮箱格式不正确"));
        } else {
          callback();
        }
      },
      trigger: "blur",
    },
  ],
}));

const onSubmit = async () => {
  if (!activateFormRef.value) return;

  activateFormRef.value.validate(async (valid) => {
    if (!valid) return;
    loading.value = true;
    try {
      const res = await authStore.resendActivation(form.email);
      if (res && res.success) {
        ElMessage.success(
          t("goActivateV2.sendSuccess_link") ||
            "激活邮件已发送,请前往邮箱点击链接完成激活",
        );
        await router.push("/auth");
      } else {
        ElMessage.error(
          res?.message ||
            t("goActivateV2.sendFailed") ||
            "发送失败,请稍后重试",
        );
      }
    } catch (e) {
      ElMessage.error(t("goActivateV2.sendFailed") || "发送失败,请稍后重试");
    } finally {
      loading.value = false;
    }
  });
};

const goBack = () => {
  router.push("/auth");
};
</script>

<style scoped lang="scss">
.auth-bg {
  min-height: 100vh;
  background: var(--color-bg);
  display: flex;
  align-items: center;
  justify-content: center;
  position: relative;
}

.auth-container {
  background: var(--color-bg);
  border-radius: 20px;
  padding: 40px 32px 32px 32px;
  max-width: 400px;
  width: 90vw;
  box-shadow:
    0 8px 32px rgba(0, 0, 0, 0.08),
    0 4px 16px rgba(0, 0, 0, 0.04);
  position: relative;
  z-index: 1;
}

.back-button {
  position: absolute;
  top: 16px;
  left: 16px;
  width: 36px;
  height: 36px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(255, 255, 255, 0.1);
  border-radius: 8px;
  cursor: pointer;
  transition: all 0.3s ease;
  backdrop-filter: blur(10px);

  &:hover {
    background: rgba(255, 255, 255, 0.2);
    border-color: rgba(0, 0, 0, 0.15);
    transform: translateY(-1px);
  }

  .input-icon-svg {
    width: 16px;
    height: 16px;
    opacity: 0.8;
  }
}

.auth-header {
  text-align: center;
  margin-bottom: 24px;
}

.logo-container {
  width: auto;
  height: 64px;
  display: flex;
  align-items: center;
  justify-content: center;
  margin: 0 auto 6px;
  background: transparent;
  border-radius: 0;
  box-shadow: none;
  overflow: visible;
}

.logo-img {
  width: auto;
  height: 100%;
  object-fit: contain;
  border-radius: 0;
}

.auth-title {
  font-size: 24px;
  font-weight: 700;
  margin-bottom: 8px;
  color: #1e6fff;
  line-height: 1.3;
}

.auth-subtitle {
  font-size: 14px;
  color: #909399;
  margin-bottom: 8px;
}

.activate-form {
  margin-bottom: 24px;

  :deep(.el-form-item__label) {
    color: #606266;
    font-weight: 500;
    font-size: 14px;
    margin-bottom: 8px;
    padding: 0;
    line-height: 1.5;

    &::before {
      color: #f56c6c;
    }
  }

  :deep(.el-input__prefix) {
    display: flex;
    align-items: center;
    justify-content: center;
    height: 100%;

    .input-icon-svg {
      margin-left: 10px;
      margin-right: 6px;
      display: block;
    }
  }

  :deep(.el-input.is-focus .el-input__prefix .input-icon-svg) {
    opacity: 1;
  }

  :deep(.el-input__inner) {
    height: 42px;
    font-size: 16px;
    border-radius: 12px;
    background: var(--color-bg) !important;
    color: #606266 !important;
    transition: all 0.3s ease;
    &::placeholder {
      color: #c0c4cc;
      font-size: 16px;
    }
  }
}

.submit-btn {
  width: 100%;
  height: 44px;
  font-size: 16px;
  font-weight: 500;
  border-radius: 12px;
  background: linear-gradient(135deg, #3399ff 0%, #00c9ff 100%);
  border: none;
  box-shadow: 0 2px 8px rgba(51, 153, 255, 0.3);

  &:hover {
    box-shadow: 0 4px 12px rgba(51, 153, 255, 0.4);
  }

  &:active {
    box-shadow: 0 1px 4px rgba(51, 153, 255, 0.3);
  }
}

.steps-info {
  background: rgba(30, 111, 255, 0.05);
  border-radius: 12px;
  padding: 16px;
  border: 1px solid rgba(30, 111, 255, 0.1);
  font-size: 14px;

  h4 {
    color: #1e6fff;
    margin: 0 0 12px 0;
    font-size: 16px;
    font-weight: 600;
  }

  ol {
    margin: 0;
    padding-left: 20px;
    color: #606266;

    li {
      margin-bottom: 8px;
      line-height: 1.5;

      &:last-child {
        margin-bottom: 0;
      }
    }
  }
}

.input-icon-svg {
  width: 18px;
  height: 18px;
  object-fit: contain;
  flex-shrink: 0;
  opacity: 0.6;
  transition: opacity 0.3s ease;
  vertical-align: middle;
}
</style>