2 天以前 3e71d77e7809a709ca2015306ab7ef7935dc82d7
style(auth): 优化认证页面样式和登录组件

- 调整认证面板样式,添加内边距和居中对齐
- 更新登录表单容器样式,增加边框和调整阴影效果
- 重构背景渐变效果,使用径向渐变替代线性渐变并调整模糊度
- 修改登录按钮样式,添加圆角、字体粗细和悬停阴影效果
- 调整复选框区域布局,统一垂直居中对齐
- 移除租户相关功能代码和依赖
- 修正类型定义,将 Recordable<any> 更新为 Recordable<unknown>
- 简化欢迎标题显示逻辑,移除表情符号
- 清理组件中的冗余导入和生命周期钩子
已修改3个文件
100 ■■■■ 文件已修改
src/packages/effects/common-ui/src/ui/authentication/login.vue 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/packages/effects/layouts/src/authentication/authentication.vue 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/_core/authentication/login.vue 66 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/packages/effects/common-ui/src/ui/authentication/login.vue
@@ -45,7 +45,7 @@
});
const emit = defineEmits<{
  submit: [Recordable<any>];
  submit: [Recordable<unknown>];
  thirdLogin: [type: number];
}>();
@@ -108,7 +108,7 @@
    <slot name="title">
      <Title>
        <slot name="title">
          {{ title || `${$t('authentication.welcomeBack')} 👋🏻` }}
          {{ title || $t('authentication.welcomeBack') }}
        </slot>
        <template #desc>
          <span class="text-muted-foreground">
@@ -124,7 +124,7 @@
    <div
      v-if="showRememberMe || showForgetPassword"
      class="mb-6 flex justify-between"
      class="mb-7 flex items-center justify-between"
    >
      <div class="flex-center">
        <VbenCheckbox
@@ -150,7 +150,7 @@
      }"
      :loading="loading"
      aria-label="login"
      class="w-full"
      class="h-11 w-full rounded-xl text-base font-semibold shadow-sm transition-shadow duration-200 hover:shadow-md focus-visible:ring-2 focus-visible:ring-primary/40"
      @click="handleSubmit"
    >
      {{ submitButtonText || $t('common.login') }}
src/packages/effects/layouts/src/authentication/authentication.vue
@@ -111,7 +111,7 @@
        <div class="login-background absolute top-0 left-0 size-full"></div>
        <div
          :key="authPanelLeft ? 'left' : authPanelRight ? 'right' : 'center'"
          class="mr-20 flex-col-center h-full"
          class="mr-20 flex-col-center h-full px-8 text-center"
          :class="{
            'enter-x': authPanelLeft,
            '-enter-x': authPanelRight,
@@ -139,7 +139,7 @@
    <div v-if="authPanelCenter" class="relative flex-center w-full">
      <div class="login-background absolute top-0 left-0 size-full"></div>
      <AuthenticationFormView
        class="w-full rounded-3xl pb-20 shadow-float shadow-primary/5 md:w-2/3 md:bg-background lg:w-1/2 xl:w-[36%]"
        class="w-full rounded-3xl border border-border/60 pb-20 shadow-float shadow-primary/10 md:w-2/3 md:bg-background/95 lg:w-1/2 xl:w-[36%]"
        data-side="bottom"
      >
        <template v-if="copyright" #copyright>
@@ -173,24 +173,18 @@
<style scoped>
.login-background {
  background: linear-gradient(
    154deg,
    #07070915 30%,
    hsl(var(--primary) / 30%) 48%,
    #07070915 64%
  );
  filter: blur(100px);
  background:
    radial-gradient(circle at 72% 38%, hsl(var(--primary) / 24%), transparent 42%),
    linear-gradient(145deg, hsl(var(--background-deep)) 0%, hsl(var(--background)) 100%);
  filter: blur(70px);
}
.dark {
  .login-background {
    background: linear-gradient(
      154deg,
      #07070915 30%,
      hsl(var(--primary) / 20%) 48%,
      #07070915 64%
    );
    filter: blur(100px);
    background:
      radial-gradient(circle at 72% 38%, hsl(var(--primary) / 18%), transparent 42%),
      linear-gradient(145deg, hsl(var(--background-deep)) 0%, hsl(var(--background)) 100%);
    filter: blur(70px);
  }
}
</style>
src/views/_core/authentication/login.vue
@@ -3,26 +3,18 @@
import type { AuthApi } from '#/api/core/auth';
import { computed, onMounted, ref } from 'vue';
import { computed, ref } from 'vue';
import { AuthenticationLogin, Verification, z } from '@vben/common-ui';
import { isCaptchaEnable, isTenantEnable } from '@vben/hooks';
import { isCaptchaEnable } from '@vben/hooks';
import { $t } from '@vben/locales';
import { useAccessStore } from '@vben/stores';
import {
  checkCaptcha,
  getCaptcha,
  getTenantByWebsite,
  getTenantSimpleList,
} from '#/api/core/auth';
import { checkCaptcha, getCaptcha } from '#/api/core/auth';
import { useAuthStore } from '#/store';
defineOptions({ name: 'Login' });
const authStore = useAuthStore();
const accessStore = useAccessStore();
const tenantEnable = isTenantEnable();
const captchaEnable = isCaptchaEnable();
const loginRef = ref();
@@ -30,69 +22,29 @@
const captchaType = 'blockPuzzle'; // 验证码类型:'blockPuzzle' | 'clickWord'
/** 获取租户列表 */
const tenantList = ref<AuthApi.TenantResult[]>([]); // 租户列表
async function fetchTenantList() {
  if (!tenantEnable) {
    return;
  }
  try {
    // 获取租户列表
    tenantList.value = await getTenantSimpleList();
  } catch (error) {
    console.error('获取租户列表失败:', error);
  }
}
/** 处理登录 */
async function handleLogin(values: any) {
  // 如果开启验证码,则先验证验证码
async function handleLogin(values: AuthApi.LoginParams) {
  if (captchaEnable) {
    verifyRef.value.show();
    return;
  }
  // 无验证码,直接登录
  await authStore.authLogin('username', values);
}
/** 验证码通过,执行登录 */
async function handleVerifySuccess({ captchaVerification }: any) {
  try {
async function handleVerifySuccess({
  captchaVerification,
}: {
  captchaVerification: string;
}) {
    await authStore.authLogin('username', {
      ...(await loginRef.value.getFormApi().getValues()),
      captchaVerification,
    });
  } catch (error) {
    console.error('Error in handleLogin:', error);
  }
}
/** 组件挂载时获取租户信息 */
onMounted(() => {
  fetchTenantList();
});
const formSchema = computed((): VbenFormSchema[] => {
  return [
    // {
    //   component: 'VbenSelect',
    //   componentProps: {
    //     options: tenantList.value.map((item) => ({
    //       label: item.name,
    //       value: item.id.toString(),
    //     })),
    //     placeholder: $t('authentication.tenantTip'),
    //   },
    //   fieldName: 'tenantId',
    //   label: $t('authentication.tenant'),
    //   dependencies: {
    //     triggerFields: ['tenantId'],
    //     if: tenantEnable,
    //     trigger(values) {
    //       accessStore.setTenantId(values.tenantId ? Number(values.tenantId) : null);
    //     },
    //   },
    // },
    {
      component: 'VbenInput',
      componentProps: {