Commit 55ee2fcad7f1c5a30b4b747d8f4e48898f7766c6
1 parent
d1291208
增加登陆界面
Showing
11 changed files
with
1086 additions
and
2 deletions
yudao-vue-ui/common/js/util.js
0 → 100644
| 1 | +let _debounceTimeout = null, | ||
| 2 | + _throttleRunning = false | ||
| 3 | + | ||
| 4 | +/** | ||
| 5 | + * 防抖 | ||
| 6 | + * 参考文章 https://juejin.cn/post/6844903669389885453 | ||
| 7 | + * | ||
| 8 | + * @param {Function} 执行函数 | ||
| 9 | + * @param {Number} delay 延时ms | ||
| 10 | + */ | ||
| 11 | +export const debounce = (fn, delay=500) => { | ||
| 12 | + clearTimeout(_debounceTimeout); | ||
| 13 | + _debounceTimeout = setTimeout(() => { | ||
| 14 | + fn(); | ||
| 15 | + }, delay); | ||
| 16 | +} | ||
| 17 | + | ||
| 18 | +/** | ||
| 19 | + * 节流 | ||
| 20 | + * 参考文章 https://juejin.cn/post/6844903669389885453 | ||
| 21 | + * | ||
| 22 | + * @param {Function} 执行函数 | ||
| 23 | + * @param {Number} delay 延时ms | ||
| 24 | + */ | ||
| 25 | +export const throttle = (fn, delay=500) => { | ||
| 26 | + if(_throttleRunning){ | ||
| 27 | + return; | ||
| 28 | + } | ||
| 29 | + _throttleRunning = true; | ||
| 30 | + fn(); | ||
| 31 | + setTimeout(() => { | ||
| 32 | + _throttleRunning = false; | ||
| 33 | + }, delay); | ||
| 34 | +} | ||
| 35 | + | ||
| 36 | +/** | ||
| 37 | + * toast | ||
| 38 | + */ | ||
| 39 | +export const msg = (title = '', param={}) => { | ||
| 40 | + if(!title) return; | ||
| 41 | + uni.showToast({ | ||
| 42 | + title, | ||
| 43 | + duration: param.duration || 1500, | ||
| 44 | + mask: param.mask || false, | ||
| 45 | + icon: param.icon || 'none' | ||
| 46 | + }); | ||
| 47 | +} | ||
| 0 | \ No newline at end of file | 48 | \ No newline at end of file |
yudao-vue-ui/common/mixin/mixin.js
0 → 100644
| 1 | +// import {request} from '@/common/js/request' | ||
| 2 | + | ||
| 3 | +export default{ | ||
| 4 | + data() { | ||
| 5 | + return { | ||
| 6 | + page: 0, // 页码 | ||
| 7 | + pageNum: 6, // 每页加载数据量 | ||
| 8 | + loadingType: 1, // 加载类型。0 加载前;1 加载中;2 没有更多 | ||
| 9 | + isLoading: false, // 刷新数据 | ||
| 10 | + loaded: false, // 加载完毕 | ||
| 11 | + } | ||
| 12 | + }, | ||
| 13 | + methods: { | ||
| 14 | + /** | ||
| 15 | + * 打印日志,方便调试 | ||
| 16 | + * | ||
| 17 | + * @param {Object} data 数据 | ||
| 18 | + */ | ||
| 19 | + log(data) { | ||
| 20 | + console.log(JSON.parse(JSON.stringify(data))) | ||
| 21 | + }, | ||
| 22 | + | ||
| 23 | + /** | ||
| 24 | + * navigatorTo 跳转页面 | ||
| 25 | + * | ||
| 26 | + * @param {String} url | ||
| 27 | + * @param {Object} options 可选参数 | ||
| 28 | + * @param {Boolean} options.login 是否检测登录 | ||
| 29 | + */ | ||
| 30 | + navTo(url, options={}) { | ||
| 31 | + this.$util.throttle(() => { | ||
| 32 | + if (!url) { | ||
| 33 | + return; | ||
| 34 | + } | ||
| 35 | + // 如果需要登陆,并且未登陆,则跳转到登陆界面 | ||
| 36 | + if ((~url.indexOf('login=1') || options.login) && !this.$store.getters.hasLogin){ | ||
| 37 | + url = '/pages/auth/login'; | ||
| 38 | + } | ||
| 39 | + // 跳转到指定 url 地址 | ||
| 40 | + uni.navigateTo({ | ||
| 41 | + url | ||
| 42 | + }) | ||
| 43 | + }, 300) | ||
| 44 | + }, | ||
| 45 | + | ||
| 46 | + /** | ||
| 47 | + * $request云函数请求 TODO 芋艿:需要改成自己的 | ||
| 48 | + * @param {String} module | ||
| 49 | + * @param {String} operation | ||
| 50 | + * @param {Boolean} data 请求参数 | ||
| 51 | + * @param {Boolean} ext 附加参数 | ||
| 52 | + * @param {Boolean} ext.showLoading 是否显示loading状态,默认不显示 | ||
| 53 | + * @param {Boolean} ext.hideLoading 是否关闭loading状态,默认关闭 | ||
| 54 | + * @param {Boolean} ext.login 未登录拦截 | ||
| 55 | + * @param {Boolean} ext.setLoaded 加载完成是设置页面加载完毕 | ||
| 56 | + */ | ||
| 57 | + $request(module, operation, data={}, ext={}){ | ||
| 58 | + if(ext.login && !this.$util.isLogin()){ | ||
| 59 | + return; | ||
| 60 | + } | ||
| 61 | + if(ext.showLoading){ | ||
| 62 | + this.isLoading = true; | ||
| 63 | + } | ||
| 64 | + return new Promise((resolve, reject)=> { | ||
| 65 | + request(module, operation, data, ext).then(result => { | ||
| 66 | + if(ext.hideLoading !== false){ | ||
| 67 | + this.isLoading = false; | ||
| 68 | + } | ||
| 69 | + setTimeout(()=>{ | ||
| 70 | + if(this.setLoaded !== false){ | ||
| 71 | + this.loaded = true; | ||
| 72 | + } | ||
| 73 | + }, 100) | ||
| 74 | + this.$refs.confirmBtn && this.$refs.confirmBtn.stop(); | ||
| 75 | + resolve(result); | ||
| 76 | + }).catch((err) => { | ||
| 77 | + reject(err); | ||
| 78 | + }) | ||
| 79 | + }) | ||
| 80 | + }, | ||
| 81 | + imageOnLoad(data, key){ // TODO 芋艿:需要改成自己的 | ||
| 82 | + setTimeout(()=>{ | ||
| 83 | + this.$set(data, 'loaded', true); | ||
| 84 | + }, 100) | ||
| 85 | + }, | ||
| 86 | + showPopup(key){ // TODO 芋艿:需要改成自己的 | ||
| 87 | + this.$util.throttle(()=>{ | ||
| 88 | + this.$refs[key].open(); | ||
| 89 | + }, 200) | ||
| 90 | + }, | ||
| 91 | + hidePopup(key){ // TODO 芋艿:需要改成自己的 | ||
| 92 | + this.$refs[key].close(); | ||
| 93 | + }, | ||
| 94 | + stopPrevent(){}, // TODO 芋艿:需要改成自己的 | ||
| 95 | + }, | ||
| 96 | +} | ||
| 0 | \ No newline at end of file | 97 | \ No newline at end of file |
yudao-vue-ui/main.js
| 1 | import App from './App' | 1 | import App from './App' |
| 2 | 2 | ||
| 3 | +// 全局 Mixin | ||
| 4 | +import mixin from './common/mixin/mixin' | ||
| 5 | +Vue.mixin(mixin) | ||
| 6 | + | ||
| 7 | +// 全局 Util | ||
| 8 | +import { | ||
| 9 | + msg, | ||
| 10 | + isLogin, | ||
| 11 | + debounce, | ||
| 12 | + throttle, | ||
| 13 | + prePage, | ||
| 14 | + date | ||
| 15 | +} from '@/common/js/util' | ||
| 16 | +Vue.prototype.$util = { | ||
| 17 | + msg, | ||
| 18 | + isLogin, | ||
| 19 | + debounce, | ||
| 20 | + throttle, | ||
| 21 | + prePage, | ||
| 22 | + date | ||
| 23 | +} | ||
| 24 | + | ||
| 25 | +// 全局 Store | ||
| 26 | +import store from './store' | ||
| 27 | +Vue.prototype.$store = store | ||
| 28 | + | ||
| 3 | // #ifndef VUE3 | 29 | // #ifndef VUE3 |
| 4 | import Vue from 'vue' | 30 | import Vue from 'vue' |
| 5 | Vue.config.productionTip = false | 31 | Vue.config.productionTip = false |
yudao-vue-ui/pages.json
| @@ -11,7 +11,21 @@ | @@ -11,7 +11,21 @@ | ||
| 11 | "navigationBarTitleText": "我的", | 11 | "navigationBarTitleText": "我的", |
| 12 | "navigationStyle": "custom" | 12 | "navigationStyle": "custom" |
| 13 | } | 13 | } |
| 14 | - } | 14 | + }, { |
| 15 | + "path": "pages/auth/login", | ||
| 16 | + "style": { | ||
| 17 | + "navigationBarTitleText": "登录", | ||
| 18 | + "navigationStyle":"custom", | ||
| 19 | + "app-plus": { | ||
| 20 | + "animationType": "slide-in-bottom" | ||
| 21 | + } | ||
| 22 | + } | ||
| 23 | + }, { | ||
| 24 | + "path" : "pages/set/userInfo", | ||
| 25 | + "style" : { | ||
| 26 | + "navigationBarTitleText": "个人资料" | ||
| 27 | + } | ||
| 28 | + } | ||
| 15 | ], | 29 | ], |
| 16 | "globalStyle": { | 30 | "globalStyle": { |
| 17 | "navigationBarTextStyle": "black", | 31 | "navigationBarTextStyle": "black", |
yudao-vue-ui/pages/auth/login.vue
0 → 100644
| 1 | +<template> | ||
| 2 | + <view class="app"> | ||
| 3 | + <view class="left-bottom-sign"></view> | ||
| 4 | + <view class="back-btn mix-icon icon-guanbi" @click="navBack"></view> | ||
| 5 | + <view class="right-top-sign"></view> | ||
| 6 | + <view class="agreement center"> | ||
| 7 | + <text class="mix-icon icon-xuanzhong" :class="{active: agreement}" @click="checkAgreement"></text> | ||
| 8 | + <text @click="checkAgreement">请认真阅读并同意</text> | ||
| 9 | + <text class="tit" @click="navToAgreementDetail(1)">《用户服务协议》</text> | ||
| 10 | + <text class="tit" @click="navToAgreementDetail(2)">《隐私权政策》</text> | ||
| 11 | + </view> | ||
| 12 | + <view class="wrapper"> | ||
| 13 | + <view class="left-top-sign">LOGIN</view> | ||
| 14 | + <view class="welcome"> | ||
| 15 | + 欢迎回来! | ||
| 16 | + </view> | ||
| 17 | + <view class="input-content"> | ||
| 18 | + <view class="input-item"> | ||
| 19 | + <text class="tit">手机号码</text> | ||
| 20 | + <view class="row"> | ||
| 21 | + <input | ||
| 22 | + v-model="username" | ||
| 23 | + type="number" | ||
| 24 | + maxlength="11" | ||
| 25 | + placeholder="请输入手机号码" | ||
| 26 | + placeholder-style="color: #909399" | ||
| 27 | + /> | ||
| 28 | + </view> | ||
| 29 | + </view> | ||
| 30 | + <view class="input-item"> | ||
| 31 | + <text class="tit">验证码</text> | ||
| 32 | + <view class="row"> | ||
| 33 | + <input | ||
| 34 | + v-model="code" | ||
| 35 | + type="number" | ||
| 36 | + maxlength="6" | ||
| 37 | + placeholder="请输入手机验证码" | ||
| 38 | + placeholder-style="color: #909399" | ||
| 39 | + /> | ||
| 40 | + <mix-code :mobile="username" templateCode="SMS_194050994"></mix-code> | ||
| 41 | + </view> | ||
| 42 | + </view> | ||
| 43 | + </view> | ||
| 44 | + <mix-button ref="confirmBtn" text="登录" marginTop="60rpx" @onConfirm="login"></mix-button> | ||
| 45 | + | ||
| 46 | + <!-- #ifdef APP-PLUS || MP-WEIXIN --> | ||
| 47 | + <view class="other-wrapper"> | ||
| 48 | + <view class="line center"> | ||
| 49 | + <text class="tit">快捷登录</text> | ||
| 50 | + </view> | ||
| 51 | + <view class="list row"> | ||
| 52 | + <!-- #ifdef MP-WEIXIN --> | ||
| 53 | + <view class="item column center" @click="mpWxGetUserInfo"> | ||
| 54 | + <image class="icon" src="/static/icon/login-wx.png"></image> | ||
| 55 | + </view> | ||
| 56 | + <!-- #endif --> | ||
| 57 | + | ||
| 58 | + <!-- #ifdef APP-PLUS --> | ||
| 59 | + <view v-if="canUseAppleLogin && false" class="item column center" style="width: 180rpx;" @click="loginByApple"> | ||
| 60 | + <image class="icon" src="/static/icon/apple.png"></image> | ||
| 61 | + <text>Apple登录</text> | ||
| 62 | + </view> | ||
| 63 | + <view class="item column center" style="width: 180rpx;" @click="loginByWxApp"> | ||
| 64 | + <image class="icon" src="/static/icon/login-wx.png"></image> | ||
| 65 | + <text>微信登录</text> | ||
| 66 | + </view> | ||
| 67 | + <!-- #endif --> | ||
| 68 | + </view> | ||
| 69 | + </view> | ||
| 70 | + <!-- #endif --> | ||
| 71 | + </view> | ||
| 72 | + | ||
| 73 | + <mix-loading v-if="isLoading"></mix-loading> | ||
| 74 | + </view> | ||
| 75 | +</template> | ||
| 76 | + | ||
| 77 | +<script> | ||
| 78 | + import {checkStr} from '@/common/js/util' | ||
| 79 | + import loginMpWx from './mixin/login-mp-wx.js' | ||
| 80 | + import loginAppWx from './mixin/login-app-wx.js' | ||
| 81 | + import loginApple from './mixin/login-apple.js' | ||
| 82 | + export default{ | ||
| 83 | + mixins: [loginMpWx, loginAppWx, loginApple], | ||
| 84 | + data(){ | ||
| 85 | + return { | ||
| 86 | + canUseAppleLogin: false, | ||
| 87 | + agreement: true, | ||
| 88 | + username: '', | ||
| 89 | + code: '', | ||
| 90 | + } | ||
| 91 | + }, | ||
| 92 | + onLoad() { | ||
| 93 | + console.log(1); | ||
| 94 | + }, | ||
| 95 | + methods: { | ||
| 96 | + loginSuccessCallBack(data){ | ||
| 97 | + this.$util.msg('登陆成功'); | ||
| 98 | + this.$store.commit('setToken', data); | ||
| 99 | + setTimeout(()=>{ | ||
| 100 | + uni.navigateBack(); | ||
| 101 | + }, 1000) | ||
| 102 | + }, | ||
| 103 | + //手机号登录 | ||
| 104 | + async login(){ | ||
| 105 | + if(!this.agreement){ | ||
| 106 | + this.$util.msg('请阅读并同意用户服务及隐私协议'); | ||
| 107 | + this.$refs.confirmBtn.stop(); | ||
| 108 | + return; | ||
| 109 | + } | ||
| 110 | + const {username, code} = this; | ||
| 111 | + if(!checkStr(username, 'mobile')){ | ||
| 112 | + this.$util.msg('请输入正确的手机号码'); | ||
| 113 | + this.$refs.confirmBtn.stop(); | ||
| 114 | + return; | ||
| 115 | + } | ||
| 116 | + if(!checkStr(code, 'mobileCode')){ | ||
| 117 | + this.$util.msg('验证码错误'); | ||
| 118 | + this.$refs.confirmBtn.stop(); | ||
| 119 | + return; | ||
| 120 | + } | ||
| 121 | + const res = await this.$request('user', 'login', {username,code}); | ||
| 122 | + this.$refs.confirmBtn.stop(); | ||
| 123 | + | ||
| 124 | + if(res.status === 1){ | ||
| 125 | + this.loginSuccessCallBack(res.data); | ||
| 126 | + }else{ | ||
| 127 | + this.$util.msg(res.msg); | ||
| 128 | + } | ||
| 129 | + }, | ||
| 130 | + navBack(){ | ||
| 131 | + uni.navigateBack(); | ||
| 132 | + }, | ||
| 133 | + //同意协议 | ||
| 134 | + checkAgreement(){ | ||
| 135 | + this.agreement = !this.agreement; | ||
| 136 | + }, | ||
| 137 | + //打开协议 | ||
| 138 | + navToAgreementDetail(type){ | ||
| 139 | + this.navTo('/pages/public/article?param=' + JSON.stringify({ | ||
| 140 | + module: 'article', | ||
| 141 | + operation: 'getAgreement', | ||
| 142 | + data: { | ||
| 143 | + type | ||
| 144 | + } | ||
| 145 | + })) | ||
| 146 | + }, | ||
| 147 | + } | ||
| 148 | + } | ||
| 149 | +</script> | ||
| 150 | + | ||
| 151 | +<style> | ||
| 152 | + page{ | ||
| 153 | + background: #fff; | ||
| 154 | + } | ||
| 155 | +</style> | ||
| 156 | +<style scoped lang='scss'> | ||
| 157 | + .app{ | ||
| 158 | + padding-top: 15vh; | ||
| 159 | + position:relative; | ||
| 160 | + width: 100vw; | ||
| 161 | + height: 100vh; | ||
| 162 | + overflow: hidden; | ||
| 163 | + background: #fff; | ||
| 164 | + } | ||
| 165 | + .wrapper{ | ||
| 166 | + position:relative; | ||
| 167 | + z-index: 90; | ||
| 168 | + padding-bottom: 40rpx; | ||
| 169 | + } | ||
| 170 | + .back-btn{ | ||
| 171 | + position:absolute; | ||
| 172 | + left: 20rpx; | ||
| 173 | + top: calc(var(--status-bar-height) + 20rpx); | ||
| 174 | + z-index: 90; | ||
| 175 | + padding: 20rpx; | ||
| 176 | + font-size: 32rpx; | ||
| 177 | + color: #606266; | ||
| 178 | + } | ||
| 179 | + .left-top-sign{ | ||
| 180 | + font-size: 120rpx; | ||
| 181 | + color: #f8f8f8; | ||
| 182 | + position:relative; | ||
| 183 | + left: -12rpx; | ||
| 184 | + } | ||
| 185 | + .right-top-sign{ | ||
| 186 | + position:absolute; | ||
| 187 | + top: 80rpx; | ||
| 188 | + right: -30rpx; | ||
| 189 | + z-index: 95; | ||
| 190 | + | ||
| 191 | + &:before, &:after{ | ||
| 192 | + display:block; | ||
| 193 | + content:""; | ||
| 194 | + width: 400rpx; | ||
| 195 | + height: 80rpx; | ||
| 196 | + background: #b4f3e2; | ||
| 197 | + } | ||
| 198 | + &:before{ | ||
| 199 | + transform: rotate(50deg); | ||
| 200 | + border-top-right-radius: 50px; | ||
| 201 | + } | ||
| 202 | + &:after{ | ||
| 203 | + position: absolute; | ||
| 204 | + right: -198rpx; | ||
| 205 | + top: 0; | ||
| 206 | + transform: rotate(-50deg); | ||
| 207 | + border-top-left-radius: 50px; | ||
| 208 | + } | ||
| 209 | + } | ||
| 210 | + .left-bottom-sign{ | ||
| 211 | + position:absolute; | ||
| 212 | + left: -270rpx; | ||
| 213 | + bottom: -320rpx; | ||
| 214 | + border: 100rpx solid #d0d1fd; | ||
| 215 | + border-radius: 50%; | ||
| 216 | + padding: 180rpx; | ||
| 217 | + } | ||
| 218 | + .welcome{ | ||
| 219 | + position:relative; | ||
| 220 | + left: 50rpx; | ||
| 221 | + top: -90rpx; | ||
| 222 | + font-size: 46rpx; | ||
| 223 | + color: #555; | ||
| 224 | + text-shadow: 1px 0px 1px rgba(0,0,0,.3); | ||
| 225 | + } | ||
| 226 | + .input-content{ | ||
| 227 | + padding: 0 60rpx; | ||
| 228 | + } | ||
| 229 | + .input-item{ | ||
| 230 | + display:flex; | ||
| 231 | + flex-direction: column; | ||
| 232 | + align-items:flex-start; | ||
| 233 | + justify-content: center; | ||
| 234 | + padding: 0 30rpx; | ||
| 235 | + background: #f8f6fc; | ||
| 236 | + height: 120rpx; | ||
| 237 | + border-radius: 4px; | ||
| 238 | + margin-bottom: 50rpx; | ||
| 239 | + | ||
| 240 | + &:last-child{ | ||
| 241 | + margin-bottom: 0; | ||
| 242 | + } | ||
| 243 | + .row{ | ||
| 244 | + width: 100%; | ||
| 245 | + } | ||
| 246 | + .tit{ | ||
| 247 | + height: 50rpx; | ||
| 248 | + line-height: 56rpx; | ||
| 249 | + font-size: 26rpx; | ||
| 250 | + color: #606266; | ||
| 251 | + } | ||
| 252 | + input{ | ||
| 253 | + flex: 1; | ||
| 254 | + height: 60rpx; | ||
| 255 | + font-size: 30rpx; | ||
| 256 | + color: #303133; | ||
| 257 | + width: 100%; | ||
| 258 | + } | ||
| 259 | + } | ||
| 260 | + /* 其他登录方式 */ | ||
| 261 | + .other-wrapper{ | ||
| 262 | + display: flex; | ||
| 263 | + flex-direction: column; | ||
| 264 | + align-items: center; | ||
| 265 | + padding-top: 20rpx; | ||
| 266 | + margin-top: 80rpx; | ||
| 267 | + | ||
| 268 | + .line{ | ||
| 269 | + margin-bottom: 40rpx; | ||
| 270 | + | ||
| 271 | + .tit{ | ||
| 272 | + margin: 0 32rpx; | ||
| 273 | + font-size: 24rpx; | ||
| 274 | + color: #606266; | ||
| 275 | + } | ||
| 276 | + &:before, &:after{ | ||
| 277 | + content: ''; | ||
| 278 | + width: 160rpx; | ||
| 279 | + height: 0; | ||
| 280 | + border-top: 1px solid #e0e0e0; | ||
| 281 | + } | ||
| 282 | + } | ||
| 283 | + .item{ | ||
| 284 | + font-size: 24rpx; | ||
| 285 | + color: #606266; | ||
| 286 | + background-color: #fff; | ||
| 287 | + border: 0; | ||
| 288 | + | ||
| 289 | + &:after{ | ||
| 290 | + border: 0; | ||
| 291 | + } | ||
| 292 | + } | ||
| 293 | + .icon{ | ||
| 294 | + width: 90rpx; | ||
| 295 | + height: 90rpx; | ||
| 296 | + margin: 0 24rpx 16rpx; | ||
| 297 | + } | ||
| 298 | + } | ||
| 299 | + .agreement{ | ||
| 300 | + position: absolute; | ||
| 301 | + left: 0; | ||
| 302 | + bottom: 6vh; | ||
| 303 | + z-index: 1; | ||
| 304 | + width: 750rpx; | ||
| 305 | + height: 90rpx; | ||
| 306 | + font-size: 24rpx; | ||
| 307 | + color: #999; | ||
| 308 | + | ||
| 309 | + .mix-icon{ | ||
| 310 | + font-size: 36rpx; | ||
| 311 | + color: #ccc; | ||
| 312 | + margin-right: 8rpx; | ||
| 313 | + margin-top: 1px; | ||
| 314 | + | ||
| 315 | + &.active{ | ||
| 316 | + color: $base-color; | ||
| 317 | + } | ||
| 318 | + } | ||
| 319 | + .tit{ | ||
| 320 | + color: #40a2ff; | ||
| 321 | + } | ||
| 322 | + } | ||
| 323 | +</style> |
yudao-vue-ui/pages/auth/mixin/login-app-wx.js
0 → 100644
| 1 | +export default{ | ||
| 2 | + // #ifdef APP-PLUS | ||
| 3 | + methods: { | ||
| 4 | + /** | ||
| 5 | + * 微信App登录 | ||
| 6 | + * "openId": "o0yywwGWxtBCvBuE8vH4Naof0cqU", | ||
| 7 | + * "nickName": "S .", | ||
| 8 | + * "gender": 1, | ||
| 9 | + * "city": "临沂", | ||
| 10 | + * "province": "山东", | ||
| 11 | + * "country": "中国", | ||
| 12 | + * "avatarUrl": "http://thirdwx.qlogo.cn/mmopen/vi_32/xqpCtHRBBmdlf201Fykhtx7P7JcicIbgV3Weic1oOvN6iaR3tEbuu74f2fkKQWXvzK3VDgNTZzgf0g8FqPvq8LCNQ/132", | ||
| 13 | + * "unionId": "oYqy4wmMcs78x9P-tsyMeM3MQ1PU" | ||
| 14 | + */ | ||
| 15 | + loginByWxApp(userInfoData){ | ||
| 16 | + if(!this.agreement){ | ||
| 17 | + this.$util.msg('请阅读并同意用户服务及隐私协议'); | ||
| 18 | + return; | ||
| 19 | + } | ||
| 20 | + this.$util.throttle(async ()=>{ | ||
| 21 | + let [err, res] = await uni.login({ | ||
| 22 | + provider: 'weixin' | ||
| 23 | + }) | ||
| 24 | + if(err){ | ||
| 25 | + console.log(err); | ||
| 26 | + return; | ||
| 27 | + } | ||
| 28 | + uni.getUserInfo({ | ||
| 29 | + provider: 'weixin', | ||
| 30 | + success: async res=>{ | ||
| 31 | + const response = await this.$request('user', 'loginByWeixin', { | ||
| 32 | + userInfo: res.userInfo, | ||
| 33 | + }, { | ||
| 34 | + showLoading: true | ||
| 35 | + }); | ||
| 36 | + if(response.status === 0){ | ||
| 37 | + this.$util.msg(response.msg); | ||
| 38 | + return; | ||
| 39 | + } | ||
| 40 | + if(response.hasBindMobile && response.data.token){ | ||
| 41 | + this.loginSuccessCallBack({ | ||
| 42 | + token: response.data.token, | ||
| 43 | + tokenExpired: response.data.tokenExpired | ||
| 44 | + }); | ||
| 45 | + }else{ | ||
| 46 | + this.navTo('/pages/auth/bindMobile?data='+JSON.stringify(response.data)) | ||
| 47 | + } | ||
| 48 | + plus.oauth.getServices(oauthRes=>{ | ||
| 49 | + oauthRes[0].logout(logoutRes => { | ||
| 50 | + console.log(logoutRes); | ||
| 51 | + }, error => { | ||
| 52 | + console.log(error); | ||
| 53 | + }) | ||
| 54 | + }) | ||
| 55 | + }, | ||
| 56 | + fail(err) { | ||
| 57 | + console.log(err); | ||
| 58 | + } | ||
| 59 | + }) | ||
| 60 | + }) | ||
| 61 | + } | ||
| 62 | + } | ||
| 63 | + // #endif | ||
| 64 | +} | ||
| 65 | + | ||
| 66 | + | ||
| 67 | + | ||
| 68 | + | ||
| 69 | + | ||
| 70 | + | ||
| 71 | + | ||
| 72 | + | ||
| 73 | + |
yudao-vue-ui/pages/auth/mixin/login-apple.js
0 → 100644
| 1 | +export default{ | ||
| 2 | + onLoad() { | ||
| 3 | + if(this.systemInfo.platform !== 'ios'){ | ||
| 4 | + return; | ||
| 5 | + } | ||
| 6 | + const systemVersion = +this.systemInfo.system.split('.')[0]; | ||
| 7 | + if(systemVersion >= 13){ | ||
| 8 | + this.canUseAppleLogin = true; | ||
| 9 | + } | ||
| 10 | + }, | ||
| 11 | + methods: { | ||
| 12 | + //苹果登录 | ||
| 13 | + async loginByApple(){ | ||
| 14 | + /* if(!this.canUseAppleLogin){ | ||
| 15 | + this.$util.msg('系统版本过低,无法使用苹果登录'); | ||
| 16 | + return; | ||
| 17 | + } */ | ||
| 18 | + if(!this.agreement){ | ||
| 19 | + this.$util.msg('请阅读并同意用户服务及隐私协议'); | ||
| 20 | + this.$refs.confirmBtn.stop(); | ||
| 21 | + return; | ||
| 22 | + } | ||
| 23 | + uni.login({ | ||
| 24 | + provider: 'apple', | ||
| 25 | + success: loginRes=> { | ||
| 26 | + // 登录成功 | ||
| 27 | + uni.getUserInfo({ | ||
| 28 | + provider: 'apple', | ||
| 29 | + success: async userRes=> { | ||
| 30 | + console.log(userRes); | ||
| 31 | + const response = await this.$request('user', 'loginByApple', { | ||
| 32 | + authorizationCode: userRes.userInfo.authorizationCode, | ||
| 33 | + identityToken: userRes.userInfo.identityToken | ||
| 34 | + }, { | ||
| 35 | + showLoading: true | ||
| 36 | + }); | ||
| 37 | + console.log(response); | ||
| 38 | + //注销苹果登录 | ||
| 39 | + this.appleLogout(); | ||
| 40 | + console.log(response); | ||
| 41 | + if(response.status === 0){ | ||
| 42 | + this.$util.msg(response.msg); | ||
| 43 | + return; | ||
| 44 | + } | ||
| 45 | + if(response.hasBindMobile && response.data.token){ | ||
| 46 | + this.loginSuccessCallBack({ | ||
| 47 | + token: response.data.token, | ||
| 48 | + tokenExpired: response.data.tokenExpired | ||
| 49 | + }); | ||
| 50 | + }else{ | ||
| 51 | + this.navTo('/pages/auth/bindMobile?type=apple&data='+JSON.stringify(response.data)) | ||
| 52 | + } | ||
| 53 | + } | ||
| 54 | + }) | ||
| 55 | + }, | ||
| 56 | + fail: err=> { | ||
| 57 | + console.log(err); | ||
| 58 | + this.$util.msg('登录失败'); | ||
| 59 | + this.appleLogout(); | ||
| 60 | + } | ||
| 61 | + }) | ||
| 62 | + }, | ||
| 63 | + appleLogout(){ | ||
| 64 | + plus.oauth.getServices(oauthRes=>{ | ||
| 65 | + const oIndex = oauthRes.findIndex(oItem=> oItem.id === 'apple'); | ||
| 66 | + oauthRes[oIndex].logout(loRes => { | ||
| 67 | + console.log('appleLogout success=> ', loRes); | ||
| 68 | + }, loErr => { | ||
| 69 | + console.log('appleLogout error=> ', loErr); | ||
| 70 | + }) | ||
| 71 | + }) | ||
| 72 | + } | ||
| 73 | + } | ||
| 74 | +} | ||
| 75 | + | ||
| 76 | + | ||
| 77 | + | ||
| 78 | + | ||
| 79 | + | ||
| 80 | + | ||
| 81 | + | ||
| 82 | + | ||
| 83 | + |
yudao-vue-ui/pages/auth/mixin/login-mp-wx.js
0 → 100644
| 1 | +export default{ | ||
| 2 | + // #ifdef MP-WEIXIN | ||
| 3 | + data(){ | ||
| 4 | + return { | ||
| 5 | + mpCodeTimer: 0, | ||
| 6 | + mpWxCode: '', | ||
| 7 | + } | ||
| 8 | + }, | ||
| 9 | + computed: { | ||
| 10 | + timerIdent(){ | ||
| 11 | + return this.$store.state.timerIdent; | ||
| 12 | + } | ||
| 13 | + }, | ||
| 14 | + watch: { | ||
| 15 | + timerIdent(){ | ||
| 16 | + this.mpCodeTimer ++; | ||
| 17 | + if(this.mpCodeTimer % 30 === 0){ | ||
| 18 | + this.getMpWxCode(); | ||
| 19 | + } | ||
| 20 | + } | ||
| 21 | + }, | ||
| 22 | + onShow(){ | ||
| 23 | + this.getMpWxCode(); | ||
| 24 | + }, | ||
| 25 | + methods: { | ||
| 26 | + //微信小程序登录 | ||
| 27 | + mpWxGetUserInfo(){ | ||
| 28 | + if(!this.agreement){ | ||
| 29 | + this.$util.msg('请阅读并同意用户服务及隐私协议'); | ||
| 30 | + return; | ||
| 31 | + } | ||
| 32 | + | ||
| 33 | + this.$util.throttle(()=>{ | ||
| 34 | + uni.getUserProfile({ | ||
| 35 | + desc: '用于展示您的头像及昵称', | ||
| 36 | + success: async profileRes=> { | ||
| 37 | + const res = await this.$request('user', 'loginByWeixin', { | ||
| 38 | + code: this.mpWxCode, | ||
| 39 | + ...profileRes.userInfo | ||
| 40 | + }, { | ||
| 41 | + showLoading: true | ||
| 42 | + }); | ||
| 43 | + if(res.status === 0){ | ||
| 44 | + this.$util.msg(res.msg); | ||
| 45 | + return; | ||
| 46 | + } | ||
| 47 | + if(res.hasBindMobile && res.data.token){ | ||
| 48 | + this.loginSuccessCallBack({ | ||
| 49 | + token: res.data.token, | ||
| 50 | + tokenExpired: res.data.tokenExpired | ||
| 51 | + }); | ||
| 52 | + }else{ | ||
| 53 | + this.navTo('/pages/auth/bindMobile?data='+JSON.stringify(res.data)) | ||
| 54 | + } | ||
| 55 | + console.log(res) | ||
| 56 | + } | ||
| 57 | + }) | ||
| 58 | + }) | ||
| 59 | + }, | ||
| 60 | + //获取code | ||
| 61 | + getMpWxCode(){ | ||
| 62 | + uni.login({ | ||
| 63 | + provider: 'weixin', | ||
| 64 | + success: res=> { | ||
| 65 | + this.mpWxCode = res.code; | ||
| 66 | + } | ||
| 67 | + }) | ||
| 68 | + }, | ||
| 69 | + | ||
| 70 | + } | ||
| 71 | + // #endif | ||
| 72 | +} | ||
| 73 | + | ||
| 74 | + | ||
| 75 | + | ||
| 76 | + | ||
| 77 | + | ||
| 78 | + | ||
| 79 | + | ||
| 80 | + | ||
| 81 | + |
yudao-vue-ui/pages/set/userInfo.vue
0 → 100644
| 1 | +<template> | ||
| 2 | + <view class="app"> | ||
| 3 | + <view class="cell"> | ||
| 4 | + <text class="tit fill">头像</text> | ||
| 5 | + <view class="avatar-wrap" @click="chooseImage"> | ||
| 6 | + <image class="avatar" :src="tempAvatar || userInfo.avatar || '/static/icon/default-avatar.png'" mode="aspectFill"></image> | ||
| 7 | + <!-- 进度遮盖 --> | ||
| 8 | + <view | ||
| 9 | + class="progress center" | ||
| 10 | + :class="{ | ||
| 11 | + 'no-transtion': uploadProgress === 0, | ||
| 12 | + show: uploadProgress != 100 | ||
| 13 | + }" | ||
| 14 | + :style="{ | ||
| 15 | + width: uploadProgress + '%', | ||
| 16 | + height: uploadProgress + '%', | ||
| 17 | + }" | ||
| 18 | + ></view> | ||
| 19 | + </view> | ||
| 20 | + </view> | ||
| 21 | + <view class="cell b-b"> | ||
| 22 | + <text class="tit fill">昵称</text> | ||
| 23 | + <input class="input" v-model="userInfo.nickname" type="text" maxlength="8" placeholder="请输入昵称" placeholder-class="placeholder"> | ||
| 24 | + </view> | ||
| 25 | + <view class="cell b-b"> | ||
| 26 | + <text class="tit fill">性别</text> | ||
| 27 | + <view class="checkbox center" @click="changeGender(1)"> | ||
| 28 | + <text v-if="userInfo.gender == 1" class="mix-icon icon-xuanzhong"></text> | ||
| 29 | + <text v-else class="mix-icon icon-yk_yuanquan"></text> | ||
| 30 | + <text>男</text> | ||
| 31 | + </view> | ||
| 32 | + <view class="checkbox center" @click="changeGender(2)"> | ||
| 33 | + <text v-if="userInfo.gender == 2" class="mix-icon icon-xuanzhong"></text> | ||
| 34 | + <text v-else class="mix-icon icon-yk_yuanquan"></text> | ||
| 35 | + <text>女</text> | ||
| 36 | + </view> | ||
| 37 | + </view> | ||
| 38 | + | ||
| 39 | + <mix-button ref="confirmBtn" text="保存资料" marginTop="80rpx" @onConfirm="confirm"></mix-button> | ||
| 40 | + </view> | ||
| 41 | +</template> | ||
| 42 | + | ||
| 43 | +<script> | ||
| 44 | + export default { | ||
| 45 | + data() { | ||
| 46 | + return { | ||
| 47 | + uploadProgress: 100, //头像上传进度 | ||
| 48 | + tempAvatar: '', | ||
| 49 | + userInfo: {}, | ||
| 50 | + } | ||
| 51 | + }, | ||
| 52 | + computed: { | ||
| 53 | + curUserInfo(){ | ||
| 54 | + return this.$store.state.userInfo | ||
| 55 | + } | ||
| 56 | + }, | ||
| 57 | + watch: { | ||
| 58 | + curUserInfo(curUserInfo){ | ||
| 59 | + const {avatar, nickname, gender} = curUserInfo; | ||
| 60 | + this.userInfo = {avatar, nickname, gender,}; | ||
| 61 | + } | ||
| 62 | + }, | ||
| 63 | + onLoad() { | ||
| 64 | + const {avatar, nickname, gender, anonymous} = this.curUserInfo; | ||
| 65 | + this.userInfo = {avatar, nickname, gender}; | ||
| 66 | + }, | ||
| 67 | + methods: { | ||
| 68 | + //提交修改 | ||
| 69 | + async confirm(){ | ||
| 70 | + const {uploadProgress, userInfo, curUserInfo} = this; | ||
| 71 | + let isUpdate = false; | ||
| 72 | + for(let key in userInfo){ | ||
| 73 | + if(userInfo[key] !== curUserInfo[key]){ | ||
| 74 | + isUpdate = true; | ||
| 75 | + break; | ||
| 76 | + } | ||
| 77 | + } | ||
| 78 | + if (isUpdate === false) { | ||
| 79 | + this.$util.msg('信息未修改'); | ||
| 80 | + this.$refs.confirmBtn.stop(); | ||
| 81 | + return; | ||
| 82 | + } | ||
| 83 | + if (!userInfo.avatar) { | ||
| 84 | + this.$util.msg('请上传头像'); | ||
| 85 | + this.$refs.confirmBtn.stop(); | ||
| 86 | + return; | ||
| 87 | + } | ||
| 88 | + if (uploadProgress !== 100) { | ||
| 89 | + this.$util.msg('请等待头像上传完毕'); | ||
| 90 | + this.$refs.confirmBtn.stop(); | ||
| 91 | + return; | ||
| 92 | + } | ||
| 93 | + if (!userInfo.nickname) { | ||
| 94 | + this.$util.msg('请输入您的昵称'); | ||
| 95 | + this.$refs.confirmBtn.stop(); | ||
| 96 | + return; | ||
| 97 | + } | ||
| 98 | + if (!userInfo.gender) { | ||
| 99 | + this.$util.msg('请选择您的性别'); | ||
| 100 | + this.$refs.confirmBtn.stop(); | ||
| 101 | + return; | ||
| 102 | + } | ||
| 103 | + const res = await this.$request('user', 'update', userInfo); | ||
| 104 | + this.$refs.confirmBtn.stop(); | ||
| 105 | + this.$util.msg(res.msg); | ||
| 106 | + if(res.status === 1){ | ||
| 107 | + this.$store.dispatch('getUserInfo'); //刷新用户信息 | ||
| 108 | + setTimeout(()=>{ | ||
| 109 | + uni.navigateBack(); | ||
| 110 | + }, 1000) | ||
| 111 | + } | ||
| 112 | + }, | ||
| 113 | + //选择头像 | ||
| 114 | + chooseImage(){ | ||
| 115 | + uni.chooseImage({ | ||
| 116 | + count: 1, | ||
| 117 | + success: res=> { | ||
| 118 | + uni.navigateTo({ | ||
| 119 | + url: `./cutImage/cut?src=${res.tempFilePaths[0]}` | ||
| 120 | + }); | ||
| 121 | + } | ||
| 122 | + }); | ||
| 123 | + }, | ||
| 124 | + //裁剪回调 | ||
| 125 | + async setAvatar(filePath){ | ||
| 126 | + this.tempAvatar = filePath; | ||
| 127 | + this.uploadProgress = 0; | ||
| 128 | + const result = await uniCloud.uploadFile({ | ||
| 129 | + filePath: filePath, | ||
| 130 | + cloudPath: + new Date() + ('000000' + Math.floor(Math.random() * 999999)).slice(-6) + '.jpg', | ||
| 131 | + onUploadProgress: e=> { | ||
| 132 | + this.uploadProgress = Math.round( | ||
| 133 | + (e.loaded * 100) / e.total | ||
| 134 | + ); | ||
| 135 | + } | ||
| 136 | + }); | ||
| 137 | + if(!result.fileID){ | ||
| 138 | + this.$util.msg('头像上传失败'); | ||
| 139 | + return; | ||
| 140 | + } | ||
| 141 | + if(typeof uniCloud.getTempFileURL === 'undefined'){ | ||
| 142 | + this.userInfo.avatar = result.fileID; | ||
| 143 | + }else{ | ||
| 144 | + const tempFiles = await uniCloud.getTempFileURL({ | ||
| 145 | + fileList: [result.fileID] | ||
| 146 | + }) | ||
| 147 | + const tempFile = tempFiles.fileList[0]; | ||
| 148 | + if(tempFile.download_url || tempFile.fileID){ | ||
| 149 | + this.userInfo.avatar = tempFile.download_url || tempFile.fileID; | ||
| 150 | + }else{ | ||
| 151 | + this.$util.msg('头像上传失败'); | ||
| 152 | + } | ||
| 153 | + } | ||
| 154 | + }, | ||
| 155 | + //修改性别 | ||
| 156 | + changeGender(gender){ | ||
| 157 | + this.$set(this.userInfo, 'gender', gender) | ||
| 158 | + } | ||
| 159 | + } | ||
| 160 | + } | ||
| 161 | +</script> | ||
| 162 | + | ||
| 163 | +<style scoped lang="scss"> | ||
| 164 | + .app{ | ||
| 165 | + padding-top: 16rpx; | ||
| 166 | + } | ||
| 167 | + .cell{ | ||
| 168 | + display: flex; | ||
| 169 | + align-items: center; | ||
| 170 | + min-height: 110rpx; | ||
| 171 | + padding: 0 40rpx; | ||
| 172 | + | ||
| 173 | + &:first-child{ | ||
| 174 | + margin-bottom: 10rpx; | ||
| 175 | + } | ||
| 176 | + &:after{ | ||
| 177 | + left: 40rpx; | ||
| 178 | + right: 40rpx; | ||
| 179 | + border-color: #d8d8d8; | ||
| 180 | + } | ||
| 181 | + .tit{ | ||
| 182 | + font-size: 30rpx; | ||
| 183 | + color: #333; | ||
| 184 | + } | ||
| 185 | + .avatar-wrap{ | ||
| 186 | + width: 120rpx; | ||
| 187 | + height: 120rpx; | ||
| 188 | + position: relative; | ||
| 189 | + border-radius: 100rpx; | ||
| 190 | + overflow: hidden; | ||
| 191 | + | ||
| 192 | + .avatar{ | ||
| 193 | + width: 100%; | ||
| 194 | + height: 100%; | ||
| 195 | + border-radius: 100rpx; | ||
| 196 | + } | ||
| 197 | + .progress{ | ||
| 198 | + position: absolute; | ||
| 199 | + left: 50%; | ||
| 200 | + top: 50%; | ||
| 201 | + transform: translate(-50%, -50%); | ||
| 202 | + width: 100rpx; | ||
| 203 | + height: 100rpx; | ||
| 204 | + box-shadow: rgba(0,0,0,.6) 0px 0px 0px 2005px; | ||
| 205 | + border-radius: 100rpx; | ||
| 206 | + transition: .5s; | ||
| 207 | + opacity: 0; | ||
| 208 | + | ||
| 209 | + &.no-transtion{ | ||
| 210 | + transition: 0s; | ||
| 211 | + } | ||
| 212 | + &.show{ | ||
| 213 | + opacity: 1; | ||
| 214 | + } | ||
| 215 | + } | ||
| 216 | + } | ||
| 217 | + .input{ | ||
| 218 | + flex: 1; | ||
| 219 | + text-align: right; | ||
| 220 | + font-size: 28rpx; | ||
| 221 | + color: #333; | ||
| 222 | + } | ||
| 223 | + switch{ | ||
| 224 | + margin: 0; | ||
| 225 | + transform: scale(0.8) translateX(10rpx); | ||
| 226 | + transform-origin: center right; | ||
| 227 | + } | ||
| 228 | + .tip{ | ||
| 229 | + margin-left: 20rpx; | ||
| 230 | + font-size: 28rpx; | ||
| 231 | + color: #999; | ||
| 232 | + } | ||
| 233 | + .checkbox{ | ||
| 234 | + padding: 12rpx 0 12rpx 40rpx; | ||
| 235 | + font-size: 28rpx; | ||
| 236 | + color: #333; | ||
| 237 | + | ||
| 238 | + .mix-icon{ | ||
| 239 | + margin-right: 12rpx; | ||
| 240 | + font-size: 36rpx; | ||
| 241 | + color: #ccc; | ||
| 242 | + } | ||
| 243 | + .icon-xuanzhong{ | ||
| 244 | + color: $base-color; | ||
| 245 | + } | ||
| 246 | + } | ||
| 247 | + } | ||
| 248 | +</style> |
yudao-vue-ui/pages/tabbar/user.vue
| @@ -59,7 +59,7 @@ | @@ -59,7 +59,7 @@ | ||
| 59 | <!-- <mix-list-cell icon="icon-shoucang_xuanzhongzhuangtai" iconColor="#54b4ef" title="我的收藏" @onClick="navTo('/pages/favorite/favorite', {login: true})"></mix-list-cell> --> | 59 | <!-- <mix-list-cell icon="icon-shoucang_xuanzhongzhuangtai" iconColor="#54b4ef" title="我的收藏" @onClick="navTo('/pages/favorite/favorite', {login: true})"></mix-list-cell> --> |
| 60 | <!-- <mix-list-cell icon="icon-pinglun-copy" iconColor="#ee883b" title="意见反馈" @onClick="navTo('/pages/feedback/feedback', {login: true})"></mix-list-cell> --> | 60 | <!-- <mix-list-cell icon="icon-pinglun-copy" iconColor="#ee883b" title="意见反馈" @onClick="navTo('/pages/feedback/feedback', {login: true})"></mix-list-cell> --> |
| 61 | <!-- <mix-list-cell icon="icon-shezhi1" iconColor="#37b0fb" title="设置" border="" @onClick="navTo('/pages/set/set', {login: true})"></mix-list-cell> --> | 61 | <!-- <mix-list-cell icon="icon-shezhi1" iconColor="#37b0fb" title="设置" border="" @onClick="navTo('/pages/set/set', {login: true})"></mix-list-cell> --> |
| 62 | - <mix-list-cell icon="icon-bianji" iconColor="#5fcda2" title="个人信息" border="" @onClick="navTo('/pages/set/set', {login: true})"></mix-list-cell> | 62 | + <mix-list-cell icon="icon-bianji" iconColor="#5fcda2" title="个人信息" border="" @onClick="navTo('/pages/set/userInfo', {login: true})"></mix-list-cell> |
| 63 | <mix-list-cell icon="icon-shezhi1" iconColor="#37b0fb" title="账号安全" border="" @onClick="navTo('/pages/set/set', {login: true})"></mix-list-cell> | 63 | <mix-list-cell icon="icon-shezhi1" iconColor="#37b0fb" title="账号安全" border="" @onClick="navTo('/pages/set/set', {login: true})"></mix-list-cell> |
| 64 | </view> | 64 | </view> |
| 65 | </view> | 65 | </view> |
yudao-vue-ui/store/index.js
0 → 100644
| 1 | +import Vue from 'vue' | ||
| 2 | +import Vuex from 'vuex' | ||
| 3 | +// import {request} from '@/common/js/request' | ||
| 4 | + | ||
| 5 | +Vue.use(Vuex) | ||
| 6 | + | ||
| 7 | +const store = new Vuex.Store({ | ||
| 8 | + state: { | ||
| 9 | + openExamine: false, // 是否开启审核状态。用于小程序、App 等审核时,关闭部分功能。TODO 芋艿:暂时没找到刷新的地方 | ||
| 10 | + token: '', // 用户身份 Token | ||
| 11 | + userInfo: {}, // 用户基本信息 | ||
| 12 | + timerIdent: false, // 全局 1s 定时器,只在全局开启一个,所有需要定时执行的任务监听该值即可,无需额外开启 TODO 芋艿:需要看看 | ||
| 13 | + orderCount: {}, // 订单数量 | ||
| 14 | + }, | ||
| 15 | + getters: { | ||
| 16 | + hasLogin(state){ | ||
| 17 | + return !!state.token; | ||
| 18 | + } | ||
| 19 | + }, | ||
| 20 | + mutations: { | ||
| 21 | + //更新state数据 | ||
| 22 | + setStateAttr(state, param){ | ||
| 23 | + if(param instanceof Array){ | ||
| 24 | + for(let item of param){ | ||
| 25 | + state[item.key] = item.val; | ||
| 26 | + } | ||
| 27 | + }else{ | ||
| 28 | + state[param.key] = param.val; | ||
| 29 | + } | ||
| 30 | + }, | ||
| 31 | + //更新token | ||
| 32 | + setToken(state, data){ | ||
| 33 | + const {token, tokenExpired} = data; | ||
| 34 | + state.token = token; | ||
| 35 | + uni.setStorageSync('uniIdToken', token); | ||
| 36 | + uni.setStorageSync('tokenExpired', tokenExpired); | ||
| 37 | + this.dispatch('getUserInfo'); //更新用户信息 | ||
| 38 | + this.dispatch('getCartCount');//更新购物车数量 | ||
| 39 | + uni.$emit('refreshCart');//刷新购物车 | ||
| 40 | + this.dispatch('getOrderCount'); //更新订单数量 | ||
| 41 | + }, | ||
| 42 | + // 退出登录 | ||
| 43 | + logout(state) { | ||
| 44 | + state.token = ''; | ||
| 45 | + uni.removeStorageSync('uniIdToken'); | ||
| 46 | + this.dispatch('getCartCount');//更新购物车数量 | ||
| 47 | + uni.$emit('refreshCart');//刷新购物车 | ||
| 48 | + this.dispatch('getOrderCount'); //更新订单数量 | ||
| 49 | + setTimeout(()=>{ | ||
| 50 | + state.userInfo = {}; | ||
| 51 | + }, 1100) | ||
| 52 | + }, | ||
| 53 | + }, | ||
| 54 | + actions: { | ||
| 55 | + //更新用户信息 | ||
| 56 | + async getUserInfo({state, commit}){ | ||
| 57 | + const res = await request('user', 'get', {}, { | ||
| 58 | + checkAuthInvalid: false | ||
| 59 | + }); | ||
| 60 | + if(res.status === 1){ | ||
| 61 | + const userInfo = res.data; | ||
| 62 | + commit('setStateAttr', { | ||
| 63 | + key: 'userInfo', | ||
| 64 | + val: userInfo | ||
| 65 | + }) | ||
| 66 | + } | ||
| 67 | + }, | ||
| 68 | + //更新用户订单数量 | ||
| 69 | + async getOrderCount({state, commit}){ | ||
| 70 | + let data = { | ||
| 71 | + c0: 0, | ||
| 72 | + c1: 0, | ||
| 73 | + c2: 0, | ||
| 74 | + c3: 0 | ||
| 75 | + } | ||
| 76 | + if(state.token){ | ||
| 77 | + try { | ||
| 78 | + const res = await request('order', 'getOrderCount'); | ||
| 79 | + data = res; | ||
| 80 | + }catch (err){ | ||
| 81 | + console.error('更新用户订单数量 => ', err); | ||
| 82 | + } | ||
| 83 | + } | ||
| 84 | + commit('setStateAttr', { | ||
| 85 | + key: 'orderCount', | ||
| 86 | + val: data | ||
| 87 | + }) | ||
| 88 | + } | ||
| 89 | + } | ||
| 90 | +}) | ||
| 91 | + | ||
| 92 | + | ||
| 93 | +export default store |