Quellcode durchsuchen

对请求接口进行封装,

XSXS vor 8 Monaten
Ursprung
Commit
9a1173b0ca

+ 43 - 0
common/baseUrl.js

@@ -0,0 +1,43 @@
+let baseUrl = "";
+let socketUrl =""
+if (process.env.NODE_ENV === 'development') {
+	baseUrl = "https://e.zhichao.art/Gapi";
+} else if (process.env.NODE_ENV === 'production') {
+	// 生产环境
+	baseUrl = "https://e.zhichao.art/Gapi";
+}
+const courtConfig = {
+	//微信公众号APPID
+	publicAppId: "xxxxxxxxxxxxx",
+	//请求接口
+	baseUrl: baseUrl,
+	socketUrl:socketUrl,
+	//平台名称
+	platformName: "萌创星球",
+	//项目logo
+	logoUrl: "/static/logo.png",
+	//页面分享配置
+	share: {
+		title: '萌创星球',
+		// #ifdef MP-WEIXIN
+		path: '/pages/home/home', //小程序分享路径
+		// #endif
+		// #ifdef H5 || APP-PLUS
+		//公众号||APP分享
+		desc: "萌创星球", // 分享描述
+		link: "xxxxxxxxxxx", // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
+		imgUrl: "xxxxxxxxxxxxxxxxx", // 分享图标
+		// #endif
+	}
+};
+//手机号验证正则表达式
+const phoneRegular = /^1\d{10}$/;
+//邮箱验证正则表达式
+const mailRegular = /^\w+@\w+(\.[a-zA-Z]{2,3}){1,2}$/;
+//密码验证正则表达式
+const passwordRegular = /^[a-zA-Z0-9]{4,10}$/;
+export default Object.assign({
+	phoneRegular,
+	mailRegular,
+	passwordRegular
+}, courtConfig);

+ 152 - 0
common/requestConfig.js

@@ -0,0 +1,152 @@
+import request from "@/node_modules/zhouWei-request/js_sdk/request"; 
+import base from '@/common/baseUrl';
+ 
+let version_code = '';
+// #ifdef APP-PLUS
+import {
+	getCurrentNo
+} from '@/uni_modules/zhouWei-APPUpdate/js_sdk/appUpdate';
+import {
+	isString
+} from "util";
+import { log } from "console";
+setTimeout(() => {
+	getCurrentNo(function(res) {
+		console.log("版本号", res);
+		version_code = res.versionCode;
+	});
+}, 200);
+// #endif
+
+//可以new多个request来支持多个域名请求
+let $http = new request({
+	//接口请求地址
+	baseUrl: base.baseUrl,
+	//服务器本地上传文件地址
+	fileUrl: base.baseUrl,
+	// 服务器上传图片默认url
+	defaultUploadUrl: "api/common/v1/upload_image",
+	// 服务器上传文件名称
+	defaultFileName: "file",
+	//设置请求头(如果使用报错跨域问题,可能是content-type请求类型和后台那边设置的不一致)
+	header: {
+		'content-type': 'application/json;',
+		// 'project_token': base.projectToken, //项目token(可删除)
+	}
+});
+ 
+//请求开始拦截器
+$http.requestStart = function(options) {
+	if (options.load) { 
+	}
+	// 图片、视频上传大小限制
+	if (options.method == "FILE") {
+		// 文件最大字节: options.maxSize 可以在调用方法的时候加入参数
+		let maxSize = options.maxSize || '';
+		for (let item of options.files) {
+			if (item.fileType == 'image') {
+				if (maxSize && item.size > maxSize) {
+					setTimeout(() => {
+						uni.showToast({
+							title: "图片过大,请重新上传",
+							icon: "none"
+						});
+					}, 500);
+					return false;
+				}
+			} else if (item.fileType == "video") {
+				if (item.duration < 3) {
+					setTimeout(() => {
+						uni.showToast({
+							title: "视频长度不足3秒,请重新上传",
+							icon: "none"
+						});
+					}, 500);
+					return false;
+				}
+			}
+		}
+	}
+	// #ifdef APP-PLUS
+	// 添加当前版本号
+	if (version_code) {
+		options.header['version_code'] = version_code;
+	}
+	// #endif
+	//请求前加入token 
+		options.header.sign = getApp().globalData.headerSign
+		// options.header["content-type"] = "application/json" 
+	return options;
+}
+//请求结束
+$http.requestEnd = function(options) {
+ 
+}
+let loginPopupNum = 0;
+let num = 0
+$http.dataFactory = function(res) {
+	console.log("接口请求数据", {
+		url: res.url,
+		resolve: res.response,
+		header: res.header,
+		data: res.data,
+		method: res.method,
+	});
+	if (res.response.statusCode && res.response.statusCode == 200) {
+		let httpData = res.response.data ;
+		if (typeof(httpData) == "string") {
+			httpData = JSON.parse(httpData);
+		}  
+	
+		//判断数据是否请求成功
+		if (httpData.success == "yes" || httpData.statusCode == "200") {
+			// 返回正确的结果(then接受数据)   
+			// 返回Promise对象,支持链式调用和await操作
+			return Promise.resolve( res.response);
+		} else if (isString(httpData.resultCode)) {
+		  
+		} else { //其他错误提示   
+			if (res.isPrompt) {
+				uni.showToast({
+					title: httpData.info || httpData.msg,
+					icon: "none",
+					duration: 3000
+				});
+			}
+			// 返回错误的结果(catch接受数据)
+			return Promise.reject({
+				statusCode: 0,
+				errMsg: "【request】" + (httpData.info || httpData.msg),
+				data: res.data
+			});
+		}
+
+		 
+
+	} else {
+		// 返回错误的结果(catch接受数据)
+		return Promise.reject({
+			statusCode: res.response.statusCode,
+			errMsg: "【request】数据工厂验证不通过",
+			data: res.data
+		});
+	}
+};
+var content = 0
+// 错误回调
+$http.requestError = function(e) {
+	// e.statusCode === 0 是参数效验错误抛出的
+	if (e.statusCode === 0) {
+		throw e;
+	} else {
+		if (content != 0) {
+			uni.showToast({
+				title: "网络错误,请检查一下网络",
+				icon: "none"
+			});
+		} else {
+			content = 1
+		}
+	}
+}
+export default $http;

+ 102 - 0
common/socket.js

@@ -0,0 +1,102 @@
+import base from '@/config/baseUrl'; 
+class socket {
+	constructor(options) {
+		//地址
+		this.socketUrl = base.socketUrl;
+		this.socketStart = false;
+		this.monitorSocketError();
+		this.monitorSocketClose();
+		this.socketReceive();
+	}
+	init(callback) {
+		const _this = this;
+		if (base.socketUrl) {
+			if(this.socketStart){
+				console.log('webSocket已经启动了');
+			}else{
+				uni.connectSocket({
+					url: this.socketUrl,
+					method: 'GET'
+				});
+				uni.onSocketOpen((res) => {
+					this.socketStart = true;
+					callback && callback();
+					console.log('WebSocket连接已打开!');
+				});
+				setTimeout(() => {
+					_this.getHeartbeat();
+				}, 5000);
+			}
+		}else{
+			console.log('config/baseUrl socketUrl为空');
+		}
+	}
+	//Socket给服务器发送消息
+	send(data, callback) {
+		const _this = this;
+		// if (store.state.userInfo.uid) {
+		// 	data.userUid = store.state.userInfo.uid;
+		// }
+		console.log(data);
+		uni.sendSocketMessage({
+			data: JSON.stringify(data),
+			success: () => {
+				callback && callback(true);
+			},
+			fail: () => {
+				callback && callback(false);
+			}
+		});
+	}
+	//Socket接收服务器发送过来的消息
+	socketReceive() {
+		const _this = this;
+		uni.onSocketMessage(function(res) {
+			let data = JSON.parse(res.data);
+			console.log('收到服务器内容:', data);
+			_this.acceptMessage && _this.acceptMessage(data);
+		});
+	}
+	//关闭Socket
+	closeSocket() {
+		uni.closeSocket();
+		_this.socketStart = false;
+	}
+	//监听Socket关闭
+	monitorSocketClose() {
+		const _this = this;
+		uni.onSocketClose(function(res) {
+			console.log('WebSocket 已关闭!');
+			_this.socketStart = false;
+			setTimeout(function() {
+				_this.init();
+			}, 3000);
+		});
+	}
+	//监听Socket错误
+	monitorSocketError() {
+		const _this = this;
+		uni.onSocketError(function(res) {
+			_this.socketStart = false;
+			console.log('WebSocket连接打开失败,请检查!');
+		});
+	}
+	//心跳
+	getHeartbeat() {
+		const _this = this;
+		this.send({
+			type: "心跳",
+			userUid: store.state.userInfo.userUid
+		}, (val) => {
+			setTimeout(() => {
+				if (val) {
+					_this.getHeartbeat();
+				} else {
+					_this.init();
+				}
+			}, 10000);
+		});
+	}
+};
+const mySocket = new socket();
+export default mySocket;

+ 2 - 2
components/card/card.vue

@@ -123,7 +123,7 @@
 
 				.look-icon {
 					width: 26rpx;
-					height: 18rpx;
+					height: 26rpx;
 					margin-right: 10rpx;
 				}
 
@@ -189,7 +189,7 @@
 
 					.like-icon {
 						width: 30rpx;
-						height: 25rpx;
+						height: 30rpx;
 						margin-right: 10rpx;
 					}
 

+ 4 - 0
main.js

@@ -25,6 +25,10 @@ Vue.prototype.isArray = Array.isArray || function(obj) {
 	return obj instanceof Array;
 };
 
+//挂载全局http请求
+import $http from '@/common/requestConfig'
+Vue.prototype.$http = $http;
+
 App.mpType = 'app'
 
 const app = new Vue({

+ 10 - 0
node_modules/zhouWei-request/changelog.md

@@ -0,0 +1,10 @@
+## 3.3.2(2021-07-29)
+修复app用阿里云上传文件报错
+## 3.3.1(2021-07-09)
+修改阿里云视频上传bug
+## 3.3.0(2021-07-09)
+新增阿里云文件上传、图片上传
+## 3.2.1(2021-05-18)
+新增文件类型
+## 3.2.0(2021-05-12)
+1. 支持uni_modules

+ 132 - 0
node_modules/zhouWei-request/js_sdk/request/core/request.js

@@ -0,0 +1,132 @@
+import { mergeConfig, dispatchRequest, jsonpRequest} from "./utils.js";
+export default class request {
+	constructor(options) {
+		//请求公共地址
+		this.baseUrl = options.baseUrl || "";
+		//公共文件上传请求地址
+		this.fileUrl = options.fileUrl || "";
+		// 超时时间
+		this.timeout = options.timeout || 6000;
+		// 服务器上传图片默认url
+		this.defaultUploadUrl = options.defaultUploadUrl || "";
+		// 服务器上传文件名称
+		this.defaultFileName = options.defaultFileName || "";
+		//默认请求头
+		this.header = options.header || {};
+		//默认配置
+		this.config = options.config || {
+			isPrompt: true,
+			load: true,
+			isFactory: true,
+            resend: 0
+		};
+	}
+	//post请求
+	post(url = '', data = {}, options = {}) {
+		return this.request({
+			method: "POST",
+			data: data,
+			url: url,
+			...options
+		});
+	}
+
+	//get请求
+	get(url = '', data = {}, options = {}) {
+		return this.request({
+			method: "GET",
+			data: data,
+			url: url,
+			...options
+		});
+	}
+
+	//put请求
+	put(url = '', data = {}, options = {}) {
+		return this.request({
+			method: "PUT",
+			data: data,
+			url: url,
+			...options
+		});
+	}
+
+	//delete请求
+	delete(url = '', data = {}, options = {}) {
+		return this.request({
+			method: "DELETE",
+			data: data,
+			url: url,
+			...options
+		});
+	}
+	//jsonp请求(只限于H5使用)
+	jsonp(url = '', data = {}, options = {}) {
+		return this.request({
+			method: "JSONP",
+			data: data,
+			url: url,
+			...options
+		});
+	}
+	//接口请求方法
+	async request(data) {
+		// 请求数据
+		let requestInfo,
+		// 是否运行过请求开始钩子
+		runRequestStart = false;
+		try {
+			if (!data.url) {
+				throw { errMsg: "【request】缺失数据url", statusCode: 0}
+			}
+			// 数据合并
+			requestInfo = mergeConfig(this, data);
+			// 代表之前运行到这里
+			runRequestStart = true;
+			//请求前回调
+			if (this.requestStart) {
+				let requestStart = this.requestStart(requestInfo);
+				if (typeof requestStart == "object") {
+					let changekeys = ["data", "header", "isPrompt", "load", "isFactory"];
+					changekeys.forEach(key => {
+						requestInfo[key] = requestStart[key];
+					});
+				} else {
+					throw {
+						errMsg: "【request】请求开始拦截器未通过",
+						statusCode: 0,
+						data: requestInfo.data,
+						method: requestInfo.method,
+						header: requestInfo.header,
+						url: requestInfo.url,
+					}
+				}
+			}
+			let requestResult = {};
+			if(requestInfo.method == "JSONP"){
+				requestResult = await jsonpRequest(requestInfo);
+			} else {
+				requestResult = await dispatchRequest(requestInfo);
+			}
+			//是否用外部的数据处理方法
+			if (requestInfo.isFactory && this.dataFactory) {
+				//数据处理
+				let result = await this.dataFactory({
+					...requestInfo,
+					response: requestResult
+				});
+				return Promise.resolve(result);
+			} else {
+				return Promise.resolve(requestResult);
+			}
+		} catch (err){
+			this.requestError && this.requestError(err);
+			return Promise.reject(err);
+		} finally {
+			// 如果请求开始未运行到,请求结束也不运行
+			if(runRequestStart){
+				this.requestEnd && this.requestEnd(requestInfo);
+			}
+		}
+	}
+}

+ 101 - 0
node_modules/zhouWei-request/js_sdk/request/core/utils.js

@@ -0,0 +1,101 @@
+// 获取合并的数据
+export const mergeConfig = function(_this, options) {
+	//判断url是不是链接
+	let urlType = /^(http|https):\/\//.test(options.url);
+	let config = Object.assign({
+		timeout: _this.timeout
+	}, _this.config, options);
+	if (options.method == "FILE") {
+		config.url = urlType ? options.url : _this.fileUrl + options.url;
+	} else {
+		config.url = urlType ? options.url : _this.baseUrl + options.url;
+	}
+	//请求头
+	if (options.header) {
+		config.header = Object.assign({}, _this.header, options.header);
+	} else {
+		config.header = Object.assign({}, _this.header);
+	}
+	return config;
+}
+// 请求
+export const dispatchRequest = function(requestInfo) {
+	return new Promise((resolve, reject) => {
+		let requestAbort = true;
+		let requestData = {
+			url: requestInfo.url,
+			header: requestInfo.header, //加入请求头
+			success: (res) => {
+				requestAbort = false;
+				resolve(res);
+			},
+			fail: (err) => {
+				requestAbort = false;
+				if(err.errMsg == "request:fail abort"){
+					reject({
+						errMsg: "请求超时,请重新尝试",
+						statusCode: 0,
+					});
+				} else {
+					reject(err);
+				}
+			}
+		};
+		//请求类型
+		if (requestInfo.method) {
+			requestData.method = requestInfo.method;
+		}
+		if (requestInfo.data) {
+			requestData.data = requestInfo.data;
+		}
+		// #ifdef MP-WEIXIN || MP-ALIPAY
+		if (requestInfo.timeout) {
+			requestData.timeout = requestInfo.timeout;
+		}
+		// #endif
+		if (requestInfo.dataType) {
+			requestData.dataType = requestInfo.dataType;
+		}
+		// #ifndef APP-PLUS || MP-ALIPAY
+		if (requestInfo.responseType) {
+			requestData.responseType = requestInfo.responseType;
+		}
+		// #endif
+		// #ifdef H5
+		if (requestInfo.withCredentials) {
+			requestData.withCredentials = requestInfo.withCredentials;
+		}
+		// #endif
+		let requestTask = uni.request(requestData);
+		setTimeout(() => {
+			if(requestAbort){
+				requestTask.abort();
+			}
+		}, requestInfo.timeout)
+	})
+}
+// jsonp请求
+export const jsonpRequest = function(requestInfo) {
+	return new Promise((resolve, reject) => {
+		let dataStr = '';
+		Object.keys(requestInfo.data).forEach(key => {
+			dataStr += key + '=' + requestInfo.data[key] + '&';
+		});
+		//匹配最后一个&并去除
+		if (dataStr !== '') {
+			dataStr = dataStr.substr(0, dataStr.lastIndexOf('&'));
+		}
+		requestInfo.url = requestInfo.url + '?' + dataStr;
+		let callbackName = "callback" + Math.ceil(Math.random() * 1000000);
+		// #ifdef H5
+		window[callbackName] = function(data) {
+			resolve(data);
+		}
+		let script = document.createElement("script");
+		script.src = requestInfo.url + "&callback=" + callbackName;
+		document.head.appendChild(script);
+		// 及时删除,防止加载过多的JS
+		document.head.removeChild(script);
+		// #endif
+	});
+}

+ 7 - 0
node_modules/zhouWei-request/js_sdk/request/index.js

@@ -0,0 +1,7 @@
+/***************纯粹的数据请求(如果使用这种可以删除掉fileUpload.js)******************/
+// import request from "./core/request.js";
+// export default request;
+
+/********数据请求同时继承了文件上传(包括七牛云上传)************/
+import upload from "./upload/upload.js";
+export default upload;

+ 451 - 0
node_modules/zhouWei-request/js_sdk/request/request.md

@@ -0,0 +1,451 @@
+# request请求、配置简单、批量上传图片、视频、超强适应性(支持多域名请求)
+1. 配置简单、源码清晰注释多、适用于一项目多域名请求、第三方请求、七牛云图片上传、本地服务器图片上传等等
+2. 支持请求`get`、`post`、`put`、`delete`
+3. 自动显示请求加载动画(可单个接口关闭)
+4. 全局`api`数据处理函数,只回调请求正确的数据(可单个接口关闭)
+5. 未登录或登录失效自动拦截并调用登录方法(可单个接口关闭)
+6. 全局自动提示接口抛出的错误信息(可单个接口关闭)
+7. 支持 Promise
+8. 支持拦截器
+9. 支持七牛云文件(图片、视频)批量上传
+10. 支持本地服务器文件(图片、视频)批量上传
+11. 支持上传文件拦截过滤
+12. 支持上传文件进度监听
+13. 支持上传文件单张成功回调
+
+| `QQ交流群(607391225)`         | `微信交流群(加我好友备注"进群")`                  |
+| ----------------------------|--------------------------- |
+|![QQ交流群](http://qn.kemean.cn//upload/202004/14/15868301778472k7oubi6.png)|![微信交流群](https://qn.kemean.cn/upload/202010/13/weiXin_group_code.jpg)|
+| QQ群号:607391225 |微信号:zhou0612wei|
+
+### [点击跳转-插件示例](https://ext.dcloud.net.cn/plugin?id=2009)
+### [点击跳转-5年的web前端开源的uni-app快速开发模板-下载看文档](https://ext.dcloud.net.cn/plugin?id=2009)
+
+### 常见问题
+1.接口请求成功了,没有返回数据或者数据是走的catch回调
+
+答:`requestConfig.js` 请求配置文件里面,有一个`$http.dataFactory`方法,里面写的只是参考示例,`此方法需要开发者根据各自的接口返回类型修改`
+
+2.官方的方法有数据,本插件方法请求报错跨域问题
+
+答:`requestConfig.js` 请求配置文件里面,`header`请求头设置的`content-type`请求类型需求和后台保持一致
+
+3.登录后用户`token`怎么设置?
+
+答:`requestConfig.js` 请求配置文件里面,`$http.requestStart`请求开始拦截器里面设置
+
+4.怎么判断上传的文件(图片)太大?怎么过滤掉太大的文件(图片)?
+
+答:`requestConfig.js` 请求配置文件里面,`$http.requestStart`请求开始拦截器里面设置
+
+5.接口请求成功了,一直提示“网络错误,请检查一下网络”?
+
+答:`requestConfig.js` 请求配置文件里面,有一个`$http.dataFactory`方法,里面写的只是参考示例,`此方法需要开发者根据各自的接口返回类型修改`
+
+### 本次更新注意事项
+1. 所有的headers都改成了header(和官方统一)
+2. 七牛云的获取token等信息提取到了`requestConfig.js`文件,参考如下
+
+### 文件说明
+1. `request => core` 请求方法的目录
+2. `request => core => request.js` 请求方法的class文件
+3. `request => core => utils.js` 请求方法的源码文件
+4. `request => upload` 上传方法的目录
+5. `request => upload => upload.js` 上传方法的class文件
+6. `request => upload => utils.js` 上传方法源码文件
+7. `request => upload => qiniuUploader.js` 七牛云官方上传文件
+8. `request => index.js` 输出方法的文件
+9. `requestConfig.js` 请求配置文件(具体看代码)
+
+### 在main.js引入并挂在Vue上
+```
+import $http from '@/zhouWei-request/requestConfig';
+Vue.prototype.$http = $http;
+```
+
+### `requestConfig.js`配置说明(requestConfig.js有配置示例)
+```
+import request from "@/plugins/request";
+//可以new多个request来支持多个域名请求
+let $http = new request({
+	//接口请求地址
+	baseUrl: "https://twin-ui.com/", //示例域名,请自行设计
+	//服务器本地上传文件地址
+	fileUrl: "https://twin-ui.com/", //示例域名,请自行设计
+	// 服务器上传图片默认url
+	defaultUploadUrl: "api/common/v1/upload_image",
+	//设置请求头(如果使用报错跨域问题,可能是content-type请求类型和后台那边设置的不一致)
+	header: {
+		'Content-Type': 'application/json;charset=UTF-8'
+	},
+    // 请求超时时间(默认6000)
+    timeout: 6000,
+    // 默认配置(可不写)
+    config: {
+        // 是否自动提示错误
+        isPrompt: true,
+        // 是否显示加载动画
+        load: true,
+        // 是否使用数据工厂
+        isFactory: true,
+       // ... 可写更多配置
+    }
+});
+
+// 添加获取七牛云token的方法
+$http.getQnToken = function(callback){
+	//该地址需要开发者自行配置(每个后台的接口风格都不一样)
+	$http.get("api/common/v1/qn_upload").then(data => {
+		/*
+		 *接口返回参数:
+		 *visitPrefix:访问文件的域名
+		 *token:七牛云上传token
+		 *folderPath:上传的文件夹
+		 *region: 地区 默认为:SCN
+		 */
+		callback({
+			visitPrefix: data.visitPrefix,
+			token: data.token,
+			folderPath: data.folderPath
+		});
+	});
+}
+//当前接口请求数
+let requestNum = 0;
+//请求开始拦截器
+$http.requestStart = function(options) {
+    if (options.load) {
+    	if (requestNum <= 0) {
+            //打开加载动画
+            uni.showLoading({
+                title: '加载中',
+                mask: true
+            });
+        }
+        requestNum += 1;
+    }
+    // 图片上传大小限制
+    if (options.method == "FILE" && options.maxSize) {
+    	// 文件最大字节: options.maxSize 可以在调用方法的时候加入参数
+    	let maxSize = options.maxSize;
+    	for (let item of options.files) {
+    		if (item.size > maxSize) {
+    			setTimeout(() => {
+    				uni.showToast({
+    					title: "图片过大,请重新上传",
+    					icon: "none"
+    				});
+    			}, 500);
+    			return false;
+    		}
+    	}
+    }
+    //请求前加入token
+    options.header['token'] = "你的项目token";
+    return options; // return false 表示请求拦截,不会继续请求
+}
+//请求结束
+$http.requestEnd = function(options) {
+	//判断当前接口是否需要加载动画
+	if (options.load) {
+		requestNum = requestNum - 1;
+		if (requestNum <= 0) {
+			uni.hideLoading();
+		}
+	}
+}
+//所有接口数据处理(可在接口里设置不调用此方法)
+//此方法需要开发者根据各自的接口返回类型修改,以下只是模板
+$http.dataFactory = async function(res) {
+    console.log("接口请求数据", {
+        url: res.url,
+        resolve: res.response,
+        header: res.header,
+        data: res.data,
+        method: res.method,
+    });
+    if (res.response.statusCode && res.response.statusCode == 200) {
+        let httpData = res.response.data;
+        if (typeof (httpData) == "string") {
+            httpData = JSON.parse(httpData);
+        }
+        // 开始----------------------以下是示例-请认真阅读代码-----------------------开始
+        //判断数据是否请求成功
+        if (httpData.success || httpData.code == 200) {  // 重点------判断接口请求是否成功,成功就返回成功的数据
+            // ---重点---返回正确的结果(then接受数据)---重点---
+            return Promise.resolve(httpData);
+        } else {
+            //其他错误提示
+            if (res.isPrompt) { // 是否提示
+                uni.showToast({
+                    title: httpData.info || httpData.msg, // 重点------把接口返回的错误抛出显示
+                    icon: "none",
+                    duration: 3000
+                });
+            }
+            // ---重点---返回错误的结果(catch接受数据)----重点---
+            return Promise.reject({
+                statusCode: 0,
+                errMsg: "【request】" + (httpData.info || httpData.msg)
+            });
+        }
+        // 结束----------------------以上是示例-请认真阅读代码-----------------------结束
+    } else {
+		// 返回错误的结果(catch接受数据)
+		return Promise.reject({
+			statusCode: res.response.statusCode,
+			errMsg: "【request】数据工厂验证不通过"
+		});
+	}
+};
+// 错误回调(所有错误都在这里)
+$http.requestError = function (e) {
+	if (e.statusCode === 0) {
+		throw e;
+	} else {
+		uni.showToast({
+			title: "网络错误,请检查一下网络",
+			icon: "none"
+		});
+	}
+}
+```
+
+### 通用请求方法
+```
+this.$http.request({
+	url: 'aid/region',
+	method: "GET", // POST、GET、PUT、DELETE、JSONP,具体说明查看官方文档
+	data: {pid:0},
+	timeout: 30000,  // 默认 30000 说明:超时时间,单位 ms,具体说明查看官方文档
+	dataType: "json",  // 默认 json 说明:如果设为 json,会尝试对返回的数据做一次 JSON.parse,具体说明查看官方文档
+	responseType: "text",  // 默认 text 说明:设置响应的数据类型。合法值:text、arraybuffer,具体说明查看官方文档
+	withCredentials: false,  // 默认 false 说明:跨域请求时是否携带凭证(cookies),具体说明查看官方文档
+	isPrompt: true,//(默认 true 说明:本接口抛出的错误是否提示)
+	load: true,//(默认 true 说明:本接口是否提示加载动画)
+	header: { //默认 无 说明:请求头
+		'Content-Type': 'application/json'
+	},
+	isFactory: true, //(默认 true 说明:本接口是否调用公共的数据处理方法,设置false后isPrompt参数将失去作用)
+}).then(function (response) {
+	//这里只会在接口是成功状态返回
+}).catch(function (error) {
+	//这里只会在接口是失败状态返回,不需要去处理错误提示
+	console.log(error);
+});
+```
+
+### get请求 正常写法 
+```
+this.$http.get('aid/region',{pid:0}).
+then(function (response) {
+	//这里只会在接口是成功状态返回
+}).catch(function (error) {
+	//这里只会在接口是失败状态返回,不需要去处理错误提示
+	console.log(error);
+});
+```
+
+### post请求 async写法 
+```
+async request(){
+	let data = await this.$http.post('aid/region',{pid:0});
+	console.log(data);
+}
+```
+
+### 其他功能配置项
+```
+let data = await this.$http.post(
+	'http://www.aaa.com/aid/region', //可以直接放链接(将不启用全局定义域名)
+	{
+		pid:0
+	}, 
+	{
+		isPrompt: true,//(默认 true 说明:本接口抛出的错误是否提示)
+		load: true,//(默认 true 说明:本接口是否提示加载动画)
+		header: { //默认 无 说明:请求头
+			'Content-Type': 'application/json'
+		},
+		isFactory: true //(默认 true 说明:本接口是否调用公共的数据处理方法,设置false后isPrompt参数将失去作用)
+	}
+);
+```
+
+### `requestConfig.js`可以设置服务器上传图片默认url
+```
+//可以new多个request来支持多个域名请求
+let $http = new request({
+	//服务器本地上传文件地址
+	fileUrl: base.baseUrl,
+	// 服务器上传图片默认url
+	defaultUploadUrl: "api/common/v1/upload_image",
+});
+```
+```
+// 上传可以不用传递url(使用全局的上传图片url)
+this.$http.urlImgUpload({
+	name:"后台接受文件key名称", //默认 file
+	count:"最大选择数",//默认 9
+	sizeType:"选择压缩图原图,默认两个都选",//默认 ['original', 'compressed']
+	sourceType:"选择相机拍照或相册上传 默认两个都选",//默认 ['album','camera']
+	data:"而外参数" //可不填,
+});
+// 上传可以不用传递url(使用全局的上传图片url)
+this.$http.urlVideoUpload({
+	sourceType:"选择相机拍照或相册上传 默认两个都选",//默认 ['album','camera']
+	compressed:"是否压缩所选的视频源文件,默认值为 true,需要压缩",//默认 false
+	maxDuration: "拍摄视频最长拍摄时间,单位秒。最长支持 60 秒", //默认 60
+	camera: '前置还是后置摄像头', //'front'、'back',默认'back'
+	name:"后台接受文件key名称", //默认 file
+	data:"而外参数" //可不填,
+});
+// 上传可以不用传递url(使用全局的上传图片url)
+this.$http.urlFileUpload({
+	files: [], // 必填 临时文件路径 格式: [{path: "图片地址"}]
+	data:"向服务器传递的参数", //可不填
+	name:"后台接受文件key名称", //默认 file
+});
+```
+
+### 本地服务器图片上传(支持多张上传)
+```
+this.$http.urlImgUpload('flie/upload',{
+	name:"后台接受文件key名称", //默认 file
+	count:"最大选择数",//默认 9
+	sizeType:"选择压缩图原图,默认两个都选",//默认 ['original', 'compressed']
+	sourceType:"选择相机拍照或相册上传 默认两个都选",//默认 ['album','camera']
+	data:"而外参数" //可不填,
+	isPrompt: true,//(默认 true 说明:本接口抛出的错误是否提示)
+	load: true,//(默认 true 说明:本接口是否提示加载动画)
+	header: { //默认 无 说明:请求头
+		'Content-Type': 'application/json'
+	},
+	isFactory: true, //(默认 true 说明:本接口是否调用公共的数据处理方法,设置false后isPrompt参数奖失去作用)
+	maxSize: 300000, //(默认 无 说明:上传的文件最大字节数限制,默认不限制)
+	onSelectComplete: res => {
+		console.log("选择完成返回:",res);
+	},
+	onEachUpdate: res => {
+		console.log("单张上传成功返回:",res);
+	},
+	onProgressUpdate: res => {
+		console.log("上传进度返回:",res);
+	}
+}).then(res => {
+	console.log("全部上传完返回结果:",res);
+});
+```
+### 本地服务器视频上传
+```
+this.$http.urlVideoUpload('flie/upload',{
+	sourceType:"选择相机拍照或相册上传 默认两个都选",//默认 ['album','camera']
+	compressed:"是否压缩所选的视频源文件,默认值为 true,需要压缩",//默认 false
+	maxDuration: "拍摄视频最长拍摄时间,单位秒。最长支持 60 秒", //默认 60
+	camera: '前置还是后置摄像头', //'front'、'back',默认'back'
+	name:"后台接受文件key名称", //默认 file
+	data:"而外参数" //可不填,
+	isPrompt: true,//(默认 true 说明:本接口抛出的错误是否提示)
+	load: true,//(默认 true 说明:本接口是否提示加载动画)
+	header: { //默认 无 说明:请求头
+		'Content-Type': 'application/json'
+	},
+	isFactory: true, //(默认 true 说明:本接口是否调用公共的数据处理方法,设置false后isPrompt参数奖失去作用)
+	maxSize: 300000, //(默认 无 说明:上传的文件最大字节数限制,默认不限制)
+	onProgressUpdate: res => {
+		console.log("上传进度返回:",res);
+	},
+	onSelectComplete: res => {
+		console.log("选择完成返回:",res);
+	},
+}).then(res => {
+	console.log("全部上传完返回结果:",res);
+});
+```
+### 本地服务器文件上传(支持多张上传)
+```
+this.$http.urlFileUpload("flie/upload",{
+	files: [], // 必填 临时文件路径 格式: [{path: "图片地址"}]
+	data:"向服务器传递的参数", //可不填
+	name:"后台接受文件key名称", //默认 file
+	isPrompt: true,//(默认 true 说明:本接口抛出的错误是否提示)
+	load: true,//(默认 true 说明:本接口是否提示加载动画)
+	header: { //默认 无 说明:请求头
+		'Content-Type': 'application/json'
+	},
+	isFactory: true, //(默认 true 说明:本接口是否调用公共的数据处理方法,设置false后isPrompt参数奖失去作用)
+	maxSize: 300000, //(默认 无 说明:上传的文件最大字节数限制,默认不限制)
+	onEachUpdate: res => {
+		console.log("单张上传成功返回:",res);
+	},
+	onProgressUpdate: res => {
+		console.log("上传进度返回:",res);
+	}
+}).then(res => {
+	console.log("全部上传完返回结果:",res);
+});
+```
+
+### 七牛云图片上传(支持多张上传)
+```
+this.$http.qnImgUpload({
+	count:"最大选择数", // 默认 9
+	sizeType:"选择压缩图原图,默认两个都选", // 默认 ['original', 'compressed']
+	sourceType:"选择相机拍照或相册上传 默认两个都选", // 默认 ['album','camera']
+	load: true, //(默认 true 说明:本接口是否提示加载动画)
+	maxSize: 300000, //(默认 无 说明:上传的文件最大字节数限制,默认不限制)
+	onSelectComplete: res => {
+		console.log("选择完成返回:",res);
+	},
+	onEachUpdate: res => {
+		console.log("单张上传成功返回:",res);
+	},
+	onProgressUpdate: res => {
+		console.log("上传进度返回:",res);
+	}
+}).then(res => {
+	console.log("全部上传完返回结果:",res);
+});
+```
+### 七牛云视频上传
+```
+this.$http.qnVideoUpload({
+	sourceType:"选择相机拍照或相册上传 默认两个都选",//默认 ['album','camera']
+	compressed:"是否压缩所选的视频源文件,默认值为 true,需要压缩",//默认 false
+	maxDuration: "拍摄视频最长拍摄时间,单位秒。最长支持 60 秒", //默认 60
+	camera: '前置还是后置摄像头', //'front'、'back',默认'back'
+	load: true,//(默认 true 说明:本接口是否提示加载动画)
+	maxSize: 300000, //(默认 无 说明:上传的文件最大字节数限制,默认不限制)
+	onSelectComplete: res => {
+		console.log("选择完成返回:",res);
+	},
+	onProgressUpdate: res => {
+		console.log("上传进度返回:",res);
+	}
+}).then(res => {
+	console.log("全部上传完返回结果:",res);
+});
+```
+### 七牛云文件上传(支持多张上传)
+```
+this.$http.qnFileUpload(
+{
+	files:[], // 必填 临时文件路径 格式: [{path: "图片地址"}]
+	load: true, //(默认 true 说明:本接口是否提示加载动画)
+	maxSize: 300000, //(默认 无 说明:上传的文件最大字节数限制,默认不限制)
+	onEachUpdate: res => {
+		console.log("单张上传成功返回:",res);
+	},
+	onProgressUpdate: res => {
+		console.log("上传进度返回:",res);
+	}
+}).then(res => {
+	console.log("全部上传完返回结果:",res);
+});
+```
+### jsonp 跨域请求(只支持H5)
+```
+let data = await this.$http.jsonp('http://www.aaa.com/aid/region',{pid:0}, {
+    isFactory: false, //(默认 true 说明:本接口是否调用公共的数据处理方法,设置false后isPrompt参数奖失去作用)
+});
+```

+ 132 - 0
node_modules/zhouWei-request/js_sdk/request/upload/Base64.js

@@ -0,0 +1,132 @@
+const Base64 = {
+
+    // private property
+    _keyStr: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
+
+    // public method for encoding
+    encode: function (input) {
+        var output = "";
+        var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
+        var i = 0;
+
+        input = Base64._utf8_encode(input);
+
+        while (i < input.length) {
+
+            chr1 = input.charCodeAt(i++);
+            chr2 = input.charCodeAt(i++);
+            chr3 = input.charCodeAt(i++);
+
+            enc1 = chr1 >> 2;
+            enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
+            enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
+            enc4 = chr3 & 63;
+
+            if (isNaN(chr2)) {
+                enc3 = enc4 = 64;
+            } else if (isNaN(chr3)) {
+                enc4 = 64;
+            }
+
+            output = output +
+                this._keyStr.charAt(enc1) + this._keyStr.charAt(enc2) +
+                this._keyStr.charAt(enc3) + this._keyStr.charAt(enc4);
+
+        }
+
+        return output;
+    },
+
+    // public method for decoding
+    decode: function (input) {
+        var output = "";
+        var chr1, chr2, chr3;
+        var enc1, enc2, enc3, enc4;
+        var i = 0;
+
+        input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
+
+        while (i < input.length) {
+
+            enc1 = this._keyStr.indexOf(input.charAt(i++));
+            enc2 = this._keyStr.indexOf(input.charAt(i++));
+            enc3 = this._keyStr.indexOf(input.charAt(i++));
+            enc4 = this._keyStr.indexOf(input.charAt(i++));
+
+            chr1 = (enc1 << 2) | (enc2 >> 4);
+            chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
+            chr3 = ((enc3 & 3) << 6) | enc4;
+
+            output = output + String.fromCharCode(chr1);
+
+            if (enc3 != 64) {
+                output = output + String.fromCharCode(chr2);
+            }
+            if (enc4 != 64) {
+                output = output + String.fromCharCode(chr3);
+            }
+
+        }
+
+        output = Base64._utf8_decode(output);
+
+        return output;
+
+    },
+
+    // private method for UTF-8 encoding
+    _utf8_encode: function (string) {
+        string = string.replace(/\r\n/g, "\n");
+        var utftext = "";
+
+        for (var n = 0; n < string.length; n++) {
+
+            var c = string.charCodeAt(n);
+
+            if (c < 128) {
+                utftext += String.fromCharCode(c);
+            } else if ((c > 127) && (c < 2048)) {
+                utftext += String.fromCharCode((c >> 6) | 192);
+                utftext += String.fromCharCode((c & 63) | 128);
+            } else {
+                utftext += String.fromCharCode((c >> 12) | 224);
+                utftext += String.fromCharCode(((c >> 6) & 63) | 128);
+                utftext += String.fromCharCode((c & 63) | 128);
+            }
+
+        }
+
+        return utftext;
+    },
+
+    // private method for UTF-8 decoding
+    _utf8_decode: function (utftext) {
+        var string = "";
+        var i = 0;
+        var c = c1 = c2 = 0;
+
+        while (i < utftext.length) {
+
+            c = utftext.charCodeAt(i);
+
+            if (c < 128) {
+                string += String.fromCharCode(c);
+                i++;
+            } else if ((c > 191) && (c < 224)) {
+                c2 = utftext.charCodeAt(i + 1);
+                string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
+                i += 2;
+            } else {
+                c2 = utftext.charCodeAt(i + 1);
+                c3 = utftext.charCodeAt(i + 2);
+                string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
+                i += 3;
+            }
+
+        }
+
+        return string;
+    }
+}
+
+module.exports = Base64;

+ 40 - 0
node_modules/zhouWei-request/js_sdk/request/upload/aliUploader.js

@@ -0,0 +1,40 @@
+const Base64 = require('./Base64.js');
+require('./hmac.js');
+require('./sha1.js');
+const Crypto = require('./crypto.js');
+// 获取policy
+const getPolicyBase64 = function (timeout) {
+    let dateTime = new Date().getTime();
+	let date = new Date(dateTime + (timeout || 1800000));
+    let srcT = date.toISOString();
+    const policyText = {
+        "expiration": srcT, //设置该Policy的失效时间
+        "conditions": [
+            ["content-length-range", 0, 100 * 1024 * 1024] // 设置上传文件的大小限制,100mb
+        ]
+    };
+    const policyBase64 = Base64.encode(JSON.stringify(policyText));
+    return policyBase64;
+}
+// 获取签名
+const getSignature = function (policyBase64, AccessKeySecret) {
+    const bytes = Crypto.HMAC(Crypto.SHA1, policyBase64, AccessKeySecret, {
+        asBytes: true
+    });
+    const signature = Crypto.util.bytesToBase64(bytes);
+    return signature;
+}
+// 获取阿里云token信息
+const getAliyunOssKey = function (options) {
+	const policyBase64 = getPolicyBase64(options.timeout);
+	const signature = getSignature(policyBase64, options.accessKeySecret);
+	return {
+		policy: policyBase64,
+		accessKeyId: options.accessKeyId,
+		accessKeySecret: options.accessKeySecret,
+		signature: signature,
+		success_action_status: '200'
+	}
+}
+
+module.exports = getAliyunOssKey;

+ 185 - 0
node_modules/zhouWei-request/js_sdk/request/upload/crypto.js

@@ -0,0 +1,185 @@
+/*!
+ * Crypto-JS v1.1.0
+ * http://code.google.com/p/crypto-js/
+ * Copyright (c) 2009, Jeff Mott. All rights reserved.
+ * http://code.google.com/p/crypto-js/wiki/License
+ */
+
+const Crypto = {};
+
+(function(){
+
+var base64map = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+
+// Crypto utilities
+var util = Crypto.util = {
+
+	// Bit-wise rotate left
+	rotl: function (n, b) {
+		return (n << b) | (n >>> (32 - b));
+	},
+
+	// Bit-wise rotate right
+	rotr: function (n, b) {
+		return (n << (32 - b)) | (n >>> b);
+	},
+
+	// Swap big-endian to little-endian and vice versa
+	endian: function (n) {
+
+		// If number given, swap endian
+		if (n.constructor == Number) {
+			return util.rotl(n,  8) & 0x00FF00FF |
+			       util.rotl(n, 24) & 0xFF00FF00;
+		}
+
+		// Else, assume array and swap all items
+		for (var i = 0; i < n.length; i++)
+			n[i] = util.endian(n[i]);
+		return n;
+
+	},
+
+	// Generate an array of any length of random bytes
+	randomBytes: function (n) {
+		for (var bytes = []; n > 0; n--)
+			bytes.push(Math.floor(Math.random() * 256));
+		return bytes;
+	},
+
+	// Convert a string to a byte array
+	stringToBytes: function (str) {
+		var bytes = [];
+		for (var i = 0; i < str.length; i++)
+			bytes.push(str.charCodeAt(i));
+		return bytes;
+	},
+
+	// Convert a byte array to a string
+	bytesToString: function (bytes) {
+		var str = [];
+		for (var i = 0; i < bytes.length; i++)
+			str.push(String.fromCharCode(bytes[i]));
+		return str.join("");
+	},
+
+	// Convert a string to big-endian 32-bit words
+	stringToWords: function (str) {
+		var words = [];
+		for (var c = 0, b = 0; c < str.length; c++, b += 8)
+			words[b >>> 5] |= str.charCodeAt(c) << (24 - b % 32);
+		return words;
+	},
+
+	// Convert a byte array to big-endian 32-bits words
+	bytesToWords: function (bytes) {
+		var words = [];
+		for (var i = 0, b = 0; i < bytes.length; i++, b += 8)
+			words[b >>> 5] |= bytes[i] << (24 - b % 32);
+		return words;
+	},
+
+	// Convert big-endian 32-bit words to a byte array
+	wordsToBytes: function (words) {
+		var bytes = [];
+		for (var b = 0; b < words.length * 32; b += 8)
+			bytes.push((words[b >>> 5] >>> (24 - b % 32)) & 0xFF);
+		return bytes;
+	},
+
+	// Convert a byte array to a hex string
+	bytesToHex: function (bytes) {
+		var hex = [];
+		for (var i = 0; i < bytes.length; i++) {
+			hex.push((bytes[i] >>> 4).toString(16));
+			hex.push((bytes[i] & 0xF).toString(16));
+		}
+		return hex.join("");
+	},
+
+	// Convert a hex string to a byte array
+	hexToBytes: function (hex) {
+		var bytes = [];
+		for (var c = 0; c < hex.length; c += 2)
+			bytes.push(parseInt(hex.substr(c, 2), 16));
+		return bytes;
+	},
+
+	// Convert a byte array to a base-64 string
+	bytesToBase64: function (bytes) {
+
+		// Use browser-native function if it exists
+		// if (typeof btoa == "function") return btoa(util.bytesToString(bytes));
+
+		var base64 = [],
+		    overflow;
+
+		for (var i = 0; i < bytes.length; i++) {
+			switch (i % 3) {
+				case 0:
+					base64.push(base64map.charAt(bytes[i] >>> 2));
+					overflow = (bytes[i] & 0x3) << 4;
+					break;
+				case 1:
+					base64.push(base64map.charAt(overflow | (bytes[i] >>> 4)));
+					overflow = (bytes[i] & 0xF) << 2;
+					break;
+				case 2:
+					base64.push(base64map.charAt(overflow | (bytes[i] >>> 6)));
+					base64.push(base64map.charAt(bytes[i] & 0x3F));
+					overflow = -1;
+			}
+		}
+
+		// Encode overflow bits, if there are any
+		if (overflow != undefined && overflow != -1)
+			base64.push(base64map.charAt(overflow));
+
+		// Add padding
+		while (base64.length % 4 != 0) base64.push("=");
+
+		return base64.join("");
+
+	},
+
+	// Convert a base-64 string to a byte array
+	base64ToBytes: function (base64) {
+
+		// Use browser-native function if it exists
+		if (typeof atob == "function") return util.stringToBytes(atob(base64));
+
+		// Remove non-base-64 characters
+		base64 = base64.replace(/[^A-Z0-9+\/]/ig, "");
+
+		var bytes = [];
+
+		for (var i = 0; i < base64.length; i++) {
+			switch (i % 4) {
+				case 1:
+					bytes.push((base64map.indexOf(base64.charAt(i - 1)) << 2) |
+					           (base64map.indexOf(base64.charAt(i)) >>> 4));
+					break;
+				case 2:
+					bytes.push(((base64map.indexOf(base64.charAt(i - 1)) & 0xF) << 4) |
+					           (base64map.indexOf(base64.charAt(i)) >>> 2));
+					break;
+				case 3:
+					bytes.push(((base64map.indexOf(base64.charAt(i - 1)) & 0x3) << 6) |
+					           (base64map.indexOf(base64.charAt(i))));
+					break;
+			}
+		}
+
+		return bytes;
+
+	}
+
+};
+
+// Crypto mode namespace
+Crypto.mode = {};
+
+})();
+
+module.exports = Crypto;

+ 41 - 0
node_modules/zhouWei-request/js_sdk/request/upload/hmac.js

@@ -0,0 +1,41 @@
+/*!
+ * Crypto-JS v1.1.0
+ * http://code.google.com/p/crypto-js/
+ * Copyright (c) 2009, Jeff Mott. All rights reserved.
+ * http://code.google.com/p/crypto-js/wiki/License
+ */
+
+const Crypto = require('./crypto.js');
+
+(function(){
+
+// Shortcut
+var util = Crypto.util;
+
+Crypto.HMAC = function (hasher, message, key, options) {
+
+	// Allow arbitrary length keys
+	key = key.length > hasher._blocksize * 4 ?
+	      hasher(key, { asBytes: true }) :
+	      util.stringToBytes(key);
+
+	// XOR keys with pad constants
+	var okey = key,
+	    ikey = key.slice(0);
+	for (var i = 0; i < hasher._blocksize * 4; i++) {
+		okey[i] ^= 0x5C;
+		ikey[i] ^= 0x36;
+	}
+
+	var hmacbytes = hasher(util.bytesToString(okey) +
+	                       hasher(util.bytesToString(ikey) + message, { asString: true }),
+	                       { asBytes: true });
+	return options && options.asBytes ? hmacbytes :
+	       options && options.asString ? util.bytesToString(hmacbytes) :
+	       util.bytesToHex(hmacbytes);
+
+};
+
+})();
+
+module.exports = Crypto;

+ 169 - 0
node_modules/zhouWei-request/js_sdk/request/upload/qiniuUploader.js

@@ -0,0 +1,169 @@
+// created by gpake
+(function () {
+
+  var config = {
+    qiniuRegion: '',
+    qiniuImageURLPrefix: '',
+    qiniuUploadToken: '',
+    qiniuUploadTokenURL: '',
+    qiniuUploadTokenFunction: null,
+    qiniuShouldUseQiniuFileName: false
+  }
+
+  module.exports = {
+    init: init,
+    upload: upload,
+  }
+
+  // 在整个程序生命周期中,只需要 init 一次即可
+  // 如果需要变更参数,再调用 init 即可
+  function init(options) {
+    config = {
+      qiniuRegion: '',
+      qiniuImageURLPrefix: '',
+      qiniuUploadToken: '',
+      qiniuUploadTokenURL: '',
+      qiniuUploadTokenFunction: null,
+      qiniuShouldUseQiniuFileName: false
+    };
+    updateConfigWithOptions(options);
+  }
+
+  function updateConfigWithOptions(options) {
+    if (options.region) {
+      config.qiniuRegion = options.region;
+    } else {
+      console.error('qiniu uploader need your bucket region');
+    }
+    if (options.uptoken) {
+      config.qiniuUploadToken = options.uptoken;
+    } else if (options.uptokenURL) {
+      config.qiniuUploadTokenURL = options.uptokenURL;
+    } else if (options.uptokenFunc) {
+      config.qiniuUploadTokenFunction = options.uptokenFunc;
+    }
+    if (options.domain) {
+      config.qiniuImageURLPrefix = options.domain;
+    }
+    config.qiniuShouldUseQiniuFileName = options.shouldUseQiniuFileName
+  }
+
+  function upload(filePath, success, fail, options, progress, cancelTask) {
+    if (null == filePath) {
+      console.error('qiniu uploader need filePath to upload');
+      return;
+    }
+    if (options) {
+      updateConfigWithOptions(options);
+    }
+    if (config.qiniuUploadToken) {
+      doUpload(filePath, success, fail, options, progress, cancelTask);
+    } else if (config.qiniuUploadTokenURL) {
+      getQiniuToken(function () {
+        doUpload(filePath, success, fail, options, progress, cancelTask);
+      });
+    } else if (config.qiniuUploadTokenFunction) {
+      config.qiniuUploadToken = config.qiniuUploadTokenFunction();
+      if (null == config.qiniuUploadToken && config.qiniuUploadToken.length > 0) {
+        console.error('qiniu UploadTokenFunction result is null, please check the return value');
+        return
+      }
+      doUpload(filePath, success, fail, options, progress, cancelTask);
+    } else {
+      console.error('qiniu uploader need one of [uptoken, uptokenURL, uptokenFunc]');
+      return;
+    }
+  }
+
+  function doUpload(filePath, success, fail, options, progress, cancelTask) {
+    if (null == config.qiniuUploadToken && config.qiniuUploadToken.length > 0) {
+      console.error('qiniu UploadToken is null, please check the init config or networking');
+      return
+    }
+    var url = uploadURLFromRegionCode(config.qiniuRegion);
+    var fileName = filePath.split('//')[1];
+    if (options && options.key) {
+      fileName = options.key;
+    }
+    var formData = {
+      'token': config.qiniuUploadToken
+    };
+    if (!config.qiniuShouldUseQiniuFileName) {
+      formData['key'] = fileName
+    }
+    var uploadTask = wx.uploadFile({
+      url: url,
+      filePath: filePath,
+      name: 'file',
+      formData: formData,
+      success: function (res) {
+        var dataString = res.data
+        if (res.data.hasOwnProperty('type') && res.data.type === 'Buffer') {
+          dataString = String.fromCharCode.apply(null, res.data.data)
+        }
+        try {
+          var dataObject = JSON.parse(dataString);
+          //do something
+          var imageUrl = config.qiniuImageURLPrefix + '/' + dataObject.key;
+          dataObject.imageURL = imageUrl;
+          if (success) {
+            success(dataObject);
+          }
+        } catch (e) {
+          console.log('parse JSON failed, origin String is: ' + dataString)
+          if (fail) {
+            fail(e);
+          }
+        }
+      },
+      fail: function (error) {
+        console.error(error);
+        if (fail) {
+          fail(error);
+        }
+      }
+    })
+
+    uploadTask.onProgressUpdate((res) => {
+      progress && progress(res)
+    })
+
+    cancelTask && cancelTask(() => {
+      uploadTask.abort()
+    })
+  }
+
+  function getQiniuToken(callback) {
+    wx.request({
+      url: config.qiniuUploadTokenURL,
+      success: function (res) {
+        var token = res.data.uptoken;
+        if (token && token.length > 0) {
+          config.qiniuUploadToken = token;
+          if (callback) {
+            callback();
+          }
+        } else {
+          console.error('qiniuUploader cannot get your token, please check the uptokenURL or server')
+        }
+      },
+      fail: function (error) {
+        console.error('qiniu UploadToken is null, please check the init config or networking: ' + error);
+      }
+    })
+  }
+
+  function uploadURLFromRegionCode(code) {
+    var uploadURL = null;
+    switch (code) {
+      case 'ECN': uploadURL = 'https://up.qbox.me'; break;
+      case 'NCN': uploadURL = 'https://up-z1.qbox.me'; break;
+      case 'SCN': uploadURL = 'https://up-z2.qbox.me'; break;
+      case 'NA': uploadURL = 'https://up-na0.qbox.me'; break;
+      case 'ASG': uploadURL = 'https://up-as0.qbox.me'; break;
+      default: console.error('please make the region is with one of [ECN, SCN, NCN, NA, ASG]');
+    }
+    return uploadURL;
+  }
+
+})();

+ 86 - 0
node_modules/zhouWei-request/js_sdk/request/upload/sha1.js

@@ -0,0 +1,86 @@
+/*!
+ * Crypto-JS v1.1.0
+ * http://code.google.com/p/crypto-js/
+ * Copyright (c) 2009, Jeff Mott. All rights reserved.
+ * http://code.google.com/p/crypto-js/wiki/License
+ */
+
+const Crypto = require('./crypto.js');
+
+(function(){
+
+// Shortcut
+var util = Crypto.util;
+
+// Public API
+var SHA1 = Crypto.SHA1 = function (message, options) {
+	var digestbytes = util.wordsToBytes(SHA1._sha1(message));
+	return options && options.asBytes ? digestbytes :
+	       options && options.asString ? util.bytesToString(digestbytes) :
+	       util.bytesToHex(digestbytes);
+};
+
+// The core
+SHA1._sha1 = function (message) {
+
+	var m  = util.stringToWords(message),
+	    l  = message.length * 8,
+	    w  =  [],
+	    H0 =  1732584193,
+	    H1 = -271733879,
+	    H2 = -1732584194,
+	    H3 =  271733878,
+	    H4 = -1009589776;
+
+	// Padding
+	m[l >> 5] |= 0x80 << (24 - l % 32);
+	m[((l + 64 >>> 9) << 4) + 15] = l;
+
+	for (var i = 0; i < m.length; i += 16) {
+
+		var a = H0,
+		    b = H1,
+		    c = H2,
+		    d = H3,
+		    e = H4;
+
+		for (var j = 0; j < 80; j++) {
+
+			if (j < 16) w[j] = m[i + j];
+			else {
+				var n = w[j-3] ^ w[j-8] ^ w[j-14] ^ w[j-16];
+				w[j] = (n << 1) | (n >>> 31);
+			}
+
+			var t = ((H0 << 5) | (H0 >>> 27)) + H4 + (w[j] >>> 0) + (
+			         j < 20 ? (H1 & H2 | ~H1 & H3) + 1518500249 :
+			         j < 40 ? (H1 ^ H2 ^ H3) + 1859775393 :
+			         j < 60 ? (H1 & H2 | H1 & H3 | H2 & H3) - 1894007588 :
+			                  (H1 ^ H2 ^ H3) - 899497514);
+
+			H4 =  H3;
+			H3 =  H2;
+			H2 = (H1 << 30) | (H1 >>> 2);
+			H1 =  H0;
+			H0 =  t;
+
+		}
+
+		H0 += a;
+		H1 += b;
+		H2 += c;
+		H3 += d;
+		H4 += e;
+
+	}
+
+	return [H0, H1, H2, H3, H4];
+
+};
+
+// Package private blocksize
+SHA1._blocksize = 16;
+
+})();
+
+module.exports = Crypto;

+ 287 - 0
node_modules/zhouWei-request/js_sdk/request/upload/upload.js

@@ -0,0 +1,287 @@
+import request from "./../core/request.js";
+const {
+	chooseImage,
+	chooseVideo,
+	qiniuUpload,
+	aliUpload,
+	urlUpload
+} = require("./utils");
+import {
+	mergeConfig
+} from "./../core/utils.js";
+export default class fileUpload extends request {
+	constructor(props) {
+		// 调用实现父类的构造函数
+		super(props);
+	}
+	//七牛云上传图片
+	async qnImgUpload(options = {}) {
+		let files;
+		try {
+			files = await chooseImage(options);
+			// 选择完成回调
+			options.onSelectComplete && options.onSelectComplete(files);
+		} catch (err) {
+			this.requestError && this.requestError(err);
+			return Promise.reject(err);
+		}
+		if (files) {
+			return this.qnFileUpload({
+				...options,
+				files: files
+			});
+		}
+	}
+	//七牛云上传视频
+	async qnVideoUpload(options = {}) {
+		let files;
+		try {
+			files = await chooseVideo(options);
+			// 选择完成回调
+			options.onSelectComplete && options.onSelectComplete(files);
+		} catch (err) {
+			this.requestError && this.requestError(err);
+			return Promise.reject(err);
+		}
+		if (files) {
+			return this.qnFileUpload({
+				...options,
+				files: files
+			});
+		}
+	}
+
+	//七牛云文件上传(支持多张上传)
+	async qnFileUpload(options = {}) {
+		let requestInfo;
+		try {
+			// 数据合并
+			requestInfo = {
+				...this.config,
+				...options,
+				header: {},
+				method: "FILE"
+			};
+			//请求前回调
+			if (this.requestStart) {
+				let requestStart = this.requestStart(requestInfo);
+				if (typeof requestStart == "object") {
+					let changekeys = ["load", "files"];
+					changekeys.forEach(key => {
+						requestInfo[key] = requestStart[key];
+					});
+				} else {
+					throw {
+						errMsg: "【request】请求开始拦截器未通过",
+						statusCode: 0,
+						data: requestInfo.data,
+						method: requestInfo.method,
+						header: requestInfo.header,
+						url: requestInfo.url,
+					}
+				}
+			}
+			let requestResult = await qiniuUpload(requestInfo, this.getQnToken);
+			return Promise.resolve(requestResult);
+		} catch (err) {
+			this.requestError && this.requestError(err);
+			return Promise.reject(err);
+		} finally {
+			this.requestEnd && this.requestEnd(requestInfo);
+		}
+	}
+	//阿里云上传图片
+	async aliImgUpload(options = {}) {
+		let files;
+		try {
+			files = await chooseImage(options);
+			// 选择完成回调
+			options.onSelectComplete && options.onSelectComplete(files);
+		} catch (err) {
+			this.requestError && this.requestError(err);
+			return Promise.reject(err);
+		}
+		if (files) {
+			return this.aliFileUpload({
+				...options,
+				files: files
+			});
+		}
+	}
+	//阿里云上传视频
+	async aliVideoUpload(options = {}) {
+		let files;
+		try {
+			files = await chooseVideo(options);
+			// 选择完成回调
+			options.onSelectComplete && options.onSelectComplete(files);
+		} catch (err) {
+			this.requestError && this.requestError(err);
+			return Promise.reject(err);
+		}
+		if (files) {
+			return this.aliFileUpload({
+				...options,
+				files: files
+			});
+		}
+	}
+	//阿里云文件上传(支持多张上传)
+	async aliFileUpload(options = {}) {
+		let requestInfo;
+		try {
+			// 数据合并
+			requestInfo = {
+				...this.config,
+				...options,
+				header: {},
+				method: "FILE"
+			};
+			//请求前回调
+			if (this.requestStart) {
+				let requestStart = this.requestStart(requestInfo);
+				if (typeof requestStart == "object") {
+					let changekeys = ["load", "files"];
+					changekeys.forEach(key => {
+						requestInfo[key] = requestStart[key];
+					});
+				} else {
+					throw {
+						errMsg: "【request】请求开始拦截器未通过",
+						statusCode: 0,
+						data: requestInfo.data,
+						method: requestInfo.method,
+						header: requestInfo.header,
+						url: requestInfo.url,
+					}
+				}
+			}
+			let requestResult = await aliUpload(requestInfo, this.getAliToken);
+			return Promise.resolve(requestResult);
+		} catch (err) {
+			this.requestError && this.requestError(err);
+			return Promise.reject(err);
+		} finally {
+			this.requestEnd && this.requestEnd(requestInfo);
+		}
+	}
+	//本地服务器图片上传
+	async urlImgUpload() {
+		let options = {};
+		if (arguments[0]) {
+			if (typeof(arguments[0]) == "string") {
+				options.url = arguments[0];
+			} else if (typeof(arguments[0]) == "object") {
+				options = Object.assign(options, arguments[0]);
+			}
+		}
+		if (arguments[1] && typeof(arguments[1]) == "object") {
+			options = Object.assign(options, arguments[1]);
+		}
+		try {
+			options.files = await chooseImage(options);
+			// 选择完成回调
+			options.onSelectComplete && options.onSelectComplete(options.files);
+		} catch (err) {
+			this.requestError && this.requestError(err);
+			return Promise.reject(err);
+		}
+		if (options.files) {
+			return this.urlFileUpload(options);
+		}
+	}
+	//本地服务器上传视频
+	async urlVideoUpload() {
+		let options = {};
+		if (arguments[0]) {
+			if (typeof(arguments[0]) == "string") {
+				options.url = arguments[0];
+			} else if (typeof(arguments[0]) == "object") {
+				options = Object.assign(options, arguments[0]);
+			}
+		}
+		if (arguments[1] && typeof(arguments[1]) == "object") {
+			options = Object.assign(options, arguments[1]);
+		}
+		try {
+			options.files = await chooseVideo(options);
+			// 选择完成回调
+			options.onSelectComplete && options.onSelectComplete(options.files);
+		} catch (err) {
+			this.requestError && this.requestError(err);
+			return Promise.reject(err);
+		}
+		if (options.files) {
+			return this.urlFileUpload(options);
+		}
+	}
+	//本地服务器文件上传方法
+	async urlFileUpload() {
+		let requestInfo = {
+			method: "FILE"
+		};
+		if (arguments[0]) {
+			if (typeof(arguments[0]) == "string") {
+				requestInfo.url = arguments[0];
+			} else if (typeof(arguments[0]) == "object") {
+				requestInfo = Object.assign(requestInfo, arguments[0]);
+			}
+		}
+		if (arguments[1] && typeof(arguments[1]) == "object") {
+			requestInfo = Object.assign(requestInfo, arguments[1]);
+		}
+		if (!requestInfo.url && this.defaultUploadUrl) {
+			requestInfo.url = this.defaultUploadUrl;
+		}
+		if (!requestInfo.name && this.defaultFileName) {
+			requestInfo.name = this.defaultFileName;
+		}
+		// 请求数据
+		// 是否运行过请求开始钩子
+		let runRequestStart = false;
+		try {
+			if (!requestInfo.url) {
+				throw {
+					errMsg: "【request】文件上传缺失数据url",
+					statusCode: 0,
+					data: requestInfo.data,
+					method: requestInfo.method,
+					header: requestInfo.header,
+					url: requestInfo.url,
+				}
+			}
+			// 数据合并
+			requestInfo = mergeConfig(this, requestInfo);
+			// 代表之前运行到这里
+			runRequestStart = true;
+			//请求前回调
+			if (this.requestStart) {
+				let requestStart = this.requestStart(requestInfo);
+				if (typeof requestStart == "object") {
+					let changekeys = ["data", "header", "isPrompt", "load", "isFactory", "files"];
+					changekeys.forEach(key => {
+						requestInfo[key] = requestStart[key];
+					});
+				} else {
+					throw {
+						errMsg: "【request】请求开始拦截器未通过",
+						statusCode: 0,
+						data: requestInfo.data,
+						method: requestInfo.method,
+						header: requestInfo.header,
+						url: requestInfo.url,
+					}
+				}
+			}
+			let requestResult = await urlUpload(requestInfo, this.dataFactory);
+			return Promise.resolve(requestResult);
+		} catch (err) {
+			this.requestError && this.requestError(err);
+			return Promise.reject(err);
+		} finally {
+			if (runRequestStart) {
+				this.requestEnd && this.requestEnd(requestInfo);
+			}
+		}
+	}
+}

+ 396 - 0
node_modules/zhouWei-request/js_sdk/request/upload/utils.js

@@ -0,0 +1,396 @@
+const qiniuUploader = require("./qiniuUploader");
+const aliUploader =  require('./aliUploader');  
+//七牛云上传文件命名
+export const randomChar = function(l, url = "") {
+	const x = "0123456789qwertyuioplkjhgfdsazxcvbnm";
+	let tmp = "";
+	let time = new Date();
+	for (let i = 0; i < l; i++) {
+		tmp += x.charAt(Math.ceil(Math.random() * 100000000) % x.length);
+	}
+	return (
+		"file/" +
+		url +
+		time.getTime() +
+		tmp
+	);
+}
+//图片选择
+export const chooseImage = function(data) {
+	return new Promise((resolve, reject) => {
+		uni.chooseImage({
+			count: data.count || 9, //默认9
+			sizeType: data.sizeType || ['original', 'compressed'], //可以指定是原图还是压缩图,默认二者都有
+			sourceType: data.sourceType || ['album', 'camera'], //从相册选择
+			success: function(res) {
+				for (var i = 0; i < res.tempFiles.length; i++) {
+					res.tempFiles[i].fileType = "image"
+				}
+				resolve(res.tempFiles);
+			},
+			fail: err => {
+				reject({
+					errMsg: err.errMsg, 
+					errCode: err.errCode, 
+					statusCode: 0,
+				});
+			}
+		});
+	});
+}
+//视频选择
+export const chooseVideo = function(data) {
+	return new Promise((resolve, reject) => {
+		uni.chooseVideo({
+			sourceType: data.sourceType || ['album', 'camera'], //从相册选择
+			compressed: data.compressed || false, //是否压缩所选的视频源文件,默认值为 true,需要压缩。
+			maxDuration: data.maxDuration || 60, //拍摄视频最长拍摄时间,单位秒。最长支持 60 秒。
+			camera: data.camera || 'back', //'front'、'back',默认'back'
+			success: function(res) {
+				let files = [{
+					path: res.tempFilePath,
+					fileType: "video"
+				}];
+				// #ifdef APP-PLUS || H5 || MP-WEIXIN
+				files[0].duration = res.duration;
+				files[0].size = res.size;
+				files[0].height = res.height;
+				files[0].width = res.width;
+				// #endif
+				// #ifdef H5
+				files[0].name = res.name;
+				// #endif
+				resolve(files);
+			},
+			fail: err => {
+				reject({
+					errMsg: err.errMsg, 
+					errCode: err.errCode, 
+					statusCode: 0,
+				});
+			}
+		});
+	});
+}
+// 七牛云上传
+export const qiniuUpload = function(requestInfo, getQnToken) {
+	return new Promise((resolve, reject) => {
+		if (Array.isArray(requestInfo.files)) {
+			let len = requestInfo.files.length;
+			let fileList = new Array;
+			if (getQnToken) {
+				getQnToken(qnRes => {
+					/*
+					 *接口返回参数:
+					 *visitPrefix:访问文件的域名
+					 *token:七牛云上传token
+					 *folderPath:上传的文件夹
+					 *region: 地区 默认为:SCN
+					 */
+                    let prefixLen = qnRes.visitPrefix.length;
+                    if(qnRes.visitPrefix.charAt(prefixLen - 1) == '/'){
+                        qnRes.visitPrefix = qnRes.visitPrefix.substring(0, prefixLen - 1)
+                    }
+					uploadFile(0);
+
+					function uploadFile(i) {
+						let item = requestInfo.files[i];
+						let updateUrl = randomChar(10, qnRes.folderPath);
+						let fileData = {
+							fileIndex: i,
+							files: requestInfo.files,
+							...item
+						};
+						if (item.name) {
+							fileData.name = item.name;
+							let nameArr = item.name.split(".");
+							updateUrl += "." + nameArr[nameArr.length - 1];
+						}
+						// 交给七牛上传
+						qiniuUploader.upload(item.path || item, (res) => {
+							fileData.url = res.imageURL;
+							requestInfo.onEachUpdate && requestInfo.onEachUpdate({
+								url: res.imageURL,
+								...fileData
+							});
+							fileList.push(res.imageURL);
+							if (len - 1 > i) {
+								uploadFile(i + 1);
+							} else {
+								resolve(fileList);
+							}
+						}, (error) => {
+							reject(error);
+						}, {
+							region: qnRes.region || 'SCN', //地区
+							domain: qnRes.visitPrefix, // bucket 域名,下载资源时用到。
+							key: updateUrl,
+							uptoken: qnRes.token, // 由其他程序生成七牛 uptoken
+							uptokenURL: 'UpTokenURL.com/uptoken' // 上传地址
+						}, (res) => {
+							console.log(requestInfo);
+							requestInfo.onProgressUpdate && requestInfo.onProgressUpdate(Object.assign({}, fileData, res));
+							// console.log('上传进度', res.progress)
+							// console.log('已经上传的数据长度', res.totalBytesSent)
+							// console.log('预期需要上传的数据总长度', res.totalBytesExpectedToSend)
+						});
+					}
+				});
+			} else {
+				reject({
+					errMsg: "请添加七牛云回调方法:getQnToken",
+					statusCode: 0
+				});
+			}
+		} else {
+			reject({
+				errMsg: "files 必须是数组类型",
+				statusCode: 0
+			});
+		};
+	});
+}
+// 阿里云oss上传
+export const aliUpload = function(requestInfo, getAliToken) {
+	return new Promise((resolve, reject) => {
+		if (Array.isArray(requestInfo.files)) {
+			let len = requestInfo.files.length;
+			let fileList = new Array;
+			if (getAliToken) {
+				getAliToken(aliRes => {
+					/*
+					 *接口返回参数:
+					 *visitPrefix:访问文件的域名
+					 *folderPath:上传的文件夹
+					 *accessKeyId: 您的oss的访问ID
+					 *accessKeySecret: 您的oss的访问密钥
+					 * timeout: 签名过期时间(毫秒)
+					 */
+					let aliyunOssKey = aliUploader({
+						accessKeyId: aliRes.accessKeyId,
+						accessKeySecret: aliRes.accessKeySecret,
+						timeout: aliRes.timeout
+					});
+                    let prefixLen = aliRes.visitPrefix.length;
+                    if(aliRes.visitPrefix.charAt(prefixLen - 1) == '/'){
+                        aliRes.visitPrefix = aliRes.visitPrefix.substring(0, prefixLen - 1)
+                    }
+					uploadFile(0);
+
+					function uploadFile(i) {
+						let item = requestInfo.files[i];
+						let updateUrl = randomChar(10, aliRes.folderPath);
+						let fileData = {
+							fileIndex: i,
+							files: requestInfo.files,
+							...item
+						};
+						if (item.name) {
+							fileData.name = item.name;
+							let nameArr = item.name.split(".");
+							updateUrl += "." + nameArr[nameArr.length - 1];
+						}
+						if (item.path) {
+							let nameArr = item.path.split(".");
+							updateUrl += "." + nameArr[nameArr.length - 1];
+						}
+						console.log("----------111", {
+						  url: aliRes.visitPrefix, // 开发者服务器的URL。
+						  filePath: item.path,
+						  name: 'file', // 必须填file。
+						  formData: {
+						    key: updateUrl,
+						    policy: aliyunOssKey.policy,
+						    OSSAccessKeyId: aliyunOssKey.accessKeyId,
+						    signature: aliyunOssKey.signature,
+						  }});
+						uni.uploadFile({
+						  url: aliRes.visitPrefix, // 开发者服务器的URL。
+						  filePath: item.path,
+						  name: 'file', // 必须填file。
+						  formData: {
+						    key: updateUrl,
+						    policy: aliyunOssKey.policy,
+						    OSSAccessKeyId: aliyunOssKey.accessKeyId,
+						    signature: aliyunOssKey.signature,
+						  },
+						  success: (res) => {
+						    if (res.statusCode === 204) {
+								fileData.url = aliRes.visitPrefix + "/" + updateUrl;
+								requestInfo.onEachUpdate && requestInfo.onEachUpdate({
+									url: fileData.url,
+									...fileData
+								});
+								fileList.push(fileData.url);
+								if (len - 1 > i) {
+									uploadFile(i + 1);
+								} else {
+									resolve(fileList);
+								}
+						    } else {
+								console.log("----失败", res);
+								reject(res);
+							}
+						  },
+						  fail: err => {
+							  console.log("----失败", err);
+						    reject(err);
+						  }
+						});
+					}
+				});
+			} else {
+				reject({
+					errMsg: "请添加阿里云回调方法:getAliToken",
+					statusCode: 0
+				});
+			}
+		} else {
+			reject({
+				errMsg: "files 必须是数组类型",
+				statusCode: 0
+			});
+		};
+	});
+}
+// 服务器URL上传
+export const urlUpload = function(requestInfo, dataFactory) {
+	return new Promise((resolve, reject) => {
+		// 本地文件上传去掉默认Content-Type
+		if (requestInfo.header['Content-Type']) {
+			delete requestInfo.header['Content-Type'];
+		}
+		// 本地文件上传去掉默认Content-Type
+		if (requestInfo.header['content-type']) {
+			delete requestInfo.header['content-type'];
+		}
+		if (Array.isArray(requestInfo.files)) {
+			// #ifdef APP-PLUS || H5
+			let files = [];
+			let fileData = {
+				files: requestInfo.files,
+				name: requestInfo.name || "file"
+			};
+			requestInfo.files.forEach(item => {
+                let fileInfo = {
+                    name: requestInfo.name || "file",
+                };
+                if(item.path){
+                    fileInfo.uri = item.path;
+                } else {
+                    fileInfo.file = item;
+                }
+				files.push(fileInfo);
+			});
+			let config = {
+				url: requestInfo.url,
+				files: files,
+				header: requestInfo.header, //加入请求头
+				success: (response) => {
+					//是否用外部的数据处理方法
+					if (requestInfo.isFactory && dataFactory) {
+						//数据处理
+						dataFactory({
+							...requestInfo,
+							response: response,
+						}).then(data => {
+							requestInfo.onEachUpdate && requestInfo.onEachUpdate({
+								data: data,
+								...fileData
+							});
+							resolve(data);
+						},err => {
+							reject(err);
+						});
+					} else {
+						requestInfo.onEachUpdate && requestInfo.onEachUpdate({
+							data: response,
+							...fileData
+						});
+						resolve(response);
+					}
+				},
+				fail: (err) => {
+					reject(err);
+				}
+			};
+			if (requestInfo.data) {
+				config.formData = requestInfo.data;
+			}
+			const uploadTask = uni.uploadFile(config);
+			uploadTask.onProgressUpdate(res => {
+				requestInfo.onProgressUpdate && requestInfo.onProgressUpdate(Object.assign({}, fileData, res));
+			});
+			// #endif
+			// #ifdef MP
+			const len = requestInfo.files.length - 1;
+			let fileList = new Array;
+			fileUpload(0);
+
+			function fileUpload(i) {
+				let item = requestInfo.files[i];
+				let fileData = {
+					fileIndex: i,
+					files: requestInfo.files,
+					...item
+				};
+				let config = {
+					url: requestInfo.url,
+					filePath: item.path,
+					header: requestInfo.header, //加入请求头
+					name: requestInfo.name || "file",
+					success: (response) => {
+						//是否用外部的数据处理方法
+						if (requestInfo.isFactory && dataFactory) {
+							//数据处理
+							dataFactory({
+								...requestInfo,
+								response: response,
+							}).then(data => {
+								fileList.push(data);
+								requestInfo.onEachUpdate && requestInfo.onEachUpdate({
+									data: data,
+									...fileData
+								});
+								if (len <= i) {
+									resolve(fileList);
+								} else {
+									fileUpload(i + 1);
+								}
+							},err => {
+								reject(err);
+							});
+						} else {
+							requestInfo.onEachUpdate && requestInfo.onEachUpdate({
+								data: response,
+								...fileData
+							});
+							fileList.push(response);
+							if (len <= i) {
+								resolve(fileList);
+							} else {
+								fileUpload(i + 1);
+							}
+						}
+					},
+					fail: (err) => {
+						reject(err);
+					}
+				};
+				if (requestInfo.data) {
+					config.formData = requestInfo.data;
+				}
+				const uploadTask = uni.uploadFile(config);
+				uploadTask.onProgressUpdate(res => {
+					requestInfo.onProgressUpdate && requestInfo.onProgressUpdate(Object.assign({}, fileData, res));
+				});
+			}
+			// #endif
+		} else {
+			reject({
+				errMsg: "files 必须是数组类型",
+				statusCode: 0
+			});
+		}
+	});
+}

+ 214 - 0
node_modules/zhouWei-request/js_sdk/requestConfig.js

@@ -0,0 +1,214 @@
+import request from "./request";
+// 全局配置的请求域名
+let baseUrl = "http://www.xxx.com/api/";
+//可以new多个request来支持多个域名请求
+let $http = new request({
+	//接口请求地址
+	baseUrl: baseUrl,
+	//服务器本地上传文件地址
+	fileUrl: baseUrl,
+	// 服务器上传图片默认url
+	defaultUploadUrl: "api/common/v1/upload_image",
+	//设置请求头(如果使用报错跨域问题,可能是content-type请求类型和后台那边设置的不一致)
+	header: {
+		'content-type': 'application/json;charset=UTF-8'
+	},
+	// 请求超时时间(默认6000)
+	timeout: 6000,
+	// 默认配置(可不写)
+	config: {
+		// 是否自动提示错误
+		isPrompt: true,
+		// 是否显示加载动画
+		load: true,
+		// 是否使用数据工厂
+		isFactory: true
+	}
+});
+
+// 添加获取七牛云token的方法
+$http.getQnToken = function(callback){
+	//该地址需要开发者自行配置(每个后台的接口风格都不一样)
+	$http.get("api/kemean/aid/qn_upload").then(data => {
+		/*
+		 *接口返回参数:
+		 *visitPrefix:访问文件的域名
+		 *token:七牛云上传token
+		 *folderPath:上传的文件夹
+		 *region: 地区 默认为:SCN
+		 */
+		callback({
+			visitPrefix: data.visitPrefix,
+			token: data.token,
+			folderPath: data.folderPath,
+			region: "SCN"
+		});
+	});
+}
+// 添加获取阿里云token的方法
+$http.getAliToken = function(callback){
+	//该地址需要开发者自行配置(每个后台的接口风格都不一样)
+	$http.get("api/open/v1/ali_oss_upload").then(data => {
+		/*
+		 *接口返回参数:
+		 *visitPrefix: 访问文件的域名
+		 *folderPath: 上传的文件夹
+		 *region: 地区 
+		 *bucket: 阿里云的 bucket
+		 *accessKeyId: 阿里云的访问ID
+		 *accessKeySecret: 阿里云的访问密钥
+		 *stsToken: 阿里云的访问token
+		 */
+		callback({
+			accessKeyId: data.accessKeyId,
+			accessKeySecret: data.accessKeySecret,
+			bucket: data.bucket,
+			region: data.region,
+			visitPrefix: data.visitPrefix,
+			token: data.token,
+			folderPath: data.folderPath,
+			stsToken: data.securityToken,
+		});
+	});
+}
+//当前接口请求数
+let requestNum = 0;
+//请求开始拦截器
+$http.requestStart = function(options) {
+	if (options.load) {
+		if (requestNum <= 0) {
+			//打开加载动画
+			uni.showLoading({
+				title: '加载中',
+				mask: true
+			});
+		}
+		requestNum += 1;
+	}
+	// 图片、视频上传大小限制
+	if (options.method == "FILE") {
+		// 文件最大字节: options.maxSize 可以在调用方法的时候加入参数
+		let maxSize = options.maxSize || '';
+		for (let item of options.files) {
+			if(item.fileType == 'image'){
+				if (maxSize && item.size > maxSize) {
+					setTimeout(() => {
+						uni.showToast({
+							title: "图片过大,请重新上传",
+							icon: "none"
+						});
+					}, 500);
+					return false;
+				}
+			} else if(item.fileType == "video"){
+				if (item.duration < 3) {
+					setTimeout(() => {
+						uni.showToast({
+							title: "视频长度不足3秒,请重新上传",
+							icon: "none"
+						});
+					}, 500);
+					return false;
+				}
+			}
+		}
+	}
+	//请求前加入token
+	options.header['token'] = "你的项目登录token";
+	return options; // return false 表示请求拦截,不会继续请求
+}
+//请求结束
+$http.requestEnd = function(options) {
+	//判断当前接口是否需要加载动画
+	if (options.load) {
+		requestNum = requestNum - 1;
+		if (requestNum <= 0) {
+			uni.hideLoading();
+		}
+	}
+}
+//登录弹窗次数
+let loginPopupNum = 0;
+//所有接口数据处理(可在接口里设置不调用此方法)
+//此方法需要开发者根据各自的接口返回类型修改,以下只是模板
+$http.dataFactory = async function(res) {
+	console.log("接口请求数据", {
+		url: res.url,
+		resolve: res.response,
+		header: res.header,
+		data: res.data,
+		method: res.method,
+	});
+	if (res.response.statusCode && res.response.statusCode == 200) {
+		let httpData = res.response.data;
+		if (typeof (httpData) == "string") {
+			httpData = JSON.parse(httpData);
+		}
+		/*********以下只是模板(及共参考),需要开发者根据各自的接口返回类型修改*********/
+
+		//判断数据是否请求成功
+		if (httpData.success || httpData.code == 200) {
+			// 返回正确的结果(then接受数据)
+			return Promise.resolve(httpData.data);
+		} else if (httpData.code == "1000" || httpData.code == "1001" || httpData.code == 1100) {
+			let content = '此时此刻需要您登录喔~';
+			if (loginPopupNum <= 0) {
+				loginPopupNum++;
+				uni.showModal({
+					title: '温馨提示',
+					content: content,
+					confirmText: "去登录",
+					cancelText: "再逛会",
+					success: function (res) {
+						loginPopupNum--;
+						if (res.confirm) {
+							uni.navigateTo({
+								url: "/pages/user/login"
+							});
+						}
+					}
+				});
+			}
+			// 返回错误的结果(catch接受数据)
+			return Promise.reject({
+				statusCode: 0,
+				errMsg: "【request】" + (httpData.info || httpData.msg)
+			});
+		} else { //其他错误提示
+			if (res.isPrompt) {
+				uni.showToast({
+					title: httpData.info || httpData.msg,
+					icon: "none",
+					duration: 3000
+				});
+			}
+			// 返回错误的结果(catch接受数据)
+			return Promise.reject({
+				statusCode: 0,
+				errMsg: "【request】" + (httpData.info || httpData.msg)
+			});
+		}
+
+		/*********以上只是模板(及共参考),需要开发者根据各自的接口返回类型修改*********/
+
+	} else {
+		// 返回错误的结果(catch接受数据)
+		return Promise.reject({
+			statusCode: res.response.statusCode,
+			errMsg: "【request】数据工厂验证不通过"
+		});
+	}
+};
+// 错误回调
+$http.requestError = function (e) {
+	// e.statusCode === 0 是参数效验错误抛出的
+	if (e.statusCode === 0) {
+		throw e;
+	} else {
+		uni.showToast({
+			title: "网络错误,请检查一下网络",
+			icon: "none"
+		});
+	}
+}
+export default $http;

+ 80 - 0
node_modules/zhouWei-request/package.json

@@ -0,0 +1,80 @@
+{
+  "id": "zhouWei-request",
+  "displayName": "request请求、配置简单、批量上传图片、视频、超强适应性(支持多域名请求)",
+  "version": "3.3.2",
+  "description": "适用于一项目多域名请求、七牛云图片上传、阿里云图片上传、本地服务器图片上传、支持 Promise",
+  "keywords": [
+    "request",
+    "请求",
+    "http",
+    "ajax",
+    "上传"
+],
+  "repository": "https://github.com/zhouwei1994/uni-app-demo",
+  "engines": {
+    "HBuilderX": "^3.1.0"
+  },
+  "dcloudext": {
+    "category": [
+        "JS SDK",
+        "通用 SDK"
+    ],
+    "sale": {
+      "regular": {
+        "price": "0.00"
+      },
+      "sourcecode": {
+        "price": "0.00"
+      }
+    },
+    "contact": {
+      "qq": "465081029"
+    },
+    "declaration": {
+      "ads": "无",
+      "data": "无",
+      "permissions": "无"
+    },
+    "npmurl": ""
+  },
+  "uni_modules": {
+    "dependencies": [],
+    "encrypt": [],
+    "platforms": {
+      "cloud": {
+        "tcb": "y",
+        "aliyun": "y"
+      },
+      "client": {
+        "App": {
+          "app-vue": "y",
+          "app-nvue": "y"
+        },
+        "H5-mobile": {
+          "Safari": "y",
+          "Android Browser": "y",
+          "微信浏览器(Android)": "y",
+          "QQ浏览器(Android)": "y"
+        },
+        "H5-pc": {
+          "Chrome": "y",
+          "IE": "y",
+          "Edge": "y",
+          "Firefox": "y",
+          "Safari": "y"
+        },
+        "小程序": {
+          "微信": "y",
+          "阿里": "y",
+          "百度": "y",
+          "字节跳动": "y",
+          "QQ": "y"
+        },
+        "快应用": {
+          "华为": "y",
+          "联盟": "y"
+        }
+      }
+    }
+  }
+}

+ 508 - 0
node_modules/zhouWei-request/readme.md

@@ -0,0 +1,508 @@
+# request请求、配置简单、批量上传图片、视频、超强适应性(支持多域名请求)
+1. 配置简单、源码清晰注释多、适用于一项目多域名请求、第三方请求、七牛云图片上传、本地服务器图片上传等等
+2. 支持请求`get`、`post`、`put`、`delete`
+3. 自动显示请求加载动画(可单个接口关闭)
+4. 全局`api`数据处理函数,只回调请求正确的数据(可单个接口关闭)
+5. 未登录或登录失效自动拦截并调用登录方法(可单个接口关闭)
+6. 全局自动提示接口抛出的错误信息(可单个接口关闭)
+7. 支持 Promise
+8. 支持拦截器
+9. 支持七牛云文件(图片、视频)批量上传
+10. 支持本地服务器文件(图片、视频)批量上传
+11. 支持上传文件拦截过滤
+12. 支持上传文件进度监听
+13. 支持上传文件单张成功回调
+
+| `QQ交流群(607391225)`         | `微信交流群(加我好友备注"进群")`                  |
+| ----------------------------|--------------------------- |
+|![QQ交流群](http://qn.kemean.cn//upload/202004/14/15868301778472k7oubi6.png)|![微信交流群](https://qn.kemean.cn/upload/202010/13/weiXin_group_code.jpg)|
+| QQ群号:607391225 |微信号:zhou0612wei|
+
+### [点击跳转-插件示例](https://ext.dcloud.net.cn/plugin?id=2009)
+### [点击跳转-5年的web前端开源的uni-app快速开发模板-下载看文档](https://ext.dcloud.net.cn/plugin?id=2009)
+
+### 常见问题
+1.接口请求成功了,没有返回数据或者数据是走的catch回调
+
+答:`requestConfig.js` 请求配置文件里面,有一个`$http.dataFactory`方法,里面写的只是参考示例,`此方法需要开发者根据各自的接口返回类型修改`
+
+2.官方的方法有数据,本插件方法请求报错跨域问题
+
+答:`requestConfig.js` 请求配置文件里面,`header`请求头设置的`content-type`请求类型需求和后台保持一致
+
+3.登录后用户`token`怎么设置?
+
+答:`requestConfig.js` 请求配置文件里面,`$http.requestStart`请求开始拦截器里面设置
+
+4.怎么判断上传的文件(图片)太大?怎么过滤掉太大的文件(图片)?
+
+答:`requestConfig.js` 请求配置文件里面,`$http.requestStart`请求开始拦截器里面设置
+
+5.接口请求成功了,一直提示“网络错误,请检查一下网络”?
+
+答:`requestConfig.js` 请求配置文件里面,有一个`$http.dataFactory`方法,里面写的只是参考示例,`此方法需要开发者根据各自的接口返回类型修改`
+
+### 本次更新注意事项
+1. 所有的headers都改成了header(和官方统一)
+2. 七牛云的获取token等信息提取到了`requestConfig.js`文件,参考如下
+
+### 文件说明
+1. `request => core` 请求方法的目录
+2. `request => core => request.js` 请求方法的class文件
+3. `request => core => utils.js` 请求方法的源码文件
+4. `request => upload` 上传方法的目录
+5. `request => upload => upload.js` 上传方法的class文件
+6. `request => upload => utils.js` 上传方法源码文件
+7. `request => upload => qiniuUploader.js` 七牛云官方上传文件
+8. `request => index.js` 输出方法的文件
+9. `requestConfig.js` 请求配置文件(具体看代码)
+
+### 在main.js引入并挂在Vue上
+```
+import $http from '@/uni_modules/zhouWei-request/js_sdk/requestConfig';
+Vue.prototype.$http = $http;
+```
+
+### `requestConfig.js`配置说明(requestConfig.js有配置示例)
+```
+import request from "@/uni_modules/zhouWei-request/js_sdk/request";
+//可以new多个request来支持多个域名请求
+let $http = new request({
+	//接口请求地址
+	baseUrl: "https://twin-ui.com/", //示例域名,请自行设计
+	//服务器本地上传文件地址
+	fileUrl: "https://twin-ui.com/", //示例域名,请自行设计
+	// 服务器上传图片默认url
+	defaultUploadUrl: "api/common/v1/upload_image",
+	//设置请求头(如果使用报错跨域问题,可能是content-type请求类型和后台那边设置的不一致)
+	header: {
+		'Content-Type': 'application/json;charset=UTF-8'
+	},
+    // 请求超时时间(默认6000)
+    timeout: 6000,
+    // 默认配置(可不写)
+    config: {
+        // 是否自动提示错误
+        isPrompt: true,
+        // 是否显示加载动画
+        load: true,
+        // 是否使用数据工厂
+        isFactory: true,
+       // ... 可写更多配置
+    }
+});
+
+// 添加获取七牛云token的方法
+$http.getQnToken = function(callback){
+	//该地址需要开发者自行配置(每个后台的接口风格都不一样)
+	$http.get("api/common/v1/qn_upload").then(data => {
+		/*
+		 *接口返回参数:
+		 *visitPrefix:访问文件的域名
+		 *token:七牛云上传token
+		 *folderPath:上传的文件夹
+		 *region: 地区 默认为:SCN
+		 */
+		callback({
+			visitPrefix: data.visitPrefix,
+			token: data.token,
+			folderPath: data.folderPath
+		});
+	});
+}
+//当前接口请求数
+let requestNum = 0;
+//请求开始拦截器
+$http.requestStart = function(options) {
+    if (options.load) {
+    	if (requestNum <= 0) {
+            //打开加载动画
+            uni.showLoading({
+                title: '加载中',
+                mask: true
+            });
+        }
+        requestNum += 1;
+    }
+    // 图片上传大小限制
+    if (options.method == "FILE" && options.maxSize) {
+    	// 文件最大字节: options.maxSize 可以在调用方法的时候加入参数
+    	let maxSize = options.maxSize;
+    	for (let item of options.files) {
+    		if (item.size > maxSize) {
+    			setTimeout(() => {
+    				uni.showToast({
+    					title: "图片过大,请重新上传",
+    					icon: "none"
+    				});
+    			}, 500);
+    			return false;
+    		}
+    	}
+    }
+    //请求前加入token
+    options.header['token'] = "你的项目token";
+    return options; // return false 表示请求拦截,不会继续请求
+}
+//请求结束
+$http.requestEnd = function(options) {
+	//判断当前接口是否需要加载动画
+	if (options.load) {
+		requestNum = requestNum - 1;
+		if (requestNum <= 0) {
+			uni.hideLoading();
+		}
+	}
+}
+//所有接口数据处理(可在接口里设置不调用此方法)
+//此方法需要开发者根据各自的接口返回类型修改,以下只是模板
+$http.dataFactory = async function(res) {
+    console.log("接口请求数据", {
+        url: res.url,
+        resolve: res.response,
+        header: res.header,
+        data: res.data,
+        method: res.method,
+    });
+    if (res.response.statusCode && res.response.statusCode == 200) {
+        let httpData = res.response.data;
+        if (typeof (httpData) == "string") {
+            httpData = JSON.parse(httpData);
+        }
+        // 开始----------------------以下是示例-请认真阅读代码-----------------------开始
+        //判断数据是否请求成功
+        if (httpData.success || httpData.code == 200) {  // 重点------判断接口请求是否成功,成功就返回成功的数据
+            // ---重点---返回正确的结果(then接受数据)---重点---
+            return Promise.resolve(httpData);
+        } else {
+            //其他错误提示
+            if (res.isPrompt) { // 是否提示
+                uni.showToast({
+                    title: httpData.info || httpData.msg, // 重点------把接口返回的错误抛出显示
+                    icon: "none",
+                    duration: 3000
+                });
+            }
+            // ---重点---返回错误的结果(catch接受数据)----重点---
+            return Promise.reject({
+                statusCode: 0,
+                errMsg: "【request】" + (httpData.info || httpData.msg)
+            });
+        }
+        // 结束----------------------以上是示例-请认真阅读代码-----------------------结束
+    } else {
+		// 返回错误的结果(catch接受数据)
+		return Promise.reject({
+			statusCode: res.response.statusCode,
+			errMsg: "【request】数据工厂验证不通过"
+		});
+	}
+};
+// 错误回调(所有错误都在这里)
+$http.requestError = function (e) {
+	if (e.statusCode === 0) {
+		throw e;
+	} else {
+		uni.showToast({
+			title: "网络错误,请检查一下网络",
+			icon: "none"
+		});
+	}
+}
+```
+
+### 通用请求方法
+```
+this.$http.request({
+	url: 'aid/region',
+	method: "GET", // POST、GET、PUT、DELETE、JSONP,具体说明查看官方文档
+	data: {pid:0},
+	timeout: 30000,  // 默认 30000 说明:超时时间,单位 ms,具体说明查看官方文档
+	dataType: "json",  // 默认 json 说明:如果设为 json,会尝试对返回的数据做一次 JSON.parse,具体说明查看官方文档
+	responseType: "text",  // 默认 text 说明:设置响应的数据类型。合法值:text、arraybuffer,具体说明查看官方文档
+	withCredentials: false,  // 默认 false 说明:跨域请求时是否携带凭证(cookies),具体说明查看官方文档
+	isPrompt: true,//(默认 true 说明:本接口抛出的错误是否提示)
+	load: true,//(默认 true 说明:本接口是否提示加载动画)
+	header: { //默认 无 说明:请求头
+		'Content-Type': 'application/json'
+	},
+	isFactory: true, //(默认 true 说明:本接口是否调用公共的数据处理方法,设置false后isPrompt参数将失去作用)
+}).then(function (response) {
+	//这里只会在接口是成功状态返回
+}).catch(function (error) {
+	//这里只会在接口是失败状态返回,不需要去处理错误提示
+	console.log(error);
+});
+```
+
+### get请求 正常写法 
+```
+this.$http.get('aid/region',{pid:0}).
+then(function (response) {
+	//这里只会在接口是成功状态返回
+}).catch(function (error) {
+	//这里只会在接口是失败状态返回,不需要去处理错误提示
+	console.log(error);
+});
+```
+
+### post请求 async写法 
+```
+async request(){
+	let data = await this.$http.post('aid/region',{pid:0});
+	console.log(data);
+}
+```
+
+### 其他功能配置项
+```
+let data = await this.$http.post(
+	'http://www.aaa.com/aid/region', //可以直接放链接(将不启用全局定义域名)
+	{
+		pid:0
+	}, 
+	{
+		isPrompt: true,//(默认 true 说明:本接口抛出的错误是否提示)
+		load: true,//(默认 true 说明:本接口是否提示加载动画)
+		header: { //默认 无 说明:请求头
+			'Content-Type': 'application/json'
+		},
+		isFactory: true //(默认 true 说明:本接口是否调用公共的数据处理方法,设置false后isPrompt参数将失去作用)
+	}
+);
+```
+
+### `requestConfig.js`可以设置服务器上传图片默认url
+```
+//可以new多个request来支持多个域名请求
+let $http = new request({
+	//服务器本地上传文件地址
+	fileUrl: base.baseUrl,
+	// 服务器上传图片默认url
+	defaultUploadUrl: "api/common/v1/upload_image",
+});
+```
+```
+// 上传可以不用传递url(使用全局的上传图片url)
+this.$http.urlImgUpload({
+	name:"后台接受文件key名称", //默认 file
+	count:"最大选择数",//默认 9
+	sizeType:"选择压缩图原图,默认两个都选",//默认 ['original', 'compressed']
+	sourceType:"选择相机拍照或相册上传 默认两个都选",//默认 ['album','camera']
+	data:"而外参数" //可不填,
+});
+// 上传可以不用传递url(使用全局的上传图片url)
+this.$http.urlVideoUpload({
+	sourceType:"选择相机拍照或相册上传 默认两个都选",//默认 ['album','camera']
+	compressed:"是否压缩所选的视频源文件,默认值为 true,需要压缩",//默认 false
+	maxDuration: "拍摄视频最长拍摄时间,单位秒。最长支持 60 秒", //默认 60
+	camera: '前置还是后置摄像头', //'front'、'back',默认'back'
+	name:"后台接受文件key名称", //默认 file
+	data:"而外参数" //可不填,
+});
+// 上传可以不用传递url(使用全局的上传图片url)
+this.$http.urlFileUpload({
+	files: [], // 必填 临时文件路径 格式: [{path: "图片地址"}]
+	data:"向服务器传递的参数", //可不填
+	name:"后台接受文件key名称", //默认 file
+});
+```
+
+### 本地服务器图片上传(支持多张上传)
+```
+this.$http.urlImgUpload('flie/upload',{
+	name:"后台接受文件key名称", //默认 file
+	count:"最大选择数",//默认 9
+	sizeType:"选择压缩图原图,默认两个都选",//默认 ['original', 'compressed']
+	sourceType:"选择相机拍照或相册上传 默认两个都选",//默认 ['album','camera']
+	data:"而外参数" //可不填,
+	isPrompt: true,//(默认 true 说明:本接口抛出的错误是否提示)
+	load: true,//(默认 true 说明:本接口是否提示加载动画)
+	header: { //默认 无 说明:请求头
+		'Content-Type': 'application/json'
+	},
+	isFactory: true, //(默认 true 说明:本接口是否调用公共的数据处理方法,设置false后isPrompt参数奖失去作用)
+	maxSize: 300000, //(默认 无 说明:上传的文件最大字节数限制,默认不限制)
+	onSelectComplete: res => {
+		console.log("选择完成返回:",res);
+	},
+	onEachUpdate: res => {
+		console.log("单张上传成功返回:",res);
+	},
+	onProgressUpdate: res => {
+		console.log("上传进度返回:",res);
+	}
+}).then(res => {
+	console.log("全部上传完返回结果:",res);
+});
+```
+### 本地服务器视频上传
+```
+this.$http.urlVideoUpload('flie/upload',{
+	sourceType:"选择相机拍照或相册上传 默认两个都选",//默认 ['album','camera']
+	compressed:"是否压缩所选的视频源文件,默认值为 true,需要压缩",//默认 false
+	maxDuration: "拍摄视频最长拍摄时间,单位秒。最长支持 60 秒", //默认 60
+	camera: '前置还是后置摄像头', //'front'、'back',默认'back'
+	name:"后台接受文件key名称", //默认 file
+	data:"而外参数" //可不填,
+	isPrompt: true,//(默认 true 说明:本接口抛出的错误是否提示)
+	load: true,//(默认 true 说明:本接口是否提示加载动画)
+	header: { //默认 无 说明:请求头
+		'Content-Type': 'application/json'
+	},
+	isFactory: true, //(默认 true 说明:本接口是否调用公共的数据处理方法,设置false后isPrompt参数奖失去作用)
+	maxSize: 300000, //(默认 无 说明:上传的文件最大字节数限制,默认不限制)
+	onProgressUpdate: res => {
+		console.log("上传进度返回:",res);
+	},
+	onSelectComplete: res => {
+		console.log("选择完成返回:",res);
+	},
+}).then(res => {
+	console.log("全部上传完返回结果:",res);
+});
+```
+### 本地服务器文件上传(支持多张上传)
+```
+this.$http.urlFileUpload("flie/upload",{
+	files: [], // 必填 临时文件路径 格式: [{path: "图片地址"}]
+	data:"向服务器传递的参数", //可不填
+	name:"后台接受文件key名称", //默认 file
+	isPrompt: true,//(默认 true 说明:本接口抛出的错误是否提示)
+	load: true,//(默认 true 说明:本接口是否提示加载动画)
+	header: { //默认 无 说明:请求头
+		'Content-Type': 'application/json'
+	},
+	isFactory: true, //(默认 true 说明:本接口是否调用公共的数据处理方法,设置false后isPrompt参数奖失去作用)
+	maxSize: 300000, //(默认 无 说明:上传的文件最大字节数限制,默认不限制)
+	onEachUpdate: res => {
+		console.log("单张上传成功返回:",res);
+	},
+	onProgressUpdate: res => {
+		console.log("上传进度返回:",res);
+	}
+}).then(res => {
+	console.log("全部上传完返回结果:",res);
+});
+```
+
+### 七牛云图片上传(支持多张上传)
+```
+this.$http.qnImgUpload({
+	count:"最大选择数", // 默认 9
+	sizeType:"选择压缩图原图,默认两个都选", // 默认 ['original', 'compressed']
+	sourceType:"选择相机拍照或相册上传 默认两个都选", // 默认 ['album','camera']
+	load: true, //(默认 true 说明:本接口是否提示加载动画)
+	maxSize: 300000, //(默认 无 说明:上传的文件最大字节数限制,默认不限制)
+	onSelectComplete: res => {
+		console.log("选择完成返回:",res);
+	},
+	onEachUpdate: res => {
+		console.log("单张上传成功返回:",res);
+	},
+	onProgressUpdate: res => {
+		console.log("上传进度返回:",res);
+	}
+}).then(res => {
+	console.log("全部上传完返回结果:",res);
+});
+```
+### 七牛云视频上传
+```
+this.$http.qnVideoUpload({
+	sourceType:"选择相机拍照或相册上传 默认两个都选",//默认 ['album','camera']
+	compressed:"是否压缩所选的视频源文件,默认值为 true,需要压缩",//默认 false
+	maxDuration: "拍摄视频最长拍摄时间,单位秒。最长支持 60 秒", //默认 60
+	camera: '前置还是后置摄像头', //'front'、'back',默认'back'
+	load: true,//(默认 true 说明:本接口是否提示加载动画)
+	maxSize: 300000, //(默认 无 说明:上传的文件最大字节数限制,默认不限制)
+	onSelectComplete: res => {
+		console.log("选择完成返回:",res);
+	},
+	onProgressUpdate: res => {
+		console.log("上传进度返回:",res);
+	}
+}).then(res => {
+	console.log("全部上传完返回结果:",res);
+});
+```
+### 七牛云文件上传(支持多张上传)
+```
+this.$http.qnFileUpload(
+{
+	files:[], // 必填 临时文件路径 格式: [{path: "图片地址"}]
+	load: true, //(默认 true 说明:本接口是否提示加载动画)
+	maxSize: 300000, //(默认 无 说明:上传的文件最大字节数限制,默认不限制)
+	onEachUpdate: res => {
+		console.log("单张上传成功返回:",res);
+	},
+	onProgressUpdate: res => {
+		console.log("上传进度返回:",res);
+	}
+}).then(res => {
+	console.log("全部上传完返回结果:",res);
+});
+```
+### 阿里云图片上传(支持多张上传)
+```
+this.$http.aliImgUpload({
+	count:"最大选择数", // 默认 9
+	sizeType:"选择压缩图原图,默认两个都选", // 默认 ['original', 'compressed']
+	sourceType:"选择相机拍照或相册上传 默认两个都选", // 默认 ['album','camera']
+	load: true, //(默认 true 说明:本接口是否提示加载动画)
+	maxSize: 300000, //(默认 无 说明:上传的文件最大字节数限制,默认不限制)
+	onSelectComplete: res => {
+		console.log("选择完成返回:",res);
+	},
+	onEachUpdate: res => {
+		console.log("单张上传成功返回:",res);
+	},
+	onProgressUpdate: res => {
+		console.log("上传进度返回:",res);
+	}
+}).then(res => {
+	console.log("全部上传完返回结果:",res);
+});
+```
+### 阿里云视频上传
+```
+this.$http.aliVideoUpload({
+	sourceType:"选择相机拍照或相册上传 默认两个都选",//默认 ['album','camera']
+	compressed:"是否压缩所选的视频源文件,默认值为 true,需要压缩",//默认 false
+	maxDuration: "拍摄视频最长拍摄时间,单位秒。最长支持 60 秒", //默认 60
+	camera: '前置还是后置摄像头', //'front'、'back',默认'back'
+	load: true,//(默认 true 说明:本接口是否提示加载动画)
+	maxSize: 300000, //(默认 无 说明:上传的文件最大字节数限制,默认不限制)
+	onSelectComplete: res => {
+		console.log("选择完成返回:",res);
+	},
+	onProgressUpdate: res => {
+		console.log("上传进度返回:",res);
+	}
+}).then(res => {
+	console.log("全部上传完返回结果:",res);
+});
+```
+### 阿里云文件上传(支持多张上传)
+```
+this.$http.aliFileUpload(
+{
+	files:[], // 必填 临时文件路径 格式: [{path: "图片地址"}]
+	load: true, //(默认 true 说明:本接口是否提示加载动画)
+	maxSize: 300000, //(默认 无 说明:上传的文件最大字节数限制,默认不限制)
+	onEachUpdate: res => {
+		console.log("单张上传成功返回:",res);
+	},
+	onProgressUpdate: res => {
+		console.log("上传进度返回:",res);
+	}
+}).then(res => {
+	console.log("全部上传完返回结果:",res);
+});
+```
+### jsonp 跨域请求(只支持H5)
+```
+let data = await this.$http.jsonp('http://www.aaa.com/aid/region',{pid:0}, {
+    isFactory: false, //(默认 true 说明:本接口是否调用公共的数据处理方法,设置false后isPrompt参数奖失去作用)
+});
+```

+ 9 - 3
pages/index/index.scss

@@ -1,5 +1,11 @@
  
 
+	@font-face {
+	    font-family: 'CustomFont';
+	    src: url('@/static/fonts/阿里妈妈数黑体.otf') format('opentype');
+	    font-weight: normal;
+	    font-style: normal;
+	}
 	.tab-nav {
 		display: flex;
 		justify-content: flex-start;
@@ -30,11 +36,11 @@
 			    border-top: 10rpx solid #ACF934;
 				display: none;
 			}
-			&.active { 
-				font-weight: bold;
+			&.active {  
 				background: #ACF934;
+				font-family: "CustomFont" !important;
 				.indicator-triangle {
-					display: block;
+					display: block; 
 				}
 			}
 		}

+ 115 - 41
pages/index/index.vue

@@ -18,12 +18,13 @@
 					<template #navCenter>
 						<view class="top" style="  display: flex;">
 							<view class="topBox" @click="lhSelectCityFun">
-								<text  style="margin-left: 10rpx; font-size: 44rpx;font-weight: 600;"> {{currentCity}} </text>
-								<image  src="@/static/home/home-bom.png"
+								<text style="margin-left: 10rpx; font-size: 44rpx;font-weight: 600;"> {{currentCity}}
+								</text>
+								<image src="@/static/home/home-bom.png"
 									style="width: 36rpx; height: 36rpx;margin-left: 15rpx;margin-right: 30rpx;"></image>
 							</view>
 							<view class="weather">
-								<p>多云🌤️20℃</p>
+								<p>{{weather.weather}}🌤️{{weather.temp}}</p>
 								<p>星期五</p>
 							</view>
 						</view>
@@ -226,8 +227,9 @@
 		</view>
 
 		<novice-guidance :step="step"></novice-guidance>
-		<lhSelectCity style="height: 100vh;" class="lhSelectCity" :currentCity="currentCity" :windowHeight="windowHeight" :hotCitys="hotCitys" @onSelect="City"
-		  v-if="lhSelectCityFalg" @closeLhSelectCityFun="closeLhSelectCityFun()" />
+		<lhSelectCity style="height: 100vh;" class="lhSelectCity" :currentCity="currentCity"
+			:windowHeight="windowHeight" :hotCitys="hotCitys" @onSelect="City" v-if="lhSelectCityFalg"
+			@closeLhSelectCityFun="closeLhSelectCityFun()" />
 	</view>
 </template>
 
@@ -346,7 +348,13 @@
 					'厦门'
 				],
 				currentCity: '北京',
-				windowHeight: ""
+				windowHeight: "",
+				weather:{
+					city: "",
+					weather: "",
+					temp: '0℃',
+					icon: 101
+				}
 			};
 		},
 		computed: {
@@ -370,12 +378,14 @@
 				return pages;
 			},
 		},
-		onLoad() {
+	 	onLoad() {
 			let that = this;
 			// 计算出可用高度
-			this.windowHeight = uni.getSystemInfoSync().windowHeight  + "px";
+			this.windowHeight = uni.getSystemInfoSync().windowHeight + "px";
 			// 不在onLoad中直接加载数据,避免与z-paging组件重复请求
-			// 让z-paging组件通过queryList方法控制数据加载
+			// 让z-paging组件通过queryList方法控制数据加载 
+			this.getWeather()
+		 
 		},
 		// 上拉加载更多
 		onReachBottom() {
@@ -383,19 +393,41 @@
 		},
 		// 下拉刷新数据
 		methods: {
-			lhSelectCityFun(){
-				this.lhSelectCityFalg=true
+			getWeather(){
+				uni.request({
+					url: this.$apiHost + '/Index/getAreaInfo',
+					data: {
+						uuid: getApp().globalData.uuid,
+						skey: getApp().globalData.skey,
+					},
+					header: {
+						"content-type": "application/json",
+						'sign': getApp().globalData.headerSign
+					},
+					success: (res) => {
+						console.log(res);
+					 this.currentCity = res.data.city 
+						this.weather = res.data	
+							console.log(this.weather ,999,res.data	);
+					},
+					complete: () => {},
+					fail: (e) => {
+					}
+				});
+			},
+			lhSelectCityFun() {
+				this.lhSelectCityFalg = true
 			},
 			// 选中事件
-			City(city) { 
+			City(city) {
 				this.currentCity = city
-				setTimeout(()=>{
+				setTimeout(() => {
 					this.lhSelectCityFalg = false
-				},300)
+				}, 300)
 
 			},
-			closeLhSelectCityFun(){ 
-				this.lhSelectCityFalg=false
+			closeLhSelectCityFun() {
+				this.lhSelectCityFalg = false
 			},
 			queryList() {
 				// 根据当前标签刷新数据
@@ -682,24 +714,64 @@
 					},
 				});
 			},
-			loadNewsList() {
+		 	loadNewsList() {
 				if (this.isLoadingNews) return;
 				this.isLoadingNews = true;
-
-				uni.request({
-					url: this.$apiHost + "/Article/getlist",
-					data: {
-						uuid: getApp().globalData.uuid,
-						skey: getApp().globalData.skey,
-						type: "list", // 新闻列表
-						offset: this.newsOffset,
-					},
-					header: {
-						"content-type": "application/json",
-						sign: getApp().globalData.headerSign,
-					},
-					success: (res) => {
-						console.log("新闻列表数据:", res.data);
+				// uni.request({
+				// 	url: this.$apiHost + "/Article/getlist",
+				// 	data: {
+				// 		uuid: getApp().globalData.uuid,
+				// 		skey: getApp().globalData.skey,
+				// 		type: "list", // 新闻列表
+				// 		offset: this.newsOffset,
+				// 	},
+				// 	header: {
+				// 		"content-type": "application/json",
+				// 		sign: getApp().globalData.headerSign,
+				// 	},
+				// 	success: (res) => {
+				// 		console.log("新闻列表数据:", res.data);
+				// 		if (
+				// 			res.data.success == "yes" &&
+				// 			res.data.list &&
+				// 			res.data.list.length > 0
+				// 		) {
+				// 			this.newsList = [...this.newsList, ...res.data.list];
+				// 			this.newsOffset += res.data.list.length;
+
+				// 			if (res.data.list.length < 20) {
+				// 				this.hasMoreNews = false;
+				// 			}
+				// 		} else {
+				// 			this.hasMoreNews = false;
+				// 		}
+
+				// 		// 无论是否有数据,都需要通知z-paging组件完成刷新
+				// 		if (this.$refs.paging) {
+				// 			this.$refs.paging.complete(this.newsList);
+				// 		}
+				// 	},
+				// 	complete: () => {
+				// 		this.isLoadingNews = false;
+				// 	},
+				// 	fail: (e) => {
+				// 		console.log("请求新闻列表失败:", e);
+				// 		this.isLoadingNews = false;
+				// 		// 加载失败时也要通知组件完成
+				// 		if (this.$refs.paging) {
+				// 			this.$refs.paging.complete(false);
+				// 		}
+				// 	},
+				// });
+				this.$http.get('/Article/getlist', {
+					uuid: getApp().globalData.uuid,
+					skey: getApp().globalData.skey,
+					type: "list", // 新闻列表
+					offset: this.newsOffset,
+				}).then(
+					async res => {
+						await res 
+						console.log("新闻列表数据:", res);
 						if (
 							res.data.success == "yes" &&
 							res.data.list &&
@@ -707,31 +779,33 @@
 						) {
 							this.newsList = [...this.newsList, ...res.data.list];
 							this.newsOffset += res.data.list.length;
-
+						
 							if (res.data.list.length < 20) {
 								this.hasMoreNews = false;
 							}
 						} else {
 							this.hasMoreNews = false;
 						}
-
+						
 						// 无论是否有数据,都需要通知z-paging组件完成刷新
 						if (this.$refs.paging) {
 							this.$refs.paging.complete(this.newsList);
 						}
-					},
-					complete: () => {
-						this.isLoadingNews = false;
-					},
-					fail: (e) => {
+					}).catch(
+					async e => {
+						await e
 						console.log("请求新闻列表失败:", e);
 						this.isLoadingNews = false;
 						// 加载失败时也要通知组件完成
 						if (this.$refs.paging) {
 							this.$refs.paging.complete(false);
 						}
-					},
-				});
+					}).finally(
+					() => {
+						 this.isLoadingNews = false;
+					})
+				 
+
 			},
 			loadMoreData() {
 				// 根据当前标签加载更多数据

+ 2 - 2
pages/login/login.vue

@@ -98,8 +98,8 @@
 					num_history: 0,
 					num_collection: 0
 				},
-				mobile: '',
-				password: '',
+				mobile: '18899990000',
+				password: '111111',
 				code: '',
 				captchaTime: 0,
 				push_token: '',

BIN
static/fonts/阿里妈妈数黑体.otf


+ 11 - 0
style/FontStyle.css

@@ -1,3 +1,14 @@
+@font-face {
+    font-family: 'CustomFont';
+    src: url('@/static/fonts/阿里妈妈数黑体.otf') format('opentype');
+    font-weight: normal;
+    font-style: normal;
+}
+
+.CustomFont {
+    font-family: 'CustomFont', sans-serif !important;
+}
+
 @font-face {
   font-family: 'iconfont';  /* project id 1639347 */
   src: url('https://at.alicdn.com/t/font_1639347_9tnhp28j8vi.eot');