Skip to content

Http.js

javascript
import Vue from 'vue'
import axios from 'axios'
import router from '@/router/router'
// import qs from "querystring";
import { getSession, Ddebounce, removeSession } from '@/utils/utils.js'

// loading对象
let loading = null

// 当前正在请求的数量
let needLoadingRequestCount = 0

// 显示loading
function showLoading() {
  if (needLoadingRequestCount === 0 && !loading) {
    loading = Vue.prototype.$loading({
      lock: true,
      text: '请求中,请稍等...',
      spinner: 'el-icon-loading',
      background: 'rgba(0, 0, 0, 0.7)',
    })
  }
  needLoadingRequestCount++
}

// 隐藏loading
function hideLoading() {
  needLoadingRequestCount--
  needLoadingRequestCount = Math.max(needLoadingRequestCount, 0)
  if (needLoadingRequestCount === 0) {
    toHideLoading()
  }
}

let toHideLoading = Ddebounce(
  () => {
    loading && loading.close()
    loading = null
  },
  500,
  false
)

const service = axios.create({
  baseURL: 'http://xxx.com', // 默认的地址
  timeout: 30000, // 请求超时时间
  headers: {},
})

// 请求拦截器
service.interceptors.request.use(
  (config) => {
    config.headers = Object.assign(config.headers, {
      'ADMIN-TOKEN': getSession('token') || '',
    })
    // 判断当前请求是否设置了不显示 Loading
    if (config.headers.showLoading !== false) {
      showLoading(config.headers.loadingTarget)
    }
    // 返回图片流方式处理
    if (config.url.includes('/login/captcha')) {
      config.responseType = 'arraybuffer'
    }
    if (
      config.method.toLocaleLowerCase() === 'get' ||
      config.method.toLocaleLowerCase() === 'delete'
    ) {
      config.params = config.data
    }
    return config
  },
  (error) => {
    // 判断当前请求是否设置了不显示 Loading
    if (error.config.headers.showLoading !== false) {
      hideLoading()
    }
    return Promise.reject(error)
  }
)

// 返回拦截器
service.interceptors.response.use(
  (config) => {
    // 判断当前请求是否设置了不显示 Loading
    if (config.headers.showLoading !== false) {
      hideLoading()
    }
    // 签名过期情况处理
    if (config.data.code === 10100) {
      removeSession('token')
      router.push('/login')
    }
    return config
  },
  (error) => {
    // 判断当前请求是否设置了不显示 Loading
    if (error.config.headers.showLoading !== false) {
      hideLoading()
    }
    return Promise.reject(error)
  }
)

// 挂载请求
Vue.prototype.$axios = service

// 请求统一处理
function requst(options) {
  return new Promise((resolve, reject) => {
    options
      .then((res) => {
        // 返回图片流方式处理
        if (res.config.url.includes('/login/captcha')) {
          resolve(
            'data:image/png;base64,' +
              btoa(
                new Uint8Array(res.data).reduce(
                  (data, byte) => data + String.fromCharCode(byte),
                  ''
                )
              )
          )
        } else {
          if (res.data?.code == 0) {
            resolve(res.data)
          } else {
            reject(res.data.msg || res.data.Msg || '加载数据超时,请稍后重试')
          }
        }
      })
      .catch((error) => {
        if (error.message.includes(`timeout of ${error.config.timeout}ms exceeded`)) {
          reject('加载数据超时,请稍后重试')
        } else {
          reject(error)
        }
      })
  })
}

// get.post.put.del.patch请求方法提取
const get = (url, params, showLoading = true) => {
  return requst(service.get(url, { data: params }, { headers: { showLoading } }))
}
const post = (url, params, showLoading = true) => {
  return requst(service.post(url, params, { headers: { showLoading } }))
}
const put = (url, params, showLoading = true) => {
  return requst(service.put(url, params, { headers: { showLoading } }))
}
const del = (url, params, showLoading = true) => {
  return requst(service.delete(url, { data: params }, { headers: { showLoading } }))
}
const patch = (url, params, showLoading = true) => {
  return requst(service.patch(url, { data: params }, { headers: { showLoading } }))
}

export default requst
export { get, post, put, del, patch }

Login.Request.js

javascript
// 根据模块封装

import { get, post } from '../Http'

export default {
  /**
   * @method 获取登录图像验证码
   * @param {*} key 随机数
   */
  getCodeImage: (params) => get(`/login/captcha?key=${params}`, '', false),

  /**
   * @method 获取图形验证码
   * @param {*} key 随机数
   */
  checkLoginCode: (params) => get(`/login/check`, params, false),

  /**
   * @method 登录验证
   * @param {*} name 登录名
   * @param {*} password 密码
   * @param {*} code 验证码
   */
  login: (params) => post(`/login`, params, false),

  /**
   * @method 退出登录
   * @param {*}
   */
  logout: (params) => post(`/logout`, params, false),
}

Login.vue 测试

vue
<template>
  <div class="login-wrap">
    <div class="ms-login">
      <div class="ms-title">{{ adminTitle }}</div>
      <el-form
        :model="form"
        :rules="rules"
        ref="ruleForm"
        label-width="0px"
        class="ms-content"
      >
        <el-form-item prop="username">
          <el-input v-model="form.name" placeholder="请输入用户名称" clearable></el-input>
        </el-form-item>
        <el-form-item prop="password">
          <el-input
            type="password"
            placeholder="请输入密码"
            v-model="form.password"
            show-password
            clearable
            maxlength="20"
            show-word-limit
          ></el-input>
        </el-form-item>
        <el-form-item label prop="code">
          <div class="disflex flexdr">
            <el-input placeholder="请输入验证码" v-model="form.code" clearable></el-input>
            <el-image @click="refreshCode" :src="codeImage" alt class="codeImage">
              <div slot="error" class="image-slot">
                <i class="el-icon-picture-outline"></i>
              </div>
            </el-image>
          </div>
        </el-form-item>
        <div class="login-btn">
          <el-button type="primary" @click="submitForm('ruleForm')">登录</el-button>
        </div>
      </el-form>
    </div>
  </div>
</template>

<script>
import LoginAjax from '@/utils/https/modules/Login.request.js'
import { generateString, setSession } from '@/utils/utils.js'

export default {
  data() {
    return {
      adminTitle: 'xxx 用户后台',
      form: {
        name: '',
        password: '',
        code: '',
      },
      rules: {
        name: [{ required: true, message: '请输入用户名称', trigger: 'blur' }],
        password: [{ required: true, message: '请输入密码', trigger: 'blur' }],
        code: [{ required: true, message: '请输入验证码', trigger: 'blur' }],
      },
      codeImage: '',
      codeKey: generateString('xxxxxxxxxxx'),
    }
  },
  methods: {
    // 刷新验证码
    async refreshCode() {
      try {
        this.codeImage = ''
        this.codeKey = generateString('xxxxxxxxxx')
        this.codeImage = await LoginAjax.getCodeImage(this.codeKey)
      } catch (error) {
        this.$message.error(error)
      }
    },

    // 登录
    submitForm(formName) {
      this.$refs[formName].validate(async (valid) => {
        if (valid) {
          try {
            const { data, msg } = await LoginAjax.login({
              key: this.codeKey,
              ...this.form,
            })
            setSession('xxxtoken', data)
            this.$message.success(msg)
            this.$router.push('/activity')
          } catch (error) {
            this.refreshCode()
            this.form.code = ''
            return false
          }
        } else {
          return false
        }
      })
    },
  },
  mounted() {
    this.$nextTick(() => {
      this.refreshCode()
    })
  },
}
</script>

<style lang="scss" scoped>
// ...
</style>