fix: 系统设置bug修复&用例管理bug修复&任务中心调整

This commit is contained in:
xinxin.wu 2024-02-19 22:51:31 +08:00 committed by Craftsman
parent 47399e6ba5
commit 95c1ade326
41 changed files with 671 additions and 187 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

After

Width:  |  Height:  |  Size: 490 KiB

View File

@ -217,7 +217,7 @@ export function addDemandRequest(data: CreateOrUpdateDemand) {
}
// 更新需求
export function updateDemand(data: CreateOrUpdateDemand) {
export function updateDemandReq(data: CreateOrUpdateDemand) {
return MSR.post({ url: UpdateDemandUrl, data });
}
// 批量关联需求
@ -239,7 +239,8 @@ export function getThirdDemandList(data: TableQueryParams) {
// 上传文件并关联用例
export function uploadOrAssociationFile(data: Record<string, any>) {
return MSR.uploadFile({ url: UploadOrAssociationFileUrl }, { request: data.request, fileList: [data.file] });
debugger;
return MSR.uploadFile({ url: UploadOrAssociationFileUrl }, { request: data.request, fileList: data.file });
}
// 转存文件
export function transferFileRequest(data: OperationFile) {

View File

@ -96,7 +96,7 @@ export function enableOrOffTemplate(organizationId: string, scene: SeneType) {
*/
// 获取自定义字段列表(组织)
export function getFieldList(params: TableQueryParams) {
return MSR.get({ url: `${GetDefinedFieldListUrl}${params.scopedId}/${params.scene}` });
return MSR.get({ url: `${GetDefinedFieldListUrl}/${params.scopedId}/${params.scene}` });
}
// 创建自定义字段(组织)
@ -154,7 +154,7 @@ export function updateOrdWorkStateFlow(data: UpdateWorkFlowSetting) {
*/
// 获取自定义字段列表(组织)
export function getProjectFieldList(params: TableQueryParams) {
return MSR.get({ url: `${GetDefinedProjectFieldListUrl}${params.scopedId}/${params.scene}` });
return MSR.get({ url: `${GetDefinedProjectFieldListUrl}/${params.scopedId}/${params.scene}` });
}
// 创建自定义字段(组织)

View File

@ -37,7 +37,7 @@ export const getOrdTemplateStateUrl = '/organization/template/enable/config';
// 系统设置-组织-自定义字段
// 获取自定义字段列表
export const GetDefinedFieldListUrl = '/organization/custom/field/list/';
export const GetDefinedFieldListUrl = '/organization/custom/field/list';
// 创建自定义字段
export const CreateFieldUrl = '/organization/custom/field/add';
// 更新自定义字段
@ -67,7 +67,7 @@ export const OrdUpdateStateFlowUrl = '/organization/status/flow/setting/status/f
// 项目管理-模板-自定义字段
// 获取自定义字段列表
export const GetDefinedProjectFieldListUrl = '/project/custom/field/list/';
export const GetDefinedProjectFieldListUrl = '/project/custom/field/list';
// 创建自定义字段
export const CreateProjectFieldUrl = '/project/custom/field/add';
// 更新自定义字段

View File

@ -175,7 +175,12 @@
</a-checkbox-group>
</a-form-item>
</div>
<div class="delete-btn" :class="{ 'delete-btn:disabled': idx === 0 }" @click="handleDeleteItem(idx)">
<div
v-if="formModel.list.length > 1"
class="delete-btn"
:class="{ 'delete-btn:disabled': idx === 0 }"
@click="handleDeleteItem(idx)"
>
<icon-minus-circle />
</div>
</section>
@ -305,7 +310,10 @@
* @description 删除条件
*/
const handleDeleteItem = (index: number) => {
if (index === 0) {
// if (index === 0) {
// return;
// }
if (formModel.list.length === 1) {
return;
}
formModel.list.splice(index, 1);

View File

@ -21,7 +21,7 @@
<template #title> {{ t('settings.navbar.task') }}</template>
<div class="divider h-full">
<TaskCenter group="system" mode="modal"></TaskCenter>
<TaskCenter group="project" mode="modal"></TaskCenter>
</div>
</a-modal>
</template>

View File

@ -375,13 +375,13 @@ export const pathMap: PathMapItem[] = [
permission: [],
level: MENU_LEVEL[2],
},
// {
// key: 'PROJECT_MANAGEMENT_PERMISSION_VERSION', // 项目管理-项目与权限-项目版本
// locale: 'project.permission.projectVersion',
// route: RouteEnum.PROJECT_MANAGEMENT_PERMISSION_VERSION,
// permission: [],
// level: MENU_LEVEL[2],
// },
{
key: 'PROJECT_MANAGEMENT_PERMISSION_VERSION', // 项目管理-项目与权限-项目版本
locale: 'project.permission.projectVersion',
route: RouteEnum.PROJECT_MANAGEMENT_PERMISSION_VERSION,
permission: [],
level: MENU_LEVEL[2],
},
{
key: 'PROJECT_MANAGEMENT_PERMISSION_MEMBER', // 项目管理-项目与权限-成员
locale: 'project.permission.member',
@ -412,6 +412,13 @@ export const pathMap: PathMapItem[] = [
permission: [],
level: MENU_LEVEL[2],
},
{
key: 'PROJECT_CUSTOM_FIELD', // 项目管理-模板管理-字段设置-新增字段
locale: 'system.orgTemplate.addField',
route: '',
permission: [],
level: MENU_LEVEL[2],
},
{
key: 'PROJECT_MANAGEMENT_TEMPLATE_MANAGEMENT', // 项目管理-模板管理列表
locale: 'menu.settings.organization.templateManagementList',

View File

@ -75,6 +75,7 @@ export enum SettingRouteEnum {
SETTING_SYSTEM_RESOURCE_POOL_DETAIL = 'settingSystemResourcePoolDetail',
SETTING_SYSTEM_AUTHORIZED_MANAGEMENT = 'settingSystemAuthorizedManagement',
SETTING_SYSTEM_LOG = 'settingSystemLog',
SETTING_SYSTEM_TASK_CENTER = 'settingSystemTaskCenter',
SETTING_SYSTEM_PLUGIN_MANAGEMENT = 'settingSystemPluginManagement',
SETTING_ORGANIZATION = 'settingOrganization',
SETTING_ORGANIZATION_MEMBER = 'settingOrganizationMember',

View File

@ -254,9 +254,9 @@ export interface DemandFormList {
// 创建需求&编辑需求
export interface CreateOrUpdateDemand {
id?: string;
caseId: string;
demandPlatform: string;
demandList?: DemandFormList[];
caseId?: string;
[key: string]: any;
}
// 转存文件

View File

@ -115,6 +115,7 @@ export interface ActionTemplateManage {
customFields?: CustomField[];
fieldType?: string;
systemFields?: Record<string, any>[];
internal?: boolean; // 是否为系统模板
}
// 工作流列表字段

View File

@ -197,6 +197,7 @@ const ProjectManagement: AppRouteRecordRaw = {
name: ProjectManagementRouteEnum.PROJECT_MANAGEMENT_TEMPLATE_MANAGEMENT_DETAIL,
locale: 'menu.settings.organization.templateManagementDetail',
editLocale: 'menu.settings.organization.templateManagementEdit',
editTag: 'id',
query: ['type'],
},
],
@ -289,17 +290,6 @@ const ProjectManagement: AppRouteRecordRaw = {
isTopMenu: true,
},
},
// 任务中心
{
path: 'taskCenter',
name: ProjectManagementRouteEnum.PROJECT_MANAGEMENT_TASK_CENTER,
component: () => import('@/views/project-management/taskCenter/index.vue'),
meta: {
locale: 'menu.projectManagement.taskCenter',
roles: ['*'],
isTopMenu: true,
},
},
// 菜单管理-误报规则
{
path: 'errorReportRule',

View File

@ -150,6 +150,17 @@ const Setting: AppRouteRecordRaw = {
isTopMenu: true,
},
},
// 任务中心
{
path: 'taskCenter',
name: SettingRouteEnum.SETTING_SYSTEM_TASK_CENTER,
component: () => import('@/views/setting/system/taskCenter/index.vue'),
meta: {
locale: 'menu.projectManagement.taskCenter',
roles: ['*'],
isTopMenu: true,
},
},
{
path: 'pluginManager',
name: SettingRouteEnum.SETTING_SYSTEM_PLUGIN_MANAGEMENT,

View File

@ -1,58 +1,36 @@
<template>
<MsBaseTable v-bind="propsRes" ref="tableRef" v-on="propsEvent">
<MsBaseTable v-bind="propsRes" ref="tableRef" :hoverable="false" v-on="propsEvent" @change="changeHandler">
<template #index="{ rowIndex }">
<div class="circle text-xs font-medium"> {{ rowIndex + 1 }}</div>
</template>
<template #caseStep="{ record }">
<!-- v-if="record.showStep" -->
<a-textarea
v-if="record.showStep"
:ref="(el: refItem) => setStepRefMap(el, record)"
v-model="record.step"
size="mini"
:auto-size="true"
class="w-max-[267px]"
class="w-max-[267px] param-input"
:placeholder="t('system.orgTemplate.stepTip')"
@blur="blurHandler(record, 'step')"
/>
<div v-else-if="record.step && !record.showStep" class="w-full cursor-pointer" @click="edit(record, 'step')">{{
record.step
}}</div>
<div
v-else-if="!record.caseStep && !record.showStep"
class="placeholder w-full cursor-pointer text-[var(--color-text-brand)]"
@click="edit(record, 'step')"
>{{ t('system.orgTemplate.stepTip') }}</div
>
</template>
<template #expectedResult="{ record }">
<a-textarea
v-if="record.showExpected"
:ref="(el: refItem) => setExpectedRefMap(el, record)"
v-model="record.expected"
:max-length="1000"
size="mini"
:auto-size="true"
class="w-max-[267px]"
class="w-max-[267px] param-input"
:placeholder="t('system.orgTemplate.expectationTip')"
@blur="blurHandler(record, 'expected')"
/>
<div
v-else-if="record.expected && !record.showExpected"
class="w-full cursor-pointer"
@click="edit(record, 'expected')"
>{{ record.expected }}</div
>
<div
v-else-if="!record.expected && !record.showExpected"
class="placeholder w-full cursor-pointer text-[var(--color-text-brand)]"
@click="edit(record, 'expected')"
>{{ t('system.orgTemplate.expectationTip') }}</div
>
</template>
<template #operation="{ record }">
<MsTableMoreAction
v-if="!record.internal"
:list="moreActions"
:list="moreActionList"
@select="(item:ActionsItem) => handleMoreActionSelect(item,record)"
/>
</template>
@ -67,6 +45,7 @@
<script setup lang="ts">
import { ref } from 'vue';
import { TableChangeExtra, TableData } from '@arco-design/web-vue';
import MsBaseTable from '@/components/pure/ms-table/base-table.vue';
import { MsTableColumn } from '@/components/pure/ms-table/type';
@ -95,6 +74,17 @@
const emit = defineEmits(['update:stepList']);
//
const stepData = ref<StepList[]>([
{
id: getGenerateId(),
step: '',
expected: '',
showStep: false,
showExpected: false,
},
]);
const templateFieldColumns = ref<MsTableColumn>([
{
title: 'system.orgTemplate.numberIndex',
@ -151,6 +141,10 @@
},
];
const moreActionList = computed(() => {
return stepData.value.length <= 1 ? moreActions.slice(0, moreActions.length - 2) : moreActions;
});
const { propsRes, propsEvent, setProps } = useTable(undefined, {
tableKey: TableKeyEnum.CASE_MANAGEMENT_DETAIL_TABLE,
columns: templateFieldColumns.value,
@ -163,17 +157,6 @@
enableDrag: true,
});
//
const stepData = ref<StepList[]>([
{
id: getGenerateId(),
step: '',
expected: '',
showStep: false,
showExpected: false,
},
]);
//
function copyStep(record: StepList) {
stepData.value.push({
@ -292,6 +275,13 @@
}
});
function changeHandler(data: TableData[], extra: TableChangeExtra, currentData: TableData[]) {
if (!currentData || currentData.length === 1) {
return false;
}
stepData.value = data as StepList[];
}
watch(
() => stepData.value,
(val) => {
@ -326,4 +316,18 @@
color: var(--color-text-4);
background: var(--color-text-n8);
}
:deep(.param-input:not(.arco-input-focus, .arco-select-view-focus)) {
&:not(:hover) {
border-color: transparent !important;
.arco-input::placeholder {
@apply invisible;
}
.arco-select-view-icon {
@apply invisible;
}
.arco-select-view-value {
color: var(--color-text-brand);
}
}
}
</style>

View File

@ -91,7 +91,13 @@
</div>
</template>
<template #default>
<div ref="wrapperRef" class="wrapperRef h-full bg-white">
<div
ref="wrapperRef"
class="wrapperRef bg-white"
:style="{
height: isFullScreen ? '100%' : 'calc(100% - 86px)',
}"
>
<MsSplitBox
ref="wrapperRef"
:class="isFullScreen ? 'h-[100%]' : 'h-[calc(100% - 78px)]'"
@ -365,7 +371,7 @@
const editLoading = ref<boolean>(false);
function updateSuccess() {
async function updateSuccess() {
detailDrawerRef.value?.initDetail();
}
@ -391,7 +397,7 @@
followLoading.value = true;
try {
if (detailInfo.value.id) {
await followerCaseRequest({ userId: userId.value as string, functionalCaseId: detailInfo.value.id });
await followerCaseRequest({ userId: userStore.userInfo.id as string, functionalCaseId: detailInfo.value.id });
updateSuccess();
Message.success(
detailInfo.value.followFlag
@ -440,8 +446,6 @@
const formRules = ref<FormItem[]>([]);
const formItem = ref<FormRuleItem[]>([]);
const isDisabled = ref<boolean>(false);
//
const options = {
resetBtn: false, //
@ -473,7 +477,15 @@
function initForm() {
formRules.value = customFields.value.map((item: any) => {
const multipleType = ['MULTIPLE_SELECT', 'CHECKBOX', 'MULTIPLE_MEMBER', 'MULTIPLE_INPUT'];
const currentDefaultValue = multipleType.includes(item.type) ? JSON.parse(item.defaultValue) : item.defaultValue;
const numberType = ['INT', 'FLOAT'];
let currentDefaultValue;
if (numberType.includes(item.type)) {
currentDefaultValue = item.defaultValue * 1;
} else if (multipleType.includes(item.type)) {
currentDefaultValue = JSON.parse(item.defaultValue);
} else {
currentDefaultValue = item.defaultValue;
}
return {
...item,
type: item.type,

View File

@ -197,7 +197,20 @@
:pagination="propsRes.msPagination!"
@success="initData()"
/>
<AddDemandModal v-model:visible="showDemandModel" :case-id="caseId" :form="modelForm" />
<AddDemandModal
ref="demandRef"
v-model:visible="showDemandModel"
:loading="confirmLoading"
:case-id="caseId"
:form="modelForm"
@save="actionDemand"
/>
<ThirdDemandDrawer
v-model:visible="showThirdDrawer"
:case-id="caseId"
:drawer-loading="drawerLoading"
@save="saveThirdDemand"
/>
</template>
<script setup lang="ts">
@ -223,9 +236,11 @@
import FeatureCaseTree from './caseTree.vue';
import ExportExcelDrawer from './exportExcelDrawer.vue';
import AddDemandModal from './tabContent/tabDemand/addDemandModal.vue';
import ThirdDemandDrawer from './tabContent/tabDemand/thirdDemandDrawer.vue';
import TableFormChange from './tableFormChange.vue';
import {
batchAssociationDemand,
batchCopyToModules,
batchDeleteCase,
batchMoveToModules,
@ -247,6 +262,7 @@
import type {
CaseManagementTable,
CaseModuleQueryParams,
CreateOrUpdateDemand,
CustomAttributes,
DemandItem,
DragCase,
@ -472,6 +488,7 @@
showInTable: true,
sortable: {
sortDirections: ['ascend', 'descend'],
sorter: true,
},
width: 200,
showDrag: true,
@ -682,6 +699,7 @@
tableKey: TableKeyEnum.CASE_MANAGEMENT_TABLE,
scroll: { x: scrollWidth.value },
selectable: true,
showJumpMethod: true,
showSetting: true,
heightUsed: 374,
enableDrag: true,
@ -942,8 +960,13 @@
function addDemand() {
showDemandModel.value = true;
}
const showThirdDrawer = ref<boolean>(false);
//
function handleAssociatedDemand() {}
function handleAssociatedDemand() {
showThirdDrawer.value = true;
}
function handleTableBatch(event: BatchActionParams, params: BatchActionQueryParams) {
batchParams.value = params;
@ -1147,9 +1170,10 @@
//
async function changeHandler(data: TableData[], extra: TableChangeExtra, currentData: TableData[]) {
if (currentData.length === 1) {
if (!currentData || currentData.length === 1) {
return;
}
if (extra && extra.dragTarget?.id) {
const params: DragCase = {
projectId: currentProjectId.value,
@ -1178,15 +1202,78 @@
}
}
function showCaseDetailEvent(record: TableData, column: TableColumnData, ev: Event) {
showDetailDrawer.value = false;
if (column.title === 'name' || column.title === 'num') {
const rowIndex = propsRes.value.data.map((item: any) => item.id).indexOf(record.id);
showDetailDrawer.value = true;
activeDetailId.value = record.id;
activeCaseIndex.value = rowIndex;
// function showCaseDetailEvent(record: TableData, column: TableColumnData, ev: Event) {
// showDetailDrawer.value = false;
// if (column.title === 'name' || column.title === 'num') {
// const rowIndex = propsRes.value.data.map((item: any) => item.id).indexOf(record.id);
// showDetailDrawer.value = true;
// activeDetailId.value = record.id;
// activeCaseIndex.value = rowIndex;
// }
// }
//
const confirmLoading = ref<boolean>(false);
const demandRef = ref();
async function actionDemand(param: CreateOrUpdateDemand, isContinue: boolean) {
try {
confirmLoading.value = true;
const { demandPlatform, demandList } = param;
const batchAddParams: CreateOrUpdateDemand = {
selectIds: batchParams.value?.selectAll ? [] : batchParams.value.selectedIds,
selectAll: !!batchParams.value?.selectAll,
excludeIds: batchParams.value?.excludeIds || [],
condition: { keyword: keyword.value },
projectId: currentProjectId.value,
moduleIds: props.activeFolder === 'all' ? [] : [props.activeFolder, ...props.offspringIds],
moduleId: selectedModuleKeys.value[0],
demandPlatform,
demandList,
};
await batchAssociationDemand(batchAddParams);
if (!isContinue) {
showDemandModel.value = false;
}
demandRef.value.resetForm();
Message.success(t('common.addSuccess'));
resetSelector();
initData();
} catch (error) {
console.log(error);
} finally {
confirmLoading.value = false;
}
}
//
const drawerLoading = ref<boolean>(false);
async function saveThirdDemand(params: CreateOrUpdateDemand) {
try {
drawerLoading.value = true;
const { demandPlatform, demandList } = params;
const batchAddParams: CreateOrUpdateDemand = {
selectIds: batchParams.value?.selectAll ? [] : batchParams.value.selectedIds,
selectAll: !!batchParams.value?.selectAll,
excludeIds: batchParams.value?.excludeIds || [],
condition: { keyword: keyword.value },
projectId: currentProjectId.value,
moduleIds: props.activeFolder === 'all' ? [] : [props.activeFolder, ...props.offspringIds],
moduleId: selectedModuleKeys.value[0],
demandPlatform,
demandList,
};
await batchAssociationDemand(batchAddParams);
Message.success(t('caseManagement.featureCase.associatedSuccess'));
showThirdDrawer.value = false;
resetSelector();
initData();
} catch (error) {
console.log(error);
} finally {
drawerLoading.value = false;
}
}
onMounted(() => {
if (route.query.id) {
showCaseDetail(route.query.id as string, 0);

View File

@ -43,7 +43,7 @@
<template #footer>
<a-button type="secondary" @click="handleCancel">{{ t('common.cancel') }}</a-button>
<a-button v-if="!form.id" type="secondary" @click="handleOK(true)">{{ t('ms.dialog.saveContinue') }}</a-button>
<a-button class="ml-[12px]" type="primary" :loading="confirmLoading" @click="handleOK(false)">
<a-button class="ml-[12px]" type="primary" :loading="props.loading" @click="handleOK(false)">
{{ updateName ? t('common.update') : t('common.create') }}
</a-button>
</template>
@ -54,7 +54,6 @@
import { ref } from 'vue';
import { FormInstance, Message, ValidatedError } from '@arco-design/web-vue';
import { addDemandRequest, updateDemand } from '@/api/modules/case-management/featureCase';
import { useI18n } from '@/hooks/useI18n';
import { useAppStore } from '@/store';
@ -67,11 +66,13 @@
caseId: string;
visible: boolean;
form: DemandItem;
loading: boolean;
}>();
const emit = defineEmits<{
(e: 'update:visible', v: boolean): void;
(e: 'success'): void;
(e: 'save', params: CreateOrUpdateDemand, isContinue: boolean): void;
}>();
const pageConfig = computed(() => appStore.pageConfig);
const form = ref<CreateOrUpdateDemand>({
@ -84,7 +85,7 @@
const showModal = ref<boolean>(false);
const confirmLoading = ref<boolean>(false);
// const confirmLoading = ref<boolean>(false);
const initModelForm: DemandFormList = {
demandId: '',
@ -112,30 +113,12 @@
function handleOK(isContinue: boolean) {
demandFormRef.value?.validate(async (errors: undefined | Record<string, ValidatedError>) => {
if (!errors) {
try {
const { demandId, demandName, demandUrl } = modelForm.value;
confirmLoading.value = true;
const params: CreateOrUpdateDemand = {
...form.value,
demandList: [{ demandId, demandName, demandUrl }],
};
if (form.value.id) {
await updateDemand(params);
Message.success(t('common.updateSuccess'));
} else {
await addDemandRequest(params);
Message.success(t('common.addSuccess'));
}
if (!isContinue) {
handleCancel();
}
resetForm();
emit('success');
} catch (error) {
console.log(error);
} finally {
confirmLoading.value = false;
}
emit('save', params, isContinue);
} else {
return false;
}
@ -171,6 +154,10 @@
updateName.value = val.demandName;
}
);
defineExpose({
resetForm,
});
</script>
<style scoped></style>

View File

@ -25,7 +25,15 @@
@update="updateDemand"
@create="addDemand"
></AssociatedDemandTable>
<AddDemandModal v-model:visible="showAddModel" :case-id="props.caseId" :form="modelForm" @success="searchList()" />
<AddDemandModal
ref="demandModalRef"
v-model:visible="showAddModel"
:case-id="props.caseId"
:form="modelForm"
:loading="confirmLoading"
@save="saveHandler"
@success="searchList()"
/>
<MsDrawer
v-model:visible="linkDemandDrawer"
:ok-disabled="tableSelected.length < 1"
@ -81,12 +89,12 @@
import AddDemandModal from './addDemandModal.vue';
import AssociatedDemandTable from './associatedDemandTable.vue';
import { addDemandRequest, getThirdDemandList } from '@/api/modules/case-management/featureCase';
import { addDemandRequest, getThirdDemandList, updateDemandReq } from '@/api/modules/case-management/featureCase';
import { getCaseRelatedInfo } from '@/api/modules/project-management/menuManagement';
import { useI18n } from '@/hooks/useI18n';
import { useAppStore } from '@/store';
import type { DemandItem } from '@/models/caseManagement/featureCase';
import type { CreateOrUpdateDemand, DemandItem } from '@/models/caseManagement/featureCase';
import { TableKeyEnum } from '@/enums/tableEnum';
const { t } = useI18n();
@ -285,6 +293,31 @@
}
);
const confirmLoading = ref<boolean>(false);
const demandModalRef = ref();
async function saveHandler(param: CreateOrUpdateDemand, isContinue: boolean) {
try {
confirmLoading.value = true;
if (param.id) {
await updateDemandReq(param);
Message.success(t('common.updateSuccess'));
} else {
await addDemandRequest(param);
Message.success(t('common.addSuccess'));
}
if (!isContinue) {
showAddModel.value = false;
}
demandModalRef.value.resetForm();
demandRef.value.initData();
} catch (error) {
console.log(error);
} finally {
confirmLoading.value = false;
}
}
onBeforeMount(async () => {
try {
const result = await getCaseRelatedInfo(currentProjectId.value);

View File

@ -0,0 +1,235 @@
<template>
<MsDrawer
v-model:visible="innerLinkDemandVisible"
:ok-disabled="tableSelected.length < 1"
:mask="false"
:title="t('caseManagement.featureCase.associatedDemand')"
:ok-text="t('caseManagement.featureCase.associated')"
:ok-loading="props.drawerLoading"
:width="960"
unmount-on-close
:show-continue="false"
@confirm="handleDrawerConfirm"
@cancel="handleDrawerCancel"
>
<div class="flex items-center justify-between">
<div
><span class="font-medium">{{ getPlatName() }}</span
><span class="ml-1 text-[var(--color-text-4)]">({{ propsRes?.msPagination?.total || 0 }})</span></div
>
<a-input-search
v-model="platformKeyword"
:max-length="255"
:placeholder="t('project.member.searchMember')"
allow-clear
class="mx-[8px] w-[240px]"
@search="searchHandler"
@press-enter="searchHandler"
></a-input-search>
</div>
<ms-base-table ref="tableRef" v-bind="propsRes" v-on="propsEvent">
<template #demandName="{ record }">
<span class="ml-1 text-[rgb(var(--primary-5))]">
{{ record.demandName }}
<span>({{ (record.children || []).length || 0 }})</span></span
>
</template>
<template v-for="item in customFields" :key="item.slotName" #[item.dataIndex]="{ record }">
<span> {{ getSlotName(record, item) }} </span>
</template>
</ms-base-table>
</MsDrawer>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import { useVModel } from '@vueuse/core';
import { Message } from '@arco-design/web-vue';
import MsDrawer from '@/components/pure/ms-drawer/index.vue';
import MsBaseTable from '@/components/pure/ms-table/base-table.vue';
import type { MsTableColumn, MsTableColumnData } from '@/components/pure/ms-table/type';
import useTable from '@/components/pure/ms-table/useTable';
import { getThirdDemandList } from '@/api/modules/case-management/featureCase';
import { getCaseRelatedInfo } from '@/api/modules/project-management/menuManagement';
import { useI18n } from '@/hooks/useI18n';
import { useAppStore } from '@/store';
import type { CreateOrUpdateDemand } from '@/models/caseManagement/featureCase';
import { TableKeyEnum } from '@/enums/tableEnum';
const { t } = useI18n();
const appStore = useAppStore();
const currentProjectId = computed(() => appStore.currentProjectId);
const props = defineProps<{
visible: boolean;
caseId: string;
drawerLoading: boolean;
}>();
const emit = defineEmits<{
(e: 'update:visible', visible: boolean): void;
(e: 'save', params: CreateOrUpdateDemand): void;
}>();
const innerLinkDemandVisible = useVModel(props, 'visible', emit);
const platformKeyword = ref<string>('');
const columns: MsTableColumn = [
{
title: 'caseManagement.featureCase.tableColumnID',
slotName: 'demandId',
dataIndex: 'demandId',
width: 200,
showTooltip: true,
},
{
title: 'caseManagement.featureCase.tableColumnName',
slotName: 'demandName',
dataIndex: 'demandName',
width: 300,
showTooltip: true,
},
// {
// title: 'caseManagement.featureCase.platformDemandState',
// width: 300,
// dataIndex: 'status',
// showTooltip: true,
// ellipsis: true,
// },
// {
// title: 'caseManagement.featureCase.platformDemandHandler',
// width: 300,
// dataIndex: 'handler',
// showTooltip: true,
// ellipsis: true,
// },
];
const fullColumns = ref<MsTableColumn>([]);
const customFields = ref<Record<string, any>[]>([]);
const { propsRes, propsEvent, loadList, setLoadListParams, resetSelector } = useTable(getThirdDemandList, {
tableKey: TableKeyEnum.CASE_MANAGEMENT_TAB_DEMAND_PLATFORM,
columns: fullColumns.value,
rowKey: 'demandId',
scroll: { x: '100%' },
selectable: true,
showSetting: false,
});
const tableSelected = computed(() => {
const selectIds = [...propsRes.value.selectedKeys];
return propsRes.value.data.filter((item: any) => selectIds.indexOf(item.demandId) > -1);
});
const platformInfo = ref<Record<string, any>>({});
function getPlatName() {
switch (platformInfo.value.platform_key) {
case 'zentao':
return t('caseManagement.featureCase.zentao');
default:
break;
}
}
async function handleDrawerConfirm() {
const demandList = tableSelected.value.map((item) => {
return {
demandId: item.demandId,
parent: item.parent,
demandName: item.demandName,
demandUrl: item.demandUrl,
};
});
const params = {
id: JSON.parse(platformInfo.value.demand_platform_config).zentaoId,
caseId: props.caseId,
demandPlatform: platformInfo.value.platform_key,
demandList,
};
emit('save', params);
}
function handleDrawerCancel() {
innerLinkDemandVisible.value = false;
}
function getSlotName(record: any, item: MsTableColumnData) {
if (item?.options) {
const currentRecord = {
...record,
...record.customFields,
};
const currentValue = currentRecord[item.dataIndex as string];
const currentOptions = (JSON.parse(item.options) || []).find((it: any) => it.value === currentValue);
if (currentOptions) {
return currentOptions.text;
}
}
return record.customFields[item.dataIndex as string] || '-';
}
const initData = async () => {
setLoadListParams({ keyword: platformKeyword.value, projectId: currentProjectId.value });
loadList();
};
const searchHandler = () => {
initData();
resetSelector();
};
const tableRef = ref();
async function initColumn() {
try {
const res = await getThirdDemandList({
current: 1,
pageSize: 10,
projectId: currentProjectId.value,
});
customFields.value = (res.data.customHeaders || []).map((item: any) => {
return {
title: item.name,
slotName: item.id,
dataIndex: item.id,
width: 200,
options: item.options,
};
}) as any;
fullColumns.value = [...columns, ...customFields.value];
} catch (error) {
tableRef.value.initColumn(columns);
console.log(error);
}
}
onBeforeMount(async () => {
try {
const result = await getCaseRelatedInfo(currentProjectId.value);
if (result && result.platform_key) {
platformInfo.value = { ...result };
}
} catch (error) {
console.log(error);
}
});
watch(
() => innerLinkDemandVisible.value,
async (val) => {
if (val) {
resetSelector();
await initColumn();
initData();
}
},
{
immediate: true,
}
);
</script>
<style scoped></style>

View File

@ -66,9 +66,11 @@
v-model:filed-ids="textDescriptionFileIds"
:upload-image="handleUploadImage"
/>
<div v-if="detailForm.caseEditType === 'TEXT' && !isEditPreposition">{{
detailForm.textDescription || '-'
}}</div>
<div
v-if="detailForm.caseEditType === 'TEXT' && !isEditPreposition"
v-dompurify-html="detailForm.textDescription || '-'"
class="text-[var(--color-text-3)]"
></div>
</a-form-item>
<a-form-item
v-if="detailForm.caseEditType === 'TEXT'"
@ -81,7 +83,7 @@
v-model:filed-ids="expectedResultFileIds"
:upload-image="handleUploadImage"
/>
<div v-else class="text-[var(--color-text-3)]" v-html="detailForm.description || '-'"></div>
<div v-else v-dompurify-html="detailForm.expectedResult || '-'" class="text-[var(--color-text-3)]"></div>
</a-form-item>
<a-form-item field="description" :label="t('caseManagement.featureCase.remark')">
<MsRichText
@ -601,10 +603,21 @@
}
);
async function startUpload() {
await sleep(300);
await fileListRef.value?.startUpload();
async function startUpload(fileIds?: string[]) {
try {
const params = {
request: {
caseId: detailForm.value.id,
projectId: currentProjectId.value,
fileIds,
},
file: fileList.value.filter((item) => item.status === 'init').map((item) => item.file),
};
await uploadOrAssociationFile(params);
emit('updateSuccess');
} catch (error) {
console.log(error);
}
}
//
watch(
@ -620,7 +633,9 @@
//
function saveSelectAssociatedFile(fileData: AssociatedList[]) {
const fileResultList = fileData.map((fileInfo) => convertToFile(fileInfo));
fileList.value.push(...fileResultList);
// fileList.value.push(...fileResultList);
const fileIds = fileResultList.map((item: any) => item.uid);
startUpload(fileIds);
}
//

View File

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

View File

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

View File

@ -26,9 +26,13 @@
:rules="[{ required: true, message: t('login.form.userName.errMsg') }]"
:validate-trigger="['change', 'blur']"
hide-label
maxlength="64"
>
<a-input v-model="userInfo.username" :max-length="255" :placeholder="t('login.form.userName.placeholder')" />
<a-input
v-model="userInfo.username"
:max-length="64"
size="large"
:placeholder="t('login.form.userName.placeholder')"
/>
</a-form-item>
<a-form-item
class="login-form-item"
@ -41,18 +45,19 @@
v-model="userInfo.password"
:placeholder="t('login.form.password.placeholder')"
allow-clear
maxlength="64"
:max-length="64"
size="large"
/>
</a-form-item>
<div class="mb-6 mt-[12px]">
<a-button type="primary" html-type="submit" long :loading="loading">
<div class="mb-[60px] mt-[12px]">
<a-button type="primary" size="large" html-type="submit" long :loading="loading">
{{ t('login.form.login') }}
</a-button>
</div>
<a-divider orientation="center" type="dashed">
<a-divider orientation="center" type="dashed" class="m-0 mb-2">
<span class="text-xs font-normal text-[var(--color-text-4)]">{{ t('login.form.modeLoginMethods') }}</span>
</a-divider>
<div class="flex items-center justify-center">
<div class="mt-4 flex items-center justify-center">
<div v-if="userInfo.authenticate !== 'LDAP' && isShowLDAP" class="loginType" @click="switchLoginType('LDAP')">
<span class="type-text text-[10px]">LDAP</span>
</div>
@ -188,13 +193,6 @@
/* stylelint-disable color-function-notation */
.login-form {
@apply flex flex-1 flex-col items-center justify-center;
background: linear-gradient(
26.72deg,
rgba(var(--primary-5), 0.02) 0%,
rgba(var(--primary-5), 0.1) 51.67%,
var(--color-text-fff) 100%
);
.title-welcome {
color: rgb(var(--primary-5));
}

View File

@ -205,6 +205,7 @@
selectable: !!hasAnyPermission(['PROJECT_USER:READ+DELETE', 'ORGANIZATION_MEMBER:READ+UPDATE']),
showSetting: true,
heightUsed: 288,
showJumpMethod: true,
columns,
scroll: {
x: 1200,

View File

@ -47,18 +47,19 @@
value: TaskCenterEnum.API_SCENARIO,
label: t('project.taskCenter.apiScenario'),
},
{
value: TaskCenterEnum.UI_TEST,
label: t('project.taskCenter.uiDefaultFile'),
},
{
value: TaskCenterEnum.LOAD_TEST,
label: t('project.taskCenter.performanceTest'),
},
{
value: TaskCenterEnum.TEST_PLAN,
label: t('project.taskCenter.testPlan'),
},
// TODO
// {
// value: TaskCenterEnum.UI_TEST,
// label: t('project.taskCenter.uiDefaultFile'),
// },
// {
// value: TaskCenterEnum.LOAD_TEST,
// label: t('project.taskCenter.performanceTest'),
// },
// {
// value: TaskCenterEnum.TEST_PLAN,
// label: t('project.taskCenter.testPlan'),
// },
]);
const timingTabList = ref([

View File

@ -31,6 +31,7 @@
:placeholder="t('system.orgTemplate.templateNamePlaceholder')"
:max-length="255"
class="max-w-[732px]"
:disabled="templateForm?.internal"
></a-input>
</a-form-item>
<a-form-item field="remark" :label="t('system.orgTemplate.description')" asterisk-position="end">

View File

@ -1,7 +1,12 @@
<template>
<MsCard has-breadcrumb simple>
<div class="mb-4 flex items-center justify-between">
<span v-if="isEnableOrdTemplate" class="font-medium">{{ t('system.orgTemplate.templateList') }}</span>
<!-- <span v-if="isEnableOrdTemplate" class="font-medium">{{
t('system.orgTemplate.templateList', { type: getTemplateName('project', route.query.type as string) })
}}</span> -->
<span v-if="isShowList" class="font-medium">{{
t('system.orgTemplate.templateList', { type: getTemplateName('project', route.query.type as string) })
}}</span>
<!--TODO 这个版本不允许修改默认模版也不允许创建用例模版 -->
<a-button
v-if="!isEnableOrdTemplate && route.query.type === 'BUG'"
@ -10,7 +15,11 @@
:disabled="false"
@click="createTemplate"
>
{{ t('system.orgTemplate.createTemplate') }}
{{
t('system.orgTemplate.createTemplateType', {
type: getTemplateName('project', route.query.type as string),
})
}}
</a-button>
<a-input-search
v-model:model-value="keyword"
@ -33,7 +42,7 @@
<!-- TODO 这个版本不允许修改默认模版也不允许创建用例模版 -->
<a-switch
v-model="record.enableDefault"
:disabled="true"
:disabled="record.enableDefault || isEnableOrdTemplate"
size="small"
type="line"
@change="(value) => changeDefault(value, record)"
@ -55,9 +64,12 @@
<MsButton v-permission="['PROJECT_TEMPLATE:READ+UPDATE']" @click="editTemplate(record.id)">{{
t('system.orgTemplate.edit')
}}</MsButton>
<MsButton v-permission="['PROJECT_TEMPLATE:READ+ADD']" class="!mr-0" @click="copyTemplate(record.id)">{{
t('system.orgTemplate.copy')
}}</MsButton>
<MsButton
v-if="route.query.type === 'BUG' && hasAnyPermission(['PROJECT_TEMPLATE:READ+ADD'])"
class="!mr-0"
@click="copyTemplate(record.id)"
>{{ t('system.orgTemplate.copy') }}</MsButton
>
<a-divider
v-if="!record.internal"
v-permission="['PROJECT_TEMPLATE:READ+ADD']"
@ -130,6 +142,7 @@
import {
getCustomDetailFields,
getTemplateName,
getTotalFieldOptionList,
} from '@/views/setting/organization/template/components/fieldSetting';
@ -203,10 +216,11 @@
const { propsRes, propsEvent, loadList, setLoadListParams, setProps } = useTable(getProjectTemplateList, {
tableKey: TableKeyEnum.ORGANIZATION_TEMPLATE_MANAGEMENT,
scroll: { x: '1400px' },
columns: fieldColumns,
selectable: false,
noDisable: true,
size: 'default',
showSetting: true,
showSetting: false,
showPagination: false,
heightUsed: 380,
});
@ -376,6 +390,16 @@
}
}
const isShowList = computed(() => {
if (!hasAnyPermission(['PROJECT_TEMPLATE:READ+ADD'])) {
return true;
}
if (isEnableOrdTemplate.value && route.query.type === 'BUG') {
return true;
}
return route.query.type !== 'BUG';
});
onMounted(() => {
fetchData();
updateColumns();

View File

@ -14,7 +14,7 @@
<TemplateItem
:card-item="item"
:index="index"
mode="organization"
mode="project"
@field-setting="fieldSetting"
@template-management="templateManagement"
@workflow-setup="workflowSetup"

View File

@ -238,10 +238,11 @@
getMemberList,
{
tableKey: TableKeyEnum.ORGANIZATION_MEMBER,
scroll: { x: 1800 },
scroll: { x: 1600 },
selectable: !!hasAnyPermission(['ORGANIZATION_MEMBER:READ+ADD', 'ORGANIZATION_MEMBER:READ+ADD']),
heightUsed: 288,
showSetting: true,
showJumpMethod: true,
size: 'default',
},
(record) => {

View File

@ -12,12 +12,7 @@
}}</span>
</template>
<div class="flex w-[100%] flex-row justify-between text-sm font-normal">
<div
v-for="(item, index) in cardContent"
:key="item.id"
class="item mt-4 p-[16px]"
:class="`ms-item-${index}`"
>
<div v-for="(item, index) in cardContent" :key="item.id" class="item mt-4" :class="`ms-item-${index}`">
<span class="mr-3">
<svg-icon width="64px" height="46px" :name="item.icon" />
</span>
@ -163,6 +158,7 @@
width: 100% !important;
}
.item {
padding: 16px;
width: calc(50% - 10px);
height: 78px;
border: 1px solid #ffffff;
@ -170,9 +166,11 @@
@apply flex items-center rounded-md;
}
.ms-item-0 {
background: url('@/assets/images/ms_plugindownload.jpg') no-repeat center / auto;
background: url('@/assets/images/ms_plugindownload.jpg') no-repeat center;
background-size: cover;
}
.ms-item-1 {
background: url('@/assets/images/ms_configplugin.jpg') no-repeat center / auto;
background: url('@/assets/images/ms_configplugin.jpg') no-repeat center;
background-size: cover;
}
</style>

View File

@ -56,7 +56,7 @@
@success="okHandler"
/>
<div>
<a-button class="mt-1 px-0" type="text" :disabled="totalData.length > 20" @click="createField">
<a-button class="mt-1 px-0" type="text" :disabled="totalData.length >= 20" @click="createField">
<template #icon>
<icon-plus class="text-[14px]" />
</template>

View File

@ -7,13 +7,7 @@
}}</a-alert>
<div class="mb-4 flex items-center justify-between">
<span v-if="isEnabledTemplate" class="font-medium">{{ t('system.orgTemplate.fieldList') }}</span>
<a-button
v-else
v-permission="props.createPermission"
type="primary"
:disabled="isDisabled"
@click="fieldHandler"
>
<a-button v-permission="props.createPermission" type="primary" :disabled="isDisabled" @click="fieldHandler">
{{ t('system.orgTemplate.addField') }}
</a-button>
<a-input-search
@ -274,7 +268,7 @@
};
const isDisabled = computed(() => {
return totalData.value.length > 20;
return totalData.value.length >= 20;
});
const tableRef = ref();

View File

@ -31,6 +31,7 @@
:placeholder="t('system.orgTemplate.templateNamePlaceholder')"
:max-length="255"
class="max-w-[732px]"
:disabled="templateForm?.internal"
></a-input>
</a-form-item>
<a-form-item field="remark" :label="t('system.orgTemplate.description')" asterisk-position="end">

View File

@ -25,13 +25,13 @@
<span v-if="props.cardItem.key === 'BUG'" class="operation hover:text-[rgb(var(--primary-5))]">
<span @click="workflowSetup">{{ t('system.orgTemplate.workflowSetup') }}</span>
<a-divider
v-if="isEnableProject && props.cardItem.key === 'BUG'"
v-if="hasEnablePermission && props.mode === 'organization' && isEnableProject"
v-permission="['ORGANIZATION_TEMPLATE:READ+ENABLE']"
direction="vertical"
/>
</span>
<span
v-if="isEnableProject && hasEnablePermission"
v-if="hasEnablePermission && props.mode === 'organization' && isEnableProject"
class="rounded p-[2px] hover:bg-[rgb(var(--primary-9))]"
>
<MsTableMoreAction :list="moreActions" @select="handleMoreActionSelect"

View File

@ -4,7 +4,12 @@
t('system.orgTemplate.enableTemplateTip')
}}</a-alert>
<div class="mb-4 flex items-center justify-between">
<span v-if="isEnableOrdTemplate" class="font-medium">{{ t('system.orgTemplate.templateList') }}</span>
<!-- <span v-if="isEnableOrdTemplate || route.query.type === 'BUG'" class="font-medium">{{
t('system.orgTemplate.templateList', { type: getTemplateName('organization', route.query.type as string) })
}}</span> -->
<span v-if="isShowListTip" class="font-medium">{{
t('system.orgTemplate.templateList', { type: getTemplateName('organization', route.query.type as string) })
}}</span>
<a-button
v-if="!isEnableOrdTemplate && route.query.type === 'BUG'"
v-permission="['ORGANIZATION_TEMPLATE:READ+ADD']"
@ -12,7 +17,11 @@
:disabled="false"
@click="createTemplate"
>
{{ t('system.orgTemplate.createTemplate') }}
{{
t('system.orgTemplate.createTemplateType', {
type: getTemplateName('organization', route.query.type as string),
})
}}
</a-button>
<a-input-search
v-model:model-value="keyword"
@ -38,9 +47,12 @@
<MsButton v-permission="['ORGANIZATION_TEMPLATE:READ+UPDATE']" @click="editTemplate(record.id)">{{
t('system.orgTemplate.edit')
}}</MsButton>
<MsButton v-permission="['ORGANIZATION_TEMPLATE:READ+ADD']" class="!mr-0" @click="copyTemplate(record.id)">{{
t('system.orgTemplate.copy')
}}</MsButton>
<MsButton
v-if="route.query.type === 'BUG' && hasAnyPermission(['ORGANIZATION_TEMPLATE:READ+ADD'])"
class="!mr-0"
@click="copyTemplate(record.id)"
>{{ t('system.orgTemplate.copy') }}</MsButton
>
<a-divider
v-if="!record.internal"
v-permission="['ORGANIZATION_TEMPLATE:READ+ADD']"
@ -89,6 +101,8 @@
import { SettingRouteEnum } from '@/enums/routeEnum';
import { TableKeyEnum } from '@/enums/tableEnum';
import { getTemplateName } from '@/views/setting/organization/template/components/fieldSetting';
const route = useRoute();
const { t } = useI18n();
const tableStore = useTableStore();
@ -145,10 +159,11 @@
const { propsRes, propsEvent, loadList, setLoadListParams, setProps } = useTable(getOrganizeTemplateList, {
tableKey: TableKeyEnum.ORGANIZATION_TEMPLATE_MANAGEMENT,
scroll: { x: '100%' },
columns: fieldColumns,
selectable: false,
noDisable: true,
size: 'default',
showSetting: true,
showSetting: false,
showPagination: false,
heightUsed: 380,
});
@ -279,11 +294,20 @@
}
}
const isShowListTip = computed(() => {
if (!hasAnyPermission(['ORGANIZATION_TEMPLATE:READ+ADD'])) {
return true;
}
if (isEnableOrdTemplate.value && route.query.type === 'BUG') {
return true;
}
return route.query.type !== 'BUG';
});
onMounted(() => {
fetchData();
updateColumns();
});
tableStore.initColumn(TableKeyEnum.ORGANIZATION_TEMPLATE_MANAGEMENT, fieldColumns, 'drawer');
</script>
<style scoped lang="less">

View File

@ -240,7 +240,7 @@
(val) => {
if (val) {
selectList.value = val as DefinedFieldItem[];
setProps({ data: selectList.value });
setProps({ data: val });
}
},
{ immediate: true }

View File

@ -69,7 +69,7 @@ export default {
'system.orgTemplate.defaultValue': 'Default value',
'system.orgTemplate.required': 'Required',
'system.orgTemplate.enableTemplateTip': 'The project template is enabled. The organization template is unavailable',
'system.orgTemplate.templateList': 'Template list',
'system.orgTemplate.templateList': ' {type} list',
'system.orgTemplate.createTemplate': 'Create',
'system.orgTemplate.templatePreview': 'Template preview',
'system.orgTemplate.templateName': 'Template name',

View File

@ -69,7 +69,7 @@ export default {
'system.orgTemplate.defaultValue': '默认值',
'system.orgTemplate.required': '是否必填',
'system.orgTemplate.enableTemplateTip': '已启用项目模板,组织模板不可操作',
'system.orgTemplate.templateList': '模板列表',
'system.orgTemplate.templateList': ' {type}列表',
'system.orgTemplate.createTemplate': '创建模板',
'system.orgTemplate.templatePreview': '模板预览',
'system.orgTemplate.templateName': '模板名称',

View File

@ -87,6 +87,7 @@
:auto-upload="false"
:disabled="confirmLoading"
:draggable="true"
:file-type-tip="t('system.plugin.supportFormatType')"
></MsUpload>
</div>
<template #footer>

View File

@ -111,4 +111,5 @@ export default {
'system.plugin.switchAllOrganizeTip': 'The plugin will be visible to all organizations',
'system.plugin.switchSectionOrganizeTip': 'Plug-in to specify organization is visible',
'system.plugin.changeOrganizeTip': 'Changing the organization will make historical data unavailable, so be careful!',
'system.plugin.supportFormatType': 'Only supports the JAR file format',
};

View File

@ -90,4 +90,5 @@ export default {
'system.plugin.switchAllOrganizeTip': '插件将对所有组织可见',
'system.plugin.switchSectionOrganizeTip': '插件将对指定组织可见',
'system.plugin.changeOrganizeTip': ' 变更组织会导致历史数据不可用,请谨慎操作!',
'system.plugin.supportFormatType': '仅支持JAR格式的文件',
};

View File

@ -0,0 +1,46 @@
<template>
<MsCard simple no-content-padding>
<TaskCenter group="system" />
</MsCard>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import MsCard from '@/components/pure/ms-card/index.vue';
import TaskCenter from '@/views/project-management/taskCenter/component/taskCom.vue';
</script>
<style scoped lang="less">
.box {
display: flex;
height: 100%;
.left {
padding: 24px;
width: 252px;
height: 100%;
border-right: 1px solid var(--color-text-n8);
.item {
padding: 0 20px;
height: 38px;
font-size: 14px;
line-height: 38px;
border-radius: 4px;
cursor: pointer;
&.active {
background: rgb(var(--primary-1));
}
}
}
.right {
width: calc(100% - 300px);
flex-grow: 1; /* 自适应 */
height: 100%;
}
}
.no-content {
:deep(.arco-tabs-content) {
padding-top: 0;
}
}
</style>