fix(缺陷管理): 富文本图片同步问题
This commit is contained in:
parent
1c6d4a64aa
commit
364d8c9a18
|
@ -2,6 +2,8 @@ package io.metersphere.plugin.platform.dto.reponse;
|
|||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@Data
|
||||
public class PlatformBugUpdateDTO {
|
||||
|
||||
|
@ -25,4 +27,8 @@ public class PlatformBugUpdateDTO {
|
|||
* 平台描述
|
||||
*/
|
||||
private String platformDescription;
|
||||
/**
|
||||
* 平台自定义字段值
|
||||
*/
|
||||
private Map<String, String> platformCustomFieldMap;
|
||||
}
|
||||
|
|
|
@ -327,7 +327,7 @@ public class BugAttachmentService {
|
|||
try {
|
||||
// upload platform attachment to minio
|
||||
bytes = in.readAllBytes();
|
||||
FileCenter.getDefaultRepository().saveFile(bytes, buildBugFileRequest(projectId, bugId, fileId, fileName));
|
||||
FileCenter.getDefaultRepository().saveFile(bytes, buildBugFileRequest(projectId, bugId, fileId, fileName, false));
|
||||
} catch (Exception e) {
|
||||
throw new MSException(e.getMessage());
|
||||
}
|
||||
|
@ -382,7 +382,7 @@ public class BugAttachmentService {
|
|||
deleteLocalIds.forEach(deleteLocalId -> {
|
||||
try {
|
||||
BugFileDTO bugFileDTO = localFileMap.get(deleteLocalId);
|
||||
FileCenter.getDefaultRepository().delete(buildBugFileRequest(projectId, bugId, bugFileDTO.getFileId(), bugFileDTO.getFileName()));
|
||||
FileCenter.getDefaultRepository().delete(buildBugFileRequest(projectId, bugId, bugFileDTO.getFileId(), bugFileDTO.getFileName(), false));
|
||||
} catch (Exception e) {
|
||||
throw new MSException(e.getMessage());
|
||||
}
|
||||
|
@ -406,7 +406,7 @@ public class BugAttachmentService {
|
|||
* @return 文件字节流
|
||||
*/
|
||||
public byte[] getLocalFileBytes(BugLocalAttachment attachment, String projectId, String bugId) {
|
||||
FileRequest fileRequest = buildBugFileRequest(projectId, bugId, attachment.getFileId(), attachment.getFileName());
|
||||
FileRequest fileRequest = buildBugFileRequest(projectId, bugId, attachment.getFileId(), attachment.getFileName(), false);
|
||||
byte[] bytes;
|
||||
try {
|
||||
bytes = fileService.download(fileRequest);
|
||||
|
@ -477,7 +477,7 @@ public class BugAttachmentService {
|
|||
record.setCreateUser(currentUser);
|
||||
bugLocalAttachmentMapper.insert(record);
|
||||
List<SyncAttachmentToPlatformRequest> localSyncFiles = new ArrayList<>();
|
||||
FileRequest fileRequest = buildBugFileRequest(projectId, bugId, record.getFileId(), file.getOriginalFilename());
|
||||
FileRequest fileRequest = buildBugFileRequest(projectId, bugId, record.getFileId(), file.getOriginalFilename(), false);
|
||||
try {
|
||||
fileService.upload(file, fileRequest);
|
||||
if (!StringUtils.equals(platformName, BugPlatform.LOCAL.getName())) {
|
||||
|
@ -534,7 +534,7 @@ public class BugAttachmentService {
|
|||
List<SyncAttachmentToPlatformRequest> syncLocalFiles = new ArrayList<>();
|
||||
BugLocalAttachment localAttachment = bugLocalAttachmentMapper.selectByPrimaryKey(refId);
|
||||
// 删除本地上传的附件, BUG_LOCAL_ATTACHMENT表
|
||||
FileRequest fileRequest = buildBugFileRequest(projectId, bugId, localAttachment.getFileId(), localAttachment.getFileName());
|
||||
FileRequest fileRequest = buildBugFileRequest(projectId, bugId, localAttachment.getFileId(), localAttachment.getFileName(), false);
|
||||
try {
|
||||
// 删除MINIO附件
|
||||
fileService.deleteFile(fileRequest);
|
||||
|
@ -586,11 +586,16 @@ public class BugAttachmentService {
|
|||
* @param resourceId 资源ID
|
||||
* @param fileId 文件ID
|
||||
* @param fileName 文件名称
|
||||
* @param compress 是否压缩预览目录
|
||||
* @return 文件请求对象
|
||||
*/
|
||||
private FileRequest buildBugFileRequest(String projectId, String resourceId, String fileId, String fileName) {
|
||||
private FileRequest buildBugFileRequest(String projectId, String resourceId, String fileId, String fileName, boolean compress) {
|
||||
FileRequest fileRequest = new FileRequest();
|
||||
fileRequest.setFolder(DefaultRepositoryDir.getBugDir(projectId, resourceId) + "/" + fileId);
|
||||
if (compress) {
|
||||
fileRequest.setFolder(DefaultRepositoryDir.getBugPreviewDir(projectId, resourceId) + "/" + fileId);
|
||||
} else {
|
||||
fileRequest.setFolder(DefaultRepositoryDir.getBugDir(projectId, resourceId) + "/" + fileId);
|
||||
}
|
||||
fileRequest.setFileName(StringUtils.isEmpty(fileName) ? null : fileName);
|
||||
fileRequest.setStorage(StorageType.MINIO.name());
|
||||
return fileRequest;
|
||||
|
@ -763,14 +768,7 @@ public class BugAttachmentService {
|
|||
//在正式目录获取
|
||||
BugLocalAttachment attachment = bugAttachments.get(0);
|
||||
fileName = attachment.getFileName();
|
||||
FileRequest fileRequest = new FileRequest();
|
||||
fileRequest.setFileName(attachment.getFileName());
|
||||
if (compressed) {
|
||||
fileRequest.setFolder(DefaultRepositoryDir.getBugPreviewDir(projectId, attachment.getBugId()) + "/" + attachment.getFileId());
|
||||
} else {
|
||||
fileRequest.setFolder(DefaultRepositoryDir.getBugDir(projectId, attachment.getBugId()) + "/" + attachment.getFileId());
|
||||
}
|
||||
fileRequest.setStorage(StorageType.MINIO.name());
|
||||
FileRequest fileRequest = buildBugFileRequest(projectId, attachment.getBugId(), attachment.getFileId(), attachment.getFileName(), compressed);
|
||||
try {
|
||||
bytes = fileService.download(fileRequest);
|
||||
} catch (Exception e) {
|
||||
|
|
|
@ -27,6 +27,9 @@ public class BugPlatformService {
|
|||
public void syncAttachmentToPlatform(List<SyncAttachmentToPlatformRequest> platformAttachments, String projectId) {
|
||||
// 平台缺陷需同步附件
|
||||
Platform platform = projectApplicationService.getPlatform(projectId, true);
|
||||
if (!platform.isSupportAttachment()) {
|
||||
return;
|
||||
}
|
||||
platformAttachments.forEach(attachment -> {
|
||||
platform.syncAttachmentToPlatform(attachment);
|
||||
try {
|
||||
|
|
|
@ -17,6 +17,7 @@ import io.metersphere.plugin.platform.dto.reponse.PlatformBugDTO;
|
|||
import io.metersphere.plugin.platform.dto.reponse.PlatformBugUpdateDTO;
|
||||
import io.metersphere.plugin.platform.dto.reponse.PlatformCustomFieldItemDTO;
|
||||
import io.metersphere.plugin.platform.dto.request.*;
|
||||
import io.metersphere.plugin.platform.enums.PlatformCustomFieldType;
|
||||
import io.metersphere.plugin.platform.enums.SyncAttachmentType;
|
||||
import io.metersphere.plugin.platform.spi.Platform;
|
||||
import io.metersphere.project.domain.*;
|
||||
|
@ -227,7 +228,7 @@ public class BugService {
|
|||
// 处理基础字段
|
||||
Bug bug = handleAndSaveBug(request, currentUser, platformName, platformBug);
|
||||
// 处理自定义字段
|
||||
handleAndSaveCustomFields(request, isUpdate);
|
||||
handleAndSaveCustomFields(request, isUpdate, platformBug);
|
||||
// 处理附件
|
||||
handleAndSaveAttachments(request, files, currentUser, platformName, platformBug);
|
||||
// 处理富文本临时文件
|
||||
|
@ -639,7 +640,7 @@ public class BugService {
|
|||
return bugCustomFieldDTO;
|
||||
}).collect(Collectors.toList());
|
||||
customEditRequest.setCustomFields(bugCustomFieldDTOList);
|
||||
handleAndSaveCustomFields(customEditRequest, true);
|
||||
handleAndSaveCustomFields(customEditRequest, true, null);
|
||||
});
|
||||
|
||||
// 批量删除缺陷
|
||||
|
@ -879,7 +880,7 @@ public class BugService {
|
|||
*
|
||||
* @param request 请求参数
|
||||
*/
|
||||
public void handleAndSaveCustomFields(BugEditRequest request, boolean merge) {
|
||||
public void handleAndSaveCustomFields(BugEditRequest request, boolean merge, PlatformBugUpdateDTO platformBug) {
|
||||
// 处理ID, 值的映射关系
|
||||
Map<String, String> customFieldMap = request.getCustomFields().stream()
|
||||
.filter(f -> StringUtils.isNotBlank(f.getId()))
|
||||
|
@ -887,6 +888,11 @@ public class BugService {
|
|||
if (MapUtils.isEmpty(customFieldMap)) {
|
||||
return;
|
||||
}
|
||||
// 拦截, 如果平台返回结果存在自定义字段值, 替换
|
||||
if (platformBug != null && MapUtils.isNotEmpty(platformBug.getPlatformCustomFieldMap())) {
|
||||
Map<String, String> platformCustomFieldMap = platformBug.getPlatformCustomFieldMap();
|
||||
platformCustomFieldMap.keySet().forEach(key -> customFieldMap.put(key, platformCustomFieldMap.get(key)));
|
||||
}
|
||||
List<BugCustomField> addFields = new ArrayList<>();
|
||||
List<BugCustomField> updateFields = new ArrayList<>();
|
||||
if (merge) {
|
||||
|
@ -1285,7 +1291,20 @@ public class BugService {
|
|||
localAttachment.setSource(BugAttachmentSourceType.RICH_TEXT.name());
|
||||
bugLocalAttachmentMapper.insert(localAttachment);
|
||||
// 替换富文本中的临时URL, 注意: 第三方的图片附件暂未存储在压缩目录, 因此不支持压缩访问
|
||||
updateBug.setDescription(updateBug.getDescription().replace("alt=\"" + key + "\"", "src=\"/bug/attachment/preview/md/" + updateBug.getProjectId() + "/" + fileId + "/false\""));
|
||||
if (StringUtils.contains(updateBug.getDescription(), "alt=\"" + key + "\"")) {
|
||||
updateBug.setDescription(updateBug.getDescription()
|
||||
.replace("alt=\"" + key + "\"", "src=\"/bug/attachment/preview/md/" + updateBug.getProjectId() + "/" + fileId + "/false\""));
|
||||
if (updateBug.getPlatformDefaultTemplate()) {
|
||||
// 来自富文本自定义字段
|
||||
PlatformCustomFieldItemDTO descriptionField = updateBug.getCustomFieldList().stream().filter(field -> StringUtils.equals(field.getCustomData(), "description")).toList().get(0);
|
||||
descriptionField.setValue(updateBug.getDescription());
|
||||
}
|
||||
} else {
|
||||
// 来自富文本自定义字段
|
||||
PlatformCustomFieldItemDTO richTextField = updateBug.getCustomFieldList().stream().filter(field -> StringUtils.equals(field.getType(), PlatformCustomFieldType.RICH_TEXT.name())
|
||||
&& field.getValue() != null && StringUtils.contains(field.getValue().toString(), "alt=\"" + key + "\"")).toList().get(0);
|
||||
richTextField.setValue(richTextField.getValue().toString().replace("alt=\"" + key + "\"", "src=\"/bug/attachment/preview/md/" + updateBug.getProjectId() + "/" + fileId + "/false\""));
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -605,6 +605,7 @@ public class BugControllerTests extends BaseTest {
|
|||
summary.setType("INPUT");
|
||||
summary.setValue("这是一个系统Jira模板创建的缺陷");
|
||||
addRequest.getCustomFields().add(summary);
|
||||
addRequest.setRichTextTmpFileIds(List.of("rich-text-file-id"));
|
||||
MultiValueMap<String, Object> addParam3 = getMultiPartParam(addRequest, null);
|
||||
this.requestMultipart(BUG_ADD, addParam3).andExpect(status().is5xxServerError());
|
||||
|
||||
|
@ -612,6 +613,7 @@ public class BugControllerTests extends BaseTest {
|
|||
this.requestGetWithOk(BUG_SYNC + "/default-project-for-bug");
|
||||
|
||||
// 添加没有附件的Jira缺陷
|
||||
addRequest.setRichTextTmpFileIds(null);
|
||||
addRequest.setLinkFileIds(null);
|
||||
addRequest.setTemplateId("default-bug-template-id");
|
||||
MultiValueMap<String, Object> addParam2 = getMultiPartParam(addRequest, null);
|
||||
|
|
|
@ -47,8 +47,10 @@
|
|||
<MsRichText
|
||||
v-if="contentEditAble"
|
||||
v-model:raw="item.defaultValue"
|
||||
v-model:filed-ids="descriptionFileIdMap[item.fieldId]"
|
||||
:disabled="!contentEditAble"
|
||||
:placeholder="t('editor.placeholder')"
|
||||
:upload-image="handleUploadImage"
|
||||
:preview-url="EditorPreviewFileUrl"
|
||||
/>
|
||||
<div v-else v-dompurify-html="item?.defaultValue || '-'" class="markdown-body"></div>
|
||||
|
@ -257,6 +259,7 @@
|
|||
const acceptType = ref('none'); // 模块-上传文件类型
|
||||
// 描述-富文本临时附件ID
|
||||
const descriptionFileIds = ref<string[]>([]);
|
||||
const descriptionFileIdMap = ref<Record<string, string[]>>({});
|
||||
const imageUrl = ref<string>('');
|
||||
const associatedDrawer = ref(false);
|
||||
const fileListRef = ref<InstanceType<typeof MsFileList>>();
|
||||
|
@ -442,6 +445,16 @@
|
|||
return data;
|
||||
}
|
||||
|
||||
function getDescriptionFileId() {
|
||||
const fileIds = [] as string[];
|
||||
Object.keys(descriptionFileIdMap.value).forEach((key) => {
|
||||
if (descriptionFileIdMap.value[key].length > 0) {
|
||||
fileIds.push(...descriptionFileIdMap.value[key]);
|
||||
}
|
||||
});
|
||||
return fileIds;
|
||||
}
|
||||
|
||||
// 保存操作
|
||||
async function handleSave() {
|
||||
try {
|
||||
|
@ -481,7 +494,7 @@
|
|||
unLinkRefIds: form.value.unLinkRefIds,
|
||||
linkFileIds: form.value.linkFileIds,
|
||||
customFields,
|
||||
richTextTmpFileIds: descriptionFileIds.value,
|
||||
richTextTmpFileIds: props.isPlatformDefaultTemplate ? getDescriptionFileId() : descriptionFileIds.value,
|
||||
};
|
||||
if (!props.isPlatformDefaultTemplate) {
|
||||
tmpObj.description = form.value.description;
|
||||
|
@ -521,8 +534,6 @@
|
|||
}
|
||||
|
||||
watchEffect(() => {
|
||||
console.log(props.currentPlatform);
|
||||
console.log(props.detailInfo.platform);
|
||||
initCurrentDetail(props.detailInfo);
|
||||
});
|
||||
defineExpose({
|
||||
|
@ -552,4 +563,4 @@
|
|||
:deep(.arco-form-item-label) {
|
||||
font-weight: bold !important;
|
||||
}
|
||||
</style>
|
||||
</style>
|
|
@ -63,6 +63,9 @@
|
|||
<MsRichText
|
||||
v-if="platformSystemFieldMap[key].type === 'RICH_TEXT'"
|
||||
v-model:raw="form.platformSystemFields[key]"
|
||||
v-model:filed-ids="descriptionFileIdMap[key]"
|
||||
:upload-image="handleUploadImage"
|
||||
:preview-url="EditorPreviewFileUrl"
|
||||
/>
|
||||
</a-form-item>
|
||||
</div>
|
||||
|
@ -316,8 +319,10 @@
|
|||
const isPlatformDefaultTemplate = ref(false);
|
||||
const imageUrl = ref('');
|
||||
const previewVisible = ref<boolean>(false);
|
||||
// 描述-富文本临时附件ID
|
||||
// 内容/富文本临时附件ID
|
||||
const descriptionFileIds = ref<string[]>([]);
|
||||
// 描述-环境/富文本临时附件ID
|
||||
const descriptionFileIdMap = ref<Record<string, string[]>>({});
|
||||
const visitedKey = 'doNotNextTipCreateBug';
|
||||
const { getIsVisited } = useVisit(visitedKey);
|
||||
|
||||
|
@ -532,6 +537,16 @@
|
|||
fileList.value.push(...fileResultList);
|
||||
}
|
||||
|
||||
function getDescriptionFileId() {
|
||||
const fileIds = [] as string[];
|
||||
Object.keys(descriptionFileIdMap.value).forEach((key) => {
|
||||
if (descriptionFileIdMap.value[key].length > 0) {
|
||||
fileIds.push(...descriptionFileIdMap.value[key]);
|
||||
}
|
||||
});
|
||||
return fileIds;
|
||||
}
|
||||
|
||||
// 保存
|
||||
const saveHandler = async (isContinue = false) => {
|
||||
formRef.value.validate((error: any) => {
|
||||
|
@ -583,11 +598,12 @@
|
|||
};
|
||||
});
|
||||
}
|
||||
|
||||
const tmpObj: BugEditFormObject = {
|
||||
...form.value,
|
||||
customFields,
|
||||
copyFiles,
|
||||
richTextTmpFileIds: descriptionFileIds.value,
|
||||
richTextTmpFileIds: isPlatformDefaultTemplate.value ? getDescriptionFileId() : descriptionFileIds.value,
|
||||
};
|
||||
if (isCopy.value) {
|
||||
delete tmpObj.id;
|
||||
|
|
Loading…
Reference in New Issue