style(测试计划): 调整测试计划报告悬浮上去style

This commit is contained in:
xinxin.wu 2024-05-23 15:40:28 +08:00 committed by Craftsman
parent a0c4df93be
commit 852353e15c
7 changed files with 68 additions and 41 deletions

View File

@ -25,7 +25,10 @@
<div class="flex h-full"> <div class="flex h-full">
<div class="w-[292px] border-r border-[var(--color-text-n8)] p-[16px]"> <div class="w-[292px] border-r border-[var(--color-text-n8)] p-[16px]">
<div class="flex items-center justify-between"> <div class="flex items-center justify-between">
<div v-if="!props.hideProjectSelect" class="w-full max-w-[162px] flex-1"> <div
v-if="!props.hideProjectSelect"
:class="`${!props.hideProjectSelect && caseType !== 'API' ? 'max-w-[259px]' : 'max-w-[162px]'} flex-1`"
>
<a-select <a-select
v-model="innerProject" v-model="innerProject"
class="mb-[16px] w-full" class="mb-[16px] w-full"
@ -305,6 +308,8 @@
* @param isSetDefaultKey 是否设置第一个节点为选中节点 * @param isSetDefaultKey 是否设置第一个节点为选中节点
*/ */
async function initModules(isSetDefaultKey = false) { async function initModules(isSetDefaultKey = false) {
console.log(111);
try { try {
moduleLoading.value = true; moduleLoading.value = true;
let params = { let params = {
@ -330,6 +335,7 @@
}); });
if (isSetDefaultKey) { if (isSetDefaultKey) {
selectedModuleKeys.value = [folderTree.value[0].id]; selectedModuleKeys.value = [folderTree.value[0].id];
[activeFolder.value] = [folderTree.value[0].id];
activeFolderName.value = folderTree.value[0].name; activeFolderName.value = folderTree.value[0].name;
const offspringIds: string[] = []; const offspringIds: string[] = [];
mapTree(folderTree.value[0].children || [], (e) => { mapTree(folderTree.value[0].children || [], (e) => {
@ -754,7 +760,7 @@
value: string | number | boolean | Record<string, any> | (string | number | boolean | Record<string, any>)[] value: string | number | boolean | Record<string, any> | (string | number | boolean | Record<string, any>)[]
) { ) {
caseType.value = value as keyof typeof CaseLinkEnum; caseType.value = value as keyof typeof CaseLinkEnum;
initModules(); initModules(true);
searchCase(); searchCase();
} }
@ -763,7 +769,7 @@
(val) => { (val) => {
if (val) { if (val) {
resetSelector(); resetSelector();
initModules(); initModules(true);
searchCase(); searchCase();
initFilter(); initFilter();
} }
@ -798,7 +804,7 @@
if (!props.hideProjectSelect) { if (!props.hideProjectSelect) {
initProjectList(true); initProjectList(true);
} }
initModules(); initModules(true);
searchCase(); searchCase();
initFilter(); initFilter();
} }

View File

@ -1,12 +1,12 @@
<template> <template>
<div :class="`min-h-[${props.size || '110px'}] flex items-center`"> <div :class="`min-h-[${props.size || '120px'}] flex items-center`">
<div class="relative mr-4"> <div class="relative mr-4">
<div :class="`${props.offset || defaultOffset} charts absolute text-center`"> <div class="charts">
<div class="text-[12px] text-[(var(--color-text-4))]">{{ t('report.detail.api.total') }}</div> <div class="text-[12px] text-[(var(--color-text-4))]">{{ t('report.detail.api.total') }}</div>
<a-popover position="bottom" content-class="response-popover-content"> <a-popover position="bottom" content-class="response-popover-content">
<div class="flex justify-center text-[18px] font-medium"> <div class="one-line-text w-full max-w-[90%] text-center text-[18px] font-medium">{{
<div class="one-line-text max-w-[60px]">{{ getIndicators(requestTotal) }}</div> getIndicators(requestTotal)
</div> }}</div>
<template #content> <template #content>
<div class="min-w-[176px] max-w-[400px] p-4 text-[14px]"> <div class="min-w-[176px] max-w-[400px] p-4 text-[14px]">
<div class="text-[12px] font-medium text-[var(--color-text-4)]">{{ t('report.detail.api.total') }}</div> <div class="text-[12px] font-medium text-[var(--color-text-4)]">{{ t('report.detail.api.total') }}</div>
@ -18,7 +18,7 @@
</a-popover> </a-popover>
</div> </div>
<a-popover position="bottom" content-class="response-popover-content"> <a-popover position="bottom" content-class="response-popover-content">
<div> <MsChart :width="props.size || '110px'" :height="props.size || '110px'" :options="props.options" /></div> <div> <MsChart :width="props.size || '120px'" :height="props.size || '120px'" :options="props.options" /></div>
<template #content> <template #content>
<div class="min-w-[176px] max-w-[400px] p-4"> <div class="min-w-[176px] max-w-[400px] p-4">
<div v-for="item of legendData" :key="item.value" class="mb-2 flex flex-nowrap justify-between"> <div v-for="item of legendData" :key="item.value" class="mb-2 flex flex-nowrap justify-between">
@ -68,10 +68,7 @@
legendData: LegendData[]; legendData: LegendData[];
requestTotal: number; requestTotal: number;
size?: string; size?: string;
offset?: string;
}>(); }>();
const defaultOffset = ref('top-[30%] right-0 bottom-0 left-0');
</script> </script>
<style scoped lang="less"> <style scoped lang="less">
@ -91,5 +88,9 @@
.charts { .charts {
z-index: 99; z-index: 99;
margin: auto; margin: auto;
width: 66%;
height: 66%;
border-radius: 50%;
@apply absolute bottom-0 left-0 right-0 top-0 flex flex-col items-center justify-center;
} }
</style> </style>

View File

@ -1,9 +1,7 @@
export default { export default {
'organization.service.searchPlugin': 'Search by plug-in name', 'organization.service.searchPlugin': 'Search by plug-in name',
'system.service.statusEnableTip': 'system.service.statusEnableTip': 'Open: Projects can be integrated with the platform',
'Open: projects can integrate with the platform and generate default templates for the platform', 'system.service.statusDisableTip': 'Shutdown: Projects cannot integrate with the platform',
'system.service.statusDisableTip':
'Shutdown: the project can not integrate with the platform and the default template for the platform is not available',
'organization.service.headerTip': 'Service integration usage guidelines', 'organization.service.headerTip': 'Service integration usage guidelines',
'organization.service.integrationList': 'Integration of List', 'organization.service.integrationList': 'Integration of List',
'organization.service.packUp': 'Pack Up', 'organization.service.packUp': 'Pack Up',

View File

@ -1,7 +1,7 @@
export default { export default {
'organization.service.searchPlugin': '通过插件名称搜索', 'organization.service.searchPlugin': '通过插件名称搜索',
'organization.service.statusEnableTip': '开启:项目可以与该平台集成并生成该平台的默认模板', 'organization.service.statusEnableTip': '开启:项目可以与该平台集成',
'organization.service.statusDisableTip': '关闭:项目无法与该平台集成且该平台默认模板不可用', 'organization.service.statusDisableTip': '关闭:项目无法与该平台集成',
'organization.service.headerTip': '服务集成 使用指引', 'organization.service.headerTip': '服务集成 使用指引',
'organization.service.integrationList': '集成列表', 'organization.service.integrationList': '集成列表',
'organization.service.packUp': '收起', 'organization.service.packUp': '收起',

View File

@ -17,6 +17,7 @@
const props = defineProps<{ const props = defineProps<{
reportId: string; reportId: string;
shareId?: string; shareId?: string;
isDelete: boolean;
}>(); }>();
const tableStore = useTableStore(); const tableStore = useTableStore();
@ -79,8 +80,10 @@
loadList(); loadList();
} }
onBeforeMount(() => { watchEffect(() => {
loadCaseList(); if (props.reportId && !props.isDelete) {
loadCaseList();
}
}); });
await tableStore.initColumn(TableKeyEnum.TEST_PLAN_REPORT_DETAIL_BUG, columns, 'drawer'); await tableStore.initColumn(TableKeyEnum.TEST_PLAN_REPORT_DETAIL_BUG, columns, 'drawer');

View File

@ -32,6 +32,7 @@
const props = defineProps<{ const props = defineProps<{
reportId: string; reportId: string;
shareId?: string; shareId?: string;
isDelete: boolean;
}>(); }>();
const tableStore = useTableStore(); const tableStore = useTableStore();
@ -114,8 +115,10 @@
loadList(); loadList();
} }
onBeforeMount(() => { watchEffect(() => {
loadCaseList(); if (props.reportId && !props.isDelete) {
loadCaseList();
}
}); });
await tableStore.initColumn(TableKeyEnum.TEST_PLAN_REPORT_DETAIL_FEATURE_CASE, columns, 'drawer'); await tableStore.initColumn(TableKeyEnum.TEST_PLAN_REPORT_DETAIL_FEATURE_CASE, columns, 'drawer');

View File

@ -88,13 +88,12 @@
<div class="block-title">{{ t('report.detail.executionAnalysis') }}</div> <div class="block-title">{{ t('report.detail.executionAnalysis') }}</div>
<SetReportChart <SetReportChart
size="150px" size="150px"
offset="top-[34%] right-0 bottom-0 left-0"
:legend-data="legendData" :legend-data="legendData"
:options="charOptions" :options="charOptions"
:request-total="getIndicators(detail.caseTotal) || 0" :request-total="getIndicators(detail.caseTotal) || 0"
/> />
</div> </div>
<div class="analysis min-w-[297px]"> <div class="analysis min-w-[330px]">
<div class="block-title">{{ t('report.detail.useCaseAnalysis') }}</div> <div class="block-title">{{ t('report.detail.useCaseAnalysis') }}</div>
<div class="flex"> <div class="flex">
<div class="w-[70%]"> <div class="w-[70%]">
@ -103,23 +102,25 @@
<SingleStatusProgress :detail="detail" status="block" /> <SingleStatusProgress :detail="detail" status="block" />
<SingleStatusProgress :detail="detail" status="error" /> <SingleStatusProgress :detail="detail" status="error" />
</div> </div>
<div class="relative w-[30%] min-w-[120px]"> <div class="relative w-[30%] min-w-[150px]">
<div class="charts absolute w-full text-center"> <div class="charts absolute w-full text-center">
<div class="text-[12px] !text-[var(--color-text-4)]">{{ t('report.passRate') }}</div> <div class="text-[12px] !text-[var(--color-text-4)]">{{ t('report.detail.api.total') }}</div>
<a-popover position="bottom" content-class="response-popover-content"> <a-popover position="bottom" content-class="response-popover-content">
<div class="flex justify-center text-[18px] font-medium"> <div class="flex justify-center text-[18px] font-medium">
<div class="one-line-text max-w-[60px] text-[var(--color-text-1)]">{{ detail.passRate }}% </div> <div class="one-line-text max-w-[80px] text-[var(--color-text-1)]">{{ functionCaseTotal }} </div>
</div> </div>
<template #content> <template #content>
<div class="min-w-[95px] max-w-[400px] p-4 text-[14px]"> <div class="min-w-[95px] max-w-[400px] p-4 text-[14px]">
<div class="text-[12px] font-medium text-[var(--color-text-4)]">{{ t('report.passRate') }}</div> <div class="text-[12px] font-medium text-[var(--color-text-4)]">{{
<div class="mt-2 text-[18px] font-medium text-[var(--color-text-1)]">{{ detail.passRate }} %</div> t('report.detail.api.total')
}}</div>
<div class="mt-2 text-[18px] font-medium text-[var(--color-text-1)]">{{ functionCaseTotal }}</div>
</div> </div>
</template> </template>
</a-popover> </a-popover>
</div> </div>
<div class="flex h-full w-full min-w-[120px] items-center justify-center"> <div class="flex h-full w-full min-w-[150px] items-center justify-center">
<MsChart width="120px" height="120px" :options="functionCaseOptions" <MsChart width="150px" height="150px" :options="functionCaseOptions"
/></div> /></div>
</div> </div>
</div> </div>
@ -155,8 +156,13 @@
no-content no-content
class="relative mb-[16px] border-b" class="relative mb-[16px] border-b"
/> />
<BugTable v-if="activeTab === 'bug'" :report-id="reportId" :share-id="shareId" /> <BugTable v-if="activeTab === 'bug'" :report-id="reportId" :share-id="shareId" :is-delete="isDelete" />
<FeatureCaseTable v-if="activeTab === 'featureCase'" :report-id="reportId" :share-id="shareId" /> <FeatureCaseTable
v-if="activeTab === 'featureCase'"
:report-id="reportId"
:is-delete="isDelete"
:share-id="shareId"
/>
</MsCard> </MsCard>
</template> </template>
@ -222,6 +228,7 @@
const shareId = ref<string>(route.query.shareId as string); const shareId = ref<string>(route.query.shareId as string);
const reportId = ref<string>(props.reportId); const reportId = ref<string>(props.reportId);
const shareLoading = ref<boolean>(false); const shareLoading = ref<boolean>(false);
const isDelete = ref<boolean>(false);
async function shareHandler() { async function shareHandler() {
try { try {
const res = await planReportShare({ const res = await planReportShare({
@ -229,9 +236,7 @@
projectId: appStore.currentProjectId, projectId: appStore.currentProjectId,
}); });
const { origin } = window.location; const { origin } = window.location;
const hrefShareDetail = await planGetShareHref(res.id); shareLink.value = `${origin}/#/${RouteEnum.SHARE}/${RouteEnum.SHARE_REPORT_TEST_PLAN}${res.shareUrl}`;
reportId.value = hrefShareDetail.reportId;
shareLink.value = `${origin}/#/${RouteEnum.SHARE}/${RouteEnum.SHARE_REPORT_TEST_PLAN}${res.shareUrl}&id=${hrefShareDetail.reportId}`;
if (navigator.clipboard) { if (navigator.clipboard) {
navigator.clipboard.writeText(shareLink.value).then( navigator.clipboard.writeText(shareLink.value).then(
() => { () => {
@ -397,15 +402,20 @@
async function getDetail() { async function getDetail() {
try { try {
// id
if (shareId.value) { if (shareId.value) {
const result = await planReportShareDetail(shareId.value, reportId.value); //
if (result.deleted) { const hrefShareDetail = await planGetShareHref(shareId.value);
if (hrefShareDetail.deleted) {
isDelete.value = hrefShareDetail.deleted;
router.push({ router.push({
name: NOT_FOUND_RESOURCE, name: NOT_FOUND_RESOURCE,
}); });
} else { return;
detail.value = result;
} }
reportId.value = hrefShareDetail.reportId;
const result = await planReportShareDetail(shareId.value, reportId.value);
detail.value = result;
} else { } else {
detail.value = await getReportDetail(reportId.value); detail.value = await getReportDetail(reportId.value);
} }
@ -442,6 +452,12 @@
showButton.value = false; showButton.value = false;
} }
const functionCaseTotal = computed(() => {
const { functionalCount } = detail.value;
const { success, error, pending, block } = functionalCount;
return success + error + pending + block;
});
const activeTab = ref('bug'); const activeTab = ref('bug');
const contentTabList = ref([ const contentTabList = ref([
{ {