fix(全局): 补充操作列权限和用例评审权限&修改全局bug

This commit is contained in:
xinxin.wu 2024-02-05 15:13:23 +08:00 committed by 刘瑞斌
parent fbef87ad59
commit 87c2ee444b
37 changed files with 246 additions and 160 deletions

View File

@ -18,9 +18,9 @@
class="mr-[2px] text-xl text-[rgb(var(--danger-6))]" class="mr-[2px] text-xl text-[rgb(var(--danger-6))]"
/> />
</slot> </slot>
<span :class="[titleClass]"> <div :class="[titleClass]">
{{ props.title || '' }} {{ props.title || '' }}
</span> </div>
</div> </div>
<!-- 描述展示 --> <!-- 描述展示 -->
<div v-if="props.subTitleTip" class="ml-8 mt-2 text-sm text-[var(--color-text-2)]"> <div v-if="props.subTitleTip" class="ml-8 mt-2 text-sm text-[var(--color-text-2)]">
@ -59,7 +59,7 @@
/> />
</a-form-item> </a-form-item>
</a-form> </a-form>
<div class="mt-4 flex flex-row flex-nowrap justify-end gap-2"> <div class="mb-1 mt-4 flex flex-row flex-nowrap justify-end gap-2">
<a-button type="secondary" size="mini" :disabled="props.loading" @click="handleCancel"> <a-button type="secondary" size="mini" :disabled="props.loading" @click="handleCancel">
{{ props.cancelText || t('common.cancel') }} {{ props.cancelText || t('common.cancel') }}
</a-button> </a-button>
@ -171,7 +171,7 @@
const titleClass = computed(() => { const titleClass = computed(() => {
return props.isDelete return props.isDelete
? 'ml-2 font-medium text-[var(--color-text-1)] text-[14px]' ? 'ml-2 font-medium text-[var(--color-text-1)] text-[14px]'
: 'mb-[8px] font-medium text-[var(--color-text-1)] text-[14px]'; : 'mb-[8px] font-medium text-[var(--color-text-1)] text-[14px] leading-[22px]';
}); });
watch( watch(
@ -215,4 +215,8 @@
}); });
</script> </script>
<style scoped lang="less"></style> <style scoped lang="less">
:deep(.arco-trigger-content) {
padding: 16px;
}
</style>

View File

@ -53,8 +53,9 @@
</div> </div>
<div class="flex-col"> <div class="flex-col">
<div v-for="item in nonSortColumn" :key="item.dataIndex" class="column-item"> <div v-for="item in nonSortColumn" :key="item.dataIndex" class="column-item">
<div>{{ t((item.title || item.columnTitle) as string) }}</div> <div v-show="item.dataIndex !== 'operation'">{{ t((item.title || item.columnTitle) as string) }}</div>
<a-switch <a-switch
v-show="item.dataIndex !== 'operation'"
v-model="item.showInTable" v-model="item.showInTable"
size="small" size="small"
:disabled="item.dataIndex === 'name' || item.dataIndex === 'operation'" :disabled="item.dataIndex === 'name' || item.dataIndex === 'operation'"

View File

@ -95,12 +95,19 @@ export const pathMap: PathMapItem[] = [
level: MENU_LEVEL[2], level: MENU_LEVEL[2],
children: [ children: [
{ {
key: 'CASE_MANAGEMENT_CASE_DETAIL', // 功能测试-功能用例详情 key: 'CASE_MANAGEMENT_CASE_CREATE', // 功能测试-功能用例创建
locale: 'menu.caseManagement.featureCaseDetail', locale: 'menu.caseManagement.featureCaseDetail',
route: RouteEnum.CASE_MANAGEMENT_CASE_DETAIL, route: RouteEnum.CASE_MANAGEMENT_CASE_DETAIL,
permission: [], permission: [],
level: MENU_LEVEL[2], level: MENU_LEVEL[2],
}, },
{
key: 'CASE_MANAGEMENT_CASE_UPDATE', // 功能测试-功能用例更新
locale: 'menu.caseManagement.featureCaseEdit',
route: RouteEnum.CASE_MANAGEMENT_CASE_DETAIL,
permission: [],
level: MENU_LEVEL[2],
},
{ {
key: 'CASE_MANAGEMENT_CASE_CREATE_SUCCESS', // 功能测试-功能用例创建成功页面 key: 'CASE_MANAGEMENT_CASE_CREATE_SUCCESS', // 功能测试-功能用例创建成功页面
locale: 'menu.caseManagement.featureCaseCreateSuccess', locale: 'menu.caseManagement.featureCaseCreateSuccess',

View File

@ -68,7 +68,7 @@ export default {
'menu.settings.organization.userGroup': '用户组', 'menu.settings.organization.userGroup': '用户组',
'menu.settings.organization.project': '项目', 'menu.settings.organization.project': '项目',
'menu.settings.organization.serviceIntegration': '服务集成', 'menu.settings.organization.serviceIntegration': '服务集成',
'menu.settings.organization.template': '模板', 'menu.settings.organization.template': '模板管理',
'menu.settings.organization.bugTemplate': '缺陷模板', 'menu.settings.organization.bugTemplate': '缺陷模板',
'menu.settings.organization.templateFieldSetting': '字段设置', 'menu.settings.organization.templateFieldSetting': '字段设置',
'menu.settings.organization.templateManagementList': '模板列表', 'menu.settings.organization.templateManagementList': '模板列表',

View File

@ -5,6 +5,7 @@
v-model:keyword="keyword" v-model:keyword="keyword"
:filter-config-list="filterConfigList" :filter-config-list="filterConfigList"
:custom-fields-config-list="searchCustomFields" :custom-fields-config-list="searchCustomFields"
:search-placeholder="t('caseManagement.featureCase.searchPlaceholder')"
:row-count="filterRowCount" :row-count="filterRowCount"
@keyword-search="fetchData" @keyword-search="fetchData"
@adv-search="handleAdvSearch" @adv-search="handleAdvSearch"
@ -348,6 +349,10 @@
}; };
}); });
const hasOperationPermission = computed(() =>
hasAnyPermission(['FUNCTIONAL_CASE:READ+UPDATE', 'FUNCTIONAL_CASE:READ+DELETE'])
);
const columns: MsTableColumn = [ const columns: MsTableColumn = [
{ {
'title': 'caseManagement.featureCase.tableColumnID', 'title': 'caseManagement.featureCase.tableColumnID',
@ -471,13 +476,13 @@
showDrag: true, showDrag: true,
}, },
{ {
title: 'caseManagement.featureCase.tableColumnActions', title: hasOperationPermission.value ? 'caseManagement.featureCase.tableColumnActions' : '',
slotName: 'operation', slotName: 'operation',
dataIndex: 'operation', dataIndex: 'operation',
fixed: 'right', fixed: 'right',
width: 260,
showInTable: true, showInTable: true,
showDrag: false, showDrag: false,
width: hasOperationPermission.value ? 260 : 50,
}, },
]; ];

View File

@ -48,7 +48,10 @@
visible: boolean; visible: boolean;
}>(); }>();
const emit = defineEmits(['update:visible']); const emit = defineEmits<{
(e: 'update:visible', visible: boolean): void;
(e: 'success'): void;
}>();
const { t } = useI18n(); const { t } = useI18n();
@ -93,6 +96,7 @@
request: { ...form.value, customFields: templateCustomFields.value }, request: { ...form.value, customFields: templateCustomFields.value },
fileList: [], fileList: [],
}); });
emit('success');
Message.success(t('caseManagement.featureCase.quicklyCreateDefectSuccess')); Message.success(t('caseManagement.featureCase.quicklyCreateDefectSuccess'));
if (!isContinue) { if (!isContinue) {
handleDrawerCancel(); handleDrawerCancel();

View File

@ -17,14 +17,14 @@
</div> </div>
<div v-else class="font-medium">{{ t('caseManagement.featureCase.testPlanLinkList') }}</div> <div v-else class="font-medium">{{ t('caseManagement.featureCase.testPlanLinkList') }}</div>
<div class="mb-4"> <div class="mb-4">
<a-radio-group v-model:model-value="showType" type="button" class="file-show-type ml-[4px]"> <!-- <a-radio-group v-model:model-value="showType" type="button" class="file-show-type ml-[4px]">
<a-radio value="link" class="show-type-icon p-[2px]">{{ <a-radio value="link" class="show-type-icon p-[2px]">{{
t('caseManagement.featureCase.directLink') t('caseManagement.featureCase.directLink')
}}</a-radio> }}</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') t('caseManagement.featureCase.testPlan')
}}</a-radio> --> }}</a-radio>
</a-radio-group> </a-radio-group> -->
<a-input-search <a-input-search
v-model:model-value="keyword" v-model:model-value="keyword"
:placeholder="t('caseManagement.featureCase.searchByNameAndId')" :placeholder="t('caseManagement.featureCase.searchByNameAndId')"
@ -85,7 +85,7 @@
</div> </div>
</template> </template>
</ms-base-table> </ms-base-table>
<AddDefectDrawer v-model:visible="showDrawer" /> <AddDefectDrawer v-model:visible="showDrawer" @success="getFetch()" />
<LinkDefectDrawer <LinkDefectDrawer
v-model:visible="showLinkDrawer" v-model:visible="showLinkDrawer"
:case-id="props.caseId" :case-id="props.caseId"
@ -106,7 +106,6 @@
import MsBaseTable from '@/components/pure/ms-table/base-table.vue'; import MsBaseTable from '@/components/pure/ms-table/base-table.vue';
import type { MsTableColumn } from '@/components/pure/ms-table/type'; import type { MsTableColumn } from '@/components/pure/ms-table/type';
import useTable from '@/components/pure/ms-table/useTable'; import useTable from '@/components/pure/ms-table/useTable';
import MsRemoveButton from '@/components/business/ms-remove-button/MsRemoveButton.vue';
import AddDefectDrawer from './addDefectDrawer.vue'; import AddDefectDrawer from './addDefectDrawer.vue';
import LinkDefectDrawer from './linkDefectDrawer.vue'; import LinkDefectDrawer from './linkDefectDrawer.vue';
@ -117,10 +116,13 @@
} from '@/api/modules/case-management/featureCase'; } from '@/api/modules/case-management/featureCase';
import { useI18n } from '@/hooks/useI18n'; import { useI18n } from '@/hooks/useI18n';
import { useAppStore } from '@/store'; import { useAppStore } from '@/store';
import useFeatureCaseStore from '@/store/modules/case/featureCase';
import { characterLimit } from '@/utils'; import { characterLimit } from '@/utils';
import type { TableQueryParams } from '@/models/common'; import type { TableQueryParams } from '@/models/common';
const featureCaseStore = useFeatureCaseStore();
const appStore = useAppStore(); const appStore = useAppStore();
const { t } = useI18n(); const { t } = useI18n();
@ -256,13 +258,17 @@
enableDrag: true, enableDrag: true,
}); });
function getFetch() { async function getFetch() {
if (showType.value === 'link') { if (showType.value === 'link') {
setLinkListParams({ keyword: keyword.value, projectId: appStore.currentProjectId, caseId: props.caseId }); setLinkListParams({ keyword: keyword.value, projectId: appStore.currentProjectId, caseId: props.caseId });
loadLinkList(); await loadLinkList();
const { msPagination } = linkPropsRes.value;
featureCaseStore.setListCount(featureCaseStore.activeTab, msPagination?.total || 0);
} else { } else {
setTestPlanListParams({ keyword: keyword.value, projectId: appStore.currentProjectId, caseId: props.caseId }); setTestPlanListParams({ keyword: keyword.value, projectId: appStore.currentProjectId, caseId: props.caseId });
testPlanLinkList(); await testPlanLinkList();
const { msPagination } = testPlanPropsRes.value;
featureCaseStore.setListCount(featureCaseStore.activeTab, msPagination?.total || 0);
} }
} }
const cancelLoading = ref<boolean>(false); const cancelLoading = ref<boolean>(false);
@ -272,6 +278,7 @@
try { try {
if (showType.value === 'link') { if (showType.value === 'link') {
await cancelAssociatedDebug(id); await cancelAssociatedDebug(id);
getFetch();
Message.success(t('caseManagement.featureCase.cancelLinkSuccess')); Message.success(t('caseManagement.featureCase.cancelLinkSuccess'));
} }
} catch (error) { } catch (error) {

View File

@ -5,7 +5,7 @@
<a-radio-group v-model="activeComment" type="button"> <a-radio-group v-model="activeComment" type="button">
<a-radio value="caseComment">{{ t('caseManagement.featureCase.caseComment') }}</a-radio> <a-radio value="caseComment">{{ t('caseManagement.featureCase.caseComment') }}</a-radio>
<a-radio value="reviewComment">{{ t('caseManagement.featureCase.reviewComment') }}</a-radio> <a-radio value="reviewComment">{{ t('caseManagement.featureCase.reviewComment') }}</a-radio>
<a-radio value="executiveComment">{{ t('caseManagement.featureCase.executiveReview') }}</a-radio> <!-- <a-radio value="executiveComment">{{ t('caseManagement.featureCase.executiveReview') }}</a-radio> -->
</a-radio-group> </a-radio-group>
</div> </div>
</div> </div>
@ -25,7 +25,7 @@
@update-or-add="handleUpdateOrAdd" @update-or-add="handleUpdateOrAdd"
/> />
<!-- 执行评论 --> <!-- 执行评论 -->
<MsComment v-else :comment-list="commentList" @delete="handleDelete" @update-or-add="handleUpdateOrAdd" /> <!-- <MsComment v-else :comment-list="commentList" @delete="handleDelete" @update-or-add="handleUpdateOrAdd" /> -->
</div> </div>
</template> </template>
@ -89,15 +89,13 @@
setCount(commentList.value); setCount(commentList.value);
break; break;
case 'reviewComment': case 'reviewComment':
initReviewCommentList(); await initReviewCommentList();
await initCommentList();
setCount(reviewCommentList.value); setCount(reviewCommentList.value);
break; break;
case 'executiveComment': case 'executiveComment':
await initCommentList(); await initCommentList();
setCount(commentList.value); setCount(commentList.value);
break; break;
default: default:
break; break;
} }
@ -146,8 +144,10 @@
watch( watch(
() => activeComment.value, () => activeComment.value,
() => { (val) => {
getAllCommentList(); if (val) {
getAllCommentList();
}
} }
); );

View File

@ -252,4 +252,5 @@ export default {
'caseManagement.featureCase.defectSource': 'defect Source', 'caseManagement.featureCase.defectSource': 'defect Source',
'caseManagement.featureCase.sortSuccess': 'Sort successfully', 'caseManagement.featureCase.sortSuccess': 'Sort successfully',
'caseManagement.featureCase.zentao': 'zentao', 'caseManagement.featureCase.zentao': 'zentao',
'caseManagement.featureCase.searchPlaceholder': 'Search by id or name',
}; };

View File

@ -247,4 +247,5 @@ export default {
'caseManagement.featureCase.defectSource': '缺陷来源', 'caseManagement.featureCase.defectSource': '缺陷来源',
'caseManagement.featureCase.sortSuccess': '排序成功', 'caseManagement.featureCase.sortSuccess': '排序成功',
'caseManagement.featureCase.zentao': '禅道', 'caseManagement.featureCase.zentao': '禅道',
'caseManagement.featureCase.searchPlaceholder': '通过id或名称搜索',
}; };

View File

@ -82,7 +82,13 @@
{{ caseDetail.num }}{{ caseDetail.name }} {{ caseDetail.num }}{{ caseDetail.name }}
</div> </div>
</a-tooltip> </a-tooltip>
<a-button type="outline" size="mini" class="arco-btn-outline--secondary" @click="editCaseVisible = true"> <a-button
v-permission="['FUNCTIONAL_CASE:READ+UPDATE']"
type="outline"
size="mini"
class="arco-btn-outline--secondary"
@click="editCaseVisible = true"
>
{{ t('common.edit') }} {{ t('common.edit') }}
</a-button> </a-button>
</div> </div>

View File

@ -68,7 +68,7 @@
</div> </div>
</template> </template>
<template #action="{ record }"> <template #action="{ record }">
<MsButton type="text" class="!mr-0" @click="review(record)"> <MsButton v-permission="['CASE_REVIEW:READ+REVIEW']" type="text" class="!mr-0" @click="review(record)">
{{ t('caseManagement.caseReview.review') }} {{ t('caseManagement.caseReview.review') }}
</MsButton> </MsButton>
<a-divider direction="vertical" :margin="8"></a-divider> <a-divider direction="vertical" :margin="8"></a-divider>
@ -80,7 +80,7 @@
type="error" type="error"
@confirm="(val, done) => handleDisassociateReviewCase(record, done)" @confirm="(val, done) => handleDisassociateReviewCase(record, done)"
> >
<MsButton type="text" class="!mr-0"> <MsButton v-permission="['CASE_REVIEW:READ+RELEVANCE']" type="text" class="!mr-0">
{{ t('caseManagement.caseReview.disassociate') }} {{ t('caseManagement.caseReview.disassociate') }}
</MsButton> </MsButton>
</MsPopconfirm> </MsPopconfirm>
@ -88,7 +88,7 @@
<template v-if="keyword.trim() === ''" #empty> <template v-if="keyword.trim() === ''" #empty>
<div class="flex w-full items-center justify-center p-[8px] text-[var(--color-text-4)]"> <div class="flex w-full items-center justify-center p-[8px] text-[var(--color-text-4)]">
{{ t('caseManagement.caseReview.tableNoData') }} {{ t('caseManagement.caseReview.tableNoData') }}
<MsButton class="ml-[8px]" @click="createCase"> <MsButton v-permission="['FUNCTIONAL_CASE:READ+ADD']" class="ml-[8px]" @click="createCase">
{{ t('caseManagement.caseReview.crateCase') }} {{ t('caseManagement.caseReview.crateCase') }}
</MsButton> </MsButton>
</div> </div>
@ -271,6 +271,7 @@
import useTableStore from '@/hooks/useTableStore'; import useTableStore from '@/hooks/useTableStore';
import useAppStore from '@/store/modules/app'; import useAppStore from '@/store/modules/app';
import useUserStore from '@/store/modules/user'; import useUserStore from '@/store/modules/user';
import { hasAnyPermission } from '@/utils/permission';
import { ReviewCaseItem, ReviewItem, ReviewPassRule, ReviewResult } from '@/models/caseManagement/caseReview'; import { ReviewCaseItem, ReviewItem, ReviewPassRule, ReviewResult } from '@/models/caseManagement/caseReview';
import { BatchApiParams, ModuleTreeNode } from '@/models/common'; import { BatchApiParams, ModuleTreeNode } from '@/models/common';
@ -293,12 +294,15 @@
const userStore = useUserStore(); const userStore = useUserStore();
const { t } = useI18n(); const { t } = useI18n();
const { openModal } = useModal(); const { openModal } = useModal();
const keyword = ref(''); const keyword = ref('');
const showType = ref<'list' | 'mind'>('list'); const showType = ref<'list' | 'mind'>('list');
const filterRowCount = ref(0); const filterRowCount = ref(0);
const filterConfigList = ref<FilterFormItem[]>([]); const filterConfigList = ref<FilterFormItem[]>([]);
const tableParams = ref<Record<string, any>>({}); const tableParams = ref<Record<string, any>>({});
const hasOperationPermission = computed(() =>
hasAnyPermission(['CASE_REVIEW:READ+REVIEW', 'CASE_REVIEW:READ+RELEVANCE'])
);
const columns: MsTableColumn = [ const columns: MsTableColumn = [
{ {
title: 'ID', title: 'ID',
@ -348,11 +352,11 @@
width: 150, width: 150,
}, },
{ {
title: 'common.operation', title: hasOperationPermission.value ? 'common.operation' : '',
slotName: 'action', slotName: 'action',
dataIndex: 'operation', dataIndex: 'operation',
fixed: 'right', fixed: 'right',
width: 140, width: hasOperationPermission.value ? 140 : 50,
}, },
]; ];
const tableStore = useTableStore(); const tableStore = useTableStore();

View File

@ -105,7 +105,12 @@
</a-tooltip> </a-tooltip>
</template> </template>
<template #action="{ record }"> <template #action="{ record }">
<MsButton type="text" class="!mr-0" @click="() => editReview(record)"> <MsButton
v-permission="['CASE_REVIEW:READ+UPDATE']"
type="text"
class="!mr-0"
@click="() => editReview(record)"
>
{{ t('common.edit') }} {{ t('common.edit') }}
</MsButton> </MsButton>
<!-- <a-divider direction="vertical" :margin="8"></a-divider> <!-- <a-divider direction="vertical" :margin="8"></a-divider>
@ -113,12 +118,16 @@
{{ t('common.export') }} {{ t('common.export') }}
</MsButton> --> </MsButton> -->
<a-divider direction="vertical" :margin="8"></a-divider> <a-divider direction="vertical" :margin="8"></a-divider>
<MsTableMoreAction :list="getMoreAction(record.status)" @select="handleMoreActionSelect($event, record)" /> <MsTableMoreAction
v-permission="['CASE_REVIEW:READ+DELETE']"
:list="getMoreAction(record.status)"
@select="handleMoreActionSelect($event, record)"
/>
</template> </template>
<template v-if="keyword.trim() === ''" #empty> <template v-if="keyword.trim() === ''" #empty>
<div class="flex w-full items-center justify-center p-[8px] text-[var(--color-text-4)]"> <div class="flex w-full items-center justify-center p-[8px] text-[var(--color-text-4)]">
{{ t('caseManagement.caseReview.tableNoData') }} {{ t('caseManagement.caseReview.tableNoData') }}
<MsButton class="ml-[8px]" @click="() => emit('goCreate')"> <MsButton v-permission="['CASE_REVIEW:READ+ADD']" class="ml-[8px]" @click="() => emit('goCreate')">
{{ t('caseManagement.caseReview.create') }} {{ t('caseManagement.caseReview.create') }}
</MsButton> </MsButton>
</div> </div>
@ -183,6 +192,7 @@
import useTableStore from '@/hooks/useTableStore'; import useTableStore from '@/hooks/useTableStore';
import useAppStore from '@/store/modules/app'; import useAppStore from '@/store/modules/app';
import useUserStore from '@/store/modules/user'; import useUserStore from '@/store/modules/user';
import { hasAnyPermission } from '@/utils/permission';
import { import {
ReviewDetailReviewersItem, ReviewDetailReviewersItem,
@ -212,7 +222,6 @@
(e: 'goCreate'): void; (e: 'goCreate'): void;
(e: 'init', params: ReviewListQueryParams): void; (e: 'init', params: ReviewListQueryParams): void;
}>(); }>();
const userStore = useUserStore(); const userStore = useUserStore();
const appStore = useAppStore(); const appStore = useAppStore();
const router = useRouter(); const router = useRouter();
@ -354,6 +363,10 @@
console.log(error); console.log(error);
} }
}); });
const hasOperationPermission = computed(() =>
hasAnyPermission(['CASE_REVIEW:READ+UPDATE', 'CASE_REVIEW:READ+DELETE'])
);
const columns: MsTableColumn = [ const columns: MsTableColumn = [
{ {
title: 'ID', title: 'ID',
@ -437,11 +450,11 @@
width: 350, width: 350,
}, },
{ {
title: 'common.operation', title: hasOperationPermission.value ? 'common.operation' : '',
slotName: 'action', slotName: 'action',
dataIndex: 'operation', dataIndex: 'operation',
fixed: 'right', fixed: 'right',
width: 110, width: hasOperationPermission.value ? 110 : 50,
}, },
]; ];
const tableStore = useTableStore(); const tableStore = useTableStore();
@ -565,6 +578,7 @@
label: 'common.delete', label: 'common.delete',
eventTag: 'delete', eventTag: 'delete',
danger: true, danger: true,
permission: ['CASE_REVIEW:READ+DELETE'],
}, },
]; ];
} }
@ -573,6 +587,7 @@
label: 'common.delete', label: 'common.delete',
eventTag: 'delete', eventTag: 'delete',
danger: true, danger: true,
permission: ['CASE_REVIEW:READ+DELETE'],
}, },
]; ];
} }

View File

@ -1,7 +1,11 @@
<template> <template>
<a-form ref="dialogFormRef" :model="caseResultForm" layout="vertical"> <a-form ref="dialogFormRef" :model="caseResultForm" layout="vertical">
<a-form-item field="reason" class="mb-[4px]"> <a-form-item field="reason" class="mb-[4px]">
<a-radio-group v-model:model-value="caseResultForm.result" @change="() => dialogFormRef?.resetFields()"> <a-radio-group
v-model:model-value="caseResultForm.result"
:disabled="!hasAnyPermission(['CASE_REVIEW:READ+REVIEW'])"
@change="() => dialogFormRef?.resetFields()"
>
<a-radio value="PASS"> <a-radio value="PASS">
<div class="inline-flex items-center"> <div class="inline-flex items-center">
<MsIcon type="icon-icon_succeed_filled" class="mr-[4px] text-[rgb(var(--success-6))]" /> <MsIcon type="icon-icon_succeed_filled" class="mr-[4px] text-[rgb(var(--success-6))]" />
@ -29,13 +33,20 @@
</a-radio-group> </a-radio-group>
</a-form-item> </a-form-item>
<div class="flex w-full items-center"> <div class="flex w-full items-center">
<a-button type="secondary" class="p-[8px_6px]" size="small" @click="modalVisible = true"> <a-button
v-permission="['CASE_REVIEW:READ+REVIEW']"
type="secondary"
class="p-[8px_6px]"
size="small"
@click="modalVisible = true"
>
<icon-plus class="mr-[4px]" /> <icon-plus class="mr-[4px]" />
{{ t('caseManagement.caseReview.reason') }} {{ t('caseManagement.caseReview.reason') }}
</a-button> </a-button>
</div> </div>
</a-form> </a-form>
<a-button <a-button
v-permission="['CASE_REVIEW:READ+REVIEW']"
type="primary" type="primary"
class="mt-[12px]" class="mt-[12px]"
:disabled="submitDisabled" :disabled="submitDisabled"
@ -77,6 +88,7 @@
import { editorUploadFile } from '@/api/modules/case-management/featureCase'; import { editorUploadFile } from '@/api/modules/case-management/featureCase';
import { useI18n } from '@/hooks/useI18n'; import { useI18n } from '@/hooks/useI18n';
import useAppStore from '@/store/modules/app'; import useAppStore from '@/store/modules/app';
import { hasAnyPermission } from '@/utils/permission';
import { ReviewPassRule, ReviewResult } from '@/models/caseManagement/caseReview'; import { ReviewPassRule, ReviewResult } from '@/models/caseManagement/caseReview';

View File

@ -32,15 +32,20 @@
<a-switch v-model:model-value="onlyMine" size="small" class="mr-[8px]" type="line" /> <a-switch v-model:model-value="onlyMine" size="small" class="mr-[8px]" type="line" />
{{ t('caseManagement.caseReview.onlyMine') }} {{ t('caseManagement.caseReview.onlyMine') }}
</div> </div>
<MsButton type="button" status="default" @click="associateDrawerVisible = true"> <MsButton
v-permission="['CASE_REVIEW:READ+UPDATE']"
type="button"
status="default"
@click="associateDrawerVisible = true"
>
<MsIcon type="icon-icon_link-record_outlined1" class="mr-[8px]" /> <MsIcon type="icon-icon_link-record_outlined1" class="mr-[8px]" />
{{ t('ms.case.associate.title') }} {{ t('ms.case.associate.title') }}
</MsButton> </MsButton>
<MsButton type="button" status="default" @click="editReview"> <MsButton v-permission="['CASE_REVIEW:READ+UPDATE']" type="button" status="default" @click="editReview">
<MsIcon type="icon-icon_edit_outlined" class="mr-[8px]" /> <MsIcon type="icon-icon_edit_outlined" class="mr-[8px]" />
{{ t('common.edit') }} {{ t('common.edit') }}
</MsButton> </MsButton>
<MsButton type="button" status="default" @click="copyReview"> <MsButton v-permission="['CASE_REVIEW:READ+ADD']" type="button" status="default" @click="copyReview">
<MsIcon type="icon-icon_copy_outlined" class="mr-[8px]" /> <MsIcon type="icon-icon_copy_outlined" class="mr-[8px]" />
{{ t('common.copy') }} {{ t('common.copy') }}
</MsButton> </MsButton>
@ -296,6 +301,7 @@
label: t('caseManagement.caseReview.quickCreate'), label: t('caseManagement.caseReview.quickCreate'),
eventTag: 'createCase', eventTag: 'createCase',
icon: 'icon-icon_add_outlined-1', icon: 'icon-icon_add_outlined-1',
permission: ['FUNCTIONAL_CASE:READ+ADD'],
}, },
// { // {
// label: t('caseManagement.caseReview.createTestPlan'), // label: t('caseManagement.caseReview.createTestPlan'),
@ -310,6 +316,7 @@
eventTag: 'delete', eventTag: 'delete',
icon: 'icon-icon_delete-trash_outlined1', icon: 'icon-icon_delete-trash_outlined1',
danger: true, danger: true,
permission: ['CASE_REVIEW:READ+DELETE'],
}, },
]; ];
const moreAction = computed(() => { const moreAction = computed(() => {

View File

@ -1,7 +1,9 @@
<template> <template>
<MsCard simple no-content-padding> <MsCard simple no-content-padding>
<div class="flex items-center justify-between border-b border-[var(--color-text-n8)] p-[24px_24px_16px_24px]"> <div class="flex items-center justify-between border-b border-[var(--color-text-n8)] p-[24px_24px_16px_24px]">
<a-button type="primary" @click="goCreateReview">{{ t('caseManagement.caseReview.create') }}</a-button> <a-button v-permission="['CASE_REVIEW:READ+ADD']" type="primary" @click="goCreateReview">{{
t('caseManagement.caseReview.create')
}}</a-button>
<a-radio-group v-model:model-value="showType" type="button" class="file-show-type"> <a-radio-group v-model:model-value="showType" type="button" class="file-show-type">
<a-radio value="all">{{ t('common.all') }}</a-radio> <a-radio value="all">{{ t('common.all') }}</a-radio>
<a-radio value="reviewByMe">{{ t('caseManagement.caseReview.waitMyReview') }}</a-radio> <a-radio value="reviewByMe">{{ t('caseManagement.caseReview.waitMyReview') }}</a-radio>

View File

@ -99,6 +99,7 @@
import useModal from '@/hooks/useModal'; import useModal from '@/hooks/useModal';
import { useAppStore, useTableStore } from '@/store'; import { useAppStore, useTableStore } from '@/store';
import { characterLimit } from '@/utils'; import { characterLimit } from '@/utils';
import { hasAnyPermission } from '@/utils/permission';
import type { import type {
AddOrUpdateCommonScript, AddOrUpdateCommonScript,
@ -118,6 +119,10 @@
const keyword = ref<string>(''); const keyword = ref<string>('');
const hasOperationPermission = computed(() =>
hasAnyPermission(['PROJECT_CUSTOM_FUNCTION:READ+UPDATE', 'PROJECT_CUSTOM_FUNCTION:READ+DELETE'])
);
const columns: MsTableColumn = [ const columns: MsTableColumn = [
{ {
title: 'project.commonScript.name', title: 'project.commonScript.name',
@ -177,11 +182,11 @@
showDrag: true, showDrag: true,
}, },
{ {
title: 'project.commonScript.tableColumnActions', title: hasOperationPermission.value ? 'project.commonScript.tableColumnActions' : '',
slotName: 'operation', slotName: 'operation',
dataIndex: 'operation', dataIndex: 'operation',
fixed: 'right', fixed: 'right',
width: 140, width: hasOperationPermission.value ? 140 : 50,
showInTable: true, showInTable: true,
showDrag: false, showDrag: false,
}, },

View File

@ -114,7 +114,9 @@
:all-names="[]" :all-names="[]"
@rename-finish="detailDrawerRef?.initDetail" @rename-finish="detailDrawerRef?.initDetail"
> >
<MsButton class="!mr-0 ml-[8px]">{{ t('common.rename') }}</MsButton> <MsButton v-permission="['PROJECT_FILE_MANAGEMENT:READ+UPDATE']" class="!mr-0 ml-[8px]">{{
t('common.rename')
}}</MsButton>
</popConfirm> </popConfirm>
<template v-if="UploadAcceptEnum.image.includes(fileType)"> <template v-if="UploadAcceptEnum.image.includes(fileType)">
<a-divider <a-divider
@ -248,6 +250,7 @@
import { useAppStore } from '@/store'; import { useAppStore } from '@/store';
import useUserStore from '@/store/modules/user'; import useUserStore from '@/store/modules/user';
import { downloadByteFile, formatFileSize } from '@/utils'; import { downloadByteFile, formatFileSize } from '@/utils';
import { hasAnyPermission } from '@/utils/permission';
import { AssociationItem, FileDetail } from '@/models/projectManagement/file'; import { AssociationItem, FileDetail } from '@/models/projectManagement/file';
import { CaseManagementRouteEnum } from '@/enums/routeEnum'; import { CaseManagementRouteEnum } from '@/enums/routeEnum';
@ -395,6 +398,8 @@
} }
} }
const hasOperationPermission = computed(() => hasAnyPermission(['PROJECT_FILE_MANAGEMENT:READ+UPDATE']));
const activeTab = ref('case'); const activeTab = ref('case');
const caseColumns: MsTableColumn = [ const caseColumns: MsTableColumn = [
@ -425,10 +430,10 @@
showTooltip: true, showTooltip: true,
}, },
{ {
title: 'common.operation', title: hasOperationPermission.value ? 'common.operation' : '',
slotName: 'action', slotName: 'action',
fixed: 'right', fixed: 'right',
width: 130, width: hasOperationPermission.value ? 130 : 50,
}, },
]; ];
const { const {
@ -450,6 +455,7 @@
{ {
label: 'project.fileManagement.updateCaseFile', label: 'project.fileManagement.updateCaseFile',
eventTag: 'updateCaseFile', eventTag: 'updateCaseFile',
permission: ['PROJECT_FILE_MANAGEMENT:READ+UPDATE'],
}, },
], ],
}; };

View File

@ -529,6 +529,13 @@
} }
return jarFileActions; return jarFileActions;
} }
const hasOperationPermission = computed(() =>
hasAnyPermission([
'PROJECT_FILE_MANAGEMENT:READ+UPDATE',
'PROJECT_FILE_MANAGEMENT:READ+DELETE',
'PROJECT_FILE_MANAGEMENT:READ+DOWNLOAD',
])
);
const columns: MsTableColumn = [ const columns: MsTableColumn = [
{ {
@ -582,11 +589,11 @@
width: 180, width: 180,
}, },
{ {
title: 'common.operation', title: hasOperationPermission.value ? 'common.operation' : '',
slotName: 'action', slotName: 'action',
dataIndex: 'operation', dataIndex: 'operation',
fixed: 'right', fixed: 'right',
width: 120, width: hasOperationPermission.value ? 120 : 50,
}, },
]; ];
const tableStore = useTableStore(); const tableStore = useTableStore();

View File

@ -129,7 +129,7 @@
const appStore = useAppStore(); const appStore = useAppStore();
const tableStore = useTableStore(); const tableStore = useTableStore();
const lastProjectId = computed(() => appStore.currentProjectId); const lastProjectId = computed(() => appStore.currentProjectId);
const hasOperationPermission = computed(() => hasAnyPermission(['PROJECT_USER:READ+DELETE']));
const columns: MsTableColumn = [ const columns: MsTableColumn = [
{ {
title: 'project.member.tableColumnName', title: 'project.member.tableColumnName',
@ -166,11 +166,11 @@
width: 150, width: 150,
}, },
{ {
title: 'project.member.tableColumnActions', title: hasOperationPermission.value ? 'project.member.tableColumnActions' : '',
slotName: 'operation', slotName: 'operation',
fixed: 'right', fixed: 'right',
dataIndex: 'operation', dataIndex: 'operation',
width: 100, width: hasOperationPermission.value ? 100 : 50,
showDrag: false, showDrag: false,
}, },
]; ];

View File

@ -315,6 +315,10 @@
const keyword = ref(''); const keyword = ref('');
const hasOperationPermission = computed(() =>
hasAnyPermission(['PROJECT_VERSION:READ+UPDATE', 'PROJECT_VERSION:READ+DELETE'])
);
const columns: MsTableColumn = [ const columns: MsTableColumn = [
{ {
title: 'project.projectVersion.versionName', title: 'project.projectVersion.versionName',
@ -360,11 +364,11 @@
showTooltip: true, showTooltip: true,
}, },
{ {
title: 'common.operation', title: hasOperationPermission.value ? 'common.operation' : '',
fixed: 'right', fixed: 'right',
slotName: 'action', slotName: 'action',
dataIndex: 'operation', dataIndex: 'operation',
width: 80, width: hasOperationPermission.value ? 80 : 50,
}, },
]; ];
const { propsRes, propsEvent, loadList, setKeyword, setLoadListParams } = useTable( const { propsRes, propsEvent, loadList, setKeyword, setLoadListParams } = useTable(

View File

@ -146,6 +146,7 @@
import { import {
getCardList, getCardList,
getCustomDetailFields, getCustomDetailFields,
getTemplateName,
getTotalFieldOptionList, getTotalFieldOptionList,
} from '@/views/setting/organization/template/components/fieldSetting'; } from '@/views/setting/organization/template/components/fieldSetting';
@ -238,13 +239,19 @@
watchEffect(async () => { watchEffect(async () => {
if (isEdit.value && route.params.mode === 'copy') { if (isEdit.value && route.params.mode === 'copy') {
title.value = t('system.orgTemplate.copyTemplate'); title.value = t('system.orgTemplate.copyTemplate', {
type: getTemplateName('organization', route.query.type as string),
});
getClassifyField(); getClassifyField();
} else if (isEdit.value) { } else if (isEdit.value) {
title.value = t('menu.settings.organization.templateManagementEdit'); title.value = t('system.orgTemplate.editTemplateType', {
type: getTemplateName('organization', route.query.type as string),
});
getClassifyField(); getClassifyField();
} else { } else {
title.value = t('menu.settings.organization.templateManagementDetail'); title.value = t('system.orgTemplate.createTemplateType', {
type: getTemplateName('organization', route.query.type as string),
});
} }
}); });

View File

@ -12,31 +12,9 @@
/** /**
* @description 项目管理-模板-字段设置-首页 * @description 项目管理-模板-字段设置-首页
*/ */
import { useRoute } from 'vue-router';
import MsCard from '@/components/pure/ms-card/index.vue'; import MsCard from '@/components/pure/ms-card/index.vue';
import FieldSetting from '@/views/setting/organization/template/components/fieldSetting.vue'; import FieldSetting from '@/views/setting/organization/template/components/fieldSetting.vue';
import { useAppStore } from '@/store';
import { getCardList } from '@/views/setting/organization/template/components/fieldSetting';
const route = useRoute();
const appStore = useAppStore();
//
const updateBreadcrumbList = () => {
const { breadcrumbList } = appStore;
const breadTitle = getCardList('project').find((item: any) => item.key === route.params.type);
if (breadTitle) {
breadcrumbList[0].locale = breadTitle.name;
appStore.setBreadcrumbList(breadcrumbList);
}
};
onMounted(() => {
updateBreadcrumbList();
});
</script> </script>
<style scoped></style> <style scoped></style>

View File

@ -113,13 +113,13 @@
import { useAppStore, useTableStore } from '@/store'; import { useAppStore, useTableStore } from '@/store';
import useTemplateStore from '@/store/modules/setting/template'; import useTemplateStore from '@/store/modules/setting/template';
import { characterLimit } from '@/utils'; import { characterLimit } from '@/utils';
import { hasAnyPermission } from '@/utils/permission';
import type { DefinedFieldItem, OrdTemplateManagement } from '@/models/setting/template'; import type { DefinedFieldItem, OrdTemplateManagement } from '@/models/setting/template';
import { ProjectManagementRouteEnum } from '@/enums/routeEnum'; import { ProjectManagementRouteEnum } from '@/enums/routeEnum';
import { TableKeyEnum } from '@/enums/tableEnum'; import { TableKeyEnum } from '@/enums/tableEnum';
import { import {
getCardList,
getCustomDetailFields, getCustomDetailFields,
getTotalFieldOptionList, getTotalFieldOptionList,
} from '@/views/setting/organization/template/components/fieldSetting'; } from '@/views/setting/organization/template/components/fieldSetting';
@ -136,6 +136,10 @@
const sceneType = computed(() => route.query.type); const sceneType = computed(() => route.query.type);
const hasOperationPermission = computed(() =>
hasAnyPermission(['PROJECT_TEMPLATE:READ+UPDATE', 'PROJECT_TEMPLATE:READ+DELETE'])
);
const fieldColumns: MsTableColumn = [ const fieldColumns: MsTableColumn = [
{ {
title: 'system.orgTemplate.columnTemplateName', title: 'system.orgTemplate.columnTemplateName',
@ -168,11 +172,11 @@
showInTable: true, showInTable: true,
}, },
{ {
title: 'system.orgTemplate.operation', title: hasOperationPermission.value ? 'system.orgTemplate.operation' : '',
slotName: 'operation', slotName: 'operation',
dataIndex: 'operation', dataIndex: 'operation',
fixed: 'right', fixed: 'right',
width: 200, width: hasOperationPermission.value ? 200 : 50,
showInTable: true, showInTable: true,
showDrag: false, showDrag: false,
}, },
@ -350,16 +354,6 @@
defectForm.value = { ...initDetailForm }; defectForm.value = { ...initDetailForm };
}; };
//
const updateBreadcrumbList = () => {
const { breadcrumbList } = appStore;
const breadTitle = getCardList('project').find((item: any) => item.key === route.query.type);
if (breadTitle) {
breadcrumbList[0].locale = breadTitle.name;
appStore.setBreadcrumbList(breadcrumbList);
}
};
const tableRef = ref(); const tableRef = ref();
function updateColumns() { function updateColumns() {
@ -374,7 +368,6 @@
} }
onMounted(() => { onMounted(() => {
updateBreadcrumbList();
fetchData(); fetchData();
updateColumns(); updateColumns();
}); });

View File

@ -154,6 +154,10 @@
const appStore = useAppStore(); const appStore = useAppStore();
const { t } = useI18n(); const { t } = useI18n();
const lastOrganizationId = computed(() => appStore.currentOrgId); const lastOrganizationId = computed(() => appStore.currentOrgId);
const hasOrdMemberOperationPermission = computed(() =>
hasAnyPermission(['ORGANIZATION_MEMBER:READ+UPDATE', 'ORGANIZATION_MEMBER:READ+DELETE'])
);
const columns: MsTableColumn = [ const columns: MsTableColumn = [
{ {
title: 'organization.member.tableColunmEmail', title: 'organization.member.tableColunmEmail',
@ -205,11 +209,11 @@
showDrag: true, showDrag: true,
}, },
{ {
title: 'organization.member.tableColunmActions', title: hasOrdMemberOperationPermission.value ? 'organization.member.tableColunmActions' : '',
slotName: 'action', slotName: 'action',
dataIndex: 'operation', dataIndex: 'operation',
fixed: 'right', fixed: 'right',
width: 140, width: hasOrdMemberOperationPermission.value ? 140 : 50,
showInTable: true, showInTable: true,
showDrag: false, showDrag: false,
}, },

View File

@ -39,7 +39,7 @@
size="mini" size="mini"
class="ml-3 px-0 text-sm" class="ml-3 px-0 text-sm"
type="text" type="text"
:disabled="!links.disabled" :disabled="links.disabled"
@click.stop="jumpHandler(links)" @click.stop="jumpHandler(links)"
> >
{{ t(links.name) }} {{ t(links.name) }}
@ -73,7 +73,6 @@
import { useI18n } from '@/hooks/useI18n'; import { useI18n } from '@/hooks/useI18n';
import useUserStore from '@/store/modules/user/index'; import useUserStore from '@/store/modules/user/index';
import { openWindow } from '@/utils/index'; import { openWindow } from '@/utils/index';
import { hasAnyPermission } from '@/utils/permission';
import type { SkipTitle, StepListType } from '@/models/setting/serviceIntegration'; import type { SkipTitle, StepListType } from '@/models/setting/serviceIntegration';
import { SettingRouteEnum } from '@/enums/routeEnum'; import { SettingRouteEnum } from '@/enums/routeEnum';
@ -81,8 +80,7 @@
const userStore = useUserStore(); const userStore = useUserStore();
const isHasSystemPermission = computed(() => { const isHasSystemPermission = computed(() => {
const { systemPermissions } = userStore.currentRole; return userStore.isAdmin;
return hasAnyPermission(systemPermissions, ['SYSTEM']) as boolean;
}); });
const { t } = useI18n(); const { t } = useI18n();
@ -90,7 +88,7 @@
const cardContent = ref<StepListType[]>([ const cardContent = ref<StepListType[]>([
{ {
id: '1001', id: '1001',
icon: 'configplugin', icon: 'downloadplugin',
title: 'organization.service.downloadPluginOrDev', title: 'organization.service.downloadPluginOrDev',
skipTitle: [ skipTitle: [
{ {
@ -111,14 +109,14 @@
}, },
{ {
id: '1002', id: '1002',
icon: 'downloadplugin', icon: 'configplugin',
title: 'organization.service.configPlugin', title: 'organization.service.configPlugin',
skipTitle: [ skipTitle: [
{ {
name: 'organization.service.jumpPlugin', name: 'organization.service.jumpPlugin',
src: '', src: '',
active: true, active: true,
disabled: isHasSystemPermission.value, disabled: !isHasSystemPermission.value,
}, },
], ],
step: '@/assets/images/ms_configplugin.jpg', step: '@/assets/images/ms_configplugin.jpg',

View File

@ -127,6 +127,11 @@ export function getCardList(type: string): Record<string, any>[] {
}); });
} }
export function getTemplateName(type: string, scene: string) {
const dataList = getCardList(type);
return dataList.find((item) => item.key === scene)?.name;
}
// table名称展示图标类型表格展示类型 // table名称展示图标类型表格展示类型
export const fieldIconAndName: fieldIconAndNameModal[] = [ export const fieldIconAndName: fieldIconAndNameModal[] = [
{ {

View File

@ -150,6 +150,7 @@
import { useAppStore, useTableStore } from '@/store'; import { useAppStore, useTableStore } from '@/store';
import useTemplateStore from '@/store/modules/setting/template'; import useTemplateStore from '@/store/modules/setting/template';
import { characterLimit } from '@/utils'; import { characterLimit } from '@/utils';
import { hasAnyPermission } from '@/utils/permission';
import type { AddOrUpdateField, SeneType } from '@/models/setting/template'; import type { AddOrUpdateField, SeneType } from '@/models/setting/template';
import { TableKeyEnum } from '@/enums/tableEnum'; import { TableKeyEnum } from '@/enums/tableEnum';
@ -166,9 +167,9 @@
const props = defineProps<{ const props = defineProps<{
mode: 'organization' | 'project'; mode: 'organization' | 'project';
deletePermission?: string[]; deletePermission: string[];
createPermission?: string[]; createPermission: string[];
updatePermission?: string[]; updatePermission: string[];
}>(); }>();
const currentOrd = computed(() => appStore.currentOrgId); const currentOrd = computed(() => appStore.currentOrgId);
@ -185,6 +186,10 @@
} }
}); });
const hasOperationPermission = computed(() =>
hasAnyPermission([...props.updatePermission, ...props.deletePermission])
);
const fieldColumns: MsTableColumn = [ const fieldColumns: MsTableColumn = [
{ {
title: 'system.orgTemplate.name', title: 'system.orgTemplate.name',
@ -211,11 +216,11 @@
showInTable: true, showInTable: true,
}, },
{ {
title: 'system.orgTemplate.operation', title: hasOperationPermission.value ? 'system.orgTemplate.operation' : '',
slotName: 'operation', slotName: 'operation',
dataIndex: 'operation', dataIndex: 'operation',
fixed: 'right', fixed: 'right',
width: 200, width: hasOperationPermission.value ? 200 : 50,
showInTable: true, showInTable: true,
}, },
]; ];

View File

@ -12,31 +12,9 @@
/** /**
* @description 系统管理-组织-模板管理-字段列表首页 * @description 系统管理-组织-模板管理-字段列表首页
*/ */
import { useRoute } from 'vue-router';
import MsCard from '@/components/pure/ms-card/index.vue'; import MsCard from '@/components/pure/ms-card/index.vue';
import FieldSetting from '@/views/setting/organization/template/components/fieldSetting.vue'; import FieldSetting from '@/views/setting/organization/template/components/fieldSetting.vue';
import { useAppStore } from '@/store';
import { getCardList } from '@/views/setting/organization/template/components/fieldSetting';
const route = useRoute();
const appStore = useAppStore();
//
const updateBreadcrumbList = () => {
const { breadcrumbList } = appStore;
const breadTitle = getCardList('organization').find((item: any) => item.key === route.query.type);
if (breadTitle) {
breadcrumbList[0].locale = breadTitle.name;
appStore.setBreadcrumbList(breadcrumbList);
}
};
onMounted(() => {
updateBreadcrumbList();
});
</script> </script>
<style scoped></style> <style scoped></style>

View File

@ -143,7 +143,7 @@
import type { ActionTemplateManage, CustomField, DefinedFieldItem } from '@/models/setting/template'; import type { ActionTemplateManage, CustomField, DefinedFieldItem } from '@/models/setting/template';
import { SettingRouteEnum } from '@/enums/routeEnum'; import { SettingRouteEnum } from '@/enums/routeEnum';
import { getCardList, getCustomDetailFields, getTotalFieldOptionList } from './fieldSetting'; import { getCardList, getCustomDetailFields, getTemplateName, getTotalFieldOptionList } from './fieldSetting';
const { t } = useI18n(); const { t } = useI18n();
const route = useRoute(); const route = useRoute();
@ -233,10 +233,14 @@
title.value = t('system.orgTemplate.copyTemplate'); title.value = t('system.orgTemplate.copyTemplate');
getClassifyField(); getClassifyField();
} else if (isEdit.value) { } else if (isEdit.value) {
title.value = t('menu.settings.organization.templateManagementEdit'); title.value = t('system.orgTemplate.createTemplateType', {
type: getTemplateName('organization', route.query.type as string),
});
getClassifyField(); getClassifyField();
} else { } else {
title.value = t('menu.settings.organization.templateManagementDetail'); title.value = t('menu.settings.organization.editTemplateType', {
type: getTemplateName('organization', route.query.type as string),
});
} }
}); });

View File

@ -83,13 +83,12 @@
import { useAppStore, useTableStore } from '@/store'; import { useAppStore, useTableStore } from '@/store';
import useTemplateStore from '@/store/modules/setting/template'; import useTemplateStore from '@/store/modules/setting/template';
import { characterLimit } from '@/utils'; import { characterLimit } from '@/utils';
import { hasAnyPermission } from '@/utils/permission';
import type { OrdTemplateManagement } from '@/models/setting/template'; import type { OrdTemplateManagement } from '@/models/setting/template';
import { SettingRouteEnum } from '@/enums/routeEnum'; import { SettingRouteEnum } from '@/enums/routeEnum';
import { TableKeyEnum } from '@/enums/tableEnum'; import { TableKeyEnum } from '@/enums/tableEnum';
import { getCardList } from './fieldSetting';
const route = useRoute(); const route = useRoute();
const { t } = useI18n(); const { t } = useI18n();
const tableStore = useTableStore(); const tableStore = useTableStore();
@ -100,6 +99,10 @@
const keyword = ref(''); const keyword = ref('');
const currentOrd = computed(() => appStore.currentOrgId); const currentOrd = computed(() => appStore.currentOrgId);
const hasOperationPermission = computed(() =>
hasAnyPermission(['ORGANIZATION_TEMPLATE:READ+UPDATE', 'ORGANIZATION_TEMPLATE:READ+DELETE'])
);
const fieldColumns: MsTableColumn = [ const fieldColumns: MsTableColumn = [
{ {
title: 'system.orgTemplate.columnTemplateName', title: 'system.orgTemplate.columnTemplateName',
@ -125,11 +128,11 @@
showInTable: true, showInTable: true,
}, },
{ {
title: 'system.orgTemplate.operation', title: hasOperationPermission.value ? 'system.orgTemplate.operation' : '',
slotName: 'operation', slotName: 'operation',
dataIndex: 'operation', dataIndex: 'operation',
fixed: 'right', fixed: 'right',
width: 200, width: hasOperationPermission.value ? 200 : 50,
showInTable: true, showInTable: true,
showDrag: false, showDrag: false,
}, },
@ -249,16 +252,6 @@
}); });
}; };
//
const updateBreadcrumbList = () => {
const { breadcrumbList } = appStore;
const breadTitle = getCardList('organization').find((item: any) => item.key === route.query.type);
if (breadTitle) {
breadcrumbList[0].locale = breadTitle.name;
appStore.setBreadcrumbList(breadcrumbList);
}
};
const tableRef = ref(); const tableRef = ref();
const sceneType = computed(() => route.query.type); const sceneType = computed(() => route.query.type);
@ -283,7 +276,6 @@
} }
onMounted(() => { onMounted(() => {
updateBreadcrumbList();
fetchData(); fetchData();
updateColumns(); updateColumns();
}); });

View File

@ -106,7 +106,9 @@ export default {
'system.orgTemplate.deleteTemplateTitle': 'Are you sure to delete { name }?', 'system.orgTemplate.deleteTemplateTitle': 'Are you sure to delete { name }?',
'system.orgTemplate.apiInputPlaceholder': 'Please enter a third-party API', 'system.orgTemplate.apiInputPlaceholder': 'Please enter a third-party API',
'system.orgTemplate.apiFieldId': 'API field', 'system.orgTemplate.apiFieldId': 'API field',
'system.orgTemplate.copyTemplate': 'Copy Template', 'system.orgTemplate.copyTemplate': 'copy{type}template',
'system.orgTemplate.createTemplateType': 'create{type}',
'system.orgTemplate.editTemplateType': 'edit{type}',
'system.orgTemplate.workFlowTip': 'system.orgTemplate.workFlowTip':
'Change the properties or workflow configuration of the event will take effect immediately on the related project. Exercise caution when performing this operation', 'Change the properties or workflow configuration of the event will take effect immediately on the related project. Exercise caution when performing this operation',
'system.orgTemplate.workFlowToolTip': 'system.orgTemplate.workFlowToolTip':

View File

@ -106,7 +106,9 @@ export default {
'system.orgTemplate.deleteTemplateTitle': '确认删除 {name} 吗?', 'system.orgTemplate.deleteTemplateTitle': '确认删除 {name} 吗?',
'system.orgTemplate.apiInputPlaceholder': '请输入第三方 API', 'system.orgTemplate.apiInputPlaceholder': '请输入第三方 API',
'system.orgTemplate.apiFieldId': 'API 字段', 'system.orgTemplate.apiFieldId': 'API 字段',
'system.orgTemplate.copyTemplate': '复制模板', 'system.orgTemplate.copyTemplate': '复制{type}模板',
'system.orgTemplate.createTemplateType': '创建{type}',
'system.orgTemplate.editTemplateType': '编辑{type}',
'system.orgTemplate.workFlowTip': '更改事项的属性或工作流配置,会在相关项目立即生效,请谨慎操作', 'system.orgTemplate.workFlowTip': '更改事项的属性或工作流配置,会在相关项目立即生效,请谨慎操作',
'system.orgTemplate.workFlowToolTip': '列为缺陷所在状态,在列内“点击+”,可添加流转状态', 'system.orgTemplate.workFlowToolTip': '列为缺陷所在状态,在列内“点击+”,可添加流转状态',
'system.orgTemplate.workFlowToolTipHover': 'hover 可更换初始状态,操作列可选择结束状态', 'system.orgTemplate.workFlowToolTipHover': 'hover 可更换初始状态,操作列可选择结束状态',

View File

@ -608,6 +608,7 @@
import { useTableStore } from '@/store'; import { useTableStore } from '@/store';
import { characterLimit } from '@/utils'; import { characterLimit } from '@/utils';
import { scrollIntoView } from '@/utils/dom'; import { scrollIntoView } from '@/utils/dom';
import { hasAnyPermission } from '@/utils/permission';
import type { AuthDetail, AuthForm, AuthItem, AuthType } from '@/models/setting/config'; import type { AuthDetail, AuthForm, AuthItem, AuthType } from '@/models/setting/config';
import { TableKeyEnum } from '@/enums/tableEnum'; import { TableKeyEnum } from '@/enums/tableEnum';
@ -618,11 +619,16 @@
const { openModal } = useModal(); const { openModal } = useModal();
const loading = ref(false); const loading = ref(false);
const hasOperationPermission = computed(() =>
hasAnyPermission(['SYSTEM_PARAMETER_SETTING_AUTH:READ+UPDATE', 'SYSTEM_PARAMETER_SETTING_AUTH:READ+DELETE'])
);
const tableActions: ActionsItem[] = [ const tableActions: ActionsItem[] = [
{ {
label: 'system.config.auth.delete', label: 'system.config.auth.delete',
eventTag: 'delete', eventTag: 'delete',
danger: true, danger: true,
permission: ['SYSTEM_PARAMETER_SETTING_AUTH:READ+DELETE'],
}, },
]; ];
const columns: MsTableColumn = [ const columns: MsTableColumn = [
@ -655,10 +661,10 @@
showInTable: true, showInTable: true,
}, },
{ {
title: 'system.config.auth.action', title: hasOperationPermission.value ? 'system.config.auth.action' : '',
slotName: 'action', slotName: 'action',
fixed: 'right', fixed: 'right',
width: 140, width: hasOperationPermission.value ? 140 : 50,
dataIndex: 'operation', dataIndex: 'operation',
showInTable: true, showInTable: true,
}, },

View File

@ -117,7 +117,7 @@
<span>{{ getTime(record.updateTime) }}</span> <span>{{ getTime(record.updateTime) }}</span>
</template> </template>
</a-table-column> </a-table-column>
<a-table-column :width="180" fixed="right" :bordered="false"> <a-table-column v-if="hasOperationPluginPermission" :width="180" fixed="right" :bordered="false">
<template #title> <template #title>
{{ t('system.plugin.tableColumnsActions') }} {{ t('system.plugin.tableColumnsActions') }}
</template> </template>
@ -215,6 +215,7 @@
import useModal from '@/hooks/useModal'; import useModal from '@/hooks/useModal';
import useVisit from '@/hooks/useVisit'; import useVisit from '@/hooks/useVisit';
import { characterLimit } from '@/utils'; import { characterLimit } from '@/utils';
import { hasAnyPermission } from '@/utils/permission';
import type { DrawerConfig, PluginForms, PluginItem, PluginList, UpdatePluginModel } from '@/models/setting/plugin'; import type { DrawerConfig, PluginForms, PluginItem, PluginList, UpdatePluginModel } from '@/models/setting/plugin';
@ -226,6 +227,10 @@
const loading = ref<boolean>(false); const loading = ref<boolean>(false);
const expandedRowKeys = reactive([]); const expandedRowKeys = reactive([]);
const hasOperationPluginPermission = computed(() =>
hasAnyPermission(['SYSTEM_PLUGIN:READ+UPDATE', 'SYSTEM_PLUGIN:READ+DELETE'])
);
const config = ref<DrawerConfig>({ const config = ref<DrawerConfig>({
title: '', title: '',
pluginId: '', pluginId: '',

View File

@ -97,6 +97,7 @@
import useModal from '@/hooks/useModal'; import useModal from '@/hooks/useModal';
import { useTableStore } from '@/store'; import { useTableStore } from '@/store';
import { characterLimit } from '@/utils'; import { characterLimit } from '@/utils';
import { hasAnyPermission } from '@/utils/permission';
import type { ResourcePoolDetail } from '@/models/setting/resourcePool'; import type { ResourcePoolDetail } from '@/models/setting/resourcePool';
import { TableKeyEnum } from '@/enums/tableEnum'; import { TableKeyEnum } from '@/enums/tableEnum';
@ -104,6 +105,10 @@
const { t } = useI18n(); const { t } = useI18n();
const router = useRouter(); const router = useRouter();
const route = useRoute(); const route = useRoute();
const hasOperationPoolPermission = computed(() =>
hasAnyPermission(['SYSTEM_TEST_RESOURCE_POOL:READ+UPDATE', 'SYSTEM_TEST_RESOURCE_POOL:READ+DELETE'])
);
const columns: MsTableColumn = [ const columns: MsTableColumn = [
{ {
title: 'system.resourcePool.tableColumnName', title: 'system.resourcePool.tableColumnName',
@ -136,11 +141,11 @@
width: 180, width: 180,
}, },
{ {
title: 'system.resourcePool.tableColumnActions', title: hasOperationPoolPermission.value ? 'system.resourcePool.tableColumnActions' : '',
slotName: 'action', slotName: 'action',
dataIndex: 'operation', dataIndex: 'operation',
fixed: 'right', fixed: 'right',
width: 140, width: hasOperationPoolPermission.value ? 140 : 50,
}, },
]; ];
const tableStore = useTableStore(); const tableStore = useTableStore();

View File

@ -330,6 +330,10 @@
const { currentLocale } = useLocale(); const { currentLocale } = useLocale();
const route = useRoute(); const route = useRoute();
const hasOperationSysUserPermission = computed(() =>
hasAnyPermission(['SYSTEM_USER:READ+UPDATE', 'SYSTEM_USER:READ+DELETE'])
);
const columns: MsTableColumn = [ const columns: MsTableColumn = [
{ {
title: 'system.user.tableColumnEmail', title: 'system.user.tableColumnEmail',
@ -365,11 +369,11 @@
dataIndex: 'enable', dataIndex: 'enable',
}, },
{ {
title: 'system.user.tableColumnActions', title: hasOperationSysUserPermission.value ? 'system.user.tableColumnActions' : '',
slotName: 'action', slotName: 'action',
dataIndex: 'operation', dataIndex: 'operation',
fixed: 'right', fixed: 'right',
width: 110, width: hasOperationSysUserPermission.value ? 110 : 50,
}, },
]; ];
const tableStore = useTableStore(); const tableStore = useTableStore();