@lark-apaas/client-toolkit 1.2.10-alpha.4 → 1.2.10-alpha.40
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.
- package/lib/apis/hooks/useScrollReveal.d.ts +1 -0
- package/lib/apis/hooks/useScrollReveal.js +1 -0
- package/lib/apis/utils/scopedStorage.d.ts +1 -0
- package/lib/apis/utils/scopedStorage.js +2 -0
- package/lib/components/AppContainer/api-proxy/core.js +2 -1
- package/lib/components/AppContainer/index.js +8 -2
- package/lib/components/AppContainer/safety.js +5 -2
- package/lib/components/AppContainer/utils/childApi.js +1 -0
- package/lib/components/AppContainer/utils/getLarkUser.js +4 -2
- package/lib/components/AppContainer/utils/observable.js +7 -1
- package/lib/components/AppContainer/utils/tea.js +1 -1
- package/lib/components/ErrorRender/index.js +5 -11
- package/lib/components/User/UserSelect.js +1 -13
- package/lib/components/ui/toast.d.ts +2 -0
- package/lib/components/ui/toast.js +53 -0
- package/lib/hooks/index.d.ts +1 -0
- package/lib/hooks/index.js +1 -0
- package/lib/hooks/useLogout.js +2 -17
- package/lib/hooks/useScrollReveal.d.ts +61 -0
- package/lib/hooks/useScrollReveal.js +37 -0
- package/lib/index.js +12 -1
- package/lib/integrations/dataloom.js +5 -3
- package/lib/integrations/services/DepartmentService.js +3 -2
- package/lib/integrations/services/UserProfileService.js +3 -2
- package/lib/integrations/services/UserService.js +4 -3
- package/lib/logger/intercept-global-error.js +16 -14
- package/lib/theme-layer.css +2 -1
- package/lib/utils/apiPath.d.ts +5 -0
- package/lib/utils/apiPath.js +5 -0
- package/lib/utils/axiosConfig.js +6 -5
- package/lib/utils/getAppId.d.ts +2 -4
- package/lib/utils/getAppId.js +2 -9
- package/lib/utils/getInitialInfo.js +5 -3
- package/lib/utils/getUserProfile.js +4 -12
- package/lib/utils/hmr-api.d.ts +39 -0
- package/lib/utils/hmr-api.js +36 -0
- package/lib/utils/module-hot.d.ts +7 -2
- package/lib/utils/module-hot.js +6 -51
- package/lib/utils/requestManager.js +1 -3
- package/lib/utils/scopedStorage.d.ts +5 -0
- package/lib/utils/scopedStorage.js +46 -0
- package/package.json +5 -5
- package/lib/apis/tools/generateImage.d.ts +0 -1
- package/lib/apis/tools/generateImage.js +0 -1
- package/lib/apis/tools/generateTextStream.d.ts +0 -1
- package/lib/apis/tools/generateTextStream.js +0 -1
- package/lib/integrations/generateImage.d.ts +0 -1
- package/lib/integrations/generateImage.js +0 -47
- package/lib/integrations/generateTextStream.d.ts +0 -21
- package/lib/integrations/generateTextStream.js +0 -98
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from '../../hooks/useScrollReveal';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "../../hooks/useScrollReveal.js";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { scopedStorage } from '../../utils/scopedStorage';
|
|
@@ -139,7 +139,8 @@ class ApiProxy {
|
|
|
139
139
|
...config,
|
|
140
140
|
headers: {
|
|
141
141
|
...this.defaultConfig.headers,
|
|
142
|
-
...config.headers
|
|
142
|
+
...config.headers,
|
|
143
|
+
'X-Page-Route': 'undefined' != typeof window ? window.location?.pathname || '/' : '/'
|
|
143
144
|
}
|
|
144
145
|
};
|
|
145
146
|
const requestKey = this.generateRequestKey(mergedConfig);
|
|
@@ -13,6 +13,7 @@ import { useAppInfo } from "../../hooks/index.js";
|
|
|
13
13
|
import { TrackKey } from "../../types/tea.js";
|
|
14
14
|
import safety from "./safety.js";
|
|
15
15
|
import { getAppId } from "../../utils/getAppId.js";
|
|
16
|
+
import { isNewPathEnabled } from "../../utils/apiPath.js";
|
|
16
17
|
import QueryProvider from "../QueryProvider/index.js";
|
|
17
18
|
import { AuthProvider } from "@lark-apaas/auth-sdk";
|
|
18
19
|
import "../../runtime/index.js";
|
|
@@ -52,15 +53,20 @@ const App = (props)=>{
|
|
|
52
53
|
if ('production' === process.env.NODE_ENV) reportTeaEvent({
|
|
53
54
|
trackKey: TrackKey.VIEW,
|
|
54
55
|
trackParams: {
|
|
55
|
-
artifact_uid: getAppId(
|
|
56
|
+
artifact_uid: getAppId(),
|
|
56
57
|
agent_id: 'agent_miaoda',
|
|
57
58
|
url: window.location.href
|
|
58
59
|
}
|
|
59
60
|
});
|
|
60
61
|
}, []);
|
|
62
|
+
const appId = getAppId();
|
|
63
|
+
const permissionApiUrl = isNewPathEnabled() ? `/app/${appId}/__runtime__/api/v1/permissions/roles` : `/spark/app/${appId}/runtime/api/v1/permissions/roles`;
|
|
61
64
|
return /*#__PURE__*/ jsxs(AuthProvider, {
|
|
62
65
|
config: {
|
|
63
|
-
enable: enableAuth
|
|
66
|
+
enable: enableAuth,
|
|
67
|
+
permissionApi: {
|
|
68
|
+
url: permissionApiUrl
|
|
69
|
+
}
|
|
64
70
|
},
|
|
65
71
|
children: [
|
|
66
72
|
/*#__PURE__*/ jsx(Toaster, {}),
|
|
@@ -3,11 +3,12 @@ import { useEffect, useRef, useState } from "react";
|
|
|
3
3
|
import { Popover, PopoverContent, PopoverTrigger } from "../ui/popover.js";
|
|
4
4
|
import { getCsrfToken } from "../../utils/getCsrfToken.js";
|
|
5
5
|
import { getAppId } from "../../utils/getAppId.js";
|
|
6
|
+
import { isNewPathEnabled } from "../../utils/apiPath.js";
|
|
6
7
|
import { useIsMobile } from "../../hooks/index.js";
|
|
7
8
|
import { X } from "lucide-react";
|
|
8
9
|
import { Sheet, SheetContent, SheetTrigger } from "../ui/drawer.js";
|
|
9
10
|
const Component = ()=>{
|
|
10
|
-
const HasClosedKey = `miaoda-creatByMiaoda-has-closed-${getAppId(
|
|
11
|
+
const HasClosedKey = `miaoda-creatByMiaoda-has-closed-${getAppId()}`;
|
|
11
12
|
const [visible, setVisible] = useState(!window.localStorage?.getItem(HasClosedKey));
|
|
12
13
|
const [open, setOpen] = useState(false);
|
|
13
14
|
const isMobile = useIsMobile();
|
|
@@ -15,7 +16,9 @@ const Component = ()=>{
|
|
|
15
16
|
const [isInternetVisible, setIsInternetVisible] = useState(false);
|
|
16
17
|
const timeoutRef = useRef(null);
|
|
17
18
|
useEffect(()=>{
|
|
18
|
-
|
|
19
|
+
const appId = getAppId();
|
|
20
|
+
const tenantInfoUrl = isNewPathEnabled() ? `/app/${appId}/__runtime__/api/v1/studio/tenant_info` : `/spark/b/${appId}/tenant_info`;
|
|
21
|
+
fetch(tenantInfoUrl, {
|
|
19
22
|
headers: {
|
|
20
23
|
'X-Suda-Csrf-Token': getCsrfToken()
|
|
21
24
|
}
|
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import { getAppId } from "../../../utils/getAppId.js";
|
|
2
2
|
import { getCsrfToken } from "../../../utils/getCsrfToken.js";
|
|
3
|
+
import { isNewPathEnabled } from "../../../utils/apiPath.js";
|
|
3
4
|
async function getLarkUserInfo() {
|
|
4
|
-
const appId = getAppId(
|
|
5
|
+
const appId = getAppId();
|
|
5
6
|
if (!appId) return {
|
|
6
7
|
code: 1,
|
|
7
8
|
msg: 'appId is required',
|
|
8
9
|
data: {}
|
|
9
10
|
};
|
|
10
|
-
const
|
|
11
|
+
const url = isNewPathEnabled() ? `/app/${appId}/__runtime__/api/v1/studio/lark/user_info` : `/spark/b/${appId}/lark/user_info`;
|
|
12
|
+
const response = await fetch(url, {
|
|
11
13
|
headers: {
|
|
12
14
|
'X-Suda-Csrf-Token': getCsrfToken()
|
|
13
15
|
}
|
|
@@ -1,11 +1,17 @@
|
|
|
1
1
|
import { AppEnv, observable } from "@lark-apaas/observable-web";
|
|
2
|
+
import { isNewPathEnabled } from "../../../utils/apiPath.js";
|
|
2
3
|
const initObservable = ()=>{
|
|
3
4
|
try {
|
|
4
5
|
const appId = window.appId;
|
|
5
6
|
observable.start({
|
|
6
7
|
serviceName: "app",
|
|
7
8
|
env: 'development' === process.env.NODE_ENV ? AppEnv.Dev : AppEnv.Prod,
|
|
8
|
-
collectorUrl: {
|
|
9
|
+
collectorUrl: isNewPathEnabled() ? {
|
|
10
|
+
log: `/app/${appId}/__runtime__/api/v1/observability/logs/collect`,
|
|
11
|
+
trace: `/app/${appId}/__runtime__/api/v1/observability/traces/collect`,
|
|
12
|
+
metric: `/app/${appId}/__runtime__/api/v1/observability/metrics/collect`,
|
|
13
|
+
time: `/app/${appId}/__runtime__/api/v1/observability/current_server_timestamp`
|
|
14
|
+
} : {
|
|
9
15
|
log: `/spark/app/${appId}/runtime/api/v1/observability/logs/collect`,
|
|
10
16
|
trace: `/spark/app/${appId}/runtime/api/v1/observability/traces/collect`,
|
|
11
17
|
metric: `/spark/app/${appId}/runtime/api/v1/observability/metrics/collect`,
|
|
@@ -16,7 +16,7 @@ async function createTracker() {
|
|
|
16
16
|
const userIDEncrypt = userID && '0' !== userID ? encryptTea(userID) : void 0;
|
|
17
17
|
const tenantIDEncrypt = tenantID && '0' !== tenantID ? encryptTea(tenantID) : void 0;
|
|
18
18
|
window.collectEvent('init', {
|
|
19
|
-
app_id:
|
|
19
|
+
app_id: 788827,
|
|
20
20
|
channel: 'cn',
|
|
21
21
|
disable_auto_pv: false,
|
|
22
22
|
enable_ab_test: false,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useEffect } from "react";
|
|
3
3
|
import { logger } from "../../logger/index.js";
|
|
4
|
-
import {
|
|
4
|
+
import { getHmrApi } from "../../utils/hmr-api.js";
|
|
5
5
|
import { submitPostMessage } from "../../utils/postMessage.js";
|
|
6
6
|
const RenderError = (props)=>{
|
|
7
7
|
const { error, resetErrorBoundary } = props;
|
|
@@ -27,16 +27,10 @@ const RenderError = (props)=>{
|
|
|
27
27
|
]);
|
|
28
28
|
useEffect(()=>{
|
|
29
29
|
if (!resetErrorBoundary) return;
|
|
30
|
-
const
|
|
31
|
-
if (
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
});
|
|
35
|
-
hot.addStatusHandler(handler);
|
|
36
|
-
return ()=>{
|
|
37
|
-
hot.removeStatusHandler(handler);
|
|
38
|
-
};
|
|
39
|
-
}
|
|
30
|
+
const hmr = getHmrApi();
|
|
31
|
+
if (hmr) return hmr.onSuccess(()=>{
|
|
32
|
+
resetErrorBoundary();
|
|
33
|
+
});
|
|
40
34
|
}, [
|
|
41
35
|
resetErrorBoundary
|
|
42
36
|
]);
|
|
@@ -67,20 +67,8 @@ const UserSelect = ({ mode = 'single', defaultValue, value, onChange, placeholde
|
|
|
67
67
|
if (!normalizedIds.length) return void setUiValue(void 0);
|
|
68
68
|
const fetchProfiles = async ()=>{
|
|
69
69
|
try {
|
|
70
|
-
const ids = normalizedIds.map((id)=>Number(id)).filter((id)=>Number.isFinite(id));
|
|
71
|
-
if (!ids.length) {
|
|
72
|
-
const profiles = normalizedIds.map((id)=>inputProfilesMap.get(id) ?? {
|
|
73
|
-
user_id: id,
|
|
74
|
-
name: '',
|
|
75
|
-
avatar: '',
|
|
76
|
-
email: '',
|
|
77
|
-
status: 1
|
|
78
|
-
});
|
|
79
|
-
setUiValue('single' === mode ? profiles[0] : profiles);
|
|
80
|
-
return;
|
|
81
|
-
}
|
|
82
70
|
const dataloom = await getDataloom();
|
|
83
|
-
const response = await dataloom.service.user.getByIds(
|
|
71
|
+
const response = await dataloom.service.user.getByIds(normalizedIds);
|
|
84
72
|
const fetchedList = Array.isArray(response?.data) ? response?.data : Array.isArray(response?.data?.user_list) ? response?.data?.user_list : [];
|
|
85
73
|
const fetchedMap = new Map();
|
|
86
74
|
fetchedList.forEach((profile)=>{
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
function showToast(message, duration = 3000) {
|
|
2
|
+
return new Promise((resolve)=>{
|
|
3
|
+
const toast = document.createElement('div');
|
|
4
|
+
const iconSvg = `<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
5
|
+
<path fill-rule="evenodd" clip-rule="evenodd" d="M8 1.333a6.667 6.667 0 1 1 0 13.334A6.667 6.667 0 0 1 8 1.333ZM8 10a.667.667 0 1 0 0 1.333A.667.667 0 0 0 8 10Zm0-5.333a.667.667 0 0 0-.667.666v3.334a.667.667 0 0 0 1.334 0V5.333A.667.667 0 0 0 8 4.667Z" fill="#ff811a"/>
|
|
6
|
+
</svg>`;
|
|
7
|
+
const iconWrapper = document.createElement('span');
|
|
8
|
+
iconWrapper.innerHTML = iconSvg;
|
|
9
|
+
Object.assign(iconWrapper.style, {
|
|
10
|
+
display: 'flex',
|
|
11
|
+
alignItems: 'center',
|
|
12
|
+
marginRight: '8px',
|
|
13
|
+
flexShrink: '0'
|
|
14
|
+
});
|
|
15
|
+
const textWrapper = document.createElement('span');
|
|
16
|
+
textWrapper.textContent = message;
|
|
17
|
+
toast.appendChild(iconWrapper);
|
|
18
|
+
toast.appendChild(textWrapper);
|
|
19
|
+
Object.assign(toast.style, {
|
|
20
|
+
position: 'fixed',
|
|
21
|
+
top: '32px',
|
|
22
|
+
left: '50%',
|
|
23
|
+
transform: 'translate(-50%, -50%)',
|
|
24
|
+
display: 'flex',
|
|
25
|
+
alignItems: 'center',
|
|
26
|
+
padding: '12px 16px',
|
|
27
|
+
backgroundColor: '#fff',
|
|
28
|
+
color: '#1f2329',
|
|
29
|
+
border: '1px solid #dee0e3',
|
|
30
|
+
borderRadius: '6px',
|
|
31
|
+
fontSize: '14px',
|
|
32
|
+
lineHeight: '1.5',
|
|
33
|
+
zIndex: '99999',
|
|
34
|
+
maxWidth: '80vw',
|
|
35
|
+
wordBreak: 'break-word',
|
|
36
|
+
boxShadow: '0 4px 8px rgba(0, 0, 0, 0.03), 0 3px 6px rgba(0, 0, 0, 0.05), 0 6px 18px rgba(0, 0, 0, 0.03)',
|
|
37
|
+
opacity: '0',
|
|
38
|
+
transition: 'opacity 0.3s ease'
|
|
39
|
+
});
|
|
40
|
+
document.body.appendChild(toast);
|
|
41
|
+
requestAnimationFrame(()=>{
|
|
42
|
+
toast.style.opacity = '1';
|
|
43
|
+
});
|
|
44
|
+
setTimeout(()=>{
|
|
45
|
+
toast.style.opacity = '0';
|
|
46
|
+
setTimeout(()=>{
|
|
47
|
+
document.body.removeChild(toast);
|
|
48
|
+
resolve();
|
|
49
|
+
}, 300);
|
|
50
|
+
}, duration);
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
export { showToast };
|
package/lib/hooks/index.d.ts
CHANGED
package/lib/hooks/index.js
CHANGED
package/lib/hooks/useLogout.js
CHANGED
|
@@ -1,28 +1,13 @@
|
|
|
1
1
|
import { useState } from "react";
|
|
2
2
|
import { getDataloom } from "../integrations/dataloom.js";
|
|
3
|
-
import { isSparkRuntime } from "../utils/utils.js";
|
|
4
3
|
function useLogout() {
|
|
5
4
|
const [isLoading, setIsLoading] = useState(false);
|
|
6
5
|
async function handlerLogout() {
|
|
7
6
|
if ('production' !== process.env.NODE_ENV) return void console.log('只有生产环境才执行登出');
|
|
8
|
-
if (isSparkRuntime()) {
|
|
9
|
-
setIsLoading(true);
|
|
10
|
-
try {
|
|
11
|
-
const dataloom = await getDataloom();
|
|
12
|
-
await dataloom.service.session.signOut();
|
|
13
|
-
} catch (error) {
|
|
14
|
-
console.error('登出失败', error);
|
|
15
|
-
} finally{
|
|
16
|
-
setIsLoading(false);
|
|
17
|
-
}
|
|
18
|
-
return;
|
|
19
|
-
}
|
|
20
7
|
setIsLoading(true);
|
|
21
8
|
try {
|
|
22
|
-
await
|
|
23
|
-
|
|
24
|
-
});
|
|
25
|
-
window.location.reload();
|
|
9
|
+
const dataloom = await getDataloom();
|
|
10
|
+
await dataloom.service.session.signOut();
|
|
26
11
|
} catch (error) {
|
|
27
12
|
console.error('登出失败', error);
|
|
28
13
|
} finally{
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { RefObject } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Options for useScrollReveal hook
|
|
4
|
+
*/
|
|
5
|
+
export interface UseScrollRevealOptions<T extends HTMLElement = HTMLElement> {
|
|
6
|
+
/** Ref to the container element to scope the query (default: document.body) */
|
|
7
|
+
containerRef?: RefObject<T | null>;
|
|
8
|
+
/** IntersectionObserver threshold - element visibility percentage to trigger (default: 0.1) */
|
|
9
|
+
threshold?: number;
|
|
10
|
+
/** IntersectionObserver rootMargin - margin around root (default: '0px 0px -50px 0px') */
|
|
11
|
+
rootMargin?: string;
|
|
12
|
+
/** CSS class to add when element becomes visible (default: 'visible') */
|
|
13
|
+
visibleClass?: string;
|
|
14
|
+
/** CSS selector for elements to observe (default: '.scroll-reveal') */
|
|
15
|
+
selector?: string;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Hook to enable scroll reveal animations using IntersectionObserver.
|
|
19
|
+
*
|
|
20
|
+
* Observes elements with the specified selector and adds a visibility class
|
|
21
|
+
* when they enter the viewport.
|
|
22
|
+
*
|
|
23
|
+
* @param options - Configuration options
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* ```tsx
|
|
27
|
+
* // Usage without parameters (queries entire document.body)
|
|
28
|
+
* import { useScrollReveal } from '@lark-apaas/client-toolkit/hooks/useScrollReveal';
|
|
29
|
+
*
|
|
30
|
+
* function MyComponent() {
|
|
31
|
+
* useScrollReveal();
|
|
32
|
+
*
|
|
33
|
+
* return <div className="scroll-reveal">I will fade in on scroll!</div>;
|
|
34
|
+
* }
|
|
35
|
+
* ```
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* ```tsx
|
|
39
|
+
* // Usage with container ref
|
|
40
|
+
* import { useRef } from 'react';
|
|
41
|
+
* import { useScrollReveal } from '@lark-apaas/client-toolkit/hooks/useScrollReveal';
|
|
42
|
+
*
|
|
43
|
+
* function MyComponent() {
|
|
44
|
+
* const containerRef = useRef<HTMLDivElement>(null);
|
|
45
|
+
* useScrollReveal({ containerRef });
|
|
46
|
+
*
|
|
47
|
+
* return (
|
|
48
|
+
* <div ref={containerRef}>
|
|
49
|
+
* <div className="scroll-reveal">I will fade in on scroll!</div>
|
|
50
|
+
* </div>
|
|
51
|
+
* );
|
|
52
|
+
* }
|
|
53
|
+
* ```
|
|
54
|
+
*
|
|
55
|
+
* @example
|
|
56
|
+
* ```tsx
|
|
57
|
+
* // Usage with custom options
|
|
58
|
+
* useScrollReveal({ threshold: 0.2, visibleClass: 'animate-in' });
|
|
59
|
+
* ```
|
|
60
|
+
*/
|
|
61
|
+
export declare function useScrollReveal<T extends HTMLElement = HTMLElement>(options?: UseScrollRevealOptions<T>): void;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { useEffect } from "react";
|
|
2
|
+
const DEFAULT_OPTIONS = {
|
|
3
|
+
threshold: 0.1,
|
|
4
|
+
rootMargin: '0px 0px -50px 0px',
|
|
5
|
+
visibleClass: 'visible',
|
|
6
|
+
selector: '.scroll-reveal'
|
|
7
|
+
};
|
|
8
|
+
function useScrollReveal(options) {
|
|
9
|
+
const { containerRef, threshold, rootMargin, visibleClass, selector } = {
|
|
10
|
+
...DEFAULT_OPTIONS,
|
|
11
|
+
...options
|
|
12
|
+
};
|
|
13
|
+
useEffect(()=>{
|
|
14
|
+
const container = containerRef?.current ?? document.body;
|
|
15
|
+
if (!container) return;
|
|
16
|
+
const observer = new IntersectionObserver((entries)=>{
|
|
17
|
+
entries.forEach((entry)=>{
|
|
18
|
+
if (entry.isIntersecting) entry.target.classList.add(visibleClass);
|
|
19
|
+
});
|
|
20
|
+
}, {
|
|
21
|
+
threshold,
|
|
22
|
+
rootMargin
|
|
23
|
+
});
|
|
24
|
+
const elements = container.querySelectorAll(selector);
|
|
25
|
+
elements.forEach((el)=>observer.observe(el));
|
|
26
|
+
return ()=>{
|
|
27
|
+
observer.disconnect();
|
|
28
|
+
};
|
|
29
|
+
}, [
|
|
30
|
+
containerRef,
|
|
31
|
+
threshold,
|
|
32
|
+
rootMargin,
|
|
33
|
+
visibleClass,
|
|
34
|
+
selector
|
|
35
|
+
]);
|
|
36
|
+
}
|
|
37
|
+
export { useScrollReveal };
|
package/lib/index.js
CHANGED
|
@@ -1,15 +1,26 @@
|
|
|
1
1
|
import { createClient } from "@lark-apaas/client-capability";
|
|
2
2
|
import { normalizeBasePath } from "./utils/utils.js";
|
|
3
|
+
import { getAppId } from "./utils/getAppId.js";
|
|
4
|
+
import { isNewPathEnabled } from "./utils/apiPath.js";
|
|
3
5
|
import { logger } from "./logger/index.js";
|
|
6
|
+
import { showToast } from "./components/ui/toast.js";
|
|
4
7
|
import { version } from "../package.json";
|
|
8
|
+
const _appId = getAppId();
|
|
9
|
+
const _acquireUploadUrl = isNewPathEnabled() ? `/app/${_appId}/__runtime__/api/v1/studio/plugins/tmp_files/acquire_upload_url` : "/af/api/v1/studio/plugins/tmp_files/acquire_upload_url";
|
|
10
|
+
const _acquireDownloadUrl = isNewPathEnabled() ? `/app/${_appId}/__runtime__/api/v1/studio/plugins/tmp_files/acquire_download_url` : "/af/api/v1/studio/plugins/tmp_files/acquire_download_url";
|
|
5
11
|
const capabilityClient = createClient({
|
|
6
12
|
baseURL: normalizeBasePath(process.env.CLIENT_BASE_PATH),
|
|
13
|
+
acquireUploadUrl: _acquireUploadUrl,
|
|
14
|
+
acquireDownloadUrl: _acquireDownloadUrl,
|
|
7
15
|
fetchOptions: {
|
|
8
16
|
headers: {
|
|
9
17
|
'X-Suda-Csrf-Token': window.csrfToken ?? ''
|
|
10
18
|
}
|
|
11
19
|
},
|
|
12
|
-
logger: logger
|
|
20
|
+
logger: logger,
|
|
21
|
+
onRateLimitError: ()=>{
|
|
22
|
+
showToast('应用额度已耗尽,请联系应用开发者');
|
|
23
|
+
}
|
|
13
24
|
});
|
|
14
25
|
const src = {
|
|
15
26
|
version: version
|
|
@@ -3,9 +3,11 @@ import { createClient } from "@data-loom/js";
|
|
|
3
3
|
import { getAppId } from "../utils/getAppId.js";
|
|
4
4
|
import { getInitialInfo } from "../utils/getInitialInfo.js";
|
|
5
5
|
const createDataLoomClient = (url, pat)=>{
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
const { baseUrl, workspace } = url ? splitWorkspaceUrl(url) : {
|
|
7
|
+
baseUrl: '',
|
|
8
|
+
workspace: ''
|
|
9
|
+
};
|
|
10
|
+
const appId = getAppId();
|
|
9
11
|
return createClient(baseUrl, pat, workspace, {
|
|
10
12
|
global: {
|
|
11
13
|
enableDataloomLog: 'production' !== process.env.NODE_ENV,
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { getAppId } from "../../utils/getAppId.js";
|
|
2
|
+
import { isNewPathEnabled } from "../../utils/apiPath.js";
|
|
2
3
|
const DEFAULT_CONFIG = {
|
|
3
|
-
getAppId: ()=>getAppId(
|
|
4
|
-
searchDepartmentUrl: (appId)
|
|
4
|
+
getAppId: ()=>getAppId(),
|
|
5
|
+
searchDepartmentUrl: (appId)=>isNewPathEnabled() ? `/app/${appId}/__runtime__/api/v1/account/search_department` : `/af/app/${appId}/runtime/api/v1/account/search_department`
|
|
5
6
|
};
|
|
6
7
|
class DepartmentService {
|
|
7
8
|
config;
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { getAppId } from "../../utils/getAppId.js";
|
|
2
|
+
import { isNewPathEnabled } from "../../utils/apiPath.js";
|
|
2
3
|
const CDN_HOST = 'https://lf3-static.bytednsdoc.com';
|
|
3
4
|
function getAssetsUrl(path) {
|
|
4
5
|
return `${CDN_HOST}${path}`;
|
|
5
6
|
}
|
|
6
7
|
const DEFAULT_CONFIG = {
|
|
7
|
-
getAppId: ()=>getAppId(
|
|
8
|
-
userProfileUrl: (appId)
|
|
8
|
+
getAppId: ()=>getAppId(),
|
|
9
|
+
userProfileUrl: (appId)=>isNewPathEnabled() ? `/app/${appId}/__runtime__/api/v1/account/user_profile` : `/af/app/${appId}/runtime/api/v1/account/user_profile`
|
|
9
10
|
};
|
|
10
11
|
class UserProfileService {
|
|
11
12
|
config;
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { getAppId } from "../../utils/getAppId.js";
|
|
2
|
+
import { isNewPathEnabled } from "../../utils/apiPath.js";
|
|
2
3
|
const DEFAULT_CONFIG = {
|
|
3
|
-
getAppId: ()=>getAppId(
|
|
4
|
-
searchUserUrl: (appId)
|
|
5
|
-
listUsersUrl: (appId)
|
|
4
|
+
getAppId: ()=>getAppId(),
|
|
5
|
+
searchUserUrl: (appId)=>isNewPathEnabled() ? `/app/${appId}/__runtime__/api/v1/account/search_user` : `/af/app/${appId}/runtime/api/v1/account/search_user`,
|
|
6
|
+
listUsersUrl: (appId)=>isNewPathEnabled() ? `/app/${appId}/__runtime__/api/v1/account/list_users` : `/af/app/${appId}/runtime/api/v1/account/list_users`
|
|
6
7
|
};
|
|
7
8
|
class UserService {
|
|
8
9
|
config;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { getHmrApi } from "../utils/hmr-api.js";
|
|
2
2
|
import { submitPostMessage, submitSlardarEvent } from "../utils/postMessage.js";
|
|
3
3
|
import { levelSchema } from "./log-types.js";
|
|
4
4
|
import { logger } from "./logger.js";
|
|
@@ -63,26 +63,28 @@ function processDevServerLog(log) {
|
|
|
63
63
|
}
|
|
64
64
|
}
|
|
65
65
|
function listenModuleHmr() {
|
|
66
|
-
const
|
|
67
|
-
if (
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
66
|
+
const hmr = getHmrApi();
|
|
67
|
+
if (hmr) {
|
|
68
|
+
hmr.onSuccess(()=>{
|
|
69
|
+
submitPostMessage({
|
|
70
|
+
type: 'DevServerMessage',
|
|
71
|
+
data: {
|
|
72
|
+
type: 'devServer-status',
|
|
73
|
+
status: 'hmr-apply-success'
|
|
74
|
+
}
|
|
75
|
+
});
|
|
74
76
|
});
|
|
75
|
-
|
|
76
|
-
console.warn('hmr apply failed',
|
|
77
|
+
hmr.onError((error)=>{
|
|
78
|
+
console.warn('hmr apply failed', error);
|
|
77
79
|
submitSlardarEvent({
|
|
78
80
|
name: 'sandbox-devServer',
|
|
79
81
|
categories: {
|
|
80
82
|
type: 'hmr-apply-failed',
|
|
81
|
-
|
|
83
|
+
error: String(error)
|
|
82
84
|
}
|
|
83
85
|
});
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
+
});
|
|
87
|
+
}
|
|
86
88
|
}
|
|
87
89
|
function interceptErrors() {
|
|
88
90
|
window.addEventListener('error', (event)=>{
|
package/lib/theme-layer.css
CHANGED
package/lib/utils/axiosConfig.js
CHANGED
|
@@ -54,7 +54,7 @@ async function logResponse(ok, responseOrError) {
|
|
|
54
54
|
logTraceID
|
|
55
55
|
};
|
|
56
56
|
if (stacktrace) logMeta.stacktrace = stacktrace;
|
|
57
|
-
logger.
|
|
57
|
+
logger.log({
|
|
58
58
|
level: ok,
|
|
59
59
|
args: [
|
|
60
60
|
parts.join(''),
|
|
@@ -110,7 +110,7 @@ async function logResponse(ok, responseOrError) {
|
|
|
110
110
|
const stacktrace = await requestStacktraceMap.get(requestUUID);
|
|
111
111
|
const logMeta = {};
|
|
112
112
|
if (stacktrace) logMeta.stacktrace = stacktrace;
|
|
113
|
-
logger.
|
|
113
|
+
logger.log({
|
|
114
114
|
level: 'error',
|
|
115
115
|
args: [
|
|
116
116
|
parts.join(''),
|
|
@@ -120,7 +120,7 @@ async function logResponse(ok, responseOrError) {
|
|
|
120
120
|
});
|
|
121
121
|
return;
|
|
122
122
|
}
|
|
123
|
-
logger.
|
|
123
|
+
logger.log({
|
|
124
124
|
level: 'error',
|
|
125
125
|
args: [
|
|
126
126
|
'请求失败:无响应对象或配置信息'
|
|
@@ -234,6 +234,7 @@ function initAxiosConfig(axiosInstance) {
|
|
|
234
234
|
config._startTime = config._startTime || Date.now();
|
|
235
235
|
const csrfToken = window.csrfToken;
|
|
236
236
|
if (csrfToken) config.headers['X-Suda-Csrf-Token'] = csrfToken;
|
|
237
|
+
if ('undefined' != typeof window && window.location?.pathname) config.headers['X-Page-Route'] = window.location.pathname;
|
|
237
238
|
return config;
|
|
238
239
|
}, (error)=>Promise.reject(error));
|
|
239
240
|
instance.interceptors.response.use((response)=>response, (error)=>{
|
|
@@ -241,8 +242,8 @@ function initAxiosConfig(axiosInstance) {
|
|
|
241
242
|
if (error.response?.status === 403) {
|
|
242
243
|
const method = (error.config?.method || 'GET').toUpperCase();
|
|
243
244
|
const url = (error.config?.url || '').split('?')[0];
|
|
244
|
-
logger.
|
|
245
|
-
level: '
|
|
245
|
+
logger.log({
|
|
246
|
+
level: 'warn',
|
|
246
247
|
args: [
|
|
247
248
|
`请求被拒绝(403):${method} ${url}`,
|
|
248
249
|
{
|
package/lib/utils/getAppId.d.ts
CHANGED
package/lib/utils/getAppId.js
CHANGED
|
@@ -1,12 +1,5 @@
|
|
|
1
|
-
function getAppId(
|
|
2
|
-
if (window.MIAODA_APP_ID) return window.MIAODA_APP_ID;
|
|
3
|
-
let prefix;
|
|
4
|
-
prefix = path.includes('/ai/feida/runtime/') ? '/ai/feida/runtime/' : path.includes('/spark/r/') ? '/spark/r/' : '/ai/miaoda/';
|
|
1
|
+
function getAppId() {
|
|
5
2
|
const windowAppId = window.appId || null;
|
|
6
|
-
|
|
7
|
-
const remainder = path.substring(prefix.length);
|
|
8
|
-
const nextSlashIndex = remainder.indexOf('/');
|
|
9
|
-
if (-1 === nextSlashIndex) return remainder || windowAppId;
|
|
10
|
-
return remainder.substring(0, nextSlashIndex) || windowAppId;
|
|
3
|
+
return windowAppId;
|
|
11
4
|
}
|
|
12
5
|
export { getAppId };
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { getAppId } from "./getAppId.js";
|
|
2
2
|
import { getCsrfToken } from "./getCsrfToken.js";
|
|
3
|
+
import { isNewPathEnabled } from "./apiPath.js";
|
|
3
4
|
async function getAppPublished() {
|
|
4
5
|
try {
|
|
5
6
|
const headers = {
|
|
@@ -8,15 +9,16 @@ async function getAppPublished() {
|
|
|
8
9
|
'x-miaoda-token': window.MIAODA_BUILTIN_TTT,
|
|
9
10
|
'X-Suda-Csrf-Token': getCsrfToken()
|
|
10
11
|
};
|
|
11
|
-
const appId = getAppId(
|
|
12
|
-
const
|
|
12
|
+
const appId = getAppId();
|
|
13
|
+
const path = isNewPathEnabled() ? `/app/${appId}/__runtime__/api/v1/studio/get_published` : `/spark/b/${appId}/get_published`;
|
|
14
|
+
const url = `${window.location.origin}${path}`;
|
|
13
15
|
const response = await fetch(url, {
|
|
14
16
|
method: 'GET',
|
|
15
17
|
headers,
|
|
16
18
|
credentials: 'include'
|
|
17
19
|
});
|
|
18
20
|
const res = await response.json();
|
|
19
|
-
if (0 === res.code) return res.data;
|
|
21
|
+
if (0 === res.code || '0' === res.status_code) return res.data;
|
|
20
22
|
console.error('Error fetching published app info:', res);
|
|
21
23
|
} catch (error) {
|
|
22
24
|
console.error('Error fetching published app info:', error);
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { getAppId } from "./getAppId.js";
|
|
2
2
|
import { getCsrfToken } from "./getCsrfToken.js";
|
|
3
|
-
import {
|
|
4
|
-
import { isSparkRuntime } from "./utils.js";
|
|
3
|
+
import { isNewPathEnabled } from "./apiPath.js";
|
|
5
4
|
async function getUserProfile(request, headers = {}) {
|
|
6
|
-
const appId = getAppId(
|
|
5
|
+
const appId = getAppId();
|
|
7
6
|
if (!appId) return {
|
|
8
7
|
code: 1,
|
|
9
8
|
msg: 'appId is required',
|
|
@@ -15,17 +14,10 @@ async function getUserProfile(request, headers = {}) {
|
|
|
15
14
|
const mergedHeaders = {
|
|
16
15
|
...defaultHeaders,
|
|
17
16
|
...headers,
|
|
18
|
-
'X-Kunlun-Token': window.token,
|
|
19
|
-
'x-miaoda-token': window.MIAODA_BUILTIN_TTT,
|
|
20
|
-
'x-lgw-csrf-token': window.lgw_csrf_token,
|
|
21
17
|
...window.CSRF_HEADERS || {}
|
|
22
18
|
};
|
|
23
|
-
const
|
|
24
|
-
|
|
25
|
-
if (isSparkRuntime()) {
|
|
26
|
-
endpoint = `/spark/b/${appId}/user/profile`;
|
|
27
|
-
mergedHeaders['X-Suda-Csrf-Token'] = getCsrfToken();
|
|
28
|
-
} else endpoint = `/ai/api/${envPath}/v1/apps/${appId}/user/profile`;
|
|
19
|
+
const endpoint = isNewPathEnabled() ? `/app/${appId}/__runtime__/api/v1/studio/user/profile` : `/spark/b/${appId}/user/profile`;
|
|
20
|
+
mergedHeaders['X-Suda-Csrf-Token'] = getCsrfToken();
|
|
29
21
|
const response = await fetch(`${window.location.origin}${endpoint}`, {
|
|
30
22
|
method: 'POST',
|
|
31
23
|
headers: mergedHeaders,
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 统一 HMR API
|
|
3
|
+
*
|
|
4
|
+
* 提供统一的 HMR 成功/失败回调接口,屏蔽 Webpack 和 Vite 的差异。
|
|
5
|
+
*
|
|
6
|
+
* - Webpack/Rspack: 通过 import.meta.webpackHot 或 module.hot
|
|
7
|
+
* - Vite: 通过 error-overlay 注入的 window.__VITE_HMR__
|
|
8
|
+
*
|
|
9
|
+
* @see docs/RFC_HMR_API.md
|
|
10
|
+
*/
|
|
11
|
+
export interface HmrApi {
|
|
12
|
+
/**
|
|
13
|
+
* 注册 HMR 成功回调
|
|
14
|
+
* @param callback 成功回调函数
|
|
15
|
+
* @returns cleanup 函数,用于取消注册
|
|
16
|
+
*/
|
|
17
|
+
onSuccess(callback: () => void): () => void;
|
|
18
|
+
/**
|
|
19
|
+
* 注册 HMR 失败回调
|
|
20
|
+
* @param callback 失败回调函数,参数为错误信息
|
|
21
|
+
* @returns cleanup 函数,用于取消注册
|
|
22
|
+
*/
|
|
23
|
+
onError(callback: (error: unknown) => void): () => void;
|
|
24
|
+
}
|
|
25
|
+
declare global {
|
|
26
|
+
interface Window {
|
|
27
|
+
__VITE_HMR__?: HmrApi;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* 获取 HMR API 实例
|
|
32
|
+
*
|
|
33
|
+
* 自动检测当前构建工具(Webpack/Vite)并返回对应实现:
|
|
34
|
+
* - Webpack/Rspack: 使用内置适配器
|
|
35
|
+
* - Vite: 使用 error-overlay 注入的 window.__VITE_HMR__
|
|
36
|
+
*
|
|
37
|
+
* @returns HmrApi 实例,如果不在开发环境或不支持 HMR 则返回 null
|
|
38
|
+
*/
|
|
39
|
+
export declare function getHmrApi(): HmrApi | null;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
function createWebpackHmrApi(hot) {
|
|
2
|
+
return {
|
|
3
|
+
onSuccess (callback) {
|
|
4
|
+
let lastStatus = null;
|
|
5
|
+
const handler = (status)=>{
|
|
6
|
+
if ('idle' === status && 'apply' === lastStatus) try {
|
|
7
|
+
callback();
|
|
8
|
+
} catch (e) {
|
|
9
|
+
console.error('[HMR] Success callback error:', e);
|
|
10
|
+
}
|
|
11
|
+
lastStatus = status;
|
|
12
|
+
};
|
|
13
|
+
hot.addStatusHandler(handler);
|
|
14
|
+
return ()=>hot.removeStatusHandler(handler);
|
|
15
|
+
},
|
|
16
|
+
onError (callback) {
|
|
17
|
+
const handler = (status)=>{
|
|
18
|
+
if ('fail' === status || 'abort' === status) try {
|
|
19
|
+
callback(new Error(`HMR ${status}`));
|
|
20
|
+
} catch (e) {
|
|
21
|
+
console.error('[HMR] Error callback error:', e);
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
hot.addStatusHandler(handler);
|
|
25
|
+
return ()=>hot.removeStatusHandler(handler);
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
function getHmrApi() {
|
|
30
|
+
if ('production' === process.env.NODE_ENV) return null;
|
|
31
|
+
if (import.meta.webpackHot) return createWebpackHmrApi(import.meta.webpackHot);
|
|
32
|
+
'undefined' != typeof module && module.hot;
|
|
33
|
+
if (window.__VITE_HMR__) return window.__VITE_HMR__;
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
export { getHmrApi };
|
|
@@ -15,10 +15,15 @@ export interface ModuleHotInstance {
|
|
|
15
15
|
addStatusHandler: (handler: (status: ModuleHotType) => void) => void;
|
|
16
16
|
removeStatusHandler: (handler: (status: ModuleHotType) => void) => void;
|
|
17
17
|
}
|
|
18
|
+
/**
|
|
19
|
+
* 获取 Webpack HMR 实例
|
|
20
|
+
* 仅支持 Webpack/Rspack 的 HMR API
|
|
21
|
+
*/
|
|
18
22
|
export declare function getModuleHot(): ModuleHotInstance | null;
|
|
19
23
|
/**
|
|
20
24
|
* 创建模块热更成功处理函数
|
|
21
|
-
*
|
|
22
|
-
*
|
|
25
|
+
* 监听模块热更状态,检测 apply -> idle 转换表示热更成功
|
|
26
|
+
*
|
|
27
|
+
* @param callback 热更回调函数,参数为是否成功和当前状态
|
|
23
28
|
*/
|
|
24
29
|
export declare function createApplyHandle(callback: (success: boolean, status: ModuleHotType) => void): (status: ModuleHotType) => void;
|
package/lib/utils/module-hot.js
CHANGED
|
@@ -1,66 +1,21 @@
|
|
|
1
|
-
function createViteHmrAdapter(viteHot) {
|
|
2
|
-
const handlers = new Set();
|
|
3
|
-
const notifyHandlers = (status)=>{
|
|
4
|
-
handlers.forEach((handler)=>{
|
|
5
|
-
try {
|
|
6
|
-
handler(status);
|
|
7
|
-
} catch (e) {
|
|
8
|
-
console.error('[HMR] Status handler error:', e);
|
|
9
|
-
}
|
|
10
|
-
});
|
|
11
|
-
};
|
|
12
|
-
const beforeUpdateHandler = ()=>{
|
|
13
|
-
notifyHandlers('prepare');
|
|
14
|
-
setTimeout(()=>notifyHandlers('apply'), 0);
|
|
15
|
-
};
|
|
16
|
-
const afterUpdateHandler = ()=>{
|
|
17
|
-
notifyHandlers('idle');
|
|
18
|
-
};
|
|
19
|
-
const errorHandler = ()=>{
|
|
20
|
-
notifyHandlers('fail');
|
|
21
|
-
};
|
|
22
|
-
const beforeFullReloadHandler = ()=>{
|
|
23
|
-
notifyHandlers('check');
|
|
24
|
-
};
|
|
25
|
-
viteHot.on('vite:beforeUpdate', beforeUpdateHandler);
|
|
26
|
-
viteHot.on('vite:afterUpdate', afterUpdateHandler);
|
|
27
|
-
viteHot.on('vite:error', errorHandler);
|
|
28
|
-
viteHot.on('vite:beforeFullReload', beforeFullReloadHandler);
|
|
29
|
-
return {
|
|
30
|
-
addStatusHandler (handler) {
|
|
31
|
-
handlers.add(handler);
|
|
32
|
-
},
|
|
33
|
-
removeStatusHandler (handler) {
|
|
34
|
-
handlers.delete(handler);
|
|
35
|
-
}
|
|
36
|
-
};
|
|
37
|
-
}
|
|
38
|
-
let viteAdapterInstance = null;
|
|
39
1
|
function getModuleHot() {
|
|
40
2
|
if ('production' === process.env.NODE_ENV) return null;
|
|
41
|
-
if (import.meta.hot) {
|
|
42
|
-
if (!viteAdapterInstance) viteAdapterInstance = createViteHmrAdapter(import.meta.hot);
|
|
43
|
-
return viteAdapterInstance;
|
|
44
|
-
}
|
|
45
3
|
if (import.meta.webpackHot) return import.meta.webpackHot;
|
|
46
4
|
'undefined' != typeof module && module.hot;
|
|
47
5
|
return null;
|
|
48
6
|
}
|
|
49
7
|
function createApplyHandle(callback) {
|
|
50
|
-
let
|
|
8
|
+
let lastStatus = null;
|
|
51
9
|
return (status)=>{
|
|
52
10
|
if ('fail' === status || 'abort' === status) {
|
|
53
|
-
|
|
11
|
+
lastStatus = status;
|
|
54
12
|
return callback(false, status);
|
|
55
13
|
}
|
|
56
|
-
if (
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
callback(true, status);
|
|
60
|
-
}
|
|
61
|
-
return;
|
|
14
|
+
if ('idle' === status && 'apply' === lastStatus) {
|
|
15
|
+
lastStatus = status;
|
|
16
|
+
return callback(true, status);
|
|
62
17
|
}
|
|
63
|
-
|
|
18
|
+
lastStatus = status;
|
|
64
19
|
};
|
|
65
20
|
}
|
|
66
21
|
export { createApplyHandle, getModuleHot };
|
|
@@ -4,9 +4,7 @@ async function fetchUserProfilesByIds(ids) {
|
|
|
4
4
|
try {
|
|
5
5
|
const dataloom = await getDataloom();
|
|
6
6
|
if (!dataloom) throw new Error('Dataloom client is unavailable');
|
|
7
|
-
const
|
|
8
|
-
if (0 === numericIds.length) return [];
|
|
9
|
-
const response = await dataloom.service.user.getByIds(numericIds);
|
|
7
|
+
const response = await dataloom.service.user.getByIds(ids);
|
|
10
8
|
return Array.isArray(response?.data) ? response.data : response?.data?.user_list || [];
|
|
11
9
|
} catch (error) {
|
|
12
10
|
console.error(`Failed to fetch profiles for user IDs ${ids.join(', ')}:`, error);
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { getAppId } from "./getAppId.js";
|
|
2
|
+
function getPrefix() {
|
|
3
|
+
const appId = getAppId();
|
|
4
|
+
const namespace = appId || '__global__';
|
|
5
|
+
return `__miaoda_${namespace}__:`;
|
|
6
|
+
}
|
|
7
|
+
function getScopedKeys() {
|
|
8
|
+
const prefix = getPrefix();
|
|
9
|
+
const keys = [];
|
|
10
|
+
for(let i = 0; i < localStorage.length; i++){
|
|
11
|
+
const key = localStorage.key(i);
|
|
12
|
+
if (key && key.startsWith(prefix)) keys.push(key.substring(prefix.length));
|
|
13
|
+
}
|
|
14
|
+
return keys;
|
|
15
|
+
}
|
|
16
|
+
const scopedStorage = {
|
|
17
|
+
getItem (key) {
|
|
18
|
+
const prefixedKey = getPrefix() + key;
|
|
19
|
+
return localStorage.getItem(prefixedKey);
|
|
20
|
+
},
|
|
21
|
+
setItem (key, value) {
|
|
22
|
+
const prefixedKey = getPrefix() + key;
|
|
23
|
+
localStorage.setItem(prefixedKey, value);
|
|
24
|
+
},
|
|
25
|
+
removeItem (key) {
|
|
26
|
+
const prefixedKey = getPrefix() + key;
|
|
27
|
+
localStorage.removeItem(prefixedKey);
|
|
28
|
+
},
|
|
29
|
+
clear () {
|
|
30
|
+
const prefix = getPrefix();
|
|
31
|
+
const keysToRemove = [];
|
|
32
|
+
for(let i = 0; i < localStorage.length; i++){
|
|
33
|
+
const key = localStorage.key(i);
|
|
34
|
+
if (key && key.startsWith(prefix)) keysToRemove.push(key);
|
|
35
|
+
}
|
|
36
|
+
keysToRemove.forEach((key)=>localStorage.removeItem(key));
|
|
37
|
+
},
|
|
38
|
+
key (index) {
|
|
39
|
+
const keys = getScopedKeys();
|
|
40
|
+
return keys[index] || null;
|
|
41
|
+
},
|
|
42
|
+
get length () {
|
|
43
|
+
return getScopedKeys().length;
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
export { scopedStorage };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lark-apaas/client-toolkit",
|
|
3
|
-
"version": "1.2.10-alpha.
|
|
3
|
+
"version": "1.2.10-alpha.40",
|
|
4
4
|
"types": "./lib/index.d.ts",
|
|
5
5
|
"main": "./lib/index.js",
|
|
6
6
|
"files": [
|
|
@@ -93,10 +93,10 @@
|
|
|
93
93
|
"dependencies": {
|
|
94
94
|
"@ant-design/colors": "^7.2.1",
|
|
95
95
|
"@ant-design/cssinjs": "^1.24.0",
|
|
96
|
-
"@data-loom/js": "0.4.
|
|
97
|
-
"@lark-apaas/auth-sdk": "
|
|
98
|
-
"@lark-apaas/client-capability": "
|
|
99
|
-
"@lark-apaas/miaoda-inspector": "^1.0.
|
|
96
|
+
"@data-loom/js": "0.4.9-alpha.2",
|
|
97
|
+
"@lark-apaas/auth-sdk": "0.1.0-alpha.55",
|
|
98
|
+
"@lark-apaas/client-capability": "0.1.3-alpha.14",
|
|
99
|
+
"@lark-apaas/miaoda-inspector": "^1.0.15",
|
|
100
100
|
"@lark-apaas/observable-web": "^1.0.1",
|
|
101
101
|
"@radix-ui/react-avatar": "^1.1.10",
|
|
102
102
|
"@radix-ui/react-popover": "^1.1.15",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from '../../integrations/generateImage';
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from "../../integrations/generateImage.js";
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from '../../integrations/generateTextStream';
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from "../../integrations/generateTextStream.js";
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare function generateImage(prompt: string, size?: string, headers?: Record<string, string>): Promise<any>;
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import { getAppId } from "../utils/getAppId.js";
|
|
2
|
-
import { getCsrfToken } from "../utils/getCsrfToken.js";
|
|
3
|
-
import { getEnvPath } from "../utils/getEnvPath.js";
|
|
4
|
-
import { isSparkRuntime } from "../utils/utils.js";
|
|
5
|
-
async function generateImage(prompt, size = '1024x1024', headers = {}) {
|
|
6
|
-
const appId = getAppId(window.location.pathname);
|
|
7
|
-
if (!appId) return {
|
|
8
|
-
code: 1,
|
|
9
|
-
msg: 'appId is required',
|
|
10
|
-
data: {}
|
|
11
|
-
};
|
|
12
|
-
const defaultHeaders = {
|
|
13
|
-
'Content-Type': 'application/json'
|
|
14
|
-
};
|
|
15
|
-
const mergedHeaders = {
|
|
16
|
-
...defaultHeaders,
|
|
17
|
-
...headers,
|
|
18
|
-
'X-Kunlun-Token': window.token,
|
|
19
|
-
'x-miaoda-token': window.MIAODA_BUILTIN_TTT,
|
|
20
|
-
'x-lgw-csrf-token': window.lgw_csrf_token,
|
|
21
|
-
...window.CSRF_HEADERS || {}
|
|
22
|
-
};
|
|
23
|
-
if (isSparkRuntime()) {
|
|
24
|
-
mergedHeaders['X-Suda-Csrf-Token'] = getCsrfToken();
|
|
25
|
-
const response = await fetch(`${window.location.origin}/spark/b/${appId}/text2image`, {
|
|
26
|
-
method: 'POST',
|
|
27
|
-
headers: mergedHeaders,
|
|
28
|
-
credentials: 'include',
|
|
29
|
-
body: JSON.stringify({
|
|
30
|
-
prompt,
|
|
31
|
-
size
|
|
32
|
-
})
|
|
33
|
-
});
|
|
34
|
-
return await response.json();
|
|
35
|
-
}
|
|
36
|
-
const response = await fetch(`${window.location.origin}/ai/api/${getEnvPath()}/v1/apps/${appId}/text2image`, {
|
|
37
|
-
method: 'POST',
|
|
38
|
-
headers: mergedHeaders,
|
|
39
|
-
credentials: 'include',
|
|
40
|
-
body: JSON.stringify({
|
|
41
|
-
prompt,
|
|
42
|
-
size
|
|
43
|
-
})
|
|
44
|
-
});
|
|
45
|
-
return await response.json();
|
|
46
|
-
}
|
|
47
|
-
export { generateImage };
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
interface GenerateTextOptions {
|
|
2
|
-
text: string;
|
|
3
|
-
thinking_type?: 'enabled' | 'disabled';
|
|
4
|
-
headers?: Record<string, string>;
|
|
5
|
-
}
|
|
6
|
-
interface GenerateTextResult {
|
|
7
|
-
content: string;
|
|
8
|
-
reasoning_content: string;
|
|
9
|
-
success: boolean;
|
|
10
|
-
error?: string;
|
|
11
|
-
}
|
|
12
|
-
/**
|
|
13
|
-
* 文生文 - 流式版本
|
|
14
|
-
* 支持实时接收生成内容的回调
|
|
15
|
-
*/
|
|
16
|
-
export declare function generateTextStream(options: GenerateTextOptions, onChunk?: (chunk: {
|
|
17
|
-
content: string;
|
|
18
|
-
reasoning_content: string;
|
|
19
|
-
finished: boolean;
|
|
20
|
-
}) => void): Promise<GenerateTextResult>;
|
|
21
|
-
export {};
|
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
import { getAppId } from "../utils/getAppId.js";
|
|
2
|
-
import { getCsrfToken } from "../utils/getCsrfToken.js";
|
|
3
|
-
import { getEnvPath } from "../utils/getEnvPath.js";
|
|
4
|
-
import { isSparkRuntime } from "../utils/utils.js";
|
|
5
|
-
async function generateTextStream(options, onChunk) {
|
|
6
|
-
const { text, thinking_type = 'disabled', headers = {} } = options;
|
|
7
|
-
const appId = getAppId(window.location.pathname);
|
|
8
|
-
if (!appId) return {
|
|
9
|
-
content: '',
|
|
10
|
-
reasoning_content: '',
|
|
11
|
-
success: false,
|
|
12
|
-
error: 'appId is required'
|
|
13
|
-
};
|
|
14
|
-
try {
|
|
15
|
-
const mergedHeaders = {
|
|
16
|
-
'Content-Type': 'application/json',
|
|
17
|
-
...headers,
|
|
18
|
-
'X-Kunlun-Token': window.token,
|
|
19
|
-
'x-miaoda-token': window.MIAODA_BUILTIN_TTT,
|
|
20
|
-
'x-lgw-csrf-token': window.lgw_csrf_token,
|
|
21
|
-
...window.CSRF_HEADERS || {}
|
|
22
|
-
};
|
|
23
|
-
let response;
|
|
24
|
-
if (isSparkRuntime()) {
|
|
25
|
-
mergedHeaders['X-Suda-Csrf-Token'] = getCsrfToken();
|
|
26
|
-
response = await fetch(`${window.location.origin}/spark/b/${appId}/text/generate`, {
|
|
27
|
-
method: 'POST',
|
|
28
|
-
headers: mergedHeaders,
|
|
29
|
-
credentials: 'include',
|
|
30
|
-
body: JSON.stringify({
|
|
31
|
-
text,
|
|
32
|
-
thinking_type
|
|
33
|
-
})
|
|
34
|
-
});
|
|
35
|
-
} else response = await fetch(`${window.location.origin}/ai/api/${getEnvPath()}/v1/apps/${appId}/text/generate`, {
|
|
36
|
-
method: 'POST',
|
|
37
|
-
headers: mergedHeaders,
|
|
38
|
-
credentials: 'include',
|
|
39
|
-
body: JSON.stringify({
|
|
40
|
-
text,
|
|
41
|
-
thinking_type
|
|
42
|
-
})
|
|
43
|
-
});
|
|
44
|
-
if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);
|
|
45
|
-
const reader = response.body?.getReader();
|
|
46
|
-
if (!reader) throw new Error('无法获取响应流');
|
|
47
|
-
let fullContent = '';
|
|
48
|
-
let fullReasoningContent = '';
|
|
49
|
-
const decoder = new TextDecoder();
|
|
50
|
-
while(true){
|
|
51
|
-
const { done, value } = await reader.read();
|
|
52
|
-
if (done) break;
|
|
53
|
-
const chunk = decoder.decode(value, {
|
|
54
|
-
stream: true
|
|
55
|
-
});
|
|
56
|
-
const lines = chunk.split('\n').filter((line)=>line.trim());
|
|
57
|
-
for (const line of lines)if (line.startsWith('data: ')) {
|
|
58
|
-
const jsonStr = line.slice(6);
|
|
59
|
-
try {
|
|
60
|
-
const data = JSON.parse(jsonStr);
|
|
61
|
-
if (0 !== data.code) return {
|
|
62
|
-
content: '',
|
|
63
|
-
reasoning_content: '',
|
|
64
|
-
success: false,
|
|
65
|
-
error: data.msg || '生成失败'
|
|
66
|
-
};
|
|
67
|
-
if (data.data.content) fullContent += data.data.content;
|
|
68
|
-
if (data.data.reasoning_content) fullReasoningContent += data.data.reasoning_content;
|
|
69
|
-
if (onChunk) onChunk({
|
|
70
|
-
content: data.data.content || '',
|
|
71
|
-
reasoning_content: data.data.reasoning_content || '',
|
|
72
|
-
finished: data.finished
|
|
73
|
-
});
|
|
74
|
-
if (data.finished) return {
|
|
75
|
-
content: fullContent,
|
|
76
|
-
reasoning_content: fullReasoningContent,
|
|
77
|
-
success: true
|
|
78
|
-
};
|
|
79
|
-
} catch (parseError) {
|
|
80
|
-
console.error(`解析JSON失败: ${jsonStr}`);
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
return {
|
|
85
|
-
content: fullContent,
|
|
86
|
-
reasoning_content: fullReasoningContent,
|
|
87
|
-
success: true
|
|
88
|
-
};
|
|
89
|
-
} catch (error) {
|
|
90
|
-
return {
|
|
91
|
-
content: '',
|
|
92
|
-
reasoning_content: '',
|
|
93
|
-
success: false,
|
|
94
|
-
error: error instanceof Error ? error.message : '未知错误'
|
|
95
|
-
};
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
export { generateTextStream };
|