chubiao преди 1 година
родител
ревизия
fa1bf444d5
променени са 43 файла, в които са добавени 9035 реда и са изтрити 36 реда
  1. 11 11
      App.vue
  2. 27 0
      api/kh.js
  3. 6 0
      pages.json
  4. 34 12
      pages/info/add-files.vue
  5. 48 0
      pages/living/check.vue
  6. 1 1
      pages/login/index.vue
  7. 27 4
      pages/lr/info.vue
  8. 5 5
      pages/lr/list.vue
  9. 1 1
      pages/my/index.vue
  10. 56 2
      pages/test/index.vue
  11. 50 0
      uni_modules/leven-js-tools/changelog.md
  12. 95 0
      uni_modules/leven-js-tools/index.js
  13. 210 0
      uni_modules/leven-js-tools/js_sdk/array/index.js
  14. 138 0
      uni_modules/leven-js-tools/js_sdk/color/index.js
  15. 319 0
      uni_modules/leven-js-tools/js_sdk/date/index.js
  16. 190 0
      uni_modules/leven-js-tools/js_sdk/encrypt/index.js
  17. 105 0
      uni_modules/leven-js-tools/js_sdk/func/funcManager.js
  18. 155 0
      uni_modules/leven-js-tools/js_sdk/number/index.js
  19. 238 0
      uni_modules/leven-js-tools/js_sdk/object/index.js
  20. 16 0
      uni_modules/leven-js-tools/js_sdk/request/index.js
  21. 132 0
      uni_modules/leven-js-tools/js_sdk/request/luch-request/adapters/index.js
  22. 51 0
      uni_modules/leven-js-tools/js_sdk/request/luch-request/core/InterceptorManager.js
  23. 201 0
      uni_modules/leven-js-tools/js_sdk/request/luch-request/core/Request.js
  24. 20 0
      uni_modules/leven-js-tools/js_sdk/request/luch-request/core/buildFullPath.js
  25. 33 0
      uni_modules/leven-js-tools/js_sdk/request/luch-request/core/defaults.js
  26. 6 0
      uni_modules/leven-js-tools/js_sdk/request/luch-request/core/dispatchRequest.js
  27. 126 0
      uni_modules/leven-js-tools/js_sdk/request/luch-request/core/mergeConfig.js
  28. 16 0
      uni_modules/leven-js-tools/js_sdk/request/luch-request/core/settle.js
  29. 64 0
      uni_modules/leven-js-tools/js_sdk/request/luch-request/helpers/buildURL.js
  30. 14 0
      uni_modules/leven-js-tools/js_sdk/request/luch-request/helpers/combineURLs.js
  31. 14 0
      uni_modules/leven-js-tools/js_sdk/request/luch-request/helpers/isAbsoluteURL.js
  32. 197 0
      uni_modules/leven-js-tools/js_sdk/request/luch-request/index.d.ts
  33. 2 0
      uni_modules/leven-js-tools/js_sdk/request/luch-request/index.js
  34. 135 0
      uni_modules/leven-js-tools/js_sdk/request/luch-request/utils.js
  35. 264 0
      uni_modules/leven-js-tools/js_sdk/request/luch-request/utils/clone.js
  36. 331 0
      uni_modules/leven-js-tools/js_sdk/string/index.js
  37. 137 0
      uni_modules/leven-js-tools/js_sdk/timer/index.js
  38. 1 0
      uni_modules/leven-js-tools/js_sdk/utils/crypto-js-4.1.1.min.js.js
  39. 4934 0
      uni_modules/leven-js-tools/js_sdk/utils/decimal.js
  40. 167 0
      uni_modules/leven-js-tools/js_sdk/utils/digit.js
  41. 251 0
      uni_modules/leven-js-tools/js_sdk/validate/index.js
  42. 84 0
      uni_modules/leven-js-tools/package.json
  43. 123 0
      uni_modules/leven-js-tools/readme.md

+ 11 - 11
App.vue

@@ -5,18 +5,18 @@
 	} from '@/common/auth.js'
 	export default {
 		onLaunch: function() {
-			if (getToken()) {
-				console.log('存在');
-				uni.reLaunch({
-					url: '/pages/index/index'
-				})
+			// if (getToken()) {
+			// 	console.log('存在');
+			// 	uni.reLaunch({
+			// 		url: '/pages/index/index'
+			// 	})
 
-			} else {
-				console.log('不存在');
-				uni.reLaunch({
-					url: '/pages/login/index'
-				})
-			}
+			// } else {
+			// 	console.log('不存在');
+			// 	uni.reLaunch({
+			// 		url: '/pages/login/index'
+			// 	})
+			// }
 			// routingIntercept()
 			console.log('App Launch')
 		},

+ 27 - 0
api/kh.js

@@ -106,4 +106,31 @@ export function CheckReturn(data) {
 		method: 'post',
 		data: data
 	})
+}
+
+
+export function YlhtAdd(data) {
+	return request({
+		url: '/api/lnst/ylht',
+		method: 'post',
+		data: data
+	})
+}
+
+
+export function YlhtUpdate(data) {
+	return request({
+		url: '/api/lnst/ylht',
+		method: 'put',
+		data: data
+	})
+}
+
+
+export function GetUrl(data) {
+	return request({
+		url: '/api/lnst/lrxx/getUrl',
+		method: 'post',
+		data: data
+	})
 }

+ 6 - 0
pages.json

@@ -41,6 +41,12 @@
 				// "onReachBottomDistance": 100 //距离底部100像素时,触发加载更多功能
 			}
 		},
+		{
+			"path": "pages/living/check",
+			"style": {
+				"navigationBarTitleText": "认证"
+			}
+		},
 		{
 			"path": "pages/living/success",
 			"style": {

+ 34 - 12
pages/info/add-files.vue

@@ -43,8 +43,8 @@
 							placeholder="请输入监护人联系电话" :inputBorder="true"></uni-easyinput>
 					</uni-forms-item>
 					<uni-forms-item label="街道社区">
-						<uni-easyinput type="text" v-model="diqu" @focus="toggle('bottom')"
-							placeholder="请选择街道社区" :clearable="false"></uni-easyinput>
+						<uni-easyinput type="text" v-model="diqu" @focus="toggle('bottom')" placeholder="请选择街道社区"
+							:clearable="false"></uni-easyinput>
 
 
 					</uni-forms-item>
@@ -181,7 +181,10 @@
 		updateKhjbxx,
 		infoKhjbxx,
 		GetLrByZjhm,
-		SaveKhjbxx
+		SaveKhjbxx,
+		YlhtUpdate,
+		CheckReturn,
+		GetUrl
 	} from '@/api/kh.js'
 	export default {
 		components: {
@@ -433,7 +436,7 @@
 						// 后端没入库,人脸库相应删除
 						// ocr失败身份证原版入库,ocr成功人脸入库
 						// showConfirm('人像与身份证不符,请重新上传')
-						
+
 						// this.baseFormData.lzzt = 1
 						// this.baseFormData.lrSpyj = ''
 						this.baseFormData.lzzt = 0
@@ -818,30 +821,49 @@
 
 							that.$refs['baseForm'].validate().then(res => {
 								if (that.updateFlag) {
+									// todo 
+									// that.baseFormData.lzzt = 1
 									updateKhjbxx(that.baseFormData).then(r => {
 										uni.hideLoading()
 										if (r.code == 200) {
-											toast('保存成功')
+											
+
+											// todo 
+											// CheckReturn({
+											// 	ylid: that.baseFormData.id
+											// }).then(rr => {
+											// 	console.log("wwwwwwwwwwwwww",res);
+											// 	// todo
+											// 	YlhtUpdate({
+											// 		id: that.baseFormData.id,
+											// 		lzzt: that.baseFormData.lzzt
+											// 	}).then(rrr => {
+
+											// 	})
+											// })
+											toast('保存成功,正在前往刷脸激活')
 											setTimeout(function() {
 												uni.switchTab({
 													url: '/pages/index/index'
 												})
-											}, 1000)
+											}, 2000)
 										}
 									})
 								} else {
+									// that.baseFormData.lzzt = 1
 									SaveKhjbxx(that.baseFormData).then(r => {
 										uni.hideLoading()
 										if (r.code == 200) {
-											toast('保存成功')
+											toast('保存成功,正在前往刷脸激活')
+											that.baseFormData.id = r.data
 											// setOpenid(r.data.openId)
 											// setUser(r.data.sysUser)
 											// setToken(r.data.token.access_token)
 											setTimeout(function() {
-												uni.switchTab({
-													url: '/pages/index/index'
-												})
-											}, 1000)
+												
+												
+												
+											}, 2000)
 										}
 									})
 								}
@@ -908,7 +930,7 @@
 		display: flex;
 		align-items: center;
 		justify-content: center;
-		box-shadow:0rpx 4rpx 10rpx 1rpx rgba(40, 216, 125,0.4);
+		box-shadow: 0rpx 4rpx 10rpx 1rpx rgba(40, 216, 125, 0.4);
 	}
 
 	.picker-view {

+ 48 - 0
pages/living/check.vue

@@ -0,0 +1,48 @@
+<template>
+	<view>
+		<button @click="zhuce">注册ylht</button>
+		<button @click="success">成功</button>
+		<button @click="fail">失败</button>
+		<button @click="huidiao">回调</button>
+	</view>
+</template>
+
+<script>
+	export default {
+		name: "my-file",
+		data() {
+			return {
+			};
+		},
+		watch: {
+
+		},
+		mounted() {
+
+		},
+		methods: {
+			zhuce() {
+
+			},
+			success() {
+				uni.navigateTo({
+					url: '/pages/living/success'
+				})
+
+			},
+			fail() {
+				uni.navigateTo({
+					url: '/pages/living/fail'
+				})
+			},
+			huidiao() {
+
+			}
+
+		}
+	}
+</script>
+
+<style>
+
+</style>

+ 1 - 1
pages/login/index.vue

@@ -96,7 +96,7 @@
 					username: '',
 					password: '',
 					// code: "081X2kll21UGPc4HRlml27WxeO3X2kl6",
-					username: '15143018065',
+					username: '15143018068',
 					password: 'sckj12356',
 					openid: "",
 				},

+ 27 - 4
pages/lr/info.vue

@@ -39,8 +39,8 @@
 							:inputBorder="true"></uni-easyinput>
 					</uni-forms-item>
 					<uni-forms-item label="街道社区">
-						<uni-easyinput type="text" v-model="diqu" @focus="toggle('bottom')"
-							placeholder="请选择街道社区" :clearable="false"></uni-easyinput>
+						<uni-easyinput type="text" v-model="diqu" @focus="toggle('bottom')" placeholder="请选择街道社区"
+							:clearable="false"></uni-easyinput>
 
 
 					</uni-forms-item>
@@ -75,6 +75,7 @@
 					</uni-forms-item>
 
 					<view>
+						<button cursor-spacing="22px" class="buttonClass" @click="ht()">刷脸激活</button>
 						<button cursor-spacing="22px" class="buttonClass" @click="preSave()">修改</button>
 					</view>
 				</uni-forms>
@@ -155,7 +156,8 @@
 		updateKhjbxx,
 		infoKhjbxx,
 		GetLrByZjhm,
-		SaveKhjbxx
+		SaveKhjbxx,
+		GetUrl
 	} from '@/api/kh.js'
 	export default {
 		components: {
@@ -313,6 +315,27 @@
 			this.id = o.id
 		},
 		methods: {
+			ht() {
+				GetUrl({
+					id: this.baseFormData.id,
+					url: 'https://www.ccsckj.com/'
+				}).then(res => {
+					console.log("1111111", res);
+					if (res.code == 200) {
+						console.log("2222222222", res);
+						uni.request({
+							url: res.data.url
+						}).then(rr => {
+							console.log("333333", rr);
+						})
+					} else {
+						toast('该功能暂未开放')
+					}
+
+
+
+				})
+			},
 			showInfo(id) {
 				infoKhjbxx(id).then(res => {
 					if (res.data) this.baseFormData = decryptData_ECB(res.data, ["lrZjhm", "lrXm",
@@ -609,7 +632,7 @@
 											// uni.switchTab({
 											// 	url: '/pages/index/index'
 											// })
-											
+
 											uni.navigateBack()
 										}, 1000)
 									}

+ 5 - 5
pages/lr/list.vue

@@ -9,25 +9,25 @@
 					<template v-slot:footer>
 						<view v-if="item.lzzt == '0'"
 							style="width: 60px;display: flex;flex-direction: column;background-image: url('../../static/images/caogao.png');background-position: left;background-size:58px 58px;background-repeat: no-repeat;">
-							<text v-if="item.updateTime">{{item.updateTime.substring(0,8) }}</text>
+							<text v-if="item.jssj">{{item.jssj.substring(0,8) }}</text>
 							<text v-else>{{item.createTime.substring(0,8) }}</text>
 							<text>{{item.lrSpyj || '无'}}</text>
 						</view>
 						<view v-else-if="item.lzzt == '1' || item.lzzt == '2' || item.lzzt == '5'|| item.lzzt == '7'"
 							style="width: 60px;display: flex;flex-direction: column;background-image: url('../../static/images/daishenhe.png');background-position: left;background-size:58px 58px;background-repeat: no-repeat;">
-							<text v-if="item.updateTime">{{item.updateTime.substring(0,8) }}</text>
+							<text v-if="item.jssj">{{item.jssj.substring(0,8) }}</text>
 							<text v-else>{{item.createTime.substring(0,8) }}</text>
 							<text>{{item.lrSpyj || '无'}}</text>
 						</view>
 						<view v-else-if="item.lzzt == '3'"
 							style="width: 60px;display: flex;flex-direction: column;background-image: url('../../static/images/tongguo.png');background-position: left;background-size:58px 58px;background-repeat: no-repeat;">
-							<text v-if="item.updateTime">{{item.updateTime.substring(0,8) }}</text>
+							<text v-if="item.jssj">{{item.jssj.substring(0,8) }}</text>
 							<text v-else>{{item.createTime.substring(0,8) }}</text>
 							<text>{{item.lrSpyj || '无'}}</text>
 						</view>
 						<view v-else-if="item.lzzt == '4'"
 							style="width: 60px;display: flex;flex-direction: column;background-image: url('../../static/images/jujue.png');background-position: left;background-size:58px 58px;background-repeat: no-repeat;">
-							<text v-if="item.updateTime">{{item.updateTime.substring(0,8) }}</text>
+							<text v-if="item.jssj">{{item.jssj.substring(0,8) }}</text>
 							<text v-else>{{item.createTime.substring(0,8) }}</text>
 							<text>{{item.lrSpyj || '无'}}</text>
 						</view>
@@ -67,7 +67,7 @@
 		mounted() {
 			this.userInfo = getUser()
 			if (this.userInfo.userType != '07') {
-				// this.form.createUserId = this.userInfo.userId
+				this.form.createUserId = this.userInfo.userId
 			}
 			this.getList()
 		},

+ 1 - 1
pages/my/index.vue

@@ -3,7 +3,7 @@
 		<uni-card>
 			<!-- 	<uni-list-item title="操作手册" showExtraIcon="true" :extra-icon="list" showArrow
 				to="/pages/my/updatePwd" /> -->
-			<uni-list-item title="活体激活" showExtraIcon="true" :extra-icon="cameraExtraIcon" showArrow to="/pages/test/index" />
+			<uni-list-item title="活体激活" showExtraIcon="true" :extra-icon="cameraExtraIcon" showArrow to="/pages/living/check" />
 			<uni-list-item title="修改密码" showExtraIcon="true" :extra-icon="extraIcon" showArrow
 				to="/pages/my/updatePwd" />
 			<view @click="goOut">

+ 56 - 2
pages/test/index.vue

@@ -4,10 +4,12 @@
 		<button @click="success">成功</button>
 		<button @click="fail">失败</button>
 		<button @click="huidiao">回调</button>
+
 	</view>
 </template>
 
 <script>
+	import jsTools from "uni_modules/leven-js-tools/index.js"
 	export default {
 		name: "my-file",
 		data() {
@@ -24,8 +26,62 @@
 
 		},
 		methods: {
+			huidiao() {
+				let url = "https://test-api-open.chinaums.com/v1/visual-ai/faceliveness/detect"
+				let appKey = '5a735c9a42d1401da0e39516f2b3bef7'
+				let desKey = 'A5D37C3D8502D503CC7B1EB62CEF4B79'
+				let authorization = "OPEN-FORM-PARAM"
+				let appId = "10037e6f6394f6e70163a6782676007d"
+				let timestamp = '20240325153744'
+				// let nonce = new Date().getTime()
+				let nonce = '20240325153744'
+				let content = ''
+				// {
+				// 	returnUrl: 'https://www.ccsckj.com/',
+				// 	type: 'action'
+				// }
+				// Base64_Encode(HmacSHA256(appId + timestamp + nonce + SHA256_HEX(content), AppKey))
+				let signature = uni.$lv.encrypt.base64Encode(uni.$lv.encrypt.hmacSha256(appId + timestamp + nonce + uni.$lv
+					.encrypt.sha256(content), appKey))
+
+
+				console.log("url:", url);
+				console.log("appKey:", appKey);
+				console.log("desKey:", desKey);
+				console.log("authorization:", authorization);
+				console.log("appId:", appId);
+				console.log("timestamp:", timestamp);
+				console.log("nonce:", nonce);
+				console.log("content:", content);
+				console.log("content111:", uni.$lv.encrypt.sha256(content));
+				console.log("signature:", signature);
+
+
+				uni.request({
+					url: url + '?authorization=' + authorization + "&appId=" + appId + "&timestamp=" + timestamp +
+						"&nonce=" + nonce + "&content=" + content + "&signature=" + signature,
+					method: 'GET',
+				}).then(res => {
+					console.log(res);
+				})
+
+
+
+			},
 			zhuce() {
+				// todo 3DES
+				let result = uni.$lv.encrypt.hmacSha256("abcdefg123456这是一条加密字符串7892345",
+					"u$DCc!tjdYn%wP!hE3Ya%qVCWKUX9p4N");
+
+				console.log("HmacSHA256:", result);
+				result = uni.$lv.encrypt.sha256("abcdefg123456这是一条加密字符串7892345");
+				console.log("SHA256_HEX:", result);
+				result = uni.$lv.encrypt.base64Encode("KNGT^$Sat#je5VX9Hdp3Y@kLUTegwg82这是一条加密字符串");
+				console.log("Base64_Encode:", result);
 
+				result = uni.$lv.validate.isWechat();
+				uni.$lv.func.toast(result);
+				console.log("微信:", result);
 			},
 			success() {
 				uni.navigateTo({
@@ -38,9 +94,7 @@
 					url: '/pages/living/fail'
 				})
 			},
-			huidiao() {
 
-			}
 
 		}
 	}

+ 50 - 0
uni_modules/leven-js-tools/changelog.md

@@ -0,0 +1,50 @@
+## 1.1.6(2023-09-12)
+* 【新增】加多少天后的日期
+* 【新增】减多少天后的日期
+## 1.1.5(2023-08-17)
+## 字符串部分新增以下内容
+* 字符串转十六进制,新增参数:是否UrlEncode
+* 十六进制转字符串,新增参数:是否UrlDecode
+## 1.1.4(2023-06-06)
+## 数字部分新增以下内容
+* 高精度加法
+* 高精度减法
+* 高精度乘法
+* 高精度除法
+## 1.1.3(2023-05-30)
+更新luch-request版本至3.1.0
+## 1.1.2(2023-05-11)
+新增以下功能:
+字符串
+1.转大写
+2.转小写
+3.下划线转驼峰
+4.驼峰转下划线
+5.分解url地址
+6.将字符串转换为16进制
+7.十六进制转换为字符串
+数组
+1.求和
+## 1.1.1(2023-05-09)
+定时器
+1.新增设置一个定时器
+验证
+1.新增验证是否是微信浏览器
+2.新增验证是否是支付宝浏览器
+
+## 1.1.0(2023-05-04)
+新增以下功能:
+日期
+1.两个日期之间的天数
+2.某个月有多少天
+3.两个日期之间的所有日期
+数字
+1.金额转大写
+颜色
+1.生成随机颜色
+字符串
+1.随机字符串
+## 1.0.1(2023-04-28)
+对象新增按键名排序
+## 1.0.0(2023-04-26)
+首次发布

+ 95 - 0
uni_modules/leven-js-tools/index.js

@@ -0,0 +1,95 @@
+/**
+ * 主管理容器
+ */
+// 数组管理器
+import {
+  ArrayManager
+} from "./js_sdk/array/index.js"
+// 加解密管理类
+import {
+  EncryptManager
+} from "./js_sdk/encrypt/index.js"
+// 数字管理类
+import {
+  NumberManager
+} from "./js_sdk/number/index.js"
+// 对象管理类
+import {
+  ObjectManager
+} from "./js_sdk/object/index.js"
+// 请求管理类
+import {
+  RequestManager
+} from "./js_sdk/request/index.js"
+// 字符串管理
+import {
+  StringManager
+} from "./js_sdk/string/index.js"
+// 验证管理
+import {
+  ValidateManager
+} from "./js_sdk/validate/index.js"
+// 定时任务管理
+import {
+  TimerManager
+} from "./js_sdk/timer/index.js"
+// 日期管理
+import {
+  DateManager
+} from "./js_sdk/date/index.js"
+// 颜色相关
+import {
+  ColorManager
+} from "./js_sdk/color/index.js"
+// 函数
+import {
+  FuncManager
+} from "./js_sdk/func/funcManager.js"
+
+// 数组管理
+let arrayManager = new ArrayManager();
+// 加解密管理
+let encryptManager = new EncryptManager();
+// 数字管理
+let numberManager = new NumberManager();
+// 对象管理类
+let objectManager = new ObjectManager();
+// 请求管理类
+let requestManager = new RequestManager();
+// 字符串管理
+let stringManager = new StringManager();
+// 验证管理
+let validateManager = new ValidateManager();
+// 定时任务管理
+let timerManager = new TimerManager();
+// 日期管理
+let dateManager = new DateManager();
+// 颜色相关
+let colorManager = new ColorManager();
+// 函数相关
+let funcManager = new FuncManager();
+
+const $lv = {
+  array: arrayManager,
+  encrypt: encryptManager,
+  number: numberManager,
+  object: objectManager,
+  request: requestManager.request(),
+  string: stringManager,
+  validate: validateManager,
+  timer: timerManager,
+  date: dateManager,
+  color: colorManager,
+  func: funcManager
+}
+
+// 挂载到uni对象
+uni.$lv = $lv;
+
+const install = (Vue) => {
+  Vue.prototype.$lv = $lv;
+}
+
+export default {
+  install
+}

+ 210 - 0
uni_modules/leven-js-tools/js_sdk/array/index.js

@@ -0,0 +1,210 @@
+/**
+ * 数组类
+ */
+export class ArrayManager {
+  constructor() {}
+
+  /**
+   * 数字类型数组排序
+   * @param arr 数组
+   * @param type  排序方式,asc:升序,desc:降序
+   * 
+   * @default asc
+   */
+  sort = (arr, type = "asc") => {
+    let arrNew = JSON.parse(JSON.stringify(arr));
+    arrNew.sort((a, b) => {
+      if (type == "asc") {
+        return a - b
+      } else {
+        return b - a
+      }
+    })
+    return arrNew;
+  }
+
+  /**
+   * 数组分割
+   * @param arr 要处理的数组
+   * @param len 分割长度
+   */
+  split = (arr, len) => {
+    if (len == 0) {
+      return arr;
+    }
+    let ret = []
+    for (let i = 0; i < arr.length; i += len) {
+      ret.push(arr.slice(i, i + len))
+    }
+    return ret
+  }
+
+  /**
+   * 判断两个数组的数据是否相同
+   * @param arr1  第一个数组
+   * @param arr2  第二个数组
+   * 
+   * @@return {true/false}
+   */
+  isSame = (arr1, arr2) => {
+    let newArr1 = JSON.parse(JSON.stringify(arr1));
+    let newArr2 = JSON.parse(JSON.stringify(arr2));
+    let arr1Sort = newArr1.sort().toString();
+    let arr2Sort = newArr2.sort().toString();
+    var c = newArr1.length === newArr2.length && arr1Sort === arr2Sort
+    return c;
+  }
+
+  /**
+   * 移除数组中的元素
+   * @param arr 要操作的数组
+   * @param value 要移除的值
+   * 
+   * @@return {Array} 移除元素后的数组
+   */
+  remove = (arr, value) => {
+    let newArr = JSON.parse(JSON.stringify(arr));
+    let indexOf = newArr.indexOf(value);
+    if (indexOf >= 0) {
+      newArr.splice(indexOf, 1)
+    }
+    return newArr;
+  }
+
+  /**
+   * 添加新元素到指定位置
+   */
+  add = (arr, index, value) => {
+    let newArr = JSON.parse(JSON.stringify(arr));
+    newArr.splice(index, 0, value);
+    return newArr;
+  }
+
+  /**
+   * 数组中的最大值
+   */
+  max = (arr) => {
+    let newArr = JSON.parse(JSON.stringify(arr));
+    newArr.sort((a, b) => {
+      return b - a
+    })
+    return newArr[0];
+  }
+
+  /**
+   * 数组中的最小值
+   */
+  min = (arr) => {
+    let newArr = JSON.parse(JSON.stringify(arr));
+    newArr.sort((a, b) => {
+      return a - b
+    })
+    return newArr[0];
+  }
+
+  /**
+   * 数组打乱
+   */
+  disruption = (arr) => {
+    return arr.sort(() => Math.random() - 0.5);
+  }
+
+  /**
+   * 随机取值
+   * @param arr 数组
+   * @param length 取出的长度
+   * @param isSame  是否可以相同
+   */
+  random = (arr, length = 1, isSame = false) => {
+    if (arr.length <= length) {
+      return arr;
+    }
+    let copyArr = JSON.parse(JSON.stringify(arr));
+    let newArr = []; //创建一个新数组
+    for (let i = 0; i < length; i++) {
+      let temp = Math.floor(Math.random() * copyArr.length); //取随机下标
+      newArr.push(copyArr[temp]); //添加到新数组
+      if (!isSame) {
+        copyArr.splice(temp, 1) //删除当前的数组元素,避免重复
+      }
+    }
+    return newArr;
+  }
+
+  /**
+   * 去重
+   */
+  unique = (arr) => {
+    let copyArr = JSON.parse(JSON.stringify(arr));
+    if (Array.hasOwnProperty('from')) {
+      return Array.from(new Set(copyArr));
+    } else {
+      var n = {},
+        r = [];
+      for (var i = 0; i < copyArr.length; i++) {
+        if (!n[copyArr[i]]) {
+          n[copyArr[i]] = true;
+          r.push(copyArr[i]);
+        }
+      }
+      return r;
+    }
+  }
+
+  /**
+   * 合并去重
+   */
+  union = (arr, arr2) => {
+    var newArr = arr.concat(arr2);
+    return this.unique(newArr);
+  }
+
+  /**
+   * 取交集
+   */
+  intersect = (arr, arr2) => {
+    arr = this.unique(arr);
+    let newArr = [];
+    for (let i = 0; i < arr.length; i++) {
+      if (arr2.includes(arr[i])) {
+        newArr.push(arr[i])
+      }
+    }
+    return newArr;
+  }
+
+  /**
+   * 是否是数组
+   */
+  isArray(value) {
+    if (typeof Array.isArray === 'function') {
+      return Array.isArray(value)
+    }
+    return Object.prototype.toString.call(value) === '[object Array]'
+  }
+
+  /**
+   * 平均值
+   * @param {Object} arr
+   */
+  avg = (arr) => {
+    let sum = 0;
+    for (let i = 0; i < arr.length; i++) {
+      sum += arr[i];
+    }
+    return sum / arr.length;
+  }
+
+  /**
+   * 求和
+   */
+  sum = (arr, hex = 10) => {
+    return arr.reduce((pre, cur) => {
+      if (hex == 16) {
+        return parseInt(parseInt('0x' + pre) + parseInt('0x' + cur)).toString(16)
+      } else {
+        return pre + cur
+      }
+    })
+  }
+}

+ 138 - 0
uni_modules/leven-js-tools/js_sdk/color/index.js

@@ -0,0 +1,138 @@
+/**
+ * 颜色相关类
+ */
+export class ColorManager {
+  constructor() {}
+
+  /**
+   * 十六进制转换为gbg
+   * @param sColor  十六进制颜色值
+   * @param str 是否以字符串形式返回,true.返回格式rgb(0,0,0), false.返回格式:[0,0,0]
+   * */
+  hexToRgb = (sColor, str = true) => {
+    const reg = /^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/
+    sColor = String(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
+      }
+      // 处理六位的颜色值
+      const sColorChange = []
+      for (let i = 1; i < 7; i += 2) {
+        sColorChange.push(parseInt(`0x${sColor.slice(i, i + 2)}`))
+      }
+      if (!str) {
+        return sColorChange
+      }
+      return `rgb(${sColorChange[0]},${sColorChange[1]},${sColorChange[2]})`
+    }
+    if (/^(rgb|RGB)/.test(sColor)) {
+      const arr = sColor.replace(/(?:\(|\)|rgb|RGB)*/g, '').split(',')
+      return arr.map((val) => Number(val))
+    }
+    return sColor
+  }
+
+  /**
+   * 将rgb表示方式转换为hex表示方式
+   * */
+  rgbToHex = (rgb) => {
+    const _this = rgb
+    const reg = /^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/
+    if (/^(rgb|RGB)/.test(_this)) {
+      const 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
+    }
+    if (reg.test(_this)) {
+      const aNum = _this.replace(/#/, '').split('')
+      if (aNum.length === 6) {
+        return _this
+      }
+      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
+    }
+  }
+
+  /**
+   * 求两个颜色之间的渐变值
+   * @param {string} startColor 开始的颜色
+   * @param {string} endColor 结束的颜色
+   * @param {number} step 颜色等分的份额
+   * */
+  gradient = (startColor = 'rgb(0, 0, 0)', endColor = 'rgb(255, 255, 255)', step = 10) => {
+    const startRGB = this.hexToRgb(startColor, false) // 转换为rgb数组模式
+    const startR = startRGB[0]
+    const startG = startRGB[1]
+    const startB = startRGB[2]
+
+    const endRGB = this.hexToRgb(endColor, false)
+    const endR = endRGB[0]
+    const endG = endRGB[1]
+    const endB = endRGB[2]
+
+    const sR = (endR - startR) / step // 总差值
+    const sG = (endG - startG) / step
+    const sB = (endB - startB) / step
+    const colorArr = []
+    for (let i = 0; i < step; i++) {
+      // 计算每一步的hex值
+      let hex = this.rgbToHex(`rgb(${Math.round((sR * i + startR))},${Math.round((sG * i + startG))},${Math.round((sB
+  			* i + startB))})`)
+      // 确保第一个颜色值为startColor的值
+      if (i === 0) hex = this.rgbToHex(startColor)
+      // 确保最后一个颜色值为endColor的值
+      if (i === step - 1) hex = this.rgbToHex(endColor)
+      colorArr.push(hex)
+    }
+    return colorArr
+  }
+
+  /**
+   * 随机颜色
+   * @param returnType  返回格式:1.十六进制,2.rgb格式,3.数组(rgb的三个值)
+   * V1.1.0
+   */
+  random = (returnType = 1) => {
+    if (returnType == 2 || returnType == 3) {
+      let rm = () => Math.random() * 256 >> 0;
+      let rm1 = rm();
+      let rm2 = rm();
+      let rm3 = rm();
+      if (returnType == 2) {
+        return `rgb(${rm1}, ${rm2}, ${rm3})`;
+      } else {
+        return [rm1, rm2, rm3];
+      }
+    } else {
+      let letters = '0123456789ABCDEF';
+      let color = '#';
+      for (let i = 0; i < 6; i++) {
+        color += letters[Math.floor(Math.random() * 16)];
+      }
+      return color;
+    }
+  }
+}

+ 319 - 0
uni_modules/leven-js-tools/js_sdk/date/index.js

@@ -0,0 +1,319 @@
+/**
+ * 日期管理类
+ */
+// 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'
+      )
+    }
+    const str = this
+    // 返回 String(str) 这里是为了使返回的值是字符串字面量,在控制台中更符合直觉
+    if (str.length >= maxLength) return String(str)
+
+    const fillLength = maxLength - str.length
+    let times = Math.ceil(fillLength / fillString.length)
+    while (times >>= 1) {
+      fillString += fillString
+      if (times === 1) {
+        fillString += fillString
+      }
+    }
+    return fillString.slice(0, fillLength) + str
+  }
+}
+
+export class DateManager {
+  constructor() {}
+
+  /**
+   * 获取时间戳
+   */
+  getTimestamp = (time, type = 's') => {
+    const now = time ? new Date(time) : new Date();
+    let timeTamp = Date.parse(now);
+    return (type === 'ms') ? timeTamp : timeTamp / 1000;
+  }
+
+  /**
+   * 格式化时间
+   * 其他更多是格式化有如下:
+   * yyyy:mm:dd|yyyy:mm|yyyy年mm月dd日|yyyy年mm月dd日 hh时MM分等,可自定义组合
+   * 
+   * 来源:uview 2.0
+   */
+  format = (dateTime = null, formatStr = 'yyyy-mm-dd') => {
+    let date
+    // 若传入时间为假值,则取当前时间
+    if (!dateTime) {
+      date = new Date()
+    }
+    // 若为unix秒时间戳,则转为毫秒时间戳(逻辑有点奇怪,但不敢改,以保证历史兼容)
+    else if (/^\d{10}$/.test(dateTime?.toString().trim())) {
+      date = new Date(dateTime * 1000)
+    }
+    // 若用户传入字符串格式时间戳,new Date无法解析,需做兼容
+    else if (typeof dateTime === 'string' && /^\d+$/.test(dateTime.trim())) {
+      date = new Date(Number(dateTime))
+    }
+    // 处理平台性差异,在Safari/Webkit中,new Date仅支持/作为分割符的字符串时间
+    // 处理 '2022-07-10 01:02:03',跳过 '2022-07-10T01:02:03'
+    else if (typeof dateTime === 'string' && dateTime.includes('-') && !dateTime.includes('T')) {
+      date = new Date(dateTime.replace(/-/g, '/'))
+    }
+    // 其他都认为符合 RFC 2822 规范
+    else {
+      date = new Date(dateTime)
+    }
+
+    const timeSource = {
+      'y': date.getFullYear().toString(), // 年
+      'm': (date.getMonth() + 1).toString().padStart(2, '0'), // 月
+      'd': date.getDate().toString().padStart(2, '0'), // 日
+      'h': date.getHours().toString().padStart(2, '0'), // 时
+      'M': date.getMinutes().toString().padStart(2, '0'), // 分
+      's': date.getSeconds().toString().padStart(2, '0') // 秒
+      // 有其他格式化字符需求可以继续添加,必须转化成字符串
+    }
+
+    for (const key in timeSource) {
+      const [ret] = new RegExp(`${key}+`).exec(formatStr) || []
+      if (ret) {
+        // 年可能只需展示两位
+        const beginIndex = key === 'y' && ret.length === 2 ? 2 : 0
+        formatStr = formatStr.replace(ret, timeSource[key].slice(beginIndex))
+      }
+    }
+
+    return formatStr
+  }
+
+  /**
+   * @description 时间戳转为多久之前
+   * @param {String|Number} timestamp 时间戳
+   * @param {String|Boolean} format
+   * 格式化规则如果为时间格式字符串,超出一定时间范围,返回固定的时间格式;
+   * 如果为布尔值false,无论什么时间,都返回多久以前的格式
+   * @returns {string} 转化后的内容
+   * 
+   * 来源:uview 2.0
+   */
+  from = (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
+    let 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 = this.format(timestamp, format)
+        }
+    }
+    return tips
+  }
+
+  /**
+   * @description 日期的月或日补零操作
+   * @param {String} value 需要补零的值
+   * 
+   * 来源:uview 2.0
+   */
+  padZero = (value) => {
+    return `00${value}`.slice(-2)
+  }
+
+  /**
+   * 获取昨天
+   */
+  yesterday = () => {
+    let day = new Date();
+    day.setTime(day.getTime() - 24 * 60 * 60 * 1000);
+    let yesterday = day.getFullYear() + "-" + this.padZero((day.getMonth() + 1)) + "-" + this.padZero(day.getDate());
+    return yesterday;
+  }
+
+  /**
+   * 周日期
+   */
+  week = (operator = 1) => {
+    let now = new Date()
+    let nowTime = now.getTime()
+    // getDay()返回0-6,其中0表示周日,需特殊处理
+    let day = now.getDay() > 0 ? now.getDay() : 7 // 表示当前是周几
+    let oneDayTime = 24 * 60 * 60 * 1000 // 一天的总ms
+    // 周一时间戳
+    let mondayTime = nowTime - (day - 1) * oneDayTime
+    // 周日时间戳
+    let sundayTime = nowTime + (7 - day) * oneDayTime
+    if (operator < 0) {
+      mondayTime = mondayTime - oneDayTime * (Math.abs(operator) * 7);
+      sundayTime = sundayTime - oneDayTime * (Math.abs(operator) * 7);
+    } else if (operator > 1) {
+      mondayTime = mondayTime + oneDayTime * ((operator - 1) * 7);
+      sundayTime = sundayTime + oneDayTime * ((operator - 1) * 7);
+    }
+    let mondayDate = this.format(mondayTime);
+    let sundayDate = this.format(sundayTime);
+    return [mondayDate, sundayDate];
+  }
+
+  // 月
+  month = (operator = 1) => {
+    let date = new Date();
+    if (operator < 0) {
+      let operatorValue = Math.abs(operator);
+      date.setMonth(date.getMonth() - operatorValue);
+    } else if (operator > 1) {
+      date.setMonth(date.getMonth() - 1 + operator);
+    }
+    let year = date.getFullYear();
+    let month = date.getMonth();
+    // 日期
+    let monthDate = new Date(year, month + 1, 0);
+    // 日期的天数
+    let monthDay = monthDate.getDate();
+    // 年份
+    let newYear = monthDate.getFullYear();
+    // 月份
+    let newMonth = monthDate.getMonth() + 1;
+    newMonth = newMonth < 10 ? "0" + newMonth : newMonth;
+    // 开始日期
+    let startDate = newYear + "-" + newMonth + "-01"
+    // 结束日期
+    let endDate = newYear + "-" + newMonth + "-" + monthDay;
+    return [startDate, endDate];
+  }
+
+  /**
+   * 验证日期格式
+   */
+  isDate = (value, separator = "-") => {
+    if (value == "") return false;
+    if (typeof value !== 'string') return false;
+    let valueArr = value.split(separator);
+    if (valueArr.length != 3) return false;
+    let intYear = parseInt(valueArr[0]);
+    let intMonth = parseInt(valueArr[1]);
+    let intDay = parseInt(valueArr[2]);
+    if (isNaN(intYear) || isNaN(intMonth) || isNaN(intDay)) return false;
+    if (intMonth > 12 || intMonth < 1) return false;
+    if (intDay < 1 || intDay > 31) return false;
+    if ((intMonth == 4 || intMonth == 6 || intMonth == 9 || intMonth == 11) && (intDay > 30)) return false;
+    if (intMonth == 2) {
+      if (intDay > 29) return false;
+      if ((((intYear % 100 == 0) && (intYear % 400 != 0)) || (intYear % 4 != 0)) && (intDay > 28)) return false;
+    }
+    return true;
+  }
+
+  /**
+   * 两个日期之间的天数
+   * @param startDate 开始日期
+   * @param endDate 结束日期日期
+   */
+  betweenDays = (startDate, endDate) => {
+    let strSeparator = "-"; //日期分隔符
+    let oDate1;
+    let oDate2;
+    let iDays;
+    oDate1 = startDate.split(strSeparator);
+    oDate2 = endDate.split(strSeparator);
+    let strDateS = new Date(oDate1[0], oDate1[1] - 1, oDate1[2]);
+    let strDateE = new Date(oDate2[0], oDate2[1] - 1, oDate2[2]);
+    iDays = parseInt(Math.abs(strDateS - strDateE) / 1000 / 60 / 60 / 24) //把相差的毫秒数转换为天数
+    return iDays;
+  }
+
+  /**
+   * 某个月的天数
+   * @param value 月份,格式:2023-05
+   */
+  monthDays = (value) => {
+    let monthArr = value.split("-");
+    let year = parseInt(monthArr[0]);
+    let month = parseInt(monthArr[1], 10);
+    let d = new Date(year, month, 0);
+    return d.getDate();
+  }
+
+  /**
+   * 两个日期之间的所有日期
+   */
+  betweenDates = (startDate, endDate) => {
+    let result = [];
+    let beginDay = startDate.split("-");
+    let endDay = endDate.split("-");
+    let diffDay = new Date();
+    let dateList = new Array;
+    let i = 0;
+    diffDay.setDate(beginDay[2]);
+    diffDay.setMonth(beginDay[1] - 1);
+    diffDay.setFullYear(beginDay[0]);
+    result.push(startDate);
+    while (i == 0) {
+      let countDay = diffDay.getTime() + 24 * 60 * 60 * 1000;
+      diffDay.setTime(countDay);
+      dateList[2] = diffDay.getDate();
+      dateList[1] = diffDay.getMonth() + 1;
+      dateList[0] = diffDay.getFullYear();
+      if (String(dateList[1]).length == 1) {
+        dateList[1] = "0" + dateList[1]
+      };
+      if (String(dateList[2]).length == 1) {
+        dateList[2] = "0" + dateList[2]
+      };
+      result.push(dateList[0] + "-" + dateList[1] + "-" + dateList[2]);
+      if (dateList[0] == endDay[0] && dateList[1] == endDay[1] && dateList[2] == endDay[2]) {
+        i = 1;
+      }
+    };
+    return result;
+  }
+
+  /**
+   * 加多少天后的日期
+   */
+  addDay = (day) => {
+    let date = new Date();
+    date.setTime(date.getTime() + 24 * 60 * 60 * 1000 * day);
+    let dateFormat = date.getFullYear() + "-" + this.padZero((date.getMonth() + 1)) + "-" + this.padZero(date.getDate());
+    return dateFormat;
+  }
+
+  /**
+   * 减多少天后的日期
+   */
+  reduceDay = (day) => {
+    let date = new Date();
+    date.setTime(date.getTime() - 24 * 60 * 60 * 1000 * day);
+    let dateFormat = date.getFullYear() + "-" + this.padZero((date.getMonth() + 1)) + "-" + this.padZero(date.getDate());
+    return dateFormat;
+  }
+}

+ 190 - 0
uni_modules/leven-js-tools/js_sdk/encrypt/index.js

@@ -0,0 +1,190 @@
+/**
+ * 加解密类
+ */
+const CryptoJS = require("../utils/crypto-js-4.1.1.min.js")
+export class EncryptManager {
+  constructor() {}
+
+  /**
+   * md5加密
+   * @param str 加密字符串
+   */
+  md5 = (str) => {
+    // return md5(str);
+    return CryptoJS.MD5(str).toString()
+  }
+
+  /**
+   * AES加密
+   * @param str 要加密的字符串
+   * @param key 秘钥
+   */
+  aesEncode = (str, key) => {
+    let encrypt = CryptoJS.AES.encrypt(str, CryptoJS.enc.Utf8.parse(key), {
+      mode: CryptoJS.mode.ECB,
+      padding: CryptoJS.pad.Pkcs7
+    }).toString();
+    return encrypt;
+  }
+
+  /**
+   * AES解密
+   */
+  aesDecode = (str, key) => {
+    let decrypt = CryptoJS.AES.decrypt(str, CryptoJS.enc.Utf8.parse(key), {
+      mode: CryptoJS.mode.ECB,
+      padding: CryptoJS.pad.Pkcs7
+    }).toString(CryptoJS.enc.Utf8);
+    return decrypt;
+  }
+
+  /**
+   * base64加密
+   */
+  base64Encode = (str) => {
+    let wordArray = CryptoJS.enc.Utf8.parse(str);
+    let encrypt = CryptoJS.enc.Base64.stringify(wordArray);
+    return encrypt;
+  }
+
+  /**
+   * base64解密
+   */
+  base64Decode = (str) => {
+    return CryptoJS.enc.Base64.parse(str).toString(CryptoJS.enc.Utf8);
+  }
+
+  /**
+   * DES加密
+   */
+  desEncode = (str, key) => {
+    let keyHex = CryptoJS.enc.Utf8.parse(key)
+    let option = {
+      mode: CryptoJS.mode.ECB,
+      padding: CryptoJS.pad.Pkcs7
+    }
+    let encrypted = CryptoJS.DES.encrypt(str, keyHex, option)
+    return encrypted.toString()
+  }
+
+  /**
+   * DES解密
+   */
+  desDecode = (str, key) => {
+    let keyHex = CryptoJS.enc.Utf8.parse(key);
+    let options = {
+      ciphertext: CryptoJS.enc.Base64.parse(str)
+    };
+    let mode = {
+      mode: CryptoJS.mode.ECB,
+      padding: CryptoJS.pad.Pkcs7
+    };
+    let decrypted = CryptoJS.DES.decrypt(options, keyHex, mode)
+    return decrypted.toString(CryptoJS.enc.Utf8)
+  }
+
+  /**
+   * RC4加密
+   */
+  rc4Encode = (str, key) => {
+    return CryptoJS.RC4.encrypt(str, key).toString();
+  }
+
+  /**
+   * RC4解密
+   */
+  rc4Decode = (str, key) => {
+    return CryptoJS.RC4.decrypt(str, key).toString(CryptoJS.enc.Utf8);
+  }
+
+  /**
+   * rabbit加密
+   */
+  rabbitEncode = (str, key) => {
+    return CryptoJS.Rabbit.encrypt(str, key).toString();
+  }
+
+  /**
+   * rabbit解密
+   */
+  rabbitDecode = (str, key) => {
+    return CryptoJS.Rabbit.decrypt(str, key).toString(CryptoJS.enc.Utf8);
+  }
+
+  /**
+   * tripleDES加密
+   */
+  tripleDESEncode = (str, key) => {
+    return CryptoJS.TripleDES.encrypt(str, key).toString();
+  }
+
+  /**
+   * tripleDES解密
+   */
+  tripleDESDecode = (str, key) => {
+    return CryptoJS.TripleDES.decrypt(str, key).toString(CryptoJS.enc.Utf8);
+  }
+
+  /**
+   * sha1
+   */
+  sha1 = (str) => {
+    return CryptoJS.SHA1(str).toString();
+  }
+
+  /**
+   * sha224
+   */
+  sha224 = (str) => {
+    return CryptoJS.SHA224(str).toString()
+  }
+
+  /**
+   * sha256
+   */
+  sha256 = (str) => {
+    return CryptoJS.SHA256(str).toString()
+  }
+
+  /**
+   * sha384
+   */
+  sha384 = (str) => {
+    return CryptoJS.SHA384(str).toString()
+  }
+
+  /**
+   * sha512
+   */
+  sha512 = (str) => {
+    return CryptoJS.SHA512(str).toString()
+  }
+
+  /**
+   * hmacSha1
+   */
+  hmacSha1 = (str, key) => {
+    return CryptoJS.HmacSHA1(str, key).toString()
+  }
+
+  /**
+   * hmacSha256
+   */
+  hmacSha256 = (str, key) => {
+    return CryptoJS.HmacSHA256(str, key).toString()
+  }
+
+  /**
+   * hmacSha512
+   */
+  hmacSha512 = (str, key) => {
+    return CryptoJS.HmacSHA512(str, key).toString()
+  }
+
+  /**
+   * hmacMd5
+   */
+  hmacMd5 = (str, key) => {
+    return CryptoJS.HmacMD5(str, key).toString()
+  }
+}

+ 105 - 0
uni_modules/leven-js-tools/js_sdk/func/funcManager.js

@@ -0,0 +1,105 @@
+/**
+ * 函数相关类
+ */
+export class FuncManager {
+  constructor() {
+    // 防抖定时器
+    this.timeout = null;
+    // 节流定时器
+    this.timer = null;
+    this.flag = null;
+  }
+
+  /**
+   * @description 进行延时,以达到可以简写代码的目的 比如: await sleep(20)将会阻塞20ms
+   * @param {number} value 堵塞时间 单位ms 毫秒
+   * @returns {Promise} 返回promise
+   */
+  sleep = (value = 30) => {
+    return new Promise((resolve) => {
+      setTimeout(() => {
+        resolve()
+      }, value)
+    })
+  }
+
+  /**
+   * 是否是函数
+   */
+  isFunc = (value) => {
+    return typeof value === 'function'
+  }
+
+  /**
+   * 防抖原理:一定时间内,只有最后一次操作,再过wait毫秒后才执行函数
+   *
+   * @param {Function} func 要执行的回调函数
+   * @param {Number} wait 延时的时间
+   * @param {Boolean} immediate 是否立即执行
+   * @return null
+   */
+  debounce = (func, wait = 500, immediate = false) => {
+    // 清除定时器
+    if (this.timeout !== null) clearTimeout(this.timeout)
+    // 立即执行,此类情况一般用不到
+    if (immediate) {
+      const callNow = !this.timeout
+      this.timeout = setTimeout(() => {
+        this.timeout = null
+      }, wait)
+      if (callNow) typeof func === 'function' && func()
+    } else {
+      // 设置定时器,当最后一次操作后,timeout不会再被清除,所以在延时wait毫秒后执行func回调方法
+      this.timeout = setTimeout(() => {
+        typeof func === 'function' && func()
+      }, wait)
+    }
+  }
+
+  /**
+   * 节流原理:在一定时间内,只能触发一次
+   *
+   * @param {Function} func 要执行的回调函数
+   * @param {Number} wait 延时的时间
+   * @param {Boolean} immediate 是否立即执行
+   * @return null
+   */
+  throttle = (func, wait = 500, immediate = true) => {
+    if (immediate) {
+      if (!this.flag) {
+        this.flag = true
+        // 如果是立即执行,则在wait毫秒内开始时执行
+        typeof func === 'function' && func()
+        this.timer = setTimeout(() => {
+          this.flag = false
+        }, wait)
+      }
+    } else if (!this.flag) {
+      this.flag = true
+      // 如果是非立即执行,则在wait毫秒内的结束处执行
+      this.timer = setTimeout(() => {
+        this.flag = false
+        typeof func === 'function' && func()
+      }, wait)
+    }
+  }
+
+  /**
+   * 显示消息提示框
+   * @param {String} title 提示的内容,长度与 icon 取值有关。
+   * @param {Function} func 执行完后的执行函数
+   * @param {Number} duration 提示的延迟时间,单位毫秒,默认:2000
+   */
+  toast = (title, func = null, duration = 2000) => {
+    uni.showToast({
+      title: String(title),
+      icon: 'none',
+      duration
+    })
+    if (typeof func === "function") {
+      setTimeout(() => {
+        func();
+      }, duration)
+    }
+  }
+}

+ 155 - 0
uni_modules/leven-js-tools/js_sdk/number/index.js

@@ -0,0 +1,155 @@
+/**
+ * 数值处理类
+ */
+import {
+  round
+} from "../utils/digit.js"
+import Decimal from "../utils/decimal.js"
+export class NumberManager {
+  constructor() {}
+
+  /**
+   * 排列组合
+   */
+  combine = (m, n) => {
+    if (m < n || n < 0) {
+      return 0;
+    }
+    return this.factorial(m, m - n + 1) / this.factorial(n, 1);
+  }
+
+  /**
+   * 阶乘函数
+   */
+  factorial = (max, min) => {
+    if (max >= min && max > 1) {
+      return max * this.factorial(max - 1, min);
+    } else {
+      return 1;
+    }
+  }
+
+  /**
+   * 随机一个区间数
+   */
+  random = (min, max) => {
+    if (min >= 0 && max > 0 && max >= min) {
+      const gab = max - min + 1
+      return Math.floor(Math.random() * gab + min)
+    }
+    return 0
+  }
+
+  /**
+   * @description 数字格式化
+   * @param {number|string} number 要格式化的数字
+   * @param {number} decimals 保留几位小数
+   * @param {string} decimalPoint 小数点符号
+   * @param {string} thousandsSeparator 千分位符号
+   * @returns {string} 格式化后的数字
+   * 
+   * 来源:uview
+   */
+  format = (number, decimals = 0, decimalPoint = '.', thousandsSeparator = ',') => {
+    number = (`${number}`).replace(/[^0-9+-Ee.]/g, '')
+    const n = !isFinite(+number) ? 0 : +number
+    const prec = !isFinite(+decimals) ? 0 : Math.abs(decimals)
+    const sep = (typeof thousandsSeparator === 'undefined') ? ',' : thousandsSeparator
+    const dec = (typeof decimalPoint === 'undefined') ? '.' : decimalPoint
+    let s = ''
+
+    s = (prec ? round(n, prec) + '' : `${Math.round(n)}`).split('.')
+    const re = /(-?\d+)(\d{3})/
+    while (re.test(s[0])) {
+      s[0] = s[0].replace(re, `$1${sep}$2`)
+    }
+
+    if ((s[1] || '').length < prec) {
+      s[1] = s[1] || ''
+      s[1] += new Array(prec - s[1].length + 1).join('0')
+    }
+    return s.join(dec)
+  }
+
+  /**
+   * 是否是数字(包含小数点)
+   */
+  isNumber = (value) => {
+    return /^[\+-]?(\d+\.?\d*|\.\d+|\d\.\d+e\+\d+)$/.test(value)
+  }
+
+  /**
+   * 是否是整数
+   */
+  isDigits = (value) => {
+    return /^\d+$/.test(value)
+  }
+
+  /**
+   * 金额转大写
+   */
+  priceToUpper = (value) => {
+    var fraction = ['角', '分'];
+    var digit = ['零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖'];
+    var unit = [
+      ['元', '万', '亿'],
+      ['', '拾', '佰', '仟']
+    ];
+    var head = value < 0 ? '欠' : '';
+    value = Math.abs(value);
+
+    var s = '';
+
+    for (var i = 0; i < fraction.length; i++) {
+      s += (digit[Math.floor(value * 10 * Math.pow(10, i)) % 10] + fraction[i]).replace(/零./, '');
+    }
+    s = s || '整';
+    value = Math.floor(value);
+
+    for (var i = 0; i < unit[0].length && value > 0; i++) {
+      var p = '';
+      for (var j = 0; j < unit[1].length && value > 0; j++) {
+        p = digit[value % 10] + unit[1][j] + p;
+        value = Math.floor(value / 10);
+      }
+      s = p.replace(/(零.)*零$/, '').replace(/^$/, '零') + unit[0][i] + s;
+    }
+    return head + s.replace(/(零.)*零元/, '元').replace(/(零.)+/g, '零').replace(/^整$/, '零元整');
+  }
+
+  /**
+   * 高精度加法
+   * v1.1.4
+   */
+  add(a, b) {
+    let result = new Decimal(a).add(new Decimal(b));
+    return result.toNumber();
+  }
+
+  /**
+   * 高精度减法
+   * v1.1.4
+   */
+  sub(a, b) {
+    let result = new Decimal(a).sub(new Decimal(b));
+    return result.toNumber();
+  }
+
+  /**
+   * 高精度乘法
+   * v1.1.4
+   */
+  mul(a, b) {
+    let result = new Decimal(a).mul(new Decimal(b));
+    return result.toNumber();
+  }
+
+  /**
+   * 高精度除法
+   * v1.1.4
+   */
+  div(a, b) {
+    let result = new Decimal(a).div(new Decimal(b));
+    return result.toNumber();
+  }
+}

+ 238 - 0
uni_modules/leven-js-tools/js_sdk/object/index.js

@@ -0,0 +1,238 @@
+/**
+ * 对象类
+ */
+export class ObjectManager {
+  constructor() {}
+
+  /**
+   * 对象转url参数
+   * @param {*} data,对象
+   * @param {*} isPrefix,是否自动加上"?"
+   * 参考:uview
+   **/
+  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('&') : ''
+  }
+
+  /**
+   * @description 克隆对象
+   * @param {object} obj 需要深度克隆的对象
+   * @returns {*} 克隆后的对象或者原值(不是对象)
+   */
+  clone = (obj, cache = new WeakMap()) => {
+    if (obj === null || typeof obj !== 'object') return obj;
+    if (cache.has(obj)) return cache.get(obj);
+    let clone;
+    if (obj instanceof Date) {
+      clone = new Date(obj.getTime());
+    } else if (obj instanceof RegExp) {
+      clone = new RegExp(obj);
+    } else if (obj instanceof Map) {
+      clone = new Map(Array.from(obj, ([key, value]) => [key, this.clone(value, cache)]));
+    } else if (obj instanceof Set) {
+      clone = new Set(Array.from(obj, value => this.clone(value, cache)));
+    } else if (Array.isArray(obj)) {
+      clone = obj.map(value => this.clone(value, cache));
+    } else if (Object.prototype.toString.call(obj) === '[object Object]') {
+      clone = Object.create(Object.getPrototypeOf(obj));
+      cache.set(obj, clone);
+      for (const [key, value] of Object.entries(obj)) {
+        clone[key] = this.clone(value, cache);
+      }
+    } else {
+      clone = Object.assign({}, obj);
+    }
+    cache.set(obj, clone);
+    return clone;
+  }
+
+  /**
+   * @description JS对象深度合并
+   * @param {object} target 需要拷贝的对象
+   * @param {object} source 拷贝的来源对象
+   * @returns {object|boolean} 深度合并后的对象或者false(入参有不是对象)
+   */
+  merge = (target = {}, source = {}) => {
+    target = this.clone(target)
+    if (typeof target !== 'object' || target === null || typeof source !== 'object' || source === null) return target;
+    const merged = Array.isArray(target) ? target.slice() : Object.assign({}, target);
+    for (const prop in source) {
+      if (!source.hasOwnProperty(prop)) continue;
+      const sourceValue = source[prop];
+      const targetValue = merged[prop];
+      if (sourceValue instanceof Date) {
+        merged[prop] = new Date(sourceValue);
+      } else if (sourceValue instanceof RegExp) {
+        merged[prop] = new RegExp(sourceValue);
+      } else if (sourceValue instanceof Map) {
+        merged[prop] = new Map(sourceValue);
+      } else if (sourceValue instanceof Set) {
+        merged[prop] = new Set(sourceValue);
+      } else if (typeof sourceValue === 'object' && sourceValue !== null) {
+        merged[prop] = deepMerge(targetValue, sourceValue);
+      } else {
+        merged[prop] = sourceValue;
+      }
+    }
+    return merged;
+  }
+
+  /**
+   * @description 获取某个对象下的属性,用于通过类似'a.b.c'的形式去获取一个对象的的属性的形式
+   * @param {object} obj 对象
+   * @param {string} key 需要获取的属性字段
+   * @returns {*}
+   */
+  getProperty = (obj, key) => {
+    if (!obj) {
+      return
+    }
+    if (typeof key !== 'string' || key === '') {
+      return ''
+    }
+    if (key.indexOf('.') !== -1) {
+      const keys = key.split('.')
+      let firstObj = obj[keys[0]] || {}
+
+      for (let i = 1; i < keys.length; i++) {
+        if (firstObj) {
+          firstObj = firstObj[keys[i]]
+        }
+      }
+      return firstObj
+    }
+    return obj[key]
+  }
+
+  /**
+   * @description 设置对象的属性值,如果'a.b.c'的形式进行设置
+   * @param {object} obj 对象
+   * @param {string} key 需要设置的属性
+   * @param {string} value 设置的值
+   */
+  setProperty = (obj, key, value) => {
+    if (!obj) {
+      return
+    }
+    // 递归赋值
+    const inFn = function(_obj, keys, v) {
+      // 最后一个属性key
+      if (keys.length === 1) {
+        _obj[keys[0]] = v
+        return
+      }
+      // 0~length-1个key
+      while (keys.length > 1) {
+        const k = keys[0]
+        if (!_obj[k] || (typeof _obj[k] !== 'object')) {
+          _obj[k] = {}
+        }
+        const key = keys.shift()
+        // 自调用判断是否存在属性,不存在则自动创建对象
+        inFn(_obj[k], keys, v)
+      }
+    }
+
+    if (typeof key !== 'string' || key === '') {
+
+    } else if (key.indexOf('.') !== -1) { // 支持多层级赋值操作
+      const keys = key.split('.')
+      inFn(obj, keys, value)
+    } else {
+      obj[key] = value
+    }
+  }
+
+  /**
+   * 是否是对象
+   * @param {Object} value
+   */
+  isObject(value) {
+    return Object.prototype.toString.call(value) === '[object Object]'
+  }
+
+  /**
+   * 移除空值
+   */
+  trim = (obj) => {
+    let map = {};
+    for (const key in obj) {
+      if (Object.hasOwnProperty.call(obj, key)) {
+        // 如果是字符串要 trim
+        const value = (typeof obj[key] === 'string') ? obj[key].trim() : obj[key];
+        if (!!value || value === 0) {
+          map[key] = value;
+        }
+      }
+    }
+    return map;
+  }
+
+  /**
+   * 将对象按照键名排序
+   * @param obj 要处理的对象
+   * @param type  排序方式,asc:升序,desc:降序
+   * v1.0.1
+   */
+  sort = (obj, type = "asc") => {
+    // 获取键名
+    let newParams = {};
+    let keys = Object.keys(obj).sort();
+    if (type == "desc") {
+      keys.reverse();
+    }
+    for (let i = 0; i < keys.length; i++) {
+      let value = obj[keys[i]];
+      newParams[keys[i]] = value;
+    }
+    return newParams;
+  }
+}

+ 16 - 0
uni_modules/leven-js-tools/js_sdk/request/index.js

@@ -0,0 +1,16 @@
+/**
+ * 请求类
+ * 
+ * luch-request版本:3.1.0
+ */
+import Request from "./luch-request/index.js"
+export class RequestManager {
+  constructor() {}
+
+  /**
+   * 请求
+   */
+  request = () => {
+    return new Request();
+  }
+}

+ 132 - 0
uni_modules/leven-js-tools/js_sdk/request/luch-request/adapters/index.js

@@ -0,0 +1,132 @@
+import buildURL from '../helpers/buildURL'
+import buildFullPath from '../core/buildFullPath'
+import settle from '../core/settle'
+import {isUndefined} from "../utils"
+
+/**
+ * 返回可选值存在的配置
+ * @param {Array} keys - 可选值数组
+ * @param {Object} config2 - 配置
+ * @return {{}} - 存在的配置项
+ */
+const mergeKeys = (keys, config2) => {
+  let config = {}
+  keys.forEach(prop => {
+    if (!isUndefined(config2[prop])) {
+      config[prop] = config2[prop]
+    }
+  })
+  return config
+}
+export default (config) => {
+  return new Promise((resolve, reject) => {
+    let fullPath = buildURL(buildFullPath(config.baseURL, config.url), config.params, config.paramsSerializer)
+    const _config = {
+      url: fullPath,
+      header: config.header,
+      complete: (response) => {
+        config.fullPath = fullPath
+        response.config = config
+        response.rawData = response.data
+        try {
+          let jsonParseHandle = false
+          const forcedJSONParsingType = typeof config.forcedJSONParsing
+          if (forcedJSONParsingType === 'boolean') {
+            jsonParseHandle = config.forcedJSONParsing
+          } else if (forcedJSONParsingType === 'object') {
+            const includesMethod = config.forcedJSONParsing.include || []
+            jsonParseHandle = includesMethod.includes(config.method)
+          }
+
+          // 对可能字符串不是json 的情况容错
+          if (jsonParseHandle && typeof response.data === 'string') {
+            response.data = JSON.parse(response.data)
+          }
+          // eslint-disable-next-line no-empty
+        } catch (e) {
+        }
+        settle(resolve, reject, response)
+      }
+    }
+    let requestTask
+    if (config.method === 'UPLOAD') {
+      delete _config.header['content-type']
+      delete _config.header['Content-Type']
+      let otherConfig = {
+        // #ifdef MP-ALIPAY
+        fileType: config.fileType,
+        // #endif
+        filePath: config.filePath,
+        name: config.name
+      }
+      const optionalKeys = [
+        // #ifdef APP-PLUS || H5
+        'files',
+        // #endif
+        // #ifdef H5
+        'file',
+        // #endif
+        // #ifdef H5 || APP-PLUS || MP-WEIXIN || MP-ALIPAY || MP-TOUTIAO || MP-KUAISHOU
+        'timeout',
+        // #endif
+        'formData'
+      ]
+      requestTask = uni.uploadFile({..._config, ...otherConfig, ...mergeKeys(optionalKeys, config)})
+    } else if (config.method === 'DOWNLOAD') {
+      const optionalKeys = [
+        // #ifdef H5 || APP-PLUS || MP-WEIXIN || MP-ALIPAY || MP-TOUTIAO || MP-KUAISHOU
+        'timeout',
+        // #endif
+        // #ifdef MP
+        'filePath',
+        // #endif
+      ]
+      requestTask = uni.downloadFile({..._config, ...mergeKeys(optionalKeys, config)})
+    } else {
+      const optionalKeys = [
+        'data',
+        'method',
+        // #ifdef H5 || APP-PLUS || MP-ALIPAY || MP-WEIXIN
+        'timeout',
+        // #endif
+        'dataType',
+        // #ifndef MP-ALIPAY
+        'responseType',
+        // #endif
+        // #ifdef APP-PLUS
+        'sslVerify',
+        // #endif
+        // #ifdef H5
+        'withCredentials',
+        // #endif
+        // #ifdef APP-PLUS
+        'firstIpv4',
+        // #endif
+        // #ifdef MP-WEIXIN
+        'enableHttp2',
+        'enableQuic',
+        // #endif
+        // #ifdef MP-TOUTIAO || MP-WEIXIN
+        'enableCache',
+        // #endif
+        // #ifdef MP-WEIXIN
+        'enableHttpDNS',
+        'httpDNSServiceId',
+        'enableChunked',
+        'forceCellularNetwork',
+        // #endif
+        // #ifdef MP-ALIPAY
+        'enableCookie',
+        // #endif
+        // #ifdef MP-BAIDU
+        'cloudCache',
+        'defer'
+        // #endif
+      ]
+      requestTask = uni.request({..._config, ...mergeKeys(optionalKeys, config)})
+    }
+    if (config.getTask) {
+      config.getTask(requestTask, config)
+    }
+  })
+}

+ 51 - 0
uni_modules/leven-js-tools/js_sdk/request/luch-request/core/InterceptorManager.js

@@ -0,0 +1,51 @@
+'use strict'
+
+
+function InterceptorManager() {
+  this.handlers = []
+}
+
+/**
+ * Add a new interceptor to the stack
+ *
+ * @param {Function} fulfilled The function to handle `then` for a `Promise`
+ * @param {Function} rejected The function to handle `reject` for a `Promise`
+ *
+ * @return {Number} An ID used to remove interceptor later
+ */
+InterceptorManager.prototype.use = function use(fulfilled, rejected) {
+  this.handlers.push({
+    fulfilled: fulfilled,
+    rejected: rejected
+  })
+  return this.handlers.length - 1
+}
+
+/**
+ * Remove an interceptor from the stack
+ *
+ * @param {Number} id The ID that was returned by `use`
+ */
+InterceptorManager.prototype.eject = function eject(id) {
+  if (this.handlers[id]) {
+    this.handlers[id] = null
+  }
+}
+
+/**
+ * Iterate over all the registered interceptors
+ *
+ * This method is particularly useful for skipping over any
+ * interceptors that may have become `null` calling `eject`.
+ *
+ * @param {Function} fn The function to call for each interceptor
+ */
+InterceptorManager.prototype.forEach = function forEach(fn) {
+  this.handlers.forEach(h => {
+    if (h !== null) {
+      fn(h)
+    }
+  })
+}
+
+export default InterceptorManager

+ 201 - 0
uni_modules/leven-js-tools/js_sdk/request/luch-request/core/Request.js

@@ -0,0 +1,201 @@
+/**
+ * @Class Request
+ * @description luch-request http请求插件
+ * @Author lu-ch
+ * @Email webwork.s@qq.com
+ * 文档: https://www.quanzhan.co/luch-request/
+ * github: https://github.com/lei-mu/luch-request
+ * DCloud: http://ext.dcloud.net.cn/plugin?id=392
+ */
+
+
+import dispatchRequest from './dispatchRequest'
+import InterceptorManager from './InterceptorManager'
+import mergeConfig from './mergeConfig'
+import defaults from './defaults'
+import { isPlainObject } from '../utils'
+import clone from '../utils/clone'
+
+export default class Request {
+  /**
+   * @param {Object} arg - 全局配置
+   * @param {String} arg.baseURL - 全局根路径
+   * @param {Object} arg.header - 全局header
+   * @param {String} arg.method = [GET|POST|PUT|DELETE|CONNECT|HEAD|OPTIONS|TRACE] - 全局默认请求方式
+   * @param {String} arg.dataType = [json] - 全局默认的dataType
+   * @param {String} arg.responseType = [text|arraybuffer] - 全局默认的responseType。支付宝小程序不支持
+   * @param {Object} arg.custom - 全局默认的自定义参数
+   * @param {Number} arg.timeout - 全局默认的超时时间,单位 ms。默认60000。H5(HBuilderX 2.9.9+)、APP(HBuilderX 2.9.9+)、微信小程序(2.10.0)、支付宝小程序
+   * @param {Boolean} arg.sslVerify - 全局默认的是否验证 ssl 证书。默认true.仅App安卓端支持(HBuilderX 2.3.3+)
+   * @param {Boolean} arg.withCredentials - 全局默认的跨域请求时是否携带凭证(cookies)。默认false。仅H5支持(HBuilderX 2.6.15+)
+   * @param {Boolean} arg.firstIpv4 - 全DNS解析时优先使用ipv4。默认false。仅 App-Android 支持 (HBuilderX 2.8.0+)
+   * @param {Function(statusCode):Boolean} arg.validateStatus - 全局默认的自定义验证器。默认statusCode >= 200 && statusCode < 300
+   */
+  constructor(arg = {}) {
+    if (!isPlainObject(arg)) {
+      arg = {}
+      console.warn('设置全局参数必须接收一个Object')
+    }
+    this.config = clone({...defaults, ...arg})
+    this.interceptors = {
+      request: new InterceptorManager(),
+      response: new InterceptorManager()
+    }
+  }
+
+  /**
+   * @Function
+   * @param {Request~setConfigCallback} f - 设置全局默认配置
+   */
+  setConfig(f) {
+    this.config = f(this.config)
+  }
+
+  middleware(config) {
+    config = mergeConfig(this.config, config)
+    let chain = [dispatchRequest, undefined]
+    let promise = Promise.resolve(config)
+
+    this.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor) {
+      chain.unshift(interceptor.fulfilled, interceptor.rejected)
+    })
+
+    this.interceptors.response.forEach(function pushResponseInterceptors(interceptor) {
+      chain.push(interceptor.fulfilled, interceptor.rejected)
+    })
+
+    while (chain.length) {
+      promise = promise.then(chain.shift(), chain.shift())
+    }
+
+    return promise
+  }
+
+  /**
+   * @Function
+   * @param {Object} config - 请求配置项
+   * @prop {String} options.url - 请求路径
+   * @prop {Object} options.data - 请求参数
+   * @prop {Object} [options.responseType = config.responseType] [text|arraybuffer] - 响应的数据类型
+   * @prop {Object} [options.dataType = config.dataType] - 如果设为 json,会尝试对返回的数据做一次 JSON.parse
+   * @prop {Object} [options.header = config.header] - 请求header
+   * @prop {Object} [options.method = config.method] - 请求方法
+   * @returns {Promise<unknown>}
+   */
+  request(config = {}) {
+    return this.middleware(config)
+  }
+
+  get(url, options = {}) {
+    return this.middleware({
+      url,
+      method: 'GET',
+      ...options
+    })
+  }
+
+  post(url, data, options = {}) {
+    return this.middleware({
+      url,
+      data,
+      method: 'POST',
+      ...options
+    })
+  }
+
+  // #ifndef MP-ALIPAY || MP-KUAISHOU || MP-JD
+  put(url, data, options = {}) {
+    return this.middleware({
+      url,
+      data,
+      method: 'PUT',
+      ...options
+    })
+  }
+
+  // #endif
+
+  // #ifdef APP-PLUS || H5 || MP-WEIXIN || MP-BAIDU
+  delete(url, data, options = {}) {
+    return this.middleware({
+      url,
+      data,
+      method: 'DELETE',
+      ...options
+    })
+  }
+
+  // #endif
+
+  // #ifdef H5 || MP-WEIXIN
+  connect(url, data, options = {}) {
+    return this.middleware({
+      url,
+      data,
+      method: 'CONNECT',
+      ...options
+    })
+  }
+
+  // #endif
+
+  // #ifdef  H5 || MP-WEIXIN || MP-BAIDU
+  head(url, data, options = {}) {
+    return this.middleware({
+      url,
+      data,
+      method: 'HEAD',
+      ...options
+    })
+  }
+
+  // #endif
+
+  // #ifdef APP-PLUS || H5 || MP-WEIXIN || MP-BAIDU
+  options(url, data, options = {}) {
+    return this.middleware({
+      url,
+      data,
+      method: 'OPTIONS',
+      ...options
+    })
+  }
+
+  // #endif
+
+  // #ifdef H5 || MP-WEIXIN
+  trace(url, data, options = {}) {
+    return this.middleware({
+      url,
+      data,
+      method: 'TRACE',
+      ...options
+    })
+  }
+
+  // #endif
+
+  upload(url, config = {}) {
+    config.url = url
+    config.method = 'UPLOAD'
+    return this.middleware(config)
+  }
+
+  download(url, config = {}) {
+    config.url = url
+    config.method = 'DOWNLOAD'
+    return this.middleware(config)
+  }
+
+  get version () {
+    return '3.1.0'
+  }
+}
+
+
+/**
+ * setConfig回调
+ * @return {Object} - 返回操作后的config
+ * @callback Request~setConfigCallback
+ * @param {Object} config - 全局默认config
+ */

+ 20 - 0
uni_modules/leven-js-tools/js_sdk/request/luch-request/core/buildFullPath.js

@@ -0,0 +1,20 @@
+'use strict'
+
+import isAbsoluteURL from '../helpers/isAbsoluteURL'
+import combineURLs from '../helpers/combineURLs'
+
+/**
+ * Creates a new URL by combining the baseURL with the requestedURL,
+ * only when the requestedURL is not already an absolute URL.
+ * If the requestURL is absolute, this function returns the requestedURL untouched.
+ *
+ * @param {string} baseURL The base URL
+ * @param {string} requestedURL Absolute or relative URL to combine
+ * @returns {string} The combined full path
+ */
+export default function buildFullPath(baseURL, requestedURL) {
+  if (baseURL && !isAbsoluteURL(requestedURL)) {
+    return combineURLs(baseURL, requestedURL)
+  }
+  return requestedURL
+}

+ 33 - 0
uni_modules/leven-js-tools/js_sdk/request/luch-request/core/defaults.js

@@ -0,0 +1,33 @@
+/**
+ * 默认的全局配置
+ */
+
+
+export default {
+  baseURL: '',
+  header: {},
+  method: 'GET',
+  dataType: 'json',
+  paramsSerializer: null,
+  // #ifndef MP-ALIPAY
+  responseType: 'text',
+  // #endif
+  custom: {},
+  // #ifdef H5 || APP-PLUS || MP-WEIXIN || MP-ALIPAY || MP-TOUTIAO || MP-KUAISHOU
+  timeout: 60000,
+  // #endif
+  // #ifdef APP-PLUS
+  sslVerify: true,
+  // #endif
+  // #ifdef H5
+  withCredentials: false,
+  // #endif
+  // #ifdef APP-PLUS
+  firstIpv4: false,
+  // #endif
+  validateStatus: function validateStatus(status) {
+    return status >= 200 && status < 300
+  },
+  // 是否尝试将响应数据json化
+  forcedJSONParsing: true
+}

+ 6 - 0
uni_modules/leven-js-tools/js_sdk/request/luch-request/core/dispatchRequest.js

@@ -0,0 +1,6 @@
+import adapter from '../adapters/index'
+
+
+export default (config) => {
+  return adapter(config)
+}

+ 126 - 0
uni_modules/leven-js-tools/js_sdk/request/luch-request/core/mergeConfig.js

@@ -0,0 +1,126 @@
+import {deepMerge, isUndefined} from '../utils'
+
+/**
+ * 合并局部配置优先的配置,如果局部有该配置项则用局部,如果全局有该配置项则用全局
+ * @param {Array} keys - 配置项
+ * @param {Object} globalsConfig - 当前的全局配置
+ * @param {Object} config2 - 局部配置
+ * @return {{}}
+ */
+const mergeKeys = (keys, globalsConfig, config2) => {
+  let config = {}
+  keys.forEach(prop => {
+    if (!isUndefined(config2[prop])) {
+      config[prop] = config2[prop]
+    } else if (!isUndefined(globalsConfig[prop])) {
+      config[prop] = globalsConfig[prop]
+    }
+  })
+  return config
+}
+/**
+ *
+ * @param globalsConfig - 当前实例的全局配置
+ * @param config2 - 当前的局部配置
+ * @return - 合并后的配置
+ */
+export default (globalsConfig, config2 = {}) => {
+  const method = config2.method || globalsConfig.method || 'GET'
+  let config = {
+    baseURL: config2.baseURL || globalsConfig.baseURL || '',
+    method: method,
+    url: config2.url || '',
+    params: config2.params || {},
+    custom: {...(globalsConfig.custom || {}), ...(config2.custom || {})},
+    header: deepMerge(globalsConfig.header || {}, config2.header || {})
+  }
+  const defaultToConfig2Keys = ['getTask', 'validateStatus', 'paramsSerializer', 'forcedJSONParsing']
+  config = {...config, ...mergeKeys(defaultToConfig2Keys, globalsConfig, config2)}
+
+  // eslint-disable-next-line no-empty
+  if (method === 'DOWNLOAD') {
+    const downloadKeys = [
+      // #ifdef H5 || APP-PLUS || MP-WEIXIN || MP-ALIPAY || MP-TOUTIAO || MP-KUAISHOU
+      'timeout',
+      // #endif
+      // #ifdef MP
+      'filePath',
+      // #endif
+    ]
+    config = {...config, ...mergeKeys(downloadKeys, globalsConfig, config2)}
+  } else if (method === 'UPLOAD') {
+    delete config.header['content-type']
+    delete config.header['Content-Type']
+    const uploadKeys = [
+      // #ifdef APP-PLUS || H5
+      'files',
+      // #endif
+      // #ifdef MP-ALIPAY
+      'fileType',
+      // #endif
+      // #ifdef H5
+      'file',
+      // #endif
+      'filePath',
+      'name',
+      // #ifdef H5 || APP-PLUS || MP-WEIXIN || MP-ALIPAY || MP-TOUTIAO || MP-KUAISHOU
+      'timeout',
+      // #endif
+      'formData',
+    ]
+    uploadKeys.forEach(prop => {
+      if (!isUndefined(config2[prop])) {
+        config[prop] = config2[prop]
+      }
+    })
+    // #ifdef H5 || APP-PLUS || MP-WEIXIN || MP-ALIPAY || MP-TOUTIAO || MP-KUAISHOU
+    if (isUndefined(config.timeout) && !isUndefined(globalsConfig.timeout)) {
+      config['timeout'] = globalsConfig['timeout']
+    }
+    // #endif
+  } else {
+    const defaultsKeys = [
+      'data',
+      // #ifdef H5 || APP-PLUS || MP-ALIPAY || MP-WEIXIN
+      'timeout',
+      // #endif
+      'dataType',
+      // #ifndef MP-ALIPAY
+      'responseType',
+      // #endif
+      // #ifdef APP-PLUS
+      'sslVerify',
+      // #endif
+      // #ifdef H5
+      'withCredentials',
+      // #endif
+      // #ifdef APP-PLUS
+      'firstIpv4',
+      // #endif
+      // #ifdef MP-WEIXIN
+      'enableHttp2',
+      'enableQuic',
+      // #endif
+      // #ifdef MP-TOUTIAO || MP-WEIXIN
+      'enableCache',
+      // #endif
+      // #ifdef MP-WEIXIN
+      'enableHttpDNS',
+      'httpDNSServiceId',
+      'enableChunked',
+      'forceCellularNetwork',
+      // #endif
+      // #ifdef MP-ALIPAY
+      'enableCookie',
+      // #endif
+      // #ifdef MP-BAIDU
+      'cloudCache',
+      'defer'
+      // #endif
+
+    ]
+    config = {...config, ...mergeKeys(defaultsKeys, globalsConfig, config2)}
+  }
+
+  return config
+}

+ 16 - 0
uni_modules/leven-js-tools/js_sdk/request/luch-request/core/settle.js

@@ -0,0 +1,16 @@
+/**
+ * Resolve or reject a Promise based on response status.
+ *
+ * @param {Function} resolve A function that resolves the promise.
+ * @param {Function} reject A function that rejects the promise.
+ * @param {object} response The response.
+ */
+export default function settle(resolve, reject, response) {
+  const validateStatus = response.config.validateStatus
+  const status = response.statusCode
+  if (status && (!validateStatus || validateStatus(status))) {
+    resolve(response)
+  } else {
+    reject(response)
+  }
+}

+ 64 - 0
uni_modules/leven-js-tools/js_sdk/request/luch-request/helpers/buildURL.js

@@ -0,0 +1,64 @@
+'use strict'
+
+import * as utils from './../utils'
+
+function encode(val) {
+  return encodeURIComponent(val).replace(/%40/gi, '@').replace(/%3A/gi, ':').replace(/%24/g, '$').replace(/%2C/gi, ',').replace(/%20/g, '+').replace(/%5B/gi, '[').replace(/%5D/gi, ']')
+}
+
+/**
+ * Build a URL by appending params to the end
+ *
+ * @param {string} url The base of the url (e.g., http://www.google.com)
+ * @param {object} [params] The params to be appended
+ * @returns {string} The formatted url
+ */
+export default function buildURL(url, params, paramsSerializer) {
+  /*eslint no-param-reassign:0*/
+  if (!params) {
+    return url
+  }
+
+  var serializedParams
+  if (paramsSerializer) {
+    serializedParams = paramsSerializer(params)
+  } else if (utils.isURLSearchParams(params)) {
+    serializedParams = params.toString()
+  } else {
+    var parts = []
+
+    utils.forEach(params, function serialize(val, key) {
+      if (val === null || typeof val === 'undefined') {
+        return
+      }
+
+      if (utils.isArray(val)) {
+        key = key + '[]'
+      } else {
+        val = [val]
+      }
+
+      utils.forEach(val, function parseValue(v) {
+        if (utils.isDate(v)) {
+          v = v.toISOString()
+        } else if (utils.isObject(v)) {
+          v = JSON.stringify(v)
+        }
+        parts.push(encode(key) + '=' + encode(v))
+      })
+    })
+
+    serializedParams = parts.join('&')
+  }
+
+  if (serializedParams) {
+    var hashmarkIndex = url.indexOf('#')
+    if (hashmarkIndex !== -1) {
+      url = url.slice(0, hashmarkIndex)
+    }
+
+    url += (url.indexOf('?') === -1 ? '?' : '&') + serializedParams
+  }
+
+  return url
+}

+ 14 - 0
uni_modules/leven-js-tools/js_sdk/request/luch-request/helpers/combineURLs.js

@@ -0,0 +1,14 @@
+'use strict'
+
+/**
+ * Creates a new URL by combining the specified URLs
+ *
+ * @param {string} baseURL The base URL
+ * @param {string} relativeURL The relative URL
+ * @returns {string} The combined URL
+ */
+export default function combineURLs(baseURL, relativeURL) {
+  return relativeURL
+    ? baseURL.replace(/\/+$/, '') + '/' + relativeURL.replace(/^\/+/, '')
+    : baseURL
+}

+ 14 - 0
uni_modules/leven-js-tools/js_sdk/request/luch-request/helpers/isAbsoluteURL.js

@@ -0,0 +1,14 @@
+'use strict'
+
+/**
+ * Determines whether the specified URL is absolute
+ *
+ * @param {string} url The URL to test
+ * @returns {boolean} True if the specified URL is absolute, otherwise false
+ */
+export default function isAbsoluteURL(url) {
+  // A URL is considered absolute if it begins with "<scheme>://" or "//" (protocol-relative URL).
+  // RFC 3986 defines scheme name as a sequence of characters beginning with a letter and followed
+  // by any combination of letters, digits, plus, period, or hyphen.
+  return /^([a-z][a-z\d+\-.]*:)?\/\//i.test(url)
+}

+ 197 - 0
uni_modules/leven-js-tools/js_sdk/request/luch-request/index.d.ts

@@ -0,0 +1,197 @@
+export type HttpTask = UniApp.RequestTask | UniApp.UploadTask | UniApp.DownloadTask;
+
+export type HttpRequestTask = UniApp.RequestTask;
+
+export type HttpUploadTask = UniApp.UploadTask;
+
+export type HttpDownloadTask = UniApp.DownloadTask;
+
+export type HttpMethod =
+    "GET"
+    | "POST"
+    | "PUT"
+    | "DELETE"
+    | "CONNECT"
+    | "HEAD"
+    | "OPTIONS"
+    | "TRACE"
+    | "UPLOAD"
+    | "DOWNLOAD";
+
+export type HttpRequestHeader = Record<string, string>;
+
+export type HttpParams = Record<string, any>;
+
+export type HttpData = Record<string, any>;
+
+export type HttpResponseType = 'arraybuffer' | 'text';
+
+export type HttpCustom = Record<string, any>;
+
+export type HttpFileType = 'image' | 'video' | 'audio';
+
+export type HttpFormData = Record<string, any>;
+
+export type HttpResponseHeader = Record<string, string> & {
+    "set-cookie"?: string[]
+};
+
+export interface HttpRequestConfig<T = HttpTask> {
+    /** @desc 请求服务器接口地址 */
+    url?: string;
+    /** @desc 请求方式,默认为 GET */
+    method?: HttpMethod;
+    /** @desc 请求基地址 */
+    baseURL?: string;
+    /** @desc 请求头信息,不能设置 Referer,App、H5 端会自动带上 cookie,且 H5 端不可手动修改 */
+    header?: HttpRequestHeader;
+    /** @desc 请求查询参数,自动拼接为查询字符串 */
+    params?: HttpParams;
+    /** @desc 请求体参数 */
+    data?: HttpData;
+    /** @desc 超时时间,单位 ms,默认为 60000,仅 H5 (HBuilderX 2.9.9+)、APP (HBuilderX 2.9.9+)、微信小程序 (2.10.0)、支付宝小程序支持 */
+    timeout?: number;
+    /** @desc 跨域请求时是否携带凭证 (cookies),默认为 false,仅 H5 (HBuilderX 2.6.15+) 支持 */
+    withCredentials?: boolean;
+    /** @desc 设置响应的数据类型,支付宝小程序不支持 */
+    responseType?: HttpResponseType;
+    /** @desc 全局自定义验证器 */
+    validateStatus?: ((statusCode: number) => boolean) | null;
+
+
+    /** params 参数自定义处理 */
+    paramsSerializer?: (params: AnyObject) => string | void;
+
+    /** @desc 默认为 json,如果设为 json,会尝试对返回的数据做一次 JSON.parse */
+    dataType?: string;
+    /** @desc DNS 解析时是否优先使用 ipv4,默认为 false,仅 App-Android (HBuilderX 2.8.0+) 支持 */
+    firstIpv4?: boolean;
+    /** @desc 是否验证 SSL 证书,默认为 true,仅 App-Android (HBuilderX 2.3.3+) 支持 */
+    sslVerify?: boolean;
+
+    /** @desc 开启 http2;微信小程序 */
+    enableHttp2?: boolean;
+
+    /** @desc 开启 quic;微信小程序 */
+    enableQuic?: boolean;
+    /** @desc 开启 cache;微信小程序、字节跳动小程序 2.31.0+ */
+    enableCache?: boolean;
+    /** @desc 开启 httpDNS;微信小程序 */
+    enableHttpDNS?: boolean;
+    /** @desc httpDNS 服务商;微信小程序 */
+    httpDNSServiceId?: string;
+    /** @desc 开启 transfer-encoding chunked;微信小程序 */
+    enableChunked?: boolean;
+    /** @desc wifi下使用移动网络发送请求;微信小程序 */
+    forceCellularNetwork?: boolean;
+    /** @desc 开启后可在headers中编辑cookie;支付宝小程序 10.2.33+ */
+    enableCookie?: boolean;
+    /** @desc 是否开启云加速;百度小程序 3.310.11+ */
+    cloudCache?: boolean | object;
+    /** @desc 控制当前请求是否延时至首屏内容渲染后发送;百度小程序 3.310.11+ */
+    defer?: boolean;
+
+    /** @desc 自定义参数 */
+    custom?: HttpCustom;
+
+    /** @desc 返回当前请求的 task 和 options,不要在这里修改 options */
+    getTask?: (task: T, options: HttpRequestConfig<T>) => void;
+
+    /** @desc 需要上传的文件列表,使用 files 时,filePath 和 name 不生效,仅支持 App、H5 (2.6.15+) */
+    files?: { name?: string; file?: File; uri: string; }[];
+    /** @desc 文件类型,仅支付宝小程序支持且为必填项 */
+    fileType?: HttpFileType;
+    /** @desc 要上传的文件对象,仅 H5 (2.6.15+) 支持 */
+    file?: File;
+    /** @desc 要上传文件资源的路径,使用 files 时,filePath 和 name 不生效 */
+    filePath?: string;
+    /** @desc 文件对应的 key,开发者在服务器端通过这个 key 可以获取到文件二进制内容,使用 files 时,filePath 和 name 不生效 */
+    name?: string;
+    /** @desc 请求中其他额外的 form data */
+    formData?: HttpFormData;
+}
+
+export interface HttpResponse<T = any, D = HttpTask> {
+    data: T;
+    statusCode: number;
+    header: HttpResponseHeader;
+    config: HttpRequestConfig<D>;
+    cookies: string[];
+    errMsg: string;
+    rawData: any;
+}
+
+export interface HttpUploadResponse<T = any, D = HttpTask> {
+    data: T;
+    statusCode: number;
+    config: HttpRequestConfig<D>;
+    errMsg: string;
+    rawData: any;
+}
+
+export interface HttpDownloadResponse extends HttpResponse {
+    tempFilePath: string;
+    apFilePath?: string;
+    filePath?: string;
+    fileContent?: string;
+}
+
+export interface HttpError<T = any, D = HttpTask> {
+    data?: T;
+    statusCode?: number;
+    header?: HttpResponseHeader;
+    config: HttpRequestConfig<D>;
+    cookies?: string[];
+    errMsg: string;
+}
+
+export interface HttpPromise<T = any> extends Promise<HttpResponse<T>> {
+}
+
+export interface HttpInterceptorManager<V, E = V> {
+    use(onFulfilled?: (value: V) => V | Promise<V>, onRejected?: (error: E) => T | Promise<E>): void;
+
+    eject(id: number): void;
+}
+
+export abstract class HttpRequestAbstract {
+    constructor(config?: HttpRequestConfig);
+
+    interceptors: {
+        request: HttpInterceptorManager<HttpRequestConfig>;
+        response: HttpInterceptorManager<HttpResponse, HttpError>;
+    }
+
+    request<T = any, R = HttpResponse<T>, D = HttpRequestTask>(config: HttpRequestConfig<D>): Promise<R>;
+
+    get<T = any, R = HttpResponse<T>, D = HttpRequestTask>(url: string, config?: HttpRequestConfig<D>): Promise<R>;
+
+    delete<T = any, R = HttpResponse<T>, D = HttpRequestTask>(url: string, data?: HttpData, config?: HttpRequestConfig<D>): Promise<R>;
+
+    head<T = any, R = HttpResponse<T>, D = HttpRequestTask>(url: string, data?: HttpData, config?: HttpRequestConfig<D>): Promise<R>;
+
+    options<T = any, R = HttpResponse<T>, D = HttpRequestTask>(url: string, data?: HttpData, config?: HttpRequestConfig<D>): Promise<R>;
+
+    post<T = any, R = HttpResponse<T>, D = HttpRequestTask>(url: string, data?: HttpData, config?: HttpRequestConfig<D>): Promise<R>;
+
+    put<T = any, R = HttpResponse<T>, D = HttpRequestTask>(url: string, data?: HttpData, config?: HttpRequestConfig<D>): Promise<R>;
+
+    config: HttpRequestConfig;
+
+    setConfig<D = HttpTask>(onSend: (config: HttpRequestConfig<D>) => HttpRequestConfig<D>): void;
+
+    connect<T = any, R = HttpResponse<T>, D = HttpRequestTask>(url: string, data?: HttpData, config?: HttpRequestConfig<D>): Promise<R>;
+
+    trace<T = any, R = HttpResponse<T>, D = HttpRequestTask>(url: string, data?: HttpData, config?: HttpRequestConfig<D>): Promise<R>;
+
+    upload<T = any, R = HttpUploadResponse<T>, D = HttpUploadTask>(url: string, config?: HttpRequestConfig<D>): Promise<R>;
+
+    download<T = any, R = HttpDownloadResponse<T>, D = HttpDownloadTask>(url: string, config?: HttpRequestConfig<D>): Promise<R>;
+
+    middleware<T = any, R = HttpResponse<T>, D = HttpTask>(config: HttpRequestConfig<D>): Promise<R>;
+}
+
+declare class HttpRequest extends HttpRequestAbstract {
+}
+
+export default HttpRequest;

+ 2 - 0
uni_modules/leven-js-tools/js_sdk/request/luch-request/index.js

@@ -0,0 +1,2 @@
+import Request from './core/Request'
+export default Request

+ 135 - 0
uni_modules/leven-js-tools/js_sdk/request/luch-request/utils.js

@@ -0,0 +1,135 @@
+'use strict'
+
+// utils is a library of generic helper functions non-specific to axios
+
+var toString = Object.prototype.toString
+
+/**
+ * Determine if a value is an Array
+ *
+ * @param {Object} val The value to test
+ * @returns {boolean} True if value is an Array, otherwise false
+ */
+export function isArray (val) {
+  return toString.call(val) === '[object Array]'
+}
+
+
+/**
+ * Determine if a value is an Object
+ *
+ * @param {Object} val The value to test
+ * @returns {boolean} True if value is an Object, otherwise false
+ */
+export function isObject (val) {
+  return val !== null && typeof val === 'object'
+}
+
+/**
+ * Determine if a value is a Date
+ *
+ * @param {Object} val The value to test
+ * @returns {boolean} True if value is a Date, otherwise false
+ */
+export function isDate (val) {
+  return toString.call(val) === '[object Date]'
+}
+
+/**
+ * Determine if a value is a URLSearchParams object
+ *
+ * @param {Object} val The value to test
+ * @returns {boolean} True if value is a URLSearchParams object, otherwise false
+ */
+export function isURLSearchParams (val) {
+  return typeof URLSearchParams !== 'undefined' && val instanceof URLSearchParams
+}
+
+
+/**
+ * Iterate over an Array or an Object invoking a function for each item.
+ *
+ * If `obj` is an Array callback will be called passing
+ * the value, index, and complete array for each item.
+ *
+ * If 'obj' is an Object callback will be called passing
+ * the value, key, and complete object for each property.
+ *
+ * @param {Object|Array} obj The object to iterate
+ * @param {Function} fn The callback to invoke for each item
+ */
+export function forEach (obj, fn) {
+  // Don't bother if no value provided
+  if (obj === null || typeof obj === 'undefined') {
+    return
+  }
+
+  // Force an array if not already something iterable
+  if (typeof obj !== 'object') {
+    /*eslint no-param-reassign:0*/
+    obj = [obj]
+  }
+
+  if (isArray(obj)) {
+    // Iterate over array values
+    for (var i = 0, l = obj.length; i < l; i++) {
+      fn.call(null, obj[i], i, obj)
+    }
+  } else {
+    // Iterate over object keys
+    for (var key in obj) {
+      if (Object.prototype.hasOwnProperty.call(obj, key)) {
+        fn.call(null, obj[key], key, obj)
+      }
+    }
+  }
+}
+
+/**
+ * 是否为boolean 值
+ * @param val
+ * @returns {boolean}
+ */
+export function isBoolean(val) {
+  return typeof val === 'boolean'
+}
+
+/**
+ * 是否为真正的对象{} new Object
+ * @param {any} obj - 检测的对象
+ * @returns {boolean}
+ */
+export function isPlainObject(obj) {
+  return Object.prototype.toString.call(obj) === '[object Object]'
+}
+
+
+
+/**
+ * Function equal to merge with the difference being that no reference
+ * to original objects is kept.
+ *
+ * @see merge
+ * @param {Object} obj1 Object to merge
+ * @returns {Object} Result of all merge properties
+ */
+export function deepMerge(/* obj1, obj2, obj3, ... */) {
+  let result = {}
+  function assignValue(val, key) {
+    if (typeof result[key] === 'object' && typeof val === 'object') {
+      result[key] = deepMerge(result[key], val)
+    } else if (typeof val === 'object') {
+      result[key] = deepMerge({}, val)
+    } else {
+      result[key] = val
+    }
+  }
+  for (let i = 0, l = arguments.length; i < l; i++) {
+    forEach(arguments[i], assignValue)
+  }
+  return result
+}
+
+export function isUndefined (val) {
+  return typeof val === 'undefined'
+}

+ 264 - 0
uni_modules/leven-js-tools/js_sdk/request/luch-request/utils/clone.js

@@ -0,0 +1,264 @@
+/* eslint-disable */
+var clone = (function() {
+  'use strict';
+
+  function _instanceof(obj, type) {
+    return type != null && obj instanceof type;
+  }
+
+  var nativeMap;
+  try {
+    nativeMap = Map;
+  } catch(_) {
+    // maybe a reference error because no `Map`. Give it a dummy value that no
+    // value will ever be an instanceof.
+    nativeMap = function() {};
+  }
+
+  var nativeSet;
+  try {
+    nativeSet = Set;
+  } catch(_) {
+    nativeSet = function() {};
+  }
+
+  var nativePromise;
+  try {
+    nativePromise = Promise;
+  } catch(_) {
+    nativePromise = function() {};
+  }
+
+  /**
+   * Clones (copies) an Object using deep copying.
+   *
+   * This function supports circular references by default, but if you are certain
+   * there are no circular references in your object, you can save some CPU time
+   * by calling clone(obj, false).
+   *
+   * Caution: if `circular` is false and `parent` contains circular references,
+   * your program may enter an infinite loop and crash.
+   *
+   * @param `parent` - the object to be cloned
+   * @param `circular` - set to true if the object to be cloned may contain
+   *    circular references. (optional - true by default)
+   * @param `depth` - set to a number if the object is only to be cloned to
+   *    a particular depth. (optional - defaults to Infinity)
+   * @param `prototype` - sets the prototype to be used when cloning an object.
+   *    (optional - defaults to parent prototype).
+   * @param `includeNonEnumerable` - set to true if the non-enumerable properties
+   *    should be cloned as well. Non-enumerable properties on the prototype
+   *    chain will be ignored. (optional - false by default)
+   */
+  function clone(parent, circular, depth, prototype, includeNonEnumerable) {
+    if (typeof circular === 'object') {
+      depth = circular.depth;
+      prototype = circular.prototype;
+      includeNonEnumerable = circular.includeNonEnumerable;
+      circular = circular.circular;
+    }
+    // maintain two arrays for circular references, where corresponding parents
+    // and children have the same index
+    var allParents = [];
+    var allChildren = [];
+
+    var useBuffer = typeof Buffer != 'undefined';
+
+    if (typeof circular == 'undefined')
+      circular = true;
+
+    if (typeof depth == 'undefined')
+      depth = Infinity;
+
+    // recurse this function so we don't reset allParents and allChildren
+    function _clone(parent, depth) {
+      // cloning null always returns null
+      if (parent === null)
+        return null;
+
+      if (depth === 0)
+        return parent;
+
+      var child;
+      var proto;
+      if (typeof parent != 'object') {
+        return parent;
+      }
+
+      if (_instanceof(parent, nativeMap)) {
+        child = new nativeMap();
+      } else if (_instanceof(parent, nativeSet)) {
+        child = new nativeSet();
+      } else if (_instanceof(parent, nativePromise)) {
+        child = new nativePromise(function (resolve, reject) {
+          parent.then(function(value) {
+            resolve(_clone(value, depth - 1));
+          }, function(err) {
+            reject(_clone(err, depth - 1));
+          });
+        });
+      } else if (clone.__isArray(parent)) {
+        child = [];
+      } else if (clone.__isRegExp(parent)) {
+        child = new RegExp(parent.source, __getRegExpFlags(parent));
+        if (parent.lastIndex) child.lastIndex = parent.lastIndex;
+      } else if (clone.__isDate(parent)) {
+        child = new Date(parent.getTime());
+      } else if (useBuffer && Buffer.isBuffer(parent)) {
+        if (Buffer.from) {
+          // Node.js >= 5.10.0
+          child = Buffer.from(parent);
+        } else {
+          // Older Node.js versions
+          child = new Buffer(parent.length);
+          parent.copy(child);
+        }
+        return child;
+      } else if (_instanceof(parent, Error)) {
+        child = Object.create(parent);
+      } else {
+        if (typeof prototype == 'undefined') {
+          proto = Object.getPrototypeOf(parent);
+          child = Object.create(proto);
+        }
+        else {
+          child = Object.create(prototype);
+          proto = prototype;
+        }
+      }
+
+      if (circular) {
+        var index = allParents.indexOf(parent);
+
+        if (index != -1) {
+          return allChildren[index];
+        }
+        allParents.push(parent);
+        allChildren.push(child);
+      }
+
+      if (_instanceof(parent, nativeMap)) {
+        parent.forEach(function(value, key) {
+          var keyChild = _clone(key, depth - 1);
+          var valueChild = _clone(value, depth - 1);
+          child.set(keyChild, valueChild);
+        });
+      }
+      if (_instanceof(parent, nativeSet)) {
+        parent.forEach(function(value) {
+          var entryChild = _clone(value, depth - 1);
+          child.add(entryChild);
+        });
+      }
+
+      for (var i in parent) {
+        var attrs = Object.getOwnPropertyDescriptor(parent, i);
+        if (attrs) {
+          child[i] = _clone(parent[i], depth - 1);
+        }
+
+        try {
+          var objProperty = Object.getOwnPropertyDescriptor(parent, i);
+          if (objProperty.set === 'undefined') {
+            // no setter defined. Skip cloning this property
+            continue;
+          }
+          child[i] = _clone(parent[i], depth - 1);
+        } catch(e){
+          if (e instanceof TypeError) {
+            // when in strict mode, TypeError will be thrown if child[i] property only has a getter
+            // we can't do anything about this, other than inform the user that this property cannot be set.
+            continue
+          } else if (e instanceof ReferenceError) {
+            //this may happen in non strict mode
+            continue
+          }
+        }
+
+      }
+
+      if (Object.getOwnPropertySymbols) {
+        var symbols = Object.getOwnPropertySymbols(parent);
+        for (var i = 0; i < symbols.length; i++) {
+          // Don't need to worry about cloning a symbol because it is a primitive,
+          // like a number or string.
+          var symbol = symbols[i];
+          var descriptor = Object.getOwnPropertyDescriptor(parent, symbol);
+          if (descriptor && !descriptor.enumerable && !includeNonEnumerable) {
+            continue;
+          }
+          child[symbol] = _clone(parent[symbol], depth - 1);
+          Object.defineProperty(child, symbol, descriptor);
+        }
+      }
+
+      if (includeNonEnumerable) {
+        var allPropertyNames = Object.getOwnPropertyNames(parent);
+        for (var i = 0; i < allPropertyNames.length; i++) {
+          var propertyName = allPropertyNames[i];
+          var descriptor = Object.getOwnPropertyDescriptor(parent, propertyName);
+          if (descriptor && descriptor.enumerable) {
+            continue;
+          }
+          child[propertyName] = _clone(parent[propertyName], depth - 1);
+          Object.defineProperty(child, propertyName, descriptor);
+        }
+      }
+
+      return child;
+    }
+
+    return _clone(parent, depth);
+  }
+
+  /**
+   * Simple flat clone using prototype, accepts only objects, usefull for property
+   * override on FLAT configuration object (no nested props).
+   *
+   * USE WITH CAUTION! This may not behave as you wish if you do not know how this
+   * works.
+   */
+  clone.clonePrototype = function clonePrototype(parent) {
+    if (parent === null)
+      return null;
+
+    var c = function () {};
+    c.prototype = parent;
+    return new c();
+  };
+
+// private utility functions
+
+  function __objToStr(o) {
+    return Object.prototype.toString.call(o);
+  }
+  clone.__objToStr = __objToStr;
+
+  function __isDate(o) {
+    return typeof o === 'object' && __objToStr(o) === '[object Date]';
+  }
+  clone.__isDate = __isDate;
+
+  function __isArray(o) {
+    return typeof o === 'object' && __objToStr(o) === '[object Array]';
+  }
+  clone.__isArray = __isArray;
+
+  function __isRegExp(o) {
+    return typeof o === 'object' && __objToStr(o) === '[object RegExp]';
+  }
+  clone.__isRegExp = __isRegExp;
+
+  function __getRegExpFlags(re) {
+    var flags = '';
+    if (re.global) flags += 'g';
+    if (re.ignoreCase) flags += 'i';
+    if (re.multiline) flags += 'm';
+    return flags;
+  }
+  clone.__getRegExpFlags = __getRegExpFlags;
+
+  return clone;
+})();
+
+export default clone

+ 331 - 0
uni_modules/leven-js-tools/js_sdk/string/index.js

@@ -0,0 +1,331 @@
+/**
+ * 字符串类
+ */
+export class StringManager {
+  constructor() {}
+
+  /**
+   * 获取uuid
+   * @param {Number} len uuid的长度
+   * @param {Boolean} first 默认的首字母
+   * @param {Nubmer} radix 生成uuid的基数(意味着返回的字符串都是这个基数),2-二进制,8-八进制,10-十进制,16-十六进制
+   */
+  uuid = (len = 32, first = "", radix = null) => {
+    const chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split('')
+    const 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 (first != "") {
+      uuid.shift()
+      return `${first}${uuid.join('')}`
+    }
+    return uuid.join('')
+  }
+
+  /**
+   * @description 去除空格
+   * @param String str 需要去除空格的字符串
+   * @param String pos both(左右)|left|right|all 默认both
+   */
+  trim = (str, pos = 'both') => {
+    str = String(str)
+    if (pos == 'both') {
+      return str.replace(/^\s+|\s+$/g, '')
+    }
+    if (pos == 'left') {
+      return str.replace(/^\s*/, '')
+    }
+    if (pos == 'right') {
+      return str.replace(/(\s*$)/g, '')
+    }
+    if (pos == 'all') {
+      return str.replace(/\s+/g, '')
+    }
+    return str
+  }
+
+  /**
+   * 验证字符串
+   */
+  isString = (str) => {
+    return typeof str === 'string'
+  }
+
+  /**
+   * 验证是否包含某个值
+   */
+
+  isContains = (str1, str2) => {
+    return str1.indexOf(str2) >= 0
+  }
+
+  /**
+   * 是否json字符串
+   */
+  isJsonString = (str) => {
+    if (typeof str === 'string') {
+      try {
+        const obj = JSON.parse(str)
+        if (typeof obj === 'object' && obj) {
+          return true
+        }
+        return false
+      } catch (e) {
+        return false
+      }
+    }
+    return false
+  }
+
+  /**
+   * 字节格式化
+   */
+  sizeFormat = (size) => {
+    if (size < 1024) {
+      return size + 'B';
+    } else if (size < (1024 * 1024)) {
+      var temp = size / 1024;
+      temp = temp.toFixed(2);
+      return temp + 'KB';
+    } else if (size < (1024 * 1024 * 1024)) {
+      var temp = size / (1024 * 1024);
+      temp = temp.toFixed(2);
+      return temp + 'MB';
+    } else {
+      var temp = size / (1024 * 1024 * 1024);
+      temp = temp.toFixed(2);
+      return temp + 'GB';
+    }
+  }
+
+  /**参数说明:
+   * 根据长度截取先使用字符串,超长部分追加… 
+   * str 对象字符串 
+   * len 目标字节长度 
+   * 返回值: 处理结果字符串 
+   */
+  substring = (str, len = 10, end = "...") => {
+    if (str) {
+      if (str.length <= len) {
+        return str;
+      }
+      let strlen = 0;
+      let s = "";
+      for (let i = 0; i < str.length; i++) {
+        s = s + str.charAt(i);
+        strlen = strlen + 1;
+        if (strlen > len) {
+          return s.substring(0, s.length - 1) + end;
+        }
+      }
+      return s;
+    } else {
+      return '';
+    }
+  }
+
+  /**
+   * 隐藏字符
+   * @param str 原始字符串
+   * @param starCount 显示隐藏字符的个数
+   * @param prevCount 开始显示的字符串个数
+   * @param endCount 结束显示的字符串个数
+   */
+  hideString = (str, starCount = 4, prevCount = 3, endCount = 4) => {
+    if (!str) {
+      return "";
+    }
+    if (str <= prevCount || str.length <= (prevCount + endCount)) {
+      return str;
+    }
+
+    let starStr = "******************************";
+    let startStr = str.substr(0, prevCount);
+    let endStr = str.substr(str.length - endCount, endCount);
+
+    return startStr + starStr.substr(0, starCount) + endStr;
+  }
+
+  /**
+   * 字符串反转
+   */
+  reverse(str) {
+    return str.split('').reverse().join('');
+  }
+
+  /**
+   * 随机字符串
+   * @param length  生成的长度
+   * @param num  是否包含数字
+   * @param lowerLetters  是否包含小写字母
+   * @param upperLetters  是否包含大写字母
+   * @param specialCharacters  是否包含特殊字符
+   */
+  random = (length, num = true, lowerLetters = true, upperLetters = true, specialCharacters = true) => {
+    // 数字
+    let numbers = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'];
+    // 小写字母
+    let lowers = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'];
+    // 大写字母
+    let uppers = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'];
+    // 特殊字符
+    let specials = ['#', '!', '@', '$', '%', '^', '&'];
+    // 可用的字符集合
+    let values = [];
+    if (num) {
+      values = values.concat(numbers);
+    }
+    if (lowerLetters) {
+      values = values.concat(lowers);
+    }
+    if (upperLetters) {
+      values = values.concat(uppers);
+    }
+    if (specialCharacters) {
+      values = values.concat(specials);
+    }
+    // 返回值
+    let returnArr = [];
+    if (length > 0) {
+      for (let i = 0; i < length; i++) {
+        // 去除一个随机值
+        let index = Math.floor(Math.random() * values.length);
+        returnArr.push(values[index]);
+      }
+    }
+
+    return returnArr.join("");
+  }
+
+  /**
+   * 转大写
+   */
+  toUpper = (str) => {
+    if (this.isString(str)) {
+      return str.toUpperCase()
+    }
+    return str;
+  }
+
+  /**
+   * 转小写
+   */
+  toLower = (str) => {
+    if (this.isString(str)) {
+      return str.toLowerCase()
+    }
+    return str;
+  }
+
+  /**
+   * 下划线转驼峰
+   */
+  underlineToHump = (str) => {
+    return str.replace(/\_(\w)/g, function(all, letter) {
+      return letter.toUpperCase();
+    });
+  }
+
+  /**
+   * 驼峰转下划线
+   */
+  humpToUnderline = (str) => {
+    return str.replace(/([A-Z])/g, "_$1").toLowerCase();
+  }
+
+  /**
+   *@param {string} url 完整的URL地址
+   *@returns {object} 自定义的对象
+   *@description 用法示例:var myURL = parseURL('http://abc.com:8080/dir/index.html?id=255&m=hello#top');
+   myURL.file='index.html'
+   myURL.hash= 'top'
+   myURL.host= 'abc.com'
+   myURL.query= '?id=255&m=hello'
+   myURL.params= Object = { id: 255, m: hello }
+   myURL.path= '/dir/index.html'
+   myURL.segments= Array = ['dir', 'index.html']
+   myURL.port= '8080'
+   myURL.protocol= 'http'
+   myURL.source= 'http://abc.com:8080/dir/index.html?id=255&m=hello#top'
+   */
+  parseUrl = (url) => {
+    var a = document.createElement('a');
+    a.href = url;
+    return {
+      source: url,
+      protocol: a.protocol.replace(':', ''),
+      host: a.hostname,
+      port: a.port,
+      query: a.search,
+      params: (function() {
+        var ret = {},
+          seg = a.search.replace(/^\?/, '').split('&'),
+          len = seg.length,
+          i = 0,
+          s;
+        for (; i < len; i++) {
+          if (!seg[i]) {
+            continue;
+          }
+          s = seg[i].split('=');
+          ret[s[0]] = s[1];
+        }
+        return ret;
+      })(),
+      file: (a.pathname.match(/\/([^\/?#]+)$/i) || [, ''])[1],
+      hash: a.hash.replace('#', ''),
+      path: a.pathname.replace(/^([^\/])/, '/$1'),
+      relative: (a.href.match(/tps?:\/\/[^\/]+(.+)/) || [, ''])[1],
+      segments: a.pathname.replace(/^\//, '').split('/')
+    };
+  }
+
+  /**
+   * 将字符串转换为16进制
+   */
+  stringToHex = (str, isUrlEncode = true) => {
+    let val = "";
+    if (isUrlEncode) {
+      // 如果包含特殊字符或中文先转换
+      str = encodeURIComponent(str);
+    }
+    for (let i = 0; i < str.length; i++) {
+      val += str.charCodeAt(i).toString(16);
+    }
+    return val;
+  }
+
+  /**
+   * 十六进制转换为字符串
+   * @param {*} str 
+   */
+  hexToString = (str, isUrlDecode = true) => {
+    var val = "",
+      len = str.length / 2;
+    for (var i = 0; i < len; i++) {
+      val += String.fromCharCode(parseInt(str.substr(i * 2, 2), 16));
+    }
+    if (!isUrlDecode) {
+      return val;
+    }
+    // 转换结果
+    return decodeURIComponent(val);
+  }
+}

+ 137 - 0
uni_modules/leven-js-tools/js_sdk/timer/index.js

@@ -0,0 +1,137 @@
+/**
+ * 定时器管理类
+ */
+import {
+  EncryptManager
+} from "../encrypt/index.js"
+export class TimerManager {
+  /**
+   * @param timeStep 时间间隔(默认为1000)
+   */
+  constructor(timeStep = 1000) {
+    // 时间间隔(毫秒)
+    this._timeStep = timeStep;
+    // 是否运行
+    this._isRunning = false;
+    // 是否暂停
+    this._isPaused = false;
+    // 定时器id
+    this._timer = null;
+    // 执行方法对象
+    this._funcList = {};
+    // 加密类
+    this.encryptManager = new EncryptManager();
+  }
+
+  /**
+   * 添加
+   * @param 执行方法
+   */
+  add = (func, name) => {
+    if (!name) {
+      name = this.encryptManager.md5(Date.parse(new Date()))
+    }
+    // this._funcList.push(func);
+    this._funcList[name] = func;
+    if (this._isRunning || this._isPaused) return;
+    this.run();
+  }
+
+  /**
+   * 开始
+   */
+  start = () => {
+    this._isPaused = false;
+    this.run();
+  }
+
+  /**
+   * 运行
+   */
+  run = () => {
+    this._timer && clearTimeout(this._timer);
+    this._timer = null;
+    if (this._isPaused) return;
+    let funcListValues = Object.values(this._funcList);
+    if (funcListValues.length == 0) {
+      this._isRunning = false;
+      return;
+    }
+
+    this._isRunning = true;
+
+    let funcListNames = Object.keys(this._funcList);
+    // 遍历方法列表执行添加的方法
+    for (let i = 0; i < funcListValues.length; i++) {
+      let func = funcListValues[i];
+      // console.log(name);
+
+      // 如果有返回值为false则删除
+      if (func() === false) {
+        let name = funcListNames[i];
+        delete this._funcList[name];
+      }
+      func = null;
+    }
+
+    this._timer = setTimeout(this.run, this._timeStep);
+  }
+
+  /**
+   * 暂停
+   */
+  stop = () => {
+    this._isPaused = true;
+  }
+
+  /**
+   * 清除所有定时器
+   */
+  clear = () => {
+    this._timer && clearTimeout(this._timer);
+    this._timer = null;
+    this._isRunning = false;
+    this._isPaused = false;
+    // this._funcList = [];
+    this._funcList = {};
+  }
+
+  /**
+   * 移除一个定时器任务
+   */
+  remove = (name) => {
+    if (this._funcList.hasOwnProperty(name)) {
+      delete this._funcList[name];
+    }
+  }
+
+  /**
+   * 设置一个定时器
+   */
+  setTimer = ({
+    name,
+    seconds,
+    onChange,
+    onComplate
+  } = params) => {
+    // 移除已经设置的当前定时器
+    this.remove(name);
+    let count = 0;
+    this.add(() => {
+      count++;
+      if (count >= seconds) {
+        this.remove(name);
+        if (onComplate && typeof onComplate === "function") {
+          onComplate(true)
+        }
+      } else {
+        if (onChange && typeof onChange === "function") {
+          onChange({
+            outSeconds: count,
+            remainSeconds: seconds - count
+          });
+        }
+      }
+    }, name)
+  }
+}

Файловите разлики са ограничени, защото са твърде много
+ 1 - 0
uni_modules/leven-js-tools/js_sdk/utils/crypto-js-4.1.1.min.js.js


Файловите разлики са ограничени, защото са твърде много
+ 4934 - 0
uni_modules/leven-js-tools/js_sdk/utils/decimal.js


+ 167 - 0
uni_modules/leven-js-tools/js_sdk/utils/digit.js

@@ -0,0 +1,167 @@
+let _boundaryCheckingState = true; // 是否进行越界检查的全局开关
+
+/**
+ * 把错误的数据转正
+ * @private
+ * @example strip(0.09999999999999998)=0.1
+ */
+function strip(num, precision = 15) {
+  return +parseFloat(Number(num).toPrecision(precision));
+}
+
+/**
+ * Return digits length of a number
+ * @private
+ * @param {*number} num Input number
+ */
+function digitLength(num) {
+  // Get digit length of e
+  const eSplit = num.toString().split(/[eE]/);
+  const len = (eSplit[0].split('.')[1] || '').length - +(eSplit[1] || 0);
+  return len > 0 ? len : 0;
+}
+
+/**
+ * 把小数转成整数,如果是小数则放大成整数
+ * @private
+ * @param {*number} num 输入数
+ */
+function float2Fixed(num) {
+  if (num.toString().indexOf('e') === -1) {
+    return Number(num.toString().replace('.', ''));
+  }
+  const dLen = digitLength(num);
+  return dLen > 0 ? strip(Number(num) * Math.pow(10, dLen)) : Number(num);
+}
+
+/**
+ * 检测数字是否越界,如果越界给出提示
+ * @private
+ * @param {*number} num 输入数
+ */
+function checkBoundary(num) {
+  if (_boundaryCheckingState) {
+    if (num > Number.MAX_SAFE_INTEGER || num < Number.MIN_SAFE_INTEGER) {
+      console.warn(`${num} 超出了精度限制,结果可能不正确`);
+    }
+  }
+}
+
+/**
+ * 把递归操作扁平迭代化
+ * @param {number[]} arr 要操作的数字数组
+ * @param {function} operation 迭代操作
+ * @private
+ */
+function iteratorOperation(arr, operation) {
+  const [num1, num2, ...others] = arr;
+  let res = operation(num1, num2);
+
+  others.forEach((num) => {
+    res = operation(res, num);
+  });
+
+  return res;
+}
+
+/**
+ * 高精度乘法
+ * @export
+ */
+export function times(...nums) {
+  if (nums.length > 2) {
+    return iteratorOperation(nums, times);
+  }
+
+  const [num1, num2] = nums;
+  const num1Changed = float2Fixed(num1);
+  const num2Changed = float2Fixed(num2);
+  const baseNum = digitLength(num1) + digitLength(num2);
+  const leftValue = num1Changed * num2Changed;
+
+  checkBoundary(leftValue);
+
+  return leftValue / Math.pow(10, baseNum);
+}
+
+/**
+ * 高精度加法
+ * @export
+ */
+export function plus(...nums) {
+  if (nums.length > 2) {
+    return iteratorOperation(nums, plus);
+  }
+
+  const [num1, num2] = nums;
+  // 取最大的小数位
+  const baseNum = Math.pow(10, Math.max(digitLength(num1), digitLength(num2)));
+  // 把小数都转为整数然后再计算
+  return (times(num1, baseNum) + times(num2, baseNum)) / baseNum;
+}
+
+/**
+ * 高精度减法
+ * @export
+ */
+export function minus(...nums) {
+  if (nums.length > 2) {
+    return iteratorOperation(nums, minus);
+  }
+
+  const [num1, num2] = nums;
+  const baseNum = Math.pow(10, Math.max(digitLength(num1), digitLength(num2)));
+  return (times(num1, baseNum) - times(num2, baseNum)) / baseNum;
+}
+
+/**
+ * 高精度除法
+ * @export
+ */
+export function divide(...nums) {
+  if (nums.length > 2) {
+    return iteratorOperation(nums, divide);
+  }
+
+  const [num1, num2] = nums;
+  const num1Changed = float2Fixed(num1);
+  const num2Changed = float2Fixed(num2);
+  checkBoundary(num1Changed);
+  checkBoundary(num2Changed);
+  // 重要,这里必须用strip进行修正
+  return times(num1Changed / num2Changed, strip(Math.pow(10, digitLength(num2) - digitLength(num1))));
+}
+
+/**
+ * 四舍五入
+ * @export
+ */
+export function round(num, ratio) {
+  const base = Math.pow(10, ratio);
+  let result = divide(Math.round(Math.abs(times(num, base))), base);
+  if (num < 0 && result !== 0) {
+    result = times(result, -1);
+  }
+  // 位数不足则补0
+  return result;
+}
+
+/**
+ * 是否进行边界检查,默认开启
+ * @param flag 标记开关,true 为开启,false 为关闭,默认为 true
+ * @export
+ */
+export function enableBoundaryChecking(flag = true) {
+  _boundaryCheckingState = flag;
+}
+
+
+export default {
+  times,
+  plus,
+  minus,
+  divide,
+  round,
+  enableBoundaryChecking,
+};
+

+ 251 - 0
uni_modules/leven-js-tools/js_sdk/validate/index.js

@@ -0,0 +1,251 @@
+/**
+ * 验证类
+ */
+export class ValidateManager {
+  constructor() {}
+
+  /**
+   * 验证电子邮箱格式
+   */
+  email = (value) => {
+    return /^\w+((-\w+)|(\.\w+))*\@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z0-9]+$/.test(value)
+  }
+
+  /**
+   * 验证手机格式
+   */
+  mobile = (value) => {
+    return /^1([3456789]\d|4[5-9]|6[1-2,4-7]|7[0-8])\d{8}$/.test(value)
+  }
+
+  /**
+   * 验证URL格式
+   */
+  url = (value) => {
+    return /^((https|http|ftp|rtsp|mms):\/\/)(([0-9a-zA-Z_!~*'().&=+$%-]+: )?[0-9a-zA-Z_!~*'().&=+$%-]+@)?(([0-9]{1,3}.){3}[0-9]{1,3}|([0-9a-zA-Z_!~*'()-]+.)*([0-9a-zA-Z][0-9a-zA-Z-]{0,61})?[0-9a-zA-Z].[a-zA-Z]{2,6})(:[0-9]{1,4})?((\/?)|(\/[0-9a-zA-Z_!~*'().;?:@&=+$,%#-]+)+\/?)$/
+      .test(value)
+  }
+
+  /**
+   * 身份证验证
+   */
+  idCard = (value) => {
+    if (value.length == 15) {
+      // 一代身份证
+      let year = value.substring(6, 8);
+      let month = value.substring(8, 10);
+      let day = value.substring(10, 12);
+      let temp_date = new Date(year, parseFloat(month) - 1, parseFloat(day));
+      // 对于老身份证中的你年龄则不需考虑千年虫问题而使用getYear()方法
+      if (temp_date.getYear() != parseFloat(year) || temp_date.getMonth() != parseFloat(month) - 1 || temp_date
+        .getDate() != parseFloat(day)) {
+        return false;
+      } else {
+        return true;
+      }
+    } else {
+      // 二代身份证
+      // 1 "验证通过!", 0 //校验不通过
+      let format =
+        /^(([1][1-5])|([2][1-3])|([3][1-7])|([4][1-6])|([5][0-4])|([6][1-5])|([7][1])|([8][1-2]))\d{4}(([1][9]\d{2})|([2]\d{3}))(([0][1-9])|([1][0-2]))(([0][1-9])|([1-2][0-9])|([3][0-1]))\d{3}[0-9xX]$/;
+      //号码规则校验
+      if (!format.test(value)) {
+        return false;
+      }
+      //区位码校验
+      //出生年月日校验   前正则限制起始年份为1900;
+      let year = value.substr(6, 4), //身份证年
+        month = value.substr(10, 2), //身份证月
+        date = value.substr(12, 2), //身份证日
+        time = Date.parse(month + '-' + date + '-' + year), //身份证日期时间戳date
+        now_time = Date.parse(new Date()), //当前时间戳
+        dates = new Date(year, month, 0).getDate(); //身份证当月天数
+      if (time > now_time || date > dates) {
+        return false;
+      }
+      //校验码判断
+      var c = new Array(7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2); //系数
+      var b = new Array('1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'); //校验码对照表
+      var id_array = value.split('');
+      var sum = 0;
+      for (var k = 0; k < 17; k++) {
+        sum += parseInt(id_array[k]) * parseInt(c[k]);
+      }
+      if (id_array[17].toUpperCase() != b[sum % 11].toUpperCase()) {
+        return false;
+      }
+      return true;
+    }
+  }
+
+  /**
+   * 车牌号
+   */
+  carNumber = (value) => {
+    // 新能源车牌
+    let xreg = /^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领A-Z]{1}[A-Z]{1}(([0-9]{5}[DF]$)|([DF][A-HJ-NP-Z0-9][0-9]{4}$))/
+    // 旧车牌
+    let 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)
+    }
+    if (value.length === 8) {
+      return xreg.test(value)
+    }
+    return false
+  }
+
+  /**
+   * 全部中文
+   */
+  chinese = (value) => {
+    let reg = /^[\u4e00-\u9fa5]+$/gi
+    return reg.test(value)
+  }
+
+  /**
+   * 包含中文
+   */
+  containChinese = (value) => {
+    if (/.*[\u4e00-\u9fa5]+.*$/.test(value)) {
+      return true;
+    }
+    return false;
+  }
+
+  /**
+   * 是否以数字开头
+   * 规则:检查字符串是否是只是含有字母数字或下划线,不能以数字开头
+   */
+  isUsername = (value) => {
+    let reg = /^[0-9a-zA-Z_]*$/g;
+    let enOrNumber = reg.test(value);
+    if (enOrNumber) {
+      if (/^[0-9]/.test(value.substr(0, 1))) {
+        return false;
+      }
+      return true;
+    } else {
+      return false;
+    }
+  }
+
+  /**
+   * 是否固定电话
+   */
+  telephone = (value) => {
+    let reg = /^\d{3,4}-\d{7,8}(-\d{3,4})?$/
+    return reg.test(value)
+  }
+
+  /**
+   * 判断是否为空
+   */
+  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 (value === 0 || isNaN(value)) return true
+        break
+      case 'object':
+        if (value === null || value.length === 0) return true
+        for (const i in value) {
+          return false
+        }
+        return true
+    }
+    return false
+  }
+
+  /**
+   * 图片格式
+   */
+  image = (value) => {
+    let newValue = value.split('?')[0]
+    let image_regexp = /\.(jpeg|jpg|gif|png|svg|webp|jfif|bmp|dpg)/i
+    return image_regexp.test(newValue)
+  }
+
+  /**
+   * 视频格式
+   */
+  video = (value) => {
+    let video_regexp = /\.(mp4|mpg|mpeg|dat|asf|avi|rm|rmvb|mov|wmv|flv|mkv|m3u8)/i
+    return video_regexp.test(value)
+  }
+
+  /**
+   * 全部字母
+   */
+  letter = (value) => {
+    return /^[a-z]+$/i.test(value);
+  }
+
+  /**
+   * 字母和空格
+   */
+  letterSpace = (value) => {
+    return /^[a-z\s]*$/i.test(value);
+  }
+
+  /**
+   * 字母和数字
+   */
+  letterNumeric = (value) => {
+    return /^[a-z0-9]+$/i.test(value);
+  }
+
+  /**
+   * 字母数字和空格
+   */
+  letterNumericSpace = (value) => {
+    return /^[a-z0-9\s]*$/i.test(value);
+  }
+
+  /**
+   * 数字和空格
+   */
+  numericSpace = (value) => {
+    return /^[\d\s]*$/.test(value);
+  }
+
+  /**
+   * 全部小写
+   */
+  lower = (value) => {
+    return /^[a-z]+$/.test(value);
+  }
+
+  /**
+   * 全部大写
+   */
+  upper = (value) => {
+    return /^[A-Z]+$/.test(value);
+  }
+
+  /**
+   * 判断是否是微信浏览器
+   */
+  isWechat = () => {
+    let ua = navigator.userAgent.toLowerCase();
+    if (ua.match(/MicroMessenger/i) == "micromessenger") {
+      return true;
+    } else {
+      return false;
+    }
+  }
+
+  /**
+   * 判断是否是支付宝浏览器
+   */
+  isAlipay = () => {
+    return /AlipayClient/.test(window.navigator.userAgent);
+  }
+}

+ 84 - 0
uni_modules/leven-js-tools/package.json

@@ -0,0 +1,84 @@
+{
+  "id": "leven-js-tools",
+  "displayName": "js实用工具包",
+  "version": "1.1.6",
+  "description": "js实用工具包让您的开发得心应手",
+  "keywords": [
+    "js",
+    "工具",
+    "jssdk",
+    "工具包"
+],
+  "repository": "",
+  "engines": {
+    "HBuilderX": "^3.4.15"
+  },
+  "dcloudext": {
+    "type": "sdk-js",
+    "sale": {
+      "regular": {
+        "price": "0.00"
+      },
+      "sourcecode": {
+        "price": "0.00"
+      }
+    },
+    "contact": {
+      "qq": "334106817"
+    },
+    "declaration": {
+      "ads": "无",
+      "data": "插件不采集任何数据",
+      "permissions": "无"
+    },
+    "npmurl": ""
+  },
+  "uni_modules": {
+    "dependencies": [],
+    "encrypt": [],
+    "platforms": {
+      "cloud": {
+        "tcb": "y",
+        "aliyun": "y"
+      },
+      "client": {
+        "Vue": {
+          "vue2": "y",
+          "vue3": "y"
+        },
+        "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",
+          "飞书": "y",
+          "京东": "y"
+        },
+        "快应用": {
+          "华为": "y",
+          "联盟": "y"
+        }
+      }
+    }
+  }
+}

+ 123 - 0
uni_modules/leven-js-tools/readme.md

@@ -0,0 +1,123 @@
+# leven-js-tools
+## 介绍
+
+插件为uniapp前端js工具包,工具包包含了众多模块,数组、颜色、日期、加解密、函数、数字、对象、请求、字符串、验证等模块,可以让您的开发得心应手,不需要为了一个功能需要花费大量的时间从网上再去搜索,本插件已集成了大部分常用的功能,本插件会持续更新。
+
+## 超级福利
+ [超级福利,点击查看](https://z7poo9xpe4.k.topthink.com/@ln2qwd82dg)
+
+## 使用文档
+
+您也可以参考以下链接的使用文档 
+
+请参考:[使用文档](https://z7poo9xpe4.k.topthink.com/@5q2g35mreg)
+
+## 全局引入
+
+
+在main.js文件中添加以下代码
+
+
+```
+// 加载js工具插件
+import jsTools from "uni_modules/leven-js-tools/index.js"
+Vue.use(jsTools);
+```
+
+
+然后就可以直接使用了,不需要在页面中单独引入插件
+
+## 使用方式
+
+
+每一种插件都是以uni.$lv开头,具体的功能会在单独的章节中讲解  
+
+1.数组
+
+
+```
+uni.$lv.array
+```
+
+
+2.颜色
+
+
+```
+uni.$lv.color
+```
+
+
+3.日期
+
+
+```
+uni.$lv.date
+```
+
+
+4.加解密
+
+
+```
+uni.$lv.encrypt
+```
+
+
+5.函数
+
+
+```
+uni.$lv.func
+```
+
+
+6.数字
+
+
+```
+uni.$lv.number
+```
+
+
+7.对象
+
+
+```
+uni.$lv.object
+```
+
+
+8.请求
+
+
+```
+uni.$lv.request
+```
+
+
+9.字符串
+
+
+```
+uni.$lv.string
+```
+
+
+10.定时器
+
+
+```
+uni.$lv.timer
+```
+
+
+11.验证器
+
+
+```
+uni.$lv.validate
+```
+
+
+> 如有任何疑问或建议可在下方评论区提出,谢谢!