Skip to content

Commit b93f4a9

Browse files
authored
Merge pull request #86 from sdcb/dev
Dev
2 parents e876b0f + 19a6c21 commit b93f4a9

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

61 files changed

+5428
-2057
lines changed

src/BE/Chats.BE.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
<Nullable>enable</Nullable>
66
<ImplicitUsings>enable</ImplicitUsings>
77
<UserSecretsId>d4aa34e2-6c5f-41b9-b61b-c1a48b1d1b44</UserSecretsId>
8-
<Version>1.1.0</Version>
8+
<Version>1.2.0</Version>
99
</PropertyGroup>
1010

1111
<ItemGroup>

src/FE/apis/adminApis.ts

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ import { useFetch } from '@/hooks/useFetch';
33
import {
44
AdminChatsDto,
55
AdminModelDto,
6+
ChatCountStatisticsByDateResult,
7+
CostStatisticsByDateResult,
68
ErrorResult,
79
GetConfigsResult,
810
GetFileServicesResult,
@@ -37,12 +39,15 @@ import {
3739
PutUserModelParams,
3840
PutUserParams,
3941
SimpleModelReferenceDto,
42+
StatisticsTimeParams,
43+
TokenStatisticsByDateResult,
4044
UpdateModelDto,
4145
UserModelDisplay,
4246
UserModelDisplayDto,
4347
ValidateModelParams,
4448
} from '@/types/adminApis';
4549
import { GetChatShareResult, GetChatVersionResult } from '@/types/clientApis';
50+
import { IKeyCount } from '@/types/common';
4651
import { ChatModelFileConfig, DBModelProvider } from '@/types/model';
4752
import { PageResult } from '@/types/page';
4853

@@ -390,3 +395,87 @@ export const defaultFileConfig: ChatModelFileConfig = {
390395
count: 5,
391396
maxSize: 10240,
392397
};
398+
399+
export const getEnabledUserCount = () => {
400+
const fetchServer = useFetch();
401+
return fetchServer.get<number>('/api/admin/statistics/enabled-user-count');
402+
};
403+
404+
export const getEnabledModelCount = () => {
405+
const fetchServer = useFetch();
406+
return fetchServer.get<number>('/api/admin/statistics/enabled-model-count');
407+
};
408+
409+
export const getTokensDuring = (params: StatisticsTimeParams) => {
410+
const fetchServer = useFetch();
411+
return fetchServer.get<number>('/api/admin/statistics/tokens-during', {
412+
params: params,
413+
});
414+
};
415+
416+
export const getCostDuring = (params: StatisticsTimeParams) => {
417+
const fetchServer = useFetch();
418+
return fetchServer.get<number>('/api/admin/statistics/cost-during', {
419+
params: params,
420+
});
421+
};
422+
423+
export const getModelProviderStatistics = (params: StatisticsTimeParams) => {
424+
const fetchServer = useFetch();
425+
return fetchServer.get<object>(
426+
'/api/admin/statistics/model-provider-statistics',
427+
{
428+
params: params,
429+
},
430+
);
431+
};
432+
433+
export const getModelStatistics = (params: StatisticsTimeParams) => {
434+
const fetchServer = useFetch();
435+
return fetchServer.get<IKeyCount[]>(
436+
'/api/admin/statistics/model-statistics',
437+
{
438+
params: params,
439+
},
440+
);
441+
};
442+
443+
export const getModelKeyStatistics = (params: StatisticsTimeParams) => {
444+
const fetchServer = useFetch();
445+
return fetchServer.get<IKeyCount[]>(
446+
'/api/admin/statistics/model-key-statistics',
447+
{ params: params },
448+
);
449+
};
450+
451+
export const getSourceStatistics = (params: StatisticsTimeParams) => {
452+
const fetchServer = useFetch();
453+
return fetchServer.get<IKeyCount[]>(
454+
'/api/admin/statistics/source-statistics',
455+
{ params: params },
456+
);
457+
};
458+
459+
export const getTokenStatisticsByDate = (params: StatisticsTimeParams) => {
460+
const fetchServer = useFetch();
461+
return fetchServer.get<TokenStatisticsByDateResult[]>(
462+
'/api/admin/statistics/token-statistics-by-date',
463+
{ params: params },
464+
);
465+
};
466+
467+
export const getCostStatisticsByDate = (params: StatisticsTimeParams) => {
468+
const fetchServer = useFetch();
469+
return fetchServer.get<CostStatisticsByDateResult[]>(
470+
'/api/admin/statistics/cost-statistics-by-date',
471+
{ params: params },
472+
);
473+
};
474+
475+
export const getChatCountStatisticsByDate = (params: StatisticsTimeParams) => {
476+
const fetchServer = useFetch();
477+
return fetchServer.get<ChatCountStatisticsByDateResult[]>(
478+
'/api/admin/statistics/chat-count-by-date',
479+
{ params: params },
480+
);
481+
};

src/FE/apis/clientApis.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ import { IChatGroup } from '@/types/group';
4444
import { PageResult } from '@/types/page';
4545
import { Prompt, PromptSlim } from '@/types/prompt';
4646
import { SmsType } from '@/types/user';
47+
import { getTz } from '@/utils/date';
4748

4849
export const changeUserPassword = (params: PostUserPassword) => {
4950
const fetchService = useFetch();
@@ -122,7 +123,7 @@ export const getUserBalanceOnly = () => {
122123
export const getBalance7DaysUsage = () => {
123124
const fetchServer = useFetch();
124125
return fetchServer.get<GetBalance7DaysUsageResult[]>(
125-
`/api/user/7-days-usage?timezoneOffset=${new Date().getTimezoneOffset()}`,
126+
`/api/user/7-days-usage?timezoneOffset=${getTz()}`,
126127
);
127128
};
128129

src/FE/components/Button/ExportButtom.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ const ExportButton: React.FC<ExportProps> = ({
4444
};
4545

4646
return (
47-
<Button variant="outline" onClick={handleExport} className={className}>
47+
<Button variant="default" onClick={handleExport} className={className}>
4848
{buttonText || t('Export')}
4949
</Button>
5050
);

src/FE/components/ChatIcon/ChatIcon.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,12 @@ import { DBModelProvider, feModelProviders } from '@/types/model';
55
import { cn } from '@/lib/utils';
66

77
interface Props {
8-
providerId: DBModelProvider;
8+
providerId?: DBModelProvider;
99
className?: string;
1010
}
1111

1212
const ChatIcon = (props: Props) => {
13-
const { providerId, className } = props;
13+
const { providerId = DBModelProvider.Test, className } = props;
1414
const { t } = useTranslation();
1515

1616
if (providerId === undefined) return null;

src/FE/components/ChatMessage/ChangeModelAction.tsx

Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import Tips from '@/components/Tips/Tips';
88
interface Props {
99
models: AdminModelDto[];
1010
readonly?: boolean;
11+
hidden?: boolean;
1112
showRegenerate?: boolean;
1213
onChangeModel: (model: AdminModelDto) => void;
1314
modelId: number;
@@ -21,27 +22,32 @@ export const ChangeModelAction = (props: Props) => {
2122
modelId,
2223
modelName,
2324
readonly,
25+
hidden,
2426
showRegenerate,
2527
onChangeModel,
2628
} = props;
2729

2830
return (
29-
<Tips
30-
trigger={
31-
<ChatModelDropdownMenu
32-
models={models}
33-
readonly={readonly}
34-
onChangeModel={(model) => {
35-
onChangeModel && onChangeModel(model);
36-
}}
37-
modelId={modelId}
38-
modelName={modelName}
39-
showRegenerate={showRegenerate}
40-
content={modelName}
31+
<>
32+
{!hidden && (
33+
<Tips
34+
trigger={
35+
<ChatModelDropdownMenu
36+
models={models}
37+
readonly={readonly}
38+
onChangeModel={(model) => {
39+
onChangeModel && onChangeModel(model);
40+
}}
41+
modelId={modelId}
42+
modelName={modelName}
43+
showRegenerate={showRegenerate}
44+
content={modelName}
45+
/>
46+
}
47+
content={t('Change Model')!}
4148
/>
42-
}
43-
content={t('Change Model')!}
44-
/>
49+
)}
50+
</>
4551
);
4652
};
4753

src/FE/components/ChatMessage/ChatMessage.tsx

Lines changed: 53 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@ import { AdminModelDto } from '@/types/adminApis';
66
import { ChatRole, IChat, Message, ResponseContent } from '@/types/chat';
77
import { IChatMessage, ReactionMessageType } from '@/types/chatMessage';
88

9+
import ChatMessageHeader from './ChatMessageHeader';
910
import ResponseMessage from './ResponseMessage';
11+
import ResponseMessageActions from './ResponseMessageActions';
1012
import UserMessage from './UserMessage';
1113

1214
import { cn } from '@/lib/utils';
@@ -29,6 +31,7 @@ export interface Props {
2931
) => void;
3032
onEditUserMessage?: (messageId: string, content: ResponseContent) => void;
3133
onDeleteMessage?: (messageId: string) => void;
34+
onChangeDisplayType?: (messageId: string) => void;
3235
}
3336

3437
export const ChatMessage: FC<Props> = memo(
@@ -46,6 +49,7 @@ export const ChatMessage: FC<Props> = memo(
4649
onEditResponseMessage,
4750
onEditUserMessage,
4851
onDeleteMessage,
52+
onChangeDisplayType,
4953
}) => {
5054
const isMultiSpan = hasMultipleSpans(selectedMessages);
5155
return (
@@ -78,6 +82,7 @@ export const ChatMessage: FC<Props> = memo(
7882
)}
7983
>
8084
<UserMessage
85+
readonly={readonly}
8186
selectedChat={selectedChat}
8287
message={message}
8388
onChangeMessage={onChangeChatLeafMessageId}
@@ -88,38 +93,55 @@ export const ChatMessage: FC<Props> = memo(
8893
</div>
8994
)}
9095
{message.role === ChatRole.Assistant && (
91-
<div
92-
onClick={() =>
93-
isMultiSpan &&
94-
onChangeChatLeafMessageId &&
95-
onChangeChatLeafMessageId(message.id)
96-
}
97-
key={'response-group-message-' + index}
98-
className={cn(
99-
'border-[1px] border-background rounded-md flex w-full bg-card mb-4',
100-
isMultiSpan &&
101-
message.isActive &&
102-
'border-primary/50 border-gray-300',
103-
isMultiSpan && 'p-1 md:p-2',
104-
!isMultiSpan && 'border-none',
105-
)}
106-
>
107-
<div className="prose dark:prose-invert rounded-r-md flex-1 overflow-auto text-base py-2 px-3">
108-
<ResponseMessage
109-
key={'response-message-' + index}
110-
chatStatus={selectedChat.status}
111-
message={message}
112-
readonly={readonly}
113-
models={models}
114-
onRegenerate={onRegenerate}
115-
onReactionMessage={onReactionMessage}
116-
onEditResponseMessage={onEditResponseMessage}
117-
onChangeChatLeafMessageId={
118-
onChangeChatLeafMessageId
119-
}
120-
onDeleteMessage={onDeleteMessage}
121-
/>
96+
<div className="group/item">
97+
<ChatMessageHeader
98+
readonly={readonly}
99+
onChangeDisplayType={onChangeDisplayType}
100+
message={message}
101+
/>
102+
<div
103+
onClick={() =>
104+
isMultiSpan &&
105+
onChangeChatLeafMessageId &&
106+
onChangeChatLeafMessageId(message.id)
107+
}
108+
key={'response-group-message-' + index}
109+
className={cn(
110+
'border-[1px] border-background rounded-md flex w-full bg-card mb-1',
111+
isMultiSpan &&
112+
message.isActive &&
113+
'border-primary/50 border-gray-300 dark:border-gray-600',
114+
isMultiSpan && 'p-1 md:p-2',
115+
!isMultiSpan && 'border-none',
116+
)}
117+
>
118+
<div className="prose dark:prose-invert rounded-r-md flex-1 overflow-auto text-base py-1 px-2">
119+
<ResponseMessage
120+
key={'response-message-' + index}
121+
chatStatus={selectedChat.status}
122+
message={message}
123+
readonly={readonly}
124+
onEditResponseMessage={onEditResponseMessage}
125+
/>
126+
</div>
122127
</div>
128+
<ResponseMessageActions
129+
key={'response-actions-' + message.id}
130+
readonly={readonly}
131+
models={models}
132+
chatStatus={selectedChat.status}
133+
message={message}
134+
onChangeMessage={onChangeChatLeafMessageId}
135+
onReactionMessage={onReactionMessage}
136+
onRegenerate={(
137+
messageId: string,
138+
modelId: number,
139+
) => {
140+
onRegenerate &&
141+
onRegenerate(message.spanId!, messageId, modelId);
142+
}}
143+
onDeleteMessage={onDeleteMessage}
144+
/>
123145
</div>
124146
)}
125147
</>

0 commit comments

Comments
 (0)