openxiangda 1.0.84 → 1.0.85

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.
@@ -20,18 +20,23 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // packages/sdk/src/runtime/react/openxiangdaProvider.tsx
21
21
  var openxiangdaProvider_exports = {};
22
22
  __export(openxiangdaProvider_exports, {
23
+ AuthClientError: () => AuthClientError,
24
+ LoginPage: () => LoginPage,
23
25
  OpenXiangdaProvider: () => OpenXiangdaProvider,
24
26
  PermissionBoundary: () => PermissionBoundary,
25
27
  RuntimeHttpError: () => RuntimeHttpError,
28
+ createAuthClient: () => createAuthClient,
26
29
  useAppMenus: () => useAppMenus,
30
+ useAuth: () => useAuth,
27
31
  useCanAccessRoute: () => useCanAccessRoute,
32
+ useLoginMethods: () => useLoginMethods,
28
33
  useOpenXiangda: () => useOpenXiangda,
29
34
  usePermission: () => usePermission,
30
35
  useRuntimeAuth: () => useRuntimeAuth,
31
36
  useRuntimeBootstrap: () => useRuntimeBootstrap
32
37
  });
33
38
  module.exports = __toCommonJS(openxiangdaProvider_exports);
34
- var import_react = require("react");
39
+ var import_react2 = require("react");
35
40
 
36
41
  // packages/sdk/src/runtime/core/fetch.ts
37
42
  var createBoundFetch = (fetchImpl) => {
@@ -39,8 +44,610 @@ var createBoundFetch = (fetchImpl) => {
39
44
  return ((input, init) => baseFetch.call(globalThis, input, init));
40
45
  };
41
46
 
42
- // packages/sdk/src/runtime/react/openxiangdaProvider.tsx
47
+ // packages/sdk/src/runtime/react/auth.tsx
48
+ var import_react = require("react");
49
+ var import_antd = require("antd");
50
+ var import_icons = require("@ant-design/icons");
51
+
52
+ // packages/sdk/src/runtime/core/auth.ts
53
+ var AuthClientError = class extends Error {
54
+ constructor(message, options = {}) {
55
+ super(message);
56
+ this.name = "AuthClientError";
57
+ this.status = options.status;
58
+ this.code = options.code;
59
+ this.payload = options.payload;
60
+ }
61
+ };
62
+ var createAuthClient = ({
63
+ appType,
64
+ servicePrefix = "/service",
65
+ fetchImpl
66
+ }) => {
67
+ const normalizedAppType = String(appType || "").trim();
68
+ if (!normalizedAppType) {
69
+ throw new Error("appType \u4E0D\u80FD\u4E3A\u7A7A");
70
+ }
71
+ const boundFetch = createBoundFetch(fetchImpl);
72
+ const request = async (path, options = {}) => {
73
+ const response = await boundFetch(buildServiceUrl(servicePrefix, path), {
74
+ credentials: "include",
75
+ ...options,
76
+ headers: {
77
+ accept: "application/json",
78
+ ...options.body ? { "content-type": "application/json" } : {},
79
+ ...options.headers || {}
80
+ }
81
+ });
82
+ const payload = await readPayload(response);
83
+ const code = getRecordValue(payload, "code");
84
+ if (!response.ok || typeof code === "number" && code >= 400) {
85
+ throw new AuthClientError(
86
+ String(getRecordValue(payload, "message") || `Auth request failed: ${response.status}`),
87
+ { status: response.status, code, payload }
88
+ );
89
+ }
90
+ return unwrapPayload(payload);
91
+ };
92
+ const appAuthPath = (suffix) => `/openxiangda-api/v1/apps/${encodeURIComponent(normalizedAppType)}/auth${suffix}`;
93
+ return {
94
+ appType: normalizedAppType,
95
+ servicePrefix,
96
+ getMethods: () => request(appAuthPath("/methods")),
97
+ passwordLogin: (input) => request(appAuthPath("/password/login"), postJson(input)),
98
+ dingtalkLogin: (input) => request(appAuthPath("/dingtalk/login"), postJson(input)),
99
+ guestLogin: (input) => request(appAuthPath("/guest/login"), postJson(input || {})),
100
+ sendPhoneCode: (input) => request(appAuthPath("/phone-code/send"), postJson(input)),
101
+ phoneCodeLogin: (input) => request(appAuthPath("/phone-code/login"), postJson(input)),
102
+ registerWithPhoneCode: (input) => request(appAuthPath("/phone-code/register"), postJson(input)),
103
+ getSsoLoginUrl: (input) => request(appAuthPath("/sso/login-url"), postJson(input || {})),
104
+ refresh: (input) => request(appAuthPath("/refresh"), postJson(input || {})),
105
+ logout: async () => {
106
+ await request(appAuthPath("/logout"), { method: "POST" });
107
+ },
108
+ resolveLoginUrl: (input) => resolveLoginUrl(normalizedAppType, input || {})
109
+ };
110
+ };
111
+ var postJson = (body) => ({
112
+ method: "POST",
113
+ body: JSON.stringify(body || {})
114
+ });
115
+ var buildServiceUrl = (servicePrefix, path) => {
116
+ const prefix = servicePrefix.endsWith("/") ? servicePrefix.slice(0, -1) : servicePrefix;
117
+ const suffix = path.startsWith("/") ? path : `/${path}`;
118
+ return `${prefix}${suffix}`;
119
+ };
120
+ var readPayload = async (response) => {
121
+ try {
122
+ return await response.json();
123
+ } catch {
124
+ return null;
125
+ }
126
+ };
127
+ var unwrapPayload = (payload) => {
128
+ if (!payload || typeof payload !== "object") return payload;
129
+ const record = payload;
130
+ if ("data" in record) return record.data;
131
+ return payload;
132
+ };
133
+ var getRecordValue = (value, key) => {
134
+ if (!value || typeof value !== "object") return void 0;
135
+ return value[key];
136
+ };
137
+ var resolveLoginUrl = (appType, {
138
+ callbackUrl = getCurrentHref(),
139
+ callbackParamName = "callback",
140
+ loginUrl
141
+ }) => {
142
+ const target = loginUrl || `/view/${encodeURIComponent(appType)}/login`;
143
+ if (!callbackUrl) return target;
144
+ try {
145
+ const base = typeof window !== "undefined" ? window.location.origin : "http://localhost";
146
+ const url = new URL(target, base);
147
+ if (!url.searchParams.has(callbackParamName)) {
148
+ url.searchParams.set(callbackParamName, callbackUrl);
149
+ }
150
+ if (target.startsWith("http://") || target.startsWith("https://")) {
151
+ return url.toString();
152
+ }
153
+ return `${url.pathname}${url.search}${url.hash}`;
154
+ } catch {
155
+ const separator = target.includes("?") ? "&" : "?";
156
+ return `${target}${separator}${callbackParamName}=${encodeURIComponent(callbackUrl)}`;
157
+ }
158
+ };
159
+ var getCurrentHref = () => typeof window === "undefined" ? "" : window.location.href;
160
+
161
+ // packages/sdk/src/runtime/react/auth.tsx
43
162
  var import_jsx_runtime = require("react/jsx-runtime");
163
+ var useAuth = (options = {}) => {
164
+ const runtime = useOpenXiangda();
165
+ const client = (0, import_react.useMemo)(
166
+ () => createAuthClient({
167
+ appType: options.appType || runtime.appType,
168
+ servicePrefix: options.servicePrefix || runtime.servicePrefix,
169
+ fetchImpl: options.fetchImpl || runtime.fetchImpl
170
+ }),
171
+ [
172
+ options.appType,
173
+ options.fetchImpl,
174
+ options.servicePrefix,
175
+ runtime.appType,
176
+ runtime.fetchImpl,
177
+ runtime.servicePrefix
178
+ ]
179
+ );
180
+ return (0, import_react.useMemo)(
181
+ () => ({
182
+ client,
183
+ getMethods: client.getMethods,
184
+ passwordLogin: client.passwordLogin,
185
+ dingtalkLogin: client.dingtalkLogin,
186
+ guestLogin: client.guestLogin,
187
+ sendPhoneCode: client.sendPhoneCode,
188
+ phoneCodeLogin: client.phoneCodeLogin,
189
+ registerWithPhoneCode: client.registerWithPhoneCode,
190
+ getSsoLoginUrl: client.getSsoLoginUrl,
191
+ refresh: client.refresh,
192
+ logout: client.logout,
193
+ resolveLoginUrl: client.resolveLoginUrl
194
+ }),
195
+ [client]
196
+ );
197
+ };
198
+ var useLoginMethods = (options = {}) => {
199
+ const auth = useAuth(options);
200
+ const [state, setState] = (0, import_react.useState)({
201
+ data: null,
202
+ loading: true,
203
+ error: null
204
+ });
205
+ const reload = (0, import_react.useCallback)(async () => {
206
+ setState((prev) => ({ ...prev, loading: true, error: null }));
207
+ try {
208
+ const data = await auth.getMethods();
209
+ setState({ data, loading: false, error: null });
210
+ } catch (error) {
211
+ setState({
212
+ data: null,
213
+ loading: false,
214
+ error: normalizeError(error)
215
+ });
216
+ }
217
+ }, [auth]);
218
+ (0, import_react.useEffect)(() => {
219
+ let disposed = false;
220
+ const run = async () => {
221
+ setState((prev) => ({ ...prev, loading: true, error: null }));
222
+ try {
223
+ const data = await auth.getMethods();
224
+ if (!disposed) setState({ data, loading: false, error: null });
225
+ } catch (error) {
226
+ if (!disposed) {
227
+ setState({
228
+ data: null,
229
+ loading: false,
230
+ error: normalizeError(error)
231
+ });
232
+ }
233
+ }
234
+ };
235
+ void run();
236
+ return () => {
237
+ disposed = true;
238
+ };
239
+ }, [auth]);
240
+ return {
241
+ ...state,
242
+ methods: state.data?.methods || [],
243
+ reload
244
+ };
245
+ };
246
+ var LoginPage = ({
247
+ title,
248
+ subtitle,
249
+ className,
250
+ style,
251
+ defaultMethod,
252
+ redirectUrl,
253
+ redirectOnSuccess = true,
254
+ onSuccess,
255
+ ...authOptions
256
+ }) => {
257
+ const runtime = useOpenXiangda();
258
+ const auth = useAuth(authOptions);
259
+ const methodsState = useLoginMethods(authOptions);
260
+ const [passwordForm] = import_antd.Form.useForm();
261
+ const [phoneForm] = import_antd.Form.useForm();
262
+ const [activeMethod, setActiveMethod] = (0, import_react.useState)(
263
+ defaultMethod || "password"
264
+ );
265
+ const [phonePurpose, setPhonePurpose] = (0, import_react.useState)(
266
+ "login"
267
+ );
268
+ const [phoneChallengeId, setPhoneChallengeId] = (0, import_react.useState)("");
269
+ const [submitting, setSubmitting] = (0, import_react.useState)(false);
270
+ const [sendingCode, setSendingCode] = (0, import_react.useState)(false);
271
+ const [error, setError] = (0, import_react.useState)(null);
272
+ const methods = methodsState.methods.filter((method) => method.enabled !== false);
273
+ const passwordMethod = findMethod(methods, "password");
274
+ const phoneMethod = findMethod(methods, "phone_code");
275
+ const dingtalkMethod = findMethod(methods, "dingtalk");
276
+ const ssoMethod = findMethod(methods, "sso");
277
+ const guestMethod = findMethod(methods, "guest");
278
+ const allowRegister = methodsState.data?.registration?.mode !== "reject";
279
+ const tabItems = (0, import_react.useMemo)(() => {
280
+ const items = [];
281
+ if (passwordMethod) {
282
+ items.push({
283
+ key: "password",
284
+ label: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_antd.Space, { size: 6, children: [
285
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_icons.UserOutlined, {}),
286
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: passwordMethod.label || "\u8D26\u53F7\u5BC6\u7801" })
287
+ ] }),
288
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
289
+ PasswordLoginForm,
290
+ {
291
+ form: passwordForm,
292
+ loading: submitting,
293
+ onFinish: async (values) => {
294
+ setSubmitting(true);
295
+ setError(null);
296
+ try {
297
+ await handleSuccess(
298
+ await auth.passwordLogin({
299
+ username: values.username,
300
+ password: values.password
301
+ })
302
+ );
303
+ } catch (loginError) {
304
+ setError(normalizeError(loginError).message);
305
+ } finally {
306
+ setSubmitting(false);
307
+ }
308
+ }
309
+ }
310
+ )
311
+ });
312
+ }
313
+ if (phoneMethod) {
314
+ items.push({
315
+ key: "phone_code",
316
+ label: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_antd.Space, { size: 6, children: [
317
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_icons.MobileOutlined, {}),
318
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: phoneMethod.label || "\u624B\u673A\u53F7" })
319
+ ] }),
320
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
321
+ PhoneCodeLoginForm,
322
+ {
323
+ allowRegister,
324
+ form: phoneForm,
325
+ loading: submitting,
326
+ phonePurpose,
327
+ sendingCode,
328
+ onPurposeChange: setPhonePurpose,
329
+ onSendCode: async () => {
330
+ const values = await phoneForm.validateFields(["phone"]);
331
+ setSendingCode(true);
332
+ setError(null);
333
+ try {
334
+ const result = await auth.sendPhoneCode({
335
+ phone: values.phone,
336
+ purpose: phonePurpose
337
+ });
338
+ setPhoneChallengeId(result.challengeId);
339
+ } catch (sendError) {
340
+ setError(normalizeError(sendError).message);
341
+ } finally {
342
+ setSendingCode(false);
343
+ }
344
+ },
345
+ onFinish: async (values) => {
346
+ setSubmitting(true);
347
+ setError(null);
348
+ try {
349
+ const data = phonePurpose === "register" ? await auth.registerWithPhoneCode({
350
+ phone: values.phone,
351
+ code: values.code,
352
+ challengeId: phoneChallengeId
353
+ }) : await auth.phoneCodeLogin({
354
+ phone: values.phone,
355
+ code: values.code,
356
+ challengeId: phoneChallengeId
357
+ });
358
+ await handleSuccess(data);
359
+ } catch (loginError) {
360
+ setError(normalizeError(loginError).message);
361
+ } finally {
362
+ setSubmitting(false);
363
+ }
364
+ }
365
+ }
366
+ )
367
+ });
368
+ }
369
+ return items;
370
+ }, [
371
+ allowRegister,
372
+ auth,
373
+ handleSuccess,
374
+ passwordForm,
375
+ passwordMethod,
376
+ phoneChallengeId,
377
+ phoneForm,
378
+ phoneMethod,
379
+ phonePurpose,
380
+ sendingCode,
381
+ submitting
382
+ ]);
383
+ (0, import_react.useEffect)(() => {
384
+ const firstKey = tabItems[0]?.key;
385
+ if (firstKey && !tabItems.some((item) => item.key === activeMethod)) {
386
+ setActiveMethod(firstKey);
387
+ }
388
+ }, [activeMethod, tabItems]);
389
+ const handleDingTalkLogin = async () => {
390
+ setSubmitting(true);
391
+ setError(null);
392
+ try {
393
+ const code = await requestDingTalkCode(dingtalkMethod);
394
+ await handleSuccess(
395
+ await auth.dingtalkLogin({
396
+ code,
397
+ corpId: getString(dingtalkMethod, "corpId")
398
+ })
399
+ );
400
+ } catch (loginError) {
401
+ setError(normalizeError(loginError).message);
402
+ } finally {
403
+ setSubmitting(false);
404
+ }
405
+ };
406
+ const handleSsoLogin = async () => {
407
+ setSubmitting(true);
408
+ setError(null);
409
+ try {
410
+ const redirectUri = getCurrentHref2();
411
+ const result = await auth.getSsoLoginUrl({
412
+ protocol: getString(ssoMethod, "protocol") || "cas",
413
+ redirectUri
414
+ });
415
+ window.location.assign(result.loginUrl);
416
+ } catch (loginError) {
417
+ setError(normalizeError(loginError).message);
418
+ setSubmitting(false);
419
+ }
420
+ };
421
+ const handleGuestLogin = async () => {
422
+ setSubmitting(true);
423
+ setError(null);
424
+ try {
425
+ await handleSuccess(
426
+ await auth.guestLogin({
427
+ guestIdentifier: getOrCreateGuestIdentifier(auth.client),
428
+ domain: getCurrentHostname()
429
+ })
430
+ );
431
+ } catch (loginError) {
432
+ setError(normalizeError(loginError).message);
433
+ } finally {
434
+ setSubmitting(false);
435
+ }
436
+ };
437
+ async function handleSuccess(data) {
438
+ await onSuccess?.(data);
439
+ await runtime.reload();
440
+ if (redirectOnSuccess && typeof window !== "undefined") {
441
+ window.location.replace(
442
+ redirectUrl || getCallbackUrl() || `/view/${auth.client.appType}`
443
+ );
444
+ }
445
+ }
446
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
447
+ "div",
448
+ {
449
+ className,
450
+ style: {
451
+ minHeight: "100vh",
452
+ display: "grid",
453
+ placeItems: "center",
454
+ padding: 24,
455
+ background: "#f6f8fb",
456
+ ...style
457
+ },
458
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
459
+ import_antd.Card,
460
+ {
461
+ style: {
462
+ width: "min(100%, 420px)",
463
+ borderRadius: 8,
464
+ boxShadow: "0 16px 48px rgba(15, 23, 42, 0.10)"
465
+ },
466
+ styles: { body: { padding: 28 } },
467
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_antd.Space, { direction: "vertical", size: 20, style: { width: "100%" }, children: [
468
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
469
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_antd.Typography.Title, { level: 3, style: { margin: 0 }, children: title || "\u5E94\u7528\u767B\u5F55" }),
470
+ subtitle ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_antd.Typography.Text, { type: "secondary", children: subtitle }) : null
471
+ ] }),
472
+ methodsState.error ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
473
+ import_antd.Alert,
474
+ {
475
+ showIcon: true,
476
+ type: "error",
477
+ message: methodsState.error.message
478
+ }
479
+ ) : null,
480
+ error ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_antd.Alert, { showIcon: true, type: "error", message: error }) : null,
481
+ methodsState.loading ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_antd.Button, { block: true, loading: true, children: "\u52A0\u8F7D\u4E2D" }) : tabItems.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
482
+ import_antd.Tabs,
483
+ {
484
+ activeKey: activeMethod,
485
+ items: tabItems,
486
+ onChange: setActiveMethod
487
+ }
488
+ ) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_antd.Empty, { description: "\u672A\u542F\u7528\u767B\u5F55\u65B9\u5F0F" }),
489
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_antd.Space, { direction: "vertical", size: 10, style: { width: "100%" }, children: [
490
+ dingtalkMethod ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
491
+ import_antd.Button,
492
+ {
493
+ block: true,
494
+ icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_icons.QrcodeOutlined, {}),
495
+ loading: submitting,
496
+ onClick: handleDingTalkLogin,
497
+ children: dingtalkMethod.label || "\u9489\u9489\u514D\u767B"
498
+ }
499
+ ) : null,
500
+ ssoMethod ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
501
+ import_antd.Button,
502
+ {
503
+ block: true,
504
+ icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_icons.SafetyCertificateOutlined, {}),
505
+ loading: submitting,
506
+ onClick: handleSsoLogin,
507
+ children: ssoMethod.label || "SSO \u767B\u5F55"
508
+ }
509
+ ) : null,
510
+ guestMethod ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
511
+ import_antd.Button,
512
+ {
513
+ block: true,
514
+ icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_icons.LoginOutlined, {}),
515
+ loading: submitting,
516
+ onClick: handleGuestLogin,
517
+ children: guestMethod.label || "\u8BBF\u5BA2\u8BBF\u95EE"
518
+ }
519
+ ) : null
520
+ ] })
521
+ ] })
522
+ }
523
+ )
524
+ }
525
+ );
526
+ };
527
+ var PasswordLoginForm = ({ form, loading, onFinish }) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_antd.Form, { form, layout: "vertical", requiredMark: false, onFinish, children: [
528
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
529
+ import_antd.Form.Item,
530
+ {
531
+ label: "\u8D26\u53F7",
532
+ name: "username",
533
+ rules: [{ required: true, message: "\u8BF7\u8F93\u5165\u8D26\u53F7" }],
534
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_antd.Input, { autoComplete: "username" })
535
+ }
536
+ ),
537
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
538
+ import_antd.Form.Item,
539
+ {
540
+ label: "\u5BC6\u7801",
541
+ name: "password",
542
+ rules: [{ required: true, message: "\u8BF7\u8F93\u5165\u5BC6\u7801" }],
543
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_antd.Input.Password, { autoComplete: "current-password" })
544
+ }
545
+ ),
546
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_antd.Button, { block: true, htmlType: "submit", icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_icons.LoginOutlined, {}), loading, type: "primary", children: "\u767B\u5F55" })
547
+ ] });
548
+ var PhoneCodeLoginForm = ({
549
+ allowRegister,
550
+ form,
551
+ loading,
552
+ phonePurpose,
553
+ sendingCode,
554
+ onPurposeChange,
555
+ onSendCode,
556
+ onFinish
557
+ }) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_antd.Form, { form, layout: "vertical", requiredMark: false, onFinish, children: [
558
+ allowRegister ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_antd.Form.Item, { style: { marginBottom: 12 }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
559
+ import_antd.Tabs,
560
+ {
561
+ activeKey: phonePurpose,
562
+ items: [
563
+ { key: "login", label: "\u767B\u5F55" },
564
+ { key: "register", label: "\u6CE8\u518C" }
565
+ ],
566
+ onChange: (key) => onPurposeChange(key === "register" ? "register" : "login"),
567
+ size: "small"
568
+ }
569
+ ) }) : null,
570
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
571
+ import_antd.Form.Item,
572
+ {
573
+ label: "\u624B\u673A\u53F7",
574
+ name: "phone",
575
+ rules: [{ required: true, message: "\u8BF7\u8F93\u5165\u624B\u673A\u53F7" }],
576
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_antd.Input, { autoComplete: "tel" })
577
+ }
578
+ ),
579
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
580
+ import_antd.Form.Item,
581
+ {
582
+ label: "\u9A8C\u8BC1\u7801",
583
+ name: "code",
584
+ rules: [{ required: true, message: "\u8BF7\u8F93\u5165\u9A8C\u8BC1\u7801" }],
585
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
586
+ import_antd.Input,
587
+ {
588
+ addonAfter: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
589
+ import_antd.Button,
590
+ {
591
+ loading: sendingCode,
592
+ onClick: onSendCode,
593
+ size: "small",
594
+ type: "link",
595
+ children: "\u53D1\u9001"
596
+ }
597
+ ),
598
+ autoComplete: "one-time-code"
599
+ }
600
+ )
601
+ }
602
+ ),
603
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_antd.Button, { block: true, htmlType: "submit", icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_icons.MobileOutlined, {}), loading, type: "primary", children: phonePurpose === "register" ? "\u6CE8\u518C" : "\u767B\u5F55" })
604
+ ] });
605
+ var findMethod = (methods, type) => methods.find((method) => method.type === type);
606
+ var normalizeError = (error) => error instanceof Error ? error : new Error(String(error || "\u8BF7\u6C42\u5931\u8D25"));
607
+ var getString = (value, key) => {
608
+ if (!value || typeof value !== "object") return void 0;
609
+ const result = value[key];
610
+ return typeof result === "string" ? result : void 0;
611
+ };
612
+ var requestDingTalkCode = (method) => {
613
+ const dd = typeof window === "undefined" ? void 0 : window.dd;
614
+ const corpId = getString(method, "corpId");
615
+ return new Promise((resolve, reject) => {
616
+ const requestAuthCode = dd?.runtime?.permission?.requestAuthCode || dd?.requestAuthCode;
617
+ if (!requestAuthCode) {
618
+ reject(new Error("\u5F53\u524D\u73AF\u5883\u4E0D\u652F\u6301\u9489\u9489\u514D\u767B"));
619
+ return;
620
+ }
621
+ requestAuthCode({
622
+ corpId,
623
+ onSuccess: (result) => {
624
+ if (result?.code) resolve(result.code);
625
+ else reject(new Error("\u9489\u9489\u672A\u8FD4\u56DE\u514D\u767B\u7801"));
626
+ },
627
+ onFail: (error) => reject(normalizeError(error))
628
+ });
629
+ });
630
+ };
631
+ var getOrCreateGuestIdentifier = (client) => {
632
+ const key = `openxiangda:${client.appType}:guest_id`;
633
+ if (typeof window === "undefined") return createGuestIdentifier();
634
+ const current = window.localStorage.getItem(key);
635
+ if (current) return current;
636
+ const next = createGuestIdentifier();
637
+ window.localStorage.setItem(key, next);
638
+ return next;
639
+ };
640
+ var createGuestIdentifier = () => `guest_${Date.now()}_${Math.random().toString(36).slice(2, 10)}`;
641
+ var getCurrentHref2 = () => typeof window === "undefined" ? "" : window.location.href;
642
+ var getCurrentHostname = () => typeof window === "undefined" ? "" : window.location.hostname;
643
+ var getCallbackUrl = () => {
644
+ if (typeof window === "undefined") return "";
645
+ const query = new URLSearchParams(window.location.search);
646
+ return query.get("callback") || query.get("redirectUri") || "";
647
+ };
648
+
649
+ // packages/sdk/src/runtime/react/openxiangdaProvider.tsx
650
+ var import_jsx_runtime2 = require("react/jsx-runtime");
44
651
  var RuntimeHttpError = class extends Error {
45
652
  constructor(snapshot) {
46
653
  super(snapshot.message);
@@ -51,24 +658,24 @@ var RuntimeHttpError = class extends Error {
51
658
  this.payload = snapshot.payload;
52
659
  }
53
660
  };
54
- var OpenXiangdaRuntimeContext = (0, import_react.createContext)(null);
661
+ var OpenXiangdaRuntimeContext = (0, import_react2.createContext)(null);
55
662
  var OpenXiangdaProvider = ({
56
663
  appType,
57
664
  servicePrefix = "/service",
58
665
  fetchImpl,
59
666
  children
60
667
  }) => {
61
- const resolvedFetch = (0, import_react.useMemo)(() => createBoundFetch(fetchImpl), [fetchImpl]);
62
- const resolvedAppType = (0, import_react.useMemo)(
668
+ const resolvedFetch = (0, import_react2.useMemo)(() => createBoundFetch(fetchImpl), [fetchImpl]);
669
+ const resolvedAppType = (0, import_react2.useMemo)(
63
670
  () => appType || resolveAppTypeFromLocation(),
64
671
  [appType]
65
672
  );
66
- const [state, setState] = (0, import_react.useState)({
673
+ const [state, setState] = (0, import_react2.useState)({
67
674
  data: null,
68
675
  loading: true,
69
676
  error: null
70
677
  });
71
- const reload = (0, import_react.useCallback)(async () => {
678
+ const reload = (0, import_react2.useCallback)(async () => {
72
679
  if (!resolvedAppType) {
73
680
  setState({
74
681
  data: null,
@@ -83,7 +690,7 @@ var OpenXiangdaProvider = ({
83
690
  setState((prev) => ({ ...prev, loading: true, error: null }));
84
691
  try {
85
692
  const response = await resolvedFetch(
86
- buildServiceUrl(
693
+ buildServiceUrl2(
87
694
  servicePrefix,
88
695
  `/openxiangda-api/v1/apps/${encodeURIComponent(
89
696
  resolvedAppType
@@ -115,10 +722,10 @@ var OpenXiangdaProvider = ({
115
722
  });
116
723
  }
117
724
  }, [resolvedAppType, resolvedFetch, servicePrefix]);
118
- (0, import_react.useEffect)(() => {
725
+ (0, import_react2.useEffect)(() => {
119
726
  void reload();
120
727
  }, [reload]);
121
- const value = (0, import_react.useMemo)(
728
+ const value = (0, import_react2.useMemo)(
122
729
  () => ({
123
730
  ...state,
124
731
  appType: resolvedAppType,
@@ -128,10 +735,10 @@ var OpenXiangdaProvider = ({
128
735
  }),
129
736
  [reload, resolvedAppType, resolvedFetch, servicePrefix, state]
130
737
  );
131
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(OpenXiangdaRuntimeContext.Provider, { value, children });
738
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(OpenXiangdaRuntimeContext.Provider, { value, children });
132
739
  };
133
740
  var useOpenXiangda = () => {
134
- const context = (0, import_react.useContext)(OpenXiangdaRuntimeContext);
741
+ const context = (0, import_react2.useContext)(OpenXiangdaRuntimeContext);
135
742
  if (!context) {
136
743
  throw new Error("useOpenXiangda must be used inside OpenXiangdaProvider");
137
744
  }
@@ -154,12 +761,12 @@ var usePermission = () => {
154
761
  };
155
762
  var useCanAccessRoute = (input) => {
156
763
  const runtime = useOpenXiangda();
157
- const [state, setState] = (0, import_react.useState)({
764
+ const [state, setState] = (0, import_react2.useState)({
158
765
  data: null,
159
766
  loading: true,
160
767
  error: null
161
768
  });
162
- (0, import_react.useEffect)(() => {
769
+ (0, import_react2.useEffect)(() => {
163
770
  let disposed = false;
164
771
  const check = async () => {
165
772
  const permissions = runtime.data?.permissions;
@@ -195,7 +802,7 @@ var useCanAccessRoute = (input) => {
195
802
  setState((prev) => ({ ...prev, loading: true, error: null }));
196
803
  try {
197
804
  const response = await runtime.fetchImpl(
198
- buildServiceUrl(
805
+ buildServiceUrl2(
199
806
  runtime.servicePrefix,
200
807
  `/openxiangda-api/v1/apps/${encodeURIComponent(
201
808
  runtime.appType
@@ -281,23 +888,23 @@ var PermissionBoundary = ({
281
888
  const access = useCanAccessRoute({ routeCode, menuCode, path });
282
889
  const fallbackState = createPermissionFallbackState(access, runtime);
283
890
  if (access.loading) {
284
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children: renderBoundaryFallback(loadingFallback, fallbackState) });
891
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_jsx_runtime2.Fragment, { children: renderBoundaryFallback(loadingFallback, fallbackState) });
285
892
  }
286
893
  if (!access.canAccess) {
287
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children: renderBoundaryFallback(fallback, fallbackState) });
894
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_jsx_runtime2.Fragment, { children: renderBoundaryFallback(fallback, fallbackState) });
288
895
  }
289
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children });
896
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_jsx_runtime2.Fragment, { children });
290
897
  };
291
898
  var useRuntimeAuth = () => {
292
899
  const runtime = useOpenXiangda();
293
- const resolveLoginUrl = (0, import_react.useCallback)(
900
+ const resolveLoginUrl2 = (0, import_react2.useCallback)(
294
901
  async (options = {}) => {
295
- const redirectUri = options.redirectUri || getCurrentHref();
296
- const domain = options.domain || getCurrentHostname();
902
+ const redirectUri = options.redirectUri || getCurrentHref3();
903
+ const domain = options.domain || getCurrentHostname2();
297
904
  const appTenantId = getRecordString(runtime.data?.app, "tenantId");
298
905
  try {
299
906
  const statusUrl = withQuery(
300
- buildServiceUrl(runtime.servicePrefix, "/api/sso/status"),
907
+ buildServiceUrl2(runtime.servicePrefix, "/api/sso/status"),
301
908
  { domain }
302
909
  );
303
910
  const statusResponse = await runtime.fetchImpl(statusUrl, {
@@ -312,7 +919,7 @@ var useRuntimeAuth = () => {
312
919
  );
313
920
  if (shouldUseSso) {
314
921
  const loginUrlResponse = await runtime.fetchImpl(
315
- withQuery(buildServiceUrl(runtime.servicePrefix, "/api/sso/login-url"), {
922
+ withQuery(buildServiceUrl2(runtime.servicePrefix, "/api/sso/login-url"), {
316
923
  domain,
317
924
  redirectUri,
318
925
  ...sso.tenantId || appTenantId ? { tenantId: String(sso.tenantId || appTenantId) } : {},
@@ -337,9 +944,9 @@ var useRuntimeAuth = () => {
337
944
  },
338
945
  [runtime.data?.app, runtime.fetchImpl, runtime.servicePrefix]
339
946
  );
340
- const redirectToLogin = (0, import_react.useCallback)(
947
+ const redirectToLogin = (0, import_react2.useCallback)(
341
948
  async (options = {}) => {
342
- const loginUrl = await resolveLoginUrl(options);
949
+ const loginUrl = await resolveLoginUrl2(options);
343
950
  if (typeof window !== "undefined") {
344
951
  if (options.replace === false) {
345
952
  window.location.assign(loginUrl);
@@ -349,11 +956,11 @@ var useRuntimeAuth = () => {
349
956
  }
350
957
  return loginUrl;
351
958
  },
352
- [resolveLoginUrl]
959
+ [resolveLoginUrl2]
353
960
  );
354
- const logout = (0, import_react.useCallback)(async () => {
961
+ const logout = (0, import_react2.useCallback)(async () => {
355
962
  const response = await runtime.fetchImpl(
356
- buildServiceUrl(runtime.servicePrefix, "/api/auth/logout"),
963
+ buildServiceUrl2(runtime.servicePrefix, "/api/auth/logout"),
357
964
  {
358
965
  method: "POST",
359
966
  credentials: "include",
@@ -370,7 +977,7 @@ var useRuntimeAuth = () => {
370
977
  }
371
978
  return payload;
372
979
  }, [runtime.fetchImpl, runtime.servicePrefix]);
373
- const logoutAndRedirect = (0, import_react.useCallback)(
980
+ const logoutAndRedirect = (0, import_react2.useCallback)(
374
981
  async (options = {}) => {
375
982
  try {
376
983
  await logout();
@@ -385,10 +992,10 @@ var useRuntimeAuth = () => {
385
992
  logout,
386
993
  logoutAndRedirect,
387
994
  redirectToLogin,
388
- resolveLoginUrl
995
+ resolveLoginUrl: resolveLoginUrl2
389
996
  };
390
997
  };
391
- var buildServiceUrl = (servicePrefix, path) => {
998
+ var buildServiceUrl2 = (servicePrefix, path) => {
392
999
  const prefix = servicePrefix.endsWith("/") ? servicePrefix.slice(0, -1) : servicePrefix;
393
1000
  const suffix = path.startsWith("/") ? path : `/${path}`;
394
1001
  return `${prefix}${suffix}`;
@@ -403,11 +1010,11 @@ var readJsonPayload = async (response) => {
403
1010
  var createRuntimeHttpError = (response, payload, fallbackMessage) => createRuntimeError({
404
1011
  type: classifyRuntimeError(
405
1012
  response.status,
406
- getRecordValue(payload, "code")
1013
+ getRecordValue2(payload, "code")
407
1014
  ),
408
1015
  status: response.status,
409
- code: getRecordValue(payload, "code"),
410
- message: getRecordValue(payload, "message") || fallbackMessage,
1016
+ code: getRecordValue2(payload, "code"),
1017
+ message: getRecordValue2(payload, "message") || fallbackMessage,
411
1018
  payload
412
1019
  });
413
1020
  var createRuntimeError = (snapshot) => new RuntimeHttpError({
@@ -483,18 +1090,18 @@ var attachCallback = (loginUrl, callback) => {
483
1090
  return `${loginUrl}${separator}callback=${encodeURIComponent(callback)}`;
484
1091
  }
485
1092
  };
486
- var getCurrentHref = () => typeof window === "undefined" ? "" : window.location.href;
487
- var getCurrentHostname = () => typeof window === "undefined" ? "" : window.location.hostname;
1093
+ var getCurrentHref3 = () => typeof window === "undefined" ? "" : window.location.href;
1094
+ var getCurrentHostname2 = () => typeof window === "undefined" ? "" : window.location.hostname;
488
1095
  var getRuntimeEnv = (key) => {
489
1096
  const env = typeof process !== "undefined" ? process.env : void 0;
490
1097
  return env?.[key];
491
1098
  };
492
- var getRecordValue = (value, key) => {
1099
+ var getRecordValue2 = (value, key) => {
493
1100
  if (!value || typeof value !== "object") return void 0;
494
1101
  return value[key];
495
1102
  };
496
1103
  var getRecordString = (value, key) => {
497
- const result = getRecordValue(value, key);
1104
+ const result = getRecordValue2(value, key);
498
1105
  return typeof result === "string" ? result : void 0;
499
1106
  };
500
1107
  var resolveAppTypeFromLocation = () => {