diff --git a/src/app/(main)/profile/stats/Client.tsx b/src/app/(main)/profile/stats/Client.tsx
index 850faf15eee08..925a8268cfd6e 100644
--- a/src/app/(main)/profile/stats/Client.tsx
+++ b/src/app/(main)/profile/stats/Client.tsx
@@ -14,7 +14,7 @@ import TotalAssistants from './features/TotalAssistants';
import TotalMessages from './features/TotalMessages';
import TotalTopics from './features/TotalTopics';
-const Client = memo<{ mobile?: boolean }>(() => {
+const Client = memo<{ mobile?: boolean }>(({ mobile }) => {
const { t } = useTranslation('auth');
return (
@@ -26,7 +26,7 @@ const Client = memo<{ mobile?: boolean }>(() => {
-
+
{
- const { t } = useTranslation('auth');
+ const { t } = useTranslation(['auth', 'chat']);
+ const theme = useTheme();
+ const router = useRouter();
+ const { data, isLoading } = useClientDataSWR('rank-sessions', async () =>
+ sessionService.rankSessions(),
+ );
+
return (
{
+ const link = qs.stringifyUrl({
+ query: {
+ session: item.id,
+ },
+ url: '/chat',
+ });
+ return {
+ icon: (
+
+ ),
+ link,
+ name: (
+
+ {item.title || t('defaultAgent', { ns: 'chat' })}
+
+ ),
+ value: item.count,
+ };
+ }) || []
+ }
+ height={420}
leftLabel={t('stats.assistantsRank.left')}
+ loading={isLoading}
+ onValueChange={(item) => router.push(item.link)}
rightLabel={t('stats.assistantsRank.right')}
/>
);
diff --git a/src/app/(main)/profile/stats/features/TopicsRank.tsx b/src/app/(main)/profile/stats/features/TopicsRank.tsx
index f0edfea094e98..ad9300151e2c5 100644
--- a/src/app/(main)/profile/stats/features/TopicsRank.tsx
+++ b/src/app/(main)/profile/stats/features/TopicsRank.tsx
@@ -1,13 +1,57 @@
import { BarList } from '@lobehub/charts';
+import { Icon } from '@lobehub/ui';
+import { useTheme } from 'antd-style';
+import { MessageSquareIcon } from 'lucide-react';
+import Link from 'next/link';
+import { useRouter } from 'next/navigation';
+import qs from 'query-string';
import { memo } from 'react';
import { useTranslation } from 'react-i18next';
+import { useClientDataSWR } from '@/libs/swr';
+import { topicService } from '@/services/topic';
+
export const TopicsRank = memo(() => {
const { t } = useTranslation('auth');
+ const theme = useTheme();
+ const router = useRouter();
+ const { data, isLoading } = useClientDataSWR('rank-topics', async () =>
+ topicService.rankTopics(),
+ );
+
return (
{
+ const link = qs.stringifyUrl({
+ query: {
+ session: item.sessionId,
+ topic: item.id,
+ },
+ url: '/chat',
+ });
+ return {
+ icon: (
+
+ ),
+ link,
+ name: (
+
+ {item.title}
+
+ ),
+ value: item.count,
+ };
+ }) || []
+ }
+ height={420}
leftLabel={t('stats.topicsRank.left')}
+ loading={isLoading}
+ onValueChange={(item) => router.push(item.link)}
rightLabel={t('stats.topicsRank.right')}
/>
);
diff --git a/src/app/(main)/profile/stats/page.tsx b/src/app/(main)/profile/stats/page.tsx
index 2789ff7f10e8f..9f143ce4739c7 100644
--- a/src/app/(main)/profile/stats/page.tsx
+++ b/src/app/(main)/profile/stats/page.tsx
@@ -1,5 +1,6 @@
import { metadataModule } from '@/server/metadata';
import { translation } from '@/server/translation';
+import { isMobileDevice } from '@/utils/server/responsive';
import Client from './Client';
@@ -13,7 +14,8 @@ export const generateMetadata = async () => {
};
const Page = async () => {
- return ;
+ const mobile = await isMobileDevice();
+ return ;
};
export default Page;
diff --git a/src/database/server/models/session.ts b/src/database/server/models/session.ts
index 47d803d87dd38..1aa90bca5f97e 100644
--- a/src/database/server/models/session.ts
+++ b/src/database/server/models/session.ts
@@ -25,6 +25,7 @@ import {
agentsToSessions,
sessionGroups,
sessions,
+ topics,
} from '../../schemas';
export class SessionModel {
@@ -118,7 +119,31 @@ export class SessionModel {
return result[0].count;
};
- rank = async () => {};
+ rank = async (): Promise<
+ {
+ avatar: string | null;
+ backgroundColor: string | null;
+ count: number;
+ id: string;
+ title: string | null;
+ }[]
+ > => {
+ return this.db
+ .select({
+ avatar: agents.avatar,
+ backgroundColor: agents.backgroundColor,
+ count: count(topics.id).as('count'),
+ id: sessions.id,
+ title: agents.title,
+ })
+ .from(sessions)
+ .leftJoin(topics, eq(sessions.id, topics.sessionId))
+ .leftJoin(agentsToSessions, eq(sessions.id, agentsToSessions.sessionId))
+ .leftJoin(agents, eq(agentsToSessions.agentId, agents.id))
+ .groupBy(sessions.id, agentsToSessions.agentId, agents.id)
+ .orderBy(desc(sql`count`))
+ .limit(10);
+ };
hasMoreThanN = async (n: number): Promise => {
const result = await this.db
diff --git a/src/database/server/models/topic.ts b/src/database/server/models/topic.ts
index c29649472eb5a..7fb82aa6a6f9f 100644
--- a/src/database/server/models/topic.ts
+++ b/src/database/server/models/topic.ts
@@ -126,7 +126,27 @@ export class TopicModel {
return result[0].count;
};
- rank = async () => {};
+ rank = async (): Promise<
+ {
+ count: number;
+ id: string;
+ sessionId: string | null;
+ title: string | null;
+ }[]
+ > => {
+ return this.db
+ .select({
+ count: count(messages.id).as('count'),
+ id: topics.id,
+ sessionId: topics.sessionId,
+ title: topics.title,
+ })
+ .from(topics)
+ .leftJoin(messages, eq(topics.id, messages.topicId))
+ .groupBy(topics.id)
+ .orderBy(desc(sql`count`))
+ .limit(10);
+ };
// **************** Create *************** //
diff --git a/src/locales/default/auth.ts b/src/locales/default/auth.ts
index a4c96cafb58d7..bbe7df4b05092 100644
--- a/src/locales/default/auth.ts
+++ b/src/locales/default/auth.ts
@@ -20,7 +20,7 @@ export default {
assistants: '助手数',
assistantsRank: {
left: '助手名称',
- right: '消息数',
+ right: '话题数',
title: '助手使用率',
},
heatmaps: {
diff --git a/src/services/session/_deprecated.ts b/src/services/session/_deprecated.ts
index db8b0d6ebe996..09d7cf55d903f 100644
--- a/src/services/session/_deprecated.ts
+++ b/src/services/session/_deprecated.ts
@@ -82,6 +82,11 @@ export class ClientService implements ISessionService {
return SessionModel.count();
}
+ // @ts-ignore
+ async rankSessions() {
+ throw new Error('Method not implemented.');
+ }
+
async hasSessions() {
return (await this.countSessions()) !== 0;
}
diff --git a/src/services/session/type.ts b/src/services/session/type.ts
index be750c8506402..95025e360da66 100644
--- a/src/services/session/type.ts
+++ b/src/services/session/type.ts
@@ -31,7 +31,20 @@ export interface ISessionService {
* @deprecated
*/
getSessionsByType(type?: 'agent' | 'group' | 'all'): Promise;
- countSessions(): Promise;
+ countSessions(params?: {
+ endDate?: string;
+ range?: [string, string];
+ startDate?: string;
+ }): Promise;
+ rankSessions(): Promise<
+ {
+ avatar: string | null;
+ count: number;
+ id: string;
+ title: string | null;
+ backgroundColor: string | null;
+ }[]
+ >;
searchSessions(keyword: string): Promise;
updateSession(id: string, data: Partial): Promise;
diff --git a/src/services/topic/_deprecated.ts b/src/services/topic/_deprecated.ts
index eeb2ffa2e3951..bec802f2fb542 100644
--- a/src/services/topic/_deprecated.ts
+++ b/src/services/topic/_deprecated.ts
@@ -38,6 +38,11 @@ export class ClientService implements ITopicService {
return TopicModel.count();
}
+ // @ts-ignore
+ async rankTopics() {
+ throw new Error('Method not implemented.');
+ }
+
async updateTopicFavorite(id: string, favorite?: boolean) {
return this.updateTopic(id, { favorite });
}
diff --git a/src/services/topic/client.ts b/src/services/topic/client.ts
index 5429390694763..333720e9f7a6f 100644
--- a/src/services/topic/client.ts
+++ b/src/services/topic/client.ts
@@ -59,7 +59,14 @@ export class ClientService extends BaseClientService implements ITopicService {
return this.topicModel.count(params);
}
- async rankTopics() {
+ async rankTopics(): Promise<
+ {
+ count: number;
+ id: string;
+ sessionId: string | null;
+ title: string | null;
+ }[]
+ > {
return this.topicModel.rank();
}
diff --git a/src/services/topic/server.ts b/src/services/topic/server.ts
index c4cb0b96b87d9..a2a22f580cf7f 100644
--- a/src/services/topic/server.ts
+++ b/src/services/topic/server.ts
@@ -32,7 +32,14 @@ export class ServerService implements ITopicService {
return lambdaClient.topic.countTopics.query(params);
}
- rankTopics = async () => {
+ rankTopics = async (): Promise<
+ {
+ count: number;
+ id: string;
+ sessionId: string | null;
+ title: string | null;
+ }[]
+ > => {
return lambdaClient.topic.rankTopics.query();
}
diff --git a/src/services/topic/type.ts b/src/services/topic/type.ts
index a03bc2367316c..6bd7ab1b1cb49 100644
--- a/src/services/topic/type.ts
+++ b/src/services/topic/type.ts
@@ -23,6 +23,14 @@ export interface ITopicService {
getTopics(params: QueryTopicParams): Promise;
getAllTopics(): Promise;
countTopics(): Promise;
+ rankTopics(): Promise<
+ {
+ id: string;
+ title: string | null;
+ count: number;
+ sessionId: string | null;
+ }[]
+ >;
searchTopics(keyword: string, sessionId?: string): Promise;
updateTopic(id: string, data: Partial): Promise;