balibabu
commited on
Commit
Β·
5743e5f
1
Parent(s):
4a78f27
feat: Expose the agent's chat window to third parties #1842 (#1897)
Browse files### What problem does this PR solve?
feat: Expose the agent's chat window to third parties #1842
### Type of change
- [x] New Feature (non-breaking change which adds functionality)
- web/src/{pages/chat β components/api-service}/chat-api-key-modal/index.tsx +4 -4
- web/src/{pages/chat β components/api-service}/chat-overview-modal/index.less +0 -0
- web/src/{pages/chat β components/api-service}/chat-overview-modal/index.tsx +17 -13
- web/src/{pages/chat β components/api-service}/embed-modal/index.less +0 -0
- web/src/{pages/chat β components/api-service}/embed-modal/index.tsx +0 -0
- web/src/components/api-service/hooks.ts +151 -0
- web/src/hooks/chat-hooks.ts +83 -51
- web/src/locales/en.ts +1 -0
- web/src/locales/zh-traditional.ts +1 -0
- web/src/locales/zh.ts +1 -0
- web/src/pages/chat/hooks.ts +1 -213
- web/src/pages/chat/index.tsx +10 -6
- web/src/pages/chat/model.ts +1 -69
- web/src/pages/flow/header/index.tsx +20 -2
web/src/{pages/chat β components/api-service}/chat-api-key-modal/index.tsx
RENAMED
@@ -9,12 +9,12 @@ import { Button, Modal, Space, Table } from 'antd';
|
|
9 |
import { useOperateApiKey } from '../hooks';
|
10 |
|
11 |
const ChatApiKeyModal = ({
|
12 |
-
visible,
|
13 |
dialogId,
|
14 |
hideModal,
|
15 |
-
|
|
|
16 |
const { createToken, removeToken, tokenList, listLoading, creatingLoading } =
|
17 |
-
useOperateApiKey(
|
18 |
const { t } = useTranslate('chat');
|
19 |
|
20 |
const columns: TableProps<IToken>['columns'] = [
|
@@ -48,7 +48,7 @@ const ChatApiKeyModal = ({
|
|
48 |
<>
|
49 |
<Modal
|
50 |
title={t('apiKey')}
|
51 |
-
open
|
52 |
onCancel={hideModal}
|
53 |
cancelButtonProps={{ style: { display: 'none' } }}
|
54 |
style={{ top: 300 }}
|
|
|
9 |
import { useOperateApiKey } from '../hooks';
|
10 |
|
11 |
const ChatApiKeyModal = ({
|
|
|
12 |
dialogId,
|
13 |
hideModal,
|
14 |
+
idKey,
|
15 |
+
}: IModalProps<any> & { dialogId: string; idKey: string }) => {
|
16 |
const { createToken, removeToken, tokenList, listLoading, creatingLoading } =
|
17 |
+
useOperateApiKey(dialogId, idKey);
|
18 |
const { t } = useTranslate('chat');
|
19 |
|
20 |
const columns: TableProps<IToken>['columns'] = [
|
|
|
48 |
<>
|
49 |
<Modal
|
50 |
title={t('apiKey')}
|
51 |
+
open
|
52 |
onCancel={hideModal}
|
53 |
cancelButtonProps={{ style: { display: 'none' } }}
|
54 |
style={{ top: 300 }}
|
web/src/{pages/chat β components/api-service}/chat-overview-modal/index.less
RENAMED
File without changes
|
web/src/{pages/chat β components/api-service}/chat-overview-modal/index.tsx
RENAMED
@@ -1,7 +1,8 @@
|
|
1 |
import LineChart from '@/components/line-chart';
|
|
|
2 |
import { useSetModalState, useTranslate } from '@/hooks/common-hooks';
|
3 |
import { IModalProps } from '@/interfaces/common';
|
4 |
-
import {
|
5 |
import { formatDate } from '@/utils/date';
|
6 |
import { Button, Card, DatePicker, Flex, Modal, Space, Typography } from 'antd';
|
7 |
import { RangePickerProps } from 'antd/es/date-picker';
|
@@ -10,7 +11,6 @@ import camelCase from 'lodash/camelCase';
|
|
10 |
import ChatApiKeyModal from '../chat-api-key-modal';
|
11 |
import EmbedModal from '../embed-modal';
|
12 |
import {
|
13 |
-
useFetchStatsOnMount,
|
14 |
usePreviewChat,
|
15 |
useSelectChartStatsList,
|
16 |
useShowEmbedModal,
|
@@ -40,8 +40,10 @@ const StatsLineChart = ({ statsType }: { statsType: keyof IStats }) => {
|
|
40 |
const ChatOverviewModal = ({
|
41 |
visible,
|
42 |
hideModal,
|
43 |
-
|
44 |
-
|
|
|
|
|
45 |
const { t } = useTranslate('chat');
|
46 |
const {
|
47 |
visible: apiKeyVisible,
|
@@ -54,15 +56,15 @@ const ChatOverviewModal = ({
|
|
54 |
showEmbedModal,
|
55 |
embedToken,
|
56 |
errorContextHolder,
|
57 |
-
} = useShowEmbedModal(
|
58 |
|
59 |
-
const { pickerValue, setPickerValue } =
|
60 |
|
61 |
const disabledDate: RangePickerProps['disabledDate'] = (current) => {
|
62 |
return current && current > dayjs().endOf('day');
|
63 |
};
|
64 |
|
65 |
-
const { handlePreview, contextHolder } = usePreviewChat(
|
66 |
|
67 |
return (
|
68 |
<>
|
@@ -97,7 +99,7 @@ const ChatOverviewModal = ({
|
|
97 |
</a>
|
98 |
</Space>
|
99 |
</Card>
|
100 |
-
<Card title={`${
|
101 |
<Flex gap={8} vertical>
|
102 |
<Space size={'middle'}>
|
103 |
<Button onClick={handlePreview}>{t('preview')}</Button>
|
@@ -124,11 +126,13 @@ const ChatOverviewModal = ({
|
|
124 |
<StatsLineChart statsType={'uv'}></StatsLineChart>
|
125 |
</div>
|
126 |
</Flex>
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
|
|
|
|
132 |
<EmbedModal
|
133 |
token={embedToken}
|
134 |
visible={embedVisible}
|
|
|
1 |
import LineChart from '@/components/line-chart';
|
2 |
+
import { useFetchNextStats } from '@/hooks/chat-hooks';
|
3 |
import { useSetModalState, useTranslate } from '@/hooks/common-hooks';
|
4 |
import { IModalProps } from '@/interfaces/common';
|
5 |
+
import { IStats } from '@/interfaces/database/chat';
|
6 |
import { formatDate } from '@/utils/date';
|
7 |
import { Button, Card, DatePicker, Flex, Modal, Space, Typography } from 'antd';
|
8 |
import { RangePickerProps } from 'antd/es/date-picker';
|
|
|
11 |
import ChatApiKeyModal from '../chat-api-key-modal';
|
12 |
import EmbedModal from '../embed-modal';
|
13 |
import {
|
|
|
14 |
usePreviewChat,
|
15 |
useSelectChartStatsList,
|
16 |
useShowEmbedModal,
|
|
|
40 |
const ChatOverviewModal = ({
|
41 |
visible,
|
42 |
hideModal,
|
43 |
+
id,
|
44 |
+
name = '',
|
45 |
+
idKey,
|
46 |
+
}: IModalProps<any> & { id: string; name?: string; idKey: string }) => {
|
47 |
const { t } = useTranslate('chat');
|
48 |
const {
|
49 |
visible: apiKeyVisible,
|
|
|
56 |
showEmbedModal,
|
57 |
embedToken,
|
58 |
errorContextHolder,
|
59 |
+
} = useShowEmbedModal(id, idKey);
|
60 |
|
61 |
+
const { pickerValue, setPickerValue } = useFetchNextStats();
|
62 |
|
63 |
const disabledDate: RangePickerProps['disabledDate'] = (current) => {
|
64 |
return current && current > dayjs().endOf('day');
|
65 |
};
|
66 |
|
67 |
+
const { handlePreview, contextHolder } = usePreviewChat(id, idKey);
|
68 |
|
69 |
return (
|
70 |
<>
|
|
|
99 |
</a>
|
100 |
</Space>
|
101 |
</Card>
|
102 |
+
<Card title={`${name} Web App`}>
|
103 |
<Flex gap={8} vertical>
|
104 |
<Space size={'middle'}>
|
105 |
<Button onClick={handlePreview}>{t('preview')}</Button>
|
|
|
126 |
<StatsLineChart statsType={'uv'}></StatsLineChart>
|
127 |
</div>
|
128 |
</Flex>
|
129 |
+
{apiKeyVisible && (
|
130 |
+
<ChatApiKeyModal
|
131 |
+
hideModal={hideApiKeyModal}
|
132 |
+
dialogId={id}
|
133 |
+
idKey={idKey}
|
134 |
+
></ChatApiKeyModal>
|
135 |
+
)}
|
136 |
<EmbedModal
|
137 |
token={embedToken}
|
138 |
visible={embedVisible}
|
web/src/{pages/chat β components/api-service}/embed-modal/index.less
RENAMED
File without changes
|
web/src/{pages/chat β components/api-service}/embed-modal/index.tsx
RENAMED
File without changes
|
web/src/components/api-service/hooks.ts
ADDED
@@ -0,0 +1,151 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import {
|
2 |
+
useCreateNextToken,
|
3 |
+
useFetchNextStats,
|
4 |
+
useFetchTokenList,
|
5 |
+
useRemoveNextToken,
|
6 |
+
} from '@/hooks/chat-hooks';
|
7 |
+
import {
|
8 |
+
useSetModalState,
|
9 |
+
useShowDeleteConfirm,
|
10 |
+
useTranslate,
|
11 |
+
} from '@/hooks/common-hooks';
|
12 |
+
import { IStats } from '@/interfaces/database/chat';
|
13 |
+
import { message } from 'antd';
|
14 |
+
import { useCallback } from 'react';
|
15 |
+
|
16 |
+
export const useOperateApiKey = (dialogId: string, idKey: string) => {
|
17 |
+
const { removeToken } = useRemoveNextToken();
|
18 |
+
const { createToken, loading: creatingLoading } = useCreateNextToken();
|
19 |
+
const { data: tokenList, loading: listLoading } = useFetchTokenList({
|
20 |
+
[idKey]: dialogId,
|
21 |
+
});
|
22 |
+
|
23 |
+
const showDeleteConfirm = useShowDeleteConfirm();
|
24 |
+
|
25 |
+
const onRemoveToken = (token: string, tenantId: string) => {
|
26 |
+
showDeleteConfirm({
|
27 |
+
onOk: () => removeToken({ dialogId, tokens: [token], tenantId }),
|
28 |
+
});
|
29 |
+
};
|
30 |
+
|
31 |
+
const onCreateToken = useCallback(() => {
|
32 |
+
createToken({ [idKey]: dialogId });
|
33 |
+
}, [createToken, idKey, dialogId]);
|
34 |
+
|
35 |
+
return {
|
36 |
+
removeToken: onRemoveToken,
|
37 |
+
createToken: onCreateToken,
|
38 |
+
tokenList,
|
39 |
+
creatingLoading,
|
40 |
+
listLoading,
|
41 |
+
};
|
42 |
+
};
|
43 |
+
|
44 |
+
type ChartStatsType = {
|
45 |
+
[k in keyof IStats]: Array<{ xAxis: string; yAxis: number }>;
|
46 |
+
};
|
47 |
+
|
48 |
+
export const useSelectChartStatsList = (): ChartStatsType => {
|
49 |
+
const { data: stats } = useFetchNextStats();
|
50 |
+
|
51 |
+
return Object.keys(stats).reduce((pre, cur) => {
|
52 |
+
const item = stats[cur as keyof IStats];
|
53 |
+
if (item.length > 0) {
|
54 |
+
pre[cur as keyof IStats] = item.map((x) => ({
|
55 |
+
xAxis: x[0] as string,
|
56 |
+
yAxis: x[1] as number,
|
57 |
+
}));
|
58 |
+
}
|
59 |
+
return pre;
|
60 |
+
}, {} as ChartStatsType);
|
61 |
+
};
|
62 |
+
|
63 |
+
export const useShowTokenEmptyError = () => {
|
64 |
+
const [messageApi, contextHolder] = message.useMessage();
|
65 |
+
const { t } = useTranslate('chat');
|
66 |
+
|
67 |
+
const showTokenEmptyError = useCallback(() => {
|
68 |
+
messageApi.error(t('tokenError'));
|
69 |
+
}, [messageApi, t]);
|
70 |
+
return { showTokenEmptyError, contextHolder };
|
71 |
+
};
|
72 |
+
|
73 |
+
const getUrlWithToken = (token: string) => {
|
74 |
+
const { protocol, host } = window.location;
|
75 |
+
return `${protocol}//${host}/chat/share?shared_id=${token}`;
|
76 |
+
};
|
77 |
+
|
78 |
+
const useFetchTokenListBeforeOtherStep = (dialogId: string, idKey: string) => {
|
79 |
+
const { showTokenEmptyError, contextHolder } = useShowTokenEmptyError();
|
80 |
+
|
81 |
+
const { data: tokenList, refetch } = useFetchTokenList({ [idKey]: dialogId });
|
82 |
+
|
83 |
+
const token =
|
84 |
+
Array.isArray(tokenList) && tokenList.length > 0 ? tokenList[0].token : '';
|
85 |
+
|
86 |
+
const handleOperate = useCallback(async () => {
|
87 |
+
const ret = await refetch();
|
88 |
+
const list = ret.data;
|
89 |
+
if (Array.isArray(list) && list.length > 0) {
|
90 |
+
return list[0]?.token;
|
91 |
+
} else {
|
92 |
+
showTokenEmptyError();
|
93 |
+
return false;
|
94 |
+
}
|
95 |
+
}, [showTokenEmptyError, refetch]);
|
96 |
+
|
97 |
+
return {
|
98 |
+
token,
|
99 |
+
contextHolder,
|
100 |
+
handleOperate,
|
101 |
+
};
|
102 |
+
};
|
103 |
+
|
104 |
+
export const useShowEmbedModal = (dialogId: string, idKey: string) => {
|
105 |
+
const {
|
106 |
+
visible: embedVisible,
|
107 |
+
hideModal: hideEmbedModal,
|
108 |
+
showModal: showEmbedModal,
|
109 |
+
} = useSetModalState();
|
110 |
+
|
111 |
+
const { handleOperate, token, contextHolder } =
|
112 |
+
useFetchTokenListBeforeOtherStep(dialogId, idKey);
|
113 |
+
|
114 |
+
const handleShowEmbedModal = useCallback(async () => {
|
115 |
+
const succeed = await handleOperate();
|
116 |
+
if (succeed) {
|
117 |
+
showEmbedModal();
|
118 |
+
}
|
119 |
+
}, [handleOperate, showEmbedModal]);
|
120 |
+
|
121 |
+
return {
|
122 |
+
showEmbedModal: handleShowEmbedModal,
|
123 |
+
hideEmbedModal,
|
124 |
+
embedVisible,
|
125 |
+
embedToken: token,
|
126 |
+
errorContextHolder: contextHolder,
|
127 |
+
};
|
128 |
+
};
|
129 |
+
|
130 |
+
export const usePreviewChat = (dialogId: string, idKey: string) => {
|
131 |
+
const { handleOperate, contextHolder } = useFetchTokenListBeforeOtherStep(
|
132 |
+
dialogId,
|
133 |
+
idKey,
|
134 |
+
);
|
135 |
+
|
136 |
+
const open = useCallback((t: string) => {
|
137 |
+
window.open(getUrlWithToken(t), '_blank');
|
138 |
+
}, []);
|
139 |
+
|
140 |
+
const handlePreview = useCallback(async () => {
|
141 |
+
const token = await handleOperate();
|
142 |
+
if (token) {
|
143 |
+
open(token);
|
144 |
+
}
|
145 |
+
}, [handleOperate, open]);
|
146 |
+
|
147 |
+
return {
|
148 |
+
handlePreview,
|
149 |
+
contextHolder,
|
150 |
+
};
|
151 |
+
};
|
web/src/hooks/chat-hooks.ts
CHANGED
@@ -4,7 +4,10 @@ import {
|
|
4 |
IStats,
|
5 |
IToken,
|
6 |
} from '@/interfaces/database/chat';
|
7 |
-
import
|
|
|
|
|
|
|
8 |
import { useDispatch, useSelector } from 'umi';
|
9 |
|
10 |
export const useFetchDialogList = () => {
|
@@ -175,79 +178,108 @@ export const useCompleteConversation = () => {
|
|
175 |
|
176 |
// #region API provided for external calls
|
177 |
|
178 |
-
export const useCreateToken = (
|
179 |
const dispatch = useDispatch();
|
180 |
|
181 |
const createToken = useCallback(() => {
|
182 |
return dispatch<any>({
|
183 |
type: 'chatModel/createToken',
|
184 |
-
payload:
|
185 |
});
|
186 |
-
}, [dispatch,
|
187 |
|
188 |
return createToken;
|
189 |
};
|
190 |
|
191 |
-
export const
|
192 |
-
const
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
|
|
|
|
|
|
|
|
|
|
200 |
},
|
201 |
-
|
202 |
-
);
|
203 |
|
204 |
-
return
|
205 |
};
|
206 |
|
207 |
-
export const
|
208 |
-
const
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
return dispatch<any>({
|
221 |
-
type: 'chatModel/removeToken',
|
222 |
-
payload: payload,
|
223 |
-
});
|
224 |
},
|
225 |
-
|
226 |
-
);
|
227 |
|
228 |
-
return
|
229 |
};
|
230 |
|
231 |
-
export const
|
232 |
-
const
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
240 |
},
|
241 |
-
|
242 |
-
);
|
243 |
|
244 |
-
return
|
245 |
};
|
246 |
|
247 |
-
|
248 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
249 |
|
250 |
-
return
|
251 |
};
|
252 |
|
253 |
//#endregion
|
|
|
4 |
IStats,
|
5 |
IToken,
|
6 |
} from '@/interfaces/database/chat';
|
7 |
+
import chatService from '@/services/chat-service';
|
8 |
+
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
|
9 |
+
import dayjs, { Dayjs } from 'dayjs';
|
10 |
+
import { useCallback, useState } from 'react';
|
11 |
import { useDispatch, useSelector } from 'umi';
|
12 |
|
13 |
export const useFetchDialogList = () => {
|
|
|
178 |
|
179 |
// #region API provided for external calls
|
180 |
|
181 |
+
export const useCreateToken = (params: Record<string, any>) => {
|
182 |
const dispatch = useDispatch();
|
183 |
|
184 |
const createToken = useCallback(() => {
|
185 |
return dispatch<any>({
|
186 |
type: 'chatModel/createToken',
|
187 |
+
payload: params,
|
188 |
});
|
189 |
+
}, [dispatch, params]);
|
190 |
|
191 |
return createToken;
|
192 |
};
|
193 |
|
194 |
+
export const useCreateNextToken = () => {
|
195 |
+
const queryClient = useQueryClient();
|
196 |
+
const {
|
197 |
+
data,
|
198 |
+
isPending: loading,
|
199 |
+
mutateAsync,
|
200 |
+
} = useMutation({
|
201 |
+
mutationKey: ['createToken'],
|
202 |
+
mutationFn: async (params: Record<string, any>) => {
|
203 |
+
const { data } = await chatService.createToken(params);
|
204 |
+
if (data.retcode === 0) {
|
205 |
+
queryClient.invalidateQueries({ queryKey: ['fetchTokenList'] });
|
206 |
+
}
|
207 |
+
return data?.data ?? [];
|
208 |
},
|
209 |
+
});
|
|
|
210 |
|
211 |
+
return { data, loading, createToken: mutateAsync };
|
212 |
};
|
213 |
|
214 |
+
export const useFetchTokenList = (params: Record<string, any>) => {
|
215 |
+
const {
|
216 |
+
data,
|
217 |
+
isFetching: loading,
|
218 |
+
refetch,
|
219 |
+
} = useQuery<IToken[]>({
|
220 |
+
queryKey: ['fetchTokenList', params],
|
221 |
+
initialData: [],
|
222 |
+
gcTime: 0,
|
223 |
+
queryFn: async () => {
|
224 |
+
const { data } = await chatService.listToken(params);
|
225 |
+
|
226 |
+
return data?.data ?? [];
|
|
|
|
|
|
|
|
|
227 |
},
|
228 |
+
});
|
|
|
229 |
|
230 |
+
return { data, loading, refetch };
|
231 |
};
|
232 |
|
233 |
+
export const useRemoveNextToken = () => {
|
234 |
+
const queryClient = useQueryClient();
|
235 |
+
const {
|
236 |
+
data,
|
237 |
+
isPending: loading,
|
238 |
+
mutateAsync,
|
239 |
+
} = useMutation({
|
240 |
+
mutationKey: ['removeToken'],
|
241 |
+
mutationFn: async (params: {
|
242 |
+
tenantId: string;
|
243 |
+
dialogId: string;
|
244 |
+
tokens: string[];
|
245 |
+
}) => {
|
246 |
+
const { data } = await chatService.removeToken(params);
|
247 |
+
if (data.retcode === 0) {
|
248 |
+
queryClient.invalidateQueries({ queryKey: ['fetchTokenList'] });
|
249 |
+
}
|
250 |
+
return data?.data ?? [];
|
251 |
},
|
252 |
+
});
|
|
|
253 |
|
254 |
+
return { data, loading, removeToken: mutateAsync };
|
255 |
};
|
256 |
|
257 |
+
type RangeValue = [Dayjs | null, Dayjs | null] | null;
|
258 |
+
|
259 |
+
const getDay = (date?: Dayjs) => date?.format('YYYY-MM-DD');
|
260 |
+
|
261 |
+
export const useFetchNextStats = () => {
|
262 |
+
const [pickerValue, setPickerValue] = useState<RangeValue>([
|
263 |
+
dayjs(),
|
264 |
+
dayjs().subtract(7, 'day'),
|
265 |
+
]);
|
266 |
+
const { data, isFetching: loading } = useQuery<IStats>({
|
267 |
+
queryKey: ['fetchStats', pickerValue],
|
268 |
+
initialData: {} as IStats,
|
269 |
+
gcTime: 0,
|
270 |
+
queryFn: async () => {
|
271 |
+
if (Array.isArray(pickerValue) && pickerValue[0]) {
|
272 |
+
const { data } = await chatService.getStats({
|
273 |
+
fromDate: getDay(pickerValue[0]),
|
274 |
+
toDate: getDay(pickerValue[1] ?? dayjs()),
|
275 |
+
});
|
276 |
+
return data?.data ?? {};
|
277 |
+
}
|
278 |
+
return {};
|
279 |
+
},
|
280 |
+
});
|
281 |
|
282 |
+
return { data, loading, pickerValue, setPickerValue };
|
283 |
};
|
284 |
|
285 |
//#endregion
|
web/src/locales/en.ts
CHANGED
@@ -783,6 +783,7 @@ The above is the content you need to summarize.`,
|
|
783 |
'15d': '12 days',
|
784 |
'30d': '30 days',
|
785 |
},
|
|
|
786 |
},
|
787 |
footer: {
|
788 |
profile: 'All rights reserved @ React',
|
|
|
783 |
'15d': '12 days',
|
784 |
'30d': '30 days',
|
785 |
},
|
786 |
+
publish: 'Publish',
|
787 |
},
|
788 |
footer: {
|
789 |
profile: 'All rights reserved @ React',
|
web/src/locales/zh-traditional.ts
CHANGED
@@ -741,6 +741,7 @@ export default {
|
|
741 |
'15d': '12倩',
|
742 |
'30d': '30倩',
|
743 |
},
|
|
|
744 |
},
|
745 |
footer: {
|
746 |
profile: 'βδΏηζζζ¬ε© @ reactβ',
|
|
|
741 |
'15d': '12倩',
|
742 |
'30d': '30倩',
|
743 |
},
|
744 |
+
publish: 'ηΌεΈ',
|
745 |
},
|
746 |
footer: {
|
747 |
profile: 'βδΏηζζζ¬ε© @ reactβ',
|
web/src/locales/zh.ts
CHANGED
@@ -759,6 +759,7 @@ export default {
|
|
759 |
'15d': '12倩',
|
760 |
'30d': '30倩',
|
761 |
},
|
|
|
762 |
},
|
763 |
footer: {
|
764 |
profile: 'All rights reserved @ React',
|
|
|
759 |
'15d': '12倩',
|
760 |
'30d': '30倩',
|
761 |
},
|
762 |
+
publish: 'εεΈ',
|
763 |
},
|
764 |
footer: {
|
765 |
profile: 'All rights reserved @ React',
|
web/src/pages/chat/hooks.ts
CHANGED
@@ -1,20 +1,14 @@
|
|
1 |
import { MessageType } from '@/constants/chat';
|
2 |
import { fileIconMap } from '@/constants/common';
|
3 |
import {
|
4 |
-
useCreateToken,
|
5 |
useFetchConversation,
|
6 |
useFetchConversationList,
|
7 |
useFetchDialog,
|
8 |
useFetchDialogList,
|
9 |
-
useFetchStats,
|
10 |
-
useListToken,
|
11 |
useRemoveConversation,
|
12 |
useRemoveDialog,
|
13 |
-
useRemoveToken,
|
14 |
useSelectConversationList,
|
15 |
useSelectDialogList,
|
16 |
-
useSelectStats,
|
17 |
-
useSelectTokenList,
|
18 |
useSetDialog,
|
19 |
useUpdateConversation,
|
20 |
} from '@/hooks/chat-hooks';
|
@@ -25,16 +19,9 @@ import {
|
|
25 |
} from '@/hooks/common-hooks';
|
26 |
import { useSendMessageWithSse } from '@/hooks/logic-hooks';
|
27 |
import { useOneNamespaceEffectsLoading } from '@/hooks/store-hooks';
|
28 |
-
import {
|
29 |
-
IAnswer,
|
30 |
-
IConversation,
|
31 |
-
IDialog,
|
32 |
-
IStats,
|
33 |
-
} from '@/interfaces/database/chat';
|
34 |
import { IChunk } from '@/interfaces/database/knowledge';
|
35 |
import { getFileExtension } from '@/utils';
|
36 |
-
import { message } from 'antd';
|
37 |
-
import dayjs, { Dayjs } from 'dayjs';
|
38 |
import omit from 'lodash/omit';
|
39 |
import trim from 'lodash/trim';
|
40 |
import {
|
@@ -773,202 +760,3 @@ export const useSendButtonDisabled = (value: string) => {
|
|
773 |
return trim(value) === '';
|
774 |
};
|
775 |
//#endregion
|
776 |
-
|
777 |
-
//#region API provided for external calls
|
778 |
-
|
779 |
-
type RangeValue = [Dayjs | null, Dayjs | null] | null;
|
780 |
-
|
781 |
-
const getDay = (date: Dayjs) => date.format('YYYY-MM-DD');
|
782 |
-
|
783 |
-
export const useFetchStatsOnMount = (visible: boolean) => {
|
784 |
-
const fetchStats = useFetchStats();
|
785 |
-
const [pickerValue, setPickerValue] = useState<RangeValue>([
|
786 |
-
dayjs(),
|
787 |
-
dayjs().subtract(7, 'day'),
|
788 |
-
]);
|
789 |
-
|
790 |
-
useEffect(() => {
|
791 |
-
if (visible && Array.isArray(pickerValue) && pickerValue[0]) {
|
792 |
-
fetchStats({
|
793 |
-
fromDate: getDay(pickerValue[0]),
|
794 |
-
toDate: getDay(pickerValue[1] ?? dayjs()),
|
795 |
-
});
|
796 |
-
}
|
797 |
-
}, [fetchStats, pickerValue, visible]);
|
798 |
-
|
799 |
-
return {
|
800 |
-
pickerValue,
|
801 |
-
setPickerValue,
|
802 |
-
};
|
803 |
-
};
|
804 |
-
|
805 |
-
export const useOperateApiKey = (visible: boolean, dialogId: string) => {
|
806 |
-
const removeToken = useRemoveToken();
|
807 |
-
const createToken = useCreateToken(dialogId);
|
808 |
-
const listToken = useListToken();
|
809 |
-
const tokenList = useSelectTokenList();
|
810 |
-
const creatingLoading = useOneNamespaceEffectsLoading('chatModel', [
|
811 |
-
'createToken',
|
812 |
-
]);
|
813 |
-
const listLoading = useOneNamespaceEffectsLoading('chatModel', ['list']);
|
814 |
-
|
815 |
-
const showDeleteConfirm = useShowDeleteConfirm();
|
816 |
-
|
817 |
-
const onRemoveToken = (token: string, tenantId: string) => {
|
818 |
-
showDeleteConfirm({
|
819 |
-
onOk: () => removeToken({ dialogId, tokens: [token], tenantId }),
|
820 |
-
});
|
821 |
-
};
|
822 |
-
|
823 |
-
useEffect(() => {
|
824 |
-
if (visible && dialogId) {
|
825 |
-
listToken(dialogId);
|
826 |
-
}
|
827 |
-
}, [listToken, dialogId, visible]);
|
828 |
-
|
829 |
-
return {
|
830 |
-
removeToken: onRemoveToken,
|
831 |
-
createToken,
|
832 |
-
tokenList,
|
833 |
-
creatingLoading,
|
834 |
-
listLoading,
|
835 |
-
};
|
836 |
-
};
|
837 |
-
|
838 |
-
type ChartStatsType = {
|
839 |
-
[k in keyof IStats]: Array<{ xAxis: string; yAxis: number }>;
|
840 |
-
};
|
841 |
-
|
842 |
-
export const useSelectChartStatsList = (): ChartStatsType => {
|
843 |
-
const stats: IStats = useSelectStats();
|
844 |
-
// const stats = {
|
845 |
-
// pv: [
|
846 |
-
// ['2024-06-01', 1],
|
847 |
-
// ['2024-07-24', 3],
|
848 |
-
// ['2024-09-01', 10],
|
849 |
-
// ],
|
850 |
-
// uv: [
|
851 |
-
// ['2024-02-01', 0],
|
852 |
-
// ['2024-03-01', 99],
|
853 |
-
// ['2024-05-01', 3],
|
854 |
-
// ],
|
855 |
-
// speed: [
|
856 |
-
// ['2024-09-01', 2],
|
857 |
-
// ['2024-09-01', 3],
|
858 |
-
// ],
|
859 |
-
// tokens: [
|
860 |
-
// ['2024-09-01', 1],
|
861 |
-
// ['2024-09-01', 3],
|
862 |
-
// ],
|
863 |
-
// round: [
|
864 |
-
// ['2024-09-01', 0],
|
865 |
-
// ['2024-09-01', 3],
|
866 |
-
// ],
|
867 |
-
// thumb_up: [
|
868 |
-
// ['2024-09-01', 3],
|
869 |
-
// ['2024-09-01', 9],
|
870 |
-
// ],
|
871 |
-
// };
|
872 |
-
|
873 |
-
return Object.keys(stats).reduce((pre, cur) => {
|
874 |
-
const item = stats[cur as keyof IStats];
|
875 |
-
if (item.length > 0) {
|
876 |
-
pre[cur as keyof IStats] = item.map((x) => ({
|
877 |
-
xAxis: x[0] as string,
|
878 |
-
yAxis: x[1] as number,
|
879 |
-
}));
|
880 |
-
}
|
881 |
-
return pre;
|
882 |
-
}, {} as ChartStatsType);
|
883 |
-
};
|
884 |
-
|
885 |
-
export const useShowTokenEmptyError = () => {
|
886 |
-
const [messageApi, contextHolder] = message.useMessage();
|
887 |
-
const { t } = useTranslate('chat');
|
888 |
-
|
889 |
-
const showTokenEmptyError = useCallback(() => {
|
890 |
-
messageApi.error(t('tokenError'));
|
891 |
-
}, [messageApi, t]);
|
892 |
-
return { showTokenEmptyError, contextHolder };
|
893 |
-
};
|
894 |
-
|
895 |
-
const getUrlWithToken = (token: string) => {
|
896 |
-
const { protocol, host } = window.location;
|
897 |
-
return `${protocol}//${host}/chat/share?shared_id=${token}`;
|
898 |
-
};
|
899 |
-
|
900 |
-
const useFetchTokenListBeforeOtherStep = (dialogId: string) => {
|
901 |
-
const { showTokenEmptyError, contextHolder } = useShowTokenEmptyError();
|
902 |
-
|
903 |
-
const listToken = useListToken();
|
904 |
-
const tokenList = useSelectTokenList();
|
905 |
-
|
906 |
-
const token =
|
907 |
-
Array.isArray(tokenList) && tokenList.length > 0 ? tokenList[0].token : '';
|
908 |
-
|
909 |
-
const handleOperate = useCallback(async () => {
|
910 |
-
const data = await listToken(dialogId);
|
911 |
-
const list = data.data;
|
912 |
-
if (data.retcode === 0 && Array.isArray(list) && list.length > 0) {
|
913 |
-
return list[0]?.token;
|
914 |
-
} else {
|
915 |
-
showTokenEmptyError();
|
916 |
-
return false;
|
917 |
-
}
|
918 |
-
}, [dialogId, listToken, showTokenEmptyError]);
|
919 |
-
|
920 |
-
return {
|
921 |
-
token,
|
922 |
-
contextHolder,
|
923 |
-
handleOperate,
|
924 |
-
};
|
925 |
-
};
|
926 |
-
|
927 |
-
export const useShowEmbedModal = (dialogId: string) => {
|
928 |
-
const {
|
929 |
-
visible: embedVisible,
|
930 |
-
hideModal: hideEmbedModal,
|
931 |
-
showModal: showEmbedModal,
|
932 |
-
} = useSetModalState();
|
933 |
-
|
934 |
-
const { handleOperate, token, contextHolder } =
|
935 |
-
useFetchTokenListBeforeOtherStep(dialogId);
|
936 |
-
|
937 |
-
const handleShowEmbedModal = useCallback(async () => {
|
938 |
-
const succeed = await handleOperate();
|
939 |
-
if (succeed) {
|
940 |
-
showEmbedModal();
|
941 |
-
}
|
942 |
-
}, [handleOperate, showEmbedModal]);
|
943 |
-
|
944 |
-
return {
|
945 |
-
showEmbedModal: handleShowEmbedModal,
|
946 |
-
hideEmbedModal,
|
947 |
-
embedVisible,
|
948 |
-
embedToken: token,
|
949 |
-
errorContextHolder: contextHolder,
|
950 |
-
};
|
951 |
-
};
|
952 |
-
|
953 |
-
export const usePreviewChat = (dialogId: string) => {
|
954 |
-
const { handleOperate, contextHolder } =
|
955 |
-
useFetchTokenListBeforeOtherStep(dialogId);
|
956 |
-
|
957 |
-
const open = useCallback((t: string) => {
|
958 |
-
window.open(getUrlWithToken(t), '_blank');
|
959 |
-
}, []);
|
960 |
-
|
961 |
-
const handlePreview = useCallback(async () => {
|
962 |
-
const token = await handleOperate();
|
963 |
-
if (token) {
|
964 |
-
open(token);
|
965 |
-
}
|
966 |
-
}, [handleOperate, open]);
|
967 |
-
|
968 |
-
return {
|
969 |
-
handlePreview,
|
970 |
-
contextHolder,
|
971 |
-
};
|
972 |
-
};
|
973 |
-
|
974 |
-
//#endregion
|
|
|
1 |
import { MessageType } from '@/constants/chat';
|
2 |
import { fileIconMap } from '@/constants/common';
|
3 |
import {
|
|
|
4 |
useFetchConversation,
|
5 |
useFetchConversationList,
|
6 |
useFetchDialog,
|
7 |
useFetchDialogList,
|
|
|
|
|
8 |
useRemoveConversation,
|
9 |
useRemoveDialog,
|
|
|
10 |
useSelectConversationList,
|
11 |
useSelectDialogList,
|
|
|
|
|
12 |
useSetDialog,
|
13 |
useUpdateConversation,
|
14 |
} from '@/hooks/chat-hooks';
|
|
|
19 |
} from '@/hooks/common-hooks';
|
20 |
import { useSendMessageWithSse } from '@/hooks/logic-hooks';
|
21 |
import { useOneNamespaceEffectsLoading } from '@/hooks/store-hooks';
|
22 |
+
import { IAnswer, IConversation, IDialog } from '@/interfaces/database/chat';
|
|
|
|
|
|
|
|
|
|
|
23 |
import { IChunk } from '@/interfaces/database/knowledge';
|
24 |
import { getFileExtension } from '@/utils';
|
|
|
|
|
25 |
import omit from 'lodash/omit';
|
26 |
import trim from 'lodash/trim';
|
27 |
import {
|
|
|
760 |
return trim(value) === '';
|
761 |
};
|
762 |
//#endregion
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
web/src/pages/chat/index.tsx
CHANGED
@@ -41,10 +41,10 @@ import {
|
|
41 |
useSelectFirstDialogOnMount,
|
42 |
} from './hooks';
|
43 |
|
|
|
44 |
import { useSetModalState, useTranslate } from '@/hooks/common-hooks';
|
45 |
import { useSetSelectedRecord } from '@/hooks/logic-hooks';
|
46 |
import { IDialog } from '@/interfaces/database/chat';
|
47 |
-
import ChatOverviewModal from './chat-overview-modal';
|
48 |
import styles from './index.less';
|
49 |
|
50 |
const { Text } = Typography;
|
@@ -371,11 +371,15 @@ const Chat = () => {
|
|
371 |
initialName={initialConversationName}
|
372 |
loading={conversationRenameLoading}
|
373 |
></RenameModal>
|
374 |
-
|
375 |
-
|
376 |
-
|
377 |
-
|
378 |
-
|
|
|
|
|
|
|
|
|
379 |
</Flex>
|
380 |
);
|
381 |
};
|
|
|
41 |
useSelectFirstDialogOnMount,
|
42 |
} from './hooks';
|
43 |
|
44 |
+
import ChatOverviewModal from '@/components/api-service/chat-overview-modal';
|
45 |
import { useSetModalState, useTranslate } from '@/hooks/common-hooks';
|
46 |
import { useSetSelectedRecord } from '@/hooks/logic-hooks';
|
47 |
import { IDialog } from '@/interfaces/database/chat';
|
|
|
48 |
import styles from './index.less';
|
49 |
|
50 |
const { Text } = Typography;
|
|
|
371 |
initialName={initialConversationName}
|
372 |
loading={conversationRenameLoading}
|
373 |
></RenameModal>
|
374 |
+
{overviewVisible && (
|
375 |
+
<ChatOverviewModal
|
376 |
+
visible={overviewVisible}
|
377 |
+
hideModal={hideOverviewModal}
|
378 |
+
id={currentRecord.id}
|
379 |
+
name={currentRecord.name}
|
380 |
+
idKey="dialogId"
|
381 |
+
></ChatOverviewModal>
|
382 |
+
)}
|
383 |
</Flex>
|
384 |
);
|
385 |
};
|
web/src/pages/chat/model.ts
CHANGED
@@ -1,14 +1,7 @@
|
|
1 |
-
import {
|
2 |
-
IConversation,
|
3 |
-
IDialog,
|
4 |
-
IStats,
|
5 |
-
IToken,
|
6 |
-
Message,
|
7 |
-
} from '@/interfaces/database/chat';
|
8 |
import i18n from '@/locales/config';
|
9 |
import chatService from '@/services/chat-service';
|
10 |
import { message } from 'antd';
|
11 |
-
import omit from 'lodash/omit';
|
12 |
import { DvaModel } from 'umi';
|
13 |
import { v4 as uuid } from 'uuid';
|
14 |
import { IClientConversation, IMessage } from './interface';
|
@@ -20,8 +13,6 @@ export interface ChatModelState {
|
|
20 |
currentDialog: IDialog;
|
21 |
conversationList: IConversation[];
|
22 |
currentConversation: IClientConversation;
|
23 |
-
tokenList: IToken[];
|
24 |
-
stats: IStats;
|
25 |
}
|
26 |
|
27 |
const model: DvaModel<ChatModelState> = {
|
@@ -32,8 +23,6 @@ const model: DvaModel<ChatModelState> = {
|
|
32 |
currentDialog: <IDialog>{},
|
33 |
conversationList: [],
|
34 |
currentConversation: {} as IClientConversation,
|
35 |
-
tokenList: [],
|
36 |
-
stats: {} as IStats,
|
37 |
},
|
38 |
reducers: {
|
39 |
save(state, action) {
|
@@ -71,18 +60,6 @@ const model: DvaModel<ChatModelState> = {
|
|
71 |
currentConversation: { ...payload, message: messageList },
|
72 |
};
|
73 |
},
|
74 |
-
setTokenList(state, { payload }) {
|
75 |
-
return {
|
76 |
-
...state,
|
77 |
-
tokenList: payload,
|
78 |
-
};
|
79 |
-
},
|
80 |
-
setStats(state, { payload }) {
|
81 |
-
return {
|
82 |
-
...state,
|
83 |
-
stats: payload,
|
84 |
-
};
|
85 |
-
},
|
86 |
},
|
87 |
|
88 |
effects: {
|
@@ -183,51 +160,6 @@ const model: DvaModel<ChatModelState> = {
|
|
183 |
}
|
184 |
return data.retcode;
|
185 |
},
|
186 |
-
*createToken({ payload }, { call, put }) {
|
187 |
-
const { data } = yield call(chatService.createToken, payload);
|
188 |
-
if (data.retcode === 0) {
|
189 |
-
yield put({
|
190 |
-
type: 'listToken',
|
191 |
-
payload: payload,
|
192 |
-
});
|
193 |
-
message.success(i18n.t('message.created'));
|
194 |
-
}
|
195 |
-
return data;
|
196 |
-
},
|
197 |
-
*listToken({ payload }, { call, put }) {
|
198 |
-
const { data } = yield call(chatService.listToken, payload);
|
199 |
-
if (data.retcode === 0) {
|
200 |
-
yield put({
|
201 |
-
type: 'setTokenList',
|
202 |
-
payload: data.data,
|
203 |
-
});
|
204 |
-
}
|
205 |
-
return data;
|
206 |
-
},
|
207 |
-
*removeToken({ payload }, { call, put }) {
|
208 |
-
const { data } = yield call(
|
209 |
-
chatService.removeToken,
|
210 |
-
omit(payload, ['dialogId']),
|
211 |
-
);
|
212 |
-
if (data.retcode === 0) {
|
213 |
-
message.success(i18n.t('message.deleted'));
|
214 |
-
yield put({
|
215 |
-
type: 'listToken',
|
216 |
-
payload: { dialog_id: payload.dialogId },
|
217 |
-
});
|
218 |
-
}
|
219 |
-
return data.retcode;
|
220 |
-
},
|
221 |
-
*getStats({ payload }, { call, put }) {
|
222 |
-
const { data } = yield call(chatService.getStats, payload);
|
223 |
-
if (data.retcode === 0) {
|
224 |
-
yield put({
|
225 |
-
type: 'setStats',
|
226 |
-
payload: data.data,
|
227 |
-
});
|
228 |
-
}
|
229 |
-
return data.retcode;
|
230 |
-
},
|
231 |
*createExternalConversation({ payload }, { call, put }) {
|
232 |
const { data } = yield call(
|
233 |
chatService.createExternalConversation,
|
|
|
1 |
+
import { IConversation, IDialog, Message } from '@/interfaces/database/chat';
|
|
|
|
|
|
|
|
|
|
|
|
|
2 |
import i18n from '@/locales/config';
|
3 |
import chatService from '@/services/chat-service';
|
4 |
import { message } from 'antd';
|
|
|
5 |
import { DvaModel } from 'umi';
|
6 |
import { v4 as uuid } from 'uuid';
|
7 |
import { IClientConversation, IMessage } from './interface';
|
|
|
13 |
currentDialog: IDialog;
|
14 |
conversationList: IConversation[];
|
15 |
currentConversation: IClientConversation;
|
|
|
|
|
16 |
}
|
17 |
|
18 |
const model: DvaModel<ChatModelState> = {
|
|
|
23 |
currentDialog: <IDialog>{},
|
24 |
conversationList: [],
|
25 |
currentConversation: {} as IClientConversation,
|
|
|
|
|
26 |
},
|
27 |
reducers: {
|
28 |
save(state, action) {
|
|
|
60 |
currentConversation: { ...payload, message: messageList },
|
61 |
};
|
62 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
63 |
},
|
64 |
|
65 |
effects: {
|
|
|
160 |
}
|
161 |
return data.retcode;
|
162 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
163 |
*createExternalConversation({ payload }, { call, put }) {
|
164 |
const { data } = yield call(
|
165 |
chatService.createExternalConversation,
|
web/src/pages/flow/header/index.tsx
CHANGED
@@ -1,8 +1,9 @@
|
|
1 |
-
import
|
|
|
2 |
import { useFetchFlow } from '@/hooks/flow-hooks';
|
3 |
import { ArrowLeftOutlined } from '@ant-design/icons';
|
4 |
import { Button, Flex, Space } from 'antd';
|
5 |
-
import { Link } from 'umi';
|
6 |
import { useSaveGraph, useSaveGraphBeforeOpeningDebugDrawer } from '../hooks';
|
7 |
import styles from './index.less';
|
8 |
|
@@ -15,6 +16,12 @@ const FlowHeader = ({ showChatDrawer }: IProps) => {
|
|
15 |
const handleRun = useSaveGraphBeforeOpeningDebugDrawer(showChatDrawer);
|
16 |
const { data } = useFetchFlow();
|
17 |
const { t } = useTranslate('flow');
|
|
|
|
|
|
|
|
|
|
|
|
|
18 |
|
19 |
return (
|
20 |
<>
|
@@ -37,8 +44,19 @@ const FlowHeader = ({ showChatDrawer }: IProps) => {
|
|
37 |
<Button type="primary" onClick={saveGraph}>
|
38 |
<b>{t('save')}</b>
|
39 |
</Button>
|
|
|
|
|
|
|
40 |
</Space>
|
41 |
</Flex>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
42 |
</>
|
43 |
);
|
44 |
};
|
|
|
1 |
+
import ChatOverviewModal from '@/components/api-service/chat-overview-modal';
|
2 |
+
import { useSetModalState, useTranslate } from '@/hooks/common-hooks';
|
3 |
import { useFetchFlow } from '@/hooks/flow-hooks';
|
4 |
import { ArrowLeftOutlined } from '@ant-design/icons';
|
5 |
import { Button, Flex, Space } from 'antd';
|
6 |
+
import { Link, useParams } from 'umi';
|
7 |
import { useSaveGraph, useSaveGraphBeforeOpeningDebugDrawer } from '../hooks';
|
8 |
import styles from './index.less';
|
9 |
|
|
|
16 |
const handleRun = useSaveGraphBeforeOpeningDebugDrawer(showChatDrawer);
|
17 |
const { data } = useFetchFlow();
|
18 |
const { t } = useTranslate('flow');
|
19 |
+
const {
|
20 |
+
visible: overviewVisible,
|
21 |
+
hideModal: hideOverviewModal,
|
22 |
+
showModal: showOverviewModal,
|
23 |
+
} = useSetModalState();
|
24 |
+
const { id } = useParams();
|
25 |
|
26 |
return (
|
27 |
<>
|
|
|
44 |
<Button type="primary" onClick={saveGraph}>
|
45 |
<b>{t('save')}</b>
|
46 |
</Button>
|
47 |
+
<Button type="primary" onClick={showOverviewModal}>
|
48 |
+
<b>{t('publish')}</b>
|
49 |
+
</Button>
|
50 |
</Space>
|
51 |
</Flex>
|
52 |
+
{overviewVisible && (
|
53 |
+
<ChatOverviewModal
|
54 |
+
visible={overviewVisible}
|
55 |
+
hideModal={hideOverviewModal}
|
56 |
+
id={id!}
|
57 |
+
idKey="canvasId"
|
58 |
+
></ChatOverviewModal>
|
59 |
+
)}
|
60 |
</>
|
61 |
);
|
62 |
};
|