feat(测试跟踪): 附件功能改造

--story=1006991 --user=宋昌昌 【测试跟踪】功能用例&缺陷增加附件功能支持视频文件(1.20分支同步上) https://www.tapd.cn/55049933/s/1202348
This commit is contained in:
song-cc-rock 2022-07-14 18:34:33 +08:00 committed by jianxing
parent ad35f8d2b5
commit c25795e462
23 changed files with 423 additions and 369 deletions

View File

@ -126,7 +126,7 @@ public class FileService {
final FileAttachmentMetadata fileAttachmentMetadata = new FileAttachmentMetadata(); final FileAttachmentMetadata fileAttachmentMetadata = new FileAttachmentMetadata();
fileAttachmentMetadata.setId(UUID.randomUUID().toString()); fileAttachmentMetadata.setId(UUID.randomUUID().toString());
fileAttachmentMetadata.setName(file.getOriginalFilename()); fileAttachmentMetadata.setName(file.getOriginalFilename());
fileAttachmentMetadata.setType(getFileType(fileAttachmentMetadata.getName()).name()); fileAttachmentMetadata.setType(getFileTypeWithoutEnum(fileAttachmentMetadata.getName()));
fileAttachmentMetadata.setSize(file.getSize()); fileAttachmentMetadata.setSize(file.getSize());
fileAttachmentMetadata.setCreateTime(System.currentTimeMillis()); fileAttachmentMetadata.setCreateTime(System.currentTimeMillis());
fileAttachmentMetadata.setUpdateTime(System.currentTimeMillis()); fileAttachmentMetadata.setUpdateTime(System.currentTimeMillis());
@ -154,7 +154,7 @@ public class FileService {
final FileAttachmentMetadata fileAttachmentMetadata = new FileAttachmentMetadata(); final FileAttachmentMetadata fileAttachmentMetadata = new FileAttachmentMetadata();
fileAttachmentMetadata.setId(UUID.randomUUID().toString()); fileAttachmentMetadata.setId(UUID.randomUUID().toString());
fileAttachmentMetadata.setName(attachmentName); fileAttachmentMetadata.setName(attachmentName);
fileAttachmentMetadata.setType(getFileType(attachmentName).name()); fileAttachmentMetadata.setType(getFileTypeWithoutEnum(attachmentName));
fileAttachmentMetadata.setSize(Integer.valueOf(bytes.length).longValue()); fileAttachmentMetadata.setSize(Integer.valueOf(bytes.length).longValue());
fileAttachmentMetadata.setCreateTime(System.currentTimeMillis()); fileAttachmentMetadata.setCreateTime(System.currentTimeMillis());
fileAttachmentMetadata.setUpdateTime(System.currentTimeMillis()); fileAttachmentMetadata.setUpdateTime(System.currentTimeMillis());
@ -332,6 +332,15 @@ public class FileService {
return FileType.valueOf(type.toUpperCase()); return FileType.valueOf(type.toUpperCase());
} }
private String getFileTypeWithoutEnum(String filename) {
if (StringUtils.isEmpty(filename)) {
return "";
}
int s = filename.lastIndexOf(".") + 1;
String type = filename.substring(s);
return type.toUpperCase();
}
public List<FileMetadata> getFileMetadataByCaseId(String caseId) { public List<FileMetadata> getFileMetadataByCaseId(String caseId) {
TestCaseFileExample testCaseFileExample = new TestCaseFileExample(); TestCaseFileExample testCaseFileExample = new TestCaseFileExample();
testCaseFileExample.createCriteria().andCaseIdEqualTo(caseId); testCaseFileExample.createCriteria().andCaseIdEqualTo(caseId);
@ -377,7 +386,9 @@ public class FileService {
return fileAttachmentMetadataMapper.selectByExample(example); return fileAttachmentMetadataMapper.selectByExample(example);
} }
public FileAttachmentMetadata getFileAttachmentMetadataByFileId(String fileId) {
return fileAttachmentMetadataMapper.selectByPrimaryKey(fileId);
}
public void deleteFileById(String fileId) { public void deleteFileById(String fileId) {
deleteFileByIds(Collections.singletonList(fileId)); deleteFileByIds(Collections.singletonList(fileId));

View File

@ -27,6 +27,7 @@ import io.metersphere.track.request.testcase.AuthUserIssueRequest;
import io.metersphere.track.request.testcase.IssuesRequest; import io.metersphere.track.request.testcase.IssuesRequest;
import io.metersphere.track.request.testcase.IssuesUpdateRequest; import io.metersphere.track.request.testcase.IssuesUpdateRequest;
import io.metersphere.track.service.IssuesService; import io.metersphere.track.service.IssuesService;
import io.metersphere.track.service.TestCaseService;
import org.apache.shiro.authz.annotation.RequiresPermissions; import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
@ -64,22 +65,33 @@ public class IssuesController {
return PageUtils.setPageInfo(page, issuesService.relateList(request)); return PageUtils.setPageInfo(page, issuesService.relateList(request));
} }
@PostMapping(value = "/add", consumes = {"multipart/form-data"}) @PostMapping(value = "/add")
@RequiresPermissions(PermissionConstants.PROJECT_TRACK_ISSUE_READ_CREATE) @RequiresPermissions(PermissionConstants.PROJECT_TRACK_ISSUE_READ_CREATE)
@MsAuditLog(module = OperLogModule.TRACK_BUG, type = OperLogConstants.CREATE, content = "#msClass.getLogDetails(#issuesRequest)", msClass = IssuesService.class) @MsAuditLog(module = OperLogModule.TRACK_BUG, type = OperLogConstants.CREATE, content = "#msClass.getLogDetails(#issuesRequest)", msClass = IssuesService.class)
@SendNotice(taskType = NoticeConstants.TaskType.DEFECT_TASK, target = "#issuesRequest", @SendNotice(taskType = NoticeConstants.TaskType.DEFECT_TASK, target = "#issuesRequest",
event = NoticeConstants.Event.CREATE, subject = "缺陷通知") event = NoticeConstants.Event.CREATE, subject = "缺陷通知")
public IssuesWithBLOBs addIssues(@RequestPart(value = "request") IssuesUpdateRequest issuesRequest, @RequestPart(value = "file", required = false) List<MultipartFile> files) { public IssuesWithBLOBs addIssues(@RequestPart(value = "request") IssuesUpdateRequest issuesRequest) {
return issuesService.addIssuesRefactor(issuesRequest, files); return issuesService.addIssues(issuesRequest);
} }
@PostMapping(value = "/update", consumes = {"multipart/form-data"}) @PostMapping(value = "/update")
@RequiresPermissions(PermissionConstants.PROJECT_TRACK_ISSUE_READ_EDIT) @RequiresPermissions(PermissionConstants.PROJECT_TRACK_ISSUE_READ_EDIT)
@MsAuditLog(module = OperLogModule.TRACK_BUG, type = OperLogConstants.UPDATE, beforeEvent = "#msClass.getLogDetails(#issuesRequest.id)", content = "#msClass.getLogDetails(#issuesRequest.id)", msClass = IssuesService.class) @MsAuditLog(module = OperLogModule.TRACK_BUG, type = OperLogConstants.UPDATE, beforeEvent = "#msClass.getLogDetails(#issuesRequest.id)", content = "#msClass.getLogDetails(#issuesRequest.id)", msClass = IssuesService.class)
@SendNotice(taskType = NoticeConstants.TaskType.DEFECT_TASK, target = "#issuesRequest", @SendNotice(taskType = NoticeConstants.TaskType.DEFECT_TASK, target = "#issuesRequest",
event = NoticeConstants.Event.UPDATE, subject = "缺陷通知") event = NoticeConstants.Event.UPDATE, subject = "缺陷通知")
public void updateIssues(@RequestPart(value = "request") IssuesUpdateRequest issuesRequest, @RequestPart(value = "file", required = false) List<MultipartFile> files) { public void updateIssues(@RequestPart(value = "request") IssuesUpdateRequest issuesRequest) {
issuesService.updateIssuesRefactor(issuesRequest, files); issuesService.updateIssues(issuesRequest);
}
@PostMapping(value = "/attachment/upload", consumes = {"multipart/form-data"})
@MsAuditLog(module = OperLogModule.TRACK_BUG, type = OperLogConstants.IMPORT, beforeEvent = "#msClass.getLogDetails(#issuesRequest.id)", content = "#msClass.getLogDetails(#request.id)", msClass = TestCaseService.class)
public void uploadAttachment(@RequestPart("request") IssuesUpdateRequest issuesRequest, @RequestPart(value = "file", required = false) MultipartFile file) {
issuesService.uploadAttachment(issuesRequest, file);
}
@GetMapping("/attachment/delete/{fileId}")
public void deleteAttachment(@PathVariable String fileId) {
issuesService.deleteAttachment(fileId);
} }
@GetMapping("/file/attachmentMetadata/{issueId}") @GetMapping("/file/attachmentMetadata/{issueId}")

View File

@ -385,15 +385,6 @@ public class TestCaseController {
.body(bytes); .body(bytes);
} }
@PostMapping("/attachment/download")
public ResponseEntity<byte[]> attachmentDownload(@RequestBody FileOperationRequest fileOperationRequest) {
byte[] bytes = fileService.getAttachmentBytes(fileOperationRequest.getId());
return ResponseEntity.ok()
.contentType(MediaType.parseMediaType("application/octet-stream"))
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + URLEncoder.encode(fileOperationRequest.getName(), StandardCharsets.UTF_8) + "\"")
.body(bytes);
}
@GetMapping("/file/preview/{fileId}") @GetMapping("/file/preview/{fileId}")
public ResponseEntity<byte[]> preview(@PathVariable String fileId) { public ResponseEntity<byte[]> preview(@PathVariable String fileId) {
byte[] bytes = fileService.loadFileAsBytes(fileId); byte[] bytes = fileService.loadFileAsBytes(fileId);
@ -403,8 +394,14 @@ public class TestCaseController {
.body(bytes); .body(bytes);
} }
@PostMapping(value = "/attachment/upload", consumes = {"multipart/form-data"})
@MsAuditLog(module = OperLogModule.TRACK_TEST_CASE, type = OperLogConstants.IMPORT, beforeEvent = "#msClass.getLogDetails(#request.id)", title = "#request.name", content = "#msClass.getLogDetails(#request.id)", msClass = TestCaseService.class)
public void uploadAttachment(@RequestPart("request") EditTestCaseRequest request, @RequestPart(value = "file", required = false) MultipartFile file) {
testCaseService.uploadAttachment(request, file);
}
@GetMapping("/attachment/preview/{fileId}") @GetMapping("/attachment/preview/{fileId}")
public ResponseEntity<byte[]> attachmentPreview(@PathVariable String fileId) { public ResponseEntity<byte[]> previewAttachment(@PathVariable String fileId) {
byte[] bytes = fileService.getAttachmentBytes(fileId); byte[] bytes = fileService.getAttachmentBytes(fileId);
return ResponseEntity.ok() return ResponseEntity.ok()
.contentType(MediaType.parseMediaType("application/octet-stream")) .contentType(MediaType.parseMediaType("application/octet-stream"))
@ -412,6 +409,20 @@ public class TestCaseController {
.body(bytes); .body(bytes);
} }
@PostMapping("/attachment/download")
public ResponseEntity<byte[]> downloadAttachment(@RequestBody FileOperationRequest fileOperationRequest) {
byte[] bytes = fileService.getAttachmentBytes(fileOperationRequest.getId());
return ResponseEntity.ok()
.contentType(MediaType.parseMediaType("application/octet-stream"))
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + URLEncoder.encode(fileOperationRequest.getName(), StandardCharsets.UTF_8) + "\"")
.body(bytes);
}
@GetMapping("/attachment/delete/{fileId}")
public void deleteAttachment(@PathVariable String fileId) {
testCaseService.deleteAttachment(fileId);
}
@PostMapping("/save") @PostMapping("/save")
@MsAuditLog(module = OperLogModule.TRACK_TEST_CASE, type = OperLogConstants.CREATE, title = "#testCaseWithBLOBs.name", content = "#msClass.getLogDetails(#testCaseWithBLOBs.id)", msClass = TestCaseService.class) @MsAuditLog(module = OperLogModule.TRACK_TEST_CASE, type = OperLogConstants.CREATE, title = "#testCaseWithBLOBs.name", content = "#msClass.getLogDetails(#testCaseWithBLOBs.id)", msClass = TestCaseService.class)
public TestCaseWithBLOBs saveTestCase(@RequestBody EditTestCaseRequest request) { public TestCaseWithBLOBs saveTestCase(@RequestBody EditTestCaseRequest request) {

View File

@ -11,7 +11,6 @@ import io.metersphere.track.request.testcase.EditTestCaseRequest;
import io.metersphere.track.request.testcase.IssuesRequest; import io.metersphere.track.request.testcase.IssuesRequest;
import io.metersphere.track.request.testcase.IssuesUpdateRequest; import io.metersphere.track.request.testcase.IssuesUpdateRequest;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.web.multipart.MultipartFile;
import java.util.List; import java.util.List;
@ -32,13 +31,13 @@ public interface IssuesPlatform {
* *
* @param issuesRequest issueRequest * @param issuesRequest issueRequest
*/ */
IssuesWithBLOBs addIssue(IssuesUpdateRequest issuesRequest, List<MultipartFile> files); IssuesWithBLOBs addIssue(IssuesUpdateRequest issuesRequest);
/** /**
* 更新缺陷 * 更新缺陷
* @param request * @param request
*/ */
void updateIssue(IssuesUpdateRequest request, List<MultipartFile> files); void updateIssue(IssuesUpdateRequest request);
/** /**
* 删除缺陷平台缺陷 * 删除缺陷平台缺陷

View File

@ -10,7 +10,6 @@ import io.metersphere.commons.constants.IssuesManagePlatform;
import io.metersphere.commons.constants.IssuesStatus; import io.metersphere.commons.constants.IssuesStatus;
import io.metersphere.commons.exception.MSException; import io.metersphere.commons.exception.MSException;
import io.metersphere.commons.utils.CommonBeanFactory; import io.metersphere.commons.utils.CommonBeanFactory;
import io.metersphere.commons.utils.FileUtils;
import io.metersphere.commons.utils.LogUtil; import io.metersphere.commons.utils.LogUtil;
import io.metersphere.dto.CustomFieldDao; import io.metersphere.dto.CustomFieldDao;
import io.metersphere.dto.CustomFieldItemDTO; import io.metersphere.dto.CustomFieldItemDTO;
@ -31,10 +30,8 @@ import org.apache.commons.lang.StringEscapeUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.web.client.HttpClientErrorException; import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.multipart.MultipartFile;
import java.io.File; import java.io.File;
import java.io.IOException;
import java.net.URLDecoder; import java.net.URLDecoder;
import java.net.URLEncoder; import java.net.URLEncoder;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
@ -227,7 +224,7 @@ public class JiraPlatform extends AbstractIssuePlatform {
} }
@Override @Override
public IssuesWithBLOBs addIssue(IssuesUpdateRequest issuesRequest, List<MultipartFile> files) { public IssuesWithBLOBs addIssue(IssuesUpdateRequest issuesRequest) {
setUserConfig(); setUserConfig();
Project project = getProject(); Project project = getProject();
@ -239,20 +236,6 @@ public class JiraPlatform extends AbstractIssuePlatform {
// 上传附件 // 上传附件
imageFiles.forEach(img -> jiraClientV2.uploadAttachment(result.getKey(), img)); imageFiles.forEach(img -> jiraClientV2.uploadAttachment(result.getKey(), img));
if (files != null) {
files.forEach(multipartFile -> {
try {
File file = new File(FileUtils.ATTACHMENT_TMP_DIR + "/" + multipartFile.getOriginalFilename());
org.apache.commons.io.FileUtils.copyInputStreamToFile(multipartFile.getInputStream(), file);
jiraClientV2.uploadAttachment(result.getKey(), file);
if (file.exists()) {
file.delete();
}
} catch (IOException e) {
LogUtil.error(e);
}
});
}
String status = getStatus(issues.getFields()); String status = getStatus(issues.getFields());
issuesRequest.setPlatformStatus(status); issuesRequest.setPlatformStatus(status);
@ -266,6 +249,21 @@ public class JiraPlatform extends AbstractIssuePlatform {
// 用例与第三方缺陷平台中的缺陷关联 // 用例与第三方缺陷平台中的缺陷关联
handleTestCaseIssues(issuesRequest); handleTestCaseIssues(issuesRequest);
// 如果是复制新增, 同步附件到第三方平台
if (StringUtils.isNotEmpty(issuesRequest.getCopyIssueId())) {
IssueFileExample example = new IssueFileExample();
example.createCriteria().andIssueIdEqualTo(issuesRequest.getCopyIssueId());
List<IssueFile> issueFiles = issueFileMapper.selectByExample(example);
if (issueFiles != null) {
issueFiles.forEach(issueFile -> {
FileAttachmentMetadata fileAttachmentMetadata = fileService.getFileAttachmentMetadataByFileId(issueFile.getFileId());
// 同步第三方平台附件
File file = new File(fileAttachmentMetadata.getFilePath() + "/" + fileAttachmentMetadata.getName());
jiraClientV2.uploadAttachment(result.getKey(), file);
});
}
}
return res; return res;
} }
@ -479,7 +477,7 @@ public class JiraPlatform extends AbstractIssuePlatform {
} }
@Override @Override
public void updateIssue(IssuesUpdateRequest request, List<MultipartFile> files) { public void updateIssue(IssuesUpdateRequest request) {
setUserConfig(); setUserConfig();
Project project = getProject(); Project project = getProject();
List<File> imageFiles = getImageFiles(request); List<File> imageFiles = getImageFiles(request);
@ -487,54 +485,40 @@ public class JiraPlatform extends AbstractIssuePlatform {
JSONObject param = buildUpdateParam(request, getIssueType(project.getIssueConfig()), project.getJiraKey()); JSONObject param = buildUpdateParam(request, getIssueType(project.getIssueConfig()), project.getJiraKey());
jiraClientV2.updateIssue(request.getPlatformId(), JSONObject.toJSONString(param)); jiraClientV2.updateIssue(request.getPlatformId(), JSONObject.toJSONString(param));
List<FileMetadata> updatedFiles = request.getUpdatedFileList(); List<FileAttachmentMetadata> newFiles = fileService.getFileAttachmentMetadataByIssueId(request.getId());
List<String> updatedFileIds = updatedFiles.stream().map(FileMetadata::getId).collect(Collectors.toList()); List<String> newFileNames = newFiles.stream().map(FileAttachmentMetadata::getName).collect(Collectors.toList());
List<FileAttachmentMetadata> originFiles = fileService.getFileAttachmentMetadataByIssueId(request.getId());
List<String> deleteAttachmentNames = new ArrayList<String>();
originFiles.forEach(originFile -> {
if (!updatedFileIds.contains(originFile.getId())) {
deleteAttachmentNames.add(originFile.getName());
}
});
Set<String> attachmentNames = new HashSet<>(); Set<String> attachmentNames = new HashSet<>();
// 更新附件 // 同步Jira平台附件
JiraIssue jiraIssue = jiraClientV2.getIssues(request.getPlatformId()); JiraIssue jiraIssue = jiraClientV2.getIssues(request.getPlatformId());
JSONObject fields = jiraIssue.getFields(); JSONObject fields = jiraIssue.getFields();
JSONArray attachments = fields.getJSONArray("attachment"); JSONArray attachments = fields.getJSONArray("attachment");
// 删除旧附件若缺陷描述中不存在且附件上传的删除列表中存在则删除
if (!attachments.isEmpty() && attachments.size() > 0) { if (!attachments.isEmpty() && attachments.size() > 0) {
// 删除旧附件若缺陷描述中不存在且附件上传的删除列表中存在则删除
for (int i = 0; i < attachments.size(); i++) { for (int i = 0; i < attachments.size(); i++) {
JSONObject attachment = attachments.getJSONObject(i); JSONObject attachment = attachments.getJSONObject(i);
String filename = attachment.getString("filename"); String filename = attachment.getString("filename");
attachmentNames.add(filename); attachmentNames.add(filename);
if (!request.getDescription().contains(filename) && deleteAttachmentNames.contains(filename)) { if (!request.getDescription().contains(filename) && !newFileNames.contains(filename)) {
String fileId = attachment.getString("id"); String fileId = attachment.getString("id");
jiraClientV2.deleteAttachment(fileId); jiraClientV2.deleteAttachment(fileId);
} }
} }
} }
//上传新附件
// 上传新附件 if (CollectionUtils.isNotEmpty(newFiles)) {
newFiles.forEach(file -> {
if (!attachmentNames.contains(file.getName())) {
File newFile = new File(file.getFilePath() + "/" + file.getName());
jiraClientV2.uploadAttachment(request.getPlatformId(), newFile);
}
});
}
imageFiles.forEach(img -> { imageFiles.forEach(img -> {
if (!attachmentNames.contains(img.getName())) { if (!attachmentNames.contains(img.getName())) {
// 旧附件没有才上传新附件 // 旧附件没有才上传新附件
jiraClientV2.uploadAttachment(request.getPlatformId(), img); jiraClientV2.uploadAttachment(request.getPlatformId(), img);
} }
}); });
if (files != null) {
files.forEach(multipartFile -> {
try {
File file = new File(FileUtils.ATTACHMENT_TMP_DIR + "/" + multipartFile.getOriginalFilename());
org.apache.commons.io.FileUtils.copyInputStreamToFile(multipartFile.getInputStream(), file);
jiraClientV2.uploadAttachment(request.getPlatformId(), file);
if (file.exists()) {
file.delete();
}
} catch (IOException e) {
LogUtil.error(e);
}
});
}
if (request.getTransitions() != null) { if (request.getTransitions() != null) {
try { try {
@ -548,7 +532,6 @@ public class JiraPlatform extends AbstractIssuePlatform {
LogUtil.error(e); LogUtil.error(e);
} }
} }
handleIssueUpdate(request); handleIssueUpdate(request);
} }

View File

@ -13,7 +13,6 @@ import io.metersphere.track.request.testcase.IssuesRequest;
import io.metersphere.track.request.testcase.IssuesUpdateRequest; import io.metersphere.track.request.testcase.IssuesUpdateRequest;
import io.metersphere.track.request.testcase.TestCaseBatchRequest; import io.metersphere.track.request.testcase.TestCaseBatchRequest;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.springframework.web.multipart.MultipartFile;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
@ -42,7 +41,7 @@ public class LocalPlatform extends LocalAbstractPlatform {
} }
@Override @Override
public IssuesWithBLOBs addIssue(IssuesUpdateRequest issuesRequest, List<MultipartFile> files) { public IssuesWithBLOBs addIssue(IssuesUpdateRequest issuesRequest) {
String issueStatus = "new"; String issueStatus = "new";
if (StringUtils.isNotBlank(issuesRequest.getCustomFields())) { if (StringUtils.isNotBlank(issuesRequest.getCustomFields())) {
List<CustomFieldItemDTO> customFields = issuesRequest.getRequestFields(); List<CustomFieldItemDTO> customFields = issuesRequest.getRequestFields();
@ -76,7 +75,7 @@ public class LocalPlatform extends LocalAbstractPlatform {
} }
@Override @Override
public void updateIssue(IssuesUpdateRequest request, List<MultipartFile> files) { public void updateIssue(IssuesUpdateRequest request) {
handleIssueUpdate(request); handleIssueUpdate(request);
} }
} }

View File

@ -30,7 +30,6 @@ import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap; import org.springframework.util.MultiValueMap;
import org.springframework.web.multipart.MultipartFile;
import java.util.*; import java.util.*;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -91,7 +90,7 @@ public class TapdPlatform extends AbstractIssuePlatform {
} }
@Override @Override
public IssuesWithBLOBs addIssue(IssuesUpdateRequest issuesRequest, List<MultipartFile> files) { public IssuesWithBLOBs addIssue(IssuesUpdateRequest issuesRequest) {
MultiValueMap<String, Object> param = buildUpdateParam(issuesRequest); MultiValueMap<String, Object> param = buildUpdateParam(issuesRequest);
TapdBug bug = tapdClient.addIssue(param); TapdBug bug = tapdClient.addIssue(param);
@ -112,7 +111,7 @@ public class TapdPlatform extends AbstractIssuePlatform {
} }
@Override @Override
public void updateIssue(IssuesUpdateRequest request, List<MultipartFile> files) { public void updateIssue(IssuesUpdateRequest request) {
MultiValueMap<String, Object> param = buildUpdateParam(request); MultiValueMap<String, Object> param = buildUpdateParam(request);
param.add("id", request.getPlatformId()); param.add("id", request.getPlatformId());
handleIssueUpdate(request); handleIssueUpdate(request);

View File

@ -37,7 +37,6 @@ import org.springframework.util.CollectionUtils;
import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap; import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate; import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;
import java.net.URLDecoder; import java.net.URLDecoder;
import java.net.URLEncoder; import java.net.URLEncoder;
@ -198,7 +197,7 @@ public class ZentaoPlatform extends AbstractIssuePlatform {
} }
@Override @Override
public IssuesWithBLOBs addIssue(IssuesUpdateRequest issuesRequest, List<MultipartFile> files) { public IssuesWithBLOBs addIssue(IssuesUpdateRequest issuesRequest) {
setUserConfig(); setUserConfig();
MultiValueMap<String, Object> param = buildUpdateParam(issuesRequest); MultiValueMap<String, Object> param = buildUpdateParam(issuesRequest);
@ -229,7 +228,7 @@ public class ZentaoPlatform extends AbstractIssuePlatform {
} }
@Override @Override
public void updateIssue(IssuesUpdateRequest request, List<MultipartFile> files) { public void updateIssue(IssuesUpdateRequest request) {
setUserConfig(); setUserConfig();
MultiValueMap<String, Object> param = buildUpdateParam(request); MultiValueMap<String, Object> param = buildUpdateParam(request);
if (request.getTransitions() != null) { if (request.getTransitions() != null) {

View File

@ -6,7 +6,6 @@ import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.Page; import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper; import com.github.pagehelper.PageHelper;
import io.metersphere.base.domain.*; import io.metersphere.base.domain.*;
import io.metersphere.base.domain.ext.CustomFieldResource;
import io.metersphere.base.mapper.*; import io.metersphere.base.mapper.*;
import io.metersphere.base.mapper.ext.ExtIssuesMapper; import io.metersphere.base.mapper.ext.ExtIssuesMapper;
import io.metersphere.commons.constants.AttachmentType; import io.metersphere.commons.constants.AttachmentType;
@ -36,7 +35,6 @@ import io.metersphere.track.request.testcase.IssuesRequest;
import io.metersphere.track.request.testcase.IssuesUpdateRequest; import io.metersphere.track.request.testcase.IssuesUpdateRequest;
import io.metersphere.track.request.testcase.TestCaseBatchRequest; import io.metersphere.track.request.testcase.TestCaseBatchRequest;
import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections4.ListUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.springframework.context.annotation.Lazy; import org.springframework.context.annotation.Lazy;
import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.data.redis.core.StringRedisTemplate;
@ -108,7 +106,7 @@ public class IssuesService {
List<AbstractIssuePlatform> platformList = getAddPlatforms(issuesRequest); List<AbstractIssuePlatform> platformList = getAddPlatforms(issuesRequest);
IssuesWithBLOBs issues = null; IssuesWithBLOBs issues = null;
for (AbstractIssuePlatform platform : platformList) { for (AbstractIssuePlatform platform : platformList) {
issues = platform.addIssue(issuesRequest, null); issues = platform.addIssue(issuesRequest);
} }
if (issuesRequest.getIsPlanEdit()) { if (issuesRequest.getIsPlanEdit()) {
issuesRequest.getAddResourceIds().forEach(l -> { issuesRequest.getAddResourceIds().forEach(l -> {
@ -116,39 +114,9 @@ public class IssuesService {
}); });
} }
saveFollows(issuesRequest.getId(), issuesRequest.getFollows()); saveFollows(issuesRequest.getId(), issuesRequest.getFollows());
List<CustomFieldResource> addFields = issuesRequest.getAddFields(); customFieldIssuesService.addFields(issuesRequest.getId(), issuesRequest.getAddFields());
addFields.addAll(issuesRequest.getEditFields());
customFieldIssuesService.addFields(issuesRequest.getId(), addFields);
return issues;
}
public void updateIssues(IssuesUpdateRequest issuesRequest) {
issuesRequest.getId();
List<AbstractIssuePlatform> platformList = getUpdatePlatforms(issuesRequest);
platformList.forEach(platform -> {
platform.updateIssue(issuesRequest, null);
});
customFieldIssuesService.editFields(issuesRequest.getId(), issuesRequest.getEditFields()); customFieldIssuesService.editFields(issuesRequest.getId(), issuesRequest.getEditFields());
customFieldIssuesService.addFields(issuesRequest.getId(), issuesRequest.getAddFields()); // copy附件
// todo 缺陷更新事件
}
public IssuesWithBLOBs addIssuesRefactor(IssuesUpdateRequest issuesRequest, List<MultipartFile> files) {
List<AbstractIssuePlatform> platformList = getAddPlatforms(issuesRequest);
IssuesWithBLOBs issues = null;
for (AbstractIssuePlatform platform : platformList) {
issues = platform.addIssue(issuesRequest, files);
}
if (issuesRequest.getIsPlanEdit()) {
issuesRequest.getAddResourceIds().forEach(l -> {
testCaseIssueService.updateIssuesCount(l);
});
}
saveFollows(issuesRequest.getId(), issuesRequest.getFollows());
customFieldIssuesService.addFields(issuesRequest.getId(), issuesRequest.getAddFields());
// copy的附件
if (StringUtils.isNotEmpty(issuesRequest.getCopyIssueId())) { if (StringUtils.isNotEmpty(issuesRequest.getCopyIssueId())) {
final String addIssueId = issues.getId(); final String addIssueId = issues.getId();
IssueFileExample example = new IssueFileExample(); IssueFileExample example = new IssueFileExample();
@ -156,6 +124,7 @@ public class IssuesService {
List<IssueFile> issueFiles = issueFileMapper.selectByExample(example); List<IssueFile> issueFiles = issueFileMapper.selectByExample(example);
if (issueFiles != null) { if (issueFiles != null) {
issueFiles.forEach(issueFile -> { issueFiles.forEach(issueFile -> {
// 同步MS附件
FileAttachmentMetadata fileAttachmentMetadata = fileService.copyAttachment(issueFile.getFileId(), AttachmentType.ISSUE.type(), addIssueId); FileAttachmentMetadata fileAttachmentMetadata = fileService.copyAttachment(issueFile.getFileId(), AttachmentType.ISSUE.type(), addIssueId);
IssueFile newIssueFile = new IssueFile(); IssueFile newIssueFile = new IssueFile();
newIssueFile.setIssueId(addIssueId); newIssueFile.setIssueId(addIssueId);
@ -164,57 +133,40 @@ public class IssuesService {
}); });
} }
} }
// 新的附件
if (files != null) {
files.forEach(file -> {
FileAttachmentMetadata fileAttachmentMetadata = fileService.saveAttachment(file, AttachmentType.ISSUE.type(), issuesRequest.getId());
IssueFile issueFile = new IssueFile();
issueFile.setIssueId(issuesRequest.getId());
issueFile.setFileId(fileAttachmentMetadata.getId());
issueFileMapper.insert(issueFile);
});
}
return issues; return issues;
} }
public void updateIssues(IssuesUpdateRequest issuesRequest) {
public void updateIssuesRefactor(IssuesUpdateRequest issuesRequest, List<MultipartFile> files) {
issuesRequest.getId();
List<AbstractIssuePlatform> platformList = getUpdatePlatforms(issuesRequest); List<AbstractIssuePlatform> platformList = getUpdatePlatforms(issuesRequest);
platformList.forEach(platform -> { platformList.forEach(platform -> {
platform.updateIssue(issuesRequest, files); platform.updateIssue(issuesRequest);
}); });
customFieldIssuesService.editFields(issuesRequest.getId(), issuesRequest.getEditFields()); customFieldIssuesService.editFields(issuesRequest.getId(), issuesRequest.getEditFields());
customFieldIssuesService.addFields(issuesRequest.getId(), issuesRequest.getAddFields()); customFieldIssuesService.addFields(issuesRequest.getId(), issuesRequest.getAddFields());
// todo 缺陷更新事件 }
// 删除原来的文件 public void uploadAttachment(IssuesUpdateRequest request, MultipartFile file) {
List<FileMetadata> updatedFiles = issuesRequest.getUpdatedFileList(); IssuesWithBLOBs issuesWithBLOBs = issuesMapper.selectByPrimaryKey(request.getId());
List<FileAttachmentMetadata> originFiles = fileService.getFileAttachmentMetadataByIssueId(issuesRequest.getId()); if (issuesWithBLOBs == null) {
List<String> updatedFileIds = updatedFiles.stream().map(FileMetadata::getId).collect(Collectors.toList()); MSException.throwException(Translator.get("issues_attachment_upload_not_found") + request.getId());
List<String> originFileIds = originFiles.stream().map(FileAttachmentMetadata::getId).collect(Collectors.toList());
// 获得差异的附件ID
List<String> deleteFileIds = ListUtils.subtract(originFileIds, updatedFileIds);
// 删除差异附件记录, 目录下附件文件
fileService.deleteAttachment(deleteFileIds);
fileService.deleteFileAttachmentByIds(deleteFileIds);
//删除用例文件关联记录
if (!CollectionUtils.isEmpty(deleteFileIds)) {
IssueFileExample issueFileExample = new IssueFileExample();
issueFileExample.createCriteria().andFileIdIn(deleteFileIds);
issueFileMapper.deleteByExample(issueFileExample);
} }
FileAttachmentMetadata fileAttachmentMetadata = fileService.saveAttachment(file, AttachmentType.ISSUE.type(), request.getId());
IssueFile issueFile = new IssueFile();
issueFile.setIssueId(request.getId());
issueFile.setFileId(fileAttachmentMetadata.getId());
issueFileMapper.insert(issueFile);
}
// 保存新的附件 public void deleteAttachment(String id) {
if (files != null) { // 删除附件记录, 目录下附件文件
files.forEach(file -> { if (StringUtils.isNotEmpty(id)) {
FileAttachmentMetadata fileAttachmentMetadata = fileService.saveAttachment(file, AttachmentType.ISSUE.type(), issuesRequest.getId()); List<String> ids = Arrays.asList(id);
IssueFile issueFile = new IssueFile(); fileService.deleteAttachment(ids);
issueFile.setIssueId(issuesRequest.getId()); fileService.deleteFileAttachmentByIds(ids);
issueFile.setFileId(fileAttachmentMetadata.getId()); //删除缺陷文件关联记录
issueFileMapper.insert(issueFile); IssueFileExample issueFileExample = new IssueFileExample();
}); issueFileExample.createCriteria().andFileIdIn(ids);
issueFileMapper.deleteByExample(issueFileExample);
} }
} }
@ -417,6 +369,7 @@ public class IssuesService {
AbstractIssuePlatform platform = IssueFactory.createPlatform(issuesWithBLOBs.getPlatform(), issuesRequest); AbstractIssuePlatform platform = IssueFactory.createPlatform(issuesWithBLOBs.getPlatform(), issuesRequest);
platform.deleteIssue(id); platform.deleteIssue(id);
// 删除缺陷对应的附件 // 删除缺陷对应的附件
fileService.deleteAttachment(AttachmentType.ISSUE.type(), id);
IssueFileExample issueFileExample = new IssueFileExample(); IssueFileExample issueFileExample = new IssueFileExample();
issueFileExample.createCriteria().andIssueIdEqualTo(id); issueFileExample.createCriteria().andIssueIdEqualTo(id);
List<IssueFile> issueFiles = issueFileMapper.selectByExample(issueFileExample); List<IssueFile> issueFiles = issueFileMapper.selectByExample(issueFileExample);
@ -427,7 +380,6 @@ public class IssuesService {
fileAttachmentMetadataMapper.deleteByExample(fileAttachmentMetadataExample); fileAttachmentMetadataMapper.deleteByExample(fileAttachmentMetadataExample);
} }
issueFileMapper.deleteByExample(issueFileExample); issueFileMapper.deleteByExample(issueFileExample);
fileService.deleteAttachment(AttachmentType.ISSUE.type(), id);
} }
public IssuesWithBLOBs get(String id) { public IssuesWithBLOBs get(String id) {

View File

@ -50,6 +50,7 @@ public class TestCaseIssueService {
List<String> caseIds = getCaseIdsByIssuesId(request.getIssuesId()); List<String> caseIds = getCaseIdsByIssuesId(request.getIssuesId());
List<TestCaseDTO> list = testCaseService.getTestCaseByIds(caseIds); List<TestCaseDTO> list = testCaseService.getTestCaseByIds(caseIds);
testCaseService.addProjectName(list); testCaseService.addProjectName(list);
testCaseService.addVersionName(list);
return list; return list;
} }

View File

@ -618,9 +618,11 @@ public class TestCaseService {
testCaseFileExample.createCriteria().andCaseIdEqualTo(testCaseId); testCaseFileExample.createCriteria().andCaseIdEqualTo(testCaseId);
List<TestCaseFile> testCaseFiles = testCaseFileMapper.selectByExample(testCaseFileExample); List<TestCaseFile> testCaseFiles = testCaseFileMapper.selectByExample(testCaseFileExample);
List<String> fileIds = testCaseFiles.stream().map(TestCaseFile::getFileId).collect(Collectors.toList()); List<String> fileIds = testCaseFiles.stream().map(TestCaseFile::getFileId).collect(Collectors.toList());
FileAttachmentMetadataExample fileAttachmentMetadataExample = new FileAttachmentMetadataExample(); if (CollectionUtils.isNotEmpty(fileIds)) {
fileAttachmentMetadataExample.createCriteria().andIdIn(fileIds); FileAttachmentMetadataExample fileAttachmentMetadataExample = new FileAttachmentMetadataExample();
fileAttachmentMetadataMapper.deleteByExample(fileAttachmentMetadataExample); fileAttachmentMetadataExample.createCriteria().andIdIn(fileIds);
fileAttachmentMetadataMapper.deleteByExample(fileAttachmentMetadataExample);
}
testCaseFileMapper.deleteByExample(testCaseFileExample); testCaseFileMapper.deleteByExample(testCaseFileExample);
fileService.deleteAttachment(AttachmentType.TEST_CASE.type(), testCaseId); fileService.deleteAttachment(AttachmentType.TEST_CASE.type(), testCaseId);
return testCaseMapper.deleteByPrimaryKey(testCaseId); return testCaseMapper.deleteByPrimaryKey(testCaseId);
@ -867,6 +869,7 @@ public class TestCaseService {
public List<TestCaseDTO> getTestCaseByNotInIssue(QueryTestCaseRequest request) { public List<TestCaseDTO> getTestCaseByNotInIssue(QueryTestCaseRequest request) {
List<TestCaseDTO> list = extTestCaseMapper.getTestCaseByNotInIssue(request); List<TestCaseDTO> list = extTestCaseMapper.getTestCaseByNotInIssue(request);
addProjectName(list); addProjectName(list);
addVersionName(list);
return list; return list;
} }
@ -885,6 +888,24 @@ public class TestCaseService {
}); });
} }
public void addVersionName(List<TestCaseDTO> list) {
List<String> versionIds = list.stream().map(TestCase::getVersionId).collect(Collectors.toList());
List<ProjectVersion> versions = new ArrayList<>();
if (CollectionUtils.isNotEmpty(versionIds)) {
ProjectVersionExample example = new ProjectVersionExample();
example.createCriteria().andIdIn(versionIds);
versions = projectVersionMapper.selectByExample(example);
}
Map<String, String> projectVersionMap = versions.stream()
.collect(Collectors.toMap(ProjectVersion::getId, ProjectVersion::getName));
list.forEach(item -> {
String versionName = projectVersionMap.get(item.getVersionId());
if (StringUtils.isNotBlank(versionName)) {
item.setVersionName(versionName);
}
});
}
public List<TestCaseDTO> getReviewCase(QueryTestCaseRequest request) { public List<TestCaseDTO> getReviewCase(QueryTestCaseRequest request) {
setDefaultOrder(request); setDefaultOrder(request);
request.getOrders().forEach(order -> { request.getOrders().forEach(order -> {
@ -1964,7 +1985,6 @@ public class TestCaseService {
public TestCase refactorSave(EditTestCaseRequest request, List<MultipartFile> files) { public TestCase refactorSave(EditTestCaseRequest request, List<MultipartFile> files) {
final TestCaseWithBLOBs testCaseWithBLOBs = addTestCase(request); final TestCaseWithBLOBs testCaseWithBLOBs = addTestCase(request);
// 复制用例时复制对应附件数据 // 复制用例时复制对应附件数据
if (StringUtils.isNotEmpty(request.getCopyCaseId())) { if (StringUtils.isNotEmpty(request.getCopyCaseId())) {
TestCaseFileExample example = new TestCaseFileExample(); TestCaseFileExample example = new TestCaseFileExample();
@ -1980,18 +2000,6 @@ public class TestCaseService {
}); });
} }
} }
// 新的附件
if (files != null) {
files.forEach(file -> {
FileAttachmentMetadata fileAttachmentMetadata = fileService.saveAttachment(file, AttachmentType.TEST_CASE.type(), request.getId());
TestCaseFile testCaseFile = new TestCaseFile();
testCaseFile.setFileId(fileAttachmentMetadata.getId());
testCaseFile.setCaseId(request.getId());
testCaseFileMapper.insert(testCaseFile);
});
}
return testCaseWithBLOBs; return testCaseWithBLOBs;
} }
@ -2039,41 +2047,36 @@ public class TestCaseService {
if (testCaseWithBLOBs == null) { if (testCaseWithBLOBs == null) {
MSException.throwException(Translator.get("edit_load_test_not_found") + request.getId()); MSException.throwException(Translator.get("edit_load_test_not_found") + request.getId());
} }
if (BooleanUtils.isTrue(request.isHandleAttachment())) {
// 新选择了一个文件删除原来的文件
List<FileMetadata> updatedFiles = request.getUpdatedFileList();
List<FileAttachmentMetadata> originFiles = fileService.getFileAttachmentMetadataByCaseId(request.getId());
List<String> updatedFileIds = updatedFiles.stream().map(FileMetadata::getId).collect(Collectors.toList());
List<String> originFileIds = originFiles.stream().map(FileAttachmentMetadata::getId).collect(Collectors.toList());
// 获得差异的附件ID
List<String> deleteFileIds = ListUtils.subtract(originFileIds, updatedFileIds);
// 删除差异附件记录, 目录下附件文件
fileService.deleteAttachment(deleteFileIds);
fileService.deleteFileAttachmentByIds(deleteFileIds);
//删除用例文件关联记录
if (!CollectionUtils.isEmpty(deleteFileIds)) {
TestCaseFileExample testCaseFileExample = new TestCaseFileExample();
testCaseFileExample.createCriteria().andFileIdIn(deleteFileIds);
testCaseFileMapper.deleteByExample(testCaseFileExample);
}
// 保存新的附件
if (files != null) {
files.forEach(file -> {
FileAttachmentMetadata fileAttachmentMetadata = fileService.saveAttachment(file, AttachmentType.TEST_CASE.type(), request.getId());
TestCaseFile testCaseFile = new TestCaseFile();
testCaseFile.setFileId(fileAttachmentMetadata.getId());
testCaseFile.setCaseId(request.getId());
testCaseFileMapper.insert(testCaseFile);
});
}
}
this.setNode(request); this.setNode(request);
return editTestCase(request); return editTestCase(request);
} }
public void uploadAttachment(EditTestCaseRequest request, MultipartFile file) {
TestCaseWithBLOBs testCaseWithBLOBs = testCaseMapper.selectByPrimaryKey(request.getId());
if (testCaseWithBLOBs == null) {
MSException.throwException(Translator.get("test_case_attachment_upload_not_found") + request.getId());
}
FileAttachmentMetadata fileAttachmentMetadata = fileService.saveAttachment(file, AttachmentType.TEST_CASE.type(), request.getId());
TestCaseFile testCaseFile = new TestCaseFile();
testCaseFile.setFileId(fileAttachmentMetadata.getId());
testCaseFile.setCaseId(request.getId());
testCaseFileMapper.insert(testCaseFile);
}
public void deleteAttachment(String id) {
// 删除附件记录, 目录下附件文件
if (StringUtils.isNotEmpty(id)) {
List<String> ids = Arrays.asList(id);
fileService.deleteAttachment(ids);
fileService.deleteFileAttachmentByIds(ids);
//删除用例文件关联记录
TestCaseFileExample testCaseFileExample = new TestCaseFileExample();
testCaseFileExample.createCriteria().andFileIdIn(ids);
testCaseFileMapper.deleteByExample(testCaseFileExample);
}
}
public String editTestCase(EditTestCaseRequest request, List<MultipartFile> files) { public String editTestCase(EditTestCaseRequest request, List<MultipartFile> files) {
String testCaseId = testPlanTestCaseMapper.selectByPrimaryKey(request.getId()).getCaseId(); String testCaseId = testPlanTestCaseMapper.selectByPrimaryKey(request.getId()).getCaseId();
request.setId(testCaseId); request.setId(testCaseId);

View File

@ -34,6 +34,9 @@ not_authorized=not authorized.
login_fail=Login fail login_fail=Login fail
user_apikey_limit=Can have up to 5 api keys user_apikey_limit=Can have up to 5 api keys
please_logout_current_user=Please logout current user first please_logout_current_user=Please logout current user first
#attachment upload
test_case_attachment_upload_not_found=Unable to upload attachment, no associated test case found
issues_attachment_upload_not_found=Unable to upload attachment, no associated issue found
#load test #load test
edit_load_test_not_found=Cannot edit test, test not found= edit_load_test_not_found=Cannot edit test, test not found=
run_load_test_not_found=Cannot run test, test not found= run_load_test_not_found=Cannot run test, test not found=

View File

@ -34,6 +34,9 @@ user_expires=用户过期
not_authorized=未经授权 not_authorized=未经授权
user_apikey_limit=最多能有5个Api key user_apikey_limit=最多能有5个Api key
please_logout_current_user=请先登出当前用户 please_logout_current_user=请先登出当前用户
#attachment upload
test_case_attachment_upload_not_found=无法上传附件,未找到相关联用例:
issues_attachment_upload_not_found=无法上传附件,未找到相关联缺陷:
#load test #load test
edit_load_test_not_found=无法编辑测试,未找到测试: edit_load_test_not_found=无法编辑测试,未找到测试:
run_load_test_not_found=无法运行测试,未找到测试: run_load_test_not_found=无法运行测试,未找到测试:

View File

@ -34,6 +34,9 @@ user_expires=用戶過期
not_authorized=未經授權 not_authorized=未經授權
user_apikey_limit=最多能有5個Api key user_apikey_limit=最多能有5個Api key
please_logout_current_user=請先登出當前用戶 please_logout_current_user=請先登出當前用戶
#attachment upload
test_case_attachment_upload_not_found=無法上傳附件,未找到相關用例:
issues_attachment_upload_not_found=無法上傳附件,未找到相關缺陷:
#load test #load test
edit_load_test_not_found=無法編輯測試,未找到測試: edit_load_test_not_found=無法編輯測試,未找到測試:
run_load_test_not_found=無法運行測試,未找到測試: run_load_test_not_found=無法運行測試,未找到測試:

View File

@ -9,12 +9,12 @@
<template v-slot:default="scope"> <template v-slot:default="scope">
<el-tooltip class="item" effect="dark" :content="scope.row.name" placement="top"> <el-tooltip class="item" effect="dark" :content="scope.row.name" placement="top">
<el-progress <el-progress
:color="scope.row.percentage >= 100 ? '' : uploadProgressColor" :color="scope.row.progress >= 100 ? '' : uploadProgressColor"
type="line" type="line"
:format="clearPercentage(scope.row)" :format="clearPercentage(scope.row)"
:stroke-width="40" :stroke-width="40"
:text-inside="true" :text-inside="true"
:percentage="scope.row.percentage >= 100 ? 100 : scope.row.percentage" :percentage="scope.row.progress >= 100 ? 100 : scope.row.progress"
></el-progress> ></el-progress>
</el-tooltip> </el-tooltip>
</template> </template>
@ -37,7 +37,7 @@
:width="70" :width="70"
:label="$t('commons.status')"> :label="$t('commons.status')">
<template v-slot:default="scope"> <template v-slot:default="scope">
<span :class="scope.row.status === '完成' ? 'green' : scope.row.status === '失败' ? 'red' : ''">{{ scope.row.status | formatProgressPercentage}}</span> <span :class="scope.row.status === 'success' ? 'green' : scope.row.status === 'error' ? 'red' : ''">{{ scope.row.status | formatStatus}}</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column <el-table-column
@ -50,17 +50,18 @@
:label="$t('commons.operating')"> :label="$t('commons.operating')">
<template v-slot:default="scope"> <template v-slot:default="scope">
<el-button @click="preview(scope.row)" :disabled="!scope.row.id" type="primary" <el-button @click="preview(scope.row)" :disabled="!scope.row.id" type="primary"
v-if="scope.row.percentage === 100 && isPreview(scope.row)" v-if="scope.row.progress === 100 && isPreview(scope.row)"
icon="el-icon-view" size="mini" circle/> icon="el-icon-view" size="mini" circle/>
<el-button @click="handleDownload(scope.row)" type="primary" :disabled="!scope.row.id" <el-button @click="handleDownload(scope.row)" type="primary" :disabled="!scope.row.id"
v-if="scope.row.percentage === 100" v-if="scope.row.progress === 100"
icon="el-icon-download" size="mini" circle/> icon="el-icon-download" size="mini" circle/>
<el-button :disabled="readOnly || !isDelete || isCopy" @click="handleDelete(scope.row, scope.$index)" type="danger" <el-button :disabled="readOnly || !isDelete || isCopy || !scope.row.id"
v-if="scope.row.percentage === 100" @click="handleDelete(scope.row, scope.$index)" type="danger"
v-if="scope.row.progress === 100"
icon="el-icon-delete" size="mini" icon="el-icon-delete" size="mini"
circle/> circle/>
<el-button :disabled="readOnly || !isDelete" @click="handleCancel(scope.row, scope.$index)" type="danger" <el-button :disabled="readOnly || !isDelete" @click="handleCancel(scope.row, scope.$index)" type="danger"
v-if="scope.row.percentage < 100" v-if="scope.row.progress < 100"
icon="el-icon-close" size="mini" icon="el-icon-close" size="mini"
circle/> circle/>
</template> </template>
@ -152,11 +153,11 @@ export default {
}, },
}, },
filters: { filters: {
formatProgressPercentage(percentage) { formatStatus(status) {
if (isNaN(percentage)) { if (isNaN(status)) {
return percentage return status === 'success' ? '完成' : '失败'
} }
return Math.floor(percentage * 100 / 100) + "%"; return Math.floor(status * 100 / 100) + "%";
} }
} }
} }

View File

@ -829,24 +829,6 @@ export default {
}, },
getOption(param) { getOption(param) {
let formData = new FormData(); let formData = new FormData();
if (this.$refs.otherInfo && this.$refs.otherInfo.uploadList) {
this.$refs.otherInfo.uploadList.forEach(f => {
formData.append("file", f);
});
}
if (this.$refs.otherInfo && this.$refs.otherInfo.fileList) {
if (param.isCopy) {
// copyID
param.fileIds = this.$refs.otherInfo.fileList.map(f => f.id);
}
param.updatedFileList = this.$refs.otherInfo.fileList;
} else {
param.fileIds = [];
param.updatedFileList = [];
}
param.handleAttachment = this.isClickAttachmentTab;
let requestJson = JSON.stringify(param, function (key, value) { let requestJson = JSON.stringify(param, function (key, value) {
return key === "file" ? undefined : value return key === "file" ? undefined : value
}); });

View File

@ -57,17 +57,19 @@
<el-row> <el-row>
<el-col :span="22"> <el-col :span="22">
<el-upload <el-upload
accept=".jpg,.jpeg,.png,.xlsx,.doc,.pdf,.docx,.txt,.json,.jmx,.side,.mp4,.mov,.dcm,.zip,.rar" multiple
action="#" :limit="8"
action=""
:auto-upload="true"
:file-list="fileList"
:show-file-list="false" :show-file-list="false"
:before-upload="beforeUpload" :before-upload="beforeUpload"
:http-request="handleUpload" :http-request="handleUpload"
:on-exceed="handleExceed" :on-exceed="handleExceed"
multiple :on-success="handleSuccess"
:limit="8" :on-error="handleError"
:disabled="readOnly && isTestPlanEdit" :disabled="(readOnly && isTestPlanEdit) || type === 'add' || isCopy">
:file-list="fileList"> <el-button :disabled="(readOnly && isTestPlanEdit) || type === 'add' || isCopy" type="primary" size="mini">{{$t('test_track.case.add_attachment')}}</el-button>
<el-button :disabled="readOnly && isTestPlanEdit" type="primary" size="mini">{{$t('test_track.case.add_attachment')}}</el-button>
<span slot="tip" class="el-upload__tip"> {{ $t('test_track.case.upload_tip') }} </span> <span slot="tip" class="el-upload__tip"> {{ $t('test_track.case.upload_tip') }} </span>
</el-upload> </el-upload>
</el-col> </el-col>
@ -130,8 +132,10 @@ import TabPaneCount from "@/business/components/track/plan/view/comonents/report
import {getRelationshipCountCase} from "@/network/testCase"; import {getRelationshipCountCase} from "@/network/testCase";
import TestCaseComment from "@/business/components/track/case/components/TestCaseComment"; import TestCaseComment from "@/business/components/track/case/components/TestCaseComment";
import ReviewCommentItem from "@/business/components/track/review/commom/ReviewCommentItem"; import ReviewCommentItem from "@/business/components/track/review/commom/ReviewCommentItem";
import {byteToSize} from "@/common/js/utils"; import {byteToSize, getTypeByFileName, hasLicense} from "@/common/js/utils";
import {TokenKey} from "@/common/js/constants"; import {TokenKey} from "@/common/js/constants";
import axios from "axios";
import {validateAndSetLicense} from "@/business/permission";
export default { export default {
name: "TestCaseEditOtherInfo", name: "TestCaseEditOtherInfo",
@ -151,7 +155,6 @@ export default {
return { return {
result: {}, result: {},
tabActiveName: "remark", tabActiveName: "remark",
uploadList: [],
fileList: [], fileList: [],
tableData: [], tableData: [],
demandOptions: [], demandOptions: [],
@ -163,7 +166,8 @@ export default {
//lazy: true, //lazy: true,
//lazyLoad:this.lazyLoad //lazyLoad:this.lazyLoad
}, },
intervalMap: new Map() intervalMap: new Map(),
cancelFileToken: [],
}; };
}, },
computed: { computed: {
@ -227,12 +231,11 @@ export default {
this.tabActiveName = "remark"; this.tabActiveName = "remark";
}, },
fileValidator(file) { fileValidator(file) {
/// todo: return file.size < 500 * 1024 * 1024;
return file.size > 0;
}, },
beforeUpload(file) { beforeUpload(file) {
if (!this.fileValidator(file)) { if (!this.fileValidator(file)) {
/// todo: this.$error(this.$t('load_test.file_size_out_of_bounds') + file.name);
return false; return false;
} }
@ -240,22 +243,84 @@ export default {
this.$error(this.$t('load_test.delete_file') + ', name: ' + file.name); this.$error(this.$t('load_test.delete_file') + ', name: ' + file.name);
return false; return false;
} }
},
handleUpload(e) {
//
let file = e.file;
let user = JSON.parse(localStorage.getItem(TokenKey)); let user = JSON.parse(localStorage.getItem(TokenKey));
this.tableData.push({ this.tableData.push({
name: file.name, name: file.name,
size: byteToSize(file.size), size: byteToSize(file.size),
updateTime: new Date().getTime(), updateTime: new Date().getTime(),
percentage: 0, progress: 0,
status: 0, status: 0,
creator: user.name creator: user.name,
type: getTypeByFileName(file.name)
}); });
this.handleProcess(file); //
return true; this.uploadFile(e, (param) => {
this.showProgress(e.file, param)
})
}, },
handleUpload(uploadResources) { async uploadFile(param, progressCallback) {
this.uploadList.push(uploadResources.file); let file = param.file;
let progress = 0;
let formData = new FormData();
let requestJson = JSON.stringify({"id": this.caseId});
formData.append("file", file);
formData.append('request', new Blob([requestJson], {
type: "application/json"
}));
let CancelToken = axios.CancelToken
let self = this;
axios({
headers: { 'Content-Type': 'application/json;charset=UTF-8' },
method: 'post',
url: '/test/case/attachment/upload',
data: formData,
cancelToken: new CancelToken(function executor(c) {
self.cancelFileToken.push({"name": file.name, "cancelFunc": c});
}),
onUploadProgress: progressEvent => { //
progress = (progressEvent.loaded / progressEvent.total * 100) | 0
progressCallback({ progress, status: progress })
}
}).then(response => { //
progress = 100;
param.onSuccess(response);
progressCallback({progress, status: 'success'});
}).catch(error => { //
progress = 100;
progressCallback({progress, status: 'error'});
})
},
showProgress(file, params) {
const { progress, status } = params
const arr = [...this.tableData].map(item => {
if (item.name === file.name) {
item.progress = progress
item.status = status
}
return item
})
this.tableData = [...arr]
},
handleExceed(files, fileList) {
this.$error(this.$t('load_test.file_size_limit'));
},
handleSuccess(response, file, fileList) {
let readyFiles = fileList.filter(item => item.status === 'ready')
if (readyFiles.length === 0 ) {
this.getFileMetaData();
}
},
handleError(err, file, fileList) {
let readyFiles = fileList.filter(item => item.status === 'ready')
if (readyFiles.length === 0 ) {
this.getFileMetaData();
}
}, },
handleDownload(file) { handleDownload(file) {
let data = { let data = {
@ -297,52 +362,27 @@ export default {
} }
}); });
}, },
handleCancel(file, index) {
this.fileList.splice(index, 1);
let i = this.uploadList.findIndex(upLoadFile => upLoadFile.name === file.name);
if (i > -1) {
this.uploadList.splice(i, 1);
}
let cancelFile = this.tableData.filter(f => f.name === file.name)[0];
clearInterval(this.intervalMap.get(cancelFile.name));
cancelFile.percentage = 100;
cancelFile.status = this.$t('notice.result.EXECUTE_FAILED');
},
_handleDelete(file, index) { _handleDelete(file, index) {
this.fileList.splice(index, 1); this.fileList.splice(index, 1);
this.tableData.splice(index, 1); this.tableData.splice(index, 1);
let i = this.uploadList.findIndex(upLoadFile => upLoadFile.name === file.name); this.$get('/test/case/attachment/delete/' + file.id, () => {
if (i > -1) { this.$success(this.$t('commons.delete_success'));
this.uploadList.splice(i, 1); this.getFileMetaData();
} });
}, },
handleExceed() { handleCancel(file, index) {
this.$error(this.$t('load_test.file_size_limit')); this.fileList.splice(index, 1);
}, let cancelToken = this.cancelFileToken.filter(f => f.name === file.name)[0];
handleProcess(file) { cancelToken.cancelFunc();
let currentUploadFile = this.tableData.filter(f => f.name === file.name)[0]; let cancelFile = this.tableData.filter(f => f.name === file.name)[0];
const interval = setInterval(() => { cancelFile.progress = 100;
let randomNum = Math.floor(Math.random() * 10); cancelFile.status = 'error';
if (currentUploadFile.percentage + randomNum > 100) {
clearInterval(interval)
currentUploadFile.percentage = 100;
currentUploadFile.status = this.$t('notice.result.EXECUTE_COMPLETED')
return
}
currentUploadFile.percentage += randomNum;
currentUploadFile.status += randomNum;
}, file.size > 1024 * 1024 ? 200 : 100)
this.intervalMap.set(currentUploadFile.name, interval);
}, },
getFileMetaData(id) { getFileMetaData(id) {
this.$emit("update:isClickAttachmentTab", true); this.$emit("update:isClickAttachmentTab", true);
// id // id
if (this.uploadList && this.uploadList.length > 0 && !id) {
return;
}
this.fileList = []; this.fileList = [];
this.tableData = []; this.tableData = [];
this.uploadList = [];
let testCaseId; let testCaseId;
if (this.isCopy) { if (this.isCopy) {
testCaseId = this.copyCaseId testCaseId = this.copyCaseId
@ -361,8 +401,8 @@ export default {
this.tableData = JSON.parse(JSON.stringify(files)); this.tableData = JSON.parse(JSON.stringify(files));
this.tableData.map(f => { this.tableData.map(f => {
f.size = byteToSize(f.size); f.size = byteToSize(f.size);
f.status = this.$t('notice.result.EXECUTE_COMPLETED'); f.status = 'success';
f.percentage = 100 f.progress = 100
}); });
}); });
} }

View File

@ -107,16 +107,19 @@
<el-row> <el-row>
<el-col :span="22"> <el-col :span="22">
<el-upload <el-upload
accept=".jpg,.jpeg,.png,.xlsx,.doc,.pdf,.docx,.txt,.json,.jmx,.side,.mp4,.mov,.dcm,.zip,.rar" multiple
action="#" :limit="8"
action=""
:auto-upload="true"
:file-list="fileList"
:show-file-list="false" :show-file-list="false"
:before-upload="beforeUpload" :before-upload="beforeUpload"
:http-request="handleUpload" :http-request="handleUpload"
:on-exceed="handleExceed" :on-exceed="handleExceed"
multiple :on-success="handleSuccess"
:limit="8" :on-error="handleError"
:file-list="fileList"> :disabled="type === 'add' || type === 'copy'">
<el-button type="primary" size="mini">{{$t('test_track.case.add_attachment')}}</el-button> <el-button type="primary" :disabled="type === 'add' || type === 'copy'" size="mini">{{$t('test_track.case.add_attachment')}}</el-button>
<span slot="tip" class="el-upload__tip"> {{ $t('test_track.case.upload_tip') }} </span> <span slot="tip" class="el-upload__tip"> {{ $t('test_track.case.upload_tip') }} </span>
</el-upload> </el-upload>
</el-col> </el-col>
@ -197,7 +200,7 @@ import {
getCurrentProjectID, getCurrentProjectID,
getCurrentUser, getCurrentUser,
getCurrentUserId, getCurrentUserId,
getCurrentWorkspaceId, getCurrentWorkspaceId, getTypeByFileName, hasLicense,
} from "@/common/js/utils"; } from "@/common/js/utils";
import {enableThirdPartTemplate, getIssuePartTemplateWithProject, getPlatformTransitions} from "@/network/Issue"; import {enableThirdPartTemplate, getIssuePartTemplateWithProject, getPlatformTransitions} from "@/network/Issue";
import CustomFiledFormItem from "@/business/components/common/components/form/CustomFiledFormItem"; import CustomFiledFormItem from "@/business/components/common/components/form/CustomFiledFormItem";
@ -207,6 +210,7 @@ import ReviewCommentItem from "@/business/components/track/review/commom/ReviewC
import {TokenKey} from "@/common/js/constants"; import {TokenKey} from "@/common/js/constants";
import {Message} from "element-ui"; import {Message} from "element-ui";
import TestCaseAttachment from "@/business/components/track/case/components/TestCaseAttachment"; import TestCaseAttachment from "@/business/components/track/case/components/TestCaseAttachment";
import axios from "axios";
const {getIssuesById} = require("@/network/Issue"); const {getIssuesById} = require("@/network/Issue");
@ -306,12 +310,11 @@ export default {
comments: [], comments: [],
richTextDefaultOpen: 'preview', richTextDefaultOpen: 'preview',
tabActiveName: 'relateTestCase', tabActiveName: 'relateTestCase',
uploadList: [],
fileList: [], fileList: [],
tableData: [], tableData: [],
readOnly: false, readOnly: false,
isDelete: true, isDelete: true,
intervalMap: new Map() cancelFileToken: [],
}; };
}, },
props: { props: {
@ -337,6 +340,15 @@ export default {
return enableThirdPartTemplate(this.currentProject); return enableThirdPartTemplate(this.currentProject);
}, },
}, },
watch: {
tabActiveName() {
if (this.tabActiveName === 'attachment') {
if (this.type === 'edit' && this.issueId) {
this.getFileMetaData(this.issueId);
}
}
},
},
methods: { methods: {
resetForm() { resetForm() {
this.form = { this.form = {
@ -356,12 +368,14 @@ export default {
} }
}, },
open(data, type) { open(data, type) {
this.tabActiveName = 'relateTestCase'
this.showFollow = false; this.showFollow = false;
this.result.loading = true; this.result.loading = true;
this.type = type; this.type = type;
this.richTextDefaultOpen = this.type === 'edit' ? 'preview' : 'edit'; this.richTextDefaultOpen = this.type === 'edit' ? 'preview' : 'edit';
if (this.$refs.testCaseIssueList) { if (this.$refs.testCaseIssueList) {
this.$refs.testCaseIssueList.clear(); this.$refs.testCaseIssueList.clear();
this.$refs.testCaseIssueList.isXpack = hasLicense();
} }
this.$nextTick(() => { this.$nextTick(() => {
getIssuePartTemplateWithProject((template, project) => { getIssuePartTemplateWithProject((template, project) => {
@ -440,7 +454,6 @@ export default {
initEdit(data) { initEdit(data) {
this.tableData = []; this.tableData = [];
this.fileList = []; this.fileList = [];
this.uploadList = [];
if (data) { if (data) {
Object.assign(this.form, data); Object.assign(this.form, data);
if (!(data.options instanceof Array)) { if (!(data.options instanceof Array)) {
@ -564,21 +577,6 @@ export default {
}, },
getOption(param) { getOption(param) {
let formData = new FormData(); let formData = new FormData();
if (this.uploadList) {
this.uploadList.forEach(f => {
formData.append("file", f);
});
}
if (this.fileList) {
// copyID TODO
param.updatedFileList = this.fileList;
} else {
param.fileIds = [];
param.updatedFileList = [];
}
let requestJson = JSON.stringify(param, function (key, value) { let requestJson = JSON.stringify(param, function (key, value) {
return key === "file" ? undefined : value return key === "file" ? undefined : value
}); });
@ -627,12 +625,11 @@ export default {
} }
}, },
fileValidator(file) { fileValidator(file) {
/// todo: return file.size < 500 * 1024 * 1024;
return file.size > 0;
}, },
beforeUpload(file) { beforeUpload(file) {
if (!this.fileValidator(file)) { if (!this.fileValidator(file)) {
/// todo: this.$error(this.$t('load_test.file_size_out_of_bounds') + file.name);
return false; return false;
} }
@ -640,22 +637,84 @@ export default {
this.$error(this.$t('load_test.delete_file') + ', name: ' + file.name); this.$error(this.$t('load_test.delete_file') + ', name: ' + file.name);
return false; return false;
} }
},
handleUpload(e) {
//
let file = e.file;
let user = JSON.parse(localStorage.getItem(TokenKey)); let user = JSON.parse(localStorage.getItem(TokenKey));
this.tableData.push({ this.tableData.push({
name: file.name, name: file.name,
size: byteToSize(file.size), size: byteToSize(file.size),
updateTime: new Date().getTime(), updateTime: new Date().getTime(),
percentage: 0, progress: 0,
status: 0, status: 0,
creator: user.name creator: user.name,
type: getTypeByFileName(file.name)
}); });
this.handleProcess(file); //
return true; this.uploadFile(e, (param) => {
this.showProgress(e.file, param)
})
}, },
handleUpload(uploadResources) { async uploadFile(param, progressCallback) {
this.uploadList.push(uploadResources.file); let file = param.file;
let progress = 0;
let formData = new FormData();
let requestJson = JSON.stringify({"id": this.issueId});
formData.append("file", file);
formData.append('request', new Blob([requestJson], {
type: "application/json"
}));
let CancelToken = axios.CancelToken
let self = this;
axios({
headers: { 'Content-Type': 'application/json;charset=UTF-8' },
method: 'post',
url: '/issues/attachment/upload',
data: formData,
cancelToken: new CancelToken(function executor(c) {
self.cancelFileToken.push({"name": file.name, "cancelFunc": c});
}),
onUploadProgress: progressEvent => { //
progress = (progressEvent.loaded / progressEvent.total * 100) | 0
progressCallback({ progress, status: progress })
}
}).then(response => { //
progress = 100;
param.onSuccess(response);
progressCallback({progress, status: 'success'});
}).catch(({error}) => { //
progress = 100;
progressCallback({progress, status: 'error'});
})
},
showProgress(file, params) {
const { progress, status } = params
const arr = [...this.tableData].map(item => {
if (item.name === file.name) {
item.progress = progress
item.status = status
}
return item
})
this.tableData = [...arr]
},
handleExceed(files, fileList) {
this.$error(this.$t('load_test.file_size_limit'));
},
handleSuccess(response, file, fileList) {
let readyFiles = fileList.filter(item => item.status === 'success')
if (readyFiles.length === fileList.length ) {
this.getFileMetaData(this.issueId);
}
},
handleError(err, file, fileList) {
let readyFiles = fileList.filter(item => item.status === 'success')
if (readyFiles.length === fileList.length ) {
this.getFileMetaData(this.issueId);
}
}, },
handleDownload(file) { handleDownload(file) {
let data = { let data = {
@ -697,51 +756,26 @@ export default {
} }
}); });
}, },
handleCancel(file, index) {
this.fileList.splice(index, 1);
let i = this.uploadList.findIndex(upLoadFile => upLoadFile.name === file.name);
if (i > -1) {
this.uploadList.splice(i, 1);
}
let cancelFile = this.tableData.filter(f => f.name === file.name)[0];
clearInterval(this.intervalMap.get(cancelFile.name));
cancelFile.percentage = 100;
cancelFile.status = this.$t('notice.result.EXECUTE_FAILED');
},
_handleDelete(file, index) { _handleDelete(file, index) {
this.fileList.splice(index, 1); this.fileList.splice(index, 1);
this.tableData.splice(index, 1); this.tableData.splice(index, 1);
let i = this.uploadList.findIndex(upLoadFile => upLoadFile.name === file.name); this.$get('/issues/attachment/delete/' + file.id, () => {
if (i > -1) { this.$success(this.$t('commons.delete_success'));
this.uploadList.splice(i, 1); this.getFileMetaData(this.issueId);
} });
}, },
handleExceed() { handleCancel(file, index) {
this.$error(this.$t('load_test.file_size_limit')); this.fileList.splice(index, 1);
}, let cancelToken = this.cancelFileToken.filter(f => f.name === file.name)[0];
handleProcess(file) { cancelToken.cancelFunc();
let currentUploadFile = this.tableData.filter(f => f.name === file.name)[0]; let cancelFile = this.tableData.filter(f => f.name === file.name)[0];
const interval = setInterval(() => { cancelFile.progress = 100;
let randomNum = Math.floor(Math.random() * 10); cancelFile.status = 'error';
if (currentUploadFile.percentage + randomNum > 100) {
clearInterval(interval)
currentUploadFile.percentage = 100;
currentUploadFile.status = this.$t('notice.result.EXECUTE_COMPLETED')
return
}
currentUploadFile.percentage += randomNum;
currentUploadFile.status += randomNum;
}, file.size > 1024 * 1024 ? 200 : 100)
this.intervalMap.set(currentUploadFile.name, interval);
}, },
getFileMetaData(id) { getFileMetaData(id) {
// id // id
if (this.uploadList && this.uploadList.length > 0 && !id) {
return;
}
this.fileList = []; this.fileList = [];
this.tableData = []; this.tableData = [];
this.uploadList = [];
if (id) { if (id) {
this.result = this.$get("issues/file/attachmentMetadata/" + id, response => { this.result = this.$get("issues/file/attachmentMetadata/" + id, response => {
let files = response.data; let files = response.data;
@ -753,8 +787,8 @@ export default {
this.tableData = JSON.parse(JSON.stringify(files)); this.tableData = JSON.parse(JSON.stringify(files));
this.tableData.map(f => { this.tableData.map(f => {
f.size = byteToSize(f.size); f.size = byteToSize(f.size);
f.status = this.$t('notice.result.EXECUTE_COMPLETED'); f.status = 'success';
f.percentage = 100 f.progress = 100
}); });
}); });
} }

View File

@ -47,6 +47,10 @@
prop="projectName"> prop="projectName">
</ms-table-column> </ms-table-column>
<ms-table-column v-if="isXpack"
:label="$t('commons.version')"
prop="versionName">
</ms-table-column>
</ms-table> </ms-table>
<test-case-relate-list <test-case-relate-list
@ -64,6 +68,7 @@ import MsTableColumn from "@/business/components/common/components/table/MsTable
import PriorityTableItem from "@/business/components/track/common/tableItems/planview/PriorityTableItem"; import PriorityTableItem from "@/business/components/track/common/tableItems/planview/PriorityTableItem";
import TypeTableItem from "@/business/components/track/common/tableItems/planview/TypeTableItem"; import TypeTableItem from "@/business/components/track/common/tableItems/planview/TypeTableItem";
import TestCaseRelateList from "@/business/components/track/issue/TestCaseRelateList"; import TestCaseRelateList from "@/business/components/track/issue/TestCaseRelateList";
import {hasLicense} from "@/common/js/utils";
export default { export default {
name: "TestCaseIssueList", name: "TestCaseIssueList",
components: {TestCaseRelateList, TypeTableItem, PriorityTableItem, MsTableColumn, MsTable}, components: {TestCaseRelateList, TypeTableItem, PriorityTableItem, MsTableColumn, MsTable},
@ -80,6 +85,7 @@ export default {
exec: this.handleDelete exec: this.handleDelete
} }
], ],
isXpack: false,
}; };
}, },
props: { props: {

View File

@ -589,3 +589,13 @@ export function byteToSize(bytes) {
return (bytes / Math.pow(k, i)).toPrecision(3) + ' ' + sizes[i]; return (bytes / Math.pow(k, i)).toPrecision(3) + ' ' + sizes[i];
} }
export function getTypeByFileName(filename) {
if (filename === '') {
return '';
}
let type = filename.substr(filename.lastIndexOf('.') + 1);
return type.toUpperCase();
}

View File

@ -1034,6 +1034,7 @@ export default {
upload_type: 'Only JMX/CSV/JAR files can be uploaded', upload_type: 'Only JMX/CSV/JAR files can be uploaded',
related_file_not_found: "No related test file found!", related_file_not_found: "No related test file found!",
delete_file_confirm: 'Confirm delete file:', delete_file_confirm: 'Confirm delete file:',
file_size_out_of_bounds: "File size out of bounds, file name: ",
file_size_limit: "The number of files exceeds the limit", file_size_limit: "The number of files exceeds the limit",
delete_file: "The file already exists, please delete the file with the same name first!", delete_file: "The file already exists, please delete the file with the same name first!",
thread_num: 'VUs:', thread_num: 'VUs:',
@ -2148,8 +2149,8 @@ export default {
cancel_relevance_project: "Disassociating the project will also cancel the associated test cases under the project", cancel_relevance_project: "Disassociating the project will also cancel the associated test cases under the project",
img_loading_fail: "Image failed to load", img_loading_fail: "Image failed to load",
pdf_loading_fail: "PDF loading failed", pdf_loading_fail: "PDF loading failed",
upload_tip: "Only jpg, jpeg, png, docx, doc, pdf, xlsx, txt, json, jmx, side, mp4, mov, dcm, zip, rar files can be uploaded", upload_tip: "file size limit[0-500MB]",
add_attachment: "Add Attachment", add_attachment: "Add",
attachment: "Attachment", attachment: "Attachment",
upload_time: "Upload Time", upload_time: "Upload Time",
total: "Total Case", total: "Total Case",

View File

@ -1041,6 +1041,7 @@ export default {
related_file_not_found: "未找到关联的测试文件!", related_file_not_found: "未找到关联的测试文件!",
delete_file_confirm: '确认删除文件: ', delete_file_confirm: '确认删除文件: ',
file_size_limit: "文件个数超出限制!", file_size_limit: "文件个数超出限制!",
file_size_out_of_bounds: "文件大小超出范围, 文件名称: ",
delete_file: "文件已存在,请先删除同名文件!", delete_file: "文件已存在,请先删除同名文件!",
thread_num: '并发用户数', thread_num: '并发用户数',
input_thread_num: '请输入线程数', input_thread_num: '请输入线程数',
@ -2145,8 +2146,8 @@ export default {
cancel_relevance_project: "取消项目关联会同时取消该项目下已关联的测试用例", cancel_relevance_project: "取消项目关联会同时取消该项目下已关联的测试用例",
img_loading_fail: "图片加载失败", img_loading_fail: "图片加载失败",
pdf_loading_fail: "PDF加载失败", pdf_loading_fail: "PDF加载失败",
upload_tip: "只能上传jpg、jpeg、png、docx、doc、pdf、xlsx、txt、json、jmx、side、mp4、mov、dcm、zip、rar文件", upload_tip: "文件大小限制[0-500MB]",
add_attachment: "添加附件", add_attachment: "添加",
attachment: "附件", attachment: "附件",
upload_time: "上传时间", upload_time: "上传时间",
total: "用例总数", total: "用例总数",

View File

@ -1038,6 +1038,7 @@ export default {
related_file_not_found: "未找到關聯的測試文件!", related_file_not_found: "未找到關聯的測試文件!",
delete_file_confirm: '確認刪除文件: ', delete_file_confirm: '確認刪除文件: ',
file_size_limit: "文件個數超出限製!", file_size_limit: "文件個數超出限製!",
file_size_out_of_bounds: "文件大小超出範圍, 文件名称: ",
delete_file: "文件已存在,請先刪除同名文件!", delete_file: "文件已存在,請先刪除同名文件!",
thread_num: '並發用戶數', thread_num: '並發用戶數',
input_thread_num: '請輸入線程數', input_thread_num: '請輸入線程數',
@ -2140,8 +2141,8 @@ export default {
cancel_relevance_project: "取消項目關聯會同時取消該項目下已關聯的測試用例", cancel_relevance_project: "取消項目關聯會同時取消該項目下已關聯的測試用例",
img_loading_fail: "圖片加載失敗", img_loading_fail: "圖片加載失敗",
pdf_loading_fail: "PDF加載失敗", pdf_loading_fail: "PDF加載失敗",
upload_tip: "只能上傳jpg、jpeg、png、docx、doc、pdf、xlsx、txt、json、jmx、side、mp4、mov、dcm、zip、rar文件", upload_tip: "文件大小限制[0-500MB]",
add_attachment: "添加附件", add_attachment: "添加",
attachment: "附件", attachment: "附件",
upload_time: "上傳時間", upload_time: "上傳時間",
total: "用例總數", total: "用例總數",