feat: 富文本删除imageIds扩展&替换预览url
This commit is contained in:
parent
a9da9a7a59
commit
336a3ee47c
|
@ -26,7 +26,7 @@
|
|||
<MsComment
|
||||
:upload-image="handleUploadImage"
|
||||
:comment-list="commentList"
|
||||
:preview-url="PreviewEditorImageUrl"
|
||||
:preview-url="`${PreviewEditorImageUrl}/${appStore.currentProjectId}`"
|
||||
@delete="handleDelete"
|
||||
@update-or-add="handleUpdateOrAdd"
|
||||
/>
|
||||
|
@ -40,7 +40,7 @@
|
|||
v-model:notice-user-ids="noticeUserIds"
|
||||
v-model:filed-ids="uploadFileIds"
|
||||
v-permission="['FUNCTIONAL_CASE:READ+COMMENT']"
|
||||
:preview-url="PreviewEditorImageUrl"
|
||||
:preview-url="`${PreviewEditorImageUrl}/${appStore.currentProjectId}`"
|
||||
:is-active="isActive"
|
||||
is-show-avatar
|
||||
is-use-bottom
|
||||
|
@ -72,6 +72,7 @@
|
|||
import { PreviewEditorImageUrl } from '@/api/requrls/case-management/featureCase';
|
||||
import { useI18n } from '@/hooks/useI18n';
|
||||
import useModal from '@/hooks/useModal';
|
||||
import { useAppStore } from '@/store';
|
||||
import { hasAnyPermission } from '@/utils/permission';
|
||||
|
||||
const props = defineProps<{
|
||||
|
@ -80,6 +81,7 @@
|
|||
|
||||
const { t } = useI18n();
|
||||
const { openModal } = useModal();
|
||||
const appStore = useAppStore();
|
||||
|
||||
const hasEditPermission = hasAnyPermission(['FUNCTIONAL_CASE:READ+COMMENT']);
|
||||
|
||||
|
|
|
@ -120,8 +120,7 @@
|
|||
}
|
||||
const uploadFileId = await props.uploadImage(arg.file);
|
||||
if (uploadFileId) {
|
||||
const infoId = route.query.orgId && route.query.pId ? route.query.pId : route.query.orgId;
|
||||
const permanentUrl = `${props.previewUrl}/${infoId}/${uploadFileId}/${true}`;
|
||||
const permanentUrl = `${props.previewUrl}/${uploadFileId}/${true}`;
|
||||
arg.process(permanentUrl, uploadFileId);
|
||||
}
|
||||
}
|
||||
|
@ -154,6 +153,12 @@
|
|||
const selectedImagesNode = ref<string>();
|
||||
const selectedCommentNode = ref<string>();
|
||||
|
||||
// TODO deletedImagesIds 为解决后台富文本附件删除图片时,后台服务器也删除,目前不确定这个版本要不要替换,等后台协调
|
||||
const previousImages = ref<string[]>([]);
|
||||
const deletedImagesIds = ref<string[]>([]);
|
||||
const addedImages = ref(new Set());
|
||||
const removedImages = ref(new Set());
|
||||
|
||||
onMounted(() => {
|
||||
const debounceOnUpdate = useDebounceFn(() => {
|
||||
const html = `${editor.value?.getHTML()}`;
|
||||
|
@ -215,6 +220,33 @@
|
|||
// eslint-disable-next-line prefer-destructuring
|
||||
selectedImagesNode.value = images[0];
|
||||
}
|
||||
|
||||
const currentImagesSet = new Set(images);
|
||||
|
||||
// 检查被删除的图片
|
||||
const deletedImages = previousImages.value.filter((fileId) => !currentImagesSet.has(fileId));
|
||||
deletedImages.forEach((id) => {
|
||||
if (!deletedImagesIds.value.includes(id)) {
|
||||
deletedImagesIds.value.push(id);
|
||||
removedImages.value.add(id);
|
||||
}
|
||||
});
|
||||
|
||||
// 检查被添加的图片(包含撤销删除则从删除里边移除掉)
|
||||
const addedImagesNow = (images || []).filter((fileId) => !previousImages.value.includes(fileId));
|
||||
addedImagesNow.forEach((id: string) => {
|
||||
if (deletedImagesIds.value.includes(id)) {
|
||||
const index = deletedImagesIds.value.indexOf(id);
|
||||
if (index > -1) {
|
||||
deletedImagesIds.value.splice(index, 1);
|
||||
removedImages.value.delete(id);
|
||||
}
|
||||
}
|
||||
addedImages.value.add(id);
|
||||
});
|
||||
|
||||
previousImages.value = images;
|
||||
|
||||
return DecorationSet.empty;
|
||||
},
|
||||
},
|
||||
|
|
|
@ -174,7 +174,7 @@
|
|||
is-show-avatar
|
||||
:upload-image="handleUploadImage"
|
||||
is-use-bottom
|
||||
:preview-url="EditorPreviewFileUrl"
|
||||
:preview-url="`${EditorPreviewFileUrl}/${appStore.currentProjectId}`"
|
||||
@publish="publishHandler"
|
||||
/>
|
||||
</template>
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
:disabled="!contentEditAble"
|
||||
:placeholder="t('editor.placeholder')"
|
||||
:upload-image="handleUploadImage"
|
||||
:preview-url="EditorPreviewFileUrl"
|
||||
:preview-url="`${EditorPreviewFileUrl}/${appStore.currentProjectId}`"
|
||||
/>
|
||||
<div v-else v-dompurify-html="form?.description || '-'" class="markdown-body"></div>
|
||||
</div>
|
||||
|
@ -52,7 +52,7 @@
|
|||
:auto-height="false"
|
||||
:placeholder="t('editor.placeholder')"
|
||||
:upload-image="handleUploadImage"
|
||||
:preview-url="EditorPreviewFileUrl"
|
||||
:preview-url="`${EditorPreviewFileUrl}/${appStore.currentProjectId}`"
|
||||
/>
|
||||
<div v-else v-dompurify-html="item?.defaultValue || '-'" class="markdown-body"></div>
|
||||
</div>
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<MsEmpty v-if="commentList.length === 0" />
|
||||
<MsComment
|
||||
v-else
|
||||
:preview-url="EditorPreviewFileUrl"
|
||||
:preview-url="`${EditorPreviewFileUrl}/${appStore.currentProjectId}`"
|
||||
:comment-list="commentList"
|
||||
:upload-image="handleUploadImage"
|
||||
:permissions="['PROJECT_BUG:READ+COMMENT']"
|
||||
|
@ -27,6 +27,7 @@
|
|||
import { EditorPreviewFileUrl } from '@/api/requrls/bug-management';
|
||||
import { useI18n } from '@/hooks/useI18n';
|
||||
import useModal from '@/hooks/useModal';
|
||||
import { useAppStore } from '@/store';
|
||||
|
||||
import message from '@arco-design/web-vue/es/message';
|
||||
|
||||
|
@ -36,6 +37,7 @@
|
|||
bugId: string;
|
||||
}>();
|
||||
const { t } = useI18n();
|
||||
const appStore = useAppStore();
|
||||
|
||||
const commentList = ref<CommentItem[]>([]);
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
v-model:raw="form.description"
|
||||
v-model:filed-ids="descriptionFileIds"
|
||||
:upload-image="handleUploadImage"
|
||||
:preview-url="EditorPreviewFileUrl"
|
||||
:preview-url="`${EditorPreviewFileUrl}/${appStore.currentProjectId}`"
|
||||
/>
|
||||
</a-form-item>
|
||||
<!-- 平台默认模板展示字段, 暂时支持输入框, 富文本类型 -->
|
||||
|
@ -61,7 +61,7 @@
|
|||
v-model:raw="form.platformSystemFields[key]"
|
||||
v-model:filed-ids="descriptionFileIdMap[key]"
|
||||
:upload-image="handleUploadImage"
|
||||
:preview-url="EditorPreviewFileUrl"
|
||||
:preview-url="`${EditorPreviewFileUrl}/${appStore.currentProjectId}`"
|
||||
/>
|
||||
</a-form-item>
|
||||
</div>
|
||||
|
|
|
@ -178,7 +178,7 @@
|
|||
title: 'system.orgTemplate.operation',
|
||||
slotName: 'operation',
|
||||
fixed: 'right',
|
||||
width: 200,
|
||||
width: 120,
|
||||
showInTable: true,
|
||||
showDrag: false,
|
||||
},
|
||||
|
|
|
@ -147,7 +147,7 @@
|
|||
v-model:notice-user-ids="noticeUserIds"
|
||||
v-model:filed-ids="uploadFileIds"
|
||||
v-permission="['FUNCTIONAL_CASE:READ+COMMENT']"
|
||||
:preview-url="PreviewEditorImageUrl"
|
||||
:preview-url="`${PreviewEditorImageUrl}/${currentProjectId}`"
|
||||
:is-active="isActive"
|
||||
is-show-avatar
|
||||
is-use-bottom
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
v-model:raw="form.prerequisite"
|
||||
v-model:filed-ids="prerequisiteFileIds"
|
||||
:upload-image="handleUploadImage"
|
||||
:preview-url="PreviewEditorImageUrl"
|
||||
:preview-url="`${PreviewEditorImageUrl}/${currentProjectId}`"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
|
@ -57,7 +57,7 @@
|
|||
v-model:raw="form.textDescription"
|
||||
v-model:filed-ids="textDescriptionFileIds"
|
||||
:upload-image="handleUploadImage"
|
||||
:preview-url="PreviewEditorImageUrl"
|
||||
:preview-url="`${PreviewEditorImageUrl}/${currentProjectId}`"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
|
@ -69,7 +69,7 @@
|
|||
v-model:raw="form.expectedResult"
|
||||
v-model:filed-ids="expectedResultFileIds"
|
||||
:upload-image="handleUploadImage"
|
||||
:preview-url="PreviewEditorImageUrl"
|
||||
:preview-url="`${PreviewEditorImageUrl}/${currentProjectId}`"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item field="description" :label="t('caseManagement.featureCase.remark')">
|
||||
|
@ -77,7 +77,7 @@
|
|||
v-model:raw="form.description"
|
||||
v-model:filed-ids="descriptionFileIds"
|
||||
:upload-image="handleUploadImage"
|
||||
:preview-url="PreviewEditorImageUrl"
|
||||
:preview-url="`${PreviewEditorImageUrl}/${currentProjectId}`"
|
||||
/>
|
||||
</a-form-item>
|
||||
<AddAttachment v-model:file-list="fileList" multiple @change="handleChange" @link-file="associatedFile" />
|
||||
|
@ -545,6 +545,24 @@
|
|||
}
|
||||
|
||||
const checkUpdateFileIds = ref<string[]>([]);
|
||||
// 前置操作附件id
|
||||
const prerequisiteFileIds = ref<string[]>([]);
|
||||
// 文本描述附件id
|
||||
const textDescriptionFileIds = ref<string[]>([]);
|
||||
// 预期结果附件id
|
||||
const expectedResultFileIds = ref<string[]>([]);
|
||||
// 描述附件id
|
||||
const descriptionFileIds = ref<string[]>([]);
|
||||
|
||||
// 所有附近文件id
|
||||
const allAttachmentsFileIds = computed(() => {
|
||||
return [
|
||||
...prerequisiteFileIds.value,
|
||||
...textDescriptionFileIds.value,
|
||||
...expectedResultFileIds.value,
|
||||
...descriptionFileIds.value,
|
||||
];
|
||||
});
|
||||
|
||||
// 处理详情字段
|
||||
function getDetailData(detailResult: DetailCase) {
|
||||
|
@ -557,6 +575,7 @@
|
|||
|
||||
form.value = {
|
||||
...detailResult,
|
||||
caseDetailFileIds: allAttachmentsFileIds.value,
|
||||
name: route.params.mode === 'copy' ? copyName : detailResult.name,
|
||||
};
|
||||
// 处理自定义字段
|
||||
|
@ -650,7 +669,7 @@
|
|||
(val) => {
|
||||
if (val) {
|
||||
if (val) {
|
||||
params.value.request = { ...form.value };
|
||||
params.value.request = { ...form.value, caseDetailFileIds: allAttachmentsFileIds.value };
|
||||
emit('update:formModeValue', params.value);
|
||||
}
|
||||
}
|
||||
|
@ -751,31 +770,10 @@
|
|||
}
|
||||
}
|
||||
|
||||
// 前置操作附件id
|
||||
const prerequisiteFileIds = ref<string[]>([]);
|
||||
// 文本描述附件id
|
||||
const textDescriptionFileIds = ref<string[]>([]);
|
||||
// 预期结果附件id
|
||||
const expectedResultFileIds = ref<string[]>([]);
|
||||
// 描述附件id
|
||||
const descriptionFileIds = ref<string[]>([]);
|
||||
|
||||
// 所有附近文件id
|
||||
const allAttachmentsFileIds = computed(() => {
|
||||
return [
|
||||
...prerequisiteFileIds.value,
|
||||
...textDescriptionFileIds.value,
|
||||
...expectedResultFileIds.value,
|
||||
...descriptionFileIds.value,
|
||||
];
|
||||
});
|
||||
|
||||
watch(
|
||||
() => allAttachmentsFileIds.value,
|
||||
(val) => {
|
||||
if (val) {
|
||||
params.value.request.caseDetailFileIds = val;
|
||||
}
|
||||
params.value.request.caseDetailFileIds = val;
|
||||
}
|
||||
);
|
||||
|
||||
|
|
|
@ -43,7 +43,7 @@
|
|||
<MsRichText
|
||||
v-model:raw="form.description"
|
||||
:upload-image="handleUploadImage"
|
||||
:preview-url="EditorPreviewFileUrl"
|
||||
:preview-url="`${EditorPreviewFileUrl}/${appStore.currentProjectId}`"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
v-model:raw="detailForm.prerequisite"
|
||||
v-model:filed-ids="prerequisiteFileIds"
|
||||
:upload-image="handleUploadImage"
|
||||
:preview-url="PreviewEditorImageUrl"
|
||||
:preview-url="`${PreviewEditorImageUrl}/${currentProjectId}`"
|
||||
class="mt-2"
|
||||
/>
|
||||
|
||||
|
@ -77,7 +77,7 @@
|
|||
v-model:raw="detailForm.textDescription"
|
||||
v-model:filed-ids="textDescriptionFileIds"
|
||||
:upload-image="handleUploadImage"
|
||||
:preview-url="PreviewEditorImageUrl"
|
||||
:preview-url="`${PreviewEditorImageUrl}/${currentProjectId}`"
|
||||
/>
|
||||
<div
|
||||
v-if="detailForm.caseEditType === 'TEXT' && !isEditPreposition"
|
||||
|
@ -95,7 +95,7 @@
|
|||
v-model:raw="detailForm.expectedResult"
|
||||
v-model:filed-ids="expectedResultFileIds"
|
||||
:upload-image="handleUploadImage"
|
||||
:preview-url="PreviewEditorImageUrl"
|
||||
:preview-url="`${PreviewEditorImageUrl}/${currentProjectId}`"
|
||||
/>
|
||||
<div
|
||||
v-else
|
||||
|
@ -109,7 +109,7 @@
|
|||
v-model:filed-ids="descriptionFileIds"
|
||||
v-model:raw="detailForm.description"
|
||||
:upload-image="handleUploadImage"
|
||||
:preview-url="PreviewEditorImageUrl"
|
||||
:preview-url="`${PreviewEditorImageUrl}/${currentProjectId}`"
|
||||
/>
|
||||
<div v-else v-dompurify-html="detailForm.description || '-'" class="markdown-body !break-words break-all"></div>
|
||||
</a-form-item>
|
||||
|
|
|
@ -248,7 +248,7 @@
|
|||
v-model:filed-ids="reviewCommentFileIds"
|
||||
:upload-image="handleUploadImage"
|
||||
:auto-height="false"
|
||||
:preview-url="PreviewEditorImageUrl"
|
||||
:preview-url="`${PreviewEditorImageUrl}/${appStore.currentProjectId}`"
|
||||
class="w-full"
|
||||
/>
|
||||
</div>
|
||||
|
|
|
@ -74,7 +74,7 @@
|
|||
v-model:filed-ids="caseResultForm.fileList"
|
||||
:auto-height="false"
|
||||
:upload-image="handleUploadImage"
|
||||
:preview-url="PreviewEditorImageUrl"
|
||||
:preview-url="`${PreviewEditorImageUrl}/${appStore.currentProjectId}`"
|
||||
class="w-full"
|
||||
/>
|
||||
</a-modal>
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
v-model:commentIds="form.notifiers"
|
||||
v-model:filedIds="form.reviewCommentFileIds"
|
||||
:upload-image="handleUploadImage"
|
||||
:preview-url="PreviewEditorImageUrl"
|
||||
:preview-url="`${PreviewEditorImageUrl}/${appStore.currentProjectId}`"
|
||||
:auto-height="false"
|
||||
class="w-full"
|
||||
:placeholder="
|
||||
|
@ -35,6 +35,7 @@
|
|||
import { editorUploadFile } from '@/api/modules/case-management/featureCase';
|
||||
import { PreviewEditorImageUrl } from '@/api/requrls/case-management/featureCase';
|
||||
import { useI18n } from '@/hooks/useI18n';
|
||||
import { useAppStore } from '@/store';
|
||||
|
||||
import { ReviewFormParams } from '@/models/caseManagement/caseReview';
|
||||
import { StartReviewStatus } from '@/enums/caseEnum';
|
||||
|
@ -48,7 +49,7 @@
|
|||
});
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
const appStore = useAppStore();
|
||||
async function handleUploadImage(file: File) {
|
||||
const { data } = await editorUploadFile({
|
||||
fileList: [file],
|
||||
|
|
|
@ -99,12 +99,14 @@
|
|||
import { previewOrgImageUrl, previewProImageUrl } from '@/api/requrls/setting/template';
|
||||
import { defaultTemplateCaseDetail } from '@/config/template';
|
||||
import { useI18n } from '@/hooks/useI18n';
|
||||
import useAppStore from '@/store/modules/app';
|
||||
import { getGenerateId } from '@/utils';
|
||||
|
||||
import type { StepList } from '@/models/caseManagement/featureCase';
|
||||
import type { defaultCaseField } from '@/models/setting/template';
|
||||
|
||||
const { t } = useI18n();
|
||||
const appStore = useAppStore();
|
||||
|
||||
const props = defineProps<{
|
||||
mode: 'organization' | 'project';
|
||||
|
@ -193,7 +195,9 @@
|
|||
}
|
||||
|
||||
const previewEditorImageUrl = computed(() =>
|
||||
props.mode === 'organization' ? previewOrgImageUrl : previewProImageUrl
|
||||
props.mode === 'organization'
|
||||
? `${previewOrgImageUrl}/${appStore.currentOrgId}`
|
||||
: `${previewProImageUrl}/${appStore.currentProjectId}`
|
||||
);
|
||||
|
||||
const fileIds = computed(() => {
|
||||
|
|
|
@ -38,9 +38,12 @@
|
|||
import { previewOrgImageUrl, previewProImageUrl } from '@/api/requrls/setting/template';
|
||||
import { defaultTemplateBugDetail } from '@/config/template';
|
||||
import { useI18n } from '@/hooks/useI18n';
|
||||
import useAppStore from '@/store/modules/app';
|
||||
|
||||
import type { defaultBugField } from '@/models/setting/template';
|
||||
|
||||
const appStore = useAppStore();
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
const props = defineProps<{
|
||||
|
@ -73,7 +76,9 @@
|
|||
}
|
||||
|
||||
const previewEditorImageUrl = computed(() =>
|
||||
props.mode === 'organization' ? previewOrgImageUrl : previewProImageUrl
|
||||
props.mode === 'organization'
|
||||
? `${previewOrgImageUrl}/${appStore.currentOrgId}`
|
||||
: `${previewProImageUrl}/${appStore.currentProjectId}`
|
||||
);
|
||||
|
||||
watch(
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
v-model:raw="innerTextForm.content"
|
||||
v-model:filedIds="innerTextForm.richTextTmpFileIds"
|
||||
:upload-image="handleUploadImage"
|
||||
:preview-url="ReportPlanPreviewImageUrl"
|
||||
:preview-url="`${ReportPlanPreviewImageUrl}/${appStore.currentProjectId}`"
|
||||
class="mt-[8px] w-full"
|
||||
:editable="props.canEdit"
|
||||
@click="handleRichClick"
|
||||
|
@ -48,12 +48,13 @@
|
|||
import { editorUploadFile } from '@/api/modules/test-plan/report';
|
||||
import { ReportPlanPreviewImageUrl } from '@/api/requrls/test-plan/report';
|
||||
import { useI18n } from '@/hooks/useI18n';
|
||||
import { useAppStore } from '@/store';
|
||||
import { hasAnyPermission } from '@/utils/permission';
|
||||
|
||||
import { customValueForm } from '@/models/testPlan/testPlanReport';
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
const appStore = useAppStore();
|
||||
const props = defineProps<{
|
||||
customForm: customValueForm;
|
||||
canEdit: boolean;
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
v-model:raw="innerSummary.content"
|
||||
v-model:filedIds="innerSummary.richTextTmpFileIds"
|
||||
:upload-image="handleUploadImage"
|
||||
:preview-url="ReportPlanPreviewImageUrl"
|
||||
:preview-url="`${ReportPlanPreviewImageUrl}/${appStore.currentProjectId}`"
|
||||
class="mt-[8px] w-full"
|
||||
:editable="props.canEdit"
|
||||
@click="handleRichClick"
|
||||
|
@ -35,6 +35,7 @@
|
|||
import { editorUploadFile } from '@/api/modules/test-plan/report';
|
||||
import { ReportPlanPreviewImageUrl } from '@/api/requrls/test-plan/report';
|
||||
import { useI18n } from '@/hooks/useI18n';
|
||||
import { useAppStore } from '@/store';
|
||||
import { hasAnyPermission } from '@/utils/permission';
|
||||
|
||||
import type { customValueForm, PlanReportDetail } from '@/models/testPlan/testPlanReport';
|
||||
|
@ -42,6 +43,8 @@
|
|||
import { getSummaryDetail } from '@/views/test-plan/report/utils';
|
||||
|
||||
const { t } = useI18n();
|
||||
const appStore = useAppStore();
|
||||
|
||||
const props = defineProps<{
|
||||
richText: customValueForm;
|
||||
shareId?: string;
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
v-model:commentIds="form.commentIds"
|
||||
v-model:filedIds="form.planCommentFileIds"
|
||||
:upload-image="handleUploadImage"
|
||||
:preview-url="PreviewEditorImageUrl"
|
||||
:preview-url="`${PreviewEditorImageUrl}/${appStore.currentProjectId}`"
|
||||
:auto-height="false"
|
||||
class="w-full"
|
||||
:max-height="props.richTextMaxHeight"
|
||||
|
@ -37,6 +37,7 @@
|
|||
import { PreviewEditorImageUrl } from '@/api/requrls/case-management/featureCase';
|
||||
import { defaultExecuteForm } from '@/config/testPlan';
|
||||
import { useI18n } from '@/hooks/useI18n';
|
||||
import { useAppStore } from '@/store';
|
||||
|
||||
import type { ExecuteFeatureCaseFormParams } from '@/models/testPlan/testPlan';
|
||||
import { LastExecuteResults } from '@/enums/caseEnum';
|
||||
|
@ -53,6 +54,7 @@
|
|||
});
|
||||
|
||||
const { t } = useI18n();
|
||||
const appStore = useAppStore();
|
||||
|
||||
const executionResultList = computed(() =>
|
||||
Object.values(executionResultMap).filter((item) => item.key !== LastExecuteResults.PENDING)
|
||||
|
|
Loading…
Reference in New Issue