refactor(项目管理): 环境管理表格换为paramsTable
This commit is contained in:
parent
057b286c19
commit
5520e314fd
|
@ -43,7 +43,7 @@ export class MSAxios {
|
||||||
|
|
||||||
const axiosCanceler = new AxiosCanceler();
|
const axiosCanceler = new AxiosCanceler();
|
||||||
|
|
||||||
// 请求拦截器
|
// TODO: 拦截配置升级了 请求拦截器
|
||||||
this.axiosInstance.interceptors.request.use((config: CreateAxiosOptions) => {
|
this.axiosInstance.interceptors.request.use((config: CreateAxiosOptions) => {
|
||||||
// 如果ignoreCancelToken为true,则不添加到pending中
|
// 如果ignoreCancelToken为true,则不添加到pending中
|
||||||
const ignoreCancelToken = config.requestOptions?.ignoreCancelToken;
|
const ignoreCancelToken = config.requestOptions?.ignoreCancelToken;
|
||||||
|
@ -56,7 +56,8 @@ export class MSAxios {
|
||||||
if (requestInterceptors && isFunction(requestInterceptors)) {
|
if (requestInterceptors && isFunction(requestInterceptors)) {
|
||||||
config = requestInterceptors(config, this.options);
|
config = requestInterceptors(config, this.options);
|
||||||
}
|
}
|
||||||
return config as InternalAxiosRequestConfig; // TODO: 拦截配置升级了,暂时 as 处理
|
// TODO: 拦截配置升级了,暂时 as 处理
|
||||||
|
return config as InternalAxiosRequestConfig;
|
||||||
}, undefined);
|
}, undefined);
|
||||||
|
|
||||||
// 响应拦截器
|
// 响应拦截器
|
||||||
|
|
|
@ -0,0 +1,89 @@
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<paramsTable
|
||||||
|
v-model:params="innerParams"
|
||||||
|
:selectable="false"
|
||||||
|
:columns="columns"
|
||||||
|
:scroll="{ minWidth: '700px' }"
|
||||||
|
:default-param-item="defaultParamItem"
|
||||||
|
@change="handleParamTableChange"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { statusCodeOptions } from '@/components/pure/ms-advance-filter/index';
|
||||||
|
import paramsTable, { type ParamTableColumn } from '@/views/api-test/components/paramTable.vue';
|
||||||
|
|
||||||
|
interface Param {
|
||||||
|
[key: string]: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
const innerParams = defineModel<Param[]>('modelValue', { default: [] });
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: 'change'): void; // 数据发生变化
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const defaultParamItem = {
|
||||||
|
responseHeader: '',
|
||||||
|
matchCondition: '',
|
||||||
|
matchValue: '',
|
||||||
|
enable: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
const responseHeaderOption = [
|
||||||
|
{ label: 'Accept', value: 'accept' },
|
||||||
|
{ label: 'Accept-Encoding', value: 'acceptEncoding' },
|
||||||
|
{ label: 'Accept-Language', value: 'acceptLanguage' },
|
||||||
|
{ label: 'Cache-Control', value: 'cacheControl' },
|
||||||
|
{ label: 'Content-Type', value: 'contentType' },
|
||||||
|
{ label: 'Content-Length', value: 'contentLength' },
|
||||||
|
{ label: 'User-Agent', value: 'userAgent' },
|
||||||
|
{ label: 'Referer', value: 'referer' },
|
||||||
|
{ label: 'Cookie', value: 'cookie' },
|
||||||
|
{ label: 'Authorization', value: 'authorization' },
|
||||||
|
{ label: 'If-None-Match', value: 'ifNoneMatch' },
|
||||||
|
{ label: 'If-Modified-Since', value: 'ifModifiedSince' },
|
||||||
|
];
|
||||||
|
|
||||||
|
const columns: ParamTableColumn[] = [
|
||||||
|
{
|
||||||
|
title: 'ms.assertion.responseHeader', // 响应头
|
||||||
|
dataIndex: 'responseHeader',
|
||||||
|
slotName: 'responseHeader',
|
||||||
|
showInTable: true,
|
||||||
|
showDrag: true,
|
||||||
|
options: responseHeaderOption,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'ms.assertion.matchCondition', // 匹配条件
|
||||||
|
dataIndex: 'matchCondition',
|
||||||
|
slotName: 'matchCondition',
|
||||||
|
showInTable: true,
|
||||||
|
showDrag: true,
|
||||||
|
options: statusCodeOptions,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'ms.assertion.matchValue', // 匹配值
|
||||||
|
dataIndex: 'matchValue',
|
||||||
|
slotName: 'matchValue',
|
||||||
|
showInTable: true,
|
||||||
|
showDrag: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '',
|
||||||
|
columnTitle: 'common.operation',
|
||||||
|
slotName: 'operation',
|
||||||
|
width: 50,
|
||||||
|
showInTable: true,
|
||||||
|
showDrag: true,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
function handleParamTableChange(resultArr: any[], isInit?: boolean) {
|
||||||
|
innerParams.value = [...resultArr];
|
||||||
|
if (!isInit) {
|
||||||
|
emit('change');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
|
@ -0,0 +1,29 @@
|
||||||
|
<template>
|
||||||
|
<div class="flex h-[62px] flex-row items-end gap-[8px] text-[var(--color-text-1)]">
|
||||||
|
<div>
|
||||||
|
<div class="mb-[8px]">{{ t('ms.assertion.statusCode') }}</div>
|
||||||
|
<a-select v-model="selectValue" class="w-[157px]">
|
||||||
|
<a-option v-for="item in statusCodeOptions" :key="item.value" :value="item.value">
|
||||||
|
{{ t(item.label) }}
|
||||||
|
</a-option>
|
||||||
|
</a-select>
|
||||||
|
</div>
|
||||||
|
<a-input-number v-if="showInput" v-model:modelValue="statusCode" hide-button class="w-[157px]" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { computed } from 'vue';
|
||||||
|
|
||||||
|
import { statusCodeOptions } from '@/components/pure/ms-advance-filter/index';
|
||||||
|
|
||||||
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
|
|
||||||
|
const selectValue = defineModel<string>('selectValue');
|
||||||
|
const statusCode = defineModel<number>('statusCode');
|
||||||
|
const showInput = computed(() => selectValue.value !== 'none' && selectValue.value !== '');
|
||||||
|
|
||||||
|
const { t } = useI18n();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped></style>
|
|
@ -11,7 +11,7 @@
|
||||||
<a-doption v-for="item in assertOption" :key="item.value" :value="item.value">{{ item.label }}</a-doption>
|
<a-doption v-for="item in assertOption" :key="item.value" :value="item.value">{{ item.label }}</a-doption>
|
||||||
</template>
|
</template>
|
||||||
</a-dropdown>
|
</a-dropdown>
|
||||||
<div class="ms-assertion-body">
|
<div v-if="showBody" class="ms-assertion-body">
|
||||||
<article class="ms-assertion-body-left">
|
<article class="ms-assertion-body-left">
|
||||||
<div
|
<div
|
||||||
v-for="(item, index) in activeOption"
|
v-for="(item, index) in activeOption"
|
||||||
|
@ -28,12 +28,22 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</article>
|
</article>
|
||||||
<section class="ms-assertion-body-right"> </section>
|
<section class="ms-assertion-body-right">
|
||||||
|
<MsAssertionStatusCodeTab
|
||||||
|
v-if="activeKey === 'statusCode'"
|
||||||
|
v-model:selectValue="codeTabState.selectValue"
|
||||||
|
v-model:statusCode="codeTabState.statusCode"
|
||||||
|
/>
|
||||||
|
<ResponseHeaderTab v-if="activeKey === 'responseHeader'" />
|
||||||
|
</section>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
import ResponseHeaderTab from './comp/ResponseHeaderTab.vue';
|
||||||
|
import MsAssertionStatusCodeTab from './comp/StatusCodeTab.vue';
|
||||||
|
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
|
@ -42,6 +52,11 @@
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
|
const codeTabState = reactive({
|
||||||
|
selectValue: '',
|
||||||
|
statusCode: 200,
|
||||||
|
});
|
||||||
|
// 源选项
|
||||||
const assertOptionSource = [
|
const assertOptionSource = [
|
||||||
{
|
{
|
||||||
label: t('ms.assertion.statusCode'),
|
label: t('ms.assertion.statusCode'),
|
||||||
|
@ -68,23 +83,28 @@
|
||||||
value: 'script',
|
value: 'script',
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
// 选中的选项
|
||||||
const selectIds = ref<string[]>([]);
|
const selectIds = ref<string[]>([]);
|
||||||
|
// Item点击的key
|
||||||
const activeKey = ref<string>('');
|
const activeKey = ref<string>('');
|
||||||
|
|
||||||
|
// 未选中的选项
|
||||||
const assertOption = computed(() => {
|
const assertOption = computed(() => {
|
||||||
return assertOptionSource.filter((item) => !selectIds.value.includes(item.value));
|
return assertOptionSource.filter((item) => !selectIds.value.includes(item.value));
|
||||||
});
|
});
|
||||||
|
// 选中的选项
|
||||||
const activeOption = computed(() => {
|
const activeOption = computed(() => {
|
||||||
return assertOptionSource.filter((item) => selectIds.value.includes(item.value));
|
return assertOptionSource.filter((item) => selectIds.value.includes(item.value));
|
||||||
});
|
});
|
||||||
|
// 是否显示主体
|
||||||
|
const showBody = computed(() => {
|
||||||
|
return selectIds.value.length > 0;
|
||||||
|
});
|
||||||
|
// dropdown选择
|
||||||
const handleSelect = (value: string | number | Record<string, any> | undefined) => {
|
const handleSelect = (value: string | number | Record<string, any> | undefined) => {
|
||||||
selectIds.value.push(value as string);
|
selectIds.value.push(value as string);
|
||||||
};
|
};
|
||||||
|
// item点击
|
||||||
const handleItemClick = (item: { label: string; value: string }) => {
|
const handleItemClick = (item: { label: string; value: string }) => {
|
||||||
activeKey.value = item.value;
|
activeKey.value = item.value;
|
||||||
};
|
};
|
||||||
|
@ -102,6 +122,7 @@
|
||||||
display: flex;
|
display: flex;
|
||||||
padding: 12px;
|
padding: 12px;
|
||||||
width: 216px;
|
width: 216px;
|
||||||
|
min-width: 216px;
|
||||||
height: calc(100vh - 394px);
|
height: calc(100vh - 394px);
|
||||||
background-color: var(--color-text-n9);
|
background-color: var(--color-text-n9);
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
@ -143,6 +164,7 @@
|
||||||
&-right {
|
&-right {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
|
padding: 16px;
|
||||||
border: 1px solid var(--color-text-n8);
|
border: 1px solid var(--color-text-n8);
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
background: var(--color-text-fff);
|
background: var(--color-text-fff);
|
||||||
|
|
|
@ -6,4 +6,7 @@ export default {
|
||||||
'ms.assertion.responseTime': '响应时间',
|
'ms.assertion.responseTime': '响应时间',
|
||||||
'ms.assertion.param': '变量',
|
'ms.assertion.param': '变量',
|
||||||
'ms.assertion.script': '脚本',
|
'ms.assertion.script': '脚本',
|
||||||
|
'ms.assertion.noValidation': '不校验',
|
||||||
|
'ms.assertion.matchCondition': '匹配条件',
|
||||||
|
'ms.assertion.matchValue': '匹配值',
|
||||||
};
|
};
|
||||||
|
|
|
@ -22,6 +22,18 @@ export const OPERATOR_MAP = {
|
||||||
|
|
||||||
export const timeSelectOptions = [GE, LE];
|
export const timeSelectOptions = [GE, LE];
|
||||||
|
|
||||||
|
export const statusCodeOptions = [
|
||||||
|
{ label: 'ms.assertion.noValidation', value: 'none' },
|
||||||
|
IN,
|
||||||
|
NOT_IN,
|
||||||
|
EQUAL,
|
||||||
|
NOT_EQUAL,
|
||||||
|
GT,
|
||||||
|
GE,
|
||||||
|
LT,
|
||||||
|
LE,
|
||||||
|
];
|
||||||
|
|
||||||
export const CustomTypeMaps: Record<string, any> = {
|
export const CustomTypeMaps: Record<string, any> = {
|
||||||
INPUT: {
|
INPUT: {
|
||||||
type: 'INPUT',
|
type: 'INPUT',
|
||||||
|
|
|
@ -182,6 +182,19 @@
|
||||||
@click="deleteParam(rowIndex)"
|
@click="deleteParam(rowIndex)"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
<template #responseHeader="{ record, columnConfig }">
|
||||||
|
<a-select v-model="record.responseHeader" @change="(val) => addTableLine(val as string)">
|
||||||
|
<a-option v-for="item in columnConfig.options" :key="item.value">{{ t(item.label) }}</a-option>
|
||||||
|
</a-select>
|
||||||
|
</template>
|
||||||
|
<template #matchCondition="{ record, columnConfig }">
|
||||||
|
<a-select v-model="record.condition" @change="(val) => addTableLine(val as string)">
|
||||||
|
<a-option v-for="item in columnConfig.options" :key="item.value">{{ t(item.label) }}</a-option>
|
||||||
|
</a-select>
|
||||||
|
</template>
|
||||||
|
<template #matchValue="{ record }">
|
||||||
|
<a-input-number v-model="record.matchValue" hide-button @change="(val) => addTableLine(val)" />
|
||||||
|
</template>
|
||||||
</MsBaseTable>
|
</MsBaseTable>
|
||||||
<a-modal
|
<a-modal
|
||||||
v-model:visible="showQuickInputParam"
|
v-model:visible="showQuickInputParam"
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
<a-textarea v-model="form.description" auto-size class="w-[732px]" :placeholder="t('common.pleaseInput')" />
|
<a-textarea v-model="form.description" auto-size class="w-[732px]" :placeholder="t('common.pleaseInput')" />
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-form>
|
</a-form>
|
||||||
<AllParamsTable
|
<paramsTable
|
||||||
v-model:params="innerParams"
|
v-model:params="innerParams"
|
||||||
:show-setting="false"
|
:show-setting="false"
|
||||||
:columns="columns"
|
:columns="columns"
|
||||||
|
@ -48,8 +48,7 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import type { MsTableColumn } from '@/components/pure/ms-table/type';
|
import paramsTable, { type ParamTableColumn } from '@/views/api-test/components/paramTable.vue';
|
||||||
import AllParamsTable from './allParams/AllParamsTable.vue';
|
|
||||||
|
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
import useProjectEnvStore from '@/store/modules/setting/useProjectEnvStore';
|
import useProjectEnvStore from '@/store/modules/setting/useProjectEnvStore';
|
||||||
|
@ -60,7 +59,7 @@
|
||||||
description: '',
|
description: '',
|
||||||
});
|
});
|
||||||
const store = useProjectEnvStore();
|
const store = useProjectEnvStore();
|
||||||
const columns: MsTableColumn = [
|
const columns: ParamTableColumn[] = [
|
||||||
{
|
{
|
||||||
title: 'project.environmental.project',
|
title: 'project.environmental.project',
|
||||||
dataIndex: 'project',
|
dataIndex: 'project',
|
||||||
|
|
Loading…
Reference in New Issue