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 UserStatsWidget from "./widgets/UserStatsWidget.vue";
|
||||||
import UserList from "./UserList.vue";
|
import UserList from "./UserList.vue";
|
||||||
import UserDetail from "./UserDetail.vue";
|
import UserDetail from "./UserDetail.vue";
|
||||||
import Login from "./Login.vue";
|
|
||||||
import { IconUserSettings } from "@halo-dev/components";
|
import { IconUserSettings } from "@halo-dev/components";
|
||||||
import { markRaw } from "vue";
|
import { markRaw } from "vue";
|
||||||
import Binding from "./Binding.vue";
|
|
||||||
import NotificationWidget from "./widgets/NotificationWidget.vue";
|
import NotificationWidget from "./widgets/NotificationWidget.vue";
|
||||||
|
|
||||||
export default definePlugin({
|
export default definePlugin({
|
||||||
|
@ -15,22 +13,6 @@ export default definePlugin({
|
||||||
NotificationWidget,
|
NotificationWidget,
|
||||||
},
|
},
|
||||||
routes: [
|
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",
|
path: "/users",
|
||||||
name: "UsersRoot",
|
name: "UsersRoot",
|
||||||
|
|
|
@ -2,10 +2,13 @@ import type { RouteRecordRaw } from "vue-router";
|
||||||
import NotFound from "@/views/exceptions/NotFound.vue";
|
import NotFound from "@/views/exceptions/NotFound.vue";
|
||||||
import Forbidden from "@/views/exceptions/Forbidden.vue";
|
import Forbidden from "@/views/exceptions/Forbidden.vue";
|
||||||
import BasicLayout from "@console/layouts/BasicLayout.vue";
|
import BasicLayout from "@console/layouts/BasicLayout.vue";
|
||||||
|
import GatewayLayout from "@console/layouts/GatewayLayout.vue";
|
||||||
import Setup from "@console/views/system/Setup.vue";
|
import Setup from "@console/views/system/Setup.vue";
|
||||||
import Redirect from "@console/views/system/Redirect.vue";
|
import Redirect from "@console/views/system/Redirect.vue";
|
||||||
import SetupInitialData from "@console/views/system/SetupInitialData.vue";
|
import SetupInitialData from "@console/views/system/SetupInitialData.vue";
|
||||||
import ResetPassword from "@console/views/system/ResetPassword.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> = [
|
export const routes: Array<RouteRecordRaw> = [
|
||||||
{
|
{
|
||||||
|
@ -24,13 +27,47 @@ 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",
|
path: "/setup",
|
||||||
name: "Setup",
|
component: GatewayLayout,
|
||||||
component: Setup,
|
children: [
|
||||||
meta: {
|
{
|
||||||
title: "core.setup.title",
|
path: "",
|
||||||
},
|
name: "Setup",
|
||||||
|
component: Setup,
|
||||||
|
meta: {
|
||||||
|
title: "core.setup.title",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/setup-initial-data",
|
path: "/setup-initial-data",
|
||||||
|
@ -47,11 +84,17 @@ export const routes: Array<RouteRecordRaw> = [
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/reset-password",
|
path: "/reset-password",
|
||||||
name: "ResetPassword",
|
component: GatewayLayout,
|
||||||
component: ResetPassword,
|
children: [
|
||||||
meta: {
|
{
|
||||||
title: "core.reset_password.title",
|
path: "",
|
||||||
},
|
name: "ResetPassword",
|
||||||
|
component: ResetPassword,
|
||||||
|
meta: {
|
||||||
|
title: "core.reset_password.title",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { computed, onBeforeMount, onMounted } from "vue";
|
import { computed, onBeforeMount, onMounted } from "vue";
|
||||||
import router from "@console/router";
|
import router from "@console/router";
|
||||||
import IconLogo from "~icons/core/logo?width=5rem&height=2rem";
|
|
||||||
import { useUserStore } from "@/stores/user";
|
import { useUserStore } from "@/stores/user";
|
||||||
import LoginForm from "@/components/login/LoginForm.vue";
|
import LoginForm from "@/components/login/LoginForm.vue";
|
||||||
import { useRoute } from "vue-router";
|
import { useRoute } from "vue-router";
|
||||||
|
@ -51,41 +50,38 @@ function handleChangeType() {
|
||||||
const isLoginType = computed(() => type.value !== "signup");
|
const isLoginType = computed(() => type.value !== "signup");
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<div class="flex h-screen flex-col items-center bg-white/90 pt-[30vh]">
|
<div class="flex w-72 flex-col">
|
||||||
<IconLogo class="mb-8" />
|
<SignupForm
|
||||||
<div class="flex w-72 flex-col">
|
v-if="type === 'signup'"
|
||||||
<SignupForm
|
button-text="core.binding.operations.signup_and_bind.button"
|
||||||
v-if="type === 'signup'"
|
@succeed="handleBinding"
|
||||||
button-text="core.binding.operations.signup_and_bind.button"
|
/>
|
||||||
@succeed="handleBinding"
|
<LoginForm
|
||||||
/>
|
v-else
|
||||||
<LoginForm
|
button-text="core.binding.operations.login_and_bind.button"
|
||||||
v-else
|
@succeed="handleBinding"
|
||||||
button-text="core.binding.operations.login_and_bind.button"
|
/>
|
||||||
@succeed="handleBinding"
|
<div
|
||||||
/>
|
v-if="globalInfo?.allowRegistration"
|
||||||
<div
|
class="flex justify-center gap-1 pt-3.5 text-xs"
|
||||||
v-if="globalInfo?.allowRegistration"
|
>
|
||||||
class="flex justify-center gap-1 pt-3.5 text-xs"
|
<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"
|
||||||
>
|
>
|
||||||
<span class="text-slate-500">
|
{{
|
||||||
{{
|
isLoginType
|
||||||
isLoginType
|
? $t("core.login.operations.signup.button")
|
||||||
? $t("core.login.operations.signup.label")
|
: $t("core.login.operations.return_login.button")
|
||||||
: $t("core.login.operations.return_login.label")
|
}}
|
||||||
}}
|
</span>
|
||||||
</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>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</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 { Toast, VButton } from "@halo-dev/components";
|
||||||
import { ref } from "vue";
|
import { ref } from "vue";
|
||||||
import { useI18n } from "vue-i18n";
|
import { useI18n } from "vue-i18n";
|
||||||
import IconLogo from "~icons/core/logo?width=5rem&height=2rem";
|
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
|
@ -38,48 +37,45 @@ const inputClasses = {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="flex h-screen flex-col items-center bg-white/90 pt-[30vh]">
|
<div class="flex w-72 flex-col">
|
||||||
<IconLogo class="mb-8" />
|
<FormKit
|
||||||
<div class="flex w-72 flex-col">
|
id="reset-password-form"
|
||||||
|
name="reset-password-form"
|
||||||
|
type="form"
|
||||||
|
:classes="{
|
||||||
|
form: '!divide-none',
|
||||||
|
}"
|
||||||
|
:config="{ validationVisibility: 'submit' }"
|
||||||
|
@submit="onSubmit"
|
||||||
|
@keyup.enter="$formkit.submit('reset-password-form')"
|
||||||
|
>
|
||||||
<FormKit
|
<FormKit
|
||||||
id="reset-password-form"
|
:classes="inputClasses"
|
||||||
name="reset-password-form"
|
name="username"
|
||||||
type="form"
|
:placeholder="$t('core.reset_password.fields.username.label')"
|
||||||
:classes="{
|
:validation-label="$t('core.reset_password.fields.username.label')"
|
||||||
form: '!divide-none',
|
:autofocus="true"
|
||||||
}"
|
type="text"
|
||||||
:config="{ validationVisibility: 'submit' }"
|
validation="required"
|
||||||
@submit="onSubmit"
|
></FormKit>
|
||||||
@keyup.enter="$formkit.submit('reset-password-form')"
|
<FormKit
|
||||||
>
|
:classes="inputClasses"
|
||||||
<FormKit
|
name="email"
|
||||||
:classes="inputClasses"
|
:placeholder="$t('core.reset_password.fields.email.label')"
|
||||||
name="username"
|
:validation-label="$t('core.reset_password.fields.email.label')"
|
||||||
:placeholder="$t('core.reset_password.fields.username.label')"
|
:autofocus="true"
|
||||||
:validation-label="$t('core.reset_password.fields.username.label')"
|
type="text"
|
||||||
:autofocus="true"
|
validation="required"
|
||||||
type="text"
|
></FormKit>
|
||||||
validation="required"
|
</FormKit>
|
||||||
></FormKit>
|
<VButton
|
||||||
<FormKit
|
class="mt-8"
|
||||||
:classes="inputClasses"
|
block
|
||||||
name="email"
|
:loading="loading"
|
||||||
:placeholder="$t('core.reset_password.fields.email.label')"
|
type="secondary"
|
||||||
:validation-label="$t('core.reset_password.fields.email.label')"
|
@click="$formkit.submit('reset-password-form')"
|
||||||
:autofocus="true"
|
>
|
||||||
type="text"
|
{{ $t("core.reset_password.operations.send.label") }}
|
||||||
validation="required"
|
</VButton>
|
||||||
></FormKit>
|
|
||||||
</FormKit>
|
|
||||||
<VButton
|
|
||||||
class="mt-8"
|
|
||||||
block
|
|
||||||
:loading="loading"
|
|
||||||
type="secondary"
|
|
||||||
@click="$formkit.submit('reset-password-form')"
|
|
||||||
>
|
|
||||||
{{ $t("core.reset_password.operations.send.label") }}
|
|
||||||
</VButton>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import IconLogo from "~icons/core/logo?width=5rem&height=2rem";
|
|
||||||
import { apiClient } from "@/utils/api-client";
|
import { apiClient } from "@/utils/api-client";
|
||||||
import { Toast, VButton } from "@halo-dev/components";
|
import { Toast, VButton } from "@halo-dev/components";
|
||||||
import { ref } from "vue";
|
import { ref } from "vue";
|
||||||
|
@ -44,87 +43,82 @@ const inputClasses = {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="flex h-screen flex-col items-center bg-white/90 pt-[30vh]">
|
<div class="flex w-72 flex-col">
|
||||||
<IconLogo class="mb-8" />
|
<FormKit
|
||||||
<div class="flex w-72 flex-col">
|
id="setup-form"
|
||||||
<FormKit
|
v-model="formState"
|
||||||
id="setup-form"
|
name="setup-form"
|
||||||
v-model="formState"
|
:actions="false"
|
||||||
name="setup-form"
|
:classes="{
|
||||||
:actions="false"
|
form: '!divide-none',
|
||||||
:classes="{
|
}"
|
||||||
form: '!divide-none',
|
:config="{ validationVisibility: 'submit' }"
|
||||||
}"
|
type="form"
|
||||||
:config="{ validationVisibility: 'submit' }"
|
@submit="handleSubmit"
|
||||||
type="form"
|
@keyup.enter="$formkit.submit('setup-form')"
|
||||||
@submit="handleSubmit"
|
|
||||||
@keyup.enter="$formkit.submit('setup-form')"
|
|
||||||
>
|
|
||||||
<FormKit
|
|
||||||
name="siteTitle"
|
|
||||||
:classes="inputClasses"
|
|
||||||
:autofocus="true"
|
|
||||||
type="text"
|
|
||||||
:validation-label="$t('core.setup.fields.site_title.label')"
|
|
||||||
:placeholder="$t('core.setup.fields.site_title.label')"
|
|
||||||
validation="required:trim|length:0,100"
|
|
||||||
></FormKit>
|
|
||||||
<FormKit
|
|
||||||
name="email"
|
|
||||||
:classes="inputClasses"
|
|
||||||
type="text"
|
|
||||||
:validation-label="$t('core.setup.fields.email.label')"
|
|
||||||
:placeholder="$t('core.setup.fields.email.label')"
|
|
||||||
validation="required|email|length:0,100"
|
|
||||||
></FormKit>
|
|
||||||
<FormKit
|
|
||||||
name="username"
|
|
||||||
:classes="inputClasses"
|
|
||||||
type="text"
|
|
||||||
:validation-label="$t('core.setup.fields.username.label')"
|
|
||||||
:placeholder="$t('core.setup.fields.username.label')"
|
|
||||||
:validation="[
|
|
||||||
['required'],
|
|
||||||
['length:0,63'],
|
|
||||||
[
|
|
||||||
'matches',
|
|
||||||
/^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$/,
|
|
||||||
],
|
|
||||||
]"
|
|
||||||
></FormKit>
|
|
||||||
<FormKit
|
|
||||||
name="password"
|
|
||||||
:classes="inputClasses"
|
|
||||||
type="password"
|
|
||||||
:validation-label="$t('core.setup.fields.password.label')"
|
|
||||||
:placeholder="$t('core.setup.fields.password.label')"
|
|
||||||
validation="required:trim|length:5,100|matches:/^\S.*\S$/"
|
|
||||||
autocomplete="current-password"
|
|
||||||
></FormKit>
|
|
||||||
<FormKit
|
|
||||||
name="password_confirm"
|
|
||||||
:classes="inputClasses"
|
|
||||||
type="password"
|
|
||||||
:validation-label="$t('core.setup.fields.confirm_password.label')"
|
|
||||||
:placeholder="$t('core.setup.fields.confirm_password.label')"
|
|
||||||
validation="confirm|required:trim|length:5,100|matches:/^\S.*\S$/"
|
|
||||||
autocomplete="current-password"
|
|
||||||
></FormKit>
|
|
||||||
</FormKit>
|
|
||||||
<VButton
|
|
||||||
block
|
|
||||||
class="mt-8"
|
|
||||||
type="secondary"
|
|
||||||
:loading="loading"
|
|
||||||
@click="$formkit.submit('setup-form')"
|
|
||||||
>
|
|
||||||
{{ $t("core.setup.operations.submit.button") }}
|
|
||||||
</VButton>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="bottom-0 mb-10 mt-auto flex items-center justify-center gap-2.5"
|
|
||||||
>
|
>
|
||||||
<LocaleChange />
|
<FormKit
|
||||||
</div>
|
name="siteTitle"
|
||||||
|
:classes="inputClasses"
|
||||||
|
:autofocus="true"
|
||||||
|
type="text"
|
||||||
|
:validation-label="$t('core.setup.fields.site_title.label')"
|
||||||
|
:placeholder="$t('core.setup.fields.site_title.label')"
|
||||||
|
validation="required:trim|length:0,100"
|
||||||
|
></FormKit>
|
||||||
|
<FormKit
|
||||||
|
name="email"
|
||||||
|
:classes="inputClasses"
|
||||||
|
type="text"
|
||||||
|
:validation-label="$t('core.setup.fields.email.label')"
|
||||||
|
:placeholder="$t('core.setup.fields.email.label')"
|
||||||
|
validation="required|email|length:0,100"
|
||||||
|
></FormKit>
|
||||||
|
<FormKit
|
||||||
|
name="username"
|
||||||
|
:classes="inputClasses"
|
||||||
|
type="text"
|
||||||
|
:validation-label="$t('core.setup.fields.username.label')"
|
||||||
|
:placeholder="$t('core.setup.fields.username.label')"
|
||||||
|
:validation="[
|
||||||
|
['required'],
|
||||||
|
['length:0,63'],
|
||||||
|
[
|
||||||
|
'matches',
|
||||||
|
/^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$/,
|
||||||
|
],
|
||||||
|
]"
|
||||||
|
></FormKit>
|
||||||
|
<FormKit
|
||||||
|
name="password"
|
||||||
|
:classes="inputClasses"
|
||||||
|
type="password"
|
||||||
|
:validation-label="$t('core.setup.fields.password.label')"
|
||||||
|
:placeholder="$t('core.setup.fields.password.label')"
|
||||||
|
validation="required:trim|length:5,100|matches:/^\S.*\S$/"
|
||||||
|
autocomplete="current-password"
|
||||||
|
></FormKit>
|
||||||
|
<FormKit
|
||||||
|
name="password_confirm"
|
||||||
|
:classes="inputClasses"
|
||||||
|
type="password"
|
||||||
|
:validation-label="$t('core.setup.fields.confirm_password.label')"
|
||||||
|
:placeholder="$t('core.setup.fields.confirm_password.label')"
|
||||||
|
validation="confirm|required:trim|length:5,100|matches:/^\S.*\S$/"
|
||||||
|
autocomplete="current-password"
|
||||||
|
></FormKit>
|
||||||
|
</FormKit>
|
||||||
|
<VButton
|
||||||
|
block
|
||||||
|
class="mt-8"
|
||||||
|
type="secondary"
|
||||||
|
:loading="loading"
|
||||||
|
@click="$formkit.submit('setup-form')"
|
||||||
|
>
|
||||||
|
{{ $t("core.setup.operations.submit.button") }}
|
||||||
|
</VButton>
|
||||||
|
</div>
|
||||||
|
<div class="bottom-0 mb-10 mt-auto flex items-center justify-center gap-2.5">
|
||||||
|
<LocaleChange />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -46,8 +46,10 @@ const inputClasses = {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="flex h-screen flex-col items-center bg-white/90 pt-[30vh]">
|
<div
|
||||||
<IconLogo class="mb-8" />
|
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">
|
<div class="flex w-72 flex-col">
|
||||||
<FormKit
|
<FormKit
|
||||||
id="reset-password-form"
|
id="reset-password-form"
|
||||||
|
|
Loading…
Reference in New Issue