feat: add document replacement functionality with file upload
parent
76ba9d0513
commit
620d4ff996
|
|
@ -28,6 +28,7 @@ from common.db.search import native_search, get_dynamics_model, native_page_sear
|
||||||
from common.event import ListenerManagement
|
from common.event import ListenerManagement
|
||||||
from common.event.common import work_thread_pool
|
from common.event.common import work_thread_pool
|
||||||
from common.exception.app_exception import AppApiException
|
from common.exception.app_exception import AppApiException
|
||||||
|
from common.field.common import UploadedFileField
|
||||||
from common.handle.impl.qa.csv_parse_qa_handle import CsvParseQAHandle
|
from common.handle.impl.qa.csv_parse_qa_handle import CsvParseQAHandle
|
||||||
from common.handle.impl.qa.xls_parse_qa_handle import XlsParseQAHandle
|
from common.handle.impl.qa.xls_parse_qa_handle import XlsParseQAHandle
|
||||||
from common.handle.impl.qa.xlsx_parse_qa_handle import XlsxParseQAHandle
|
from common.handle.impl.qa.xlsx_parse_qa_handle import XlsxParseQAHandle
|
||||||
|
|
@ -1503,6 +1504,38 @@ class DocumentSerializers(serializers.Serializer):
|
||||||
tag_id__in=tag_ids
|
tag_id__in=tag_ids
|
||||||
).delete()
|
).delete()
|
||||||
|
|
||||||
|
class ReplaceSourceFile(serializers.Serializer):
|
||||||
|
workspace_id = serializers.CharField(required=True, label=_('workspace id'))
|
||||||
|
knowledge_id = serializers.UUIDField(required=True, label=_('knowledge id'))
|
||||||
|
document_id = serializers.UUIDField(required=True, label=_('document id'))
|
||||||
|
file = UploadedFileField(required=True, label=_("file"))
|
||||||
|
|
||||||
|
def is_valid(self, *, raise_exception=False):
|
||||||
|
super().is_valid(raise_exception=True)
|
||||||
|
workspace_id = self.data.get('workspace_id')
|
||||||
|
query_set = QuerySet(Knowledge).filter(id=self.data.get('knowledge_id'))
|
||||||
|
if workspace_id and workspace_id != 'None':
|
||||||
|
query_set = query_set.filter(workspace_id=workspace_id)
|
||||||
|
if not query_set.exists():
|
||||||
|
raise AppApiException(500, _('Knowledge id does not exist'))
|
||||||
|
if not QuerySet(Document).filter(
|
||||||
|
id=self.data.get('document_id'),
|
||||||
|
knowledge_id=self.data.get('knowledge_id')
|
||||||
|
).exists():
|
||||||
|
raise AppApiException(500, _('Document id does not exist'))
|
||||||
|
|
||||||
|
def replace(self):
|
||||||
|
self.is_valid(raise_exception=True)
|
||||||
|
file = self.data.get('file')
|
||||||
|
source_file = QuerySet(File).filter(source_id=self.data.get('document_id')).first()
|
||||||
|
|
||||||
|
if not source_file:
|
||||||
|
raise AppApiException(500, _('Source file not found'))
|
||||||
|
|
||||||
|
source_file.save(file.read())
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
class FileBufferHandle:
|
class FileBufferHandle:
|
||||||
buffer = None
|
buffer = None
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,7 @@ urlpatterns = [
|
||||||
path('workspace/<str:workspace_id>/knowledge/<str:knowledge_id>/document/<str:document_id>/export', views.DocumentView.Export.as_view()),
|
path('workspace/<str:workspace_id>/knowledge/<str:knowledge_id>/document/<str:document_id>/export', views.DocumentView.Export.as_view()),
|
||||||
path('workspace/<str:workspace_id>/knowledge/<str:knowledge_id>/document/<str:document_id>/export_zip', views.DocumentView.ExportZip.as_view()),
|
path('workspace/<str:workspace_id>/knowledge/<str:knowledge_id>/document/<str:document_id>/export_zip', views.DocumentView.ExportZip.as_view()),
|
||||||
path('workspace/<str:workspace_id>/knowledge/<str:knowledge_id>/document/<str:document_id>/download_source_file', views.DocumentView.DownloadSourceFile.as_view()),
|
path('workspace/<str:workspace_id>/knowledge/<str:knowledge_id>/document/<str:document_id>/download_source_file', views.DocumentView.DownloadSourceFile.as_view()),
|
||||||
|
path('workspace/<str:workspace_id>/knowledge/<str:knowledge_id>/document/<str:document_id>/replace_source_file', views.DocumentView.ReplaceSourceFile.as_view()),
|
||||||
path('workspace/<str:workspace_id>/knowledge/<str:knowledge_id>/document/<str:document_id>/tags', views.DocumentView.Tags.as_view()),
|
path('workspace/<str:workspace_id>/knowledge/<str:knowledge_id>/document/<str:document_id>/tags', views.DocumentView.Tags.as_view()),
|
||||||
path('workspace/<str:workspace_id>/knowledge/<str:knowledge_id>/document/<str:document_id>/tags/batch_delete', views.DocumentView.Tags.BatchDelete.as_view()),
|
path('workspace/<str:workspace_id>/knowledge/<str:knowledge_id>/document/<str:document_id>/tags/batch_delete', views.DocumentView.Tags.BatchDelete.as_view()),
|
||||||
path('workspace/<str:workspace_id>/knowledge/<str:knowledge_id>/document/<str:document_id>/paragraph', views.ParagraphView.as_view()),
|
path('workspace/<str:workspace_id>/knowledge/<str:knowledge_id>/document/<str:document_id>/paragraph', views.ParagraphView.as_view()),
|
||||||
|
|
|
||||||
|
|
@ -686,6 +686,31 @@ class DocumentView(APIView):
|
||||||
'workspace_id': workspace_id, 'document_id': document_id, 'knowledge_id': knowledge_id
|
'workspace_id': workspace_id, 'document_id': document_id, 'knowledge_id': knowledge_id
|
||||||
}).download_source_file()
|
}).download_source_file()
|
||||||
|
|
||||||
|
class ReplaceSourceFile(APIView):
|
||||||
|
authentication_classes = [TokenAuth]
|
||||||
|
|
||||||
|
@extend_schema(
|
||||||
|
summary=_('Replace source file'),
|
||||||
|
operation_id=_('Replace source file'), # type: ignore
|
||||||
|
parameters=DocumentDownloadSourceAPI.get_parameters(),
|
||||||
|
responses=DocumentDownloadSourceAPI.get_response(),
|
||||||
|
tags=[_('Knowledge Base/Documentation')] # type: ignore
|
||||||
|
)
|
||||||
|
@has_permissions(
|
||||||
|
PermissionConstants.KNOWLEDGE_DOCUMENT_EDIT.get_workspace_knowledge_permission(),
|
||||||
|
PermissionConstants.KNOWLEDGE_DOCUMENT_EDIT.get_workspace_permission_workspace_manage_role(),
|
||||||
|
RoleConstants.WORKSPACE_MANAGE.get_workspace_role(),
|
||||||
|
ViewPermission([RoleConstants.USER.get_workspace_role()],
|
||||||
|
[PermissionConstants.KNOWLEDGE.get_workspace_knowledge_permission()], CompareConstants.AND),
|
||||||
|
)
|
||||||
|
def post(self, request: Request, workspace_id: str, knowledge_id: str, document_id: str):
|
||||||
|
return result.success(DocumentSerializers.ReplaceSourceFile(data={
|
||||||
|
'workspace_id': workspace_id,
|
||||||
|
'document_id': document_id,
|
||||||
|
'knowledge_id': knowledge_id,
|
||||||
|
'file': request.FILES.get('file')
|
||||||
|
}).replace())
|
||||||
|
|
||||||
class Tags(APIView):
|
class Tags(APIView):
|
||||||
authentication_classes = [TokenAuth]
|
authentication_classes = [TokenAuth]
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -144,6 +144,14 @@ const getDownloadSourceFile: (knowledge_id: string, document_id: string, documen
|
||||||
return exportFile(document_name, `${prefix.value}/${knowledge_id}/document/${document_id}/download_source_file`, {}, undefined)
|
return exportFile(document_name, `${prefix.value}/${knowledge_id}/document/${document_id}/download_source_file`, {}, undefined)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const postReplaceSourceFile: (knowledge_id: string, document_id: string, data: any) => Promise<Result<any>> = (
|
||||||
|
knowledge_id,
|
||||||
|
document_id,
|
||||||
|
data,
|
||||||
|
) => {
|
||||||
|
return post(`${prefix.value}/${knowledge_id}/document/${document_id}/replace_source_file`, data, {}, undefined)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 导出文档
|
* 导出文档
|
||||||
* @param document_name 文档名称
|
* @param document_name 文档名称
|
||||||
|
|
@ -608,6 +616,7 @@ export default {
|
||||||
putBatchCancelTask,
|
putBatchCancelTask,
|
||||||
putCancelTask,
|
putCancelTask,
|
||||||
getDownloadSourceFile,
|
getDownloadSourceFile,
|
||||||
|
postReplaceSourceFile,
|
||||||
exportDocument,
|
exportDocument,
|
||||||
exportDocumentZip,
|
exportDocumentZip,
|
||||||
putDocumentRefresh,
|
putDocumentRefresh,
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ export default {
|
||||||
cancelGenerate: 'Cancel Generation',
|
cancelGenerate: 'Cancel Generation',
|
||||||
export: 'Export to',
|
export: 'Export to',
|
||||||
download: 'Download',
|
download: 'Download',
|
||||||
|
replace: 'Replace',
|
||||||
},
|
},
|
||||||
|
|
||||||
tip: {
|
tip: {
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ export default {
|
||||||
cancelGenerate: '取消生成',
|
cancelGenerate: '取消生成',
|
||||||
export: '导出',
|
export: '导出',
|
||||||
download: '下载原文档',
|
download: '下载原文档',
|
||||||
|
replace: '替换原文档',
|
||||||
},
|
},
|
||||||
tip: {
|
tip: {
|
||||||
saveMessage: '当前的更改尚未保存,确认退出吗?',
|
saveMessage: '当前的更改尚未保存,确认退出吗?',
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ export default {
|
||||||
cancelGenerate: '取消生成',
|
cancelGenerate: '取消生成',
|
||||||
export: '匯出',
|
export: '匯出',
|
||||||
download: '下載原文件',
|
download: '下載原文件',
|
||||||
|
replace: '替換原文件',
|
||||||
},
|
},
|
||||||
tip: {
|
tip: {
|
||||||
saveMessage: '當前的更改尚未保存,確認退出嗎?',
|
saveMessage: '當前的更改尚未保存,確認退出嗎?',
|
||||||
|
|
|
||||||
|
|
@ -494,6 +494,21 @@
|
||||||
</el-icon>
|
</el-icon>
|
||||||
{{ $t('views.document.setting.download') }}
|
{{ $t('views.document.setting.download') }}
|
||||||
</el-dropdown-item>
|
</el-dropdown-item>
|
||||||
|
<el-upload
|
||||||
|
ref="elUploadRef"
|
||||||
|
:file-list="[]"
|
||||||
|
action="#"
|
||||||
|
:auto-upload="false"
|
||||||
|
:show-file-list="false"
|
||||||
|
:on-change="(file: any, fileList: any) => replaceDocument(file, row)"
|
||||||
|
>
|
||||||
|
<el-dropdown-item v-if="permissionPrecise.doc_edit(id)">
|
||||||
|
<el-icon class="color-secondary">
|
||||||
|
<Upload />
|
||||||
|
</el-icon>
|
||||||
|
{{ $t('views.document.setting.replace') }}
|
||||||
|
</el-dropdown-item>
|
||||||
|
</el-upload>
|
||||||
<el-dropdown-item
|
<el-dropdown-item
|
||||||
@click.stop="deleteDocument(row)"
|
@click.stop="deleteDocument(row)"
|
||||||
v-if="permissionPrecise.doc_delete(id)"
|
v-if="permissionPrecise.doc_delete(id)"
|
||||||
|
|
@ -1079,6 +1094,20 @@ function downloadDocument(row: any) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const elUploadRef = ref()
|
||||||
|
|
||||||
|
function replaceDocument(file: any, row: any) {
|
||||||
|
const formData = new FormData()
|
||||||
|
formData.append('file', file.raw, file.name)
|
||||||
|
elUploadRef.value.clearFiles()
|
||||||
|
loadSharedApi({ type: 'document', systemType: apiType.value })
|
||||||
|
.postReplaceSourceFile(id, row.id, formData, loading)
|
||||||
|
.then(() => {
|
||||||
|
getList()
|
||||||
|
})
|
||||||
|
.catch((e: any) => {})
|
||||||
|
}
|
||||||
|
|
||||||
function deleteDocument(row: any) {
|
function deleteDocument(row: any) {
|
||||||
MsgConfirm(
|
MsgConfirm(
|
||||||
`${t('views.document.delete.confirmTitle3')} ${row.name} ?`,
|
`${t('views.document.delete.confirmTitle3')} ${row.name} ?`,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue