feat: implement knowledge tag management functionality
parent
56d32c1b71
commit
c47c70afb0
|
|
@ -39,8 +39,11 @@ class Group(Enum):
|
||||||
SYSTEM_RES_KNOWLEDGE = "SYSTEM_RESOURCE_KNOWLEDGE"
|
SYSTEM_RES_KNOWLEDGE = "SYSTEM_RESOURCE_KNOWLEDGE"
|
||||||
KNOWLEDGE_HIT_TEST = "KNOWLEDGE_HIT_TEST"
|
KNOWLEDGE_HIT_TEST = "KNOWLEDGE_HIT_TEST"
|
||||||
KNOWLEDGE_DOCUMENT = "KNOWLEDGE_DOCUMENT"
|
KNOWLEDGE_DOCUMENT = "KNOWLEDGE_DOCUMENT"
|
||||||
|
KNOWLEDGE_TAG = "KNOWLEDGE_TAG"
|
||||||
SYSTEM_KNOWLEDGE_DOCUMENT = "SYSTEM_KNOWLEDGE_DOCUMENT"
|
SYSTEM_KNOWLEDGE_DOCUMENT = "SYSTEM_KNOWLEDGE_DOCUMENT"
|
||||||
SYSTEM_RES_KNOWLEDGE_DOCUMENT = "SYSTEM_RESOURCE_KNOWLEDGE_DOCUMENT"
|
SYSTEM_RES_KNOWLEDGE_DOCUMENT = "SYSTEM_RESOURCE_KNOWLEDGE_DOCUMENT"
|
||||||
|
SYSTEM_RES_KNOWLEDGE_TAG = "SYSTEM_RES_KNOWLEDGE_TAG"
|
||||||
|
SYSTEM_KNOWLEDGE_TAG = "SYSTEM_KNOWLEDGE_TAG"
|
||||||
|
|
||||||
KNOWLEDGE_PROBLEM = "KNOWLEDGE_PROBLEM"
|
KNOWLEDGE_PROBLEM = "KNOWLEDGE_PROBLEM"
|
||||||
SYSTEM_KNOWLEDGE_PROBLEM = "SYSTEM_KNOWLEDGE_PROBLEM"
|
SYSTEM_KNOWLEDGE_PROBLEM = "SYSTEM_KNOWLEDGE_PROBLEM"
|
||||||
|
|
@ -696,6 +699,28 @@ class PermissionConstants(Enum):
|
||||||
resource_permission_group_list=[ResourcePermissionConst.KNOWLEDGE_MANGE],
|
resource_permission_group_list=[ResourcePermissionConst.KNOWLEDGE_MANGE],
|
||||||
parent_group=[WorkspaceGroup.KNOWLEDGE, UserGroup.KNOWLEDGE]
|
parent_group=[WorkspaceGroup.KNOWLEDGE, UserGroup.KNOWLEDGE]
|
||||||
)
|
)
|
||||||
|
KNOWLEDGE_TAG_READ = Permission(
|
||||||
|
group=Group.KNOWLEDGE_TAG, operate=Operate.READ,
|
||||||
|
role_list=[RoleConstants.ADMIN, RoleConstants.USER],
|
||||||
|
resource_permission_group_list=[ResourcePermissionConst.KNOWLEDGE_MANGE],
|
||||||
|
parent_group=[WorkspaceGroup.KNOWLEDGE, UserGroup.KNOWLEDGE]
|
||||||
|
)
|
||||||
|
KNOWLEDGE_TAG_CREATE = Permission(
|
||||||
|
group=Group.KNOWLEDGE_TAG, operate=Operate.CREATE,
|
||||||
|
role_list=[RoleConstants.ADMIN, RoleConstants.USER],
|
||||||
|
resource_permission_group_list=[ResourcePermissionConst.KNOWLEDGE_MANGE],
|
||||||
|
parent_group=[WorkspaceGroup.KNOWLEDGE, UserGroup.KNOWLEDGE]
|
||||||
|
)
|
||||||
|
KNOWLEDGE_TAG_EDIT = Permission(
|
||||||
|
group=Group.KNOWLEDGE_TAG, operate=Operate.EDIT, role_list=[RoleConstants.ADMIN, RoleConstants.USER],
|
||||||
|
resource_permission_group_list=[ResourcePermissionConst.KNOWLEDGE_MANGE],
|
||||||
|
parent_group=[WorkspaceGroup.KNOWLEDGE, UserGroup.KNOWLEDGE]
|
||||||
|
)
|
||||||
|
KNOWLEDGE_TAG_DELETE = Permission(
|
||||||
|
group=Group.KNOWLEDGE_TAG, operate=Operate.DELETE, role_list=[RoleConstants.ADMIN, RoleConstants.USER],
|
||||||
|
resource_permission_group_list=[ResourcePermissionConst.KNOWLEDGE_MANGE],
|
||||||
|
parent_group=[WorkspaceGroup.KNOWLEDGE, UserGroup.KNOWLEDGE]
|
||||||
|
)
|
||||||
APPLICATION_WORKSPACE_USER_RESOURCE_PERMISSION_READ = Permission(
|
APPLICATION_WORKSPACE_USER_RESOURCE_PERMISSION_READ = Permission(
|
||||||
group=Group.APPLICATION_WORKSPACE_USER_RESOURCE_PERMISSION, operate=Operate.READ,
|
group=Group.APPLICATION_WORKSPACE_USER_RESOURCE_PERMISSION, operate=Operate.READ,
|
||||||
role_list=[RoleConstants.ADMIN, RoleConstants.WORKSPACE_MANAGE],
|
role_list=[RoleConstants.ADMIN, RoleConstants.WORKSPACE_MANAGE],
|
||||||
|
|
@ -1199,6 +1224,22 @@ class PermissionConstants(Enum):
|
||||||
group=Group.SYSTEM_KNOWLEDGE_DOCUMENT, operate=Operate.MIGRATE, role_list=[RoleConstants.ADMIN],
|
group=Group.SYSTEM_KNOWLEDGE_DOCUMENT, operate=Operate.MIGRATE, role_list=[RoleConstants.ADMIN],
|
||||||
parent_group=[SystemGroup.SHARED_KNOWLEDGE], is_ee=settings.edition == "EE"
|
parent_group=[SystemGroup.SHARED_KNOWLEDGE], is_ee=settings.edition == "EE"
|
||||||
)
|
)
|
||||||
|
SHARED_KNOWLEDGE_TAG_READ = Permission(
|
||||||
|
group=Group.SYSTEM_KNOWLEDGE_TAG, operate=Operate.READ, role_list=[RoleConstants.ADMIN],
|
||||||
|
parent_group=[SystemGroup.SHARED_KNOWLEDGE], is_ee=settings.edition == "EE"
|
||||||
|
)
|
||||||
|
SHARED_KNOWLEDGE_TAG_CREATE = Permission(
|
||||||
|
group=Group.SYSTEM_KNOWLEDGE_TAG, operate=Operate.CREATE, role_list=[RoleConstants.ADMIN],
|
||||||
|
parent_group=[SystemGroup.SHARED_KNOWLEDGE], is_ee=settings.edition == "EE"
|
||||||
|
)
|
||||||
|
SHARED_KNOWLEDGE_TAG_EDIT = Permission(
|
||||||
|
group=Group.SYSTEM_KNOWLEDGE_TAG, operate=Operate.EDIT, role_list=[RoleConstants.ADMIN],
|
||||||
|
parent_group=[SystemGroup.SHARED_KNOWLEDGE], is_ee=settings.edition == "EE"
|
||||||
|
)
|
||||||
|
SHARED_KNOWLEDGE_TAG_DELETE = Permission(
|
||||||
|
group=Group.SYSTEM_KNOWLEDGE_TAG, operate=Operate.DELETE, role_list=[RoleConstants.ADMIN],
|
||||||
|
parent_group=[SystemGroup.SHARED_KNOWLEDGE], is_ee=settings.edition == "EE"
|
||||||
|
)
|
||||||
SHARED_KNOWLEDGE_PROBLEM_READ = Permission(
|
SHARED_KNOWLEDGE_PROBLEM_READ = Permission(
|
||||||
group=Group.SYSTEM_KNOWLEDGE_PROBLEM, operate=Operate.READ, role_list=[RoleConstants.ADMIN],
|
group=Group.SYSTEM_KNOWLEDGE_PROBLEM, operate=Operate.READ, role_list=[RoleConstants.ADMIN],
|
||||||
parent_group=[SystemGroup.SHARED_KNOWLEDGE], is_ee=settings.edition == "EE"
|
parent_group=[SystemGroup.SHARED_KNOWLEDGE], is_ee=settings.edition == "EE"
|
||||||
|
|
@ -1427,6 +1468,22 @@ class PermissionConstants(Enum):
|
||||||
group=Group.SYSTEM_RES_KNOWLEDGE_PROBLEM, operate=Operate.RELATE, role_list=[RoleConstants.ADMIN],
|
group=Group.SYSTEM_RES_KNOWLEDGE_PROBLEM, operate=Operate.RELATE, role_list=[RoleConstants.ADMIN],
|
||||||
parent_group=[SystemGroup.RESOURCE_KNOWLEDGE], is_ee=settings.edition == "EE"
|
parent_group=[SystemGroup.RESOURCE_KNOWLEDGE], is_ee=settings.edition == "EE"
|
||||||
)
|
)
|
||||||
|
RESOURCE_KNOWLEDGE_TAG_READ = Permission(
|
||||||
|
group=Group.SYSTEM_RES_KNOWLEDGE_TAG, operate=Operate.READ, role_list=[RoleConstants.ADMIN],
|
||||||
|
parent_group=[SystemGroup.RESOURCE_KNOWLEDGE], is_ee=settings.edition == "EE"
|
||||||
|
)
|
||||||
|
RESOURCE_KNOWLEDGE_TAG_CREATE = Permission(
|
||||||
|
group=Group.SYSTEM_RES_KNOWLEDGE_TAG, operate=Operate.CREATE, role_list=[RoleConstants.ADMIN],
|
||||||
|
parent_group=[SystemGroup.RESOURCE_KNOWLEDGE], is_ee=settings.edition == "EE"
|
||||||
|
)
|
||||||
|
RESOURCE_KNOWLEDGE_TAG_EDIT = Permission(
|
||||||
|
group=Group.SYSTEM_RES_KNOWLEDGE_TAG, operate=Operate.EDIT, role_list=[RoleConstants.ADMIN],
|
||||||
|
parent_group=[SystemGroup.RESOURCE_KNOWLEDGE], is_ee=settings.edition == "EE"
|
||||||
|
)
|
||||||
|
RESOURCE_KNOWLEDGE_TAG_DELETE = Permission(
|
||||||
|
group=Group.SYSTEM_RES_KNOWLEDGE_TAG, operate=Operate.DELETE, role_list=[RoleConstants.ADMIN],
|
||||||
|
parent_group=[SystemGroup.RESOURCE_KNOWLEDGE], is_ee=settings.edition == "EE"
|
||||||
|
)
|
||||||
RESOURCE_KNOWLEDGE_CHAT_USER_READ = Permission(
|
RESOURCE_KNOWLEDGE_CHAT_USER_READ = Permission(
|
||||||
group=Group.SYSTEM_RES_KNOWLEDGE_CHAT_USER, operate=Operate.READ, role_list=[RoleConstants.ADMIN],
|
group=Group.SYSTEM_RES_KNOWLEDGE_CHAT_USER, operate=Operate.READ, role_list=[RoleConstants.ADMIN],
|
||||||
parent_group=[SystemGroup.RESOURCE_KNOWLEDGE], is_ee=settings.edition == "EE"
|
parent_group=[SystemGroup.RESOURCE_KNOWLEDGE], is_ee=settings.edition == "EE"
|
||||||
|
|
|
||||||
|
|
@ -535,3 +535,39 @@ class DocumentDownloadSourceAPI(APIMixin):
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_response():
|
def get_response():
|
||||||
return DefaultResultSerializer
|
return DefaultResultSerializer
|
||||||
|
|
||||||
|
|
||||||
|
class DocumentTagsAPI(APIMixin):
|
||||||
|
@staticmethod
|
||||||
|
def get_parameters():
|
||||||
|
return [
|
||||||
|
OpenApiParameter(
|
||||||
|
name="workspace_id",
|
||||||
|
description="工作空间id",
|
||||||
|
type=OpenApiTypes.STR,
|
||||||
|
location='path',
|
||||||
|
required=True,
|
||||||
|
),
|
||||||
|
OpenApiParameter(
|
||||||
|
name="knowledge_id",
|
||||||
|
description="知识库id",
|
||||||
|
type=OpenApiTypes.STR,
|
||||||
|
location='path',
|
||||||
|
required=True,
|
||||||
|
),
|
||||||
|
OpenApiParameter(
|
||||||
|
name="document_id",
|
||||||
|
description="文档id",
|
||||||
|
type=OpenApiTypes.STR,
|
||||||
|
location='path',
|
||||||
|
required=True,
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_request():
|
||||||
|
return None
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_response():
|
||||||
|
return DefaultResultSerializer
|
||||||
|
|
@ -0,0 +1,107 @@
|
||||||
|
from drf_spectacular.types import OpenApiTypes
|
||||||
|
from drf_spectacular.utils import OpenApiParameter
|
||||||
|
|
||||||
|
from common.mixins.api_mixin import APIMixin
|
||||||
|
from common.result import DefaultResultSerializer
|
||||||
|
from knowledge.serializers.tag import TagCreateSerializer, TagEditSerializer
|
||||||
|
|
||||||
|
|
||||||
|
class TagCreateAPI(APIMixin):
|
||||||
|
@staticmethod
|
||||||
|
def get_parameters():
|
||||||
|
return [
|
||||||
|
OpenApiParameter(
|
||||||
|
name="workspace_id",
|
||||||
|
description="工作空间id",
|
||||||
|
type=OpenApiTypes.STR,
|
||||||
|
location='path',
|
||||||
|
required=True,
|
||||||
|
),
|
||||||
|
OpenApiParameter(
|
||||||
|
name="knowledge_id",
|
||||||
|
description="知识库id",
|
||||||
|
type=OpenApiTypes.STR,
|
||||||
|
location='path',
|
||||||
|
required=True,
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_request():
|
||||||
|
return TagCreateSerializer
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_response():
|
||||||
|
return DefaultResultSerializer
|
||||||
|
|
||||||
|
|
||||||
|
class TagDeleteAPI(APIMixin):
|
||||||
|
@staticmethod
|
||||||
|
def get_parameters():
|
||||||
|
return [
|
||||||
|
OpenApiParameter(
|
||||||
|
name="workspace_id",
|
||||||
|
description="工作空间id",
|
||||||
|
type=OpenApiTypes.STR,
|
||||||
|
location='path',
|
||||||
|
required=True,
|
||||||
|
),
|
||||||
|
OpenApiParameter(
|
||||||
|
name="knowledge_id",
|
||||||
|
description="知识库id",
|
||||||
|
type=OpenApiTypes.STR,
|
||||||
|
location='path',
|
||||||
|
required=True,
|
||||||
|
),
|
||||||
|
OpenApiParameter(
|
||||||
|
name="tag_id",
|
||||||
|
description="标签id",
|
||||||
|
type=OpenApiTypes.STR,
|
||||||
|
location='path',
|
||||||
|
required=True,
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_request():
|
||||||
|
return None
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_response():
|
||||||
|
return DefaultResultSerializer
|
||||||
|
|
||||||
|
|
||||||
|
class TagEditAPI(APIMixin):
|
||||||
|
@staticmethod
|
||||||
|
def get_parameters():
|
||||||
|
return [
|
||||||
|
OpenApiParameter(
|
||||||
|
name="workspace_id",
|
||||||
|
description="工作空间id",
|
||||||
|
type=OpenApiTypes.STR,
|
||||||
|
location='path',
|
||||||
|
required=True,
|
||||||
|
),
|
||||||
|
OpenApiParameter(
|
||||||
|
name="knowledge_id",
|
||||||
|
description="知识库id",
|
||||||
|
type=OpenApiTypes.STR,
|
||||||
|
location='path',
|
||||||
|
required=True,
|
||||||
|
),
|
||||||
|
OpenApiParameter(
|
||||||
|
name="tag_id",
|
||||||
|
description="标签id",
|
||||||
|
type=OpenApiTypes.STR,
|
||||||
|
location='path',
|
||||||
|
required=True,
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_request():
|
||||||
|
return TagEditSerializer
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_response():
|
||||||
|
return DefaultResultSerializer
|
||||||
|
|
@ -0,0 +1,54 @@
|
||||||
|
# Generated by Django 5.2.7 on 2025-10-11 07:38
|
||||||
|
|
||||||
|
import django.db.models.deletion
|
||||||
|
import uuid_utils.compat
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('knowledge', '0002_alter_file_source_type'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Tag',
|
||||||
|
fields=[
|
||||||
|
('create_time', models.DateTimeField(auto_now_add=True, db_index=True, verbose_name='创建时间')),
|
||||||
|
('update_time', models.DateTimeField(auto_now=True, db_index=True, verbose_name='修改时间')),
|
||||||
|
('id', models.UUIDField(default=uuid_utils.compat.uuid7, editable=False, primary_key=True, serialize=False, verbose_name='主键id')),
|
||||||
|
('key', models.CharField(db_index=True, max_length=64, verbose_name='标签键')),
|
||||||
|
('value', models.CharField(db_index=True, max_length=128, verbose_name='标签值')),
|
||||||
|
('knowledge', models.ForeignKey(db_constraint=False, on_delete=django.db.models.deletion.DO_NOTHING, to='knowledge.knowledge', verbose_name='知识库')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'db_table': 'tag',
|
||||||
|
},
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='DocumentTag',
|
||||||
|
fields=[
|
||||||
|
('create_time', models.DateTimeField(auto_now_add=True, db_index=True, verbose_name='创建时间')),
|
||||||
|
('update_time', models.DateTimeField(auto_now=True, db_index=True, verbose_name='修改时间')),
|
||||||
|
('id', models.UUIDField(default=uuid_utils.compat.uuid7, editable=False, primary_key=True, serialize=False, verbose_name='主键id')),
|
||||||
|
('document', models.ForeignKey(db_constraint=False, on_delete=django.db.models.deletion.DO_NOTHING, to='knowledge.document', verbose_name='文档')),
|
||||||
|
('tag', models.ForeignKey(db_constraint=False, on_delete=django.db.models.deletion.DO_NOTHING, to='knowledge.tag', verbose_name='标签')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'db_table': 'document_tag',
|
||||||
|
},
|
||||||
|
),
|
||||||
|
migrations.AddIndex(
|
||||||
|
model_name='tag',
|
||||||
|
index=models.Index(fields=['knowledge', 'key'], name='tag_knowled_cba590_idx'),
|
||||||
|
),
|
||||||
|
migrations.AlterUniqueTogether(
|
||||||
|
name='tag',
|
||||||
|
unique_together={('knowledge', 'key', 'value')},
|
||||||
|
),
|
||||||
|
migrations.AlterUniqueTogether(
|
||||||
|
name='documenttag',
|
||||||
|
unique_together={('document', 'tag')},
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
@ -162,6 +162,35 @@ class Document(AppModelMixin):
|
||||||
class Meta:
|
class Meta:
|
||||||
db_table = "document"
|
db_table = "document"
|
||||||
|
|
||||||
|
class Tag(AppModelMixin):
|
||||||
|
"""
|
||||||
|
标签表 - 存储标签的key-value定义
|
||||||
|
"""
|
||||||
|
id = models.UUIDField(primary_key=True, max_length=128, default=uuid.uuid7, editable=False, verbose_name="主键id")
|
||||||
|
knowledge = models.ForeignKey(Knowledge, on_delete=models.DO_NOTHING, verbose_name="知识库", db_constraint=False)
|
||||||
|
key = models.CharField(max_length=64, verbose_name="标签键", db_index=True)
|
||||||
|
value = models.CharField(max_length=128, verbose_name="标签值", db_index=True)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
db_table = "tag"
|
||||||
|
unique_together = [['knowledge', 'key', 'value']] # 在同一知识库内key-value组合唯一
|
||||||
|
indexes = [
|
||||||
|
models.Index(fields=['knowledge', 'key']),
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
class DocumentTag(AppModelMixin):
|
||||||
|
"""
|
||||||
|
文档标签关联表
|
||||||
|
"""
|
||||||
|
id = models.UUIDField(primary_key=True, max_length=128, default=uuid.uuid7, editable=False, verbose_name="主键id")
|
||||||
|
document = models.ForeignKey(Document, on_delete=models.DO_NOTHING, verbose_name="文档", db_constraint=False)
|
||||||
|
tag = models.ForeignKey(Tag, on_delete=models.DO_NOTHING, verbose_name="标签", db_constraint=False)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
db_table = "document_tag"
|
||||||
|
unique_together = [['document', 'tag']] # 文档和标签的组合唯一
|
||||||
|
|
||||||
|
|
||||||
class Paragraph(AppModelMixin):
|
class Paragraph(AppModelMixin):
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ import json
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import traceback
|
import traceback
|
||||||
|
from collections import defaultdict
|
||||||
from functools import reduce
|
from functools import reduce
|
||||||
from tempfile import TemporaryDirectory
|
from tempfile import TemporaryDirectory
|
||||||
from typing import Dict, List
|
from typing import Dict, List
|
||||||
|
|
@ -15,8 +16,8 @@ from django.core import validators
|
||||||
from django.db import transaction, models
|
from django.db import transaction, models
|
||||||
from django.db.models import QuerySet, Func, F, Value
|
from django.db.models import QuerySet, Func, F, Value
|
||||||
from django.db.models.aggregates import Max
|
from django.db.models.aggregates import Max
|
||||||
from django.db.models.fields.json import KeyTextTransform
|
from django.db.models.functions import Substr, Reverse
|
||||||
from django.db.models.functions import Substr, Reverse, Coalesce, Cast
|
from django.db.models.query_utils import Q
|
||||||
from django.http import HttpResponse
|
from django.http import HttpResponse
|
||||||
from django.utils.translation import gettext_lazy as _, gettext, get_language, to_locale
|
from django.utils.translation import gettext_lazy as _, gettext, get_language, to_locale
|
||||||
from openpyxl.cell.cell import ILLEGAL_CHARACTERS_RE
|
from openpyxl.cell.cell import ILLEGAL_CHARACTERS_RE
|
||||||
|
|
@ -47,7 +48,7 @@ from common.utils.fork import Fork
|
||||||
from common.utils.logger import maxkb_logger
|
from common.utils.logger import maxkb_logger
|
||||||
from common.utils.split_model import get_split_model, flat_map
|
from common.utils.split_model import get_split_model, flat_map
|
||||||
from knowledge.models import Knowledge, Paragraph, Problem, Document, KnowledgeType, ProblemParagraphMapping, State, \
|
from knowledge.models import Knowledge, Paragraph, Problem, Document, KnowledgeType, ProblemParagraphMapping, State, \
|
||||||
TaskType, File, FileSourceType
|
TaskType, File, FileSourceType, Tag, DocumentTag
|
||||||
from knowledge.serializers.common import ProblemParagraphManage, BatchSerializer, \
|
from knowledge.serializers.common import ProblemParagraphManage, BatchSerializer, \
|
||||||
get_embedding_model_id_by_knowledge_id, MetaSerializer, write_image, zip_dir
|
get_embedding_model_id_by_knowledge_id, MetaSerializer, write_image, zip_dir
|
||||||
from knowledge.serializers.paragraph import ParagraphSerializers, ParagraphInstanceSerializer, \
|
from knowledge.serializers.paragraph import ParagraphSerializers, ParagraphInstanceSerializer, \
|
||||||
|
|
@ -1286,6 +1287,35 @@ class DocumentSerializers(serializers.Serializer):
|
||||||
except AlreadyQueued as e:
|
except AlreadyQueued as e:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def batch_add_tag(self, instance: Dict, with_valid=True):
|
||||||
|
if with_valid:
|
||||||
|
self.is_valid(raise_exception=True)
|
||||||
|
document_id_list = instance.get("document_ids")
|
||||||
|
tag_id_list = instance.get("tag_ids")
|
||||||
|
# 批量查询已存在的标签关联关系
|
||||||
|
existing_relations = {
|
||||||
|
(str(doc_id), str(tag_id))
|
||||||
|
for doc_id, tag_id in QuerySet(DocumentTag).filter(
|
||||||
|
document_id__in=document_id_list,
|
||||||
|
tag_id__in=tag_id_list
|
||||||
|
).values_list('document_id', 'tag_id')
|
||||||
|
}
|
||||||
|
|
||||||
|
# 批量创建不存在的关联关系
|
||||||
|
new_relations = [
|
||||||
|
DocumentTag(
|
||||||
|
id=uuid.uuid7(),
|
||||||
|
document_id=document_id,
|
||||||
|
tag_id=tag_id,
|
||||||
|
)
|
||||||
|
for document_id in document_id_list
|
||||||
|
for tag_id in tag_id_list
|
||||||
|
if (document_id, tag_id) not in existing_relations
|
||||||
|
]
|
||||||
|
|
||||||
|
if new_relations:
|
||||||
|
QuerySet(DocumentTag).bulk_create(new_relations)
|
||||||
|
|
||||||
class BatchGenerateRelated(serializers.Serializer):
|
class BatchGenerateRelated(serializers.Serializer):
|
||||||
workspace_id = serializers.CharField(required=True, label=_('workspace id'))
|
workspace_id = serializers.CharField(required=True, label=_('workspace id'))
|
||||||
knowledge_id = serializers.UUIDField(required=True, label=_('knowledge id'))
|
knowledge_id = serializers.UUIDField(required=True, label=_('knowledge id'))
|
||||||
|
|
@ -1328,10 +1358,149 @@ class DocumentSerializers(serializers.Serializer):
|
||||||
QuerySet(Document).filter(id__in=document_id_list))()
|
QuerySet(Document).filter(id__in=document_id_list))()
|
||||||
try:
|
try:
|
||||||
for document_id in document_id_list:
|
for document_id in document_id_list:
|
||||||
generate_related_by_document_id.delay(document_id, model_id, model_params_setting, prompt, state_list)
|
generate_related_by_document_id.delay(
|
||||||
|
document_id, model_id, model_params_setting, prompt, state_list
|
||||||
|
)
|
||||||
except AlreadyQueued as e:
|
except AlreadyQueued as e:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
class Tags(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'))
|
||||||
|
name = serializers.CharField(required=False, allow_null=True, allow_blank=True, label=_('search value'))
|
||||||
|
|
||||||
|
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 list(self):
|
||||||
|
self.is_valid(raise_exception=True)
|
||||||
|
|
||||||
|
tag_ids = QuerySet(DocumentTag).filter(
|
||||||
|
document_id=self.data.get('document_id')
|
||||||
|
).values_list('tag_id', flat=True)
|
||||||
|
|
||||||
|
if self.data.get('name'):
|
||||||
|
tag_ids = QuerySet(Tag).filter(
|
||||||
|
knowledge_id=self.data.get('knowledge_id'),
|
||||||
|
id__in=tag_ids,
|
||||||
|
).filter(
|
||||||
|
Q(key__icontains=self.data.get('name')) | Q(value__icontains=self.data.get('name'))
|
||||||
|
).values_list('id', flat=True)
|
||||||
|
|
||||||
|
# 获取所有标签,按创建时间排序保持稳定顺序
|
||||||
|
tags = QuerySet(Tag).filter(
|
||||||
|
knowledge_id=self.data.get('knowledge_id'),
|
||||||
|
id__in=tag_ids
|
||||||
|
).values('key', 'value', 'id', 'create_time', 'update_time').order_by('create_time', 'key', 'value')
|
||||||
|
|
||||||
|
# 按key分组
|
||||||
|
grouped_tags = defaultdict(list)
|
||||||
|
for tag in tags:
|
||||||
|
grouped_tags[tag['key']].append({
|
||||||
|
'id': tag['id'],
|
||||||
|
'value': tag['value'],
|
||||||
|
'create_time': tag['create_time'],
|
||||||
|
'update_time': tag['update_time']
|
||||||
|
})
|
||||||
|
|
||||||
|
# 转换为期望的格式,保持key的顺序
|
||||||
|
result = []
|
||||||
|
# 按key排序以确保结果顺序一致
|
||||||
|
for key in sorted(grouped_tags.keys()):
|
||||||
|
values = grouped_tags[key]
|
||||||
|
# 按创建时间对values进行排序
|
||||||
|
values.sort(key=lambda x: x['create_time'])
|
||||||
|
result.append({
|
||||||
|
'key': key,
|
||||||
|
'values': values,
|
||||||
|
})
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
class AddTags(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'))
|
||||||
|
tag_ids = serializers.ListField(
|
||||||
|
required=True, label=_('tag ids'), child=serializers.UUIDField(required=True, label=_('tag id'))
|
||||||
|
)
|
||||||
|
|
||||||
|
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 add_tags(self):
|
||||||
|
self.is_valid(raise_exception=True)
|
||||||
|
document_id = self.data.get('document_id')
|
||||||
|
tag_ids = self.data.get('tag_ids')
|
||||||
|
existing_tag_ids = set(
|
||||||
|
QuerySet(DocumentTag).filter(
|
||||||
|
document_id=document_id, tag_id__in=tag_ids
|
||||||
|
).values_list('tag_id', flat=True)
|
||||||
|
)
|
||||||
|
new_tags = [
|
||||||
|
DocumentTag(
|
||||||
|
id=uuid.uuid7(),
|
||||||
|
document_id=document_id,
|
||||||
|
tag_id=tag_id
|
||||||
|
) for tag_id in tag_ids if tag_id not in existing_tag_ids
|
||||||
|
]
|
||||||
|
if new_tags:
|
||||||
|
QuerySet(DocumentTag).bulk_create(new_tags)
|
||||||
|
|
||||||
|
class DeleteTags(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'))
|
||||||
|
tag_ids = serializers.ListField(
|
||||||
|
required=True, label=_('tag ids'), child=serializers.UUIDField(required=True, label=_('tag id'))
|
||||||
|
)
|
||||||
|
|
||||||
|
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 delete_tags(self):
|
||||||
|
self.is_valid(raise_exception=True)
|
||||||
|
document_id = self.data.get('document_id')
|
||||||
|
tag_ids = self.data.get('tag_ids')
|
||||||
|
QuerySet(DocumentTag).filter(
|
||||||
|
document_id=document_id,
|
||||||
|
tag_id__in=tag_ids
|
||||||
|
).delete()
|
||||||
|
|
||||||
|
|
||||||
class FileBufferHandle:
|
class FileBufferHandle:
|
||||||
buffer = None
|
buffer = None
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,250 @@
|
||||||
|
# coding=utf-8
|
||||||
|
"""
|
||||||
|
@project: maxkb
|
||||||
|
@Author:AI Assistant
|
||||||
|
@file: tag.py
|
||||||
|
@date:2025/10/13
|
||||||
|
@desc: 标签系统相关序列化器
|
||||||
|
"""
|
||||||
|
from collections import defaultdict
|
||||||
|
from typing import Dict
|
||||||
|
|
||||||
|
import uuid_utils.compat as uuid
|
||||||
|
from django.db import transaction
|
||||||
|
from django.db.models import QuerySet
|
||||||
|
from django.db.models.query_utils import Q
|
||||||
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
from rest_framework import serializers
|
||||||
|
|
||||||
|
from common.exception.app_exception import AppApiException
|
||||||
|
from knowledge.models import Tag, Knowledge, DocumentTag
|
||||||
|
|
||||||
|
|
||||||
|
class TagModelSerializer(serializers.ModelSerializer):
|
||||||
|
"""标签模型序列化器"""
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = Tag
|
||||||
|
fields = ['id', 'knowledge_id', 'key', 'value', 'create_time', 'update_time']
|
||||||
|
read_only_fields = ['id', 'create_time', 'update_time']
|
||||||
|
|
||||||
|
|
||||||
|
class TagCreateSerializer(serializers.Serializer):
|
||||||
|
"""创建标签序列化器"""
|
||||||
|
key = serializers.CharField(required=True, max_length=64, label=_('Tag Key'))
|
||||||
|
value = serializers.CharField(required=True, max_length=128, label=_('Tag Value'))
|
||||||
|
|
||||||
|
|
||||||
|
class TagEditSerializer(serializers.Serializer):
|
||||||
|
key = serializers.CharField(required=False, max_length=64, label=_('Tag Key'))
|
||||||
|
value = serializers.CharField(required=False, max_length=128, label=_('Tag Value'))
|
||||||
|
|
||||||
|
|
||||||
|
class TagSerializers(serializers.Serializer):
|
||||||
|
class Create(serializers.Serializer):
|
||||||
|
workspace_id = serializers.CharField(required=True, label=_('Workspace ID'))
|
||||||
|
knowledge_id = serializers.UUIDField(required=True, label=_('Knowledge ID'))
|
||||||
|
tags = serializers.ListField(required=True, label=_('Tags'), child=TagCreateSerializer())
|
||||||
|
|
||||||
|
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'))
|
||||||
|
|
||||||
|
def insert(self):
|
||||||
|
self.is_valid(raise_exception=True)
|
||||||
|
|
||||||
|
knowledge_id = self.data.get('knowledge_id')
|
||||||
|
|
||||||
|
# 获取数据库中已存在的key-value组合
|
||||||
|
existing_tags = set(
|
||||||
|
QuerySet(Tag).filter(knowledge_id=knowledge_id)
|
||||||
|
.values_list('key', 'value', named=False)
|
||||||
|
)
|
||||||
|
|
||||||
|
# 过滤掉已存在的标签
|
||||||
|
tag_objects = []
|
||||||
|
for tag_data in self.data.get('tags', []):
|
||||||
|
key = tag_data.get('key')
|
||||||
|
value = tag_data.get('value')
|
||||||
|
|
||||||
|
# 检查key-value组合是否已存在
|
||||||
|
if (key, value) not in existing_tags:
|
||||||
|
tag = Tag(
|
||||||
|
id=uuid.uuid7(),
|
||||||
|
knowledge_id=knowledge_id,
|
||||||
|
key=key,
|
||||||
|
value=value
|
||||||
|
)
|
||||||
|
tag_objects.append(tag)
|
||||||
|
# 将新标签添加到已存在集合中,避免本次批量插入中的重复
|
||||||
|
existing_tags.add((key, value))
|
||||||
|
|
||||||
|
# 批量插入未重复的标签
|
||||||
|
if tag_objects:
|
||||||
|
Tag.objects.bulk_create(tag_objects)
|
||||||
|
|
||||||
|
class Operate(serializers.Serializer):
|
||||||
|
workspace_id = serializers.CharField(required=True, label=_('Workspace ID'))
|
||||||
|
knowledge_id = serializers.UUIDField(required=True, label=_('Knowledge ID'))
|
||||||
|
tag_id = serializers.UUIDField(required=True, label=_('Tag ID'))
|
||||||
|
|
||||||
|
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'))
|
||||||
|
|
||||||
|
@transaction.atomic
|
||||||
|
def edit(self, instance: Dict):
|
||||||
|
self.is_valid(raise_exception=True)
|
||||||
|
tag = QuerySet(Tag).get(id=self.data.get('tag_id'))
|
||||||
|
if tag is None:
|
||||||
|
raise AppApiException(500, _('Tag id does not exist'))
|
||||||
|
|
||||||
|
# 如果key发生变化,更新所有相同key的标签
|
||||||
|
if instance.get('key') and instance.get('key') != tag.key:
|
||||||
|
old_key = tag.key
|
||||||
|
new_key = instance.get('key')
|
||||||
|
|
||||||
|
# 检查新key是否已存在于同一个knowledge中
|
||||||
|
existing_key_exists = QuerySet(Tag).filter(
|
||||||
|
knowledge_id=tag.knowledge_id,
|
||||||
|
key=new_key
|
||||||
|
).exists()
|
||||||
|
|
||||||
|
if existing_key_exists:
|
||||||
|
raise AppApiException(500, _('Tag key already exists'))
|
||||||
|
|
||||||
|
# 批量更新所有具有相同old_key的标签
|
||||||
|
QuerySet(Tag).filter(
|
||||||
|
knowledge_id=tag.knowledge_id,
|
||||||
|
key=old_key
|
||||||
|
).update(key=new_key)
|
||||||
|
|
||||||
|
# 如果只是value变化,只更新当前标签
|
||||||
|
if instance.get('value') and instance.get('value') != tag.value:
|
||||||
|
# 检查新key是否已存在于同一个knowledge中
|
||||||
|
existing_value_exists = QuerySet(Tag).filter(
|
||||||
|
knowledge_id=tag.knowledge_id,
|
||||||
|
key=instance.get('key'),
|
||||||
|
value=instance.get('value')
|
||||||
|
).exists()
|
||||||
|
|
||||||
|
if existing_value_exists:
|
||||||
|
raise AppApiException(500, _('Tag value already exists'))
|
||||||
|
QuerySet(Tag).filter(
|
||||||
|
id=tag.id
|
||||||
|
).update(value=instance.get('value'))
|
||||||
|
|
||||||
|
@transaction.atomic
|
||||||
|
def delete(self, delete_type: str):
|
||||||
|
self.is_valid(raise_exception=True)
|
||||||
|
if delete_type == 'key':
|
||||||
|
# 删除同一knowledge_id下相同key的所有标签
|
||||||
|
tag = QuerySet(Tag).get(id=self.data.get('tag_id'))
|
||||||
|
if tag is None:
|
||||||
|
raise AppApiException(500, _('Tag id does not exist'))
|
||||||
|
QuerySet(Tag).filter(
|
||||||
|
knowledge_id=tag.knowledge_id,
|
||||||
|
key=tag.key
|
||||||
|
).delete()
|
||||||
|
QuerySet(DocumentTag).filter(tag_id=tag.id).delete()
|
||||||
|
else:
|
||||||
|
# 仅删除当前标签
|
||||||
|
QuerySet(Tag).filter(id=self.data.get('tag_id')).delete()
|
||||||
|
QuerySet(DocumentTag).filter(tag_id=self.data.get('tag_id')).delete()
|
||||||
|
|
||||||
|
class BatchDelete(serializers.Serializer):
|
||||||
|
workspace_id = serializers.CharField(required=True, label=_('Workspace ID'))
|
||||||
|
knowledge_id = serializers.UUIDField(required=True, label=_('Knowledge ID'))
|
||||||
|
tag_ids = serializers.ListField(required=True, label=_('Tag IDs'), child=serializers.UUIDField())
|
||||||
|
|
||||||
|
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'))
|
||||||
|
|
||||||
|
@transaction.atomic
|
||||||
|
def batch_delete(self):
|
||||||
|
self.is_valid(raise_exception=True)
|
||||||
|
tag_ids = self.data.get('tag_ids', [])
|
||||||
|
if not tag_ids:
|
||||||
|
return
|
||||||
|
|
||||||
|
# 获取要删除的标签的key
|
||||||
|
tags_to_delete = QuerySet(Tag).filter(id__in=tag_ids)
|
||||||
|
keys_to_delete = set(tags_to_delete.values_list('key', flat=True))
|
||||||
|
|
||||||
|
# 删除具有相同key的所有标签
|
||||||
|
QuerySet(Tag).filter(
|
||||||
|
knowledge_id=self.data.get('knowledge_id'),
|
||||||
|
key__in=keys_to_delete
|
||||||
|
).delete()
|
||||||
|
|
||||||
|
# 删除关联的DocumentTag
|
||||||
|
QuerySet(DocumentTag).filter(tag_id__in=tag_ids).delete()
|
||||||
|
|
||||||
|
class Query(serializers.Serializer):
|
||||||
|
workspace_id = serializers.CharField(required=True, label=_('Workspace ID'))
|
||||||
|
knowledge_id = serializers.UUIDField(required=True, label=_('Knowledge ID'))
|
||||||
|
name = serializers.CharField(required=False, allow_null=True, allow_blank=True, label=_('search value'))
|
||||||
|
|
||||||
|
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'))
|
||||||
|
|
||||||
|
def list(self):
|
||||||
|
self.is_valid(raise_exception=True)
|
||||||
|
if self.data.get('name'):
|
||||||
|
name = self.data.get('name')
|
||||||
|
tags = QuerySet(Tag).filter(
|
||||||
|
knowledge_id=self.data.get('knowledge_id')
|
||||||
|
).filter(
|
||||||
|
Q(key__icontains=name) | Q(value__icontains=name)
|
||||||
|
).values('key', 'value', 'id', 'create_time', 'update_time').order_by('create_time', 'key', 'value')
|
||||||
|
else:
|
||||||
|
# 获取所有标签,按创建时间排序保持稳定顺序
|
||||||
|
tags = QuerySet(Tag).filter(
|
||||||
|
knowledge_id=self.data.get('knowledge_id')
|
||||||
|
).values('key', 'value', 'id', 'create_time', 'update_time').order_by('create_time', 'key', 'value')
|
||||||
|
|
||||||
|
# 按key分组
|
||||||
|
grouped_tags = defaultdict(list)
|
||||||
|
for tag in tags:
|
||||||
|
grouped_tags[tag['key']].append({
|
||||||
|
'id': tag['id'],
|
||||||
|
'value': tag['value'],
|
||||||
|
'create_time': tag['create_time'],
|
||||||
|
'update_time': tag['update_time']
|
||||||
|
})
|
||||||
|
|
||||||
|
# 转换为期望的格式,保持key的顺序
|
||||||
|
result = []
|
||||||
|
# 按key排序以确保结果顺序一致
|
||||||
|
for key in sorted(grouped_tags.keys()):
|
||||||
|
values = grouped_tags[key]
|
||||||
|
# 按创建时间对values进行排序
|
||||||
|
values.sort(key=lambda x: x['create_time'])
|
||||||
|
result.append({
|
||||||
|
'key': key,
|
||||||
|
'values': values,
|
||||||
|
})
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
@ -19,6 +19,10 @@ urlpatterns = [
|
||||||
path('workspace/<str:workspace_id>/knowledge/<str:knowledge_id>/hit_test', views.KnowledgeView.HitTest.as_view()),
|
path('workspace/<str:workspace_id>/knowledge/<str:knowledge_id>/hit_test', views.KnowledgeView.HitTest.as_view()),
|
||||||
path('workspace/<str:workspace_id>/knowledge/<str:knowledge_id>/export', views.KnowledgeView.Export.as_view()),
|
path('workspace/<str:workspace_id>/knowledge/<str:knowledge_id>/export', views.KnowledgeView.Export.as_view()),
|
||||||
path('workspace/<str:workspace_id>/knowledge/<str:knowledge_id>/export_zip', views.KnowledgeView.ExportZip.as_view()),
|
path('workspace/<str:workspace_id>/knowledge/<str:knowledge_id>/export_zip', views.KnowledgeView.ExportZip.as_view()),
|
||||||
|
path('workspace/<str:workspace_id>/knowledge/<str:knowledge_id>/tags', views.KnowledgeTagView.as_view()),
|
||||||
|
path('workspace/<str:workspace_id>/knowledge/<str:knowledge_id>/tags/batch_delete', views.KnowledgeTagView.BatchDelete.as_view()),
|
||||||
|
path('workspace/<str:workspace_id>/knowledge/<str:knowledge_id>/tags/<str:tag_id>', views.KnowledgeTagView.Operate.as_view()),
|
||||||
|
path('workspace/<str:workspace_id>/knowledge/<str:knowledge_id>/tags/<str:tag_id>/<str:delete_type>', views.KnowledgeTagView.Delete.as_view()),
|
||||||
path('workspace/<str:workspace_id>/knowledge/<str:knowledge_id>/document', views.DocumentView.as_view()),
|
path('workspace/<str:workspace_id>/knowledge/<str:knowledge_id>/document', views.DocumentView.as_view()),
|
||||||
path('workspace/<str:workspace_id>/knowledge/<str:knowledge_id>/document/split', views.DocumentView.Split.as_view()),
|
path('workspace/<str:workspace_id>/knowledge/<str:knowledge_id>/document/split', views.DocumentView.Split.as_view()),
|
||||||
path('workspace/<str:workspace_id>/knowledge/<str:knowledge_id>/document/split_pattern', views.DocumentView.SplitPattern.as_view()),
|
path('workspace/<str:workspace_id>/knowledge/<str:knowledge_id>/document/split_pattern', views.DocumentView.SplitPattern.as_view()),
|
||||||
|
|
@ -32,6 +36,7 @@ urlpatterns = [
|
||||||
path('workspace/<str:workspace_id>/knowledge/<str:knowledge_id>/document/table', views.TableDocumentView.as_view()),
|
path('workspace/<str:workspace_id>/knowledge/<str:knowledge_id>/document/table', views.TableDocumentView.as_view()),
|
||||||
path('workspace/<str:workspace_id>/knowledge/<str:knowledge_id>/document/batch_hit_handling', views.DocumentView.BatchEditHitHandling.as_view()),
|
path('workspace/<str:workspace_id>/knowledge/<str:knowledge_id>/document/batch_hit_handling', views.DocumentView.BatchEditHitHandling.as_view()),
|
||||||
path('workspace/<str:workspace_id>/knowledge/<str:knowledge_id>/document/batch_cancel_task', views.DocumentView.BatchCancelTask.as_view()),
|
path('workspace/<str:workspace_id>/knowledge/<str:knowledge_id>/document/batch_cancel_task', views.DocumentView.BatchCancelTask.as_view()),
|
||||||
|
path('workspace/<str:workspace_id>/knowledge/<str:knowledge_id>/document/batch_add_tag', views.DocumentView.BatchAddTag.as_view()),
|
||||||
path('workspace/<str:workspace_id>/knowledge/<str:knowledge_id>/document/migrate/<str:target_knowledge_id>', views.DocumentView.Migrate.as_view()),
|
path('workspace/<str:workspace_id>/knowledge/<str:knowledge_id>/document/migrate/<str:target_knowledge_id>', views.DocumentView.Migrate.as_view()),
|
||||||
path('workspace/<str:workspace_id>/knowledge/<str:knowledge_id>/document/<str:document_id>', views.DocumentView.Operate.as_view()),
|
path('workspace/<str:workspace_id>/knowledge/<str:knowledge_id>/document/<str:document_id>', views.DocumentView.Operate.as_view()),
|
||||||
path('workspace/<str:workspace_id>/knowledge/<str:knowledge_id>/document/<str:document_id>/sync', views.DocumentView.SyncWeb.as_view()),
|
path('workspace/<str:workspace_id>/knowledge/<str:knowledge_id>/document/<str:document_id>/sync', views.DocumentView.SyncWeb.as_view()),
|
||||||
|
|
@ -40,6 +45,8 @@ 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>/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>/paragraph', views.ParagraphView.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/batch_delete', views.ParagraphView.BatchDelete.as_view()),
|
path('workspace/<str:workspace_id>/knowledge/<str:knowledge_id>/document/<str:document_id>/paragraph/batch_delete', views.ParagraphView.BatchDelete.as_view()),
|
||||||
path('workspace/<str:workspace_id>/knowledge/<str:knowledge_id>/document/<str:document_id>/paragraph/batch_generate_related', views.ParagraphView.BatchGenerateRelated.as_view()),
|
path('workspace/<str:workspace_id>/knowledge/<str:knowledge_id>/document/<str:document_id>/paragraph/batch_generate_related', views.ParagraphView.BatchGenerateRelated.as_view()),
|
||||||
|
|
|
||||||
|
|
@ -2,3 +2,4 @@ from .document import *
|
||||||
from .knowledge import *
|
from .knowledge import *
|
||||||
from .paragraph import *
|
from .paragraph import *
|
||||||
from .problem import *
|
from .problem import *
|
||||||
|
from .tag import *
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ from knowledge.api.document import DocumentSplitAPI, DocumentBatchAPI, DocumentB
|
||||||
DocumentReadAPI, DocumentEditAPI, DocumentDeleteAPI, TableDocumentCreateAPI, QaDocumentCreateAPI, \
|
DocumentReadAPI, DocumentEditAPI, DocumentDeleteAPI, TableDocumentCreateAPI, QaDocumentCreateAPI, \
|
||||||
WebDocumentCreateAPI, CancelTaskAPI, BatchCancelTaskAPI, SyncWebAPI, RefreshAPI, BatchEditHitHandlingAPI, \
|
WebDocumentCreateAPI, CancelTaskAPI, BatchCancelTaskAPI, SyncWebAPI, RefreshAPI, BatchEditHitHandlingAPI, \
|
||||||
DocumentTreeReadAPI, DocumentSplitPatternAPI, BatchRefreshAPI, BatchGenerateRelatedAPI, TemplateExportAPI, \
|
DocumentTreeReadAPI, DocumentSplitPatternAPI, BatchRefreshAPI, BatchGenerateRelatedAPI, TemplateExportAPI, \
|
||||||
DocumentExportAPI, DocumentMigrateAPI, DocumentDownloadSourceAPI
|
DocumentExportAPI, DocumentMigrateAPI, DocumentDownloadSourceAPI, DocumentTagsAPI
|
||||||
from knowledge.serializers.common import get_knowledge_operation_object
|
from knowledge.serializers.common import get_knowledge_operation_object
|
||||||
from knowledge.serializers.document import DocumentSerializers
|
from knowledge.serializers.document import DocumentSerializers
|
||||||
from knowledge.views.common import get_knowledge_document_operation_object, get_document_operation_object_batch, \
|
from knowledge.views.common import get_knowledge_document_operation_object, get_document_operation_object_batch, \
|
||||||
|
|
@ -506,6 +506,37 @@ class DocumentView(APIView):
|
||||||
data={'workspace_id': workspace_id, 'knowledge_id': knowledge_id}
|
data={'workspace_id': workspace_id, 'knowledge_id': knowledge_id}
|
||||||
).batch_refresh(request.data))
|
).batch_refresh(request.data))
|
||||||
|
|
||||||
|
class BatchAddTag(APIView):
|
||||||
|
authentication_classes = [TokenAuth]
|
||||||
|
|
||||||
|
@extend_schema(
|
||||||
|
methods=['POST'],
|
||||||
|
summary=_('Batch add tags to documents'),
|
||||||
|
operation_id=_('Batch add tags to documents'), # type: ignore
|
||||||
|
request=DocumentTagsAPI.get_request(),
|
||||||
|
parameters=DocumentTagsAPI.get_parameters(),
|
||||||
|
responses=DocumentTagsAPI.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),
|
||||||
|
)
|
||||||
|
@log(
|
||||||
|
menu='document', operate="Batch add tags to documents",
|
||||||
|
get_operation_object=lambda r, keywords: get_knowledge_document_operation_object(
|
||||||
|
get_knowledge_operation_object(keywords.get('knowledge_id')),
|
||||||
|
get_document_operation_object_batch(r.data.get('document_ids'))
|
||||||
|
),
|
||||||
|
)
|
||||||
|
def post(self, request: Request, workspace_id: str, knowledge_id: str):
|
||||||
|
return result.success(DocumentSerializers.Batch(
|
||||||
|
data={'workspace_id': workspace_id, 'knowledge_id': knowledge_id}
|
||||||
|
).batch_add_tag(request.data))
|
||||||
|
|
||||||
class BatchGenerateRelated(APIView):
|
class BatchGenerateRelated(APIView):
|
||||||
authentication_classes = [TokenAuth]
|
authentication_classes = [TokenAuth]
|
||||||
|
|
||||||
|
|
@ -655,6 +686,86 @@ 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 Tags(APIView):
|
||||||
|
authentication_classes = [TokenAuth]
|
||||||
|
|
||||||
|
@extend_schema(
|
||||||
|
summary=_('Get document tags'),
|
||||||
|
description=_('Get document tags'),
|
||||||
|
operation_id=_('Get document tags'), # type: ignore
|
||||||
|
parameters=DocumentTagsAPI.get_parameters(),
|
||||||
|
responses=DocumentTagsAPI.get_response(),
|
||||||
|
tags=[_('Knowledge Base/Documentation')] # type: ignore
|
||||||
|
)
|
||||||
|
@has_permissions(
|
||||||
|
PermissionConstants.KNOWLEDGE_TAG_READ.get_workspace_knowledge_permission(),
|
||||||
|
PermissionConstants.KNOWLEDGE_TAG_READ.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 get(self, request: Request, workspace_id: str, knowledge_id: str, document_id: str):
|
||||||
|
return result.success(DocumentSerializers.Tags(data={
|
||||||
|
'workspace_id': workspace_id, 'knowledge_id': knowledge_id, 'document_id': document_id,
|
||||||
|
'name': request.query_params.get('name')
|
||||||
|
}).list())
|
||||||
|
|
||||||
|
@extend_schema(
|
||||||
|
summary=_('Add document tags'),
|
||||||
|
description=_('Add document tags'),
|
||||||
|
operation_id=_('Add document tags'), # type: ignore
|
||||||
|
parameters=DocumentTagsAPI.get_parameters(),
|
||||||
|
responses=DocumentTagsAPI.get_response(),
|
||||||
|
tags=[_('Knowledge Base/Documentation')] # type: ignore
|
||||||
|
)
|
||||||
|
@has_permissions(
|
||||||
|
PermissionConstants.KNOWLEDGE_TAG_READ.get_workspace_knowledge_permission(),
|
||||||
|
PermissionConstants.KNOWLEDGE_TAG_READ.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.AddTags(data={
|
||||||
|
'workspace_id': workspace_id, 'knowledge_id': knowledge_id, 'document_id': document_id,
|
||||||
|
'tag_ids': request.data
|
||||||
|
}).add_tags())
|
||||||
|
|
||||||
|
class BatchDelete(APIView):
|
||||||
|
authentication_classes = [TokenAuth]
|
||||||
|
|
||||||
|
@extend_schema(
|
||||||
|
summary=_('Delete document tags'),
|
||||||
|
description=_('Delete document tags'),
|
||||||
|
operation_id=_('Delete document tags'), # type: ignore
|
||||||
|
parameters=DocumentTagsAPI.get_parameters(),
|
||||||
|
request=DocumentTagsAPI.get_request(),
|
||||||
|
responses=DocumentTagsAPI.get_response(),
|
||||||
|
tags=[_('Knowledge Base/Documentation')] # type: ignore
|
||||||
|
)
|
||||||
|
@has_permissions(
|
||||||
|
PermissionConstants.KNOWLEDGE_TAG_READ.get_workspace_knowledge_permission(),
|
||||||
|
PermissionConstants.KNOWLEDGE_TAG_READ.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),
|
||||||
|
)
|
||||||
|
@log(
|
||||||
|
menu='document', operate="Delete document tags",
|
||||||
|
get_operation_object=lambda r, keywords: get_knowledge_document_operation_object(
|
||||||
|
get_knowledge_operation_object(keywords.get('knowledge_id')),
|
||||||
|
get_document_operation_object(keywords.get('document_id'))
|
||||||
|
),
|
||||||
|
)
|
||||||
|
def put(self, request: Request, workspace_id: str, knowledge_id: str, document_id: str):
|
||||||
|
return result.success(DocumentSerializers.DeleteTags(data={
|
||||||
|
'workspace_id': workspace_id,
|
||||||
|
'knowledge_id': knowledge_id,
|
||||||
|
'document_id': document_id,
|
||||||
|
'tag_ids': request.data
|
||||||
|
}).delete_tags())
|
||||||
|
|
||||||
class Migrate(APIView):
|
class Migrate(APIView):
|
||||||
authentication_classes = [TokenAuth]
|
authentication_classes = [TokenAuth]
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,138 @@
|
||||||
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
from drf_spectacular.utils import extend_schema
|
||||||
|
from rest_framework.request import Request
|
||||||
|
from rest_framework.views import APIView
|
||||||
|
|
||||||
|
from common.auth import TokenAuth
|
||||||
|
from common.auth.authentication import has_permissions
|
||||||
|
from common.constants.permission_constants import PermissionConstants, RoleConstants
|
||||||
|
from common.log.log import log
|
||||||
|
from common.result import result
|
||||||
|
from knowledge.api.tag import TagCreateAPI, TagDeleteAPI, TagEditAPI
|
||||||
|
from knowledge.serializers.common import get_knowledge_operation_object
|
||||||
|
from knowledge.serializers.tag import TagSerializers
|
||||||
|
|
||||||
|
|
||||||
|
class KnowledgeTagView(APIView):
|
||||||
|
authentication_classes = [TokenAuth]
|
||||||
|
|
||||||
|
@extend_schema(
|
||||||
|
summary=_("Create Knowledge Tag"),
|
||||||
|
description=_("Create a new knowledge tag"),
|
||||||
|
parameters=TagCreateAPI.get_parameters(),
|
||||||
|
request=TagCreateAPI.get_request(),
|
||||||
|
responses=TagCreateAPI.get_response(),
|
||||||
|
tags=[_('Knowledge Base/Tag')] # type: ignore
|
||||||
|
)
|
||||||
|
@has_permissions(
|
||||||
|
PermissionConstants.KNOWLEDGE_TAG_CREATE.get_workspace_permission(),
|
||||||
|
RoleConstants.WORKSPACE_MANAGE.get_workspace_role(),
|
||||||
|
RoleConstants.USER.get_workspace_role()
|
||||||
|
)
|
||||||
|
@log(
|
||||||
|
menu='tag', operate="Create a knowledge tag",
|
||||||
|
get_operation_object=lambda r, keywords: get_knowledge_operation_object(keywords.get('knowledge_id'))
|
||||||
|
)
|
||||||
|
def post(self, request: Request, workspace_id: str, knowledge_id: str):
|
||||||
|
return result.success(TagSerializers.Create(
|
||||||
|
data={'workspace_id': workspace_id, 'knowledge_id': knowledge_id, 'tags': request.data}
|
||||||
|
).insert())
|
||||||
|
|
||||||
|
@extend_schema(
|
||||||
|
summary=_("Get Knowledge Tag"),
|
||||||
|
description=_("Get knowledge tag"),
|
||||||
|
parameters=TagCreateAPI.get_parameters(),
|
||||||
|
request=TagCreateAPI.get_request(),
|
||||||
|
responses=TagCreateAPI.get_response(),
|
||||||
|
tags=[_('Knowledge Base/Tag')] # type: ignore
|
||||||
|
)
|
||||||
|
@has_permissions(
|
||||||
|
PermissionConstants.KNOWLEDGE_TAG_READ.get_workspace_permission(),
|
||||||
|
RoleConstants.WORKSPACE_MANAGE.get_workspace_role(),
|
||||||
|
RoleConstants.USER.get_workspace_role()
|
||||||
|
)
|
||||||
|
@log(
|
||||||
|
menu='tag', operate="Create a knowledge tag",
|
||||||
|
get_operation_object=lambda r, keywords: get_knowledge_operation_object(keywords.get('knowledge_id'))
|
||||||
|
)
|
||||||
|
def get(self, request: Request, workspace_id: str, knowledge_id: str):
|
||||||
|
return result.success(TagSerializers.Query(data={
|
||||||
|
'workspace_id': workspace_id,
|
||||||
|
'knowledge_id': knowledge_id,
|
||||||
|
'name': request.query_params.get('name')
|
||||||
|
}).list())
|
||||||
|
|
||||||
|
class Operate(APIView):
|
||||||
|
authentication_classes = [TokenAuth]
|
||||||
|
|
||||||
|
@extend_schema(
|
||||||
|
summary=_("Update Knowledge Tag"),
|
||||||
|
description=_("Update a knowledge tag"),
|
||||||
|
parameters=TagEditAPI.get_parameters(),
|
||||||
|
request=TagEditAPI.get_request(),
|
||||||
|
responses=TagEditAPI.get_response(),
|
||||||
|
tags=[_('Knowledge Base/Tag')] # type: ignore
|
||||||
|
)
|
||||||
|
@has_permissions(
|
||||||
|
PermissionConstants.KNOWLEDGE_TAG_EDIT.get_workspace_permission(),
|
||||||
|
RoleConstants.WORKSPACE_MANAGE.get_workspace_role(),
|
||||||
|
RoleConstants.USER.get_workspace_role()
|
||||||
|
)
|
||||||
|
@log(
|
||||||
|
menu='tag', operate="Update a knowledge tag",
|
||||||
|
get_operation_object=lambda r, keywords: get_knowledge_operation_object(keywords.get('knowledge_id'))
|
||||||
|
)
|
||||||
|
def put(self, request: Request, workspace_id: str, knowledge_id: str, tag_id: str):
|
||||||
|
return result.success(TagSerializers.Operate(
|
||||||
|
data={'workspace_id': workspace_id, 'knowledge_id': knowledge_id, 'tag_id': tag_id}
|
||||||
|
).edit(request.data))
|
||||||
|
|
||||||
|
class Delete(APIView):
|
||||||
|
authentication_classes = [TokenAuth]
|
||||||
|
|
||||||
|
@extend_schema(
|
||||||
|
summary=_("Delete Knowledge Tag"),
|
||||||
|
description=_("Delete a knowledge tag"),
|
||||||
|
parameters=TagDeleteAPI.get_parameters(),
|
||||||
|
request=TagDeleteAPI.get_request(),
|
||||||
|
responses=TagDeleteAPI.get_response(),
|
||||||
|
tags=[_('Knowledge Base/Tag')] # type: ignore
|
||||||
|
)
|
||||||
|
@has_permissions(
|
||||||
|
PermissionConstants.KNOWLEDGE_TAG_DELETE.get_workspace_permission(),
|
||||||
|
RoleConstants.WORKSPACE_MANAGE.get_workspace_role(),
|
||||||
|
RoleConstants.USER.get_workspace_role()
|
||||||
|
)
|
||||||
|
@log(
|
||||||
|
menu='tag', operate="Delete a knowledge tag",
|
||||||
|
get_operation_object=lambda r, keywords: get_knowledge_operation_object(keywords.get('knowledge_id'))
|
||||||
|
)
|
||||||
|
def delete(self, request: Request, workspace_id: str, knowledge_id: str, tag_id: str, delete_type: str):
|
||||||
|
return result.success(TagSerializers.Operate(
|
||||||
|
data={'workspace_id': workspace_id, 'knowledge_id': knowledge_id, 'tag_id': tag_id}
|
||||||
|
).delete(delete_type))
|
||||||
|
|
||||||
|
class BatchDelete(APIView):
|
||||||
|
authentication_classes = [TokenAuth]
|
||||||
|
|
||||||
|
@extend_schema(
|
||||||
|
summary=_("Batch Delete Knowledge Tag"),
|
||||||
|
description=_("Batch Delete a knowledge tag"),
|
||||||
|
parameters=TagDeleteAPI.get_parameters(),
|
||||||
|
request=TagDeleteAPI.get_request(),
|
||||||
|
responses=TagDeleteAPI.get_response(),
|
||||||
|
tags=[_('Knowledge Base/Tag')] # type: ignore
|
||||||
|
)
|
||||||
|
@has_permissions(
|
||||||
|
PermissionConstants.KNOWLEDGE_TAG_DELETE.get_workspace_permission(),
|
||||||
|
RoleConstants.WORKSPACE_MANAGE.get_workspace_role(),
|
||||||
|
RoleConstants.USER.get_workspace_role()
|
||||||
|
)
|
||||||
|
@log(
|
||||||
|
menu='tag', operate="Batch Delete knowledge tag",
|
||||||
|
get_operation_object=lambda r, keywords: get_knowledge_operation_object(keywords.get('knowledge_id'))
|
||||||
|
)
|
||||||
|
def put(self, request: Request, workspace_id: str, knowledge_id: str):
|
||||||
|
return result.success(TagSerializers.BatchDelete(
|
||||||
|
data={'workspace_id': workspace_id, 'knowledge_id': knowledge_id, 'tag_ids': request.data}
|
||||||
|
).batch_delete())
|
||||||
|
|
@ -1,14 +1,14 @@
|
||||||
import { Result } from '@/request/Result'
|
import { Result } from '@/request/Result'
|
||||||
import { get, post, del, put, exportExcel, exportFile } from '@/request/index'
|
import { del, exportExcel, exportFile, get, post, put } from '@/request/index'
|
||||||
import type { Ref } from 'vue'
|
import type { Ref } from 'vue'
|
||||||
import type { KeyValue } from '@/api/type/common'
|
import type { KeyValue, pageRequest } from '@/api/type/common'
|
||||||
import type { pageRequest } from '@/api/type/common'
|
|
||||||
|
|
||||||
import useStore from '@/stores'
|
import useStore from '@/stores'
|
||||||
const prefix: any = { _value: '/workspace/' }
|
|
||||||
|
const prefix: any = {_value: '/workspace/'}
|
||||||
Object.defineProperty(prefix, 'value', {
|
Object.defineProperty(prefix, 'value', {
|
||||||
get: function () {
|
get: function () {
|
||||||
const { user } = useStore()
|
const {user} = useStore()
|
||||||
return this._value + user.getWorkspaceId() + '/knowledge'
|
return this._value + user.getWorkspaceId() + '/knowledge'
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
@ -18,7 +18,7 @@ Object.defineProperty(prefix, 'value', {
|
||||||
* @param 参数 knowledge_id,
|
* @param 参数 knowledge_id,
|
||||||
* param {
|
* param {
|
||||||
" name": "string",
|
" name": "string",
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const getDocumentList: (knowledge_id: string, loading?: Ref<boolean>) => Promise<Result<any>> = (
|
const getDocumentList: (knowledge_id: string, loading?: Ref<boolean>) => Promise<Result<any>> = (
|
||||||
|
|
@ -32,9 +32,9 @@ const getDocumentList: (knowledge_id: string, loading?: Ref<boolean>) => Promise
|
||||||
* 文档分页列表
|
* 文档分页列表
|
||||||
* @param 参数 knowledge_id,
|
* @param 参数 knowledge_id,
|
||||||
* param {
|
* param {
|
||||||
"name": "string",
|
"name": "string",
|
||||||
folder_id: "string",
|
folder_id: "string",
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const getDocumentPage: (
|
const getDocumentPage: (
|
||||||
|
|
@ -69,9 +69,9 @@ const getDocumentDetail: (
|
||||||
* @param 参数
|
* @param 参数
|
||||||
* knowledge_id, document_id,
|
* knowledge_id, document_id,
|
||||||
* {
|
* {
|
||||||
"name": "string",
|
"name": "string",
|
||||||
"is_active": true,
|
"is_active": true,
|
||||||
"meta": {}
|
"meta": {}
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
const putDocument: (
|
const putDocument: (
|
||||||
|
|
@ -99,11 +99,11 @@ const delDocument: (
|
||||||
* 批量取消文档任务
|
* 批量取消文档任务
|
||||||
* @param 参数 knowledge_id,
|
* @param 参数 knowledge_id,
|
||||||
*{
|
*{
|
||||||
"id_list": [
|
"id_list": [
|
||||||
"3fa85f64-5717-4562-b3fc-2c963f66afa6"
|
"3fa85f64-5717-4562-b3fc-2c963f66afa6"
|
||||||
],
|
],
|
||||||
"type": 0
|
"type": 0
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const putBatchCancelTask: (
|
const putBatchCancelTask: (
|
||||||
|
|
@ -192,10 +192,10 @@ const exportDocumentZip: (
|
||||||
* @param 参数
|
* @param 参数
|
||||||
* knowledge_id, document_id,
|
* knowledge_id, document_id,
|
||||||
* {
|
* {
|
||||||
"state_list": [
|
"state_list": [
|
||||||
"string"
|
"string"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
const putDocumentRefresh: (
|
const putDocumentRefresh: (
|
||||||
knowledge_id: string,
|
knowledge_id: string,
|
||||||
|
|
@ -205,7 +205,7 @@ const putDocumentRefresh: (
|
||||||
) => Promise<Result<any>> = (knowledge_id, document_id, state_list, loading) => {
|
) => Promise<Result<any>> = (knowledge_id, document_id, state_list, loading) => {
|
||||||
return put(
|
return put(
|
||||||
`${prefix.value}/${knowledge_id}/document/${document_id}/refresh`,
|
`${prefix.value}/${knowledge_id}/document/${document_id}/refresh`,
|
||||||
{ state_list },
|
{state_list},
|
||||||
undefined,
|
undefined,
|
||||||
loading,
|
loading,
|
||||||
)
|
)
|
||||||
|
|
@ -232,23 +232,23 @@ const putDocumentSync: (
|
||||||
/**
|
/**
|
||||||
* 创建批量文档
|
* 创建批量文档
|
||||||
* @param 参数
|
* @param 参数
|
||||||
{
|
{
|
||||||
"name": "string",
|
"name": "string",
|
||||||
"paragraphs": [
|
"paragraphs": [
|
||||||
{
|
{
|
||||||
"content": "string",
|
"content": "string",
|
||||||
"title": "string",
|
"title": "string",
|
||||||
"problem_list": [
|
"problem_list": [
|
||||||
{
|
{
|
||||||
"id": "string",
|
"id": "string",
|
||||||
"content": "string"
|
"content": "string"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"is_active": true
|
"is_active": true
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"source_file_id": string
|
"source_file_id": string
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
const putMulDocument: (
|
const putMulDocument: (
|
||||||
knowledge_id: string,
|
knowledge_id: string,
|
||||||
|
|
@ -268,8 +268,8 @@ const putMulDocument: (
|
||||||
* 批量删除文档
|
* 批量删除文档
|
||||||
* @param 参数 knowledge_id,
|
* @param 参数 knowledge_id,
|
||||||
* {
|
* {
|
||||||
"id_list": [String]
|
"id_list": [String]
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
const delMulDocument: (
|
const delMulDocument: (
|
||||||
knowledge_id: string,
|
knowledge_id: string,
|
||||||
|
|
@ -278,7 +278,7 @@ const delMulDocument: (
|
||||||
) => Promise<Result<boolean>> = (knowledge_id, data, loading) => {
|
) => Promise<Result<boolean>> = (knowledge_id, data, loading) => {
|
||||||
return put(
|
return put(
|
||||||
`${prefix.value}/${knowledge_id}/document/batch_delete`,
|
`${prefix.value}/${knowledge_id}/document/batch_delete`,
|
||||||
{ id_list: data },
|
{id_list: data},
|
||||||
undefined,
|
undefined,
|
||||||
loading,
|
loading,
|
||||||
)
|
)
|
||||||
|
|
@ -287,16 +287,16 @@ const delMulDocument: (
|
||||||
/**
|
/**
|
||||||
* 批量关联
|
* 批量关联
|
||||||
* @param 参数 knowledge_id,
|
* @param 参数 knowledge_id,
|
||||||
{
|
{
|
||||||
"document_id_list": [
|
"document_id_list": [
|
||||||
"string"
|
"string"
|
||||||
],
|
],
|
||||||
"model_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
"model_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
"prompt": "string",
|
"prompt": "string",
|
||||||
"state_list": [
|
"state_list": [
|
||||||
"string"
|
"string"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
const putBatchGenerateRelated: (
|
const putBatchGenerateRelated: (
|
||||||
knowledge_id: string,
|
knowledge_id: string,
|
||||||
|
|
@ -336,14 +336,14 @@ const putBatchEditHitHandling: (
|
||||||
* 批量刷新文档向量库
|
* 批量刷新文档向量库
|
||||||
* @param knowledge_id 知识库id
|
* @param knowledge_id 知识库id
|
||||||
* @param data
|
* @param data
|
||||||
{
|
{
|
||||||
"id_list": [
|
"id_list": [
|
||||||
"string"
|
"string"
|
||||||
],
|
],
|
||||||
"state_list": [
|
"state_list": [
|
||||||
"string"
|
"string"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
* @param loading
|
* @param loading
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
|
|
@ -355,7 +355,7 @@ const putBatchRefresh: (
|
||||||
) => Promise<Result<boolean>> = (knowledge_id, data, stateList, loading) => {
|
) => Promise<Result<boolean>> = (knowledge_id, data, stateList, loading) => {
|
||||||
return put(
|
return put(
|
||||||
`${prefix.value}/${knowledge_id}/document/batch_refresh`,
|
`${prefix.value}/${knowledge_id}/document/batch_refresh`,
|
||||||
{ id_list: data, state_list: stateList },
|
{id_list: data, state_list: stateList},
|
||||||
undefined,
|
undefined,
|
||||||
loading,
|
loading,
|
||||||
)
|
)
|
||||||
|
|
@ -372,7 +372,7 @@ const putMulSyncDocument: (
|
||||||
) => Promise<Result<boolean>> = (knowledge_id, data, loading) => {
|
) => Promise<Result<boolean>> = (knowledge_id, data, loading) => {
|
||||||
return put(
|
return put(
|
||||||
`${prefix.value}/${knowledge_id}/document/batch_sync`,
|
`${prefix.value}/${knowledge_id}/document/batch_sync`,
|
||||||
{ id_list: data },
|
{id_list: data},
|
||||||
undefined,
|
undefined,
|
||||||
loading,
|
loading,
|
||||||
)
|
)
|
||||||
|
|
@ -462,7 +462,7 @@ const exportQATemplate: (fileName: string, type: string, loading?: Ref<boolean>)
|
||||||
type,
|
type,
|
||||||
loading,
|
loading,
|
||||||
) => {
|
) => {
|
||||||
return exportExcel(fileName, `/workspace/knowledge/document/template/export`, { type }, loading)
|
return exportExcel(fileName, `/workspace/knowledge/document/template/export`, {type}, loading)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -477,7 +477,7 @@ const exportTableTemplate: (fileName: string, type: string, loading?: Ref<boolea
|
||||||
return exportExcel(
|
return exportExcel(
|
||||||
fileName,
|
fileName,
|
||||||
`/workspace/knowledge/document/table_template/export`,
|
`/workspace/knowledge/document/table_template/export`,
|
||||||
{ type },
|
{type},
|
||||||
loading,
|
loading,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -550,7 +550,7 @@ const putMulLarkSyncDocument: (
|
||||||
data: any,
|
data: any,
|
||||||
loading?: Ref<boolean>,
|
loading?: Ref<boolean>,
|
||||||
) => Promise<Result<boolean>> = (knowledge_id, data, loading) => {
|
) => Promise<Result<boolean>> = (knowledge_id, data, loading) => {
|
||||||
return put(`${prefix.value}/lark/${knowledge_id}/_batch`, { id_list: data }, undefined, loading)
|
return put(`${prefix.value}/lark/${knowledge_id}/_batch`, {id_list: data}, undefined, loading)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -564,6 +564,41 @@ const importLarkDocument: (
|
||||||
return post(`${prefix.value}/lark/${knowledge_id}/import`, data, null, loading)
|
return post(`${prefix.value}/lark/${knowledge_id}/import`, data, null, loading)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const getDocumentTags: (
|
||||||
|
knowledge_id: string,
|
||||||
|
document_id: string,
|
||||||
|
params: any,
|
||||||
|
loading?: Ref<boolean>,
|
||||||
|
) => Promise<Result<Array<string>>> = (knowledge_id, document_id, params, loading) => {
|
||||||
|
return get(`${prefix.value}/${knowledge_id}/document/${document_id}/tags`, params, loading)
|
||||||
|
}
|
||||||
|
|
||||||
|
const postDocumentTags: (
|
||||||
|
knowledge_id: string,
|
||||||
|
document_id: string,
|
||||||
|
data: any,
|
||||||
|
loading?: Ref<boolean>,
|
||||||
|
) => Promise<Result<boolean>> = (knowledge_id, document_id, data, loading) => {
|
||||||
|
return post(`${prefix.value}/${knowledge_id}/document/${document_id}/tags`, data, null, loading)
|
||||||
|
}
|
||||||
|
|
||||||
|
const postMulDocumentTags: (
|
||||||
|
knowledge_id: string,
|
||||||
|
data: any,
|
||||||
|
loading?: Ref<boolean>,
|
||||||
|
) => Promise<Result<boolean>> = (knowledge_id, data, loading) => {
|
||||||
|
return post(`${prefix.value}/${knowledge_id}/document/batch_add_tag`, data, null, loading)
|
||||||
|
}
|
||||||
|
|
||||||
|
const delMulDocumentTag: (
|
||||||
|
knowledge_id: string,
|
||||||
|
document_id: string,
|
||||||
|
tags: any,
|
||||||
|
loading?: Ref<boolean>,
|
||||||
|
) => Promise<Result<boolean>> = (knowledge_id, document_id, tags, loading) => {
|
||||||
|
return put(`${prefix.value}/${knowledge_id}/document/${document_id}/tags/batch_delete`, tags, null, loading)
|
||||||
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
getDocumentList,
|
getDocumentList,
|
||||||
getDocumentPage,
|
getDocumentPage,
|
||||||
|
|
@ -595,4 +630,8 @@ export default {
|
||||||
putLarkDocumentSync,
|
putLarkDocumentSync,
|
||||||
putMulLarkSyncDocument,
|
putMulLarkSyncDocument,
|
||||||
importLarkDocument,
|
importLarkDocument,
|
||||||
|
getDocumentTags,
|
||||||
|
postDocumentTags,
|
||||||
|
postMulDocumentTags,
|
||||||
|
delMulDocumentTag
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -255,6 +255,49 @@ const putLarkKnowledge: (
|
||||||
return put(`${prefix.value}/lark/${knowledge_id}`, data, undefined, loading)
|
return put(`${prefix.value}/lark/${knowledge_id}`, data, undefined, loading)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const getTags: (knowledge_id: string, params: any, loading?: Ref<boolean>) => Promise<Result<any>> = (
|
||||||
|
knowledge_id,
|
||||||
|
params,
|
||||||
|
loading,
|
||||||
|
) => {
|
||||||
|
return get(`${prefix.value}/${knowledge_id}/tags`, params, loading)
|
||||||
|
}
|
||||||
|
|
||||||
|
const postTags: (knowledge_id: string, tags: any, loading?: Ref<boolean>) => Promise<Result<any>> = (
|
||||||
|
knowledge_id,
|
||||||
|
tags,
|
||||||
|
loading,
|
||||||
|
) => {
|
||||||
|
return post(`${prefix.value}/${knowledge_id}/tags`, tags, null, loading)
|
||||||
|
}
|
||||||
|
|
||||||
|
const putTag: (knowledge_id: string, tag_id: string, tag: any, loading?: Ref<boolean>) => Promise<Result<any>> = (
|
||||||
|
knowledge_id,
|
||||||
|
tag_id,
|
||||||
|
tag,
|
||||||
|
loading,
|
||||||
|
) => {
|
||||||
|
return put(`${prefix.value}/${knowledge_id}/tags/${tag_id}`, tag, null, loading)
|
||||||
|
}
|
||||||
|
|
||||||
|
const delTag: (knowledge_id: string, tag_id: string, type: string, loading?: Ref<boolean>) => Promise<Result<any>> = (
|
||||||
|
knowledge_id,
|
||||||
|
tag_id,
|
||||||
|
type,
|
||||||
|
loading,
|
||||||
|
) => {
|
||||||
|
return del(`${prefix.value}/${knowledge_id}/tags/${tag_id}/${type}`, null, loading)
|
||||||
|
}
|
||||||
|
|
||||||
|
const delMulTag: (knowledge_id: string, tags: any, loading?: Ref<boolean>) => Promise<Result<any>> = (
|
||||||
|
knowledge_id,
|
||||||
|
tags,
|
||||||
|
loading,
|
||||||
|
) => {
|
||||||
|
return put(`${prefix.value}/${knowledge_id}/tags/batch_delete`, tags, null, loading)
|
||||||
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
getKnowledgeList,
|
getKnowledgeList,
|
||||||
getKnowledgeListPage,
|
getKnowledgeListPage,
|
||||||
|
|
@ -271,5 +314,10 @@ export default {
|
||||||
getKnowledgeModel,
|
getKnowledgeModel,
|
||||||
postWebKnowledge,
|
postWebKnowledge,
|
||||||
postLarkKnowledge,
|
postLarkKnowledge,
|
||||||
putLarkKnowledge
|
putLarkKnowledge,
|
||||||
|
getTags,
|
||||||
|
postTags,
|
||||||
|
putTag,
|
||||||
|
delTag,
|
||||||
|
delMulTag
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -523,6 +523,40 @@ const importLarkDocument: (
|
||||||
return post(`${prefix}/lark/${knowledge_id}/import`, data, null, loading)
|
return post(`${prefix}/lark/${knowledge_id}/import`, data, null, loading)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const getDocumentTags: (
|
||||||
|
knowledge_id: string,
|
||||||
|
document_id: string,
|
||||||
|
params: any,
|
||||||
|
loading?: Ref<boolean>,
|
||||||
|
) => Promise<Result<Array<string>>> = (knowledge_id, document_id, params, loading) => {
|
||||||
|
return get(`${prefix}/${knowledge_id}/document/${document_id}/tags`, params, loading)
|
||||||
|
}
|
||||||
|
|
||||||
|
const postDocumentTags: (
|
||||||
|
knowledge_id: string,
|
||||||
|
document_id: string,
|
||||||
|
data: any,
|
||||||
|
loading?: Ref<boolean>,
|
||||||
|
) => Promise<Result<boolean>> = (knowledge_id, document_id, data, loading) => {
|
||||||
|
return post(`${prefix}/${knowledge_id}/document/${document_id}/tags`, data, null, loading)
|
||||||
|
}
|
||||||
|
|
||||||
|
const postMulDocumentTags: (
|
||||||
|
knowledge_id: string,
|
||||||
|
data: any,
|
||||||
|
loading?: Ref<boolean>,
|
||||||
|
) => Promise<Result<boolean>> = (knowledge_id, data, loading) => {
|
||||||
|
return post(`${prefix}/${knowledge_id}/document/batch_add_tag`, data, null, loading)
|
||||||
|
}
|
||||||
|
|
||||||
|
const delMulDocumentTag: (
|
||||||
|
knowledge_id: string,
|
||||||
|
document_id: string,
|
||||||
|
tags: any,
|
||||||
|
loading?: Ref<boolean>,
|
||||||
|
) => Promise<Result<boolean>> = (knowledge_id, document_id, tags, loading) => {
|
||||||
|
return put(`${prefix}/${knowledge_id}/document/${document_id}/tags/batch_delete`, tags, null, loading)
|
||||||
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
getDocumentList,
|
getDocumentList,
|
||||||
|
|
@ -555,4 +589,8 @@ export default {
|
||||||
putLarkDocumentSync,
|
putLarkDocumentSync,
|
||||||
putMulLarkSyncDocument,
|
putMulLarkSyncDocument,
|
||||||
importLarkDocument,
|
importLarkDocument,
|
||||||
|
getDocumentTags,
|
||||||
|
postDocumentTags,
|
||||||
|
postMulDocumentTags,
|
||||||
|
delMulDocumentTag
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -205,6 +205,49 @@ const putLarkKnowledge: (
|
||||||
return put(`${prefix}/lark/${knowledge_id}`, data, undefined, loading)
|
return put(`${prefix}/lark/${knowledge_id}`, data, undefined, loading)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const getTags: (knowledge_id: string, params: any, loading?: Ref<boolean>) => Promise<Result<any>> = (
|
||||||
|
knowledge_id,
|
||||||
|
params,
|
||||||
|
loading,
|
||||||
|
) => {
|
||||||
|
return get(`${prefix}/${knowledge_id}/tags`, params, loading)
|
||||||
|
}
|
||||||
|
|
||||||
|
const postTags: (knowledge_id: string, tags: any, loading?: Ref<boolean>) => Promise<Result<any>> = (
|
||||||
|
knowledge_id,
|
||||||
|
tags,
|
||||||
|
loading,
|
||||||
|
) => {
|
||||||
|
return post(`${prefix}/${knowledge_id}/tags`, tags, null, loading)
|
||||||
|
}
|
||||||
|
|
||||||
|
const putTag: (knowledge_id: string, tag_id: string, tag: any, loading?: Ref<boolean>) => Promise<Result<any>> = (
|
||||||
|
knowledge_id,
|
||||||
|
tag_id,
|
||||||
|
tag,
|
||||||
|
loading,
|
||||||
|
) => {
|
||||||
|
return put(`${prefix}/${knowledge_id}/tags/${tag_id}`, tag, null, loading)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const delTag: (knowledge_id: string, tag_id: string, type: string, loading?: Ref<boolean>) => Promise<Result<any>> = (
|
||||||
|
knowledge_id,
|
||||||
|
tag_id,
|
||||||
|
type,
|
||||||
|
loading,
|
||||||
|
) => {
|
||||||
|
return del(`${prefix}/${knowledge_id}/tags/${tag_id}/${type}`, null, loading)
|
||||||
|
}
|
||||||
|
|
||||||
|
const delMulTag: (knowledge_id: string, tags: any, loading?: Ref<boolean>) => Promise<Result<any>> = (
|
||||||
|
knowledge_id,
|
||||||
|
tags,
|
||||||
|
loading,
|
||||||
|
) => {
|
||||||
|
return put(`${prefix}/${knowledge_id}/tags/batch_delete`, tags, null, loading)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
getKnowledgeList,
|
getKnowledgeList,
|
||||||
|
|
@ -219,7 +262,12 @@ export default {
|
||||||
putKnowledgeHitTest,
|
putKnowledgeHitTest,
|
||||||
putSyncWebKnowledge,
|
putSyncWebKnowledge,
|
||||||
getKnowledgeModel,
|
getKnowledgeModel,
|
||||||
putLarkKnowledge
|
putLarkKnowledge,
|
||||||
|
getTags,
|
||||||
|
postTags,
|
||||||
|
putTag,
|
||||||
|
delTag,
|
||||||
|
delMulTag
|
||||||
} as {
|
} as {
|
||||||
[key: string]: any
|
[key: string]: any
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -524,6 +524,41 @@ const importLarkDocument: (
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const getDocumentTags: (
|
||||||
|
knowledge_id: string,
|
||||||
|
document_id: string,
|
||||||
|
params: any,
|
||||||
|
loading?: Ref<boolean>,
|
||||||
|
) => Promise<Result<Array<string>>> = (knowledge_id, document_id, params, loading) => {
|
||||||
|
return get(`${prefix}/${knowledge_id}/document/${document_id}/tags`, params, loading)
|
||||||
|
}
|
||||||
|
|
||||||
|
const postDocumentTags: (
|
||||||
|
knowledge_id: string,
|
||||||
|
document_id: string,
|
||||||
|
data: any,
|
||||||
|
loading?: Ref<boolean>,
|
||||||
|
) => Promise<Result<boolean>> = (knowledge_id, document_id, data, loading) => {
|
||||||
|
return post(`${prefix}/${knowledge_id}/document/${document_id}/tags`, data, null, loading)
|
||||||
|
}
|
||||||
|
|
||||||
|
const postMulDocumentTags: (
|
||||||
|
knowledge_id: string,
|
||||||
|
data: any,
|
||||||
|
loading?: Ref<boolean>,
|
||||||
|
) => Promise<Result<boolean>> = (knowledge_id, data, loading) => {
|
||||||
|
return post(`${prefix}/${knowledge_id}/document/batch_add_tag`, data, null, loading)
|
||||||
|
}
|
||||||
|
|
||||||
|
const delMulDocumentTag: (
|
||||||
|
knowledge_id: string,
|
||||||
|
document_id: string,
|
||||||
|
tags: any,
|
||||||
|
loading?: Ref<boolean>,
|
||||||
|
) => Promise<Result<boolean>> = (knowledge_id, document_id, tags, loading) => {
|
||||||
|
return put(`${prefix}/${knowledge_id}/document/${document_id}/tags/batch_delete`, tags, null, loading)
|
||||||
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
getDocumentList,
|
getDocumentList,
|
||||||
getDocumentPage,
|
getDocumentPage,
|
||||||
|
|
@ -555,4 +590,8 @@ export default {
|
||||||
putLarkDocumentSync,
|
putLarkDocumentSync,
|
||||||
putMulLarkSyncDocument,
|
putMulLarkSyncDocument,
|
||||||
importLarkDocument,
|
importLarkDocument,
|
||||||
|
getDocumentTags,
|
||||||
|
postDocumentTags,
|
||||||
|
postMulDocumentTags,
|
||||||
|
delMulDocumentTag
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -249,6 +249,47 @@ const putLarkKnowledge: (
|
||||||
return put(`${prefix}/lark/${knowledge_id}`, data, undefined, loading)
|
return put(`${prefix}/lark/${knowledge_id}`, data, undefined, loading)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const getTags: (knowledge_id: string, params: any, loading?: Ref<boolean>) => Promise<Result<any>> = (
|
||||||
|
knowledge_id,
|
||||||
|
params,
|
||||||
|
loading,
|
||||||
|
) => {
|
||||||
|
return get(`${prefix}/${knowledge_id}/tags`, params, loading)
|
||||||
|
}
|
||||||
|
|
||||||
|
const postTags: (knowledge_id: string, tags: any, loading?: Ref<boolean>) => Promise<Result<any>> = (
|
||||||
|
knowledge_id,
|
||||||
|
tags,
|
||||||
|
loading,
|
||||||
|
) => {
|
||||||
|
return post(`${prefix}/${knowledge_id}/tags`, tags, null, loading)
|
||||||
|
}
|
||||||
|
|
||||||
|
const putTag: (knowledge_id: string, tag_id: string, tag: any, loading?: Ref<boolean>) => Promise<Result<any>> = (
|
||||||
|
knowledge_id,
|
||||||
|
tag_id,
|
||||||
|
tag,
|
||||||
|
loading,
|
||||||
|
) => {
|
||||||
|
return put(`${prefix}/${knowledge_id}/tags/${tag_id}`, tag, null, loading)
|
||||||
|
}
|
||||||
|
|
||||||
|
const delTag: (knowledge_id: string, tag_id: string, type: string, loading?: Ref<boolean>) => Promise<Result<any>> = (
|
||||||
|
knowledge_id,
|
||||||
|
tag_id,
|
||||||
|
type,
|
||||||
|
loading,
|
||||||
|
) => {
|
||||||
|
return del(`${prefix}/${knowledge_id}/tags/${tag_id}/${type}`, null, loading)
|
||||||
|
}
|
||||||
|
|
||||||
|
const delMulTag: (knowledge_id: string, tags: any, loading?: Ref<boolean>) => Promise<Result<any>> = (
|
||||||
|
knowledge_id,
|
||||||
|
tags,
|
||||||
|
loading,
|
||||||
|
) => {
|
||||||
|
return put(`${prefix}/${knowledge_id}/tags/batch_delete`, tags, null, loading)
|
||||||
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
getKnowledgeList,
|
getKnowledgeList,
|
||||||
|
|
@ -266,7 +307,12 @@ export default {
|
||||||
getKnowledgeModel,
|
getKnowledgeModel,
|
||||||
postWebKnowledge,
|
postWebKnowledge,
|
||||||
postLarkKnowledge,
|
postLarkKnowledge,
|
||||||
putLarkKnowledge
|
putLarkKnowledge,
|
||||||
|
getTags,
|
||||||
|
postTags,
|
||||||
|
putTag,
|
||||||
|
delTag,
|
||||||
|
delMulTag
|
||||||
} as {
|
} as {
|
||||||
[key: string]: any
|
[key: string]: any
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -98,6 +98,19 @@ export default {
|
||||||
import: 'Start Import',
|
import: 'Start Import',
|
||||||
preview: 'Apply',
|
preview: 'Apply',
|
||||||
},
|
},
|
||||||
|
tag: {
|
||||||
|
label: 'Tag Management',
|
||||||
|
key: 'Tag',
|
||||||
|
value: 'Value',
|
||||||
|
add: 'Add Tag',
|
||||||
|
setting: 'Tag Settings',
|
||||||
|
create: 'Create Tag',
|
||||||
|
edit: 'Edit Tag',
|
||||||
|
deleteConfirm: 'Confirm delete tag: ',
|
||||||
|
deleteTip: 'After deletion, resources using this tag will have the tag removed. Please proceed with caution!',
|
||||||
|
requiredMessage1: 'Please enter a tag',
|
||||||
|
requiredMessage2: 'Please enter a value',
|
||||||
|
},
|
||||||
table: {
|
table: {
|
||||||
name: 'Document Name',
|
name: 'Document Name',
|
||||||
char_length: 'Character',
|
char_length: 'Character',
|
||||||
|
|
|
||||||
|
|
@ -93,6 +93,19 @@ export default {
|
||||||
import: '开始导入',
|
import: '开始导入',
|
||||||
preview: '生成预览',
|
preview: '生成预览',
|
||||||
},
|
},
|
||||||
|
tag: {
|
||||||
|
label: '标签管理',
|
||||||
|
key: '标签',
|
||||||
|
value: '标签值',
|
||||||
|
add: '添加标签',
|
||||||
|
setting: '标签设置',
|
||||||
|
create: '创建标签',
|
||||||
|
edit: '编辑标签',
|
||||||
|
deleteConfirm: '是否删除标签: ',
|
||||||
|
deleteTip: '删除后使用该标签的资源将会删除该标签,请谨慎操作!',
|
||||||
|
requiredMessage1: '请输入标签',
|
||||||
|
requiredMessage2: '请输入标签值',
|
||||||
|
},
|
||||||
table: {
|
table: {
|
||||||
name: '文件名称',
|
name: '文件名称',
|
||||||
char_length: '字符数',
|
char_length: '字符数',
|
||||||
|
|
|
||||||
|
|
@ -96,6 +96,19 @@ export default {
|
||||||
import: '開始導入',
|
import: '開始導入',
|
||||||
preview: '生成預覽',
|
preview: '生成預覽',
|
||||||
},
|
},
|
||||||
|
tag: {
|
||||||
|
label: '標籤管理',
|
||||||
|
key: '標籤',
|
||||||
|
value: '標籤值',
|
||||||
|
add: '添加標籤',
|
||||||
|
setting: '標籤設置',
|
||||||
|
create: '創建標籤',
|
||||||
|
edit: '編輯標籤',
|
||||||
|
deleteConfirm: '是否刪除標籤: ',
|
||||||
|
deleteTip: '刪除後使用該標籤的資源將會刪除該標籤,請謹慎操作!',
|
||||||
|
requiredMessage1: '請輸入標籤',
|
||||||
|
requiredMessage2: '請輸入標籤值',
|
||||||
|
},
|
||||||
table: {
|
table: {
|
||||||
name: '文件名稱',
|
name: '文件名稱',
|
||||||
char_length: '字符數',
|
char_length: '字符數',
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,97 @@
|
||||||
|
<template>
|
||||||
|
<el-dialog
|
||||||
|
v-model="dialogVisible"
|
||||||
|
:title="$t('views.document.tag.add')"
|
||||||
|
:before-close="close"
|
||||||
|
>
|
||||||
|
<el-form
|
||||||
|
ref="FormRef"
|
||||||
|
:model="{ tags }"
|
||||||
|
label-position="top"
|
||||||
|
require-asterisk-position="right"
|
||||||
|
@submit.prevent
|
||||||
|
>
|
||||||
|
<div class="flex-between flex" v-for="(tag, index) in tags" :key="tag">
|
||||||
|
<el-form-item :label="index === 0? $t('views.document.tag.key') : ''"
|
||||||
|
:prop="`tags.${index}.key`"
|
||||||
|
style="width: 50%"
|
||||||
|
:rules="{ required: true, message: $t('views.document.tag.requiredMessage1'), trigger: 'blur' }">
|
||||||
|
<el-select v-model="tag.key" @change="tagKeyChange(tag)" filterable>
|
||||||
|
<el-option v-for="op in keyOptions" :key="op" :value="op.key"
|
||||||
|
:label="op.key"></el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item :label="index === 0? $t('views.document.tag.value') : ''"
|
||||||
|
:prop="`tags.${index}.value`"
|
||||||
|
style="width: 50%"
|
||||||
|
:rules="{ required: true, message: $t('views.document.tag.requiredMessage2'), trigger: 'blur' }">
|
||||||
|
<el-select v-model="tag.value" filterable>
|
||||||
|
<el-option v-for="op in tag.valueOptions" :key="op" :value="op.id"
|
||||||
|
:label="op.value"></el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
</div>
|
||||||
|
</el-form>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="mt-20">
|
||||||
|
<el-button link type="primary" @click="add">
|
||||||
|
<AppIcon iconName="app-add-outlined" class="mr-4"/>
|
||||||
|
{{ $t('common.add') }}
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
<template #footer>
|
||||||
|
<div class="dialog-footer">
|
||||||
|
<el-button @click="close">{{ $t('common.cancel') }}</el-button>
|
||||||
|
<el-button type="primary" @click="submit">{{ $t('common.confirm') }}</el-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref } from 'vue'
|
||||||
|
import AppIcon from "@/components/app-icon/AppIcon.vue";
|
||||||
|
|
||||||
|
const emit = defineEmits(['addTags'])
|
||||||
|
const props = defineProps({
|
||||||
|
knowledgeTags: {
|
||||||
|
type: Array,
|
||||||
|
default: () => []
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const FormRef = ref()
|
||||||
|
const dialogVisible = ref<boolean>(false)
|
||||||
|
const tags = ref<Array<any>>([])
|
||||||
|
const keyOptions = ref()
|
||||||
|
|
||||||
|
const add = () => {
|
||||||
|
tags.value.push({})
|
||||||
|
}
|
||||||
|
|
||||||
|
function tagKeyChange(tag: any) {
|
||||||
|
const currentKeyOption = keyOptions.value.find((op: any) => op.key === tag.key)
|
||||||
|
tag.valueOptions = currentKeyOption ? currentKeyOption.values : []
|
||||||
|
tag.value = null
|
||||||
|
}
|
||||||
|
|
||||||
|
const submit = () => {
|
||||||
|
FormRef.value.validate((valid: boolean) => {
|
||||||
|
if (!valid) return
|
||||||
|
emit('addTags', tags.value.map(tag => tag.value))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const open = () => {
|
||||||
|
dialogVisible.value = true
|
||||||
|
tags.value = [{}]
|
||||||
|
keyOptions.value = props.knowledgeTags
|
||||||
|
}
|
||||||
|
|
||||||
|
const close = () => {
|
||||||
|
dialogVisible.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
defineExpose({open, close})
|
||||||
|
</script>
|
||||||
|
<style lang="scss" scoped></style>
|
||||||
|
|
@ -0,0 +1,107 @@
|
||||||
|
<template>
|
||||||
|
<el-dialog
|
||||||
|
v-model="dialogVisible"
|
||||||
|
:title="$t('views.document.tag.create')"
|
||||||
|
:before-close="close"
|
||||||
|
>
|
||||||
|
<el-form
|
||||||
|
ref="FormRef"
|
||||||
|
:model="{ tags }"
|
||||||
|
label-position="top"
|
||||||
|
require-asterisk-position="right"
|
||||||
|
@submit.prevent
|
||||||
|
>
|
||||||
|
<div class="flex-between" v-for="(tag, index) in tags" :key="tag">
|
||||||
|
<el-form-item :label="index === 0? $t('views.document.tag.key') : ''"
|
||||||
|
:prop="`tags.${index}.key`"
|
||||||
|
style="width: 50%"
|
||||||
|
:rules="{ required: true, message: $t('views.document.tag.requiredMessage1'), trigger: 'blur' }">
|
||||||
|
<el-input v-model="tag.key" :disabled="currentTagKey"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item :label="index === 0? $t('views.document.tag.value') : ''"
|
||||||
|
:prop="`tags.${index}.value`"
|
||||||
|
style="width: 50%"
|
||||||
|
:rules="{ required: true, message: $t('views.document.tag.requiredMessage2'), trigger: 'blur' }">
|
||||||
|
<el-input v-model="tag.value"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
</div>
|
||||||
|
</el-form>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="mt-20">
|
||||||
|
<el-button link type="primary" @click="add">
|
||||||
|
<AppIcon iconName="app-add-outlined" class="mr-4"/>
|
||||||
|
{{ $t('common.add') }}
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
<template #footer>
|
||||||
|
<div class="dialog-footer">
|
||||||
|
<el-button @click="close">{{ $t('common.cancel') }}</el-button>
|
||||||
|
<el-button type="primary" @click="submit">{{ $t('common.confirm') }}</el-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { computed, ref } from 'vue'
|
||||||
|
import AppIcon from "@/components/app-icon/AppIcon.vue";
|
||||||
|
import { useRoute } from "vue-router";
|
||||||
|
import { loadSharedApi } from "@/utils/dynamics-api/shared-api.ts";
|
||||||
|
import { cloneDeep } from "lodash";
|
||||||
|
|
||||||
|
const route = useRoute()
|
||||||
|
const {
|
||||||
|
params: {id}, // id为knowledgeID
|
||||||
|
} = route as any
|
||||||
|
const emit = defineEmits(['refresh'])
|
||||||
|
|
||||||
|
const apiType = computed(() => {
|
||||||
|
if (route.path.includes('shared')) {
|
||||||
|
return 'systemShare'
|
||||||
|
} else if (route.path.includes('resource-management')) {
|
||||||
|
return 'systemManage'
|
||||||
|
} else {
|
||||||
|
return 'workspace'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const FormRef = ref()
|
||||||
|
const loading = ref(false)
|
||||||
|
const dialogVisible = ref<boolean>(false)
|
||||||
|
const currentTagKey = ref(null)
|
||||||
|
const tags = ref<Array<any>>([])
|
||||||
|
|
||||||
|
const add = () => {
|
||||||
|
if (currentTagKey.value) {
|
||||||
|
tags.value.push({key: currentTagKey.value})
|
||||||
|
} else {
|
||||||
|
tags.value.push({})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const submit = () => {
|
||||||
|
FormRef.value.validate((valid: boolean) => {
|
||||||
|
if (!valid) return
|
||||||
|
loadSharedApi({type: 'knowledge', systemType: apiType.value})
|
||||||
|
.postTags(id, tags.value, loading)
|
||||||
|
.then((res: any) => {
|
||||||
|
close()
|
||||||
|
emit('refresh')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const open = (row?: any) => {
|
||||||
|
const currentRow = cloneDeep(row)
|
||||||
|
dialogVisible.value = true
|
||||||
|
currentTagKey.value = currentRow ? currentRow.key : null
|
||||||
|
tags.value = currentRow ? [{...{key: currentRow.key}}] : [{}]
|
||||||
|
}
|
||||||
|
|
||||||
|
const close = () => {
|
||||||
|
dialogVisible.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
defineExpose({open, close})
|
||||||
|
</script>
|
||||||
|
<style lang="scss" scoped></style>
|
||||||
|
|
@ -0,0 +1,98 @@
|
||||||
|
<template>
|
||||||
|
<el-dialog
|
||||||
|
v-model="dialogVisible"
|
||||||
|
:title="$t('views.document.tag.edit')"
|
||||||
|
:before-close="close"
|
||||||
|
>
|
||||||
|
<el-form
|
||||||
|
ref="FormRef"
|
||||||
|
:model="form"
|
||||||
|
label-position="top"
|
||||||
|
require-asterisk-position="right"
|
||||||
|
@submit.prevent
|
||||||
|
>
|
||||||
|
<el-form-item label="标签" v-if="isEditKey"
|
||||||
|
:rules="{ required: true, message: $t('views.document.tag.requiredMessage1'), trigger: 'blur' }"
|
||||||
|
prop="key">
|
||||||
|
<el-input v-model="form.key"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<div v-else class="flex-between">
|
||||||
|
<el-form-item label="标签" prop="key"
|
||||||
|
style="width: 50%"
|
||||||
|
:rules="{ required: true, message: $t('views.document.tag.requiredMessage1'), trigger: 'blur' }">
|
||||||
|
<el-input v-model="form.key" :disabled="true"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="标签值" prop="value"
|
||||||
|
style="width: 50%"
|
||||||
|
:rules="{ required: true, message: $t('views.document.tag.requiredMessage2'), trigger: 'blur' }">
|
||||||
|
<el-input v-model="form.value"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
</div>
|
||||||
|
</el-form>
|
||||||
|
<template #footer>
|
||||||
|
<div class="dialog-footer">
|
||||||
|
<el-button @click="close">{{ $t('common.cancel') }}</el-button>
|
||||||
|
<el-button type="primary" @click="submit">{{ $t('common.confirm') }}</el-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { computed, ref } from 'vue'
|
||||||
|
import { useRoute } from "vue-router";
|
||||||
|
import { loadSharedApi } from "@/utils/dynamics-api/shared-api.ts";
|
||||||
|
|
||||||
|
const route = useRoute()
|
||||||
|
const {
|
||||||
|
params: {id}, // id为knowledgeID
|
||||||
|
} = route as any
|
||||||
|
const emit = defineEmits(['refresh'])
|
||||||
|
|
||||||
|
const apiType = computed(() => {
|
||||||
|
if (route.path.includes('shared')) {
|
||||||
|
return 'systemShare'
|
||||||
|
} else if (route.path.includes('resource-management')) {
|
||||||
|
return 'systemManage'
|
||||||
|
} else {
|
||||||
|
return 'workspace'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
const FormRef = ref()
|
||||||
|
const isEditKey = ref(false)
|
||||||
|
const form = ref({
|
||||||
|
id: '',
|
||||||
|
key: '',
|
||||||
|
value: ''
|
||||||
|
})
|
||||||
|
|
||||||
|
const loading = ref(false)
|
||||||
|
const dialogVisible = ref<boolean>(false)
|
||||||
|
|
||||||
|
const submit = () => {
|
||||||
|
FormRef.value.validate((valid: boolean) => {
|
||||||
|
if (valid) {
|
||||||
|
loadSharedApi({type: 'knowledge', systemType: apiType.value})
|
||||||
|
.putTag(id, form.value.id, form.value, loading)
|
||||||
|
.then((res: any) => {
|
||||||
|
close()
|
||||||
|
emit('refresh')
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const open = (row: any, isKey: boolean) => {
|
||||||
|
dialogVisible.value = true
|
||||||
|
form.value.id = row.id
|
||||||
|
form.value.key = row.key
|
||||||
|
form.value.value = row.value
|
||||||
|
isEditKey.value = isKey
|
||||||
|
}
|
||||||
|
|
||||||
|
const close = () => {
|
||||||
|
dialogVisible.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
defineExpose({open, close})
|
||||||
|
</script>
|
||||||
|
<style lang="scss" scoped></style>
|
||||||
|
|
@ -0,0 +1,232 @@
|
||||||
|
<template>
|
||||||
|
<el-drawer v-model="debugVisible" size="60%" :append-to-body="true">
|
||||||
|
<template #header>
|
||||||
|
<h4>{{ $t('views.document.tag.label') }}</h4>
|
||||||
|
</template>
|
||||||
|
<div class="flex-between">
|
||||||
|
<div>
|
||||||
|
<el-button type="primary" @click="openCreateTagDialog()">{{
|
||||||
|
$t('views.document.tag.create')
|
||||||
|
}}
|
||||||
|
</el-button>
|
||||||
|
<el-button :disabled="multipleSelection.length === 0" @click="batchDelete">
|
||||||
|
{{ $t('common.delete') }}
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
<el-input
|
||||||
|
v-model="filterText"
|
||||||
|
prefix-icon="Search"
|
||||||
|
class="w-240"
|
||||||
|
@change="getList"
|
||||||
|
clearable
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<el-table
|
||||||
|
:data="tableData"
|
||||||
|
:span-method="spanMethod"
|
||||||
|
v-loading="loading"
|
||||||
|
@selection-change="handleSelectionChange"
|
||||||
|
>
|
||||||
|
<el-table-column type="selection" width="55"/>
|
||||||
|
<el-table-column :label="$t('views.document.tag.key')">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<div class="flex-between">
|
||||||
|
{{ row.key }}
|
||||||
|
<div>
|
||||||
|
<el-button link>
|
||||||
|
<AppIcon iconName="app-add-outlined" class="mr-4"
|
||||||
|
@click="openCreateTagDialog(row)"/>
|
||||||
|
</el-button>
|
||||||
|
<el-button link>
|
||||||
|
<AppIcon iconName="app-edit" class="mr-4" @click="editTagKey(row)"/>
|
||||||
|
</el-button>
|
||||||
|
<el-button link>
|
||||||
|
<AppIcon iconName="app-delete" class="mr-4" @click="delTag(row)"/>
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column :label="$t('views.document.tag.value')">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<div class="flex-between">
|
||||||
|
{{ row.value }}
|
||||||
|
<div>
|
||||||
|
<el-button link>
|
||||||
|
<AppIcon iconName="app-edit" class="mr-4" @click="editTagValue(row)"/>
|
||||||
|
</el-button>
|
||||||
|
<el-button link>
|
||||||
|
<AppIcon iconName="app-delete" class="mr-4" @click="delTagValue(row)"/>
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
</el-drawer>
|
||||||
|
<CreateTagDialog ref="createTagDialogRef" @refresh="getList"/>
|
||||||
|
<EditTagDialog ref="editTagDialogRef" @refresh="getList"/>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { computed, ref } from 'vue'
|
||||||
|
import { useRoute } from 'vue-router'
|
||||||
|
import { loadSharedApi } from "@/utils/dynamics-api/shared-api.ts"
|
||||||
|
import CreateTagDialog from "./CreateTagDialog.vue"
|
||||||
|
import { MsgConfirm } from "@/utils/message.ts";
|
||||||
|
import { t } from "@/locales";
|
||||||
|
import EditTagDialog from "@/views/document/component/EditTagDialog.vue";
|
||||||
|
|
||||||
|
const emit = defineEmits(['refresh'])
|
||||||
|
|
||||||
|
const route = useRoute()
|
||||||
|
const {
|
||||||
|
params: {id}, // id为knowledgeID
|
||||||
|
} = route as any
|
||||||
|
|
||||||
|
const apiType = computed(() => {
|
||||||
|
if (route.path.includes('shared')) {
|
||||||
|
return 'systemShare'
|
||||||
|
} else if (route.path.includes('resource-management')) {
|
||||||
|
return 'systemManage'
|
||||||
|
} else {
|
||||||
|
return 'workspace'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const loading = ref(false)
|
||||||
|
const debugVisible = ref(false)
|
||||||
|
const filterText = ref('')
|
||||||
|
const tags = ref<Array<any>>([])
|
||||||
|
|
||||||
|
// 将原始数据转换为表格数据
|
||||||
|
const tableData = computed(() => {
|
||||||
|
const result: any[] = []
|
||||||
|
tags.value.forEach((tag: any) => {
|
||||||
|
if (tag.values && tag.values.length > 0) {
|
||||||
|
tag.values.forEach((value: any, index: number) => {
|
||||||
|
result.push({
|
||||||
|
id: value.id,
|
||||||
|
key: tag.key,
|
||||||
|
value: value.value,
|
||||||
|
keyIndex: index // 用于判断是否为第一行
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return result
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
// 合并单元格方法
|
||||||
|
const spanMethod = ({row, column, rowIndex, columnIndex}: any) => {
|
||||||
|
if (columnIndex === 0 || columnIndex === 1) { // key列 (由于添加了选择列,索引变为1)
|
||||||
|
if (row.keyIndex === 0) {
|
||||||
|
// 计算当前key有多少个值
|
||||||
|
const sameKeyCount = tableData.value.filter(item => item.key === row.key).length
|
||||||
|
return {
|
||||||
|
rowspan: sameKeyCount,
|
||||||
|
colspan: 1
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
rowspan: 0,
|
||||||
|
colspan: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const multipleSelection = ref<any[]>([])
|
||||||
|
const handleSelectionChange = (val: any[]) => {
|
||||||
|
multipleSelection.value = val
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const createTagDialogRef = ref()
|
||||||
|
|
||||||
|
function openCreateTagDialog(row?: any) {
|
||||||
|
createTagDialogRef.value?.open(row)
|
||||||
|
}
|
||||||
|
|
||||||
|
function batchDelete() {
|
||||||
|
MsgConfirm(t('views.document.tag.deleteConfirm'), t('views.document.tag.deleteTip'), {
|
||||||
|
confirmButtonText: t('common.delete'),
|
||||||
|
confirmButtonClass: 'danger',
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
const tagsToDelete = multipleSelection.value.map(item => item.id)
|
||||||
|
loadSharedApi({type: 'knowledge', systemType: apiType.value})
|
||||||
|
.delMulTag(id, tagsToDelete)
|
||||||
|
.then(() => {
|
||||||
|
getList()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const editTagDialogRef = ref()
|
||||||
|
|
||||||
|
function editTagKey(row: any) {
|
||||||
|
editTagDialogRef.value?.open(row, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
function delTag(row: any) {
|
||||||
|
MsgConfirm(t('views.document.tag.deleteConfirm') + row.key, t('views.document.tag.deleteTip'), {
|
||||||
|
confirmButtonText: t('common.delete'),
|
||||||
|
confirmButtonClass: 'danger',
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
loadSharedApi({type: 'knowledge', systemType: apiType.value})
|
||||||
|
.delTag(id, row.id, 'key')
|
||||||
|
.then(() => {
|
||||||
|
getList()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function editTagValue(row: any) {
|
||||||
|
editTagDialogRef.value?.open(row, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
function delTagValue(row: any) {
|
||||||
|
MsgConfirm(t('views.document.tag.deleteConfirm') + row.key + '-' + row.value, t('views.document.tag.deleteTip'), {
|
||||||
|
confirmButtonText: t('common.delete'),
|
||||||
|
confirmButtonClass: 'danger',
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
loadSharedApi({type: 'knowledge', systemType: apiType.value})
|
||||||
|
.delTag(id, row.id, 'one')
|
||||||
|
.then(() => {
|
||||||
|
getList()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function getList() {
|
||||||
|
const params = {
|
||||||
|
...(filterText.value && {name: filterText.value}),
|
||||||
|
}
|
||||||
|
loadSharedApi({type: 'knowledge', systemType: apiType.value})
|
||||||
|
.getTags(id, params, loading)
|
||||||
|
.then((res: any) => {
|
||||||
|
tags.value = res.data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const open = () => {
|
||||||
|
debugVisible.value = true
|
||||||
|
getList()
|
||||||
|
}
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
open,
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
<style lang="scss"></style>
|
||||||
|
|
@ -0,0 +1,214 @@
|
||||||
|
<template>
|
||||||
|
<el-drawer v-model="debugVisible" size="60%" :append-to-body="true">
|
||||||
|
<template #header>
|
||||||
|
<h4>{{ $t('views.document.tag.setting') }}</h4>
|
||||||
|
</template>
|
||||||
|
<div class="flex-between">
|
||||||
|
<div>
|
||||||
|
<el-button type="primary" @click="openAddTagDialog()">
|
||||||
|
{{ $t('views.document.tag.add') }}
|
||||||
|
</el-button>
|
||||||
|
<el-button :disabled="multipleSelection.length === 0" @click="batchDelete">
|
||||||
|
{{ $t('common.delete') }}
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
<el-input
|
||||||
|
v-model="filterText"
|
||||||
|
prefix-icon="Search"
|
||||||
|
class="w-240"
|
||||||
|
@change="getList"
|
||||||
|
clearable
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<el-table
|
||||||
|
:data="tableData"
|
||||||
|
:span-method="spanMethod"
|
||||||
|
v-loading="loading"
|
||||||
|
@selection-change="handleSelectionChange"
|
||||||
|
>
|
||||||
|
<el-table-column type="selection" width="55"/>
|
||||||
|
<el-table-column :label="$t('views.document.tag.key')">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<div class="flex-between">
|
||||||
|
{{ row.key }}
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column :label="$t('views.document.tag.value')">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<div class="flex-between">
|
||||||
|
{{ row.value }}
|
||||||
|
<div>
|
||||||
|
<el-button link>
|
||||||
|
<AppIcon iconName="app-delete" class="mr-4" @click="delTagValue(row)"/>
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
</el-drawer>
|
||||||
|
<AddTagDialog ref="addTagDialogRef" @addTags="addTags" :knowledge-tags="knowledgeTags"/>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { computed, ref } from 'vue'
|
||||||
|
import { useRoute } from 'vue-router'
|
||||||
|
import { loadSharedApi } from "@/utils/dynamics-api/shared-api.ts"
|
||||||
|
import { MsgConfirm } from "@/utils/message.ts";
|
||||||
|
import { t } from "@/locales";
|
||||||
|
import AddTagDialog from "@/views/document/component/AddTagDialog.vue";
|
||||||
|
|
||||||
|
const emit = defineEmits(['refresh'])
|
||||||
|
const props = defineProps({
|
||||||
|
knowledgeTags: {
|
||||||
|
type: Array,
|
||||||
|
default: () => []
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const route = useRoute()
|
||||||
|
const {
|
||||||
|
params: {id}, // id为knowledgeID
|
||||||
|
} = route as any
|
||||||
|
|
||||||
|
const apiType = computed(() => {
|
||||||
|
if (route.path.includes('shared')) {
|
||||||
|
return 'systemShare'
|
||||||
|
} else if (route.path.includes('resource-management')) {
|
||||||
|
return 'systemManage'
|
||||||
|
} else {
|
||||||
|
return 'workspace'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const document_id = ref('')
|
||||||
|
const loading = ref(false)
|
||||||
|
const debugVisible = ref(false)
|
||||||
|
const filterText = ref('')
|
||||||
|
const tags = ref<Array<any>>([])
|
||||||
|
|
||||||
|
// 将原始数据转换为表格数据
|
||||||
|
const tableData = computed(() => {
|
||||||
|
const result: any[] = []
|
||||||
|
tags.value.forEach((tag: any) => {
|
||||||
|
if (tag.values && tag.values.length > 0) {
|
||||||
|
tag.values.forEach((value: any, index: number) => {
|
||||||
|
result.push({
|
||||||
|
id: value.id,
|
||||||
|
key: tag.key,
|
||||||
|
value: value.value,
|
||||||
|
keyIndex: index // 用于判断是否为第一行
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return result
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
// 合并单元格方法
|
||||||
|
const spanMethod = ({row, column, rowIndex, columnIndex}: any) => {
|
||||||
|
if (columnIndex === 0 || columnIndex === 1) { // key列 (由于添加了选择列,索引变为1)
|
||||||
|
if (row.keyIndex === 0) {
|
||||||
|
// 计算当前key有多少个值
|
||||||
|
const sameKeyCount = tableData.value.filter(item => item.key === row.key).length
|
||||||
|
return {
|
||||||
|
rowspan: sameKeyCount,
|
||||||
|
colspan: 1
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
rowspan: 0,
|
||||||
|
colspan: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const multipleSelection = ref<any[]>([])
|
||||||
|
const handleSelectionChange = (val: any[]) => {
|
||||||
|
multipleSelection.value = val
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function batchDelete() {
|
||||||
|
MsgConfirm(t('views.document.tag.deleteConfirm'), t('views.document.tag.deleteTip'), {
|
||||||
|
confirmButtonText: t('common.delete'),
|
||||||
|
confirmButtonClass: 'danger',
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
const tagsToDelete = multipleSelection.value.reduce((acc, item) => {
|
||||||
|
// 找出当前选中项的key对应的所有value id
|
||||||
|
const sameKeyItems = tableData.value.filter(data => data.key === item.key)
|
||||||
|
const sameKeyIds = sameKeyItems.map(data => data.id)
|
||||||
|
return [...acc, ...sameKeyIds]
|
||||||
|
}, [] as string[])
|
||||||
|
|
||||||
|
loadSharedApi({type: 'document', systemType: apiType.value})
|
||||||
|
.delMulDocumentTag(id, document_id.value, tagsToDelete, loading)
|
||||||
|
.then(() => {
|
||||||
|
getList()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function delTagValue(row: any) {
|
||||||
|
MsgConfirm(t('views.document.tag.deleteConfirm') + row.key + '-' + row.value, t('views.document.tag.deleteTip'), {
|
||||||
|
confirmButtonText: t('common.delete'),
|
||||||
|
confirmButtonClass: 'danger',
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
loadSharedApi({type: 'document', systemType: apiType.value})
|
||||||
|
.delMulDocumentTag(id, document_id.value, [row.id], loading)
|
||||||
|
.then(() => {
|
||||||
|
getList()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function getList() {
|
||||||
|
const params = {
|
||||||
|
...(filterText.value && {name: filterText.value}),
|
||||||
|
}
|
||||||
|
loadSharedApi({type: 'document', systemType: apiType.value})
|
||||||
|
.getDocumentTags(id, document_id.value, params, loading)
|
||||||
|
.then((res: any) => {
|
||||||
|
tags.value = res.data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const addTagDialogRef = ref()
|
||||||
|
|
||||||
|
function openAddTagDialog() {
|
||||||
|
addTagDialogRef.value?.open()
|
||||||
|
}
|
||||||
|
|
||||||
|
function addTags(tags: any) {
|
||||||
|
loadSharedApi({type: 'document', systemType: apiType.value})
|
||||||
|
.postDocumentTags(id, document_id.value, tags, loading)
|
||||||
|
.then(() => {
|
||||||
|
addTagDialogRef.value?.close()
|
||||||
|
getList()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const open = (doc: any) => {
|
||||||
|
debugVisible.value = true
|
||||||
|
document_id.value = doc.id
|
||||||
|
|
||||||
|
getList()
|
||||||
|
}
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
open,
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
<style lang="scss"></style>
|
||||||
|
|
@ -57,6 +57,13 @@
|
||||||
>
|
>
|
||||||
{{ $t('common.setting') }}
|
{{ $t('common.setting') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
|
<el-button
|
||||||
|
@click="openAddTagDialog()"
|
||||||
|
:disabled="multipleSelection.length === 0"
|
||||||
|
v-if="permissionPrecise.doc_edit(id)"
|
||||||
|
>
|
||||||
|
{{ $t('views.document.tag.add') }}
|
||||||
|
</el-button>
|
||||||
<el-dropdown v-if="MoreFilledPermission0(id)">
|
<el-dropdown v-if="MoreFilledPermission0(id)">
|
||||||
<el-button class="ml-12 mr-12">
|
<el-button class="ml-12 mr-12">
|
||||||
<AppIcon iconName="app-more"></AppIcon>
|
<AppIcon iconName="app-more"></AppIcon>
|
||||||
|
|
@ -96,15 +103,19 @@
|
||||||
</el-dropdown>
|
</el-dropdown>
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
|
<div>
|
||||||
<el-input
|
<el-input
|
||||||
v-model="filterText"
|
v-model="filterText"
|
||||||
:placeholder="$t('common.searchBar.placeholder')"
|
:placeholder="$t('common.searchBar.placeholder')"
|
||||||
prefix-icon="Search"
|
prefix-icon="Search"
|
||||||
class="w-240"
|
class="w-240"
|
||||||
@change="getList"
|
@change="getList"
|
||||||
clearable
|
clearable
|
||||||
/>
|
/>
|
||||||
|
<el-button @click="openTagDrawer" class="ml-12">
|
||||||
|
{{ $t('views.document.tag.label') }}
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<app-table
|
<app-table
|
||||||
ref="multipleTableRef"
|
ref="multipleTableRef"
|
||||||
|
|
@ -448,6 +459,11 @@
|
||||||
></AppIcon>
|
></AppIcon>
|
||||||
{{ $t('views.document.generateQuestion.title') }}
|
{{ $t('views.document.generateQuestion.title') }}
|
||||||
</el-dropdown-item>
|
</el-dropdown-item>
|
||||||
|
<el-dropdown-item
|
||||||
|
@click="openTagSettingDrawer(row)"
|
||||||
|
>
|
||||||
|
{{ $t('views.document.tag.setting') }}
|
||||||
|
</el-dropdown-item>
|
||||||
<el-dropdown-item
|
<el-dropdown-item
|
||||||
@click="openknowledgeDialog(row)"
|
@click="openknowledgeDialog(row)"
|
||||||
v-if="permissionPrecise.doc_migrate(id)"
|
v-if="permissionPrecise.doc_migrate(id)"
|
||||||
|
|
@ -645,6 +661,9 @@
|
||||||
:workspaceId="knowledgeDetail?.workspace_id"
|
:workspaceId="knowledgeDetail?.workspace_id"
|
||||||
/>
|
/>
|
||||||
<GenerateRelatedDialog ref="GenerateRelatedDialogRef" @refresh="getList" :apiType="apiType" />
|
<GenerateRelatedDialog ref="GenerateRelatedDialogRef" @refresh="getList" :apiType="apiType" />
|
||||||
|
<TagDrawer ref="tagDrawerRef"/>
|
||||||
|
<TagSettingDrawer ref="tagSettingDrawerRef" :knowledge-tags="knowledgeTags"/>
|
||||||
|
<AddTagDialog ref="addTagDialogRef" @addTags="addTags" :knowledge-tags="knowledgeTags"/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
|
@ -666,6 +685,9 @@ import { TaskType, State } from '@/utils/status'
|
||||||
import { t } from '@/locales'
|
import { t } from '@/locales'
|
||||||
import permissionMap from '@/permission'
|
import permissionMap from '@/permission'
|
||||||
import { loadSharedApi } from '@/utils/dynamics-api/shared-api'
|
import { loadSharedApi } from '@/utils/dynamics-api/shared-api'
|
||||||
|
import TagDrawer from "./component/TagDrawer.vue";
|
||||||
|
import TagSettingDrawer from "./component/TagSettingDrawer.vue";
|
||||||
|
import AddTagDialog from "@/views/document/component/AddTagDialog.vue";
|
||||||
|
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
|
@ -1181,6 +1203,43 @@ function openGenerateDialog(row?: any) {
|
||||||
GenerateRelatedDialogRef.value.open(arr, 'document')
|
GenerateRelatedDialogRef.value.open(arr, 'document')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const tagDrawerRef = ref()
|
||||||
|
function openTagDrawer() {
|
||||||
|
tagDrawerRef.value.open()
|
||||||
|
}
|
||||||
|
|
||||||
|
const tagSettingDrawerRef = ref()
|
||||||
|
function openTagSettingDrawer(doc: any) {
|
||||||
|
tagSettingDrawerRef.value.open(doc)
|
||||||
|
}
|
||||||
|
|
||||||
|
const addTagDialogRef = ref()
|
||||||
|
|
||||||
|
function openAddTagDialog() {
|
||||||
|
addTagDialogRef.value?.open()
|
||||||
|
}
|
||||||
|
|
||||||
|
function addTags(tags: any) {
|
||||||
|
const arr: string[] = multipleSelection.value.map((v) => v.id)
|
||||||
|
|
||||||
|
loadSharedApi({type: 'document', systemType: apiType.value})
|
||||||
|
.postMulDocumentTags(id, {tag_ids: tags, document_ids: arr}, loading)
|
||||||
|
.then(() => {
|
||||||
|
addTagDialogRef.value?.close()
|
||||||
|
getList()
|
||||||
|
clearSelection()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const knowledgeTags = ref<any[]>([])
|
||||||
|
function getTags() {
|
||||||
|
loadSharedApi({type: 'knowledge', systemType: apiType.value})
|
||||||
|
.getTags(id, {}, loading)
|
||||||
|
.then((res: any) => {
|
||||||
|
knowledgeTags.value = res.data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
getDetail()
|
getDetail()
|
||||||
if (beforePagination.value) {
|
if (beforePagination.value) {
|
||||||
|
|
@ -1191,6 +1250,7 @@ onMounted(() => {
|
||||||
filterMethod.value = beforeSearch.value['filterMethod']
|
filterMethod.value = beforeSearch.value['filterMethod']
|
||||||
}
|
}
|
||||||
getList()
|
getList()
|
||||||
|
getTags()
|
||||||
// 初始化定时任务
|
// 初始化定时任务
|
||||||
initInterval()
|
initInterval()
|
||||||
})
|
})
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue