mirror of https://github.com/halo-dev/halo
refactor: layout of login related page (#5413)
#### What type of PR is this? /area ui /kind improvement /milestone 2.13.0 #### What this PR does / why we need it: 优化登录相关页面的布局,修复在不同分辨率下的样式问题。 #### Which issue(s) this PR fixes: Fixes https://github.com/halo-dev/halo/issues/5346 #### Special notes for your reviewer: 测试登录或者注册页面,任意放大或者缩小页面,观察页面样式是否正常。 #### Does this PR introduce a user-facing change? ```release-note 优化登录相关页面的布局,修复在不同分辨率下的样式问题。 ```pull/5422/head^2
parent
2bfa20d316
commit
827030dd68
|
@ -0,0 +1,13 @@
|
|||
<script lang="ts" setup>
|
||||
import IconLogo from "~icons/core/logo?width=5rem&height=2rem";
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
class="flex h-screen flex-col items-center overflow-auto bg-white/90 pt-[30vh]"
|
||||
>
|
||||
<IconLogo class="mb-8 flex-none" />
|
||||
|
||||
<RouterView />
|
||||
</div>
|
||||
</template>
|
|
@ -1,98 +0,0 @@
|
|||
<script lang="ts" setup>
|
||||
import { computed, watch } from "vue";
|
||||
import IconLogo from "~icons/core/logo?width=5rem&height=2rem";
|
||||
import LoginForm from "@/components/login/LoginForm.vue";
|
||||
import { useRouteQuery } from "@vueuse/router";
|
||||
import SignupForm from "@/components/signup/SignupForm.vue";
|
||||
import SocialAuthProviders from "@/components/login/SocialAuthProviders.vue";
|
||||
import { useGlobalInfoFetch } from "@console/composables/use-global-info";
|
||||
import { useTitle } from "@vueuse/core";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { AppName } from "@/constants/app";
|
||||
import MdiKeyboardBackspace from "~icons/mdi/keyboard-backspace";
|
||||
import LocaleChange from "@/components/common/LocaleChange.vue";
|
||||
|
||||
const { globalInfo } = useGlobalInfoFetch();
|
||||
const { t } = useI18n();
|
||||
|
||||
const SIGNUP_TYPE = "signup";
|
||||
|
||||
function onLoginSucceed() {
|
||||
window.location.reload();
|
||||
}
|
||||
|
||||
function onSignupSucceed() {
|
||||
window.location.href = "/uc";
|
||||
}
|
||||
|
||||
const type = useRouteQuery<string>("type", "");
|
||||
|
||||
function handleChangeType() {
|
||||
type.value = type.value === SIGNUP_TYPE ? "" : SIGNUP_TYPE;
|
||||
}
|
||||
|
||||
const isLoginType = computed(() => type.value !== SIGNUP_TYPE);
|
||||
|
||||
// page title
|
||||
const title = useTitle();
|
||||
watch(
|
||||
() => type.value,
|
||||
(value) => {
|
||||
const routeTitle = t(
|
||||
`core.${value === SIGNUP_TYPE ? SIGNUP_TYPE : "login"}.title`
|
||||
);
|
||||
title.value = [routeTitle, AppName].join(" - ");
|
||||
}
|
||||
);
|
||||
</script>
|
||||
<template>
|
||||
<div class="flex h-screen flex-col items-center bg-white/90 pt-[30vh]">
|
||||
<IconLogo class="mb-8" />
|
||||
<div class="flex w-72 flex-col">
|
||||
<SignupForm v-if="type === 'signup'" @succeed="onSignupSucceed" />
|
||||
<LoginForm v-else @succeed="onLoginSucceed" />
|
||||
<SocialAuthProviders />
|
||||
<div class="flex justify-center gap-2 pt-3.5 text-xs">
|
||||
<div v-if="globalInfo?.allowRegistration" class="space-x-0.5">
|
||||
<span class="text-slate-500">
|
||||
{{
|
||||
isLoginType
|
||||
? $t("core.login.operations.signup.label")
|
||||
: $t("core.login.operations.return_login.label")
|
||||
}},
|
||||
</span>
|
||||
<span
|
||||
class="cursor-pointer text-secondary hover:text-gray-600"
|
||||
@click="handleChangeType"
|
||||
>
|
||||
{{
|
||||
isLoginType
|
||||
? $t("core.login.operations.signup.button")
|
||||
: $t("core.login.operations.return_login.button")
|
||||
}}
|
||||
</span>
|
||||
</div>
|
||||
<RouterLink
|
||||
:to="{ name: 'ResetPassword' }"
|
||||
class="text-secondary hover:text-gray-600"
|
||||
>
|
||||
{{ $t("core.login.operations.reset_password.button") }}
|
||||
</RouterLink>
|
||||
</div>
|
||||
<div class="flex justify-center pt-3.5">
|
||||
<a
|
||||
class="inline-flex items-center gap-0.5 text-xs text-gray-600 hover:text-gray-900"
|
||||
href="/"
|
||||
>
|
||||
<MdiKeyboardBackspace class="!h-3.5 !w-3.5" />
|
||||
<span> {{ $t("core.login.operations.return_site") }} </span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="bottom-0 mb-10 mt-auto flex items-center justify-center gap-2.5"
|
||||
>
|
||||
<LocaleChange />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
|
@ -3,10 +3,8 @@ import BasicLayout from "@console/layouts/BasicLayout.vue";
|
|||
import UserStatsWidget from "./widgets/UserStatsWidget.vue";
|
||||
import UserList from "./UserList.vue";
|
||||
import UserDetail from "./UserDetail.vue";
|
||||
import Login from "./Login.vue";
|
||||
import { IconUserSettings } from "@halo-dev/components";
|
||||
import { markRaw } from "vue";
|
||||
import Binding from "./Binding.vue";
|
||||
import NotificationWidget from "./widgets/NotificationWidget.vue";
|
||||
|
||||
export default definePlugin({
|
||||
|
@ -15,22 +13,6 @@ export default definePlugin({
|
|||
NotificationWidget,
|
||||
},
|
||||
routes: [
|
||||
{
|
||||
path: "/login",
|
||||
name: "Login",
|
||||
component: Login,
|
||||
meta: {
|
||||
title: "core.login.title",
|
||||
},
|
||||
},
|
||||
{
|
||||
path: "/binding/:provider",
|
||||
name: "Binding",
|
||||
component: Binding,
|
||||
meta: {
|
||||
title: "core.binding.title",
|
||||
},
|
||||
},
|
||||
{
|
||||
path: "/users",
|
||||
name: "UsersRoot",
|
||||
|
|
|
@ -2,10 +2,13 @@ import type { RouteRecordRaw } from "vue-router";
|
|||
import NotFound from "@/views/exceptions/NotFound.vue";
|
||||
import Forbidden from "@/views/exceptions/Forbidden.vue";
|
||||
import BasicLayout from "@console/layouts/BasicLayout.vue";
|
||||
import GatewayLayout from "@console/layouts/GatewayLayout.vue";
|
||||
import Setup from "@console/views/system/Setup.vue";
|
||||
import Redirect from "@console/views/system/Redirect.vue";
|
||||
import SetupInitialData from "@console/views/system/SetupInitialData.vue";
|
||||
import ResetPassword from "@console/views/system/ResetPassword.vue";
|
||||
import Login from "@console/views/system/Login.vue";
|
||||
import Binding from "@console/views/system/Binding.vue";
|
||||
|
||||
export const routes: Array<RouteRecordRaw> = [
|
||||
{
|
||||
|
@ -24,14 +27,48 @@ export const routes: Array<RouteRecordRaw> = [
|
|||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: "/login",
|
||||
component: GatewayLayout,
|
||||
children: [
|
||||
{
|
||||
path: "",
|
||||
name: "Login",
|
||||
component: Login,
|
||||
meta: {
|
||||
title: "core.login.title",
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: "/binding/:provider",
|
||||
component: GatewayLayout,
|
||||
children: [
|
||||
{
|
||||
path: "",
|
||||
name: "Binding",
|
||||
component: Binding,
|
||||
meta: {
|
||||
title: "core.binding.title",
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: "/setup",
|
||||
component: GatewayLayout,
|
||||
children: [
|
||||
{
|
||||
path: "",
|
||||
name: "Setup",
|
||||
component: Setup,
|
||||
meta: {
|
||||
title: "core.setup.title",
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: "/setup-initial-data",
|
||||
name: "SetupInitialData",
|
||||
|
@ -47,12 +84,18 @@ export const routes: Array<RouteRecordRaw> = [
|
|||
},
|
||||
{
|
||||
path: "/reset-password",
|
||||
component: GatewayLayout,
|
||||
children: [
|
||||
{
|
||||
path: "",
|
||||
name: "ResetPassword",
|
||||
component: ResetPassword,
|
||||
meta: {
|
||||
title: "core.reset_password.title",
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
export default routes;
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
<script lang="ts" setup>
|
||||
import { computed, onBeforeMount, onMounted } from "vue";
|
||||
import router from "@console/router";
|
||||
import IconLogo from "~icons/core/logo?width=5rem&height=2rem";
|
||||
import { useUserStore } from "@/stores/user";
|
||||
import LoginForm from "@/components/login/LoginForm.vue";
|
||||
import { useRoute } from "vue-router";
|
||||
|
@ -51,8 +50,6 @@ function handleChangeType() {
|
|||
const isLoginType = computed(() => type.value !== "signup");
|
||||
</script>
|
||||
<template>
|
||||
<div class="flex h-screen flex-col items-center bg-white/90 pt-[30vh]">
|
||||
<IconLogo class="mb-8" />
|
||||
<div class="flex w-72 flex-col">
|
||||
<SignupForm
|
||||
v-if="type === 'signup'"
|
||||
|
@ -87,5 +84,4 @@ const isLoginType = computed(() => type.value !== "signup");
|
|||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
|
@ -0,0 +1,94 @@
|
|||
<script lang="ts" setup>
|
||||
import { computed, watch } from "vue";
|
||||
import LoginForm from "@/components/login/LoginForm.vue";
|
||||
import { useRouteQuery } from "@vueuse/router";
|
||||
import SignupForm from "@/components/signup/SignupForm.vue";
|
||||
import SocialAuthProviders from "@/components/login/SocialAuthProviders.vue";
|
||||
import { useGlobalInfoFetch } from "@console/composables/use-global-info";
|
||||
import { useTitle } from "@vueuse/core";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { AppName } from "@/constants/app";
|
||||
import MdiKeyboardBackspace from "~icons/mdi/keyboard-backspace";
|
||||
import LocaleChange from "@/components/common/LocaleChange.vue";
|
||||
|
||||
const { globalInfo } = useGlobalInfoFetch();
|
||||
const { t } = useI18n();
|
||||
|
||||
const SIGNUP_TYPE = "signup";
|
||||
|
||||
function onLoginSucceed() {
|
||||
window.location.reload();
|
||||
}
|
||||
|
||||
function onSignupSucceed() {
|
||||
window.location.href = "/uc";
|
||||
}
|
||||
|
||||
const type = useRouteQuery<string>("type", "");
|
||||
|
||||
function handleChangeType() {
|
||||
type.value = type.value === SIGNUP_TYPE ? "" : SIGNUP_TYPE;
|
||||
}
|
||||
|
||||
const isLoginType = computed(() => type.value !== SIGNUP_TYPE);
|
||||
|
||||
// page title
|
||||
const title = useTitle();
|
||||
watch(
|
||||
() => type.value,
|
||||
(value) => {
|
||||
const routeTitle = t(
|
||||
`core.${value === SIGNUP_TYPE ? SIGNUP_TYPE : "login"}.title`
|
||||
);
|
||||
title.value = [routeTitle, AppName].join(" - ");
|
||||
}
|
||||
);
|
||||
</script>
|
||||
<template>
|
||||
<div class="flex w-72 flex-col">
|
||||
<SignupForm v-if="type === 'signup'" @succeed="onSignupSucceed" />
|
||||
<LoginForm v-else @succeed="onLoginSucceed" />
|
||||
<SocialAuthProviders />
|
||||
<div class="flex justify-center gap-2 pt-3.5 text-xs">
|
||||
<div v-if="globalInfo?.allowRegistration" class="space-x-0.5">
|
||||
<span class="text-slate-500">
|
||||
{{
|
||||
isLoginType
|
||||
? $t("core.login.operations.signup.label")
|
||||
: $t("core.login.operations.return_login.label")
|
||||
}},
|
||||
</span>
|
||||
<span
|
||||
class="cursor-pointer text-secondary hover:text-gray-600"
|
||||
@click="handleChangeType"
|
||||
>
|
||||
{{
|
||||
isLoginType
|
||||
? $t("core.login.operations.signup.button")
|
||||
: $t("core.login.operations.return_login.button")
|
||||
}}
|
||||
</span>
|
||||
</div>
|
||||
<RouterLink
|
||||
:to="{ name: 'ResetPassword' }"
|
||||
class="text-secondary hover:text-gray-600"
|
||||
>
|
||||
{{ $t("core.login.operations.reset_password.button") }}
|
||||
</RouterLink>
|
||||
</div>
|
||||
<div class="flex justify-center pt-3.5">
|
||||
<a
|
||||
class="inline-flex items-center gap-0.5 text-xs text-gray-600 hover:text-gray-900"
|
||||
href="/"
|
||||
>
|
||||
<MdiKeyboardBackspace class="!h-3.5 !w-3.5" />
|
||||
<span> {{ $t("core.login.operations.return_site") }} </span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="bottom-0 mb-10 mt-auto flex items-center justify-center gap-2.5 pt-3.5"
|
||||
>
|
||||
<LocaleChange />
|
||||
</div>
|
||||
</template>
|
|
@ -3,7 +3,6 @@ import { apiClient } from "@/utils/api-client";
|
|||
import { Toast, VButton } from "@halo-dev/components";
|
||||
import { ref } from "vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import IconLogo from "~icons/core/logo?width=5rem&height=2rem";
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
|
@ -38,8 +37,6 @@ const inputClasses = {
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<div class="flex h-screen flex-col items-center bg-white/90 pt-[30vh]">
|
||||
<IconLogo class="mb-8" />
|
||||
<div class="flex w-72 flex-col">
|
||||
<FormKit
|
||||
id="reset-password-form"
|
||||
|
@ -81,5 +78,4 @@ const inputClasses = {
|
|||
{{ $t("core.reset_password.operations.send.label") }}
|
||||
</VButton>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
<script lang="ts" setup>
|
||||
import IconLogo from "~icons/core/logo?width=5rem&height=2rem";
|
||||
import { apiClient } from "@/utils/api-client";
|
||||
import { Toast, VButton } from "@halo-dev/components";
|
||||
import { ref } from "vue";
|
||||
|
@ -44,8 +43,6 @@ const inputClasses = {
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<div class="flex h-screen flex-col items-center bg-white/90 pt-[30vh]">
|
||||
<IconLogo class="mb-8" />
|
||||
<div class="flex w-72 flex-col">
|
||||
<FormKit
|
||||
id="setup-form"
|
||||
|
@ -121,10 +118,7 @@ const inputClasses = {
|
|||
{{ $t("core.setup.operations.submit.button") }}
|
||||
</VButton>
|
||||
</div>
|
||||
<div
|
||||
class="bottom-0 mb-10 mt-auto flex items-center justify-center gap-2.5"
|
||||
>
|
||||
<div class="bottom-0 mb-10 mt-auto flex items-center justify-center gap-2.5">
|
||||
<LocaleChange />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
@ -46,8 +46,10 @@ const inputClasses = {
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<div class="flex h-screen flex-col items-center bg-white/90 pt-[30vh]">
|
||||
<IconLogo class="mb-8" />
|
||||
<div
|
||||
class="flex h-screen flex-col items-center overflow-auto bg-white/90 pt-[30vh]"
|
||||
>
|
||||
<IconLogo class="mb-8 flex-none" />
|
||||
<div class="flex w-72 flex-col">
|
||||
<FormKit
|
||||
id="reset-password-form"
|
||||
|
|
Loading…
Reference in New Issue