-
@@ -12,7 +12,7 @@
-
+
{{ datasetName }}
- {{t('vabI18n.knowledge.document.header.description')}} {{ pagination.total }} {{ $t(pagination.total > 1
- ? 'vabI18n.knowledge.document.header.descriptionEnds'
+ {{t('vabI18n.knowledge.document.header.description')}} {{ pagination.total }} {{ $t(pagination.total > 1
+ ? 'vabI18n.knowledge.document.header.descriptionEnds'
: 'vabI18n.knowledge.document.header.descriptionEnd') }}
-
@@ -90,9 +90,9 @@
@row-dblclick="handleRowDoubleClick"
>
-
-
+
-
-
{{t('vabI18n.knowledge.document.buttons.batchDelete', { count: selectedRows.length })}}
{{t('vabI18n.knowledge.document.buttons.refresh')}}
-
+
{{t('vabI18n.knowledge.document.buttons.upload')}}
-
@@ -117,11 +117,11 @@
-
-
@@ -144,22 +144,22 @@
-
{{t('vabI18n.knowledge.document.buttons.preview')}}
-
-
{{t('vabI18n.knowledge.document.buttons.open', '打开')}}
-
{{t('vabI18n.knowledge.document.buttons.rename')}}
-
{{t('vabI18n.knowledge.document.buttons.delete')}}
@@ -226,16 +226,16 @@
-
-
+
+
-
-
- {{ previewTextContent }}
-
-
-
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+ 分段{{segment.position}}:
+
+
+
- 分段数据
+{{segment.content}}
+
+ 暂无分段数据
+
+
+
+
-
-
+
+
+
- {{ previewTextContent }}
+
+
+
-
- {{t('vabI18n.knowledge.document.renameDialog.label')}}
- {{t('vabI18n.knowledge.document.createFolderDialog.label', '文件夹名称')}}
-
@@ -456,7 +485,8 @@
import { useRoute, useRouter } from 'vue-router'
import { ref, reactive, computed, onMounted, onUnmounted } from 'vue'
import VueOfficePdf from '@vue-office/pdf'
-import { getDatasetDocPage, uploadDocument, deleteDocument, downloadDocument, previewDocumentUrl, renameDocument, createFolder, CreateFolderReq } from '@/api/dataset'
+import { getDatasetDocPage, uploadDocument, deleteDocument, downloadDocument, previewDocumentUrl, renameDocument, createFolder, CreateFolderReq} from '@/api/dataset'
+import {getSegmentList} from "@/api/Segment"
import DocUpload from './DocUpload.vue'
//引入VueOfficeDocx组件
import VueOfficeDocx from '@vue-office/docx'
@@ -467,6 +497,7 @@ import VueOfficeExcel from '@vue-office/excel'
//引入相关样式
import '@vue-office/excel/lib/index.css'
+
import VueOfficePptx from '@vue-office/pptx'
// 引入 markdown 解析器和代码高亮
@@ -539,7 +570,7 @@ folderName: [
{ pattern: /^[^<>:"/\\|?*]+$/, message: t('vabI18n.knowledge.document.createFolderDialog.rules.namePattern', '文件夹名称不能包含特殊字符'), trigger: 'blur' }
]
}
-
+const segmentList= ref([])
// 右键菜单相关
const contextMenuVisible = ref(false)
const contextMenuPosition = reactive({
@@ -559,7 +590,10 @@ name: string;
-
+const handleClose = () => {
+ uploadDialogVisible.value = false
+ segmentList.value = []
+}
// 组件卸载时清理
@@ -675,8 +709,8 @@ if (selectedRows.value.length === 0) {
try {
await ElMessageBox.confirm(
- t('vabI18n.knowledge.document.messages.batchDeleteConfirm', {
- count: selectedRows.value.length
+ t('vabI18n.knowledge.document.messages.batchDeleteConfirm', {
+ count: selectedRows.value.length
}),
t('vabI18n.knowledge.document.messages.deleteConfirmTitle'),
{
@@ -686,6 +720,10 @@ try {
}
)
+ const handleClose = () => {
+ previewDrawerVisible.value = false,
+ segmentList.value = []
+ }
const loading = ElLoading.service({
lock: true,
text: t('vabI18n.knowledge.document.messages.deleteing'),
@@ -759,7 +797,7 @@ try {
message: t('vabI18n.knowledge.document.messages.renameSuccess'),
type: 'success'
})
-
+
renameDialogVisible.value = false
await fetchDocuments()
} catch (error) {
@@ -857,10 +895,10 @@ const handleDownload = async (row: FileItem) => {
try {
// 使用新的API下载方式,传入fileId(数字类型)
const response = await downloadDocument(parseInt(row.id))
-
+
// 创建 Blob 对象
const blob = new Blob([response.data], { type: 'application/octet-stream' })
-
+
// 创建下载链接
const url = window.URL.createObjectURL(blob)
const link = document.createElement('a')
@@ -869,11 +907,11 @@ try {
link.style.display = 'none'
document.body.appendChild(link)
link.click()
-
+
// 清理
document.body.removeChild(link)
window.URL.revokeObjectURL(url)
-
+
} catch (error) {
ElNotification({
title: t('vabI18n.knowledge.document.errors.downloadFailed'),
@@ -896,7 +934,7 @@ try {
// 对于txt和markdown文件,我们需要获取原始文本内容
// 这里可以通过下载接口获取文件内容,然后转为文本
const response = await downloadDocument(fileId)
-
+
// 将响应数据转为文本
if (response.data instanceof Blob) {
const text = await response.data.text()
@@ -916,26 +954,32 @@ const handlePreview = async (row: FileItem) => {
// 显示抽屉
previewDrawerVisible.value = true
previewLoading.value = true
-
- console.log("row",row)
+
previewFileType.value = row.fileType;
try {
// 对于txt和markdown文件,获取文本内容
if (['txt', 'md', 'markdown', 'mdx'].includes(row.fileType.toLowerCase())) {
const content = await fetchFileContent(parseInt(row.id), row.fileType)
-
+
if (row.fileType.toLowerCase() === 'txt') {
previewTextContent.value = content
} else if (['md', 'markdown', 'mdx'].includes(row.fileType.toLowerCase())) {
// 配置并解析 markdown
const renderer = new marked.Renderer()
-
+
marked.setOptions({
breaks: true,
gfm: true
})
-
+ const resp = await getSegmentList({
+ datasetId:datasetId.value,
+ documentId: row.difyDocId
+ })
+ if (resp.data?.length) {
+ segmentList.value = resp.data
+ }
+
previewMarkdownContent.value = marked.parse(content) as string
}
} else {
@@ -1002,7 +1046,7 @@ try {
}
const { data } = await getDatasetDocPage(params)
-
+
// 映射API数据到表格结构,适配新的TDatasetFiles字段
fileList.value = data.content.map((item: any) => ({
id: item.id,
@@ -1077,7 +1121,7 @@ return statusMap[status] || '未知状态'
const getStatusTagType = (status: string): 'success' | 'primary' | 'warning' | 'info' | 'danger' => {
const typeMap: Record = {
'preprocessing': 'info',
- 'indexing': 'warning',
+ 'indexing': 'warning',
'waiting': 'info',
'queued': 'info', // 修改为info类型,显示较深灰色
'failed': 'danger',
@@ -1242,7 +1286,7 @@ try {
}
await createFolder(folderData)
-
+
ElNotification({
title: t('vabI18n.knowledge.document.messages.createFolderSuccess', '创建成功'),
message: t('vabI18n.knowledge.document.messages.createFolderSuccessMessage', `文件夹"${createFolderForm.folderName}"创建成功`),
@@ -1251,7 +1295,7 @@ try {
createFolderDialogVisible.value = false
createFolderForm.folderName = ''
-
+
// 刷新文件列表
await fetchDocuments()
} catch (error) {
@@ -1282,12 +1326,12 @@ margin-bottom: 24px;
align-items: center;
gap: 12px;
margin-bottom: 8px;
-
+
.back-button {
color: #409eff;
font-size: 14px;
padding: 8px 12px;
-
+
&:hover {
background-color: #ecf5ff;
color: #337ecc;
@@ -1310,25 +1354,25 @@ margin-bottom: 24px;
.breadcrumb-container {
margin: 12px 0;
-
+
.breadcrumb-clickable {
cursor: pointer;
-
+
&:hover {
color: #409eff;
}
}
-
+
::v-deep .el-breadcrumb__inner {
display: flex;
align-items: center;
gap: 4px;
-
+
&.is-link:hover {
color: #409eff;
}
}
-
+
::v-deep .el-breadcrumb__item:last-child .el-breadcrumb__inner {
color: #303133;
font-weight: 500;
@@ -1423,7 +1467,7 @@ box-shadow: 0 1px 6px rgba(0, 0, 0, 0.1);
::v-deep .el-table__body tr {
transition: all 0.2s ease;
-
+
&:hover {
background: #f5f7fa !important;
}
@@ -1480,18 +1524,18 @@ flex-wrap: nowrap;
transition: all 0.2s ease;
white-space: nowrap;
flex-shrink: 0;
-
+
&:hover:not(.disabled-btn) {
transform: translateY(-1px);
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
}
-
+
&.disabled-btn {
color: #c0c4cc !important;
cursor: not-allowed !important;
background: transparent !important;
border-color: transparent !important;
-
+
&:hover {
transform: none !important;
box-shadow: none !important;
@@ -1534,7 +1578,7 @@ border-top: 1px solid #ebeef5;
::v-deep .el-dialog__close {
color: white;
font-size: 20px;
-
+
&:hover {
color: rgba(255, 255, 255, 0.8);
transform: scale(1.1);
@@ -1580,7 +1624,7 @@ border-top: 1px solid #ebeef5;
::v-deep .el-dialog__close {
color: white;
font-size: 20px;
-
+
&:hover {
color: rgba(255, 255, 255, 0.8);
transform: scale(1.1) rotate(90deg);
@@ -1595,12 +1639,12 @@ border-top: 1px solid #ebeef5;
.dialog-content {
text-align: center;
-
+
.dialog-icon {
margin-bottom: 24px;
animation: pulse 2s infinite;
}
-
+
.rename-form {
.form-label {
font-size: 16px;
@@ -1609,18 +1653,18 @@ border-top: 1px solid #ebeef5;
margin-bottom: 16px;
text-align: left;
}
-
+
.rename-input {
::v-deep .el-input__wrapper {
border-radius: 12px;
box-shadow: 0 4px 12px rgba(64, 158, 255, 0.1);
border: 2px solid transparent;
transition: all 0.3s ease;
-
+
&:hover {
box-shadow: 0 6px 16px rgba(64, 158, 255, 0.15);
}
-
+
&.is-focus {
border-color: #409eff;
box-shadow: 0 8px 20px rgba(64, 158, 255, 0.2);
@@ -1636,22 +1680,22 @@ border-top: 1px solid #ebeef5;
gap: 16px;
padding: 20px 0;
background: linear-gradient(135deg, #f8fbff 0%, #f0f9ff 100%);
-
+
.el-button {
border-radius: 12px;
padding: 12px 24px;
font-weight: 600;
transition: all 0.3s ease;
-
+
&:hover {
transform: translateY(-2px);
box-shadow: 0 8px 20px rgba(0, 0, 0, 0.1);
}
-
+
&.el-button--primary {
background: linear-gradient(135deg, #409eff 0%, #36cfc9 100%);
border: none;
-
+
&:hover {
background: linear-gradient(135deg, #337ecc 0%, #2bb0a8 100%);
}
@@ -1687,7 +1731,7 @@ border-top: 1px solid #ebeef5;
::v-deep .el-dialog__close {
color: white;
font-size: 20px;
-
+
&:hover {
color: rgba(255, 255, 255, 0.8);
transform: scale(1.1) rotate(90deg);
@@ -1702,12 +1746,12 @@ border-top: 1px solid #ebeef5;
.dialog-content {
text-align: center;
-
+
.dialog-icon {
margin-bottom: 24px;
animation: bounce 2s infinite;
}
-
+
.create-folder-form {
.form-label {
font-size: 16px;
@@ -1716,18 +1760,18 @@ border-top: 1px solid #ebeef5;
margin-bottom: 16px;
text-align: left;
}
-
+
.folder-name-input {
::v-deep .el-input__wrapper {
border-radius: 12px;
box-shadow: 0 4px 12px rgba(103, 194, 58, 0.1);
border: 2px solid transparent;
transition: all 0.3s ease;
-
+
&:hover {
box-shadow: 0 6px 16px rgba(103, 194, 58, 0.15);
}
-
+
&.is-focus {
border-color: #67c23a;
box-shadow: 0 8px 20px rgba(103, 194, 58, 0.2);
@@ -1743,22 +1787,22 @@ border-top: 1px solid #ebeef5;
gap: 16px;
padding: 20px 0;
background: linear-gradient(135deg, #f6ffed 0%, #f0f9ff 100%);
-
+
.el-button {
border-radius: 12px;
padding: 12px 24px;
font-weight: 600;
transition: all 0.3s ease;
-
+
&:hover {
transform: translateY(-2px);
box-shadow: 0 8px 20px rgba(0, 0, 0, 0.1);
}
-
+
&.el-button--primary {
background: linear-gradient(135deg, #67c23a 0%, #85ce61 100%);
border: none;
-
+
&:hover {
background: linear-gradient(135deg, #529e2b 0%, #6cb33f 100%);
}
@@ -1840,18 +1884,18 @@ border-left: 4px solid #e6a23c;
padding: 24px 32px;
color: white;
box-shadow: 0 4px 20px rgba(102, 126, 234, 0.15);
-
+
.el-drawer__title {
font-weight: 700;
color: white;
font-size: 18px;
letter-spacing: 0.5px;
}
-
+
.el-drawer__close-btn {
color: white;
font-size: 20px;
-
+
&:hover {
color: rgba(255, 255, 255, 0.8);
transform: scale(1.1);
@@ -1901,7 +1945,7 @@ background: #fafafa;
border-radius: 4px;
padding: 24px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
-
+
// Markdown 内容样式
h1, h2, h3, h4, h5, h6 {
margin-top: 0;
@@ -1910,45 +1954,45 @@ background: #fafafa;
line-height: 1.25;
color: #24292e;
}
-
+
h1 {
font-size: 2em;
border-bottom: 1px solid #eaecef;
padding-bottom: 0.3em;
}
-
+
h2 {
font-size: 1.5em;
border-bottom: 1px solid #eaecef;
padding-bottom: 0.3em;
}
-
+
h3 {
font-size: 1.25em;
}
-
+
p {
margin-bottom: 16px;
line-height: 1.6;
color: #24292e;
}
-
+
ul, ol {
padding-left: 2em;
margin-bottom: 16px;
}
-
+
li {
margin-bottom: 0.25em;
}
-
+
blockquote {
padding: 0 1em;
color: #6a737d;
border-left: 0.25em solid #dfe2e5;
margin: 0 0 16px 0;
}
-
+
code {
padding: 0.2em 0.4em;
margin: 0;
@@ -1957,7 +2001,7 @@ background: #fafafa;
border-radius: 3px;
font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
}
-
+
pre {
padding: 16px;
overflow: auto;
@@ -1966,7 +2010,7 @@ background: #fafafa;
background-color: #f6f8fa;
border-radius: 6px;
margin-bottom: 16px;
-
+
code {
display: inline;
max-width: auto;
@@ -1979,45 +2023,45 @@ background: #fafafa;
border: 0;
}
}
-
+
table {
border-spacing: 0;
border-collapse: collapse;
margin-bottom: 16px;
width: 100%;
overflow: auto;
-
+
th, td {
padding: 6px 13px;
border: 1px solid #dfe2e5;
}
-
+
th {
font-weight: 600;
background-color: #f6f8fa;
}
-
+
tr:nth-child(2n) {
background-color: #f6f8fa;
}
}
-
+
img {
max-width: 100%;
height: auto;
border-radius: 4px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
-
+
a {
color: #0366d6;
text-decoration: none;
-
+
&:hover {
text-decoration: underline;
}
}
-
+
hr {
height: 0.25em;
padding: 0;
@@ -2093,14 +2137,14 @@ margin-bottom: 20px;
background: linear-gradient(135deg, #f8f9ff 0%, #e8f4fd 100%);
border-radius: 8px;
border: 1px solid #e1e8f0;
-
+
.stat-number {
font-size: 24px;
font-weight: 700;
color: #409eff;
margin-bottom: 4px;
}
-
+
.stat-label {
font-size: 12px;
color: #666;
@@ -2176,7 +2220,7 @@ flex: 0 0 220px;
.progress-status {
margin-top: 8px;
text-align: center;
-
+
.status-tag {
font-weight: 600;
}
@@ -2205,7 +2249,7 @@ overflow: hidden;
color: white;
padding: 16px 20px 12px;
border-bottom: none;
-
+
.menu-title {
font-size: 14px;
font-weight: 600;
@@ -2221,16 +2265,16 @@ overflow: hidden;
cursor: pointer;
transition: all 0.3s ease;
border-bottom: 1px solid #f0f2f5;
-
+
&:last-child {
border-bottom: none;
}
-
+
&:hover {
background: linear-gradient(135deg, #f8fbff 0%, #e8f4fd 100%);
transform: translateX(4px);
}
-
+
.item-icon {
width: 40px;
height: 40px;
@@ -2244,11 +2288,11 @@ overflow: hidden;
flex-shrink: 0;
transition: all 0.3s ease;
}
-
+
.item-content {
flex: 1;
padding-top: 2px;
-
+
.item-title {
font-size: 15px;
font-weight: 600;
@@ -2256,14 +2300,14 @@ overflow: hidden;
margin-bottom: 4px;
line-height: 1.4;
}
-
+
.item-desc {
font-size: 12px;
color: #909399;
line-height: 1.3;
}
}
-
+
&:hover .item-icon {
transform: scale(1.1);
box-shadow: 0 8px 20px rgba(64, 158, 255, 0.3);
@@ -2317,4 +2361,82 @@ transform: scale(0.9) translateY(-5px);
gap: 4px;
}
}
-
\ No newline at end of file
+.segment-list-container {
+ width: 30%;
+ border-right: 1px solid #ebeef5;
+ overflow-y: auto;
+ padding: 16px;
+ background: #f9fafc;
+ display: flex;
+ flex-direction: column;
+ gap: 12px;
+
+ h3 {
+ margin-bottom: 12px;
+ font-size: 16px;
+ font-weight: 600;
+ color: #303133;
+ }
+
+ .el-form-item {
+ cursor: pointer;
+ padding: 16px; // 内边距增加
+ border-radius: 8px;
+ background: white;
+ transition: all 0.2s ease;
+ box-shadow: 0 2px 6px rgba(0, 0, 0, 0.05);
+ min-height: 100px; // 增加最小高度,让卡片更高
+ display: flex;
+ flex-direction: column;
+ justify-content: center; // 让内容垂直居中
+
+ &:hover {
+ background: #f0f4ff;
+ transform: translateX(2px);
+ box-shadow: 0 4px 12px rgba(64, 158, 255, 0.15);
+ }
+
+ span {
+ font-size: 14px;
+ font-weight: 500;
+ color: #606266;
+ margin-top: 4px;
+ word-break: break-word; // 防止长文本溢出
+ }
+
+ h4 {
+ font-family: "Microsoft YaHei", "微软雅黑", sans-serif; // 设置微软雅黑字体
+ font-size: 14px;
+ font-weight: 600;
+ color: #4a4a4a;
+ margin: 0;
+ line-height: 1.6;
+ display: -webkit-box;
+ -webkit-line-clamp: 4;
+ -webkit-box-orient: vertical;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ word-break: break-word;
+ }
+ }
+
+ .empty-state {
+ text-align: center;
+ color: #909399;
+ font-size: 14px;
+ margin-top: 20px;
+ }
+}
+
+/* 右侧预览内容保持原有样式 */
+.preview-content-container {
+ flex: 1;
+ padding: 10px;
+ overflow-y: auto;
+ background: #ffffff;
+ border-radius: 0 8px 8px 0;
+}
+
+
+
+
diff --git a/chat-server/src/main/java/com/bjtds/brichat/controller/DocumentSegmentController.java b/chat-server/src/main/java/com/bjtds/brichat/controller/DocumentSegmentController.java
new file mode 100644
index 0000000..34b91f4
--- /dev/null
+++ b/chat-server/src/main/java/com/bjtds/brichat/controller/DocumentSegmentController.java
@@ -0,0 +1,29 @@
+package com.bjtds.brichat.controller;
+
+import com.bjtds.brichat.entity.dto.SegmentDto;
+import com.bjtds.brichat.service.dify.DocumentSegmentService;
+import com.bjtds.brichat.util.ResultUtils;
+import lombok.extern.slf4j.Slf4j;
+import org.checkerframework.checker.units.qual.C;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.Comparator;
+import java.util.List;
+
+@RestController
+@Slf4j
+@CrossOrigin(value = "*", maxAge = 3600)
+@RequestMapping("/documentSegment")
+public class DocumentSegmentController {
+ @Autowired
+ private DocumentSegmentService documentSegmentService;
+
+ @GetMapping("/selectSegments")
+ public ResultUtils SelectSegments(@RequestParam("documentId") String documentId, @RequestParam("datasetId") String datasetId) {
+ List segments = documentSegmentService.SelectSegments(documentId, datasetId);
+ segments.sort(Comparator.comparing(SegmentDto::getPosition));
+ return ResultUtils.success(segments);
+ }
+}
diff --git a/chat-server/src/main/java/com/bjtds/brichat/mapper/postgresql/DifyDocumentSegmentMapper.java b/chat-server/src/main/java/com/bjtds/brichat/mapper/postgresql/DifyDocumentSegmentMapper.java
new file mode 100644
index 0000000..3691b78
--- /dev/null
+++ b/chat-server/src/main/java/com/bjtds/brichat/mapper/postgresql/DifyDocumentSegmentMapper.java
@@ -0,0 +1,13 @@
+package com.bjtds.brichat.mapper.postgresql;
+
+
+import com.bjtds.brichat.entity.dto.SegmentDto;
+import org.apache.ibatis.annotations.Mapper;
+
+import java.util.List;
+
+@Mapper
+public interface DifyDocumentSegmentMapper {
+
+ List SelectSegmentsByDocumentIdAndDatasetId(String documentId, String datasetId);
+}
diff --git a/chat-server/src/main/java/com/bjtds/brichat/service/dify/DocumentSegmentService.java b/chat-server/src/main/java/com/bjtds/brichat/service/dify/DocumentSegmentService.java
new file mode 100644
index 0000000..46f6f45
--- /dev/null
+++ b/chat-server/src/main/java/com/bjtds/brichat/service/dify/DocumentSegmentService.java
@@ -0,0 +1,10 @@
+package com.bjtds.brichat.service.dify;
+
+import com.bjtds.brichat.entity.dto.SegmentDto;
+
+import java.util.List;
+
+public interface DocumentSegmentService {
+
+ List SelectSegments(String documentId, String datasetId);
+}
diff --git a/chat-server/src/main/java/com/bjtds/brichat/service/dify/impl/DocumentSegmentServiceImpl.java b/chat-server/src/main/java/com/bjtds/brichat/service/dify/impl/DocumentSegmentServiceImpl.java
new file mode 100644
index 0000000..39a5035
--- /dev/null
+++ b/chat-server/src/main/java/com/bjtds/brichat/service/dify/impl/DocumentSegmentServiceImpl.java
@@ -0,0 +1,22 @@
+package com.bjtds.brichat.service.dify.impl;
+
+import com.bjtds.brichat.entity.dto.SegmentDto;
+import com.bjtds.brichat.mapper.postgresql.DifyDocumentSegmentMapper;
+import com.bjtds.brichat.service.dify.DocumentSegmentService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.Collections;
+import java.util.List;
+
+@Service
+public class DocumentSegmentServiceImpl implements DocumentSegmentService {
+
+ @Autowired
+ private DifyDocumentSegmentMapper difyDocumentSegmentMapper;
+
+ @Override
+ public List SelectSegments(String documentId, String datasetId) {
+ return difyDocumentSegmentMapper.SelectSegmentsByDocumentIdAndDatasetId(documentId, datasetId);
+ }
+}
diff --git a/chat-server/src/main/resources/com/bjtds/brichat/mapper/postgresql/DifyDocumentSegmentMapper.xml b/chat-server/src/main/resources/com/bjtds/brichat/mapper/postgresql/DifyDocumentSegmentMapper.xml
new file mode 100644
index 0000000..b6b0efa
--- /dev/null
+++ b/chat-server/src/main/resources/com/bjtds/brichat/mapper/postgresql/DifyDocumentSegmentMapper.xml
@@ -0,0 +1,15 @@
+
+
+
+
+