Skip to content

Commit

Permalink
feat: ✨️登录注册开发
Browse files Browse the repository at this point in the history
  • Loading branch information
ZRMYDYCG committed Mar 5, 2025
1 parent 67d386b commit d7872e3
Show file tree
Hide file tree
Showing 7 changed files with 329 additions and 53 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
}
},
"dependencies": {
"@element-plus/icons-vue": "^2.3.1",
"@tailwindcss/vite": "^4.0.9",
"@vueuse/core": "^12.7.0",
"axios": "^1.8.1",
Expand Down
29 changes: 3 additions & 26 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion src/router/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import useUserStore from '@/store/modules/user'
import { useUserStore } from '@/store/modules/user'
import { createRouter, createWebHistory } from 'vue-router'
import routes from './routes'

Expand Down
59 changes: 42 additions & 17 deletions src/store/modules/user.ts
Original file line number Diff line number Diff line change
@@ -1,35 +1,60 @@
import $api from '@/api'
import { HTTP_CODE, HTTP_HOST } from '@/settings/config/http'
import { defineStore } from 'pinia'
import { ref } from 'vue'

const useUserStore = defineStore('userStore', () => {
const token = ref('has-token')
const userInfo = ref<{
nickname: string
avatar: string
account: string
}>()
interface UserInfo {
avatar: string
[key: string]: any
}

const updateUserInfo = (user) => {
export const useUserStore = defineStore('userStore', () => {
const userInfo = ref<UserInfo | null>(null)
const updateUserInfo = (user: UserInfo) => {
userInfo.value = user

// 数据持久化
localStorage.setItem('user', JSON.stringify(user))
}

const updateToken = (token) => {
token.value = token
localStorage.setItem('token', JSON.stringify(token))
const token = ref<string>('')
const updateToken = (value: string) => {
token.value = value

// 数据持久化
localStorage.setItem('token', value)
}

const loginAction = () => {
return new Promise(() => {})
// 登录action
const accountLogin = (data: { account: string; password: string }) => {
return new Promise<void>((resolve, reject) => {
;($api as any).login
.accountLogin(data)
.then((res) => {
const { code, data, message } = res.data
if (code === HTTP_CODE.HTTP_SUCCESS_CODE) {
const { avatar, ...extra } = data.info
updateUserInfo({
avatar: `${HTTP_HOST}${avatar}`,
...extra,
})
updateToken(data.token)
resolve()
} else {
reject(message)
}
})
.catch(() => {
reject('登录失败')
})
})
}

return {
token,
userInfo,
updateUserInfo,
token,
updateToken,
loginAction,
accountLogin,
}
})

export default useUserStore
2 changes: 1 addition & 1 deletion src/utils/http/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { HTTP_TIMEOUT } from '@/settings/config/http'
import useUserStore from '@/store/modules/user'
import { useUserStore } from '@/store/modules/user'
import axios from 'axios'

// 创建http axios实例
Expand Down
144 changes: 140 additions & 4 deletions src/view/login/index.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,143 @@
<script lang="ts"></script>

<template>
<div></div>
<div class="login">
<el-form
ref="loginFormRef"
:model="formMdl"
:rules="rules"
label-position="left"
label-width="0px"
class="login-container"
>
<div class="logo">
<img src="/logo.svg" alt="logo" />
<h3>LightChat</h3>
</div>

<el-form-item prop="account">
<el-input
v-model.trim="formMdl.account"
type="text"
size="large"
:prefix-icon="IconUser"
auto-complete="off"
placeholder="账号"
@keyup.enter="handleLogin"
></el-input>
</el-form-item>
<el-form-item prop="password">
<el-input
v-model.trim="formMdl.password"
type="password"
size="large"
:prefix-icon="IconUnlock"
auto-complete="off"
placeholder="密码"
@keyup.enter="handleLogin"
>
</el-input>
</el-form-item>
<el-form-item>
<el-button class="login-btn" type="primary" size="large" :loading="loading" @click.prevent="handleLogin">
立即登录
</el-button>
</el-form-item>
</el-form>
</div>
</template>

<style scoped></style>
<script setup lang="ts">
import useUserStore from '@/store/modules/user'
import { Unlock as IconUnlock, User as IconUser } from '@element-plus/icons-vue'
import { ElMessage, type FormInstance } from 'element-plus'
import { ref } from 'vue'
import { useRouter } from 'vue-router'
const userStore = useUserStore()
const router = useRouter()
const rules = {
account: [{ required: true, message: '请输入账号', trigger: 'blur' }],
password: [{ required: true, message: '请输入密码', trigger: 'blur' }],
}
// 登录表单引用
const loginFormRef = ref<FormInstance | null>(null)
const loading = ref(false)
const formMdl = ref({
account: '',
password: '',
})
const handleLogin = async () => {
if (loading.value) return
const validateStatus = await new Promise<boolean>((resolve) => {
if (!loginFormRef.value) return resolve(false)
loginFormRef.value.validate((valid) => {
resolve(valid)
})
})
if (!validateStatus) return
loading.value = true
userStore
.accountLogin(formMdl.value)
.then(() => {
ElMessage.success({
message: '登录成功',
duration: 3000,
})
// 跳转默认页
router.push({ path: '/chat/main' })
})
.catch((message: string) => {
ElMessage.error({
message,
duration: 3000,
})
})
.finally(() => {
setTimeout(() => {
loading.value = false
}, 150)
})
}
</script>

<style>
.login {
display: flex;
justify-content: center;
box-sizing: border-box;
padding: 150px 150px 30px;
}
.login-container {
width: 330px;
background-color: transparent;
}
.login-container .logo {
text-align: center;
margin: 0 auto 40px auto;
}
.login-container .logo img {
display: inline-block;
height: 60px;
margin-right: 6px;
vertical-align: middle;
}
.login-container .logo h3 {
color: rgba(0, 0, 0, 0.85);
font-size: 20px;
}
.login-container .login-btn {
width: 100%;
margin-top: 30px;
}
</style>
Loading

0 comments on commit d7872e3

Please sign in to comment.