fix: 系统设置bug修复&用例管理bug修复&任务中心调整
This commit is contained in:
parent
47399e6ba5
commit
95c1ade326
Binary file not shown.
Before Width: | Height: | Size: 46 KiB After Width: | Height: | Size: 490 KiB |
|
@ -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) {
|
||||
|
|
|
@ -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}` });
|
||||
}
|
||||
|
||||
// 创建自定义字段(组织)
|
||||
|
|
|
@ -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';
|
||||
// 更新自定义字段
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -254,9 +254,9 @@ export interface DemandFormList {
|
|||
// 创建需求&编辑需求
|
||||
export interface CreateOrUpdateDemand {
|
||||
id?: string;
|
||||
caseId: string;
|
||||
demandPlatform: string;
|
||||
demandList?: DemandFormList[];
|
||||
caseId?: string;
|
||||
[key: string]: any;
|
||||
}
|
||||
// 转存文件
|
||||
|
|
|
@ -115,6 +115,7 @@ export interface ActionTemplateManage {
|
|||
customFields?: CustomField[];
|
||||
fieldType?: string;
|
||||
systemFields?: Record<string, any>[];
|
||||
internal?: boolean; // 是否为系统模板
|
||||
}
|
||||
|
||||
// 工作流列表字段
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
const { demandId, demandName, demandUrl } = modelForm.value;
|
||||
const params: CreateOrUpdateDemand = {
|
||||
...form.value,
|
||||
demandList: [{ demandId, demandName, demandUrl }],
|
||||
};
|
||||
emit('save', params, isContinue);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
@ -171,6 +154,10 @@
|
|||
updateName.value = val.demandName;
|
||||
}
|
||||
);
|
||||
|
||||
defineExpose({
|
||||
resetForm,
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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>
|
|
@ -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();
|
||||
emit('updateSuccess');
|
||||
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);
|
||||
}
|
||||
|
||||
// 更新文件
|
||||
|
|
|
@ -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',
|
||||
};
|
||||
|
|
|
@ -247,5 +247,5 @@ export default {
|
|||
'caseManagement.featureCase.defectSource': '缺陷来源',
|
||||
'caseManagement.featureCase.sortSuccess': '排序成功',
|
||||
'caseManagement.featureCase.zentao': '禅道',
|
||||
'caseManagement.featureCase.searchPlaceholder': '通过id或名称搜索',
|
||||
'caseManagement.featureCase.searchPlaceholder': '通过ID或名称搜索',
|
||||
};
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -205,6 +205,7 @@
|
|||
selectable: !!hasAnyPermission(['PROJECT_USER:READ+DELETE', 'ORGANIZATION_MEMBER:READ+UPDATE']),
|
||||
showSetting: true,
|
||||
heightUsed: 288,
|
||||
showJumpMethod: true,
|
||||
columns,
|
||||
scroll: {
|
||||
x: 1200,
|
||||
|
|
|
@ -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([
|
||||
|
|
|
@ -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">
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
<TemplateItem
|
||||
:card-item="item"
|
||||
:index="index"
|
||||
mode="organization"
|
||||
mode="project"
|
||||
@field-setting="fieldSetting"
|
||||
@template-management="templateManagement"
|
||||
@workflow-setup="workflowSetup"
|
||||
|
|
|
@ -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) => {
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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">
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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">
|
||||
|
|
|
@ -240,7 +240,7 @@
|
|||
(val) => {
|
||||
if (val) {
|
||||
selectList.value = val as DefinedFieldItem[];
|
||||
setProps({ data: selectList.value });
|
||||
setProps({ data: val });
|
||||
}
|
||||
},
|
||||
{ immediate: true }
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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': '模板名称',
|
||||
|
|
|
@ -87,6 +87,7 @@
|
|||
:auto-upload="false"
|
||||
:disabled="confirmLoading"
|
||||
:draggable="true"
|
||||
:file-type-tip="t('system.plugin.supportFormatType')"
|
||||
></MsUpload>
|
||||
</div>
|
||||
<template #footer>
|
||||
|
|
|
@ -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',
|
||||
};
|
||||
|
|
|
@ -90,4 +90,5 @@ export default {
|
|||
'system.plugin.switchAllOrganizeTip': '插件将对所有组织可见',
|
||||
'system.plugin.switchSectionOrganizeTip': '插件将对指定组织可见',
|
||||
'system.plugin.changeOrganizeTip': ' 变更组织会导致历史数据不可用,请谨慎操作!',
|
||||
'system.plugin.supportFormatType': '仅支持JAR格式的文件',
|
||||
};
|
||||
|
|
|
@ -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>
|
Loading…
Reference in New Issue