vue-d2admin前端axio异步请求详情
vue-d2admin前端axio异步请求详情
- d2admin>src>api>sys.login.js 设计axio api
import request from '@/plugin/axios' export function AccountLogin (data) { return request({ url: '/login', method: 'post', data }) }
- d2admin>src>store>d2admin>modules>account.js 创建使用API模块
import { Message, MessageBox } from 'element-ui' import util from '@/libs/util.js' import router from '@/router' import { AccountLogin } from '@api/sys.login' export default { namespaced: true, actions: { /** * @description 登录 * @param {Object} param context * @param {Object} param username {String} 用户账号 * @param {Object} param password {String} 密码 * @param {Object} param route {Object} 登录成功后定向的路由对象 任何 vue-router 支持的格式 */ login ({ dispatch }, { username = '', password = '' } = {}) { return new Promise((resolve, reject) => { // 开始请求登录接口 AccountLogin({ username, password }) .then(async res => { // 设置 cookie 一定要存 uuid 和 token 两个 cookie // 整个系统依赖这两个数据进行校验和存储 // uuid 是用户身份唯一标识 用户注册的时候确定 并且不可改变 不可重复 // token 代表用户当前登录状态 建议在网络请求中携带 token // 如有必要 token 需要定时更新,默认保存一天 util.cookies.set('uuid', res.uuid) util.cookies.set('token', res.token) // 设置 vuex 用户信息 await dispatch('d2admin/user/set', { name: res.name }, { root: true }) // 用户登录后从持久化数据加载一系列的设置 await dispatch('load') // 结束 resolve() }) .catch(err => { console.log('err: ', err) reject(err) }) }) }, /** * @description 注销用户并返回登录页面 * @param {Object} param context * @param {Object} param confirm {Boolean} 是否需要确认 */ logout ({ commit, dispatch }, { confirm = false } = {}) { /** * @description 注销 */ async function logout () { // 删除cookie util.cookies.remove('token') util.cookies.remove('uuid') // 清空 vuex 用户信息 await dispatch('d2admin/user/set', {}, { root: true }) // 跳转路由 router.push({ name: 'login' }) } // 判断是否需要确认 if (confirm) { commit('d2admin/gray/set', true, { root: true }) MessageBox.confirm('注销当前账户吗? 打开的标签页和用户设置将会被保存。', '确认操作', { confirmButtonText: '确定注销', cancelButtonText: '放弃', type: 'warning' }) .then(() => { commit('d2admin/gray/set', false, { root: true }) logout() }) .catch(() => { commit('d2admin/gray/set', false, { root: true }) Message({ message: '放弃注销用户' }) }) } else { logout() } }, /** * @description 用户登录后从持久化数据加载一系列的设置 * @param {Object} state vuex state */ load ({ dispatch }) { return new Promise(async resolve => { // DB -> store 加载用户名 await dispatch('d2admin/user/load', null, { root: true }) // DB -> store 加载主题 await dispatch('d2admin/theme/load', null, { root: true }) // DB -> store 加载页面过渡效果设置 await dispatch('d2admin/transition/load', null, { root: true }) // DB -> store 持久化数据加载上次退出时的多页列表 await dispatch('d2admin/page/openedLoad', null, { root: true }) // DB -> store 持久化数据加载侧边栏折叠状态 await dispatch('d2admin/menu/asideCollapseLoad', null, { root: true }) // DB -> store 持久化数据加载全局尺寸 await dispatch('d2admin/size/load', null, { root: true }) // end resolve() }) } } }
- d2admin>src>views>system>login>page.vue 通过模块调用API使用axio
methods: { ...mapActions('d2admin/account', [ 'login' ]),
<template> <div class="page-login"> <div class="page-login--layer page-login--layer-area"> <ul class="circles"> <li v-for="n in 10" :key="n"></li> </ul> </div> <div class="page-login--layer page-login--layer-time" flex="main:center cross:center"> {{time}} </div> <div class="page-login--layer"> <div class="page-login--content" flex="dir:top main:justify cross:center box:justify"> <div class="page-login--content-header"> <p class="page-login--content-header-motto"> 时间是一切财富中最宝贵的财富。 <span>—— 德奥弗拉斯多</span> </p> </div> <div class="page-login--content-main" flex="dir:top main:center cross:center"> <!-- logo --> <img class="page-login--logo" src="./image/logo@2x.png"> <!-- 表单 --> <div class="page-login--form"> <el-card shadow="never"> <el-form ref="loginForm" label-position="top" :rules="rules" :model="formLogin" size="default"> <el-form-item prop="username"> <el-input type="text" v-model="formLogin.username" placeholder="用户名"> <i slot="prepend" class="fa fa-user-circle-o"></i> </el-input> </el-form-item> <el-form-item prop="password"> <el-input type="password" v-model="formLogin.password" placeholder="密码"> <i slot="prepend" class="fa fa-keyboard-o"></i> </el-input> </el-form-item> <el-form-item prop="code"> <el-input type="text" v-model="formLogin.code" placeholder="- - - -"> <template slot="prepend">验证码</template> <template slot="append"> <img class="login-code" src="./image/login-code.png"> </template> </el-input> </el-form-item> <el-button size="default" @click="submit" type="primary" class="button-login">登录</el-button> </el-form> </el-card> <p class="page-login--options" flex="main:justify cross:center"> <span><d2-icon name="question-circle"/> 忘记密码</span> <span>注册用户</span> </p> <!-- 快速登录按钮 --> <el-button class="page-login--quick" size="default" type="info" @click="dialogVisible = true"> 快速选择用户(测试功能) </el-button> </div> </div> <div class="page-login--content-footer"> <p class="page-login--content-footer-options"> <a href="#">帮助</a> <a href="#">隐私</a> <a href="#">条款</a> </p> <p class="page-login--content-footer-copyright"> Copyright <d2-icon name="copyright"/> 2018 D2 Projects 开源组织出品 <a href="https://github.com/FairyEver">@FairyEver</a> </p> </div> </div> </div> <el-dialog title="快速选择用户" :visible.sync="dialogVisible" width="400px"> <el-row :gutter="10" style="margin: -20px 0px -10px 0px;"> <el-col v-for="(user, index) in users" :key="index" :span="8"> <div class="page-login--quick-user" @click="handleUserBtnClick(user)"> <d2-icon name="user-circle-o"/> <span>{{user.name}}</span> </div> </el-col> </el-row> </el-dialog> </div> </template> <script> import dayjs from 'dayjs' import { mapActions } from 'vuex' export default { data () { return { timeInterval: null, time: dayjs().format('HH:mm:ss'), // 快速选择用户 dialogVisible: false, users: [ { name: '管理员', username: 'admin', password: 'admin' }, { name: '编辑', username: 'editor', password: 'editor' }, { name: '用户1', username: 'user1', password: 'user1' } ], // 表单 formLogin: { username: 'admin', password: 'admin', code: 'v9am' }, // 校验 rules: { username: [ { required: true, message: '请输入用户名', trigger: 'blur' } ], password: [ { required: true, message: '请输入密码', trigger: 'blur' } ], code: [ { required: true, message: '请输入验证码', trigger: 'blur' } ] } } }, mounted () { this.timeInterval = setInterval(() => { this.refreshTime() }, 1000) }, beforeDestroy () { clearInterval(this.timeInterval) }, methods: { ...mapActions('d2admin/account', [ 'login' ]), refreshTime () { this.time = dayjs().format('HH:mm:ss') }, /** * @description 接收选择一个用户快速登录的事件 * @param {Object} user 用户信息 */ handleUserBtnClick (user) { this.formLogin.username = user.username this.formLogin.password = user.password this.submit() }, /** * @description 提交表单 */ // 提交登录信息 submit () { this.$refs.loginForm.validate((valid) => { if (valid) { // 登录 // 注意 这里的演示没有传验证码 // 具体需要传递的数据请自行修改代码 this.login({ username: this.formLogin.username, password: this.formLogin.password }) .then(() => { // 重定向对象不存在则返回顶层路径 this.$router.replace(this.$route.query.redirect || '/') }) } else { // 登录表单校验失败 this.$message.error('表单校验失败') } }) } } } </script> <style lang="scss"> .page-login { @extend %unable-select; $backgroundColor: #F0F2F5; // --- background-color: $backgroundColor; height: 100%; position: relative; // 层 .page-login--layer { @extend %full; overflow: auto; } .page-login--layer-area { overflow: hidden; } // 时间 .page-login--layer-time { font-size: 24em; font-weight: bold; color: rgba(0, 0, 0, 0.03); overflow: hidden; } // 登陆页面控件的容器 .page-login--content { height: 100%; min-height: 500px; } // header .page-login--content-header { padding: 1em 0; .page-login--content-header-motto { margin: 0px; padding: 0px; color: $color-text-normal; text-align: center; font-size: 12px; span { color: $color-text-sub; } } } // main .page-login--logo { width: 240px; margin-bottom: 2em; margin-top: -2em; } // 登录表单 .page-login--form { width: 280px; // 卡片 .el-card { margin-bottom: 15px; } // 登录按钮 .button-login { width: 100%; } // 输入框左边的图表区域缩窄 .el-input-group__prepend { padding: 0px 14px; } .login-code { height: 40px - 2px; display: block; margin: 0px -20px; border-top-right-radius: 2px; border-bottom-right-radius: 2px; } // 登陆选项 .page-login--options { margin: 0px; padding: 0px; font-size: 14px; color: $color-primary; margin-bottom: 15px; font-weight: bold; } .page-login--quick { width: 100%; } } // 快速选择用户面板 .page-login--quick-user { @extend %flex-center-col; padding: 10px 0px; border-radius: 4px; &:hover { background-color: $color-bg; i { color: $color-text-normal; } span { color: $color-text-normal; } } i { font-size: 36px; color: $color-text-sub; } span { font-size: 12px; margin-top: 10px; color: $color-text-sub; } } // footer .page-login--content-footer { padding: 1em 0; .page-login--content-footer-options { padding: 0px; margin: 0px; margin-bottom: 10px; font-size: 14px; text-align: center; a { color: $color-text-normal; margin: 0 1em; } } .page-login--content-footer-copyright { padding: 0px; margin: 0px; font-size: 12px; color: $color-text-normal; a { color: $color-text-normal; } } } // 背景 .circles { position: absolute; top: 0; left: 0; width: 100%; height: 100%; overflow: hidden; li { position: absolute; display: block; list-style: none; width: 20px; height: 20px; background: #FFF; animation: animate 25s linear infinite; bottom: -200px; @keyframes animate { 0%{ transform: translateY(0) rotate(0deg); opacity: 1; border-radius: 0; } 100%{ transform: translateY(-1000px) rotate(720deg); opacity: 0; border-radius: 50%; } } &:nth-child(1) { left: 15%; width: 80px; height: 80px; animation-delay: 0s; } &:nth-child(2) { left: 5%; width: 20px; height: 20px; animation-delay: 2s; animation-duration: 12s; } &:nth-child(3) { left: 70%; width: 20px; height: 20px; animation-delay: 4s; } &:nth-child(4) { left: 40%; width: 60px; height: 60px; animation-delay: 0s; animation-duration: 18s; } &:nth-child(5) { left: 65%; width: 20px; height: 20px; animation-delay: 0s; } &:nth-child(6) { left: 75%; width: 150px; height: 150px; animation-delay: 3s; } &:nth-child(7) { left: 35%; width: 200px; height: 200px; animation-delay: 7s; } &:nth-child(8) { left: 50%; width: 25px; height: 25px; animation-delay: 15s; animation-duration: 45s; } &:nth-child(9) { left: 20%; width: 15px; height: 15px; animation-delay: 2s; animation-duration: 35s; } &:nth-child(10) { left: 85%; width: 150px; height: 150px; animation-delay: 0s; animation-duration: 11s; } } } } </style>
跨域问题,在vue.config.js里面配置
https://cli.vuejs.org/zh/config/#devserver-proxy
网名:浩秦;
邮箱:root#landv.pw;
博客:landv.cnblogs.com;
只要我能控制一個國家的貨幣發行,我不在乎誰制定法律。金錢一旦作響,壞話隨之戛然而止。