fix(缺陷管理): 富文本图片同步问题

This commit is contained in:
song-cc-rock 2024-03-19 19:26:35 +08:00 committed by Craftsman
parent 921d77bf48
commit a3aad0b82c
5 changed files with 40 additions and 17 deletions

View File

@ -3,6 +3,7 @@ package io.metersphere.plugin.platform.dto.reponse;
import lombok.Data;
import java.util.List;
import java.util.Map;
@Data
public class PlatformBugDTO extends MsSyncBugDTO {
@ -22,7 +23,9 @@ public class PlatformBugDTO extends MsSyncBugDTO {
private List<PlatformCustomFieldItemDTO> needSyncCustomFields;
/**
* 缺陷同步需要下载的第三方富文本图片文件Key
* 缺陷同步需要下载的第三方富文本图片{key: name}
* key: 唯一文件流获取的ID
* name: 文件名称
*/
private List<String> richTextImageKeys;
private Map<String, String> richTextImageMap;
}

View File

@ -2,6 +2,7 @@ package io.metersphere.plugin.platform.dto.reponse;
import lombok.Data;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@ -42,6 +43,6 @@ public class PlatformDemandDTO {
/**
* 自定义字段
*/
private Map<String, Object> customFields;
private Map<String, Object> customFields = new HashMap<>();
}
}

View File

@ -103,8 +103,6 @@ public class BugService {
@Resource
protected TemplateMapper templateMapper;
@Resource
private BugCommentMapper bugCommentMapper;
@Resource
private BugContentMapper bugContentMapper;
@Resource
private SqlSessionFactory sqlSessionFactory;
@ -1257,25 +1255,25 @@ public class BugService {
* @param platform 平台对象
*/
private void syncRichTextToMs(PlatformBugDTO updateBug, Platform platform) {
if (CollectionUtils.isNotEmpty(updateBug.getRichTextImageKeys())) {
if (MapUtils.isNotEmpty(updateBug.getRichTextImageMap())) {
Map<String, String> richTextImageMap = updateBug.getRichTextImageMap();
// 同步第三方的富文本文件
updateBug.getRichTextImageKeys().forEach(key -> platform.getAttachmentContent(key, (in) -> {
richTextImageMap.keySet().forEach(key -> platform.getAttachmentContent(key, (in) -> {
if (in == null) {
return;
}
String fileId = IDGenerator.nextStr();
// 第三方平台的图片下载命名为平台名称+随机数字
String fileName = updateBug.getPlatform() + "-" + IDGenerator.nextNum() + ".jpg";
String fileName = updateBug.getPlatform() + "-" + richTextImageMap.get(key);
byte[] bytes;
try {
// upload platform attachment to minio
// 获取第三方平台附件流
bytes = in.readAllBytes();
// 第三方平台下载的图片默认不压缩
FileCenter.getDefaultRepository().saveFile(bytes, buildBugFileRequest(updateBug.getProjectId(), updateBug.getId(), fileId, fileName));
} catch (Exception e) {
throw new MSException(e.getMessage());
}
// save bug attachment relation
// 保存缺陷附件关系
BugLocalAttachment localAttachment = new BugLocalAttachment();
localAttachment.setId(IDGenerator.nextStr());
localAttachment.setBugId(updateBug.getId());
@ -1286,7 +1284,7 @@ public class BugService {
localAttachment.setCreateUser("admin");
localAttachment.setSource(BugAttachmentSourceType.RICH_TEXT.name());
bugLocalAttachmentMapper.insert(localAttachment);
// 替换富文本中的临时URL为预览URL
// 替换富文本中的临时URL, 注意: 第三方的图片附件暂未存储在压缩目录, 因此不支持压缩访问
updateBug.setDescription(updateBug.getDescription().replace("alt=\"" + key + "\"", "src=\"/bug/attachment/preview/md/" + updateBug.getProjectId() + "/" + fileId + "/false\""));
}));
}

View File

@ -2,7 +2,6 @@ import { markRaw } from 'vue';
import ImageView from './ImageView.vue';
import { PreviewEditorImageUrl } from '@/api/requrls/case-management/featureCase';
import { useI18n } from '@/hooks/useI18n';
import type { ExtensionOptions, NodeBubbleMenu } from '../../types';
@ -13,9 +12,9 @@ import {
EditorState,
isActive,
mergeAttributes,
ToolboxItem,
VueNodeViewRenderer,
} from '@halo-dev/richtext-editor';
import { ToolboxItem } from '@halo-dev/richtext-editor';
import type { ImageOptions } from '@tiptap/extension-image';
import TiptapImage from '@tiptap/extension-image';
@ -102,6 +101,18 @@ const Image = TiptapImage.extend<ExtensionOptions & ImageOptions>({
};
},
},
// 第三方平台链接, 富文本双向同步时需要
psrc: {
default: undefined,
parseHTML: (element) => {
return element.getAttribute('psrc') || null;
},
renderHTML: (attributes) => {
return {
psrc: attributes.psrc,
};
},
},
};
},

View File

@ -120,6 +120,7 @@
</template>
<script lang="ts" setup>
import { computed } from 'vue';
import { FormInstance, Message } from '@arco-design/web-vue';
import MsDrawer from '@/components/pure/ms-drawer/index.vue';
@ -134,6 +135,7 @@
} from '@/api/modules/project-management/menuManagement';
import { useI18n } from '@/hooks/useI18n';
import { useAppStore } from '@/store';
import useLicenseStore from '@/store/modules/setting/license';
import { PoolOption, SelectValue } from '@/models/projectManagement/menuManagement';
import { MenuEnum } from '@/enums/commonEnum';
@ -158,6 +160,7 @@
]);
const appStore = useAppStore();
const licenseStore = useLicenseStore();
const currentProjectId = computed(() => appStore.currentProjectId);
const currentOrgId = computed(() => appStore.currentOrgId);
const platformDisabled = computed(() => platformOption.value.length === 0);
@ -175,6 +178,9 @@
});
const okDisabled = computed(() => !form.PLATFORM_KEY);
const isXpack = computed(() => {
return licenseStore.hasLicense();
});
const fApi = ref<any>({});
const emit = defineEmits<{
@ -255,7 +261,11 @@
await handlePlatformChange(res.platform_key);
form.SYNC_ENABLE = res.sync_enable;
form.PLATFORM_KEY = res.platform_key;
if (!isXpack.value) {
form.MECHANISM = 'increment';
} else {
form.MECHANISM = res.mechanism;
}
form.CRON_EXPRESSION = res.cron_expression;
}
} catch (e) {