首页完成 新增登录

main
JayChou 8 months ago
parent 36f35fa1b4
commit d9c0811199
  1. 2
      .env.development
  2. 48
      src/Layout/tabbar/index.vue
  3. 25
      src/api/user.ts
  4. BIN
      src/assets/images/bg.png
  5. BIN
      src/assets/images/code.png
  6. 10
      src/main.ts
  7. 23
      src/permissions.ts
  8. 3
      src/router/index.ts
  9. 11
      src/router/module/constRouter/defineRouter.ts
  10. 45
      src/store/module/user.ts
  11. 4
      src/styles/index.scss
  12. 7
      src/utils/requset.ts
  13. 9
      src/utils/token.ts
  14. 106
      src/views/home/index.vue
  15. 146
      src/views/login/index.vue

@ -1,5 +1,5 @@
# 变量必须以 VITE_ 为前缀才能暴露给外部读取
NODE_ENV = 'development'
VITE_APP_TITLE = '教学一体化平台'
VITE_APP_BASE_API = 'http://39.106.16.162:8080'
VITE_APP_BASE_API = http://localhost:18085/jeecg-boot
# VITE_APP_BASE_API = 'http://127.0.0.1:8080'

@ -14,9 +14,27 @@
</ul>
</div>
</div>
<div class="right">
<div class="right" v-if="!useUserStore.token">
<div class="registered gradient">注册</div>
<div class="login">登录</div>
<div class="login" @click="$router.push('/login')">登录</div>
</div>
<div class="right" v-else>
<div class="avater">
<img src="../../assets/images/default.png" alt="" />
</div>
<el-dropdown>
<span class="el-dropdown-link">
{{ useUserStore.userInfo.username }}
<el-icon class="el-icon--right">
<arrow-down />
</el-icon>
</span>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item @click="layout">退出登录</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</div>
</div>
</div>
@ -24,12 +42,11 @@
<script lang="ts" setup>
import { constRouter } from '@/router/module/constRouter'
// import { useRouter, useRoute } from 'vue-router'
import { useRouter } from 'vue-router'
import { onMounted, ref } from 'vue'
// const $router = useRouter()
// const $route = useRoute()
console.log(constRouter, '111')
import userStore from '@/store/module/user'
const useUserStore = userStore()
const $router = useRouter()
const flog = ref(false)
onMounted(() => {
window.addEventListener('scroll', () => {
@ -40,6 +57,11 @@ onMounted(() => {
}
})
})
const layout = async () => {
useUserStore.layOut()
}
</script>
<style lang="scss" scoped>
@ -136,9 +158,17 @@ onMounted(() => {
color: #fff;
}
.login {
color: #1D2129;
color: #1d2129;
margin-left: 20px;
border: 1px solid #E5E6EB;
border: 1px solid #e5e6eb;
}
.avater {
width: 35px;
height: 35px;
img {
width: 100%;
}
margin-right: 20px;
}
}
.menu {

@ -0,0 +1,25 @@
import request from '@/utils/requset'
export const getCode = (time:any) => {
return request({
url:'/sys/randomImage/' + time,
})
}
export const loginApi = (data:any) => {
return request({
url:'/sys/login',
method:"POST",
data
})
}
export const getUserInfoApi = () => {
return request({
url:'/sys/user/getUserInfo'
})
}
export const logOut = () => {
return request({
url:'/sys/logout'
})
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 484 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

@ -12,21 +12,25 @@ import zhCn from 'element-plus/dist/locale/zh-cn.mjs'
import gloablComponent from './components/index'
// 引入全局样式
import '@/styles/index.scss'
// 引入路由
import router from '@/router/index'
// 引入仓库
import pinia from '@/store/index'
// 引入路由
import router from './permissions'
import '@/utils/rem.js'
// 创建vue实例
const app = createApp(App)
app.use(pinia)
// 注册element plus组件库
app.use(ElementPlus, {
locale: zhCn,
})
// 注册全局组件
app.use(gloablComponent)
app.use(router)
app.use(pinia)
// app.use(G6)
// 挂载点
app.mount('#app')

@ -0,0 +1,23 @@
import router from '@/router/index'
import userStore from './store/module/user'
router.beforeEach(async (to, form, next) => {
const useuserStore = userStore()
if (useuserStore.token) {
if (to.path === '/login') {
next({ path: '/' })
} else {
if (!Object.keys(useuserStore.userInfo).length) {
useuserStore.getUserInfo()
next()
}else{
next()
}
}
}else{
next()
}
})
export default router

@ -1,8 +1,9 @@
import { createRouter, createWebHashHistory,createWebHistory } from 'vue-router'
import { constRouter } from './module/constRouter'
import defineRouter from './module/constRouter/defineRouter'
const router = createRouter({
history: createWebHashHistory(),
routes: [constRouter],
routes: [...defineRouter,constRouter],
scrollBehavior() {
return {
left: 0,

@ -0,0 +1,11 @@
const defineRouter = [
{
path:'/login',
component: () => import('@/views/login/index.vue'),
meta:{
title:'登录'
}
}
]
export default defineRouter

@ -0,0 +1,45 @@
import { defineStore } from 'pinia'
import { loginApi,getUserInfoApi ,logOut} from '@/api/user'
import { ElNotification } from 'element-plus'
import { setToken, getToken ,removeToken} from '@/utils/token'
const userStore = defineStore('defineStore', {
state: (): any => ({
token: getToken() || '',
userInfo: {},
}),
actions: {
async login(parmas: any) {
const res: any = await loginApi(parmas)
if (res.code === 412) {
return 0
} else if (res.code === 500) {
return 1
} else {
console.log(res.result.userInfo)
this.token = res.result.token
setToken(this.token)
this.userInfo = res.result.userInfo
ElNotification({
title: '登录成功',
message: '欢迎回来' + this.userInfo.username,
type: 'success',
})
}
},
async getUserInfo(){
const res:any = await getUserInfoApi()
this.userInfo = res.result.userInfo
console.log(res);
},
async layOut(){
await logOut()
removeToken()
this.token = ''
this.userInfo = {}
}
},
})
export default userStore

@ -1,6 +1,8 @@
// 引入清除浏览器默认样式文件
@import './reset.scss';
:root {
--el-color-primary: #0BD7C6;
}
.container-1420{
width: 1420px;
margin: 0 auto;

@ -1,5 +1,8 @@
// 引入第三方请求库axios
import axios from 'axios'
import pinia from '@/store'
import userStore from '@/store/module/user'
// 创建axios实例
const server = axios.create({
baseURL: import.meta.env.VITE_APP_BASE_API,
@ -7,6 +10,10 @@ const server = axios.create({
})
// 创建请求拦截器
server.interceptors.request.use((config) => {
const useuserStore = userStore(pinia)
config.headers.Authorization = useuserStore.token
config.headers['x-access-token'] = useuserStore.token
return config
})

@ -0,0 +1,9 @@
export const setToken = (token: string) => {
localStorage.setItem('token', token)
}
export const removeToken = () => {
localStorage.removeItem('token')
}
export const getToken = () => {
return localStorage.getItem('token')
}

@ -32,7 +32,31 @@
</div>
<div class="newa-panel">
<div class="tab">
<div :class="active === i ? 'item active gradient' : 'item'" v-for="i in 5" :key="i" @click="active = i">全部</div>
<div
:class="active === i ? 'item active gradient' : 'item'"
v-for="i in 5"
:key="i"
@click="active = i"
>
全部
</div>
</div>
<div class="newa-main">
<div class="left"></div>
<div class="right">
<div class="title">新闻标题</div>
<div class="description">
我是新闻描述,我是新闻描述,我是新闻描述
</div>
<div class="newa-main-list">
<ul>
<li v-for="i in 6" :key="i ">
<div class="time">2024-09-12</div>
<div class="info">我是一段新闻描述,我是一段新闻描述,我是一段新闻描述</div>
</li>
</ul>
</div>
</div>
</div>
</div>
</div>
@ -159,7 +183,11 @@ const active = ref(1)
backdrop-filter: blur(10px);
box-shadow: 2px 6px 14px rgba(0, 0, 0, 0.25);
margin-top: 25px;
padding: 46px 180px 70px 180px;
// padding: 46px 180px 70px 180px;
padding-top: 46px;
display: flex;
flex-direction: column;
align-items: center;
.tab {
display: flex;
justify-content: space-between;
@ -175,14 +203,88 @@ const active = ref(1)
box-shadow: 7px 7px 22px -10px rgba(0, 0, 0, 0.22);
cursor: pointer;
transition: all 0.2s;
margin-right: 48px;
}
.item:hover {
transform: scale(1.1);
}
.item:last-child {
margin: 0;
}
.active {
color: #fff;
}
}
.newa-main {
width: 1200px;
height: 465px;
padding: 58px 54px 19px 25px;
display: flex;
align-items: center;
justify-content: space-between;
.left {
width: 546px;
height: 388px;
background-color: #d9d9d9;
border-radius: 15px;
}
.right {
flex: 1;
height: 388px;
margin-left: 89px;
padding: 15px 0;
.title {
font-size: 24px;
font-weight: 600;
color: #1e2033;
}
.description {
font-size: 14px;
margin-top: 10px;
color: #1e2033;
}
.newa-main-list{
width: 100%;
height: 270px;
// background-color: pink;
margin-top: 38px;
ul{
width: 100%;
height: 100%;
display: flex;
flex-wrap: wrap;
justify-content: space-between;
align-items: center;
li{
width: 227px;
height: 65px;
.time{
position: relative;
font-size: 14px;
color: #1e2033;
padding-left: 13px;
}
.time::before{
content: ' ';
display: block;
position: absolute;
top: 0;
left: 0;
width: 6px;
height: 13px;
background-color: #319245;
}
.info{
margin-top: 12px;
font-size: 12px;
color: #1e2033;
line-height: 18px;
}
}
}
}
}
}
}
}
</style>

@ -0,0 +1,146 @@
<template>
<div class="login-content">
<div class="login-form">
<div class="login-title">登录</div>
<div class="form">
<el-form :model="form" label-width="80">
<el-form-item label="账号">
<el-input v-model="form.account" style="height: .2344rem" />
</el-form-item>
<el-form-item label="密码">
<el-input v-model="form.password" style="height: .2344rem" />
</el-form-item>
<el-form-item label="验证码">
<div class="captcha">
<el-input
v-model="form.captcha"
style="height: .2344rem"
maxlength="4"
/>
<div class="code" @click="getcodeinfo">
<img :src="codeUrl" alt="" srcset="" />
</div>
</div>
</el-form-item>
</el-form>
<div class="submit gradient" @click.enter="submit">登录</div>
</div>
</div>
</div>
</template>
<script lang="ts" setup>
import { onMounted, reactive, ref, toRefs, watch } from 'vue'
import { getCode } from '@/api/user'
import userStore from '@/store/module/user'
import { ElMessage } from 'element-plus'
import { useRouter } from 'vue-router'
const useUserStore = userStore()
const form = ref({
account: '',
password: '',
captcha: '',
})
const codeUrl = ref('')
const getcodeinfo = async () => {
const res: any = await getCode(1629428467008)
codeUrl.value = res.result
console.log(codeUrl.value)
}
getcodeinfo()
const Router = useRouter()
const submit = async () => {
console.log(111, useUserStore)
let data = {
captcha: form.value.captcha,
checkKey: 1629428467008,
password: form.value.password,
username: form.value.account,
}
const res = await useUserStore.login(data)
console.log(res)
if (res === 0) {
ElMessage('验证码错误')
getcodeinfo()
} else if (res === 1) {
ElMessage('账号或密码错误')
getcodeinfo()
}else{
Router.push('/')
}
}
</script>
<style lang="scss" scoped>
.login-content {
width: 100%;
height: 100vh;
background: url('../../assets/images/bg.png') no-repeat;
background-size: cover;
display: flex;
align-items: center;
justify-content: center;
.login-form {
width: 640px;
height: 820px;
border-radius: 15px;
background-color: #ffffff1a !important;
padding: 70px 60px;
backdrop-filter: blur(10px);
box-shadow: 0 4px 8px 1px rgba(0, 0, 0, 0.2);
.login-title {
font-size: 32px;
font-weight: 700;
}
.form {
margin-top: 35px;
padding: 0 40px;
.captcha {
width: 100%;
height: 100%;
position: relative;
.code {
width: 100%;
height: 100%;
position: absolute;
top: 0;
right: 0;
width: 105px;
height: 100%;
// background-color: pink;
display: flex;
align-items: center;
img{
width: 100%;
height: 100%;
}
}
}
.submit {
width: 399px;
height: 50px;
text-align: center;
line-height: 50px;
font-size: 20px;
font-weight: 600;
cursor: pointer;
color: #fff;
border-radius: 10px;
margin-top: 35px;
}
}
}
}
:deep(.el-form-item) {
display: flex;
flex-direction: column;
}
:deep(.el-input__wrapper) {
box-shadow: none;
}
:deep(.el-form-item__label) {
justify-content: start;
}
</style>
Loading…
Cancel
Save