KnowledgeBase_frontend/src/pages/KnowledgeBase/Detail/DatasetTab.jsx

247 lines
11 KiB
JavaScript

import React, { useState, useEffect, useRef } from 'react';
import { Link } from 'react-router-dom';
import SvgIcon from '../../../components/SvgIcon';
export default function DatasetTab({ knowledgeBase }) {
const [searchQuery, setSearchQuery] = useState('');
const [selectedDocuments, setSelectedDocuments] = useState([]);
const [selectAll, setSelectAll] = useState(false);
const [showBatchDropdown, setShowBatchDropdown] = useState(false);
const dropdownRef = useRef(null);
// Handle click outside dropdown
useEffect(() => {
function handleClickOutside(event) {
if (dropdownRef.current && !dropdownRef.current.contains(event.target)) {
setShowBatchDropdown(false);
}
}
// Add event listener
document.addEventListener('mousedown', handleClickOutside);
return () => {
// Remove event listener on cleanup
document.removeEventListener('mousedown', handleClickOutside);
};
}, [dropdownRef]);
// Mock data for documents in this knowledge base
const documents = [
{
id: '1001',
name: '测试数据集 001',
description: '产品相关的所有文档和说明',
size: '124kb',
updatedAt: '2023-05-15',
},
{
id: '1002',
name: '产品分析数据',
description: '技术架构和API文档',
size: '89kb',
updatedAt: '2023-05-10',
},
];
// Handle select all checkbox
const handleSelectAll = () => {
if (selectAll) {
setSelectedDocuments([]);
} else {
setSelectedDocuments(documents.map((doc) => doc.id));
}
setSelectAll(!selectAll);
};
// Handle individual document selection
const handleSelectDocument = (docId) => {
if (selectedDocuments.includes(docId)) {
setSelectedDocuments(selectedDocuments.filter((id) => id !== docId));
setSelectAll(false);
} else {
setSelectedDocuments([...selectedDocuments, docId]);
if (selectedDocuments.length + 1 === documents.length) {
setSelectAll(true);
}
}
};
// Handle batch delete
const handleBatchDelete = () => {
if (selectedDocuments.length === 0) return;
// Here you would typically call an API to delete the selected documents
console.log('Deleting documents:', selectedDocuments);
// Reset selection
setSelectedDocuments([]);
setSelectAll(false);
setShowBatchDropdown(false);
};
return (
<>
{/* Breadcrumb navigation */}
<div className='d-flex align-items-center mb-4 mt-3'>
<nav aria-label='breadcrumb'>
<ol className='breadcrumb mb-0'>
<li className='breadcrumb-item'>
<Link className='text-secondary text-decoration-none' to='/'>
知识库
</Link>
</li>
<li className='breadcrumb-item'>
<Link className='text-secondary text-decoration-none' to={`/knowledge-base/${knowledgeBase.id}`}>{knowledgeBase.title}</Link>
</li>
<li className='breadcrumb-item active text-dark' aria-current='page'>
数据集
</li>
</ol>
</nav>
</div>
{/* Action bar */}
<div className='d-flex justify-content-between align-items-center mb-3'>
<div className='d-flex align-items-center'>
<div className='dropdown me-2 position-relative' ref={dropdownRef}>
<button
className={`btn ${
selectedDocuments.length > 0 ? 'btn-outline-dark' : 'btn-outline-secondary'
} dropdown-toggle d-flex align-items-center gap-1`}
type='button'
onClick={() => setShowBatchDropdown(!showBatchDropdown)}
aria-expanded={showBatchDropdown}
disabled={selectedDocuments.length === 0}
>
<SvgIcon className='stack-fill' />
批量操作 {selectedDocuments.length > 0 ? `(${selectedDocuments.length})` : ''}
</button>
{showBatchDropdown && (
<ul className='dropdown-menu shadow show' style={{ position: 'absolute', zIndex: 1000 }}>
<li>
<button
className='dropdown-item d-flex align-items-center text-danger'
onClick={handleBatchDelete}
>
<SvgIcon className='trash me-2' />
删除
</button>
</li>
</ul>
)}
</div>
<div className='position-relative'>
<input
type='text'
className='form-control'
placeholder='搜索文件...'
value={searchQuery}
onChange={(e) => setSearchQuery(e.target.value)}
/>
<span className='position-absolute top-50 end-0 translate-middle-y pe-3'>
<SvgIcon className='search' />
</span>
</div>
</div>
<button className='btn btn-dark d-flex align-items-center gap-1'>
<SvgIcon className='plus' />
新增文件
</button>
</div>
{/* Documents table */}
<div className='card border-0 shadow-sm'>
<div className='card-body p-0'>
<table className='table table-hover mb-0'>
<thead className='table-light'>
<tr>
<th scope='col' width='40'>
<div className='form-check'>
<input
className='form-check-input'
type='checkbox'
id='selectAllCheckbox'
checked={selectAll}
onChange={handleSelectAll}
/>
</div>
</th>
<th scope='col'>ID</th>
<th scope='col'>名称</th>
<th scope='col'>描述</th>
<th scope='col'>文档大小</th>
<th scope='col'>更新日期</th>
<th scope='col'>操作</th>
</tr>
</thead>
<tbody>
{documents.map((doc) => (
<tr key={doc.id}>
<td>
<div className='form-check'>
<input
className='form-check-input'
type='checkbox'
id={`checkbox-${doc.id}`}
checked={selectedDocuments.includes(doc.id)}
onChange={() => handleSelectDocument(doc.id)}
/>
</div>
</td>
<td>#{doc.id}</td>
<td>{doc.name}</td>
<td>{doc.description}</td>
<td>{doc.size}</td>
<td>{doc.updatedAt}</td>
<td>
<div className='d-flex gap-2'>
<button className='btn btn-sm btn-outline-primary' title='查看'>
<SvgIcon className='eye' />
</button>
<button className='btn btn-sm btn-outline-success' title='编辑'>
<SvgIcon className='edit' />
</button>
<button className='btn btn-sm btn-outline-danger' title='删除'>
<SvgIcon className='trash' />
</button>
</div>
</td>
</tr>
))}
</tbody>
</table>
</div>
</div>
{/* Pagination */}
<div className='d-flex justify-content-between align-items-center mt-3'>
<div>
每页行数:
<select className='form-select form-select-sm d-inline-block ms-2' style={{ width: '70px' }}>
<option value='5'>5</option>
<option value='10'>10</option>
<option value='20'>20</option>
</select>
</div>
<div className='d-flex align-items-center'>
<span className='me-3'>1-5 of 10</span>
<nav aria-label='Page navigation'>
<ul className='pagination pagination-sm mb-0'>
<li className='page-item'>
<button className='page-link' aria-label='Previous'>
<span aria-hidden='true'>&laquo;</span>
</button>
</li>
<li className='page-item'>
<button className='page-link' aria-label='Next'>
<span aria-hidden='true'>&raquo;</span>
</button>
</li>
</ul>
</nav>
</div>
</div>
</>
);
}