diff --git a/backend/src/main/java/io/metersphere/controller/UserController.java b/backend/src/main/java/io/metersphere/controller/UserController.java index 55324f028e..e6314d2788 100644 --- a/backend/src/main/java/io/metersphere/controller/UserController.java +++ b/backend/src/main/java/io/metersphere/controller/UserController.java @@ -17,15 +17,14 @@ import io.metersphere.controller.request.member.SetAdminRequest; import io.metersphere.controller.request.organization.AddOrgMemberRequest; import io.metersphere.controller.request.organization.QueryOrgMemberRequest; import io.metersphere.dto.UserDTO; +import io.metersphere.dto.UserRoleDTO; import io.metersphere.service.OrganizationService; import io.metersphere.service.UserService; import io.metersphere.service.WorkspaceService; import org.apache.commons.lang3.StringUtils; import org.apache.shiro.authz.annotation.Logical; import org.apache.shiro.authz.annotation.RequiresRoles; -import org.springframework.beans.BeanUtils; import org.springframework.web.bind.annotation.*; - import javax.annotation.Resource; import java.util.List; @@ -54,6 +53,12 @@ public class UserController { return PageUtils.setPageInfo(page, userService.getUserListWithRequest(request)); } + @GetMapping("/special/user/role/{userId}") + @RequiresRoles(RoleConstants.ADMIN) + public UserRoleDTO getUserRole(@PathVariable("userId") String userId) { + return userService.getUserRole(userId); + } + @GetMapping("/special/delete/{userId}") @RequiresRoles(RoleConstants.ADMIN) public void deleteUser(@PathVariable(value = "userId") String userId) { diff --git a/backend/src/main/java/io/metersphere/dto/UserRoleDTO.java b/backend/src/main/java/io/metersphere/dto/UserRoleDTO.java new file mode 100644 index 0000000000..80009d51c3 --- /dev/null +++ b/backend/src/main/java/io/metersphere/dto/UserRoleDTO.java @@ -0,0 +1,18 @@ +package io.metersphere.dto; + +import io.metersphere.base.domain.Role; +import io.metersphere.base.domain.UserRole; +import lombok.Getter; +import lombok.Setter; +import java.util.List; + +@Getter +@Setter +public class UserRoleDTO { + + private String userId; + private List roles; + private List userRoles; + private static final long serialVersionUID = 1L; + +} diff --git a/backend/src/main/java/io/metersphere/excel/domain/TestCaseExcelData.java b/backend/src/main/java/io/metersphere/excel/domain/TestCaseExcelData.java index 04e124c695..7cb794da88 100644 --- a/backend/src/main/java/io/metersphere/excel/domain/TestCaseExcelData.java +++ b/backend/src/main/java/io/metersphere/excel/domain/TestCaseExcelData.java @@ -14,52 +14,52 @@ public class TestCaseExcelData { @NotBlank @Length(max=50) - @ExcelProperty("用例名称") + @ExcelProperty("{test_case_name}") private String name; @NotBlank @Length(max=1000) - @ExcelProperty("所属模块") + @ExcelProperty("{test_case_module}") @ColumnWidth(30) @Pattern(regexp = "^(?!.*//).*$", message = "{incorrect_format}") private String nodePath; @NotBlank - @ExcelProperty("用例类型") + @ExcelProperty("{test_case_type}") @Pattern(regexp = "(^functional$)|(^performance$)|(^api$)", message = "{test_case_type_validate}") private String type; @NotBlank - @ExcelProperty("维护人") + @ExcelProperty("{test_case_maintainer}") private String maintainer; @NotBlank - @ExcelProperty("优先级") + @ExcelProperty("{test_case_priority}") @Pattern(regexp = "(^P0$)|(^P1$)|(^P2$)|(^P3$)", message = "{test_case_priority_validate}") private String priority; @NotBlank - @ExcelProperty("测试方式") + @ExcelProperty("{test_case_method}") @Pattern(regexp = "(^manual$)|(^auto$)", message = "{test_case_method_validate}") private String method; @ColumnWidth(50) - @ExcelProperty("前置条件") + @ExcelProperty("{test_case_prerequisite}") @Length(min=0, max=1000) private String prerequisite; @ColumnWidth(50) - @ExcelProperty("备注") + @ExcelProperty("{test_case_remark}") @Length(max=1000) private String remark; @ColumnWidth(50) - @ExcelProperty("步骤描述") + @ExcelProperty("{test_case_step_desc}") @Length(max=1000) private String stepDesc; @ColumnWidth(50) - @ExcelProperty("预期结果") + @ExcelProperty("{test_case_step_result}") @Length(max=1000) private String stepResult; } diff --git a/backend/src/main/java/io/metersphere/excel/listener/EasyExcelListener.java b/backend/src/main/java/io/metersphere/excel/listener/EasyExcelListener.java index acfd96c6ae..a069d73bcd 100644 --- a/backend/src/main/java/io/metersphere/excel/listener/EasyExcelListener.java +++ b/backend/src/main/java/io/metersphere/excel/listener/EasyExcelListener.java @@ -6,24 +6,22 @@ import com.alibaba.excel.event.AnalysisEventListener; import com.alibaba.excel.exception.ExcelAnalysisException; import com.alibaba.excel.util.StringUtils; import io.metersphere.commons.utils.LogUtil; -import io.metersphere.excel.utils.ExcelValidateHelper; import io.metersphere.excel.domain.ExcelErrData; +import io.metersphere.excel.utils.EasyExcelI18nTranslator; +import io.metersphere.excel.utils.ExcelValidateHelper; import io.metersphere.i18n.Translator; -import org.springframework.stereotype.Component; -import javax.annotation.Resource; -import java.lang.reflect.Field; -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Type; +import java.lang.reflect.*; import java.util.*; -@Component public abstract class EasyExcelListener extends AnalysisEventListener { protected List> errList = new ArrayList<>(); protected List list = new ArrayList<>(); + protected EasyExcelI18nTranslator easyExcelI18nTranslator; + /** * 每隔2000条存储数据库,然后清理list ,方便内存回收 */ @@ -31,16 +29,15 @@ public abstract class EasyExcelListener extends AnalysisEventListener { protected Class clazz; - @Resource - ExcelValidateHelper excelValidateHelper; - public EasyExcelListener(){ Type type = getClass().getGenericSuperclass(); this.clazz = (Class) ((ParameterizedType) type).getActualTypeArguments()[0]; + this.easyExcelI18nTranslator = new EasyExcelI18nTranslator(this.clazz); + this.easyExcelI18nTranslator.translateExcelProperty(); } /** - * 这个每一条数据解析都会来调用 + * 每条数据解析都会调用 * * @param t * @param analysisContext @@ -51,7 +48,7 @@ public abstract class EasyExcelListener extends AnalysisEventListener { Integer rowIndex = analysisContext.readRowHolder().getRowIndex(); try { //根据excel数据实体中的javax.validation + 正则表达式来校验excel数据 - errMsg = excelValidateHelper.validateEntity(t); + errMsg = ExcelValidateHelper.validateEntity(t); //自定义校验规则 errMsg = validate(t, errMsg); } catch (NoSuchFieldException e) { @@ -104,7 +101,6 @@ public abstract class EasyExcelListener extends AnalysisEventListener { */ @Override public void invokeHeadMap(Map headMap, AnalysisContext context) { - super.invokeHeadMap(headMap, context); if (clazz != null){ try { Set fieldNameSet = getFieldNameSet(clazz); @@ -118,6 +114,7 @@ public abstract class EasyExcelListener extends AnalysisEventListener { e.printStackTrace(); } } + super.invokeHeadMap(headMap, context); } /** @@ -142,11 +139,11 @@ public abstract class EasyExcelListener extends AnalysisEventListener { return result; } - - public List> getAndClearErrList() { - List> tmp = this.errList; - this.errList = new ArrayList<>(); - return tmp; + public List> getErrList() { + return errList; } + public void close () { + this.easyExcelI18nTranslator.resetExcelProperty(); + } } \ No newline at end of file diff --git a/backend/src/main/java/io/metersphere/excel/listener/TestCaseDataListener.java b/backend/src/main/java/io/metersphere/excel/listener/TestCaseDataListener.java index 350c9b6fae..09b66b35b5 100644 --- a/backend/src/main/java/io/metersphere/excel/listener/TestCaseDataListener.java +++ b/backend/src/main/java/io/metersphere/excel/listener/TestCaseDataListener.java @@ -2,26 +2,23 @@ package io.metersphere.excel.listener; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; -import io.metersphere.excel.domain.TestCaseExcelData; import io.metersphere.base.domain.TestCaseWithBLOBs; import io.metersphere.commons.constants.TestCaseConstants; import io.metersphere.commons.utils.BeanUtils; +import io.metersphere.excel.domain.TestCaseExcelData; import io.metersphere.i18n.Translator; import io.metersphere.track.service.TestCaseService; import org.apache.commons.lang3.StringUtils; -import org.springframework.stereotype.Component; -import javax.annotation.Resource; import java.util.List; import java.util.Set; import java.util.UUID; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; -@Component + public class TestCaseDataListener extends EasyExcelListener { - @Resource private TestCaseService testCaseService; private String projectId; @@ -30,13 +27,11 @@ public class TestCaseDataListener extends EasyExcelListener { Set userIds; - public TestCaseDataListener() {} - - public TestCaseDataListener init(String projectId, Set testCaseNames, Set userIds) { + public TestCaseDataListener(TestCaseService testCaseService, String projectId, Set testCaseNames, Set userIds) { + this.testCaseService = testCaseService; this.projectId = projectId; this.testCaseNames = testCaseNames; this.userIds = userIds; - return this; } @Override diff --git a/backend/src/main/java/io/metersphere/excel/utils/EasyExcelExporter.java b/backend/src/main/java/io/metersphere/excel/utils/EasyExcelExporter.java new file mode 100644 index 0000000000..c2896048a9 --- /dev/null +++ b/backend/src/main/java/io/metersphere/excel/utils/EasyExcelExporter.java @@ -0,0 +1,52 @@ +package io.metersphere.excel.utils; + +import com.alibaba.excel.EasyExcel; +import com.alibaba.excel.annotation.ExcelProperty; +import io.metersphere.commons.utils.LogUtil; +import io.metersphere.excel.domain.TestCaseExcelData; +import io.metersphere.exception.ExcelException; +import io.metersphere.i18n.Translator; + +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Proxy; +import java.net.URLEncoder; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.regex.Pattern; + +public class EasyExcelExporter { + + EasyExcelI18nTranslator easyExcelI18nTranslator; + + public EasyExcelExporter() { + easyExcelI18nTranslator = new EasyExcelI18nTranslator(TestCaseExcelData.class); + easyExcelI18nTranslator.translateExcelProperty(); + } + + public void export(HttpServletResponse response, Class clazz, List data, String fileName, String sheetName) { + response.setContentType("application/vnd.ms-excel"); + response.setCharacterEncoding("utf-8"); + try { + response.setHeader("Content-disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8") + ".xlsx"); + EasyExcel.write(response.getOutputStream(), clazz).sheet(sheetName).doWrite(data); + } catch (UnsupportedEncodingException e) { + LogUtil.error(e.getMessage(), e); + throw new ExcelException("Utf-8 encoding is not supported"); + } catch (IOException e) { + LogUtil.error(e.getMessage(), e); + throw new ExcelException("IO exception"); + } + + } + + public void close() { + easyExcelI18nTranslator.resetExcelProperty(); + } + +} diff --git a/backend/src/main/java/io/metersphere/excel/utils/EasyExcelI18nTranslator.java b/backend/src/main/java/io/metersphere/excel/utils/EasyExcelI18nTranslator.java new file mode 100644 index 0000000000..4024d43dca --- /dev/null +++ b/backend/src/main/java/io/metersphere/excel/utils/EasyExcelI18nTranslator.java @@ -0,0 +1,98 @@ +package io.metersphere.excel.utils; + +import com.alibaba.excel.annotation.ExcelProperty; +import io.metersphere.commons.utils.LogUtil; +import io.metersphere.excel.domain.TestCaseExcelData; +import io.metersphere.exception.ExcelException; +import io.metersphere.i18n.Translator; + +import java.lang.reflect.Field; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Proxy; +import java.util.*; +import java.util.function.BiConsumer; +import java.util.regex.Pattern; + +/** + * 表头国际化 + * 先调用 saveOriginalExcelProperty 存储原表头注解值 + * 再调用 translateExcelProperty 获取国际化的值 + * 最后调用 resetExcelProperty 重置为原来值,防止切换语言后无法国际化 + */ +public class EasyExcelI18nTranslator { + + private Map> excelPropertyMap = new HashMap<>(); + + private Class clazz; + + public EasyExcelI18nTranslator(Class clazz) { + this.clazz = clazz; + saveOriginalExcelProperty(); + } + + private void readExcelProperty(Class clazz, BiConsumer> operate) { + Field field; + Field[] fields = clazz.getDeclaredFields(); + for (int i = 0; i < fields.length ; i++) { + try { + field = clazz.getDeclaredField(fields[i].getName()); + field.setAccessible(true); + ExcelProperty excelProperty = field.getAnnotation(ExcelProperty.class); + if(excelProperty != null){ + InvocationHandler invocationHandler = Proxy.getInvocationHandler(excelProperty); + Field fieldValue = invocationHandler.getClass().getDeclaredField("memberValues"); + fieldValue.setAccessible(true); + Map memberValues = null; + try { + memberValues = (Map) fieldValue.get(invocationHandler); + } catch (IllegalAccessException e) { + LogUtil.error(e.getMessage(), e); + throw new ExcelException(e.getMessage()); + } + + operate.accept(field.getName(), memberValues); + + } + } catch (NoSuchFieldException e) { + e.printStackTrace(); + throw new RuntimeException(e.getMessage(), e); + } + } + + + } + + public void saveOriginalExcelProperty() { + readExcelProperty(clazz, (fieldName, memberValues) -> { + List values = Arrays.asList((String [])memberValues.get("value")); + List copyValues = new ArrayList<>(); + values.forEach(value -> { + copyValues.add(value); + }); + excelPropertyMap.put(fieldName, copyValues); + }); + } + + public void translateExcelProperty() { + readExcelProperty(TestCaseExcelData.class, (fieldName, memberValues) -> { + String [] values = (String[]) memberValues.get("value"); + for (int j = 0; j < values.length; j++) { + if (Pattern.matches("^\\{.+\\}$", values[j])) { + values[j] = Translator.get(values[j].substring(1, values[j].length() - 1)); + } + } + memberValues.put("value", values); + }); + } + + public void resetExcelProperty() { + readExcelProperty(clazz, (fieldName, memberValues) -> { + String [] values = (String[]) memberValues.get("value"); + List list = excelPropertyMap.get(fieldName); + for (int j = 0; j < values.length; j++) { + values[j] = list.get(j); + } + memberValues.put("value", values); + }); + } +} diff --git a/backend/src/main/java/io/metersphere/excel/utils/EasyExcelUtil.java b/backend/src/main/java/io/metersphere/excel/utils/EasyExcelUtil.java deleted file mode 100644 index a759e03d54..0000000000 --- a/backend/src/main/java/io/metersphere/excel/utils/EasyExcelUtil.java +++ /dev/null @@ -1,30 +0,0 @@ -package io.metersphere.excel.utils; - -import com.alibaba.excel.EasyExcel; -import io.metersphere.commons.utils.LogUtil; -import io.metersphere.exception.ExcelException; - -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.net.URLEncoder; -import java.util.List; - -public class EasyExcelUtil { - - public static void export(HttpServletResponse response, Class clazz, List data, String fileName, String sheetName) { - response.setContentType("application/vnd.ms-excel"); - response.setCharacterEncoding("utf-8"); - try { - response.setHeader("Content-disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8") + ".xlsx"); - EasyExcel.write(response.getOutputStream(), clazz).sheet(sheetName).doWrite(data); - } catch (UnsupportedEncodingException e) { - LogUtil.error(e.getMessage(), e); - throw new ExcelException("不支持UTF-8编码"); - } catch (IOException e) { - LogUtil.error(e.getMessage(), e); - throw new ExcelException("IO异常"); - } - - } -} diff --git a/backend/src/main/java/io/metersphere/excel/utils/ExcelValidateHelper.java b/backend/src/main/java/io/metersphere/excel/utils/ExcelValidateHelper.java index 6bacd4a925..90572163b8 100644 --- a/backend/src/main/java/io/metersphere/excel/utils/ExcelValidateHelper.java +++ b/backend/src/main/java/io/metersphere/excel/utils/ExcelValidateHelper.java @@ -4,6 +4,7 @@ import com.alibaba.excel.annotation.ExcelProperty; import org.springframework.stereotype.Component; import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean; +import javax.annotation.PostConstruct; import javax.annotation.Resource; import javax.validation.ConstraintViolation; import javax.validation.groups.Default; @@ -13,14 +14,14 @@ import java.util.Set; @Component public class ExcelValidateHelper { - private ExcelValidateHelper(){} + private static ExcelValidateHelper excelValidateHelper; @Resource LocalValidatorFactoryBean localValidatorFactoryBean; - public String validateEntity(T obj) throws NoSuchFieldException { + public static String validateEntity(T obj) throws NoSuchFieldException { StringBuilder result = new StringBuilder(); - Set> set = localValidatorFactoryBean.getValidator().validate(obj, Default.class); + Set> set = excelValidateHelper.localValidatorFactoryBean.getValidator().validate(obj, Default.class); if (set != null && !set.isEmpty()) { for (ConstraintViolation cv : set) { Field declaredField = obj.getClass().getDeclaredField(cv.getPropertyPath().toString()); @@ -31,4 +32,10 @@ public class ExcelValidateHelper { } return result.toString(); } + + @PostConstruct + public void initialize() { + excelValidateHelper = this; + excelValidateHelper.localValidatorFactoryBean = this.localValidatorFactoryBean; + } } \ No newline at end of file diff --git a/backend/src/main/java/io/metersphere/service/UserService.java b/backend/src/main/java/io/metersphere/service/UserService.java index 7ee198862b..f0c9a24416 100644 --- a/backend/src/main/java/io/metersphere/service/UserService.java +++ b/backend/src/main/java/io/metersphere/service/UserService.java @@ -17,13 +17,13 @@ import io.metersphere.controller.request.member.SetAdminRequest; import io.metersphere.controller.request.organization.AddOrgMemberRequest; import io.metersphere.controller.request.organization.QueryOrgMemberRequest; import io.metersphere.dto.UserDTO; +import io.metersphere.dto.UserRoleDTO; import io.metersphere.i18n.Translator; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.BeanUtils; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.CollectionUtils; - import javax.annotation.Resource; import java.util.List; import java.util.UUID; @@ -100,16 +100,24 @@ public class UserService { } UserDTO userDTO = new UserDTO(); BeanUtils.copyProperties(user, userDTO); + UserRoleDTO userRole = getUserRole(userId); + userDTO.setUserRoles(userRole.getUserRoles()); + userDTO.setRoles(userRole.getRoles()); + return userDTO; + } + + public UserRoleDTO getUserRole(String userId) { + UserRoleDTO userRoleDTO = new UserRoleDTO(); // UserRoleExample userRoleExample = new UserRoleExample(); userRoleExample.createCriteria().andUserIdEqualTo(userId); List userRoleList = userRoleMapper.selectByExample(userRoleExample); if (CollectionUtils.isEmpty(userRoleList)) { - return userDTO; + return userRoleDTO; } // 设置 user_role - userDTO.setUserRoles(userRoleList); + userRoleDTO.setUserRoles(userRoleList); List roleIds = userRoleList.stream().map(UserRole::getRoleId).collect(Collectors.toList()); @@ -117,9 +125,9 @@ public class UserService { roleExample.createCriteria().andIdIn(roleIds); List roleList = roleMapper.selectByExample(roleExample); - userDTO.setRoles(roleList); + userRoleDTO.setRoles(roleList); - return userDTO; + return userRoleDTO; } public List getUserList() { diff --git a/backend/src/main/java/io/metersphere/track/controller/TestCaseController.java b/backend/src/main/java/io/metersphere/track/controller/TestCaseController.java index f7d4854159..d4ff8a7918 100644 --- a/backend/src/main/java/io/metersphere/track/controller/TestCaseController.java +++ b/backend/src/main/java/io/metersphere/track/controller/TestCaseController.java @@ -77,7 +77,7 @@ public class TestCaseController { } @PostMapping("/import/{projectId}") - public ExcelResponse testCaseImport(MultipartFile file, @PathVariable String projectId){ + public ExcelResponse testCaseImport(MultipartFile file, @PathVariable String projectId) throws NoSuchFieldException { return testCaseService.testCaseImport(file, projectId); } diff --git a/backend/src/main/java/io/metersphere/track/service/TestCaseService.java b/backend/src/main/java/io/metersphere/track/service/TestCaseService.java index a509c1441a..f71b47396c 100644 --- a/backend/src/main/java/io/metersphere/track/service/TestCaseService.java +++ b/backend/src/main/java/io/metersphere/track/service/TestCaseService.java @@ -9,14 +9,13 @@ import io.metersphere.base.mapper.ext.ExtTestCaseMapper; import io.metersphere.commons.exception.MSException; import io.metersphere.commons.user.SessionUser; import io.metersphere.commons.utils.BeanUtils; -import io.metersphere.commons.utils.LogUtil; import io.metersphere.commons.utils.SessionUtils; import io.metersphere.excel.domain.ExcelErrData; import io.metersphere.excel.domain.ExcelResponse; import io.metersphere.excel.domain.TestCaseExcelData; import io.metersphere.excel.listener.EasyExcelListener; import io.metersphere.excel.listener.TestCaseDataListener; -import io.metersphere.excel.utils.EasyExcelUtil; +import io.metersphere.excel.utils.EasyExcelExporter; import io.metersphere.i18n.Translator; import io.metersphere.track.dto.TestCaseDTO; import io.metersphere.track.request.testcase.QueryTestCaseRequest; @@ -31,7 +30,6 @@ import org.springframework.web.multipart.MultipartFile; import javax.annotation.Resource; import javax.servlet.http.HttpServletResponse; -import java.io.IOException; import java.util.*; import java.util.stream.Collectors; @@ -60,9 +58,6 @@ public class TestCaseService { @Resource TestCaseNodeService testCaseNodeService; - @Resource - TestCaseDataListener testCaseDataListener; - @Resource UserMapper userMapper; @@ -173,42 +168,40 @@ public class TestCaseService { public ExcelResponse testCaseImport(MultipartFile file, String projectId) { + ExcelResponse excelResponse = new ExcelResponse(); + + String currentWorkspaceId = SessionUtils.getCurrentWorkspaceId(); + QueryTestCaseRequest queryTestCaseRequest = new QueryTestCaseRequest(); + queryTestCaseRequest.setProjectId(projectId); + List testCases = extTestCaseMapper.getTestCaseNames(queryTestCaseRequest); + Set testCaseNames = testCases.stream() + .map(TestCase::getName) + .collect(Collectors.toSet()); + + UserExample userExample = new UserExample(); + userExample.createCriteria().andLastWorkspaceIdEqualTo(currentWorkspaceId); + List users = userMapper.selectByExample(userExample); + Set userIds = users.stream().map(User::getId).collect(Collectors.toSet()); + + EasyExcelListener easyExcelListener = null; + List> errList = null; try { - - ExcelResponse excelResponse = new ExcelResponse(); - - String currentWorkspaceId = SessionUtils.getCurrentWorkspaceId(); - QueryTestCaseRequest queryTestCaseRequest = new QueryTestCaseRequest(); - queryTestCaseRequest.setProjectId(projectId); - List testCases = extTestCaseMapper.getTestCaseNames(queryTestCaseRequest); - Set testCaseNames = testCases.stream() - .map(TestCase::getName) - .collect(Collectors.toSet()); - - UserExample userExample = new UserExample(); - userExample.createCriteria().andLastWorkspaceIdEqualTo(currentWorkspaceId); - List users = userMapper.selectByExample(userExample); - Set userIds = users.stream().map(User::getId).collect(Collectors.toSet()); - - EasyExcelFactory.read(file.getInputStream(), TestCaseExcelData.class, - testCaseDataListener.init(projectId, testCaseNames, userIds)).sheet().doRead(); - - List> errList = testCaseDataListener.getAndClearErrList(); - //如果包含错误信息就导出错误信息 - if (!errList.isEmpty()) { - excelResponse.setSuccess(false); - excelResponse.setErrList(errList); - } else { - excelResponse.setSuccess(true); - } - return excelResponse; - - } catch (IOException e) { - LogUtil.error(e.getMessage(), e); - e.printStackTrace(); + easyExcelListener = new TestCaseDataListener(this, projectId, testCaseNames, userIds); + EasyExcelFactory.read(file.getInputStream(), TestCaseExcelData.class, easyExcelListener).sheet().doRead(); + errList = easyExcelListener.getErrList(); + } catch (Exception e) { + MSException.throwException(e.getMessage()); + } finally { + easyExcelListener.close(); } - - return null; + //如果包含错误信息就导出错误信息 + if (!errList.isEmpty()) { + excelResponse.setSuccess(false); + excelResponse.setErrList(errList); + } else { + excelResponse.setSuccess(true); + } + return excelResponse; } public void saveImportData(List testCases, String projectId) { @@ -226,8 +219,16 @@ public class TestCaseService { } public void testCaseTemplateExport(HttpServletResponse response) { - EasyExcelUtil.export(response, TestCaseExcelData.class, generateExportTemplate(), - Translator.get("test_case_import_template_name"), Translator.get("test_case_import_template_sheet")); + EasyExcelExporter easyExcelExporter = null; + try { + easyExcelExporter = new EasyExcelExporter(); + easyExcelExporter.export(response, TestCaseExcelData.class, generateExportTemplate(), + Translator.get("test_case_import_template_name"), Translator.get("test_case_import_template_sheet")); + } catch (Exception e) { + MSException.throwException(e); + } finally { + easyExcelExporter.close(); + } } private List generateExportTemplate() { @@ -238,28 +239,29 @@ public class TestCaseService { SessionUser user = SessionUtils.getUser(); for (int i = 1; i <= 5; i++) { TestCaseExcelData data = new TestCaseExcelData(); - data.setName("测试用例" + i); - path.append("/" + "模块" + i); + data.setName(Translator.get("test_case") + i); + path.append("/" + Translator.get("module") + i); data.setNodePath(path.toString()); data.setPriority("P" + i%4); data.setType(types.get(i%3)); data.setMethod(methods.get(i%2)); - data.setPrerequisite("前置条件选填"); - data.setStepDesc("1. 每个步骤以换行分隔\n2. 步骤前可标序号\n3. 测试步骤和结果选填"); - data.setStepResult("1. 每条结果以换行分隔\n2. 结果前可标序号\n3. 测试步骤和结果选填"); + data.setPrerequisite(Translator.get("preconditions_optional")); + data.setStepDesc("1. " + Translator.get("step_tip_separate") + + "\n2. " + Translator.get("step_tip_order") + "\n3. " + Translator.get("step_tip_optional")); + data.setStepResult("1. " + Translator.get("step_tip_order") + "\n2. " + Translator.get("result_tip_order") + "\n3. " + Translator.get("result_tip_optional")); data.setMaintainer(user.getId()); - data.setRemark("备注选填"); + data.setRemark(Translator.get("remark_optional")); list.add(data); } list.add(new TestCaseExcelData()); TestCaseExcelData explain = new TestCaseExcelData(); - explain.setName("同一项目下测试用例名称不能重复!"); - explain.setNodePath("模块名称请按照'/模块1/模块2'的格式书写; 错误格式示例:('/', '/tes//test'); 若无该模块,则自动创建模块"); - explain.setType("用例类型必须为:functional、performance、api"); - explain.setMethod("测试方式必须为:manual、auto"); - explain.setPriority("优先级必须为:P0、P1、P2、P3"); - explain.setMaintainer("维护人必须为该工作空间相关人员"); + explain.setName(Translator.get("do_not_modify_header_order")); + explain.setNodePath(Translator.get("module_created_automatically")); + explain.setType(Translator.get("options") + "(functional、performance、api)"); + explain.setMethod(Translator.get("options") + "(manual、auto)"); + explain.setPriority(Translator.get("options") + "(P0、P1、P2、P3)"); + explain.setMaintainer(Translator.get("please_input_workspace_member")); list.add(explain); return list; diff --git a/backend/src/main/resources/i18n/messages.properties b/backend/src/main/resources/i18n/messages.properties index 195a2618d7..a540e76319 100644 --- a/backend/src/main/resources/i18n/messages.properties +++ b/backend/src/main/resources/i18n/messages.properties @@ -17,4 +17,28 @@ error= incorrect_format= test_case_type_validate= test_case_priority_validate= -test_case_method_validate= \ No newline at end of file +test_case_method_validate= +test_case_name= +test_case_module= +test_case_type= +test_case_maintainer= +test_case_priority= +test_case_method= +test_case_prerequisite= +test_case_remark= +test_case_step_desc= +test_case_step_result= +test_case= +module= +preconditions_optional= +step_tip_separate= +step_tip_order= +step_tip_optional= +result_tip_separate= +result_tip_order= +result_tip_optional= +remark_optional= +do_not_modify_header_order= +module_created_automatically= +options= +please_input_workspace_member= \ No newline at end of file diff --git a/backend/src/main/resources/i18n/messages_en_US.properties b/backend/src/main/resources/i18n/messages_en_US.properties index 05b5d6ab6c..24542ca605 100644 --- a/backend/src/main/resources/i18n/messages_en_US.properties +++ b/backend/src/main/resources/i18n/messages_en_US.properties @@ -58,4 +58,27 @@ before_delete_plan=There is an associated test case under this plan, please unli incorrect_format=Incorrect format test_case_type_validate=must be functional, performance, api test_case_priority_validate=must be P0, P1, P2, P3 -test_case_method_validate=\ must be manual, auto \ No newline at end of file +test_case_method_validate=\ must be manual, auto +test_case_name=Name +test_case_type=Type +test_case_priority=Priority +test_case_method=method +test_case_prerequisite=Prerequisite +test_case_remark=Remark +test_case_step_desc=Step description +test_case_step_result=Step result +test_case_module=module +test_case=Test case +module=Module +preconditions_optional=Preconditions optional +step_tip_separate=Each step is separated by a new line +step_tip_order=The serial number can be marked before the step +step_tip_optional=Test steps and results optional +result_tip_separate=Each result is separated by a new line +result_tip_order=The sequence number can be marked before the result +result_tip_optional=Test steps and results optional +remark_optional=Remark optional +do_not_modify_header_order=Do not modify the header order +module_created_automatically=If there is no such module, will be created automatically +options=options +please_input_workspace_member=Please input workspace merber \ No newline at end of file diff --git a/backend/src/main/resources/i18n/messages_zh_CN.properties b/backend/src/main/resources/i18n/messages_zh_CN.properties index 59b42f9db3..bc73da3bb2 100644 --- a/backend/src/main/resources/i18n/messages_zh_CN.properties +++ b/backend/src/main/resources/i18n/messages_zh_CN.properties @@ -51,11 +51,35 @@ parse_data_error=解析数据出错 missing_header_information=缺少头部信息 number=第 row=行 -incorrect_format=格式不正确 +incorrect_format=所属模块 test_case_type_validate=必须为functional、performance、api test_case_priority_validate=必须为P0、P1、P2、P3 test_case_method_validate=必须为manual、auto error=出错 +test_case_name=用例名称 +test_case_type=用例类型 +test_case_maintainer=维护人 +test_case_priority=优先级 +test_case_method=测试方式 +test_case_prerequisite=前置条件 +test_case_remark=备注 +test_case_step_desc=步骤描述 +test_case_step_result=预期结果 +test_case_module=所属模块 +test_case=测试用例 +module=模块 +preconditions_optional=前置条件选填 +step_tip_separate=每个步骤以换行分隔 +step_tip_order=步骤前可标序号 +step_tip_optional=步骤前可标序号 +result_tip_separate=每条结果以换行分隔 +result_tip_order=结果前可标序号 +result_tip_optional=测试步骤和结果选填 +remark_optional=备注选填 +do_not_modify_header_order=请勿修改表头顺序 +module_created_automatically=若无该模块将自动创建 +options=选项 +please_input_workspace_member=请填写该工作空间相关人员 test_case_exist=该项目下已存在用例: node_deep_limit=节点深度不超过5层! before_delete_plan=该计划下存在关联测试用例,请先取消关联! diff --git a/backend/src/main/resources/i18n/messages_zh_TW.properties b/backend/src/main/resources/i18n/messages_zh_TW.properties index 90d693dd84..2923b6c2eb 100644 --- a/backend/src/main/resources/i18n/messages_zh_TW.properties +++ b/backend/src/main/resources/i18n/messages_zh_TW.properties @@ -51,11 +51,35 @@ parse_data_error=解析數據出錯 missing_header_information=缺少頭部信息 number=第 row=行 -incorrect_format=格式不正確 +incorrect_format=所屬模塊 test_case_type_validate=必須為functional、performance、api test_case_priority_validate=必須為P0、P1、P2、P3 test_case_method_validate=必須為manual、auto -error=出错 +error=出錯 +test_case_name=用例名稱 +test_case_type=用例類型 +test_case_maintainer=維護人 +test_case_priority=優先級 +test_case_method=測試方式 +test_case_prerequisite=前置條件 +test_case_remark=備註 +test_case_step_desc=步驟描述 +test_case_step_result=預期結果 +test_case_module=所屬模塊 +test_case=測試用例 +module=模塊 +preconditions_optional=前置條件選填 +step_tip_separate=每個步驟以換行分隔 +step_tip_order=步驟前可標序號 +step_tip_optional=步驟前可標序號 +result_tip_separate=每條結果以換行分隔 +result_tip_order=結果前可標序號 +result_tip_optional=測試步驟和結果選填 +remark_optional=備註選填 +do_not_modify_header_order=請勿修改表頭順序 +module_created_automatically=若無該模塊將自動創建 +options=選項 +please_input_workspace_member=請填寫該工作空間相關人員 test_case_exist=該項目下已存在用例: node_deep_limit=節點深度不超過5層! before_delete_plan=該計劃下存在關聯測試用例,請先取消關聯! diff --git a/frontend/src/business/components/settings/system/User.vue b/frontend/src/business/components/settings/system/User.vue index 9a17e92e10..ef1a8becf2 100644 --- a/frontend/src/business/components/settings/system/User.vue +++ b/frontend/src/business/components/settings/system/User.vue @@ -1,7 +1,7 @@