更新大理市民卡app
diff --git a/uview-ui/libs/function/$parent.js b/uview-ui/libs/function/$parent.js
new file mode 100644
index 0000000..80515c4
--- /dev/null
+++ b/uview-ui/libs/function/$parent.js
@@ -0,0 +1,18 @@
+// 获取父组件的参数,因为支付宝小程序不支持provide/inject的写法
+// this.$parent在非H5中,可以准确获取到父组件,但是在H5中,需要多次this.$parent.$parent.xxx
+// 这里默认值等于undefined有它的含义,因为最顶层元素(组件)的$parent就是undefined,意味着不传name
+// 值(默认为undefined),就是查找最顶层的$parent
+export default function $parent(name = undefined) {
+	let parent = this.$parent;
+	// 通过while历遍,这里主要是为了H5需要多层解析的问题
+	while (parent) {
+		// 父组件
+		if (parent.$options && parent.$options.name !== name) {
+			// 如果组件的name不相等,继续上一级寻找
+			parent = parent.$parent;
+		} else {
+			return parent;
+		}
+	}
+	return false;
+}
\ No newline at end of file
diff --git a/uview-ui/libs/function/addUnit.js b/uview-ui/libs/function/addUnit.js
new file mode 100644
index 0000000..247fae2
--- /dev/null
+++ b/uview-ui/libs/function/addUnit.js
@@ -0,0 +1,8 @@
+import validation from './test.js';
+
+// 添加单位,如果有rpx,%,px等单位结尾或者值为auto,直接返回,否则加上rpx单位结尾
+export default function addUnit(value = 'auto', unit = 'rpx') {
+    value = String(value);
+	// 用uView内置验证规则中的number判断是否为数值
+    return validation.number(value) ? `${value}${unit}` : value;
+}
\ No newline at end of file
diff --git a/uview-ui/libs/function/bem.js b/uview-ui/libs/function/bem.js
new file mode 100644
index 0000000..05d1a36
--- /dev/null
+++ b/uview-ui/libs/function/bem.js
@@ -0,0 +1,5 @@
+function bem(name, conf) {
+  
+}
+
+module.exports.bem = bem;
diff --git a/uview-ui/libs/function/color.js b/uview-ui/libs/function/color.js
new file mode 100644
index 0000000..dafb8c1
--- /dev/null
+++ b/uview-ui/libs/function/color.js
@@ -0,0 +1,37 @@
+// 为了让用户能够自定义主题,会逐步弃用此文件,各颜色通过css提供
+// 为了给某些特殊场景使用和向后兼容,无需删除此文件(2020-06-20)
+let color = {
+	primary: "#2979ff",
+	primaryDark: "#2b85e4",
+	primaryDisabled: "#a0cfff",
+	primaryLight: "#ecf5ff",
+	bgColor: "#f3f4f6",
+	
+	info: "#909399",
+	infoDark: "#82848a",
+	infoDisabled: "#c8c9cc",
+	infoLight: "#f4f4f5",
+	
+	warning: "#ff9900",
+	warningDark: "#f29100",
+	warningDisabled: "#fcbd71",
+	warningLight: "#fdf6ec",
+	
+	error: "#fa3534",
+	errorDark: "#dd6161",
+	errorDisabled: "#fab6b6",
+	errorLight: "#fef0f0",
+	
+	success: "#19be6b",
+	successDark: "#18b566",
+	successDisabled: "#71d5a1",
+	successLight: "#dbf1e1",
+	
+	mainColor: "#303133",
+	contentColor: "#606266",
+	tipsColor: "#909399",
+	lightColor: "#c0c4cc",
+	borderColor: "#e4e7ed"
+}
+
+export default color;
\ No newline at end of file
diff --git a/uview-ui/libs/function/colorGradient.js b/uview-ui/libs/function/colorGradient.js
new file mode 100644
index 0000000..7157513
--- /dev/null
+++ b/uview-ui/libs/function/colorGradient.js
@@ -0,0 +1,100 @@
+/**
+ * 求两个颜色之间的渐变值
+ * @param {string} startColor 开始的颜色
+ * @param {string} endColor 结束的颜色
+ * @param {number} step 颜色等分的份额
+ * */
+function colorGradient(startColor = 'rgb(0, 0, 0)', endColor = 'rgb(255, 255, 255)', step = 10) {
+	let startRGB = hexToRgb(startColor, false); //转换为rgb数组模式
+	let startR = startRGB[0];
+	let startG = startRGB[1];
+	let startB = startRGB[2];
+
+	let endRGB = hexToRgb(endColor, false);
+	let endR = endRGB[0];
+	let endG = endRGB[1];
+	let endB = endRGB[2];
+
+	let sR = (endR - startR) / step; //总差值
+	let sG = (endG - startG) / step;
+	let sB = (endB - startB) / step;
+	let colorArr = [];
+	for (let i = 0; i < step; i++) {
+		//计算每一步的hex值 
+		let hex = rgbToHex('rgb(' + Math.round((sR * i + startR)) + ',' + Math.round((sG * i + startG)) + ',' + Math.round((sB *
+			i + startB)) + ')');
+		colorArr.push(hex);
+	}
+	return colorArr;
+}
+
+// 将hex表示方式转换为rgb表示方式(这里返回rgb数组模式)
+function hexToRgb(sColor, str = true) {
+	let reg = /^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/;
+	sColor = sColor.toLowerCase();
+	if (sColor && reg.test(sColor)) {
+		if (sColor.length === 4) {
+			let sColorNew = "#";
+			for (let i = 1; i < 4; i += 1) {
+				sColorNew += sColor.slice(i, i + 1).concat(sColor.slice(i, i + 1));
+			}
+			sColor = sColorNew;
+		}
+		//处理六位的颜色值
+		let sColorChange = [];
+		for (let i = 1; i < 7; i += 2) {
+			sColorChange.push(parseInt("0x" + sColor.slice(i, i + 2)));
+		}
+		if(!str) {
+			return sColorChange;
+		} else {
+			return `rgb(${sColorChange[0]},${sColorChange[1]},${sColorChange[2]})`;
+		}
+	} else if (/^(rgb|RGB)/.test(sColor)) {
+		let arr = sColor.replace(/(?:\(|\)|rgb|RGB)*/g, "").split(",")
+		return arr.map(val => Number(val));
+	} else {
+		return sColor;
+	}
+};
+
+// 将rgb表示方式转换为hex表示方式
+function rgbToHex(rgb) {
+	let _this = rgb;
+	let reg = /^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/;
+	if (/^(rgb|RGB)/.test(_this)) {
+		let aColor = _this.replace(/(?:\(|\)|rgb|RGB)*/g, "").split(",");
+		let strHex = "#";
+		for (let i = 0; i < aColor.length; i++) {
+			let hex = Number(aColor[i]).toString(16);
+			hex = String(hex).length == 1 ? 0 + '' + hex : hex; // 保证每个rgb的值为2位
+			if (hex === "0") {
+				hex += hex;
+			}
+			strHex += hex;
+		}
+		if (strHex.length !== 7) {
+			strHex = _this;
+		}
+		return strHex;
+	} else if (reg.test(_this)) {
+		let aNum = _this.replace(/#/, "").split("");
+		if (aNum.length === 6) {
+			return _this;
+		} else if (aNum.length === 3) {
+			let numHex = "#";
+			for (let i = 0; i < aNum.length; i += 1) {
+				numHex += (aNum[i] + aNum[i]);
+			}
+			return numHex;
+		}
+	} else {
+		return _this;
+	}
+}
+
+export default {
+	colorGradient,
+	hexToRgb,
+	rgbToHex
+}
\ No newline at end of file
diff --git a/uview-ui/libs/function/debounce.js b/uview-ui/libs/function/debounce.js
new file mode 100644
index 0000000..4f1027b
--- /dev/null
+++ b/uview-ui/libs/function/debounce.js
@@ -0,0 +1,29 @@
+let timeout = null;
+
+/**
+ * 防抖原理:一定时间内,只有最后一次操作,再过wait毫秒后才执行函数
+ * 
+ * @param {Function} func 要执行的回调函数 
+ * @param {Number} wait 延时的时间
+ * @param {Boolean} immediate 是否立即执行 
+ * @return null
+ */
+function debounce(func, wait = 500, immediate = false) {
+	// 清除定时器
+	if (timeout !== null) clearTimeout(timeout);
+	// 立即执行,此类情况一般用不到
+	if (immediate) {
+		var callNow = !timeout;
+		timeout = setTimeout(function() {
+			timeout = null;
+		}, wait);
+		if (callNow) typeof func === 'function' && func();
+	} else {
+		// 设置定时器,当最后一次操作后,timeout不会再被清除,所以在延时wait毫秒后执行func回调方法
+		timeout = setTimeout(function() {
+			typeof func === 'function' && func();
+		}, wait);
+	}
+}
+
+export default debounce
diff --git a/uview-ui/libs/function/deepClone.js b/uview-ui/libs/function/deepClone.js
new file mode 100644
index 0000000..3db999a
--- /dev/null
+++ b/uview-ui/libs/function/deepClone.js
@@ -0,0 +1,23 @@
+// 判断arr是否为一个数组,返回一个bool值
+function isArray (arr) {
+    return Object.prototype.toString.call(arr) === '[object Array]';
+}
+
+// 深度克隆
+function deepClone (obj) {
+	// 对常见的“非”值,直接返回原来值
+	if([null, undefined, NaN, false].includes(obj)) return obj;
+    if(typeof obj !== "object" && typeof obj !== 'function') {
+		//原始类型直接返回
+        return obj;
+    }
+    var o = isArray(obj) ? [] : {};
+    for(let i in obj) {
+        if(obj.hasOwnProperty(i)){
+            o[i] = typeof obj[i] === "object" ? deepClone(obj[i]) : obj[i];
+        }
+    }
+    return o;
+}
+
+export default deepClone;
diff --git a/uview-ui/libs/function/deepMerge.js b/uview-ui/libs/function/deepMerge.js
new file mode 100644
index 0000000..81d2d18
--- /dev/null
+++ b/uview-ui/libs/function/deepMerge.js
@@ -0,0 +1,30 @@
+import deepClone from "./deepClone";
+
+// JS对象深度合并
+function deepMerge(target = {}, source = {}) {
+	target = deepClone(target);
+	if (typeof target !== 'object' || typeof source !== 'object') return false;
+	for (var prop in source) {
+		if (!source.hasOwnProperty(prop)) continue;
+		if (prop in target) {
+			if (typeof target[prop] !== 'object') {
+				target[prop] = source[prop];
+			} else {
+				if (typeof source[prop] !== 'object') {
+					target[prop] = source[prop];
+				} else {
+					if (target[prop].concat && source[prop].concat) {
+						target[prop] = target[prop].concat(source[prop]);
+					} else {
+						target[prop] = deepMerge(target[prop], source[prop]);
+					}
+				}
+			}
+		} else {
+			target[prop] = source[prop];
+		}
+	}
+	return target;
+}
+
+export default deepMerge;
\ No newline at end of file
diff --git a/uview-ui/libs/function/getParent.js b/uview-ui/libs/function/getParent.js
new file mode 100644
index 0000000..9cb45c4
--- /dev/null
+++ b/uview-ui/libs/function/getParent.js
@@ -0,0 +1,47 @@
+// 获取父组件的参数,因为支付宝小程序不支持provide/inject的写法
+// this.$parent在非H5中,可以准确获取到父组件,但是在H5中,需要多次this.$parent.$parent.xxx
+export default function getParent(name, keys) {
+	let parent = this.$parent;
+	// 通过while历遍,这里主要是为了H5需要多层解析的问题
+	while (parent) {
+		// 父组件
+		if (parent.$options.name !== name) {
+			// 如果组件的name不相等,继续上一级寻找
+			parent = parent.$parent;
+		} else {
+			let data = {};
+			// 判断keys是否数组,如果传过来的是一个数组,那么直接使用数组元素值当做键值去父组件寻找
+			if(Array.isArray(keys)) {
+				keys.map(val => {
+					data[val] = parent[val] ? parent[val] : '';
+				})
+			} else {
+				// 历遍传过来的对象参数
+				for(let i in keys) {
+					// 如果子组件有此值则用,无此值则用父组件的值
+					// 判断是否空数组,如果是,则用父组件的值,否则用子组件的值
+					if(Array.isArray(keys[i])) {
+						if(keys[i].length) {
+							data[i] = keys[i];
+						} else {
+							data[i] = parent[i];
+						}
+					} else if(keys[i].constructor === Object) {
+						// 判断是否对象,如果是对象,且有属性,那么使用子组件的值,否则使用父组件的值
+						if(Object.keys(keys[i]).length) {
+							data[i] = keys[i];
+						} else {
+							data[i] = parent[i];
+						}
+					} else {
+						// 只要子组件有传值,即使是false值,也是“传值”了,也需要覆盖父组件的同名参数
+						data[i] = (keys[i] || keys[i] === false) ? keys[i] : parent[i];
+					}
+				}
+			}
+			return data;
+		}
+	}
+
+	return {};
+}
\ No newline at end of file
diff --git a/uview-ui/libs/function/guid.js b/uview-ui/libs/function/guid.js
new file mode 100644
index 0000000..8497664
--- /dev/null
+++ b/uview-ui/libs/function/guid.js
@@ -0,0 +1,41 @@
+/**
+ * 本算法来源于简书开源代码,详见:https://www.jianshu.com/p/fdbf293d0a85
+ * 全局唯一标识符(uuid,Globally Unique Identifier),也称作 uuid(Universally Unique IDentifier) 
+ * 一般用于多个组件之间,给它一个唯一的标识符,或者v-for循环的时候,如果使用数组的index可能会导致更新列表出现问题
+ * 最可能的情况是左滑删除item或者对某条信息流"不喜欢"并去掉它的时候,会导致组件内的数据可能出现错乱
+ * v-for的时候,推荐使用后端返回的id而不是循环的index
+ * @param {Number} len uuid的长度
+ * @param {Boolean} firstU 将返回的首字母置为"u"
+ * @param {Nubmer} radix 生成uuid的基数(意味着返回的字符串都是这个基数),2-二进制,8-八进制,10-十进制,16-十六进制
+ */
+function guid(len = 32, firstU = true, radix = null) {
+	let chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split('');
+	let uuid = [];
+	radix = radix || chars.length;
+
+	if (len) {
+		// 如果指定uuid长度,只是取随机的字符,0|x为位运算,能去掉x的小数位,返回整数位
+		for (let i = 0; i < len; i++) uuid[i] = chars[0 | Math.random() * radix];
+	} else {
+		let r;
+		// rfc4122标准要求返回的uuid中,某些位为固定的字符
+		uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-';
+		uuid[14] = '4';
+
+		for (let i = 0; i < 36; i++) {
+			if (!uuid[i]) {
+				r = 0 | Math.random() * 16;
+				uuid[i] = chars[(i == 19) ? (r & 0x3) | 0x8 : r];
+			}
+		}
+	}
+	// 移除第一个字符,并用u替代,因为第一个字符为数值时,该guuid不能用作id或者class
+	if (firstU) {
+		uuid.shift();
+		return 'u' + uuid.join('');
+	} else {
+		return uuid.join('');
+	}
+}
+
+export default guid;
diff --git a/uview-ui/libs/function/md5.js b/uview-ui/libs/function/md5.js
new file mode 100644
index 0000000..8d541a1
--- /dev/null
+++ b/uview-ui/libs/function/md5.js
@@ -0,0 +1,385 @@
+/*
+ * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
+ * Digest Algorithm, as defined in RFC 1321.
+ * Version 2.2 Copyright (C) Paul Johnston 1999 - 2009
+ * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
+ * Distributed under the BSD License
+ * See http://pajhome.org.uk/crypt/md5 for more info.
+ */
+
+/*
+ * Configurable variables. You may need to tweak these to be compatible with
+ * the server-side, but the defaults work in most cases.
+ */
+var hexcase = 0;   /* hex output format. 0 - lowercase; 1 - uppercase        */
+var b64pad  = "";  /* base-64 pad character. "=" for strict RFC compliance   */
+
+/*
+ * These are the functions you'll usually want to call
+ * They take string arguments and return either hex or base-64 encoded strings
+ */
+function hex_md5(s)    { return rstr2hex(rstr_md5(str2rstr_utf8(s))); }
+function b64_md5(s)    { return rstr2b64(rstr_md5(str2rstr_utf8(s))); }
+function any_md5(s, e) { return rstr2any(rstr_md5(str2rstr_utf8(s)), e); }
+function hex_hmac_md5(k, d)
+  { return rstr2hex(rstr_hmac_md5(str2rstr_utf8(k), str2rstr_utf8(d))); }
+function b64_hmac_md5(k, d)
+  { return rstr2b64(rstr_hmac_md5(str2rstr_utf8(k), str2rstr_utf8(d))); }
+function any_hmac_md5(k, d, e)
+  { return rstr2any(rstr_hmac_md5(str2rstr_utf8(k), str2rstr_utf8(d)), e); }
+
+/*
+ * Perform a simple self-test to see if the VM is working
+ */
+function md5_vm_test()
+{
+  return hex_md5("abc").toLowerCase() == "900150983cd24fb0d6963f7d28e17f72";
+}
+
+/*
+ * Calculate the MD5 of a raw string
+ */
+function rstr_md5(s)
+{
+  return binl2rstr(binl_md5(rstr2binl(s), s.length * 8));
+}
+
+/*
+ * Calculate the HMAC-MD5, of a key and some data (raw strings)
+ */
+function rstr_hmac_md5(key, data)
+{
+  var bkey = rstr2binl(key);
+  if(bkey.length > 16) bkey = binl_md5(bkey, key.length * 8);
+
+  var ipad = Array(16), opad = Array(16);
+  for(var i = 0; i < 16; i++)
+  {
+    ipad[i] = bkey[i] ^ 0x36363636;
+    opad[i] = bkey[i] ^ 0x5C5C5C5C;
+  }
+
+  var hash = binl_md5(ipad.concat(rstr2binl(data)), 512 + data.length * 8);
+  return binl2rstr(binl_md5(opad.concat(hash), 512 + 128));
+}
+
+/*
+ * Convert a raw string to a hex string
+ */
+function rstr2hex(input)
+{
+  try { hexcase } catch(e) { hexcase=0; }
+  var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
+  var output = "";
+  var x;
+  for(var i = 0; i < input.length; i++)
+  {
+    x = input.charCodeAt(i);
+    output += hex_tab.charAt((x >>> 4) & 0x0F)
+           +  hex_tab.charAt( x        & 0x0F);
+  }
+  return output;
+}
+
+/*
+ * Convert a raw string to a base-64 string
+ */
+function rstr2b64(input)
+{
+  try { b64pad } catch(e) { b64pad=''; }
+  var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+  var output = "";
+  var len = input.length;
+  for(var i = 0; i < len; i += 3)
+  {
+    var triplet = (input.charCodeAt(i) << 16)
+                | (i + 1 < len ? input.charCodeAt(i+1) << 8 : 0)
+                | (i + 2 < len ? input.charCodeAt(i+2)      : 0);
+    for(var j = 0; j < 4; j++)
+    {
+      if(i * 8 + j * 6 > input.length * 8) output += b64pad;
+      else output += tab.charAt((triplet >>> 6*(3-j)) & 0x3F);
+    }
+  }
+  return output;
+}
+
+/*
+ * Convert a raw string to an arbitrary string encoding
+ */
+function rstr2any(input, encoding)
+{
+  var divisor = encoding.length;
+  var i, j, q, x, quotient;
+
+  /* Convert to an array of 16-bit big-endian values, forming the dividend */
+  var dividend = Array(Math.ceil(input.length / 2));
+  for(i = 0; i < dividend.length; i++)
+  {
+    dividend[i] = (input.charCodeAt(i * 2) << 8) | input.charCodeAt(i * 2 + 1);
+  }
+
+  /*
+   * Repeatedly perform a long division. The binary array forms the dividend,
+   * the length of the encoding is the divisor. Once computed, the quotient
+   * forms the dividend for the next step. All remainders are stored for later
+   * use.
+   */
+  var full_length = Math.ceil(input.length * 8 /
+                                    (Math.log(encoding.length) / Math.log(2)));
+  var remainders = Array(full_length);
+  for(j = 0; j < full_length; j++)
+  {
+    quotient = Array();
+    x = 0;
+    for(i = 0; i < dividend.length; i++)
+    {
+      x = (x << 16) + dividend[i];
+      q = Math.floor(x / divisor);
+      x -= q * divisor;
+      if(quotient.length > 0 || q > 0)
+        quotient[quotient.length] = q;
+    }
+    remainders[j] = x;
+    dividend = quotient;
+  }
+
+  /* Convert the remainders to the output string */
+  var output = "";
+  for(i = remainders.length - 1; i >= 0; i--)
+    output += encoding.charAt(remainders[i]);
+
+  return output;
+}
+
+/*
+ * Encode a string as utf-8.
+ * For efficiency, this assumes the input is valid utf-16.
+ */
+function str2rstr_utf8(input)
+{
+  var output = "";
+  var i = -1;
+  var x, y;
+
+  while(++i < input.length)
+  {
+    /* Decode utf-16 surrogate pairs */
+    x = input.charCodeAt(i);
+    y = i + 1 < input.length ? input.charCodeAt(i + 1) : 0;
+    if(0xD800 <= x && x <= 0xDBFF && 0xDC00 <= y && y <= 0xDFFF)
+    {
+      x = 0x10000 + ((x & 0x03FF) << 10) + (y & 0x03FF);
+      i++;
+    }
+
+    /* Encode output as utf-8 */
+    if(x <= 0x7F)
+      output += String.fromCharCode(x);
+    else if(x <= 0x7FF)
+      output += String.fromCharCode(0xC0 | ((x >>> 6 ) & 0x1F),
+                                    0x80 | ( x         & 0x3F));
+    else if(x <= 0xFFFF)
+      output += String.fromCharCode(0xE0 | ((x >>> 12) & 0x0F),
+                                    0x80 | ((x >>> 6 ) & 0x3F),
+                                    0x80 | ( x         & 0x3F));
+    else if(x <= 0x1FFFFF)
+      output += String.fromCharCode(0xF0 | ((x >>> 18) & 0x07),
+                                    0x80 | ((x >>> 12) & 0x3F),
+                                    0x80 | ((x >>> 6 ) & 0x3F),
+                                    0x80 | ( x         & 0x3F));
+  }
+  return output;
+}
+
+/*
+ * Encode a string as utf-16
+ */
+function str2rstr_utf16le(input)
+{
+  var output = "";
+  for(var i = 0; i < input.length; i++)
+    output += String.fromCharCode( input.charCodeAt(i)        & 0xFF,
+                                  (input.charCodeAt(i) >>> 8) & 0xFF);
+  return output;
+}
+
+function str2rstr_utf16be(input)
+{
+  var output = "";
+  for(var i = 0; i < input.length; i++)
+    output += String.fromCharCode((input.charCodeAt(i) >>> 8) & 0xFF,
+                                   input.charCodeAt(i)        & 0xFF);
+  return output;
+}
+
+/*
+ * Convert a raw string to an array of little-endian words
+ * Characters >255 have their high-byte silently ignored.
+ */
+function rstr2binl(input)
+{
+  var output = Array(input.length >> 2);
+  for(var i = 0; i < output.length; i++)
+    output[i] = 0;
+  for(var i = 0; i < input.length * 8; i += 8)
+    output[i>>5] |= (input.charCodeAt(i / 8) & 0xFF) << (i%32);
+  return output;
+}
+
+/*
+ * Convert an array of little-endian words to a string
+ */
+function binl2rstr(input)
+{
+  var output = "";
+  for(var i = 0; i < input.length * 32; i += 8)
+    output += String.fromCharCode((input[i>>5] >>> (i % 32)) & 0xFF);
+  return output;
+}
+
+/*
+ * Calculate the MD5 of an array of little-endian words, and a bit length.
+ */
+function binl_md5(x, len)
+{
+  /* append padding */
+  x[len >> 5] |= 0x80 << ((len) % 32);
+  x[(((len + 64) >>> 9) << 4) + 14] = len;
+
+  var a =  1732584193;
+  var b = -271733879;
+  var c = -1732584194;
+  var d =  271733878;
+
+  for(var i = 0; i < x.length; i += 16)
+  {
+    var olda = a;
+    var oldb = b;
+    var oldc = c;
+    var oldd = d;
+
+    a = md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936);
+    d = md5_ff(d, a, b, c, x[i+ 1], 12, -389564586);
+    c = md5_ff(c, d, a, b, x[i+ 2], 17,  606105819);
+    b = md5_ff(b, c, d, a, x[i+ 3], 22, -1044525330);
+    a = md5_ff(a, b, c, d, x[i+ 4], 7 , -176418897);
+    d = md5_ff(d, a, b, c, x[i+ 5], 12,  1200080426);
+    c = md5_ff(c, d, a, b, x[i+ 6], 17, -1473231341);
+    b = md5_ff(b, c, d, a, x[i+ 7], 22, -45705983);
+    a = md5_ff(a, b, c, d, x[i+ 8], 7 ,  1770035416);
+    d = md5_ff(d, a, b, c, x[i+ 9], 12, -1958414417);
+    c = md5_ff(c, d, a, b, x[i+10], 17, -42063);
+    b = md5_ff(b, c, d, a, x[i+11], 22, -1990404162);
+    a = md5_ff(a, b, c, d, x[i+12], 7 ,  1804603682);
+    d = md5_ff(d, a, b, c, x[i+13], 12, -40341101);
+    c = md5_ff(c, d, a, b, x[i+14], 17, -1502002290);
+    b = md5_ff(b, c, d, a, x[i+15], 22,  1236535329);
+
+    a = md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510);
+    d = md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632);
+    c = md5_gg(c, d, a, b, x[i+11], 14,  643717713);
+    b = md5_gg(b, c, d, a, x[i+ 0], 20, -373897302);
+    a = md5_gg(a, b, c, d, x[i+ 5], 5 , -701558691);
+    d = md5_gg(d, a, b, c, x[i+10], 9 ,  38016083);
+    c = md5_gg(c, d, a, b, x[i+15], 14, -660478335);
+    b = md5_gg(b, c, d, a, x[i+ 4], 20, -405537848);
+    a = md5_gg(a, b, c, d, x[i+ 9], 5 ,  568446438);
+    d = md5_gg(d, a, b, c, x[i+14], 9 , -1019803690);
+    c = md5_gg(c, d, a, b, x[i+ 3], 14, -187363961);
+    b = md5_gg(b, c, d, a, x[i+ 8], 20,  1163531501);
+    a = md5_gg(a, b, c, d, x[i+13], 5 , -1444681467);
+    d = md5_gg(d, a, b, c, x[i+ 2], 9 , -51403784);
+    c = md5_gg(c, d, a, b, x[i+ 7], 14,  1735328473);
+    b = md5_gg(b, c, d, a, x[i+12], 20, -1926607734);
+
+    a = md5_hh(a, b, c, d, x[i+ 5], 4 , -378558);
+    d = md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463);
+    c = md5_hh(c, d, a, b, x[i+11], 16,  1839030562);
+    b = md5_hh(b, c, d, a, x[i+14], 23, -35309556);
+    a = md5_hh(a, b, c, d, x[i+ 1], 4 , -1530992060);
+    d = md5_hh(d, a, b, c, x[i+ 4], 11,  1272893353);
+    c = md5_hh(c, d, a, b, x[i+ 7], 16, -155497632);
+    b = md5_hh(b, c, d, a, x[i+10], 23, -1094730640);
+    a = md5_hh(a, b, c, d, x[i+13], 4 ,  681279174);
+    d = md5_hh(d, a, b, c, x[i+ 0], 11, -358537222);
+    c = md5_hh(c, d, a, b, x[i+ 3], 16, -722521979);
+    b = md5_hh(b, c, d, a, x[i+ 6], 23,  76029189);
+    a = md5_hh(a, b, c, d, x[i+ 9], 4 , -640364487);
+    d = md5_hh(d, a, b, c, x[i+12], 11, -421815835);
+    c = md5_hh(c, d, a, b, x[i+15], 16,  530742520);
+    b = md5_hh(b, c, d, a, x[i+ 2], 23, -995338651);
+
+    a = md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844);
+    d = md5_ii(d, a, b, c, x[i+ 7], 10,  1126891415);
+    c = md5_ii(c, d, a, b, x[i+14], 15, -1416354905);
+    b = md5_ii(b, c, d, a, x[i+ 5], 21, -57434055);
+    a = md5_ii(a, b, c, d, x[i+12], 6 ,  1700485571);
+    d = md5_ii(d, a, b, c, x[i+ 3], 10, -1894986606);
+    c = md5_ii(c, d, a, b, x[i+10], 15, -1051523);
+    b = md5_ii(b, c, d, a, x[i+ 1], 21, -2054922799);
+    a = md5_ii(a, b, c, d, x[i+ 8], 6 ,  1873313359);
+    d = md5_ii(d, a, b, c, x[i+15], 10, -30611744);
+    c = md5_ii(c, d, a, b, x[i+ 6], 15, -1560198380);
+    b = md5_ii(b, c, d, a, x[i+13], 21,  1309151649);
+    a = md5_ii(a, b, c, d, x[i+ 4], 6 , -145523070);
+    d = md5_ii(d, a, b, c, x[i+11], 10, -1120210379);
+    c = md5_ii(c, d, a, b, x[i+ 2], 15,  718787259);
+    b = md5_ii(b, c, d, a, x[i+ 9], 21, -343485551);
+
+    a = safe_add(a, olda);
+    b = safe_add(b, oldb);
+    c = safe_add(c, oldc);
+    d = safe_add(d, oldd);
+  }
+  return Array(a, b, c, d);
+}
+
+/*
+ * These functions implement the four basic operations the algorithm uses.
+ */
+function md5_cmn(q, a, b, x, s, t)
+{
+  return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s),b);
+}
+function md5_ff(a, b, c, d, x, s, t)
+{
+  return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t);
+}
+function md5_gg(a, b, c, d, x, s, t)
+{
+  return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t);
+}
+function md5_hh(a, b, c, d, x, s, t)
+{
+  return md5_cmn(b ^ c ^ d, a, b, x, s, t);
+}
+function md5_ii(a, b, c, d, x, s, t)
+{
+  return md5_cmn(c ^ (b | (~d)), a, b, x, s, t);
+}
+
+/*
+ * Add integers, wrapping at 2^32. This uses 16-bit operations internally
+ * to work around bugs in some JS interpreters.
+ */
+function safe_add(x, y)
+{
+  var lsw = (x & 0xFFFF) + (y & 0xFFFF);
+  var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
+  return (msw << 16) | (lsw & 0xFFFF);
+}
+
+/*
+ * Bitwise rotate a 32-bit number to the left.
+ */
+function bit_rol(num, cnt)
+{
+  return (num << cnt) | (num >>> (32 - cnt));
+}
+
+module.exports = {
+	md5 : function(str){
+		return hex_md5(str);
+	}
+}
\ No newline at end of file
diff --git a/uview-ui/libs/function/queryParams.js b/uview-ui/libs/function/queryParams.js
new file mode 100644
index 0000000..81c7e5e
--- /dev/null
+++ b/uview-ui/libs/function/queryParams.js
@@ -0,0 +1,58 @@
+/**
+ * 对象转url参数
+ * @param {*} data,对象
+ * @param {*} isPrefix,是否自动加上"?"
+ */
+function queryParams(data = {}, isPrefix = true, arrayFormat = 'brackets') {
+	let prefix = isPrefix ? '?' : ''
+	let _result = []
+	if (['indices', 'brackets', 'repeat', 'comma'].indexOf(arrayFormat) == -1) arrayFormat = 'brackets';
+	for (let key in data) {
+		let value = data[key]
+		// 去掉为空的参数
+		if (['', undefined, null].indexOf(value) >= 0) {
+			continue;
+		}
+		// 如果值为数组,另行处理
+		if (value.constructor === Array) {
+			// e.g. {ids: [1, 2, 3]}
+			switch (arrayFormat) {
+				case 'indices':
+					// 结果: ids[0]=1&ids[1]=2&ids[2]=3
+					for (let i = 0; i < value.length; i++) {
+						_result.push(key + '[' + i + ']=' + value[i])
+					}
+					break;
+				case 'brackets':
+					// 结果: ids[]=1&ids[]=2&ids[]=3
+					value.forEach(_value => {
+						_result.push(key + '[]=' + _value)
+					})
+					break;
+				case 'repeat':
+					// 结果: ids=1&ids=2&ids=3
+					value.forEach(_value => {
+						_result.push(key + '=' + _value)
+					})
+					break;
+				case 'comma':
+					// 结果: ids=1,2,3
+					let commaStr = "";
+					value.forEach(_value => {
+						commaStr += (commaStr ? "," : "") + _value;
+					})
+					_result.push(key + '=' + commaStr)
+					break;
+				default:
+					value.forEach(_value => {
+						_result.push(key + '[]=' + _value)
+					})
+			}
+		} else {
+			_result.push(key + '=' + value)
+		}
+	}
+	return _result.length ? prefix + _result.join('&') : ''
+}
+
+export default queryParams;
diff --git a/uview-ui/libs/function/random.js b/uview-ui/libs/function/random.js
new file mode 100644
index 0000000..e155279
--- /dev/null
+++ b/uview-ui/libs/function/random.js
@@ -0,0 +1,10 @@
+function random(min, max) {
+	if (min >= 0 && max > 0 && max >= min) {
+		let gab = max - min + 1;
+		return Math.floor(Math.random() * gab + min);
+	} else {
+		return 0;
+	}
+}
+
+export default random;
diff --git a/uview-ui/libs/function/randomArray.js b/uview-ui/libs/function/randomArray.js
new file mode 100644
index 0000000..590a048
--- /dev/null
+++ b/uview-ui/libs/function/randomArray.js
@@ -0,0 +1,7 @@
+// 打乱数组
+function randomArray(array = []) {
+	// 原理是sort排序,Math.random()产生0<= x < 1之间的数,会导致x-0.05大于或者小于0
+	return array.sort(() => Math.random() - 0.5);
+}
+
+export default randomArray
diff --git a/uview-ui/libs/function/route.js b/uview-ui/libs/function/route.js
new file mode 100644
index 0000000..1e39057
--- /dev/null
+++ b/uview-ui/libs/function/route.js
@@ -0,0 +1,85 @@
+import queryParams from '../../libs/function/queryParams.js';
+/**
+ * 路由跳转
+ * 注意:本方法没有对跳转的回调函数进行封装
+ */
+function route(options = {}, params = false) {
+	let config = {
+		type: 'navigateTo',
+		url: '',
+		delta: 1, // navigateBack页面后退时,回退的层数
+		params: {}, // 传递的参数
+		animationType: 'pop-in', // 窗口动画,只在APP有效
+		animationDuration: 300, // 窗口动画持续时间,单位毫秒,只在APP有效
+	};
+	config = Object.assign(config, options);
+	// 如果url没有"/"开头,添加上,因为uni的路由跳转需要"/"开头
+	if (config.url[0] != '/') config.url = '/' + config.url;
+	// 判断是否有传递显式的参数,Object.keys转为数组并判断长度,switchTab类型时不能携带参数
+	if (Object.keys(config.params).length && config.type != 'switchTab') {
+		// 判断用户传递的url中,是否带有参数
+		// 使用正则匹配,主要依据是判断是否有"/","?","="等,如“/page/index/index?name=mary"
+		// 如果有url中有get参数,转换后无需带上"?"
+		let query = '';
+		if (/.*\/.*\?.*=.*/.test(config.url)) {
+			// object对象转为get类型的参数
+			query = queryParams(config.params, false);
+			// 因为已有get参数,所以后面拼接的参数需要带上"&"隔开
+			config.url += "&" + query;
+		} else {
+			query = queryParams(config.params);
+			config.url += query;
+		}
+	}
+	// 简写形式,把url和参数拼接起来
+	if (typeof options === 'string' && typeof params == 'object') {
+		let query = '';
+		if (/.*\/.*\?.*=.*/.test(options)) {
+			// object对象转为get类型的参数
+			query = queryParams(params, false);
+			// 因为已有get参数,所以后面拼接的参数需要带上"&"隔开
+			options += "&" + query;
+		} else {
+			query = queryParams(params);
+			options += query;
+		}
+	}
+	// 判断是否一个字符串,如果是,直接跳转(简写法)
+	// 如果是中情形,默认第二个参数为对象形式的参数
+	if (typeof options === 'string') {
+		if (options[0] != '/') options = '/' + options;
+		return uni.navigateTo({
+			url: options
+		});
+	}
+	// navigateTo类型的跳转
+	if (config.type == 'navigateTo' || config.type == 'to') {
+		return uni.navigateTo({
+			url: config.url,
+			animationType: config.animationType,
+			animationDuration: config.animationDuration,
+		});
+	}
+	if (config.type == 'redirectTo' || config.type == 'redirect') {
+		return uni.redirectTo({
+			url: config.url,
+		});
+	}
+	if (config.type == 'switchTab' || config.type == 'tab') {
+		return uni.switchTab({
+			url: config.url,
+		});
+	}
+	if (config.type == 'reLaunch') {
+		return uni.reLaunch({
+			url: config.url
+		});
+	}
+	if (config.type == 'navigateBack' || config.type == 'back') {
+		return uni.navigateBack({
+			delta: parseInt(config.delta ? config.delta : this.delta)
+		});
+	}
+}
+
+export default route;
diff --git a/uview-ui/libs/function/sys.js b/uview-ui/libs/function/sys.js
new file mode 100644
index 0000000..00f6a28
--- /dev/null
+++ b/uview-ui/libs/function/sys.js
@@ -0,0 +1,9 @@
+export function os() {
+	return uni.getSystemInfoSync().platform;
+};
+
+export function sys() {
+	return uni.getSystemInfoSync();
+}
+
+
diff --git a/uview-ui/libs/function/test.js b/uview-ui/libs/function/test.js
new file mode 100644
index 0000000..b8418a6
--- /dev/null
+++ b/uview-ui/libs/function/test.js
@@ -0,0 +1,232 @@
+/**
+ * 验证电子邮箱格式
+ */
+function email(value) {
+	return /^\w+((-\w+)|(\.\w+))*\@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z0-9]+$/.test(value);
+}
+
+/**
+ * 验证手机格式
+ */
+function mobile(value) {
+	return /^1[23456789]\d{9}$/.test(value)
+}
+
+/**
+ * 验证URL格式
+ */
+function url(value) {
+	return /http(s)?:\/\/([\w-]+\.)+[\w-]+(\/[\w-.\/?%&=]*)?/.test(value)
+}
+
+/**
+ * 验证日期格式
+ */
+function date(value) {
+	return !/Invalid|NaN/.test(new Date(value).toString())
+}
+
+/**
+ * 验证ISO类型的日期格式
+ */
+function dateISO(value) {
+	return /^\d{4}[\/\-](0?[1-9]|1[012])[\/\-](0?[1-9]|[12][0-9]|3[01])$/.test(value)
+}
+
+/**
+ * 验证十进制数字
+ */
+function number(value) {
+	return /^(?:-?\d+|-?\d{1,3}(?:,\d{3})+)?(?:\.\d+)?$/.test(value)
+}
+
+/**
+ * 验证整数
+ */
+function digits(value) {
+	return /^\d+$/.test(value)
+}
+
+/**
+ * 验证身份证号码
+ */
+function idCard(value) {
+	return /^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}([0-9]|X)$/.test(
+		value)
+}
+
+/**
+ * 是否车牌号
+ */
+function carNo(value) {
+	// 新能源车牌
+	const xreg = /^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领A-Z]{1}[A-Z]{1}(([0-9]{5}[DF]$)|([DF][A-HJ-NP-Z0-9][0-9]{4}$))/;
+	// 旧车牌
+	const creg = /^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领A-Z]{1}[A-Z]{1}[A-HJ-NP-Z0-9]{4}[A-HJ-NP-Z0-9挂学警港澳]{1}$/;
+	if (value.length === 7) {
+		return creg.test(value);
+	} else if (value.length === 8) {
+		return xreg.test(value);
+	} else {
+		return false;
+	}
+}
+
+/**
+ * 金额,只允许2位小数
+ */
+function amount(value) {
+	//金额,只允许保留两位小数
+	return /^[1-9]\d*(,\d{3})*(\.\d{1,2})?$|^0\.\d{1,2}$/.test(value);
+}
+
+/**
+ * 中文
+ */
+function chinese(value) {
+	let reg = /^[\u4e00-\u9fa5]+$/gi;
+	return reg.test(value);
+}
+
+/**
+ * 只能输入字母
+ */
+function letter(value) {
+	return /^[a-zA-Z]*$/.test(value);
+}
+
+/**
+ * 只能是字母或者数字
+ */
+function enOrNum(value) {
+	//英文或者数字
+	let reg = /^[0-9a-zA-Z]*$/g;
+	return reg.test(value);
+}
+
+/**
+ * 验证是否包含某个值
+ */
+function contains(value, param) {
+	return value.indexOf(param) >= 0
+}
+
+/**
+ * 验证一个值范围[min, max]
+ */
+function range(value, param) {
+	return value >= param[0] && value <= param[1]
+}
+
+/**
+ * 验证一个长度范围[min, max]
+ */
+function rangeLength(value, param) {
+	return value.length >= param[0] && value.length <= param[1]
+}
+
+/**
+ * 是否固定电话
+ */
+function landline(value) {
+	let reg = /^\d{3,4}-\d{7,8}(-\d{3,4})?$/;
+	return reg.test(value);
+}
+
+/**
+ * 判断是否为空
+ */
+function empty(value) {
+	switch (typeof value) {
+		case 'undefined':
+			return true;
+		case 'string':
+			if (value.replace(/(^[ \t\n\r]*)|([ \t\n\r]*$)/g, '').length == 0) return true;
+			break;
+		case 'boolean':
+			if (!value) return true;
+			break;
+		case 'number':
+			if (0 === value || isNaN(value)) return true;
+			break;
+		case 'object':
+			if (null === value || value.length === 0) return true;
+			for (var i in value) {
+				return false;
+			}
+			return true;
+	}
+	return false;
+}
+
+/**
+ * 是否json字符串
+ */
+function jsonString(value) {
+	if (typeof value == 'string') {
+		try {
+			var obj = JSON.parse(value);
+			if (typeof obj == 'object' && obj) {
+				return true;
+			} else {
+				return false;
+			}
+		} catch (e) {
+			return false;
+		}
+	}
+	return false;
+}
+
+
+/**
+ * 是否数组
+ */
+function array(value) {
+	if (typeof Array.isArray === "function") {
+		return Array.isArray(value);
+	} else {
+		return Object.prototype.toString.call(value) === "[object Array]";
+	}
+}
+
+/**
+ * 是否对象
+ */
+function object(value) {
+	return Object.prototype.toString.call(value) === '[object Object]';
+}
+
+/**
+ * 是否短信验证码
+ */
+function code(value, len = 6) {
+	return new RegExp(`^\\d{${len}}$`).test(value);
+}
+
+
+export default {
+	email,
+	mobile,
+	url,
+	date,
+	dateISO,
+	number,
+	digits,
+	idCard,
+	carNo,
+	amount,
+	chinese,
+	letter,
+	enOrNum,
+	contains,
+	range,
+	rangeLength,
+	empty,
+	isEmpty: empty,
+	jsonString,
+	landline,
+	object,
+	array,
+	code
+}
diff --git a/uview-ui/libs/function/throttle.js b/uview-ui/libs/function/throttle.js
new file mode 100644
index 0000000..ad830b2
--- /dev/null
+++ b/uview-ui/libs/function/throttle.js
@@ -0,0 +1,32 @@
+let timer, flag;
+/**
+ * 节流原理:在一定时间内,只能触发一次
+ * 
+ * @param {Function} func 要执行的回调函数 
+ * @param {Number} wait 延时的时间
+ * @param {Boolean} immediate 是否立即执行
+ * @return null
+ */
+function throttle(func, wait = 500, immediate = true) {
+	if (immediate) {
+		if (!flag) {
+			flag = true;
+			// 如果是立即执行,则在wait毫秒内开始时执行
+			typeof func === 'function' && func();
+			timer = setTimeout(() => {
+				flag = false;
+			}, wait);
+		}
+	} else {
+		if (!flag) {
+			flag = true
+			// 如果是非立即执行,则在wait毫秒内的结束处执行
+			timer = setTimeout(() => {
+				flag = false
+				typeof func === 'function' && func();
+			}, wait);
+		}
+		
+	}
+};
+export default throttle
diff --git a/uview-ui/libs/function/timeFormat.js b/uview-ui/libs/function/timeFormat.js
new file mode 100644
index 0000000..1238010
--- /dev/null
+++ b/uview-ui/libs/function/timeFormat.js
@@ -0,0 +1,52 @@
+// padStart 的 polyfill,因为某些机型或情况,还无法支持es7的padStart,比如电脑版的微信小程序
+// 所以这里做一个兼容polyfill的兼容处理
+if (!String.prototype.padStart) {
+	// 为了方便表示这里 fillString 用了ES6 的默认参数,不影响理解
+	String.prototype.padStart = function(maxLength, fillString = ' ') {
+		if (Object.prototype.toString.call(fillString) !== "[object String]") throw new TypeError(
+			'fillString must be String')
+		let str = this
+		// 返回 String(str) 这里是为了使返回的值是字符串字面量,在控制台中更符合直觉
+		if (str.length >= maxLength) return String(str)
+
+		let fillLength = maxLength - str.length,
+			times = Math.ceil(fillLength / fillString.length)
+		while (times >>= 1) {
+			fillString += fillString
+			if (times === 1) {
+				fillString += fillString
+			}
+		}
+		return fillString.slice(0, fillLength) + str;
+	}
+}
+
+function timeFormat(timestamp = null, fmt = 'yyyy-mm-dd') {
+	// 其他更多是格式化有如下:
+	// yyyy:mm:dd|yyyy:mm|yyyy年mm月dd日|yyyy年mm月dd日 hh时MM分等,可自定义组合
+	timestamp = parseInt(timestamp);
+	// 如果为null,则格式化当前时间
+	if (!timestamp) timestamp = Number(new Date());
+	// 判断用户输入的时间戳是秒还是毫秒,一般前端js获取的时间戳是毫秒(13位),后端传过来的为秒(10位)
+	if (timestamp.toString().length == 10) timestamp *= 1000;
+	let date = new Date(timestamp);
+	let ret;
+	let opt = {
+		"y+": date.getFullYear().toString(), // 年
+		"m+": (date.getMonth() + 1).toString(), // 月
+		"d+": date.getDate().toString(), // 日
+		"h+": date.getHours().toString(), // 时
+		"M+": date.getMinutes().toString(), // 分
+		"s+": date.getSeconds().toString() // 秒
+		// 有其他格式化字符需求可以继续添加,必须转化成字符串
+	};
+	for (let k in opt) {
+		ret = new RegExp("(" + k + ")").exec(fmt);
+		if (ret) {
+			fmt = fmt.replace(ret[1], (ret[1].length == 1) ? (opt[k]) : (opt[k].padStart(ret[1].length, "0")))
+		};
+	};
+	return fmt;
+}
+
+export default timeFormat
diff --git a/uview-ui/libs/function/timeFrom.js b/uview-ui/libs/function/timeFrom.js
new file mode 100644
index 0000000..52d858e
--- /dev/null
+++ b/uview-ui/libs/function/timeFrom.js
@@ -0,0 +1,46 @@
+import timeFormat from '../../libs/function/timeFormat.js';
+
+/**
+ * 时间戳转为多久之前
+ * @param String timestamp 时间戳
+ * @param String | Boolean format 如果为时间格式字符串,超出一定时间范围,返回固定的时间格式;
+ * 如果为布尔值false,无论什么时间,都返回多久以前的格式
+ */
+function timeFrom(timestamp = null, format = 'yyyy-mm-dd') {
+	if (timestamp == null) timestamp = Number(new Date());
+	timestamp = parseInt(timestamp);
+	// 判断用户输入的时间戳是秒还是毫秒,一般前端js获取的时间戳是毫秒(13位),后端传过来的为秒(10位)
+	if (timestamp.toString().length == 10) timestamp *= 1000;
+	var timer = (new Date()).getTime() - timestamp;
+	timer = parseInt(timer / 1000);
+	// 如果小于5分钟,则返回"刚刚",其他以此类推
+	let tips = '';
+	switch (true) {
+		case timer < 300:
+			tips = '刚刚';
+			break;
+		case timer >= 300 && timer < 3600:
+			tips = parseInt(timer / 60) + '分钟前';
+			break;
+		case timer >= 3600 && timer < 86400:
+			tips = parseInt(timer / 3600) + '小时前';
+			break;
+		case timer >= 86400 && timer < 2592000:
+			tips = parseInt(timer / 86400) + '天前';
+			break;
+		default:
+			// 如果format为false,则无论什么时间戳,都显示xx之前
+			if(format === false) {
+				if(timer >= 2592000 && timer < 365 * 86400) {
+					tips = parseInt(timer / (86400 * 30)) + '个月前';
+				} else {
+					tips = parseInt(timer / (86400 * 365)) + '年前';
+				}
+			} else {
+				tips = timeFormat(timestamp, format);
+			}
+	}
+	return tips;
+}
+
+export default timeFrom;
diff --git a/uview-ui/libs/function/toast.js b/uview-ui/libs/function/toast.js
new file mode 100644
index 0000000..91afa73
--- /dev/null
+++ b/uview-ui/libs/function/toast.js
@@ -0,0 +1,9 @@
+function toast(title, duration = 1500) {
+	uni.showToast({
+		title: title,
+		icon: 'none',
+		duration: duration
+	})
+}
+
+export default toast
diff --git a/uview-ui/libs/function/trim.js b/uview-ui/libs/function/trim.js
new file mode 100644
index 0000000..72adc37
--- /dev/null
+++ b/uview-ui/libs/function/trim.js
@@ -0,0 +1,15 @@
+function trim(str, pos = 'both') {
+	if (pos == 'both') {
+		return str.replace(/^\s+|\s+$/g, "");
+	} else if (pos == "left") {
+		return str.replace(/^\s*/, '');
+	} else if (pos == 'right') {
+		return str.replace(/(\s*$)/g, "");
+	} else if (pos == 'all') {
+		return str.replace(/\s+/g, "");
+	} else {
+		return str;
+	}
+}
+
+export default trim
diff --git a/uview-ui/libs/function/type2icon.js b/uview-ui/libs/function/type2icon.js
new file mode 100644
index 0000000..23cb40e
--- /dev/null
+++ b/uview-ui/libs/function/type2icon.js
@@ -0,0 +1,35 @@
+/**
+ * 根据主题type值,获取对应的图标
+ * @param String type 主题名称,primary|info|error|warning|success
+ * @param String fill 是否使用fill填充实体的图标  
+ */
+function type2icon(type = 'success', fill = false) {
+	// 如果非预置值,默认为success
+	if (['primary', 'info', 'error', 'warning', 'success'].indexOf(type) == -1) type = 'success';
+	let iconName = '';
+	// 目前(2019-12-12),info和primary使用同一个图标
+	switch (type) {
+		case 'primary':
+			iconName = 'info-circle';
+			break;
+		case 'info':
+			iconName = 'info-circle';
+			break;
+		case 'error':
+			iconName = 'close-circle';
+			break;
+		case 'warning':
+			iconName = 'error-circle';
+			break;
+		case 'success':
+			iconName = 'checkmark-circle';
+			break;
+		default:
+			iconName = 'checkmark-circle';
+	}
+	// 是否是实体类型,加上-fill,在icon组件库中,实体的类名是后面加-fill的
+	if (fill) iconName += '-fill';
+	return iconName;
+}
+
+export default type2icon