UNPKG

@jianghujs/jianghu

Version:

Progressive Enterprise Framework

265 lines (242 loc) 8.7 kB
{% extends 'template/jhTemplateV4.html'%} {% block vueTemplate %} <script type="text/html" id="app-template"> <div> <v-app> <v-main> <v-row class="align-center" style="height: 100vh"> <v-col cols="12" align="center"> <div class="mb-10 text-h7 font-weight-bold success--text"><$ ctx.app.config.appTitle $></div> <v-card class="login-form-card pa-8"> <v-card-text class="pa-0"> <div class="title">登录您的账户</div> <v-form ref="loginForm" lazy-validation> <!-- 表单 [注:登录表单包含密码输入框,chrome密码自动填充的时候会与vuetify的v-input组件样式冲突,使用原生input避免冲突] --> <v-row class="my-0"> <v-col cols="12"> <input class="jh-cus-input" v-model="userId" placeholder="用户名"/> </v-col> <v-col cols="12"> <div class="password-wrapper"> <input class="jh-cus-input" v-model="password" :type="isPasswordShown ? 'text' : 'password'" data-type="password" @keyup.enter.exact="doUiAction('login')" placeholder="密码" /> <v-icon @click="isPasswordShown = !isPasswordShown" small class="mdi-eye">{{isPasswordShown ? 'mdi-eye-off-outline' : 'mdi-eye-outline'}}</v-icon> </div> </v-col> <v-col cols="12"> <v-checkbox class="jh-v-input" dense single-line filled v-model="isRememberPassword" color="success" label="记住密码"/> </v-col> </v-row> <!-- 操作按钮 --> <v-row class="my-0 px-3"> <v-btn block color="success" small @click="doUiAction('login')">登录</v-btn> <v-btn block color="success" small outlined class="mt-2" @click="toWXLoginUrl" >微信登录</v-btn> </v-row> </v-form> </v-card-text> <!-- v-overlay --> <v-overlay :value="loading" color="#eaeaea"> <v-progress-circular indeterminate color="success"></v-progress-circular> </v-overlay> </v-card> </v-col> </v-row> </v-main> </v-app> <jh-toast/> <jh-mask/> <jh-confirm-dialog/> </div> </script> <div id="app"> </div> {% endblock %} {% block vueScript %} <!-- 加载页面组件 >>>>>>>>>>>>> --> {% include 'utility/jianghuJs/prepareDeviceIdV4.html' %} <!-- <<<<<<<<<<<<< 加载页面组件 --> <script type="module"> new Vue({ el: '#app', template: '#app-template', vueComponent: 'page', vuetify: new Vuetify(), components: {}, data() { return { userId: '', password: '', isPasswordShown: false, isRememberPassword: true, loading: false, }; }, mounted() { this.doUiAction('getUrlObj'); }, methods: { async doUiAction(uiActionId, uiActionData) { switch (uiActionId) { case 'getUrlObj': await this.getUrlObj(); break; case 'login': await this.prepareLoginData(); await this.doLogin(); await this.setLocalStorage(); await this.redirectToPreLoginURL(); break; case 'wxLogin': await this.prepareLoginData(); await this.doWxLogin(); await this.setLocalStorage(); await this.redirectToPreLoginURL(); break; default: console.error("[doUiAction] uiActionId not find", { uiActionId }); break; } }, toWXLoginUrl() { const redirectUrl = '<$ ctx.app.config.wechat.redirectUrl $>'; const appId = '<$ ctx.app.config.wechat.appId $>'; const authUrl = '<$ ctx.app.config.wechat.authUrl $>'; if (!redirectUrl || !appId || !authUrl) { window.vtoast.fail('微信登录尚未开放'); return; } let currentUrl = redirectUrl + location.pathname; location.replace(`${authUrl}?appid=${appId}&redirect_uri=${encodeURIComponent(currentUrl)}&response_type=code&scope=snsapi_userinfo&state=#wechat_redirect`); }, // ---------- getUrlObj uiAction >>>>>>>>>> -------- async getUrlObj() { const urlObj = new URLSearchParams(location.search); if (urlObj.get('errorReason')) { window.vtoast.fail(urlObj.get('errorReason')); } this.redirectUrl = urlObj.get('redirectUrl'); // code登录 if (urlObj.get('code')) { this.doUiAction('wxLogin') } }, // ---------- <<<<<<<<<<< getUrlObj uiAction -------- // ---------- login uiAction >>>>>>>>>> -------- async prepareLoginData() { this.deviceId = window.deviceId; this.userId = _.replace(this.userId, /\s+/g, '');; this.password = _.toString(this.password); }, async doLogin() { try { const resultData = (await window.jianghuAxios({ data: { appData: { pageId: 'login', actionId: 'passwordLogin', actionData: { userId: this.userId, password: this.password, deviceId: this.deviceId }, } } })).data.appData.resultData; this.loginResult = resultData; window.vtoast.success('登录成功'); } catch (error) { const { errorCode, errorReason } = error || {}; if (errorCode) { window.vtoast.fail(errorReason); throw new Error("登录失败", { errorCode, errorReason }); } else { window.vtoast.fail('登录失败'); throw new Error("登录失败"); } } }, async doWxLogin() { this.tip = '微信登录中...' this.loading = true const urlParams = new URLSearchParams(location.search); const code = urlParams.get('code') try { const resultData = (await window.jianghuAxios({ data: { appData: { pageId: 'login', actionId: 'wxLogin', actionData: { code, deviceId: this.deviceId }, } } })).data.appData.resultData; console.log(resultData) this.loginResult = resultData; window.vtoast.success('登录成功'); } catch (error) { const { errorCode, errorReason } = error || {}; if (errorCode) { window.vtoast.fail(errorReason); throw new Error("登录失败", { errorCode, errorReason }); } else { window.vtoast.fail('登录失败'); throw new Error("登录失败"); } this.loading = false } }, async setLocalStorage() { localStorage.setItem(`${window.appInfo.appId}_authToken`, this.loginResult.authToken); localStorage.setItem(`${window.appInfo.appId}_userId`, this.loginResult.userId); localStorage.setItem(`${window.appInfo.appId}_deviceId`, this.deviceId); }, async redirectToPreLoginURL() { let redirectTo = `/${window.appInfo.appId}`; if (this.redirectUrl) { redirectTo = decodeURIComponent(this.redirectUrl); } window.location.href = redirectTo; } // ---------- <<<<<<<<<<< login uiAction -------- } }); </script> <style scoped> .login-form-card { width: 400px; } /* ---------- 输入框 >>>>>>>>>> -------- */ .jh-cus-input { border: 1px solid rgba(0, 0, 0, .06); width: 100%; height: 32px; border-radius: 6px; padding: 0 12px; color: #5E6278 !important; outline: none; font-size: 13px !important; } .jh-cus-input:focus, .jh-cus-input:focus-visible, input:focus-visible { border: thin solid var(--cPrimaryColor) !important; } /* ---------- <<<<<<<<<<< 输入框 -------- */ /* ---------- 密码框 >>>>>>>>>> -------- */ .password-wrapper { position: relative; } .password-wrapper .mdi-eye { position: absolute; right: 8px; top: 8px; } /* ---------- <<<<<<<<<<< 密码框 -------- */ </style> {% endblock %}