commit 53af2dd84ef1d243c18a83564d7c315a4b45f4e4
Author: 陆亚狮 <2696699791@qq.com>
Date:   Mon Apr 7 09:30:11 2025 +0800
    init
diff --git a/App.vue b/App.vue
new file mode 100644
index 0000000..f21e65c
--- /dev/null
+++ b/App.vue
@@ -0,0 +1,63 @@
+
+
diff --git a/api/api.js b/api/api.js
new file mode 100644
index 0000000..f1bd11f
--- /dev/null
+++ b/api/api.js
@@ -0,0 +1,37 @@
+import request from '@/utils/request'
+//使用说明
+//  export const getList = data => request.get('/api/list', data, false)
+//              页面调用名  请求参数       请求类型  接口地址         loading是否显示
+/*页面中调用方法:(若无请求参数则留空,例:this.$api.getList())
+this.$api.getList(params).then(res => {
+	
+})
+*/
+//列表
+export const getList = data => request.get('/api/list', data)
+//登陆
+export const login = data => request.post('/api/login', data)
+//注册
+export const register = data => request.post('/api/register', data)
+//忘记密码
+export const forgetPassWord = data => request.post('/api/forgetPassWord', data)
+//登陆用户信息
+export const baseInfo = data => request.get('/api/baseinfo', data)
+//检测版本升级
+export const checkVersion = data => request.post('/api/checkVersion2', data,false)
+//文章详情
+export const detail = data => request.get('/api/detail', data,false)
+//获取单页内容
+export const page = data => request.get('/api/page', data)
+//提交实名认证资料
+export const auth = data => request.post('/api/auth', data)
+//修改密码
+export const password = data => request.post('/api/password', data)
+//注销帐号
+export const logout_account = data => request.post('/api/logout_account', data)
+//修改手机号
+export const phoneBind = data => request.get('/api/phoneBind', data)
+//修改邮箱
+export const emailBind = data => request.get('/api/emailBind', data)
+//提交反馈
+export const feedback = data => request.post('/api/feedback', data)
diff --git a/api/env.js b/api/env.js
new file mode 100644
index 0000000..d256ed8
--- /dev/null
+++ b/api/env.js
@@ -0,0 +1,11 @@
+let BASE_URL
+//开发环境中
+if (process.env.NODE_ENV === 'development') {
+  // 开发环境
+  BASE_URL = 'https://mock.apifox.cn/m1/3553664-0-default'  //开发环境请求地址
+} else {
+  // 生产环境
+  BASE_URL = 'https://mock.apifox.cn/m1/3553664-0-default'  //生成环境请求地址
+}
+ 
+export default BASE_URL
\ No newline at end of file
diff --git a/components/appUpdate/appUpdate.js b/components/appUpdate/appUpdate.js
new file mode 100644
index 0000000..0bbbf94
--- /dev/null
+++ b/components/appUpdate/appUpdate.js
@@ -0,0 +1,790 @@
+export default function(updateInfo) {
+	updateInfo.platform = updateInfo.platform ? updateInfo.platform : 'android'
+	updateInfo.mainColor = updateInfo.mainColor ? updateInfo.mainColor : 'FF5B78'
+	if (updateInfo.platform == 'android' || updateInfo.platform == 'ios') {
+		
+	} else {
+		return false
+	}
+	let maskLayer = new plus.nativeObj.View('maskLayer', {
+		top: '0px',
+		left: '0px',
+		height: '100%',
+		width: '100%',
+		backgroundColor: 'rgba(0,0,0,0.5)'
+	})
+	let screenWidth = plus.screen.resolutionWidth
+	let screenHeight = plus.screen.resolutionHeight
+	const popupViewWidth = screenWidth * 0.7
+	const viewContentPadding = 20
+	const viewContentWidth = parseInt(popupViewWidth - (viewContentPadding * 2))
+	const descriptionList = drawtext((updateInfo.updateContent || '发现新版本'), viewContentWidth)
+	let popupViewHeight = 80 + 20 + 20 + 90 + 50
+	let popupViewContentList = [{
+			src: '/static/images/update.png',
+			id: "logo", 
+			tag: "img",
+			position: {
+				top: "0px",
+				left: (popupViewWidth - 124) / 2 + "px",
+				width: "124px",
+				height: "80px",
+			}
+		},
+		{
+			tag: 'font',
+			id: 'title',
+			text: "发现新版本 " + (updateInfo.version || ''),
+			textStyles: {
+				size: '18px',
+				color: "#333",
+				weight: "bold",
+				whiteSpace: "normal"
+			},
+			position: {
+				top: '90px',
+				left: viewContentPadding + "px",
+				width: viewContentWidth + "px",
+				height: "30px",
+			}
+		}
+	]
+	const textHeight = 18
+	let contentTop = 130
+	descriptionList.forEach((item, index) => {
+		if (index > 0) {
+			popupViewHeight += textHeight;
+			contentTop += textHeight;
+		}
+		popupViewContentList.push({
+			tag: 'font',
+			id: 'content' + index + 1,
+			text: item.content,
+			textStyles: {
+				size: '14px',
+				color: "#666",
+				lineSpacing: "50%",
+				align: "left"
+			},
+			position: {
+				top: contentTop + "px",
+				left: viewContentPadding + "px",
+				width: viewContentWidth + "px",
+				height: textHeight + "px",
+			}
+		});
+		if (item.type == "break") {
+			contentTop += 10;
+			popupViewHeight += 10;
+		}
+	})
+	if (updateInfo.force) {
+		popupViewContentList.push({
+			tag: 'rect', //绘制底边按钮
+			rectStyles: {
+				radius: "6px",
+				color: updateInfo.mainColor
+			},
+			position: {
+				bottom: viewContentPadding + 'px',
+				left: viewContentPadding + "px",
+				width: viewContentWidth + "px",
+				height: "40px"
+			}
+		})
+		popupViewContentList.push({
+			tag: 'font',
+			id: 'confirmText',
+			text: "立即升级",
+			textStyles: {
+				size: '16px',
+				color: "#FFF",
+				lineSpacing: "0%",
+			},
+			position: {
+				bottom: viewContentPadding + 'px',
+				left: viewContentPadding + "px",
+				width: viewContentWidth + "px",
+				height: "40px"
+			}
+		})
+	} else {
+		popupViewContentList.push({
+			tag: 'rect',
+			id: 'cancelBox',
+			rectStyles: {
+				radius: "3px",
+				borderColor: "#f1f1f1",
+				borderWidth: "1px",
+			},
+			position: {
+				bottom: viewContentPadding + 'px',
+				left: viewContentPadding + "px",
+				width: (viewContentWidth - viewContentPadding) / 2 + "px",
+				height: "40px",
+			}
+		})
+		popupViewContentList.push({
+			tag: 'rect',
+			id: 'confirmBox',
+			rectStyles: {
+				radius: "3px",
+				color: updateInfo.mainColor,
+			},
+			position: {
+				bottom: viewContentPadding + 'px',
+				left: ((viewContentWidth - viewContentPadding) / 2 + viewContentPadding * 2) + "px",
+				width: (viewContentWidth - viewContentPadding) / 2 + "px",
+				height: "40px",
+			}
+		})
+		popupViewContentList.push({
+			tag: 'font',
+			id: 'cancelText',
+			text: "暂不升级",
+			textStyles: {
+				size: '16px',
+				color: "#666",
+				lineSpacing: "0%",
+				whiteSpace: "normal"
+			},
+			position: {
+				bottom: viewContentPadding + 'px',
+				left: viewContentPadding + "px",
+				width: (viewContentWidth - viewContentPadding) / 2 + "px",
+				height: "40px",
+			}
+		})
+		popupViewContentList.push({
+			tag: 'font',
+			id: 'confirmText',
+			text: "立即升级",
+			textStyles: {
+				size: '16px',
+				color: "#FFF",
+				lineSpacing: "0%",
+				whiteSpace: "normal"
+			}, 
+			position: {
+				bottom: viewContentPadding + 'px',
+				left: ((viewContentWidth - viewContentPadding) / 2 + viewContentPadding * 2) + "px",
+				width: (viewContentWidth - viewContentPadding) / 2 + "px",
+				height: "40px",
+			}
+		})
+	}
+	let popupView = new plus.nativeObj.View("popupView", { //创建底部图标菜单
+		tag: "rect",
+		top: (screenHeight - popupViewHeight) / 2 + "px",
+		left: '15%',
+		height: popupViewHeight + "px",
+		width: "70%"
+	})
+	popupView.drawRect({
+		color: "#FFFFFF",
+		radius: "8px"
+	}, {
+		top: "40px",
+		height: popupViewHeight - 40 + "px",
+	})
+	popupView.draw(popupViewContentList)
+	popupView.addEventListener("click", e => {
+		let maxTop = popupViewHeight - viewContentPadding
+		let maxLeft = popupViewWidth - viewContentPadding
+		let buttonWidth = (viewContentWidth - viewContentPadding) / 2
+		if (e.clientY > maxTop - 30 && e.clientY < maxTop) {
+			if (updateInfo.force) {
+				if (e.clientX > viewContentPadding && e.clientX < maxLeft) {
+					maskLayer.hide()
+					popupView.hide()
+					let platform = updateInfo.platform || 'android'
+					let downUrl = updateInfo.downUrl || ''
+					download(updateInfo)
+				}
+			} else {
+				let maxTop = popupViewHeight - viewContentPadding;
+				let maxLeft = popupViewWidth - viewContentPadding;
+				let buttonWidth = (viewContentWidth - viewContentPadding) / 2;
+				if (e.clientY > maxTop - 30 && e.clientY < maxTop) {
+					// 暂不升级
+					if (e.clientX > viewContentPadding && e.clientX < maxLeft - buttonWidth -
+						viewContentPadding) {
+						maskLayer.hide()
+						popupView.hide()
+					}
+					if (e.clientX > maxLeft - buttonWidth && e.clientX < maxLeft) {
+						// 立即升级
+						maskLayer.hide()
+						popupView.hide()
+						let platform = updateInfo.platform || 'android'
+						let downUrl = updateInfo.downUrl || ''
+						download(updateInfo)
+					}
+				}
+			}
+		}
+	})
+	// 点击遮罩层
+	maskLayer.addEventListener("click", function() { //处理遮罩层点击
+		// maskLayer.hide();
+		// popupView.hide();
+	})
+	// 显示弹窗
+	maskLayer.show()
+	popupView.show()
+}
+
+// 下载流程
+function download(updateInfo) {
+	let platform = updateInfo.platform || 'android'
+	if (updateInfo.downUrl) {
+		if (platform == 'ios') {
+			plus.runtime.openURL(updateInfo.downUrl)
+		}
+		if (platform == 'android') {
+			getDownload(updateInfo)
+		}
+	} else {
+		plus.nativeUI.alert('下载地址无效')
+	}
+}
+
+// 从服务器下载应用资源包(wgt文件)
+const getDownload = function(data) {
+	let dtask
+	let popupData = {
+		progress: true,
+		buttonNum: 2
+	};
+	if(data.force){
+		popupData.buttonNum = 0
+	}
+	
+	let lastProgressValue = 0
+	let popupObj = downloadPopup(popupData, data.mainColor)
+	
+	dtask = plus.downloader.createDownload(data.downUrl, {
+		filename: "_doc/update/"
+	}, function(download, status) {
+		if (status == 200) {
+			popupObj.change({
+				progressValue: 100,
+				progressTip:"正在安装文件...",
+				progress: true,
+				buttonNum: 0
+			})
+			plus.runtime.install(download.filename, {}, function() {
+				popupObj.change({
+					contentText: "应用资源更新完成!",
+					buttonNum: 1,
+					progress: false
+				});
+			}, function(e) {
+				popupObj.cancel()
+				plus.nativeUI.alert("安装文件失败[" + e.code + "]:" + e.message);
+			});
+		} else {
+			popupObj.change({
+				contentText: "文件下载失败...",
+				buttonNum: 1,
+				progress: false
+			});
+		}
+	});
+	dtask.start()
+	dtask.addEventListener("statechanged", function(task, status) {
+		switch (task.state) {
+			case 1: // 开始
+				popupObj.change({
+					progressValue:0,
+					progressTip:"准备下载...",
+					progress: true
+				});
+				break;
+			case 2: // 已连接到服务器  
+				popupObj.change({
+					progressValue:0,
+					progressTip:"开始下载...",
+					progress: true
+				});
+				break;
+			case 3:
+				const progress = parseInt(task.downloadedSize / task.totalSize * 100);
+				if(progress - lastProgressValue >= 2){
+					lastProgressValue = progress;
+					popupObj.change({
+						progressValue:progress,
+						progressTip: "已下载" + progress + "%",
+						progress: true
+					});
+				}
+				break;
+		}
+	})
+	// 取消下载
+	popupObj.cancelDownload = function(){
+		dtask && dtask.abort()
+		uni.showToast({
+			title: "已取消下载",
+			icon:"none"
+		});
+	}
+	// 重启APP
+	popupObj.reboot = function(){
+		plus.runtime.restart()
+	}
+}
+
+// 文件下载的弹窗绘图
+function downloadPopupDrawing(data, mainColor){
+	// 以下为计算菜单的nview绘制布局,为固定算法,使用者无关关心
+	const screenWidth = plus.screen.resolutionWidth;
+	const screenHeight = plus.screen.resolutionHeight;
+	//弹窗容器宽度
+	const popupViewWidth = screenWidth * 0.7;
+	
+	// 弹窗容器的Padding
+	const viewContentPadding = 20;
+	// 弹窗容器的宽度
+	const viewContentWidth = popupViewWidth - (viewContentPadding * 2);
+	// 弹窗容器高度
+	let popupViewHeight = viewContentPadding * 3 + 60;
+	let progressTip = data.progressTip || "准备下载...";
+	let contentText = data.contentText || "正在为您更新,请耐心等待";
+	
+	let elementList = [
+		{
+			tag: 'rect', //背景色
+			color: '#FFFFFF',
+			rectStyles:{
+				radius: "8px"
+			}
+		},
+		{
+			tag: 'font',
+			id: 'title',
+			text: "升级APP",
+			textStyles: {
+				size: '16px',
+				color: "#333",
+				weight: "bold",
+				verticalAlign: "middle",
+				whiteSpace: "normal"
+			},
+			position: {
+				top: viewContentPadding + 'px',
+				height: "30px",
+			}
+		},
+		{
+			tag: 'font',
+			id: 'content',
+			text: contentText,
+			textStyles: {
+				size: '14px',
+				color: "#333",
+				verticalAlign: "middle",
+				whiteSpace: "normal"
+			},
+			position: {
+				top: viewContentPadding * 2 + 30 + 'px',
+				height: "20px",
+			}
+		}
+	];
+	// 是否有进度条
+	
+	if(data.progress){
+		popupViewHeight += viewContentPadding + 40
+		elementList = elementList.concat([
+			{
+				tag: 'font',
+				id: 'progressValue',
+				text: progressTip,
+				textStyles: {
+					size: '14px',
+					color: mainColor,
+					whiteSpace: "normal"
+				},
+				position: {
+					top: viewContentPadding * 4 + 20 + 'px',
+					height: "30px"
+				}
+			},
+			{
+				tag: 'rect', //绘制进度条背景
+				id: 'progressBg',
+				rectStyles:{
+					radius: "4px",
+					borderColor: "#f1f1f1",
+					borderWidth: "1px",
+				},
+				position:{
+					top: viewContentPadding * 4 + 60 + 'px',
+					left: viewContentPadding + "px",
+					width: viewContentWidth + "px",
+					height: "8px"
+				}
+			},
+		])
+	}
+	
+	if (data.buttonNum == 2) {
+		popupViewHeight += viewContentPadding + 30;
+		elementList = elementList.concat([
+			{
+				tag: 'rect', //绘制底边按钮
+				rectStyles:{
+					radius: "3px",
+					borderColor: "#f1f1f1",
+					borderWidth: "1px",
+				},
+				position:{
+					bottom: viewContentPadding + 'px',
+					left: viewContentPadding + "px",
+					width: (viewContentWidth - viewContentPadding) / 2 + "px",
+					height: "40px"
+				}
+			},
+			{
+				tag: 'rect', //绘制底边按钮
+				rectStyles:{
+					radius: "3px",
+					color: mainColor
+				},
+				position:{
+					bottom: viewContentPadding + 'px',
+					left: ((viewContentWidth - viewContentPadding) / 2 + viewContentPadding * 2) + "px",
+					width: (viewContentWidth - viewContentPadding) / 2 + "px",
+					height: "40px"
+				}
+			},
+			{
+				tag: 'font',
+				id: 'cancelText',
+				text: "取消下载",
+				textStyles: {
+					size: '14px',
+					color: "#666",
+					lineSpacing: "0%",
+					whiteSpace: "normal"
+				},
+				position: {
+					bottom: viewContentPadding + 'px',
+					left: viewContentPadding + "px",
+					width: (viewContentWidth - viewContentPadding) / 2 + "px",
+					height: "40px",
+				}
+			},
+			{
+				tag: 'font',
+				id: 'confirmText',
+				text: "后台下载",
+				textStyles: {
+					size: '14px',
+					color: "#FFF",
+					lineSpacing: "0%",
+					whiteSpace: "normal"
+				},
+				position: {
+					bottom: viewContentPadding + 'px',
+					left: ((viewContentWidth - viewContentPadding) / 2 + viewContentPadding * 2) + "px",
+					width: (viewContentWidth - viewContentPadding) / 2 + "px",
+					height: "40px",
+				}
+			}
+		]);
+	}
+	
+	if (data.buttonNum == 1) {
+		popupViewHeight += viewContentPadding + 40;
+		elementList = elementList.concat([
+			{
+				tag: 'rect', //绘制底边按钮
+				rectStyles:{
+					radius: "6px",
+					color: $mainColor
+				},
+				position:{
+					bottom: viewContentPadding + 'px',
+					left: viewContentPadding + "px",
+					width: viewContentWidth + "px",
+					height: "40px"
+				}
+			},
+			{
+				tag: 'font',
+				id: 'confirmText',
+				text: "关闭",
+				textStyles: {
+					size: '14px',
+					color: "#FFF",
+					lineSpacing: "0%",
+				},
+				position: {
+					bottom: viewContentPadding + 'px',
+					left: viewContentPadding + "px",
+					width: viewContentWidth + "px",
+					height: "40px"
+				}
+			}
+		]);
+	}
+	
+	return {
+		popupViewHeight:popupViewHeight,
+		popupViewWidth:popupViewWidth,
+		screenHeight:screenHeight,
+		viewContentWidth:viewContentWidth,
+		viewContentPadding:viewContentPadding,
+		elementList: elementList
+	};
+}
+// 文件下载的弹窗
+function downloadPopup(data, mainColor) {
+	
+	// 弹窗遮罩层
+	let maskLayer = new plus.nativeObj.View("maskLayer", { //先创建遮罩层
+		top: '0px',
+		left: '0px',
+		height: '100%',
+		width: '100%',
+		backgroundColor: 'rgba(0,0,0,0.5)'
+	});
+	
+	let popupViewData = downloadPopupDrawing(data, mainColor);
+	
+	// 弹窗内容
+	let popupView = new plus.nativeObj.View("popupView", { //创建底部图标菜单
+		tag: "rect",
+		top: (popupViewData.screenHeight - popupViewData.popupViewHeight) / 2 + "px",
+		left: '15%',
+		height: popupViewData.popupViewHeight + "px",
+		width: "70%",
+	});
+	let progressValue = 0;
+	let progressTip = 0;
+	let contentText = 0;
+	let buttonNum = 2;
+	if(data.buttonNum >= 0){
+		buttonNum = data.buttonNum;
+	}
+	popupView.draw(popupViewData.elementList);
+    let callbackData = {
+		change: function(res) {
+			let progressElement = [];
+			if(res.progressValue){
+				progressValue = res.progressValue;
+				// 绘制进度条
+				progressElement.push({
+					tag: 'rect', //绘制进度条背景
+					id: 'progressValueBg',
+					rectStyles:{
+						radius: "4px",
+						color: mainColor
+					},
+					position:{
+						top: popupViewData.viewContentPadding * 4 + 60 + 'px',
+						left: popupViewData.viewContentPadding + "px",
+						width: popupViewData.viewContentWidth * (res.progressValue / 100) + "px",
+						height: "8px"
+					}
+				});
+			}
+			if(res.progressTip){
+				progressTip = res.progressTip;
+				progressElement.push({
+					tag: 'font',
+					id: 'progressValue',
+					text: res.progressTip,
+					textStyles: {
+						size: '14px',
+						color: mainColor,
+						whiteSpace: "normal"
+					},
+					position: {
+						top: popupViewData.viewContentPadding * 4 + 20 + 'px',
+						height: "30px"
+					}
+				});
+			}
+			if(res.contentText){
+				contentText = res.contentText;
+				progressElement.push({
+					tag: 'font',
+					id: 'content',
+					text: res.contentText,
+					textStyles: {
+						size: '16px',
+						color: "#333",
+						whiteSpace: "normal"
+					},
+					position: {
+						top: popupViewData.viewContentPadding * 2 + 30 + 'px',
+						height: "30px",
+					}
+				});
+			}
+			if(res.buttonNum >= 0 && buttonNum != res.buttonNum){
+				buttonNum = res.buttonNum;
+				popupView.reset();
+				popupViewData = downloadPopupDrawing(Object.assign({
+					progressValue:progressValue,
+					progressTip:progressTip,
+					contentText:contentText,
+				},res));
+				let newElement = [];
+				popupViewData.elementList.map((item,index) => {
+					let have = false;
+					progressElement.forEach((childItem,childIndex) => {
+						if(item.id == childItem.id){
+							have = true;
+						}
+					});
+					if(!have){
+						newElement.push(item);
+					}
+				});
+				progressElement = newElement.concat(progressElement);
+				popupView.setStyle({
+					tag: "rect",
+					top: (popupViewData.screenHeight - popupViewData.popupViewHeight) / 2 + "px",
+					left: '15%',
+					height: popupViewData.popupViewHeight + "px",
+					width: "70%",
+				});
+				popupView.draw(progressElement); 
+			}else{
+				popupView.draw(progressElement);
+			}
+		},
+		cancel: function() { 
+			maskLayer.hide();
+			popupView.hide();
+		}
+	}
+	popupView.addEventListener("click", function(e) {
+		let maxTop = popupViewData.popupViewHeight - popupViewData.viewContentPadding;
+		let maxLeft = popupViewData.popupViewWidth - popupViewData.viewContentPadding;
+		if (e.clientY > maxTop - 40 && e.clientY < maxTop) {
+			if(buttonNum == 1){
+				// 单按钮
+				if (e.clientX > popupViewData.viewContentPadding && e.clientX < maxLeft) {
+					maskLayer.hide();
+					popupView.hide();
+                    callbackData.reboot();
+				}
+			}else if(buttonNum == 2){
+				// 双按钮
+				let buttonWidth = (popupViewData.viewContentWidth - popupViewData.viewContentPadding) / 2;
+				if (e.clientX > popupViewData.viewContentPadding && e.clientX < maxLeft - buttonWidth - popupViewData.viewContentPadding) {
+					maskLayer.hide();
+					popupView.hide();
+                    callbackData.cancelDownload();
+				} else if (e.clientX > maxLeft - buttonWidth && e.clientX < maxLeft) {
+					maskLayer.hide();
+					popupView.hide();
+				}
+			}
+		}
+	});
+	// 显示弹窗
+	maskLayer.show();
+	popupView.show();
+	// 改变进度条
+	return callbackData
+}
+
+// 文字换行
+function drawtext(text, maxWidth) {
+	let textArr = text.split("");
+	let len = textArr.length;
+	// 上个节点
+	let previousNode = 0;
+	// 记录节点宽度
+	let nodeWidth = 0;
+	// 文本换行数组
+	let rowText = [];
+	// 如果是字母,侧保存长度
+	let letterWidth = 0;
+	// 汉字宽度
+	let chineseWidth = 14;
+	// otherFont宽度
+	let otherWidth = 7;
+	for (let i = 0; i < len; i++) {
+		if (/[\u4e00-\u9fa5]|[\uFE30-\uFFA0]/g.test(textArr[i])) {
+			if (letterWidth > 0) {
+				if (nodeWidth + chineseWidth + letterWidth * otherWidth > maxWidth) {
+					rowText.push({
+						type: "text",
+						content: text.substring(previousNode, i)
+					});
+					previousNode = i
+					nodeWidth = chineseWidth
+					letterWidth = 0
+				} else {
+					nodeWidth += chineseWidth + letterWidth * otherWidth
+					letterWidth = 0
+				}
+			} else {
+				if (nodeWidth + chineseWidth > maxWidth) {
+					rowText.push({
+						type: "text",
+						content: text.substring(previousNode, i)
+					})
+					previousNode = i
+					nodeWidth = chineseWidth
+				} else {
+					nodeWidth += chineseWidth
+				}
+			}
+		} else {
+			if (/\n/g.test(textArr[i])) {
+				rowText.push({
+					type: "break",
+					content: text.substring(previousNode, i)
+				})
+				previousNode = i + 1
+				nodeWidth = 0
+				letterWidth = 0
+			} else if (textArr[i] == "\\" && textArr[i + 1] == "n") {
+				rowText.push({
+					type: "break",
+					content: text.substring(previousNode, i)
+				})
+				previousNode = i + 2
+				nodeWidth = 0
+				letterWidth = 0
+			} else if (/[a-zA-Z0-9]/g.test(textArr[i])) {
+				letterWidth += 1;
+				if (nodeWidth + letterWidth * otherWidth > maxWidth) {
+					rowText.push({
+						type: "text",
+						content: text.substring(previousNode, i + 1 - letterWidth)
+					})
+					previousNode = i + 1 - letterWidth
+					nodeWidth = letterWidth * otherWidth
+					letterWidth = 0
+				}
+			} else {
+				if (nodeWidth + otherWidth > maxWidth) {
+					rowText.push({
+						type: "text",
+						content: text.substring(previousNode, i)
+					});
+					previousNode = i
+					nodeWidth = otherWidth
+				} else {
+					nodeWidth += otherWidth
+				}
+			}
+		}
+	}
+	if (previousNode < len) {
+		rowText.push({
+			type: "text",
+			content: text.substring(previousNode, len)
+		})
+	}
+	return rowText
+}
\ No newline at end of file
diff --git a/components/daySelect/index.vue b/components/daySelect/index.vue
new file mode 100644
index 0000000..3ed2e56
--- /dev/null
+++ b/components/daySelect/index.vue
@@ -0,0 +1,117 @@
+
+  
+    
+			{{ currentYear }}年  {{ currentMonth }}月
+      
+        
+          
+            
+              {{ item.day }}
+              今天
+              周{{ item.week }}
+            
+          
+        
+      
+    
+  
+
+
+
+
+
diff --git a/config/config.js b/config/config.js
new file mode 100644
index 0000000..6d3c1fc
--- /dev/null
+++ b/config/config.js
@@ -0,0 +1,17 @@
+
+let config = {
+	//不拦截页面路径
+    whiteList: [
+    	'/pages/public/login',
+		'/pages/public/forget_password',
+		'/pages/public/register',
+		'/pages/index/index',
+		'/pages/index/list',
+		'/pages/subPack/index/detail',
+		//一行一个
+    ],
+    token : 'token', //本地存储token的变量名
+    login_page : '/pages/public/login',  //拦截后跳转的登陆页路径
+	vconsole_status: 0,  //是否启用调试工具,1为启用,0不启用
+}
+export default config
\ No newline at end of file
diff --git a/index.html b/index.html
new file mode 100644
index 0000000..c3ff205
--- /dev/null
+++ b/index.html
@@ -0,0 +1,20 @@
+
+
+  
+    
+    
+    
+    
+    
+  
+  
+    
+    
+  
+
diff --git a/main.js b/main.js
new file mode 100644
index 0000000..3472935
--- /dev/null
+++ b/main.js
@@ -0,0 +1,47 @@
+import App from './App'
+import '@/utils/interceptor.js';//引入拦截
+
+import Vue from 'vue'
+import uView from '@/uni_modules/uview-ui'
+Vue.use(uView)
+
+import store from './store'
+
+// 注册请求方法
+import * as api from '@/api/api.js'
+Vue.prototype.$api = api
+
+
+import BASE_URL from '@/api/env.js' //引入接口共用地址
+Vue.prototype.$API_BASE_URL= BASE_URL
+
+import config from '@/config/config.js';
+Vue.prototype.$systemConfig = config
+
+let vuexStore = require("@/store/$u.mixin.js");
+Vue.mixin(vuexStore);
+
+//是否启用调试工具
+if(config.vconsole_status){
+	const vconsole = require('vconsole')
+	Vue.prototype.$vconsole = new vconsole() // 使用vconsole
+}
+
+
+Vue.config.productionTip = false
+App.mpType = 'app'
+const app = new Vue({
+	store,
+  ...App
+})
+app.$mount()
+
+// #ifdef VUE3
+import { createSSRApp } from 'vue'
+export function createApp() {
+  const app = createSSRApp(App)
+  return {
+    app
+  }
+}
+// #endif
\ No newline at end of file
diff --git a/manifest.json b/manifest.json
new file mode 100644
index 0000000..c1671fd
--- /dev/null
+++ b/manifest.json
@@ -0,0 +1,91 @@
+{
+    "name" : "巡检保洁",
+    "appid" : "",
+    "description" : "",
+    "versionName" : "1.0.0",
+    "versionCode" : "100",
+    "transformPx" : false,
+    /* 5+App特有相关 */
+    "app-plus" : {
+        "usingComponents" : true,
+        "nvueStyleCompiler" : "uni-app",
+        "compilerVersion" : 3,
+        "splashscreen" : {
+            "alwaysShowBeforeRender" : true,
+            "waiting" : true,
+            "autoclose" : true,
+            "delay" : 0
+        },
+        /* 模块配置 */
+        "modules" : {
+            "Camera" : {}
+        },
+        /* 应用发布信息 */
+        "distribute" : {
+            /* android打包配置 */
+            "android" : {
+                "permissions" : [
+                    "",
+                    "",
+                    "",
+                    "",
+                    "",
+                    "",
+                    "",
+                    "",
+                    "",
+                    "",
+                    "",
+                    "",
+                    "",
+                    "",
+                    "",
+                    "",
+                    "",
+                    ""
+                ]
+            },
+            /* ios打包配置 */
+            "ios" : {},
+            /* SDK配置 */
+            "sdkConfigs" : {
+                "geolocation" : {
+                    "system" : {
+                        "__platform__" : [ "ios" ]
+                    }
+                }
+            },
+            "splashscreen" : {
+                "androidStyle" : "default"
+            }
+        }
+    },
+    /* 快应用特有相关 */
+    "quickapp" : {},
+    /* 小程序特有相关 */
+    "mp-weixin" : {
+        "appid" : "",
+        "setting" : {
+            "urlCheck" : false,
+            "postcss" : true,
+            "minified" : true
+        },
+        "usingComponents" : true,
+        "optimization" : {
+            "subPackages" : true
+        }
+    },
+    "mp-alipay" : {
+        "usingComponents" : true
+    },
+    "mp-baidu" : {
+        "usingComponents" : true
+    },
+    "mp-toutiao" : {
+        "usingComponents" : true
+    },
+    "uniStatistics" : {
+        "enable" : false
+    },
+    "vueVersion" : "2"
+}
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..b2277a2
--- /dev/null
+++ b/package.json
@@ -0,0 +1,20 @@
+{
+    "id": "liuyan814-unitempate",
+    "name": "巡检保洁",
+    "displayName": "巡检保洁",
+    "version": "1.0.6",
+    "description": "快速搭建uni-app项目,封装request,带页面拦截器,请求锁,带请求loading,集成uview,集成在线更新组件、集成调试工具vconsole,分包。",
+    "keywords": [
+        "封装request",
+        "页面拦截器",
+        "uview",
+        "图鸟UI",
+        "在线更新"
+    ],
+    "dcloudext": {
+        "category": [
+            "uni-app前端模板",
+            "前端页面模板"
+        ]
+    }
+}
\ No newline at end of file
diff --git a/pages.json b/pages.json
new file mode 100644
index 0000000..72802a3
--- /dev/null
+++ b/pages.json
@@ -0,0 +1,222 @@
+{
+	// 如果您是通过uni_modules形式引入uView,可以忽略此配置
+	"easycom": {
+		"^u-(.*)": "@/uni_modules/uview-ui/components/u-$1/u-$1.vue"
+	},
+	"pages": [
+		{
+			"path": "pages/index/index",
+			"style": {
+				"navigationBarTitleText": "首页"
+			}
+		},
+		{
+			"path": "pages/index/list",
+			"style": {
+				"navigationBarTitleText": "保洁点位"
+			}
+		},
+		{
+			"path": "pages/index/cleanDetails",
+			"style": {
+				"navigationStyle": "custom" ,
+				"navigationBarTextStyle": "black",
+				"navigationBarTitleText": "保洁详情"
+			}
+		},
+		{
+			"path": "pages/index/cleanPlan",
+			"style": {
+				"navigationStyle": "custom" ,
+				"navigationBarTextStyle": "black",
+				"navigationBarTitleText": "保洁计划"
+			}
+		},
+		{
+			"path": "pages/index/planList",
+			"style": {
+				"navigationStyle": "custom" ,
+				"navigationBarTextStyle": "black",
+				"navigationBarTitleText": "计划列表"
+			}
+		},
+		{
+			"path": "pages/my/index",
+			"style": {
+				"navigationBarTitleText": "我的",
+				"navigationBarBackgroundColor": "#4790FF",
+				"navigationBarTextStyle": "white",
+				"enablePullDownRefresh": true
+
+			}
+		},
+		{
+			"path": "pages/public/login",
+			"style": {
+				"navigationBarTitleText": "登录"
+			}
+		},
+		{
+			"path" : "pages/my/profile",
+			"style" : 
+			{
+				"navigationBarTitleText" : "个人信息",
+				"enablePullDownRefresh" : false
+			}
+		},
+		{
+			"path" : "pages/my/account/setting",
+			"style" : 
+			{
+				"navigationBarTitleText" : "设置",
+				"enablePullDownRefresh" : false
+			}
+		},
+		{
+			"path" : "pages/my/account/password",
+			"style" : 
+			{
+				"navigationBarTitleText" : "修改密码",
+				"enablePullDownRefresh" : false
+			}
+		},
+		{
+			"path" : "pages/my/account/index",
+			"style" : 
+			{
+				"navigationBarTitleText" : "帐号&安全",
+				"enablePullDownRefresh" : false
+			}
+		},
+		{
+			"path" : "pages/my/about/index",
+			"style" : 
+			{
+				"navigationBarTitleText" : "关于我们",
+				"enablePullDownRefresh" : false
+			}
+		},
+		{
+			"path" : "pages/my/account/phone",
+			"style" : 
+			{
+				"navigationBarTitleText" : "手机号绑定",
+				"enablePullDownRefresh" : false
+			}
+		},
+		{
+			"path" : "pages/my/account/email",
+			"style" : 
+			{
+				"navigationBarTitleText" : "邮箱绑定",
+				"enablePullDownRefresh" : false
+			}
+		},
+		{
+			"path" : "pages/my/account/logout_account",
+			"style" : 
+			{
+				"navigationBarTitleText" : "注销帐号",
+				"enablePullDownRefresh" : false
+			}
+		},
+		{
+			"path" : "pages/my/auth",
+			"style" : 
+			{
+				"navigationBarTitleText" : "实名认证",
+				"enablePullDownRefresh" : false
+			}
+		},
+		{
+			"path" : "pages/public/page",
+			"style" : 
+			{
+				"navigationBarTitleText" : "",
+				"enablePullDownRefresh" : false
+			}
+		},
+		{
+			"path" : "pages/my/about/feedback",
+			"style" : 
+			{
+				"navigationBarTitleText" : "意见反馈",
+				"enablePullDownRefresh" : false
+			}
+		},
+		{
+			"path" : "pages/public/register",
+			"style" : 
+			{
+				"navigationBarTitleText" : "注册",
+				"enablePullDownRefresh" : false
+			}
+		},
+		{
+			"path" : "pages/public/forget_password",
+			"style" : 
+			{
+				"navigationBarTitleText" : "忘记密码",
+				"enablePullDownRefresh" : false
+			}
+		}
+		
+    ],
+	//分包加载配置,此配置为小程序的分包加载机制。
+	"subPackages": [
+		{
+			"root": "pages/subPack", //子包的根目录
+			"pages": [
+				{
+					"path": "index/detail",
+					"style": {
+						"navigationBarTitleText": "详情"
+					}
+				}
+				
+			]
+		}
+	],
+	
+	"globalStyle": {
+		"navigationBarTextStyle": "#211D2F",
+		"navigationBarTitleText": "uni-app",
+		"navigationBarBackgroundColor": "white",
+		"backgroundColor": "#F8F8F8"
+	}, 
+	"tabBar": {
+		"color": "#2D2D2D",
+		"selectedColor": "#4183F8",
+		"borderStyle": "white",
+		"list": [
+			{
+				"pagePath": "pages/index/index",
+				"iconPath": "static/tab/home.png",
+				"selectedIconPath": "static/tab/home_cur.png",
+				"text": "首页"
+			},
+			{
+				"pagePath": "pages/index/list",
+				"iconPath": "static/tab/list.png",
+				"selectedIconPath": "static/tab/list_cur.png",
+				"text": "计划"
+			},
+			{
+				"pagePath": "pages/my/index",
+				"iconPath": "static/tab/my.png",
+				"selectedIconPath": "static/tab/my_cur.png",
+				"text": "我的"
+			}
+		]
+	},
+	
+	// 分包预载配置
+	"preloadRule": {
+		// 当我们进入了pages/index/index页面以后就会预下载pages/subPack分包
+		"pages/index/index": {
+			"network": "all",	//在指定网络下预下载,可选值为:all(不限网络)、wifi(仅wifi下预下载)
+			"packages": ["pages/subPack"]	//进入页面后预下载分包
+		}
+	},
+	"uniIdRouter": {}
+}
diff --git a/pages/detail.vue b/pages/detail.vue
new file mode 100644
index 0000000..5309fa1
--- /dev/null
+++ b/pages/detail.vue
@@ -0,0 +1,155 @@
+
+	
+		
+		    
+		    
+				
+				
+				
+					
+					
+					
+					
+					
+					
+				
+				
+				基本信息:
+				
+					订单编号:
+					{{item.order_sn}}
+				
+
+				派单信息:
+				
+				
+					派单时间:
+					{{item.dispatch_time}}
+				
+				
+				
+					安装师傅:
+					{{item.master_name}}
+				
+				
+				
+					师傅电话:
+					{{item.master_tel}}
+				
+		    
+		
+	
+
+
+
diff --git a/pages/form.vue b/pages/form.vue
new file mode 100644
index 0000000..4e085d2
--- /dev/null
+++ b/pages/form.vue
@@ -0,0 +1,205 @@
+
+	
+		
+			
+				
+			
+			
+				
+			
+			
+				
+			
+			
+				
+			
+			
+				
+			
+			
+				 
+			
+			
+			
+				
+				
+					我已知晓并同意 《用户服务协议》及《隐私政策》
+				
+			
+			
+			
+				提交注册
+			
+		
+		
+		
+			  
+			  
+		
+	
+
+
+
+
+
+
diff --git a/pages/index/cleanDetails.vue b/pages/index/cleanDetails.vue
new file mode 100644
index 0000000..9607b9a
--- /dev/null
+++ b/pages/index/cleanDetails.vue
@@ -0,0 +1,116 @@
+
+  
+    
+    
+      保洁区域名称
+      所在区域:学校操场
+    
+    
+      区域详情
+      
+        
+          室内/室外
+          区域类型
+        
+        
+          保洁员1号
+          保洁人员
+        
+        
+          2024/1/27 9:53:35
+          清扫时间
+        
+        
+          清扫完成
+          备注
+        
+      
+      保洁区域图片
+      
+        
+      
+    
+  
+
+
+
+
+
diff --git a/pages/index/cleanPlan.vue b/pages/index/cleanPlan.vue
new file mode 100644
index 0000000..cf31785
--- /dev/null
+++ b/pages/index/cleanPlan.vue
@@ -0,0 +1,224 @@
+
+  
+    
+      
+        
+          
+        
+      
+    
+    
+      2024年11月21号
+       08:30~11:30
+      
+        
+          {{ v.name }}
+        
+      
+    
+    
+      
+        待保洁
+        
+          
+          东大门北侧_门2
+        
+        
+          区域类型
+          
+          
+        
+        
+          {{ "需要清理整个户外通道/保持跑道整洁花坛边落叶清扫" }}
+        
+      
+    
+  
+
+
+
+
+
diff --git a/pages/index/index.vue b/pages/index/index.vue
new file mode 100644
index 0000000..ec990c1
--- /dev/null
+++ b/pages/index/index.vue
@@ -0,0 +1,173 @@
+
+  
+    
+    
+      今日任务
+      
+        
+          
+            足球场休息室
+            
+          
+          
+            
+          
+        
+      
+    
+    
+      
+        
+        已保洁区域
+        26 /50 
+        
+      
+      
+        
+        已保洁区域
+        26 /50 
+        
+      
+    
+    
+      今日保洁计划名称
+      
+        00:00:00
+        23:59:00
+      
+    
+  
+
+
+
diff --git a/pages/index/list.vue b/pages/index/list.vue
new file mode 100644
index 0000000..32292c3
--- /dev/null
+++ b/pages/index/list.vue
@@ -0,0 +1,170 @@
+
+  
+    
+      
+        
+        
+      
+    
+
+    保洁区域
+
+    
+      
+        
+        
+          
+        
+
+        
+        
+          
+        
+
+        
+        
+          
+        
+      
+    
+
+    
+    保存
+  
+
+
+
+
+
diff --git a/pages/index/planList.vue b/pages/index/planList.vue
new file mode 100644
index 0000000..4c85a11
--- /dev/null
+++ b/pages/index/planList.vue
@@ -0,0 +1,90 @@
+
+  
+    
+       424242 
+    
+
+    
+      
+        已完成计划
+        12
+      
+      
+        未完成计划
+        5
+      
+    
+
+    
+      
+        
+          
+          05-21
+        
+        
+          校门A区教学楼
+          
+        
+        
+          北大门右侧操场跑道/南广场升旗台/A区第二食堂3楼
+        
+      
+    
+  
+
+
+
+
+
diff --git a/pages/my/about/feedback.vue b/pages/my/about/feedback.vue
new file mode 100644
index 0000000..900d697
--- /dev/null
+++ b/pages/my/about/feedback.vue
@@ -0,0 +1,73 @@
+
+	
+		
+			
+				
+			
+			
+			
+				
+			
+			
+			确定
+		
+	
+
+
+
+
+
diff --git a/pages/my/about/index.vue b/pages/my/about/index.vue
new file mode 100644
index 0000000..4ab3592
--- /dev/null
+++ b/pages/my/about/index.vue
@@ -0,0 +1,69 @@
+
+	
+		
+			
+		
+		
+		
+		
+		
+			
+			
+			
+			
+		
+		
+		
+			
+			
+		
+	
+
+
+
diff --git a/pages/my/account/email.vue b/pages/my/account/email.vue
new file mode 100644
index 0000000..46a2112
--- /dev/null
+++ b/pages/my/account/email.vue
@@ -0,0 +1,116 @@
+
+	
+		 
+			{{baseInfo.email}}
+			
+			
+				
+			
+			
+			
+			
+				
+				
+				{{tips}}
+			
+			确定
+		
+	
+	
+
+
+
+
\ No newline at end of file
diff --git a/pages/my/account/index.vue b/pages/my/account/index.vue
new file mode 100644
index 0000000..32a5112
--- /dev/null
+++ b/pages/my/account/index.vue
@@ -0,0 +1,89 @@
+
+	
+		
+				
+				
+		
+		
+		
+				
+		
+		
+		
+				
+		
+		
+		
+			  	退出登陆
+		
+		
+		
+		
+		
+	
+
+
+
diff --git a/pages/my/account/logout_account.vue b/pages/my/account/logout_account.vue
new file mode 100644
index 0000000..019b7d7
--- /dev/null
+++ b/pages/my/account/logout_account.vue
@@ -0,0 +1,82 @@
+
+	
+		
+				
+		
+	
+		
+		
+			
+			我同意<<注销协议>>,提交后帐号将不再恢复
+			
+			
+				注销帐号
+				
+			
+		
+		
+		
+	
+
+
+
diff --git a/pages/my/account/password.vue b/pages/my/account/password.vue
new file mode 100644
index 0000000..18e125d
--- /dev/null
+++ b/pages/my/account/password.vue
@@ -0,0 +1,73 @@
+
+	
+		
+			
+				
+			
+			
+			
+				
+			
+			确定
+		
+	
+	
+
+
+
+
\ No newline at end of file
diff --git a/pages/my/account/phone.vue b/pages/my/account/phone.vue
new file mode 100644
index 0000000..ca6e940
--- /dev/null
+++ b/pages/my/account/phone.vue
@@ -0,0 +1,120 @@
+
+	
+		
+			{{baseInfo.phone}}
+			
+			
+				
+			
+			
+			
+				
+				
+				{{tips}}
+			
+			确定
+		
+	
+	
+
+
+
+
\ No newline at end of file
diff --git a/pages/my/account/setting.vue b/pages/my/account/setting.vue
new file mode 100644
index 0000000..624c6bd
--- /dev/null
+++ b/pages/my/account/setting.vue
@@ -0,0 +1,38 @@
+
+	
+		
+			
+				
+					
+				
+				
+				
+		
+	
+
+
+
diff --git a/pages/my/auth.vue b/pages/my/auth.vue
new file mode 100644
index 0000000..bf21e37
--- /dev/null
+++ b/pages/my/auth.vue
@@ -0,0 +1,108 @@
+
+	
+		
+				
+					
+				
+				
+					
+				
+				
+					 
+				
+				
+				
+					提交
+				
+			
+	
+
+
+
+
+
+
diff --git a/pages/my/index.vue b/pages/my/index.vue
new file mode 100644
index 0000000..edc8e70
--- /dev/null
+++ b/pages/my/index.vue
@@ -0,0 +1,172 @@
+
+  
+	  
+		  
+		  
+			  {{baseInfo.name}}
+			  帐号:{{baseInfo.phone}}
+			  
+		  	
+		  
+			  
+			  
+		  
+	  
+	  
+	
+			
+			
+			
+			
+			
+	  		
+			
+	
+	
+	
+	
+	
+	
+		
+		
+  
+
+
+
+
+
diff --git a/pages/my/profile.vue b/pages/my/profile.vue
new file mode 100644
index 0000000..efa333c
--- /dev/null
+++ b/pages/my/profile.vue
@@ -0,0 +1,70 @@
+
+	
+		
+				
+				
+		
+		
+		
+				
+		
+		
+
+		
+				
+				
+				
+		
+	
+
+
+
diff --git a/pages/public/forget_password.vue b/pages/public/forget_password.vue
new file mode 100644
index 0000000..790063e
--- /dev/null
+++ b/pages/public/forget_password.vue
@@ -0,0 +1,130 @@
+
+	
+		
+			
+			
+			
+				
+			
+			
+			
+				
+				
+				{{tips}}
+			
+			
+			
+				
+			
+			
+			
+			确定
+		
+	
+	
+
+
+
+
\ No newline at end of file
diff --git a/pages/public/login.vue b/pages/public/login.vue
new file mode 100644
index 0000000..7837d74
--- /dev/null
+++ b/pages/public/login.vue
@@ -0,0 +1,120 @@
+
+	
+	
+		
+			
+		
+		
+			
+				
+				
+					
+				
+				
+					
+				
+			
+			登录
+			忘记密码
+			没有帐号?注册
+		
+
+	
+
+
+
+
\ No newline at end of file
diff --git a/pages/public/page.vue b/pages/public/page.vue
new file mode 100644
index 0000000..249e992
--- /dev/null
+++ b/pages/public/page.vue
@@ -0,0 +1,49 @@
+
+	
+		
+		
+	
+
+
+
diff --git a/pages/public/register.vue b/pages/public/register.vue
new file mode 100644
index 0000000..b818145
--- /dev/null
+++ b/pages/public/register.vue
@@ -0,0 +1,179 @@
+
+	
+		
+				
+				
+				
+				
+				
+				
+					
+					
+						我已知晓并同意 《用户服务协议》及《隐私政策》
+					
+				
+				
+				
+				
+					提交注册
+				
+			
+			
+			
+			
+			      
+			      
+			    
+				
+				
+	
+
+
+
+
+
+
diff --git a/pages/subPack/index/detail.vue b/pages/subPack/index/detail.vue
new file mode 100644
index 0000000..c2b5421
--- /dev/null
+++ b/pages/subPack/index/detail.vue
@@ -0,0 +1,136 @@
+
+	
+	    
+	      
+	      
+	        {{detail.title}}
+	      
+	     
+	    
+	      {{detail.source}}
+	      发表于
+	      {{detail.addtime}}
+	    
+	    
+			
+	
+			
+			
+	      
+	    
+	    
+	  
+
+ 
+
\ No newline at end of file
diff --git a/pages/tab_list.vue b/pages/tab_list.vue
new file mode 100644
index 0000000..3516ca9
--- /dev/null
+++ b/pages/tab_list.vue
@@ -0,0 +1,73 @@
+
+	
+		
+			
+				
+			
+		
+			
+			
+			
+				
+					
+						申请:{{item.master_id}}
+						时间:{{item.addtime}}
+						数量:{{item.total_nums}}
+					
+				
+			
+			
+		
+	
+
+
+
\ No newline at end of file
diff --git a/pages/templates.vue b/pages/templates.vue
new file mode 100644
index 0000000..0df9ba1
--- /dev/null
+++ b/pages/templates.vue
@@ -0,0 +1,31 @@
+
+	
+		
+				
+		
+	
+
+
+
\ No newline at end of file
diff --git a/pages/─ú░σ─┐┬╝.txt b/pages/─ú░σ─┐┬╝.txt
new file mode 100644
index 0000000..9dbcfbc
--- /dev/null
+++ b/pages/─ú░σ─┐┬╝.txt
@@ -0,0 +1 @@
+可把模板放在 \HBuilder X\templates\file\vue-page目录下面,这样可以在新建页面中,快速创建。
\ No newline at end of file
diff --git a/readme.md b/readme.md
new file mode 100644
index 0000000..94da6f9
--- /dev/null
+++ b/readme.md
@@ -0,0 +1,131 @@
+## 项目说明
+
+本项目可以快速搭建uni-app项目,封装request,集成z-paging(下拉刷新,上拉加载),带页面拦截器,请求锁,请求loading,集成uview,集成在线更新组件,集成本地调试工具vconsole、分包。
+
+## 接口开发
+
+接口服务器地址文件:**api/env.js**,修改服务器地址:
+
+```json
+let BASE_URL
+//开发环境中
+if (process.env.NODE_ENV === 'development') {
+  // 开发环境
+  BASE_URL = 'https://mock.apifox.com/m1/3553664-0-default'  //开发环境请求地址
+} else {
+  // 生产环境
+  BASE_URL = 'https://mock.apifox.com/m1/3553664-0-default'  //生成环境请求地址
+}
+
+export default BASE_URL
+```
+
+接口文件:**api/api.js**,在里面定义相关接口地址即可。
+
+```json
+//列表,GET方式请求
+export const getList = data => request.get('/api/list', data)   
+//登陆,POST方式请求
+export const login = data => request.post('/api/login', data)
+//检测版本升级,POST方式请求,第三个参数(false)不显示loading加载
+export const checkVersion = data => request.post('/api/checkVersion', data,false)
+```
+
+页面中调用的方法:
+
+GET或POST调用如下:(无须导入接口方法,已在全局文件main.js中引入)
+
+```json
+//请求参数
+const params = {
+    page: pageNo,
+    limit: pageSize
+}
+//getList即对应api.js中的接口
+this.$api.getList(params).then(res => {
+    //todo....
+})
+```
+
+## 页面拦截器
+
+本项目集成了页面拦截器,页面拦截器即表示在白名单的页面URL不拦截,其他页面则拦截。
+
+场景:办公OA APP,只有登陆页面不需要拦截,其他页面则需要拦截。
+
+拦截器与token搭配使用,若是本地无TOKE,APP启动时打开首页,则自动会跳转到登陆页。若本地存在TOKEN,则打开首页时不会再要求登陆。
+
+页面拦截器配置文件在**config/config.js**
+
+以OA为例,登陆页不需要拦截则设置如下,还可添加其他不需要拦截的页面。
+
+```json
+let config = {
+    //不拦截页面路径
+    whiteList: [
+        '/pages/public/login'
+    ],
+    token : 'token', //本地存储token的变量名
+    login_page : '/pages/public/login'  //拦截后跳转的登陆页路径
+}
+```
+
+ 注:封装请求文件(/utils/request.js)中,若服务器返回错误码大于400,则也跳转登陆页。
+
+```
+if(res.code > 400){
+    clearStorageSync('token')
+    useRouter(systemConfig.login_page, 'reLaunch')
+}else{
+    reslove(res)
+}
+```
+
+## 在线升级
+
+本项目集成了在线升级组件(仅支持APP),文件在:**components/appUpdate**,是否更新需要服务器返回如下JSON信息:
+
+```json
+{
+        "code": 0,
+        "platform": "android",
+        "version": "1.3.0",
+        "downUrl": "下载地址",
+        "updateContent": "修复BUG",
+        "force" : 0
+    }
+```
+
+> code为0时会提示更新,1则不弹出更新窗口。
+> 
+> 测试更新弹出窗口,可修改api.js中的检测更新接口地址为:/api/checkVersion2
+
+## 本地调试工具vconsole
+
+本项目集成了本地调试工具vconsole,主要用于在生成APP或小程序后方便调试检查错误。
+
+若不需要开启,可以修改配置文件config/config.js是否开启:
+
+`vconsole_status: 1,  //是否启用调试工具,1为启用,0不启用`
+
+## 分包
+
+ 增加分包功能,分包功能主要针对微信小程序,分包配置在pages.json中subPackages段内。如果不需要分包可以删除,并修改manifest.json 中"mp-weixin“段中 ` "subPackages" : true` 删除。
+
+## 集成UI
+
+本项目含集成了uview,z-paging,具体使用方法见官方文档。
+
+uview官方文档:[介绍 | uView - 多平台快速开发的UI框架 - uni-app UI框架](https://v1.uviewui.com/components/intro.html)
+
+z-paging官方文档:[介绍 | z-paging文档](https://z-paging.zxlee.cn/start/intro.html)(非常方便的实现上拉加载、下拉刷新等功能)
+
+## 其他说明
+
+**下载说明:建议单独下载文件后并解压,并在HB中打开目录进行演示,不要覆盖现在项目。**
+
+注:本项目中接口服务器和数据为mock数据,运行即可看到数据。
+
+登陆: 随机输入用户名和密码都可以登陆成功。
+
+如果在使用过程中遇到问题,可以在评论区反馈也可加微信liuyan814。
diff --git a/static/images/area-bg.png b/static/images/area-bg.png
new file mode 100644
index 0000000..d1d4119
Binary files /dev/null and b/static/images/area-bg.png differ
diff --git a/static/images/list.png b/static/images/list.png
new file mode 100644
index 0000000..953d783
Binary files /dev/null and b/static/images/list.png differ
diff --git a/static/images/list_cur.png b/static/images/list_cur.png
new file mode 100644
index 0000000..30b9857
Binary files /dev/null and b/static/images/list_cur.png differ
diff --git a/static/images/login_bg.png b/static/images/login_bg.png
new file mode 100644
index 0000000..4297c19
Binary files /dev/null and b/static/images/login_bg.png differ
diff --git a/static/images/logo.png b/static/images/logo.png
new file mode 100644
index 0000000..60091c2
Binary files /dev/null and b/static/images/logo.png differ
diff --git a/static/images/plan-bg.png b/static/images/plan-bg.png
new file mode 100644
index 0000000..a574622
Binary files /dev/null and b/static/images/plan-bg.png differ
diff --git a/static/images/plan-icon-bg.png b/static/images/plan-icon-bg.png
new file mode 100644
index 0000000..cf583e3
Binary files /dev/null and b/static/images/plan-icon-bg.png differ
diff --git a/static/images/pos-icon.png b/static/images/pos-icon.png
new file mode 100644
index 0000000..9db86a4
Binary files /dev/null and b/static/images/pos-icon.png differ
diff --git a/static/images/update.png b/static/images/update.png
new file mode 100644
index 0000000..33d6c48
Binary files /dev/null and b/static/images/update.png differ
diff --git a/static/logo.png b/static/logo.png
new file mode 100644
index 0000000..b2dade8
Binary files /dev/null and b/static/logo.png differ
diff --git a/static/tab/home.png b/static/tab/home.png
new file mode 100644
index 0000000..3aefa52
Binary files /dev/null and b/static/tab/home.png differ
diff --git a/static/tab/home_cur.png b/static/tab/home_cur.png
new file mode 100644
index 0000000..e7fe9e6
Binary files /dev/null and b/static/tab/home_cur.png differ
diff --git a/static/tab/list.png b/static/tab/list.png
new file mode 100644
index 0000000..975a5a0
Binary files /dev/null and b/static/tab/list.png differ
diff --git a/static/tab/list_cur.png b/static/tab/list_cur.png
new file mode 100644
index 0000000..77a0cd9
Binary files /dev/null and b/static/tab/list_cur.png differ
diff --git a/static/tab/my.png b/static/tab/my.png
new file mode 100644
index 0000000..cba9f6a
Binary files /dev/null and b/static/tab/my.png differ
diff --git a/static/tab/my_cur.png b/static/tab/my_cur.png
new file mode 100644
index 0000000..67ccfd5
Binary files /dev/null and b/static/tab/my_cur.png differ
diff --git a/store/$u.mixin.js b/store/$u.mixin.js
new file mode 100644
index 0000000..94ed2ee
--- /dev/null
+++ b/store/$u.mixin.js
@@ -0,0 +1,27 @@
+import { mapState } from 'vuex'
+import store from "@/store"
+
+// 尝试将用户在根目录中的store/index.js的vuex的state变量,全部加载到全局变量中
+let $uStoreKey = [];
+try{
+	$uStoreKey = store.state ? Object.keys(store.state) : [];
+}catch(e){
+	
+}
+
+module.exports = {
+	created() {
+		// 将vuex方法挂在到$u中
+		// 使用方法为:如果要修改vuex的state中的user.name变量为"史诗" => this.$u.vuex('user.name', '史诗')
+		// 如果要修改vuex的state的version变量为1.0.1 => this.$u.vuex('version', '1.0.1')
+		this.$u.vuex = (name, value) => {
+			this.$store.commit('$uStore', {
+				name,value
+			})
+		}
+	},
+	computed: {
+		// 将vuex的state中的所有变量,解构到全局混入的mixin中
+		...mapState($uStoreKey)
+	}
+}
\ No newline at end of file
diff --git a/store/index.js b/store/index.js
new file mode 100644
index 0000000..33ce954
--- /dev/null
+++ b/store/index.js
@@ -0,0 +1,64 @@
+import Vue from 'vue'
+import Vuex from 'vuex'
+Vue.use(Vuex)
+
+let lifeData = {};
+
+try{
+	// 尝试获取本地是否存在lifeData变量,第一次启动APP时是不存在的
+	lifeData = uni.getStorageSync('lifeData');
+}catch(e){
+	
+}
+
+// 需要永久存储,且下次APP启动需要取出的,在state中的变量名
+let saveStateKeys = ['vuex_user', 'vuex_token'];
+
+// 保存变量到本地存储中
+const saveLifeData = function(key, value){
+	// 判断变量名是否在需要存储的数组中
+	if(saveStateKeys.indexOf(key) != -1) {
+		// 获取本地存储的lifeData对象,将变量添加到对象中
+		let tmp = uni.getStorageSync('lifeData');
+		// 第一次打开APP,不存在lifeData变量,故放一个{}空对象
+		tmp = tmp ? tmp : {};
+		tmp[key] = value;
+		// 执行这一步后,所有需要存储的变量,都挂载在本地的lifeData对象中
+		uni.setStorageSync('lifeData', tmp);
+	}
+}
+const store = new Vuex.Store({
+	// 下面这些值仅为示例,使用过程中请删除
+	state: {
+		// 如果上面从本地获取的lifeData对象下有对应的属性,就赋值给state中对应的变量
+		// 加上vuex_前缀,是防止变量名冲突,也让人一目了然
+		vuex_user: lifeData.vuex_user ? lifeData.vuex_user : {name: '明月'},
+		vuex_token: lifeData.vuex_token ? lifeData.vuex_token : '',
+		// 如果vuex_version无需保存到本地永久存储,无需lifeData.vuex_version方式
+		vuex_version: '1.0.1',
+	},
+	mutations: {
+		$uStore(state, payload) {
+			// 判断是否多层级调用,state中为对象存在的情况,诸如user.info.score = 1
+			let nameArr = payload.name.split('.');
+			let saveKey = '';
+			let len = nameArr.length;
+			if(nameArr.length >= 2) {
+				let obj = state[nameArr[0]];
+				for(let i = 1; i < len - 1; i ++) {
+					obj = obj[nameArr[i]];
+				}
+				obj[nameArr[len - 1]] = payload.value;
+				saveKey = nameArr[0];
+			} else {
+				// 单层级变量,在state就是一个普通变量的情况
+				state[payload.name] = payload.value;
+				saveKey = payload.name;
+			}
+			// 保存变量到本地,见顶部函数定义
+			saveLifeData(saveKey, state[saveKey])
+		}
+	}
+})
+
+export default store
\ No newline at end of file
diff --git a/uni.scss b/uni.scss
new file mode 100644
index 0000000..6fe4b58
--- /dev/null
+++ b/uni.scss
@@ -0,0 +1,76 @@
+/**
+ * 这里是uni-app内置的常用样式变量
+ *
+ * uni-app 官方扩展插件及插件市场(https://ext.dcloud.net.cn)上很多三方插件均使用了这些样式变量
+ * 如果你是插件开发者,建议你使用scss预处理,并在插件代码中直接使用这些变量(无需 import 这个文件),方便用户通过搭积木的方式开发整体风格一致的App
+ *
+ */
+
+/**
+ * 如果你是App开发者(插件使用者),你可以通过修改这些变量来定制自己的插件主题,实现自定义主题功能
+ *
+ * 如果你的项目同样使用了scss预处理,你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件
+ */
+
+/* 颜色变量 */
+@import '@/uni_modules/uview-ui/theme.scss';
+/* 行为相关颜色 */
+$uni-color-primary: #007aff;
+$uni-color-success: #4cd964;
+$uni-color-warning: #f0ad4e;
+$uni-color-error: #dd524d;
+
+/* 文字基本颜色 */
+$uni-text-color:#333;//基本色
+$uni-text-color-inverse:#fff;//反色
+$uni-text-color-grey:#999;//辅助灰色,如加载更多的提示信息
+$uni-text-color-placeholder: #808080;
+$uni-text-color-disable:#c0c0c0;
+
+/* 背景颜色 */
+$uni-bg-color:#ffffff;
+$uni-bg-color-grey:#f8f8f8;
+$uni-bg-color-hover:#f1f1f1;//点击状态颜色
+$uni-bg-color-mask:rgba(0, 0, 0, 0.4);//遮罩颜色
+
+/* 边框颜色 */
+$uni-border-color:#c8c7cc;
+
+/* 尺寸变量 */
+
+/* 文字尺寸 */
+$uni-font-size-sm:12px;
+$uni-font-size-base:14px;
+$uni-font-size-lg:16;
+
+/* 图片尺寸 */
+$uni-img-size-sm:20px;
+$uni-img-size-base:26px;
+$uni-img-size-lg:40px;
+
+/* Border Radius */
+$uni-border-radius-sm: 2px;
+$uni-border-radius-base: 3px;
+$uni-border-radius-lg: 6px;
+$uni-border-radius-circle: 50%;
+
+/* 水平间距 */
+$uni-spacing-row-sm: 5px;
+$uni-spacing-row-base: 10px;
+$uni-spacing-row-lg: 15px;
+
+/* 垂直间距 */
+$uni-spacing-col-sm: 4px;
+$uni-spacing-col-base: 8px;
+$uni-spacing-col-lg: 12px;
+
+/* 透明度 */
+$uni-opacity-disabled: 0.3; // 组件禁用态的透明度
+
+/* 文章场景相关 */
+$uni-color-title: #2C405A; // 文章标题颜色
+$uni-font-size-title:20px;
+$uni-color-subtitle: #555555; // 二级标题颜色
+$uni-font-size-subtitle:26px;
+$uni-color-paragraph: #3F536E; // 文章段落颜色
+$uni-font-size-paragraph:15px;
diff --git a/utils/common.js b/utils/common.js
new file mode 100644
index 0000000..4d901c1
--- /dev/null
+++ b/utils/common.js
@@ -0,0 +1,88 @@
+//获取当前时间,格式YYYY-MM-DD HH:MM:SS
+const GetNowTime = time => {
+  var date = time,
+    year = date.getFullYear(),
+    month = date.getMonth() + 1,
+    day = date.getDate(),
+    hour = date.getHours() < 10 ? "0" + date.getHours() : date.getHours(),
+    minute = date.getMinutes() < 10 ? "0" + date.getMinutes() : date.getMinutes(),
+    second = date.getSeconds() < 10 ? "0" + date.getSeconds() : date.getSeconds();
+  month >= 1 && month <= 9 ? (month = "0" + month) : "";
+  day >= 0 && day <= 9 ? (day = "0" + day) : "";
+  // var timer = year + '-' + month + '-' + day + ' ' + hour + ':' + minute + ':' + second;
+  var timer = year + '-' + month + '-' + day;
+  return timer;
+}
+
+// 格式化电话号码
+const GetPhone = phone => {
+  let tel = phone.slice(0, 3) + '****' + phone.slice(7, 11);
+  return tel;
+}
+//返回日期和周几数组
+function weekDate() {
+  const myDate = new Date();
+  const padZero = num => String(num).padStart(2, '0'); // 补零工具函数
+
+  const dayList = [];
+
+  // 生成当天数据(补零)
+  dayList.push({
+    day: padZero(myDate.getDate()),
+    month: padZero(myDate.getMonth() + 1),
+    week: toWeekDay(myDate.getDay()),
+    year: myDate.getFullYear()
+  });
+
+  // 生成后续10天数据
+  for (let i = 0; i < 10; i++) {
+    myDate.setDate(myDate.getDate() + 1);
+    dayList.push({
+      day: padZero(myDate.getDate()),
+      month: padZero(myDate.getMonth() + 1),
+      week: toWeekDay(myDate.getDay()),
+      year: myDate.getFullYear()
+    });
+  }
+
+  // 返回标准化日期格式
+  return {
+    dayList,
+    StartDate: `${dayList[0].year}-${dayList[0].month}-${dayList[0].day}`,
+    EndDate: `${dayList[dayList.length - 1].year}-${dayList[dayList.length - 1].month}-${dayList[dayList.length - 1].day}`
+  };
+}
+
+function toWeekDay(weekDay) { // 传入数据 讲一周的某一天返回成中文状态下的字符
+  switch (weekDay) {
+    case 1:
+      return '一';
+      break;
+    case 2:
+      return '二';
+      break;
+    case 3:
+      return '三';
+      break;
+    case 4:
+      return '四';
+      break;
+    case 5:
+      return '五';
+      break;
+    case 6:
+      return '六';
+      break;
+    case 0:
+      return '日';
+      break;
+    default:
+      break;
+  }
+  return '传入未知参数';
+}
+module.exports = {
+  GetNowTime,
+  GetPhone,
+  weekDate
+}
\ No newline at end of file
diff --git a/utils/interceptor.js b/utils/interceptor.js
new file mode 100644
index 0000000..0e6ce41
--- /dev/null
+++ b/utils/interceptor.js
@@ -0,0 +1,50 @@
+
+import systemConfig from '@/config/config.js';
+// 页面白名单,不受拦截
+const whiteList = systemConfig.whiteList 
+function hasPermission (url) {
+	let islogin = uni.getStorageSync(systemConfig.token );//isLogin是登录成功后在本地存储登录标识,存储一个能够判断用户登录的唯一标识就行
+    // 在白名单中或有登录判断条件可以直接跳转
+    if(whiteList.indexOf(url) !== -1 || islogin) {
+		//console.log('通过')
+        return true 
+    } 
+	//console.log('失败')
+    return false
+}
+uni.addInterceptor('navigateTo', {
+    // 页面跳转前进行拦截, invoke根据返回值进行判断是否继续执行跳转
+    invoke (e) {
+		const url = e.url.split('?')[0]
+        if(!hasPermission(url)){
+            uni.reLaunch({
+                url:systemConfig.login_page 
+            })
+            return false
+        }
+        return true
+    },
+    success (e) {
+		
+    }
+})
+ 
+uni.addInterceptor('switchTab', {
+    // tabbar页面跳转前进行拦截
+    invoke (e) {
+		
+		const url = e.url.split('?')[0]
+		if(!hasPermission(url)){
+            uni.reLaunch({
+                url: systemConfig.login_page 
+            })
+			//console.log('不在白名单内')
+            return false
+        }
+		//console.log('在白名单内')
+        return true
+    },
+    success (e) {
+		
+    }
+})
\ No newline at end of file
diff --git a/utils/request.js b/utils/request.js
new file mode 100644
index 0000000..4851b88
--- /dev/null
+++ b/utils/request.js
@@ -0,0 +1,62 @@
+
+
+import BASE_URL from '@/api/env.js' //引入接口共用地址
+import RequestManager from '@/utils/requestManager.js'
+import {toast, clearStorageSync, getStorageSync, useRouter} from '@/utils/utils.js'
+import systemConfig from '@/config/config.js';
+const manager = new RequestManager()
+
+const baseRequest = async (url, method, data = {}, loading = true) =>{
+	let requestId = manager.generateId(method, url, data)
+	if(!requestId) {
+		console.log('重复请求')
+	}
+	if(!requestId)return false;
+	
+	const header = {}
+	header.Authorization = getStorageSync(systemConfig.token) || ''
+	return new Promise((reslove, reject) => {
+		loading && uni.showLoading({title: 'loading'})
+		uni.request({
+			url: BASE_URL + url,
+			method: method || 'GET',
+			header: header,
+			timeout: 10000,
+			data: data || {},
+			complete: ()=>{
+				uni.hideLoading()
+				manager.deleteById(requestId)
+			},
+			success: (successData) => {
+				//console.log(successData)
+				const res = successData.data
+				if(successData.statusCode == 200){
+					// 业务逻辑,自行修改,401是服务器上返回该token过期,过期后跳转到登陆页面
+					if(res.code > 400){
+						clearStorageSync('token')
+						useRouter(systemConfig.login_page, 'reLaunch')
+					}else{
+						reslove(res)
+					}
+				}else{
+					console.log('网络连接失败,请稍后重试' ,url)
+					toast('网络连接失败,请稍后重试')
+					reject(res)
+				}
+			},
+			fail: (msg) => {
+				console.log("请求:"+BASE_URL + url +',发生错误:', err)
+				toast('网络连接失败,请稍后重试')
+				reject(msg)
+			}
+		})
+	})
+}
+
+const request = {};
+
+['options', 'get', 'post', 'put', 'head', 'delete', 'trace', 'connect'].forEach((method) => {
+	request[method] = (api, data, loading) => baseRequest(api, method, data, loading)
+})
+
+export default request
\ No newline at end of file
diff --git a/utils/requestManager.js b/utils/requestManager.js
new file mode 100644
index 0000000..56dff20
--- /dev/null
+++ b/utils/requestManager.js
@@ -0,0 +1,66 @@
+class RequestManager {
+    constructor() {
+        this.idMap = new Map()
+    }
+    /**
+     * 生成唯一ID,并将ID和请求信息存储到map对象中
+     * @param {string} method - 请求方法
+     * @param {string} url - 请求URL
+     * @param {object} params - 请求参数
+     * @returns {string|boolean} - 生成的唯一ID,如果存在相同请求则返回false
+     */
+    generateId(method, url, params) {
+        const id = this.generateUniqueId(method, url, params)
+        if (this.idMap.has(id)) {
+            return false
+        }
+        this.idMap.set(id, { method, url, params })
+        return id
+    }
+
+    /**
+     * 根据ID删除map对象中的请求信息
+     * @param {string} id - 要删除的唯一ID
+     */
+    deleteById(id) {
+        this.idMap.delete(id)
+    }
+
+    /**
+     * 生成唯一ID的方法
+     * @param {string} method - 请求方法
+     * @param {string} url - 请求URL
+     * @param {object} params - 请求参数
+     * @returns {string} - 生成的唯一ID
+     */
+    generateUniqueId(method, url, params) {
+        const idString = `${method}-${url}-${this.serializeObject(params)}`
+        let id = 0;
+        for (let i = 0; i < idString.length; i++) {
+            id = ((id << 5) - id) + idString.charCodeAt(i)
+            id |= 0;
+        }
+        return id.toString()
+    }
+
+    /**
+     * 序列化对象为字符串
+     * @param {object} obj - 要序列化的对象
+     * @returns {string} - 序列化后的字符串
+     */
+    serializeObject(obj) {
+        const keys = Object.keys(obj).sort()
+        const serializedObj = {}
+        for (let key of keys) {
+            const value = obj[key]
+            if (value !== null && typeof value === 'object') {
+                serializedObj[key] = this.serializeObject(value)
+            } else {
+                serializedObj[key] = value
+            }
+        }
+        return JSON.stringify(serializedObj)
+    }
+}
+
+export default RequestManager
\ No newline at end of file
diff --git a/utils/utils.js b/utils/utils.js
new file mode 100644
index 0000000..0ff3976
--- /dev/null
+++ b/utils/utils.js
@@ -0,0 +1,475 @@
+/**
+ * 提示方法
+ * @param {String} title 提示文字
+ * @param {String}  icon icon图片
+ * @param {Number}  duration 提示时间
+ */
+export function toast(title, icon = 'none', duration = 1500) {
+	if(title) {
+		uni.showToast({
+		    title,
+		    icon,
+		    duration
+		})
+	}
+}
+
+/**
+ * @param {String} url
+ * @return {function}
+ * @description navigateTo跳转
+ */
+export function Jump(url) {
+	uni.navigateTo({
+		url: url
+	})
+}
+
+
+
+/**
+ * 提示信息
+ * **/
+export function showModal(title, msg, showCancel) {
+	uni.showModal({
+		title: title,
+		content: msg,
+		showCancel: showCancel,
+		success: function(res) {
+
+		}
+	})
+}
+
+
+export function showLoading(content) {
+	uni.showLoading({
+		title: content
+	})
+}
+/**
+ * 隐藏loading
+ * **/
+export function hideLoading() {
+	uni.hideLoading()
+}
+
+/***
+ * 获取时间戳
+ */
+export function getTimStamp() {
+	var timestamp = Date.parse(new Date());
+	timestamp = timestamp / 1000;
+	return timestamp;
+}
+/***
+ * 生成随机数
+ */
+export function getNonce() {
+	var t = '';
+	for (var i = 0; i < 12; i++) {
+		t += Math.floor(Math.random() * 10);
+	}
+	return t;
+}
+/**
+ * 获取32位随机数
+ * ***/
+export function getnoncestr() {
+	let len = len || 32;
+	var $chars = 'abcdefghijklmnopqrstuvwxyz0123456789';
+	var maxPos = $chars.length;
+	var pwd = '';
+	for (var i = 0; i < len; i++) {
+		pwd += $chars.charAt(Math.floor(Math.random() * maxPos));
+	}
+	return pwd;
+}
+
+/**
+ * 解析url中的参数
+ */
+export function UrlParamHash(url) {
+	var params = {},
+		h;
+	var hash = url.slice(url.indexOf("?") + 1).split("&");
+	for (var i = 0; i < hash.length; i++) {
+		h = hash[i].split("=");
+		if (h.length > 1) {
+			params[h[0]] = h[1];
+		} else {
+			params[h[0]] = "";
+		}
+	}
+	return params;
+}
+
+
+/**
+ * 一键复制 uni.setClipboardData
+ * 用法:
+ *    1. import {setClipboardData} from '该文件的地址'
+ *    2. 利用async await
+ *    3. await setClipboardData(需要复制的文本)
+ */
+const setClipboardData = (text) =>{
+	return new Promise((resolve,reject)=>{
+		uni.setClipboardData({
+			data: text,
+			success: (res) => {
+				resolve(res)
+			},
+			fail: (err) => {
+				reject(err)
+			}
+		})
+	})
+}
+
+/**
+ * 获取系统剪贴板内容 uni.getClipboardData
+ * 用法:
+ *    1. import {getClipboardData} from '该文件的地址'
+ *    2. 利用async await来接收获取到的数据
+ *    3. await getClipboardData()
+ */
+const getClipboardData = () =>{
+	return new Promise((resolve,reject)=>{
+		uni.getClipboardData({
+			success: (res) => {
+				resolve(res)
+			},
+			fail: (err) => {
+				reject(err)
+			}
+		})
+	})
+}
+
+/**
+ * 拨打电话 uni.makePhoneCall()
+ * 用法:
+ *    1. import {getBatteryInfo} from '该文件的地址'
+ *    2. 直接makePhoneCall(拨打的电话号码)
+ */
+const makePhoneCall = (phone) =>{
+	uni.makePhoneCall({
+		phoneNumber:phone
+	})
+}
+
+
+/**
+ * 设置缓存
+ * @param {String} key 键名
+ * @param {String} data 值
+ */
+export function setStorageSync(key, data) {
+    uni.setStorageSync(key, data)
+}
+
+/**
+ * 获取缓存
+ * @param {String} key 键名
+ */
+export function getStorageSync(key) {
+    return uni.getStorageSync(key)
+}
+
+/**
+ * 删除缓存
+ * @param {String} key 键名
+ */
+export function removeStorageSync(key) {
+    return uni.removeStorageSync(key)
+}
+
+/**
+ * 清空缓存
+ * @param {String} key 键名
+ */
+export function clearStorageSync() {
+    return uni.clearStorageSync()
+}
+
+
+/**
+ * 页面跳转
+ * @param {'navigateTo' | 'redirectTo' | 'reLaunch' | 'switchTab' | 'navigateBack' | number } url  转跳路径
+ * @param {String} params 跳转时携带的参数
+ * @param {String} type 转跳方式
+ **/
+export function useRouter(url, params = {}, type = 'navigateTo') {
+    try {
+        if (Object.keys(params).length) url = `${url}?data=${encodeURIComponent(JSON.stringify(params))}`
+        if (type === 'navigateBack') {
+            uni[type]({ delta: url })
+        } else {
+            uni[type]({ url })
+        }
+    } catch (error) {
+        console.error(error)
+    }
+}
+
+/**
+ * 预览图片
+ * @param {Array} urls 图片链接
+ */
+export function previewImage(urls, itemList = ['发送给朋友', '保存图片', '收藏']) {
+    uni.previewImage({
+        urls,
+        longPressActions: {
+            itemList,
+            fail: function (error) {
+                console.error(error,'===previewImage')
+            }
+        }
+    })
+}
+
+/**
+ * 保存图片到本地
+ * @param {String} filePath 图片临时路径
+ **/
+export function saveImage(filePath) {
+    if (!filePath) return false
+    uni.saveImageToPhotosAlbum({
+        filePath,
+        success: (res) => {
+            toast('图片保存成功', 'success')
+        },
+        fail: (err) => {
+            if (err.errMsg === 'saveImageToPhotosAlbum:fail:auth denied' || err.errMsg === 'saveImageToPhotosAlbum:fail auth deny') {
+                uni.showModal({
+                    title: '提示',
+                    content: '需要您授权保存相册',
+                    showCancel: false,
+                    success: (modalSuccess) => {
+                        uni.openSetting({
+                            success(settingdata) {
+                                if (settingdata.authSetting['scope.writePhotosAlbum']) {
+                                    uni.showModal({
+                                        title: '提示',
+                                        content: '获取权限成功,再次点击图片即可保存',
+                                        showCancel: false
+                                    })
+                                } else {
+                                    uni.showModal({
+                                        title: '提示',
+                                        content: '获取权限失败,将无法保存到相册哦~',
+                                        showCancel: false
+                                    })
+                                }
+                            },
+                            fail(failData) {
+                                console.log('failData', failData)
+                            }
+                        })
+                    }
+                })
+            }
+        }
+    })
+}
+
+/**
+ * 深拷贝
+ * @param {Object} data
+ **/
+export const clone = (data) => JSON.parse(JSON.stringify(data))
+ /**
+ * 获取平台名称
+ * @return {string} 平台名称
+ */
+export function getPlatform() {
+	let platform;
+	switch (process.env.VUE_APP_PLATFORM) {
+		case 'app':
+		case 'app-plus':
+			let n = uni.getSystemInfoSync().platform.toLowerCase();
+			if (n === 'ios') {
+				platform = 'ios';
+			} else if (n === 'android') {
+				platform = 'android';
+			} else {
+				platform = 'app';
+			}
+			break;
+		case 'mp-weixin':
+			platform = 'wx';
+			break;
+		case 'mp-alipay':
+			platform = 'alipay';
+			break;
+		case 'mp-baidu':
+			platform = 'baidu';
+			break;
+		case 'mp-qq':
+			platform = 'qq';
+			break;
+		case 'mp-toutiao':
+			platform = 'toutiao';
+			break;
+		case 'quickapp-webview':
+			platform = 'kuai';
+			break;
+	}
+
+	return platform;
+}
+
+/**
+ * 数组去重
+ * @param {Array} array 数值
+ * @retrun {Array} 数值
+ */
+export function   arrayShuffle(array) {
+	let i = array.length, t, j;
+	while (i) {
+		j = Math.floor(Math.random() * i--);
+		t = array[i];
+		array[i] = array[j];
+		array[j] = t;
+	}
+	return array;
+}
+
+/**
+ * 日期格式化
+ * @param {Date} date 日期
+ * @param {string} format 返回的日期格式
+ * @retrun {string} 日期
+ */
+export function dateFormat(date, format = 'YYYY-MM-DD HH:mm:ss') {
+	const config = {
+		YYYY: date.getFullYear(),
+		MM: date.getMonth()+1,
+		DD: date.getDate(),
+		HH: date.getHours(),
+		mm: date.getMinutes(),
+		ss: date.getSeconds(),
+	}
+	for(const key in config){
+		let value = config[key];
+		if (value < 10) {
+			value = '0' + value;
+		}
+		format = format.replace(key, value)
+	}
+	return format
+}
+
+/**
+ * base64转文件
+ * @param {string} base64data base64
+ * @param {Function} cb 回调
+ */
+export function base64ToSrc(base64data, cb) {
+	const FILE_BASE_NAME = 'tmp_base64src';
+	const [, format, bodyData] = /data:image\/(\w+);base64,(.*)/.exec(base64data) || [];
+	if (!format) {
+		return (new Error('格式错误'));
+	}
+
+	// #ifdef MP-WEIXIN
+	let filePath = `${wx.env.USER_DATA_PATH}/${FILE_BASE_NAME}.${format}`;
+	// #endif
+	// #ifdef MP-QQ
+	let filePath = `${qq.env.USER_DATA_PATH}/${FILE_BASE_NAME}.${format}`;
+	// #endif
+
+	const buffer = uni.base64ToArrayBuffer(bodyData);
+	uni.getFileSystemManager().writeFile({
+		filePath,
+		data: buffer,
+		encoding: 'binary',
+		success() {
+			cb && cb(filePath);
+		}
+	});
+}
+
+/**
+ * base64解码
+ * @param {string} str str
+ * @param {string}
+ */
+export function encodeBase64(str) {
+	return new Buffer.from(str).toString('base64');
+}
+
+/**
+ * base64解码
+ * @param {string} str str
+ * @param {string}
+ */
+export function decodeBase64(str) {
+	const commonContent = str.replace(/\s/g, '+');
+	return new Buffer.from(commonContent, 'base64').toString();
+}
+
+/**
+ * 播放声音
+ * @param {string} src 声音文件地址
+ * @param {Boolean} loop 是否循环
+ */
+export function playSound(src, loop = false) {
+	const innerAudioContext = uni.createInnerAudioContext();
+	innerAudioContext.autoplay = true;
+	innerAudioContext.loop = loop;
+	innerAudioContext.src = src;
+	innerAudioContext.onPlay(() => {});
+	innerAudioContext.onError((res) => {});
+}
+
+/**
+ * 生成订单ID
+ * @param {string} prefix 订单前缀
+ * @param {string} 订单ID
+ */
+export function createOrderSn(prefix = '') {
+	return `${prefix}${this.randomString(10).toUpperCase()}${+new Date()}`;
+}
+
+/**
+ * 图片转base64
+ * @param {string} src 图片地址
+ * @return {Promise} base64
+ */
+export function imageToBase64(src) {
+	return new Promise((resolve, reject) => {
+		uni.getImageInfo({
+			src,
+			success: image => {
+				console.log(image);
+				uni.getFileSystemManager().readFile({
+					filePath: image.path,
+					encoding: 'base64',
+					success: e => {
+						return resolve(`data:image/jpeg;base64,${e.data}`);
+					},
+					fail: e => {
+						return reject(null);
+					}
+				})
+			}
+		});
+	})
+}
+
+
+/**
+ * 随机范围内的数字
+ * @param {number} start 起始数字
+ * @param {number} end 起始数字
+ * @return {number || null} 随机数
+ */
+export function  randomByRange(start, end){
+	if (typeof start === 'number' && typeof end === 'number') {
+		return start + Math.floor(Math.random() * (end - start));
+	} else {
+		console.error('参数必须为数字');
+		return null;
+	}
+}
\ No newline at end of file