Files
lgp-admin-plus/packages/effects/layouts/src/authentication/authentication.vue
xingyu a4736a49f8 feat: migrate to Tailwind CSS v4 (#7614)
* chore: update deps

* feat: use jsonc/x language

* chore: update eslint 10.0

* fix: no-useless-assignment

* feat: add CLAUDE.md

* chore: ignore

* feat: claude

* fix: lint

* chore: suppot eslint v10

* fix: lint

* fix: lint

* fix: type check

* fix: unit test

* fix: Suggested fix

* fix: unit test

* chore: update stylelint v17

* chore: update all major deps

* fix:  echarts console warn

* chore: update vitest v4

* feat: add skills ignores

* chore: update deps

* chore: update deps

* fix: cspell

* chore: update deps

* chore: update tailwindcss v4

* chore: remove postcss config

* fix: no use catalog

* chore: tailwind v4 config

* fix: tailwindcss v4 sort

* feat: use eslint-plugin-better-tailwindcss

* fix: Interference between enforce-consistent-line-wrapping, jsx-curly-brace-presence and Prettier

* fix: Interference between enforce-consistent-line-wrapping, jsx-curly-brace-presence and Prettier

* fix(lint): resolve prettier and better-tailwindcss formatting conflicts

* fix(tailwind): update theme references and lint sources

* style(format): normalize apps docs and playground vue files

* style(format): normalize core ui-kit components

* style(format): normalize effects ui and layout components
2026-03-10 05:08:45 +08:00

197 lines
5.1 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<script setup lang="ts">
import type { ToolbarType } from './types';
import { computed } from 'vue';
import { preferences, usePreferences } from '@vben/preferences';
import { Copyright } from '../basic/copyright';
import AuthenticationFormView from './form.vue';
import SloganIcon from './icons/slogan.vue';
import Toolbar from './toolbar.vue';
interface Props {
appName?: string;
logo?: string;
logoDark?: string;
pageTitle?: string;
pageDescription?: string;
sloganImage?: string;
toolbar?: boolean;
copyright?: boolean;
toolbarList?: ToolbarType[];
clickLogo?: () => void;
}
const props = withDefaults(defineProps<Props>(), {
appName: '',
copyright: true,
logo: '',
logoDark: '',
pageDescription: '',
pageTitle: '',
sloganImage: '',
toolbar: true,
toolbarList: () => ['color', 'language', 'layout', 'theme'],
clickLogo: () => {},
});
const { authPanelCenter, authPanelLeft, authPanelRight, isDark } =
usePreferences();
/**
* @zh_CN 根据主题选择合适的 logo 图标
*/
const logoSrc = computed(() => {
// 如果是暗色主题且提供了 logoDark,则使用暗色主题的 logo
if (isDark.value && props.logoDark) {
return props.logoDark;
}
// 否则使用默认的 logo
return props.logo;
});
</script>
<template>
<div
:class="[isDark ? 'dark' : '']"
class="flex min-h-full flex-1 overflow-x-hidden select-none"
>
<template v-if="toolbar">
<slot name="toolbar">
<Toolbar :toolbar-list="toolbarList" />
</slot>
</template>
<!-- 左侧认证面板 -->
<AuthenticationFormView
v-if="authPanelLeft"
class="min-h-full w-2/5 flex-1"
data-side="left"
>
<template v-if="copyright" #copyright>
<slot name="copyright">
<Copyright
v-if="preferences.copyright.enable"
v-bind="preferences.copyright"
/>
</slot>
</template>
</AuthenticationFormView>
<slot name="logo">
<!-- 头部 Logo 和应用名称 -->
<div
v-if="logoSrc || appName"
class="absolute top-0 left-0 z-10 flex flex-1"
@click="clickLogo"
>
<div
class="mt-4 ml-4 flex flex-1 items-center text-foreground sm:top-6 sm:left-6 lg:text-foreground"
>
<img
v-if="logoSrc"
:key="logoSrc"
:alt="appName"
:src="logoSrc"
class="mr-2"
width="42"
/>
<p v-if="appName" class="m-0 text-xl font-medium">
{{ appName }}
</p>
</div>
</div>
</slot>
<!-- 系统介绍 -->
<div v-if="!authPanelCenter" class="relative hidden w-0 flex-1 lg:block">
<div
class="absolute inset-0 size-full bg-background-deep dark:bg-[#070709]"
>
<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="{
'enter-x': authPanelLeft,
'-enter-x': authPanelRight,
}"
>
<template v-if="sloganImage">
<img
:alt="appName"
:src="sloganImage"
class="h-64 w-2/5 animate-float"
/>
</template>
<SloganIcon v-else :alt="appName" class="h-64 w-2/5 animate-float" />
<div class="text-1xl mt-6 font-sans text-foreground lg:text-2xl">
{{ pageTitle }}
</div>
<div class="mt-2 dark:text-muted-foreground">
{{ pageDescription }}
</div>
</div>
</div>
</div>
<!-- 中心认证面板 -->
<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%]"
data-side="bottom"
>
<template v-if="copyright" #copyright>
<slot name="copyright">
<Copyright
v-if="preferences.copyright.enable"
v-bind="preferences.copyright"
/>
</slot>
</template>
</AuthenticationFormView>
</div>
<!-- 右侧认证面板 -->
<AuthenticationFormView
v-if="authPanelRight"
class="min-h-full w-2/5 flex-1"
data-side="right"
>
<template v-if="copyright" #copyright>
<slot name="copyright">
<Copyright
v-if="preferences.copyright.enable"
v-bind="preferences.copyright"
/>
</slot>
</template>
</AuthenticationFormView>
</div>
</template>
<style scoped>
.login-background {
background: linear-gradient(
154deg,
#07070915 30%,
hsl(var(--primary) / 30%) 48%,
#07070915 64%
);
filter: blur(100px);
}
.dark {
.login-background {
background: linear-gradient(
154deg,
#07070915 30%,
hsl(var(--primary) / 20%) 48%,
#07070915 64%
);
filter: blur(100px);
}
}
</style>