fix(测试计划): 新建计划保存并创建后清空数据&处理计划详情里已归档的样式&新建缺陷后刷新数据

--bug=1040979 --user=吕梦园
https://www.tapd.cn/55049933/bugtrace/bugs/view/1155049933001040979
--bug=1041178 --user=吕梦园
https://www.tapd.cn/55049933/bugtrace/bugs/view/1155049933001041178
--bug=1041192 --user=吕梦园
https://www.tapd.cn/55049933/bugtrace/bugs/view/1155049933001041192
This commit is contained in:
teukkk 2024-05-27 14:37:38 +08:00 committed by 刘瑞斌
parent 793637536c
commit 9ec7d44b35
7 changed files with 73 additions and 37 deletions

View File

@ -5,7 +5,9 @@
</template> </template>
<template #name="{ record }"> <template #name="{ record }">
<div class="flex flex-nowrap items-center"> <div class="flex flex-nowrap items-center">
<a-tooltip :content="record.name">
<div class="one-line-text max-w-[200px] flex-auto items-center"> {{ characterLimit(record.name) }}</div> <div class="one-line-text max-w-[200px] flex-auto items-center"> {{ characterLimit(record.name) }}</div>
</a-tooltip>
<a-popover class="bug-content-popover" title="" position="right" style="width: 480px"> <a-popover class="bug-content-popover" title="" position="right" style="width: 480px">
<span class="ml-1 text-[rgb(var(--primary-5))]">{{ t('caseManagement.featureCase.preview') }}</span> <span class="ml-1 text-[rgb(var(--primary-5))]">{{ t('caseManagement.featureCase.preview') }}</span>
<template #content> <template #content>
@ -28,7 +30,7 @@
t('caseManagement.featureCase.cancelLink') t('caseManagement.featureCase.cancelLink')
}}</MsButton> }}</MsButton>
</template> </template>
<template v-if="(keyword || '').trim() === ''" #empty> <template v-if="(keyword || '').trim() === '' && props.canEdit" #empty>
<div class="flex w-full items-center justify-center text-[var(--color-text-4)]"> <div class="flex w-full items-center justify-center text-[var(--color-text-4)]">
{{ t('caseManagement.featureCase.tableNoDataWidthComma') }} {{ t('caseManagement.featureCase.tableNoDataWidthComma') }}
<span v-if="hasAnyPermission(['FUNCTIONAL_CASE:READ+UPDATE', 'PROJECT_BUG:READ+ADD'])">{{ <span v-if="hasAnyPermission(['FUNCTIONAL_CASE:READ+UPDATE', 'PROJECT_BUG:READ+ADD'])">{{
@ -69,14 +71,20 @@
const appStore = useAppStore(); const appStore = useAppStore();
const { t } = useI18n(); const { t } = useI18n();
const props = defineProps<{ const props = withDefaults(
defineProps<{
caseId: string; caseId: string;
keyword: string; keyword: string;
bugColumns: MsTableColumn; bugColumns: MsTableColumn;
bugTotal: number; // bugTotal: number; //
loadParams?: Record<string, any>; loadParams?: Record<string, any>;
loadBugListApi: (params: TableQueryParams) => Promise<CommonList<Record<string, any>>>; // loadBugListApi: (params: TableQueryParams) => Promise<CommonList<Record<string, any>>>; //
}>(); canEdit: boolean;
}>(),
{
canEdit: true,
}
);
const emit = defineEmits<{ const emit = defineEmits<{
(e: 'link'): void; (e: 'link'): void;
@ -93,7 +101,7 @@
setLoadListParams: setLinkListParams, setLoadListParams: setLinkListParams,
} = useTable(props.loadBugListApi, { } = useTable(props.loadBugListApi, {
columns: props.bugColumns, columns: props.bugColumns,
scroll: { x: 'auto' }, scroll: { x: '100%' },
heightUsed: 340, heightUsed: 340,
enableDrag: false, enableDrag: false,
}); });

View File

@ -330,7 +330,7 @@
if (!isContinue) { if (!isContinue) {
handleCancel(); handleCancel();
} }
form.value.name = ''; form.value = { ...cloneDeep(initForm), moduleId: form.value.moduleId };
} }
}); });
} }

View File

@ -17,8 +17,13 @@
</a-button> </a-button>
</div> </div>
<MsBaseTable <MsBaseTable
ref="tableRef"
v-bind="propsRes" v-bind="propsRes"
:action-config="batchActions" :action-config="batchActions"
:selectable="hasOperationPermission"
:draggable="
hasAnyPermission(['PROJECT_TEST_PLAN:READ+UPDATE']) && props.canEdit ? { type: 'handle', width: 32 } : undefined
"
v-on="propsEvent" v-on="propsEvent"
@batch-action="handleTableBatch" @batch-action="handleTableBatch"
@drag-change="handleDragChange" @drag-change="handleDragChange"
@ -39,7 +44,7 @@
</template> </template>
<template #lastExecResult="{ record }"> <template #lastExecResult="{ record }">
<a-select <a-select
v-if="hasAnyPermission(['PROJECT_TEST_PLAN:READ+EXECUTE'])" v-if="hasAnyPermission(['PROJECT_TEST_PLAN:READ+EXECUTE']) && props.canEdit"
v-model:model-value="record.lastExecResult" v-model:model-value="record.lastExecResult"
:placeholder="t('common.pleaseSelect')" :placeholder="t('common.pleaseSelect')"
class="param-input w-full" class="param-input w-full"
@ -54,7 +59,7 @@
</a-select> </a-select>
<span v-else class="text-[var(--color-text-2)]"><ExecuteResult :execute-result="record.lastExecResult" /></span> <span v-else class="text-[var(--color-text-2)]"><ExecuteResult :execute-result="record.lastExecResult" /></span>
</template> </template>
<template #operation="{ record }"> <template v-if="props.canEdit" #operation="{ record }">
<MsButton <MsButton
v-permission="['PROJECT_TEST_PLAN:READ+EXECUTE']" v-permission="['PROJECT_TEST_PLAN:READ+EXECUTE']"
type="text" type="text"
@ -221,6 +226,7 @@
planId: string; planId: string;
moduleTree: ModuleTreeNode[]; moduleTree: ModuleTreeNode[];
repeatCase: boolean; repeatCase: boolean;
canEdit: boolean;
}>(); }>();
const emit = defineEmits<{ const emit = defineEmits<{
@ -238,10 +244,10 @@
const keyword = ref(''); const keyword = ref('');
const hasOperationPermission = computed(() => const hasOperationPermission = computed(
hasAnyPermission(['PROJECT_TEST_PLAN:READ+EXECUTE', 'PROJECT_TEST_PLAN:READ+ASSOCIATION']) () => hasAnyPermission(['PROJECT_TEST_PLAN:READ+EXECUTE', 'PROJECT_TEST_PLAN:READ+ASSOCIATION']) && props.canEdit
); );
const columns: MsTableColumn = [ const columns = computed<MsTableColumn>(() => [
{ {
title: 'ID', title: 'ID',
dataIndex: 'num', dataIndex: 'num',
@ -335,16 +341,13 @@
fixed: 'right', fixed: 'right',
width: hasOperationPermission.value ? 200 : 50, width: hasOperationPermission.value ? 200 : 50,
}, },
]; ]);
const { propsRes, propsEvent, loadList, setLoadListParams, resetSelector, getTableQueryParams } = useTable( const { propsRes, propsEvent, loadList, setLoadListParams, resetSelector, getTableQueryParams } = useTable(
getPlanDetailFeatureCaseList, getPlanDetailFeatureCaseList,
{ {
scroll: { x: '100%' }, scroll: { x: '100%' },
tableKey: TableKeyEnum.TEST_PLAN_DETAIL_FEATURE_CASE_TABLE, tableKey: TableKeyEnum.TEST_PLAN_DETAIL_FEATURE_CASE_TABLE,
showSetting: true, showSetting: true,
selectable: hasOperationPermission.value,
showSelectAll: true,
draggable: hasAnyPermission(['PROJECT_TEST_PLAN:READ+UPDATE']) ? { type: 'handle', width: 32 } : undefined,
heightUsed: 460, heightUsed: 460,
showSubdirectory: true, showSubdirectory: true,
}, },
@ -379,6 +382,14 @@
], ],
}; };
const tableRef = ref<InstanceType<typeof MsBaseTable>>();
watch(
() => hasOperationPermission.value,
() => {
tableRef.value?.initColumn(columns.value);
}
);
async function getModuleIds() { async function getModuleIds() {
let moduleIds: string[] = []; let moduleIds: string[] = [];
if (props.activeModule !== 'all') { if (props.activeModule !== 'all') {
@ -660,6 +671,7 @@
...route.query, ...route.query,
caseId: record.caseId, caseId: record.caseId,
testPlanCaseId: record.id, testPlanCaseId: record.id,
canEdit: String(props.canEdit),
}, },
state: { state: {
params: JSON.stringify(getTableQueryParams()), params: JSON.stringify(getTableQueryParams()),
@ -677,7 +689,7 @@
loadCaseList, loadCaseList,
}); });
await tableStore.initColumn(TableKeyEnum.TEST_PLAN_DETAIL_FEATURE_CASE_TABLE, columns, 'drawer', true); await tableStore.initColumn(TableKeyEnum.TEST_PLAN_DETAIL_FEATURE_CASE_TABLE, columns.value, 'drawer', true);
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>

View File

@ -1,7 +1,7 @@
<template> <template>
<div> <div>
<div class="mb-4 grid grid-cols-3"> <div class="mb-4 grid grid-cols-3">
<div> <div v-if="props.canEdit">
<a-dropdown-button <a-dropdown-button
v-if="hasAnyPermission(['PROJECT_BUG:READ']) && total" v-if="hasAnyPermission(['PROJECT_BUG:READ']) && total"
type="primary" type="primary"
@ -68,6 +68,7 @@
:case-id="props.caseId" :case-id="props.caseId"
:bug-total="total" :bug-total="total"
:bug-columns="columns" :bug-columns="columns"
:can-edit="props.canEdit"
:load-bug-list-api="associatedBugPage" :load-bug-list-api="associatedBugPage"
:load-params="{ :load-params="{
caseId: props.caseId, caseId: props.caseId,
@ -105,6 +106,7 @@
const props = defineProps<{ const props = defineProps<{
caseId: string; caseId: string;
testPlanCaseId: string; testPlanCaseId: string;
canEdit: boolean;
}>(); }>();
const keyword = ref<string>(''); const keyword = ref<string>('');
@ -240,6 +242,9 @@
const statusFilterOptions = ref<BugOptionItem[]>([]); const statusFilterOptions = ref<BugOptionItem[]>([]);
async function initFilterOptions() { async function initFilterOptions() {
if (!props.canEdit) {
columns.value = columns.value.filter((item) => item.dataIndex !== 'operation');
}
if (hasAnyPermission(['PROJECT_BUG:READ'])) { if (hasAnyPermission(['PROJECT_BUG:READ'])) {
const res = await getCustomOptionHeader(appStore.currentProjectId); const res = await getCustomOptionHeader(appStore.currentProjectId);
handleUserFilterOptions.value = res.handleUserOption; handleUserFilterOptions.value = res.handleUserOption;

View File

@ -73,9 +73,12 @@
</a-tooltip> </a-tooltip>
</div> </div>
</div> </div>
<a-button v-permission="['FUNCTIONAL_CASE:READ+UPDATE']" type="outline" @click="editCaseVisible = true">{{ <a-button
t('common.edit') v-if="canEdit && hasAnyPermission(['FUNCTIONAL_CASE:READ+UPDATE'])"
}}</a-button> type="outline"
@click="editCaseVisible = true"
>{{ t('common.edit') }}</a-button
>
</div> </div>
<MsTab <MsTab
v-model:active-key="activeTab" v-model:active-key="activeTab"
@ -101,7 +104,7 @@
<CaseTabDetail ref="caseTabDetailRef" is-test-plan :form="caseDetail" /> <CaseTabDetail ref="caseTabDetailRef" is-test-plan :form="caseDetail" />
<!-- 开始执行 --> <!-- 开始执行 -->
<div <div
v-permission="['PROJECT_TEST_PLAN:READ+EXECUTE']" v-if="canEdit && hasAnyPermission(['PROJECT_TEST_PLAN:READ+EXECUTE'])"
class="px-[16px] py-[8px] shadow-[0_-1px_4px_rgba(2,2,2,0.1)]" class="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="mb-[12px] flex items-center justify-between">
@ -127,7 +130,7 @@
<span class="ml-1 text-[rgb(var(--danger-6))]">{{ caseDetail.bugListCount }}</span> <span class="ml-1 text-[rgb(var(--danger-6))]">{{ caseDetail.bugListCount }}</span>
</MsTag> </MsTag>
<a-dropdown @select="handleSelect"> <a-dropdown @select="handleSelect">
<a-button v-if="hasAnyPermission(['PROJECT_BUG:READ'])" type="outline" size="mini" class="ml-1"> <a-button v-if="hasAnyPermission(['PROJECT_BUG:READ'])" type="outline" size="small" class="ml-1">
<template #icon> <icon-plus class="text-[12px]" /> </template> <template #icon> <icon-plus class="text-[12px]" /> </template>
</a-button> </a-button>
<template #content> <template #content>
@ -183,6 +186,7 @@
ref="bugRef" ref="bugRef"
:case-id="activeCaseId" :case-id="activeCaseId"
:test-plan-case-id="activeId" :test-plan-case-id="activeId"
:can-edit="canEdit"
@link="linkDefect" @link="linkDefect"
@new="addBug" @new="addBug"
@update-count="loadCaseDetail()" @update-count="loadCaseDetail()"
@ -212,7 +216,7 @@
caseId: activeCaseId, caseId: activeCaseId,
testPlanId:route.query.id as string, testPlanId:route.query.id as string,
}" }"
@success="loadCaseDetail()" @success="loadBugListAndCaseDetail"
/> />
</template> </template>
@ -248,7 +252,7 @@
import { testPlanDefaultDetail } from '@/config/testPlan'; import { testPlanDefaultDetail } from '@/config/testPlan';
import { useI18n } from '@/hooks/useI18n'; import { useI18n } from '@/hooks/useI18n';
import useAppStore from '@/store/modules/app'; import useAppStore from '@/store/modules/app';
import { hasAllPermission, hasAnyPermission } from '@/utils/permission'; import { hasAnyPermission } from '@/utils/permission';
import type { TableQueryParams } from '@/models/common'; import type { TableQueryParams } from '@/models/common';
import type { PlanDetailFeatureCaseItem, TestPlanDetail } from '@/models/testPlan/testPlan'; import type { PlanDetailFeatureCaseItem, TestPlanDetail } from '@/models/testPlan/testPlan';
@ -280,6 +284,7 @@
const activeCaseId = ref(route.query.caseId as string); const activeCaseId = ref(route.query.caseId as string);
const activeId = ref(route.query.testPlanCaseId as string); const activeId = ref(route.query.testPlanCaseId as string);
const canEdit = ref(route.query.canEdit === 'true');
const keyword = ref(''); const keyword = ref('');
const lastExecResult = ref(''); const lastExecResult = ref('');
const executeResultOptions = computed(() => { const executeResultOptions = computed(() => {
@ -499,17 +504,20 @@
} }
function getTotal(key: string) { function getTotal(key: string) {
const { bugListCount, runListCount } = caseDetail.value; const { bugListCount } = caseDetail.value;
switch (key) { switch (key) {
case 'defectList': case 'defectList':
return bugListCount > 99 ? `99+` : `${bugListCount || 0}`; return bugListCount > 99 ? `99+` : `${bugListCount}`;
case 'executionHistory':
return runListCount > 99 ? `99+` : `${runListCount || 0}`;
default: default:
return ''; return '';
} }
} }
function loadBugListAndCaseDetail() {
addSuccess();
loadCaseDetail();
}
async function associateSuccessHandler(params: TableQueryParams) { async function associateSuccessHandler(params: TableQueryParams) {
try { try {
drawerLoading.value = true; drawerLoading.value = true;
@ -521,8 +529,7 @@
}); });
Message.success(t('caseManagement.featureCase.associatedSuccess')); Message.success(t('caseManagement.featureCase.associatedSuccess'));
showLinkDrawer.value = false; showLinkDrawer.value = false;
addSuccess(); loadBugListAndCaseDetail();
loadCaseDetail();
} catch (error) { } catch (error) {
console.log(error); console.log(error);
} finally { } finally {

View File

@ -19,6 +19,7 @@
:active-module="activeFolderId" :active-module="activeFolderId"
:offspring-ids="offspringIds" :offspring-ids="offspringIds"
:module-tree="moduleTree" :module-tree="moduleTree"
:can-edit="props.canEdit"
@get-module-count="getModuleCount" @get-module-count="getModuleCount"
@refresh="emit('refresh')" @refresh="emit('refresh')"
@init-modules="initModules" @init-modules="initModules"
@ -42,6 +43,7 @@
const props = defineProps<{ const props = defineProps<{
repeatCase: boolean; repeatCase: boolean;
canEdit: boolean;
}>(); }>();
const emit = defineEmits<{ const emit = defineEmits<{

View File

@ -7,11 +7,12 @@
hide-footer hide-footer
no-content-padding no-content-padding
hide-divider hide-divider
hide-back
> >
<template #headerLeft> <template #headerLeft>
<MsStatusTag :status="detail.status || 'PREPARED'" /> <MsStatusTag :status="detail.status || 'PREPARED'" />
<a-tooltip :content="`[${detail.num}]${detail.name}`"> <a-tooltip :content="`[${detail.num}]${detail.name}`">
<div class="one-line-text ml-[4px] max-w-[360px] gap-[4px] font-medium text-[var(--color-text-1)]"> <div class="one-line-text ml-[8px] max-w-[360px] gap-[4px] font-medium text-[var(--color-text-1)]">
<span>[{{ detail.num }}]</span> <span>[{{ detail.num }}]</span>
{{ detail.name }} {{ detail.name }}
</div> </div>
@ -103,6 +104,7 @@
v-if="activeTab === 'featureCase'" v-if="activeTab === 'featureCase'"
ref="featureCaseRef" ref="featureCaseRef"
:repeat-case="detail.repeatCase" :repeat-case="detail.repeatCase"
:can-edit="detail.status !== 'ARCHIVED'"
@refresh="initDetail" @refresh="initDetail"
/> />
<!-- TODO 先不上 --> <!-- TODO 先不上 -->