fix(测试跟踪): 修复测试计划及用例评审添加缺陷关联时附件上传的问题
--bug=1015225 --user=宋昌昌 【测试跟踪】测试计划/用例评审-功能用例-添加缺陷-上传附件,报500 https://www.tapd.cn/55049933/s/1212386
This commit is contained in:
parent
008c213346
commit
47dab7999c
|
@ -28,6 +28,7 @@ import io.metersphere.track.request.testcase.IssuesUpdateRequest;
|
|||
import io.metersphere.track.service.IssuesService;
|
||||
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
|
@ -62,13 +63,13 @@ public class IssuesController {
|
|||
return PageUtils.setPageInfo(page, issuesService.relateList(request));
|
||||
}
|
||||
|
||||
@PostMapping(value = "/add")
|
||||
@PostMapping(value = "/add", consumes = {"multipart/form-data"})
|
||||
@RequiresPermissions(PermissionConstants.PROJECT_TRACK_ISSUE_READ_CREATE)
|
||||
@MsAuditLog(module = OperLogModule.TRACK_BUG, type = OperLogConstants.CREATE, content = "#msClass.getLogDetails(#issuesRequest)", msClass = IssuesService.class)
|
||||
@SendNotice(taskType = NoticeConstants.TaskType.DEFECT_TASK, target = "#issuesRequest",
|
||||
event = NoticeConstants.Event.CREATE, subject = "缺陷通知")
|
||||
public IssuesWithBLOBs addIssues(@RequestPart(value = "request") IssuesUpdateRequest issuesRequest) {
|
||||
return issuesService.addIssues(issuesRequest);
|
||||
public IssuesWithBLOBs addIssues(@RequestPart(value = "request") IssuesUpdateRequest issuesRequest, @RequestPart(value = "file", required = false) List<MultipartFile> files) {
|
||||
return issuesService.addIssues(issuesRequest, files);
|
||||
}
|
||||
|
||||
@PostMapping(value = "/update")
|
||||
|
|
|
@ -210,14 +210,14 @@ public class TestCaseController {
|
|||
@MsAuditLog(module = OperLogModule.TRACK_TEST_CASE, type = OperLogConstants.CREATE, title = "#request.name", content = "#msClass.getLogDetails(#request.id)", msClass = TestCaseService.class)
|
||||
@SendNotice(taskType = NoticeConstants.TaskType.TRACK_TEST_CASE_TASK, targetClass = TestCaseMapper.class,
|
||||
event = NoticeConstants.Event.CREATE, subject = "测试用例通知")
|
||||
public TestCase addTestCase(@RequestPart("request") EditTestCaseRequest request) {
|
||||
public TestCase addTestCase(@RequestPart("request") EditTestCaseRequest request, @RequestPart(value = "file", required = false) List<MultipartFile> files) {
|
||||
if (StringUtils.isBlank(request.getId())) {
|
||||
//新增 后端生成 id
|
||||
request.setId(UUID.randomUUID().toString());
|
||||
} else {
|
||||
//复制,前端生成 id
|
||||
}
|
||||
return testCaseService.add(request);
|
||||
return testCaseService.add(request, files);
|
||||
}
|
||||
|
||||
@PostMapping("/edit/order")
|
||||
|
|
|
@ -41,6 +41,7 @@ import org.springframework.context.annotation.Lazy;
|
|||
import org.springframework.data.redis.core.StringRedisTemplate;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.*;
|
||||
|
@ -104,7 +105,7 @@ public class IssuesService {
|
|||
}
|
||||
|
||||
|
||||
public IssuesWithBLOBs addIssues(IssuesUpdateRequest issuesRequest) {
|
||||
public IssuesWithBLOBs addIssues(IssuesUpdateRequest issuesRequest, List<MultipartFile> files) {
|
||||
List<AbstractIssuePlatform> platformList = getAddPlatforms(issuesRequest);
|
||||
IssuesWithBLOBs issues = null;
|
||||
for (AbstractIssuePlatform platform : platformList) {
|
||||
|
@ -118,13 +119,22 @@ public class IssuesService {
|
|||
saveFollows(issuesRequest.getId(), issuesRequest.getFollows());
|
||||
customFieldIssuesService.addFields(issuesRequest.getId(), issuesRequest.getAddFields());
|
||||
customFieldIssuesService.editFields(issuesRequest.getId(), issuesRequest.getEditFields());
|
||||
// 复制新增, 同步缺陷的MS附件
|
||||
if (StringUtils.isNotEmpty(issuesRequest.getCopyIssueId())) {
|
||||
// 复制新增, 同步缺陷的MS附件
|
||||
AttachmentRequest attachmentRequest = new AttachmentRequest();
|
||||
attachmentRequest.setCopyBelongId(issuesRequest.getCopyIssueId());
|
||||
attachmentRequest.setBelongId(issues.getId());
|
||||
attachmentRequest.setBelongType(AttachmentType.ISSUE.type());
|
||||
attachmentService.copyAttachment(attachmentRequest);
|
||||
} else {
|
||||
// 新增, 需保存并同步所有待上传的附件
|
||||
final String issueId = issues.getId();
|
||||
files.forEach(file -> {
|
||||
AttachmentRequest attachmentRequest = new AttachmentRequest();
|
||||
attachmentRequest.setBelongId(issueId);
|
||||
attachmentRequest.setBelongType(AttachmentType.ISSUE.type());
|
||||
attachmentService.uploadAttachment(attachmentRequest, file);
|
||||
});
|
||||
}
|
||||
return issues;
|
||||
}
|
||||
|
|
|
@ -1957,15 +1957,23 @@ public class TestCaseService {
|
|||
return false;
|
||||
}
|
||||
|
||||
public TestCase add(EditTestCaseRequest request) {
|
||||
public TestCase add(EditTestCaseRequest request, List<MultipartFile> files) {
|
||||
final TestCaseWithBLOBs testCaseWithBLOBs = addTestCase(request);
|
||||
// 复制用例时复制对应附件数据
|
||||
if (StringUtils.isNotEmpty(request.getCopyCaseId())) {
|
||||
// 复制用例时复制对应附件数据
|
||||
AttachmentRequest attachmentRequest = new AttachmentRequest();
|
||||
attachmentRequest.setCopyBelongId(request.getCopyCaseId());
|
||||
attachmentRequest.setBelongId(testCaseWithBLOBs.getId());
|
||||
attachmentRequest.setBelongType(AttachmentType.TEST_CASE.type());
|
||||
attachmentService.copyAttachment(attachmentRequest);
|
||||
} else {
|
||||
// 新增需上传用例所有待上传的附件
|
||||
files.forEach(file -> {
|
||||
AttachmentRequest attachmentRequest = new AttachmentRequest();
|
||||
attachmentRequest.setBelongId(testCaseWithBLOBs.getId());
|
||||
attachmentRequest.setBelongType(AttachmentType.TEST_CASE.type());
|
||||
attachmentService.uploadAttachment(attachmentRequest, file);
|
||||
});
|
||||
}
|
||||
return testCaseWithBLOBs;
|
||||
}
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
:width="70"
|
||||
:label="$t('commons.status')">
|
||||
<template v-slot:default="scope">
|
||||
<span :class="scope.row.status === 'success' ? 'green' : scope.row.status === 'error' ? 'red' : ''">{{ scope.row.status | formatStatus}}</span>
|
||||
<span :class="scope.row.status === 'success' ? 'green' : scope.row.status === 'error' ? 'red' : scope.row.status === 'toUpload' ? 'yellow' : ''">{{ scope.row.status | formatStatus}}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
|
@ -55,7 +55,7 @@
|
|||
<el-button @click="handleDownload(scope.row)" type="primary" :disabled="!scope.row.id"
|
||||
v-if="scope.row.progress === 100"
|
||||
icon="el-icon-download" size="mini" circle/>
|
||||
<el-button :disabled="readOnly || !isDelete || isCopy || !scope.row.id"
|
||||
<el-button :disabled="readOnly || !isDelete || isCopy || (!scope.row.id && scope.row.status !== 'toUpload')"
|
||||
@click="handleDelete(scope.row, scope.$index)" type="danger"
|
||||
v-if="scope.row.progress === 100"
|
||||
icon="el-icon-delete" size="mini"
|
||||
|
@ -132,7 +132,7 @@ export default {
|
|||
filters: {
|
||||
formatStatus(status) {
|
||||
if (isNaN(status)) {
|
||||
return status === 'success' ? '完成' : '失败'
|
||||
return status === 'success' ? '完成' : status === 'toUpload' ? '待上传' : '失败'
|
||||
}
|
||||
return Math.floor(status * 100 / 100) + "%";
|
||||
}
|
||||
|
@ -165,4 +165,8 @@ export default {
|
|||
.red {
|
||||
color: red;
|
||||
}
|
||||
|
||||
.yellow {
|
||||
color: #E6A23C;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -832,6 +832,11 @@ export default {
|
|||
return key === "file" ? undefined : value
|
||||
});
|
||||
|
||||
if (this.$refs.otherInfo.uploadFiles.length > 0) {
|
||||
this.$refs.otherInfo.uploadFiles.forEach(f => {
|
||||
formData.append("file", f);
|
||||
});
|
||||
}
|
||||
formData.append('request', new Blob([requestJson], {
|
||||
type: "application/json"
|
||||
}));
|
||||
|
|
|
@ -73,8 +73,8 @@
|
|||
:on-exceed="handleExceed"
|
||||
:on-success="handleSuccess"
|
||||
:on-error="handleError"
|
||||
:disabled="(readOnly && isTestPlanEdit) || type === 'add' || isCopy">
|
||||
<el-button :disabled="(readOnly && isTestPlanEdit) || type === 'add' || isCopy" type="primary" size="mini">{{$t('test_track.case.add_attachment')}}</el-button>
|
||||
:disabled="(readOnly && isTestPlanEdit) || isCopy">
|
||||
<el-button :disabled="(readOnly && isTestPlanEdit) || isCopy" 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>
|
||||
</el-upload>
|
||||
</el-col>
|
||||
|
@ -174,6 +174,7 @@ export default {
|
|||
},
|
||||
intervalMap: new Map(),
|
||||
cancelFileToken: [],
|
||||
uploadFiles: []
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
|
@ -258,12 +259,17 @@ export default {
|
|||
name: file.name,
|
||||
size: byteToSize(file.size),
|
||||
updateTime: new Date().getTime(),
|
||||
progress: 0,
|
||||
status: 0,
|
||||
progress: this.type === 'add' ? 100 : 0,
|
||||
status: this.type === 'add' ? 'toUpload' : 0,
|
||||
creator: user.name,
|
||||
type: getTypeByFileName(file.name)
|
||||
});
|
||||
|
||||
if (this.type === 'add') {
|
||||
// 新增上传
|
||||
this.uploadFiles.push(file);
|
||||
return false;
|
||||
}
|
||||
// 上传文件
|
||||
this.uploadFile(e, (param) => {
|
||||
this.showProgress(e.file, param)
|
||||
|
@ -358,10 +364,14 @@ export default {
|
|||
}
|
||||
this.fileList.splice(index, 1);
|
||||
this.tableData.splice(index, 1);
|
||||
this.$get('/attachment/delete/testcase/' + file.id , response => {
|
||||
this.$success(this.$t('commons.delete_success'));
|
||||
this.getFileMetaData();
|
||||
});
|
||||
if (this.type === 'add') {
|
||||
this.uploadFiles.splice(index, 1);
|
||||
} else {
|
||||
this.$get('/attachment/delete/testcase/' + file.id , response => {
|
||||
this.$success(this.$t('commons.delete_success'));
|
||||
this.getFileMetaData();
|
||||
});
|
||||
}
|
||||
},
|
||||
handleCancel(file, index) {
|
||||
this.fileList.splice(index, 1);
|
||||
|
|
|
@ -115,8 +115,8 @@
|
|||
:on-exceed="handleExceed"
|
||||
:on-success="handleSuccess"
|
||||
:on-error="handleError"
|
||||
:disabled="type === 'add' || type === 'copy' || isCaseEdit">
|
||||
<el-button type="primary" :disabled="type === 'add' || type === 'copy' || isCaseEdit" size="mini">{{$t('test_track.case.add_attachment')}}</el-button>
|
||||
:disabled="type === 'copy'">
|
||||
<el-button type="primary" :disabled="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>
|
||||
</el-upload>
|
||||
</el-col>
|
||||
|
@ -308,6 +308,7 @@ export default {
|
|||
readOnly: false,
|
||||
isDelete: true,
|
||||
cancelFileToken: [],
|
||||
uploadFiles: []
|
||||
};
|
||||
},
|
||||
props: {
|
||||
|
@ -574,9 +575,15 @@ export default {
|
|||
return key === "file" ? undefined : value
|
||||
});
|
||||
|
||||
if (this.uploadFiles.length > 0) {
|
||||
this.uploadFiles.forEach(f => {
|
||||
formData.append("file", f);
|
||||
});
|
||||
}
|
||||
formData.append('request', new Blob([requestJson], {
|
||||
type: "application/json"
|
||||
}));
|
||||
|
||||
return {
|
||||
method: 'POST',
|
||||
url: this.url,
|
||||
|
@ -639,13 +646,17 @@ export default {
|
|||
name: file.name,
|
||||
size: byteToSize(file.size),
|
||||
updateTime: new Date().getTime(),
|
||||
progress: 0,
|
||||
status: 0,
|
||||
progress: this.type === 'add' || this.isCaseEdit? 100 : 0,
|
||||
status: this.type === 'add' || this.isCaseEdit? 'toUpload' : 0,
|
||||
creator: user.name,
|
||||
type: getTypeByFileName(file.name)
|
||||
});
|
||||
|
||||
// 上传文件
|
||||
if (this.type === 'add' || this.isCaseEdit) {
|
||||
// 新增上传
|
||||
this.uploadFiles.push(file);
|
||||
return false;
|
||||
}
|
||||
this.uploadFile(e, (param) => {
|
||||
this.showProgress(e.file, param)
|
||||
})
|
||||
|
@ -739,11 +750,14 @@ export default {
|
|||
}
|
||||
this.fileList.splice(index, 1);
|
||||
this.tableData.splice(index, 1);
|
||||
let data = {"belongId": this.issueId, "belongType": "issue"}
|
||||
this.$get('/attachment/delete/issue/' + file.id , response => {
|
||||
this.$success(this.$t('commons.delete_success'));
|
||||
this.getFileMetaData(this.issueId);
|
||||
});
|
||||
if (this.type === 'add' || this.isCaseEdit) {
|
||||
this.uploadFiles.splice(index, 1);
|
||||
} else {
|
||||
this.$get('/attachment/delete/issue/' + file.id , response => {
|
||||
this.$success(this.$t('commons.delete_success'));
|
||||
this.getFileMetaData(this.issueId);
|
||||
});
|
||||
}
|
||||
},
|
||||
handleCancel(file, index) {
|
||||
this.fileList.splice(index, 1);
|
||||
|
|
Loading…
Reference in New Issue