<template> <modal-inner class="modal__inner-1--account-management" aria-label="管理外部账号"> <div class="modal__content"> <div class="modal__image"> <icon-key></icon-key> </div> <p v-if="entries.length">StackEdit中文版可以访问以下外部账号:</p> <p v-else>StackEdit中文版尚未访问任何外部账号。</p> <div> <div class="account-entry flex flex--column" v-for="entry in entries" :key="entry.token.sub"> <div class="account-entry__header flex flex--row flex--align-center"> <div class="account-entry__icon flex flex--column flex--center"> <icon-provider :provider-id="entry.providerId"></icon-provider> </div> <div class="account-entry__description"> {{entry.name}} </div> <div class="account-entry__buttons flex flex--row flex--center"> <button class="account-entry__button button" @click="remove(entry)" v-title="'删除访问'"> <icon-delete></icon-delete> </button> </div> </div> <div class="account-entry__row"> <span class="account-entry__field" v-if="entry.userId"> <b>用户ID:</b> {{entry.userId}} </span> <span class="account-entry__field" v-if="entry.url"> <b>URL:</b> {{entry.url}} </span> <span class="account-entry__field line-entry" v-if="entry.customHeaders"> <b>自定义请求头:</b> {{entry.customHeaders}} </span> <span class="account-entry__field line-entry" v-if="entry.customParams"> <b>自定义Form参数:</b> {{entry.customParams}} </span> <span class="account-entry__field" v-if="entry.scopes"> <b>权限范围:</b> {{entry.scopes.join(', ')}} </span> </div> </div> </div> <menu-entry @click.native="addBloggerAccount"> <icon-provider slot="icon" provider-id="blogger"></icon-provider> <span>添加Blogger账号</span> </menu-entry> <menu-entry @click.native="addDropboxAccount"> <icon-provider slot="icon" provider-id="dropbox"></icon-provider> <span>添加Dropbox账号</span> </menu-entry> <menu-entry @click.native="addGithubAccount"> <icon-provider slot="icon" provider-id="github"></icon-provider> <span>添加GitHub账号</span> </menu-entry> <menu-entry @click.native="addGiteeAccount"> <icon-provider slot="icon" provider-id="gitee"></icon-provider> <span>添加Gitee账号</span> </menu-entry> <menu-entry @click.native="addGitlabAccount"> <icon-provider slot="icon" provider-id="gitlab"></icon-provider> <span>添加GitLab账号</span> </menu-entry> <menu-entry @click.native="addGiteaAccount"> <icon-provider slot="icon" provider-id="gitea"></icon-provider> <span>添加Gitea账号</span> </menu-entry> <menu-entry @click.native="addGoogleDriveAccount"> <icon-provider slot="icon" provider-id="googleDrive"></icon-provider> <span>添加Google Drive账号</span> </menu-entry> <menu-entry @click.native="addGooglePhotosAccount"> <icon-provider slot="icon" provider-id="googlePhotos"></icon-provider> <span>添加Google Photos账号</span> </menu-entry> <menu-entry @click.native="addWordpressAccount"> <icon-provider slot="icon" provider-id="wordpress"></icon-provider> <span>添加WordPress账号</span> </menu-entry> <menu-entry @click.native="addZendeskAccount"> <icon-provider slot="icon" provider-id="zendesk"></icon-provider> <span>添加Zendesk账号</span> </menu-entry> <menu-entry @click.native="addSmmsAccount"> <icon-provider slot="icon" provider-id="smms"></icon-provider> <span>添加SM.MS账号</span> </menu-entry> <menu-entry @click.native="addCustomAccount"> <icon-provider slot="icon" provider-id="custom"></icon-provider> <span>添加自定义图床账号</span> </menu-entry> </div> <div class="modal__button-bar"> <button class="button button--resolve" @click="config.resolve()">关闭</button> </div> </modal-inner> </template> <script> import { mapGetters } from 'vuex'; import ModalInner from './common/ModalInner'; import MenuEntry from '../menus/common/MenuEntry'; import store from '../../store'; import utils from '../../services/utils'; import googleHelper from '../../services/providers/helpers/googleHelper'; import dropboxHelper from '../../services/providers/helpers/dropboxHelper'; import githubHelper from '../../services/providers/helpers/githubHelper'; import giteeHelper from '../../services/providers/helpers/giteeHelper'; import gitlabHelper from '../../services/providers/helpers/gitlabHelper'; import giteaHelper from '../../services/providers/helpers/giteaHelper'; import wordpressHelper from '../../services/providers/helpers/wordpressHelper'; import zendeskHelper from '../../services/providers/helpers/zendeskHelper'; import smmsHelper from '../../services/providers/helpers/smmsHelper'; import customHelper from '../../services/providers/helpers/customHelper'; import badgeSvc from '../../services/badgeSvc'; export default { components: { ModalInner, MenuEntry, }, computed: { ...mapGetters('modal', [ 'config', ]), entries() { return [ ...Object.values(store.getters['data/googleTokensBySub']).map(token => ({ token, providerId: 'google', userId: token.sub, name: token.name, scopes: ['openid', 'profile', ...token.scopes .map(scope => scope.replace(/^https:\/\/www.googleapis.com\/auth\//, ''))], })), ...Object.values(store.getters['data/couchdbTokensBySub']).map(token => ({ token, providerId: 'couchdb', url: token.dbUrl, name: token.name, })), ...Object.values(store.getters['data/dropboxTokensBySub']).map(token => ({ token, providerId: 'dropbox', userId: token.sub, name: token.name, })), ...Object.values(store.getters['data/githubTokensBySub']).map(token => ({ token, providerId: 'github', userId: token.sub, name: token.name, scopes: token.scopes, })), ...Object.values(store.getters['data/giteeTokensBySub']).map(token => ({ token, providerId: 'gitee', userId: token.sub, name: token.name, scopes: ['projects', 'pull_requests'], })), ...Object.values(store.getters['data/gitlabTokensBySub']).map(token => ({ token, providerId: 'gitlab', url: token.serverUrl, userId: token.sub, name: token.name, scopes: ['api'], })), ...Object.values(store.getters['data/giteaTokensBySub']).map(token => ({ token, providerId: 'gitea', url: token.serverUrl, userId: token.sub, name: token.name, scopes: ['api'], })), ...Object.values(store.getters['data/wordpressTokensBySub']).map(token => ({ token, providerId: 'wordpress', userId: token.sub, name: token.name, scopes: ['global'], })), ...Object.values(store.getters['data/zendeskTokensBySub']).map(token => ({ token, providerId: 'zendesk', url: `https://${token.subdomain}.zendesk.com/`, userId: token.sub, name: token.name, scopes: ['read', 'hc:write'], })), ...Object.values(store.getters['data/smmsTokensBySub']).map(token => ({ token, providerId: 'smms', userId: token.sub, name: token.name, scopes: ['api'], })), ...Object.values(store.getters['data/customTokensBySub']).map(token => ({ token, providerId: 'custom', url: token.uploadUrl, userId: token.name, name: token.name, customHeaders: token.customHeaders && JSON.stringify(token.customHeaders), customParams: token.customParams && JSON.stringify(token.customParams), scopes: ['upload'], })), ]; }, }, methods: { async remove(entry) { const tokensBySub = utils.deepCopy(store.getters[`data/${entry.providerId}TokensBySub`]); delete tokensBySub[entry.token.sub]; await store.dispatch('data/patchTokensByType', { [entry.providerId]: tokensBySub, }); badgeSvc.addBadge('removeAccount'); }, async addBloggerAccount() { try { await googleHelper.addBloggerAccount(); } catch (e) { /* cancel */ } }, async addDropboxAccount() { try { await store.dispatch('modal/open', { type: 'dropboxAccount' }); await dropboxHelper.addAccount(!store.getters['data/localSettings'].dropboxRestrictedAccess); } catch (e) { /* cancel */ } }, async addGithubAccount() { try { await store.dispatch('modal/open', { type: 'githubAccount' }); await githubHelper.addAccount(store.getters['data/localSettings'].githubRepoFullAccess); } catch (e) { /* cancel */ } }, async addGiteeAccount() { try { await store.dispatch('modal/open', { type: 'giteeAccount' }); await giteeHelper.addAccount(); } catch (e) { /* cancel */ } }, async addGitlabAccount() { try { const { serverUrl, applicationId } = await store.dispatch('modal/open', { type: 'gitlabAccount' }); await gitlabHelper.addAccount(serverUrl, applicationId); } catch (e) { /* cancel */ } }, async addGiteaAccount() { try { const applicationInfo = await store.dispatch('modal/open', { type: 'giteaAccount' }); await giteaHelper.addAccount(applicationInfo); } catch (e) { /* cancel */ } }, async addGoogleDriveAccount() { try { await store.dispatch('modal/open', { type: 'googleDriveAccount' }); await googleHelper.addDriveAccount(!store.getters['data/localSettings'].googleDriveRestrictedAccess); } catch (e) { /* cancel */ } }, async addGooglePhotosAccount() { try { await googleHelper.addPhotosAccount(); } catch (e) { /* cancel */ } }, async addWordpressAccount() { try { await wordpressHelper.addAccount(); } catch (e) { /* cancel */ } }, async addZendeskAccount() { try { const { subdomain, clientId } = await store.dispatch('modal/open', { type: 'zendeskAccount' }); await zendeskHelper.addAccount(subdomain, clientId); } catch (e) { /* cancel */ } }, async addSmmsAccount() { try { const { proxyUrl, apiSecretToken } = await store.dispatch('modal/open', { type: 'smmsAccount' }); await smmsHelper.addAccount(proxyUrl, apiSecretToken); } catch (e) { /* cancel */ } }, async addCustomAccount() { try { const accountInfo = await store.dispatch('modal/open', { type: 'customAccount' }); await customHelper.addAccount(accountInfo); } catch (e) { /* cancel */ } }, }, }; </script> <style lang="scss"> @import '../../styles/variables.scss'; .line-entry { word-break: break-word; /* 文本行的任意字内断开,就算是一个单词也会分开 */ word-wrap: break-word; /* IE */ white-space: -moz-pre-wrap; /* Mozilla */ white-space: -hp-pre-wrap; /* HP printers */ white-space: -o-pre-wrap; /* Opera 7 */ white-space: -pre-wrap; /* Opera 4-6 */ white-space: pre; /* CSS2 */ white-space: pre-wrap; /* CSS 2.1 */ white-space: pre-line; /* CSS 3 (and 2.1 as well, actually) */ } .account-entry { margin: 1.5em 0; height: auto; font-size: 17px; line-height: 1.5; } $button-size: 30px; .account-entry__header { line-height: $button-size; } .account-entry__row { border-top: 1px solid $hr-color; font-size: 0.67em; padding: 0.25em 0; } .account-entry__field { opacity: 0.5; } .account-entry__icon { height: 22px; width: 22px; margin-right: 0.75rem; flex: none; } .account-entry__description { width: 100%; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; } .account-entry__buttons { margin-left: 0.75rem; } .account-entry__button { width: $button-size; height: $button-size; padding: 4px; background-color: transparent; opacity: 0.75; &:active, &:focus, &:hover { opacity: 1; background-color: rgba(0, 0, 0, 0.1); } } </style>