docs: archive historical openspec changes
This commit is contained in:
@@ -0,0 +1,627 @@
|
||||
# 文档管理页面开发 - 设计文档
|
||||
|
||||
## 1. 架构设计
|
||||
|
||||
### 1.1 整体架构
|
||||
```
|
||||
documents.html (独立页面)
|
||||
├── HTML 结构
|
||||
│ ├── 顶部导航栏
|
||||
│ ├── 状态统计区域
|
||||
│ ├── 操作工具栏
|
||||
│ ├── 文档列表区域
|
||||
│ └── 详情面板(滑出式)
|
||||
├── CSS 样式(复用 styles.css + 少量定制)
|
||||
└── JavaScript 逻辑
|
||||
├── API 调用层
|
||||
├── 状态管理
|
||||
├── UI 渲染
|
||||
└── 事件处理
|
||||
```
|
||||
|
||||
### 1.2 页面结构
|
||||
```html
|
||||
<body>
|
||||
<div class="app-layout">
|
||||
<!-- 左侧导航(可选,或仅顶部导航) -->
|
||||
<aside class="sidebar-mini">
|
||||
<a href="index.html">返回主页</a>
|
||||
<a href="documents.html" class="active">文档管理</a>
|
||||
</aside>
|
||||
|
||||
<!-- 主内容区 -->
|
||||
<main class="main-content">
|
||||
<!-- 顶部导航栏 -->
|
||||
<header class="page-header">
|
||||
<h1>文档管理</h1>
|
||||
<button id="uploadBtn">上传文档</button>
|
||||
<button id="refreshBtn">刷新</button>
|
||||
</header>
|
||||
|
||||
<!-- 状态统计卡片 -->
|
||||
<section class="stats-cards">
|
||||
<div class="stat-card" data-status="PENDING">
|
||||
<span class="stat-label">待处理</span>
|
||||
<span class="stat-value" id="statPending">0</span>
|
||||
</div>
|
||||
<div class="stat-card" data-status="PROCESSING">
|
||||
<span class="stat-label">处理中</span>
|
||||
<span class="stat-value" id="statProcessing">0</span>
|
||||
</div>
|
||||
<div class="stat-card" data-status="INDEXED">
|
||||
<span class="stat-label">已索引</span>
|
||||
<span class="stat-value" id="statIndexed">0</span>
|
||||
</div>
|
||||
<div class="stat-card" data-status="FAILED">
|
||||
<span class="stat-label">失败</span>
|
||||
<span class="stat-value" id="statFailed">0</span>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- 操作工具栏 -->
|
||||
<div class="toolbar">
|
||||
<div class="filters">
|
||||
<select id="statusFilter">
|
||||
<option value="">全部状态</option>
|
||||
<option value="PENDING">待处理</option>
|
||||
<option value="PROCESSING">处理中</option>
|
||||
<option value="INDEXED">已索引</option>
|
||||
<option value="FAILED">失败</option>
|
||||
</select>
|
||||
<input type="text" id="faultSourceFilter" placeholder="按故障源筛选">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 文档列表 -->
|
||||
<div class="documents-table-container">
|
||||
<table class="documents-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>文件名</th>
|
||||
<th>类别</th>
|
||||
<th>故障源</th>
|
||||
<th>接口名称</th>
|
||||
<th>版本</th>
|
||||
<th>状态</th>
|
||||
<th>分块数</th>
|
||||
<th>上传时间</th>
|
||||
<th>操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="documentsTableBody">
|
||||
<!-- 动态生成 -->
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="pagination" id="pagination">
|
||||
<!-- 分页控件 -->
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<!-- 详情面板(右侧滑出) -->
|
||||
<aside class="detail-panel" id="detailPanel">
|
||||
<div class="panel-header">
|
||||
<h2>文档详情</h2>
|
||||
<button id="closePanelBtn">×</button>
|
||||
</div>
|
||||
<div class="panel-content" id="panelContent">
|
||||
<!-- 动态生成 -->
|
||||
</div>
|
||||
</aside>
|
||||
</div>
|
||||
|
||||
<!-- 上传对话框 -->
|
||||
<div class="modal" id="uploadModal">
|
||||
<div class="modal-content">
|
||||
<h2>上传文档</h2>
|
||||
<form id="uploadForm">
|
||||
<div class="form-group">
|
||||
<label>选择文件</label>
|
||||
<input type="file" id="fileInput" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>文档类别</label>
|
||||
<select id="faultCategory">
|
||||
<option value="EXTERNAL_API">外部接口调用失败</option>
|
||||
<option value="INTERNAL_ERROR">系统内部错误</option>
|
||||
<option value="DATABASE">数据库问题</option>
|
||||
<option value="CACHE">缓存问题</option>
|
||||
<option value="NETWORK">网络问题</option>
|
||||
<option value="THREAD">线程问题</option>
|
||||
<option value="MEMORY">内存问题</option>
|
||||
<option value="CONFIG">配置问题</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>故障源</label>
|
||||
<input type="text" id="faultSource" placeholder="如:广东、order-service">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>接口名称</label>
|
||||
<input type="text" id="apiName" placeholder="如:社保查询、订单服务API">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>版本</label>
|
||||
<input type="text" id="version" value="v1.0">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>分块大小</label>
|
||||
<input type="number" id="chunkSize" value="500">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>分块重叠</label>
|
||||
<input type="number" id="chunkOverlap" value="50">
|
||||
</div>
|
||||
<div class="modal-actions">
|
||||
<button type="submit" id="submitUploadBtn">上传</button>
|
||||
<button type="button" id="cancelUploadBtn">取消</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 删除确认对话框 -->
|
||||
<div class="modal" id="deleteModal">
|
||||
<div class="modal-content">
|
||||
<h2>确认删除</h2>
|
||||
<p id="deleteMessage"></p>
|
||||
<p class="warning">此操作将删除 MySQL 和 Milvus 中的所有数据,不可恢复。</p>
|
||||
<div class="modal-actions">
|
||||
<button id="confirmDeleteBtn" class="danger">删除</button>
|
||||
<button id="cancelDeleteBtn">取消</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
```
|
||||
|
||||
## 2. API 交互设计
|
||||
|
||||
### 2.1 API 响应格式
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"message": "success",
|
||||
"data": { ... },
|
||||
"timestamp": 1719283200000
|
||||
}
|
||||
```
|
||||
|
||||
### 2.2 API 调用封装
|
||||
```javascript
|
||||
class DocumentAPI {
|
||||
constructor() {
|
||||
this.baseUrl = '/api/documents';
|
||||
}
|
||||
|
||||
async uploadDocument(formData) {
|
||||
const response = await fetch(`${this.baseUrl}/upload`, {
|
||||
method: 'POST',
|
||||
body: formData
|
||||
});
|
||||
return this.handleResponse(response);
|
||||
}
|
||||
|
||||
async getDocument(docId) {
|
||||
const response = await fetch(`${this.baseUrl}/${docId}`);
|
||||
return this.handleResponse(response);
|
||||
}
|
||||
|
||||
async getDocumentsByStatus(status, page = 0, size = 20) {
|
||||
const response = await fetch(
|
||||
`${this.baseUrl}/status/${status}?page=${page}&size=${size}`
|
||||
);
|
||||
return this.handleResponse(response);
|
||||
}
|
||||
|
||||
async getDocumentsByFaultSource(faultSource) {
|
||||
const response = await fetch(
|
||||
`${this.baseUrl}/faultSource/${encodeURIComponent(faultSource)}`
|
||||
);
|
||||
return this.handleResponse(response);
|
||||
}
|
||||
|
||||
async deleteDocument(docId) {
|
||||
const response = await fetch(`${this.baseUrl}/${docId}`, {
|
||||
method: 'DELETE'
|
||||
});
|
||||
return this.handleResponse(response);
|
||||
}
|
||||
|
||||
async handleResponse(response) {
|
||||
const result = await response.json();
|
||||
if (result.code !== 200) {
|
||||
throw new Error(result.message || '请求失败');
|
||||
}
|
||||
return result.data;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2.3 状态管理
|
||||
```javascript
|
||||
class DocumentManager {
|
||||
constructor() {
|
||||
this.api = new DocumentAPI();
|
||||
this.documents = [];
|
||||
this.currentFilter = { status: '', faultSource: '' };
|
||||
this.currentPage = 0;
|
||||
this.pageSize = 20;
|
||||
this.selectedDocId = null;
|
||||
}
|
||||
|
||||
async loadDocuments() {
|
||||
// 根据筛选条件加载文档
|
||||
if (this.currentFilter.status) {
|
||||
this.documents = await this.api.getDocumentsByStatus(
|
||||
this.currentFilter.status,
|
||||
this.currentPage,
|
||||
this.pageSize
|
||||
);
|
||||
} else if (this.currentFilter.faultSource) {
|
||||
this.documents = await this.api.getDocumentsByFaultSource(
|
||||
this.currentFilter.faultSource
|
||||
);
|
||||
} else {
|
||||
// 默认加载已索引的文档
|
||||
this.documents = await this.api.getDocumentsByStatus(
|
||||
'INDEXED',
|
||||
this.currentPage,
|
||||
this.pageSize
|
||||
);
|
||||
}
|
||||
this.renderDocuments();
|
||||
this.updateStats();
|
||||
}
|
||||
|
||||
async updateStats() {
|
||||
const statuses = ['PENDING', 'PROCESSING', 'INDEXED', 'FAILED'];
|
||||
for (const status of statuses) {
|
||||
const docs = await this.api.getDocumentsByStatus(status, 0, 999);
|
||||
document.getElementById(`stat${status.charAt(0) + status.slice(1).toLowerCase()}`).textContent = docs.length;
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 3. UI 组件设计
|
||||
|
||||
### 3.1 状态徽章
|
||||
```javascript
|
||||
function getStatusBadge(status) {
|
||||
const badges = {
|
||||
PENDING: { text: '待处理', color: '#757575' },
|
||||
PROCESSING: { text: '处理中', color: '#1a73e8' },
|
||||
INDEXED: { text: '已索引', color: '#34a853' },
|
||||
FAILED: { text: '失败', color: '#ea4335' }
|
||||
};
|
||||
const badge = badges[status] || badges.PENDING;
|
||||
return `<span class="status-badge" style="background: ${badge.color}">${badge.text}</span>`;
|
||||
}
|
||||
```
|
||||
|
||||
### 3.2 文档列表行
|
||||
```javascript
|
||||
function renderDocumentRow(doc) {
|
||||
return `
|
||||
<tr data-doc-id="${doc.docId}" class="document-row">
|
||||
<td>${doc.fileName}</td>
|
||||
<td>${doc.faultCategory}</td>
|
||||
<td>${doc.faultSource || '-'}</td>
|
||||
<td>${doc.apiName || '-'}</td>
|
||||
<td>${doc.version}</td>
|
||||
<td>${getStatusBadge(doc.status)}</td>
|
||||
<td>${doc.chunkCount}</td>
|
||||
<td>${formatDateTime(doc.createdAt)}</td>
|
||||
<td>
|
||||
<button class="btn-view" data-doc-id="${doc.docId}">查看</button>
|
||||
<button class="btn-delete" data-doc-id="${doc.docId}">删除</button>
|
||||
</td>
|
||||
</tr>
|
||||
`;
|
||||
}
|
||||
```
|
||||
|
||||
### 3.3 详情面板
|
||||
```javascript
|
||||
function renderDetailPanel(doc) {
|
||||
return `
|
||||
<div class="detail-section">
|
||||
<h3>基本信息</h3>
|
||||
<div class="detail-item">
|
||||
<label>文档ID:</label>
|
||||
<span>${doc.docId}</span>
|
||||
</div>
|
||||
<div class="detail-item">
|
||||
<label>文件名:</label>
|
||||
<span>${doc.fileName}</span>
|
||||
</div>
|
||||
<div class="detail-item">
|
||||
<label>文件大小:</label>
|
||||
<span>${formatFileSize(doc.fileSize)}</span>
|
||||
</div>
|
||||
<div class="detail-item">
|
||||
<label>状态:</label>
|
||||
${getStatusBadge(doc.status)}
|
||||
</div>
|
||||
</div>
|
||||
<div class="detail-section">
|
||||
<h3>分类信息</h3>
|
||||
<div class="detail-item">
|
||||
<label>文档类别:</label>
|
||||
<span>${doc.faultCategory}</span>
|
||||
</div>
|
||||
<div class="detail-item">
|
||||
<label>故障源:</label>
|
||||
<span>${doc.faultSource || '-'}</span>
|
||||
</div>
|
||||
<div class="detail-item">
|
||||
<label>接口名称:</label>
|
||||
<span>${doc.apiName || '-'}</span>
|
||||
</div>
|
||||
<div class="detail-item">
|
||||
<label>版本:</label>
|
||||
<span>${doc.version}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="detail-section">
|
||||
<h3>索引信息</h3>
|
||||
<div class="detail-item">
|
||||
<label>分块数量:</label>
|
||||
<span>${doc.chunkCount}</span>
|
||||
</div>
|
||||
<div class="detail-item">
|
||||
<label>索引时间:</label>
|
||||
<span>${formatDateTime(doc.indexedAt)}</span>
|
||||
</div>
|
||||
${doc.status === 'FAILED' ? `
|
||||
<div class="detail-item error">
|
||||
<label>错误信息:</label>
|
||||
<span>${doc.errorMessage}</span>
|
||||
</div>
|
||||
` : ''}
|
||||
</div>
|
||||
<div class="detail-section">
|
||||
<h3>时间信息</h3>
|
||||
<div class="detail-item">
|
||||
<label>创建时间:</label>
|
||||
<span>${formatDateTime(doc.createdAt)}</span>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
```
|
||||
|
||||
## 4. 样式设计
|
||||
|
||||
### 4.1 核心样式变量(复用 styles.css)
|
||||
```css
|
||||
/* 复用现有变量 */
|
||||
--primary-color: #1a73e8;
|
||||
--background: #ffffff;
|
||||
--surface: #f1f3f4;
|
||||
--border: #dadce0;
|
||||
--text: #202124;
|
||||
--text-secondary: #5f6368;
|
||||
```
|
||||
|
||||
### 4.2 文档管理特定样式
|
||||
```css
|
||||
/* 状态统计卡片 */
|
||||
.stats-cards {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
gap: 16px;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.stat-card {
|
||||
background: #ffffff;
|
||||
border: 1px solid #dadce0;
|
||||
border-radius: 8px;
|
||||
padding: 16px;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.stat-card:hover {
|
||||
border-color: #1a73e8;
|
||||
box-shadow: 0 1px 3px rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
/* 文档表格 */
|
||||
.documents-table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
background: #ffffff;
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.documents-table th {
|
||||
background: #f1f3f4;
|
||||
padding: 12px;
|
||||
text-align: left;
|
||||
font-weight: 500;
|
||||
border-bottom: 1px solid #dadce0;
|
||||
}
|
||||
|
||||
.documents-table td {
|
||||
padding: 12px;
|
||||
border-bottom: 1px solid #f1f3f4;
|
||||
}
|
||||
|
||||
.document-row:hover {
|
||||
background: #f8f9fa;
|
||||
}
|
||||
|
||||
/* 状态徽章 */
|
||||
.status-badge {
|
||||
display: inline-block;
|
||||
padding: 4px 8px;
|
||||
border-radius: 4px;
|
||||
color: #ffffff;
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
/* 详情面板 */
|
||||
.detail-panel {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
right: -400px;
|
||||
width: 400px;
|
||||
height: 100vh;
|
||||
background: #ffffff;
|
||||
border-left: 1px solid #dadce0;
|
||||
box-shadow: -2px 0 8px rgba(0,0,0,0.1);
|
||||
transition: right 0.3s ease;
|
||||
overflow-y: auto;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
.detail-panel.open {
|
||||
right: 0;
|
||||
}
|
||||
```
|
||||
|
||||
## 5. 事件处理流程
|
||||
|
||||
### 5.1 上传文档流程
|
||||
```
|
||||
1. 用户点击"上传文档"按钮
|
||||
↓
|
||||
2. 显示上传表单对话框
|
||||
↓
|
||||
3. 用户选择文件并填写表单
|
||||
↓
|
||||
4. 点击"上传"按钮,触发表单提交
|
||||
↓
|
||||
5. 构建 FormData,调用 API
|
||||
POST /api/documents/upload
|
||||
↓
|
||||
6. 显示加载状态(禁用按钮,显示加载图标)
|
||||
↓
|
||||
7. 成功:关闭对话框,刷新列表,高亮新文档
|
||||
失败:显示错误信息,保持对话框打开
|
||||
```
|
||||
|
||||
### 5.2 删除文档流程
|
||||
```
|
||||
1. 用户点击"删除"按钮
|
||||
↓
|
||||
2. 显示删除确认对话框
|
||||
↓
|
||||
3. 用户确认删除
|
||||
↓
|
||||
4. 调用 API
|
||||
DELETE /api/documents/{docId}
|
||||
↓
|
||||
5. 成功:关闭对话框,刷新列表
|
||||
失败:显示错误信息
|
||||
```
|
||||
|
||||
### 5.3 筛选流程
|
||||
```
|
||||
1. 用户选择筛选条件
|
||||
- 点击状态卡片
|
||||
- 选择状态下拉框
|
||||
- 输入故障源
|
||||
↓
|
||||
2. 更新 currentFilter
|
||||
↓
|
||||
3. 重置 currentPage = 0
|
||||
↓
|
||||
4. 调用 loadDocuments()
|
||||
↓
|
||||
5. 渲染新的文档列表
|
||||
```
|
||||
|
||||
## 6. 错误处理
|
||||
|
||||
### 6.1 网络错误
|
||||
```javascript
|
||||
try {
|
||||
const data = await api.uploadDocument(formData);
|
||||
showSuccess('文档上传成功');
|
||||
} catch (error) {
|
||||
showError('上传失败: ' + error.message);
|
||||
}
|
||||
```
|
||||
|
||||
### 6.2 业务错误
|
||||
```javascript
|
||||
async handleResponse(response) {
|
||||
const result = await response.json();
|
||||
if (result.code !== 200) {
|
||||
throw new Error(result.message || '请求失败');
|
||||
}
|
||||
return result.data;
|
||||
}
|
||||
```
|
||||
|
||||
### 6.3 用户提示
|
||||
```javascript
|
||||
function showError(message) {
|
||||
// 显示顶部通知条
|
||||
const notification = document.createElement('div');
|
||||
notification.className = 'notification error';
|
||||
notification.textContent = message;
|
||||
document.body.appendChild(notification);
|
||||
setTimeout(() => notification.remove(), 3000);
|
||||
}
|
||||
```
|
||||
|
||||
## 7. 性能优化
|
||||
|
||||
### 7.1 分页加载
|
||||
- 每页 20 条记录
|
||||
- 避免一次性加载所有文档
|
||||
|
||||
### 7.2 防抖处理
|
||||
- 故障源输入框使用防抖(300ms)
|
||||
- 避免频繁调用 API
|
||||
|
||||
### 7.3 缓存策略
|
||||
- 状态统计数据缓存 5 秒
|
||||
- 避免频繁刷新统计数据
|
||||
|
||||
## 8. 可访问性
|
||||
|
||||
- 按钮添加 aria-label
|
||||
- 表格添加 caption
|
||||
- 表单字段添加 label 关联
|
||||
- 对话框添加 role="dialog" 和 aria-modal="true"
|
||||
|
||||
## 9. 浏览器兼容性
|
||||
|
||||
- 目标浏览器:Chrome 90+, Firefox 88+, Safari 14+
|
||||
- 使用标准 Fetch API(无需 polyfill)
|
||||
- 使用 ES6 语法(async/await, class, arrow function)
|
||||
|
||||
## 10. 测试场景
|
||||
|
||||
### 10.1 功能测试
|
||||
- [ ] 上传文档(成功 / 失败)
|
||||
- [ ] 查看文档列表
|
||||
- [ ] 按状态筛选
|
||||
- [ ] 按故障源筛选
|
||||
- [ ] 查看文档详情
|
||||
- [ ] 删除文档
|
||||
- [ ] 刷新列表
|
||||
- [ ] 分页切换
|
||||
|
||||
### 10.2 边界测试
|
||||
- [ ] 空列表状态
|
||||
- [ ] 大文件上传(接近 10MB)
|
||||
- [ ] 网络超时
|
||||
- [ ] 后端服务不可用
|
||||
- [ ] 特殊字符文件名
|
||||
- [ ] 中文故障源
|
||||
|
||||
### 10.3 用户体验测试
|
||||
- [ ] 上传进度反馈
|
||||
- [ ] 错误信息清晰
|
||||
- [ ] 加载状态提示
|
||||
- [ ] 删除二次确认
|
||||
- [ ] 表单验证
|
||||
@@ -0,0 +1,179 @@
|
||||
# 文档管理页面开发提案
|
||||
|
||||
## 1. 目标
|
||||
|
||||
为 SuperBizAgent 开发一个独立的文档管理页面,用于管理 API 文档的上传、查询、删除和状态监控。
|
||||
|
||||
## 2. 背景
|
||||
|
||||
- 后端已完成文档管理功能(DocumentController),包含上传、查询、删除 API
|
||||
- 数据库表设计已完成(api_document 表)
|
||||
- 项目已有 index.html 聊天界面,使用统一的 styles.css 设计风格
|
||||
- 需要一个独立的文档管理界面来操作文档元数据
|
||||
|
||||
## 3. 核心功能
|
||||
|
||||
### 3.1 文档列表展示
|
||||
- 显示文档元数据:文件名、类别、状态、版本、分块数、上传时间
|
||||
- 状态筛选:PENDING / PROCESSING / INDEXED / FAILED
|
||||
- 故障源筛选:支持按 fault_source 筛选
|
||||
- 分页支持:每页 20 条
|
||||
- 默认排序:按上传时间倒序(最新在前)
|
||||
|
||||
### 3.2 文档上传
|
||||
- 文件选择器(支持拖拽上传)
|
||||
- 元信息表单:
|
||||
- fault_category(文档类别):下拉选择(EXTERNAL_API / INTERNAL_ERROR 等)
|
||||
- fault_source(故障源):文本输入(如"广东"、"order-service")
|
||||
- api_name(接口名称):文本输入
|
||||
- version(版本):文本输入(默认 v1.0)
|
||||
- 分块配置(可选,有默认值):
|
||||
- chunkSize:默认 500
|
||||
- chunkOverlap:默认 50
|
||||
- 上传后行为:刷新列表并高亮新文档
|
||||
|
||||
### 3.3 文档详情查看
|
||||
- 点击文档行展开详情面板(右侧滑出或弹窗)
|
||||
- 显示完整元数据(包括 docId、fileSize、fileHash、indexedAt 等)
|
||||
- 显示索引状态和分块信息
|
||||
- 失败文档显示错误信息(error_message)
|
||||
|
||||
### 3.4 文档删除
|
||||
- 删除按钮(每行一个)
|
||||
- 确认对话框:警告硬删除(MySQL + Milvus 数据都会删除)
|
||||
- 删除成功后刷新列表
|
||||
|
||||
### 3.5 状态监控
|
||||
- 顶部统计卡片:显示各状态文档数量
|
||||
- PENDING:待处理
|
||||
- PROCESSING:处理中
|
||||
- INDEXED:已索引
|
||||
- FAILED:失败
|
||||
- 点击统计卡片快速筛选对应状态的文档
|
||||
|
||||
## 4. 技术方案
|
||||
|
||||
### 4.1 前端技术栈
|
||||
- 纯静态页面(HTML + CSS + JavaScript)
|
||||
- 复用现有 styles.css 的设计风格
|
||||
- 使用原生 Fetch API 调用后端接口
|
||||
- 无需引入额外框架
|
||||
|
||||
### 4.2 页面结构
|
||||
```
|
||||
documents.html
|
||||
├── 顶部导航栏(返回主页按钮)
|
||||
├── 状态统计卡片区域
|
||||
├── 操作区域(上传按钮 + 筛选器)
|
||||
├── 文档列表表格
|
||||
└── 详情面板(右侧滑出)
|
||||
```
|
||||
|
||||
### 4.3 样式设计
|
||||
- 保持与 index.html 一致的现代简洁风格
|
||||
- 使用卡片式布局
|
||||
- 状态标签使用颜色区分:
|
||||
- PENDING:灰色
|
||||
- PROCESSING:蓝色
|
||||
- INDEXED:绿色
|
||||
- FAILED:红色
|
||||
|
||||
### 4.4 API 集成
|
||||
```javascript
|
||||
// 后端 API
|
||||
const API_BASE = '/api/documents';
|
||||
|
||||
// 上传文档
|
||||
POST /api/documents/upload (FormData)
|
||||
|
||||
// 查询文档详情
|
||||
GET /api/documents/{docId}
|
||||
|
||||
// 按状态查询
|
||||
GET /api/documents/status/{status}?page=0&size=20
|
||||
|
||||
// 按故障源查询
|
||||
GET /api/documents/faultSource/{faultSource}
|
||||
|
||||
// 删除文档
|
||||
DELETE /api/documents/{docId}
|
||||
```
|
||||
|
||||
### 4.5 状态更新策略
|
||||
- 不实现自动轮询(避免复杂性)
|
||||
- 提供手动刷新按钮
|
||||
- 用户可随时点击刷新查看最新状态
|
||||
|
||||
## 5. 用户体验
|
||||
|
||||
### 5.1 上传流程
|
||||
1. 用户点击"上传文档"按钮
|
||||
2. 弹出上传表单对话框
|
||||
3. 选择文件 + 填写元信息
|
||||
4. 点击确认上传
|
||||
5. 显示上传中状态(禁用按钮,显示加载图标)
|
||||
6. 上传成功:关闭对话框,刷新列表,高亮新文档
|
||||
7. 上传失败:显示错误信息,保持对话框打开
|
||||
|
||||
### 5.2 筛选流程
|
||||
1. 点击状态统计卡片 → 快速筛选该状态文档
|
||||
2. 使用下拉筛选器 → 按状态或故障源筛选
|
||||
3. 清除筛选 → 显示全部文档
|
||||
|
||||
### 5.3 删除流程
|
||||
1. 点击删除按钮
|
||||
2. 弹出确认对话框:"确定删除文档 {fileName}?此操作将删除 MySQL 和 Milvus 中的所有数据,不可恢复。"
|
||||
3. 确认 → 调用删除 API → 刷新列表
|
||||
4. 取消 → 关闭对话框
|
||||
|
||||
## 6. 实现优先级
|
||||
|
||||
### P0(必须实现)
|
||||
- 文档列表展示(带状态和故障源筛选)
|
||||
- 文档上传(基本表单 + 文件选择)
|
||||
- 文档删除(带确认)
|
||||
- 状态统计卡片
|
||||
|
||||
### P1(重要但可后续优化)
|
||||
- 文档详情查看(右侧面板)
|
||||
- 拖拽上传
|
||||
- 列表分页
|
||||
|
||||
### P2(可选增强)
|
||||
- 批量删除
|
||||
- 导出文档列表
|
||||
- 上传历史记录
|
||||
|
||||
## 7. 文件清单
|
||||
|
||||
需要创建的文件:
|
||||
- `src/main/resources/static/documents.html` - 文档管理页面主 HTML
|
||||
- `src/main/resources/static/documents.js` - 文档管理页面逻辑(可选,也可内联到 HTML)
|
||||
- `src/main/resources/static/documents.css` - 文档管理页面专属样式(可选,优先复用 styles.css)
|
||||
|
||||
需要修改的文件:
|
||||
- `src/main/resources/static/index.html` - 添加"文档管理"入口链接(侧边栏)
|
||||
|
||||
## 8. 约束和风险
|
||||
|
||||
### 约束
|
||||
- 保持与现有页面风格一致
|
||||
- 不引入新的前端框架或库
|
||||
- 文件上传大小受限于后端配置(Spring Boot multipart.max-file-size)
|
||||
|
||||
### 风险
|
||||
- 大文件上传可能超时(需要后端支持超时配置)
|
||||
- 文件 hash 计算在前端(需要 File API 支持)→ 暂时由后端处理
|
||||
- 状态监控无实时更新,用户需手动刷新
|
||||
|
||||
## 9. 验收标准
|
||||
|
||||
- [ ] 可以通过页面上传文档,填写完整元信息
|
||||
- [ ] 可以查看文档列表,显示正确的元数据
|
||||
- [ ] 可以按状态筛选文档(PENDING / PROCESSING / INDEXED / FAILED)
|
||||
- [ ] 可以按故障源筛选文档
|
||||
- [ ] 可以删除文档,删除后列表自动刷新
|
||||
- [ ] 状态统计卡片显示正确数量
|
||||
- [ ] 页面样式与 index.html 保持一致
|
||||
- [ ] 失败文档显示错误信息
|
||||
- [ ] 上传失败时显示明确的错误提示
|
||||
@@ -0,0 +1,406 @@
|
||||
# 文档管理页面开发 - 任务清单
|
||||
|
||||
## 任务分解
|
||||
|
||||
### Task 1: 创建基础 HTML 结构
|
||||
**优先级**: P0
|
||||
**预计时间**: 30 分钟
|
||||
**依赖**: 无
|
||||
|
||||
**描述**:
|
||||
创建 documents.html 文件,包含完整的页面结构:
|
||||
- 页面布局(app-layout)
|
||||
- 顶部导航栏(page-header)
|
||||
- 状态统计卡片区域(stats-cards)
|
||||
- 操作工具栏(toolbar)
|
||||
- 文档列表表格(documents-table)
|
||||
- 详情面板(detail-panel)
|
||||
- 上传对话框(uploadModal)
|
||||
- 删除确认对话框(deleteModal)
|
||||
|
||||
**验收标准**:
|
||||
- [ ] HTML 结构完整,包含所有必要的容器元素
|
||||
- [ ] 引入 styles.css
|
||||
- [ ] 表单元素 ID 正确
|
||||
- [ ] 对话框结构完整
|
||||
|
||||
**文件**:
|
||||
- 创建: `src/main/resources/static/documents.html`
|
||||
|
||||
---
|
||||
|
||||
### Task 2: 实现样式定制
|
||||
**优先级**: P0
|
||||
**预计时间**: 45 分钟
|
||||
**依赖**: Task 1
|
||||
|
||||
**描述**:
|
||||
创建 documents.css 文件,实现文档管理页面的特定样式:
|
||||
- 状态统计卡片样式
|
||||
- 文档表格样式
|
||||
- 状态徽章样式(4 种颜色)
|
||||
- 详情面板滑出动画
|
||||
- 对话框样式
|
||||
- 响应式布局
|
||||
|
||||
**验收标准**:
|
||||
- [ ] 样式与 index.html 风格一致
|
||||
- [ ] 状态徽章颜色正确(PENDING 灰色、PROCESSING 蓝色、INDEXED 绿色、FAILED 红色)
|
||||
- [ ] 表格可读性好,hover 效果流畅
|
||||
- [ ] 详情面板滑出动画流畅
|
||||
- [ ] 对话框居中显示,背景遮罩半透明
|
||||
|
||||
**文件**:
|
||||
- 创建: `src/main/resources/static/documents.css`
|
||||
|
||||
---
|
||||
|
||||
### Task 3: 实现 API 调用层
|
||||
**优先级**: P0
|
||||
**预计时间**: 30 分钟
|
||||
**依赖**: Task 1
|
||||
|
||||
**描述**:
|
||||
在 documents.html 的 script 标签中实现 DocumentAPI 类:
|
||||
- uploadDocument(formData)
|
||||
- getDocument(docId)
|
||||
- getDocumentsByStatus(status, page, size)
|
||||
- getDocumentsByFaultSource(faultSource)
|
||||
- deleteDocument(docId)
|
||||
- handleResponse(response) - 统一处理 Result 格式
|
||||
|
||||
**验收标准**:
|
||||
- [ ] 所有 API 方法实现完整
|
||||
- [ ] 正确处理 Result 响应格式(code、message、data)
|
||||
- [ ] 错误处理完善,抛出清晰的错误信息
|
||||
- [ ] URL 编码正确(faultSource 参数)
|
||||
|
||||
**文件**:
|
||||
- 修改: `src/main/resources/static/documents.html` (script 部分)
|
||||
|
||||
---
|
||||
|
||||
### Task 4: 实现状态管理器
|
||||
**优先级**: P0
|
||||
**预计时间**: 45 分钟
|
||||
**依赖**: Task 3
|
||||
|
||||
**描述**:
|
||||
实现 DocumentManager 类,管理文档数据和 UI 状态:
|
||||
- loadDocuments() - 加载文档列表
|
||||
- updateStats() - 更新状态统计
|
||||
- renderDocuments() - 渲染文档列表
|
||||
- renderDetailPanel(docId) - 渲染详情面板
|
||||
- applyFilter(filter) - 应用筛选条件
|
||||
- refreshList() - 刷新列表
|
||||
|
||||
**验收标准**:
|
||||
- [ ] 状态管理逻辑清晰
|
||||
- [ ] 筛选条件正确应用
|
||||
- [ ] 列表渲染正确
|
||||
- [ ] 详情面板显示正确
|
||||
- [ ] 统计数据准确
|
||||
|
||||
**文件**:
|
||||
- 修改: `src/main/resources/static/documents.html` (script 部分)
|
||||
|
||||
---
|
||||
|
||||
### Task 5: 实现 UI 渲染函数
|
||||
**优先级**: P0
|
||||
**预计时间**: 45 分钟
|
||||
**依赖**: Task 4
|
||||
|
||||
**描述**:
|
||||
实现 UI 渲染相关的辅助函数:
|
||||
- getStatusBadge(status) - 生成状态徽章 HTML
|
||||
- renderDocumentRow(doc) - 生成文档表格行
|
||||
- renderDetailPanel(doc) - 生成详情面板内容
|
||||
- formatDateTime(dateTime) - 格式化日期时间
|
||||
- formatFileSize(bytes) - 格式化文件大小
|
||||
|
||||
**验收标准**:
|
||||
- [ ] 状态徽章颜色正确
|
||||
- [ ] 表格行包含所有必要字段
|
||||
- [ ] 详情面板信息完整
|
||||
- [ ] 日期时间格式友好(YYYY-MM-DD HH:mm:ss)
|
||||
- [ ] 文件大小单位正确(B、KB、MB)
|
||||
|
||||
**文件**:
|
||||
- 修改: `src/main/resources/static/documents.html` (script 部分)
|
||||
|
||||
---
|
||||
|
||||
### Task 6: 实现文档上传功能
|
||||
**优先级**: P0
|
||||
**预计时间**: 60 分钟
|
||||
**依赖**: Task 3, Task 4
|
||||
|
||||
**描述**:
|
||||
实现文档上传的完整流程:
|
||||
- 显示/隐藏上传对话框
|
||||
- 表单验证(文件必填)
|
||||
- 构建 FormData(包含文件和元信息)
|
||||
- 调用上传 API
|
||||
- 显示上传进度(加载状态)
|
||||
- 处理上传结果(成功刷新列表,失败显示错误)
|
||||
- 表单重置
|
||||
|
||||
**验收标准**:
|
||||
- [ ] 点击"上传文档"按钮打开对话框
|
||||
- [ ] 文件必选,其他字段使用默认值
|
||||
- [ ] FormData 包含所有参数(file、faultCategory、faultSource、apiName、version、chunkSize、chunkOverlap)
|
||||
- [ ] 上传中按钮禁用,显示加载状态
|
||||
- [ ] 上传成功:关闭对话框,刷新列表,高亮新文档(可选)
|
||||
- [ ] 上传失败:显示错误信息,对话框保持打开
|
||||
- [ ] 取消按钮关闭对话框
|
||||
|
||||
**文件**:
|
||||
- 修改: `src/main/resources/static/documents.html` (script 部分)
|
||||
|
||||
---
|
||||
|
||||
### Task 7: 实现文档删除功能
|
||||
**优先级**: P0
|
||||
**预计时间**: 30 分钟
|
||||
**依赖**: Task 3, Task 4
|
||||
|
||||
**描述**:
|
||||
实现文档删除的完整流程:
|
||||
- 显示删除确认对话框
|
||||
- 显示待删除文档的文件名
|
||||
- 调用删除 API
|
||||
- 处理删除结果(成功刷新列表,失败显示错误)
|
||||
|
||||
**验收标准**:
|
||||
- [ ] 点击"删除"按钮打开确认对话框
|
||||
- [ ] 对话框显示文件名和警告信息
|
||||
- [ ] 点击"确认删除"调用 API
|
||||
- [ ] 删除成功:关闭对话框,刷新列表
|
||||
- [ ] 删除失败:显示错误信息
|
||||
- [ ] 点击"取消"关闭对话框
|
||||
|
||||
**文件**:
|
||||
- 修改: `src/main/resources/static/documents.html` (script 部分)
|
||||
|
||||
---
|
||||
|
||||
### Task 8: 实现筛选功能
|
||||
**优先级**: P0
|
||||
**预计时间**: 30 分钟
|
||||
**依赖**: Task 4
|
||||
|
||||
**描述**:
|
||||
实现文档筛选功能:
|
||||
- 状态下拉框筛选
|
||||
- 故障源输入框筛选(带防抖)
|
||||
- 点击状态卡片快速筛选
|
||||
- 清除筛选
|
||||
- 筛选时重置分页
|
||||
|
||||
**验收标准**:
|
||||
- [ ] 状态下拉框改变时触发筛选
|
||||
- [ ] 故障源输入框使用防抖(300ms)
|
||||
- [ ] 点击状态卡片筛选对应状态的文档
|
||||
- [ ] 筛选后 currentPage 重置为 0
|
||||
- [ ] 筛选结果正确显示
|
||||
|
||||
**文件**:
|
||||
- 修改: `src/main/resources/static/documents.html` (script 部分)
|
||||
|
||||
---
|
||||
|
||||
### Task 9: 实现详情面板
|
||||
**优先级**: P1
|
||||
**预计时间**: 30 分钟
|
||||
**依赖**: Task 4, Task 5
|
||||
|
||||
**描述**:
|
||||
实现文档详情面板功能:
|
||||
- 点击"查看"按钮打开详情面板
|
||||
- 加载文档详细信息
|
||||
- 显示详情面板(滑出动画)
|
||||
- 关闭详情面板
|
||||
|
||||
**验收标准**:
|
||||
- [ ] 点击"查看"按钮打开详情面板
|
||||
- [ ] 调用 API 获取文档详情
|
||||
- [ ] 详情面板从右侧滑出
|
||||
- [ ] 显示完整的文档信息(基本信息、分类信息、索引信息、时间信息)
|
||||
- [ ] 失败文档显示错误信息(红色标注)
|
||||
- [ ] 点击关闭按钮或遮罩关闭面板
|
||||
|
||||
**文件**:
|
||||
- 修改: `src/main/resources/static/documents.html` (script 部分)
|
||||
|
||||
---
|
||||
|
||||
### Task 10: 实现状态统计
|
||||
**优先级**: P0
|
||||
**预计时间**: 20 分钟
|
||||
**依赖**: Task 3, Task 4
|
||||
|
||||
**描述**:
|
||||
实现状态统计功能:
|
||||
- 页面加载时查询各状态文档数量
|
||||
- 更新统计卡片数字
|
||||
- 点击卡片筛选对应状态
|
||||
|
||||
**验收标准**:
|
||||
- [ ] 页面加载时自动查询统计数据
|
||||
- [ ] 4 个状态卡片显示正确数量
|
||||
- [ ] 点击卡片筛选对应状态的文档
|
||||
- [ ] 刷新列表后自动更新统计
|
||||
|
||||
**文件**:
|
||||
- 修改: `src/main/resources/static/documents.html` (script 部分)
|
||||
|
||||
---
|
||||
|
||||
### Task 11: 实现刷新功能
|
||||
**优先级**: P0
|
||||
**预计时间**: 15 分钟
|
||||
**依赖**: Task 4
|
||||
|
||||
**描述**:
|
||||
实现手动刷新功能:
|
||||
- 点击刷新按钮重新加载列表
|
||||
- 保持当前筛选条件
|
||||
- 更新状态统计
|
||||
|
||||
**验收标准**:
|
||||
- [ ] 点击"刷新"按钮重新加载数据
|
||||
- [ ] 保持当前筛选条件不变
|
||||
- [ ] 同时更新统计数据
|
||||
- [ ] 显示加载状态
|
||||
|
||||
**文件**:
|
||||
- 修改: `src/main/resources/static/documents.html` (script 部分)
|
||||
|
||||
---
|
||||
|
||||
### Task 12: 添加页面入口
|
||||
**优先级**: P1
|
||||
**预计时间**: 15 分钟
|
||||
**依赖**: Task 1
|
||||
|
||||
**描述**:
|
||||
在 index.html 的侧边栏添加文档管理页面入口:
|
||||
- 在"新建对话"按钮下方添加导航按钮
|
||||
- 按钮文字:文档管理
|
||||
- 链接到 documents.html
|
||||
|
||||
**验收标准**:
|
||||
- [ ] 侧边栏显示"文档管理"按钮
|
||||
- [ ] 点击按钮跳转到 documents.html
|
||||
- [ ] 按钮样式与"新建对话"按钮一致
|
||||
- [ ] 使用合适的图标(文档图标)
|
||||
|
||||
**文件**:
|
||||
- 修改: `src/main/resources/static/index.html`
|
||||
|
||||
---
|
||||
|
||||
### Task 13: 错误处理和用户提示
|
||||
**优先级**: P0
|
||||
**预计时间**: 30 分钟
|
||||
**依赖**: 所有功能任务
|
||||
|
||||
**描述**:
|
||||
实现统一的错误处理和用户提示:
|
||||
- showError(message) - 显示错误通知
|
||||
- showSuccess(message) - 显示成功通知
|
||||
- showLoading() / hideLoading() - 显示/隐藏全局加载状态
|
||||
- 网络错误处理
|
||||
- API 错误处理
|
||||
|
||||
**验收标准**:
|
||||
- [ ] 通知条在页面顶部显示
|
||||
- [ ] 错误通知红色背景,成功通知绿色背景
|
||||
- [ ] 通知 3 秒后自动消失
|
||||
- [ ] 全局加载状态覆盖整个页面
|
||||
- [ ] 所有 API 调用都有错误处理
|
||||
- [ ] 错误信息清晰友好
|
||||
|
||||
**文件**:
|
||||
- 修改: `src/main/resources/static/documents.html` (script 部分)
|
||||
- 修改: `src/main/resources/static/documents.css`
|
||||
|
||||
---
|
||||
|
||||
### Task 14: 测试和优化
|
||||
**优先级**: P1
|
||||
**预计时间**: 60 分钟
|
||||
**依赖**: 所有功能任务
|
||||
|
||||
**描述**:
|
||||
进行全面测试和优化:
|
||||
- 功能测试(所有操作流程)
|
||||
- 边界测试(空列表、网络错误等)
|
||||
- 浏览器兼容性测试
|
||||
- 性能优化(防抖、缓存)
|
||||
- 代码优化(重构重复代码)
|
||||
|
||||
**验收标准**:
|
||||
- [ ] 所有功能正常工作
|
||||
- [ ] 边界情况处理正确
|
||||
- [ ] Chrome、Firefox、Safari 正常运行
|
||||
- [ ] 无明显性能问题
|
||||
- [ ] 代码结构清晰,无重复代码
|
||||
|
||||
**文件**:
|
||||
- 修改: `src/main/resources/static/documents.html`
|
||||
- 修改: `src/main/resources/static/documents.css`
|
||||
|
||||
---
|
||||
|
||||
## 任务执行顺序
|
||||
|
||||
**阶段 1:基础搭建**
|
||||
1. Task 1: 创建基础 HTML 结构
|
||||
2. Task 2: 实现样式定制
|
||||
|
||||
**阶段 2:核心逻辑**
|
||||
3. Task 3: 实现 API 调用层
|
||||
4. Task 4: 实现状态管理器
|
||||
5. Task 5: 实现 UI 渲染函数
|
||||
|
||||
**阶段 3:功能实现**
|
||||
6. Task 6: 实现文档上传功能
|
||||
7. Task 7: 实现文档删除功能
|
||||
8. Task 8: 实现筛选功能
|
||||
9. Task 10: 实现状态统计
|
||||
10. Task 11: 实现刷新功能
|
||||
11. Task 13: 错误处理和用户提示
|
||||
|
||||
**阶段 4:增强功能**
|
||||
12. Task 9: 实现详情面板
|
||||
13. Task 12: 添加页面入口
|
||||
|
||||
**阶段 5:测试和优化**
|
||||
14. Task 14: 测试和优化
|
||||
|
||||
---
|
||||
|
||||
## 预计总时间
|
||||
|
||||
- P0 任务:约 6 小时
|
||||
- P1 任务:约 2 小时
|
||||
- 总计:约 8 小时
|
||||
|
||||
---
|
||||
|
||||
## 风险和依赖
|
||||
|
||||
**技术风险**:
|
||||
- 文件上传可能受后端配置限制(需确认 max-file-size)
|
||||
- 大文件上传可能超时
|
||||
|
||||
**外部依赖**:
|
||||
- 后端服务必须运行(localhost:9900)
|
||||
- 数据库和 Milvus 服务正常
|
||||
|
||||
**缓解措施**:
|
||||
- 在上传前添加文件大小检查(前端限制 10MB)
|
||||
- 添加详细的错误提示
|
||||
- 提供重试机制
|
||||
Reference in New Issue
Block a user