feat: 完成用户登录界面,api还需完善
This commit is contained in:
1 parent
4c69f57aaa
commit
d7dcc473a9
18 files changed
+681
-129
No files matched your search
+14
-76
@@ -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
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
Reference in new issue
Block a user