feat: 富文本删除imageIds扩展&替换预览url

This commit is contained in:
xinxin.wu 2024-08-08 13:46:54 +08:00 committed by Craftsman
parent a9da9a7a59
commit 336a3ee47c
19 changed files with 104 additions and 54 deletions

View File

@ -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']);

View File

@ -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;
},
},

View File

@ -174,7 +174,7 @@
is-show-avatar
:upload-image="handleUploadImage"
is-use-bottom
:preview-url="EditorPreviewFileUrl"
:preview-url="`${EditorPreviewFileUrl}/${appStore.currentProjectId}`"
@publish="publishHandler"
/>
</template>

View File

@ -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>

View File

@ -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[]>([]);

View File

@ -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>

View File

@ -178,7 +178,7 @@
title: 'system.orgTemplate.operation',
slotName: 'operation',
fixed: 'right',
width: 200,
width: 120,
showInTable: true,
showDrag: false,
},

View File

@ -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

View File

@ -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;
}
);

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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],

View 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(() => {

View File

@ -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(

View File

@ -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;

View File

@ -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;

View File

@ -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)