fix(系统管理&用例管理): 修复用例bug和补充权限和系统包类型补充

This commit is contained in:
xinxin.wu 2024-01-29 15:08:55 +08:00 committed by 刘瑞斌
parent eaf7160ee5
commit 15fc7e84ae
30 changed files with 314 additions and 181 deletions

View File

@ -52,8 +52,12 @@
onBeforeMount(async () => {
try {
appStore.initSystemVersion(); //
licenseStore.getValidateLicense(); // license
await appStore.initSystemPackage(); //
await appStore.initSystemVersion(); //
// license
if (appStore.packageType === 'enterprise') {
licenseStore.getValidateLicense();
}
if (licenseStore.hasLicense()) {
appStore.initPageConfig(); //
}

View File

@ -41,6 +41,7 @@ import {
GetCaseListUrl,
GetCaseModulesCountUrl,
GetCaseModuleTreeUrl,
getChangeHistoryListUrl,
GetCommentListUrl,
GetDebugDrawerPageUrl,
GetDefaultTemplateFieldsUrl,
@ -54,6 +55,7 @@ import {
GetReviewCommentListUrl,
GetReviewerListUrl,
GetSearchCustomFieldsUrl,
GetThirdDemandUrl,
getTransferTreeUrl,
GetTrashCaseModuleTreeUrl,
importExcelCaseUrl,
@ -79,6 +81,7 @@ import type {
BatchMoveOrCopyType,
CaseManagementTable,
CaseModuleQueryParams,
ChangeHistoryItem,
CreateOrUpdateDemand,
CreateOrUpdateModule,
DeleteCaseType,
@ -230,6 +233,11 @@ export function cancelAssociationDemand(id: string) {
return MSR.get({ url: `${CancelAssociationDemandUrl}/${id}` });
}
// 获取三方关联需求列表
export function getThirdDemandList(data: TableQueryParams) {
return MSR.post({ url: GetThirdDemandUrl, data });
}
// 附件
// 上传文件并关联用例
@ -408,4 +416,9 @@ export function dragSort(data: DragCase) {
return MSR.post({ url: dragSortUrl, data });
}
// 获取已关联缺陷列表
export function getChangeHistoryList(data: TableQueryParams) {
return MSR.post<CommonList<ChangeHistoryItem>>({ url: getChangeHistoryListUrl, data });
}
export default {};

View File

@ -1,6 +1,6 @@
// 系统全局类的接口
import MSR from '@/api/http/index';
import { GetVersionUrl, OrgOptionsUrl, SwitchOrgUrl } from '@/api/requrls/system';
import { GetVersionUrl, OrgOptionsUrl, PackageTypeUrl, SwitchOrgUrl } from '@/api/requrls/system';
// 获取系统版本
export function getSystemVersion() {
@ -16,3 +16,8 @@ export function getOrgOptions() {
export function switchUserOrg(organizationId: string, userId: string) {
return MSR.post({ url: SwitchOrgUrl, data: { organizationId, userId } }, { ignoreCancelToken: true });
}
// 获取当前系统的版本
export function getPackageType() {
return MSR.get<'community' | 'enterprise'>({ url: PackageTypeUrl }, { ignoreCancelToken: true });
}

View File

@ -71,6 +71,8 @@ export const UpdateDemandUrl = '/functional/case/demand/update';
export const BatchAssociationDemandUrl = '/functional/case/demand/batch/relevance';
// 取消关联
export const CancelAssociationDemandUrl = '/functional/case/demand/cancel';
// 获取三方关联需求的接口
export const GetThirdDemandUrl = '/functional/case/demand/third/list/page';
// 附件管理
// 上传文件并关联用例
@ -145,3 +147,5 @@ export const exportExcelCheckUrl = '/functional/case/pre-check/excel';
export const importExcelCaseUrl = '/functional/case/import/excel';
// 用例拖拽排序
export const dragSortUrl = '/functional/case/edit/pos';
// 获取变更历史
export const getChangeHistoryListUrl = '/functional/case/operation-history';

View File

@ -3,3 +3,4 @@
export const GetVersionUrl = '/system/version/current';
export const OrgOptionsUrl = '/system/organization/switch-option';
export const SwitchOrgUrl = '/system/organization/switch';
export const PackageTypeUrl = '/system/version/package-type';

View File

@ -89,7 +89,7 @@
?.filter((item: any) => permission.accessRouter(item) && item.meta?.isTopMenu)
.filter((item: any) => {
if (item.name === RouteEnum.SETTING_SYSTEM_AUTHORIZED_MANAGEMENT) {
return licenseStore.hasLicense();
return appStore.packageType === 'enterprise';
}
return true;
});

View File

@ -12,6 +12,7 @@
:span-all="props.spanAll"
@expand="(rowKey, record) => emit('expand', record)"
@sorter-change="(dataIndex: string,direction: string) => handleSortChange(dataIndex, direction)"
@cell-click="(record: TableData,column: TableColumnData,ev: Event) => emit('cell-click',record, column,ev)"
>
<template #optional="{ rowIndex, record }">
<slot name="optional" v-bind="{ rowIndex, record }" />
@ -59,6 +60,7 @@
:summary-cell-style="item.summaryCellStyle"
:index="item.index"
:tooltip="item.tooltip"
:title="item.slotName"
>
<template #title>
<div :class="{ 'flex w-full flex-row flex-nowrap items-center': !item.align }">
@ -255,7 +257,7 @@
MsTableColumn,
MsTableProps,
} from './type';
import type { TableData } from '@arco-design/web-vue';
import type { TableColumnData, TableData } from '@arco-design/web-vue';
const batchLeft = ref('10px');
const { t } = useI18n();
@ -290,6 +292,7 @@
(e: 'selectAllChange', value: SelectAllEnum): void;
(e: 'sorterChange', value: { [key: string]: string }): void;
(e: 'expand', record: TableData): void | Promise<any>;
(e: 'cell-click', record: TableData, column: TableColumnData, ev: Event): void | Promise<any>;
(e: 'clearSelector'): void;
(e: 'filterChange', dataIndex: string, value: (string | number)[], multiple: boolean, isCustomParam: boolean): void;
}>();

View File

@ -33,6 +33,7 @@ export enum TableKeyEnum {
PROJECT_MANAGEMENT_COMMON_SCRIPT_CHANGE_HISTORY = 'projectManagementCommonScriptChangeHistory',
ORGANIZATION_TEMPLATE_DEFECT_TABLE = 'organizationTemplateManagementDefect',
CASE_MANAGEMENT_TABLE = 'caseManagement',
CASE_MANAGEMENT_RECYCLE_TABLE = 'caseRecycleManagement',
CASE_MANAGEMENT_DETAIL_TABLE = 'caseManagementDetailTable',
CASE_MANAGEMENT_ASSOCIATED_TABLE = 'caseManagementAssociatedFileTable',
BUG_MANAGEMENT = 'bugManagement',

View File

@ -331,3 +331,16 @@ export interface DragCase {
moveMode: 'BEFORE' | 'AFTER' | 'APPEND'[]; // 拖拽类型
moveId: string;
}
// 变更历史
export interface ChangeHistoryItem {
id: string;
projectId: string;
createTime: string;
createUser: string;
sourceId: string;
type: string;
module: string;
refId: string;
createUserName: string;
versionName: string;
}

View File

@ -6,7 +6,7 @@ import type { BreadcrumbItem } from '@/components/business/ms-breadcrumb/types';
import { getProjectInfo } from '@/api/modules/project-management/basicInfo';
import { getPageConfig } from '@/api/modules/setting/config';
import { getSystemVersion } from '@/api/modules/system';
import { getPackageType, getSystemVersion } from '@/api/modules/system';
import { getMenuList } from '@/api/modules/user';
import defaultSettings from '@/config/settings.json';
import { useI18n } from '@/hooks/useI18n';
@ -58,6 +58,7 @@ const useAppStore = defineStore('app', {
...defaultLoginConfig,
...defaultPlatformConfig,
},
packageType: 'community',
}),
getters: {
@ -210,6 +211,16 @@ const useAppStore = defineStore('app', {
console.log(error);
}
},
/**
*
*/
async initSystemPackage() {
try {
this.packageType = await getPackageType();
} catch (error) {
console.log(error);
}
},
/**
*
*/

View File

@ -37,6 +37,7 @@ export interface AppState {
pageConfig: PageConfig;
innerHeight: number;
currentMenuConfig: string[];
packageType: 'community' | 'enterprise';
}
export interface UploadFileTaskState {

View File

@ -83,6 +83,12 @@ const useUserStore = defineStore('user', {
appStore.setCurrentOrgId(res.lastOrganizationId || '');
appStore.setCurrentProjectId(res.lastProjectId || '');
this.setInfo(res);
// 登录后初始化系统包版本
appStore.initSystemPackage();
if (appStore.packageType === 'enterprise') {
const licenseStore = useLicenseStore();
licenseStore.getValidateLicense();
}
} catch (err) {
clearToken();
throw err;

View File

@ -73,6 +73,7 @@
async function save(isReview: boolean) {
try {
loading.value = true;
//
if (route.params.mode === 'edit') {
await updateCaseRequest(caseDetailInfo.value);
Message.success(t('caseManagement.featureCase.editSuccess'));
@ -80,7 +81,9 @@
name: CaseManagementRouteEnum.CASE_MANAGEMENT_CASE,
query: { organizationId: route.query.organizationId, projectId: route.query.projectId },
});
//
} else {
//
if (isReview) {
caseDetailInfo.value.request.reviewId = route.query.reviewId;
}
@ -89,6 +92,10 @@
Message.success(route.params.mode === 'copy' ? t('ms.description.copySuccess') : t('common.addSuccess'));
featureCaseStore.setIsAlreadySuccess(true);
isShowTip.value = !getIsVisited();
if (isReview) {
router.back();
return;
}
if (isShowTip.value && !route.query.id) {
router.push({
name: CaseManagementRouteEnum.CASE_MANAGEMENT_CASE_CREATE_SUCCESS,
@ -97,25 +104,16 @@
...route.query,
},
});
} else {
router.push({
name: CaseManagementRouteEnum.CASE_MANAGEMENT_CASE,
query: {
organizationId: route.query.organizationId,
projectId: route.query.projectId,
},
});
}
}
if (isReview) {
router.back();
return;
}
router.push({ name: CaseManagementRouteEnum.CASE_MANAGEMENT_CASE, query: { ...route.query } });
featureCaseStore.setIsAlreadySuccess(true);
isShowTip.value = !getIsVisited();
if (isShowTip.value && !route.query.id) {
router.push({
name: CaseManagementRouteEnum.CASE_MANAGEMENT_CASE_CREATE_SUCCESS,
query: {
id: createSuccessId.value,
...route.query,
},
});
}
} catch (error) {
// eslint-disable-next-line no-console
console.log(error);

View File

@ -124,7 +124,7 @@
<TabCaseReview v-else-if="activeTab === 'caseReview'" :case-id="props.detailId" />
<TabTestPlan v-else-if="activeTab === 'testPlan'" />
<TabComment v-else-if="activeTab === 'comments'" ref="commentRef" :case-id="props.detailId" />
<TabChangeHistory v-else-if="activeTab === 'changeHistory'" />
<TabChangeHistory v-else-if="activeTab === 'changeHistory'" :case-id="props.detailId" />
</div>
</div>
</template>
@ -520,7 +520,7 @@
event: notifiers ? 'AT' : 'COMMENT', // (: COMMENT; @: AT; /@: REPLAY;)
};
await createCommentList(params);
commentRef.value.initCommentList();
commentRef.value.getAllCommentList();
Message.success(t('common.publishSuccessfully'));
} catch (error) {
console.log(error);

View File

@ -32,6 +32,7 @@
v-on="propsEvent"
@batch-action="handleTableBatch"
@change="changeHandler"
@cell-click="showCaseDetailEvent"
>
<template #num="{ record, rowIndex }">
<span class="flex w-full" @click="showCaseDetail(record.id, rowIndex)">{{ record.num }}</span>
@ -84,8 +85,13 @@
</template>
<!-- 渲染自定义字段开始TODO -->
<template v-for="item in customFieldsColumns" :key="item.slotName" #[item.slotName]="{ record }">
<a-tooltip :content="getTableFields(record.customFields, item)" position="top" :mouse-enter-delay="100" mini>
<div>{{ getTableFields(record.customFields, item) }}</div>
<a-tooltip
:content="getTableFields(record.customFields, item as MsTableColumn)"
position="top"
:mouse-enter-delay="100"
mini
>
<div>{{ getTableFields(record.customFields, item as MsTableColumn) }}</div>
</a-tooltip>
</template>
<!-- 渲染自定义字段结束 -->
@ -194,7 +200,7 @@
<script setup lang="ts">
import { ref } from 'vue';
import { useRoute, useRouter } from 'vue-router';
import { Message, TableChangeExtra, TableData } from '@arco-design/web-vue';
import { Message, TableChangeExtra, TableColumnData, TableData } from '@arco-design/web-vue';
import { CustomTypeMaps, MsAdvanceFilter } from '@/components/pure/ms-advance-filter';
import { FilterFormItem, FilterResult, FilterType } from '@/components/pure/ms-advance-filter/type';
@ -396,8 +402,8 @@
},
{
title: 'caseManagement.featureCase.tableColumnVersion',
slotName: 'versionId',
dataIndex: 'versionId',
slotName: 'versionName',
dataIndex: 'versionNam',
width: 300,
showTooltip: true,
showInTable: true,
@ -419,6 +425,18 @@
isTag: true,
showDrag: true,
},
{
title: 'caseManagement.featureCase.tableColumnUpdateUser',
slotName: 'updateUserName',
dataIndex: 'updateUserName',
sortable: {
sortDirections: ['ascend', 'descend'],
sorter: true,
},
showInTable: true,
width: 200,
showDrag: true,
},
{
title: 'caseManagement.featureCase.tableColumnUpdateTime',
slotName: 'updateTime',
@ -433,8 +451,8 @@
},
{
title: 'caseManagement.featureCase.tableColumnCreateUser',
slotName: 'createUser',
dataIndex: 'createUser',
slotName: 'createUserName',
dataIndex: 'createUserName',
showInTable: true,
width: 200,
showDrag: true,
@ -1121,21 +1139,24 @@
//
async function changeHandler(data: TableData[], extra: TableChangeExtra, currentData: TableData[]) {
if (currentData.length === 1) {
return;
}
if (extra && extra.dragTarget?.id) {
const params: DragCase = {
projectId: currentProjectId.value,
targetId: '',
targetId: '', // id
moveMode: 'BEFORE',
moveId: extra.dragTarget.id as string,
moveId: extra.dragTarget.id as string, // id
};
const index = currentData.findIndex((item: any) => item.raw.id === extra.dragTarget?.id);
const index = currentData.findIndex((item: any) => item.key === extra.dragTarget?.id);
if (index > -1 && currentData[index + 1].raw) {
params.moveMode = 'AFTER';
if (index > -1 && currentData[index + 1]) {
params.moveMode = 'BEFORE';
params.targetId = currentData[index + 1].raw.id;
} else if (index > -1 && !currentData[index + 1].raw) {
if (index > -1 && currentData[index - 1].raw) {
params.moveMode = 'BEFORE';
} else if (index > -1 && !currentData[index + 1]) {
if (index > -1 && currentData[index - 1]) {
params.moveMode = 'AFTER';
params.targetId = currentData[index - 1].raw.id;
}
}
@ -1149,7 +1170,13 @@
}
}
onBeforeMount(() => {
function showCaseDetailEvent(record: TableData, column: TableColumnData, ev: Event) {
if (column.title === 'name' || column.title === 'num') {
const rowIndex = propsRes.value.data.map((item: any) => item.id).indexOf(record.id);
showCaseDetail(record.id, rowIndex);
}
}
onMounted(() => {
if (route.query.id) {
showCaseDetail(route.query.id as string, 0);
}

View File

@ -84,6 +84,9 @@
v-on="propsEvent"
@batch-action="handleTableBatch"
>
<template #num="{ record }">
<span class="flex w-full">{{ record.num }}</span>
</template>
<template #caseLevel="{ record }">
<caseLevel :case-level="(getCaseLevels(record.customFields) as CaseLevel)" />
</template>
@ -108,21 +111,17 @@
<span class="one-line-text inline-block">{{ getModules(record.moduleId) }}</span>
</a-tooltip>
</template>
<!-- 自定义字段非系统TODO -->
<!-- <template v-for="item in customFieldsColumns" :key="item.slotName" #[item.slotName]="{ record }">
<div v-if="isCaseLevel(item.slotName as string).name === '用例等级'" class="flex items-center">
<span v-if="!record.visible" class="flex items-center" @click="record.visible = true">
<caseLevel :case-level="getCaseLevel(record, item)" />
</span>
</div>
<div v-if="isCaseLevel(item.slotName as string).name === '用例状态'" class="flex items-center">
<MsTag
:type="getCaseState(record[item.slotName as string]).type"
:theme="getCaseState(record[item.slotName as string]).theme"
>{{ record[item.slotName as string] }}</MsTag
>
</div>
</template> -->
<!-- 回收站自定义字段 -->
<template v-for="item in customFieldsColumns" :key="item.slotName" #[item.slotName]="{ record }">
<a-tooltip
:content="getTableFields(record.customFields, item as MsTableColumn)"
position="top"
:mouse-enter-delay="100"
mini
>
<div>{{ getTableFields(record.customFields, item as MsTableColumn) }}</div>
</a-tooltip>
</template>
<template #operation="{ record }">
<MsButton v-permission="['FUNCTIONAL_CASE:READ+DELETE']" @click="recoverCase(record.id)">{{
t('caseManagement.featureCase.batchRecover')
@ -154,12 +153,7 @@
import MsIcon from '@/components/pure/ms-icon-font/index.vue';
import MsSplitBox from '@/components/pure/ms-split-box/index.vue';
import MsBaseTable from '@/components/pure/ms-table/base-table.vue';
import type {
BatchActionParams,
BatchActionQueryParams,
MsTableColumn,
MsTableColumnData,
} from '@/components/pure/ms-table/type';
import type { BatchActionParams, BatchActionQueryParams, MsTableColumn } from '@/components/pure/ms-table/type';
import useTable from '@/components/pure/ms-table/useTable';
import type { TagType, Theme } from '@/components/pure/ms-tag/ms-tag.vue';
import caseLevel from '@/components/business/ms-case-associate/caseLevel.vue';
@ -193,7 +187,7 @@
import { ModuleTreeNode } from '@/models/projectManagement/file';
import { TableKeyEnum } from '@/enums/tableEnum';
import { getCaseLevels, getReviewStatusClass, getStatusText } from './utils';
import { getCaseLevels, getReviewStatusClass, getStatusText, getTableFields } from './utils';
const tableStore = useTableStore();
const featureCaseStore = useFeatureCaseStore();
@ -211,7 +205,7 @@
const { propsRes, propsEvent, loadList, setLoadListParams, resetSelector, setAdvanceFilter } = useTable(
getRecycleListRequest,
{
tableKey: TableKeyEnum.FILE_MANAGEMENT_CASE_RECYCLE,
tableKey: TableKeyEnum.CASE_MANAGEMENT_RECYCLE_TABLE,
scroll: { x: scrollWidth.value },
selectable: true,
showSetting: true,
@ -228,20 +222,21 @@
}),
})
);
const columns: MsTableColumn = [
{
title: 'caseManagement.featureCase.tableColumnID',
dataIndex: 'id',
width: 200,
showInTable: true,
sortable: {
'title': 'caseManagement.featureCase.tableColumnID',
'slotName': 'num',
'dataIndex': 'num',
'width': 200,
'showInTable': true,
'sortable': {
sortDirections: ['ascend', 'descend'],
sorter: true,
},
showTooltip: true,
ellipsis: true,
showDrag: false,
'filter-icon-align-left': true,
'showTooltip': true,
'ellipsis': true,
'showDrag': false,
},
{
title: 'caseManagement.featureCase.tableColumnName',
@ -264,15 +259,6 @@
width: 200,
showDrag: true,
},
{
title: 'caseManagement.featureCase.tableColumnCaseState',
dataIndex: 'caseState',
showInTable: true,
width: 200,
showTooltip: true,
ellipsis: true,
showDrag: true,
},
{
title: 'caseManagement.featureCase.tableColumnReviewResult',
dataIndex: 'reviewStatus',
@ -291,8 +277,8 @@
},
{
title: 'caseManagement.featureCase.tableColumnVersion',
slotName: 'versionId',
dataIndex: 'versionId',
slotName: 'versionName',
dataIndex: 'versionNam',
width: 300,
showTooltip: true,
showInTable: true,
@ -301,6 +287,7 @@
{
title: 'caseManagement.featureCase.tableColumnModule',
slotName: 'moduleId',
dataIndex: 'moduleId',
showInTable: true,
width: 300,
showDrag: true,
@ -314,28 +301,13 @@
showDrag: true,
},
{
title: 'caseManagement.featureCase.tableColumnCreateUser',
slotName: 'createUser',
dataIndex: 'createUser',
showInTable: true,
showDrag: true,
},
{
title: 'caseManagement.featureCase.tableColumnCreateTime',
slotName: 'createTime',
dataIndex: 'createTime',
showInTable: true,
title: 'caseManagement.featureCase.tableColumnUpdateUser',
slotName: 'updateUserName',
dataIndex: 'updateUserName',
sortable: {
sortDirections: ['ascend', 'descend'],
sorter: true,
},
width: 200,
showDrag: true,
},
{
title: 'caseManagement.featureCase.tableColumnUpdateUser',
slotName: 'updateUser',
dataIndex: 'updateUser',
showInTable: true,
width: 200,
showDrag: true,
@ -352,12 +324,31 @@
width: 200,
showDrag: true,
},
{
title: 'caseManagement.featureCase.tableColumnCreateUser',
slotName: 'createUserName',
dataIndex: 'createUserName',
showInTable: true,
width: 200,
showDrag: true,
},
{
title: 'caseManagement.featureCase.tableColumnCreateTime',
slotName: 'createTime',
dataIndex: 'createTime',
showInTable: true,
sortable: {
sortDirections: ['ascend', 'descend'],
},
width: 200,
showDrag: true,
},
{
title: 'caseManagement.featureCase.tableColumnActions',
slotName: 'operation',
dataIndex: 'operation',
fixed: 'right',
width: 140,
width: 260,
showInTable: true,
showDrag: false,
},
@ -668,13 +659,12 @@
//
async function getDefaultFields() {
const result = await getCaseDefaultFields(currentProjectId.value);
initDefaultFields.value = result.customFields;
initDefaultFields.value = result.customFields.filter((item: any) => !item.internal);
customFieldsColumns = initDefaultFields.value.map((item: any) => {
return {
title: item.fieldName,
slotName: item.fieldId as string,
dataIndex: item.fieldId,
showTooltip: true,
showInTable: true,
showDrag: true,
width: 300,
@ -686,7 +676,7 @@
...customFieldsColumns,
...columns.slice(columns.length - 1, columns.length),
];
tableStore.initColumn(TableKeyEnum.CASE_MANAGEMENT_TABLE, fullColumns, 'drawer');
tableStore.initColumn(TableKeyEnum.CASE_MANAGEMENT_RECYCLE_TABLE, fullColumns, 'drawer');
tableRef.value?.initColumn(fullColumns);
}
@ -737,7 +727,7 @@
},
{
title: 'caseManagement.featureCase.tableColumnUpdateUser',
dataIndex: 'updateUser',
dataIndex: 'updateUserName',
type: FilterType.SELECT,
selectProps: {
mode: 'static',
@ -826,7 +816,7 @@
getRecycleModules();
initRecycleModulesCount();
});
tableStore.initColumn(TableKeyEnum.FILE_MANAGEMENT_CASE_RECYCLE, columns, 'drawer');
tableStore.initColumn(TableKeyEnum.CASE_MANAGEMENT_RECYCLE_TABLE, columns, 'drawer');
</script>
<style scoped lang="less">

View File

@ -89,17 +89,17 @@
enable: true,
},
],
testPlan: [
{
key: 'testPlan',
title: 'caseManagement.featureCase.testPlan',
enable: true,
},
],
// testPlan: [
// {
// key: 'testPlan',
// title: 'caseManagement.featureCase.testPlan',
// enable: true,
// },
// ],
});
let buggerTab: TabItemType[] = [];
let testPlanTab: TabItemType[] = [];
// let testPlanTab: TabItemType[] = [];
function getTabList() {
if (licenseStore.hasLicense()) {
@ -134,25 +134,29 @@
title: 'caseManagement.featureCase.comments',
enable: true,
},
...getTabList(),
// TOTO Xpack
// ...getTabList(),
]);
async function getTabModule() {
buggerTab = [];
testPlanTab = [];
// testPlanTab = [];
const result = await postTabletList({ projectId: currentProjectId.value });
const enableModuleArr = result.filter((item: any) => item.module === 'testPlan' || item.module === 'bugManagement');
// TODO
// const enableModuleArr = result.filter((item: any) => item.module === 'testPlan' || item.module === 'bugManagement');
const enableModuleArr = result.filter((item: any) => item.module === 'bugManagement');
enableModuleArr.forEach((item) => {
if (item.module === 'bugManagement') {
buggerTab.push(...moduleTab.value[item.module]);
} else if (item.module === 'testPlan') {
testPlanTab.push(...moduleTab.value[item.module]);
}
// else if (item.module === 'testPlan') {
// testPlanTab.push(...moduleTab.value[item.module]);
// }
});
const newTabDefaultSettingList = [
tabDefaultSettingList.value[0],
...buggerTab,
...tabDefaultSettingList.value.slice(1, -2),
...testPlanTab,
// ...testPlanTab,
tabDefaultSettingList.value[tabDefaultSettingList.value.length - 2],
tabDefaultSettingList.value[tabDefaultSettingList.value.length - 1],
];

View File

@ -21,9 +21,9 @@
<a-radio value="link" class="show-type-icon p-[2px]">{{
t('caseManagement.featureCase.directLink')
}}</a-radio>
<a-radio value="testPlan" class="show-type-icon p-[2px]">{{
<!-- <a-radio value="testPlan" class="show-type-icon p-[2px]">{{
t('caseManagement.featureCase.testPlan')
}}</a-radio>
}}</a-radio> -->
</a-radio-group>
<a-input-search
v-model:model-value="keyword"
@ -135,7 +135,7 @@
const columns: MsTableColumn = [
{
title: 'caseManagement.featureCase.tableColumnID',
dataIndex: 'id',
dataIndex: 'num',
width: 200,
showInTable: true,
showTooltip: true,

View File

@ -57,7 +57,7 @@
const columns: MsTableColumn = [
{
title: 'ID',
dataIndex: 'reviewId',
dataIndex: 'reviewNum',
sortIndex: 1,
showTooltip: true,
width: 300,

View File

@ -12,6 +12,7 @@
<template #name="{ record }">
<a-button type="text" class="px-0">{{ record.name }}</a-button>
</template>
<template #type> </template>
<template #operation="{ record }">
<MsRemoveButton
position="br"
@ -78,37 +79,43 @@
import MsFormItemSub from '@/components/business/ms-form-item-sub/index.vue';
import MsRemoveButton from '@/components/business/ms-remove-button/MsRemoveButton.vue';
import { getRecycleListRequest } from '@/api/modules/case-management/featureCase';
import { getChangeHistoryList } from '@/api/modules/case-management/featureCase';
import { useI18n } from '@/hooks/useI18n';
import useModal from '@/hooks/useModal';
import useVisit from '@/hooks/useVisit';
import { useAppStore } from '@/store';
import { characterLimit } from '@/utils';
import { TableKeyEnum } from '@/enums/tableEnum';
const { t } = useI18n();
const appStore = useAppStore();
const visitedKey = 'notRemindChangeHistoryTip';
const { addVisited } = useVisit(visitedKey);
const { getIsVisited } = useVisit(visitedKey);
const props = defineProps<{
caseId: string;
}>();
const columns: MsTableColumn = [
{
title: 'caseManagement.featureCase.changeNumber',
dataIndex: 'changeNumber',
dataIndex: 'id',
showTooltip: true,
width: 90,
},
{
title: 'caseManagement.featureCase.changeType',
slotName: 'changeType',
dataIndex: 'changeType',
slotName: 'type',
dataIndex: 'type',
width: 200,
},
{
title: 'caseManagement.featureCase.operator',
dataIndex: 'operator',
slotName: 'operator',
dataIndex: 'createUser',
slotName: 'createUser',
width: 150,
},
{
@ -128,7 +135,7 @@
},
];
const { propsRes, propsEvent, loadList, setLoadListParams, resetSelector } = useTable(getRecycleListRequest, {
const { propsRes, propsEvent, loadList, setLoadListParams, resetSelector } = useTable(getChangeHistoryList, {
columns,
tableKey: TableKeyEnum.CASE_MANAGEMENT_TAB_CHANGE_HISTORY,
scroll: { x: '100%' },
@ -209,8 +216,18 @@
isShowTip.value = !getIsVisited();
};
function initData() {
setLoadListParams({
projectId: appStore.currentProjectId,
sourceId: props.caseId,
module: 'FUNCTIONAL_CASE',
});
loadList();
}
onBeforeMount(() => {
doCheckIsTip();
initData();
});
</script>

View File

@ -15,7 +15,7 @@
}}</MsButton>
</template>
<template v-if="(props.funParams.keyword || '').trim() === ''" #empty>
<div class="flex w-full w-full items-center justify-center">
<div class="flex w-full items-center justify-center">
{{ t('caseManagement.caseReview.tableNoData') }}
<MsButton class="ml-[8px]" @click="emit('create')">
{{ t('caseManagement.featureCase.addDemand') }}
@ -49,6 +49,7 @@
funParams: {
caseId: string;
keyword: string;
projectId: string;
}; //
isShowOperation?: boolean; //
highlightName?: boolean; //
@ -106,8 +107,7 @@
});
const initData = async () => {
const { keyword, caseId } = props.funParams;
setLoadListParams({ keyword, caseId });
setLoadListParams({ ...props.funParams });
loadList();
};

View File

@ -21,7 +21,7 @@
</div>
<AssociatedDemandTable
ref="demandRef"
:fun-params="{ caseId: props.caseId, keyword }"
:fun-params="{ caseId: props.caseId, keyword, projectId: currentProjectId }"
@update="updateDemand"
@create="addDemand"
></AssociatedDemandTable>
@ -29,7 +29,7 @@
<MsDrawer
v-model:visible="linkDemandDrawer"
:mask="false"
:title="t('caseManagement.featureCase.associatedFile')"
:title="t('caseManagement.featureCase.associatedDemand')"
:ok-text="t('caseManagement.featureCase.associated')"
:ok-loading="drawerLoading"
:ok-disabled="tableSelected.length < 1"
@ -40,7 +40,10 @@
@cancel="handleDrawerCancel"
>
<div class="flex items-center justify-between">
<div><span class="font-medium">XXXXXXXXX</span><span class="ml-1 text-[var(--color-text-4)]">(101)</span></div>
<div
><span class="font-medium">XXXXXXXXX</span
><span class="ml-1 text-[var(--color-text-4)]">({{ propsRes.value }})</span></div
>
<a-input-search
v-model="platformKeyword"
:max-length="250"
@ -74,7 +77,7 @@
import AddDemandModal from './addDemandModal.vue';
import AssociatedDemandTable from './associatedDemandTable.vue';
import { batchAssociationDemand, getDemandList } from '@/api/modules/case-management/featureCase';
import { batchAssociationDemand, getThirdDemandList } from '@/api/modules/case-management/featureCase';
import { useI18n } from '@/hooks/useI18n';
import { useAppStore } from '@/store';
@ -84,6 +87,8 @@
const { t } = useI18n();
const appStore = useAppStore();
const currentProjectId = computed(() => appStore.currentProjectId);
const props = defineProps<{
caseId: string;
}>();
@ -160,7 +165,7 @@
},
];
const { propsRes, propsEvent, loadList, setLoadListParams, resetSelector } = useTable(getDemandList, {
const { propsRes, propsEvent, loadList, setLoadListParams, resetSelector } = useTable(getThirdDemandList, {
tableKey: TableKeyEnum.CASE_MANAGEMENT_TAB_DEMAND_PLATFORM,
columns,
rowKey: 'id',
@ -206,7 +211,7 @@
showDrawer.value = false;
}
// ()
//
const linkDemandDrawer = ref<boolean>(false);
function associatedDemand() {
linkDemandDrawer.value = true;
@ -215,8 +220,8 @@
const platformKeyword = ref<string>('');
const initData = async () => {
setLoadListParams({ keyword: platformKeyword.value });
// loadList();
setLoadListParams({ keyword: platformKeyword.value, projectId: currentProjectId.value });
loadList();
};
const searchHandler = () => {
@ -224,10 +229,19 @@
resetSelector();
};
onMounted(() => {
resetSelector();
initData();
});
watch(
() => linkDemandDrawer.value,
(val) => {
if (val) {
resetSelector();
initData();
}
}
);
// onMounted(() => {
// resetSelector();
// initData();
// });
</script>
<style scoped></style>

View File

@ -250,7 +250,7 @@
const columns: MsTableColumn = [
{
title: 'ID',
dataIndex: 'id',
dataIndex: 'num',
sortIndex: 1,
showTooltip: true,
sortable: {

View File

@ -1,3 +1,4 @@
import { MsTableColumnData } from '@/components/pure/ms-table/type';
import type { MsFileItem } from '@/components/pure/ms-upload/types';
import type { CaseLevel } from '@/components/business/ms-case-associate/types';
@ -133,30 +134,35 @@ export function getCaseLevels(customFields: CustomAttributes[]): CaseLevel {
}
// 处理自定义字段
export function getTableFields(customFields: any, itemDataIndex: any) {
export function getTableFields(customFields: CustomAttributes[], itemDataIndex: MsTableColumnData) {
const multipleExcludes = ['MULTIPLE_SELECT', 'CHECKBOX', 'MULTIPLE_MEMBER'];
const selectExcludes = ['MEMBER', 'RADIO', 'SELECT'];
const currentColumnData = customFields.find((item: any) => itemDataIndex.dataIndex === item.fieldId);
// 处理多选项
if (multipleExcludes.includes(currentColumnData.type)) {
const selectValue = JSON.parse(currentColumnData.defaultValue);
return currentColumnData.options
.filter((item: any) => selectValue.includes(item.value))
.map((it: any) => it.text)
.join(',');
const currentColumnData: CustomAttributes | undefined = customFields.find(
(item: any) => itemDataIndex.dataIndex === item.fieldId
);
if (currentColumnData) {
// 处理多选项
if (multipleExcludes.includes(currentColumnData.type)) {
const selectValue = JSON.parse(currentColumnData.defaultValue);
return currentColumnData.options
.filter((item: any) => selectValue.includes(item.value))
.map((it: any) => it.text)
.join(',');
}
if (currentColumnData.type === 'MULTIPLE_INPUT') {
// 处理标签形式
return JSON.parse(currentColumnData.defaultValue).join('');
}
if (selectExcludes.includes(currentColumnData.type)) {
return currentColumnData.options
.filter((item: any) => currentColumnData.defaultValue === item.value)
.map((it: any) => it.text)
.join();
}
return currentColumnData.defaultValue;
}
if (currentColumnData.type === 'MULTIPLE_INPUT') {
// 处理标签形式
return JSON.parse(currentColumnData.defaultValue).join('');
}
if (selectExcludes.includes(currentColumnData.type)) {
return currentColumnData.options
.filter((item: any) => currentColumnData.defaultValue === item.value)
.map((it: any) => it.text)
.join();
}
return currentColumnData.defaultValue;
}
export default {};

View File

@ -219,7 +219,7 @@
</div>
<caseTabDemand
ref="caseDemandRef"
:fun-params="{ caseId: route.query.caseId as string, keyword: demandKeyword }"
:fun-params="{ caseId: route.query.caseId as string, keyword: demandKeyword,projectId:appStore.currentProjectId }"
/>
</div>
</div>

View File

@ -8,16 +8,17 @@
<span class="title-welcome">{{ innerSlogan || t('login.form.title') }}</span>
</div>
</div>
<div class="form mt-[32px]">
<div class="form mt-[32px] min-w-[416px]">
<a-form ref="formRef" :model="userInfo" @submit="handleSubmit">
<a-form-item class="login-form-item" field="radio" hide-label>
<!-- TOTO 第一版本暂时只考虑普通登录 -->
<!-- <a-form-item class="login-form-item" field="radio" hide-label>
<a-radio-group v-model="userInfo.authenticate" type="button">
<a-radio value="LOCAL">普通登陆</a-radio>
<a-radio v-xpack value="LDAP">LDAP</a-radio>
<a-radio value="OAuth2">OAuth2 测试</a-radio>
<a-radio value="OIDC 90">OIDC 90</a-radio>
<a-radio v-xpack value="OAuth2">OAuth2 测试</a-radio>
<a-radio v-xpack value="OIDC 90">OIDC 90</a-radio>
</a-radio-group>
</a-form-item>
</a-form-item> -->
<a-form-item
class="login-form-item"
field="username"

View File

@ -26,7 +26,11 @@
<span class="font-normal">{{ t(item.title) }}</span>
<span>
<a-tooltip
:content="isHasSystemPermission ? '' : t('organization.service.noPermissionsTip')"
:content="
isHasSystemPermission
? t('organization.service.jumpPlugin')
: t('organization.service.noPermissionsTip')
"
position="bottom"
>
<a-button

View File

@ -20,7 +20,7 @@
<a-input-number
v-model:model-value="timeCount"
class="w-[130px]"
:disabled="saveLoading"
:disabled="saveLoading || !userStore.isAdmin"
@blur="() => saveConfig()"
>
<template #append>
@ -61,7 +61,9 @@
import { getCleanupConfig, saveCleanupConfig } from '@/api/modules/setting/config';
import { useI18n } from '@/hooks/useI18n';
import { useUserStore } from '@/store';
const userStore = useUserStore();
const { t } = useI18n();
const loading = ref(false);

View File

@ -113,10 +113,15 @@
<MsButton v-permission="['SYSTEM_PLUGIN:READ+UPDATE']" @click="update(record)">{{
t('system.plugin.edit')
}}</MsButton>
<MsButton v-if="record.enable" @click="disableHandler(record)">{{
t('system.plugin.tableDisable')
<MsButton
v-if="record.enable"
v-permission="['SYSTEM_PLUGIN:READ+UPDATE']"
@click="disableHandler(record)"
>{{ t('system.plugin.tableDisable') }}</MsButton
>
<MsButton v-else v-permission="['SYSTEM_PLUGIN:READ+UPDATE']" @click="enableHandler(record)">{{
t('system.plugin.tableEnable')
}}</MsButton>
<MsButton v-else @click="enableHandler(record)">{{ t('system.plugin.tableEnable') }}</MsButton>
<MsTableMoreAction
v-permission="['SYSTEM_PLUGIN:READ+DELETE']"
:list="tableActions"

View File

@ -456,10 +456,12 @@
{
label: 'system.user.resetPassword',
eventTag: 'resetPassword',
permission: ['SYSTEM_USER:READ+UPDATE'],
},
{
label: 'system.user.disable',
eventTag: 'disabled',
permission: ['SYSTEM_USER:READ+UPDATE'],
},
{
isDivider: true,
@ -468,6 +470,7 @@
label: 'system.user.delete',
eventTag: 'delete',
danger: true,
permission: ['SYSTEM_USER:READ+DELETE'],
},
];