只要创建 uniapp 项目就会有默认配置,但我们都会有解决跨域问题等,所以建好项目配置和封装是必要的。
根目录新建一个 common 文件夹,里边配置 util.js 、 request.js 、 config.js 可按需配置,以下配上内容
/**
* 拼接对象为请求字符串
* 对于需要编码的文本(比如说中文)我们要进行编码
* @param {Object} obj - 待拼接的对象
* @returns {string} - 拼接成的请求字符串
**/
export function formatGetUri(obj, Object) {
// const params: Array < string >= []
const params = []
Object.keys(obj).forEach((key) => {
let value = obj[key]
if (typeof value !== 'undefined' || value !== null) {
params.push([key, encodeURIComponent(value)].json('='))
}
})
return '?' + params.join('&')
}
//表单序列化
export function convertSerialize(data){
let list = [];
Object.keys(data).forEach(ele => {
list.push(`${ele}=${data[ele]}`)
})
return list.join('&');
}
import {convertSerialize} from './util.js'
import store from '../store/index.js'
const request = {}
const headers = {}
request.globalRequest = (url, method, data, power) => {
let header = {}
/**
* 权限判断
*/
switch (power) {
case 0:
headers['Authorization'] = 'Bearer' + uni.getStorageSync('token')
// 处理刷新token后重新请求的自定义变量
headers['refresh_token'] = false
break
case 1:
headers['Authorization'] = 'Basic a3N1ZGk6a3N1ZGk='
break;
case 2:
headers['Authorization'] = 'Basic a3N1ZGlfcGM6a3N1ZGlfcGM='
break;
case 3:
responseType = 'blob'
break;
case 4:
header = {
'content-type': "application/x-www-form-urlencoded;charset=utf-8"
}
break;
default:
break;
}
//接口公共参数
const obj = {
orgId: uni.getStorageSync('orgId') || 0,
userId: uni.getStorageSync('userId') || 0,
operator: uni.getStorageSync('loginName') || '匿名',
timestamp: new Date().getTime()
}
let JSONParams = {
url: url,
method: method,
data: { ...obj,
...data
},
dataType: 'JSON',
header: header,
}
if (power != 4) {
JSONParams = {
url: url,
method: method,
data: { ...obj,
...data
},
dataType: 'JSON',
header: headers,
}
}
return uni.request(JSONParams).then(res => {
if (res[1]) {
//TODO 根据实际后台返回格式修改
if (res[1].statusCode == 200) {
// #ifdef H5
return res[1].data
// #endif
// #ifdef MP-WEIXIN
return JSON.parse(res[1].data)
// #endif
// #ifdef APP-PLUS
return res[1].data
// #endif
} else if (res[1].statusCode == 401 && !headers.refresh_token) {
//接口返回401时认证 续签
const {url, method, data} = JSONParams
headers.refresh_token = true
return store.dispatch('refreshToken').then(res=>{
uni.setStorageSync('token',res)
return request.globalRequest(url, method, data, 0)
})
} else if (res[1].statusCode == 403) {
//接口返回403时token过期权限不足,故重登
uni.redirectTo({
url: '/pages/public/login'
})
} else {
//抛出异常
throw res[1].data
}
}
}).catch(params => {
switch (params.code) {
case 401:
uni.clearStorageSync()
break
default:
uni.showToast({
title: params.message,
icon: 'none'
})
return Promise.reject()
break
}
})
}
export default request
此处用到续签,顺便加上这个功能,不需要时可删除,拦截器拦截401前需在 store 入口文件添加操作,place look
import Vue from 'vue'
import Vuex from 'vuex'
import api from '../api/index.js'
Vue.use(Vuex)
const store = new Vuex.Store({
state: {},
actions: {
async refreshToken(store) {
let token = uni.getStorageSync('token')
let refresh_Token = uni.getStorageSync('refreshToken')
let params = {
access_token: token,
refresh_token: refresh_Token,
grant_type: 'refresh_token',
client_id: 'flying',
client_secret: 'yaohw',
}
//登录
let newToken = await api.user.login(params)
return newToken.value
}
}
})
export default store
let UAC_URL = ""
let DT_WB_URL = ""
//默认路径应与 manifest.json 一致,同时修改
let DEFAULT_UAC_URL = "http://192.168.0.125:9101"
let DEFAULT_DT_WB_URL = "http://192.168.0.125:9102"
if (process.env.NODE_ENV === 'development') {
// #ifdef H5
UAC_URL = '/uac'
DT_WB_URL = '/lift'
// #endif
// #ifdef MP-WEIXIN
UAC_URL = DEFAULT_UAC_URL
DT_WB_URL = DEFAULT_DT_WB_URL
// #endif
// #ifdef APP-PLUS
UAC_URL = DEFAULT_UAC_URL
DT_WB_URL = DEFAULT_DT_WB_URL
// #endif
} else {
UAC_URL = DEFAULT_UAC_URL
DT_WB_URL = DEFAULT_DT_WB_URL
}
export default {
UAC_URL,
DT_WB_URL
}
{
"h5" : {
//实现跨域访问
"devServer" : {
"port" : 9200, //本机端口
"disableHostCheck" : true,
"proxy" : { //访问的ip及端口,可有多个
"/uac" : {
"target" : "http://192.168.0.125:9101/",
"changeOrigin" : true,
"secure" : false,
"pathRewrite" : {
"^/uac" : "/"
}
},
"/lift" : {
"target" : "http://192.168.0.125:9102/",
"changeOrigin" : true,
"secure" : false,
"pathRewrite" : {
"^/lift" : "/"
}
}
}
}
}
}
目录安排:
api —— index.js文件、modules文件夹
modules —— js文件(请求接口)
import user from './modules/user.js'
import home from './modules/home.js'
import order from './modules/order.js'
const api = {
user,
home,
order
}
export default api
import request from '@/common/request.js'
import config from '@/common/config.js'
import {
formatGetUri
} from '@/common/util.js'
const uac = config.UAC_URL
const lift = config.DT_WB_URL
const user = {}
//轮播图
user.banners = () => request.globalRequest(lift + "/anon/banner/app/valid", 'POST', null, 0)
export default user
import Vue from 'vue'
import App from './App'
import api from 'api/index.js'
import url from './common/config.js'
Vue.config.productionTip = false
Vue.prototype.$fire = new Vue();
Vue.prototype.$api = {
api
};
Vue.prototype.$url = url;
App.mpType = 'app'
const app = new Vue({
...App
})
app.$mount()
//轮播图,接口已在user.js定义
banners() {
this.$api.api.user.banners().then(res => {
if (res.result.code == '000000') {
this.carouselList = res.body
} else if (res.result.code == '999999') {
this.$u.toast('丫,网络开小差了')
} else {
this.$u.toast(res);
}
})
},
到此为止,一个简单的框架就算完成了,还附带了接口请求及调用、token过期重登及续签,希望整理的还算清楚