feat(测试计划): 测试计划详情-功能用例详情-执行内容展示调整优化
This commit is contained in:
parent
a3f70d1f64
commit
ae1b6ddb02
|
@ -12,7 +12,6 @@
|
|||
* import rehypeStringify from 'rehype-stringify';
|
||||
* return unified().use(rehypeParse).use(rehypeFormat).use(rehypeStringify).processSync(content.value);
|
||||
*/
|
||||
import { useRoute } from 'vue-router';
|
||||
import { useDebounceFn, useVModel } from '@vueuse/core';
|
||||
|
||||
import type { MsFileItem } from '@/components/pure/ms-upload/types';
|
||||
|
@ -71,7 +70,6 @@
|
|||
import * as fastq from 'fastq';
|
||||
|
||||
const { t } = useI18n();
|
||||
const route = useRoute();
|
||||
type Task = {
|
||||
file: File;
|
||||
process: (permalink: string, fileId: string) => void;
|
||||
|
@ -91,6 +89,7 @@
|
|||
previewUrl?: string;
|
||||
editable?: boolean;
|
||||
limitLength?: number;
|
||||
autoFocus?: boolean;
|
||||
}>(),
|
||||
{
|
||||
raw: '',
|
||||
|
@ -109,6 +108,8 @@
|
|||
(event: 'update:filedIds', value: string[]): void;
|
||||
(event: 'update', value: string): void;
|
||||
(event: 'update:commentIds', value: string): void;
|
||||
(event: 'blur', eveValue: FocusEvent): void;
|
||||
(event: 'focus', eveValue: FocusEvent): void;
|
||||
}>();
|
||||
|
||||
const imagesNodesIds = useVModel(props, 'filedIds', emit);
|
||||
|
@ -149,6 +150,16 @@
|
|||
}
|
||||
);
|
||||
|
||||
watch(
|
||||
() => props.autoFocus,
|
||||
(val) => {
|
||||
editor.value?.setOptions({ autofocus: val });
|
||||
},
|
||||
{
|
||||
immediate: true,
|
||||
}
|
||||
);
|
||||
|
||||
const attachmentSelectorModal = ref(false);
|
||||
const selectedImagesNode = ref<string>();
|
||||
const selectedCommentNode = ref<string>();
|
||||
|
@ -385,11 +396,20 @@
|
|||
limit: props.limitLength || null,
|
||||
}),
|
||||
],
|
||||
autofocus: false,
|
||||
autofocus: props.autoFocus,
|
||||
editable: props.editable,
|
||||
onUpdate: () => {
|
||||
debounceOnUpdate();
|
||||
},
|
||||
onBlur: ({ event }) => {
|
||||
// 避免移动到菜单上触发失去焦点切换视图
|
||||
if (!event.relatedTarget) {
|
||||
emit('blur', event);
|
||||
}
|
||||
},
|
||||
onFocus: ({ event }) => {
|
||||
emit('focus', event);
|
||||
},
|
||||
editorProps: {
|
||||
handleDrop: (view, event: DragEvent, _, moved) => {
|
||||
if (!moved && event.dataTransfer && event.dataTransfer.files) {
|
||||
|
|
|
@ -1,15 +1,29 @@
|
|||
<template>
|
||||
<a-form :model="form">
|
||||
<a-form-item field="lastExecResult" class="mb-[8px]">
|
||||
<a-radio-group v-model:model-value="form.lastExecResult">
|
||||
<a-radio v-for="item in executionResultList" :key="item.key" :value="item.key">
|
||||
<ExecuteResult :execute-result="item.key" />
|
||||
</a-radio>
|
||||
</a-radio-group>
|
||||
<div class="flex w-full items-center justify-between">
|
||||
<a-radio-group v-model:model-value="form.lastExecResult">
|
||||
<a-radio v-for="item in executionResultList" :key="item.key" :value="item.key">
|
||||
<ExecuteResult :execute-result="item.key" />
|
||||
</a-radio>
|
||||
</a-radio-group>
|
||||
<slot name="headerRight"></slot>
|
||||
</div>
|
||||
</a-form-item>
|
||||
<a-form-item field="content" asterisk-position="end" class="mb-0">
|
||||
<div class="flex w-full items-center">
|
||||
<a-textarea
|
||||
v-if="props.isDblclickPlaceholder && !achievedForm"
|
||||
v-model="form.content"
|
||||
allow-clear
|
||||
:placeholder="t('testPlan.featureCase.richTextDblclickPlaceholder')"
|
||||
:auto-size="{ minRows: 1 }"
|
||||
style="resize: vertical"
|
||||
:max-length="1000"
|
||||
@click="achievedForm = true"
|
||||
/>
|
||||
<MsRichText
|
||||
v-if="!props.isDblclickPlaceholder || achievedForm"
|
||||
v-model:raw="form.content"
|
||||
v-model:commentIds="form.commentIds"
|
||||
v-model:filedIds="form.planCommentFileIds"
|
||||
|
@ -17,12 +31,14 @@
|
|||
:preview-url="`${PreviewEditorImageUrl}/${appStore.currentProjectId}`"
|
||||
:auto-height="false"
|
||||
class="w-full"
|
||||
:auto-focus="true"
|
||||
:max-height="props.richTextMaxHeight"
|
||||
:placeholder="
|
||||
props.isDblclickPlaceholder
|
||||
? t('testPlan.featureCase.richTextDblclickPlaceholder')
|
||||
: t('editor.placeholder')
|
||||
"
|
||||
@blur="blurHandler"
|
||||
/>
|
||||
</div>
|
||||
</a-form-item>
|
||||
|
@ -48,10 +64,18 @@
|
|||
richTextMaxHeight?: string;
|
||||
}>();
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'dblclick'): void;
|
||||
}>();
|
||||
|
||||
const form = defineModel<ExecuteFeatureCaseFormParams>('form', {
|
||||
required: true,
|
||||
});
|
||||
|
||||
const achievedForm = defineModel<boolean>('achieved', {
|
||||
default: false,
|
||||
});
|
||||
|
||||
const { t } = useI18n();
|
||||
const appStore = useAppStore();
|
||||
|
||||
|
@ -65,6 +89,21 @@
|
|||
});
|
||||
return data;
|
||||
}
|
||||
|
||||
function blurHandler() {
|
||||
if (props.isDblclickPlaceholder && !form.value.content) {
|
||||
achievedForm.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
watch(
|
||||
() => achievedForm.value,
|
||||
(val) => {
|
||||
if (val && props.isDblclickPlaceholder) {
|
||||
emit('dblclick');
|
||||
}
|
||||
}
|
||||
);
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
|
|
|
@ -1,5 +1,15 @@
|
|||
<template>
|
||||
<ExecuteForm v-model:form="form" is-dblclick-placeholder class="execute-form" />
|
||||
<ExecuteForm
|
||||
v-model:achieved="achievedForm"
|
||||
v-model:form="form"
|
||||
is-dblclick-placeholder
|
||||
class="execute-form"
|
||||
@dblclick="dblclickHandler"
|
||||
>
|
||||
<template #headerRight>
|
||||
<slot name="headerRight"></slot>
|
||||
</template>
|
||||
</ExecuteForm>
|
||||
<a-button type="primary" class="mt-[12px]" :loading="submitLoading" @click="() => submit()">
|
||||
{{ t('caseManagement.caseReview.commitResult') }}
|
||||
</a-button>
|
||||
|
@ -59,9 +69,8 @@
|
|||
|
||||
const modalVisible = ref(false);
|
||||
const submitLoading = ref(false);
|
||||
|
||||
// 双击富文本内容打开弹窗
|
||||
onMounted(() => {
|
||||
function dblclickHandler() {
|
||||
nextTick(() => {
|
||||
const editorContent = document.querySelector('.execute-form')?.querySelector('.editor-content');
|
||||
useEventListener(editorContent, 'dblclick', () => {
|
||||
|
@ -69,7 +78,7 @@
|
|||
dialogForm.value = cloneDeep(form.value);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
watch(
|
||||
() => props.stepExecutionResult,
|
||||
|
@ -93,12 +102,15 @@
|
|||
}
|
||||
);
|
||||
|
||||
const achievedForm = ref<boolean>(false);
|
||||
|
||||
function cancel(e: Event) {
|
||||
// 点击取消/关闭,弹窗关闭,富文本内容都清空;点击空白处,弹窗关闭,将弹窗内容填入下面富文本内容里
|
||||
if (!(e.target as any)?.classList.contains('arco-modal-wrapper')) {
|
||||
dialogForm.value = { ...defaultExecuteForm };
|
||||
}
|
||||
form.value = cloneDeep(dialogForm.value);
|
||||
achievedForm.value = false;
|
||||
}
|
||||
|
||||
// 提交执行
|
||||
|
@ -128,6 +140,7 @@
|
|||
modalVisible.value = false;
|
||||
Message.success(t('common.updateSuccess'));
|
||||
form.value = { ...defaultExecuteForm };
|
||||
achievedForm.value = false;
|
||||
emit('done', params.lastExecResult, params.content ?? '');
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
|
|
|
@ -116,83 +116,83 @@
|
|||
v-if="canEdit && hasAnyPermission(['PROJECT_TEST_PLAN:READ+EXECUTE'])"
|
||||
class="z-[101] px-[16px] py-[8px] shadow-[0_-1px_4px_rgba(2,2,2,0.1)]"
|
||||
>
|
||||
<div class="mb-[12px] flex items-center justify-between">
|
||||
<div class="font-medium text-[var(--color-text-1)]">
|
||||
{{ t('testPlan.featureCase.startExecution') }}
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<a-switch v-model:model-value="autoNext" size="small" />
|
||||
<div class="mx-[8px]">{{ t('caseManagement.caseReview.autoNext') }}</div>
|
||||
<a-tooltip position="top">
|
||||
<template #content>
|
||||
<div>{{ t('testPlan.featureCase.autoNextTip1') }}</div>
|
||||
<div>{{ t('testPlan.featureCase.autoNextTip2') }}</div>
|
||||
</template>
|
||||
<icon-question-circle
|
||||
class="text-[var(--color-text-brand)] hover:text-[rgb(var(--primary-4))]"
|
||||
size="16"
|
||||
/>
|
||||
</a-tooltip>
|
||||
<MsTag type="danger" theme="light" size="medium" class="ml-4">
|
||||
<MsIcon type="icon-icon_defect" class="!text-[14px] text-[rgb(var(--danger-6))]" size="16" />
|
||||
<span class="ml-1 text-[rgb(var(--danger-6))]"> {{ t('testPlan.featureCase.bug') }}</span>
|
||||
<span class="ml-1 text-[rgb(var(--danger-6))]">{{ caseDetail.bugListCount }}</span>
|
||||
</MsTag>
|
||||
<a-dropdown @select="handleSelect">
|
||||
<a-button
|
||||
v-if="hasAllPermission(['PROJECT_BUG:READ', 'PROJECT_TEST_PLAN:READ+EXECUTE'])"
|
||||
type="outline"
|
||||
size="small"
|
||||
class="ml-1"
|
||||
>
|
||||
<template #icon> <icon-plus class="text-[12px]" /> </template>
|
||||
</a-button>
|
||||
<template #content>
|
||||
<a-doption
|
||||
v-permission="['PROJECT_BUG:READ+ADD']"
|
||||
:disabled="!hasAnyPermission(['PROJECT_BUG:READ+ADD'])"
|
||||
value="new"
|
||||
>{{ t('common.newCreate') }}</a-doption
|
||||
>
|
||||
<a-doption
|
||||
v-if="createdBugCount > 0 && hasAnyPermission(['PROJECT_BUG:READ'])"
|
||||
:disabled="!hasAnyPermission(['PROJECT_BUG:READ'])"
|
||||
value="link"
|
||||
>{{ t('common.associated') }}</a-doption
|
||||
>
|
||||
<a-popover v-else title="" position="left">
|
||||
<a-doption
|
||||
v-if="createdBugCount < 1 && hasAnyPermission(['PROJECT_BUG:READ'])"
|
||||
:disabled="!hasAnyPermission(['PROJECT_BUG:READ'])"
|
||||
value="link"
|
||||
>{{ t('common.associated') }}</a-doption
|
||||
>
|
||||
<template #content>
|
||||
<div class="flex items-center text-[14px]">
|
||||
<span class="text-[var(--color-text-4)]">{{
|
||||
t('testPlan.featureCase.noBugDataTooltip')
|
||||
}}</span>
|
||||
<MsButton
|
||||
:disabled="!hasAnyPermission(['PROJECT_BUG:READ+ADD'])"
|
||||
type="text"
|
||||
@click="handleSelect('new')"
|
||||
>
|
||||
{{ t('testPlan.featureCase.noBugDataNewBug') }}
|
||||
</MsButton>
|
||||
</div>
|
||||
</template>
|
||||
</a-popover>
|
||||
</template>
|
||||
</a-dropdown>
|
||||
</div>
|
||||
</div>
|
||||
<ExecuteSubmit
|
||||
:id="activeId"
|
||||
:case-id="activeCaseId"
|
||||
:test-plan-id="route.query.id as string"
|
||||
:step-execution-result="stepExecutionResult"
|
||||
@done="executeDone"
|
||||
/>
|
||||
>
|
||||
<template #headerRight>
|
||||
<div class="mb-[12px] flex items-center justify-between">
|
||||
<div class="flex items-center">
|
||||
<a-switch v-model:model-value="autoNext" size="small" />
|
||||
<div class="mx-[8px]">{{ t('caseManagement.caseReview.autoNext') }}</div>
|
||||
<a-tooltip position="top">
|
||||
<template #content>
|
||||
<div>{{ t('testPlan.featureCase.autoNextTip1') }}</div>
|
||||
<div>{{ t('testPlan.featureCase.autoNextTip2') }}</div>
|
||||
</template>
|
||||
<icon-question-circle
|
||||
class="text-[var(--color-text-brand)] hover:text-[rgb(var(--primary-4))]"
|
||||
size="16"
|
||||
/>
|
||||
</a-tooltip>
|
||||
<MsTag type="danger" theme="light" size="medium" class="ml-4">
|
||||
<MsIcon type="icon-icon_defect" class="!text-[14px] text-[rgb(var(--danger-6))]" size="16" />
|
||||
<span class="ml-1 text-[rgb(var(--danger-6))]"> {{ t('testPlan.featureCase.bug') }}</span>
|
||||
<span class="ml-1 text-[rgb(var(--danger-6))]">{{ caseDetail.bugListCount }}</span>
|
||||
</MsTag>
|
||||
<a-dropdown @select="handleSelect">
|
||||
<a-button
|
||||
v-if="hasAllPermission(['PROJECT_BUG:READ', 'PROJECT_TEST_PLAN:READ+EXECUTE'])"
|
||||
type="outline"
|
||||
size="small"
|
||||
class="ml-1"
|
||||
>
|
||||
<template #icon> <icon-plus class="text-[12px]" /> </template>
|
||||
</a-button>
|
||||
<template #content>
|
||||
<a-doption
|
||||
v-permission="['PROJECT_BUG:READ+ADD']"
|
||||
:disabled="!hasAnyPermission(['PROJECT_BUG:READ+ADD'])"
|
||||
value="new"
|
||||
>{{ t('common.newCreate') }}</a-doption
|
||||
>
|
||||
<a-doption
|
||||
v-if="createdBugCount > 0 && hasAnyPermission(['PROJECT_BUG:READ'])"
|
||||
:disabled="!hasAnyPermission(['PROJECT_BUG:READ'])"
|
||||
value="link"
|
||||
>{{ t('common.associated') }}</a-doption
|
||||
>
|
||||
<a-popover v-else title="" position="left">
|
||||
<a-doption
|
||||
v-if="createdBugCount < 1 && hasAnyPermission(['PROJECT_BUG:READ'])"
|
||||
:disabled="!hasAnyPermission(['PROJECT_BUG:READ'])"
|
||||
value="link"
|
||||
>{{ t('common.associated') }}</a-doption
|
||||
>
|
||||
<template #content>
|
||||
<div class="flex items-center text-[14px]">
|
||||
<span class="text-[var(--color-text-4)]">{{
|
||||
t('testPlan.featureCase.noBugDataTooltip')
|
||||
}}</span>
|
||||
<MsButton
|
||||
:disabled="!hasAnyPermission(['PROJECT_BUG:READ+ADD'])"
|
||||
type="text"
|
||||
@click="handleSelect('new')"
|
||||
>
|
||||
{{ t('testPlan.featureCase.noBugDataNewBug') }}
|
||||
</MsButton>
|
||||
</div>
|
||||
</template>
|
||||
</a-popover>
|
||||
</template>
|
||||
</a-dropdown>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</ExecuteSubmit>
|
||||
</div>
|
||||
</div>
|
||||
<BugList
|
||||
|
|
Loading…
Reference in New Issue