feat: 支持知识库导入 PPTX 与 XLSX 文档

- 打通 Office 文档桥接解析、解析进度承接与图片引用改写

- 落地 PPTX 按页分块、XLSX 行窗口分块以及预览与检索渲染闭环
This commit is contained in:
2026-04-18 13:01:17 +08:00
parent ad67ba85ad
commit 4130381658
28 changed files with 2876 additions and 120 deletions

View File

@@ -1,5 +1,5 @@
<script setup lang="ts">
import { reactive, ref, watch } from 'vue';
import { computed, reactive, ref, watch } from 'vue';
import { $t } from '@easyflow/locales';
@@ -8,6 +8,7 @@ import {
ElForm,
ElFormItem,
ElInput,
ElInputNumber,
ElMessage,
ElOption,
ElSelect,
@@ -85,7 +86,7 @@ const createDefaultFormState = () => ({
mdSplitterLevel: 2,
overlapSize: 128,
regex: '',
rowsPerChunk: 1,
rowsPerChunk: 10,
strategyCode: 'AUTO',
});
@@ -126,6 +127,17 @@ const strategyOptions = [
},
];
const fileExt = computed(() =>
String(props.documentTitle || '')
.split('.')
.pop()
?.toLowerCase() || '',
);
const isPptx = computed(() => fileExt.value === 'pptx');
const isXlsx = computed(() => fileExt.value === 'xlsx');
const showStrategySelector = computed(() => !isPptx.value && !isXlsx.value);
const mdLevels = [1, 2, 3, 4, 5, 6];
const showLengthSettings = (strategyCode?: string) =>
@@ -150,9 +162,22 @@ const resetPreviewState = () => {
previewError.value = '';
};
const buildStrategyConfig = () => ({
...formState,
});
const buildStrategyConfig = () => {
if (isPptx.value) {
return {
strategyCode: 'OFFICE_PPTX_PAGE',
};
}
if (isXlsx.value) {
return {
rowsPerChunk: formState.rowsPerChunk,
strategyCode: 'OFFICE_XLSX_ROW_WINDOW',
};
}
return {
...formState,
};
};
const normalizeSourceRanges = (ranges?: SourceRange[]) =>
Array.isArray(ranges)
@@ -292,6 +317,13 @@ watch(
previewSequence += 1;
clearPreviewTimer();
Object.assign(formState, createDefaultFormState());
if (isPptx.value) {
formState.strategyCode = 'OFFICE_PPTX_PAGE';
}
if (isXlsx.value) {
formState.strategyCode = 'OFFICE_XLSX_ROW_WINDOW';
formState.rowsPerChunk = 10;
}
resetPreviewState();
if (activeDocumentId.value) {
schedulePreviewGeneration();
@@ -317,6 +349,7 @@ watch(
<ElForm :model="formState" label-position="top" class="workbench__form">
<div class="workbench__form-grid">
<ElFormItem
v-if="showStrategySelector"
:label="$t('documentCollection.importDoc.strategySelection')"
class="workbench__form-full"
>
@@ -330,6 +363,20 @@ watch(
</ElSelect>
</ElFormItem>
<ElFormItem
v-if="isXlsx"
label="每多少行分一块"
class="workbench__form-full"
>
<ElInputNumber
v-model="formState.rowsPerChunk"
:min="1"
:max="200"
:step="1"
class="workbench__rows-input"
/>
</ElFormItem>
<ElFormItem
v-if="showLengthSettings(formState.strategyCode)"
:label="$t('documentCollection.splitterDoc.chunkSize')"
@@ -478,6 +525,10 @@ watch(
box-shadow: 0 0 0 1px rgb(15 23 42 / 7%) inset;
}
.workbench__rows-input {
width: 100%;
}
:deep(.workbench__form .el-slider__runway) {
background: rgb(15 23 42 / 8%);
}