@lobehub/lobehub 2.0.0-next.296 → 2.0.0-next.297
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/CHANGELOG.md +25 -0
- package/changelog/v1.json +9 -0
- package/package.json +2 -2
- package/packages/types/package.json +1 -1
- package/packages/types/src/discover/assistants.ts +4 -0
- package/packages/types/src/discover/groupAgents.ts +196 -0
- package/packages/types/src/discover/index.ts +5 -1
- package/src/app/[variants]/(main)/community/(detail)/group_agent/features/DetailProvider.tsx +19 -0
- package/src/app/[variants]/(main)/community/(detail)/group_agent/features/Details/Members/index.tsx +137 -0
- package/src/app/[variants]/(main)/community/(detail)/group_agent/features/Details/Nav.tsx +88 -0
- package/src/app/[variants]/(main)/community/(detail)/group_agent/features/Details/Overview/index.tsx +213 -0
- package/src/app/[variants]/(main)/community/(detail)/group_agent/features/Details/Related/index.tsx +85 -0
- package/src/app/[variants]/(main)/community/(detail)/group_agent/features/Details/SystemRole/TagList.tsx +20 -0
- package/src/app/[variants]/(main)/community/(detail)/group_agent/features/Details/SystemRole/index.tsx +71 -0
- package/src/app/[variants]/(main)/community/(detail)/group_agent/features/Details/Versions/index.tsx +119 -0
- package/src/app/[variants]/(main)/community/(detail)/group_agent/features/Details/index.tsx +51 -0
- package/src/app/[variants]/(main)/community/(detail)/group_agent/features/Header.tsx +253 -0
- package/src/app/[variants]/(main)/community/(detail)/group_agent/features/Sidebar/ActionButton/AddGroupAgent.tsx +222 -0
- package/src/app/[variants]/(main)/community/(detail)/group_agent/features/Sidebar/ActionButton/index.tsx +34 -0
- package/src/app/[variants]/(main)/community/(detail)/group_agent/features/Sidebar/Summary/index.tsx +42 -0
- package/src/app/[variants]/(main)/community/(detail)/group_agent/features/Sidebar/index.tsx +41 -0
- package/src/app/[variants]/(main)/community/(detail)/group_agent/features/StatusPage/index.tsx +104 -0
- package/src/app/[variants]/(main)/community/(detail)/group_agent/index.tsx +103 -0
- package/src/app/[variants]/(main)/community/(detail)/group_agent/loading.tsx +1 -0
- package/src/app/[variants]/(main)/community/(detail)/user/features/DetailProvider.tsx +7 -1
- package/src/app/[variants]/(main)/community/(detail)/user/features/UserContent.tsx +2 -0
- package/src/app/[variants]/(main)/community/(detail)/user/features/UserGroupCard.tsx +186 -0
- package/src/app/[variants]/(main)/community/(detail)/user/features/UserGroupList.tsx +59 -0
- package/src/app/[variants]/(main)/community/(detail)/user/index.tsx +3 -1
- package/src/app/[variants]/(main)/community/(list)/assistant/features/List/Item.tsx +26 -8
- package/src/app/[variants]/(main)/community/(list)/assistant/index.tsx +1 -0
- package/src/app/[variants]/(main)/group/profile/features/GroupProfile/index.tsx +2 -0
- package/src/app/[variants]/(main)/group/profile/features/Header/AgentPublishButton/PublishResultModal.tsx +2 -1
- package/src/app/[variants]/(main)/group/profile/features/Header/GroupPublishButton/GroupForkConfirmModal.tsx +60 -0
- package/src/app/[variants]/(main)/group/profile/features/Header/GroupPublishButton/GroupPublishResultModal.tsx +62 -0
- package/src/app/[variants]/(main)/group/profile/features/Header/GroupPublishButton/PublishButton.tsx +122 -0
- package/src/app/[variants]/(main)/group/profile/features/Header/GroupPublishButton/index.tsx +46 -0
- package/src/app/[variants]/(main)/group/profile/features/Header/GroupPublishButton/types.ts +12 -0
- package/src/app/[variants]/(main)/group/profile/features/Header/GroupPublishButton/useMarketGroupPublish.ts +211 -0
- package/src/app/[variants]/(main)/group/profile/features/Header/GroupPublishButton/utils.ts +22 -0
- package/src/app/[variants]/router/desktopRouter.config.tsx +7 -0
- package/src/locales/default/setting.ts +12 -0
- package/src/server/routers/lambda/market/agentGroup.ts +296 -0
- package/src/server/routers/lambda/market/index.ts +134 -4
- package/src/server/services/discover/index.ts +123 -7
- package/src/services/discover.ts +55 -0
- package/src/store/discover/slices/groupAgent/action.ts +80 -0
- package/src/store/discover/store.ts +3 -0
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { Flexbox } from '@lobehub/ui';
|
|
4
|
+
import { memo } from 'react';
|
|
5
|
+
import { useParams } from 'react-router-dom';
|
|
6
|
+
|
|
7
|
+
import { useQuery } from '@/hooks/useQuery';
|
|
8
|
+
import { useDiscoverStore } from '@/store/discover';
|
|
9
|
+
|
|
10
|
+
import NotFound from '../components/NotFound';
|
|
11
|
+
import { TocProvider } from '../features/Toc/useToc';
|
|
12
|
+
import Details from './features/Details';
|
|
13
|
+
import { DetailProvider } from './features/DetailProvider';
|
|
14
|
+
import Header from './features/Header';
|
|
15
|
+
import StatusPage from './features/StatusPage';
|
|
16
|
+
import Loading from './loading';
|
|
17
|
+
|
|
18
|
+
interface GroupAgentDetailPageProps {
|
|
19
|
+
mobile?: boolean;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const GroupAgentDetailPage = memo<GroupAgentDetailPageProps>(({ mobile }) => {
|
|
23
|
+
const params = useParams<{ slug: string }>();
|
|
24
|
+
const identifier = decodeURIComponent(params.slug ?? '');
|
|
25
|
+
const { version } = useQuery() as { version?: string };
|
|
26
|
+
|
|
27
|
+
// Fetch group agent detail
|
|
28
|
+
const useGroupAgentDetail = useDiscoverStore((s) => s.useGroupAgentDetail);
|
|
29
|
+
const { data, isLoading } = useGroupAgentDetail({ identifier, version });
|
|
30
|
+
|
|
31
|
+
if (isLoading) return <Loading />;
|
|
32
|
+
|
|
33
|
+
if (!data) return <NotFound />;
|
|
34
|
+
|
|
35
|
+
// Check status and show appropriate page
|
|
36
|
+
const status = (data as any)?.group?.status || (data as any)?.status;
|
|
37
|
+
if (status === 'unpublished' || status === 'archived' || status === 'deprecated') {
|
|
38
|
+
return <StatusPage status={status} />;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Transform API data to match DiscoverGroupAgentDetail type
|
|
42
|
+
const apiConfig = (data as any)?.currentVersion?.config || {};
|
|
43
|
+
|
|
44
|
+
const transformedData = {
|
|
45
|
+
// Top level fields
|
|
46
|
+
author: (data as any)?.author,
|
|
47
|
+
// From currentVersion
|
|
48
|
+
avatar: (data as any)?.currentVersion?.avatar,
|
|
49
|
+
backgroundColor: (data as any)?.currentVersion?.backgroundColor,
|
|
50
|
+
category: (data as any)?.currentVersion?.category,
|
|
51
|
+
commentCount: (data as any)?.group?.commentCount,
|
|
52
|
+
|
|
53
|
+
// From currentVersion.config - rename systemPrompt to systemRole for consistency
|
|
54
|
+
config: {
|
|
55
|
+
...apiConfig,
|
|
56
|
+
allowDM: apiConfig.allowDM,
|
|
57
|
+
// Rename systemPrompt -> systemRole
|
|
58
|
+
openingMessage: apiConfig.openingMessage,
|
|
59
|
+
openingQuestions: apiConfig.openingQuestions,
|
|
60
|
+
revealDM: apiConfig.revealDM,
|
|
61
|
+
summary: apiConfig.summary,
|
|
62
|
+
systemRole: apiConfig.systemPrompt,
|
|
63
|
+
},
|
|
64
|
+
|
|
65
|
+
createdAt: (data as any)?.group?.createdAt,
|
|
66
|
+
// Version info
|
|
67
|
+
currentVersion: (data as any)?.currentVersion?.version,
|
|
68
|
+
currentVersionNumber: (data as any)?.currentVersion?.versionNumber,
|
|
69
|
+
description: (data as any)?.currentVersion?.description,
|
|
70
|
+
favoriteCount: (data as any)?.group?.favoriteCount,
|
|
71
|
+
homepage: (data as any)?.group?.homepage,
|
|
72
|
+
// From group
|
|
73
|
+
identifier: (data as any)?.group?.identifier,
|
|
74
|
+
installCount: (data as any)?.group?.installCount,
|
|
75
|
+
likeCount: (data as any)?.group?.likeCount,
|
|
76
|
+
locale: (data as any)?.locale,
|
|
77
|
+
memberAgents: (data as any)?.memberAgents || [],
|
|
78
|
+
status: (data as any)?.group?.status,
|
|
79
|
+
summary: (data as any)?.summary,
|
|
80
|
+
tags: (data as any)?.currentVersion?.tags,
|
|
81
|
+
title: (data as any)?.currentVersion?.name || (data as any)?.group?.name,
|
|
82
|
+
updatedAt: (data as any)?.group?.updatedAt,
|
|
83
|
+
userName: (data as any)?.author?.userName,
|
|
84
|
+
versions: (data as any)?.versions || [],
|
|
85
|
+
visibility: (data as any)?.group?.visibility,
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
return (
|
|
89
|
+
<TocProvider>
|
|
90
|
+
<DetailProvider config={transformedData}>
|
|
91
|
+
<Flexbox gap={16} width={'100%'}>
|
|
92
|
+
{/* Header Section */}
|
|
93
|
+
<Header mobile={mobile} />
|
|
94
|
+
|
|
95
|
+
{/* Details Section */}
|
|
96
|
+
<Details mobile={mobile} />
|
|
97
|
+
</Flexbox>
|
|
98
|
+
</DetailProvider>
|
|
99
|
+
</TocProvider>
|
|
100
|
+
);
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
export default GroupAgentDetailPage;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { DetailsLoading as default } from '../../components/ListLoading';
|
|
@@ -3,11 +3,17 @@
|
|
|
3
3
|
import { type ReactNode, createContext, memo, use } from 'react';
|
|
4
4
|
|
|
5
5
|
import { type MarketUserProfile } from '@/layout/AuthProvider/MarketAuth/types';
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
type DiscoverAssistantItem,
|
|
8
|
+
type DiscoverGroupAgentItem,
|
|
9
|
+
type DiscoverUserInfo,
|
|
10
|
+
} from '@/types/discover';
|
|
7
11
|
|
|
8
12
|
export interface UserDetailContextConfig {
|
|
9
13
|
agentCount: number;
|
|
14
|
+
agentGroups?: DiscoverGroupAgentItem[];
|
|
10
15
|
agents: DiscoverAssistantItem[];
|
|
16
|
+
groupCount: number;
|
|
11
17
|
isOwner: boolean;
|
|
12
18
|
mobile?: boolean;
|
|
13
19
|
onEditProfile?: (onSuccess?: (profile: MarketUserProfile) => void) => void;
|
|
@@ -6,11 +6,13 @@ import { memo } from 'react';
|
|
|
6
6
|
import UserAgentList from './UserAgentList';
|
|
7
7
|
import UserFavoriteAgents from './UserFavoriteAgents';
|
|
8
8
|
import UserFavoritePlugins from './UserFavoritePlugins';
|
|
9
|
+
import UserGroupList from './UserGroupList';
|
|
9
10
|
|
|
10
11
|
const UserContent = memo(() => {
|
|
11
12
|
return (
|
|
12
13
|
<Flexbox gap={32}>
|
|
13
14
|
<UserAgentList />
|
|
15
|
+
<UserGroupList />
|
|
14
16
|
<UserFavoriteAgents />
|
|
15
17
|
<UserFavoritePlugins />
|
|
16
18
|
</Flexbox>
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { Avatar, Block, Flexbox, Icon, Tag, Text, Tooltip, TooltipGroup } from '@lobehub/ui';
|
|
4
|
+
import { createStaticStyles } from 'antd-style';
|
|
5
|
+
import { ClockIcon, DownloadIcon, UsersIcon } from 'lucide-react';
|
|
6
|
+
import qs from 'query-string';
|
|
7
|
+
import { memo, useCallback } from 'react';
|
|
8
|
+
import { useTranslation } from 'react-i18next';
|
|
9
|
+
import { Link, useNavigate } from 'react-router-dom';
|
|
10
|
+
import urlJoin from 'url-join';
|
|
11
|
+
|
|
12
|
+
import PublishedTime from '@/components/PublishedTime';
|
|
13
|
+
import { type DiscoverGroupAgentItem } from '@/types/discover';
|
|
14
|
+
import { formatIntergerNumber } from '@/utils/format';
|
|
15
|
+
|
|
16
|
+
const styles = createStaticStyles(({ css, cssVar }) => {
|
|
17
|
+
return {
|
|
18
|
+
desc: css`
|
|
19
|
+
flex: 1;
|
|
20
|
+
margin: 0 !important;
|
|
21
|
+
color: ${cssVar.colorTextSecondary};
|
|
22
|
+
`,
|
|
23
|
+
footer: css`
|
|
24
|
+
margin-block-start: 16px;
|
|
25
|
+
border-block-start: 1px dashed ${cssVar.colorBorder};
|
|
26
|
+
background: ${cssVar.colorBgContainer};
|
|
27
|
+
`,
|
|
28
|
+
secondaryDesc: css`
|
|
29
|
+
font-size: 12px;
|
|
30
|
+
color: ${cssVar.colorTextDescription};
|
|
31
|
+
`,
|
|
32
|
+
statTag: css`
|
|
33
|
+
border-radius: 4px;
|
|
34
|
+
|
|
35
|
+
font-family: ${cssVar.fontFamilyCode};
|
|
36
|
+
font-size: 11px;
|
|
37
|
+
color: ${cssVar.colorTextSecondary};
|
|
38
|
+
|
|
39
|
+
background: ${cssVar.colorFillTertiary};
|
|
40
|
+
`,
|
|
41
|
+
title: css`
|
|
42
|
+
margin: 0 !important;
|
|
43
|
+
font-size: 16px !important;
|
|
44
|
+
font-weight: 500 !important;
|
|
45
|
+
|
|
46
|
+
&:hover {
|
|
47
|
+
color: ${cssVar.colorLink};
|
|
48
|
+
}
|
|
49
|
+
`,
|
|
50
|
+
};
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
type UserGroupCardProps = DiscoverGroupAgentItem;
|
|
54
|
+
|
|
55
|
+
const UserGroupCard = memo<UserGroupCardProps>(
|
|
56
|
+
({ avatar, title, description, createdAt, category, installCount, identifier, memberCount }) => {
|
|
57
|
+
const { t } = useTranslation(['discover']);
|
|
58
|
+
const navigate = useNavigate();
|
|
59
|
+
|
|
60
|
+
const link = qs.stringifyUrl(
|
|
61
|
+
{
|
|
62
|
+
query: { source: 'new' },
|
|
63
|
+
url: urlJoin('/community/group_agent', identifier),
|
|
64
|
+
},
|
|
65
|
+
{ skipNull: true },
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
const handleCardClick = useCallback(() => {
|
|
69
|
+
navigate(link);
|
|
70
|
+
}, [link, navigate]);
|
|
71
|
+
|
|
72
|
+
return (
|
|
73
|
+
<Block
|
|
74
|
+
clickable
|
|
75
|
+
height={'100%'}
|
|
76
|
+
onClick={handleCardClick}
|
|
77
|
+
style={{
|
|
78
|
+
cursor: 'pointer',
|
|
79
|
+
overflow: 'hidden',
|
|
80
|
+
position: 'relative',
|
|
81
|
+
}}
|
|
82
|
+
variant={'outlined'}
|
|
83
|
+
width={'100%'}
|
|
84
|
+
>
|
|
85
|
+
<Flexbox
|
|
86
|
+
align={'flex-start'}
|
|
87
|
+
gap={16}
|
|
88
|
+
horizontal
|
|
89
|
+
justify={'space-between'}
|
|
90
|
+
padding={16}
|
|
91
|
+
width={'100%'}
|
|
92
|
+
>
|
|
93
|
+
<Flexbox
|
|
94
|
+
gap={12}
|
|
95
|
+
horizontal
|
|
96
|
+
style={{
|
|
97
|
+
overflow: 'hidden',
|
|
98
|
+
}}
|
|
99
|
+
>
|
|
100
|
+
<Avatar avatar={avatar} shape={'square'} size={40} style={{ flex: 'none' }} />
|
|
101
|
+
<Flexbox
|
|
102
|
+
flex={1}
|
|
103
|
+
gap={2}
|
|
104
|
+
style={{
|
|
105
|
+
overflow: 'hidden',
|
|
106
|
+
}}
|
|
107
|
+
>
|
|
108
|
+
<Link
|
|
109
|
+
onClick={(e) => e.stopPropagation()}
|
|
110
|
+
style={{ color: 'inherit', flex: 1, overflow: 'hidden' }}
|
|
111
|
+
to={link}
|
|
112
|
+
>
|
|
113
|
+
<Text as={'h3'} className={styles.title} ellipsis style={{ flex: 1 }}>
|
|
114
|
+
{title}
|
|
115
|
+
</Text>
|
|
116
|
+
</Link>
|
|
117
|
+
</Flexbox>
|
|
118
|
+
</Flexbox>
|
|
119
|
+
</Flexbox>
|
|
120
|
+
<Flexbox flex={1} gap={12} paddingInline={16}>
|
|
121
|
+
<Text
|
|
122
|
+
as={'p'}
|
|
123
|
+
className={styles.desc}
|
|
124
|
+
ellipsis={{
|
|
125
|
+
rows: 3,
|
|
126
|
+
}}
|
|
127
|
+
>
|
|
128
|
+
{description}
|
|
129
|
+
</Text>
|
|
130
|
+
<TooltipGroup>
|
|
131
|
+
<Flexbox align={'center'} gap={4} horizontal>
|
|
132
|
+
{memberCount !== undefined && memberCount > 0 && (
|
|
133
|
+
<Tooltip
|
|
134
|
+
placement={'top'}
|
|
135
|
+
styles={{ root: { pointerEvents: 'none' } }}
|
|
136
|
+
title={t('groupAgents.memberCount', { defaultValue: 'Members' })}
|
|
137
|
+
>
|
|
138
|
+
<Tag className={styles.statTag} icon={<Icon icon={UsersIcon} />}>
|
|
139
|
+
{formatIntergerNumber(memberCount)}
|
|
140
|
+
</Tag>
|
|
141
|
+
</Tooltip>
|
|
142
|
+
)}
|
|
143
|
+
{installCount !== undefined && installCount > 0 && (
|
|
144
|
+
<Tooltip
|
|
145
|
+
placement={'top'}
|
|
146
|
+
styles={{ root: { pointerEvents: 'none' } }}
|
|
147
|
+
title={t('groupAgents.downloads', { defaultValue: 'Downloads' })}
|
|
148
|
+
>
|
|
149
|
+
<Tag className={styles.statTag} icon={<Icon icon={DownloadIcon} />}>
|
|
150
|
+
{formatIntergerNumber(installCount)}
|
|
151
|
+
</Tag>
|
|
152
|
+
</Tooltip>
|
|
153
|
+
)}
|
|
154
|
+
</Flexbox>
|
|
155
|
+
</TooltipGroup>
|
|
156
|
+
</Flexbox>
|
|
157
|
+
<Flexbox
|
|
158
|
+
align={'center'}
|
|
159
|
+
className={styles.footer}
|
|
160
|
+
horizontal
|
|
161
|
+
justify={'space-between'}
|
|
162
|
+
padding={16}
|
|
163
|
+
>
|
|
164
|
+
<Flexbox
|
|
165
|
+
align={'center'}
|
|
166
|
+
className={styles.secondaryDesc}
|
|
167
|
+
horizontal
|
|
168
|
+
justify={'space-between'}
|
|
169
|
+
>
|
|
170
|
+
<Flexbox align={'center'} gap={4} horizontal>
|
|
171
|
+
<Icon icon={ClockIcon} size={14} />
|
|
172
|
+
<PublishedTime
|
|
173
|
+
className={styles.secondaryDesc}
|
|
174
|
+
date={createdAt}
|
|
175
|
+
template={'MMM DD, YYYY'}
|
|
176
|
+
/>
|
|
177
|
+
</Flexbox>
|
|
178
|
+
{category && t(`category.groupAgent.${category}` as any, { defaultValue: category })}
|
|
179
|
+
</Flexbox>
|
|
180
|
+
</Flexbox>
|
|
181
|
+
</Block>
|
|
182
|
+
);
|
|
183
|
+
},
|
|
184
|
+
);
|
|
185
|
+
|
|
186
|
+
export default UserGroupCard;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { Flexbox, Grid, Tag, Text } from '@lobehub/ui';
|
|
4
|
+
import { Pagination } from 'antd';
|
|
5
|
+
import { memo, useMemo, useState } from 'react';
|
|
6
|
+
import { useTranslation } from 'react-i18next';
|
|
7
|
+
|
|
8
|
+
import { useUserDetailContext } from './DetailProvider';
|
|
9
|
+
import UserGroupCard from './UserGroupCard';
|
|
10
|
+
|
|
11
|
+
interface UserGroupListProps {
|
|
12
|
+
pageSize?: number;
|
|
13
|
+
rows?: number;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const UserGroupList = memo<UserGroupListProps>(({ rows = 4, pageSize = 10 }) => {
|
|
17
|
+
const { t } = useTranslation('discover');
|
|
18
|
+
const { agentGroups, groupCount } = useUserDetailContext();
|
|
19
|
+
const [currentPage, setCurrentPage] = useState(1);
|
|
20
|
+
|
|
21
|
+
const paginatedGroups = useMemo(() => {
|
|
22
|
+
if (!agentGroups) return [];
|
|
23
|
+
const startIndex = (currentPage - 1) * pageSize;
|
|
24
|
+
return agentGroups.slice(startIndex, startIndex + pageSize);
|
|
25
|
+
}, [agentGroups, currentPage, pageSize]);
|
|
26
|
+
|
|
27
|
+
if (!agentGroups || agentGroups.length === 0) return null;
|
|
28
|
+
|
|
29
|
+
const showPagination = agentGroups.length > pageSize;
|
|
30
|
+
|
|
31
|
+
return (
|
|
32
|
+
<Flexbox gap={16}>
|
|
33
|
+
<Flexbox align={'center'} gap={8} horizontal>
|
|
34
|
+
<Text fontSize={16} weight={500}>
|
|
35
|
+
{t('user.publishedGroups', { defaultValue: '创作的群组' })}
|
|
36
|
+
</Text>
|
|
37
|
+
{groupCount > 0 && <Tag>{groupCount}</Tag>}
|
|
38
|
+
</Flexbox>
|
|
39
|
+
<Grid rows={rows} width={'100%'}>
|
|
40
|
+
{paginatedGroups.map((item, index) => (
|
|
41
|
+
<UserGroupCard key={item.identifier || index} {...item} />
|
|
42
|
+
))}
|
|
43
|
+
</Grid>
|
|
44
|
+
{showPagination && (
|
|
45
|
+
<Flexbox align={'center'} justify={'center'}>
|
|
46
|
+
<Pagination
|
|
47
|
+
current={currentPage}
|
|
48
|
+
onChange={(page) => setCurrentPage(page)}
|
|
49
|
+
pageSize={pageSize}
|
|
50
|
+
showSizeChanger={false}
|
|
51
|
+
total={agentGroups.length}
|
|
52
|
+
/>
|
|
53
|
+
</Flexbox>
|
|
54
|
+
)}
|
|
55
|
+
</Flexbox>
|
|
56
|
+
);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
export default UserGroupList;
|
|
@@ -58,11 +58,13 @@ const UserDetailPage = memo<UserDetailPageProps>(({ mobile }) => {
|
|
|
58
58
|
|
|
59
59
|
const contextConfig = useMemo(() => {
|
|
60
60
|
if (!data || !data.user) return null;
|
|
61
|
-
const { user, agents } = data;
|
|
61
|
+
const { user, agents, agentGroups } = data;
|
|
62
62
|
const totalInstalls = agents.reduce((sum, agent) => sum + (agent.installCount || 0), 0);
|
|
63
63
|
return {
|
|
64
64
|
agentCount: agents.length,
|
|
65
|
+
agentGroups: agentGroups || [],
|
|
65
66
|
agents,
|
|
67
|
+
groupCount: agentGroups?.length || 0,
|
|
66
68
|
isOwner,
|
|
67
69
|
mobile,
|
|
68
70
|
onEditProfile: handleEditProfile,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Avatar, Block, Flexbox, Icon, Text } from '@lobehub/ui';
|
|
1
|
+
import { Avatar, Block, Flexbox, Icon, Tag, Text } from '@lobehub/ui';
|
|
2
2
|
import { createStaticStyles } from 'antd-style';
|
|
3
3
|
import { ClockIcon } from 'lucide-react';
|
|
4
4
|
import qs from 'query-string';
|
|
@@ -9,8 +9,8 @@ import urlJoin from 'url-join';
|
|
|
9
9
|
|
|
10
10
|
import PublishedTime from '@/components/PublishedTime';
|
|
11
11
|
import { useQuery } from '@/hooks/useQuery';
|
|
12
|
-
import { type AssistantMarketSource, type DiscoverAssistantItem } from '@/types/discover';
|
|
13
12
|
import { discoverService } from '@/services/discover';
|
|
13
|
+
import { type AssistantMarketSource, type DiscoverAssistantItem } from '@/types/discover';
|
|
14
14
|
|
|
15
15
|
import TokenTag from './TokenTag';
|
|
16
16
|
|
|
@@ -68,13 +68,16 @@ const AssistantItem = memo<DiscoverAssistantItem>(
|
|
|
68
68
|
installCount,
|
|
69
69
|
backgroundColor,
|
|
70
70
|
userName,
|
|
71
|
+
type,
|
|
71
72
|
}) => {
|
|
72
73
|
const navigate = useNavigate();
|
|
73
74
|
const { source } = useQuery() as { source?: AssistantMarketSource };
|
|
75
|
+
const isGroupAgent = type === 'agent-group';
|
|
76
|
+
const basePath = isGroupAgent ? '/community/group_agent' : '/community/assistant';
|
|
74
77
|
const link = qs.stringifyUrl(
|
|
75
78
|
{
|
|
76
79
|
query: { source },
|
|
77
|
-
url: urlJoin(
|
|
80
|
+
url: urlJoin(basePath, identifier),
|
|
78
81
|
},
|
|
79
82
|
{ skipNull: true },
|
|
80
83
|
);
|
|
@@ -93,11 +96,13 @@ const AssistantItem = memo<DiscoverAssistantItem>(
|
|
|
93
96
|
);
|
|
94
97
|
|
|
95
98
|
const handleClick = useCallback(() => {
|
|
96
|
-
discoverService
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
99
|
+
discoverService
|
|
100
|
+
.reportAgentEvent({
|
|
101
|
+
event: 'click',
|
|
102
|
+
identifier,
|
|
103
|
+
source: location.pathname,
|
|
104
|
+
})
|
|
105
|
+
.catch(() => {});
|
|
101
106
|
|
|
102
107
|
navigate(link);
|
|
103
108
|
}, [identifier, link, navigate]);
|
|
@@ -115,6 +120,19 @@ const AssistantItem = memo<DiscoverAssistantItem>(
|
|
|
115
120
|
variant={'outlined'}
|
|
116
121
|
width={'100%'}
|
|
117
122
|
>
|
|
123
|
+
{isGroupAgent && (
|
|
124
|
+
<Tag
|
|
125
|
+
color="info"
|
|
126
|
+
style={{
|
|
127
|
+
position: 'absolute',
|
|
128
|
+
right: 12,
|
|
129
|
+
top: 12,
|
|
130
|
+
zIndex: 1,
|
|
131
|
+
}}
|
|
132
|
+
>
|
|
133
|
+
{t('groupAgents.tag', { defaultValue: '群组' })}
|
|
134
|
+
</Tag>
|
|
135
|
+
)}
|
|
118
136
|
<Flexbox
|
|
119
137
|
align={'flex-start'}
|
|
120
138
|
gap={16}
|
|
@@ -14,6 +14,7 @@ import { agentGroupSelectors } from '@/store/agentGroup/selectors';
|
|
|
14
14
|
import { useGroupProfileStore } from '@/store/groupProfile';
|
|
15
15
|
|
|
16
16
|
import AutoSaveHint from '../Header/AutoSaveHint';
|
|
17
|
+
import GroupPublishButton from '../Header/GroupPublishButton';
|
|
17
18
|
import GroupHeader from './GroupHeader';
|
|
18
19
|
|
|
19
20
|
const GroupProfile = memo(() => {
|
|
@@ -75,6 +76,7 @@ const GroupProfile = memo(() => {
|
|
|
75
76
|
>
|
|
76
77
|
{t('startConversation')}
|
|
77
78
|
</Button>
|
|
79
|
+
<GroupPublishButton />
|
|
78
80
|
</Flexbox>
|
|
79
81
|
</Flexbox>
|
|
80
82
|
<Divider />
|
|
@@ -19,7 +19,8 @@ const PublishResultModal = memo<PublishResultModalProps>(({ identifier, onCancel
|
|
|
19
19
|
|
|
20
20
|
const handleGoToMarket = () => {
|
|
21
21
|
if (identifier) {
|
|
22
|
-
|
|
22
|
+
console.log('identifier', identifier);
|
|
23
|
+
navigate(`/community/group_agent/${identifier}`);
|
|
23
24
|
}
|
|
24
25
|
onCancel();
|
|
25
26
|
};
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { Avatar, Flexbox, Modal } from '@lobehub/ui';
|
|
4
|
+
import { memo } from 'react';
|
|
5
|
+
import { useTranslation } from 'react-i18next';
|
|
6
|
+
|
|
7
|
+
import type { OriginalGroupInfo } from './types';
|
|
8
|
+
|
|
9
|
+
interface GroupForkConfirmModalProps {
|
|
10
|
+
loading?: boolean;
|
|
11
|
+
onCancel: () => void;
|
|
12
|
+
onConfirm: () => void;
|
|
13
|
+
open: boolean;
|
|
14
|
+
originalGroup: OriginalGroupInfo | null;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const GroupForkConfirmModal = memo<GroupForkConfirmModalProps>(
|
|
18
|
+
({ open, onCancel, onConfirm, originalGroup, loading }) => {
|
|
19
|
+
const { t } = useTranslation('setting');
|
|
20
|
+
|
|
21
|
+
if (!originalGroup) return null;
|
|
22
|
+
|
|
23
|
+
const authorName = originalGroup.author?.name || originalGroup.author?.userName || 'Unknown';
|
|
24
|
+
|
|
25
|
+
return (
|
|
26
|
+
<Modal
|
|
27
|
+
cancelText={t('cancel', { ns: 'common' })}
|
|
28
|
+
centered
|
|
29
|
+
closable
|
|
30
|
+
confirmLoading={loading}
|
|
31
|
+
okText={t('marketPublish.forkConfirm.confirmGroup')}
|
|
32
|
+
onCancel={onCancel}
|
|
33
|
+
onOk={onConfirm}
|
|
34
|
+
open={open}
|
|
35
|
+
title={t('marketPublish.forkConfirm.titleGroup')}
|
|
36
|
+
width={480}
|
|
37
|
+
>
|
|
38
|
+
<Flexbox gap={16} style={{ marginTop: 16 }}>
|
|
39
|
+
<Flexbox align="center" gap={12} horizontal>
|
|
40
|
+
<Avatar avatar={originalGroup.avatar} size={48} style={{ flex: 'none' }} />
|
|
41
|
+
<Flexbox gap={4}>
|
|
42
|
+
<div style={{ fontWeight: 500 }}>{originalGroup.name}</div>
|
|
43
|
+
<div style={{ fontSize: 12, opacity: 0.6 }}>
|
|
44
|
+
{t('marketPublish.forkConfirm.by', { author: authorName })}
|
|
45
|
+
</div>
|
|
46
|
+
</Flexbox>
|
|
47
|
+
</Flexbox>
|
|
48
|
+
|
|
49
|
+
<p style={{ lineHeight: 1.6, margin: 0 }}>
|
|
50
|
+
{t('marketPublish.forkConfirm.descriptionGroup')}
|
|
51
|
+
</p>
|
|
52
|
+
</Flexbox>
|
|
53
|
+
</Modal>
|
|
54
|
+
);
|
|
55
|
+
},
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
GroupForkConfirmModal.displayName = 'GroupForkConfirmModal';
|
|
59
|
+
|
|
60
|
+
export default GroupForkConfirmModal;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { FluentEmoji, Modal, Text } from '@lobehub/ui';
|
|
4
|
+
import { Result } from 'antd';
|
|
5
|
+
import { memo } from 'react';
|
|
6
|
+
import { useTranslation } from 'react-i18next';
|
|
7
|
+
import { useNavigate } from 'react-router-dom';
|
|
8
|
+
|
|
9
|
+
interface GroupPublishResultModalProps {
|
|
10
|
+
identifier?: string;
|
|
11
|
+
onCancel: () => void;
|
|
12
|
+
open: boolean;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const GroupPublishResultModal = memo<GroupPublishResultModalProps>(
|
|
16
|
+
({ identifier, onCancel, open }) => {
|
|
17
|
+
const navigate = useNavigate();
|
|
18
|
+
const { t } = useTranslation('setting');
|
|
19
|
+
const { t: tCommon } = useTranslation('common');
|
|
20
|
+
|
|
21
|
+
const handleGoToMarket = () => {
|
|
22
|
+
if (identifier) {
|
|
23
|
+
navigate(`/community/group_agent/${identifier}`);
|
|
24
|
+
}
|
|
25
|
+
onCancel();
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
return (
|
|
29
|
+
<Modal
|
|
30
|
+
cancelText={tCommon('cancel')}
|
|
31
|
+
centered
|
|
32
|
+
okText={t('marketPublish.resultModal.view')}
|
|
33
|
+
onCancel={onCancel}
|
|
34
|
+
onOk={handleGoToMarket}
|
|
35
|
+
open={open}
|
|
36
|
+
title={null}
|
|
37
|
+
width={440}
|
|
38
|
+
>
|
|
39
|
+
<Result
|
|
40
|
+
icon={<FluentEmoji emoji={'🎉'} size={96} type={'anim'} />}
|
|
41
|
+
style={{
|
|
42
|
+
paddingBottom: 32,
|
|
43
|
+
paddingTop: 48,
|
|
44
|
+
width: '100%',
|
|
45
|
+
}}
|
|
46
|
+
subTitle={
|
|
47
|
+
<Text fontSize={14} type={'secondary'}>
|
|
48
|
+
{t('marketPublish.resultModal.messageGroup')}
|
|
49
|
+
</Text>
|
|
50
|
+
}
|
|
51
|
+
title={
|
|
52
|
+
<Text fontSize={28} weight={'bold'}>
|
|
53
|
+
{t('marketPublish.resultModal.title')}
|
|
54
|
+
</Text>
|
|
55
|
+
}
|
|
56
|
+
/>
|
|
57
|
+
</Modal>
|
|
58
|
+
);
|
|
59
|
+
},
|
|
60
|
+
);
|
|
61
|
+
|
|
62
|
+
export default GroupPublishResultModal;
|