@lark-apaas/client-toolkit 1.1.11 → 1.1.13-userprofile-test.0
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/useTheme.d.ts +1 -0
- package/lib/apis/hooks/useTheme.js +1 -0
- package/lib/components/User/UserDisplay.d.ts +6 -1
- package/lib/components/User/UserDisplay.js +80 -29
- package/lib/hooks/useTheme.d.ts +4 -0
- package/lib/hooks/useTheme.js +9 -0
- package/lib/logger/intercept-global-error.js +3 -2
- package/lib/logger/log-types.d.ts +13 -4
- package/lib/logger/log-types.js +5 -2
- package/lib/logger/selected-logs.js +51 -5
- package/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from '../../hooks/useTheme';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "../../hooks/useTheme.js";
|
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import type { IUserProfile } from '../../apis/udt-types';
|
|
3
3
|
export interface UserDisplayProps {
|
|
4
|
-
|
|
4
|
+
/**
|
|
5
|
+
* 支持传入完整的用户资料(IUserProfile)/ 列表(IUserProfile[])
|
|
6
|
+
* 或仅传入用户 ID(string)/ 列表(string[])。
|
|
7
|
+
* 当传入 user_id 或 user_id[] 时组件会自动拉取用户资料并渲染。
|
|
8
|
+
*/
|
|
9
|
+
users: IUserProfile | IUserProfile[] | string | string[];
|
|
5
10
|
size?: 'small' | 'medium' | 'large';
|
|
6
11
|
className?: string;
|
|
7
12
|
style?: React.CSSProperties;
|
|
@@ -6,38 +6,82 @@ import { UserProfile } from "./UserProfile/index.js";
|
|
|
6
6
|
import { UserWithAvatar } from "./UserWithAvatar.js";
|
|
7
7
|
import { Popover, PopoverContent, PopoverTrigger } from "../ui/popover.js";
|
|
8
8
|
const UserDisplay = ({ users, size, className, style, showLabel = true })=>{
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
const normalizedIds = useMemo(()=>{
|
|
10
|
+
if (!users) return [];
|
|
11
|
+
if (Array.isArray(users)) {
|
|
12
|
+
if (0 === users.length) return [];
|
|
13
|
+
const first = users[0];
|
|
14
|
+
const isStringArray = 'string' == typeof first;
|
|
15
|
+
return isStringArray ? users.filter(Boolean).map((id)=>String(id)) : users.map((u)=>String(u.user_id)).filter(Boolean);
|
|
16
|
+
}
|
|
17
|
+
return 'string' == typeof users ? [
|
|
18
|
+
String(users)
|
|
19
|
+
] : [
|
|
20
|
+
String(users.user_id)
|
|
21
|
+
].filter(Boolean);
|
|
22
|
+
}, [
|
|
23
|
+
users
|
|
24
|
+
]);
|
|
25
|
+
const inputProfilesMap = useMemo(()=>{
|
|
26
|
+
const map = new Map();
|
|
27
|
+
if (!users) return map;
|
|
28
|
+
if (Array.isArray(users)) {
|
|
29
|
+
const first = users[0];
|
|
30
|
+
const isStringArray = 'string' == typeof first;
|
|
31
|
+
if (!isStringArray) {
|
|
32
|
+
for (const u of users)if (u?.user_id) map.set(String(u.user_id), {
|
|
33
|
+
user_id: String(u.user_id),
|
|
34
|
+
name: u?.name ?? '',
|
|
35
|
+
avatar: u?.avatar ?? '',
|
|
36
|
+
email: u?.email ?? '',
|
|
37
|
+
status: u?.status ?? 1
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
} else if ('string' != typeof users) {
|
|
41
|
+
const u = users;
|
|
42
|
+
if (u?.user_id) map.set(String(u.user_id), {
|
|
43
|
+
user_id: String(u.user_id),
|
|
44
|
+
name: u?.name ?? '',
|
|
45
|
+
avatar: u?.avatar ?? '',
|
|
46
|
+
email: u?.email ?? '',
|
|
47
|
+
status: u?.status ?? 1
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
return map;
|
|
51
|
+
}, [
|
|
12
52
|
users
|
|
13
53
|
]);
|
|
14
|
-
const [resolvedUsers, setResolvedUsers] = useState(
|
|
54
|
+
const [resolvedUsers, setResolvedUsers] = useState(()=>normalizedIds.map((id)=>inputProfilesMap.get(id) ?? {
|
|
55
|
+
user_id: id,
|
|
56
|
+
name: '',
|
|
57
|
+
avatar: '',
|
|
58
|
+
email: '',
|
|
59
|
+
status: 1
|
|
60
|
+
}));
|
|
15
61
|
const [loadingProfiles, setLoadingProfiles] = useState(false);
|
|
16
62
|
useEffect(()=>{
|
|
17
63
|
let isCancelled = false;
|
|
18
|
-
if (!
|
|
64
|
+
if (!normalizedIds.length) {
|
|
19
65
|
setResolvedUsers([]);
|
|
20
66
|
setLoadingProfiles(false);
|
|
21
67
|
return ()=>{
|
|
22
68
|
isCancelled = true;
|
|
23
69
|
};
|
|
24
70
|
}
|
|
25
|
-
const usersNeedingDetails = normalizedUsers.filter((user)=>!user?.name?.trim());
|
|
26
|
-
if (!usersNeedingDetails.length) {
|
|
27
|
-
setResolvedUsers(normalizedUsers);
|
|
28
|
-
setLoadingProfiles(false);
|
|
29
|
-
return ()=>{
|
|
30
|
-
isCancelled = true;
|
|
31
|
-
};
|
|
32
|
-
}
|
|
33
71
|
const fetchProfiles = async ()=>{
|
|
34
72
|
try {
|
|
35
73
|
setLoadingProfiles(true);
|
|
36
74
|
const dataloom = await getDataloom();
|
|
37
75
|
if (!dataloom) throw new Error('dataloom client is unavailable');
|
|
38
|
-
const ids =
|
|
76
|
+
const ids = normalizedIds.map((id)=>Number(id)).filter((id)=>Number.isFinite(id));
|
|
39
77
|
if (!ids.length) {
|
|
40
|
-
setResolvedUsers(
|
|
78
|
+
setResolvedUsers(normalizedIds.map((id)=>inputProfilesMap.get(id) ?? {
|
|
79
|
+
user_id: id,
|
|
80
|
+
name: '',
|
|
81
|
+
avatar: '',
|
|
82
|
+
email: '',
|
|
83
|
+
status: 1
|
|
84
|
+
}));
|
|
41
85
|
setLoadingProfiles(false);
|
|
42
86
|
return;
|
|
43
87
|
}
|
|
@@ -51,28 +95,35 @@ const UserDisplay = ({ users, size, className, style, showLabel = true })=>{
|
|
|
51
95
|
user_id: id,
|
|
52
96
|
name: profile?.name ?? '',
|
|
53
97
|
avatar: profile?.avatar ?? '',
|
|
54
|
-
email: profile?.email,
|
|
55
|
-
status: profile?.status
|
|
56
|
-
...profile
|
|
98
|
+
email: profile?.email ?? '',
|
|
99
|
+
status: profile?.status ?? 1
|
|
57
100
|
});
|
|
58
101
|
});
|
|
59
|
-
const mergedUsers =
|
|
60
|
-
const id = String(user.user_id);
|
|
102
|
+
const mergedUsers = normalizedIds.map((id)=>{
|
|
61
103
|
const fetched = fetchedMap.get(id);
|
|
62
|
-
|
|
104
|
+
const given = inputProfilesMap.get(id);
|
|
105
|
+
const name = given?.name?.trim() ? given.name : fetched?.name ?? '';
|
|
106
|
+
const avatar = given?.avatar || fetched?.avatar || '';
|
|
107
|
+
const email = given?.email || fetched?.email || '';
|
|
108
|
+
const status = given?.status ?? fetched?.status ?? 1;
|
|
63
109
|
return {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
status: user.status ?? fetched.status
|
|
110
|
+
user_id: id,
|
|
111
|
+
name,
|
|
112
|
+
avatar,
|
|
113
|
+
email,
|
|
114
|
+
status
|
|
70
115
|
};
|
|
71
116
|
});
|
|
72
117
|
if (!isCancelled) setResolvedUsers(mergedUsers);
|
|
73
118
|
} catch (error) {
|
|
74
119
|
console.error('Failed to resolve user profiles:', error);
|
|
75
|
-
if (!isCancelled) setResolvedUsers(
|
|
120
|
+
if (!isCancelled) setResolvedUsers(normalizedIds.map((id)=>inputProfilesMap.get(id) ?? {
|
|
121
|
+
user_id: id,
|
|
122
|
+
name: '',
|
|
123
|
+
avatar: '',
|
|
124
|
+
email: '',
|
|
125
|
+
status: 1
|
|
126
|
+
}));
|
|
76
127
|
} finally{
|
|
77
128
|
if (!isCancelled) setLoadingProfiles(false);
|
|
78
129
|
}
|
|
@@ -82,7 +133,7 @@ const UserDisplay = ({ users, size, className, style, showLabel = true })=>{
|
|
|
82
133
|
isCancelled = true;
|
|
83
134
|
};
|
|
84
135
|
}, [
|
|
85
|
-
|
|
136
|
+
normalizedIds
|
|
86
137
|
]);
|
|
87
138
|
if (!resolvedUsers.length || loadingProfiles) return null;
|
|
88
139
|
return /*#__PURE__*/ jsx("div", {
|
|
@@ -17,10 +17,11 @@ function interceptErrors() {
|
|
|
17
17
|
const originalMethod = window.console[method];
|
|
18
18
|
window.console[method] = (...args)=>{
|
|
19
19
|
originalMethod(...args);
|
|
20
|
+
const level = 'log' === method ? 'info' : method;
|
|
20
21
|
const log = args[0];
|
|
21
|
-
if ('string' == typeof log && log.startsWith('[Dataloom]') && levelSchema.safeParse(
|
|
22
|
+
if ('string' == typeof log && log.startsWith('[Dataloom]') && levelSchema.safeParse(level).success) {
|
|
22
23
|
logger.log({
|
|
23
|
-
level:
|
|
24
|
+
level: level,
|
|
24
25
|
args
|
|
25
26
|
});
|
|
26
27
|
postMessage({
|
|
@@ -28,10 +28,10 @@ export declare const logStackFrameSchema: z.ZodObject<{
|
|
|
28
28
|
}, z.core.$strip>;
|
|
29
29
|
export declare const levelSchema: z.ZodEnum<{
|
|
30
30
|
success: "success";
|
|
31
|
+
debug: "debug";
|
|
31
32
|
info: "info";
|
|
32
33
|
warn: "warn";
|
|
33
34
|
error: "error";
|
|
34
|
-
debug: "debug";
|
|
35
35
|
}>;
|
|
36
36
|
export declare const logMeta: z.ZodObject<{
|
|
37
37
|
stacktrace: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
@@ -45,15 +45,18 @@ export declare const logMeta: z.ZodObject<{
|
|
|
45
45
|
noStacktrace: z.ZodOptional<z.ZodBoolean>;
|
|
46
46
|
repairMessage: z.ZodOptional<z.ZodString>;
|
|
47
47
|
type: z.ZodOptional<z.ZodString>;
|
|
48
|
+
isDuplicate: z.ZodOptional<z.ZodBoolean>;
|
|
49
|
+
duplicateCount: z.ZodOptional<z.ZodNumber>;
|
|
50
|
+
duplicateOfId: z.ZodOptional<z.ZodString>;
|
|
48
51
|
}, z.core.$strip>;
|
|
49
52
|
export declare const selectedLogSchema: z.ZodObject<{
|
|
50
53
|
type: z.ZodLiteral<"typedLogV2">;
|
|
51
54
|
level: z.ZodEnum<{
|
|
52
55
|
success: "success";
|
|
56
|
+
debug: "debug";
|
|
53
57
|
info: "info";
|
|
54
58
|
warn: "warn";
|
|
55
59
|
error: "error";
|
|
56
|
-
debug: "debug";
|
|
57
60
|
}>;
|
|
58
61
|
id: z.ZodString;
|
|
59
62
|
args: z.ZodArray<z.ZodUnknown>;
|
|
@@ -69,16 +72,19 @@ export declare const selectedLogSchema: z.ZodObject<{
|
|
|
69
72
|
noStacktrace: z.ZodOptional<z.ZodBoolean>;
|
|
70
73
|
repairMessage: z.ZodOptional<z.ZodString>;
|
|
71
74
|
type: z.ZodOptional<z.ZodString>;
|
|
75
|
+
isDuplicate: z.ZodOptional<z.ZodBoolean>;
|
|
76
|
+
duplicateCount: z.ZodOptional<z.ZodNumber>;
|
|
77
|
+
duplicateOfId: z.ZodOptional<z.ZodString>;
|
|
72
78
|
}, z.core.$strip>;
|
|
73
79
|
}, z.core.$strip>;
|
|
74
|
-
export type LogLevel =
|
|
80
|
+
export type LogLevel = z.infer<typeof levelSchema>;
|
|
75
81
|
export declare const logWithMetaSchema: z.ZodObject<{
|
|
76
82
|
level: z.ZodEnum<{
|
|
77
83
|
success: "success";
|
|
84
|
+
debug: "debug";
|
|
78
85
|
info: "info";
|
|
79
86
|
warn: "warn";
|
|
80
87
|
error: "error";
|
|
81
|
-
debug: "debug";
|
|
82
88
|
}>;
|
|
83
89
|
args: z.ZodArray<z.ZodUnknown>;
|
|
84
90
|
meta: z.ZodOptional<z.ZodObject<{
|
|
@@ -93,6 +99,9 @@ export declare const logWithMetaSchema: z.ZodObject<{
|
|
|
93
99
|
noStacktrace: z.ZodOptional<z.ZodBoolean>;
|
|
94
100
|
repairMessage: z.ZodOptional<z.ZodString>;
|
|
95
101
|
type: z.ZodOptional<z.ZodString>;
|
|
102
|
+
isDuplicate: z.ZodOptional<z.ZodBoolean>;
|
|
103
|
+
duplicateCount: z.ZodOptional<z.ZodNumber>;
|
|
104
|
+
duplicateOfId: z.ZodOptional<z.ZodString>;
|
|
96
105
|
}, z.core.$strip>>;
|
|
97
106
|
}, z.core.$strip>;
|
|
98
107
|
export type LogStackFrame = z.infer<typeof logStackFrameSchema>;
|
package/lib/logger/log-types.js
CHANGED
|
@@ -27,10 +27,10 @@ const logStackFrameSchema = zod.object({
|
|
|
27
27
|
columnNumber: zod.number()
|
|
28
28
|
});
|
|
29
29
|
const levelSchema = zod["enum"]([
|
|
30
|
+
'debug',
|
|
30
31
|
'info',
|
|
31
32
|
'warn',
|
|
32
33
|
'error',
|
|
33
|
-
'debug',
|
|
34
34
|
'success'
|
|
35
35
|
]);
|
|
36
36
|
const logMeta = zod.object({
|
|
@@ -39,7 +39,10 @@ const logMeta = zod.object({
|
|
|
39
39
|
skipFrame: zod.optional(zod.number()),
|
|
40
40
|
noStacktrace: zod.optional(zod.boolean()),
|
|
41
41
|
repairMessage: zod.optional(zod.string()),
|
|
42
|
-
type: zod.optional(zod.string())
|
|
42
|
+
type: zod.optional(zod.string()),
|
|
43
|
+
isDuplicate: zod.optional(zod.boolean()),
|
|
44
|
+
duplicateCount: zod.optional(zod.number()),
|
|
45
|
+
duplicateOfId: zod.optional(zod.string())
|
|
43
46
|
});
|
|
44
47
|
const selectedLogSchema = zod.object({
|
|
45
48
|
type: zod.literal('typedLogV2'),
|
|
@@ -40,7 +40,17 @@ async function sendSelectedLog(logWithoutID) {
|
|
|
40
40
|
if (!log.meta.stacktrace) try {
|
|
41
41
|
const stacktrace = await stacktrace_js.fromError(error);
|
|
42
42
|
log.meta.stacktrace = mapStacktrace(stacktrace);
|
|
43
|
-
} catch (e) {
|
|
43
|
+
} catch (e) {
|
|
44
|
+
if (window.parent !== window) try {
|
|
45
|
+
window.parent.postMessage({
|
|
46
|
+
type: 'STACKTRACE_PARSE_ERROR',
|
|
47
|
+
payload: {
|
|
48
|
+
error: e instanceof Error ? e.message : String(e),
|
|
49
|
+
context: 'StackTrace.fromError'
|
|
50
|
+
}
|
|
51
|
+
}, '*');
|
|
52
|
+
} catch (postError) {}
|
|
53
|
+
}
|
|
44
54
|
newParts.push(newError.message, newError);
|
|
45
55
|
} else newParts.push(log.args[i]);
|
|
46
56
|
log.args = newParts;
|
|
@@ -49,11 +59,46 @@ async function sendSelectedLog(logWithoutID) {
|
|
|
49
59
|
const firstFrameIndex = frames.findIndex((frame)=>!frame.fileName.includes('node_modules/@lark-apaas/client-toolkit/lib/logger'));
|
|
50
60
|
frames = -1 === firstFrameIndex ? [] : frames.slice(firstFrameIndex);
|
|
51
61
|
log.meta.stacktrace = frames;
|
|
52
|
-
} catch (e) {
|
|
62
|
+
} catch (e) {
|
|
63
|
+
if (window.parent !== window) try {
|
|
64
|
+
window.parent.postMessage({
|
|
65
|
+
type: 'STACKTRACE_PARSE_ERROR',
|
|
66
|
+
payload: {
|
|
67
|
+
error: e instanceof Error ? e.message : String(e),
|
|
68
|
+
context: 'getStacktrace'
|
|
69
|
+
}
|
|
70
|
+
}, '*');
|
|
71
|
+
} catch (postError) {}
|
|
72
|
+
}
|
|
53
73
|
if (void 0 === log.meta.skipFrame) log.meta.skipFrame = 2;
|
|
54
74
|
const logJSON = JSON.stringify(log);
|
|
55
|
-
|
|
56
|
-
|
|
75
|
+
const logForDedup = {
|
|
76
|
+
...log
|
|
77
|
+
};
|
|
78
|
+
delete logForDedup.id;
|
|
79
|
+
const logContentForDedup = JSON.stringify(logForDedup);
|
|
80
|
+
if (lastLogInfo && lastLogInfo.content === logContentForDedup) {
|
|
81
|
+
lastLogInfo.count++;
|
|
82
|
+
log.meta.isDuplicate = true;
|
|
83
|
+
log.meta.duplicateCount = lastLogInfo.count;
|
|
84
|
+
log.meta.duplicateOfId = lastLogInfo.id;
|
|
85
|
+
const updatedLogJSON = JSON.stringify(log);
|
|
86
|
+
try {
|
|
87
|
+
batchLogInfo('info', updatedLogJSON);
|
|
88
|
+
} catch (e) {}
|
|
89
|
+
if (window.parent !== window) try {
|
|
90
|
+
window.parent.postMessage({
|
|
91
|
+
type: 'SELECTED_LOG',
|
|
92
|
+
payload: updatedLogJSON
|
|
93
|
+
}, '*');
|
|
94
|
+
} catch (e) {}
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
lastLogInfo = {
|
|
98
|
+
content: logContentForDedup,
|
|
99
|
+
id: log.id,
|
|
100
|
+
count: 1
|
|
101
|
+
};
|
|
57
102
|
try {
|
|
58
103
|
batchLogInfo('info', logJSON);
|
|
59
104
|
} catch (e) {}
|
|
@@ -70,6 +115,7 @@ async function getStacktrace() {
|
|
|
70
115
|
const frames = mapStacktrace(stacktrace);
|
|
71
116
|
return frames;
|
|
72
117
|
}
|
|
118
|
+
let lastLogInfo = null;
|
|
73
119
|
async function sendTypedLogV2(logWithMeta) {
|
|
74
120
|
sendSelectedLog({
|
|
75
121
|
type: 'typedLogV2',
|
|
@@ -84,7 +130,7 @@ const typedLogInterceptor = (logger)=>({
|
|
|
84
130
|
logger.debug(message, ...args);
|
|
85
131
|
} catch (e) {}
|
|
86
132
|
sendTypedLogV2({
|
|
87
|
-
level: '
|
|
133
|
+
level: 'info',
|
|
88
134
|
args: [
|
|
89
135
|
message,
|
|
90
136
|
...args
|