Compare commits

...

2 Commits

Author SHA1 Message Date
jiangxucong f512e5022e Merge remote-tracking branch 'origin/main' into main 5 months ago
jiangxucong 534762dddb AI工具集和助手接口联调 5 months ago

@ -22,19 +22,20 @@
"category": { "category": {
"assistant": { "assistant": {
"all": "全部", "all": "全部",
"academic": "收藏", "collect": "收藏",
"career": "政务", "academic": "政务",
"copywriting": "教育", "education": "教育",
"design": "营销", "marketing": "营销",
"education": "设计", "design": "设计",
"emotions": "办公", "office": "办公",
"programming": "编程", "programming": "编程",
"games": "娱乐", "entertainment": "娱乐",
"life": "生活", "life": "生活",
"general": "通用" "general": "通用"
}, },
"plugin": { "plugin": {
"all": "全部", "all": "全部",
"collect": "收藏",
"gaming-entertainment": "游戏娱乐", "gaming-entertainment": "游戏娱乐",
"life-style": "生活方式", "life-style": "生活方式",
"media-generate": "媒体生成", "media-generate": "媒体生成",

Binary file not shown.

After

Width:  |  Height:  |  Size: 351 B

@ -61,7 +61,7 @@ const TopActions = memo<TopActionProps>(({ tab }) => {
<div className={value == '/chat' ? cx(styles.iconText, styles.iconSelectText) : cx(styles.iconText) }></div> <div className={value == '/chat' ? cx(styles.iconText, styles.iconSelectText) : cx(styles.iconText) }></div>
</Link> </Link>
{enableKnowledgeBase && ( {enableKnowledgeBase && (
<Link className={value == '/discover/assistants' ? cx(styles.linkUrl, styles.linkclic) : cx(styles.linkUrl)} aria-label={t('tab.files')} href={'/discover/assistants'} onClick={() => {setValue("/discover/assistants"); window.localStorage.setItem("nowChat", "")}}> <Link className={value == '/discover/assistants' ? cx(styles.linkUrl, styles.linkclic) : cx(styles.linkUrl)} aria-label={t('tab.files')} href={`/discover/assistants?userid=${localStorage.getItem('userId')}`} onClick={() => {setValue("/discover/assistants"); window.localStorage.setItem("nowChat", "")}}>
<Image alt={"files"} className={cx(styles.iconImg)} preview={false} src="/images/zs.png" /> <Image alt={"files"} className={cx(styles.iconImg)} preview={false} src="/images/zs.png" />
<div className={value == '/discover/assistants' ? cx(styles.iconText, styles.iconSelectText) : cx(styles.iconText) }></div> <div className={value == '/discover/assistants' ? cx(styles.iconText, styles.iconSelectText) : cx(styles.iconText) }></div>
</Link> </Link>
@ -85,7 +85,7 @@ const TopActions = memo<TopActionProps>(({ tab }) => {
</Link> </Link>
)} )}
{showMarket && ( {showMarket && (
<Link className={value == '/plugins' ? cx(styles.linkUrl, styles.linkclic) : cx(styles.linkUrl)} aria-label={t('tab.Plugins')} href={'/plugins'} onClick={() => {setValue("/plugins"); window.localStorage.setItem("nowChat", "")}}> <Link className={value == '/plugins' ? cx(styles.linkUrl, styles.linkclic) : cx(styles.linkUrl)} aria-label={t('tab.Plugins')} href={'/discover/plugins'} onClick={() => {setValue("/plugins"); window.localStorage.setItem("nowChat", "")}}>
<Image alt={"plugins"} className={cx(styles.iconImg)} preview={false} src="/images/cj.png" /> <Image alt={"plugins"} className={cx(styles.iconImg)} preview={false} src="/images/cj.png" />
<div className={value == '/plugins' ? cx(styles.iconText, styles.iconSelectText) : cx(styles.iconText) }></div> <div className={value == '/plugins' ? cx(styles.iconText, styles.iconSelectText) : cx(styles.iconText) }></div>
</Link> </Link>

@ -87,21 +87,7 @@ const Layout = memo<LayoutProps>(({ children, nav }) => {
width={'100%'} width={'100%'}
> >
{nav} {nav}
<div style={{ width: '100%' }}>
<div className={cx(styles.topCenten)}>
<div className={cx(styles.ledDiv)}>
<span className={cx(styles.leftTitle)} style={{ marginLeft: '40px' }}></span>
<Divider className={cx(styles.dividerCen)} type="vertical" />
<span className={cx(styles.leftTitle)}>{title[window?.location?.pathname]}</span>
</div>
<div className={cx(styles.ledDiv)} style={{ height: '42px', lineHeight: "42px", textAlign: 'right' }}>
<Input className={cx(styles.inp)} placeholder="请输入关键字搜索助手" suffix={<SearchOutlined className={cx(styles.serchIcon)} />} />
<Avatar style={{ backgroundColor: '#90ACFF' }} icon={<UserOutlined />} />
<span className={cx(styles.nameSpn)}> </span>
</div>
</div>
{children} {children}
</div>
</Flexbox> </Flexbox>
</> </>
); );

@ -1,7 +1,7 @@
'use client'; 'use client';
import { ActionIcon, Icon } from '@lobehub/ui'; import { ActionIcon, Icon } from '@lobehub/ui';
import { App, Dropdown } from 'antd'; import { App, Dropdown, Button } from 'antd';
import { createStyles } from 'antd-style'; import { createStyles } from 'antd-style';
import { ChevronDownIcon, PlusIcon } from 'lucide-react'; import { ChevronDownIcon, PlusIcon } from 'lucide-react';
import { useRouter } from 'next/navigation'; import { useRouter } from 'next/navigation';
@ -15,9 +15,9 @@ import { DiscoverAssistantItem } from '@/types/discover';
const useStyles = createStyles(({ css }) => ({ const useStyles = createStyles(({ css }) => ({
button: css` button: css`
button { border-radius: 20px;
width: 100%; color: #2E62FF;
} border: 1px solid #2E62FF;
`, `,
})); }));
@ -36,6 +36,7 @@ const AddAgent = memo<{ data: DiscoverAssistantItem; mobile?: boolean }>(({ data
const session = await createSession({ config: data.config, meta: data.meta }); const session = await createSession({ config: data.config, meta: data.meta });
setIsLoading(false); setIsLoading(false);
message.success(t('assistants.addAgentSuccess')); message.success(t('assistants.addAgentSuccess'));
console.log(SESSION_CHAT_URL(session, mobile),'5555555555555555555555')
router.push(SESSION_CHAT_URL(session, mobile)); router.push(SESSION_CHAT_URL(session, mobile));
}; };
@ -59,27 +60,9 @@ const AddAgent = memo<{ data: DiscoverAssistantItem; mobile?: boolean }>(({ data
); );
return ( return (
<Dropdown.Button <>
className={styles.button} <Button className={styles.button} loading={isLoading} onClick={handleAddAgentAndConverse}></Button>
icon={<Icon icon={ChevronDownIcon} />} </>
loading={isLoading}
menu={{
items: [
{
key: 'addAgent',
label: t('assistants.addAgent'),
onClick: handleAddAgent,
},
],
}}
onClick={handleAddAgentAndConverse}
overlayStyle={{ minWidth: 267 }}
size={'large'}
style={{ flex: 1, width: 'unset' }}
type={'primary'}
>
{t('assistants.addAgentAndConverse')}
</Dropdown.Button>
); );
}); });

@ -11,12 +11,12 @@ import { memo } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { Flexbox } from 'react-layout-kit'; import { Flexbox } from 'react-layout-kit';
import urlJoin from 'url-join'; import urlJoin from 'url-join';
import { useRouter } from 'next/navigation';
import { DiscoverAssistantItem } from '@/types/discover'; import { DiscoverAssistantItem } from '@/types/discover';
import GitHubAvatar from '../../../../components/GitHubAvatar'; import GitHubAvatar from '../../../../components/GitHubAvatar';
import Back from '../../../features/Back'; import Back from '../../../features/Back';
import Actions from './Actions';
export const useStyles = createStyles(({ css, token }) => ({ export const useStyles = createStyles(({ css, token }) => ({
tag: css` tag: css`
color: ${token.colorTextSecondary}; color: ${token.colorTextSecondary};
@ -33,6 +33,36 @@ export const useStyles = createStyles(({ css, token }) => ({
font-weight: bold; font-weight: bold;
line-height: 1.2; line-height: 1.2;
`, `,
top: css`
padding: 20px 0px;
box-sizing: border-box;
border-width: 0px 0px 2px 0px;
border-style: solid;
border-color: rgba(187, 204, 253, 0.24);
padding: 20px 50px;
`,
topBtn: css`
border-radius: 20px;
color: #2E62FF;
border: 1px solid #2E62FF;
`,
conTitle: css`
width: 125px;
height: 50px;
line-height: 50px;
text-align: center;
color: #fff;
font-size: 20px;
border-radius: 0px 129px 129px 0px;
opacity: 1;
background: linear-gradient(270deg, #2D65FF 0%, rgba(0, 166, 255, 0.52) 99%);
`,
description: css`
padding: 0 45px;
`,
tag: css`
padding: 0px 45px;
`,
})); }));
interface HeaderProps { interface HeaderProps {
@ -43,12 +73,14 @@ interface HeaderProps {
const Header = memo<HeaderProps>(({ identifier, data, mobile }) => { const Header = memo<HeaderProps>(({ identifier, data, mobile }) => {
const { styles, theme } = useStyles(); const { styles, theme } = useStyles();
const router = useRouter()
const { t } = useTranslation('discover'); const { t } = useTranslation('discover');
const handleBack = () => {
router.push('/discover/assistants?userid=' + localStorage.getItem('userId'))
}
return ( return (
<Flexbox gap={12} width={'100%'}> <Flexbox gap={12} width={'100%'}>
{!mobile && <Back href={'/discover/assistants'} />} <Flexbox align={'center'} gap={8} horizontal justify={'space-between'} width={'100%'} className={styles.top}>
<Flexbox align={'center'} gap={8} horizontal justify={'space-between'} width={'100%'}>
<Flexbox align={'center'} gap={16} horizontal justify={'flex-start'}> <Flexbox align={'center'} gap={16} horizontal justify={'flex-start'}>
<Avatar <Avatar
alt={identifier} alt={identifier}
@ -72,28 +104,17 @@ const Header = memo<HeaderProps>(({ identifier, data, mobile }) => {
</time> </time>
</Flexbox> </Flexbox>
</Flexbox> </Flexbox>
<Actions data={data} identifier={identifier} />
</Flexbox> </Flexbox>
{!mobile && ( {!mobile && (
<Flexbox align={'center'} gap={4} horizontal justify={'flex-end'}> <Flexbox align={'center'} gap={4} horizontal justify={'flex-end'}>
<Link href={'/discover/assistants'}> <Button className={styles.topBtn} onClick={() => handleBack()}></Button>
<Button className={styles.tag} shape={'round'} size={'small'}>
{t('tab.assistants')}
</Button>
</Link>
{data.meta?.category && (
<>
<Icon color={theme.colorTextSecondary} icon={ChevronRight} />
<Link href={urlJoin('/discover/assistants', data.meta.category)}>
<Button className={styles.tag} shape={'round'} size={'small'}>
{t(`category.assistant.${data.meta.category}`)}
</Button>
</Link>
</>
)}
</Flexbox> </Flexbox>
)} )}
</Flexbox> </Flexbox>
<div>{data.meta.description}</div> <div className={styles.conTitle}></div>
<div className={styles.description}>{data.meta.description}</div>
<div className={styles.tag}>
{data.meta.tags && ( {data.meta.tags && (
<Flexbox gap={4} horizontal wrap={'wrap'}> <Flexbox gap={4} horizontal wrap={'wrap'}>
{data.meta.tags.map((tag) => ( {data.meta.tags.map((tag) => (
@ -111,6 +132,8 @@ const Header = memo<HeaderProps>(({ identifier, data, mobile }) => {
))} ))}
</Flexbox> </Flexbox>
)} )}
</div>
<div className={styles.conTitle}></div>
</Flexbox> </Flexbox>
); );
}); });

@ -21,23 +21,17 @@ interface ConversationExampleProps extends FlexboxProps {
const ConversationExample = memo<ConversationExampleProps>(({ data }) => { const ConversationExample = memo<ConversationExampleProps>(({ data }) => {
const { t } = useTranslation('discover'); const { t } = useTranslation('discover');
const theme = useTheme(); const theme = useTheme();
console.log(data.config.systemRole,111111111)
return ( return (
<HighlightBlock <>
avatar={data?.meta.avatar} <Flexbox paddingInline={16} style={{padding: '0 45'}}>
icon={BotMessageSquare}
justify={'space-between'}
style={{ background: theme.colorBgContainer }}
title={t('assistants.systemRole')}
>
<Flexbox paddingInline={16}>
{data.config.systemRole ? ( {data.config.systemRole ? (
<Markdown fontSize={theme.fontSize}>{data.config.systemRole}</Markdown> <Markdown fontSize={theme.fontSize}>{data.config.systemRole}</Markdown>
) : ( ) : (
<Skeleton paragraph={{ rows: 4 }} title={false} /> <Skeleton paragraph={{ rows: 4 }} title={false} />
)} )}
</Flexbox> </Flexbox>
</HighlightBlock> </>
); );
}); });

@ -64,7 +64,7 @@ const Page = async ({ params, searchParams }: Props) => {
const discoverService = new DiscoverService(); const discoverService = new DiscoverService();
const data = await discoverService.getAssistantById(locale, identifier); const data = await discoverService.getAssistantById(locale, identifier);
if (!data) return notFound(); if (!data) return notFound();
console.log(data,'37373733737')
const { meta, createdAt, author, config } = data; const { meta, createdAt, author, config } = data;
let pluginData: DiscoverPlugintem[] = []; let pluginData: DiscoverPlugintem[] = [];
@ -93,17 +93,8 @@ const Page = async ({ params, searchParams }: Props) => {
<> <>
<StructuredData ld={ld} /> <StructuredData ld={ld} />
<DetailLayout <DetailLayout
actions={<Actions data={data} identifier={identifier} />}
header={<Header data={data} identifier={identifier} mobile={mobile} />} header={<Header data={data} identifier={identifier} mobile={mobile} />}
mobile={mobile} mobile={mobile}
sidebar={
<InfoSidebar
data={data}
identifier={identifier}
mobile={mobile}
pluginData={pluginData}
/>
}
/* ↓ cloud slot ↓ */ /* ↓ cloud slot ↓ */
/* ↑ cloud slot ↑ */ /* ↑ cloud slot ↑ */

@ -37,6 +37,7 @@ const DetailLayout = memo<DetailLayoutProps>(
return ( return (
<> <>
<div style={{ backgroundColor: '#fff'}}>
{header} {header}
<Flexbox gap={32} horizontal width={'100%'}> <Flexbox gap={32} horizontal width={'100%'}>
<Flexbox flex={1} gap={48} style={{ overflow: 'hidden', position: 'relative' }}> <Flexbox flex={1} gap={48} style={{ overflow: 'hidden', position: 'relative' }}>
@ -51,6 +52,7 @@ const DetailLayout = memo<DetailLayoutProps>(
{sidebar} {sidebar}
</SidebarContainer> </SidebarContainer>
</Flexbox> </Flexbox>
</div>
</> </>
); );
}, },

@ -8,7 +8,7 @@ import { DiscoverService } from '@/server/services/discover';
import { translation } from '@/server/translation'; import { translation } from '@/server/translation';
import { AssistantCategory } from '@/types/discover'; import { AssistantCategory } from '@/types/discover';
import { isMobileDevice } from '@/utils/responsive'; import { isMobileDevice } from '@/utils/responsive';
import request from '@/app/api/request';
import List from '../features/List'; import List from '../features/List';
type Props = { params: { slug: AssistantCategory }; searchParams: { hl?: Locales } }; type Props = { params: { slug: AssistantCategory }; searchParams: { hl?: Locales } };
@ -30,14 +30,52 @@ const Page = async ({ params, searchParams }: Props) => {
const { t, locale } = await translation('metadata', searchParams?.hl); const { t, locale } = await translation('metadata', searchParams?.hl);
const { t: td } = await translation('discover', searchParams?.hl); const { t: td } = await translation('discover', searchParams?.hl);
const mobile = isMobileDevice(); const mobile = isMobileDevice();
const discoverService = new DiscoverService(); const discoverService = new DiscoverService();
const items = await discoverService.getAssistantCategory(locale, params.slug); console.log(params.slug,3333333)
let items;
if(params.slug == "collect") {
const res = await request({
url: "/flxai/api/robot/appaiassistant/getAllAiAssistant",
method: "get",
params: {
userid: searchParams.userid
}
})
items = res.data;
items = items.map((item,index)=> {
item.classify = 'collect';
return item
})
} else {
const res = await request({
url: "/flxai/api/robot/appaiassistant/getAllAiAssistant",
method: "get",
params: {
userid: searchParams.userid
}
})
const array2Object = {};
res?.data?.forEach(item => {
array2Object[item.identifier] = item;
});
items = await discoverService.getAssistantCategory(locale, params.slug);
items = items.map((item,index)=> {
const matchingItem = array2Object[item.identifier];
if (matchingItem) {
console.log('3838383838',matchingItem);
matchingItem.status = '1';
return matchingItem
} else {
item.status = '0';
return item
}
})
}
console.log(8272772727,items)
const ld = ldModule.generate({ const ld = ldModule.generate({
description: t('discover.assistants.description'), description: t('discover.assistants.description'),
title: [td(`category.assistant.${params.slug}`), t('discover.assistants.title')].join(' · '), title: [td(`category.assistant.${params.slug}`), t('discover.assistants.title')].join(' · '),
url: urlJoin('/discover/assistants', params.slug), url: urlJoin('/discover/assistants', params.slug + '?userid=' + searchParams.userid),
webpage: { webpage: {
enable: true, enable: true,
search: '/discover/search', search: '/discover/search',

@ -1,19 +1,18 @@
import { Avatar, Tag } from '@lobehub/ui'; import { Avatar, Tag } from '@lobehub/ui';
import { Skeleton, Typography } from 'antd'; import { Skeleton, Typography, App } from 'antd';
import { createStyles } from 'antd-style'; import { createStyles } from 'antd-style';
import { startCase } from 'lodash-es'; import { startCase } from 'lodash-es';
import dynamic from 'next/dynamic'; import dynamic from 'next/dynamic';
import qs from 'query-string'; import qs from 'query-string';
import { memo } from 'react'; import { memo, useState } from 'react';
import { Center, Flexbox, FlexboxProps } from 'react-layout-kit'; import { Center, Flexbox, FlexboxProps } from 'react-layout-kit';
import urlJoin from 'url-join'; import urlJoin from 'url-join';
import request from '@/app/api/request';
import { DiscoverAssistantItem } from '@/types/discover'; import { DiscoverAssistantItem } from '@/types/discover';
import CardBanner from '../../../components/CardBanner'; import CardBanner from '../../../components/CardBanner';
import GitHubAvatar from '../../../components/GitHubAvatar'; import GitHubAvatar from '../../../components/GitHubAvatar';
import { useCategoryItem } from '../../assistants/features/useCategory'; import { useCategoryItem } from '../../assistants/features/useCategory';
import { StarOutlined } from '@ant-design/icons';
const Link = dynamic(() => import('next/link'), { const Link = dynamic(() => import('next/link'), {
loading: () => <Skeleton.Button size={'small'} style={{ height: 22 }} />, loading: () => <Skeleton.Button size={'small'} style={{ height: 22 }} />,
ssr: false, ssr: false,
@ -59,8 +58,16 @@ const useStyles = createStyles(({ css, token, isDarkMode }) => ({
margin-block-end: 0 !important; margin-block-end: 0 !important;
font-weight: bold; font-weight: bold;
`, `,
collectBtn: css`
font-size: 12px;
width: 20px;
height: 20px;
line-height: 20px;
border-radius: 50%;
background: #FFF3D9;
text-align: center;
`,
})); }));
export interface AssistantCardProps export interface AssistantCardProps
extends Omit<DiscoverAssistantItem, 'suggestions' | 'socialData' | 'config'>, extends Omit<DiscoverAssistantItem, 'suggestions' | 'socialData' | 'config'>,
Omit<FlexboxProps, 'children'> { Omit<FlexboxProps, 'children'> {
@ -69,13 +76,20 @@ export interface AssistantCardProps
} }
const AssistantCard = memo<AssistantCardProps>( const AssistantCard = memo<AssistantCardProps>(
({ showCategory, className, meta, createdAt, author, variant, ...rest }) => { ({ showCategory, className, meta, createdAt, author, variant, ...rest }) => {
const { avatar, title, description, tags = [], category } = meta; const { avatar, title, description, tags = [], category } = meta;
const { createAt,homepage,identifier,schemaVersion,status,classify } = {...rest}
const { cx, styles, theme } = useStyles(); const { cx, styles, theme } = useStyles();
const { message } = App.useApp();
const categoryItem = useCategoryItem(category, 12); const categoryItem = useCategoryItem(category, 12);
const isCompact = variant === 'compact'; const isCompact = variant === 'compact';
const { createAt,homepage,identifier,schemaVersion } = {...rest} // console.log(tags,avatar,author,9383737)
console.log(tags,avatar,author,9383737) console.log(status,9999999999)
const [val, setVal] = useState(status)
const handleCollect = (e) => {
console.log(e,8844848)
e.preventDefault()
e.stopPropagation()
const params = { const params = {
"author": author, "author": author,
"createAt": createAt, "createAt": createAt,
@ -87,19 +101,22 @@ const AssistantCard = memo<AssistantCardProps>(
"tags": tags.join(','), "tags": tags.join(','),
"title": title, "title": title,
"category": category, "category": category,
"schemaVersion": schemaVersion "schemaVersion": schemaVersion,
"userid": localStorage.getItem('userId'),
} }
console.log(params,68686868) request({
const handleCollect = () => { url: "/flxai/api/robot/appaiassistant",
axios.post('https://api.example.com/data',params) method: "post",
.then(response => { data: params
// 请求成功后的处理 }).then(response => {
console.log(response.data); console.log(response,222222222)
if (response.code == 0) {
message.success('收藏成功')
setVal("1")
}
}).catch(error => {
console.error('Error fetching data: ', error);
}) })
.catch(error => {
// 请求失败后的处理
console.error('Error posting data:', error);
});
} }
const user = ( const user = (
<Flexbox <Flexbox
@ -112,7 +129,17 @@ const AssistantCard = memo<AssistantCardProps>(
<span>{author}</span> <span>{author}</span>
</Flexbox> </Flexbox>
); );
const renderElement = () => {
if (classify != 'collect') {
if(val == "1") {
return <div className={styles.collectBtn} onClick={(e) => {e.stopPropagation()}}><StarOutlined style={{color: '#FFAD01'}}/></div>
} else {
return <div className={styles.collectBtn} style={{background: '#F1F1F1'}} onClick={(e) => handleCollect(e)}><StarOutlined style={{color: '#D6D6D6'}}/></div>
}
} else {
return;
}
};
return ( return (
<Flexbox className={cx(styles.container, className)} gap={24} {...rest}> <Flexbox className={cx(styles.container, className)} gap={24} {...rest}>
{!isCompact && <CardBanner avatar={avatar} />} {!isCompact && <CardBanner avatar={avatar} />}
@ -170,13 +197,11 @@ const AssistantCard = memo<AssistantCardProps>(
{description} {description}
</Paragraph> </Paragraph>
<Flexbox gap={6} horizontal style={{ flexWrap: 'wrap',justifyContent: 'space-between' }}> <Flexbox gap={6} horizontal style={{ flexWrap: 'wrap',justifyContent: 'space-between' }}>
<div> <div onClick={(e) => {e.stopPropagation()}} style={{width: '85%'}}>
{showCategory && categoryItem ? ( {showCategory && categoryItem ? (
<Link href={urlJoin('/discover/assistants', categoryItem.key)}> <Tag icon={categoryItem.icon} style={{ margin: '0 5' }}>
<Tag icon={categoryItem.icon} style={{ margin: 0 }}>
{categoryItem.label} {categoryItem.label}
</Tag> </Tag>
</Link>
) : ( ) : (
tags tags
.slice(0, 4) .slice(0, 4)
@ -187,14 +212,12 @@ const AssistantCard = memo<AssistantCardProps>(
url: '/discover/search', url: '/discover/search',
}); });
return ( return (
<Link href={url} key={index}> <Tag style={{ margin: '0 5' }}>{startCase(tag).trim()}</Tag>
<Tag style={{ margin: 0 }}>{startCase(tag).trim()}</Tag>
</Link>
); );
}) })
)} )}
</div> </div>
<div style={{ fontSize: 12 }} onClick={() => handleCollect()}></div> {renderElement()}
</Flexbox> </Flexbox>
</Flexbox> </Flexbox>
</Flexbox> </Flexbox>

@ -30,7 +30,7 @@ const Category = memo(() => {
<Link <Link
href={urlJoin( href={urlJoin(
'/discover/assistants', '/discover/assistants',
item.key === AssistantCategory.All ? '' : item.key, item.key === AssistantCategory.All ? '' : item.key + '?userid=' + localStorage.getItem('userId'),
)} )}
> >
{item.label} {item.label}
@ -38,7 +38,7 @@ const Category = memo(() => {
), ),
}))} }))}
onSelect={({ key }) => { onSelect={({ key }) => {
router.push(urlJoin('/discover/assistants', key === AssistantCategory.All ? '' : key)); router.push(urlJoin('/discover/assistants', key === AssistantCategory.All ? '' : key + '?userid=' + localStorage.getItem('userId')));
}} }}
selectedKeys={[selectedKey || 'all']} selectedKeys={[selectedKey || 'all']}
/> />

@ -6,7 +6,7 @@ import Link from 'next/link';
import {memo, useMemo, useState} from 'react'; import {memo, useMemo, useState} from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import urlJoin from 'url-join'; import urlJoin from 'url-join';
import { useRouter } from 'next/navigation';
import { DiscoverAssistantItem } from '@/types/discover'; import { DiscoverAssistantItem } from '@/types/discover';
import SearchResultCount from '../../../components/SearchResultCount'; import SearchResultCount from '../../../components/SearchResultCount';
@ -127,7 +127,7 @@ const useStyles = createStyles(({css, token}) => ({
const List = memo<ListProps>(({ category, mobile, searchKeywords, items = [] }) => { const List = memo<ListProps>(({ category, mobile, searchKeywords, items = [] }) => {
const { t } = useTranslation('discover'); const { t } = useTranslation('discover');
const { styles, cx } = useStyles() const { styles, cx } = useStyles()
const router = useRouter()
const { all, recent, last } = useMemo(() => { const { all, recent, last } = useMemo(() => {
const recentLength = mobile ? 4 : 8; const recentLength = mobile ? 4 : 8;
return { return {
@ -136,12 +136,13 @@ const List = memo<ListProps>(({ category, mobile, searchKeywords, items = [] })
recent: items.slice(0, recentLength), recent: items.slice(0, recentLength),
}; };
}, [items, mobile]); }, [items, mobile]);
console.log(recent,last,92929292) console.log(category,recent,last,92929292)
const [val, setVal] = useState("") const [val, setVal] = useState("")
const handleClickCard = (item) => { const handleClickCard = (item) => {
console.log(item) console.log(item)
setVal(item) setVal(item)
router.push(urlJoin('/discover/assistant/', item.identifier))
} }
const handleBack = () => { const handleBack = () => {
@ -157,9 +158,9 @@ const List = memo<ListProps>(({ category, mobile, searchKeywords, items = [] })
data={all} data={all}
initialItemCount={24} initialItemCount={24}
itemContent={(_, item) => ( itemContent={(_, item) => (
<Link href={urlJoin('/discover/assistant/', item.identifier)} key={item.identifier}> // <Link href={urlJoin('/discover/assistant/', item.identifier)} key={item.identifier}>
<Card showCategory variant={'compact'} {...item} /> <Card onClick={() => handleClickCard(item)} showCategory variant={'compact'} {...item} />
</Link> // </Link>
)} )}
style={{ style={{
minHeight: '75vh', minHeight: '75vh',
@ -170,13 +171,26 @@ const List = memo<ListProps>(({ category, mobile, searchKeywords, items = [] })
} }
return ( return (
<>
{category == "collect"?(
<>
<Title tag={all.length}></Title>
<Grid maxItemWidth={280} rows={4}>
{all.map((item) => (
// <Link href={urlJoin('/discover/assistant/', item.identifier)} key={item.identifier}>
<Card onClick={() => handleClickCard(item)} showCategory={!category} {...item} />
// </Link>
))}
</Grid>
</>
):(
<> <>
<Title tag={recent.length}>{t('assistants.recentSubmits')}</Title> <Title tag={recent.length}>{t('assistants.recentSubmits')}</Title>
<Grid maxItemWidth={280} rows={4}> <Grid maxItemWidth={280} rows={4}>
{recent.map((item) => ( {recent.map((item) => (
<Link href={urlJoin('/discover/assistant/', item.identifier)} key={item.identifier}> // <Link href={urlJoin('/discover/assistant/', item.identifier)} key={item.identifier}>
<Card onClick={() => handleClickCard(item)} showCategory={!category} {...item} /> <Card onClick={() => handleClickCard(item)} showCategory={!category} {...item} />
</Link> // </Link>
))} ))}
</Grid> </Grid>
{last && last?.length > 0 && ( {last && last?.length > 0 && (
@ -186,9 +200,7 @@ const List = memo<ListProps>(({ category, mobile, searchKeywords, items = [] })
data={last} data={last}
initialItemCount={12} initialItemCount={12}
itemContent={(_, item) => ( itemContent={(_, item) => (
<Link href={urlJoin('/discover/assistant/', item.identifier)} key={item.identifier}>
<Card onClick={() => handleClickCard(item)} showCategory={!category} variant={'compact'} {...item} /> <Card onClick={() => handleClickCard(item)} showCategory={!category} variant={'compact'} {...item} />
</Link>
)} )}
style={{ style={{
minHeight: '75vh', minHeight: '75vh',
@ -198,6 +210,8 @@ const List = memo<ListProps>(({ category, mobile, searchKeywords, items = [] })
</> </>
)} )}
</> </>
)}
</>
); );
}); });

@ -16,6 +16,7 @@ import {
PencilIcon, PencilIcon,
PrinterIcon, PrinterIcon,
TerminalSquareIcon, TerminalSquareIcon,
Star,
} from 'lucide-react'; } from 'lucide-react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
@ -37,7 +38,7 @@ export const useCategory = (fontsize?: number) => {
label: t('category.assistant.all'), label: t('category.assistant.all'),
}, },
{ {
icon: <Icon color="#FFAD01" icon={MicroscopeIcon} size={size} />, icon: <Icon color="#FFAD01" icon={Star} size={size} />,
key: AssistantCategory.Collect, key: AssistantCategory.Collect,
label: t('category.assistant.collect'), label: t('category.assistant.collect'),
}, },

@ -5,13 +5,14 @@ import { metadataModule } from '@/server/metadata';
import { DiscoverService } from '@/server/services/discover'; import { DiscoverService } from '@/server/services/discover';
import { translation } from '@/server/translation'; import { translation } from '@/server/translation';
import { isMobileDevice } from '@/utils/responsive'; import { isMobileDevice } from '@/utils/responsive';
import request from '@/app/api/request';
import List from './features/List'; import List from './features/List';
import urlJoin from 'url-join';
type Props = { searchParams: { hl?: Locales } }; type Props = { searchParams: { hl?: Locales } };
export const generateMetadata = async ({ searchParams }: Props) => { export const generateMetadata = async ({ searchParams }: Props) => {
const { t, locale } = await translation('metadata', searchParams?.hl); const { t, locale } = await translation('metadata', searchParams?.hl);
console.log(searchParams,'jiangxucong74774747')
return metadataModule.generate({ return metadataModule.generate({
alternate: true, alternate: true,
description: t('discover.assistants.description'), description: t('discover.assistants.description'),
@ -24,14 +25,37 @@ export const generateMetadata = async ({ searchParams }: Props) => {
const Page = async ({ searchParams }: Props) => { const Page = async ({ searchParams }: Props) => {
const { t, locale } = await translation('metadata', searchParams?.hl); const { t, locale } = await translation('metadata', searchParams?.hl);
const mobile = isMobileDevice(); const mobile = isMobileDevice();
const discoverService = new DiscoverService(); const discoverService = new DiscoverService();
const items = await discoverService.getAssistantList(locale); console.log(searchParams,22222222222)
console.log(items,8272772727) const res = await request({
url: "/flxai/api/robot/appaiassistant/getAllAiAssistant",
method: "get",
params: {
userid: searchParams.userid
}
})
console.log(res,4322222)
const array2Object = {};
res?.data?.forEach(item => {
array2Object[item.identifier] = item;
});
let items = await discoverService.getAssistantList(locale);
console.log(8272772727,'jiangxucong')
items = items.map((item,index)=> {
const matchingItem = array2Object[item.identifier];
if (matchingItem) {
console.log('5959595959',matchingItem);
matchingItem.status = '1';
return matchingItem
} else {
item.status = '0';
return item
}
})
const ld = ldModule.generate({ const ld = ldModule.generate({
description: t('discover.assistants.description'), description: t('discover.assistants.description'),
title: t('discover.assistants.title'), title: t('discover.assistants.title'),
url: '/discover/assistants', url: urlJoin('/discover/assistants?userid=',searchParams.userid),
webpage: { webpage: {
enable: true, enable: true,
search: '/discover/search', search: '/discover/search',

@ -10,6 +10,7 @@ import {
ScanSearch, ScanSearch,
TwitterIcon, TwitterIcon,
Umbrella, Umbrella,
Star
} from 'lucide-react'; } from 'lucide-react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
@ -26,10 +27,15 @@ export const useCategory = (fontsize?: number) => {
return [ return [
{ {
icon: <Icon color={theme.colorTextSecondary} icon={LayoutPanelTop} size={size} />, icon: <Icon color="#003BFF" icon={LayoutPanelTop} size={size} />,
key: PluginCategory.All, key: PluginCategory.All,
label: t('category.plugin.all'), label: t('category.plugin.all'),
}, },
{
icon: <Icon color="#FFAD01" icon={Star} size={size} />,
key: PluginCategory.Collect,
label: t('category.plugin.collect'),
},
{ {
icon: <Icon color={theme.colorTextSecondary} icon={ImagePlay} size={size} />, icon: <Icon color={theme.colorTextSecondary} icon={ImagePlay} size={size} />,
key: PluginCategory.MediaGenerate, key: PluginCategory.MediaGenerate,

@ -3,24 +3,84 @@
import { ChatHeader } from '@lobehub/ui'; import { ChatHeader } from '@lobehub/ui';
import Link from 'next/link'; import Link from 'next/link';
import { memo } from 'react'; import { memo } from 'react';
import {createStyles, useTheme} from 'antd-style';
import { ProductLogo } from '@/components/Branding'; import { ProductLogo } from '@/components/Branding';
import { Divider, Avatar } from "antd";
import { UserOutlined, SearchOutlined } from '@ant-design/icons';
import CreateButton from '../../features/CreateButton'; import CreateButton from '../../features/CreateButton';
import StoreSearchBar from '../../features/StoreSearchBar'; import StoreSearchBar from '../../features/StoreSearchBar';
const useStyles = createStyles(({ css, token }) => ({
topCenten: css`
width: 100%;
background: #FFFFFF;
box-sizing: border-box;
/* 分割线颜色 */
border-width: 0px 0px 2px 0px;
border-style: solid;
border-color: rgba(187, 204, 253, 0.24);
`,
leftTitle: css`
font-size: 20px;
color: #3d3d3d;
display: inline-block
`,
dividerCen: css`
width: 1px;
height: 26px;
background-color: #d8d8d8;
margin: 8px 16px;
`,
ledDiv: css `
line-height: 52px;
display: inline-block;
`,
nameSpn: css`
margin-left: 8px;
display: inline-block;
`,
serchIcon: css`
color: #BCCEFF;
font-size: 24px;
`,
inp: css`
width: 283px;
margin-right: 43px;
background: #F3F6FF;
&:hover, &:active, &:focus {
border-color: transparent !important;
background: #F3F6FF !important;
}
`,
}))
const title = {
"/chat": '会话',
"/discover/assistants": "助手",
"/files": "工具",
"/model": "模型",
"/robot": "数字人",
"/plugins": "插件",
"/power": "算力",
"/knowledge": "知识库"
}
const Header = memo(() => { const Header = memo(() => {
const { styles, cx } = useStyles()
return ( return (
true ? <></> : <ChatHeader <ChatHeader
left={ left={
<Link href={'/discover'} style={{ color: 'inherit' }}> <div className={cx(styles.ledDiv)}>
<ProductLogo extra={'Discover'} size={36} type={'text'} /> <span className={cx(styles.leftTitle)}>AI</span>
</Link> <Divider className={cx(styles.dividerCen)} type="vertical" />
<span className={cx(styles.leftTitle)}>{title[window?.location?.pathname]}</span>
</div>
} }
right={<CreateButton />} right={<>
<Avatar style={{ backgroundColor: '#90ACFF' }} icon={<UserOutlined />} />
<span className={cx(styles.nameSpn)}></span>
</>}
style={{ style={{
position: 'relative', position: 'relative',
zIndex: 10, zIndex: 10,
background: '#fff',
}} }}
styles={{ styles={{
center: { flex: 1, maxWidth: 1440 }, center: { flex: 1, maxWidth: 1440 },

@ -45,11 +45,11 @@ const StoreSearchBar = memo<StoreSearchBarProps>(({ mobile, onBlur, onFocus, ...
useEffect(() => { useEffect(() => {
if (!pathname.includes('/discover/search')) return; if (!pathname.includes('/discover/search')) return;
// 使用 useQueryState 时,当 handleSearch 为空时无法回跳 // 使用 useQueryState 时,当 handleSearch 为空时无法回跳
if (!q) router.push(urlJoin('/discover', activeType), { query: {}, replace: true }); if (!q) router.push(urlJoin('/discover', activeType), { query: { userid: localStorage.getItem('userId') }, replace: true });
}, [q, pathname, activeType]); }, [q, pathname, activeType]);
const handleSearch = (value: string) => { const handleSearch = (value: string) => {
router.push('/discover/search', { query: { q: value, type: activeType } }); router.push('/discover/search', { query: { q: value, type: activeType, userid: localStorage.getItem('userId') } });
}; };
return ( return (

@ -23,9 +23,6 @@ const Layout = async ({ children }: PropsWithChildren) => {
width={'100%'} width={'100%'}
> >
<Flexbox gap={24} horizontal style={{ position: 'relative' }} width={'100%'}> <Flexbox gap={24} horizontal style={{ position: 'relative' }} width={'100%'}>
<CategoryContainer top={32}>
<Category />
</CategoryContainer>
<Flexbox flex={1} gap={16}> <Flexbox flex={1} gap={16}>
{children} {children}
</Flexbox> </Flexbox>

@ -1,24 +1,48 @@
import { Locales } from '@/locales/resources'; import { Locales } from '@/locales/resources';
import { DiscoverService } from '@/server/services/discover'; import { DiscoverService } from '@/server/services/discover';
import request from '@/app/api/request';
import Back from '../../(detail)/features/Back'; import Back from '../../(detail)/features/Back';
import List from '../../(list)/assistants/features/List'; import List from '../../(list)/assistants/features/List';
const AssistantsResult = async ({ const AssistantsResult = async ({
locale, locale,
q, q,
userid,
mobile, mobile,
}: { }: {
locale: Locales; locale: Locales;
mobile?: boolean; mobile?: boolean;
q: string; q: string;
userid: string;
}) => { }) => {
const res = await request({
url: "/flxai/api/robot/appaiassistant/getAllAiAssistant",
method: "get",
params: {
userid: userid
}
})
const array2Object = {};
res?.data?.forEach(item => {
array2Object[item.identifier] = item;
});
const discoverService = new DiscoverService(); const discoverService = new DiscoverService();
const items = await discoverService.searchAssistant(locale, q); let items = await discoverService.searchAssistant(locale, q);
items = items.map((item,index)=> {
const matchingItem = array2Object[item.identifier];
if (matchingItem) {
matchingItem.status = '1';
return matchingItem
} else {
item.status = '0';
return item
}
})
console.log(locale,q,userid,'383737363636363')
const backUrl = '/discover/assistants?userid=' + userid
return ( return (
<> <>
{!mobile && <Back href={'/discover/assistants'} style={{ marginBottom: 0 }} />} {!mobile && <Back href={backUrl} style={{ marginBottom: 0 }} />}
<List items={items} mobile={mobile} searchKeywords={q} /> <List items={items} mobile={mobile} searchKeywords={q} />
</> </>
); );

@ -45,7 +45,7 @@ export const generateMetadata = async ({ searchParams }: Props) => {
}; };
const Page = async ({ searchParams }: Props) => { const Page = async ({ searchParams }: Props) => {
const { q, type = 'assistants' } = searchParams; const { q, type = 'assistants',userid } = searchParams;
if (!q) redirect(urlJoin(`/discover`, type)); if (!q) redirect(urlJoin(`/discover`, type));
const keywords = decodeURIComponent(q); const keywords = decodeURIComponent(q);
@ -65,7 +65,7 @@ const Page = async ({ searchParams }: Props) => {
return ( return (
<> <>
<StructuredData ld={ld} /> <StructuredData ld={ld} />
{type === 'assistants' && <AssistantsResult locale={locale} mobile={mobile} q={keywords} />} {type === 'assistants' && <AssistantsResult locale={locale} mobile={mobile} q={keywords} userid={userid} />}
{type === 'plugins' && <PluginsResult locale={locale} mobile={mobile} q={keywords} />} {type === 'plugins' && <PluginsResult locale={locale} mobile={mobile} q={keywords} />}
{type === 'models' && <ModelsResult locale={locale} mobile={mobile} q={keywords} />} {type === 'models' && <ModelsResult locale={locale} mobile={mobile} q={keywords} />}
{type === 'providers' && <ProvidersResult locale={locale} mobile={mobile} q={keywords} />} {type === 'providers' && <ProvidersResult locale={locale} mobile={mobile} q={keywords} />}

File diff suppressed because it is too large Load Diff

@ -0,0 +1,93 @@
import axios from 'axios';
// 创建axios实例
const service = axios.create({
baseURL: `http://192.168.7.3:18080`, // 设置基础URL
timeout: 60000 // 设置请求超时时间
});
// 请求拦截器
service.interceptors.request.use(
(config) => {
// 在发送请求之前做些什么例如添加token到headers
// config.headers['Authorization'] = 'Bearer ' + token;
return config;
},
(error) => {
// 对请求错误做些什么
console.log(error); // for debug
return Promise.reject(error);
}
);
// 响应拦截器
service.interceptors.response.use(
(response) => {
// 对响应数据做点什么,例如根据状态码判断成功或失败
const res = response.data;
if (response.status === 200) {
return res;
} else {
return Promise.reject(res);
}
},
(error) => {
// 对响应错误做点什么
/***** 接收到异常响应的处理开始 *****/
if (error && error.response) {
// 1.公共错误处理
// 2.根据响应码具体处理
switch (error.response.status) {
case 400:
error.message = "错误请求";
break;
case 401:
error.message = "错误请求";
break;
case 423:
// token刷新失效
error.message = error.response.data + "请重新登录";
break;
case 403:
error.message = "拒绝访问";
break;
case 404:
error.message = "请求错误,未找到该资源";
break;
case 405:
error.message = "请求方法未允许";
break;
case 408:
error.message = "请求超时";
break;
case 500:
error.message = "服务器端出错";
break;
case 501:
error.message = "网络未实现";
break;
case 502:
error.message = "网络错误";
break;
case 503:
error.message = "服务不可用";
break;
case 504:
error.message = "网络超时";
break;
case 505:
error.message = "http版本不支持该请求";
break;
default:
error.message = `连接错误${error.response.status}`;
}
} else {
error.message = "连接服务器失败";
}
/***** 处理结束 *****/
//如果不需要错误处理,以上的处理过程都可省略
return Promise.reject(error.response);
}
);
export default service;

@ -21,20 +21,21 @@ export default {
back: '返回发现', back: '返回发现',
category: { category: {
assistant: { assistant: {
all: "全部", 'all': "全部",
collect: "收藏", 'collect': "收藏",
academic: "政务", 'academic': "政务",
education: "教育", 'education': "教育",
marketing: "营销", 'marketing': "营销",
design: "设计", 'design': "设计",
office: "办公", 'office': "办公",
programming: "编程", 'programming': "编程",
entertainment: "娱乐", 'entertainment': "娱乐",
life: "生活", 'life': "生活",
general: "通用" 'general': "通用"
}, },
plugin: { plugin: {
'all': '全部', 'all': '全部',
'collect': "收藏",
'gaming-entertainment': '游戏娱乐', 'gaming-entertainment': '游戏娱乐',
'life-style': '生活方式', 'life-style': '生活方式',
'media-generate': '媒体生成', 'media-generate': '媒体生成',

@ -13,11 +13,12 @@ export class AssistantStore {
getAgentIndexUrl = (lang: Locales = DEFAULT_LANG) => { getAgentIndexUrl = (lang: Locales = DEFAULT_LANG) => {
if (isLocaleNotSupport(lang)) return this.baseUrl; if (isLocaleNotSupport(lang)) return this.baseUrl;
console.log(urlJoin(this.baseUrl, `index.${normalizeLocale(lang)}.json`),928272772727)
return urlJoin(this.baseUrl, `index.${normalizeLocale(lang)}.json`); return urlJoin(this.baseUrl, `index.${normalizeLocale(lang)}.json`);
}; };
getAgentUrl = (identifier: string, lang: Locales = DEFAULT_LANG) => { getAgentUrl = (identifier: string, lang: Locales = DEFAULT_LANG) => {
console.log(urlJoin(this.baseUrl, `${identifier}.json`),88888888888888888888)
if (isLocaleNotSupport(lang)) return urlJoin(this.baseUrl, `${identifier}.json`); if (isLocaleNotSupport(lang)) return urlJoin(this.baseUrl, `${identifier}.json`);
return urlJoin(this.baseUrl, `${identifier}.${normalizeLocale(lang)}.json`); return urlJoin(this.baseUrl, `${identifier}.${normalizeLocale(lang)}.json`);

@ -53,7 +53,7 @@ export class DiscoverService {
let res = await fetch(this.assistantStore.getAgentIndexUrl(locale), { let res = await fetch(this.assistantStore.getAgentIndexUrl(locale), {
next: { revalidate }, next: { revalidate },
}); });
console.log(res.ok,29298811)
if (!res.ok) { if (!res.ok) {
res = await fetch(this.assistantStore.getAgentIndexUrl(DEFAULT_LANG), { res = await fetch(this.assistantStore.getAgentIndexUrl(DEFAULT_LANG), {
next: { revalidate }, next: { revalidate },
@ -84,7 +84,7 @@ export class DiscoverService {
if (!res.ok) return; if (!res.ok) return;
let assistant = await res.json(); let assistant = await res.json();
console.log(assistant,6868686866868)
if (!assistant) return; if (!assistant) return;
assistant = merge(cloneDeep(DEFAULT_DISCOVER_ASSISTANT_ITEM), assistant); assistant = merge(cloneDeep(DEFAULT_DISCOVER_ASSISTANT_ITEM), assistant);

@ -20,7 +20,8 @@ export class ClientService implements IUserService {
const user = await UserModel.getUser(); const user = await UserModel.getUser();
const messageCount = await MessageModel.count(); const messageCount = await MessageModel.count();
const sessionCount = await SessionModel.count(); const sessionCount = await SessionModel.count();
console.log(user,2827272727)
localStorage.setItem('userId',user.uuid)
return { return {
avatar: user.avatar, avatar: user.avatar,
canEnablePWAGuide: messageCount >= 4, canEnablePWAGuide: messageCount >= 4,

@ -26,6 +26,7 @@ export enum AssistantCategory {
export enum PluginCategory { export enum PluginCategory {
All = 'all', All = 'all',
Collect = 'collect',
GamingEntertainment = 'gaming-entertainment', GamingEntertainment = 'gaming-entertainment',
LifeStyle = 'lifestyle', LifeStyle = 'lifestyle',
MediaGenerate = 'media-generate', MediaGenerate = 'media-generate',

Loading…
Cancel
Save