feat(系统): 资源池&系统设置优化

This commit is contained in:
baiqi 2024-07-09 15:33:20 +08:00 committed by 刘瑞斌
parent 53293f50e6
commit 6a6055300a
14 changed files with 166 additions and 138 deletions

View File

@ -1,7 +1,7 @@
<template>
<a-form ref="formRef" :model="form" layout="vertical">
<div
class="mb-[16px] overflow-y-auto rounded-[4px] bg-[var(--color-fill-1)] p-[12px]"
class="mb-[16px] overflow-y-auto rounded-[4px] border border-[var(--color-text-n8)] p-[12px]"
:style="{ width: props.formWidth || '100%' }"
>
<a-scrollbar class="overflow-y-auto" :style="{ 'max-height': props.maxHeight }">

View File

@ -133,6 +133,7 @@
showBatchModal.value = false;
target.value = [];
} catch (error) {
// eslint-disable-next-line no-console
console.log(error);
} finally {
batchLoading.value = false;
@ -156,6 +157,7 @@
break;
}
} catch (error) {
// eslint-disable-next-line no-console
console.log(error);
}
};
@ -166,6 +168,7 @@
treeList.value = await callBack(orgId);
loading.value = false;
} catch (error) {
// eslint-disable-next-line no-console
console.log(error);
}
};

View File

@ -88,11 +88,13 @@
}
}
.ms-button--danger {
color: rgb(var(--danger-6));
color: rgb(var(--danger-6)) !important;
&:not(.ms-button-text, .ms-button--disabled):hover {
color: rgb(var(--danger-6));
background-color: rgb(var(--danger-1));
}
&:hover {
color: rgb(var(--danger-6));
}
}
.ms-button--disabled {
@apply cursor-not-allowed;

View File

@ -3,7 +3,7 @@
ref="fullRef"
:class="`${
!isAdaptive ? 'h-full' : ''
} flex flex-col rounded-[var(--border-radius-small)] bg-[var(--color-fill-1)] p-[12px]`"
} flex flex-col rounded-[var(--border-radius-small)] border border-[var(--color-text-n8)] p-[12px]`"
>
<div v-if="showTitleLine" class="mb-[8px] flex items-center justify-between">
<div class="flex flex-wrap gap-[4px]">

View File

@ -181,7 +181,7 @@
:content="String(record[item.dataIndex as string])"
:disabled="record[item.dataIndex as string] === '' || record[item.dataIndex as string] === undefined || record[item.dataIndex as string] === null"
>
<div class="one-line-text">
<div class="one-line-text w-full">
<slot :name="item.slotName" v-bind="{ record, rowIndex, column, columnConfig: item }">
{{ record[item.dataIndex as string] || (attrs.emptyDataShowLine ? '-' : '') }}
</slot>

View File

@ -197,4 +197,5 @@ export default {
'common.selectedCount': '{count} data selected',
'common.advancedSettings': 'Advanced settings',
'common.auth_redirect_tip': 'You will be redirected to the certification source page for certification',
'common.default': 'Default',
};

View File

@ -196,4 +196,5 @@ export default {
'common.selectedCount': '(已选 {count} 项数据)',
'common.advancedSettings': '高级设置',
'common.auth_redirect_tip': '即将跳转至认证源页面进行认证',
'common.default': '默认',
};

View File

@ -7,7 +7,7 @@
v-permission="['SYSTEM_PARAMETER_SETTING_BASE:READ+UPDATE']"
type="outline"
size="mini"
@click="baseInfoDrawerVisible = true"
@click="baseInfoModalVisible = true"
>
{{ t('system.config.update') }}
</a-button>
@ -66,13 +66,14 @@
{{ t('system.config.email.test') }}
</a-button>
</MsCard>
<MsDrawer
v-model:visible="baseInfoDrawerVisible"
<a-modal
v-model:visible="baseInfoModalVisible"
:title="t('system.config.baseInfo.updateTitle')"
:ok-text="t('system.config.baseInfo.update')"
:ok-loading="baseDrawerLoading"
:width="680"
@confirm="updateBaseInfo"
:ok-loading="baseModalLoading"
title-align="start"
class="ms-modal-form"
:on-before-ok="updateBaseInfo"
@cancel="baseInfoCancel"
>
<a-form ref="baseFormRef" :model="baseInfoForm" layout="vertical">
@ -82,6 +83,7 @@
asterisk-position="end"
:rules="[{ required: true, message: t('system.config.baseInfo.pageUrlRequired') }]"
required
class="mb-0"
>
<a-input
v-model:model-value="baseInfoForm.url"
@ -92,7 +94,7 @@
<MsFormItemSub :text="t('system.config.baseInfo.pageUrlSub', { url: defaultUrl })" @fill="fillDefaultUrl" />
</a-form-item>
</a-form>
</MsDrawer>
</a-modal>
<MsDrawer
v-model:visible="emailConfigDrawerVisible"
:title="t('system.config.email.updateTitle')"
@ -133,6 +135,14 @@
allow-clear
></a-input>
</a-form-item>
<a-form-item :label="t('system.config.email.ssl')" field="ssl" asterisk-position="end">
<a-switch v-model:model-value="emailConfigForm.ssl" type="line" />
<MsFormItemSub :text="t('system.config.email.sslTip')" :show-fill-icon="false" />
</a-form-item>
<a-form-item :label="t('system.config.email.tsl')" field="tsl" asterisk-position="end">
<a-switch v-model:model-value="emailConfigForm.tsl" type="line" />
<MsFormItemSub :text="t('system.config.email.tslTip')" :show-fill-icon="false" />
</a-form-item>
<a-form-item
:label="t('system.config.email.account')"
field="account"
@ -183,14 +193,6 @@
allow-clear
></a-input>
</a-form-item>
<a-form-item :label="t('system.config.email.ssl')" field="ssl" asterisk-position="end">
<a-switch v-model:model-value="emailConfigForm.ssl" type="line" />
<MsFormItemSub :text="t('system.config.email.sslTip')" :show-fill-icon="false" />
</a-form-item>
<a-form-item :label="t('system.config.email.tsl')" field="tsl" asterisk-position="end">
<a-switch v-model:model-value="emailConfigForm.tsl" type="line" />
<MsFormItemSub :text="t('system.config.email.tslTip')" :show-fill-icon="false" />
</a-form-item>
</a-form>
<a-button type="outline" class="flex-1" :loading="drawerTestLoading" @click="testLink('drawer')">
{{ t('system.config.email.test') }}
@ -222,8 +224,8 @@
const { t } = useI18n();
const baseLoading = ref(false);
const baseDrawerLoading = ref(false);
const baseInfoDrawerVisible = ref(false);
const baseModalLoading = ref(false);
const baseInfoModalVisible = ref(false);
const baseFormRef = ref<FormInstance>();
const baseInfo = ref({
url: 'http://127.0.0.1:8081',
@ -282,20 +284,21 @@
/**
* 保存基础信息
*/
function updateBaseInfo() {
function updateBaseInfo(done: (closed: boolean) => void) {
baseFormRef.value?.validate(async (errors: Record<string, ValidatedError> | undefined) => {
if (!errors) {
try {
baseDrawerLoading.value = true;
baseModalLoading.value = true;
await saveBaseInfo(makeBaseInfoParams());
Message.success(t('system.config.baseInfo.updateSuccess'));
baseInfoDrawerVisible.value = false;
done(true);
initBaseInfo();
} catch (error) {
// eslint-disable-next-line no-console
console.log(error);
done(false);
} finally {
baseDrawerLoading.value = false;
baseModalLoading.value = false;
}
}
});

View File

@ -238,6 +238,7 @@
});
});
} catch (error) {
// eslint-disable-next-line no-console
console.log(error);
} finally {
loading.value = false;
@ -294,6 +295,7 @@
await closeValidateLarkSuite();
}
// eslint-disable-next-line no-console
console.log(error);
} finally {
loadList();
@ -321,6 +323,7 @@
Message.success(t(message));
loadList();
} catch (error) {
// eslint-disable-next-line no-console
console.log(error);
} finally {
loading.value = false;
@ -340,14 +343,12 @@
min-height: 300px;
border-radius: var(--border-radius-small);
background: var(--color-text-n9);
.list {
display: flex;
flex-wrap: wrap;
justify-content: flex-start;
align-content: flex-start;
width: 100%;
.item {
margin: 8px;
padding: 24px;
@ -355,7 +356,6 @@
border-radius: 4px;
background: white;
@apply flex flex-col justify-between;
.ms-enable {
font-size: 12px;
border-radius: var(--border-radius-small);

View File

@ -117,6 +117,7 @@
try {
weComForm.value = await getWeComInfo();
} catch (error) {
// eslint-disable-next-line no-console
console.log(error);
} finally {
loading.value = false;
@ -149,6 +150,7 @@
Message.success(t('organization.service.testLinkStatusTip'));
} catch (error) {
weComForm.value.valid = false;
// eslint-disable-next-line no-console
console.log(error);
} finally {
loading.value = false;
@ -166,6 +168,7 @@
Message.success(t('common.saveSuccess'));
emits('success');
} catch (error) {
// eslint-disable-next-line no-console
console.log(error);
} finally {
loading.value = false;
@ -179,11 +182,10 @@
<style scoped lang="less">
.footer-button {
display: flex;
justify-content: space-between;
align-items: center;
flex-direction: row;
justify-content: space-between;
}
.ms-switch {
display: flex;
align-items: center;

View File

@ -149,21 +149,30 @@
</a-form-item>
</template> -->
<a-form-item v-if="isShowTypeItem" :label="t('system.resourcePool.type')" field="type" class="form-item">
<!-- <a-form-item v-if="isShowTypeItem" :label="t('system.resourcePool.type')" field="type" class="form-item">
<a-radio-group v-model:model-value="form.type" type="button" @change="changeResourceType">
<a-radio value="Node">Node</a-radio>
<!-- TODO:第一版不上 -->
<!-- <a-radio v-xpack value="Kubernetes">Kubernetes</a-radio> -->
<a-radio v-xpack value="Kubernetes">Kubernetes</a-radio>
</a-radio-group>
</a-form-item>
</a-form-item> -->
<template v-if="isShowNodeResources">
<a-form-item field="addType" :class="`${licenseStore.hasLicense() ? '' : 'has-license-class'} form-item`">
<template #label>
<div class="flex items-center">
<div
class="mb-[8px] flex w-full items-center justify-between"
:class="`${licenseStore.hasLicense() ? '' : 'has-license-class'} form-item !w-full`"
>
{{ t('system.resourcePool.addResource') }}
</div>
</template>
<a-popconfirm
<MsButton
type="text"
@click="
() => {
form.addType = form.addType === 'single' ? 'multiple' : 'single';
handleTypeChange(form.addType);
}
"
>
{{ form.addType === 'single' ? t('system.resourcePool.batchAdd') : t('system.resourcePool.singleAdd') }}
</MsButton>
<!-- <a-popconfirm
v-if="!getIsVisited()"
v-xpack
class="ms-pop-confirm--hidden-cancel"
@ -197,14 +206,14 @@
<a-radio-group v-else v-model:model-value="form.addType" v-xpack type="button" @change="handleTypeChange">
<a-radio value="single">{{ t('system.resourcePool.singleAdd') }}</a-radio>
<a-radio v-xpack value="multiple">
<a-tooltip :content="t('system.resourcePool.changeAddTypeTip')" position="tl" mini
><span>
<a-tooltip :content="t('system.resourcePool.changeAddTypeTip')" position="tl" mini>
<span>
{{ t('system.resourcePool.batchAdd') }}
</span></a-tooltip
></a-radio
>
</a-radio-group>
</a-form-item>
</span>
</a-tooltip>
</a-radio>
</a-radio-group> -->
</div>
<MsBatchForm
v-show="form.addType === 'single'"
ref="batchFormRef"
@ -225,19 +234,11 @@
height="400px"
theme="MS-text"
:show-theme-change="false"
:show-full-screen="false"
@change="() => setIsSave(false)"
>
<template #leftTitle>
<a-form-item
:label="t('system.resourcePool.batchAddResource')"
asterisk-position="end"
class="hide-wrapper mb-0 w-auto"
required
>
</a-form-item>
</template>
</MsCodeEditor>
<div class="mb-[24px] mt-[4px] text-[12px] leading-[16px] text-[var(--color-text-4)]">
<div class="mb-[24px] mt-[4px] text-[12px] leading-[16px] text-[rgb(var(--warning-6))]">
{{ t('system.resourcePool.nodeConfigEditorTip') }}
</div>
</div>
@ -397,7 +398,6 @@
import { addPool, getPoolInfo, updatePoolInfo } from '@/api/modules/setting/resourcePool';
import { useI18n } from '@/hooks/useI18n';
import useLeaveUnSaveTip from '@/hooks/useLeaveUnSaveTip';
import useVisit from '@/hooks/useVisit';
import useAppStore from '@/store/modules/app';
import useLicenseStore from '@/store/modules/setting/license';
import { downloadStringFile, sleep } from '@/utils';
@ -526,18 +526,18 @@
// form.value.testResourceDTO.loadTestHeap = defaultHeap;
// }
const visitedKey = 'changeAddResourceType';
const { addVisited, getIsVisited } = useVisit(visitedKey);
// const visitedKey = 'changeAddResourceType';
// const { addVisited, getIsVisited } = useVisit(visitedKey);
/**
* 切换类型提示确认框隐藏时设置已访问标
* @param visible 显示/
*/
function handlePopChange(visible: boolean) {
if (!visible) {
addVisited();
}
}
// /**
// * 访
// * @param visible /
// */
// function handlePopChange(visible: boolean) {
// if (!visible) {
// addVisited();
// }
// }
/**
* 控制表单项显示隐藏逻辑计算器
@ -685,12 +685,12 @@
setIsSave(false);
}
function changeResourceType(val: string | number | boolean) {
if (val === 'Kubernetes') {
setBatchFormRes();
}
setIsSave(false);
}
// function changeResourceType(val: string | number | boolean) {
// if (val === 'Kubernetes') {
// setBatchFormRes();
// }
// setIsSave(false);
// }
/**
* 下载 yaml 文件

View File

@ -17,13 +17,41 @@
</div>
<ms-base-table v-bind="propsRes" no-disable v-on="propsEvent">
<template #name="{ record }">
<a-button type="text" class="px-0" @click="showPoolDetail(record.id)">{{ record.name }}</a-button>
<div class="flex w-full items-center justify-start gap-[8px]">
<a-button
type="text"
class="px-0"
:class="record.id === '100001100001' ? '' : 'w-full justify-start'"
@click="showPoolDetail(record.id)"
>
<div class="one-line-text">
{{ record.name }}
</div>
</a-button>
<MsTag v-if="record.id === '100001100001'" size="small" tooltip-disabled>{{ t('common.default') }}</MsTag>
</div>
</template>
<template #enable="{ record }">
<div class="flex items-center gap-[8px]">
<a-switch
v-model:model-value="record.enable"
v-permission="['SYSTEM_TEST_RESOURCE_POOL:READ+UPDATE']"
v-xpack
size="small"
:before-change="(val) => handleToggle(val, record)"
>
</a-switch>
{{ record.enable ? t('system.resourcePool.tableEnabled') : t('system.resourcePool.tableDisabled') }}
</div>
</template>
<template #action="{ record }">
<MsButton v-permission="['SYSTEM_TEST_RESOURCE_POOL:READ+UPDATE']" @click="editPool(record)">
{{ t('system.resourcePool.editPool') }}
</MsButton>
<MsButton
<MsButton v-permission="['SYSTEM_TEST_RESOURCE_POOL:READ+DELETE']" status="danger" @click="deletePool(record)">
{{ t('common.delete') }}
</MsButton>
<!-- <MsButton
v-if="record.enable"
v-permission="['SYSTEM_TEST_RESOURCE_POOL:READ+UPDATE']"
v-xpack
@ -33,12 +61,7 @@
</MsButton>
<MsButton v-else v-permission="['SYSTEM_TEST_RESOURCE_POOL:READ+UPDATE']" v-xpack @click="enablePool(record)">
{{ t('system.resourcePool.tableEnable') }}
</MsButton>
<MsTableMoreAction
v-permission="['SYSTEM_TEST_RESOURCE_POOL:READ+DELETE']"
:list="tableActions"
@select="handleSelect($event, record)"
></MsTableMoreAction>
</MsButton> -->
</template>
</ms-base-table>
</MsCard>
@ -87,9 +110,7 @@
import MsBaseTable from '@/components/pure/ms-table/base-table.vue';
import type { MsTableColumn } from '@/components/pure/ms-table/type';
import useTable from '@/components/pure/ms-table/useTable';
import MsTableMoreAction from '@/components/pure/ms-table-more-action/index.vue';
import type { ActionsItem } from '@/components/pure/ms-table-more-action/types';
import { TagType, Theme } from '@/components/pure/ms-tag/ms-tag.vue';
import MsTag, { TagType, Theme } from '@/components/pure/ms-tag/ms-tag.vue';
import MsTrialAlert from '@/components/business/ms-trial-alert/index.vue';
import JobTemplateDrawer from './components/jobTemplateDrawer.vue';
@ -100,7 +121,7 @@
import { characterLimit } from '@/utils';
import { hasAnyPermission } from '@/utils/permission';
import type { ResourcePoolDetail } from '@/models/setting/resourcePool';
import type { ResourcePoolDetail, ResourcePoolItem } from '@/models/setting/resourcePool';
import { TableKeyEnum } from '@/enums/tableEnum';
const { t } = useI18n();
@ -116,6 +137,7 @@
slotName: 'name',
dataIndex: 'name',
showTooltip: true,
width: 200,
},
{
title: 'system.resourcePool.tableColumnStatus',
@ -127,10 +149,10 @@
dataIndex: 'description',
showTooltip: true,
},
{
title: 'system.resourcePool.tableColumnType',
dataIndex: 'type',
},
// {
// title: 'system.resourcePool.tableColumnType',
// dataIndex: 'type',
// },
{
title: 'system.resourcePool.tableColumnCreateTime',
dataIndex: 'createTime',
@ -142,14 +164,17 @@
width: 180,
},
{
title: hasOperationPoolPermission.value ? 'system.resourcePool.tableColumnActions' : '',
title: 'system.resourcePool.tableColumnActions',
slotName: 'action',
dataIndex: 'operation',
fixed: 'right',
width: hasOperationPoolPermission.value ? 140 : 50,
width: 120,
},
];
const tableStore = useTableStore();
if (!hasOperationPoolPermission.value) {
columns.pop();
}
await tableStore.initColumn(TableKeyEnum.SYSTEM_RESOURCEPOOL, columns, 'drawer');
const { propsRes, propsEvent, loadList, setKeyword } = useTable(getPoolList, {
tableKey: TableKeyEnum.SYSTEM_RESOURCEPOOL,
@ -172,21 +197,12 @@
}
const { openModal } = useModal();
const tableActions: ActionsItem[] = [
{
label: 'system.resourcePool.delete',
eventTag: 'delete',
danger: true,
},
];
const loading = ref(false);
/**
* 启用资源池
*/
async function enablePool(record: any) {
async function enablePool(record: ResourcePoolItem) {
try {
loading.value = true;
await togglePoolStatus(record.id);
@ -203,7 +219,7 @@
/**
* 禁用资源池
*/
function disabledPool(record: any) {
function disabledPool(record: ResourcePoolItem) {
openModal({
type: 'warning',
title: t('system.resourcePool.disablePoolTip', { name: characterLimit(record.name) }),
@ -225,10 +241,19 @@
});
}
function handleToggle(newValue: string | number | boolean, record: ResourcePoolItem) {
if (newValue) {
enablePool(record);
} else {
disabledPool(record);
}
return false;
}
/**
* 删除资源池
*/
function deletePool(record: any) {
function deletePool(record: ResourcePoolItem) {
if (propsRes.value.data.length === 1) {
Message.warning(t('system.resourcePool.atLeastOnePool'));
return;
@ -257,20 +282,6 @@
});
}
/**
* 处理表格更多按钮事件
* @param item
*/
function handleSelect(item: ActionsItem, record: any) {
switch (item.eventTag) {
case 'delete':
deletePool(record);
break;
default:
break;
}
}
const showDetailDrawer = ref(false);
const activePoolDesc = ref<Description[]>([]);
const activePool = ref<ResourcePoolDetail | null>(null);
@ -296,10 +307,10 @@
return;
}
activePool.value = res;
const poolUses = [
activePool.value.apiTest ? t('system.resourcePool.useAPI') : '',
activePool.value.uiTest ? t('system.resourcePool.useUI') : '',
];
// const poolUses = [
// activePool.value.apiTest ? t('system.resourcePool.useAPI') : '',
// activePool.value.uiTest ? t('system.resourcePool.useUI') : '',
// ];
const { type, testResourceReturnDTO, apiTest, uiTest } = activePool.value;
const {
ip,
@ -444,11 +455,11 @@
* 编辑资源池
* @param record
*/
function editPool(record: any) {
function editPool(record: ResourcePoolDetail | null) {
router.push({
name: 'settingSystemResourcePoolDetail',
query: {
id: record.id,
id: record?.id,
},
});
}

View File

@ -3,7 +3,9 @@ export default {
'system.resourcePool.searchPool': 'Search by name',
'system.resourcePool.delete': 'Delete',
'system.resourcePool.tableEnable': 'Enable',
'system.resourcePool.tableDisable': 'Disable',
'system.resourcePool.tableEnabled': 'Enabled',
'system.resourcePool.tableDisable': 'Disabled',
'system.resourcePool.tableDisabled': '已禁用',
'system.resourcePool.editPool': 'Edit',
'system.resourcePool.tableColumnName': 'Name',
'system.resourcePool.tableColumnStatus': 'Status',
@ -12,8 +14,9 @@ export default {
'system.resourcePool.tableColumnUpdateTime': 'UpdateTime',
'system.resourcePool.tableColumnActions': 'Actions',
'system.resourcePool.enablePoolSuccess': 'Enabled successfully',
'system.resourcePool.disablePoolTip': 'About to disable resource pool `{name}`',
'system.resourcePool.disablePoolContent': 'When disabled, tests using this resource pool will stop executing',
'system.resourcePool.disablePoolTip': 'Confirm to disable resource pool {name} ?',
'system.resourcePool.disablePoolContent':
'After disabling, the test execution using this resource pool will fail, so please operate with caution!',
'system.resourcePool.disablePoolConfirm': 'Confirm',
'system.resourcePool.disablePoolCancel': 'Cancel',
'system.resourcePool.disablePoolSuccess': 'Disabled successfully',
@ -62,13 +65,13 @@ export default {
'system.resourcePool.uiGridRequired': 'Please enter selenium-grid address',
'system.resourcePool.girdConcurrentNumber': 'grid maximum number of threads',
'system.resourcePool.type': 'Type',
'system.resourcePool.addResource': 'Add resources',
'system.resourcePool.addResource': 'Add nodes',
'system.resourcePool.singleAdd': 'Single add',
'system.resourcePool.batchAdd': 'Batch add',
'system.resourcePool.batchAddTipConfirm': 'Got it',
'system.resourcePool.batchAddResource': 'Batch add resources',
'system.resourcePool.batchAddResource': 'Batch add nodes',
'system.resourcePool.changeAddTypeTip':
'After switching, the content of the added resources will continue to appear in csv; the added resources can be modified in batches',
'After switching, the content of the added nodes will continue to appear in csv; the added nodes can be modified in batches',
'system.resourcePool.changeAddTypePopTitle': 'Toggle add resource type?',
'system.resourcePool.ip': 'IP',
'system.resourcePool.ipRequired': 'Please enter an IP address',

View File

@ -3,7 +3,9 @@ export default {
'system.resourcePool.searchPool': '通过名称搜索',
'system.resourcePool.delete': '删除',
'system.resourcePool.tableEnable': '启用',
'system.resourcePool.tableEnabled': '已启用',
'system.resourcePool.tableDisable': '禁用',
'system.resourcePool.tableDisabled': '已禁用',
'system.resourcePool.editPool': '编辑',
'system.resourcePool.tableColumnName': '名称',
'system.resourcePool.tableColumnStatus': '状态',
@ -12,8 +14,8 @@ export default {
'system.resourcePool.tableColumnUpdateTime': '更新时间',
'system.resourcePool.tableColumnActions': '操作',
'system.resourcePool.enablePoolSuccess': '启用成功',
'system.resourcePool.disablePoolTip': '即将禁用资源池 `{name}`',
'system.resourcePool.disablePoolContent': '禁用后,正在使用该资源池的测试会停止执行',
'system.resourcePool.disablePoolTip': '确认禁用资源池 {name} ',
'system.resourcePool.disablePoolContent': '禁用后,会导致使用该资源池运行的测试执行失败,请谨慎操作!',
'system.resourcePool.disablePoolConfirm': '确认禁用',
'system.resourcePool.disablePoolCancel': '取消',
'system.resourcePool.disablePoolSuccess': '禁用成功',
@ -60,12 +62,12 @@ export default {
'system.resourcePool.uiGridRequired': 'selenium-grid 不能为空',
'system.resourcePool.girdConcurrentNumber': 'grid最大线程数',
'system.resourcePool.type': '类型',
'system.resourcePool.addResource': '添加资源',
'system.resourcePool.addResource': '添加节点',
'system.resourcePool.singleAdd': '单个添加',
'system.resourcePool.batchAdd': '批量添加',
'system.resourcePool.batchAddTipConfirm': '知道了',
'system.resourcePool.batchAddResource': '批量添加资源',
'system.resourcePool.changeAddTypeTip': '切换后,已添加资源内容将继续显示在 csv 内;可批量修改已添加资源',
'system.resourcePool.batchAddResource': '批量添加节点',
'system.resourcePool.changeAddTypeTip': '切换后,已添加节点内容将继续显示在 csv 内;可批量修改已添加节点',
'system.resourcePool.changeAddTypePopTitle': '切换添加资源类型?',
'system.resourcePool.allUseTip': '如果配置多个测试类型,会存在抢占资源的情况,建议一种测试类型配置一个资源池',
'system.resourcePool.ip': 'IP',