mirror of
https://github.com/infiniflow/ragflow.git
synced 2025-12-08 20:42:30 +08:00
feat: set chunk to available state and select all chunk (#57)
* feat: set chunk to available state * feat: select all chunk
This commit is contained in:
@ -1,41 +1,36 @@
|
||||
import { api_host } from '@/utils/api';
|
||||
import { getOneNamespaceEffectsLoading } from '@/utils/storeUtil';
|
||||
import { DeleteOutlined, MinusSquareOutlined } from '@ant-design/icons';
|
||||
import type { PaginationProps } from 'antd';
|
||||
import {
|
||||
Button,
|
||||
Card,
|
||||
Col,
|
||||
Input,
|
||||
Pagination,
|
||||
Popconfirm,
|
||||
Row,
|
||||
Select,
|
||||
Spin,
|
||||
Switch,
|
||||
} from 'antd';
|
||||
import { Button, Input, Pagination, Space, Spin } from 'antd';
|
||||
import { debounce } from 'lodash';
|
||||
import React, { useCallback, useEffect, useState } from 'react';
|
||||
import { useDispatch, useSearchParams, useSelector } from 'umi';
|
||||
import CreateModal from './components/createModal';
|
||||
|
||||
import ChunkCard from './components/chunk-card';
|
||||
import ChunkToolBar from './components/chunk-toolbar';
|
||||
import styles from './index.less';
|
||||
import { ChunkModelState } from './model';
|
||||
|
||||
interface PayloadType {
|
||||
doc_id: string;
|
||||
keywords?: string;
|
||||
available_int?: number;
|
||||
}
|
||||
|
||||
const Chunk = () => {
|
||||
const dispatch = useDispatch();
|
||||
const chunkModel = useSelector((state: any) => state.chunkModel);
|
||||
const chunkModel: ChunkModelState = useSelector(
|
||||
(state: any) => state.chunkModel,
|
||||
);
|
||||
const [keywords, SetKeywords] = useState('');
|
||||
const [available_int, setAvailableInt] = useState(-1);
|
||||
const [selectedChunkIds, setSelectedChunkIds] = useState<string[]>([]);
|
||||
const [searchParams] = useSearchParams();
|
||||
const [pagination, setPagination] = useState({ page: 1, size: 30 });
|
||||
const { data = [], total, chunk_id, isShowCreateModal } = chunkModel;
|
||||
const {
|
||||
data = [],
|
||||
total,
|
||||
chunk_id,
|
||||
isShowCreateModal,
|
||||
pagination,
|
||||
} = chunkModel;
|
||||
const effects = useSelector((state: any) => state.loading.effects);
|
||||
const loading = getOneNamespaceEffectsLoading('chunkModel', effects, [
|
||||
'create_hunk',
|
||||
@ -44,23 +39,19 @@ const Chunk = () => {
|
||||
]);
|
||||
const documentId: string = searchParams.get('doc_id') || '';
|
||||
|
||||
const getChunkList = (value?: string) => {
|
||||
const getChunkList = () => {
|
||||
const payload: PayloadType = {
|
||||
doc_id: documentId,
|
||||
keywords: value || keywords,
|
||||
available_int,
|
||||
};
|
||||
if (payload.available_int === -1) {
|
||||
delete payload.available_int;
|
||||
}
|
||||
|
||||
dispatch({
|
||||
type: 'chunkModel/chunk_list',
|
||||
payload: {
|
||||
...payload,
|
||||
...pagination,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const confirm = async (id: string) => {
|
||||
const retcode = await dispatch<any>({
|
||||
type: 'chunkModel/rm_chunk',
|
||||
@ -84,29 +75,55 @@ const Chunk = () => {
|
||||
getChunkList();
|
||||
};
|
||||
|
||||
const onShowSizeChange: PaginationProps['onShowSizeChange'] = (
|
||||
const onPaginationChange: PaginationProps['onShowSizeChange'] = (
|
||||
page,
|
||||
size,
|
||||
) => {
|
||||
setPagination({ page, size });
|
||||
};
|
||||
|
||||
const switchChunk = async (id: string, available_int: boolean) => {
|
||||
const retcode = await dispatch<any>({
|
||||
type: 'chunkModel/switch_chunk',
|
||||
setSelectedChunkIds([]);
|
||||
dispatch({
|
||||
type: 'chunkModel/setPagination',
|
||||
payload: {
|
||||
chunk_ids: [id],
|
||||
available_int: Number(available_int),
|
||||
doc_id: documentId,
|
||||
current: page,
|
||||
pageSize: size,
|
||||
},
|
||||
});
|
||||
|
||||
retcode === 0 && getChunkList();
|
||||
getChunkList();
|
||||
};
|
||||
|
||||
const selectAllChunk = useCallback(
|
||||
(checked: boolean) => {
|
||||
setSelectedChunkIds(checked ? data.map((x) => x.chunk_id) : []);
|
||||
// setSelectedChunkIds((previousIds) => {
|
||||
// return checked ? [...previousIds, ...data.map((x) => x.chunk_id)] : [];
|
||||
// });
|
||||
},
|
||||
[data],
|
||||
);
|
||||
|
||||
const handleSingleCheckboxClick = useCallback(
|
||||
(chunkId: string, checked: boolean) => {
|
||||
setSelectedChunkIds((previousIds) => {
|
||||
const idx = previousIds.findIndex((x) => x === chunkId);
|
||||
const nextIds = [...previousIds];
|
||||
if (checked && idx === -1) {
|
||||
nextIds.push(chunkId);
|
||||
} else if (!checked && idx !== -1) {
|
||||
nextIds.splice(idx, 1);
|
||||
}
|
||||
return nextIds;
|
||||
});
|
||||
},
|
||||
[],
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
getChunkList();
|
||||
}, [documentId, available_int, pagination]);
|
||||
return () => {
|
||||
dispatch({
|
||||
type: 'chunkModel/resetFilter', // TODO: need to reset state uniformly
|
||||
});
|
||||
};
|
||||
}, [documentId]);
|
||||
|
||||
const debounceChange = debounce(getChunkList, 300);
|
||||
const debounceCallback = useCallback(
|
||||
@ -117,17 +134,20 @@ const Chunk = () => {
|
||||
const handleInputChange = (
|
||||
e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>,
|
||||
) => {
|
||||
setSelectedChunkIds([]);
|
||||
const value = e.target.value;
|
||||
SetKeywords(value);
|
||||
debounceCallback(value);
|
||||
};
|
||||
const handleSelectChange = (value: number) => {
|
||||
setAvailableInt(value);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className={styles.chunkPage}>
|
||||
<ChunkToolBar></ChunkToolBar>
|
||||
<ChunkToolBar
|
||||
getChunkList={getChunkList}
|
||||
selectAllChunk={selectAllChunk}
|
||||
checked={selectedChunkIds.length === data.length}
|
||||
></ChunkToolBar>
|
||||
<div className={styles.filter}>
|
||||
<div>
|
||||
<Input
|
||||
@ -137,28 +157,6 @@ const Chunk = () => {
|
||||
allowClear
|
||||
onChange={handleInputChange}
|
||||
/>
|
||||
<Select
|
||||
showSearch
|
||||
placeholder="是否启用"
|
||||
optionFilterProp="children"
|
||||
value={available_int}
|
||||
onChange={handleSelectChange}
|
||||
style={{ width: 220 }}
|
||||
options={[
|
||||
{
|
||||
value: -1,
|
||||
label: '全部',
|
||||
},
|
||||
{
|
||||
value: 1,
|
||||
label: '启用',
|
||||
},
|
||||
{
|
||||
value: 0,
|
||||
label: '未启用',
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
<Button
|
||||
onClick={() => {
|
||||
@ -171,86 +169,16 @@ const Chunk = () => {
|
||||
</div>
|
||||
<div className={styles.pageContent}>
|
||||
<Spin spinning={loading} className={styles.spin} size="large">
|
||||
<Row gutter={{ xs: 8, sm: 16, md: 24, lg: 24 }}>
|
||||
{data.map((item: any) => {
|
||||
return (
|
||||
<Col
|
||||
className="gutter-row"
|
||||
key={item.chunk_id}
|
||||
xs={24}
|
||||
sm={12}
|
||||
md={12}
|
||||
lg={8}
|
||||
>
|
||||
<Card
|
||||
className={styles.card}
|
||||
onClick={() => {
|
||||
handleEditchunk(item.chunk_id);
|
||||
}}
|
||||
>
|
||||
<img
|
||||
style={{ width: '50px' }}
|
||||
src={`${api_host}/document/image/${item.img_id}`}
|
||||
alt=""
|
||||
/>
|
||||
<div className={styles.container}>
|
||||
<div className={styles.content}>
|
||||
<span className={styles.context}>
|
||||
{item.content_ltks}
|
||||
</span>
|
||||
<span className={styles.delete}>
|
||||
<Switch
|
||||
size="small"
|
||||
defaultValue={item.available_int == '1'}
|
||||
onChange={(checked: boolean, e: any) => {
|
||||
e.stopPropagation();
|
||||
e.nativeEvent.stopImmediatePropagation();
|
||||
switchChunk(item.chunk_id, checked);
|
||||
}}
|
||||
/>
|
||||
</span>
|
||||
</div>
|
||||
<div className={styles.footer}>
|
||||
<span className={styles.text}>
|
||||
<MinusSquareOutlined />
|
||||
{item.doc_num}文档
|
||||
</span>
|
||||
<span className={styles.text}>
|
||||
<MinusSquareOutlined />
|
||||
{item.chunk_num}个
|
||||
</span>
|
||||
<span className={styles.text}>
|
||||
<MinusSquareOutlined />
|
||||
{item.token_num}千字符
|
||||
</span>
|
||||
<span style={{ float: 'right' }}>
|
||||
<Popconfirm
|
||||
title="Delete the task"
|
||||
description="Are you sure to delete this task?"
|
||||
onConfirm={(e: any) => {
|
||||
e.stopPropagation();
|
||||
e.nativeEvent.stopImmediatePropagation();
|
||||
console.log(confirm);
|
||||
confirm(item.chunk_id);
|
||||
}}
|
||||
okText="Yes"
|
||||
cancelText="No"
|
||||
>
|
||||
<DeleteOutlined
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
e.nativeEvent.stopImmediatePropagation();
|
||||
}}
|
||||
/>
|
||||
</Popconfirm>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
</Col>
|
||||
);
|
||||
})}
|
||||
</Row>
|
||||
<Space direction="vertical" size={'middle'}>
|
||||
{data.map((item) => (
|
||||
<ChunkCard
|
||||
item={item}
|
||||
key={item.chunk_id}
|
||||
checked={selectedChunkIds.some((x) => x === item.chunk_id)}
|
||||
handleCheckboxClick={handleSingleCheckboxClick}
|
||||
></ChunkCard>
|
||||
))}
|
||||
</Space>
|
||||
</Spin>
|
||||
</div>
|
||||
<div className={styles.pageFooter}>
|
||||
@ -259,10 +187,10 @@ const Chunk = () => {
|
||||
showLessItems
|
||||
showQuickJumper
|
||||
showSizeChanger
|
||||
onChange={onShowSizeChange}
|
||||
defaultPageSize={30}
|
||||
pageSizeOptions={[30, 60, 90]}
|
||||
defaultCurrent={pagination.page}
|
||||
onChange={onPaginationChange}
|
||||
defaultPageSize={10}
|
||||
pageSizeOptions={[10, 30, 60, 90]}
|
||||
defaultCurrent={pagination.current}
|
||||
total={total}
|
||||
/>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user