微服务项目->在线oj系统(Java-Spring)----[前端]
前端开发
创建一个VUE项目
这个时候,我们存放文件的地方就会出现一个文件夹
然后我们在vscode上的工作区中打开即可(方便编写代码)
删除并修改vue代码
这里我们需要删除我们不需要的代码和样式
这里是初始的代码格式
修改之后代码结构
Login.vue代码
主要是样式和布局,这个我们后端不做深入
<template><div class="login-page"><div class="orange"> </div><div class="blue"></div><div class="blue small"></div><div class="login-box"><div class="logo-box"><div class="right"><div class="sys-name">⽐特OJ后台管理</div><div class="sys-sub-name">帮助100万学⽣就业</div></div></div><div class="form-box"><div class="form-item"><img src="../assets/images/shouji.png"><el-input v-model="userAccount" placeholder="请输⼊账号" /></div><div class="form-item"><img src="../assets/images/yanzhengma.png"><el-input v-model="password" type="password" show-password placeholder="请输⼊密码" /></div><div class="submit-box" @click="login">登录</div></div></div></div>
</template>
<script setup>
import { ref } from 'vue'
import { loginServeice } from '@/apis/suer'
// 假设 request 封装在 @/utils/request.js 中,根据实际路径调整
import request from '@/utils/request';
import router from '@/router' // 假设路由文件在 src/router/index.js
const userAccount = ref('')
const password = ref('')
import { setToken } from '@/utils/cookie'
async function login() {try {const loginresult = await loginServeice(userAccount.value, password.value)console.log(loginresult)setToken(loginresult.data)router.push('/oj/system')} catch (error) {console.error('登录失败:', error);}
}
</script>
<style lang="scss" scoped>
.login-page {width: 100vw;height: 100vh;position: relative;overflow: hidden;.login-box {overflow: hidden;.logo-box {display: flex;align-items: center;margin-bottom: 30px;img {width: 68px;height: 68px;margin-right: 16px;}.sys-name {height: 33px;font-family: PingFangSC, PingFang SC;font-weight: 600;font-size: 24px;color: #222222;line-height: 33px;margin-bottom: 13px;}.sys-sub-name {height: 22px;font-family: PingFangSC, PingFang SC;font-weight: 400;font-size: 16px;color: #222222;line-height: 22px;}}:deep(.form-box) {.submit-box {margin-top: 90px;width: 456px;height: 48px;background: #32C5FF;border-radius: 8px;cursor: pointer;display: flex;justify-content: center;align-items: center;font-family: PingFangSC, PingFang SC;font-weight: 600;font-size: 16px;color: #FFFFFF;letter-spacing: 1px;}.form-item {display: flex;align-items: center;width: 456px;height: 48px;background: #F8F8F8;border-radius: 8px;margin-bottom: 30px;position: relative;.code-btn-box {position: absolute;right: 0;width: 151px;height: 48px;background: #32C5FF;border-radius: 8px;top: 0;display: flex;align-items: center;justify-content: center;cursor: pointer;span {font-family: PingFangSC, PingFang SC;font-weight: 400;font-size: 16px;color: #FFFFFF;}}.error-tip {position: absolute;width: 140px;text-align: right;padding-right: 12px;height: 20px;font-family: PingFangSC, PingFang SC;font-weight: 400;font-size: 14px;color: #FD4C40;line-height: 20px;right: 0;&.bottom {right: 157px;}}.el-input {width: 380px;font-family: PingFangSC, PingFang SC;font-weight: 400;font-size: 16px;color: #222222;}.el-input__wrapper {border: none;box-shadow: none;background: transparent;width: 230px;padding-left: 0;}img {width: 24px;height: 24px;margin: 0 18px;}}}width:456px;height:404px;background: #FFFFFF;box-shadow: 0px 0px 6px 0px rgba(0, 0, 0, 0.1);border-radius: 10px;opacity: 0.9;position: absolute;top: 50%;left: 50%;transform: translate(-50%, -50%);z-index: 2;padding: 0 72px;padding-top: 50px;}&::after {position: absolute;top: 0;left: 0;height: 100vh;bottom: 0;right: 0;background: rgba(255, 255, 255, .8);z-index: 1;content: '';}.orange {background: #F0714A;width: 498px;height: 498px;border-radius: 50%;background: #F0714A;opacity: 0.67;filter: blur(50px);left: 14.2%;top: 41%;position: absolute;}.blue {width: 334px;height: 334px;background: #32C5FF;opacity: 0.67;filter: blur(50px);left: 14.2%;top: 42%;position: absolute;top: 16.3%;left: 80.7%;&.small {width: 186px;height: 186px;top: 8.2%;left: 58.2%;}}
}
</style>
修改router⽬录下index.js⽂件
主要功能是路由功能
import { createRouter, createWebHistory } from 'vue-router'
const router = createRouter({history: createWebHistory(import.meta.env.BASE_URL),routes: [{path: '/oj/login',name: 'login',component: () => import('../views/Login.vue'),},],
})export default router
Element-plus
先导⼊包:
npm install element-plus --save
按需导⼊
npm install -D unplugin-vue-components unplugin-auto-import
加入配置
修改账户和密码框
- v-model:前端与Vue实例的双向绑定
在一个简单的登录页面,需要获取用户输入的用户名。可以在<input>
标签上使用v-model
,将它绑定到 Vue 实例中的一个数据属性上
- type="password",设置格式为密码框
- show-password,设置可显示密码
Axios
发起 HTTP 请求
作用:
- 向后端 API 获取数据
- 提交数据到后端
安装Axios
npm install axios
创建实例
import axios from "axios"; const service = axios.create({baseURL: 127.0.0.1:19090/systemtimeout: 5000,
});export default service;
127.0.0.1:19090/system是所以使用它的前缀,注意要加上http,否则会自动加上我们vue的前缀127.0.0.1:5173
这是是为进行跨域访问所以进行优化
import axios from "axios"; const service = axios.create({baseURL: "/dev-api",timeout: 5000,
});
因为浏览器不同域不可访问, 添加代理
这里的意思将请求转发到127.0.0.1:19090/system/dev-api/sysUser/login,然后将/dev-api/替换为空
定义请求⽅法:
• 创建apis⽬录
• 定义登录⽅法
import service from "@/utils/request";
import request from '@/utils/request';
export function loginServeice(userAccount, password) {return request({url: "/sysUser/login",method: "post",data: { userAccount, password },});
}
发送token
安装js-cookie
npm install js-cookie
创建cookie.js
import Cookies from "js-cookie";
const TokenKey = "Admin-Oj-b-Token";
export function getToken() {return Cookies.get(TokenKey);
}
export function setToken(token) {return Cookies.set(TokenKey, token);
}export function removeToken() {return Cookies.remove(TokenKey);
}
响应拦截
我们之前的代码太过于冗余,需要res.data.data,这样不利于我们操作,所以来一个响应拦截
service.interceptors.response.use((res) => {// 未设置状态码则默认成功状态const code = res.data.code;const msg = res.data.msg;if (code !== 1000) {ElMessage.error(msg);return Promise.reject(new Error(msg));} else {return Promise.resolve(res.data);}},(error) => {return Promise.reject(error);}
);
这里的error是指请求失效,而不是密码错误等错误
我们这里的return Promise.reject(new Error(msg));会抛出异常,就需要我们下面代码中捕获异常,然后对异常情况(密码错误或者账号不存在)进行处理,
ElMessage.error(msg); 是使用Elment*进行的错误提示
修改Login.vue代码
import { ref } from 'vue'
import { loginServeice } from '@/apis/suer'
// 假设 request 封装在 @/utils/request.js 中,根据实际路径调整
import request from '@/utils/request';
import router from '@/router' // 假设路由文件在 src/router/index.js
const userAccount = ref('')
const password = ref('')
import { setToken } from '@/utils/cookie'
async function login() {try {const loginresult = await loginServeice(userAccount.value, password.value)console.log(loginresult)setToken(loginresult.data)router.push('/oj/system')} catch (error) {console.error('登录失败:', error);}
}
router.push('/oj/system')可以跳转带另一个页面
setToken来设置我们的token