diff --git a/backend/services/bug-management/src/main/java/io/metersphere/bug/service/BugService.java b/backend/services/bug-management/src/main/java/io/metersphere/bug/service/BugService.java index ded8f88b72..2f8420b859 100644 --- a/backend/services/bug-management/src/main/java/io/metersphere/bug/service/BugService.java +++ b/backend/services/bug-management/src/main/java/io/metersphere/bug/service/BugService.java @@ -756,6 +756,9 @@ public class BugService { }).toList(); statusField.setOptions(statusCustomOption); statusField.setRequired(true); + if (CollectionUtils.isEmpty(templateDTO.getCustomFields())) { + templateDTO.setCustomFields(new ArrayList<>()); + } templateDTO.getCustomFields().addFirst(statusField); return templateDTO; } @@ -1570,7 +1573,7 @@ public class BugService { }); // 第三方平台模板 TemplateDTO pluginDefaultTemplate = getPluginBugDefaultTemplate(projectId, true); - if (pluginDefaultTemplate != null) { + if (pluginDefaultTemplate != null && CollectionUtils.isNotEmpty(pluginDefaultTemplate.getCustomFields())) { headerCustomFields.addAll(pluginDefaultTemplate.getCustomFields()); } return headerCustomFields; diff --git a/backend/services/project-management/src/main/java/io/metersphere/project/controller/CustomFunctionController.java b/backend/services/project-management/src/main/java/io/metersphere/project/controller/CustomFunctionController.java index c6bd1d09ff..6da58ed575 100644 --- a/backend/services/project-management/src/main/java/io/metersphere/project/controller/CustomFunctionController.java +++ b/backend/services/project-management/src/main/java/io/metersphere/project/controller/CustomFunctionController.java @@ -1,6 +1,7 @@ package io.metersphere.project.controller; import com.github.pagehelper.Page; +import com.github.pagehelper.PageHelper; import com.github.pagehelper.page.PageMethod; import io.metersphere.project.domain.CustomFunction; import io.metersphere.project.dto.customfunction.CustomFuncColumnsOptionDTO; @@ -11,6 +12,8 @@ import io.metersphere.project.dto.customfunction.request.CustomFunctionUpdateReq import io.metersphere.project.service.CustomFunctionLogService; import io.metersphere.project.service.CustomFunctionService; import io.metersphere.sdk.constants.PermissionConstants; +import io.metersphere.system.dto.OperationHistoryDTO; +import io.metersphere.system.dto.request.OperationHistoryRequest; import io.metersphere.system.log.annotation.Log; import io.metersphere.system.log.constants.OperationLogType; import io.metersphere.system.security.CheckOwner; @@ -93,11 +96,21 @@ public class CustomFunctionController { } @GetMapping("/delete/{id}") - @Operation(summary = "项目管理-公共脚本-脚本删除") + @Operation(summary = "项目管理-脚本删除") @RequiresPermissions(PermissionConstants.PROJECT_CUSTOM_FUNCTION_DELETE) @Log(type = OperationLogType.DELETE, expression = "#msClass.delLog(#id)", msClass = CustomFunctionLogService.class) @CheckOwner(resourceId = "#id", resourceType = "custom_function") public void delete(@PathVariable String id) { customFunctionService.delete(id); } + + @PostMapping("/history/page") + @Operation(summary = "项目管理-公共脚本-变更历史-列表") + @RequiresPermissions(PermissionConstants.PROJECT_CUSTOM_FUNCTION_READ) + @CheckOwner(resourceId = "#request.getProjectId()", resourceType = "project") + public Pager> page(@Validated @RequestBody OperationHistoryRequest request) { + Page page = PageHelper.startPage(request.getCurrent(), request.getPageSize(), + StringUtils.isNotBlank(request.getSortString()) ? request.getSortString() : "id desc"); + return PageUtils.setPageInfo(page, customFunctionService.list(request)); + } } diff --git a/backend/services/project-management/src/main/java/io/metersphere/project/service/CustomFunctionService.java b/backend/services/project-management/src/main/java/io/metersphere/project/service/CustomFunctionService.java index 7e2fecb856..2ac5f16cbe 100644 --- a/backend/services/project-management/src/main/java/io/metersphere/project/service/CustomFunctionService.java +++ b/backend/services/project-management/src/main/java/io/metersphere/project/service/CustomFunctionService.java @@ -19,16 +19,30 @@ import io.metersphere.project.mapper.ExtCustomFunctionMapper; import io.metersphere.project.request.ProjectMemberRequest; import io.metersphere.sdk.exception.MSException; import io.metersphere.sdk.util.BeanUtils; +import io.metersphere.sdk.util.Translator; +import io.metersphere.system.domain.OperationHistory; +import io.metersphere.system.domain.OperationHistoryExample; +import io.metersphere.system.domain.User; +import io.metersphere.system.domain.UserExample; +import io.metersphere.system.dto.OperationHistoryDTO; +import io.metersphere.system.dto.request.OperationHistoryRequest; +import io.metersphere.system.log.constants.OperationLogModule; +import io.metersphere.system.log.constants.OperationLogType; +import io.metersphere.system.mapper.OperationHistoryMapper; +import io.metersphere.system.mapper.UserMapper; import io.metersphere.system.uid.IDGenerator; import io.metersphere.system.utils.ServiceUtils; import jakarta.annotation.Resource; import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.nio.charset.StandardCharsets; import java.util.List; +import java.util.Map; import java.util.Optional; +import java.util.stream.Collectors; /** * @author: LAN @@ -51,6 +65,12 @@ public class CustomFunctionService { @Resource ExtCustomFunctionMapper extCustomFunctionMapper; + @Resource + UserMapper userMapper; + + @Resource + OperationHistoryMapper operationHistoryMapper; + public List getPage(CustomFunctionPageRequest request) { List list = extCustomFunctionMapper.list(request); if (!CollectionUtils.isEmpty(list)) { @@ -147,6 +167,39 @@ public class CustomFunctionService { customFunctionBlobMapper.deleteByPrimaryKey(id); } + /** + * 公共脚本变更历史分页列表 + * @param request 请求参数 + * @return 变更历史集合 + */ + public List list(OperationHistoryRequest request) { + OperationHistoryExample example = new OperationHistoryExample(); + example.createCriteria().andProjectIdEqualTo(request.getProjectId()).andModuleIn(List.of(OperationLogModule.PROJECT_CUSTOM_FUNCTION)) + .andSourceIdEqualTo(request.getSourceId()); + List history = operationHistoryMapper.selectByExample(example); + if (org.apache.commons.collections4.CollectionUtils.isEmpty(history)) { + return List.of(); + } + List userIds = history.stream().map(OperationHistory::getCreateUser).toList(); + UserExample userExample = new UserExample(); + userExample.createCriteria().andIdIn(userIds); + List users = userMapper.selectByExample(userExample); + Map userMap = users.stream().collect(Collectors.toMap(User::getId, User::getName)); + return history.stream().map(h -> { + OperationHistoryDTO dto = new OperationHistoryDTO(); + BeanUtils.copyBean(dto, h); + dto.setCreateUserName(userMap.get(h.getCreateUser()) == null ? h.getCreateUser() : userMap.get(h.getCreateUser())); + if (StringUtils.equals(dto.getType(), OperationLogType.ADD.name())) { + dto.setType(Translator.get("add")); + } else if (StringUtils.equals(dto.getType(), OperationLogType.UPDATE.name())) { + dto.setType(Translator.get("update")); + } else if (StringUtils.equals(dto.getType(), OperationLogType.DELETE.name())) { + dto.setType(Translator.get("delete")); + } + return dto; + }).toList(); + } + private CustomFunction checkCustomFunction(String id) { return ServiceUtils.checkResourceExist(customFunctionMapper.selectByPrimaryKey(id), "resource_not_exist"); } diff --git a/frontend/src/views/project-management/projectAndPermission/member/index.vue b/frontend/src/views/project-management/projectAndPermission/member/index.vue index 89eb6aaefc..af62092130 100644 --- a/frontend/src/views/project-management/projectAndPermission/member/index.vue +++ b/frontend/src/views/project-management/projectAndPermission/member/index.vue @@ -397,6 +397,8 @@ onBeforeMount(() => { initData(); }); + + await tableStore.initColumn(TableKeyEnum.PROJECT_MEMBER, columns, 'drawer');