diff --git a/App.vue b/App.vue
index c9b84c184c3c0609be071164c9f9b1251307a22a..91621c78a56c768693fe4ba461f1b856d71a7a83 100644
--- a/App.vue
+++ b/App.vue
@@ -1,16 +1,9 @@
 <script>
 import { mapActions } from 'vuex'
 export default {
-	onLaunch: function() {
-		console.log('App Launch')
+	onLaunch: function() {
 		this.checkUpdate()
 		this.setSystemInfo()
-	},
-	onShow: function() {
-		console.log('App Show')
-	},
-	onHide: function() {
-		console.log('App Hide')
 	},
 	
 	methods: {
@@ -40,3 +33,15 @@ export default {
 	
 }
 </script>
+
+<style>
+@import url("@/styles/layout.css");
+
+/* 隐藏scrollbar 滚动条 */
+::-webkit-scrollbar {
+  display:none;
+  width:0;
+  height:0;
+  color:transparent;
+}
+</style>
diff --git a/apis/address.js b/apis/address.js
new file mode 100644
index 0000000000000000000000000000000000000000..993d633443c6387d0ae6c91430b4755397674b94
--- /dev/null
+++ b/apis/address.js
@@ -0,0 +1,48 @@
+// 地址相关
+import { request } from "@/lib/service"
+import { baseUrl } from '@/config'
+
+/**
+ * @desc 获取地址
+ */
+export function addressList() {
+	return request({
+		url: `${baseUrl}/a`
+	})
+}
+
+/**
+ * @desc 地址详情
+ */
+export function addressList() {
+	return request({
+		url: `${baseUrl}/a`
+	})
+}
+
+/**
+ * @desc 编辑地址
+ */
+export function editAddress() {
+	return request({
+		url: `${baseUrl}/a`
+	})
+}
+
+/**
+ * @desc 删除地址
+ */
+export function delAddress() {
+	return request({
+		url: `${baseUrl}/a`
+	})
+}
+
+/**
+ * @desc 添加地址
+ */
+export function addAddress() {
+	return request({
+		url: `${baseUrl}/a`
+	})
+}
\ No newline at end of file
diff --git a/apis/carts.js b/apis/carts.js
new file mode 100644
index 0000000000000000000000000000000000000000..6c74f70ffe4100ab8e890e91fc6230d4a3a7a2d7
--- /dev/null
+++ b/apis/carts.js
@@ -0,0 +1,31 @@
+// 购物车相关
+import { request } from "@/lib/service"
+import { baseUrl } from '@/config'
+
+/**
+ * @desc 获取购物车列表
+ */
+export function cartsList() {
+	return request({
+		url: `${baseUrl}/a`
+	})
+}
+
+/**
+ * @desc 编辑购物车商品
+ */
+export function editCart() {
+	return request({
+		url: `${baseUrl}/a`
+	})
+}
+
+
+/**
+ * @desc 删除购物车商品
+ */
+export function delCart() {
+	return request({
+		url: `${baseUrl}/a`
+	})
+}
diff --git a/apis/goods.js b/apis/goods.js
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/apis/order.js b/apis/order.js
new file mode 100644
index 0000000000000000000000000000000000000000..46bd8de2f3cc9969a9ef5057ba2e4cd2e1909b2b
--- /dev/null
+++ b/apis/order.js
@@ -0,0 +1,31 @@
+// 订单相关
+import { request } from "@/lib/service"
+import { baseUrl } from '@/config'
+
+/**
+ * @desc 获取订单列表
+ */
+export function orderList() {
+	return request({
+		url: `${baseUrl}/a`
+	})
+}
+
+/**
+ * @desc 订单详情
+ */
+export function orderDetail() {
+	return request({
+		url: `${baseUrl}/a`
+	})
+}
+
+
+/**
+ * @desc 删除订单
+ */
+export function delOrder() {
+	return request({
+		url: `${baseUrl}/a`
+	})
+}
diff --git a/apis/user.js b/apis/user.js
new file mode 100644
index 0000000000000000000000000000000000000000..04f96b3fac8762a0de0da48eec4f9d2197d2a0aa
--- /dev/null
+++ b/apis/user.js
@@ -0,0 +1,30 @@
+// 用户相关
+import { request } from "@/lib/service"
+import { baseUrl } from '@/config' // 将请求的baseUrl写这里,为了开发时调试请求地址
+
+/**
+ * @desc 登录
+ */
+export function login() {
+	return request({
+		url: `${baseUrl}/a`
+	})
+}
+
+/**
+ * @desc 注册
+ */
+export function register() {
+	return request({
+		url:`${baseUrl}/a`
+	})
+}
+
+/**
+ * @desc 获取手机验证码
+ */
+export function smsCode() {
+	return request({
+		url:`${baseUrl}/a`
+	})
+}
\ No newline at end of file
diff --git a/components/uni-popup/index.vue b/components/uni-popup/index.vue
new file mode 100644
index 0000000000000000000000000000000000000000..1418ed1d9a9a7d33c32fe51a86489bfe17cc6bc8
--- /dev/null
+++ b/components/uni-popup/index.vue
@@ -0,0 +1,266 @@
+<template>
+	<view v-if="showPopup" class="uni-popup" @touchmove.stop.prevent="clear">
+		<uni-transition :mode-class="['fade']" :styles="maskClass" :duration="duration" :show="showTrans" @click="onTap" />
+		<uni-transition :mode-class="ani" :styles="transClass" :duration="duration" :show="showTrans" @click="onTap">
+			<view class="uni-popup__wrapper-box" @click.stop="clear">
+				<slot />
+			</view>
+		</uni-transition>
+	</view>
+</template>
+
+<script>
+	import uniTransition from '../uni-transition/index.vue'
+
+	/**
+	 * PopUp 弹出层
+	 * @description 弹出层组件,为了解决遮罩弹层的问题
+	 * @tutorial https://ext.dcloud.net.cn/plugin?id=329
+	 * @property {String} type = [top|center|bottom] 弹出方式
+	 * 	@value top 顶部弹出
+	 * 	@value center 中间弹出
+	 * 	@value bottom 底部弹出
+	 * @property {Boolean} animation = [ture|false] 是否开启动画
+	 * @property {Boolean} maskClick = [ture|false] 蒙版点击是否关闭弹窗
+	 * @event {Function} change 打开关闭弹窗触发,e={show: false}
+	 */
+
+	export default {
+		name: 'UniPopup',
+		components: {
+			uniTransition
+		},
+		props: {
+			// 开启动画
+			animation: {
+				type: Boolean,
+				default: true
+			},
+			// 弹出层类型,可选值,top: 顶部弹出层;bottom:底部弹出层;center:全屏弹出层
+			type: {
+				type: String,
+				default: 'center'
+			},
+			// maskClick
+			maskClick: {
+				type: Boolean,
+				default: true
+			}
+		},
+		data() {
+			return {
+				duration: 300,
+				ani: [],
+				showPopup: false,
+				showTrans: false,
+				maskClass: {
+					'position': 'fixed',
+					'bottom': 0,
+					'top': 0,
+					'left': 0,
+					'right': 0,
+					'backgroundColor': 'rgba(0, 0, 0, 0.4)'
+					
+				},
+				transClass: {
+					'position': 'fixed',
+					'left': 0,
+					'right': 0,
+				}
+			}
+		},
+		watch: {
+			type: {
+				handler: function(newVal) {
+					switch (this.type) {
+						case 'top':
+							this.ani = ['slide-top']
+							this.transClass = {
+								'position': 'fixed',
+								'left': 0,
+								'right': 0,
+							}
+							break
+						case 'bottom':
+							this.ani = ['slide-bottom']
+							this.transClass = {
+								'position': 'fixed',
+								'left': 0,
+								'right': 0,
+								'bottom': 0
+							}
+							break
+						case 'center':
+							this.ani = ['zoom-out', 'fade']
+							this.transClass = {
+								'position': 'fixed',
+								/* #ifndef APP-NVUE */
+								'display': 'flex',
+								'flexDirection': 'column',
+								/* #endif */
+								'bottom': 0,
+								'left': 0,
+								'right': 0,
+								'top': 0,
+								'justifyContent': 'center',
+								'alignItems': 'center'
+							}
+
+							break
+					}
+				},
+				immediate: true
+			}
+		},
+		created() {
+			if (this.animation) {
+				this.duration = 300
+			} else {
+				this.duration = 0
+			}
+		},
+		methods: {
+			clear(e) {
+				// TODO nvue 取消冒泡
+				e.stopPropagation()
+			},
+			open() {
+				this.showPopup = true
+				this.$nextTick(() => {
+					clearTimeout(this.timer)
+					this.timer = setTimeout(() => {
+						this.showTrans = true
+					}, 50);
+				})
+				this.$emit('popchange', {
+					show: true
+				})
+			},
+			close(type) {
+				this.showTrans = false
+				this.$nextTick(() => {
+					clearTimeout(this.timer)
+					this.timer = setTimeout(() => {
+						this.$emit('popchange', {
+							show: false
+						})
+						this.showPopup = false
+					}, 300)
+				})
+			},
+	
+			onTap() {
+				if (!this.maskClick) return
+				this.close()
+			}
+		}
+	}
+</script>
+<style scoped>
+	.uni-popup {
+		position: fixed;
+		/* #ifdef H5 */
+		top: var(--window-top);
+		/* #endif */
+		/* #ifndef H5 */
+		top: 0;
+		/* #endif */
+		bottom: 0;
+		left: 0;
+		right: 0;
+		/* #ifndef APP-NVUE */
+		z-index: 9999;
+		/* #endif */
+	}
+
+	.uni-popup__mask {
+		position: absolute;
+		top: 0;
+		bottom: 0;
+		left: 0;
+		right: 0;
+		background-color: rgba(0, 0, 0, 0.4);
+		opacity: 0;
+	}
+
+	.mask-ani {
+		transition-property: opacity;
+		transition-duration: 0.2s;
+	}
+
+	.uni-top-mask {
+		opacity: 1;
+	}
+
+	.uni-bottom-mask {
+		opacity: 1;
+	}
+
+	.uni-center-mask {
+		opacity: 1;
+	}
+
+	.uni-popup__wrapper {
+		/* #ifndef APP-NVUE */
+		display: block;
+		/* #endif */
+		position: absolute;
+	}
+
+	.top {
+		top: 0;
+		left: 0;
+		right: 0;
+		transform: translateY(-500px);
+	}
+
+	.bottom {
+		bottom: 0;
+		left: 0;
+		right: 0;
+		transform: translateY(500px);
+	}
+
+	.center {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		flex-direction: column;
+		/* #endif */
+		bottom: 0;
+		left: 0;
+		right: 0;
+		top: 0;
+		justify-content: center;
+		align-items: center;
+		transform: scale(1.2);
+		opacity: 0;
+	}
+
+	.uni-popup__wrapper-box {
+		/* #ifndef APP-NVUE */
+		display: block;
+		/* #endif */
+		position: relative;
+	}
+
+	.content-ani {
+		/* transition: transform 0.3s;
+ */
+		transition-property: transform, opacity;
+		transition-duration: 0.2s;
+	}
+
+
+	.uni-top-content {
+		transform: translateY(0);
+	}
+
+	.uni-bottom-content {
+		transform: translateY(0);
+	}
+
+	.uni-center-content {
+		transform: scale(1);
+		opacity: 1;
+	}
+</style>
\ No newline at end of file
diff --git a/components/uni-transition/index.vue b/components/uni-transition/index.vue
new file mode 100644
index 0000000000000000000000000000000000000000..0543b442b9f22a424b787e9da43f1344f12f3ad6
--- /dev/null
+++ b/components/uni-transition/index.vue
@@ -0,0 +1,278 @@
+<template>
+	<view v-if="isShow" ref="ani" class="uni-transition" :class="[ani.in]" :style="'transform:' +transform+';'+stylesObject" @click="change">
+		<slot></slot>
+	</view>
+</template>
+
+<script>
+	// #ifdef APP-NVUE
+	const animation = uni.requireNativePlugin('animation');
+	// #endif
+	/**
+	 * Transition 过渡动画
+	 * @description 简单过渡动画组件
+	 * @tutorial https://ext.dcloud.net.cn/plugin?id=985
+	 * @property {Boolean} show = [false|true] 控制组件显示或隐藏
+	 * @property {Array} modeClass = [fade|slide-top|slide-right|slide-bottom|slide-left|zoom-in|zoom-out] 过渡动画类型
+	 *  @value fade 渐隐渐出过渡
+	 *  @value slide-top 由上至下过渡
+	 *  @value slide-right 由右至左过渡
+	 *  @value slide-bottom 由下至上过渡
+	 *  @value slide-left 由左至右过渡
+	 *  @value zoom-in 由小到大过渡
+	 *  @value zoom-out 由大到小过渡
+	 * @property {Number} duration 过渡动画持续时间
+	 * @property {Object} styles 组件样式,同 css 样式,注意带’-‘连接符的属性需要使用小驼峰写法如:`backgroundColor:red`
+	 */
+	export default {
+		name: 'uniTransition',
+		props: {
+			show: {
+				type: Boolean,
+				default: false
+			},
+			modeClass: {
+				type: Array,
+				default () {
+					return []
+				}
+			},
+			duration: {
+				type: Number,
+				default: 300
+			},
+			styles: {
+				type: Object,
+				default () {
+					return {}
+				}
+			}
+		},
+		data() {
+			return {
+				isShow: false,
+				transform: '',
+				ani: {
+					in: '',
+					active: ''
+				}
+			};
+		},
+		watch: {
+			show: {
+				handler(newVal) {
+					if (newVal) {
+						this.open()
+					} else {
+						this.close()
+					}
+				},
+				immediate: true
+			}
+		},
+		computed: {
+			stylesObject() {
+				let styles = {
+					...this.styles,
+					'transition-duration': this.duration / 1000 + 's'
+				}
+				let transfrom = ''
+				for (let i in styles) {
+					let line = this.toLine(i)
+					transfrom += line + ':' + styles[i] + ';'
+				}
+				return transfrom
+			}
+		},
+		created() {
+			// this.timer = null
+			// this.nextTick = (time = 50) => new Promise(resolve => {
+			// 	clearTimeout(this.timer)
+			// 	this.timer = setTimeout(resolve, time)
+			// 	return this.timer
+			// });
+		},
+		methods: {
+			change() {
+				this.$emit('click', {
+					detail: this.isShow
+				})
+			},
+			open() {
+				this.isShow = true
+				this.transform = ''
+				this.ani.in = ''
+				for (let i in this.getTranfrom(false)) {
+					if (i === 'opacity') {
+						this.ani.in = 'fade-in'
+					} else {
+						this.transform += `${this.getTranfrom(false)[i]} `
+					}
+				}
+				this.$nextTick(() => {
+					setTimeout(() => {
+						this._animation(true)
+					}, 50)
+				})
+
+			},
+			close(type) {
+				this._animation(false)
+			},
+			_animation(type) {
+				let styles = this.getTranfrom(type)
+				// #ifdef APP-NVUE
+				if (!this.$refs['ani']) return
+				animation.transition(this.$refs['ani'].ref, {
+					styles,
+					duration: this.duration, //ms
+					timingFunction: 'ease',
+					needLayout: false,
+					delay: 0 //ms
+				}, () => {
+					if (!type) {
+						this.isShow = false
+					}
+					this.$emit('change', {
+						detail: this.isShow
+					})
+				})
+				// #endif
+				// #ifndef APP-NVUE
+				this.transform = ''
+				for (let i in styles) {
+					if (i === 'opacity') {
+						this.ani.in = `fade-${type?'out':'in'}`
+					} else {
+						this.transform += `${styles[i]} `
+					}
+				}
+				clearTimeout(this.timer)
+				this.timer = setTimeout(() => {
+					if (!type) {
+						this.isShow = false
+					}
+					this.$emit('change', {
+						detail: this.isShow
+					})
+
+				}, this.duration)
+				// #endif
+
+			},
+			getTranfrom(type) {
+				let styles = {
+					transform: ''
+				}
+				this.modeClass.forEach((mode) => {
+					switch (mode) {
+						case 'fade':
+							styles.opacity = type ? 1 : 0
+							break;
+						case 'slide-top':
+							styles.transform += `translateY(${type?'0':'-100%'}) `
+							break;
+						case 'slide-right':
+							styles.transform += `translateX(${type?'0':'100%'}) `
+							break;
+						case 'slide-bottom':
+							styles.transform += `translateY(${type?'0':'100%'}) `
+							break;
+						case 'slide-left':
+							styles.transform += `translateX(${type?'0':'-100%'}) `
+							break;
+						case 'zoom-in':
+							styles.transform += `scale(${type?1:0.8}) `
+							break;
+						case 'zoom-out':
+							styles.transform += `scale(${type?1:1.2}) `
+							break;
+					}
+				})
+				return styles
+			},
+			_modeClassArr(type) {
+				let mode = this.modeClass
+				if (typeof(mode) !== "string") {
+					let modestr = ''
+					mode.forEach((item) => {
+						modestr += (item + '-' + type + ',')
+					})
+					return modestr.substr(0, modestr.length - 1)
+				} else {
+					return mode + '-' + type
+				}
+			},
+			// getEl(el) {
+			// 	console.log(el || el.ref || null);
+			// 	return el || el.ref || null
+			// },
+			toLine(name) {
+				return name.replace(/([A-Z])/g, "-$1").toLowerCase();
+			}
+		}
+	}
+</script>
+
+<style scoped>
+	.uni-transition {
+		transition-timing-function: ease;
+		transition-duration: 0.3s;
+		transition-property: transform, opacity;
+	}
+
+	.fade-in {
+		opacity: 0;
+	}
+
+	.fade-active {
+		opacity: 1;
+	}
+
+	.slide-top-in {
+		/* transition-property: transform, opacity; */
+		transform: translateY(-100%);
+	}
+
+	.slide-top-active {
+		transform: translateY(0);
+		/* opacity: 1; */
+	}
+
+	.slide-right-in {
+		transform: translateX(100%);
+	}
+
+	.slide-right-active {
+		transform: translateX(0);
+	}
+
+	.slide-bottom-in {
+		transform: translateY(100%);
+	}
+
+	.slide-bottom-active {
+		transform: translateY(0);
+	}
+
+	.slide-left-in {
+		transform: translateX(-100%);
+	}
+
+	.slide-left-active {
+		transform: translateX(0);
+		opacity: 1;
+	}
+
+	.zoom-in-in {
+		transform: scale(0.8);
+	}
+
+	.zoom-out-active {
+		transform: scale(1);
+	}
+
+	.zoom-out-in {
+		transform: scale(1.2);
+	}
+</style>
\ No newline at end of file
diff --git a/package-lock.json b/package-lock.json
new file mode 100644
index 0000000000000000000000000000000000000000..e1392ef6871037709b33a3b2c6de36a3fbcc3d37
--- /dev/null
+++ b/package-lock.json
@@ -0,0 +1,13 @@
+{
+  "name": "singlestore",
+  "version": "1.0.0",
+  "lockfileVersion": 1,
+  "requires": true,
+  "dependencies": {
+    "dayjs": {
+      "version": "1.10.5",
+      "resolved": "https://registry.nlark.com/dayjs/download/dayjs-1.10.5.tgz?cache=0&sync_timestamp=1622012259636&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fdayjs%2Fdownload%2Fdayjs-1.10.5.tgz",
+      "integrity": "sha1-VgDfRUj8JFOz8WPrsqu+llzPuYY="
+    }
+  }
+}
diff --git a/package.json b/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..043fa258f3abda7727d505a0728cdec0ef0e6a76
--- /dev/null
+++ b/package.json
@@ -0,0 +1,21 @@
+{
+  "name": "singlestore",
+  "version": "1.0.0",
+  "description": "",
+  "main": "main.js",
+  "directories": {
+    "lib": "lib"
+  },
+  "scripts": {
+    "test": "echo \"Error: no test specified\" && exit 1"
+  },
+  "repository": {
+    "type": "git",
+    "url": "http://git.gelifood.com/max/singlestore.git"
+  },
+  "author": "",
+  "license": "ISC",
+  "dependencies": {
+    "dayjs": "^1.10.5"
+  }
+}
diff --git a/pages.json b/pages.json
index 3d476a86cdfaa4fb3d3930ba21c9046da06ca4c7..947257c2ace1492da1ef97d39b1f0764649c2ed1 100644
--- a/pages.json
+++ b/pages.json
@@ -5,14 +5,74 @@
 			"style": {
 				"navigationBarTitleText": "首页"
 			}
+		},
+		{
+			"path": "pages/login/index",
+			"style": {
+				"navigationBarTitleText": "登录"
+			}
+		},
+		{
+			"path": "pages/carts/index",
+			"style": {
+				"navigationBarTitleText": "购物车"
+			}
 		},
 		{
 			"path": "pages/mine/index",
 			"style": {
 				"navigationBarTitleText": "我的"
 			}
+		},
+		{
+			"path": "pages/category/index",
+			"style": {
+				"navigationBarTitleText": "分类"
+			}
+		},
+		{
+			"path": "pages/order/order-list",
+			"style": {
+				"navigationBarTitleText": "订单管理"
+			}
+		},
+		{
+			"path": "pages/goods/detail",
+			"style": {
+				"navigationBarTitleText": "商品详情"
+			}
+		},
+		{
+			"path": "pages/order/confirm-order",
+			"style": {
+				"navigationBarTitleText": "确认订单"
+			}
+		},
+		
+		{
+			"path": "pages/search/index",
+			"style": {
+				"navigationBarTitleText": "搜索"
+			}
 		}
 	],
+	"subPackages": [{
+		"root": "subPages",
+		"pages": [
+			{
+				"path": "test/index",
+				"style": {
+					"navigationBarTitleText": "test"
+				}
+			}
+		]	
+	}],
+	"preloadRule": {
+		"subPages/test/index": {
+			"network": "all",
+			"packages": ["__APP__"]
+		}
+	},
 	"globalStyle": {
 		"navigationBarTextStyle": "black",
 		"navigationBarTitleText": " ",
@@ -30,6 +90,18 @@
 				"selectedIconPath": "static/images/tabbar/find-selected.png",
 				"pagePath": "pages/home/index",
 				"text":"首页"
+			},
+			{
+				"iconPath": "static/images/tabbar/find.png",
+				"selectedIconPath": "static/images/tabbar/find-selected.png",
+				"pagePath": "pages/category/index",
+				"text":"商品分类"
+			},
+			{
+				"iconPath": "static/images/tabbar/find.png",
+				"selectedIconPath": "static/images/tabbar/find-selected.png",
+				"pagePath": "pages/carts/index",
+				"text":"购物车"
 			},
 			{
 				"iconPath": "static/images/tabbar/my.png",
diff --git a/pages/carts/index.vue b/pages/carts/index.vue
new file mode 100644
index 0000000000000000000000000000000000000000..0cedd2c1e939edc26eb8616fa246d32e6808a4bf
--- /dev/null
+++ b/pages/carts/index.vue
@@ -0,0 +1,9 @@
+<template>
+	<view>carts</view>
+</template>
+
+<script>
+</script>
+
+<style>
+</style>
diff --git a/pages/category/index.vue b/pages/category/index.vue
new file mode 100644
index 0000000000000000000000000000000000000000..6f56ee9abae8aeb2df15d3351f124624f35da438
--- /dev/null
+++ b/pages/category/index.vue
@@ -0,0 +1,43 @@
+<template>
+	<view class="category-wrap w-100">
+		<!-- search bar -->
+		<view class="searchBar-wrap w-100">搜索框</view>
+		
+		<!-- category -->
+		<view class="category flex j-between w-100">
+			<scroll-view
+				class="scroll-left"
+				scroll-y
+			>
+				<view class="flex j-center a-center p-2" v-for="(item, index) in 20" :key="index">1</view>
+			</scroll-view>
+			
+			<scroll-view
+				class="scroll-right flex-1"
+				scroll-y
+			>
+				<view>2</view>
+			</scroll-view>
+		</view>
+	</view>
+</template>
+
+<script>
+</script>
+
+<style lang="scss" scoped>
+.category-wrap {
+	.searchBar-wrap {
+		height: 10vh;
+		background-color: red;
+	}
+	
+	.category{
+		height: 90vh;
+		overflow: hidden;
+		.scroll-left {
+			flex: 0 0 240rpx;
+		}
+	}
+}
+</style>
diff --git a/pages/goods/detail.vue b/pages/goods/detail.vue
new file mode 100644
index 0000000000000000000000000000000000000000..7fa514d09642b529d48adcf070f09c0ceb8ac55f
--- /dev/null
+++ b/pages/goods/detail.vue
@@ -0,0 +1,9 @@
+<template>
+	<view>商品详情</view>
+</template>
+
+<script>
+</script>
+
+<style>
+</style>
diff --git a/pages/home/index.vue b/pages/home/index.vue
index dcaabae75f51eb2a85253d0e24f5717320accb5c..d4c77eb72e13ca75310dc2b1f024c423c1816e01 100644
--- a/pages/home/index.vue
+++ b/pages/home/index.vue
@@ -1,38 +1,43 @@
 <template>
 	<view class="content">
 		
-		<view class="test">1</view>
+		<view class="test" @click="login">登录</view>
 		<view>{{str}}</view>
-		<button type="default" @click="testTime">倒计时测试</button>
+		<button @click="go">去分包</button>
 	</view>
 </template>
 
 <script>
-	import { mapState } from 'vuex'
-	import { timerFn } from '@/utils/common.js'
-	import { test } from '@/apis/test.js'
-	export default {
-		data() {
-			return {
-				str: ""
-			}
-		},
-		computed: {
-			...mapState(['systemInfo'])
-		},
-		async onLoad() {
-			console.log(this.systemInfo.systemInfo)
-			const a = await test()
-			console.log(a)
+import { mapState } from 'vuex'
+
+import { test } from '@/apis/test.js'
+export default {
+	data() {
+		return {
+			str: ""
+		}
+	},
+	computed: {
+		...mapState(['systemInfo'])
+	},
+	async onLoad() {
+		console.log(this.systemInfo.systemInfo)
+		const a = await test()
+		console.log(a)
+	},
+	methods: {
+		login() {
+			wx.navigateTo({
+				url: '/pages/login/index'
+			})
 		},
-		methods: {
-			testTime() {
-				timerFn(10, num => {
-					this.str = num
-				})
-			}
+		go() {
+			uni.navigateTo({
+				url: "/subPages/test/index"
+			})
 		}
 	}
+}
 </script>
 
 <style lang="scss">
diff --git a/pages/login/common.js b/pages/login/common.js
new file mode 100644
index 0000000000000000000000000000000000000000..1334779ab3f3608f1de8f6a0371eb5367b291dbf
--- /dev/null
+++ b/pages/login/common.js
@@ -0,0 +1,23 @@
+import Validator from "@/utils/validate.js"
+
+
+function smsValidate() {
+	const smsValidator = new Validator()
+	const form = this.form
+	smsValidator.add(form.phone, [{strategy: 'notEmpty', errorMsg: '手机号码不能为空'}, {strategy: 'isMobile', errorMsg: '手机号码格式不正确'}])
+	smsValidator.add(form.smsCode, [{strategy: 'notEmpty', errorMsg: '验证码不能为空'}])
+	return smsValidator.validate()
+}
+
+function accoutValidate() {
+	const smsValidator = new Validator()
+	const form = this.form
+	smsValidator.add(form.phone, [{strategy: 'notEmpty', errorMsg: '手机号码不能为空'}, {strategy: 'isMobile', errorMsg: '手机号码格式不正确'}])
+	smsValidator.add(form.password, [{strategy: 'notEmpty', errorMsg: '密码不能为空'}])
+	return smsValidator.validate()
+}
+
+export default {
+	smsValidate,
+	accoutValidate
+}
\ No newline at end of file
diff --git a/pages/login/index.vue b/pages/login/index.vue
index 4b8d87d2603706e177fa4367b7f06aa728cd4ed4..152bfbfbdd1531048f5756e417237d8b03323fc8 100644
--- a/pages/login/index.vue
+++ b/pages/login/index.vue
@@ -1,9 +1,114 @@
 <template>
-	<view>login</view>
+	<view>
+		<view>
+			<input 
+				type="text"
+				placeholder="请输入手机号码"
+				data-type="phone"
+				@input="inputForm" 
+			/>
+		</view>
+		
+		<view v-show="login_type === 'smsLogin'">
+			<input
+				type="text"
+				placeholder="请输入验证码"
+				data-type="smsCode"
+				@input="inputForm" 
+			/>
+			<view>SMS</view>
+		</view>
+		
+		<view v-show="login_type === 'accoutLogin'">
+			<input
+				type="password"
+				placeholder="请输入密码"
+				data-type="password"
+				@input="inputForm" 
+			/>
+		</view>
+		
+		<view>
+			<button type="default" @click="handleLogin('smsLogin')">短信验证码注册登录</button>
+			<button open-type="getPhoneNumber" @getphonenumber="getPhoneNumber">微信快捷登录</button>
+			<button type="default" @click="handleLogin('accoutLogin')">密码登录</button>
+		</view>
+		
+	
+	</view>
 </template>
 
 <script>
+import loginCommon from './common.js'
+import uniPopup from '@/components/uni-popup/index.vue'
+import { timerFn } from '@/utils/common.js'
+
+export default {
+	data() {
+		return {
+			login_type: "smsLogin", // smsLogin wxLogin accoutLogin
+			form: {
+				phone: null,
+				smsCode: null,
+				password: null
+			}
+		}
+	},
+	components: {
+		uniPopup
+	},
+	methods: {
+		...loginCommon,
+		
+		inputForm(e) {
+			const { type } = e.currentTarget.dataset
+			this.form[type] = e.detail.value
+		},
+		
+		handleLogin(type) { 
+			if(type !== this.login_type) return this.login_type = type
+			console.log('-----------------------')
+			switch (type) {
+				case 'smsLogin':
+					const smsValidaErr = this.smsValidate()
+					if(smsValidaErr) return this.$toast({title: smsValidaErr})
+					console.log('login api')
+					uni.navigateBack()
+					break;
+				case 'accoutLogin':
+					const accoutValidaErr = this.accoutValidate()
+					if(accoutValidaErr) return this.$toast({title: accoutValidaErr})
+					console.log('login api')
+					uni.navigateBack()
+					break;
+				default:
+					break;
+			}
+		},
+		
+		
+		getPhoneNumber (e) {
+		    console.log(e.detail.errMsg)
+		    console.log(e.detail.iv)
+		    console.log(e.detail.encryptedData)
+		 },
+
+		
+		// testTime() {
+		// 	timerFn(10, num => {
+		// 		this.str = num
+		// 	})
+		// },
+	}
+}
 </script>
 
-<style>
+<style  scoped>
+
+.test {
+	position: fixed;
+	right: 20rpx;
+	top: 20rpx;
+	z-index: 2;
+}
 </style>
diff --git a/pages/mine/index.vue b/pages/mine/index.vue
index ddaddc5485f8f1fe85cbbe674eb1a19797f602dd..dd421ae52f2ad45c546d25e1bbcef56898deaff9 100644
--- a/pages/mine/index.vue
+++ b/pages/mine/index.vue
@@ -1,9 +1,33 @@
 <template>
-	<view>mine</view>
+	<view class="w-100">
+		<!-- userInfo -->
+		<view class="user-wrap flex j-start a-center w-100">
+			<block>
+				<open-data class="avatar mr-2" type="userAvatarUrl"></open-data>
+				<open-data type="userNickName" lang="zh_CN"></open-data>
+			</block>
+		</view>
+	</view>
 </template>
 
 <script>
+export default {
+	data() {
+		return {
+			token: null
+		}
+	}
+}
 </script>
 
-<style>
+<style lang="scss" scoped>
+.user-wrap {
+	@include borderBox(20rpx, 20rpx);
+	height: 240rpx;
+	background-color: red;
+	.avatar {
+		width: 160rpx;
+		height: 160rpx;
+	}
+}
 </style>
diff --git a/pages/order/confirm-order.vue b/pages/order/confirm-order.vue
new file mode 100644
index 0000000000000000000000000000000000000000..4a2ad5014f67fe2b74359f917be4a0a108ade950
--- /dev/null
+++ b/pages/order/confirm-order.vue
@@ -0,0 +1,9 @@
+<template>
+	<view>确认订单</view>
+</template>
+
+<script>
+</script>
+
+<style>
+</style>
diff --git a/pages/order/order-list.vue b/pages/order/order-list.vue
new file mode 100644
index 0000000000000000000000000000000000000000..0bf9be168eea06e293aa60c45bdaa132e301d1e8
--- /dev/null
+++ b/pages/order/order-list.vue
@@ -0,0 +1,30 @@
+<template>
+	<view class="w-100 order-wrap">
+		<!-- tabBar -->
+		<scroll-view class="tab-wrap w-100" scroll-x>
+			<view class="tab-item">全部</view>
+			<view class="tab-item">待付款</view>
+			<view class="tab-item">å¾…æ”¶è´§</view>
+			<view class="tab-item">已收货</view>
+			<view class="tab-item">退货退款</view>
+			<view class="tab-item">交易关闭</view>
+		</scroll-view>
+	</view>
+</template>
+
+<script>
+</script>
+
+<style lang="scss" scoped>
+.order-wrap {
+	.tab-wrap {
+		height: 98rpx;
+		white-space:nowrap;
+		overflow: hidden;
+		.tab-item {
+			@include borderBox(20rpx, 20rpx);
+			display: inline-block;
+		}
+	}
+}
+</style>
diff --git a/pages/search/index.vue b/pages/search/index.vue
new file mode 100644
index 0000000000000000000000000000000000000000..4d5428efcb9c1c42ba2ffb4bf62c65d05c531f3c
--- /dev/null
+++ b/pages/search/index.vue
@@ -0,0 +1,9 @@
+<template>
+	<view>search</view>
+</template>
+
+<script>
+</script>
+
+<style>
+</style>
diff --git a/readme.md b/readme.md
index f006ba27e68c9ff349d3b05c67a128d7af21d588..49c2bc47ec79c15f9e5ef85ffaec1ba14e1b3b6d 100644
--- a/readme.md
+++ b/readme.md
@@ -9,7 +9,7 @@
 	setStorage("str1", str1) ""1""
 	getStorage("str1") // "1"
 	
-	setStorage(num) "1"
+	setStorage(num) // "1"
 	getStorage("num") // 1
 	
 	getStorage("str1") === getStorage("num") // false
diff --git a/store/modules/user.js b/store/modules/user.js
index e9c341b6c2567c0ded4e4ec25040b1ea72820d5a..889162afb0024e2b86c20c3b50a75dc795e2eb34 100644
--- a/store/modules/user.js
+++ b/store/modules/user.js
@@ -1,4 +1,6 @@
 import { getStorage, setStorage, removeStorage } from '@/lib/storage'
+// import store from '@/store/index.js'
+
 const state = {
 	token: '',
 	userInfo: ''
diff --git a/styles/layout.css b/styles/layout.css
index 4ba6cde3a8d989f17ab536452a80949ba0bff941..88360094c27c9786935d271d33a6be919279c9d0 100644
--- a/styles/layout.css
+++ b/styles/layout.css
@@ -24,6 +24,87 @@
 .flex-4{ flex: 4; }
 .flex-5{ flex: 5; }
 
+/*  -- 内外边距 -- */
+.m-0 { margin: 0; }
+.m-1 { margin: 10rpx; }
+.m-2 { margin: 20rpx; }
+.m-3 { margin: 30rpx; }
+.m-4 { margin: 40rpx; }
+.m-5 { margin: 50rpx; }
+.mt-0 { margin-top: 0; }
+.mt-1 { margin-top: 10rpx; }
+.mt-2 { margin-top: 20rpx; }
+.mt-3 { margin-top: 30rpx; }
+.mt-4 { margin-top: 40rpx; }
+.mt-5 { margin-top: 50rpx; }
+.mb-0 { margin-bottom: 0; }
+.mb-1 { margin-bottom: 10rpx; }
+.mb-2 { margin-bottom: 20rpx; }
+.mb-3 { margin-bottom: 30rpx; }
+.mb-4 { margin-bottom: 40rpx; }
+.mb-5 { margin-bottom: 50rpx; }
+.ml-0 { margin-left: 0; }
+.ml-1 { margin-left: 10rpx; }
+.ml-2 { margin-left: 20rpx; }
+.ml-3 { margin-left: 30rpx; }
+.ml-4 { margin-left: 40rpx; }
+.ml-5 { margin-left: 50rpx; }
+.mr-0 { margin-right: 0; }
+.mr-1 { margin-right: 10rpx; }
+.mr-2 { margin-right: 20rpx; }
+.mr-3 { margin-right: 30rpx; }
+.mr-4 { margin-right: 40rpx; }
+.mr-5 { margin-right: 50rpx; }
+.my-0 { margin-top: 0; margin-bottom: 0; }
+.my-1 { margin-top: 10rpx; margin-bottom: 10rpx; }
+.my-2 { margin-top: 20rpx; margin-bottom: 20rpx; }
+.my-3 { margin-top: 30rpx; margin-bottom: 30rpx; }
+.my-4 { margin-top: 40rpx; margin-bottom: 40rpx; }
+.my-5 { margin-top: 50rpx; margin-bottom: 50rpx; }
+.mx-0 { margin-left: 0; margin-right: 0; }
+.mx-1 { margin-left: 10rpx; margin-right: 10rpx; }
+.mx-2 { margin-left: 20rpx; margin-right: 20rpx; }
+.mx-3 { margin-left: 30rpx; margin-right: 30rpx; }
+.mx-4 { margin-left: 40rpx; margin-right: 40rpx; }
+.mx-5 { margin-left: 50rpx; margin-right: 50rpx; }
+
+.p-1 { padding: 10rpx; }
+.p-2 { padding: 20rpx; }
+.p-3 { padding: 30rpx; }
+.p-4 { padding: 40rpx; }
+.p-5 { padding: 50rpx; }
+.pt-1 { padding-top: 10rpx; }
+.pt-2 { padding-top: 20rpx; }
+.pt-3 { padding-top: 30rpx; }
+.pt-4 { padding-top: 40rpx; }
+.pt-5 { padding-top: 50rpx; }
+.pb-1 { padding-bottom: 10rpx; }
+.pb-2 { padding-bottom: 20rpx; }
+.pb-3 { padding-bottom: 30rpx; }
+.pb-4 { padding-bottom: 40rpx; }
+.pb-5 { padding-bottom: 50rpx; }
+.pl-1 { padding-left: 10rpx; }
+.pl-2 { padding-left: 20rpx; }
+.pl-3 { padding-left: 30rpx; }
+.pl-4 { padding-left: 40rpx; }
+.pl-5 { padding-left: 50rpx; }
+.pr-1 { padding-right: 10rpx; }
+.pr-2 { padding-right: 20rpx; }
+.pr-3 { padding-right: 30rpx; }
+.pr-4 { padding-right: 40rpx; }
+.pr-5 { padding-right: 50rpx; }
+.py-1 { padding-top: 10rpx; padding-bottom: 10rpx; }
+.py-2 { padding-top: 20rpx; padding-bottom: 20rpx; }
+.py-3 { padding-top: 30rpx; padding-bottom: 30rpx; }
+.py-4 { padding-top: 40rpx; padding-bottom: 40rpx; }
+.py-5 { padding-top: 50rpx; padding-bottom: 50rpx; }
+.px-1 { padding-left: 10rpx; padding-right: 10rpx; }
+.px-2 { padding-left: 20rpx; padding-right: 20rpx; }
+.px-3 { padding-left: 30rpx; padding-right: 30rpx; }
+.px-4 { padding-left: 40rpx; padding-right: 40rpx; }
+.px-5 { padding-left: 50rpx; padding-right: 50rpx; }
+
+
 /* 文字对齐 */
 .text-left { text-align: left; }
 .text-right { text-align: right; }
diff --git a/subPages/test/index.vue b/subPages/test/index.vue
new file mode 100644
index 0000000000000000000000000000000000000000..f224c253cbefdb73759c3111b0cde73cac612c98
--- /dev/null
+++ b/subPages/test/index.vue
@@ -0,0 +1,9 @@
+<template>
+	<view>1</view>
+</template>
+
+<script>
+</script>
+
+<style>
+</style>
diff --git a/utils/common.js b/utils/common.js
index 84aae6831a43f66cdfa78454294552df349452a8..122586c8eaf03e798b25618142d9c90269c571a5 100644
--- a/utils/common.js
+++ b/utils/common.js
@@ -14,4 +14,4 @@ export function timerFn(num = 60, cb) {
 			return
 		}
 	}, 1000)
-}
\ No newline at end of file
+}
diff --git a/vue.config.js b/vue.config.js
new file mode 100644
index 0000000000000000000000000000000000000000..e330d71f05043d9337033b5c463aef8fc5ff88bd
--- /dev/null
+++ b/vue.config.js
@@ -0,0 +1,15 @@
+module.exports = {
+    chainWebpack: (config) => {
+        // 发行或运行时启用了压缩时会生效
+        config.optimization.minimizer('terser').tap((args) => {
+            const compress = args[0].terserOptions.compress
+            // 非 App 平台移除 console 代码(包含所有 console 方法,如 log,debug,info...)
+            compress.drop_console = true
+            compress.pure_funcs = [
+                '__f__', // App 平台 vue 移除日志代码
+                // 'console.debug' // 可移除指定的 console 方法
+            ]
+            return args
+        })
+    }
+}
\ No newline at end of file