Fly 2 years ago
parent
commit
bd8820f2d6

+ 4 - 2
components/headModules/reverse-back.vue

@@ -1,7 +1,6 @@
 <template>
 	<view class="reverse-back-box" @click.stop="reverseBackBtn">
-		<!-- <image class="reverse-back-icon" src="../../static/logo.png" mode="aspectFit"></image> -->
-		<u-icon name="arrow-leftward" size="20" color="#000"></u-icon>
+		<text class="iconfont">&#xe603;</text>
 	</view>
 </template>
 
@@ -38,6 +37,9 @@
 		height: 37rpx;
 		display: flex;
 		align-items: center;
+		height: 100%;
+		font-size: 32rpx;
+		color: #000;
 		// .reverse-back-icon {
 		// 	width: 100%;
 		// 	height: 100%;

+ 27 - 14
components/headModules/style.vue

@@ -1,6 +1,9 @@
 <template>
-	<view class="style-box" @click.stop="setPagesStyle()">
-		<view :class="['style-status' , `${pageStyle}_style` ]"></view>
+	<view :class="['style-box' , `${pageStyle}_style-box` ]" @click.stop="setPagesStyle()">
+		<view :class="['style-status' , `${pageStyle}_style` ]">
+			<text class="iconfont" v-if="pageStyle === 'daytime'">&#xe60f;</text>
+			<text class="iconfont" v-else-if="pageStyle === 'black'">&#xe6b8;</text>
+		</view>
 	</view>
 </template>
 
@@ -8,7 +11,7 @@
 	export default {
 		data() {
 			return {
-				pageStyle: 'daytime' , // daytime : '日渐模式' , black: 夜间模式
+				pageStyle: 'black' , // daytime : '日渐模式' , black: 夜间模式
 			};
 		},
 		methods:{
@@ -20,33 +23,43 @@
 </script>
 
 <style lang="scss" scoped>
+	.daytime_style-box{
+		background-color: #fcfcfc;
+		background-color: #5C5F70;
+	}
+	.black_style-box{
+		background-color: #5C5F70;
+	}
 	.style-box{
-		width: 72rpx;
-		height: 44rpx;
+		width: 68rpx;
+		height: 40rpx;
 		border-radius: 30rpx;
-		background-color: #5C5F70;
 		position: relative;
 		.style-status{
-			width: 39rpx;
-			height: 39rpx;
+			width: 36rpx;
+			height: 36rpx;
 			background-color: #fff;
 			border-radius: 50%;
 			position: absolute;
-			background-size: 39rpx 39rpx;
 			top: 50%;
 			left: 5rpx;
 			transform: translateY(-50%);
 			// transition: left  3s linear;
 			transition:left,background 0.5s;
+			display: flex;
+			justify-content: center;
+			align-items: center;
+			.iconfont{
+				color: $Theme-Color;
+				font-size: 26rpx;
+			}
 		}
-		.black_style{
-			background: url("@/static/logo.png") no-repeat center center;
+		.black_style{ 
 			left: 30rpx;
 			// width:100rpx;
 		}
-		.daytime_style{
-			background: url("@/static/logo.png") no-repeat center center;
-			left: 5rpx;
+		.daytime_style{ 
+			left: 4rpx;
 		}
 		
 	}

+ 2 - 2
components/marketplace/marketplace - 副本.vue

@@ -31,7 +31,7 @@
 			</uni-th>
 		</uni-tr>
 		<!-- 表格数据行 -->
-		<uni-tr v-for="item in 30" :rise-fall="riseFallStatus">
+		<uni-tr v-for="item in 30" :rise-fall="stocksColor">
 			<uni-td>
 				<view class="table-title">
 					<view class="title">
@@ -80,7 +80,7 @@
 		},
 		computed: {
 			...mapGetters([
-				'riseFallStatus'
+				'stocksColor'
 			]),
 		},
 		methods: {

+ 2 - 2
components/marketplace/marketplace.vue

@@ -31,7 +31,7 @@
 			</uni-th>
 		</uni-tr>
 		<!-- 表格数据行 -->
-		<uni-tr v-for="item in 30" :rise-fall="riseFallStatus">
+		<uni-tr v-for="item in 30" :rise-fall="stocksColor">
 			<uni-td>
 				<view class="table-title">
 					<view class="title">
@@ -78,7 +78,7 @@
 		},
 		computed: {
 			...mapGetters([
-				'riseFallStatus'
+				'stocksColor'
 			]),
 		},
 		methods: {

+ 20 - 0
components/setStockColor/setStockColor.vue

@@ -0,0 +1,20 @@
+<template>
+	<view>
+		
+	</view>
+</template>
+
+<script>
+	export default {
+		name:"setStockColor",
+		data() {
+			return {
+				
+			};
+		}
+	}
+</script>
+
+<style lang="scss">
+
+</style>

+ 115 - 0
components/setting-color/setting-color.vue

@@ -0,0 +1,115 @@
+<template>
+	<uni-popup ref="popupRef" type="bottom">
+
+		<view class="popup-box">
+			<view class="popup-title">
+				<text class="title-side"></text>
+				<text class="title-name">涨跌颜色</text>
+				<text class="title-side iconfont">&#xe621;</text>
+			</view>
+
+			<view class="stocks-content">
+				<block v-for="(val,key,index) in stocksColorObj">
+					<view class="stocks-item" @click.stop="setStocksColor(key)">
+						<text class="stocks-text">{{ val }}</text>
+						<text v-if="stocksColor === key" class="active-stocks iconfont">&#xe627;</text>
+					</view>
+				</block>
+			</view>
+		</view>
+	</uni-popup>
+</template>
+<script>
+	import {
+		mapGetters
+	} from 'vuex'
+	export default {
+		name: 'setting-color',
+		data() {
+			return {
+				stocksColorObj: this.$stocksColorObj,
+			};
+		},
+		computed: {
+			...mapGetters([
+				'stocksColor'
+			]),
+		},
+	 
+		mounted() {
+ 
+		},
+		methods: {
+			open() {
+				this.$nextTick(() => {
+					this.$refs.popupRef.open();
+				})
+			},
+			setStocksColor(key){
+				this.$store.commit('app/SET_STOCKS_COLOR', key)
+				this.$refs.popupRef.close();
+				uni.reLaunch({
+					url: '/pages/index/index'
+				});
+			}
+
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	.popup-box {
+		width: 100%;
+		background-color: #Fff;
+		border-radius: 50rpx 50rpx 0px 0px;
+	
+		.popup-title {
+			width: 100%;
+			height: 106rpx;
+			border-radius: 50rpx 50rpx 0px 0px;
+			background-color: #F7F7F7 !important;
+			display: flex;
+			justify-content: space-between;
+			align-items: center;
+			padding: 0 40rpx;
+			font-weight: 700;
+	
+			.title-side {
+				flex-shrink: 0;
+				font-size: 28rpx;
+				width: 40rpx;
+				height: 100%;
+				line-height: 106rpx;
+				color: #666;
+				font-weight: 400;
+			}
+		}
+	
+		// <view class="stocks-content">
+		// 	<block v-for="(val,key,index) in stocksColorObj">
+		// 		<view class="stocks-item">
+		// 			<text class="stocks-text">{{ val }}</text>
+		// 			<text v-if="stocksColor === key" class="active-stocks iconfont">&#xe627;</text>
+		// 		</view>
+		// 	</block>
+		// </view>
+		.stocks-content{
+			width: 100%;
+			background-color: #Fff;
+			.stocks-item{
+				width: 100%;
+				height: 90rpx;
+				display: flex;
+				justify-content: space-between;
+				align-items: center;
+				padding: 0 $pages-padding 0 60rpx;
+				border-bottom: 1rpx solid $border-color;
+				font-size: 28rpx;
+			}
+			.active-stocks{
+				color: $Theme-Color;
+			}
+		}
+	
+	}
+</style>

+ 86 - 6
components/sharePage/sharePage.vue

@@ -5,7 +5,7 @@
 			<view class="share-status-bar" :style="{'height': `${statusBarHeight}px`}"></view>
 			<!-- statusBarHeight -->
 			<view class="share-content">
-				<view class="content">
+				<view class="content" id="share-content">
 					<view class="share-top">
 						<image class="share-logo" src="@/static/share/img_02.png" mode="aspectFit"></image>
 						<text class="share-title">注册会员</text>
@@ -54,7 +54,7 @@
 							<text class="share-icon iconfont" style="color: #1890ff;">&#xe887;</text>
 							<text class="share-text">QQ</text>
 						</view>
-						<view class="share-icons">
+						<view class="share-icons" @click="my_js.onclicks">
 							<text class="share-icon iconfont" style="color: #83a0e5">&#xe6b4;</text>
 							<text class="share-text">保存图片</text>
 						</view>
@@ -73,6 +73,12 @@
 	} from 'vuex'
 	export default {
 		name: "sharePage",
+		props: {
+			tabBar: {
+				type: Boolean,
+				default: true
+			}
+		},
 		data() {
 			return {
 
@@ -85,23 +91,96 @@
 		},
 		mounted() {
 
-
+			// this.$refs.popupRef.open()
 		},
 		methods: {
 			openShare() {
 				this.$nextTick(() => {
-					uni.hideTabBar();
+					this.showTabBar(false)
 					this.$refs.popupRef.open()
 				})
 			},
 			cancelShare() {
 				this.$refs.popupRef.close()
-				uni.showTabBar()
-			}
+				this.showTabBar()
+			},
+			showTabBar(type = true) {
+				if (this.tabBar) {
+					try {
+						if (type) {
+							uni.showTabBar();
+						} else {
+							uni.hideTabBar();
+						}
+					} catch {}
+				}
+			},
+
+
+
+			saveBase64(imageStr) {
+				uni.showLoading({
+					title: "保存中"
+				})
+				try{
+					let bitmap = new plus.nativeObj.Bitmap();
+					bitmap.loadBase64Data(imageStr, function() {
+						console.log('加载base64图片数据成功');
+						//图片名称命名
+						bitmap.save('_doc/' + new Date().getTime() + '.png', {
+							quality: 100
+						}, function(i) {
+							// 将图片保存到相册
+							uni.saveImageToPhotosAlbum({
+								filePath: i.target,
+								success: function() {
+									bitmap.clear(); //销毁Bitmap图片
+									// uni.$u.toast('保存图片成功')
+					
+									uni.showToast({
+										title: '保存图片成功',
+										duration: 2000
+									});
+									// that.noPhoto = true;
+								}
+							});
+						}, function(e) {
+							console.log('保存图片失败:' + JSON.stringify(e));
+						});
+					}, function(e) {
+						console.log('截屏绘制图片失败:' + JSON.stringify(e));
+					});
+				}catch{
+					uni.hideLoading()
+				}
+			},
+
+
 		}
 	}
 </script>
 
+<script module="my_js" lang="renderjs">
+	import html2canvas from 'html2canvas';
+	export default {
+		data() {
+			return {}
+		},
+		methods: {
+			onclicks(event, ownerInstance) {
+				html2canvas(document.getElementById('share-content'), {
+					backgroundColor: '#fff',
+					useCORS: true,
+					taintTest: true,
+					timeout: 2000
+				}).then(canvas => {
+					let imgurl = canvas.toDataURL('image/jpg');
+					ownerInstance.callMethod('saveBase64', imgurl)
+				})
+			}
+		}
+	}
+</script>
 <style lang="scss" scoped>
 	.share-box {
 		width: 750rpx;
@@ -137,6 +216,7 @@
 
 					.share-logo {
 						display: inline-block;
+						width: 322rpx;
 						height: 80rpx;
 						// margin-bottom: 14rpx;
 					}

+ 49 - 33
main.js

@@ -1,11 +1,25 @@
 import App from './App'
 import store from './store'
 
+
 // main.js,注意要在use方法之后执行
 import uView from 'uview-ui'
 Vue.use(uView)
 // uni.$u.config.unit = 'rpx'
 
+
+
+
+
+import initialize from "@/utils/initialize.js"
+Vue.use(initialize);
+
+// 全局加载组件
+import reverseBack from "@/components/headModules/reverse-back.vue"
+
+Vue.component('reverseBack', reverseBack)
+
+
 // 如此配置即可
 // #ifndef VUE3
 import Vue from 'vue'
@@ -13,46 +27,48 @@ Vue.config.productionTip = false
 App.mpType = 'app'
 
 try {
-  function isPromise(obj) {
-    return (
-      !!obj &&
-      (typeof obj === "object" || typeof obj === "function") &&
-      typeof obj.then === "function"
-    );
-  }
-
-  // 统一 vue2 API Promise 化返回格式与 vue3 保持一致
-  uni.addInterceptor({
-    returnValue(res) {
-      if (!isPromise(res)) {
-        return res;
-      }
-      return new Promise((resolve, reject) => {
-        res.then((res) => {
-          if (res[0]) {
-            reject(res[0]);
-          } else {
-            resolve(res[1]);
-          }
-        });
-      });
-    },
-  });
-} catch (error) { }
+	function isPromise(obj) {
+		return (
+			!!obj &&
+			(typeof obj === "object" || typeof obj === "function") &&
+			typeof obj.then === "function"
+		);
+	}
+
+	// 统一 vue2 API Promise 化返回格式与 vue3 保持一致
+	uni.addInterceptor({
+		returnValue(res) {
+			if (!isPromise(res)) {
+				return res;
+			}
+			return new Promise((resolve, reject) => {
+				res.then((res) => {
+					if (res[0]) {
+						reject(res[0]);
+					} else {
+						resolve(res[1]);
+					}
+				});
+			});
+		},
+	});
+} catch (error) {}
 
 const app = new Vue({
-  ...App,
-  store
+	...App,
+	store
 })
 app.$mount()
 // #endif
 
 // #ifdef VUE3
-import { createSSRApp } from 'vue'
+import {
+	createSSRApp
+} from 'vue'
 export function createApp() {
-  const app = createSSRApp(App)
-  return {
-    app
-  }
+	const app = createSSRApp(App)
+	return {
+		app
+	}
 }
 // #endif

+ 58 - 4
package-lock.json

@@ -1,11 +1,65 @@
 {
+  "name": "BiKing",
+  "lockfileVersion": 3,
   "requires": true,
-  "lockfileVersion": 1,
-  "dependencies": {
-    "uview-ui": {
+  "packages": {
+    "": {
+      "dependencies": {
+        "html2canvas": "^1.4.1",
+        "uview-ui": "^2.0.36"
+      }
+    },
+    "node_modules/base64-arraybuffer": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmmirror.com/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz",
+      "integrity": "sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==",
+      "engines": {
+        "node": ">= 0.6.0"
+      }
+    },
+    "node_modules/css-line-break": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmmirror.com/css-line-break/-/css-line-break-2.1.0.tgz",
+      "integrity": "sha512-FHcKFCZcAha3LwfVBhCQbW2nCNbkZXn7KVUJcsT5/P8YmfsVja0FMPJr0B903j/E69HUphKiV9iQArX8SDYA4w==",
+      "dependencies": {
+        "utrie": "^1.0.2"
+      }
+    },
+    "node_modules/html2canvas": {
+      "version": "1.4.1",
+      "resolved": "https://registry.npmmirror.com/html2canvas/-/html2canvas-1.4.1.tgz",
+      "integrity": "sha512-fPU6BHNpsyIhr8yyMpTLLxAbkaK8ArIBcmZIRiBLiDhjeqvXolaEmDGmELFuX9I4xDcaKKcJl+TKZLqruBbmWA==",
+      "dependencies": {
+        "css-line-break": "^2.1.0",
+        "text-segmentation": "^1.0.3"
+      },
+      "engines": {
+        "node": ">=8.0.0"
+      }
+    },
+    "node_modules/text-segmentation": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmmirror.com/text-segmentation/-/text-segmentation-1.0.3.tgz",
+      "integrity": "sha512-iOiPUo/BGnZ6+54OsWxZidGCsdU8YbE4PSpdPinp7DeMtUJNJBoJ/ouUSTJjHkh1KntHaltHl/gDs2FC4i5+Nw==",
+      "dependencies": {
+        "utrie": "^1.0.2"
+      }
+    },
+    "node_modules/utrie": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmmirror.com/utrie/-/utrie-1.0.2.tgz",
+      "integrity": "sha512-1MLa5ouZiOmQzUbjbu9VmjLzn1QLXBhwpUa7kdLUQK+KQ5KA9I1vk5U4YHe/X2Ch7PYnJfWuWT+VbuxbGwljhw==",
+      "dependencies": {
+        "base64-arraybuffer": "^1.0.2"
+      }
+    },
+    "node_modules/uview-ui": {
       "version": "2.0.36",
       "resolved": "https://registry.npmmirror.com/uview-ui/-/uview-ui-2.0.36.tgz",
-      "integrity": "sha512-ASSZT6M8w3GTO1eFPbsgEFV0U5UujK+8pTNr+MSUbRNcRMC1u63DDTLJVeArV91kWM0bfAexK3SK9pnTqF9TtA=="
+      "integrity": "sha512-ASSZT6M8w3GTO1eFPbsgEFV0U5UujK+8pTNr+MSUbRNcRMC1u63DDTLJVeArV91kWM0bfAexK3SK9pnTqF9TtA==",
+      "engines": {
+        "HBuilderX": "^3.1.0"
+      }
     }
   }
 }

+ 6 - 0
package.json

@@ -0,0 +1,6 @@
+{
+  "dependencies": {
+    "html2canvas": "^1.4.1",
+    "uview-ui": "^2.0.36"
+  }
+}

+ 18 - 0
pages.json

@@ -90,6 +90,24 @@
                     "style" : {
                         "navigationBarTitleText" : "充币记录"
                     }
+                },
+                {
+                    "path" : "setting",
+                    "style" : {
+                        "navigationBarTitleText" : "系统设置"
+                    }
+                },
+                {
+                    "path" : "safety-set",
+                    "style" : {
+                        "navigationBarTitleText" : "安全设置"
+                    }
+                },
+                {
+                    "path" : "change-password",
+                    "style" : {
+                        "navigationBarTitleText" : "修改密码"
+                    }
                 }
             ]
         }

+ 281 - 0
pages/content/change-password.vue

@@ -0,0 +1,281 @@
+<template>
+	<view>
+		<headContent>
+			<template #left>
+				<reverse-back />
+			</template>
+			<template #content>
+				<view class="haed-title">
+					修改登录密码
+				</view>
+			</template>
+		</headContent>
+
+		<view class="change-hint">
+			<text class="iconfont">&#xe8ec;</text>
+			<text>修改登录密码需24小时后才能操作体现</text>
+		</view>
+
+		<view class="form-box">
+			<form class="form-content">
+				<view class="form-item ">
+					<view class="form-item-lable">原密码</view>
+					<input class="form-item-input" v-model="formData.password" :maxlength="maxlength"
+						placeholder-class="form-item-place" :type="showPwd ? 'text' : 'password'" placeholder="请输入原密码">
+					<!-- <input class="form-item-input" v-model="formData.password" :maxlength="maxlength"
+						placeholder-class="form-item-place" :type="showConfirmPsd ? 'text' : 'password'" placeholder="请输入原密码"> -->
+					<view class="form-item-icon" @click.stop="showPwd = !showPwd">
+						<text v-show="showPwd" class="iconfont">&#xe663;</text>
+						<text v-show="!showPwd" class="iconfont">&#xe664;</text>
+					</view>
+				</view>
+				<view class="err-hint">{{ formError.psdErr }}</view>
+				<view class="form-item ">
+					<view class="form-item-lable">新密码</view>
+					<input class="form-item-input" v-model="formData.newPassword" :maxlength="maxlength"
+						placeholder-class="form-item-place" :type="showNewPsd ? 'text' : 'password'" placeholder="请输入新密码">
+					<view class="form-item-icon" @click.stop="showNewPsd = !showNewPsd">
+						<text v-show="showNewPsd" class="iconfont">&#xe663;</text>
+						<text v-show="!showNewPsd" class="iconfont">&#xe664;</text>
+					</view>
+				</view>
+				<view class="err-hint">{{ formError.newPsdErr }}</view>
+				<view class="form-item ">
+					<view class="form-item-lable">确认密码</view>
+					<input class="form-item-input" v-model="formData.confirmPassword" :maxlength="maxlength"
+						placeholder-class="form-item-place" :type="showConfirmPsd ? 'text' : 'password'" placeholder="请再次输入新密码">
+					<view class="form-item-icon" @click.stop="showConfirmPsd = !showConfirmPsd">
+						<text v-show="showConfirmPsd" class="iconfont">&#xe663;</text>
+						<text v-show="!showConfirmPsd" class="iconfont">&#xe664;</text>
+					</view>
+				</view>
+				<view class="err-hint">{{ formError.confirmPsdErr }}</view>
+			</form>
+
+			<view :class="['form-btn' , deblockingSubmitBtn() ? 'active-form-btn' : '' ]"
+				@click.stop="SubmitPassWord()">
+				确定
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	import {
+		validPassword
+	} from "@/utils/validate.js"
+	export default {
+		name: 'change-password',
+		data() {
+			return {
+				maxlength: 20,
+				showPwd: false,
+				showNewPsd:false,
+				showConfirmPsd:false,
+				formData: {
+					password: '',
+					newPassword: '',
+					confirmPassword: ''
+				},
+				formError: {
+					psdErr: '',
+					newPsdErr: '',
+					confirmPsdErr: ''
+				}
+			};
+		},
+		watch: {
+			'formData.password'(newPsd, oldPsd) {
+				this.validateField('password')
+			},
+			'formData.newPassword'(newPsd, oldPsd) {
+				this.validateField('newPassword')
+			},
+			'formData.confirmPassword'(newPsd, oldPsd) {
+				this.validateField('confirmPassword')
+			}
+		},
+		methods: {
+			validateField(key) {
+				let validateStatus = false
+				switch (key) {
+					case 'password':
+						if (this.formData[key].trim()) {
+							this.formError.psdErr = '';
+							validateStatus = true;
+						} else {
+							this.formError.psdErr = '请输入原密码';
+							validateStatus = false;
+						};
+						break;
+					case 'newPassword':
+						if (!this.formData[key].trim()) {
+							this.formError.newPsdErr = '请输入新密码'
+							validateStatus = false;
+						} else if (!validPassword(this.formData[key])) {
+							this.formError.newPsdErr = '密码长度为8-20位字符,必须同时包含大写字母、小写字母和数字';
+							validateStatus = false;
+						} else {
+							this.formError.newPsdErr = '';
+							validateStatus = true;
+						};
+						break;
+					case 'confirmPassword':
+						if (!this.formData[key].trim()) {
+							this.formError.confirmPsdErr = '请再次输入新密码';
+							validateStatus = false;
+						} else if (this.formData[key] !== this.formData.newPassword) {
+							this.formError.confirmPsdErr = '确认密码和新密码输入不一致';
+							validateStatus = false;
+						} else {
+							this.formError.confirmPsdErr = '';
+							validateStatus = true;
+						}
+						break;
+					default:
+						validateStatus = false
+
+				};
+				return validateStatus;
+			},
+			confirmValidateField() {
+				return new Promise((resolve, reject) => {
+					let validateStatus = true;
+					for (let key in this.formData) {
+						console.log('SubmitPassWord', key)
+						if (validateStatus) {
+							validateStatus = this.validateField(key)
+						} else {
+							this.validateField(key)
+						}
+					}
+
+
+					if (validateStatus) {
+						resolve()
+					} else {
+						reject()
+					};
+				})
+
+			},
+
+			deblockingSubmitBtn() {
+				for (let key in this.formData) {
+					if (this.formData[key] === '') {
+						return false
+						break;
+					}
+				};
+				return true
+			},
+			SubmitPassWord() {
+
+				this.confirmValidateField().then(res => {
+					uni.showLoading({
+						title: '修改中',
+						mask: true
+					})
+
+
+					setTimeout(() => {
+						uni.hideLoading()
+					}, 500)
+				})
+
+
+			}
+
+
+
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	.change-hint {
+		font-size: 26rpx;
+		padding: 0 $pages-padding;
+		display: flex;
+		align-items: center;
+		color: $Theme-Color;
+		border-top: 1rpx solid $border-color;
+		height: 80rpx;
+
+		.iconfont {
+			margin-right: 20rpx;
+		}
+	}
+
+	.form-box {
+		width: 100%;
+		padding: 0 $pages-padding;
+
+		.form-content {
+			width: 100%;
+
+			.form-item {
+				width: 100%;
+				height: 80rpx;
+				display: flex;
+				align-items: center;
+				font-size: 28rpx;
+				border-bottom: 1rpx solid $border-color;
+
+				.form-item-lable {
+					width: 180rpx;
+				}
+
+				.form-item-input {
+					font-size: 28rpx;
+					flex: 1;
+					height: 100%;
+					border: none;
+				}
+
+				.form-item-place {
+					font-size: 28rpx;
+					color: #ccc;
+				}
+
+				.form-item-icon {
+					width: 50rpx;
+					height: 100%;
+					display: flex;
+					justify-content: flex-end;
+					align-items: center;
+
+					.iconfont {
+						font-size: 26rpx;
+					}
+				}
+			}
+
+			.err-hint {
+				width: 100%;
+				min-height: 50rpx;
+				font-size: 26rpx;
+				color: red;
+				line-height: 1.2;
+				padding-top: 10rpx;
+			}
+		}
+
+		.form-btn {
+			width: 100%;
+			background-color: #ccc;
+			height: 80rpx;
+			margin-top: 60rpx;
+			border-radius: 10rpx;
+			text-align: center;
+			line-height: 80rpx;
+			color: #fff;
+			letter-spacing: 1px;
+			font-size: 28rpx;
+		}
+
+		.active-form-btn {
+			background-color: $Theme-Color ;
+		}
+	}
+</style>

+ 55 - 29
pages/content/mine.vue

@@ -22,16 +22,17 @@
 			</view>
 		</view>
 
-		<gap height="8rpx" />
+		<gap />
 		<!-- 个人信息 -->
 		<view class="mine-muen">
-			<view class="mine-muen-item">
+			<view class="mine-muen-item" @click.stop="openSafetySet()">
 				<view class="muen-content">
 					<image class="muen-icon" src="@/static/logo.png" mode="aspectFit" />
 					<text class="muen-text">安全设置</text>
 				</view>
 				<view class="muen-more">
-					<image class="muen-more-icon" src="../../static/logo.png" mode="aspectFit" />
+					<text class="more-icon iconfont">&#xe88e;</text>
+					<!-- <image class="muen-more-icon" src="../../static/logo.png" mode="aspectFit" /> -->
 				</view>
 			</view>
 			<view class="mine-muen-item">
@@ -41,7 +42,7 @@
 				</view>
 				<view class="muen-more">
 					<text class="muen-more-text">去认证</text>
-					<image class="muen-more-icon" src="../../static/logo.png" mode="aspectFit" />
+					<text class="more-icon iconfont">&#xe88e;</text>
 				</view>
 			</view>
 			<view class="mine-muen-item">
@@ -50,7 +51,7 @@
 					<text class="muen-text">提现地址</text>
 				</view>
 				<view class="muen-more">
-					<image class="muen-more-icon" src="../../static/logo.png" mode="aspectFit" />
+					<text class="more-icon iconfont">&#xe88e;</text>
 				</view>
 			</view>
 			<view class="mine-muen-item">
@@ -59,7 +60,7 @@
 					<text class="muen-text">我的红包</text>
 				</view>
 				<view class="muen-more">
-					<image class="muen-more-icon" src="../../static/logo.png" mode="aspectFit" />
+					<text class="more-icon iconfont">&#xe88e;</text>
 				</view>
 			</view>
 			<view class="mine-muen-item">
@@ -68,16 +69,16 @@
 					<text class="muen-text">活动中心</text>
 				</view>
 				<view class="muen-more">
-					<image class="muen-more-icon" src="../../static/logo.png" mode="aspectFit" />
+					<text class="more-icon iconfont">&#xe88e;</text>
 				</view>
 			</view>
-			<view class="mine-muen-item">
+			<view class="mine-muen-item" @click.stop="openShare()">
 				<view class="muen-content">
 					<image class="muen-icon" src="@/static/logo.png" mode="aspectFit" />
 					<text class="muen-text">邀请链接</text>
 				</view>
 				<view class="muen-more">
-					<image class="muen-more-icon" src="../../static/logo.png" mode="aspectFit" />
+					<text class="more-icon iconfont">&#xe88e;</text>
 				</view>
 			</view>
 			<view class="mine-muen-item">
@@ -86,24 +87,24 @@
 					<text class="muen-text">合约战绩</text>
 				</view>
 				<view class="muen-more">
-					<image class="muen-more-icon" src="../../static/logo.png" mode="aspectFit" />
+					<text class="more-icon iconfont">&#xe88e;</text>
 				</view>
 			</view>
 		</view>
 
-		<gap height="8rpx" />
+		<gap />
 		<view class="mine-muen">
-			<view class="mine-muen-item">
+			<view class="mine-muen-item" @click.stop="openSetting()">
 				<view class="muen-content">
 					<image class="muen-icon" src="../../static/logo.png" mode="aspectFit" />
 					<text class="muen-text">系统设置</text>
 				</view>
 				<view class="muen-more">
-					<image class="muen-more-icon" src="../../static/logo.png" mode="aspectFit" />
+					<text class="more-icon iconfont">&#xe88e;</text>
 				</view>
 			</view>
 		</view>
-		<gap height="8rpx" />
+		<gap />
 		<view class="mine-muen">
 			<view class="mine-muen-item">
 				<view class="muen-content">
@@ -112,11 +113,11 @@
 				</view>
 				<view class="muen-more">
 					<text class="muen-more-text">当前版本 V2.4.6 62</text>
-					<image class="muen-more-icon" src="../../static/logo.png" mode="aspectFit" />
+					<text class="more-icon iconfont">&#xe88e;</text>
 				</view>
 			</view>
 		</view>
-		<gap height="8rpx" />
+		<gap />
 		<view class="mine-muen">
 			<view class="mine-muen-item">
 				<view class="muen-content">
@@ -124,7 +125,7 @@
 					<text class="muen-text">消息中心</text>
 				</view>
 				<view class="muen-more">
-					<image class="muen-more-icon" src="../../static/logo.png" mode="aspectFit" />
+					<text class="more-icon iconfont">&#xe88e;</text>
 				</view>
 			</view>
 			<view class="mine-muen-item">
@@ -133,7 +134,7 @@
 					<text class="muen-text">在线客服</text>
 				</view>
 				<view class="muen-more">
-					<image class="muen-more-icon" src="../../static/logo.png" mode="aspectFit" />
+					<text class="more-icon iconfont">&#xe88e;</text>
 				</view>
 			</view>
 			<view class="mine-muen-item">
@@ -142,15 +143,21 @@
 					<text class="muen-text">关于我们</text>
 				</view>
 				<view class="muen-more">
-					<image class="muen-more-icon" src="../../static/logo.png" mode="aspectFit" />
+					<text class="more-icon iconfont">&#xe88e;</text>
 				</view>
 			</view>
+			<view class="mine-btn">
+				安全登录
+			</view>
 		</view>
 
 
-		<view class="mine-btn">
-			退出登录
-		</view>
+	
+		
+		<!-- 邀请 -->
+		<sharePage ref="sharePageRef" :tabBar="false"/>
+		<!--  -->
+		
 	</view>
 </template>
 
@@ -187,6 +194,26 @@
 					name: '合约战绩'
 				}]
 			};
+		},
+		methods:{
+			// 打开邀请
+			openShare(){
+				this.$nextTick(() => {
+					this.$refs.sharePageRef.openShare()
+				})
+			},
+			// 系统设置
+			openSetting(){
+				uni.navigateTo({
+					url:'/pages/content/setting'
+				})
+			},
+			// 安全设置
+			openSafetySet(){
+				uni.navigateTo({
+					url:'/pages/content/safety-set'
+				})
+			}
 		}
 	}
 </script>
@@ -279,27 +306,26 @@
 
 			.muen-more-icon {
 
-				width: 11rpx;
-				height: 21rpx;
+				font-size: 26rpx;
+				color: #ccc;
 			}
 		}
 	}
 	
 	.mine-btn{
 		width: 690rpx;
-		margin: 36rpx auto;
-		 
-		height: 75rpx;
+		height: 90rpx;
+		margin: 80rpx auto;
 		background: #05c175;
 		border-radius: 8rpx;
 		
  
-		font-size: 32rpx;
+		font-size: 30rpx;
 		font-family: PingFang SC, PingFang SC-Regular;
 		font-weight: 400;
 		text-align: center;
 		color: #ffffff;
-		line-height:75rpx;
+		line-height:90rpx;
 		letter-spacing: 0.64rpx;
 	}
 </style>

+ 145 - 0
pages/content/safety-set.vue

@@ -0,0 +1,145 @@
+<template>
+	<view>
+		<headContent>
+			<template #left>
+				<reverse-back />
+			</template>
+			<template #content>
+				<view class="haed-title">
+					安全设置
+				</view>
+			</template>
+		</headContent>
+		<view class="safety-set">
+			<view class="safety-set-item" @click.stop="changePassword()">
+				<text class="safety-set-lable">登录密码</text>
+				<view class="safety-set-more">
+					<text class="more-lable">修改</text>
+					<text class="more-icon iconfont">&#xe88e;</text>
+				</view>
+			</view>
+			<view class="safety-set-item">
+				<text class="safety-set-lable">谷歌验证</text>
+				<view class="safety-set-more">
+					<text class="more-lable">绑定</text>
+					<text class="more-icon iconfont">&#xe88e;</text>
+				</view>
+			</view>
+			<view class="safety-set-item">
+				<text class="safety-set-lable">邮箱</text>
+				<view class="safety-set-more">
+					<text class="more-lable active-more-lable">已绑定</text>
+					<text v-if="true" class="more-icon iconfont">&#xe88e;</text>
+					<text v-else class="more-icon iconfont"></text>
+				</view>
+			</view>
+			<view class="safety-set-item">
+				<text class="safety-set-lable">手机</text>
+				<view class="safety-set-more">
+					<text class="more-lable">绑定</text>
+					<text class="more-icon iconfont">&#xe88e;</text>
+				</view>
+			</view>
+		</view>
+		<view class="safety-title">
+			交易设置
+		</view>
+		<view class="safety-set item-border">
+			<view class="safety-set-item">
+				<text class="safety-set-lable">法币收款设置</text>
+				<view class="safety-set-more">
+					<text class="more-icon iconfont">&#xe88e;</text>
+				</view>
+			</view>
+			<view class="safety-set-item ">
+				<text class="safety-set-lable">资金密码{法币、转账}</text>
+				<view class="safety-set-more">
+					<text class="more-lable">去设置</text>
+					<text class="more-icon iconfont">&#xe88e;</text>
+				</view>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		name: 'safety-set',
+		data() {
+			return {
+
+			};
+		},
+		methods:{
+			changePassword(){
+				uni.navigateTo({
+					url:'/pages/content/change-password'
+				})
+			}
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	.safety-set {
+		width: 100%;
+
+		.safety-set-item {
+			width: 100%;
+			height: 80rpx;
+			display: flex;
+			align-items: center;
+			justify-content: space-between;
+			padding: 0 $pages-padding;
+			font-size: 28rpx;
+
+			.safety-set-lable {
+				// font-weight: 700;
+				flex-shrink: 0;
+			}
+
+			border-top: 1rpx solid $border-color;
+			.safety-set-more{
+				flex-shrink: 0;
+				display: flex;
+				align-items: center;
+				.more-lable{
+					color:$Theme-Color;
+				}
+				.active-more-lable{
+					color: #ccc;
+				}
+				.more-icon{
+					width: 32rpx;
+					height: 32rpx;
+					color: #ccc;
+					font-size: 32rpx;
+				}
+			}
+			// <view class="safety-set-item">
+			// 	<text class="safety-set-lable">邮箱</text>
+			// 	<view class="safety-set-more">
+			// 		<text class="more-lable active-more-lable">已绑定</text>
+			// 		<text class="more-icon iconfont">&#xe88e;</text>
+			// 	</view>
+			// </view>
+		}
+	}
+
+	.safety-title {
+		width: 100%;
+		height: 80rpx;
+		line-height: 80rpx;
+		font-size: 28rpx;
+		color: $Theme-Color;
+		padding: 0 $pages-padding;
+		background-color: $page-bg;
+	}
+
+	.item-border {
+		.safety-set-item {
+			border-top: none;
+			border-bottom: 1rpx solid $border-color;
+		}
+	}
+</style>

+ 114 - 0
pages/content/setting.vue

@@ -0,0 +1,114 @@
+<template>
+	<view>
+		<!-- 头部 -->
+		<headContent>
+			<template #left>
+				<reverse-back />
+			</template>
+			<template #content>
+				<view class="haed-title">
+					系统设置
+				</view>
+			</template>
+		</headContent>
+
+		<gap />
+		<view class="set-list">
+			<view class="set-item">
+				<text>语言切换</text>
+				<view class="set-moer">
+					<text class="set-moer-text">简体中文</text>
+					<text class="set-moer-icon iconfont">&#xe88e;</text>
+				</view>
+			</view>
+			<view class="set-item">
+				<text>网络检查</text>
+				<view class="set-moer">
+					<text class="set-moer-icon iconfont">&#xe88e;</text>
+				</view>
+			</view>
+			<view class="set-item" @click.stop="selectStocksColor()">
+				<text>涨跌颜色</text>
+				<view class="set-moer">
+					<text class="set-moer-text set-color">{{ stocksColorObj[stocksColor] }}</text>
+					<text class="set-moer-icon iconfont">&#xe88e;</text>
+				</view>
+			</view>
+		</view>
+
+		<setting-color ref="settingColorRef"/>
+	</view>
+</template>
+
+<script>
+	import {
+		mapGetters
+	} from 'vuex'
+	import reverseBack from "@/components/headModules/reverse-back.vue"
+	export default {
+		name: 'setting',
+		components: {
+			reverseBack
+		},
+		computed: {
+			...mapGetters([
+				'stocksColor'
+			]),
+		},
+
+		data() {
+			return {
+				stocksColorObj: this.$stocksColorObj,
+			};
+		},
+		methods:{
+			// 修改股票颜色
+			selectStocksColor(){
+				this.$nextTick(() => {
+					this.$refs.settingColorRef.open();
+				})
+			}
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	.set-list {
+		width: 100%;
+		padding: 0 $pages-padding;
+
+		.set-item {
+			display: flex;
+			justify-content: space-between;
+			align-items: center;
+			height: 90rpx;
+			width: 100%;
+			border-bottom: 1rpx solid $border-color;
+			font-size: 24rpx;
+			color: #0f0f0f;
+
+			text {
+				flex-shrink: 0;
+			}
+
+			.set-moer {
+				flex-shrink: 0;
+				display: flex;
+				align-items: center;
+
+				.set-moer-text {
+					font-size: 26rpx;
+				}
+
+				.set-moer-icon {
+					color: #ccc;
+					font-size: 28rpx;
+				}
+
+				.set-color {
+					color: $Theme-Color;
+				}
+			}
+		}
+	}
+</style>

+ 12 - 8
pages/content/share.vue

@@ -98,22 +98,25 @@
 				}
 
 			}
-			
-			.share-footer{
+
+			.share-footer {
 				width: 100%;
 				display: flex;
 				align-items: center;
-				.share-code{
+
+				.share-code {
 					width: 178rpx;
 					height: 178rpx;
 				}
-				.share-btns{
+
+				.share-btns {
 					width: calc(100% - 178rpx);
 					padding-left: 45rpx;
-					.share-btn{
+
+					.share-btn {
 						width: 100%;
 						height: 58rpx;
-						background: linear-gradient(180deg,#faae3d, #f9d159);
+						background: linear-gradient(180deg, #faae3d, #f9d159);
 						border-radius: 29rpx;
 						text-align: center;
 						line-height: 58rpx;
@@ -123,7 +126,8 @@
 						color: #1a1a1a;
 						letter-spacing: 0.56rpx;
 					}
-					.share-btn-hint{
+
+					.share-btn-hint {
 						padding-top: 22rpx;
 						font-size: 28rpx;
 						font-family: PingFang SC, PingFang SC-Regular;
@@ -135,7 +139,7 @@
 					}
 				}
 			}
-			
+
 			// <view class="share-footer">
 			// 	<image class="share-code" src="../../static/share/img_03.png" mode=""></image>
 			// 	<view class="share-btns">

+ 2 - 2
pages/index/index.vue

@@ -1,5 +1,5 @@
 <template>
-	<view class="content"  :rise-fall="riseFallStatus">
+	<view class="content"  :rise-fall="stocksColor">
 		<!-- 头部 -->
 		<headContent>
 			<template #left>
@@ -72,7 +72,7 @@
 		},
 		computed: {
 			...mapGetters([
-				'riseFallStatus'
+				'stocksColor'
 			]),
 		},
 		onLoad() {

+ 2 - 2
pages/index/modules/usdt.vue

@@ -1,5 +1,5 @@
 <template>
-	<view class="usdt-box" :rise-fall="riseFallStatus">
+	<view class="usdt-box" :rise-fall="stocksColor">
 		<view  :class="['usdt-item' , index === 1 ? 'rise' : 'fall']"
 			v-for="(item , index ) in list" :key="`usdt_${index}`">
 			<text class="item-title">BTC/USDT</text>
@@ -29,7 +29,7 @@
 
 		computed: {
 			...mapGetters([
-				'riseFallStatus'
+				'stocksColor'
 			]),
 		}
 	}

+ 3 - 3
static/fontsize/iconfont.css

@@ -1,9 +1,9 @@
 
 @font-face {
   font-family: 'iconfont';  /* Project id 4023758 */
-  src: url('https://at.alicdn.com/t/c/font_4023758_ir57trmugjf.woff2?t=1681983300972') format('woff2'),
-       url('https://at.alicdn.com/t/c/font_4023758_ir57trmugjf.woff?t=1681983300972') format('woff'),
-       url('https://at.alicdn.com/t/c/font_4023758_ir57trmugjf.ttf?t=1681983300972') format('truetype');
+  src: url('https://at.alicdn.com/t/c/font_4023758_5m3dyscqq3l.woff2?t=1682058406783') format('woff2'),
+       url('https://at.alicdn.com/t/c/font_4023758_5m3dyscqq3l.woff?t=1682058406783') format('woff'),
+       url('https://at.alicdn.com/t/c/font_4023758_5m3dyscqq3l.ttf?t=1682058406783') format('truetype');
 }
 .iconfont {
 	font-family: "iconfont" !important;

+ 5 - 5
store/getters.js

@@ -1,7 +1,7 @@
 const getters = {
-	riseFallStatus: state => state.app.riseFallStatus,
-  headHeight: state => state.app.headHeight,
-  statusBarHeight: state => state.app.statusBarHeight,
-   
+	stocksColor: state => state.app.stocksColor,
+	headHeight: state => state.app.headHeight,
+	statusBarHeight: state => state.app.statusBarHeight,
+
 }
-export default getters
+export default getters

+ 5 - 2
store/modules/app.config.js

@@ -3,14 +3,17 @@
  	statusBarHeight: 0,
 	
 	// 涨跌颜色
-	riseFallStatus: 'green_rise' , // green_rise:绿涨红跌 , red_rise:绿跌红涨 
+	stocksColor: 'green_rise' , // green_rise:绿涨红跌 , red_rise:绿跌红涨 
 	
  }
 
  const mutations = {
  	SET_statusBarHeight: (state, Height) => {
  		state.statusBarHeight = Height
- 	}
+ 	},
+	SET_STOCKS_COLOR: (state, code) => {
+ 		state.stocksColor = code
+ 	},
 
  }
 

+ 29 - 0
utils/config.js

@@ -0,0 +1,29 @@
+ const config = {
+	stocksColorObj:{
+		'green_rise':'绿涨红跌',
+		'red_rise':'红涨绿跌',
+	}
+	// stocksColorList: [
+	// 	{
+	// 		name: '绿涨红跌',
+	// 		code: 'green_rise'
+	// 	},
+	// 	{
+	// 		name: '红涨绿跌',
+	// 		code: 'red_rise'
+	// 	}
+	// ]
+
+
+
+
+
+
+
+
+
+
+
+}
+
+export default config

+ 17 - 0
utils/initialize.js

@@ -0,0 +1,17 @@
+
+import config from "./config.js"
+
+// import share from "@/components/headModules/share.vue"
+// import reverseBack from "@/components/headModules/reverse-back.vue"
+
+export default {
+	install(Vue) {
+		// 挂载全局对象
+		Vue.prototype.$config = config; // 全局配置
+		Vue.prototype.$stocksColorObj = config.stocksColorObj; // 股票颜色
+
+		// Vue.component('share', share)
+		// Vue.component('reverseBack', reverseBack)
+
+	}
+}

+ 135 - 0
utils/validate.js

@@ -0,0 +1,135 @@
+export function validPassword (str) {
+  // const reg = /^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{8}$/;
+  // 必须同时包含数字,大小写字母
+  /**
+   *(?=.{12})表示要大等于12位。
+   *(?=.*?[a-z])表示要有小写字母。
+   *(?=.*?[A-Z])表示要有大写字母。 
+   */
+  const reg = /^(?=.{8})(?=.*?[a-z])(?=.*?[A-Z])(?=.*?\d).*$/;
+  return reg.test(str);
+}
+
+
+//  ------------------------------------------------------------------------
+/**
+ * @param {string} path
+ * @returns {Boolean}
+ */
+export function isExternal (path) {
+  return /^(https?:|mailto:|tel:)/.test(path);
+}
+
+/**
+ * @param {string} str
+ * @returns {Boolean}
+ */
+export function validUsername (str) {
+  const valid_map = ["admin", "editor"];
+  return valid_map.indexOf(str.trim()) >= 0;
+}
+
+/**
+ * @param {string} url
+ * @returns {Boolean}
+ */
+export function validURL (url) {
+  const reg =
+    /^(https?|ftp):\/\/([a-zA-Z0-9.-]+(:[a-zA-Z0-9.&%$-]+)*@)*((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}|([a-zA-Z0-9-]+\.)*[a-zA-Z0-9-]+\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{2}))(:[0-9]+)*(\/($|[a-zA-Z0-9.,?'\\+&%$#=~_-]+))*$/;
+  return reg.test(url);
+}
+
+/**
+ * @param {string} str
+ * @returns {Boolean}
+ */
+export function validLowerCase (str) {
+  const reg = /^[a-z]+$/;
+  return reg.test(str);
+}
+
+/**
+ * @param {string} str
+ * @returns {Boolean}
+ */
+export function validUpperCase (str) {
+  const reg = /^[A-Z]+$/;
+  return reg.test(str);
+}
+
+/**
+ * @param {string} str
+ * @returns {Boolean}
+ */
+export function validAlphabets (str) {
+  const reg = /^[A-Za-z]+$/;
+  return reg.test(str);
+}
+
+/**
+ * @param {string} email
+ * @returns {Boolean}
+ */
+export function validEmail (email) {
+  const reg =
+    /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
+  return reg.test(email);
+}
+
+/**
+ * @param {string} str
+ * @returns {Boolean}
+ */
+export function isString (str) {
+  if (typeof str === "string" || str instanceof String) {
+    return true;
+  }
+  return false;
+}
+
+/**
+ * @param {Array} arg
+ * @returns {Boolean}
+ */
+export function isArray (arg) {
+  if (typeof Array.isArray === "undefined") {
+    return Object.prototype.toString.call(arg) === "[object Array]";
+  }
+  return Array.isArray(arg);
+}
+
+
+
+// 填写内容必须是纯数字 / 正整数
+export function validPositiveInteger (str) {
+  const reg = /(^[1-9]\d*$)/;
+  return reg.test(str);
+}
+// 大于等于0,保留两位小数
+export function validTwoMinNum (str) {
+  const reg = /^([0-9]{1}|^[1-9]{1}\d{1,15})(\.\d{1,2})?$/;
+  return reg.test(str);
+}
+
+// 填写内容必须是纯数字 / 整数
+export function validPositiveIntegerZero (str) {
+  const reg = /(^[0-9]\d*$)/;
+  return reg.test(str);
+}
+
+export const validateNum = (rule, value, callback) => {
+  // console.log('value = ' , value , '---', 1 + value , rule)
+  if (value === "" || value === undefined) {
+    if (rule.required) {
+      callback(new Error(rule.msg));
+    } else {
+      callback();
+    }
+  } else {
+    if (rule.valids.regular(value)) {
+      callback();
+    } else {
+      callback(new Error(rule.valids.msg));
+    }
+  }
+};