feat(测试计划): 报告-报告总结-单击聚焦编辑&保存提示

This commit is contained in:
teukkk 2024-08-05 17:34:58 +08:00 committed by 刘瑞斌
parent 366b00706e
commit 85bd5949f8
6 changed files with 59 additions and 50 deletions

View File

@ -449,6 +449,10 @@
editor.value?.destroy();
});
function focus() {
editor.value?.chain().focus();
}
const contentStyles = computed(() => {
return {
maxHeight: props.autoHeight ? '800px' : props.maxHeight || '260px',
@ -514,6 +518,10 @@
console.log(error);
}
}
defineExpose({
focus,
});
</script>
<template>

View File

@ -160,6 +160,7 @@ export default {
'common.nameNotNull': '名称不能为空',
'common.namePlaceholder': '请输入名称,按回车键保存',
'common.unsavedLeave': '有标签页的内容未保存,离开后未保存的内容将丢失,确定要离开吗?',
'common.editUnsavedLeave': '编辑内容未保存,离开后未保存的内容将丢失,确定要离开吗?',
'common.image': '图片',
'common.text': '文本',
'common.resourceDeleted': '资源已被删除',

View File

@ -96,6 +96,7 @@
</div>
<div class="config-right-container">
<ViewReport
ref="viewReportRef"
v-model:card-list="cardItemList"
:detail-info="props.detailInfo"
:is-drawer="props.isDrawer"
@ -363,6 +364,7 @@
}
const confirmLoading = ref<boolean>(false);
const viewReportRef = ref<InstanceType<typeof ViewReport>>();
//
async function handleSave() {
if (!reportForm.value.reportName) {
@ -374,6 +376,7 @@
try {
const params: manualReportGenParams = makeParams();
const reportId = await manualReportGen(params);
viewReportRef.value?.setIsSave(true);
Message.success(t('report.detail.manualGenReportSuccess'));
if (reportId) {
router.push({

View File

@ -14,17 +14,20 @@
:placeholder="t('report.detail.customTitlePlaceHolder')"
:max-length="255"
allow-clear
@change="() => emit('handleSetSave')"
@blur="blurHandler"
/>
<div :class="`${hasAnyPermission(['PROJECT_TEST_PLAN_REPORT:READ+UPDATE']) && !shareId ? '' : 'cursor-not-allowed'}`">
<MsRichText
ref="msRichTextRef"
v-model:raw="innerTextForm.content"
v-model:filedIds="innerTextForm.richTextTmpFileIds"
:upload-image="handleUploadImage"
:preview-url="ReportPlanPreviewImageUrl"
class="mt-[8px] w-full"
:editable="props.canEdit"
@click="handleClick"
@click="handleRichClick"
@update="() => emit('handleSetSave')"
/>
</div>
<div
@ -38,12 +41,12 @@
<script setup lang="ts">
import { ref } from 'vue';
import { useVModel } from '@vueuse/core';
import MsRichText from '@/components/pure/ms-rich-text/MsRichText.vue';
import { editorUploadFile } from '@/api/modules/test-plan/report';
import { ReportPlanPreviewImageUrl } from '@/api/requrls/test-plan/report';
import useDoubleClick from '@/hooks/useDoubleClick';
import { useI18n } from '@/hooks/useI18n';
import { hasAnyPermission } from '@/utils/permission';
@ -60,7 +63,8 @@
const emit = defineEmits<{
(e: 'updateCustom', formValue: customValueForm): void;
(e: 'dblclick'): void;
(e: 'handleClick'): void;
(e: 'handleSetSave'): void;
(e: 'cancel'): void;
}>();
@ -87,9 +91,11 @@
label: innerTextForm.value.label || t('report.detail.customDefaultCardName'),
});
}
function emitDoubleClick() {
const msRichTextRef = ref<InstanceType<typeof MsRichText>>();
function handleRichClick() {
if (!props.shareId) {
emit('dblclick');
msRichTextRef.value?.focus();
emit('handleClick');
}
}
@ -100,8 +106,6 @@
});
}
const { handleClick } = useDoubleClick(emitDoubleClick);
function handleCancel() {
emit('cancel');
}

View File

@ -1,22 +1,18 @@
<template>
<div :class="`${hasAnyPermission(['PROJECT_TEST_PLAN_REPORT:READ+UPDATE']) && !shareId ? '' : 'cursor-not-allowed'}`">
<MsRichText
ref="msRichTextRef"
v-model:raw="innerSummary.content"
v-model:filedIds="innerSummary.richTextTmpFileIds"
:upload-image="handleUploadImage"
:preview-url="ReportPlanPreviewImageUrl"
class="mt-[8px] w-full"
:editable="props.canEdit"
@click="handleClick"
@click="handleRichClick"
@update="emit('handleSetSave')"
/>
<MsFormItemSub
v-if="
hasAnyPermission(['PROJECT_TEST_PLAN_REPORT:READ+UPDATE']) &&
!shareId &&
props.showButton &&
props.canEdit &&
props.isPreview
"
v-if="hasAnyPermission(['PROJECT_TEST_PLAN_REPORT:READ+UPDATE']) && !shareId && props.canEdit && props.isPreview"
:text="t('report.detail.oneClickSummary')"
:show-fill-icon="true"
@fill="handleSummary"
@ -24,7 +20,7 @@
</div>
<div
v-show="props.showButton && hasAnyPermission(['PROJECT_TEST_PLAN_REPORT:READ+UPDATE']) && !shareId && props.canEdit"
v-show="hasAnyPermission(['PROJECT_TEST_PLAN_REPORT:READ+UPDATE']) && !shareId && props.canEdit"
class="mt-[16px] flex items-center gap-[12px]"
>
<a-button type="primary" @click="handleUpdateReportDetail">{{ t('common.save') }}</a-button>
@ -33,7 +29,6 @@
</template>
<script setup lang="ts">
import { ref } from 'vue';
import { useVModel } from '@vueuse/core';
import MsRichText from '@/components/pure/ms-rich-text/MsRichText.vue';
@ -41,7 +36,6 @@
import { editorUploadFile } from '@/api/modules/test-plan/report';
import { ReportPlanPreviewImageUrl } from '@/api/requrls/test-plan/report';
import useDoubleClick from '@/hooks/useDoubleClick';
import { useI18n } from '@/hooks/useI18n';
import { hasAnyPermission } from '@/utils/permission';
@ -53,7 +47,6 @@
const props = defineProps<{
richText: customValueForm;
shareId?: string;
showButton: boolean;
isPlanGroup: boolean;
detail: PlanReportDetail;
canEdit: boolean;
@ -63,7 +56,8 @@
const emit = defineEmits<{
(e: 'updateSummary', form: customValueForm): void;
(e: 'cancel'): void;
(e: 'dblclick'): void;
(e: 'handleClick'): void;
(e: 'handleSetSave'): void;
(e: 'handleSummary', content: string): void;
}>();
@ -134,12 +128,13 @@
emit('handleSummary', summaryContent.value);
}
function emitDoubleClick() {
const msRichTextRef = ref<InstanceType<typeof MsRichText>>();
function handleRichClick() {
if (!props.shareId) {
emit('dblclick');
msRichTextRef.value?.focus();
emit('handleClick');
}
}
const { handleClick } = useDoubleClick(emitDoubleClick);
</script>
<style scoped></style>

View File

@ -124,13 +124,13 @@
</SystemTrigger>
</div>
<div :class="`${props.isPreview ? 'mt-[16px]' : 'mt-[24px]'} drag-container`">
<div class="drag-container mt-[16px]">
<VueDraggable v-model="innerCardList" :disabled="props.isPreview" group="report">
<div
v-for="(item, index) of innerCardList"
v-show="showItem(item)"
:key="item.id"
:class="`${props.isPreview ? 'mt-[16px]' : 'hover-card mt-[24px]'} card-item`"
:class="`${props.isPreview ? '' : 'hover-card'} card-item mt-[16px]`"
>
<div v-if="!props.isPreview" class="action">
<div class="actionList">
@ -178,13 +178,13 @@
:share-id="shareId"
:is-preview="props.isPreview"
:can-edit="item.enableEdit"
:show-button="showButton"
:is-plan-group="props.isGroup"
:detail="detail"
@update-summary="(formValue:customValueForm) => updateCustom(formValue, item)"
@cancel="() => handleCancelCustom(item)"
@handle-summary="(value:string) => handleSummary(value,item)"
@dblclick="handleDoubleClick(item)"
@handle-click="handleClick(item)"
@handle-set-save="setIsSave(false)"
/>
<BugTable
v-else-if="item.value === ReportCardTypeEnum.BUG_DETAIL"
@ -222,8 +222,9 @@
richTextTmpFileIds: [],
}"
@update-custom="(formValue:customValueForm)=>updateCustom(formValue,item)"
@dblclick="handleDoubleClick(item)"
@handle-click="handleClick(item)"
@cancel="() => handleCancelCustom(item)"
@handle-set-save="setIsSave(false)"
/>
</MsCard>
</div>
@ -234,7 +235,6 @@
<script setup lang="ts">
import { ref } from 'vue';
import { useRoute } from 'vue-router';
import { useEventListener } from '@vueuse/core';
import { Message } from '@arco-design/web-vue';
import { cloneDeep } from 'lodash-es';
import { VueDraggable } from 'vue-draggable-plus';
@ -256,6 +256,7 @@
import { getReportLayout, updateReportDetail } from '@/api/modules/test-plan/report';
import { commonConfig, defaultCount, defaultReportDetail, seriesConfig, statusConfig } from '@/config/testPlan';
import { useI18n } from '@/hooks/useI18n';
import useLeaveUnSaveTip from '@/hooks/useLeaveUnSaveTip';
import { addCommasToNumber } from '@/utils';
import { UpdateReportDetailParams } from '@/models/testPlan/report';
@ -287,12 +288,17 @@
(e: 'updateCustom', item: configItem): void;
}>();
const { setIsSave } = useLeaveUnSaveTip({
leaveTitle: 'common.tip',
leaveContent: 'common.editUnsavedLeave',
tipType: 'warning',
});
const innerCardList = defineModel<configItem[]>('cardList', {
default: [],
});
const detail = ref<PlanReportDetail>({ ...cloneDeep(defaultReportDetail) });
const showButton = ref<boolean>(false);
const richText = ref<{ summary: string; richTextTmpFileIds?: string[] }>({
summary: '',
@ -513,23 +519,16 @@
};
}
onMounted(async () => {
nextTick(() => {
const editorContent = document.querySelector('.editor-content');
useEventListener(editorContent, 'click', () => {
showButton.value = true;
});
});
});
function handleCancelCustom(cardItem: configItem) {
const originItem = originLayoutInfo.value.find((item: configItem) => item.id === cardItem.id);
const index = originLayoutInfo.value.findIndex((e: configItem) => e.id === cardItem.id);
if (originItem && index !== -1) {
innerCardList.value.splice(index, 1, originItem);
}
showButton.value = false;
cardItem.enableEdit = false;
if (props.isPreview) {
setIsSave(true);
}
if (isDefaultLayout.value) {
cardItem.content = detail.value.summary;
richText.value.summary = detail.value.summary;
@ -575,10 +574,12 @@
innerCardList.value.splice(moveIndex, 1);
innerCardList.value.splice(moveIndex + 1, 0, cardItem);
}
setIsSave(false);
}
//
const deleteCard = (cardItem: configItem) => {
innerCardList.value = innerCardList.value.filter((item) => item.id !== cardItem.id);
setIsSave(false);
};
//
@ -588,11 +589,8 @@
}
}
function handleDoubleClick(cardItem: configItem) {
if (cardItem.value === ReportCardTypeEnum.SUMMARY) {
showButton.value = true;
}
cardItem.enableEdit = !cardItem.enableEdit;
function handleClick(cardItem: configItem) {
cardItem.enableEdit = true;
}
async function handleUpdateReportDetail(currentItem: configItem) {
@ -605,11 +603,8 @@
};
await updateReportDetail(params);
Message.success(t('common.updateSuccess'));
if (currentItem.value === ReportCardTypeEnum.SUMMARY) {
showButton.value = false;
} else {
currentItem.enableEdit = !currentItem.enableEdit;
}
setIsSave(true);
currentItem.enableEdit = false;
emit('updateSuccess');
} catch (error) {
console.log(error);
@ -638,6 +633,9 @@
handleUpdateReportDetail(newCurrentItem);
}
}
defineExpose({
setIsSave,
});
</script>
<style scoped lang="less">