UNPKG

egg-born-front

Version:
460 lines (459 loc) 14.4 kB
const F7Locales = { dialog: ['buttonCancel', 'buttonOk', 'passwordPlaceholder', 'preloaderTitle', 'progressTitle', 'usernamePlaceholder'], picker: ['toolbarCloseText'], colorPicker: ['navbarTitleText', 'navbarCloseText'], calendar: ['timePickerPlaceholder', 'headerPlaceholder', 'toolbarCloseText'], smartSelect: [ 'pageBackLinkText', 'popupCloseLinkText', 'sheetCloseLinkText', 'searchbarPlaceholder', 'searchbarDisableText', ], }; export default { render(c) { const children = []; // layout if (this.layout) { children.push( c(this.layout, { ref: 'layout', }) ); } // error if (this.error) { const elError = c('div', { staticClass: 'eb-breathe' }); const elButton = c('f7-button', { attrs: { text: this.$text('Try Again'), }, on: { click: this.onClickTryAgain, }, }); const elErrorContainer = c( 'div', { staticClass: 'eb-init-error-container', }, [c('div', [elError, elButton])] ); children.push(elErrorContainer); } // app const app = c( 'f7-app', { staticClass: '', props: { params: this.$root.$options.framework7 }, }, children ); return c('div', [app]); }, data() { return { layout: null, sticky: true, error: null, layoutPrefer: null, layoutPreferNotification: null, layoutPreferSwitchButton: null, layoutInstance: null, reloading: false, }; }, created() { this.onResize = this.$meta.util.debounce(() => { this.resize(); }, 300); }, beforeDestroy() { this.$f7.off('resize', this.onResize); this._clearLayoutPreferNotification(); }, mounted() { this.$f7ready(() => { this.ready(); }); }, methods: { ready() { if (this.$f7.device.ie) { this.$f7.dialog.alert('Supports All Modern Browsers Except IE'); return; } // hash init const hashInit = this.$meta.util.parseHash(location.hash); if (hashInit && hashInit !== '/') this.$store.commit('auth/setHashInit', hashInit); // on resize this.$f7.on('resize', this.onResize); // auth echo init this._authEchoInit(); }, setLayoutInstance(layoutInstance) { this.layoutInstance = layoutInstance; }, clearLayoutInstance(layoutInstance) { if (this.layoutInstance === layoutInstance) { this.layoutInstance = null; } }, getLayoutInstance() { return this.layoutInstance; }, _clearLayoutPreferNotification() { this.layoutPrefer = null; if (this.layoutPreferSwitchButton) { this.layoutPreferSwitchButton.off('click'); this.layoutPreferSwitchButton = null; } if (this.layoutPreferNotification) { if (!this.layoutPreferNotification.destroyed) { this.layoutPreferNotification.close(); } this.layoutPreferNotification = null; } }, _calcLayout() { // layout prefer const layoutPrefer = this._calcLayoutPrefer(); // layout real let layoutReal; if (this.sticky && this.layout) { layoutReal = this.layout; } else { layoutReal = layoutPrefer; } // notification if (layoutPrefer === layoutReal) { // force clear layoutPrefer and notification this._clearLayoutPreferNotification(); } else { if (this.layoutPrefer !== layoutPrefer) { // force clear layoutPrefer and notification this._clearLayoutPreferNotification(); this.layoutPrefer = layoutPrefer; this._showNotificationLayoutPrefer({ layoutPrefer }); } } // ok return layoutReal; }, async _showNotificationLayoutPrefer({ layoutPrefer }) { // options const title = this.$text(layoutPrefer === 'pc' ? 'AppLayoutSwitchPromptPC' : 'AppLayoutSwitchPromptMobile'); const icon = await this.$meta.util.combineIcon({ f7: '::info-circle', size: 16 }); const options = { icon, title, text: `<div><button class="button AppLayoutSwitchNow">${this.$text('Switch Now')}</button></div>`, closeButton: true, closeOnClick: false, swipeToClose: false, on: { closed(notification) { notification.destroy(); }, }, }; // closeTimeout const closeTimeout = this.$meta.config.layout.notification.closeTimeout; if (closeTimeout !== -1) { options.closeTimeout = closeTimeout; } this.layoutPreferNotification = this.$f7.notification.create(options); this.layoutPreferNotification.open(); this.layoutPreferSwitchButton = this.$$('.AppLayoutSwitchNow'); this.layoutPreferSwitchButton.on('click', () => { this._switchPreferLayout(); }); }, async _showNotificationError({ title }) { const icon = await this.$meta.util.combineIcon({ f7: '::cross-circle', size: 16 }); const notification = this.$f7.notification.create({ icon, title, closeTimeout: 3000, }); notification.open(); }, _switchPreferLayout() { if (!this.layoutPrefer) return; // set layout this.setLayout(this.layoutPrefer); // force clear layoutPrefer and notification this._clearLayoutPreferNotification(); }, _calcLayoutPrefer() { const breakpoint = this.$meta.config.layout.breakpoint; const windowWidth = window.document.documentElement.clientWidth; const windowHeight = window.document.documentElement.clientHeight; let layout = windowWidth < windowHeight || windowWidth <= breakpoint ? 'mobile' : 'pc'; if (!this._getLayoutItem(layout)) { layout = layout === 'pc' ? 'mobile' : 'pc'; } return layout; }, resize() { // layout const layout = this._calcLayout(); // set this.setLayout(layout); }, setLayout(layout) { // check if switch if (this.layout === layout) { const component = this.getLayoutInstance(); if (component) component.onResize(); } else { // load module layout this.$meta.module.use(this._getLayoutItem(layout).module, module => { this.$options.components[layout] = module.options.components[this._getLayoutItem(layout).component]; // clear router history this.$meta.util.clearRouterHistory(); // set html css layout this._setHtmlCSSLayout(layout); // ready this.layout = layout; }); } }, async reload(ops) { if (this.reloading) return; this.reloading = true; try { // ops ops = ops || { echo: false, hash: null }; // hash if (ops.hash && ops.hash !== '/') this.$store.commit('auth/setHashInit', ops.hash); // reload this.$store.commit('auth/setReload', true); // echo if (ops.echo) { await this._authEcho(); this._reloadLayout(); } else { this._reloadLayout(); } } finally { this.reloading = false; } }, async _authEchoInit() { await this._authEcho(); // resize this.resize(); }, _setTheme(theme) { return this.$meta.theme.set(theme); }, _setHtmlCSSLayout(layout) { const $html = this.$$('html'); $html.removeClass(`eb-layout-${layout === 'pc' ? 'mobile' : 'pc'}`); $html.addClass(`eb-layout-${layout}`); }, _setHtmlCSSAuthStatus() { const loggedIn = this.$store.state.auth.loggedIn; const $html = this.$$('html'); $html.removeClass(`eb-user-${loggedIn ? 'anonymous' : 'authenticated'}`); $html.addClass(`eb-user-${loggedIn ? 'authenticated' : 'anonymous'}`); }, async _setLocaleModules(localeModules) { if (!localeModules || localeModules.length === 0) return; const promises = []; for (const localeModule of localeModules) { promises.push(this.$meta.module.use(localeModule)); } return await Promise.all(promises); }, async _authEcho() { try { // get auth first const locale = this.$meta.util.getLocale(); const data = await this.$api.post(`/a/base/auth/echo?locale=${locale}`); // instance this.$store.commit('auth/setInstance', data.instance); // loginInfo this.$store.commit('auth/setLoginInfo', data); // clientId this.$store.commit('auth/setClientId', data.clientId); // login, should after setClientId this.$store.commit('auth/login', { loggedIn: data.user.agent.anonymous === 0, user: data.user, }); // title window.document.title = this.$store.getters['auth/title']; // check if need activation this._checkActivation(); // set locale resource this._setLocaleResource(); // set auth status this._setHtmlCSSAuthStatus(); // theme await this._setTheme(data.config.theme); // localeModules await this._setLocaleModules(data.config.localeModules); // uniform messages const action = { actionModule: 'a-message', actionComponent: 'uniform', name: 'initialize', }; await this.$meta.util.performAction({ ctx: this, action }); // error this.error = null; } catch (err) { // err this.error = err.message; this.layout = null; // force to null this._showNotificationError({ title: err.message }); // should throw error throw err; } }, _reloadLayout() { const layout = this.layout; this.layout = null; this.$nextTick(() => { // clear router history this.$meta.util.clearRouterHistory(); // restore layout this.layout = layout; }); }, _setLocaleResource() { for (const f7Component in F7Locales) { const component = this.$f7.params[f7Component]; const locales = F7Locales[f7Component]; for (const key of locales) { component[key] = this.$text(component[key]); } } }, _checkActivation() { // const hashInit = this.$store.state.auth.hashInit; // should not return, as cause 403 when open hashInit // if (hashInit) return; // const userAgent = this.$store.state.auth.user.agent; const configBase = this.$meta.config.modules['a-base']; const account = configBase.account; // if (userAgent.anonymous) return; if (userAgent.activated || !account.needActivation) return; // const way = this._chooseActivationWay(account); if (!way) return; // let url = way.url; // need not check hashInit valid if (hashInit) { url = this.$meta.util.combineQueries(url, { returnTo: hashInit, }); } this.$store.commit('auth/setHashInit', url); }, _chooseActivationWay(account) { const ways = account.activationWays.split(','); for (const way of ways) { if (way === 'email' && account.url.emailConfirm) return { way, url: account.url.emailConfirm }; if (way === 'mobile' && account.url.mobileVerify) return { way, url: account.url.mobileVerify }; } return null; }, _getLayoutItem(layout) { return this.$meta.config.layout.items[layout]; }, _getLayoutModuleConfig() { return this.getLayoutInstance().layoutConfig; }, _getUrlLogin() { const configLayout = this._getLayoutModuleConfig(); return configLayout.login; }, _checkIfPasswordReset() { const hashInit = this.$store.state.auth.hashInit; if (!hashInit) return false; const configBase = this.$meta.config.modules['a-base']; const account = configBase.account; const url = account && account.url.passwordReset; if (!url) return false; return hashInit.indexOf(url) > -1; }, checkIfNeedOpenLogin() { const configLayout = this._getLayoutModuleConfig(); return configLayout.loginOnStart === true && !this.$store.state.auth.loggedIn && !this._checkIfPasswordReset(); }, popupHashInit() { // const hashInit = this.$store.state.auth.hashInit; this.$store.commit('auth/setHashInit', null); // if (this._hashInitValid(hashInit)) return hashInit; return null; }, _hashInitValid(hashInit) { const urlLogin = this._getUrlLogin(); return hashInit && hashInit !== '/' && hashInit !== urlLogin; }, toLogin({ url, module, path, state, hash }) { // hash hash = hash || this.popupHashInit(); // url let toApiPage = true; if (!url) { url = this.$meta.util.combineFetchPath(module, path); } else { if (url.indexOf('/api/') === 0) { url = `${this.$meta.config.api.baseURL}${url}`; } else { toApiPage = false; } } url = this.$meta.util.combineQueries(url, { state: state || 'login', returnTo: this.$meta.util.combineHash(hash), 'x-scene': this.$meta.config.scene, }); // go if (toApiPage) { location.assign(url); } else { this.getLayoutInstance().navigate(url); } }, openLogin(routeTo, options) { // hash init let hashInit; if (!routeTo || typeof routeTo === 'string') { hashInit = routeTo; } else if (!routeTo.url || typeof routeTo.url === 'string') { hashInit = routeTo.url; } else { hashInit = routeTo.url.url; } if (hashInit && hashInit !== '/') this.$store.commit('auth/setHashInit', hashInit); // query const query = routeTo && routeTo.query; // url let url = this._getUrlLogin(); url = query ? this.$meta.util.combineQueries(url, query) : url; // navigate this.getLayoutInstance().navigate(url, options); }, onClickTryAgain() { this.error = null; this._authEchoInit(); }, async logout() { await this.$api.post('/a/base/auth/logout'); await this.reload({ echo: true }); }, }, };