Skip to content

Commit fdc4f17

Browse files
committed
style: 更新文件管理功能,支持HTML文件图标和颜色,优化文件选择状态管理
1 parent 66abbc9 commit fdc4f17

File tree

6 files changed

+106
-36
lines changed

6 files changed

+106
-36
lines changed

docs/changelog/roadmap.md

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,9 @@
1818
- [ ] 统一图谱数据结构,优化可视化方式 [#298](https://github.com/xerrors/Yuxi-Know/issues/298) <Badge type="info" text="0.4" />
1919
- [ ] 集成智能体评估,首先使用命令行来实现,然后考虑放在 UI 里面展示
2020
- [ ] 开发与生产环境隔离,构建生产镜像 <Badge type="info" text="0.4" />
21-
- [ ] 支持 MinerU 2.5 的解析方法 <Badge type="info" text="0.3.5" />
22-
- [ ] MinerU 处理的结果转义字符没有处理
23-
- [ ] 文件管理:(1)文件选择的时候会跨数据库;(2)文件校验会算上失败的文件;
24-
- [ ] Tasker 中获取历史任务的时候,仅获取 top100 个 task。
21+
- [x] 支持 MinerU 2.5 的解析方法 <Badge type="info" text="0.3.5" />
22+
- [x] 文件管理:(1)文件选择的时候会跨数据库;(2)文件校验会算上失败的文件;
23+
- [x] Tasker 中获取历史任务的时候,仅获取 top100 个 task。
2524

2625

2726
## Later

src/knowledge/manager.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,8 @@ def file_existed_in_db(self, db_id: str | None, content_hash: str | None) -> boo
359359
for file_info in kb_instance.files_meta.values():
360360
if file_info.get("database_id") != db_id:
361361
continue
362+
if file_info.get("status") == "failed":
363+
continue
362364
if file_info.get("content_hash") == content_hash:
363365
return True
364366

web/src/components/FileTable.vue

Lines changed: 39 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,21 @@
1010
>添加文件</a-button>
1111
</div>
1212
<div class="panel-actions">
13+
<a-input
14+
v-model:value="filenameFilter"
15+
placeholder="搜索文件名"
16+
size="small"
17+
class="action-searcher"
18+
allow-clear
19+
@change="onFilterChange"
20+
/>
1321
<a-button
1422
type="text"
1523
@click="handleRefresh"
1624
:loading="refreshing"
17-
:icon="h(ReloadOutlined)"
25+
:icon="h(RefreshCcw)"
1826
title="刷新"
27+
class="panel-action-btn"
1928
/>
2029
<!-- <a-button
2130
@click="toggleAutoRefresh"
@@ -26,22 +35,14 @@
2635
>
2736
Auto
2837
</a-button> -->
29-
<a-input
30-
v-model:value="filenameFilter"
31-
placeholder="搜索文件名"
32-
size="small"
33-
style="width: 120px; margin-right: 8px; border-radius: 6px; padding: 4px 8px;"
34-
allow-clear
35-
@change="onFilterChange"
36-
/>
37-
<!-- <a-button
38+
<a-button
3839
type="text"
3940
@click="toggleRightPanel"
4041
:icon="h(ChevronLast)"
4142
title="切换右侧面板"
4243
class="panel-action-btn expand"
4344
:class="{ 'expanded': props.rightPanelVisible }"
44-
/> -->
45+
/>
4546
</div>
4647
</div>
4748

@@ -134,10 +135,9 @@ import {
134135
ClockCircleFilled,
135136
DeleteOutlined,
136137
PlusOutlined,
137-
ReloadOutlined,
138138
DownloadOutlined,
139139
} from '@ant-design/icons-vue';
140-
import { ChevronLast } from 'lucide-vue-next';
140+
import { ChevronLast, RefreshCcw } from 'lucide-vue-next';
141141
142142
const store = useDatabaseStore();
143143
const userStore = useUserStore();
@@ -403,6 +403,14 @@ import { parseToShanghai } from '@/utils/time';
403403
display: flex;
404404
align-items: center;
405405
gap: 6px;
406+
407+
.action-searcher {
408+
width: 120px;
409+
margin-right: 8px;
410+
border-radius: 6px;
411+
padding: 4px 8px;
412+
border: none;
413+
}
406414
}
407415
408416
.batch-actions-compact {
@@ -500,25 +508,27 @@ import { parseToShanghai } from '@/utils/time';
500508
}
501509
502510
.panel-action-btn {
511+
display: flex;
512+
align-items: center;
513+
justify-content: center;
503514
border-radius: 6px;
504-
border: 1px solid var(--gray-300);
505-
background-color: var(--gray-50);
515+
/* border: 1px solid var(--gray-300); */
516+
/* background-color: var(--gray-50); */
506517
color: var(--gray-700);
507518
transition: all 0.1s ease;
519+
font-size: 12px;
520+
521+
svg {
522+
height: 16px;
523+
}
508524
509525
&.expand {
510526
transform: scaleX(-1);
511527
}
512-
}
513528
514-
.panel-action-btn.expanded {
515-
width: 30px;
516-
height: 30px;
517-
display: flex;
518-
align-items: center;
519-
justify-content: center;
520-
transform: scaleX(1);
521-
padding: 4px;
529+
&.expanded {
530+
transform: scaleX(1);
531+
}
522532
}
523533
524534
.panel-action-btn.auto-refresh-btn.ant-btn-primary {
@@ -535,19 +545,19 @@ import { parseToShanghai } from '@/utils/time';
535545
.panel-action-btn:hover {
536546
background-color: var(--main-5);
537547
color: var(--main-color);
548+
border: 1px solid var(--main-color);
538549
}
539550
540-
.panel-action-btn.expanded:hover {
541-
background-color: var(--main-5);
542-
border-color: var(--main-color);
543-
color: var(--main-color);
544-
}
545551
546552
/* Table row selection styling */
547553
:deep(.ant-table-tbody > tr.ant-table-row-selected > td) {
548554
background-color: var(--main-5);
549555
}
550556
557+
:deep(.ant-table-tbody > tr.ant-table-row-selected.ant-table-row:hover > td) {
558+
background-color: var(--main-20);
559+
}
560+
551561
:deep(.ant-table-tbody > tr:hover > td) {
552562
background-color: var(--main-5);
553563
}

web/src/stores/database.js

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ export const useDatabaseStore = defineStore('database', () => {
4040
});
4141

4242
let refreshInterval = null;
43+
let autoRefreshSource = null; // Tracks whether auto-refresh was user-triggered or automatic
44+
let autoRefreshManualOverride = false; // Indicates user explicitly disabled auto-refresh
4345

4446
// Actions
4547
async function getDatabaseInfo(id) {
@@ -51,6 +53,7 @@ export const useDatabaseStore = defineStore('database', () => {
5153
try {
5254
const data = await databaseApi.getDatabaseInfo(db_id);
5355
database.value = data;
56+
ensureAutoRefreshForProcessing(data?.files);
5457
await loadQueryParams(db_id);
5558
} catch (error) {
5659
console.error(error);
@@ -180,6 +183,40 @@ export const useDatabaseStore = defineStore('database', () => {
180183
});
181184
}
182185

186+
const processingStatuses = new Set(['processing', 'waiting']);
187+
188+
function enableAutoRefresh(source = 'auto') {
189+
if (autoRefreshManualOverride && source === 'auto') {
190+
return;
191+
}
192+
193+
if (!state.autoRefresh) {
194+
state.autoRefresh = true;
195+
autoRefreshSource = source;
196+
autoRefreshManualOverride = false;
197+
startAutoRefresh();
198+
return;
199+
}
200+
201+
if (source === 'auto' && autoRefreshSource !== 'manual') {
202+
autoRefreshSource = 'auto';
203+
}
204+
}
205+
206+
function ensureAutoRefreshForProcessing(filesMap) {
207+
const files = Object.values(filesMap || {});
208+
const hasPending = files.some((file) => file && processingStatuses.has(file.status));
209+
if (hasPending) {
210+
enableAutoRefresh('auto');
211+
} else if (autoRefreshSource === 'auto' && state.autoRefresh) {
212+
state.autoRefresh = false;
213+
autoRefreshSource = null;
214+
autoRefreshManualOverride = false;
215+
stopAutoRefresh();
216+
}
217+
return hasPending;
218+
}
219+
183220
async function addFiles({ items, contentType, params }) {
184221
if (items.length === 0) {
185222
message.error(contentType === 'file' ? '请先上传文件' : '请输入有效的网页链接');
@@ -191,6 +228,7 @@ export const useDatabaseStore = defineStore('database', () => {
191228
const data = await documentApi.addDocuments(databaseId.value, items, { ...params, content_type: contentType });
192229
if (data.status === 'success' || data.status === 'queued') {
193230
const itemType = contentType === 'file' ? '文件' : 'URL';
231+
enableAutoRefresh('auto');
194232
message.success(data.message || `${itemType}已提交处理,请在任务中心查看进度`);
195233
if (data.task_id) {
196234
taskerStore.registerQueuedTask({
@@ -299,10 +337,15 @@ export const useDatabaseStore = defineStore('database', () => {
299337
}
300338

301339
function toggleAutoRefresh() {
302-
state.autoRefresh = !state.autoRefresh;
303-
if (state.autoRefresh) {
340+
const nextState = !state.autoRefresh;
341+
state.autoRefresh = nextState;
342+
if (nextState) {
343+
autoRefreshSource = 'manual';
344+
autoRefreshManualOverride = false;
304345
startAutoRefresh();
305346
} else {
347+
autoRefreshManualOverride = true;
348+
autoRefreshSource = null;
306349
stopAutoRefresh();
307350
}
308351
}

web/src/utils/file_utils.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,10 @@ export const getFileIcon = (filename) => {
3838
'bmp': FileImageFilled,
3939
'svg': FileImageFilled,
4040
'webp': FileImageFilled,
41+
42+
// HTML文件
43+
'html': FileTextFilled,
44+
'htm': FileTextFilled,
4145
}
4246

4347
return iconMap[extension] || FileUnknownFilled
@@ -79,6 +83,10 @@ export const getFileIconColor = (filename) => {
7983
'bmp': '#722ed1',
8084
'svg': '#722ed1',
8185
'webp': '#722ed1',
86+
87+
// HTML文件 - 橙色
88+
'html': '#fa8c16',
89+
'htm': '#fa8c16',
8290
}
8391

8492
return colorMap[extension] || '#8c8c8c'

web/src/views/DataBaseInfoView.vue

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,8 +175,15 @@ const toggleGraphMaximize = () => {
175175
isGraphMaximized.value = !isGraphMaximized.value;
176176
};
177177
178+
const resetFileSelectionState = () => {
179+
store.selectedRowKeys = [];
180+
store.selectedFile = null;
181+
store.state.fileDetailModalVisible = false;
182+
};
183+
178184
watch(() => route.params.database_id, async (newId) => {
179185
store.databaseId = newId;
186+
resetFileSelectionState();
180187
store.stopAutoRefresh();
181188
await store.getDatabaseInfo(newId);
182189
store.startAutoRefresh();
@@ -187,6 +194,7 @@ watch(() => route.params.database_id, async (newId) => {
187194
// 组件挂载时启动示例轮播
188195
onMounted(() => {
189196
store.databaseId = route.params.database_id;
197+
resetFileSelectionState();
190198
store.getDatabaseInfo();
191199
store.startAutoRefresh();
192200
@@ -549,4 +557,4 @@ const handleMouseUpHorizontal = () => {
549557
overflow: hidden;
550558
}
551559
}
552-
</style>
560+
</style>

0 commit comments

Comments
 (0)