#### axios引入和二次封装
1.安装axios包
cnpm install axios
在src中创建api和utils文件夹,utils中创建request.js文件
2.在request中定义axios二次封装
import axios from 'axios'
import { ElMessage } from 'element-plus'
const http = axios.create({
baseURL: 'https:/v3pz.itndedu.com/v3pz',
timeout: 10000
})
//添加拦截器
// 添加请求拦截器
http.interceptors.request.use(function (config) {
// 在发送请求之前做些什么
const token = localStorage.getItem('pz_token')
//不需要添加token的api
const whiteUrl = ['/get/code','/user/authentication','/login']
if (token && !whiteUrl.includes(config)) {
config.headers['x-token'] = token
}
return config;
}, function (error) {
// 对请求错误做些什么
return Promise.reject(error);
});
// 添加响应拦截器
http.interceptors.response.use(function (response) {
// 2xx 范围内的状态码都会触发该函数。
// 对响应数据做点什么
//对接口异常的数据,给用户提示
if (response.data.code === -1) {
ElMessage.warning(response.data.message)
}
return response;
}, function (error) {
// 超出 2xx 范围的状态码都会触发该函数。
// 对响应错误做点什么
return Promise.reject(error);
});
export default http
3.在api中创建一个index.js
import request from '../utils/request'
//发送验证码
export const getCode = (data) => {
return request.post('/get/code')
}
#### 注册接口和登录接口联调
1.在api中设置出口
2.在index.vue中设置登录和注册页面的联调
<template>
<el-row class="login-container" >
<el-card style="max-width: 480px">
<template #header>
<div class="card-header">
<img :src="imgUrl" alt="">
</div>
</template>
<div class="jump-link">
<el-link type="primary" @click="handleChange">{{ formType ? '返回登录':'注册账号'}}</el-link>
</div>
<el-form
ref="loginFormRef"
:model="loginForm"
style="max-width: 600px"
class="demo-ruleForm"
:rules="rules">
<el-form-item prop="userName">
<el-input v-model="loginForm.userName" placeholder="手机号" :prefix-icon="UserFilled"></el-input>
</el-form-item>
<el-form-item prop="passWord">
<el-input v-model="loginForm.passWord" type="password" placeholder="密码" :prefix-icon="Lock "></el-input>
</el-form-item>
<el-form-item v-if="formType" prop="validCode">
<el-input v-model="loginForm.validCode" placeholder="验证码" :prefix-icon="Lock ">
<template #append>
<span @click="countdownChange">{{ countdown.validText }}</span>
</template>
</el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" :style="{width: '100%'}" @click="submitForm(loginFormRef)">
{{ formType ? '注册账号':'登录'}}
</el-button>
</el-form-item>
</el-form>
</el-card>
</el-row>
</template>
<script setup>
import { ref,reactive } from 'vue'
import { getCode,login,userAuthentication } from '../../api'
import { ElMessage } from 'element-plus'
import { UserFilled,Lock } from '@element-plus/icons-vue'
const imgUrl = new URL('../../../public/login-head.png', import.meta.url).href
//表单的初始数据
const loginForm = reactive({
userName: '',
passWord: '',
validCode: ''
})
//切换表单(0登录)(1注册)
const formType = ref(0)
//点击切换登录和注册
const handleChange = () => {
formType.value = formType.value ? 0 : 1
}
//账号校验规则
const validateUser = (rule,value,callback) => {
//不能为空
if (value === '') {
callback(new Error('请输入账号'))
} else {
const phoneReg = /^1(3[0-9]|4[01456879]|5[0-35-9]|6[2567]|7[0-8]|8[0-9]|9[0-35-9])\d{8}$/
phoneReg.test(value) ? callback() : callback(new Error('手机号格式不正确,请输入正确手机号'))
}
}
//密码校验规则
const validatePass = (rule,value,callback) => {
//不能为空
if (value === '') {
callback(new Error('请输入密码'))
} else {
const reg = /^[a-zA-Z0-9_-]{4,16}$/
reg.test(value) ? callback() : callback(new Error('密码格式不对,需要4到16位字符,请确认格式'))
}
}
//表单校验
const rules = reactive({
userName: [{ validator: validateUser,trigger: 'blur'}],
passWord: [{ validator: validatePass,trigger: 'blur'}],
})
//发送短信
const countdown = reactive({
validText: '获取验证码',
time: 60
})
let flag = false
const countdownChange = () => {
//如果已发送就不处理
if(flag) return
//判断手机号是否正确
const phoneReg = /^1(3[0-9]|4[01456879]|5[0-35-9]|6[2567]|7[0-8]|8[0-9]|9[0-35-9])\d{8}$/
if (!loginForm.userName || !phoneReg.test(loginForm.userName) ) {
return ElMessage({
message: '请检查手机号是否正确',
type: 'warning'
})
}
//倒计时
setInterval(() => {
if(countdown.time <= 0){
countdown.time = 60
countdown.validText = `获取验证码`
flag = false
clearInterval(time)
} else {
countdown.time -= 1
countdown.validText = `剩余${countdown.time}s`
}
},1000)
flag = true
getCode({ tel: loginForm.userName }).then(({ data }) => {
if (data.code === 10000) {
ElMessage.success('发送成功')
}
})
}
const loginFormRef = ref()
//表单提交
const submitForm = async (formEl) => {
if (!formEl) return
//手动触发校验
await formEl.validate((valid,fields ) => {
if (valid) {
//注册页面
if (formType.value) {
userAuthentication(loginForm).then(() => {
if (data.code) {
ElMessage.success('注册成功,请登录')
formType.value = 0
}
})
} else {
//登录页面
login(loginForm).then(() => {
if (data.code) {
ElMessage.success('登录成功')
//将token和用户信息缓存到浏览器
localStorage.setItem('pz_token',data.data.token)
localStorage.setItem('pz_userInfo',JSON.stringify(data.data.userInfo))
}
})
}
} else {
console.log('error submit!',fields)
}
})
}
</script>
<style lang="less" scoped>
:deep(.el-card__header) {
padding: 0
}
.login-container {
height: 100%;
align-items: center;
justify-content: center;
.card-header{
background-color: #899fe1;
img {
width: 430px;
}
}
.jump-link {
text-align: right;
margin-bottom: 10px;
}
}
</style>
#### 用户鉴权和路由守卫添加
1.router.push('/')
2.如果token不存在,不进入首页,所以要有一个路由守卫
3.在main.js中做路由守卫的判断
import router from './router'
router.beforeEach((to,from) => {
const token = localStorage.getItem('pz_token')
//非登录页面token不存在
if (!token && to.path !== '/login') {
return '/login'
} else if (token && to.path === '/login') {
return '/'
} else {
return true
}
})
admin中的index.vue
<script setup>
import { authAdmin } from '../../../api'
import { reactive,onMounted } from 'vue'
const paginationData = reactive({
pageNum: 1,
pageSize: 10
})
onMounted(() => {
authAdmin(paginationData).then(({data}) => {
})
})
</script>
#### 菜单管理添加弹窗显示
group的index.vue
<template>
<button @click="dialogFormVisable = true">打开</button>
<el-dialog
v-model="dialogFormVisable"
:before-close="beforeClose"
title="添加权限"
width="500"
>
<el-form
ref="formRef"
label-width="100px"
label-position="left"
:model="form"
>
<el-form-item label="名称" prop="name">
<el-input v-model="form.name" aria-placeholder="请填写权限名称" />
</el-form-item>
<el-form-item label="权限" prop="permissions">
<el-tree
ref="treeRef"
:data="permissionData"
style="max-width: 600px;"
node-key="id"
show-checkbox
:default-checked-keys="defaultKeys"
>
</el-tree>
</el-form-item>
</el-form>
</el-dialog>
</template>
<script setup>
import { ref,reactive,onMounted } from 'vue'
import { userGetMenu } from '../../../api'
onMounted(() => {
//菜单数据
userGetMenu().then(({ data }) => {
permissionData.value = data.data
})
})
//form的数据
const form = reactive({
name: '',
permissions: ''
})
//树形菜单权限数据
const permissionData = ref([])
//弹窗的显示隐藏
const dialogFormVisable = ref(false)
//关闭弹窗的回调
const beforeClose = () => {
dialogFormVisable.value = false
}
//选中权限
const defaultKeys = [4,5]
const treeRef = ref()
</script>
<style lang="less" scoped>
</style>
#### 菜单管理添加接口联调
<template>
<button @click="dialogFormVisable = true">打开</button>
<el-dialog
v-model="dialogFormVisable"
:before-close="beforeClose"
title="添加权限"
width="500"
>
<el-form
ref="formRef"
label-width="100px"
label-position="left"
:model="form"
:rules="rules"
>
<el-form-item prop="id" v-show="false">
<el-input v-model="form.id" />
</el-form-item>
<el-form-item label="名称" prop="name">
<el-input v-model="form.name" aria-placeholder="请填写权限名称" />
</el-form-item>
<el-form-item label="权限" prop="permissions">
<el-tree
ref="treeRef"
:data="permissionData"
style="max-width: 600px;"
node-key="id"
show-checkbox
:default-checked-keys="defaultKeys"
:default-expanded-keys="[2]"
>
</el-tree>
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="confirm()">确认</el-button>
</div>
</template>
</el-dialog>
</template>
<script setup>
import { ref,reactive,onMounted } from 'vue'
import { userGetMenu,userSetMenu,menuList } from '../../../api'
onMounted(() => {
//菜单数据
userGetMenu().then(({ data }) => {
permissionData.value = data.data
})
getListData()
})
const paginationData = reactive({
pageNum: 1,
pageSize: 10
})
//请求列表数据
const getListData = () => {
menuList(paginationData).then(({data}) => {
})
}
const formRef = ref()
//form的数据
const form = reactive({
id: '',
name: '',
permissions: ''
})
//树形菜单权限数据
const permissionData = ref([])
//弹窗的显示隐藏
const dialogFormVisable = ref(false)
//关闭弹窗的回调
const beforeClose = () => {
dialogFormVisable.value = false
}
//选中权限
const defaultKeys = [4,5]
const treeRef = ref()
//
const rules = reactive({
name: [{ required: true,trigger: 'blur',message: '请输入权限名称'}],
})
//表单提交
const confirm = async (formEl) => {
if (!formEl) return
await formEl.validate((valid,fields) => {
if (valid) {
//获取到选择的checkbox数据
const permissions = JSON.stringify(treeRef.value.getCheckedKeys())
userSetMenu({
name: form.name,
permissions,
id: form.id
}).then((data) => {
})
} else {
console.log('error submit!',fields)
}
})
}
</script>
<style lang="less" scoped>
</style>