fix: 修改全局bugs_Global

This commit is contained in:
xinxin.wu 2024-04-18 20:54:34 +08:00 committed by Craftsman
parent cc340ce8c5
commit 6902b785e6
28 changed files with 248 additions and 78 deletions

View File

@ -35,7 +35,7 @@ export function addProjectUserGroup(data: ActionProjectMember) {
} }
// 批量移除项目成员 // 批量移除项目成员
export function batchRemoveMember(data: ActionProjectMember) { export function batchRemoveMember(data: TableQueryParams) {
return MSR.post({ url: BatchRemoveMemberUrl, data }); return MSR.post({ url: BatchRemoveMemberUrl, data });
} }

View File

@ -102,3 +102,25 @@ body {
border: 0.5px solid var(--color-text-input-border); /* 设置近似 0.5px 的边框 */ border: 0.5px solid var(--color-text-input-border); /* 设置近似 0.5px 的边框 */
border-radius: 4px; border-radius: 4px;
} }
.markdown-body ol {
list-style: decimal !important;
}
.markdown-body ul {
list-style: disc !important;
}
.markdown-body ul li[data-type='taskItem'] {
height: 24px;
line-height: 24px;
list-style: none !important;
@apply my-6 flex items-center;
label {
margin-right: 4px;
@apply flex items-center;
}
> div {
@apply flex items-center;
> p {
margin-bottom: 0;
}
}
}

View File

@ -11,7 +11,7 @@
<template #title> <template #title>
{{ batchTitle }} {{ batchTitle }}
<div class="text-[var(--color-text-4)]"> <div class="text-[var(--color-text-4)]">
{{ t('msBatchModal.batchModalSubTitle', { count: (props.selectData || []).length }) }} {{ t('msBatchModal.batchModalSubTitle', { count: props.currentSelectCount }) }}
</div> </div>
</template> </template>
<a-spin :loading="loading" class="w-full"> <a-spin :loading="loading" class="w-full">
@ -63,7 +63,7 @@
defineProps<{ defineProps<{
visible: boolean; visible: boolean;
action: string; action: string;
selectData: string[] | undefined; currentSelectCount: number | undefined;
}>(), }>(),
{ {
visible: false, visible: false,

View File

@ -447,6 +447,9 @@
keyword: keyword.value, keyword: keyword.value,
projectId: innerProject.value, projectId: innerProject.value,
excludeIds: [...props.associatedIds], // id excludeIds: [...props.associatedIds], // id
condition: {
keyword: keyword.value,
},
}); });
if (props.hasNotAssociatedIds && props.hasNotAssociatedIds.length > 0) { if (props.hasNotAssociatedIds && props.hasNotAssociatedIds.length > 0) {
props.hasNotAssociatedIds.forEach((hasNotAssociatedId) => { props.hasNotAssociatedIds.forEach((hasNotAssociatedId) => {

View File

@ -176,7 +176,8 @@
Object.keys(config).forEach((key) => { Object.keys(config).forEach((key) => {
const value = res[configKey][key]; const value = res[configKey][key];
config[key] = value || config[key]; config[key] = value || config[key];
dynamicForm.value[configKey].status = value !== undefined ? 1 : 0; // @desc
dynamicForm.value[configKey].status = value ? 1 : 0;
}); });
}); });
} }

View File

@ -1,5 +1,12 @@
<template> <template>
<MsDrawer v-model:visible="innerVisible" :title="t('ms.personal')" :width="960" :footer="false" no-content-padding> <MsDrawer
v-model:visible="innerVisible"
:title="t('ms.personal')"
:width="960"
:footer="false"
unmount-on-close
no-content-padding
>
<div class="flex h-full w-full"> <div class="flex h-full w-full">
<div class="h-full w-[208px] bg-[var(--color-text-n9)]"> <div class="h-full w-[208px] bg-[var(--color-text-n9)]">
<MsMenuPanel <MsMenuPanel

View File

@ -180,7 +180,12 @@
ExtensionHistory, ExtensionHistory,
ExtensionHorizontalRule, ExtensionHorizontalRule,
ExtensionItalic, ExtensionItalic,
ExtensionOrderedList, // ExtensionOrderedList,
ExtensionOrderedList.configure({
HTMLAttributes: {
class: 'my-custom-class',
},
}),
ExtensionStrike, ExtensionStrike,
ExtensionText, ExtensionText,
ExtensionImage.configure({ ExtensionImage.configure({

View File

@ -41,7 +41,7 @@
:sql-code-editor-height="props.sqlCodeEditorHeight" :sql-code-editor-height="props.sqlCodeEditorHeight"
@copy="copyListItem" @copy="copyListItem"
@delete="deleteListItem" @delete="deleteListItem"
@change="emit('change')" @change="changeHandler"
/> />
</div> </div>
</template> </template>
@ -244,6 +244,10 @@
} }
}); });
function changeHandler() {
emit('change');
}
defineExpose({ defineExpose({
activeItemId, activeItemId,
}); });

View File

@ -33,7 +33,7 @@
{{ `${t('apiTestDebug.wait')}${item.delay}` }} ms {{ `${t('apiTestDebug.wait')}${item.delay}` }} ms
</div> </div>
<div v-else class="flex min-w-[42px] items-center justify-between"> <div v-else class="flex min-w-[42px] items-center justify-between">
<div class="one-line-text"> {{ t(conditionTypeNameMap[item.processorType]) }}</div> <div class="one-line-text"> {{ item.name || t(conditionTypeNameMap[item.processorType]) }}</div>
<a-badge <a-badge
v-if="item.processorType === RequestConditionProcessor.REQUEST_SCRIPT" v-if="item.processorType === RequestConditionProcessor.REQUEST_SCRIPT"
class="ml-1 mt-[2px] min-w-[48px]" class="ml-1 mt-[2px] min-w-[48px]"

View File

@ -352,6 +352,7 @@
import useModal from '@/hooks/useModal'; import useModal from '@/hooks/useModal';
import useTableStore from '@/hooks/useTableStore'; import useTableStore from '@/hooks/useTableStore';
import useAppStore from '@/store/modules/app'; import useAppStore from '@/store/modules/app';
import { characterLimit } from '@/utils';
import { hasAnyPermission } from '@/utils/permission'; import { hasAnyPermission } from '@/utils/permission';
import { ApiDefinitionDetail } from '@/models/apiTest/management'; import { ApiDefinitionDetail } from '@/models/apiTest/management';
@ -664,7 +665,7 @@
* 删除接口 * 删除接口
*/ */
function deleteApi(record?: ApiDefinitionDetail, isBatch?: boolean, params?: BatchActionQueryParams) { function deleteApi(record?: ApiDefinitionDetail, isBatch?: boolean, params?: BatchActionQueryParams) {
let title = t('apiTestManagement.deleteApiTipTitle', { name: record?.name }); let title = t('apiTestManagement.deleteApiTipTitle', { name: characterLimit(record?.name) });
let selectIds = [record?.id || '']; let selectIds = [record?.id || ''];
if (isBatch) { if (isBatch) {
title = t('apiTestManagement.batchDeleteApiTip', { title = t('apiTestManagement.batchDeleteApiTip', {

View File

@ -408,6 +408,7 @@
import useModal from '@/hooks/useModal'; import useModal from '@/hooks/useModal';
import useTableStore from '@/hooks/useTableStore'; import useTableStore from '@/hooks/useTableStore';
import useAppStore from '@/store/modules/app'; import useAppStore from '@/store/modules/app';
import { characterLimit } from '@/utils';
import { hasAnyPermission } from '@/utils/permission'; import { hasAnyPermission } from '@/utils/permission';
import { ApiCaseDetail } from '@/models/apiTest/management'; import { ApiCaseDetail } from '@/models/apiTest/management';
@ -788,7 +789,7 @@
? t('case.batchDeleteCaseTip', { ? t('case.batchDeleteCaseTip', {
count: batchParams.value.currentSelectCount || tableSelected.value.length, count: batchParams.value.currentSelectCount || tableSelected.value.length,
}) })
: t('apiTestManagement.deleteApiTipTitle', { name: record?.name }); : t('apiTestManagement.deleteApiTipTitle', { name: characterLimit(record?.name) });
openModal({ openModal({
type: 'error', type: 'error',

View File

@ -104,7 +104,14 @@
'bg-white', 'bg-white',
]" ]"
> >
<MsSplitBox expand-direction="right" :max="0.7" :min="0.7" :size="900" direction="horizontal"> <MsSplitBox
expand-direction="right"
:size="0.8"
:max="0.7"
:min="0.6"
direction="horizontal"
:class="{ 'left-bug-detail': activeTab === 'comment' }"
>
<template #first> <template #first>
<div class="leftWrapper h-full"> <div class="leftWrapper h-full">
<a-spin :loading="detailLoading" class="w-full"> <a-spin :loading="detailLoading" class="w-full">

View File

@ -79,6 +79,7 @@
batchParams: BatchActionQueryParams; batchParams: BatchActionQueryParams;
activeFolder: string; activeFolder: string;
offspringIds: string[]; offspringIds: string[];
condition?: TableQueryParams;
}>(); }>();
const emits = defineEmits<{ const emits = defineEmits<{
@ -186,6 +187,9 @@
tags: form.value.tags, tags: form.value.tags,
moduleIds: props.activeFolder === 'all' ? [] : [props.activeFolder, ...props.offspringIds], moduleIds: props.activeFolder === 'all' ? [] : [props.activeFolder, ...props.offspringIds],
customField: form.value.selectedAttrsId === 'systemTags' ? {} : customField, customField: form.value.selectedAttrsId === 'systemTags' ? {} : customField,
condition: {
...props.condition,
},
}; };
await batchEditAttrs(params); await batchEditAttrs(params);
Message.success(t('caseManagement.featureCase.editSuccess')); Message.success(t('caseManagement.featureCase.editSuccess'));

View File

@ -92,7 +92,7 @@
ref="wrapperRef" ref="wrapperRef"
:class="[`${!commentInputIsActive ? 'h-[calc(100%-72px)]' : 'h-[calc(100%-286px)]'}`, 'bg-white']" :class="[`${!commentInputIsActive ? 'h-[calc(100%-72px)]' : 'h-[calc(100%-286px)]'}`, 'bg-white']"
> >
<MsSplitBox :size="900" :max="0.7" :min="0.5" direction="horizontal" expand-direction="right"> <MsSplitBox :size="0.8" :max="0.7" :min="0.6" direction="horizontal" expand-direction="right">
<template #first> <template #first>
<div class="leftWrapper h-full"> <div class="leftWrapper h-full">
<div class="header h-[50px]"> <div class="header h-[50px]">

View File

@ -352,9 +352,10 @@
v-if="showBatchMoveDrawer" v-if="showBatchMoveDrawer"
ref="caseTreeRef" ref="caseTreeRef"
v-model:selected-keys="selectedModuleKeys" v-model:selected-keys="selectedModuleKeys"
v-model:group-keyword="groupKeyword"
:active-folder="props.activeFolder" :active-folder="props.activeFolder"
:is-expand-all="true" :is-expand-all="true"
is-modal :is-modal="true"
@case-node-select="caseNodeSelect" @case-node-select="caseNodeSelect"
></FeatureCaseTree> ></FeatureCaseTree>
</a-modal> </a-modal>
@ -364,6 +365,7 @@
:batch-params="batchParams" :batch-params="batchParams"
:active-folder="props.activeFolder" :active-folder="props.activeFolder"
:offspring-ids="props.offspringIds" :offspring-ids="props.offspringIds"
:condition="conditionParams"
@success="successHandler" @success="successHandler"
/> />
<CaseDetailDrawer <CaseDetailDrawer
@ -479,6 +481,7 @@
const keyword = ref<string>(''); const keyword = ref<string>('');
const filterRowCount = ref(0); const filterRowCount = ref(0);
const groupKeyword = ref<string>('');
const showType = ref<string>('list'); const showType = ref<string>('list');
@ -934,6 +937,12 @@
const caseFilters = ref<string[]>([]); const caseFilters = ref<string[]>([]);
const executeResultFilters = ref<string[]>([]); const executeResultFilters = ref<string[]>([]);
const conditionParams = ref({
keyword: '',
filter: {},
combine: {},
});
async function initTableParams() { async function initTableParams() {
let moduleIds: string[] = []; let moduleIds: string[] = [];
if (props.activeFolder && props.activeFolder !== 'all') { if (props.activeFolder && props.activeFolder !== 'all') {
@ -943,11 +952,18 @@
moduleIds = [...featureCaseStore.moduleId, ...props.offspringIds]; moduleIds = [...featureCaseStore.moduleId, ...props.offspringIds];
} }
} }
conditionParams.value = {
keyword: keyword.value,
filter: propsRes.value.filter,
combine: batchParams.value.condition,
};
return { return {
keyword: keyword.value,
moduleIds, moduleIds,
projectId: currentProjectId.value, projectId: currentProjectId.value,
excludeIds: batchParams.value.excludeIds,
selectAll: batchParams.value.selectAll,
selectIds: batchParams.value.selectedIds as string[],
filter: { filter: {
reviewStatus: statusFilters.value, reviewStatus: statusFilters.value,
caseLevel: caseFilters.value, caseLevel: caseFilters.value,

View File

@ -1,10 +1,18 @@
<template> <template>
<a-spin class="min-h-[400px] w-full" :loading="loading"> <a-spin class="min-h-[400px] w-full" :loading="loading">
<a-input
v-if="props.isModal"
v-model:model-value="moduleKeyword"
:placeholder="t('caseManagement.caseReview.folderSearchPlaceholder')"
allow-clear
class="mb-[16px]"
:max-length="255"
/>
<MsTree <MsTree
v-model:focus-node-key="focusNodeKey" v-model:focus-node-key="focusNodeKey"
:selected-keys="props.selectedKeys" :selected-keys="props.selectedKeys"
:data="caseTree" :data="caseTree"
:keyword="props.groupKeyword" :keyword="moduleKeyword"
:node-more-actions="caseMoreActions" :node-more-actions="caseMoreActions"
:expand-all="props.isExpandAll" :expand-all="props.isExpandAll"
:empty-text="t('common.noData')" :empty-text="t('common.noData')"
@ -69,6 +77,7 @@
<script setup lang="ts"> <script setup lang="ts">
import { computed, ref, watch } from 'vue'; import { computed, ref, watch } from 'vue';
import { useVModel } from '@vueuse/core';
import { Message } from '@arco-design/web-vue'; import { Message } from '@arco-design/web-vue';
import MsButton from '@/components/pure/ms-button/index.vue'; import MsButton from '@/components/pure/ms-button/index.vue';
@ -84,6 +93,7 @@
moveCaseModuleTree, moveCaseModuleTree,
updateCaseModuleTree, updateCaseModuleTree,
} from '@/api/modules/case-management/featureCase'; } from '@/api/modules/case-management/featureCase';
import { ProjectMemberOptions } from '@/api/requrls/project-management/projectMember';
import { useI18n } from '@/hooks/useI18n'; import { useI18n } from '@/hooks/useI18n';
import useModal from '@/hooks/useModal'; import useModal from '@/hooks/useModal';
import useAppStore from '@/store/modules/app'; import useAppStore from '@/store/modules/app';
@ -108,15 +118,17 @@
isExpandAll: boolean; // isExpandAll: boolean; //
allNames?: string[]; // name allNames?: string[]; // name
modulesCount?: Record<string, number>; // modulesCount?: Record<string, number>; //
groupKeyword?: string; // groupKeyword: string; //
}>(); }>();
const emits = defineEmits(['update:selectedKeys', 'caseNodeSelect', 'init', 'dragUpdate']); const emits = defineEmits(['update:selectedKeys', 'caseNodeSelect', 'init', 'dragUpdate', 'update:groupKeyword']);
const currentProjectId = computed(() => appStore.currentProjectId); const currentProjectId = computed(() => appStore.currentProjectId);
const caseTree = ref<ModuleTreeNode[]>([]); const caseTree = ref<ModuleTreeNode[]>([]);
const moduleKeyword = useVModel(props, 'groupKeyword', emits);
const setFocusKey = (node: MsTreeNodeData) => { const setFocusKey = (node: MsTreeNodeData) => {
focusNodeKey.value = node.id || ''; focusNodeKey.value = node.id || '';
}; };
@ -160,7 +172,7 @@
caseTree.value = mapTree<ModuleTreeNode>(res, (e) => { caseTree.value = mapTree<ModuleTreeNode>(res, (e) => {
return { return {
...e, ...e,
hideMoreAction: e.id === 'root', hideMoreAction: e.id === 'root' || props.isModal,
draggable: e.id !== 'root' && !props.isModal, draggable: e.id !== 'root' && !props.isModal,
disabled: e.id === props.activeFolder && props.isModal, disabled: e.id === props.activeFolder && props.isModal,
count: props.modulesCount?.[e.id] || 0, count: props.modulesCount?.[e.id] || 0,
@ -345,7 +357,7 @@
}; };
} }
return { return {
height: 'calc(100vh - 335px)', height: 'calc(100vh - 294px)',
threshold: 200, threshold: 200,
fixedSize: true, fixedSize: true,
buffer: 15, buffer: 15,
@ -370,6 +382,7 @@
caseTree.value = mapTree<ModuleTreeNode>(caseTree.value, (node) => { caseTree.value = mapTree<ModuleTreeNode>(caseTree.value, (node) => {
return { return {
...node, ...node,
hideMoreAction: props.isModal,
count: obj?.[node.id] || 0, count: obj?.[node.id] || 0,
}; };
}); });

View File

@ -13,7 +13,7 @@
@confirm="handleDrawerConfirm" @confirm="handleDrawerConfirm"
@cancel="handleDrawerCancel" @cancel="handleDrawerCancel"
> >
<div class="flex items-center justify-between"> <div class="mb-4 flex items-center justify-between">
<div class="font-medium">{{ t('caseManagement.featureCase.defectList') }}</div> <div class="font-medium">{{ t('caseManagement.featureCase.defectList') }}</div>
<div> <div>
<a-input-search <a-input-search
@ -185,6 +185,7 @@
searchMode: 'AND', searchMode: 'AND',
combine: {}, combine: {},
caseId: props.caseId, caseId: props.caseId,
condition: { keyword: keyword.value },
}; };
showDrawer.value = false; showDrawer.value = false;
emit('save', params); emit('save', params);
@ -207,8 +208,8 @@
() => props.visible, () => props.visible,
(val) => { (val) => {
if (val) { if (val) {
getFetch();
resetSelector(); resetSelector();
getFetch();
} }
} }
); );

View File

@ -214,6 +214,9 @@
sourceId: props.caseId, sourceId: props.caseId,
projectId: currentProjectId.value, projectId: currentProjectId.value,
sourceType: currentSelectCase.value, sourceType: currentSelectCase.value,
condition: {
keyword: keyword.value,
},
}); });
await loadList(); await loadList();
featureCaseStore.getCaseCounts(props.caseId); featureCaseStore.getCaseCounts(props.caseId);

View File

@ -63,13 +63,14 @@
<div class="text-[var(--color-text-4)]">({{ modulesCount[activeFolder] }})</div> <div class="text-[var(--color-text-4)]">({{ modulesCount[activeFolder] }})</div>
</div> </div>
<div class="flex items-center gap-[8px]"> <div class="flex items-center gap-[8px]">
<a-select <!-- TODO这个版本不做 -->
<!-- <a-select
v-model:model-value="version" v-model:model-value="version"
:options="versionOptions" :options="versionOptions"
:placeholder="t('ms.case.associate.versionPlaceholder')" :placeholder="t('ms.case.associate.versionPlaceholder')"
class="w-[200px]" class="w-[200px]"
allow-clear allow-clear
/> /> -->
<a-input-search <a-input-search
v-model="keyword" v-model="keyword"
:placeholder="t('ms.case.associate.searchPlaceholder')" :placeholder="t('ms.case.associate.searchPlaceholder')"
@ -78,10 +79,11 @@
@press-enter="searchCase" @press-enter="searchCase"
@search="searchCase" @search="searchCase"
/> />
<a-button type="outline" class="arco-btn-outline--secondary px-[8px]"> <!-- TODO这个版本不做 -->
<!-- <a-button type="outline" class="arco-btn-outline--secondary px-[8px]">
<MsIcon type="icon-icon-filter" class="mr-[4px] text-[var(--color-text-4)]" /> <MsIcon type="icon-icon-filter" class="mr-[4px] text-[var(--color-text-4)]" />
<div class="text-[var(--color-text-4)]">{{ t('common.filter') }}</div> <div class="text-[var(--color-text-4)]">{{ t('common.filter') }}</div>
</a-button> </a-button> -->
</div> </div>
</div> </div>
<ms-base-table v-bind="propsRes" no-disable v-on="propsEvent"> <ms-base-table v-bind="propsRes" no-disable v-on="propsEvent">
@ -140,6 +142,7 @@
import { ref } from 'vue'; import { ref } from 'vue';
import { useRouter } from 'vue-router'; import { useRouter } from 'vue-router';
import { Message } from '@arco-design/web-vue'; import { Message } from '@arco-design/web-vue';
import { filter } from 'lodash-es';
import MsButton from '@/components/pure/ms-button/index.vue'; import MsButton from '@/components/pure/ms-button/index.vue';
import MsDrawer from '@/components/pure/ms-drawer/index.vue'; import MsDrawer from '@/components/pure/ms-drawer/index.vue';
@ -151,6 +154,7 @@
import MsTree from '@/components/business/ms-tree/index.vue'; import MsTree from '@/components/business/ms-tree/index.vue';
import type { MsTreeNodeData } from '@/components/business/ms-tree/types'; import type { MsTreeNodeData } from '@/components/business/ms-tree/types';
import TableFilter from '../../tableFilter.vue'; import TableFilter from '../../tableFilter.vue';
import conditionStatus from '@/views/api-test/report/component/conditionStatus.vue';
import { import {
addPrepositionRelation, addPrepositionRelation,
@ -401,6 +405,13 @@
filter: { filter: {
caseLevel: caseFilters.value, caseLevel: caseFilters.value,
}, },
condition: {
keyword: keyword.value,
filter: {
caseLevel: caseFilters.value,
...propsRes.value.filter,
},
},
}); });
} }
@ -414,6 +425,13 @@
current: propsRes.value.msPagination?.current, current: propsRes.value.msPagination?.current,
pageSize: propsRes.value.msPagination?.pageSize, pageSize: propsRes.value.msPagination?.pageSize,
excludeIds, excludeIds,
condition: {
keyword: keyword.value,
filter: {
caseLevel: caseFilters.value,
...propsRes.value.filter,
},
},
}; };
modulesCount.value = await getCaseModulesCounts(emitTableParams); modulesCount.value = await getCaseModulesCounts(emitTableParams);
} catch (error) { } catch (error) {
@ -449,13 +467,16 @@
const params = { const params = {
id: props.caseId, id: props.caseId,
excludeIds: [...excludeKeys], excludeIds: [...excludeKeys],
selectIds: selectorStatus === 'all' ? [] : [...selectedKeys], selectIds: [...selectedKeys] || [],
selectAll: selectorStatus === 'all', selectAll: selectorStatus === 'all',
moduleIds, moduleIds,
versionId, versionId,
refId: '', refId: '',
type: props.showType === 'preposition' ? 'PRE' : 'POST', type: props.showType === 'preposition' ? 'PRE' : 'POST',
projectId: currentProjectId.value, projectId: currentProjectId.value,
condition: {
keyword: keyword.value,
},
}; };
await addPrepositionRelation(params); await addPrepositionRelation(params);
Message.success(t('common.addSuccess')); Message.success(t('common.addSuccess'));

View File

@ -33,7 +33,7 @@
<div <div
v-else v-else
v-dompurify-html="detailForm?.prerequisite || '-'" v-dompurify-html="detailForm?.prerequisite || '-'"
class="markdown-body !break-words break-all" class="markdown-body list-item-css !break-words break-all"
></div> ></div>
</a-form-item> </a-form-item>
<a-form-item <a-form-item

View File

@ -65,11 +65,12 @@
<FeatureCaseTree <FeatureCaseTree
ref="caseTreeRef" ref="caseTreeRef"
v-model:selected-keys="selectedKeys" v-model:selected-keys="selectedKeys"
v-model:group-keyword="groupKeyword"
:all-names="rootModulesName" :all-names="rootModulesName"
:active-folder="activeFolder" :active-folder="activeFolder"
:is-expand-all="isExpandAll" :is-expand-all="isExpandAll"
:modules-count="modulesCount" :modules-count="modulesCount"
:group-keyword="groupKeyword" :is-modal="false"
@case-node-select="caseNodeSelect" @case-node-select="caseNodeSelect"
@init="setRootModules" @init="setRootModules"
@drag-update="dragUpdate" @drag-update="dragUpdate"

View File

@ -5,7 +5,7 @@
position="bottom" position="bottom"
class="ms-pop-confirm--hidden-icon" class="ms-pop-confirm--hidden-icon"
:ok-loading="loading" :ok-loading="loading"
:on-before-ok="handleBeforeOk" :on-before-ok="beforeConfirm"
:cancel-button-props="{ disabled: loading }" :cancel-button-props="{ disabled: loading }"
@popup-visible-change="reset" @popup-visible-change="reset"
> >
@ -13,21 +13,19 @@
<div class="mb-[8px] text-[14px] font-medium text-[var(--color-text-1)]">{{ <div class="mb-[8px] text-[14px] font-medium text-[var(--color-text-1)]">{{
props.id ? t('system.userGroup.rename') : t('system.userGroup.createUserGroup') props.id ? t('system.userGroup.rename') : t('system.userGroup.createUserGroup')
}}</div> }}</div>
<div v-outer="handleOutsideClick"> <a-form ref="formRef" :model="form" layout="vertical">
<a-form ref="formRef" :model="form" layout="vertical"> <a-form-item class="hidden-item" field="name" :rules="[{ validator: validateName }]">
<a-form-item class="hidden-item" field="name" :rules="[{ validator: validateName }]"> <a-input
<a-input v-model="form.name"
v-model="form.name" class="w-[245px]"
class="w-[245px]" :placeholder="t('system.userGroup.searchHolder')"
:placeholder="t('system.userGroup.searchHolder')" allow-clear
allow-clear :max-length="255"
:max-length="255" @press-enter="handleBeforeOk(undefined)"
@press-enter="handleBeforeOk(undefined)" @keyup.esc="handleCancel"
@keyup.esc="handleCancel" />
/> </a-form-item>
</a-form-item> </a-form>
</a-form>
</div>
</template> </template>
<slot></slot> <slot></slot>
</a-popconfirm> </a-popconfirm>
@ -139,16 +137,61 @@
}); });
}; };
function beforeConfirm(done?: (closed: boolean) => void) {
if (loading.value) return;
formRef.value?.validate(async (errors) => {
if (!errors) {
try {
loading.value = true;
if (props.type === EnvAuthScopeEnum.PROJECT) {
await updateOrAddEnv({ fileList: [], request: { ...store.currentEnvDetailInfo, name: form.name } });
} else {
const id = store.currentGroupId === NEW_ENV_GROUP ? undefined : store.currentGroupId;
if (id) {
const detail: Record<string, any> = await getGroupDetailEnv(id);
const envGroupProject = detail?.environmentGroupInfo.filter(
(item: any) => item.projectId && item.environmentId
);
const params = {
id,
name: form.name,
description: detail.description,
projectId: appStore.currentProjectId,
envGroupProject,
};
await groupUpdateEnv(params);
}
}
Message.success(t('project.fileManagement.renameSuccess'));
emit('success');
handleCancel();
if (done) {
done(true);
} else {
currentVisible.value = false;
}
} catch (error) {
// eslint-disable-next-line no-console
console.log(error);
if (done) {
done(false);
}
} finally {
loading.value = false;
}
} else if (done) {
done(false);
}
});
}
watchEffect(() => { watchEffect(() => {
currentVisible.value = props.visible; currentVisible.value = props.visible;
form.name = props.defaultName || ''; form.name = props.defaultName || '';
}); });
const handleOutsideClick = () => {
if (currentVisible.value) {
handleCancel();
}
};
function reset(val: boolean) { function reset(val: boolean) {
if (!val) { if (!val) {
form.name = ''; form.name = '';

View File

@ -1,5 +1,5 @@
<template> <template>
<div v-if="showTitle" class="title"> <div v-if="!getIsVisited()" class="title">
<span class="text-[var(--color-text-1)]">{{ t('project.environmental.httpTitle') }}</span> <span class="text-[var(--color-text-1)]">{{ t('project.environmental.httpTitle') }}</span>
<span class="cursor-pointer text-[var(--color-text-2)]" @click="handleNoWarning">{{ <span class="cursor-pointer text-[var(--color-text-2)]" @click="handleNoWarning">{{
t('project.environmental.httpNoWarning') t('project.environmental.httpNoWarning')
@ -115,6 +115,7 @@
import { getEnvModules } from '@/api/modules/api-test/management'; import { getEnvModules } from '@/api/modules/api-test/management';
import { useI18n } from '@/hooks/useI18n'; import { useI18n } from '@/hooks/useI18n';
import useVisit from '@/hooks/useVisit';
import { useAppStore, useTableStore } from '@/store'; import { useAppStore, useTableStore } from '@/store';
import useProjectEnvStore from '@/store/modules/setting/useProjectEnvStore'; import useProjectEnvStore from '@/store/modules/setting/useProjectEnvStore';
import { findNodeNames } from '@/utils'; import { findNodeNames } from '@/utils';
@ -128,10 +129,10 @@
const appStore = useAppStore(); const appStore = useAppStore();
const { t } = useI18n(); const { t } = useI18n();
const visitedKey = 'notRemindHttp';
const { addVisited, getIsVisited } = useVisit(visitedKey);
const store = useProjectEnvStore(); const store = useProjectEnvStore();
const showTitle = computed(() => store.httpNoWarning);
const tableStore = useTableStore(); const tableStore = useTableStore();
const addVisible = ref(false); const addVisible = ref(false);
const columns: MsTableColumn = [ const columns: MsTableColumn = [
@ -229,8 +230,9 @@
isCopy.value = false; isCopy.value = false;
addVisible.value = true; addVisible.value = true;
}; };
const handleNoWarning = () => { const handleNoWarning = () => {
store.setHttpNoWarning(false); addVisited();
}; };
watch( watch(

View File

@ -86,7 +86,7 @@
ref="batchModalRef" ref="batchModalRef"
v-model:visible="batchVisible" v-model:visible="batchVisible"
:action="batchAction" :action="batchAction"
:select-data="selectData" :current-select-count="batchParams.currentSelectCount"
@add-user-group="addUserGroup" @add-user-group="addUserGroup"
/> />
</template> </template>
@ -117,6 +117,7 @@
import { characterLimit, formatPhoneNumber } from '@/utils'; import { characterLimit, formatPhoneNumber } from '@/utils';
import { hasAnyPermission } from '@/utils/permission'; import { hasAnyPermission } from '@/utils/permission';
import type { TableQueryParams } from '@/models/common';
import { import {
ActionProjectMember, ActionProjectMember,
ProjectMemberItem, ProjectMemberItem,
@ -254,13 +255,20 @@
}; };
// //
const selectData = ref<string[] | undefined>([]); // const selectData = ref<string[] | undefined>([]);
const batchParams = ref<BatchActionQueryParams>({
selectedIds: [],
selectAll: false,
excludeIds: [],
currentSelectCount: 0,
});
// //
const batchRemoveHandler = () => { const batchRemoveHandler = () => {
const { selectedIds, excludeIds, selectAll } = batchParams.value;
openModal({ openModal({
type: 'error', type: 'error',
title: t('project.member.batchRemoveTip', { number: (selectData.value || []).length }), title: t('project.member.batchRemoveTip', { number: batchParams.value.currentSelectCount }),
content: t('project.member.batchRemoveContent'), content: t('project.member.batchRemoveContent'),
okText: t('project.member.deleteMemberConfirm'), okText: t('project.member.deleteMemberConfirm'),
cancelText: t('project.member.Cancel'), cancelText: t('project.member.Cancel'),
@ -269,9 +277,20 @@
}, },
onBeforeOk: async () => { onBeforeOk: async () => {
try { try {
const params: ActionProjectMember = { const params: TableQueryParams = {
selectAll: !!selectAll,
excludeIds: excludeIds || [],
selectIds: selectedIds || [],
projectId: lastProjectId.value, projectId: lastProjectId.value,
userIds: selectData.value, keyword: keyword.value,
condition: {
keyword: keyword.value,
filter: {
...propsRes.value.filter,
roleIds: roleIds.value ? [roleIds.value] : [],
},
combine: batchParams.value.condition,
},
}; };
await batchRemoveMember(params); await batchRemoveMember(params);
Message.success(t('project.member.deleteMemberSuccess')); Message.success(t('project.member.deleteMemberSuccess'));
@ -308,27 +327,22 @@
const batchVisible = ref<boolean>(false); const batchVisible = ref<boolean>(false);
const batchAction = ref(''); const batchAction = ref('');
const batchModalRef = ref(); const batchModalRef = ref();
const batchParams = ref<BatchActionQueryParams>({
selectedIds: [],
selectAll: false,
excludeIds: [],
currentSelectCount: 0,
});
// //
const addUserGroup = async (target: string[]) => { const addUserGroup = async (target: string[]) => {
const { selectedIds, excludeIds, selectAll } = batchParams.value; const { selectedIds, excludeIds, selectAll } = batchParams.value;
const params = { const params = {
projectId: lastProjectId.value, projectId: lastProjectId.value,
userIds: selectData.value, userIds: batchParams.value.selectedIds || [],
roleIds: target,
selectAll: !!selectAll, selectAll: !!selectAll,
excludeIds: excludeIds || [], excludeIds: excludeIds || [],
selectIds: selectedIds || [], selectIds: selectedIds || [],
keyword: keyword.value, roleIds: roleIds.value ? [roleIds.value] : [],
condition: { condition: {
keyword: keyword.value, keyword: keyword.value,
filter: propsRes.value.filter, filter: {
...propsRes.value.filter,
roleIds: roleIds.value ? [roleIds.value] : [],
},
combine: batchParams.value.condition, combine: batchParams.value.condition,
}, },
}; };
@ -345,7 +359,6 @@
// //
const handleTableBatch = (event: BatchActionParams, params: BatchActionQueryParams) => { const handleTableBatch = (event: BatchActionParams, params: BatchActionQueryParams) => {
batchParams.value = params; batchParams.value = params;
selectData.value = params.selectedIds;
if (event.eventTag === 'batchActionRemove') { if (event.eventTag === 'batchActionRemove') {
batchRemoveHandler(); batchRemoveHandler();
} }

View File

@ -109,7 +109,7 @@
ref="batchModalRef" ref="batchModalRef"
v-model:visible="showBatchModal" v-model:visible="showBatchModal"
:action="batchAction" :action="batchAction"
:select-data="selectedData" :current-select-count="batchParams.currentSelectCount"
@add-project="addProjectOrAddUserGroup" @add-project="addProjectOrAddUserGroup"
@add-user-group="addProjectOrAddUserGroup" @add-user-group="addProjectOrAddUserGroup"
/> />

View File

@ -5,9 +5,7 @@
<a-alert :closable="true" class="mb-4"> <a-alert :closable="true" class="mb-4">
<div> <div>
{{ t('system.plugin.alertDescribe') }} {{ t('system.plugin.alertDescribe') }}
<a class="mx-1" href="javascript:;">{{ t('system.plugin.viewTable') }}</a <span class="mx-1 text-[rgb(var(--primary-5))]" @click="openLink">{{ t('system.plugin.viewTable') }}</span>
>{{ t('system.plugin.downAddress') }}
<a class="mx-1" href="https://github.com/metersphere" target="_blank">{{ t('system.plugin.goDownload') }} </a>
</div> </div>
</a-alert> </a-alert>
<pluginTable /> <pluginTable />
@ -25,6 +23,10 @@
import { useI18n } from '@/hooks/useI18n'; import { useI18n } from '@/hooks/useI18n';
const { t } = useI18n(); const { t } = useI18n();
function openLink() {
window.open('https://metersphere.io/docs/v3.x/plugin/', '_blank');
}
</script> </script>
<style scoped> <style scoped>

View File

@ -42,8 +42,8 @@ export default {
'The project can not integrate with the platform and the default template of the platform is not available, be careful!', 'The project can not integrate with the platform and the default template of the platform is not available, be careful!',
'system.plugin.alertDescribe': 'system.plugin.alertDescribe':
'The MeterSphere v3.0 release supports plug-ins of DevOps、 API imports、 requests、 project management、 protocols、 and other types', 'The MeterSphere v3.0 release supports plug-ins of DevOps、 API imports、 requests、 project management、 protocols、 and other types',
'system.plugin.viewTable': 'View the form', 'system.plugin.viewTable': 'View details',
'system.plugin.downAddress': 'More open source plug-ins can be downloaded here', 'system.plugin.downAddress': 'Click the link to open a new page',
'system.plugin.goDownload': 'downloads', 'system.plugin.goDownload': 'downloads',
'system.plugin.deletePluginTip': 'Are you sure to delete the {name} plugin?', 'system.plugin.deletePluginTip': 'Are you sure to delete the {name} plugin?',
'system.plugin.disablePluginTip': 'Are you sure to disable the {name} plugin?', 'system.plugin.disablePluginTip': 'Are you sure to disable the {name} plugin?',

View File

@ -64,8 +64,8 @@ export default {
'system.plugin.disablePluginContent': '项目无法与该平台集成且该平台默认模板不可用,谨慎操作!', 'system.plugin.disablePluginContent': '项目无法与该平台集成且该平台默认模板不可用,谨慎操作!',
'system.plugin.alertDescribe': 'system.plugin.alertDescribe':
'MeterSphere v3.0 版本支持 DevOps、API 导入、请求、项目管理、协议 类型的插件,具体支持插件请', 'MeterSphere v3.0 版本支持 DevOps、API 导入、请求、项目管理、协议 类型的插件,具体支持插件请',
'system.plugin.viewTable': '查看表格', 'system.plugin.viewTable': '查看详情',
'system.plugin.downAddress': '更多开源插件,请在此下载', 'system.plugin.downAddress': '点击新开网页打开链接',
'system.plugin.goDownload': '去下载', 'system.plugin.goDownload': '去下载',
'system.plugin.totalNum': '共', 'system.plugin.totalNum': '共',
'system.plugin.dataList': '项数据', 'system.plugin.dataList': '项数据',