diff --git a/yudao-vue-ui/common/js/util.js b/yudao-vue-ui/common/js/util.js
new file mode 100644
index 0000000000..13ab716a9e
--- /dev/null
+++ b/yudao-vue-ui/common/js/util.js
@@ -0,0 +1,47 @@
+let _debounceTimeout = null,
+	_throttleRunning = false
+	
+/**
+ * 防抖
+ * 参考文章 https://juejin.cn/post/6844903669389885453
+ * 
+ * @param {Function} 执行函数
+ * @param {Number} delay 延时ms   
+ */
+export const debounce = (fn, delay=500) => {
+	clearTimeout(_debounceTimeout);
+	_debounceTimeout = setTimeout(() => {
+		fn();
+	}, delay);
+}
+
+/**
+ * 节流
+ * 参考文章 https://juejin.cn/post/6844903669389885453
+ * 
+ * @param {Function} 执行函数
+ * @param {Number} delay 延时ms  
+ */
+export const throttle = (fn, delay=500) => {
+	if(_throttleRunning){
+		return;
+	}
+	_throttleRunning = true;
+	fn();
+	setTimeout(() => {
+	    _throttleRunning = false;
+	}, delay);
+}
+
+/**
+ * toast
+ */
+export const msg = (title = '', param={}) => {
+	if(!title) return;
+	uni.showToast({
+		title,
+		duration: param.duration || 1500,
+		mask: param.mask || false,
+		icon: param.icon || 'none'
+	});
+}
\ No newline at end of file
diff --git a/yudao-vue-ui/common/mixin/mixin.js b/yudao-vue-ui/common/mixin/mixin.js
new file mode 100644
index 0000000000..701d702226
--- /dev/null
+++ b/yudao-vue-ui/common/mixin/mixin.js
@@ -0,0 +1,96 @@
+// import {request} from '@/common/js/request'
+
+export default{
+	data() {
+		return {
+			page: 0, // 页码
+			pageNum: 6, // 每页加载数据量
+			loadingType: 1, // 加载类型。0 加载前;1 加载中;2 没有更多
+			isLoading: false, // 刷新数据
+			loaded: false, // 加载完毕
+		}
+	},
+	methods: {
+		/**
+		 * 打印日志,方便调试
+		 *
+		 * @param {Object} data 数据
+		 */
+		log(data) {
+			console.log(JSON.parse(JSON.stringify(data)))
+		},
+		
+		/**
+		 * navigatorTo 跳转页面
+		 * 
+		 * @param {String} url
+		 * @param {Object} options 可选参数
+		 * @param {Boolean} options.login 是否检测登录  
+		 */
+		navTo(url, options={}) {
+			this.$util.throttle(() => {
+				if (!url) {
+					return;
+				}
+				// 如果需要登陆,并且未登陆,则跳转到登陆界面
+				if ((~url.indexOf('login=1') || options.login) && !this.$store.getters.hasLogin){
+					url = '/pages/auth/login';
+				}
+				// 跳转到指定 url 地址
+				uni.navigateTo({
+					url
+				})
+			}, 300)
+		},
+		
+		/**
+		 * $request云函数请求 TODO 芋艿:需要改成自己的
+		 * @param {String} module
+		 * @param {String} operation
+		 * @param {Boolean} data 请求参数
+		 * @param {Boolean} ext 附加参数
+		 * @param {Boolean} ext.showLoading 是否显示loading状态,默认不显示
+		 * @param {Boolean} ext.hideLoading 是否关闭loading状态,默认关闭
+		 * @param {Boolean} ext.login 未登录拦截
+		 * @param {Boolean} ext.setLoaded 加载完成是设置页面加载完毕
+		 */
+		$request(module, operation, data={}, ext={}){
+			if(ext.login && !this.$util.isLogin()){
+				return;
+			}
+			if(ext.showLoading){
+				this.isLoading = true;
+			}
+			return new Promise((resolve, reject)=> {
+				request(module, operation, data, ext).then(result => {
+					if(ext.hideLoading !== false){
+						this.isLoading = false;
+					}
+					setTimeout(()=>{
+						if(this.setLoaded !== false){
+							this.loaded = true;
+						}
+					}, 100)
+					this.$refs.confirmBtn && this.$refs.confirmBtn.stop();
+					resolve(result);
+				}).catch((err) => {
+					reject(err);
+				})
+			})
+		},
+		imageOnLoad(data, key){ // TODO 芋艿:需要改成自己的
+			setTimeout(()=>{
+				this.$set(data, 'loaded', true);
+			}, 100)
+		},
+		showPopup(key){ //  TODO 芋艿:需要改成自己的
+			this.$util.throttle(()=>{
+				this.$refs[key].open();
+			}, 200)
+		},
+		hidePopup(key){ //  TODO 芋艿:需要改成自己的
+			this.$refs[key].close();
+		},
+		stopPrevent(){}, //  TODO 芋艿:需要改成自己的
+	},
+}
\ No newline at end of file
diff --git a/yudao-vue-ui/main.js b/yudao-vue-ui/main.js
index afc6b0895d..565d893ffb 100644
--- a/yudao-vue-ui/main.js
+++ b/yudao-vue-ui/main.js
@@ -1,5 +1,31 @@
 import App from './App'
 
+// 全局 Mixin
+import mixin from './common/mixin/mixin'
+Vue.mixin(mixin) 
+
+// 全局 Util
+import {
+	msg,
+	isLogin,
+	debounce,
+	throttle,
+	prePage,
+	date
+} from '@/common/js/util'
+Vue.prototype.$util = {
+	msg,
+	isLogin,
+	debounce,
+	throttle,
+	prePage,
+	date
+}
+
+// 全局 Store
+import store from './store'
+Vue.prototype.$store = store
+
 // #ifndef VUE3
 import Vue from 'vue'
 Vue.config.productionTip = false
diff --git a/yudao-vue-ui/pages.json b/yudao-vue-ui/pages.json
index 1f30ba5093..4e14ef627c 100644
--- a/yudao-vue-ui/pages.json
+++ b/yudao-vue-ui/pages.json
@@ -11,7 +11,21 @@
 				"navigationBarTitleText": "我的",
 				"navigationStyle": "custom"
 			}
-		}
+		}, {
+			"path": "pages/auth/login",
+			"style": {
+				"navigationBarTitleText": "登录",
+				"navigationStyle":"custom",
+				"app-plus": {
+					"animationType": "slide-in-bottom"
+				}
+			}
+		}, {
+            "path" : "pages/set/userInfo",
+            "style" : {
+				"navigationBarTitleText": "个人资料"
+			}
+        }
 	],
 	"globalStyle": {
 		"navigationBarTextStyle": "black",
diff --git a/yudao-vue-ui/pages/auth/login.vue b/yudao-vue-ui/pages/auth/login.vue
new file mode 100644
index 0000000000..8667c0da1d
--- /dev/null
+++ b/yudao-vue-ui/pages/auth/login.vue
@@ -0,0 +1,323 @@
+
+	
+		
+		
+		
+		
+			
+			请认真阅读并同意
+			《用户服务协议》
+			《隐私权政策》
+		
+		
+			LOGIN
+			
+				欢迎回来!
+			
+			
+				
+					手机号码
+					
+						
+					
+				
+				
+					验证码
+					
+						
+						
+					
+				
+			
+			
+			
+			
+			
+				
+					快捷登录
+				
+				
+					
+					
+						
+					
+					
+					
+					
+					
+						
+						Apple登录
+					
+					
+						
+						微信登录
+					
+					
+				
+			
+			
+		
+		
+		
+	
+
+
+
+
+
+
diff --git a/yudao-vue-ui/pages/auth/mixin/login-app-wx.js b/yudao-vue-ui/pages/auth/mixin/login-app-wx.js
new file mode 100644
index 0000000000..834ff87acb
--- /dev/null
+++ b/yudao-vue-ui/pages/auth/mixin/login-app-wx.js
@@ -0,0 +1,73 @@
+export default{
+	// #ifdef APP-PLUS
+	methods: {
+		/**
+		 * 微信App登录
+		 *  "openId": "o0yywwGWxtBCvBuE8vH4Naof0cqU",
+		 *	"nickName": "S .",
+		 *	"gender": 1,
+		 *	"city": "临沂",
+		 *	"province": "山东",
+		 *	"country": "中国",
+		 *	"avatarUrl": "http://thirdwx.qlogo.cn/mmopen/vi_32/xqpCtHRBBmdlf201Fykhtx7P7JcicIbgV3Weic1oOvN6iaR3tEbuu74f2fkKQWXvzK3VDgNTZzgf0g8FqPvq8LCNQ/132",
+		 *	"unionId": "oYqy4wmMcs78x9P-tsyMeM3MQ1PU"
+		 */
+		loginByWxApp(userInfoData){
+			if(!this.agreement){
+				this.$util.msg('请阅读并同意用户服务及隐私协议');
+				return;
+			}
+			this.$util.throttle(async ()=>{
+				let [err, res] = await uni.login({
+					provider: 'weixin'
+				})
+				if(err){
+					console.log(err);
+					return;
+				}
+				uni.getUserInfo({
+					provider: 'weixin',
+					success: async res=>{
+						const response = await this.$request('user', 'loginByWeixin', {
+							userInfo: res.userInfo,
+						}, {
+							showLoading: true
+						});
+						if(response.status === 0){
+							this.$util.msg(response.msg);
+							return;
+						}
+						if(response.hasBindMobile && response.data.token){
+							this.loginSuccessCallBack({
+								token: response.data.token,
+								tokenExpired: response.data.tokenExpired
+							});
+						}else{
+							this.navTo('/pages/auth/bindMobile?data='+JSON.stringify(response.data))
+						}
+						plus.oauth.getServices(oauthRes=>{
+							oauthRes[0].logout(logoutRes => {
+								console.log(logoutRes);
+							}, error => {
+								console.log(error);
+							})
+						})
+					},
+					fail(err) {
+						console.log(err);
+					}
+				})
+			})
+		}
+	}
+	// #endif
+}
+
+
+
+
+
+
+
+
+
diff --git a/yudao-vue-ui/pages/auth/mixin/login-apple.js b/yudao-vue-ui/pages/auth/mixin/login-apple.js
new file mode 100644
index 0000000000..c0c98d3455
--- /dev/null
+++ b/yudao-vue-ui/pages/auth/mixin/login-apple.js
@@ -0,0 +1,83 @@
+export default{
+	onLoad() {
+		if(this.systemInfo.platform !== 'ios'){
+			return;
+		}
+		const systemVersion = +this.systemInfo.system.split('.')[0];
+		if(systemVersion >= 13){
+			this.canUseAppleLogin = true;
+		}
+	},
+	methods: {
+		//苹果登录
+		async loginByApple(){
+			/* if(!this.canUseAppleLogin){
+				this.$util.msg('系统版本过低,无法使用苹果登录');
+				return;
+			} */ 
+			if(!this.agreement){
+				this.$util.msg('请阅读并同意用户服务及隐私协议');
+				this.$refs.confirmBtn.stop();
+				return;
+			}
+			uni.login({  
+			    provider: 'apple',  
+			    success: loginRes=> {  
+			        // 登录成功   
+			        uni.getUserInfo({  
+			            provider: 'apple',  
+			            success: async userRes=> {
+							console.log(userRes);
+							const response = await this.$request('user', 'loginByApple', {
+								authorizationCode: userRes.userInfo.authorizationCode,
+								identityToken: userRes.userInfo.identityToken
+							}, {
+								showLoading: true
+							});
+							console.log(response);
+							//注销苹果登录
+							this.appleLogout();
+							console.log(response);
+							if(response.status === 0){
+								this.$util.msg(response.msg);
+								return;
+							}
+							if(response.hasBindMobile && response.data.token){
+								this.loginSuccessCallBack({
+									token: response.data.token,
+									tokenExpired: response.data.tokenExpired
+								});
+							}else{
+								this.navTo('/pages/auth/bindMobile?type=apple&data='+JSON.stringify(response.data))
+							}
+			            }  
+			        })  
+			    },  
+			    fail: err=> {  
+					console.log(err);
+					this.$util.msg('登录失败');
+					this.appleLogout();
+			    }  
+			})
+		},
+		appleLogout(){
+			plus.oauth.getServices(oauthRes=>{
+				const oIndex = oauthRes.findIndex(oItem=> oItem.id === 'apple');
+				oauthRes[oIndex].logout(loRes => {
+					console.log('appleLogout success=> ', loRes);
+				}, loErr => {
+					console.log('appleLogout error=> ', loErr);
+				})
+			})
+		}
+	}
+}
+
+
+
+
+
+
+
+
+
diff --git a/yudao-vue-ui/pages/auth/mixin/login-mp-wx.js b/yudao-vue-ui/pages/auth/mixin/login-mp-wx.js
new file mode 100644
index 0000000000..1f4438a86b
--- /dev/null
+++ b/yudao-vue-ui/pages/auth/mixin/login-mp-wx.js
@@ -0,0 +1,81 @@
+export default{
+	// #ifdef MP-WEIXIN
+	data(){
+		return {
+			mpCodeTimer: 0,
+			mpWxCode: '',
+		}
+	},
+	computed: {
+		timerIdent(){
+			return this.$store.state.timerIdent;
+		}
+	},
+	watch: {
+		timerIdent(){
+			this.mpCodeTimer ++;
+			if(this.mpCodeTimer % 30 === 0){
+				this.getMpWxCode();
+			}
+		}
+	},
+	onShow(){
+		this.getMpWxCode();
+	},
+	methods: {
+		//微信小程序登录
+		mpWxGetUserInfo(){
+			if(!this.agreement){
+				this.$util.msg('请阅读并同意用户服务及隐私协议');
+				return;
+			}
+			
+			this.$util.throttle(()=>{
+				uni.getUserProfile({
+					desc: '用于展示您的头像及昵称',
+					success: async profileRes=> {
+						const res = await this.$request('user', 'loginByWeixin', {
+							code: this.mpWxCode,
+							...profileRes.userInfo
+						}, {
+							showLoading: true
+						});
+						if(res.status === 0){
+							this.$util.msg(res.msg);
+							return;
+						}
+						if(res.hasBindMobile && res.data.token){
+							this.loginSuccessCallBack({
+								token: res.data.token,
+								tokenExpired: res.data.tokenExpired
+							});
+						}else{
+							this.navTo('/pages/auth/bindMobile?data='+JSON.stringify(res.data))
+						}
+						console.log(res)
+					}
+				})
+			})
+		},
+		//获取code
+		getMpWxCode(){
+			uni.login({
+				provider: 'weixin',
+				success: res=> {
+					this.mpWxCode = res.code;
+				}
+			})
+		},
+		
+	}
+	// #endif
+}
+
+
+
+
+
+
+
+
+
diff --git a/yudao-vue-ui/pages/set/userInfo.vue b/yudao-vue-ui/pages/set/userInfo.vue
new file mode 100644
index 0000000000..89dcd33a38
--- /dev/null
+++ b/yudao-vue-ui/pages/set/userInfo.vue
@@ -0,0 +1,248 @@
+
+	
+		
+			头像
+			
+				
+				
+				
+			
+		
+		
+			昵称
+			
+		
+		
+			性别
+			
+				
+				
+				男
+			
+			
+				
+				
+				女
+			
+		
+		
+		
+	
+
+
+
+
+
diff --git a/yudao-vue-ui/pages/tabbar/user.vue b/yudao-vue-ui/pages/tabbar/user.vue
index db09735378..8e72213bc0 100644
--- a/yudao-vue-ui/pages/tabbar/user.vue
+++ b/yudao-vue-ui/pages/tabbar/user.vue
@@ -59,7 +59,7 @@
 			
 			
 			
-			
+			
 			
 		
 	
diff --git a/yudao-vue-ui/store/index.js b/yudao-vue-ui/store/index.js
new file mode 100644
index 0000000000..afcddc646e
--- /dev/null
+++ b/yudao-vue-ui/store/index.js
@@ -0,0 +1,93 @@
+import Vue from 'vue'
+import Vuex from 'vuex'
+// import {request} from '@/common/js/request'
+
+Vue.use(Vuex)
+
+const store = new Vuex.Store({
+	state: {
+		openExamine: false, // 是否开启审核状态。用于小程序、App 等审核时,关闭部分功能。TODO 芋艿:暂时没找到刷新的地方
+		token: '', // 用户身份 Token
+		userInfo: {}, // 用户基本信息
+		timerIdent: false, // 全局 1s 定时器,只在全局开启一个,所有需要定时执行的任务监听该值即可,无需额外开启 TODO 芋艿:需要看看
+		orderCount: {}, // 订单数量
+	},
+	getters: {
+		hasLogin(state){
+			return !!state.token;
+		}
+	},
+	mutations: {
+		//更新state数据
+		setStateAttr(state, param){
+			if(param instanceof Array){
+				for(let item of param){
+					state[item.key] = item.val;
+				}
+			}else{
+				state[param.key] = param.val;
+			}
+		},
+		//更新token
+		setToken(state, data){
+			const {token, tokenExpired} = data;
+			state.token = token;
+			uni.setStorageSync('uniIdToken', token);
+			uni.setStorageSync('tokenExpired', tokenExpired);
+			this.dispatch('getUserInfo'); //更新用户信息
+			this.dispatch('getCartCount');//更新购物车数量
+			uni.$emit('refreshCart');//刷新购物车
+			this.dispatch('getOrderCount'); //更新订单数量
+		},
+		// 退出登录
+		logout(state) {
+			state.token = '';
+			uni.removeStorageSync('uniIdToken');
+			this.dispatch('getCartCount');//更新购物车数量
+			uni.$emit('refreshCart');//刷新购物车
+			this.dispatch('getOrderCount'); //更新订单数量
+			setTimeout(()=>{
+				state.userInfo = {};
+			}, 1100)
+		},
+	},
+	actions: {
+		//更新用户信息
+		async getUserInfo({state, commit}){
+			const res = await request('user', 'get', {}, {
+				checkAuthInvalid: false
+			});
+			if(res.status === 1){
+				const userInfo = res.data;
+				commit('setStateAttr', {
+					key: 'userInfo',
+					val: userInfo
+				})
+			}
+		},
+		//更新用户订单数量
+		async getOrderCount({state, commit}){
+			let data = {
+				c0: 0,
+				c1: 0,
+				c2: 0,
+				c3: 0
+			}
+			if(state.token){
+				try {
+					const res = await request('order', 'getOrderCount');
+					data = res;
+				}catch (err){
+					console.error('更新用户订单数量 => ', err);
+				}
+			}
+			commit('setStateAttr', {
+				key: 'orderCount',
+				val: data
+			})
+		}
+	}
+}) 
+
+
+export default store