S0025136190 9 miesięcy temu
rodzic
commit
a215d9c431

+ 14 - 10
src/apis/api.ts

@@ -24,17 +24,21 @@ axiosInstance.interceptors.request.use(
 // 响应拦截器
 axiosInstance.interceptors.response.use(
     (response: AxiosResponse) => {// 成功信息
-        const { data } = response;
-        if (data.code === 200) {// 成功
+        const { config, data } = response;
+        if (config.responseType === 'blob') {
             return Promise.resolve(data);
-        } else {// 失败
-            if (data.code === 401) {
-                LocalStorage.clear();
-                router.navigate({ pathname: '/login' }, { replace: true });
-                message.error('登录过期');
-                return Promise.reject();
-            } else {
-                return Promise.reject(data);
+        } else {
+            if (data.code === 200) {// 成功
+                return Promise.resolve(data);
+            } else {// 失败
+                if (data.code === 401) {
+                    LocalStorage.clear();
+                    router.navigate({ pathname: '/login' }, { replace: true });
+                    message.error('登录过期');
+                    return Promise.reject();
+                } else {
+                    return Promise.reject(data);
+                }
             }
         }
     },

+ 45 - 18
src/apis/index.ts

@@ -29,26 +29,26 @@ export type FetchAppIndexParams = {
 };
 
 export type CreateOrModifyApplicationApiParams = {
-    name: string, 
-    desc: string,  
+    name: string,
+    desc: string,
     prompt: string,
-    temperature: number, 
-    top_p: number,  
-    knowledge_ids: string[], 
-    param_desc: string, 
-    max_token: number, 
-    knowledge_info: { 
-        model: string, 
-        knowledge_ids: string[], 
-        slice_config_type: string, 
-        recall_method: string, 
-        slice_count: number, 
-        rerank_status: number, 
-        rerank_model_name: string, 
-        show_recall_result: boolean, 
+    temperature: number,
+    top_p: number,
+    knowledge_ids: string[],
+    param_desc: string,
+    max_token: number,
+    knowledge_info: {
+        model: string,
+        knowledge_ids: string[],
+        slice_config_type: string,
+        recall_method: string,
+        slice_count: number,
+        rerank_status: number,
+        rerank_model_name: string,
+        show_recall_result: boolean,
         recall_slice_splicing_method: string,
     },
-    questionList :[
+    questionList: [
         {
             question: string,
         }
@@ -74,6 +74,11 @@ export type ModifyDocumentApiParams = {
     parse_image: number
 };
 
+export type FetchDialogApiParams = {
+    pageNumber: number,
+    pageSize: number,
+};
+
 // Api函数类型
 export type LoginApi = (data: LoginApiParams) => Promise<any>;
 export type LogoutApi = () => Promise<any>;
@@ -96,6 +101,9 @@ export type FetchDocumentLibListApi = (data: FetchDocumentLibListApiParams) => P
 export type FetchDocumentLibApi = (id: string) => Promise<any>;
 export type ModifyDocumentLibApi = (id: string, data: ModifyDocumentApiParams) => Promise<any>;
 export type DeleteDocumentLibApi = (id: string) => Promise<any>;
+export type FetchApplicationDataLibApi = () => Promise<any>;
+export type FetchDialogListLibApi = (appId: string, data: FetchDialogApiParams) => Promise<any>;
+export type FetchDialogListLibAllApi = (data: FetchDialogApiParams) => Promise<any>;
 
 // 登录
 const loginApi: LoginApi = async (data) => {
@@ -147,7 +155,7 @@ const fetchIndexApi: FetchAppIndexApi = async (data) => {
     return api.post('/bigmodel/api/index', data);
 };
 
-// 编辑应用
+// 获取应用详情
 const fetchApplicationDetailApi: FetchApplicationDetailApi = async (appId) => {
     return api.get(`bigmodel/api/selectApplication/${appId}`);
 };
@@ -202,6 +210,22 @@ const deleteDocumentApi: DeleteDocumentLibApi = async (id) => {
     return api.delete(`bigmodel/api/delDocument/${id}`);
 };
 
+// 获取应用列表
+const fetchApplicationDataApi: FetchApplicationDataLibApi = async () => {
+    return api.get('bigmodel/api/application/list');
+};
+
+// 获取对话列表
+const fetchDialogListApi: FetchDialogListLibApi = async (appId, data) => {
+    return api.post(`bigmodel/api/dialog/${appId}`, data);
+};
+
+// 获取所有应用对话列表
+const fetchDialogAllListApi: FetchDialogListLibAllApi = async (data) => {
+    return api.post(`bigmodel/api/allDialog`, data);
+};
+
+
 export const apis = {
     login: loginApi,
     logout: logoutApi,
@@ -224,4 +248,7 @@ export const apis = {
     fetchDocumentDetailLibApi: fetchDocumentLibApi,
     modifyDocumentLibApi: modifyDocumentApi,
     deleteDocumentLibApi: deleteDocumentApi,
+    fetchApplicationDataLibApi: fetchApplicationDataApi,
+    fetchDialogListLibApi: fetchDialogListApi,
+    fetchDialogAllListLibApi: fetchDialogAllListApi,
 };

+ 149 - 2
src/pages/dataExport/index.tsx

@@ -1,26 +1,173 @@
 import * as React from 'react';
+import { useParams } from 'react-router-dom';
 import { observer } from 'mobx-react';
 import store from './store';
 import './style.less';
+import { Select, TableColumnsType, Table, Button, TablePaginationConfig } from 'antd';
+import { CloudDownloadOutlined } from '@ant-design/icons';
+import dayjs from 'dayjs';
+import { Record } from './types';
+import { apis } from '@/apis';
+import { set } from 'mobx';
+import { downloadFile } from '@/utils';
+import api from '@/apis/api';
+
+const { Option } = Select;
 
 const DataExport: React.FC = () => {
     const {
         state,
         init,
+        onChangePagination,
         reset
     } = store;
+
     const {
-        pageLoading
+        pageLoading,
+        list,
+        appId,
+        page,
     } = state;
 
     React.useEffect(() => {
         init();
+        fetchApplicationDataApi();
         return () => reset();
     }, []);
 
+    type AppList = {
+        label: string;
+        value: string,
+    }[];
+
+    const [loading, setLoading] = React.useState<boolean>(false);
+    const [applicationList, setApplicationList] = React.useState<AppList>([]);
+
+    // 获取应用列表
+    const fetchApplicationDataApi = async () => {
+        try {
+            setLoading(true);
+            const res = await apis.fetchApplicationDataLibApi();
+            const list = res.data.map((item: any) => {
+                return {
+                    label: item.name,
+                    value: item.appId,
+                }
+            });
+            setApplicationList(list);
+        } catch (error: any) {
+            setLoading(false);
+            console.error(error);
+        }
+    }
+
+    const columns: TableColumnsType<Record> = [
+        {
+            title: '序号',
+            dataIndex: 'index',
+            width: 80,
+            render: (text, record, index) => {
+                return index + 1;
+            }
+        },
+        {
+            title: '聊天标题',
+            dataIndex: 'dialog_name',
+        },
+        {
+            title: '消息长度',
+            dataIndex: 'length',
+        },
+        {
+            title: '聊天时间',
+            dataIndex: 'create_time',
+            width: 200,
+            render: (text) => {
+                if (text) {
+                    return dayjs(text).format('YYYY-MM-DD HH:mm:ss');
+                } else {
+                    return '--';
+                }
+            }
+        },
+        {
+            title: '操作',
+            dataIndex: 'operation',
+            width: 150,
+            fixed: 'right',
+            render: (text, record) => {
+                return (
+                    <a
+                        style={{ marginRight: 16 }}
+                        onClick={async () => {
+                            try {
+                                const blob = await api.post(`/bigmodel/api/dialog/export/${record.id}`, {}, { responseType: 'blob' });
+                                const fileName = `${record.dialog_name}.xlsx`;
+                                downloadFile(blob, fileName);
+                            } catch (error) {
+                                console.error(error);
+                            }
+                        }}
+                    >
+                        <CloudDownloadOutlined />
+                    </a >
+                )
+            }
+        }
+    ];
+
+    const paginationConfig: TablePaginationConfig = {
+        // 显示数据总量
+        showTotal: (total: number) => {
+            return `共 ${total} 条`;
+        },
+        // 展示分页条数切换
+        showSizeChanger: true,
+        // 指定每页显示条数
+        pageSizeOptions: ['10', '20', '50', '100'],
+        // 快速跳转至某页
+        showQuickJumper: true,
+        current: page.pageNumber,
+        pageSize: page.pageSize,
+        total: page.total,
+        onChange: async (page, pageSize) => {
+            await onChangePagination(page, pageSize);
+        },
+    };
+
     return (
         <div className='dataExport'>
-            数据导出
+            <div style={{ display: 'flex', justifyContent: 'space-between', alignContent: 'center' }}>
+                
+                <Select
+                    style={{ width: '20%' }}
+                    placeholder='请选择应用'
+                    allowClear={true}
+                    value={appId}
+                    onChange={(value) => {
+                            init(value); 
+                    }}
+                >
+                    {
+                        applicationList.map((item, index) => {
+                            return <Option value={item.value} key={index}>
+                                {item.label}
+                            </Option>
+                        })
+                    }
+                </Select>
+            </div>
+
+            <div className='dataExport-content'>
+                <Table
+                    scroll={{ x: 'max-content' }}
+                    rowKey={(record) => record.id}
+                    loading={pageLoading}
+                    columns={columns}
+                    dataSource={list}
+                    pagination={paginationConfig}
+                />
+            </div>
         </div>
     );
 };

+ 82 - 2
src/pages/dataExport/store.ts

@@ -5,6 +5,13 @@ import { State, ReadonlyState, StateAction, DataExportStore } from './types';
 // 定义状态
 const stateGenerator = (): ReadonlyState => ({
     pageLoading: false,
+    list: [],
+    appId: '',
+    page: {
+        pageNumber: 1,
+        pageSize: 10,
+        total: 0,
+    },
 });
 
 // 修改状态
@@ -13,6 +20,16 @@ const stateActionsGenerator = (state: State): StateAction => {
         setPageLoading: (loading) => {
             state.pageLoading = loading;
         },
+        setList: (list) => {
+            state.list = list;
+        },
+        setAppId: (appId) => {
+            state.appId = appId;
+        },
+        setPage: (page) => {
+            state.page = page;
+        },
+
     };
 };
 
@@ -22,24 +39,87 @@ const useDataExportStore = (): DataExportStore => {
     const actions = stateActionsGenerator(state);
 
     const api = {
+         // 获取应用聊天列表
+         fetchDocumentLibList: async () => {
+            actions.setPageLoading(true);
+            try {
+                const data = {
+                    pageNumber: state.page.pageNumber,
+                    pageSize: state.page.pageSize,
+                };
+                const res = await apis.fetchDialogListLibApi(state.appId, data);
+                actions.setList(res.rows);
+                actions.setPage({
+                    ...state.page,
+                    total: res.total,
+                });
+                
+            } catch (error: any) {
+                console.error(error);
+            } finally {
+                actions.setPageLoading(false);
+            }
+        },
 
+        // 获取所有聊天列表
+        fetchDocumentLibAllList: async () => {
+            actions.setPageLoading(true);
+            try {
+                const data = {
+                    pageNumber: state.page.pageNumber,
+                    pageSize: state.page.pageSize,
+                };
+                const res = await apis.fetchDialogAllListLibApi(data);
+                actions.setList(res.rows);
+                actions.setPage({
+                    ...state.page,
+                    total: res.total,
+                });
+            } catch (error: any) {
+                console.error(error);
+            } finally {
+                actions.setPageLoading(false);
+            }
+        },
     }
 
-    // 初始渲染
-    const init = () => {
+    // 更改分页
+    const onChangePagination: DataExportStore['onChangePagination'] = async (pageNumber, pageSize) => {
+        actions.setPage({
+            ...state.page,
+            pageNumber: pageNumber,
+            pageSize: pageSize,
+        });
+        // 获取知识库列表
+        init();
+    }
 
+    // 初始渲染
+    const init: DataExportStore['init'] = (appId) => {
+        // 获取知识列表
+        if(appId){
+            actions.setAppId(appId);
+            api.fetchDocumentLibList();
+        }else{
+            api.fetchDocumentLibAllList();
+        }
     }
 
     // 状态重置
     const reset = () => {
         const initialPageLoading = stateGenerator().pageLoading;
+        const initialPage = stateGenerator().page;
 
         actions.setPageLoading(initialPageLoading);
+        actions.setList([]);
+        actions.setAppId('');
+        actions.setPage(initialPage);
     }
 
     return {
         state,
         init,
+        onChangePagination,
         reset
     };
 };

+ 7 - 0
src/pages/dataExport/style.less

@@ -3,4 +3,11 @@
   height: 100%;
   background: #FFFFFF;
   border-radius: @border-radius-base;
+}
+
+.dataExport-content {
+  width: 100%;
+  background: #FFFFFF;
+  border-radius: @border-radius-base;
+  padding-top: 20px;
 }

+ 27 - 1
src/pages/dataExport/types.ts

@@ -1,6 +1,28 @@
+import { set } from "mobx";
+
+export type Record = {
+    id: string,
+    appId: string,
+    knowledgeIdd: string,
+    userId: string,
+    did: string,
+    dialog_name: string,
+    dialog_id: string,
+    type: string,
+    content: string,
+    create_time: string
+};
+
 // 定义状态
 export type State = {
     pageLoading: boolean,
+    list: Record[],
+    appId: string,
+    page: {
+        pageNumber: number,
+        pageSize: number,
+        total: number,
+    },
 };
 
 // 只读状态
@@ -9,11 +31,15 @@ export type ReadonlyState = Readonly<State>;
 // 修改状态
 export type StateAction = {
     setPageLoading: (loading: boolean) => void,
+    setList: (list: State['list']) => void,
+    setAppId: (appId: string) => void,
+    setPage: (page: State['page']) => void,
 };
 
 // 仓库类型
 export type DataExportStore = {
     state: ReadonlyState,
-    init: () => void,
+    init: (appId?: string) => void,
+    onChangePagination: (pageNumber: number, pageSize: number) => Promise<any>,
     reset: () => void,
 };

+ 11 - 0
src/utils/index.ts

@@ -1,4 +1,15 @@
 // 正则表达式
 export const regex = {
     password: /^[a-zA-Z0-9]{6,16}$/,// 密码
+};
+
+export const downloadFile = (blob: any, fileName: string) => {
+    const downUrl = window.URL.createObjectURL(new Blob([blob]));
+    const elementA = document.createElement('a');
+    elementA.href = downUrl;
+    elementA.download = fileName;
+    elementA.style.display = 'none';
+    document.body.appendChild(elementA);
+    elementA.click();
+    document.body.removeChild(elementA);
 };