@arcblock/did-connect-react 3.2.1 → 3.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,29 @@
1
+ import { jsxs as s, jsx as r } from "react/jsx-runtime";
2
+ import { useMemo as a } from "react";
3
+ import { Box as d, Typography as m } from "@mui/material";
4
+ import p from "prop-types";
5
+ import c from "@arcblock/ux/lib/UserCard";
6
+ import { withQuery as l, joinURL as f } from "ufo";
7
+ import { useMemoizedFn as u } from "ahooks";
8
+ import { BLOCKLET_SERVICE_PATH_PREFIX as x } from "../constant.js";
9
+ function h({ data: e }) {
10
+ const { message: i, data: o } = e, t = a(() => new URLSearchParams(window.location.search).get("locale") || "en", []), n = u(() => {
11
+ window.open(
12
+ l(f(x, "user"), {
13
+ locale: t,
14
+ did: o.did
15
+ }),
16
+ "_blank"
17
+ );
18
+ });
19
+ return /* @__PURE__ */ s(d, { sx: { display: "flex", flexDirection: "column", gap: 2 }, children: [
20
+ /* @__PURE__ */ r(m, { sx: { fontSize: 14, color: "text.secondary" }, children: i }),
21
+ /* @__PURE__ */ r(c, { showDid: !0, did: o.did, onAvatarClick: n })
22
+ ] });
23
+ }
24
+ h.propTypes = {
25
+ data: p.object.isRequired
26
+ };
27
+ export {
28
+ h as default
29
+ };
@@ -1,18 +1,21 @@
1
- import { jsxs as K, jsx as W } from "react/jsx-runtime";
2
- import l from "prop-types";
3
- import Y from "lodash/isUndefined";
4
- import { createContext as $, use as J } from "react";
5
- import h from "@arcblock/ux/lib/Toast";
6
- import { useReactive as m, useMemoizedFn as d, useCreation as Q, useLatest as Z } from "ahooks";
7
- import v from "lodash/noop";
8
- import R from "lodash/omit";
9
- import { joinURL as ee } from "ufo";
10
- import { translate as te } from "@arcblock/ux/lib/Locale/util";
11
- import { getBlockletData as S, getFederatedEnabled as k, getMaster as F } from "@arcblock/ux/lib/Util/federated";
12
- import { BLOCKLET_SERVICE_PATH_PREFIX as B, LOGIN_PROVIDER_NAME as A } from "@arcblock/ux/lib/Util/constant";
13
- import { createAxios as oe, openPopup as re, runPopup as ne, sleep as ie, getApiErrorMessage as O } from "../utils.js";
14
- import { parseResponse as se, PassportSwitcher as ae } from "../components/PassportSwitcher.js";
15
- const E = $({}), { Provider: de, Consumer: Le } = E, C = `${B}/api/oauth`, ce = {
1
+ import { jsxs as J, jsx as E } from "react/jsx-runtime";
2
+ import h from "prop-types";
3
+ import Q from "lodash/isUndefined";
4
+ import { createContext as Z, use as ee } from "react";
5
+ import l from "@arcblock/ux/lib/Toast";
6
+ import { useReactive as v, useMemoizedFn as u, useCreation as te, useLatest as oe } from "ahooks";
7
+ import O from "lodash/noop";
8
+ import B from "lodash/omit";
9
+ import { joinURL as re } from "ufo";
10
+ import { translate as ne } from "@arcblock/ux/lib/Locale/util";
11
+ import ie from "@arcblock/ux/lib/Dialog/use-confirm";
12
+ import { getBlockletData as S, getFederatedEnabled as C, getMaster as R } from "@arcblock/ux/lib/Util/federated";
13
+ import { BLOCKLET_SERVICE_PATH_PREFIX as F, LOGIN_PROVIDER_NAME as f } from "@arcblock/ux/lib/Util/constant";
14
+ import { createAxios as se, openPopup as ae, runPopup as de, sleep as ce, getApiErrorMessage as m } from "../utils.js";
15
+ import { parseResponse as ue, PassportSwitcher as le } from "../components/PassportSwitcher.js";
16
+ import pe from "../Session/hooks/use-mobile.js";
17
+ import he from "./bind-conflict-alert.js";
18
+ const D = Z({}), { Provider: fe, Consumer: Te } = D, k = `${F}/api/oauth`, be = {
16
19
  zh: {
17
20
  bindOAuth: "绑定第三方登录",
18
21
  bind: "绑定",
@@ -24,7 +27,10 @@ const E = $({}), { Provider: de, Consumer: Le } = E, C = `${B}/api/oauth`, ce =
24
27
  unbindOAuthFailed: "绑定 {provider} 失败",
25
28
  loginRequired: "授权请求被拒绝",
26
29
  cancelAuth: "取消授权",
27
- noPassports: "没有可更换的通行证"
30
+ noPassports: "没有可更换的通行证",
31
+ confirm: "我知道了",
32
+ ALREADY_EXIST: "当前账户已存在",
33
+ ALREADY_BIND: "当前账户绑定过 {provider}"
28
34
  },
29
35
  en: {
30
36
  bindOAuth: "Bind third party login",
@@ -37,31 +43,41 @@ const E = $({}), { Provider: de, Consumer: Le } = E, C = `${B}/api/oauth`, ce =
37
43
  unbindOAuthFailed: "Unbind {provider} failed",
38
44
  loginRequired: "You have declined the authentication request",
39
45
  cancelAuth: "Cancel authentication",
40
- noPassports: "No passports to switch"
46
+ noPassports: "No passports to switch",
47
+ confirm: "I know",
48
+ ALREADY_EXIST: "Your account already exists",
49
+ ALREADY_BIND: "Your account is already bind to {provider}"
41
50
  }
42
51
  };
43
- function ue({
52
+ function Ae({
44
53
  children: w,
45
54
  locale: p = "en",
46
- onBindOAuth: T = v,
47
- onUnbindOAuth: j = v,
48
- onSwitchPassport: x = v,
49
- session: M = null
55
+ onBindOAuth: T = O,
56
+ onUnbindOAuth: _ = O,
57
+ onSwitchPassport: I = O,
58
+ session: Y = null
50
59
  }) {
51
- const o = m({
60
+ const x = pe(), { confirmApi: M, confirmHolder: N } = ie({
61
+ maxWidth: !1,
62
+ PaperProps: {
63
+ style: {
64
+ minWidth: x ? "100%" : 600
65
+ }
66
+ }
67
+ }), r = v({
52
68
  baseUrl: "/",
53
69
  bindFnSession: void 0,
54
70
  bindAuthLoading: !1,
55
71
  unbindAuthLoading: !1
56
- }), i = m({
72
+ }), c = v({
57
73
  open: !1,
58
74
  currentUser: null,
59
75
  passports: [],
60
76
  selectedPassport: void 0,
61
77
  reset() {
62
- i.open = !1, i.currentUser = null, i.passports = [], i.selectedPassport = void 0;
78
+ c.open = !1, c.currentUser = null, c.passports = [], c.selectedPassport = void 0;
63
79
  }
64
- }), b = m({
80
+ }), b = v({
65
81
  user: null,
66
82
  // loginLoading: false,
67
83
  checking: !1,
@@ -72,172 +88,189 @@ function ue({
72
88
  reset({ status: t = "" } = {}) {
73
89
  b.loading = !!t, b.checking = !1, b.error = "", b.status = t;
74
90
  }
75
- }), s = d((t, e = {}) => te(ce, t, p, "en", e)), _ = Q(() => oe({
91
+ }), i = u((t, e = {}) => ne(be, t, p, "en", e)), j = te(() => se({
76
92
  // NOTICE: 请求必须向当前站点发起
77
- baseURL: C
78
- }), [o.baseUrl, C]), g = Z(_), P = d(async () => {
79
- if (o.baseUrl === "/")
93
+ baseURL: k
94
+ }), [r.baseUrl, k]), A = oe(j), P = u(async () => {
95
+ if (r.baseUrl === "/")
80
96
  return window.blocklet;
81
97
  try {
82
- if (new URL(o.baseUrl).host === window.location.host)
98
+ if (new URL(r.baseUrl).host === window.location.host)
83
99
  return window.blocklet;
84
100
  } catch {
85
101
  }
86
- return await S(o.baseUrl);
87
- }), U = d(async ({ sourceAppPid: t } = {}) => {
88
- const e = await P(), r = k(e), n = F(e);
89
- return r && n?.appPid && t === n?.appPid ? (await S(n.appUrl))?.settings?.oauth || {} : e?.settings?.oauth || {};
90
- }), q = d(async ({ sourceAppPid: t } = {}) => {
102
+ return await S(r.baseUrl);
103
+ }), U = u(async ({ sourceAppPid: t } = {}) => {
104
+ const e = await P(), o = C(e), n = R(e);
105
+ return o && n?.appPid && t === n?.appPid ? (await S(n.appUrl))?.settings?.oauth || {} : e?.settings?.oauth || {};
106
+ }), X = u(async ({ sourceAppPid: t } = {}) => {
91
107
  const e = await U({ sourceAppPid: t });
92
- return Object.entries(e).map(([n, c]) => ({ ...c, provider: n })).filter((n) => n.enabled).sort((n, c) => n?.order !== void 0 && c?.order !== void 0 ? n.order - c.order : n?.order !== void 0 ? -1 : 1);
93
- }), y = d(async ({ provider: t } = {}) => {
94
- const e = re(ee(o.baseUrl, B, "/oauth/login", t), {
108
+ return Object.entries(e).map(([n, a]) => ({ ...a, provider: n })).filter((n) => n.enabled).sort((n, a) => n?.order !== void 0 && a?.order !== void 0 ? n.order - a.order : n?.order !== void 0 ? -1 : 1);
109
+ }), L = u(async ({ provider: t } = {}) => {
110
+ const e = ae(re(r.baseUrl, F, "/oauth/login", t), {
95
111
  name: "oauth-login:popup",
96
112
  offsetX: 650,
97
113
  height: 700,
98
114
  width: 500
99
115
  });
100
116
  try {
101
- const r = await ne({
117
+ const o = await de({
102
118
  popup: e,
103
119
  closeTimeout: 0
104
120
  });
105
- return r?.response ? r.response?.code : null;
106
- } catch (r) {
107
- throw r?.message === "Popup closed" ? new Error(s("cancelAuth")) : r;
121
+ return o?.response ? o.response?.code : null;
122
+ } catch (o) {
123
+ throw o?.message === "Popup closed" ? new Error(i("cancelAuth")) : o;
108
124
  }
109
- }), I = async ({ session: t, oauthItem: e } = {}) => {
110
- o.bindFnSession = t, o.bindAuthLoading = !0;
125
+ }), q = async ({ session: t, oauthItem: e } = {}) => {
126
+ r.bindFnSession = t, r.bindAuthLoading = !0;
111
127
  try {
112
- const r = await y(e), n = o.bindFnSession?.user?.sourceAppPid;
113
- await g.current.post("/bind", {
128
+ const o = await L(e), n = r.bindFnSession?.user?.sourceAppPid;
129
+ await A.current.post("/bind", {
114
130
  locale: p,
115
131
  provider: e.provider,
116
- code: r,
132
+ code: o,
117
133
  sourceAppPid: n
118
- }), h.success(s("bindOAuthSucceed", { provider: A[e.provider] })), T(e);
119
- } catch (r) {
120
- h.error(O(r, s("bindOAuthFailed", { provider: A[e.provider] })));
134
+ }), l.success(i("bindOAuthSucceed", { provider: f[e.provider] })), T(e);
135
+ } catch (o) {
136
+ if (o.response?.status === 409) {
137
+ const { data: a = {} } = o.response || {}, { code: d } = a || {};
138
+ ["ALREADY_EXIST", "ALREADY_BIND"].includes(d) ? M.open({
139
+ title: i(d, { provider: e.provider }),
140
+ showCancelButton: !1,
141
+ confirmButtonText: i("confirm"),
142
+ content: /* @__PURE__ */ E(he, { data: a }),
143
+ onConfirm(s) {
144
+ s();
145
+ }
146
+ }) : l.error(
147
+ m(o, i("bindOAuthFailed", { provider: f[e.provider] }))
148
+ );
149
+ } else
150
+ l.error(
151
+ m(o, i("bindOAuthFailed", { provider: f[e.provider] }))
152
+ );
121
153
  } finally {
122
- o.bindAuthLoading = !1;
154
+ r.bindAuthLoading = !1;
123
155
  }
124
- }, D = async ({ session: t, connectedAccount: e }) => {
125
- o.unbindAuthLoading = !0;
156
+ }, W = async ({ session: t, connectedAccount: e }) => {
157
+ r.unbindAuthLoading = !0;
126
158
  try {
127
- const r = t?.user?.sourceAppPid;
128
- await g.current.post("/unbind", {
159
+ const o = t?.user?.sourceAppPid;
160
+ await A.current.post("/unbind", {
129
161
  locale: p,
130
- connectedAccount: R(e, ["showProvider"]),
131
- sourceAppPid: r
132
- }), h.success(
133
- s("unbindOAuthSucceed", {
134
- provider: A[e.showProvider || e.provider]
162
+ connectedAccount: B(e, ["showProvider"]),
163
+ sourceAppPid: o
164
+ }), l.success(
165
+ i("unbindOAuthSucceed", {
166
+ provider: f[e.showProvider || e.provider]
135
167
  })
136
- ), j(e);
137
- } catch (r) {
138
- h.error(
139
- O(
140
- r,
141
- s("unbindOAuthFailed", {
142
- provider: A[e.showProvider || e.provider]
168
+ ), _(e);
169
+ } catch (o) {
170
+ l.error(
171
+ m(
172
+ o,
173
+ i("unbindOAuthFailed", {
174
+ provider: f[e.showProvider || e.provider]
143
175
  })
144
176
  )
145
177
  );
146
178
  } finally {
147
- o.unbindAuthLoading = !1;
179
+ r.unbindAuthLoading = !1;
148
180
  }
149
- }, N = async (t = {}) => {
181
+ }, z = async (t = {}) => {
150
182
  try {
151
- const { data: e } = await g.current.get("/passports");
152
- e.length > 0 ? (i.open = !0, i.currentUser = t, i.passports = e || []) : h.error(s("noPassports"));
183
+ const { data: e } = await A.current.get("/passports");
184
+ e.length > 0 ? (c.open = !0, c.currentUser = t, c.passports = e || []) : l.error(i("noPassports"));
153
185
  } catch (e) {
154
- h.error(e.message || s("getPassportFailed"));
186
+ l.error(e.message || i("getPassportFailed"));
155
187
  }
156
- }, z = d((...t) => {
157
- i.reset(), x(...t);
188
+ }, H = u((...t) => {
189
+ c.reset(), I(...t);
158
190
  }), V = (t) => {
159
- o.baseUrl = t || "/";
160
- }, X = d(async ({ provider: t } = {}, { action: e = "login", ...r } = {}) => {
161
- const n = o.baseUrl;
162
- if (r?.sourceAppPid === window.blocklet?.appPid)
163
- o.baseUrl = window.blocklet?.appUrl || "/";
164
- else if (r?.sourceAppPid) {
165
- const u = await P(), a = k(u), f = F(u);
166
- a && f?.appPid && r?.sourceAppPid === f?.appPid && (o.baseUrl = f.appUrl);
191
+ r.baseUrl = t || "/";
192
+ }, G = u(async ({ provider: t } = {}, { action: e = "login", ...o } = {}) => {
193
+ const n = r.baseUrl;
194
+ if (o?.sourceAppPid === window.blocklet?.appPid)
195
+ r.baseUrl = window.blocklet?.appUrl || "/";
196
+ else if (o?.sourceAppPid) {
197
+ const d = await P(), s = C(d), g = R(d);
198
+ s && g?.appPid && o?.sourceAppPid === g?.appPid && (r.baseUrl = g.appUrl);
167
199
  }
168
- const c = window?.blocklet?.componentId;
200
+ const a = window?.blocklet?.componentId;
169
201
  try {
170
- const u = await y({ provider: t });
171
- if (o.baseUrl = n, await ie(100), u) {
172
- const a = {
173
- ...r,
202
+ const d = await L({ provider: t });
203
+ if (r.baseUrl = n, await ce(100), d) {
204
+ const s = {
205
+ ...o,
174
206
  action: e,
175
207
  locale: p,
176
- code: u,
208
+ code: d,
177
209
  provider: t,
178
- componentId: c
210
+ componentId: a
179
211
  };
180
- Y(a.inviter) && window.localStorage.getItem("inviter") && (a.inviter = window.localStorage.getItem("inviter"));
181
- const f = ["connect-to-did-space", "connect-to-did-domain"].includes(a.action) ? "login" : a.action, { data: H } = await g.current.post("/login", { ...a, action: f }), L = se(H);
182
- return L.provider = t, L;
212
+ Q(s.inviter) && window.localStorage.getItem("inviter") && (s.inviter = window.localStorage.getItem("inviter"));
213
+ const g = ["connect-to-did-space", "connect-to-did-domain"].includes(s.action) ? "login" : s.action, { data: $ } = await A.current.post("/login", { ...s, action: g }), y = ue($);
214
+ return y.provider = t, y;
183
215
  }
184
- return o.baseUrl = n, null;
185
- } catch (u) {
186
- const a = O(u, s("loginOAuthFailed", { provider: A[t] }));
187
- throw o.baseUrl = n, new Error(a);
216
+ return r.baseUrl = n, null;
217
+ } catch (d) {
218
+ const s = m(d, i("loginOAuthFailed", { provider: f[t] }));
219
+ throw r.baseUrl = n, new Error(s);
188
220
  }
189
- }), G = d(() => {
221
+ }), K = u(() => {
190
222
  });
191
- return /* @__PURE__ */ K(
192
- de,
223
+ return /* @__PURE__ */ J(
224
+ fe,
193
225
  {
194
226
  value: {
195
227
  locale: p,
196
228
  getOAuthConfigs: U,
197
- getOAuthConfigList: q,
198
- bindOAuth: I,
199
- unbindOAuth: D,
200
- loginOAuth: X,
201
- logoutOAuth: G,
202
- switchOAuthPassport: N,
203
- baseUrl: o.baseUrl,
229
+ getOAuthConfigList: X,
230
+ bindOAuth: q,
231
+ unbindOAuth: W,
232
+ loginOAuth: G,
233
+ logoutOAuth: K,
234
+ switchOAuthPassport: z,
235
+ baseUrl: r.baseUrl,
204
236
  setBaseUrl: V,
205
237
  oauthState: b,
206
- unbindAuthLoading: o.unbindAuthLoading,
207
- bindAuthLoading: o.bindAuthLoading,
208
- t: s
238
+ unbindAuthLoading: r.unbindAuthLoading,
239
+ bindAuthLoading: r.bindAuthLoading,
240
+ t: i
209
241
  },
210
242
  children: [
211
243
  w,
212
- /* @__PURE__ */ W(
213
- ae,
244
+ N,
245
+ /* @__PURE__ */ E(
246
+ le,
214
247
  {
215
- api: g.current,
248
+ api: A.current,
216
249
  locale: p,
217
- switchState: i,
218
- onSwitchPassport: z,
219
- session: M
250
+ switchState: c,
251
+ onSwitchPassport: H,
252
+ session: Y
220
253
  }
221
254
  )
222
255
  ]
223
256
  }
224
257
  );
225
258
  }
226
- function Se() {
227
- const w = J(E);
228
- return R(w, ["locale", "getToken"]);
259
+ function _e() {
260
+ const w = ee(D);
261
+ return B(w, ["locale", "getToken"]);
229
262
  }
230
- ue.propTypes = {
231
- children: l.node.isRequired,
232
- locale: l.string,
233
- onBindOAuth: l.func,
234
- onUnbindOAuth: l.func,
235
- onSwitchPassport: l.func,
236
- session: l.object
263
+ Ae.propTypes = {
264
+ children: h.node.isRequired,
265
+ locale: h.string,
266
+ onBindOAuth: h.func,
267
+ onUnbindOAuth: h.func,
268
+ onSwitchPassport: h.func,
269
+ session: h.object
237
270
  };
238
271
  export {
239
- Le as OAuthConsumer,
240
- E as OAuthContext,
241
- ue as OAuthProvider,
242
- Se as useOAuth
272
+ Te as OAuthConsumer,
273
+ D as OAuthContext,
274
+ Ae as OAuthProvider,
275
+ _e as useOAuth
243
276
  };
@@ -1,4 +1,4 @@
1
- const o = "3.2.1", s = {
1
+ const o = "3.2.3", s = {
2
2
  version: o
3
3
  };
4
4
  export {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arcblock/did-connect-react",
3
- "version": "3.2.1",
3
+ "version": "3.2.3",
4
4
  "description": "Client side library to work with DID Connect by ArcBlock.",
5
5
  "keywords": [
6
6
  "react",
@@ -32,10 +32,10 @@
32
32
  "url": "https://github.com/ArcBlock/ux/issues"
33
33
  },
34
34
  "dependencies": {
35
- "@arcblock/bridge": "3.2.1",
35
+ "@arcblock/bridge": "3.2.3",
36
36
  "@arcblock/did": "^1.27.3",
37
- "@arcblock/icons": "3.2.1",
38
- "@arcblock/react-hooks": "3.2.1",
37
+ "@arcblock/icons": "3.2.3",
38
+ "@arcblock/react-hooks": "3.2.3",
39
39
  "@arcblock/ws": "^1.27.3",
40
40
  "@fontsource/lexend": "^5.2.9",
41
41
  "@iconify-icons/logos": "^1.2.36",
@@ -80,5 +80,5 @@
80
80
  "eslint-plugin-react-hooks": "^4.6.2",
81
81
  "jest": "^29.7.0"
82
82
  },
83
- "gitHead": "a41d3c8699798dcfc3fba68407cbb713c587bbd6"
83
+ "gitHead": "bbd2b3c8caecf454ee738676f1ca5fe0e71fdb6a"
84
84
  }
@@ -0,0 +1,37 @@
1
+ import { useMemo } from 'react';
2
+ import { Box, Typography } from '@mui/material';
3
+ import PropTypes from 'prop-types';
4
+ import UserCard from '@arcblock/ux/lib/UserCard';
5
+ import { joinURL, withQuery } from 'ufo';
6
+ import { useMemoizedFn } from 'ahooks';
7
+
8
+ import { BLOCKLET_SERVICE_PATH_PREFIX } from '../constant';
9
+
10
+ export default function BindConflictAlert({ data }) {
11
+ const { message, data: userInfo } = data;
12
+
13
+ const locale = useMemo(() => {
14
+ return new URLSearchParams(window.location.search).get('locale') || 'en';
15
+ }, []);
16
+
17
+ const visitUser = useMemoizedFn(() => {
18
+ window.open(
19
+ withQuery(joinURL(BLOCKLET_SERVICE_PATH_PREFIX, 'user'), {
20
+ locale,
21
+ did: userInfo.did,
22
+ }),
23
+ '_blank'
24
+ );
25
+ });
26
+
27
+ return (
28
+ <Box sx={{ display: 'flex', flexDirection: 'column', gap: 2 }}>
29
+ <Typography sx={{ fontSize: 14, color: 'text.secondary' }}>{message}</Typography>
30
+ <UserCard showDid did={userInfo.did} onAvatarClick={visitUser} />
31
+ </Box>
32
+ );
33
+ }
34
+
35
+ BindConflictAlert.propTypes = {
36
+ data: PropTypes.object.isRequired,
37
+ };
@@ -7,6 +7,7 @@ import noop from 'lodash/noop';
7
7
  import omit from 'lodash/omit';
8
8
  import { joinURL } from 'ufo';
9
9
  import { translate } from '@arcblock/ux/lib/Locale/util';
10
+ import useConfirm from '@arcblock/ux/lib/Dialog/use-confirm';
10
11
  import { getFederatedEnabled, getMaster, getBlockletData } from '@arcblock/ux/lib/Util/federated';
11
12
  import { LOGIN_PROVIDER_NAME, BLOCKLET_SERVICE_PATH_PREFIX } from '@arcblock/ux/lib/Util/constant';
12
13
 
@@ -14,6 +15,9 @@ import { LOGIN_PROVIDER_NAME, BLOCKLET_SERVICE_PATH_PREFIX } from '@arcblock/ux/
14
15
  import { getApiErrorMessage, createAxios, openPopup, runPopup, sleep } from '../utils';
15
16
  import { PassportSwitcher, parseResponse } from '../components/PassportSwitcher';
16
17
 
18
+ import useMobile from '../Session/hooks/use-mobile';
19
+ import BindConflictAlert from './bind-conflict-alert';
20
+
17
21
  const OAuthContext = createContext({});
18
22
  const { Provider, Consumer: OAuthConsumer } = OAuthContext;
19
23
 
@@ -32,6 +36,9 @@ const translations = {
32
36
  loginRequired: '授权请求被拒绝',
33
37
  cancelAuth: '取消授权',
34
38
  noPassports: '没有可更换的通行证',
39
+ confirm: '我知道了',
40
+ ALREADY_EXIST: '当前账户已存在',
41
+ ALREADY_BIND: '当前账户绑定过 {provider}',
35
42
  },
36
43
  en: {
37
44
  bindOAuth: 'Bind third party login',
@@ -45,6 +52,9 @@ const translations = {
45
52
  loginRequired: 'You have declined the authentication request',
46
53
  cancelAuth: 'Cancel authentication',
47
54
  noPassports: 'No passports to switch',
55
+ confirm: 'I know',
56
+ ALREADY_EXIST: 'Your account already exists',
57
+ ALREADY_BIND: 'Your account is already bind to {provider}',
48
58
  },
49
59
  };
50
60
 
@@ -56,6 +66,15 @@ function OAuthProvider({
56
66
  onSwitchPassport = noop,
57
67
  session = null,
58
68
  }) {
69
+ const isMobile = useMobile();
70
+ const { confirmApi, confirmHolder } = useConfirm({
71
+ maxWidth: false,
72
+ PaperProps: {
73
+ style: {
74
+ minWidth: isMobile ? '100%' : 600,
75
+ },
76
+ },
77
+ });
59
78
  const state = useReactive({
60
79
  baseUrl: '/',
61
80
  bindFnSession: undefined,
@@ -189,7 +208,31 @@ function OAuthProvider({
189
208
  Toast.success(t('bindOAuthSucceed', { provider: LOGIN_PROVIDER_NAME[oauthItem.provider] }));
190
209
  onBindOAuth(oauthItem);
191
210
  } catch (err) {
192
- Toast.error(getApiErrorMessage(err, t('bindOAuthFailed', { provider: LOGIN_PROVIDER_NAME[oauthItem.provider] })));
211
+ // 对已存在的错误类型特殊处理
212
+ const statusCode = err.response?.status;
213
+ if (statusCode === 409) {
214
+ const { data = {} } = err.response || {};
215
+ const { code } = data || {};
216
+ if (['ALREADY_EXIST', 'ALREADY_BIND'].includes(code)) {
217
+ confirmApi.open({
218
+ title: t(code, { provider: oauthItem.provider }),
219
+ showCancelButton: false,
220
+ confirmButtonText: t('confirm'),
221
+ content: <BindConflictAlert data={data} />,
222
+ onConfirm(close) {
223
+ close();
224
+ },
225
+ });
226
+ } else {
227
+ Toast.error(
228
+ getApiErrorMessage(err, t('bindOAuthFailed', { provider: LOGIN_PROVIDER_NAME[oauthItem.provider] }))
229
+ );
230
+ }
231
+ } else {
232
+ Toast.error(
233
+ getApiErrorMessage(err, t('bindOAuthFailed', { provider: LOGIN_PROVIDER_NAME[oauthItem.provider] }))
234
+ );
235
+ }
193
236
  } finally {
194
237
  state.bindAuthLoading = false;
195
238
  }
@@ -326,6 +369,7 @@ function OAuthProvider({
326
369
  t,
327
370
  }}>
328
371
  {children}
372
+ {confirmHolder}
329
373
  <PassportSwitcher
330
374
  api={api.current}
331
375
  locale={locale}