feat(测试计划): 报告-报告总结-单击聚焦编辑&保存提示
This commit is contained in:
parent
366b00706e
commit
85bd5949f8
|
@ -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>
|
||||
|
|
|
@ -160,6 +160,7 @@ export default {
|
|||
'common.nameNotNull': '名称不能为空',
|
||||
'common.namePlaceholder': '请输入名称,按回车键保存',
|
||||
'common.unsavedLeave': '有标签页的内容未保存,离开后未保存的内容将丢失,确定要离开吗?',
|
||||
'common.editUnsavedLeave': '编辑内容未保存,离开后未保存的内容将丢失,确定要离开吗?',
|
||||
'common.image': '图片',
|
||||
'common.text': '文本',
|
||||
'common.resourceDeleted': '资源已被删除',
|
||||
|
|
|
@ -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({
|
||||
|
|
|
@ -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');
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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">
|
||||
|
|
Loading…
Reference in New Issue