From 8edbecba8dc96e45a1c5516f69c3a201956a960f Mon Sep 17 00:00:00 2001 From: wxg0103 <727495428@qq.com> Date: Tue, 5 Nov 2024 11:52:56 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=BA=94=E7=94=A8=E3=80=81=E7=9F=A5?= =?UTF-8?q?=E8=AF=86=E5=BA=93=E3=80=81=E5=87=BD=E6=95=B0=E5=BA=93=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E5=88=9B=E5=BB=BA=E8=80=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --story=1016834 --user=王孝刚 应用、知识库、函数增加创建者,可以按创建用户查看资源 #1304 https://www.tapd.cn/57709429/s/1605886 --- .../serializers/application_serializers.py | 13 ++- .../serializers/dataset_serializers.py | 6 +- apps/dataset/views/dataset.py | 2 +- .../serializers/function_lib_serializer.py | 3 + apps/function_lib/views/function_lib_views.py | 3 +- apps/users/serializers/user_serializers.py | 37 ++++++- apps/users/urls.py | 1 + apps/users/views/user.py | 13 +++ ui/src/api/application.ts | 10 +- ui/src/components/card-box/index.vue | 20 +++- ui/src/styles/variables.scss | 2 +- ui/src/views/application/index.vue | 89 +++++++++++++---- ui/src/views/dataset/index.vue | 94 ++++++++++++++---- ui/src/views/function-lib/index.vue | 96 +++++++++++++++---- 14 files changed, 323 insertions(+), 66 deletions(-) diff --git a/apps/application/serializers/application_serializers.py b/apps/application/serializers/application_serializers.py index a271c2345c4..0232313e824 100644 --- a/apps/application/serializers/application_serializers.py +++ b/apps/application/serializers/application_serializers.py @@ -19,8 +19,10 @@ from django.contrib.postgres.fields import ArrayField from django.core import cache, validators from django.core import signing +from django.core.paginator import Paginator from django.db import transaction, models -from django.db.models import QuerySet +from django.db.models import QuerySet, Q +from django.forms import CharField from django.http import HttpResponse from django.template import Template, Context from rest_framework import serializers @@ -44,7 +46,7 @@ from dataset.serializers.common_serializers import list_paragraph, get_embedding_model_by_dataset_id_list from embedding.models import SearchMode from function_lib.serializers.function_lib_serializer import FunctionLibSerializer -from setting.models import AuthOperate +from setting.models import AuthOperate, TeamMember, TeamMemberPermission from setting.models.model_management import Model from setting.models_provider import get_model_credential from setting.models_provider.constants.model_provider_constants import ModelProvideConstants @@ -559,17 +561,22 @@ class Query(serializers.Serializer): desc = serializers.CharField(required=False, error_messages=ErrMessage.char("应用描述")) user_id = serializers.UUIDField(required=True, error_messages=ErrMessage.uuid("用户id")) + select_user_id = serializers.UUIDField(required=False, error_messages=ErrMessage.uuid("选择用户id")) def get_query_set(self): user_id = self.data.get("user_id") query_set_dict = {} query_set = QuerySet(model=get_dynamics_model( {'temp_application.name': models.CharField(), 'temp_application.desc': models.CharField(), - 'temp_application.create_time': models.DateTimeField()})) + 'temp_application.create_time': models.DateTimeField(), + 'temp_application.user_id': models.CharField(), })) if "desc" in self.data and self.data.get('desc') is not None: query_set = query_set.filter(**{'temp_application.desc__icontains': self.data.get("desc")}) if "name" in self.data and self.data.get('name') is not None: query_set = query_set.filter(**{'temp_application.name__icontains': self.data.get("name")}) + if 'select_user_id' in self.data and self.data.get('select_user_id') is not None and self.data.get( + 'select_user_id') != 'all': + query_set = query_set.filter(**{'temp_application.user_id__exact': self.data.get('select_user_id')}) query_set = query_set.order_by("-temp_application.create_time") query_set_dict['default_sql'] = query_set diff --git a/apps/dataset/serializers/dataset_serializers.py b/apps/dataset/serializers/dataset_serializers.py index 7250bea7744..7598432cc5e 100644 --- a/apps/dataset/serializers/dataset_serializers.py +++ b/apps/dataset/serializers/dataset_serializers.py @@ -129,17 +129,21 @@ class Query(ApiMixin, serializers.Serializer): ) user_id = serializers.CharField(required=True) + select_user_id = serializers.CharField(required=False) def get_query_set(self): user_id = self.data.get("user_id") query_set_dict = {} query_set = QuerySet(model=get_dynamics_model( {'temp.name': models.CharField(), 'temp.desc': models.CharField(), - "document_temp.char_length": models.IntegerField(), 'temp.create_time': models.DateTimeField()})) + "document_temp.char_length": models.IntegerField(), 'temp.create_time': models.DateTimeField(), + 'temp.user_id': models.CharField(), })) if "desc" in self.data and self.data.get('desc') is not None: query_set = query_set.filter(**{'temp.desc__icontains': self.data.get("desc")}) if "name" in self.data and self.data.get('name') is not None: query_set = query_set.filter(**{'temp.name__icontains': self.data.get("name")}) + if "select_user_id" in self.data and self.data.get('select_user_id') is not None: + query_set = query_set.filter(**{'temp.user_id__exact': self.data.get("select_user_id")}) query_set = query_set.order_by("-temp.create_time") query_set_dict['default_sql'] = query_set diff --git a/apps/dataset/views/dataset.py b/apps/dataset/views/dataset.py index 4bd9e1f749b..f16fbd45b7e 100644 --- a/apps/dataset/views/dataset.py +++ b/apps/dataset/views/dataset.py @@ -221,7 +221,7 @@ class Page(APIView): def get(self, request: Request, current_page, page_size): d = DataSetSerializers.Query( data={'name': request.query_params.get('name', None), 'desc': request.query_params.get("desc", None), - 'user_id': str(request.user.id)}) + 'user_id': str(request.user.id), 'select_user_id': request.query_params.get('select_user_id', None)}) d.is_valid() return result.success(d.page(current_page, page_size)) diff --git a/apps/function_lib/serializers/function_lib_serializer.py b/apps/function_lib/serializers/function_lib_serializer.py index fbf173db264..3f5655fba4c 100644 --- a/apps/function_lib/serializers/function_lib_serializer.py +++ b/apps/function_lib/serializers/function_lib_serializer.py @@ -98,6 +98,7 @@ class Query(serializers.Serializer): is_active = serializers.BooleanField(required=False, error_messages=ErrMessage.char("是否可用")) user_id = serializers.UUIDField(required=True, error_messages=ErrMessage.uuid("用户id")) + select_user_id = serializers.CharField(required=False, allow_null=True, allow_blank=True) def get_query_set(self): query_set = QuerySet(FunctionLib).filter( @@ -108,6 +109,8 @@ def get_query_set(self): query_set = query_set.filter(desc__contains=self.data.get('desc')) if self.data.get('is_active') is not None: query_set = query_set.filter(is_active=self.data.get('is_active')) + if self.data.get('select_user_id') is not None: + query_set = query_set.filter(user_id=self.data.get('select_user_id')) query_set = query_set.order_by("-create_time") return query_set diff --git a/apps/function_lib/views/function_lib_views.py b/apps/function_lib/views/function_lib_views.py index 7589a608b7e..eadc411a480 100644 --- a/apps/function_lib/views/function_lib_views.py +++ b/apps/function_lib/views/function_lib_views.py @@ -105,5 +105,6 @@ def get(self, request: Request, current_page: int, page_size: int): FunctionLibSerializer.Query( data={'name': request.query_params.get('name'), 'desc': request.query_params.get('desc'), - 'user_id': request.user.id}).page( + 'user_id': request.user.id, + 'select_user_id': request.query_params.get('select_user_id')}).page( current_page, page_size)) diff --git a/apps/users/serializers/user_serializers.py b/apps/users/serializers/user_serializers.py index e8d696360a1..600cf86c3f0 100644 --- a/apps/users/serializers/user_serializers.py +++ b/apps/users/serializers/user_serializers.py @@ -17,7 +17,7 @@ from django.core.mail import send_mail from django.core.mail.backends.smtp import EmailBackend from django.db import transaction -from django.db.models import Q, QuerySet +from django.db.models import Q, QuerySet, Prefetch from drf_yasg import openapi from rest_framework import serializers @@ -35,6 +35,7 @@ from common.util.lock import lock from dataset.models import DataSet, Document, Paragraph, Problem, ProblemParagraphMapping from embedding.task import delete_embedding_by_dataset_id_list +from function_lib.models.function import FunctionLib from setting.models import Team, SystemSetting, SettingType, Model, TeamMember, TeamMemberPermission from smartdoc.conf import PROJECT_DIR from users.models.user import User, password_encrypt, get_user_dynamics_permission @@ -495,6 +496,40 @@ def list(self, with_valid=True): return [{'id': user_model.id, 'username': user_model.username, 'email': user_model.email} for user_model in QuerySet(User).filter(Q(username=email_or_username) | Q(email=email_or_username))] + def listByType(self, type, user_id): + teamIds = TeamMember.objects.filter(user_id=user_id).values_list('id', flat=True) + targets = TeamMemberPermission.objects.filter( + member_id__in=teamIds, + auth_target_type=type, + operate__contains=['USE'] + ).values_list('target', flat=True) + prefetch_users = Prefetch('user', queryset=User.objects.only('id', 'username')) + + user_list = [] + if type == 'DATASET': + user_list = DataSet.objects.filter( + Q(id__in=targets) | Q(user_id=user_id) + ).prefetch_related(prefetch_users).distinct('user_id') + elif type == 'APPLICATION': + user_list = Application.objects.filter( + Q(id__in=targets) | Q(user_id=user_id) + ).prefetch_related(prefetch_users).distinct('user_id') + elif type == 'FUNCTION': + user_list = FunctionLib.objects.filter( + Q(permission_type='PUBLIC') | Q(user_id=user_id) + ).prefetch_related(prefetch_users).distinct('user_id') + + other_users = [ + {'id': app.user.id, 'username': app.user.username} + for app in user_list if app.user.id != user_id + ] + users = [ + {'id': 'all', 'username': '全部'}, + {'id': user_id, 'username': '我的'} + ] + users.extend(other_users) + return users + class UserInstanceSerializer(ApiMixin, serializers.ModelSerializer): class Meta: diff --git a/apps/users/urls.py b/apps/users/urls.py index 55388d894c1..b06eb03aabc 100644 --- a/apps/users/urls.py +++ b/apps/users/urls.py @@ -21,4 +21,5 @@ name="user_manage_re_password"), path("user_manage//", views.UserManage.Page.as_view(), name="user_manage_re_password"), + path('user/list/', views.UserListView.as_view()), ] diff --git a/apps/users/views/user.py b/apps/users/views/user.py index e691ff4b989..9dc91f96278 100644 --- a/apps/users/views/user.py +++ b/apps/users/views/user.py @@ -301,3 +301,16 @@ def get(self, request: Request, user_id): def put(self, request: Request, user_id): return result.success( UserManageSerializer.Operate(data={'id': user_id}).edit(request.data, with_valid=True)) + + +class UserListView(APIView): + authentication_classes = [TokenAuth] + + @swagger_auto_schema(operation_summary="通过类型获取用户列表", + operation_id="通过类型获取用户列表", + manual_parameters=UserSerializer.Query.get_request_params_api(), + responses=result.get_api_array_response(UserSerializer.Query.get_response_body_api()), + tags=['用户']) + @has_permissions(PermissionConstants.USER_READ) + def get(self, request: Request, type): + return result.success(UserSerializer().listByType(type, request.user.id)) diff --git a/ui/src/api/application.ts b/ui/src/api/application.ts index ac81e41a5fb..92f9aaae49b 100644 --- a/ui/src/api/application.ts +++ b/ui/src/api/application.ts @@ -456,6 +456,13 @@ const putWorkFlowVersion: ( ) } +const getUserList: (type: string, loading?: Ref) => Promise> = ( + type, + loading +) => { + return get(`/user/list/${type}`, undefined, loading) +} + export default { getAllAppilcation, getApplication, @@ -492,5 +499,6 @@ export default { getWorkFlowVersion, getWorkFlowVersionDetail, putWorkFlowVersion, - playDemoText + playDemoText, + getUserList } diff --git a/ui/src/components/card-box/index.vue b/ui/src/components/card-box/index.vue index ea585791f62..dda9abc1c60 100644 --- a/ui/src/components/card-box/index.vue +++ b/ui/src/components/card-box/index.vue @@ -8,9 +8,19 @@ - - {{ title }} - +
+ + {{ title }} + + + + 创建人: {{ username }} + +
@@ -49,6 +59,7 @@ const props = withDefaults( * 是否展示icon */ showIcon?: boolean + username?: string }>(), { title: '标题', description: '', showIcon: true, border: true } ) @@ -62,13 +73,12 @@ function cardEnter() { } function cardLeave() { - show.value = subHovered.value; + show.value = subHovered.value } function subHoveredEnter() { subHovered.value = true } -