zoukankan      html  css  js  c++  java
  • 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 {
         240px;
        margin-bottom: 2em;
        margin-top: -2em;
      }
      // 登录表单
      .page-login--form {
         280px;
        // 卡片
        .el-card {
          margin-bottom: 15px;
        }
        // 登录按钮
        .button-login {
           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 {
           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;
         100%;
        height: 100%;
        overflow: hidden;
        li {
          position: absolute;
          display: block;
          list-style: none;
           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%;
             80px;
            height: 80px;
            animation-delay: 0s;
          }
          &:nth-child(2) {
            left: 5%;
             20px;
            height: 20px;
            animation-delay: 2s;
            animation-duration: 12s;
          }
          &:nth-child(3) {
            left: 70%;
             20px;
            height: 20px;
            animation-delay: 4s;
          }
          &:nth-child(4) {
            left: 40%;
             60px;
            height: 60px;
            animation-delay: 0s;
            animation-duration: 18s;
          }
          &:nth-child(5) {
            left: 65%;
             20px;
            height: 20px;
            animation-delay: 0s;
          }
          &:nth-child(6) {
            left: 75%;
             150px;
            height: 150px;
            animation-delay: 3s;
          }
          &:nth-child(7) {
            left: 35%;
             200px;
            height: 200px;
            animation-delay: 7s;
          }
          &:nth-child(8) {
            left: 50%;
             25px;
            height: 25px;
            animation-delay: 15s;
            animation-duration: 45s;
          }
          &:nth-child(9) {
            left: 20%;
             15px;
            height: 15px;
            animation-delay: 2s;
            animation-duration: 35s;
          }
          &:nth-child(10) {
            left: 85%;
             150px;
            height: 150px;
            animation-delay: 0s;
            animation-duration: 11s;
          }
        }
      }
    }
    </style>

    跨域问题,在vue.config.js里面配置

    https://cli.vuejs.org/zh/config/#devserver-proxy

  • 相关阅读:
    HDU4628+状态压缩DP
    Javascript 去掉字符串前后空格的五种方法
    Javascript 数组之判断取值和数组取值
    ASP.NET MVC 出现错误 “The view 'XXX' or its master was not found or no view engine support”
    ASP.NET MVC 页面调整并传递参数
    ASP.NET MV3 部署网站 报"Could not load file or assembly ' System.Web.Helpers “ 错的解决方法
    ASP.NET MVC 控制器向View传值的三种方法
    CSharp 如何通过拼接XML调用存储过程来查询数据
    SQLServer : EXEC和sp_executesql的区别
    关于SQLServer2005的学习笔记—异常捕获及处理
  • 原文地址:https://www.cnblogs.com/landv/p/11095094.html
Copyright © 2011-2022 走看看