199 lines
9.8 KiB
Python
199 lines
9.8 KiB
Python
# encoding: UTF-8
|
|
import random
|
|
import string
|
|
|
|
from .baseCrudController import BaseCrudController
|
|
from ..model.projectModel import Environment, Project, ProjectMember
|
|
from ..service.projectService import ProjectService
|
|
from ..service.userService import UserService
|
|
from ..dao.rbacDao import RbacDao
|
|
|
|
|
|
class ProjectController(BaseCrudController):
|
|
"""项目、项目成员、环境配置相关接口控制器。"""
|
|
|
|
def project_list(self):
|
|
"""分页查询项目列表。"""
|
|
page_num = self._get(self.req_data, 'pageNo', 'page', default=1)
|
|
page_size = self._get(self.req_data, 'pageSize', 'size', default=20)
|
|
keyword = self._get(self.req_data, 'keyword')
|
|
status = self._get(self.req_data, 'status')
|
|
filter_list = []
|
|
# 关键字先按项目名称模糊匹配。
|
|
if keyword:
|
|
filter_list.append(Project.name.like('%{}%'.format(keyword)))
|
|
# 状态字段是枚举数字,查询时显式转 int。
|
|
if status not in (None, ''):
|
|
filter_list.append(Project.status == int(status))
|
|
items, total = ProjectService.list_by_filters(self.session, Project, filter_list, page_num, page_size,
|
|
Project.created_time)
|
|
product_ids = list({item.product_id for item in items if item.product_id})
|
|
product_map = ProjectService.get_product_map(self.session, product_ids)
|
|
result_list = self.serialize_list(items, ['is_delete'])
|
|
for item in result_list:
|
|
item['product_name'] = product_map.get(item.get('product_id'), '')
|
|
return {'list': result_list, 'total': total}
|
|
|
|
def project_detail(self):
|
|
"""查询项目详情。"""
|
|
project_id = self._get(self.req_data, 'projectId', 'id')
|
|
if not project_id:
|
|
return {}, 'projectId 为必传参数'
|
|
item = ProjectService.get_by_id(self.session, Project, project_id)
|
|
if not item:
|
|
return {}, '未查询到对应项目!'
|
|
return self.serialize(item, ['is_delete']), ''
|
|
|
|
def project_create(self):
|
|
"""创建项目。"""
|
|
name = self._get(self.req_data, 'name')
|
|
if not name:
|
|
return 0, 'name 为必传参数'
|
|
add_info = {
|
|
'key': ''.join(random.choices(string.ascii_letters + string.digits, k=6)),
|
|
'name': name,
|
|
'product_id': self._get(self.req_data, 'productId', 'product_id'),
|
|
'description': self._get(self.req_data, 'description'),
|
|
'department': self._get(self.req_data, 'department'),
|
|
# 默认状态为启用。
|
|
'status': int(self._get(self.req_data, 'status', default=1)),
|
|
'config': self._get(self.req_data, 'config', default={}),
|
|
'created_by': self._get(self.req_data, 'createdBy'),
|
|
'is_delete': 0
|
|
}
|
|
return ProjectService.create(self.session, Project, add_info)
|
|
|
|
def project_update(self):
|
|
"""更新项目。"""
|
|
project_id = self._get(self.req_data, 'projectId', 'id')
|
|
if not project_id:
|
|
return 0, 'projectId 为必传参数'
|
|
update_info = {}
|
|
# 仅更新前端实际传入的字段,避免把未传字段覆盖为空。
|
|
for req_key, column_key in [('key', 'key'), ('name', 'name'), ('productId', 'product_id'),
|
|
('product_id', 'product_id'), ('description', 'description'),
|
|
('department', 'department'), ('status', 'status'), ('config', 'config')]:
|
|
value = self._get(self.req_data, req_key)
|
|
if value is not None:
|
|
update_info[column_key] = value
|
|
return ProjectService.update_by_id(self.session, Project, project_id, update_info)
|
|
|
|
def project_delete(self):
|
|
"""软删除项目。"""
|
|
project_id = self._get(self.req_data, 'projectId', 'id')
|
|
if not project_id:
|
|
return 0, 'projectId 为必传参数'
|
|
return ProjectService.delete_by_id(self.session, Project, project_id)
|
|
|
|
def environment_list(self):
|
|
"""按项目查询环境配置列表。"""
|
|
project_id = self._get(self.req_data, 'projectId', 'project_id')
|
|
if not project_id:
|
|
return {'list': [], 'total': 0}
|
|
items, total = ProjectService.list_by_filters(self.session, Environment,
|
|
[Environment.project_id == int(project_id)],
|
|
self._get(self.req_data, 'pageNo', default=1),
|
|
self._get(self.req_data, 'pageSize', default=20),
|
|
Environment.created_time)
|
|
return {'list': self.serialize_list(items, ['is_delete']), 'total': total}
|
|
|
|
def environment_create(self):
|
|
"""新增环境配置。"""
|
|
project_id = self._get(self.req_data, 'project_id')
|
|
name = self._get(self.req_data, 'name')
|
|
variables = self._get(self.req_data, 'variables')
|
|
if not project_id or not name or variables is None:
|
|
return 0, 'projectId、name、variables 为必传参数'
|
|
return ProjectService.create(self.session, Environment, {
|
|
'project_id': project_id,
|
|
'name': name,
|
|
'variables': variables,
|
|
# 兼容是否加密开关。
|
|
'is_encrypted': bool(self._get(self.req_data, 'isEncrypted', default=False)),
|
|
'is_delete': 0
|
|
})
|
|
|
|
def environment_update(self):
|
|
"""更新环境配置。"""
|
|
env_id = self._get(self.req_data, 'environmentId', 'id')
|
|
if not env_id:
|
|
return 0, 'environmentId 为必传参数'
|
|
update_info = {}
|
|
for req_key, column_key in [('name', 'name'), ('variables', 'variables'), ('isEncrypted', 'is_encrypted')]:
|
|
value = self._get(self.req_data, req_key)
|
|
if value is not None:
|
|
update_info[column_key] = value
|
|
return ProjectService.update_by_id(self.session, Environment, env_id, update_info)
|
|
|
|
def environment_delete(self):
|
|
"""软删除环境配置。"""
|
|
env_id = self._get(self.req_data, 'environmentId', 'id')
|
|
if not env_id:
|
|
return 0, 'environmentId 为必传参数'
|
|
return ProjectService.delete_by_id(self.session, Environment, env_id)
|
|
|
|
def member_list(self):
|
|
"""查询项目成员列表(带用户名、角色名称、项目名称)。"""
|
|
project_id = self._get(self.req_data, 'projectId', 'project_id')
|
|
filters = [ProjectMember.project_id == int(project_id)] if project_id else []
|
|
items, total = ProjectService.list_by_filters(self.session, ProjectMember, filters,
|
|
self._get(self.req_data, 'pageNo', default=1),
|
|
self._get(self.req_data, 'pageSize', default=20),
|
|
ProjectMember.joined_time)
|
|
result_list = self.serialize_list(items)
|
|
if not result_list:
|
|
return {'list': result_list, 'total': total}
|
|
user_ids = [item.get('user_id') for item in result_list]
|
|
project_ids = [item.get('project_id') for item in result_list]
|
|
user_map = UserService.get_user_info_map(self.session, user_ids)
|
|
project_map = ProjectService.get_project_name_map(self.session, project_ids)
|
|
user_role_map = UserService.get_user_roles_map(self.session, user_ids)
|
|
|
|
for item in result_list:
|
|
user_id = item.get('user_id')
|
|
user_info = user_map.get(user_id, {})
|
|
item['real_name'] = user_info.get('real_name', '')
|
|
item['username'] = user_info.get('username', '')
|
|
project_info = project_map.get(item.get('project_id'), {})
|
|
item['project_name'] = project_info.get('name', '')
|
|
|
|
role_info = user_role_map.get(user_id, {})
|
|
role_names = role_info.get('role_names', [])
|
|
item['role_names'] = role_names
|
|
item['role_name'] = ','.join(role_names) if role_names else ''
|
|
return {'list': result_list, 'total': total}
|
|
|
|
def member_create(self):
|
|
"""批量新增项目成员(根据用户系统角色自动映射项目成员角色)。"""
|
|
project_id = self._get(self.req_data, 'project_id')
|
|
user_ids = self._get(self.req_data, 'user_ids')
|
|
if not project_id or not user_ids:
|
|
return 0, 'project_id、user_ids 为必传参数'
|
|
if not isinstance(user_ids, list):
|
|
return 0, 'user_ids 必须为数组'
|
|
if not user_ids:
|
|
return 0, 'user_ids 不能为空'
|
|
user_role_map = UserService.get_user_roles_map(self.session, user_ids)
|
|
role_name_map = RbacDao.get_role_name_map(self.session)
|
|
name_to_project_role = {name: role_id for role_id, name in role_name_map.items()}
|
|
created_ids = []
|
|
for user_id in user_ids:
|
|
role_info = user_role_map.get(user_id, {})
|
|
role_names = role_info.get('role_names', [])
|
|
project_role = 0
|
|
for role_name in role_names:
|
|
if role_name in name_to_project_role:
|
|
project_role = name_to_project_role[role_name]
|
|
break
|
|
if project_role == 0:
|
|
return 0, f'用户 {user_id} 未分配有效角色,无法添加为项目成员'
|
|
create_id, err_msg = ProjectService.create(self.session, ProjectMember, {
|
|
'project_id': project_id,
|
|
'user_id': user_id,
|
|
'role': project_role
|
|
})
|
|
if err_msg:
|
|
return 0, f'用户 {user_id} 添加失败:{err_msg}'
|
|
created_ids.append(create_id)
|
|
return created_ids[0] if len(created_ids) == 1 else created_ids, ''
|