fix(用例管理): 代码回退菜单恢复
This commit is contained in:
parent
a7a855dfa8
commit
4d832ce503
|
@ -295,8 +295,11 @@ export function createCommentList(data: CommentParams) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 编辑评论
|
// 编辑评论
|
||||||
export function updateCommentList(data: CommentParams) {
|
export function addOrUpdateCommentList(data: CommentParams) {
|
||||||
return MSR.post({ url: UpdateCommentItemUrl, data });
|
if (data.fetchType === 'UPDATE') {
|
||||||
|
return MSR.post({ url: UpdateCommentItemUrl, data });
|
||||||
|
}
|
||||||
|
return MSR.post({ url: CreateCommentItemUrl, data });
|
||||||
}
|
}
|
||||||
|
|
||||||
// 删除评论
|
// 删除评论
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="flex flex-row gap-[8px]">
|
<div class="flex flex-row gap-[8px]">
|
||||||
<div class="p-1"> <MsAvatar avatar="word" /></div>
|
<div class="p-1"> <MsAvatar :avatar="props.element.commentUserInfos[0].avatar" /></div>
|
||||||
<div class="flex w-full flex-col">
|
<div class="flex w-full flex-col">
|
||||||
<div class="font-medium text-[var(--color-text-1)]">{{ props.element.createUser }}</div>
|
<div class="font-medium text-[var(--color-text-1)]">{{ props.element.commentUserInfos[0].name }}</div>
|
||||||
<div v-dompurify-html="props.element.content" class="markdown-body mt-[4px]"></div>
|
<div v-dompurify-html="props.element.content" class="markdown-body mt-[4px]"></div>
|
||||||
|
|
||||||
<div class="mb-4 mt-[16px] flex flex-row items-center">
|
<div class="mb-4 mt-[16px] flex flex-row items-center">
|
||||||
|
|
|
@ -26,6 +26,7 @@ export default {
|
||||||
'menu.apiTest': 'API Test',
|
'menu.apiTest': 'API Test',
|
||||||
'menu.apiTest.debug': 'API debug',
|
'menu.apiTest.debug': 'API debug',
|
||||||
'menu.apiTest.management': 'API Management',
|
'menu.apiTest.management': 'API Management',
|
||||||
|
'menu.apiTest.report': 'API Report',
|
||||||
'menu.uiTest': 'UI Test',
|
'menu.uiTest': 'UI Test',
|
||||||
'menu.performanceTest': 'Performance Test',
|
'menu.performanceTest': 'Performance Test',
|
||||||
'menu.projectManagement': 'Project',
|
'menu.projectManagement': 'Project',
|
||||||
|
|
|
@ -26,6 +26,7 @@ export default {
|
||||||
'menu.apiTest': '接口测试',
|
'menu.apiTest': '接口测试',
|
||||||
'menu.apiTest.debug': '接口调试',
|
'menu.apiTest.debug': '接口调试',
|
||||||
'menu.apiTest.management': '接口管理',
|
'menu.apiTest.management': '接口管理',
|
||||||
|
'menu.apiTest.report': '接口报告',
|
||||||
'menu.uiTest': 'UI测试',
|
'menu.uiTest': 'UI测试',
|
||||||
'menu.workstation': '工作台',
|
'menu.workstation': '工作台',
|
||||||
'menu.loadTest': '性能测试',
|
'menu.loadTest': '性能测试',
|
||||||
|
|
|
@ -43,6 +43,16 @@ const ApiTest: AppRouteRecordRaw = {
|
||||||
isTopMenu: true,
|
isTopMenu: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: 'report',
|
||||||
|
name: ApiTestRouteEnum.API_TEST_REPORT,
|
||||||
|
component: () => import('@/views/api-test/report/index.vue'),
|
||||||
|
meta: {
|
||||||
|
locale: 'menu.apiTest.report',
|
||||||
|
roles: ['*'],
|
||||||
|
isTopMenu: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
<template>
|
||||||
|
<!-- <MsCard class="mb-[16px]" :title="props.title" hide-back hide-footer auto-height no-content-padding no-bottom-radius>
|
||||||
|
<a-tabs v-model:active-key="innerTab" class="no-content">
|
||||||
|
<a-tab-pane v-for="item of tabList" :key="item.key" :title="item.title" />
|
||||||
|
</a-tabs>
|
||||||
|
</MsCard> -->
|
||||||
|
<div></div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref } from 'vue';
|
||||||
|
|
||||||
|
import MsCard from '@/components/pure/ms-card/index.vue';
|
||||||
|
|
||||||
|
const tabList = [
|
||||||
|
{
|
||||||
|
value: '',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped></style>
|
|
@ -0,0 +1 @@
|
||||||
|
export default {};
|
|
@ -0,0 +1,85 @@
|
||||||
|
export default {
|
||||||
|
'apiTestManagement.newApi': '新建接口',
|
||||||
|
'apiTestManagement.importApi': '导入接口',
|
||||||
|
'apiTestManagement.fileImport': '文件导入',
|
||||||
|
'apiTestManagement.timeImport': '定时导入',
|
||||||
|
'apiTestManagement.addSubModule': '添加子模块',
|
||||||
|
'apiTestManagement.allApi': '全部接口',
|
||||||
|
'apiTestManagement.searchTip': '请输入模块/接口名称',
|
||||||
|
'apiTestManagement.moveSearchTip': '请输入模块名称搜索',
|
||||||
|
'apiTestManagement.noMatchModule': '暂无匹配的模块/接口',
|
||||||
|
'apiTestManagement.execute': '执行',
|
||||||
|
'apiTestManagement.share': '分享 API',
|
||||||
|
'apiTestManagement.shareModule': '分享模块',
|
||||||
|
'apiTestManagement.doc': '文档',
|
||||||
|
'apiTestManagement.closeAll': '关闭全部tab',
|
||||||
|
'apiTestManagement.closeOther': '关闭其他tab',
|
||||||
|
'apiTestManagement.showSubdirectory': '显示子目录用例',
|
||||||
|
'apiTestManagement.searchPlaceholder': '输入 ID/名称/api路径搜索',
|
||||||
|
'apiTestManagement.apiName': '接口名称',
|
||||||
|
'apiTestManagement.apiType': '请求类型',
|
||||||
|
'apiTestManagement.apiStatus': '状态',
|
||||||
|
'apiTestManagement.responsiblePerson': '责任人',
|
||||||
|
'apiTestManagement.path': '路径',
|
||||||
|
'apiTestManagement.version': '版本',
|
||||||
|
'apiTestManagement.createTime': '创建时间',
|
||||||
|
'apiTestManagement.updateTime': '更新时间',
|
||||||
|
'apiTestManagement.deprecate': '已废弃',
|
||||||
|
'apiTestManagement.processing': '进行中',
|
||||||
|
'apiTestManagement.debugging': '联调中',
|
||||||
|
'apiTestManagement.done': '已完成',
|
||||||
|
'apiTestManagement.deleteApiTipTitle': '确认删除 {name} 吗?',
|
||||||
|
'apiTestManagement.deleteApiTip': '删除后,接口将放入回收站,可在回收站内进行数据恢复',
|
||||||
|
'apiTestManagement.batchDeleteApiTip': '确认删除已选中的 {count} 个接口吗?',
|
||||||
|
'apiTestManagement.batchModalSubTitle': '(已选 {count} 个接口)',
|
||||||
|
'apiTestManagement.chooseAttr': '选择属性',
|
||||||
|
'apiTestManagement.attrRequired': '属性不能为空',
|
||||||
|
'apiTestManagement.batchUpdate': '批量更新为',
|
||||||
|
'apiTestManagement.valueRequired': '属性值不能为空',
|
||||||
|
'apiTestManagement.batchMoveConfirm': '移动至所选模块',
|
||||||
|
'apiTestManagement.belongModule': '所属模块',
|
||||||
|
'apiTestManagement.importMode': '导入模式',
|
||||||
|
'apiTestManagement.importModeTip1': '覆盖:',
|
||||||
|
'apiTestManagement.importModeTip2': '1.同一接口请求类型+路径一致,请求参数内容不一致则覆盖',
|
||||||
|
'apiTestManagement.importModeTip3': '2.同一接口请求类型+路径一致,请求参数内容一致不做变更',
|
||||||
|
'apiTestManagement.importModeTip4': '3.非同一接口,请求类型+路径一致,则新增',
|
||||||
|
'apiTestManagement.importModeTip5': '不覆盖:',
|
||||||
|
'apiTestManagement.importModeTip6': '1.同一接口请求类型+路径一致,则不做变更',
|
||||||
|
'apiTestManagement.importModeTip7': '2.非同一接口请求类型+路径一致,则新增',
|
||||||
|
'apiTestManagement.cover': '覆盖',
|
||||||
|
'apiTestManagement.uncover': '不覆盖',
|
||||||
|
'apiTestManagement.moreSetting': '更多设置',
|
||||||
|
'apiTestManagement.importType': '导入方式',
|
||||||
|
'apiTestManagement.urlImport': 'URL 导入',
|
||||||
|
'apiTestManagement.syncImportCase': '同步导入接口用例',
|
||||||
|
'apiTestManagement.syncUpdateDirectory': '同步更新接口所在目录',
|
||||||
|
'apiTestManagement.importSwaggerFileTip1': '支持 Swagger 3.0 版本的 json 文件,',
|
||||||
|
'apiTestManagement.importSwaggerFileTip2': '2.0 的文件建议自行在官网转换成 3.0 再进行导入',
|
||||||
|
'apiTestManagement.importSwaggerFileTip3': ',大小不超过 50M',
|
||||||
|
'apiTestManagement.urlImportPlaceholder': '请输入OpenAPI/Swagger URL',
|
||||||
|
'apiTestManagement.swaggerURLRequired': 'SwaggerURL 不能为空',
|
||||||
|
'apiTestManagement.basicAuth': 'Basic Auth 认证',
|
||||||
|
'apiTestManagement.account': '账号',
|
||||||
|
'apiTestManagement.accountRequired': '账号不能为空',
|
||||||
|
'apiTestManagement.password': '密码',
|
||||||
|
'apiTestManagement.passwordRequired': '密码不能为空',
|
||||||
|
'apiTestManagement.taskName': '任务名称',
|
||||||
|
'apiTestManagement.taskNamePlaceholder': '请输入任务名称',
|
||||||
|
'apiTestManagement.taskNameRequired': '任务名称不能为空',
|
||||||
|
'apiTestManagement.syncFrequency': '同步频率',
|
||||||
|
'apiTestManagement.timeTaskList': '定时任务列表',
|
||||||
|
'apiTestManagement.timeTaskHour': '(每小时)',
|
||||||
|
'apiTestManagement.timeTaskSixHour': '(每 6 小时)',
|
||||||
|
'apiTestManagement.timeTaskTwelveHour': '(每 12 小时)',
|
||||||
|
'apiTestManagement.timeTaskDay': '(每天)',
|
||||||
|
'apiTestManagement.customFrequency': '自定义频率',
|
||||||
|
'apiTestManagement.case': '用例',
|
||||||
|
'apiTestManagement.definition': '定义',
|
||||||
|
'apiTestManagement.addDependency': '添加依赖关系',
|
||||||
|
'apiTestManagement.preDependency': '前置依赖',
|
||||||
|
'apiTestManagement.addPreDependency': '添加前置依赖',
|
||||||
|
'apiTestManagement.postDependency': '后置依赖',
|
||||||
|
'apiTestManagement.addPostDependency': '添加后置依赖',
|
||||||
|
'apiTestManagement.saveAsCase': '保存为新用例',
|
||||||
|
'apiTestManagement.apiNamePlaceholder': '请输入接口名称',
|
||||||
|
};
|
|
@ -92,16 +92,9 @@
|
||||||
height: 'calc(100% - 86px)',
|
height: 'calc(100% - 86px)',
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<MsSplitBox
|
<MsSplitBox :size="0.7" :max="0.9" :min="0.7" direction="horizontal" expand-direction="right">
|
||||||
ref="wrapperRef"
|
|
||||||
class="h-[calc(100% - 78px)]"
|
|
||||||
expand-direction="right"
|
|
||||||
:max="0.7"
|
|
||||||
:min="0.7"
|
|
||||||
:size="900"
|
|
||||||
>
|
|
||||||
<template #first>
|
<template #first>
|
||||||
<div class="leftWrapper">
|
<div class="leftWrapper h-full">
|
||||||
<div class="header h-[50px]">
|
<div class="header h-[50px]">
|
||||||
<a-menu mode="horizontal" :default-selected-keys="[activeTab || 'detail']" @menu-item-click="clickMenu">
|
<a-menu mode="horizontal" :default-selected-keys="[activeTab || 'detail']" @menu-item-click="clickMenu">
|
||||||
<a-menu-item key="detail">{{ t('caseManagement.featureCase.detail') }} </a-menu-item>
|
<a-menu-item key="detail">{{ t('caseManagement.featureCase.detail') }} </a-menu-item>
|
||||||
|
@ -121,29 +114,48 @@
|
||||||
>
|
>
|
||||||
</a-menu>
|
</a-menu>
|
||||||
</div>
|
</div>
|
||||||
<div class="leftContent mt-4 px-4">
|
<keep-alive>
|
||||||
<TabDetail
|
<div class="leftContent mt-4 px-4">
|
||||||
v-if="activeTab === 'detail'"
|
<template v-if="activeTab === 'detail'">
|
||||||
ref="tabDetailRef"
|
<TabDetail
|
||||||
:form="detailInfo"
|
ref="tabDetailRef"
|
||||||
:allow-edit="true"
|
:form="detailInfo"
|
||||||
:form-rules="formItem"
|
:allow-edit="true"
|
||||||
:active-tab="activeTab"
|
:form-rules="formItem"
|
||||||
@update-success="updateSuccess"
|
:active-tab="activeTab"
|
||||||
/>
|
@update-success="updateSuccess"
|
||||||
<TabCaseTable v-show="activeTab === 'case'" :case-id="props.detailId" />
|
/>
|
||||||
<TabDemand v-show="activeTab === 'requirement'" :case-id="props.detailId" />
|
</template>
|
||||||
<TabDefect v-show="activeTab === 'bug'" :case-id="props.detailId" />
|
<template v-if="activeTab === 'requirement'">
|
||||||
<TabDependency v-show="activeTab === 'dependency'" :case-id="props.detailId" />
|
<TabDemand :active-tab="activeTab" :case-id="props.detailId" />
|
||||||
<TabCaseReview v-show="activeTab === 'caseReview'" :case-id="props.detailId" />
|
</template>
|
||||||
<TabTestPlan v-show="activeTab === 'testPlan'" :active-tab="activeTab" />
|
<template v-if="activeTab === 'case'">
|
||||||
<TabComment v-if="activeTab === 'comments'" ref="commentRef" :case-id="props.detailId" />
|
<TabCaseTable :active-tab="activeTab" :case-id="props.detailId" />
|
||||||
<TabChangeHistory v-show="activeTab === 'changeHistory'" :case-id="props.detailId" />
|
</template>
|
||||||
</div>
|
<template v-if="activeTab === 'bug'">
|
||||||
|
<TabDefect :active-tab="activeTab" :case-id="props.detailId" />
|
||||||
|
</template>
|
||||||
|
<template v-if="activeTab === 'dependency'">
|
||||||
|
<TabDependency :active-tab="activeTab" :case-id="props.detailId" />
|
||||||
|
</template>
|
||||||
|
<template v-if="activeTab === 'caseReview'">
|
||||||
|
<TabCaseReview :active-tab="activeTab" :case-id="props.detailId" />
|
||||||
|
</template>
|
||||||
|
<template v-if="activeTab === 'testPlan'">
|
||||||
|
<TabTestPlan :active-tab="activeTab" />
|
||||||
|
</template>
|
||||||
|
<template v-if="activeTab === 'comments'">
|
||||||
|
<TabComment ref="commentRef" :active-tab="activeTab" :case-id="props.detailId" />
|
||||||
|
</template>
|
||||||
|
<template v-if="activeTab === 'changeHistory'">
|
||||||
|
<TabChangeHistory :active-tab="activeTab" :case-id="props.detailId" />
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</keep-alive>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #second>
|
<template #second>
|
||||||
<div class="rightWrapper p-[24px]">
|
<div class="rightWrapper h-full p-[24px]">
|
||||||
<div class="mb-4 font-medium">{{ t('caseManagement.featureCase.basicInfo') }}</div>
|
<div class="mb-4 font-medium">{{ t('caseManagement.featureCase.basicInfo') }}</div>
|
||||||
<div class="baseItem">
|
<div class="baseItem">
|
||||||
<span class="label"> {{ t('caseManagement.featureCase.tableColumnModule') }}</span>
|
<span class="label"> {{ t('caseManagement.featureCase.tableColumnModule') }}</span>
|
||||||
|
@ -349,7 +361,16 @@
|
||||||
|
|
||||||
// 初始化count
|
// 初始化count
|
||||||
function setCount(detail: DetailCase) {
|
function setCount(detail: DetailCase) {
|
||||||
const { bugCount, caseCount, caseReviewCount, demandCount, relateEdgeCount, testPlanCount, commentCount, historyCount } = detail;
|
const {
|
||||||
|
bugCount,
|
||||||
|
caseCount,
|
||||||
|
caseReviewCount,
|
||||||
|
demandCount,
|
||||||
|
relateEdgeCount,
|
||||||
|
testPlanCount,
|
||||||
|
commentCount,
|
||||||
|
historyCount,
|
||||||
|
} = detail;
|
||||||
const countMap: Record<string, any> = {
|
const countMap: Record<string, any> = {
|
||||||
case: caseCount,
|
case: caseCount,
|
||||||
dependency: relateEdgeCount,
|
dependency: relateEdgeCount,
|
||||||
|
@ -358,7 +379,7 @@
|
||||||
bug: bugCount,
|
bug: bugCount,
|
||||||
requirement: demandCount,
|
requirement: demandCount,
|
||||||
comments: commentCount,
|
comments: commentCount,
|
||||||
changeHistory: historyCount
|
changeHistory: historyCount,
|
||||||
};
|
};
|
||||||
featureCaseStore.initCountMap(countMap);
|
featureCaseStore.initCountMap(countMap);
|
||||||
}
|
}
|
||||||
|
@ -611,9 +632,10 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
provide('activeTab', activeTab.value);
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
// settingDrawerRef.value.getTabModule();
|
settingDrawerRef.value.getTabModule();
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -128,8 +128,9 @@
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
caseId: string;
|
caseId: string;
|
||||||
|
activeTab: string;
|
||||||
}>();
|
}>();
|
||||||
const activeTab = computed(() => featureCaseStore.activeTab);
|
// const activeTab = computed(() => featureCaseStore.activeTab);
|
||||||
const showType = ref('link');
|
const showType = ref('link');
|
||||||
|
|
||||||
const keyword = ref<string>('');
|
const keyword = ref<string>('');
|
||||||
|
@ -322,18 +323,18 @@
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
watch(
|
// watch(
|
||||||
() => activeTab.value,
|
// () => activeTab.value,
|
||||||
(val) => {
|
// (val) => {
|
||||||
if (val === 'bug') {
|
// if (val === 'bug') {
|
||||||
getFetch();
|
// getFetch();
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
);
|
// );
|
||||||
|
|
||||||
// onMounted(() => {
|
onMounted(() => {
|
||||||
// getFetch();
|
getFetch();
|
||||||
// });
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped></style>
|
<style scoped></style>
|
||||||
|
|
|
@ -273,20 +273,20 @@
|
||||||
}
|
}
|
||||||
const activeTab = computed(() => featureCaseStore.activeTab);
|
const activeTab = computed(() => featureCaseStore.activeTab);
|
||||||
|
|
||||||
watch(
|
// watch(
|
||||||
() => activeTab.value,
|
// () => activeTab.value,
|
||||||
(val) => {
|
// (val) => {
|
||||||
if (val === 'case') {
|
// if (val === 'case') {
|
||||||
getEnabledModules();
|
// getEnabledModules();
|
||||||
getFetch();
|
// getFetch();
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
);
|
// );
|
||||||
|
|
||||||
// onMounted(async () => {
|
onMounted(async () => {
|
||||||
// getEnabledModules();
|
getEnabledModules();
|
||||||
// getFetch();
|
getFetch();
|
||||||
// });
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped></style>
|
<style scoped></style>
|
||||||
|
|
|
@ -48,11 +48,12 @@
|
||||||
import debounce from 'lodash-es/debounce';
|
import debounce from 'lodash-es/debounce';
|
||||||
|
|
||||||
const featureCaseStore = useFeatureCaseStore();
|
const featureCaseStore = useFeatureCaseStore();
|
||||||
const activeTab = computed(() => featureCaseStore.activeTab);
|
// const activeTab = computed(() => featureCaseStore.activeTab);
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
caseId: string; // 用例id
|
caseId: string; // 用例id
|
||||||
|
activeTab: string;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const keyword = ref<string>('');
|
const keyword = ref<string>('');
|
||||||
|
@ -114,18 +115,18 @@
|
||||||
initData();
|
initData();
|
||||||
}, 100);
|
}, 100);
|
||||||
|
|
||||||
watch(
|
// watch(
|
||||||
() => activeTab.value,
|
// () => activeTab.value,
|
||||||
(val) => {
|
// (val) => {
|
||||||
if (val === 'caseReview') {
|
// if (val === 'caseReview') {
|
||||||
initData();
|
// initData();
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
);
|
// );
|
||||||
|
|
||||||
// onMounted(() => {
|
onMounted(() => {
|
||||||
// initData();
|
initData();
|
||||||
// });
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped></style>
|
<style scoped></style>
|
||||||
|
|
|
@ -95,13 +95,14 @@
|
||||||
|
|
||||||
const appStore = useAppStore();
|
const appStore = useAppStore();
|
||||||
const featureCaseStore = useFeatureCaseStore();
|
const featureCaseStore = useFeatureCaseStore();
|
||||||
const activeTab = computed(() => featureCaseStore.activeTab);
|
// const activeTab = computed(() => featureCaseStore.activeTab);
|
||||||
const visitedKey = 'notRemindChangeHistoryTip';
|
const visitedKey = 'notRemindChangeHistoryTip';
|
||||||
const { addVisited } = useVisit(visitedKey);
|
const { addVisited } = useVisit(visitedKey);
|
||||||
const { getIsVisited } = useVisit(visitedKey);
|
const { getIsVisited } = useVisit(visitedKey);
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
caseId: string;
|
caseId: string;
|
||||||
|
// activeTab: string;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const columns: MsTableColumn = [
|
const columns: MsTableColumn = [
|
||||||
|
@ -247,20 +248,20 @@
|
||||||
featureCaseStore.getCaseCounts(props.caseId);
|
featureCaseStore.getCaseCounts(props.caseId);
|
||||||
}
|
}
|
||||||
|
|
||||||
watch(
|
// watch(
|
||||||
() => activeTab.value,
|
// () => activeTab.value,
|
||||||
(val) => {
|
// (val) => {
|
||||||
if (val === 'changeHistory') {
|
// if (val === 'changeHistory') {
|
||||||
doCheckIsTip();
|
// doCheckIsTip();
|
||||||
initData();
|
// initData();
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
);
|
// );
|
||||||
|
|
||||||
// onMounted(() => {
|
onMounted(() => {
|
||||||
// doCheckIsTip();
|
doCheckIsTip();
|
||||||
// initData();
|
initData();
|
||||||
// });
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped></style>
|
<style scoped></style>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="flex items-center justify-between">
|
<div class="mb-4 flex items-center justify-between">
|
||||||
<div class="font-medium">{{ t('caseManagement.featureCase.commentList') }}</div>
|
<div class="font-medium">{{ t('caseManagement.featureCase.commentList') }}</div>
|
||||||
<div>
|
<div>
|
||||||
<a-radio-group v-model="activeComment" type="button">
|
<a-radio-group v-model="activeComment" type="button">
|
||||||
|
@ -11,48 +11,77 @@
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<!-- 用例评论 -->
|
<!-- 用例评论 -->
|
||||||
<MsComment
|
<div v-show="activeComment === 'caseComment'">
|
||||||
v-if="activeComment === 'caseComment'"
|
<MsComment :comment-list="commentList" @delete="handleDelete" @update-or-add="handleUpdateOrAdd" />
|
||||||
:comment-list="commentList"
|
<MsEmpty v-if="commentList.length === 0" />
|
||||||
@delete="handleDelete"
|
</div>
|
||||||
@update-or-add="handleUpdateOrAdd"
|
|
||||||
/>
|
|
||||||
<!-- 评审评论 -->
|
<!-- 评审评论 -->
|
||||||
<MsComment
|
<div v-show="activeComment === 'reviewComment'" class="flex flex-1 flex-col overflow-hidden">
|
||||||
v-else-if="activeComment === 'reviewComment'"
|
<div class="review-history-list">
|
||||||
:comment-list="reviewCommentList"
|
<div v-for="item of reviewCommentList" :key="item.id" class="review-history-list-item">
|
||||||
@delete="handleDelete"
|
<div class="flex items-center">
|
||||||
@update-or-add="handleUpdateOrAdd"
|
<MSAvatar :avatar="item.userLogo" />
|
||||||
/>
|
<div class="ml-[8px] flex items-center">
|
||||||
<!-- 执行评论 -->
|
<div class="font-medium text-[var(--color-text-1)]">{{ item.userName }}</div>
|
||||||
<!-- <MsComment v-else :comment-list="commentList" @delete="handleDelete" @update-or-add="handleUpdateOrAdd" /> -->
|
<a-divider direction="vertical" margin="8px"></a-divider>
|
||||||
|
<div v-if="item.status === 'PASS'" class="flex items-center">
|
||||||
|
<MsIcon type="icon-icon_succeed_filled" class="mr-[4px] text-[rgb(var(--success-6))]" />
|
||||||
|
{{ t('caseManagement.caseReview.pass') }}
|
||||||
|
</div>
|
||||||
|
<div v-else-if="item.status === 'UN_PASS'" class="flex items-center">
|
||||||
|
<MsIcon type="icon-icon_close_filled" class="mr-[4px] text-[rgb(var(--danger-6))]" />
|
||||||
|
{{ t('caseManagement.caseReview.fail') }}
|
||||||
|
</div>
|
||||||
|
<div v-else-if="item.status === 'UNDER_REVIEWED'" class="flex items-center">
|
||||||
|
<MsIcon type="icon-icon_warning_filled" class="mr-[4px] text-[rgb(var(--warning-6))]" />
|
||||||
|
{{ t('caseManagement.caseReview.suggestion') }}
|
||||||
|
</div>
|
||||||
|
<div v-else-if="item.status === 'RE_REVIEWED'" class="flex items-center">
|
||||||
|
<MsIcon type="icon-icon_resubmit_filled" class="mr-[4px] text-[rgb(var(--warning-6))]" />
|
||||||
|
{{ t('caseManagement.caseReview.reReview') }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="markdown-body ml-[48px]" v-html="item.contentText"></div>
|
||||||
|
<div class="ml-[48px] mt-[8px] text-[var(--color-text-4)]">
|
||||||
|
{{ dayjs(item.createTime).format('YYYY-MM-DD HH:mm:ss') }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<MsEmpty v-if="reviewCommentList.length === 0" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
import { Message } from '@arco-design/web-vue';
|
import { Message } from '@arco-design/web-vue';
|
||||||
|
import dayjs from 'dayjs';
|
||||||
|
|
||||||
|
import MSAvatar from '@/components/pure/ms-avatar/index.vue';
|
||||||
|
import MsEmpty from '@/components/pure/ms-empty/index.vue';
|
||||||
import MsComment from '@/components/business/ms-comment';
|
import MsComment from '@/components/business/ms-comment';
|
||||||
import { CommentItem, CommentParams } from '@/components/business/ms-comment/types';
|
import { CommentItem, CommentParams } from '@/components/business/ms-comment/types';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
addOrUpdateCommentList,
|
||||||
deleteCommentList,
|
deleteCommentList,
|
||||||
getCommentList,
|
getCommentList,
|
||||||
getReviewCommentList,
|
getReviewCommentList,
|
||||||
updateCommentList,
|
|
||||||
} from '@/api/modules/case-management/featureCase';
|
} from '@/api/modules/case-management/featureCase';
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
import useModal from '@/hooks/useModal';
|
import useModal from '@/hooks/useModal';
|
||||||
import useFeatureCaseStore from '@/store/modules/case/featureCase';
|
import useFeatureCaseStore from '@/store/modules/case/featureCase';
|
||||||
|
|
||||||
const featureCaseStore = useFeatureCaseStore();
|
const featureCaseStore = useFeatureCaseStore();
|
||||||
const activeTab = computed(() => featureCaseStore.activeTab);
|
// const activeTab = computed(() => featureCaseStore.activeTab);
|
||||||
const { openModal } = useModal();
|
const { openModal } = useModal();
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
caseId: string;
|
caseId: string;
|
||||||
|
activeTab: string;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const activeComment = ref('caseComment');
|
const activeComment = ref('caseComment');
|
||||||
|
@ -104,13 +133,8 @@
|
||||||
|
|
||||||
// 添加或者更新评论
|
// 添加或者更新评论
|
||||||
async function handleUpdateOrAdd(item: CommentParams, cb: (result: boolean) => void) {
|
async function handleUpdateOrAdd(item: CommentParams, cb: (result: boolean) => void) {
|
||||||
debugger;
|
|
||||||
try {
|
try {
|
||||||
if (item.id) {
|
await addOrUpdateCommentList(item);
|
||||||
await updateCommentList(item);
|
|
||||||
} else {
|
|
||||||
await updateCommentList(item);
|
|
||||||
}
|
|
||||||
getAllCommentList();
|
getAllCommentList();
|
||||||
cb(true);
|
cb(true);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|
|
@ -65,9 +65,9 @@
|
||||||
</div>
|
</div>
|
||||||
<ms-base-table ref="tableRef" v-bind="propsRes" v-on="propsEvent">
|
<ms-base-table ref="tableRef" v-bind="propsRes" v-on="propsEvent">
|
||||||
<template #demandName="{ record }">
|
<template #demandName="{ record }">
|
||||||
<a-button type="text" class="flex w-full" @click="openDemandUrl(record.demandUrl)">{{
|
<a-button type="text" class="flex w-full" @click="openDemandUrl(record.demandUrl)"
|
||||||
record.demandName
|
>{{ record.demandName }}<span>({{ (record.children || []).length || 0 }})</span></a-button
|
||||||
}}<span>({{ (record.children || []).length || 0 }})</span></a-button>
|
>
|
||||||
</template>
|
</template>
|
||||||
<template v-for="item in customFields" :key="item.slotName" #[item.dataIndex]="{ record }">
|
<template v-for="item in customFields" :key="item.slotName" #[item.dataIndex]="{ record }">
|
||||||
<span> {{ getSlotName(record, item) }} </span>
|
<span> {{ getSlotName(record, item) }} </span>
|
||||||
|
@ -362,33 +362,33 @@
|
||||||
showAddModel.value = true;
|
showAddModel.value = true;
|
||||||
modelForm.value = { ...initModelForm };
|
modelForm.value = { ...initModelForm };
|
||||||
}
|
}
|
||||||
const activeTab = computed(() => featureCaseStore.activeTab);
|
// const activeTab = computed(() => featureCaseStore.activeTab);
|
||||||
// onMounted(async () => {
|
onMounted(async () => {
|
||||||
// try {
|
try {
|
||||||
// const result = await getCaseRelatedInfo(currentProjectId.value);
|
const result = await getCaseRelatedInfo(currentProjectId.value);
|
||||||
// if (result && result.platform_key) {
|
if (result && result.platform_key) {
|
||||||
// platformInfo.value = { ...result };
|
platformInfo.value = { ...result };
|
||||||
// }
|
|
||||||
// } catch (error) {
|
|
||||||
// console.log(error);
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
|
|
||||||
watch(
|
|
||||||
() => activeTab.value,
|
|
||||||
async (val) => {
|
|
||||||
if (val === 'requirement') {
|
|
||||||
try {
|
|
||||||
const result = await getCaseRelatedInfo(currentProjectId.value);
|
|
||||||
if (result && result.platform_key) {
|
|
||||||
platformInfo.value = { ...result };
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.log(error);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
}
|
}
|
||||||
);
|
});
|
||||||
|
|
||||||
|
// watch(
|
||||||
|
// () => activeTab.value,
|
||||||
|
// async (val) => {
|
||||||
|
// if (val === 'requirement') {
|
||||||
|
// try {
|
||||||
|
// const result = await getCaseRelatedInfo(currentProjectId.value);
|
||||||
|
// if (result && result.platform_key) {
|
||||||
|
// platformInfo.value = { ...result };
|
||||||
|
// }
|
||||||
|
// } catch (error) {
|
||||||
|
// console.log(error);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// );
|
||||||
|
|
||||||
function getPlatName() {
|
function getPlatName() {
|
||||||
switch (platformInfo.value.platform_key) {
|
switch (platformInfo.value.platform_key) {
|
||||||
|
|
|
@ -84,7 +84,7 @@
|
||||||
import { characterLimit } from '@/utils';
|
import { characterLimit } from '@/utils';
|
||||||
|
|
||||||
const featureCaseStore = useFeatureCaseStore();
|
const featureCaseStore = useFeatureCaseStore();
|
||||||
const activeTab = computed(() => featureCaseStore.activeTab);
|
// const activeTab = computed(() => featureCaseStore.activeTab);
|
||||||
|
|
||||||
const appStore = useAppStore();
|
const appStore = useAppStore();
|
||||||
|
|
||||||
|
@ -95,6 +95,7 @@
|
||||||
const keyword = ref<string>('');
|
const keyword = ref<string>('');
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
caseId: string;
|
caseId: string;
|
||||||
|
activeTab: string;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const columns: MsTableColumn = [
|
const columns: MsTableColumn = [
|
||||||
|
@ -216,18 +217,18 @@
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
watch(
|
// watch(
|
||||||
() => activeTab.value,
|
// () => activeTab.value,
|
||||||
(val) => {
|
// (val) => {
|
||||||
if (val === 'dependency') {
|
// if (val === 'dependency') {
|
||||||
initData();
|
// initData();
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
);
|
// );
|
||||||
|
|
||||||
// onMounted(() => {
|
onMounted(() => {
|
||||||
// initData();
|
initData();
|
||||||
// });
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped></style>
|
<style scoped></style>
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
:upload-image="handleUploadImage"
|
:upload-image="handleUploadImage"
|
||||||
class="mt-2"
|
class="mt-2"
|
||||||
/>
|
/>
|
||||||
<div v-else v-dompurify-html="detailForm?.prerequisite || '-'" class="markdown-body"></div>
|
<div v-else v-dompurify-html="detailForm?.prerequisite || '-'"></div>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item
|
<a-form-item
|
||||||
field="step"
|
field="step"
|
||||||
|
@ -69,7 +69,6 @@
|
||||||
<div
|
<div
|
||||||
v-if="detailForm.caseEditType === 'TEXT' && !isEditPreposition"
|
v-if="detailForm.caseEditType === 'TEXT' && !isEditPreposition"
|
||||||
v-dompurify-html="detailForm.textDescription || '-'"
|
v-dompurify-html="detailForm.textDescription || '-'"
|
||||||
class="markdown-body"
|
|
||||||
></div>
|
></div>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item
|
<a-form-item
|
||||||
|
@ -83,7 +82,7 @@
|
||||||
v-model:filed-ids="expectedResultFileIds"
|
v-model:filed-ids="expectedResultFileIds"
|
||||||
:upload-image="handleUploadImage"
|
:upload-image="handleUploadImage"
|
||||||
/>
|
/>
|
||||||
<div v-else v-dompurify-html="detailForm.expectedResult || '-'" class="markdown-body"></div>
|
<div v-else v-dompurify-html="detailForm.expectedResult || '-'"></div>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item field="description" :label="t('caseManagement.featureCase.remark')">
|
<a-form-item field="description" :label="t('caseManagement.featureCase.remark')">
|
||||||
<MsRichText
|
<MsRichText
|
||||||
|
@ -92,7 +91,7 @@
|
||||||
v-model:raw="detailForm.description"
|
v-model:raw="detailForm.description"
|
||||||
:upload-image="handleUploadImage"
|
:upload-image="handleUploadImage"
|
||||||
/>
|
/>
|
||||||
<div v-else v-dompurify-html="detailForm.description || '-'" class="markdown-body"></div>
|
<div v-else v-dompurify-html="detailForm.description || '-'"></div>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<div v-if="isEditPreposition" class="flex justify-end">
|
<div v-if="isEditPreposition" class="flex justify-end">
|
||||||
<a-button type="secondary" @click="handleCancel">{{ t('common.cancel') }}</a-button>
|
<a-button type="secondary" @click="handleCancel">{{ t('common.cancel') }}</a-button>
|
||||||
|
@ -285,7 +284,6 @@
|
||||||
import { getModules, getModulesCount } from '@/api/modules/project-management/fileManagement';
|
import { getModules, getModulesCount } from '@/api/modules/project-management/fileManagement';
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
import useAppStore from '@/store/modules/app';
|
import useAppStore from '@/store/modules/app';
|
||||||
import useFeatureCaseStore from '@/store/modules/case/featureCase';
|
|
||||||
import { downloadByteFile, getGenerateId } from '@/utils';
|
import { downloadByteFile, getGenerateId } from '@/utils';
|
||||||
import { scrollIntoView } from '@/utils/dom';
|
import { scrollIntoView } from '@/utils/dom';
|
||||||
|
|
||||||
|
@ -298,7 +296,7 @@
|
||||||
|
|
||||||
const appStore = useAppStore();
|
const appStore = useAppStore();
|
||||||
const currentProjectId = computed(() => appStore.currentProjectId);
|
const currentProjectId = computed(() => appStore.currentProjectId);
|
||||||
const featureCaseStore = useFeatureCaseStore();
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
const props = withDefaults(
|
const props = withDefaults(
|
||||||
|
@ -306,7 +304,7 @@
|
||||||
form: DetailCase;
|
form: DetailCase;
|
||||||
allowEdit?: boolean; // 是否允许编辑
|
allowEdit?: boolean; // 是否允许编辑
|
||||||
formRules?: FormRuleItem[]; // 编辑表单
|
formRules?: FormRuleItem[]; // 编辑表单
|
||||||
activeTab?: string | number;
|
activeTab?: string;
|
||||||
}>(),
|
}>(),
|
||||||
{
|
{
|
||||||
allowEdit: true, // 是否允许编辑
|
allowEdit: true, // 是否允许编辑
|
||||||
|
|
|
@ -32,7 +32,13 @@
|
||||||
@search="loadCaseList"
|
@search="loadCaseList"
|
||||||
@press-enter="loadCaseList"
|
@press-enter="loadCaseList"
|
||||||
/>
|
/>
|
||||||
<a-select v-model:model-value="type" :options="typeOptions" class="w-[92px]" @change="loadCaseList" :disabled="onlyMineStatus">
|
<a-select
|
||||||
|
v-model:model-value="type"
|
||||||
|
:options="typeOptions"
|
||||||
|
class="w-[92px]"
|
||||||
|
:disabled="onlyMineStatus"
|
||||||
|
@change="loadCaseList"
|
||||||
|
>
|
||||||
</a-select>
|
</a-select>
|
||||||
</div>
|
</div>
|
||||||
<a-spin :loading="caseListLoading" class="h-[calc(100%-46px)] w-full">
|
<a-spin :loading="caseListLoading" class="h-[calc(100%-46px)] w-full">
|
||||||
|
@ -210,7 +216,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="ml-[48px] text-[var(--color-text-2)]" v-html="item.contentText"></div>
|
<div class="markdown-body ml-[48px]" v-html="item.contentText"></div>
|
||||||
<div class="ml-[48px] mt-[8px] text-[var(--color-text-4)]">
|
<div class="ml-[48px] mt-[8px] text-[var(--color-text-4)]">
|
||||||
{{ dayjs(item.createTime).format('YYYY-MM-DD HH:mm:ss') }}
|
{{ dayjs(item.createTime).format('YYYY-MM-DD HH:mm:ss') }}
|
||||||
</div>
|
</div>
|
||||||
|
|
Loading…
Reference in New Issue