Tlias案例-登录 退出 打包部署
登录
步骤:
1:为“登录”按钮绑定事件,点击登录按钮,发送异步请求到服务器端,执行登录操作。
2:为“取消”按钮绑定事件,点击取消按钮,清空登录表单数据。
基本功能
<script setup>import { ref } from 'vue'import { loginApi } from '@/api/login'import { ElMessage } from 'element-plus'import { useRouter } from 'vue-router'let loginForm = ref({username:'', password:''})const router = useRouter();//登录const login = async () => {let result = await loginApi(loginForm.value); if(result.code){ElMessage.success('登录成功');// 页面跳转 router.push('/index');}else{ // 失败ElMessage.error(result.msg);}}//重置const reset = () => {loginForm.value = {username:'', password:''}}</script><template><div id="container"><div class="login-form"><el-form label-width="80px"><p class="title">Tlias智能学习辅助系统</p><el-form-item label="用户名" prop="username"><el-input v-model="loginForm.username" placeholder="请输入用户名"></el-input></el-form-item><el-form-item label="密码" prop="password"><el-input type="password" v-model="loginForm.password" placeholder="请输入密码"></el-input></el-form-item><el-form-item><el-button class="button" type="primary" @click="login">登 录</el-button><el-button class="button" type="info" @click="reset">重 置</el-button></el-form-item></el-form></div></div>
</template><style scoped>
#container {padding: 10%;height: 410px;background-image: url('../../assets/bg1.jpg');background-repeat: no-repeat;background-size: cover;
}.login-form {max-width: 400px;padding: 30px;margin: 0 auto;border: 1px solid #e0e0e0;border-radius: 10px;box-shadow: 0 0 10px rgba(0, 0, 0, 0.5);background-color: white;
}.title {font-size: 30px;font-family: '楷体';text-align: center;margin-bottom: 30px;font-weight: bold;
}.button {margin-top: 30px;width: 120px;
}
</style>
import request from "@/utils/request";//登录
export const loginApi = (data) => request.post('/login', data);
问题:目前执行登录操作,登录成功之后,并没有将令牌信息存储起来,在后续的每次操作中,也就拿不到登录时的令牌信息了。
方案:需要在登录成功后,将令牌信息存储起来。在后续的请求中,再将令牌取出来,携带到服务器。
这里使用 localStorage 来进行存储,下面介绍一下这个东西。
localStorage 是浏览器提供的本地存储机制(5 MB)。
存储形式为 key - value 形式,键和值都是字符串类型。
API 方法:
//登录const login = async () => {let result = await loginApi(loginForm.value); if(result.code){ElMessage.success('登录成功');//存储当前登录的用户信息localStorage.setItem('user',JSON.stringify(result.data));// 页面跳转router.push('/index');}else{ // 失败ElMessage.error(result.msg);}}
携带令牌访问服务器端
在后续的每一次 Ajax 请求中都获取 localStorage 中的令牌,在请求头中将令牌携带到服务器端。
如果我们要用 localStroage 的话,需要在后续的每一次 Ajax 请求中都要获取 localStorage 中的令牌,然后在请求头中将令牌携带到服务端。但是这个过程过于繁琐了 ,我们考虑 axios 拦截器
其中包含了 request 拦截器,和 response 拦截器,后者我们在一开始就实现了,现在要实现前者
import axios from 'axios'//创建axios实例对象
const request = axios.create({baseURL: '/api',timeout: 600000
})//axios的请求 request 拦截器 - 获取 localStorage 中保存的 token,在请求头中增加 token 请求头
request.interceptors.request.use((config) => { //成功回调const loginUser = JSON.parse(localStorage.getItem('user'));if(loginUser && loginUser.token){config.headers.token = loginUser.token;}return config},(error) => { //失败回调return Promise.reject(error)}
)//axios的响应 response 拦截器
request.interceptors.response.use((response) => { //成功回调return response.data},(error) => { //失败回调return Promise.reject(error)}
)export default request
这里有一个例外,那就是文件上传这个接口,我们文件上传时,并没有基于 axios 实例(request)来发送请求,我们用的是 “饿了么” 里面的组件发送的请求,我们直接参考 “饿了么”官方文档。这里添加一个 header 就可以
<!-- 第五行 --><el-row :gutter="20"><el-col :span="24"><el-form-item label="头像"><el-uploadclass="avatar-uploader"action="/api/upload":headers="{'token': token}":show-file-list="false":on-success="handleAvatarSuccess":before-upload="beforeAvatarUpload"><img v-if="employee.image" :src="employee.image" class="avatar" /><el-icon v-else class="avatar-uploader-icon"><Plus /></el-icon></el-upload></el-form-item></el-col>
const token = ref('')//钩子函数
onMounted(() => {search(); //查询员工列表数据queryAllDepts();//查询所有部门列表数据getToken();
})//获取请求头
const getToken = () => {const loginUser = JSON.parse(localStorage.getItem('user'));if(loginUser && loginUser.token){token.value = loginUser.token;}
}
响应401跳转登录界面
这里还有一个 bug 就是当服务器端给前端响应的状态码是 401(未登录 或 未认证) 时,前端不会跳转到登录界面。
那么既然是后端响应的 401 我们自然要在响应拦截器里进行操作
import router from '../router'
import { ElMessage } from 'element-plus'//axios的响应 response 拦截器
request.interceptors.response.use((response) => { //成功回调return response.data},(error) => { //失败回调if(error.response.status === 401){ // 三个等号是全等(比较类型和值)ElMessage.error('登录信息已过期,请重新登录');router.push('/login');}else{ElMessage.error('接口出错,请稍后再试');}return Promise.reject(error)}
)
退出
分两步
1:展示当前登录的员工的姓名。
2:删除登录信息。
先完成第一步
<script setup>
import { ref, onMounted } from 'vue'const empName = ref('');onMounted(() => {empName.value = JSON.parse(localStorage.getItem('user')).name;
})</script>
<a href="javascript:void(0);" @click="logout"><el-icon><SwitchButton /></el-icon> 退出登录[{{ empName }}]</a>
然后是第二步,完成这个 logout 方法
const logout = () => {//弹出确认框ElMessageBox.confirm('您确认退出登录吗?','提示',{ confirmButtonText: '确认',cancelButtonText: '取消',type: 'warning'}).then(async () => { //确认ElMessage.success('退出登录成功');//清除本地存储localStorage.removeItem('user');// 页面跳转router.push('/login');}).catch(() => { //取消ElMessage.info('您已取消退出登录');})
}
打包
打包后会出现这个 dist 目录
部署
部署在 Nginx 服务器。
介绍:Nginx 是一款轻量级的 Web 服务器/反向代理服务器及电子邮件(IMAP/P0P3)服务器。其特点是占有内存少,并发能力强,在各大互联网公司都有非常广泛的使用。
官网:https://nginx.org/
下载完成之后的步骤:
1:部署:将打包好的 dist 目录下的文件,复制到 nginx 安装目录的 html 目录下。(注意不要复制 dist 目录,复制的是 dist 目录里的文件)
2:启动:双击 nginx.exe 文件即可,Nginx 服务器默认占用 80 端口号。
完成了上述两个步骤后,会发现还是连接不到服务器,那是因为在打包时并没有将 vite.config.js 这个配置文件打包进去,所以无法连接到服务器,这时用 nginx 当中的反向代理就可以解决这个问题
用我们需要的 nginx.conf 文件替换掉 原本 conf 目录下的该文件
最后我们要在 nginx 安装目录下执行以下命令,代表重新加载 nginx 的配置文件
如果我们要停止
最后一点注意事项:
Nginx 默认占用的端口号是 80 端口号,如果 80 端口号被占用,可以在 nginx.conf 中修改端口号。