fix(all): 修复bugs
This commit is contained in:
parent
617b44780e
commit
526e563270
|
@ -6,6 +6,8 @@ import {
|
|||
GetPluginScriptUrl,
|
||||
GetProtocolListUrl,
|
||||
LocalExecuteApiDebugUrl,
|
||||
StopExecuteUrl,
|
||||
StopLocalExecuteUrl,
|
||||
} from '@/api/requrls/api-test/common';
|
||||
|
||||
import {
|
||||
|
@ -16,6 +18,7 @@ import {
|
|||
ProtocolItem,
|
||||
} from '@/models/apiTest/common';
|
||||
import { EnvConfig, EnvironmentItem } from '@/models/projectManagement/environmental';
|
||||
import { ScenarioStepType } from '@/enums/apiEnum';
|
||||
|
||||
// 获取协议列表
|
||||
export function getProtocolList(organizationId: string) {
|
||||
|
@ -46,3 +49,15 @@ export function getEnvList(projectId: string) {
|
|||
export function getEnvironment(envId: string) {
|
||||
return MSR.get<EnvConfig>({ url: GetEnvironmentUrl, params: envId });
|
||||
}
|
||||
|
||||
// 停止本地执行
|
||||
export function stopLocalExecute(host: string, id: string | number, type?: ScenarioStepType) {
|
||||
return MSR.post({
|
||||
url: type ? `${host}${StopLocalExecuteUrl}/${type}/${id}` : `${host}${StopLocalExecuteUrl}/${id}`,
|
||||
});
|
||||
}
|
||||
|
||||
// 停止执行
|
||||
export function stopExecute(id: string | number, type?: ScenarioStepType) {
|
||||
return MSR.get({ url: type ? `${StopExecuteUrl}/${type}/${id}` : `${StopExecuteUrl}/${id}` });
|
||||
}
|
||||
|
|
|
@ -4,3 +4,5 @@ export const GetPluginScriptUrl = '/api/test/plugin/script'; // 获取插件配
|
|||
export const LocalExecuteApiDebugUrl = '/api/debug'; // 本地执行调试
|
||||
export const GetEnvListUrl = '/api/test/env-list'; // 获取接口测试环境列表
|
||||
export const GetEnvironmentUrl = '/api/test/environment'; // 获取接口测试环境详情
|
||||
export const StopExecuteUrl = '/task/center/api/project/stop'; // 停止执行
|
||||
export const StopLocalExecuteUrl = '/api/stop'; // 停止本地执行
|
||||
|
|
|
@ -4,7 +4,11 @@
|
|||
<a-space>
|
||||
<div class="one-line-text flex max-w-[145px] items-center">
|
||||
<img :src="props.logo" class="mr-[4px] h-[34px] w-[32px]" />
|
||||
<div class="font-['Helvetica_Neue'] text-[16px] font-bold text-[rgb(var(--primary-5))]">{{ props.name }}</div>
|
||||
<a-tooltip :content="props.name">
|
||||
<div class="one-line-text font-['Helvetica_Neue'] text-[16px] font-bold text-[rgb(var(--primary-5))]">
|
||||
{{ props.name }}
|
||||
</div>
|
||||
</a-tooltip>
|
||||
</div>
|
||||
</a-space>
|
||||
</div>
|
||||
|
|
|
@ -408,6 +408,7 @@ export interface Scenario {
|
|||
stepResponses: Record<string | number, Array<RequestResult>>; // 步骤响应集合,key 为步骤 id,value 为步骤响应内容
|
||||
isExecute?: boolean; // 是否从列表执行进去场景详情
|
||||
isDebug?: boolean; // 是否调试,区分执行场景和批量调试步骤
|
||||
executeType?: 'localExec' | 'serverExec'; // 执行类型
|
||||
}
|
||||
// 场景详情
|
||||
export interface ScenarioDetail extends Scenario {
|
||||
|
|
|
@ -87,8 +87,8 @@
|
|||
:max-length="255"
|
||||
:disabled="props.disabled"
|
||||
size="small"
|
||||
@press-enter="isShowEditScriptNameInput = false"
|
||||
@blur="isShowEditScriptNameInput = false"
|
||||
@press-enter="handleScriptNameInputBlur"
|
||||
@blur="handleScriptNameInputBlur"
|
||||
@change="() => emit('change')"
|
||||
/>
|
||||
</div>
|
||||
|
@ -689,6 +689,13 @@ if (!result){
|
|||
},
|
||||
];
|
||||
|
||||
function handleScriptNameInputBlur() {
|
||||
if (condition.value.name === '') {
|
||||
condition.value.name = t('apiTestDebug.preconditionScriptName');
|
||||
}
|
||||
isShowEditScriptNameInput.value = false;
|
||||
}
|
||||
|
||||
const showQuoteDrawer = ref(false);
|
||||
function saveQuoteScriptHandler(item: any) {
|
||||
// TODO:any
|
||||
|
|
|
@ -222,6 +222,7 @@
|
|||
try {
|
||||
deleteListItem(item);
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(error);
|
||||
}
|
||||
},
|
||||
|
|
|
@ -841,7 +841,7 @@
|
|||
if (
|
||||
!filterKeyValParams(arr, props.defaultParamItem).lastDataIsDefault &&
|
||||
!props.isTreeTable &&
|
||||
!filterKeyValParams(arr, arr[arr.length - 2]).lastDataIsDefault // 为了判断最后俩行是否一致(因为下拉框切换会新增一行一样的数据,此时最后一条数据与默认数据是不一样的)
|
||||
!filterKeyValParams([arr[arr.length - 2], arr[arr.length - 1]], arr[arr.length - 1]).lastDataIsDefault // 为了判断最后俩行是否一致(因为下拉框切换会新增一行一样的数据,此时最后一条数据与默认数据是不一样的)
|
||||
) {
|
||||
addTableLine(arr.length - 1, false, true);
|
||||
}
|
||||
|
|
|
@ -1,19 +1,18 @@
|
|||
<template>
|
||||
<a-scrollbar class="overflow-y-auto" :style="{ height: '300px' }">
|
||||
<MsBaseTable v-bind="propsRes" v-on="propsEvent">
|
||||
<MsFormTable :data="props.requestResult?.responseResult.assertions" :columns="columns" :selectable="false">
|
||||
<template #status="{ record }">
|
||||
<MsTag :type="record.pass === true ? 'success' : 'danger'" theme="light">
|
||||
{{ record.pass === true ? t('common.success') : t('common.fail') }}
|
||||
</MsTag>
|
||||
</template>
|
||||
</MsBaseTable>
|
||||
</MsFormTable>
|
||||
</a-scrollbar>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import MsBaseTable from '@/components/pure/ms-table/base-table.vue';
|
||||
import MsFormTable from '@/components/pure/ms-form-table/index.vue';
|
||||
import { MsTableColumn } from '@/components/pure/ms-table/type';
|
||||
import useTable from '@/components/pure/ms-table/useTable';
|
||||
import MsTag from '@/components/pure/ms-tag/ms-tag.vue';
|
||||
|
||||
import { useI18n } from '@/hooks/useI18n';
|
||||
|
@ -43,22 +42,6 @@
|
|||
showTooltip: true,
|
||||
},
|
||||
];
|
||||
const { propsRes, propsEvent } = useTable(undefined, {
|
||||
scroll: { x: '100%' },
|
||||
columns,
|
||||
});
|
||||
|
||||
watch(
|
||||
() => props.requestResult?.responseResult.assertions,
|
||||
(val) => {
|
||||
if (val) {
|
||||
propsRes.value.data = props.requestResult?.responseResult.assertions || [];
|
||||
}
|
||||
},
|
||||
{
|
||||
immediate: true,
|
||||
}
|
||||
);
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
|
|
|
@ -104,7 +104,7 @@
|
|||
import TabCaseDependency from '@/views/api-test/management/components/management/case/tabContent/tabCaseDependency.vue';
|
||||
import TabCaseExecuteHistory from '@/views/api-test/management/components/management/case/tabContent/tabCaseExecuteHistory.vue';
|
||||
|
||||
import { localExecuteApiDebug } from '@/api/modules/api-test/common';
|
||||
import { localExecuteApiDebug, stopExecute, stopLocalExecute } from '@/api/modules/api-test/common';
|
||||
import { debugCase, deleteCase, runCase, toggleFollowCase } from '@/api/modules/api-test/management';
|
||||
import { getSocket } from '@/api/modules/project-management/commonScript';
|
||||
import useModal from '@/hooks/useModal';
|
||||
|
@ -112,7 +112,7 @@
|
|||
|
||||
import { ProtocolItem } from '@/models/apiTest/common';
|
||||
import { EnvConfig } from '@/models/projectManagement/environmental';
|
||||
import { RequestMethods } from '@/enums/apiEnum';
|
||||
import { RequestMethods, ScenarioStepType } from '@/enums/apiEnum';
|
||||
|
||||
import { defaultResponse } from '@/views/api-test/components/config';
|
||||
|
||||
|
@ -299,7 +299,17 @@
|
|||
executeCase.value = false;
|
||||
}
|
||||
}
|
||||
function stopDebug() {
|
||||
async function stopDebug() {
|
||||
try {
|
||||
if (caseDetail.value.frontendDebug) {
|
||||
await stopLocalExecute(executeRef.value?.localExecuteUrl || '', reportId.value, ScenarioStepType.API_CASE);
|
||||
} else {
|
||||
await stopExecute(reportId.value, ScenarioStepType.API_CASE);
|
||||
}
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(error);
|
||||
}
|
||||
websocket.value?.close();
|
||||
caseDetail.value.executeLoading = false;
|
||||
executeCase.value = false;
|
||||
|
|
|
@ -82,7 +82,7 @@
|
|||
:scenario-id="scenarioId"
|
||||
@replace="handleReplace"
|
||||
/>
|
||||
<MsButton type="icon" status="secondary" @click="emit('deleteStep')">
|
||||
<MsButton type="icon" status="secondary" class="mr-4" @click="emit('deleteStep')">
|
||||
<MsIcon type="icon-icon_delete-trash_outlined" />
|
||||
{{ t('common.delete') }}
|
||||
</MsButton>
|
||||
|
|
|
@ -142,6 +142,7 @@
|
|||
|
||||
import { getScenarioDetail } from '@/api/modules/api-test/scenario';
|
||||
import { useI18n } from '@/hooks/useI18n';
|
||||
import useModal from '@/hooks/useModal';
|
||||
import { deleteNodes, filterTree, getGenerateId, mapTree, traverseTree } from '@/utils';
|
||||
import { countNodes } from '@/utils/tree';
|
||||
|
||||
|
@ -156,6 +157,7 @@
|
|||
}>();
|
||||
|
||||
const { t } = useI18n();
|
||||
const { openModal } = useModal();
|
||||
|
||||
const scenario = defineModel<Scenario>('scenario', {
|
||||
required: true,
|
||||
|
@ -268,12 +270,26 @@
|
|||
}
|
||||
|
||||
function batchDelete() {
|
||||
openModal({
|
||||
type: 'error',
|
||||
title: t('common.tip'),
|
||||
content: t('apiScenario.deleteStepConfirmWithChildren'),
|
||||
okText: t('common.confirmDelete'),
|
||||
cancelText: t('common.cancel'),
|
||||
okButtonProps: {
|
||||
status: 'danger',
|
||||
},
|
||||
maskClosable: false,
|
||||
onBeforeOk: async () => {
|
||||
deleteNodes(scenario.value.steps, checkedKeys.value, (node) => !node.isQuoteScenarioStep, 'uniqueId');
|
||||
Message.success(t('common.deleteSuccess'));
|
||||
if (scenario.value.steps.length === 0) {
|
||||
checkedAll.value = false;
|
||||
indeterminate.value = false;
|
||||
}
|
||||
},
|
||||
hideCancel: false,
|
||||
});
|
||||
}
|
||||
|
||||
const showScenarioReportVisible = ref(false);
|
||||
|
|
|
@ -328,7 +328,7 @@
|
|||
</div>
|
||||
</a-form-item>
|
||||
<a-form-item v-show="scenarioConfigForm.useOriginScenarioParam" class="hidden-item">
|
||||
<a-radio-group v-model:model-value="scenarioConfigForm.useOriginScenarioParamPreferential" type="button">
|
||||
<a-radio-group v-model:model-value="scenarioConfigForm.useOriginScenarioParamPreferential">
|
||||
<a-radio :value="true">
|
||||
<div class="flex items-center gap-[4px]">
|
||||
{{ t('apiScenario.sourceScenario') }}
|
||||
|
@ -530,6 +530,7 @@
|
|||
import { debugScenario, getScenarioStep } from '@/api/modules/api-test/scenario';
|
||||
import { getSocket } from '@/api/modules/project-management/commonScript';
|
||||
import { useI18n } from '@/hooks/useI18n';
|
||||
import useModal from '@/hooks/useModal';
|
||||
import useAppStore from '@/store/modules/app';
|
||||
import {
|
||||
deleteNode,
|
||||
|
@ -594,6 +595,7 @@
|
|||
|
||||
const appStore = useAppStore();
|
||||
const { t } = useI18n();
|
||||
const { openModal } = useModal();
|
||||
|
||||
const steps = defineModel<ScenarioStepItem[]>('steps', {
|
||||
required: true,
|
||||
|
@ -779,69 +781,45 @@
|
|||
});
|
||||
const showScenarioConfig = ref(false);
|
||||
const scenarioConfigParamTip = computed(() => {
|
||||
if (
|
||||
scenarioConfigForm.value.useOriginScenarioParam &&
|
||||
!scenarioConfigForm.value.useOriginScenarioParamPreferential &&
|
||||
!scenarioConfigForm.value.enableScenarioEnv
|
||||
) {
|
||||
// 使用当前场景参数-空值
|
||||
return t('apiScenario.currentScenarioAndNull');
|
||||
if (!scenarioConfigForm.value.useOriginScenarioParam && !scenarioConfigForm.value.enableScenarioEnv) {
|
||||
// 非使用原场景参数-非选择源场景环境
|
||||
return t('apiScenario.notSource');
|
||||
}
|
||||
if (
|
||||
scenarioConfigForm.value.useOriginScenarioParam &&
|
||||
!scenarioConfigForm.value.useOriginScenarioParamPreferential &&
|
||||
scenarioConfigForm.value.enableScenarioEnv
|
||||
) {
|
||||
// 使用当前场景参数-空值-且选择源场景环境
|
||||
return t('apiScenario.currentScenarioAndNullAndSourceEnv');
|
||||
if (!scenarioConfigForm.value.useOriginScenarioParam && scenarioConfigForm.value.enableScenarioEnv) {
|
||||
// 非使用原场景参数-选择源场景环境
|
||||
return t('apiScenario.notSourceParamAndSourceEnv');
|
||||
}
|
||||
if (
|
||||
scenarioConfigForm.value.useOriginScenarioParam &&
|
||||
scenarioConfigForm.value.useOriginScenarioParamPreferential &&
|
||||
!scenarioConfigForm.value.enableScenarioEnv
|
||||
) {
|
||||
// 使用当前场景参数-原场景参数
|
||||
return t('apiScenario.currentScenarioAndSourceScenario');
|
||||
// 使用原场景参数-优先使用原场景参数
|
||||
return t('apiScenario.sourceParamAndSource');
|
||||
}
|
||||
if (
|
||||
scenarioConfigForm.value.useOriginScenarioParam &&
|
||||
scenarioConfigForm.value.useOriginScenarioParamPreferential &&
|
||||
scenarioConfigForm.value.enableScenarioEnv
|
||||
) {
|
||||
// 使用当前场景参数-原场景参数-且选择源场景环境
|
||||
return t('apiScenario.currentScenarioAndSourceScenarioAndSourceEnv');
|
||||
// 使用原场景参数-优先使用原场景参数-选择源场景环境
|
||||
return t('apiScenario.sourceParamAndSourceEnv');
|
||||
}
|
||||
if (
|
||||
!scenarioConfigForm.value.useOriginScenarioParam &&
|
||||
scenarioConfigForm.value.useOriginScenarioParam &&
|
||||
!scenarioConfigForm.value.useOriginScenarioParamPreferential &&
|
||||
!scenarioConfigForm.value.enableScenarioEnv
|
||||
) {
|
||||
// 使用原场景参数-空值
|
||||
return t('apiScenario.sourceScenarioAndNull');
|
||||
// 使用原场景参数-优先使用当前场景参数
|
||||
return t('apiScenario.currentParamAndSource');
|
||||
}
|
||||
if (
|
||||
!scenarioConfigForm.value.useOriginScenarioParam &&
|
||||
scenarioConfigForm.value.useOriginScenarioParam &&
|
||||
!scenarioConfigForm.value.useOriginScenarioParamPreferential &&
|
||||
scenarioConfigForm.value.enableScenarioEnv
|
||||
) {
|
||||
// 使用原场景参数-空值-且选择源场景环境
|
||||
return t('apiScenario.sourceScenarioAndNullAndSourceEnv');
|
||||
}
|
||||
if (
|
||||
!scenarioConfigForm.value.useOriginScenarioParam &&
|
||||
scenarioConfigForm.value.useOriginScenarioParamPreferential &&
|
||||
!scenarioConfigForm.value.enableScenarioEnv
|
||||
) {
|
||||
// 使用原场景参数-当前场景参数
|
||||
return t('apiScenario.sourceScenarioAndCurrentScenario');
|
||||
}
|
||||
if (
|
||||
!scenarioConfigForm.value.useOriginScenarioParam &&
|
||||
scenarioConfigForm.value.useOriginScenarioParamPreferential &&
|
||||
scenarioConfigForm.value.enableScenarioEnv
|
||||
) {
|
||||
// 使用原场景参数-当前场景参数-且选择源场景环境
|
||||
return t('apiScenario.sourceScenarioAndCurrentScenarioAndSourceEnv');
|
||||
// 使用原场景参数-优先使用当前场景参数-选择源场景环境
|
||||
return t('apiScenario.currentParamAndSourceEnv');
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -1153,7 +1131,7 @@
|
|||
})[0]
|
||||
),
|
||||
name: `copy_${node.name}`,
|
||||
copyFromStepId: node.id,
|
||||
copyFromStepId: stepDetail ? node.id : node.copyFromStepId,
|
||||
sort: node.sort + 1,
|
||||
isNew: true,
|
||||
id,
|
||||
|
@ -1174,8 +1152,25 @@
|
|||
showScenarioConfig.value = true;
|
||||
break;
|
||||
case 'delete':
|
||||
openModal({
|
||||
type: 'error',
|
||||
title: t('common.tip'),
|
||||
content:
|
||||
node.children && node.children.length > 0
|
||||
? t('apiScenario.deleteStepConfirmWithChildren')
|
||||
: t('apiScenario.deleteStepConfirm', { name: node.name }),
|
||||
okText: t('common.confirmDelete'),
|
||||
cancelText: t('common.cancel'),
|
||||
okButtonProps: {
|
||||
status: 'danger',
|
||||
},
|
||||
maskClosable: false,
|
||||
onBeforeOk: async () => {
|
||||
deleteNode(steps.value, node.uniqueId, 'uniqueId');
|
||||
scenario.value.unSaved = true;
|
||||
},
|
||||
hideCancel: false,
|
||||
});
|
||||
break;
|
||||
case 'saveAsApi':
|
||||
activeStep.value = node as ScenarioStepItem;
|
||||
|
@ -1321,7 +1316,7 @@
|
|||
// 复制 api、引用 api、自定义 api打开抽屉
|
||||
activeStep.value = step;
|
||||
if (
|
||||
(stepDetails.value[step.id] === undefined && step.copyFromStepId && !step.isNew) ||
|
||||
(stepDetails.value[step.id] === undefined && step.copyFromStepId) ||
|
||||
(stepDetails.value[step.id] === undefined && !step.isNew)
|
||||
) {
|
||||
// 查看场景详情时,详情映射中没有对应数据,初始化步骤详情(复制的步骤没有加载详情前就被复制,打开复制后的步骤就初始化被复制步骤的详情)
|
||||
|
@ -1332,7 +1327,7 @@
|
|||
activeStep.value = step;
|
||||
if (
|
||||
_stepType.isCopyCase &&
|
||||
((stepDetails.value[step.id] === undefined && step.copyFromStepId && !step.isNew) ||
|
||||
((stepDetails.value[step.id] === undefined && step.copyFromStepId) ||
|
||||
(stepDetails.value[step.id] === undefined && !step.isNew))
|
||||
) {
|
||||
// 只有复制的 case 需要查看步骤详情,引用的无法更改所以不需要在此初始化详情
|
||||
|
@ -1358,16 +1353,11 @@
|
|||
/**
|
||||
* 开启websocket监听,接收执行结果
|
||||
*/
|
||||
function debugSocket(
|
||||
step: ScenarioStepItem,
|
||||
_scenario: Scenario,
|
||||
reportId: string | number,
|
||||
executeType?: 'localExec' | 'serverExec'
|
||||
) {
|
||||
function debugSocket(step: ScenarioStepItem, _scenario: Scenario, reportId: string | number) {
|
||||
websocketMap[reportId] = getSocket(
|
||||
reportId || '',
|
||||
executeType === 'localExec' ? '/ws/debug' : '',
|
||||
executeType === 'localExec' ? localExecuteUrl?.value : ''
|
||||
scenario.value.executeType === 'localExec' ? '/ws/debug' : '',
|
||||
scenario.value.executeType === 'localExec' ? localExecuteUrl?.value : ''
|
||||
);
|
||||
websocketMap[reportId].addEventListener('message', (event) => {
|
||||
const data = JSON.parse(event.data);
|
||||
|
@ -1396,21 +1386,20 @@
|
|||
}
|
||||
|
||||
async function realExecute(
|
||||
executeParams: Pick<ApiScenarioDebugRequest, 'steps' | 'stepDetails' | 'reportId' | 'stepFileParam'>,
|
||||
executeType?: 'localExec' | 'serverExec'
|
||||
executeParams: Pick<ApiScenarioDebugRequest, 'steps' | 'stepDetails' | 'reportId' | 'stepFileParam'>
|
||||
) {
|
||||
const [currentStep] = executeParams.steps;
|
||||
try {
|
||||
currentStep.isExecuting = true;
|
||||
currentStep.executeStatus = ScenarioExecuteStatus.EXECUTING;
|
||||
debugSocket(currentStep, scenario.value, executeParams.reportId, executeType); // 开启websocket
|
||||
debugSocket(currentStep, scenario.value, executeParams.reportId); // 开启websocket
|
||||
const res = await debugScenario({
|
||||
id: scenario.value.id || '',
|
||||
grouped: false,
|
||||
environmentId: currentEnvConfig?.value?.id || '',
|
||||
projectId: appStore.currentProjectId,
|
||||
scenarioConfig: scenario.value.scenarioConfig,
|
||||
frontendDebug: executeType === 'localExec',
|
||||
frontendDebug: scenario.value.executeType === 'localExec',
|
||||
...executeParams,
|
||||
steps: mapTree(executeParams.steps, (node) => {
|
||||
return {
|
||||
|
@ -1420,7 +1409,7 @@
|
|||
};
|
||||
}),
|
||||
});
|
||||
if (executeType === 'localExec' && localExecuteUrl?.value) {
|
||||
if (scenario.value.executeType === 'localExec' && localExecuteUrl?.value) {
|
||||
await localExecuteApiDebug(localExecuteUrl.value, res);
|
||||
}
|
||||
} catch (error) {
|
||||
|
@ -1461,17 +1450,15 @@
|
|||
return step.enable || step.uniqueId === realStep.uniqueId;
|
||||
}
|
||||
);
|
||||
realExecute(
|
||||
{
|
||||
scenario.value.executeType = isPriorityLocalExec?.value ? 'localExec' : 'serverExec';
|
||||
realExecute({
|
||||
steps: [realStep as ScenarioStepItem],
|
||||
stepDetails: _stepDetails,
|
||||
reportId: realStep.reportId,
|
||||
stepFileParam: {
|
||||
[realStep.id]: stepFileParam,
|
||||
},
|
||||
},
|
||||
isPriorityLocalExec?.value ? 'localExec' : 'serverExec'
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1488,8 +1475,8 @@
|
|||
realStep.executeStatus = ScenarioExecuteStatus.EXECUTING;
|
||||
const stepFileParam = scenario.value.stepFileParam[realStep.id];
|
||||
request.executeLoading = true;
|
||||
realExecute(
|
||||
{
|
||||
scenario.value.executeType = executeType;
|
||||
realExecute({
|
||||
steps: [realStep as ScenarioStepItem],
|
||||
stepDetails: {
|
||||
[realStep.id]: request,
|
||||
|
@ -1498,9 +1485,7 @@
|
|||
stepFileParam: {
|
||||
[realStep.uniqueId]: stepFileParam,
|
||||
},
|
||||
},
|
||||
executeType
|
||||
);
|
||||
});
|
||||
} else {
|
||||
// 步骤列表找不到该步骤,说明是新建的自定义请求还未保存,则临时创建一个步骤进行调试(不保存步骤信息)
|
||||
const reportId = getGenerateId();
|
||||
|
@ -1519,8 +1504,7 @@
|
|||
reportId,
|
||||
uniqueId: request.stepId,
|
||||
};
|
||||
realExecute(
|
||||
{
|
||||
realExecute({
|
||||
steps: [activeStep.value],
|
||||
stepDetails: {
|
||||
[request.stepId]: request,
|
||||
|
@ -1532,13 +1516,11 @@
|
|||
linkFileIds: request.linkFileIds || [],
|
||||
},
|
||||
},
|
||||
},
|
||||
executeType
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function handleStopExecute(step?: ScenarioStepItem) {
|
||||
async function handleStopExecute(step?: ScenarioStepItem) {
|
||||
if (step?.reportId) {
|
||||
const realStep = findNodeByKey<ScenarioStepItem>(steps.value, step.uniqueId, 'uniqueId');
|
||||
websocketMap[step.reportId].close();
|
||||
|
@ -1759,12 +1741,26 @@
|
|||
*/
|
||||
function deleteStep(step?: ScenarioStepItem) {
|
||||
if (step) {
|
||||
openModal({
|
||||
type: 'error',
|
||||
title: t('common.tip'),
|
||||
content: t('apiScenario.deleteStepConfirm', { name: step.name }),
|
||||
okText: t('common.confirmDelete'),
|
||||
cancelText: t('common.cancel'),
|
||||
okButtonProps: {
|
||||
status: 'danger',
|
||||
},
|
||||
maskClosable: false,
|
||||
onBeforeOk: async () => {
|
||||
customCaseDrawerVisible.value = false;
|
||||
customApiDrawerVisible.value = false;
|
||||
deleteNode(steps.value, step.uniqueId, 'uniqueId');
|
||||
activeStep.value = undefined;
|
||||
scenario.value.unSaved = true;
|
||||
Message.success(t('common.deleteSuccess'));
|
||||
},
|
||||
hideCancel: false,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -74,7 +74,11 @@ export default function updateStepStatus(
|
|||
// 非逻辑控制器直接更改本身状态
|
||||
if (stepResponses[node.uniqueId] && stepResponses[node.uniqueId].length > 0) {
|
||||
// 存在多个请求结果说明是循环控制器下的步骤,需要判断其子步骤的执行结果
|
||||
if (stepResponses[node.uniqueId].some((report) => !report.isSuccessful)) {
|
||||
if (
|
||||
stepResponses[node.uniqueId].some(
|
||||
(report) => !report.isSuccessful && report.status !== ScenarioExecuteStatus.FAKE_ERROR
|
||||
)
|
||||
) {
|
||||
node.executeStatus = ScenarioExecuteStatus.FAILED;
|
||||
} else if (
|
||||
stepResponses[node.uniqueId].some((report) => report.status === ScenarioExecuteStatus.FAKE_ERROR)
|
||||
|
|
|
@ -118,7 +118,7 @@
|
|||
import executeButton from '@/views/api-test/components/executeButton.vue';
|
||||
import ScenarioTable from '@/views/api-test/scenario/components/scenarioTable.vue';
|
||||
|
||||
import { localExecuteApiDebug } from '@/api/modules/api-test/common';
|
||||
import { localExecuteApiDebug, stopExecute, stopLocalExecute } from '@/api/modules/api-test/common';
|
||||
import {
|
||||
addScenario,
|
||||
debugScenario,
|
||||
|
@ -246,14 +246,14 @@
|
|||
activeScenarioTab.value.stepResponses = {};
|
||||
activeScenarioTab.value.reportId = executeParams.reportId; // 存储报告ID
|
||||
debugSocket(activeScenarioTab.value, executeType, localExecuteUrl); // 开启websocket
|
||||
activeScenarioTab.value.isDebug = !isExecute;
|
||||
let res;
|
||||
if (isExecute && executeType !== 'localExec' && !activeScenarioTab.value.isNew) {
|
||||
// 执行场景且非本地执行且非未保存场景
|
||||
activeScenarioTab.value.isDebug = false;
|
||||
res = await executeScenario({
|
||||
id: activeScenarioTab.value.id,
|
||||
grouped: false,
|
||||
environmentId: currentEnvConfig.value?.id || '',
|
||||
environmentId: activeScenarioTab.value.environmentId || '',
|
||||
projectId: appStore.currentProjectId,
|
||||
scenarioConfig: activeScenarioTab.value.scenarioConfig,
|
||||
...executeParams,
|
||||
|
@ -266,11 +266,10 @@
|
|||
}),
|
||||
});
|
||||
} else {
|
||||
activeScenarioTab.value.isDebug = true;
|
||||
res = await debugScenario({
|
||||
id: activeScenarioTab.value.id,
|
||||
grouped: false,
|
||||
environmentId: currentEnvConfig.value?.id || '',
|
||||
environmentId: activeScenarioTab.value.environmentId || '',
|
||||
projectId: appStore.currentProjectId,
|
||||
scenarioConfig: activeScenarioTab.value.scenarioConfig,
|
||||
stepFileParam: activeScenarioTab.value.stepFileParam,
|
||||
|
@ -329,7 +328,24 @@
|
|||
);
|
||||
}
|
||||
|
||||
function handleStopExecute() {
|
||||
async function handleStopExecute() {
|
||||
if (!activeScenarioTab.value.isDebug) {
|
||||
// 调试模式不需要调停止执行接口
|
||||
try {
|
||||
if (activeScenarioTab.value.executeType === 'localExec') {
|
||||
await stopLocalExecute(
|
||||
executeButtonRef.value?.localExecuteUrl || '',
|
||||
activeScenarioTab.value.reportId,
|
||||
ScenarioStepType.API_SCENARIO
|
||||
);
|
||||
} else {
|
||||
await stopExecute(activeScenarioTab.value.reportId, ScenarioStepType.API_SCENARIO);
|
||||
}
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(error);
|
||||
}
|
||||
}
|
||||
websocketMap[activeScenarioTab.value.reportId]?.close();
|
||||
activeScenarioTab.value.executeLoading = false;
|
||||
setStepExecuteStatus(activeScenarioTab.value);
|
||||
|
@ -479,7 +495,7 @@
|
|||
};
|
||||
}),
|
||||
projectId: appStore.currentProjectId,
|
||||
environmentId: currentEnvConfig.value?.id || '',
|
||||
environmentId: activeScenarioTab.value.environmentId || '',
|
||||
});
|
||||
const scenarioDetail = await getScenarioDetail(res.id);
|
||||
scenarioDetail.stepDetails = {};
|
||||
|
@ -519,7 +535,7 @@
|
|||
} else {
|
||||
await updateScenario({
|
||||
...activeScenarioTab.value,
|
||||
environmentId: currentEnvConfig.value?.id || '',
|
||||
environmentId: activeScenarioTab.value.environmentId || '',
|
||||
steps: mapTree(activeScenarioTab.value.steps, (node) => {
|
||||
return {
|
||||
...node,
|
||||
|
@ -554,7 +570,7 @@
|
|||
if (isLoadedTabIndex > -1 && action !== 'copy') {
|
||||
// 如果点击的请求在tab中已经存在,则直接切换到该tab
|
||||
activeScenarioTab.value = scenarioTabs.value[isLoadedTabIndex];
|
||||
// requestCompositionRef里监听的是id,所以id相等的时候需要单独调执行
|
||||
// tab子组件里监听的是id变化,所以id相等的时候需要单独调执行
|
||||
if (action === 'execute') {
|
||||
handleExecute(executeButtonRef.value?.isPriorityLocalExec ? 'localExec' : 'serverExec');
|
||||
}
|
||||
|
|
|
@ -170,21 +170,17 @@ export default {
|
|||
'apiScenario.sourceScenarioParams': 'Source Scenario Parameters',
|
||||
'apiScenario.sourceScenarioEnv': 'Use source Scenario Environment',
|
||||
'apiScenario.valuePriority': 'Value Priority:',
|
||||
'apiScenario.currentScenarioAndNull':
|
||||
'Current Step Parameters > Current Scenario Parameters > Current Environment Parameters > Empty Value',
|
||||
'apiScenario.currentScenarioAndNullAndSourceEnv':
|
||||
'Current Step Parameters > Current Scenario Parameters > Source Environment Parameters > Empty Value',
|
||||
'apiScenario.currentScenarioAndSourceScenario':
|
||||
'Current Step Parameters > Current Scenario Parameters > Current Environment Parameters > Source Scenario Parameters',
|
||||
'apiScenario.currentScenarioAndSourceScenarioAndSourceEnv':
|
||||
'Current Step Parameters > Current Scenario Parameters > Source Scenario Parameters > Source Environment Parameters',
|
||||
'apiScenario.sourceScenarioAndNull': 'Source Scenario Parameters > Empty Value',
|
||||
'apiScenario.sourceScenarioAndNullAndSourceEnv':
|
||||
'Source Scenario Parameters > Source Environment Parameters > Empty Value',
|
||||
'apiScenario.sourceScenarioAndCurrentScenario':
|
||||
'Source Scenario Parameters > Current Step Parameters > Current Scenario Parameters > Current Environment Parameters',
|
||||
'apiScenario.sourceScenarioAndCurrentScenarioAndSourceEnv':
|
||||
'Source Scenario Parameters > Source Environment Parameters > Current Step Parameters > Current Scenario Parameters',
|
||||
'apiScenario.notSource': 'Current Step Parameters > Current Scenario Parameters > Current Environment Parameters',
|
||||
'apiScenario.notSourceParamAndSourceEnv':
|
||||
'Current Step Parameters > Current Scenario Parameters > Original Environment Parameters',
|
||||
'apiScenario.currentParamAndSource':
|
||||
'Current Step Parameters > Current Scenario Parameters > Current Environment Parameters > Original Scenario Parameters',
|
||||
'apiScenario.currentParamAndSourceEnv':
|
||||
'Current Step Parameters > Current Scenario Parameters > Original Scenario Parameters > Original Environment Parameters',
|
||||
'apiScenario.sourceParamAndSource':
|
||||
'Original Scenario Parameters > Current Step Parameters > Current Scenario Parameters > Current Environment Parameters',
|
||||
'apiScenario.sourceParamAndSourceEnv':
|
||||
'Original Scenario Parameters > Original Environment Parameters > Current Step Parameters > Current Scenario Parameters',
|
||||
'apiScenario.fullQuoteTip':
|
||||
'Full Quote: Follows the original step content and step status changes. Step status cannot be adjusted.',
|
||||
'apiScenario.stepQuoteTip':
|
||||
|
@ -193,6 +189,9 @@ export default {
|
|||
'apiScenario.setSuccess': 'Set Successful',
|
||||
'apiScenario.pleaseInputUrl': 'Please enter URL',
|
||||
'apiScenario.syncSaveAsCase': 'Synchronously add test interface case',
|
||||
'apiScenario.deleteStepConfirm': 'Are you sure you want to delete {name}?',
|
||||
'apiScenario.deleteStepConfirmWithChildren':
|
||||
'Are you sure you want to delete the selected step and all substeps within the step?',
|
||||
// Execution History
|
||||
'apiScenario.executeHistory.searchPlaceholder': 'Search by ID or name',
|
||||
'apiScenario.executeHistory.num': 'No.',
|
||||
|
|
|
@ -169,20 +169,20 @@ export default {
|
|||
'apiScenario.sourceScenarioParams': '使用原场景参数',
|
||||
'apiScenario.sourceScenarioEnv': '使用原场景环境',
|
||||
'apiScenario.valuePriority': '取值优先级:',
|
||||
'apiScenario.currentScenarioAndNull': '当前步骤参数 > 当前场景参数 > 当前环境参数 > 空值',
|
||||
'apiScenario.currentScenarioAndNullAndSourceEnv': '当前步骤参数 > 当前场景参数 > 原环境参数 > 空值',
|
||||
'apiScenario.currentScenarioAndSourceScenario': '当前步骤参数 > 当前场景参数 > 当前环境参数 > 原场景参数',
|
||||
'apiScenario.currentScenarioAndSourceScenarioAndSourceEnv': '当前步骤参数 > 当前场景参数 > 原场景参数> 原环境参数',
|
||||
'apiScenario.sourceScenarioAndNull': '原场景参数 > 空值',
|
||||
'apiScenario.sourceScenarioAndNullAndSourceEnv': '原场景参数 > 原环境参数 > 空值',
|
||||
'apiScenario.sourceScenarioAndCurrentScenario': '原场景参数 > 当前步骤参数 > 当前场景参数 > 当前环境参数',
|
||||
'apiScenario.sourceScenarioAndCurrentScenarioAndSourceEnv': '原场景参数 > 原环境参数 > 当前步骤参数 > 当前场景参数',
|
||||
'apiScenario.notSource': '当前步骤参数 > 当前场景参数 > 当前环境参数',
|
||||
'apiScenario.notSourceParamAndSourceEnv': '当前步骤参数 > 当前场景参数 > 原环境参数',
|
||||
'apiScenario.currentParamAndSource': '当前步骤参数 > 当前场景参数 > 当前环境参数 > 原场景参数',
|
||||
'apiScenario.currentParamAndSourceEnv': '当前步骤参数 > 当前场景参数 > 原场景参数 > 原环境参数',
|
||||
'apiScenario.sourceParamAndSource': '原场景参数 > 当前步骤参数 > 当前场景参数 > 当前环境参数',
|
||||
'apiScenario.sourceParamAndSourceEnv': '原场景参数 > 原环境参数 > 当前步骤参数 > 当前场景参数',
|
||||
'apiScenario.fullQuoteTip': '完全引用:跟随原步骤内容及步骤状态变化,步骤状态不可调整',
|
||||
'apiScenario.stepQuoteTip': '步骤引用:仅跟随原步骤内容变化,步骤状态可调整',
|
||||
'apiScenario.sourceScenarioEnvTip': '使用原场景运行环境,包含环境参数',
|
||||
'apiScenario.setSuccess': '设置成功',
|
||||
'apiScenario.pleaseInputUrl': '请输入 url',
|
||||
'apiScenario.syncSaveAsCase': '同步添加测试接口用例',
|
||||
'apiScenario.deleteStepConfirm': '确认删除 {name} 吗?',
|
||||
'apiScenario.deleteStepConfirmWithChildren': '确认删除所选步骤以及步骤内所有子步骤?',
|
||||
// 执行历史
|
||||
'apiScenario.executeHistory.searchPlaceholder': '通过ID或名称搜索',
|
||||
'apiScenario.executeHistory.num': '序号',
|
||||
|
|
|
@ -5,14 +5,16 @@
|
|||
<img :src="innerLogo" class="h-[60px] w-[290px]" />
|
||||
</div>
|
||||
<div class="title-0 mt-[16px] flex justify-center">
|
||||
<span class="title-welcome">{{ t(innerSlogan || '') || t('login.form.title') }}</span>
|
||||
<span class="title-welcome one-line-text max-w-[300px]">
|
||||
{{ t(innerSlogan || '') || t('login.form.title') }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form mt-[32px] min-w-[416px]">
|
||||
<div v-if="userInfo.authenticate === 'LOCAL'" class="mb-7 text-[18px] font-medium text-[rgb(var(--primary-5))]">{{
|
||||
t('login.form.accountLogin')
|
||||
}}</div>
|
||||
<div v-if="userInfo.authenticate === 'LOCAL'" class="mb-7 text-[18px] font-medium text-[rgb(var(--primary-5))]">
|
||||
{{ t('login.form.accountLogin') }}
|
||||
</div>
|
||||
<div
|
||||
v-if="isShowLDAP && userInfo.authenticate !== 'LOCAL'"
|
||||
class="mb-7 text-[18px] font-medium text-[rgb(var(--primary-5))]"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<template>
|
||||
<div class="relative">
|
||||
<!-- 风格、主题色配置 -->
|
||||
<MsCard class="mb-[16px]" :loading="pageloading" simple auto-height>
|
||||
<MsCard class="mb-[16px]" :loading="pageLoading" simple auto-height>
|
||||
<div class="config-title">
|
||||
{{ t('system.config.page.theme') }}
|
||||
<a-tooltip :content="t('system.config.page.themeTip')" position="tl" class="themeTip">
|
||||
|
@ -32,7 +32,7 @@
|
|||
</div>
|
||||
</MsCard>
|
||||
<!-- 登录页配置 -->
|
||||
<MsCard class="mb-[16px]" :loading="pageloading" simple auto-height>
|
||||
<MsCard class="mb-[16px]" :loading="pageLoading" simple auto-height>
|
||||
<div class="config-title">
|
||||
{{ t('system.config.page.loginPageConfig') }}
|
||||
</div>
|
||||
|
@ -194,6 +194,7 @@
|
|||
v-model:model-value="pageConfig.slogan"
|
||||
:placeholder="t('system.config.page.sloganPlaceholder')"
|
||||
:max-length="255"
|
||||
:disabled="!hasAnyPermission(['SYSTEM_PARAMETER_SETTING_DISPLAY:READ+UPDATE'])"
|
||||
></a-input>
|
||||
<MsFormItemSub :text="t('system.config.page.sloganTip')" :show-fill-icon="false" />
|
||||
</a-form-item>
|
||||
|
@ -202,6 +203,7 @@
|
|||
v-model:model-value="pageConfig.title"
|
||||
:placeholder="t('system.config.page.titlePlaceholder')"
|
||||
:max-length="255"
|
||||
:disabled="!hasAnyPermission(['SYSTEM_PARAMETER_SETTING_DISPLAY:READ+UPDATE'])"
|
||||
></a-input>
|
||||
<MsFormItemSub :text="t('system.config.page.titleTip')" :show-fill-icon="false" />
|
||||
</a-form-item>
|
||||
|
@ -212,7 +214,7 @@
|
|||
</div>
|
||||
</MsCard>
|
||||
<!-- 平台主页面配置 -->
|
||||
<MsCard class="mb-[96px]" :loading="pageloading" simple auto-height>
|
||||
<MsCard class="mb-[96px]" :loading="pageLoading" simple auto-height>
|
||||
<div class="config-title">
|
||||
{{ t('system.config.page.platformConfig') }}
|
||||
</div>
|
||||
|
@ -273,8 +275,8 @@
|
|||
<MsUpload
|
||||
v-model:file-list="pageConfig.logoPlatform"
|
||||
accept="image"
|
||||
:max-size="1"
|
||||
size-unit="MB"
|
||||
:max-size="200"
|
||||
size-unit="KB"
|
||||
:auto-upload="false"
|
||||
>
|
||||
<a-button
|
||||
|
@ -308,6 +310,7 @@
|
|||
v-model:model-value="pageConfig.platformName"
|
||||
:placeholder="t('system.config.page.platformNamePlaceholder')"
|
||||
:max-length="255"
|
||||
:disabled="!hasAnyPermission(['SYSTEM_PARAMETER_SETTING_DISPLAY:READ+UPDATE'])"
|
||||
></a-input>
|
||||
<MsFormItemSub :text="t('system.config.page.platformNameTip')" :show-fill-icon="false" />
|
||||
</a-form-item>
|
||||
|
@ -316,6 +319,7 @@
|
|||
v-model:model-value="pageConfig.helpDoc"
|
||||
:placeholder="t('system.config.page.helpDocPlaceholder')"
|
||||
:max-length="255"
|
||||
:disabled="!hasAnyPermission(['SYSTEM_PARAMETER_SETTING_DISPLAY:READ+UPDATE'])"
|
||||
></a-input>
|
||||
<MsFormItemSub :text="t('system.config.page.helpDocTip')" :show-fill-icon="false" />
|
||||
</a-form-item>
|
||||
|
@ -329,9 +333,9 @@
|
|||
class="fixed bottom-0 right-[16px] z-[999] flex justify-between bg-white p-[24px] shadow-[0_-1px_4px_rgba(2,2,2,0.1)]"
|
||||
:style="{ width: `calc(100% - ${menuWidth + 16}px)` }"
|
||||
>
|
||||
<a-button v-permission="['SYSTEM_PARAMETER_SETTING_DISPLAY:READ+UPDATE']" type="secondary" @click="resetAll">{{
|
||||
t('system.config.page.resetAll')
|
||||
}}</a-button>
|
||||
<a-button v-permission="['SYSTEM_PARAMETER_SETTING_DISPLAY:READ+UPDATE']" type="secondary" @click="resetAll">
|
||||
{{ t('system.config.page.resetAll') }}
|
||||
</a-button>
|
||||
<a-button v-permission="['SYSTEM_PARAMETER_SETTING_DISPLAY:READ+UPDATE']" type="primary" @click="beforeSave">
|
||||
{{ t('system.config.page.save') }}
|
||||
</a-button>
|
||||
|
@ -359,6 +363,7 @@
|
|||
import useAppStore from '@/store/modules/app';
|
||||
import { sleep } from '@/utils';
|
||||
import { scrollIntoView } from '@/utils/dom';
|
||||
import { hasAnyPermission } from '@/utils/permission';
|
||||
import { setCustomTheme, setPlatformColor, watchStyle, watchTheme } from '@/utils/theme';
|
||||
|
||||
import type { FormInstance, ValidatedError } from '@arco-design/web-vue';
|
||||
|
@ -373,7 +378,7 @@
|
|||
const menuWidth = computed(() => {
|
||||
return appStore.menuCollapse ? collapsedWidth : appStore.menuWidth;
|
||||
});
|
||||
const pageloading = ref(false);
|
||||
const pageLoading = ref(false);
|
||||
const pageConfig = ref({ ...appStore.pageConfig });
|
||||
const loginPageFullRef = ref<HTMLElement | null>(null);
|
||||
const platformPageFullRef = ref<HTMLElement | null>(null);
|
||||
|
@ -554,40 +559,42 @@
|
|||
*/
|
||||
async function save() {
|
||||
try {
|
||||
pageloading.value = true;
|
||||
pageLoading.value = true;
|
||||
await savePageConfig(makeParams());
|
||||
Message.success(t('system.config.page.saveSuccess'));
|
||||
await sleep(300);
|
||||
window.location.reload();
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(error);
|
||||
} finally {
|
||||
pageloading.value = false;
|
||||
pageLoading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存前校验
|
||||
*/
|
||||
function beforeSave() {
|
||||
async function beforeSave() {
|
||||
try {
|
||||
loginConfigFormRef.value?.validate((errors: Record<string, ValidatedError> | undefined) => {
|
||||
await loginConfigFormRef.value?.validate((errors: Record<string, ValidatedError> | undefined) => {
|
||||
if (errors) {
|
||||
throw new Error('登录页表单校验不通过');
|
||||
}
|
||||
});
|
||||
platformConfigFormRef.value?.validate((errors: Record<string, ValidatedError> | undefined) => {
|
||||
await platformConfigFormRef.value?.validate((errors: Record<string, ValidatedError> | undefined) => {
|
||||
if (errors) {
|
||||
throw new Error('平台页表单校验不通过');
|
||||
}
|
||||
});
|
||||
save();
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(error);
|
||||
}
|
||||
const errDom = document.querySelector('.arco-form-item-message');
|
||||
scrollIntoView(errDom, { block: 'center' });
|
||||
}
|
||||
}
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
if (isSave.value === false) {
|
||||
|
|
|
@ -85,7 +85,7 @@ export default {
|
|||
'system.config.page.platformNamePlaceholder': 'Please enter a platform name',
|
||||
'system.config.page.platformNameRequired': 'Platform name cannot be empty',
|
||||
'system.config.page.platformNameTip':
|
||||
'The general product name of the whole site, the recommended number of words is 8',
|
||||
'The general product name of the whole site, the recommended number of words is 7',
|
||||
'system.config.page.helpDoc': 'Help document',
|
||||
'system.config.page.helpDocPlaceholder': 'Please enter the address of the help document',
|
||||
'system.config.page.helpDocTip': 'Help document jump link can be set, the default is official help document',
|
||||
|
|
|
@ -60,7 +60,7 @@ export default {
|
|||
'system.config.page.replace': '替换图片',
|
||||
'system.config.page.iconTip':
|
||||
'顶部网站显示的 icon;建议使用 SVG 或 PNG 格式透明背景图片,宽高 18px;图片大小仅支持 200 KB 以内',
|
||||
'system.config.page.loginLogo': '登录 logo',
|
||||
'system.config.page.loginLogo': '登录 Logo',
|
||||
'system.config.page.loginLogoTip':
|
||||
'登录页面右侧 logo;建议使用 SVG 或 PNG 格式透明背景图片,高度不小于 48px;图片大小仅支持 200 KB 以内',
|
||||
'system.config.page.loginBg': '登录背景图',
|
||||
|
@ -69,7 +69,7 @@ export default {
|
|||
'system.config.page.slogan': 'Slogan',
|
||||
'system.config.page.sloganPlaceholder': '请输入 Slogan',
|
||||
'system.config.page.sloganRequired': 'Slogan不能为空',
|
||||
'system.config.page.sloganTip': '产品logo下的 slogan',
|
||||
'system.config.page.sloganTip': '产品Logo下的 slogan',
|
||||
'system.config.page.title': '网站名称',
|
||||
'system.config.page.titlePlaceholder': '请输入网站名称',
|
||||
'system.config.page.titleTip': '显示在网页tab的平台名称',
|
||||
|
@ -77,11 +77,11 @@ export default {
|
|||
'system.config.page.platformConfig': '平台设置',
|
||||
'system.config.page.platformLogo': '平台 Logo',
|
||||
'system.config.page.platformLogoTip':
|
||||
'平台页面顶部显示的 logo;建议使用 SVG 或 PNG 格式透明背景图片,高度不小于 32px;图片大小仅支持 200 KB 以内',
|
||||
'平台页面顶部显示的 Logo;建议使用 SVG 或 PNG 格式透明背景图片,高度不小于 32px;图片大小仅支持 200 KB 以内',
|
||||
'system.config.page.platformName': '平台名称',
|
||||
'system.config.page.platformNamePlaceholder': '请输入平台名称',
|
||||
'system.config.page.platformNameRequired': '平台名称不能为空',
|
||||
'system.config.page.platformNameTip': '全站通用产品名称,建议字数 8',
|
||||
'system.config.page.platformNameTip': '全站通用产品名称,建议字数 7',
|
||||
'system.config.page.helpDoc': '帮助文档',
|
||||
'system.config.page.helpDocPlaceholder': '请输入帮助文档地址',
|
||||
'system.config.page.helpDocTip': '可设置帮助文档跳转链接,默认为官方帮助文档',
|
||||
|
|
Loading…
Reference in New Issue