浏览代码

feat: save the selected parser to the backend on the upload file page and upload document (#54)

* feat: add pagination to document table

* feat: fetch document list by page

* feat: poll the document list

* feat: upload document

* feat: save the selected parser to the backend on the upload file page
tags/v0.1.0
balibabu 1年前
父节点
当前提交
f305776217

+ 23
- 0
web/src/assets/svg/select-files-end.svg 查看文件

@@ -0,0 +1,23 @@
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_304_1382)">
<path
d="M0 16C0 7.16344 7.16344 0 16 0C24.8366 0 32 7.16344 32 16C32 24.8366 24.8366 32 16 32C7.16344 32 0 24.8366 0 16Z"
fill="#F9F5FF" />
<path
d="M1 16C1 7.71573 7.71573 1 16 1C24.2843 1 31 7.71573 31 16C31 24.2843 24.2843 31 16 31C7.71573 31 1 24.2843 1 16Z"
fill="#7F56D9" />
<path
d="M1 16C1 7.71573 7.71573 1 16 1C24.2843 1 31 7.71573 31 16C31 24.2843 24.2843 31 16 31C7.71573 31 1 24.2843 1 16Z"
stroke="#7F56D9" stroke-width="2" />
<path fill-rule="evenodd" clip-rule="evenodd"
d="M22.7951 9.85338L13.2484 19.0667L10.7151 16.3601C10.2484 15.9201 9.51509 15.8934 8.98176 16.2667C8.46176 16.6534 8.31509 17.3334 8.63509 17.8801L11.6351 22.7601C11.9284 23.2134 12.4351 23.4934 13.0084 23.4934C13.5551 23.4934 14.0751 23.2134 14.3684 22.7601C14.8484 22.1334 24.0084 11.2134 24.0084 11.2134C25.2084 9.98672 23.7551 8.90672 22.7951 9.84005V9.85338Z"
fill="white" />
</g>
<defs>
<clipPath id="clip0_304_1382">
<path
d="M0 16C0 7.16344 7.16344 0 16 0C24.8366 0 32 7.16344 32 16C32 24.8366 24.8366 32 16 32C7.16344 32 0 24.8366 0 16Z"
fill="white" />
</clipPath>
</defs>
</svg>

+ 35
- 0
web/src/assets/svg/select-files-start.svg 查看文件

@@ -0,0 +1,35 @@
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
<g filter="url(#filter0_d_304_382)">
<g clip-path="url(#clip0_304_382)">
<path
d="M4 20C4 11.1634 11.1634 4 20 4C28.8366 4 36 11.1634 36 20C36 28.8366 28.8366 36 20 36C11.1634 36 4 28.8366 4 20Z"
fill="#F9F5FF" />
<path
d="M5 20C5 11.7157 11.7157 5 20 5C28.2843 5 35 11.7157 35 20C35 28.2843 28.2843 35 20 35C11.7157 35 5 28.2843 5 20Z"
fill="#7F56D9" />
<path
d="M5 20C5 11.7157 11.7157 5 20 5C28.2843 5 35 11.7157 35 20C35 28.2843 28.2843 35 20 35C11.7157 35 5 28.2843 5 20Z"
stroke="#7F56D9" stroke-width="2" />
<circle cx="20" cy="20" r="5" fill="white" />
</g>
</g>
<defs>
<filter id="filter0_d_304_382" x="0" y="0" width="40" height="40" filterUnits="userSpaceOnUse"
color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix" />
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
result="hardAlpha" />
<feMorphology radius="4" operator="dilate" in="SourceAlpha" result="effect1_dropShadow_304_382" />
<feOffset />
<feComposite in2="hardAlpha" operator="out" />
<feColorMatrix type="matrix" values="0 0 0 0 0.619152 0 0 0 0 0.465529 0 0 0 0 0.930549 0 0 0 0.24 0" />
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_304_382" />
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_304_382" result="shape" />
</filter>
<clipPath id="clip0_304_382">
<path
d="M4 20C4 11.1634 11.1634 4 20 4C28.8366 4 36 11.1634 36 20C36 28.8366 28.8366 36 20 36C11.1634 36 4 28.8366 4 20Z"
fill="white" />
</clipPath>
</defs>
</svg>

+ 25
- 14
web/src/components/deleting-confirm/index.tsx 查看文件

@@ -8,20 +8,31 @@ interface IProps {
onCancel?: (...args: any[]) => any;
}

export const showDeleteConfirm = ({ onOk, onCancel }: IProps) => {
confirm({
title: 'Are you sure delete this item?',
icon: <ExclamationCircleFilled />,
content: 'Some descriptions',
okText: 'Yes',
okType: 'danger',
cancelText: 'No',
onOk() {
onOk?.();
},
onCancel() {
onCancel?.();
},
export const showDeleteConfirm = ({
onOk,
onCancel,
}: IProps): Promise<number> => {
return new Promise((resolve, reject) => {
confirm({
title: 'Are you sure delete this item?',
icon: <ExclamationCircleFilled />,
content: 'Some descriptions',
okText: 'Yes',
okType: 'danger',
cancelText: 'No',
async onOk() {
try {
const ret = await onOk?.();
resolve(ret);
console.info(ret);
} catch (error) {
reject(error);
}
},
onCancel() {
onCancel?.();
},
});
});
};


+ 41
- 1
web/src/hooks/knowledgeHook.ts 查看文件

@@ -1,4 +1,6 @@
import { useSearchParams } from 'umi';
import showDeleteConfirm from '@/components/deleting-confirm';
import { IKnowledge } from '@/interfaces/database/knowledge';
import { useDispatch, useSearchParams, useSelector } from 'umi';

export const useKnowledgeBaseId = (): string => {
const [searchParams] = useSearchParams();
@@ -6,3 +8,41 @@ export const useKnowledgeBaseId = (): string => {

return knowledgeBaseId || '';
};

export const useDeleteDocumentById = (): {
removeDocument: (documentId: string) => Promise<number>;
} => {
const dispatch = useDispatch();
const knowledgeBaseId = useKnowledgeBaseId();

const removeDocument = (documentId: string) => () => {
return dispatch({
type: 'kFModel/document_rm',
payload: {
doc_id: documentId,
kb_id: knowledgeBaseId,
},
});
};

const onRmDocument = (documentId: string): Promise<number> => {
return showDeleteConfirm({ onOk: removeDocument(documentId) });
};

return {
removeDocument: onRmDocument,
};
};

export const useGetDocumentDefaultParser = (knowledgeBaseId: string) => {
const data: IKnowledge[] = useSelector(
(state: any) => state.knowledgeModel.data,
);

const item = data.find((x) => x.id === knowledgeBaseId);

return {
defaultParserId: item?.parser_id ?? '',
parserConfig: item?.parser_config ?? '',
};
};

+ 8
- 0
web/src/interfaces/common.ts 查看文件

@@ -0,0 +1,8 @@
export interface Pagination {
current: number;
pageSize: number;
}

export interface BaseState {
pagination: Pagination;
}

+ 41
- 0
web/src/interfaces/database/knowledge.ts 查看文件

@@ -1,5 +1,33 @@
import { RunningStatus } from '@/constants/knowledge';

// knowledge base
export interface IKnowledge {
avatar?: any;
chunk_num: number;
create_date: string;
create_time: number;
created_by: string;
description: string;
doc_num: number;
id: string;
name: string;
parser_config: Parserconfig;
parser_id: string;
permission: string;
similarity_threshold: number;
status: string;
tenant_id: string;
token_num: number;
update_date: string;
update_time: number;
vector_similarity_weight: number;
}

export interface Parserconfig {
from_page: number;
to_page: number;
}

export interface IKnowledgeFile {
chunk_num: number;
create_date: string;
@@ -24,3 +52,16 @@ export interface IKnowledgeFile {
update_date: string;
update_time: number;
}

export interface ITenantInfo {
asr_id: string;
embd_id: string;
img2txt_id: string;
llm_id: string;
name: string;
parser_ids: string;
role: string;
tenant_id: string;
chat_id: string;
speech2text_id: string;
}

+ 1
- 0
web/src/less/variable.less 查看文件

@@ -5,6 +5,7 @@
@gray3: rgba(52, 48, 62, 1);
@gray8: rgba(165, 163, 169, 1);
@gray11: rgba(232, 232, 234, 1);
@purple: rgba(127, 86, 217, 1);

@fontSize12: 12px;
@fontSize14: 14px;

+ 65
- 0
web/src/pages/add-knowledge/components/knowledge-dataset/knowledge-upload-file/index.less 查看文件

@@ -0,0 +1,65 @@
.uploadWrapper {
display: flex;
flex-direction: column;
padding: 32px;
height: 100%;
.backToList {
padding-bottom: 60px;
}
.footer {
text-align: right;
.nextButton {
background-color: @purple;
}
}
.uploadContent {
flex: 1;
padding-top: 60px;
}
.uploader {
display: block;
height: 200px;
}
.hiddenUploader {
:global(.ant-upload-drag) {
display: none;
}
}
.fileIcon {
font-size: 40px;
align-items: end;
}
.deleteIcon {
font-size: 20px;
}
.uploaderItem {
margin-top: 16px;
:global(.ant-card-body) {
padding: 16px;
}
}
.uploaderItemProgress {
padding-left: 50px;
}
.uploaderItemTextWrapper {
flex: 1;
text-align: left;
padding-left: 10px;
}
}

.progressWrapper {
text-align: center;
}

.progress {
width: 50%;
margin: 0;
}

.selectFilesText {
transform: translateX(10%);
}
.changeSpecificCategoryText {
transform: translateX(30%);
}

+ 262
- 1
web/src/pages/add-knowledge/components/knowledge-dataset/knowledge-upload-file/index.tsx 查看文件

@@ -1,5 +1,266 @@
import { ReactComponent as SelectFilesEndIcon } from '@/assets/svg/select-files-end.svg';
import { ReactComponent as SelectFilesStartIcon } from '@/assets/svg/select-files-start.svg';
import {
useDeleteDocumentById,
useGetDocumentDefaultParser,
useKnowledgeBaseId,
} from '@/hooks/knowledgeHook';
import { ITenantInfo } from '@/interfaces/database/knowledge';
import uploadService from '@/services/uploadService';
import {
ArrowLeftOutlined,
DeleteOutlined,
EditOutlined,
FileDoneOutlined,
InboxOutlined,
} from '@ant-design/icons';
import {
Button,
Card,
Flex,
Popover,
Progress,
Radio,
RadioChangeEvent,
Space,
Upload,
UploadFile,
UploadProps,
} from 'antd';
import classNames from 'classnames';
import { ReactElement, useEffect, useState } from 'react';
import { Nullable } from 'typings';
import { Link, useDispatch, useNavigate, useSelector } from 'umi';

import { KnowledgeRouteKey } from '@/constants/knowledge';
import styles from './index.less';

const { Dragger } = Upload;

type UploadRequestOption = Parameters<
NonNullable<UploadProps['customRequest']>
>[0];

const UploaderItem = ({
file,
actions,
isUpload,
parserArray,
}: {
isUpload: boolean;
originNode: ReactElement;
file: UploadFile;
fileList: object[];
parserArray: string[];
actions: { download: Function; preview: Function; remove: any };
}) => {
const { parserConfig, defaultParserId } = useGetDocumentDefaultParser(
file?.response?.kb_id,
);
const { removeDocument } = useDeleteDocumentById();
const [value, setValue] = useState(defaultParserId);
const dispatch = useDispatch();

const documentId = file?.response?.id;

const onChange = (e: RadioChangeEvent) => {
const val = e.target.value;
setValue(val);
saveParser(val);
};

const content = (
<Radio.Group onChange={onChange} value={value}>
<Space direction="vertical">
{parserArray.map((x) => (
<Radio value={x} key={x}>
{x}
</Radio>
))}
</Space>
</Radio.Group>
);

const handleRemove = async () => {
const ret: any = await removeDocument(documentId);
if (ret === 0) {
actions?.remove();
}
};

const saveParser = (parserId: string) => {
dispatch({
type: 'kFModel/document_change_parser',
payload: {
parser_id: parserId,
doc_id: documentId,
parser_config: parserConfig,
},
});
};

useEffect(() => {
setValue(defaultParserId);
}, [defaultParserId]);

return (
<Card className={styles.uploaderItem}>
<Flex justify="space-between">
<FileDoneOutlined className={styles.fileIcon} />
<section className={styles.uploaderItemTextWrapper}>
<div>
<b>{file.name}</b>
</div>
<span>{file.size}</span>
</section>
{isUpload ? (
<DeleteOutlined
className={styles.deleteIcon}
onClick={handleRemove}
/>
) : (
<Popover content={content} placement="bottom">
<EditOutlined />
</Popover>
)}
</Flex>
<Flex>
<Progress
showInfo={false}
percent={100}
className={styles.uploaderItemProgress}
strokeColor="
rgba(127, 86, 217, 1)
"
/>
<span>100%</span>
</Flex>
</Card>
);
};

const KnowledgeUploadFile = () => {
return <div>KnowledgeUploadFile</div>;
const knowledgeBaseId = useKnowledgeBaseId();
const [isUpload, setIsUpload] = useState(true);
const dispatch = useDispatch();
const tenantIfo: Nullable<ITenantInfo> = useSelector(
(state: any) => state.settingModel.tenantIfo,
);
const navigate = useNavigate();

const parserArray = tenantIfo?.parser_ids.split(',') ?? [];

const createRequest: (props: UploadRequestOption) => void = async function ({
file,
onSuccess,
onError,
onProgress,
}) {
const { data } = await uploadService.uploadFile(file, knowledgeBaseId);
if (data.retcode === 0) {
onSuccess && onSuccess(data.data);
} else {
onError && onError(data.data);
}
};

const props: UploadProps = {
name: 'file',
multiple: true,
itemRender(originNode, file, fileList, actions) {
return (
<UploaderItem
isUpload={isUpload}
file={file}
fileList={fileList}
originNode={originNode}
actions={actions}
parserArray={parserArray}
></UploaderItem>
);
},
customRequest: createRequest,
onDrop(e) {
console.log('Dropped files', e.dataTransfer.files);
},
};

const handleNextClick = () => {
if (!isUpload) {
navigate(`/knowledge/${KnowledgeRouteKey.Dataset}?id=${knowledgeBaseId}`);
} else {
setIsUpload(false);
}
};

useEffect(() => {
dispatch({
type: 'settingModel/getTenantInfo',
});
}, []);

return (
<div className={styles.uploadWrapper}>
<section>
<Space className={styles.backToList}>
<ArrowLeftOutlined />
<Link to={`/knowledge/dataset?id=${knowledgeBaseId}`}>
Back to select files
</Link>
</Space>
<div className={styles.progressWrapper}>
<Flex align="center" justify="center">
<SelectFilesStartIcon></SelectFilesStartIcon>
<Progress
percent={100}
showInfo={false}
className={styles.progress}
strokeColor="
rgba(127, 86, 217, 1)
"
/>
<SelectFilesEndIcon></SelectFilesEndIcon>
</Flex>
<Flex justify="space-around">
<p className={styles.selectFilesText}>
<b>Select files</b>
</p>
<p className={styles.changeSpecificCategoryText}>
<b>Change specific category</b>
</p>
</Flex>
</div>
</section>
<section className={styles.uploadContent}>
<Dragger
{...props}
className={classNames(styles.uploader, {
[styles.hiddenUploader]: !isUpload,
})}
>
<p className="ant-upload-drag-icon">
<InboxOutlined />
</p>
<p className="ant-upload-text">
Click or drag file to this area to upload
</p>
<p className="ant-upload-hint">
Support for a single or bulk upload. Strictly prohibited from
uploading company data or other banned files.
</p>
</Dragger>
</section>
<section className={styles.footer}>
<Button
type="primary"
className={styles.nextButton}
onClick={handleNextClick}
>
Next
</Button>
</section>
</div>
);
};

export default KnowledgeUploadFile;

+ 65
- 28
web/src/pages/add-knowledge/components/knowledge-file/index.tsx 查看文件

@@ -1,5 +1,9 @@
import { KnowledgeRouteKey } from '@/constants/knowledge';
import { useKnowledgeBaseId } from '@/hooks/knowledgeHook';
import {
useDeleteDocumentById,
useKnowledgeBaseId,
} from '@/hooks/knowledgeHook';
import { Pagination } from '@/interfaces/common';
import { IKnowledgeFile } from '@/interfaces/database/knowledge';
import { getOneNamespaceEffectsLoading } from '@/utils/stroreUtil';
import { PlusOutlined, SearchOutlined } from '@ant-design/icons';
@@ -15,8 +19,8 @@ import {
Tag,
} from 'antd';
import type { ColumnsType } from 'antd/es/table';
import { debounce } from 'lodash';
import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { PaginationProps } from 'antd/lib';
import React, { useEffect, useMemo, useState } from 'react';
import { useDispatch, useNavigate, useSelector } from 'umi';
import CreateEPModal from './createEFileModal';
import styles from './index.less';
@@ -30,50 +34,90 @@ const KnowledgeFile = () => {
const dispatch = useDispatch();
const kFModel = useSelector((state: any) => state.kFModel);
const effects = useSelector((state: any) => state.loading.effects);
const { data } = kFModel;
const { data, total } = kFModel;
const knowledgeBaseId = useKnowledgeBaseId();
const { removeDocument } = useDeleteDocumentById();
const loading = getOneNamespaceEffectsLoading('kFModel', effects, [
'getKfList',
'updateDocumentStatus',
]);
const [inputValue, setInputValue] = useState('');
const [doc_id, setDocId] = useState('0');
const [parser_id, setParserId] = useState('0');
let navigate = useNavigate();
const getKfList = (keywords?: string) => {
const getKfList = () => {
const payload = {
kb_id: knowledgeBaseId,
keywords,
};
if (!keywords) {
delete payload.keywords;
}
dispatch({
type: 'kFModel/getKfList',
payload,
});
};
const throttledGetDocumentList = () => {
dispatch({
type: 'kFModel/throttledGetDocumentList',
payload: knowledgeBaseId,
});
};
const setPagination = (pageNumber = 1, pageSize?: number) => {
const pagination: Pagination = {
current: pageNumber,
} as Pagination;
if (pageSize) {
pagination.pageSize = pageSize;
}
dispatch({
type: 'kFModel/setPagination',
payload: pagination,
});
};
const onPageChange: PaginationProps['onChange'] = (pageNumber, pageSize) => {
setPagination(pageNumber, pageSize);
getKfList();
};
const pagination: PaginationProps = useMemo(() => {
return {
showQuickJumper: true,
total,
showSizeChanger: true,
current: kFModel.pagination.currentPage,
pageSize: kFModel.pagination.pageSize,
pageSizeOptions: [1, 2, 10, 20, 50, 100],
onChange: onPageChange,
};
}, [total, kFModel.pagination]);
useEffect(() => {
if (knowledgeBaseId) {
getKfList();
dispatch({
type: 'kFModel/pollGetDocumentList-start',
payload: knowledgeBaseId,
});
}
return () => {
dispatch({
type: 'kFModel/pollGetDocumentList-stop',
});
};
}, [knowledgeBaseId]);
const debounceChange = debounce(getKfList, 300);
const debounceCallback = useCallback(
(value: string) => debounceChange(value),
[],
);
const handleInputChange = (
e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>,
) => {
const value = e.target.value;
setInputValue(value);
debounceCallback(e.target.value);
dispatch({ type: 'kFModel/setSearchString', payload: value });
setPagination();
throttledGetDocumentList();
};
const onChangeStatus = (e: boolean, doc_id: string) => {
dispatch({
type: 'kFModel/updateDocumentStatus',
@@ -85,13 +129,7 @@ const KnowledgeFile = () => {
});
};
const onRmDocument = () => {
dispatch({
type: 'kFModel/document_rm',
payload: {
doc_id,
kb_id: knowledgeBaseId,
},
});
removeDocument(doc_id);
};
const showCEFModal = () => {
dispatch({
@@ -226,7 +264,6 @@ const KnowledgeFile = () => {
key: 'action',
render: (_, record) => (
<ParsingActionCell
documentId={doc_id}
knowledgeBaseId={knowledgeBaseId}
setDocumentAndParserId={setDocumentAndParserId(record)}
record={record}
@@ -248,12 +285,12 @@ const KnowledgeFile = () => {
<div className={styles.filter}>
<Space>
<h3>Total</h3>
<Tag color="purple">100 files</Tag>
<Tag color="purple">{total} files</Tag>
</Space>
<Space>
<Input
placeholder="Seach your files"
value={inputValue}
value={kFModel.searchString}
style={{ width: 220 }}
allowClear
onChange={handleInputChange}
@@ -272,7 +309,7 @@ const KnowledgeFile = () => {
columns={finalColumns}
dataSource={data}
loading={loading}
pagination={false}
pagination={pagination}
scroll={{ scrollToFirstRowOnChange: true, x: true, y: 'fill' }}
/>
<CreateEPModal getKfList={getKfList} kb_id={knowledgeBaseId} />

+ 44
- 9
web/src/pages/add-knowledge/components/knowledge-file/model.ts 查看文件

@@ -1,3 +1,4 @@
import { BaseState } from '@/interfaces/common';
import { IKnowledgeFile } from '@/interfaces/database/knowledge';
import kbService from '@/services/kbService';
import { message } from 'antd';
@@ -6,14 +7,16 @@ import pick from 'lodash/pick';
import { Nullable } from 'typings';
import { DvaModel } from 'umi';
export interface KFModelState {
export interface KFModelState extends BaseState {
isShowCEFwModal: boolean;
isShowTntModal: boolean;
isShowSegmentSetModal: boolean;
isShowRenameModal: boolean;
tenantIfo: any;
data: IKnowledgeFile[];
total: number;
currentRecord: Nullable<IKnowledgeFile>;
searchString: string;
}
const model: DvaModel<KFModelState> = {
@@ -25,7 +28,13 @@ const model: DvaModel<KFModelState> = {
isShowRenameModal: false,
tenantIfo: {},
data: [],
total: 0,
currentRecord: null,
searchString: '',
pagination: {
current: 1,
pageSize: 10,
},
},
reducers: {
updateState(state, { payload }) {
@@ -40,6 +49,12 @@ const model: DvaModel<KFModelState> = {
setCurrentRecord(state, { payload }) {
return { ...state, currentRecord: payload };
},
setSearchString(state, { payload }) {
return { ...state, searchString: payload };
},
setPagination(state, { payload }) {
return { ...state, pagination: { ...state.pagination, ...payload } };
},
},
subscriptions: {
setup({ dispatch, history }) {
@@ -69,22 +84,41 @@ const model: DvaModel<KFModelState> = {
callback && callback(res);
}
},
*getKfList({ payload = {} }, { call, put }) {
const { data, response } = yield call(
kbService.get_document_list,
payload,
);
const { retcode, data: res, retmsg } = data;
*getKfList({ payload = {} }, { call, put, select }) {
const state: KFModelState = yield select((state: any) => state.kFModel);
const requestBody = {
...payload,
page: state.pagination.current,
page_size: state.pagination.pageSize,
};
if (state.searchString) {
requestBody['keywords'] = state.searchString;
}
const { data } = yield call(kbService.get_document_list, requestBody);
const { retcode, data: res } = data;
if (retcode === 0) {
yield put({
type: 'updateState',
payload: {
data: res,
data: res.docs,
total: res.total,
},
});
}
},
throttledGetDocumentList: [
function* ({ payload }, { call, put }) {
yield put({ type: 'getKfList', payload: { kb_id: payload } });
},
{ type: 'throttle', ms: 1000 }, // TODO: Provide type support for this effect
],
pollGetDocumentList: [
function* ({ payload }, { call, put }) {
yield put({ type: 'getKfList', payload: { kb_id: payload } });
},
{ type: 'poll', delay: 5000 }, // TODO: Provide type support for this effect
],
*updateDocumentStatus({ payload = {} }, { call, put }) {
const { data, response } = yield call(
kbService.document_change_status,
@@ -106,11 +140,12 @@ const model: DvaModel<KFModelState> = {
const { retcode, data: res, retmsg } = data;
if (retcode === 0) {
message.success('删除成功!');
put({
yield put({
type: 'getKfList',
payload: { kb_id: payload.kb_id },
});
}
return retcode;
},
*document_rename({ payload = {} }, { call, put }) {
const { data } = yield call(

+ 1
- 2
web/src/pages/add-knowledge/components/knowledge-file/parsing-action-cell/index.tsx 查看文件

@@ -5,19 +5,18 @@ import { Button, Dropdown, MenuProps, Space, Tooltip } from 'antd';
import { useDispatch } from 'umi';

interface IProps {
documentId: string;
knowledgeBaseId: string;
record: IKnowledgeFile;
setDocumentAndParserId: () => void;
}

const ParsingActionCell = ({
documentId,
knowledgeBaseId,
record,
setDocumentAndParserId,
}: IProps) => {
const dispatch = useDispatch();
const documentId = record.id;

const removeDocument = () => {
dispatch({

+ 1
- 2
web/src/pages/add-knowledge/components/knowledge-file/segmentSetModal.tsx 查看文件

@@ -18,8 +18,7 @@ const SegmentSetModal: React.FC<kFProps> = ({
const kFModel = useSelector((state: any) => state.kFModel);
const settingModel = useSelector((state: any) => state.settingModel);
const [selectedTag, setSelectedTag] = useState('');
const { tenantIfo = {} } = settingModel;
const { parser_ids = '' } = tenantIfo;
const parser_ids = settingModel?.tenantIfo?.parser_ids ?? '';
const { isShowSegmentSetModal } = kFModel;
const { t } = useTranslation();

+ 7
- 4
web/src/pages/add-knowledge/components/knowledge-file/upload.tsx 查看文件

@@ -1,7 +1,8 @@
import { useKnowledgeBaseId } from '@/hooks/knowledgeHook';
import uploadService from '@/services/uploadService';
import type { UploadProps } from 'antd';
import { Button, Upload } from 'antd';
import React from 'react';
import { Link } from 'umi';
interface PropsType {
kb_id: string;
getKfList: () => void;
@@ -12,6 +13,8 @@ type UploadRequestOption = Parameters<
>[0];
const FileUpload: React.FC<PropsType> = ({ kb_id, getKfList }) => {
const knowledgeBaseId = useKnowledgeBaseId();
const createRequest: (props: UploadRequestOption) => void = async function ({
file,
onSuccess,
@@ -30,9 +33,9 @@ const FileUpload: React.FC<PropsType> = ({ kb_id, getKfList }) => {
showUploadList: false,
};
return (
<Upload {...uploadProps}>
<Button type="link">导入文件</Button>
</Upload>
// <Upload {...uploadProps}>
<Link to={`/knowledge/dataset/upload?id=${knowledgeBaseId}`}>导入文件</Link>
// </Upload>
);
};

+ 1
- 2
web/src/pages/add-knowledge/components/knowledge-sidebar/index.tsx 查看文件

@@ -75,7 +75,6 @@ const KnowledgeSidebar = () => {
useEffect(() => {
const widthSize = () => {
const width = getWidth();
console.log(width);

setWindowWidth(width);
};
@@ -106,7 +105,7 @@ const KnowledgeSidebar = () => {
[styles.defaultWidth]: windowWidth.width > 957,
[styles.minWidth]: windowWidth.width <= 957,
})}
inlineCollapsed={collapsed}
// inlineCollapsed={collapsed}
items={items}
onSelect={handleSelect}
/>

+ 1
- 1
web/src/pages/add-knowledge/index.less 查看文件

@@ -13,6 +13,6 @@
.content {
background-color: white;
margin-top: 16px;
// flex: 1;
flex: 1;
}
}

+ 4
- 14
web/src/pages/setting/model.ts 查看文件

@@ -1,6 +1,8 @@
import { ITenantInfo } from '@/interfaces/database/knowledge';
import userService from '@/services/userService';
import authorizationUtil from '@/utils/authorizationUtil';
import { message } from 'antd';
import { Nullable } from 'typings';
import { DvaModel } from 'umi';
export interface SettingModelState {
@@ -9,7 +11,7 @@ export interface SettingModelState {
isShowSAKModal: boolean;
isShowSSModal: boolean;
llm_factory: string;
tenantIfo: any;
tenantIfo: Nullable<ITenantInfo>;
llmInfo: any;
myLlm: any[];
factoriesList: any[];
@@ -23,7 +25,7 @@ const model: DvaModel<SettingModelState> = {
isShowSAKModal: false,
isShowSSModal: false,
llm_factory: '',
tenantIfo: {},
tenantIfo: null,
llmInfo: {},
myLlm: [],
factoriesList: [],
@@ -73,23 +75,11 @@ const model: DvaModel<SettingModelState> = {
}
},
*getTenantInfo({ payload = {} }, { call, put }) {
yield put({
type: 'updateState',
payload: {
loading: true,
},
});
const { data } = yield call(userService.get_tenant_info, payload);
const { retcode, data: res } = data;
// llm_id 对应chat_id
// asr_id 对应speech2txt
yield put({
type: 'updateState',
payload: {
loading: false,
},
});
if (retcode === 0) {
res.chat_id = res.llm_id;
res.speech2text_id = res.asr_id;

+ 4
- 4
web/src/services/uploadService.ts 查看文件

@@ -1,21 +1,21 @@
import request from '@/utils/request';
import api from '@/utils/api';
import request from '@/utils/request';
const { upload } = api;
const uploadService = {
uploadFile: function (file, kb_id) {
uploadFile: function (file: any, kb_id: string) {
const formData = new FormData();
formData.append('file', file);
formData.append('kb_id', kb_id);
const options = {
method: 'post',
data: formData
data: formData,
};
return request(upload, options);
}
},
};
export default uploadService;

正在加载...
取消
保存