feat: 完成用户登录界面,api还需完善

This commit is contained in:
539943419 committed 2025-01-14 02:10:39 +08:00
1 parent 4c69f57aaa
commit d7dcc473a9
18 files changed
+681 -129

No files matched your search

+14 -76
View File
@@ -1,90 +1,28 @@
<template>
<div>
index
<div>
<el-button @click="uploadTest">
uploadPostTest
</el-button>
<el-button @click="editTest">
editPostTest
</el-button>
<el-button @click="testLogin">
testLogin
</el-button>
<el-button @click="testRegister">
testRegister
</el-button>
<el-button @click="testRefreshToken">
testRefreshToken
</el-button>
</div>
<el-button @click="handleLogout">
logout
</el-button>
<nuxt-link to="user/test"> test</nuxt-link>
</div>
</template>
<script setup lang="ts">
import useUserStore from '~/hooks/pinia/useUserStore';
import { uploadPost, updatePost } from '~/hooks/useFetch';
const router = useRouter()
const userStore = useUserStore()
const uploadTest = () => {
uploadPost({
title: `测试上传`,
summary: `测试摘要测试摘要测试摘要测试摘要测试摘要测试摘要测试摘要测试摘要测试摘要测试摘要测试摘要`,
type:'markdown',
tags: ['test', 'test1'],
url: '',
date: parseInt(new Date().getTime().toFixed()),
content: '测试上传测试上传测试上传测试上传测试上传测试上传测试上传测试上传测试上传测试上传测试上传测试上传测试上传测试上传测试上传'
})
}
const editTest = () => {
updatePost({
id: 1,
title: `测试上传`,
summary: `测试摘要测试摘要测试摘要测试摘要测试摘要测试摘要测试摘要测试摘要测试摘要测试摘要测试摘要`,
type:'markdown',
tags: ['test', 'test1'],
url: '',
date: parseInt(new Date().getTime().toFixed()),
content: '测试上传测试上传测试上传测试上传测试上传测试上传测试上传测试上传测试上传测试上传测试上传测试上传测试上传测试上传测试上传'
})
}
const testLogin = async () => {
const response = await $fetch('/api/user/login', {
method: 'POST',
body: {
username: 'admin',
password: 'admin'
}
})
const token = response.token
userStore.setToken(token)
}
const testRegister = () => {
$fetch('/api/user/register', {
method: 'POST',
body: {
username: 'admin',
password: 'admin'
}
})
}
const testRefreshToken = async () => {
const response = await $fetch('/api/user/refreshToken', {
method: 'POST',
body: {
token: userStore.token
}
})
const token = response.token
userStore.setToken(token)
const handleLogout = () => {
userStore.logout()
router.push('user/login')
}
onBeforeMount(() => {
if (userStore.isLogin === false) {
return router.push('user/login')
}
})
</script>
<style lang="scss" scoped></style>
<style scoped></style>
+213 -2
View File
@@ -1,13 +1,224 @@
<template>
<div>
login
<div class="login-warpper">
<div class="login-card">
<div class="login-logo">
<cat></cat>
</div>
<!-- <div>杪Blog后台</div> -->
<div class="login-form">
<el-input class="login-form-input" v-model="username" placeholder="用户名" />
<el-input class="login-form-input" v-model="password" placeholder="密码" type="password" show-password />
<div :class="['login-form-message', `login-form-message-${message.type}`]">
<span>{{ message.message }}</span>
<nuxt-link to="/user/register">注册账户</nuxt-link>
</div>
<div class="login-form-button-warpper">
<el-button class="login-form-button" @click="handleLogin">
登 录
</el-button>
</div>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import useUserStore from '~/hooks/pinia/useUserStore';
import cat from '~/components/icons/cat.vue';
import useMiaoFetch from '~/hooks/useMiaoFetch';
const { user: { login } } = useMiaoFetch()
const router = useRouter()
const userStore = useUserStore()
const username = ref('')
const password = ref('')
let isLogining = false
const message = ref({
type: 'warning',
message: ''
})
watch(() => username.value + password.value, () => {
message.value = {
type: 'default',
message: '',
}
})
const handleLogin = async () => {
if (isLogining) return
if (username.value === '' || password.value === '') {
message.value = {
type: 'warning',
message: '用户名或密码不能为空'
}
return
}
isLogining = true
message.value = {
type: 'default',
message: '登录中...'
}
try {
const res = await login({
username: username.value,
password: password.value
})
isLogining = false
message.value = {
type: 'default',
message: '登录成功'
}
userStore.setLoginStatus(true)
userStore.setToken(res.token)
userStore.setTokenExpireTime(res.expiresIn)
router.push('/user')
} catch (e) {
isLogining = false
// @ts-ignore
const code = e.statusCode ?? undefined
console.log(code, code === 401)
if (code === 401) {
message.value = {
type: 'warning',
message: '用户名或密码错误'
}
} else {
message.value = {
type: 'warning',
message: '登录失败'
}
}
}
}
onBeforeMount(() => {
if (userStore.isLogin === true) {
return router.push('/user')
}
})
</script>
<style lang="scss" scoped>
.login-warpper {
width: 100%;
margin: 0 auto;
min-height: calc(100vh - 60px);
display: flex;
flex-direction: column;
justify-content: center;
.login-card {
position: relative;
width: 300px;
// aspect-ratio: 9/16;
border-radius: 20px;
margin: auto;
box-shadow: rgba(50, 50, 93, 0.25) 0px 30px 60px -12px inset, rgba(0, 0, 0, 0.3) 0px 18px 36px -18px inset;
.login-logo {
width: 100px;
height: 100px;
// aspect-ratio: 1;
display: flex;
justify-content: center;
align-items: center;
margin: 80px auto 40px;
svg {
width: 100%;
aspect-ratio: 1;
}
}
.login-form {
width: 180px;
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: center;
gap: 15px;
margin: 40px auto 80px;
&-message {
margin: -10px 0 0px;
width: 100%;
text-align: left;
font-size: 10px;
user-select: none;
display: flex;
justify-content: space-between;
&-warning {
color: #f56c6c;
}
&-default {
color: #15aa87;
}
& > a {
color: #15aa87;
text-decoration: none;
}
}
&-input {
padding: 0;
width: 100%;
--el-input-focus-border-color: #15aa87;
--el-input-hover-border-color: #15aa875d;
}
&-button-warpper {
.login-form-button {
width: 150px;
--el-button-active-border-color: #15aa87;
--el-button-hover-border-color: #15aa875d;
--el-button-hover-bg-color: #ffffff;
--el-button-hover-text-color: #15aa87;
--el-button-outline-color: #15aa87a0;
}
}
}
}
// &::before {
// content: '';
// display: block;
// width: 20vw;
// aspect-ratio: 1;
// border-radius: 50%;
// background-color: aqua;
// position: absolute;
// top: 0;
// left: 40%;
// }
// &::after {
// content: '';
// display: block;
// width: 20vw;
// aspect-ratio: 1;
// border-radius: 50%;
// background-color: rgb(35, 191, 79);
// position: absolute;
// bottom: 0;
// left: 40%;
// }
}
</style>
<style>
/* .login-form-input .el-input__wrapper {
transition: box-shadow .3s ease;
}
.login-form-input .el-input__wrapper.is-focus {
box-shadow: 0 0 0 1px #15aa87 !important;
} */
</style>
+172
View File
@@ -0,0 +1,172 @@
<template>
<div class="login-warpper">
<div class="login-card">
<div class="login-logo">
<cat></cat>
</div>
<!-- <div>杪Blog后台</div> -->
<div class="login-form">
<el-input class="login-form-input" v-model="username" placeholder="用户名" />
<el-input class="login-form-input" v-model="password" placeholder="密码" type="password" show-password />
<div :class="['login-form-message', `login-form-message-${message.type}`]">
<span>{{ message.message }}</span>
<nuxt-link to="/user/login">登录账户</nuxt-link>
</div>
<div class="login-form-button-warpper">
<el-button class="login-form-button" @click="handleRegister">
注 册
</el-button>
</div>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import useUserStore from '~/hooks/pinia/useUserStore';
import cat from '~/components/icons/cat.vue';
import useMiaoFetch from '~/hooks/useMiaoFetch';
const { user: { register } } = useMiaoFetch()
const router = useRouter()
const userStore = useUserStore()
const username = ref('')
const password = ref('')
let isLogining = false
const message = ref({
type: 'warning',
message: ''
})
watch(() => username.value + password.value, () => {
message.value = {
type: 'default',
message: '',
}
})
const handleRegister = async () => {
if (isLogining) return
if (username.value === '' || password.value === '') {
message.value = {
type: 'warning',
message: '用户名或密码不能为空'
}
return
}
isLogining = true
message.value = {
type: 'default',
message: '注册中...'
}
try {
const res = await register({
username: username.value,
password: password.value
})
message.value = {
type: 'default',
message: '注册成功'
}
userStore.setLoginStatus(true)
userStore.setToken(res.token)
userStore.setTokenExpireTime(res.expiresIn)
router.push('/user')
} catch (e) {
message.value = {
type: 'warning',
message: '注册失败'
}
}
}
</script>
<style lang="scss" scoped>
.login-warpper {
width: 100%;
margin: 0 auto;
min-height: calc(100vh - 60px);
display: flex;
flex-direction: column;
justify-content: center;
.login-card {
position: relative;
width: 300px;
// aspect-ratio: 9/16;
border-radius: 20px;
margin: auto;
box-shadow: rgba(50, 50, 93, 0.25) 0px 30px 60px -12px inset, rgba(0, 0, 0, 0.3) 0px 18px 36px -18px inset;
.login-logo {
width: 100px;
height: 100px;
// aspect-ratio: 1;
display: flex;
justify-content: center;
align-items: center;
margin: 80px auto 40px;
svg {
width: 100%;
aspect-ratio: 1;
}
}
.login-form {
width: 180px;
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: center;
gap: 15px;
margin: 40px auto 80px;
&-message {
margin: -10px 0 0px;
width: 100%;
text-align: left;
font-size: 10px;
user-select: none;
display: flex;
justify-content: space-between;
&-warning {
color: #f56c6c;
}
&-default {
color: #15aa87;
}
&>a {
color: #15aa87;
text-decoration: none;
}
}
&-input {
padding: 0;
width: 100%;
--el-input-focus-border-color: #15aa87;
--el-input-hover-border-color: #15aa875d;
}
&-button-warpper {
.login-form-button {
width: 150px;
--el-button-active-border-color: #15aa87;
--el-button-hover-border-color: #15aa875d;
--el-button-hover-bg-color: #ffffff;
--el-button-hover-text-color: #15aa87;
--el-button-outline-color: #15aa87a0;
}
}
}
}
}
</style>
+99
View File
@@ -0,0 +1,99 @@
<template>
<div>
its the page which is used to test the api
<div>
<el-button @click="uploadTest">
uploadPostTest
</el-button>
<el-button @click="editTest">
editPostTest
</el-button>
<el-button @click="testLogin">
testLogin
</el-button>
<el-button @click="testRegister">
testRegister
</el-button>
<el-button @click="testRefreshToken">
testRefreshToken
</el-button>
<el-button @click="testAuth">
testAuth
</el-button>
</div>
</div>
</template>
<script setup lang="ts">
import useUserStore from '~/hooks/pinia/useUserStore';
import useMiaoFetch, { testAuth } from '~/hooks/useMiaoFetch';
const { post: { uploadPost, updatePost } } = useMiaoFetch()
const userStore = useUserStore()
const uploadTest = () => {
uploadPost({
title: `测试上传`,
summary: `测试摘要测试摘要测试摘要测试摘要测试摘要测试摘要测试摘要测试摘要测试摘要测试摘要测试摘要`,
type: 'markdown',
tags: ['test', 'test1'],
url: '',
date: parseInt(new Date().getTime().toFixed()),
content: '测试上传测试上传测试上传测试上传测试上传测试上传测试上传测试上传测试上传测试上传测试上传测试上传测试上传测试上传测试上传'
})
}
const editTest = () => {
updatePost({
id: 1,
title: `测试上传`,
summary: `测试摘要测试摘要测试摘要测试摘要测试摘要测试摘要测试摘要测试摘要测试摘要测试摘要测试摘要`,
type: 'markdown',
tags: ['test', 'test1'],
url: '',
date: parseInt(new Date().getTime().toFixed()),
content: '测试上传测试上传测试上传测试上传测试上传测试上传测试上传测试上传测试上传测试上传测试上传测试上传测试上传测试上传测试上传'
})
}
const testLogin = async () => {
const response = await $fetch('/api/user/login', {
method: 'POST',
body: {
username: 'admin',
password: 'admin'
}
})
const token = response.token
userStore.setToken(token)
}
const testRegister = () => {
$fetch('/api/user/register', {
method: 'POST',
body: {
username: 'admin',
password: 'admin'
}
})
}
const testRefreshToken = async () => {
const response = await $fetch('/api/user/refreshToken', {
method: 'POST',
body: {
token: userStore.token
}
})
const token = response.token
userStore.setToken(token)
}
onMounted(() => {
// testAuth()
})
</script>
<style lang="scss" scoped></style>