diff --git a/apps/web-antd/src/router/routes/core.ts b/apps/web-antd/src/router/routes/core.ts index f793a57e..6a4a6381 100644 --- a/apps/web-antd/src/router/routes/core.ts +++ b/apps/web-antd/src/router/routes/core.ts @@ -29,6 +29,14 @@ const coreRoutes: RouteRecordRaw[] = [ path: '/', redirect: DEFAULT_HOME_PATH, }, + { + component: () => import('#/views/_core/social-callback/index.vue'), + meta: { + title: $t('page.core.oauthLogin'), + }, + name: 'OAuthRedirect', + path: '/social-callback', + }, { component: AuthPageLayout, meta: { diff --git a/apps/web-antd/src/views/_core/authentication/login.vue b/apps/web-antd/src/views/_core/authentication/login.vue index e1d9c921..64a368b5 100644 --- a/apps/web-antd/src/views/_core/authentication/login.vue +++ b/apps/web-antd/src/views/_core/authentication/login.vue @@ -3,13 +3,14 @@ import { onMounted, ref } from 'vue'; import { AuthenticationLogin } from '@vben/common-ui'; -import { message } from 'ant-design-vue'; import { omit } from 'lodash-es'; import { tenantList, type TenantResp } from '#/api'; import { captchaImage, type CaptchaResponse } from '#/api/core/captcha'; import { useAuthStore } from '#/store'; +import OauthLogin from './oauth-login.vue'; + defineOptions({ name: 'Login' }); const authStore = useAuthStore(); @@ -71,18 +72,6 @@ async function handleAccountLogin(values: LoginForm) { } } } - -function handleOauthLogin(provider: string) { - switch (provider) { - case 'gitee': { - message.success('todo gitee login'); - break; - } - default: { - message.warn('暂不支持该登录方式'); - } - } -} diff --git a/apps/web-antd/src/views/_core/authentication/oauth-login.vue b/apps/web-antd/src/views/_core/authentication/oauth-login.vue new file mode 100644 index 00000000..f8805ff0 --- /dev/null +++ b/apps/web-antd/src/views/_core/authentication/oauth-login.vue @@ -0,0 +1,45 @@ + + + diff --git a/apps/web-antd/src/views/_core/oauth-common.ts b/apps/web-antd/src/views/_core/oauth-common.ts new file mode 100644 index 00000000..b51a95fc --- /dev/null +++ b/apps/web-antd/src/views/_core/oauth-common.ts @@ -0,0 +1,94 @@ +import { authBinding } from '#/api/core/auth'; +/** + * @description: 菜单 + * @param key key + * @param title 标题 + * @param description 描述 + * @param extra 按钮文字 + * @param avatar 图标 + * @param color 图标颜色可直接写英文颜色/hex + */ +export interface ListItem { + key: string; + title: string; + description: string; + extra?: string; + avatar?: string; + color?: string; +} + +/** + * @description: 绑定账号 + * @param source 来源 如gitee github 与后端的social-callback?source=xxx对应 + * @param bound 是否已经绑定 + * @param action 账号绑定回调 + */ +export interface BindItem extends ListItem { + source: string; + bound?: boolean; + action?: (source: string) => Promise; +} + +/** + * todo tenantId + * 绑定授权从userStore.userInfo获取 + * 登录从localStorage获取 + * @param source + */ +async function handleAuthBinding(source: string) { + const tenantId = localStorage.getItem('__oauth_tenant_id') ?? '000000'; + // 这里返回打开授权页面的链接 + const href = await authBinding(source, tenantId); + window.location.href = href; +} + +/** + * 账号绑定 list + * 添加账号绑定只需要在这里增加即可 + * 添加过的项目会在个人主页-绑定账号中显示 + * action不为空的会在登录页显示 + */ +export const accountBindList: BindItem[] = [ + { + avatar: 'ri:taobao-fill', + color: '#ff4000', + description: '绑定淘宝账号', + key: '1', + source: 'taobao', + title: '淘宝', + }, + { + avatar: 'fa-brands:alipay', + color: '#2eabff', + description: '绑定支付宝账号', + key: '2', + source: 'alipay', + title: '支付宝', + }, + { + avatar: 'ri:dingding-fill', + color: '#2eabff', + description: '绑定钉钉账号', + key: '3', + source: 'ding', + title: '钉钉', + }, + { + action: () => handleAuthBinding('gitee'), + avatar: 'simple-icons:gitee', + color: '#c71d23', + description: '绑定GITEE账号', + key: '4', + source: 'gitee', + title: 'GITEE', + }, + { + action: () => handleAuthBinding('github'), + avatar: 'uiw:github', + color: '', + description: '绑定GITHUB账号', + key: '5', + source: 'github', + title: 'GITHUB', + }, +]; diff --git a/apps/web-antd/src/views/_core/profile/components/account-bind.vue b/apps/web-antd/src/views/_core/profile/components/account-bind.vue index 51663b1d..a4a2f1f5 100644 --- a/apps/web-antd/src/views/_core/profile/components/account-bind.vue +++ b/apps/web-antd/src/views/_core/profile/components/account-bind.vue @@ -3,13 +3,26 @@ import type { ColumnsType } from 'ant-design-vue/es/table'; import type { SocialInfo } from '#/api/system/social/model'; -import { onMounted, ref } from 'vue'; +import { computed, onMounted, ref, unref } from 'vue'; -import { Avatar, Modal, Table } from 'ant-design-vue'; +import { createIconifyIcon } from '@vben/icons'; + +import { + Alert, + Avatar, + Card, + List, + ListItem, + message, + Modal, + Table, +} from 'ant-design-vue'; import { authUnbinding } from '#/api'; import { socialList } from '#/api/system/social'; +import { accountBindList, type BindItem } from '../../oauth-common'; + const columns: ColumnsType = [ { align: 'center', @@ -36,14 +49,6 @@ const columns: ColumnsType = [ }, ]; -const tableData = ref([]); - -async function reload() { - tableData.value = await socialList(); -} - -onMounted(reload); - /** * 解绑账号 */ @@ -58,10 +63,47 @@ function handleUnbind(record: Record) { type: 'warning', }); } + +/** + * 没有传递action事件则不支持绑定 弹出默认提示 + */ +function defaultTip(title: string) { + message.info({ content: `暂不支持绑定${title}` }); +} + +function buttonText(item: BindItem) { + return item.bound ? '已绑定' : '绑定'; +} + +/** + * 已经绑定的平台 + */ +const boundPlatformsList = ref([]); +const bindList = computed(() => { + const list = [...accountBindList]; + list.forEach((item) => { + item.bound = !!unref(boundPlatformsList).includes(item.source); + }); + return list; +}); + +const tableData = ref([]); + +async function reload() { + const resp = await socialList(); + /** + * 平台转小写 + * 已经绑定的平台 + */ + boundPlatformsList.value = resp.map((item) => item.source.toLowerCase()); + tableData.value = resp; +} + +onMounted(reload); -
todo: 绑定功能
+
+ + + + + + +
+ + diff --git a/apps/web-antd/src/views/_core/social-callback/index.vue b/apps/web-antd/src/views/_core/social-callback/index.vue new file mode 100644 index 00000000..ad7135f4 --- /dev/null +++ b/apps/web-antd/src/views/_core/social-callback/index.vue @@ -0,0 +1,81 @@ + + + + + diff --git a/cspell.json b/cspell.json index 60020248..05d09ac8 100644 --- a/cspell.json +++ b/cspell.json @@ -4,49 +4,51 @@ "language": "en,en-US", "allowCompoundWords": true, "words": [ - "clsx", - "esno", - "demi", - "unref", - "taze", "acmr", "antd", - "lucide", + "antdv", + "astro", "brotli", + "clsx", "defu", + "demi", + "echarts", + "ependencies", + "esno", + "etag", "execa", + "Gitee", "iconify", "intlify", + "lockb", + "lucide", "mkdist", "mockjs", + "nocheck", "noopener", "noreferrer", "nprogress", + "nuxt", "pinia", + "prefixs", "publint", + "Qqchat", "qrcode", "shadcn", "sonner", + "sortablejs", + "styl", + "taze", + "ui-kit", "unplugin", + "unref", "vben", "vbenjs", - "vueuse", - "yxxx", - "nuxt", - "lockb", - "astro", - "ui-kit", - "styl", - "vnode", - "nocheck", - "prefixs", - "vitepress", - "antdv", - "ependencies", "vite", - "echarts", - "sortablejs", - "etag" + "vitepress", + "vnode", + "vueuse", + "yxxx" ], "ignorePaths": [ "**/node_modules/**", diff --git a/packages/effects/common-ui/src/ui/authentication/login.vue b/packages/effects/common-ui/src/ui/authentication/login.vue index 7584b7f3..aa7f257d 100644 --- a/packages/effects/common-ui/src/ui/authentication/login.vue +++ b/packages/effects/common-ui/src/ui/authentication/login.vue @@ -92,6 +92,19 @@ const formState = reactive({ username: localUsername, }); +/** + * oauth登录 需要tenantId参数 + */ +watch( + () => formState.tenantId, + (tenantId) => { + localStorage.setItem('__oauth_tenant_id', tenantId); + }, + { + immediate: true, + }, +); + /** * 默认选中第一项租户 */ diff --git a/packages/locales/src/langs/en-US.json b/packages/locales/src/langs/en-US.json index 80fe320f..46e31685 100644 --- a/packages/locales/src/langs/en-US.json +++ b/packages/locales/src/langs/en-US.json @@ -5,7 +5,8 @@ "register": "Register", "codeLogin": "Code Login", "qrcodeLogin": "Qr Code Login", - "forgetPassword": "Forget Password" + "forgetPassword": "Forget Password", + "oauthLogin": "Oauth Login" }, "dashboard": { "title": "Dashboard", diff --git a/packages/locales/src/langs/zh-CN.json b/packages/locales/src/langs/zh-CN.json index ca9bbfbd..452977c6 100644 --- a/packages/locales/src/langs/zh-CN.json +++ b/packages/locales/src/langs/zh-CN.json @@ -5,7 +5,8 @@ "register": "注册", "codeLogin": "验证码登录", "qrcodeLogin": "二维码登录", - "forgetPassword": "忘记密码" + "forgetPassword": "忘记密码", + "oauthLogin": "第三方登录" }, "dashboard": { "title": "概览",