注册页面、修改密码页面。
parent
7841e706f6
commit
f467cc9203
|
@ -0,0 +1,21 @@
|
||||||
|
<template>
|
||||||
|
<div class="page">
|
||||||
|
<RouterView />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup></script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.page {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
color: #666666;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -2,6 +2,7 @@ import { createRouter, createWebHistory } from "vue-router";
|
||||||
import MainPage from "../layouts/MainPage/MainPage.vue";
|
import MainPage from "../layouts/MainPage/MainPage.vue";
|
||||||
import Login from "../views/Login/Login.vue";
|
import Login from "../views/Login/Login.vue";
|
||||||
import Page404 from "../views/404/index.vue";
|
import Page404 from "../views/404/index.vue";
|
||||||
|
import UserLayout from "@/layouts/UserLayout/UserLayout.vue";
|
||||||
|
|
||||||
const router = createRouter({
|
const router = createRouter({
|
||||||
history: createWebHistory(import.meta.env.BASE_URL),
|
history: createWebHistory(import.meta.env.BASE_URL),
|
||||||
|
@ -18,9 +19,25 @@ const router = createRouter({
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/login",
|
path: "",
|
||||||
name: "login",
|
component: UserLayout,
|
||||||
component: Login,
|
children: [
|
||||||
|
{
|
||||||
|
path: "/login",
|
||||||
|
name: "login",
|
||||||
|
component: Login,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/register",
|
||||||
|
name: "register",
|
||||||
|
component: () => import("@/views/Register/Register.vue"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/changePassword",
|
||||||
|
name: "changePassword",
|
||||||
|
component: () => import("@/views/ChangePassword/ChangePassword.vue"),
|
||||||
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
export interface ChangePasswordByOTPCommand {
|
||||||
|
principal: string;
|
||||||
|
otp: string;
|
||||||
|
password: string;
|
||||||
|
reenteredPassword: string;
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
export interface RegisterCommand {
|
||||||
|
principal: string;
|
||||||
|
username: string;
|
||||||
|
code: string;
|
||||||
|
password: string;
|
||||||
|
reenteredPassword: string;
|
||||||
|
}
|
|
@ -1,28 +1,149 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="login-page">
|
<div class="form-container">
|
||||||
<LoginByPassword v-if="loginByPassword" @toLoginByOTP="loginByPassword = false" />
|
<div class="title">
|
||||||
<LoginByOTP v-else @toLoginByPassword="loginByPassword = true" />
|
<span style="color: #6777ef">Plusone </span>
|
||||||
|
<span style="font-weight: 300">Admin</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<n-form
|
||||||
|
ref="formRef"
|
||||||
|
:model="model"
|
||||||
|
:rules="rules"
|
||||||
|
:show-feedback="false"
|
||||||
|
:show-label="false"
|
||||||
|
size="large"
|
||||||
|
>
|
||||||
|
<n-form-item path="principal">
|
||||||
|
<n-input
|
||||||
|
placeholder="邮箱地址 / 手机号"
|
||||||
|
v-model:value="model.principal"
|
||||||
|
@keydown.enter.prevent
|
||||||
|
/>
|
||||||
|
</n-form-item>
|
||||||
|
|
||||||
|
<n-grid y-gap="24" :cols="24">
|
||||||
|
<n-gi :span="15">
|
||||||
|
<n-form-item path="otp">
|
||||||
|
<n-input placeholder="验证码" v-model:value="model.otp" />
|
||||||
|
</n-form-item>
|
||||||
|
</n-gi>
|
||||||
|
<n-gi :span="9">
|
||||||
|
<div style="display: flex; justify-content: flex-end">
|
||||||
|
<n-button
|
||||||
|
class="txt-btn"
|
||||||
|
@click="handleBtnGetOTPClick"
|
||||||
|
size="large"
|
||||||
|
style="width: 100%"
|
||||||
|
>
|
||||||
|
获取验证码
|
||||||
|
</n-button>
|
||||||
|
</div>
|
||||||
|
</n-gi>
|
||||||
|
</n-grid>
|
||||||
|
|
||||||
|
<n-form-item path="password">
|
||||||
|
<n-input placeholder="密码" v-model:value="model.password" type="password" />
|
||||||
|
</n-form-item>
|
||||||
|
|
||||||
|
<n-form-item path="reenteredPassword">
|
||||||
|
<n-input placeholder="重复密码" v-model:value="model.reenteredPassword" type="password" />
|
||||||
|
</n-form-item>
|
||||||
|
|
||||||
|
<n-button
|
||||||
|
type="primary"
|
||||||
|
size="large"
|
||||||
|
style="width: 100%; margin-top: 8px; margin-bottom: 8px;"
|
||||||
|
@click="handleBtnChangePasswordClick"
|
||||||
|
>
|
||||||
|
修改密码
|
||||||
|
</n-button>
|
||||||
|
</n-form>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref } from "vue";
|
import { ref } from "vue";
|
||||||
import LoginByPassword from "./components/ChangePasswordByPassword.vue";
|
import type { FormInst, FormItemRule, FormRules } from "naive-ui";
|
||||||
import LoginByOTP from "./components/ChangePasswordByOTP.vue";
|
import type { ChangePasswordByOTPCommand } from "@/type/commands/ChangePasswordCommand";
|
||||||
|
|
||||||
const loginByPassword = ref(true);
|
const formRef = ref<FormInst | null>(null);
|
||||||
|
const model = ref<ChangePasswordByOTPCommand>({
|
||||||
|
principal: "",
|
||||||
|
otp: "",
|
||||||
|
password: "",
|
||||||
|
reenteredPassword: "",
|
||||||
|
});
|
||||||
|
|
||||||
|
const rules: FormRules = {
|
||||||
|
principal: [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
validator(rule: FormItemRule, value: string) {
|
||||||
|
if (!value) {
|
||||||
|
return new Error("需要年龄");
|
||||||
|
} else if (!/^\d*$/.test(value)) {
|
||||||
|
return new Error("年龄应该为整数");
|
||||||
|
} else if (Number(value) < 18) {
|
||||||
|
return new Error("年龄应该超过十八岁");
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
trigger: ["input", "blur"],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
otp: [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: "请输入密码",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
function handleBtnChangePasswordClick(e: MouseEvent) {
|
||||||
|
e.preventDefault();
|
||||||
|
formRef.value?.validate((errors) => {
|
||||||
|
if (!errors) {
|
||||||
|
window.$message.success("验证成功");
|
||||||
|
} else {
|
||||||
|
console.log(errors);
|
||||||
|
window.$message.error("验证失败");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleBtnGetOTPClick() {
|
||||||
|
console.log("handleBtnGetOTPClick");
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.login-page {
|
.form-container {
|
||||||
position: absolute;
|
width: 320px;
|
||||||
top: 0;
|
background-color: #f3f3f3;
|
||||||
right: 0;
|
padding: 32px 40px;
|
||||||
bottom: 0;
|
border-radius: 6px;
|
||||||
left: 0;
|
border: solid 1px #e4e4e4;
|
||||||
display: flex;
|
box-shadow: 0 4px 24px 0 rgba(0, 0, 0, 0.2);
|
||||||
align-items: center;
|
border-top: solid 4px #6777ef;
|
||||||
justify-content: center;
|
}
|
||||||
color: #666666;
|
|
||||||
|
.title {
|
||||||
|
font-size: 30px;
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.n-form-item {
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.txt-btn {
|
||||||
|
line-height: 40px;
|
||||||
|
font-size: 15px;
|
||||||
|
color: #6777ef;
|
||||||
|
}
|
||||||
|
|
||||||
|
.txt-btn:hover {
|
||||||
|
color: rgba(103, 119, 239, 0.8);
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -1,179 +0,0 @@
|
||||||
<template>
|
|
||||||
<div class="login-form-container">
|
|
||||||
<div class="title">
|
|
||||||
<span style="color: #6777ef">Plusone </span>
|
|
||||||
<span style="font-weight: 300">Admin</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<n-form
|
|
||||||
ref="formRef"
|
|
||||||
:model="model"
|
|
||||||
:rules="rules"
|
|
||||||
:show-feedback="false"
|
|
||||||
:show-label="false"
|
|
||||||
size="large"
|
|
||||||
>
|
|
||||||
<n-form-item path="principal">
|
|
||||||
<n-input
|
|
||||||
placeholder="邮箱地址 / 手机号"
|
|
||||||
v-model:value="model.principal"
|
|
||||||
@keydown.enter.prevent
|
|
||||||
/>
|
|
||||||
</n-form-item>
|
|
||||||
|
|
||||||
<n-grid y-gap="24" :cols="24">
|
|
||||||
<n-gi :span="15">
|
|
||||||
<n-form-item path="password">
|
|
||||||
<n-input
|
|
||||||
placeholder="验证码"
|
|
||||||
v-model:value="model.otp"
|
|
||||||
@input="handlePasswordInput"
|
|
||||||
@keydown.enter.prevent
|
|
||||||
/>
|
|
||||||
</n-form-item>
|
|
||||||
</n-gi>
|
|
||||||
<n-gi :span="9">
|
|
||||||
<div style="display: flex; justify-content: flex-end">
|
|
||||||
<n-button
|
|
||||||
class="txt-btn"
|
|
||||||
@click="handleBtnGetOTPClick"
|
|
||||||
size="large"
|
|
||||||
style="width: 100%"
|
|
||||||
>
|
|
||||||
获取验证码
|
|
||||||
</n-button>
|
|
||||||
</div>
|
|
||||||
</n-gi>
|
|
||||||
</n-grid>
|
|
||||||
|
|
||||||
<n-grid y-gap="24" :cols="2">
|
|
||||||
<n-gi>
|
|
||||||
<n-form-item path="rememberMe">
|
|
||||||
<n-checkbox v-model:checked="model.rememberMe" size="large">
|
|
||||||
<span style="color: #808080">保持登录状态</span>
|
|
||||||
</n-checkbox>
|
|
||||||
</n-form-item>
|
|
||||||
</n-gi>
|
|
||||||
<n-gi>
|
|
||||||
<div style="display: flex; justify-content: flex-end">
|
|
||||||
<n-button class="txt-btn" text @click="$emit('toLoginByPassword')">
|
|
||||||
密码登录
|
|
||||||
</n-button>
|
|
||||||
</div>
|
|
||||||
</n-gi>
|
|
||||||
</n-grid>
|
|
||||||
|
|
||||||
<n-button
|
|
||||||
type="primary"
|
|
||||||
size="large"
|
|
||||||
style="width: 100%; margin-top: 8px"
|
|
||||||
@click="handleBtnLoginClick"
|
|
||||||
>
|
|
||||||
登录
|
|
||||||
</n-button>
|
|
||||||
|
|
||||||
<div style="display: flex; justify-content: flex-end; margin-top: 8px">
|
|
||||||
<n-button class="txt-btn" text style="margin-left: 16px"> 忘记密码 </n-button>
|
|
||||||
<n-button class="txt-btn" text style="margin-left: 16px"> 免费注册 </n-button>
|
|
||||||
</div>
|
|
||||||
</n-form>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts" setup>
|
|
||||||
import { ref } from "vue";
|
|
||||||
import type { FormInst, FormItemInst, FormItemRule, FormRules } from "naive-ui";
|
|
||||||
|
|
||||||
interface LoginByPasswordCommand {
|
|
||||||
principal: string;
|
|
||||||
otp: string;
|
|
||||||
rememberMe: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
const formRef = ref<FormInst | null>(null);
|
|
||||||
const rPasswordFormItemRef = ref<FormItemInst | null>(null);
|
|
||||||
const model = ref<LoginByPasswordCommand>({
|
|
||||||
principal: "",
|
|
||||||
otp: "",
|
|
||||||
rememberMe: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
const rules: FormRules = {
|
|
||||||
principal: [
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
validator(rule: FormItemRule, value: string) {
|
|
||||||
if (!value) {
|
|
||||||
return new Error("需要年龄");
|
|
||||||
} else if (!/^\d*$/.test(value)) {
|
|
||||||
return new Error("年龄应该为整数");
|
|
||||||
} else if (Number(value) < 18) {
|
|
||||||
return new Error("年龄应该超过十八岁");
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
trigger: ["input", "blur"],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
otp: [
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
message: "请输入密码",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
|
|
||||||
function handlePasswordInput() {
|
|
||||||
if (model.value.rememberMe) {
|
|
||||||
rPasswordFormItemRef.value?.validate({ trigger: "password-input" });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleBtnLoginClick(e: MouseEvent) {
|
|
||||||
e.preventDefault();
|
|
||||||
formRef.value?.validate((errors) => {
|
|
||||||
if (!errors) {
|
|
||||||
window.$message.success("验证成功");
|
|
||||||
} else {
|
|
||||||
console.log(errors);
|
|
||||||
window.$message.error("验证失败");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleBtnGetOTPClick() {
|
|
||||||
console.log("handleBtnGetOTPClick");
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.login-form-container {
|
|
||||||
width: 320px;
|
|
||||||
background-color: #f3f3f3;
|
|
||||||
padding: 32px 40px;
|
|
||||||
border-radius: 6px;
|
|
||||||
border: solid 1px #e4e4e4;
|
|
||||||
box-shadow: 0 4px 24px 0 rgba(0, 0, 0, 0.2);
|
|
||||||
border-top: solid 4px #6777ef;
|
|
||||||
}
|
|
||||||
|
|
||||||
.title {
|
|
||||||
font-size: 30px;
|
|
||||||
text-align: center;
|
|
||||||
margin-bottom: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.n-form-item {
|
|
||||||
margin-bottom: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.txt-btn {
|
|
||||||
line-height: 40px;
|
|
||||||
font-size: 15px;
|
|
||||||
color: #6777ef;
|
|
||||||
}
|
|
||||||
|
|
||||||
.txt-btn:hover {
|
|
||||||
color: rgba(103, 119, 239, 0.8);
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -1,159 +0,0 @@
|
||||||
<template>
|
|
||||||
<div class="login-form-container">
|
|
||||||
<div class="title">
|
|
||||||
<span style="color: #6777ef">Plusone </span>
|
|
||||||
<span style="font-weight: 300">Admin</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<n-form
|
|
||||||
ref="formRef"
|
|
||||||
:model="model"
|
|
||||||
:rules="rules"
|
|
||||||
:show-feedback="false"
|
|
||||||
:show-label="false"
|
|
||||||
size="large"
|
|
||||||
>
|
|
||||||
<n-form-item path="principal">
|
|
||||||
<n-input
|
|
||||||
placeholder="用户名 / 邮箱地址 / 手机号"
|
|
||||||
v-model:value="model.principal"
|
|
||||||
@keydown.enter.prevent
|
|
||||||
/>
|
|
||||||
</n-form-item>
|
|
||||||
<n-form-item path="password">
|
|
||||||
<n-input
|
|
||||||
placeholder="密码"
|
|
||||||
v-model:value="model.password"
|
|
||||||
type="password"
|
|
||||||
@input="handlePasswordInput"
|
|
||||||
@keydown.enter.prevent
|
|
||||||
/>
|
|
||||||
</n-form-item>
|
|
||||||
|
|
||||||
<n-grid y-gap="24" :cols="2">
|
|
||||||
<n-gi>
|
|
||||||
<n-form-item path="rememberMe">
|
|
||||||
<n-checkbox v-model:checked="model.rememberMe" size="large">
|
|
||||||
<span style="color: #808080">保持登录状态</span>
|
|
||||||
</n-checkbox>
|
|
||||||
</n-form-item>
|
|
||||||
</n-gi>
|
|
||||||
<n-gi>
|
|
||||||
<div style="display: flex; justify-content: flex-end">
|
|
||||||
<n-button class="txt-btn" text @click="$emit('toLoginByOTP')"> 验证码登录 </n-button>
|
|
||||||
</div>
|
|
||||||
</n-gi>
|
|
||||||
</n-grid>
|
|
||||||
|
|
||||||
<n-button
|
|
||||||
type="primary"
|
|
||||||
size="large"
|
|
||||||
style="width: 100%; margin-top: 8px"
|
|
||||||
@click="handleBtnLoginClick"
|
|
||||||
>
|
|
||||||
登录
|
|
||||||
</n-button>
|
|
||||||
|
|
||||||
<div style="display: flex; justify-content: flex-end; margin-top: 8px">
|
|
||||||
<n-button class="txt-btn" text style="margin-left: 16px"> 忘记密码 </n-button>
|
|
||||||
<n-button class="txt-btn" text style="margin-left: 16px"> 免费注册 </n-button>
|
|
||||||
</div>
|
|
||||||
</n-form>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts" setup>
|
|
||||||
import { ref } from "vue";
|
|
||||||
import type { FormInst, FormItemInst, FormItemRule, FormRules } from "naive-ui";
|
|
||||||
import type { PrincipalType } from "@/type/PrincipalType";
|
|
||||||
|
|
||||||
interface LoginByPasswordCommand {
|
|
||||||
principal: string;
|
|
||||||
password: string;
|
|
||||||
rememberMe: boolean;
|
|
||||||
principalType?: PrincipalType;
|
|
||||||
}
|
|
||||||
|
|
||||||
const formRef = ref<FormInst | null>(null);
|
|
||||||
const rPasswordFormItemRef = ref<FormItemInst | null>(null);
|
|
||||||
const model = ref<LoginByPasswordCommand>({
|
|
||||||
principal: "",
|
|
||||||
password: "",
|
|
||||||
rememberMe: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
const rules: FormRules = {
|
|
||||||
principal: [
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
validator(rule: FormItemRule, value: string) {
|
|
||||||
if (!value) {
|
|
||||||
return new Error("需要年龄");
|
|
||||||
} else if (!/^\d*$/.test(value)) {
|
|
||||||
return new Error("年龄应该为整数");
|
|
||||||
} else if (Number(value) < 18) {
|
|
||||||
return new Error("年龄应该超过十八岁");
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
trigger: ["input", "blur"],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
password: [
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
message: "请输入密码",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
|
|
||||||
function handlePasswordInput() {
|
|
||||||
if (model.value.rememberMe) {
|
|
||||||
rPasswordFormItemRef.value?.validate({ trigger: "password-input" });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleBtnLoginClick(e: MouseEvent) {
|
|
||||||
e.preventDefault();
|
|
||||||
formRef.value?.validate((errors) => {
|
|
||||||
if (!errors) {
|
|
||||||
window.$message.success("验证成功");
|
|
||||||
} else {
|
|
||||||
console.log(errors);
|
|
||||||
window.$message.error("验证失败");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.login-form-container {
|
|
||||||
width: 320px;
|
|
||||||
background-color: #f3f3f3;
|
|
||||||
padding: 32px 40px;
|
|
||||||
border-radius: 6px;
|
|
||||||
border: solid 1px #e4e4e4;
|
|
||||||
box-shadow: 0 4px 24px 0 rgba(0, 0, 0, 0.2);
|
|
||||||
border-top: solid 4px #6777ef;
|
|
||||||
}
|
|
||||||
|
|
||||||
.title {
|
|
||||||
font-size: 30px;
|
|
||||||
text-align: center;
|
|
||||||
margin-bottom: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.n-form-item {
|
|
||||||
margin-bottom: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.txt-btn {
|
|
||||||
line-height: 40px;
|
|
||||||
font-size: 15px;
|
|
||||||
color: #6777ef;
|
|
||||||
}
|
|
||||||
|
|
||||||
.txt-btn:hover {
|
|
||||||
color: rgba(103, 119, 239, 0.8);
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -1,8 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="login-page">
|
<LoginByPassword v-if="loginByPassword" @toLoginByOTP="loginByPassword = false" />
|
||||||
<LoginByPassword v-if="loginByPassword" @toLoginByOTP="loginByPassword = false" />
|
<LoginByOTP v-else @toLoginByPassword="loginByPassword = true" />
|
||||||
<LoginByOTP v-else @toLoginByPassword="loginByPassword = true" />
|
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
@ -12,17 +10,3 @@ import LoginByOTP from "./components/LoginByOTP.vue";
|
||||||
|
|
||||||
const loginByPassword = ref(true);
|
const loginByPassword = ref(true);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.login-page {
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
right: 0;
|
|
||||||
bottom: 0;
|
|
||||||
left: 0;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
color: #666666;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
|
@ -21,9 +21,9 @@
|
||||||
/>
|
/>
|
||||||
</n-form-item>
|
</n-form-item>
|
||||||
|
|
||||||
<n-grid y-gap="24" :cols="24">
|
<n-grid x-gap="8" :cols="24">
|
||||||
<n-gi :span="15">
|
<n-gi :span="15">
|
||||||
<n-form-item path="password">
|
<n-form-item path="otp">
|
||||||
<n-input
|
<n-input
|
||||||
placeholder="验证码"
|
placeholder="验证码"
|
||||||
v-model:value="model.otp"
|
v-model:value="model.otp"
|
||||||
|
@ -73,8 +73,9 @@
|
||||||
</n-button>
|
</n-button>
|
||||||
|
|
||||||
<div style="display: flex; justify-content: flex-end; margin-top: 8px">
|
<div style="display: flex; justify-content: flex-end; margin-top: 8px">
|
||||||
<n-button class="txt-btn" text style="margin-left: 16px"> 忘记密码 </n-button>
|
<n-button class="txt-btn" text style="margin-left: 16px" @click="$router.push('/register')">
|
||||||
<n-button class="txt-btn" text style="margin-left: 16px"> 免费注册 </n-button>
|
免费注册
|
||||||
|
</n-button>
|
||||||
</div>
|
</div>
|
||||||
</n-form>
|
</n-form>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -18,7 +18,6 @@
|
||||||
placeholder="密码"
|
placeholder="密码"
|
||||||
v-model:value="model.password"
|
v-model:value="model.password"
|
||||||
type="password"
|
type="password"
|
||||||
@input="handlePasswordInput"
|
|
||||||
@keydown.enter.prevent
|
@keydown.enter.prevent
|
||||||
/>
|
/>
|
||||||
</n-form-item>
|
</n-form-item>
|
||||||
|
@ -48,8 +47,17 @@
|
||||||
</n-button>
|
</n-button>
|
||||||
|
|
||||||
<div style="display: flex; justify-content: flex-end; margin-top: 8px">
|
<div style="display: flex; justify-content: flex-end; margin-top: 8px">
|
||||||
<n-button class="txt-btn" text style="margin-left: 16px"> 忘记密码 </n-button>
|
<n-button
|
||||||
<n-button class="txt-btn" text style="margin-left: 16px"> 免费注册 </n-button>
|
class="txt-btn"
|
||||||
|
text
|
||||||
|
style="margin-left: 16px"
|
||||||
|
@click="$router.push('/changePassword')"
|
||||||
|
>
|
||||||
|
忘记密码
|
||||||
|
</n-button>
|
||||||
|
<n-button class="txt-btn" text style="margin-left: 16px" @click="$router.push('/register')">
|
||||||
|
免费注册
|
||||||
|
</n-button>
|
||||||
</div>
|
</div>
|
||||||
</n-form>
|
</n-form>
|
||||||
</div>
|
</div>
|
||||||
|
@ -57,13 +65,12 @@
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref } from "vue";
|
import { ref } from "vue";
|
||||||
import type { FormInst, FormItemInst } from "naive-ui";
|
import type { FormInst } from "naive-ui";
|
||||||
import { PrincipalType, regexConsts } from "@/type/PrincipalType";
|
import { PrincipalType, regexConsts } from "@/type/PrincipalType";
|
||||||
import type { LoginByPasswordCommand } from "@/type/commands/LoginCommands";
|
import type { LoginByPasswordCommand } from "@/type/commands/LoginCommands";
|
||||||
import { loginByPassword } from "@/api/account";
|
import { loginByPassword } from "@/api/account";
|
||||||
|
|
||||||
const formRef = ref<FormInst | null>(null);
|
const formRef = ref<FormInst | null>(null);
|
||||||
const rPasswordFormItemRef = ref<FormItemInst | null>(null);
|
|
||||||
const model = ref<LoginByPasswordCommand>({
|
const model = ref<LoginByPasswordCommand>({
|
||||||
principal: "",
|
principal: "",
|
||||||
password: "",
|
password: "",
|
||||||
|
@ -71,12 +78,6 @@ const model = ref<LoginByPasswordCommand>({
|
||||||
principalType: null,
|
principalType: null,
|
||||||
});
|
});
|
||||||
|
|
||||||
function handlePasswordInput() {
|
|
||||||
if (model.value.rememberMe) {
|
|
||||||
rPasswordFormItemRef.value?.validate({ trigger: "password-input" });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleBtnLoginClick(e: MouseEvent) {
|
function handleBtnLoginClick(e: MouseEvent) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
const principal = model.value.principal;
|
const principal = model.value.principal;
|
||||||
|
|
|
@ -0,0 +1,123 @@
|
||||||
|
<template>
|
||||||
|
<div class="form-container">
|
||||||
|
<div class="title">
|
||||||
|
<span style="color: #6777ef">Plusone </span>
|
||||||
|
<span style="font-weight: 300">Admin</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<n-form ref="formRef" :model="model" :show-feedback="false" :show-label="false" size="large">
|
||||||
|
<n-form-item path="principal">
|
||||||
|
<n-input placeholder="邮箱地址 / 手机号" v-model:value="model.principal" />
|
||||||
|
</n-form-item>
|
||||||
|
|
||||||
|
<n-form-item path="username">
|
||||||
|
<n-input placeholder="用户名" v-model:value="model.username" />
|
||||||
|
</n-form-item>
|
||||||
|
|
||||||
|
<n-grid y-gap="24" :cols="24">
|
||||||
|
<n-gi :span="15">
|
||||||
|
<n-form-item path="code">
|
||||||
|
<n-input placeholder="验证码" v-model:value="model.code" />
|
||||||
|
</n-form-item>
|
||||||
|
</n-gi>
|
||||||
|
<n-gi :span="9">
|
||||||
|
<div style="display: flex; justify-content: flex-end">
|
||||||
|
<n-button
|
||||||
|
class="txt-btn"
|
||||||
|
@click="handleBtnGetOTPClick"
|
||||||
|
size="large"
|
||||||
|
style="width: 100%"
|
||||||
|
>
|
||||||
|
获取验证码
|
||||||
|
</n-button>
|
||||||
|
</div>
|
||||||
|
</n-gi>
|
||||||
|
</n-grid>
|
||||||
|
|
||||||
|
<n-form-item path="password">
|
||||||
|
<n-input placeholder="密码" v-model:value="model.password" type="password" />
|
||||||
|
</n-form-item>
|
||||||
|
|
||||||
|
<n-form-item path="reenteredPassword">
|
||||||
|
<n-input placeholder="重复密码" v-model:value="model.reenteredPassword" type="password" />
|
||||||
|
</n-form-item>
|
||||||
|
|
||||||
|
<n-grid :cols="2" style="margin-top: 16px">
|
||||||
|
<n-gi>
|
||||||
|
<n-button type="primary" style="width: 72px" @click="handleBtnChangePasswordClick">
|
||||||
|
注册
|
||||||
|
</n-button>
|
||||||
|
</n-gi>
|
||||||
|
<n-gi>
|
||||||
|
<div style="display: flex; justify-content: flex-end">
|
||||||
|
<span style="line-height: 32px">已有帐号?</span>
|
||||||
|
<n-button
|
||||||
|
class="txt-btn"
|
||||||
|
style="line-height: 32px"
|
||||||
|
text
|
||||||
|
@click="$router.push('/login')"
|
||||||
|
>
|
||||||
|
前往登录
|
||||||
|
</n-button>
|
||||||
|
</div>
|
||||||
|
</n-gi>
|
||||||
|
</n-grid>
|
||||||
|
</n-form>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { ref } from "vue";
|
||||||
|
import type { FormInst } from "naive-ui";
|
||||||
|
import type { RegisterCommand } from "@/type/commands/RegisterCommand";
|
||||||
|
|
||||||
|
const formRef = ref<FormInst | null>(null);
|
||||||
|
const model = ref<RegisterCommand>({
|
||||||
|
principal: "",
|
||||||
|
username: "",
|
||||||
|
code: "",
|
||||||
|
password: "",
|
||||||
|
reenteredPassword: "",
|
||||||
|
});
|
||||||
|
|
||||||
|
function handleBtnChangePasswordClick(e: MouseEvent) {
|
||||||
|
e.preventDefault();
|
||||||
|
console.log(formRef.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleBtnGetOTPClick() {
|
||||||
|
console.log("handleBtnGetOTPClick");
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.form-container {
|
||||||
|
width: 320px;
|
||||||
|
background-color: #f3f3f3;
|
||||||
|
padding: 32px 40px;
|
||||||
|
border-radius: 6px;
|
||||||
|
border: solid 1px #e4e4e4;
|
||||||
|
box-shadow: 0 4px 24px 0 rgba(0, 0, 0, 0.2);
|
||||||
|
border-top: solid 4px #6777ef;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
font-size: 30px;
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.n-form-item {
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.txt-btn {
|
||||||
|
line-height: 40px;
|
||||||
|
font-size: 15px;
|
||||||
|
color: #6777ef;
|
||||||
|
}
|
||||||
|
|
||||||
|
.txt-btn:hover {
|
||||||
|
color: rgba(103, 119, 239, 0.8);
|
||||||
|
}
|
||||||
|
</style>
|
Loading…
Reference in New Issue